OLD | NEW |
---|---|
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "core/fxge/include/fx_ge.h" | 7 #include "core/fxge/include/fx_ge.h" |
8 | 8 |
9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ | 9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |
10 | 10 |
11 #include <windows.h> | 11 #include <windows.h> |
12 | 12 |
13 #include <algorithm> | |
14 | |
13 #include "core/fxge/dib/dib_int.h" | 15 #include "core/fxge/dib/dib_int.h" |
14 #include "core/fxge/ge/fx_text_int.h" | 16 #include "core/fxge/ge/fx_text_int.h" |
15 #include "core/fxge/include/fx_freetype.h" | 17 #include "core/fxge/include/fx_freetype.h" |
16 #include "core/fxge/include/fx_ge_win32.h" | 18 #include "core/fxge/include/fx_ge_win32.h" |
17 #include "core/fxge/win32/win32_int.h" | 19 #include "core/fxge/win32/win32_int.h" |
18 | 20 |
21 #if defined(PDFIUM_PRINT_TEXT_WITH_GDI) | |
22 namespace { | |
23 | |
24 class ScopedState { | |
25 public: | |
26 ScopedState(HDC hDC, HFONT hFont) : m_hDC(hDC) { | |
27 m_iState = SaveDC(m_hDC); | |
28 m_hFont = SelectObject(m_hDC, hFont); | |
29 } | |
30 | |
31 ~ScopedState() { | |
32 HGDIOBJ hFont = SelectObject(m_hDC, m_hFont); | |
33 DeleteObject(hFont); | |
34 RestoreDC(m_hDC, m_iState); | |
35 } | |
36 | |
37 private: | |
38 HDC m_hDC; | |
39 HGDIOBJ m_hFont; | |
40 int m_iState; | |
41 | |
42 ScopedState(const ScopedState&) = delete; | |
43 void operator=(const ScopedState&) = delete; | |
44 }; | |
45 | |
46 } // namespace | |
47 | |
48 bool g_pdfium_print_text_with_gdi = false; | |
49 | |
50 PDFiumEnsureTypefaceCharactersAccessible g_pdfium_typeface_accessible_func = | |
51 nullptr; | |
52 #endif | |
53 | |
19 CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC) | 54 CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC) |
20 : CGdiDeviceDriver(hDC, FXDC_PRINTER), | 55 : CGdiDeviceDriver(hDC, FXDC_PRINTER), |
21 m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)), | 56 m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)), |
22 m_VertSize(::GetDeviceCaps(m_hDC, VERTSIZE)) {} | 57 m_VertSize(::GetDeviceCaps(m_hDC, VERTSIZE)) {} |
23 | 58 |
24 CGdiPrinterDriver::~CGdiPrinterDriver() {} | 59 CGdiPrinterDriver::~CGdiPrinterDriver() {} |
25 | 60 |
26 int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const { | 61 int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const { |
27 if (caps_id == FXDC_HORZ_SIZE) | 62 if (caps_id == FXDC_HORZ_SIZE) |
28 return m_HorzSize; | 63 return m_HorzSize; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 FXSYS_fabs(pMatrix->c) < 0.5f && pMatrix->d != 0) { | 174 FXSYS_fabs(pMatrix->c) < 0.5f && pMatrix->d != 0) { |
140 FX_BOOL bFlipX = pMatrix->a < 0; | 175 FX_BOOL bFlipX = pMatrix->a < 0; |
141 FX_BOOL bFlipY = pMatrix->d > 0; | 176 FX_BOOL bFlipY = pMatrix->d > 0; |
142 return StretchDIBits(pSource, color, | 177 return StretchDIBits(pSource, color, |
143 bFlipX ? full_rect.right : full_rect.left, | 178 bFlipX ? full_rect.right : full_rect.left, |
144 bFlipY ? full_rect.bottom : full_rect.top, | 179 bFlipY ? full_rect.bottom : full_rect.top, |
145 bFlipX ? -full_rect.Width() : full_rect.Width(), | 180 bFlipX ? -full_rect.Width() : full_rect.Width(), |
146 bFlipY ? -full_rect.Height() : full_rect.Height(), | 181 bFlipY ? -full_rect.Height() : full_rect.Height(), |
147 nullptr, 0, blend_type); | 182 nullptr, 0, blend_type); |
148 } | 183 } |
149 if (FXSYS_fabs(pMatrix->a) < 0.5f && FXSYS_fabs(pMatrix->d) < 0.5f) { | 184 if (FXSYS_fabs(pMatrix->a) >= 0.5f || FXSYS_fabs(pMatrix->d) >= 0.5f) |
150 std::unique_ptr<CFX_DIBitmap> pTransformed( | 185 return FALSE; |
151 pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0)); | 186 |
152 if (!pTransformed) | 187 std::unique_ptr<CFX_DIBitmap> pTransformed( |
188 pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0)); | |
189 if (!pTransformed) | |
190 return FALSE; | |
191 | |
192 return StretchDIBits(pTransformed.get(), color, full_rect.left, full_rect.top, | |
193 full_rect.Width(), full_rect.Height(), nullptr, 0, | |
194 blend_type); | |
195 } | |
196 | |
197 FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars, | |
198 const FXTEXT_CHARPOS* pCharPos, | |
199 CFX_Font* pFont, | |
200 CFX_FontCache* pCache, | |
201 const CFX_Matrix* pObject2Device, | |
202 FX_FLOAT font_size, | |
203 uint32_t color) { | |
204 #if defined(PDFIUM_PRINT_TEXT_WITH_GDI) | |
205 if (!g_pdfium_print_text_with_gdi) | |
206 return FALSE; | |
207 | |
208 if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont()) | |
209 return FALSE; | |
210 | |
211 // Font | |
212 // | |
213 // Note that |pFont| has the actual font to render with embedded within, but | |
214 // but unfortunately AddFontMemResourceEx() does not seem to cooperate. | |
215 // Loading font data to memory seems to work, but then enumerating the fonts | |
216 // fails to find it. This requires more investigation. In the meanwhile, | |
217 // assume the printing is happening on the machine that generated the PDF, so | |
Ilya Kulshin
2016/07/12 23:40:56
This doesn't sound like a safe assumption, especia
Lei Zhang
2016/07/13 00:01:05
This code path is gated on |g_pdfium_print_text_wi
| |
218 // the embedded font, if not a web font, is available through GDI anyway. | |
219 // TODO(thestig): Figure out why AddFontMemResourceEx() does not work. | |
220 // Generalize this method to work for all PDFs with embedded fonts. | |
221 // In sandboxed environments, font loading may not work at all, so this may be | |
222 // the best possible effort. | |
223 LOGFONT lf = {}; | |
224 lf.lfHeight = -font_size; | |
225 lf.lfWeight = pFont->IsBold() ? FW_BOLD : FW_NORMAL; | |
226 lf.lfItalic = pFont->IsItalic(); | |
227 lf.lfCharSet = DEFAULT_CHARSET; | |
228 | |
229 const CFX_WideString wsName = pFont->GetFaceName().UTF8Decode(); | |
230 int iNameLen = std::min(wsName.GetLength(), LF_FACESIZE - 1); | |
231 memcpy(lf.lfFaceName, wsName.c_str(), sizeof(lf.lfFaceName[0]) * iNameLen); | |
232 lf.lfFaceName[iNameLen] = 0; | |
233 | |
234 HFONT hFont = CreateFontIndirect(&lf); | |
235 if (!hFont) | |
236 return FALSE; | |
237 | |
238 ScopedState state(m_hDC, hFont); | |
239 size_t nTextMetricSize = GetOutlineTextMetrics(m_hDC, 0, nullptr); | |
240 if (nTextMetricSize == 0) { | |
241 // Give up and fail if there is no way to get the font to try again. | |
242 if (!g_pdfium_typeface_accessible_func) | |
153 return FALSE; | 243 return FALSE; |
154 | 244 |
155 return StretchDIBits(pTransformed.get(), color, full_rect.left, | 245 // Try to get the font. Any letter will do. |
156 full_rect.top, full_rect.Width(), full_rect.Height(), | 246 g_pdfium_typeface_accessible_func(&lf, L"A", 1); |
157 nullptr, 0, blend_type); | 247 nTextMetricSize = GetOutlineTextMetrics(m_hDC, 0, nullptr); |
248 if (nTextMetricSize == 0) | |
249 return FALSE; | |
158 } | 250 } |
251 | |
252 std::vector<BYTE> buf(nTextMetricSize); | |
253 OUTLINETEXTMETRIC* pTextMetric = | |
254 reinterpret_cast<OUTLINETEXTMETRIC*>(buf.data()); | |
255 if (GetOutlineTextMetrics(m_hDC, nTextMetricSize, pTextMetric) == 0) | |
256 return FALSE; | |
257 | |
258 // If the selected font is not the requested font, then bail out. This can | |
259 // happen with web fonts, for example. | |
260 wchar_t* wsSelectedName = reinterpret_cast<wchar_t*>( | |
261 buf.data() + reinterpret_cast<size_t>(pTextMetric->otmpFaceName)); | |
262 if (wsName != wsSelectedName) | |
263 return FALSE; | |
264 | |
265 // Transforms | |
266 SetGraphicsMode(m_hDC, GM_ADVANCED); | |
267 XFORM xform; | |
268 xform.eM11 = pObject2Device->GetA(); | |
269 xform.eM12 = pObject2Device->GetB(); | |
270 xform.eM21 = -pObject2Device->GetC(); | |
271 xform.eM22 = -pObject2Device->GetD(); | |
272 xform.eDx = pObject2Device->GetE(); | |
273 xform.eDy = pObject2Device->GetF(); | |
274 ModifyWorldTransform(m_hDC, &xform, MWT_LEFTMULTIPLY); | |
275 | |
276 // Color | |
277 int iUnusedAlpha; | |
278 FX_COLORREF rgb; | |
279 ArgbDecode(color, iUnusedAlpha, rgb); | |
280 SetTextColor(m_hDC, rgb); | |
281 SetBkMode(m_hDC, TRANSPARENT); | |
282 | |
283 // Text | |
284 CFX_WideString wsText; | |
285 for (int i = 0; i < nChars; ++i) { | |
286 // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary | |
287 // values from PDFs. | |
288 const FXTEXT_CHARPOS& charpos = pCharPos[i]; | |
289 ASSERT(charpos.m_OriginX == 0); | |
290 ASSERT(charpos.m_OriginY == 0); | |
291 ASSERT(charpos.m_AdjustMatrix[0] == 0); | |
292 ASSERT(charpos.m_AdjustMatrix[1] == 0); | |
293 ASSERT(charpos.m_AdjustMatrix[2] == 0); | |
294 ASSERT(charpos.m_AdjustMatrix[3] == 0); | |
295 wsText += charpos.m_GlyphIndex; | |
296 } | |
297 | |
298 // Draw | |
299 SetTextAlign(m_hDC, TA_LEFT | TA_BASELINE); | |
300 if (ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(), nChars, | |
301 nullptr)) { | |
302 return TRUE; | |
303 } | |
304 | |
305 // Give up and fail if there is no way to get the font to try again. | |
306 if (!g_pdfium_typeface_accessible_func) | |
307 return FALSE; | |
308 | |
309 // Try to get the font and draw again. | |
310 g_pdfium_typeface_accessible_func(&lf, wsText.c_str(), nChars); | |
311 return ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(), | |
312 nChars, nullptr); | |
313 #else | |
159 return FALSE; | 314 return FALSE; |
315 #endif | |
160 } | 316 } |
161 | 317 |
162 #endif | 318 #endif // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |
OLD | NEW |