Replace FX_NEW with new, remove tests from fpdfapi
[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     FX_BYTE             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_WIN32_MOBILE_ || _FX_OS_ == _FX_WIN64_)
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, FX_BOOL bVert, FX_BOOL bTranslateName)
219 {
220     LOGFONTA lfa;
221     FXSYS_memcpy32(&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(FX_LPCBYTE 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, FX_BOOL bVert, FX_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     FX_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 FX_UINT32 FX_GetLangHashCode( FX_LPCSTR pStr)
433 {
434     FXSYS_assert( pStr != NULL);
435     FX_INT32 iLength = FXSYS_strlen(pStr);
436     FX_LPCSTR pStrEnd = pStr + iLength;
437     FX_UINT32 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(FX_UINT32 uCode)
516 {
517     FX_INT32 iStart = 0;
518     FX_INT32 iEnd = sizeof(gs_FXLang2CharsetTable) / sizeof(FX_LANG2CS) - 1;
519     while (iStart <= iEnd) {
520         FX_INT32 iMid = (iStart + iEnd) / 2;
521         const FX_LANG2CS &charset = gs_FXLang2CharsetTable[iMid];
522         if (uCode == charset.uLang) {
523             return charset.uCharset;
524         } else if (uCode < charset.uLang) {
525             iEnd = iMid - 1;
526         } else {
527             iStart = iMid + 1;
528         }
529     };
530     return 0;
531 }
532 static FX_WORD FX_GetCharsetFromLang(FX_LPCSTR pLang, FX_INT32 iLength)
533 {
534     FXSYS_assert(pLang);
535     if (iLength < 0) {
536         iLength = FXSYS_strlen(pLang);
537     }
538     FX_UINT32 uHash = FX_GetLangHashCode(pLang);
539     return FX_GetCsFromLangCode(uHash);
540 }
541 static void _CFString2CFXByteString(CFStringRef src, CFX_ByteString &dest)
542 {
543     SInt32 len =  CFStringGetLength(src);
544     CFRange range = CFRangeMake(0, len);
545     CFIndex used = 0;
546     UInt8* pBuffer = (UInt8*)calloc(len+1, sizeof(UInt8));
547     CFStringGetBytes(src, range, kCFStringEncodingASCII, 0, false, pBuffer, len, &used);
548     dest = (FX_LPSTR)pBuffer;
549     free(pBuffer);
550 }
551 FX_BOOL IsHasCharSet(CFArrayRef languages, const CFX_DWordArray &charSets)
552 {
553     int iCount = charSets.GetSize();
554     for (int i = 0; i < CFArrayGetCount(languages); ++i) {
555         CFStringRef language = (CFStringRef)CFArrayGetValueAtIndex(languages, i);
556         FX_DWORD CharSet = FX_GetCharsetFromLang(CFStringGetCStringPtr(language, kCFStringEncodingMacRoman), -1);
557         for (int j = 0; j < iCount; ++j) {
558             if (CharSet == charSets[j]) {
559                 return TRUE;
560             }
561         }
562     }
563     return FALSE;
564 }
565 void FX_GetCharWidth(CTFontRef font, UniChar start, UniChar end, int* width)
566 {
567     CGFloat size = CTFontGetSize(font);
568     for (; start <= end; ++start) {
569         CGGlyph pGlyph = 0;
570         CFIndex count = 1;
571         CTFontGetGlyphsForCharacters(font, &start, &pGlyph, count);
572         CGSize advances;
573         CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &pGlyph, &advances, 1);
574         *width = (int)(advances.width / size * 1000) ;
575         width++;
576     }
577 }
578 static void _InsertWidthArray(CTFontRef font, int start, int end, CPDF_Array* pWidthArray)
579 {
580     int size = end - start + 1;
581     int* widths = FX_Alloc(int, size);
582     FX_GetCharWidth(font, start, end, widths);
583     int i;
584     for (i = 1; i < size; i ++)
585         if (widths[i] != *widths) {
586             break;
587         }
588     if (i == size) {
589         int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
590         pWidthArray->AddInteger(first + size - 1);
591         pWidthArray->AddInteger(*widths);
592     } else {
593         CPDF_Array* pWidthArray1 = new CPDF_Array;
594         pWidthArray->Add(pWidthArray1);
595         for (i = 0; i < size; i ++) {
596             pWidthArray1->AddInteger(widths[i]);
597         }
598     }
599     FX_Free(widths);
600 }
601 CPDF_Font* CPDF_Document::AddMacFont(CTFontRef pFont, FX_BOOL bVert, FX_BOOL bTranslateName)
602 {
603     CTFontRef font = (CTFontRef)pFont;
604     CTFontDescriptorRef descriptor = CTFontCopyFontDescriptor(font);
605     if (descriptor == NULL) {
606         return NULL;
607     }
608     CFX_ByteString basefont;
609     FX_BOOL bCJK = FALSE;
610     int flags = 0, italicangle = 0, ascend = 0, descend = 0, capheight = 0, bbox[4];
611     FXSYS_memset32(bbox, 0, sizeof(int) * 4);
612     CFArrayRef languages = (CFArrayRef)CTFontDescriptorCopyAttribute(descriptor, kCTFontLanguagesAttribute);
613     if (languages == NULL) {
614         CFRelease(descriptor);
615         return NULL;
616     }
617     CFX_DWordArray charSets;
618     charSets.Add(FXFONT_CHINESEBIG5_CHARSET);
619     charSets.Add(FXFONT_GB2312_CHARSET);
620     charSets.Add(FXFONT_HANGEUL_CHARSET);
621     charSets.Add(FXFONT_SHIFTJIS_CHARSET);
622     if (IsHasCharSet(languages, charSets)) {
623         bCJK = TRUE;
624     }
625     CFRelease(descriptor);
626     CFDictionaryRef traits = (CFDictionaryRef)CTFontCopyTraits(font);
627     if (traits == NULL) {
628         CFRelease(languages);
629         return NULL;
630     }
631     CFNumberRef sybolicTrait = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait);
632     CTFontSymbolicTraits trait = 0;
633     CFNumberGetValue(sybolicTrait, kCFNumberSInt32Type, &trait);
634     if (trait & kCTFontItalicTrait) {
635         flags |= PDFFONT_ITALIC;
636     }
637     if (trait & kCTFontMonoSpaceTrait) {
638         flags |= PDFFONT_FIXEDPITCH;
639     }
640     if (trait & kCTFontModernSerifsClass) {
641         flags |= PDFFONT_SERIF;
642     }
643     if (trait & kCTFontScriptsClass) {
644         flags |= PDFFONT_SCRIPT;
645     }
646     CFNumberRef weightTrait = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait);
647     Float32 weight = 0;
648     CFNumberGetValue(weightTrait, kCFNumberFloat32Type, &weight);
649     italicangle = CTFontGetSlantAngle(font);
650     ascend      = CTFontGetAscent(font);
651     descend     = CTFontGetDescent(font);
652     capheight   = CTFontGetCapHeight(font);
653     CGRect box  = CTFontGetBoundingBox(font);
654     bbox[0]     = box.origin.x;
655     bbox[1]     = box.origin.y;
656     bbox[2]     = box.origin.x + box.size.width;
657     bbox[3]     = box.origin.y + box.size.height;
658     if (bTranslateName && bCJK) {
659         CFStringRef postName = CTFontCopyPostScriptName(font);
660         _CFString2CFXByteString(postName, basefont);
661         CFRelease(postName);
662     }
663     if (basefont.IsEmpty()) {
664         CFStringRef fullName = CTFontCopyFullName(font);
665         _CFString2CFXByteString(fullName, basefont);
666         CFRelease(fullName);
667     }
668     basefont.Replace(" ", "");
669     CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
670     CPDF_Dictionary* pFontDict = pBaseDict;
671     if (!bCJK) {
672         charSets.RemoveAll();
673         charSets.Add(FXFONT_ANSI_CHARSET);
674         charSets.Add(FXFONT_DEFAULT_CHARSET);
675         charSets.Add(FXFONT_SYMBOL_CHARSET);
676         if (IsHasCharSet(languages, charSets)) {
677             charSets.RemoveAll();
678             charSets.Add(FXFONT_SYMBOL_CHARSET);
679             if (IsHasCharSet(languages, charSets)) {
680                 flags |= PDFFONT_SYMBOLIC;
681             } else {
682                 flags |= PDFFONT_NONSYMBOLIC;
683             }
684             pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
685         } else {
686             flags |= PDFFONT_NONSYMBOLIC;
687             size_t i;
688             for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++) {
689                 charSets.RemoveAll();
690                 charSets.Add(g_FX_CharsetUnicodes[i].m_Charset);
691                 if (IsHasCharSet(languages, charSets)) {
692                     break;
693                 }
694             }
695             if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
696                 CPDF_Dictionary* pEncoding = new CPDF_Dictionary;
697                 pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
698                 CPDF_Array* pArray = new CPDF_Array;
699                 pArray->AddInteger(128);
700                 const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
701                 for (int j = 0; j < 128; j ++) {
702                     CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
703                     if (name.IsEmpty()) {
704                         pArray->AddName(FX_BSTRC(".notdef"));
705                     } else {
706                         pArray->AddName(name);
707                     }
708                 }
709                 pEncoding->SetAt(FX_BSTRC("Differences"), pArray);
710                 AddIndirectObject(pEncoding);
711                 pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding);
712             }
713         }
714         if (weight > 0.0 && trait & kCTFontItalicTrait) {
715             basefont += ",BoldItalic";
716         } else if (weight > 0.0) {
717             basefont += ",Bold";
718         } else if (trait & kCTFontItalicTrait) {
719             basefont += ",Italic";
720         }
721         pBaseDict->SetAtName("Subtype", "TrueType");
722         pBaseDict->SetAtName("BaseFont", basefont);
723         pBaseDict->SetAtNumber("FirstChar", 32);
724         pBaseDict->SetAtNumber("LastChar", 255);
725         int char_widths[224];
726         FX_GetCharWidth(font, 32, 255, char_widths);
727         CPDF_Array* pWidths = new CPDF_Array;
728         for (int i = 0; i < 224; i ++) {
729             pWidths->AddInteger(char_widths[i]);
730         }
731         pBaseDict->SetAt("Widths", pWidths);
732     }  else {
733         flags |= PDFFONT_NONSYMBOLIC;
734         CPDF_Array* pArray = NULL;
735         pFontDict = new CPDF_Dictionary;
736         CFX_ByteString cmap;
737         CFX_ByteString ordering;
738         int supplement;
739         FX_BOOL bFound = FALSE;
740         CPDF_Array* pWidthArray = new CPDF_Array;
741         charSets.RemoveAll();
742         charSets.Add(FXFONT_CHINESEBIG5_CHARSET);
743         if (IsHasCharSet(languages, charSets)) {
744             cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
745             ordering = "CNS1";
746             supplement = 4;
747             pWidthArray->AddInteger(1);
748             _InsertWidthArray(font, 0x20, 0x7e, pWidthArray);
749             bFound = TRUE;
750         }
751         charSets.RemoveAll();
752         charSets.Add(FXFONT_GB2312_CHARSET);
753         if (!bFound && IsHasCharSet(languages, charSets)) {
754             cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
755             ordering = "GB1", supplement = 2;
756             pWidthArray->AddInteger(7716);
757             _InsertWidthArray(font, 0x20, 0x20, pWidthArray);
758             pWidthArray->AddInteger(814);
759             _InsertWidthArray(font, 0x21, 0x7e, pWidthArray);
760             bFound = TRUE;
761         }
762         charSets.RemoveAll();
763         charSets.Add(FXFONT_HANGEUL_CHARSET);
764         if (!bFound && IsHasCharSet(languages, charSets)) {
765             cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
766             ordering = "Korea1";
767             supplement = 2;
768             pWidthArray->AddInteger(1);
769             _InsertWidthArray(font, 0x20, 0x7e, pWidthArray);
770             bFound = TRUE;
771         }
772         charSets.RemoveAll();
773         charSets.Add(FXFONT_SHIFTJIS_CHARSET);
774         if (!bFound && IsHasCharSet(languages, charSets)) {
775             cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
776             ordering = "Japan1";
777             supplement = 5;
778             pWidthArray->AddInteger(231);
779             _InsertWidthArray(font, 0x20, 0x7d, pWidthArray);
780             pWidthArray->AddInteger(326);
781             _InsertWidthArray(font, 0xa0, 0xa0, pWidthArray);
782             pWidthArray->AddInteger(327);
783             _InsertWidthArray(font, 0xa1, 0xdf, pWidthArray);
784             pWidthArray->AddInteger(631);
785             _InsertWidthArray(font, 0x7e, 0x7e, pWidthArray);
786         }
787         pBaseDict->SetAtName("Subtype", "Type0");
788         pBaseDict->SetAtName("BaseFont", basefont);
789         pBaseDict->SetAtName("Encoding", cmap);
790         pFontDict->SetAt("W", pWidthArray);
791         pFontDict->SetAtName("Type", "Font");
792         pFontDict->SetAtName("Subtype", "CIDFontType2");
793         pFontDict->SetAtName("BaseFont", basefont);
794         CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
795         pCIDSysInfo->SetAtString("Registry", "Adobe");
796         pCIDSysInfo->SetAtString("Ordering", ordering);
797         pCIDSysInfo->SetAtInteger("Supplement", supplement);
798         pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
799         pArray = new CPDF_Array;
800         pBaseDict->SetAt("DescendantFonts", pArray);
801         AddIndirectObject(pFontDict);
802         pArray->AddReference(this, pFontDict);
803     }
804     AddIndirectObject(pBaseDict);
805     CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
806     pFontDesc->SetAtName("Type", "FontDescriptor");
807     pFontDesc->SetAtName("FontName", basefont);
808     pFontDesc->SetAtInteger("Flags", flags);
809     CPDF_Array* pBBox = new CPDF_Array;
810     for (int i = 0; i < 4; i ++) {
811         pBBox->AddInteger(bbox[i]);
812     }
813     pFontDesc->SetAt("FontBBox", pBBox);
814     pFontDesc->SetAtInteger("ItalicAngle", italicangle);
815     pFontDesc->SetAtInteger("Ascent", ascend);
816     pFontDesc->SetAtInteger("Descent", descend);
817     pFontDesc->SetAtInteger("CapHeight", capheight);
818     CGFloat fStemV = 0;
819     int16_t min_width = SHRT_MAX;
820     static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
821     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
822     CGGlyph glyphs[count];
823     CGRect boundingRects[count];
824     if (CTFontGetGlyphsForCharacters(font, stem_chars, glyphs, count)) {
825         CTFontGetBoundingRectsForGlyphs(font, kCTFontHorizontalOrientation,
826                                         glyphs, boundingRects, count);
827         for (size_t i = 0; i < count; i++) {
828             int16_t width = boundingRects[i].size.width;
829             if (width > 0 && width < min_width) {
830                 min_width = width;
831                 fStemV = min_width;
832             }
833         }
834     }
835     pFontDesc->SetAtInteger("StemV", fStemV);
836     AddIndirectObject(pFontDesc);
837     pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
838     CFRelease(traits);
839     CFRelease(languages);
840     return LoadFont(pBaseDict);
841 }
842 #endif
843 static void _InsertWidthArray1(CFX_Font* pFont, IFX_FontEncoding* pEncoding, FX_WCHAR start, FX_WCHAR end, CPDF_Array* pWidthArray)
844 {
845     int size = end - start + 1;
846     int* widths = FX_Alloc(int, size);
847     int i;
848     for (i = 0; i < size; i ++) {
849         int glyph_index = pEncoding->GlyphFromCharCode(start + i);
850         widths[i] = pFont->GetGlyphWidth(glyph_index);
851     }
852     for (i = 1; i < size; i ++)
853         if (widths[i] != *widths) {
854             break;
855         }
856     if (i == size) {
857         int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
858         pWidthArray->AddInteger(first + size - 1);
859         pWidthArray->AddInteger(*widths);
860     } else {
861         CPDF_Array* pWidthArray1 = new CPDF_Array;
862         pWidthArray->Add(pWidthArray1);
863         for (i = 0; i < size; i ++) {
864             pWidthArray1->AddInteger(widths[i]);
865         }
866     }
867     FX_Free(widths);
868 }
869 CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, FX_BOOL bVert)
870 {
871     if (pFont == NULL) {
872         return NULL;
873     }
874     FX_BOOL bCJK = charset == FXFONT_CHINESEBIG5_CHARSET || charset == FXFONT_GB2312_CHARSET ||
875                    charset == FXFONT_HANGEUL_CHARSET || charset == FXFONT_SHIFTJIS_CHARSET;
876     CFX_ByteString basefont = pFont->GetFamilyName();
877     basefont.Replace(" ", "");
878     int flags = 0;
879     if (pFont->IsBold()) {
880         flags |= PDFFONT_FORCEBOLD;
881     }
882     if (pFont->IsItalic()) {
883         flags |= PDFFONT_ITALIC;
884     }
885     if (pFont->IsFixedWidth()) {
886         flags |= PDFFONT_FIXEDPITCH;
887     }
888     CPDF_Dictionary* pBaseDict = new CPDF_Dictionary;
889     pBaseDict->SetAtName("Type", "Font");
890     IFX_FontEncoding* pEncoding = FXGE_CreateUnicodeEncoding(pFont);
891     CPDF_Dictionary* pFontDict = pBaseDict;
892     if (!bCJK) {
893         CPDF_Array* pWidths = new CPDF_Array;
894         int charcode;
895         for (charcode = 32; charcode < 128; charcode ++) {
896             int glyph_index = pEncoding->GlyphFromCharCode(charcode);
897             int char_width = pFont->GetGlyphWidth(glyph_index);
898             pWidths->AddInteger(char_width);
899         }
900         if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_DEFAULT_CHARSET ||
901                 charset == FXFONT_SYMBOL_CHARSET) {
902             if (charset == FXFONT_SYMBOL_CHARSET) {
903                 flags |= PDFFONT_SYMBOLIC;
904             } else {
905                 flags |= PDFFONT_NONSYMBOLIC;
906             }
907             pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
908             for (charcode = 128; charcode <= 255; charcode ++) {
909                 int glyph_index = pEncoding->GlyphFromCharCode(charcode);
910                 int char_width = pFont->GetGlyphWidth(glyph_index);
911                 pWidths->AddInteger(char_width);
912             }
913         } else {
914             flags |= PDFFONT_NONSYMBOLIC;
915             size_t i;
916             for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++)
917                 if (g_FX_CharsetUnicodes[i].m_Charset == charset) {
918                     break;
919                 }
920             if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
921                 CPDF_Dictionary* pEncodingDict = new CPDF_Dictionary;
922                 pEncodingDict->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
923                 CPDF_Array* pArray = new CPDF_Array;
924                 pArray->AddInteger(128);
925                 const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
926                 for (int j = 0; j < 128; j ++) {
927                     CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
928                     if (name.IsEmpty()) {
929                         pArray->AddName(FX_BSTRC(".notdef"));
930                     } else {
931                         pArray->AddName(name);
932                     }
933                     int glyph_index = pEncoding->GlyphFromCharCode(pUnicodes[j]);
934                     int char_width = pFont->GetGlyphWidth(glyph_index);
935                     pWidths->AddInteger(char_width);
936                 }
937                 pEncodingDict->SetAt(FX_BSTRC("Differences"), pArray);
938                 AddIndirectObject(pEncodingDict);
939                 pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncodingDict);
940             }
941         }
942         if (pFont->IsBold() && pFont->IsItalic()) {
943             basefont += ",BoldItalic";
944         } else if (pFont->IsBold()) {
945             basefont += ",Bold";
946         } else if (pFont->IsItalic()) {
947             basefont += ",Italic";
948         }
949         pBaseDict->SetAtName("Subtype", "TrueType");
950         pBaseDict->SetAtName("BaseFont", basefont);
951         pBaseDict->SetAtNumber("FirstChar", 32);
952         pBaseDict->SetAtNumber("LastChar", 255);
953         pBaseDict->SetAt("Widths", pWidths);
954     } else {
955         flags |= PDFFONT_NONSYMBOLIC;
956         pFontDict = new CPDF_Dictionary;
957         CFX_ByteString cmap;
958         CFX_ByteString ordering;
959         int supplement;
960         CPDF_Array* pWidthArray = new CPDF_Array;
961         switch (charset) {
962             case FXFONT_CHINESEBIG5_CHARSET:
963                 cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
964                 ordering = "CNS1";
965                 supplement = 4;
966                 pWidthArray->AddInteger(1);
967                 _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7e, pWidthArray);
968                 break;
969             case FXFONT_GB2312_CHARSET:
970                 cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
971                 ordering = "GB1", supplement = 2;
972                 pWidthArray->AddInteger(7716);
973                 _InsertWidthArray1(pFont, pEncoding, 0x20, 0x20, pWidthArray);
974                 pWidthArray->AddInteger(814);
975                 _InsertWidthArray1(pFont, pEncoding, 0x21, 0x7e, pWidthArray);
976                 break;
977             case FXFONT_HANGEUL_CHARSET:
978                 cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
979                 ordering = "Korea1";
980                 supplement = 2;
981                 pWidthArray->AddInteger(1);
982                 _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7e, pWidthArray);
983                 break;
984             case FXFONT_SHIFTJIS_CHARSET:
985                 cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
986                 ordering = "Japan1";
987                 supplement = 5;
988                 pWidthArray->AddInteger(231);
989                 _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7d, pWidthArray);
990                 pWidthArray->AddInteger(326);
991                 _InsertWidthArray1(pFont, pEncoding, 0xa0, 0xa0, pWidthArray);
992                 pWidthArray->AddInteger(327);
993                 _InsertWidthArray1(pFont, pEncoding, 0xa1, 0xdf, pWidthArray);
994                 pWidthArray->AddInteger(631);
995                 _InsertWidthArray1(pFont, pEncoding, 0x7e, 0x7e, pWidthArray);
996                 break;
997         }
998         pBaseDict->SetAtName("Subtype", "Type0");
999         pBaseDict->SetAtName("BaseFont", basefont);
1000         pBaseDict->SetAtName("Encoding", cmap);
1001         pFontDict->SetAt("W", pWidthArray);
1002         pFontDict->SetAtName("Type", "Font");
1003         pFontDict->SetAtName("Subtype", "CIDFontType2");
1004         pFontDict->SetAtName("BaseFont", basefont);
1005         CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary;
1006         pCIDSysInfo->SetAtString("Registry", "Adobe");
1007         pCIDSysInfo->SetAtString("Ordering", ordering);
1008         pCIDSysInfo->SetAtInteger("Supplement", supplement);
1009         pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
1010         CPDF_Array* pArray = new CPDF_Array;
1011         pBaseDict->SetAt("DescendantFonts", pArray);
1012         AddIndirectObject(pFontDict);
1013         pArray->AddReference(this, pFontDict);
1014     }
1015     AddIndirectObject(pBaseDict);
1016     CPDF_Dictionary* pFontDesc = new CPDF_Dictionary;
1017     pFontDesc->SetAtName("Type", "FontDescriptor");
1018     pFontDesc->SetAtName("FontName", basefont);
1019     pFontDesc->SetAtInteger("Flags", flags);
1020     pFontDesc->SetAtInteger("ItalicAngle", pFont->m_pSubstFont ? pFont->m_pSubstFont->m_ItalicAngle : 0);
1021     pFontDesc->SetAtInteger("Ascent", pFont->GetAscent());
1022     pFontDesc->SetAtInteger("Descent", pFont->GetDescent());
1023     FX_RECT bbox;
1024     pFont->GetBBox(bbox);
1025     CPDF_Array* pBBox = new CPDF_Array;
1026     pBBox->AddInteger(bbox.left);
1027     pBBox->AddInteger(bbox.bottom);
1028     pBBox->AddInteger(bbox.right);
1029     pBBox->AddInteger(bbox.top);
1030     pFontDesc->SetAt("FontBBox", pBBox);
1031     FX_INT32 nStemV = 0;
1032     if (pFont->m_pSubstFont) {
1033         nStemV = pFont->m_pSubstFont->m_Weight / 5;
1034     } else {
1035         static const FX_CHAR stem_chars[] = {'i', 'I', '!', '1'};
1036         const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
1037         FX_DWORD glyph = pEncoding->GlyphFromCharCode(stem_chars[0]);
1038         nStemV = pFont->GetGlyphWidth(glyph);
1039         for (size_t i = 1; i < count; i++) {
1040             glyph = pEncoding->GlyphFromCharCode(stem_chars[i]);
1041             int width = pFont->GetGlyphWidth(glyph);
1042             if (width > 0 && width < nStemV) {
1043                 nStemV = width;
1044             }
1045         }
1046     }
1047     if (pEncoding) {
1048         delete pEncoding;
1049     }
1050     pFontDesc->SetAtInteger("StemV", nStemV);
1051     AddIndirectObject(pFontDesc);
1052     pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
1053     return LoadFont(pBaseDict);
1054 }
1055 static int InsertDeletePDFPage(CPDF_Document* pDoc, CPDF_Dictionary* pPages,
1056                                int nPagesToGo, CPDF_Dictionary* pPage, FX_BOOL bInsert, CFX_PtrArray& stackList)
1057 {
1058     CPDF_Array* pKidList = pPages->GetArray("Kids");
1059     if (!pKidList) {
1060         return -1;
1061     }
1062     int nKids = pKidList->GetCount();
1063     for (int i = 0; i < nKids; i ++) {
1064         CPDF_Dictionary* pKid = pKidList->GetDict(i);
1065         if (pKid->GetString("Type") == FX_BSTRC("Page")) {
1066             if (nPagesToGo == 0) {
1067                 if (bInsert) {
1068                     pKidList->InsertAt(i, CPDF_Reference::Create(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(FX_LPCSTR 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, FX_BSTR name);
1174 void FPDFAPI_FlatPageAttr(CPDF_Dictionary* pPageDict, FX_BSTR 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 }