From 4db9046e56c884a350fa2c5087f8d5b8110463c4 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Mon, 19 Jun 2017 17:07:40 -0400 Subject: Add heuristic for improving text rendering in CPDF_CharPosList::Load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL uses the following algorithm for improving substitute font spacing (we are assuming the text layout is horizontal): * Calculate PDFWidth, the width that the PDF says the glyph should have. * Calculate FTWidth, the width calculated by freetype for the glyph, using the substitute font that we'll use to render it. Note that some embedded fonts have PDFWidth == FTWidth + 1, so we consider that to be matching widths. * If PDFWidth > FTWidth + 1 , move the x coordinate by the difference / 2 so that the glyph is rendered in a more centered spot and the text looks better. * If PDFWidth < FTWidth, transform the glyph horizontally by PDFWidth / FTWidth so that the glyph gets compressed and does not overlap with surrounding glyphs. Bug: chromium:431507 Change-Id: Ia378344253fabe44d93af4daab98bb3b7bca22de Reviewed-on: https://pdfium-review.googlesource.com/6630 Reviewed-by: Lei Zhang Commit-Queue: Nicolás Peña --- DEPS | 2 +- core/fpdfapi/font/cpdf_font.cpp | 4 ++++ core/fpdfapi/font/cpdf_font.h | 1 + core/fpdfapi/font/cpdf_simplefont.cpp | 4 ++++ core/fpdfapi/font/cpdf_simplefont.h | 2 ++ core/fpdfapi/render/cpdf_charposlist.cpp | 32 ++++++++++++++++++++++++++++++-- 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/DEPS b/DEPS index 7cecfe542e..67159e016c 100644 --- a/DEPS +++ b/DEPS @@ -19,7 +19,7 @@ vars = { 'jinja2_revision': 'd34383206fa42d52faa10bb9931d6d538f3a57e0', 'jpeg_turbo_revision': '7260e4d8b8e1e40b17f03fafdf1cd83296900f76', 'markupsafe_revision': '8f45f5cfa0009d2a70589bcda0349b8cb2b72783', - 'pdfium_tests_revision': '5379e0a6580443318c8192cdfc78a76e880ca3f6', + 'pdfium_tests_revision': '692df048179862d2e2eae2492e33a4673debe8bc', 'skia_revision': 'bb581ce30f55360fd3a12e7f5aa1fe324b16d085', 'tools_memory_revision': '427f10475e1a8d72424c29d00bf689122b738e5d', 'trace_event_revision': '06294c8a4a6f744ef284cd63cfe54dbf61eea290', diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp index 1faa4ec4be..bdd3464ed2 100644 --- a/core/fpdfapi/font/cpdf_font.cpp +++ b/core/fpdfapi/font/cpdf_font.cpp @@ -159,6 +159,10 @@ uint32_t CPDF_Font::CharCodeFromUnicode(wchar_t unicode) const { return m_pToUnicodeMap ? m_pToUnicodeMap->ReverseLookup(unicode) : 0; } +bool CPDF_Font::HasFontWidths() const { + return true; +} + void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) { m_Flags = pFontDesc->GetIntegerFor("Flags", FXFONT_NONSYMBOLIC); int ItalicAngle = 0; diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h index 1fef77b322..f70542223c 100644 --- a/core/fpdfapi/font/cpdf_font.h +++ b/core/fpdfapi/font/cpdf_font.h @@ -61,6 +61,7 @@ class CPDF_Font { virtual int GlyphFromCharCodeExt(uint32_t charcode); virtual CFX_WideString UnicodeFromCharCode(uint32_t charcode) const; virtual uint32_t CharCodeFromUnicode(wchar_t Unicode) const; + virtual bool HasFontWidths() const; const CFX_ByteString& GetBaseFont() const { return m_BaseFont; } CFX_SubstFont* GetSubstFont() const { return m_Font.GetSubstFont(); } diff --git a/core/fpdfapi/font/cpdf_simplefont.cpp b/core/fpdfapi/font/cpdf_simplefont.cpp index ebf2cb65c7..a6c3ba0547 100644 --- a/core/fpdfapi/font/cpdf_simplefont.cpp +++ b/core/fpdfapi/font/cpdf_simplefont.cpp @@ -212,3 +212,7 @@ uint32_t CPDF_SimpleFont::CharCodeFromUnicode(wchar_t unicode) const { return ret; return m_Encoding.CharCodeFromUnicode(unicode); } + +bool CPDF_SimpleFont::HasFontWidths() const { + return !m_bUseFontWidth; +} diff --git a/core/fpdfapi/font/cpdf_simplefont.h b/core/fpdfapi/font/cpdf_simplefont.h index 3e414fa788..6a22f46966 100644 --- a/core/fpdfapi/font/cpdf_simplefont.h +++ b/core/fpdfapi/font/cpdf_simplefont.h @@ -29,6 +29,8 @@ class CPDF_SimpleFont : public CPDF_Font { CPDF_FontEncoding* GetEncoding() { return &m_Encoding; } + bool HasFontWidths() const override; + protected: virtual void LoadGlyphMap() = 0; diff --git a/core/fpdfapi/render/cpdf_charposlist.cpp b/core/fpdfapi/render/cpdf_charposlist.cpp index d4c6b3b5f9..68df46bdad 100644 --- a/core/fpdfapi/render/cpdf_charposlist.cpp +++ b/core/fpdfapi/render/cpdf_charposlist.cpp @@ -44,13 +44,16 @@ void CPDF_CharPosList::Load(const std::vector& charCodes, charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode); GlyphID = charpos.m_ExtGID; #endif + CFX_Font* pCurrentFont; if (GlyphID != static_cast(-1)) { charpos.m_FallbackFontPosition = -1; + pCurrentFont = pFont->GetFont(); } else { charpos.m_FallbackFontPosition = pFont->FallbackFontFromCharcode(CharCode); charpos.m_GlyphIndex = pFont->FallbackGlyphFromCharcode( charpos.m_FallbackFontPosition, CharCode); + pCurrentFont = pFont->GetFontFallback(charpos.m_FallbackFontPosition); #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ charpos.m_ExtGID = charpos.m_GlyphIndex; #endif @@ -63,6 +66,29 @@ void CPDF_CharPosList::Load(const std::vector& charCodes, charpos.m_Origin = CFX_PointF(iChar ? charPos[iChar - 1] : 0, 0); charpos.m_bGlyphAdjust = false; + + float scalingFactor = 1.0f; + if (!pFont->IsEmbedded() && pFont->HasFontWidths() && !bVertWriting && + !(pCurrentFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_MM)) { + int pdfGlyphWidth = pFont->GetCharWidthF(CharCode); + int ftGlyphWidth = + pCurrentFont ? pCurrentFont->GetGlyphWidth(charpos.m_GlyphIndex) : 0; + if (ftGlyphWidth && pdfGlyphWidth > ftGlyphWidth + 1) { + // Move the initial x position by half of the excess (transformed to + // text space coordinates). + charpos.m_Origin.x += + (pdfGlyphWidth - ftGlyphWidth) * FontSize / 2000.0f; + } else if (pdfGlyphWidth && ftGlyphWidth && + pdfGlyphWidth < ftGlyphWidth) { + scalingFactor = static_cast(pdfGlyphWidth) / ftGlyphWidth; + ASSERT(scalingFactor >= 0.0f); + charpos.m_AdjustMatrix[0] = scalingFactor; + charpos.m_AdjustMatrix[1] = 0.0f; + charpos.m_AdjustMatrix[2] = 0.0f; + charpos.m_AdjustMatrix[3] = 1.0f; + charpos.m_bGlyphAdjust = true; + } + } if (!pCIDFont) continue; @@ -79,9 +105,11 @@ void CPDF_CharPosList::Load(const std::vector& charCodes, const uint8_t* pTransform = pCIDFont->GetCIDTransform(CID); if (pTransform && !bVert) { - charpos.m_AdjustMatrix[0] = pCIDFont->CIDTransformToFloat(pTransform[0]); + charpos.m_AdjustMatrix[0] = + pCIDFont->CIDTransformToFloat(pTransform[0]) * scalingFactor; + charpos.m_AdjustMatrix[1] = + pCIDFont->CIDTransformToFloat(pTransform[1]) * scalingFactor; charpos.m_AdjustMatrix[2] = pCIDFont->CIDTransformToFloat(pTransform[2]); - charpos.m_AdjustMatrix[1] = pCIDFont->CIDTransformToFloat(pTransform[1]); charpos.m_AdjustMatrix[3] = pCIDFont->CIDTransformToFloat(pTransform[3]); charpos.m_Origin.x += pCIDFont->CIDTransformToFloat(pTransform[4]) * FontSize; -- cgit v1.2.3