Add heuristic for improving text rendering in CPDF_CharPosList::Load

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 <thestig@chromium.org>
Commit-Queue: Nicolás Peña <npm@chromium.org>
diff --git a/DEPS b/DEPS
index 7cecfe5..67159e0 100644
--- a/DEPS
+++ b/DEPS
@@ -19,7 +19,7 @@
   '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 1faa4ec..bdd3464 100644
--- a/core/fpdfapi/font/cpdf_font.cpp
+++ b/core/fpdfapi/font/cpdf_font.cpp
@@ -159,6 +159,10 @@
   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 1fef77b..f705422 100644
--- a/core/fpdfapi/font/cpdf_font.h
+++ b/core/fpdfapi/font/cpdf_font.h
@@ -61,6 +61,7 @@
   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 ebf2cb6..a6c3ba0 100644
--- a/core/fpdfapi/font/cpdf_simplefont.cpp
+++ b/core/fpdfapi/font/cpdf_simplefont.cpp
@@ -212,3 +212,7 @@
     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 3e414fa..6a22f46 100644
--- a/core/fpdfapi/font/cpdf_simplefont.h
+++ b/core/fpdfapi/font/cpdf_simplefont.h
@@ -29,6 +29,8 @@
 
   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 d4c6b3b..68df46b 100644
--- a/core/fpdfapi/render/cpdf_charposlist.cpp
+++ b/core/fpdfapi/render/cpdf_charposlist.cpp
@@ -44,13 +44,16 @@
     charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode);
     GlyphID = charpos.m_ExtGID;
 #endif
+    CFX_Font* pCurrentFont;
     if (GlyphID != static_cast<uint32_t>(-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 @@
 
     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<float>(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 @@
 
     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;