Reduce duplicated code in CPDF_Document by adding auxiliary methods

ProcessbCJK and CalculateFontDesc methods are used to reduce the code
duplication between AddFont and AddWindowsFont methods.

Review-Url: https://codereview.chromium.org/2341373003
diff --git a/core/fpdfapi/fpdf_parser/cpdf_document.cpp b/core/fpdfapi/fpdf_parser/cpdf_document.cpp
index 6b58aea..75a88b7 100644
--- a/core/fpdfapi/fpdf_parser/cpdf_document.cpp
+++ b/core/fpdfapi/fpdf_parser/cpdf_document.cpp
@@ -182,11 +182,7 @@
     {FXFONT_BALTIC_CHARSET, g_FX_CP1257Unicodes},
 };
 
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
-void InsertWidthArray(HDC hDC, int start, int end, CPDF_Array* pWidthArray) {
-  int size = end - start + 1;
-  int* widths = FX_Alloc(int, size);
-  GetCharWidth(hDC, start, end, widths);
+void InsertWidthArrayImpl(int* widths, int size, CPDF_Array* pWidthArray) {
   int i;
   for (i = 1; i < size; i++) {
     if (widths[i] != *widths)
@@ -205,6 +201,14 @@
   FX_Free(widths);
 }
 
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+void InsertWidthArray(HDC hDC, int start, int end, CPDF_Array* pWidthArray) {
+  int size = end - start + 1;
+  int* widths = FX_Alloc(int, size);
+  GetCharWidth(hDC, start, end, widths);
+  InsertWidthArrayImpl(widths, size, pWidthArray);
+}
+
 CFX_ByteString FPDF_GetPSNameFromTT(HDC hDC) {
   CFX_ByteString result;
   DWORD size = ::GetFontData(hDC, 'eman', 0, nullptr, 0);
@@ -230,22 +234,7 @@
     int glyph_index = pEncoding->GlyphFromCharCode(start + i);
     widths[i] = pFont->GetGlyphWidth(glyph_index);
   }
-  for (i = 1; i < size; i++) {
-    if (widths[i] != *widths)
-      break;
-  }
-  if (i == size) {
-    int first = pWidthArray->GetIntegerAt(pWidthArray->GetCount() - 1);
-    pWidthArray->AddInteger(first + size - 1);
-    pWidthArray->AddInteger(*widths);
-  } else {
-    CPDF_Array* pWidthArray1 = new CPDF_Array;
-    pWidthArray->Add(pWidthArray1);
-    for (i = 0; i < size; i++) {
-      pWidthArray1->AddInteger(widths[i]);
-    }
-  }
-  FX_Free(widths);
+  InsertWidthArrayImpl(widths, size, pWidthArray);
 }
 
 int InsertDeletePDFPage(CPDF_Document* pDoc,
@@ -394,6 +383,25 @@
   pBaseDict->SetFor("Widths", pWidths);
 }
 
+CPDF_Dictionary* CalculateFontDesc(CFX_ByteString basefont,
+                                   int flags,
+                                   int italicangle,
+                                   int ascend,
+                                   int descend,
+                                   CPDF_Array* bbox,
+                                   int32_t stemV) {
+  CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
+  pFontDesc->SetNameFor("Type", "FontDescriptor");
+  pFontDesc->SetNameFor("FontName", basefont);
+  pFontDesc->SetIntegerFor("Flags", flags);
+  pFontDesc->SetFor("FontBBox", bbox);
+  pFontDesc->SetIntegerFor("ItalicAngle", italicangle);
+  pFontDesc->SetIntegerFor("Ascent", ascend);
+  pFontDesc->SetIntegerFor("Descent", descend);
+  pFontDesc->SetIntegerFor("StemV", stemV);
+  return pFontDesc;
+}
+
 }  // namespace
 
 CPDF_Document::CPDF_Document(std::unique_ptr<CPDF_Parser> pParser)
@@ -743,6 +751,74 @@
   return i;
 }
 
