Create struct CFX_TextRenderOptions to represent text rendering options.

This CL creates a new structure CFX_TextRenderOptions, to represent the
following option flags which are used for text rendering:

  FXFONT_CIDFONT
  FXTEXT_CLEARTYPE
  FXTEXT_BGR_STRIPE
  FXTEXT_NO_NATIVETEXT
  FXTEXT_NOSMOOTH

This will help remove integer flag |text_flags| in DrawNormalText(),
reduce related bitwise operations, and make it easier to change
rendering options in the future.

Bug: pdfium:1531
Change-Id: I21cc9c57fcf745a01c0b9f519f01cbd9a674941c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70051
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Hui Yingst <nigi@chromium.org>
diff --git a/core/fpdfapi/render/cpdf_textrenderer.cpp b/core/fpdfapi/render/cpdf_textrenderer.cpp
index 2398c7c..24c0e5b 100644
--- a/core/fpdfapi/render/cpdf_textrenderer.cpp
+++ b/core/fpdfapi/render/cpdf_textrenderer.cpp
@@ -24,21 +24,23 @@
   return position == -1 ? pFont->GetFont() : pFont->GetFontFallback(position);
 }
 
-int GetTextRenderOptionsHelper(const CPDF_Font* pFont,
-                               const CPDF_RenderOptions& options) {
-  int text_options = 0;
+CFX_TextRenderOptions GetTextRenderOptionsHelper(
+    const CPDF_Font* pFont,
+    const CPDF_RenderOptions& options) {
+  CFX_TextRenderOptions text_options;
+
   if (pFont->IsCIDFont())
-    text_options |= FXFONT_CIDFONT;
+    text_options.font_is_cid = true;
 
   if (options.GetOptions().bNoTextSmooth) {
-    text_options |= FXTEXT_NOSMOOTH;
+    text_options.aliasing_type = CFX_TextRenderOptions::kAliasing;
   } else if (options.GetOptions().bClearType) {
-    text_options |= FXTEXT_CLEARTYPE;
-    if (options.GetOptions().bBGRStripe)
-      text_options |= FXTEXT_BGR_STRIPE;
+    text_options.aliasing_type = options.GetOptions().bBGRStripe
+                                     ? CFX_TextRenderOptions::kBgrStripe
+                                     : CFX_TextRenderOptions::kLcd;
   }
   if (options.GetOptions().bNoNativeText)
-    text_options |= FXTEXT_NO_NATIVETEXT;
+    text_options.native_text = false;
 
   return text_options;
 }
@@ -140,7 +142,8 @@
   if (pos.empty())
     return true;
 
-  int fxge_flags = GetTextRenderOptionsHelper(pFont, options);
+  CFX_TextRenderOptions text_options =
+      GetTextRenderOptionsHelper(pFont, options);
   bool bDraw = true;
   int32_t fontPosition = pos[0].m_FallbackFontPosition;
   size_t startIndex = 0;
@@ -152,7 +155,7 @@
     CFX_Font* font = GetFont(pFont, fontPosition);
     if (!pDevice->DrawNormalText(i - startIndex, &pos[startIndex], font,
                                  font_size, mtText2Device, fill_argb,
-                                 fxge_flags)) {
+                                 text_options)) {
       bDraw = false;
     }
     fontPosition = curFontPosition;
@@ -161,7 +164,7 @@
   CFX_Font* font = GetFont(pFont, fontPosition);
   if (!pDevice->DrawNormalText(pos.size() - startIndex, &pos[startIndex], font,
                                font_size, mtText2Device, fill_argb,
-                               fxge_flags)) {
+                               text_options)) {
     bDraw = false;
   }
   return bDraw;
diff --git a/core/fxge/BUILD.gn b/core/fxge/BUILD.gn
index 98ec1b5..3d1d0a1 100644
--- a/core/fxge/BUILD.gn
+++ b/core/fxge/BUILD.gn
@@ -53,6 +53,8 @@
     "cfx_renderdevice.h",
     "cfx_substfont.cpp",
     "cfx_substfont.h",
