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