+CPDF_Dictionary* CPDF_Document::ProcessbCJK(
+    CPDF_Dictionary* pBaseDict,
+    int charset,
+    FX_BOOL bVert,
+    CFX_ByteString basefont,
+    std::function<void(FX_WCHAR, FX_WCHAR, CPDF_Array*)> Insert) {
+  CPDF_Dictionary* pFontDict = new CPDF_Dictionary;
+  CFX_ByteString cmap;
+  CFX_ByteString ordering;
+  int supplement = 0;
+  CPDF_Array* pWidthArray = new CPDF_Array;
+  switch (charset) {
+    case FXFONT_CHINESEBIG5_CHARSET:
+      cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
+      ordering = "CNS1";
+      supplement = 4;
+      pWidthArray->AddInteger(1);
+      Insert(0x20, 0x7e, pWidthArray);
+      break;
+    case FXFONT_GB2312_CHARSET:
+      cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
+      ordering = "GB1";
+      supplement = 2;
+      pWidthArray->AddInteger(7716);
+      Insert(0x20, 0x20, pWidthArray);
+      pWidthArray->AddInteger(814);
+      Insert(0x21, 0x7e, pWidthArray);
+      break;
+    case FXFONT_HANGEUL_CHARSET:
+      cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
+      ordering = "Korea1";
+      supplement = 2;
+      pWidthArray->AddInteger(1);
+      Insert(0x20, 0x7e, pWidthArray);
+      break;
+    case FXFONT_SHIFTJIS_CHARSET:
+      cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
+      ordering = "Japan1";
+      supplement = 5;
+      pWidthArray->AddInteger(231);
+      Insert(0x20, 0x7d, pWidthArray);
+      pWidthArray->AddInteger(326);
+      Insert(0xa0, 0xa0, pWidthArray);
+      pWidthArray->AddInteger(327);
+      Insert(0xa1, 0xdf, pWidthArray);
+      pWidthArray->AddInteger(631);
+      Insert(0x7e, 0x7e, pWidthArray);
+      break;
+  }
+  pBaseDict->SetNameFor("Subtype", "Type0");
+  pBaseDict->SetNameFor("BaseFont", basefont);
+  pBaseDict->SetNameFor("Encoding", cmap);
+  pFontDict->SetFor("W", pWidthArray);
+  pFontDict->SetNameFor("Type", "Font");
+  pFontDict->SetNameFor("Subtype", "CIDFontType2");
+  pFontDict->SetNameFor("BaseFont", basefont);
+  CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
+  pCIDSysInfo->SetStringFor("Registry", "Adobe");
+  pCIDSysInfo->SetStringFor("Ordering", ordering);
+  pCIDSysInfo->SetIntegerFor("Supplement", supplement);
+  pFontDict->SetFor("CIDSystemInfo", pCIDSysInfo);
+  CPDF_Array* pArray = new CPDF_Array;
+  pBaseDict->SetFor("DescendantFonts", pArray);
+  AddIndirectObject(pFontDict);
+  pArray->AddReference(this, pFontDict);
+  return pFontDict;
+}
+
 CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, FX_BOOL bVert) {
   if (!pFont)
     return nullptr;
@@ -791,77 +867,16 @@
     ProcessNonbCJK(pBaseDict, pFont->IsBold(), pFont->IsItalic(), basefont,
                    pWidths);
   } else {
-    flags |= PDFFONT_NONSYMBOLIC;
-    pFontDict = new CPDF_Dictionary;
-    CFX_ByteString cmap;
-    CFX_ByteString ordering;
-    int supplement = 0;
-    CPDF_Array* pWidthArray = new CPDF_Array;
-    switch (charset) {
-      case FXFONT_CHINESEBIG5_CHARSET:
-        cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
-        ordering = "CNS1";
-        supplement = 4;
-        pWidthArray->AddInteger(1);
-        InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7e, pWidthArray);
-        break;
-      case FXFONT_GB2312_CHARSET:
-        cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
-        ordering = "GB1";
-        supplement = 2;
-        pWidthArray->AddInteger(7716);
-        InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x20, pWidthArray);
-        pWidthArray->AddInteger(814);
-        InsertWidthArray1(pFont, pEncoding.get(), 0x21, 0x7e, pWidthArray);
-        break;
-      case FXFONT_HANGEUL_CHARSET:
-        cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
-        ordering = "Korea1";
-        supplement = 2;
-        pWidthArray->AddInteger(1);
-        InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7e, pWidthArray);
-        break;
-      case FXFONT_SHIFTJIS_CHARSET:
-        cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
-        ordering = "Japan1";
-        supplement = 5;
-        pWidthArray->AddInteger(231);
-        InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7d, pWidthArray);
-        pWidthArray->AddInteger(326);
-        InsertWidthArray1(pFont, pEncoding.get(), 0xa0, 0xa0, pWidthArray);
-        pWidthArray->AddInteger(327);
-        InsertWidthArray1(pFont, pEncoding.get(), 0xa1, 0xdf, pWidthArray);
-        pWidthArray->AddInteger(631);
-        InsertWidthArray1(pFont, pEncoding.get(), 0x7e, 0x7e, pWidthArray);
-        break;
-    }
-    pBaseDict->SetNameFor("Subtype", "Type0");
-    pBaseDict->SetNameFor("BaseFont", basefont);
-    pBaseDict->SetNameFor("Encoding", cmap);
-    pFontDict->SetFor("W", pWidthArray);
-    pFontDict->SetNameFor("Type", "Font");
-    pFontDict->SetNameFor("Subtype", "CIDFontType2");
-    pFontDict->SetNameFor("BaseFont", basefont);
-    CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
-    pCIDSysInfo->SetStringFor("Registry", "Adobe");
-    pCIDSysInfo->SetStringFor("Ordering", ordering);
-    pCIDSysInfo->SetIntegerFor("Supplement", supplement);
-    pFontDict->SetFor("CIDSystemInfo", pCIDSysInfo);
-    CPDF_Array* pArray = new CPDF_Array;
-    pBaseDict->SetFor("DescendantFonts", pArray);
-    AddIndirectObject(pFontDict);
-    pArray->AddReference(this, pFontDict);
+    pFontDict = ProcessbCJK(pBaseDict, charset, bVert, basefont,
+                            [pFont, &pEncoding](FX_WCHAR start, FX_WCHAR end,
+                                                CPDF_Array* widthArr) {
+                              InsertWidthArray1(pFont, pEncoding.get(), start,
+                                                end, widthArr);
+                            });
   }
   AddIndirectObject(pBaseDict);
