Chromium Code Reviews| Index: core/fxge/win32/fx_win32_print.cpp |
| diff --git a/core/fxge/win32/fx_win32_print.cpp b/core/fxge/win32/fx_win32_print.cpp |
| index aef6062e73ec12ca290b7605f1e8a88054d6315c..7185a4e1469c574f2f2d3a52a88a7cd4588500ce 100644 |
| --- a/core/fxge/win32/fx_win32_print.cpp |
| +++ b/core/fxge/win32/fx_win32_print.cpp |
| @@ -10,12 +10,26 @@ |
| #include <windows.h> |
| +#include <algorithm> |
| + |
| #include "core/fxge/dib/dib_int.h" |
| #include "core/fxge/ge/fx_text_int.h" |
| #include "core/fxge/include/fx_freetype.h" |
| #include "core/fxge/include/fx_ge_win32.h" |
| #include "core/fxge/win32/win32_int.h" |
| +// Set to true to enable printing text with GDI. |
| +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
|
| + |
| +// Pointer to a helper function to make |font| with |text| of |text_length| |
| +// accessible when printing text with GDI. This is useful in sandboxed |
| +// environments where PDFium's access to GDI may be restricted. |
| +typedef void (*PDFiumEnsureTypefaceCharactersAccessible)(const LOGFONT& font, |
| + const wchar_t* text, |
| + size_t text_length); |
| +PDFiumEnsureTypefaceCharactersAccessible g_pdfium_typeface_accessible_func = |
| + nullptr; |
| + |
| CGdiPrinterDriver::CGdiPrinterDriver(HDC hDC) |
| : CGdiDeviceDriver(hDC, FXDC_PRINTER), |
| m_HorzSize(::GetDeviceCaps(m_hDC, HORZSIZE)), |
| @@ -146,17 +160,110 @@ FX_BOOL CGdiPrinterDriver::StartDIBits(const CFX_DIBSource* pSource, |
| bFlipY ? -full_rect.Height() : full_rect.Height(), |
| nullptr, 0, blend_type); |
| } |
| - if (FXSYS_fabs(pMatrix->a) < 0.5f && FXSYS_fabs(pMatrix->d) < 0.5f) { |
| - std::unique_ptr<CFX_DIBitmap> pTransformed( |
| - pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0)); |
| - if (!pTransformed) |
| - return FALSE; |
| + if (FXSYS_fabs(pMatrix->a) >= 0.5f || FXSYS_fabs(pMatrix->d) >= 0.5f) |
| + return FALSE; |
| - return StretchDIBits(pTransformed.get(), color, full_rect.left, |
| - full_rect.top, full_rect.Width(), full_rect.Height(), |
| - nullptr, 0, blend_type); |
| + std::unique_ptr<CFX_DIBitmap> pTransformed( |
| + pSource->SwapXY(pMatrix->c > 0, pMatrix->b < 0)); |
| + if (!pTransformed) |
| + return FALSE; |
| + |
| + return StretchDIBits(pTransformed.get(), color, full_rect.left, full_rect.top, |
| + full_rect.Width(), full_rect.Height(), nullptr, 0, |
| + blend_type); |
| +} |
| + |
| +FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars, |
| + const FXTEXT_CHARPOS* pCharPos, |
| + CFX_Font* pFont, |
| + CFX_FontCache* pCache, |
| + const CFX_Matrix* pObject2Device, |
| + FX_FLOAT font_size, |
| + uint32_t color) { |
| + if (!g_pdfium_print_text_with_gdi) |
| + return FALSE; |
| + |
| + if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont()) |
| + return FALSE; |
| + |
| + // Font |
| + // |
| + // 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.
|
| + // but unfortunately AddFontMemResourceEx() does not seem to cooperate. |
| + // Loading font data to memory seems to work, but then enumerating the fonts |
| + // fails to find it. This requires more investigation. In the meanwhile, |
| + // assume the printing is happening on the machine that generated the PDF, so |
| + // the embedded font is available through GDI anyway. |
| + LOGFONT lf = {}; |
| + lf.lfHeight = -font_size; |
| + lf.lfWeight = pFont->IsBold() ? FW_BOLD : FW_NORMAL; |
| + lf.lfItalic = pFont->IsItalic(); |
| + lf.lfCharSet = DEFAULT_CHARSET; |
| + |
| + const CFX_WideString wsName = pFont->GetFaceName().UTF8Decode(); |
| + int len = std::min(wsName.GetLength(), LF_FACESIZE - 1); |
| + memcpy(lf.lfFaceName, wsName.c_str(), sizeof(lf.lfFaceName[0]) * len); |
| + lf.lfFaceName[len] = 0; |
| + |
| + HFONT font = CreateFontIndirect(&lf); |
| + if (!font) |
| + return FALSE; |
| + |
| + int dc = SaveDC(m_hDC); |
| + HGDIOBJ old_font = SelectObject(m_hDC, font); |
| + |
| + // Transforms |
| + // |
| + // This is known to work with PDFs generated via Skia's PDF generator. It |
| + // 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.
|
| + ASSERT(pObject2Device->GetB() == 0); |
| + ASSERT(pObject2Device->GetC() == 0); |
| + ASSERT(pObject2Device->GetA() == -pObject2Device->GetD()); |
| + SetGraphicsMode(m_hDC, GM_ADVANCED); |
| + XFORM xform = {}; |
| + xform.eM11 = pObject2Device->GetA(); |
| + xform.eM22 = pObject2Device->GetA(); |
| + xform.eDx = pObject2Device->GetE(); |
| + xform.eDy = pObject2Device->GetF(); |
| + ModifyWorldTransform(m_hDC, &xform, MWT_LEFTMULTIPLY); |
| + |
| + // Color |
| + int unused_alpha; |
| + FX_COLORREF rgb; |
| + ArgbDecode(color, unused_alpha, rgb); |
| + SetTextColor(m_hDC, rgb); |
| + SetBkMode(m_hDC, TRANSPARENT); |
| + |
| + // Text |
| + CFX_WideString wstr; |
| + for (int i = 0; i < nChars; ++i) { |
| + // Same as above. Only works with PDFs from Skia's PDF generator. |
| + const FXTEXT_CHARPOS& charpos = pCharPos[i]; |
| + ASSERT(charpos.m_OriginX == 0); |
| + ASSERT(charpos.m_OriginY == 0); |
| + ASSERT(charpos.m_AdjustMatrix[0] == 0); |
| + ASSERT(charpos.m_AdjustMatrix[1] == 0); |
| + ASSERT(charpos.m_AdjustMatrix[2] == 0); |
| + ASSERT(charpos.m_AdjustMatrix[3] == 0); |
| + wstr += charpos.m_GlyphIndex; |
| + } |
| + |
| + // Draw |
| + SetTextAlign(m_hDC, TA_LEFT | TA_BASELINE); |
| + BOOL ret = ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wstr.c_str(), |
| + nChars, nullptr); |
| + if (!ret) { |
| + if (g_pdfium_typeface_accessible_func) { |
| + g_pdfium_typeface_accessible_func(lf, wstr.c_str(), nChars); |
| + ret = ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wstr.c_str(), |
| + nChars, nullptr); |
| + } |
| } |
| - return FALSE; |
| + |
| + SelectObject(m_hDC, old_font); |
| + DeleteObject(font); |
| + RestoreDC(m_hDC, dc); |
| + return ret; |
| } |
| -#endif |
| +#endif // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_ |