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 // Set to true to enable printing text with GDI. | |
| 22 bool g_pdfium_print_text_with_gdi = false; | |
|
Lei Zhang
2016/06/30 07:54:08
dsinclair: Given the somewhat experimental status,
dsinclair
2016/06/30 13:31:57
Why not make it a compile option that's off by def
Lei Zhang
2016/06/30 22:20:09
It's more complicated, but done in patch set 2. Th
| |
| 23 | |
| 24 // Pointer to a helper function to make |font| with |text| of |text_length| | |
| 25 // accessible when printing text with GDI. This is useful in sandboxed | |
| 26 // environments where PDFium's access to GDI may be restricted. | |
| 27 typedef void (*PDFiumEnsureTypefaceCharactersAccessible)(const LOGFONT& font, | |
| 28 const wchar_t* text, | |
| 29 size_t text_length); | |
| 30 PDFiumEnsureTypefaceCharactersAccessible g_pdfium_typeface_accessible_func = | |
| 31 nullptr; | |
| 32 | |
| 19 CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC) | 33 CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC) |
| 20 : CGdiDeviceDriver(hDC, FXDC_PRINTER), | 34 : CGdiDeviceDriver(hDC, FXDC_PRINTER), |
| 21 m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)), | 35 m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)), |
| 22 m_VertSize(::GetDeviceCaps(m_hDC, VERTSIZE)) {} | 36 m_VertSize(::GetDeviceCaps(m_hDC, VERTSIZE)) {} |
| 23 | 37 |
| 24 CGdiPrinterDriver::~CGdiPrinterDriver() {} | 38 CGdiPrinterDriver::~CGdiPrinterDriver() {} |
| 25 | 39 |
| 26 int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const { | 40 int CGdiPrinterDriver::GetDeviceCaps(int caps_id) const { |
| 27 if (caps_id == FXDC_HORZ_SIZE) | 41 if (caps_id == FXDC_HORZ_SIZE) |
| 28 return m_HorzSize; | 42 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) { | 153 FXSYS_fabs(pMatrix->c) < 0.5f && pMatrix->d != 0) { |
| 140 FX_BOOL bFlipX = pMatrix->a < 0; | 154 FX_BOOL bFlipX = pMatrix->a < 0; |
| 141 FX_BOOL bFlipY = pMatrix->d > 0; | 155 FX_BOOL bFlipY = pMatrix->d > 0; |
| 142 return StretchDIBits(pSource, color, | 156 return StretchDIBits(pSource, color, |
| 143 bFlipX ? full_rect.right : full_rect.left, | 157 bFlipX ? full_rect.right : full_rect.left, |
| 144 bFlipY ? full_rect.bottom : full_rect.top, | 158 bFlipY ? full_rect.bottom : full_rect.top, |
| 145 bFlipX ? -full_rect.Width() : full_rect.Width(), | 159 bFlipX ? -full_rect.Width() : full_rect.Width(), |
| 146 bFlipY ? -full_rect.Height() : full_rect.Height(), | 160 bFlipY ? -full_rect.Height() : full_rect.Height(), |
| 147 nullptr, 0, blend_type); | 161 nullptr, 0, blend_type); |
| 148 } | 162 } |
| 149 if (FXSYS_fabs(pMatrix->a) < 0.5f && FXSYS_fabs(pMatrix->d) < 0.5f) { | 163 if (FXSYS_fabs(pMatrix->a) >= 0.5f || FXSYS_fabs(pMatrix->d) >= 0.5f) |
| 150 std::unique_ptr<CFX_DIBitmap> pTransformed( | 164 return FALSE; |
| 151 pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0)); | |
| 152 if (!pTransformed) | |
| 153 return FALSE; | |
| 154 | 165 |
| 155 return StretchDIBits(pTransformed.get(), color, full_rect.left, | 166 std::unique_ptr<CFX_DIBitmap> pTransformed( |
| 156 full_rect.top, full_rect.Width(), full_rect.Height(), | 167 pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0)); |
| 157 nullptr, 0, blend_type); | 168 if (!pTransformed) |
| 158 } | 169 return FALSE; |
| 159 return FALSE; | 170 |
| 171 return StretchDIBits(pTransformed.get(), color, full_rect.left, full_rect.top, | |
| 172 full_rect.Width(), full_rect.Height(), nullptr, 0, | |
| 173 blend_type); | |
| 160 } | 174 } |
| 161 | 175 |
| 162 #endif | 176 FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars, |
| 177 const FXTEXT_CHARPOS* pCharPos, | |
| 178 CFX_Font* pFont, | |
| 179 CFX_FontCache* pCache, | |
| 180 const CFX_Matrix* pObject2Device, | |
| 181 FX_FLOAT font_size, | |
| 182 uint32_t color) { | |
| 183 if (!g_pdfium_print_text_with_gdi) | |
| 184 return FALSE; | |
| 185 | |
| 186 if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont()) | |
| 187 return FALSE; | |
| 188 | |
| 189 // Font | |
| 190 // | |
| 191 // Note that |pFont| has the actual font to render with embedded within, but | |
|
dsinclair
2016/06/30 13:31:56
This sounds like more of a TODO?
Lei Zhang
2016/06/30 22:20:09
Done.
| |
| 192 // but unfortunately AddFontMemResourceEx() does not seem to cooperate. | |
| 193 // Loading font data to memory seems to work, but then enumerating the fonts | |
| 194 // fails to find it. This requires more investigation. In the meanwhile, | |
| 195 // assume the printing is happening on the machine that generated the PDF, so | |
| 196 // the embedded font is available through GDI anyway. | |
| 197 LOGFONT lf = {}; | |
| 198 lf.lfHeight = -font_size; | |
| 199 lf.lfWeight = pFont->IsBold() ? FW_BOLD : FW_NORMAL; | |
| 200 lf.lfItalic = pFont->IsItalic(); | |
| 201 lf.lfCharSet = DEFAULT_CHARSET; | |
| 202 | |
| 203 const CFX_WideString wsName = pFont->GetFaceName().UTF8Decode(); | |
| 204 int len = std::min(wsName.GetLength(), LF_FACESIZE - 1); | |
| 205 memcpy(lf.lfFaceName, wsName.c_str(), sizeof(lf.lfFaceName[0]) * len); | |
| 206 lf.lfFaceName[len] = 0; | |
| 207 | |
| 208 HFONT font = CreateFontIndirect(&lf); | |
| 209 if (!font) | |
| 210 return FALSE; | |
| 211 | |
| 212 int dc = SaveDC(m_hDC); | |
| 213 HGDIOBJ old_font = SelectObject(m_hDC, font); | |
| 214 | |
| 215 // Transforms | |
| 216 // | |
| 217 // This is known to work with PDFs generated via Skia's PDF generator. It | |
| 218 // obviously do not work for arbitrary PDFs. | |
|
dsinclair
2016/06/30 13:31:57
nit: s/do/does/
Lei Zhang
2016/06/30 22:20:09
Done.
| |
| 219 ASSERT(pObject2Device->GetB() == 0); | |
| 220 ASSERT(pObject2Device->GetC() == 0); | |
| 221 ASSERT(pObject2Device->GetA() == -pObject2Device->GetD()); | |
| 222 SetGraphicsMode(m_hDC, GM_ADVANCED); | |
| 223 XFORM xform = {}; | |
| 224 xform.eM11 = pObject2Device->GetA(); | |
| 225 xform.eM22 = pObject2Device->GetA(); | |
| 226 xform.eDx = pObject2Device->GetE(); | |
| 227 xform.eDy = pObject2Device->GetF(); | |
| 228 ModifyWorldTransform(m_hDC, &xform, MWT_LEFTMULTIPLY); | |
| 229 | |
| 230 // Color | |
| 231 int unused_alpha; | |
| 232 FX_COLORREF rgb; | |
| 233 ArgbDecode(color, unused_alpha, rgb); | |
| 234 SetTextColor(m_hDC, rgb); | |
| 235 SetBkMode(m_hDC, TRANSPARENT); | |
| 236 | |
| 237 // Text | |
| 238 CFX_WideString wstr; | |
| 239 for (int i = 0; i < nChars; ++i) { | |
| 240 // Same as above. Only works with PDFs from Skia's PDF generator. | |
| 241 const FXTEXT_CHARPOS& charpos = pCharPos[i]; | |
| 242 ASSERT(charpos.m_OriginX == 0); | |
| 243 ASSERT(charpos.m_OriginY == 0); | |
| 244 ASSERT(charpos.m_AdjustMatrix[0] == 0); | |
| 245 ASSERT(charpos.m_AdjustMatrix[1] == 0); | |
| 246 ASSERT(charpos.m_AdjustMatrix[2] == 0); | |
| 247 ASSERT(charpos.m_AdjustMatrix[3] == 0); | |
| 248 wstr += charpos.m_GlyphIndex; | |
| 249 } | |
| 250 | |
| 251 // Draw | |
| 252 SetTextAlign(m_hDC, TA_LEFT | TA_BASELINE); | |
| 253 BOOL ret = ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wstr.c_str(), | |
| 254 nChars, nullptr); | |
| 255 if (!ret) { | |
| 256 if (g_pdfium_typeface_accessible_func) { | |
| 257 g_pdfium_typeface_accessible_func(lf, wstr.c_str(), nChars); | |
| 258 ret = ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wstr.c_str(), | |
| 259 nChars, nullptr); | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 SelectObject(m_hDC, old_font); | |
| 264 DeleteObject(font); | |
| 265 RestoreDC(m_hDC, dc); | |
| 266 return ret; | |
| 267 } | |
| 268 | |
| 269 #endif // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ | |
| OLD | NEW |