Split core/include/fpdfapi/fpdf_resource.h

This CL splits apart the core/include/fpdfapi/fpdf_resource.h file and places
the classes into individual files.

R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/1824033002 .
diff --git a/BUILD.gn b/BUILD.gn
index 862929f..cc25e5c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -309,13 +309,27 @@
     "core/fpdfapi/fpdf_edit/editint.h",
     "core/fpdfapi/fpdf_edit/fpdf_edit_create.cpp",
     "core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp",
-    "core/fpdfapi/fpdf_edit/fpdf_edit_image.cpp",
     "core/fpdfapi/fpdf_edit/include/cpdf_creator.h",
     "core/fpdfapi/fpdf_edit/include/cpdf_pagecontentgenerator.h",
+    "core/fpdfapi/fpdf_font/cpdf_cidfont.cpp",
+    "core/fpdfapi/fpdf_font/cpdf_cidfont.h",
+    "core/fpdfapi/fpdf_font/cpdf_font.cpp",
+    "core/fpdfapi/fpdf_font/cpdf_fontencoding.cpp",
+    "core/fpdfapi/fpdf_font/cpdf_simplefont.cpp",
+    "core/fpdfapi/fpdf_font/cpdf_simplefont.h",
+    "core/fpdfapi/fpdf_font/cpdf_truetypefont.cpp",
+    "core/fpdfapi/fpdf_font/cpdf_truetypefont.h",
+    "core/fpdfapi/fpdf_font/cpdf_type1font.cpp",
+    "core/fpdfapi/fpdf_font/cpdf_type1font.h",
+    "core/fpdfapi/fpdf_font/cpdf_type3char.cpp",
+    "core/fpdfapi/fpdf_font/cpdf_type3char.h",
+    "core/fpdfapi/fpdf_font/cpdf_type3font.cpp",
+    "core/fpdfapi/fpdf_font/cpdf_type3font.h",
     "core/fpdfapi/fpdf_font/font_int.h",
     "core/fpdfapi/fpdf_font/fpdf_font.cpp",
-    "core/fpdfapi/fpdf_font/fpdf_font_charset.cpp",
     "core/fpdfapi/fpdf_font/fpdf_font_cid.cpp",
+    "core/fpdfapi/fpdf_font/include/cpdf_font.h",
+    "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h",
     "core/fpdfapi/fpdf_font/ttgsubtable.cpp",
     "core/fpdfapi/fpdf_font/ttgsubtable.h",
     "core/fpdfapi/fpdf_page/cpdf_allstates.cpp",
@@ -323,6 +337,8 @@
     "core/fpdfapi/fpdf_page/cpdf_clippath.cpp",
     "core/fpdfapi/fpdf_page/cpdf_clippathdata.cpp",
     "core/fpdfapi/fpdf_page/cpdf_clippathdata.h",
+    "core/fpdfapi/fpdf_page/cpdf_color.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_colorspace.cpp",
     "core/fpdfapi/fpdf_page/cpdf_colorstate.cpp",
     "core/fpdfapi/fpdf_page/cpdf_colorstate.h",
     "core/fpdfapi/fpdf_page/cpdf_colorstatedata.cpp",
@@ -333,6 +349,7 @@
     "core/fpdfapi/fpdf_page/cpdf_contentmarkdata.h",
     "core/fpdfapi/fpdf_page/cpdf_contentmarkitem.cpp",
     "core/fpdfapi/fpdf_page/cpdf_contentmarkitem.h",
+    "core/fpdfapi/fpdf_page/cpdf_countedobject.h",
     "core/fpdfapi/fpdf_page/cpdf_form.cpp",
     "core/fpdfapi/fpdf_page/cpdf_formobject.cpp",
     "core/fpdfapi/fpdf_page/cpdf_generalstate.cpp",
@@ -340,7 +357,10 @@
     "core/fpdfapi/fpdf_page/cpdf_graphicstates.cpp",
     "core/fpdfapi/fpdf_page/cpdf_graphicstates.h",
     "core/fpdfapi/fpdf_page/cpdf_graphstate.h",
+    "core/fpdfapi/fpdf_page/cpdf_image.cpp",
     "core/fpdfapi/fpdf_page/cpdf_imageobject.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_meshstream.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_meshstream.h",
     "core/fpdfapi/fpdf_page/cpdf_page.cpp",
     "core/fpdfapi/fpdf_page/cpdf_pageobject.cpp",
     "core/fpdfapi/fpdf_page/cpdf_pageobjectholder.cpp",
@@ -349,23 +369,31 @@
     "core/fpdfapi/fpdf_page/cpdf_parseoptions.cpp",
     "core/fpdfapi/fpdf_page/cpdf_parseoptions.h",
     "core/fpdfapi/fpdf_page/cpdf_pathobject.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_pattern.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_pattern.h",
     "core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_shadingpattern.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h",
     "core/fpdfapi/fpdf_page/cpdf_textobject.cpp",
     "core/fpdfapi/fpdf_page/cpdf_textstate.cpp",
     "core/fpdfapi/fpdf_page/cpdf_textstate.h",
     "core/fpdfapi/fpdf_page/cpdf_textstatedata.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp",
+    "core/fpdfapi/fpdf_page/cpdf_tilingpattern.h",
     "core/fpdfapi/fpdf_page/fpdf_page_colors.cpp",
     "core/fpdfapi/fpdf_page/fpdf_page_doc.cpp",
     "core/fpdfapi/fpdf_page/fpdf_page_func.cpp",
-    "core/fpdfapi/fpdf_page/fpdf_page_image.cpp",
     "core/fpdfapi/fpdf_page/fpdf_page_parser.cpp",
     "core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp",
     "core/fpdfapi/fpdf_page/fpdf_page_pattern.cpp",
     "core/fpdfapi/fpdf_page/include/cpdf_clippath.h",
+    "core/fpdfapi/fpdf_page/include/cpdf_color.h",
+    "core/fpdfapi/fpdf_page/include/cpdf_colorspace.h",
     "core/fpdfapi/fpdf_page/include/cpdf_form.h",
     "core/fpdfapi/fpdf_page/include/cpdf_formobject.h",
     "core/fpdfapi/fpdf_page/include/cpdf_generalstate.h",
     "core/fpdfapi/fpdf_page/include/cpdf_generalstatedata.h",
+    "core/fpdfapi/fpdf_page/include/cpdf_image.h",
     "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h",
     "core/fpdfapi/fpdf_page/include/cpdf_page.h",
     "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h",
@@ -442,7 +470,6 @@
     "core/fpdfapi/include/cpdf_modulemgr.h",
     "core/fpdfapi/ipdf_pagemodule.h",
     "core/fpdfapi/ipdf_rendermodule.h",
-    "core/include/fpdfapi/fpdf_resource.h",
   ]
   configs += [ ":pdfium_config" ]
 }
diff --git a/core/fpdfapi/fpdf_cmaps/CNS1/cmaps_cns1.cpp b/core/fpdfapi/fpdf_cmaps/CNS1/cmaps_cns1.cpp
index 086a786..b6a9132 100644
--- a/core/fpdfapi/fpdf_cmaps/CNS1/cmaps_cns1.cpp
+++ b/core/fpdfapi/fpdf_cmaps/CNS1/cmaps_cns1.cpp
@@ -9,8 +9,7 @@
 #include "core/fpdfapi/fpdf_cmaps/cmap_int.h"
 #include "core/fpdfapi/fpdf_font/font_int.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/fxcrt/include/fx_basic.h"  // For FX_ArraySize().
-#include "core/include/fpdfapi/fpdf_resource.h"
+#include "core/fxcrt/include/fx_basic.h"
 
 static const FXCMAP_CMap g_FXCMAP_CNS1_cmaps[] = {
     {"B5pc-H", FXCMAP_CMap::Range, g_FXCMAP_B5pc_H_0, 247, FXCMAP_CMap::None,
diff --git a/core/fpdfapi/fpdf_cmaps/GB1/cmaps_gb1.cpp b/core/fpdfapi/fpdf_cmaps/GB1/cmaps_gb1.cpp
index 95d2315..702bf06 100644
--- a/core/fpdfapi/fpdf_cmaps/GB1/cmaps_gb1.cpp
+++ b/core/fpdfapi/fpdf_cmaps/GB1/cmaps_gb1.cpp
@@ -9,8 +9,7 @@
 #include "core/fpdfapi/fpdf_cmaps/cmap_int.h"
 #include "core/fpdfapi/fpdf_font/font_int.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/fxcrt/include/fx_basic.h"  // For FX_ArraySize().
-#include "core/include/fpdfapi/fpdf_resource.h"
+#include "core/fxcrt/include/fx_basic.h"
 
 static const FXCMAP_CMap g_FXCMAP_GB1_cmaps[] = {
     {"GB-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_GB_EUC_H_0, 90, FXCMAP_CMap::None,
diff --git a/core/fpdfapi/fpdf_cmaps/Japan1/cmaps_japan1.cpp b/core/fpdfapi/fpdf_cmaps/Japan1/cmaps_japan1.cpp
index 8c43d41..43f7e0e 100644
--- a/core/fpdfapi/fpdf_cmaps/Japan1/cmaps_japan1.cpp
+++ b/core/fpdfapi/fpdf_cmaps/Japan1/cmaps_japan1.cpp
@@ -9,8 +9,7 @@
 #include "core/fpdfapi/fpdf_cmaps/cmap_int.h"
 #include "core/fpdfapi/fpdf_font/font_int.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/fxcrt/include/fx_basic.h"  // For FX_ArraySize().
-#include "core/include/fpdfapi/fpdf_resource.h"
+#include "core/fxcrt/include/fx_basic.h"
 
 static const FXCMAP_CMap g_FXCMAP_Japan1_cmaps[] = {
     {"83pv-RKSJ-H", FXCMAP_CMap::Range, g_FXCMAP_83pv_RKSJ_H_1, 222,
diff --git a/core/fpdfapi/fpdf_cmaps/Korea1/cmaps_korea1.cpp b/core/fpdfapi/fpdf_cmaps/Korea1/cmaps_korea1.cpp
index 0001aaa..77f65df 100644
--- a/core/fpdfapi/fpdf_cmaps/Korea1/cmaps_korea1.cpp
+++ b/core/fpdfapi/fpdf_cmaps/Korea1/cmaps_korea1.cpp
@@ -9,8 +9,7 @@
 #include "core/fpdfapi/fpdf_cmaps/cmap_int.h"
 #include "core/fpdfapi/fpdf_font/font_int.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/fxcrt/include/fx_basic.h"  // For FX_ArraySize().
-#include "core/include/fpdfapi/fpdf_resource.h"
+#include "core/fxcrt/include/fx_basic.h"
 
 static const FXCMAP_CMap g_FXCMAP_Korea1_cmaps[] = {
     {"KSC-EUC-H", FXCMAP_CMap::Range, g_FXCMAP_KSC_EUC_H_0, 467,
diff --git a/core/fpdfapi/fpdf_cmaps/fpdf_cmaps.cpp b/core/fpdfapi/fpdf_cmaps/fpdf_cmaps.cpp
index 73ac8e1..4e0737d 100644
--- a/core/fpdfapi/fpdf_cmaps/fpdf_cmaps.cpp
+++ b/core/fpdfapi/fpdf_cmaps/fpdf_cmaps.cpp
@@ -8,7 +8,6 @@
 
 #include "core/fpdfapi/fpdf_font/font_int.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 
 void FPDFAPI_FindEmbeddedCMap(const char* name,
                               int charset,
diff --git a/core/fpdfapi/fpdf_edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/fpdf_edit/cpdf_pagecontentgenerator.cpp
index 20211f2..0ab34ea 100644
--- a/core/fpdfapi/fpdf_edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/fpdf_edit/cpdf_pagecontentgenerator.cpp
@@ -7,6 +7,7 @@
 #include "core/fpdfapi/fpdf_edit/include/cpdf_pagecontentgenerator.h"
 
 #include "core/fpdfapi/fpdf_edit/include/cpdf_creator.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
@@ -14,6 +15,8 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
 
 CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& ar, CFX_Matrix& matrix) {
diff --git a/core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp b/core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
index 874b205..7688bb0 100644
--- a/core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
+++ b/core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
@@ -6,6 +6,8 @@
 
 #include <limits.h>
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
diff --git a/core/fpdfapi/fpdf_font/cpdf_cidfont.cpp b/core/fpdfapi/fpdf_font/cpdf_cidfont.cpp
new file mode 100644
index 0000000..d528017
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_cidfont.cpp
@@ -0,0 +1,908 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_font/cpdf_cidfont.h"
+
+#include "core/fpdfapi/fpdf_cmaps/cmap_int.h"
+#include "core/fpdfapi/fpdf_font/font_int.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
+#include "core/fpdfapi/fpdf_font/ttgsubtable.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
+#include "core/fpdfapi/include/cpdf_modulemgr.h"
+
+namespace {
+
+const uint16_t g_CharsetCPs[CIDSET_NUM_SETS] = {0, 936, 950, 932, 949, 1200};
+
+const struct CIDTransform {
+  uint16_t CID;
+  uint8_t a;
+  uint8_t b;
+  uint8_t c;
+  uint8_t d;
+  uint8_t e;
+  uint8_t f;
+} g_Japan1_VertCIDs[] = {
+    {97, 129, 0, 0, 127, 55, 0},     {7887, 127, 0, 0, 127, 76, 89},
+    {7888, 127, 0, 0, 127, 79, 94},  {7889, 0, 129, 127, 0, 17, 127},
+    {7890, 0, 129, 127, 0, 17, 127}, {7891, 0, 129, 127, 0, 17, 127},
+    {7892, 0, 129, 127, 0, 17, 127}, {7893, 0, 129, 127, 0, 17, 127},
+    {7894, 0, 129, 127, 0, 17, 127}, {7895, 0, 129, 127, 0, 17, 127},
+    {7896, 0, 129, 127, 0, 17, 127}, {7897, 0, 129, 127, 0, 17, 127},
+    {7898, 0, 129, 127, 0, 17, 127}, {7899, 0, 129, 127, 0, 17, 104},
+    {7900, 0, 129, 127, 0, 17, 127}, {7901, 0, 129, 127, 0, 17, 104},
+    {7902, 0, 129, 127, 0, 17, 127}, {7903, 0, 129, 127, 0, 17, 127},
+    {7904, 0, 129, 127, 0, 17, 127}, {7905, 0, 129, 127, 0, 17, 114},
+    {7906, 0, 129, 127, 0, 17, 127}, {7907, 0, 129, 127, 0, 17, 127},
+    {7908, 0, 129, 127, 0, 17, 127}, {7909, 0, 129, 127, 0, 17, 127},
+    {7910, 0, 129, 127, 0, 17, 127}, {7911, 0, 129, 127, 0, 17, 127},
+    {7912, 0, 129, 127, 0, 17, 127}, {7913, 0, 129, 127, 0, 17, 127},
+    {7914, 0, 129, 127, 0, 17, 127}, {7915, 0, 129, 127, 0, 17, 114},
+    {7916, 0, 129, 127, 0, 17, 127}, {7917, 0, 129, 127, 0, 17, 127},
+    {7918, 127, 0, 0, 127, 18, 25},  {7919, 127, 0, 0, 127, 18, 25},
+    {7920, 127, 0, 0, 127, 18, 25},  {7921, 127, 0, 0, 127, 18, 25},
+    {7922, 127, 0, 0, 127, 18, 25},  {7923, 127, 0, 0, 127, 18, 25},
+    {7924, 127, 0, 0, 127, 18, 25},  {7925, 127, 0, 0, 127, 18, 25},
+    {7926, 127, 0, 0, 127, 18, 25},  {7927, 127, 0, 0, 127, 18, 25},
+    {7928, 127, 0, 0, 127, 18, 25},  {7929, 127, 0, 0, 127, 18, 25},
+    {7930, 127, 0, 0, 127, 18, 25},  {7931, 127, 0, 0, 127, 18, 25},
+    {7932, 127, 0, 0, 127, 18, 25},  {7933, 127, 0, 0, 127, 18, 25},
+    {7934, 127, 0, 0, 127, 18, 25},  {7935, 127, 0, 0, 127, 18, 25},
+    {7936, 127, 0, 0, 127, 18, 25},  {7937, 127, 0, 0, 127, 18, 25},
+    {7938, 127, 0, 0, 127, 18, 25},  {7939, 127, 0, 0, 127, 18, 25},
+    {8720, 0, 129, 127, 0, 19, 102}, {8721, 0, 129, 127, 0, 13, 127},
+    {8722, 0, 129, 127, 0, 19, 108}, {8723, 0, 129, 127, 0, 19, 102},
+    {8724, 0, 129, 127, 0, 19, 102}, {8725, 0, 129, 127, 0, 19, 102},
+    {8726, 0, 129, 127, 0, 19, 102}, {8727, 0, 129, 127, 0, 19, 102},
+    {8728, 0, 129, 127, 0, 19, 114}, {8729, 0, 129, 127, 0, 19, 114},
+    {8730, 0, 129, 127, 0, 38, 108}, {8731, 0, 129, 127, 0, 13, 108},
+    {8732, 0, 129, 127, 0, 19, 108}, {8733, 0, 129, 127, 0, 19, 108},
+    {8734, 0, 129, 127, 0, 19, 108}, {8735, 0, 129, 127, 0, 19, 108},
+    {8736, 0, 129, 127, 0, 19, 102}, {8737, 0, 129, 127, 0, 19, 102},
+    {8738, 0, 129, 127, 0, 19, 102}, {8739, 0, 129, 127, 0, 19, 102},
+    {8740, 0, 129, 127, 0, 19, 102}, {8741, 0, 129, 127, 0, 19, 102},
+    {8742, 0, 129, 127, 0, 19, 102}, {8743, 0, 129, 127, 0, 19, 102},
+    {8744, 0, 129, 127, 0, 19, 102}, {8745, 0, 129, 127, 0, 19, 102},
+    {8746, 0, 129, 127, 0, 19, 114}, {8747, 0, 129, 127, 0, 19, 114},
+    {8748, 0, 129, 127, 0, 19, 102}, {8749, 0, 129, 127, 0, 19, 102},
+    {8750, 0, 129, 127, 0, 19, 102}, {8751, 0, 129, 127, 0, 19, 102},
+    {8752, 0, 129, 127, 0, 19, 102}, {8753, 0, 129, 127, 0, 19, 102},
+    {8754, 0, 129, 127, 0, 19, 102}, {8755, 0, 129, 127, 0, 19, 102},
+    {8756, 0, 129, 127, 0, 19, 102}, {8757, 0, 129, 127, 0, 19, 102},
+    {8758, 0, 129, 127, 0, 19, 102}, {8759, 0, 129, 127, 0, 19, 102},
+    {8760, 0, 129, 127, 0, 19, 102}, {8761, 0, 129, 127, 0, 19, 102},
+    {8762, 0, 129, 127, 0, 19, 102}, {8763, 0, 129, 127, 0, 19, 102},
+    {8764, 0, 129, 127, 0, 19, 102}, {8765, 0, 129, 127, 0, 19, 102},
+    {8766, 0, 129, 127, 0, 19, 102}, {8767, 0, 129, 127, 0, 19, 102},
+    {8768, 0, 129, 127, 0, 19, 102}, {8769, 0, 129, 127, 0, 19, 102},
+    {8770, 0, 129, 127, 0, 19, 102}, {8771, 0, 129, 127, 0, 19, 102},
+    {8772, 0, 129, 127, 0, 19, 102}, {8773, 0, 129, 127, 0, 19, 102},
+    {8774, 0, 129, 127, 0, 19, 102}, {8775, 0, 129, 127, 0, 19, 102},
+    {8776, 0, 129, 127, 0, 19, 102}, {8777, 0, 129, 127, 0, 19, 102},
+    {8778, 0, 129, 127, 0, 19, 102}, {8779, 0, 129, 127, 0, 19, 114},
+    {8780, 0, 129, 127, 0, 19, 108}, {8781, 0, 129, 127, 0, 19, 114},
+    {8782, 0, 129, 127, 0, 13, 114}, {8783, 0, 129, 127, 0, 19, 108},
+    {8784, 0, 129, 127, 0, 13, 114}, {8785, 0, 129, 127, 0, 19, 108},
+    {8786, 0, 129, 127, 0, 19, 108}, {8787, 0, 129, 127, 0, 19, 108},
+    {8788, 0, 129, 127, 0, 19, 108}, {8789, 0, 129, 127, 0, 19, 108},
+    {8790, 0, 129, 127, 0, 19, 108}, {8791, 0, 129, 127, 0, 19, 108},
+    {8792, 0, 129, 127, 0, 19, 108}, {8793, 0, 129, 127, 0, 19, 108},
+    {8794, 0, 129, 127, 0, 19, 108}, {8795, 0, 129, 127, 0, 19, 108},
+    {8796, 0, 129, 127, 0, 19, 108}, {8797, 0, 129, 127, 0, 19, 108},
+    {8798, 0, 129, 127, 0, 19, 108}, {8799, 0, 129, 127, 0, 19, 108},
+    {8800, 0, 129, 127, 0, 19, 108}, {8801, 0, 129, 127, 0, 19, 108},
+    {8802, 0, 129, 127, 0, 19, 108}, {8803, 0, 129, 127, 0, 19, 108},
+    {8804, 0, 129, 127, 0, 19, 108}, {8805, 0, 129, 127, 0, 19, 108},
+    {8806, 0, 129, 127, 0, 19, 108}, {8807, 0, 129, 127, 0, 19, 108},
+    {8808, 0, 129, 127, 0, 19, 108}, {8809, 0, 129, 127, 0, 19, 108},
+    {8810, 0, 129, 127, 0, 19, 108}, {8811, 0, 129, 127, 0, 19, 114},
+    {8812, 0, 129, 127, 0, 19, 102}, {8813, 0, 129, 127, 0, 19, 114},
+    {8814, 0, 129, 127, 0, 76, 102}, {8815, 0, 129, 127, 0, 13, 121},
+    {8816, 0, 129, 127, 0, 19, 114}, {8817, 0, 129, 127, 0, 19, 127},
+    {8818, 0, 129, 127, 0, 19, 114}, {8819, 0, 129, 127, 0, 218, 108},
+};
+
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+
+bool IsValidEmbeddedCharcodeFromUnicodeCharset(CIDSet charset) {
+  switch (charset) {
+    case CIDSET_GB1:
+    case CIDSET_CNS1:
+    case CIDSET_JAPAN1:
+    case CIDSET_KOREA1:
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+FX_WCHAR EmbeddedUnicodeFromCharcode(const FXCMAP_CMap* pEmbedMap,
+                                     CIDSet charset,
+                                     FX_DWORD charcode) {
+  if (!IsValidEmbeddedCharcodeFromUnicodeCharset(charset))
+    return 0;
+
+  uint16_t cid = FPDFAPI_CIDFromCharCode(pEmbedMap, charcode);
+  if (cid == 0)
+    return 0;
+
+  CPDF_FontGlobals* pFontGlobals =
+      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
+  const uint16_t* pCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap;
+  if (!pCodes)
+    return 0;
+
+  if (cid < pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count)
+    return pCodes[cid];
+  return 0;
+}
+
+FX_DWORD EmbeddedCharcodeFromUnicode(const FXCMAP_CMap* pEmbedMap,
+                                     CIDSet charset,
+                                     FX_WCHAR unicode) {
+  if (!IsValidEmbeddedCharcodeFromUnicodeCharset(charset))
+    return 0;
+
+  CPDF_FontGlobals* pFontGlobals =
+      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
+  const uint16_t* pCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap;
+  if (!pCodes)
+    return 0;
+
+  int nCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count;
+  for (int i = 0; i < nCodes; ++i) {
+    if (pCodes[i] == unicode) {
+      FX_DWORD CharCode = FPDFAPI_CharCodeFromCID(pEmbedMap, i);
+      if (CharCode != 0) {
+        return CharCode;
+      }
+    }
+  }
+  return 0;
+}
+
+#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+
+void FT_UseCIDCharmap(FXFT_Face face, int coding) {
+  int encoding;
+  switch (coding) {
+    case CIDCODING_GB:
+      encoding = FXFT_ENCODING_GB2312;
+      break;
+    case CIDCODING_BIG5:
+      encoding = FXFT_ENCODING_BIG5;
+      break;
+    case CIDCODING_JIS:
+      encoding = FXFT_ENCODING_SJIS;
+      break;
+    case CIDCODING_KOREA:
+      encoding = FXFT_ENCODING_JOHAB;
+      break;
+    default:
+      encoding = FXFT_ENCODING_UNICODE;
+  }
+  int err = FXFT_Select_Charmap(face, encoding);
+  if (err) {
+    err = FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE);
+  }
+  if (err && FXFT_Get_Face_Charmaps(face)) {
+    FXFT_Set_Charmap(face, *FXFT_Get_Face_Charmaps(face));
+  }
+}
+
+int CompareCIDTransform(const void* key, const void* element) {
+  uint16_t CID = *static_cast<const uint16_t*>(key);
+  return CID - static_cast<const struct CIDTransform*>(element)->CID;
+}
+
+}  // namespace
+
+CPDF_CIDFont::CPDF_CIDFont()
+    : m_pCMap(nullptr),
+      m_pAllocatedCMap(nullptr),
+      m_pCID2UnicodeMap(nullptr),
+      m_pCIDToGIDMap(nullptr),
+      m_bCIDIsGID(FALSE),
+      m_pAnsiWidths(nullptr),
+      m_bAdobeCourierStd(FALSE),
+      m_pTTGSUBTable(nullptr) {}
+
+CPDF_CIDFont::~CPDF_CIDFont() {
+  if (m_pAnsiWidths) {
+    FX_Free(m_pAnsiWidths);
+  }
+  delete m_pAllocatedCMap;
+  delete m_pCIDToGIDMap;
+  delete m_pTTGSUBTable;
+}
+
+bool CPDF_CIDFont::IsCIDFont() const {
+  return true;
+}
+
+const CPDF_CIDFont* CPDF_CIDFont::AsCIDFont() const {
+  return this;
+}
+
+CPDF_CIDFont* CPDF_CIDFont::AsCIDFont() {
+  return this;
+}
+
+uint16_t CPDF_CIDFont::CIDFromCharCode(FX_DWORD charcode) const {
+  if (!m_pCMap) {
+    return (uint16_t)charcode;
+  }
+  return m_pCMap->CIDFromCharCode(charcode);
+}
+
+FX_BOOL CPDF_CIDFont::IsVertWriting() const {
+  return m_pCMap ? m_pCMap->IsVertWriting() : FALSE;
+}
+
+CFX_WideString CPDF_CIDFont::UnicodeFromCharCode(FX_DWORD charcode) const {
+  CFX_WideString str = CPDF_Font::UnicodeFromCharCode(charcode);
+  if (!str.IsEmpty())
+    return str;
+  FX_WCHAR ret = GetUnicodeFromCharCode(charcode);
+  if (ret == 0)
+    return CFX_WideString();
+  return ret;
+}
+
+FX_WCHAR CPDF_CIDFont::GetUnicodeFromCharCode(FX_DWORD charcode) const {
+  switch (m_pCMap->m_Coding) {
+    case CIDCODING_UCS2:
+    case CIDCODING_UTF16:
+      return (FX_WCHAR)charcode;
+    case CIDCODING_CID:
+      if (!m_pCID2UnicodeMap || !m_pCID2UnicodeMap->IsLoaded()) {
+        return 0;
+      }
+      return m_pCID2UnicodeMap->UnicodeFromCID((uint16_t)charcode);
+  }
+  if (!m_pCMap->IsLoaded() || !m_pCID2UnicodeMap ||
+      !m_pCID2UnicodeMap->IsLoaded()) {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+    FX_WCHAR unicode;
+    int charsize = 1;
+    if (charcode > 255) {
+      charcode = (charcode % 256) * 256 + (charcode / 256);
+      charsize = 2;
+    }
+    int ret = FXSYS_MultiByteToWideChar(g_CharsetCPs[m_pCMap->m_Coding], 0,
+                                        (const FX_CHAR*)&charcode, charsize,
+                                        &unicode, 1);
+    if (ret != 1) {
+      return 0;
+    }
+    return unicode;
+#else
+    if (m_pCMap->m_pEmbedMap) {
+      return EmbeddedUnicodeFromCharcode(m_pCMap->m_pEmbedMap,
+                                         m_pCMap->m_Charset, charcode);
+    }
+    return 0;
+#endif
+  }
+  return m_pCID2UnicodeMap->UnicodeFromCID(CIDFromCharCode(charcode));
+}
+
+FX_DWORD CPDF_CIDFont::CharCodeFromUnicode(FX_WCHAR unicode) const {
+  FX_DWORD charcode = CPDF_Font::CharCodeFromUnicode(unicode);
+  if (charcode)
+    return charcode;
+  switch (m_pCMap->m_Coding) {
+    case CIDCODING_UNKNOWN:
+      return 0;
+    case CIDCODING_UCS2:
+    case CIDCODING_UTF16:
+      return unicode;
+    case CIDCODING_CID: {
+      if (!m_pCID2UnicodeMap || !m_pCID2UnicodeMap->IsLoaded()) {
+        return 0;
+      }
+      FX_DWORD CID = 0;
+      while (CID < 65536) {
+        FX_WCHAR this_unicode =
+            m_pCID2UnicodeMap->UnicodeFromCID((uint16_t)CID);
+        if (this_unicode == unicode) {
+          return CID;
+        }
+        CID++;
+      }
+      break;
+    }
+  }
+
+  if (unicode < 0x80) {
+    return static_cast<FX_DWORD>(unicode);
+  }
+  if (m_pCMap->m_Coding == CIDCODING_CID) {
+    return 0;
+  }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+  uint8_t buffer[32];
+  int ret =
+      FXSYS_WideCharToMultiByte(g_CharsetCPs[m_pCMap->m_Coding], 0, &unicode, 1,
+                                (char*)buffer, 4, NULL, NULL);
+  if (ret == 1) {
+    return buffer[0];
+  }
+  if (ret == 2) {
+    return buffer[0] * 256 + buffer[1];
+  }
+#else
+  if (m_pCMap->m_pEmbedMap) {
+    return EmbeddedCharcodeFromUnicode(m_pCMap->m_pEmbedMap, m_pCMap->m_Charset,
+                                       unicode);
+  }
+#endif
+  return 0;
+}
+
+FX_BOOL CPDF_CIDFont::Load() {
+  if (m_pFontDict->GetStringBy("Subtype") == "TrueType") {
+    return LoadGB2312();
+  }
+  CPDF_Array* pFonts = m_pFontDict->GetArrayBy("DescendantFonts");
+  if (!pFonts) {
+    return FALSE;
+  }
+  if (pFonts->GetCount() != 1) {
+    return FALSE;
+  }
+  CPDF_Dictionary* pCIDFontDict = pFonts->GetDictAt(0);
+  if (!pCIDFontDict) {
+    return FALSE;
+  }
+  m_BaseFont = pCIDFontDict->GetStringBy("BaseFont");
+  if ((m_BaseFont.Compare("CourierStd") == 0 ||
+       m_BaseFont.Compare("CourierStd-Bold") == 0 ||
+       m_BaseFont.Compare("CourierStd-BoldOblique") == 0 ||
+       m_BaseFont.Compare("CourierStd-Oblique") == 0) &&
+      !IsEmbedded()) {
+    m_bAdobeCourierStd = TRUE;
+  }
+  CPDF_Dictionary* pFontDesc = pCIDFontDict->GetDictBy("FontDescriptor");
+  if (pFontDesc) {
+    LoadFontDescriptor(pFontDesc);
+  }
+  CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding");
+  if (!pEncoding) {
+    return FALSE;
+  }
+  CFX_ByteString subtype = pCIDFontDict->GetStringBy("Subtype");
+  m_bType1 = (subtype == "CIDFontType0");
+
+  if (pEncoding->IsName()) {
+    CFX_ByteString cmap = pEncoding->GetString();
+    m_pCMap =
+        CPDF_ModuleMgr::Get()
+            ->GetPageModule()
+            ->GetFontGlobals()
+            ->m_CMapManager.GetPredefinedCMap(cmap, m_pFontFile && m_bType1);
+  } else if (CPDF_Stream* pStream = pEncoding->AsStream()) {
+    m_pAllocatedCMap = m_pCMap = new CPDF_CMap;
+    CPDF_StreamAcc acc;
+    acc.LoadAllData(pStream, FALSE);
+    m_pCMap->LoadEmbedded(acc.GetData(), acc.GetSize());
+  } else {
+    return FALSE;
+  }
+  if (!m_pCMap) {
+    return FALSE;
+  }
+  m_Charset = m_pCMap->m_Charset;
+  if (m_Charset == CIDSET_UNKNOWN) {
+    CPDF_Dictionary* pCIDInfo = pCIDFontDict->GetDictBy("CIDSystemInfo");
+    if (pCIDInfo) {
+      m_Charset = CharsetFromOrdering(pCIDInfo->GetStringBy("Ordering"));
+    }
+  }
+  if (m_Charset != CIDSET_UNKNOWN)
+    m_pCID2UnicodeMap =
+        CPDF_ModuleMgr::Get()
+            ->GetPageModule()
+            ->GetFontGlobals()
+            ->m_CMapManager.GetCID2UnicodeMap(
+                m_Charset,
+                !m_pFontFile && (m_pCMap->m_Coding == CIDCODING_CID ||
+                                 pCIDFontDict->KeyExist("W")));
+  if (m_Font.GetFace()) {
+    if (m_bType1) {
+      FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE);
+    } else {
+      FT_UseCIDCharmap(m_Font.GetFace(), m_pCMap->m_Coding);
+    }
+  }
+  m_DefaultWidth = pCIDFontDict->GetIntegerBy("DW", 1000);
+  CPDF_Array* pWidthArray = pCIDFontDict->GetArrayBy("W");
+  if (pWidthArray) {
+    LoadMetricsArray(pWidthArray, m_WidthList, 1);
+  }
+  if (!IsEmbedded()) {
+    LoadSubstFont();
+  }
+  if (1) {
+    if (m_pFontFile || (GetSubstFont()->m_SubstFlags & FXFONT_SUBST_EXACT)) {
+      CPDF_Object* pmap = pCIDFontDict->GetElementValue("CIDToGIDMap");
+      if (pmap) {
+        if (CPDF_Stream* pStream = pmap->AsStream()) {
+          m_pCIDToGIDMap = new CPDF_StreamAcc;
+          m_pCIDToGIDMap->LoadAllData(pStream, FALSE);
+        } else if (pmap->GetString() == "Identity") {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+          if (m_pFontFile) {
+            m_bCIDIsGID = TRUE;
+          }
+#else
+          m_bCIDIsGID = TRUE;
+#endif
+        }
+      }
+    }
+  }
+  CheckFontMetrics();
+  if (IsVertWriting()) {
+    pWidthArray = pCIDFontDict->GetArrayBy("W2");
+    if (pWidthArray) {
+      LoadMetricsArray(pWidthArray, m_VertMetrics, 3);
+    }
+    CPDF_Array* pDefaultArray = pCIDFontDict->GetArrayBy("DW2");
+    if (pDefaultArray) {
+      m_DefaultVY = pDefaultArray->GetIntegerAt(0);
+      m_DefaultW1 = pDefaultArray->GetIntegerAt(1);
+    } else {
+      m_DefaultVY = 880;
+      m_DefaultW1 = -1000;
+    }
+  }
+  return TRUE;
+}
+
+FX_RECT CPDF_CIDFont::GetCharBBox(FX_DWORD charcode, int level) {
+  if (charcode < 256 && m_CharBBox[charcode].right != FX_SMALL_RECT::kInvalid)
+    return FX_RECT(m_CharBBox[charcode]);
+
+  FX_RECT rect;
+  FX_BOOL bVert = FALSE;
+  int glyph_index = GlyphFromCharCode(charcode, &bVert);
+  FXFT_Face face = m_Font.GetFace();
+  if (face) {
+    if (FXFT_Is_Face_Tricky(face)) {
+      int err = FXFT_Load_Glyph(face, glyph_index,
+                                FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
+      if (!err) {
+        FXFT_BBox cbox;
+        FXFT_Glyph glyph;
+        err = FXFT_Get_Glyph(((FXFT_Face)face)->glyph, &glyph);
+        if (!err) {
+          FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox);
+          int pixel_size_x = ((FXFT_Face)face)->size->metrics.x_ppem;
+          int pixel_size_y = ((FXFT_Face)face)->size->metrics.y_ppem;
+          if (pixel_size_x == 0 || pixel_size_y == 0) {
+            rect = FX_RECT(cbox.xMin, cbox.yMax, cbox.xMax, cbox.yMin);
+          } else {
+            rect = FX_RECT(cbox.xMin * 1000 / pixel_size_x,
+                           cbox.yMax * 1000 / pixel_size_y,
+                           cbox.xMax * 1000 / pixel_size_x,
+                           cbox.yMin * 1000 / pixel_size_y);
+          }
+          if (rect.top > FXFT_Get_Face_Ascender(face)) {
+            rect.top = FXFT_Get_Face_Ascender(face);
+          }
+          if (rect.bottom < FXFT_Get_Face_Descender(face)) {
+            rect.bottom = FXFT_Get_Face_Descender(face);
+          }
+          FXFT_Done_Glyph(glyph);
+        }
+      }
+    } else {
+      int err = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_NO_SCALE);
+      if (err == 0) {
+        rect = FX_RECT(TT2PDF(FXFT_Get_Glyph_HoriBearingX(face), face),
+                       TT2PDF(FXFT_Get_Glyph_HoriBearingY(face), face),
+                       TT2PDF(FXFT_Get_Glyph_HoriBearingX(face) +
+                                  FXFT_Get_Glyph_Width(face),
+                              face),
+                       TT2PDF(FXFT_Get_Glyph_HoriBearingY(face) -
+                                  FXFT_Get_Glyph_Height(face),
+                              face));
+        rect.top += rect.top / 64;
+      }
+    }
+  }
+  if (!m_pFontFile && m_Charset == CIDSET_JAPAN1) {
+    uint16_t CID = CIDFromCharCode(charcode);
+    const uint8_t* pTransform = GetCIDTransform(CID);
+    if (pTransform && !bVert) {
+      CFX_Matrix matrix(CIDTransformToFloat(pTransform[0]),
+                        CIDTransformToFloat(pTransform[1]),
+                        CIDTransformToFloat(pTransform[2]),
+                        CIDTransformToFloat(pTransform[3]),
+                        CIDTransformToFloat(pTransform[4]) * 1000,
+                        CIDTransformToFloat(pTransform[5]) * 1000);
+      CFX_FloatRect rect_f(rect);
+      rect_f.Transform(&matrix);
+      rect = rect_f.GetOutterRect();
+    }
+  }
+  if (charcode < 256)
+    m_CharBBox[charcode] = rect.ToSmallRect();
+
+  return rect;
+}
+int CPDF_CIDFont::GetCharWidthF(FX_DWORD charcode, int level) {
+  if (m_pAnsiWidths && charcode < 0x80) {
+    return m_pAnsiWidths[charcode];
+  }
+  uint16_t cid = CIDFromCharCode(charcode);
+  int size = m_WidthList.GetSize();
+  FX_DWORD* list = m_WidthList.GetData();
+  for (int i = 0; i < size; i += 3) {
+    if (cid >= list[i] && cid <= list[i + 1]) {
+      return (int)list[i + 2];
+    }
+  }
+  return m_DefaultWidth;
+}
+short CPDF_CIDFont::GetVertWidth(uint16_t CID) const {
+  FX_DWORD vertsize = m_VertMetrics.GetSize() / 5;
+  if (vertsize == 0) {
+    return m_DefaultW1;
+  }
+  const FX_DWORD* pTable = m_VertMetrics.GetData();
+  for (FX_DWORD i = 0; i < vertsize; i++)
+    if (pTable[i * 5] <= CID && pTable[i * 5 + 1] >= CID) {
+      return (short)(int)pTable[i * 5 + 2];
+    }
+  return m_DefaultW1;
+}
+void CPDF_CIDFont::GetVertOrigin(uint16_t CID, short& vx, short& vy) const {
+  FX_DWORD vertsize = m_VertMetrics.GetSize() / 5;
+  if (vertsize) {
+    const FX_DWORD* pTable = m_VertMetrics.GetData();
+    for (FX_DWORD i = 0; i < vertsize; i++)
+      if (pTable[i * 5] <= CID && pTable[i * 5 + 1] >= CID) {
+        vx = (short)(int)pTable[i * 5 + 3];
+        vy = (short)(int)pTable[i * 5 + 4];
+        return;
+      }
+  }
+  FX_DWORD dwWidth = m_DefaultWidth;
+  int size = m_WidthList.GetSize();
+  const FX_DWORD* list = m_WidthList.GetData();
+  for (int i = 0; i < size; i += 3) {
+    if (CID >= list[i] && CID <= list[i + 1]) {
+      dwWidth = (uint16_t)list[i + 2];
+      break;
+    }
+  }
+  vx = (short)dwWidth / 2;
+  vy = (short)m_DefaultVY;
+}
+int CPDF_CIDFont::GetGlyphIndex(FX_DWORD unicode, FX_BOOL* pVertGlyph) {
+  if (pVertGlyph) {
+    *pVertGlyph = FALSE;
+  }
+  FXFT_Face face = m_Font.GetFace();
+  int index = FXFT_Get_Char_Index(face, unicode);
+  if (unicode == 0x2502) {
+    return index;
+  }
+  if (index && IsVertWriting()) {
+    if (m_pTTGSUBTable) {
+      uint32_t vindex = 0;
+      m_pTTGSUBTable->GetVerticalGlyph(index, &vindex);
+      if (vindex) {
+        index = vindex;
+        if (pVertGlyph) {
+          *pVertGlyph = TRUE;
+        }
+      }
+      return index;
+    }
+    if (!m_Font.GetSubData()) {
+      unsigned long length = 0;
+      int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
+                                       NULL, &length);
+      if (!error) {
+        m_Font.SetSubData(FX_Alloc(uint8_t, length));
+      }
+    }
+    int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
+                                     m_Font.GetSubData(), NULL);
+    if (!error && m_Font.GetSubData()) {
+      m_pTTGSUBTable = new CFX_CTTGSUBTable;
+      m_pTTGSUBTable->LoadGSUBTable((FT_Bytes)m_Font.GetSubData());
+      uint32_t vindex = 0;
+      m_pTTGSUBTable->GetVerticalGlyph(index, &vindex);
+      if (vindex) {
+        index = vindex;
+        if (pVertGlyph) {
+          *pVertGlyph = TRUE;
+        }
+      }
+    }
+    return index;
+  }
+  if (pVertGlyph) {
+    *pVertGlyph = FALSE;
+  }
+  return index;
+}
+int CPDF_CIDFont::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) {
+  if (pVertGlyph) {
+    *pVertGlyph = FALSE;
+  }
+  if (!m_pFontFile && !m_pCIDToGIDMap) {
+    uint16_t cid = CIDFromCharCode(charcode);
+    FX_WCHAR unicode = 0;
+    if (m_bCIDIsGID) {
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
+      return cid;
+#else
+      if (m_Flags & PDFFONT_SYMBOLIC) {
+        return cid;
+      }
+      CFX_WideString uni_str = UnicodeFromCharCode(charcode);
+      if (uni_str.IsEmpty()) {
+        return cid;
+      }
+      unicode = uni_str.GetAt(0);
+#endif
+    } else {
+      if (cid && m_pCID2UnicodeMap && m_pCID2UnicodeMap->IsLoaded()) {
+        unicode = m_pCID2UnicodeMap->UnicodeFromCID(cid);
+      }
+      if (unicode == 0) {
+        unicode = GetUnicodeFromCharCode(charcode);
+      }
+      if (unicode == 0 && !(m_Flags & PDFFONT_SYMBOLIC)) {
+        unicode = UnicodeFromCharCode(charcode).GetAt(0);
+      }
+    }
+    FXFT_Face face = m_Font.GetFace();
+    if (unicode == 0) {
+      if (!m_bAdobeCourierStd) {
+        return charcode == 0 ? -1 : (int)charcode;
+      }
+      charcode += 31;
+      int index = 0, iBaseEncoding;
+      FX_BOOL bMSUnicode = FT_UseTTCharmap(face, 3, 1);
+      FX_BOOL bMacRoman = FALSE;
+      if (!bMSUnicode) {
+        bMacRoman = FT_UseTTCharmap(face, 1, 0);
+      }
+      iBaseEncoding = PDFFONT_ENCODING_STANDARD;
+      if (bMSUnicode) {
+        iBaseEncoding = PDFFONT_ENCODING_WINANSI;
+      } else if (bMacRoman) {
+        iBaseEncoding = PDFFONT_ENCODING_MACROMAN;
+      }
+      const FX_CHAR* name = GetAdobeCharName(iBaseEncoding, NULL, charcode);
+      if (!name) {
+        return charcode == 0 ? -1 : (int)charcode;
+      }
+      uint16_t unicode = PDF_UnicodeFromAdobeName(name);
+      if (unicode) {
+        if (bMSUnicode) {
+          index = FXFT_Get_Char_Index(face, unicode);
+        } else if (bMacRoman) {
+          FX_DWORD maccode =
+              FT_CharCodeFromUnicode(FXFT_ENCODING_APPLE_ROMAN, unicode);
+          index = !maccode ? FXFT_Get_Name_Index(face, (char*)name)
+                           : FXFT_Get_Char_Index(face, maccode);
+        } else {
+          return FXFT_Get_Char_Index(face, unicode);
+        }
+      } else {
+        return charcode == 0 ? -1 : (int)charcode;
+      }
+      if (index == 0 || index == 0xffff) {
+        return charcode == 0 ? -1 : (int)charcode;
+      }
+      return index;
+    }
+    if (m_Charset == CIDSET_JAPAN1) {
+      if (unicode == '\\') {
+        unicode = '/';
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
+      } else if (unicode == 0xa5) {
+        unicode = 0x5c;
+#endif
+      }
+    }
+    if (!face)
+      return unicode;
+
+    int err = FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE);
+    if (err != 0) {
+      int i;
+      for (i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
+        FX_DWORD ret = FT_CharCodeFromUnicode(
+            FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i]),
+            (FX_WCHAR)charcode);
+        if (ret == 0) {
+          continue;
+        }
+        FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[i]);
+        unicode = (FX_WCHAR)ret;
+        break;
+      }
+      if (i == FXFT_Get_Face_CharmapCount(face) && i) {
+        FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]);
+        unicode = (FX_WCHAR)charcode;
+      }
+    }
+    if (FXFT_Get_Face_Charmap(face)) {
+      int index = GetGlyphIndex(unicode, pVertGlyph);
+      if (index == 0)
+        return -1;
+      return index;
+    }
+    return unicode;
+  }
+  if (!m_Font.GetFace())
+    return -1;
+
+  uint16_t cid = CIDFromCharCode(charcode);
+  if (m_bType1) {
+    if (!m_pCIDToGIDMap) {
+      return cid;
+    }
+  } else {
+    if (!m_pCIDToGIDMap) {
+      if (m_pFontFile && !m_pCMap->m_pMapping)
+        return cid;
+      if (m_pCMap->m_Coding == CIDCODING_UNKNOWN ||
+          !FXFT_Get_Face_Charmap(m_Font.GetFace())) {
+        return cid;
+      }
+      if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmap(m_Font.GetFace())) ==
+          FXFT_ENCODING_UNICODE) {
+        CFX_WideString unicode_str = UnicodeFromCharCode(charcode);
+        if (unicode_str.IsEmpty()) {
+          return -1;
+        }
+        charcode = unicode_str.GetAt(0);
+      }
+      return GetGlyphIndex(charcode, pVertGlyph);
+    }
+  }
+  FX_DWORD byte_pos = cid * 2;
+  if (byte_pos + 2 > m_pCIDToGIDMap->GetSize())
+    return -1;
+
+  const uint8_t* pdata = m_pCIDToGIDMap->GetData() + byte_pos;
+  return pdata[0] * 256 + pdata[1];
+}
+FX_DWORD CPDF_CIDFont::GetNextChar(const FX_CHAR* pString,
+                                   int nStrLen,
+                                   int& offset) const {
+  return m_pCMap->GetNextChar(pString, nStrLen, offset);
+}
+int CPDF_CIDFont::GetCharSize(FX_DWORD charcode) const {
+  return m_pCMap->GetCharSize(charcode);
+}
+int CPDF_CIDFont::CountChar(const FX_CHAR* pString, int size) const {
+  return m_pCMap->CountChar(pString, size);
+}
+int CPDF_CIDFont::AppendChar(FX_CHAR* str, FX_DWORD charcode) const {
+  return m_pCMap->AppendChar(str, charcode);
+}
+FX_BOOL CPDF_CIDFont::IsUnicodeCompatible() const {
+  if (!m_pCMap->IsLoaded() || !m_pCID2UnicodeMap ||
+      !m_pCID2UnicodeMap->IsLoaded()) {
+    return m_pCMap->m_Coding != CIDCODING_UNKNOWN;
+  }
+  return TRUE;
+}
+FX_BOOL CPDF_CIDFont::IsFontStyleFromCharCode(FX_DWORD charcode) const {
+  return TRUE;
+}
+void CPDF_CIDFont::LoadSubstFont() {
+  m_Font.LoadSubst(m_BaseFont, !m_bType1, m_Flags, m_StemV * 5, m_ItalicAngle,
+                   g_CharsetCPs[m_Charset], IsVertWriting());
+}
+void CPDF_CIDFont::LoadMetricsArray(CPDF_Array* pArray,
+                                    CFX_DWordArray& result,
+                                    int nElements) {
+  int width_status = 0;
+  int iCurElement = 0;
+  int first_code = 0;
+  int last_code = 0;
+  FX_DWORD count = pArray->GetCount();
+  for (FX_DWORD i = 0; i < count; i++) {
+    CPDF_Object* pObj = pArray->GetElementValue(i);
+    if (!pObj)
+      continue;
+
+    if (CPDF_Array* pArray = pObj->AsArray()) {
+      if (width_status != 1)
+        return;
+
+      FX_DWORD count = pArray->GetCount();
+      for (FX_DWORD j = 0; j < count; j += nElements) {
+        result.Add(first_code);
+        result.Add(first_code);
+        for (int k = 0; k < nElements; k++) {
+          result.Add(pArray->GetIntegerAt(j + k));
+        }
+        first_code++;
+      }
+      width_status = 0;
+    } else {
+      if (width_status == 0) {
+        first_code = pObj->GetInteger();
+        width_status = 1;
+      } else if (width_status == 1) {
+        last_code = pObj->GetInteger();
+        width_status = 2;
+        iCurElement = 0;
+      } else {
+        if (!iCurElement) {
+          result.Add(first_code);
+          result.Add(last_code);
+        }
+        result.Add(pObj->GetInteger());
+        iCurElement++;
+        if (iCurElement == nElements) {
+          width_status = 0;
+        }
+      }
+    }
+  }
+}
+
+// static
+FX_FLOAT CPDF_CIDFont::CIDTransformToFloat(uint8_t ch) {
+  if (ch < 128) {
+    return ch * 1.0f / 127;
+  }
+  return (-255 + ch) * 1.0f / 127;
+}
+
+FX_BOOL CPDF_CIDFont::LoadGB2312() {
+  m_BaseFont = m_pFontDict->GetStringBy("BaseFont");
+  CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictBy("FontDescriptor");
+  if (pFontDesc) {
+    LoadFontDescriptor(pFontDesc);
+  }
+  m_Charset = CIDSET_GB1;
+  m_bType1 = FALSE;
+  m_pCMap = CPDF_ModuleMgr::Get()
+                ->GetPageModule()
+                ->GetFontGlobals()
+                ->m_CMapManager.GetPredefinedCMap("GBK-EUC-H", FALSE);
+  m_pCID2UnicodeMap = CPDF_ModuleMgr::Get()
+                          ->GetPageModule()
+                          ->GetFontGlobals()
+                          ->m_CMapManager.GetCID2UnicodeMap(m_Charset, FALSE);
+  if (!IsEmbedded()) {
+    LoadSubstFont();
+  }
+  CheckFontMetrics();
+  m_DefaultWidth = 1000;
+  m_pAnsiWidths = FX_Alloc(uint16_t, 128);
+  for (int i = 32; i < 127; i++) {
+    m_pAnsiWidths[i] = 500;
+  }
+  return TRUE;
+}
+
+const uint8_t* CPDF_CIDFont::GetCIDTransform(uint16_t CID) const {
+  if (m_Charset != CIDSET_JAPAN1 || m_pFontFile)
+    return nullptr;
+
+  const struct CIDTransform* found = (const struct CIDTransform*)FXSYS_bsearch(
+      &CID, g_Japan1_VertCIDs, FX_ArraySize(g_Japan1_VertCIDs),
+      sizeof(g_Japan1_VertCIDs[0]), CompareCIDTransform);
+  return found ? &found->a : nullptr;
+}
diff --git a/core/fpdfapi/fpdf_font/cpdf_cidfont.h b/core/fpdfapi/fpdf_font/cpdf_cidfont.h
new file mode 100644
index 0000000..6ff7c82
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_cidfont.h
@@ -0,0 +1,89 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_FONT_CPDF_CIDFONT_H_
+#define CORE_FPDFAPI_FPDF_FONT_CPDF_CIDFONT_H_
+
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
+#include "core/fxcrt/include/fx_string.h"
+#include "core/fxcrt/include/fx_system.h"
+
+enum CIDSet {
+  CIDSET_UNKNOWN,
+  CIDSET_GB1,
+  CIDSET_CNS1,
+  CIDSET_JAPAN1,
+  CIDSET_KOREA1,
+  CIDSET_UNICODE,
+  CIDSET_NUM_SETS
+};
+
+class CFX_CTTGSUBTable;
+class CPDF_Array;
+class CPDF_CID2UnicodeMap;
+class CPDF_CMap;
+class CPDF_StreamAcc;
+
+class CPDF_CIDFont : public CPDF_Font {
+ public:
+  CPDF_CIDFont();
+  ~CPDF_CIDFont() override;
+
+  static FX_FLOAT CIDTransformToFloat(uint8_t ch);
+
+  // CPDF_Font:
+  bool IsCIDFont() const override;
+  const CPDF_CIDFont* AsCIDFont() const override;
+  CPDF_CIDFont* AsCIDFont() override;
+  int GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph = NULL) override;
+  int GetCharWidthF(FX_DWORD charcode, int level = 0) override;
+  FX_RECT GetCharBBox(FX_DWORD charcode, int level = 0) override;
+  FX_DWORD GetNextChar(const FX_CHAR* pString,
+                       int nStrLen,
+                       int& offset) const override;
+  int CountChar(const FX_CHAR* pString, int size) const override;
+  int AppendChar(FX_CHAR* str, FX_DWORD charcode) const override;
+  int GetCharSize(FX_DWORD charcode) const override;
+  FX_BOOL IsVertWriting() const override;
+  FX_BOOL IsUnicodeCompatible() const override;
+  FX_BOOL Load() override;
+  CFX_WideString UnicodeFromCharCode(FX_DWORD charcode) const override;
+  FX_DWORD CharCodeFromUnicode(FX_WCHAR Unicode) const override;
+
+  FX_BOOL LoadGB2312();
+  uint16_t CIDFromCharCode(FX_DWORD charcode) const;
+  const uint8_t* GetCIDTransform(uint16_t CID) const;
+  short GetVertWidth(uint16_t CID) const;
+  void GetVertOrigin(uint16_t CID, short& vx, short& vy) const;
+  virtual FX_BOOL IsFontStyleFromCharCode(FX_DWORD charcode) const;
+
+ protected:
+  int GetGlyphIndex(FX_DWORD unicodeb, FX_BOOL* pVertGlyph);
+  void LoadMetricsArray(CPDF_Array* pArray,
+                        CFX_DWordArray& result,
+                        int nElements);
+  void LoadSubstFont();
+  FX_WCHAR GetUnicodeFromCharCode(FX_DWORD charcode) const;
+
+  CPDF_CMap* m_pCMap;
+  CPDF_CMap* m_pAllocatedCMap;
+  CPDF_CID2UnicodeMap* m_pCID2UnicodeMap;
+  CIDSet m_Charset;
+  FX_BOOL m_bType1;
+  CPDF_StreamAcc* m_pCIDToGIDMap;
+  FX_BOOL m_bCIDIsGID;
+  uint16_t m_DefaultWidth;
+  uint16_t* m_pAnsiWidths;
+  FX_SMALL_RECT m_CharBBox[256];
+  CFX_DWordArray m_WidthList;
+  short m_DefaultVY;
+  short m_DefaultW1;
+  CFX_DWordArray m_VertMetrics;
+  FX_BOOL m_bAdobeCourierStd;
+  CFX_CTTGSUBTable* m_pTTGSUBTable;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_FONT_CPDF_CIDFONT_H_
diff --git a/core/fpdfapi/fpdf_font/cpdf_font.cpp b/core/fpdfapi/fpdf_font/cpdf_font.cpp
new file mode 100644
index 0000000..bb63966
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_font.cpp
@@ -0,0 +1,492 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
+
+#include "core/fpdfapi/fpdf_font/cpdf_truetypefont.h"
+#include "core/fpdfapi/fpdf_font/cpdf_type1font.h"
+#include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
+#include "core/fpdfapi/fpdf_font/font_int.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
+#include "core/fpdfapi/fpdf_page/pageint.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_name.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
+#include "core/fpdfapi/include/cpdf_modulemgr.h"
+#include "core/include/fxge/fx_freetype.h"
+
+namespace {
+
+const uint8_t ChineseFontNames[][5] = {{0xCB, 0xCE, 0xCC, 0xE5, 0x00},
+                                       {0xBF, 0xAC, 0xCC, 0xE5, 0x00},
+                                       {0xBA, 0xDA, 0xCC, 0xE5, 0x00},
+                                       {0xB7, 0xC2, 0xCB, 0xCE, 0x00},
+                                       {0xD0, 0xC2, 0xCB, 0xCE, 0x00}};
+
+FX_BOOL GetPredefinedEncoding(int& basemap, const CFX_ByteString& value) {
+  if (value == "WinAnsiEncoding")
+    basemap = PDFFONT_ENCODING_WINANSI;
+  else if (value == "MacRomanEncoding")
+    basemap = PDFFONT_ENCODING_MACROMAN;
+  else if (value == "MacExpertEncoding")
+    basemap = PDFFONT_ENCODING_MACEXPERT;
+  else if (value == "PDFDocEncoding")
+    basemap = PDFFONT_ENCODING_PDFDOC;
+  else
+    return FALSE;
+  return TRUE;
+}
+
+}  // namespace
+
+CPDF_Font::CPDF_Font()
+    : m_pFontFile(nullptr),
+      m_pFontDict(nullptr),
+      m_pToUnicodeMap(nullptr),
+      m_bToUnicodeLoaded(FALSE),
+      m_Flags(0),
+      m_StemV(0),
+      m_Ascent(0),
+      m_Descent(0),
+      m_ItalicAngle(0) {}
+
+CPDF_Font::~CPDF_Font() {
+  delete m_pToUnicodeMap;
+  m_pToUnicodeMap = NULL;
+
+  if (m_pFontFile) {
+    m_pDocument->GetPageData()->ReleaseFontFileStreamAcc(
+        const_cast<CPDF_Stream*>(m_pFontFile->GetStream()->AsStream()));
+  }
+}
+
+bool CPDF_Font::IsType1Font() const {
+  return false;
+}
+
+bool CPDF_Font::IsTrueTypeFont() const {
+  return false;
+}
+
+bool CPDF_Font::IsType3Font() const {
+  return false;
+}
+
+bool CPDF_Font::IsCIDFont() const {
+  return false;
+}
+
+const CPDF_Type1Font* CPDF_Font::AsType1Font() const {
+  return nullptr;
+}
+
+CPDF_Type1Font* CPDF_Font::AsType1Font() {
+  return nullptr;
+}
+
+const CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() const {
+  return nullptr;
+}
+
+CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() {
+  return nullptr;
+}
+
+const CPDF_Type3Font* CPDF_Font::AsType3Font() const {
+  return nullptr;
+}
+
+CPDF_Type3Font* CPDF_Font::AsType3Font() {
+  return nullptr;
+}
+
+const CPDF_CIDFont* CPDF_Font::AsCIDFont() const {
+  return nullptr;
+}
+
+CPDF_CIDFont* CPDF_Font::AsCIDFont() {
+  return nullptr;
+}
+
+FX_BOOL CPDF_Font::IsUnicodeCompatible() const {
+  return FALSE;
+}
+
+int CPDF_Font::CountChar(const FX_CHAR* pString, int size) const {
+  return size;
+}
+
+int CPDF_Font::GetCharSize(FX_DWORD charcode) const {
+  return 1;
+}
+
+int CPDF_Font::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) {
+  ASSERT(false);
+  return 0;
+}
+
+int CPDF_Font::GlyphFromCharCodeExt(FX_DWORD charcode) {
+  return GlyphFromCharCode(charcode);
+}
+
+FX_BOOL CPDF_Font::IsVertWriting() const {
+  FX_BOOL bVertWriting = FALSE;
+  const CPDF_CIDFont* pCIDFont = AsCIDFont();
+  if (pCIDFont) {
+    bVertWriting = pCIDFont->IsVertWriting();
+  } else {
+    bVertWriting = m_Font.IsVertical();
+  }
+  return bVertWriting;
+}
+
+int CPDF_Font::AppendChar(FX_CHAR* buf, FX_DWORD charcode) const {
+  *buf = (FX_CHAR)charcode;
+  return 1;
+}
+
+void CPDF_Font::AppendChar(CFX_ByteString& str, FX_DWORD charcode) const {
+  char buf[4];
+  int len = AppendChar(buf, charcode);
+  if (len == 1) {
+    str += buf[0];
+  } else {
+    str += CFX_ByteString(buf, len);
+  }
+}
+
+CFX_WideString CPDF_Font::UnicodeFromCharCode(FX_DWORD charcode) const {
+  if (!m_bToUnicodeLoaded)
+    ((CPDF_Font*)this)->LoadUnicodeMap();
+
+  if (m_pToUnicodeMap)
+    return m_pToUnicodeMap->Lookup(charcode);
+  return CFX_WideString();
+}
+
+FX_DWORD CPDF_Font::CharCodeFromUnicode(FX_WCHAR unicode) const {
+  if (!m_bToUnicodeLoaded)
+    ((CPDF_Font*)this)->LoadUnicodeMap();
+
+  if (m_pToUnicodeMap)
+    return m_pToUnicodeMap->ReverseLookup(unicode);
+  return 0;
+}
+
+void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) {
+  m_Flags = pFontDesc->GetIntegerBy("Flags", PDFFONT_NONSYMBOLIC);
+  int ItalicAngle = 0;
+  FX_BOOL bExistItalicAngle = FALSE;
+  if (pFontDesc->KeyExist("ItalicAngle")) {
+    ItalicAngle = pFontDesc->GetIntegerBy("ItalicAngle");
+    bExistItalicAngle = TRUE;
+  }
+  if (ItalicAngle < 0) {
+    m_Flags |= PDFFONT_ITALIC;
+    m_ItalicAngle = ItalicAngle;
+  }
+  FX_BOOL bExistStemV = FALSE;
+  if (pFontDesc->KeyExist("StemV")) {
+    m_StemV = pFontDesc->GetIntegerBy("StemV");
+    bExistStemV = TRUE;
+  }
+  FX_BOOL bExistAscent = FALSE;
+  if (pFontDesc->KeyExist("Ascent")) {
+    m_Ascent = pFontDesc->GetIntegerBy("Ascent");
+    bExistAscent = TRUE;
+  }
+  FX_BOOL bExistDescent = FALSE;
+  if (pFontDesc->KeyExist("Descent")) {
+    m_Descent = pFontDesc->GetIntegerBy("Descent");
+    bExistDescent = TRUE;
+  }
+  FX_BOOL bExistCapHeight = FALSE;
+  if (pFontDesc->KeyExist("CapHeight")) {
+    bExistCapHeight = TRUE;
+  }
+  if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent &&
+      bExistStemV) {
+    m_Flags |= PDFFONT_USEEXTERNATTR;
+  }
+  if (m_Descent > 10) {
+    m_Descent = -m_Descent;
+  }
+  CPDF_Array* pBBox = pFontDesc->GetArrayBy("FontBBox");
+  if (pBBox) {
+    m_FontBBox.left = pBBox->GetIntegerAt(0);
+    m_FontBBox.bottom = pBBox->GetIntegerAt(1);
+    m_FontBBox.right = pBBox->GetIntegerAt(2);
+    m_FontBBox.top = pBBox->GetIntegerAt(3);
+  }
+
+  CPDF_Stream* pFontFile = pFontDesc->GetStreamBy("FontFile");
+  if (!pFontFile)
+    pFontFile = pFontDesc->GetStreamBy("FontFile2");
+  if (!pFontFile)
+    pFontFile = pFontDesc->GetStreamBy("FontFile3");
+  if (!pFontFile)
+    return;
+
+  m_pFontFile = m_pDocument->LoadFontFile(pFontFile);
+  if (!m_pFontFile)
+    return;
+
+  const uint8_t* pFontData = m_pFontFile->GetData();
+  FX_DWORD dwFontSize = m_pFontFile->GetSize();
+  if (!m_Font.LoadEmbedded(pFontData, dwFontSize)) {
+    m_pDocument->GetPageData()->ReleaseFontFileStreamAcc(
+        const_cast<CPDF_Stream*>(m_pFontFile->GetStream()->AsStream()));
+    m_pFontFile = nullptr;
+  }
+}
+
+void CPDF_Font::CheckFontMetrics() {
+  if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
+      m_FontBBox.right == 0) {
+    FXFT_Face face = m_Font.GetFace();
+    if (face) {
+      m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face);
+      m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face);
+      m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face);
+      m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face);
+      m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face);
+      m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face);
+    } else {
+      FX_BOOL bFirst = TRUE;
+      for (int i = 0; i < 256; i++) {
+        FX_RECT rect = GetCharBBox(i);
+        if (rect.left == rect.right) {
+          continue;
+        }
+        if (bFirst) {
+          m_FontBBox = rect;
+          bFirst = FALSE;
+        } else {
+          if (m_FontBBox.top < rect.top) {
+            m_FontBBox.top = rect.top;
+          }
+          if (m_FontBBox.right < rect.right) {
+            m_FontBBox.right = rect.right;
+          }
+          if (m_FontBBox.left > rect.left) {
+            m_FontBBox.left = rect.left;
+          }
+          if (m_FontBBox.bottom > rect.bottom) {
+            m_FontBBox.bottom = rect.bottom;
+          }
+        }
+      }
+    }
+  }
+  if (m_Ascent == 0 && m_Descent == 0) {
+    FX_RECT rect = GetCharBBox('A');
+    m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top;
+    rect = GetCharBBox('g');
+    m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom;
+  }
+}
+
+void CPDF_Font::LoadUnicodeMap() {
+  m_bToUnicodeLoaded = TRUE;
+  CPDF_Stream* pStream = m_pFontDict->GetStreamBy("ToUnicode");
+  if (!pStream) {
+    return;
+  }
+  m_pToUnicodeMap = new CPDF_ToUnicodeMap;
+  m_pToUnicodeMap->Load(pStream);
+}
+
+int CPDF_Font::GetStringWidth(const FX_CHAR* pString, int size) {
+  int offset = 0;
+  int width = 0;
+  while (offset < size) {
+    FX_DWORD charcode = GetNextChar(pString, size, offset);
+    width += GetCharWidthF(charcode);
+  }
+  return width;
+}
+
+CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc,
+                                   const CFX_ByteStringC& name) {
+  CFX_ByteString fontname(name);
+  int font_id = PDF_GetStandardFontName(&fontname);
+  if (font_id < 0) {
+    return nullptr;
+  }
+  CPDF_FontGlobals* pFontGlobals =
+      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
+  CPDF_Font* pFont = pFontGlobals->Find(pDoc, font_id);
+  if (pFont) {
+    return pFont;
+  }
+  CPDF_Dictionary* pDict = new CPDF_Dictionary;
+  pDict->SetAtName("Type", "Font");
+  pDict->SetAtName("Subtype", "Type1");
+  pDict->SetAtName("BaseFont", fontname);
+  pDict->SetAtName("Encoding", "WinAnsiEncoding");
+  pFont = CPDF_Font::CreateFontF(NULL, pDict);
+  pFontGlobals->Set(pDoc, font_id, pFont);
+  return pFont;
+}
+
+CPDF_Font* CPDF_Font::CreateFontF(CPDF_Document* pDoc,
+                                  CPDF_Dictionary* pFontDict) {
+  CFX_ByteString type = pFontDict->GetStringBy("Subtype");
+  CPDF_Font* pFont;
+  if (type == "TrueType") {
+    {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ || \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ ||   \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ || \
+    _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+      CFX_ByteString basefont = pFontDict->GetStringBy("BaseFont");
+      CFX_ByteString tag = basefont.Left(4);
+      int i;
+      int count = sizeof(ChineseFontNames) / sizeof(ChineseFontNames[0]);
+      for (i = 0; i < count; ++i) {
+        if (tag == CFX_ByteString((const FX_CHAR*)ChineseFontNames[i])) {
+          break;
+        }
+      }
+      if (i < count) {
+        CPDF_Dictionary* pFontDesc = pFontDict->GetDictBy("FontDescriptor");
+        if (!pFontDesc || !pFontDesc->KeyExist("FontFile2")) {
+          pFont = new CPDF_CIDFont;
+          pFont->m_pFontDict = pFontDict;
+          pFont->m_pDocument = pDoc;
+          pFont->m_BaseFont = pFontDict->GetStringBy("BaseFont");
+          if (!pFont->Load()) {
+            delete pFont;
+            return NULL;
+          }
+          return pFont;
+        }
+      }
+#endif
+    }
+    pFont = new CPDF_TrueTypeFont;
+  } else if (type == "Type3") {
+    pFont = new CPDF_Type3Font;
+  } else if (type == "Type0") {
+    pFont = new CPDF_CIDFont;
+  } else {
+    pFont = new CPDF_Type1Font;
+  }
+  pFont->m_pFontDict = pFontDict;
+  pFont->m_pDocument = pDoc;
+  pFont->m_BaseFont = pFontDict->GetStringBy("BaseFont");
+  if (!pFont->Load()) {
+    delete pFont;
+    return NULL;
+  }
+  return pFont;
+}
+
+FX_DWORD CPDF_Font::GetNextChar(const FX_CHAR* pString,
+                                int nStrLen,
+                                int& offset) const {
+  if (offset < 0 || nStrLen < 1) {
+    return 0;
+  }
+  uint8_t ch = offset < nStrLen ? pString[offset++] : pString[nStrLen - 1];
+  return static_cast<FX_DWORD>(ch);
+}
+
+void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding,
+                                int& iBaseEncoding,
+                                CFX_ByteString*& pCharNames,
+                                FX_BOOL bEmbedded,
+                                FX_BOOL bTrueType) {
+  if (!pEncoding) {
+    if (m_BaseFont == "Symbol") {
+      iBaseEncoding = bTrueType ? PDFFONT_ENCODING_MS_SYMBOL
+                                : PDFFONT_ENCODING_ADOBE_SYMBOL;
+    } else if (!bEmbedded && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
+      iBaseEncoding = PDFFONT_ENCODING_WINANSI;
+    }
+    return;
+  }
+  if (pEncoding->IsName()) {
+    if (iBaseEncoding == PDFFONT_ENCODING_ADOBE_SYMBOL ||
+        iBaseEncoding == PDFFONT_ENCODING_ZAPFDINGBATS) {
+      return;
+    }
+    if ((m_Flags & PDFFONT_SYMBOLIC) && m_BaseFont == "Symbol") {
+      if (!bTrueType) {
+        iBaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
+      }
+      return;
+    }
+    CFX_ByteString bsEncoding = pEncoding->GetString();
+    if (bsEncoding.Compare("MacExpertEncoding") == 0) {
+      bsEncoding = "WinAnsiEncoding";
+    }
+    GetPredefinedEncoding(iBaseEncoding, bsEncoding);
+    return;
+  }
+
+  CPDF_Dictionary* pDict = pEncoding->AsDictionary();
+  if (!pDict)
+    return;
+
+  if (iBaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL &&
+      iBaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS) {
+    CFX_ByteString bsEncoding = pDict->GetStringBy("BaseEncoding");
+    if (bsEncoding.Compare("MacExpertEncoding") == 0 && bTrueType) {
+      bsEncoding = "WinAnsiEncoding";
+    }
+    GetPredefinedEncoding(iBaseEncoding, bsEncoding);
+  }
+  if ((!bEmbedded || bTrueType) && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
+    iBaseEncoding = PDFFONT_ENCODING_STANDARD;
+  }
+  CPDF_Array* pDiffs = pDict->GetArrayBy("Differences");
+  if (!pDiffs) {
+    return;
+  }
+  pCharNames = new CFX_ByteString[256];
+  FX_DWORD cur_code = 0;
+  for (FX_DWORD i = 0; i < pDiffs->GetCount(); i++) {
+    CPDF_Object* pElement = pDiffs->GetElementValue(i);
+    if (!pElement)
+      continue;
+
+    if (CPDF_Name* pName = pElement->AsName()) {
+      if (cur_code < 256)
+        pCharNames[cur_code] = pName->GetString();
+      cur_code++;
+    } else {
+      cur_code = pElement->GetInteger();
+    }
+  }
+}
+
+FX_BOOL CPDF_Font::IsStandardFont() const {
+  if (!IsType1Font())
+    return FALSE;
+  if (m_pFontFile)
+    return FALSE;
+  if (AsType1Font()->GetBase14Font() < 0)
+    return FALSE;
+  return TRUE;
+}
+
+const FX_CHAR* CPDF_Font::GetAdobeCharName(int iBaseEncoding,
+                                           const CFX_ByteString* pCharNames,
+                                           int charcode) {
+  ASSERT(charcode >= 0 && charcode < 256);
+  if (charcode < 0 || charcode >= 256)
+    return nullptr;
+
+  const FX_CHAR* name = nullptr;
+  if (pCharNames)
+    name = pCharNames[charcode];
+  if ((!name || name[0] == 0) && iBaseEncoding)
+    name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode);
+  return name && name[0] ? name : nullptr;
+}
diff --git a/core/fpdfapi/fpdf_font/fpdf_font_charset.cpp b/core/fpdfapi/fpdf_font/cpdf_fontencoding.cpp
similarity index 88%
rename from core/fpdfapi/fpdf_font/fpdf_font_charset.cpp
rename to core/fpdfapi/fpdf_font/cpdf_fontencoding.cpp
index 1b503c6..64e11e0 100644
--- a/core/fpdfapi/fpdf_font/fpdf_font_charset.cpp
+++ b/core/fpdfapi/fpdf_font/cpdf_fontencoding.cpp
@@ -1,77 +1,52 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
+// Copyright 2016 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.
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
-#include "core/include/fxge/fx_freetype.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
 
-static const struct _UnicodeAlt {
-  uint16_t m_Unicode;
-  const FX_CHAR* m_Alter;
-} UnicodeAlts[] = {
-    {0x00a0, " "},    {0x00a1, "!"},   {0x00a2, "c"},   {0x00a3, "P"},
-    {0x00a4, "o"},    {0x00a5, "Y"},   {0x00a6, "|"},   {0x00a7, "S"},
-    {0x00a9, "(C)"},  {0x00aa, "a"},   {0x00ab, "<<"},  {0x00ac, "-|"},
-    {0x00ae, "(R)"},  {0x00af, "-"},   {0x00b0, "o"},   {0x00b1, "+/-"},
-    {0x00b2, "^2"},   {0x00b3, "^3"},  {0x00b4, "'"},   {0x00b5, "u"},
-    {0x00b6, "P"},    {0x00b7, "."},   {0x00b9, "^1"},  {0x00ba, "o"},
-    {0x00bb, ">>"},   {0x00bc, "1/4"}, {0x00bd, "1/2"}, {0x00be, "3/4"},
-    {0x00bf, "?"},    {0x00c0, "A"},   {0x00c1, "A"},   {0x00c2, "A"},
-    {0x00c3, "A"},    {0x00c4, "A"},   {0x00c5, "A"},   {0x00c6, "AE"},
-    {0x00c7, "C"},    {0x00c8, "E"},   {0x00c9, "E"},   {0x00ca, "E"},
-    {0x00cb, "E"},    {0x00cc, "I"},   {0x00cd, "I"},   {0x00ce, "I"},
-    {0x00cf, "I"},    {0x00d1, "N"},   {0x00d2, "O"},   {0x00d3, "O"},
-    {0x00d4, "O"},    {0x00d5, "O"},   {0x00d6, "O"},   {0x00d7, "x"},
-    {0x00d8, "O"},    {0x00d9, "U"},   {0x00da, "U"},   {0x00db, "U"},
-    {0x00dc, "U"},    {0x00dd, "Y"},   {0x00df, "S"},   {0x00e0, "a"},
-    {0x00e1, "a"},    {0x00e2, "a"},   {0x00e3, "a"},   {0x00e4, "a"},
-    {0x00e5, "a"},    {0x00e6, "ae"},  {0x00e7, "c"},   {0x00e8, "e"},
-    {0x00e9, "e"},    {0x00ea, "e"},   {0x00eb, "e"},   {0x00ec, "i"},
-    {0x00ed, "i"},    {0x00ee, "i"},   {0x00ef, "i"},   {0x00f1, "n"},
-    {0x00f2, "o"},    {0x00f3, "o"},   {0x00f4, "o"},   {0x00f5, "o"},
-    {0x00f6, "o"},    {0x00f7, "/"},   {0x00f8, "o"},   {0x00f9, "u"},
-    {0x00fa, "u"},    {0x00fb, "u"},   {0x00fc, "u"},   {0x00fd, "y"},
-    {0x00ff, "y"},    {0x02b0, "h"},   {0x02b2, "j"},   {0x02b3, "r"},
-    {0x02b7, "w"},    {0x02b8, "y"},   {0x02b9, "'"},   {0x02ba, "\""},
-    {0x02bb, "'"},    {0x02bc, "'"},   {0x02bd, "'"},   {0x02be, "'"},
-    {0x02bf, "'"},    {0x02c2, "<"},   {0x02c3, ">"},   {0x02c4, "^"},
-    {0x02c5, "v"},    {0x02c6, "^"},   {0x02c7, "v"},   {0x02c8, "'"},
-    {0x02c9, "-"},    {0x02ca, "'"},   {0x02cb, "'"},   {0x02cc, "."},
-    {0x02cd, "_"},    {0x2010, "-"},   {0x2012, "-"},   {0x2013, "-"},
-    {0x2014, "--"},   {0x2015, "--"},  {0x2016, "|"},   {0x2017, "_"},
-    {0x2018, "'"},    {0x2019, "'"},   {0x201a, ","},   {0x201b, "'"},
-    {0x201c, "\""},   {0x201d, "\""},  {0x201e, ","},   {0x201f, "'"},
-    {0x2020, "+"},    {0x2021, "+"},   {0x2022, "*"},   {0x2023, ">"},
-    {0x2024, "."},    {0x2025, ".."},  {0x2027, "."},   {0x2032, "'"},
-    {0x2033, "\""},   {0x2035, "'"},   {0x2036, "\""},  {0x2038, "^"},
-    {0x2039, "<"},    {0x203a, ">"},   {0x203b, "*"},   {0x203c, "!!"},
-    {0x203d, "?!"},   {0x203e, "-"},   {0x2044, "/"},   {0x2047, "??"},
-    {0x2048, "?!"},   {0x2049, "!?"},  {0x204e, "*"},   {0x2052, "%"},
-    {0x2122, "(TM)"}, {0x2212, "-"},   {0x2215, "/"},   {0x2216, "\\"},
-    {0x2217, "*"},    {0x2218, "*"},   {0x2219, "*"},   {0x2223, "|"},
-    {0x22c5, "."},    {0x266f, "#"},   {0XF6D9, "(C)"}, {0XF6DA, "(C)"},
-    {0XF6DB, "(TM)"}, {0XF8E8, "(C)"}, {0xf8e9, "(C)"}, {0XF8EA, "(TM)"},
-    {0xfb01, "fi"},   {0xfb02, "fl"}};
-const FX_CHAR* FCS_GetAltStr(FX_WCHAR unicode) {
-  int begin = 0;
-  int end = sizeof UnicodeAlts / sizeof(struct _UnicodeAlt) - 1;
-  while (begin <= end) {
-    int middle = (begin + end) / 2;
-    uint16_t middlecode = UnicodeAlts[middle].m_Unicode;
-    if (middlecode > unicode) {
-      end = middle - 1;
-    } else if (middlecode < unicode) {
-      begin = middle + 1;
-    } else {
-      return UnicodeAlts[middle].m_Alter;
-    }
-  }
-  return NULL;
-}
-static const uint16_t StandardEncoding[256] = {
+#include "core/fpdfapi/fpdf_parser/include/cpdf_name.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/include/fxge/fx_freetype.h"
+#include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
+
+namespace {
+
+const uint16_t MSSymbolEncoding[256] = {
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 32,     33,     8704,   35,
+    8707,   37,     38,     8715,   40,     41,     8727,   43,     44,
+    8722,   46,     47,     48,     49,     50,     51,     52,     53,
+    54,     55,     56,     57,     58,     59,     60,     61,     62,
+    63,     8773,   913,    914,    935,    916,    917,    934,    915,
+    919,    921,    977,    922,    923,    924,    925,    927,    928,
+    920,    929,    931,    932,    933,    962,    937,    926,    936,
+    918,    91,     8756,   93,     8869,   95,     8254,   945,    946,
+    967,    948,    949,    966,    947,    951,    953,    981,    954,
+    955,    956,    957,    959,    960,    952,    961,    963,    964,
+    965,    982,    969,    958,    968,    950,    123,    124,    125,
+    8764,   0,      0,      0,      0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 978,
+    8242,   8804,   8725,   8734,   402,    9827,   9830,   9828,   9824,
+    8596,   8592,   8593,   8594,   8595,   176,    177,    8243,   8805,
+    215,    8733,   8706,   8729,   247,    8800,   8801,   8776,   8943,
+    0,      0,      8629,   0,      8465,   8476,   8472,   8855,   8853,
+    8709,   8745,   8746,   8835,   8839,   8836,   8834,   8838,   8712,
+    8713,   8736,   8711,   174,    169,    8482,   8719,   8730,   8901,
+    172,    8743,   8744,   8660,   8656,   8657,   8658,   8659,   9674,
+    9001,   0,      0,      0,      8721,   0,      0,      0,      0,
+    0,      0,      0,      0,      0,      0,      0x0000, 9002,   8747,
+    8992,   0,      8993,   0,      0,      0,      0,      0,      0,
+    0x0000, 0x0000, 0x0000, 0x0000};
+
+const uint16_t StandardEncoding[256] = {
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -101,7 +76,8 @@
     0x0152, 0x00ba, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00e6, 0x0000,
     0x0000, 0x0000, 0x0131, 0x0000, 0x0000, 0x0142, 0x00f8, 0x0153, 0x00df,
     0x0000, 0x0000, 0x0000, 0x0000};
-static const uint16_t MacRomanEncoding[256] = {
+
+const uint16_t MacRomanEncoding[256] = {
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -131,7 +107,8 @@
     0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4, 0x0000, 0x00d2, 0x00da,
     0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc, 0x00af, 0x02d8, 0x02d9, 0x02da,
     0x00b8, 0x02dd, 0x02db, 0x02c7};
-static const uint16_t AdobeWinAnsiEncoding[256] = {
+
+const uint16_t AdobeWinAnsiEncoding[256] = {
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -161,7 +138,8 @@
     0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2,
     0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb,
     0x00fc, 0x00fd, 0x00fe, 0x00ff};
-static const uint16_t MacExpertEncoding[256] = {
+
+const uint16_t MacExpertEncoding[256] = {
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -191,7 +169,8 @@
     0xf6f2, 0xf6eb, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf6ee, 0xf6fb,
     0xf6f4, 0xf7af, 0xf6ea, 0x207f, 0xf6ef, 0xf6e2, 0xf6e8, 0xf6f7, 0xf6fc,
     0x0000, 0x0000, 0x0000, 0x0000};
-static const uint16_t AdobeSymbolEncoding[256] = {
+
+const uint16_t AdobeSymbolEncoding[256] = {
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -222,7 +201,8 @@
     0x2320, 0xF8F5, 0x2321, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, 0xF8FA, 0xF8FB,
     0xF8FC, 0xF8FD, 0xF8FE, 0x0000,
 };
-static const uint16_t ZapfEncoding[256] = {
+
+const uint16_t ZapfEncoding[256] = {
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -253,7 +233,8 @@
     0x27B3, 0x27B4, 0x27B5, 0x27B6, 0x27B7, 0x27B8, 0x27B9, 0x27BA, 0x27BB,
     0x27BC, 0x27BD, 0x27BE, 0x0000,
 };
-static const FX_CHAR* const StandardEncodingNames[224] = {
+
+const FX_CHAR* const StandardEncodingNames[224] = {
     "space",
     "exclam",
     "quotedbl",
@@ -479,7 +460,8 @@
     NULL,
     NULL,
 };
-static const FX_CHAR* const AdobeWinAnsiEncodingNames[224] = {
+
+const FX_CHAR* const AdobeWinAnsiEncodingNames[224] = {
     "space",
     "exclam",
     "quotedbl",
@@ -705,7 +687,8 @@
     "thorn",
     "ydieresis",
 };
-static const FX_CHAR* const MacRomanEncodingNames[224] = {
+
+const FX_CHAR* const MacRomanEncodingNames[224] = {
     "space",
     "exclam",
     "quotedbl",
@@ -931,7 +914,8 @@
     "ogonek",
     "caron",
 };
-static const FX_CHAR* const MacExpertEncodingNames[224] = {
+
+const FX_CHAR* const MacExpertEncodingNames[224] = {
     "space",
     "exclamsmall",
     "Hungarumlautsmall",
@@ -1157,7 +1141,8 @@
     NULL,
     NULL,
 };
-static const FX_CHAR* const PDFDocEncodingNames[232] = {
+
+const FX_CHAR* const PDFDocEncodingNames[232] = {
     "breve",
     "caron",
     "circumflex",
@@ -1391,7 +1376,8 @@
     "thorn",
     "ydieresis",
 };
-static const FX_CHAR* const AdobeSymbolEncodingNames[224] = {
+
+const FX_CHAR* const AdobeSymbolEncodingNames[224] = {
     "space",
     "exclam",
     "universal",
@@ -1617,7 +1603,8 @@
     "bracerightbt",
     NULL,
 };
-static const FX_CHAR* const ZapfEncodingNames[224] = {
+
+const FX_CHAR* const ZapfEncodingNames[224] = {
     "space", "a1",   "a2",   "a202", "a3",   "a4",   "a5",   "a119", "a118",
     "a117",  "a11",  "a12",  "a13",  "a14",  "a15",  "a16",  "a105", "a17",
     "a18",   "a19",  "a20",  "a21",  "a22",  "a23",  "a24",  "a25",  "a26",
@@ -1643,91 +1630,89 @@
     "a176",  "a177", "a178", "a179", "a193", "a180", "a199", "a181", "a200",
     "a182",  NULL,   "a201", "a183", "a184", "a197", "a185", "a194", "a198",
     "a186",  "a195", "a187", "a188", "a189", "a190", "a191", NULL};
-const FX_CHAR* PDF_CharNameFromPredefinedCharSet(int encoding,
-                                                 uint8_t charcode) {
-  if (encoding == PDFFONT_ENCODING_PDFDOC) {
-    if (charcode < 24) {
-      return NULL;
-    }
-    charcode -= 24;
-  } else {
-    if (charcode < 32) {
-      return NULL;
-    }
-    charcode -= 32;
-  }
-  switch (encoding) {
-    case PDFFONT_ENCODING_WINANSI:
-      return AdobeWinAnsiEncodingNames[charcode];
-    case PDFFONT_ENCODING_MACROMAN:
-      return MacRomanEncodingNames[charcode];
-    case PDFFONT_ENCODING_MACEXPERT:
-      return MacExpertEncodingNames[charcode];
-    case PDFFONT_ENCODING_STANDARD:
-      return StandardEncodingNames[charcode];
-    case PDFFONT_ENCODING_ADOBE_SYMBOL:
-      return AdobeSymbolEncodingNames[charcode];
-    case PDFFONT_ENCODING_ZAPFDINGBATS:
-      return ZapfEncodingNames[charcode];
-    case PDFFONT_ENCODING_PDFDOC:
-      return PDFDocEncodingNames[charcode];
-  }
-  return NULL;
-}
-FX_WCHAR FT_UnicodeFromCharCode(int encoding, FX_DWORD charcode) {
-  switch (encoding) {
-    case FXFT_ENCODING_UNICODE:
-      return (uint16_t)charcode;
-    case FXFT_ENCODING_ADOBE_STANDARD:
-      return StandardEncoding[(uint8_t)charcode];
-    case FXFT_ENCODING_ADOBE_EXPERT:
-      return MacExpertEncoding[(uint8_t)charcode];
-    case FXFT_ENCODING_ADOBE_LATIN_1:
-      return AdobeWinAnsiEncoding[(uint8_t)charcode];
-    case FXFT_ENCODING_APPLE_ROMAN:
-      return MacRomanEncoding[(uint8_t)charcode];
-    case PDFFONT_ENCODING_PDFDOC:
-      return PDFDocEncoding[(uint8_t)charcode];
-  }
+
+FX_DWORD PDF_FindCode(const uint16_t* pCodes, uint16_t unicode) {
+  for (FX_DWORD i = 0; i < 256; i++)
+    if (pCodes[i] == unicode)
+      return i;
   return 0;
 }
-static FX_DWORD PDF_FindCode(const uint16_t* pCodes, uint16_t unicode) {
-  for (FX_DWORD i = 0; i < 256; i++)
-    if (pCodes[i] == unicode) {
+
+}  // namespace
+
+CPDF_FontEncoding::CPDF_FontEncoding() {
+  FXSYS_memset(m_Unicodes, 0, sizeof(m_Unicodes));
+}
+
+int CPDF_FontEncoding::CharCodeFromUnicode(FX_WCHAR unicode) const {
+  for (int i = 0; i < 256; i++)
+    if (m_Unicodes[i] == unicode) {
       return i;
     }
-  return 0;
+  return -1;
 }
-static const uint16_t MSSymbolEncoding[256] = {
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 32,     33,     8704,   35,
-    8707,   37,     38,     8715,   40,     41,     8727,   43,     44,
-    8722,   46,     47,     48,     49,     50,     51,     52,     53,
-    54,     55,     56,     57,     58,     59,     60,     61,     62,
-    63,     8773,   913,    914,    935,    916,    917,    934,    915,
-    919,    921,    977,    922,    923,    924,    925,    927,    928,
-    920,    929,    931,    932,    933,    962,    937,    926,    936,
-    918,    91,     8756,   93,     8869,   95,     8254,   945,    946,
-    967,    948,    949,    966,    947,    951,    953,    981,    954,
-    955,    956,    957,    959,    960,    952,    961,    963,    964,
-    965,    982,    969,    958,    968,    950,    123,    124,    125,
-    8764,   0,      0,      0,      0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 978,
-    8242,   8804,   8725,   8734,   402,    9827,   9830,   9828,   9824,
-    8596,   8592,   8593,   8594,   8595,   176,    177,    8243,   8805,
-    215,    8733,   8706,   8729,   247,    8800,   8801,   8776,   8943,
-    0,      0,      8629,   0,      8465,   8476,   8472,   8855,   8853,
-    8709,   8745,   8746,   8835,   8839,   8836,   8834,   8838,   8712,
-    8713,   8736,   8711,   174,    169,    8482,   8719,   8730,   8901,
-    172,    8743,   8744,   8660,   8656,   8657,   8658,   8659,   9674,
-    9001,   0,      0,      0,      8721,   0,      0,      0,      0,
-    0,      0,      0,      0,      0,      0,      0x0000, 9002,   8747,
-    8992,   0,      8993,   0,      0,      0,      0,      0,      0,
-    0x0000, 0x0000, 0x0000, 0x0000};
+
+CPDF_FontEncoding::CPDF_FontEncoding(int PredefinedEncoding) {
+  const uint16_t* pSrc = PDF_UnicodesForPredefinedCharSet(PredefinedEncoding);
+  if (!pSrc) {
+    FXSYS_memset(m_Unicodes, 0, sizeof(m_Unicodes));
+  } else {
+    for (int i = 0; i < 256; i++)
+      m_Unicodes[i] = pSrc[i];
+  }
+}
+
+FX_BOOL CPDF_FontEncoding::IsIdentical(CPDF_FontEncoding* pAnother) const {
+  return FXSYS_memcmp(m_Unicodes, pAnother->m_Unicodes, sizeof(m_Unicodes)) ==
+         0;
+}
+
+CPDF_Object* CPDF_FontEncoding::Realize() {
+  int predefined = 0;
+  for (int cs = PDFFONT_ENCODING_WINANSI; cs < PDFFONT_ENCODING_ZAPFDINGBATS;
+       cs++) {
+    const uint16_t* pSrc = PDF_UnicodesForPredefinedCharSet(cs);
+    FX_BOOL match = TRUE;
+    for (int i = 0; i < 256; ++i) {
+      if (m_Unicodes[i] != pSrc[i]) {
+        match = FALSE;
+        break;
+      }
+    }
+    if (match) {
+      predefined = cs;
+      break;
+    }
+  }
+  if (predefined) {
+    if (predefined == PDFFONT_ENCODING_WINANSI) {
+      return new CPDF_Name("WinAnsiEncoding");
+    }
+    if (predefined == PDFFONT_ENCODING_MACROMAN) {
+      return new CPDF_Name("MacRomanEncoding");
+    }
+    if (predefined == PDFFONT_ENCODING_MACEXPERT) {
+      return new CPDF_Name("MacExpertEncoding");
+    }
+    return NULL;
+  }
+  const uint16_t* pStandard =
+      PDF_UnicodesForPredefinedCharSet(PDFFONT_ENCODING_WINANSI);
+  CPDF_Array* pDiff = new CPDF_Array;
+  for (int i = 0; i < 256; i++) {
+    if (pStandard[i] == m_Unicodes[i]) {
+      continue;
+    }
+    pDiff->Add(new CPDF_Number(i));
+    pDiff->Add(new CPDF_Name(PDF_AdobeNameFromUnicode(m_Unicodes[i])));
+  }
+
+  CPDF_Dictionary* pDict = new CPDF_Dictionary;
+  pDict->SetAtName("BaseEncoding", "WinAnsiEncoding");
+  pDict->SetAt("Differences", pDiff);
+  return pDict;
+}
+
 FX_DWORD FT_CharCodeFromUnicode(int encoding, FX_WCHAR unicode) {
   switch (encoding) {
     case FXFT_ENCODING_UNICODE:
@@ -1768,14 +1753,63 @@
   }
   return NULL;
 }
-FX_DWORD PDF_PredefinedCharCodeFromUnicode(int encoding, FX_WCHAR unicode) {
-  return PDF_FindCode(PDF_UnicodesForPredefinedCharSet(encoding), unicode);
-}
+
 FX_WCHAR PDF_UnicodeFromAdobeName(const FX_CHAR* name) {
   return (FX_WCHAR)(FXFT_unicode_from_adobe_name(name) & 0x7FFFFFFF);
 }
+
 CFX_ByteString PDF_AdobeNameFromUnicode(FX_WCHAR unicode) {
   char glyph_name[64];
   FXFT_adobe_name_from_unicode(glyph_name, unicode);
   return CFX_ByteString(glyph_name);
 }
+
+const FX_CHAR* PDF_CharNameFromPredefinedCharSet(int encoding,
+                                                 uint8_t charcode) {
+  if (encoding == PDFFONT_ENCODING_PDFDOC) {
+    if (charcode < 24)
+      return NULL;
+
+    charcode -= 24;
+  } else {
+    if (charcode < 32)
+      return NULL;
+
+    charcode -= 32;
+  }
+  switch (encoding) {
+    case PDFFONT_ENCODING_WINANSI:
+      return AdobeWinAnsiEncodingNames[charcode];
+    case PDFFONT_ENCODING_MACROMAN:
+      return MacRomanEncodingNames[charcode];
+    case PDFFONT_ENCODING_MACEXPERT:
+      return MacExpertEncodingNames[charcode];
+    case PDFFONT_ENCODING_STANDARD:
+      return StandardEncodingNames[charcode];
+    case PDFFONT_ENCODING_ADOBE_SYMBOL:
+      return AdobeSymbolEncodingNames[charcode];
+    case PDFFONT_ENCODING_ZAPFDINGBATS:
+      return ZapfEncodingNames[charcode];
+    case PDFFONT_ENCODING_PDFDOC:
+      return PDFDocEncodingNames[charcode];
+  }
+  return nullptr;
+}
+
+FX_WCHAR FT_UnicodeFromCharCode(int encoding, FX_DWORD charcode) {
+  switch (encoding) {
+    case FXFT_ENCODING_UNICODE:
+      return (uint16_t)charcode;
+    case FXFT_ENCODING_ADOBE_STANDARD:
+      return StandardEncoding[(uint8_t)charcode];
+    case FXFT_ENCODING_ADOBE_EXPERT:
+      return MacExpertEncoding[(uint8_t)charcode];
+    case FXFT_ENCODING_ADOBE_LATIN_1:
+      return AdobeWinAnsiEncoding[(uint8_t)charcode];
+    case FXFT_ENCODING_APPLE_ROMAN:
+      return MacRomanEncoding[(uint8_t)charcode];
+    case PDFFONT_ENCODING_PDFDOC:
+      return PDFDocEncoding[(uint8_t)charcode];
+  }
+  return 0;
+}
diff --git a/core/fpdfapi/fpdf_font/cpdf_simplefont.cpp b/core/fpdfapi/fpdf_font/cpdf_simplefont.cpp
new file mode 100644
index 0000000..d7057e1
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_simplefont.cpp
@@ -0,0 +1,222 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_font/cpdf_simplefont.h"
+
+#include "core/fpdfapi/fpdf_font/font_int.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/include/fxge/fx_freetype.h"
+
+CPDF_SimpleFont::CPDF_SimpleFont()
+    : m_pCharNames(nullptr), m_BaseEncoding(PDFFONT_ENCODING_BUILTIN) {
+  FXSYS_memset(m_CharWidth, 0xff, sizeof m_CharWidth);
+  FXSYS_memset(m_GlyphIndex, 0xff, sizeof m_GlyphIndex);
+  FXSYS_memset(m_ExtGID, 0xff, sizeof m_ExtGID);
+}
+
+CPDF_SimpleFont::~CPDF_SimpleFont() {
+  delete[] m_pCharNames;
+}
+
+int CPDF_SimpleFont::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) {
+  if (pVertGlyph) {
+    *pVertGlyph = FALSE;
+  }
+  if (charcode > 0xff) {
+    return -1;
+  }
+  int index = m_GlyphIndex[(uint8_t)charcode];
+  if (index == 0xffff) {
+    return -1;
+  }
+  return index;
+}
+
+void CPDF_SimpleFont::LoadCharMetrics(int charcode) {
+  if (!m_Font.GetFace())
+    return;
+
+  if (charcode < 0 || charcode > 0xff) {
+    return;
+  }
+  int glyph_index = m_GlyphIndex[charcode];
+  if (glyph_index == 0xffff) {
+    if (!m_pFontFile && charcode != 32) {
+      LoadCharMetrics(32);
+      m_CharBBox[charcode] = m_CharBBox[32];
+      if (m_bUseFontWidth) {
+        m_CharWidth[charcode] = m_CharWidth[32];
+      }
+    }
+    return;
+  }
+  FXFT_Face face = m_Font.GetFace();
+  int err = FXFT_Load_Glyph(
+      face, glyph_index,
+      FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
+  if (err) {
+    return;
+  }
+  m_CharBBox[charcode] = FX_SMALL_RECT(
+      TT2PDF(FXFT_Get_Glyph_HoriBearingX(face), face),
+      TT2PDF(FXFT_Get_Glyph_HoriBearingY(face), face),
+      TT2PDF(FXFT_Get_Glyph_HoriBearingX(face) + FXFT_Get_Glyph_Width(face),
+             face),
+      TT2PDF(FXFT_Get_Glyph_HoriBearingY(face) - FXFT_Get_Glyph_Height(face),
+             face));
+
+  if (m_bUseFontWidth) {
+    int TT_Width = TT2PDF(FXFT_Get_Glyph_HoriAdvance(face), face);
+    if (m_CharWidth[charcode] == 0xffff) {
+      m_CharWidth[charcode] = TT_Width;
+    } else if (TT_Width && !IsEmbedded()) {
+      m_CharBBox[charcode].right =
+          m_CharBBox[charcode].right * m_CharWidth[charcode] / TT_Width;
+      m_CharBBox[charcode].left =
+          m_CharBBox[charcode].left * m_CharWidth[charcode] / TT_Width;
+    }
+  }
+}
+
+int CPDF_SimpleFont::GetCharWidthF(FX_DWORD charcode, int level) {
+  if (charcode > 0xff) {
+    charcode = 0;
+  }
+  if (m_CharWidth[charcode] == 0xffff) {
+    LoadCharMetrics(charcode);
+    if (m_CharWidth[charcode] == 0xffff) {
+      m_CharWidth[charcode] = 0;
+    }
+  }
+  return (int16_t)m_CharWidth[charcode];
+}
+
+FX_RECT CPDF_SimpleFont::GetCharBBox(FX_DWORD charcode, int level) {
+  if (charcode > 0xff)
+    charcode = 0;
+
+  if (m_CharBBox[charcode].left == FX_SMALL_RECT::kInvalid)
+    LoadCharMetrics(charcode);
+
+  return FX_RECT(m_CharBBox[charcode]);
+}
+
+FX_BOOL CPDF_SimpleFont::LoadCommon() {
+  CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictBy("FontDescriptor");
+  if (pFontDesc) {
+    LoadFontDescriptor(pFontDesc);
+  }
+  CPDF_Array* pWidthArray = m_pFontDict->GetArrayBy("Widths");
+  int width_start = 0, width_end = -1;
+  m_bUseFontWidth = TRUE;
+  if (pWidthArray) {
+    m_bUseFontWidth = FALSE;
+    if (pFontDesc && pFontDesc->KeyExist("MissingWidth")) {
+      int MissingWidth = pFontDesc->GetIntegerBy("MissingWidth");
+      for (int i = 0; i < 256; i++) {
+        m_CharWidth[i] = MissingWidth;
+      }
+    }
+    width_start = m_pFontDict->GetIntegerBy("FirstChar", 0);
+    width_end = m_pFontDict->GetIntegerBy("LastChar", 0);
+    if (width_start >= 0 && width_start <= 255) {
+      if (width_end <= 0 ||
+          width_end >= width_start + (int)pWidthArray->GetCount()) {
+        width_end = width_start + pWidthArray->GetCount() - 1;
+      }
+      if (width_end > 255) {
+        width_end = 255;
+      }
+      for (int i = width_start; i <= width_end; i++) {
+        m_CharWidth[i] = pWidthArray->GetIntegerAt(i - width_start);
+      }
+    }
+  }
+  if (m_pFontFile) {
+    if (m_BaseFont.GetLength() > 8 && m_BaseFont[7] == '+') {
+      m_BaseFont = m_BaseFont.Mid(8);
+    }
+  } else {
+    LoadSubstFont();
+  }
+  if (!(m_Flags & PDFFONT_SYMBOLIC)) {
+    m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
+  }
+  CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding");
+  LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, m_pFontFile != NULL,
+                  m_Font.IsTTFont());
+  LoadGlyphMap();
+  delete[] m_pCharNames;
+  m_pCharNames = NULL;
+  if (!m_Font.GetFace())
+    return TRUE;
+
+  if (m_Flags & PDFFONT_ALLCAP) {
+    unsigned char lowercases[] = {'a', 'z', 0xe0, 0xf6, 0xf8, 0xfd};
+    for (size_t range = 0; range < sizeof lowercases / 2; range++) {
+      for (int i = lowercases[range * 2]; i <= lowercases[range * 2 + 1]; i++) {
+        if (m_GlyphIndex[i] != 0xffff && m_pFontFile) {
+          continue;
+        }
+        m_GlyphIndex[i] = m_GlyphIndex[i - 32];
+        if (m_CharWidth[i - 32]) {
+          m_CharWidth[i] = m_CharWidth[i - 32];
+          m_CharBBox[i] = m_CharBBox[i - 32];
+        }
+      }
+    }
+  }
+  CheckFontMetrics();
+  return TRUE;
+}
+
+void CPDF_SimpleFont::LoadSubstFont() {
+  if (!m_bUseFontWidth && !(m_Flags & PDFFONT_FIXEDPITCH)) {
+    int width = 0, i;
+    for (i = 0; i < 256; i++) {
+      if (m_CharWidth[i] == 0 || m_CharWidth[i] == 0xffff) {
+        continue;
+      }
+      if (width == 0) {
+        width = m_CharWidth[i];
+      } else if (width != m_CharWidth[i]) {
+        break;
+      }
+    }
+    if (i == 256 && width) {
+      m_Flags |= PDFFONT_FIXEDPITCH;
+    }
+  }
+  int weight = m_StemV < 140 ? m_StemV * 5 : (m_StemV * 4 + 140);
+  m_Font.LoadSubst(m_BaseFont, IsTrueTypeFont(), m_Flags, weight, m_ItalicAngle,
+                   0);
+  if (m_Font.GetSubstFont()->m_SubstFlags & FXFONT_SUBST_NONSYMBOL) {
+  }
+}
+
+FX_BOOL CPDF_SimpleFont::IsUnicodeCompatible() const {
+  return m_BaseEncoding != PDFFONT_ENCODING_BUILTIN &&
+         m_BaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL &&
+         m_BaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS;
+}
+
+CFX_WideString CPDF_SimpleFont::UnicodeFromCharCode(FX_DWORD charcode) const {
+  CFX_WideString unicode = CPDF_Font::UnicodeFromCharCode(charcode);
+  if (!unicode.IsEmpty())
+    return unicode;
+  FX_WCHAR ret = m_Encoding.UnicodeFromCharCode((uint8_t)charcode);
+  if (ret == 0)
+    return CFX_WideString();
+  return ret;
+}
+
+FX_DWORD CPDF_SimpleFont::CharCodeFromUnicode(FX_WCHAR unicode) const {
+  FX_DWORD ret = CPDF_Font::CharCodeFromUnicode(unicode);
+  if (ret)
+    return ret;
+  return m_Encoding.CharCodeFromUnicode(unicode);
+}
diff --git a/core/fpdfapi/fpdf_font/cpdf_simplefont.h b/core/fpdfapi/fpdf_font/cpdf_simplefont.h
new file mode 100644
index 0000000..19d6816
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_simplefont.h
@@ -0,0 +1,48 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_FONT_CPDF_SIMPLEFONT_H_
+#define CORE_FPDFAPI_FPDF_FONT_CPDF_SIMPLEFONT_H_
+
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
+#include "core/fxcrt/include/fx_string.h"
+#include "core/fxcrt/include/fx_system.h"
+
+class CPDF_SimpleFont : public CPDF_Font {
+ public:
+  CPDF_SimpleFont();
+  virtual ~CPDF_SimpleFont();
+
+  // CPDF_Font:
+  int GetCharWidthF(FX_DWORD charcode, int level = 0) override;
+  FX_RECT GetCharBBox(FX_DWORD charcode, int level = 0) override;
+  int GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph = NULL) override;
+  FX_BOOL IsUnicodeCompatible() const override;
+  CFX_WideString UnicodeFromCharCode(FX_DWORD charcode) const override;
+  FX_DWORD CharCodeFromUnicode(FX_WCHAR Unicode) const override;
+
+  CPDF_FontEncoding* GetEncoding() { return &m_Encoding; }
+
+ protected:
+  virtual void LoadGlyphMap() = 0;
+
+  FX_BOOL LoadCommon();
+  void LoadSubstFont();
+  void LoadFaceMetrics();
+  void LoadCharMetrics(int charcode);
+
+  CPDF_FontEncoding m_Encoding;
+  uint16_t m_GlyphIndex[256];
+  uint16_t m_ExtGID[256];
+  CFX_ByteString* m_pCharNames;
+  int m_BaseEncoding;
+  uint16_t m_CharWidth[256];
+  FX_SMALL_RECT m_CharBBox[256];
+  FX_BOOL m_bUseFontWidth;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_FONT_CPDF_SIMPLEFONT_H_
diff --git a/core/fpdfapi/fpdf_font/cpdf_truetypefont.cpp b/core/fpdfapi/fpdf_font/cpdf_truetypefont.cpp
new file mode 100644
index 0000000..13e0318
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_truetypefont.cpp
@@ -0,0 +1,225 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_font/cpdf_truetypefont.h"
+
+#include "core/fpdfapi/fpdf_font/font_int.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/include/fxge/fx_font.h"
+
+CPDF_TrueTypeFont::CPDF_TrueTypeFont() {}
+
+bool CPDF_TrueTypeFont::IsTrueTypeFont() const {
+  return true;
+}
+
+const CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() const {
+  return this;
+}
+
+CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() {
+  return this;
+}
+
+FX_BOOL CPDF_TrueTypeFont::Load() {
+  return LoadCommon();
+}
+
+void CPDF_TrueTypeFont::LoadGlyphMap() {
+  if (!m_Font.GetFace())
+    return;
+
+  int baseEncoding = m_BaseEncoding;
+  if (m_pFontFile && m_Font.GetFace()->num_charmaps > 0 &&
+      (baseEncoding == PDFFONT_ENCODING_MACROMAN ||
+       baseEncoding == PDFFONT_ENCODING_WINANSI) &&
+      (m_Flags & PDFFONT_SYMBOLIC)) {
+    FX_BOOL bSupportWin = FALSE;
+    FX_BOOL bSupportMac = FALSE;
+    for (int i = 0; i < FXFT_Get_Face_CharmapCount(m_Font.GetFace()); i++) {
+      int platform_id = FXFT_Get_Charmap_PlatformID(
+          FXFT_Get_Face_Charmaps(m_Font.GetFace())[i]);
+      if (platform_id == 0 || platform_id == 3) {
+        bSupportWin = TRUE;
+      } else if (platform_id == 0 || platform_id == 1) {
+        bSupportMac = TRUE;
+      }
+    }
+    if (baseEncoding == PDFFONT_ENCODING_WINANSI && !bSupportWin) {
+      baseEncoding =
+          bSupportMac ? PDFFONT_ENCODING_MACROMAN : PDFFONT_ENCODING_BUILTIN;
+    } else if (baseEncoding == PDFFONT_ENCODING_MACROMAN && !bSupportMac) {
+      baseEncoding =
+          bSupportWin ? PDFFONT_ENCODING_WINANSI : PDFFONT_ENCODING_BUILTIN;
+    }
+  }
+  if (((baseEncoding == PDFFONT_ENCODING_MACROMAN ||
+        baseEncoding == PDFFONT_ENCODING_WINANSI) &&
+       !m_pCharNames) ||
+      (m_Flags & PDFFONT_NONSYMBOLIC)) {
+    if (!FXFT_Has_Glyph_Names(m_Font.GetFace()) &&
+        (!m_Font.GetFace()->num_charmaps || !m_Font.GetFace()->charmaps)) {
+      int nStartChar = m_pFontDict->GetIntegerBy("FirstChar");
+      if (nStartChar < 0 || nStartChar > 255)
+        return;
+
+      int charcode = 0;
+      for (; charcode < nStartChar; charcode++) {
+        m_GlyphIndex[charcode] = 0;
+      }
+      uint16_t nGlyph = charcode - nStartChar + 3;
+      for (; charcode < 256; charcode++, nGlyph++) {
+        m_GlyphIndex[charcode] = nGlyph;
+      }
+      return;
+    }
+    FX_BOOL bMSUnicode = FT_UseTTCharmap(m_Font.GetFace(), 3, 1);
+    FX_BOOL bMacRoman = FALSE, bMSSymbol = FALSE;
+    if (!bMSUnicode) {
+      if (m_Flags & PDFFONT_NONSYMBOLIC) {
+        bMacRoman = FT_UseTTCharmap(m_Font.GetFace(), 1, 0);
+        bMSSymbol = !bMacRoman && FT_UseTTCharmap(m_Font.GetFace(), 3, 0);
+      } else {
+        bMSSymbol = FT_UseTTCharmap(m_Font.GetFace(), 3, 0);
+        bMacRoman = !bMSSymbol && FT_UseTTCharmap(m_Font.GetFace(), 1, 0);
+      }
+    }
+    FX_BOOL bToUnicode = m_pFontDict->KeyExist("ToUnicode");
+    for (int charcode = 0; charcode < 256; charcode++) {
+      const FX_CHAR* name =
+          GetAdobeCharName(baseEncoding, m_pCharNames, charcode);
+      if (!name) {
+        m_GlyphIndex[charcode] =
+            m_pFontFile ? FXFT_Get_Char_Index(m_Font.GetFace(), charcode) : -1;
+        continue;
+      }
+      m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
+      if (bMSSymbol) {
+        const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
+        for (int j = 0; j < 4; j++) {
+          uint16_t unicode = prefix[j] * 256 + charcode;
+          m_GlyphIndex[charcode] =
+              FXFT_Get_Char_Index(m_Font.GetFace(), unicode);
+          if (m_GlyphIndex[charcode]) {
+            break;
+          }
+        }
+      } else if (m_Encoding.m_Unicodes[charcode]) {
+        if (bMSUnicode) {
+          m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
+              m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]);
+        } else if (bMacRoman) {
+          FX_DWORD maccode = FT_CharCodeFromUnicode(
+              FXFT_ENCODING_APPLE_ROMAN, m_Encoding.m_Unicodes[charcode]);
+          if (!maccode) {
+            m_GlyphIndex[charcode] =
+                FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
+          } else {
+            m_GlyphIndex[charcode] =
+                FXFT_Get_Char_Index(m_Font.GetFace(), maccode);
+          }
+        }
+      }
+      if ((m_GlyphIndex[charcode] == 0 || m_GlyphIndex[charcode] == 0xffff) &&
+          name) {
+        if (name[0] == '.' && FXSYS_strcmp(name, ".notdef") == 0) {
+          m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 32);
+        } else {
+          m_GlyphIndex[charcode] =
+              FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
+          if (m_GlyphIndex[charcode] == 0) {
+            if (bToUnicode) {
+              CFX_WideString wsUnicode = UnicodeFromCharCode(charcode);
+              if (!wsUnicode.IsEmpty()) {
+                m_GlyphIndex[charcode] =
+                    FXFT_Get_Char_Index(m_Font.GetFace(), wsUnicode[0]);
+                m_Encoding.m_Unicodes[charcode] = wsUnicode[0];
+              }
+            }
+            if (m_GlyphIndex[charcode] == 0) {
+              m_GlyphIndex[charcode] =
+                  FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
+            }
+          }
+        }
+      }
+    }
+    return;
+  }
+  if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) {
+    const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
+    FX_BOOL bGotOne = FALSE;
+    for (int charcode = 0; charcode < 256; charcode++) {
+      for (int j = 0; j < 4; j++) {
+        uint16_t unicode = prefix[j] * 256 + charcode;
+        m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), unicode);
+        if (m_GlyphIndex[charcode]) {
+          bGotOne = TRUE;
+          break;
+        }
+      }
+    }
+    if (bGotOne) {
+      if (baseEncoding != PDFFONT_ENCODING_BUILTIN) {
+        for (int charcode = 0; charcode < 256; charcode++) {
+          const FX_CHAR* name =
+              GetAdobeCharName(baseEncoding, m_pCharNames, charcode);
+          if (!name) {
+            continue;
+          }
+          m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
+        }
+      } else if (FT_UseTTCharmap(m_Font.GetFace(), 1, 0)) {
+        for (int charcode = 0; charcode < 256; charcode++) {
+          m_Encoding.m_Unicodes[charcode] =
+              FT_UnicodeFromCharCode(FXFT_ENCODING_APPLE_ROMAN, charcode);
+        }
+      }
+      return;
+    }
+  }
+  if (FT_UseTTCharmap(m_Font.GetFace(), 1, 0)) {
+    FX_BOOL bGotOne = FALSE;
+    for (int charcode = 0; charcode < 256; charcode++) {
+      m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
+      m_Encoding.m_Unicodes[charcode] =
+          FT_UnicodeFromCharCode(FXFT_ENCODING_APPLE_ROMAN, charcode);
+      if (m_GlyphIndex[charcode]) {
+        bGotOne = TRUE;
+      }
+    }
+    if (m_pFontFile || bGotOne) {
+      return;
+    }
+  }
+  if (FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE) == 0) {
+    FX_BOOL bGotOne = FALSE;
+    const uint16_t* pUnicodes = PDF_UnicodesForPredefinedCharSet(baseEncoding);
+    for (int charcode = 0; charcode < 256; charcode++) {
+      if (m_pFontFile) {
+        m_Encoding.m_Unicodes[charcode] = charcode;
+      } else {
+        const FX_CHAR* name = GetAdobeCharName(0, m_pCharNames, charcode);
+        if (name) {
+          m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
+        } else if (pUnicodes) {
+          m_Encoding.m_Unicodes[charcode] = pUnicodes[charcode];
+        }
+      }
+      m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
+          m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]);
+      if (m_GlyphIndex[charcode]) {
+        bGotOne = TRUE;
+      }
+    }
+    if (bGotOne) {
+      return;
+    }
+  }
+  for (int charcode = 0; charcode < 256; charcode++) {
+    m_GlyphIndex[charcode] = charcode;
+  }
+}
diff --git a/core/fpdfapi/fpdf_font/cpdf_truetypefont.h b/core/fpdfapi/fpdf_font/cpdf_truetypefont.h
new file mode 100644
index 0000000..46b19e5
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_truetypefont.h
@@ -0,0 +1,30 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_FONT_CPDF_TRUETYPEFONT_H_
+#define CORE_FPDFAPI_FPDF_FONT_CPDF_TRUETYPEFONT_H_
+
+#include "core/fpdfapi/fpdf_font/cpdf_simplefont.h"
+#include "core/fxcrt/include/fx_system.h"
+
+class CPDF_TrueTypeFont : public CPDF_SimpleFont {
+ public:
+  CPDF_TrueTypeFont();
+
+  // CPDF_Font:
+  bool IsTrueTypeFont() const override;
+  const CPDF_TrueTypeFont* AsTrueTypeFont() const override;
+  CPDF_TrueTypeFont* AsTrueTypeFont() override;
+
+ protected:
+  // CPDF_Font:
+  FX_BOOL Load() override;
+
+  // CPDF_SimpleFont:
+  void LoadGlyphMap() override;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_FONT_CPDF_TRUETYPEFONT_H_
diff --git a/core/fpdfapi/fpdf_font/cpdf_type1font.cpp b/core/fpdfapi/fpdf_font/cpdf_type1font.cpp
new file mode 100644
index 0000000..5a6ee34
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_type1font.cpp
@@ -0,0 +1,403 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_font/cpdf_type1font.h"
+
+#include "core/fpdfapi/fpdf_font/font_int.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/include/fxge/fx_freetype.h"
+
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+#include "core/fxge/apple/apple_int.h"
+#endif
+
+namespace {
+
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+struct GlyphNameMap {
+  const FX_CHAR* m_pStrAdobe;
+  const FX_CHAR* m_pStrUnicode;
+};
+
+const GlyphNameMap g_GlyphNameSubsts[] = {{"ff", "uniFB00"},
+                                          {"fi", "uniFB01"},
+                                          {"fl", "uniFB02"},
+                                          {"ffi", "uniFB03"},
+                                          {"ffl", "uniFB04"}};
+
+int compareString(const void* key, const void* element) {
+  return FXSYS_stricmp((const FX_CHAR*)key,
+                       ((GlyphNameMap*)element)->m_pStrAdobe);
+}
+
+const FX_CHAR* GlyphNameRemap(const FX_CHAR* pStrAdobe) {
+  GlyphNameMap* found = (GlyphNameMap*)FXSYS_bsearch(
+      pStrAdobe, g_GlyphNameSubsts,
+      sizeof(g_GlyphNameSubsts) / sizeof(GlyphNameMap), sizeof(GlyphNameMap),
+      compareString);
+  if (found)
+    return found->m_pStrUnicode;
+  return NULL;
+}
+
+#endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+
+FX_BOOL FT_UseType1Charmap(FXFT_Face face) {
+  if (FXFT_Get_Face_CharmapCount(face) == 0) {
+    return FALSE;
+  }
+  if (FXFT_Get_Face_CharmapCount(face) == 1 &&
+      FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) ==
+          FXFT_ENCODING_UNICODE) {
+    return FALSE;
+  }
+  if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) ==
+      FXFT_ENCODING_UNICODE) {
+    FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[1]);
+  } else {
+    FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]);
+  }
+  return TRUE;
+}
+
+}  // namespace
+
+CPDF_Type1Font::CPDF_Type1Font() : m_Base14Font(-1) {}
+
+bool CPDF_Type1Font::IsType1Font() const {
+  return true;
+}
+
+const CPDF_Type1Font* CPDF_Type1Font::AsType1Font() const {
+  return this;
+}
+
+CPDF_Type1Font* CPDF_Type1Font::AsType1Font() {
+  return this;
+}
+
+FX_BOOL CPDF_Type1Font::Load() {
+  m_Base14Font = PDF_GetStandardFontName(&m_BaseFont);
+  if (m_Base14Font >= 0) {
+    CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictBy("FontDescriptor");
+    if (pFontDesc && pFontDesc->KeyExist("Flags"))
+      m_Flags = pFontDesc->GetIntegerBy("Flags");
+    else
+      m_Flags = m_Base14Font >= 12 ? PDFFONT_SYMBOLIC : PDFFONT_NONSYMBOLIC;
+
+    if (m_Base14Font < 4) {
+      for (int i = 0; i < 256; i++)
+        m_CharWidth[i] = 600;
+    }
+    if (m_Base14Font == 12)
+      m_BaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
+    else if (m_Base14Font == 13)
+      m_BaseEncoding = PDFFONT_ENCODING_ZAPFDINGBATS;
+    else if (m_Flags & PDFFONT_NONSYMBOLIC)
+      m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
+  }
+  return LoadCommon();
+}
+
+int CPDF_Type1Font::GlyphFromCharCodeExt(FX_DWORD charcode) {
+  if (charcode > 0xff) {
+    return -1;
+  }
+  int index = m_ExtGID[(uint8_t)charcode];
+  if (index == 0xffff) {
+    return -1;
+  }
+  return index;
+}
+
+void CPDF_Type1Font::LoadGlyphMap() {
+  if (!m_Font.GetFace())
+    return;
+
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+  FX_BOOL bCoreText = TRUE;
+  CQuartz2D& quartz2d =
+      ((CApplePlatform*)CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
+  if (!m_Font.GetPlatformFont()) {
+    if (m_Font.GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) {
+      bCoreText = FALSE;
+    }
+    m_Font.SetPlatformFont(
+        quartz2d.CreateFont(m_Font.GetFontData(), m_Font.GetSize()));
+    if (!m_Font.GetPlatformFont()) {
+      bCoreText = FALSE;
+    }
+  }
+#endif
+  if (!IsEmbedded() && (m_Base14Font < 12) && m_Font.IsTTFont()) {
+    if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) {
+      FX_BOOL bGotOne = FALSE;
+      for (int charcode = 0; charcode < 256; charcode++) {
+        const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
+        for (int j = 0; j < 4; j++) {
+          uint16_t unicode = prefix[j] * 256 + charcode;
+          m_GlyphIndex[charcode] =
+              FXFT_Get_Char_Index(m_Font.GetFace(), unicode);
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+          FX_CHAR name_glyph[256];
+          FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
+                              name_glyph, 256);
+          name_glyph[255] = 0;
+          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
+              kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
+              kCFAllocatorNull);
+          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
+              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
+          if (name_ct) {
+            CFRelease(name_ct);
+          }
+#endif
+          if (m_GlyphIndex[charcode]) {
+            bGotOne = TRUE;
+            break;
+          }
+        }
+      }
+      if (bGotOne) {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+        if (!bCoreText) {
+          FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
+        }
+#endif
+        return;
+      }
+    }
+    FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE);
+    if (m_BaseEncoding == 0) {
+      m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
+    }
+    for (int charcode = 0; charcode < 256; charcode++) {
+      const FX_CHAR* name =
+          GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
+      if (!name) {
+        continue;
+      }
+      m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
+      m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
+          m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]);
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+      FX_CHAR name_glyph[256];
+      FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], name_glyph,
+                          256);
+      name_glyph[255] = 0;
+      CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
+          kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
+          kCFAllocatorNull);
+      m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
+          (CGFontRef)m_Font.GetPlatformFont(), name_ct);
+      if (name_ct) {
+        CFRelease(name_ct);
+      }
+#endif
+      if (m_GlyphIndex[charcode] == 0 && FXSYS_strcmp(name, ".notdef") == 0) {
+        m_Encoding.m_Unicodes[charcode] = 0x20;
+        m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 0x20);
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+        FX_CHAR name_glyph[256];
+        FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
+                            name_glyph, 256);
+        name_glyph[255] = 0;
+        CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
+            kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
+            kCFAllocatorNull);
+        m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
+            (CGFontRef)m_Font.GetPlatformFont(), name_ct);
+        if (name_ct) {
+          CFRelease(name_ct);
+        }
+#endif
+      }
+    }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+    if (!bCoreText) {
+      FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
+    }
+#endif
+    return;
+  }
+  FT_UseType1Charmap(m_Font.GetFace());
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+  if (bCoreText) {
+    if (m_Flags & PDFFONT_SYMBOLIC) {
+      for (int charcode = 0; charcode < 256; charcode++) {
+        const FX_CHAR* name =
+            GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
+        if (name) {
+          m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
+          m_GlyphIndex[charcode] =
+              FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
+          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
+              kCFAllocatorDefault, name, kCFStringEncodingASCII,
+              kCFAllocatorNull);
+          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
+              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
+          if (name_ct) {
+            CFRelease(name_ct);
+          }
+        } else {
+          m_GlyphIndex[charcode] =
+              FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
+          FX_WCHAR unicode = 0;
+          if (m_GlyphIndex[charcode]) {
+            unicode =
+                FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);
+          }
+          FX_CHAR name_glyph[256];
+          FXSYS_memset(name_glyph, 0, sizeof(name_glyph));
+          FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
+                              name_glyph, 256);
+          name_glyph[255] = 0;
+          if (unicode == 0 && name_glyph[0] != 0) {
+            unicode = PDF_UnicodeFromAdobeName(name_glyph);
+          }
+          m_Encoding.m_Unicodes[charcode] = unicode;
+          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
+              kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
+              kCFAllocatorNull);
+          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
+              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
+          if (name_ct) {
+            CFRelease(name_ct);
+          }
+        }
+      }
+      return;
+    }
+    FX_BOOL bUnicode = FALSE;
+    if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) {
+      bUnicode = TRUE;
+    }
+    for (int charcode = 0; charcode < 256; charcode++) {
+      const FX_CHAR* name =
+          GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
+      if (!name) {
+        continue;
+      }
+      m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
+      const FX_CHAR* pStrUnicode = GlyphNameRemap(name);
+      if (pStrUnicode &&
+          0 == FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name)) {
+        name = pStrUnicode;
+      }
+      m_GlyphIndex[charcode] =
+          FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
+      CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
+          kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull);
+      m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
+          (CGFontRef)m_Font.GetPlatformFont(), name_ct);
+      if (name_ct) {
+        CFRelease(name_ct);
+      }
+      if (m_GlyphIndex[charcode] == 0) {
+        if (FXSYS_strcmp(name, ".notdef") != 0 &&
+            FXSYS_strcmp(name, "space") != 0) {
+          m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
+              m_Font.GetFace(),
+              bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);
+          FX_CHAR name_glyph[256];
+          FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
+                              name_glyph, 256);
+          name_glyph[255] = 0;
+          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
+              kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
+              kCFAllocatorNull);
+          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
+              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
+          if (name_ct) {
+            CFRelease(name_ct);
+          }
+        } else {
+          m_Encoding.m_Unicodes[charcode] = 0x20;
+          m_GlyphIndex[charcode] =
+              bUnicode ? FXFT_Get_Char_Index(m_Font.GetFace(), 0x20) : 0xffff;
+          FX_CHAR name_glyph[256];
+          FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
+                              name_glyph, 256);
+          name_glyph[255] = 0;
+          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
+              kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
+              kCFAllocatorNull);
+          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
+              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
+          if (name_ct) {
+            CFRelease(name_ct);
+          }
+        }
+      }
+    }
+    return;
+  }
+#endif
+  if (m_Flags & PDFFONT_SYMBOLIC) {
+    for (int charcode = 0; charcode < 256; charcode++) {
+      const FX_CHAR* name =
+          GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
+      if (name) {
+        m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
+        m_GlyphIndex[charcode] =
+            FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
+      } else {
+        m_GlyphIndex[charcode] =
+            FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
+        if (m_GlyphIndex[charcode]) {
+          FX_WCHAR unicode =
+              FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);
+          if (unicode == 0) {
+            FX_CHAR name_glyph[256];
+            FXSYS_memset(name_glyph, 0, sizeof(name_glyph));
+            FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
+                                name_glyph, 256);
+            name_glyph[255] = 0;
+            if (name_glyph[0] != 0) {
+              unicode = PDF_UnicodeFromAdobeName(name_glyph);
+            }
+          }
+          m_Encoding.m_Unicodes[charcode] = unicode;
+        }
+      }
+    }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+    if (!bCoreText) {
+      FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
+    }
+#endif
+    return;
+  }
+  FX_BOOL bUnicode = FALSE;
+  if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) {
+    bUnicode = TRUE;
+  }
+  for (int charcode = 0; charcode < 256; charcode++) {
+    const FX_CHAR* name =
+        GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
+    if (!name) {
+      continue;
+    }
+    m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
+    m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
+    if (m_GlyphIndex[charcode] == 0) {
+      if (FXSYS_strcmp(name, ".notdef") != 0 &&
+          FXSYS_strcmp(name, "space") != 0) {
+        m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
+            m_Font.GetFace(),
+            bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);
+      } else {
+        m_Encoding.m_Unicodes[charcode] = 0x20;
+        m_GlyphIndex[charcode] = 0xffff;
+      }
+    }
+  }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+  if (!bCoreText) {
+    FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
+  }
+#endif
+}
diff --git a/core/fpdfapi/fpdf_font/cpdf_type1font.h b/core/fpdfapi/fpdf_font/cpdf_type1font.h
new file mode 100644
index 0000000..da82cd4
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_type1font.h
@@ -0,0 +1,35 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE1FONT_H_
+#define CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE1FONT_H_
+
+#include "core/fpdfapi/fpdf_font/cpdf_simplefont.h"
+#include "core/fxcrt/include/fx_system.h"
+
+class CPDF_Type1Font : public CPDF_SimpleFont {
+ public:
+  CPDF_Type1Font();
+
+  // CPDF_Font:
+  bool IsType1Font() const override;
+  const CPDF_Type1Font* AsType1Font() const override;
+  CPDF_Type1Font* AsType1Font() override;
+  int GlyphFromCharCodeExt(FX_DWORD charcode) override;
+
+  int GetBase14Font() const { return m_Base14Font; }
+
+ protected:
+  // CPDF_Font:
+  FX_BOOL Load() override;
+
+  // CPDF_SimpleFont:
+  void LoadGlyphMap() override;
+
+  int m_Base14Font;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE1FONT_H_
diff --git a/core/fpdfapi/fpdf_font/cpdf_type3char.cpp b/core/fpdfapi/fpdf_font/cpdf_type3char.cpp
new file mode 100644
index 0000000..c9d4443
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_type3char.cpp
@@ -0,0 +1,43 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_font/cpdf_type3char.h"
+
+#include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
+#include "core/include/fxge/fx_dib.h"
+
+CPDF_Type3Char::CPDF_Type3Char(CPDF_Form* pForm)
+    : m_pForm(pForm), m_pBitmap(nullptr), m_bColored(FALSE) {}
+
+CPDF_Type3Char::~CPDF_Type3Char() {
+  delete m_pForm;
+  delete m_pBitmap;
+}
+
+FX_BOOL CPDF_Type3Char::LoadBitmap(CPDF_RenderContext* pContext) {
+  if (m_pBitmap || !m_pForm) {
+    return TRUE;
+  }
+  if (m_pForm->GetPageObjectList()->size() == 1 && !m_bColored) {
+    auto& pPageObj = m_pForm->GetPageObjectList()->front();
+    if (pPageObj->IsImage()) {
+      m_ImageMatrix = pPageObj->AsImage()->m_Matrix;
+      const CFX_DIBSource* pSource =
+          pPageObj->AsImage()->m_pImage->LoadDIBSource();
+      if (pSource) {
+        m_pBitmap = pSource->Clone();
+        delete pSource;
+      }
+      delete m_pForm;
+      m_pForm = NULL;
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
diff --git a/core/fpdfapi/fpdf_font/cpdf_type3char.h b/core/fpdfapi/fpdf_font/cpdf_type3char.h
new file mode 100644
index 0000000..c67620b
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_type3char.h
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE3CHAR_H_
+#define CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE3CHAR_H_
+
+#include "core/fxcrt/include/fx_coordinates.h"
+#include "core/fxcrt/include/fx_system.h"
+
+class CFX_DIBitmap;
+class CPDF_Form;
+class CPDF_RenderContext;
+
+class CPDF_Type3Char {
+ public:
+  // Takes ownership of |pForm|.
+  explicit CPDF_Type3Char(CPDF_Form* pForm);
+  ~CPDF_Type3Char();
+
+  FX_BOOL LoadBitmap(CPDF_RenderContext* pContext);
+
+  CPDF_Form* m_pForm;
+  CFX_DIBitmap* m_pBitmap;
+  FX_BOOL m_bColored;
+  int m_Width;
+  CFX_Matrix m_ImageMatrix;
+  FX_RECT m_BBox;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE3CHAR_H_
diff --git a/core/fpdfapi/fpdf_font/cpdf_type3font.cpp b/core/fpdfapi/fpdf_font/cpdf_type3font.cpp
new file mode 100644
index 0000000..91a03a9
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_type3font.cpp
@@ -0,0 +1,162 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
+
+#include "core/fpdfapi/fpdf_font/cpdf_type3char.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
+#include "core/fpdfapi/fpdf_page/pageint.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/fxcrt/include/fx_system.h"
+#include "third_party/base/stl_util.h"
+
+CPDF_Type3Font::CPDF_Type3Font()
+    : m_pCharProcs(nullptr),
+      m_pPageResources(nullptr),
+      m_pFontResources(nullptr) {
+  FXSYS_memset(m_CharWidthL, 0, sizeof(m_CharWidthL));
+}
+
+CPDF_Type3Font::~CPDF_Type3Font() {
+  for (auto it : m_CacheMap)
+    delete it.second;
+}
+
+bool CPDF_Type3Font::IsType3Font() const {
+  return true;
+}
+
+const CPDF_Type3Font* CPDF_Type3Font::AsType3Font() const {
+  return this;
+}
+
+CPDF_Type3Font* CPDF_Type3Font::AsType3Font() {
+  return this;
+}
+
+FX_BOOL CPDF_Type3Font::Load() {
+  m_pFontResources = m_pFontDict->GetDictBy("Resources");
+  CPDF_Array* pMatrix = m_pFontDict->GetArrayBy("FontMatrix");
+  FX_FLOAT xscale = 1.0f, yscale = 1.0f;
+  if (pMatrix) {
+    m_FontMatrix = pMatrix->GetMatrix();
+    xscale = m_FontMatrix.a;
+    yscale = m_FontMatrix.d;
+  }
+  CPDF_Array* pBBox = m_pFontDict->GetArrayBy("FontBBox");
+  if (pBBox) {
+    m_FontBBox.left = (int32_t)(pBBox->GetNumberAt(0) * xscale * 1000);
+    m_FontBBox.bottom = (int32_t)(pBBox->GetNumberAt(1) * yscale * 1000);
+    m_FontBBox.right = (int32_t)(pBBox->GetNumberAt(2) * xscale * 1000);
+    m_FontBBox.top = (int32_t)(pBBox->GetNumberAt(3) * yscale * 1000);
+  }
+  int StartChar = m_pFontDict->GetIntegerBy("FirstChar");
+  CPDF_Array* pWidthArray = m_pFontDict->GetArrayBy("Widths");
+  if (pWidthArray && (StartChar >= 0 && StartChar < 256)) {
+    FX_DWORD count = pWidthArray->GetCount();
+    if (count > 256) {
+      count = 256;
+    }
+    if (StartChar + count > 256) {
+      count = 256 - StartChar;
+    }
+    for (FX_DWORD i = 0; i < count; i++) {
+      m_CharWidthL[StartChar + i] =
+          FXSYS_round(pWidthArray->GetNumberAt(i) * xscale * 1000);
+    }
+  }
+  m_pCharProcs = m_pFontDict->GetDictBy("CharProcs");
+  CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding");
+  if (pEncoding) {
+    LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, FALSE, FALSE);
+    if (m_pCharNames) {
+      for (int i = 0; i < 256; i++) {
+        m_Encoding.m_Unicodes[i] = PDF_UnicodeFromAdobeName(m_pCharNames[i]);
+        if (m_Encoding.m_Unicodes[i] == 0) {
+          m_Encoding.m_Unicodes[i] = i;
+        }
+      }
+    }
+  }
+  return TRUE;
+}
+
+void CPDF_Type3Font::CheckType3FontMetrics() {
+  CheckFontMetrics();
+}
+
+CPDF_Type3Char* CPDF_Type3Font::LoadChar(FX_DWORD charcode, int level) {
+  if (level >= _FPDF_MAX_TYPE3_FORM_LEVEL_)
+    return nullptr;
+
+  auto it = m_CacheMap.find(charcode);
+  if (it != m_CacheMap.end())
+    return it->second;
+
+  const FX_CHAR* name =
+      GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
+  if (!name)
+    return nullptr;
+
+  CPDF_Stream* pStream =
+      ToStream(m_pCharProcs ? m_pCharProcs->GetElementValue(name) : nullptr);
+  if (!pStream)
+    return nullptr;
+
+  std::unique_ptr<CPDF_Type3Char> pNewChar(new CPDF_Type3Char(new CPDF_Form(
+      m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources,
+      pStream, nullptr)));
+
+  // This can trigger recursion into this method. The content of |m_CacheMap|
+  // can change as a result. Thus after it returns, check the cache again for
+  // a cache hit.
+  pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get(), nullptr,
+                                  level + 1);
+  it = m_CacheMap.find(charcode);
+  if (it != m_CacheMap.end())
+    return it->second;
+
+  FX_FLOAT scale = m_FontMatrix.GetXUnit();
+  pNewChar->m_Width = (int32_t)(pNewChar->m_Width * scale + 0.5f);
+  FX_RECT& rcBBox = pNewChar->m_BBox;
+  CFX_FloatRect char_rect(
+      (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f,
+      (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f);
+  if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top)
+    char_rect = pNewChar->m_pForm->CalcBoundingBox();
+
+  char_rect.Transform(&m_FontMatrix);
+  rcBBox.left = FXSYS_round(char_rect.left * 1000);
+  rcBBox.right = FXSYS_round(char_rect.right * 1000);
+  rcBBox.top = FXSYS_round(char_rect.top * 1000);
+  rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000);
+
+  ASSERT(!pdfium::ContainsKey(m_CacheMap, charcode));
+  CPDF_Type3Char* pCachedChar = pNewChar.release();
+  m_CacheMap[charcode] = pCachedChar;
+  if (pCachedChar->m_pForm->GetPageObjectList()->empty()) {
+    delete pCachedChar->m_pForm;
+    pCachedChar->m_pForm = nullptr;
+  }
+  return pCachedChar;
+}
+
+int CPDF_Type3Font::GetCharWidthF(FX_DWORD charcode, int level) {
+  if (charcode >= FX_ArraySize(m_CharWidthL))
+    charcode = 0;
+
+  if (m_CharWidthL[charcode])
+    return m_CharWidthL[charcode];
+
+  const CPDF_Type3Char* pChar = LoadChar(charcode, level);
+  return pChar ? pChar->m_Width : 0;
+}
+
+FX_RECT CPDF_Type3Font::GetCharBBox(FX_DWORD charcode, int level) {
+  const CPDF_Type3Char* pChar = LoadChar(charcode, level);
+  return pChar ? pChar->m_BBox : FX_RECT();
+}
diff --git a/core/fpdfapi/fpdf_font/cpdf_type3font.h b/core/fpdfapi/fpdf_font/cpdf_type3font.h
new file mode 100644
index 0000000..5545569
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/cpdf_type3font.h
@@ -0,0 +1,56 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE3FONT_H_
+#define CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE3FONT_H_
+
+#include <map>
+
+#include "core/fpdfapi/fpdf_font/cpdf_simplefont.h"
+#include "core/fxcrt/include/fx_coordinates.h"
+#include "core/fxcrt/include/fx_system.h"
+
+class CPDF_Dictionary;
+class CPDF_Type3Char;
+
+class CPDF_Type3Font : public CPDF_SimpleFont {
+ public:
+  CPDF_Type3Font();
+  ~CPDF_Type3Font() override;
+
+  // CPDF_Font:
+  bool IsType3Font() const override;
+  const CPDF_Type3Font* AsType3Font() const override;
+  CPDF_Type3Font* AsType3Font() override;
+  int GetCharWidthF(FX_DWORD charcode, int level = 0) override;
+  FX_RECT GetCharBBox(FX_DWORD charcode, int level = 0) override;
+
+  void SetPageResources(CPDF_Dictionary* pResources) {
+    m_pPageResources = pResources;
+  }
+  CPDF_Type3Char* LoadChar(FX_DWORD charcode, int level = 0);
+  void CheckType3FontMetrics();
+
+  CFX_Matrix& GetFontMatrix() { return m_FontMatrix; }
+
+ protected:
+  CFX_Matrix m_FontMatrix;
+
+ private:
+  // CPDF_Font:
+  FX_BOOL Load() override;
+
+  // CPDF_SimpleFont:
+  void LoadGlyphMap() override {}
+
+  int m_CharWidthL[256];
+  CPDF_Dictionary* m_pCharProcs;
+  CPDF_Dictionary* m_pPageResources;
+  CPDF_Dictionary* m_pFontResources;
+  std::map<FX_DWORD, CPDF_Type3Char*> m_CacheMap;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_FONT_CPDF_TYPE3FONT_H_
diff --git a/core/fpdfapi/fpdf_font/font_int.h b/core/fpdfapi/fpdf_font/font_int.h
index 74380f1..b9b5b53 100644
--- a/core/fpdfapi/fpdf_font/font_int.h
+++ b/core/fpdfapi/fpdf_font/font_int.h
@@ -10,8 +10,8 @@
 #include <map>
 #include <memory>
 
+#include "core/fpdfapi/fpdf_font/cpdf_cidfont.h"
 #include "core/fxcrt/include/fx_basic.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 
 class CPDF_CID2UnicodeMap;
 class CPDF_CMap;
@@ -22,6 +22,7 @@
 
 short TT2PDF(int m, FXFT_Face face);
 FX_BOOL FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id);
+CIDSet CharsetFromOrdering(const CFX_ByteString& ordering);
 
 class CPDF_CMapManager {
  public:
diff --git a/core/fpdfapi/fpdf_font/fpdf_font.cpp b/core/fpdfapi/fpdf_font/fpdf_font.cpp
index 8dc9161..c0c6f52 100644
--- a/core/fpdfapi/fpdf_font/fpdf_font.cpp
+++ b/core/fpdfapi/fpdf_font/fpdf_font.cpp
@@ -14,87 +14,12 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_name.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
 #include "core/fxcrt/include/fx_ext.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "core/include/fxge/fx_freetype.h"
 #include "third_party/base/stl_util.h"
 
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-#include "core/fxge/apple/apple_int.h"
-#endif
-
-namespace {
-
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-struct GlyphNameMap {
-  const FX_CHAR* m_pStrAdobe;
-  const FX_CHAR* m_pStrUnicode;
-};
-
-const GlyphNameMap g_GlyphNameSubsts[] = {{"ff", "uniFB00"},
-                                          {"fi", "uniFB01"},
-                                          {"fl", "uniFB02"},
-                                          {"ffi", "uniFB03"},
-                                          {"ffl", "uniFB04"}};
-
-int compareString(const void* key, const void* element) {
-  return FXSYS_stricmp((const FX_CHAR*)key,
-                       ((GlyphNameMap*)element)->m_pStrAdobe);
-}
-
-const FX_CHAR* GlyphNameRemap(const FX_CHAR* pStrAdobe) {
-  GlyphNameMap* found = (GlyphNameMap*)FXSYS_bsearch(
-      pStrAdobe, g_GlyphNameSubsts,
-      sizeof(g_GlyphNameSubsts) / sizeof(GlyphNameMap), sizeof(GlyphNameMap),
-      compareString);
-  if (found)
-    return found->m_pStrUnicode;
-  return NULL;
-}
-#endif
-
-const uint8_t ChineseFontNames[][5] = {{0xCB, 0xCE, 0xCC, 0xE5, 0x00},
-                                       {0xBF, 0xAC, 0xCC, 0xE5, 0x00},
-                                       {0xBA, 0xDA, 0xCC, 0xE5, 0x00},
-                                       {0xB7, 0xC2, 0xCB, 0xCE, 0x00},
-                                       {0xD0, 0xC2, 0xCB, 0xCE, 0x00}};
-
-FX_BOOL GetPredefinedEncoding(int& basemap, const CFX_ByteString& value) {
-  if (value == "WinAnsiEncoding") {
-    basemap = PDFFONT_ENCODING_WINANSI;
-  } else if (value == "MacRomanEncoding") {
-    basemap = PDFFONT_ENCODING_MACROMAN;
-  } else if (value == "MacExpertEncoding") {
-    basemap = PDFFONT_ENCODING_MACEXPERT;
-  } else if (value == "PDFDocEncoding") {
-    basemap = PDFFONT_ENCODING_PDFDOC;
-  } else {
-    return FALSE;
-  }
-  return TRUE;
-}
-
-FX_BOOL FT_UseType1Charmap(FXFT_Face face) {
-  if (FXFT_Get_Face_CharmapCount(face) == 0) {
-    return FALSE;
-  }
-  if (FXFT_Get_Face_CharmapCount(face) == 1 &&
-      FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) ==
-          FXFT_ENCODING_UNICODE) {
-    return FALSE;
-  }
-  if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) ==
-      FXFT_ENCODING_UNICODE) {
-    FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[1]);
-  } else {
-    FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]);
-  }
-  return TRUE;
-}
-
-}  // namespace
-
 FX_BOOL FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id) {
   for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
     if (FXFT_Get_Charmap_PlatformID(FXFT_Get_Face_Charmaps(face)[i]) ==
@@ -156,356 +81,15 @@
   m_StockMap.erase(pDoc);
 }
 
-CPDF_Font::CPDF_Font()
-    : m_pFontFile(nullptr),
-      m_pFontDict(nullptr),
-      m_pToUnicodeMap(nullptr),
-      m_bToUnicodeLoaded(FALSE),
-      m_Flags(0),
-      m_StemV(0),
-      m_Ascent(0),
-      m_Descent(0),
-      m_ItalicAngle(0) {}
 
-CPDF_Font::~CPDF_Font() {
-  delete m_pToUnicodeMap;
-  m_pToUnicodeMap = NULL;
-
-  if (m_pFontFile) {
-    m_pDocument->GetPageData()->ReleaseFontFileStreamAcc(
-        const_cast<CPDF_Stream*>(m_pFontFile->GetStream()->AsStream()));
-  }
-}
-
-bool CPDF_Font::IsType1Font() const {
-  return false;
-}
-
-bool CPDF_Font::IsTrueTypeFont() const {
-  return false;
-}
-
-bool CPDF_Font::IsType3Font() const {
-  return false;
-}
-
-bool CPDF_Font::IsCIDFont() const {
-  return false;
-}
-
-const CPDF_Type1Font* CPDF_Font::AsType1Font() const {
-  return nullptr;
-}
-
-CPDF_Type1Font* CPDF_Font::AsType1Font() {
-  return nullptr;
-}
-
-const CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() const {
-  return nullptr;
-}
-
-CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() {
-  return nullptr;
-}
-
-const CPDF_Type3Font* CPDF_Font::AsType3Font() const {
-  return nullptr;
-}
-
-CPDF_Type3Font* CPDF_Font::AsType3Font() {
-  return nullptr;
-}
-
-const CPDF_CIDFont* CPDF_Font::AsCIDFont() const {
-  return nullptr;
-}
-
-CPDF_CIDFont* CPDF_Font::AsCIDFont() {
-  return nullptr;
-}
-
-FX_BOOL CPDF_Font::IsUnicodeCompatible() const {
-  return FALSE;
-}
-
-int CPDF_Font::CountChar(const FX_CHAR* pString, int size) const {
-  return size;
-}
-
-int CPDF_Font::GetCharSize(FX_DWORD charcode) const {
-  return 1;
-}
-
-int CPDF_Font::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) {
-  ASSERT(false);
-  return 0;
-}
-
-int CPDF_Font::GlyphFromCharCodeExt(FX_DWORD charcode) {
-  return GlyphFromCharCode(charcode);
-}
-
-FX_BOOL CPDF_Font::IsVertWriting() const {
-  FX_BOOL bVertWriting = FALSE;
-  const CPDF_CIDFont* pCIDFont = AsCIDFont();
-  if (pCIDFont) {
-    bVertWriting = pCIDFont->IsVertWriting();
-  } else {
-    bVertWriting = m_Font.IsVertical();
-  }
-  return bVertWriting;
-}
-
-int CPDF_Font::AppendChar(FX_CHAR* buf, FX_DWORD charcode) const {
-  *buf = (FX_CHAR)charcode;
-  return 1;
-}
-
-void CPDF_Font::AppendChar(CFX_ByteString& str, FX_DWORD charcode) const {
-  char buf[4];
-  int len = AppendChar(buf, charcode);
-  if (len == 1) {
-    str += buf[0];
-  } else {
-    str += CFX_ByteString(buf, len);
-  }
-}
-
-CFX_WideString CPDF_Font::UnicodeFromCharCode(FX_DWORD charcode) const {
-  if (!m_bToUnicodeLoaded)
-    ((CPDF_Font*)this)->LoadUnicodeMap();
-
-  if (m_pToUnicodeMap)
-    return m_pToUnicodeMap->Lookup(charcode);
-  return CFX_WideString();
-}
-
-FX_DWORD CPDF_Font::CharCodeFromUnicode(FX_WCHAR unicode) const {
-  if (!m_bToUnicodeLoaded)
-    ((CPDF_Font*)this)->LoadUnicodeMap();
-
-  if (m_pToUnicodeMap)
-    return m_pToUnicodeMap->ReverseLookup(unicode);
-  return 0;
-}
-
-void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) {
-  m_Flags = pFontDesc->GetIntegerBy("Flags", PDFFONT_NONSYMBOLIC);
-  int ItalicAngle = 0;
-  FX_BOOL bExistItalicAngle = FALSE;
-  if (pFontDesc->KeyExist("ItalicAngle")) {
-    ItalicAngle = pFontDesc->GetIntegerBy("ItalicAngle");
-    bExistItalicAngle = TRUE;
-  }
-  if (ItalicAngle < 0) {
-    m_Flags |= PDFFONT_ITALIC;
-    m_ItalicAngle = ItalicAngle;
-  }
-  FX_BOOL bExistStemV = FALSE;
-  if (pFontDesc->KeyExist("StemV")) {
-    m_StemV = pFontDesc->GetIntegerBy("StemV");
-    bExistStemV = TRUE;
-  }
-  FX_BOOL bExistAscent = FALSE;
-  if (pFontDesc->KeyExist("Ascent")) {
-    m_Ascent = pFontDesc->GetIntegerBy("Ascent");
-    bExistAscent = TRUE;
-  }
-  FX_BOOL bExistDescent = FALSE;
-  if (pFontDesc->KeyExist("Descent")) {
-    m_Descent = pFontDesc->GetIntegerBy("Descent");
-    bExistDescent = TRUE;
-  }
-  FX_BOOL bExistCapHeight = FALSE;
-  if (pFontDesc->KeyExist("CapHeight")) {
-    bExistCapHeight = TRUE;
-  }
-  if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent &&
-      bExistStemV) {
-    m_Flags |= PDFFONT_USEEXTERNATTR;
-  }
-  if (m_Descent > 10) {
-    m_Descent = -m_Descent;
-  }
-  CPDF_Array* pBBox = pFontDesc->GetArrayBy("FontBBox");
-  if (pBBox) {
-    m_FontBBox.left = pBBox->GetIntegerAt(0);
-    m_FontBBox.bottom = pBBox->GetIntegerAt(1);
-    m_FontBBox.right = pBBox->GetIntegerAt(2);
-    m_FontBBox.top = pBBox->GetIntegerAt(3);
-  }
-
-  CPDF_Stream* pFontFile = pFontDesc->GetStreamBy("FontFile");
-  if (!pFontFile)
-    pFontFile = pFontDesc->GetStreamBy("FontFile2");
-  if (!pFontFile)
-    pFontFile = pFontDesc->GetStreamBy("FontFile3");
-  if (!pFontFile)
-    return;
-
-  m_pFontFile = m_pDocument->LoadFontFile(pFontFile);
-  if (!m_pFontFile)
-    return;
-
-  const uint8_t* pFontData = m_pFontFile->GetData();
-  FX_DWORD dwFontSize = m_pFontFile->GetSize();
-  if (!m_Font.LoadEmbedded(pFontData, dwFontSize)) {
-    m_pDocument->GetPageData()->ReleaseFontFileStreamAcc(
-        const_cast<CPDF_Stream*>(m_pFontFile->GetStream()->AsStream()));
-    m_pFontFile = nullptr;
-  }
-}
 
 short TT2PDF(int m, FXFT_Face face) {
   int upm = FXFT_Get_Face_UnitsPerEM(face);
-  if (upm == 0) {
+  if (upm == 0)
     return (short)m;
-  }
   return (m * 1000 + upm / 2) / upm;
 }
 
-void CPDF_Font::CheckFontMetrics() {
-  if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
-      m_FontBBox.right == 0) {
-    FXFT_Face face = m_Font.GetFace();
-    if (face) {
-      m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face);
-      m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face);
-      m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face);
-      m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face);
-      m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face);
-      m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face);
-    } else {
-      FX_BOOL bFirst = TRUE;
-      for (int i = 0; i < 256; i++) {
-        FX_RECT rect = GetCharBBox(i);
-        if (rect.left == rect.right) {
-          continue;
-        }
-        if (bFirst) {
-          m_FontBBox = rect;
-          bFirst = FALSE;
-        } else {
-          if (m_FontBBox.top < rect.top) {
-            m_FontBBox.top = rect.top;
-          }
-          if (m_FontBBox.right < rect.right) {
-            m_FontBBox.right = rect.right;
-          }
-          if (m_FontBBox.left > rect.left) {
-            m_FontBBox.left = rect.left;
-          }
-          if (m_FontBBox.bottom > rect.bottom) {
-            m_FontBBox.bottom = rect.bottom;
-          }
-        }
-      }
-    }
-  }
-  if (m_Ascent == 0 && m_Descent == 0) {
-    FX_RECT rect = GetCharBBox('A');
-    m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top;
-    rect = GetCharBBox('g');
-    m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom;
-  }
-}
-
-void CPDF_Font::LoadUnicodeMap() {
-  m_bToUnicodeLoaded = TRUE;
-  CPDF_Stream* pStream = m_pFontDict->GetStreamBy("ToUnicode");
-  if (!pStream) {
-    return;
-  }
-  m_pToUnicodeMap = new CPDF_ToUnicodeMap;
-  m_pToUnicodeMap->Load(pStream);
-}
-
-int CPDF_Font::GetStringWidth(const FX_CHAR* pString, int size) {
-  int offset = 0;
-  int width = 0;
-  while (offset < size) {
-    FX_DWORD charcode = GetNextChar(pString, size, offset);
-    width += GetCharWidthF(charcode);
-  }
-  return width;
-}
-
-CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc,
-                                   const CFX_ByteStringC& name) {
-  CFX_ByteString fontname(name);
-  int font_id = PDF_GetStandardFontName(&fontname);
-  if (font_id < 0) {
-    return nullptr;
-  }
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
-  CPDF_Font* pFont = pFontGlobals->Find(pDoc, font_id);
-  if (pFont) {
-    return pFont;
-  }
-  CPDF_Dictionary* pDict = new CPDF_Dictionary;
-  pDict->SetAtName("Type", "Font");
-  pDict->SetAtName("Subtype", "Type1");
-  pDict->SetAtName("BaseFont", fontname);
-  pDict->SetAtName("Encoding", "WinAnsiEncoding");
-  pFont = CPDF_Font::CreateFontF(NULL, pDict);
-  pFontGlobals->Set(pDoc, font_id, pFont);
-  return pFont;
-}
-
-CPDF_Font* CPDF_Font::CreateFontF(CPDF_Document* pDoc,
-                                  CPDF_Dictionary* pFontDict) {
-  CFX_ByteString type = pFontDict->GetStringBy("Subtype");
-  CPDF_Font* pFont;
-  if (type == "TrueType") {
-    {
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ || \
-    _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ ||   \
-    _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ || \
-    _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-      CFX_ByteString basefont = pFontDict->GetStringBy("BaseFont");
-      CFX_ByteString tag = basefont.Left(4);
-      int i;
-      int count = sizeof(ChineseFontNames) / sizeof(ChineseFontNames[0]);
-      for (i = 0; i < count; ++i) {
-        if (tag == CFX_ByteString((const FX_CHAR*)ChineseFontNames[i])) {
-          break;
-        }
-      }
-      if (i < count) {
-        CPDF_Dictionary* pFontDesc = pFontDict->GetDictBy("FontDescriptor");
-        if (!pFontDesc || !pFontDesc->KeyExist("FontFile2")) {
-          pFont = new CPDF_CIDFont;
-          pFont->m_pFontDict = pFontDict;
-          pFont->m_pDocument = pDoc;
-          pFont->m_BaseFont = pFontDict->GetStringBy("BaseFont");
-          if (!pFont->Load()) {
-            delete pFont;
-            return NULL;
-          }
-          return pFont;
-        }
-      }
-#endif
-    }
-    pFont = new CPDF_TrueTypeFont;
-  } else if (type == "Type3") {
-    pFont = new CPDF_Type3Font;
-  } else if (type == "Type0") {
-    pFont = new CPDF_CIDFont;
-  } else {
-    pFont = new CPDF_Type1Font;
-  }
-  pFont->m_pFontDict = pFontDict;
-  pFont->m_pDocument = pDoc;
-  pFont->m_BaseFont = pFontDict->GetStringBy("BaseFont");
-  if (!pFont->Load()) {
-    delete pFont;
-    return NULL;
-  }
-  return pFont;
-}
 
 CFX_WideString CPDF_ToUnicodeMap::Lookup(FX_DWORD charcode) {
   auto it = m_Map.find(charcode);
@@ -716,1098 +300,3 @@
     m_pBaseMap = NULL;
   }
 }
-
-FX_DWORD CPDF_Font::GetNextChar(const FX_CHAR* pString,
-                                int nStrLen,
-                                int& offset) const {
-  if (offset < 0 || nStrLen < 1) {
-    return 0;
-  }
-  uint8_t ch = offset < nStrLen ? pString[offset++] : pString[nStrLen - 1];
-  return static_cast<FX_DWORD>(ch);
-}
-
-void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding,
-                                int& iBaseEncoding,
-                                CFX_ByteString*& pCharNames,
-                                FX_BOOL bEmbedded,
-                                FX_BOOL bTrueType) {
-  if (!pEncoding) {
-    if (m_BaseFont == "Symbol") {
-      iBaseEncoding = bTrueType ? PDFFONT_ENCODING_MS_SYMBOL
-                                : PDFFONT_ENCODING_ADOBE_SYMBOL;
-    } else if (!bEmbedded && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
-      iBaseEncoding = PDFFONT_ENCODING_WINANSI;
-    }
-    return;
-  }
-  if (pEncoding->IsName()) {
-    if (iBaseEncoding == PDFFONT_ENCODING_ADOBE_SYMBOL ||
-        iBaseEncoding == PDFFONT_ENCODING_ZAPFDINGBATS) {
-      return;
-    }
-    if ((m_Flags & PDFFONT_SYMBOLIC) && m_BaseFont == "Symbol") {
-      if (!bTrueType) {
-        iBaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
-      }
-      return;
-    }
-    CFX_ByteString bsEncoding = pEncoding->GetString();
-    if (bsEncoding.Compare("MacExpertEncoding") == 0) {
-      bsEncoding = "WinAnsiEncoding";
-    }
-    GetPredefinedEncoding(iBaseEncoding, bsEncoding);
-    return;
-  }
-
-  CPDF_Dictionary* pDict = pEncoding->AsDictionary();
-  if (!pDict)
-    return;
-
-  if (iBaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL &&
-      iBaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS) {
-    CFX_ByteString bsEncoding = pDict->GetStringBy("BaseEncoding");
-    if (bsEncoding.Compare("MacExpertEncoding") == 0 && bTrueType) {
-      bsEncoding = "WinAnsiEncoding";
-    }
-    GetPredefinedEncoding(iBaseEncoding, bsEncoding);
-  }
-  if ((!bEmbedded || bTrueType) && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
-    iBaseEncoding = PDFFONT_ENCODING_STANDARD;
-  }
-  CPDF_Array* pDiffs = pDict->GetArrayBy("Differences");
-  if (!pDiffs) {
-    return;
-  }
-  pCharNames = new CFX_ByteString[256];
-  FX_DWORD cur_code = 0;
-  for (FX_DWORD i = 0; i < pDiffs->GetCount(); i++) {
-    CPDF_Object* pElement = pDiffs->GetElementValue(i);
-    if (!pElement)
-      continue;
-
-    if (CPDF_Name* pName = pElement->AsName()) {
-      if (cur_code < 256)
-        pCharNames[cur_code] = pName->GetString();
-      cur_code++;
-    } else {
-      cur_code = pElement->GetInteger();
-    }
-  }
-}
-
-FX_BOOL CPDF_Font::IsStandardFont() const {
-  if (!IsType1Font())
-    return FALSE;
-  if (m_pFontFile)
-    return FALSE;
-  if (AsType1Font()->GetBase14Font() < 0)
-    return FALSE;
-  return TRUE;
-}
-
-CPDF_SimpleFont::CPDF_SimpleFont()
-    : m_pCharNames(nullptr), m_BaseEncoding(PDFFONT_ENCODING_BUILTIN) {
-  FXSYS_memset(m_CharWidth, 0xff, sizeof m_CharWidth);
-  FXSYS_memset(m_GlyphIndex, 0xff, sizeof m_GlyphIndex);
-  FXSYS_memset(m_ExtGID, 0xff, sizeof m_ExtGID);
-}
-
-CPDF_SimpleFont::~CPDF_SimpleFont() {
-  delete[] m_pCharNames;
-}
-
-int CPDF_SimpleFont::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) {
-  if (pVertGlyph) {
-    *pVertGlyph = FALSE;
-  }
-  if (charcode > 0xff) {
-    return -1;
-  }
-  int index = m_GlyphIndex[(uint8_t)charcode];
-  if (index == 0xffff) {
-    return -1;
-  }
-  return index;
-}
-
-void CPDF_SimpleFont::LoadCharMetrics(int charcode) {
-  if (!m_Font.GetFace())
-    return;
-
-  if (charcode < 0 || charcode > 0xff) {
-    return;
-  }
-  int glyph_index = m_GlyphIndex[charcode];
-  if (glyph_index == 0xffff) {
-    if (!m_pFontFile && charcode != 32) {
-      LoadCharMetrics(32);
-      m_CharBBox[charcode] = m_CharBBox[32];
-      if (m_bUseFontWidth) {
-        m_CharWidth[charcode] = m_CharWidth[32];
-      }
-    }
-    return;
-  }
-  FXFT_Face face = m_Font.GetFace();
-  int err = FXFT_Load_Glyph(
-      face, glyph_index,
-      FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
-  if (err) {
-    return;
-  }
-  m_CharBBox[charcode] = FX_SMALL_RECT(
-      TT2PDF(FXFT_Get_Glyph_HoriBearingX(face), face),
-      TT2PDF(FXFT_Get_Glyph_HoriBearingY(face), face),
-      TT2PDF(FXFT_Get_Glyph_HoriBearingX(face) + FXFT_Get_Glyph_Width(face),
-             face),
-      TT2PDF(FXFT_Get_Glyph_HoriBearingY(face) - FXFT_Get_Glyph_Height(face),
-             face));
-
-  if (m_bUseFontWidth) {
-    int TT_Width = TT2PDF(FXFT_Get_Glyph_HoriAdvance(face), face);
-    if (m_CharWidth[charcode] == 0xffff) {
-      m_CharWidth[charcode] = TT_Width;
-    } else if (TT_Width && !IsEmbedded()) {
-      m_CharBBox[charcode].right =
-          m_CharBBox[charcode].right * m_CharWidth[charcode] / TT_Width;
-      m_CharBBox[charcode].left =
-          m_CharBBox[charcode].left * m_CharWidth[charcode] / TT_Width;
-    }
-  }
-}
-
-int CPDF_SimpleFont::GetCharWidthF(FX_DWORD charcode, int level) {
-  if (charcode > 0xff) {
-    charcode = 0;
-  }
-  if (m_CharWidth[charcode] == 0xffff) {
-    LoadCharMetrics(charcode);
-    if (m_CharWidth[charcode] == 0xffff) {
-      m_CharWidth[charcode] = 0;
-    }
-  }
-  return (int16_t)m_CharWidth[charcode];
-}
-
-FX_RECT CPDF_SimpleFont::GetCharBBox(FX_DWORD charcode, int level) {
-  if (charcode > 0xff)
-    charcode = 0;
-
-  if (m_CharBBox[charcode].left == FX_SMALL_RECT::kInvalid)
-    LoadCharMetrics(charcode);
-
-  return FX_RECT(m_CharBBox[charcode]);
-}
-
-const FX_CHAR* GetAdobeCharName(int iBaseEncoding,
-                                const CFX_ByteString* pCharNames,
-                                int charcode) {
-  ASSERT(charcode >= 0 && charcode < 256);
-  if (charcode < 0 || charcode >= 256) {
-    return NULL;
-  }
-  const FX_CHAR* name = NULL;
-  if (pCharNames) {
-    name = pCharNames[charcode];
-  }
-  if ((!name || name[0] == 0) && iBaseEncoding) {
-    name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode);
-  }
-  return name && name[0] ? name : nullptr;
-}
-
-FX_BOOL CPDF_SimpleFont::LoadCommon() {
-  CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictBy("FontDescriptor");
-  if (pFontDesc) {
-    LoadFontDescriptor(pFontDesc);
-  }
-  CPDF_Array* pWidthArray = m_pFontDict->GetArrayBy("Widths");
-  int width_start = 0, width_end = -1;
-  m_bUseFontWidth = TRUE;
-  if (pWidthArray) {
-    m_bUseFontWidth = FALSE;
-    if (pFontDesc && pFontDesc->KeyExist("MissingWidth")) {
-      int MissingWidth = pFontDesc->GetIntegerBy("MissingWidth");
-      for (int i = 0; i < 256; i++) {
-        m_CharWidth[i] = MissingWidth;
-      }
-    }
-    width_start = m_pFontDict->GetIntegerBy("FirstChar", 0);
-    width_end = m_pFontDict->GetIntegerBy("LastChar", 0);
-    if (width_start >= 0 && width_start <= 255) {
-      if (width_end <= 0 ||
-          width_end >= width_start + (int)pWidthArray->GetCount()) {
-        width_end = width_start + pWidthArray->GetCount() - 1;
-      }
-      if (width_end > 255) {
-        width_end = 255;
-      }
-      for (int i = width_start; i <= width_end; i++) {
-        m_CharWidth[i] = pWidthArray->GetIntegerAt(i - width_start);
-      }
-    }
-  }
-  if (m_pFontFile) {
-    if (m_BaseFont.GetLength() > 8 && m_BaseFont[7] == '+') {
-      m_BaseFont = m_BaseFont.Mid(8);
-    }
-  } else {
-    LoadSubstFont();
-  }
-  if (!(m_Flags & PDFFONT_SYMBOLIC)) {
-    m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
-  }
-  CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding");
-  LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, m_pFontFile != NULL,
-                  m_Font.IsTTFont());
-  LoadGlyphMap();
-  delete[] m_pCharNames;
-  m_pCharNames = NULL;
-  if (!m_Font.GetFace())
-    return TRUE;
-
-  if (m_Flags & PDFFONT_ALLCAP) {
-    unsigned char lowercases[] = {'a', 'z', 0xe0, 0xf6, 0xf8, 0xfd};
-    for (size_t range = 0; range < sizeof lowercases / 2; range++) {
-      for (int i = lowercases[range * 2]; i <= lowercases[range * 2 + 1]; i++) {
-        if (m_GlyphIndex[i] != 0xffff && m_pFontFile) {
-          continue;
-        }
-        m_GlyphIndex[i] = m_GlyphIndex[i - 32];
-        if (m_CharWidth[i - 32]) {
-          m_CharWidth[i] = m_CharWidth[i - 32];
-          m_CharBBox[i] = m_CharBBox[i - 32];
-        }
-      }
-    }
-  }
-  CheckFontMetrics();
-  return TRUE;
-}
-
-void CPDF_SimpleFont::LoadSubstFont() {
-  if (!m_bUseFontWidth && !(m_Flags & PDFFONT_FIXEDPITCH)) {
-    int width = 0, i;
-    for (i = 0; i < 256; i++) {
-      if (m_CharWidth[i] == 0 || m_CharWidth[i] == 0xffff) {
-        continue;
-      }
-      if (width == 0) {
-        width = m_CharWidth[i];
-      } else if (width != m_CharWidth[i]) {
-        break;
-      }
-    }
-    if (i == 256 && width) {
-      m_Flags |= PDFFONT_FIXEDPITCH;
-    }
-  }
-  int weight = m_StemV < 140 ? m_StemV * 5 : (m_StemV * 4 + 140);
-  m_Font.LoadSubst(m_BaseFont, IsTrueTypeFont(), m_Flags, weight, m_ItalicAngle,
-                   0);
-  if (m_Font.GetSubstFont()->m_SubstFlags & FXFONT_SUBST_NONSYMBOL) {
-  }
-}
-
-FX_BOOL CPDF_SimpleFont::IsUnicodeCompatible() const {
-  return m_BaseEncoding != PDFFONT_ENCODING_BUILTIN &&
-         m_BaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL &&
-         m_BaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS;
-}
-
-CFX_WideString CPDF_SimpleFont::UnicodeFromCharCode(FX_DWORD charcode) const {
-  CFX_WideString unicode = CPDF_Font::UnicodeFromCharCode(charcode);
-  if (!unicode.IsEmpty())
-    return unicode;
-  FX_WCHAR ret = m_Encoding.UnicodeFromCharCode((uint8_t)charcode);
-  if (ret == 0)
-    return CFX_WideString();
-  return ret;
-}
-
-FX_DWORD CPDF_SimpleFont::CharCodeFromUnicode(FX_WCHAR unicode) const {
-  FX_DWORD ret = CPDF_Font::CharCodeFromUnicode(unicode);
-  if (ret)
-    return ret;
-  return m_Encoding.CharCodeFromUnicode(unicode);
-}
-
-CPDF_Type1Font::CPDF_Type1Font() : m_Base14Font(-1) {}
-
-bool CPDF_Type1Font::IsType1Font() const {
-  return true;
-}
-
-const CPDF_Type1Font* CPDF_Type1Font::AsType1Font() const {
-  return this;
-}
-
-CPDF_Type1Font* CPDF_Type1Font::AsType1Font() {
-  return this;
-}
-
-FX_BOOL CPDF_Type1Font::Load() {
-  m_Base14Font = PDF_GetStandardFontName(&m_BaseFont);
-  if (m_Base14Font >= 0) {
-    CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictBy("FontDescriptor");
-    if (pFontDesc && pFontDesc->KeyExist("Flags"))
-      m_Flags = pFontDesc->GetIntegerBy("Flags");
-    else
-      m_Flags = m_Base14Font >= 12 ? PDFFONT_SYMBOLIC : PDFFONT_NONSYMBOLIC;
-
-    if (m_Base14Font < 4) {
-      for (int i = 0; i < 256; i++)
-        m_CharWidth[i] = 600;
-    }
-    if (m_Base14Font == 12)
-      m_BaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
-    else if (m_Base14Font == 13)
-      m_BaseEncoding = PDFFONT_ENCODING_ZAPFDINGBATS;
-    else if (m_Flags & PDFFONT_NONSYMBOLIC)
-      m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
-  }
-  return LoadCommon();
-}
-
-int CPDF_Type1Font::GlyphFromCharCodeExt(FX_DWORD charcode) {
-  if (charcode > 0xff) {
-    return -1;
-  }
-  int index = m_ExtGID[(uint8_t)charcode];
-  if (index == 0xffff) {
-    return -1;
-  }
-  return index;
-}
-
-void CPDF_Type1Font::LoadGlyphMap() {
-  if (!m_Font.GetFace())
-    return;
-
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-  FX_BOOL bCoreText = TRUE;
-  CQuartz2D& quartz2d =
-      ((CApplePlatform*)CFX_GEModule::Get()->GetPlatformData())->_quartz2d;
-  if (!m_Font.GetPlatformFont()) {
-    if (m_Font.GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) {
-      bCoreText = FALSE;
-    }
-    m_Font.SetPlatformFont(
-        quartz2d.CreateFont(m_Font.GetFontData(), m_Font.GetSize()));
-    if (!m_Font.GetPlatformFont()) {
-      bCoreText = FALSE;
-    }
-  }
-#endif
-  if (!IsEmbedded() && (m_Base14Font < 12) && m_Font.IsTTFont()) {
-    if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) {
-      FX_BOOL bGotOne = FALSE;
-      for (int charcode = 0; charcode < 256; charcode++) {
-        const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
-        for (int j = 0; j < 4; j++) {
-          uint16_t unicode = prefix[j] * 256 + charcode;
-          m_GlyphIndex[charcode] =
-              FXFT_Get_Char_Index(m_Font.GetFace(), unicode);
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-          FX_CHAR name_glyph[256];
-          FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
-                              name_glyph, 256);
-          name_glyph[255] = 0;
-          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
-              kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
-              kCFAllocatorNull);
-          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
-              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
-          if (name_ct) {
-            CFRelease(name_ct);
-          }
-#endif
-          if (m_GlyphIndex[charcode]) {
-            bGotOne = TRUE;
-            break;
-          }
-        }
-      }
-      if (bGotOne) {
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-        if (!bCoreText) {
-          FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
-        }
-#endif
-        return;
-      }
-    }
-    FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE);
-    if (m_BaseEncoding == 0) {
-      m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
-    }
-    for (int charcode = 0; charcode < 256; charcode++) {
-      const FX_CHAR* name =
-          GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
-      if (!name) {
-        continue;
-      }
-      m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
-      m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
-          m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]);
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-      FX_CHAR name_glyph[256];
-      FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], name_glyph,
-                          256);
-      name_glyph[255] = 0;
-      CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
-          kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
-          kCFAllocatorNull);
-      m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
-          (CGFontRef)m_Font.GetPlatformFont(), name_ct);
-      if (name_ct) {
-        CFRelease(name_ct);
-      }
-#endif
-      if (m_GlyphIndex[charcode] == 0 && FXSYS_strcmp(name, ".notdef") == 0) {
-        m_Encoding.m_Unicodes[charcode] = 0x20;
-        m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 0x20);
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-        FX_CHAR name_glyph[256];
-        FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
-                            name_glyph, 256);
-        name_glyph[255] = 0;
-        CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
-            kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
-            kCFAllocatorNull);
-        m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
-            (CGFontRef)m_Font.GetPlatformFont(), name_ct);
-        if (name_ct) {
-          CFRelease(name_ct);
-        }
-#endif
-      }
-    }
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-    if (!bCoreText) {
-      FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
-    }
-#endif
-    return;
-  }
-  FT_UseType1Charmap(m_Font.GetFace());
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-  if (bCoreText) {
-    if (m_Flags & PDFFONT_SYMBOLIC) {
-      for (int charcode = 0; charcode < 256; charcode++) {
-        const FX_CHAR* name =
-            GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
-        if (name) {
-          m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
-          m_GlyphIndex[charcode] =
-              FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
-          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
-              kCFAllocatorDefault, name, kCFStringEncodingASCII,
-              kCFAllocatorNull);
-          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
-              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
-          if (name_ct) {
-            CFRelease(name_ct);
-          }
-        } else {
-          m_GlyphIndex[charcode] =
-              FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
-          FX_WCHAR unicode = 0;
-          if (m_GlyphIndex[charcode]) {
-            unicode =
-                FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);
-          }
-          FX_CHAR name_glyph[256];
-          FXSYS_memset(name_glyph, 0, sizeof(name_glyph));
-          FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
-                              name_glyph, 256);
-          name_glyph[255] = 0;
-          if (unicode == 0 && name_glyph[0] != 0) {
-            unicode = PDF_UnicodeFromAdobeName(name_glyph);
-          }
-          m_Encoding.m_Unicodes[charcode] = unicode;
-          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
-              kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
-              kCFAllocatorNull);
-          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
-              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
-          if (name_ct) {
-            CFRelease(name_ct);
-          }
-        }
-      }
-      return;
-    }
-    FX_BOOL bUnicode = FALSE;
-    if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) {
-      bUnicode = TRUE;
-    }
-    for (int charcode = 0; charcode < 256; charcode++) {
-      const FX_CHAR* name =
-          GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
-      if (!name) {
-        continue;
-      }
-      m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
-      const FX_CHAR* pStrUnicode = GlyphNameRemap(name);
-      if (pStrUnicode &&
-          0 == FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name)) {
-        name = pStrUnicode;
-      }
-      m_GlyphIndex[charcode] =
-          FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
-      CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
-          kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull);
-      m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
-          (CGFontRef)m_Font.GetPlatformFont(), name_ct);
-      if (name_ct) {
-        CFRelease(name_ct);
-      }
-      if (m_GlyphIndex[charcode] == 0) {
-        if (FXSYS_strcmp(name, ".notdef") != 0 &&
-            FXSYS_strcmp(name, "space") != 0) {
-          m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
-              m_Font.GetFace(),
-              bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);
-          FX_CHAR name_glyph[256];
-          FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
-                              name_glyph, 256);
-          name_glyph[255] = 0;
-          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
-              kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
-              kCFAllocatorNull);
-          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
-              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
-          if (name_ct) {
-            CFRelease(name_ct);
-          }
-        } else {
-          m_Encoding.m_Unicodes[charcode] = 0x20;
-          m_GlyphIndex[charcode] =
-              bUnicode ? FXFT_Get_Char_Index(m_Font.GetFace(), 0x20) : 0xffff;
-          FX_CHAR name_glyph[256];
-          FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
-                              name_glyph, 256);
-          name_glyph[255] = 0;
-          CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
-              kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII,
-              kCFAllocatorNull);
-          m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName(
-              (CGFontRef)m_Font.GetPlatformFont(), name_ct);
-          if (name_ct) {
-            CFRelease(name_ct);
-          }
-        }
-      }
-    }
-    return;
-  }
-#endif
-  if (m_Flags & PDFFONT_SYMBOLIC) {
-    for (int charcode = 0; charcode < 256; charcode++) {
-      const FX_CHAR* name =
-          GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
-      if (name) {
-        m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
-        m_GlyphIndex[charcode] =
-            FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
-      } else {
-        m_GlyphIndex[charcode] =
-            FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
-        if (m_GlyphIndex[charcode]) {
-          FX_WCHAR unicode =
-              FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);
-          if (unicode == 0) {
-            FX_CHAR name_glyph[256];
-            FXSYS_memset(name_glyph, 0, sizeof(name_glyph));
-            FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
-                                name_glyph, 256);
-            name_glyph[255] = 0;
-            if (name_glyph[0] != 0) {
-              unicode = PDF_UnicodeFromAdobeName(name_glyph);
-            }
-          }
-          m_Encoding.m_Unicodes[charcode] = unicode;
-        }
-      }
-    }
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-    if (!bCoreText) {
-      FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
-    }
-#endif
-    return;
-  }
-  FX_BOOL bUnicode = FALSE;
-  if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) {
-    bUnicode = TRUE;
-  }
-  for (int charcode = 0; charcode < 256; charcode++) {
-    const FX_CHAR* name =
-        GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
-    if (!name) {
-      continue;
-    }
-    m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
-    m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
-    if (m_GlyphIndex[charcode] == 0) {
-      if (FXSYS_strcmp(name, ".notdef") != 0 &&
-          FXSYS_strcmp(name, "space") != 0) {
-        m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
-            m_Font.GetFace(),
-            bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);
-      } else {
-        m_Encoding.m_Unicodes[charcode] = 0x20;
-        m_GlyphIndex[charcode] = 0xffff;
-      }
-    }
-  }
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-  if (!bCoreText) {
-    FXSYS_memcpy(m_ExtGID, m_GlyphIndex, 256);
-  }
-#endif
-}
-
-CPDF_FontEncoding::CPDF_FontEncoding() {
-  FXSYS_memset(m_Unicodes, 0, sizeof(m_Unicodes));
-}
-
-int CPDF_FontEncoding::CharCodeFromUnicode(FX_WCHAR unicode) const {
-  for (int i = 0; i < 256; i++)
-    if (m_Unicodes[i] == unicode) {
-      return i;
-    }
-  return -1;
-}
-
-CPDF_FontEncoding::CPDF_FontEncoding(int PredefinedEncoding) {
-  const uint16_t* pSrc = PDF_UnicodesForPredefinedCharSet(PredefinedEncoding);
-  if (!pSrc) {
-    FXSYS_memset(m_Unicodes, 0, sizeof(m_Unicodes));
-  } else {
-    for (int i = 0; i < 256; i++)
-      m_Unicodes[i] = pSrc[i];
-  }
-}
-
-FX_BOOL CPDF_FontEncoding::IsIdentical(CPDF_FontEncoding* pAnother) const {
-  return FXSYS_memcmp(m_Unicodes, pAnother->m_Unicodes, sizeof(m_Unicodes)) ==
-         0;
-}
-
-CPDF_Object* CPDF_FontEncoding::Realize() {
-  int predefined = 0;
-  for (int cs = PDFFONT_ENCODING_WINANSI; cs < PDFFONT_ENCODING_ZAPFDINGBATS;
-       cs++) {
-    const uint16_t* pSrc = PDF_UnicodesForPredefinedCharSet(cs);
-    FX_BOOL match = TRUE;
-    for (int i = 0; i < 256; ++i) {
-      if (m_Unicodes[i] != pSrc[i]) {
-        match = FALSE;
-        break;
-      }
-    }
-    if (match) {
-      predefined = cs;
-      break;
-    }
-  }
-  if (predefined) {
-    if (predefined == PDFFONT_ENCODING_WINANSI) {
-      return new CPDF_Name("WinAnsiEncoding");
-    }
-    if (predefined == PDFFONT_ENCODING_MACROMAN) {
-      return new CPDF_Name("MacRomanEncoding");
-    }
-    if (predefined == PDFFONT_ENCODING_MACEXPERT) {
-      return new CPDF_Name("MacExpertEncoding");
-    }
-    return NULL;
-  }
-  const uint16_t* pStandard =
-      PDF_UnicodesForPredefinedCharSet(PDFFONT_ENCODING_WINANSI);
-  CPDF_Array* pDiff = new CPDF_Array;
-  for (int i = 0; i < 256; i++) {
-    if (pStandard[i] == m_Unicodes[i]) {
-      continue;
-    }
-    pDiff->Add(new CPDF_Number(i));
-    pDiff->Add(new CPDF_Name(PDF_AdobeNameFromUnicode(m_Unicodes[i])));
-  }
-
-  CPDF_Dictionary* pDict = new CPDF_Dictionary;
-  pDict->SetAtName("BaseEncoding", "WinAnsiEncoding");
-  pDict->SetAt("Differences", pDiff);
-  return pDict;
-}
-
-CPDF_TrueTypeFont::CPDF_TrueTypeFont() {}
-
-bool CPDF_TrueTypeFont::IsTrueTypeFont() const {
-  return true;
-}
-
-const CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() const {
-  return this;
-}
-
-CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() {
-  return this;
-}
-
-FX_BOOL CPDF_TrueTypeFont::Load() {
-  return LoadCommon();
-}
-
-void CPDF_TrueTypeFont::LoadGlyphMap() {
-  if (!m_Font.GetFace())
-    return;
-
-  int baseEncoding = m_BaseEncoding;
-  if (m_pFontFile && m_Font.GetFace()->num_charmaps > 0 &&
-      (baseEncoding == PDFFONT_ENCODING_MACROMAN ||
-       baseEncoding == PDFFONT_ENCODING_WINANSI) &&
-      (m_Flags & PDFFONT_SYMBOLIC)) {
-    FX_BOOL bSupportWin = FALSE;
-    FX_BOOL bSupportMac = FALSE;
-    for (int i = 0; i < FXFT_Get_Face_CharmapCount(m_Font.GetFace()); i++) {
-      int platform_id = FXFT_Get_Charmap_PlatformID(
-          FXFT_Get_Face_Charmaps(m_Font.GetFace())[i]);
-      if (platform_id == 0 || platform_id == 3) {
-        bSupportWin = TRUE;
-      } else if (platform_id == 0 || platform_id == 1) {
-        bSupportMac = TRUE;
-      }
-    }
-    if (baseEncoding == PDFFONT_ENCODING_WINANSI && !bSupportWin) {
-      baseEncoding =
-          bSupportMac ? PDFFONT_ENCODING_MACROMAN : PDFFONT_ENCODING_BUILTIN;
-    } else if (baseEncoding == PDFFONT_ENCODING_MACROMAN && !bSupportMac) {
-      baseEncoding =
-          bSupportWin ? PDFFONT_ENCODING_WINANSI : PDFFONT_ENCODING_BUILTIN;
-    }
-  }
-  if (((baseEncoding == PDFFONT_ENCODING_MACROMAN ||
-        baseEncoding == PDFFONT_ENCODING_WINANSI) &&
-       !m_pCharNames) ||
-      (m_Flags & PDFFONT_NONSYMBOLIC)) {
-    if (!FXFT_Has_Glyph_Names(m_Font.GetFace()) &&
-        (!m_Font.GetFace()->num_charmaps || !m_Font.GetFace()->charmaps)) {
-      int nStartChar = m_pFontDict->GetIntegerBy("FirstChar");
-      if (nStartChar < 0 || nStartChar > 255)
-        return;
-
-      int charcode = 0;
-      for (; charcode < nStartChar; charcode++) {
-        m_GlyphIndex[charcode] = 0;
-      }
-      uint16_t nGlyph = charcode - nStartChar + 3;
-      for (; charcode < 256; charcode++, nGlyph++) {
-        m_GlyphIndex[charcode] = nGlyph;
-      }
-      return;
-    }
-    FX_BOOL bMSUnicode = FT_UseTTCharmap(m_Font.GetFace(), 3, 1);
-    FX_BOOL bMacRoman = FALSE, bMSSymbol = FALSE;
-    if (!bMSUnicode) {
-      if (m_Flags & PDFFONT_NONSYMBOLIC) {
-        bMacRoman = FT_UseTTCharmap(m_Font.GetFace(), 1, 0);
-        bMSSymbol = !bMacRoman && FT_UseTTCharmap(m_Font.GetFace(), 3, 0);
-      } else {
-        bMSSymbol = FT_UseTTCharmap(m_Font.GetFace(), 3, 0);
-        bMacRoman = !bMSSymbol && FT_UseTTCharmap(m_Font.GetFace(), 1, 0);
-      }
-    }
-    FX_BOOL bToUnicode = m_pFontDict->KeyExist("ToUnicode");
-    for (int charcode = 0; charcode < 256; charcode++) {
-      const FX_CHAR* name =
-          GetAdobeCharName(baseEncoding, m_pCharNames, charcode);
-      if (!name) {
-        m_GlyphIndex[charcode] =
-            m_pFontFile ? FXFT_Get_Char_Index(m_Font.GetFace(), charcode) : -1;
-        continue;
-      }
-      m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
-      if (bMSSymbol) {
-        const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
-        for (int j = 0; j < 4; j++) {
-          uint16_t unicode = prefix[j] * 256 + charcode;
-          m_GlyphIndex[charcode] =
-              FXFT_Get_Char_Index(m_Font.GetFace(), unicode);
-          if (m_GlyphIndex[charcode]) {
-            break;
-          }
-        }
-      } else if (m_Encoding.m_Unicodes[charcode]) {
-        if (bMSUnicode) {
-          m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
-              m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]);
-        } else if (bMacRoman) {
-          FX_DWORD maccode = FT_CharCodeFromUnicode(
-              FXFT_ENCODING_APPLE_ROMAN, m_Encoding.m_Unicodes[charcode]);
-          if (!maccode) {
-            m_GlyphIndex[charcode] =
-                FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
-          } else {
-            m_GlyphIndex[charcode] =
-                FXFT_Get_Char_Index(m_Font.GetFace(), maccode);
-          }
-        }
-      }
-      if ((m_GlyphIndex[charcode] == 0 || m_GlyphIndex[charcode] == 0xffff) &&
-          name) {
-        if (name[0] == '.' && FXSYS_strcmp(name, ".notdef") == 0) {
-          m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 32);
-        } else {
-          m_GlyphIndex[charcode] =
-              FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
-          if (m_GlyphIndex[charcode] == 0) {
-            if (bToUnicode) {
-              CFX_WideString wsUnicode = UnicodeFromCharCode(charcode);
-              if (!wsUnicode.IsEmpty()) {
-                m_GlyphIndex[charcode] =
-                    FXFT_Get_Char_Index(m_Font.GetFace(), wsUnicode[0]);
-                m_Encoding.m_Unicodes[charcode] = wsUnicode[0];
-              }
-            }
-            if (m_GlyphIndex[charcode] == 0) {
-              m_GlyphIndex[charcode] =
-                  FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
-            }
-          }
-        }
-      }
-    }
-    return;
-  }
-  if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) {
-    const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
-    FX_BOOL bGotOne = FALSE;
-    for (int charcode = 0; charcode < 256; charcode++) {
-      for (int j = 0; j < 4; j++) {
-        uint16_t unicode = prefix[j] * 256 + charcode;
-        m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), unicode);
-        if (m_GlyphIndex[charcode]) {
-          bGotOne = TRUE;
-          break;
-        }
-      }
-    }
-    if (bGotOne) {
-      if (baseEncoding != PDFFONT_ENCODING_BUILTIN) {
-        for (int charcode = 0; charcode < 256; charcode++) {
-          const FX_CHAR* name =
-              GetAdobeCharName(baseEncoding, m_pCharNames, charcode);
-          if (!name) {
-            continue;
-          }
-          m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
-        }
-      } else if (FT_UseTTCharmap(m_Font.GetFace(), 1, 0)) {
-        for (int charcode = 0; charcode < 256; charcode++) {
-          m_Encoding.m_Unicodes[charcode] =
-              FT_UnicodeFromCharCode(FXFT_ENCODING_APPLE_ROMAN, charcode);
-        }
-      }
-      return;
-    }
-  }
-  if (FT_UseTTCharmap(m_Font.GetFace(), 1, 0)) {
-    FX_BOOL bGotOne = FALSE;
-    for (int charcode = 0; charcode < 256; charcode++) {
-      m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
-      m_Encoding.m_Unicodes[charcode] =
-          FT_UnicodeFromCharCode(FXFT_ENCODING_APPLE_ROMAN, charcode);
-      if (m_GlyphIndex[charcode]) {
-        bGotOne = TRUE;
-      }
-    }
-    if (m_pFontFile || bGotOne) {
-      return;
-    }
-  }
-  if (FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE) == 0) {
-    FX_BOOL bGotOne = FALSE;
-    const uint16_t* pUnicodes = PDF_UnicodesForPredefinedCharSet(baseEncoding);
-    for (int charcode = 0; charcode < 256; charcode++) {
-      if (m_pFontFile) {
-        m_Encoding.m_Unicodes[charcode] = charcode;
-      } else {
-        const FX_CHAR* name = GetAdobeCharName(0, m_pCharNames, charcode);
-        if (name) {
-          m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
-        } else if (pUnicodes) {
-          m_Encoding.m_Unicodes[charcode] = pUnicodes[charcode];
-        }
-      }
-      m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
-          m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]);
-      if (m_GlyphIndex[charcode]) {
-        bGotOne = TRUE;
-      }
-    }
-    if (bGotOne) {
-      return;
-    }
-  }
-  for (int charcode = 0; charcode < 256; charcode++) {
-    m_GlyphIndex[charcode] = charcode;
-  }
-}
-
-CPDF_Type3Font::CPDF_Type3Font()
-    : m_pCharProcs(nullptr),
-      m_pPageResources(nullptr),
-      m_pFontResources(nullptr) {
-  FXSYS_memset(m_CharWidthL, 0, sizeof(m_CharWidthL));
-}
-
-CPDF_Type3Font::~CPDF_Type3Font() {
-  for (auto it : m_CacheMap)
-    delete it.second;
-}
-
-bool CPDF_Type3Font::IsType3Font() const {
-  return true;
-}
-
-const CPDF_Type3Font* CPDF_Type3Font::AsType3Font() const {
-  return this;
-}
-
-CPDF_Type3Font* CPDF_Type3Font::AsType3Font() {
-  return this;
-}
-
-FX_BOOL CPDF_Type3Font::Load() {
-  m_pFontResources = m_pFontDict->GetDictBy("Resources");
-  CPDF_Array* pMatrix = m_pFontDict->GetArrayBy("FontMatrix");
-  FX_FLOAT xscale = 1.0f, yscale = 1.0f;
-  if (pMatrix) {
-    m_FontMatrix = pMatrix->GetMatrix();
-    xscale = m_FontMatrix.a;
-    yscale = m_FontMatrix.d;
-  }
-  CPDF_Array* pBBox = m_pFontDict->GetArrayBy("FontBBox");
-  if (pBBox) {
-    m_FontBBox.left = (int32_t)(pBBox->GetNumberAt(0) * xscale * 1000);
-    m_FontBBox.bottom = (int32_t)(pBBox->GetNumberAt(1) * yscale * 1000);
-    m_FontBBox.right = (int32_t)(pBBox->GetNumberAt(2) * xscale * 1000);
-    m_FontBBox.top = (int32_t)(pBBox->GetNumberAt(3) * yscale * 1000);
-  }
-  int StartChar = m_pFontDict->GetIntegerBy("FirstChar");
-  CPDF_Array* pWidthArray = m_pFontDict->GetArrayBy("Widths");
-  if (pWidthArray && (StartChar >= 0 && StartChar < 256)) {
-    FX_DWORD count = pWidthArray->GetCount();
-    if (count > 256) {
-      count = 256;
-    }
-    if (StartChar + count > 256) {
-      count = 256 - StartChar;
-    }
-    for (FX_DWORD i = 0; i < count; i++) {
-      m_CharWidthL[StartChar + i] =
-          FXSYS_round(pWidthArray->GetNumberAt(i) * xscale * 1000);
-    }
-  }
-  m_pCharProcs = m_pFontDict->GetDictBy("CharProcs");
-  CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding");
-  if (pEncoding) {
-    LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, FALSE, FALSE);
-    if (m_pCharNames) {
-      for (int i = 0; i < 256; i++) {
-        m_Encoding.m_Unicodes[i] = PDF_UnicodeFromAdobeName(m_pCharNames[i]);
-        if (m_Encoding.m_Unicodes[i] == 0) {
-          m_Encoding.m_Unicodes[i] = i;
-        }
-      }
-    }
-  }
-  return TRUE;
-}
-
-void CPDF_Type3Font::CheckType3FontMetrics() {
-  CheckFontMetrics();
-}
-
-CPDF_Type3Char* CPDF_Type3Font::LoadChar(FX_DWORD charcode, int level) {
-  if (level >= _FPDF_MAX_TYPE3_FORM_LEVEL_)
-    return nullptr;
-
-  auto it = m_CacheMap.find(charcode);
-  if (it != m_CacheMap.end())
-    return it->second;
-
-  const FX_CHAR* name =
-      GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);
-  if (!name)
-    return nullptr;
-
-  CPDF_Stream* pStream =
-      ToStream(m_pCharProcs ? m_pCharProcs->GetElementValue(name) : nullptr);
-  if (!pStream)
-    return nullptr;
-
-  std::unique_ptr<CPDF_Type3Char> pNewChar(new CPDF_Type3Char(new CPDF_Form(
-      m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources,
-      pStream, nullptr)));
-
-  // This can trigger recursion into this method. The content of |m_CacheMap|
-  // can change as a result. Thus after it returns, check the cache again for
-  // a cache hit.
-  pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get(), nullptr,
-                                  level + 1);
-  it = m_CacheMap.find(charcode);
-  if (it != m_CacheMap.end())
-    return it->second;
-
-  FX_FLOAT scale = m_FontMatrix.GetXUnit();
-  pNewChar->m_Width = (int32_t)(pNewChar->m_Width * scale + 0.5f);
-  FX_RECT& rcBBox = pNewChar->m_BBox;
-  CFX_FloatRect char_rect(
-      (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f,
-      (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f);
-  if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top)
-    char_rect = pNewChar->m_pForm->CalcBoundingBox();
-
-  char_rect.Transform(&m_FontMatrix);
-  rcBBox.left = FXSYS_round(char_rect.left * 1000);
-  rcBBox.right = FXSYS_round(char_rect.right * 1000);
-  rcBBox.top = FXSYS_round(char_rect.top * 1000);
-  rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000);
-
-  ASSERT(!pdfium::ContainsKey(m_CacheMap, charcode));
-  CPDF_Type3Char* pCachedChar = pNewChar.release();
-  m_CacheMap[charcode] = pCachedChar;
-  if (pCachedChar->m_pForm->GetPageObjectList()->empty()) {
-    delete pCachedChar->m_pForm;
-    pCachedChar->m_pForm = nullptr;
-  }
-  return pCachedChar;
-}
-
-int CPDF_Type3Font::GetCharWidthF(FX_DWORD charcode, int level) {
-  if (charcode >= FX_ArraySize(m_CharWidthL))
-    charcode = 0;
-
-  if (m_CharWidthL[charcode])
-    return m_CharWidthL[charcode];
-
-  const CPDF_Type3Char* pChar = LoadChar(charcode, level);
-  return pChar ? pChar->m_Width : 0;
-}
-
-FX_RECT CPDF_Type3Font::GetCharBBox(FX_DWORD charcode, int level) {
-  const CPDF_Type3Char* pChar = LoadChar(charcode, level);
-  return pChar ? pChar->m_BBox : FX_RECT();
-}
-
-CPDF_Type3Char::CPDF_Type3Char(CPDF_Form* pForm)
-    : m_pForm(pForm), m_pBitmap(nullptr), m_bColored(FALSE) {}
-
-CPDF_Type3Char::~CPDF_Type3Char() {
-  delete m_pForm;
-  delete m_pBitmap;
-}
diff --git a/core/fpdfapi/fpdf_font/fpdf_font_cid.cpp b/core/fpdfapi/fpdf_font/fpdf_font_cid.cpp
index c73043a..95452a7 100644
--- a/core/fpdfapi/fpdf_font/fpdf_font_cid.cpp
+++ b/core/fpdfapi/fpdf_font/fpdf_font_cid.cpp
@@ -13,7 +13,6 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
 #include "core/fxcrt/include/fx_ext.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "core/include/fxge/fx_freetype.h"
 #include "core/include/fxge/fx_ge.h"
 
@@ -22,7 +21,6 @@
 const FX_CHAR* const g_CharsetNames[CIDSET_NUM_SETS] = {
     nullptr, "GB1", "CNS1", "Japan1", "Korea1", "UCS"};
 
-const uint16_t g_CharsetCPs[CIDSET_NUM_SETS] = {0, 936, 950, 932, 949, 1200};
 
 class CPDF_PredefinedCMap {
  public:
@@ -192,14 +190,6 @@
   return static_cast<CIDSet>(index);
 }
 
-CIDSet CharsetFromOrdering(const CFX_ByteString& ordering) {
-  for (size_t charset = 1; charset < FX_ArraySize(g_CharsetNames); ++charset) {
-    if (ordering == CFX_ByteStringC(g_CharsetNames[charset]))
-      return CIDSetFromSizeT(charset);
-  }
-  return CIDSET_UNKNOWN;
-}
-
 CFX_ByteString CMap_GetString(const CFX_ByteStringC& word) {
   return word.Mid(1, word.GetLength() - 2);
 }
@@ -284,183 +274,6 @@
   return 1;
 }
 
-#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
-
-bool IsValidEmbeddedCharcodeFromUnicodeCharset(CIDSet charset) {
-  switch (charset) {
-    case CIDSET_GB1:
-    case CIDSET_CNS1:
-    case CIDSET_JAPAN1:
-    case CIDSET_KOREA1:
-      return true;
-
-    default:
-      return false;
-  }
-}
-
-FX_DWORD EmbeddedCharcodeFromUnicode(const FXCMAP_CMap* pEmbedMap,
-                                     CIDSet charset,
-                                     FX_WCHAR unicode) {
-  if (!IsValidEmbeddedCharcodeFromUnicodeCharset(charset))
-    return 0;
-
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
-  const uint16_t* pCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap;
-  if (!pCodes)
-    return 0;
-
-  int nCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count;
-  for (int i = 0; i < nCodes; ++i) {
-    if (pCodes[i] == unicode) {
-      FX_DWORD CharCode = FPDFAPI_CharCodeFromCID(pEmbedMap, i);
-      if (CharCode != 0) {
-        return CharCode;
-      }
-    }
-  }
-  return 0;
-}
-
-FX_WCHAR EmbeddedUnicodeFromCharcode(const FXCMAP_CMap* pEmbedMap,
-                                     CIDSet charset,
-                                     FX_DWORD charcode) {
-  if (!IsValidEmbeddedCharcodeFromUnicodeCharset(charset))
-    return 0;
-
-  uint16_t cid = FPDFAPI_CIDFromCharCode(pEmbedMap, charcode);
-  if (cid == 0)
-    return 0;
-
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
-  const uint16_t* pCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap;
-  if (!pCodes)
-    return 0;
-
-  if (cid < pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count)
-    return pCodes[cid];
-  return 0;
-}
-
-#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
-
-void FT_UseCIDCharmap(FXFT_Face face, int coding) {
-  int encoding;
-  switch (coding) {
-    case CIDCODING_GB:
-      encoding = FXFT_ENCODING_GB2312;
-      break;
-    case CIDCODING_BIG5:
-      encoding = FXFT_ENCODING_BIG5;
-      break;
-    case CIDCODING_JIS:
-      encoding = FXFT_ENCODING_SJIS;
-      break;
-    case CIDCODING_KOREA:
-      encoding = FXFT_ENCODING_JOHAB;
-      break;
-    default:
-      encoding = FXFT_ENCODING_UNICODE;
-  }
-  int err = FXFT_Select_Charmap(face, encoding);
-  if (err) {
-    err = FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE);
-  }
-  if (err && FXFT_Get_Face_Charmaps(face)) {
-    FXFT_Set_Charmap(face, *FXFT_Get_Face_Charmaps(face));
-  }
-}
-
-const struct CIDTransform {
-  uint16_t CID;
-  uint8_t a, b, c, d, e, f;
-} g_Japan1_VertCIDs[] = {
-    {97, 129, 0, 0, 127, 55, 0},     {7887, 127, 0, 0, 127, 76, 89},
-    {7888, 127, 0, 0, 127, 79, 94},  {7889, 0, 129, 127, 0, 17, 127},
-    {7890, 0, 129, 127, 0, 17, 127}, {7891, 0, 129, 127, 0, 17, 127},
-    {7892, 0, 129, 127, 0, 17, 127}, {7893, 0, 129, 127, 0, 17, 127},
-    {7894, 0, 129, 127, 0, 17, 127}, {7895, 0, 129, 127, 0, 17, 127},
-    {7896, 0, 129, 127, 0, 17, 127}, {7897, 0, 129, 127, 0, 17, 127},
-    {7898, 0, 129, 127, 0, 17, 127}, {7899, 0, 129, 127, 0, 17, 104},
-    {7900, 0, 129, 127, 0, 17, 127}, {7901, 0, 129, 127, 0, 17, 104},
-    {7902, 0, 129, 127, 0, 17, 127}, {7903, 0, 129, 127, 0, 17, 127},
-    {7904, 0, 129, 127, 0, 17, 127}, {7905, 0, 129, 127, 0, 17, 114},
-    {7906, 0, 129, 127, 0, 17, 127}, {7907, 0, 129, 127, 0, 17, 127},
-    {7908, 0, 129, 127, 0, 17, 127}, {7909, 0, 129, 127, 0, 17, 127},
-    {7910, 0, 129, 127, 0, 17, 127}, {7911, 0, 129, 127, 0, 17, 127},
-    {7912, 0, 129, 127, 0, 17, 127}, {7913, 0, 129, 127, 0, 17, 127},
-    {7914, 0, 129, 127, 0, 17, 127}, {7915, 0, 129, 127, 0, 17, 114},
-    {7916, 0, 129, 127, 0, 17, 127}, {7917, 0, 129, 127, 0, 17, 127},
-    {7918, 127, 0, 0, 127, 18, 25},  {7919, 127, 0, 0, 127, 18, 25},
-    {7920, 127, 0, 0, 127, 18, 25},  {7921, 127, 0, 0, 127, 18, 25},
-    {7922, 127, 0, 0, 127, 18, 25},  {7923, 127, 0, 0, 127, 18, 25},
-    {7924, 127, 0, 0, 127, 18, 25},  {7925, 127, 0, 0, 127, 18, 25},
-    {7926, 127, 0, 0, 127, 18, 25},  {7927, 127, 0, 0, 127, 18, 25},
-    {7928, 127, 0, 0, 127, 18, 25},  {7929, 127, 0, 0, 127, 18, 25},
-    {7930, 127, 0, 0, 127, 18, 25},  {7931, 127, 0, 0, 127, 18, 25},
-    {7932, 127, 0, 0, 127, 18, 25},  {7933, 127, 0, 0, 127, 18, 25},
-    {7934, 127, 0, 0, 127, 18, 25},  {7935, 127, 0, 0, 127, 18, 25},
-    {7936, 127, 0, 0, 127, 18, 25},  {7937, 127, 0, 0, 127, 18, 25},
-    {7938, 127, 0, 0, 127, 18, 25},  {7939, 127, 0, 0, 127, 18, 25},
-    {8720, 0, 129, 127, 0, 19, 102}, {8721, 0, 129, 127, 0, 13, 127},
-    {8722, 0, 129, 127, 0, 19, 108}, {8723, 0, 129, 127, 0, 19, 102},
-    {8724, 0, 129, 127, 0, 19, 102}, {8725, 0, 129, 127, 0, 19, 102},
-    {8726, 0, 129, 127, 0, 19, 102}, {8727, 0, 129, 127, 0, 19, 102},
-    {8728, 0, 129, 127, 0, 19, 114}, {8729, 0, 129, 127, 0, 19, 114},
-    {8730, 0, 129, 127, 0, 38, 108}, {8731, 0, 129, 127, 0, 13, 108},
-    {8732, 0, 129, 127, 0, 19, 108}, {8733, 0, 129, 127, 0, 19, 108},
-    {8734, 0, 129, 127, 0, 19, 108}, {8735, 0, 129, 127, 0, 19, 108},
-    {8736, 0, 129, 127, 0, 19, 102}, {8737, 0, 129, 127, 0, 19, 102},
-    {8738, 0, 129, 127, 0, 19, 102}, {8739, 0, 129, 127, 0, 19, 102},
-    {8740, 0, 129, 127, 0, 19, 102}, {8741, 0, 129, 127, 0, 19, 102},
-    {8742, 0, 129, 127, 0, 19, 102}, {8743, 0, 129, 127, 0, 19, 102},
-    {8744, 0, 129, 127, 0, 19, 102}, {8745, 0, 129, 127, 0, 19, 102},
-    {8746, 0, 129, 127, 0, 19, 114}, {8747, 0, 129, 127, 0, 19, 114},
-    {8748, 0, 129, 127, 0, 19, 102}, {8749, 0, 129, 127, 0, 19, 102},
-    {8750, 0, 129, 127, 0, 19, 102}, {8751, 0, 129, 127, 0, 19, 102},
-    {8752, 0, 129, 127, 0, 19, 102}, {8753, 0, 129, 127, 0, 19, 102},
-    {8754, 0, 129, 127, 0, 19, 102}, {8755, 0, 129, 127, 0, 19, 102},
-    {8756, 0, 129, 127, 0, 19, 102}, {8757, 0, 129, 127, 0, 19, 102},
-    {8758, 0, 129, 127, 0, 19, 102}, {8759, 0, 129, 127, 0, 19, 102},
-    {8760, 0, 129, 127, 0, 19, 102}, {8761, 0, 129, 127, 0, 19, 102},
-    {8762, 0, 129, 127, 0, 19, 102}, {8763, 0, 129, 127, 0, 19, 102},
-    {8764, 0, 129, 127, 0, 19, 102}, {8765, 0, 129, 127, 0, 19, 102},
-    {8766, 0, 129, 127, 0, 19, 102}, {8767, 0, 129, 127, 0, 19, 102},
-    {8768, 0, 129, 127, 0, 19, 102}, {8769, 0, 129, 127, 0, 19, 102},
-    {8770, 0, 129, 127, 0, 19, 102}, {8771, 0, 129, 127, 0, 19, 102},
-    {8772, 0, 129, 127, 0, 19, 102}, {8773, 0, 129, 127, 0, 19, 102},
-    {8774, 0, 129, 127, 0, 19, 102}, {8775, 0, 129, 127, 0, 19, 102},
-    {8776, 0, 129, 127, 0, 19, 102}, {8777, 0, 129, 127, 0, 19, 102},
-    {8778, 0, 129, 127, 0, 19, 102}, {8779, 0, 129, 127, 0, 19, 114},
-    {8780, 0, 129, 127, 0, 19, 108}, {8781, 0, 129, 127, 0, 19, 114},
-    {8782, 0, 129, 127, 0, 13, 114}, {8783, 0, 129, 127, 0, 19, 108},
-    {8784, 0, 129, 127, 0, 13, 114}, {8785, 0, 129, 127, 0, 19, 108},
-    {8786, 0, 129, 127, 0, 19, 108}, {8787, 0, 129, 127, 0, 19, 108},
-    {8788, 0, 129, 127, 0, 19, 108}, {8789, 0, 129, 127, 0, 19, 108},
-    {8790, 0, 129, 127, 0, 19, 108}, {8791, 0, 129, 127, 0, 19, 108},
-    {8792, 0, 129, 127, 0, 19, 108}, {8793, 0, 129, 127, 0, 19, 108},
-    {8794, 0, 129, 127, 0, 19, 108}, {8795, 0, 129, 127, 0, 19, 108},
-    {8796, 0, 129, 127, 0, 19, 108}, {8797, 0, 129, 127, 0, 19, 108},
-    {8798, 0, 129, 127, 0, 19, 108}, {8799, 0, 129, 127, 0, 19, 108},
-    {8800, 0, 129, 127, 0, 19, 108}, {8801, 0, 129, 127, 0, 19, 108},
-    {8802, 0, 129, 127, 0, 19, 108}, {8803, 0, 129, 127, 0, 19, 108},
-    {8804, 0, 129, 127, 0, 19, 108}, {8805, 0, 129, 127, 0, 19, 108},
-    {8806, 0, 129, 127, 0, 19, 108}, {8807, 0, 129, 127, 0, 19, 108},
-    {8808, 0, 129, 127, 0, 19, 108}, {8809, 0, 129, 127, 0, 19, 108},
-    {8810, 0, 129, 127, 0, 19, 108}, {8811, 0, 129, 127, 0, 19, 114},
-    {8812, 0, 129, 127, 0, 19, 102}, {8813, 0, 129, 127, 0, 19, 114},
-    {8814, 0, 129, 127, 0, 76, 102}, {8815, 0, 129, 127, 0, 13, 121},
-    {8816, 0, 129, 127, 0, 19, 114}, {8817, 0, 129, 127, 0, 19, 127},
-    {8818, 0, 129, 127, 0, 19, 114}, {8819, 0, 129, 127, 0, 218, 108},
-};
-
-int CompareCIDTransform(const void* key, const void* element) {
-  uint16_t CID = *static_cast<const uint16_t*>(key);
-  return CID - static_cast<const struct CIDTransform*>(element)->CID;
-}
-
 }  // namespace
 
 CPDF_CMapManager::CPDF_CMapManager() {
@@ -975,706 +788,10 @@
   FPDFAPI_LoadCID2UnicodeMap(charset, m_pEmbeddedMap, m_EmbeddedCount);
 }
 
-CPDF_CIDFont::CPDF_CIDFont()
-    : m_pCMap(nullptr),
-      m_pAllocatedCMap(nullptr),
-      m_pCID2UnicodeMap(nullptr),
-      m_pCIDToGIDMap(nullptr),
-      m_bCIDIsGID(FALSE),
-      m_pAnsiWidths(nullptr),
-      m_bAdobeCourierStd(FALSE),
-      m_pTTGSUBTable(nullptr) {}
-
-CPDF_CIDFont::~CPDF_CIDFont() {
-  if (m_pAnsiWidths) {
-    FX_Free(m_pAnsiWidths);
+CIDSet CharsetFromOrdering(const CFX_ByteString& ordering) {
+  for (size_t charset = 1; charset < FX_ArraySize(g_CharsetNames); ++charset) {
+    if (ordering == CFX_ByteStringC(g_CharsetNames[charset]))
+      return CIDSetFromSizeT(charset);
   }
-  delete m_pAllocatedCMap;
-  delete m_pCIDToGIDMap;
-  delete m_pTTGSUBTable;
-}
-
-bool CPDF_CIDFont::IsCIDFont() const {
-  return true;
-}
-
-const CPDF_CIDFont* CPDF_CIDFont::AsCIDFont() const {
-  return this;
-}
-
-CPDF_CIDFont* CPDF_CIDFont::AsCIDFont() {
-  return this;
-}
-
-uint16_t CPDF_CIDFont::CIDFromCharCode(FX_DWORD charcode) const {
-  if (!m_pCMap) {
-    return (uint16_t)charcode;
-  }
-  return m_pCMap->CIDFromCharCode(charcode);
-}
-
-FX_BOOL CPDF_CIDFont::IsVertWriting() const {
-  return m_pCMap ? m_pCMap->IsVertWriting() : FALSE;
-}
-
-CFX_WideString CPDF_CIDFont::UnicodeFromCharCode(FX_DWORD charcode) const {
-  CFX_WideString str = CPDF_Font::UnicodeFromCharCode(charcode);
-  if (!str.IsEmpty())
-    return str;
-  FX_WCHAR ret = GetUnicodeFromCharCode(charcode);
-  if (ret == 0)
-    return CFX_WideString();
-  return ret;
-}
-
-FX_WCHAR CPDF_CIDFont::GetUnicodeFromCharCode(FX_DWORD charcode) const {
-  switch (m_pCMap->m_Coding) {
-    case CIDCODING_UCS2:
-    case CIDCODING_UTF16:
-      return (FX_WCHAR)charcode;
-    case CIDCODING_CID:
-      if (!m_pCID2UnicodeMap || !m_pCID2UnicodeMap->IsLoaded()) {
-        return 0;
-      }
-      return m_pCID2UnicodeMap->UnicodeFromCID((uint16_t)charcode);
-  }
-  if (!m_pCMap->IsLoaded() || !m_pCID2UnicodeMap ||
-      !m_pCID2UnicodeMap->IsLoaded()) {
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
-    FX_WCHAR unicode;
-    int charsize = 1;
-    if (charcode > 255) {
-      charcode = (charcode % 256) * 256 + (charcode / 256);
-      charsize = 2;
-    }
-    int ret = FXSYS_MultiByteToWideChar(g_CharsetCPs[m_pCMap->m_Coding], 0,
-                                        (const FX_CHAR*)&charcode, charsize,
-                                        &unicode, 1);
-    if (ret != 1) {
-      return 0;
-    }
-    return unicode;
-#else
-    if (m_pCMap->m_pEmbedMap) {
-      return EmbeddedUnicodeFromCharcode(m_pCMap->m_pEmbedMap,
-                                         m_pCMap->m_Charset, charcode);
-    }
-    return 0;
-#endif
-  }
-  return m_pCID2UnicodeMap->UnicodeFromCID(CIDFromCharCode(charcode));
-}
-
-FX_DWORD CPDF_CIDFont::CharCodeFromUnicode(FX_WCHAR unicode) const {
-  FX_DWORD charcode = CPDF_Font::CharCodeFromUnicode(unicode);
-  if (charcode)
-    return charcode;
-  switch (m_pCMap->m_Coding) {
-    case CIDCODING_UNKNOWN:
-      return 0;
-    case CIDCODING_UCS2:
-    case CIDCODING_UTF16:
-      return unicode;
-    case CIDCODING_CID: {
-      if (!m_pCID2UnicodeMap || !m_pCID2UnicodeMap->IsLoaded()) {
-        return 0;
-      }
-      FX_DWORD CID = 0;
-      while (CID < 65536) {
-        FX_WCHAR this_unicode =
-            m_pCID2UnicodeMap->UnicodeFromCID((uint16_t)CID);
-        if (this_unicode == unicode) {
-          return CID;
-        }
-        CID++;
-      }
-      break;
-    }
-  }
-
-  if (unicode < 0x80) {
-    return static_cast<FX_DWORD>(unicode);
-  }
-  if (m_pCMap->m_Coding == CIDCODING_CID) {
-    return 0;
-  }
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
-  uint8_t buffer[32];
-  int ret =
-      FXSYS_WideCharToMultiByte(g_CharsetCPs[m_pCMap->m_Coding], 0, &unicode, 1,
-                                (char*)buffer, 4, NULL, NULL);
-  if (ret == 1) {
-    return buffer[0];
-  }
-  if (ret == 2) {
-    return buffer[0] * 256 + buffer[1];
-  }
-#else
-  if (m_pCMap->m_pEmbedMap) {
-    return EmbeddedCharcodeFromUnicode(m_pCMap->m_pEmbedMap, m_pCMap->m_Charset,
-                                       unicode);
-  }
-#endif
-  return 0;
-}
-
-FX_BOOL CPDF_CIDFont::Load() {
-  if (m_pFontDict->GetStringBy("Subtype") == "TrueType") {
-    return LoadGB2312();
-  }
-  CPDF_Array* pFonts = m_pFontDict->GetArrayBy("DescendantFonts");
-  if (!pFonts) {
-    return FALSE;
-  }
-  if (pFonts->GetCount() != 1) {
-    return FALSE;
-  }
-  CPDF_Dictionary* pCIDFontDict = pFonts->GetDictAt(0);
-  if (!pCIDFontDict) {
-    return FALSE;
-  }
-  m_BaseFont = pCIDFontDict->GetStringBy("BaseFont");
-  if ((m_BaseFont.Compare("CourierStd") == 0 ||
-       m_BaseFont.Compare("CourierStd-Bold") == 0 ||
-       m_BaseFont.Compare("CourierStd-BoldOblique") == 0 ||
-       m_BaseFont.Compare("CourierStd-Oblique") == 0) &&
-      !IsEmbedded()) {
-    m_bAdobeCourierStd = TRUE;
-  }
-  CPDF_Dictionary* pFontDesc = pCIDFontDict->GetDictBy("FontDescriptor");
-  if (pFontDesc) {
-    LoadFontDescriptor(pFontDesc);
-  }
-  CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding");
-  if (!pEncoding) {
-    return FALSE;
-  }
-  CFX_ByteString subtype = pCIDFontDict->GetStringBy("Subtype");
-  m_bType1 = (subtype == "CIDFontType0");
-
-  if (pEncoding->IsName()) {
-    CFX_ByteString cmap = pEncoding->GetString();
-    m_pCMap =
-        CPDF_ModuleMgr::Get()
-            ->GetPageModule()
-            ->GetFontGlobals()
-            ->m_CMapManager.GetPredefinedCMap(cmap, m_pFontFile && m_bType1);
-  } else if (CPDF_Stream* pStream = pEncoding->AsStream()) {
-    m_pAllocatedCMap = m_pCMap = new CPDF_CMap;
-    CPDF_StreamAcc acc;
-    acc.LoadAllData(pStream, FALSE);
-    m_pCMap->LoadEmbedded(acc.GetData(), acc.GetSize());
-  } else {
-    return FALSE;
-  }
-  if (!m_pCMap) {
-    return FALSE;
-  }
-  m_Charset = m_pCMap->m_Charset;
-  if (m_Charset == CIDSET_UNKNOWN) {
-    CPDF_Dictionary* pCIDInfo = pCIDFontDict->GetDictBy("CIDSystemInfo");
-    if (pCIDInfo) {
-      m_Charset = CharsetFromOrdering(pCIDInfo->GetStringBy("Ordering"));
-    }
-  }
-  if (m_Charset != CIDSET_UNKNOWN)
-    m_pCID2UnicodeMap =
-        CPDF_ModuleMgr::Get()
-            ->GetPageModule()
-            ->GetFontGlobals()
-            ->m_CMapManager.GetCID2UnicodeMap(
-                m_Charset,
-                !m_pFontFile && (m_pCMap->m_Coding == CIDCODING_CID ||
-                                 pCIDFontDict->KeyExist("W")));
-  if (m_Font.GetFace()) {
-    if (m_bType1) {
-      FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE);
-    } else {
-      FT_UseCIDCharmap(m_Font.GetFace(), m_pCMap->m_Coding);
-    }
-  }
-  m_DefaultWidth = pCIDFontDict->GetIntegerBy("DW", 1000);
-  CPDF_Array* pWidthArray = pCIDFontDict->GetArrayBy("W");
-  if (pWidthArray) {
-    LoadMetricsArray(pWidthArray, m_WidthList, 1);
-  }
-  if (!IsEmbedded()) {
-    LoadSubstFont();
-  }
-  if (1) {
-    if (m_pFontFile || (GetSubstFont()->m_SubstFlags & FXFONT_SUBST_EXACT)) {
-      CPDF_Object* pmap = pCIDFontDict->GetElementValue("CIDToGIDMap");
-      if (pmap) {
-        if (CPDF_Stream* pStream = pmap->AsStream()) {
-          m_pCIDToGIDMap = new CPDF_StreamAcc;
-          m_pCIDToGIDMap->LoadAllData(pStream, FALSE);
-        } else if (pmap->GetString() == "Identity") {
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
-          if (m_pFontFile) {
-            m_bCIDIsGID = TRUE;
-          }
-#else
-          m_bCIDIsGID = TRUE;
-#endif
-        }
-      }
-    }
-  }
-  CheckFontMetrics();
-  if (IsVertWriting()) {
-    pWidthArray = pCIDFontDict->GetArrayBy("W2");
-    if (pWidthArray) {
-      LoadMetricsArray(pWidthArray, m_VertMetrics, 3);
-    }
-    CPDF_Array* pDefaultArray = pCIDFontDict->GetArrayBy("DW2");
-    if (pDefaultArray) {
-      m_DefaultVY = pDefaultArray->GetIntegerAt(0);
-      m_DefaultW1 = pDefaultArray->GetIntegerAt(1);
-    } else {
-      m_DefaultVY = 880;
-      m_DefaultW1 = -1000;
-    }
-  }
-  return TRUE;
-}
-
-FX_RECT CPDF_CIDFont::GetCharBBox(FX_DWORD charcode, int level) {
-  if (charcode < 256 && m_CharBBox[charcode].right != FX_SMALL_RECT::kInvalid)
-    return FX_RECT(m_CharBBox[charcode]);
-
-  FX_RECT rect;
-  FX_BOOL bVert = FALSE;
-  int glyph_index = GlyphFromCharCode(charcode, &bVert);
-  FXFT_Face face = m_Font.GetFace();
-  if (face) {
-    if (FXFT_Is_Face_Tricky(face)) {
-      int err = FXFT_Load_Glyph(face, glyph_index,
-                                FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
-      if (!err) {
-        FXFT_BBox cbox;
-        FXFT_Glyph glyph;
-        err = FXFT_Get_Glyph(((FXFT_Face)face)->glyph, &glyph);
-        if (!err) {
-          FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox);
-          int pixel_size_x = ((FXFT_Face)face)->size->metrics.x_ppem;
-          int pixel_size_y = ((FXFT_Face)face)->size->metrics.y_ppem;
-          if (pixel_size_x == 0 || pixel_size_y == 0) {
-            rect = FX_RECT(cbox.xMin, cbox.yMax, cbox.xMax, cbox.yMin);
-          } else {
-            rect = FX_RECT(cbox.xMin * 1000 / pixel_size_x,
-                           cbox.yMax * 1000 / pixel_size_y,
-                           cbox.xMax * 1000 / pixel_size_x,
-                           cbox.yMin * 1000 / pixel_size_y);
-          }
-          if (rect.top > FXFT_Get_Face_Ascender(face)) {
-            rect.top = FXFT_Get_Face_Ascender(face);
-          }
-          if (rect.bottom < FXFT_Get_Face_Descender(face)) {
-            rect.bottom = FXFT_Get_Face_Descender(face);
-          }
-          FXFT_Done_Glyph(glyph);
-        }
-      }
-    } else {
-      int err = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_NO_SCALE);
-      if (err == 0) {
-        rect = FX_RECT(TT2PDF(FXFT_Get_Glyph_HoriBearingX(face), face),
-                       TT2PDF(FXFT_Get_Glyph_HoriBearingY(face), face),
-                       TT2PDF(FXFT_Get_Glyph_HoriBearingX(face) +
-                                  FXFT_Get_Glyph_Width(face),
-                              face),
-                       TT2PDF(FXFT_Get_Glyph_HoriBearingY(face) -
-                                  FXFT_Get_Glyph_Height(face),
-                              face));
-        rect.top += rect.top / 64;
-      }
-    }
-  }
-  if (!m_pFontFile && m_Charset == CIDSET_JAPAN1) {
-    uint16_t CID = CIDFromCharCode(charcode);
-    const uint8_t* pTransform = GetCIDTransform(CID);
-    if (pTransform && !bVert) {
-      CFX_Matrix matrix(CIDTransformToFloat(pTransform[0]),
-                        CIDTransformToFloat(pTransform[1]),
-                        CIDTransformToFloat(pTransform[2]),
-                        CIDTransformToFloat(pTransform[3]),
-                        CIDTransformToFloat(pTransform[4]) * 1000,
-                        CIDTransformToFloat(pTransform[5]) * 1000);
-      CFX_FloatRect rect_f(rect);
-      rect_f.Transform(&matrix);
-      rect = rect_f.GetOutterRect();
-    }
-  }
-  if (charcode < 256)
-    m_CharBBox[charcode] = rect.ToSmallRect();
-
-  return rect;
-}
-int CPDF_CIDFont::GetCharWidthF(FX_DWORD charcode, int level) {
-  if (m_pAnsiWidths && charcode < 0x80) {
-    return m_pAnsiWidths[charcode];
-  }
-  uint16_t cid = CIDFromCharCode(charcode);
-  int size = m_WidthList.GetSize();
-  FX_DWORD* list = m_WidthList.GetData();
-  for (int i = 0; i < size; i += 3) {
-    if (cid >= list[i] && cid <= list[i + 1]) {
-      return (int)list[i + 2];
-    }
-  }
-  return m_DefaultWidth;
-}
-short CPDF_CIDFont::GetVertWidth(uint16_t CID) const {
-  FX_DWORD vertsize = m_VertMetrics.GetSize() / 5;
-  if (vertsize == 0) {
-    return m_DefaultW1;
-  }
-  const FX_DWORD* pTable = m_VertMetrics.GetData();
-  for (FX_DWORD i = 0; i < vertsize; i++)
-    if (pTable[i * 5] <= CID && pTable[i * 5 + 1] >= CID) {
-      return (short)(int)pTable[i * 5 + 2];
-    }
-  return m_DefaultW1;
-}
-void CPDF_CIDFont::GetVertOrigin(uint16_t CID, short& vx, short& vy) const {
-  FX_DWORD vertsize = m_VertMetrics.GetSize() / 5;
-  if (vertsize) {
-    const FX_DWORD* pTable = m_VertMetrics.GetData();
-    for (FX_DWORD i = 0; i < vertsize; i++)
-      if (pTable[i * 5] <= CID && pTable[i * 5 + 1] >= CID) {
-        vx = (short)(int)pTable[i * 5 + 3];
-        vy = (short)(int)pTable[i * 5 + 4];
-        return;
-      }
-  }
-  FX_DWORD dwWidth = m_DefaultWidth;
-  int size = m_WidthList.GetSize();
-  const FX_DWORD* list = m_WidthList.GetData();
-  for (int i = 0; i < size; i += 3) {
-    if (CID >= list[i] && CID <= list[i + 1]) {
-      dwWidth = (uint16_t)list[i + 2];
-      break;
-    }
-  }
-  vx = (short)dwWidth / 2;
-  vy = (short)m_DefaultVY;
-}
-int CPDF_CIDFont::GetGlyphIndex(FX_DWORD unicode, FX_BOOL* pVertGlyph) {
-  if (pVertGlyph) {
-    *pVertGlyph = FALSE;
-  }
-  FXFT_Face face = m_Font.GetFace();
-  int index = FXFT_Get_Char_Index(face, unicode);
-  if (unicode == 0x2502) {
-    return index;
-  }
-  if (index && IsVertWriting()) {
-    if (m_pTTGSUBTable) {
-      uint32_t vindex = 0;
-      m_pTTGSUBTable->GetVerticalGlyph(index, &vindex);
-      if (vindex) {
-        index = vindex;
-        if (pVertGlyph) {
-          *pVertGlyph = TRUE;
-        }
-      }
-      return index;
-    }
-    if (!m_Font.GetSubData()) {
-      unsigned long length = 0;
-      int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
-                                       NULL, &length);
-      if (!error) {
-        m_Font.SetSubData(FX_Alloc(uint8_t, length));
-      }
-    }
-    int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
-                                     m_Font.GetSubData(), NULL);
-    if (!error && m_Font.GetSubData()) {
-      m_pTTGSUBTable = new CFX_CTTGSUBTable;
-      m_pTTGSUBTable->LoadGSUBTable((FT_Bytes)m_Font.GetSubData());
-      uint32_t vindex = 0;
-      m_pTTGSUBTable->GetVerticalGlyph(index, &vindex);
-      if (vindex) {
-        index = vindex;
-        if (pVertGlyph) {
-          *pVertGlyph = TRUE;
-        }
-      }
-    }
-    return index;
-  }
-  if (pVertGlyph) {
-    *pVertGlyph = FALSE;
-  }
-  return index;
-}
-int CPDF_CIDFont::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) {
-  if (pVertGlyph) {
-    *pVertGlyph = FALSE;
-  }
-  if (!m_pFontFile && !m_pCIDToGIDMap) {
-    uint16_t cid = CIDFromCharCode(charcode);
-    FX_WCHAR unicode = 0;
-    if (m_bCIDIsGID) {
-#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
-      return cid;
-#else
-      if (m_Flags & PDFFONT_SYMBOLIC) {
-        return cid;
-      }
-      CFX_WideString uni_str = UnicodeFromCharCode(charcode);
-      if (uni_str.IsEmpty()) {
-        return cid;
-      }
-      unicode = uni_str.GetAt(0);
-#endif
-    } else {
-      if (cid && m_pCID2UnicodeMap && m_pCID2UnicodeMap->IsLoaded()) {
-        unicode = m_pCID2UnicodeMap->UnicodeFromCID(cid);
-      }
-      if (unicode == 0) {
-        unicode = GetUnicodeFromCharCode(charcode);
-      }
-      if (unicode == 0 && !(m_Flags & PDFFONT_SYMBOLIC)) {
-        unicode = UnicodeFromCharCode(charcode).GetAt(0);
-      }
-    }
-    FXFT_Face face = m_Font.GetFace();
-    if (unicode == 0) {
-      if (!m_bAdobeCourierStd) {
-        return charcode == 0 ? -1 : (int)charcode;
-      }
-      charcode += 31;
-      int index = 0, iBaseEncoding;
-      FX_BOOL bMSUnicode = FT_UseTTCharmap(face, 3, 1);
-      FX_BOOL bMacRoman = FALSE;
-      if (!bMSUnicode) {
-        bMacRoman = FT_UseTTCharmap(face, 1, 0);
-      }
-      iBaseEncoding = PDFFONT_ENCODING_STANDARD;
-      if (bMSUnicode) {
-        iBaseEncoding = PDFFONT_ENCODING_WINANSI;
-      } else if (bMacRoman) {
-        iBaseEncoding = PDFFONT_ENCODING_MACROMAN;
-      }
-      const FX_CHAR* name = GetAdobeCharName(iBaseEncoding, NULL, charcode);
-      if (!name) {
-        return charcode == 0 ? -1 : (int)charcode;
-      }
-      uint16_t unicode = PDF_UnicodeFromAdobeName(name);
-      if (unicode) {
-        if (bMSUnicode) {
-          index = FXFT_Get_Char_Index(face, unicode);
-        } else if (bMacRoman) {
-          FX_DWORD maccode =
-              FT_CharCodeFromUnicode(FXFT_ENCODING_APPLE_ROMAN, unicode);
-          index = !maccode ? FXFT_Get_Name_Index(face, (char*)name)
-                           : FXFT_Get_Char_Index(face, maccode);
-        } else {
-          return FXFT_Get_Char_Index(face, unicode);
-        }
-      } else {
-        return charcode == 0 ? -1 : (int)charcode;
-      }
-      if (index == 0 || index == 0xffff) {
-        return charcode == 0 ? -1 : (int)charcode;
-      }
-      return index;
-    }
-    if (m_Charset == CIDSET_JAPAN1) {
-      if (unicode == '\\') {
-        unicode = '/';
-#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
-      } else if (unicode == 0xa5) {
-        unicode = 0x5c;
-#endif
-      }
-    }
-    if (!face)
-      return unicode;
-
-    int err = FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE);
-    if (err != 0) {
-      int i;
-      for (i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
-        FX_DWORD ret = FT_CharCodeFromUnicode(
-            FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i]),
-            (FX_WCHAR)charcode);
-        if (ret == 0) {
-          continue;
-        }
-        FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[i]);
-        unicode = (FX_WCHAR)ret;
-        break;
-      }
-      if (i == FXFT_Get_Face_CharmapCount(face) && i) {
-        FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]);
-        unicode = (FX_WCHAR)charcode;
-      }
-    }
-    if (FXFT_Get_Face_Charmap(face)) {
-      int index = GetGlyphIndex(unicode, pVertGlyph);
-      if (index == 0)
-        return -1;
-      return index;
-    }
-    return unicode;
-  }
-  if (!m_Font.GetFace())
-    return -1;
-
-  uint16_t cid = CIDFromCharCode(charcode);
-  if (m_bType1) {
-    if (!m_pCIDToGIDMap) {
-      return cid;
-    }
-  } else {
-    if (!m_pCIDToGIDMap) {
-      if (m_pFontFile && !m_pCMap->m_pMapping)
-        return cid;
-      if (m_pCMap->m_Coding == CIDCODING_UNKNOWN ||
-          !FXFT_Get_Face_Charmap(m_Font.GetFace())) {
-        return cid;
-      }
-      if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmap(m_Font.GetFace())) ==
-          FXFT_ENCODING_UNICODE) {
-        CFX_WideString unicode_str = UnicodeFromCharCode(charcode);
-        if (unicode_str.IsEmpty()) {
-          return -1;
-        }
-        charcode = unicode_str.GetAt(0);
-      }
-      return GetGlyphIndex(charcode, pVertGlyph);
-    }
-  }
-  FX_DWORD byte_pos = cid * 2;
-  if (byte_pos + 2 > m_pCIDToGIDMap->GetSize())
-    return -1;
-
-  const uint8_t* pdata = m_pCIDToGIDMap->GetData() + byte_pos;
-  return pdata[0] * 256 + pdata[1];
-}
-FX_DWORD CPDF_CIDFont::GetNextChar(const FX_CHAR* pString,
-                                   int nStrLen,
-                                   int& offset) const {
-  return m_pCMap->GetNextChar(pString, nStrLen, offset);
-}
-int CPDF_CIDFont::GetCharSize(FX_DWORD charcode) const {
-  return m_pCMap->GetCharSize(charcode);
-}
-int CPDF_CIDFont::CountChar(const FX_CHAR* pString, int size) const {
-  return m_pCMap->CountChar(pString, size);
-}
-int CPDF_CIDFont::AppendChar(FX_CHAR* str, FX_DWORD charcode) const {
-  return m_pCMap->AppendChar(str, charcode);
-}
-FX_BOOL CPDF_CIDFont::IsUnicodeCompatible() const {
-  if (!m_pCMap->IsLoaded() || !m_pCID2UnicodeMap ||
-      !m_pCID2UnicodeMap->IsLoaded()) {
-    return m_pCMap->m_Coding != CIDCODING_UNKNOWN;
-  }
-  return TRUE;
-}
-FX_BOOL CPDF_CIDFont::IsFontStyleFromCharCode(FX_DWORD charcode) const {
-  return TRUE;
-}
-void CPDF_CIDFont::LoadSubstFont() {
-  m_Font.LoadSubst(m_BaseFont, !m_bType1, m_Flags, m_StemV * 5, m_ItalicAngle,
-                   g_CharsetCPs[m_Charset], IsVertWriting());
-}
-void CPDF_CIDFont::LoadMetricsArray(CPDF_Array* pArray,
-                                    CFX_DWordArray& result,
-                                    int nElements) {
-  int width_status = 0;
-  int iCurElement = 0;
-  int first_code = 0;
-  int last_code = 0;
-  FX_DWORD count = pArray->GetCount();
-  for (FX_DWORD i = 0; i < count; i++) {
-    CPDF_Object* pObj = pArray->GetElementValue(i);
-    if (!pObj)
-      continue;
-
-    if (CPDF_Array* pArray = pObj->AsArray()) {
-      if (width_status != 1)
-        return;
-
-      FX_DWORD count = pArray->GetCount();
-      for (FX_DWORD j = 0; j < count; j += nElements) {
-        result.Add(first_code);
-        result.Add(first_code);
-        for (int k = 0; k < nElements; k++) {
-          result.Add(pArray->GetIntegerAt(j + k));
-        }
-        first_code++;
-      }
-      width_status = 0;
-    } else {
-      if (width_status == 0) {
-        first_code = pObj->GetInteger();
-        width_status = 1;
-      } else if (width_status == 1) {
-        last_code = pObj->GetInteger();
-        width_status = 2;
-        iCurElement = 0;
-      } else {
-        if (!iCurElement) {
-          result.Add(first_code);
-          result.Add(last_code);
-        }
-        result.Add(pObj->GetInteger());
-        iCurElement++;
-        if (iCurElement == nElements) {
-          width_status = 0;
-        }
-      }
-    }
-  }
-}
-
-// static
-FX_FLOAT CPDF_CIDFont::CIDTransformToFloat(uint8_t ch) {
-  if (ch < 128) {
-    return ch * 1.0f / 127;
-  }
-  return (-255 + ch) * 1.0f / 127;
-}
-
-FX_BOOL CPDF_CIDFont::LoadGB2312() {
-  m_BaseFont = m_pFontDict->GetStringBy("BaseFont");
-  CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictBy("FontDescriptor");
-  if (pFontDesc) {
-    LoadFontDescriptor(pFontDesc);
-  }
-  m_Charset = CIDSET_GB1;
-  m_bType1 = FALSE;
-  m_pCMap = CPDF_ModuleMgr::Get()
-                ->GetPageModule()
-                ->GetFontGlobals()
-                ->m_CMapManager.GetPredefinedCMap("GBK-EUC-H", FALSE);
-  m_pCID2UnicodeMap = CPDF_ModuleMgr::Get()
-                          ->GetPageModule()
-                          ->GetFontGlobals()
-                          ->m_CMapManager.GetCID2UnicodeMap(m_Charset, FALSE);
-  if (!IsEmbedded()) {
-    LoadSubstFont();
-  }
-  CheckFontMetrics();
-  m_DefaultWidth = 1000;
-  m_pAnsiWidths = FX_Alloc(uint16_t, 128);
-  for (int i = 32; i < 127; i++) {
-    m_pAnsiWidths[i] = 500;
-  }
-  return TRUE;
-}
-
-const uint8_t* CPDF_CIDFont::GetCIDTransform(uint16_t CID) const {
-  if (m_Charset != CIDSET_JAPAN1 || m_pFontFile)
-    return nullptr;
-
-  const struct CIDTransform* found = (const struct CIDTransform*)FXSYS_bsearch(
-      &CID, g_Japan1_VertCIDs, FX_ArraySize(g_Japan1_VertCIDs),
-      sizeof(g_Japan1_VertCIDs[0]), CompareCIDTransform);
-  return found ? &found->a : nullptr;
+  return CIDSET_UNKNOWN;
 }
diff --git a/core/fpdfapi/fpdf_font/include/cpdf_font.h b/core/fpdfapi/fpdf_font/include/cpdf_font.h
new file mode 100644
index 0000000..1931c24
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/include/cpdf_font.h
@@ -0,0 +1,128 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_FONT_INCLUDE_CPDF_FONT_H_
+#define CORE_FPDFAPI_FPDF_FONT_INCLUDE_CPDF_FONT_H_
+
+#include "core/fxcrt/include/fx_string.h"
+#include "core/fxcrt/include/fx_system.h"
+#include "core/include/fxge/fx_font.h"
+
+#define PDFFONT_FIXEDPITCH 1
+#define PDFFONT_SERIF 2
+#define PDFFONT_SYMBOLIC 4
+#define PDFFONT_SCRIPT 8
+#define PDFFONT_NONSYMBOLIC 32
+#define PDFFONT_ITALIC 64
+#define PDFFONT_ALLCAP 0x10000
+#define PDFFONT_SMALLCAP 0x20000
+#define PDFFONT_FORCEBOLD 0x40000
+#define PDFFONT_USEEXTERNATTR 0x80000
+
+class CFX_SubstFont;
+class CPDF_CIDFont;
+class CPDF_Dictionary;
+class CPDF_Document;
+class CPDF_Object;
+class CPDF_StreamAcc;
+class CPDF_TrueTypeFont;
+class CPDF_Type1Font;
+class CPDF_Type3Font;
+class CPDF_ToUnicodeMap;
+
+class CPDF_Font {
+ public:
+  static CPDF_Font* CreateFontF(CPDF_Document* pDoc,
+                                CPDF_Dictionary* pFontDict);
+  static CPDF_Font* GetStockFont(CPDF_Document* pDoc,
+                                 const CFX_ByteStringC& fontname);
+  static const FX_DWORD kInvalidCharCode = static_cast<FX_DWORD>(-1);
+
+  virtual ~CPDF_Font();
+
+  virtual bool IsType1Font() const;
+  virtual bool IsTrueTypeFont() const;
+  virtual bool IsType3Font() const;
+  virtual bool IsCIDFont() const;
+  virtual const CPDF_Type1Font* AsType1Font() const;
+  virtual CPDF_Type1Font* AsType1Font();
+  virtual const CPDF_TrueTypeFont* AsTrueTypeFont() const;
+  virtual CPDF_TrueTypeFont* AsTrueTypeFont();
+  virtual const CPDF_Type3Font* AsType3Font() const;
+  virtual CPDF_Type3Font* AsType3Font();
+  virtual const CPDF_CIDFont* AsCIDFont() const;
+  virtual CPDF_CIDFont* AsCIDFont();
+
+  virtual FX_BOOL IsVertWriting() const;
+  virtual FX_BOOL IsUnicodeCompatible() const;
+  virtual FX_DWORD GetNextChar(const FX_CHAR* pString,
+                               int nStrLen,
+                               int& offset) const;
+  virtual int CountChar(const FX_CHAR* pString, int size) const;
+  virtual int AppendChar(FX_CHAR* buf, FX_DWORD charcode) const;
+  virtual int GetCharSize(FX_DWORD charcode) const;
+  virtual int GlyphFromCharCode(FX_DWORD charcode,
+                                FX_BOOL* pVertGlyph = nullptr);
+  virtual int GlyphFromCharCodeExt(FX_DWORD charcode);
+  virtual CFX_WideString UnicodeFromCharCode(FX_DWORD charcode) const;
+  virtual FX_DWORD CharCodeFromUnicode(FX_WCHAR Unicode) const;
+
+  const CFX_ByteString& GetBaseFont() const { return m_BaseFont; }
+  const CFX_SubstFont* GetSubstFont() const { return m_Font.GetSubstFont(); }
+  FX_DWORD GetFlags() const { return m_Flags; }
+  FX_BOOL IsEmbedded() const { return IsType3Font() || m_pFontFile != nullptr; }
+  CPDF_StreamAcc* GetFontFile() const { return m_pFontFile; }
+  CPDF_Dictionary* GetFontDict() const { return m_pFontDict; }
+  FX_BOOL IsStandardFont() const;
+  FXFT_Face GetFace() const { return m_Font.GetFace(); }
+  void AppendChar(CFX_ByteString& str, FX_DWORD charcode) const;
+
+  void GetFontBBox(FX_RECT& rect) const { rect = m_FontBBox; }
+  int GetTypeAscent() const { return m_Ascent; }
+  int GetTypeDescent() const { return m_Descent; }
+  int GetItalicAngle() const { return m_ItalicAngle; }
+  int GetStemV() const { return m_StemV; }
+  int GetStringWidth(const FX_CHAR* pString, int size);
+
+  virtual int GetCharWidthF(FX_DWORD charcode, int level = 0) = 0;
+  virtual FX_RECT GetCharBBox(FX_DWORD charcode, int level = 0) = 0;
+
+  CPDF_Document* m_pDocument;
+  CFX_Font m_Font;
+
+ protected:
+  CPDF_Font();
+
+  virtual FX_BOOL Load() = 0;
+
+  FX_BOOL Initialize();
+  void LoadUnicodeMap();
+  void LoadPDFEncoding(CPDF_Object* pEncoding,
+                       int& iBaseEncoding,
+                       CFX_ByteString*& pCharNames,
+                       FX_BOOL bEmbedded,
+                       FX_BOOL bTrueType);
+  void LoadFontDescriptor(CPDF_Dictionary* pDict);
+  void CheckFontMetrics();
+
+  const FX_CHAR* GetAdobeCharName(int iBaseEncoding,
+                                  const CFX_ByteString* pCharNames,
+                                  int charcode);
+
+  CFX_ByteString m_BaseFont;
+  CPDF_StreamAcc* m_pFontFile;
+  CPDF_Dictionary* m_pFontDict;
+  CPDF_ToUnicodeMap* m_pToUnicodeMap;
+  FX_BOOL m_bToUnicodeLoaded;
+  int m_Flags;
+  FX_RECT m_FontBBox;
+  int m_StemV;
+  int m_Ascent;
+  int m_Descent;
+  int m_ItalicAngle;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_FONT_INCLUDE_CPDF_FONT_H_
diff --git a/core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h b/core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h
new file mode 100644
index 0000000..a64687c
--- /dev/null
+++ b/core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h
@@ -0,0 +1,59 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_FONT_INCLUDE_CPDF_FONTENCODING_H_
+#define CORE_FPDFAPI_FPDF_FONT_INCLUDE_CPDF_FONTENCODING_H_
+
+#include "core/fxcrt/include/fx_string.h"
+
+#define PDFFONT_ENCODING_BUILTIN 0
+#define PDFFONT_ENCODING_WINANSI 1
+#define PDFFONT_ENCODING_MACROMAN 2
+#define PDFFONT_ENCODING_MACEXPERT 3
+#define PDFFONT_ENCODING_STANDARD 4
+#define PDFFONT_ENCODING_ADOBE_SYMBOL 5
+#define PDFFONT_ENCODING_ZAPFDINGBATS 6
+#define PDFFONT_ENCODING_PDFDOC 7
+#define PDFFONT_ENCODING_MS_SYMBOL 8
+#define PDFFONT_ENCODING_UNICODE 9
+
+FX_DWORD FT_CharCodeFromUnicode(int encoding, FX_WCHAR unicode);
+FX_WCHAR FT_UnicodeFromCharCode(int encoding, FX_DWORD charcode);
+
+FX_WCHAR PDF_UnicodeFromAdobeName(const FX_CHAR* name);
+CFX_ByteString PDF_AdobeNameFromUnicode(FX_WCHAR unicode);
+
+const uint16_t* PDF_UnicodesForPredefinedCharSet(int encoding);
+const FX_CHAR* PDF_CharNameFromPredefinedCharSet(int encoding,
+                                                 uint8_t charcode);
+
+class CPDF_Object;
+
+class CPDF_FontEncoding {
+ public:
+  CPDF_FontEncoding();
+  explicit CPDF_FontEncoding(int PredefinedEncoding);
+
+  void LoadEncoding(CPDF_Object* pEncoding);
+
+  FX_BOOL IsIdentical(CPDF_FontEncoding* pAnother) const;
+
+  FX_WCHAR UnicodeFromCharCode(uint8_t charcode) const {
+    return m_Unicodes[charcode];
+  }
+  int CharCodeFromUnicode(FX_WCHAR unicode) const;
+
+  void SetUnicode(uint8_t charcode, FX_WCHAR unicode) {
+    m_Unicodes[charcode] = unicode;
+  }
+
+  CPDF_Object* Realize();
+
+ public:
+  FX_WCHAR m_Unicodes[256];
+};
+
+#endif  // CORE_FPDFAPI_FPDF_FONT_INCLUDE_CPDF_FONTENCODING_H_
diff --git a/core/fpdfapi/fpdf_page/cpdf_allstates.cpp b/core/fpdfapi/fpdf_page/cpdf_allstates.cpp
index 96ccc77..5d02381 100644
--- a/core/fpdfapi/fpdf_page/cpdf_allstates.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_allstates.cpp
@@ -8,6 +8,7 @@
 
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 
 namespace {
 
diff --git a/core/fpdfapi/fpdf_page/cpdf_color.cpp b/core/fpdfapi/fpdf_page/cpdf_color.cpp
new file mode 100644
index 0000000..d174660
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_color.cpp
@@ -0,0 +1,180 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_page/include/cpdf_color.h"
+
+#include "core/fpdfapi/fpdf_page/pageint.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fxcrt/include/fx_system.h"
+
+CPDF_Color::CPDF_Color(int family) {
+  m_pCS = CPDF_ColorSpace::GetStockCS(family);
+  int nComps = 3;
+  if (family == PDFCS_DEVICEGRAY)
+    nComps = 1;
+  else if (family == PDFCS_DEVICECMYK)
+    nComps = 4;
+
+  m_pBuffer = FX_Alloc(FX_FLOAT, nComps);
+  for (int i = 0; i < nComps; i++)
+    m_pBuffer[i] = 0;
+}
+
+CPDF_Color::~CPDF_Color() {
+  ReleaseBuffer();
+  ReleaseColorSpace();
+}
+
+void CPDF_Color::ReleaseBuffer() {
+  if (!m_pBuffer)
+    return;
+
+  if (m_pCS->GetFamily() == PDFCS_PATTERN) {
+    PatternValue* pvalue = (PatternValue*)m_pBuffer;
+    CPDF_Pattern* pPattern =
+        pvalue->m_pCountedPattern ? pvalue->m_pCountedPattern->get() : nullptr;
+    if (pPattern && pPattern->m_pDocument) {
+      CPDF_DocPageData* pPageData = pPattern->m_pDocument->GetPageData();
+      if (pPageData)
+        pPageData->ReleasePattern(pPattern->m_pPatternObj);
+    }
+  }
+  FX_Free(m_pBuffer);
+  m_pBuffer = nullptr;
+}
+
+void CPDF_Color::ReleaseColorSpace() {
+  if (m_pCS && m_pCS->m_pDocument && m_pCS->GetArray()) {
+    m_pCS->m_pDocument->GetPageData()->ReleaseColorSpace(m_pCS->GetArray());
+    m_pCS = nullptr;
+  }
+}
+
+void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS) {
+  if (m_pCS == pCS) {
+    if (!m_pBuffer)
+      m_pBuffer = pCS->CreateBuf();
+
+    ReleaseColorSpace();
+    m_pCS = pCS;
+    return;
+  }
+  ReleaseBuffer();
+  ReleaseColorSpace();
+
+  m_pCS = pCS;
+  if (m_pCS) {
+    m_pBuffer = pCS->CreateBuf();
+    pCS->GetDefaultColor(m_pBuffer);
+  }
+}
+
+void CPDF_Color::SetValue(FX_FLOAT* comps) {
+  if (!m_pBuffer)
+    return;
+  if (m_pCS->GetFamily() != PDFCS_PATTERN)
+    FXSYS_memcpy(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(FX_FLOAT));
+}
+
+void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps) {
+  if (ncomps > MAX_PATTERN_COLORCOMPS)
+    return;
+
+  if (!m_pCS || m_pCS->GetFamily() != PDFCS_PATTERN) {
+    FX_Free(m_pBuffer);
+    m_pCS = CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
+    m_pBuffer = m_pCS->CreateBuf();
+  }
+
+  CPDF_DocPageData* pDocPageData = nullptr;
+  PatternValue* pvalue = (PatternValue*)m_pBuffer;
+  if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
+    pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData();
+    if (pDocPageData)
+      pDocPageData->ReleasePattern(pvalue->m_pPattern->m_pPatternObj);
+  }
+  pvalue->m_nComps = ncomps;
+  pvalue->m_pPattern = pPattern;
+  if (ncomps)
+    FXSYS_memcpy(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT));
+
+  pvalue->m_pCountedPattern = nullptr;
+  if (pPattern && pPattern->m_pDocument) {
+    if (!pDocPageData)
+      pDocPageData = pPattern->m_pDocument->GetPageData();
+
+    pvalue->m_pCountedPattern =
+        pDocPageData->FindPatternPtr(pPattern->m_pPatternObj);
+  }
+}
+
+void CPDF_Color::Copy(const CPDF_Color* pSrc) {
+  ReleaseBuffer();
+  ReleaseColorSpace();
+
+  m_pCS = pSrc->m_pCS;
+  if (m_pCS && m_pCS->m_pDocument) {
+    CPDF_Array* pArray = m_pCS->GetArray();
+    if (pArray)
+      m_pCS = m_pCS->m_pDocument->GetPageData()->GetCopiedColorSpace(pArray);
+  }
+  if (!m_pCS)
+    return;
+
+  m_pBuffer = m_pCS->CreateBuf();
+  FXSYS_memcpy(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize());
+  if (m_pCS->GetFamily() == PDFCS_PATTERN) {
+    PatternValue* pvalue = (PatternValue*)m_pBuffer;
+    if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
+      pvalue->m_pPattern =
+          pvalue->m_pPattern->m_pDocument->GetPageData()->GetPattern(
+              pvalue->m_pPattern->m_pPatternObj, FALSE,
+              &pvalue->m_pPattern->m_ParentMatrix);
+    }
+  }
+}
+
+FX_BOOL CPDF_Color::GetRGB(int& R, int& G, int& B) const {
+  if (!m_pCS || !m_pBuffer)
+    return FALSE;
+
+  FX_FLOAT r = 0.0f, g = 0.0f, b = 0.0f;
+  if (!m_pCS->GetRGB(m_pBuffer, r, g, b))
+    return FALSE;
+
+  R = (int32_t)(r * 255 + 0.5f);
+  G = (int32_t)(g * 255 + 0.5f);
+  B = (int32_t)(b * 255 + 0.5f);
+  return TRUE;
+}
+
+CPDF_Pattern* CPDF_Color::GetPattern() const {
+  if (!m_pBuffer || m_pCS->GetFamily() != PDFCS_PATTERN)
+    return nullptr;
+
+  PatternValue* pvalue = (PatternValue*)m_pBuffer;
+  return pvalue->m_pPattern;
+}
+
+CPDF_ColorSpace* CPDF_Color::GetPatternCS() const {
+  if (!m_pBuffer || m_pCS->GetFamily() != PDFCS_PATTERN)
+    return nullptr;
+  return m_pCS->GetBaseCS();
+}
+
+FX_FLOAT* CPDF_Color::GetPatternColor() const {
+  if (!m_pBuffer || m_pCS->GetFamily() != PDFCS_PATTERN)
+    return nullptr;
+
+  PatternValue* pvalue = (PatternValue*)m_pBuffer;
+  return pvalue->m_nComps ? pvalue->m_Comps : nullptr;
+}
+
+FX_BOOL CPDF_Color::IsEqual(const CPDF_Color& other) const {
+  return m_pCS && m_pCS == other.m_pCS &&
+         FXSYS_memcmp(m_pBuffer, other.m_pBuffer, m_pCS->GetBufSize()) == 0;
+}
diff --git a/core/fpdfapi/fpdf_page/cpdf_colorspace.cpp b/core/fpdfapi/fpdf_page/cpdf_colorspace.cpp
new file mode 100644
index 0000000..b1b4644
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_colorspace.cpp
@@ -0,0 +1,1253 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_page/include/cpdf_colorspace.h"
+
+#include "core/fpdfapi/fpdf_page/pageint.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_object.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
+#include "core/fpdfapi/include/cpdf_modulemgr.h"
+#include "core/include/fxcodec/fx_codec.h"
+
+namespace {
+
+const uint8_t g_sRGBSamples1[] = {
+    0,   3,   6,   10,  13,  15,  18,  20,  22,  23,  25,  27,  28,  30,  31,
+    32,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
+    48,  49,  49,  50,  51,  52,  53,  53,  54,  55,  56,  56,  57,  58,  58,
+    59,  60,  61,  61,  62,  62,  63,  64,  64,  65,  66,  66,  67,  67,  68,
+    68,  69,  70,  70,  71,  71,  72,  72,  73,  73,  74,  74,  75,  76,  76,
+    77,  77,  78,  78,  79,  79,  79,  80,  80,  81,  81,  82,  82,  83,  83,
+    84,  84,  85,  85,  85,  86,  86,  87,  87,  88,  88,  88,  89,  89,  90,
+    90,  91,  91,  91,  92,  92,  93,  93,  93,  94,  94,  95,  95,  95,  96,
+    96,  97,  97,  97,  98,  98,  98,  99,  99,  99,  100, 100, 101, 101, 101,
+    102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 106, 106, 106, 107,
+    107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 110, 111, 111, 111,
+    112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 116, 116,
+    116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120,
+};
+
+const uint8_t g_sRGBSamples2[] = {
+    120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+    136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149,
+    150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162,
+    163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173,
+    174, 175, 175, 176, 177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184,
+    185, 185, 186, 187, 187, 188, 189, 189, 190, 190, 191, 192, 192, 193, 194,
+    194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202, 203,
+    203, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212,
+    212, 213, 213, 214, 214, 215, 215, 216, 216, 217, 218, 218, 219, 219, 220,
+    220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228,
+    228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235,
+    236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242,
+    243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, 248, 249, 249,
+    250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255,
+};
+
+class CPDF_CalGray : public CPDF_ColorSpace {
+ public:
+  explicit CPDF_CalGray(CPDF_Document* pDoc);
+
+  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
+
+  FX_BOOL GetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT& R,
+                 FX_FLOAT& G,
+                 FX_FLOAT& B) const override;
+  FX_BOOL SetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT R,
+                 FX_FLOAT G,
+                 FX_FLOAT B) const override;
+
+  void TranslateImageLine(uint8_t* pDestBuf,
+                          const uint8_t* pSrcBuf,
+                          int pixels,
+                          int image_width,
+                          int image_height,
+                          FX_BOOL bTransMask = FALSE) const override;
+
+ private:
+  FX_FLOAT m_WhitePoint[3];
+  FX_FLOAT m_BlackPoint[3];
+  FX_FLOAT m_Gamma;
+};
+
+class CPDF_CalRGB : public CPDF_ColorSpace {
+ public:
+  explicit CPDF_CalRGB(CPDF_Document* pDoc);
+
+  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
+
+  FX_BOOL GetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT& R,
+                 FX_FLOAT& G,
+                 FX_FLOAT& B) const override;
+  FX_BOOL SetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT R,
+                 FX_FLOAT G,
+                 FX_FLOAT B) const override;
+
+  void TranslateImageLine(uint8_t* pDestBuf,
+                          const uint8_t* pSrcBuf,
+                          int pixels,
+                          int image_width,
+                          int image_height,
+                          FX_BOOL bTransMask = FALSE) const override;
+
+  FX_FLOAT m_WhitePoint[3];
+  FX_FLOAT m_BlackPoint[3];
+  FX_FLOAT m_Gamma[3];
+  FX_FLOAT m_Matrix[9];
+  FX_BOOL m_bGamma;
+  FX_BOOL m_bMatrix;
+};
+
+class CPDF_LabCS : public CPDF_ColorSpace {
+ public:
+  explicit CPDF_LabCS(CPDF_Document* pDoc);
+
+  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
+
+  void GetDefaultValue(int iComponent,
+                       FX_FLOAT& value,
+                       FX_FLOAT& min,
+                       FX_FLOAT& max) const override;
+  FX_BOOL GetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT& R,
+                 FX_FLOAT& G,
+                 FX_FLOAT& B) const override;
+  FX_BOOL SetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT R,
+                 FX_FLOAT G,
+                 FX_FLOAT B) const override;
+
+  void TranslateImageLine(uint8_t* pDestBuf,
+                          const uint8_t* pSrcBuf,
+                          int pixels,
+                          int image_width,
+                          int image_height,
+                          FX_BOOL bTransMask = FALSE) const override;
+
+  FX_FLOAT m_WhitePoint[3];
+  FX_FLOAT m_BlackPoint[3];
+  FX_FLOAT m_Ranges[4];
+};
+
+class CPDF_ICCBasedCS : public CPDF_ColorSpace {
+ public:
+  explicit CPDF_ICCBasedCS(CPDF_Document* pDoc);
+  ~CPDF_ICCBasedCS() override;
+
+  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
+
+  FX_BOOL GetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT& R,
+                 FX_FLOAT& G,
+                 FX_FLOAT& B) const override;
+  FX_BOOL SetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT R,
+                 FX_FLOAT G,
+                 FX_FLOAT B) const override;
+
+  FX_BOOL v_GetCMYK(FX_FLOAT* pBuf,
+                    FX_FLOAT& c,
+                    FX_FLOAT& m,
+                    FX_FLOAT& y,
+                    FX_FLOAT& k) const override;
+
+  void EnableStdConversion(FX_BOOL bEnabled) override;
+  void TranslateImageLine(uint8_t* pDestBuf,
+                          const uint8_t* pSrcBuf,
+                          int pixels,
+                          int image_width,
+                          int image_height,
+                          FX_BOOL bTransMask = FALSE) const override;
+
+  CPDF_ColorSpace* m_pAlterCS;
+  CPDF_IccProfile* m_pProfile;
+  uint8_t* m_pCache;
+  FX_FLOAT* m_pRanges;
+  FX_BOOL m_bOwn;
+};
+
+class CPDF_IndexedCS : public CPDF_ColorSpace {
+ public:
+  explicit CPDF_IndexedCS(CPDF_Document* pDoc);
+  ~CPDF_IndexedCS() override;
+
+  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
+
+  FX_BOOL GetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT& R,
+                 FX_FLOAT& G,
+                 FX_FLOAT& B) const override;
+  CPDF_ColorSpace* GetBaseCS() const override;
+
+  void EnableStdConversion(FX_BOOL bEnabled) override;
+
+  CPDF_ColorSpace* m_pBaseCS;
+  CPDF_CountedColorSpace* m_pCountedBaseCS;
+  int m_nBaseComponents;
+  int m_MaxIndex;
+  CFX_ByteString m_Table;
+  FX_FLOAT* m_pCompMinMax;
+};
+
+class CPDF_SeparationCS : public CPDF_ColorSpace {
+ public:
+  explicit CPDF_SeparationCS(CPDF_Document* pDoc);
+  ~CPDF_SeparationCS() override;
+
+  // CPDF_ColorSpace:
+  void GetDefaultValue(int iComponent,
+                       FX_FLOAT& value,
+                       FX_FLOAT& min,
+                       FX_FLOAT& max) const override;
+  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
+  FX_BOOL GetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT& R,
+                 FX_FLOAT& G,
+                 FX_FLOAT& B) const override;
+  void EnableStdConversion(FX_BOOL bEnabled) override;
+
+  CPDF_ColorSpace* m_pAltCS;
+  CPDF_Function* m_pFunc;
+  enum { None, All, Colorant } m_Type;
+};
+
+class CPDF_DeviceNCS : public CPDF_ColorSpace {
+ public:
+  explicit CPDF_DeviceNCS(CPDF_Document* pDoc);
+  ~CPDF_DeviceNCS() override;
+
+  // CPDF_ColorSpace:
+  void GetDefaultValue(int iComponent,
+                       FX_FLOAT& value,
+                       FX_FLOAT& min,
+                       FX_FLOAT& max) const override;
+  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
+  FX_BOOL GetRGB(FX_FLOAT* pBuf,
+                 FX_FLOAT& R,
+                 FX_FLOAT& G,
+                 FX_FLOAT& B) const override;
+  void EnableStdConversion(FX_BOOL bEnabled) override;
+
+  CPDF_ColorSpace* m_pAltCS;
+  CPDF_Function* m_pFunc;
+};
+
+FX_FLOAT RGB_Conversion(FX_FLOAT colorComponent) {
+  if (colorComponent > 1)
+    colorComponent = 1;
+  if (colorComponent < 0)
+    colorComponent = 0;
+
+  int scale = (int)(colorComponent * 1023);
+  if (scale < 0)
+    scale = 0;
+  if (scale < 192)
+    colorComponent = (g_sRGBSamples1[scale] / 255.0f);
+  else
+    colorComponent = (g_sRGBSamples2[scale / 4 - 48] / 255.0f);
+  return colorComponent;
+}
+
+void XYZ_to_sRGB(FX_FLOAT X,
+                 FX_FLOAT Y,
+                 FX_FLOAT Z,
+                 FX_FLOAT& R,
+                 FX_FLOAT& G,
+                 FX_FLOAT& B) {
+  FX_FLOAT R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z;
+  FX_FLOAT G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z;
+  FX_FLOAT B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z;
+
+  R = RGB_Conversion(R1);
+  G = RGB_Conversion(G1);
+  B = RGB_Conversion(B1);
+}
+
+void XYZ_to_sRGB_WhitePoint(FX_FLOAT X,
+                            FX_FLOAT Y,
+                            FX_FLOAT Z,
+                            FX_FLOAT& R,
+                            FX_FLOAT& G,
+                            FX_FLOAT& B,
+                            FX_FLOAT Xw,
+                            FX_FLOAT Yw,
+                            FX_FLOAT Zw) {
+  // The following RGB_xyz is based on
+  // sRGB value {Rx,Ry}={0.64, 0.33}, {Gx,Gy}={0.30, 0.60}, {Bx,By}={0.15, 0.06}
+
+  FX_FLOAT Rx = 0.64f, Ry = 0.33f;
+  FX_FLOAT Gx = 0.30f, Gy = 0.60f;
+  FX_FLOAT Bx = 0.15f, By = 0.06f;
+  CFX_Matrix_3by3 RGB_xyz(Rx, Gx, Bx, Ry, Gy, By, 1 - Rx - Ry, 1 - Gx - Gy,
+                          1 - Bx - By);
+  CFX_Vector_3by1 whitePoint(Xw, Yw, Zw);
+  CFX_Vector_3by1 XYZ(X, Y, Z);
+
+  CFX_Vector_3by1 RGB_Sum_XYZ = RGB_xyz.Inverse().TransformVector(whitePoint);
+  CFX_Matrix_3by3 RGB_SUM_XYZ_DIAG(RGB_Sum_XYZ.a, 0, 0, 0, RGB_Sum_XYZ.b, 0, 0,
+                                   0, RGB_Sum_XYZ.c);
+  CFX_Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG);
+  CFX_Vector_3by1 RGB = M.Inverse().TransformVector(XYZ);
+
+  R = RGB_Conversion(RGB.a);
+  G = RGB_Conversion(RGB.b);
+  B = RGB_Conversion(RGB.c);
+}
+
+}  // namespace
+
+CPDF_ColorSpace* CPDF_ColorSpace::ColorspaceFromName(
+    const CFX_ByteString& name) {
+  if (name == "DeviceRGB" || name == "RGB") {
+    return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
+  }
+  if (name == "DeviceGray" || name == "G") {
+    return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
+  }
+  if (name == "DeviceCMYK" || name == "CMYK") {
+    return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
+  }
+  if (name == "Pattern") {
+    return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
+  }
+  return NULL;
+}
+
+CPDF_ColorSpace* CPDF_ColorSpace::GetStockCS(int family) {
+  return CPDF_ModuleMgr::Get()->GetPageModule()->GetStockCS(family);
+}
+
+CPDF_ColorSpace* CPDF_ColorSpace::Load(CPDF_Document* pDoc, CPDF_Object* pObj) {
+  if (!pObj)
+    return nullptr;
+  if (pObj->IsName())
+    return ColorspaceFromName(pObj->GetString());
+
+  if (CPDF_Stream* pStream = pObj->AsStream()) {
+    CPDF_Dictionary* pDict = pStream->GetDict();
+    if (!pDict)
+      return nullptr;
+
+    for (const auto& it : *pDict) {
+      CPDF_ColorSpace* pRet = nullptr;
+      CPDF_Object* pValue = it.second;
+      if (ToName(pValue))
+        pRet = ColorspaceFromName(pValue->GetString());
+      if (pRet)
+        return pRet;
+    }
+    return nullptr;
+  }
+
+  CPDF_Array* pArray = pObj->AsArray();
+  if (!pArray || pArray->GetCount() == 0)
+    return nullptr;
+
+  CPDF_Object* pFamilyObj = pArray->GetElementValue(0);
+  if (!pFamilyObj)
+    return nullptr;
+
+  CFX_ByteString familyname = pFamilyObj->GetString();
+  if (pArray->GetCount() == 1)
+    return ColorspaceFromName(familyname);
+
+  CPDF_ColorSpace* pCS = NULL;
+  FX_DWORD id = familyname.GetID();
+  if (id == FXBSTR_ID('C', 'a', 'l', 'G')) {
+    pCS = new CPDF_CalGray(pDoc);
+  } else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) {
+    pCS = new CPDF_CalRGB(pDoc);
+  } else if (id == FXBSTR_ID('L', 'a', 'b', 0)) {
+    pCS = new CPDF_LabCS(pDoc);
+  } else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) {
+    pCS = new CPDF_ICCBasedCS(pDoc);
+  } else if (id == FXBSTR_ID('I', 'n', 'd', 'e') ||
+             id == FXBSTR_ID('I', 0, 0, 0)) {
+    pCS = new CPDF_IndexedCS(pDoc);
+  } else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) {
+    pCS = new CPDF_SeparationCS(pDoc);
+  } else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) {
+    pCS = new CPDF_DeviceNCS(pDoc);
+  } else if (id == FXBSTR_ID('P', 'a', 't', 't')) {
+    pCS = new CPDF_PatternCS(pDoc);
+  } else {
+    return NULL;
+  }
+  pCS->m_pArray = pArray;
+  if (!pCS->v_Load(pDoc, pArray)) {
+    pCS->ReleaseCS();
+    return NULL;
+  }
+  return pCS;
+}
+
+void CPDF_ColorSpace::ReleaseCS() {
+  if (this == GetStockCS(PDFCS_DEVICERGB)) {
+    return;
+  }
+  if (this == GetStockCS(PDFCS_DEVICEGRAY)) {
+    return;
+  }
+  if (this == GetStockCS(PDFCS_DEVICECMYK)) {
+    return;
+  }
+  if (this == GetStockCS(PDFCS_PATTERN)) {
+    return;
+  }
+  delete this;
+}
+
+int CPDF_ColorSpace::GetBufSize() const {
+  if (m_Family == PDFCS_PATTERN) {
+    return sizeof(PatternValue);
+  }
+  return m_nComponents * sizeof(FX_FLOAT);
+}
+
+FX_FLOAT* CPDF_ColorSpace::CreateBuf() {
+  int size = GetBufSize();
+  uint8_t* pBuf = FX_Alloc(uint8_t, size);
+  return (FX_FLOAT*)pBuf;
+}
+
+FX_BOOL CPDF_ColorSpace::sRGB() const {
+  if (m_Family == PDFCS_DEVICERGB) {
+    return TRUE;
+  }
+  if (m_Family != PDFCS_ICCBASED) {
+    return FALSE;
+  }
+  CPDF_ICCBasedCS* pCS = (CPDF_ICCBasedCS*)this;
+  return pCS->m_pProfile->m_bsRGB;
+}
+
+FX_BOOL CPDF_ColorSpace::GetCMYK(FX_FLOAT* pBuf,
+                                 FX_FLOAT& c,
+                                 FX_FLOAT& m,
+                                 FX_FLOAT& y,
+                                 FX_FLOAT& k) const {
+  if (v_GetCMYK(pBuf, c, m, y, k)) {
+    return TRUE;
+  }
+  FX_FLOAT R, G, B;
+  if (!GetRGB(pBuf, R, G, B)) {
+    return FALSE;
+  }
+  sRGB_to_AdobeCMYK(R, G, B, c, m, y, k);
+  return TRUE;
+}
+
+FX_BOOL CPDF_ColorSpace::SetCMYK(FX_FLOAT* pBuf,
+                                 FX_FLOAT c,
+                                 FX_FLOAT m,
+                                 FX_FLOAT y,
+                                 FX_FLOAT k) const {
+  if (v_SetCMYK(pBuf, c, m, y, k)) {
+    return TRUE;
+  }
+  FX_FLOAT R, G, B;
+  AdobeCMYK_to_sRGB(c, m, y, k, R, G, B);
+  return SetRGB(pBuf, R, G, B);
+}
+
+void CPDF_ColorSpace::GetDefaultColor(FX_FLOAT* buf) const {
+  if (!buf || m_Family == PDFCS_PATTERN) {
+    return;
+  }
+  FX_FLOAT min, max;
+  for (int i = 0; i < m_nComponents; i++) {
+    GetDefaultValue(i, buf[i], min, max);
+  }
+}
+
+int CPDF_ColorSpace::GetMaxIndex() const {
+  if (m_Family != PDFCS_INDEXED) {
+    return 0;
+  }
+  CPDF_IndexedCS* pCS = (CPDF_IndexedCS*)this;
+  return pCS->m_MaxIndex;
+}
+
+void CPDF_ColorSpace::TranslateImageLine(uint8_t* dest_buf,
+                                         const uint8_t* src_buf,
+                                         int pixels,
+                                         int image_width,
+                                         int image_height,
+                                         FX_BOOL bTransMask) const {
+  CFX_FixedBufGrow<FX_FLOAT, 16> srcbuf(m_nComponents);
+  FX_FLOAT* src = srcbuf;
+  FX_FLOAT R, G, B;
+  for (int i = 0; i < pixels; i++) {
+    for (int j = 0; j < m_nComponents; j++)
+      if (m_Family == PDFCS_INDEXED) {
+        src[j] = (FX_FLOAT)(*src_buf++);
+      } else {
+        src[j] = (FX_FLOAT)(*src_buf++) / 255;
+      }
+    GetRGB(src, R, G, B);
+    *dest_buf++ = (int32_t)(B * 255);
+    *dest_buf++ = (int32_t)(G * 255);
+    *dest_buf++ = (int32_t)(R * 255);
+  }
+}
+
+void CPDF_ColorSpace::EnableStdConversion(FX_BOOL bEnabled) {
+  if (bEnabled)
+    m_dwStdConversion++;
+  else if (m_dwStdConversion)
+    m_dwStdConversion--;
+}
+
+CPDF_CalGray::CPDF_CalGray(CPDF_Document* pDoc)
+    : CPDF_ColorSpace(pDoc, PDFCS_CALGRAY, 1) {}
+
+FX_BOOL CPDF_CalGray::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+  CPDF_Dictionary* pDict = pArray->GetDictAt(1);
+  if (!pDict)
+    return FALSE;
+
+  CPDF_Array* pParam = pDict->GetArrayBy("WhitePoint");
+  int i;
+  for (i = 0; i < 3; i++)
+    m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
+
+  pParam = pDict->GetArrayBy("BlackPoint");
+  for (i = 0; i < 3; i++)
+    m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
+
+  m_Gamma = pDict->GetNumberBy("Gamma");
+  if (m_Gamma == 0)
+    m_Gamma = 1.0f;
+  return TRUE;
+}
+
+FX_BOOL CPDF_CalGray::GetRGB(FX_FLOAT* pBuf,
+                             FX_FLOAT& R,
+                             FX_FLOAT& G,
+                             FX_FLOAT& B) const {
+  R = G = B = *pBuf;
+  return TRUE;
+}
+
+FX_BOOL CPDF_CalGray::SetRGB(FX_FLOAT* pBuf,
+                             FX_FLOAT R,
+                             FX_FLOAT G,
+                             FX_FLOAT B) const {
+  if (R == G && R == B) {
+    *pBuf = R;
+    return TRUE;
+  }
+  return FALSE;
+}
+
+void CPDF_CalGray::TranslateImageLine(uint8_t* pDestBuf,
+                                      const uint8_t* pSrcBuf,
+                                      int pixels,
+                                      int image_width,
+                                      int image_height,
+                                      FX_BOOL bTransMask) const {
+  for (int i = 0; i < pixels; i++) {
+    *pDestBuf++ = pSrcBuf[i];
+    *pDestBuf++ = pSrcBuf[i];
+    *pDestBuf++ = pSrcBuf[i];
+  }
+}
+
+CPDF_CalRGB::CPDF_CalRGB(CPDF_Document* pDoc)
+    : CPDF_ColorSpace(pDoc, PDFCS_CALRGB, 3) {}
+
+FX_BOOL CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+  CPDF_Dictionary* pDict = pArray->GetDictAt(1);
+  if (!pDict)
+    return FALSE;
+
+  CPDF_Array* pParam = pDict->GetArrayBy("WhitePoint");
+  int i;
+  for (i = 0; i < 3; i++)
+    m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
+
+  pParam = pDict->GetArrayBy("BlackPoint");
+  for (i = 0; i < 3; i++)
+    m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
+
+  pParam = pDict->GetArrayBy("Gamma");
+  if (pParam) {
+    m_bGamma = TRUE;
+    for (i = 0; i < 3; i++)
+      m_Gamma[i] = pParam->GetNumberAt(i);
+  } else {
+    m_bGamma = FALSE;
+  }
+
+  pParam = pDict->GetArrayBy("Matrix");
+  if (pParam) {
+    m_bMatrix = TRUE;
+    for (i = 0; i < 9; i++)
+      m_Matrix[i] = pParam->GetNumberAt(i);
+  } else {
+    m_bMatrix = FALSE;
+  }
+  return TRUE;
+}
+
+FX_BOOL CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf,
+                            FX_FLOAT& R,
+                            FX_FLOAT& G,
+                            FX_FLOAT& B) const {
+  FX_FLOAT A_ = pBuf[0];
+  FX_FLOAT B_ = pBuf[1];
+  FX_FLOAT C_ = pBuf[2];
+  if (m_bGamma) {
+    A_ = (FX_FLOAT)FXSYS_pow(A_, m_Gamma[0]);
+    B_ = (FX_FLOAT)FXSYS_pow(B_, m_Gamma[1]);
+    C_ = (FX_FLOAT)FXSYS_pow(C_, m_Gamma[2]);
+  }
+
+  FX_FLOAT X;
+  FX_FLOAT Y;
+  FX_FLOAT Z;
+  if (m_bMatrix) {
+    X = m_Matrix[0] * A_ + m_Matrix[3] * B_ + m_Matrix[6] * C_;
+    Y = m_Matrix[1] * A_ + m_Matrix[4] * B_ + m_Matrix[7] * C_;
+    Z = m_Matrix[2] * A_ + m_Matrix[5] * B_ + m_Matrix[8] * C_;
+  } else {
+    X = A_;
+    Y = B_;
+    Z = C_;
+  }
+  XYZ_to_sRGB_WhitePoint(X, Y, Z, R, G, B, m_WhitePoint[0], m_WhitePoint[1],
+                         m_WhitePoint[2]);
+  return TRUE;
+}
+
+FX_BOOL CPDF_CalRGB::SetRGB(FX_FLOAT* pBuf,
+                            FX_FLOAT R,
+                            FX_FLOAT G,
+                            FX_FLOAT B) const {
+  pBuf[0] = R;
+  pBuf[1] = G;
+  pBuf[2] = B;
+  return TRUE;
+}
+
+void CPDF_CalRGB::TranslateImageLine(uint8_t* pDestBuf,
+                                     const uint8_t* pSrcBuf,
+                                     int pixels,
+                                     int image_width,
+                                     int image_height,
+                                     FX_BOOL bTransMask) const {
+  if (bTransMask) {
+    FX_FLOAT Cal[3];
+    FX_FLOAT R;
+    FX_FLOAT G;
+    FX_FLOAT B;
+    for (int i = 0; i < pixels; i++) {
+      Cal[0] = ((FX_FLOAT)pSrcBuf[2]) / 255;
+      Cal[1] = ((FX_FLOAT)pSrcBuf[1]) / 255;
+      Cal[2] = ((FX_FLOAT)pSrcBuf[0]) / 255;
+      GetRGB(Cal, R, G, B);
+      pDestBuf[0] = FXSYS_round(B * 255);
+      pDestBuf[1] = FXSYS_round(G * 255);
+      pDestBuf[2] = FXSYS_round(R * 255);
+      pSrcBuf += 3;
+      pDestBuf += 3;
+    }
+  }
+  ReverseRGB(pDestBuf, pSrcBuf, pixels);
+}
+
+CPDF_LabCS::CPDF_LabCS(CPDF_Document* pDoc)
+    : CPDF_ColorSpace(pDoc, PDFCS_LAB, 3) {}
+
+void CPDF_LabCS::GetDefaultValue(int iComponent,
+                                 FX_FLOAT& value,
+                                 FX_FLOAT& min,
+                                 FX_FLOAT& max) const {
+  assert(iComponent < 3);
+  value = 0;
+  if (iComponent == 0) {
+    min = 0;
+    max = 100 * 1.0f;
+  } else {
+    min = m_Ranges[iComponent * 2 - 2];
+    max = m_Ranges[iComponent * 2 - 1];
+    if (value < min)
+      value = min;
+    else if (value > max)
+      value = max;
+  }
+}
+
+FX_BOOL CPDF_LabCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+  CPDF_Dictionary* pDict = pArray->GetDictAt(1);
+  if (!pDict)
+    return FALSE;
+
+  CPDF_Array* pParam = pDict->GetArrayBy("WhitePoint");
+  int i;
+  for (i = 0; i < 3; i++)
+    m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
+
+  pParam = pDict->GetArrayBy("BlackPoint");
+  for (i = 0; i < 3; i++)
+    m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
+
+  pParam = pDict->GetArrayBy("Range");
+  const FX_FLOAT def_ranges[4] = {-100 * 1.0f, 100 * 1.0f, -100 * 1.0f,
+                                  100 * 1.0f};
+  for (i = 0; i < 4; i++)
+    m_Ranges[i] = pParam ? pParam->GetNumberAt(i) : def_ranges[i];
+  return TRUE;
+}
+
+FX_BOOL CPDF_LabCS::GetRGB(FX_FLOAT* pBuf,
+                           FX_FLOAT& R,
+                           FX_FLOAT& G,
+                           FX_FLOAT& B) const {
+  FX_FLOAT Lstar = pBuf[0];
+  FX_FLOAT astar = pBuf[1];
+  FX_FLOAT bstar = pBuf[2];
+  FX_FLOAT M = (Lstar + 16.0f) / 116.0f;
+  FX_FLOAT L = M + astar / 500.0f;
+  FX_FLOAT N = M - bstar / 200.0f;
+  FX_FLOAT X, Y, Z;
+  if (L < 0.2069f)
+    X = 0.957f * 0.12842f * (L - 0.1379f);
+  else
+    X = 0.957f * L * L * L;
+
+  if (M < 0.2069f)
+    Y = 0.12842f * (M - 0.1379f);
+  else
+    Y = M * M * M;
+
+  if (N < 0.2069f)
+    Z = 1.0889f * 0.12842f * (N - 0.1379f);
+  else
+    Z = 1.0889f * N * N * N;
+
+  XYZ_to_sRGB(X, Y, Z, R, G, B);
+  return TRUE;
+}
+
+FX_BOOL CPDF_LabCS::SetRGB(FX_FLOAT* pBuf,
+                           FX_FLOAT R,
+                           FX_FLOAT G,
+                           FX_FLOAT B) const {
+  return FALSE;
+}
+
+void CPDF_LabCS::TranslateImageLine(uint8_t* pDestBuf,
+                                    const uint8_t* pSrcBuf,
+                                    int pixels,
+                                    int image_width,
+                                    int image_height,
+                                    FX_BOOL bTransMask) const {
+  for (int i = 0; i < pixels; i++) {
+    FX_FLOAT lab[3];
+    FX_FLOAT R, G, B;
+    lab[0] = (pSrcBuf[0] * 100 / 255.0f);
+    lab[1] = (FX_FLOAT)(pSrcBuf[1] - 128);
+    lab[2] = (FX_FLOAT)(pSrcBuf[2] - 128);
+    GetRGB(lab, R, G, B);
+    pDestBuf[0] = (int32_t)(B * 255);
+    pDestBuf[1] = (int32_t)(G * 255);
+    pDestBuf[2] = (int32_t)(R * 255);
+    pDestBuf += 3;
+    pSrcBuf += 3;
+  }
+}
+
+CPDF_ICCBasedCS::CPDF_ICCBasedCS(CPDF_Document* pDoc)
+    : CPDF_ColorSpace(pDoc, PDFCS_ICCBASED, 0),
+      m_pAlterCS(nullptr),
+      m_pProfile(nullptr),
+      m_pCache(nullptr),
+      m_pRanges(nullptr),
+      m_bOwn(FALSE) {}
+
+CPDF_ICCBasedCS::~CPDF_ICCBasedCS() {
+  FX_Free(m_pCache);
+  FX_Free(m_pRanges);
+  if (m_pAlterCS && m_bOwn)
+    m_pAlterCS->ReleaseCS();
+  if (m_pProfile && m_pDocument)
+    m_pDocument->GetPageData()->ReleaseIccProfile(m_pProfile);
+}
+
+FX_BOOL CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+  CPDF_Stream* pStream = pArray->GetStreamAt(1);
+  if (!pStream)
+    return FALSE;
+
+  m_pProfile = pDoc->LoadIccProfile(pStream);
+  if (!m_pProfile)
+    return FALSE;
+
+  m_nComponents =
+      m_pProfile
+          ->GetComponents();  // Try using the nComponents from ICC profile
+  CPDF_Dictionary* pDict = pStream->GetDict();
+  if (!m_pProfile->m_pTransform) {  // No valid ICC profile or using sRGB
+    CPDF_Object* pAlterCSObj =
+        pDict ? pDict->GetElementValue("Alternate") : nullptr;
+    if (pAlterCSObj) {
+      CPDF_ColorSpace* pAlterCS = CPDF_ColorSpace::Load(pDoc, pAlterCSObj);
+      if (pAlterCS) {
+        if (m_nComponents == 0) {                 // NO valid ICC profile
+          if (pAlterCS->CountComponents() > 0) {  // Use Alternative colorspace
+            m_nComponents = pAlterCS->CountComponents();
+            m_pAlterCS = pAlterCS;
+            m_bOwn = TRUE;
+          } else {  // No valid alternative colorspace
+            pAlterCS->ReleaseCS();
+            int32_t nDictComponents = pDict ? pDict->GetIntegerBy("N") : 0;
+            if (nDictComponents != 1 && nDictComponents != 3 &&
+                nDictComponents != 4) {
+              return FALSE;
+            }
+            m_nComponents = nDictComponents;
+          }
+
+        } else {  // Using sRGB
+          if (pAlterCS->CountComponents() != m_nComponents) {
+            pAlterCS->ReleaseCS();
+          } else {
+            m_pAlterCS = pAlterCS;
+            m_bOwn = TRUE;
+          }
+        }
+      }
+    }
+    if (!m_pAlterCS) {
+      if (m_nComponents == 1)
+        m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY);
+      else if (m_nComponents == 3)
+        m_pAlterCS = GetStockCS(PDFCS_DEVICERGB);
+      else if (m_nComponents == 4)
+        m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK);
+    }
+  }
+  CPDF_Array* pRanges = pDict->GetArrayBy("Range");
+  m_pRanges = FX_Alloc2D(FX_FLOAT, m_nComponents, 2);
+  for (int i = 0; i < m_nComponents * 2; i++) {
+    if (pRanges)
+      m_pRanges[i] = pRanges->GetNumberAt(i);
+    else if (i % 2)
+      m_pRanges[i] = 1.0f;
+    else
+      m_pRanges[i] = 0;
+  }
+  return TRUE;
+}
+
+FX_BOOL CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf,
+                                FX_FLOAT& R,
+                                FX_FLOAT& G,
+                                FX_FLOAT& B) const {
+  if (m_pProfile && m_pProfile->m_bsRGB) {
+    R = pBuf[0];
+    G = pBuf[1];
+    B = pBuf[2];
+    return TRUE;
+  }
+  ICodec_IccModule* pIccModule = CPDF_ModuleMgr::Get()->GetIccModule();
+  if (!m_pProfile->m_pTransform || !pIccModule) {
+    if (m_pAlterCS) {
+      return m_pAlterCS->GetRGB(pBuf, R, G, B);
+    }
+    R = G = B = 0.0f;
+    return TRUE;
+  }
+  FX_FLOAT rgb[3];
+  pIccModule->SetComponents(m_nComponents);
+  pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb);
+  R = rgb[0];
+  G = rgb[1];
+  B = rgb[2];
+  return TRUE;
+}
+
+FX_BOOL CPDF_ICCBasedCS::SetRGB(FX_FLOAT* pBuf,
+                                FX_FLOAT R,
+                                FX_FLOAT G,
+                                FX_FLOAT B) const {
+  return FALSE;
+}
+
+FX_BOOL CPDF_ICCBasedCS::v_GetCMYK(FX_FLOAT* pBuf,
+                                   FX_FLOAT& c,
+                                   FX_FLOAT& m,
+                                   FX_FLOAT& y,
+                                   FX_FLOAT& k) const {
+  if (m_nComponents != 4)
+    return FALSE;
+
+  c = pBuf[0];
+  m = pBuf[1];
+  y = pBuf[2];
+  k = pBuf[3];
+  return TRUE;
+}
+
+void CPDF_ICCBasedCS::EnableStdConversion(FX_BOOL bEnabled) {
+  CPDF_ColorSpace::EnableStdConversion(bEnabled);
+  if (m_pAlterCS)
+    m_pAlterCS->EnableStdConversion(bEnabled);
+}
+
+void CPDF_ICCBasedCS::TranslateImageLine(uint8_t* pDestBuf,
+                                         const uint8_t* pSrcBuf,
+                                         int pixels,
+                                         int image_width,
+                                         int image_height,
+                                         FX_BOOL bTransMask) const {
+  if (m_pProfile->m_bsRGB) {
+    ReverseRGB(pDestBuf, pSrcBuf, pixels);
+  } else if (m_pProfile->m_pTransform) {
+    int nMaxColors = 1;
+    for (int i = 0; i < m_nComponents; i++) {
+      nMaxColors *= 52;
+    }
+    if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) {
+      CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(
+          m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels);
+    } else {
+      if (!m_pCache) {
+        ((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc2D(uint8_t, nMaxColors, 3);
+        uint8_t* temp_src = FX_Alloc2D(uint8_t, nMaxColors, m_nComponents);
+        uint8_t* pSrc = temp_src;
+        for (int i = 0; i < nMaxColors; i++) {
+          FX_DWORD color = i;
+          FX_DWORD order = nMaxColors / 52;
+          for (int c = 0; c < m_nComponents; c++) {
+            *pSrc++ = (uint8_t)(color / order * 5);
+            color %= order;
+            order /= 52;
+          }
+        }
+        CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(
+            m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors);
+        FX_Free(temp_src);
+      }
+      for (int i = 0; i < pixels; i++) {
+        int index = 0;
+        for (int c = 0; c < m_nComponents; c++) {
+          index = index * 52 + (*pSrcBuf) / 5;
+          pSrcBuf++;
+        }
+        index *= 3;
+        *pDestBuf++ = m_pCache[index];
+        *pDestBuf++ = m_pCache[index + 1];
+        *pDestBuf++ = m_pCache[index + 2];
+      }
+    }
+  } else if (m_pAlterCS) {
+    m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width,
+                                   image_height);
+  }
+}
+
+CPDF_IndexedCS::CPDF_IndexedCS(CPDF_Document* pDoc)
+    : CPDF_ColorSpace(pDoc, PDFCS_INDEXED, 1),
+      m_pBaseCS(nullptr),
+      m_pCountedBaseCS(nullptr),
+      m_pCompMinMax(nullptr) {}
+
+CPDF_IndexedCS::~CPDF_IndexedCS() {
+  FX_Free(m_pCompMinMax);
+  CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : NULL;
+  if (pCS && m_pDocument) {
+    m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
+  }
+}
+
+FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+  if (pArray->GetCount() < 4) {
+    return FALSE;
+  }
+  CPDF_Object* pBaseObj = pArray->GetElementValue(1);
+  if (pBaseObj == m_pArray) {
+    return FALSE;
+  }
+  CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
+  m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, NULL);
+  if (!m_pBaseCS) {
+    return FALSE;
+  }
+  m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
+  m_nBaseComponents = m_pBaseCS->CountComponents();
+  m_pCompMinMax = FX_Alloc2D(FX_FLOAT, m_nBaseComponents, 2);
+  FX_FLOAT defvalue;
+  for (int i = 0; i < m_nBaseComponents; i++) {
+    m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2],
+                               m_pCompMinMax[i * 2 + 1]);
+    m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2];
+  }
+  m_MaxIndex = pArray->GetIntegerAt(2);
+
+  CPDF_Object* pTableObj = pArray->GetElementValue(3);
+  if (!pTableObj)
+    return FALSE;
+
+  if (CPDF_String* pString = pTableObj->AsString()) {
+    m_Table = pString->GetString();
+  } else if (CPDF_Stream* pStream = pTableObj->AsStream()) {
+    CPDF_StreamAcc acc;
+    acc.LoadAllData(pStream, FALSE);
+    m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize());
+  }
+  return TRUE;
+}
+
+FX_BOOL CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf,
+                               FX_FLOAT& R,
+                               FX_FLOAT& G,
+                               FX_FLOAT& B) const {
+  int index = (int32_t)(*pBuf);
+  if (index < 0 || index > m_MaxIndex) {
+    return FALSE;
+  }
+  if (m_nBaseComponents) {
+    if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents ||
+        (index + 1) * m_nBaseComponents > (int)m_Table.GetLength()) {
+      R = G = B = 0;
+      return FALSE;
+    }
+  }
+  CFX_FixedBufGrow<FX_FLOAT, 16> Comps(m_nBaseComponents);
+  FX_FLOAT* comps = Comps;
+  const uint8_t* pTable = m_Table;
+  for (int i = 0; i < m_nBaseComponents; i++) {
+    comps[i] =
+        m_pCompMinMax[i * 2] +
+        m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255;
+  }
+  return m_pBaseCS->GetRGB(comps, R, G, B);
+}
+
+CPDF_ColorSpace* CPDF_IndexedCS::GetBaseCS() const {
+  return m_pBaseCS;
+}
+
+void CPDF_IndexedCS::EnableStdConversion(FX_BOOL bEnabled) {
+  CPDF_ColorSpace::EnableStdConversion(bEnabled);
+  if (m_pBaseCS) {
+    m_pBaseCS->EnableStdConversion(bEnabled);
+  }
+}
+
+CPDF_PatternCS::CPDF_PatternCS(CPDF_Document* pDoc)
+    : CPDF_ColorSpace(pDoc, PDFCS_PATTERN, 1),
+      m_pBaseCS(nullptr),
+      m_pCountedBaseCS(nullptr) {}
+
+CPDF_PatternCS::~CPDF_PatternCS() {
+  CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : NULL;
+  if (pCS && m_pDocument) {
+    m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
+  }
+}
+
+FX_BOOL CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+  CPDF_Object* pBaseCS = pArray->GetElementValue(1);
+  if (pBaseCS == m_pArray) {
+    return FALSE;
+  }
+  CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
+  m_pBaseCS = pDocPageData->GetColorSpace(pBaseCS, NULL);
+  if (m_pBaseCS) {
+    if (m_pBaseCS->GetFamily() == PDFCS_PATTERN) {
+      return FALSE;
+    }
+    m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
+    m_nComponents = m_pBaseCS->CountComponents() + 1;
+    if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) {
+      return FALSE;
+    }
+  } else {
+    m_nComponents = 1;
+  }
+  return TRUE;
+}
+
+FX_BOOL CPDF_PatternCS::GetRGB(FX_FLOAT* pBuf,
+                               FX_FLOAT& R,
+                               FX_FLOAT& G,
+                               FX_FLOAT& B) const {
+  if (m_pBaseCS) {
+    ASSERT(m_pBaseCS->GetFamily() != PDFCS_PATTERN);
+    PatternValue* pvalue = (PatternValue*)pBuf;
+    if (m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B)) {
+      return TRUE;
+    }
+  }
+  R = G = B = 0.75f;
+  return FALSE;
+}
+
+CPDF_ColorSpace* CPDF_PatternCS::GetBaseCS() const {
+  return m_pBaseCS;
+}
+
+CPDF_SeparationCS::CPDF_SeparationCS(CPDF_Document* pDoc)
+    : CPDF_ColorSpace(pDoc, PDFCS_SEPARATION, 1),
+      m_pAltCS(nullptr),
+      m_pFunc(nullptr) {}
+
+CPDF_SeparationCS::~CPDF_SeparationCS() {
+  if (m_pAltCS) {
+    m_pAltCS->ReleaseCS();
+  }
+  delete m_pFunc;
+}
+
+void CPDF_SeparationCS::GetDefaultValue(int iComponent,
+                                        FX_FLOAT& value,
+                                        FX_FLOAT& min,
+                                        FX_FLOAT& max) const {
+  value = 1.0f;
+  min = 0;
+  max = 1.0f;
+}
+
+FX_BOOL CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+  CFX_ByteString name = pArray->GetStringAt(1);
+  if (name == "None") {
+    m_Type = None;
+  } else {
+    m_Type = Colorant;
+    CPDF_Object* pAltCS = pArray->GetElementValue(2);
+    if (pAltCS == m_pArray) {
+      return FALSE;
+    }
+    m_pAltCS = Load(pDoc, pAltCS);
+    if (!m_pAltCS) {
+      return FALSE;
+    }
+    CPDF_Object* pFuncObj = pArray->GetElementValue(3);
+    if (pFuncObj && !pFuncObj->IsName())
+      m_pFunc = CPDF_Function::Load(pFuncObj);
+
+    if (m_pFunc && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
+      delete m_pFunc;
+      m_pFunc = NULL;
+    }
+  }
+  return TRUE;
+}
+
+FX_BOOL CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf,
+                                  FX_FLOAT& R,
+                                  FX_FLOAT& G,
+                                  FX_FLOAT& B) const {
+  if (m_Type == None) {
+    return FALSE;
+  }
+  if (!m_pFunc) {
+    if (!m_pAltCS) {
+      return FALSE;
+    }
+    int nComps = m_pAltCS->CountComponents();
+    CFX_FixedBufGrow<FX_FLOAT, 16> results(nComps);
+    for (int i = 0; i < nComps; i++) {
+      results[i] = *pBuf;
+    }
+    return m_pAltCS->GetRGB(results, R, G, B);
+  }
+  CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
+  int nresults = 0;
+  m_pFunc->Call(pBuf, 1, results, nresults);
+  if (nresults == 0) {
+    return FALSE;
+  }
+  if (m_pAltCS) {
+    return m_pAltCS->GetRGB(results, R, G, B);
+  }
+  R = G = B = 0;
+  return FALSE;
+}
+
+void CPDF_SeparationCS::EnableStdConversion(FX_BOOL bEnabled) {
+  CPDF_ColorSpace::EnableStdConversion(bEnabled);
+  if (m_pAltCS) {
+    m_pAltCS->EnableStdConversion(bEnabled);
+  }
+}
+
+CPDF_DeviceNCS::CPDF_DeviceNCS(CPDF_Document* pDoc)
+    : CPDF_ColorSpace(pDoc, PDFCS_DEVICEN, 0),
+      m_pAltCS(nullptr),
+      m_pFunc(nullptr) {}
+
+CPDF_DeviceNCS::~CPDF_DeviceNCS() {
+  delete m_pFunc;
+  if (m_pAltCS) {
+    m_pAltCS->ReleaseCS();
+  }
+}
+
+void CPDF_DeviceNCS::GetDefaultValue(int iComponent,
+                                     FX_FLOAT& value,
+                                     FX_FLOAT& min,
+                                     FX_FLOAT& max) const {
+  value = 1.0f;
+  min = 0;
+  max = 1.0f;
+}
+
+FX_BOOL CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+  CPDF_Array* pObj = ToArray(pArray->GetElementValue(1));
+  if (!pObj)
+    return FALSE;
+
+  m_nComponents = pObj->GetCount();
+  CPDF_Object* pAltCS = pArray->GetElementValue(2);
+  if (!pAltCS || pAltCS == m_pArray) {
+    return FALSE;
+  }
+  m_pAltCS = Load(pDoc, pAltCS);
+  m_pFunc = CPDF_Function::Load(pArray->GetElementValue(3));
+  if (!m_pAltCS || !m_pFunc) {
+    return FALSE;
+  }
+  if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+FX_BOOL CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf,
+                               FX_FLOAT& R,
+                               FX_FLOAT& G,
+                               FX_FLOAT& B) const {
+  if (!m_pFunc) {
+    return FALSE;
+  }
+  CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
+  int nresults = 0;
+  m_pFunc->Call(pBuf, m_nComponents, results, nresults);
+  if (nresults == 0) {
+    return FALSE;
+  }
+  return m_pAltCS->GetRGB(results, R, G, B);
+}
+
+void CPDF_DeviceNCS::EnableStdConversion(FX_BOOL bEnabled) {
+  CPDF_ColorSpace::EnableStdConversion(bEnabled);
+  if (m_pAltCS) {
+    m_pAltCS->EnableStdConversion(bEnabled);
+  }
+}
diff --git a/core/fpdfapi/fpdf_page/cpdf_colorstate.cpp b/core/fpdfapi/fpdf_page/cpdf_colorstate.cpp
index 02999c9..81e5e41 100644
--- a/core/fpdfapi/fpdf_page/cpdf_colorstate.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_colorstate.cpp
@@ -6,6 +6,10 @@
 
 #include "core/fpdfapi/fpdf_page/cpdf_colorstate.h"
 
+#include "core/fpdfapi/fpdf_page/cpdf_pattern.h"
+#include "core/fpdfapi/fpdf_page/cpdf_tilingpattern.h"
+#include "core/include/fxge/fx_dib.h"
+
 void CPDF_ColorState::SetFillColor(CPDF_ColorSpace* pCS,
                                    FX_FLOAT* pValue,
                                    int nValues) {
diff --git a/core/fpdfapi/fpdf_page/cpdf_colorstatedata.h b/core/fpdfapi/fpdf_page/cpdf_colorstatedata.h
index 319fea5..96e43bd 100644
--- a/core/fpdfapi/fpdf_page/cpdf_colorstatedata.h
+++ b/core/fpdfapi/fpdf_page/cpdf_colorstatedata.h
@@ -7,8 +7,8 @@
 #ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_COLORSTATEDATA_H_
 #define CORE_FPDFAPI_FPDF_PAGE_CPDF_COLORSTATEDATA_H_
 
+#include "core/fpdfapi/fpdf_page/include/cpdf_color.h"
 #include "core/fxcrt/include/fx_system.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 
 class CPDF_ColorStateData {
  public:
diff --git a/core/fpdfapi/fpdf_page/cpdf_countedobject.h b/core/fpdfapi/fpdf_page/cpdf_countedobject.h
new file mode 100644
index 0000000..da840be
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_countedobject.h
@@ -0,0 +1,45 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_COUNTEDOBJECT_H_
+#define CORE_FPDFAPI_FPDF_PAGE_CPDF_COUNTEDOBJECT_H_
+
+#include "core/fpdfapi/fpdf_page/cpdf_pattern.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_colorspace.h"
+#include "core/fxcrt/include/fx_system.h"
+
+template <class T>
+class CPDF_CountedObject {
+ public:
+  explicit CPDF_CountedObject(T* ptr) : m_nCount(1), m_pObj(ptr) {}
+  void reset(T* ptr) {  // CAUTION: tosses prior ref counts.
+    m_nCount = 1;
+    m_pObj = ptr;
+  }
+  void clear() {  // Now you're all weak ptrs ...
+    delete m_pObj;
+    m_pObj = nullptr;
+  }
+  T* get() const { return m_pObj; }
+  T* AddRef() {
+    FXSYS_assert(m_pObj);
+    ++m_nCount;
+    return m_pObj;
+  }
+  void RemoveRef() {
+    if (m_nCount)
+      --m_nCount;
+  }
+  size_t use_count() const { return m_nCount; }
+
+ protected:
+  size_t m_nCount;
+  T* m_pObj;
+};
+using CPDF_CountedColorSpace = CPDF_CountedObject<CPDF_ColorSpace>;
+using CPDF_CountedPattern = CPDF_CountedObject<CPDF_Pattern>;
+
+#endif  // CORE_FPDFAPI_FPDF_PAGE_CPDF_COUNTEDOBJECT_H_
diff --git a/core/fpdfapi/fpdf_edit/fpdf_edit_image.cpp b/core/fpdfapi/fpdf_page/cpdf_image.cpp
similarity index 73%
rename from core/fpdfapi/fpdf_edit/fpdf_edit_image.cpp
rename to core/fpdfapi/fpdf_page/cpdf_image.cpp
index 50e4f79..d9e7d77 100644
--- a/core/fpdfapi/fpdf_edit/fpdf_edit_image.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_image.cpp
@@ -1,20 +1,78 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
+// Copyright 2016 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.
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
-#include "core/fpdfapi/fpdf_page/pageint.h"
-#include "core/fpdfapi/fpdf_parser/cpdf_boolean.h"
-#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
-#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
+
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfapi/include/cpdf_modulemgr.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/include/fxge/fx_dib.h"
+#include "core/fpdfapi/fpdf_page/pageint.h"
+#include "core/include/fxcodec/fx_codec.h"
+#include "core/fpdfapi/fpdf_parser/cpdf_boolean.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_render/cpdf_pagerendercache.h"
 #include "core/fpdfapi/fpdf_render/render_int.h"
-#include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/include/fxcodec/fx_codec.h"
+
+CPDF_Image::CPDF_Image(CPDF_Document* pDoc)
+    : m_pDIBSource(nullptr),
+      m_pMask(nullptr),
+      m_MatteColor(0),
+      m_pStream(nullptr),
+      m_bInline(FALSE),
+      m_pInlineDict(nullptr),
+      m_pDocument(pDoc),
+      m_pOC(nullptr) {}
+
+CPDF_Image::~CPDF_Image() {
+  if (m_bInline) {
+    if (m_pStream)
+      m_pStream->Release();
+    if (m_pInlineDict)
+      m_pInlineDict->Release();
+  }
+}
+
+void CPDF_Image::Release() {
+  if (m_bInline || (m_pStream && m_pStream->GetObjNum() == 0))
+    delete this;
+}
+
+CPDF_Image* CPDF_Image::Clone() {
+  if (m_pStream->GetObjNum())
+    return m_pDocument->GetPageData()->GetImage(m_pStream);
+
+  CPDF_Image* pImage = new CPDF_Image(m_pDocument);
+  pImage->LoadImageF(ToStream(m_pStream->Clone()), m_bInline);
+  if (m_bInline)
+    pImage->SetInlineDict(ToDictionary(m_pInlineDict->Clone(TRUE)));
+
+  return pImage;
+}
+
+FX_BOOL CPDF_Image::LoadImageF(CPDF_Stream* pStream, FX_BOOL bInline) {
+  m_pStream = pStream;
+  if (m_bInline && m_pInlineDict) {
+    m_pInlineDict->Release();
+    m_pInlineDict = NULL;
+  }
+  m_bInline = bInline;
+  CPDF_Dictionary* pDict = pStream->GetDict();
+  if (m_bInline) {
+    m_pInlineDict = ToDictionary(pDict->Clone());
+  }
+  m_pOC = pDict->GetDictBy("OC");
+  m_bIsMask =
+      !pDict->KeyExist("ColorSpace") || pDict->GetIntegerBy("ImageMask");
+  m_bInterpolate = pDict->GetIntegerBy("Interpolate");
+  m_Height = pDict->GetIntegerBy("Height");
+  m_Width = pDict->GetIntegerBy("Width");
+  return TRUE;
+}
 
 CPDF_Dictionary* CPDF_Image::InitJPEG(uint8_t* pData, FX_DWORD size) {
   int32_t width;
@@ -61,6 +119,7 @@
   }
   return pDict;
 }
+
 void CPDF_Image::SetJpegImage(uint8_t* pData, FX_DWORD size) {
   CPDF_Dictionary* pDict = InitJPEG(pData, size);
   if (!pDict) {
@@ -68,6 +127,7 @@
   }
   m_pStream->InitStream(pData, size, pDict);
 }
+
 void CPDF_Image::SetJpegImage(IFX_FileRead* pFile) {
   FX_DWORD size = (FX_DWORD)pFile->GetSize();
   if (!size) {
@@ -92,23 +152,12 @@
   }
   m_pStream->InitStreamFromFile(pFile, pDict);
 }
-void _DCTEncodeBitmap(CPDF_Dictionary* pBitmapDict,
-                      const CFX_DIBitmap* pBitmap,
-                      int quality,
-                      uint8_t*& buf,
-                      FX_STRSIZE& size) {}
-void _JBIG2EncodeBitmap(CPDF_Dictionary* pBitmapDict,
-                        const CFX_DIBitmap* pBitmap,
-                        CPDF_Document* pDoc,
-                        uint8_t*& buf,
-                        FX_STRSIZE& size,
-                        FX_BOOL bLossLess) {}
+
 void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap,
                           int32_t iCompress,
                           IFX_FileWrite* pFileWrite,
                           IFX_FileRead* pFileRead,
-                          const CFX_DIBitmap* pMask,
-                          const CPDF_ImageSetParam* pParam) {
+                          const CFX_DIBitmap* pMask) {
   int32_t BitmapWidth = pBitmap->GetWidth();
   int32_t BitmapHeight = pBitmap->GetHeight();
   if (BitmapWidth < 1 || BitmapHeight < 1) {
@@ -117,8 +166,7 @@
   uint8_t* src_buf = pBitmap->GetBuffer();
   int32_t src_pitch = pBitmap->GetPitch();
   int32_t bpp = pBitmap->GetBPP();
-  FX_BOOL bUseMatte =
-      pParam && pParam->pMatteColor && (pBitmap->GetFormat() == FXDIB_Argb);
+
   CPDF_Dictionary* pDict = new CPDF_Dictionary;
   pDict->SetAtName("Type", "XObject");
   pDict->SetAtName("Subtype", "Image");
@@ -234,11 +282,7 @@
     pMaskDict->SetAtInteger("BitsPerComponent", 8);
     if (pMaskBitmap->GetBPP() == 8 &&
         (iCompress & PDF_IMAGE_MASK_LOSSY_COMPRESS) != 0) {
-      _DCTEncodeBitmap(pMaskDict, pMaskBitmap, pParam ? pParam->nQuality : 75,
-                       mask_buf, mask_size);
     } else if (pMaskBitmap->GetFormat() == FXDIB_1bppMask) {
-      _JBIG2EncodeBitmap(pMaskDict, pMaskBitmap, m_pDocument, mask_buf,
-                         mask_size, TRUE);
     } else {
       mask_buf = FX_Alloc2D(uint8_t, maskHeight, maskWidth);
       mask_size = maskHeight * maskWidth;  // Safe since checked alloc returned.
@@ -248,15 +292,7 @@
       }
     }
     pMaskDict->SetAtInteger("Length", mask_size);
-    if (bUseMatte) {
-      int a, r, g, b;
-      ArgbDecode(*(pParam->pMatteColor), a, r, g, b);
-      CPDF_Array* pMatte = new CPDF_Array;
-      pMatte->AddInteger(r);
-      pMatte->AddInteger(g);
-      pMatte->AddInteger(b);
-      pMaskDict->SetAt("Matte", pMatte);
-    }
+
     CPDF_Stream* pMaskStream = new CPDF_Stream(mask_buf, mask_size, pMaskDict);
     m_pDocument->AddIndirectObject(pMaskStream);
     pDict->SetAtReference("SMask", m_pDocument, pMaskStream);
@@ -267,14 +303,8 @@
   FX_BOOL bStream = pFileWrite && pFileRead;
   if (opType == 0) {
     if (iCompress & PDF_IMAGE_LOSSLESS_COMPRESS) {
-      if (pBitmap->GetBPP() == 1) {
-        _JBIG2EncodeBitmap(pDict, pBitmap, m_pDocument, dest_buf, dest_size,
-                           TRUE);
-      }
     } else {
       if (pBitmap->GetBPP() == 1) {
-        _JBIG2EncodeBitmap(pDict, pBitmap, m_pDocument, dest_buf, dest_size,
-                           FALSE);
       } else if (pBitmap->GetBPP() >= 8 && pBitmap->GetPalette()) {
         CFX_DIBitmap* pNewBitmap = new CFX_DIBitmap();
         pNewBitmap->Copy(pBitmap);
@@ -289,32 +319,6 @@
         dest_size = 0;
         delete pNewBitmap;
         return;
-      } else {
-        if (bUseMatte) {
-          CFX_DIBitmap* pNewBitmap = new CFX_DIBitmap();
-          pNewBitmap->Create(BitmapWidth, BitmapHeight, FXDIB_Argb);
-          uint8_t* dst_buf = pNewBitmap->GetBuffer();
-          int32_t src_offset = 0;
-          for (int32_t row = 0; row < BitmapHeight; row++) {
-            src_offset = row * src_pitch;
-            for (int32_t column = 0; column < BitmapWidth; column++) {
-              FX_FLOAT alpha = src_buf[src_offset + 3] / 255.0f;
-              dst_buf[src_offset] = (uint8_t)(src_buf[src_offset] * alpha);
-              dst_buf[src_offset + 1] =
-                  (uint8_t)(src_buf[src_offset + 1] * alpha);
-              dst_buf[src_offset + 2] =
-                  (uint8_t)(src_buf[src_offset + 2] * alpha);
-              dst_buf[src_offset + 3] = (uint8_t)(src_buf[src_offset + 3]);
-              src_offset += 4;
-            }
-          }
-          _DCTEncodeBitmap(pDict, pNewBitmap, pParam ? pParam->nQuality : 75,
-                           dest_buf, dest_size);
-          delete pNewBitmap;
-        } else {
-          _DCTEncodeBitmap(pDict, pBitmap, pParam ? pParam->nQuality : 75,
-                           dest_buf, dest_size);
-        }
       }
     }
     if (bStream) {
@@ -352,7 +356,7 @@
     for (int32_t row = 0; row < BitmapHeight; row++) {
       src_offset = row * src_pitch;
       for (int32_t column = 0; column < BitmapWidth; column++) {
-        FX_FLOAT alpha = bUseMatte ? src_buf[src_offset + 3] / 255.0f : 1;
+        FX_FLOAT alpha = 1;
         pDest[dest_offset] = (uint8_t)(src_buf[src_offset + 2] * alpha);
         pDest[dest_offset + 1] = (uint8_t)(src_buf[src_offset + 1] * alpha);
         pDest[dest_offset + 2] = (uint8_t)(src_buf[src_offset] * alpha);
@@ -386,6 +390,72 @@
   m_Height = BitmapHeight;
   FX_Free(dest_buf);
 }
+
 void CPDF_Image::ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pBitmap) {
   pPage->GetRenderCache()->ResetBitmap(m_pStream, pBitmap);
 }
+
+CFX_DIBSource* CPDF_Image::LoadDIBSource(CFX_DIBSource** ppMask,
+                                         FX_DWORD* pMatteColor,
+                                         FX_BOOL bStdCS,
+                                         FX_DWORD GroupFamily,
+                                         FX_BOOL bLoadMask) const {
+  std::unique_ptr<CPDF_DIBSource> source(new CPDF_DIBSource);
+  if (source->Load(m_pDocument, m_pStream,
+                   reinterpret_cast<CPDF_DIBSource**>(ppMask), pMatteColor,
+                   nullptr, nullptr, bStdCS, GroupFamily, bLoadMask)) {
+    return source.release();
+  }
+  return nullptr;
+}
+
+CFX_DIBSource* CPDF_Image::DetachBitmap() {
+  CFX_DIBSource* pBitmap = m_pDIBSource;
+  m_pDIBSource = nullptr;
+  return pBitmap;
+}
+
+CFX_DIBSource* CPDF_Image::DetachMask() {
+  CFX_DIBSource* pBitmap = m_pMask;
+  m_pMask = nullptr;
+  return pBitmap;
+}
+
+FX_BOOL CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource,
+                                       CPDF_Dictionary* pPageResource,
+                                       FX_BOOL bStdCS,
+                                       FX_DWORD GroupFamily,
+                                       FX_BOOL bLoadMask) {
+  std::unique_ptr<CPDF_DIBSource> source(new CPDF_DIBSource);
+  int ret =
+      source->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResource,
+                                 pPageResource, bStdCS, GroupFamily, bLoadMask);
+  if (ret == 2) {
+    m_pDIBSource = source.release();
+    return TRUE;
+  }
+  if (!ret) {
+    m_pDIBSource = nullptr;
+    return FALSE;
+  }
+  m_pMask = source->DetachMask();
+  m_MatteColor = source->GetMatteColor();
+  m_pDIBSource = source.release();
+  return FALSE;
+}
+
+FX_BOOL CPDF_Image::Continue(IFX_Pause* pPause) {
+  CPDF_DIBSource* pSource = static_cast<CPDF_DIBSource*>(m_pDIBSource);
+  int ret = pSource->ContinueLoadDIBSource(pPause);
+  if (ret == 2) {
+    return TRUE;
+  }
+  if (!ret) {
+    delete m_pDIBSource;
+    m_pDIBSource = nullptr;
+    return FALSE;
+  }
+  m_pMask = pSource->DetachMask();
+  m_MatteColor = pSource->GetMatteColor();
+  return FALSE;
+}
diff --git a/core/fpdfapi/fpdf_page/cpdf_imageobject.cpp b/core/fpdfapi/fpdf_page/cpdf_imageobject.cpp
index f339935..6203d56 100644
--- a/core/fpdfapi/fpdf_page/cpdf_imageobject.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_imageobject.cpp
@@ -6,6 +6,7 @@
 
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 
diff --git a/core/fpdfapi/fpdf_page/cpdf_meshstream.cpp b/core/fpdfapi/fpdf_page/cpdf_meshstream.cpp
new file mode 100644
index 0000000..1d983d2
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_meshstream.cpp
@@ -0,0 +1,119 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_page/cpdf_meshstream.h"
+
+#include "core/fpdfapi/fpdf_page/include/cpdf_colorspace.h"
+#include "core/fpdfapi/fpdf_page/pageint.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+
+FX_BOOL CPDF_MeshStream::Load(CPDF_Stream* pShadingStream,
+                              CPDF_Function** pFuncs,
+                              int nFuncs,
+                              CPDF_ColorSpace* pCS) {
+  m_Stream.LoadAllData(pShadingStream);
+  m_BitStream.Init(m_Stream.GetData(), m_Stream.GetSize());
+  m_pFuncs = pFuncs;
+  m_nFuncs = nFuncs;
+  m_pCS = pCS;
+  CPDF_Dictionary* pDict = pShadingStream->GetDict();
+  m_nCoordBits = pDict->GetIntegerBy("BitsPerCoordinate");
+  m_nCompBits = pDict->GetIntegerBy("BitsPerComponent");
+  m_nFlagBits = pDict->GetIntegerBy("BitsPerFlag");
+  if (!m_nCoordBits || !m_nCompBits)
+    return FALSE;
+
+  FX_DWORD nComps = pCS->CountComponents();
+  if (nComps > 8)
+    return FALSE;
+
+  m_nComps = nFuncs ? 1 : nComps;
+  if (((int)m_nComps < 0) || m_nComps > 8)
+    return FALSE;
+
+  m_CoordMax = m_nCoordBits == 32 ? -1 : (1 << m_nCoordBits) - 1;
+  m_CompMax = (1 << m_nCompBits) - 1;
+  CPDF_Array* pDecode = pDict->GetArrayBy("Decode");
+  if (!pDecode || pDecode->GetCount() != 4 + m_nComps * 2)
+    return FALSE;
+
+  m_xmin = pDecode->GetNumberAt(0);
+  m_xmax = pDecode->GetNumberAt(1);
+  m_ymin = pDecode->GetNumberAt(2);
+  m_ymax = pDecode->GetNumberAt(3);
+  for (FX_DWORD i = 0; i < m_nComps; i++) {
+    m_ColorMin[i] = pDecode->GetNumberAt(i * 2 + 4);
+    m_ColorMax[i] = pDecode->GetNumberAt(i * 2 + 5);
+  }
+  return TRUE;
+}
+
+FX_DWORD CPDF_MeshStream::GetFlag() {
+  return m_BitStream.GetBits(m_nFlagBits) & 0x03;
+}
+
+void CPDF_MeshStream::GetCoords(FX_FLOAT& x, FX_FLOAT& y) {
+  if (m_nCoordBits == 32) {
+    x = m_xmin + (FX_FLOAT)(m_BitStream.GetBits(m_nCoordBits) *
+                            (m_xmax - m_xmin) / (double)m_CoordMax);
+    y = m_ymin + (FX_FLOAT)(m_BitStream.GetBits(m_nCoordBits) *
+                            (m_ymax - m_ymin) / (double)m_CoordMax);
+  } else {
+    x = m_xmin +
+        m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) / m_CoordMax;
+    y = m_ymin +
+        m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) / m_CoordMax;
+  }
+}
+
+void CPDF_MeshStream::GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b) {
+  FX_DWORD i;
+  FX_FLOAT color_value[8];
+  for (i = 0; i < m_nComps; i++) {
+    color_value[i] = m_ColorMin[i] +
+                     m_BitStream.GetBits(m_nCompBits) *
+                         (m_ColorMax[i] - m_ColorMin[i]) / m_CompMax;
+  }
+  if (m_nFuncs) {
+    static const int kMaxResults = 8;
+    FX_FLOAT result[kMaxResults];
+    int nResults;
+    FXSYS_memset(result, 0, sizeof(result));
+    for (FX_DWORD i = 0; i < m_nFuncs; i++) {
+      if (m_pFuncs[i] && m_pFuncs[i]->CountOutputs() <= kMaxResults) {
+        m_pFuncs[i]->Call(color_value, 1, result, nResults);
+      }
+    }
+    m_pCS->GetRGB(result, r, g, b);
+  } else {
+    m_pCS->GetRGB(color_value, r, g, b);
+  }
+}
+
+FX_DWORD CPDF_MeshStream::GetVertex(CPDF_MeshVertex& vertex,
+                                    CFX_Matrix* pObject2Bitmap) {
+  FX_DWORD flag = GetFlag();
+  GetCoords(vertex.x, vertex.y);
+  pObject2Bitmap->Transform(vertex.x, vertex.y);
+  GetColor(vertex.r, vertex.g, vertex.b);
+  m_BitStream.ByteAlign();
+  return flag;
+}
+
+FX_BOOL CPDF_MeshStream::GetVertexRow(CPDF_MeshVertex* vertex,
+                                      int count,
+                                      CFX_Matrix* pObject2Bitmap) {
+  for (int i = 0; i < count; i++) {
+    if (m_BitStream.IsEOF())
+      return FALSE;
+
+    GetCoords(vertex[i].x, vertex[i].y);
+    pObject2Bitmap->Transform(vertex[i].x, vertex[i].y);
+    GetColor(vertex[i].r, vertex[i].g, vertex[i].b);
+    m_BitStream.ByteAlign();
+  }
+  return TRUE;
+}
diff --git a/core/fpdfapi/fpdf_page/cpdf_meshstream.h b/core/fpdfapi/fpdf_page/cpdf_meshstream.h
new file mode 100644
index 0000000..4934c0b
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_meshstream.h
@@ -0,0 +1,63 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_MESHSTREAM_H_
+#define CORE_FPDFAPI_FPDF_PAGE_CPDF_MESHSTREAM_H_
+
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
+#include "core/fxcrt/include/fx_basic.h"
+#include "core/fxcrt/include/fx_system.h"
+
+struct CPDF_MeshVertex {
+  FX_FLOAT x;
+  FX_FLOAT y;
+  FX_FLOAT r;
+  FX_FLOAT g;
+  FX_FLOAT b;
+};
+
+class CFX_Matrix;
+class CPDF_ColorSpace;
+class CPDF_Function;
+class CPDF_Stream;
+
+class CPDF_MeshStream {
+ public:
+  FX_BOOL Load(CPDF_Stream* pShadingStream,
+               CPDF_Function** pFuncs,
+               int nFuncs,
+               CPDF_ColorSpace* pCS);
+
+  FX_DWORD GetFlag();
+
+  void GetCoords(FX_FLOAT& x, FX_FLOAT& y);
+  void GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b);
+
+  FX_DWORD GetVertex(CPDF_MeshVertex& vertex, CFX_Matrix* pObject2Bitmap);
+  FX_BOOL GetVertexRow(CPDF_MeshVertex* vertex,
+                       int count,
+                       CFX_Matrix* pObject2Bitmap);
+
+  CPDF_Function** m_pFuncs;
+  CPDF_ColorSpace* m_pCS;
+  FX_DWORD m_nFuncs;
+  FX_DWORD m_nCoordBits;
+  FX_DWORD m_nCompBits;
+  FX_DWORD m_nFlagBits;
+  FX_DWORD m_nComps;
+  FX_DWORD m_CoordMax;
+  FX_DWORD m_CompMax;
+  FX_FLOAT m_xmin;
+  FX_FLOAT m_xmax;
+  FX_FLOAT m_ymin;
+  FX_FLOAT m_ymax;
+  FX_FLOAT m_ColorMin[8];
+  FX_FLOAT m_ColorMax[8];
+  CPDF_StreamAcc m_Stream;
+  CFX_BitStream m_BitStream;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_PAGE_CPDF_MESHSTREAM_H_
diff --git a/core/fpdfapi/fpdf_page/cpdf_page.cpp b/core/fpdfapi/fpdf_page/cpdf_page.cpp
index 2c01cd5..6fd9b0a 100644
--- a/core/fpdfapi/fpdf_page/cpdf_page.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_page.cpp
@@ -9,6 +9,7 @@
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_object.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
 #include "core/fpdfapi/ipdf_rendermodule.h"
diff --git a/core/fpdfapi/fpdf_page/cpdf_pageobjectholder.cpp b/core/fpdfapi/fpdf_page/cpdf_pageobjectholder.cpp
index fa6347e..cd6eca5 100644
--- a/core/fpdfapi/fpdf_page/cpdf_pageobjectholder.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_pageobjectholder.cpp
@@ -8,6 +8,7 @@
 
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 
 CPDF_PageObjectHolder::CPDF_PageObjectHolder()
     : m_pFormDict(nullptr),
diff --git a/core/fpdfapi/fpdf_page/cpdf_pattern.cpp b/core/fpdfapi/fpdf_page/cpdf_pattern.cpp
new file mode 100644
index 0000000..fc9d10e
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_pattern.cpp
@@ -0,0 +1,21 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_page/cpdf_pattern.h"
+
+CPDF_Pattern::CPDF_Pattern(PatternType type,
+                           CPDF_Document* pDoc,
+                           CPDF_Object* pObj,
+                           const CFX_Matrix* pParentMatrix)
+    : m_PatternType(type),
+      m_pDocument(pDoc),
+      m_pPatternObj(pObj),
+      m_bForceClear(FALSE) {
+  if (pParentMatrix)
+    m_ParentMatrix = *pParentMatrix;
+}
+
+CPDF_Pattern::~CPDF_Pattern() {}
diff --git a/core/fpdfapi/fpdf_page/cpdf_pattern.h b/core/fpdfapi/fpdf_page/cpdf_pattern.h
new file mode 100644
index 0000000..7f9a33b
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_pattern.h
@@ -0,0 +1,39 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_PATTERN_H_
+#define CORE_FPDFAPI_FPDF_PAGE_CPDF_PATTERN_H_
+
+#include "core/fxcrt/include/fx_coordinates.h"
+#include "core/fxcrt/include/fx_system.h"
+
+class CPDF_Document;
+class CPDF_Object;
+
+class CPDF_Pattern {
+ public:
+  enum PatternType { TILING = 1, SHADING };
+
+  virtual ~CPDF_Pattern();
+
+  void SetForceClear(FX_BOOL bForceClear) { m_bForceClear = bForceClear; }
+
+  const PatternType m_PatternType;
+  CPDF_Document* const m_pDocument;
+  CPDF_Object* const m_pPatternObj;
+  CFX_Matrix m_Pattern2Form;
+  CFX_Matrix m_ParentMatrix;
+
+ protected:
+  CPDF_Pattern(PatternType type,
+               CPDF_Document* pDoc,
+               CPDF_Object* pObj,
+               const CFX_Matrix* pParentMatrix);
+
+  FX_BOOL m_bForceClear;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_PAGE_CPDF_PATTERN_H_
diff --git a/core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp b/core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp
index 16287fe..56dd6d4 100644
--- a/core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp
@@ -6,6 +6,7 @@
 
 #include "core/fpdfapi/fpdf_page/include/cpdf_shadingobject.h"
 
+#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 
diff --git a/core/fpdfapi/fpdf_page/cpdf_shadingpattern.cpp b/core/fpdfapi/fpdf_page/cpdf_shadingpattern.cpp
new file mode 100644
index 0000000..6ccf140
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_shadingpattern.cpp
@@ -0,0 +1,101 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
+
+#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_object.h"
+
+namespace {
+
+ShadingType ToShadingType(int type) {
+  return (type > static_cast<int>(kInvalidShading) &&
+          type < static_cast<int>(kMaxShading))
+             ? static_cast<ShadingType>(type)
+             : kInvalidShading;
+}
+
+}  // namespace
+
+CPDF_ShadingPattern::CPDF_ShadingPattern(CPDF_Document* pDoc,
+                                         CPDF_Object* pPatternObj,
+                                         FX_BOOL bShading,
+                                         const CFX_Matrix* parentMatrix)
+    : CPDF_Pattern(SHADING,
+                   pDoc,
+                   bShading ? nullptr : pPatternObj,
+                   parentMatrix),
+      m_ShadingType(kInvalidShading),
+      m_bShadingObj(bShading),
+      m_pShadingObj(pPatternObj),
+      m_pCS(nullptr),
+      m_pCountedCS(nullptr),
+      m_nFuncs(0) {
+  if (!bShading) {
+    CPDF_Dictionary* pDict = m_pPatternObj->GetDict();
+    m_Pattern2Form = pDict->GetMatrixBy("Matrix");
+    m_pShadingObj = pDict->GetElementValue("Shading");
+    if (parentMatrix)
+      m_Pattern2Form.Concat(*parentMatrix);
+  }
+  for (int i = 0; i < FX_ArraySize(m_pFunctions); ++i)
+    m_pFunctions[i] = nullptr;
+}
+
+CPDF_ShadingPattern::~CPDF_ShadingPattern() {
+  for (int i = 0; i < m_nFuncs; ++i)
+    delete m_pFunctions[i];
+
+  CPDF_ColorSpace* pCS = m_pCountedCS ? m_pCountedCS->get() : nullptr;
+  if (pCS && m_pDocument)
+    m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
+}
+
+FX_BOOL CPDF_ShadingPattern::Load() {
+  if (m_ShadingType != kInvalidShading)
+    return TRUE;
+
+  CPDF_Dictionary* pShadingDict =
+      m_pShadingObj ? m_pShadingObj->GetDict() : nullptr;
+  if (!pShadingDict)
+    return FALSE;
+
+  if (m_nFuncs) {
+    for (int i = 0; i < m_nFuncs; i++)
+      delete m_pFunctions[i];
+    m_nFuncs = 0;
+  }
+  CPDF_Object* pFunc = pShadingDict->GetElementValue("Function");
+  if (pFunc) {
+    if (CPDF_Array* pArray = pFunc->AsArray()) {
+      m_nFuncs = std::min<int>(pArray->GetCount(), 4);
+
+      for (int i = 0; i < m_nFuncs; i++)
+        m_pFunctions[i] = CPDF_Function::Load(pArray->GetElementValue(i));
+    } else {
+      m_pFunctions[0] = CPDF_Function::Load(pFunc);
+      m_nFuncs = 1;
+    }
+  }
+  CPDF_Object* pCSObj = pShadingDict->GetElementValue("ColorSpace");
+  if (!pCSObj)
+    return FALSE;
+
+  CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData();
+  m_pCS = pDocPageData->GetColorSpace(pCSObj, nullptr);
+  if (m_pCS)
+    m_pCountedCS = pDocPageData->FindColorSpacePtr(m_pCS->GetArray());
+
+  m_ShadingType = ToShadingType(pShadingDict->GetIntegerBy("ShadingType"));
+
+  // We expect to have a stream if our shading type is a mesh.
+  if (IsMeshShading() && !ToStream(m_pShadingObj))
+    return FALSE;
+
+  return TRUE;
+}
diff --git a/core/fpdfapi/fpdf_page/cpdf_shadingpattern.h b/core/fpdfapi/fpdf_page/cpdf_shadingpattern.h
new file mode 100644
index 0000000..55a249a
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_shadingpattern.h
@@ -0,0 +1,62 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_SHADINGPATTERN_H_
+#define CORE_FPDFAPI_FPDF_PAGE_CPDF_SHADINGPATTERN_H_
+
+#include "core/fpdfapi/fpdf_page/cpdf_countedobject.h"
+#include "core/fpdfapi/fpdf_page/cpdf_pattern.h"
+#include "core/fpdfapi/fpdf_page/pageint.h"
+#include "core/fxcrt/include/fx_system.h"
+
+typedef enum {
+  kInvalidShading = 0,
+  kFunctionBasedShading = 1,
+  kAxialShading = 2,
+  kRadialShading = 3,
+  kFreeFormGouraudTriangleMeshShading = 4,
+  kLatticeFormGouraudTriangleMeshShading = 5,
+  kCoonsPatchMeshShading = 6,
+  kTensorProductPatchMeshShading = 7,
+  kMaxShading = 8
+} ShadingType;
+
+class CFX_Matrix;
+class CPDF_ColorSpace;
+class CPDF_Document;
+class CPDF_Object;
+
+class CPDF_ShadingPattern : public CPDF_Pattern {
+ public:
+  CPDF_ShadingPattern(CPDF_Document* pDoc,
+                      CPDF_Object* pPatternObj,
+                      FX_BOOL bShading,
+                      const CFX_Matrix* parentMatrix);
+
+  ~CPDF_ShadingPattern() override;
+
+  bool IsMeshShading() const {
+    return m_ShadingType == kFreeFormGouraudTriangleMeshShading ||
+           m_ShadingType == kLatticeFormGouraudTriangleMeshShading ||
+           m_ShadingType == kCoonsPatchMeshShading ||
+           m_ShadingType == kTensorProductPatchMeshShading;
+  }
+  FX_BOOL Load();
+
+  ShadingType m_ShadingType;
+  FX_BOOL m_bShadingObj;
+  CPDF_Object* m_pShadingObj;
+
+  // Still keep |m_pCS| as some CPDF_ColorSpace (name object) are not managed
+  // as counted objects. Refer to CPDF_DocPageData::GetColorSpace.
+  CPDF_ColorSpace* m_pCS;
+
+  CPDF_CountedColorSpace* m_pCountedCS;
+  CPDF_Function* m_pFunctions[4];
+  int m_nFuncs;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_PAGE_CPDF_SHADINGPATTERN_H_
diff --git a/core/fpdfapi/fpdf_page/cpdf_textobject.cpp b/core/fpdfapi/fpdf_page/cpdf_textobject.cpp
index ef37b30..cf588dc 100644
--- a/core/fpdfapi/fpdf_page/cpdf_textobject.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_textobject.cpp
@@ -6,6 +6,9 @@
 
 #include "core/fpdfapi/fpdf_page/include/cpdf_textobject.h"
 
+#include "core/fpdfapi/fpdf_font/cpdf_cidfont.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
+
 CPDF_TextObject::CPDF_TextObject()
     : m_PosX(0),
       m_PosY(0),
diff --git a/core/fpdfapi/fpdf_page/cpdf_textstate.cpp b/core/fpdfapi/fpdf_page/cpdf_textstate.cpp
index f56d58e..5269cae 100644
--- a/core/fpdfapi/fpdf_page/cpdf_textstate.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_textstate.cpp
@@ -4,6 +4,7 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_page/cpdf_textstate.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
diff --git a/core/fpdfapi/fpdf_page/cpdf_textstatedata.cpp b/core/fpdfapi/fpdf_page/cpdf_textstatedata.cpp
index af65fb5..5cd6061 100644
--- a/core/fpdfapi/fpdf_page/cpdf_textstatedata.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_textstatedata.cpp
@@ -6,9 +6,9 @@
 
 #include "core/fpdfapi/fpdf_page/include/cpdf_textstatedata.h"
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 
 CPDF_TextStateData::CPDF_TextStateData()
     : m_pFont(nullptr),
diff --git a/core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp b/core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp
new file mode 100644
index 0000000..f49ad2b
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp
@@ -0,0 +1,51 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fpdfapi/fpdf_page/cpdf_tilingpattern.h"
+
+#include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_object.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+
+CPDF_TilingPattern::CPDF_TilingPattern(CPDF_Document* pDoc,
+                                       CPDF_Object* pPatternObj,
+                                       const CFX_Matrix* parentMatrix)
+    : CPDF_Pattern(TILING, pDoc, pPatternObj, parentMatrix) {
+  CPDF_Dictionary* pDict = m_pPatternObj->GetDict();
+  m_Pattern2Form = pDict->GetMatrixBy("Matrix");
+  m_bColored = pDict->GetIntegerBy("PaintType") == 1;
+  if (parentMatrix)
+    m_Pattern2Form.Concat(*parentMatrix);
+
+  m_pForm = nullptr;
+}
+
+CPDF_TilingPattern::~CPDF_TilingPattern() {
+  delete m_pForm;
+}
+
+FX_BOOL CPDF_TilingPattern::Load() {
+  if (m_pForm)
+    return TRUE;
+
+  CPDF_Dictionary* pDict = m_pPatternObj->GetDict();
+  if (!pDict)
+    return FALSE;
+
+  m_bColored = pDict->GetIntegerBy("PaintType") == 1;
+  m_XStep = (FX_FLOAT)FXSYS_fabs(pDict->GetNumberBy("XStep"));
+  m_YStep = (FX_FLOAT)FXSYS_fabs(pDict->GetNumberBy("YStep"));
+
+  CPDF_Stream* pStream = m_pPatternObj->AsStream();
+  if (!pStream)
+    return FALSE;
+
+  m_pForm = new CPDF_Form(m_pDocument, NULL, pStream);
+  m_pForm->ParseContent(NULL, &m_ParentMatrix, NULL, NULL);
+  m_BBox = pDict->GetRectBy("BBox");
+  return TRUE;
+}
diff --git a/core/fpdfapi/fpdf_page/cpdf_tilingpattern.h b/core/fpdfapi/fpdf_page/cpdf_tilingpattern.h
new file mode 100644
index 0000000..44446ea
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/cpdf_tilingpattern.h
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_TILINGPATTERN_H_
+#define CORE_FPDFAPI_FPDF_PAGE_CPDF_TILINGPATTERN_H_
+
+#include "core/fpdfapi/fpdf_page/cpdf_pattern.h"
+#include "core/fxcrt/include/fx_coordinates.h"
+#include "core/fxcrt/include/fx_system.h"
+
+class CPDF_Document;
+class CPDF_Form;
+class CPDF_Object;
+
+class CPDF_TilingPattern : public CPDF_Pattern {
+ public:
+  CPDF_TilingPattern(CPDF_Document* pDoc,
+                     CPDF_Object* pPatternObj,
+                     const CFX_Matrix* parentMatrix);
+  ~CPDF_TilingPattern() override;
+
+  FX_BOOL Load();
+
+  FX_BOOL m_bColored;
+  CFX_FloatRect m_BBox;
+  FX_FLOAT m_XStep;
+  FX_FLOAT m_YStep;
+  CPDF_Form* m_pForm;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_PAGE_CPDF_TILINGPATTERN_H_
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_colors.cpp b/core/fpdfapi/fpdf_page/fpdf_page_colors.cpp
index d4b69f2..cc40976 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_colors.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_colors.cpp
@@ -13,12 +13,24 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
 #include "core/include/fxcodec/fx_codec.h"
 
 namespace {
 
+FX_DWORD ComponentsForFamily(int family) {
+  if (family == PDFCS_DEVICERGB)
+    return 3;
+  if (family == PDFCS_DEVICEGRAY)
+    return 1;
+  return 4;
+}
+
+}  // namespace
+
 void sRGB_to_AdobeCMYK(FX_FLOAT R,
                        FX_FLOAT G,
                        FX_FLOAT B,
@@ -38,14 +50,6 @@
   }
 }
 
-FX_DWORD ComponentsForFamily(int family) {
-  if (family == PDFCS_DEVICERGB)
-    return 3;
-  if (family == PDFCS_DEVICEGRAY)
-    return 1;
-  return 4;
-}
-
 void ReverseRGB(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels) {
   if (pDestBuf == pSrcBuf) {
     for (int i = 0; i < pixels; i++) {
@@ -64,8 +68,6 @@
   }
 }
 
-}  // namespace
-
 CPDF_DeviceCS::CPDF_DeviceCS(CPDF_Document* pDoc, int family)
     : CPDF_ColorSpace(pDoc, family, ComponentsForFamily(family)) {}
 
@@ -213,420 +215,7 @@
     }
   }
 }
-const uint8_t g_sRGBSamples1[] = {
-    0,   3,   6,   10,  13,  15,  18,  20,  22,  23,  25,  27,  28,  30,  31,
-    32,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
-    48,  49,  49,  50,  51,  52,  53,  53,  54,  55,  56,  56,  57,  58,  58,
-    59,  60,  61,  61,  62,  62,  63,  64,  64,  65,  66,  66,  67,  67,  68,
-    68,  69,  70,  70,  71,  71,  72,  72,  73,  73,  74,  74,  75,  76,  76,
-    77,  77,  78,  78,  79,  79,  79,  80,  80,  81,  81,  82,  82,  83,  83,
-    84,  84,  85,  85,  85,  86,  86,  87,  87,  88,  88,  88,  89,  89,  90,
-    90,  91,  91,  91,  92,  92,  93,  93,  93,  94,  94,  95,  95,  95,  96,
-    96,  97,  97,  97,  98,  98,  98,  99,  99,  99,  100, 100, 101, 101, 101,
-    102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 106, 106, 106, 107,
-    107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 110, 111, 111, 111,
-    112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 116, 116,
-    116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120,
-};
-const uint8_t g_sRGBSamples2[] = {
-    120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
-    136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149,
-    150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162,
-    163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173,
-    174, 175, 175, 176, 177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184,
-    185, 185, 186, 187, 187, 188, 189, 189, 190, 190, 191, 192, 192, 193, 194,
-    194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202, 203,
-    203, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212,
-    212, 213, 213, 214, 214, 215, 215, 216, 216, 217, 218, 218, 219, 219, 220,
-    220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228,
-    228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235,
-    236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242,
-    243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, 248, 249, 249,
-    250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255,
-};
 
-static FX_FLOAT RGB_Conversion(FX_FLOAT colorComponent) {
-  if (colorComponent > 1) {
-    colorComponent = 1;
-  }
-  if (colorComponent < 0) {
-    colorComponent = 0;
-  }
-  int scale = (int)(colorComponent * 1023);
-  if (scale < 0) {
-    scale = 0;
-  }
-  if (scale < 192) {
-    colorComponent = (g_sRGBSamples1[scale] / 255.0f);
-  } else {
-    colorComponent = (g_sRGBSamples2[scale / 4 - 48] / 255.0f);
-  }
-  return colorComponent;
-}
-
-static void XYZ_to_sRGB(FX_FLOAT X,
-                        FX_FLOAT Y,
-                        FX_FLOAT Z,
-                        FX_FLOAT& R,
-                        FX_FLOAT& G,
-                        FX_FLOAT& B) {
-  FX_FLOAT R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z;
-  FX_FLOAT G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z;
-  FX_FLOAT B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z;
-
-  R = RGB_Conversion(R1);
-  G = RGB_Conversion(G1);
-  B = RGB_Conversion(B1);
-}
-
-static void XYZ_to_sRGB_WhitePoint(FX_FLOAT X,
-                                   FX_FLOAT Y,
-                                   FX_FLOAT Z,
-                                   FX_FLOAT& R,
-                                   FX_FLOAT& G,
-                                   FX_FLOAT& B,
-                                   FX_FLOAT Xw,
-                                   FX_FLOAT Yw,
-                                   FX_FLOAT Zw) {
-  // The following RGB_xyz is based on
-  // sRGB value {Rx,Ry}={0.64, 0.33}, {Gx,Gy}={0.30, 0.60}, {Bx,By}={0.15, 0.06}
-
-  FX_FLOAT Rx = 0.64f, Ry = 0.33f;
-  FX_FLOAT Gx = 0.30f, Gy = 0.60f;
-  FX_FLOAT Bx = 0.15f, By = 0.06f;
-  CFX_Matrix_3by3 RGB_xyz(Rx, Gx, Bx, Ry, Gy, By, 1 - Rx - Ry, 1 - Gx - Gy,
-                          1 - Bx - By);
-  CFX_Vector_3by1 whitePoint(Xw, Yw, Zw);
-  CFX_Vector_3by1 XYZ(X, Y, Z);
-
-  CFX_Vector_3by1 RGB_Sum_XYZ = RGB_xyz.Inverse().TransformVector(whitePoint);
-  CFX_Matrix_3by3 RGB_SUM_XYZ_DIAG(RGB_Sum_XYZ.a, 0, 0, 0, RGB_Sum_XYZ.b, 0, 0,
-                                   0, RGB_Sum_XYZ.c);
-  CFX_Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG);
-  CFX_Vector_3by1 RGB = M.Inverse().TransformVector(XYZ);
-
-  R = RGB_Conversion(RGB.a);
-  G = RGB_Conversion(RGB.b);
-  B = RGB_Conversion(RGB.c);
-}
-class CPDF_CalGray : public CPDF_ColorSpace {
- public:
-  explicit CPDF_CalGray(CPDF_Document* pDoc)
-      : CPDF_ColorSpace(pDoc, PDFCS_CALGRAY, 1) {}
-  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
-  FX_BOOL GetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT& R,
-                 FX_FLOAT& G,
-                 FX_FLOAT& B) const override;
-  FX_BOOL SetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT R,
-                 FX_FLOAT G,
-                 FX_FLOAT B) const override;
-  void TranslateImageLine(uint8_t* pDestBuf,
-                          const uint8_t* pSrcBuf,
-                          int pixels,
-                          int image_width,
-                          int image_height,
-                          FX_BOOL bTransMask = FALSE) const override;
-
- private:
-  FX_FLOAT m_WhitePoint[3];
-  FX_FLOAT m_BlackPoint[3];
-  FX_FLOAT m_Gamma;
-};
-
-FX_BOOL CPDF_CalGray::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-  CPDF_Dictionary* pDict = pArray->GetDictAt(1);
-  if (!pDict)
-    return FALSE;
-
-  CPDF_Array* pParam = pDict->GetArrayBy("WhitePoint");
-  int i;
-  for (i = 0; i < 3; i++) {
-    m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
-  }
-  pParam = pDict->GetArrayBy("BlackPoint");
-  for (i = 0; i < 3; i++) {
-    m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
-  }
-  m_Gamma = pDict->GetNumberBy("Gamma");
-  if (m_Gamma == 0) {
-    m_Gamma = 1.0f;
-  }
-  return TRUE;
-}
-FX_BOOL CPDF_CalGray::GetRGB(FX_FLOAT* pBuf,
-                             FX_FLOAT& R,
-                             FX_FLOAT& G,
-                             FX_FLOAT& B) const {
-  R = G = B = *pBuf;
-  return TRUE;
-}
-FX_BOOL CPDF_CalGray::SetRGB(FX_FLOAT* pBuf,
-                             FX_FLOAT R,
-                             FX_FLOAT G,
-                             FX_FLOAT B) const {
-  if (R == G && R == B) {
-    *pBuf = R;
-    return TRUE;
-  }
-  return FALSE;
-}
-void CPDF_CalGray::TranslateImageLine(uint8_t* pDestBuf,
-                                      const uint8_t* pSrcBuf,
-                                      int pixels,
-                                      int image_width,
-                                      int image_height,
-                                      FX_BOOL bTransMask) const {
-  for (int i = 0; i < pixels; i++) {
-    *pDestBuf++ = pSrcBuf[i];
-    *pDestBuf++ = pSrcBuf[i];
-    *pDestBuf++ = pSrcBuf[i];
-  }
-}
-class CPDF_CalRGB : public CPDF_ColorSpace {
- public:
-  explicit CPDF_CalRGB(CPDF_Document* pDoc)
-      : CPDF_ColorSpace(pDoc, PDFCS_CALRGB, 3) {}
-  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
-  FX_BOOL GetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT& R,
-                 FX_FLOAT& G,
-                 FX_FLOAT& B) const override;
-  FX_BOOL SetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT R,
-                 FX_FLOAT G,
-                 FX_FLOAT B) const override;
-  void TranslateImageLine(uint8_t* pDestBuf,
-                          const uint8_t* pSrcBuf,
-                          int pixels,
-                          int image_width,
-                          int image_height,
-                          FX_BOOL bTransMask = FALSE) const override;
-
-  FX_FLOAT m_WhitePoint[3];
-  FX_FLOAT m_BlackPoint[3];
-  FX_FLOAT m_Gamma[3];
-  FX_FLOAT m_Matrix[9];
-  FX_BOOL m_bGamma;
-  FX_BOOL m_bMatrix;
-};
-FX_BOOL CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-  CPDF_Dictionary* pDict = pArray->GetDictAt(1);
-  if (!pDict)
-    return FALSE;
-
-  CPDF_Array* pParam = pDict->GetArrayBy("WhitePoint");
-  int i;
-  for (i = 0; i < 3; i++) {
-    m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
-  }
-  pParam = pDict->GetArrayBy("BlackPoint");
-  for (i = 0; i < 3; i++) {
-    m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
-  }
-  pParam = pDict->GetArrayBy("Gamma");
-  if (pParam) {
-    m_bGamma = TRUE;
-    for (i = 0; i < 3; i++) {
-      m_Gamma[i] = pParam->GetNumberAt(i);
-    }
-  } else {
-    m_bGamma = FALSE;
-  }
-  pParam = pDict->GetArrayBy("Matrix");
-  if (pParam) {
-    m_bMatrix = TRUE;
-    for (i = 0; i < 9; i++) {
-      m_Matrix[i] = pParam->GetNumberAt(i);
-    }
-  } else {
-    m_bMatrix = FALSE;
-  }
-  return TRUE;
-}
-FX_BOOL CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf,
-                            FX_FLOAT& R,
-                            FX_FLOAT& G,
-                            FX_FLOAT& B) const {
-  FX_FLOAT A_ = pBuf[0];
-  FX_FLOAT B_ = pBuf[1];
-  FX_FLOAT C_ = pBuf[2];
-  if (m_bGamma) {
-    A_ = (FX_FLOAT)FXSYS_pow(A_, m_Gamma[0]);
-    B_ = (FX_FLOAT)FXSYS_pow(B_, m_Gamma[1]);
-    C_ = (FX_FLOAT)FXSYS_pow(C_, m_Gamma[2]);
-  }
-  FX_FLOAT X, Y, Z;
-  if (m_bMatrix) {
-    X = m_Matrix[0] * A_ + m_Matrix[3] * B_ + m_Matrix[6] * C_;
-    Y = m_Matrix[1] * A_ + m_Matrix[4] * B_ + m_Matrix[7] * C_;
-    Z = m_Matrix[2] * A_ + m_Matrix[5] * B_ + m_Matrix[8] * C_;
-  } else {
-    X = A_;
-    Y = B_;
-    Z = C_;
-  }
-  XYZ_to_sRGB_WhitePoint(X, Y, Z, R, G, B, m_WhitePoint[0], m_WhitePoint[1],
-                         m_WhitePoint[2]);
-  return TRUE;
-}
-FX_BOOL CPDF_CalRGB::SetRGB(FX_FLOAT* pBuf,
-                            FX_FLOAT R,
-                            FX_FLOAT G,
-                            FX_FLOAT B) const {
-  pBuf[0] = R;
-  pBuf[1] = G;
-  pBuf[2] = B;
-  return TRUE;
-}
-void CPDF_CalRGB::TranslateImageLine(uint8_t* pDestBuf,
-                                     const uint8_t* pSrcBuf,
-                                     int pixels,
-                                     int image_width,
-                                     int image_height,
-                                     FX_BOOL bTransMask) const {
-  if (bTransMask) {
-    FX_FLOAT Cal[3];
-    FX_FLOAT R, G, B;
-    for (int i = 0; i < pixels; i++) {
-      Cal[0] = ((FX_FLOAT)pSrcBuf[2]) / 255;
-      Cal[1] = ((FX_FLOAT)pSrcBuf[1]) / 255;
-      Cal[2] = ((FX_FLOAT)pSrcBuf[0]) / 255;
-      GetRGB(Cal, R, G, B);
-      pDestBuf[0] = FXSYS_round(B * 255);
-      pDestBuf[1] = FXSYS_round(G * 255);
-      pDestBuf[2] = FXSYS_round(R * 255);
-      pSrcBuf += 3;
-      pDestBuf += 3;
-    }
-  }
-  ReverseRGB(pDestBuf, pSrcBuf, pixels);
-}
-class CPDF_LabCS : public CPDF_ColorSpace {
- public:
-  explicit CPDF_LabCS(CPDF_Document* pDoc)
-      : CPDF_ColorSpace(pDoc, PDFCS_LAB, 3) {}
-  void GetDefaultValue(int iComponent,
-                       FX_FLOAT& value,
-                       FX_FLOAT& min,
-                       FX_FLOAT& max) const override;
-  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
-  FX_BOOL GetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT& R,
-                 FX_FLOAT& G,
-                 FX_FLOAT& B) const override;
-  FX_BOOL SetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT R,
-                 FX_FLOAT G,
-                 FX_FLOAT B) const override;
-  void TranslateImageLine(uint8_t* pDestBuf,
-                          const uint8_t* pSrcBuf,
-                          int pixels,
-                          int image_width,
-                          int image_height,
-                          FX_BOOL bTransMask = FALSE) const override;
-
-  FX_FLOAT m_WhitePoint[3];
-  FX_FLOAT m_BlackPoint[3];
-  FX_FLOAT m_Ranges[4];
-};
-FX_BOOL CPDF_LabCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-  CPDF_Dictionary* pDict = pArray->GetDictAt(1);
-  if (!pDict) {
-    return FALSE;
-  }
-  CPDF_Array* pParam = pDict->GetArrayBy("WhitePoint");
-  int i;
-  for (i = 0; i < 3; i++) {
-    m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
-  }
-  pParam = pDict->GetArrayBy("BlackPoint");
-  for (i = 0; i < 3; i++) {
-    m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0;
-  }
-  pParam = pDict->GetArrayBy("Range");
-  const FX_FLOAT def_ranges[4] = {-100 * 1.0f, 100 * 1.0f, -100 * 1.0f,
-                                  100 * 1.0f};
-  for (i = 0; i < 4; i++) {
-    m_Ranges[i] = pParam ? pParam->GetNumberAt(i) : def_ranges[i];
-  }
-  return TRUE;
-}
-void CPDF_LabCS::GetDefaultValue(int iComponent,
-                                 FX_FLOAT& value,
-                                 FX_FLOAT& min,
-                                 FX_FLOAT& max) const {
-  assert(iComponent < 3);
-  value = 0;
-  if (iComponent == 0) {
-    min = 0;
-    max = 100 * 1.0f;
-  } else {
-    min = m_Ranges[iComponent * 2 - 2];
-    max = m_Ranges[iComponent * 2 - 1];
-    if (value < min) {
-      value = min;
-    } else if (value > max) {
-      value = max;
-    }
-  }
-}
-FX_BOOL CPDF_LabCS::GetRGB(FX_FLOAT* pBuf,
-                           FX_FLOAT& R,
-                           FX_FLOAT& G,
-                           FX_FLOAT& B) const {
-  FX_FLOAT Lstar = pBuf[0];
-  FX_FLOAT astar = pBuf[1];
-  FX_FLOAT bstar = pBuf[2];
-  FX_FLOAT M = (Lstar + 16.0f) / 116.0f;
-  FX_FLOAT L = M + astar / 500.0f;
-  FX_FLOAT N = M - bstar / 200.0f;
-  FX_FLOAT X, Y, Z;
-  if (L < 0.2069f) {
-    X = 0.957f * 0.12842f * (L - 0.1379f);
-  } else {
-    X = 0.957f * L * L * L;
-  }
-  if (M < 0.2069f) {
-    Y = 0.12842f * (M - 0.1379f);
-  } else {
-    Y = M * M * M;
-  }
-  if (N < 0.2069f) {
-    Z = 1.0889f * 0.12842f * (N - 0.1379f);
-  } else {
-    Z = 1.0889f * N * N * N;
-  }
-  XYZ_to_sRGB(X, Y, Z, R, G, B);
-  return TRUE;
-}
-FX_BOOL CPDF_LabCS::SetRGB(FX_FLOAT* pBuf,
-                           FX_FLOAT R,
-                           FX_FLOAT G,
-                           FX_FLOAT B) const {
-  return FALSE;
-}
-void CPDF_LabCS::TranslateImageLine(uint8_t* pDestBuf,
-                                    const uint8_t* pSrcBuf,
-                                    int pixels,
-                                    int image_width,
-                                    int image_height,
-                                    FX_BOOL bTransMask) const {
-  for (int i = 0; i < pixels; i++) {
-    FX_FLOAT lab[3];
-    FX_FLOAT R, G, B;
-    lab[0] = (pSrcBuf[0] * 100 / 255.0f);
-    lab[1] = (FX_FLOAT)(pSrcBuf[1] - 128);
-    lab[2] = (FX_FLOAT)(pSrcBuf[2] - 128);
-    GetRGB(lab, R, G, B);
-    pDestBuf[0] = (int32_t)(B * 255);
-    pDestBuf[1] = (int32_t)(G * 255);
-    pDestBuf[2] = (int32_t)(R * 255);
-    pDestBuf += 3;
-    pSrcBuf += 3;
-  }
-}
 CPDF_IccProfile::CPDF_IccProfile(const uint8_t* pData, FX_DWORD dwSize)
     : m_bsRGB(FALSE), m_pTransform(NULL), m_nSrcComponents(0) {
   if (dwSize == 3144 &&
@@ -643,907 +232,4 @@
     CPDF_ModuleMgr::Get()->GetIccModule()->DestroyTransform(m_pTransform);
   }
 }
-class CPDF_ICCBasedCS : public CPDF_ColorSpace {
- public:
-  explicit CPDF_ICCBasedCS(CPDF_Document* pDoc)
-      : CPDF_ColorSpace(pDoc, PDFCS_ICCBASED, 0),
-        m_pAlterCS(nullptr),
-        m_pProfile(nullptr),
-        m_pCache(nullptr),
-        m_pRanges(nullptr),
-        m_bOwn(FALSE) {}
-  ~CPDF_ICCBasedCS() override;
 
-  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
-  FX_BOOL GetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT& R,
-                 FX_FLOAT& G,
-                 FX_FLOAT& B) const override;
-  FX_BOOL SetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT R,
-                 FX_FLOAT G,
-                 FX_FLOAT B) const override;
-  FX_BOOL v_GetCMYK(FX_FLOAT* pBuf,
-                    FX_FLOAT& c,
-                    FX_FLOAT& m,
-                    FX_FLOAT& y,
-                    FX_FLOAT& k) const override;
-  void EnableStdConversion(FX_BOOL bEnabled) override;
-  void TranslateImageLine(uint8_t* pDestBuf,
-                          const uint8_t* pSrcBuf,
-                          int pixels,
-                          int image_width,
-                          int image_height,
-                          FX_BOOL bTransMask = FALSE) const override;
-
-  CPDF_ColorSpace* m_pAlterCS;
-  CPDF_IccProfile* m_pProfile;
-  uint8_t* m_pCache;
-  FX_FLOAT* m_pRanges;
-  FX_BOOL m_bOwn;
-};
-
-CPDF_ICCBasedCS::~CPDF_ICCBasedCS() {
-  FX_Free(m_pCache);
-  FX_Free(m_pRanges);
-  if (m_pAlterCS && m_bOwn) {
-    m_pAlterCS->ReleaseCS();
-  }
-  if (m_pProfile && m_pDocument) {
-    m_pDocument->GetPageData()->ReleaseIccProfile(m_pProfile);
-  }
-}
-
-FX_BOOL CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-  CPDF_Stream* pStream = pArray->GetStreamAt(1);
-  if (!pStream) {
-    return FALSE;
-  }
-  m_pProfile = pDoc->LoadIccProfile(pStream);
-  if (!m_pProfile) {
-    return FALSE;
-  }
-  m_nComponents =
-      m_pProfile
-          ->GetComponents();  // Try using the nComponents from ICC profile
-  CPDF_Dictionary* pDict = pStream->GetDict();
-  if (!m_pProfile->m_pTransform) {  // No valid ICC profile or using sRGB
-    CPDF_Object* pAlterCSObj =
-        pDict ? pDict->GetElementValue("Alternate") : NULL;
-    if (pAlterCSObj) {
-      CPDF_ColorSpace* pAlterCS = CPDF_ColorSpace::Load(pDoc, pAlterCSObj);
-      if (pAlterCS) {
-        if (m_nComponents == 0) {                 // NO valid ICC profile
-          if (pAlterCS->CountComponents() > 0) {  // Use Alternative colorspace
-            m_nComponents = pAlterCS->CountComponents();
-            m_pAlterCS = pAlterCS;
-            m_bOwn = TRUE;
-          } else {  // No valid alternative colorspace
-            pAlterCS->ReleaseCS();
-            int32_t nDictComponents = pDict ? pDict->GetIntegerBy("N") : 0;
-            if (nDictComponents != 1 && nDictComponents != 3 &&
-                nDictComponents != 4) {
-              return FALSE;
-            }
-            m_nComponents = nDictComponents;
-          }
-
-        } else {  // Using sRGB
-          if (pAlterCS->CountComponents() != m_nComponents) {
-            pAlterCS->ReleaseCS();
-          } else {
-            m_pAlterCS = pAlterCS;
-            m_bOwn = TRUE;
-          }
-        }
-      }
-    }
-    if (!m_pAlterCS) {
-      if (m_nComponents == 1) {
-        m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY);
-      } else if (m_nComponents == 3) {
-        m_pAlterCS = GetStockCS(PDFCS_DEVICERGB);
-      } else if (m_nComponents == 4) {
-        m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK);
-      }
-    }
-  }
-  CPDF_Array* pRanges = pDict->GetArrayBy("Range");
-  m_pRanges = FX_Alloc2D(FX_FLOAT, m_nComponents, 2);
-  for (int i = 0; i < m_nComponents * 2; i++) {
-    if (pRanges) {
-      m_pRanges[i] = pRanges->GetNumberAt(i);
-    } else if (i % 2) {
-      m_pRanges[i] = 1.0f;
-    } else {
-      m_pRanges[i] = 0;
-    }
-  }
-  return TRUE;
-}
-FX_BOOL CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf,
-                                FX_FLOAT& R,
-                                FX_FLOAT& G,
-                                FX_FLOAT& B) const {
-  if (m_pProfile && m_pProfile->m_bsRGB) {
-    R = pBuf[0];
-    G = pBuf[1];
-    B = pBuf[2];
-    return TRUE;
-  }
-  ICodec_IccModule* pIccModule = CPDF_ModuleMgr::Get()->GetIccModule();
-  if (!m_pProfile->m_pTransform || !pIccModule) {
-    if (m_pAlterCS) {
-      return m_pAlterCS->GetRGB(pBuf, R, G, B);
-    }
-    R = G = B = 0.0f;
-    return TRUE;
-  }
-  FX_FLOAT rgb[3];
-  pIccModule->SetComponents(m_nComponents);
-  pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb);
-  R = rgb[0];
-  G = rgb[1];
-  B = rgb[2];
-  return TRUE;
-}
-FX_BOOL CPDF_ICCBasedCS::v_GetCMYK(FX_FLOAT* pBuf,
-                                   FX_FLOAT& c,
-                                   FX_FLOAT& m,
-                                   FX_FLOAT& y,
-                                   FX_FLOAT& k) const {
-  if (m_nComponents != 4) {
-    return FALSE;
-  }
-  c = pBuf[0];
-  m = pBuf[1];
-  y = pBuf[2];
-  k = pBuf[3];
-  return TRUE;
-}
-FX_BOOL CPDF_ICCBasedCS::SetRGB(FX_FLOAT* pBuf,
-                                FX_FLOAT R,
-                                FX_FLOAT G,
-                                FX_FLOAT B) const {
-  return FALSE;
-}
-void CPDF_ICCBasedCS::EnableStdConversion(FX_BOOL bEnabled) {
-  CPDF_ColorSpace::EnableStdConversion(bEnabled);
-  if (m_pAlterCS) {
-    m_pAlterCS->EnableStdConversion(bEnabled);
-  }
-}
-void CPDF_ICCBasedCS::TranslateImageLine(uint8_t* pDestBuf,
-                                         const uint8_t* pSrcBuf,
-                                         int pixels,
-                                         int image_width,
-                                         int image_height,
-                                         FX_BOOL bTransMask) const {
-  if (m_pProfile->m_bsRGB) {
-    ReverseRGB(pDestBuf, pSrcBuf, pixels);
-  } else if (m_pProfile->m_pTransform) {
-    int nMaxColors = 1;
-    for (int i = 0; i < m_nComponents; i++) {
-      nMaxColors *= 52;
-    }
-    if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) {
-      CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(
-          m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels);
-    } else {
-      if (!m_pCache) {
-        ((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc2D(uint8_t, nMaxColors, 3);
-        uint8_t* temp_src = FX_Alloc2D(uint8_t, nMaxColors, m_nComponents);
-        uint8_t* pSrc = temp_src;
-        for (int i = 0; i < nMaxColors; i++) {
-          FX_DWORD color = i;
-          FX_DWORD order = nMaxColors / 52;
-          for (int c = 0; c < m_nComponents; c++) {
-            *pSrc++ = (uint8_t)(color / order * 5);
-            color %= order;
-            order /= 52;
-          }
-        }
-        CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline(
-            m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors);
-        FX_Free(temp_src);
-      }
-      for (int i = 0; i < pixels; i++) {
-        int index = 0;
-        for (int c = 0; c < m_nComponents; c++) {
-          index = index * 52 + (*pSrcBuf) / 5;
-          pSrcBuf++;
-        }
-        index *= 3;
-        *pDestBuf++ = m_pCache[index];
-        *pDestBuf++ = m_pCache[index + 1];
-        *pDestBuf++ = m_pCache[index + 2];
-      }
-    }
-  } else if (m_pAlterCS) {
-    m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width,
-                                   image_height);
-  }
-}
-class CPDF_IndexedCS : public CPDF_ColorSpace {
- public:
-  explicit CPDF_IndexedCS(CPDF_Document* pDoc)
-      : CPDF_ColorSpace(pDoc, PDFCS_INDEXED, 1),
-        m_pBaseCS(nullptr),
-        m_pCountedBaseCS(nullptr),
-        m_pCompMinMax(nullptr) {}
-  ~CPDF_IndexedCS() override;
-
-  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
-  FX_BOOL GetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT& R,
-                 FX_FLOAT& G,
-                 FX_FLOAT& B) const override;
-  CPDF_ColorSpace* GetBaseCS() const override;
-  void EnableStdConversion(FX_BOOL bEnabled) override;
-
-  CPDF_ColorSpace* m_pBaseCS;
-  CPDF_CountedColorSpace* m_pCountedBaseCS;
-  int m_nBaseComponents;
-  int m_MaxIndex;
-  CFX_ByteString m_Table;
-  FX_FLOAT* m_pCompMinMax;
-};
-CPDF_IndexedCS::~CPDF_IndexedCS() {
-  FX_Free(m_pCompMinMax);
-  CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : NULL;
-  if (pCS && m_pDocument) {
-    m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
-  }
-}
-FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-  if (pArray->GetCount() < 4) {
-    return FALSE;
-  }
-  CPDF_Object* pBaseObj = pArray->GetElementValue(1);
-  if (pBaseObj == m_pArray) {
-    return FALSE;
-  }
-  CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
-  m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, NULL);
-  if (!m_pBaseCS) {
-    return FALSE;
-  }
-  m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
-  m_nBaseComponents = m_pBaseCS->CountComponents();
-  m_pCompMinMax = FX_Alloc2D(FX_FLOAT, m_nBaseComponents, 2);
-  FX_FLOAT defvalue;
-  for (int i = 0; i < m_nBaseComponents; i++) {
-    m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2],
-                               m_pCompMinMax[i * 2 + 1]);
-    m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2];
-  }
-  m_MaxIndex = pArray->GetIntegerAt(2);
-
-  CPDF_Object* pTableObj = pArray->GetElementValue(3);
-  if (!pTableObj)
-    return FALSE;
-
-  if (CPDF_String* pString = pTableObj->AsString()) {
-    m_Table = pString->GetString();
-  } else if (CPDF_Stream* pStream = pTableObj->AsStream()) {
-    CPDF_StreamAcc acc;
-    acc.LoadAllData(pStream, FALSE);
-    m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize());
-  }
-  return TRUE;
-}
-
-FX_BOOL CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf,
-                               FX_FLOAT& R,
-                               FX_FLOAT& G,
-                               FX_FLOAT& B) const {
-  int index = (int32_t)(*pBuf);
-  if (index < 0 || index > m_MaxIndex) {
-    return FALSE;
-  }
-  if (m_nBaseComponents) {
-    if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents ||
-        (index + 1) * m_nBaseComponents > (int)m_Table.GetLength()) {
-      R = G = B = 0;
-      return FALSE;
-    }
-  }
-  CFX_FixedBufGrow<FX_FLOAT, 16> Comps(m_nBaseComponents);
-  FX_FLOAT* comps = Comps;
-  const uint8_t* pTable = m_Table;
-  for (int i = 0; i < m_nBaseComponents; i++) {
-    comps[i] =
-        m_pCompMinMax[i * 2] +
-        m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255;
-  }
-  return m_pBaseCS->GetRGB(comps, R, G, B);
-}
-CPDF_ColorSpace* CPDF_IndexedCS::GetBaseCS() const {
-  return m_pBaseCS;
-}
-void CPDF_IndexedCS::EnableStdConversion(FX_BOOL bEnabled) {
-  CPDF_ColorSpace::EnableStdConversion(bEnabled);
-  if (m_pBaseCS) {
-    m_pBaseCS->EnableStdConversion(bEnabled);
-  }
-}
-
-#define MAX_PATTERN_COLORCOMPS 16
-struct PatternValue {
-  CPDF_Pattern* m_pPattern;
-  CPDF_CountedPattern* m_pCountedPattern;
-  int m_nComps;
-  FX_FLOAT m_Comps[MAX_PATTERN_COLORCOMPS];
-};
-
-CPDF_PatternCS::~CPDF_PatternCS() {
-  CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : NULL;
-  if (pCS && m_pDocument) {
-    m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
-  }
-}
-FX_BOOL CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-  CPDF_Object* pBaseCS = pArray->GetElementValue(1);
-  if (pBaseCS == m_pArray) {
-    return FALSE;
-  }
-  CPDF_DocPageData* pDocPageData = pDoc->GetPageData();
-  m_pBaseCS = pDocPageData->GetColorSpace(pBaseCS, NULL);
-  if (m_pBaseCS) {
-    if (m_pBaseCS->GetFamily() == PDFCS_PATTERN) {
-      return FALSE;
-    }
-    m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
-    m_nComponents = m_pBaseCS->CountComponents() + 1;
-    if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) {
-      return FALSE;
-    }
-  } else {
-    m_nComponents = 1;
-  }
-  return TRUE;
-}
-FX_BOOL CPDF_PatternCS::GetRGB(FX_FLOAT* pBuf,
-                               FX_FLOAT& R,
-                               FX_FLOAT& G,
-                               FX_FLOAT& B) const {
-  if (m_pBaseCS) {
-    ASSERT(m_pBaseCS->GetFamily() != PDFCS_PATTERN);
-    PatternValue* pvalue = (PatternValue*)pBuf;
-    if (m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B)) {
-      return TRUE;
-    }
-  }
-  R = G = B = 0.75f;
-  return FALSE;
-}
-CPDF_ColorSpace* CPDF_PatternCS::GetBaseCS() const {
-  return m_pBaseCS;
-}
-class CPDF_SeparationCS : public CPDF_ColorSpace {
- public:
-  explicit CPDF_SeparationCS(CPDF_Document* pDoc)
-      : CPDF_ColorSpace(pDoc, PDFCS_SEPARATION, 1),
-        m_pAltCS(nullptr),
-        m_pFunc(nullptr) {}
-  ~CPDF_SeparationCS() override;
-
-  // CPDF_ColorSpace:
-  void GetDefaultValue(int iComponent,
-                       FX_FLOAT& value,
-                       FX_FLOAT& min,
-                       FX_FLOAT& max) const override;
-  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
-  FX_BOOL GetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT& R,
-                 FX_FLOAT& G,
-                 FX_FLOAT& B) const override;
-  void EnableStdConversion(FX_BOOL bEnabled) override;
-
-  CPDF_ColorSpace* m_pAltCS;
-  CPDF_Function* m_pFunc;
-  enum { None, All, Colorant } m_Type;
-};
-CPDF_SeparationCS::~CPDF_SeparationCS() {
-  if (m_pAltCS) {
-    m_pAltCS->ReleaseCS();
-  }
-  delete m_pFunc;
-}
-void CPDF_SeparationCS::GetDefaultValue(int iComponent,
-                                        FX_FLOAT& value,
-                                        FX_FLOAT& min,
-                                        FX_FLOAT& max) const {
-  value = 1.0f;
-  min = 0;
-  max = 1.0f;
-}
-FX_BOOL CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-  CFX_ByteString name = pArray->GetStringAt(1);
-  if (name == "None") {
-    m_Type = None;
-  } else {
-    m_Type = Colorant;
-    CPDF_Object* pAltCS = pArray->GetElementValue(2);
-    if (pAltCS == m_pArray) {
-      return FALSE;
-    }
-    m_pAltCS = Load(pDoc, pAltCS);
-    if (!m_pAltCS) {
-      return FALSE;
-    }
-    CPDF_Object* pFuncObj = pArray->GetElementValue(3);
-    if (pFuncObj && !pFuncObj->IsName())
-      m_pFunc = CPDF_Function::Load(pFuncObj);
-
-    if (m_pFunc && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
-      delete m_pFunc;
-      m_pFunc = NULL;
-    }
-  }
-  return TRUE;
-}
-FX_BOOL CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf,
-                                  FX_FLOAT& R,
-                                  FX_FLOAT& G,
-                                  FX_FLOAT& B) const {
-  if (m_Type == None) {
-    return FALSE;
-  }
-  if (!m_pFunc) {
-    if (!m_pAltCS) {
-      return FALSE;
-    }
-    int nComps = m_pAltCS->CountComponents();
-    CFX_FixedBufGrow<FX_FLOAT, 16> results(nComps);
-    for (int i = 0; i < nComps; i++) {
-      results[i] = *pBuf;
-    }
-    return m_pAltCS->GetRGB(results, R, G, B);
-  }
-  CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
-  int nresults = 0;
-  m_pFunc->Call(pBuf, 1, results, nresults);
-  if (nresults == 0) {
-    return FALSE;
-  }
-  if (m_pAltCS) {
-    return m_pAltCS->GetRGB(results, R, G, B);
-  }
-  R = G = B = 0;
-  return FALSE;
-}
-void CPDF_SeparationCS::EnableStdConversion(FX_BOOL bEnabled) {
-  CPDF_ColorSpace::EnableStdConversion(bEnabled);
-  if (m_pAltCS) {
-    m_pAltCS->EnableStdConversion(bEnabled);
-  }
-}
-class CPDF_DeviceNCS : public CPDF_ColorSpace {
- public:
-  explicit CPDF_DeviceNCS(CPDF_Document* pDoc)
-      : CPDF_ColorSpace(pDoc, PDFCS_DEVICEN, 0),
-        m_pAltCS(nullptr),
-        m_pFunc(nullptr) {}
-  ~CPDF_DeviceNCS() override;
-
-  // CPDF_ColorSpace:
-  void GetDefaultValue(int iComponent,
-                       FX_FLOAT& value,
-                       FX_FLOAT& min,
-                       FX_FLOAT& max) const override;
-  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
-  FX_BOOL GetRGB(FX_FLOAT* pBuf,
-                 FX_FLOAT& R,
-                 FX_FLOAT& G,
-                 FX_FLOAT& B) const override;
-  void EnableStdConversion(FX_BOOL bEnabled) override;
-
-  CPDF_ColorSpace* m_pAltCS;
-  CPDF_Function* m_pFunc;
-};
-CPDF_DeviceNCS::~CPDF_DeviceNCS() {
-  delete m_pFunc;
-  if (m_pAltCS) {
-    m_pAltCS->ReleaseCS();
-  }
-}
-void CPDF_DeviceNCS::GetDefaultValue(int iComponent,
-                                     FX_FLOAT& value,
-                                     FX_FLOAT& min,
-                                     FX_FLOAT& max) const {
-  value = 1.0f;
-  min = 0;
-  max = 1.0f;
-}
-FX_BOOL CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-  CPDF_Array* pObj = ToArray(pArray->GetElementValue(1));
-  if (!pObj)
-    return FALSE;
-
-  m_nComponents = pObj->GetCount();
-  CPDF_Object* pAltCS = pArray->GetElementValue(2);
-  if (!pAltCS || pAltCS == m_pArray) {
-    return FALSE;
-  }
-  m_pAltCS = Load(pDoc, pAltCS);
-  m_pFunc = CPDF_Function::Load(pArray->GetElementValue(3));
-  if (!m_pAltCS || !m_pFunc) {
-    return FALSE;
-  }
-  if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) {
-    return FALSE;
-  }
-  return TRUE;
-}
-FX_BOOL CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf,
-                               FX_FLOAT& R,
-                               FX_FLOAT& G,
-                               FX_FLOAT& B) const {
-  if (!m_pFunc) {
-    return FALSE;
-  }
-  CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs());
-  int nresults = 0;
-  m_pFunc->Call(pBuf, m_nComponents, results, nresults);
-  if (nresults == 0) {
-    return FALSE;
-  }
-  return m_pAltCS->GetRGB(results, R, G, B);
-}
-void CPDF_DeviceNCS::EnableStdConversion(FX_BOOL bEnabled) {
-  CPDF_ColorSpace::EnableStdConversion(bEnabled);
-  if (m_pAltCS) {
-    m_pAltCS->EnableStdConversion(bEnabled);
-  }
-}
-
-CPDF_ColorSpace* CPDF_ColorSpace::GetStockCS(int family) {
-  return CPDF_ModuleMgr::Get()->GetPageModule()->GetStockCS(family);
-}
-
-CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name) {
-  if (name == "DeviceRGB" || name == "RGB") {
-    return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
-  }
-  if (name == "DeviceGray" || name == "G") {
-    return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
-  }
-  if (name == "DeviceCMYK" || name == "CMYK") {
-    return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
-  }
-  if (name == "Pattern") {
-    return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
-  }
-  return NULL;
-}
-CPDF_ColorSpace* CPDF_ColorSpace::Load(CPDF_Document* pDoc, CPDF_Object* pObj) {
-  if (!pObj)
-    return nullptr;
-  if (pObj->IsName())
-    return _CSFromName(pObj->GetString());
-
-  if (CPDF_Stream* pStream = pObj->AsStream()) {
-    CPDF_Dictionary* pDict = pStream->GetDict();
-    if (!pDict)
-      return nullptr;
-
-    for (const auto& it : *pDict) {
-      CPDF_ColorSpace* pRet = nullptr;
-      CPDF_Object* pValue = it.second;
-      if (ToName(pValue))
-        pRet = _CSFromName(pValue->GetString());
-      if (pRet)
-        return pRet;
-    }
-    return nullptr;
-  }
-
-  CPDF_Array* pArray = pObj->AsArray();
-  if (!pArray || pArray->GetCount() == 0)
-    return nullptr;
-
-  CPDF_Object* pFamilyObj = pArray->GetElementValue(0);
-  if (!pFamilyObj)
-    return nullptr;
-
-  CFX_ByteString familyname = pFamilyObj->GetString();
-  if (pArray->GetCount() == 1)
-    return _CSFromName(familyname);
-
-  CPDF_ColorSpace* pCS = NULL;
-  FX_DWORD id = familyname.GetID();
-  if (id == FXBSTR_ID('C', 'a', 'l', 'G')) {
-    pCS = new CPDF_CalGray(pDoc);
-  } else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) {
-    pCS = new CPDF_CalRGB(pDoc);
-  } else if (id == FXBSTR_ID('L', 'a', 'b', 0)) {
-    pCS = new CPDF_LabCS(pDoc);
-  } else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) {
-    pCS = new CPDF_ICCBasedCS(pDoc);
-  } else if (id == FXBSTR_ID('I', 'n', 'd', 'e') ||
-             id == FXBSTR_ID('I', 0, 0, 0)) {
-    pCS = new CPDF_IndexedCS(pDoc);
-  } else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) {
-    pCS = new CPDF_SeparationCS(pDoc);
-  } else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) {
-    pCS = new CPDF_DeviceNCS(pDoc);
-  } else if (id == FXBSTR_ID('P', 'a', 't', 't')) {
-    pCS = new CPDF_PatternCS(pDoc);
-  } else {
-    return NULL;
-  }
-  pCS->m_pArray = pArray;
-  if (!pCS->v_Load(pDoc, pArray)) {
-    pCS->ReleaseCS();
-    return NULL;
-  }
-  return pCS;
-}
-void CPDF_ColorSpace::ReleaseCS() {
-  if (this == GetStockCS(PDFCS_DEVICERGB)) {
-    return;
-  }
-  if (this == GetStockCS(PDFCS_DEVICEGRAY)) {
-    return;
-  }
-  if (this == GetStockCS(PDFCS_DEVICECMYK)) {
-    return;
-  }
-  if (this == GetStockCS(PDFCS_PATTERN)) {
-    return;
-  }
-  delete this;
-}
-int CPDF_ColorSpace::GetBufSize() const {
-  if (m_Family == PDFCS_PATTERN) {
-    return sizeof(PatternValue);
-  }
-  return m_nComponents * sizeof(FX_FLOAT);
-}
-FX_FLOAT* CPDF_ColorSpace::CreateBuf() {
-  int size = GetBufSize();
-  uint8_t* pBuf = FX_Alloc(uint8_t, size);
-  return (FX_FLOAT*)pBuf;
-}
-FX_BOOL CPDF_ColorSpace::sRGB() const {
-  if (m_Family == PDFCS_DEVICERGB) {
-    return TRUE;
-  }
-  if (m_Family != PDFCS_ICCBASED) {
-    return FALSE;
-  }
-  CPDF_ICCBasedCS* pCS = (CPDF_ICCBasedCS*)this;
-  return pCS->m_pProfile->m_bsRGB;
-}
-FX_BOOL CPDF_ColorSpace::GetCMYK(FX_FLOAT* pBuf,
-                                 FX_FLOAT& c,
-                                 FX_FLOAT& m,
-                                 FX_FLOAT& y,
-                                 FX_FLOAT& k) const {
-  if (v_GetCMYK(pBuf, c, m, y, k)) {
-    return TRUE;
-  }
-  FX_FLOAT R, G, B;
-  if (!GetRGB(pBuf, R, G, B)) {
-    return FALSE;
-  }
-  sRGB_to_AdobeCMYK(R, G, B, c, m, y, k);
-  return TRUE;
-}
-FX_BOOL CPDF_ColorSpace::SetCMYK(FX_FLOAT* pBuf,
-                                 FX_FLOAT c,
-                                 FX_FLOAT m,
-                                 FX_FLOAT y,
-                                 FX_FLOAT k) const {
-  if (v_SetCMYK(pBuf, c, m, y, k)) {
-    return TRUE;
-  }
-  FX_FLOAT R, G, B;
-  AdobeCMYK_to_sRGB(c, m, y, k, R, G, B);
-  return SetRGB(pBuf, R, G, B);
-}
-void CPDF_ColorSpace::GetDefaultColor(FX_FLOAT* buf) const {
-  if (!buf || m_Family == PDFCS_PATTERN) {
-    return;
-  }
-  FX_FLOAT min, max;
-  for (int i = 0; i < m_nComponents; i++) {
-    GetDefaultValue(i, buf[i], min, max);
-  }
-}
-int CPDF_ColorSpace::GetMaxIndex() const {
-  if (m_Family != PDFCS_INDEXED) {
-    return 0;
-  }
-  CPDF_IndexedCS* pCS = (CPDF_IndexedCS*)this;
-  return pCS->m_MaxIndex;
-}
-void CPDF_ColorSpace::TranslateImageLine(uint8_t* dest_buf,
-                                         const uint8_t* src_buf,
-                                         int pixels,
-                                         int image_width,
-                                         int image_height,
-                                         FX_BOOL bTransMask) const {
-  CFX_FixedBufGrow<FX_FLOAT, 16> srcbuf(m_nComponents);
-  FX_FLOAT* src = srcbuf;
-  FX_FLOAT R, G, B;
-  for (int i = 0; i < pixels; i++) {
-    for (int j = 0; j < m_nComponents; j++)
-      if (m_Family == PDFCS_INDEXED) {
-        src[j] = (FX_FLOAT)(*src_buf++);
-      } else {
-        src[j] = (FX_FLOAT)(*src_buf++) / 255;
-      }
-    GetRGB(src, R, G, B);
-    *dest_buf++ = (int32_t)(B * 255);
-    *dest_buf++ = (int32_t)(G * 255);
-    *dest_buf++ = (int32_t)(R * 255);
-  }
-}
-void CPDF_ColorSpace::EnableStdConversion(FX_BOOL bEnabled) {
-  if (bEnabled) {
-    m_dwStdConversion++;
-  } else if (m_dwStdConversion) {
-    m_dwStdConversion--;
-  }
-}
-CPDF_Color::CPDF_Color(int family) {
-  m_pCS = CPDF_ColorSpace::GetStockCS(family);
-  int nComps = 3;
-  if (family == PDFCS_DEVICEGRAY) {
-    nComps = 1;
-  } else if (family == PDFCS_DEVICECMYK) {
-    nComps = 4;
-  }
-  m_pBuffer = FX_Alloc(FX_FLOAT, nComps);
-  for (int i = 0; i < nComps; i++) {
-    m_pBuffer[i] = 0;
-  }
-}
-CPDF_Color::~CPDF_Color() {
-  ReleaseBuffer();
-  ReleaseColorSpace();
-}
-void CPDF_Color::ReleaseBuffer() {
-  if (!m_pBuffer) {
-    return;
-  }
-  if (m_pCS->GetFamily() == PDFCS_PATTERN) {
-    PatternValue* pvalue = (PatternValue*)m_pBuffer;
-    CPDF_Pattern* pPattern =
-        pvalue->m_pCountedPattern ? pvalue->m_pCountedPattern->get() : NULL;
-    if (pPattern && pPattern->m_pDocument) {
-      CPDF_DocPageData* pPageData = pPattern->m_pDocument->GetPageData();
-      if (pPageData) {
-        pPageData->ReleasePattern(pPattern->m_pPatternObj);
-      }
-    }
-  }
-  FX_Free(m_pBuffer);
-  m_pBuffer = NULL;
-}
-void CPDF_Color::ReleaseColorSpace() {
-  if (m_pCS && m_pCS->m_pDocument && m_pCS->GetArray()) {
-    m_pCS->m_pDocument->GetPageData()->ReleaseColorSpace(m_pCS->GetArray());
-    m_pCS = NULL;
-  }
-}
-void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS) {
-  if (m_pCS == pCS) {
-    if (!m_pBuffer) {
-      m_pBuffer = pCS->CreateBuf();
-    }
-    ReleaseColorSpace();
-    m_pCS = pCS;
-    return;
-  }
-  ReleaseBuffer();
-  ReleaseColorSpace();
-  m_pCS = pCS;
-  if (m_pCS) {
-    m_pBuffer = pCS->CreateBuf();
-    pCS->GetDefaultColor(m_pBuffer);
-  }
-}
-void CPDF_Color::SetValue(FX_FLOAT* comps) {
-  if (!m_pBuffer) {
-    return;
-  }
-  if (m_pCS->GetFamily() != PDFCS_PATTERN) {
-    FXSYS_memcpy(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(FX_FLOAT));
-  }
-}
-void CPDF_Color::SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comps, int ncomps) {
-  if (ncomps > MAX_PATTERN_COLORCOMPS) {
-    return;
-  }
-  if (!m_pCS || m_pCS->GetFamily() != PDFCS_PATTERN) {
-    FX_Free(m_pBuffer);
-    m_pCS = CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
-    m_pBuffer = m_pCS->CreateBuf();
-  }
-  CPDF_DocPageData* pDocPageData = NULL;
-  PatternValue* pvalue = (PatternValue*)m_pBuffer;
-  if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
-    pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData();
-    if (pDocPageData) {
-      pDocPageData->ReleasePattern(pvalue->m_pPattern->m_pPatternObj);
-    }
-  }
-  pvalue->m_nComps = ncomps;
-  pvalue->m_pPattern = pPattern;
-  if (ncomps) {
-    FXSYS_memcpy(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT));
-  }
-  pvalue->m_pCountedPattern = NULL;
-  if (pPattern && pPattern->m_pDocument) {
-    if (!pDocPageData) {
-      pDocPageData = pPattern->m_pDocument->GetPageData();
-    }
-    pvalue->m_pCountedPattern =
-        pDocPageData->FindPatternPtr(pPattern->m_pPatternObj);
-  }
-}
-void CPDF_Color::Copy(const CPDF_Color* pSrc) {
-  ReleaseBuffer();
-  ReleaseColorSpace();
-  m_pCS = pSrc->m_pCS;
-  if (m_pCS && m_pCS->m_pDocument) {
-    CPDF_Array* pArray = m_pCS->GetArray();
-    if (pArray) {
-      m_pCS = m_pCS->m_pDocument->GetPageData()->GetCopiedColorSpace(pArray);
-    }
-  }
-  if (!m_pCS) {
-    return;
-  }
-  m_pBuffer = m_pCS->CreateBuf();
-  FXSYS_memcpy(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize());
-  if (m_pCS->GetFamily() == PDFCS_PATTERN) {
-    PatternValue* pvalue = (PatternValue*)m_pBuffer;
-    if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
-      pvalue->m_pPattern =
-          pvalue->m_pPattern->m_pDocument->GetPageData()->GetPattern(
-              pvalue->m_pPattern->m_pPatternObj, FALSE,
-              &pvalue->m_pPattern->m_ParentMatrix);
-    }
-  }
-}
-FX_BOOL CPDF_Color::GetRGB(int& R, int& G, int& B) const {
-  if (!m_pCS || !m_pBuffer) {
-    return FALSE;
-  }
-  FX_FLOAT r = 0.0f, g = 0.0f, b = 0.0f;
-  if (!m_pCS->GetRGB(m_pBuffer, r, g, b)) {
-    return FALSE;
-  }
-  R = (int32_t)(r * 255 + 0.5f);
-  G = (int32_t)(g * 255 + 0.5f);
-  B = (int32_t)(b * 255 + 0.5f);
-  return TRUE;
-}
-CPDF_Pattern* CPDF_Color::GetPattern() const {
-  if (!m_pBuffer || m_pCS->GetFamily() != PDFCS_PATTERN) {
-    return NULL;
-  }
-  PatternValue* pvalue = (PatternValue*)m_pBuffer;
-  return pvalue->m_pPattern;
-}
-CPDF_ColorSpace* CPDF_Color::GetPatternCS() const {
-  if (!m_pBuffer || m_pCS->GetFamily() != PDFCS_PATTERN) {
-    return NULL;
-  }
-  return m_pCS->GetBaseCS();
-}
-FX_FLOAT* CPDF_Color::GetPatternColor() const {
-  if (!m_pBuffer || m_pCS->GetFamily() != PDFCS_PATTERN) {
-    return NULL;
-  }
-  PatternValue* pvalue = (PatternValue*)m_pBuffer;
-  return pvalue->m_nComps ? pvalue->m_Comps : NULL;
-}
-FX_BOOL CPDF_Color::IsEqual(const CPDF_Color& other) const {
-  return m_pCS && m_pCS == other.m_pCS &&
-         FXSYS_memcmp(m_pBuffer, other.m_pBuffer, m_pCS->GetBufSize()) == 0;
-}
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_doc.cpp b/core/fpdfapi/fpdf_page/fpdf_page_doc.cpp
index 0d0c373..2e68702 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_doc.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_doc.cpp
@@ -7,10 +7,16 @@
 #include "core/fpdfapi/fpdf_page/pageint.h"
 
 #include "core/fdrm/crypto/include/fx_crypt.h"
+#include "core/fpdfapi/fpdf_font/cpdf_type1font.h"
 #include "core/fpdfapi/fpdf_font/font_int.h"
+#include "core/fpdfapi/fpdf_page/cpdf_pattern.h"
+#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
+#include "core/fpdfapi/fpdf_page/cpdf_tilingpattern.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
 #include "core/fpdfapi/ipdf_pagemodule.h"
 
@@ -91,7 +97,6 @@
   return GetValidatePageData()->GetFontFileStreamAcc(pStream);
 }
 
-CPDF_ColorSpace* _CSFromName(const CFX_ByteString& name);
 CPDF_ColorSpace* CPDF_Document::LoadColorSpace(CPDF_Object* pCSObj,
                                                CPDF_Dictionary* pResources) {
   return GetValidatePageData()->GetColorSpace(pCSObj, pResources);
@@ -322,7 +327,7 @@
 
   if (pCSObj->IsName()) {
     CFX_ByteString name = pCSObj->GetConstString();
-    CPDF_ColorSpace* pCS = _CSFromName(name);
+    CPDF_ColorSpace* pCS = CPDF_ColorSpace::ColorspaceFromName(name);
     if (!pCS && pResources) {
       CPDF_Dictionary* pList = pResources->GetDictBy("ColorSpace");
       if (pList) {
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_func.cpp b/core/fpdfapi/fpdf_page/fpdf_page_func.cpp
index cea7d6b..96aad6d 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_func.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_func.cpp
@@ -15,6 +15,8 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fxcrt/include/fx_safe_types.h"
 #include "third_party/base/numerics/safe_conversions_impl.h"
 
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_image.cpp b/core/fpdfapi/fpdf_page/fpdf_page_image.cpp
deleted file mode 100644
index f668236..0000000
--- a/core/fpdfapi/fpdf_page/fpdf_page_image.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 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.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "core/fpdfapi/fpdf_page/pageint.h"
-
-#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
-#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
-
-void CPDF_Image::Release() {
-  if (m_bInline || (m_pStream && m_pStream->GetObjNum() == 0)) {
-    delete this;
-  }
-}
-CPDF_Image* CPDF_Image::Clone() {
-  if (m_pStream->GetObjNum())
-    return m_pDocument->GetPageData()->GetImage(m_pStream);
-
-  CPDF_Image* pImage = new CPDF_Image(m_pDocument);
-  pImage->LoadImageF(ToStream(m_pStream->Clone()), m_bInline);
-  if (m_bInline)
-    pImage->SetInlineDict(ToDictionary(m_pInlineDict->Clone(TRUE)));
-
-  return pImage;
-}
-CPDF_Image::CPDF_Image(CPDF_Document* pDoc) {
-  m_pDocument = pDoc;
-  m_pStream = NULL;
-  m_pOC = NULL;
-  m_bInline = FALSE;
-  m_pInlineDict = NULL;
-  m_pDIBSource = NULL;
-  m_pMask = NULL;
-  m_MatteColor = 0;
-}
-CPDF_Image::~CPDF_Image() {
-  if (m_bInline) {
-    if (m_pStream) {
-      m_pStream->Release();
-    }
-    if (m_pInlineDict) {
-      m_pInlineDict->Release();
-    }
-  }
-}
-FX_BOOL CPDF_Image::LoadImageF(CPDF_Stream* pStream, FX_BOOL bInline) {
-  m_pStream = pStream;
-  if (m_bInline && m_pInlineDict) {
-    m_pInlineDict->Release();
-    m_pInlineDict = NULL;
-  }
-  m_bInline = bInline;
-  CPDF_Dictionary* pDict = pStream->GetDict();
-  if (m_bInline) {
-    m_pInlineDict = ToDictionary(pDict->Clone());
-  }
-  m_pOC = pDict->GetDictBy("OC");
-  m_bIsMask =
-      !pDict->KeyExist("ColorSpace") || pDict->GetIntegerBy("ImageMask");
-  m_bInterpolate = pDict->GetIntegerBy("Interpolate");
-  m_Height = pDict->GetIntegerBy("Height");
-  m_Width = pDict->GetIntegerBy("Width");
-  return TRUE;
-}
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
index 700103e..63c84bb 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
@@ -9,9 +9,13 @@
 #include <vector>
 
 #include "core/fpdfapi/fpdf_edit/include/cpdf_creator.h"
+#include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_page/cpdf_allstates.h"
+#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_formobject.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pathobject.h"
@@ -23,6 +27,8 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_name.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
 
 namespace {
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp b/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
index c0d7c08..0421104 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
@@ -8,6 +8,7 @@
 
 #include <limits.h>
 
+#include "core/fpdfapi/fpdf_font/cpdf_type3char.h"
 #include "core/fpdfapi/fpdf_page/cpdf_allstates.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
@@ -21,6 +22,8 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_name.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_pattern.cpp b/core/fpdfapi/fpdf_page/fpdf_page_pattern.cpp
index fbb2c28..822d06d 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_pattern.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_pattern.cpp
@@ -8,10 +8,13 @@
 
 #include <algorithm>
 
+#include "core/fpdfapi/fpdf_page/cpdf_meshstream.h"
+#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
 
 namespace {
 
@@ -22,245 +25,9 @@
 const int kSingleColorPerPatch = 1;
 const int kQuadColorsPerPatch = 4;
 
-ShadingType ToShadingType(int type) {
-  return (type > static_cast<int>(kInvalidShading) &&
-          type < static_cast<int>(kMaxShading))
-             ? static_cast<ShadingType>(type)
-             : kInvalidShading;
-}
-
 }  // namespace
 
-CPDF_Pattern::CPDF_Pattern(PatternType type,
-                           CPDF_Document* pDoc,
-                           CPDF_Object* pObj,
-                           const CFX_Matrix* pParentMatrix)
-    : m_PatternType(type),
-      m_pDocument(pDoc),
-      m_pPatternObj(pObj),
-      m_bForceClear(FALSE) {
-  if (pParentMatrix)
-    m_ParentMatrix = *pParentMatrix;
-}
-CPDF_Pattern::~CPDF_Pattern() {}
-CPDF_TilingPattern::CPDF_TilingPattern(CPDF_Document* pDoc,
-                                       CPDF_Object* pPatternObj,
-                                       const CFX_Matrix* parentMatrix)
-    : CPDF_Pattern(TILING, pDoc, pPatternObj, parentMatrix) {
-  CPDF_Dictionary* pDict = m_pPatternObj->GetDict();
-  m_Pattern2Form = pDict->GetMatrixBy("Matrix");
-  m_bColored = pDict->GetIntegerBy("PaintType") == 1;
-  if (parentMatrix) {
-    m_Pattern2Form.Concat(*parentMatrix);
-  }
-  m_pForm = NULL;
-}
-CPDF_TilingPattern::~CPDF_TilingPattern() {
-  delete m_pForm;
-  m_pForm = NULL;
-}
-FX_BOOL CPDF_TilingPattern::Load() {
-  if (m_pForm)
-    return TRUE;
 
-  CPDF_Dictionary* pDict = m_pPatternObj->GetDict();
-  if (!pDict)
-    return FALSE;
-
-  m_bColored = pDict->GetIntegerBy("PaintType") == 1;
-  m_XStep = (FX_FLOAT)FXSYS_fabs(pDict->GetNumberBy("XStep"));
-  m_YStep = (FX_FLOAT)FXSYS_fabs(pDict->GetNumberBy("YStep"));
-
-  CPDF_Stream* pStream = m_pPatternObj->AsStream();
-  if (!pStream)
-    return FALSE;
-
-  m_pForm = new CPDF_Form(m_pDocument, NULL, pStream);
-  m_pForm->ParseContent(NULL, &m_ParentMatrix, NULL, NULL);
-  m_BBox = pDict->GetRectBy("BBox");
-  return TRUE;
-}
-CPDF_ShadingPattern::CPDF_ShadingPattern(CPDF_Document* pDoc,
-                                         CPDF_Object* pPatternObj,
-                                         FX_BOOL bShading,
-                                         const CFX_Matrix* parentMatrix)
-    : CPDF_Pattern(SHADING,
-                   pDoc,
-                   bShading ? nullptr : pPatternObj,
-                   parentMatrix),
-      m_ShadingType(kInvalidShading),
-      m_bShadingObj(bShading),
-      m_pShadingObj(pPatternObj),
-      m_pCS(nullptr),
-      m_pCountedCS(nullptr),
-      m_nFuncs(0) {
-  if (!bShading) {
-    CPDF_Dictionary* pDict = m_pPatternObj->GetDict();
-    m_Pattern2Form = pDict->GetMatrixBy("Matrix");
-    m_pShadingObj = pDict->GetElementValue("Shading");
-    if (parentMatrix)
-      m_Pattern2Form.Concat(*parentMatrix);
-  }
-  for (int i = 0; i < FX_ArraySize(m_pFunctions); ++i)
-    m_pFunctions[i] = nullptr;
-}
-
-CPDF_ShadingPattern::~CPDF_ShadingPattern() {
-  for (int i = 0; i < m_nFuncs; ++i)
-    delete m_pFunctions[i];
-
-  CPDF_ColorSpace* pCS = m_pCountedCS ? m_pCountedCS->get() : NULL;
-  if (pCS && m_pDocument)
-    m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
-}
-
-FX_BOOL CPDF_ShadingPattern::Load() {
-  if (m_ShadingType != kInvalidShading)
-    return TRUE;
-
-  CPDF_Dictionary* pShadingDict =
-      m_pShadingObj ? m_pShadingObj->GetDict() : NULL;
-  if (!pShadingDict) {
-    return FALSE;
-  }
-  if (m_nFuncs) {
-    for (int i = 0; i < m_nFuncs; i++)
-      delete m_pFunctions[i];
-    m_nFuncs = 0;
-  }
-  CPDF_Object* pFunc = pShadingDict->GetElementValue("Function");
-  if (pFunc) {
-    if (CPDF_Array* pArray = pFunc->AsArray()) {
-      m_nFuncs = std::min<int>(pArray->GetCount(), 4);
-
-      for (int i = 0; i < m_nFuncs; i++) {
-        m_pFunctions[i] = CPDF_Function::Load(pArray->GetElementValue(i));
-      }
-    } else {
-      m_pFunctions[0] = CPDF_Function::Load(pFunc);
-      m_nFuncs = 1;
-    }
-  }
-  CPDF_Object* pCSObj = pShadingDict->GetElementValue("ColorSpace");
-  if (!pCSObj) {
-    return FALSE;
-  }
-  CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData();
-  m_pCS = pDocPageData->GetColorSpace(pCSObj, NULL);
-  if (m_pCS) {
-    m_pCountedCS = pDocPageData->FindColorSpacePtr(m_pCS->GetArray());
-  }
-
-  m_ShadingType = ToShadingType(pShadingDict->GetIntegerBy("ShadingType"));
-
-  // We expect to have a stream if our shading type is a mesh.
-  if (IsMeshShading() && !ToStream(m_pShadingObj))
-    return FALSE;
-
-  return TRUE;
-}
-FX_BOOL CPDF_MeshStream::Load(CPDF_Stream* pShadingStream,
-                              CPDF_Function** pFuncs,
-                              int nFuncs,
-                              CPDF_ColorSpace* pCS) {
-  m_Stream.LoadAllData(pShadingStream);
-  m_BitStream.Init(m_Stream.GetData(), m_Stream.GetSize());
-  m_pFuncs = pFuncs;
-  m_nFuncs = nFuncs;
-  m_pCS = pCS;
-  CPDF_Dictionary* pDict = pShadingStream->GetDict();
-  m_nCoordBits = pDict->GetIntegerBy("BitsPerCoordinate");
-  m_nCompBits = pDict->GetIntegerBy("BitsPerComponent");
-  m_nFlagBits = pDict->GetIntegerBy("BitsPerFlag");
-  if (!m_nCoordBits || !m_nCompBits) {
-    return FALSE;
-  }
-  FX_DWORD nComps = pCS->CountComponents();
-  if (nComps > 8) {
-    return FALSE;
-  }
-  m_nComps = nFuncs ? 1 : nComps;
-  if (((int)m_nComps < 0) || m_nComps > 8) {
-    return FALSE;
-  }
-  m_CoordMax = m_nCoordBits == 32 ? -1 : (1 << m_nCoordBits) - 1;
-  m_CompMax = (1 << m_nCompBits) - 1;
-  CPDF_Array* pDecode = pDict->GetArrayBy("Decode");
-  if (!pDecode || pDecode->GetCount() != 4 + m_nComps * 2) {
-    return FALSE;
-  }
-  m_xmin = pDecode->GetNumberAt(0);
-  m_xmax = pDecode->GetNumberAt(1);
-  m_ymin = pDecode->GetNumberAt(2);
-  m_ymax = pDecode->GetNumberAt(3);
-  for (FX_DWORD i = 0; i < m_nComps; i++) {
-    m_ColorMin[i] = pDecode->GetNumberAt(i * 2 + 4);
-    m_ColorMax[i] = pDecode->GetNumberAt(i * 2 + 5);
-  }
-  return TRUE;
-}
-FX_DWORD CPDF_MeshStream::GetFlag() {
-  return m_BitStream.GetBits(m_nFlagBits) & 0x03;
-}
-void CPDF_MeshStream::GetCoords(FX_FLOAT& x, FX_FLOAT& y) {
-  if (m_nCoordBits == 32) {
-    x = m_xmin + (FX_FLOAT)(m_BitStream.GetBits(m_nCoordBits) *
-                            (m_xmax - m_xmin) / (double)m_CoordMax);
-    y = m_ymin + (FX_FLOAT)(m_BitStream.GetBits(m_nCoordBits) *
-                            (m_ymax - m_ymin) / (double)m_CoordMax);
-  } else {
-    x = m_xmin +
-        m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) / m_CoordMax;
-    y = m_ymin +
-        m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) / m_CoordMax;
-  }
-}
-void CPDF_MeshStream::GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b) {
-  FX_DWORD i;
-  FX_FLOAT color_value[8];
-  for (i = 0; i < m_nComps; i++) {
-    color_value[i] = m_ColorMin[i] +
-                     m_BitStream.GetBits(m_nCompBits) *
-                         (m_ColorMax[i] - m_ColorMin[i]) / m_CompMax;
-  }
-  if (m_nFuncs) {
-    static const int kMaxResults = 8;
-    FX_FLOAT result[kMaxResults];
-    int nResults;
-    FXSYS_memset(result, 0, sizeof(result));
-    for (FX_DWORD i = 0; i < m_nFuncs; i++) {
-      if (m_pFuncs[i] && m_pFuncs[i]->CountOutputs() <= kMaxResults) {
-        m_pFuncs[i]->Call(color_value, 1, result, nResults);
-      }
-    }
-    m_pCS->GetRGB(result, r, g, b);
-  } else {
-    m_pCS->GetRGB(color_value, r, g, b);
-  }
-}
-FX_DWORD CPDF_MeshStream::GetVertex(CPDF_MeshVertex& vertex,
-                                    CFX_Matrix* pObject2Bitmap) {
-  FX_DWORD flag = GetFlag();
-  GetCoords(vertex.x, vertex.y);
-  pObject2Bitmap->Transform(vertex.x, vertex.y);
-  GetColor(vertex.r, vertex.g, vertex.b);
-  m_BitStream.ByteAlign();
-  return flag;
-}
-FX_BOOL CPDF_MeshStream::GetVertexRow(CPDF_MeshVertex* vertex,
-                                      int count,
-                                      CFX_Matrix* pObject2Bitmap) {
-  for (int i = 0; i < count; i++) {
-    if (m_BitStream.IsEOF()) {
-      return FALSE;
-    }
-    GetCoords(vertex[i].x, vertex[i].y);
-    pObject2Bitmap->Transform(vertex[i].x, vertex[i].y);
-    GetColor(vertex[i].r, vertex[i].g, vertex[i].b);
-    m_BitStream.ByteAlign();
-  }
-  return TRUE;
-}
 
 CFX_FloatRect GetShadingBBox(CPDF_Stream* pStream,
                              ShadingType type,
diff --git a/core/fpdfapi/fpdf_page/include/cpdf_color.h b/core/fpdfapi/fpdf_page/include/cpdf_color.h
new file mode 100644
index 0000000..9e20684
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/include/cpdf_color.h
@@ -0,0 +1,47 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_COLOR_H_
+#define CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_COLOR_H_
+
+#include "core/fpdfapi/fpdf_page/include/cpdf_colorspace.h"
+#include "core/fxcrt/include/fx_system.h"
+
+class CPDF_Pattern;
+
+class CPDF_Color {
+ public:
+  CPDF_Color() : m_pCS(nullptr), m_pBuffer(nullptr) {}
+  explicit CPDF_Color(int family);
+  ~CPDF_Color();
+
+  FX_BOOL IsNull() const { return !m_pBuffer; }
+  FX_BOOL IsEqual(const CPDF_Color& other) const;
+  FX_BOOL IsPattern() const {
+    return m_pCS && m_pCS->GetFamily() == PDFCS_PATTERN;
+  }
+
+  void Copy(const CPDF_Color* pSrc);
+
+  void SetColorSpace(CPDF_ColorSpace* pCS);
+  void SetValue(FX_FLOAT* comp);
+  void SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comp, int ncomps);
+
+  FX_BOOL GetRGB(int& R, int& G, int& B) const;
+  CPDF_Pattern* GetPattern() const;
+  CPDF_ColorSpace* GetPatternCS() const;
+  FX_FLOAT* GetPatternColor() const;
+
+  CPDF_ColorSpace* m_pCS;
+
+ protected:
+  void ReleaseBuffer();
+  void ReleaseColorSpace();
+
+  FX_FLOAT* m_pBuffer;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_COLOR_H_
diff --git a/core/fpdfapi/fpdf_page/include/cpdf_colorspace.h b/core/fpdfapi/fpdf_page/include/cpdf_colorspace.h
new file mode 100644
index 0000000..afdd71d
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/include/cpdf_colorspace.h
@@ -0,0 +1,122 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_COLORSPACE_H_
+#define CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_COLORSPACE_H_
+
+#include "core/fxcrt/include/fx_string.h"
+#include "core/fxcrt/include/fx_system.h"
+
+#define PDFCS_DEVICEGRAY 1
+#define PDFCS_DEVICERGB 2
+#define PDFCS_DEVICECMYK 3
+#define PDFCS_CALGRAY 4
+#define PDFCS_CALRGB 5
+#define PDFCS_LAB 6
+#define PDFCS_ICCBASED 7
+#define PDFCS_SEPARATION 8
+#define PDFCS_DEVICEN 9
+#define PDFCS_INDEXED 10
+#define PDFCS_PATTERN 11
+
+class CPDF_Array;
+class CPDF_Document;
+class CPDF_Object;
+
+class CPDF_ColorSpace {
+ public:
+  static CPDF_ColorSpace* GetStockCS(int Family);
+  static CPDF_ColorSpace* Load(CPDF_Document* pDoc, CPDF_Object* pCSObj);
+  static CPDF_ColorSpace* ColorspaceFromName(const CFX_ByteString& name);
+
+  void ReleaseCS();
+
+  int GetBufSize() const;
+  FX_FLOAT* CreateBuf();
+  void GetDefaultColor(FX_FLOAT* buf) const;
+  FX_DWORD CountComponents() const { return m_nComponents; }
+  int GetFamily() const { return m_Family; }
+  virtual void GetDefaultValue(int iComponent,
+                               FX_FLOAT& value,
+                               FX_FLOAT& min,
+                               FX_FLOAT& max) const {
+    value = 0;
+    min = 0;
+    max = 1.0f;
+  }
+
+  FX_BOOL sRGB() const;
+  virtual FX_BOOL GetRGB(FX_FLOAT* pBuf,
+                         FX_FLOAT& R,
+                         FX_FLOAT& G,
+                         FX_FLOAT& B) const = 0;
+  virtual FX_BOOL SetRGB(FX_FLOAT* pBuf,
+                         FX_FLOAT R,
+                         FX_FLOAT G,
+                         FX_FLOAT B) const {
+    return FALSE;
+  }
+
+  FX_BOOL GetCMYK(FX_FLOAT* pBuf,
+                  FX_FLOAT& c,
+                  FX_FLOAT& m,
+                  FX_FLOAT& y,
+                  FX_FLOAT& k) const;
+  FX_BOOL SetCMYK(FX_FLOAT* pBuf,
+                  FX_FLOAT c,
+                  FX_FLOAT m,
+                  FX_FLOAT y,
+                  FX_FLOAT k) const;
+
+  virtual void TranslateImageLine(uint8_t* dest_buf,
+                                  const uint8_t* src_buf,
+                                  int pixels,
+                                  int image_width,
+                                  int image_height,
+                                  FX_BOOL bTransMask = FALSE) const;
+
+  CPDF_Array*& GetArray() { return m_pArray; }
+  int GetMaxIndex() const;
+  virtual CPDF_ColorSpace* GetBaseCS() const { return NULL; }
+
+  virtual void EnableStdConversion(FX_BOOL bEnabled);
+
+  CPDF_Document* const m_pDocument;
+
+ protected:
+  CPDF_ColorSpace(CPDF_Document* pDoc, int family, FX_DWORD nComponents)
+      : m_pDocument(pDoc),
+        m_Family(family),
+        m_nComponents(nComponents),
+        m_pArray(nullptr),
+        m_dwStdConversion(0) {}
+  virtual ~CPDF_ColorSpace() {}
+
+  virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
+    return TRUE;
+  }
+  virtual FX_BOOL v_GetCMYK(FX_FLOAT* pBuf,
+                            FX_FLOAT& c,
+                            FX_FLOAT& m,
+                            FX_FLOAT& y,
+                            FX_FLOAT& k) const {
+    return FALSE;
+  }
+  virtual FX_BOOL v_SetCMYK(FX_FLOAT* pBuf,
+                            FX_FLOAT c,
+                            FX_FLOAT m,
+                            FX_FLOAT y,
+                            FX_FLOAT k) const {
+    return FALSE;
+  }
+
+  int m_Family;
+  FX_DWORD m_nComponents;
+  CPDF_Array* m_pArray;
+  FX_DWORD m_dwStdConversion;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_COLORSPACE_H_
diff --git a/core/fpdfapi/fpdf_page/include/cpdf_formobject.h b/core/fpdfapi/fpdf_page/include/cpdf_formobject.h
index 234cd73..b12d68c 100644
--- a/core/fpdfapi/fpdf_page/include/cpdf_formobject.h
+++ b/core/fpdfapi/fpdf_page/include/cpdf_formobject.h
@@ -10,7 +10,7 @@
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fxcrt/include/fx_coordinates.h"
 
-class Form;
+class CPDF_Form;
 
 class CPDF_FormObject : public CPDF_PageObject {
  public:
diff --git a/core/fpdfapi/fpdf_page/include/cpdf_image.h b/core/fpdfapi/fpdf_page/include/cpdf_image.h
new file mode 100644
index 0000000..048b86d
--- /dev/null
+++ b/core/fpdfapi/fpdf_page/include/cpdf_image.h
@@ -0,0 +1,98 @@
+// Copyright 2016 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_IMAGE_H_
+#define CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_IMAGE_H_
+
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fxcrt/include/fx_system.h"
+
+#define PDF_IMAGE_NO_COMPRESS 0x0000
+#define PDF_IMAGE_LOSSY_COMPRESS 0x0001
+#define PDF_IMAGE_LOSSLESS_COMPRESS 0x0002
+#define PDF_IMAGE_MASK_LOSSY_COMPRESS 0x0004
+#define PDF_IMAGE_MASK_LOSSLESS_COMPRESS 0x0008
+
+class CFX_DIBitmap;
+class CFX_DIBSource;
+class CPDF_Dictionay;
+class CPDF_Document;
+class CPDF_Page;
+class IFX_FileRead;
+class IFX_FileWrite;
+class IFX_Pause;
+
+class CPDF_Image {
+ public:
+  explicit CPDF_Image(CPDF_Document* pDoc);
+  ~CPDF_Image();
+
+  FX_BOOL LoadImageF(CPDF_Stream* pImageStream, FX_BOOL bInline);
+
+  void Release();
+
+  CPDF_Image* Clone();
+
+  CPDF_Dictionary* GetInlineDict() const { return m_pInlineDict; }
+  CPDF_Stream* GetStream() const { return m_pStream; }
+  CPDF_Dictionary* GetDict() const {
+    return m_pStream ? m_pStream->GetDict() : NULL;
+  }
+  CPDF_Dictionary* GetOC() const { return m_pOC; }
+  CPDF_Document* GetDocument() const { return m_pDocument; }
+
+  int32_t GetPixelHeight() const { return m_Height; }
+  int32_t GetPixelWidth() const { return m_Width; }
+
+  FX_BOOL IsInline() { return m_bInline; }
+  FX_BOOL IsMask() const { return m_bIsMask; }
+  FX_BOOL IsInterpol() const { return m_bInterpolate; }
+
+  CFX_DIBSource* LoadDIBSource(CFX_DIBSource** ppMask = NULL,
+                               FX_DWORD* pMatteColor = NULL,
+                               FX_BOOL bStdCS = FALSE,
+                               FX_DWORD GroupFamily = 0,
+                               FX_BOOL bLoadMask = FALSE) const;
+
+  void SetInlineDict(CPDF_Dictionary* pDict) { m_pInlineDict = pDict; }
+  void SetImage(const CFX_DIBitmap* pDIBitmap,
+                int32_t iCompress,
+                IFX_FileWrite* pFileWrite = NULL,
+                IFX_FileRead* pFileRead = NULL,
+                const CFX_DIBitmap* pMask = NULL);
+  void SetJpegImage(uint8_t* pImageData, FX_DWORD size);
+  void SetJpegImage(IFX_FileRead* pFile);
+
+  void ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pDIBitmap);
+
+  FX_BOOL StartLoadDIBSource(CPDF_Dictionary* pFormResource,
+                             CPDF_Dictionary* pPageResource,
+                             FX_BOOL bStdCS = FALSE,
+                             FX_DWORD GroupFamily = 0,
+                             FX_BOOL bLoadMask = FALSE);
+  FX_BOOL Continue(IFX_Pause* pPause);
+  CFX_DIBSource* DetachBitmap();
+  CFX_DIBSource* DetachMask();
+
+  CFX_DIBSource* m_pDIBSource;
+  CFX_DIBSource* m_pMask;
+  FX_DWORD m_MatteColor;
+
+ private:
+  CPDF_Dictionary* InitJPEG(uint8_t* pData, FX_DWORD size);
+
+  CPDF_Stream* m_pStream;
+  FX_BOOL m_bInline;
+  CPDF_Dictionary* m_pInlineDict;
+  int32_t m_Height;
+  int32_t m_Width;
+  FX_BOOL m_bIsMask;
+  FX_BOOL m_bInterpolate;
+  CPDF_Document* m_pDocument;
+  CPDF_Dictionary* m_pOC;
+};
+
+#endif  // CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_IMAGE_H_
diff --git a/core/fpdfapi/fpdf_page/pageint.h b/core/fpdfapi/fpdf_page/pageint.h
index e6a1500..d254477 100644
--- a/core/fpdfapi/fpdf_page/pageint.h
+++ b/core/fpdfapi/fpdf_page/pageint.h
@@ -13,9 +13,9 @@
 #include <vector>
 
 #include "core/fpdfapi/fpdf_page/cpdf_contentmark.h"
+#include "core/fpdfapi/fpdf_page/cpdf_countedobject.h"
 #include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobjectholder.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "core/include/fxge/fx_ge.h"
 
 class CPDF_AllStates;
@@ -26,6 +26,7 @@
 class CPDF_IccProfile;
 class CPDF_Image;
 class CPDF_ImageObject;
+class CPDF_Page;
 class CPDF_ParseOptions;
 class CPDF_Pattern;
 class CPDF_StreamAcc;
@@ -438,10 +439,7 @@
 
 class CPDF_PatternCS : public CPDF_ColorSpace {
  public:
-  explicit CPDF_PatternCS(CPDF_Document* pDoc)
-      : CPDF_ColorSpace(pDoc, PDFCS_PATTERN, 1),
-        m_pBaseCS(nullptr),
-        m_pCountedBaseCS(nullptr) {}
+  explicit CPDF_PatternCS(CPDF_Document* pDoc);
   ~CPDF_PatternCS() override;
   FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
   FX_BOOL GetRGB(FX_FLOAT* pBuf,
@@ -455,6 +453,14 @@
   CPDF_CountedColorSpace* m_pCountedBaseCS;
 };
 
+#define MAX_PATTERN_COLORCOMPS 16
+struct PatternValue {
+  CPDF_Pattern* m_pPattern;
+  CPDF_CountedPattern* m_pCountedPattern;
+  int m_nComps;
+  FX_FLOAT m_Comps[MAX_PATTERN_COLORCOMPS];
+};
+
 void PDF_ReplaceAbbr(CPDF_Object* pObj);
 bool IsPathOperator(const uint8_t* buf, size_t len);
 
diff --git a/core/fpdfapi/fpdf_parser/cpdf_document.cpp b/core/fpdfapi/fpdf_parser/cpdf_document.cpp
index 6a6e40f..eb9a483 100644
--- a/core/fpdfapi/fpdf_parser/cpdf_document.cpp
+++ b/core/fpdfapi/fpdf_parser/cpdf_document.cpp
@@ -12,6 +12,7 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_parser.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
 #include "core/fpdfapi/fpdf_render/render_int.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
 #include "core/fpdfapi/ipdf_rendermodule.h"
diff --git a/core/fpdfapi/fpdf_render/fpdf_render.cpp b/core/fpdfapi/fpdf_render/fpdf_render.cpp
index 3f79abe..24ca282 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render.cpp
@@ -6,10 +6,13 @@
 
 #include "core/fpdfapi/fpdf_render/render_int.h"
 
+#include "core/fpdfapi/fpdf_font/cpdf_type3char.h"
+#include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
 #include "core/fpdfapi/fpdf_page/cpdf_colorstatedata.h"
 #include "core/fpdfapi/fpdf_page/cpdf_graphicstates.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_formobject.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
index bda2a44..b28aee6 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
@@ -10,7 +10,10 @@
 #include <vector>
 
 #include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
+#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
+#include "core/fpdfapi/fpdf_page/cpdf_tilingpattern.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp b/core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
index 5c4f7f5..1ad091e 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
@@ -92,71 +93,6 @@
 
 }  // namespace
 
-CFX_DIBSource* CPDF_Image::LoadDIBSource(CFX_DIBSource** ppMask,
-                                         FX_DWORD* pMatteColor,
-                                         FX_BOOL bStdCS,
-                                         FX_DWORD GroupFamily,
-                                         FX_BOOL bLoadMask) const {
-  std::unique_ptr<CPDF_DIBSource> source(new CPDF_DIBSource);
-  if (source->Load(m_pDocument, m_pStream,
-                   reinterpret_cast<CPDF_DIBSource**>(ppMask), pMatteColor,
-                   nullptr, nullptr, bStdCS, GroupFamily, bLoadMask)) {
-    return source.release();
-  }
-  return nullptr;
-}
-
-CFX_DIBSource* CPDF_Image::DetachBitmap() {
-  CFX_DIBSource* pBitmap = m_pDIBSource;
-  m_pDIBSource = nullptr;
-  return pBitmap;
-}
-
-CFX_DIBSource* CPDF_Image::DetachMask() {
-  CFX_DIBSource* pBitmap = m_pMask;
-  m_pMask = nullptr;
-  return pBitmap;
-}
-
-FX_BOOL CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource,
-                                       CPDF_Dictionary* pPageResource,
-                                       FX_BOOL bStdCS,
-                                       FX_DWORD GroupFamily,
-                                       FX_BOOL bLoadMask) {
-  std::unique_ptr<CPDF_DIBSource> source(new CPDF_DIBSource);
-  int ret =
-      source->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResource,
-                                 pPageResource, bStdCS, GroupFamily, bLoadMask);
-  if (ret == 2) {
-    m_pDIBSource = source.release();
-    return TRUE;
-  }
-  if (!ret) {
-    m_pDIBSource = nullptr;
-    return FALSE;
-  }
-  m_pMask = source->DetachMask();
-  m_MatteColor = source->GetMatteColor();
-  m_pDIBSource = source.release();
-  return FALSE;
-}
-
-FX_BOOL CPDF_Image::Continue(IFX_Pause* pPause) {
-  CPDF_DIBSource* pSource = static_cast<CPDF_DIBSource*>(m_pDIBSource);
-  int ret = pSource->ContinueLoadDIBSource(pPause);
-  if (ret == 2) {
-    return TRUE;
-  }
-  if (!ret) {
-    delete m_pDIBSource;
-    m_pDIBSource = nullptr;
-    return FALSE;
-  }
-  m_pMask = pSource->DetachMask();
-  m_MatteColor = pSource->GetMatteColor();
-  return FALSE;
-}
-
 CPDF_DIBSource::CPDF_DIBSource()
     : m_pDocument(nullptr),
       m_pStream(nullptr),
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
index 9006f20..d4dd8ec 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
@@ -7,7 +7,10 @@
 #include "core/fpdfapi/fpdf_render/render_int.h"
 
 #include "core/fpdfapi/fpdf_page/cpdf_graphicstates.h"
+#include "core/fpdfapi/fpdf_page/cpdf_meshstream.h"
 #include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
+#include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
+#include "core/fpdfapi/fpdf_page/cpdf_tilingpattern.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pathobject.h"
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
index 44e57e4..04b0c93 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
@@ -6,6 +6,10 @@
 
 #include "core/fpdfapi/fpdf_render/render_int.h"
 
+#include "core/fpdfapi/fpdf_font/cpdf_cidfont.h"
+#include "core/fpdfapi/fpdf_font/cpdf_type3char.h"
+#include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
@@ -318,27 +322,7 @@
   pFont->m_pDocument->GetRenderData()->ReleaseCachedType3(pFont);
   pFont->m_pDocument->GetPageData()->ReleaseFont(pFont->GetFontDict());
 }
-FX_BOOL CPDF_Type3Char::LoadBitmap(CPDF_RenderContext* pContext) {
-  if (m_pBitmap || !m_pForm) {
-    return TRUE;
-  }
-  if (m_pForm->GetPageObjectList()->size() == 1 && !m_bColored) {
-    auto& pPageObj = m_pForm->GetPageObjectList()->front();
-    if (pPageObj->IsImage()) {
-      m_ImageMatrix = pPageObj->AsImage()->m_Matrix;
-      const CFX_DIBSource* pSource =
-          pPageObj->AsImage()->m_pImage->LoadDIBSource();
-      if (pSource) {
-        m_pBitmap = pSource->Clone();
-        delete pSource;
-      }
-      delete m_pForm;
-      m_pForm = NULL;
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
+
 class CPDF_RefType3Cache {
  public:
   CPDF_RefType3Cache(CPDF_Type3Font* pType3Font) {
diff --git a/core/fpdfapi/fpdf_render/render_int.h b/core/fpdfapi/fpdf_render/render_int.h
index b171b60..ea1b1d8 100644
--- a/core/fpdfapi/fpdf_render/render_int.h
+++ b/core/fpdfapi/fpdf_render/render_int.h
@@ -10,10 +10,11 @@
 #include <map>
 #include <memory>
 
+#include "core/fpdfapi/fpdf_page/cpdf_countedobject.h"
 #include "core/fpdfapi/fpdf_page/cpdf_graphicstates.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_clippath.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 
 class CPDF_PageObjectHolder;
 class CPDF_PageRenderCache;
@@ -40,6 +41,7 @@
 class CPDF_Color;
 class CPDF_Dictionary;
 class CPDF_ImageObject;
+class CPDF_Stream;
 
 #define TYPE3_MAX_BLUES 16
 
diff --git a/core/fpdfdoc/doc_ap.cpp b/core/fpdfdoc/doc_ap.cpp
index cdbdd1e..06e9da8 100644
--- a/core/fpdfdoc/doc_ap.cpp
+++ b/core/fpdfdoc/doc_ap.cpp
@@ -4,9 +4,11 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
 #include "core/fpdfdoc/doc_utils.h"
 #include "core/fpdfdoc/pdf_vt.h"
 #include "core/include/fpdfdoc/fpdf_ap.h"
diff --git a/core/fpdfdoc/doc_form.cpp b/core/fpdfdoc/doc_form.cpp
index cecf6a8..eb70e2b 100644
--- a/core/fpdfdoc/doc_form.cpp
+++ b/core/fpdfdoc/doc_form.cpp
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_parser/include/cfdf_document.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
diff --git a/core/fpdfdoc/doc_tagged.cpp b/core/fpdfdoc/doc_tagged.cpp
index 4be0d6c..1664aff 100644
--- a/core/fpdfdoc/doc_tagged.cpp
+++ b/core/fpdfdoc/doc_tagged.cpp
@@ -10,6 +10,7 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_reference.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
 #include "core/fpdfdoc/doc_utils.h"
 #include "core/fpdfdoc/tagged_int.h"
 #include "core/include/fpdfdoc/fpdf_tagged.h"
diff --git a/core/fpdfdoc/doc_utils.cpp b/core/fpdfdoc/doc_utils.cpp
index 795a26a..8659a62 100644
--- a/core/fpdfdoc/doc_utils.cpp
+++ b/core/fpdfdoc/doc_utils.cpp
@@ -7,11 +7,13 @@
 #include <algorithm>
 #include <vector>
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
 #include "core/fpdfdoc/doc_utils.h"
 #include "core/include/fpdfdoc/fpdf_doc.h"
+#include "core/include/fxge/fx_font.h"
 
 namespace {
 
diff --git a/core/fpdfdoc/doc_utils.h b/core/fpdfdoc/doc_utils.h
index 6bfd005..e9a11e0 100644
--- a/core/fpdfdoc/doc_utils.h
+++ b/core/fpdfdoc/doc_utils.h
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "core/fpdfapi/fpdf_parser/include/cpdf_parser.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 
 class CPDF_Dictionary;
 class CPDF_FormField;
diff --git a/core/fpdftext/fpdf_text_int.cpp b/core/fpdftext/fpdf_text_int.cpp
index 2e267fd..34f17fb 100644
--- a/core/fpdftext/fpdf_text_int.cpp
+++ b/core/fpdftext/fpdf_text_int.cpp
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_formobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_textobject.h"
@@ -25,7 +26,6 @@
 #include "core/fxcrt/fx_bidi.h"
 #include "core/fxcrt/include/fx_ext.h"
 #include "core/fxcrt/include/fx_ucd.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "third_party/base/stl_util.h"
 
 #define FPDFTEXT_RLTB 1
diff --git a/core/fxcodec/codec/fx_codec_jpx_opj.cpp b/core/fxcodec/codec/fx_codec_jpx_opj.cpp
index 607f082..99eb78f 100644
--- a/core/fxcodec/codec/fx_codec_jpx_opj.cpp
+++ b/core/fxcodec/codec/fx_codec_jpx_opj.cpp
@@ -8,9 +8,9 @@
 #include <limits>
 #include <vector>
 
+#include "core/fpdfapi/fpdf_page/include/cpdf_colorspace.h"
 #include "core/fxcodec/codec/codec_int.h"
 #include "core/fxcrt/include/fx_safe_types.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "core/include/fxcodec/fx_codec.h"
 #include "third_party/lcms2-2.6/include/lcms2.h"
 #include "third_party/libopenjpeg20/openjpeg.h"
diff --git a/core/include/fpdfapi/fpdf_resource.h b/core/include/fpdfapi/fpdf_resource.h
deleted file mode 100644
index f309114..0000000
--- a/core/include/fpdfapi/fpdf_resource.h
+++ /dev/null
@@ -1,774 +0,0 @@
-// Copyright 2014 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.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef CORE_INCLUDE_FPDFAPI_FPDF_RESOURCE_H_
-#define CORE_INCLUDE_FPDFAPI_FPDF_RESOURCE_H_
-
-#include <map>
-
-#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
-#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
-#include "core/fxcrt/include/fx_system.h"
-#include "core/include/fxge/fx_font.h"
-
-class CFX_CTTGSUBTable;
-class CFX_DIBitmap;
-class CFX_Font;
-class CFX_SubstFont;
-class CPDF_CID2UnicodeMap;
-class CPDF_CIDFont;
-class CPDF_CMap;
-class CPDF_Color;
-class CPDF_ColorSpace;
-class CPDF_Document;
-class CPDF_FontEncoding;
-class CPDF_Form;
-class CPDF_Function;
-class CPDF_Image;
-class CPDF_Page;
-class CPDF_Pattern;
-class CPDF_RenderContext;
-class CPDF_ShadingPattern;
-class CPDF_TilingPattern;
-class CPDF_ToUnicodeMap;
-class CPDF_TrueTypeFont;
-class CPDF_Type1Font;
-class CPDF_Type3Font;
-typedef struct FT_FaceRec_* FXFT_Face;
-
-FX_WCHAR PDF_UnicodeFromAdobeName(const FX_CHAR* name);
-CFX_ByteString PDF_AdobeNameFromUnicode(FX_WCHAR unicode);
-const FX_CHAR* FCS_GetAltStr(FX_WCHAR unicode);
-const FX_CHAR* PDF_CharNameFromPredefinedCharSet(int encoding,
-                                                 uint8_t charcode);
-
-FX_WCHAR FT_UnicodeFromCharCode(int encoding, FX_DWORD charcode);
-FX_DWORD FT_CharCodeFromUnicode(int encoding, FX_WCHAR unicode);
-const uint16_t* PDF_UnicodesForPredefinedCharSet(int encoding);
-const FX_CHAR* GetAdobeCharName(int iBaseEncoding,
-                                const CFX_ByteString* pCharNames,
-                                int charcode);
-
-template <class T>
-class CPDF_CountedObject {
- public:
-  explicit CPDF_CountedObject(T* ptr) : m_nCount(1), m_pObj(ptr) {}
-  void reset(T* ptr) {  // CAUTION: tosses prior ref counts.
-    m_nCount = 1;
-    m_pObj = ptr;
-  }
-  void clear() {  // Now you're all weak ptrs ...
-    delete m_pObj;
-    m_pObj = nullptr;
-  }
-  T* get() const { return m_pObj; }
-  T* AddRef() {
-    FXSYS_assert(m_pObj);
-    ++m_nCount;
-    return m_pObj;
-  }
-  void RemoveRef() {
-    if (m_nCount)
-      --m_nCount;
-  }
-  size_t use_count() const { return m_nCount; }
-
- protected:
-  size_t m_nCount;
-  T* m_pObj;
-};
-using CPDF_CountedColorSpace = CPDF_CountedObject<CPDF_ColorSpace>;
-using CPDF_CountedPattern = CPDF_CountedObject<CPDF_Pattern>;
-
-#define PDFFONT_FIXEDPITCH 1
-#define PDFFONT_SERIF 2
-#define PDFFONT_SYMBOLIC 4
-#define PDFFONT_SCRIPT 8
-#define PDFFONT_NONSYMBOLIC 32
-#define PDFFONT_ITALIC 64
-#define PDFFONT_ALLCAP 0x10000
-#define PDFFONT_SMALLCAP 0x20000
-#define PDFFONT_FORCEBOLD 0x40000
-#define PDFFONT_USEEXTERNATTR 0x80000
-
-class CPDF_Font {
- public:
-  static CPDF_Font* CreateFontF(CPDF_Document* pDoc,
-                                CPDF_Dictionary* pFontDict);
-  static CPDF_Font* GetStockFont(CPDF_Document* pDoc,
-                                 const CFX_ByteStringC& fontname);
-  static const FX_DWORD kInvalidCharCode = static_cast<FX_DWORD>(-1);
-
-  virtual ~CPDF_Font();
-
-  virtual bool IsType1Font() const;
-  virtual bool IsTrueTypeFont() const;
-  virtual bool IsType3Font() const;
-  virtual bool IsCIDFont() const;
-  virtual const CPDF_Type1Font* AsType1Font() const;
-  virtual CPDF_Type1Font* AsType1Font();
-  virtual const CPDF_TrueTypeFont* AsTrueTypeFont() const;
-  virtual CPDF_TrueTypeFont* AsTrueTypeFont();
-  virtual const CPDF_Type3Font* AsType3Font() const;
-  virtual CPDF_Type3Font* AsType3Font();
-  virtual const CPDF_CIDFont* AsCIDFont() const;
-  virtual CPDF_CIDFont* AsCIDFont();
-
-  virtual FX_BOOL IsVertWriting() const;
-  virtual FX_BOOL IsUnicodeCompatible() const;
-  virtual FX_DWORD GetNextChar(const FX_CHAR* pString,
-                               int nStrLen,
-                               int& offset) const;
-  virtual int CountChar(const FX_CHAR* pString, int size) const;
-  virtual int AppendChar(FX_CHAR* buf, FX_DWORD charcode) const;
-  virtual int GetCharSize(FX_DWORD charcode) const;
-  virtual int GlyphFromCharCode(FX_DWORD charcode,
-                                FX_BOOL* pVertGlyph = nullptr);
-  virtual int GlyphFromCharCodeExt(FX_DWORD charcode);
-  virtual CFX_WideString UnicodeFromCharCode(FX_DWORD charcode) const;
-  virtual FX_DWORD CharCodeFromUnicode(FX_WCHAR Unicode) const;
-
-  const CFX_ByteString& GetBaseFont() const { return m_BaseFont; }
-  const CFX_SubstFont* GetSubstFont() const { return m_Font.GetSubstFont(); }
-  FX_DWORD GetFlags() const { return m_Flags; }
-  FX_BOOL IsEmbedded() const { return IsType3Font() || m_pFontFile != nullptr; }
-  CPDF_StreamAcc* GetFontFile() const { return m_pFontFile; }
-  CPDF_Dictionary* GetFontDict() const { return m_pFontDict; }
-  FX_BOOL IsStandardFont() const;
-  FXFT_Face GetFace() const { return m_Font.GetFace(); }
-  void AppendChar(CFX_ByteString& str, FX_DWORD charcode) const;
-
-  void GetFontBBox(FX_RECT& rect) const { rect = m_FontBBox; }
-  int GetTypeAscent() const { return m_Ascent; }
-  int GetTypeDescent() const { return m_Descent; }
-  int GetItalicAngle() const { return m_ItalicAngle; }
-  int GetStemV() const { return m_StemV; }
-  int GetStringWidth(const FX_CHAR* pString, int size);
-
-  virtual int GetCharWidthF(FX_DWORD charcode, int level = 0) = 0;
-  virtual FX_RECT GetCharBBox(FX_DWORD charcode, int level = 0) = 0;
-
-  CPDF_Document* m_pDocument;
-  CFX_Font m_Font;
-
- protected:
-  CPDF_Font();
-
-  virtual FX_BOOL Load() = 0;
-
-  FX_BOOL Initialize();
-  void LoadUnicodeMap();
-  void LoadPDFEncoding(CPDF_Object* pEncoding,
-                       int& iBaseEncoding,
-                       CFX_ByteString*& pCharNames,
-                       FX_BOOL bEmbedded,
-                       FX_BOOL bTrueType);
-  void LoadFontDescriptor(CPDF_Dictionary* pDict);
-  void CheckFontMetrics();
-
-  CFX_ByteString m_BaseFont;
-  CPDF_StreamAcc* m_pFontFile;
-  CPDF_Dictionary* m_pFontDict;
-  CPDF_ToUnicodeMap* m_pToUnicodeMap;
-  FX_BOOL m_bToUnicodeLoaded;
-  int m_Flags;
-  FX_RECT m_FontBBox;
-  int m_StemV;
-  int m_Ascent;
-  int m_Descent;
-  int m_ItalicAngle;
-};
-
-#define PDFFONT_ENCODING_BUILTIN 0
-#define PDFFONT_ENCODING_WINANSI 1
-#define PDFFONT_ENCODING_MACROMAN 2
-#define PDFFONT_ENCODING_MACEXPERT 3
-#define PDFFONT_ENCODING_STANDARD 4
-#define PDFFONT_ENCODING_ADOBE_SYMBOL 5
-#define PDFFONT_ENCODING_ZAPFDINGBATS 6
-#define PDFFONT_ENCODING_PDFDOC 7
-#define PDFFONT_ENCODING_MS_SYMBOL 8
-#define PDFFONT_ENCODING_UNICODE 9
-
-class CPDF_FontEncoding {
- public:
-  CPDF_FontEncoding();
-
-  CPDF_FontEncoding(int PredefinedEncoding);
-
-  void LoadEncoding(CPDF_Object* pEncoding);
-
-  FX_BOOL IsIdentical(CPDF_FontEncoding* pAnother) const;
-
-  FX_WCHAR UnicodeFromCharCode(uint8_t charcode) const {
-    return m_Unicodes[charcode];
-  }
-
-  int CharCodeFromUnicode(FX_WCHAR unicode) const;
-
-  void SetUnicode(uint8_t charcode, FX_WCHAR unicode) {
-    m_Unicodes[charcode] = unicode;
-  }
-
-  CPDF_Object* Realize();
-
- public:
-  FX_WCHAR m_Unicodes[256];
-};
-
-class CPDF_SimpleFont : public CPDF_Font {
- public:
-  CPDF_SimpleFont();
-  ~CPDF_SimpleFont() override;
-
-  // CPDF_Font:
-  int GetCharWidthF(FX_DWORD charcode, int level = 0) override;
-  FX_RECT GetCharBBox(FX_DWORD charcode, int level = 0) override;
-  int GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph = NULL) override;
-  FX_BOOL IsUnicodeCompatible() const override;
-  CFX_WideString UnicodeFromCharCode(FX_DWORD charcode) const override;
-  FX_DWORD CharCodeFromUnicode(FX_WCHAR Unicode) const override;
-
-  CPDF_FontEncoding* GetEncoding() { return &m_Encoding; }
-
- protected:
-  virtual void LoadGlyphMap() = 0;
-
-  FX_BOOL LoadCommon();
-  void LoadSubstFont();
-  void LoadFaceMetrics();
-  void LoadCharMetrics(int charcode);
-
-  CPDF_FontEncoding m_Encoding;
-  uint16_t m_GlyphIndex[256];
-  uint16_t m_ExtGID[256];
-  CFX_ByteString* m_pCharNames;
-  int m_BaseEncoding;
-  uint16_t m_CharWidth[256];
-  FX_SMALL_RECT m_CharBBox[256];
-  FX_BOOL m_bUseFontWidth;
-};
-
-class CPDF_Type1Font : public CPDF_SimpleFont {
- public:
-  CPDF_Type1Font();
-
-  // CPDF_Font:
-  bool IsType1Font() const override;
-  const CPDF_Type1Font* AsType1Font() const override;
-  CPDF_Type1Font* AsType1Font() override;
-  int GlyphFromCharCodeExt(FX_DWORD charcode) override;
-
-  int GetBase14Font() const { return m_Base14Font; }
-
- protected:
-  // CPDF_Font:
-  FX_BOOL Load() override;
-
-  // CPDF_SimpleFont:
-  void LoadGlyphMap() override;
-
-  int m_Base14Font;
-};
-
-class CPDF_TrueTypeFont : public CPDF_SimpleFont {
- public:
-  CPDF_TrueTypeFont();
-
-  // CPDF_Font:
-  bool IsTrueTypeFont() const override;
-  const CPDF_TrueTypeFont* AsTrueTypeFont() const override;
-  CPDF_TrueTypeFont* AsTrueTypeFont() override;
-
- protected:
-  // CPDF_Font:
-  FX_BOOL Load() override;
-
-  // CPDF_SimpleFont:
-  void LoadGlyphMap() override;
-};
-
-class CPDF_Type3Char {
- public:
-  // Takes ownership of |pForm|.
-  explicit CPDF_Type3Char(CPDF_Form* pForm);
-  ~CPDF_Type3Char();
-
-  FX_BOOL LoadBitmap(CPDF_RenderContext* pContext);
-
-  CPDF_Form* m_pForm;
-  CFX_DIBitmap* m_pBitmap;
-  FX_BOOL m_bColored;
-  int m_Width;
-  CFX_Matrix m_ImageMatrix;
-  FX_RECT m_BBox;
-};
-
-class CPDF_Type3Font : public CPDF_SimpleFont {
- public:
-  CPDF_Type3Font();
-  ~CPDF_Type3Font() override;
-
-  // CPDF_Font:
-  bool IsType3Font() const override;
-  const CPDF_Type3Font* AsType3Font() const override;
-  CPDF_Type3Font* AsType3Font() override;
-  int GetCharWidthF(FX_DWORD charcode, int level = 0) override;
-  FX_RECT GetCharBBox(FX_DWORD charcode, int level = 0) override;
-
-  void SetPageResources(CPDF_Dictionary* pResources) {
-    m_pPageResources = pResources;
-  }
-  CPDF_Type3Char* LoadChar(FX_DWORD charcode, int level = 0);
-  void CheckType3FontMetrics();
-
-  CFX_Matrix& GetFontMatrix() { return m_FontMatrix; }
-
- protected:
-  CFX_Matrix m_FontMatrix;
-
- private:
-  // CPDF_Font:
-  FX_BOOL Load() override;
-
-  // CPDF_SimpleFont:
-  void LoadGlyphMap() override {}
-
-  int m_CharWidthL[256];
-  CPDF_Dictionary* m_pCharProcs;
-  CPDF_Dictionary* m_pPageResources;
-  CPDF_Dictionary* m_pFontResources;
-  std::map<FX_DWORD, CPDF_Type3Char*> m_CacheMap;
-};
-
-enum CIDSet : uint8_t {
-  CIDSET_UNKNOWN,
-  CIDSET_GB1,
-  CIDSET_CNS1,
-  CIDSET_JAPAN1,
-  CIDSET_KOREA1,
-  CIDSET_UNICODE,
-  CIDSET_NUM_SETS
-};
-
-class CPDF_CIDFont : public CPDF_Font {
- public:
-  CPDF_CIDFont();
-  ~CPDF_CIDFont() override;
-
-  static FX_FLOAT CIDTransformToFloat(uint8_t ch);
-
-  // CPDF_Font:
-  bool IsCIDFont() const override;
-  const CPDF_CIDFont* AsCIDFont() const override;
-  CPDF_CIDFont* AsCIDFont() override;
-  int GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph = NULL) override;
-  int GetCharWidthF(FX_DWORD charcode, int level = 0) override;
-  FX_RECT GetCharBBox(FX_DWORD charcode, int level = 0) override;
-  FX_DWORD GetNextChar(const FX_CHAR* pString,
-                       int nStrLen,
-                       int& offset) const override;
-  int CountChar(const FX_CHAR* pString, int size) const override;
-  int AppendChar(FX_CHAR* str, FX_DWORD charcode) const override;
-  int GetCharSize(FX_DWORD charcode) const override;
-  FX_BOOL IsVertWriting() const override;
-  FX_BOOL IsUnicodeCompatible() const override;
-  FX_BOOL Load() override;
-  CFX_WideString UnicodeFromCharCode(FX_DWORD charcode) const override;
-  FX_DWORD CharCodeFromUnicode(FX_WCHAR Unicode) const override;
-
-  FX_BOOL LoadGB2312();
-  uint16_t CIDFromCharCode(FX_DWORD charcode) const;
-  const uint8_t* GetCIDTransform(uint16_t CID) const;
-  short GetVertWidth(uint16_t CID) const;
-  void GetVertOrigin(uint16_t CID, short& vx, short& vy) const;
-  virtual FX_BOOL IsFontStyleFromCharCode(FX_DWORD charcode) const;
-
- protected:
-  int GetGlyphIndex(FX_DWORD unicodeb, FX_BOOL* pVertGlyph);
-  void LoadMetricsArray(CPDF_Array* pArray,
-                        CFX_DWordArray& result,
-                        int nElements);
-  void LoadSubstFont();
-  FX_WCHAR GetUnicodeFromCharCode(FX_DWORD charcode) const;
-
-  CPDF_CMap* m_pCMap;
-  CPDF_CMap* m_pAllocatedCMap;
-  CPDF_CID2UnicodeMap* m_pCID2UnicodeMap;
-  CIDSet m_Charset;
-  FX_BOOL m_bType1;
-  CPDF_StreamAcc* m_pCIDToGIDMap;
-  FX_BOOL m_bCIDIsGID;
-  uint16_t m_DefaultWidth;
-  uint16_t* m_pAnsiWidths;
-  FX_SMALL_RECT m_CharBBox[256];
-  CFX_DWordArray m_WidthList;
-  short m_DefaultVY;
-  short m_DefaultW1;
-  CFX_DWordArray m_VertMetrics;
-  FX_BOOL m_bAdobeCourierStd;
-  CFX_CTTGSUBTable* m_pTTGSUBTable;
-};
-
-#define PDFCS_DEVICEGRAY 1
-#define PDFCS_DEVICERGB 2
-#define PDFCS_DEVICECMYK 3
-#define PDFCS_CALGRAY 4
-#define PDFCS_CALRGB 5
-#define PDFCS_LAB 6
-#define PDFCS_ICCBASED 7
-#define PDFCS_SEPARATION 8
-#define PDFCS_DEVICEN 9
-#define PDFCS_INDEXED 10
-#define PDFCS_PATTERN 11
-
-class CPDF_ColorSpace {
- public:
-  static CPDF_ColorSpace* GetStockCS(int Family);
-
-  static CPDF_ColorSpace* Load(CPDF_Document* pDoc, CPDF_Object* pCSObj);
-
-  void ReleaseCS();
-
-  int GetBufSize() const;
-  FX_FLOAT* CreateBuf();
-  void GetDefaultColor(FX_FLOAT* buf) const;
-  FX_DWORD CountComponents() const { return m_nComponents; }
-  int GetFamily() const { return m_Family; }
-  virtual void GetDefaultValue(int iComponent,
-                               FX_FLOAT& value,
-                               FX_FLOAT& min,
-                               FX_FLOAT& max) const {
-    value = 0;
-    min = 0;
-    max = 1.0f;
-  }
-
-  FX_BOOL sRGB() const;
-  virtual FX_BOOL GetRGB(FX_FLOAT* pBuf,
-                         FX_FLOAT& R,
-                         FX_FLOAT& G,
-                         FX_FLOAT& B) const = 0;
-  virtual FX_BOOL SetRGB(FX_FLOAT* pBuf,
-                         FX_FLOAT R,
-                         FX_FLOAT G,
-                         FX_FLOAT B) const {
-    return FALSE;
-  }
-
-  FX_BOOL GetCMYK(FX_FLOAT* pBuf,
-                  FX_FLOAT& c,
-                  FX_FLOAT& m,
-                  FX_FLOAT& y,
-                  FX_FLOAT& k) const;
-  FX_BOOL SetCMYK(FX_FLOAT* pBuf,
-                  FX_FLOAT c,
-                  FX_FLOAT m,
-                  FX_FLOAT y,
-                  FX_FLOAT k) const;
-
-  virtual void TranslateImageLine(uint8_t* dest_buf,
-                                  const uint8_t* src_buf,
-                                  int pixels,
-                                  int image_width,
-                                  int image_height,
-                                  FX_BOOL bTransMask = FALSE) const;
-
-  CPDF_Array*& GetArray() { return m_pArray; }
-  int GetMaxIndex() const;
-  virtual CPDF_ColorSpace* GetBaseCS() const { return NULL; }
-
-  virtual void EnableStdConversion(FX_BOOL bEnabled);
-
-  CPDF_Document* const m_pDocument;
-
- protected:
-  CPDF_ColorSpace(CPDF_Document* pDoc, int family, FX_DWORD nComponents)
-      : m_pDocument(pDoc),
-        m_Family(family),
-        m_nComponents(nComponents),
-        m_pArray(nullptr),
-        m_dwStdConversion(0) {}
-  virtual ~CPDF_ColorSpace() {}
-  virtual FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) {
-    return TRUE;
-  }
-  virtual FX_BOOL v_GetCMYK(FX_FLOAT* pBuf,
-                            FX_FLOAT& c,
-                            FX_FLOAT& m,
-                            FX_FLOAT& y,
-                            FX_FLOAT& k) const {
-    return FALSE;
-  }
-  virtual FX_BOOL v_SetCMYK(FX_FLOAT* pBuf,
-                            FX_FLOAT c,
-                            FX_FLOAT m,
-                            FX_FLOAT y,
-                            FX_FLOAT k) const {
-    return FALSE;
-  }
-
-  int m_Family;
-  FX_DWORD m_nComponents;
-  CPDF_Array* m_pArray;
-  FX_DWORD m_dwStdConversion;
-};
-class CPDF_Color {
- public:
-  CPDF_Color() : m_pCS(NULL), m_pBuffer(NULL) {}
-
-  CPDF_Color(int family);
-
-  ~CPDF_Color();
-
-  FX_BOOL IsNull() const { return !m_pBuffer; }
-
-  FX_BOOL IsEqual(const CPDF_Color& other) const;
-
-  FX_BOOL IsPattern() const {
-    return m_pCS && m_pCS->GetFamily() == PDFCS_PATTERN;
-  }
-
-  void Copy(const CPDF_Color* pSrc);
-
-  void SetColorSpace(CPDF_ColorSpace* pCS);
-
-  void SetValue(FX_FLOAT* comp);
-
-  void SetValue(CPDF_Pattern* pPattern, FX_FLOAT* comp, int ncomps);
-
-  FX_BOOL GetRGB(int& R, int& G, int& B) const;
-
-  CPDF_Pattern* GetPattern() const;
-
-  CPDF_ColorSpace* GetPatternCS() const;
-
-  FX_FLOAT* GetPatternColor() const;
-
-  CPDF_ColorSpace* m_pCS;
-
- protected:
-  void ReleaseBuffer();
-  void ReleaseColorSpace();
-  FX_FLOAT* m_pBuffer;
-};
-
-class CPDF_Pattern {
- public:
-  enum PatternType { TILING = 1, SHADING };
-
-  virtual ~CPDF_Pattern();
-
-  void SetForceClear(FX_BOOL bForceClear) { m_bForceClear = bForceClear; }
-
-  const PatternType m_PatternType;
-  CPDF_Document* const m_pDocument;
-  CPDF_Object* const m_pPatternObj;
-  CFX_Matrix m_Pattern2Form;
-  CFX_Matrix m_ParentMatrix;
-
- protected:
-  CPDF_Pattern(PatternType type,
-               CPDF_Document* pDoc,
-               CPDF_Object* pObj,
-               const CFX_Matrix* pParentMatrix);
-
-  FX_BOOL m_bForceClear;
-};
-
-class CPDF_TilingPattern : public CPDF_Pattern {
- public:
-  CPDF_TilingPattern(CPDF_Document* pDoc,
-                     CPDF_Object* pPatternObj,
-                     const CFX_Matrix* parentMatrix);
-
-  ~CPDF_TilingPattern() override;
-
-  FX_BOOL Load();
-
-  FX_BOOL m_bColored;
-
-  CFX_FloatRect m_BBox;
-
-  FX_FLOAT m_XStep;
-
-  FX_FLOAT m_YStep;
-
-  CPDF_Form* m_pForm;
-};
-
-typedef enum {
-  kInvalidShading = 0,
-  kFunctionBasedShading = 1,
-  kAxialShading = 2,
-  kRadialShading = 3,
-  kFreeFormGouraudTriangleMeshShading = 4,
-  kLatticeFormGouraudTriangleMeshShading = 5,
-  kCoonsPatchMeshShading = 6,
-  kTensorProductPatchMeshShading = 7,
-  kMaxShading = 8
-} ShadingType;
-
-class CPDF_ShadingPattern : public CPDF_Pattern {
- public:
-  CPDF_ShadingPattern(CPDF_Document* pDoc,
-                      CPDF_Object* pPatternObj,
-                      FX_BOOL bShading,
-                      const CFX_Matrix* parentMatrix);
-
-  ~CPDF_ShadingPattern() override;
-
-  bool IsMeshShading() const {
-    return m_ShadingType == kFreeFormGouraudTriangleMeshShading ||
-           m_ShadingType == kLatticeFormGouraudTriangleMeshShading ||
-           m_ShadingType == kCoonsPatchMeshShading ||
-           m_ShadingType == kTensorProductPatchMeshShading;
-  }
-  FX_BOOL Load();
-
-  ShadingType m_ShadingType;
-  FX_BOOL m_bShadingObj;
-  CPDF_Object* m_pShadingObj;
-
-  // Still keep |m_pCS| as some CPDF_ColorSpace (name object) are not managed
-  // as counted objects. Refer to CPDF_DocPageData::GetColorSpace.
-  CPDF_ColorSpace* m_pCS;
-
-  CPDF_CountedColorSpace* m_pCountedCS;
-  CPDF_Function* m_pFunctions[4];
-  int m_nFuncs;
-};
-
-struct CPDF_MeshVertex {
-  FX_FLOAT x, y;
-  FX_FLOAT r, g, b;
-};
-class CPDF_MeshStream {
- public:
-  FX_BOOL Load(CPDF_Stream* pShadingStream,
-               CPDF_Function** pFuncs,
-               int nFuncs,
-               CPDF_ColorSpace* pCS);
-
-  FX_DWORD GetFlag();
-
-  void GetCoords(FX_FLOAT& x, FX_FLOAT& y);
-
-  void GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b);
-
-  FX_DWORD GetVertex(CPDF_MeshVertex& vertex, CFX_Matrix* pObject2Bitmap);
-
-  FX_BOOL GetVertexRow(CPDF_MeshVertex* vertex,
-                       int count,
-                       CFX_Matrix* pObject2Bitmap);
-  CPDF_Function** m_pFuncs;
-  CPDF_ColorSpace* m_pCS;
-  FX_DWORD m_nFuncs, m_nCoordBits, m_nCompBits, m_nFlagBits, m_nComps;
-  FX_DWORD m_CoordMax, m_CompMax;
-  FX_FLOAT m_xmin, m_xmax, m_ymin, m_ymax;
-  FX_FLOAT m_ColorMin[8], m_ColorMax[8];
-  CPDF_StreamAcc m_Stream;
-  CFX_BitStream m_BitStream;
-};
-#define PDF_IMAGE_NO_COMPRESS 0x0000
-#define PDF_IMAGE_LOSSY_COMPRESS 0x0001
-#define PDF_IMAGE_LOSSLESS_COMPRESS 0x0002
-#define PDF_IMAGE_MASK_LOSSY_COMPRESS 0x0004
-#define PDF_IMAGE_MASK_LOSSLESS_COMPRESS 0x0008
-class CPDF_ImageSetParam {
- public:
-  CPDF_ImageSetParam() : pMatteColor(NULL), nQuality(80) {}
-  FX_ARGB* pMatteColor;
-  int32_t nQuality;
-};
-class CPDF_Image {
- public:
-  CPDF_Image(CPDF_Document* pDoc);
-
-  ~CPDF_Image();
-
-  FX_BOOL LoadImageF(CPDF_Stream* pImageStream, FX_BOOL bInline);
-
-  void Release();
-
-  CPDF_Image* Clone();
-
-  FX_BOOL IsInline() { return m_bInline; }
-
-  void SetInlineDict(CPDF_Dictionary* pDict) { m_pInlineDict = pDict; }
-
-  CPDF_Dictionary* GetInlineDict() const { return m_pInlineDict; }
-
-  CPDF_Stream* GetStream() const { return m_pStream; }
-
-  CPDF_Dictionary* GetDict() const {
-    return m_pStream ? m_pStream->GetDict() : NULL;
-  }
-
-  CPDF_Dictionary* GetOC() const { return m_pOC; }
-
-  CPDF_Document* GetDocument() const { return m_pDocument; }
-
-  int32_t GetPixelHeight() const { return m_Height; }
-
-  int32_t GetPixelWidth() const { return m_Width; }
-
-  FX_BOOL IsMask() const { return m_bIsMask; }
-
-  FX_BOOL IsInterpol() const { return m_bInterpolate; }
-
-  CFX_DIBSource* LoadDIBSource(CFX_DIBSource** ppMask = NULL,
-                               FX_DWORD* pMatteColor = NULL,
-                               FX_BOOL bStdCS = FALSE,
-                               FX_DWORD GroupFamily = 0,
-                               FX_BOOL bLoadMask = FALSE) const;
-
-  void SetImage(const CFX_DIBitmap* pDIBitmap,
-                int32_t iCompress,
-                IFX_FileWrite* pFileWrite = NULL,
-                IFX_FileRead* pFileRead = NULL,
-                const CFX_DIBitmap* pMask = NULL,
-                const CPDF_ImageSetParam* pParam = NULL);
-
-  void SetJpegImage(uint8_t* pImageData, FX_DWORD size);
-
-  void SetJpegImage(IFX_FileRead* pFile);
-
-  void ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pDIBitmap);
-
- public:
-  FX_BOOL StartLoadDIBSource(CPDF_Dictionary* pFormResource,
-                             CPDF_Dictionary* pPageResource,
-                             FX_BOOL bStdCS = FALSE,
-                             FX_DWORD GroupFamily = 0,
-                             FX_BOOL bLoadMask = FALSE);
-  FX_BOOL Continue(IFX_Pause* pPause);
-  CFX_DIBSource* DetachBitmap();
-  CFX_DIBSource* DetachMask();
-  CFX_DIBSource* m_pDIBSource;
-  CFX_DIBSource* m_pMask;
-  FX_DWORD m_MatteColor;
-
- private:
-  CPDF_Stream* m_pStream;
-  FX_BOOL m_bInline;
-  CPDF_Dictionary* m_pInlineDict;
-
-  int32_t m_Height;
-
-  int32_t m_Width;
-
-  FX_BOOL m_bIsMask;
-
-  FX_BOOL m_bInterpolate;
-
-  CPDF_Document* m_pDocument;
-
-  CPDF_Dictionary* m_pOC;
-  CPDF_Dictionary* InitJPEG(uint8_t* pData, FX_DWORD size);
-};
-
-#endif  // CORE_INCLUDE_FPDFAPI_FPDF_RESOURCE_H_
diff --git a/core/include/fpdfdoc/fpdf_tagged.h b/core/include/fpdfdoc/fpdf_tagged.h
index 82ac64d..28fe84b 100644
--- a/core/include/fpdfdoc/fpdf_tagged.h
+++ b/core/include/fpdfdoc/fpdf_tagged.h
@@ -7,6 +7,8 @@
 #ifndef CORE_INCLUDE_FPDFDOC_FPDF_TAGGED_H_
 #define CORE_INCLUDE_FPDFDOC_FPDF_TAGGED_H_
 
+#include "core/include/fxge/fx_dib.h"
+
 class CPDF_Document;
 class CPDF_StructElement;
 class CPDF_StructTree;
diff --git a/core/include/fxcodec/fx_codec.h b/core/include/fxcodec/fx_codec.h
index e209fcf..99d4dbd 100644
--- a/core/include/fxcodec/fx_codec.h
+++ b/core/include/fxcodec/fx_codec.h
@@ -532,6 +532,14 @@
   virtual void SetComponents(FX_DWORD nComponents) = 0;
 };
 
+void ReverseRGB(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels);
+void sRGB_to_AdobeCMYK(FX_FLOAT R,
+                       FX_FLOAT G,
+                       FX_FLOAT B,
+                       FX_FLOAT& c,
+                       FX_FLOAT& m,
+                       FX_FLOAT& y,
+                       FX_FLOAT& k);
 void AdobeCMYK_to_sRGB(FX_FLOAT c,
                        FX_FLOAT m,
                        FX_FLOAT y,
diff --git a/core/include/fxge/fx_font.h b/core/include/fxge/fx_font.h
index 900f139..964a379 100644
--- a/core/include/fxge/fx_font.h
+++ b/core/include/fxge/fx_font.h
@@ -13,6 +13,7 @@
 
 #include "core/fxcrt/include/fx_system.h"
 #include "core/include/fxge/fx_dib.h"
+#include "core/include/fxge/fx_freetype.h"
 
 typedef struct FT_FaceRec_* FXFT_Face;
 typedef void* FXFT_Library;
diff --git a/core/include/fxge/fx_freetype.h b/core/include/fxge/fx_freetype.h
index 698cd5c..6920d86 100644
--- a/core/include/fxge/fx_freetype.h
+++ b/core/include/fxge/fx_freetype.h
@@ -18,6 +18,7 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+
 #define FXFT_ENCODING_UNICODE FT_ENCODING_UNICODE
 #define FXFT_ENCODING_ADOBE_STANDARD FT_ENCODING_ADOBE_STANDARD
 #define FXFT_ENCODING_ADOBE_EXPERT FT_ENCODING_ADOBE_EXPERT
diff --git a/fpdfsdk/formfiller/DEPS b/fpdfsdk/formfiller/DEPS
new file mode 100644
index 0000000..8e0928c
--- /dev/null
+++ b/fpdfsdk/formfiller/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  '+core/fpdfapi/fpdf_font/include',
+]
diff --git a/fpdfsdk/formfiller/cba_fontmap.cpp b/fpdfsdk/formfiller/cba_fontmap.cpp
index caa0704..d32b604 100644
--- a/fpdfsdk/formfiller/cba_fontmap.cpp
+++ b/fpdfsdk/formfiller/cba_fontmap.cpp
@@ -6,10 +6,11 @@
 
 #include "fpdfsdk/formfiller/cba_fontmap.h"
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
 #include "fpdfsdk/include/fsdk_baseannot.h"
 
 CBA_FontMap::CBA_FontMap(CPDFSDK_Annot* pAnnot,
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index b6333d4..3ad7c6e 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -13,6 +13,8 @@
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h"
+#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
 #include "fpdfsdk/include/fsdk_define.h"
 
 typedef CFX_ArrayTemplate<CPDF_Dictionary*> CPDF_ObjectArray;
diff --git a/fpdfsdk/fpdfeditimg.cpp b/fpdfsdk/fpdfeditimg.cpp
index f052687..c189f23 100644
--- a/fpdfsdk/fpdfeditimg.cpp
+++ b/fpdfsdk/fpdfeditimg.cpp
@@ -6,10 +6,10 @@
 
 #include "public/fpdf_edit.h"
 
+#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "fpdfsdk/include/fsdk_define.h"
 
 DLLEXPORT FPDF_PAGEOBJECT STDCALL
diff --git a/fpdfsdk/fxedit/DEPS b/fpdfsdk/fxedit/DEPS
new file mode 100644
index 0000000..8e0928c
--- /dev/null
+++ b/fpdfsdk/fxedit/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  '+core/fpdfapi/fpdf_font/include',
+]
diff --git a/fpdfsdk/fxedit/fxet_ap.cpp b/fpdfsdk/fxedit/fxet_ap.cpp
index a323403..8d57e41 100644
--- a/fpdfsdk/fxedit/fxet_ap.cpp
+++ b/fpdfsdk/fxedit/fxet_ap.cpp
@@ -4,8 +4,8 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_parser/include/fpdf_parser_decode.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "fpdfsdk/include/fxedit/fx_edit.h"
 #include "fpdfsdk/include/fxedit/fxet_edit.h"
 
diff --git a/fpdfsdk/fxedit/fxet_edit.cpp b/fpdfsdk/fxedit/fxet_edit.cpp
index d2a558f..b568440 100644
--- a/fpdfsdk/fxedit/fxet_edit.cpp
+++ b/fpdfsdk/fxedit/fxet_edit.cpp
@@ -8,7 +8,7 @@
 
 #include <algorithm>
 
-#include "core/include/fpdfapi/fpdf_resource.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 
 #define FX_EDIT_UNDO_MAXITEM 10000
 
diff --git a/fpdfsdk/javascript/DEPS b/fpdfsdk/javascript/DEPS
index a1f0ec3..80f4b76 100644
--- a/fpdfsdk/javascript/DEPS
+++ b/fpdfsdk/javascript/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   '+core/fdrm/crypto/include',
+  '+core/fpdfapi/fpdf_font/include',
   '+xfa/fxjse'
 ]
diff --git a/fpdfsdk/javascript/Document.cpp b/fpdfsdk/javascript/Document.cpp
index fe4cd7c..9b3df61 100644
--- a/fpdfsdk/javascript/Document.cpp
+++ b/fpdfsdk/javascript/Document.cpp
@@ -8,6 +8,7 @@
 
 #include <vector>
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 #include "fpdfsdk/include/fsdk_mgr.h"
diff --git a/fpdfsdk/javascript/Document.h b/fpdfsdk/javascript/Document.h
index 20862c8..c0ef840 100644
--- a/fpdfsdk/javascript/Document.h
+++ b/fpdfsdk/javascript/Document.h
@@ -13,7 +13,6 @@
 
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_textobject.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "fpdfsdk/javascript/JS_Define.h"
 
 class PrintParamsObj : public CJS_EmbedObj {
diff --git a/fpdfsdk/javascript/Field.cpp b/fpdfsdk/javascript/Field.cpp
index 4955124..198c833 100644
--- a/fpdfsdk/javascript/Field.cpp
+++ b/fpdfsdk/javascript/Field.cpp
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "fpdfsdk/include/fsdk_mgr.h"
 #include "fpdfsdk/include/javascript/IJavaScript.h"
diff --git a/fpdfsdk/pdfwindow/DEPS b/fpdfsdk/pdfwindow/DEPS
new file mode 100644
index 0000000..8e0928c
--- /dev/null
+++ b/fpdfsdk/pdfwindow/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  '+core/fpdfapi/fpdf_font/include',
+]
diff --git a/fpdfsdk/pdfwindow/PWL_Edit.cpp b/fpdfsdk/pdfwindow/PWL_Edit.cpp
index cf7e4ff..affb1be 100644
--- a/fpdfsdk/pdfwindow/PWL_Edit.cpp
+++ b/fpdfsdk/pdfwindow/PWL_Edit.cpp
@@ -8,9 +8,9 @@
 
 #include <vector>
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fxcrt/include/fx_safe_types.h"
 #include "core/fxcrt/include/fx_xml.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "core/include/fxge/fx_ge.h"
 #include "fpdfsdk/include/pdfwindow/PWL_Caret.h"
 #include "fpdfsdk/include/pdfwindow/PWL_EditCtrl.h"
diff --git a/fpdfsdk/pdfwindow/PWL_FontMap.cpp b/fpdfsdk/pdfwindow/PWL_FontMap.cpp
index 1ac55bc..298b744 100644
--- a/fpdfsdk/pdfwindow/PWL_FontMap.cpp
+++ b/fpdfsdk/pdfwindow/PWL_FontMap.cpp
@@ -6,9 +6,10 @@
 
 #include "fpdfsdk/include/pdfwindow/PWL_FontMap.h"
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
+#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
 #include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "fpdfsdk/include/pdfwindow/PWL_Wnd.h"
 
 namespace {
diff --git a/pdfium.gyp b/pdfium.gyp
index 44aac84..cb2cc98 100644
--- a/pdfium.gyp
+++ b/pdfium.gyp
@@ -317,13 +317,27 @@
         'core/fpdfapi/fpdf_edit/cpdf_pagecontentgenerator.cpp',
         'core/fpdfapi/fpdf_edit/fpdf_edit_create.cpp',
         'core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp',
-        'core/fpdfapi/fpdf_edit/fpdf_edit_image.cpp',
         'core/fpdfapi/fpdf_edit/include/cpdf_creator.h',
         'core/fpdfapi/fpdf_edit/include/cpdf_pagecontentgenerator.h',
+        'core/fpdfapi/fpdf_font/cpdf_cidfont.cpp',
+        'core/fpdfapi/fpdf_font/cpdf_cidfont.h',
+        'core/fpdfapi/fpdf_font/cpdf_font.cpp',
+        'core/fpdfapi/fpdf_font/cpdf_fontencoding.cpp',
+        'core/fpdfapi/fpdf_font/cpdf_simplefont.cpp',
+        'core/fpdfapi/fpdf_font/cpdf_simplefont.h',
+        'core/fpdfapi/fpdf_font/cpdf_truetypefont.cpp',
+        'core/fpdfapi/fpdf_font/cpdf_truetypefont.h',
+        'core/fpdfapi/fpdf_font/cpdf_type1font.cpp',
+        'core/fpdfapi/fpdf_font/cpdf_type1font.h',
+        'core/fpdfapi/fpdf_font/cpdf_type3char.cpp',
+        'core/fpdfapi/fpdf_font/cpdf_type3char.h',
+        'core/fpdfapi/fpdf_font/cpdf_type3font.cpp',
+        'core/fpdfapi/fpdf_font/cpdf_type3font.h',
         'core/fpdfapi/fpdf_font/font_int.h',
         'core/fpdfapi/fpdf_font/fpdf_font.cpp',
-        'core/fpdfapi/fpdf_font/fpdf_font_charset.cpp',
         'core/fpdfapi/fpdf_font/fpdf_font_cid.cpp',
+        'core/fpdfapi/fpdf_font/include/cpdf_font.h',
+        'core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h',
         'core/fpdfapi/fpdf_font/ttgsubtable.cpp',
         'core/fpdfapi/fpdf_font/ttgsubtable.h',
         'core/fpdfapi/fpdf_page/cpdf_allstates.cpp',
@@ -331,6 +345,8 @@
         'core/fpdfapi/fpdf_page/cpdf_clippath.cpp',
         'core/fpdfapi/fpdf_page/cpdf_clippathdata.cpp',
         'core/fpdfapi/fpdf_page/cpdf_clippathdata.h',
+        'core/fpdfapi/fpdf_page/cpdf_color.cpp',
+        'core/fpdfapi/fpdf_page/cpdf_colorspace.cpp',
         'core/fpdfapi/fpdf_page/cpdf_colorstate.cpp',
         'core/fpdfapi/fpdf_page/cpdf_colorstate.h',
         'core/fpdfapi/fpdf_page/cpdf_colorstatedata.cpp',
@@ -341,6 +357,7 @@
         'core/fpdfapi/fpdf_page/cpdf_contentmarkdata.h',
         'core/fpdfapi/fpdf_page/cpdf_contentmarkitem.cpp',
         'core/fpdfapi/fpdf_page/cpdf_contentmarkitem.h',
+        'core/fpdfapi/fpdf_page/cpdf_countedobject.h',
         'core/fpdfapi/fpdf_page/cpdf_form.cpp',
         'core/fpdfapi/fpdf_page/cpdf_formobject.cpp',
         'core/fpdfapi/fpdf_page/cpdf_generalstate.cpp',
@@ -348,7 +365,10 @@
         'core/fpdfapi/fpdf_page/cpdf_graphicstates.cpp',
         'core/fpdfapi/fpdf_page/cpdf_graphicstates.h',
         'core/fpdfapi/fpdf_page/cpdf_graphstate.h',
+        'core/fpdfapi/fpdf_page/cpdf_image.cpp',
         'core/fpdfapi/fpdf_page/cpdf_imageobject.cpp',
+        'core/fpdfapi/fpdf_page/cpdf_meshstream.cpp',
+        'core/fpdfapi/fpdf_page/cpdf_meshstream.h',
         'core/fpdfapi/fpdf_page/cpdf_page.cpp',
         'core/fpdfapi/fpdf_page/cpdf_pageobject.cpp',
         'core/fpdfapi/fpdf_page/cpdf_pageobjectholder.cpp',
@@ -357,23 +377,31 @@
         'core/fpdfapi/fpdf_page/cpdf_parseoptions.cpp',
         'core/fpdfapi/fpdf_page/cpdf_parseoptions.h',
         'core/fpdfapi/fpdf_page/cpdf_pathobject.cpp',
+        'core/fpdfapi/fpdf_page/cpdf_pattern.cpp',
+        'core/fpdfapi/fpdf_page/cpdf_pattern.h',
         'core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp',
+        'core/fpdfapi/fpdf_page/cpdf_shadingpattern.cpp',
+        'core/fpdfapi/fpdf_page/cpdf_shadingpattern.h',
         'core/fpdfapi/fpdf_page/cpdf_textobject.cpp',
         'core/fpdfapi/fpdf_page/cpdf_textstate.cpp',
         'core/fpdfapi/fpdf_page/cpdf_textstate.h',
         'core/fpdfapi/fpdf_page/cpdf_textstatedata.cpp',
+        'core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp',
+        'core/fpdfapi/fpdf_pgae/cpdf_tilingpattern.h',
         'core/fpdfapi/fpdf_page/fpdf_page_colors.cpp',
         'core/fpdfapi/fpdf_page/fpdf_page_doc.cpp',
         'core/fpdfapi/fpdf_page/fpdf_page_func.cpp',
-        'core/fpdfapi/fpdf_page/fpdf_page_image.cpp',
         'core/fpdfapi/fpdf_page/fpdf_page_parser.cpp',
         'core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp',
         'core/fpdfapi/fpdf_page/fpdf_page_pattern.cpp',
         'core/fpdfapi/fpdf_page/include/cpdf_clippath.h',
+        'core/fpdfapi/fpdf_page/include/cpdf_color.h',
+        'core/fpdfapi/fpdf_page/include/cpdf_colorspace.h',
         'core/fpdfapi/fpdf_page/include/cpdf_form.h',
         'core/fpdfapi/fpdf_page/include/cpdf_formobject.h',
         'core/fpdfapi/fpdf_page/include/cpdf_graphstate.h',
         'core/fpdfapi/fpdf_page/include/cpdf_generalstatedata.h',
+        'core/fpdfapi/fpdf_page/include/cpdf_image.h',
         'core/fpdfapi/fpdf_page/include/cpdf_imageobject.h',
         'core/fpdfapi/fpdf_page/include/cpdf_page.h',
         'core/fpdfapi/fpdf_page/include/cpdf_pageobject.h',
@@ -450,7 +478,6 @@
         'core/fpdfapi/include/cpdf_modulemgr.h',
         'core/fpdfapi/ipdf_rendermodule.h',
         'core/fpdfapi/ipdf_pagemodule.h',
-        'core/include/fpdfapi/fpdf_resource.h',
       ],
     },
     {
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 64eef26..4ec18ee 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -15,10 +15,9 @@
 // pointers
 // or long integer numbers.
 
-#define FPDF_ARGB(a, r, g, b)                                     \
-  ((((uint32_t)(((uint8_t)(b) | ((FX_WORD)((uint8_t)(g)) << 8)) | \
-                (((FX_DWORD)(uint8_t)(r)) << 16)))) |             \
-   (((FX_DWORD)(uint8_t)(a)) << 24))
+#define FPDF_ARGB(a, r, g, b)                                      \
+  ((uint32_t)(((uint32_t)(b)&0xff) | (((uint32_t)(g)&0xff) << 8) | \
+              (((uint32_t)(r)&0xff) << 16) | (((uint32_t)(a)&0xff) << 24)))
 #define FPDF_GetBValue(argb) ((uint8_t)(argb))
 #define FPDF_GetGValue(argb) ((uint8_t)(((uint16_t)(argb)) >> 8))
 #define FPDF_GetRValue(argb) ((uint8_t)((argb) >> 16))
diff --git a/xfa/fxfa/app/DEPS b/xfa/fxfa/app/DEPS
index 6678121..a191196 100644
--- a/xfa/fxfa/app/DEPS
+++ b/xfa/fxfa/app/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   '+core/fdrm/crypto/include',
+  '+core/fpdfapi/fpdf_font/include',
   '+core/fpdfapi/fpdf_page/include',
   '+core/fpdfapi/fpdf_parser/include',
 ]
diff --git a/xfa/fxfa/app/xfa_fontmgr.cpp b/xfa/fxfa/app/xfa_fontmgr.cpp
index 25a291f..6ac5f0c 100644
--- a/xfa/fxfa/app/xfa_fontmgr.cpp
+++ b/xfa/fxfa/app/xfa_fontmgr.cpp
@@ -8,9 +8,9 @@
 
 #include <algorithm>
 
+#include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
-#include "core/include/fpdfapi/fpdf_resource.h"
 #include "xfa/fxfa/app/xfa_ffapp.h"
 #include "xfa/fxfa/app/xfa_ffdoc.h"