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 16a429c636a6ed8ee3db40248efb291941ce9b5c..207ff24552e163d66f9c97b6bb07cc728f61740f 100644 |
--- a/core/fxge/win32/fx_win32_print.cpp |
+++ b/core/fxge/win32/fx_win32_print.cpp |
@@ -209,6 +209,10 @@ FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars, |
if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont()) |
return FALSE; |
+ // Scale factor used to minimize the kerning problems caused by rounding |
+ // errors below. Value choosen based on the title of https://crbug.com/18383 |
+ const double kScaleFactor = 10; |
+ |
// Font |
// |
// Note that |pFont| has the actual font to render with embedded within, but |
@@ -222,7 +226,7 @@ FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars, |
// In sandboxed environments, font loading may not work at all, so this may be |
// the best possible effort. |
LOGFONT lf = {}; |
- lf.lfHeight = -font_size; |
+ lf.lfHeight = -font_size * kScaleFactor; |
lf.lfWeight = pFont->IsBold() ? FW_BOLD : FW_NORMAL; |
lf.lfItalic = pFont->IsItalic(); |
lf.lfCharSet = DEFAULT_CHARSET; |
@@ -266,10 +270,10 @@ FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars, |
// Transforms |
SetGraphicsMode(m_hDC, GM_ADVANCED); |
XFORM xform; |
- xform.eM11 = pObject2Device->GetA(); |
- xform.eM12 = pObject2Device->GetB(); |
- xform.eM21 = -pObject2Device->GetC(); |
- xform.eM22 = -pObject2Device->GetD(); |
+ xform.eM11 = pObject2Device->GetA() / kScaleFactor; |
+ xform.eM12 = pObject2Device->GetB() / kScaleFactor; |
+ xform.eM21 = -pObject2Device->GetC() / kScaleFactor; |
+ xform.eM22 = -pObject2Device->GetD() / kScaleFactor; |
xform.eDx = pObject2Device->GetE(); |
xform.eDy = pObject2Device->GetF(); |
ModifyWorldTransform(m_hDC, &xform, MWT_LEFTMULTIPLY); |
@@ -283,23 +287,32 @@ FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars, |
// Text |
CFX_WideString wsText; |
+ std::vector<INT> spacing(nChars); |
+ FX_FLOAT fPreviousOriginX = 0; |
for (int i = 0; i < nChars; ++i) { |
// Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary |
// values from PDFs. |
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); |
+ ASSERT(charpos.m_OriginY == 0); |
+ |
+ // Round the spacing to the nearest integer, but keep track of the rounding |
+ // error for calculating the next spacing value. |
+ FX_FLOAT fOriginX = charpos.m_OriginX * kScaleFactor; |
+ FX_FLOAT fPixelSpacing = fOriginX - fPreviousOriginX; |
+ spacing[i] = FXSYS_round(fPixelSpacing); |
+ fPreviousOriginX = fOriginX - (fPixelSpacing - spacing[i]); |
+ |
wsText += charpos.m_GlyphIndex; |
} |
// Draw |
SetTextAlign(m_hDC, TA_LEFT | TA_BASELINE); |
if (ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(), nChars, |
- nullptr)) { |
+ nChars > 1 ? &spacing[1] : nullptr)) { |
return TRUE; |
} |
@@ -310,7 +323,7 @@ FX_BOOL CGdiPrinterDriver::DrawDeviceText(int nChars, |
// Try to get the font and draw again. |
g_pdfium_typeface_accessible_func(&lf, wsText.c_str(), nChars); |
return ExtTextOutW(m_hDC, 0, 0, ETO_GLYPH_INDEX, nullptr, wsText.c_str(), |
- nChars, nullptr); |
+ nChars, nChars > 1 ? &spacing[1] : nullptr); |
#else |
return FALSE; |
#endif |