Cleanup CFX_UnicodeEncoding and remove IFX_FontEncoding.
[pdfium.git] / core / src / fpdfapi / fpdf_edit / fpdf_edit_doc.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../../include/fpdfapi/fpdf_page.h"
8 #include "../../../include/fpdfapi/fpdf_module.h"
9 #include "../fpdf_page/pageint.h"
10 #include <limits.h>
11 CPDF_Document::CPDF_Document() : CPDF_IndirectObjects(NULL) {
12   m_pRootDict = NULL;
13   m_pInfoDict = NULL;
14   m_bLinearized = FALSE;
15   m_dwFirstPageNo = 0;
16   m_dwFirstPageObjNum = 0;
17   m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this);
18   m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this);
19 }
20 void CPDF_Document::CreateNewDoc() {
21   ASSERT(m_pRootDict == NULL && m_pInfoDict == NULL);
22   m_pRootDict = new CPDF_Dictionary;
23   m_pRootDict->SetAtName("Type", "Catalog");
24   int objnum = AddIndirectObject(m_pRootDict);
25   CPDF_Dictionary* pPages = new CPDF_Dictionary;
26   pPages->SetAtName("Type", "Pages");
27   pPages->SetAtNumber("Count", 0);
28   pPages->SetAt("Kids", new CPDF_Array);
29   objnum = AddIndirectObject(pPages);
30   m_pRootDict->SetAtReference("Pages", this, objnum);
31   m_pInfoDict = new CPDF_Dictionary;
32   AddIndirectObject(m_pInfoDict);
33 }
34 static const FX_WCHAR g_FX_CP874Unicodes[128] = {
35     0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, 0x0000,
36     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2018,
37     0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x0000, 0x0000,
38     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00A0, 0x0E01, 0x0E02, 0x0E03,
39     0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C,
40     0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15,
41     0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E,
42     0x0E1F, 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27,
43     0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, 0x0E30,
44     0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, 0x0E38, 0x0E39,
45     0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, 0x0E40, 0x0E41, 0x0E42,
46     0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B,
47     0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54,
48     0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000,
49     0x0000, 0x0000,
50 };
51 static const FX_WCHAR g_FX_CP1250Unicodes[128] = {
52     0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000,
53     0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, 0x0000, 0x2018,
54     0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161,
55     0x203A, 0x015B, 0x0165, 0x017E, 0x017A, 0x00A0, 0x02C7, 0x02D8, 0x0141,
56     0x00A4, 0x0104, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC,
57     0x00AD, 0x00AE, 0x017B, 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5,
58     0x00B6, 0x00B7, 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E,
59     0x017C, 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
60     0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, 0x0110,
61     0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E,
62     0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, 0x0155, 0x00E1, 0x00E2,
63     0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB,
64     0x011B, 0x00ED, 0x00EE, 0x010F, 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4,
65     0x0151, 0x00F6, 0x00F7, 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD,
66     0x0163, 0x02D9,
67 };
68 static const FX_WCHAR g_FX_CP1251Unicodes[128] = {
69     0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC,
70     0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, 0x0452, 0x2018,
71     0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459,
72     0x203A, 0x045A, 0x045C, 0x045B, 0x045F, 0x00A0, 0x040E, 0x045E, 0x0408,
73     0x00A4, 0x0490, 0x00A6, 0x00A7, 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC,
74     0x00AD, 0x00AE, 0x0407, 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5,
75     0x00B6, 0x00B7, 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455,
76     0x0457, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
77     0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420,
78     0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429,
79     0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432,
80     0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B,
81     0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444,
82     0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D,
83     0x044E, 0x044F,
84 };
85 static const FX_WCHAR g_FX_CP1253Unicodes[128] = {
86     0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000,
87     0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2018,
88     0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000,
89     0x203A, 0x0000, 0x0000, 0x0000, 0x0000, 0x00A0, 0x0385, 0x0386, 0x00A3,
90     0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC,
91     0x00AD, 0x00AE, 0x2015, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5,
92     0x00B6, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E,
93     0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
94     0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
95     0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
96     0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03B0, 0x03B1, 0x03B2,
97     0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB,
98     0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4,
99     0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD,
100     0x03CE, 0x0000,
101 };
102 static const FX_WCHAR g_FX_CP1254Unicodes[128] = {
103     0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6,
104     0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, 0x0000, 0x2018,
105     0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161,
106     0x203A, 0x0153, 0x0000, 0x0000, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3,
107     0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC,
108     0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5,
109     0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE,
110     0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
111     0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x011E,
112     0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9,
113     0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, 0x00E0, 0x00E1, 0x00E2,
114     0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB,
115     0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4,
116     0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131,
117     0x015F, 0x00FF,
118 };
119 static const FX_WCHAR g_FX_CP1255Unicodes[128] = {
120     0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6,
121     0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2018,
122     0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0000,
123     0x203A, 0x0000, 0x0000, 0x0000, 0x0000, 0x00A0, 0x00A1, 0x00A2, 0x00A3,
124     0x20AA, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC,
125     0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5,
126     0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE,
127     0x00BF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
128     0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, 0x05C0,
129     0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x0000,
130     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x05D0, 0x05D1, 0x05D2,
131     0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB,
132     0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4,
133     0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E,
134     0x200F, 0x0000,
135 };
136 static const FX_WCHAR g_FX_CP1256Unicodes[128] = {
137     0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6,
138     0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, 0x06AF, 0x2018,
139     0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06A9, 0x2122, 0x0691,
140     0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, 0x00A0, 0x060C, 0x00A2, 0x00A3,
141     0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC,
142     0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5,
143     0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE,
144     0x061F, 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
145     0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630,
146     0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, 0x0637, 0x0638,
147     0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643, 0x00E0, 0x0644, 0x00E2,
148     0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB,
149     0x0649, 0x064A, 0x00EE, 0x00EF, 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4,
150     0x064F, 0x0650, 0x00F7, 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E,
151     0x200F, 0x06D2,
152 };
153 static const FX_WCHAR g_FX_CP1257Unicodes[128] = {
154     0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000,
155     0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, 0x0000, 0x2018,
156     0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0000,
157     0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, 0x00A0, 0x0000, 0x00A2, 0x00A3,
158     0x00A4, 0x0000, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC,
159     0x00AD, 0x00AE, 0x00C6, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5,
160     0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE,
161     0x00E6, 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112,
162     0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, 0x0160,
163     0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141,
164     0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, 0x0105, 0x012F, 0x0101,
165     0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117,
166     0x0123, 0x0137, 0x012B, 0x013C, 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D,
167     0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C,
168     0x017E, 0x02D9,
169 };
170 typedef struct {
171   uint8_t m_Charset;
172   const FX_WCHAR* m_pUnicodes;
173 } FX_CharsetUnicodes;
174 const FX_CharsetUnicodes g_FX_CharsetUnicodes[] = {
175     {FXFONT_THAI_CHARSET, g_FX_CP874Unicodes},
176     {FXFONT_EASTEUROPE_CHARSET, g_FX_CP1250Unicodes},
177     {FXFONT_RUSSIAN_CHARSET, g_FX_CP1251Unicodes},
178     {FXFONT_GREEK_CHARSET, g_FX_CP1253Unicodes},
179     {FXFONT_TURKISH_CHARSET, g_FX_CP1254Unicodes},
180     {FXFONT_HEBREW_CHARSET, g_FX_CP1255Unicodes},
181     {FXFONT_ARABIC_CHARSET, g_FX_CP1256Unicodes},
182     {FXFONT_BALTIC_CHARSET, g_FX_CP1257Unicodes},
183 };
184 #if (_FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_)
185 static void _InsertWidthArray(HDC hDC,
186                               int start,
187                               int end,
188                               CPDF_Array* pWidthArray) {
189   int size = end - start + 1;
190   int* widths = FX_Alloc(int, size);
191   GetCharWidth(hDC, start, end, widths);
192   int i;
193   for (i = 1; i < size; i++)
194     if (widths[i] != *widths) {
195       break;
196     }
197   if (i == size) {
198     int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
199     pWidthArray->AddInteger(first + size - 1);
200     pWidthArray->AddInteger(*widths);
201   } else {
202     CPDF_Array* pWidthArray1 = new CPDF_Array;
203     pWidthArray->Add(pWidthArray1);
204     for (i = 0; i < size; i++) {
205       pWidthArray1->AddInteger(widths[i]);
206     }
207   }
208   FX_Free(widths);
209 }
210 CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTW* pLogFont,
211                                          FX_BOOL bVert,
212                                          FX_BOOL bTranslateName) {
213   LOGFONTA lfa;
214   FXSYS_memcpy(&lfa, pLogFont, (char*)lfa.lfFaceName - (char*)&lfa);
215   CFX_ByteString face = CFX_ByteString::FromUnicode(pLogFont->lfFaceName);
216   if (face.GetLength() >= LF_FACESIZE) {
217     return NULL;
218   }
219   FXSYS_strcpy(lfa.lfFaceName, face.c_str());
220   return AddWindowsFont(&lfa, bVert, bTranslateName);
221 }
222 extern CFX_ByteString _FPDF_GetNameFromTT(const uint8_t* name_table,
223                                           FX_DWORD name);
224 CFX_ByteString _FPDF_GetPSNameFromTT(HDC hDC) {
225   CFX_ByteString result;
226   DWORD size = ::GetFontData(hDC, 'eman', 0, NULL, 0);
227   if (size != GDI_ERROR) {
228     LPBYTE buffer = FX_Alloc(BYTE, size);
229     ::GetFontData(hDC, 'eman', 0, buffer, size);
230     result = _FPDF_GetNameFromTT(buffer, 6);
231     FX_Free(buffer);
232   }
233   return result;
234 }
235 CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont,
236                                          FX_BOOL bVert,
237                                          FX_BOOL bTranslateName) {
238   pLogFont->lfHeight = -1000;
239   pLogFont->lfWidth = 0;
240   HGDIOBJ hFont = CreateFontIndirectA(pLogFont);
241   HDC hDC = CreateCompatibleDC(NULL);
242   hFont = SelectObject(hDC, hFont);
243   int tm_size = GetOutlineTextMetrics(hDC, 0, NULL);
244   if (tm_size == 0) {
245     hFont = SelectObject(hDC, hFont);
246     DeleteObject(hFont);
247     DeleteDC(hDC);
248     return NULL;
249   }
250   LPBYTE tm_buf = FX_Alloc(BYTE, tm_size);
251   OUTLINETEXTMETRIC* ptm = (OUTLINETEXTMETRIC*)tm_buf;
252   GetOutlineTextMetrics(hDC, tm_size, ptm);
253   int flags = 0, italicangle, ascend, descend, capheight, bbox[4];
254   if (pLogFont->lfItalic) {
255     flags |= PDFFONT_ITALIC;
256   }
257   if ((pLogFont->lfPitchAndFamily & 3) == FIXED_PITCH) {
258     flags |= PDFFONT_FIXEDPITCH;
259   }
260   if ((pLogFont->lfPitchAndFamily & 0xf8) == FF_ROMAN) {
261     flags |= PDFFONT_SERIF;
262   }
263   if ((pLogFont->lfPitchAndFamily & 0xf8) == FF_SCRIPT) {
264     flags |= PDFFONT_SCRIPT;
265   }
266   FX_BOOL bCJK = pLogFont->lfCharSet == CHINESEBIG5_CHARSET ||
267                  pLogFont->lfCharSet == GB2312_CHARSET ||
268                  pLogFont->lfCharSet == HANGEUL_CHARSET ||
269                  pLogFont->lfCharSet == SHIFTJIS_CHARSET;
270   CFX_ByteString basefont;
271   if (bTranslateName && bCJK) {
272     basefont = _FPDF_GetPSNameFromTT(hDC);
273   }
274   if (basefont.IsEmpty()) {
275     basefont = pLogFont->lfFaceName;
276   }
277   italicangle = ptm->otmItalicAngle / 10;
278   ascend = ptm->otmrcFontBox.top;
279   descend = ptm->otmrcFontBox.bottom;
280   capheight = ptm->otmsCapEmHeight;
281   bbox[0] = ptm->otmrcFontBox.left;
282   bbox[1] = ptm->otmrcFontBox.bottom;
283   bbox[2] = ptm->otmrcFontBox.right;
284   bbox[3] = ptm->otmrcFontBox.top;
285   FX_Free(tm_buf);
286   basefont.Replace(" ", "");
287   CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
288   pBaseDict->SetAtName("Type", "Font");
289   CPDF_Dictionary* pFontDict = pBaseDict;
290   if (!bCJK) {
291     if (pLogFont->lfCharSet == ANSI_CHARSET ||
292         pLogFont->lfCharSet == DEFAULT_CHARSET ||
293         pLogFont->lfCharSet == SYMBOL_CHARSET) {
294       if (pLogFont->lfCharSet == SYMBOL_CHARSET) {
295         flags |= PDFFONT_SYMBOLIC;
296       } else {
297         flags |= PDFFONT_NONSYMBOLIC;
298       }
299       pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
300     } else {
301       flags |= PDFFONT_NONSYMBOLIC;
302       int i;
303       for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes);
304            i++)
305         if (g_FX_CharsetUnicodes[i].m_Charset == pLogFont->lfCharSet) {
306           break;
307         }
308       if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
309         CPDF_Dictionary* pEncoding = new CPDF_Dictionary;
310         pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
311         CPDF_Array* pArray = new CPDF_Array;
312         pArray->AddInteger(128);
313         const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
314         for (int j = 0; j < 128; j++) {
315           CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
316           if (name.IsEmpty()) {
317             pArray->AddName(FX_BSTRC(".notdef"));
318           } else {
319             pArray->AddName(name);
320           }
321         }
322         pEncoding->SetAt(FX_BSTRC("Differences"), pArray);
323         AddIndirectObject(pEncoding);
324         pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding);
325       }
326     }
327     if (pLogFont->lfWeight > FW_MEDIUM && pLogFont->lfItalic) {
328       basefont += ",BoldItalic";
329     } else if (pLogFont->lfWeight > FW_MEDIUM) {
330       basefont += ",Bold";
331     } else if (pLogFont->lfItalic) {
332       basefont += ",Italic";
333     }
334     pBaseDict->SetAtName("Subtype", "TrueType");
335     pBaseDict->SetAtName("BaseFont", basefont);
336     pBaseDict->SetAtNumber("FirstChar", 32);
337     pBaseDict->SetAtNumber("LastChar", 255);
338     int char_widths[224];
339     GetCharWidth(hDC, 32, 255, char_widths);
340     CPDF_Array* pWidths = new CPDF_Array;
341     for (int i = 0; i < 224; i++) {
342       pWidths->AddInteger(char_widths[i]);
343     }
344     pBaseDict->SetAt("Widths", pWidths);
345   } else {
346     flags |= PDFFONT_NONSYMBOLIC;
347     pFontDict = new CPDF_Dictionary;
348     CFX_ByteString cmap;
349     CFX_ByteString ordering;
350     int supplement;
351     CPDF_Array* pWidthArray = new CPDF_Array;
352     switch (pLogFont->lfCharSet) {
353       case CHINESEBIG5_CHARSET:
354         cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
355         ordering = "CNS1";
356         supplement = 4;
357         pWidthArray->AddInteger(1);
358         _InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray);
359         break;
360       case GB2312_CHARSET:
361         cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
362         ordering = "GB1", supplement = 2;
363         pWidthArray->AddInteger(7716);
364         _InsertWidthArray(hDC, 0x20, 0x20, pWidthArray);
365         pWidthArray->AddInteger(814);
366         _InsertWidthArray(hDC, 0x21, 0x7e, pWidthArray);
367         break;
368       case HANGEUL_CHARSET:
369         cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
370         ordering = "Korea1";
371         supplement = 2;
372         pWidthArray->AddInteger(1);
373         _InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray);
374         break;
375       case SHIFTJIS_CHARSET:
376         cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
377         ordering = "Japan1";
378         supplement = 5;
379         pWidthArray->AddInteger(231);
380         _InsertWidthArray(hDC, 0x20, 0x7d, pWidthArray);
381         pWidthArray->AddInteger(326);
382         _InsertWidthArray(hDC, 0xa0, 0xa0, pWidthArray);
383         pWidthArray->AddInteger(327);
384         _InsertWidthArray(hDC, 0xa1, 0xdf, pWidthArray);
385         pWidthArray->AddInteger(631);
386         _InsertWidthArray(hDC, 0x7e, 0x7e, pWidthArray);
387         break;
388     }
389     pBaseDict->SetAtName("Subtype", "Type0");
390     pBaseDict->SetAtName("BaseFont", basefont);
391     pBaseDict->SetAtName("Encoding", cmap);
392     pFontDict->SetAt("W", pWidthArray);
393     pFontDict->SetAtName("Type", "Font");
394     pFontDict->SetAtName("Subtype", "CIDFontType2");
395     pFontDict->SetAtName("BaseFont", basefont);
396     CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
397     pCIDSysInfo->SetAtString("Registry", "Adobe");
398     pCIDSysInfo->SetAtString("Ordering", ordering);
399     pCIDSysInfo->SetAtInteger("Supplement", supplement);
400     pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
401     CPDF_Array* pArray = new CPDF_Array;
402     pBaseDict->SetAt("DescendantFonts", pArray);
403     AddIndirectObject(pFontDict);
404     pArray->AddReference(this, pFontDict);
405   }
406   AddIndirectObject(pBaseDict);
407   CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
408   pFontDesc->SetAtName("Type", "FontDescriptor");
409   pFontDesc->SetAtName("FontName", basefont);
410   pFontDesc->SetAtInteger("Flags", flags);
411   CPDF_Array* pBBox = new CPDF_Array;
412   for (int i = 0; i < 4; i++) {
413     pBBox->AddInteger(bbox[i]);
414   }
415   pFontDesc->SetAt("FontBBox", pBBox);
416   pFontDesc->SetAtInteger("ItalicAngle", italicangle);
417   pFontDesc->SetAtInteger("Ascent", ascend);
418   pFontDesc->SetAtInteger("Descent", descend);
419   pFontDesc->SetAtInteger("CapHeight", capheight);
420   pFontDesc->SetAtInteger("StemV", pLogFont->lfWeight / 5);
421   AddIndirectObject(pFontDesc);
422   pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
423   hFont = SelectObject(hDC, hFont);
424   DeleteObject(hFont);
425   DeleteDC(hDC);
426   return LoadFont(pBaseDict);
427 }
428 #endif
429
430 #if (_FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_)
431 uint32_t FX_GetLangHashCode(const FX_CHAR* pStr) {
432   FXSYS_assert(pStr != NULL);
433   int32_t iLength = FXSYS_strlen(pStr);
434   const FX_CHAR* pStrEnd = pStr + iLength;
435   uint32_t uHashCode = 0;
436   while (pStr < pStrEnd) {
437     uHashCode = 31 * uHashCode + tolower(*pStr++);
438   }
439   return uHashCode;
440 }
441 struct FX_LANG2CS {
442   FX_DWORD uLang;
443   int uCharset;
444 } * FX_LPLANG2CS;
445 static const FX_LANG2CS gs_FXLang2CharsetTable[] = {
446     {3109, 0},         {3121, 178}, {3129, 162}, {3139, 204}, {3141, 204},
447     {3166, 0},         {3184, 238}, {3197, 0},   {3201, 0},   {3239, 161},
448     {3241, 0},         {3246, 0},   {3247, 186}, {3248, 0},   {3259, 178},
449     {3267, 0},         {3273, 0},   {3276, 0},   {3301, 0},   {3310, 1},
450     {3325, 177},       {3329, 1},   {3338, 238}, {3341, 238}, {3345, 1},
451     {3355, 0},         {3370, 0},   {3371, 0},   {3383, 128}, {3424, 204},
452     {3427, 1},         {3428, 129}, {3436, 178}, {3464, 186}, {3466, 186},
453     {3486, 204},       {3487, 0},   {3493, 1},   {3494, 0},   {3508, 0},
454     {3518, 0},         {3520, 0},   {3569, 1},   {3580, 238}, {3588, 0},
455     {3645, 238},       {3651, 204}, {3672, 238}, {3673, 238}, {3678, 238},
456     {3679, 238},       {3683, 0},   {3684, 0},   {3693, 1},   {3697, 1},
457     {3700, 222},       {3710, 162}, {3734, 204}, {3741, 178}, {3749, 162},
458     {3763, 163},       {3886, 134}, {105943, 0}, {106375, 1}, {3923451837, 134},
459     {3923451838, 136},
460 };
461 static FX_WORD FX_GetCsFromLangCode(uint32_t uCode) {
462   int32_t iStart = 0;
463   int32_t iEnd = sizeof(gs_FXLang2CharsetTable) / sizeof(FX_LANG2CS) - 1;
464   while (iStart <= iEnd) {
465     int32_t iMid = (iStart + iEnd) / 2;
466     const FX_LANG2CS& charset = gs_FXLang2CharsetTable[iMid];
467     if (uCode == charset.uLang) {
468       return charset.uCharset;
469     }
470     if (uCode < charset.uLang) {
471       iEnd = iMid - 1;
472     } else {
473       iStart = iMid + 1;
474     }
475   };
476   return 0;
477 }
478 static FX_WORD FX_GetCharsetFromLang(const FX_CHAR* pLang, int32_t iLength) {
479   FXSYS_assert(pLang);
480   if (iLength < 0) {
481     iLength = FXSYS_strlen(pLang);
482   }
483   uint32_t uHash = FX_GetLangHashCode(pLang);
484   return FX_GetCsFromLangCode(uHash);
485 }
486 static void _CFString2CFXByteString(CFStringRef src, CFX_ByteString& dest) {
487   SInt32 len = CFStringGetLength(src);
488   CFRange range = CFRangeMake(0, len);
489   CFIndex used = 0;
490   UInt8* pBuffer = (UInt8*)calloc(len + 1, sizeof(UInt8));
491   CFStringGetBytes(src, range, kCFStringEncodingASCII, 0, false, pBuffer, len,
492                    &used);
493   dest = (FX_CHAR*)pBuffer;
494   free(pBuffer);
495 }
496 FX_BOOL IsHasCharSet(CFArrayRef languages, const CFX_DWordArray& charSets) {
497   int iCount = charSets.GetSize();
498   for (int i = 0; i < CFArrayGetCount(languages); ++i) {
499     CFStringRef language = (CFStringRef)CFArrayGetValueAtIndex(languages, i);
500     FX_DWORD CharSet = FX_GetCharsetFromLang(
501         CFStringGetCStringPtr(language, kCFStringEncodingMacRoman), -1);
502     for (int j = 0; j < iCount; ++j) {
503       if (CharSet == charSets[j]) {
504         return TRUE;
505       }
506     }
507   }
508   return FALSE;
509 }
510 void FX_GetCharWidth(CTFontRef font, UniChar start, UniChar end, int* width) {
511   CGFloat size = CTFontGetSize(font);
512   for (; start <= end; ++start) {
513     CGGlyph pGlyph = 0;
514     CFIndex count = 1;
515     CTFontGetGlyphsForCharacters(font, &start, &pGlyph, count);
516     CGSize advances;
517     CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &pGlyph,
518                                &advances, 1);
519     *width = (int)(advances.width / size * 1000);
520     width++;
521   }
522 }
523 static void _InsertWidthArray(CTFontRef font,
524                               int start,
525                               int end,
526                               CPDF_Array* pWidthArray) {
527   int size = end - start + 1;
528   int* widths = FX_Alloc(int, size);
529   FX_GetCharWidth(font, start, end, widths);
530   int i;
531   for (i = 1; i < size; i++)
532     if (widths[i] != *widths) {
533       break;
534     }
535   if (i == size) {
536     int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
537     pWidthArray->AddInteger(first + size - 1);
538     pWidthArray->AddInteger(*widths);
539   } else {
540     CPDF_Array* pWidthArray1 = new CPDF_Array;
541     pWidthArray->Add(pWidthArray1);
542     for (i = 0; i < size; i++) {
543       pWidthArray1->AddInteger(widths[i]);
544     }
545   }
546   FX_Free(widths);
547 }
548 CPDF_Font* CPDF_Document::AddMacFont(CTFontRef pFont,
549                                      FX_BOOL bVert,
550                                      FX_BOOL bTranslateName) {
551   CTFontRef font = (CTFontRef)pFont;
552   CTFontDescriptorRef descriptor = CTFontCopyFontDescriptor(font);
553   if (descriptor == NULL) {
554     return NULL;
555   }
556   CFX_ByteString basefont;
557   FX_BOOL bCJK = FALSE;
558   int flags = 0, italicangle = 0, ascend = 0, descend = 0, capheight = 0,
559       bbox[4];
560   FXSYS_memset(bbox, 0, sizeof(int) * 4);
561   CFArrayRef languages = (CFArrayRef)CTFontDescriptorCopyAttribute(
562       descriptor, kCTFontLanguagesAttribute);
563   if (languages == NULL) {
564     CFRelease(descriptor);
565     return NULL;
566   }
567   CFX_DWordArray charSets;
568   charSets.Add(FXFONT_CHINESEBIG5_CHARSET);
569   charSets.Add(FXFONT_GB2312_CHARSET);
570   charSets.Add(FXFONT_HANGEUL_CHARSET);
571   charSets.Add(FXFONT_SHIFTJIS_CHARSET);
572   if (IsHasCharSet(languages, charSets)) {
573     bCJK = TRUE;
574   }
575   CFRelease(descriptor);
576   CFDictionaryRef traits = (CFDictionaryRef)CTFontCopyTraits(font);
577   if (traits == NULL) {
578     CFRelease(languages);
579     return NULL;
580   }
581   CFNumberRef sybolicTrait =
582       (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait);
583   CTFontSymbolicTraits trait = 0;
584   CFNumberGetValue(sybolicTrait, kCFNumberSInt32Type, &trait);
585   if (trait & kCTFontItalicTrait) {
586     flags |= PDFFONT_ITALIC;
587   }
588   if (trait & kCTFontMonoSpaceTrait) {
589     flags |= PDFFONT_FIXEDPITCH;
590   }
591   if (trait & kCTFontModernSerifsClass) {
592     flags |= PDFFONT_SERIF;
593   }
594   if (trait & kCTFontScriptsClass) {
595     flags |= PDFFONT_SCRIPT;
596   }
597   CFNumberRef weightTrait =
598       (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait);
599   Float32 weight = 0;
600   CFNumberGetValue(weightTrait, kCFNumberFloat32Type, &weight);
601   italicangle = CTFontGetSlantAngle(font);
602   ascend = CTFontGetAscent(font);
603   descend = CTFontGetDescent(font);
604   capheight = CTFontGetCapHeight(font);
605   CGRect box = CTFontGetBoundingBox(font);
606   bbox[0] = box.origin.x;
607   bbox[1] = box.origin.y;
608   bbox[2] = box.origin.x + box.size.width;
609   bbox[3] = box.origin.y + box.size.height;
610   if (bTranslateName && bCJK) {
611     CFStringRef postName = CTFontCopyPostScriptName(font);
612     _CFString2CFXByteString(postName, basefont);
613     CFRelease(postName);
614   }
615   if (basefont.IsEmpty()) {
616     CFStringRef fullName = CTFontCopyFullName(font);
617     _CFString2CFXByteString(fullName, basefont);
618     CFRelease(fullName);
619   }
620   basefont.Replace(" ", "");
621   CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
622   CPDF_Dictionary* pFontDict = pBaseDict;
623   if (!bCJK) {
624     charSets.RemoveAll();
625     charSets.Add(FXFONT_ANSI_CHARSET);
626     charSets.Add(FXFONT_DEFAULT_CHARSET);
627     charSets.Add(FXFONT_SYMBOL_CHARSET);
628     if (IsHasCharSet(languages, charSets)) {
629       charSets.RemoveAll();
630       charSets.Add(FXFONT_SYMBOL_CHARSET);
631       if (IsHasCharSet(languages, charSets)) {
632         flags |= PDFFONT_SYMBOLIC;
633       } else {
634         flags |= PDFFONT_NONSYMBOLIC;
635       }
636       pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
637     } else {
638       flags |= PDFFONT_NONSYMBOLIC;
639       size_t i;
640       for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes);
641            i++) {
642         charSets.RemoveAll();
643         charSets.Add(g_FX_CharsetUnicodes[i].m_Charset);
644         if (IsHasCharSet(languages, charSets)) {
645           break;
646         }
647       }
648       if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
649         CPDF_Dictionary* pEncoding = new CPDF_Dictionary;
650         pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
651         CPDF_Array* pArray = new CPDF_Array;
652         pArray->AddInteger(128);
653         const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
654         for (int j = 0; j < 128; j++) {
655           CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
656           if (name.IsEmpty()) {
657             pArray->AddName(FX_BSTRC(".notdef"));
658           } else {
659             pArray->AddName(name);
660           }
661         }
662         pEncoding->SetAt(FX_BSTRC("Differences"), pArray);
663         AddIndirectObject(pEncoding);
664         pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding);
665       }
666     }
667     if (weight > 0.0 && trait & kCTFontItalicTrait) {
668       basefont += ",BoldItalic";
669     } else if (weight > 0.0) {
670       basefont += ",Bold";
671     } else if (trait & kCTFontItalicTrait) {
672       basefont += ",Italic";
673     }
674     pBaseDict->SetAtName("Subtype", "TrueType");
675     pBaseDict->SetAtName("BaseFont", basefont);
676     pBaseDict->SetAtNumber("FirstChar", 32);
677     pBaseDict->SetAtNumber("LastChar", 255);
678     int char_widths[224];
679     FX_GetCharWidth(font, 32, 255, char_widths);
680     CPDF_Array* pWidths = new CPDF_Array;
681     for (int i = 0; i < 224; i++) {
682       pWidths->AddInteger(char_widths[i]);
683     }
684     pBaseDict->SetAt("Widths", pWidths);
685   } else {
686     flags |= PDFFONT_NONSYMBOLIC;
687     CPDF_Array* pArray = NULL;
688     pFontDict = new CPDF_Dictionary;
689     CFX_ByteString cmap;
690     CFX_ByteString ordering;
691     int supplement;
692     FX_BOOL bFound = FALSE;
693     CPDF_Array* pWidthArray = new CPDF_Array;
694     charSets.RemoveAll();
695     charSets.Add(FXFONT_CHINESEBIG5_CHARSET);
696     if (IsHasCharSet(languages, charSets)) {
697       cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
698       ordering = "CNS1";
699       supplement = 4;
700       pWidthArray->AddInteger(1);
701       _InsertWidthArray(font, 0x20, 0x7e, pWidthArray);
702       bFound = TRUE;
703     }
704     charSets.RemoveAll();
705     charSets.Add(FXFONT_GB2312_CHARSET);
706     if (!bFound && IsHasCharSet(languages, charSets)) {
707       cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
708       ordering = "GB1", supplement = 2;
709       pWidthArray->AddInteger(7716);
710       _InsertWidthArray(font, 0x20, 0x20, pWidthArray);
711       pWidthArray->AddInteger(814);
712       _InsertWidthArray(font, 0x21, 0x7e, pWidthArray);
713       bFound = TRUE;
714     }
715     charSets.RemoveAll();
716     charSets.Add(FXFONT_HANGEUL_CHARSET);
717     if (!bFound && IsHasCharSet(languages, charSets)) {
718       cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
719       ordering = "Korea1";
720       supplement = 2;
721       pWidthArray->AddInteger(1);
722       _InsertWidthArray(font, 0x20, 0x7e, pWidthArray);
723       bFound = TRUE;
724     }
725     charSets.RemoveAll();
726     charSets.Add(FXFONT_SHIFTJIS_CHARSET);
727     if (!bFound && IsHasCharSet(languages, charSets)) {
728       cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
729       ordering = "Japan1";
730       supplement = 5;
731       pWidthArray->AddInteger(231);
732       _InsertWidthArray(font, 0x20, 0x7d, pWidthArray);
733       pWidthArray->AddInteger(326);
734       _InsertWidthArray(font, 0xa0, 0xa0, pWidthArray);
735       pWidthArray->AddInteger(327);
736       _InsertWidthArray(font, 0xa1, 0xdf, pWidthArray);
737       pWidthArray->AddInteger(631);
738       _InsertWidthArray(font, 0x7e, 0x7e, pWidthArray);
739     }
740     pBaseDict->SetAtName("Subtype", "Type0");
741     pBaseDict->SetAtName("BaseFont", basefont);
742     pBaseDict->SetAtName("Encoding", cmap);
743     pFontDict->SetAt("W", pWidthArray);
744     pFontDict->SetAtName("Type", "Font");
745     pFontDict->SetAtName("Subtype", "CIDFontType2");
746     pFontDict->SetAtName("BaseFont", basefont);
747     CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
748     pCIDSysInfo->SetAtString("Registry", "Adobe");
749     pCIDSysInfo->SetAtString("Ordering", ordering);
750     pCIDSysInfo->SetAtInteger("Supplement", supplement);
751     pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
752     pArray = new CPDF_Array;
753     pBaseDict->SetAt("DescendantFonts", pArray);
754     AddIndirectObject(pFontDict);
755     pArray->AddReference(this, pFontDict);
756   }
757   AddIndirectObject(pBaseDict);
758   CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
759   pFontDesc->SetAtName("Type", "FontDescriptor");
760   pFontDesc->SetAtName("FontName", basefont);
761   pFontDesc->SetAtInteger("Flags", flags);
762   CPDF_Array* pBBox = new CPDF_Array;
763   for (int i = 0; i < 4; i++) {
764     pBBox->AddInteger(bbox[i]);
765   }
766   pFontDesc->SetAt("FontBBox", pBBox);
767   pFontDesc->SetAtInteger("ItalicAngle", italicangle);
768   pFontDesc->SetAtInteger("Ascent", ascend);
769   pFontDesc->SetAtInteger("Descent", descend);
770   pFontDesc->SetAtInteger("CapHeight", capheight);
771   CGFloat fStemV = 0;
772   int16_t min_width = SHRT_MAX;
773   static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
774   const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
775   CGGlyph glyphs[count];
776   CGRect boundingRects[count];
777   if (CTFontGetGlyphsForCharacters(font, stem_chars, glyphs, count)) {
778     CTFontGetBoundingRectsForGlyphs(font, kCTFontHorizontalOrientation, glyphs,
779                                     boundingRects, count);
780     for (size_t i = 0; i < count; i++) {
781       int16_t width = boundingRects[i].size.width;
782       if (width > 0 && width < min_width) {
783         min_width = width;
784         fStemV = min_width;
785       }
786     }
787   }
788   pFontDesc->SetAtInteger("StemV", fStemV);
789   AddIndirectObject(pFontDesc);
790   pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
791   CFRelease(traits);
792   CFRelease(languages);
793   return LoadFont(pBaseDict);
794 }
795 #endif  // (_FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_)
796
797 static void _InsertWidthArray1(CFX_Font* pFont,
798                                CFX_UnicodeEncoding* pEncoding,
799                                FX_WCHAR start,
800                                FX_WCHAR end,
801                                CPDF_Array* pWidthArray) {
802   int size = end - start + 1;
803   int* widths = FX_Alloc(int, size);
804   int i;
805   for (i = 0; i < size; i++) {
806     int glyph_index = pEncoding->GlyphFromCharCode(start + i);
807     widths[i] = pFont->GetGlyphWidth(glyph_index);
808   }
809   for (i = 1; i < size; i++)
810     if (widths[i] != *widths) {
811       break;
812     }
813   if (i == size) {
814     int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
815     pWidthArray->AddInteger(first + size - 1);
816     pWidthArray->AddInteger(*widths);
817   } else {
818     CPDF_Array* pWidthArray1 = new CPDF_Array;
819     pWidthArray->Add(pWidthArray1);
820     for (i = 0; i < size; i++) {
821       pWidthArray1->AddInteger(widths[i]);
822     }
823   }
824   FX_Free(widths);
825 }
826
827 CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, FX_BOOL bVert) {
828   if (pFont == NULL) {
829     return NULL;
830   }
831   FX_BOOL bCJK = charset == FXFONT_CHINESEBIG5_CHARSET ||
832                  charset == FXFONT_GB2312_CHARSET ||
833                  charset == FXFONT_HANGEUL_CHARSET ||
834                  charset == FXFONT_SHIFTJIS_CHARSET;
835   CFX_ByteString basefont = pFont->GetFamilyName();
836   basefont.Replace(" ", "");
837   int flags = 0;
838   if (pFont->IsBold()) {
839     flags |= PDFFONT_FORCEBOLD;
840   }
841   if (pFont->IsItalic()) {
842     flags |= PDFFONT_ITALIC;
843   }
844   if (pFont->IsFixedWidth()) {
845     flags |= PDFFONT_FIXEDPITCH;
846   }
847   CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
848   pBaseDict->SetAtName("Type", "Font");
849   nonstd::unique_ptr<CFX_UnicodeEncoding> pEncoding(
850       new CFX_UnicodeEncoding(pFont));
851   CPDF_Dictionary* pFontDict = pBaseDict;
852   if (!bCJK) {
853     CPDF_Array* pWidths = new CPDF_Array;
854     int charcode;
855     for (charcode = 32; charcode < 128; charcode++) {
856       int glyph_index = pEncoding->GlyphFromCharCode(charcode);
857       int char_width = pFont->GetGlyphWidth(glyph_index);
858       pWidths->AddInteger(char_width);
859     }
860     if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_DEFAULT_CHARSET ||
861         charset == FXFONT_SYMBOL_CHARSET) {
862       if (charset == FXFONT_SYMBOL_CHARSET) {
863         flags |= PDFFONT_SYMBOLIC;
864       } else {
865         flags |= PDFFONT_NONSYMBOLIC;
866       }
867       pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
868       for (charcode = 128; charcode <= 255; charcode++) {
869         int glyph_index = pEncoding->GlyphFromCharCode(charcode);
870         int char_width = pFont->GetGlyphWidth(glyph_index);
871         pWidths->AddInteger(char_width);
872       }
873     } else {
874       flags |= PDFFONT_NONSYMBOLIC;
875       size_t i;
876       for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes);
877            i++)
878         if (g_FX_CharsetUnicodes[i].m_Charset == charset) {
879           break;
880         }
881       if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
882         CPDF_Dictionary* pEncodingDict = new CPDF_Dictionary;
883         pEncodingDict->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
884         CPDF_Array* pArray = new CPDF_Array;
885         pArray->AddInteger(128);
886         const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
887         for (int j = 0; j < 128; j++) {
888           CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
889           if (name.IsEmpty()) {
890             pArray->AddName(FX_BSTRC(".notdef"));
891           } else {
892             pArray->AddName(name);
893           }
894           int glyph_index = pEncoding->GlyphFromCharCode(pUnicodes[j]);
895           int char_width = pFont->GetGlyphWidth(glyph_index);
896           pWidths->AddInteger(char_width);
897         }
898         pEncodingDict->SetAt(FX_BSTRC("Differences"), pArray);
899         AddIndirectObject(pEncodingDict);
900         pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncodingDict);
901       }
902     }
903     if (pFont->IsBold() && pFont->IsItalic()) {
904       basefont += ",BoldItalic";
905     } else if (pFont->IsBold()) {
906       basefont += ",Bold";
907     } else if (pFont->IsItalic()) {
908       basefont += ",Italic";
909     }
910     pBaseDict->SetAtName("Subtype", "TrueType");
911     pBaseDict->SetAtName("BaseFont", basefont);
912     pBaseDict->SetAtNumber("FirstChar", 32);
913     pBaseDict->SetAtNumber("LastChar", 255);
914     pBaseDict->SetAt("Widths", pWidths);
915   } else {
916     flags |= PDFFONT_NONSYMBOLIC;
917     pFontDict = new CPDF_Dictionary;
918     CFX_ByteString cmap;
919     CFX_ByteString ordering;
920     int supplement;
921     CPDF_Array* pWidthArray = new CPDF_Array;
922     switch (charset) {
923       case FXFONT_CHINESEBIG5_CHARSET:
924         cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
925         ordering = "CNS1";
926         supplement = 4;
927         pWidthArray->AddInteger(1);
928         _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7e, pWidthArray);
929         break;
930       case FXFONT_GB2312_CHARSET:
931         cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
932         ordering = "GB1", supplement = 2;
933         pWidthArray->AddInteger(7716);
934         _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x20, pWidthArray);
935         pWidthArray->AddInteger(814);
936         _InsertWidthArray1(pFont, pEncoding.get(), 0x21, 0x7e, pWidthArray);
937         break;
938       case FXFONT_HANGEUL_CHARSET:
939         cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
940         ordering = "Korea1";
941         supplement = 2;
942         pWidthArray->AddInteger(1);
943         _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7e, pWidthArray);
944         break;
945       case FXFONT_SHIFTJIS_CHARSET:
946         cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
947         ordering = "Japan1";
948         supplement = 5;
949         pWidthArray->AddInteger(231);
950         _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7d, pWidthArray);
951         pWidthArray->AddInteger(326);
952         _InsertWidthArray1(pFont, pEncoding.get(), 0xa0, 0xa0, pWidthArray);
953         pWidthArray->AddInteger(327);
954         _InsertWidthArray1(pFont, pEncoding.get(), 0xa1, 0xdf, pWidthArray);
955         pWidthArray->AddInteger(631);
956         _InsertWidthArray1(pFont, pEncoding.get(), 0x7e, 0x7e, pWidthArray);
957         break;
958     }
959     pBaseDict->SetAtName("Subtype", "Type0");
960     pBaseDict->SetAtName("BaseFont", basefont);
961     pBaseDict->SetAtName("Encoding", cmap);
962     pFontDict->SetAt("W", pWidthArray);
963     pFontDict->SetAtName("Type", "Font");
964     pFontDict->SetAtName("Subtype", "CIDFontType2");
965     pFontDict->SetAtName("BaseFont", basefont);
966     CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
967     pCIDSysInfo->SetAtString("Registry", "Adobe");
968     pCIDSysInfo->SetAtString("Ordering", ordering);
969     pCIDSysInfo->SetAtInteger("Supplement", supplement);
970     pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
971     CPDF_Array* pArray = new CPDF_Array;
972     pBaseDict->SetAt("DescendantFonts", pArray);
973     AddIndirectObject(pFontDict);
974     pArray->AddReference(this, pFontDict);
975   }
976   AddIndirectObject(pBaseDict);
977   CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
978   pFontDesc->SetAtName("Type", "FontDescriptor");
979   pFontDesc->SetAtName("FontName", basefont);
980   pFontDesc->SetAtInteger("Flags", flags);
981   pFontDesc->SetAtInteger(
982       "ItalicAngle",
983       pFont->m_pSubstFont ? pFont->m_pSubstFont->m_ItalicAngle : 0);
984   pFontDesc->SetAtInteger("Ascent", pFont->GetAscent());
985   pFontDesc->SetAtInteger("Descent", pFont->GetDescent());
986   FX_RECT bbox;
987   pFont->GetBBox(bbox);
988   CPDF_Array* pBBox = new CPDF_Array;
989   pBBox->AddInteger(bbox.left);
990   pBBox->AddInteger(bbox.bottom);
991   pBBox->AddInteger(bbox.right);
992   pBBox->AddInteger(bbox.top);
993   pFontDesc->SetAt("FontBBox", pBBox);
994   int32_t nStemV = 0;
995   if (pFont->m_pSubstFont) {
996     nStemV = pFont->m_pSubstFont->m_Weight / 5;
997   } else {
998     static const FX_CHAR stem_chars[] = {'i', 'I', '!', '1'};
999     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
1000     FX_DWORD glyph = pEncoding->GlyphFromCharCode(stem_chars[0]);
1001     nStemV = pFont->GetGlyphWidth(glyph);
1002     for (size_t i = 1; i < count; i++) {
1003       glyph = pEncoding->GlyphFromCharCode(stem_chars[i]);
1004       int width = pFont->GetGlyphWidth(glyph);
1005       if (width > 0 && width < nStemV) {
1006         nStemV = width;
1007       }
1008     }
1009   }
1010   pFontDesc->SetAtInteger("StemV", nStemV);
1011   AddIndirectObject(pFontDesc);
1012   pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
1013   return LoadFont(pBaseDict);
1014 }
1015 static int InsertDeletePDFPage(CPDF_Document* pDoc,
1016                                CPDF_Dictionary* pPages,
1017                                int nPagesToGo,
1018                                CPDF_Dictionary* pPage,
1019                                FX_BOOL bInsert,
1020                                CFX_PtrArray& stackList) {
1021   CPDF_Array* pKidList = pPages->GetArray("Kids");
1022   if (!pKidList) {
1023     return -1;
1024   }
1025   int nKids = pKidList->GetCount();
1026   for (int i = 0; i < nKids; i++) {
1027     CPDF_Dictionary* pKid = pKidList->GetDict(i);
1028     if (pKid->GetString("Type") == FX_BSTRC("Page")) {
1029       if (nPagesToGo == 0) {
1030         if (bInsert) {
1031           pKidList->InsertAt(i, new CPDF_Reference(pDoc, pPage->GetObjNum()));
1032           pPage->SetAtReference("Parent", pDoc, pPages->GetObjNum());
1033         } else {
1034           pKidList->RemoveAt(i);
1035         }
1036         pPages->SetAtInteger("Count",
1037                              pPages->GetInteger("Count") + (bInsert ? 1 : -1));
1038         return 1;
1039       }
1040       nPagesToGo--;
1041     } else {
1042       int nPages = pKid->GetInteger("Count");
1043       if (nPagesToGo < nPages) {
1044         int stackCount = stackList.GetSize();
1045         for (int j = 0; j < stackCount; ++j) {
1046           if (pKid == stackList[j]) {
1047             return -1;
1048           }
1049         }
1050         stackList.Add(pKid);
1051         if (InsertDeletePDFPage(pDoc, pKid, nPagesToGo, pPage, bInsert,
1052                                 stackList) < 0) {
1053           return -1;
1054         }
1055         stackList.RemoveAt(stackCount);
1056         pPages->SetAtInteger("Count",
1057                              pPages->GetInteger("Count") + (bInsert ? 1 : -1));
1058         return 1;
1059       }
1060       nPagesToGo -= nPages;
1061     }
1062   }
1063   return 0;
1064 }
1065 static int InsertNewPage(CPDF_Document* pDoc,
1066                          int iPage,
1067                          CPDF_Dictionary* pPageDict,
1068                          CFX_DWordArray& pageList) {
1069   CPDF_Dictionary* pRoot = pDoc->GetRoot();
1070   if (!pRoot) {
1071     return -1;
1072   }
1073   CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
1074   if (!pPages) {
1075     return -1;
1076   }
1077   int nPages = pDoc->GetPageCount();
1078   if (iPage < 0 || iPage > nPages) {
1079     return -1;
1080   }
1081   if (iPage == nPages) {
1082     CPDF_Array* pPagesList = pPages->GetArray(FX_BSTRC("Kids"));
1083     if (!pPagesList) {
1084       pPagesList = new CPDF_Array;
1085       pPages->SetAt(FX_BSTRC("Kids"), pPagesList);
1086     }
1087     pPagesList->Add(pPageDict, pDoc);
1088     pPages->SetAtInteger(FX_BSTRC("Count"), nPages + 1);
1089     pPageDict->SetAtReference(FX_BSTRC("Parent"), pDoc, pPages->GetObjNum());
1090   } else {
1091     CFX_PtrArray stack;
1092     stack.Add(pPages);
1093     if (InsertDeletePDFPage(pDoc, pPages, iPage, pPageDict, TRUE, stack) < 0) {
1094       return -1;
1095     }
1096   }
1097   pageList.InsertAt(iPage, pPageDict->GetObjNum());
1098   return iPage;
1099 }
1100 CPDF_Dictionary* CPDF_Document::CreateNewPage(int iPage) {
1101   CPDF_Dictionary* pDict = new CPDF_Dictionary;
1102   pDict->SetAtName("Type", "Page");
1103   FX_DWORD dwObjNum = AddIndirectObject(pDict);
1104   if (InsertNewPage(this, iPage, pDict, m_PageList) < 0) {
1105     ReleaseIndirectObject(dwObjNum);
1106     return NULL;
1107   }
1108   return pDict;
1109 }
1110 int _PDF_GetStandardFontName(CFX_ByteString& name);
1111 CPDF_Font* CPDF_Document::AddStandardFont(const FX_CHAR* font,
1112                                           CPDF_FontEncoding* pEncoding) {
1113   CFX_ByteString name(font, -1);
1114   if (_PDF_GetStandardFontName(name) < 0) {
1115     return NULL;
1116   }
1117   return GetPageData()->GetStandardFont(name, pEncoding);
1118 }
1119 void CPDF_Document::DeletePage(int iPage) {
1120   CPDF_Dictionary* pRoot = GetRoot();
1121   if (pRoot == NULL) {
1122     return;
1123   }
1124   CPDF_Dictionary* pPages = pRoot->GetDict("Pages");
1125   if (pPages == NULL) {
1126     return;
1127   }
1128   int nPages = pPages->GetInteger("Count");
1129   if (iPage < 0 || iPage >= nPages) {
1130     return;
1131   }
1132   CFX_PtrArray stack;
1133   stack.Add(pPages);
1134   if (InsertDeletePDFPage(this, pPages, iPage, NULL, FALSE, stack) < 0) {
1135     return;
1136   }
1137   m_PageList.RemoveAt(iPage);
1138 }
1139 CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict,
1140                                  const CFX_ByteStringC& name);
1141 void FPDFAPI_FlatPageAttr(CPDF_Dictionary* pPageDict,
1142                           const CFX_ByteStringC& name) {
1143   if (pPageDict->KeyExist(name)) {
1144     return;
1145   }
1146   CPDF_Object* pObj = FPDFAPI_GetPageAttr(pPageDict, name);
1147   if (pObj) {
1148     pPageDict->SetAt(name, pObj->Clone());
1149   }
1150 }