-  CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
-  pFontDesc->SetNameFor("Type", "FontDescriptor");
-  pFontDesc->SetNameFor("FontName", basefont);
-  pFontDesc->SetIntegerFor("Flags", flags);
-  pFontDesc->SetIntegerFor(
-      "ItalicAngle",
-      pFont->GetSubstFont() ? pFont->GetSubstFont()->m_ItalicAngle : 0);
-  pFontDesc->SetIntegerFor("Ascent", pFont->GetAscent());
-  pFontDesc->SetIntegerFor("Descent", pFont->GetDescent());
+  int italicangle =
+      pFont->GetSubstFont() ? pFont->GetSubstFont()->m_ItalicAngle : 0;
   FX_RECT bbox;
   pFont->GetBBox(bbox);
   CPDF_Array* pBBox = new CPDF_Array;
@@ -869,7 +884,6 @@
   pBBox->AddInteger(bbox.bottom);
   pBBox->AddInteger(bbox.right);
   pBBox->AddInteger(bbox.top);
-  pFontDesc->SetFor("FontBBox", pBBox);
   int32_t nStemV = 0;
   if (pFont->GetSubstFont()) {
     nStemV = pFont->GetSubstFont()->m_Weight / 5;
@@ -885,7 +899,9 @@
         nStemV = width;
     }
   }
-  pFontDesc->SetIntegerFor("StemV", nStemV);
+  CPDF_Dictionary* pFontDesc =
+      CalculateFontDesc(basefont, flags, italicangle, pFont->GetAscent(),
+                        pFont->GetDescent(), pBBox, nStemV);
   AddIndirectObject(pFontDesc);
   pFontDict->SetReferenceFor("FontDescriptor", this, pFontDesc);
   return LoadFont(pBaseDict);
