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