Chromium Code Reviews| 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 |