@@ -968,79 +984,20 @@
     ProcessNonbCJK(pBaseDict, pLogFont->lfWeight > FW_MEDIUM,
                    pLogFont->lfItalic != 0, basefont, pWidths);
   } else {
-    pFontDict = new CPDF_Dictionary;
-    CFX_ByteString cmap;
-    CFX_ByteString ordering;
-    int supplement = 0;
-    CPDF_Array* pWidthArray = new CPDF_Array;
-    switch (pLogFont->lfCharSet) {
-      case CHINESEBIG5_CHARSET:
-        cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
-        ordering = "CNS1";
-        supplement = 4;
-        pWidthArray->AddInteger(1);
-        InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray);
-        break;
-      case GB2312_CHARSET:
-        cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
-        ordering = "GB1", supplement = 2;
-        pWidthArray->AddInteger(7716);
-        InsertWidthArray(hDC, 0x20, 0x20, pWidthArray);
-        pWidthArray->AddInteger(814);
-        InsertWidthArray(hDC, 0x21, 0x7e, pWidthArray);
-        break;
-      case HANGEUL_CHARSET:
-        cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
-        ordering = "Korea1";
-        supplement = 2;
-        pWidthArray->AddInteger(1);
-        InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray);
-        break;
-      case SHIFTJIS_CHARSET:
-        cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
-        ordering = "Japan1";
-        supplement = 5;
-        pWidthArray->AddInteger(231);
-        InsertWidthArray(hDC, 0x20, 0x7d, pWidthArray);
-        pWidthArray->AddInteger(326);
-        InsertWidthArray(hDC, 0xa0, 0xa0, pWidthArray);
-        pWidthArray->AddInteger(327);
-        InsertWidthArray(hDC, 0xa1, 0xdf, pWidthArray);
-        pWidthArray->AddInteger(631);
-        InsertWidthArray(hDC, 0x7e, 0x7e, pWidthArray);
-        break;
-    }
-    pBaseDict->SetNameFor("Subtype", "Type0");
-    pBaseDict->SetNameFor("BaseFont", basefont);
-    pBaseDict->SetNameFor("Encoding", cmap);
-    pFontDict->SetFor("W", pWidthArray);
-    pFontDict->SetNameFor("Type", "Font");
-    pFontDict->SetNameFor("Subtype", "CIDFontType2");
-    pFontDict->SetNameFor("BaseFont", basefont);
-    CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
-    pCIDSysInfo->SetStringFor("Registry", "Adobe");
-    pCIDSysInfo->SetStringFor("Ordering", ordering);
-    pCIDSysInfo->SetIntegerFor("Supplement", supplement);
-    pFontDict->SetFor("CIDSystemInfo", pCIDSysInfo);
-    CPDF_Array* pArray = new CPDF_Array;
-    pBaseDict->SetFor("DescendantFonts", pArray);
-    AddIndirectObject(pFontDict);
-    pArray->AddReference(this, pFontDict);
+    pFontDict =
+        ProcessbCJK(pBaseDict, pLogFont->lfCharSet, bVert, basefont,
+                    [&hDC](FX_WCHAR start, FX_WCHAR end, CPDF_Array* widthArr) {
+                      InsertWidthArray(hDC, start, end, widthArr);
+                    });
   }
   AddIndirectObject(pBaseDict);
-  CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
-  pFontDesc->SetNameFor("Type", "FontDescriptor");
-  pFontDesc->SetNameFor("FontName", basefont);
-  pFontDesc->SetIntegerFor("Flags", flags);
   CPDF_Array* pBBox = new CPDF_Array;
   for (int i = 0; i < 4; i++)
     pBBox->AddInteger(bbox[i]);
-  pFontDesc->SetFor("FontBBox", pBBox);
-  pFontDesc->SetIntegerFor("ItalicAngle", italicangle);
-  pFontDesc->SetIntegerFor("Ascent", ascend);
-  pFontDesc->SetIntegerFor("Descent", descend);
+  CPDF_Dictionary* pFontDesc =
+      CalculateFontDesc(basefont, flags, italicangle, ascend, descend, pBBox,
+                        pLogFont->lfWeight / 5);
   pFontDesc->SetIntegerFor("CapHeight", capheight);
-  pFontDesc->SetIntegerFor("StemV", pLogFont->lfWeight / 5);
   AddIndirectObject(pFontDesc);
   pFontDict->SetReferenceFor("FontDescriptor", this, pFontDesc);
   hFont = SelectObject(hDC, hFont);
diff --git a/core/fpdfapi/fpdf_parser/include/cpdf_document.h b/core/fpdfapi/fpdf_parser/include/cpdf_document.h
index 494868e..0b865cb 100644
--- a/core/fpdfapi/fpdf_parser/include/cpdf_document.h
+++ b/core/fpdfapi/fpdf_parser/include/cpdf_document.h
@@ -7,6 +7,7 @@
 #ifndef CORE_FPDFAPI_FPDF_PARSER_INCLUDE_CPDF_DOCUMENT_H_
 #define CORE_FPDFAPI_FPDF_PARSER_INCLUDE_CPDF_DOCUMENT_H_
 
+#include <functional>
 #include <memory>
 
 #include "core/fpdfapi/fpdf_parser/include/cpdf_indirect_object_holder.h"
@@ -128,6 +129,12 @@
   void LoadDocInternal();
   size_t CalculateEncodingDict(int charset, CPDF_Dictionary* pBaseDict);
   CPDF_Dictionary* GetPagesDict() const;
+  CPDF_Dictionary* ProcessbCJK(
+      CPDF_Dictionary* pBaseDict,
+      int charset,
+      FX_BOOL bVert,
+      CFX_ByteString basefont,
+      std::function<void(FX_WCHAR, FX_WCHAR, CPDF_Array*)> Insert);
 };
 
 #endif  // CORE_FPDFAPI_FPDF_PARSER_INCLUDE_CPDF_DOCUMENT_H_