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_ |