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