fpdf_edit_doc.cpp revision ee451cb395940862dad63c85adfe8f2fd55e864c
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>
11CPDF_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}
21void 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}
36static 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};
54static 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};
72static 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};
90static 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};
108static 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};
126static 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};
144static 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};
162static 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};
180typedef struct {
181    FX_BYTE		m_Charset;
182    const FX_WCHAR*	m_pUnicodes;
183} FX_CharsetUnicodes;
184const 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_)
195static 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}
218CPDF_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}
229extern CFX_ByteString _FPDF_GetNameFromTT(FX_LPCBYTE name_table, FX_DWORD name);
230CFX_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}
242CPDF_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_)
432FX_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}
443struct FX_LANG2CS {
444    FX_DWORD    uLang;
445    int         uCharset;
446}*FX_LPLANG2CS;
447static 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};
515static 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}
532static 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}
541static 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}
552FX_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}
566void 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}
579static 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}
602CPDF_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
845static 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}
871CPDF_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}
1057static 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}
1077static 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}
1121static 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}
1154CPDF_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}
1165int _PDF_GetStandardFontName(CFX_ByteString& name);
1166CPDF_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}
1174void 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}
1195CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict, FX_BSTR name);
1196void 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}
1206