Don't bother passing -1 as the length to the CFX_ByteString ctor.
[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 CFX_ByteString _FPDF_GetPSNameFromTT(HDC hDC) {
223   CFX_ByteString result;
224   DWORD size = ::GetFontData(hDC, 'eman', 0, NULL, 0);
225   if (size != GDI_ERROR) {
226     LPBYTE buffer = FX_Alloc(BYTE, size);
227     ::GetFontData(hDC, 'eman', 0, buffer, size);
228     result = GetNameFromTT(buffer, 6);
229     FX_Free(buffer);
230   }
231   return result;
232 }
233 CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont,
234                                          FX_BOOL bVert,
235                                          FX_BOOL bTranslateName) {
236   pLogFont->lfHeight = -1000;
237   pLogFont->lfWidth = 0;
238   HGDIOBJ hFont = CreateFontIndirectA(pLogFont);
239   HDC hDC = CreateCompatibleDC(NULL);
240   hFont = SelectObject(hDC, hFont);
241   int tm_size = GetOutlineTextMetrics(hDC, 0, NULL);
242   if (tm_size == 0) {
243     hFont = SelectObject(hDC, hFont);
244     DeleteObject(hFont);
245     DeleteDC(hDC);
246     return NULL;
247   }
248   LPBYTE tm_buf = FX_Alloc(BYTE, tm_size);
249   OUTLINETEXTMETRIC* ptm = (OUTLINETEXTMETRIC*)tm_buf;
250   GetOutlineTextMetrics(hDC, tm_size, ptm);
251   int flags = 0, italicangle, ascend, descend, capheight, bbox[4];
252   if (pLogFont->lfItalic) {
253     flags |= PDFFONT_ITALIC;
254   }
255   if ((pLogFont->lfPitchAndFamily & 3) == FIXED_PITCH) {
256     flags |= PDFFONT_FIXEDPITCH;
257   }
258   if ((pLogFont->lfPitchAndFamily & 0xf8) == FF_ROMAN) {
259     flags |= PDFFONT_SERIF;
260   }
261   if ((pLogFont->lfPitchAndFamily & 0xf8) == FF_SCRIPT) {
262     flags |= PDFFONT_SCRIPT;
263   }
264   FX_BOOL bCJK = pLogFont->lfCharSet == CHINESEBIG5_CHARSET ||
265                  pLogFont->lfCharSet == GB2312_CHARSET ||
266                  pLogFont->lfCharSet == HANGEUL_CHARSET ||
267                  pLogFont->lfCharSet == SHIFTJIS_CHARSET;
268   CFX_ByteString basefont;
269   if (bTranslateName && bCJK) {
270     basefont = _FPDF_GetPSNameFromTT(hDC);
271   }
272   if (basefont.IsEmpty()) {
273     basefont = pLogFont->lfFaceName;
274   }
275   italicangle = ptm->otmItalicAngle / 10;
276   ascend = ptm->otmrcFontBox.top;
277   descend = ptm->otmrcFontBox.bottom;
278   capheight = ptm->otmsCapEmHeight;
279   bbox[0] = ptm->otmrcFontBox.left;
280   bbox[1] = ptm->otmrcFontBox.bottom;
281   bbox[2] = ptm->otmrcFontBox.right;
282   bbox[3] = ptm->otmrcFontBox.top;
283   FX_Free(tm_buf);
284   basefont.Replace(" ", "");
285   CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
286   pBaseDict->SetAtName("Type", "Font");
287   CPDF_Dictionary* pFontDict = pBaseDict;
288   if (!bCJK) {
289     if (pLogFont->lfCharSet == ANSI_CHARSET ||
290         pLogFont->lfCharSet == DEFAULT_CHARSET ||
291         pLogFont->lfCharSet == SYMBOL_CHARSET) {
292       if (pLogFont->lfCharSet == SYMBOL_CHARSET) {
293         flags |= PDFFONT_SYMBOLIC;
294       } else {
295         flags |= PDFFONT_NONSYMBOLIC;
296       }
297       pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
298     } else {
299       flags |= PDFFONT_NONSYMBOLIC;
300       int i;
301       for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes);
302            i++)
303         if (g_FX_CharsetUnicodes[i].m_Charset == pLogFont->lfCharSet) {
304           break;
305         }
306       if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
307         CPDF_Dictionary* pEncoding = new CPDF_Dictionary;
308         pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
309         CPDF_Array* pArray = new CPDF_Array;
310         pArray->AddInteger(128);
311         const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
312         for (int j = 0; j < 128; j++) {
313           CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
314           if (name.IsEmpty()) {
315             pArray->AddName(FX_BSTRC(".notdef"));
316           } else {
317             pArray->AddName(name);
318           }
319         }
320         pEncoding->SetAt(FX_BSTRC("Differences"), pArray);
321         AddIndirectObject(pEncoding);
322         pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding);
323       }
324     }
325     if (pLogFont->lfWeight > FW_MEDIUM && pLogFont->lfItalic) {
326       basefont += ",BoldItalic";
327     } else if (pLogFont->lfWeight > FW_MEDIUM) {
328       basefont += ",Bold";
329     } else if (pLogFont->lfItalic) {
330       basefont += ",Italic";
331     }
332     pBaseDict->SetAtName("Subtype", "TrueType");
333     pBaseDict->SetAtName("BaseFont", basefont);
334     pBaseDict->SetAtNumber("FirstChar", 32);
335     pBaseDict->SetAtNumber("LastChar", 255);
336     int char_widths[224];
337     GetCharWidth(hDC, 32, 255, char_widths);
338     CPDF_Array* pWidths = new CPDF_Array;
339     for (int i = 0; i < 224; i++) {
340       pWidths->AddInteger(char_widths[i]);
341     }
342     pBaseDict->SetAt("Widths", pWidths);
343   } else {
344     flags |= PDFFONT_NONSYMBOLIC;
345     pFontDict = new CPDF_Dictionary;
346     CFX_ByteString cmap;
347     CFX_ByteString ordering;
348     int supplement;
349     CPDF_Array* pWidthArray = new CPDF_Array;
350     switch (pLogFont->lfCharSet) {
351       case CHINESEBIG5_CHARSET:
352         cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
353         ordering = "CNS1";
354         supplement = 4;
355         pWidthArray->AddInteger(1);
356         _InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray);
357         break;
358       case GB2312_CHARSET:
359         cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
360         ordering = "GB1", supplement = 2;
361         pWidthArray->AddInteger(7716);
362         _InsertWidthArray(hDC, 0x20, 0x20, pWidthArray);
363         pWidthArray->AddInteger(814);
364         _InsertWidthArray(hDC, 0x21, 0x7e, pWidthArray);
365         break;
366       case HANGEUL_CHARSET:
367         cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
368         ordering = "Korea1";
369         supplement = 2;
370         pWidthArray->AddInteger(1);
371         _InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray);
372         break;
373       case SHIFTJIS_CHARSET:
374         cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
375         ordering = "Japan1";
376         supplement = 5;
377         pWidthArray->AddInteger(231);
378         _InsertWidthArray(hDC, 0x20, 0x7d, pWidthArray);
379         pWidthArray->AddInteger(326);
380         _InsertWidthArray(hDC, 0xa0, 0xa0, pWidthArray);
381         pWidthArray->AddInteger(327);
382         _InsertWidthArray(hDC, 0xa1, 0xdf, pWidthArray);
383         pWidthArray->AddInteger(631);
384         _InsertWidthArray(hDC, 0x7e, 0x7e, pWidthArray);
385         break;
386     }
387     pBaseDict->SetAtName("Subtype", "Type0");
388     pBaseDict->SetAtName("BaseFont", basefont);
389     pBaseDict->SetAtName("Encoding", cmap);
390     pFontDict->SetAt("W", pWidthArray);
391     pFontDict->SetAtName("Type", "Font");
392     pFontDict->SetAtName("Subtype", "CIDFontType2");
393     pFontDict->SetAtName("BaseFont", basefont);
394     CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
395     pCIDSysInfo->SetAtString("Registry", "Adobe");
396     pCIDSysInfo->SetAtString("Ordering", ordering);
397     pCIDSysInfo->SetAtInteger("Supplement", supplement);
398     pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
399     CPDF_Array* pArray = new CPDF_Array;
400     pBaseDict->SetAt("DescendantFonts", pArray);
401     AddIndirectObject(pFontDict);
402     pArray->AddReference(this, pFontDict);
403   }
404   AddIndirectObject(pBaseDict);
405   CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
406   pFontDesc->SetAtName("Type", "FontDescriptor");
407   pFontDesc->SetAtName("FontName", basefont);
408   pFontDesc->SetAtInteger("Flags", flags);
409   CPDF_Array* pBBox = new CPDF_Array;
410   for (int i = 0; i < 4; i++) {
411     pBBox->AddInteger(bbox[i]);
412   }
413   pFontDesc->SetAt("FontBBox", pBBox);
414   pFontDesc->SetAtInteger("ItalicAngle", italicangle);
415   pFontDesc->SetAtInteger("Ascent", ascend);
416   pFontDesc->SetAtInteger("Descent", descend);
417   pFontDesc->SetAtInteger("CapHeight", capheight);
418   pFontDesc->SetAtInteger("StemV", pLogFont->lfWeight / 5);
419   AddIndirectObject(pFontDesc);
420   pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
421   hFont = SelectObject(hDC, hFont);
422   DeleteObject(hFont);
423   DeleteDC(hDC);
424   return LoadFont(pBaseDict);
425 }
426 #endif
427
428 #if (_FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_)
429 uint32_t FX_GetLangHashCode(const FX_CHAR* pStr) {
430   FXSYS_assert(pStr != NULL);
431   int32_t iLength = FXSYS_strlen(pStr);
432   const FX_CHAR* pStrEnd = pStr + iLength;
433   uint32_t uHashCode = 0;
434   while (pStr < pStrEnd) {
435     uHashCode = 31 * uHashCode + tolower(*pStr++);
436   }
437   return uHashCode;
438 }
439 struct FX_LANG2CS {
440   FX_DWORD uLang;
441   int uCharset;
442 } * FX_LPLANG2CS;
443 static const FX_LANG2CS gs_FXLang2CharsetTable[] = {
444     {3109, 0},         {3121, 178}, {3129, 162}, {3139, 204}, {3141, 204},
445     {3166, 0},         {3184, 238}, {3197, 0},   {3201, 0},   {3239, 161},
446     {3241, 0},         {3246, 0},   {3247, 186}, {3248, 0},   {3259, 178},
447     {3267, 0},         {3273, 0},   {3276, 0},   {3301, 0},   {3310, 1},
448     {3325, 177},       {3329, 1},   {3338, 238}, {3341, 238}, {3345, 1},
449     {3355, 0},         {3370, 0},   {3371, 0},   {3383, 128}, {3424, 204},
450     {3427, 1},         {3428, 129}, {3436, 178}, {3464, 186}, {3466, 186},
451     {3486, 204},       {3487, 0},   {3493, 1},   {3494, 0},   {3508, 0},
452     {3518, 0},         {3520, 0},   {3569, 1},   {3580, 238}, {3588, 0},
453     {3645, 238},       {3651, 204}, {3672, 238}, {3673, 238}, {3678, 238},
454     {3679, 238},       {3683, 0},   {3684, 0},   {3693, 1},   {3697, 1},
455     {3700, 222},       {3710, 162}, {3734, 204}, {3741, 178}, {3749, 162},
456     {3763, 163},       {3886, 134}, {105943, 0}, {106375, 1}, {3923451837, 134},
457     {3923451838, 136},
458 };
459 static FX_WORD FX_GetCsFromLangCode(uint32_t uCode) {
460   int32_t iStart = 0;
461   int32_t iEnd = sizeof(gs_FXLang2CharsetTable) / sizeof(FX_LANG2CS) - 1;
462   while (iStart <= iEnd) {
463     int32_t iMid = (iStart + iEnd) / 2;
464     const FX_LANG2CS& charset = gs_FXLang2CharsetTable[iMid];
465     if (uCode == charset.uLang) {
466       return charset.uCharset;
467     }
468     if (uCode < charset.uLang) {
469       iEnd = iMid - 1;
470     } else {
471       iStart = iMid + 1;
472     }
473   };
474   return 0;
475 }
476 static FX_WORD FX_GetCharsetFromLang(const FX_CHAR* pLang, int32_t iLength) {
477   FXSYS_assert(pLang);
478   if (iLength < 0) {
479     iLength = FXSYS_strlen(pLang);
480   }
481   uint32_t uHash = FX_GetLangHashCode(pLang);
482   return FX_GetCsFromLangCode(uHash);
483 }
484 static void _CFString2CFXByteString(CFStringRef src, CFX_ByteString& dest) {
485   SInt32 len = CFStringGetLength(src);
486   CFRange range = CFRangeMake(0, len);
487   CFIndex used = 0;
488   UInt8* pBuffer = (UInt8*)calloc(len + 1, sizeof(UInt8));
489   CFStringGetBytes(src, range, kCFStringEncodingASCII, 0, false, pBuffer, len,
490                    &used);
491   dest = (FX_CHAR*)pBuffer;
492   free(pBuffer);
493 }
494 FX_BOOL IsHasCharSet(CFArrayRef languages, const CFX_DWordArray& charSets) {
495   int iCount = charSets.GetSize();
496   for (int i = 0; i < CFArrayGetCount(languages); ++i) {
497     CFStringRef language = (CFStringRef)CFArrayGetValueAtIndex(languages, i);
498     FX_DWORD CharSet = FX_GetCharsetFromLang(
499         CFStringGetCStringPtr(language, kCFStringEncodingMacRoman), -1);
500     for (int j = 0; j < iCount; ++j) {
501       if (CharSet == charSets[j]) {
502         return TRUE;
503       }
504     }
505   }
506   return FALSE;
507 }
508 void FX_GetCharWidth(CTFontRef font, UniChar start, UniChar end, int* width) {
509   CGFloat size = CTFontGetSize(font);
510   for (; start <= end; ++start) {
511     CGGlyph pGlyph = 0;
512     CFIndex count = 1;
513     CTFontGetGlyphsForCharacters(font, &start, &pGlyph, count);
514     CGSize advances;
515     CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &pGlyph,
516                                &advances, 1);
517     *width = (int)(advances.width / size * 1000);
518     width++;
519   }
520 }
521 static void _InsertWidthArray(CTFontRef font,
522                               int start,
523                               int end,
524                               CPDF_Array* pWidthArray) {
525   int size = end - start + 1;
526   int* widths = FX_Alloc(int, size);
527   FX_GetCharWidth(font, start, end, widths);
528   int i;
529   for (i = 1; i < size; i++)
530     if (widths[i] != *widths) {
531       break;
532     }
533   if (i == size) {
534     int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
535     pWidthArray->AddInteger(first + size - 1);
536     pWidthArray->AddInteger(*widths);
537   } else {
538     CPDF_Array* pWidthArray1 = new CPDF_Array;
539     pWidthArray->Add(pWidthArray1);
540     for (i = 0; i < size; i++) {
541       pWidthArray1->AddInteger(widths[i]);
542     }
543   }
544   FX_Free(widths);
545 }
546 CPDF_Font* CPDF_Document::AddMacFont(CTFontRef pFont,
547                                      FX_BOOL bVert,
548                                      FX_BOOL bTranslateName) {
549   CTFontRef font = (CTFontRef)pFont;
550   CTFontDescriptorRef descriptor = CTFontCopyFontDescriptor(font);
551   if (descriptor == NULL) {
552     return NULL;
553   }
554   CFX_ByteString basefont;
555   FX_BOOL bCJK = FALSE;
556   int flags = 0, italicangle = 0, ascend = 0, descend = 0, capheight = 0,
557       bbox[4];
558   FXSYS_memset(bbox, 0, sizeof(int) * 4);
559   CFArrayRef languages = (CFArrayRef)CTFontDescriptorCopyAttribute(
560       descriptor, kCTFontLanguagesAttribute);
561   if (languages == NULL) {
562     CFRelease(descriptor);
563     return NULL;
564   }
565   CFX_DWordArray charSets;
566   charSets.Add(FXFONT_CHINESEBIG5_CHARSET);
567   charSets.Add(FXFONT_GB2312_CHARSET);
568   charSets.Add(FXFONT_HANGEUL_CHARSET);
569   charSets.Add(FXFONT_SHIFTJIS_CHARSET);
570   if (IsHasCharSet(languages, charSets)) {
571     bCJK = TRUE;
572   }
573   CFRelease(descriptor);
574   CFDictionaryRef traits = (CFDictionaryRef)CTFontCopyTraits(font);
575   if (traits == NULL) {
576     CFRelease(languages);
577     return NULL;
578   }
579   CFNumberRef sybolicTrait =
580       (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait);
581   CTFontSymbolicTraits trait = 0;
582   CFNumberGetValue(sybolicTrait, kCFNumberSInt32Type, &trait);
583   if (trait & kCTFontItalicTrait) {
584     flags |= PDFFONT_ITALIC;
585   }
586   if (trait & kCTFontMonoSpaceTrait) {
587     flags |= PDFFONT_FIXEDPITCH;
588   }
589   if (trait & kCTFontModernSerifsClass) {
590     flags |= PDFFONT_SERIF;
591   }
592   if (trait & kCTFontScriptsClass) {
593     flags |= PDFFONT_SCRIPT;
594   }
595   CFNumberRef weightTrait =
596       (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait);
597   Float32 weight = 0;
598   CFNumberGetValue(weightTrait, kCFNumberFloat32Type, &weight);
599   italicangle = CTFontGetSlantAngle(font);
600   ascend = CTFontGetAscent(font);
601   descend = CTFontGetDescent(font);
602   capheight = CTFontGetCapHeight(font);
603   CGRect box = CTFontGetBoundingBox(font);
604   bbox[0] = box.origin.x;
605   bbox[1] = box.origin.y;
606   bbox[2] = box.origin.x + box.size.width;
607   bbox[3] = box.origin.y + box.size.height;
608   if (bTranslateName && bCJK) {
609     CFStringRef postName = CTFontCopyPostScriptName(font);
610     _CFString2CFXByteString(postName, basefont);
611     CFRelease(postName);
612   }
613   if (basefont.IsEmpty()) {
614     CFStringRef fullName = CTFontCopyFullName(font);
615     _CFString2CFXByteString(fullName, basefont);
616     CFRelease(fullName);
617   }
618   basefont.Replace(" ", "");
619   CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
620   CPDF_Dictionary* pFontDict = pBaseDict;
621   if (!bCJK) {
622     charSets.RemoveAll();
623     charSets.Add(FXFONT_ANSI_CHARSET);
624     charSets.Add(FXFONT_DEFAULT_CHARSET);
625     charSets.Add(FXFONT_SYMBOL_CHARSET);
626     if (IsHasCharSet(languages, charSets)) {
627       charSets.RemoveAll();
628       charSets.Add(FXFONT_SYMBOL_CHARSET);
629       if (IsHasCharSet(languages, charSets)) {
630         flags |= PDFFONT_SYMBOLIC;
631       } else {
632         flags |= PDFFONT_NONSYMBOLIC;
633       }
634       pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
635     } else {
636       flags |= PDFFONT_NONSYMBOLIC;
637       size_t i;
638       for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes);
639            i++) {
640         charSets.RemoveAll();
641         charSets.Add(g_FX_CharsetUnicodes[i].m_Charset);
642         if (IsHasCharSet(languages, charSets)) {
643           break;
644         }
645       }
646       if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
647         CPDF_Dictionary* pEncoding = new CPDF_Dictionary;
648         pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
649         CPDF_Array* pArray = new CPDF_Array;
650         pArray->AddInteger(128);
651         const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
652         for (int j = 0; j < 128; j++) {
653           CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
654           if (name.IsEmpty()) {
655             pArray->AddName(FX_BSTRC(".notdef"));
656           } else {
657             pArray->AddName(name);
658           }
659         }
660         pEncoding->SetAt(FX_BSTRC("Differences"), pArray);
661         AddIndirectObject(pEncoding);
662         pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding);
663       }
664     }
665     if (weight > 0.0 && trait & kCTFontItalicTrait) {
666       basefont += ",BoldItalic";
667     } else if (weight > 0.0) {
668       basefont += ",Bold";
669     } else if (trait & kCTFontItalicTrait) {
670       basefont += ",Italic";
671     }
672     pBaseDict->SetAtName("Subtype", "TrueType");
673     pBaseDict->SetAtName("BaseFont", basefont);
674     pBaseDict->SetAtNumber("FirstChar", 32);
675     pBaseDict->SetAtNumber("LastChar", 255);
676     int char_widths[224];
677     FX_GetCharWidth(font, 32, 255, char_widths);
678     CPDF_Array* pWidths = new CPDF_Array;
679     for (int i = 0; i < 224; i++) {
680       pWidths->AddInteger(char_widths[i]);
681     }
682     pBaseDict->SetAt("Widths", pWidths);
683   } else {
684     flags |= PDFFONT_NONSYMBOLIC;
685     CPDF_Array* pArray = NULL;
686     pFontDict = new CPDF_Dictionary;
687     CFX_ByteString cmap;
688     CFX_ByteString ordering;
689     int supplement;
690     FX_BOOL bFound = FALSE;
691     CPDF_Array* pWidthArray = new CPDF_Array;
692     charSets.RemoveAll();
693     charSets.Add(FXFONT_CHINESEBIG5_CHARSET);
694     if (IsHasCharSet(languages, charSets)) {
695       cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
696       ordering = "CNS1";
697       supplement = 4;
698       pWidthArray->AddInteger(1);
699       _InsertWidthArray(font, 0x20, 0x7e, pWidthArray);
700       bFound = TRUE;
701     }
702     charSets.RemoveAll();
703     charSets.Add(FXFONT_GB2312_CHARSET);
704     if (!bFound && IsHasCharSet(languages, charSets)) {
705       cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
706       ordering = "GB1", supplement = 2;
707       pWidthArray->AddInteger(7716);
708       _InsertWidthArray(font, 0x20, 0x20, pWidthArray);
709       pWidthArray->AddInteger(814);
710       _InsertWidthArray(font, 0x21, 0x7e, pWidthArray);
711       bFound = TRUE;
712     }
713     charSets.RemoveAll();
714     charSets.Add(FXFONT_HANGEUL_CHARSET);
715     if (!bFound && IsHasCharSet(languages, charSets)) {
716       cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
717       ordering = "Korea1";
718       supplement = 2;
719       pWidthArray->AddInteger(1);
720       _InsertWidthArray(font, 0x20, 0x7e, pWidthArray);
721       bFound = TRUE;
722     }
723     charSets.RemoveAll();
724     charSets.Add(FXFONT_SHIFTJIS_CHARSET);
725     if (!bFound && IsHasCharSet(languages, charSets)) {
726       cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
727       ordering = "Japan1";
728       supplement = 5;
729       pWidthArray->AddInteger(231);
730       _InsertWidthArray(font, 0x20, 0x7d, pWidthArray);
731       pWidthArray->AddInteger(326);
732       _InsertWidthArray(font, 0xa0, 0xa0, pWidthArray);
733       pWidthArray->AddInteger(327);
734       _InsertWidthArray(font, 0xa1, 0xdf, pWidthArray);
735       pWidthArray->AddInteger(631);
736       _InsertWidthArray(font, 0x7e, 0x7e, pWidthArray);
737     }
738     pBaseDict->SetAtName("Subtype", "Type0");
739     pBaseDict->SetAtName("BaseFont", basefont);
740     pBaseDict->SetAtName("Encoding", cmap);
741     pFontDict->SetAt("W", pWidthArray);
742     pFontDict->SetAtName("Type", "Font");
743     pFontDict->SetAtName("Subtype", "CIDFontType2");
744     pFontDict->SetAtName("BaseFont", basefont);
745     CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
746     pCIDSysInfo->SetAtString("Registry", "Adobe");
747     pCIDSysInfo->SetAtString("Ordering", ordering);
748     pCIDSysInfo->SetAtInteger("Supplement", supplement);
749     pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
750     pArray = new CPDF_Array;
751     pBaseDict->SetAt("DescendantFonts", pArray);
752     AddIndirectObject(pFontDict);
753     pArray->AddReference(this, pFontDict);
754   }
755   AddIndirectObject(pBaseDict);
756   CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
757   pFontDesc->SetAtName("Type", "FontDescriptor");
758   pFontDesc->SetAtName("FontName", basefont);
759   pFontDesc->SetAtInteger("Flags", flags);
760   CPDF_Array* pBBox = new CPDF_Array;
761   for (int i = 0; i < 4; i++) {
762     pBBox->AddInteger(bbox[i]);
763   }
764   pFontDesc->SetAt("FontBBox", pBBox);
765   pFontDesc->SetAtInteger("ItalicAngle", italicangle);
766   pFontDesc->SetAtInteger("Ascent", ascend);
767   pFontDesc->SetAtInteger("Descent", descend);
768   pFontDesc->SetAtInteger("CapHeight", capheight);
769   CGFloat fStemV = 0;
770   int16_t min_width = SHRT_MAX;
771   static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
772   const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
773   CGGlyph glyphs[count];
774   CGRect boundingRects[count];
775   if (CTFontGetGlyphsForCharacters(font, stem_chars, glyphs, count)) {
776     CTFontGetBoundingRectsForGlyphs(font, kCTFontHorizontalOrientation, glyphs,
777                                     boundingRects, count);
778     for (size_t i = 0; i < count; i++) {
779       int16_t width = boundingRects[i].size.width;
780       if (width > 0 && width < min_width) {
781         min_width = width;
782         fStemV = min_width;
783       }
784     }
785   }
786   pFontDesc->SetAtInteger("StemV", fStemV);
787   AddIndirectObject(pFontDesc);
788   pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
789   CFRelease(traits);
790   CFRelease(languages);
791   return LoadFont(pBaseDict);
792 }
793 #endif  // (_FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_)
794
795 static void _InsertWidthArray1(CFX_Font* pFont,
796                                CFX_UnicodeEncoding* pEncoding,
797                                FX_WCHAR start,
798                                FX_WCHAR end,
799                                CPDF_Array* pWidthArray) {
800   int size = end - start + 1;
801   int* widths = FX_Alloc(int, size);
802   int i;
803   for (i = 0; i < size; i++) {
804     int glyph_index = pEncoding->GlyphFromCharCode(start + i);
805     widths[i] = pFont->GetGlyphWidth(glyph_index);
806   }
807   for (i = 1; i < size; i++)
808     if (widths[i] != *widths) {
809       break;
810     }
811   if (i == size) {
812     int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
813     pWidthArray->AddInteger(first + size - 1);
814     pWidthArray->AddInteger(*widths);
815   } else {
816     CPDF_Array* pWidthArray1 = new CPDF_Array;
817     pWidthArray->Add(pWidthArray1);
818     for (i = 0; i < size; i++) {
819       pWidthArray1->AddInteger(widths[i]);
820     }
821   }
822   FX_Free(widths);
823 }
824
825 CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, FX_BOOL bVert) {
826   if (pFont == NULL) {
827     return NULL;
828   }
829   FX_BOOL bCJK = charset == FXFONT_CHINESEBIG5_CHARSET ||
830                  charset == FXFONT_GB2312_CHARSET ||
831                  charset == FXFONT_HANGEUL_CHARSET ||
832                  charset == FXFONT_SHIFTJIS_CHARSET;
833   CFX_ByteString basefont = pFont->GetFamilyName();
834   basefont.Replace(" ", "");
835   int flags = 0;
836   if (pFont->IsBold()) {
837     flags |= PDFFONT_FORCEBOLD;
838   }
839   if (pFont->IsItalic()) {
840     flags |= PDFFONT_ITALIC;
841   }
842   if (pFont->IsFixedWidth()) {
843     flags |= PDFFONT_FIXEDPITCH;
844   }
845   CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
846   pBaseDict->SetAtName("Type", "Font");
847   nonstd::unique_ptr<CFX_UnicodeEncoding> pEncoding(
848       new CFX_UnicodeEncoding(pFont));
849   CPDF_Dictionary* pFontDict = pBaseDict;
850   if (!bCJK) {
851     CPDF_Array* pWidths = new CPDF_Array;
852     int charcode;
853     for (charcode = 32; charcode < 128; charcode++) {
854       int glyph_index = pEncoding->GlyphFromCharCode(charcode);
855       int char_width = pFont->GetGlyphWidth(glyph_index);
856       pWidths->AddInteger(char_width);
857     }
858     if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_DEFAULT_CHARSET ||
859         charset == FXFONT_SYMBOL_CHARSET) {
860       if (charset == FXFONT_SYMBOL_CHARSET) {
861         flags |= PDFFONT_SYMBOLIC;
862       } else {
863         flags |= PDFFONT_NONSYMBOLIC;
864       }
865       pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
866       for (charcode = 128; charcode <= 255; charcode++) {
867         int glyph_index = pEncoding->GlyphFromCharCode(charcode);
868         int char_width = pFont->GetGlyphWidth(glyph_index);
869         pWidths->AddInteger(char_width);
870       }
871     } else {
872       flags |= PDFFONT_NONSYMBOLIC;
873       size_t i;
874       for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes);
875            i++)
876         if (g_FX_CharsetUnicodes[i].m_Charset == charset) {
877           break;
878         }
879       if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
880         CPDF_Dictionary* pEncodingDict = new CPDF_Dictionary;
881         pEncodingDict->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
882         CPDF_Array* pArray = new CPDF_Array;
883         pArray->AddInteger(128);
884         const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
885         for (int j = 0; j < 128; j++) {
886           CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
887           if (name.IsEmpty()) {
888             pArray->AddName(FX_BSTRC(".notdef"));
889           } else {
890             pArray->AddName(name);
891           }
892           int glyph_index = pEncoding->GlyphFromCharCode(pUnicodes[j]);
893           int char_width = pFont->GetGlyphWidth(glyph_index);
894           pWidths->AddInteger(char_width);
895         }
896         pEncodingDict->SetAt(FX_BSTRC("Differences"), pArray);
897         AddIndirectObject(pEncodingDict);
898         pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncodingDict);
899       }
900     }
901     if (pFont->IsBold() && pFont->IsItalic()) {
902       basefont += ",BoldItalic";
903     } else if (pFont->IsBold()) {
904       basefont += ",Bold";
905     } else if (pFont->IsItalic()) {
906       basefont += ",Italic";
907     }
908     pBaseDict->SetAtName("Subtype", "TrueType");
909     pBaseDict->SetAtName("BaseFont", basefont);
910     pBaseDict->SetAtNumber("FirstChar", 32);
911     pBaseDict->SetAtNumber("LastChar", 255);
912     pBaseDict->SetAt("Widths", pWidths);
913   } else {
914     flags |= PDFFONT_NONSYMBOLIC;
915     pFontDict = new CPDF_Dictionary;
916     CFX_ByteString cmap;
917     CFX_ByteString ordering;
918     int supplement;
919     CPDF_Array* pWidthArray = new CPDF_Array;
920     switch (charset) {
921       case FXFONT_CHINESEBIG5_CHARSET:
922         cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
923         ordering = "CNS1";
924         supplement = 4;
925         pWidthArray->AddInteger(1);
926         _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7e, pWidthArray);
927         break;
928       case FXFONT_GB2312_CHARSET:
929         cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
930         ordering = "GB1", supplement = 2;
931         pWidthArray->AddInteger(7716);
932         _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x20, pWidthArray);
933         pWidthArray->AddInteger(814);
934         _InsertWidthArray1(pFont, pEncoding.get(), 0x21, 0x7e, pWidthArray);
935         break;
936       case FXFONT_HANGEUL_CHARSET:
937         cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
938         ordering = "Korea1";
939         supplement = 2;
940         pWidthArray->AddInteger(1);
941         _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7e, pWidthArray);
942         break;
943       case FXFONT_SHIFTJIS_CHARSET:
944         cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
945         ordering = "Japan1";
946         supplement = 5;
947         pWidthArray->AddInteger(231);
948         _InsertWidthArray1(pFont, pEncoding.get(), 0x20, 0x7d, pWidthArray);
949         pWidthArray->AddInteger(326);
950         _InsertWidthArray1(pFont, pEncoding.get(), 0xa0, 0xa0, pWidthArray);
951         pWidthArray->AddInteger(327);
952         _InsertWidthArray1(pFont, pEncoding.get(), 0xa1, 0xdf, pWidthArray);
953         pWidthArray->AddInteger(631);
954         _InsertWidthArray1(pFont, pEncoding.get(), 0x7e, 0x7e, pWidthArray);
955         break;
956     }
957     pBaseDict->SetAtName("Subtype", "Type0");
958     pBaseDict->SetAtName("BaseFont", basefont);
959     pBaseDict->SetAtName("Encoding", cmap);
960     pFontDict->SetAt("W", pWidthArray);
961     pFontDict->SetAtName("Type", "Font");
962     pFontDict->SetAtName("Subtype", "CIDFontType2");
963     pFontDict->SetAtName("BaseFont", basefont);
964     CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
965     pCIDSysInfo->SetAtString("Registry", "Adobe");
966     pCIDSysInfo->SetAtString("Ordering", ordering);
967     pCIDSysInfo->SetAtInteger("Supplement", supplement);
968     pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
969     CPDF_Array* pArray = new CPDF_Array;
970     pBaseDict->SetAt("DescendantFonts", pArray);
971     AddIndirectObject(pFontDict);
972     pArray->AddReference(this, pFontDict);
973   }
974   AddIndirectObject(pBaseDict);
975   CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
976   pFontDesc->SetAtName("Type", "FontDescriptor");
977   pFontDesc->SetAtName("FontName", basefont);
978   pFontDesc->SetAtInteger("Flags", flags);
979   pFontDesc->SetAtInteger(
980       "ItalicAngle",
981       pFont->GetSubstFont() ? pFont->GetSubstFont()->m_ItalicAngle : 0);
982   pFontDesc->SetAtInteger("Ascent", pFont->GetAscent());
983   pFontDesc->SetAtInteger("Descent", pFont->GetDescent());
984   FX_RECT bbox;
985   pFont->GetBBox(bbox);
986   CPDF_Array* pBBox = new CPDF_Array;
987   pBBox->AddInteger(bbox.left);
988   pBBox->AddInteger(bbox.bottom);
989   pBBox->AddInteger(bbox.right);
990   pBBox->AddInteger(bbox.top);
991   pFontDesc->SetAt("FontBBox", pBBox);
992   int32_t nStemV = 0;
993   if (pFont->GetSubstFont()) {
994     nStemV = pFont->GetSubstFont()->m_Weight / 5;
995   } else {
996     static const FX_CHAR stem_chars[] = {'i', 'I', '!', '1'};
997     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
998     FX_DWORD glyph = pEncoding->GlyphFromCharCode(stem_chars[0]);
999     nStemV = pFont->GetGlyphWidth(glyph);
1000     for (size_t i = 1; i < count; i++) {
1001       glyph = pEncoding->GlyphFromCharCode(stem_chars[i]);
1002       int width = pFont->GetGlyphWidth(glyph);
1003       if (width > 0 && width < nStemV) {
1004         nStemV = width;
1005       }
1006     }
1007   }
1008   pFontDesc->SetAtInteger("StemV", nStemV);
1009   AddIndirectObject(pFontDesc);
1010   pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
1011   return LoadFont(pBaseDict);
1012 }
1013 static int InsertDeletePDFPage(CPDF_Document* pDoc,
1014                                CPDF_Dictionary* pPages,
1015                                int nPagesToGo,
1016                                CPDF_Dictionary* pPage,
1017                                FX_BOOL bInsert,
1018                                CFX_PtrArray& stackList) {
1019   CPDF_Array* pKidList = pPages->GetArray("Kids");
1020   if (!pKidList) {
1021     return -1;
1022   }
1023   int nKids = pKidList->GetCount();
1024   for (int i = 0; i < nKids; i++) {
1025     CPDF_Dictionary* pKid = pKidList->GetDict(i);
1026     if (pKid->GetString("Type") == FX_BSTRC("Page")) {
1027       if (nPagesToGo == 0) {
1028         if (bInsert) {
1029           pKidList->InsertAt(i, new CPDF_Reference(pDoc, pPage->GetObjNum()));
1030           pPage->SetAtReference("Parent", pDoc, pPages->GetObjNum());
1031         } else {
1032           pKidList->RemoveAt(i);
1033         }
1034         pPages->SetAtInteger("Count",
1035                              pPages->GetInteger("Count") + (bInsert ? 1 : -1));
1036         return 1;
1037       }
1038       nPagesToGo--;
1039     } else {
1040       int nPages = pKid->GetInteger("Count");
1041       if (nPagesToGo < nPages) {
1042         int stackCount = stackList.GetSize();
1043         for (int j = 0; j < stackCount; ++j) {
1044           if (pKid == stackList[j]) {
1045             return -1;
1046           }
1047         }
1048         stackList.Add(pKid);
1049         if (InsertDeletePDFPage(pDoc, pKid, nPagesToGo, pPage, bInsert,
1050                                 stackList) < 0) {
1051           return -1;
1052         }
1053         stackList.RemoveAt(stackCount);
1054         pPages->SetAtInteger("Count",
1055                              pPages->GetInteger("Count") + (bInsert ? 1 : -1));
1056         return 1;
1057       }
1058       nPagesToGo -= nPages;
1059     }
1060   }
1061   return 0;
1062 }
1063 static int InsertNewPage(CPDF_Document* pDoc,
1064                          int iPage,
1065                          CPDF_Dictionary* pPageDict,
1066                          CFX_DWordArray& pageList) {
1067   CPDF_Dictionary* pRoot = pDoc->GetRoot();
1068   if (!pRoot) {
1069     return -1;
1070   }
1071   CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
1072   if (!pPages) {
1073     return -1;
1074   }
1075   int nPages = pDoc->GetPageCount();
1076   if (iPage < 0 || iPage > nPages) {
1077     return -1;
1078   }
1079   if (iPage == nPages) {
1080     CPDF_Array* pPagesList = pPages->GetArray(FX_BSTRC("Kids"));
1081     if (!pPagesList) {
1082       pPagesList = new CPDF_Array;
1083       pPages->SetAt(FX_BSTRC("Kids"), pPagesList);
1084     }
1085     pPagesList->Add(pPageDict, pDoc);
1086     pPages->SetAtInteger(FX_BSTRC("Count"), nPages + 1);
1087     pPageDict->SetAtReference(FX_BSTRC("Parent"), pDoc, pPages->GetObjNum());
1088   } else {
1089     CFX_PtrArray stack;
1090     stack.Add(pPages);
1091     if (InsertDeletePDFPage(pDoc, pPages, iPage, pPageDict, TRUE, stack) < 0) {
1092       return -1;
1093     }
1094   }
1095   pageList.InsertAt(iPage, pPageDict->GetObjNum());
1096   return iPage;
1097 }
1098 CPDF_Dictionary* CPDF_Document::CreateNewPage(int iPage) {
1099   CPDF_Dictionary* pDict = new CPDF_Dictionary;
1100   pDict->SetAtName("Type", "Page");
1101   FX_DWORD dwObjNum = AddIndirectObject(pDict);
1102   if (InsertNewPage(this, iPage, pDict, m_PageList) < 0) {
1103     ReleaseIndirectObject(dwObjNum);
1104     return NULL;
1105   }
1106   return pDict;
1107 }
1108
1109 CPDF_Font* CPDF_Document::AddStandardFont(const FX_CHAR* font,
1110                                           CPDF_FontEncoding* pEncoding) {
1111   CFX_ByteString name(font);
1112   if (PDF_GetStandardFontName(&name) < 0)
1113     return nullptr;
1114   return GetPageData()->GetStandardFont(name, pEncoding);
1115 }
1116
1117 void CPDF_Document::DeletePage(int iPage) {
1118   CPDF_Dictionary* pRoot = GetRoot();
1119   if (pRoot == NULL) {
1120     return;
1121   }
1122   CPDF_Dictionary* pPages = pRoot->GetDict("Pages");
1123   if (pPages == NULL) {
1124     return;
1125   }
1126   int nPages = pPages->GetInteger("Count");
1127   if (iPage < 0 || iPage >= nPages) {
1128     return;
1129   }
1130   CFX_PtrArray stack;
1131   stack.Add(pPages);
1132   if (InsertDeletePDFPage(this, pPages, iPage, NULL, FALSE, stack) < 0) {
1133     return;
1134   }
1135   m_PageList.RemoveAt(iPage);
1136 }
1137 CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict,
1138                                  const CFX_ByteStringC& name);
1139 void FPDFAPI_FlatPageAttr(CPDF_Dictionary* pPageDict,
1140                           const CFX_ByteStringC& name) {
1141   if (pPageDict->KeyExist(name)) {
1142     return;
1143   }
1144   CPDF_Object* pObj = FPDFAPI_GetPageAttr(pPageDict, name);
1145   if (pObj) {
1146     pPageDict->SetAt(name, pObj->Clone());
1147   }
1148 }