+    "cfx_textrenderoptions.cpp",
+    "cfx_textrenderoptions.h",
     "cfx_unicodeencoding.cpp",
     "cfx_unicodeencoding.h",
     "dib/cfx_bitmapcomposer.cpp",
diff --git a/core/fxge/cfx_font.cpp b/core/fxge/cfx_font.cpp
index 12c1d32..0782c51 100644
--- a/core/fxge/cfx_font.cpp
+++ b/core/fxge/cfx_font.cpp
@@ -709,15 +709,16 @@
   return pPath.release();
 }
 
-const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(uint32_t glyph_index,
-                                                 bool bFontStyle,
-                                                 const CFX_Matrix& matrix,
-                                                 uint32_t dest_width,
-                                                 int anti_alias,
-                                                 int* pTextFlags) const {
+const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(
+    uint32_t glyph_index,
+    bool bFontStyle,
+    const CFX_Matrix& matrix,
+    uint32_t dest_width,
+    int anti_alias,
+    CFX_TextRenderOptions* text_options) const {
   return GetOrCreateGlyphCache()->LoadGlyphBitmap(this, glyph_index, bFontStyle,
                                                   matrix, dest_width,
-                                                  anti_alias, pTextFlags);
+                                                  anti_alias, text_options);
 }
 
 const CFX_PathData* CFX_Font::LoadGlyphPath(uint32_t glyph_index,
diff --git a/core/fxge/cfx_font.h b/core/fxge/cfx_font.h
index 45ea79b..e3822b4 100644
--- a/core/fxge/cfx_font.h
+++ b/core/fxge/cfx_font.h
@@ -15,6 +15,7 @@
 #include "core/fxcrt/fx_coordinates.h"
 #include "core/fxcrt/fx_memory_wrappers.h"
 #include "core/fxge/cfx_face.h"
+#include "core/fxge/cfx_textrenderoptions.h"
 #include "core/fxge/fx_freetype.h"
 #include "third_party/base/span.h"
 
@@ -68,12 +69,13 @@
 #endif  // !defined(OS_WIN)
 #endif  // defined(PDF_ENABLE_XFA)
 
-  const CFX_GlyphBitmap* LoadGlyphBitmap(uint32_t glyph_index,
-                                         bool bFontStyle,
-                                         const CFX_Matrix& matrix,
-                                         uint32_t dest_width,
-                                         int anti_alias,
-                                         int* pTextFlags) const;
+  const CFX_GlyphBitmap* LoadGlyphBitmap(
+      uint32_t glyph_index,
+      bool bFontStyle,
+      const CFX_Matrix& matrix,
+      uint32_t dest_width,
+      int anti_alias,
+      CFX_TextRenderOptions* text_options) const;
   const CFX_PathData* LoadGlyphPath(uint32_t glyph_index,
                                     uint32_t dest_width) const;
 
diff --git a/core/fxge/cfx_glyphcache.cpp b/core/fxge/cfx_glyphcache.cpp
index b48697b..57bb0d6 100644
--- a/core/fxge/cfx_glyphcache.cpp
+++ b/core/fxge/cfx_glyphcache.cpp
@@ -246,19 +246,20 @@
   return pGlyphPath;
 }
 
