1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <crtdbg.h>
8
9 #include <algorithm>
10 #include <memory>
11 #include <vector>
12
13 #include "core/fxcrt/fx_codepage.h"
14 #include "core/fxcrt/fx_memory.h"
15 #include "core/fxcrt/fx_system.h"
16 #include "core/fxcrt/maybe_owned.h"
17 #include "core/fxge/cfx_folderfontinfo.h"
18 #include "core/fxge/cfx_fontmgr.h"
19 #include "core/fxge/cfx_gemodule.h"
20 #include "core/fxge/cfx_windowsrenderdevice.h"
21 #include "core/fxge/dib/cfx_dibextractor.h"
22 #include "core/fxge/dib/cfx_imagerenderer.h"
23 #include "core/fxge/dib/cstretchengine.h"
24 #include "core/fxge/fx_font.h"
25 #include "core/fxge/fx_freetype.h"
26 #include "core/fxge/ifx_systemfontinfo.h"
27 #include "core/fxge/win32/cfx_windowsdib.h"
28 #include "core/fxge/win32/dwrite_int.h"
29 #include "core/fxge/win32/win32_int.h"
30 #include "third_party/base/ptr_util.h"
31 #include "third_party/base/stl_util.h"
32
33 #ifndef _SKIA_SUPPORT_
34 #include "core/fxge/agg/fx_agg_driver.h"
35 #endif
36
37 namespace {
38
39 const struct {
40 const char* m_pFaceName;
41 const char* m_pVariantName;
42 } g_VariantNames[] = {
43 {"DFKai-SB", "\x19\x6A\x77\x69\xD4\x9A"},
44 };
45
46 const struct {
47 const char* m_pName;
48 const char* m_pWinName;
49 bool m_bBold;
50 bool m_bItalic;
51 } g_Base14Substs[] = {
52 {"Courier", "Courier New", false, false},
53 {"Courier-Bold", "Courier New", true, false},
54 {"Courier-BoldOblique", "Courier New", true, true},
55 {"Courier-Oblique", "Courier New", false, true},
56 {"Helvetica", "Arial", false, false},
57 {"Helvetica-Bold", "Arial", true, false},
58 {"Helvetica-BoldOblique", "Arial", true, true},
59 {"Helvetica-Oblique", "Arial", false, true},
60 {"Times-Roman", "Times New Roman", false, false},
61 {"Times-Bold", "Times New Roman", true, false},
62 {"Times-BoldItalic", "Times New Roman", true, true},
63 {"Times-Italic", "Times New Roman", false, true},
64 };
65
66 struct FontNameMap {
67 const char* m_pSubFontName;
68 const char* m_pSrcFontName;
69 };
70 const FontNameMap g_JpFontNameMap[] = {
71 {"MS Mincho", "Heiseimin-W3"},
72 {"MS Gothic", "Jun101-Light"},
73 };
74
GetSubFontName(ByteString * name)75 bool GetSubFontName(ByteString* name) {
76 for (size_t i = 0; i < FX_ArraySize(g_JpFontNameMap); ++i) {
77 if (!FXSYS_stricmp(name->c_str(), g_JpFontNameMap[i].m_pSrcFontName)) {
78 *name = g_JpFontNameMap[i].m_pSubFontName;
79 return true;
80 }
81 }
82 return false;
83 }
84
IsGDIEnabled()85 bool IsGDIEnabled() {
86 // If GDI is disabled then GetDC for the desktop will fail.
87 HDC hdc = ::GetDC(nullptr);
88 if (!hdc)
89 return false;
90 ::ReleaseDC(nullptr, hdc);
91 return true;
92 }
93
CreatePen(const CFX_GraphStateData * pGraphState,const CFX_Matrix * pMatrix,uint32_t argb)94 HPEN CreatePen(const CFX_GraphStateData* pGraphState,
95 const CFX_Matrix* pMatrix,
96 uint32_t argb) {
97 float width;
98 float scale = 1.f;
99 if (pMatrix)
100 scale = fabs(pMatrix->a) > fabs(pMatrix->b) ? fabs(pMatrix->a)
101 : fabs(pMatrix->b);
102 if (pGraphState) {
103 width = scale * pGraphState->m_LineWidth;
104 } else {
105 width = 1.0f;
106 }
107 uint32_t PenStyle = PS_GEOMETRIC;
108 if (width < 1) {
109 width = 1;
110 }
111 if (pGraphState->m_DashCount) {
112 PenStyle |= PS_USERSTYLE;
113 } else {
114 PenStyle |= PS_SOLID;
115 }
116 switch (pGraphState->m_LineCap) {
117 case 0:
118 PenStyle |= PS_ENDCAP_FLAT;
119 break;
120 case 1:
121 PenStyle |= PS_ENDCAP_ROUND;
122 break;
123 case 2:
124 PenStyle |= PS_ENDCAP_SQUARE;
125 break;
126 }
127 switch (pGraphState->m_LineJoin) {
128 case 0:
129 PenStyle |= PS_JOIN_MITER;
130 break;
131 case 1:
132 PenStyle |= PS_JOIN_ROUND;
133 break;
134 case 2:
135 PenStyle |= PS_JOIN_BEVEL;
136 break;
137 }
138 int a;
139 FX_COLORREF rgb;
140 std::tie(a, rgb) = ArgbToColorRef(argb);
141 LOGBRUSH lb;
142 lb.lbColor = rgb;
143 lb.lbStyle = BS_SOLID;
144 lb.lbHatch = 0;
145 std::vector<uint32_t> dashes;
146 if (pGraphState->m_DashCount) {
147 dashes.resize(pGraphState->m_DashCount);
148 for (int i = 0; i < pGraphState->m_DashCount; i++) {
149 dashes[i] = FXSYS_round(
150 pMatrix ? pMatrix->TransformDistance(pGraphState->m_DashArray[i])
151 : pGraphState->m_DashArray[i]);
152 dashes[i] = std::max(dashes[i], 1U);
153 }
154 }
155 return ExtCreatePen(PenStyle, (DWORD)ceil(width), &lb,
156 pGraphState->m_DashCount,
157 reinterpret_cast<const DWORD*>(dashes.data()));
158 }
159
CreateBrush(uint32_t argb)160 HBRUSH CreateBrush(uint32_t argb) {
161 int a;
162 FX_COLORREF rgb;
163 std::tie(a, rgb) = ArgbToColorRef(argb);
164 return CreateSolidBrush(rgb);
165 }
166
SetPathToDC(HDC hDC,const CFX_PathData * pPathData,const CFX_Matrix * pMatrix)167 void SetPathToDC(HDC hDC,
168 const CFX_PathData* pPathData,
169 const CFX_Matrix* pMatrix) {
170 BeginPath(hDC);
171
172 const std::vector<FX_PATHPOINT>& pPoints = pPathData->GetPoints();
173 for (size_t i = 0; i < pPoints.size(); i++) {
174 CFX_PointF pos = pPoints[i].m_Point;
175 if (pMatrix)
176 pos = pMatrix->Transform(pos);
177
178 CFX_Point screen(FXSYS_round(pos.x), FXSYS_round(pos.y));
179 FXPT_TYPE point_type = pPoints[i].m_Type;
180 if (point_type == FXPT_TYPE::MoveTo) {
181 MoveToEx(hDC, screen.x, screen.y, nullptr);
182 } else if (point_type == FXPT_TYPE::LineTo) {
183 if (pPoints[i].m_Point == pPoints[i - 1].m_Point)
184 screen.x++;
185
186 LineTo(hDC, screen.x, screen.y);
187 } else if (point_type == FXPT_TYPE::BezierTo) {
188 POINT lppt[3];
189 lppt[0].x = screen.x;
190 lppt[0].y = screen.y;
191
192 pos = pPoints[i + 1].m_Point;
193 if (pMatrix)
194 pos = pMatrix->Transform(pos);
195
196 lppt[1].x = FXSYS_round(pos.x);
197 lppt[1].y = FXSYS_round(pos.y);
198
199 pos = pPoints[i + 2].m_Point;
200 if (pMatrix)
201 pos = pMatrix->Transform(pos);
202
203 lppt[2].x = FXSYS_round(pos.x);
204 lppt[2].y = FXSYS_round(pos.y);
205 PolyBezierTo(hDC, lppt, 3);
206 i += 2;
207 }
208 if (pPoints[i].m_CloseFigure)
209 CloseFigure(hDC);
210 }
211 EndPath(hDC);
212 }
213
214 #ifdef _SKIA_SUPPORT_
215 // TODO(caryclark) This antigrain function is duplicated here to permit
216 // removing the last remaining dependency. Eventually, this will be elminiated
217 // altogether and replace by Skia code.
218
219 struct rect_base {
220 float x1;
221 float y1;
222 float x2;
223 float y2;
224 };
225
clip_liang_barsky(float x1,float y1,float x2,float y2,const rect_base & clip_box,float * x,float * y)226 unsigned clip_liang_barsky(float x1,
227 float y1,
228 float x2,
229 float y2,
230 const rect_base& clip_box,
231 float* x,
232 float* y) {
233 const float nearzero = 1e-30f;
234 float deltax = x2 - x1;
235 float deltay = y2 - y1;
236 unsigned np = 0;
237 if (deltax == 0)
238 deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
239 float xin, xout;
240 if (deltax > 0) {
241 xin = clip_box.x1;
242 xout = clip_box.x2;
243 } else {
244 xin = clip_box.x2;
245 xout = clip_box.x1;
246 }
247 float tinx = (xin - x1) / deltax;
248 if (deltay == 0)
249 deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
250 float yin, yout;
251 if (deltay > 0) {
252 yin = clip_box.y1;
253 yout = clip_box.y2;
254 } else {
255 yin = clip_box.y2;
256 yout = clip_box.y1;
257 }
258 float tiny = (yin - y1) / deltay;
259 float tin1, tin2;
260 if (tinx < tiny) {
261 tin1 = tinx;
262 tin2 = tiny;
263 } else {
264 tin1 = tiny;
265 tin2 = tinx;
266 }
267 if (tin1 <= 1.0f) {
268 if (0 < tin1) {
269 *x++ = xin;
270 *y++ = yin;
271 ++np;
272 }
273 if (tin2 <= 1.0f) {
274 float toutx = (xout - x1) / deltax;
275 float touty = (yout - y1) / deltay;
276 float tout1 = (toutx < touty) ? toutx : touty;
277 if (tin2 > 0 || tout1 > 0) {
278 if (tin2 <= tout1) {
279 if (tin2 > 0) {
280 if (tinx > tiny) {
281 *x++ = xin;
282 *y++ = y1 + (deltay * tinx);
283 } else {
284 *x++ = x1 + (deltax * tiny);
285 *y++ = yin;
286 }
287 ++np;
288 }
289 if (tout1 < 1.0f) {
290 if (toutx < touty) {
291 *x++ = xout;
292 *y++ = y1 + (deltay * toutx);
293 } else {
294 *x++ = x1 + (deltax * touty);
295 *y++ = yout;
296 }
297 } else {
298 *x++ = x2;
299 *y++ = y2;
300 }
301 ++np;
302 } else {
303 if (tinx > tiny) {
304 *x++ = xin;
305 *y++ = yout;
306 } else {
307 *x++ = xout;
308 *y++ = yin;
309 }
310 ++np;
311 }
312 }
313 }
314 }
315 return np;
316 }
317 #endif // _SKIA_SUPPORT_
318
319 class CFX_Win32FallbackFontInfo final : public CFX_FolderFontInfo {
320 public:
CFX_Win32FallbackFontInfo()321 CFX_Win32FallbackFontInfo() {}
~CFX_Win32FallbackFontInfo()322 ~CFX_Win32FallbackFontInfo() override {}
323
324 // CFX_FolderFontInfo:
325 void* MapFont(int weight,
326 bool bItalic,
327 int charset,
328 int pitch_family,
329 const char* family) override;
330 };
331
332 class CFX_Win32FontInfo final : public IFX_SystemFontInfo {
333 public:
334 CFX_Win32FontInfo();
335 ~CFX_Win32FontInfo() override;
336
337 // IFX_SystemFontInfo
338 bool EnumFontList(CFX_FontMapper* pMapper) override;
339 void* MapFont(int weight,
340 bool bItalic,
341 int charset,
342 int pitch_family,
343 const char* face) override;
GetFont(const char * face)344 void* GetFont(const char* face) override { return nullptr; }
345 uint32_t GetFontData(void* hFont,
346 uint32_t table,
347 uint8_t* buffer,
348 uint32_t size) override;
349 bool GetFaceName(void* hFont, ByteString* name) override;
350 bool GetFontCharset(void* hFont, int* charset) override;
351 void DeleteFont(void* hFont) override;
352
353 bool IsOpenTypeFromDiv(const LOGFONTA* plf);
354 bool IsSupportFontFormDiv(const LOGFONTA* plf);
355 void AddInstalledFont(const LOGFONTA* plf, uint32_t FontType);
356 void GetGBPreference(ByteString& face, int weight, int picth_family);
357 void GetJapanesePreference(ByteString& face, int weight, int picth_family);
358 ByteString FindFont(const ByteString& name);
359
360 HDC m_hDC;
361 UnownedPtr<CFX_FontMapper> m_pMapper;
362 ByteString m_LastFamily;
363 ByteString m_KaiTi, m_FangSong;
364 };
365
FontEnumProc(const LOGFONTA * plf,const TEXTMETRICA * lpntme,uint32_t FontType,LPARAM lParam)366 int CALLBACK FontEnumProc(const LOGFONTA* plf,
367 const TEXTMETRICA* lpntme,
368 uint32_t FontType,
369 LPARAM lParam) {
370 CFX_Win32FontInfo* pFontInfo = reinterpret_cast<CFX_Win32FontInfo*>(lParam);
371 pFontInfo->AddInstalledFont(plf, FontType);
372 return 1;
373 }
374
CFX_Win32FontInfo()375 CFX_Win32FontInfo::CFX_Win32FontInfo() : m_hDC(CreateCompatibleDC(nullptr)) {}
376
~CFX_Win32FontInfo()377 CFX_Win32FontInfo::~CFX_Win32FontInfo() {
378 DeleteDC(m_hDC);
379 }
380
IsOpenTypeFromDiv(const LOGFONTA * plf)381 bool CFX_Win32FontInfo::IsOpenTypeFromDiv(const LOGFONTA* plf) {
382 HFONT hFont = CreateFontIndirectA(plf);
383 bool ret = false;
384 uint32_t font_size = GetFontData(hFont, 0, nullptr, 0);
385 if (font_size != GDI_ERROR && font_size >= sizeof(uint32_t)) {
386 uint32_t lVersion = 0;
387 GetFontData(hFont, 0, (uint8_t*)(&lVersion), sizeof(uint32_t));
388 lVersion = (((uint32_t)(uint8_t)(lVersion)) << 24) |
389 ((uint32_t)((uint8_t)(lVersion >> 8))) << 16 |
390 ((uint32_t)((uint8_t)(lVersion >> 16))) << 8 |
391 ((uint8_t)(lVersion >> 24));
392 if (lVersion == FXBSTR_ID('O', 'T', 'T', 'O') || lVersion == 0x00010000 ||
393 lVersion == FXBSTR_ID('t', 't', 'c', 'f') ||
394 lVersion == FXBSTR_ID('t', 'r', 'u', 'e') || lVersion == 0x00020000) {
395 ret = true;
396 }
397 }
398 DeleteFont(hFont);
399 return ret;
400 }
401
IsSupportFontFormDiv(const LOGFONTA * plf)402 bool CFX_Win32FontInfo::IsSupportFontFormDiv(const LOGFONTA* plf) {
403 HFONT hFont = CreateFontIndirectA(plf);
404 bool ret = false;
405 uint32_t font_size = GetFontData(hFont, 0, nullptr, 0);
406 if (font_size != GDI_ERROR && font_size >= sizeof(uint32_t)) {
407 uint32_t lVersion = 0;
408 GetFontData(hFont, 0, (uint8_t*)(&lVersion), sizeof(uint32_t));
409 lVersion = (((uint32_t)(uint8_t)(lVersion)) << 24) |
410 ((uint32_t)((uint8_t)(lVersion >> 8))) << 16 |
411 ((uint32_t)((uint8_t)(lVersion >> 16))) << 8 |
412 ((uint8_t)(lVersion >> 24));
413 if (lVersion == FXBSTR_ID('O', 'T', 'T', 'O') || lVersion == 0x00010000 ||
414 lVersion == FXBSTR_ID('t', 't', 'c', 'f') ||
415 lVersion == FXBSTR_ID('t', 'r', 'u', 'e') || lVersion == 0x00020000 ||
416 (lVersion & 0xFFFF0000) == FXBSTR_ID(0x80, 0x01, 0x00, 0x00) ||
417 (lVersion & 0xFFFF0000) == FXBSTR_ID('%', '!', 0, 0)) {
418 ret = true;
419 }
420 }
421 DeleteFont(hFont);
422 return ret;
423 }
424
AddInstalledFont(const LOGFONTA * plf,uint32_t FontType)425 void CFX_Win32FontInfo::AddInstalledFont(const LOGFONTA* plf,
426 uint32_t FontType) {
427 ByteString name(plf->lfFaceName);
428 if (name.GetLength() > 0 && name[0] == '@')
429 return;
430
431 if (name == m_LastFamily) {
432 m_pMapper->AddInstalledFont(name, plf->lfCharSet);
433 return;
434 }
435 if (!(FontType & TRUETYPE_FONTTYPE)) {
436 if (!(FontType & DEVICE_FONTTYPE) || !IsSupportFontFormDiv(plf))
437 return;
438 }
439
440 m_pMapper->AddInstalledFont(name, plf->lfCharSet);
441 m_LastFamily = name;
442 }
443
EnumFontList(CFX_FontMapper * pMapper)444 bool CFX_Win32FontInfo::EnumFontList(CFX_FontMapper* pMapper) {
445 m_pMapper = pMapper;
446 LOGFONTA lf;
447 memset(&lf, 0, sizeof(LOGFONTA));
448 lf.lfCharSet = FX_CHARSET_Default;
449 lf.lfFaceName[0] = 0;
450 lf.lfPitchAndFamily = 0;
451 EnumFontFamiliesExA(m_hDC, &lf, (FONTENUMPROCA)FontEnumProc, (uintptr_t) this,
452 0);
453 return true;
454 }
455
FindFont(const ByteString & name)456 ByteString CFX_Win32FontInfo::FindFont(const ByteString& name) {
457 if (!m_pMapper)
458 return name;
459
460 for (size_t i = 0; i < m_pMapper->m_InstalledTTFonts.size(); ++i) {
461 ByteString thisname = m_pMapper->m_InstalledTTFonts[i];
462 if (thisname.Left(name.GetLength()) == name)
463 return m_pMapper->m_InstalledTTFonts[i];
464 }
465 for (size_t i = 0; i < m_pMapper->m_LocalizedTTFonts.size(); ++i) {
466 ByteString thisname = m_pMapper->m_LocalizedTTFonts[i].first;
467 if (thisname.Left(name.GetLength()) == name)
468 return m_pMapper->m_LocalizedTTFonts[i].second;
469 }
470 return ByteString();
471 }
472
MapFont(int weight,bool bItalic,int charset,int pitch_family,const char * cstr_face)473 void* CFX_Win32FallbackFontInfo::MapFont(int weight,
474 bool bItalic,
475 int charset,
476 int pitch_family,
477 const char* cstr_face) {
478 void* font = GetSubstFont(cstr_face);
479 if (font)
480 return font;
481
482 bool bCJK = true;
483 switch (charset) {
484 case FX_CHARSET_ShiftJIS:
485 case FX_CHARSET_ChineseSimplified:
486 case FX_CHARSET_ChineseTraditional:
487 case FX_CHARSET_Hangul:
488 break;
489 default:
490 bCJK = false;
491 break;
492 }
493 return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK);
494 }
495
GetGBPreference(ByteString & face,int weight,int picth_family)496 void CFX_Win32FontInfo::GetGBPreference(ByteString& face,
497 int weight,
498 int picth_family) {
499 if (face.Contains("KaiTi") || face.Contains("\xbf\xac")) {
500 if (m_KaiTi.IsEmpty()) {
501 m_KaiTi = FindFont("KaiTi");
502 if (m_KaiTi.IsEmpty()) {
503 m_KaiTi = "SimSun";
504 }
505 }
506 face = m_KaiTi;
507 } else if (face.Contains("FangSong") || face.Contains("\xb7\xc2\xcb\xce")) {
508 if (m_FangSong.IsEmpty()) {
509 m_FangSong = FindFont("FangSong");
510 if (m_FangSong.IsEmpty()) {
511 m_FangSong = "SimSun";
512 }
513 }
514 face = m_FangSong;
515 } else if (face.Contains("SimSun") || face.Contains("\xcb\xce")) {
516 face = "SimSun";
517 } else if (face.Contains("SimHei") || face.Contains("\xba\xda")) {
518 face = "SimHei";
519 } else if (!(picth_family & FF_ROMAN) && weight > 550) {
520 face = "SimHei";
521 } else {
522 face = "SimSun";
523 }
524 }
525
GetJapanesePreference(ByteString & face,int weight,int picth_family)526 void CFX_Win32FontInfo::GetJapanesePreference(ByteString& face,
527 int weight,
528 int picth_family) {
529 if (face.Contains("Gothic") ||
530 face.Contains("\x83\x53\x83\x56\x83\x62\x83\x4e")) {
531 if (face.Contains("PGothic") ||
532 face.Contains("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e")) {
533 face = "MS PGothic";
534 } else if (face.Contains("UI Gothic")) {
535 face = "MS UI Gothic";
536 } else {
537 if (face.Contains("HGSGothicM") || face.Contains("HGMaruGothicMPRO")) {
538 face = "MS PGothic";
539 } else {
540 face = "MS Gothic";
541 }
542 }
543 return;
544 }
545 if (face.Contains("Mincho") || face.Contains("\x96\xbe\x92\xa9")) {
546 if (face.Contains("PMincho") || face.Contains("\x82\x6f\x96\xbe\x92\xa9")) {
547 face = "MS PMincho";
548 } else {
549 face = "MS Mincho";
550 }
551 return;
552 }
553 if (GetSubFontName(&face))
554 return;
555
556 if (!(picth_family & FF_ROMAN) && weight > 400) {
557 face = "MS PGothic";
558 } else {
559 face = "MS PMincho";
560 }
561 }
562
MapFont(int weight,bool bItalic,int charset,int pitch_family,const char * cstr_face)563 void* CFX_Win32FontInfo::MapFont(int weight,
564 bool bItalic,
565 int charset,
566 int pitch_family,
567 const char* cstr_face) {
568 ByteString face = cstr_face;
569 int iBaseFont;
570 for (iBaseFont = 0; iBaseFont < 12; iBaseFont++) {
571 if (face == ByteStringView(g_Base14Substs[iBaseFont].m_pName)) {
572 face = g_Base14Substs[iBaseFont].m_pWinName;
573 weight = g_Base14Substs[iBaseFont].m_bBold ? FW_BOLD : FW_NORMAL;
574 bItalic = g_Base14Substs[iBaseFont].m_bItalic;
575 break;
576 }
577 }
578 if (charset == FX_CHARSET_ANSI || charset == FX_CHARSET_Symbol)
579 charset = FX_CHARSET_Default;
580
581 int subst_pitch_family = pitch_family;
582 switch (charset) {
583 case FX_CHARSET_ShiftJIS:
584 subst_pitch_family = FF_ROMAN;
585 break;
586 case FX_CHARSET_ChineseTraditional:
587 case FX_CHARSET_Hangul:
588 case FX_CHARSET_ChineseSimplified:
589 subst_pitch_family = 0;
590 break;
591 }
592 HFONT hFont =
593 ::CreateFontA(-10, 0, 0, 0, weight, bItalic, 0, 0, charset,
594 OUT_TT_ONLY_PRECIS, 0, 0, subst_pitch_family, face.c_str());
595 char facebuf[100];
596 HFONT hOldFont = (HFONT)::SelectObject(m_hDC, hFont);
597 ::GetTextFaceA(m_hDC, 100, facebuf);
598 ::SelectObject(m_hDC, hOldFont);
599 if (face.EqualNoCase(facebuf))
600 return hFont;
601
602 WideString wsFace = WideString::FromLocal(facebuf);
603 for (size_t i = 0; i < FX_ArraySize(g_VariantNames); ++i) {
604 if (face != g_VariantNames[i].m_pFaceName)
605 continue;
606
607 const unsigned short* pName = reinterpret_cast<const unsigned short*>(
608 g_VariantNames[i].m_pVariantName);
609 size_t len = WideString::WStringLength(pName);
610 WideString wsName = WideString::FromUTF16LE(pName, len);
611 if (wsFace == wsName)
612 return hFont;
613 }
614 ::DeleteObject(hFont);
615 if (charset == FX_CHARSET_Default)
616 return nullptr;
617
618 switch (charset) {
619 case FX_CHARSET_ShiftJIS:
620 GetJapanesePreference(face, weight, pitch_family);
621 break;
622 case FX_CHARSET_ChineseSimplified:
623 GetGBPreference(face, weight, pitch_family);
624 break;
625 case FX_CHARSET_Hangul:
626 face = "Gulim";
627 break;
628 case FX_CHARSET_ChineseTraditional:
629 if (face.Contains("MSung")) {
630 face = "MingLiU";
631 } else {
632 face = "PMingLiU";
633 }
634 break;
635 }
636 hFont =
637 ::CreateFontA(-10, 0, 0, 0, weight, bItalic, 0, 0, charset,
638 OUT_TT_ONLY_PRECIS, 0, 0, subst_pitch_family, face.c_str());
639 return hFont;
640 }
641
DeleteFont(void * hFont)642 void CFX_Win32FontInfo::DeleteFont(void* hFont) {
643 ::DeleteObject(hFont);
644 }
645
GetFontData(void * hFont,uint32_t table,uint8_t * buffer,uint32_t size)646 uint32_t CFX_Win32FontInfo::GetFontData(void* hFont,
647 uint32_t table,
648 uint8_t* buffer,
649 uint32_t size) {
650 HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont);
651 table = FXDWORD_GET_MSBFIRST(reinterpret_cast<uint8_t*>(&table));
652 size = ::GetFontData(m_hDC, table, 0, buffer, size);
653 ::SelectObject(m_hDC, hOldFont);
654 if (size == GDI_ERROR) {
655 return 0;
656 }
657 return size;
658 }
659
GetFaceName(void * hFont,ByteString * name)660 bool CFX_Win32FontInfo::GetFaceName(void* hFont, ByteString* name) {
661 char facebuf[100];
662 HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont);
663 int ret = ::GetTextFaceA(m_hDC, 100, facebuf);
664 ::SelectObject(m_hDC, hOldFont);
665 if (ret == 0) {
666 return false;
667 }
668 *name = facebuf;
669 return true;
670 }
671
GetFontCharset(void * hFont,int * charset)672 bool CFX_Win32FontInfo::GetFontCharset(void* hFont, int* charset) {
673 TEXTMETRIC tm;
674 HFONT hOldFont = (HFONT)::SelectObject(m_hDC, (HFONT)hFont);
675 ::GetTextMetrics(m_hDC, &tm);
676 ::SelectObject(m_hDC, hOldFont);
677 *charset = tm.tmCharSet;
678 return true;
679 }
680
681 } // namespace
682
683 int g_pdfium_print_mode = WindowsPrintMode::kModeEmf;
684
CreateDefault(const char ** pUnused)685 std::unique_ptr<IFX_SystemFontInfo> IFX_SystemFontInfo::CreateDefault(
686 const char** pUnused) {
687 if (IsGDIEnabled())
688 return std::unique_ptr<IFX_SystemFontInfo>(new CFX_Win32FontInfo);
689
690 // Select the fallback font information class if GDI is disabled.
691 CFX_Win32FallbackFontInfo* pInfoFallback = new CFX_Win32FallbackFontInfo;
692 // Construct the font path manually, SHGetKnownFolderPath won't work under
693 // a restrictive sandbox.
694 CHAR windows_path[MAX_PATH] = {};
695 DWORD path_len = ::GetWindowsDirectoryA(windows_path, MAX_PATH);
696 if (path_len > 0 && path_len < MAX_PATH) {
697 ByteString fonts_path(windows_path);
698 fonts_path += "\\Fonts";
699 pInfoFallback->AddPath(fonts_path);
700 }
701 return std::unique_ptr<IFX_SystemFontInfo>(pInfoFallback);
702 }
703
InitPlatform()704 void CFX_GEModule::InitPlatform() {
705 CWin32Platform* pPlatformData = new CWin32Platform;
706 OSVERSIONINFO ver;
707 ver.dwOSVersionInfoSize = sizeof(ver);
708 GetVersionEx(&ver);
709 pPlatformData->m_bHalfTone = ver.dwMajorVersion >= 5;
710 if (IsGDIEnabled())
711 pPlatformData->m_GdiplusExt.Load();
712 m_pPlatformData = pPlatformData;
713 m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault(nullptr));
714 }
715
DestroyPlatform()716 void CFX_GEModule::DestroyPlatform() {
717 delete (CWin32Platform*)m_pPlatformData;
718 m_pPlatformData = nullptr;
719 }
720
CGdiDeviceDriver(HDC hDC,int device_class)721 CGdiDeviceDriver::CGdiDeviceDriver(HDC hDC, int device_class) {
722 m_hDC = hDC;
723 m_DeviceClass = device_class;
724 CWin32Platform* pPlatform =
725 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
726 SetStretchBltMode(hDC, pPlatform->m_bHalfTone ? HALFTONE : COLORONCOLOR);
727 DWORD obj_type = GetObjectType(m_hDC);
728 m_bMetafileDCType = obj_type == OBJ_ENHMETADC || obj_type == OBJ_ENHMETAFILE;
729 if (obj_type == OBJ_MEMDC) {
730 HBITMAP hBitmap = CreateBitmap(1, 1, 1, 1, nullptr);
731 hBitmap = (HBITMAP)SelectObject(m_hDC, hBitmap);
732 BITMAP bitmap;
733 GetObject(hBitmap, sizeof bitmap, &bitmap);
734 m_nBitsPerPixel = bitmap.bmBitsPixel;
735 m_Width = bitmap.bmWidth;
736 m_Height = abs(bitmap.bmHeight);
737 hBitmap = (HBITMAP)SelectObject(m_hDC, hBitmap);
738 DeleteObject(hBitmap);
739 } else {
740 m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL);
741 m_Width = ::GetDeviceCaps(m_hDC, HORZRES);
742 m_Height = ::GetDeviceCaps(m_hDC, VERTRES);
743 }
744 if (m_DeviceClass != FXDC_DISPLAY) {
745 m_RenderCaps = FXRC_BIT_MASK;
746 } else {
747 m_RenderCaps = FXRC_GET_BITS | FXRC_BIT_MASK;
748 }
749 }
750
~CGdiDeviceDriver()751 CGdiDeviceDriver::~CGdiDeviceDriver() {}
752
GetDeviceCaps(int caps_id) const753 int CGdiDeviceDriver::GetDeviceCaps(int caps_id) const {
754 switch (caps_id) {
755 case FXDC_DEVICE_CLASS:
756 return m_DeviceClass;
757 case FXDC_PIXEL_WIDTH:
758 return m_Width;
759 case FXDC_PIXEL_HEIGHT:
760 return m_Height;
761 case FXDC_BITS_PIXEL:
762 return m_nBitsPerPixel;
763 case FXDC_RENDER_CAPS:
764 return m_RenderCaps;
765 }
766 return 0;
767 }
768
SaveState()769 void CGdiDeviceDriver::SaveState() {
770 SaveDC(m_hDC);
771 }
772
RestoreState(bool bKeepSaved)773 void CGdiDeviceDriver::RestoreState(bool bKeepSaved) {
774 RestoreDC(m_hDC, -1);
775 if (bKeepSaved)
776 SaveDC(m_hDC);
777 }
778
GDI_SetDIBits(const RetainPtr<CFX_DIBitmap> & pBitmap1,const FX_RECT * pSrcRect,int left,int top)779 bool CGdiDeviceDriver::GDI_SetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap1,
780 const FX_RECT* pSrcRect,
781 int left,
782 int top) {
783 if (m_DeviceClass == FXDC_PRINTER) {
784 RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1->FlipImage(false, true);
785 if (!pBitmap)
786 return false;
787
788 if (pBitmap->IsCmykImage() && !pBitmap->ConvertFormat(FXDIB_Rgb))
789 return false;
790
791 int width = pSrcRect->Width(), height = pSrcRect->Height();
792 LPBYTE pBuffer = pBitmap->GetBuffer();
793 ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap);
794 ((BITMAPINFOHEADER*)info.c_str())->biHeight *= -1;
795 FX_RECT dst_rect(0, 0, width, height);
796 dst_rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
797 int dst_width = dst_rect.Width();
798 int dst_height = dst_rect.Height();
799 ::StretchDIBits(m_hDC, left, top, dst_width, dst_height, 0, 0, dst_width,
800 dst_height, pBuffer, (BITMAPINFO*)info.c_str(),
801 DIB_RGB_COLORS, SRCCOPY);
802 } else {
803 RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1;
804 if (pBitmap->IsCmykImage()) {
805 pBitmap = pBitmap->CloneConvert(FXDIB_Rgb);
806 if (!pBitmap)
807 return false;
808 }
809 int width = pSrcRect->Width(), height = pSrcRect->Height();
810 LPBYTE pBuffer = pBitmap->GetBuffer();
811 ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap);
812 ::SetDIBitsToDevice(m_hDC, left, top, width, height, pSrcRect->left,
813 pBitmap->GetHeight() - pSrcRect->bottom, 0,
814 pBitmap->GetHeight(), pBuffer,
815 (BITMAPINFO*)info.c_str(), DIB_RGB_COLORS);
816 }
817 return true;
818 }
819
GDI_StretchDIBits(const RetainPtr<CFX_DIBitmap> & pBitmap1,int dest_left,int dest_top,int dest_width,int dest_height,uint32_t flags)820 bool CGdiDeviceDriver::GDI_StretchDIBits(
821 const RetainPtr<CFX_DIBitmap>& pBitmap1,
822 int dest_left,
823 int dest_top,
824 int dest_width,
825 int dest_height,
826 uint32_t flags) {
827 RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1;
828 if (!pBitmap || dest_width == 0 || dest_height == 0)
829 return false;
830
831 if (pBitmap->IsCmykImage() && !pBitmap->ConvertFormat(FXDIB_Rgb))
832 return false;
833
834 ByteString info = CFX_WindowsDIB::GetBitmapInfo(pBitmap);
835 if ((int64_t)abs(dest_width) * abs(dest_height) <
836 (int64_t)pBitmap1->GetWidth() * pBitmap1->GetHeight() * 4 ||
837 (flags & FXDIB_INTERPOL) || (flags & FXDIB_BICUBIC_INTERPOL)) {
838 SetStretchBltMode(m_hDC, HALFTONE);
839 } else {
840 SetStretchBltMode(m_hDC, COLORONCOLOR);
841 }
842 RetainPtr<CFX_DIBitmap> pToStrechBitmap = pBitmap;
843 if (m_DeviceClass == FXDC_PRINTER &&
844 ((int64_t)pBitmap->GetWidth() * pBitmap->GetHeight() >
845 (int64_t)abs(dest_width) * abs(dest_height))) {
846 pToStrechBitmap = pBitmap->StretchTo(dest_width, dest_height, 0, nullptr);
847 }
848 ByteString toStrechBitmapInfo =
849 CFX_WindowsDIB::GetBitmapInfo(pToStrechBitmap);
850 ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0,
851 pToStrechBitmap->GetWidth(), pToStrechBitmap->GetHeight(),
852 pToStrechBitmap->GetBuffer(),
853 (BITMAPINFO*)toStrechBitmapInfo.c_str(), DIB_RGB_COLORS,
854 SRCCOPY);
855 return true;
856 }
857
GDI_StretchBitMask(const RetainPtr<CFX_DIBitmap> & pBitmap1,int dest_left,int dest_top,int dest_width,int dest_height,uint32_t bitmap_color,uint32_t flags)858 bool CGdiDeviceDriver::GDI_StretchBitMask(
859 const RetainPtr<CFX_DIBitmap>& pBitmap1,
860 int dest_left,
861 int dest_top,
862 int dest_width,
863 int dest_height,
864 uint32_t bitmap_color,
865 uint32_t flags) {
866 RetainPtr<CFX_DIBitmap> pBitmap = pBitmap1;
867 if (!pBitmap || dest_width == 0 || dest_height == 0)
868 return false;
869
870 int width = pBitmap->GetWidth(), height = pBitmap->GetHeight();
871 struct {
872 BITMAPINFOHEADER bmiHeader;
873 uint32_t bmiColors[2];
874 } bmi;
875 memset(&bmi.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
876 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
877 bmi.bmiHeader.biBitCount = 1;
878 bmi.bmiHeader.biCompression = BI_RGB;
879 bmi.bmiHeader.biHeight = -height;
880 bmi.bmiHeader.biPlanes = 1;
881 bmi.bmiHeader.biWidth = width;
882 if (m_nBitsPerPixel != 1) {
883 SetStretchBltMode(m_hDC, HALFTONE);
884 }
885 bmi.bmiColors[0] = 0xffffff;
886 bmi.bmiColors[1] = 0;
887
888 HBRUSH hPattern = CreateSolidBrush(bitmap_color & 0xffffff);
889 HBRUSH hOld = (HBRUSH)SelectObject(m_hDC, hPattern);
890
891 // In PDF, when image mask is 1, use device bitmap; when mask is 0, use brush
892 // bitmap.
893 // A complete list of the boolen operations is as follows:
894
895 /* P(bitmap_color) S(ImageMask) D(DeviceBitmap) Result
896 * 0 0 0 0
897 * 0 0 1 0
898 * 0 1 0 0
899 * 0 1 1 1
900 * 1 0 0 1
901 * 1 0 1 1
902 * 1 1 0 0
903 * 1 1 1 1
904 */
905 // The boolen codes is B8. Based on
906 // http://msdn.microsoft.com/en-us/library/aa932106.aspx, the ROP3 code is
907 // 0xB8074A
908
909 ::StretchDIBits(m_hDC, dest_left, dest_top, dest_width, dest_height, 0, 0,
910 width, height, pBitmap->GetBuffer(), (BITMAPINFO*)&bmi,
911 DIB_RGB_COLORS, 0xB8074A);
912
913 SelectObject(m_hDC, hOld);
914 DeleteObject(hPattern);
915
916 return true;
917 }
918
GetClipBox(FX_RECT * pRect)919 bool CGdiDeviceDriver::GetClipBox(FX_RECT* pRect) {
920 return !!(::GetClipBox(m_hDC, (RECT*)pRect));
921 }
922
DrawLine(float x1,float y1,float x2,float y2)923 void CGdiDeviceDriver::DrawLine(float x1, float y1, float x2, float y2) {
924 if (!m_bMetafileDCType) { // EMF drawing is not bound to the DC.
925 int startOutOfBoundsFlag = (x1 < 0) | ((x1 > m_Width) << 1) |
926 ((y1 < 0) << 2) | ((y1 > m_Height) << 3);
927 int endOutOfBoundsFlag = (x2 < 0) | ((x2 > m_Width) << 1) |
928 ((y2 < 0) << 2) | ((y2 > m_Height) << 3);
929 if (startOutOfBoundsFlag & endOutOfBoundsFlag)
930 return;
931
932 if (startOutOfBoundsFlag || endOutOfBoundsFlag) {
933 float x[2];
934 float y[2];
935 int np;
936 #ifdef _SKIA_SUPPORT_
937 // TODO(caryclark) temporary replacement of antigrain in line function
938 // to permit removing antigrain altogether
939 rect_base rect = {0.0f, 0.0f, (float)(m_Width), (float)(m_Height)};
940 np = clip_liang_barsky(x1, y1, x2, y2, rect, x, y);
941 #else
942 agg::rect_base<float> rect(0.0f, 0.0f, (float)(m_Width),
943 (float)(m_Height));
944 np = agg::clip_liang_barsky<float>(x1, y1, x2, y2, rect, x, y);
945 #endif
946 if (np == 0)
947 return;
948
949 if (np == 1) {
950 x2 = x[0];
951 y2 = y[0];
952 } else {
953 ASSERT(np == 2);
954 x1 = x[0];
955 y1 = y[0];
956 x2 = x[1];
957 y2 = y[1];
958 }
959 }
960 }
961
962 MoveToEx(m_hDC, FXSYS_round(x1), FXSYS_round(y1), nullptr);
963 LineTo(m_hDC, FXSYS_round(x2), FXSYS_round(y2));
964 }
965
DrawPath(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,const CFX_GraphStateData * pGraphState,uint32_t fill_color,uint32_t stroke_color,int fill_mode,int blend_type)966 bool CGdiDeviceDriver::DrawPath(const CFX_PathData* pPathData,
967 const CFX_Matrix* pMatrix,
968 const CFX_GraphStateData* pGraphState,
969 uint32_t fill_color,
970 uint32_t stroke_color,
971 int fill_mode,
972 int blend_type) {
973 if (blend_type != FXDIB_BLEND_NORMAL)
974 return false;
975
976 CWin32Platform* pPlatform =
977 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
978 if (!(pGraphState || stroke_color == 0) &&
979 !pPlatform->m_GdiplusExt.IsAvailable()) {
980 CFX_FloatRect bbox_f = pPathData->GetBoundingBox();
981 if (pMatrix)
982 bbox_f = pMatrix->TransformRect(bbox_f);
983
984 FX_RECT bbox = bbox_f.GetInnerRect();
985 if (bbox.Width() <= 0) {
986 return DrawCosmeticLine(CFX_PointF(bbox.left, bbox.top),
987 CFX_PointF(bbox.left, bbox.bottom + 1),
988 fill_color, FXDIB_BLEND_NORMAL);
989 }
990 if (bbox.Height() <= 0) {
991 return DrawCosmeticLine(CFX_PointF(bbox.left, bbox.top),
992 CFX_PointF(bbox.right + 1, bbox.top), fill_color,
993 FXDIB_BLEND_NORMAL);
994 }
995 }
996 int fill_alpha = FXARGB_A(fill_color);
997 int stroke_alpha = FXARGB_A(stroke_color);
998 bool bDrawAlpha = (fill_alpha > 0 && fill_alpha < 255) ||
999 (stroke_alpha > 0 && stroke_alpha < 255 && pGraphState);
1000 if (!pPlatform->m_GdiplusExt.IsAvailable() && bDrawAlpha)
1001 return false;
1002
1003 if (pPlatform->m_GdiplusExt.IsAvailable()) {
1004 if (bDrawAlpha ||
1005 ((m_DeviceClass != FXDC_PRINTER && !(fill_mode & FXFILL_FULLCOVER)) ||
1006 (pGraphState && pGraphState->m_DashCount))) {
1007 if (!((!pMatrix || !pMatrix->WillScale()) && pGraphState &&
1008 pGraphState->m_LineWidth == 1.f &&
1009 (pPathData->GetPoints().size() == 5 ||
1010 pPathData->GetPoints().size() == 4) &&
1011 pPathData->IsRect())) {
1012 if (pPlatform->m_GdiplusExt.DrawPath(m_hDC, pPathData, pMatrix,
1013 pGraphState, fill_color,
1014 stroke_color, fill_mode)) {
1015 return true;
1016 }
1017 }
1018 }
1019 }
1020 int old_fill_mode = fill_mode;
1021 fill_mode &= 3;
1022 HPEN hPen = nullptr;
1023 HBRUSH hBrush = nullptr;
1024 if (pGraphState && stroke_alpha) {
1025 SetMiterLimit(m_hDC, pGraphState->m_MiterLimit, nullptr);
1026 hPen = CreatePen(pGraphState, pMatrix, stroke_color);
1027 hPen = (HPEN)SelectObject(m_hDC, hPen);
1028 }
1029 if (fill_mode && fill_alpha) {
1030 SetPolyFillMode(m_hDC, fill_mode);
1031 hBrush = CreateBrush(fill_color);
1032 hBrush = (HBRUSH)SelectObject(m_hDC, hBrush);
1033 }
1034 if (pPathData->GetPoints().size() == 2 && pGraphState &&
1035 pGraphState->m_DashCount) {
1036 CFX_PointF pos1 = pPathData->GetPoint(0);
1037 CFX_PointF pos2 = pPathData->GetPoint(1);
1038 if (pMatrix) {
1039 pos1 = pMatrix->Transform(pos1);
1040 pos2 = pMatrix->Transform(pos2);
1041 }
1042 DrawLine(pos1.x, pos1.y, pos2.x, pos2.y);
1043 } else {
1044 SetPathToDC(m_hDC, pPathData, pMatrix);
1045 if (pGraphState && stroke_alpha) {
1046 if (fill_mode && fill_alpha) {
1047 if (old_fill_mode & FX_FILL_TEXT_MODE) {
1048 StrokeAndFillPath(m_hDC);
1049 } else {
1050 FillPath(m_hDC);
1051 SetPathToDC(m_hDC, pPathData, pMatrix);
1052 StrokePath(m_hDC);
1053 }
1054 } else {
1055 StrokePath(m_hDC);
1056 }
1057 } else if (fill_mode && fill_alpha) {
1058 FillPath(m_hDC);
1059 }
1060 }
1061 if (hPen) {
1062 hPen = (HPEN)SelectObject(m_hDC, hPen);
1063 DeleteObject(hPen);
1064 }
1065 if (hBrush) {
1066 hBrush = (HBRUSH)SelectObject(m_hDC, hBrush);
1067 DeleteObject(hBrush);
1068 }
1069 return true;
1070 }
1071
FillRectWithBlend(const FX_RECT * pRect,uint32_t fill_color,int blend_type)1072 bool CGdiDeviceDriver::FillRectWithBlend(const FX_RECT* pRect,
1073 uint32_t fill_color,
1074 int blend_type) {
1075 if (blend_type != FXDIB_BLEND_NORMAL)
1076 return false;
1077
1078 int alpha;
1079 FX_COLORREF rgb;
1080 std::tie(alpha, rgb) = ArgbToColorRef(fill_color);
1081 if (alpha == 0)
1082 return true;
1083
1084 if (alpha < 255)
1085 return false;
1086
1087 HBRUSH hBrush = CreateSolidBrush(rgb);
1088 ::FillRect(m_hDC, (RECT*)pRect, hBrush);
1089 DeleteObject(hBrush);
1090 return true;
1091 }
1092
SetClip_PathFill(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,int fill_mode)1093 bool CGdiDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData,
1094 const CFX_Matrix* pMatrix,
1095 int fill_mode) {
1096 if (pPathData->GetPoints().size() == 5) {
1097 CFX_FloatRect rectf;
1098 if (pPathData->IsRect(pMatrix, &rectf)) {
1099 FX_RECT rect = rectf.GetOuterRect();
1100 IntersectClipRect(m_hDC, rect.left, rect.top, rect.right, rect.bottom);
1101 return true;
1102 }
1103 }
1104 SetPathToDC(m_hDC, pPathData, pMatrix);
1105 SetPolyFillMode(m_hDC, fill_mode & 3);
1106 SelectClipPath(m_hDC, RGN_AND);
1107 return true;
1108 }
1109
SetClip_PathStroke(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,const CFX_GraphStateData * pGraphState)1110 bool CGdiDeviceDriver::SetClip_PathStroke(
1111 const CFX_PathData* pPathData,
1112 const CFX_Matrix* pMatrix,
1113 const CFX_GraphStateData* pGraphState) {
1114 HPEN hPen = CreatePen(pGraphState, pMatrix, 0xff000000);
1115 hPen = (HPEN)SelectObject(m_hDC, hPen);
1116 SetPathToDC(m_hDC, pPathData, pMatrix);
1117 WidenPath(m_hDC);
1118 SetPolyFillMode(m_hDC, WINDING);
1119 bool ret = !!SelectClipPath(m_hDC, RGN_AND);
1120 hPen = (HPEN)SelectObject(m_hDC, hPen);
1121 DeleteObject(hPen);
1122 return ret;
1123 }
1124
DrawCosmeticLine(const CFX_PointF & ptMoveTo,const CFX_PointF & ptLineTo,uint32_t color,int blend_type)1125 bool CGdiDeviceDriver::DrawCosmeticLine(const CFX_PointF& ptMoveTo,
1126 const CFX_PointF& ptLineTo,
1127 uint32_t color,
1128 int blend_type) {
1129 if (blend_type != FXDIB_BLEND_NORMAL)
1130 return false;
1131
1132 int a;
1133 FX_COLORREF rgb;
1134 std::tie(a, rgb) = ArgbToColorRef(color);
1135 if (a == 0)
1136 return true;
1137
1138 HPEN hPen = CreatePen(PS_SOLID, 1, rgb);
1139 hPen = (HPEN)SelectObject(m_hDC, hPen);
1140 MoveToEx(m_hDC, FXSYS_round(ptMoveTo.x), FXSYS_round(ptMoveTo.y), nullptr);
1141 LineTo(m_hDC, FXSYS_round(ptLineTo.x), FXSYS_round(ptLineTo.y));
1142 hPen = (HPEN)SelectObject(m_hDC, hPen);
1143 DeleteObject(hPen);
1144 return true;
1145 }
1146
CGdiDisplayDriver(HDC hDC)1147 CGdiDisplayDriver::CGdiDisplayDriver(HDC hDC)
1148 : CGdiDeviceDriver(hDC, FXDC_DISPLAY) {
1149 CWin32Platform* pPlatform =
1150 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
1151 if (pPlatform->m_GdiplusExt.IsAvailable()) {
1152 m_RenderCaps |= FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE;
1153 }
1154 }
1155
~CGdiDisplayDriver()1156 CGdiDisplayDriver::~CGdiDisplayDriver() {}
1157
GetDIBits(const RetainPtr<CFX_DIBitmap> & pBitmap,int left,int top)1158 bool CGdiDisplayDriver::GetDIBits(const RetainPtr<CFX_DIBitmap>& pBitmap,
1159 int left,
1160 int top) {
1161 bool ret = false;
1162 int width = pBitmap->GetWidth();
1163 int height = pBitmap->GetHeight();
1164 HBITMAP hbmp = CreateCompatibleBitmap(m_hDC, width, height);
1165 HDC hDCMemory = CreateCompatibleDC(m_hDC);
1166 HBITMAP holdbmp = (HBITMAP)SelectObject(hDCMemory, hbmp);
1167 BitBlt(hDCMemory, 0, 0, width, height, m_hDC, left, top, SRCCOPY);
1168 SelectObject(hDCMemory, holdbmp);
1169 BITMAPINFO bmi;
1170 memset(&bmi, 0, sizeof bmi);
1171 bmi.bmiHeader.biSize = sizeof bmi.bmiHeader;
1172 bmi.bmiHeader.biBitCount = pBitmap->GetBPP();
1173 bmi.bmiHeader.biHeight = -height;
1174 bmi.bmiHeader.biPlanes = 1;
1175 bmi.bmiHeader.biWidth = width;
1176 if (pBitmap->GetBPP() > 8 && !pBitmap->IsCmykImage()) {
1177 ret = ::GetDIBits(hDCMemory, hbmp, 0, height, pBitmap->GetBuffer(), &bmi,
1178 DIB_RGB_COLORS) == height;
1179 } else {
1180 auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1181 if (bitmap->Create(width, height, FXDIB_Rgb)) {
1182 bmi.bmiHeader.biBitCount = 24;
1183 ::GetDIBits(hDCMemory, hbmp, 0, height, bitmap->GetBuffer(), &bmi,
1184 DIB_RGB_COLORS);
1185 ret = pBitmap->TransferBitmap(0, 0, width, height, bitmap, 0, 0);
1186 } else {
1187 ret = false;
1188 }
1189 }
1190 if (pBitmap->HasAlpha() && ret)
1191 pBitmap->LoadChannel(FXDIB_Alpha, 0xff);
1192
1193 DeleteObject(hbmp);
1194 DeleteObject(hDCMemory);
1195 return ret;
1196 }
1197
SetDIBits(const RetainPtr<CFX_DIBSource> & pSource,uint32_t color,const FX_RECT * pSrcRect,int left,int top,int blend_type)1198 bool CGdiDisplayDriver::SetDIBits(const RetainPtr<CFX_DIBSource>& pSource,
1199 uint32_t color,
1200 const FX_RECT* pSrcRect,
1201 int left,
1202 int top,
1203 int blend_type) {
1204 ASSERT(blend_type == FXDIB_BLEND_NORMAL);
1205 if (pSource->IsAlphaMask()) {
1206 int width = pSource->GetWidth(), height = pSource->GetHeight();
1207 int alpha = FXARGB_A(color);
1208 if (pSource->GetBPP() != 1 || alpha != 255) {
1209 auto background = pdfium::MakeRetain<CFX_DIBitmap>();
1210 if (!background->Create(width, height, FXDIB_Rgb32) ||
1211 !GetDIBits(background, left, top) ||
1212 !background->CompositeMask(0, 0, width, height, pSource, color, 0, 0,
1213 FXDIB_BLEND_NORMAL, nullptr, false, 0)) {
1214 return false;
1215 }
1216 FX_RECT src_rect(0, 0, width, height);
1217 return SetDIBits(background, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL);
1218 }
1219 FX_RECT clip_rect(left, top, left + pSrcRect->Width(),
1220 top + pSrcRect->Height());
1221 return StretchDIBits(pSource, color, left - pSrcRect->left,
1222 top - pSrcRect->top, width, height, &clip_rect, 0,
1223 FXDIB_BLEND_NORMAL);
1224 }
1225 int width = pSrcRect->Width(), height = pSrcRect->Height();
1226 if (pSource->HasAlpha()) {
1227 auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1228 if (!bitmap->Create(width, height, FXDIB_Rgb) ||
1229 !GetDIBits(bitmap, left, top) ||
1230 !bitmap->CompositeBitmap(0, 0, width, height, pSource, pSrcRect->left,
1231 pSrcRect->top, FXDIB_BLEND_NORMAL, nullptr,
1232 false)) {
1233 return false;
1234 }
1235 FX_RECT src_rect(0, 0, width, height);
1236 return SetDIBits(bitmap, 0, &src_rect, left, top, FXDIB_BLEND_NORMAL);
1237 }
1238 CFX_DIBExtractor temp(pSource);
1239 RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
1240 if (!pBitmap)
1241 return false;
1242 return GDI_SetDIBits(pBitmap, pSrcRect, left, top);
1243 }
1244
UseFoxitStretchEngine(const RetainPtr<CFX_DIBSource> & pSource,uint32_t color,int dest_left,int dest_top,int dest_width,int dest_height,const FX_RECT * pClipRect,int render_flags)1245 bool CGdiDisplayDriver::UseFoxitStretchEngine(
1246 const RetainPtr<CFX_DIBSource>& pSource,
1247 uint32_t color,
1248 int dest_left,
1249 int dest_top,
1250 int dest_width,
1251 int dest_height,
1252 const FX_RECT* pClipRect,
1253 int render_flags) {
1254 FX_RECT bitmap_clip = *pClipRect;
1255 if (dest_width < 0)
1256 dest_left += dest_width;
1257
1258 if (dest_height < 0)
1259 dest_top += dest_height;
1260
1261 bitmap_clip.Offset(-dest_left, -dest_top);
1262 RetainPtr<CFX_DIBitmap> pStretched =
1263 pSource->StretchTo(dest_width, dest_height, render_flags, &bitmap_clip);
1264 if (!pStretched)
1265 return true;
1266
1267 FX_RECT src_rect(0, 0, pStretched->GetWidth(), pStretched->GetHeight());
1268 return SetDIBits(pStretched, color, &src_rect, pClipRect->left,
1269 pClipRect->top, FXDIB_BLEND_NORMAL);
1270 }
1271
StretchDIBits(const RetainPtr<CFX_DIBSource> & pSource,uint32_t color,int dest_left,int dest_top,int dest_width,int dest_height,const FX_RECT * pClipRect,uint32_t flags,int blend_type)1272 bool CGdiDisplayDriver::StretchDIBits(const RetainPtr<CFX_DIBSource>& pSource,
1273 uint32_t color,
1274 int dest_left,
1275 int dest_top,
1276 int dest_width,
1277 int dest_height,
1278 const FX_RECT* pClipRect,
1279 uint32_t flags,
1280 int blend_type) {
1281 ASSERT(pSource && pClipRect);
1282 if (flags || dest_width > 10000 || dest_width < -10000 ||
1283 dest_height > 10000 || dest_height < -10000) {
1284 return UseFoxitStretchEngine(pSource, color, dest_left, dest_top,
1285 dest_width, dest_height, pClipRect, flags);
1286 }
1287 if (pSource->IsAlphaMask()) {
1288 FX_RECT image_rect;
1289 image_rect.left = dest_width > 0 ? dest_left : dest_left + dest_width;
1290 image_rect.right = dest_width > 0 ? dest_left + dest_width : dest_left;
1291 image_rect.top = dest_height > 0 ? dest_top : dest_top + dest_height;
1292 image_rect.bottom = dest_height > 0 ? dest_top + dest_height : dest_top;
1293 FX_RECT clip_rect = image_rect;
1294 clip_rect.Intersect(*pClipRect);
1295 clip_rect.Offset(-image_rect.left, -image_rect.top);
1296 int clip_width = clip_rect.Width(), clip_height = clip_rect.Height();
1297 RetainPtr<CFX_DIBitmap> pStretched(
1298 pSource->StretchTo(dest_width, dest_height, flags, &clip_rect));
1299 if (!pStretched)
1300 return true;
1301
1302 auto background = pdfium::MakeRetain<CFX_DIBitmap>();
1303 if (!background->Create(clip_width, clip_height, FXDIB_Rgb32) ||
1304 !GetDIBits(background, image_rect.left + clip_rect.left,
1305 image_rect.top + clip_rect.top) ||
1306 !background->CompositeMask(0, 0, clip_width, clip_height, pStretched,
1307 color, 0, 0, FXDIB_BLEND_NORMAL, nullptr,
1308 false, 0)) {
1309 return false;
1310 }
1311
1312 FX_RECT src_rect(0, 0, clip_width, clip_height);
1313 return SetDIBits(background, 0, &src_rect, image_rect.left + clip_rect.left,
1314 image_rect.top + clip_rect.top, FXDIB_BLEND_NORMAL);
1315 }
1316 if (pSource->HasAlpha()) {
1317 CWin32Platform* pPlatform =
1318 (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
1319 if (pPlatform->m_GdiplusExt.IsAvailable() && !pSource->IsCmykImage()) {
1320 CFX_DIBExtractor temp(pSource);
1321 RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
1322 if (!pBitmap)
1323 return false;
1324 return pPlatform->m_GdiplusExt.StretchDIBits(
1325 m_hDC, pBitmap, dest_left, dest_top, dest_width, dest_height,
1326 pClipRect, flags);
1327 }
1328 return UseFoxitStretchEngine(pSource, color, dest_left, dest_top,
1329 dest_width, dest_height, pClipRect, flags);
1330 }
1331 CFX_DIBExtractor temp(pSource);
1332 RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
1333 if (!pBitmap)
1334 return false;
1335 return GDI_StretchDIBits(pBitmap, dest_left, dest_top, dest_width,
1336 dest_height, flags);
1337 }
1338
StartDIBits(const RetainPtr<CFX_DIBSource> & pBitmap,int bitmap_alpha,uint32_t color,const CFX_Matrix * pMatrix,uint32_t render_flags,std::unique_ptr<CFX_ImageRenderer> * handle,int blend_type)1339 bool CGdiDisplayDriver::StartDIBits(const RetainPtr<CFX_DIBSource>& pBitmap,
1340 int bitmap_alpha,
1341 uint32_t color,
1342 const CFX_Matrix* pMatrix,
1343 uint32_t render_flags,
1344 std::unique_ptr<CFX_ImageRenderer>* handle,
1345 int blend_type) {
1346 return false;
1347 }
1348
CFX_WindowsRenderDevice(HDC hDC)1349 CFX_WindowsRenderDevice::CFX_WindowsRenderDevice(HDC hDC) {
1350 SetDeviceDriver(pdfium::WrapUnique(CreateDriver(hDC)));
1351 }
1352
~CFX_WindowsRenderDevice()1353 CFX_WindowsRenderDevice::~CFX_WindowsRenderDevice() {}
1354
1355 // static
CreateDriver(HDC hDC)1356 IFX_RenderDeviceDriver* CFX_WindowsRenderDevice::CreateDriver(HDC hDC) {
1357 int device_type = ::GetDeviceCaps(hDC, TECHNOLOGY);
1358 int obj_type = ::GetObjectType(hDC);
1359 bool use_printer = device_type == DT_RASPRINTER ||
1360 device_type == DT_PLOTTER ||
1361 device_type == DT_CHARSTREAM || obj_type == OBJ_ENHMETADC;
1362
1363 if (!use_printer)
1364 return new CGdiDisplayDriver(hDC);
1365
1366 if (g_pdfium_print_mode == WindowsPrintMode::kModeEmf)
1367 return new CGdiPrinterDriver(hDC);
1368
1369 if (g_pdfium_print_mode == WindowsPrintMode::kModeTextOnly)
1370 return new CTextOnlyPrinterDriver(hDC);
1371
1372 // Should be PostScript
1373 ASSERT(g_pdfium_print_mode == WindowsPrintMode::kModePostScript2 ||
1374 g_pdfium_print_mode == WindowsPrintMode::kModePostScript3);
1375 return new CPSPrinterDriver(hDC, g_pdfium_print_mode, false);
1376 }
1377