1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | 'use strict';
|
23 |
|
24 | var _cff_parser = require('../../core/cff_parser');
|
25 |
|
26 | var _fonts = require('../../core/fonts');
|
27 |
|
28 | var _stream = require('../../core/stream');
|
29 |
|
30 | describe('CFFParser', function () {
|
31 | function createWithNullProto(obj) {
|
32 | var result = Object.create(null);
|
33 | for (var i in obj) {
|
34 | result[i] = obj[i];
|
35 | }
|
36 | return result;
|
37 | }
|
38 | var privateDictStub = {
|
39 | getByName: function getByName(name) {
|
40 | return 0;
|
41 | }
|
42 | };
|
43 | var fontData, parser, cff;
|
44 | beforeAll(function (done) {
|
45 | var exampleFont = '0100040100010101134142434445462b' + '54696d65732d526f6d616e000101011f' + 'f81b00f81c02f81d03f819041c6f000d' + 'fb3cfb6efa7cfa1605e911b8f1120003' + '01010813183030312e30303754696d65' + '7320526f6d616e54696d657300000002' + '010102030e0e7d99f92a99fb7695f773' + '8b06f79a93fc7c8c077d99f85695f75e' + '9908fb6e8cf87393f7108b09a70adf0b' + 'f78e14';
|
46 | var fontArr = [];
|
47 | for (var i = 0, ii = exampleFont.length; i < ii; i += 2) {
|
48 | var hex = exampleFont.substr(i, 2);
|
49 | fontArr.push(parseInt(hex, 16));
|
50 | }
|
51 | fontData = new _stream.Stream(fontArr);
|
52 | done();
|
53 | });
|
54 | afterAll(function () {
|
55 | fontData = null;
|
56 | });
|
57 | beforeEach(function (done) {
|
58 | parser = new _cff_parser.CFFParser(fontData, {}, _fonts.SEAC_ANALYSIS_ENABLED);
|
59 | cff = parser.parse();
|
60 | done();
|
61 | });
|
62 | afterEach(function (done) {
|
63 | parser = cff = null;
|
64 | done();
|
65 | });
|
66 | it('parses header', function () {
|
67 | var header = cff.header;
|
68 | expect(header.major).toEqual(1);
|
69 | expect(header.minor).toEqual(0);
|
70 | expect(header.hdrSize).toEqual(4);
|
71 | expect(header.offSize).toEqual(1);
|
72 | });
|
73 | it('parses name index', function () {
|
74 | var names = cff.names;
|
75 | expect(names.length).toEqual(1);
|
76 | expect(names[0]).toEqual('ABCDEF+Times-Roman');
|
77 | });
|
78 | it('parses string index', function () {
|
79 | var strings = cff.strings;
|
80 | expect(strings.count).toEqual(3);
|
81 | expect(strings.get(0)).toEqual('.notdef');
|
82 | expect(strings.get(391)).toEqual('001.007');
|
83 | });
|
84 | it('parses top dict', function () {
|
85 | var topDict = cff.topDict;
|
86 | expect(topDict.getByName('version')).toEqual(391);
|
87 | expect(topDict.getByName('FullName')).toEqual(392);
|
88 | expect(topDict.getByName('FamilyName')).toEqual(393);
|
89 | expect(topDict.getByName('Weight')).toEqual(389);
|
90 | expect(topDict.getByName('UniqueID')).toEqual(28416);
|
91 | expect(topDict.getByName('FontBBox')).toEqual([-168, -218, 1000, 898]);
|
92 | expect(topDict.getByName('CharStrings')).toEqual(94);
|
93 | expect(topDict.getByName('Private')).toEqual([45, 102]);
|
94 | });
|
95 | it('refuses to add topDict key with invalid value (bug 1068432)', function () {
|
96 | var topDict = cff.topDict;
|
97 | var defaultValue = topDict.getByName('UnderlinePosition');
|
98 | topDict.setByKey(3075, [NaN]);
|
99 | expect(topDict.getByName('UnderlinePosition')).toEqual(defaultValue);
|
100 | });
|
101 | it('ignores reserved commands in parseDict, and refuses to add privateDict ' + 'keys with invalid values (bug 1308536)', function () {
|
102 | var bytes = new Uint8Array([64, 39, 31, 30, 252, 114, 137, 115, 79, 30, 197, 119, 2, 99, 127, 6]);
|
103 | parser.bytes = bytes;
|
104 | var topDict = cff.topDict;
|
105 | topDict.setByName('Private', [bytes.length, 0]);
|
106 | var parsePrivateDict = function parsePrivateDict() {
|
107 | parser.parsePrivateDict(topDict);
|
108 | };
|
109 | expect(parsePrivateDict).not.toThrow();
|
110 | var privateDict = topDict.privateDict;
|
111 | expect(privateDict.getByName('BlueValues')).toBeNull();
|
112 | });
|
113 | it('parses a CharString having cntrmask', function () {
|
114 | var bytes = new Uint8Array([0, 1, 1, 0, 38, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 1, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 3, 20, 22, 22, 14]);
|
115 | parser.bytes = bytes;
|
116 | var charStringsIndex = parser.parseIndex(0).obj;
|
117 | var charStrings = parser.parseCharStrings({
|
118 | charStrings: charStringsIndex,
|
119 | privateDict: privateDictStub
|
120 | }).charStrings;
|
121 | expect(charStrings.count).toEqual(1);
|
122 | expect(charStrings.get(0).length).toEqual(38);
|
123 | });
|
124 | it('parses a CharString endchar with 4 args w/seac enabled', function () {
|
125 | var parser = new _cff_parser.CFFParser(fontData, {}, true);
|
126 | parser.parse();
|
127 | var bytes = new Uint8Array([0, 1, 1, 0, 237, 247, 22, 247, 72, 204, 247, 86, 14]);
|
128 | parser.bytes = bytes;
|
129 | var charStringsIndex = parser.parseIndex(0).obj;
|
130 | var result = parser.parseCharStrings({
|
131 | charStrings: charStringsIndex,
|
132 | privateDict: privateDictStub
|
133 | });
|
134 | expect(result.charStrings.count).toEqual(1);
|
135 | expect(result.charStrings.get(0).length).toEqual(1);
|
136 | expect(result.seacs.length).toEqual(1);
|
137 | expect(result.seacs[0].length).toEqual(4);
|
138 | expect(result.seacs[0][0]).toEqual(130);
|
139 | expect(result.seacs[0][1]).toEqual(180);
|
140 | expect(result.seacs[0][2]).toEqual(65);
|
141 | expect(result.seacs[0][3]).toEqual(194);
|
142 | });
|
143 | it('parses a CharString endchar with 4 args w/seac disabled', function () {
|
144 | var parser = new _cff_parser.CFFParser(fontData, {}, false);
|
145 | parser.parse();
|
146 | var bytes = new Uint8Array([0, 1, 1, 0, 237, 247, 22, 247, 72, 204, 247, 86, 14]);
|
147 | parser.bytes = bytes;
|
148 | var charStringsIndex = parser.parseIndex(0).obj;
|
149 | var result = parser.parseCharStrings({
|
150 | charStrings: charStringsIndex,
|
151 | privateDict: privateDictStub
|
152 | });
|
153 | expect(result.charStrings.count).toEqual(1);
|
154 | expect(result.charStrings.get(0).length).toEqual(9);
|
155 | expect(result.seacs.length).toEqual(0);
|
156 | });
|
157 | it('parses a CharString endchar no args', function () {
|
158 | var bytes = new Uint8Array([0, 1, 1, 0, 14]);
|
159 | parser.bytes = bytes;
|
160 | var charStringsIndex = parser.parseIndex(0).obj;
|
161 | var result = parser.parseCharStrings({
|
162 | charStrings: charStringsIndex,
|
163 | privateDict: privateDictStub
|
164 | });
|
165 | expect(result.charStrings.count).toEqual(1);
|
166 | expect(result.charStrings.get(0)[0]).toEqual(14);
|
167 | expect(result.seacs.length).toEqual(0);
|
168 | });
|
169 | it('parses predefined charsets', function () {
|
170 | var charset = parser.parseCharsets(0, 0, null, true);
|
171 | expect(charset.predefined).toEqual(true);
|
172 | });
|
173 | it('parses charset format 0', function () {
|
174 | var bytes = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x02]);
|
175 | parser.bytes = bytes;
|
176 | var charset = parser.parseCharsets(3, 2, new _cff_parser.CFFStrings(), false);
|
177 | expect(charset.charset[1]).toEqual('exclam');
|
178 | charset = parser.parseCharsets(3, 2, new _cff_parser.CFFStrings(), true);
|
179 | expect(charset.charset[1]).toEqual(2);
|
180 | });
|
181 | it('parses charset format 1', function () {
|
182 | var bytes = new Uint8Array([0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x01]);
|
183 | parser.bytes = bytes;
|
184 | var charset = parser.parseCharsets(3, 2, new _cff_parser.CFFStrings(), false);
|
185 | expect(charset.charset).toEqual(['.notdef', 'quoteright', 'parenleft']);
|
186 | charset = parser.parseCharsets(3, 2, new _cff_parser.CFFStrings(), true);
|
187 | expect(charset.charset).toEqual(['.notdef', 8, 9]);
|
188 | });
|
189 | it('parses charset format 2', function () {
|
190 | var bytes = new Uint8Array([0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01]);
|
191 | parser.bytes = bytes;
|
192 | var charset = parser.parseCharsets(3, 2, new _cff_parser.CFFStrings(), false);
|
193 | expect(charset.charset).toEqual(['.notdef', 'quoteright', 'parenleft']);
|
194 | charset = parser.parseCharsets(3, 2, new _cff_parser.CFFStrings(), true);
|
195 | expect(charset.charset).toEqual(['.notdef', 8, 9]);
|
196 | });
|
197 | it('parses encoding format 0', function () {
|
198 | var bytes = new Uint8Array([0x00, 0x00, 0x00, 0x01, 0x08]);
|
199 | parser.bytes = bytes;
|
200 | var encoding = parser.parseEncoding(2, {}, new _cff_parser.CFFStrings(), null);
|
201 | expect(encoding.encoding).toEqual(createWithNullProto({ 0x8: 1 }));
|
202 | });
|
203 | it('parses encoding format 1', function () {
|
204 | var bytes = new Uint8Array([0x00, 0x00, 0x01, 0x01, 0x07, 0x01]);
|
205 | parser.bytes = bytes;
|
206 | var encoding = parser.parseEncoding(2, {}, new _cff_parser.CFFStrings(), null);
|
207 | expect(encoding.encoding).toEqual(createWithNullProto({
|
208 | 0x7: 0x01,
|
209 | 0x08: 0x02
|
210 | }));
|
211 | });
|
212 | it('parses fdselect format 0', function () {
|
213 | var bytes = new Uint8Array([0x00, 0x00, 0x01]);
|
214 | parser.bytes = bytes.slice();
|
215 | var fdSelect = parser.parseFDSelect(0, 2);
|
216 | expect(fdSelect.fdSelect).toEqual([0, 1]);
|
217 | expect(fdSelect.raw).toEqual(bytes);
|
218 | });
|
219 | it('parses fdselect format 3', function () {
|
220 | var bytes = new Uint8Array([0x03, 0x00, 0x02, 0x00, 0x00, 0x09, 0x00, 0x02, 0x0a, 0x00, 0x04]);
|
221 | parser.bytes = bytes.slice();
|
222 | var fdSelect = parser.parseFDSelect(0, 4);
|
223 | expect(fdSelect.fdSelect).toEqual([9, 9, 0xa, 0xa]);
|
224 | expect(fdSelect.raw).toEqual(bytes);
|
225 | });
|
226 | it('parses invalid fdselect format 3 (bug 1146106)', function () {
|
227 | var bytes = new Uint8Array([0x03, 0x00, 0x02, 0x00, 0x01, 0x09, 0x00, 0x02, 0x0a, 0x00, 0x04]);
|
228 | parser.bytes = bytes.slice();
|
229 | var fdSelect = parser.parseFDSelect(0, 4);
|
230 | expect(fdSelect.fdSelect).toEqual([9, 9, 0xa, 0xa]);
|
231 | bytes[3] = bytes[4] = 0x00;
|
232 | expect(fdSelect.raw).toEqual(bytes);
|
233 | });
|
234 | });
|
235 | describe('CFFCompiler', function () {
|
236 | function testParser(bytes) {
|
237 | bytes = new Uint8Array(bytes);
|
238 | return new _cff_parser.CFFParser({
|
239 | getBytes: function getBytes() {
|
240 | return bytes;
|
241 | }
|
242 | }, {}, _fonts.SEAC_ANALYSIS_ENABLED);
|
243 | }
|
244 | it('encodes integers', function () {
|
245 | var c = new _cff_parser.CFFCompiler();
|
246 | expect(c.encodeInteger(0)).toEqual([0x8b]);
|
247 | expect(c.encodeInteger(100)).toEqual([0xef]);
|
248 | expect(c.encodeInteger(-100)).toEqual([0x27]);
|
249 | expect(c.encodeInteger(1000)).toEqual([0xfa, 0x7c]);
|
250 | expect(c.encodeInteger(-1000)).toEqual([0xfe, 0x7c]);
|
251 | expect(c.encodeInteger(10000)).toEqual([0x1c, 0x27, 0x10]);
|
252 | expect(c.encodeInteger(-10000)).toEqual([0x1c, 0xd8, 0xf0]);
|
253 | expect(c.encodeInteger(100000)).toEqual([0x1d, 0x00, 0x01, 0x86, 0xa0]);
|
254 | expect(c.encodeInteger(-100000)).toEqual([0x1d, 0xff, 0xfe, 0x79, 0x60]);
|
255 | });
|
256 | it('encodes floats', function () {
|
257 | var c = new _cff_parser.CFFCompiler();
|
258 | expect(c.encodeFloat(-2.25)).toEqual([0x1e, 0xe2, 0xa2, 0x5f]);
|
259 | expect(c.encodeFloat(5e-11)).toEqual([0x1e, 0x5c, 0x11, 0xff]);
|
260 | });
|
261 | it('sanitizes name index', function () {
|
262 | var c = new _cff_parser.CFFCompiler();
|
263 | var nameIndexCompiled = c.compileNameIndex(['[a']);
|
264 | var parser = testParser(nameIndexCompiled);
|
265 | var nameIndex = parser.parseIndex(0);
|
266 | var names = parser.parseNameIndex(nameIndex.obj);
|
267 | expect(names).toEqual(['_a']);
|
268 | var longName = '';
|
269 | for (var i = 0; i < 129; i++) {
|
270 | longName += '_';
|
271 | }
|
272 | nameIndexCompiled = c.compileNameIndex([longName]);
|
273 | parser = testParser(nameIndexCompiled);
|
274 | nameIndex = parser.parseIndex(0);
|
275 | names = parser.parseNameIndex(nameIndex.obj);
|
276 | expect(names[0].length).toEqual(127);
|
277 | });
|
278 | }); |
\ | No newline at end of file |