-const CFX_GlyphBitmap* CFX_GlyphCache::LoadGlyphBitmap(const CFX_Font* pFont,
-                                                       uint32_t glyph_index,
-                                                       bool bFontStyle,
-                                                       const CFX_Matrix& matrix,
-                                                       uint32_t dest_width,
-                                                       int anti_alias,
-                                                       int* pTextFlags) {
+const CFX_GlyphBitmap* CFX_GlyphCache::LoadGlyphBitmap(
+    const CFX_Font* pFont,
+    uint32_t glyph_index,
+    bool bFontStyle,
+    const CFX_Matrix& matrix,
+    uint32_t dest_width,
+    int anti_alias,
+    CFX_TextRenderOptions* text_options) {
   if (glyph_index == kInvalidGlyphIndex)
     return nullptr;
 
   UniqueKeyGen keygen;
 #if defined(OS_MACOSX)
-  const bool bNative = !(*pTextFlags & FXTEXT_NO_NATIVETEXT);
+  const bool bNative = text_options->native_text;
 #else
   const bool bNative = false;
 #endif
@@ -267,7 +268,7 @@
 
 #if defined(OS_MACOSX) && !defined _SKIA_SUPPORT_ && \
     !defined _SKIA_SUPPORT_PATHS_
-  const bool bDoLookUp = !!(*pTextFlags & FXTEXT_NO_NATIVETEXT);
+  const bool bDoLookUp = !text_options->native_text;
 #else
   const bool bDoLookUp = true;
 #endif
@@ -308,7 +309,7 @@
   }
   GenKey(&keygen, pFont, matrix, dest_width, anti_alias, /*bNative=*/false);
   ByteString FaceGlyphsKey2(keygen.key_, keygen.key_len_);
-  *pTextFlags |= FXTEXT_NO_NATIVETEXT;
+  text_options->native_text = false;
   return LookUpGlyphBitmap(pFont, matrix, FaceGlyphsKey2, glyph_index,
                            bFontStyle, dest_width, anti_alias);
 #endif
diff --git a/core/fxge/cfx_glyphcache.h b/core/fxge/cfx_glyphcache.h
index caf9172..d8305c7 100644
--- a/core/fxge/cfx_glyphcache.h
+++ b/core/fxge/cfx_glyphcache.h
@@ -25,6 +25,7 @@
 class CFX_GlyphBitmap;
 class CFX_Matrix;
 class CFX_PathData;
+struct CFX_TextRenderOptions;
 
 class CFX_GlyphCache : public Retainable, public Observable {
  public:
@@ -37,7 +38,7 @@
                                          const CFX_Matrix& matrix,
                                          uint32_t dest_width,
                                          int anti_alias,
-                                         int* pTextFlags);
+                                         CFX_TextRenderOptions* text_options);
   const CFX_PathData* LoadGlyphPath(const CFX_Font* pFont,
                                     uint32_t glyph_index,
                                     uint32_t dest_width);
diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp
index 7899d0a..49ff7ca 100644
--- a/core/fxge/cfx_renderdevice.cpp
+++ b/core/fxge/cfx_renderdevice.cpp
@@ -353,9 +353,10 @@
   }
 }
 
