[SkiaPaths] Avoid overlapping when drawing text.

SkiaPaths draws text according to each glyph's default font width
unless horizontal scale is specified. Sometimes a character's width
defined in the pdf file is smaller than the character's default font
width, which makes it overlap with other characters. Add a process to
scale each individual character by the ratio of its actual width in the
pdf file and its default font width to avoid overlapping.

When cache is enabled, sometimes text is not rendered even after its
CFX_RenderDevice is destroyed and its font becomes unavailable. To
guarantee a valid font before finishing drawing the text object, call
Flush() in CFDE_TextOut::DrawString() before CFX_RenderDevice structure
is released.

Bug: pdfium:1351
Change-Id: Ib693e5b1a9d94c7889a9285cd047c07f52c16085
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/60510
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 474b7cf..a073694 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -890,6 +890,7 @@
       m_drawMatrix = matrix;
       m_drawIndex = m_commandIndex;
       m_type = Accumulator::kText;
+      m_pFont = pFont;
     }
     if (!hasRSX && !m_rsxform.isEmpty())
       FlushText();
@@ -910,6 +911,7 @@
           cur_index, {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip});
       m_charDetails.SetGlyphAt(cur_index,
                                static_cast<uint16_t>(cp.m_GlyphIndex));
+      m_charDetails.SetFontCharWidthAt(cur_index, cp.m_FontCharWidth);
 #if defined(OS_MACOSX)
       if (cp.m_ExtGID) {
         m_charDetails.SetGlyphAt(cur_index, static_cast<uint16_t>(cp.m_ExtGID));
@@ -980,22 +982,34 @@
     printf("\n");
 #endif
 
-    sk_sp<SkTextBlob> blob;
     if (m_rsxform.count()) {
-      blob = SkTextBlob::MakeFromRSXform(glyphs.begin(), glyphs.bytes(),
-                                         m_rsxform.begin(), font,
-                                         SkTextEncoding::kGlyphID);
+      sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromRSXform(
+          glyphs.begin(), glyphs.bytes(), m_rsxform.begin(), font,
+          SkTextEncoding::kGlyphID);
+      skCanvas->drawTextBlob(blob, 0, 0, skPaint);
     } else {
       const SkTDArray<SkPoint>& positions = m_charDetails.GetPositions();
-      blob = SkTextBlob::MakeFromPosText(glyphs.begin(), glyphs.bytes(),
-                                         positions.begin(), font,
-                                         SkTextEncoding::kGlyphID);
+      const SkTDArray<uint32_t>& widths = m_charDetails.GetFontCharWidths();
+      for (int i = 0; i < m_charDetails.Count(); ++i) {
+        uint32_t font_glyph_width =
+            m_pFont ? m_pFont->GetGlyphWidth(glyphs[i]) : 0;
+        uint32_t pdf_glyph_width = widths[i];
+        if (font_glyph_width && pdf_glyph_width &&
+            font_glyph_width > pdf_glyph_width) {
+          font.setScaleX(SkIntToScalar(pdf_glyph_width) / font_glyph_width);
+        } else {
+          font.setScaleX(SkIntToScalar(1));
+        }
+        sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText(
+            &glyphs[i], sizeof(glyphs[i]), font, SkTextEncoding::kGlyphID);
+        skCanvas->drawTextBlob(blob, positions[i].fX, positions[i].fY, skPaint);
+      }
     }
-    skCanvas->drawTextBlob(blob, 0, 0, skPaint);
 
     m_drawIndex = INT_MAX;
     m_type = Accumulator::kNone;
     m_drawMatrix = CFX_Matrix();
+    m_pFont = nullptr;
     m_italicAngle = 0;
   }
 
@@ -1448,6 +1462,12 @@
     }
     const SkTDArray<uint16_t>& GetGlyphs() const { return m_glyphs; }
     void SetGlyphAt(int index, uint16_t glyph) { m_glyphs[index] = glyph; }
+    const SkTDArray<uint32_t>& GetFontCharWidths() const {
+      return m_fontCharWidths;
+    }
+    void SetFontCharWidthAt(int index, uint32_t width) {
+      m_fontCharWidths[index] = width;
+    }
     int Count() const {
       ASSERT(m_positions.count() == m_glyphs.count());
       return m_glyphs.count();
@@ -1456,11 +1476,14 @@
       ASSERT(count >= 0);
       m_positions.setCount(count);
       m_glyphs.setCount(count);
+      m_fontCharWidths.setCount(count);
     }
 
    private:
     SkTDArray<SkPoint> m_positions;  // accumulator for text positions
     SkTDArray<uint16_t> m_glyphs;    // accumulator for text glyphs
+    // accumulator for glyphs' width defined in pdf
+    SkTDArray<uint32_t> m_fontCharWidths;
   };
 
   SkTArray<SkPath> m_clips;        // stack of clips that may be reused
@@ -1469,6 +1492,7 @@
   SkTDArray<SkRSXform> m_rsxform;  // accumulator for txt rotate/scale/translate
   SkPath m_skPath;                 // accumulator for path contours
   SkPath m_skEmptyPath;            // used as placehold in the clips array
+  UnownedPtr<CFX_Font> m_pFont;
   CFX_Matrix m_drawMatrix;
   CFX_GraphStateData m_clipState;
   CFX_GraphStateData m_drawState;
@@ -1724,7 +1748,7 @@
                                        font, SkTextEncoding::kGlyphID);
           m_pCanvas->drawTextBlob(blob, positions[index].fX,
                                   positions[index].fY, paint);
-          font.setScaleX(1);
+          font.setScaleX(SkIntToScalar(1));
         } else {
           SkAutoCanvasRestore scoped_save_restore2(m_pCanvas, /*doSave=*/true);
           SkMatrix adjust;
@@ -1749,10 +1773,23 @@
       }
     }
   } else {
-    m_pCanvas->drawTextBlob(SkTextBlob::MakeFromPosText(
-                                glyphs.begin(), nChars * 2, positions.begin(),
-                                font, SkTextEncoding::kGlyphID),
-                            0, 0, paint);
+    for (int index = 0; index < nChars; ++index) {
+      const TextCharPos& cp = pCharPos[index];
+      uint32_t font_glyph_width =
+          pFont ? pFont->GetGlyphWidth(cp.m_GlyphIndex) : 0;
+      uint32_t pdf_glyph_width = cp.m_FontCharWidth;
+      if (font_glyph_width && pdf_glyph_width &&
+          font_glyph_width > pdf_glyph_width) {
+        font.setScaleX(SkIntToScalar(pdf_glyph_width) / font_glyph_width);
+      } else {
+        font.setScaleX(SkIntToScalar(1));
+      }
+      auto blob =
+          SkTextBlob::MakeFromText(&glyphs[index], sizeof(glyphs[index]), font,
+                                   SkTextEncoding::kGlyphID);
+      m_pCanvas->drawTextBlob(blob, positions[index].fX, positions[index].fY,
+                              paint);
+    }
   }
 
   return true;
diff --git a/xfa/fde/cfde_textout.cpp b/xfa/fde/cfde_textout.cpp
index 5616d8d..cc7d6dc 100644
--- a/xfa/fde/cfde_textout.cpp
+++ b/xfa/fde/cfde_textout.cpp
@@ -114,6 +114,9 @@
     bRet = device->DrawNormalText(iCurCount, pCurCP, font, -fFontSize, matrix,
                                   color, FXTEXT_CLEARTYPE);
   }
+#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
+  device->Flush(false);
+#endif
 
   return bRet;
 }