Convert all line endings to LF.
[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*)malloc(sizeof(UInt8) * (len + 1));
547     FXSYS_memset32(pBuffer, 0, sizeof(UInt8) * (len + 1));
548     CFStringGetBytes(src, range, kCFStringEncodingASCII, 0, false, pBuffer, len, &used);
549     dest = (FX_LPSTR)pBuffer;
550     free(pBuffer);
551 }
552 FX_BOOL IsHasCharSet(CFArrayRef languages, const CFX_DWordArray &charSets)
553 {
554     int iCount = charSets.GetSize();
555     for (int i = 0; i < CFArrayGetCount(languages); ++i) {
556         CFStringRef language = (CFStringRef)CFArrayGetValueAtIndex(languages, i);
557         FX_DWORD CharSet = FX_GetCharsetFromLang(CFStringGetCStringPtr(language, kCFStringEncodingMacRoman), -1);
558         for (int j = 0; j < iCount; ++j) {
559             if (CharSet == charSets[j]) {
560                 return TRUE;
561             }
562         }
563     }
564     return FALSE;
565 }
566 void FX_GetCharWidth(CTFontRef font, UniChar start, UniChar end, int* width)
567 {
568     CGFloat size = CTFontGetSize(font);
569     for (; start <= end; ++start) {
570         CGGlyph pGlyph = 0;
571         CFIndex count = 1;
572         CTFontGetGlyphsForCharacters(font, &start, &pGlyph, count);
573         CGSize advances;
574         CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &pGlyph, &advances, 1);
575         *width = (int)(advances.width / size * 1000) ;
576         width++;
577     }
578 }
579 static void _InsertWidthArray(CTFontRef font, int start, int end, CPDF_Array* pWidthArray)
580 {
581     int size = end - start + 1;
582     int* widths = FX_Alloc(int, size);
583     FX_GetCharWidth(font, start, end, widths);
584     int i;
585     for (i = 1; i < size; i ++)
586         if (widths[i] != *widths) {
587             break;
588         }
589     if (i == size) {
590         int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
591         pWidthArray->AddInteger(first + size - 1);
592         pWidthArray->AddInteger(*widths);
593     } else {
594         CPDF_Array* pWidthArray1 = FX_NEW CPDF_Array;
595         pWidthArray->Add(pWidthArray1);
596         for (i = 0; i < size; i ++) {
597             pWidthArray1->AddInteger(widths[i]);
598         }
599     }
600     FX_Free(widths);
601 }
602 CPDF_Font* CPDF_Document::AddMacFont(CTFontRef pFont, FX_BOOL bVert, FX_BOOL bTranslateName)
603 {
604     CTFontRef font = (CTFontRef)pFont;
605     CTFontDescriptorRef descriptor = CTFontCopyFontDescriptor(font);
606     if (descriptor == NULL) {
607         return NULL;
608     }
609     CFX_ByteString basefont;
610     FX_BOOL bCJK = FALSE;
611     int flags = 0, italicangle = 0, ascend = 0, descend = 0, capheight = 0, bbox[4];
612     FXSYS_memset32(bbox, 0, sizeof(int) * 4);
613     CFArrayRef languages = (CFArrayRef)CTFontDescriptorCopyAttribute(descriptor, kCTFontLanguagesAttribute);
614     if (languages == NULL) {
615         CFRelease(descriptor);
616         return NULL;
617     }
618     CFX_DWordArray charSets;
619     charSets.Add(FXFONT_CHINESEBIG5_CHARSET);
620     charSets.Add(FXFONT_GB2312_CHARSET);
621     charSets.Add(FXFONT_HANGEUL_CHARSET);
622     charSets.Add(FXFONT_SHIFTJIS_CHARSET);
623     if (IsHasCharSet(languages, charSets)) {
624         bCJK = TRUE;
625     }
626     CFRelease(descriptor);
627     CFDictionaryRef traits = (CFDictionaryRef)CTFontCopyTraits(font);
628     if (traits == NULL) {
629         CFRelease(languages);
630         return NULL;
631     }
632     CFNumberRef sybolicTrait = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait);
633     CTFontSymbolicTraits trait = 0;
634     CFNumberGetValue(sybolicTrait, kCFNumberSInt32Type, &trait);
635     if (trait & kCTFontItalicTrait) {
636         flags |= PDFFONT_ITALIC;
637     }
638     if (trait & kCTFontMonoSpaceTrait) {
639         flags |= PDFFONT_FIXEDPITCH;
640     }
641     if (trait & kCTFontModernSerifsClass) {
642         flags |= PDFFONT_SERIF;
643     }
644     if (trait & kCTFontScriptsClass) {
645         flags |= PDFFONT_SCRIPT;
646     }
647     CFNumberRef weightTrait = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait);
648     Float32 weight = 0;
649     CFNumberGetValue(weightTrait, kCFNumberFloat32Type, &weight);
650     italicangle = CTFontGetSlantAngle(font);
651     ascend      = CTFontGetAscent(font);
652     descend     = CTFontGetDescent(font);
653     capheight   = CTFontGetCapHeight(font);
654     CGRect box  = CTFontGetBoundingBox(font);
655     bbox[0]     = box.origin.x;
656     bbox[1]     = box.origin.y;
657     bbox[2]     = box.origin.x + box.size.width;
658     bbox[3]     = box.origin.y + box.size.height;
659     if (bTranslateName && bCJK) {
660         CFStringRef postName = CTFontCopyPostScriptName(font);
661         _CFString2CFXByteString(postName, basefont);
662         CFRelease(postName);
663     }
664     if (basefont.IsEmpty()) {
665         CFStringRef fullName = CTFontCopyFullName(font);
666         _CFString2CFXByteString(fullName, basefont);
667         CFRelease(fullName);
668     }
669     basefont.Replace(" ", "");
670     CPDF_Dictionary* pFontDict = NULL;
671     CPDF_Dictionary* pBaseDict = FX_NEW CPDF_Dictionary;
672     pFontDict = pBaseDict;
673     if (!bCJK) {
674         charSets.RemoveAll();
675         charSets.Add(FXFONT_ANSI_CHARSET);
676         charSets.Add(FXFONT_DEFAULT_CHARSET);
677         charSets.Add(FXFONT_SYMBOL_CHARSET);
678         if (IsHasCharSet(languages, charSets)) {
679             charSets.RemoveAll();
680             charSets.Add(FXFONT_SYMBOL_CHARSET);
681             if (IsHasCharSet(languages, charSets)) {
682                 flags |= PDFFONT_SYMBOLIC;
683             } else {
684                 flags |= PDFFONT_NONSYMBOLIC;
685             }
686             pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
687         } else {
688             flags |= PDFFONT_NONSYMBOLIC;
689             int i;
690             for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++) {
691                 charSets.RemoveAll();
692                 charSets.Add(g_FX_CharsetUnicodes[i].m_Charset);
693                 if (IsHasCharSet(languages, charSets)) {
694                     break;
695                 }
696             }
697             if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
698                 CPDF_Dictionary* pEncoding = FX_NEW CPDF_Dictionary;
699                 pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
700                 CPDF_Array* pArray = FX_NEW CPDF_Array;
701                 pArray->AddInteger(128);
702                 const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
703                 for (int j = 0; j < 128; j ++) {
704                     CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
705                     if (name.IsEmpty()) {
706                         pArray->AddName(FX_BSTRC(".notdef"));
707                     } else {
708                         pArray->AddName(name);
709                     }
710                 }
711                 pEncoding->SetAt(FX_BSTRC("Differences"), pArray);
712                 AddIndirectObject(pEncoding);
713                 pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding);
714             }
715         }
716         if (weight > 0.0 && trait & kCTFontItalicTrait) {
717             basefont += ",BoldItalic";
718         } else if (weight > 0.0) {
719             basefont += ",Bold";
720         } else if (trait & kCTFontItalicTrait) {
721             basefont += ",Italic";
722         }
723         pBaseDict->SetAtName("Subtype", "TrueType");
724         pBaseDict->SetAtName("BaseFont", basefont);
725         pBaseDict->SetAtNumber("FirstChar", 32);
726         pBaseDict->SetAtNumber("LastChar", 255);
727         int char_widths[224];
728         FX_GetCharWidth(font, 32, 255, char_widths);
729         CPDF_Array* pWidths = FX_NEW CPDF_Array;
730         for (int i = 0; i < 224; i ++) {
731             pWidths->AddInteger(char_widths[i]);
732         }
733         pBaseDict->SetAt("Widths", pWidths);
734     }  else {
735         flags |= PDFFONT_NONSYMBOLIC;
736         CPDF_Array* pArray = NULL;
737         pFontDict = FX_NEW CPDF_Dictionary;
738         CFX_ByteString cmap;
739         CFX_ByteString ordering;
740         int supplement;
741         FX_BOOL bFound = FALSE;
742         CPDF_Array* pWidthArray = FX_NEW CPDF_Array;
743         charSets.RemoveAll();
744         charSets.Add(FXFONT_CHINESEBIG5_CHARSET);
745         if (IsHasCharSet(languages, charSets)) {
746             cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
747             ordering = "CNS1";
748             supplement = 4;
749             pWidthArray->AddInteger(1);
750             _InsertWidthArray(font, 0x20, 0x7e, pWidthArray);
751             bFound = TRUE;
752         }
753         charSets.RemoveAll();
754         charSets.Add(FXFONT_GB2312_CHARSET);
755         if (!bFound && IsHasCharSet(languages, charSets)) {
756             cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
757             ordering = "GB1", supplement = 2;
758             pWidthArray->AddInteger(7716);
759             _InsertWidthArray(font, 0x20, 0x20, pWidthArray);
760             pWidthArray->AddInteger(814);
761             _InsertWidthArray(font, 0x21, 0x7e, pWidthArray);
762             bFound = TRUE;
763         }
764         charSets.RemoveAll();
765         charSets.Add(FXFONT_HANGEUL_CHARSET);
766         if (!bFound && IsHasCharSet(languages, charSets)) {
767             cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
768             ordering = "Korea1";
769             supplement = 2;
770             pWidthArray->AddInteger(1);
771             _InsertWidthArray(font, 0x20, 0x7e, pWidthArray);
772             bFound = TRUE;
773         }
774         charSets.RemoveAll();
775         charSets.Add(FXFONT_SHIFTJIS_CHARSET);
776         if (!bFound && IsHasCharSet(languages, charSets)) {
777             cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
778             ordering = "Japan1";
779             supplement = 5;
780             pWidthArray->AddInteger(231);
781             _InsertWidthArray(font, 0x20, 0x7d, pWidthArray);
782             pWidthArray->AddInteger(326);
783             _InsertWidthArray(font, 0xa0, 0xa0, pWidthArray);
784             pWidthArray->AddInteger(327);
785             _InsertWidthArray(font, 0xa1, 0xdf, pWidthArray);
786             pWidthArray->AddInteger(631);
787             _InsertWidthArray(font, 0x7e, 0x7e, pWidthArray);
788         }
789         pBaseDict->SetAtName("Subtype", "Type0");
790         pBaseDict->SetAtName("BaseFont", basefont);
791         pBaseDict->SetAtName("Encoding", cmap);
792         pFontDict->SetAt("W", pWidthArray);
793         pFontDict->SetAtName("Type", "Font");
794         pFontDict->SetAtName("Subtype", "CIDFontType2");
795         pFontDict->SetAtName("BaseFont", basefont);
796         CPDF_Dictionary* pCIDSysInfo = FX_NEW CPDF_Dictionary;
797         pCIDSysInfo->SetAtString("Registry", "Adobe");
798         pCIDSysInfo->SetAtString("Ordering", ordering);
799         pCIDSysInfo->SetAtInteger("Supplement", supplement);
800         pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
801         pArray = FX_NEW CPDF_Array;
802         pBaseDict->SetAt("DescendantFonts", pArray);
803         AddIndirectObject(pFontDict);
804         pArray->AddReference(this, pFontDict);
805     }
806     AddIndirectObject(pBaseDict);
807     CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary;
808     pFontDesc->SetAtName("Type", "FontDescriptor");
809     pFontDesc->SetAtName("FontName", basefont);
810     pFontDesc->SetAtInteger("Flags", flags);
811     CPDF_Array* pBBox = FX_NEW CPDF_Array;
812     for (int i = 0; i < 4; i ++) {
813         pBBox->AddInteger(bbox[i]);
814     }
815     pFontDesc->SetAt("FontBBox", pBBox);
816     pFontDesc->SetAtInteger("ItalicAngle", italicangle);
817     pFontDesc->SetAtInteger("Ascent", ascend);
818     pFontDesc->SetAtInteger("Descent", descend);
819     pFontDesc->SetAtInteger("CapHeight", capheight);
820     CGFloat fStemV = 0;
821     int16_t min_width = SHRT_MAX;
822     static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
823     const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
824     CGGlyph glyphs[count];
825     CGRect boundingRects[count];
826     if (CTFontGetGlyphsForCharacters(font, stem_chars, glyphs, count)) {
827         CTFontGetBoundingRectsForGlyphs(font, kCTFontHorizontalOrientation,
828                                         glyphs, boundingRects, count);
829         for (size_t i = 0; i < count; i++) {
830             int16_t width = boundingRects[i].size.width;
831             if (width > 0 && width < min_width) {
832                 min_width = width;
833                 fStemV = min_width;
834             }
835         }
836     }
837     pFontDesc->SetAtInteger("StemV", fStemV);
838     AddIndirectObject(pFontDesc);
839     pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
840     CFRelease(traits);
841     CFRelease(languages);
842     return LoadFont(pBaseDict);
843 }
844 #endif
845 static void _InsertWidthArray1(CFX_Font* pFont, IFX_FontEncoding* pEncoding, FX_WCHAR start, FX_WCHAR end, CPDF_Array* pWidthArray)
846 {
847     int size = end - start + 1;
848     int* widths = FX_Alloc(int, size);
849     int i;
850     for (i = 0; i < size; i ++) {
851         int glyph_index = pEncoding->GlyphFromCharCode(start + i);
852         widths[i] = pFont->GetGlyphWidth(glyph_index);
853     }
854     for (i = 1; i < size; i ++)
855         if (widths[i] != *widths) {
856             break;
857         }
858     if (i == size) {
859         int first = pWidthArray->GetInteger(pWidthArray->GetCount() - 1);
860         pWidthArray->AddInteger(first + size - 1);
861         pWidthArray->AddInteger(*widths);
862     } else {
863         CPDF_Array* pWidthArray1 = FX_NEW CPDF_Array;
864         pWidthArray->Add(pWidthArray1);
865         for (i = 0; i < size; i ++) {
866             pWidthArray1->AddInteger(widths[i]);
867         }
868     }
869     FX_Free(widths);
870 }
871 CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, FX_BOOL bVert)
872 {
873     if (pFont == NULL) {
874         return NULL;
875     }
876     FX_BOOL bCJK = charset == FXFONT_CHINESEBIG5_CHARSET || charset == FXFONT_GB2312_CHARSET ||
877                    charset == FXFONT_HANGEUL_CHARSET || charset == FXFONT_SHIFTJIS_CHARSET;
878     CFX_ByteString basefont = pFont->GetFamilyName();
879     basefont.Replace(" ", "");
880     int flags = 0;
881     if (pFont->IsBold()) {
882         flags |= PDFFONT_FORCEBOLD;
883     }
884     if (pFont->IsItalic()) {
885         flags |= PDFFONT_ITALIC;
886     }
887     if (pFont->IsFixedWidth()) {
888         flags |= PDFFONT_FIXEDPITCH;
889     }
890     CPDF_Dictionary* pBaseDict = FX_NEW CPDF_Dictionary;
891     pBaseDict->SetAtName("Type", "Font");
892     IFX_FontEncoding* pEncoding = FXGE_CreateUnicodeEncoding(pFont);
893     CPDF_Dictionary* pFontDict = pBaseDict;
894     if (!bCJK) {
895         CPDF_Array* pWidths = FX_NEW CPDF_Array;
896         int charcode;
897         for (charcode = 32; charcode < 128; charcode ++) {
898             int glyph_index = pEncoding->GlyphFromCharCode(charcode);
899             int char_width = pFont->GetGlyphWidth(glyph_index);
900             pWidths->AddInteger(char_width);
901         }
902         if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_DEFAULT_CHARSET ||
903                 charset == FXFONT_SYMBOL_CHARSET) {
904             if (charset == FXFONT_SYMBOL_CHARSET) {
905                 flags |= PDFFONT_SYMBOLIC;
906             } else {
907                 flags |= PDFFONT_NONSYMBOLIC;
908             }
909             pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
910             for (charcode = 128; charcode <= 255; charcode ++) {
911                 int glyph_index = pEncoding->GlyphFromCharCode(charcode);
912                 int char_width = pFont->GetGlyphWidth(glyph_index);
913                 pWidths->AddInteger(char_width);
914             }
915         } else {
916             flags |= PDFFONT_NONSYMBOLIC;
917             int i;
918             for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++)
919                 if (g_FX_CharsetUnicodes[i].m_Charset == charset) {
920                     break;
921                 }
922             if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) {
923                 CPDF_Dictionary* pEncodingDict = FX_NEW CPDF_Dictionary;
924                 pEncodingDict->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding");
925                 CPDF_Array* pArray = FX_NEW CPDF_Array;
926                 pArray->AddInteger(128);
927                 const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes;
928                 for (int j = 0; j < 128; j ++) {
929                     CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
930                     if (name.IsEmpty()) {
931                         pArray->AddName(FX_BSTRC(".notdef"));
932                     } else {
933                         pArray->AddName(name);
934                     }
935                     int glyph_index = pEncoding->GlyphFromCharCode(pUnicodes[j]);
936                     int char_width = pFont->GetGlyphWidth(glyph_index);
937                     pWidths->AddInteger(char_width);
938                 }
939                 pEncodingDict->SetAt(FX_BSTRC("Differences"), pArray);
940                 AddIndirectObject(pEncodingDict);
941                 pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncodingDict);
942             }
943         }
944         if (pFont->IsBold() && pFont->IsItalic()) {
945             basefont += ",BoldItalic";
946         } else if (pFont->IsBold()) {
947             basefont += ",Bold";
948         } else if (pFont->IsItalic()) {
949             basefont += ",Italic";
950         }
951         pBaseDict->SetAtName("Subtype", "TrueType");
952         pBaseDict->SetAtName("BaseFont", basefont);
953         pBaseDict->SetAtNumber("FirstChar", 32);
954         pBaseDict->SetAtNumber("LastChar", 255);
955         pBaseDict->SetAt("Widths", pWidths);
956     } else {
957         flags |= PDFFONT_NONSYMBOLIC;
958         pFontDict = FX_NEW CPDF_Dictionary;
959         CFX_ByteString cmap;
960         CFX_ByteString ordering;
961         int supplement;
962         CPDF_Array* pWidthArray = FX_NEW CPDF_Array;
963         switch (charset) {
964             case FXFONT_CHINESEBIG5_CHARSET:
965                 cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H";
966                 ordering = "CNS1";
967                 supplement = 4;
968                 pWidthArray->AddInteger(1);
969                 _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7e, pWidthArray);
970                 break;
971             case FXFONT_GB2312_CHARSET:
972                 cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H";
973                 ordering = "GB1", supplement = 2;
974                 pWidthArray->AddInteger(7716);
975                 _InsertWidthArray1(pFont, pEncoding, 0x20, 0x20, pWidthArray);
976                 pWidthArray->AddInteger(814);
977                 _InsertWidthArray1(pFont, pEncoding, 0x21, 0x7e, pWidthArray);
978                 break;
979             case FXFONT_HANGEUL_CHARSET:
980                 cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H";
981                 ordering = "Korea1";
982                 supplement = 2;
983                 pWidthArray->AddInteger(1);
984                 _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7e, pWidthArray);
985                 break;
986             case FXFONT_SHIFTJIS_CHARSET:
987                 cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H";
988                 ordering = "Japan1";
989                 supplement = 5;
990                 pWidthArray->AddInteger(231);
991                 _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7d, pWidthArray);
992                 pWidthArray->AddInteger(326);
993                 _InsertWidthArray1(pFont, pEncoding, 0xa0, 0xa0, pWidthArray);
994                 pWidthArray->AddInteger(327);
995                 _InsertWidthArray1(pFont, pEncoding, 0xa1, 0xdf, pWidthArray);
996                 pWidthArray->AddInteger(631);
997                 _InsertWidthArray1(pFont, pEncoding, 0x7e, 0x7e, pWidthArray);
998                 break;
999         }
1000         pBaseDict->SetAtName("Subtype", "Type0");
1001         pBaseDict->SetAtName("BaseFont", basefont);
1002         pBaseDict->SetAtName("Encoding", cmap);
1003         pFontDict->SetAt("W", pWidthArray);
1004         pFontDict->SetAtName("Type", "Font");
1005         pFontDict->SetAtName("Subtype", "CIDFontType2");
1006         pFontDict->SetAtName("BaseFont", basefont);
1007         CPDF_Dictionary* pCIDSysInfo = FX_NEW CPDF_Dictionary;
1008         pCIDSysInfo->SetAtString("Registry", "Adobe");
1009         pCIDSysInfo->SetAtString("Ordering", ordering);
1010         pCIDSysInfo->SetAtInteger("Supplement", supplement);
1011         pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo);
1012         CPDF_Array* pArray = FX_NEW CPDF_Array;
1013         pBaseDict->SetAt("DescendantFonts", pArray);
1014         AddIndirectObject(pFontDict);
1015         pArray->AddReference(this, pFontDict);
1016     }
1017     AddIndirectObject(pBaseDict);
1018     CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary;
1019     pFontDesc->SetAtName("Type", "FontDescriptor");
1020     pFontDesc->SetAtName("FontName", basefont);
1021     pFontDesc->SetAtInteger("Flags", flags);
1022     pFontDesc->SetAtInteger("ItalicAngle", pFont->m_pSubstFont ? pFont->m_pSubstFont->m_ItalicAngle : 0);
1023     pFontDesc->SetAtInteger("Ascent", pFont->GetAscent());
1024     pFontDesc->SetAtInteger("Descent", pFont->GetDescent());
1025     FX_RECT bbox;
1026     pFont->GetBBox(bbox);
1027     CPDF_Array* pBBox = FX_NEW CPDF_Array;
1028     pBBox->AddInteger(bbox.left);
1029     pBBox->AddInteger(bbox.bottom);
1030     pBBox->AddInteger(bbox.right);
1031     pBBox->AddInteger(bbox.top);
1032     pFontDesc->SetAt("FontBBox", pBBox);
1033     FX_INT32 nStemV = 0;
1034     if (pFont->m_pSubstFont) {
1035         nStemV = pFont->m_pSubstFont->m_Weight / 5;
1036     } else {
1037         static const FX_CHAR stem_chars[] = {'i', 'I', '!', '1'};
1038         const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
1039         FX_DWORD glyph = pEncoding->GlyphFromCharCode(stem_chars[0]);
1040         nStemV = pFont->GetGlyphWidth(glyph);
1041         for (size_t i = 1; i < count; i++) {
1042             glyph = pEncoding->GlyphFromCharCode(stem_chars[i]);
1043             int width = pFont->GetGlyphWidth(glyph);
1044             if (width > 0 && width < nStemV) {
1045                 nStemV = width;
1046             }
1047         }
1048     }
1049     if (pEncoding) {
1050         delete pEncoding;
1051     }
1052     pFontDesc->SetAtInteger("StemV", nStemV);
1053     AddIndirectObject(pFontDesc);
1054     pFontDict->SetAtReference("FontDescriptor", this, pFontDesc);
1055     return LoadFont(pBaseDict);
1056 }
1057 static CPDF_Stream* GetFormStream(CPDF_Document* pDoc, CPDF_Object* pResObj)
1058 {
1059     if (pResObj->GetType() != PDFOBJ_REFERENCE) {
1060         return NULL;
1061     }
1062     CPDF_Reference* pRef = (CPDF_Reference*)pResObj;
1063     FX_BOOL bForm;
1064     if (pDoc->IsFormStream(pRef->GetRefObjNum(), bForm) && !bForm) {
1065         return NULL;
1066     }
1067     pResObj = pRef->GetDirect();
1068     if (pResObj->GetType() != PDFOBJ_STREAM) {
1069         return NULL;
1070     }
1071     CPDF_Stream* pXObject = (CPDF_Stream*)pResObj;
1072     if (pXObject->GetDict()->GetString(FX_BSTRC("Subtype")) != FX_BSTRC("Form")) {
1073         return NULL;
1074     }
1075     return pXObject;
1076 }
1077 static int InsertDeletePDFPage(CPDF_Document* pDoc, CPDF_Dictionary* pPages,
1078                                int nPagesToGo, CPDF_Dictionary* pPage, FX_BOOL bInsert, CFX_PtrArray& stackList)
1079 {
1080     CPDF_Array* pKidList = pPages->GetArray("Kids");
1081     if (!pKidList) {
1082         return -1;
1083     }
1084     int nKids = pKidList->GetCount();
1085     for (int i = 0; i < nKids; i ++) {
1086         CPDF_Dictionary* pKid = pKidList->GetDict(i);
1087         if (pKid->GetString("Type") == FX_BSTRC("Page")) {
1088             if (nPagesToGo == 0) {
1089                 if (bInsert) {
1090                     pKidList->InsertAt(i, CPDF_Reference::Create(pDoc, pPage->GetObjNum()));
1091                     pPage->SetAtReference("Parent", pDoc, pPages->GetObjNum());
1092                 } else {
1093                     pKidList->RemoveAt(i);
1094                 }
1095                 pPages->SetAtInteger("Count", pPages->GetInteger("Count") + (bInsert ? 1 : -1));
1096                 return 1;
1097             }
1098             nPagesToGo --;
1099         } else {
1100             int nPages = pKid->GetInteger("Count");
1101             if (nPagesToGo < nPages) {
1102                 int stackCount = stackList.GetSize();
1103                 for (int j = 0; j < stackCount; ++j) {
1104                     if (pKid == stackList[j]) {
1105                         return -1;
1106                     }
1107                 }
1108                 stackList.Add(pKid);
1109                 if (InsertDeletePDFPage(pDoc, pKid, nPagesToGo, pPage, bInsert, stackList) < 0) {
1110                     return -1;
1111                 }
1112                 stackList.RemoveAt(stackCount);
1113                 pPages->SetAtInteger("Count", pPages->GetInteger("Count") + (bInsert ? 1 : -1));
1114                 return 1;
1115             }
1116             nPagesToGo -= nPages;
1117         }
1118     }
1119     return 0;
1120 }
1121 static int InsertNewPage(CPDF_Document* pDoc, int iPage, CPDF_Dictionary* pPageDict, CFX_DWordArray &pageList)
1122 {
1123     CPDF_Dictionary* pRoot = pDoc->GetRoot();
1124     if (!pRoot) {
1125         return -1;
1126     }
1127     CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages"));
1128     if (!pPages) {
1129         return -1;
1130     }
1131     int nPages = pDoc->GetPageCount();
1132     if (iPage < 0 || iPage > nPages) {
1133         return -1;
1134     }
1135     if (iPage == nPages) {
1136         CPDF_Array* pPagesList = pPages->GetArray(FX_BSTRC("Kids"));
1137         if (!pPagesList) {
1138             pPagesList = FX_NEW CPDF_Array;
1139             pPages->SetAt(FX_BSTRC("Kids"), pPagesList);
1140         }
1141         pPagesList->Add(pPageDict, pDoc);
1142         pPages->SetAtInteger(FX_BSTRC("Count"), nPages + 1);
1143         pPageDict->SetAtReference(FX_BSTRC("Parent"), pDoc, pPages->GetObjNum());
1144     } else {
1145         CFX_PtrArray stack;
1146         stack.Add(pPages);
1147         if (InsertDeletePDFPage(pDoc, pPages, iPage, pPageDict, TRUE, stack) < 0) {
1148             return -1;
1149         }
1150     }
1151     pageList.InsertAt(iPage, pPageDict->GetObjNum());
1152     return iPage;
1153 }
1154 CPDF_Dictionary* CPDF_Document::CreateNewPage(int iPage)
1155 {
1156     CPDF_Dictionary* pDict = FX_NEW CPDF_Dictionary;
1157     pDict->SetAtName("Type", "Page");
1158     FX_DWORD dwObjNum = AddIndirectObject(pDict);
1159     if (InsertNewPage(this, iPage, pDict, m_PageList) < 0) {
1160         ReleaseIndirectObject(dwObjNum);
1161         return NULL;
1162     }
1163     return pDict;
1164 }
1165 int _PDF_GetStandardFontName(CFX_ByteString& name);
1166 CPDF_Font* CPDF_Document::AddStandardFont(FX_LPCSTR font, CPDF_FontEncoding* pEncoding)
1167 {
1168     CFX_ByteString name(font, -1);
1169     if (_PDF_GetStandardFontName(name) < 0) {
1170         return NULL;
1171     }
1172     return GetPageData()->GetStandardFont(name, pEncoding);
1173 }
1174 void CPDF_Document::DeletePage(int iPage)
1175 {
1176     CPDF_Dictionary* pRoot = GetRoot();
1177     if (pRoot == NULL) {
1178         return;
1179     }
1180     CPDF_Dictionary* pPages = pRoot->GetDict("Pages");
1181     if (pPages == NULL) {
1182         return;
1183     }
1184     int nPages = pPages->GetInteger("Count");
1185     if (iPage < 0 || iPage >= nPages) {
1186         return;
1187     }
1188     CFX_PtrArray stack;
1189     stack.Add(pPages);
1190     if (InsertDeletePDFPage(this, pPages, iPage, NULL, FALSE, stack) < 0) {
1191         return;
1192     }
1193     m_PageList.RemoveAt(iPage);
1194 }
1195 CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict, FX_BSTR name);
1196 void FPDFAPI_FlatPageAttr(CPDF_Dictionary* pPageDict, FX_BSTR name)
1197 {
1198     if (pPageDict->KeyExist(name)) {
1199         return;
1200     }
1201     CPDF_Object* pObj = FPDFAPI_GetPageAttr(pPageDict, name);
1202     if (pObj) {
1203         pPageDict->SetAt(name, pObj->Clone());
1204     }
1205 }