-bool ShouldDrawDeviceText(const CFX_Font* pFont, uint32_t text_flags) {
+bool ShouldDrawDeviceText(const CFX_Font* pFont,
+                          const CFX_TextRenderOptions& options) {
 #if defined(OS_MACOSX)
-  if (text_flags & FXFONT_CIDFONT)
+  if (options.font_is_cid)
     return false;
 
   const ByteString bsPsName = pFont->GetPsName();
@@ -860,38 +861,37 @@
                                       float font_size,
                                       const CFX_Matrix& mtText2Device,
                                       uint32_t fill_color,
-                                      uint32_t text_flags) {
-  int nativetext_flags = text_flags;
+                                      const CFX_TextRenderOptions& options) {
   if (GetDeviceType() != DeviceType::kDisplay) {
-    if (ShouldDrawDeviceText(pFont, text_flags) &&
+    if (ShouldDrawDeviceText(pFont, options) &&
         m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, mtText2Device,
                                         font_size, fill_color)) {
       return true;
     }
     if (FXARGB_A(fill_color) < 255)
       return false;
-  } else if (!(text_flags & FXTEXT_NO_NATIVETEXT)) {
-    if (ShouldDrawDeviceText(pFont, text_flags) &&
+  } else if (options.native_text) {
+    if (ShouldDrawDeviceText(pFont, options) &&
         m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, mtText2Device,
                                         font_size, fill_color)) {
       return true;
     }
   }
+  bool is_text_smooth = options.IsSmooth();
   CFX_Matrix char2device = mtText2Device;
   CFX_Matrix text2Device = mtText2Device;
   char2device.Scale(font_size, -font_size);
   if (fabs(char2device.a) + fabs(char2device.b) > 50 * 1.0f ||
       GetDeviceType() == DeviceType::kPrinter) {
     if (pFont->GetFaceRec()) {
-      int nPathFlags =
-          (text_flags & FXTEXT_NOSMOOTH) == 0 ? 0 : FXFILL_NOPATHSMOOTH;
+      int nPathFlags = is_text_smooth ? 0 : FXFILL_NOPATHSMOOTH;
       return DrawTextPath(nChars, pCharPos, pFont, font_size, mtText2Device,
                           nullptr, nullptr, fill_color, 0, nullptr, nPathFlags);
     }
   }
   int anti_alias = FT_RENDER_MODE_MONO;
   bool bNormal = false;
-  if ((text_flags & FXTEXT_NOSMOOTH) == 0) {
+  if (is_text_smooth) {
     if (GetDeviceType() == DeviceType::kDisplay && m_bpp > 1) {
       if (!CFX_GEModule::Get()->GetFontMgr()->FTLibrarySupportsHinting()) {
         // Some Freetype implementations (like the one packaged with Fedora) do
@@ -907,16 +907,13 @@
         anti_alias = FT_RENDER_MODE_NORMAL;
       } else {
         anti_alias = FT_RENDER_MODE_LCD;
-
-        bool bClearType = false;
-        if (pFont->GetFaceRec())
-          bClearType = !!(text_flags & FXTEXT_CLEARTYPE);
-        bNormal = !bClearType;
+        bNormal = !pFont->GetFaceRec() || !options.IsLcd();
       }
     }
   }
   std::vector<TextGlyphPos> glyphs(nChars);
   CFX_Matrix deviceCtm = char2device;
+  CFX_TextRenderOptions native_text_options(options);
 
   for (size_t i = 0; i < glyphs.size(); ++i) {
     TextGlyphPos& glyph = glyphs[i];
@@ -936,11 +933,11 @@
       new_matrix.Concat(deviceCtm);
       glyph.m_pGlyph = pFont->LoadGlyphBitmap(
           charpos.m_GlyphIndex, charpos.m_bFontStyle, new_matrix,
-          charpos.m_FontCharWidth, anti_alias, &nativetext_flags);
+          charpos.m_FontCharWidth, anti_alias, &native_text_options);
     } else {
       glyph.m_pGlyph = pFont->LoadGlyphBitmap(
           charpos.m_GlyphIndex, charpos.m_bFontStyle, deviceCtm,
-          charpos.m_FontCharWidth, anti_alias, &nativetext_flags);
+          charpos.m_FontCharWidth, anti_alias, &native_text_options);
     }
   }
   if (anti_alias < FT_RENDER_MODE_LCD && glyphs.size() > 1)
@@ -1019,7 +1016,6 @@
       }
       continue;
     }
-    bool bBGRStripe = !!(text_flags & FXTEXT_BGR_STRIPE);
     ncols /= 3;
     int x_subpixel = static_cast<int>(glyph.m_fDeviceOrigin.x * 3) % 3;
     int start_col = std::max(point->x, 0);
@@ -1032,8 +1028,10 @@
     if (start_col >= end_col)
       continue;
 
-    DrawNormalTextHelper(bitmap, pGlyph, nrows, point->x, point->y, start_col,
-                         end_col, bNormal, bBGRStripe, x_subpixel, a, r, g, b);
+    DrawNormalTextHelper(
+        bitmap, pGlyph, nrows, point->x, point->y, start_col, end_col, bNormal,
+        options.aliasing_type == CFX_TextRenderOptions::kBgrStripe, x_subpixel,
+        a, r, g, b);
   }
   if (bitmap->IsAlphaMask())
     SetBitMask(bitmap, bmp_rect.left, bmp_rect.top, fill_color);
