Remove a few unused variables, functions, and member variables.
[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 = FX_NEW CPDF_Dictionary;
25     m_pRootDict->SetAtName("Type", "Catalog");
26     int objnum = AddIndirectObject(m_pRootDict);
27     CPDF_Dictionary* pPages = FX_NEW CPDF_Dictionary;
28     pPages->SetAtName("Type", "Pages");
29     pPages->SetAtNumber("Count", 0);
30     pPages->SetAt("Kids", FX_NEW CPDF_Array);
31     objnum = AddIndirectObject(pPages);
32     m_pRootDict->SetAtReference("Pages", this, objnum);
33     m_pInfoDict = FX_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 = FX_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, (FX_LPCSTR)face);
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 = FX_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 = FX_NEW CPDF_Dictionary;
312                 pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
313                 CPDF_Array* pArray = FX_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 = FX_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 = FX_NEW CPDF_Dictionary;
350         CFX_ByteString cmap;
351         CFX_ByteString ordering;
352         int supplement;
353         CPDF_Array* pWidthArray = FX_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 = FX_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 = FX_NEW CPDF_Array;
404         pBaseDict->SetAt("DescendantFonts", pArray);
405         AddIndirectObject(pFontDict);
406         pArray->AddReference(this, pFontDict);
407     }
408     AddIndirectObject(pBaseDict);
409     CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary;
410     pFontDesc->SetAtName("Type", "FontDescriptor");
411     pFontDesc->SetAtName("FontName", basefont);
412     pFontDesc->SetAtInteger("Flags", flags);
413     CPDF_Array* pBBox = FX_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 = FX_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* pFontDict = NULL;
670     CPDF_Dictionary* pBaseDict = FX_NEW CPDF_Dictionary;
671     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 = FX_NEW CPDF_Dictionary;
698                 pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
699                 CPDF_Array* pArray = FX_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 = FX_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 = FX_NEW CPDF_Dictionary;
737         CFX_ByteString cmap;
738         CFX_ByteString ordering;
739         int supplement;
740         FX_BOOL bFound = FALSE;
741         CPDF_Array* pWidthArray = FX_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 = FX_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 = FX_NEW CPDF_Array;
801         pBaseDict->SetAt("DescendantFonts", pArray);
802         AddIndirectObject(pFontDict);
803         pArray->AddReference(this, pFontDict);
804     }
805     AddIndirectObject(pBaseDict);
806     CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary;
807     pFontDesc->SetAtName("Type", "FontDescriptor");
808     pFontDesc->SetAtName("FontName", basefont);
809     pFontDesc->SetAtInteger("Flags", flags);
810     CPDF_Array* pBBox = FX_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 = FX_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, FX_BOOL bVert)
871 {
872     if (pFont == NULL) {
873         return NULL;
874     }
875     FX_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 = FX_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 = FX_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 = FX_NEW CPDF_Dictionary;
923                 pEncodingDict->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
924                 CPDF_Array* pArray = FX_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 = FX_NEW CPDF_Dictionary;
958         CFX_ByteString cmap;
959         CFX_ByteString ordering;
960         int supplement;
961         CPDF_Array* pWidthArray = FX_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 = FX_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 = FX_NEW CPDF_Array;
1012         pBaseDict->SetAt("DescendantFonts", pArray);
1013         AddIndirectObject(pFontDict);
1014         pArray->AddReference(this, pFontDict);
1015     }
1016     AddIndirectObject(pBaseDict);
1017     CPDF_Dictionary* pFontDesc = FX_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 = FX_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     FX_INT32 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     if (pEncoding) {
1049         delete pEncoding;
1050     }
1051     pFontDesc->SetAtInteger("StemV", nStemV);
1052     AddIndirectObject(pFontDesc);
1053     pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
1054     return LoadFont(pBaseDict);
1055 }
1056 static int InsertDeletePDFPage(CPDF_Document* pDoc, CPDF_Dictionary* pPages,
1057                                int nPagesToGo, CPDF_Dictionary* pPage, FX_BOOL bInsert, CFX_PtrArray& stackList)
1058 {
1059     CPDF_Array* pKidList = pPages->GetArray("Kids");
1060     if (!pKidList) {
1061         return -1;
1062     }
1063     int nKids = pKidList->GetCount();
1064     for (int i = 0; i < nKids; i ++) {
1065         CPDF_Dictionary* pKid = pKidList->GetDict(i);
1066         if (pKid->GetString("Type") == FX_BSTRC("Page")) {
1067             if (nPagesToGo == 0) {
1068                 if (bInsert) {
1069                     pKidList->InsertAt(i, CPDF_Reference::Create(pDoc, pPage->GetObjNum()));
1070                     pPage->SetAtReference("Parent", pDoc, pPages->GetObjNum());
1071                 } else {
1072                     pKidList->RemoveAt(i);
1073                 }
1074                 pPages->SetAtInteger("Count", pPages->GetInteger("Count") + (bInsert ? 1 : -1));
1075                 return 1;
1076             }
1077             nPagesToGo --;
1078         } else {
1079             int nPages = pKid->GetInteger("Count");
1080             if (nPagesToGo < nPages) {
1081                 int stackCount = stackList.GetSize();
1082                 for (int j = 0; j < stackCount; ++j) {
1083                     if (pKid == stackList[j]) {
1084                         return -1;
1085                     }
1086                 }
1087                 stackList.Add(pKid);
1088                 if (InsertDeletePDFPage(pDoc, pKid, nPagesToGo, pPage, bInsert, stackList) < 0) {
1089                     return -1;
1090                 }
1091                 stackList.RemoveAt(stackCount);
1092                 pPages->SetAtInteger("Count", pPages->GetInteger("Count") + (bInsert ? 1 : -1));
1093                 return 1;
1094             }
1095             nPagesToGo -= nPages;
1096         }
1097     }
1098     return 0;
1099 }
1100 static int InsertNewPage(CPDF_Document* pDoc, int iPage, CPDF_Dictionary* pPageDict, CFX_DWordArray &pageList)
1101 {
1102     CPDF_Dictionary* pRoot = pDoc->GetRoot();
1103     if (!pRoot) {
1104         return -1;
1105     }
1106     CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
1107     if (!pPages) {
1108         return -1;
1109     }
1110     int nPages = pDoc->GetPageCount();
1111     if (iPage < 0 || iPage > nPages) {
1112         return -1;
1113     }
1114     if (iPage == nPages) {
1115         CPDF_Array* pPagesList = pPages->GetArray(FX_BSTRC("Kids"));
1116         if (!pPagesList) {
1117             pPagesList = FX_NEW CPDF_Array;
1118             pPages->SetAt(FX_BSTRC("Kids"), pPagesList);
1119         }
1120         pPagesList->Add(pPageDict, pDoc);
1121         pPages->SetAtInteger(FX_BSTRC("Count"), nPages + 1);
1122         pPageDict->SetAtReference(FX_BSTRC("Parent"), pDoc, pPages->GetObjNum());
1123     } else {
1124         CFX_PtrArray stack;
1125         stack.Add(pPages);
1126         if (InsertDeletePDFPage(pDoc, pPages, iPage, pPageDict, TRUE, stack) < 0) {
1127             return -1;
1128         }
1129     }
1130     pageList.InsertAt(iPage, pPageDict->GetObjNum());
1131     return iPage;
1132 }
1133 CPDF_Dictionary* CPDF_Document::CreateNewPage(int iPage)
1134 {
1135     CPDF_Dictionary* pDict = FX_NEW CPDF_Dictionary;
1136     pDict->SetAtName("Type", "Page");
1137     FX_DWORD dwObjNum = AddIndirectObject(pDict);
1138     if (InsertNewPage(this, iPage, pDict, m_PageList) < 0) {
1139         ReleaseIndirectObject(dwObjNum);
1140         return NULL;
1141     }
1142     return pDict;
1143 }
1144 int _PDF_GetStandardFontName(CFX_ByteString& name);
1145 CPDF_Font* CPDF_Document::AddStandardFont(FX_LPCSTR font, CPDF_FontEncoding* pEncoding)
1146 {
1147     CFX_ByteString name(font, -1);
1148     if (_PDF_GetStandardFontName(name) < 0) {
1149         return NULL;
1150     }
1151     return GetPageData()->GetStandardFont(name, pEncoding);
1152 }
1153 void CPDF_Document::DeletePage(int iPage)
1154 {
1155     CPDF_Dictionary* pRoot = GetRoot();
1156     if (pRoot == NULL) {
1157         return;
1158     }
1159     CPDF_Dictionary* pPages = pRoot->GetDict("Pages");
1160     if (pPages == NULL) {
1161         return;
1162     }
1163     int nPages = pPages->GetInteger("Count");
1164     if (iPage < 0 || iPage >= nPages) {
1165         return;
1166     }
1167     CFX_PtrArray stack;
1168     stack.Add(pPages);
1169     if (InsertDeletePDFPage(this, pPages, iPage, NULL, FALSE, stack) < 0) {
1170         return;
1171     }
1172     m_PageList.RemoveAt(iPage);
1173 }
1174 CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict, FX_BSTR name);
1175 void FPDFAPI_FlatPageAttr(CPDF_Dictionary* pPageDict, FX_BSTR name)
1176 {
1177     if (pPageDict->KeyExist(name)) {
1178         return;
1179     }
1180     CPDF_Object* pObj = FPDFAPI_GetPageAttr(pPageDict, name);
1181     if (pObj) {
1182         pPageDict->SetAt(name, pObj->Clone());
1183     }
1184 }