Chromium Code Reviews| 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; | |
| 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 if (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 |
| 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 } |
| 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 } | |
| 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 } | |
| 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); | |
|
Lei Zhang
2016/04/26 23:06:36
Yes, this is on lines 906 and 1121 as well. This f
| |
| 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 |