diff --git a/core/fxge/cfx_renderdevice.h b/core/fxge/cfx_renderdevice.h
index e4b6437..84c2e03 100644
--- a/core/fxge/cfx_renderdevice.h
+++ b/core/fxge/cfx_renderdevice.h
@@ -26,6 +26,7 @@
 class PauseIndicatorIface;
 class TextCharPos;
 struct CFX_Color;
+struct CFX_TextRenderOptions;
 
 enum class BorderStyle { SOLID, DASH, BEVELED, INSET, UNDERLINE };
 
@@ -162,7 +163,7 @@
                       float font_size,
                       const CFX_Matrix& mtText2Device,
                       uint32_t fill_color,
-                      uint32_t text_flags);
+                      const CFX_TextRenderOptions& options);
   bool DrawTextPath(int nChars,
                     const TextCharPos* pCharPos,
                     CFX_Font* pFont,
diff --git a/core/fxge/cfx_textrenderoptions.cpp b/core/fxge/cfx_textrenderoptions.cpp
new file mode 100644
index 0000000..6d63aeb
--- /dev/null
+++ b/core/fxge/cfx_textrenderoptions.cpp
@@ -0,0 +1,21 @@
+// Copyright 2020 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxge/cfx_textrenderoptions.h"
+
+#include "third_party/base/no_destructor.h"
+
+// static
+const CFX_TextRenderOptions& CFX_TextRenderOptions::LcdOptions() {
+  static pdfium::base::NoDestructor<CFX_TextRenderOptions> instance(kLcd);
+  return *instance;
+}
+
+CFX_TextRenderOptions::CFX_TextRenderOptions() = default;
+
+CFX_TextRenderOptions::CFX_TextRenderOptions(AliasingType type)
+    : aliasing_type(type) {}
+
+CFX_TextRenderOptions::CFX_TextRenderOptions(
+    const CFX_TextRenderOptions& other) = default;
diff --git a/core/fxge/cfx_textrenderoptions.h b/core/fxge/cfx_textrenderoptions.h
new file mode 100644
index 0000000..eecc487
--- /dev/null
+++ b/core/fxge/cfx_textrenderoptions.h
@@ -0,0 +1,48 @@
+// Copyright 2020 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CORE_FXGE_CFX_TEXTRENDEROPTIONS_H_
+#define CORE_FXGE_CFX_TEXTRENDEROPTIONS_H_
+
+struct CFX_TextRenderOptions {
+  // AliasingType defines the options for drawing pixels on the edges of the
+  // text. The values are defined in an incrementing order due to the latter
+  // aliasing type's dependency on the previous one.
+  enum AliasingType {
+    // No transparent pixels on glyph edges.
+    kAliasing,
+
+    // May have transparent pixels on glyph edges.
+    kAntiAliasing,
+
+    // LCD optimization, can be enabled when anti-aliasing is allowed.
+    kLcd,
+
+    // BGR stripe optimization, can be enabled when LCD optimazation is enabled.
+    kBgrStripe,
+  };
+
+  static const CFX_TextRenderOptions& LcdOptions();
+
+  CFX_TextRenderOptions();
+  explicit CFX_TextRenderOptions(AliasingType type);
+  CFX_TextRenderOptions(const CFX_TextRenderOptions& other);
+
+  // Indicates whether LCD optimazation is enabled.
+  bool IsLcd() const { return aliasing_type >= kLcd; }
+
+  // Indicates whether anti aliasing is enabled.
+  bool IsSmooth() const { return aliasing_type >= kAntiAliasing; }
+
+  // Aliasing option for fonts.
+  AliasingType aliasing_type = kAntiAliasing;
+
+  // Font is CID font.
+  bool font_is_cid = false;
+
+  // Using the native text output available on some platforms.
+  bool native_text = true;
+};
+
+#endif  // CORE_FXGE_CFX_TEXTRENDEROPTIONS_H_
diff --git a/core/fxge/fx_font.h b/core/fxge/fx_font.h
index b748d55..0c2229a 100644
--- a/core/fxge/fx_font.h
+++ b/core/fxge/fx_font.h
@@ -39,7 +39,6 @@
 
 /* Other font flags */
 #define FXFONT_USEEXTERNATTR 0x80000
-#define FXFONT_CIDFONT 0x100000
 
 #define GET_TT_SHORT(w) (uint16_t)(((w)[0] << 8) | (w)[1])
 #define GET_TT_LONG(w) \
diff --git a/core/fxge/render_defines.h b/core/fxge/render_defines.h
index 152c7f1..3321505 100644
--- a/core/fxge/render_defines.h
+++ b/core/fxge/render_defines.h
@@ -39,9 +39,4 @@
 #define FX_ZEROAREA_FILL 256
 #define FXFILL_NOPATHSMOOTH 512
 
-#define FXTEXT_CLEARTYPE 0x01
-#define FXTEXT_BGR_STRIPE 0x02
-#define FXTEXT_NO_NATIVETEXT 0x08
-#define FXTEXT_NOSMOOTH 0x20
-
 #endif  // CORE_FXGE_RENDER_DEFINES_H_
diff --git a/fxbarcode/oned/BC_OneDimWriter.cpp b/fxbarcode/oned/BC_OneDimWriter.cpp
index 8634ecd..605fd8f 100644
--- a/fxbarcode/oned/BC_OneDimWriter.cpp
+++ b/fxbarcode/oned/BC_OneDimWriter.cpp
@@ -37,8 +37,8 @@
 #include "fxbarcode/BC_Writer.h"
 
 // static
-uint32_t CBC_OneDimWriter::GetTextRenderOptions() {
-  return FXTEXT_CLEARTYPE;
+const CFX_TextRenderOptions& CBC_OneDimWriter::GetTextRenderOptions() {
+  return CFX_TextRenderOptions::LcdOptions();
 }
 
 // static
diff --git a/fxbarcode/oned/BC_OneDimWriter.h b/fxbarcode/oned/BC_OneDimWriter.h
index da9b086..98e8878 100644
--- a/fxbarcode/oned/BC_OneDimWriter.h
+++ b/fxbarcode/oned/BC_OneDimWriter.h
@@ -11,6 +11,7 @@
 
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/unowned_ptr.h"
+#include "core/fxge/cfx_textrenderoptions.h"
 #include "fxbarcode/BC_Library.h"
 #include "fxbarcode/BC_Writer.h"
 #include "fxbarcode/utils.h"
@@ -22,7 +23,7 @@
 
 class CBC_OneDimWriter : public CBC_Writer {
  public:
-  static uint32_t GetTextRenderOptions();
+  static const CFX_TextRenderOptions& GetTextRenderOptions();
   static bool HasValidContentSize(WideStringView contents);
 
   CBC_OneDimWriter();
diff --git a/xfa/fde/cfde_textout.cpp b/xfa/fde/cfde_textout.cpp
index 35d66c9..c54973d 100644
--- a/xfa/fde/cfde_textout.cpp
+++ b/xfa/fde/cfde_textout.cpp
@@ -69,6 +69,7 @@
   RetainPtr<CFGAS_GEFont> pCurFont;
   TextCharPos* pCurCP = nullptr;
   int32_t iCurCount = 0;
+  const CFX_TextRenderOptions& options = CFX_TextRenderOptions::LcdOptions();
   for (auto& pos : pCharPos) {
     RetainPtr<CFGAS_GEFont> pSTFont =
         pFont->GetSubstFont(static_cast<int32_t>(pos.m_GlyphIndex));
@@ -88,7 +89,7 @@
 #endif
 
         device->DrawNormalText(iCurCount, pCurCP, font, -fFontSize, matrix,
-                               color, FXTEXT_CLEARTYPE);
+                               color, options);
       }
       pCurFont = pSTFont;
       pCurCP = &pos;
@@ -111,7 +112,7 @@
 #endif
 
     bRet = device->DrawNormalText(iCurCount, pCurCP, font, -fFontSize, matrix,
-                                  color, FXTEXT_CLEARTYPE);
+                                  color, options);
   }
 #if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
   device->Flush(false);