aboutsummaryrefslogtreecommitdiff
path: root/static/dist/js/pdf.worker.js
diff options
context:
space:
mode:
Diffstat (limited to 'static/dist/js/pdf.worker.js')
-rw-r--r--static/dist/js/pdf.worker.js43506
1 files changed, 43506 insertions, 0 deletions
diff --git a/static/dist/js/pdf.worker.js b/static/dist/js/pdf.worker.js
new file mode 100644
index 00000000..11a6cf9e
--- /dev/null
+++ b/static/dist/js/pdf.worker.js
@@ -0,0 +1,43506 @@
1/* Copyright 2012 Mozilla Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/* jshint globalstrict: false */
16/* umdutils ignore */
17
18(function (root, factory) {
19 'use strict';
20 if (typeof define === 'function' && define.amd) {
21define('pdfjs-dist/build/pdf.worker', ['exports'], factory);
22 } else if (typeof exports !== 'undefined') {
23 factory(exports);
24 } else {
25factory((root.pdfjsDistBuildPdfWorker = {}));
26 }
27}(this, function (exports) {
28 // Use strict in our context only - users might not want it
29 'use strict';
30
31var pdfjsVersion = '1.6.210';
32var pdfjsBuild = '4ce2356';
33
34 var pdfjsFilePath =
35 typeof document !== 'undefined' && document.currentScript ?
36 document.currentScript.src : null;
37
38 var pdfjsLibs = {};
39
40 (function pdfjsWrapper() {
41
42
43
44(function (root, factory) {
45 {
46 factory((root.pdfjsCoreArithmeticDecoder = {}));
47 }
48}(this, function (exports) {
49
50/* This class implements the QM Coder decoding as defined in
51 * JPEG 2000 Part I Final Committee Draft Version 1.0
52 * Annex C.3 Arithmetic decoding procedure
53 * available at http://www.jpeg.org/public/fcd15444-1.pdf
54 *
55 * The arithmetic decoder is used in conjunction with context models to decode
56 * JPEG2000 and JBIG2 streams.
57 */
58var ArithmeticDecoder = (function ArithmeticDecoderClosure() {
59 // Table C-2
60 var QeTable = [
61 {qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1},
62 {qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0},
63 {qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0},
64 {qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0},
65 {qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0},
66 {qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0},
67 {qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1},
68 {qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0},
69 {qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0},
70 {qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0},
71 {qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0},
72 {qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0},
73 {qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0},
74 {qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0},
75 {qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1},
76 {qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0},
77 {qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0},
78 {qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0},
79 {qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0},
80 {qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0},
81 {qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0},
82 {qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0},
83 {qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0},
84 {qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0},
85 {qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0},
86 {qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0},
87 {qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0},
88 {qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0},
89 {qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0},
90 {qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0},
91 {qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0},
92 {qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0},
93 {qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0},
94 {qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0},
95 {qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0},
96 {qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0},
97 {qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0},
98 {qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0},
99 {qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0},
100 {qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0},
101 {qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0},
102 {qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0},
103 {qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0},
104 {qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0},
105 {qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0},
106 {qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0},
107 {qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0}
108 ];
109
110 // C.3.5 Initialisation of the decoder (INITDEC)
111 function ArithmeticDecoder(data, start, end) {
112 this.data = data;
113 this.bp = start;
114 this.dataEnd = end;
115
116 this.chigh = data[start];
117 this.clow = 0;
118
119 this.byteIn();
120
121 this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F);
122 this.clow = (this.clow << 7) & 0xFFFF;
123 this.ct -= 7;
124 this.a = 0x8000;
125 }
126
127 ArithmeticDecoder.prototype = {
128 // C.3.4 Compressed data input (BYTEIN)
129 byteIn: function ArithmeticDecoder_byteIn() {
130 var data = this.data;
131 var bp = this.bp;
132 if (data[bp] === 0xFF) {
133 var b1 = data[bp + 1];
134 if (b1 > 0x8F) {
135 this.clow += 0xFF00;
136 this.ct = 8;
137 } else {
138 bp++;
139 this.clow += (data[bp] << 9);
140 this.ct = 7;
141 this.bp = bp;
142 }
143 } else {
144 bp++;
145 this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00;
146 this.ct = 8;
147 this.bp = bp;
148 }
149 if (this.clow > 0xFFFF) {
150 this.chigh += (this.clow >> 16);
151 this.clow &= 0xFFFF;
152 }
153 },
154 // C.3.2 Decoding a decision (DECODE)
155 readBit: function ArithmeticDecoder_readBit(contexts, pos) {
156 // contexts are packed into 1 byte:
157 // highest 7 bits carry cx.index, lowest bit carries cx.mps
158 var cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1;
159 var qeTableIcx = QeTable[cx_index];
160 var qeIcx = qeTableIcx.qe;
161 var d;
162 var a = this.a - qeIcx;
163
164 if (this.chigh < qeIcx) {
165 // exchangeLps
166 if (a < qeIcx) {
167 a = qeIcx;
168 d = cx_mps;
169 cx_index = qeTableIcx.nmps;
170 } else {
171 a = qeIcx;
172 d = 1 ^ cx_mps;
173 if (qeTableIcx.switchFlag === 1) {
174 cx_mps = d;
175 }
176 cx_index = qeTableIcx.nlps;
177 }
178 } else {
179 this.chigh -= qeIcx;
180 if ((a & 0x8000) !== 0) {
181 this.a = a;
182 return cx_mps;
183 }
184 // exchangeMps
185 if (a < qeIcx) {
186 d = 1 ^ cx_mps;
187 if (qeTableIcx.switchFlag === 1) {
188 cx_mps = d;
189 }
190 cx_index = qeTableIcx.nlps;
191 } else {
192 d = cx_mps;
193 cx_index = qeTableIcx.nmps;
194 }
195 }
196 // C.3.3 renormD;
197 do {
198 if (this.ct === 0) {
199 this.byteIn();
200 }
201
202 a <<= 1;
203 this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1);
204 this.clow = (this.clow << 1) & 0xFFFF;
205 this.ct--;
206 } while ((a & 0x8000) === 0);
207 this.a = a;
208
209 contexts[pos] = cx_index << 1 | cx_mps;
210 return d;
211 }
212 };
213
214 return ArithmeticDecoder;
215})();
216
217exports.ArithmeticDecoder = ArithmeticDecoder;
218}));
219
220
221(function (root, factory) {
222 {
223 factory((root.pdfjsCoreBidi = {}));
224 }
225}(this, function (exports) {
226
227 // Character types for symbols from 0000 to 00FF.
228 var baseTypes = [
229 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS',
230 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
231 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON',
232 'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN',
233 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON',
234 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
235 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON',
236 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
237 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
238 'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN',
239 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
240 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
241 'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON',
242 'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON',
243 'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
244 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
245 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
246 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
247 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
248 ];
249
250 // Character types for symbols from 0600 to 06FF
251 var arabicTypes = [
252 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
253 'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL',
254 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
255 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
256 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
257 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
258 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
259 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL',
260 'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN',
261 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL',
262 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
263 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
264 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
265 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
266 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
267 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
268 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
269 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
270 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
271 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM',
272 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
273 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
274 ];
275
276 function isOdd(i) {
277 return (i & 1) !== 0;
278 }
279
280 function isEven(i) {
281 return (i & 1) === 0;
282 }
283
284 function findUnequal(arr, start, value) {
285 for (var j = start, jj = arr.length; j < jj; ++j) {
286 if (arr[j] !== value) {
287 return j;
288 }
289 }
290 return j;
291 }
292
293 function setValues(arr, start, end, value) {
294 for (var j = start; j < end; ++j) {
295 arr[j] = value;
296 }
297 }
298
299 function reverseValues(arr, start, end) {
300 for (var i = start, j = end - 1; i < j; ++i, --j) {
301 var temp = arr[i];
302 arr[i] = arr[j];
303 arr[j] = temp;
304 }
305 }
306
307 function createBidiText(str, isLTR, vertical) {
308 return {
309 str: str,
310 dir: (vertical ? 'ttb' : (isLTR ? 'ltr' : 'rtl'))
311 };
312 }
313
314 // These are used in bidi(), which is called frequently. We re-use them on
315 // each call to avoid unnecessary allocations.
316 var chars = [];
317 var types = [];
318
319 function bidi(str, startLevel, vertical) {
320 var isLTR = true;
321 var strLength = str.length;
322 if (strLength === 0 || vertical) {
323 return createBidiText(str, isLTR, vertical);
324 }
325
326 // Get types and fill arrays
327 chars.length = strLength;
328 types.length = strLength;
329 var numBidi = 0;
330
331 var i, ii;
332 for (i = 0; i < strLength; ++i) {
333 chars[i] = str.charAt(i);
334
335 var charCode = str.charCodeAt(i);
336 var charType = 'L';
337 if (charCode <= 0x00ff) {
338 charType = baseTypes[charCode];
339 } else if (0x0590 <= charCode && charCode <= 0x05f4) {
340 charType = 'R';
341 } else if (0x0600 <= charCode && charCode <= 0x06ff) {
342 charType = arabicTypes[charCode & 0xff];
343 } else if (0x0700 <= charCode && charCode <= 0x08AC) {
344 charType = 'AL';
345 }
346 if (charType === 'R' || charType === 'AL' || charType === 'AN') {
347 numBidi++;
348 }
349 types[i] = charType;
350 }
351
352 // Detect the bidi method
353 // - If there are no rtl characters then no bidi needed
354 // - If less than 30% chars are rtl then string is primarily ltr
355 // - If more than 30% chars are rtl then string is primarily rtl
356 if (numBidi === 0) {
357 isLTR = true;
358 return createBidiText(str, isLTR);
359 }
360
361 if (startLevel === -1) {
362 if ((strLength / numBidi) < 0.3) {
363 isLTR = true;
364 startLevel = 0;
365 } else {
366 isLTR = false;
367 startLevel = 1;
368 }
369 }
370
371 var levels = [];
372 for (i = 0; i < strLength; ++i) {
373 levels[i] = startLevel;
374 }
375
376 /*
377 X1-X10: skip most of this, since we are NOT doing the embeddings.
378 */
379 var e = (isOdd(startLevel) ? 'R' : 'L');
380 var sor = e;
381 var eor = sor;
382
383 /*
384 W1. Examine each non-spacing mark (NSM) in the level run, and change the
385 type of the NSM to the type of the previous character. If the NSM is at the
386 start of the level run, it will get the type of sor.
387 */
388 var lastType = sor;
389 for (i = 0; i < strLength; ++i) {
390 if (types[i] === 'NSM') {
391 types[i] = lastType;
392 } else {
393 lastType = types[i];
394 }
395 }
396
397 /*
398 W2. Search backwards from each instance of a European number until the
399 first strong type (R, L, AL, or sor) is found. If an AL is found, change
400 the type of the European number to Arabic number.
401 */
402 lastType = sor;
403 var t;
404 for (i = 0; i < strLength; ++i) {
405 t = types[i];
406 if (t === 'EN') {
407 types[i] = (lastType === 'AL') ? 'AN' : 'EN';
408 } else if (t === 'R' || t === 'L' || t === 'AL') {
409 lastType = t;
410 }
411 }
412
413 /*
414 W3. Change all ALs to R.
415 */
416 for (i = 0; i < strLength; ++i) {
417 t = types[i];
418 if (t === 'AL') {
419 types[i] = 'R';
420 }
421 }
422
423 /*
424 W4. A single European separator between two European numbers changes to a
425 European number. A single common separator between two numbers of the same
426 type changes to that type:
427 */
428 for (i = 1; i < strLength - 1; ++i) {
429 if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') {
430 types[i] = 'EN';
431 }
432 if (types[i] === 'CS' &&
433 (types[i - 1] === 'EN' || types[i - 1] === 'AN') &&
434 types[i + 1] === types[i - 1]) {
435 types[i] = types[i - 1];
436 }
437 }
438
439 /*
440 W5. A sequence of European terminators adjacent to European numbers changes
441 to all European numbers:
442 */
443 for (i = 0; i < strLength; ++i) {
444 if (types[i] === 'EN') {
445 // do before
446 var j;
447 for (j = i - 1; j >= 0; --j) {
448 if (types[j] !== 'ET') {
449 break;
450 }
451 types[j] = 'EN';
452 }
453 // do after
454 for (j = i + 1; j < strLength; ++j) {
455 if (types[j] !== 'ET') {
456 break;
457 }
458 types[j] = 'EN';
459 }
460 }
461 }
462
463 /*
464 W6. Otherwise, separators and terminators change to Other Neutral:
465 */
466 for (i = 0; i < strLength; ++i) {
467 t = types[i];
468 if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') {
469 types[i] = 'ON';
470 }
471 }
472
473 /*
474 W7. Search backwards from each instance of a European number until the
475 first strong type (R, L, or sor) is found. If an L is found, then change
476 the type of the European number to L.
477 */
478 lastType = sor;
479 for (i = 0; i < strLength; ++i) {
480 t = types[i];
481 if (t === 'EN') {
482 types[i] = ((lastType === 'L') ? 'L' : 'EN');
483 } else if (t === 'R' || t === 'L') {
484 lastType = t;
485 }
486 }
487
488 /*
489 N1. A sequence of neutrals takes the direction of the surrounding strong
490 text if the text on both sides has the same direction. European and Arabic
491 numbers are treated as though they were R. Start-of-level-run (sor) and
492 end-of-level-run (eor) are used at level run boundaries.
493 */
494 for (i = 0; i < strLength; ++i) {
495 if (types[i] === 'ON') {
496 var end = findUnequal(types, i + 1, 'ON');
497 var before = sor;
498 if (i > 0) {
499 before = types[i - 1];
500 }
501
502 var after = eor;
503 if (end + 1 < strLength) {
504 after = types[end + 1];
505 }
506 if (before !== 'L') {
507 before = 'R';
508 }
509 if (after !== 'L') {
510 after = 'R';
511 }
512 if (before === after) {
513 setValues(types, i, end, before);
514 }
515 i = end - 1; // reset to end (-1 so next iteration is ok)
516 }
517 }
518
519 /*
520 N2. Any remaining neutrals take the embedding direction.
521 */
522 for (i = 0; i < strLength; ++i) {
523 if (types[i] === 'ON') {
524 types[i] = e;
525 }
526 }
527
528 /*
529 I1. For all characters with an even (left-to-right) embedding direction,
530 those of type R go up one level and those of type AN or EN go up two
531 levels.
532 I2. For all characters with an odd (right-to-left) embedding direction,
533 those of type L, EN or AN go up one level.
534 */
535 for (i = 0; i < strLength; ++i) {
536 t = types[i];
537 if (isEven(levels[i])) {
538 if (t === 'R') {
539 levels[i] += 1;
540 } else if (t === 'AN' || t === 'EN') {
541 levels[i] += 2;
542 }
543 } else { // isOdd
544 if (t === 'L' || t === 'AN' || t === 'EN') {
545 levels[i] += 1;
546 }
547 }
548 }
549
550 /*
551 L1. On each line, reset the embedding level of the following characters to
552 the paragraph embedding level:
553
554 segment separators,
555 paragraph separators,
556 any sequence of whitespace characters preceding a segment separator or
557 paragraph separator, and any sequence of white space characters at the end
558 of the line.
559 */
560
561 // don't bother as text is only single line
562
563 /*
564 L2. From the highest level found in the text to the lowest odd level on
565 each line, reverse any contiguous sequence of characters that are at that
566 level or higher.
567 */
568
569 // find highest level & lowest odd level
570 var highestLevel = -1;
571 var lowestOddLevel = 99;
572 var level;
573 for (i = 0, ii = levels.length; i < ii; ++i) {
574 level = levels[i];
575 if (highestLevel < level) {
576 highestLevel = level;
577 }
578 if (lowestOddLevel > level && isOdd(level)) {
579 lowestOddLevel = level;
580 }
581 }
582
583 // now reverse between those limits
584 for (level = highestLevel; level >= lowestOddLevel; --level) {
585 // find segments to reverse
586 var start = -1;
587 for (i = 0, ii = levels.length; i < ii; ++i) {
588 if (levels[i] < level) {
589 if (start >= 0) {
590 reverseValues(chars, start, i);
591 start = -1;
592 }
593 } else if (start < 0) {
594 start = i;
595 }
596 }
597 if (start >= 0) {
598 reverseValues(chars, start, levels.length);
599 }
600 }
601
602 /*
603 L3. Combining marks applied to a right-to-left base character will at this
604 point precede their base character. If the rendering engine expects them to
605 follow the base characters in the final display process, then the ordering
606 of the marks and the base character must be reversed.
607 */
608
609 // don't bother for now
610
611 /*
612 L4. A character that possesses the mirrored property as specified by
613 Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved
614 directionality of that character is R.
615 */
616
617 // don't mirror as characters are already mirrored in the pdf
618
619 // Finally, return string
620 for (i = 0, ii = chars.length; i < ii; ++i) {
621 var ch = chars[i];
622 if (ch === '<' || ch === '>') {
623 chars[i] = '';
624 }
625 }
626 return createBidiText(chars.join(''), isLTR);
627 }
628
629exports.bidi = bidi;
630}));
631
632
633(function (root, factory) {
634 {
635 factory((root.pdfjsCoreCharsets = {}));
636 }
637}(this, function (exports) {
638
639var ISOAdobeCharset = [
640 '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
641 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
642 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
643 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
644 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
645 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
646 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
647 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
648 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
649 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
650 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
651 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
652 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
653 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
654 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
655 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
656 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
657 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
658 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
659 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
660 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
661 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
662 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
663 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
664 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
665 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
666 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
667 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
668 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
669 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
670 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
671 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
672 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
673 'ugrave', 'yacute', 'ydieresis', 'zcaron'
674];
675
676var ExpertCharset = [
677 '.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
678 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
679 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
680 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
681 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
682 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
683 'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
684 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
685 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
686 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
687 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
688 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
689 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
690 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
691 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
692 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
693 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
694 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
695 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
696 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
697 'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
698 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
699 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
700 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
701 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
702 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
703 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
704 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
705 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
706 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall',
707 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
708 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
709 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
710 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
711 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
712 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
713 'Ydieresissmall'
714];
715
716var ExpertSubsetCharset = [
717 '.notdef', 'space', 'dollaroldstyle', 'dollarsuperior',
718 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
719 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
720 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
721 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
722 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
723 'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior',
724 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
725 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
726 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
727 'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted',
728 'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter',
729 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
730 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
731 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
732 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
733 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
734 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
735 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
736 'periodinferior', 'commainferior'
737];
738
739exports.ISOAdobeCharset = ISOAdobeCharset;
740exports.ExpertCharset = ExpertCharset;
741exports.ExpertSubsetCharset = ExpertSubsetCharset;
742}));
743
744
745(function (root, factory) {
746 {
747 factory((root.pdfjsCoreEncodings = {}));
748 }
749}(this, function (exports) {
750
751 var ExpertEncoding = [
752 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
753 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
754 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle',
755 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
756 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
757 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
758 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
759 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
760 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior',
761 'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior',
762 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
763 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior',
764 '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '',
765 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
766 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
767 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
768 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
769 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
770 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '',
771 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
772 '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
773 '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall',
774 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '',
775 'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall',
776 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
777 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
778 'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior',
779 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior',
780 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
781 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
782 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
783 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior',
784 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
785 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
786 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
787 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
788 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
789 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
790 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
791 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
792 'Ydieresissmall'];
793
794 var MacExpertEncoding = [
795 '', '', '', '', '', '', '', '', '', '', '', '', '', '',
796 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
797 'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle',
798 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
799 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
800 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle',
801 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle',
802 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle',
803 'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '',
804 'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter',
805 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
806 'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff',
807 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior',
808 'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall',
809 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
810 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
811 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
812 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
813 'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '',
814 'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall',
815 'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall',
816 'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall',
817 'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall',
818 'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall',
819 'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '',
820 'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior',
821 'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior',
822 'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior',
823 'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '',
824 'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior',
825 'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall',
826 'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '',
827 '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '',
828 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior',
829 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
830 'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior',
831 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior',
832 '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall',
833 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior',
834 'periodsuperior', 'Dotaccentsmall', 'Ringsmall'];
835
836 var MacRomanEncoding = [
837 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
838 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
839 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
840 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
841 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
842 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
843 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
844 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
845 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
846 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
847 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
848 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '',
849 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis',
850 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde',
851 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
852 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute',
853 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave',
854 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling',
855 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright',
856 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity',
857 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff',
858 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine',
859 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot',
860 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft',
861 'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE',
862 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft',
863 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
864 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl',
865 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand',
866 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
867 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple',
868 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex',
869 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
870 'ogonek', 'caron'];
871
872 var StandardEncoding = [
873 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
874 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
875 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
876 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
877 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
878 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
879 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
880 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
881 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
882 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f',
883 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
884 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
885 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
886 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown',
887 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
888 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
889 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
890 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
891 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
892 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
893 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla',
894 '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '',
895 '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '',
896 '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae',
897 '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'];
898
899 var WinAnsiEncoding = [
900 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
901 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
902 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
903 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
904 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
905 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
906 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
907 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
908 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
909 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
910 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
911 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
912 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase',
913 'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron',
914 'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft',
915 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash',
916 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet',
917 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling',
918 'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright',
919 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered',
920 'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute',
921 'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior',
922 'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters',
923 'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis',
924 'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
925 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve',
926 'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash',
927 'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn',
928 'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis',
929 'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis',
930 'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
931 'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
932 'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
933 'ydieresis'];
934
935 var SymbolSetEncoding = [
936 '', '', '', '', '', '', '', '', '', '', '', '', '', '',
937 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
938 'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
939 'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus',
940 'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
941 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
942 'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi',
943 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa',
944 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau',
945 'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft',
946 'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex',
947 'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota',
948 'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho',
949 'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta',
950 'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '',
951 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
952 '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal',
953 'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade',
954 'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree',
955 'plusminus', 'second', 'greaterequal', 'multiply', 'proportional',
956 'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence',
957 'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn',
958 'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply',
959 'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset',
960 'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element',
961 'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif',
962 'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot',
963 'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup',
964 'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans',
965 'copyrightsans', 'trademarksans', 'summation', 'parenlefttp',
966 'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex',
967 'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex',
968 '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt',
969 'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
970 'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
971 'bracerightbt'];
972
973 var ZapfDingbatsEncoding = [
974 '', '', '', '', '', '', '', '', '', '', '', '', '', '',
975 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
976 'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117',
977 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19',
978 'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7',
979 'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36',
980 'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46',
981 'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56',
982 'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66',
983 'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75',
984 'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97',
985 'a98', 'a99', 'a100', '', 'a89', 'a90', 'a93', 'a94', 'a91', 'a92', 'a205',
986 'a85', 'a206', 'a86', 'a87', 'a88', 'a95', 'a96', '', '', '', '', '', '',
987 '', '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103',
988 'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120',
989 'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129',
990 'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138',
991 'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147',
992 'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156',
993 'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165',
994 'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173',
995 'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180',
996 'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197', 'a185',
997 'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190', 'a191'];
998
999 function getEncoding(encodingName) {
1000 switch (encodingName) {
1001 case 'WinAnsiEncoding':
1002 return WinAnsiEncoding;
1003 case 'StandardEncoding':
1004 return StandardEncoding;
1005 case 'MacRomanEncoding':
1006 return MacRomanEncoding;
1007 case 'SymbolSetEncoding':
1008 return SymbolSetEncoding;
1009 case 'ZapfDingbatsEncoding':
1010 return ZapfDingbatsEncoding;
1011 case 'ExpertEncoding':
1012 return ExpertEncoding;
1013 case 'MacExpertEncoding':
1014 return MacExpertEncoding;
1015 default:
1016 return null;
1017 }
1018 }
1019
1020 exports.WinAnsiEncoding = WinAnsiEncoding;
1021 exports.StandardEncoding = StandardEncoding;
1022 exports.MacRomanEncoding = MacRomanEncoding;
1023 exports.SymbolSetEncoding = SymbolSetEncoding;
1024 exports.ZapfDingbatsEncoding = ZapfDingbatsEncoding;
1025 exports.ExpertEncoding = ExpertEncoding;
1026 exports.getEncoding = getEncoding;
1027}));
1028
1029
1030(function (root, factory) {
1031 {
1032 factory((root.pdfjsSharedUtil = {}));
1033 }
1034}(this, function (exports) {
1035
1036var globalScope = (typeof window !== 'undefined') ? window :
1037 (typeof global !== 'undefined') ? global :
1038 (typeof self !== 'undefined') ? self : this;
1039
1040var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
1041
1042var TextRenderingMode = {
1043 FILL: 0,
1044 STROKE: 1,
1045 FILL_STROKE: 2,
1046 INVISIBLE: 3,
1047 FILL_ADD_TO_PATH: 4,
1048 STROKE_ADD_TO_PATH: 5,
1049 FILL_STROKE_ADD_TO_PATH: 6,
1050 ADD_TO_PATH: 7,
1051 FILL_STROKE_MASK: 3,
1052 ADD_TO_PATH_FLAG: 4
1053};
1054
1055var ImageKind = {
1056 GRAYSCALE_1BPP: 1,
1057 RGB_24BPP: 2,
1058 RGBA_32BPP: 3
1059};
1060
1061var AnnotationType = {
1062 TEXT: 1,
1063 LINK: 2,
1064 FREETEXT: 3,
1065 LINE: 4,
1066 SQUARE: 5,
1067 CIRCLE: 6,
1068 POLYGON: 7,
1069 POLYLINE: 8,
1070 HIGHLIGHT: 9,
1071 UNDERLINE: 10,
1072 SQUIGGLY: 11,
1073 STRIKEOUT: 12,
1074 STAMP: 13,
1075 CARET: 14,
1076 INK: 15,
1077 POPUP: 16,
1078 FILEATTACHMENT: 17,
1079 SOUND: 18,
1080 MOVIE: 19,
1081 WIDGET: 20,
1082 SCREEN: 21,
1083 PRINTERMARK: 22,
1084 TRAPNET: 23,
1085 WATERMARK: 24,
1086 THREED: 25,
1087 REDACT: 26
1088};
1089
1090var AnnotationFlag = {
1091 INVISIBLE: 0x01,
1092 HIDDEN: 0x02,
1093 PRINT: 0x04,
1094 NOZOOM: 0x08,
1095 NOROTATE: 0x10,
1096 NOVIEW: 0x20,
1097 READONLY: 0x40,
1098 LOCKED: 0x80,
1099 TOGGLENOVIEW: 0x100,
1100 LOCKEDCONTENTS: 0x200
1101};
1102
1103var AnnotationFieldFlag = {
1104 READONLY: 0x0000001,
1105 REQUIRED: 0x0000002,
1106 NOEXPORT: 0x0000004,
1107 MULTILINE: 0x0001000,
1108 PASSWORD: 0x0002000,
1109 NOTOGGLETOOFF: 0x0004000,
1110 RADIO: 0x0008000,
1111 PUSHBUTTON: 0x0010000,
1112 COMBO: 0x0020000,
1113 EDIT: 0x0040000,
1114 SORT: 0x0080000,
1115 FILESELECT: 0x0100000,
1116 MULTISELECT: 0x0200000,
1117 DONOTSPELLCHECK: 0x0400000,
1118 DONOTSCROLL: 0x0800000,
1119 COMB: 0x1000000,
1120 RICHTEXT: 0x2000000,
1121 RADIOSINUNISON: 0x2000000,
1122 COMMITONSELCHANGE: 0x4000000,
1123};
1124
1125var AnnotationBorderStyleType = {
1126 SOLID: 1,
1127 DASHED: 2,
1128 BEVELED: 3,
1129 INSET: 4,
1130 UNDERLINE: 5
1131};
1132
1133var StreamType = {
1134 UNKNOWN: 0,
1135 FLATE: 1,
1136 LZW: 2,
1137 DCT: 3,
1138 JPX: 4,
1139 JBIG: 5,
1140 A85: 6,
1141 AHX: 7,
1142 CCF: 8,
1143 RL: 9
1144};
1145
1146var FontType = {
1147 UNKNOWN: 0,
1148 TYPE1: 1,
1149 TYPE1C: 2,
1150 CIDFONTTYPE0: 3,
1151 CIDFONTTYPE0C: 4,
1152 TRUETYPE: 5,
1153 CIDFONTTYPE2: 6,
1154 TYPE3: 7,
1155 OPENTYPE: 8,
1156 TYPE0: 9,
1157 MMTYPE1: 10
1158};
1159
1160var VERBOSITY_LEVELS = {
1161 errors: 0,
1162 warnings: 1,
1163 infos: 5
1164};
1165
1166// All the possible operations for an operator list.
1167var OPS = {
1168 // Intentionally start from 1 so it is easy to spot bad operators that will be
1169 // 0's.
1170 dependency: 1,
1171 setLineWidth: 2,
1172 setLineCap: 3,
1173 setLineJoin: 4,
1174 setMiterLimit: 5,
1175 setDash: 6,
1176 setRenderingIntent: 7,
1177 setFlatness: 8,
1178 setGState: 9,
1179 save: 10,
1180 restore: 11,
1181 transform: 12,
1182 moveTo: 13,
1183 lineTo: 14,
1184 curveTo: 15,
1185 curveTo2: 16,
1186 curveTo3: 17,
1187 closePath: 18,
1188 rectangle: 19,
1189 stroke: 20,
1190 closeStroke: 21,
1191 fill: 22,
1192 eoFill: 23,
1193 fillStroke: 24,
1194 eoFillStroke: 25,
1195 closeFillStroke: 26,
1196 closeEOFillStroke: 27,
1197 endPath: 28,
1198 clip: 29,
1199 eoClip: 30,
1200 beginText: 31,
1201 endText: 32,
1202 setCharSpacing: 33,
1203 setWordSpacing: 34,
1204 setHScale: 35,
1205 setLeading: 36,
1206 setFont: 37,
1207 setTextRenderingMode: 38,
1208 setTextRise: 39,
1209 moveText: 40,
1210 setLeadingMoveText: 41,
1211 setTextMatrix: 42,
1212 nextLine: 43,
1213 showText: 44,
1214 showSpacedText: 45,
1215 nextLineShowText: 46,
1216 nextLineSetSpacingShowText: 47,
1217 setCharWidth: 48,
1218 setCharWidthAndBounds: 49,
1219 setStrokeColorSpace: 50,
1220 setFillColorSpace: 51,
1221 setStrokeColor: 52,
1222 setStrokeColorN: 53,
1223 setFillColor: 54,
1224 setFillColorN: 55,
1225 setStrokeGray: 56,
1226 setFillGray: 57,
1227 setStrokeRGBColor: 58,
1228 setFillRGBColor: 59,
1229 setStrokeCMYKColor: 60,
1230 setFillCMYKColor: 61,
1231 shadingFill: 62,
1232 beginInlineImage: 63,
1233 beginImageData: 64,
1234 endInlineImage: 65,
1235 paintXObject: 66,
1236 markPoint: 67,
1237 markPointProps: 68,
1238 beginMarkedContent: 69,
1239 beginMarkedContentProps: 70,
1240 endMarkedContent: 71,
1241 beginCompat: 72,
1242 endCompat: 73,
1243 paintFormXObjectBegin: 74,
1244 paintFormXObjectEnd: 75,
1245 beginGroup: 76,
1246 endGroup: 77,
1247 beginAnnotations: 78,
1248 endAnnotations: 79,
1249 beginAnnotation: 80,
1250 endAnnotation: 81,
1251 paintJpegXObject: 82,
1252 paintImageMaskXObject: 83,
1253 paintImageMaskXObjectGroup: 84,
1254 paintImageXObject: 85,
1255 paintInlineImageXObject: 86,
1256 paintInlineImageXObjectGroup: 87,
1257 paintImageXObjectRepeat: 88,
1258 paintImageMaskXObjectRepeat: 89,
1259 paintSolidColorImageMask: 90,
1260 constructPath: 91
1261};
1262
1263var verbosity = VERBOSITY_LEVELS.warnings;
1264
1265function setVerbosityLevel(level) {
1266 verbosity = level;
1267}
1268
1269function getVerbosityLevel() {
1270 return verbosity;
1271}
1272
1273// A notice for devs. These are good for things that are helpful to devs, such
1274// as warning that Workers were disabled, which is important to devs but not
1275// end users.
1276function info(msg) {
1277 if (verbosity >= VERBOSITY_LEVELS.infos) {
1278 console.log('Info: ' + msg);
1279 }
1280}
1281
1282// Non-fatal warnings.
1283function warn(msg) {
1284 if (verbosity >= VERBOSITY_LEVELS.warnings) {
1285 console.log('Warning: ' + msg);
1286 }
1287}
1288
1289// Deprecated API function -- display regardless of the PDFJS.verbosity setting.
1290function deprecated(details) {
1291 console.log('Deprecated API usage: ' + details);
1292}
1293
1294// Fatal errors that should trigger the fallback UI and halt execution by
1295// throwing an exception.
1296function error(msg) {
1297 if (verbosity >= VERBOSITY_LEVELS.errors) {
1298 console.log('Error: ' + msg);
1299 console.log(backtrace());
1300 }
1301 throw new Error(msg);
1302}
1303
1304function backtrace() {
1305 try {
1306 throw new Error();
1307 } catch (e) {
1308 return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
1309 }
1310}
1311
1312function assert(cond, msg) {
1313 if (!cond) {
1314 error(msg);
1315 }
1316}
1317
1318var UNSUPPORTED_FEATURES = {
1319 unknown: 'unknown',
1320 forms: 'forms',
1321 javaScript: 'javaScript',
1322 smask: 'smask',
1323 shadingPattern: 'shadingPattern',
1324 font: 'font'
1325};
1326
1327// Checks if URLs have the same origin. For non-HTTP based URLs, returns false.
1328function isSameOrigin(baseUrl, otherUrl) {
1329 try {
1330 var base = new URL(baseUrl);
1331 if (!base.origin || base.origin === 'null') {
1332 return false; // non-HTTP url
1333 }
1334 } catch (e) {
1335 return false;
1336 }
1337
1338 var other = new URL(otherUrl, base);
1339 return base.origin === other.origin;
1340}
1341
1342// Validates if URL is safe and allowed, e.g. to avoid XSS.
1343function isValidUrl(url, allowRelative) {
1344 if (!url || typeof url !== 'string') {
1345 return false;
1346 }
1347 // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1)
1348 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
1349 var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url);
1350 if (!protocol) {
1351 return allowRelative;
1352 }
1353 protocol = protocol[0].toLowerCase();
1354 switch (protocol) {
1355 case 'http':
1356 case 'https':
1357 case 'ftp':
1358 case 'mailto':
1359 case 'tel':
1360 return true;
1361 default:
1362 return false;
1363 }
1364}
1365
1366function shadow(obj, prop, value) {
1367 Object.defineProperty(obj, prop, { value: value,
1368 enumerable: true,
1369 configurable: true,
1370 writable: false });
1371 return value;
1372}
1373
1374function getLookupTableFactory(initializer) {
1375 var lookup;
1376 return function () {
1377 if (initializer) {
1378 lookup = Object.create(null);
1379 initializer(lookup);
1380 initializer = null;
1381 }
1382 return lookup;
1383 };
1384}
1385
1386var PasswordResponses = {
1387 NEED_PASSWORD: 1,
1388 INCORRECT_PASSWORD: 2
1389};
1390
1391var PasswordException = (function PasswordExceptionClosure() {
1392 function PasswordException(msg, code) {
1393 this.name = 'PasswordException';
1394 this.message = msg;
1395 this.code = code;
1396 }
1397
1398 PasswordException.prototype = new Error();
1399 PasswordException.constructor = PasswordException;
1400
1401 return PasswordException;
1402})();
1403
1404var UnknownErrorException = (function UnknownErrorExceptionClosure() {
1405 function UnknownErrorException(msg, details) {
1406 this.name = 'UnknownErrorException';
1407 this.message = msg;
1408 this.details = details;
1409 }
1410
1411 UnknownErrorException.prototype = new Error();
1412 UnknownErrorException.constructor = UnknownErrorException;
1413
1414 return UnknownErrorException;
1415})();
1416
1417var InvalidPDFException = (function InvalidPDFExceptionClosure() {
1418 function InvalidPDFException(msg) {
1419 this.name = 'InvalidPDFException';
1420 this.message = msg;
1421 }
1422
1423 InvalidPDFException.prototype = new Error();
1424 InvalidPDFException.constructor = InvalidPDFException;
1425
1426 return InvalidPDFException;
1427})();
1428
1429var MissingPDFException = (function MissingPDFExceptionClosure() {
1430 function MissingPDFException(msg) {
1431 this.name = 'MissingPDFException';
1432 this.message = msg;
1433 }
1434
1435 MissingPDFException.prototype = new Error();
1436 MissingPDFException.constructor = MissingPDFException;
1437
1438 return MissingPDFException;
1439})();
1440
1441var UnexpectedResponseException =
1442 (function UnexpectedResponseExceptionClosure() {
1443 function UnexpectedResponseException(msg, status) {
1444 this.name = 'UnexpectedResponseException';
1445 this.message = msg;
1446 this.status = status;
1447 }
1448
1449 UnexpectedResponseException.prototype = new Error();
1450 UnexpectedResponseException.constructor = UnexpectedResponseException;
1451
1452 return UnexpectedResponseException;
1453})();
1454
1455var NotImplementedException = (function NotImplementedExceptionClosure() {
1456 function NotImplementedException(msg) {
1457 this.message = msg;
1458 }
1459
1460 NotImplementedException.prototype = new Error();
1461 NotImplementedException.prototype.name = 'NotImplementedException';
1462 NotImplementedException.constructor = NotImplementedException;
1463
1464 return NotImplementedException;
1465})();
1466
1467var MissingDataException = (function MissingDataExceptionClosure() {
1468 function MissingDataException(begin, end) {
1469 this.begin = begin;
1470 this.end = end;
1471 this.message = 'Missing data [' + begin + ', ' + end + ')';
1472 }
1473
1474 MissingDataException.prototype = new Error();
1475 MissingDataException.prototype.name = 'MissingDataException';
1476 MissingDataException.constructor = MissingDataException;
1477
1478 return MissingDataException;
1479})();
1480
1481var XRefParseException = (function XRefParseExceptionClosure() {
1482 function XRefParseException(msg) {
1483 this.message = msg;
1484 }
1485
1486 XRefParseException.prototype = new Error();
1487 XRefParseException.prototype.name = 'XRefParseException';
1488 XRefParseException.constructor = XRefParseException;
1489
1490 return XRefParseException;
1491})();
1492
1493var NullCharactersRegExp = /\x00/g;
1494
1495function removeNullCharacters(str) {
1496 if (typeof str !== 'string') {
1497 warn('The argument for removeNullCharacters must be a string.');
1498 return str;
1499 }
1500 return str.replace(NullCharactersRegExp, '');
1501}
1502
1503function bytesToString(bytes) {
1504 assert(bytes !== null && typeof bytes === 'object' &&
1505 bytes.length !== undefined, 'Invalid argument for bytesToString');
1506 var length = bytes.length;
1507 var MAX_ARGUMENT_COUNT = 8192;
1508 if (length < MAX_ARGUMENT_COUNT) {
1509 return String.fromCharCode.apply(null, bytes);
1510 }
1511 var strBuf = [];
1512 for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
1513 var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
1514 var chunk = bytes.subarray(i, chunkEnd);
1515 strBuf.push(String.fromCharCode.apply(null, chunk));
1516 }
1517 return strBuf.join('');
1518}
1519
1520function stringToBytes(str) {
1521 assert(typeof str === 'string', 'Invalid argument for stringToBytes');
1522 var length = str.length;
1523 var bytes = new Uint8Array(length);
1524 for (var i = 0; i < length; ++i) {
1525 bytes[i] = str.charCodeAt(i) & 0xFF;
1526 }
1527 return bytes;
1528}
1529
1530/**
1531 * Gets length of the array (Array, Uint8Array, or string) in bytes.
1532 * @param {Array|Uint8Array|string} arr
1533 * @returns {number}
1534 */
1535function arrayByteLength(arr) {
1536 if (arr.length !== undefined) {
1537 return arr.length;
1538 }
1539 assert(arr.byteLength !== undefined);
1540 return arr.byteLength;
1541}
1542
1543/**
1544 * Combines array items (arrays) into single Uint8Array object.
1545 * @param {Array} arr - the array of the arrays (Array, Uint8Array, or string).
1546 * @returns {Uint8Array}
1547 */
1548function arraysToBytes(arr) {
1549 // Shortcut: if first and only item is Uint8Array, return it.
1550 if (arr.length === 1 && (arr[0] instanceof Uint8Array)) {
1551 return arr[0];
1552 }
1553 var resultLength = 0;
1554 var i, ii = arr.length;
1555 var item, itemLength ;
1556 for (i = 0; i < ii; i++) {
1557 item = arr[i];
1558 itemLength = arrayByteLength(item);
1559 resultLength += itemLength;
1560 }
1561 var pos = 0;
1562 var data = new Uint8Array(resultLength);
1563 for (i = 0; i < ii; i++) {
1564 item = arr[i];
1565 if (!(item instanceof Uint8Array)) {
1566 if (typeof item === 'string') {
1567 item = stringToBytes(item);
1568 } else {
1569 item = new Uint8Array(item);
1570 }
1571 }
1572 itemLength = item.byteLength;
1573 data.set(item, pos);
1574 pos += itemLength;
1575 }
1576 return data;
1577}
1578
1579function string32(value) {
1580 return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff,
1581 (value >> 8) & 0xff, value & 0xff);
1582}
1583
1584function log2(x) {
1585 var n = 1, i = 0;
1586 while (x > n) {
1587 n <<= 1;
1588 i++;
1589 }
1590 return i;
1591}
1592
1593function readInt8(data, start) {
1594 return (data[start] << 24) >> 24;
1595}
1596
1597function readUint16(data, offset) {
1598 return (data[offset] << 8) | data[offset + 1];
1599}
1600
1601function readUint32(data, offset) {
1602 return ((data[offset] << 24) | (data[offset + 1] << 16) |
1603 (data[offset + 2] << 8) | data[offset + 3]) >>> 0;
1604}
1605
1606// Lazy test the endianness of the platform
1607// NOTE: This will be 'true' for simulated TypedArrays
1608function isLittleEndian() {
1609 var buffer8 = new Uint8Array(2);
1610 buffer8[0] = 1;
1611 var buffer16 = new Uint16Array(buffer8.buffer);
1612 return (buffer16[0] === 1);
1613}
1614
1615// Checks if it's possible to eval JS expressions.
1616function isEvalSupported() {
1617 try {
1618 /* jshint evil: true */
1619 new Function('');
1620 return true;
1621 } catch (e) {
1622 return false;
1623 }
1624}
1625
1626var Uint32ArrayView = (function Uint32ArrayViewClosure() {
1627
1628 function Uint32ArrayView(buffer, length) {
1629 this.buffer = buffer;
1630 this.byteLength = buffer.length;
1631 this.length = length === undefined ? (this.byteLength >> 2) : length;
1632 ensureUint32ArrayViewProps(this.length);
1633 }
1634 Uint32ArrayView.prototype = Object.create(null);
1635
1636 var uint32ArrayViewSetters = 0;
1637 function createUint32ArrayProp(index) {
1638 return {
1639 get: function () {
1640 var buffer = this.buffer, offset = index << 2;
1641 return (buffer[offset] | (buffer[offset + 1] << 8) |
1642 (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0;
1643 },
1644 set: function (value) {
1645 var buffer = this.buffer, offset = index << 2;
1646 buffer[offset] = value & 255;
1647 buffer[offset + 1] = (value >> 8) & 255;
1648 buffer[offset + 2] = (value >> 16) & 255;
1649 buffer[offset + 3] = (value >>> 24) & 255;
1650 }
1651 };
1652 }
1653
1654 function ensureUint32ArrayViewProps(length) {
1655 while (uint32ArrayViewSetters < length) {
1656 Object.defineProperty(Uint32ArrayView.prototype,
1657 uint32ArrayViewSetters,
1658 createUint32ArrayProp(uint32ArrayViewSetters));
1659 uint32ArrayViewSetters++;
1660 }
1661 }
1662
1663 return Uint32ArrayView;
1664})();
1665
1666exports.Uint32ArrayView = Uint32ArrayView;
1667
1668var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
1669
1670var Util = (function UtilClosure() {
1671 function Util() {}
1672
1673 var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
1674
1675 // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids
1676 // creating many intermediate strings.
1677 Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
1678 rgbBuf[1] = r;
1679 rgbBuf[3] = g;
1680 rgbBuf[5] = b;
1681 return rgbBuf.join('');
1682 };
1683
1684 // Concatenates two transformation matrices together and returns the result.
1685 Util.transform = function Util_transform(m1, m2) {
1686 return [
1687 m1[0] * m2[0] + m1[2] * m2[1],
1688 m1[1] * m2[0] + m1[3] * m2[1],
1689 m1[0] * m2[2] + m1[2] * m2[3],
1690 m1[1] * m2[2] + m1[3] * m2[3],
1691 m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
1692 m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
1693 ];
1694 };
1695
1696 // For 2d affine transforms
1697 Util.applyTransform = function Util_applyTransform(p, m) {
1698 var xt = p[0] * m[0] + p[1] * m[2] + m[4];
1699 var yt = p[0] * m[1] + p[1] * m[3] + m[5];
1700 return [xt, yt];
1701 };
1702
1703 Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
1704 var d = m[0] * m[3] - m[1] * m[2];
1705 var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
1706 var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
1707 return [xt, yt];
1708 };
1709
1710 // Applies the transform to the rectangle and finds the minimum axially
1711 // aligned bounding box.
1712 Util.getAxialAlignedBoundingBox =
1713 function Util_getAxialAlignedBoundingBox(r, m) {
1714
1715 var p1 = Util.applyTransform(r, m);
1716 var p2 = Util.applyTransform(r.slice(2, 4), m);
1717 var p3 = Util.applyTransform([r[0], r[3]], m);
1718 var p4 = Util.applyTransform([r[2], r[1]], m);
1719 return [
1720 Math.min(p1[0], p2[0], p3[0], p4[0]),
1721 Math.min(p1[1], p2[1], p3[1], p4[1]),
1722 Math.max(p1[0], p2[0], p3[0], p4[0]),
1723 Math.max(p1[1], p2[1], p3[1], p4[1])
1724 ];
1725 };
1726
1727 Util.inverseTransform = function Util_inverseTransform(m) {
1728 var d = m[0] * m[3] - m[1] * m[2];
1729 return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
1730 (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
1731 };
1732
1733 // Apply a generic 3d matrix M on a 3-vector v:
1734 // | a b c | | X |
1735 // | d e f | x | Y |
1736 // | g h i | | Z |
1737 // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
1738 // with v as [X,Y,Z]
1739 Util.apply3dTransform = function Util_apply3dTransform(m, v) {
1740 return [
1741 m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
1742 m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
1743 m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
1744 ];
1745 };
1746
1747 // This calculation uses Singular Value Decomposition.
1748 // The SVD can be represented with formula A = USV. We are interested in the
1749 // matrix S here because it represents the scale values.
1750 Util.singularValueDecompose2dScale =
1751 function Util_singularValueDecompose2dScale(m) {
1752
1753 var transpose = [m[0], m[2], m[1], m[3]];
1754
1755 // Multiply matrix m with its transpose.
1756 var a = m[0] * transpose[0] + m[1] * transpose[2];
1757 var b = m[0] * transpose[1] + m[1] * transpose[3];
1758 var c = m[2] * transpose[0] + m[3] * transpose[2];
1759 var d = m[2] * transpose[1] + m[3] * transpose[3];
1760
1761 // Solve the second degree polynomial to get roots.
1762 var first = (a + d) / 2;
1763 var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
1764 var sx = first + second || 1;
1765 var sy = first - second || 1;
1766
1767 // Scale values are the square roots of the eigenvalues.
1768 return [Math.sqrt(sx), Math.sqrt(sy)];
1769 };
1770
1771 // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
1772 // For coordinate systems whose origin lies in the bottom-left, this
1773 // means normalization to (BL,TR) ordering. For systems with origin in the
1774 // top-left, this means (TL,BR) ordering.
1775 Util.normalizeRect = function Util_normalizeRect(rect) {
1776 var r = rect.slice(0); // clone rect
1777 if (rect[0] > rect[2]) {
1778 r[0] = rect[2];
1779 r[2] = rect[0];
1780 }
1781 if (rect[1] > rect[3]) {
1782 r[1] = rect[3];
1783 r[3] = rect[1];
1784 }
1785 return r;
1786 };
1787
1788 // Returns a rectangle [x1, y1, x2, y2] corresponding to the
1789 // intersection of rect1 and rect2. If no intersection, returns 'false'
1790 // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
1791 Util.intersect = function Util_intersect(rect1, rect2) {
1792 function compare(a, b) {
1793 return a - b;
1794 }
1795
1796 // Order points along the axes
1797 var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
1798 orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
1799 result = [];
1800
1801 rect1 = Util.normalizeRect(rect1);
1802 rect2 = Util.normalizeRect(rect2);
1803
1804 // X: first and second points belong to different rectangles?
1805 if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
1806 (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
1807 // Intersection must be between second and third points
1808 result[0] = orderedX[1];
1809 result[2] = orderedX[2];
1810 } else {
1811 return false;
1812 }
1813
1814 // Y: first and second points belong to different rectangles?
1815 if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
1816 (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
1817 // Intersection must be between second and third points
1818 result[1] = orderedY[1];
1819 result[3] = orderedY[2];
1820 } else {
1821 return false;
1822 }
1823
1824 return result;
1825 };
1826
1827 Util.sign = function Util_sign(num) {
1828 return num < 0 ? -1 : 1;
1829 };
1830
1831 var ROMAN_NUMBER_MAP = [
1832 '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM',
1833 '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC',
1834 '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'
1835 ];
1836 /**
1837 * Converts positive integers to (upper case) Roman numerals.
1838 * @param {integer} number - The number that should be converted.
1839 * @param {boolean} lowerCase - Indicates if the result should be converted
1840 * to lower case letters. The default is false.
1841 * @return {string} The resulting Roman number.
1842 */
1843 Util.toRoman = function Util_toRoman(number, lowerCase) {
1844 assert(isInt(number) && number > 0,
1845 'The number should be a positive integer.');
1846 var pos, romanBuf = [];
1847 // Thousands
1848 while (number >= 1000) {
1849 number -= 1000;
1850 romanBuf.push('M');
1851 }
1852 // Hundreds
1853 pos = (number / 100) | 0;
1854 number %= 100;
1855 romanBuf.push(ROMAN_NUMBER_MAP[pos]);
1856 // Tens
1857 pos = (number / 10) | 0;
1858 number %= 10;
1859 romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
1860 // Ones
1861 romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
1862
1863 var romanStr = romanBuf.join('');
1864 return (lowerCase ? romanStr.toLowerCase() : romanStr);
1865 };
1866
1867 Util.appendToArray = function Util_appendToArray(arr1, arr2) {
1868 Array.prototype.push.apply(arr1, arr2);
1869 };
1870
1871 Util.prependToArray = function Util_prependToArray(arr1, arr2) {
1872 Array.prototype.unshift.apply(arr1, arr2);
1873 };
1874
1875 Util.extendObj = function extendObj(obj1, obj2) {
1876 for (var key in obj2) {
1877 obj1[key] = obj2[key];
1878 }
1879 };
1880
1881 Util.getInheritableProperty = function Util_getInheritableProperty(dict,
1882 name) {
1883 while (dict && !dict.has(name)) {
1884 dict = dict.get('Parent');
1885 }
1886 if (!dict) {
1887 return null;
1888 }
1889 return dict.get(name);
1890 };
1891
1892 Util.inherit = function Util_inherit(sub, base, prototype) {
1893 sub.prototype = Object.create(base.prototype);
1894 sub.prototype.constructor = sub;
1895 for (var prop in prototype) {
1896 sub.prototype[prop] = prototype[prop];
1897 }
1898 };
1899
1900 Util.loadScript = function Util_loadScript(src, callback) {
1901 var script = document.createElement('script');
1902 var loaded = false;
1903 script.setAttribute('src', src);
1904 if (callback) {
1905 script.onload = function() {
1906 if (!loaded) {
1907 callback();
1908 }
1909 loaded = true;
1910 };
1911 }
1912 document.getElementsByTagName('head')[0].appendChild(script);
1913 };
1914
1915 return Util;
1916})();
1917
1918/**
1919 * PDF page viewport created based on scale, rotation and offset.
1920 * @class
1921 * @alias PageViewport
1922 */
1923var PageViewport = (function PageViewportClosure() {
1924 /**
1925 * @constructor
1926 * @private
1927 * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates.
1928 * @param scale {number} scale of the viewport.
1929 * @param rotation {number} rotations of the viewport in degrees.
1930 * @param offsetX {number} offset X
1931 * @param offsetY {number} offset Y
1932 * @param dontFlip {boolean} if true, axis Y will not be flipped.
1933 */
1934 function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
1935 this.viewBox = viewBox;
1936 this.scale = scale;
1937 this.rotation = rotation;
1938 this.offsetX = offsetX;
1939 this.offsetY = offsetY;
1940
1941 // creating transform to convert pdf coordinate system to the normal
1942 // canvas like coordinates taking in account scale and rotation
1943 var centerX = (viewBox[2] + viewBox[0]) / 2;
1944 var centerY = (viewBox[3] + viewBox[1]) / 2;
1945 var rotateA, rotateB, rotateC, rotateD;
1946 rotation = rotation % 360;
1947 rotation = rotation < 0 ? rotation + 360 : rotation;
1948 switch (rotation) {
1949 case 180:
1950 rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
1951 break;
1952 case 90:
1953 rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
1954 break;
1955 case 270:
1956 rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
1957 break;
1958 //case 0:
1959 default:
1960 rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
1961 break;
1962 }
1963
1964 if (dontFlip) {
1965 rotateC = -rotateC; rotateD = -rotateD;
1966 }
1967
1968 var offsetCanvasX, offsetCanvasY;
1969 var width, height;
1970 if (rotateA === 0) {
1971 offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
1972 offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
1973 width = Math.abs(viewBox[3] - viewBox[1]) * scale;
1974 height = Math.abs(viewBox[2] - viewBox[0]) * scale;
1975 } else {
1976 offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
1977 offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
1978 width = Math.abs(viewBox[2] - viewBox[0]) * scale;
1979 height = Math.abs(viewBox[3] - viewBox[1]) * scale;
1980 }
1981 // creating transform for the following operations:
1982 // translate(-centerX, -centerY), rotate and flip vertically,
1983 // scale, and translate(offsetCanvasX, offsetCanvasY)
1984 this.transform = [
1985 rotateA * scale,
1986 rotateB * scale,
1987 rotateC * scale,
1988 rotateD * scale,
1989 offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
1990 offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
1991 ];
1992
1993 this.width = width;
1994 this.height = height;
1995 this.fontScale = scale;
1996 }
1997 PageViewport.prototype = /** @lends PageViewport.prototype */ {
1998 /**
1999 * Clones viewport with additional properties.
2000 * @param args {Object} (optional) If specified, may contain the 'scale' or
2001 * 'rotation' properties to override the corresponding properties in
2002 * the cloned viewport.
2003 * @returns {PageViewport} Cloned viewport.
2004 */
2005 clone: function PageViewPort_clone(args) {
2006 args = args || {};
2007 var scale = 'scale' in args ? args.scale : this.scale;
2008 var rotation = 'rotation' in args ? args.rotation : this.rotation;
2009 return new PageViewport(this.viewBox.slice(), scale, rotation,
2010 this.offsetX, this.offsetY, args.dontFlip);
2011 },
2012 /**
2013 * Converts PDF point to the viewport coordinates. For examples, useful for
2014 * converting PDF location into canvas pixel coordinates.
2015 * @param x {number} X coordinate.
2016 * @param y {number} Y coordinate.
2017 * @returns {Object} Object that contains 'x' and 'y' properties of the
2018 * point in the viewport coordinate space.
2019 * @see {@link convertToPdfPoint}
2020 * @see {@link convertToViewportRectangle}
2021 */
2022 convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
2023 return Util.applyTransform([x, y], this.transform);
2024 },
2025 /**
2026 * Converts PDF rectangle to the viewport coordinates.
2027 * @param rect {Array} xMin, yMin, xMax and yMax coordinates.
2028 * @returns {Array} Contains corresponding coordinates of the rectangle
2029 * in the viewport coordinate space.
2030 * @see {@link convertToViewportPoint}
2031 */
2032 convertToViewportRectangle:
2033 function PageViewport_convertToViewportRectangle(rect) {
2034 var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
2035 var br = Util.applyTransform([rect[2], rect[3]], this.transform);
2036 return [tl[0], tl[1], br[0], br[1]];
2037 },
2038 /**
2039 * Converts viewport coordinates to the PDF location. For examples, useful
2040 * for converting canvas pixel location into PDF one.
2041 * @param x {number} X coordinate.
2042 * @param y {number} Y coordinate.
2043 * @returns {Object} Object that contains 'x' and 'y' properties of the
2044 * point in the PDF coordinate space.
2045 * @see {@link convertToViewportPoint}
2046 */
2047 convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
2048 return Util.applyInverseTransform([x, y], this.transform);
2049 }
2050 };
2051 return PageViewport;
2052})();
2053
2054var PDFStringTranslateTable = [
2055 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2056 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
2057 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2058 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2059 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2060 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014,
2061 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C,
2062 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160,
2063 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC
2064];
2065
2066function stringToPDFString(str) {
2067 var i, n = str.length, strBuf = [];
2068 if (str[0] === '\xFE' && str[1] === '\xFF') {
2069 // UTF16BE BOM
2070 for (i = 2; i < n; i += 2) {
2071 strBuf.push(String.fromCharCode(
2072 (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)));
2073 }
2074 } else {
2075 for (i = 0; i < n; ++i) {
2076 var code = PDFStringTranslateTable[str.charCodeAt(i)];
2077 strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
2078 }
2079 }
2080 return strBuf.join('');
2081}
2082
2083function stringToUTF8String(str) {
2084 return decodeURIComponent(escape(str));
2085}
2086
2087function utf8StringToString(str) {
2088 return unescape(encodeURIComponent(str));
2089}
2090
2091function isEmptyObj(obj) {
2092 for (var key in obj) {
2093 return false;
2094 }
2095 return true;
2096}
2097
2098function isBool(v) {
2099 return typeof v === 'boolean';
2100}
2101
2102function isInt(v) {
2103 return typeof v === 'number' && ((v | 0) === v);
2104}
2105
2106function isNum(v) {
2107 return typeof v === 'number';
2108}
2109
2110function isString(v) {
2111 return typeof v === 'string';
2112}
2113
2114function isArray(v) {
2115 return v instanceof Array;
2116}
2117
2118function isArrayBuffer(v) {
2119 return typeof v === 'object' && v !== null && v.byteLength !== undefined;
2120}
2121
2122// Checks if ch is one of the following characters: SPACE, TAB, CR or LF.
2123function isSpace(ch) {
2124 return (ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A);
2125}
2126
2127/**
2128 * Promise Capability object.
2129 *
2130 * @typedef {Object} PromiseCapability
2131 * @property {Promise} promise - A promise object.
2132 * @property {function} resolve - Fulfills the promise.
2133 * @property {function} reject - Rejects the promise.
2134 */
2135
2136/**
2137 * Creates a promise capability object.
2138 * @alias createPromiseCapability
2139 *
2140 * @return {PromiseCapability} A capability object contains:
2141 * - a Promise, resolve and reject methods.
2142 */
2143function createPromiseCapability() {
2144 var capability = {};
2145 capability.promise = new Promise(function (resolve, reject) {
2146 capability.resolve = resolve;
2147 capability.reject = reject;
2148 });
2149 return capability;
2150}
2151
2152/**
2153 * Polyfill for Promises:
2154 * The following promise implementation tries to generally implement the
2155 * Promise/A+ spec. Some notable differences from other promise libraries are:
2156 * - There currently isn't a separate deferred and promise object.
2157 * - Unhandled rejections eventually show an error if they aren't handled.
2158 *
2159 * Based off of the work in:
2160 * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
2161 */
2162(function PromiseClosure() {
2163 if (globalScope.Promise) {
2164 // Promises existing in the DOM/Worker, checking presence of all/resolve
2165 if (typeof globalScope.Promise.all !== 'function') {
2166 globalScope.Promise.all = function (iterable) {
2167 var count = 0, results = [], resolve, reject;
2168 var promise = new globalScope.Promise(function (resolve_, reject_) {
2169 resolve = resolve_;
2170 reject = reject_;
2171 });
2172 iterable.forEach(function (p, i) {
2173 count++;
2174 p.then(function (result) {
2175 results[i] = result;
2176 count--;
2177 if (count === 0) {
2178 resolve(results);
2179 }
2180 }, reject);
2181 });
2182 if (count === 0) {
2183 resolve(results);
2184 }
2185 return promise;
2186 };
2187 }
2188 if (typeof globalScope.Promise.resolve !== 'function') {
2189 globalScope.Promise.resolve = function (value) {
2190 return new globalScope.Promise(function (resolve) { resolve(value); });
2191 };
2192 }
2193 if (typeof globalScope.Promise.reject !== 'function') {
2194 globalScope.Promise.reject = function (reason) {
2195 return new globalScope.Promise(function (resolve, reject) {
2196 reject(reason);
2197 });
2198 };
2199 }
2200 if (typeof globalScope.Promise.prototype.catch !== 'function') {
2201 globalScope.Promise.prototype.catch = function (onReject) {
2202 return globalScope.Promise.prototype.then(undefined, onReject);
2203 };
2204 }
2205 return;
2206 }
2207 var STATUS_PENDING = 0;
2208 var STATUS_RESOLVED = 1;
2209 var STATUS_REJECTED = 2;
2210
2211 // In an attempt to avoid silent exceptions, unhandled rejections are
2212 // tracked and if they aren't handled in a certain amount of time an
2213 // error is logged.
2214 var REJECTION_TIMEOUT = 500;
2215
2216 var HandlerManager = {
2217 handlers: [],
2218 running: false,
2219 unhandledRejections: [],
2220 pendingRejectionCheck: false,
2221
2222 scheduleHandlers: function scheduleHandlers(promise) {
2223 if (promise._status === STATUS_PENDING) {
2224 return;
2225 }
2226
2227 this.handlers = this.handlers.concat(promise._handlers);
2228 promise._handlers = [];
2229
2230 if (this.running) {
2231 return;
2232 }
2233 this.running = true;
2234
2235 setTimeout(this.runHandlers.bind(this), 0);
2236 },
2237
2238 runHandlers: function runHandlers() {
2239 var RUN_TIMEOUT = 1; // ms
2240 var timeoutAt = Date.now() + RUN_TIMEOUT;
2241 while (this.handlers.length > 0) {
2242 var handler = this.handlers.shift();
2243
2244 var nextStatus = handler.thisPromise._status;
2245 var nextValue = handler.thisPromise._value;
2246
2247 try {
2248 if (nextStatus === STATUS_RESOLVED) {
2249 if (typeof handler.onResolve === 'function') {
2250 nextValue = handler.onResolve(nextValue);
2251 }
2252 } else if (typeof handler.onReject === 'function') {
2253 nextValue = handler.onReject(nextValue);
2254 nextStatus = STATUS_RESOLVED;
2255
2256 if (handler.thisPromise._unhandledRejection) {
2257 this.removeUnhandeledRejection(handler.thisPromise);
2258 }
2259 }
2260 } catch (ex) {
2261 nextStatus = STATUS_REJECTED;
2262 nextValue = ex;
2263 }
2264
2265 handler.nextPromise._updateStatus(nextStatus, nextValue);
2266 if (Date.now() >= timeoutAt) {
2267 break;
2268 }
2269 }
2270
2271 if (this.handlers.length > 0) {
2272 setTimeout(this.runHandlers.bind(this), 0);
2273 return;
2274 }
2275
2276 this.running = false;
2277 },
2278
2279 addUnhandledRejection: function addUnhandledRejection(promise) {
2280 this.unhandledRejections.push({
2281 promise: promise,
2282 time: Date.now()
2283 });
2284 this.scheduleRejectionCheck();
2285 },
2286
2287 removeUnhandeledRejection: function removeUnhandeledRejection(promise) {
2288 promise._unhandledRejection = false;
2289 for (var i = 0; i < this.unhandledRejections.length; i++) {
2290 if (this.unhandledRejections[i].promise === promise) {
2291 this.unhandledRejections.splice(i);
2292 i--;
2293 }
2294 }
2295 },
2296
2297 scheduleRejectionCheck: function scheduleRejectionCheck() {
2298 if (this.pendingRejectionCheck) {
2299 return;
2300 }
2301 this.pendingRejectionCheck = true;
2302 setTimeout(function rejectionCheck() {
2303 this.pendingRejectionCheck = false;
2304 var now = Date.now();
2305 for (var i = 0; i < this.unhandledRejections.length; i++) {
2306 if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) {
2307 var unhandled = this.unhandledRejections[i].promise._value;
2308 var msg = 'Unhandled rejection: ' + unhandled;
2309 if (unhandled.stack) {
2310 msg += '\n' + unhandled.stack;
2311 }
2312 warn(msg);
2313 this.unhandledRejections.splice(i);
2314 i--;
2315 }
2316 }
2317 if (this.unhandledRejections.length) {
2318 this.scheduleRejectionCheck();
2319 }
2320 }.bind(this), REJECTION_TIMEOUT);
2321 }
2322 };
2323
2324 function Promise(resolver) {
2325 this._status = STATUS_PENDING;
2326 this._handlers = [];
2327 try {
2328 resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
2329 } catch (e) {
2330 this._reject(e);
2331 }
2332 }
2333 /**
2334 * Builds a promise that is resolved when all the passed in promises are
2335 * resolved.
2336 * @param {array} promises array of data and/or promises to wait for.
2337 * @return {Promise} New dependent promise.
2338 */
2339 Promise.all = function Promise_all(promises) {
2340 var resolveAll, rejectAll;
2341 var deferred = new Promise(function (resolve, reject) {
2342 resolveAll = resolve;
2343 rejectAll = reject;
2344 });
2345 var unresolved = promises.length;
2346 var results = [];
2347 if (unresolved === 0) {
2348 resolveAll(results);
2349 return deferred;
2350 }
2351 function reject(reason) {
2352 if (deferred._status === STATUS_REJECTED) {
2353 return;
2354 }
2355 results = [];
2356 rejectAll(reason);
2357 }
2358 for (var i = 0, ii = promises.length; i < ii; ++i) {
2359 var promise = promises[i];
2360 var resolve = (function(i) {
2361 return function(value) {
2362 if (deferred._status === STATUS_REJECTED) {
2363 return;
2364 }
2365 results[i] = value;
2366 unresolved--;
2367 if (unresolved === 0) {
2368 resolveAll(results);
2369 }
2370 };
2371 })(i);
2372 if (Promise.isPromise(promise)) {
2373 promise.then(resolve, reject);
2374 } else {
2375 resolve(promise);
2376 }
2377 }
2378 return deferred;
2379 };
2380
2381 /**
2382 * Checks if the value is likely a promise (has a 'then' function).
2383 * @return {boolean} true if value is thenable
2384 */
2385 Promise.isPromise = function Promise_isPromise(value) {
2386 return value && typeof value.then === 'function';
2387 };
2388
2389 /**
2390 * Creates resolved promise
2391 * @param value resolve value
2392 * @returns {Promise}
2393 */
2394 Promise.resolve = function Promise_resolve(value) {
2395 return new Promise(function (resolve) { resolve(value); });
2396 };
2397
2398 /**
2399 * Creates rejected promise
2400 * @param reason rejection value
2401 * @returns {Promise}
2402 */
2403 Promise.reject = function Promise_reject(reason) {
2404 return new Promise(function (resolve, reject) { reject(reason); });
2405 };
2406
2407 Promise.prototype = {
2408 _status: null,
2409 _value: null,
2410 _handlers: null,
2411 _unhandledRejection: null,
2412
2413 _updateStatus: function Promise__updateStatus(status, value) {
2414 if (this._status === STATUS_RESOLVED ||
2415 this._status === STATUS_REJECTED) {
2416 return;
2417 }
2418
2419 if (status === STATUS_RESOLVED &&
2420 Promise.isPromise(value)) {
2421 value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
2422 this._updateStatus.bind(this, STATUS_REJECTED));
2423 return;
2424 }
2425
2426 this._status = status;
2427 this._value = value;
2428
2429 if (status === STATUS_REJECTED && this._handlers.length === 0) {
2430 this._unhandledRejection = true;
2431 HandlerManager.addUnhandledRejection(this);
2432 }
2433
2434 HandlerManager.scheduleHandlers(this);
2435 },
2436
2437 _resolve: function Promise_resolve(value) {
2438 this._updateStatus(STATUS_RESOLVED, value);
2439 },
2440
2441 _reject: function Promise_reject(reason) {
2442 this._updateStatus(STATUS_REJECTED, reason);
2443 },
2444
2445 then: function Promise_then(onResolve, onReject) {
2446 var nextPromise = new Promise(function (resolve, reject) {
2447 this.resolve = resolve;
2448 this.reject = reject;
2449 });
2450 this._handlers.push({
2451 thisPromise: this,
2452 onResolve: onResolve,
2453 onReject: onReject,
2454 nextPromise: nextPromise
2455 });
2456 HandlerManager.scheduleHandlers(this);
2457 return nextPromise;
2458 },
2459
2460 catch: function Promise_catch(onReject) {
2461 return this.then(undefined, onReject);
2462 }
2463 };
2464
2465 globalScope.Promise = Promise;
2466})();
2467
2468(function WeakMapClosure() {
2469 if (globalScope.WeakMap) {
2470 return;
2471 }
2472
2473 var id = 0;
2474 function WeakMap() {
2475 this.id = '$weakmap' + (id++);
2476 }
2477 WeakMap.prototype = {
2478 has: function(obj) {
2479 return !!Object.getOwnPropertyDescriptor(obj, this.id);
2480 },
2481 get: function(obj, defaultValue) {
2482 return this.has(obj) ? obj[this.id] : defaultValue;
2483 },
2484 set: function(obj, value) {
2485 Object.defineProperty(obj, this.id, {
2486 value: value,
2487 enumerable: false,
2488 configurable: true
2489 });
2490 },
2491 delete: function(obj) {
2492 delete obj[this.id];
2493 }
2494 };
2495
2496 globalScope.WeakMap = WeakMap;
2497})();
2498
2499var StatTimer = (function StatTimerClosure() {
2500 function rpad(str, pad, length) {
2501 while (str.length < length) {
2502 str += pad;
2503 }
2504 return str;
2505 }
2506 function StatTimer() {
2507 this.started = Object.create(null);
2508 this.times = [];
2509 this.enabled = true;
2510 }
2511 StatTimer.prototype = {
2512 time: function StatTimer_time(name) {
2513 if (!this.enabled) {
2514 return;
2515 }
2516 if (name in this.started) {
2517 warn('Timer is already running for ' + name);
2518 }
2519 this.started[name] = Date.now();
2520 },
2521 timeEnd: function StatTimer_timeEnd(name) {
2522 if (!this.enabled) {
2523 return;
2524 }
2525 if (!(name in this.started)) {
2526 warn('Timer has not been started for ' + name);
2527 }
2528 this.times.push({
2529 'name': name,
2530 'start': this.started[name],
2531 'end': Date.now()
2532 });
2533 // Remove timer from started so it can be called again.
2534 delete this.started[name];
2535 },
2536 toString: function StatTimer_toString() {
2537 var i, ii;
2538 var times = this.times;
2539 var out = '';
2540 // Find the longest name for padding purposes.
2541 var longest = 0;
2542 for (i = 0, ii = times.length; i < ii; ++i) {
2543 var name = times[i]['name'];
2544 if (name.length > longest) {
2545 longest = name.length;
2546 }
2547 }
2548 for (i = 0, ii = times.length; i < ii; ++i) {
2549 var span = times[i];
2550 var duration = span.end - span.start;
2551 out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
2552 }
2553 return out;
2554 }
2555 };
2556 return StatTimer;
2557})();
2558
2559var createBlob = function createBlob(data, contentType) {
2560 if (typeof Blob !== 'undefined') {
2561 return new Blob([data], { type: contentType });
2562 }
2563 warn('The "Blob" constructor is not supported.');
2564};
2565
2566var createObjectURL = (function createObjectURLClosure() {
2567 // Blob/createObjectURL is not available, falling back to data schema.
2568 var digits =
2569 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
2570
2571 return function createObjectURL(data, contentType, forceDataSchema) {
2572 if (!forceDataSchema &&
2573 typeof URL !== 'undefined' && URL.createObjectURL) {
2574 var blob = createBlob(data, contentType);
2575 return URL.createObjectURL(blob);
2576 }
2577
2578 var buffer = 'data:' + contentType + ';base64,';
2579 for (var i = 0, ii = data.length; i < ii; i += 3) {
2580 var b1 = data[i] & 0xFF;
2581 var b2 = data[i + 1] & 0xFF;
2582 var b3 = data[i + 2] & 0xFF;
2583 var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
2584 var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
2585 var d4 = i + 2 < ii ? (b3 & 0x3F) : 64;
2586 buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
2587 }
2588 return buffer;
2589 };
2590})();
2591
2592function MessageHandler(sourceName, targetName, comObj) {
2593 this.sourceName = sourceName;
2594 this.targetName = targetName;
2595 this.comObj = comObj;
2596 this.callbackIndex = 1;
2597 this.postMessageTransfers = true;
2598 var callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
2599 var ah = this.actionHandler = Object.create(null);
2600
2601 this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
2602 var data = event.data;
2603 if (data.targetName !== this.sourceName) {
2604 return;
2605 }
2606 if (data.isReply) {
2607 var callbackId = data.callbackId;
2608 if (data.callbackId in callbacksCapabilities) {
2609 var callback = callbacksCapabilities[callbackId];
2610 delete callbacksCapabilities[callbackId];
2611 if ('error' in data) {
2612 callback.reject(data.error);
2613 } else {
2614 callback.resolve(data.data);
2615 }
2616 } else {
2617 error('Cannot resolve callback ' + callbackId);
2618 }
2619 } else if (data.action in ah) {
2620 var action = ah[data.action];
2621 if (data.callbackId) {
2622 var sourceName = this.sourceName;
2623 var targetName = data.sourceName;
2624 Promise.resolve().then(function () {
2625 return action[0].call(action[1], data.data);
2626 }).then(function (result) {
2627 comObj.postMessage({
2628 sourceName: sourceName,
2629 targetName: targetName,
2630 isReply: true,
2631 callbackId: data.callbackId,
2632 data: result
2633 });
2634 }, function (reason) {
2635 if (reason instanceof Error) {
2636 // Serialize error to avoid "DataCloneError"
2637 reason = reason + '';
2638 }
2639 comObj.postMessage({
2640 sourceName: sourceName,
2641 targetName: targetName,
2642 isReply: true,
2643 callbackId: data.callbackId,
2644 error: reason
2645 });
2646 });
2647 } else {
2648 action[0].call(action[1], data.data);
2649 }
2650 } else {
2651 error('Unknown action from worker: ' + data.action);
2652 }
2653 }.bind(this);
2654 comObj.addEventListener('message', this._onComObjOnMessage);
2655}
2656
2657MessageHandler.prototype = {
2658 on: function messageHandlerOn(actionName, handler, scope) {
2659 var ah = this.actionHandler;
2660 if (ah[actionName]) {
2661 error('There is already an actionName called "' + actionName + '"');
2662 }
2663 ah[actionName] = [handler, scope];
2664 },
2665 /**
2666 * Sends a message to the comObj to invoke the action with the supplied data.
2667 * @param {String} actionName Action to call.
2668 * @param {JSON} data JSON data to send.
2669 * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
2670 */
2671 send: function messageHandlerSend(actionName, data, transfers) {
2672 var message = {
2673 sourceName: this.sourceName,
2674 targetName: this.targetName,
2675 action: actionName,
2676 data: data
2677 };
2678 this.postMessage(message, transfers);
2679 },
2680 /**
2681 * Sends a message to the comObj to invoke the action with the supplied data.
2682 * Expects that other side will callback with the response.
2683 * @param {String} actionName Action to call.
2684 * @param {JSON} data JSON data to send.
2685 * @param {Array} [transfers] Optional list of transfers/ArrayBuffers.
2686 * @returns {Promise} Promise to be resolved with response data.
2687 */
2688 sendWithPromise:
2689 function messageHandlerSendWithPromise(actionName, data, transfers) {
2690 var callbackId = this.callbackIndex++;
2691 var message = {
2692 sourceName: this.sourceName,
2693 targetName: this.targetName,
2694 action: actionName,
2695 data: data,
2696 callbackId: callbackId
2697 };
2698 var capability = createPromiseCapability();
2699 this.callbacksCapabilities[callbackId] = capability;
2700 try {
2701 this.postMessage(message, transfers);
2702 } catch (e) {
2703 capability.reject(e);
2704 }
2705 return capability.promise;
2706 },
2707 /**
2708 * Sends raw message to the comObj.
2709 * @private
2710 * @param message {Object} Raw message.
2711 * @param transfers List of transfers/ArrayBuffers, or undefined.
2712 */
2713 postMessage: function (message, transfers) {
2714 if (transfers && this.postMessageTransfers) {
2715 this.comObj.postMessage(message, transfers);
2716 } else {
2717 this.comObj.postMessage(message);
2718 }
2719 },
2720
2721 destroy: function () {
2722 this.comObj.removeEventListener('message', this._onComObjOnMessage);
2723 }
2724};
2725
2726function loadJpegStream(id, imageUrl, objs) {
2727 var img = new Image();
2728 img.onload = (function loadJpegStream_onloadClosure() {
2729 objs.resolve(id, img);
2730 });
2731 img.onerror = (function loadJpegStream_onerrorClosure() {
2732 objs.resolve(id, null);
2733 warn('Error during JPEG image loading');
2734 });
2735 img.src = imageUrl;
2736}
2737
2738 // Polyfill from https://github.com/Polymer/URL
2739/* Any copyright is dedicated to the Public Domain.
2740 * http://creativecommons.org/publicdomain/zero/1.0/ */
2741(function checkURLConstructor(scope) {
2742 // feature detect for URL constructor
2743 var hasWorkingUrl = false;
2744 try {
2745 if (typeof URL === 'function' &&
2746 typeof URL.prototype === 'object' &&
2747 ('origin' in URL.prototype)) {
2748 var u = new URL('b', 'http://a');
2749 u.pathname = 'c%20d';
2750 hasWorkingUrl = u.href === 'http://a/c%20d';
2751 }
2752 } catch(e) { }
2753
2754 if (hasWorkingUrl) {
2755 return;
2756 }
2757
2758 var relative = Object.create(null);
2759 relative['ftp'] = 21;
2760 relative['file'] = 0;
2761 relative['gopher'] = 70;
2762 relative['http'] = 80;
2763 relative['https'] = 443;
2764 relative['ws'] = 80;
2765 relative['wss'] = 443;
2766
2767 var relativePathDotMapping = Object.create(null);
2768 relativePathDotMapping['%2e'] = '.';
2769 relativePathDotMapping['.%2e'] = '..';
2770 relativePathDotMapping['%2e.'] = '..';
2771 relativePathDotMapping['%2e%2e'] = '..';
2772
2773 function isRelativeScheme(scheme) {
2774 return relative[scheme] !== undefined;
2775 }
2776
2777 function invalid() {
2778 clear.call(this);
2779 this._isInvalid = true;
2780 }
2781
2782 function IDNAToASCII(h) {
2783 if ('' === h) {
2784 invalid.call(this);
2785 }
2786 // XXX
2787 return h.toLowerCase();
2788 }
2789
2790 function percentEscape(c) {
2791 var unicode = c.charCodeAt(0);
2792 if (unicode > 0x20 &&
2793 unicode < 0x7F &&
2794 // " # < > ? `
2795 [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) === -1
2796 ) {
2797 return c;
2798 }
2799 return encodeURIComponent(c);
2800 }
2801
2802 function percentEscapeQuery(c) {
2803 // XXX This actually needs to encode c using encoding and then
2804 // convert the bytes one-by-one.
2805
2806 var unicode = c.charCodeAt(0);
2807 if (unicode > 0x20 &&
2808 unicode < 0x7F &&
2809 // " # < > ` (do not escape '?')
2810 [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) === -1
2811 ) {
2812 return c;
2813 }
2814 return encodeURIComponent(c);
2815 }
2816
2817 var EOF, ALPHA = /[a-zA-Z]/,
2818 ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
2819
2820 function parse(input, stateOverride, base) {
2821 function err(message) {
2822 errors.push(message);
2823 }
2824
2825 var state = stateOverride || 'scheme start',
2826 cursor = 0,
2827 buffer = '',
2828 seenAt = false,
2829 seenBracket = false,
2830 errors = [];
2831
2832 loop: while ((input[cursor - 1] !== EOF || cursor === 0) &&
2833 !this._isInvalid) {
2834 var c = input[cursor];
2835 switch (state) {
2836 case 'scheme start':
2837 if (c && ALPHA.test(c)) {
2838 buffer += c.toLowerCase(); // ASCII-safe
2839 state = 'scheme';
2840 } else if (!stateOverride) {
2841 buffer = '';
2842 state = 'no scheme';
2843 continue;
2844 } else {
2845 err('Invalid scheme.');
2846 break loop;
2847 }
2848 break;
2849
2850 case 'scheme':
2851 if (c && ALPHANUMERIC.test(c)) {
2852 buffer += c.toLowerCase(); // ASCII-safe
2853 } else if (':' === c) {
2854 this._scheme = buffer;
2855 buffer = '';
2856 if (stateOverride) {
2857 break loop;
2858 }
2859 if (isRelativeScheme(this._scheme)) {
2860 this._isRelative = true;
2861 }
2862 if ('file' === this._scheme) {
2863 state = 'relative';
2864 } else if (this._isRelative && base &&
2865 base._scheme === this._scheme) {
2866 state = 'relative or authority';
2867 } else if (this._isRelative) {
2868 state = 'authority first slash';
2869 } else {
2870 state = 'scheme data';
2871 }
2872 } else if (!stateOverride) {
2873 buffer = '';
2874 cursor = 0;
2875 state = 'no scheme';
2876 continue;
2877 } else if (EOF === c) {
2878 break loop;
2879 } else {
2880 err('Code point not allowed in scheme: ' + c);
2881 break loop;
2882 }
2883 break;
2884
2885 case 'scheme data':
2886 if ('?' === c) {
2887 this._query = '?';
2888 state = 'query';
2889 } else if ('#' === c) {
2890 this._fragment = '#';
2891 state = 'fragment';
2892 } else {
2893 // XXX error handling
2894 if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
2895 this._schemeData += percentEscape(c);
2896 }
2897 }
2898 break;
2899
2900 case 'no scheme':
2901 if (!base || !(isRelativeScheme(base._scheme))) {
2902 err('Missing scheme.');
2903 invalid.call(this);
2904 } else {
2905 state = 'relative';
2906 continue;
2907 }
2908 break;
2909
2910 case 'relative or authority':
2911 if ('/' === c && '/' === input[cursor+1]) {
2912 state = 'authority ignore slashes';
2913 } else {
2914 err('Expected /, got: ' + c);
2915 state = 'relative';
2916 continue;
2917 }
2918 break;
2919
2920 case 'relative':
2921 this._isRelative = true;
2922 if ('file' !== this._scheme) {
2923 this._scheme = base._scheme;
2924 }
2925 if (EOF === c) {
2926 this._host = base._host;
2927 this._port = base._port;
2928 this._path = base._path.slice();
2929 this._query = base._query;
2930 this._username = base._username;
2931 this._password = base._password;
2932 break loop;
2933 } else if ('/' === c || '\\' === c) {
2934 if ('\\' === c) {
2935 err('\\ is an invalid code point.');
2936 }
2937 state = 'relative slash';
2938 } else if ('?' === c) {
2939 this._host = base._host;
2940 this._port = base._port;
2941 this._path = base._path.slice();
2942 this._query = '?';
2943 this._username = base._username;
2944 this._password = base._password;
2945 state = 'query';
2946 } else if ('#' === c) {
2947 this._host = base._host;
2948 this._port = base._port;
2949 this._path = base._path.slice();
2950 this._query = base._query;
2951 this._fragment = '#';
2952 this._username = base._username;
2953 this._password = base._password;
2954 state = 'fragment';
2955 } else {
2956 var nextC = input[cursor+1];
2957 var nextNextC = input[cursor+2];
2958 if ('file' !== this._scheme || !ALPHA.test(c) ||
2959 (nextC !== ':' && nextC !== '|') ||
2960 (EOF !== nextNextC && '/' !== nextNextC && '\\' !== nextNextC &&
2961 '?' !== nextNextC && '#' !== nextNextC)) {
2962 this._host = base._host;
2963 this._port = base._port;
2964 this._username = base._username;
2965 this._password = base._password;
2966 this._path = base._path.slice();
2967 this._path.pop();
2968 }
2969 state = 'relative path';
2970 continue;
2971 }
2972 break;
2973
2974 case 'relative slash':
2975 if ('/' === c || '\\' === c) {
2976 if ('\\' === c) {
2977 err('\\ is an invalid code point.');
2978 }
2979 if ('file' === this._scheme) {
2980 state = 'file host';
2981 } else {
2982 state = 'authority ignore slashes';
2983 }
2984 } else {
2985 if ('file' !== this._scheme) {
2986 this._host = base._host;
2987 this._port = base._port;
2988 this._username = base._username;
2989 this._password = base._password;
2990 }
2991 state = 'relative path';
2992 continue;
2993 }
2994 break;
2995
2996 case 'authority first slash':
2997 if ('/' === c) {
2998 state = 'authority second slash';
2999 } else {
3000 err('Expected \'/\', got: ' + c);
3001 state = 'authority ignore slashes';
3002 continue;
3003 }
3004 break;
3005
3006 case 'authority second slash':
3007 state = 'authority ignore slashes';
3008 if ('/' !== c) {
3009 err('Expected \'/\', got: ' + c);
3010 continue;
3011 }
3012 break;
3013
3014 case 'authority ignore slashes':
3015 if ('/' !== c && '\\' !== c) {
3016 state = 'authority';
3017 continue;
3018 } else {
3019 err('Expected authority, got: ' + c);
3020 }
3021 break;
3022
3023 case 'authority':
3024 if ('@' === c) {
3025 if (seenAt) {
3026 err('@ already seen.');
3027 buffer += '%40';
3028 }
3029 seenAt = true;
3030 for (var i = 0; i < buffer.length; i++) {
3031 var cp = buffer[i];
3032 if ('\t' === cp || '\n' === cp || '\r' === cp) {
3033 err('Invalid whitespace in authority.');
3034 continue;
3035 }
3036 // XXX check URL code points
3037 if (':' === cp && null === this._password) {
3038 this._password = '';
3039 continue;
3040 }
3041 var tempC = percentEscape(cp);
3042 if (null !== this._password) {
3043 this._password += tempC;
3044 } else {
3045 this._username += tempC;
3046 }
3047 }
3048 buffer = '';
3049 } else if (EOF === c || '/' === c || '\\' === c ||
3050 '?' === c || '#' === c) {
3051 cursor -= buffer.length;
3052 buffer = '';
3053 state = 'host';
3054 continue;
3055 } else {
3056 buffer += c;
3057 }
3058 break;
3059
3060 case 'file host':
3061 if (EOF === c || '/' === c || '\\' === c || '?' === c || '#' === c) {
3062 if (buffer.length === 2 && ALPHA.test(buffer[0]) &&
3063 (buffer[1] === ':' || buffer[1] === '|')) {
3064 state = 'relative path';
3065 } else if (buffer.length === 0) {
3066 state = 'relative path start';
3067 } else {
3068 this._host = IDNAToASCII.call(this, buffer);
3069 buffer = '';
3070 state = 'relative path start';
3071 }
3072 continue;
3073 } else if ('\t' === c || '\n' === c || '\r' === c) {
3074 err('Invalid whitespace in file host.');
3075 } else {
3076 buffer += c;
3077 }
3078 break;
3079
3080 case 'host':
3081 case 'hostname':
3082 if (':' === c && !seenBracket) {
3083 // XXX host parsing
3084 this._host = IDNAToASCII.call(this, buffer);
3085 buffer = '';
3086 state = 'port';
3087 if ('hostname' === stateOverride) {
3088 break loop;
3089 }
3090 } else if (EOF === c || '/' === c ||
3091 '\\' === c || '?' === c || '#' === c) {
3092 this._host = IDNAToASCII.call(this, buffer);
3093 buffer = '';
3094 state = 'relative path start';
3095 if (stateOverride) {
3096 break loop;
3097 }
3098 continue;
3099 } else if ('\t' !== c && '\n' !== c && '\r' !== c) {
3100 if ('[' === c) {
3101 seenBracket = true;
3102 } else if (']' === c) {
3103 seenBracket = false;
3104 }
3105 buffer += c;
3106 } else {
3107 err('Invalid code point in host/hostname: ' + c);
3108 }
3109 break;
3110
3111 case 'port':
3112 if (/[0-9]/.test(c)) {
3113 buffer += c;
3114 } else if (EOF === c || '/' === c || '\\' === c ||
3115 '?' === c || '#' === c || stateOverride) {
3116 if ('' !== buffer) {
3117 var temp = parseInt(buffer, 10);
3118 if (temp !== relative[this._scheme]) {
3119 this._port = temp + '';
3120 }
3121 buffer = '';
3122 }
3123 if (stateOverride) {
3124 break loop;
3125 }
3126 state = 'relative path start';
3127 continue;
3128 } else if ('\t' === c || '\n' === c || '\r' === c) {
3129 err('Invalid code point in port: ' + c);
3130 } else {
3131 invalid.call(this);
3132 }
3133 break;
3134
3135 case 'relative path start':
3136 if ('\\' === c) {
3137 err('\'\\\' not allowed in path.');
3138 }
3139 state = 'relative path';
3140 if ('/' !== c && '\\' !== c) {
3141 continue;
3142 }
3143 break;
3144
3145 case 'relative path':
3146 if (EOF === c || '/' === c || '\\' === c ||
3147 (!stateOverride && ('?' === c || '#' === c))) {
3148 if ('\\' === c) {
3149 err('\\ not allowed in relative path.');
3150 }
3151 var tmp;
3152 if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
3153 buffer = tmp;
3154 }
3155 if ('..' === buffer) {
3156 this._path.pop();
3157 if ('/' !== c && '\\' !== c) {
3158 this._path.push('');
3159 }
3160 } else if ('.' === buffer && '/' !== c && '\\' !== c) {
3161 this._path.push('');
3162 } else if ('.' !== buffer) {
3163 if ('file' === this._scheme && this._path.length === 0 &&
3164 buffer.length === 2 && ALPHA.test(buffer[0]) &&
3165 buffer[1] === '|') {
3166 buffer = buffer[0] + ':';
3167 }
3168 this._path.push(buffer);
3169 }
3170 buffer = '';
3171 if ('?' === c) {
3172 this._query = '?';
3173 state = 'query';
3174 } else if ('#' === c) {
3175 this._fragment = '#';
3176 state = 'fragment';
3177 }
3178 } else if ('\t' !== c && '\n' !== c && '\r' !== c) {
3179 buffer += percentEscape(c);
3180 }
3181 break;
3182
3183 case 'query':
3184 if (!stateOverride && '#' === c) {
3185 this._fragment = '#';
3186 state = 'fragment';
3187 } else if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
3188 this._query += percentEscapeQuery(c);
3189 }
3190 break;
3191
3192 case 'fragment':
3193 if (EOF !== c && '\t' !== c && '\n' !== c && '\r' !== c) {
3194 this._fragment += c;
3195 }
3196 break;
3197 }
3198
3199 cursor++;
3200 }
3201 }
3202
3203 function clear() {
3204 this._scheme = '';
3205 this._schemeData = '';
3206 this._username = '';
3207 this._password = null;
3208 this._host = '';
3209 this._port = '';
3210 this._path = [];
3211 this._query = '';
3212 this._fragment = '';
3213 this._isInvalid = false;
3214 this._isRelative = false;
3215 }
3216
3217 // Does not process domain names or IP addresses.
3218 // Does not handle encoding for the query parameter.
3219 function JURL(url, base /* , encoding */) {
3220 if (base !== undefined && !(base instanceof JURL)) {
3221 base = new JURL(String(base));
3222 }
3223
3224 this._url = url;
3225 clear.call(this);
3226
3227 var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
3228 // encoding = encoding || 'utf-8'
3229
3230 parse.call(this, input, null, base);
3231 }
3232
3233 JURL.prototype = {
3234 toString: function() {
3235 return this.href;
3236 },
3237 get href() {
3238 if (this._isInvalid) {
3239 return this._url;
3240 }
3241 var authority = '';
3242 if ('' !== this._username || null !== this._password) {
3243 authority = this._username +
3244 (null !== this._password ? ':' + this._password : '') + '@';
3245 }
3246
3247 return this.protocol +
3248 (this._isRelative ? '//' + authority + this.host : '') +
3249 this.pathname + this._query + this._fragment;
3250 },
3251 set href(href) {
3252 clear.call(this);
3253 parse.call(this, href);
3254 },
3255
3256 get protocol() {
3257 return this._scheme + ':';
3258 },
3259 set protocol(protocol) {
3260 if (this._isInvalid) {
3261 return;
3262 }
3263 parse.call(this, protocol + ':', 'scheme start');
3264 },
3265
3266 get host() {
3267 return this._isInvalid ? '' : this._port ?
3268 this._host + ':' + this._port : this._host;
3269 },
3270 set host(host) {
3271 if (this._isInvalid || !this._isRelative) {
3272 return;
3273 }
3274 parse.call(this, host, 'host');
3275 },
3276
3277 get hostname() {
3278 return this._host;
3279 },
3280 set hostname(hostname) {
3281 if (this._isInvalid || !this._isRelative) {
3282 return;
3283 }
3284 parse.call(this, hostname, 'hostname');
3285 },
3286
3287 get port() {
3288 return this._port;
3289 },
3290 set port(port) {
3291 if (this._isInvalid || !this._isRelative) {
3292 return;
3293 }
3294 parse.call(this, port, 'port');
3295 },
3296
3297 get pathname() {
3298 return this._isInvalid ? '' : this._isRelative ?
3299 '/' + this._path.join('/') : this._schemeData;
3300 },
3301 set pathname(pathname) {
3302 if (this._isInvalid || !this._isRelative) {
3303 return;
3304 }
3305 this._path = [];
3306 parse.call(this, pathname, 'relative path start');
3307 },
3308
3309 get search() {
3310 return this._isInvalid || !this._query || '?' === this._query ?
3311 '' : this._query;
3312 },
3313 set search(search) {
3314 if (this._isInvalid || !this._isRelative) {
3315 return;
3316 }
3317 this._query = '?';
3318 if ('?' === search[0]) {
3319 search = search.slice(1);
3320 }
3321 parse.call(this, search, 'query');
3322 },
3323
3324 get hash() {
3325 return this._isInvalid || !this._fragment || '#' === this._fragment ?
3326 '' : this._fragment;
3327 },
3328 set hash(hash) {
3329 if (this._isInvalid) {
3330 return;
3331 }
3332 this._fragment = '#';
3333 if ('#' === hash[0]) {
3334 hash = hash.slice(1);
3335 }
3336 parse.call(this, hash, 'fragment');
3337 },
3338
3339 get origin() {
3340 var host;
3341 if (this._isInvalid || !this._scheme) {
3342 return '';
3343 }
3344 // javascript: Gecko returns String(""), WebKit/Blink String("null")
3345 // Gecko throws error for "data://"
3346 // data: Gecko returns "", Blink returns "data://", WebKit returns "null"
3347 // Gecko returns String("") for file: mailto:
3348 // WebKit/Blink returns String("SCHEME://") for file: mailto:
3349 switch (this._scheme) {
3350 case 'data':
3351 case 'file':
3352 case 'javascript':
3353 case 'mailto':
3354 return 'null';
3355 }
3356 host = this.host;
3357 if (!host) {
3358 return '';
3359 }
3360 return this._scheme + '://' + host;
3361 }
3362 };
3363
3364 // Copy over the static methods
3365 var OriginalURL = scope.URL;
3366 if (OriginalURL) {
3367 JURL.createObjectURL = function(blob) {
3368 // IE extension allows a second optional options argument.
3369 // http://msdn.microsoft.com/en-us/library/ie/hh772302(v=vs.85).aspx
3370 return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
3371 };
3372 JURL.revokeObjectURL = function(url) {
3373 OriginalURL.revokeObjectURL(url);
3374 };
3375 }
3376
3377 scope.URL = JURL;
3378})(globalScope);
3379
3380exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
3381exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
3382exports.OPS = OPS;
3383exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS;
3384exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
3385exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
3386exports.AnnotationFieldFlag = AnnotationFieldFlag;
3387exports.AnnotationFlag = AnnotationFlag;
3388exports.AnnotationType = AnnotationType;
3389exports.FontType = FontType;
3390exports.ImageKind = ImageKind;
3391exports.InvalidPDFException = InvalidPDFException;
3392exports.MessageHandler = MessageHandler;
3393exports.MissingDataException = MissingDataException;
3394exports.MissingPDFException = MissingPDFException;
3395exports.NotImplementedException = NotImplementedException;
3396exports.PageViewport = PageViewport;
3397exports.PasswordException = PasswordException;
3398exports.PasswordResponses = PasswordResponses;
3399exports.StatTimer = StatTimer;
3400exports.StreamType = StreamType;
3401exports.TextRenderingMode = TextRenderingMode;
3402exports.UnexpectedResponseException = UnexpectedResponseException;
3403exports.UnknownErrorException = UnknownErrorException;
3404exports.Util = Util;
3405exports.XRefParseException = XRefParseException;
3406exports.arrayByteLength = arrayByteLength;
3407exports.arraysToBytes = arraysToBytes;
3408exports.assert = assert;
3409exports.bytesToString = bytesToString;
3410exports.createBlob = createBlob;
3411exports.createPromiseCapability = createPromiseCapability;
3412exports.createObjectURL = createObjectURL;
3413exports.deprecated = deprecated;
3414exports.error = error;
3415exports.getLookupTableFactory = getLookupTableFactory;
3416exports.getVerbosityLevel = getVerbosityLevel;
3417exports.globalScope = globalScope;
3418exports.info = info;
3419exports.isArray = isArray;
3420exports.isArrayBuffer = isArrayBuffer;
3421exports.isBool = isBool;
3422exports.isEmptyObj = isEmptyObj;
3423exports.isInt = isInt;
3424exports.isNum = isNum;
3425exports.isString = isString;
3426exports.isSpace = isSpace;
3427exports.isSameOrigin = isSameOrigin;
3428exports.isValidUrl = isValidUrl;
3429exports.isLittleEndian = isLittleEndian;
3430exports.isEvalSupported = isEvalSupported;
3431exports.loadJpegStream = loadJpegStream;
3432exports.log2 = log2;
3433exports.readInt8 = readInt8;
3434exports.readUint16 = readUint16;
3435exports.readUint32 = readUint32;
3436exports.removeNullCharacters = removeNullCharacters;
3437exports.setVerbosityLevel = setVerbosityLevel;
3438exports.shadow = shadow;
3439exports.string32 = string32;
3440exports.stringToBytes = stringToBytes;
3441exports.stringToPDFString = stringToPDFString;
3442exports.stringToUTF8String = stringToUTF8String;
3443exports.utf8StringToString = utf8StringToString;
3444exports.warn = warn;
3445}));
3446
3447
3448(function (root, factory) {
3449 {
3450 factory((root.pdfjsCoreCFFParser = {}), root.pdfjsSharedUtil,
3451 root.pdfjsCoreCharsets, root.pdfjsCoreEncodings);
3452 }
3453}(this, function (exports, sharedUtil, coreCharsets, coreEncodings) {
3454
3455var error = sharedUtil.error;
3456var info = sharedUtil.info;
3457var bytesToString = sharedUtil.bytesToString;
3458var warn = sharedUtil.warn;
3459var isArray = sharedUtil.isArray;
3460var Util = sharedUtil.Util;
3461var stringToBytes = sharedUtil.stringToBytes;
3462var assert = sharedUtil.assert;
3463var ISOAdobeCharset = coreCharsets.ISOAdobeCharset;
3464var ExpertCharset = coreCharsets.ExpertCharset;
3465var ExpertSubsetCharset = coreCharsets.ExpertSubsetCharset;
3466var StandardEncoding = coreEncodings.StandardEncoding;
3467var ExpertEncoding = coreEncodings.ExpertEncoding;
3468
3469// Maximum subroutine call depth of type 2 chartrings. Matches OTS.
3470var MAX_SUBR_NESTING = 10;
3471
3472/**
3473 * The CFF class takes a Type1 file and wrap it into a
3474 * 'Compact Font Format' which itself embed Type2 charstrings.
3475 */
3476var CFFStandardStrings = [
3477 '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
3478 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
3479 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
3480 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
3481 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
3482 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
3483 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum',
3484 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
3485 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
3486 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
3487 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
3488 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
3489 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
3490 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase',
3491 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown',
3492 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent',
3493 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash',
3494 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae',
3495 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior',
3496 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn',
3497 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters',
3498 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior',
3499 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring',
3500 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave',
3501 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute',
3502 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute',
3503 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron',
3504 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde',
3505 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute',
3506 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex',
3507 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex',
3508 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall',
3509 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall',
3510 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
3511 'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle',
3512 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
3513 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior',
3514 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior',
3515 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior',
3516 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
3517 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior',
3518 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall',
3519 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
3520 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
3521 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
3522 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
3523 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
3524 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall',
3525 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior',
3526 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth',
3527 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds',
3528 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
3529 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior',
3530 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior',
3531 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',
3532 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior',
3533 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall',
3534 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',
3535 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall',
3536 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall',
3537 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall',
3538 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',
3539 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall',
3540 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003',
3541 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'
3542];
3543
3544
3545var CFFParser = (function CFFParserClosure() {
3546 var CharstringValidationData = [
3547 null,
3548 { id: 'hstem', min: 2, stackClearing: true, stem: true },
3549 null,
3550 { id: 'vstem', min: 2, stackClearing: true, stem: true },
3551 { id: 'vmoveto', min: 1, stackClearing: true },
3552 { id: 'rlineto', min: 2, resetStack: true },
3553 { id: 'hlineto', min: 1, resetStack: true },
3554 { id: 'vlineto', min: 1, resetStack: true },
3555 { id: 'rrcurveto', min: 6, resetStack: true },
3556 null,
3557 { id: 'callsubr', min: 1, undefStack: true },
3558 { id: 'return', min: 0, undefStack: true },
3559 null, // 12
3560 null,
3561 { id: 'endchar', min: 0, stackClearing: true },
3562 null,
3563 null,
3564 null,
3565 { id: 'hstemhm', min: 2, stackClearing: true, stem: true },
3566 { id: 'hintmask', min: 0, stackClearing: true },
3567 { id: 'cntrmask', min: 0, stackClearing: true },
3568 { id: 'rmoveto', min: 2, stackClearing: true },
3569 { id: 'hmoveto', min: 1, stackClearing: true },
3570 { id: 'vstemhm', min: 2, stackClearing: true, stem: true },
3571 { id: 'rcurveline', min: 8, resetStack: true },
3572 { id: 'rlinecurve', min: 8, resetStack: true },
3573 { id: 'vvcurveto', min: 4, resetStack: true },
3574 { id: 'hhcurveto', min: 4, resetStack: true },
3575 null, // shortint
3576 { id: 'callgsubr', min: 1, undefStack: true },
3577 { id: 'vhcurveto', min: 4, resetStack: true },
3578 { id: 'hvcurveto', min: 4, resetStack: true }
3579 ];
3580 var CharstringValidationData12 = [
3581 null,
3582 null,
3583 null,
3584 { id: 'and', min: 2, stackDelta: -1 },
3585 { id: 'or', min: 2, stackDelta: -1 },
3586 { id: 'not', min: 1, stackDelta: 0 },
3587 null,
3588 null,
3589 null,
3590 { id: 'abs', min: 1, stackDelta: 0 },
3591 { id: 'add', min: 2, stackDelta: -1,
3592 stackFn: function stack_div(stack, index) {
3593 stack[index - 2] = stack[index - 2] + stack[index - 1];
3594 }
3595 },
3596 { id: 'sub', min: 2, stackDelta: -1,
3597 stackFn: function stack_div(stack, index) {
3598 stack[index - 2] = stack[index - 2] - stack[index - 1];
3599 }
3600 },
3601 { id: 'div', min: 2, stackDelta: -1,
3602 stackFn: function stack_div(stack, index) {
3603 stack[index - 2] = stack[index - 2] / stack[index - 1];
3604 }
3605 },
3606 null,
3607 { id: 'neg', min: 1, stackDelta: 0,
3608 stackFn: function stack_div(stack, index) {
3609 stack[index - 1] = -stack[index - 1];
3610 }
3611 },
3612 { id: 'eq', min: 2, stackDelta: -1 },
3613 null,
3614 null,
3615 { id: 'drop', min: 1, stackDelta: -1 },
3616 null,
3617 { id: 'put', min: 2, stackDelta: -2 },
3618 { id: 'get', min: 1, stackDelta: 0 },
3619 { id: 'ifelse', min: 4, stackDelta: -3 },
3620 { id: 'random', min: 0, stackDelta: 1 },
3621 { id: 'mul', min: 2, stackDelta: -1,
3622 stackFn: function stack_div(stack, index) {
3623 stack[index - 2] = stack[index - 2] * stack[index - 1];
3624 }
3625 },
3626 null,
3627 { id: 'sqrt', min: 1, stackDelta: 0 },
3628 { id: 'dup', min: 1, stackDelta: 1 },
3629 { id: 'exch', min: 2, stackDelta: 0 },
3630 { id: 'index', min: 2, stackDelta: 0 },
3631 { id: 'roll', min: 3, stackDelta: -2 },
3632 null,
3633 null,
3634 null,
3635 { id: 'hflex', min: 7, resetStack: true },
3636 { id: 'flex', min: 13, resetStack: true },
3637 { id: 'hflex1', min: 9, resetStack: true },
3638 { id: 'flex1', min: 11, resetStack: true }
3639 ];
3640
3641 function CFFParser(file, properties, seacAnalysisEnabled) {
3642 this.bytes = file.getBytes();
3643 this.properties = properties;
3644 this.seacAnalysisEnabled = !!seacAnalysisEnabled;
3645 }
3646 CFFParser.prototype = {
3647 parse: function CFFParser_parse() {
3648 var properties = this.properties;
3649 var cff = new CFF();
3650 this.cff = cff;
3651
3652 // The first five sections must be in order, all the others are reached
3653 // via offsets contained in one of the below.
3654 var header = this.parseHeader();
3655 var nameIndex = this.parseIndex(header.endPos);
3656 var topDictIndex = this.parseIndex(nameIndex.endPos);
3657 var stringIndex = this.parseIndex(topDictIndex.endPos);
3658 var globalSubrIndex = this.parseIndex(stringIndex.endPos);
3659
3660 var topDictParsed = this.parseDict(topDictIndex.obj.get(0));
3661 var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
3662
3663 cff.header = header.obj;
3664 cff.names = this.parseNameIndex(nameIndex.obj);
3665 cff.strings = this.parseStringIndex(stringIndex.obj);
3666 cff.topDict = topDict;
3667 cff.globalSubrIndex = globalSubrIndex.obj;
3668
3669 this.parsePrivateDict(cff.topDict);
3670
3671 cff.isCIDFont = topDict.hasName('ROS');
3672
3673 var charStringOffset = topDict.getByName('CharStrings');
3674 var charStringIndex = this.parseIndex(charStringOffset).obj;
3675
3676 var fontMatrix = topDict.getByName('FontMatrix');
3677 if (fontMatrix) {
3678 properties.fontMatrix = fontMatrix;
3679 }
3680
3681 var fontBBox = topDict.getByName('FontBBox');
3682 if (fontBBox) {
3683 // adjusting ascent/descent
3684 properties.ascent = fontBBox[3];
3685 properties.descent = fontBBox[1];
3686 properties.ascentScaled = true;
3687 }
3688
3689 var charset, encoding;
3690 if (cff.isCIDFont) {
3691 var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
3692 for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
3693 var dictRaw = fdArrayIndex.get(i);
3694 var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw),
3695 cff.strings);
3696 this.parsePrivateDict(fontDict);
3697 cff.fdArray.push(fontDict);
3698 }
3699 // cid fonts don't have an encoding
3700 encoding = null;
3701 charset = this.parseCharsets(topDict.getByName('charset'),
3702 charStringIndex.count, cff.strings, true);
3703 cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'),
3704 charStringIndex.count);
3705 } else {
3706 charset = this.parseCharsets(topDict.getByName('charset'),
3707 charStringIndex.count, cff.strings, false);
3708 encoding = this.parseEncoding(topDict.getByName('Encoding'),
3709 properties,
3710 cff.strings, charset.charset);
3711 }
3712
3713 cff.charset = charset;
3714 cff.encoding = encoding;
3715
3716 var charStringsAndSeacs = this.parseCharStrings(
3717 charStringIndex,
3718 topDict.privateDict.subrsIndex,
3719 globalSubrIndex.obj,
3720 cff.fdSelect,
3721 cff.fdArray);
3722 cff.charStrings = charStringsAndSeacs.charStrings;
3723 cff.seacs = charStringsAndSeacs.seacs;
3724 cff.widths = charStringsAndSeacs.widths;
3725
3726 return cff;
3727 },
3728 parseHeader: function CFFParser_parseHeader() {
3729 var bytes = this.bytes;
3730 var bytesLength = bytes.length;
3731 var offset = 0;
3732
3733 // Prevent an infinite loop, by checking that the offset is within the
3734 // bounds of the bytes array. Necessary in empty, or invalid, font files.
3735 while (offset < bytesLength && bytes[offset] !== 1) {
3736 ++offset;
3737 }
3738 if (offset >= bytesLength) {
3739 error('Invalid CFF header');
3740 } else if (offset !== 0) {
3741 info('cff data is shifted');
3742 bytes = bytes.subarray(offset);
3743 this.bytes = bytes;
3744 }
3745 var major = bytes[0];
3746 var minor = bytes[1];
3747 var hdrSize = bytes[2];
3748 var offSize = bytes[3];
3749 var header = new CFFHeader(major, minor, hdrSize, offSize);
3750 return { obj: header, endPos: hdrSize };
3751 },
3752 parseDict: function CFFParser_parseDict(dict) {
3753 var pos = 0;
3754
3755 function parseOperand() {
3756 var value = dict[pos++];
3757 if (value === 30) {
3758 return parseFloatOperand();
3759 } else if (value === 28) {
3760 value = dict[pos++];
3761 value = ((value << 24) | (dict[pos++] << 16)) >> 16;
3762 return value;
3763 } else if (value === 29) {
3764 value = dict[pos++];
3765 value = (value << 8) | dict[pos++];
3766 value = (value << 8) | dict[pos++];
3767 value = (value << 8) | dict[pos++];
3768 return value;
3769 } else if (value >= 32 && value <= 246) {
3770 return value - 139;
3771 } else if (value >= 247 && value <= 250) {
3772 return ((value - 247) * 256) + dict[pos++] + 108;
3773 } else if (value >= 251 && value <= 254) {
3774 return -((value - 251) * 256) - dict[pos++] - 108;
3775 } else {
3776 error('255 is not a valid DICT command');
3777 }
3778 return -1;
3779 }
3780
3781 function parseFloatOperand() {
3782 var str = '';
3783 var eof = 15;
3784 var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8',
3785 '9', '.', 'E', 'E-', null, '-'];
3786 var length = dict.length;
3787 while (pos < length) {
3788 var b = dict[pos++];
3789 var b1 = b >> 4;
3790 var b2 = b & 15;
3791
3792 if (b1 === eof) {
3793 break;
3794 }
3795 str += lookup[b1];
3796
3797 if (b2 === eof) {
3798 break;
3799 }
3800 str += lookup[b2];
3801 }
3802 return parseFloat(str);
3803 }
3804
3805 var operands = [];
3806 var entries = [];
3807
3808 pos = 0;
3809 var end = dict.length;
3810 while (pos < end) {
3811 var b = dict[pos];
3812 if (b <= 21) {
3813 if (b === 12) {
3814 b = (b << 8) | dict[++pos];
3815 }
3816 entries.push([b, operands]);
3817 operands = [];
3818 ++pos;
3819 } else {
3820 operands.push(parseOperand());
3821 }
3822 }
3823 return entries;
3824 },
3825 parseIndex: function CFFParser_parseIndex(pos) {
3826 var cffIndex = new CFFIndex();
3827 var bytes = this.bytes;
3828 var count = (bytes[pos++] << 8) | bytes[pos++];
3829 var offsets = [];
3830 var end = pos;
3831 var i, ii;
3832
3833 if (count !== 0) {
3834 var offsetSize = bytes[pos++];
3835 // add 1 for offset to determine size of last object
3836 var startPos = pos + ((count + 1) * offsetSize) - 1;
3837
3838 for (i = 0, ii = count + 1; i < ii; ++i) {
3839 var offset = 0;
3840 for (var j = 0; j < offsetSize; ++j) {
3841 offset <<= 8;
3842 offset += bytes[pos++];
3843 }
3844 offsets.push(startPos + offset);
3845 }
3846 end = offsets[count];
3847 }
3848 for (i = 0, ii = offsets.length - 1; i < ii; ++i) {
3849 var offsetStart = offsets[i];
3850 var offsetEnd = offsets[i + 1];
3851 cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
3852 }
3853 return {obj: cffIndex, endPos: end};
3854 },
3855 parseNameIndex: function CFFParser_parseNameIndex(index) {
3856 var names = [];
3857 for (var i = 0, ii = index.count; i < ii; ++i) {
3858 var name = index.get(i);
3859 // OTS doesn't allow names to be over 127 characters.
3860 var length = Math.min(name.length, 127);
3861 var data = [];
3862 // OTS also only permits certain characters in the name.
3863 for (var j = 0; j < length; ++j) {
3864 var c = name[j];
3865 if (j === 0 && c === 0) {
3866 data[j] = c;
3867 continue;
3868 }
3869 if ((c < 33 || c > 126) || c === 91 /* [ */ || c === 93 /* ] */ ||
3870 c === 40 /* ( */ || c === 41 /* ) */ || c === 123 /* { */ ||
3871 c === 125 /* } */ || c === 60 /* < */ || c === 62 /* > */ ||
3872 c === 47 /* / */ || c === 37 /* % */ || c === 35 /* # */) {
3873 data[j] = 95;
3874 continue;
3875 }
3876 data[j] = c;
3877 }
3878 names.push(bytesToString(data));
3879 }
3880 return names;
3881 },
3882 parseStringIndex: function CFFParser_parseStringIndex(index) {
3883 var strings = new CFFStrings();
3884 for (var i = 0, ii = index.count; i < ii; ++i) {
3885 var data = index.get(i);
3886 strings.add(bytesToString(data));
3887 }
3888 return strings;
3889 },
3890 createDict: function CFFParser_createDict(Type, dict, strings) {
3891 var cffDict = new Type(strings);
3892 for (var i = 0, ii = dict.length; i < ii; ++i) {
3893 var pair = dict[i];
3894 var key = pair[0];
3895 var value = pair[1];
3896 cffDict.setByKey(key, value);
3897 }
3898 return cffDict;
3899 },
3900 parseCharString: function CFFParser_parseCharString(state, data,
3901 localSubrIndex,
3902 globalSubrIndex) {
3903 if (state.callDepth > MAX_SUBR_NESTING) {
3904 return false;
3905 }
3906 var stackSize = state.stackSize;
3907 var stack = state.stack;
3908
3909 var length = data.length;
3910
3911 for (var j = 0; j < length;) {
3912 var value = data[j++];
3913 var validationCommand = null;
3914 if (value === 12) {
3915 var q = data[j++];
3916 if (q === 0) {
3917 // The CFF specification state that the 'dotsection' command
3918 // (12, 0) is deprecated and treated as a no-op, but all Type2
3919 // charstrings processors should support them. Unfortunately
3920 // the font sanitizer don't. As a workaround the sequence (12, 0)
3921 // is replaced by a useless (0, hmoveto).
3922 data[j - 2] = 139;
3923 data[j - 1] = 22;
3924 stackSize = 0;
3925 } else {
3926 validationCommand = CharstringValidationData12[q];
3927 }
3928 } else if (value === 28) { // number (16 bit)
3929 stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16;
3930 j += 2;
3931 stackSize++;
3932 } else if (value === 14) {
3933 if (stackSize >= 4) {
3934 stackSize -= 4;
3935 if (this.seacAnalysisEnabled) {
3936 state.seac = stack.slice(stackSize, stackSize + 4);
3937 return false;
3938 }
3939 }
3940 validationCommand = CharstringValidationData[value];
3941 } else if (value >= 32 && value <= 246) { // number
3942 stack[stackSize] = value - 139;
3943 stackSize++;
3944 } else if (value >= 247 && value <= 254) { // number (+1 bytes)
3945 stack[stackSize] = (value < 251 ?
3946 ((value - 247) << 8) + data[j] + 108 :
3947 -((value - 251) << 8) - data[j] - 108);
3948 j++;
3949 stackSize++;
3950 } else if (value === 255) { // number (32 bit)
3951 stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) |
3952 (data[j + 2] << 8) | data[j + 3]) / 65536;
3953 j += 4;
3954 stackSize++;
3955 } else if (value === 19 || value === 20) {
3956 state.hints += stackSize >> 1;
3957 // skipping right amount of hints flag data
3958 j += (state.hints + 7) >> 3;
3959 stackSize %= 2;
3960 validationCommand = CharstringValidationData[value];
3961 } else if (value === 10 || value === 29) {
3962 var subrsIndex;
3963 if (value === 10) {
3964 subrsIndex = localSubrIndex;
3965 } else {
3966 subrsIndex = globalSubrIndex;
3967 }
3968 if (!subrsIndex) {
3969 validationCommand = CharstringValidationData[value];
3970 warn('Missing subrsIndex for ' + validationCommand.id);
3971 return false;
3972 }
3973 var bias = 32768;
3974 if (subrsIndex.count < 1240) {
3975 bias = 107;
3976 } else if (subrsIndex.count < 33900) {
3977 bias = 1131;
3978 }
3979 var subrNumber = stack[--stackSize] + bias;
3980 if (subrNumber < 0 || subrNumber >= subrsIndex.count) {
3981 validationCommand = CharstringValidationData[value];
3982 warn('Out of bounds subrIndex for ' + validationCommand.id);
3983 return false;
3984 }
3985 state.stackSize = stackSize;
3986 state.callDepth++;
3987 var valid = this.parseCharString(state, subrsIndex.get(subrNumber),
3988 localSubrIndex, globalSubrIndex);
3989 if (!valid) {
3990 return false;
3991 }
3992 state.callDepth--;
3993 stackSize = state.stackSize;
3994 continue;
3995 } else if (value === 11) {
3996 state.stackSize = stackSize;
3997 return true;
3998 } else {
3999 validationCommand = CharstringValidationData[value];
4000 }
4001 if (validationCommand) {
4002 if (validationCommand.stem) {
4003 state.hints += stackSize >> 1;
4004 }
4005 if ('min' in validationCommand) {
4006 if (!state.undefStack && stackSize < validationCommand.min) {
4007 warn('Not enough parameters for ' + validationCommand.id +
4008 '; actual: ' + stackSize +
4009 ', expected: ' + validationCommand.min);
4010 return false;
4011 }
4012 }
4013 if (state.firstStackClearing && validationCommand.stackClearing) {
4014 state.firstStackClearing = false;
4015 // the optional character width can be found before the first
4016 // stack-clearing command arguments
4017 stackSize -= validationCommand.min;
4018 if (stackSize >= 2 && validationCommand.stem) {
4019 // there are even amount of arguments for stem commands
4020 stackSize %= 2;
4021 } else if (stackSize > 1) {
4022 warn('Found too many parameters for stack-clearing command');
4023 }
4024 if (stackSize > 0 && stack[stackSize - 1] >= 0) {
4025 state.width = stack[stackSize - 1];
4026 }
4027 }
4028 if ('stackDelta' in validationCommand) {
4029 if ('stackFn' in validationCommand) {
4030 validationCommand.stackFn(stack, stackSize);
4031 }
4032 stackSize += validationCommand.stackDelta;
4033 } else if (validationCommand.stackClearing) {
4034 stackSize = 0;
4035 } else if (validationCommand.resetStack) {
4036 stackSize = 0;
4037 state.undefStack = false;
4038 } else if (validationCommand.undefStack) {
4039 stackSize = 0;
4040 state.undefStack = true;
4041 state.firstStackClearing = false;
4042 }
4043 }
4044 }
4045 state.stackSize = stackSize;
4046 return true;
4047 },
4048 parseCharStrings: function CFFParser_parseCharStrings(charStrings,
4049 localSubrIndex,
4050 globalSubrIndex,
4051 fdSelect,
4052 fdArray) {
4053 var seacs = [];
4054 var widths = [];
4055 var count = charStrings.count;
4056 for (var i = 0; i < count; i++) {
4057 var charstring = charStrings.get(i);
4058 var state = {
4059 callDepth: 0,
4060 stackSize: 0,
4061 stack: [],
4062 undefStack: true,
4063 hints: 0,
4064 firstStackClearing: true,
4065 seac: null,
4066 width: null
4067 };
4068 var valid = true;
4069 var localSubrToUse = null;
4070 if (fdSelect && fdArray.length) {
4071 var fdIndex = fdSelect.getFDIndex(i);
4072 if (fdIndex === -1) {
4073 warn('Glyph index is not in fd select.');
4074 valid = false;
4075 }
4076 if (fdIndex >= fdArray.length) {
4077 warn('Invalid fd index for glyph index.');
4078 valid = false;
4079 }
4080 if (valid) {
4081 localSubrToUse = fdArray[fdIndex].privateDict.subrsIndex;
4082 }
4083 } else if (localSubrIndex) {
4084 localSubrToUse = localSubrIndex;
4085 }
4086 if (valid) {
4087 valid = this.parseCharString(state, charstring, localSubrToUse,
4088 globalSubrIndex);
4089 }
4090 if (state.width !== null) {
4091 widths[i] = state.width;
4092 }
4093 if (state.seac !== null) {
4094 seacs[i] = state.seac;
4095 }
4096 if (!valid) {
4097 // resetting invalid charstring to single 'endchar'
4098 charStrings.set(i, new Uint8Array([14]));
4099 }
4100 }
4101 return { charStrings: charStrings, seacs: seacs, widths: widths };
4102 },
4103 emptyPrivateDictionary:
4104 function CFFParser_emptyPrivateDictionary(parentDict) {
4105 var privateDict = this.createDict(CFFPrivateDict, [],
4106 parentDict.strings);
4107 parentDict.setByKey(18, [0, 0]);
4108 parentDict.privateDict = privateDict;
4109 },
4110 parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
4111 // no private dict, do nothing
4112 if (!parentDict.hasName('Private')) {
4113 this.emptyPrivateDictionary(parentDict);
4114 return;
4115 }
4116 var privateOffset = parentDict.getByName('Private');
4117 // make sure the params are formatted correctly
4118 if (!isArray(privateOffset) || privateOffset.length !== 2) {
4119 parentDict.removeByName('Private');
4120 return;
4121 }
4122 var size = privateOffset[0];
4123 var offset = privateOffset[1];
4124 // remove empty dicts or ones that refer to invalid location
4125 if (size === 0 || offset >= this.bytes.length) {
4126 this.emptyPrivateDictionary(parentDict);
4127 return;
4128 }
4129
4130 var privateDictEnd = offset + size;
4131 var dictData = this.bytes.subarray(offset, privateDictEnd);
4132 var dict = this.parseDict(dictData);
4133 var privateDict = this.createDict(CFFPrivateDict, dict,
4134 parentDict.strings);
4135 parentDict.privateDict = privateDict;
4136
4137 // Parse the Subrs index also since it's relative to the private dict.
4138 if (!privateDict.getByName('Subrs')) {
4139 return;
4140 }
4141 var subrsOffset = privateDict.getByName('Subrs');
4142 var relativeOffset = offset + subrsOffset;
4143 // Validate the offset.
4144 if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
4145 this.emptyPrivateDictionary(parentDict);
4146 return;
4147 }
4148 var subrsIndex = this.parseIndex(relativeOffset);
4149 privateDict.subrsIndex = subrsIndex.obj;
4150 },
4151 parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) {
4152 if (pos === 0) {
4153 return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE,
4154 ISOAdobeCharset);
4155 } else if (pos === 1) {
4156 return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT,
4157 ExpertCharset);
4158 } else if (pos === 2) {
4159 return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET,
4160 ExpertSubsetCharset);
4161 }
4162
4163 var bytes = this.bytes;
4164 var start = pos;
4165 var format = bytes[pos++];
4166 var charset = ['.notdef'];
4167 var id, count, i;
4168
4169 // subtract 1 for the .notdef glyph
4170 length -= 1;
4171
4172 switch (format) {
4173 case 0:
4174 for (i = 0; i < length; i++) {
4175 id = (bytes[pos++] << 8) | bytes[pos++];
4176 charset.push(cid ? id : strings.get(id));
4177 }
4178 break;
4179 case 1:
4180 while (charset.length <= length) {
4181 id = (bytes[pos++] << 8) | bytes[pos++];
4182 count = bytes[pos++];
4183 for (i = 0; i <= count; i++) {
4184 charset.push(cid ? id++ : strings.get(id++));
4185 }
4186 }
4187 break;
4188 case 2:
4189 while (charset.length <= length) {
4190 id = (bytes[pos++] << 8) | bytes[pos++];
4191 count = (bytes[pos++] << 8) | bytes[pos++];
4192 for (i = 0; i <= count; i++) {
4193 charset.push(cid ? id++ : strings.get(id++));
4194 }
4195 }
4196 break;
4197 default:
4198 error('Unknown charset format');
4199 }
4200 // Raw won't be needed if we actually compile the charset.
4201 var end = pos;
4202 var raw = bytes.subarray(start, end);
4203
4204 return new CFFCharset(false, format, charset, raw);
4205 },
4206 parseEncoding: function CFFParser_parseEncoding(pos,
4207 properties,
4208 strings,
4209 charset) {
4210 var encoding = Object.create(null);
4211 var bytes = this.bytes;
4212 var predefined = false;
4213 var hasSupplement = false;
4214 var format, i, ii;
4215 var raw = null;
4216
4217 function readSupplement() {
4218 var supplementsCount = bytes[pos++];
4219 for (i = 0; i < supplementsCount; i++) {
4220 var code = bytes[pos++];
4221 var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
4222 encoding[code] = charset.indexOf(strings.get(sid));
4223 }
4224 }
4225
4226 if (pos === 0 || pos === 1) {
4227 predefined = true;
4228 format = pos;
4229 var baseEncoding = pos ? ExpertEncoding : StandardEncoding;
4230 for (i = 0, ii = charset.length; i < ii; i++) {
4231 var index = baseEncoding.indexOf(charset[i]);
4232 if (index !== -1) {
4233 encoding[index] = i;
4234 }
4235 }
4236 } else {
4237 var dataStart = pos;
4238 format = bytes[pos++];
4239 switch (format & 0x7f) {
4240 case 0:
4241 var glyphsCount = bytes[pos++];
4242 for (i = 1; i <= glyphsCount; i++) {
4243 encoding[bytes[pos++]] = i;
4244 }
4245 break;
4246
4247 case 1:
4248 var rangesCount = bytes[pos++];
4249 var gid = 1;
4250 for (i = 0; i < rangesCount; i++) {
4251 var start = bytes[pos++];
4252 var left = bytes[pos++];
4253 for (var j = start; j <= start + left; j++) {
4254 encoding[j] = gid++;
4255 }
4256 }
4257 break;
4258
4259 default:
4260 error('Unknown encoding format: ' + format + ' in CFF');
4261 break;
4262 }
4263 var dataEnd = pos;
4264 if (format & 0x80) {
4265 // The font sanitizer does not support CFF encoding with a
4266 // supplement, since the encoding is not really used to map
4267 // between gid to glyph, let's overwrite what is declared in
4268 // the top dictionary to let the sanitizer think the font use
4269 // StandardEncoding, that's a lie but that's ok.
4270 bytes[dataStart] &= 0x7f;
4271 readSupplement();
4272 hasSupplement = true;
4273 }
4274 raw = bytes.subarray(dataStart, dataEnd);
4275 }
4276 format = format & 0x7f;
4277 return new CFFEncoding(predefined, format, encoding, raw);
4278 },
4279 parseFDSelect: function CFFParser_parseFDSelect(pos, length) {
4280 var start = pos;
4281 var bytes = this.bytes;
4282 var format = bytes[pos++];
4283 var fdSelect = [], rawBytes;
4284 var i, invalidFirstGID = false;
4285
4286 switch (format) {
4287 case 0:
4288 for (i = 0; i < length; ++i) {
4289 var id = bytes[pos++];
4290 fdSelect.push(id);
4291 }
4292 rawBytes = bytes.subarray(start, pos);
4293 break;
4294 case 3:
4295 var rangesCount = (bytes[pos++] << 8) | bytes[pos++];
4296 for (i = 0; i < rangesCount; ++i) {
4297 var first = (bytes[pos++] << 8) | bytes[pos++];
4298 if (i === 0 && first !== 0) {
4299 warn('parseFDSelect: The first range must have a first GID of 0' +
4300 ' -- trying to recover.');
4301 invalidFirstGID = true;
4302 first = 0;
4303 }
4304 var fdIndex = bytes[pos++];
4305 var next = (bytes[pos] << 8) | bytes[pos + 1];
4306 for (var j = first; j < next; ++j) {
4307 fdSelect.push(fdIndex);
4308 }
4309 }
4310 // Advance past the sentinel(next).
4311 pos += 2;
4312 rawBytes = bytes.subarray(start, pos);
4313
4314 if (invalidFirstGID) {
4315 rawBytes[3] = rawBytes[4] = 0; // Adjust the first range, first GID.
4316 }
4317 break;
4318 default:
4319 error('parseFDSelect: Unknown format "' + format + '".');
4320 break;
4321 }
4322 assert(fdSelect.length === length, 'parseFDSelect: Invalid font data.');
4323
4324 return new CFFFDSelect(fdSelect, rawBytes);
4325 }
4326 };
4327 return CFFParser;
4328})();
4329
4330// Compact Font Format
4331var CFF = (function CFFClosure() {
4332 function CFF() {
4333 this.header = null;
4334 this.names = [];
4335 this.topDict = null;
4336 this.strings = new CFFStrings();
4337 this.globalSubrIndex = null;
4338
4339 // The following could really be per font, but since we only have one font
4340 // store them here.
4341 this.encoding = null;
4342 this.charset = null;
4343 this.charStrings = null;
4344 this.fdArray = [];
4345 this.fdSelect = null;
4346
4347 this.isCIDFont = false;
4348 }
4349 return CFF;
4350})();
4351
4352var CFFHeader = (function CFFHeaderClosure() {
4353 function CFFHeader(major, minor, hdrSize, offSize) {
4354 this.major = major;
4355 this.minor = minor;
4356 this.hdrSize = hdrSize;
4357 this.offSize = offSize;
4358 }
4359 return CFFHeader;
4360})();
4361
4362var CFFStrings = (function CFFStringsClosure() {
4363 function CFFStrings() {
4364 this.strings = [];
4365 }
4366 CFFStrings.prototype = {
4367 get: function CFFStrings_get(index) {
4368 if (index >= 0 && index <= 390) {
4369 return CFFStandardStrings[index];
4370 }
4371 if (index - 391 <= this.strings.length) {
4372 return this.strings[index - 391];
4373 }
4374 return CFFStandardStrings[0];
4375 },
4376 add: function CFFStrings_add(value) {
4377 this.strings.push(value);
4378 },
4379 get count() {
4380 return this.strings.length;
4381 }
4382 };
4383 return CFFStrings;
4384})();
4385
4386var CFFIndex = (function CFFIndexClosure() {
4387 function CFFIndex() {
4388 this.objects = [];
4389 this.length = 0;
4390 }
4391 CFFIndex.prototype = {
4392 add: function CFFIndex_add(data) {
4393 this.length += data.length;
4394 this.objects.push(data);
4395 },
4396 set: function CFFIndex_set(index, data) {
4397 this.length += data.length - this.objects[index].length;
4398 this.objects[index] = data;
4399 },
4400 get: function CFFIndex_get(index) {
4401 return this.objects[index];
4402 },
4403 get count() {
4404 return this.objects.length;
4405 }
4406 };
4407 return CFFIndex;
4408})();
4409
4410var CFFDict = (function CFFDictClosure() {
4411 function CFFDict(tables, strings) {
4412 this.keyToNameMap = tables.keyToNameMap;
4413 this.nameToKeyMap = tables.nameToKeyMap;
4414 this.defaults = tables.defaults;
4415 this.types = tables.types;
4416 this.opcodes = tables.opcodes;
4417 this.order = tables.order;
4418 this.strings = strings;
4419 this.values = Object.create(null);
4420 }
4421 CFFDict.prototype = {
4422 // value should always be an array
4423 setByKey: function CFFDict_setByKey(key, value) {
4424 if (!(key in this.keyToNameMap)) {
4425 return false;
4426 }
4427 // ignore empty values
4428 if (value.length === 0) {
4429 return true;
4430 }
4431 var type = this.types[key];
4432 // remove the array wrapping these types of values
4433 if (type === 'num' || type === 'sid' || type === 'offset') {
4434 value = value[0];
4435 // Ignore invalid values (fixes bug 1068432).
4436 if (isNaN(value)) {
4437 warn('Invalid CFFDict value: ' + value + ', for key: ' + key + '.');
4438 return true;
4439 }
4440 }
4441 this.values[key] = value;
4442 return true;
4443 },
4444 setByName: function CFFDict_setByName(name, value) {
4445 if (!(name in this.nameToKeyMap)) {
4446 error('Invalid dictionary name "' + name + '"');
4447 }
4448 this.values[this.nameToKeyMap[name]] = value;
4449 },
4450 hasName: function CFFDict_hasName(name) {
4451 return this.nameToKeyMap[name] in this.values;
4452 },
4453 getByName: function CFFDict_getByName(name) {
4454 if (!(name in this.nameToKeyMap)) {
4455 error('Invalid dictionary name "' + name + '"');
4456 }
4457 var key = this.nameToKeyMap[name];
4458 if (!(key in this.values)) {
4459 return this.defaults[key];
4460 }
4461 return this.values[key];
4462 },
4463 removeByName: function CFFDict_removeByName(name) {
4464 delete this.values[this.nameToKeyMap[name]];
4465 }
4466 };
4467 CFFDict.createTables = function CFFDict_createTables(layout) {
4468 var tables = {
4469 keyToNameMap: {},
4470 nameToKeyMap: {},
4471 defaults: {},
4472 types: {},
4473 opcodes: {},
4474 order: []
4475 };
4476 for (var i = 0, ii = layout.length; i < ii; ++i) {
4477 var entry = layout[i];
4478 var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
4479 tables.keyToNameMap[key] = entry[1];
4480 tables.nameToKeyMap[entry[1]] = key;
4481 tables.types[key] = entry[2];
4482 tables.defaults[key] = entry[3];
4483 tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]];
4484 tables.order.push(key);
4485 }
4486 return tables;
4487 };
4488 return CFFDict;
4489})();
4490
4491var CFFTopDict = (function CFFTopDictClosure() {
4492 var layout = [
4493 [[12, 30], 'ROS', ['sid', 'sid', 'num'], null],
4494 [[12, 20], 'SyntheticBase', 'num', null],
4495 [0, 'version', 'sid', null],
4496 [1, 'Notice', 'sid', null],
4497 [[12, 0], 'Copyright', 'sid', null],
4498 [2, 'FullName', 'sid', null],
4499 [3, 'FamilyName', 'sid', null],
4500 [4, 'Weight', 'sid', null],
4501 [[12, 1], 'isFixedPitch', 'num', 0],
4502 [[12, 2], 'ItalicAngle', 'num', 0],
4503 [[12, 3], 'UnderlinePosition', 'num', -100],
4504 [[12, 4], 'UnderlineThickness', 'num', 50],
4505 [[12, 5], 'PaintType', 'num', 0],
4506 [[12, 6], 'CharstringType', 'num', 2],
4507 [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'],
4508 [0.001, 0, 0, 0.001, 0, 0]],
4509 [13, 'UniqueID', 'num', null],
4510 [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]],
4511 [[12, 8], 'StrokeWidth', 'num', 0],
4512 [14, 'XUID', 'array', null],
4513 [15, 'charset', 'offset', 0],
4514 [16, 'Encoding', 'offset', 0],
4515 [17, 'CharStrings', 'offset', 0],
4516 [18, 'Private', ['offset', 'offset'], null],
4517 [[12, 21], 'PostScript', 'sid', null],
4518 [[12, 22], 'BaseFontName', 'sid', null],
4519 [[12, 23], 'BaseFontBlend', 'delta', null],
4520 [[12, 31], 'CIDFontVersion', 'num', 0],
4521 [[12, 32], 'CIDFontRevision', 'num', 0],
4522 [[12, 33], 'CIDFontType', 'num', 0],
4523 [[12, 34], 'CIDCount', 'num', 8720],
4524 [[12, 35], 'UIDBase', 'num', null],
4525 // XXX: CID Fonts on DirectWrite 6.1 only seem to work if FDSelect comes
4526 // before FDArray.
4527 [[12, 37], 'FDSelect', 'offset', null],
4528 [[12, 36], 'FDArray', 'offset', null],
4529 [[12, 38], 'FontName', 'sid', null]
4530 ];
4531 var tables = null;
4532 function CFFTopDict(strings) {
4533 if (tables === null) {
4534 tables = CFFDict.createTables(layout);
4535 }
4536 CFFDict.call(this, tables, strings);
4537 this.privateDict = null;
4538 }
4539 CFFTopDict.prototype = Object.create(CFFDict.prototype);
4540 return CFFTopDict;
4541})();
4542
4543var CFFPrivateDict = (function CFFPrivateDictClosure() {
4544 var layout = [
4545 [6, 'BlueValues', 'delta', null],
4546 [7, 'OtherBlues', 'delta', null],
4547 [8, 'FamilyBlues', 'delta', null],
4548 [9, 'FamilyOtherBlues', 'delta', null],
4549 [[12, 9], 'BlueScale', 'num', 0.039625],
4550 [[12, 10], 'BlueShift', 'num', 7],
4551 [[12, 11], 'BlueFuzz', 'num', 1],
4552 [10, 'StdHW', 'num', null],
4553 [11, 'StdVW', 'num', null],
4554 [[12, 12], 'StemSnapH', 'delta', null],
4555 [[12, 13], 'StemSnapV', 'delta', null],
4556 [[12, 14], 'ForceBold', 'num', 0],
4557 [[12, 17], 'LanguageGroup', 'num', 0],
4558 [[12, 18], 'ExpansionFactor', 'num', 0.06],
4559 [[12, 19], 'initialRandomSeed', 'num', 0],
4560 [20, 'defaultWidthX', 'num', 0],
4561 [21, 'nominalWidthX', 'num', 0],
4562 [19, 'Subrs', 'offset', null]
4563 ];
4564 var tables = null;
4565 function CFFPrivateDict(strings) {
4566 if (tables === null) {
4567 tables = CFFDict.createTables(layout);
4568 }
4569 CFFDict.call(this, tables, strings);
4570 this.subrsIndex = null;
4571 }
4572 CFFPrivateDict.prototype = Object.create(CFFDict.prototype);
4573 return CFFPrivateDict;
4574})();
4575
4576var CFFCharsetPredefinedTypes = {
4577 ISO_ADOBE: 0,
4578 EXPERT: 1,
4579 EXPERT_SUBSET: 2
4580};
4581var CFFCharset = (function CFFCharsetClosure() {
4582 function CFFCharset(predefined, format, charset, raw) {
4583 this.predefined = predefined;
4584 this.format = format;
4585 this.charset = charset;
4586 this.raw = raw;
4587 }
4588 return CFFCharset;
4589})();
4590
4591var CFFEncoding = (function CFFEncodingClosure() {
4592 function CFFEncoding(predefined, format, encoding, raw) {
4593 this.predefined = predefined;
4594 this.format = format;
4595 this.encoding = encoding;
4596 this.raw = raw;
4597 }
4598 return CFFEncoding;
4599})();
4600
4601var CFFFDSelect = (function CFFFDSelectClosure() {
4602 function CFFFDSelect(fdSelect, raw) {
4603 this.fdSelect = fdSelect;
4604 this.raw = raw;
4605 }
4606 CFFFDSelect.prototype = {
4607 getFDIndex: function CFFFDSelect_get(glyphIndex) {
4608 if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {
4609 return -1;
4610 }
4611 return this.fdSelect[glyphIndex];
4612 }
4613 };
4614 return CFFFDSelect;
4615})();
4616
4617// Helper class to keep track of where an offset is within the data and helps
4618// filling in that offset once it's known.
4619var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
4620 function CFFOffsetTracker() {
4621 this.offsets = Object.create(null);
4622 }
4623 CFFOffsetTracker.prototype = {
4624 isTracking: function CFFOffsetTracker_isTracking(key) {
4625 return key in this.offsets;
4626 },
4627 track: function CFFOffsetTracker_track(key, location) {
4628 if (key in this.offsets) {
4629 error('Already tracking location of ' + key);
4630 }
4631 this.offsets[key] = location;
4632 },
4633 offset: function CFFOffsetTracker_offset(value) {
4634 for (var key in this.offsets) {
4635 this.offsets[key] += value;
4636 }
4637 },
4638 setEntryLocation: function CFFOffsetTracker_setEntryLocation(key,
4639 values,
4640 output) {
4641 if (!(key in this.offsets)) {
4642 error('Not tracking location of ' + key);
4643 }
4644 var data = output.data;
4645 var dataOffset = this.offsets[key];
4646 var size = 5;
4647 for (var i = 0, ii = values.length; i < ii; ++i) {
4648 var offset0 = i * size + dataOffset;
4649 var offset1 = offset0 + 1;
4650 var offset2 = offset0 + 2;
4651 var offset3 = offset0 + 3;
4652 var offset4 = offset0 + 4;
4653 // It's easy to screw up offsets so perform this sanity check.
4654 if (data[offset0] !== 0x1d || data[offset1] !== 0 ||
4655 data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) {
4656 error('writing to an offset that is not empty');
4657 }
4658 var value = values[i];
4659 data[offset0] = 0x1d;
4660 data[offset1] = (value >> 24) & 0xFF;
4661 data[offset2] = (value >> 16) & 0xFF;
4662 data[offset3] = (value >> 8) & 0xFF;
4663 data[offset4] = value & 0xFF;
4664 }
4665 }
4666 };
4667 return CFFOffsetTracker;
4668})();
4669
4670// Takes a CFF and converts it to the binary representation.
4671var CFFCompiler = (function CFFCompilerClosure() {
4672 function CFFCompiler(cff) {
4673 this.cff = cff;
4674 }
4675 CFFCompiler.prototype = {
4676 compile: function CFFCompiler_compile() {
4677 var cff = this.cff;
4678 var output = {
4679 data: [],
4680 length: 0,
4681 add: function CFFCompiler_add(data) {
4682 this.data = this.data.concat(data);
4683 this.length = this.data.length;
4684 }
4685 };
4686
4687 // Compile the five entries that must be in order.
4688 var header = this.compileHeader(cff.header);
4689 output.add(header);
4690
4691 var nameIndex = this.compileNameIndex(cff.names);
4692 output.add(nameIndex);
4693
4694 if (cff.isCIDFont) {
4695 // The spec is unclear on how font matrices should relate to each other
4696 // when there is one in the main top dict and the sub top dicts.
4697 // Windows handles this differently than linux and osx so we have to
4698 // normalize to work on all.
4699 // Rules based off of some mailing list discussions:
4700 // - If main font has a matrix and subfont doesn't, use the main matrix.
4701 // - If no main font matrix and there is a subfont matrix, use the
4702 // subfont matrix.
4703 // - If both have matrices, concat together.
4704 // - If neither have matrices, use default.
4705 // To make this work on all platforms we move the top matrix into each
4706 // sub top dict and concat if necessary.
4707 if (cff.topDict.hasName('FontMatrix')) {
4708 var base = cff.topDict.getByName('FontMatrix');
4709 cff.topDict.removeByName('FontMatrix');
4710 for (var i = 0, ii = cff.fdArray.length; i < ii; i++) {
4711 var subDict = cff.fdArray[i];
4712 var matrix = base.slice(0);
4713 if (subDict.hasName('FontMatrix')) {
4714 matrix = Util.transform(matrix, subDict.getByName('FontMatrix'));
4715 }
4716 subDict.setByName('FontMatrix', matrix);
4717 }
4718 }
4719 }
4720
4721 var compiled = this.compileTopDicts([cff.topDict],
4722 output.length,
4723 cff.isCIDFont);
4724 output.add(compiled.output);
4725 var topDictTracker = compiled.trackers[0];
4726
4727 var stringIndex = this.compileStringIndex(cff.strings.strings);
4728 output.add(stringIndex);
4729
4730 var globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
4731 output.add(globalSubrIndex);
4732
4733 // Now start on the other entries that have no specific order.
4734 if (cff.encoding && cff.topDict.hasName('Encoding')) {
4735 if (cff.encoding.predefined) {
4736 topDictTracker.setEntryLocation('Encoding', [cff.encoding.format],
4737 output);
4738 } else {
4739 var encoding = this.compileEncoding(cff.encoding);
4740 topDictTracker.setEntryLocation('Encoding', [output.length], output);
4741 output.add(encoding);
4742 }
4743 }
4744
4745 if (cff.charset && cff.topDict.hasName('charset')) {
4746 if (cff.charset.predefined) {
4747 topDictTracker.setEntryLocation('charset', [cff.charset.format],
4748 output);
4749 } else {
4750 var charset = this.compileCharset(cff.charset);
4751 topDictTracker.setEntryLocation('charset', [output.length], output);
4752 output.add(charset);
4753 }
4754 }
4755
4756 var charStrings = this.compileCharStrings(cff.charStrings);
4757 topDictTracker.setEntryLocation('CharStrings', [output.length], output);
4758 output.add(charStrings);
4759
4760 if (cff.isCIDFont) {
4761 // For some reason FDSelect must be in front of FDArray on windows. OSX
4762 // and linux don't seem to care.
4763 topDictTracker.setEntryLocation('FDSelect', [output.length], output);
4764 var fdSelect = this.compileFDSelect(cff.fdSelect.raw);
4765 output.add(fdSelect);
4766 // It is unclear if the sub font dictionary can have CID related
4767 // dictionary keys, but the sanitizer doesn't like them so remove them.
4768 compiled = this.compileTopDicts(cff.fdArray, output.length, true);
4769 topDictTracker.setEntryLocation('FDArray', [output.length], output);
4770 output.add(compiled.output);
4771 var fontDictTrackers = compiled.trackers;
4772
4773 this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
4774 }
4775
4776 this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
4777
4778 // If the font data ends with INDEX whose object data is zero-length,
4779 // the sanitizer will bail out. Add a dummy byte to avoid that.
4780 output.add([0]);
4781
4782 return output.data;
4783 },
4784 encodeNumber: function CFFCompiler_encodeNumber(value) {
4785 if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) { // isInt
4786 return this.encodeInteger(value);
4787 } else {
4788 return this.encodeFloat(value);
4789 }
4790 },
4791 encodeFloat: function CFFCompiler_encodeFloat(num) {
4792 var value = num.toString();
4793
4794 // rounding inaccurate doubles
4795 var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
4796 if (m) {
4797 var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
4798 value = (Math.round(num * epsilon) / epsilon).toString();
4799 }
4800
4801 var nibbles = '';
4802 var i, ii;
4803 for (i = 0, ii = value.length; i < ii; ++i) {
4804 var a = value[i];
4805 if (a === 'e') {
4806 nibbles += value[++i] === '-' ? 'c' : 'b';
4807 } else if (a === '.') {
4808 nibbles += 'a';
4809 } else if (a === '-') {
4810 nibbles += 'e';
4811 } else {
4812 nibbles += a;
4813 }
4814 }
4815 nibbles += (nibbles.length & 1) ? 'f' : 'ff';
4816 var out = [30];
4817 for (i = 0, ii = nibbles.length; i < ii; i += 2) {
4818 out.push(parseInt(nibbles.substr(i, 2), 16));
4819 }
4820 return out;
4821 },
4822 encodeInteger: function CFFCompiler_encodeInteger(value) {
4823 var code;
4824 if (value >= -107 && value <= 107) {
4825 code = [value + 139];
4826 } else if (value >= 108 && value <= 1131) {
4827 value = value - 108;
4828 code = [(value >> 8) + 247, value & 0xFF];
4829 } else if (value >= -1131 && value <= -108) {
4830 value = -value - 108;
4831 code = [(value >> 8) + 251, value & 0xFF];
4832 } else if (value >= -32768 && value <= 32767) {
4833 code = [0x1c, (value >> 8) & 0xFF, value & 0xFF];
4834 } else {
4835 code = [0x1d,
4836 (value >> 24) & 0xFF,
4837 (value >> 16) & 0xFF,
4838 (value >> 8) & 0xFF,
4839 value & 0xFF];
4840 }
4841 return code;
4842 },
4843 compileHeader: function CFFCompiler_compileHeader(header) {
4844 return [
4845 header.major,
4846 header.minor,
4847 header.hdrSize,
4848 header.offSize
4849 ];
4850 },
4851 compileNameIndex: function CFFCompiler_compileNameIndex(names) {
4852 var nameIndex = new CFFIndex();
4853 for (var i = 0, ii = names.length; i < ii; ++i) {
4854 nameIndex.add(stringToBytes(names[i]));
4855 }
4856 return this.compileIndex(nameIndex);
4857 },
4858 compileTopDicts: function CFFCompiler_compileTopDicts(dicts,
4859 length,
4860 removeCidKeys) {
4861 var fontDictTrackers = [];
4862 var fdArrayIndex = new CFFIndex();
4863 for (var i = 0, ii = dicts.length; i < ii; ++i) {
4864 var fontDict = dicts[i];
4865 if (removeCidKeys) {
4866 fontDict.removeByName('CIDFontVersion');
4867 fontDict.removeByName('CIDFontRevision');
4868 fontDict.removeByName('CIDFontType');
4869 fontDict.removeByName('CIDCount');
4870 fontDict.removeByName('UIDBase');
4871 }
4872 var fontDictTracker = new CFFOffsetTracker();
4873 var fontDictData = this.compileDict(fontDict, fontDictTracker);
4874 fontDictTrackers.push(fontDictTracker);
4875 fdArrayIndex.add(fontDictData);
4876 fontDictTracker.offset(length);
4877 }
4878 fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
4879 return {
4880 trackers: fontDictTrackers,
4881 output: fdArrayIndex
4882 };
4883 },
4884 compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts,
4885 trackers,
4886 output) {
4887 for (var i = 0, ii = dicts.length; i < ii; ++i) {
4888 var fontDict = dicts[i];
4889 assert(fontDict.privateDict && fontDict.hasName('Private'),
4890 'There must be an private dictionary.');
4891 var privateDict = fontDict.privateDict;
4892 var privateDictTracker = new CFFOffsetTracker();
4893 var privateDictData = this.compileDict(privateDict, privateDictTracker);
4894
4895 var outputLength = output.length;
4896 privateDictTracker.offset(outputLength);
4897 if (!privateDictData.length) {
4898 // The private dictionary was empty, set the output length to zero to
4899 // ensure the offset length isn't out of bounds in the eyes of the
4900 // sanitizer.
4901 outputLength = 0;
4902 }
4903
4904 trackers[i].setEntryLocation('Private',
4905 [privateDictData.length, outputLength],
4906 output);
4907 output.add(privateDictData);
4908
4909 if (privateDict.subrsIndex && privateDict.hasName('Subrs')) {
4910 var subrs = this.compileIndex(privateDict.subrsIndex);
4911 privateDictTracker.setEntryLocation('Subrs', [privateDictData.length],
4912 output);
4913 output.add(subrs);
4914 }
4915 }
4916 },
4917 compileDict: function CFFCompiler_compileDict(dict, offsetTracker) {
4918 var out = [];
4919 // The dictionary keys must be in a certain order.
4920 var order = dict.order;
4921 for (var i = 0; i < order.length; ++i) {
4922 var key = order[i];
4923 if (!(key in dict.values)) {
4924 continue;
4925 }
4926 var values = dict.values[key];
4927 var types = dict.types[key];
4928 if (!isArray(types)) {
4929 types = [types];
4930 }
4931 if (!isArray(values)) {
4932 values = [values];
4933 }
4934
4935 // Remove any empty dict values.
4936 if (values.length === 0) {
4937 continue;
4938 }
4939
4940 for (var j = 0, jj = types.length; j < jj; ++j) {
4941 var type = types[j];
4942 var value = values[j];
4943 switch (type) {
4944 case 'num':
4945 case 'sid':
4946 out = out.concat(this.encodeNumber(value));
4947 break;
4948 case 'offset':
4949 // For offsets we just insert a 32bit integer so we don't have to
4950 // deal with figuring out the length of the offset when it gets
4951 // replaced later on by the compiler.
4952 var name = dict.keyToNameMap[key];
4953 // Some offsets have the offset and the length, so just record the
4954 // position of the first one.
4955 if (!offsetTracker.isTracking(name)) {
4956 offsetTracker.track(name, out.length);
4957 }
4958 out = out.concat([0x1d, 0, 0, 0, 0]);
4959 break;
4960 case 'array':
4961 case 'delta':
4962 out = out.concat(this.encodeNumber(value));
4963 for (var k = 1, kk = values.length; k < kk; ++k) {
4964 out = out.concat(this.encodeNumber(values[k]));
4965 }
4966 break;
4967 default:
4968 error('Unknown data type of ' + type);
4969 break;
4970 }
4971 }
4972 out = out.concat(dict.opcodes[key]);
4973 }
4974 return out;
4975 },
4976 compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
4977 var stringIndex = new CFFIndex();
4978 for (var i = 0, ii = strings.length; i < ii; ++i) {
4979 stringIndex.add(stringToBytes(strings[i]));
4980 }
4981 return this.compileIndex(stringIndex);
4982 },
4983 compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
4984 var globalSubrIndex = this.cff.globalSubrIndex;
4985 this.out.writeByteArray(this.compileIndex(globalSubrIndex));
4986 },
4987 compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) {
4988 return this.compileIndex(charStrings);
4989 },
4990 compileCharset: function CFFCompiler_compileCharset(charset) {
4991 return this.compileTypedArray(charset.raw);
4992 },
4993 compileEncoding: function CFFCompiler_compileEncoding(encoding) {
4994 return this.compileTypedArray(encoding.raw);
4995 },
4996 compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) {
4997 return this.compileTypedArray(fdSelect);
4998 },
4999 compileTypedArray: function CFFCompiler_compileTypedArray(data) {
5000 var out = [];
5001 for (var i = 0, ii = data.length; i < ii; ++i) {
5002 out[i] = data[i];
5003 }
5004 return out;
5005 },
5006 compileIndex: function CFFCompiler_compileIndex(index, trackers) {
5007 trackers = trackers || [];
5008 var objects = index.objects;
5009 // First 2 bytes contains the number of objects contained into this index
5010 var count = objects.length;
5011
5012 // If there is no object, just create an index. This technically
5013 // should just be [0, 0] but OTS has an issue with that.
5014 if (count === 0) {
5015 return [0, 0, 0];
5016 }
5017
5018 var data = [(count >> 8) & 0xFF, count & 0xff];
5019
5020 var lastOffset = 1, i;
5021 for (i = 0; i < count; ++i) {
5022 lastOffset += objects[i].length;
5023 }
5024
5025 var offsetSize;
5026 if (lastOffset < 0x100) {
5027 offsetSize = 1;
5028 } else if (lastOffset < 0x10000) {
5029 offsetSize = 2;
5030 } else if (lastOffset < 0x1000000) {
5031 offsetSize = 3;
5032 } else {
5033 offsetSize = 4;
5034 }
5035
5036 // Next byte contains the offset size use to reference object in the file
5037 data.push(offsetSize);
5038
5039 // Add another offset after this one because we need a new offset
5040 var relativeOffset = 1;
5041 for (i = 0; i < count + 1; i++) {
5042 if (offsetSize === 1) {
5043 data.push(relativeOffset & 0xFF);
5044 } else if (offsetSize === 2) {
5045 data.push((relativeOffset >> 8) & 0xFF,
5046 relativeOffset & 0xFF);
5047 } else if (offsetSize === 3) {
5048 data.push((relativeOffset >> 16) & 0xFF,
5049 (relativeOffset >> 8) & 0xFF,
5050 relativeOffset & 0xFF);
5051 } else {
5052 data.push((relativeOffset >>> 24) & 0xFF,
5053 (relativeOffset >> 16) & 0xFF,
5054 (relativeOffset >> 8) & 0xFF,
5055 relativeOffset & 0xFF);
5056 }
5057
5058 if (objects[i]) {
5059 relativeOffset += objects[i].length;
5060 }
5061 }
5062
5063 for (i = 0; i < count; i++) {
5064 // Notify the tracker where the object will be offset in the data.
5065 if (trackers[i]) {
5066 trackers[i].offset(data.length);
5067 }
5068 for (var j = 0, jj = objects[i].length; j < jj; j++) {
5069 data.push(objects[i][j]);
5070 }
5071 }
5072 return data;
5073 }
5074 };
5075 return CFFCompiler;
5076})();
5077
5078exports.CFFStandardStrings = CFFStandardStrings;
5079exports.CFFParser = CFFParser;
5080exports.CFF = CFF;
5081exports.CFFHeader = CFFHeader;
5082exports.CFFStrings = CFFStrings;
5083exports.CFFIndex = CFFIndex;
5084exports.CFFCharset = CFFCharset;
5085exports.CFFTopDict = CFFTopDict;
5086exports.CFFPrivateDict = CFFPrivateDict;
5087exports.CFFCompiler = CFFCompiler;
5088}));
5089
5090
5091(function (root, factory) {
5092 {
5093 factory((root.pdfjsCoreChunkedStream = {}), root.pdfjsSharedUtil);
5094 }
5095}(this, function (exports, sharedUtil) {
5096
5097var MissingDataException = sharedUtil.MissingDataException;
5098var arrayByteLength = sharedUtil.arrayByteLength;
5099var arraysToBytes = sharedUtil.arraysToBytes;
5100var assert = sharedUtil.assert;
5101var createPromiseCapability = sharedUtil.createPromiseCapability;
5102var isInt = sharedUtil.isInt;
5103var isEmptyObj = sharedUtil.isEmptyObj;
5104
5105var ChunkedStream = (function ChunkedStreamClosure() {
5106 function ChunkedStream(length, chunkSize, manager) {
5107 this.bytes = new Uint8Array(length);
5108 this.start = 0;
5109 this.pos = 0;
5110 this.end = length;
5111 this.chunkSize = chunkSize;
5112 this.loadedChunks = [];
5113 this.numChunksLoaded = 0;
5114 this.numChunks = Math.ceil(length / chunkSize);
5115 this.manager = manager;
5116 this.progressiveDataLength = 0;
5117 this.lastSuccessfulEnsureByteChunk = -1; // a single-entry cache
5118 }
5119
5120 // required methods for a stream. if a particular stream does not
5121 // implement these, an error should be thrown
5122 ChunkedStream.prototype = {
5123
5124 getMissingChunks: function ChunkedStream_getMissingChunks() {
5125 var chunks = [];
5126 for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) {
5127 if (!this.loadedChunks[chunk]) {
5128 chunks.push(chunk);
5129 }
5130 }
5131 return chunks;
5132 },
5133
5134 getBaseStreams: function ChunkedStream_getBaseStreams() {
5135 return [this];
5136 },
5137
5138 allChunksLoaded: function ChunkedStream_allChunksLoaded() {
5139 return this.numChunksLoaded === this.numChunks;
5140 },
5141
5142 onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) {
5143 var end = begin + chunk.byteLength;
5144
5145 assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin);
5146 // Using this.length is inaccurate here since this.start can be moved
5147 // See ChunkedStream.moveStart()
5148 var length = this.bytes.length;
5149 assert(end % this.chunkSize === 0 || end === length,
5150 'Bad end offset: ' + end);
5151
5152 this.bytes.set(new Uint8Array(chunk), begin);
5153 var chunkSize = this.chunkSize;
5154 var beginChunk = Math.floor(begin / chunkSize);
5155 var endChunk = Math.floor((end - 1) / chunkSize) + 1;
5156 var curChunk;
5157
5158 for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
5159 if (!this.loadedChunks[curChunk]) {
5160 this.loadedChunks[curChunk] = true;
5161 ++this.numChunksLoaded;
5162 }
5163 }
5164 },
5165
5166 onReceiveProgressiveData:
5167 function ChunkedStream_onReceiveProgressiveData(data) {
5168 var position = this.progressiveDataLength;
5169 var beginChunk = Math.floor(position / this.chunkSize);
5170
5171 this.bytes.set(new Uint8Array(data), position);
5172 position += data.byteLength;
5173 this.progressiveDataLength = position;
5174 var endChunk = position >= this.end ? this.numChunks :
5175 Math.floor(position / this.chunkSize);
5176 var curChunk;
5177 for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
5178 if (!this.loadedChunks[curChunk]) {
5179 this.loadedChunks[curChunk] = true;
5180 ++this.numChunksLoaded;
5181 }
5182 }
5183 },
5184
5185 ensureByte: function ChunkedStream_ensureByte(pos) {
5186 var chunk = Math.floor(pos / this.chunkSize);
5187 if (chunk === this.lastSuccessfulEnsureByteChunk) {
5188 return;
5189 }
5190
5191 if (!this.loadedChunks[chunk]) {
5192 throw new MissingDataException(pos, pos + 1);
5193 }
5194 this.lastSuccessfulEnsureByteChunk = chunk;
5195 },
5196
5197 ensureRange: function ChunkedStream_ensureRange(begin, end) {
5198 if (begin >= end) {
5199 return;
5200 }
5201
5202 if (end <= this.progressiveDataLength) {
5203 return;
5204 }
5205
5206 var chunkSize = this.chunkSize;
5207 var beginChunk = Math.floor(begin / chunkSize);
5208 var endChunk = Math.floor((end - 1) / chunkSize) + 1;
5209 for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
5210 if (!this.loadedChunks[chunk]) {
5211 throw new MissingDataException(begin, end);
5212 }
5213 }
5214 },
5215
5216 nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) {
5217 var chunk, numChunks = this.numChunks;
5218 for (var i = 0; i < numChunks; ++i) {
5219 chunk = (beginChunk + i) % numChunks; // Wrap around to beginning
5220 if (!this.loadedChunks[chunk]) {
5221 return chunk;
5222 }
5223 }
5224 return null;
5225 },
5226
5227 hasChunk: function ChunkedStream_hasChunk(chunk) {
5228 return !!this.loadedChunks[chunk];
5229 },
5230
5231 get length() {
5232 return this.end - this.start;
5233 },
5234
5235 get isEmpty() {
5236 return this.length === 0;
5237 },
5238
5239 getByte: function ChunkedStream_getByte() {
5240 var pos = this.pos;
5241 if (pos >= this.end) {
5242 return -1;
5243 }
5244 this.ensureByte(pos);
5245 return this.bytes[this.pos++];
5246 },
5247
5248 getUint16: function ChunkedStream_getUint16() {
5249 var b0 = this.getByte();
5250 var b1 = this.getByte();
5251 if (b0 === -1 || b1 === -1) {
5252 return -1;
5253 }
5254 return (b0 << 8) + b1;
5255 },
5256
5257 getInt32: function ChunkedStream_getInt32() {
5258 var b0 = this.getByte();
5259 var b1 = this.getByte();
5260 var b2 = this.getByte();
5261 var b3 = this.getByte();
5262 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
5263 },
5264
5265 // returns subarray of original buffer
5266 // should only be read
5267 getBytes: function ChunkedStream_getBytes(length) {
5268 var bytes = this.bytes;
5269 var pos = this.pos;
5270 var strEnd = this.end;
5271
5272 if (!length) {
5273 this.ensureRange(pos, strEnd);
5274 return bytes.subarray(pos, strEnd);
5275 }
5276
5277 var end = pos + length;
5278 if (end > strEnd) {
5279 end = strEnd;
5280 }
5281 this.ensureRange(pos, end);
5282
5283 this.pos = end;
5284 return bytes.subarray(pos, end);
5285 },
5286
5287 peekByte: function ChunkedStream_peekByte() {
5288 var peekedByte = this.getByte();
5289 this.pos--;
5290 return peekedByte;
5291 },
5292
5293 peekBytes: function ChunkedStream_peekBytes(length) {
5294 var bytes = this.getBytes(length);
5295 this.pos -= bytes.length;
5296 return bytes;
5297 },
5298
5299 getByteRange: function ChunkedStream_getBytes(begin, end) {
5300 this.ensureRange(begin, end);
5301 return this.bytes.subarray(begin, end);
5302 },
5303
5304 skip: function ChunkedStream_skip(n) {
5305 if (!n) {
5306 n = 1;
5307 }
5308 this.pos += n;
5309 },
5310
5311 reset: function ChunkedStream_reset() {
5312 this.pos = this.start;
5313 },
5314
5315 moveStart: function ChunkedStream_moveStart() {
5316 this.start = this.pos;
5317 },
5318
5319 makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) {
5320 this.ensureRange(start, start + length);
5321
5322 function ChunkedStreamSubstream() {}
5323 ChunkedStreamSubstream.prototype = Object.create(this);
5324 ChunkedStreamSubstream.prototype.getMissingChunks = function() {
5325 var chunkSize = this.chunkSize;
5326 var beginChunk = Math.floor(this.start / chunkSize);
5327 var endChunk = Math.floor((this.end - 1) / chunkSize) + 1;
5328 var missingChunks = [];
5329 for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
5330 if (!this.loadedChunks[chunk]) {
5331 missingChunks.push(chunk);
5332 }
5333 }
5334 return missingChunks;
5335 };
5336 var subStream = new ChunkedStreamSubstream();
5337 subStream.pos = subStream.start = start;
5338 subStream.end = start + length || this.end;
5339 subStream.dict = dict;
5340 return subStream;
5341 },
5342
5343 isStream: true
5344 };
5345
5346 return ChunkedStream;
5347})();
5348
5349var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
5350
5351 function ChunkedStreamManager(pdfNetworkStream, args) {
5352 var chunkSize = args.rangeChunkSize;
5353 var length = args.length;
5354 this.stream = new ChunkedStream(length, chunkSize, this);
5355 this.length = length;
5356 this.chunkSize = chunkSize;
5357 this.pdfNetworkStream = pdfNetworkStream;
5358 this.url = args.url;
5359 this.disableAutoFetch = args.disableAutoFetch;
5360 this.msgHandler = args.msgHandler;
5361
5362 this.currRequestId = 0;
5363
5364 this.chunksNeededByRequest = Object.create(null);
5365 this.requestsByChunk = Object.create(null);
5366 this.promisesByRequest = Object.create(null);
5367 this.progressiveDataLength = 0;
5368 this.aborted = false;
5369
5370 this._loadedStreamCapability = createPromiseCapability();
5371 }
5372
5373 ChunkedStreamManager.prototype = {
5374 onLoadedStream: function ChunkedStreamManager_getLoadedStream() {
5375 return this._loadedStreamCapability.promise;
5376 },
5377
5378 sendRequest: function ChunkedStreamManager_sendRequest(begin, end) {
5379 var rangeReader = this.pdfNetworkStream.getRangeReader(begin, end);
5380 if (!rangeReader.isStreamingSupported) {
5381 rangeReader.onProgress = this.onProgress.bind(this);
5382 }
5383 var chunks = [], loaded = 0;
5384 var manager = this;
5385 var promise = new Promise(function (resolve, reject) {
5386 var readChunk = function (chunk) {
5387 try {
5388 if (!chunk.done) {
5389 var data = chunk.value;
5390 chunks.push(data);
5391 loaded += arrayByteLength(data);
5392 if (rangeReader.isStreamingSupported) {
5393 manager.onProgress({loaded: loaded});
5394 }
5395 rangeReader.read().then(readChunk, reject);
5396 return;
5397 }
5398 var chunkData = arraysToBytes(chunks);
5399 chunks = null;
5400 resolve(chunkData);
5401 } catch (e) {
5402 reject(e);
5403 }
5404 };
5405 rangeReader.read().then(readChunk, reject);
5406 });
5407 promise.then(function (data) {
5408 if (this.aborted) {
5409 return; // ignoring any data after abort
5410 }
5411 this.onReceiveData({chunk: data, begin: begin});
5412 }.bind(this));
5413 // TODO check errors
5414 },
5415
5416 // Get all the chunks that are not yet loaded and groups them into
5417 // contiguous ranges to load in as few requests as possible
5418 requestAllChunks: function ChunkedStreamManager_requestAllChunks() {
5419 var missingChunks = this.stream.getMissingChunks();
5420 this._requestChunks(missingChunks);
5421 return this._loadedStreamCapability.promise;
5422 },
5423
5424 _requestChunks: function ChunkedStreamManager_requestChunks(chunks) {
5425 var requestId = this.currRequestId++;
5426
5427 var i, ii;
5428 var chunksNeeded = Object.create(null);
5429 this.chunksNeededByRequest[requestId] = chunksNeeded;
5430 for (i = 0, ii = chunks.length; i < ii; i++) {
5431 if (!this.stream.hasChunk(chunks[i])) {
5432 chunksNeeded[chunks[i]] = true;
5433 }
5434 }
5435
5436 if (isEmptyObj(chunksNeeded)) {
5437 return Promise.resolve();
5438 }
5439
5440 var capability = createPromiseCapability();
5441 this.promisesByRequest[requestId] = capability;
5442
5443 var chunksToRequest = [];
5444 for (var chunk in chunksNeeded) {
5445 chunk = chunk | 0;
5446 if (!(chunk in this.requestsByChunk)) {
5447 this.requestsByChunk[chunk] = [];
5448 chunksToRequest.push(chunk);
5449 }
5450 this.requestsByChunk[chunk].push(requestId);
5451 }
5452
5453 if (!chunksToRequest.length) {
5454 return capability.promise;
5455 }
5456
5457 var groupedChunksToRequest = this.groupChunks(chunksToRequest);
5458
5459 for (i = 0; i < groupedChunksToRequest.length; ++i) {
5460 var groupedChunk = groupedChunksToRequest[i];
5461 var begin = groupedChunk.beginChunk * this.chunkSize;
5462 var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length);
5463 this.sendRequest(begin, end);
5464 }
5465
5466 return capability.promise;
5467 },
5468
5469 getStream: function ChunkedStreamManager_getStream() {
5470 return this.stream;
5471 },
5472
5473 // Loads any chunks in the requested range that are not yet loaded
5474 requestRange: function ChunkedStreamManager_requestRange(begin, end) {
5475
5476 end = Math.min(end, this.length);
5477
5478 var beginChunk = this.getBeginChunk(begin);
5479 var endChunk = this.getEndChunk(end);
5480
5481 var chunks = [];
5482 for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
5483 chunks.push(chunk);
5484 }
5485
5486 return this._requestChunks(chunks);
5487 },
5488
5489 requestRanges: function ChunkedStreamManager_requestRanges(ranges) {
5490 ranges = ranges || [];
5491 var chunksToRequest = [];
5492
5493 for (var i = 0; i < ranges.length; i++) {
5494 var beginChunk = this.getBeginChunk(ranges[i].begin);
5495 var endChunk = this.getEndChunk(ranges[i].end);
5496 for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
5497 if (chunksToRequest.indexOf(chunk) < 0) {
5498 chunksToRequest.push(chunk);
5499 }
5500 }
5501 }
5502
5503 chunksToRequest.sort(function(a, b) { return a - b; });
5504 return this._requestChunks(chunksToRequest);
5505 },
5506
5507 // Groups a sorted array of chunks into as few contiguous larger
5508 // chunks as possible
5509 groupChunks: function ChunkedStreamManager_groupChunks(chunks) {
5510 var groupedChunks = [];
5511 var beginChunk = -1;
5512 var prevChunk = -1;
5513 for (var i = 0; i < chunks.length; ++i) {
5514 var chunk = chunks[i];
5515
5516 if (beginChunk < 0) {
5517 beginChunk = chunk;
5518 }
5519
5520 if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
5521 groupedChunks.push({ beginChunk: beginChunk,
5522 endChunk: prevChunk + 1 });
5523 beginChunk = chunk;
5524 }
5525 if (i + 1 === chunks.length) {
5526 groupedChunks.push({ beginChunk: beginChunk,
5527 endChunk: chunk + 1 });
5528 }
5529
5530 prevChunk = chunk;
5531 }
5532 return groupedChunks;
5533 },
5534
5535 onProgress: function ChunkedStreamManager_onProgress(args) {
5536 var bytesLoaded = (this.stream.numChunksLoaded * this.chunkSize +
5537 args.loaded);
5538 this.msgHandler.send('DocProgress', {
5539 loaded: bytesLoaded,
5540 total: this.length
5541 });
5542 },
5543
5544 onReceiveData: function ChunkedStreamManager_onReceiveData(args) {
5545 var chunk = args.chunk;
5546 var isProgressive = args.begin === undefined;
5547 var begin = isProgressive ? this.progressiveDataLength : args.begin;
5548 var end = begin + chunk.byteLength;
5549
5550 var beginChunk = Math.floor(begin / this.chunkSize);
5551 var endChunk = end < this.length ? Math.floor(end / this.chunkSize) :
5552 Math.ceil(end / this.chunkSize);
5553
5554 if (isProgressive) {
5555 this.stream.onReceiveProgressiveData(chunk);
5556 this.progressiveDataLength = end;
5557 } else {
5558 this.stream.onReceiveData(begin, chunk);
5559 }
5560
5561 if (this.stream.allChunksLoaded()) {
5562 this._loadedStreamCapability.resolve(this.stream);
5563 }
5564
5565 var loadedRequests = [];
5566 var i, requestId;
5567 for (chunk = beginChunk; chunk < endChunk; ++chunk) {
5568 // The server might return more chunks than requested
5569 var requestIds = this.requestsByChunk[chunk] || [];
5570 delete this.requestsByChunk[chunk];
5571
5572 for (i = 0; i < requestIds.length; ++i) {
5573 requestId = requestIds[i];
5574 var chunksNeeded = this.chunksNeededByRequest[requestId];
5575 if (chunk in chunksNeeded) {
5576 delete chunksNeeded[chunk];
5577 }
5578
5579 if (!isEmptyObj(chunksNeeded)) {
5580 continue;
5581 }
5582
5583 loadedRequests.push(requestId);
5584 }
5585 }
5586
5587 // If there are no pending requests, automatically fetch the next
5588 // unfetched chunk of the PDF
5589 if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) {
5590 var nextEmptyChunk;
5591 if (this.stream.numChunksLoaded === 1) {
5592 // This is a special optimization so that after fetching the first
5593 // chunk, rather than fetching the second chunk, we fetch the last
5594 // chunk.
5595 var lastChunk = this.stream.numChunks - 1;
5596 if (!this.stream.hasChunk(lastChunk)) {
5597 nextEmptyChunk = lastChunk;
5598 }
5599 } else {
5600 nextEmptyChunk = this.stream.nextEmptyChunk(endChunk);
5601 }
5602 if (isInt(nextEmptyChunk)) {
5603 this._requestChunks([nextEmptyChunk]);
5604 }
5605 }
5606
5607 for (i = 0; i < loadedRequests.length; ++i) {
5608 requestId = loadedRequests[i];
5609 var capability = this.promisesByRequest[requestId];
5610 delete this.promisesByRequest[requestId];
5611 capability.resolve();
5612 }
5613
5614 this.msgHandler.send('DocProgress', {
5615 loaded: this.stream.numChunksLoaded * this.chunkSize,
5616 total: this.length
5617 });
5618 },
5619
5620 onError: function ChunkedStreamManager_onError(err) {
5621 this._loadedStreamCapability.reject(err);
5622 },
5623
5624 getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) {
5625 var chunk = Math.floor(begin / this.chunkSize);
5626 return chunk;
5627 },
5628
5629 getEndChunk: function ChunkedStreamManager_getEndChunk(end) {
5630 var chunk = Math.floor((end - 1) / this.chunkSize) + 1;
5631 return chunk;
5632 },
5633
5634 abort: function ChunkedStreamManager_abort() {
5635 this.aborted = true;
5636 if (this.pdfNetworkStream) {
5637 this.pdfNetworkStream.cancelAllRequests('abort');
5638 }
5639 for(var requestId in this.promisesByRequest) {
5640 var capability = this.promisesByRequest[requestId];
5641 capability.reject(new Error('Request was aborted'));
5642 }
5643 }
5644 };
5645
5646 return ChunkedStreamManager;
5647})();
5648
5649exports.ChunkedStream = ChunkedStream;
5650exports.ChunkedStreamManager = ChunkedStreamManager;
5651}));
5652
5653
5654(function (root, factory) {
5655 {
5656 factory((root.pdfjsCoreGlyphList = {}), root.pdfjsSharedUtil);
5657 }
5658}(this, function (exports, sharedUtil) {
5659var getLookupTableFactory = sharedUtil.getLookupTableFactory;
5660
5661var getGlyphsUnicode = getLookupTableFactory(function (t) {
5662 t['A'] = 0x0041;
5663 t['AE'] = 0x00C6;
5664 t['AEacute'] = 0x01FC;
5665 t['AEmacron'] = 0x01E2;
5666 t['AEsmall'] = 0xF7E6;
5667 t['Aacute'] = 0x00C1;
5668 t['Aacutesmall'] = 0xF7E1;
5669 t['Abreve'] = 0x0102;
5670 t['Abreveacute'] = 0x1EAE;
5671 t['Abrevecyrillic'] = 0x04D0;
5672 t['Abrevedotbelow'] = 0x1EB6;
5673 t['Abrevegrave'] = 0x1EB0;
5674 t['Abrevehookabove'] = 0x1EB2;
5675 t['Abrevetilde'] = 0x1EB4;
5676 t['Acaron'] = 0x01CD;
5677 t['Acircle'] = 0x24B6;
5678 t['Acircumflex'] = 0x00C2;
5679 t['Acircumflexacute'] = 0x1EA4;
5680 t['Acircumflexdotbelow'] = 0x1EAC;
5681 t['Acircumflexgrave'] = 0x1EA6;
5682 t['Acircumflexhookabove'] = 0x1EA8;
5683 t['Acircumflexsmall'] = 0xF7E2;
5684 t['Acircumflextilde'] = 0x1EAA;
5685 t['Acute'] = 0xF6C9;
5686 t['Acutesmall'] = 0xF7B4;
5687 t['Acyrillic'] = 0x0410;
5688 t['Adblgrave'] = 0x0200;
5689 t['Adieresis'] = 0x00C4;
5690 t['Adieresiscyrillic'] = 0x04D2;
5691 t['Adieresismacron'] = 0x01DE;
5692 t['Adieresissmall'] = 0xF7E4;
5693 t['Adotbelow'] = 0x1EA0;
5694 t['Adotmacron'] = 0x01E0;
5695 t['Agrave'] = 0x00C0;
5696 t['Agravesmall'] = 0xF7E0;
5697 t['Ahookabove'] = 0x1EA2;
5698 t['Aiecyrillic'] = 0x04D4;
5699 t['Ainvertedbreve'] = 0x0202;
5700 t['Alpha'] = 0x0391;
5701 t['Alphatonos'] = 0x0386;
5702 t['Amacron'] = 0x0100;
5703 t['Amonospace'] = 0xFF21;
5704 t['Aogonek'] = 0x0104;
5705 t['Aring'] = 0x00C5;
5706 t['Aringacute'] = 0x01FA;
5707 t['Aringbelow'] = 0x1E00;
5708 t['Aringsmall'] = 0xF7E5;
5709 t['Asmall'] = 0xF761;
5710 t['Atilde'] = 0x00C3;
5711 t['Atildesmall'] = 0xF7E3;
5712 t['Aybarmenian'] = 0x0531;
5713 t['B'] = 0x0042;
5714 t['Bcircle'] = 0x24B7;
5715 t['Bdotaccent'] = 0x1E02;
5716 t['Bdotbelow'] = 0x1E04;
5717 t['Becyrillic'] = 0x0411;
5718 t['Benarmenian'] = 0x0532;
5719 t['Beta'] = 0x0392;
5720 t['Bhook'] = 0x0181;
5721 t['Blinebelow'] = 0x1E06;
5722 t['Bmonospace'] = 0xFF22;
5723 t['Brevesmall'] = 0xF6F4;
5724 t['Bsmall'] = 0xF762;
5725 t['Btopbar'] = 0x0182;
5726 t['C'] = 0x0043;
5727 t['Caarmenian'] = 0x053E;
5728 t['Cacute'] = 0x0106;
5729 t['Caron'] = 0xF6CA;
5730 t['Caronsmall'] = 0xF6F5;
5731 t['Ccaron'] = 0x010C;
5732 t['Ccedilla'] = 0x00C7;
5733 t['Ccedillaacute'] = 0x1E08;
5734 t['Ccedillasmall'] = 0xF7E7;
5735 t['Ccircle'] = 0x24B8;
5736 t['Ccircumflex'] = 0x0108;
5737 t['Cdot'] = 0x010A;
5738 t['Cdotaccent'] = 0x010A;
5739 t['Cedillasmall'] = 0xF7B8;
5740 t['Chaarmenian'] = 0x0549;
5741 t['Cheabkhasiancyrillic'] = 0x04BC;
5742 t['Checyrillic'] = 0x0427;
5743 t['Chedescenderabkhasiancyrillic'] = 0x04BE;
5744 t['Chedescendercyrillic'] = 0x04B6;
5745 t['Chedieresiscyrillic'] = 0x04F4;
5746 t['Cheharmenian'] = 0x0543;
5747 t['Chekhakassiancyrillic'] = 0x04CB;
5748 t['Cheverticalstrokecyrillic'] = 0x04B8;
5749 t['Chi'] = 0x03A7;
5750 t['Chook'] = 0x0187;
5751 t['Circumflexsmall'] = 0xF6F6;
5752 t['Cmonospace'] = 0xFF23;
5753 t['Coarmenian'] = 0x0551;
5754 t['Csmall'] = 0xF763;
5755 t['D'] = 0x0044;
5756 t['DZ'] = 0x01F1;
5757 t['DZcaron'] = 0x01C4;
5758 t['Daarmenian'] = 0x0534;
5759 t['Dafrican'] = 0x0189;
5760 t['Dcaron'] = 0x010E;
5761 t['Dcedilla'] = 0x1E10;
5762 t['Dcircle'] = 0x24B9;
5763 t['Dcircumflexbelow'] = 0x1E12;
5764 t['Dcroat'] = 0x0110;
5765 t['Ddotaccent'] = 0x1E0A;
5766 t['Ddotbelow'] = 0x1E0C;
5767 t['Decyrillic'] = 0x0414;
5768 t['Deicoptic'] = 0x03EE;
5769 t['Delta'] = 0x2206;
5770 t['Deltagreek'] = 0x0394;
5771 t['Dhook'] = 0x018A;
5772 t['Dieresis'] = 0xF6CB;
5773 t['DieresisAcute'] = 0xF6CC;
5774 t['DieresisGrave'] = 0xF6CD;
5775 t['Dieresissmall'] = 0xF7A8;
5776 t['Digammagreek'] = 0x03DC;
5777 t['Djecyrillic'] = 0x0402;
5778 t['Dlinebelow'] = 0x1E0E;
5779 t['Dmonospace'] = 0xFF24;
5780 t['Dotaccentsmall'] = 0xF6F7;
5781 t['Dslash'] = 0x0110;
5782 t['Dsmall'] = 0xF764;
5783 t['Dtopbar'] = 0x018B;
5784 t['Dz'] = 0x01F2;
5785 t['Dzcaron'] = 0x01C5;
5786 t['Dzeabkhasiancyrillic'] = 0x04E0;
5787 t['Dzecyrillic'] = 0x0405;
5788 t['Dzhecyrillic'] = 0x040F;
5789 t['E'] = 0x0045;
5790 t['Eacute'] = 0x00C9;
5791 t['Eacutesmall'] = 0xF7E9;
5792 t['Ebreve'] = 0x0114;
5793 t['Ecaron'] = 0x011A;
5794 t['Ecedillabreve'] = 0x1E1C;
5795 t['Echarmenian'] = 0x0535;
5796 t['Ecircle'] = 0x24BA;
5797 t['Ecircumflex'] = 0x00CA;
5798 t['Ecircumflexacute'] = 0x1EBE;
5799 t['Ecircumflexbelow'] = 0x1E18;
5800 t['Ecircumflexdotbelow'] = 0x1EC6;
5801 t['Ecircumflexgrave'] = 0x1EC0;
5802 t['Ecircumflexhookabove'] = 0x1EC2;
5803 t['Ecircumflexsmall'] = 0xF7EA;
5804 t['Ecircumflextilde'] = 0x1EC4;
5805 t['Ecyrillic'] = 0x0404;
5806 t['Edblgrave'] = 0x0204;
5807 t['Edieresis'] = 0x00CB;
5808 t['Edieresissmall'] = 0xF7EB;
5809 t['Edot'] = 0x0116;
5810 t['Edotaccent'] = 0x0116;
5811 t['Edotbelow'] = 0x1EB8;
5812 t['Efcyrillic'] = 0x0424;
5813 t['Egrave'] = 0x00C8;
5814 t['Egravesmall'] = 0xF7E8;
5815 t['Eharmenian'] = 0x0537;
5816 t['Ehookabove'] = 0x1EBA;
5817 t['Eightroman'] = 0x2167;
5818 t['Einvertedbreve'] = 0x0206;
5819 t['Eiotifiedcyrillic'] = 0x0464;
5820 t['Elcyrillic'] = 0x041B;
5821 t['Elevenroman'] = 0x216A;
5822 t['Emacron'] = 0x0112;
5823 t['Emacronacute'] = 0x1E16;
5824 t['Emacrongrave'] = 0x1E14;
5825 t['Emcyrillic'] = 0x041C;
5826 t['Emonospace'] = 0xFF25;
5827 t['Encyrillic'] = 0x041D;
5828 t['Endescendercyrillic'] = 0x04A2;
5829 t['Eng'] = 0x014A;
5830 t['Enghecyrillic'] = 0x04A4;
5831 t['Enhookcyrillic'] = 0x04C7;
5832 t['Eogonek'] = 0x0118;
5833 t['Eopen'] = 0x0190;
5834 t['Epsilon'] = 0x0395;
5835 t['Epsilontonos'] = 0x0388;
5836 t['Ercyrillic'] = 0x0420;
5837 t['Ereversed'] = 0x018E;
5838 t['Ereversedcyrillic'] = 0x042D;
5839 t['Escyrillic'] = 0x0421;
5840 t['Esdescendercyrillic'] = 0x04AA;
5841 t['Esh'] = 0x01A9;
5842 t['Esmall'] = 0xF765;
5843 t['Eta'] = 0x0397;
5844 t['Etarmenian'] = 0x0538;
5845 t['Etatonos'] = 0x0389;
5846 t['Eth'] = 0x00D0;
5847 t['Ethsmall'] = 0xF7F0;
5848 t['Etilde'] = 0x1EBC;
5849 t['Etildebelow'] = 0x1E1A;
5850 t['Euro'] = 0x20AC;
5851 t['Ezh'] = 0x01B7;
5852 t['Ezhcaron'] = 0x01EE;
5853 t['Ezhreversed'] = 0x01B8;
5854 t['F'] = 0x0046;
5855 t['Fcircle'] = 0x24BB;
5856 t['Fdotaccent'] = 0x1E1E;
5857 t['Feharmenian'] = 0x0556;
5858 t['Feicoptic'] = 0x03E4;
5859 t['Fhook'] = 0x0191;
5860 t['Fitacyrillic'] = 0x0472;
5861 t['Fiveroman'] = 0x2164;
5862 t['Fmonospace'] = 0xFF26;
5863 t['Fourroman'] = 0x2163;
5864 t['Fsmall'] = 0xF766;
5865 t['G'] = 0x0047;
5866 t['GBsquare'] = 0x3387;
5867 t['Gacute'] = 0x01F4;
5868 t['Gamma'] = 0x0393;
5869 t['Gammaafrican'] = 0x0194;
5870 t['Gangiacoptic'] = 0x03EA;
5871 t['Gbreve'] = 0x011E;
5872 t['Gcaron'] = 0x01E6;
5873 t['Gcedilla'] = 0x0122;
5874 t['Gcircle'] = 0x24BC;
5875 t['Gcircumflex'] = 0x011C;
5876 t['Gcommaaccent'] = 0x0122;
5877 t['Gdot'] = 0x0120;
5878 t['Gdotaccent'] = 0x0120;
5879 t['Gecyrillic'] = 0x0413;
5880 t['Ghadarmenian'] = 0x0542;
5881 t['Ghemiddlehookcyrillic'] = 0x0494;
5882 t['Ghestrokecyrillic'] = 0x0492;
5883 t['Gheupturncyrillic'] = 0x0490;
5884 t['Ghook'] = 0x0193;
5885 t['Gimarmenian'] = 0x0533;
5886 t['Gjecyrillic'] = 0x0403;
5887 t['Gmacron'] = 0x1E20;
5888 t['Gmonospace'] = 0xFF27;
5889 t['Grave'] = 0xF6CE;
5890 t['Gravesmall'] = 0xF760;
5891 t['Gsmall'] = 0xF767;
5892 t['Gsmallhook'] = 0x029B;
5893 t['Gstroke'] = 0x01E4;
5894 t['H'] = 0x0048;
5895 t['H18533'] = 0x25CF;
5896 t['H18543'] = 0x25AA;
5897 t['H18551'] = 0x25AB;
5898 t['H22073'] = 0x25A1;
5899 t['HPsquare'] = 0x33CB;
5900 t['Haabkhasiancyrillic'] = 0x04A8;
5901 t['Hadescendercyrillic'] = 0x04B2;
5902 t['Hardsigncyrillic'] = 0x042A;
5903 t['Hbar'] = 0x0126;
5904 t['Hbrevebelow'] = 0x1E2A;
5905 t['Hcedilla'] = 0x1E28;
5906 t['Hcircle'] = 0x24BD;
5907 t['Hcircumflex'] = 0x0124;
5908 t['Hdieresis'] = 0x1E26;
5909 t['Hdotaccent'] = 0x1E22;
5910 t['Hdotbelow'] = 0x1E24;
5911 t['Hmonospace'] = 0xFF28;
5912 t['Hoarmenian'] = 0x0540;
5913 t['Horicoptic'] = 0x03E8;
5914 t['Hsmall'] = 0xF768;
5915 t['Hungarumlaut'] = 0xF6CF;
5916 t['Hungarumlautsmall'] = 0xF6F8;
5917 t['Hzsquare'] = 0x3390;
5918 t['I'] = 0x0049;
5919 t['IAcyrillic'] = 0x042F;
5920 t['IJ'] = 0x0132;
5921 t['IUcyrillic'] = 0x042E;
5922 t['Iacute'] = 0x00CD;
5923 t['Iacutesmall'] = 0xF7ED;
5924 t['Ibreve'] = 0x012C;
5925 t['Icaron'] = 0x01CF;
5926 t['Icircle'] = 0x24BE;
5927 t['Icircumflex'] = 0x00CE;
5928 t['Icircumflexsmall'] = 0xF7EE;
5929 t['Icyrillic'] = 0x0406;
5930 t['Idblgrave'] = 0x0208;
5931 t['Idieresis'] = 0x00CF;
5932 t['Idieresisacute'] = 0x1E2E;
5933 t['Idieresiscyrillic'] = 0x04E4;
5934 t['Idieresissmall'] = 0xF7EF;
5935 t['Idot'] = 0x0130;
5936 t['Idotaccent'] = 0x0130;
5937 t['Idotbelow'] = 0x1ECA;
5938 t['Iebrevecyrillic'] = 0x04D6;
5939 t['Iecyrillic'] = 0x0415;
5940 t['Ifraktur'] = 0x2111;
5941 t['Igrave'] = 0x00CC;
5942 t['Igravesmall'] = 0xF7EC;
5943 t['Ihookabove'] = 0x1EC8;
5944 t['Iicyrillic'] = 0x0418;
5945 t['Iinvertedbreve'] = 0x020A;
5946 t['Iishortcyrillic'] = 0x0419;
5947 t['Imacron'] = 0x012A;
5948 t['Imacroncyrillic'] = 0x04E2;
5949 t['Imonospace'] = 0xFF29;
5950 t['Iniarmenian'] = 0x053B;
5951 t['Iocyrillic'] = 0x0401;
5952 t['Iogonek'] = 0x012E;
5953 t['Iota'] = 0x0399;
5954 t['Iotaafrican'] = 0x0196;
5955 t['Iotadieresis'] = 0x03AA;
5956 t['Iotatonos'] = 0x038A;
5957 t['Ismall'] = 0xF769;
5958 t['Istroke'] = 0x0197;
5959 t['Itilde'] = 0x0128;
5960 t['Itildebelow'] = 0x1E2C;
5961 t['Izhitsacyrillic'] = 0x0474;
5962 t['Izhitsadblgravecyrillic'] = 0x0476;
5963 t['J'] = 0x004A;
5964 t['Jaarmenian'] = 0x0541;
5965 t['Jcircle'] = 0x24BF;
5966 t['Jcircumflex'] = 0x0134;
5967 t['Jecyrillic'] = 0x0408;
5968 t['Jheharmenian'] = 0x054B;
5969 t['Jmonospace'] = 0xFF2A;
5970 t['Jsmall'] = 0xF76A;
5971 t['K'] = 0x004B;
5972 t['KBsquare'] = 0x3385;
5973 t['KKsquare'] = 0x33CD;
5974 t['Kabashkircyrillic'] = 0x04A0;
5975 t['Kacute'] = 0x1E30;
5976 t['Kacyrillic'] = 0x041A;
5977 t['Kadescendercyrillic'] = 0x049A;
5978 t['Kahookcyrillic'] = 0x04C3;
5979 t['Kappa'] = 0x039A;
5980 t['Kastrokecyrillic'] = 0x049E;
5981 t['Kaverticalstrokecyrillic'] = 0x049C;
5982 t['Kcaron'] = 0x01E8;
5983 t['Kcedilla'] = 0x0136;
5984 t['Kcircle'] = 0x24C0;
5985 t['Kcommaaccent'] = 0x0136;
5986 t['Kdotbelow'] = 0x1E32;
5987 t['Keharmenian'] = 0x0554;
5988 t['Kenarmenian'] = 0x053F;
5989 t['Khacyrillic'] = 0x0425;
5990 t['Kheicoptic'] = 0x03E6;
5991 t['Khook'] = 0x0198;
5992 t['Kjecyrillic'] = 0x040C;
5993 t['Klinebelow'] = 0x1E34;
5994 t['Kmonospace'] = 0xFF2B;
5995 t['Koppacyrillic'] = 0x0480;
5996 t['Koppagreek'] = 0x03DE;
5997 t['Ksicyrillic'] = 0x046E;
5998 t['Ksmall'] = 0xF76B;
5999 t['L'] = 0x004C;
6000 t['LJ'] = 0x01C7;
6001 t['LL'] = 0xF6BF;
6002 t['Lacute'] = 0x0139;
6003 t['Lambda'] = 0x039B;
6004 t['Lcaron'] = 0x013D;
6005 t['Lcedilla'] = 0x013B;
6006 t['Lcircle'] = 0x24C1;
6007 t['Lcircumflexbelow'] = 0x1E3C;
6008 t['Lcommaaccent'] = 0x013B;
6009 t['Ldot'] = 0x013F;
6010 t['Ldotaccent'] = 0x013F;
6011 t['Ldotbelow'] = 0x1E36;
6012 t['Ldotbelowmacron'] = 0x1E38;
6013 t['Liwnarmenian'] = 0x053C;
6014 t['Lj'] = 0x01C8;
6015 t['Ljecyrillic'] = 0x0409;
6016 t['Llinebelow'] = 0x1E3A;
6017 t['Lmonospace'] = 0xFF2C;
6018 t['Lslash'] = 0x0141;
6019 t['Lslashsmall'] = 0xF6F9;
6020 t['Lsmall'] = 0xF76C;
6021 t['M'] = 0x004D;
6022 t['MBsquare'] = 0x3386;
6023 t['Macron'] = 0xF6D0;
6024 t['Macronsmall'] = 0xF7AF;
6025 t['Macute'] = 0x1E3E;
6026 t['Mcircle'] = 0x24C2;
6027 t['Mdotaccent'] = 0x1E40;
6028 t['Mdotbelow'] = 0x1E42;
6029 t['Menarmenian'] = 0x0544;
6030 t['Mmonospace'] = 0xFF2D;
6031 t['Msmall'] = 0xF76D;
6032 t['Mturned'] = 0x019C;
6033 t['Mu'] = 0x039C;
6034 t['N'] = 0x004E;
6035 t['NJ'] = 0x01CA;
6036 t['Nacute'] = 0x0143;
6037 t['Ncaron'] = 0x0147;
6038 t['Ncedilla'] = 0x0145;
6039 t['Ncircle'] = 0x24C3;
6040 t['Ncircumflexbelow'] = 0x1E4A;
6041 t['Ncommaaccent'] = 0x0145;
6042 t['Ndotaccent'] = 0x1E44;
6043 t['Ndotbelow'] = 0x1E46;
6044 t['Nhookleft'] = 0x019D;
6045 t['Nineroman'] = 0x2168;
6046 t['Nj'] = 0x01CB;
6047 t['Njecyrillic'] = 0x040A;
6048 t['Nlinebelow'] = 0x1E48;
6049 t['Nmonospace'] = 0xFF2E;
6050 t['Nowarmenian'] = 0x0546;
6051 t['Nsmall'] = 0xF76E;
6052 t['Ntilde'] = 0x00D1;
6053 t['Ntildesmall'] = 0xF7F1;
6054 t['Nu'] = 0x039D;
6055 t['O'] = 0x004F;
6056 t['OE'] = 0x0152;
6057 t['OEsmall'] = 0xF6FA;
6058 t['Oacute'] = 0x00D3;
6059 t['Oacutesmall'] = 0xF7F3;
6060 t['Obarredcyrillic'] = 0x04E8;
6061 t['Obarreddieresiscyrillic'] = 0x04EA;
6062 t['Obreve'] = 0x014E;
6063 t['Ocaron'] = 0x01D1;
6064 t['Ocenteredtilde'] = 0x019F;
6065 t['Ocircle'] = 0x24C4;
6066 t['Ocircumflex'] = 0x00D4;
6067 t['Ocircumflexacute'] = 0x1ED0;
6068 t['Ocircumflexdotbelow'] = 0x1ED8;
6069 t['Ocircumflexgrave'] = 0x1ED2;
6070 t['Ocircumflexhookabove'] = 0x1ED4;
6071 t['Ocircumflexsmall'] = 0xF7F4;
6072 t['Ocircumflextilde'] = 0x1ED6;
6073 t['Ocyrillic'] = 0x041E;
6074 t['Odblacute'] = 0x0150;
6075 t['Odblgrave'] = 0x020C;
6076 t['Odieresis'] = 0x00D6;
6077 t['Odieresiscyrillic'] = 0x04E6;
6078 t['Odieresissmall'] = 0xF7F6;
6079 t['Odotbelow'] = 0x1ECC;
6080 t['Ogoneksmall'] = 0xF6FB;
6081 t['Ograve'] = 0x00D2;
6082 t['Ogravesmall'] = 0xF7F2;
6083 t['Oharmenian'] = 0x0555;
6084 t['Ohm'] = 0x2126;
6085 t['Ohookabove'] = 0x1ECE;
6086 t['Ohorn'] = 0x01A0;
6087 t['Ohornacute'] = 0x1EDA;
6088 t['Ohorndotbelow'] = 0x1EE2;
6089 t['Ohorngrave'] = 0x1EDC;
6090 t['Ohornhookabove'] = 0x1EDE;
6091 t['Ohorntilde'] = 0x1EE0;
6092 t['Ohungarumlaut'] = 0x0150;
6093 t['Oi'] = 0x01A2;
6094 t['Oinvertedbreve'] = 0x020E;
6095 t['Omacron'] = 0x014C;
6096 t['Omacronacute'] = 0x1E52;
6097 t['Omacrongrave'] = 0x1E50;
6098 t['Omega'] = 0x2126;
6099 t['Omegacyrillic'] = 0x0460;
6100 t['Omegagreek'] = 0x03A9;
6101 t['Omegaroundcyrillic'] = 0x047A;
6102 t['Omegatitlocyrillic'] = 0x047C;
6103 t['Omegatonos'] = 0x038F;
6104 t['Omicron'] = 0x039F;
6105 t['Omicrontonos'] = 0x038C;
6106 t['Omonospace'] = 0xFF2F;
6107 t['Oneroman'] = 0x2160;
6108 t['Oogonek'] = 0x01EA;
6109 t['Oogonekmacron'] = 0x01EC;
6110 t['Oopen'] = 0x0186;
6111 t['Oslash'] = 0x00D8;
6112 t['Oslashacute'] = 0x01FE;
6113 t['Oslashsmall'] = 0xF7F8;
6114 t['Osmall'] = 0xF76F;
6115 t['Ostrokeacute'] = 0x01FE;
6116 t['Otcyrillic'] = 0x047E;
6117 t['Otilde'] = 0x00D5;
6118 t['Otildeacute'] = 0x1E4C;
6119 t['Otildedieresis'] = 0x1E4E;
6120 t['Otildesmall'] = 0xF7F5;
6121 t['P'] = 0x0050;
6122 t['Pacute'] = 0x1E54;
6123 t['Pcircle'] = 0x24C5;
6124 t['Pdotaccent'] = 0x1E56;
6125 t['Pecyrillic'] = 0x041F;
6126 t['Peharmenian'] = 0x054A;
6127 t['Pemiddlehookcyrillic'] = 0x04A6;
6128 t['Phi'] = 0x03A6;
6129 t['Phook'] = 0x01A4;
6130 t['Pi'] = 0x03A0;
6131 t['Piwrarmenian'] = 0x0553;
6132 t['Pmonospace'] = 0xFF30;
6133 t['Psi'] = 0x03A8;
6134 t['Psicyrillic'] = 0x0470;
6135 t['Psmall'] = 0xF770;
6136 t['Q'] = 0x0051;
6137 t['Qcircle'] = 0x24C6;
6138 t['Qmonospace'] = 0xFF31;
6139 t['Qsmall'] = 0xF771;
6140 t['R'] = 0x0052;
6141 t['Raarmenian'] = 0x054C;
6142 t['Racute'] = 0x0154;
6143 t['Rcaron'] = 0x0158;
6144 t['Rcedilla'] = 0x0156;
6145 t['Rcircle'] = 0x24C7;
6146 t['Rcommaaccent'] = 0x0156;
6147 t['Rdblgrave'] = 0x0210;
6148 t['Rdotaccent'] = 0x1E58;
6149 t['Rdotbelow'] = 0x1E5A;
6150 t['Rdotbelowmacron'] = 0x1E5C;
6151 t['Reharmenian'] = 0x0550;
6152 t['Rfraktur'] = 0x211C;
6153 t['Rho'] = 0x03A1;
6154 t['Ringsmall'] = 0xF6FC;
6155 t['Rinvertedbreve'] = 0x0212;
6156 t['Rlinebelow'] = 0x1E5E;
6157 t['Rmonospace'] = 0xFF32;
6158 t['Rsmall'] = 0xF772;
6159 t['Rsmallinverted'] = 0x0281;
6160 t['Rsmallinvertedsuperior'] = 0x02B6;
6161 t['S'] = 0x0053;
6162 t['SF010000'] = 0x250C;
6163 t['SF020000'] = 0x2514;
6164 t['SF030000'] = 0x2510;
6165 t['SF040000'] = 0x2518;
6166 t['SF050000'] = 0x253C;
6167 t['SF060000'] = 0x252C;
6168 t['SF070000'] = 0x2534;
6169 t['SF080000'] = 0x251C;
6170 t['SF090000'] = 0x2524;
6171 t['SF100000'] = 0x2500;
6172 t['SF110000'] = 0x2502;
6173 t['SF190000'] = 0x2561;
6174 t['SF200000'] = 0x2562;
6175 t['SF210000'] = 0x2556;
6176 t['SF220000'] = 0x2555;
6177 t['SF230000'] = 0x2563;
6178 t['SF240000'] = 0x2551;
6179 t['SF250000'] = 0x2557;
6180 t['SF260000'] = 0x255D;
6181 t['SF270000'] = 0x255C;
6182 t['SF280000'] = 0x255B;
6183 t['SF360000'] = 0x255E;
6184 t['SF370000'] = 0x255F;
6185 t['SF380000'] = 0x255A;
6186 t['SF390000'] = 0x2554;
6187 t['SF400000'] = 0x2569;
6188 t['SF410000'] = 0x2566;
6189 t['SF420000'] = 0x2560;
6190 t['SF430000'] = 0x2550;
6191 t['SF440000'] = 0x256C;
6192 t['SF450000'] = 0x2567;
6193 t['SF460000'] = 0x2568;
6194 t['SF470000'] = 0x2564;
6195 t['SF480000'] = 0x2565;
6196 t['SF490000'] = 0x2559;
6197 t['SF500000'] = 0x2558;
6198 t['SF510000'] = 0x2552;
6199 t['SF520000'] = 0x2553;
6200 t['SF530000'] = 0x256B;
6201 t['SF540000'] = 0x256A;
6202 t['Sacute'] = 0x015A;
6203 t['Sacutedotaccent'] = 0x1E64;
6204 t['Sampigreek'] = 0x03E0;
6205 t['Scaron'] = 0x0160;
6206 t['Scarondotaccent'] = 0x1E66;
6207 t['Scaronsmall'] = 0xF6FD;
6208 t['Scedilla'] = 0x015E;
6209 t['Schwa'] = 0x018F;
6210 t['Schwacyrillic'] = 0x04D8;
6211 t['Schwadieresiscyrillic'] = 0x04DA;
6212 t['Scircle'] = 0x24C8;
6213 t['Scircumflex'] = 0x015C;
6214 t['Scommaaccent'] = 0x0218;
6215 t['Sdotaccent'] = 0x1E60;
6216 t['Sdotbelow'] = 0x1E62;
6217 t['Sdotbelowdotaccent'] = 0x1E68;
6218 t['Seharmenian'] = 0x054D;
6219 t['Sevenroman'] = 0x2166;
6220 t['Shaarmenian'] = 0x0547;
6221 t['Shacyrillic'] = 0x0428;
6222 t['Shchacyrillic'] = 0x0429;
6223 t['Sheicoptic'] = 0x03E2;
6224 t['Shhacyrillic'] = 0x04BA;
6225 t['Shimacoptic'] = 0x03EC;
6226 t['Sigma'] = 0x03A3;
6227 t['Sixroman'] = 0x2165;
6228 t['Smonospace'] = 0xFF33;
6229 t['Softsigncyrillic'] = 0x042C;
6230 t['Ssmall'] = 0xF773;
6231 t['Stigmagreek'] = 0x03DA;
6232 t['T'] = 0x0054;
6233 t['Tau'] = 0x03A4;
6234 t['Tbar'] = 0x0166;
6235 t['Tcaron'] = 0x0164;
6236 t['Tcedilla'] = 0x0162;
6237 t['Tcircle'] = 0x24C9;
6238 t['Tcircumflexbelow'] = 0x1E70;
6239 t['Tcommaaccent'] = 0x0162;
6240 t['Tdotaccent'] = 0x1E6A;
6241 t['Tdotbelow'] = 0x1E6C;
6242 t['Tecyrillic'] = 0x0422;
6243 t['Tedescendercyrillic'] = 0x04AC;
6244 t['Tenroman'] = 0x2169;
6245 t['Tetsecyrillic'] = 0x04B4;
6246 t['Theta'] = 0x0398;
6247 t['Thook'] = 0x01AC;
6248 t['Thorn'] = 0x00DE;
6249 t['Thornsmall'] = 0xF7FE;
6250 t['Threeroman'] = 0x2162;
6251 t['Tildesmall'] = 0xF6FE;
6252 t['Tiwnarmenian'] = 0x054F;
6253 t['Tlinebelow'] = 0x1E6E;
6254 t['Tmonospace'] = 0xFF34;
6255 t['Toarmenian'] = 0x0539;
6256 t['Tonefive'] = 0x01BC;
6257 t['Tonesix'] = 0x0184;
6258 t['Tonetwo'] = 0x01A7;
6259 t['Tretroflexhook'] = 0x01AE;
6260 t['Tsecyrillic'] = 0x0426;
6261 t['Tshecyrillic'] = 0x040B;
6262 t['Tsmall'] = 0xF774;
6263 t['Twelveroman'] = 0x216B;
6264 t['Tworoman'] = 0x2161;
6265 t['U'] = 0x0055;
6266 t['Uacute'] = 0x00DA;
6267 t['Uacutesmall'] = 0xF7FA;
6268 t['Ubreve'] = 0x016C;
6269 t['Ucaron'] = 0x01D3;
6270 t['Ucircle'] = 0x24CA;
6271 t['Ucircumflex'] = 0x00DB;
6272 t['Ucircumflexbelow'] = 0x1E76;
6273 t['Ucircumflexsmall'] = 0xF7FB;
6274 t['Ucyrillic'] = 0x0423;
6275 t['Udblacute'] = 0x0170;
6276 t['Udblgrave'] = 0x0214;
6277 t['Udieresis'] = 0x00DC;
6278 t['Udieresisacute'] = 0x01D7;
6279 t['Udieresisbelow'] = 0x1E72;
6280 t['Udieresiscaron'] = 0x01D9;
6281 t['Udieresiscyrillic'] = 0x04F0;
6282 t['Udieresisgrave'] = 0x01DB;
6283 t['Udieresismacron'] = 0x01D5;
6284 t['Udieresissmall'] = 0xF7FC;
6285 t['Udotbelow'] = 0x1EE4;
6286 t['Ugrave'] = 0x00D9;
6287 t['Ugravesmall'] = 0xF7F9;
6288 t['Uhookabove'] = 0x1EE6;
6289 t['Uhorn'] = 0x01AF;
6290 t['Uhornacute'] = 0x1EE8;
6291 t['Uhorndotbelow'] = 0x1EF0;
6292 t['Uhorngrave'] = 0x1EEA;
6293 t['Uhornhookabove'] = 0x1EEC;
6294 t['Uhorntilde'] = 0x1EEE;
6295 t['Uhungarumlaut'] = 0x0170;
6296 t['Uhungarumlautcyrillic'] = 0x04F2;
6297 t['Uinvertedbreve'] = 0x0216;
6298 t['Ukcyrillic'] = 0x0478;
6299 t['Umacron'] = 0x016A;
6300 t['Umacroncyrillic'] = 0x04EE;
6301 t['Umacrondieresis'] = 0x1E7A;
6302 t['Umonospace'] = 0xFF35;
6303 t['Uogonek'] = 0x0172;
6304 t['Upsilon'] = 0x03A5;
6305 t['Upsilon1'] = 0x03D2;
6306 t['Upsilonacutehooksymbolgreek'] = 0x03D3;
6307 t['Upsilonafrican'] = 0x01B1;
6308 t['Upsilondieresis'] = 0x03AB;
6309 t['Upsilondieresishooksymbolgreek'] = 0x03D4;
6310 t['Upsilonhooksymbol'] = 0x03D2;
6311 t['Upsilontonos'] = 0x038E;
6312 t['Uring'] = 0x016E;
6313 t['Ushortcyrillic'] = 0x040E;
6314 t['Usmall'] = 0xF775;
6315 t['Ustraightcyrillic'] = 0x04AE;
6316 t['Ustraightstrokecyrillic'] = 0x04B0;
6317 t['Utilde'] = 0x0168;
6318 t['Utildeacute'] = 0x1E78;
6319 t['Utildebelow'] = 0x1E74;
6320 t['V'] = 0x0056;
6321 t['Vcircle'] = 0x24CB;
6322 t['Vdotbelow'] = 0x1E7E;
6323 t['Vecyrillic'] = 0x0412;
6324 t['Vewarmenian'] = 0x054E;
6325 t['Vhook'] = 0x01B2;
6326 t['Vmonospace'] = 0xFF36;
6327 t['Voarmenian'] = 0x0548;
6328 t['Vsmall'] = 0xF776;
6329 t['Vtilde'] = 0x1E7C;
6330 t['W'] = 0x0057;
6331 t['Wacute'] = 0x1E82;
6332 t['Wcircle'] = 0x24CC;
6333 t['Wcircumflex'] = 0x0174;
6334 t['Wdieresis'] = 0x1E84;
6335 t['Wdotaccent'] = 0x1E86;
6336 t['Wdotbelow'] = 0x1E88;
6337 t['Wgrave'] = 0x1E80;
6338 t['Wmonospace'] = 0xFF37;
6339 t['Wsmall'] = 0xF777;
6340 t['X'] = 0x0058;
6341 t['Xcircle'] = 0x24CD;
6342 t['Xdieresis'] = 0x1E8C;
6343 t['Xdotaccent'] = 0x1E8A;
6344 t['Xeharmenian'] = 0x053D;
6345 t['Xi'] = 0x039E;
6346 t['Xmonospace'] = 0xFF38;
6347 t['Xsmall'] = 0xF778;
6348 t['Y'] = 0x0059;
6349 t['Yacute'] = 0x00DD;
6350 t['Yacutesmall'] = 0xF7FD;
6351 t['Yatcyrillic'] = 0x0462;
6352 t['Ycircle'] = 0x24CE;
6353 t['Ycircumflex'] = 0x0176;
6354 t['Ydieresis'] = 0x0178;
6355 t['Ydieresissmall'] = 0xF7FF;
6356 t['Ydotaccent'] = 0x1E8E;
6357 t['Ydotbelow'] = 0x1EF4;
6358 t['Yericyrillic'] = 0x042B;
6359 t['Yerudieresiscyrillic'] = 0x04F8;
6360 t['Ygrave'] = 0x1EF2;
6361 t['Yhook'] = 0x01B3;
6362 t['Yhookabove'] = 0x1EF6;
6363 t['Yiarmenian'] = 0x0545;
6364 t['Yicyrillic'] = 0x0407;
6365 t['Yiwnarmenian'] = 0x0552;
6366 t['Ymonospace'] = 0xFF39;
6367 t['Ysmall'] = 0xF779;
6368 t['Ytilde'] = 0x1EF8;
6369 t['Yusbigcyrillic'] = 0x046A;
6370 t['Yusbigiotifiedcyrillic'] = 0x046C;
6371 t['Yuslittlecyrillic'] = 0x0466;
6372 t['Yuslittleiotifiedcyrillic'] = 0x0468;
6373 t['Z'] = 0x005A;
6374 t['Zaarmenian'] = 0x0536;
6375 t['Zacute'] = 0x0179;
6376 t['Zcaron'] = 0x017D;
6377 t['Zcaronsmall'] = 0xF6FF;
6378 t['Zcircle'] = 0x24CF;
6379 t['Zcircumflex'] = 0x1E90;
6380 t['Zdot'] = 0x017B;
6381 t['Zdotaccent'] = 0x017B;
6382 t['Zdotbelow'] = 0x1E92;
6383 t['Zecyrillic'] = 0x0417;
6384 t['Zedescendercyrillic'] = 0x0498;
6385 t['Zedieresiscyrillic'] = 0x04DE;
6386 t['Zeta'] = 0x0396;
6387 t['Zhearmenian'] = 0x053A;
6388 t['Zhebrevecyrillic'] = 0x04C1;
6389 t['Zhecyrillic'] = 0x0416;
6390 t['Zhedescendercyrillic'] = 0x0496;
6391 t['Zhedieresiscyrillic'] = 0x04DC;
6392 t['Zlinebelow'] = 0x1E94;
6393 t['Zmonospace'] = 0xFF3A;
6394 t['Zsmall'] = 0xF77A;
6395 t['Zstroke'] = 0x01B5;
6396 t['a'] = 0x0061;
6397 t['aabengali'] = 0x0986;
6398 t['aacute'] = 0x00E1;
6399 t['aadeva'] = 0x0906;
6400 t['aagujarati'] = 0x0A86;
6401 t['aagurmukhi'] = 0x0A06;
6402 t['aamatragurmukhi'] = 0x0A3E;
6403 t['aarusquare'] = 0x3303;
6404 t['aavowelsignbengali'] = 0x09BE;
6405 t['aavowelsigndeva'] = 0x093E;
6406 t['aavowelsigngujarati'] = 0x0ABE;
6407 t['abbreviationmarkarmenian'] = 0x055F;
6408 t['abbreviationsigndeva'] = 0x0970;
6409 t['abengali'] = 0x0985;
6410 t['abopomofo'] = 0x311A;
6411 t['abreve'] = 0x0103;
6412 t['abreveacute'] = 0x1EAF;
6413 t['abrevecyrillic'] = 0x04D1;
6414 t['abrevedotbelow'] = 0x1EB7;
6415 t['abrevegrave'] = 0x1EB1;
6416 t['abrevehookabove'] = 0x1EB3;
6417 t['abrevetilde'] = 0x1EB5;
6418 t['acaron'] = 0x01CE;
6419 t['acircle'] = 0x24D0;
6420 t['acircumflex'] = 0x00E2;
6421 t['acircumflexacute'] = 0x1EA5;
6422 t['acircumflexdotbelow'] = 0x1EAD;
6423 t['acircumflexgrave'] = 0x1EA7;
6424 t['acircumflexhookabove'] = 0x1EA9;
6425 t['acircumflextilde'] = 0x1EAB;
6426 t['acute'] = 0x00B4;
6427 t['acutebelowcmb'] = 0x0317;
6428 t['acutecmb'] = 0x0301;
6429 t['acutecomb'] = 0x0301;
6430 t['acutedeva'] = 0x0954;
6431 t['acutelowmod'] = 0x02CF;
6432 t['acutetonecmb'] = 0x0341;
6433 t['acyrillic'] = 0x0430;
6434 t['adblgrave'] = 0x0201;
6435 t['addakgurmukhi'] = 0x0A71;
6436 t['adeva'] = 0x0905;
6437 t['adieresis'] = 0x00E4;
6438 t['adieresiscyrillic'] = 0x04D3;
6439 t['adieresismacron'] = 0x01DF;
6440 t['adotbelow'] = 0x1EA1;
6441 t['adotmacron'] = 0x01E1;
6442 t['ae'] = 0x00E6;
6443 t['aeacute'] = 0x01FD;
6444 t['aekorean'] = 0x3150;
6445 t['aemacron'] = 0x01E3;
6446 t['afii00208'] = 0x2015;
6447 t['afii08941'] = 0x20A4;
6448 t['afii10017'] = 0x0410;
6449 t['afii10018'] = 0x0411;
6450 t['afii10019'] = 0x0412;
6451 t['afii10020'] = 0x0413;
6452 t['afii10021'] = 0x0414;
6453 t['afii10022'] = 0x0415;
6454 t['afii10023'] = 0x0401;
6455 t['afii10024'] = 0x0416;
6456 t['afii10025'] = 0x0417;
6457 t['afii10026'] = 0x0418;
6458 t['afii10027'] = 0x0419;
6459 t['afii10028'] = 0x041A;
6460 t['afii10029'] = 0x041B;
6461 t['afii10030'] = 0x041C;
6462 t['afii10031'] = 0x041D;
6463 t['afii10032'] = 0x041E;
6464 t['afii10033'] = 0x041F;
6465 t['afii10034'] = 0x0420;
6466 t['afii10035'] = 0x0421;
6467 t['afii10036'] = 0x0422;
6468 t['afii10037'] = 0x0423;
6469 t['afii10038'] = 0x0424;
6470 t['afii10039'] = 0x0425;
6471 t['afii10040'] = 0x0426;
6472 t['afii10041'] = 0x0427;
6473 t['afii10042'] = 0x0428;
6474 t['afii10043'] = 0x0429;
6475 t['afii10044'] = 0x042A;
6476 t['afii10045'] = 0x042B;
6477 t['afii10046'] = 0x042C;
6478 t['afii10047'] = 0x042D;
6479 t['afii10048'] = 0x042E;
6480 t['afii10049'] = 0x042F;
6481 t['afii10050'] = 0x0490;
6482 t['afii10051'] = 0x0402;
6483 t['afii10052'] = 0x0403;
6484 t['afii10053'] = 0x0404;
6485 t['afii10054'] = 0x0405;
6486 t['afii10055'] = 0x0406;
6487 t['afii10056'] = 0x0407;
6488 t['afii10057'] = 0x0408;
6489 t['afii10058'] = 0x0409;
6490 t['afii10059'] = 0x040A;
6491 t['afii10060'] = 0x040B;
6492 t['afii10061'] = 0x040C;
6493 t['afii10062'] = 0x040E;
6494 t['afii10063'] = 0xF6C4;
6495 t['afii10064'] = 0xF6C5;
6496 t['afii10065'] = 0x0430;
6497 t['afii10066'] = 0x0431;
6498 t['afii10067'] = 0x0432;
6499 t['afii10068'] = 0x0433;
6500 t['afii10069'] = 0x0434;
6501 t['afii10070'] = 0x0435;
6502 t['afii10071'] = 0x0451;
6503 t['afii10072'] = 0x0436;
6504 t['afii10073'] = 0x0437;
6505 t['afii10074'] = 0x0438;
6506 t['afii10075'] = 0x0439;
6507 t['afii10076'] = 0x043A;
6508 t['afii10077'] = 0x043B;
6509 t['afii10078'] = 0x043C;
6510 t['afii10079'] = 0x043D;
6511 t['afii10080'] = 0x043E;
6512 t['afii10081'] = 0x043F;
6513 t['afii10082'] = 0x0440;
6514 t['afii10083'] = 0x0441;
6515 t['afii10084'] = 0x0442;
6516 t['afii10085'] = 0x0443;
6517 t['afii10086'] = 0x0444;
6518 t['afii10087'] = 0x0445;
6519 t['afii10088'] = 0x0446;
6520 t['afii10089'] = 0x0447;
6521 t['afii10090'] = 0x0448;
6522 t['afii10091'] = 0x0449;
6523 t['afii10092'] = 0x044A;
6524 t['afii10093'] = 0x044B;
6525 t['afii10094'] = 0x044C;
6526 t['afii10095'] = 0x044D;
6527 t['afii10096'] = 0x044E;
6528 t['afii10097'] = 0x044F;
6529 t['afii10098'] = 0x0491;
6530 t['afii10099'] = 0x0452;
6531 t['afii10100'] = 0x0453;
6532 t['afii10101'] = 0x0454;
6533 t['afii10102'] = 0x0455;
6534 t['afii10103'] = 0x0456;
6535 t['afii10104'] = 0x0457;
6536 t['afii10105'] = 0x0458;
6537 t['afii10106'] = 0x0459;
6538 t['afii10107'] = 0x045A;
6539 t['afii10108'] = 0x045B;
6540 t['afii10109'] = 0x045C;
6541 t['afii10110'] = 0x045E;
6542 t['afii10145'] = 0x040F;
6543 t['afii10146'] = 0x0462;
6544 t['afii10147'] = 0x0472;
6545 t['afii10148'] = 0x0474;
6546 t['afii10192'] = 0xF6C6;
6547 t['afii10193'] = 0x045F;
6548 t['afii10194'] = 0x0463;
6549 t['afii10195'] = 0x0473;
6550 t['afii10196'] = 0x0475;
6551 t['afii10831'] = 0xF6C7;
6552 t['afii10832'] = 0xF6C8;
6553 t['afii10846'] = 0x04D9;
6554 t['afii299'] = 0x200E;
6555 t['afii300'] = 0x200F;
6556 t['afii301'] = 0x200D;
6557 t['afii57381'] = 0x066A;
6558 t['afii57388'] = 0x060C;
6559 t['afii57392'] = 0x0660;
6560 t['afii57393'] = 0x0661;
6561 t['afii57394'] = 0x0662;
6562 t['afii57395'] = 0x0663;
6563 t['afii57396'] = 0x0664;
6564 t['afii57397'] = 0x0665;
6565 t['afii57398'] = 0x0666;
6566 t['afii57399'] = 0x0667;
6567 t['afii57400'] = 0x0668;
6568 t['afii57401'] = 0x0669;
6569 t['afii57403'] = 0x061B;
6570 t['afii57407'] = 0x061F;
6571 t['afii57409'] = 0x0621;
6572 t['afii57410'] = 0x0622;
6573 t['afii57411'] = 0x0623;
6574 t['afii57412'] = 0x0624;
6575 t['afii57413'] = 0x0625;
6576 t['afii57414'] = 0x0626;
6577 t['afii57415'] = 0x0627;
6578 t['afii57416'] = 0x0628;
6579 t['afii57417'] = 0x0629;
6580 t['afii57418'] = 0x062A;
6581 t['afii57419'] = 0x062B;
6582 t['afii57420'] = 0x062C;
6583 t['afii57421'] = 0x062D;
6584 t['afii57422'] = 0x062E;
6585 t['afii57423'] = 0x062F;
6586 t['afii57424'] = 0x0630;
6587 t['afii57425'] = 0x0631;
6588 t['afii57426'] = 0x0632;
6589 t['afii57427'] = 0x0633;
6590 t['afii57428'] = 0x0634;
6591 t['afii57429'] = 0x0635;
6592 t['afii57430'] = 0x0636;
6593 t['afii57431'] = 0x0637;
6594 t['afii57432'] = 0x0638;
6595 t['afii57433'] = 0x0639;
6596 t['afii57434'] = 0x063A;
6597 t['afii57440'] = 0x0640;
6598 t['afii57441'] = 0x0641;
6599 t['afii57442'] = 0x0642;
6600 t['afii57443'] = 0x0643;
6601 t['afii57444'] = 0x0644;
6602 t['afii57445'] = 0x0645;
6603 t['afii57446'] = 0x0646;
6604 t['afii57448'] = 0x0648;
6605 t['afii57449'] = 0x0649;
6606 t['afii57450'] = 0x064A;
6607 t['afii57451'] = 0x064B;
6608 t['afii57452'] = 0x064C;
6609 t['afii57453'] = 0x064D;
6610 t['afii57454'] = 0x064E;
6611 t['afii57455'] = 0x064F;
6612 t['afii57456'] = 0x0650;
6613 t['afii57457'] = 0x0651;
6614 t['afii57458'] = 0x0652;
6615 t['afii57470'] = 0x0647;
6616 t['afii57505'] = 0x06A4;
6617 t['afii57506'] = 0x067E;
6618 t['afii57507'] = 0x0686;
6619 t['afii57508'] = 0x0698;
6620 t['afii57509'] = 0x06AF;
6621 t['afii57511'] = 0x0679;
6622 t['afii57512'] = 0x0688;
6623 t['afii57513'] = 0x0691;
6624 t['afii57514'] = 0x06BA;
6625 t['afii57519'] = 0x06D2;
6626 t['afii57534'] = 0x06D5;
6627 t['afii57636'] = 0x20AA;
6628 t['afii57645'] = 0x05BE;
6629 t['afii57658'] = 0x05C3;
6630 t['afii57664'] = 0x05D0;
6631 t['afii57665'] = 0x05D1;
6632 t['afii57666'] = 0x05D2;
6633 t['afii57667'] = 0x05D3;
6634 t['afii57668'] = 0x05D4;
6635 t['afii57669'] = 0x05D5;
6636 t['afii57670'] = 0x05D6;
6637 t['afii57671'] = 0x05D7;
6638 t['afii57672'] = 0x05D8;
6639 t['afii57673'] = 0x05D9;
6640 t['afii57674'] = 0x05DA;
6641 t['afii57675'] = 0x05DB;
6642 t['afii57676'] = 0x05DC;
6643 t['afii57677'] = 0x05DD;
6644 t['afii57678'] = 0x05DE;
6645 t['afii57679'] = 0x05DF;
6646 t['afii57680'] = 0x05E0;
6647 t['afii57681'] = 0x05E1;
6648 t['afii57682'] = 0x05E2;
6649 t['afii57683'] = 0x05E3;
6650 t['afii57684'] = 0x05E4;
6651 t['afii57685'] = 0x05E5;
6652 t['afii57686'] = 0x05E6;
6653 t['afii57687'] = 0x05E7;
6654 t['afii57688'] = 0x05E8;
6655 t['afii57689'] = 0x05E9;
6656 t['afii57690'] = 0x05EA;
6657 t['afii57694'] = 0xFB2A;
6658 t['afii57695'] = 0xFB2B;
6659 t['afii57700'] = 0xFB4B;
6660 t['afii57705'] = 0xFB1F;
6661 t['afii57716'] = 0x05F0;
6662 t['afii57717'] = 0x05F1;
6663 t['afii57718'] = 0x05F2;
6664 t['afii57723'] = 0xFB35;
6665 t['afii57793'] = 0x05B4;
6666 t['afii57794'] = 0x05B5;
6667 t['afii57795'] = 0x05B6;
6668 t['afii57796'] = 0x05BB;
6669 t['afii57797'] = 0x05B8;
6670 t['afii57798'] = 0x05B7;
6671 t['afii57799'] = 0x05B0;
6672 t['afii57800'] = 0x05B2;
6673 t['afii57801'] = 0x05B1;
6674 t['afii57802'] = 0x05B3;
6675 t['afii57803'] = 0x05C2;
6676 t['afii57804'] = 0x05C1;
6677 t['afii57806'] = 0x05B9;
6678 t['afii57807'] = 0x05BC;
6679 t['afii57839'] = 0x05BD;
6680 t['afii57841'] = 0x05BF;
6681 t['afii57842'] = 0x05C0;
6682 t['afii57929'] = 0x02BC;
6683 t['afii61248'] = 0x2105;
6684 t['afii61289'] = 0x2113;
6685 t['afii61352'] = 0x2116;
6686 t['afii61573'] = 0x202C;
6687 t['afii61574'] = 0x202D;
6688 t['afii61575'] = 0x202E;
6689 t['afii61664'] = 0x200C;
6690 t['afii63167'] = 0x066D;
6691 t['afii64937'] = 0x02BD;
6692 t['agrave'] = 0x00E0;
6693 t['agujarati'] = 0x0A85;
6694 t['agurmukhi'] = 0x0A05;
6695 t['ahiragana'] = 0x3042;
6696 t['ahookabove'] = 0x1EA3;
6697 t['aibengali'] = 0x0990;
6698 t['aibopomofo'] = 0x311E;
6699 t['aideva'] = 0x0910;
6700 t['aiecyrillic'] = 0x04D5;
6701 t['aigujarati'] = 0x0A90;
6702 t['aigurmukhi'] = 0x0A10;
6703 t['aimatragurmukhi'] = 0x0A48;
6704 t['ainarabic'] = 0x0639;
6705 t['ainfinalarabic'] = 0xFECA;
6706 t['aininitialarabic'] = 0xFECB;
6707 t['ainmedialarabic'] = 0xFECC;
6708 t['ainvertedbreve'] = 0x0203;
6709 t['aivowelsignbengali'] = 0x09C8;
6710 t['aivowelsigndeva'] = 0x0948;
6711 t['aivowelsigngujarati'] = 0x0AC8;
6712 t['akatakana'] = 0x30A2;
6713 t['akatakanahalfwidth'] = 0xFF71;
6714 t['akorean'] = 0x314F;
6715 t['alef'] = 0x05D0;
6716 t['alefarabic'] = 0x0627;
6717 t['alefdageshhebrew'] = 0xFB30;
6718 t['aleffinalarabic'] = 0xFE8E;
6719 t['alefhamzaabovearabic'] = 0x0623;
6720 t['alefhamzaabovefinalarabic'] = 0xFE84;
6721 t['alefhamzabelowarabic'] = 0x0625;
6722 t['alefhamzabelowfinalarabic'] = 0xFE88;
6723 t['alefhebrew'] = 0x05D0;
6724 t['aleflamedhebrew'] = 0xFB4F;
6725 t['alefmaddaabovearabic'] = 0x0622;
6726 t['alefmaddaabovefinalarabic'] = 0xFE82;
6727 t['alefmaksuraarabic'] = 0x0649;
6728 t['alefmaksurafinalarabic'] = 0xFEF0;
6729 t['alefmaksurainitialarabic'] = 0xFEF3;
6730 t['alefmaksuramedialarabic'] = 0xFEF4;
6731 t['alefpatahhebrew'] = 0xFB2E;
6732 t['alefqamatshebrew'] = 0xFB2F;
6733 t['aleph'] = 0x2135;
6734 t['allequal'] = 0x224C;
6735 t['alpha'] = 0x03B1;
6736 t['alphatonos'] = 0x03AC;
6737 t['amacron'] = 0x0101;
6738 t['amonospace'] = 0xFF41;
6739 t['ampersand'] = 0x0026;
6740 t['ampersandmonospace'] = 0xFF06;
6741 t['ampersandsmall'] = 0xF726;
6742 t['amsquare'] = 0x33C2;
6743 t['anbopomofo'] = 0x3122;
6744 t['angbopomofo'] = 0x3124;
6745 t['angbracketleft'] = 0x3008; // Glyph is missing from Adobe's original list.
6746 t['angbracketright'] = 0x3009; // Glyph is missing from Adobe's original list.
6747 t['angkhankhuthai'] = 0x0E5A;
6748 t['angle'] = 0x2220;
6749 t['anglebracketleft'] = 0x3008;
6750 t['anglebracketleftvertical'] = 0xFE3F;
6751 t['anglebracketright'] = 0x3009;
6752 t['anglebracketrightvertical'] = 0xFE40;
6753 t['angleleft'] = 0x2329;
6754 t['angleright'] = 0x232A;
6755 t['angstrom'] = 0x212B;
6756 t['anoteleia'] = 0x0387;
6757 t['anudattadeva'] = 0x0952;
6758 t['anusvarabengali'] = 0x0982;
6759 t['anusvaradeva'] = 0x0902;
6760 t['anusvaragujarati'] = 0x0A82;
6761 t['aogonek'] = 0x0105;
6762 t['apaatosquare'] = 0x3300;
6763 t['aparen'] = 0x249C;
6764 t['apostrophearmenian'] = 0x055A;
6765 t['apostrophemod'] = 0x02BC;
6766 t['apple'] = 0xF8FF;
6767 t['approaches'] = 0x2250;
6768 t['approxequal'] = 0x2248;
6769 t['approxequalorimage'] = 0x2252;
6770 t['approximatelyequal'] = 0x2245;
6771 t['araeaekorean'] = 0x318E;
6772 t['araeakorean'] = 0x318D;
6773 t['arc'] = 0x2312;
6774 t['arighthalfring'] = 0x1E9A;
6775 t['aring'] = 0x00E5;
6776 t['aringacute'] = 0x01FB;
6777 t['aringbelow'] = 0x1E01;
6778 t['arrowboth'] = 0x2194;
6779 t['arrowdashdown'] = 0x21E3;
6780 t['arrowdashleft'] = 0x21E0;
6781 t['arrowdashright'] = 0x21E2;
6782 t['arrowdashup'] = 0x21E1;
6783 t['arrowdblboth'] = 0x21D4;
6784 t['arrowdbldown'] = 0x21D3;
6785 t['arrowdblleft'] = 0x21D0;
6786 t['arrowdblright'] = 0x21D2;
6787 t['arrowdblup'] = 0x21D1;
6788 t['arrowdown'] = 0x2193;
6789 t['arrowdownleft'] = 0x2199;
6790 t['arrowdownright'] = 0x2198;
6791 t['arrowdownwhite'] = 0x21E9;
6792 t['arrowheaddownmod'] = 0x02C5;
6793 t['arrowheadleftmod'] = 0x02C2;
6794 t['arrowheadrightmod'] = 0x02C3;
6795 t['arrowheadupmod'] = 0x02C4;
6796 t['arrowhorizex'] = 0xF8E7;
6797 t['arrowleft'] = 0x2190;
6798 t['arrowleftdbl'] = 0x21D0;
6799 t['arrowleftdblstroke'] = 0x21CD;
6800 t['arrowleftoverright'] = 0x21C6;
6801 t['arrowleftwhite'] = 0x21E6;
6802 t['arrowright'] = 0x2192;
6803 t['arrowrightdblstroke'] = 0x21CF;
6804 t['arrowrightheavy'] = 0x279E;
6805 t['arrowrightoverleft'] = 0x21C4;
6806 t['arrowrightwhite'] = 0x21E8;
6807 t['arrowtableft'] = 0x21E4;
6808 t['arrowtabright'] = 0x21E5;
6809 t['arrowup'] = 0x2191;
6810 t['arrowupdn'] = 0x2195;
6811 t['arrowupdnbse'] = 0x21A8;
6812 t['arrowupdownbase'] = 0x21A8;
6813 t['arrowupleft'] = 0x2196;
6814 t['arrowupleftofdown'] = 0x21C5;
6815 t['arrowupright'] = 0x2197;
6816 t['arrowupwhite'] = 0x21E7;
6817 t['arrowvertex'] = 0xF8E6;
6818 t['asciicircum'] = 0x005E;
6819 t['asciicircummonospace'] = 0xFF3E;
6820 t['asciitilde'] = 0x007E;
6821 t['asciitildemonospace'] = 0xFF5E;
6822 t['ascript'] = 0x0251;
6823 t['ascriptturned'] = 0x0252;
6824 t['asmallhiragana'] = 0x3041;
6825 t['asmallkatakana'] = 0x30A1;
6826 t['asmallkatakanahalfwidth'] = 0xFF67;
6827 t['asterisk'] = 0x002A;
6828 t['asteriskaltonearabic'] = 0x066D;
6829 t['asteriskarabic'] = 0x066D;
6830 t['asteriskmath'] = 0x2217;
6831 t['asteriskmonospace'] = 0xFF0A;
6832 t['asterisksmall'] = 0xFE61;
6833 t['asterism'] = 0x2042;
6834 t['asuperior'] = 0xF6E9;
6835 t['asymptoticallyequal'] = 0x2243;
6836 t['at'] = 0x0040;
6837 t['atilde'] = 0x00E3;
6838 t['atmonospace'] = 0xFF20;
6839 t['atsmall'] = 0xFE6B;
6840 t['aturned'] = 0x0250;
6841 t['aubengali'] = 0x0994;
6842 t['aubopomofo'] = 0x3120;
6843 t['audeva'] = 0x0914;
6844 t['augujarati'] = 0x0A94;
6845 t['augurmukhi'] = 0x0A14;
6846 t['aulengthmarkbengali'] = 0x09D7;
6847 t['aumatragurmukhi'] = 0x0A4C;
6848 t['auvowelsignbengali'] = 0x09CC;
6849 t['auvowelsigndeva'] = 0x094C;
6850 t['auvowelsigngujarati'] = 0x0ACC;
6851 t['avagrahadeva'] = 0x093D;
6852 t['aybarmenian'] = 0x0561;
6853 t['ayin'] = 0x05E2;
6854 t['ayinaltonehebrew'] = 0xFB20;
6855 t['ayinhebrew'] = 0x05E2;
6856 t['b'] = 0x0062;
6857 t['babengali'] = 0x09AC;
6858 t['backslash'] = 0x005C;
6859 t['backslashmonospace'] = 0xFF3C;
6860 t['badeva'] = 0x092C;
6861 t['bagujarati'] = 0x0AAC;
6862 t['bagurmukhi'] = 0x0A2C;
6863 t['bahiragana'] = 0x3070;
6864 t['bahtthai'] = 0x0E3F;
6865 t['bakatakana'] = 0x30D0;
6866 t['bar'] = 0x007C;
6867 t['barmonospace'] = 0xFF5C;
6868 t['bbopomofo'] = 0x3105;
6869 t['bcircle'] = 0x24D1;
6870 t['bdotaccent'] = 0x1E03;
6871 t['bdotbelow'] = 0x1E05;
6872 t['beamedsixteenthnotes'] = 0x266C;
6873 t['because'] = 0x2235;
6874 t['becyrillic'] = 0x0431;
6875 t['beharabic'] = 0x0628;
6876 t['behfinalarabic'] = 0xFE90;
6877 t['behinitialarabic'] = 0xFE91;
6878 t['behiragana'] = 0x3079;
6879 t['behmedialarabic'] = 0xFE92;
6880 t['behmeeminitialarabic'] = 0xFC9F;
6881 t['behmeemisolatedarabic'] = 0xFC08;
6882 t['behnoonfinalarabic'] = 0xFC6D;
6883 t['bekatakana'] = 0x30D9;
6884 t['benarmenian'] = 0x0562;
6885 t['bet'] = 0x05D1;
6886 t['beta'] = 0x03B2;
6887 t['betasymbolgreek'] = 0x03D0;
6888 t['betdagesh'] = 0xFB31;
6889 t['betdageshhebrew'] = 0xFB31;
6890 t['bethebrew'] = 0x05D1;
6891 t['betrafehebrew'] = 0xFB4C;
6892 t['bhabengali'] = 0x09AD;
6893 t['bhadeva'] = 0x092D;
6894 t['bhagujarati'] = 0x0AAD;
6895 t['bhagurmukhi'] = 0x0A2D;
6896 t['bhook'] = 0x0253;
6897 t['bihiragana'] = 0x3073;
6898 t['bikatakana'] = 0x30D3;
6899 t['bilabialclick'] = 0x0298;
6900 t['bindigurmukhi'] = 0x0A02;
6901 t['birusquare'] = 0x3331;
6902 t['blackcircle'] = 0x25CF;
6903 t['blackdiamond'] = 0x25C6;
6904 t['blackdownpointingtriangle'] = 0x25BC;
6905 t['blackleftpointingpointer'] = 0x25C4;
6906 t['blackleftpointingtriangle'] = 0x25C0;
6907 t['blacklenticularbracketleft'] = 0x3010;
6908 t['blacklenticularbracketleftvertical'] = 0xFE3B;
6909 t['blacklenticularbracketright'] = 0x3011;
6910 t['blacklenticularbracketrightvertical'] = 0xFE3C;
6911 t['blacklowerlefttriangle'] = 0x25E3;
6912 t['blacklowerrighttriangle'] = 0x25E2;
6913 t['blackrectangle'] = 0x25AC;
6914 t['blackrightpointingpointer'] = 0x25BA;
6915 t['blackrightpointingtriangle'] = 0x25B6;
6916 t['blacksmallsquare'] = 0x25AA;
6917 t['blacksmilingface'] = 0x263B;
6918 t['blacksquare'] = 0x25A0;
6919 t['blackstar'] = 0x2605;
6920 t['blackupperlefttriangle'] = 0x25E4;
6921 t['blackupperrighttriangle'] = 0x25E5;
6922 t['blackuppointingsmalltriangle'] = 0x25B4;
6923 t['blackuppointingtriangle'] = 0x25B2;
6924 t['blank'] = 0x2423;
6925 t['blinebelow'] = 0x1E07;
6926 t['block'] = 0x2588;
6927 t['bmonospace'] = 0xFF42;
6928 t['bobaimaithai'] = 0x0E1A;
6929 t['bohiragana'] = 0x307C;
6930 t['bokatakana'] = 0x30DC;
6931 t['bparen'] = 0x249D;
6932 t['bqsquare'] = 0x33C3;
6933 t['braceex'] = 0xF8F4;
6934 t['braceleft'] = 0x007B;
6935 t['braceleftbt'] = 0xF8F3;
6936 t['braceleftmid'] = 0xF8F2;
6937 t['braceleftmonospace'] = 0xFF5B;
6938 t['braceleftsmall'] = 0xFE5B;
6939 t['bracelefttp'] = 0xF8F1;
6940 t['braceleftvertical'] = 0xFE37;
6941 t['braceright'] = 0x007D;
6942 t['bracerightbt'] = 0xF8FE;
6943 t['bracerightmid'] = 0xF8FD;
6944 t['bracerightmonospace'] = 0xFF5D;
6945 t['bracerightsmall'] = 0xFE5C;
6946 t['bracerighttp'] = 0xF8FC;
6947 t['bracerightvertical'] = 0xFE38;
6948 t['bracketleft'] = 0x005B;
6949 t['bracketleftbt'] = 0xF8F0;
6950 t['bracketleftex'] = 0xF8EF;
6951 t['bracketleftmonospace'] = 0xFF3B;
6952 t['bracketlefttp'] = 0xF8EE;
6953 t['bracketright'] = 0x005D;
6954 t['bracketrightbt'] = 0xF8FB;
6955 t['bracketrightex'] = 0xF8FA;
6956 t['bracketrightmonospace'] = 0xFF3D;
6957 t['bracketrighttp'] = 0xF8F9;
6958 t['breve'] = 0x02D8;
6959 t['brevebelowcmb'] = 0x032E;
6960 t['brevecmb'] = 0x0306;
6961 t['breveinvertedbelowcmb'] = 0x032F;
6962 t['breveinvertedcmb'] = 0x0311;
6963 t['breveinverteddoublecmb'] = 0x0361;
6964 t['bridgebelowcmb'] = 0x032A;
6965 t['bridgeinvertedbelowcmb'] = 0x033A;
6966 t['brokenbar'] = 0x00A6;
6967 t['bstroke'] = 0x0180;
6968 t['bsuperior'] = 0xF6EA;
6969 t['btopbar'] = 0x0183;
6970 t['buhiragana'] = 0x3076;
6971 t['bukatakana'] = 0x30D6;
6972 t['bullet'] = 0x2022;
6973 t['bulletinverse'] = 0x25D8;
6974 t['bulletoperator'] = 0x2219;
6975 t['bullseye'] = 0x25CE;
6976 t['c'] = 0x0063;
6977 t['caarmenian'] = 0x056E;
6978 t['cabengali'] = 0x099A;
6979 t['cacute'] = 0x0107;
6980 t['cadeva'] = 0x091A;
6981 t['cagujarati'] = 0x0A9A;
6982 t['cagurmukhi'] = 0x0A1A;
6983 t['calsquare'] = 0x3388;
6984 t['candrabindubengali'] = 0x0981;
6985 t['candrabinducmb'] = 0x0310;
6986 t['candrabindudeva'] = 0x0901;
6987 t['candrabindugujarati'] = 0x0A81;
6988 t['capslock'] = 0x21EA;
6989 t['careof'] = 0x2105;
6990 t['caron'] = 0x02C7;
6991 t['caronbelowcmb'] = 0x032C;
6992 t['caroncmb'] = 0x030C;
6993 t['carriagereturn'] = 0x21B5;
6994 t['cbopomofo'] = 0x3118;
6995 t['ccaron'] = 0x010D;
6996 t['ccedilla'] = 0x00E7;
6997 t['ccedillaacute'] = 0x1E09;
6998 t['ccircle'] = 0x24D2;
6999 t['ccircumflex'] = 0x0109;
7000 t['ccurl'] = 0x0255;
7001 t['cdot'] = 0x010B;
7002 t['cdotaccent'] = 0x010B;
7003 t['cdsquare'] = 0x33C5;
7004 t['cedilla'] = 0x00B8;
7005 t['cedillacmb'] = 0x0327;
7006 t['cent'] = 0x00A2;
7007 t['centigrade'] = 0x2103;
7008 t['centinferior'] = 0xF6DF;
7009 t['centmonospace'] = 0xFFE0;
7010 t['centoldstyle'] = 0xF7A2;
7011 t['centsuperior'] = 0xF6E0;
7012 t['chaarmenian'] = 0x0579;
7013 t['chabengali'] = 0x099B;
7014 t['chadeva'] = 0x091B;
7015 t['chagujarati'] = 0x0A9B;
7016 t['chagurmukhi'] = 0x0A1B;
7017 t['chbopomofo'] = 0x3114;
7018 t['cheabkhasiancyrillic'] = 0x04BD;
7019 t['checkmark'] = 0x2713;
7020 t['checyrillic'] = 0x0447;
7021 t['chedescenderabkhasiancyrillic'] = 0x04BF;
7022 t['chedescendercyrillic'] = 0x04B7;
7023 t['chedieresiscyrillic'] = 0x04F5;
7024 t['cheharmenian'] = 0x0573;
7025 t['chekhakassiancyrillic'] = 0x04CC;
7026 t['cheverticalstrokecyrillic'] = 0x04B9;
7027 t['chi'] = 0x03C7;
7028 t['chieuchacirclekorean'] = 0x3277;
7029 t['chieuchaparenkorean'] = 0x3217;
7030 t['chieuchcirclekorean'] = 0x3269;
7031 t['chieuchkorean'] = 0x314A;
7032 t['chieuchparenkorean'] = 0x3209;
7033 t['chochangthai'] = 0x0E0A;
7034 t['chochanthai'] = 0x0E08;
7035 t['chochingthai'] = 0x0E09;
7036 t['chochoethai'] = 0x0E0C;
7037 t['chook'] = 0x0188;
7038 t['cieucacirclekorean'] = 0x3276;
7039 t['cieucaparenkorean'] = 0x3216;
7040 t['cieuccirclekorean'] = 0x3268;
7041 t['cieuckorean'] = 0x3148;
7042 t['cieucparenkorean'] = 0x3208;
7043 t['cieucuparenkorean'] = 0x321C;
7044 t['circle'] = 0x25CB;
7045 t['circlecopyrt'] = 0x00A9; // Glyph is missing from Adobe's original list.
7046 t['circlemultiply'] = 0x2297;
7047 t['circleot'] = 0x2299;
7048 t['circleplus'] = 0x2295;
7049 t['circlepostalmark'] = 0x3036;
7050 t['circlewithlefthalfblack'] = 0x25D0;
7051 t['circlewithrighthalfblack'] = 0x25D1;
7052 t['circumflex'] = 0x02C6;
7053 t['circumflexbelowcmb'] = 0x032D;
7054 t['circumflexcmb'] = 0x0302;
7055 t['clear'] = 0x2327;
7056 t['clickalveolar'] = 0x01C2;
7057 t['clickdental'] = 0x01C0;
7058 t['clicklateral'] = 0x01C1;
7059 t['clickretroflex'] = 0x01C3;
7060 t['club'] = 0x2663;
7061 t['clubsuitblack'] = 0x2663;
7062 t['clubsuitwhite'] = 0x2667;
7063 t['cmcubedsquare'] = 0x33A4;
7064 t['cmonospace'] = 0xFF43;
7065 t['cmsquaredsquare'] = 0x33A0;
7066 t['coarmenian'] = 0x0581;
7067 t['colon'] = 0x003A;
7068 t['colonmonetary'] = 0x20A1;
7069 t['colonmonospace'] = 0xFF1A;
7070 t['colonsign'] = 0x20A1;
7071 t['colonsmall'] = 0xFE55;
7072 t['colontriangularhalfmod'] = 0x02D1;
7073 t['colontriangularmod'] = 0x02D0;
7074 t['comma'] = 0x002C;
7075 t['commaabovecmb'] = 0x0313;
7076 t['commaaboverightcmb'] = 0x0315;
7077 t['commaaccent'] = 0xF6C3;
7078 t['commaarabic'] = 0x060C;
7079 t['commaarmenian'] = 0x055D;
7080 t['commainferior'] = 0xF6E1;
7081 t['commamonospace'] = 0xFF0C;
7082 t['commareversedabovecmb'] = 0x0314;
7083 t['commareversedmod'] = 0x02BD;
7084 t['commasmall'] = 0xFE50;
7085 t['commasuperior'] = 0xF6E2;
7086 t['commaturnedabovecmb'] = 0x0312;
7087 t['commaturnedmod'] = 0x02BB;
7088 t['compass'] = 0x263C;
7089 t['congruent'] = 0x2245;
7090 t['contourintegral'] = 0x222E;
7091 t['control'] = 0x2303;
7092 t['controlACK'] = 0x0006;
7093 t['controlBEL'] = 0x0007;
7094 t['controlBS'] = 0x0008;
7095 t['controlCAN'] = 0x0018;
7096 t['controlCR'] = 0x000D;
7097 t['controlDC1'] = 0x0011;
7098 t['controlDC2'] = 0x0012;
7099 t['controlDC3'] = 0x0013;
7100 t['controlDC4'] = 0x0014;
7101 t['controlDEL'] = 0x007F;
7102 t['controlDLE'] = 0x0010;
7103 t['controlEM'] = 0x0019;
7104 t['controlENQ'] = 0x0005;
7105 t['controlEOT'] = 0x0004;
7106 t['controlESC'] = 0x001B;
7107 t['controlETB'] = 0x0017;
7108 t['controlETX'] = 0x0003;
7109 t['controlFF'] = 0x000C;
7110 t['controlFS'] = 0x001C;
7111 t['controlGS'] = 0x001D;
7112 t['controlHT'] = 0x0009;
7113 t['controlLF'] = 0x000A;
7114 t['controlNAK'] = 0x0015;
7115 t['controlRS'] = 0x001E;
7116 t['controlSI'] = 0x000F;
7117 t['controlSO'] = 0x000E;
7118 t['controlSOT'] = 0x0002;
7119 t['controlSTX'] = 0x0001;
7120 t['controlSUB'] = 0x001A;
7121 t['controlSYN'] = 0x0016;
7122 t['controlUS'] = 0x001F;
7123 t['controlVT'] = 0x000B;
7124 t['copyright'] = 0x00A9;
7125 t['copyrightsans'] = 0xF8E9;
7126 t['copyrightserif'] = 0xF6D9;
7127 t['cornerbracketleft'] = 0x300C;
7128 t['cornerbracketlefthalfwidth'] = 0xFF62;
7129 t['cornerbracketleftvertical'] = 0xFE41;
7130 t['cornerbracketright'] = 0x300D;
7131 t['cornerbracketrighthalfwidth'] = 0xFF63;
7132 t['cornerbracketrightvertical'] = 0xFE42;
7133 t['corporationsquare'] = 0x337F;
7134 t['cosquare'] = 0x33C7;
7135 t['coverkgsquare'] = 0x33C6;
7136 t['cparen'] = 0x249E;
7137 t['cruzeiro'] = 0x20A2;
7138 t['cstretched'] = 0x0297;
7139 t['curlyand'] = 0x22CF;
7140 t['curlyor'] = 0x22CE;
7141 t['currency'] = 0x00A4;
7142 t['cyrBreve'] = 0xF6D1;
7143 t['cyrFlex'] = 0xF6D2;
7144 t['cyrbreve'] = 0xF6D4;
7145 t['cyrflex'] = 0xF6D5;
7146 t['d'] = 0x0064;
7147 t['daarmenian'] = 0x0564;
7148 t['dabengali'] = 0x09A6;
7149 t['dadarabic'] = 0x0636;
7150 t['dadeva'] = 0x0926;
7151 t['dadfinalarabic'] = 0xFEBE;
7152 t['dadinitialarabic'] = 0xFEBF;
7153 t['dadmedialarabic'] = 0xFEC0;
7154 t['dagesh'] = 0x05BC;
7155 t['dageshhebrew'] = 0x05BC;
7156 t['dagger'] = 0x2020;
7157 t['daggerdbl'] = 0x2021;
7158 t['dagujarati'] = 0x0AA6;
7159 t['dagurmukhi'] = 0x0A26;
7160 t['dahiragana'] = 0x3060;
7161 t['dakatakana'] = 0x30C0;
7162 t['dalarabic'] = 0x062F;
7163 t['dalet'] = 0x05D3;
7164 t['daletdagesh'] = 0xFB33;
7165 t['daletdageshhebrew'] = 0xFB33;
7166 t['dalethebrew'] = 0x05D3;
7167 t['dalfinalarabic'] = 0xFEAA;
7168 t['dammaarabic'] = 0x064F;
7169 t['dammalowarabic'] = 0x064F;
7170 t['dammatanaltonearabic'] = 0x064C;
7171 t['dammatanarabic'] = 0x064C;
7172 t['danda'] = 0x0964;
7173 t['dargahebrew'] = 0x05A7;
7174 t['dargalefthebrew'] = 0x05A7;
7175 t['dasiapneumatacyrilliccmb'] = 0x0485;
7176 t['dblGrave'] = 0xF6D3;
7177 t['dblanglebracketleft'] = 0x300A;
7178 t['dblanglebracketleftvertical'] = 0xFE3D;
7179 t['dblanglebracketright'] = 0x300B;
7180 t['dblanglebracketrightvertical'] = 0xFE3E;
7181 t['dblarchinvertedbelowcmb'] = 0x032B;
7182 t['dblarrowleft'] = 0x21D4;
7183 t['dblarrowright'] = 0x21D2;
7184 t['dbldanda'] = 0x0965;
7185 t['dblgrave'] = 0xF6D6;
7186 t['dblgravecmb'] = 0x030F;
7187 t['dblintegral'] = 0x222C;
7188 t['dbllowline'] = 0x2017;
7189 t['dbllowlinecmb'] = 0x0333;
7190 t['dbloverlinecmb'] = 0x033F;
7191 t['dblprimemod'] = 0x02BA;
7192 t['dblverticalbar'] = 0x2016;
7193 t['dblverticallineabovecmb'] = 0x030E;
7194 t['dbopomofo'] = 0x3109;
7195 t['dbsquare'] = 0x33C8;
7196 t['dcaron'] = 0x010F;
7197 t['dcedilla'] = 0x1E11;
7198 t['dcircle'] = 0x24D3;
7199 t['dcircumflexbelow'] = 0x1E13;
7200 t['dcroat'] = 0x0111;
7201 t['ddabengali'] = 0x09A1;
7202 t['ddadeva'] = 0x0921;
7203 t['ddagujarati'] = 0x0AA1;
7204 t['ddagurmukhi'] = 0x0A21;
7205 t['ddalarabic'] = 0x0688;
7206 t['ddalfinalarabic'] = 0xFB89;
7207 t['dddhadeva'] = 0x095C;
7208 t['ddhabengali'] = 0x09A2;
7209 t['ddhadeva'] = 0x0922;
7210 t['ddhagujarati'] = 0x0AA2;
7211 t['ddhagurmukhi'] = 0x0A22;
7212 t['ddotaccent'] = 0x1E0B;
7213 t['ddotbelow'] = 0x1E0D;
7214 t['decimalseparatorarabic'] = 0x066B;
7215 t['decimalseparatorpersian'] = 0x066B;
7216 t['decyrillic'] = 0x0434;
7217 t['degree'] = 0x00B0;
7218 t['dehihebrew'] = 0x05AD;
7219 t['dehiragana'] = 0x3067;
7220 t['deicoptic'] = 0x03EF;
7221 t['dekatakana'] = 0x30C7;
7222 t['deleteleft'] = 0x232B;
7223 t['deleteright'] = 0x2326;
7224 t['delta'] = 0x03B4;
7225 t['deltaturned'] = 0x018D;
7226 t['denominatorminusonenumeratorbengali'] = 0x09F8;
7227 t['dezh'] = 0x02A4;
7228 t['dhabengali'] = 0x09A7;
7229 t['dhadeva'] = 0x0927;
7230 t['dhagujarati'] = 0x0AA7;
7231 t['dhagurmukhi'] = 0x0A27;
7232 t['dhook'] = 0x0257;
7233 t['dialytikatonos'] = 0x0385;
7234 t['dialytikatonoscmb'] = 0x0344;
7235 t['diamond'] = 0x2666;
7236 t['diamondsuitwhite'] = 0x2662;
7237 t['dieresis'] = 0x00A8;
7238 t['dieresisacute'] = 0xF6D7;
7239 t['dieresisbelowcmb'] = 0x0324;
7240 t['dieresiscmb'] = 0x0308;
7241 t['dieresisgrave'] = 0xF6D8;
7242 t['dieresistonos'] = 0x0385;
7243 t['dihiragana'] = 0x3062;
7244 t['dikatakana'] = 0x30C2;
7245 t['dittomark'] = 0x3003;
7246 t['divide'] = 0x00F7;
7247 t['divides'] = 0x2223;
7248 t['divisionslash'] = 0x2215;
7249 t['djecyrillic'] = 0x0452;
7250 t['dkshade'] = 0x2593;
7251 t['dlinebelow'] = 0x1E0F;
7252 t['dlsquare'] = 0x3397;
7253 t['dmacron'] = 0x0111;
7254 t['dmonospace'] = 0xFF44;
7255 t['dnblock'] = 0x2584;
7256 t['dochadathai'] = 0x0E0E;
7257 t['dodekthai'] = 0x0E14;
7258 t['dohiragana'] = 0x3069;
7259 t['dokatakana'] = 0x30C9;
7260 t['dollar'] = 0x0024;
7261 t['dollarinferior'] = 0xF6E3;
7262 t['dollarmonospace'] = 0xFF04;
7263 t['dollaroldstyle'] = 0xF724;
7264 t['dollarsmall'] = 0xFE69;
7265 t['dollarsuperior'] = 0xF6E4;
7266 t['dong'] = 0x20AB;
7267 t['dorusquare'] = 0x3326;
7268 t['dotaccent'] = 0x02D9;
7269 t['dotaccentcmb'] = 0x0307;
7270 t['dotbelowcmb'] = 0x0323;
7271 t['dotbelowcomb'] = 0x0323;
7272 t['dotkatakana'] = 0x30FB;
7273 t['dotlessi'] = 0x0131;
7274 t['dotlessj'] = 0xF6BE;
7275 t['dotlessjstrokehook'] = 0x0284;
7276 t['dotmath'] = 0x22C5;
7277 t['dottedcircle'] = 0x25CC;
7278 t['doubleyodpatah'] = 0xFB1F;
7279 t['doubleyodpatahhebrew'] = 0xFB1F;
7280 t['downtackbelowcmb'] = 0x031E;
7281 t['downtackmod'] = 0x02D5;
7282 t['dparen'] = 0x249F;
7283 t['dsuperior'] = 0xF6EB;
7284 t['dtail'] = 0x0256;
7285 t['dtopbar'] = 0x018C;
7286 t['duhiragana'] = 0x3065;
7287 t['dukatakana'] = 0x30C5;
7288 t['dz'] = 0x01F3;
7289 t['dzaltone'] = 0x02A3;
7290 t['dzcaron'] = 0x01C6;
7291 t['dzcurl'] = 0x02A5;
7292 t['dzeabkhasiancyrillic'] = 0x04E1;
7293 t['dzecyrillic'] = 0x0455;
7294 t['dzhecyrillic'] = 0x045F;
7295 t['e'] = 0x0065;
7296 t['eacute'] = 0x00E9;
7297 t['earth'] = 0x2641;
7298 t['ebengali'] = 0x098F;
7299 t['ebopomofo'] = 0x311C;
7300 t['ebreve'] = 0x0115;
7301 t['ecandradeva'] = 0x090D;
7302 t['ecandragujarati'] = 0x0A8D;
7303 t['ecandravowelsigndeva'] = 0x0945;
7304 t['ecandravowelsigngujarati'] = 0x0AC5;
7305 t['ecaron'] = 0x011B;
7306 t['ecedillabreve'] = 0x1E1D;
7307 t['echarmenian'] = 0x0565;
7308 t['echyiwnarmenian'] = 0x0587;
7309 t['ecircle'] = 0x24D4;
7310 t['ecircumflex'] = 0x00EA;
7311 t['ecircumflexacute'] = 0x1EBF;
7312 t['ecircumflexbelow'] = 0x1E19;
7313 t['ecircumflexdotbelow'] = 0x1EC7;
7314 t['ecircumflexgrave'] = 0x1EC1;
7315 t['ecircumflexhookabove'] = 0x1EC3;
7316 t['ecircumflextilde'] = 0x1EC5;
7317 t['ecyrillic'] = 0x0454;
7318 t['edblgrave'] = 0x0205;
7319 t['edeva'] = 0x090F;
7320 t['edieresis'] = 0x00EB;
7321 t['edot'] = 0x0117;
7322 t['edotaccent'] = 0x0117;
7323 t['edotbelow'] = 0x1EB9;
7324 t['eegurmukhi'] = 0x0A0F;
7325 t['eematragurmukhi'] = 0x0A47;
7326 t['efcyrillic'] = 0x0444;
7327 t['egrave'] = 0x00E8;
7328 t['egujarati'] = 0x0A8F;
7329 t['eharmenian'] = 0x0567;
7330 t['ehbopomofo'] = 0x311D;
7331 t['ehiragana'] = 0x3048;
7332 t['ehookabove'] = 0x1EBB;
7333 t['eibopomofo'] = 0x311F;
7334 t['eight'] = 0x0038;
7335 t['eightarabic'] = 0x0668;
7336 t['eightbengali'] = 0x09EE;
7337 t['eightcircle'] = 0x2467;
7338 t['eightcircleinversesansserif'] = 0x2791;
7339 t['eightdeva'] = 0x096E;
7340 t['eighteencircle'] = 0x2471;
7341 t['eighteenparen'] = 0x2485;
7342 t['eighteenperiod'] = 0x2499;
7343 t['eightgujarati'] = 0x0AEE;
7344 t['eightgurmukhi'] = 0x0A6E;
7345 t['eighthackarabic'] = 0x0668;
7346 t['eighthangzhou'] = 0x3028;
7347 t['eighthnotebeamed'] = 0x266B;
7348 t['eightideographicparen'] = 0x3227;
7349 t['eightinferior'] = 0x2088;
7350 t['eightmonospace'] = 0xFF18;
7351 t['eightoldstyle'] = 0xF738;
7352 t['eightparen'] = 0x247B;
7353 t['eightperiod'] = 0x248F;
7354 t['eightpersian'] = 0x06F8;
7355 t['eightroman'] = 0x2177;
7356 t['eightsuperior'] = 0x2078;
7357 t['eightthai'] = 0x0E58;
7358 t['einvertedbreve'] = 0x0207;
7359 t['eiotifiedcyrillic'] = 0x0465;
7360 t['ekatakana'] = 0x30A8;
7361 t['ekatakanahalfwidth'] = 0xFF74;
7362 t['ekonkargurmukhi'] = 0x0A74;
7363 t['ekorean'] = 0x3154;
7364 t['elcyrillic'] = 0x043B;
7365 t['element'] = 0x2208;
7366 t['elevencircle'] = 0x246A;
7367 t['elevenparen'] = 0x247E;
7368 t['elevenperiod'] = 0x2492;
7369 t['elevenroman'] = 0x217A;
7370 t['ellipsis'] = 0x2026;
7371 t['ellipsisvertical'] = 0x22EE;
7372 t['emacron'] = 0x0113;
7373 t['emacronacute'] = 0x1E17;
7374 t['emacrongrave'] = 0x1E15;
7375 t['emcyrillic'] = 0x043C;
7376 t['emdash'] = 0x2014;
7377 t['emdashvertical'] = 0xFE31;
7378 t['emonospace'] = 0xFF45;
7379 t['emphasismarkarmenian'] = 0x055B;
7380 t['emptyset'] = 0x2205;
7381 t['enbopomofo'] = 0x3123;
7382 t['encyrillic'] = 0x043D;
7383 t['endash'] = 0x2013;
7384 t['endashvertical'] = 0xFE32;
7385 t['endescendercyrillic'] = 0x04A3;
7386 t['eng'] = 0x014B;
7387 t['engbopomofo'] = 0x3125;
7388 t['enghecyrillic'] = 0x04A5;
7389 t['enhookcyrillic'] = 0x04C8;
7390 t['enspace'] = 0x2002;
7391 t['eogonek'] = 0x0119;
7392 t['eokorean'] = 0x3153;
7393 t['eopen'] = 0x025B;
7394 t['eopenclosed'] = 0x029A;
7395 t['eopenreversed'] = 0x025C;
7396 t['eopenreversedclosed'] = 0x025E;
7397 t['eopenreversedhook'] = 0x025D;
7398 t['eparen'] = 0x24A0;
7399 t['epsilon'] = 0x03B5;
7400 t['epsilontonos'] = 0x03AD;
7401 t['equal'] = 0x003D;
7402 t['equalmonospace'] = 0xFF1D;
7403 t['equalsmall'] = 0xFE66;
7404 t['equalsuperior'] = 0x207C;
7405 t['equivalence'] = 0x2261;
7406 t['erbopomofo'] = 0x3126;
7407 t['ercyrillic'] = 0x0440;
7408 t['ereversed'] = 0x0258;
7409 t['ereversedcyrillic'] = 0x044D;
7410 t['escyrillic'] = 0x0441;
7411 t['esdescendercyrillic'] = 0x04AB;
7412 t['esh'] = 0x0283;
7413 t['eshcurl'] = 0x0286;
7414 t['eshortdeva'] = 0x090E;
7415 t['eshortvowelsigndeva'] = 0x0946;
7416 t['eshreversedloop'] = 0x01AA;
7417 t['eshsquatreversed'] = 0x0285;
7418 t['esmallhiragana'] = 0x3047;
7419 t['esmallkatakana'] = 0x30A7;
7420 t['esmallkatakanahalfwidth'] = 0xFF6A;
7421 t['estimated'] = 0x212E;
7422 t['esuperior'] = 0xF6EC;
7423 t['eta'] = 0x03B7;
7424 t['etarmenian'] = 0x0568;
7425 t['etatonos'] = 0x03AE;
7426 t['eth'] = 0x00F0;
7427 t['etilde'] = 0x1EBD;
7428 t['etildebelow'] = 0x1E1B;
7429 t['etnahtafoukhhebrew'] = 0x0591;
7430 t['etnahtafoukhlefthebrew'] = 0x0591;
7431 t['etnahtahebrew'] = 0x0591;
7432 t['etnahtalefthebrew'] = 0x0591;
7433 t['eturned'] = 0x01DD;
7434 t['eukorean'] = 0x3161;
7435 t['euro'] = 0x20AC;
7436 t['evowelsignbengali'] = 0x09C7;
7437 t['evowelsigndeva'] = 0x0947;
7438 t['evowelsigngujarati'] = 0x0AC7;
7439 t['exclam'] = 0x0021;
7440 t['exclamarmenian'] = 0x055C;
7441 t['exclamdbl'] = 0x203C;
7442 t['exclamdown'] = 0x00A1;
7443 t['exclamdownsmall'] = 0xF7A1;
7444 t['exclammonospace'] = 0xFF01;
7445 t['exclamsmall'] = 0xF721;
7446 t['existential'] = 0x2203;
7447 t['ezh'] = 0x0292;
7448 t['ezhcaron'] = 0x01EF;
7449 t['ezhcurl'] = 0x0293;
7450 t['ezhreversed'] = 0x01B9;
7451 t['ezhtail'] = 0x01BA;
7452 t['f'] = 0x0066;
7453 t['fadeva'] = 0x095E;
7454 t['fagurmukhi'] = 0x0A5E;
7455 t['fahrenheit'] = 0x2109;
7456 t['fathaarabic'] = 0x064E;
7457 t['fathalowarabic'] = 0x064E;
7458 t['fathatanarabic'] = 0x064B;
7459 t['fbopomofo'] = 0x3108;
7460 t['fcircle'] = 0x24D5;
7461 t['fdotaccent'] = 0x1E1F;
7462 t['feharabic'] = 0x0641;
7463 t['feharmenian'] = 0x0586;
7464 t['fehfinalarabic'] = 0xFED2;
7465 t['fehinitialarabic'] = 0xFED3;
7466 t['fehmedialarabic'] = 0xFED4;
7467 t['feicoptic'] = 0x03E5;
7468 t['female'] = 0x2640;
7469 t['ff'] = 0xFB00;
7470 t['ffi'] = 0xFB03;
7471 t['ffl'] = 0xFB04;
7472 t['fi'] = 0xFB01;
7473 t['fifteencircle'] = 0x246E;
7474 t['fifteenparen'] = 0x2482;
7475 t['fifteenperiod'] = 0x2496;
7476 t['figuredash'] = 0x2012;
7477 t['filledbox'] = 0x25A0;
7478 t['filledrect'] = 0x25AC;
7479 t['finalkaf'] = 0x05DA;
7480 t['finalkafdagesh'] = 0xFB3A;
7481 t['finalkafdageshhebrew'] = 0xFB3A;
7482 t['finalkafhebrew'] = 0x05DA;
7483 t['finalmem'] = 0x05DD;
7484 t['finalmemhebrew'] = 0x05DD;
7485 t['finalnun'] = 0x05DF;
7486 t['finalnunhebrew'] = 0x05DF;
7487 t['finalpe'] = 0x05E3;
7488 t['finalpehebrew'] = 0x05E3;
7489 t['finaltsadi'] = 0x05E5;
7490 t['finaltsadihebrew'] = 0x05E5;
7491 t['firsttonechinese'] = 0x02C9;
7492 t['fisheye'] = 0x25C9;
7493 t['fitacyrillic'] = 0x0473;
7494 t['five'] = 0x0035;
7495 t['fivearabic'] = 0x0665;
7496 t['fivebengali'] = 0x09EB;
7497 t['fivecircle'] = 0x2464;
7498 t['fivecircleinversesansserif'] = 0x278E;
7499 t['fivedeva'] = 0x096B;
7500 t['fiveeighths'] = 0x215D;
7501 t['fivegujarati'] = 0x0AEB;
7502 t['fivegurmukhi'] = 0x0A6B;
7503 t['fivehackarabic'] = 0x0665;
7504 t['fivehangzhou'] = 0x3025;
7505 t['fiveideographicparen'] = 0x3224;
7506 t['fiveinferior'] = 0x2085;
7507 t['fivemonospace'] = 0xFF15;
7508 t['fiveoldstyle'] = 0xF735;
7509 t['fiveparen'] = 0x2478;
7510 t['fiveperiod'] = 0x248C;
7511 t['fivepersian'] = 0x06F5;
7512 t['fiveroman'] = 0x2174;
7513 t['fivesuperior'] = 0x2075;
7514 t['fivethai'] = 0x0E55;
7515 t['fl'] = 0xFB02;
7516 t['florin'] = 0x0192;
7517 t['fmonospace'] = 0xFF46;
7518 t['fmsquare'] = 0x3399;
7519 t['fofanthai'] = 0x0E1F;
7520 t['fofathai'] = 0x0E1D;
7521 t['fongmanthai'] = 0x0E4F;
7522 t['forall'] = 0x2200;
7523 t['four'] = 0x0034;
7524 t['fourarabic'] = 0x0664;
7525 t['fourbengali'] = 0x09EA;
7526 t['fourcircle'] = 0x2463;
7527 t['fourcircleinversesansserif'] = 0x278D;
7528 t['fourdeva'] = 0x096A;
7529 t['fourgujarati'] = 0x0AEA;
7530 t['fourgurmukhi'] = 0x0A6A;
7531 t['fourhackarabic'] = 0x0664;
7532 t['fourhangzhou'] = 0x3024;
7533 t['fourideographicparen'] = 0x3223;
7534 t['fourinferior'] = 0x2084;
7535 t['fourmonospace'] = 0xFF14;
7536 t['fournumeratorbengali'] = 0x09F7;
7537 t['fouroldstyle'] = 0xF734;
7538 t['fourparen'] = 0x2477;
7539 t['fourperiod'] = 0x248B;
7540 t['fourpersian'] = 0x06F4;
7541 t['fourroman'] = 0x2173;
7542 t['foursuperior'] = 0x2074;
7543 t['fourteencircle'] = 0x246D;
7544 t['fourteenparen'] = 0x2481;
7545 t['fourteenperiod'] = 0x2495;
7546 t['fourthai'] = 0x0E54;
7547 t['fourthtonechinese'] = 0x02CB;
7548 t['fparen'] = 0x24A1;
7549 t['fraction'] = 0x2044;
7550 t['franc'] = 0x20A3;
7551 t['g'] = 0x0067;
7552 t['gabengali'] = 0x0997;
7553 t['gacute'] = 0x01F5;
7554 t['gadeva'] = 0x0917;
7555 t['gafarabic'] = 0x06AF;
7556 t['gaffinalarabic'] = 0xFB93;
7557 t['gafinitialarabic'] = 0xFB94;
7558 t['gafmedialarabic'] = 0xFB95;
7559 t['gagujarati'] = 0x0A97;
7560 t['gagurmukhi'] = 0x0A17;
7561 t['gahiragana'] = 0x304C;
7562 t['gakatakana'] = 0x30AC;
7563 t['gamma'] = 0x03B3;
7564 t['gammalatinsmall'] = 0x0263;
7565 t['gammasuperior'] = 0x02E0;
7566 t['gangiacoptic'] = 0x03EB;
7567 t['gbopomofo'] = 0x310D;
7568 t['gbreve'] = 0x011F;
7569 t['gcaron'] = 0x01E7;
7570 t['gcedilla'] = 0x0123;
7571 t['gcircle'] = 0x24D6;
7572 t['gcircumflex'] = 0x011D;
7573 t['gcommaaccent'] = 0x0123;
7574 t['gdot'] = 0x0121;
7575 t['gdotaccent'] = 0x0121;
7576 t['gecyrillic'] = 0x0433;
7577 t['gehiragana'] = 0x3052;
7578 t['gekatakana'] = 0x30B2;
7579 t['geometricallyequal'] = 0x2251;
7580 t['gereshaccenthebrew'] = 0x059C;
7581 t['gereshhebrew'] = 0x05F3;
7582 t['gereshmuqdamhebrew'] = 0x059D;
7583 t['germandbls'] = 0x00DF;
7584 t['gershayimaccenthebrew'] = 0x059E;
7585 t['gershayimhebrew'] = 0x05F4;
7586 t['getamark'] = 0x3013;
7587 t['ghabengali'] = 0x0998;
7588 t['ghadarmenian'] = 0x0572;
7589 t['ghadeva'] = 0x0918;
7590 t['ghagujarati'] = 0x0A98;
7591 t['ghagurmukhi'] = 0x0A18;
7592 t['ghainarabic'] = 0x063A;
7593 t['ghainfinalarabic'] = 0xFECE;
7594 t['ghaininitialarabic'] = 0xFECF;
7595 t['ghainmedialarabic'] = 0xFED0;
7596 t['ghemiddlehookcyrillic'] = 0x0495;
7597 t['ghestrokecyrillic'] = 0x0493;
7598 t['gheupturncyrillic'] = 0x0491;
7599 t['ghhadeva'] = 0x095A;
7600 t['ghhagurmukhi'] = 0x0A5A;
7601 t['ghook'] = 0x0260;
7602 t['ghzsquare'] = 0x3393;
7603 t['gihiragana'] = 0x304E;
7604 t['gikatakana'] = 0x30AE;
7605 t['gimarmenian'] = 0x0563;
7606 t['gimel'] = 0x05D2;
7607 t['gimeldagesh'] = 0xFB32;
7608 t['gimeldageshhebrew'] = 0xFB32;
7609 t['gimelhebrew'] = 0x05D2;
7610 t['gjecyrillic'] = 0x0453;
7611 t['glottalinvertedstroke'] = 0x01BE;
7612 t['glottalstop'] = 0x0294;
7613 t['glottalstopinverted'] = 0x0296;
7614 t['glottalstopmod'] = 0x02C0;
7615 t['glottalstopreversed'] = 0x0295;
7616 t['glottalstopreversedmod'] = 0x02C1;
7617 t['glottalstopreversedsuperior'] = 0x02E4;
7618 t['glottalstopstroke'] = 0x02A1;
7619 t['glottalstopstrokereversed'] = 0x02A2;
7620 t['gmacron'] = 0x1E21;
7621 t['gmonospace'] = 0xFF47;
7622 t['gohiragana'] = 0x3054;
7623 t['gokatakana'] = 0x30B4;
7624 t['gparen'] = 0x24A2;
7625 t['gpasquare'] = 0x33AC;
7626 t['gradient'] = 0x2207;
7627 t['grave'] = 0x0060;
7628 t['gravebelowcmb'] = 0x0316;
7629 t['gravecmb'] = 0x0300;
7630 t['gravecomb'] = 0x0300;
7631 t['gravedeva'] = 0x0953;
7632 t['gravelowmod'] = 0x02CE;
7633 t['gravemonospace'] = 0xFF40;
7634 t['gravetonecmb'] = 0x0340;
7635 t['greater'] = 0x003E;
7636 t['greaterequal'] = 0x2265;
7637 t['greaterequalorless'] = 0x22DB;
7638 t['greatermonospace'] = 0xFF1E;
7639 t['greaterorequivalent'] = 0x2273;
7640 t['greaterorless'] = 0x2277;
7641 t['greateroverequal'] = 0x2267;
7642 t['greatersmall'] = 0xFE65;
7643 t['gscript'] = 0x0261;
7644 t['gstroke'] = 0x01E5;
7645 t['guhiragana'] = 0x3050;
7646 t['guillemotleft'] = 0x00AB;
7647 t['guillemotright'] = 0x00BB;
7648 t['guilsinglleft'] = 0x2039;
7649 t['guilsinglright'] = 0x203A;
7650 t['gukatakana'] = 0x30B0;
7651 t['guramusquare'] = 0x3318;
7652 t['gysquare'] = 0x33C9;
7653 t['h'] = 0x0068;
7654 t['haabkhasiancyrillic'] = 0x04A9;
7655 t['haaltonearabic'] = 0x06C1;
7656 t['habengali'] = 0x09B9;
7657 t['hadescendercyrillic'] = 0x04B3;
7658 t['hadeva'] = 0x0939;
7659 t['hagujarati'] = 0x0AB9;
7660 t['hagurmukhi'] = 0x0A39;
7661 t['haharabic'] = 0x062D;
7662 t['hahfinalarabic'] = 0xFEA2;
7663 t['hahinitialarabic'] = 0xFEA3;
7664 t['hahiragana'] = 0x306F;
7665 t['hahmedialarabic'] = 0xFEA4;
7666 t['haitusquare'] = 0x332A;
7667 t['hakatakana'] = 0x30CF;
7668 t['hakatakanahalfwidth'] = 0xFF8A;
7669 t['halantgurmukhi'] = 0x0A4D;
7670 t['hamzaarabic'] = 0x0621;
7671 t['hamzalowarabic'] = 0x0621;
7672 t['hangulfiller'] = 0x3164;
7673 t['hardsigncyrillic'] = 0x044A;
7674 t['harpoonleftbarbup'] = 0x21BC;
7675 t['harpoonrightbarbup'] = 0x21C0;
7676 t['hasquare'] = 0x33CA;
7677 t['hatafpatah'] = 0x05B2;
7678 t['hatafpatah16'] = 0x05B2;
7679 t['hatafpatah23'] = 0x05B2;
7680 t['hatafpatah2f'] = 0x05B2;
7681 t['hatafpatahhebrew'] = 0x05B2;
7682 t['hatafpatahnarrowhebrew'] = 0x05B2;
7683 t['hatafpatahquarterhebrew'] = 0x05B2;
7684 t['hatafpatahwidehebrew'] = 0x05B2;
7685 t['hatafqamats'] = 0x05B3;
7686 t['hatafqamats1b'] = 0x05B3;
7687 t['hatafqamats28'] = 0x05B3;
7688 t['hatafqamats34'] = 0x05B3;
7689 t['hatafqamatshebrew'] = 0x05B3;
7690 t['hatafqamatsnarrowhebrew'] = 0x05B3;
7691 t['hatafqamatsquarterhebrew'] = 0x05B3;
7692 t['hatafqamatswidehebrew'] = 0x05B3;
7693 t['hatafsegol'] = 0x05B1;
7694 t['hatafsegol17'] = 0x05B1;
7695 t['hatafsegol24'] = 0x05B1;
7696 t['hatafsegol30'] = 0x05B1;
7697 t['hatafsegolhebrew'] = 0x05B1;
7698 t['hatafsegolnarrowhebrew'] = 0x05B1;
7699 t['hatafsegolquarterhebrew'] = 0x05B1;
7700 t['hatafsegolwidehebrew'] = 0x05B1;
7701 t['hbar'] = 0x0127;
7702 t['hbopomofo'] = 0x310F;
7703 t['hbrevebelow'] = 0x1E2B;
7704 t['hcedilla'] = 0x1E29;
7705 t['hcircle'] = 0x24D7;
7706 t['hcircumflex'] = 0x0125;
7707 t['hdieresis'] = 0x1E27;
7708 t['hdotaccent'] = 0x1E23;
7709 t['hdotbelow'] = 0x1E25;
7710 t['he'] = 0x05D4;
7711 t['heart'] = 0x2665;
7712 t['heartsuitblack'] = 0x2665;
7713 t['heartsuitwhite'] = 0x2661;
7714 t['hedagesh'] = 0xFB34;
7715 t['hedageshhebrew'] = 0xFB34;
7716 t['hehaltonearabic'] = 0x06C1;
7717 t['heharabic'] = 0x0647;
7718 t['hehebrew'] = 0x05D4;
7719 t['hehfinalaltonearabic'] = 0xFBA7;
7720 t['hehfinalalttwoarabic'] = 0xFEEA;
7721 t['hehfinalarabic'] = 0xFEEA;
7722 t['hehhamzaabovefinalarabic'] = 0xFBA5;
7723 t['hehhamzaaboveisolatedarabic'] = 0xFBA4;
7724 t['hehinitialaltonearabic'] = 0xFBA8;
7725 t['hehinitialarabic'] = 0xFEEB;
7726 t['hehiragana'] = 0x3078;
7727 t['hehmedialaltonearabic'] = 0xFBA9;
7728 t['hehmedialarabic'] = 0xFEEC;
7729 t['heiseierasquare'] = 0x337B;
7730 t['hekatakana'] = 0x30D8;
7731 t['hekatakanahalfwidth'] = 0xFF8D;
7732 t['hekutaarusquare'] = 0x3336;
7733 t['henghook'] = 0x0267;
7734 t['herutusquare'] = 0x3339;
7735 t['het'] = 0x05D7;
7736 t['hethebrew'] = 0x05D7;
7737 t['hhook'] = 0x0266;
7738 t['hhooksuperior'] = 0x02B1;
7739 t['hieuhacirclekorean'] = 0x327B;
7740 t['hieuhaparenkorean'] = 0x321B;
7741 t['hieuhcirclekorean'] = 0x326D;
7742 t['hieuhkorean'] = 0x314E;
7743 t['hieuhparenkorean'] = 0x320D;
7744 t['hihiragana'] = 0x3072;
7745 t['hikatakana'] = 0x30D2;
7746 t['hikatakanahalfwidth'] = 0xFF8B;
7747 t['hiriq'] = 0x05B4;
7748 t['hiriq14'] = 0x05B4;
7749 t['hiriq21'] = 0x05B4;
7750 t['hiriq2d'] = 0x05B4;
7751 t['hiriqhebrew'] = 0x05B4;
7752 t['hiriqnarrowhebrew'] = 0x05B4;
7753 t['hiriqquarterhebrew'] = 0x05B4;
7754 t['hiriqwidehebrew'] = 0x05B4;
7755 t['hlinebelow'] = 0x1E96;
7756 t['hmonospace'] = 0xFF48;
7757 t['hoarmenian'] = 0x0570;
7758 t['hohipthai'] = 0x0E2B;
7759 t['hohiragana'] = 0x307B;
7760 t['hokatakana'] = 0x30DB;
7761 t['hokatakanahalfwidth'] = 0xFF8E;
7762 t['holam'] = 0x05B9;
7763 t['holam19'] = 0x05B9;
7764 t['holam26'] = 0x05B9;
7765 t['holam32'] = 0x05B9;
7766 t['holamhebrew'] = 0x05B9;
7767 t['holamnarrowhebrew'] = 0x05B9;
7768 t['holamquarterhebrew'] = 0x05B9;
7769 t['holamwidehebrew'] = 0x05B9;
7770 t['honokhukthai'] = 0x0E2E;
7771 t['hookabovecomb'] = 0x0309;
7772 t['hookcmb'] = 0x0309;
7773 t['hookpalatalizedbelowcmb'] = 0x0321;
7774 t['hookretroflexbelowcmb'] = 0x0322;
7775 t['hoonsquare'] = 0x3342;
7776 t['horicoptic'] = 0x03E9;
7777 t['horizontalbar'] = 0x2015;
7778 t['horncmb'] = 0x031B;
7779 t['hotsprings'] = 0x2668;
7780 t['house'] = 0x2302;
7781 t['hparen'] = 0x24A3;
7782 t['hsuperior'] = 0x02B0;
7783 t['hturned'] = 0x0265;
7784 t['huhiragana'] = 0x3075;
7785 t['huiitosquare'] = 0x3333;
7786 t['hukatakana'] = 0x30D5;
7787 t['hukatakanahalfwidth'] = 0xFF8C;
7788 t['hungarumlaut'] = 0x02DD;
7789 t['hungarumlautcmb'] = 0x030B;
7790 t['hv'] = 0x0195;
7791 t['hyphen'] = 0x002D;
7792 t['hypheninferior'] = 0xF6E5;
7793 t['hyphenmonospace'] = 0xFF0D;
7794 t['hyphensmall'] = 0xFE63;
7795 t['hyphensuperior'] = 0xF6E6;
7796 t['hyphentwo'] = 0x2010;
7797 t['i'] = 0x0069;
7798 t['iacute'] = 0x00ED;
7799 t['iacyrillic'] = 0x044F;
7800 t['ibengali'] = 0x0987;
7801 t['ibopomofo'] = 0x3127;
7802 t['ibreve'] = 0x012D;
7803 t['icaron'] = 0x01D0;
7804 t['icircle'] = 0x24D8;
7805 t['icircumflex'] = 0x00EE;
7806 t['icyrillic'] = 0x0456;
7807 t['idblgrave'] = 0x0209;
7808 t['ideographearthcircle'] = 0x328F;
7809 t['ideographfirecircle'] = 0x328B;
7810 t['ideographicallianceparen'] = 0x323F;
7811 t['ideographiccallparen'] = 0x323A;
7812 t['ideographiccentrecircle'] = 0x32A5;
7813 t['ideographicclose'] = 0x3006;
7814 t['ideographiccomma'] = 0x3001;
7815 t['ideographiccommaleft'] = 0xFF64;
7816 t['ideographiccongratulationparen'] = 0x3237;
7817 t['ideographiccorrectcircle'] = 0x32A3;
7818 t['ideographicearthparen'] = 0x322F;
7819 t['ideographicenterpriseparen'] = 0x323D;
7820 t['ideographicexcellentcircle'] = 0x329D;
7821 t['ideographicfestivalparen'] = 0x3240;
7822 t['ideographicfinancialcircle'] = 0x3296;
7823 t['ideographicfinancialparen'] = 0x3236;
7824 t['ideographicfireparen'] = 0x322B;
7825 t['ideographichaveparen'] = 0x3232;
7826 t['ideographichighcircle'] = 0x32A4;
7827 t['ideographiciterationmark'] = 0x3005;
7828 t['ideographiclaborcircle'] = 0x3298;
7829 t['ideographiclaborparen'] = 0x3238;
7830 t['ideographicleftcircle'] = 0x32A7;
7831 t['ideographiclowcircle'] = 0x32A6;
7832 t['ideographicmedicinecircle'] = 0x32A9;
7833 t['ideographicmetalparen'] = 0x322E;
7834 t['ideographicmoonparen'] = 0x322A;
7835 t['ideographicnameparen'] = 0x3234;
7836 t['ideographicperiod'] = 0x3002;
7837 t['ideographicprintcircle'] = 0x329E;
7838 t['ideographicreachparen'] = 0x3243;
7839 t['ideographicrepresentparen'] = 0x3239;
7840 t['ideographicresourceparen'] = 0x323E;
7841 t['ideographicrightcircle'] = 0x32A8;
7842 t['ideographicsecretcircle'] = 0x3299;
7843 t['ideographicselfparen'] = 0x3242;
7844 t['ideographicsocietyparen'] = 0x3233;
7845 t['ideographicspace'] = 0x3000;
7846 t['ideographicspecialparen'] = 0x3235;
7847 t['ideographicstockparen'] = 0x3231;
7848 t['ideographicstudyparen'] = 0x323B;
7849 t['ideographicsunparen'] = 0x3230;
7850 t['ideographicsuperviseparen'] = 0x323C;
7851 t['ideographicwaterparen'] = 0x322C;
7852 t['ideographicwoodparen'] = 0x322D;
7853 t['ideographiczero'] = 0x3007;
7854 t['ideographmetalcircle'] = 0x328E;
7855 t['ideographmooncircle'] = 0x328A;
7856 t['ideographnamecircle'] = 0x3294;
7857 t['ideographsuncircle'] = 0x3290;
7858 t['ideographwatercircle'] = 0x328C;
7859 t['ideographwoodcircle'] = 0x328D;
7860 t['ideva'] = 0x0907;
7861 t['idieresis'] = 0x00EF;
7862 t['idieresisacute'] = 0x1E2F;
7863 t['idieresiscyrillic'] = 0x04E5;
7864 t['idotbelow'] = 0x1ECB;
7865 t['iebrevecyrillic'] = 0x04D7;
7866 t['iecyrillic'] = 0x0435;
7867 t['ieungacirclekorean'] = 0x3275;
7868 t['ieungaparenkorean'] = 0x3215;
7869 t['ieungcirclekorean'] = 0x3267;
7870 t['ieungkorean'] = 0x3147;
7871 t['ieungparenkorean'] = 0x3207;
7872 t['igrave'] = 0x00EC;
7873 t['igujarati'] = 0x0A87;
7874 t['igurmukhi'] = 0x0A07;
7875 t['ihiragana'] = 0x3044;
7876 t['ihookabove'] = 0x1EC9;
7877 t['iibengali'] = 0x0988;
7878 t['iicyrillic'] = 0x0438;
7879 t['iideva'] = 0x0908;
7880 t['iigujarati'] = 0x0A88;
7881 t['iigurmukhi'] = 0x0A08;
7882 t['iimatragurmukhi'] = 0x0A40;
7883 t['iinvertedbreve'] = 0x020B;
7884 t['iishortcyrillic'] = 0x0439;
7885 t['iivowelsignbengali'] = 0x09C0;
7886 t['iivowelsigndeva'] = 0x0940;
7887 t['iivowelsigngujarati'] = 0x0AC0;
7888 t['ij'] = 0x0133;
7889 t['ikatakana'] = 0x30A4;
7890 t['ikatakanahalfwidth'] = 0xFF72;
7891 t['ikorean'] = 0x3163;
7892 t['ilde'] = 0x02DC;
7893 t['iluyhebrew'] = 0x05AC;
7894 t['imacron'] = 0x012B;
7895 t['imacroncyrillic'] = 0x04E3;
7896 t['imageorapproximatelyequal'] = 0x2253;
7897 t['imatragurmukhi'] = 0x0A3F;
7898 t['imonospace'] = 0xFF49;
7899 t['increment'] = 0x2206;
7900 t['infinity'] = 0x221E;
7901 t['iniarmenian'] = 0x056B;
7902 t['integral'] = 0x222B;
7903 t['integralbottom'] = 0x2321;
7904 t['integralbt'] = 0x2321;
7905 t['integralex'] = 0xF8F5;
7906 t['integraltop'] = 0x2320;
7907 t['integraltp'] = 0x2320;
7908 t['intersection'] = 0x2229;
7909 t['intisquare'] = 0x3305;
7910 t['invbullet'] = 0x25D8;
7911 t['invcircle'] = 0x25D9;
7912 t['invsmileface'] = 0x263B;
7913 t['iocyrillic'] = 0x0451;
7914 t['iogonek'] = 0x012F;
7915 t['iota'] = 0x03B9;
7916 t['iotadieresis'] = 0x03CA;
7917 t['iotadieresistonos'] = 0x0390;
7918 t['iotalatin'] = 0x0269;
7919 t['iotatonos'] = 0x03AF;
7920 t['iparen'] = 0x24A4;
7921 t['irigurmukhi'] = 0x0A72;
7922 t['ismallhiragana'] = 0x3043;
7923 t['ismallkatakana'] = 0x30A3;
7924 t['ismallkatakanahalfwidth'] = 0xFF68;
7925 t['issharbengali'] = 0x09FA;
7926 t['istroke'] = 0x0268;
7927 t['isuperior'] = 0xF6ED;
7928 t['iterationhiragana'] = 0x309D;
7929 t['iterationkatakana'] = 0x30FD;
7930 t['itilde'] = 0x0129;
7931 t['itildebelow'] = 0x1E2D;
7932 t['iubopomofo'] = 0x3129;
7933 t['iucyrillic'] = 0x044E;
7934 t['ivowelsignbengali'] = 0x09BF;
7935 t['ivowelsigndeva'] = 0x093F;
7936 t['ivowelsigngujarati'] = 0x0ABF;
7937 t['izhitsacyrillic'] = 0x0475;
7938 t['izhitsadblgravecyrillic'] = 0x0477;
7939 t['j'] = 0x006A;
7940 t['jaarmenian'] = 0x0571;
7941 t['jabengali'] = 0x099C;
7942 t['jadeva'] = 0x091C;
7943 t['jagujarati'] = 0x0A9C;
7944 t['jagurmukhi'] = 0x0A1C;
7945 t['jbopomofo'] = 0x3110;
7946 t['jcaron'] = 0x01F0;
7947 t['jcircle'] = 0x24D9;
7948 t['jcircumflex'] = 0x0135;
7949 t['jcrossedtail'] = 0x029D;
7950 t['jdotlessstroke'] = 0x025F;
7951 t['jecyrillic'] = 0x0458;
7952 t['jeemarabic'] = 0x062C;
7953 t['jeemfinalarabic'] = 0xFE9E;
7954 t['jeeminitialarabic'] = 0xFE9F;
7955 t['jeemmedialarabic'] = 0xFEA0;
7956 t['jeharabic'] = 0x0698;
7957 t['jehfinalarabic'] = 0xFB8B;
7958 t['jhabengali'] = 0x099D;
7959 t['jhadeva'] = 0x091D;
7960 t['jhagujarati'] = 0x0A9D;
7961 t['jhagurmukhi'] = 0x0A1D;
7962 t['jheharmenian'] = 0x057B;
7963 t['jis'] = 0x3004;
7964 t['jmonospace'] = 0xFF4A;
7965 t['jparen'] = 0x24A5;
7966 t['jsuperior'] = 0x02B2;
7967 t['k'] = 0x006B;
7968 t['kabashkircyrillic'] = 0x04A1;
7969 t['kabengali'] = 0x0995;
7970 t['kacute'] = 0x1E31;
7971 t['kacyrillic'] = 0x043A;
7972 t['kadescendercyrillic'] = 0x049B;
7973 t['kadeva'] = 0x0915;
7974 t['kaf'] = 0x05DB;
7975 t['kafarabic'] = 0x0643;
7976 t['kafdagesh'] = 0xFB3B;
7977 t['kafdageshhebrew'] = 0xFB3B;
7978 t['kaffinalarabic'] = 0xFEDA;
7979 t['kafhebrew'] = 0x05DB;
7980 t['kafinitialarabic'] = 0xFEDB;
7981 t['kafmedialarabic'] = 0xFEDC;
7982 t['kafrafehebrew'] = 0xFB4D;
7983 t['kagujarati'] = 0x0A95;
7984 t['kagurmukhi'] = 0x0A15;
7985 t['kahiragana'] = 0x304B;
7986 t['kahookcyrillic'] = 0x04C4;
7987 t['kakatakana'] = 0x30AB;
7988 t['kakatakanahalfwidth'] = 0xFF76;
7989 t['kappa'] = 0x03BA;
7990 t['kappasymbolgreek'] = 0x03F0;
7991 t['kapyeounmieumkorean'] = 0x3171;
7992 t['kapyeounphieuphkorean'] = 0x3184;
7993 t['kapyeounpieupkorean'] = 0x3178;
7994 t['kapyeounssangpieupkorean'] = 0x3179;
7995 t['karoriisquare'] = 0x330D;
7996 t['kashidaautoarabic'] = 0x0640;
7997 t['kashidaautonosidebearingarabic'] = 0x0640;
7998 t['kasmallkatakana'] = 0x30F5;
7999 t['kasquare'] = 0x3384;
8000 t['kasraarabic'] = 0x0650;
8001 t['kasratanarabic'] = 0x064D;
8002 t['kastrokecyrillic'] = 0x049F;
8003 t['katahiraprolongmarkhalfwidth'] = 0xFF70;
8004 t['kaverticalstrokecyrillic'] = 0x049D;
8005 t['kbopomofo'] = 0x310E;
8006 t['kcalsquare'] = 0x3389;
8007 t['kcaron'] = 0x01E9;
8008 t['kcedilla'] = 0x0137;
8009 t['kcircle'] = 0x24DA;
8010 t['kcommaaccent'] = 0x0137;
8011 t['kdotbelow'] = 0x1E33;
8012 t['keharmenian'] = 0x0584;
8013 t['kehiragana'] = 0x3051;
8014 t['kekatakana'] = 0x30B1;
8015 t['kekatakanahalfwidth'] = 0xFF79;
8016 t['kenarmenian'] = 0x056F;
8017 t['kesmallkatakana'] = 0x30F6;
8018 t['kgreenlandic'] = 0x0138;
8019 t['khabengali'] = 0x0996;
8020 t['khacyrillic'] = 0x0445;
8021 t['khadeva'] = 0x0916;
8022 t['khagujarati'] = 0x0A96;
8023 t['khagurmukhi'] = 0x0A16;
8024 t['khaharabic'] = 0x062E;
8025 t['khahfinalarabic'] = 0xFEA6;
8026 t['khahinitialarabic'] = 0xFEA7;
8027 t['khahmedialarabic'] = 0xFEA8;
8028 t['kheicoptic'] = 0x03E7;
8029 t['khhadeva'] = 0x0959;
8030 t['khhagurmukhi'] = 0x0A59;
8031 t['khieukhacirclekorean'] = 0x3278;
8032 t['khieukhaparenkorean'] = 0x3218;
8033 t['khieukhcirclekorean'] = 0x326A;
8034 t['khieukhkorean'] = 0x314B;
8035 t['khieukhparenkorean'] = 0x320A;
8036 t['khokhaithai'] = 0x0E02;
8037 t['khokhonthai'] = 0x0E05;
8038 t['khokhuatthai'] = 0x0E03;
8039 t['khokhwaithai'] = 0x0E04;
8040 t['khomutthai'] = 0x0E5B;
8041 t['khook'] = 0x0199;
8042 t['khorakhangthai'] = 0x0E06;
8043 t['khzsquare'] = 0x3391;
8044 t['kihiragana'] = 0x304D;
8045 t['kikatakana'] = 0x30AD;
8046 t['kikatakanahalfwidth'] = 0xFF77;
8047 t['kiroguramusquare'] = 0x3315;
8048 t['kiromeetorusquare'] = 0x3316;
8049 t['kirosquare'] = 0x3314;
8050 t['kiyeokacirclekorean'] = 0x326E;
8051 t['kiyeokaparenkorean'] = 0x320E;
8052 t['kiyeokcirclekorean'] = 0x3260;
8053 t['kiyeokkorean'] = 0x3131;
8054 t['kiyeokparenkorean'] = 0x3200;
8055 t['kiyeoksioskorean'] = 0x3133;
8056 t['kjecyrillic'] = 0x045C;
8057 t['klinebelow'] = 0x1E35;
8058 t['klsquare'] = 0x3398;
8059 t['kmcubedsquare'] = 0x33A6;
8060 t['kmonospace'] = 0xFF4B;
8061 t['kmsquaredsquare'] = 0x33A2;
8062 t['kohiragana'] = 0x3053;
8063 t['kohmsquare'] = 0x33C0;
8064 t['kokaithai'] = 0x0E01;
8065 t['kokatakana'] = 0x30B3;
8066 t['kokatakanahalfwidth'] = 0xFF7A;
8067 t['kooposquare'] = 0x331E;
8068 t['koppacyrillic'] = 0x0481;
8069 t['koreanstandardsymbol'] = 0x327F;
8070 t['koroniscmb'] = 0x0343;
8071 t['kparen'] = 0x24A6;
8072 t['kpasquare'] = 0x33AA;
8073 t['ksicyrillic'] = 0x046F;
8074 t['ktsquare'] = 0x33CF;
8075 t['kturned'] = 0x029E;
8076 t['kuhiragana'] = 0x304F;
8077 t['kukatakana'] = 0x30AF;
8078 t['kukatakanahalfwidth'] = 0xFF78;
8079 t['kvsquare'] = 0x33B8;
8080 t['kwsquare'] = 0x33BE;
8081 t['l'] = 0x006C;
8082 t['labengali'] = 0x09B2;
8083 t['lacute'] = 0x013A;
8084 t['ladeva'] = 0x0932;
8085 t['lagujarati'] = 0x0AB2;
8086 t['lagurmukhi'] = 0x0A32;
8087 t['lakkhangyaothai'] = 0x0E45;
8088 t['lamaleffinalarabic'] = 0xFEFC;
8089 t['lamalefhamzaabovefinalarabic'] = 0xFEF8;
8090 t['lamalefhamzaaboveisolatedarabic'] = 0xFEF7;
8091 t['lamalefhamzabelowfinalarabic'] = 0xFEFA;
8092 t['lamalefhamzabelowisolatedarabic'] = 0xFEF9;
8093 t['lamalefisolatedarabic'] = 0xFEFB;
8094 t['lamalefmaddaabovefinalarabic'] = 0xFEF6;
8095 t['lamalefmaddaaboveisolatedarabic'] = 0xFEF5;
8096 t['lamarabic'] = 0x0644;
8097 t['lambda'] = 0x03BB;
8098 t['lambdastroke'] = 0x019B;
8099 t['lamed'] = 0x05DC;
8100 t['lameddagesh'] = 0xFB3C;
8101 t['lameddageshhebrew'] = 0xFB3C;
8102 t['lamedhebrew'] = 0x05DC;
8103 t['lamfinalarabic'] = 0xFEDE;
8104 t['lamhahinitialarabic'] = 0xFCCA;
8105 t['laminitialarabic'] = 0xFEDF;
8106 t['lamjeeminitialarabic'] = 0xFCC9;
8107 t['lamkhahinitialarabic'] = 0xFCCB;
8108 t['lamlamhehisolatedarabic'] = 0xFDF2;
8109 t['lammedialarabic'] = 0xFEE0;
8110 t['lammeemhahinitialarabic'] = 0xFD88;
8111 t['lammeeminitialarabic'] = 0xFCCC;
8112 t['largecircle'] = 0x25EF;
8113 t['lbar'] = 0x019A;
8114 t['lbelt'] = 0x026C;
8115 t['lbopomofo'] = 0x310C;
8116 t['lcaron'] = 0x013E;
8117 t['lcedilla'] = 0x013C;
8118 t['lcircle'] = 0x24DB;
8119 t['lcircumflexbelow'] = 0x1E3D;
8120 t['lcommaaccent'] = 0x013C;
8121 t['ldot'] = 0x0140;
8122 t['ldotaccent'] = 0x0140;
8123 t['ldotbelow'] = 0x1E37;
8124 t['ldotbelowmacron'] = 0x1E39;
8125 t['leftangleabovecmb'] = 0x031A;
8126 t['lefttackbelowcmb'] = 0x0318;
8127 t['less'] = 0x003C;
8128 t['lessequal'] = 0x2264;
8129 t['lessequalorgreater'] = 0x22DA;
8130 t['lessmonospace'] = 0xFF1C;
8131 t['lessorequivalent'] = 0x2272;
8132 t['lessorgreater'] = 0x2276;
8133 t['lessoverequal'] = 0x2266;
8134 t['lesssmall'] = 0xFE64;
8135 t['lezh'] = 0x026E;
8136 t['lfblock'] = 0x258C;
8137 t['lhookretroflex'] = 0x026D;
8138 t['lira'] = 0x20A4;
8139 t['liwnarmenian'] = 0x056C;
8140 t['lj'] = 0x01C9;
8141 t['ljecyrillic'] = 0x0459;
8142 t['ll'] = 0xF6C0;
8143 t['lladeva'] = 0x0933;
8144 t['llagujarati'] = 0x0AB3;
8145 t['llinebelow'] = 0x1E3B;
8146 t['llladeva'] = 0x0934;
8147 t['llvocalicbengali'] = 0x09E1;
8148 t['llvocalicdeva'] = 0x0961;
8149 t['llvocalicvowelsignbengali'] = 0x09E3;
8150 t['llvocalicvowelsigndeva'] = 0x0963;
8151 t['lmiddletilde'] = 0x026B;
8152 t['lmonospace'] = 0xFF4C;
8153 t['lmsquare'] = 0x33D0;
8154 t['lochulathai'] = 0x0E2C;
8155 t['logicaland'] = 0x2227;
8156 t['logicalnot'] = 0x00AC;
8157 t['logicalnotreversed'] = 0x2310;
8158 t['logicalor'] = 0x2228;
8159 t['lolingthai'] = 0x0E25;
8160 t['longs'] = 0x017F;
8161 t['lowlinecenterline'] = 0xFE4E;
8162 t['lowlinecmb'] = 0x0332;
8163 t['lowlinedashed'] = 0xFE4D;
8164 t['lozenge'] = 0x25CA;
8165 t['lparen'] = 0x24A7;
8166 t['lslash'] = 0x0142;
8167 t['lsquare'] = 0x2113;
8168 t['lsuperior'] = 0xF6EE;
8169 t['ltshade'] = 0x2591;
8170 t['luthai'] = 0x0E26;
8171 t['lvocalicbengali'] = 0x098C;
8172 t['lvocalicdeva'] = 0x090C;
8173 t['lvocalicvowelsignbengali'] = 0x09E2;
8174 t['lvocalicvowelsigndeva'] = 0x0962;
8175 t['lxsquare'] = 0x33D3;
8176 t['m'] = 0x006D;
8177 t['mabengali'] = 0x09AE;
8178 t['macron'] = 0x00AF;
8179 t['macronbelowcmb'] = 0x0331;
8180 t['macroncmb'] = 0x0304;
8181 t['macronlowmod'] = 0x02CD;
8182 t['macronmonospace'] = 0xFFE3;
8183 t['macute'] = 0x1E3F;
8184 t['madeva'] = 0x092E;
8185 t['magujarati'] = 0x0AAE;
8186 t['magurmukhi'] = 0x0A2E;
8187 t['mahapakhhebrew'] = 0x05A4;
8188 t['mahapakhlefthebrew'] = 0x05A4;
8189 t['mahiragana'] = 0x307E;
8190 t['maichattawalowleftthai'] = 0xF895;
8191 t['maichattawalowrightthai'] = 0xF894;
8192 t['maichattawathai'] = 0x0E4B;
8193 t['maichattawaupperleftthai'] = 0xF893;
8194 t['maieklowleftthai'] = 0xF88C;
8195 t['maieklowrightthai'] = 0xF88B;
8196 t['maiekthai'] = 0x0E48;
8197 t['maiekupperleftthai'] = 0xF88A;
8198 t['maihanakatleftthai'] = 0xF884;
8199 t['maihanakatthai'] = 0x0E31;
8200 t['maitaikhuleftthai'] = 0xF889;
8201 t['maitaikhuthai'] = 0x0E47;
8202 t['maitholowleftthai'] = 0xF88F;
8203 t['maitholowrightthai'] = 0xF88E;
8204 t['maithothai'] = 0x0E49;
8205 t['maithoupperleftthai'] = 0xF88D;
8206 t['maitrilowleftthai'] = 0xF892;
8207 t['maitrilowrightthai'] = 0xF891;
8208 t['maitrithai'] = 0x0E4A;
8209 t['maitriupperleftthai'] = 0xF890;
8210 t['maiyamokthai'] = 0x0E46;
8211 t['makatakana'] = 0x30DE;
8212 t['makatakanahalfwidth'] = 0xFF8F;
8213 t['male'] = 0x2642;
8214 t['mansyonsquare'] = 0x3347;
8215 t['maqafhebrew'] = 0x05BE;
8216 t['mars'] = 0x2642;
8217 t['masoracirclehebrew'] = 0x05AF;
8218 t['masquare'] = 0x3383;
8219 t['mbopomofo'] = 0x3107;
8220 t['mbsquare'] = 0x33D4;
8221 t['mcircle'] = 0x24DC;
8222 t['mcubedsquare'] = 0x33A5;
8223 t['mdotaccent'] = 0x1E41;
8224 t['mdotbelow'] = 0x1E43;
8225 t['meemarabic'] = 0x0645;
8226 t['meemfinalarabic'] = 0xFEE2;
8227 t['meeminitialarabic'] = 0xFEE3;
8228 t['meemmedialarabic'] = 0xFEE4;
8229 t['meemmeeminitialarabic'] = 0xFCD1;
8230 t['meemmeemisolatedarabic'] = 0xFC48;
8231 t['meetorusquare'] = 0x334D;
8232 t['mehiragana'] = 0x3081;
8233 t['meizierasquare'] = 0x337E;
8234 t['mekatakana'] = 0x30E1;
8235 t['mekatakanahalfwidth'] = 0xFF92;
8236 t['mem'] = 0x05DE;
8237 t['memdagesh'] = 0xFB3E;
8238 t['memdageshhebrew'] = 0xFB3E;
8239 t['memhebrew'] = 0x05DE;
8240 t['menarmenian'] = 0x0574;
8241 t['merkhahebrew'] = 0x05A5;
8242 t['merkhakefulahebrew'] = 0x05A6;
8243 t['merkhakefulalefthebrew'] = 0x05A6;
8244 t['merkhalefthebrew'] = 0x05A5;
8245 t['mhook'] = 0x0271;
8246 t['mhzsquare'] = 0x3392;
8247 t['middledotkatakanahalfwidth'] = 0xFF65;
8248 t['middot'] = 0x00B7;
8249 t['mieumacirclekorean'] = 0x3272;
8250 t['mieumaparenkorean'] = 0x3212;
8251 t['mieumcirclekorean'] = 0x3264;
8252 t['mieumkorean'] = 0x3141;
8253 t['mieumpansioskorean'] = 0x3170;
8254 t['mieumparenkorean'] = 0x3204;
8255 t['mieumpieupkorean'] = 0x316E;
8256 t['mieumsioskorean'] = 0x316F;
8257 t['mihiragana'] = 0x307F;
8258 t['mikatakana'] = 0x30DF;
8259 t['mikatakanahalfwidth'] = 0xFF90;
8260 t['minus'] = 0x2212;
8261 t['minusbelowcmb'] = 0x0320;
8262 t['minuscircle'] = 0x2296;
8263 t['minusmod'] = 0x02D7;
8264 t['minusplus'] = 0x2213;
8265 t['minute'] = 0x2032;
8266 t['miribaarusquare'] = 0x334A;
8267 t['mirisquare'] = 0x3349;
8268 t['mlonglegturned'] = 0x0270;
8269 t['mlsquare'] = 0x3396;
8270 t['mmcubedsquare'] = 0x33A3;
8271 t['mmonospace'] = 0xFF4D;
8272 t['mmsquaredsquare'] = 0x339F;
8273 t['mohiragana'] = 0x3082;
8274 t['mohmsquare'] = 0x33C1;
8275 t['mokatakana'] = 0x30E2;
8276 t['mokatakanahalfwidth'] = 0xFF93;
8277 t['molsquare'] = 0x33D6;
8278 t['momathai'] = 0x0E21;
8279 t['moverssquare'] = 0x33A7;
8280 t['moverssquaredsquare'] = 0x33A8;
8281 t['mparen'] = 0x24A8;
8282 t['mpasquare'] = 0x33AB;
8283 t['mssquare'] = 0x33B3;
8284 t['msuperior'] = 0xF6EF;
8285 t['mturned'] = 0x026F;
8286 t['mu'] = 0x00B5;
8287 t['mu1'] = 0x00B5;
8288 t['muasquare'] = 0x3382;
8289 t['muchgreater'] = 0x226B;
8290 t['muchless'] = 0x226A;
8291 t['mufsquare'] = 0x338C;
8292 t['mugreek'] = 0x03BC;
8293 t['mugsquare'] = 0x338D;
8294 t['muhiragana'] = 0x3080;
8295 t['mukatakana'] = 0x30E0;
8296 t['mukatakanahalfwidth'] = 0xFF91;
8297 t['mulsquare'] = 0x3395;
8298 t['multiply'] = 0x00D7;
8299 t['mumsquare'] = 0x339B;
8300 t['munahhebrew'] = 0x05A3;
8301 t['munahlefthebrew'] = 0x05A3;
8302 t['musicalnote'] = 0x266A;
8303 t['musicalnotedbl'] = 0x266B;
8304 t['musicflatsign'] = 0x266D;
8305 t['musicsharpsign'] = 0x266F;
8306 t['mussquare'] = 0x33B2;
8307 t['muvsquare'] = 0x33B6;
8308 t['muwsquare'] = 0x33BC;
8309 t['mvmegasquare'] = 0x33B9;
8310 t['mvsquare'] = 0x33B7;
8311 t['mwmegasquare'] = 0x33BF;
8312 t['mwsquare'] = 0x33BD;
8313 t['n'] = 0x006E;
8314 t['nabengali'] = 0x09A8;
8315 t['nabla'] = 0x2207;
8316 t['nacute'] = 0x0144;
8317 t['nadeva'] = 0x0928;
8318 t['nagujarati'] = 0x0AA8;
8319 t['nagurmukhi'] = 0x0A28;
8320 t['nahiragana'] = 0x306A;
8321 t['nakatakana'] = 0x30CA;
8322 t['nakatakanahalfwidth'] = 0xFF85;
8323 t['napostrophe'] = 0x0149;
8324 t['nasquare'] = 0x3381;
8325 t['nbopomofo'] = 0x310B;
8326 t['nbspace'] = 0x00A0;
8327 t['ncaron'] = 0x0148;
8328 t['ncedilla'] = 0x0146;
8329 t['ncircle'] = 0x24DD;
8330 t['ncircumflexbelow'] = 0x1E4B;
8331 t['ncommaaccent'] = 0x0146;
8332 t['ndotaccent'] = 0x1E45;
8333 t['ndotbelow'] = 0x1E47;
8334 t['nehiragana'] = 0x306D;
8335 t['nekatakana'] = 0x30CD;
8336 t['nekatakanahalfwidth'] = 0xFF88;
8337 t['newsheqelsign'] = 0x20AA;
8338 t['nfsquare'] = 0x338B;
8339 t['ngabengali'] = 0x0999;
8340 t['ngadeva'] = 0x0919;
8341 t['ngagujarati'] = 0x0A99;
8342 t['ngagurmukhi'] = 0x0A19;
8343 t['ngonguthai'] = 0x0E07;
8344 t['nhiragana'] = 0x3093;
8345 t['nhookleft'] = 0x0272;
8346 t['nhookretroflex'] = 0x0273;
8347 t['nieunacirclekorean'] = 0x326F;
8348 t['nieunaparenkorean'] = 0x320F;
8349 t['nieuncieuckorean'] = 0x3135;
8350 t['nieuncirclekorean'] = 0x3261;
8351 t['nieunhieuhkorean'] = 0x3136;
8352 t['nieunkorean'] = 0x3134;
8353 t['nieunpansioskorean'] = 0x3168;
8354 t['nieunparenkorean'] = 0x3201;
8355 t['nieunsioskorean'] = 0x3167;
8356 t['nieuntikeutkorean'] = 0x3166;
8357 t['nihiragana'] = 0x306B;
8358 t['nikatakana'] = 0x30CB;
8359 t['nikatakanahalfwidth'] = 0xFF86;
8360 t['nikhahitleftthai'] = 0xF899;
8361 t['nikhahitthai'] = 0x0E4D;
8362 t['nine'] = 0x0039;
8363 t['ninearabic'] = 0x0669;
8364 t['ninebengali'] = 0x09EF;
8365 t['ninecircle'] = 0x2468;
8366 t['ninecircleinversesansserif'] = 0x2792;
8367 t['ninedeva'] = 0x096F;
8368 t['ninegujarati'] = 0x0AEF;
8369 t['ninegurmukhi'] = 0x0A6F;
8370 t['ninehackarabic'] = 0x0669;
8371 t['ninehangzhou'] = 0x3029;
8372 t['nineideographicparen'] = 0x3228;
8373 t['nineinferior'] = 0x2089;
8374 t['ninemonospace'] = 0xFF19;
8375 t['nineoldstyle'] = 0xF739;
8376 t['nineparen'] = 0x247C;
8377 t['nineperiod'] = 0x2490;
8378 t['ninepersian'] = 0x06F9;
8379 t['nineroman'] = 0x2178;
8380 t['ninesuperior'] = 0x2079;
8381 t['nineteencircle'] = 0x2472;
8382 t['nineteenparen'] = 0x2486;
8383 t['nineteenperiod'] = 0x249A;
8384 t['ninethai'] = 0x0E59;
8385 t['nj'] = 0x01CC;
8386 t['njecyrillic'] = 0x045A;
8387 t['nkatakana'] = 0x30F3;
8388 t['nkatakanahalfwidth'] = 0xFF9D;
8389 t['nlegrightlong'] = 0x019E;
8390 t['nlinebelow'] = 0x1E49;
8391 t['nmonospace'] = 0xFF4E;
8392 t['nmsquare'] = 0x339A;
8393 t['nnabengali'] = 0x09A3;
8394 t['nnadeva'] = 0x0923;
8395 t['nnagujarati'] = 0x0AA3;
8396 t['nnagurmukhi'] = 0x0A23;
8397 t['nnnadeva'] = 0x0929;
8398 t['nohiragana'] = 0x306E;
8399 t['nokatakana'] = 0x30CE;
8400 t['nokatakanahalfwidth'] = 0xFF89;
8401 t['nonbreakingspace'] = 0x00A0;
8402 t['nonenthai'] = 0x0E13;
8403 t['nonuthai'] = 0x0E19;
8404 t['noonarabic'] = 0x0646;
8405 t['noonfinalarabic'] = 0xFEE6;
8406 t['noonghunnaarabic'] = 0x06BA;
8407 t['noonghunnafinalarabic'] = 0xFB9F;
8408 t['nooninitialarabic'] = 0xFEE7;
8409 t['noonjeeminitialarabic'] = 0xFCD2;
8410 t['noonjeemisolatedarabic'] = 0xFC4B;
8411 t['noonmedialarabic'] = 0xFEE8;
8412 t['noonmeeminitialarabic'] = 0xFCD5;
8413 t['noonmeemisolatedarabic'] = 0xFC4E;
8414 t['noonnoonfinalarabic'] = 0xFC8D;
8415 t['notcontains'] = 0x220C;
8416 t['notelement'] = 0x2209;
8417 t['notelementof'] = 0x2209;
8418 t['notequal'] = 0x2260;
8419 t['notgreater'] = 0x226F;
8420 t['notgreaternorequal'] = 0x2271;
8421 t['notgreaternorless'] = 0x2279;
8422 t['notidentical'] = 0x2262;
8423 t['notless'] = 0x226E;
8424 t['notlessnorequal'] = 0x2270;
8425 t['notparallel'] = 0x2226;
8426 t['notprecedes'] = 0x2280;
8427 t['notsubset'] = 0x2284;
8428 t['notsucceeds'] = 0x2281;
8429 t['notsuperset'] = 0x2285;
8430 t['nowarmenian'] = 0x0576;
8431 t['nparen'] = 0x24A9;
8432 t['nssquare'] = 0x33B1;
8433 t['nsuperior'] = 0x207F;
8434 t['ntilde'] = 0x00F1;
8435 t['nu'] = 0x03BD;
8436 t['nuhiragana'] = 0x306C;
8437 t['nukatakana'] = 0x30CC;
8438 t['nukatakanahalfwidth'] = 0xFF87;
8439 t['nuktabengali'] = 0x09BC;
8440 t['nuktadeva'] = 0x093C;
8441 t['nuktagujarati'] = 0x0ABC;
8442 t['nuktagurmukhi'] = 0x0A3C;
8443 t['numbersign'] = 0x0023;
8444 t['numbersignmonospace'] = 0xFF03;
8445 t['numbersignsmall'] = 0xFE5F;
8446 t['numeralsigngreek'] = 0x0374;
8447 t['numeralsignlowergreek'] = 0x0375;
8448 t['numero'] = 0x2116;
8449 t['nun'] = 0x05E0;
8450 t['nundagesh'] = 0xFB40;
8451 t['nundageshhebrew'] = 0xFB40;
8452 t['nunhebrew'] = 0x05E0;
8453 t['nvsquare'] = 0x33B5;
8454 t['nwsquare'] = 0x33BB;
8455 t['nyabengali'] = 0x099E;
8456 t['nyadeva'] = 0x091E;
8457 t['nyagujarati'] = 0x0A9E;
8458 t['nyagurmukhi'] = 0x0A1E;
8459 t['o'] = 0x006F;
8460 t['oacute'] = 0x00F3;
8461 t['oangthai'] = 0x0E2D;
8462 t['obarred'] = 0x0275;
8463 t['obarredcyrillic'] = 0x04E9;
8464 t['obarreddieresiscyrillic'] = 0x04EB;
8465 t['obengali'] = 0x0993;
8466 t['obopomofo'] = 0x311B;
8467 t['obreve'] = 0x014F;
8468 t['ocandradeva'] = 0x0911;
8469 t['ocandragujarati'] = 0x0A91;
8470 t['ocandravowelsigndeva'] = 0x0949;
8471 t['ocandravowelsigngujarati'] = 0x0AC9;
8472 t['ocaron'] = 0x01D2;
8473 t['ocircle'] = 0x24DE;
8474 t['ocircumflex'] = 0x00F4;
8475 t['ocircumflexacute'] = 0x1ED1;
8476 t['ocircumflexdotbelow'] = 0x1ED9;
8477 t['ocircumflexgrave'] = 0x1ED3;
8478 t['ocircumflexhookabove'] = 0x1ED5;
8479 t['ocircumflextilde'] = 0x1ED7;
8480 t['ocyrillic'] = 0x043E;
8481 t['odblacute'] = 0x0151;
8482 t['odblgrave'] = 0x020D;
8483 t['odeva'] = 0x0913;
8484 t['odieresis'] = 0x00F6;
8485 t['odieresiscyrillic'] = 0x04E7;
8486 t['odotbelow'] = 0x1ECD;
8487 t['oe'] = 0x0153;
8488 t['oekorean'] = 0x315A;
8489 t['ogonek'] = 0x02DB;
8490 t['ogonekcmb'] = 0x0328;
8491 t['ograve'] = 0x00F2;
8492 t['ogujarati'] = 0x0A93;
8493 t['oharmenian'] = 0x0585;
8494 t['ohiragana'] = 0x304A;
8495 t['ohookabove'] = 0x1ECF;
8496 t['ohorn'] = 0x01A1;
8497 t['ohornacute'] = 0x1EDB;
8498 t['ohorndotbelow'] = 0x1EE3;
8499 t['ohorngrave'] = 0x1EDD;
8500 t['ohornhookabove'] = 0x1EDF;
8501 t['ohorntilde'] = 0x1EE1;
8502 t['ohungarumlaut'] = 0x0151;
8503 t['oi'] = 0x01A3;
8504 t['oinvertedbreve'] = 0x020F;
8505 t['okatakana'] = 0x30AA;
8506 t['okatakanahalfwidth'] = 0xFF75;
8507 t['okorean'] = 0x3157;
8508 t['olehebrew'] = 0x05AB;
8509 t['omacron'] = 0x014D;
8510 t['omacronacute'] = 0x1E53;
8511 t['omacrongrave'] = 0x1E51;
8512 t['omdeva'] = 0x0950;
8513 t['omega'] = 0x03C9;
8514 t['omega1'] = 0x03D6;
8515 t['omegacyrillic'] = 0x0461;
8516 t['omegalatinclosed'] = 0x0277;
8517 t['omegaroundcyrillic'] = 0x047B;
8518 t['omegatitlocyrillic'] = 0x047D;
8519 t['omegatonos'] = 0x03CE;
8520 t['omgujarati'] = 0x0AD0;
8521 t['omicron'] = 0x03BF;
8522 t['omicrontonos'] = 0x03CC;
8523 t['omonospace'] = 0xFF4F;
8524 t['one'] = 0x0031;
8525 t['onearabic'] = 0x0661;
8526 t['onebengali'] = 0x09E7;
8527 t['onecircle'] = 0x2460;
8528 t['onecircleinversesansserif'] = 0x278A;
8529 t['onedeva'] = 0x0967;
8530 t['onedotenleader'] = 0x2024;
8531 t['oneeighth'] = 0x215B;
8532 t['onefitted'] = 0xF6DC;
8533 t['onegujarati'] = 0x0AE7;
8534 t['onegurmukhi'] = 0x0A67;
8535 t['onehackarabic'] = 0x0661;
8536 t['onehalf'] = 0x00BD;
8537 t['onehangzhou'] = 0x3021;
8538 t['oneideographicparen'] = 0x3220;
8539 t['oneinferior'] = 0x2081;
8540 t['onemonospace'] = 0xFF11;
8541 t['onenumeratorbengali'] = 0x09F4;
8542 t['oneoldstyle'] = 0xF731;
8543 t['oneparen'] = 0x2474;
8544 t['oneperiod'] = 0x2488;
8545 t['onepersian'] = 0x06F1;
8546 t['onequarter'] = 0x00BC;
8547 t['oneroman'] = 0x2170;
8548 t['onesuperior'] = 0x00B9;
8549 t['onethai'] = 0x0E51;
8550 t['onethird'] = 0x2153;
8551 t['oogonek'] = 0x01EB;
8552 t['oogonekmacron'] = 0x01ED;
8553 t['oogurmukhi'] = 0x0A13;
8554 t['oomatragurmukhi'] = 0x0A4B;
8555 t['oopen'] = 0x0254;
8556 t['oparen'] = 0x24AA;
8557 t['openbullet'] = 0x25E6;
8558 t['option'] = 0x2325;
8559 t['ordfeminine'] = 0x00AA;
8560 t['ordmasculine'] = 0x00BA;
8561 t['orthogonal'] = 0x221F;
8562 t['oshortdeva'] = 0x0912;
8563 t['oshortvowelsigndeva'] = 0x094A;
8564 t['oslash'] = 0x00F8;
8565 t['oslashacute'] = 0x01FF;
8566 t['osmallhiragana'] = 0x3049;
8567 t['osmallkatakana'] = 0x30A9;
8568 t['osmallkatakanahalfwidth'] = 0xFF6B;
8569 t['ostrokeacute'] = 0x01FF;
8570 t['osuperior'] = 0xF6F0;
8571 t['otcyrillic'] = 0x047F;
8572 t['otilde'] = 0x00F5;
8573 t['otildeacute'] = 0x1E4D;
8574 t['otildedieresis'] = 0x1E4F;
8575 t['oubopomofo'] = 0x3121;
8576 t['overline'] = 0x203E;
8577 t['overlinecenterline'] = 0xFE4A;
8578 t['overlinecmb'] = 0x0305;
8579 t['overlinedashed'] = 0xFE49;
8580 t['overlinedblwavy'] = 0xFE4C;
8581 t['overlinewavy'] = 0xFE4B;
8582 t['overscore'] = 0x00AF;
8583 t['ovowelsignbengali'] = 0x09CB;
8584 t['ovowelsigndeva'] = 0x094B;
8585 t['ovowelsigngujarati'] = 0x0ACB;
8586 t['p'] = 0x0070;
8587 t['paampssquare'] = 0x3380;
8588 t['paasentosquare'] = 0x332B;
8589 t['pabengali'] = 0x09AA;
8590 t['pacute'] = 0x1E55;
8591 t['padeva'] = 0x092A;
8592 t['pagedown'] = 0x21DF;
8593 t['pageup'] = 0x21DE;
8594 t['pagujarati'] = 0x0AAA;
8595 t['pagurmukhi'] = 0x0A2A;
8596 t['pahiragana'] = 0x3071;
8597 t['paiyannoithai'] = 0x0E2F;
8598 t['pakatakana'] = 0x30D1;
8599 t['palatalizationcyrilliccmb'] = 0x0484;
8600 t['palochkacyrillic'] = 0x04C0;
8601 t['pansioskorean'] = 0x317F;
8602 t['paragraph'] = 0x00B6;
8603 t['parallel'] = 0x2225;
8604 t['parenleft'] = 0x0028;
8605 t['parenleftaltonearabic'] = 0xFD3E;
8606 t['parenleftbt'] = 0xF8ED;
8607 t['parenleftex'] = 0xF8EC;
8608 t['parenleftinferior'] = 0x208D;
8609 t['parenleftmonospace'] = 0xFF08;
8610 t['parenleftsmall'] = 0xFE59;
8611 t['parenleftsuperior'] = 0x207D;
8612 t['parenlefttp'] = 0xF8EB;
8613 t['parenleftvertical'] = 0xFE35;
8614 t['parenright'] = 0x0029;
8615 t['parenrightaltonearabic'] = 0xFD3F;
8616 t['parenrightbt'] = 0xF8F8;
8617 t['parenrightex'] = 0xF8F7;
8618 t['parenrightinferior'] = 0x208E;
8619 t['parenrightmonospace'] = 0xFF09;
8620 t['parenrightsmall'] = 0xFE5A;
8621 t['parenrightsuperior'] = 0x207E;
8622 t['parenrighttp'] = 0xF8F6;
8623 t['parenrightvertical'] = 0xFE36;
8624 t['partialdiff'] = 0x2202;
8625 t['paseqhebrew'] = 0x05C0;
8626 t['pashtahebrew'] = 0x0599;
8627 t['pasquare'] = 0x33A9;
8628 t['patah'] = 0x05B7;
8629 t['patah11'] = 0x05B7;
8630 t['patah1d'] = 0x05B7;
8631 t['patah2a'] = 0x05B7;
8632 t['patahhebrew'] = 0x05B7;
8633 t['patahnarrowhebrew'] = 0x05B7;
8634 t['patahquarterhebrew'] = 0x05B7;
8635 t['patahwidehebrew'] = 0x05B7;
8636 t['pazerhebrew'] = 0x05A1;
8637 t['pbopomofo'] = 0x3106;
8638 t['pcircle'] = 0x24DF;
8639 t['pdotaccent'] = 0x1E57;
8640 t['pe'] = 0x05E4;
8641 t['pecyrillic'] = 0x043F;
8642 t['pedagesh'] = 0xFB44;
8643 t['pedageshhebrew'] = 0xFB44;
8644 t['peezisquare'] = 0x333B;
8645 t['pefinaldageshhebrew'] = 0xFB43;
8646 t['peharabic'] = 0x067E;
8647 t['peharmenian'] = 0x057A;
8648 t['pehebrew'] = 0x05E4;
8649 t['pehfinalarabic'] = 0xFB57;
8650 t['pehinitialarabic'] = 0xFB58;
8651 t['pehiragana'] = 0x307A;
8652 t['pehmedialarabic'] = 0xFB59;
8653 t['pekatakana'] = 0x30DA;
8654 t['pemiddlehookcyrillic'] = 0x04A7;
8655 t['perafehebrew'] = 0xFB4E;
8656 t['percent'] = 0x0025;
8657 t['percentarabic'] = 0x066A;
8658 t['percentmonospace'] = 0xFF05;
8659 t['percentsmall'] = 0xFE6A;
8660 t['period'] = 0x002E;
8661 t['periodarmenian'] = 0x0589;
8662 t['periodcentered'] = 0x00B7;
8663 t['periodhalfwidth'] = 0xFF61;
8664 t['periodinferior'] = 0xF6E7;
8665 t['periodmonospace'] = 0xFF0E;
8666 t['periodsmall'] = 0xFE52;
8667 t['periodsuperior'] = 0xF6E8;
8668 t['perispomenigreekcmb'] = 0x0342;
8669 t['perpendicular'] = 0x22A5;
8670 t['perthousand'] = 0x2030;
8671 t['peseta'] = 0x20A7;
8672 t['pfsquare'] = 0x338A;
8673 t['phabengali'] = 0x09AB;
8674 t['phadeva'] = 0x092B;
8675 t['phagujarati'] = 0x0AAB;
8676 t['phagurmukhi'] = 0x0A2B;
8677 t['phi'] = 0x03C6;
8678 t['phi1'] = 0x03D5;
8679 t['phieuphacirclekorean'] = 0x327A;
8680 t['phieuphaparenkorean'] = 0x321A;
8681 t['phieuphcirclekorean'] = 0x326C;
8682 t['phieuphkorean'] = 0x314D;
8683 t['phieuphparenkorean'] = 0x320C;
8684 t['philatin'] = 0x0278;
8685 t['phinthuthai'] = 0x0E3A;
8686 t['phisymbolgreek'] = 0x03D5;
8687 t['phook'] = 0x01A5;
8688 t['phophanthai'] = 0x0E1E;
8689 t['phophungthai'] = 0x0E1C;
8690 t['phosamphaothai'] = 0x0E20;
8691 t['pi'] = 0x03C0;
8692 t['pieupacirclekorean'] = 0x3273;
8693 t['pieupaparenkorean'] = 0x3213;
8694 t['pieupcieuckorean'] = 0x3176;
8695 t['pieupcirclekorean'] = 0x3265;
8696 t['pieupkiyeokkorean'] = 0x3172;
8697 t['pieupkorean'] = 0x3142;
8698 t['pieupparenkorean'] = 0x3205;
8699 t['pieupsioskiyeokkorean'] = 0x3174;
8700 t['pieupsioskorean'] = 0x3144;
8701 t['pieupsiostikeutkorean'] = 0x3175;
8702 t['pieupthieuthkorean'] = 0x3177;
8703 t['pieuptikeutkorean'] = 0x3173;
8704 t['pihiragana'] = 0x3074;
8705 t['pikatakana'] = 0x30D4;
8706 t['pisymbolgreek'] = 0x03D6;
8707 t['piwrarmenian'] = 0x0583;
8708 t['plus'] = 0x002B;
8709 t['plusbelowcmb'] = 0x031F;
8710 t['pluscircle'] = 0x2295;
8711 t['plusminus'] = 0x00B1;
8712 t['plusmod'] = 0x02D6;
8713 t['plusmonospace'] = 0xFF0B;
8714 t['plussmall'] = 0xFE62;
8715 t['plussuperior'] = 0x207A;
8716 t['pmonospace'] = 0xFF50;
8717 t['pmsquare'] = 0x33D8;
8718 t['pohiragana'] = 0x307D;
8719 t['pointingindexdownwhite'] = 0x261F;
8720 t['pointingindexleftwhite'] = 0x261C;
8721 t['pointingindexrightwhite'] = 0x261E;
8722 t['pointingindexupwhite'] = 0x261D;
8723 t['pokatakana'] = 0x30DD;
8724 t['poplathai'] = 0x0E1B;
8725 t['postalmark'] = 0x3012;
8726 t['postalmarkface'] = 0x3020;
8727 t['pparen'] = 0x24AB;
8728 t['precedes'] = 0x227A;
8729 t['prescription'] = 0x211E;
8730 t['primemod'] = 0x02B9;
8731 t['primereversed'] = 0x2035;
8732 t['product'] = 0x220F;
8733 t['projective'] = 0x2305;
8734 t['prolongedkana'] = 0x30FC;
8735 t['propellor'] = 0x2318;
8736 t['propersubset'] = 0x2282;
8737 t['propersuperset'] = 0x2283;
8738 t['proportion'] = 0x2237;
8739 t['proportional'] = 0x221D;
8740 t['psi'] = 0x03C8;
8741 t['psicyrillic'] = 0x0471;
8742 t['psilipneumatacyrilliccmb'] = 0x0486;
8743 t['pssquare'] = 0x33B0;
8744 t['puhiragana'] = 0x3077;
8745 t['pukatakana'] = 0x30D7;
8746 t['pvsquare'] = 0x33B4;
8747 t['pwsquare'] = 0x33BA;
8748 t['q'] = 0x0071;
8749 t['qadeva'] = 0x0958;
8750 t['qadmahebrew'] = 0x05A8;
8751 t['qafarabic'] = 0x0642;
8752 t['qaffinalarabic'] = 0xFED6;
8753 t['qafinitialarabic'] = 0xFED7;
8754 t['qafmedialarabic'] = 0xFED8;
8755 t['qamats'] = 0x05B8;
8756 t['qamats10'] = 0x05B8;
8757 t['qamats1a'] = 0x05B8;
8758 t['qamats1c'] = 0x05B8;
8759 t['qamats27'] = 0x05B8;
8760 t['qamats29'] = 0x05B8;
8761 t['qamats33'] = 0x05B8;
8762 t['qamatsde'] = 0x05B8;
8763 t['qamatshebrew'] = 0x05B8;
8764 t['qamatsnarrowhebrew'] = 0x05B8;
8765 t['qamatsqatanhebrew'] = 0x05B8;
8766 t['qamatsqatannarrowhebrew'] = 0x05B8;
8767 t['qamatsqatanquarterhebrew'] = 0x05B8;
8768 t['qamatsqatanwidehebrew'] = 0x05B8;
8769 t['qamatsquarterhebrew'] = 0x05B8;
8770 t['qamatswidehebrew'] = 0x05B8;
8771 t['qarneyparahebrew'] = 0x059F;
8772 t['qbopomofo'] = 0x3111;
8773 t['qcircle'] = 0x24E0;
8774 t['qhook'] = 0x02A0;
8775 t['qmonospace'] = 0xFF51;
8776 t['qof'] = 0x05E7;
8777 t['qofdagesh'] = 0xFB47;
8778 t['qofdageshhebrew'] = 0xFB47;
8779 t['qofhebrew'] = 0x05E7;
8780 t['qparen'] = 0x24AC;
8781 t['quarternote'] = 0x2669;
8782 t['qubuts'] = 0x05BB;
8783 t['qubuts18'] = 0x05BB;
8784 t['qubuts25'] = 0x05BB;
8785 t['qubuts31'] = 0x05BB;
8786 t['qubutshebrew'] = 0x05BB;
8787 t['qubutsnarrowhebrew'] = 0x05BB;
8788 t['qubutsquarterhebrew'] = 0x05BB;
8789 t['qubutswidehebrew'] = 0x05BB;
8790 t['question'] = 0x003F;
8791 t['questionarabic'] = 0x061F;
8792 t['questionarmenian'] = 0x055E;
8793 t['questiondown'] = 0x00BF;
8794 t['questiondownsmall'] = 0xF7BF;
8795 t['questiongreek'] = 0x037E;
8796 t['questionmonospace'] = 0xFF1F;
8797 t['questionsmall'] = 0xF73F;
8798 t['quotedbl'] = 0x0022;
8799 t['quotedblbase'] = 0x201E;
8800 t['quotedblleft'] = 0x201C;
8801 t['quotedblmonospace'] = 0xFF02;
8802 t['quotedblprime'] = 0x301E;
8803 t['quotedblprimereversed'] = 0x301D;
8804 t['quotedblright'] = 0x201D;
8805 t['quoteleft'] = 0x2018;
8806 t['quoteleftreversed'] = 0x201B;
8807 t['quotereversed'] = 0x201B;
8808 t['quoteright'] = 0x2019;
8809 t['quoterightn'] = 0x0149;
8810 t['quotesinglbase'] = 0x201A;
8811 t['quotesingle'] = 0x0027;
8812 t['quotesinglemonospace'] = 0xFF07;
8813 t['r'] = 0x0072;
8814 t['raarmenian'] = 0x057C;
8815 t['rabengali'] = 0x09B0;
8816 t['racute'] = 0x0155;
8817 t['radeva'] = 0x0930;
8818 t['radical'] = 0x221A;
8819 t['radicalex'] = 0xF8E5;
8820 t['radoverssquare'] = 0x33AE;
8821 t['radoverssquaredsquare'] = 0x33AF;
8822 t['radsquare'] = 0x33AD;
8823 t['rafe'] = 0x05BF;
8824 t['rafehebrew'] = 0x05BF;
8825 t['ragujarati'] = 0x0AB0;
8826 t['ragurmukhi'] = 0x0A30;
8827 t['rahiragana'] = 0x3089;
8828 t['rakatakana'] = 0x30E9;
8829 t['rakatakanahalfwidth'] = 0xFF97;
8830 t['ralowerdiagonalbengali'] = 0x09F1;
8831 t['ramiddlediagonalbengali'] = 0x09F0;
8832 t['ramshorn'] = 0x0264;
8833 t['ratio'] = 0x2236;
8834 t['rbopomofo'] = 0x3116;
8835 t['rcaron'] = 0x0159;
8836 t['rcedilla'] = 0x0157;
8837 t['rcircle'] = 0x24E1;
8838 t['rcommaaccent'] = 0x0157;
8839 t['rdblgrave'] = 0x0211;
8840 t['rdotaccent'] = 0x1E59;
8841 t['rdotbelow'] = 0x1E5B;
8842 t['rdotbelowmacron'] = 0x1E5D;
8843 t['referencemark'] = 0x203B;
8844 t['reflexsubset'] = 0x2286;
8845 t['reflexsuperset'] = 0x2287;
8846 t['registered'] = 0x00AE;
8847 t['registersans'] = 0xF8E8;
8848 t['registerserif'] = 0xF6DA;
8849 t['reharabic'] = 0x0631;
8850 t['reharmenian'] = 0x0580;
8851 t['rehfinalarabic'] = 0xFEAE;
8852 t['rehiragana'] = 0x308C;
8853 t['rekatakana'] = 0x30EC;
8854 t['rekatakanahalfwidth'] = 0xFF9A;
8855 t['resh'] = 0x05E8;
8856 t['reshdageshhebrew'] = 0xFB48;
8857 t['reshhebrew'] = 0x05E8;
8858 t['reversedtilde'] = 0x223D;
8859 t['reviahebrew'] = 0x0597;
8860 t['reviamugrashhebrew'] = 0x0597;
8861 t['revlogicalnot'] = 0x2310;
8862 t['rfishhook'] = 0x027E;
8863 t['rfishhookreversed'] = 0x027F;
8864 t['rhabengali'] = 0x09DD;
8865 t['rhadeva'] = 0x095D;
8866 t['rho'] = 0x03C1;
8867 t['rhook'] = 0x027D;
8868 t['rhookturned'] = 0x027B;
8869 t['rhookturnedsuperior'] = 0x02B5;
8870 t['rhosymbolgreek'] = 0x03F1;
8871 t['rhotichookmod'] = 0x02DE;
8872 t['rieulacirclekorean'] = 0x3271;
8873 t['rieulaparenkorean'] = 0x3211;
8874 t['rieulcirclekorean'] = 0x3263;
8875 t['rieulhieuhkorean'] = 0x3140;
8876 t['rieulkiyeokkorean'] = 0x313A;
8877 t['rieulkiyeoksioskorean'] = 0x3169;
8878 t['rieulkorean'] = 0x3139;
8879 t['rieulmieumkorean'] = 0x313B;
8880 t['rieulpansioskorean'] = 0x316C;
8881 t['rieulparenkorean'] = 0x3203;
8882 t['rieulphieuphkorean'] = 0x313F;
8883 t['rieulpieupkorean'] = 0x313C;
8884 t['rieulpieupsioskorean'] = 0x316B;
8885 t['rieulsioskorean'] = 0x313D;
8886 t['rieulthieuthkorean'] = 0x313E;
8887 t['rieultikeutkorean'] = 0x316A;
8888 t['rieulyeorinhieuhkorean'] = 0x316D;
8889 t['rightangle'] = 0x221F;
8890 t['righttackbelowcmb'] = 0x0319;
8891 t['righttriangle'] = 0x22BF;
8892 t['rihiragana'] = 0x308A;
8893 t['rikatakana'] = 0x30EA;
8894 t['rikatakanahalfwidth'] = 0xFF98;
8895 t['ring'] = 0x02DA;
8896 t['ringbelowcmb'] = 0x0325;
8897 t['ringcmb'] = 0x030A;
8898 t['ringhalfleft'] = 0x02BF;
8899 t['ringhalfleftarmenian'] = 0x0559;
8900 t['ringhalfleftbelowcmb'] = 0x031C;
8901 t['ringhalfleftcentered'] = 0x02D3;
8902 t['ringhalfright'] = 0x02BE;
8903 t['ringhalfrightbelowcmb'] = 0x0339;
8904 t['ringhalfrightcentered'] = 0x02D2;
8905 t['rinvertedbreve'] = 0x0213;
8906 t['rittorusquare'] = 0x3351;
8907 t['rlinebelow'] = 0x1E5F;
8908 t['rlongleg'] = 0x027C;
8909 t['rlonglegturned'] = 0x027A;
8910 t['rmonospace'] = 0xFF52;
8911 t['rohiragana'] = 0x308D;
8912 t['rokatakana'] = 0x30ED;
8913 t['rokatakanahalfwidth'] = 0xFF9B;
8914 t['roruathai'] = 0x0E23;
8915 t['rparen'] = 0x24AD;
8916 t['rrabengali'] = 0x09DC;
8917 t['rradeva'] = 0x0931;
8918 t['rragurmukhi'] = 0x0A5C;
8919 t['rreharabic'] = 0x0691;
8920 t['rrehfinalarabic'] = 0xFB8D;
8921 t['rrvocalicbengali'] = 0x09E0;
8922 t['rrvocalicdeva'] = 0x0960;
8923 t['rrvocalicgujarati'] = 0x0AE0;
8924 t['rrvocalicvowelsignbengali'] = 0x09C4;
8925 t['rrvocalicvowelsigndeva'] = 0x0944;
8926 t['rrvocalicvowelsigngujarati'] = 0x0AC4;
8927 t['rsuperior'] = 0xF6F1;
8928 t['rtblock'] = 0x2590;
8929 t['rturned'] = 0x0279;
8930 t['rturnedsuperior'] = 0x02B4;
8931 t['ruhiragana'] = 0x308B;
8932 t['rukatakana'] = 0x30EB;
8933 t['rukatakanahalfwidth'] = 0xFF99;
8934 t['rupeemarkbengali'] = 0x09F2;
8935 t['rupeesignbengali'] = 0x09F3;
8936 t['rupiah'] = 0xF6DD;
8937 t['ruthai'] = 0x0E24;
8938 t['rvocalicbengali'] = 0x098B;
8939 t['rvocalicdeva'] = 0x090B;
8940 t['rvocalicgujarati'] = 0x0A8B;
8941 t['rvocalicvowelsignbengali'] = 0x09C3;
8942 t['rvocalicvowelsigndeva'] = 0x0943;
8943 t['rvocalicvowelsigngujarati'] = 0x0AC3;
8944 t['s'] = 0x0073;
8945 t['sabengali'] = 0x09B8;
8946 t['sacute'] = 0x015B;
8947 t['sacutedotaccent'] = 0x1E65;
8948 t['sadarabic'] = 0x0635;
8949 t['sadeva'] = 0x0938;
8950 t['sadfinalarabic'] = 0xFEBA;
8951 t['sadinitialarabic'] = 0xFEBB;
8952 t['sadmedialarabic'] = 0xFEBC;
8953 t['sagujarati'] = 0x0AB8;
8954 t['sagurmukhi'] = 0x0A38;
8955 t['sahiragana'] = 0x3055;
8956 t['sakatakana'] = 0x30B5;
8957 t['sakatakanahalfwidth'] = 0xFF7B;
8958 t['sallallahoualayhewasallamarabic'] = 0xFDFA;
8959 t['samekh'] = 0x05E1;
8960 t['samekhdagesh'] = 0xFB41;
8961 t['samekhdageshhebrew'] = 0xFB41;
8962 t['samekhhebrew'] = 0x05E1;
8963 t['saraaathai'] = 0x0E32;
8964 t['saraaethai'] = 0x0E41;
8965 t['saraaimaimalaithai'] = 0x0E44;
8966 t['saraaimaimuanthai'] = 0x0E43;
8967 t['saraamthai'] = 0x0E33;
8968 t['saraathai'] = 0x0E30;
8969 t['saraethai'] = 0x0E40;
8970 t['saraiileftthai'] = 0xF886;
8971 t['saraiithai'] = 0x0E35;
8972 t['saraileftthai'] = 0xF885;
8973 t['saraithai'] = 0x0E34;
8974 t['saraothai'] = 0x0E42;
8975 t['saraueeleftthai'] = 0xF888;
8976 t['saraueethai'] = 0x0E37;
8977 t['saraueleftthai'] = 0xF887;
8978 t['sarauethai'] = 0x0E36;
8979 t['sarauthai'] = 0x0E38;
8980 t['sarauuthai'] = 0x0E39;
8981 t['sbopomofo'] = 0x3119;
8982 t['scaron'] = 0x0161;
8983 t['scarondotaccent'] = 0x1E67;
8984 t['scedilla'] = 0x015F;
8985 t['schwa'] = 0x0259;
8986 t['schwacyrillic'] = 0x04D9;
8987 t['schwadieresiscyrillic'] = 0x04DB;
8988 t['schwahook'] = 0x025A;
8989 t['scircle'] = 0x24E2;
8990 t['scircumflex'] = 0x015D;
8991 t['scommaaccent'] = 0x0219;
8992 t['sdotaccent'] = 0x1E61;
8993 t['sdotbelow'] = 0x1E63;
8994 t['sdotbelowdotaccent'] = 0x1E69;
8995 t['seagullbelowcmb'] = 0x033C;
8996 t['second'] = 0x2033;
8997 t['secondtonechinese'] = 0x02CA;
8998 t['section'] = 0x00A7;
8999 t['seenarabic'] = 0x0633;
9000 t['seenfinalarabic'] = 0xFEB2;
9001 t['seeninitialarabic'] = 0xFEB3;
9002 t['seenmedialarabic'] = 0xFEB4;
9003 t['segol'] = 0x05B6;
9004 t['segol13'] = 0x05B6;
9005 t['segol1f'] = 0x05B6;
9006 t['segol2c'] = 0x05B6;
9007 t['segolhebrew'] = 0x05B6;
9008 t['segolnarrowhebrew'] = 0x05B6;
9009 t['segolquarterhebrew'] = 0x05B6;
9010 t['segoltahebrew'] = 0x0592;
9011 t['segolwidehebrew'] = 0x05B6;
9012 t['seharmenian'] = 0x057D;
9013 t['sehiragana'] = 0x305B;
9014 t['sekatakana'] = 0x30BB;
9015 t['sekatakanahalfwidth'] = 0xFF7E;
9016 t['semicolon'] = 0x003B;
9017 t['semicolonarabic'] = 0x061B;
9018 t['semicolonmonospace'] = 0xFF1B;
9019 t['semicolonsmall'] = 0xFE54;
9020 t['semivoicedmarkkana'] = 0x309C;
9021 t['semivoicedmarkkanahalfwidth'] = 0xFF9F;
9022 t['sentisquare'] = 0x3322;
9023 t['sentosquare'] = 0x3323;
9024 t['seven'] = 0x0037;
9025 t['sevenarabic'] = 0x0667;
9026 t['sevenbengali'] = 0x09ED;
9027 t['sevencircle'] = 0x2466;
9028 t['sevencircleinversesansserif'] = 0x2790;
9029 t['sevendeva'] = 0x096D;
9030 t['seveneighths'] = 0x215E;
9031 t['sevengujarati'] = 0x0AED;
9032 t['sevengurmukhi'] = 0x0A6D;
9033 t['sevenhackarabic'] = 0x0667;
9034 t['sevenhangzhou'] = 0x3027;
9035 t['sevenideographicparen'] = 0x3226;
9036 t['seveninferior'] = 0x2087;
9037 t['sevenmonospace'] = 0xFF17;
9038 t['sevenoldstyle'] = 0xF737;
9039 t['sevenparen'] = 0x247A;
9040 t['sevenperiod'] = 0x248E;
9041 t['sevenpersian'] = 0x06F7;
9042 t['sevenroman'] = 0x2176;
9043 t['sevensuperior'] = 0x2077;
9044 t['seventeencircle'] = 0x2470;
9045 t['seventeenparen'] = 0x2484;
9046 t['seventeenperiod'] = 0x2498;
9047 t['seventhai'] = 0x0E57;
9048 t['sfthyphen'] = 0x00AD;
9049 t['shaarmenian'] = 0x0577;
9050 t['shabengali'] = 0x09B6;
9051 t['shacyrillic'] = 0x0448;
9052 t['shaddaarabic'] = 0x0651;
9053 t['shaddadammaarabic'] = 0xFC61;
9054 t['shaddadammatanarabic'] = 0xFC5E;
9055 t['shaddafathaarabic'] = 0xFC60;
9056 t['shaddakasraarabic'] = 0xFC62;
9057 t['shaddakasratanarabic'] = 0xFC5F;
9058 t['shade'] = 0x2592;
9059 t['shadedark'] = 0x2593;
9060 t['shadelight'] = 0x2591;
9061 t['shademedium'] = 0x2592;
9062 t['shadeva'] = 0x0936;
9063 t['shagujarati'] = 0x0AB6;
9064 t['shagurmukhi'] = 0x0A36;
9065 t['shalshelethebrew'] = 0x0593;
9066 t['shbopomofo'] = 0x3115;
9067 t['shchacyrillic'] = 0x0449;
9068 t['sheenarabic'] = 0x0634;
9069 t['sheenfinalarabic'] = 0xFEB6;
9070 t['sheeninitialarabic'] = 0xFEB7;
9071 t['sheenmedialarabic'] = 0xFEB8;
9072 t['sheicoptic'] = 0x03E3;
9073 t['sheqel'] = 0x20AA;
9074 t['sheqelhebrew'] = 0x20AA;
9075 t['sheva'] = 0x05B0;
9076 t['sheva115'] = 0x05B0;
9077 t['sheva15'] = 0x05B0;
9078 t['sheva22'] = 0x05B0;
9079 t['sheva2e'] = 0x05B0;
9080 t['shevahebrew'] = 0x05B0;
9081 t['shevanarrowhebrew'] = 0x05B0;
9082 t['shevaquarterhebrew'] = 0x05B0;
9083 t['shevawidehebrew'] = 0x05B0;
9084 t['shhacyrillic'] = 0x04BB;
9085 t['shimacoptic'] = 0x03ED;
9086 t['shin'] = 0x05E9;
9087 t['shindagesh'] = 0xFB49;
9088 t['shindageshhebrew'] = 0xFB49;
9089 t['shindageshshindot'] = 0xFB2C;
9090 t['shindageshshindothebrew'] = 0xFB2C;
9091 t['shindageshsindot'] = 0xFB2D;
9092 t['shindageshsindothebrew'] = 0xFB2D;
9093 t['shindothebrew'] = 0x05C1;
9094 t['shinhebrew'] = 0x05E9;
9095 t['shinshindot'] = 0xFB2A;
9096 t['shinshindothebrew'] = 0xFB2A;
9097 t['shinsindot'] = 0xFB2B;
9098 t['shinsindothebrew'] = 0xFB2B;
9099 t['shook'] = 0x0282;
9100 t['sigma'] = 0x03C3;
9101 t['sigma1'] = 0x03C2;
9102 t['sigmafinal'] = 0x03C2;
9103 t['sigmalunatesymbolgreek'] = 0x03F2;
9104 t['sihiragana'] = 0x3057;
9105 t['sikatakana'] = 0x30B7;
9106 t['sikatakanahalfwidth'] = 0xFF7C;
9107 t['siluqhebrew'] = 0x05BD;
9108 t['siluqlefthebrew'] = 0x05BD;
9109 t['similar'] = 0x223C;
9110 t['sindothebrew'] = 0x05C2;
9111 t['siosacirclekorean'] = 0x3274;
9112 t['siosaparenkorean'] = 0x3214;
9113 t['sioscieuckorean'] = 0x317E;
9114 t['sioscirclekorean'] = 0x3266;
9115 t['sioskiyeokkorean'] = 0x317A;
9116 t['sioskorean'] = 0x3145;
9117 t['siosnieunkorean'] = 0x317B;
9118 t['siosparenkorean'] = 0x3206;
9119 t['siospieupkorean'] = 0x317D;
9120 t['siostikeutkorean'] = 0x317C;
9121 t['six'] = 0x0036;
9122 t['sixarabic'] = 0x0666;
9123 t['sixbengali'] = 0x09EC;
9124 t['sixcircle'] = 0x2465;
9125 t['sixcircleinversesansserif'] = 0x278F;
9126 t['sixdeva'] = 0x096C;
9127 t['sixgujarati'] = 0x0AEC;
9128 t['sixgurmukhi'] = 0x0A6C;
9129 t['sixhackarabic'] = 0x0666;
9130 t['sixhangzhou'] = 0x3026;
9131 t['sixideographicparen'] = 0x3225;
9132 t['sixinferior'] = 0x2086;
9133 t['sixmonospace'] = 0xFF16;
9134 t['sixoldstyle'] = 0xF736;
9135 t['sixparen'] = 0x2479;
9136 t['sixperiod'] = 0x248D;
9137 t['sixpersian'] = 0x06F6;
9138 t['sixroman'] = 0x2175;
9139 t['sixsuperior'] = 0x2076;
9140 t['sixteencircle'] = 0x246F;
9141 t['sixteencurrencydenominatorbengali'] = 0x09F9;
9142 t['sixteenparen'] = 0x2483;
9143 t['sixteenperiod'] = 0x2497;
9144 t['sixthai'] = 0x0E56;
9145 t['slash'] = 0x002F;
9146 t['slashmonospace'] = 0xFF0F;
9147 t['slong'] = 0x017F;
9148 t['slongdotaccent'] = 0x1E9B;
9149 t['smileface'] = 0x263A;
9150 t['smonospace'] = 0xFF53;
9151 t['sofpasuqhebrew'] = 0x05C3;
9152 t['softhyphen'] = 0x00AD;
9153 t['softsigncyrillic'] = 0x044C;
9154 t['sohiragana'] = 0x305D;
9155 t['sokatakana'] = 0x30BD;
9156 t['sokatakanahalfwidth'] = 0xFF7F;
9157 t['soliduslongoverlaycmb'] = 0x0338;
9158 t['solidusshortoverlaycmb'] = 0x0337;
9159 t['sorusithai'] = 0x0E29;
9160 t['sosalathai'] = 0x0E28;
9161 t['sosothai'] = 0x0E0B;
9162 t['sosuathai'] = 0x0E2A;
9163 t['space'] = 0x0020;
9164 t['spacehackarabic'] = 0x0020;
9165 t['spade'] = 0x2660;
9166 t['spadesuitblack'] = 0x2660;
9167 t['spadesuitwhite'] = 0x2664;
9168 t['sparen'] = 0x24AE;
9169 t['squarebelowcmb'] = 0x033B;
9170 t['squarecc'] = 0x33C4;
9171 t['squarecm'] = 0x339D;
9172 t['squarediagonalcrosshatchfill'] = 0x25A9;
9173 t['squarehorizontalfill'] = 0x25A4;
9174 t['squarekg'] = 0x338F;
9175 t['squarekm'] = 0x339E;
9176 t['squarekmcapital'] = 0x33CE;
9177 t['squareln'] = 0x33D1;
9178 t['squarelog'] = 0x33D2;
9179 t['squaremg'] = 0x338E;
9180 t['squaremil'] = 0x33D5;
9181 t['squaremm'] = 0x339C;
9182 t['squaremsquared'] = 0x33A1;
9183 t['squareorthogonalcrosshatchfill'] = 0x25A6;
9184 t['squareupperlefttolowerrightfill'] = 0x25A7;
9185 t['squareupperrighttolowerleftfill'] = 0x25A8;
9186 t['squareverticalfill'] = 0x25A5;
9187 t['squarewhitewithsmallblack'] = 0x25A3;
9188 t['srsquare'] = 0x33DB;
9189 t['ssabengali'] = 0x09B7;
9190 t['ssadeva'] = 0x0937;
9191 t['ssagujarati'] = 0x0AB7;
9192 t['ssangcieuckorean'] = 0x3149;
9193 t['ssanghieuhkorean'] = 0x3185;
9194 t['ssangieungkorean'] = 0x3180;
9195 t['ssangkiyeokkorean'] = 0x3132;
9196 t['ssangnieunkorean'] = 0x3165;
9197 t['ssangpieupkorean'] = 0x3143;
9198 t['ssangsioskorean'] = 0x3146;
9199 t['ssangtikeutkorean'] = 0x3138;
9200 t['ssuperior'] = 0xF6F2;
9201 t['sterling'] = 0x00A3;
9202 t['sterlingmonospace'] = 0xFFE1;
9203 t['strokelongoverlaycmb'] = 0x0336;
9204 t['strokeshortoverlaycmb'] = 0x0335;
9205 t['subset'] = 0x2282;
9206 t['subsetnotequal'] = 0x228A;
9207 t['subsetorequal'] = 0x2286;
9208 t['succeeds'] = 0x227B;
9209 t['suchthat'] = 0x220B;
9210 t['suhiragana'] = 0x3059;
9211 t['sukatakana'] = 0x30B9;
9212 t['sukatakanahalfwidth'] = 0xFF7D;
9213 t['sukunarabic'] = 0x0652;
9214 t['summation'] = 0x2211;
9215 t['sun'] = 0x263C;
9216 t['superset'] = 0x2283;
9217 t['supersetnotequal'] = 0x228B;
9218 t['supersetorequal'] = 0x2287;
9219 t['svsquare'] = 0x33DC;
9220 t['syouwaerasquare'] = 0x337C;
9221 t['t'] = 0x0074;
9222 t['tabengali'] = 0x09A4;
9223 t['tackdown'] = 0x22A4;
9224 t['tackleft'] = 0x22A3;
9225 t['tadeva'] = 0x0924;
9226 t['tagujarati'] = 0x0AA4;
9227 t['tagurmukhi'] = 0x0A24;
9228 t['taharabic'] = 0x0637;
9229 t['tahfinalarabic'] = 0xFEC2;
9230 t['tahinitialarabic'] = 0xFEC3;
9231 t['tahiragana'] = 0x305F;
9232 t['tahmedialarabic'] = 0xFEC4;
9233 t['taisyouerasquare'] = 0x337D;
9234 t['takatakana'] = 0x30BF;
9235 t['takatakanahalfwidth'] = 0xFF80;
9236 t['tatweelarabic'] = 0x0640;
9237 t['tau'] = 0x03C4;
9238 t['tav'] = 0x05EA;
9239 t['tavdages'] = 0xFB4A;
9240 t['tavdagesh'] = 0xFB4A;
9241 t['tavdageshhebrew'] = 0xFB4A;
9242 t['tavhebrew'] = 0x05EA;
9243 t['tbar'] = 0x0167;
9244 t['tbopomofo'] = 0x310A;
9245 t['tcaron'] = 0x0165;
9246 t['tccurl'] = 0x02A8;
9247 t['tcedilla'] = 0x0163;
9248 t['tcheharabic'] = 0x0686;
9249 t['tchehfinalarabic'] = 0xFB7B;
9250 t['tchehinitialarabic'] = 0xFB7C;
9251 t['tchehmedialarabic'] = 0xFB7D;
9252 t['tcircle'] = 0x24E3;
9253 t['tcircumflexbelow'] = 0x1E71;
9254 t['tcommaaccent'] = 0x0163;
9255 t['tdieresis'] = 0x1E97;
9256 t['tdotaccent'] = 0x1E6B;
9257 t['tdotbelow'] = 0x1E6D;
9258 t['tecyrillic'] = 0x0442;
9259 t['tedescendercyrillic'] = 0x04AD;
9260 t['teharabic'] = 0x062A;
9261 t['tehfinalarabic'] = 0xFE96;
9262 t['tehhahinitialarabic'] = 0xFCA2;
9263 t['tehhahisolatedarabic'] = 0xFC0C;
9264 t['tehinitialarabic'] = 0xFE97;
9265 t['tehiragana'] = 0x3066;
9266 t['tehjeeminitialarabic'] = 0xFCA1;
9267 t['tehjeemisolatedarabic'] = 0xFC0B;
9268 t['tehmarbutaarabic'] = 0x0629;
9269 t['tehmarbutafinalarabic'] = 0xFE94;
9270 t['tehmedialarabic'] = 0xFE98;
9271 t['tehmeeminitialarabic'] = 0xFCA4;
9272 t['tehmeemisolatedarabic'] = 0xFC0E;
9273 t['tehnoonfinalarabic'] = 0xFC73;
9274 t['tekatakana'] = 0x30C6;
9275 t['tekatakanahalfwidth'] = 0xFF83;
9276 t['telephone'] = 0x2121;
9277 t['telephoneblack'] = 0x260E;
9278 t['telishagedolahebrew'] = 0x05A0;
9279 t['telishaqetanahebrew'] = 0x05A9;
9280 t['tencircle'] = 0x2469;
9281 t['tenideographicparen'] = 0x3229;
9282 t['tenparen'] = 0x247D;
9283 t['tenperiod'] = 0x2491;
9284 t['tenroman'] = 0x2179;
9285 t['tesh'] = 0x02A7;
9286 t['tet'] = 0x05D8;
9287 t['tetdagesh'] = 0xFB38;
9288 t['tetdageshhebrew'] = 0xFB38;
9289 t['tethebrew'] = 0x05D8;
9290 t['tetsecyrillic'] = 0x04B5;
9291 t['tevirhebrew'] = 0x059B;
9292 t['tevirlefthebrew'] = 0x059B;
9293 t['thabengali'] = 0x09A5;
9294 t['thadeva'] = 0x0925;
9295 t['thagujarati'] = 0x0AA5;
9296 t['thagurmukhi'] = 0x0A25;
9297 t['thalarabic'] = 0x0630;
9298 t['thalfinalarabic'] = 0xFEAC;
9299 t['thanthakhatlowleftthai'] = 0xF898;
9300 t['thanthakhatlowrightthai'] = 0xF897;
9301 t['thanthakhatthai'] = 0x0E4C;
9302 t['thanthakhatupperleftthai'] = 0xF896;
9303 t['theharabic'] = 0x062B;
9304 t['thehfinalarabic'] = 0xFE9A;
9305 t['thehinitialarabic'] = 0xFE9B;
9306 t['thehmedialarabic'] = 0xFE9C;
9307 t['thereexists'] = 0x2203;
9308 t['therefore'] = 0x2234;
9309 t['theta'] = 0x03B8;
9310 t['theta1'] = 0x03D1;
9311 t['thetasymbolgreek'] = 0x03D1;
9312 t['thieuthacirclekorean'] = 0x3279;
9313 t['thieuthaparenkorean'] = 0x3219;
9314 t['thieuthcirclekorean'] = 0x326B;
9315 t['thieuthkorean'] = 0x314C;
9316 t['thieuthparenkorean'] = 0x320B;
9317 t['thirteencircle'] = 0x246C;
9318 t['thirteenparen'] = 0x2480;
9319 t['thirteenperiod'] = 0x2494;
9320 t['thonangmonthothai'] = 0x0E11;
9321 t['thook'] = 0x01AD;
9322 t['thophuthaothai'] = 0x0E12;
9323 t['thorn'] = 0x00FE;
9324 t['thothahanthai'] = 0x0E17;
9325 t['thothanthai'] = 0x0E10;
9326 t['thothongthai'] = 0x0E18;
9327 t['thothungthai'] = 0x0E16;
9328 t['thousandcyrillic'] = 0x0482;
9329 t['thousandsseparatorarabic'] = 0x066C;
9330 t['thousandsseparatorpersian'] = 0x066C;
9331 t['three'] = 0x0033;
9332 t['threearabic'] = 0x0663;
9333 t['threebengali'] = 0x09E9;
9334 t['threecircle'] = 0x2462;
9335 t['threecircleinversesansserif'] = 0x278C;
9336 t['threedeva'] = 0x0969;
9337 t['threeeighths'] = 0x215C;
9338 t['threegujarati'] = 0x0AE9;
9339 t['threegurmukhi'] = 0x0A69;
9340 t['threehackarabic'] = 0x0663;
9341 t['threehangzhou'] = 0x3023;
9342 t['threeideographicparen'] = 0x3222;
9343 t['threeinferior'] = 0x2083;
9344 t['threemonospace'] = 0xFF13;
9345 t['threenumeratorbengali'] = 0x09F6;
9346 t['threeoldstyle'] = 0xF733;
9347 t['threeparen'] = 0x2476;
9348 t['threeperiod'] = 0x248A;
9349 t['threepersian'] = 0x06F3;
9350 t['threequarters'] = 0x00BE;
9351 t['threequartersemdash'] = 0xF6DE;
9352 t['threeroman'] = 0x2172;
9353 t['threesuperior'] = 0x00B3;
9354 t['threethai'] = 0x0E53;
9355 t['thzsquare'] = 0x3394;
9356 t['tihiragana'] = 0x3061;
9357 t['tikatakana'] = 0x30C1;
9358 t['tikatakanahalfwidth'] = 0xFF81;
9359 t['tikeutacirclekorean'] = 0x3270;
9360 t['tikeutaparenkorean'] = 0x3210;
9361 t['tikeutcirclekorean'] = 0x3262;
9362 t['tikeutkorean'] = 0x3137;
9363 t['tikeutparenkorean'] = 0x3202;
9364 t['tilde'] = 0x02DC;
9365 t['tildebelowcmb'] = 0x0330;
9366 t['tildecmb'] = 0x0303;
9367 t['tildecomb'] = 0x0303;
9368 t['tildedoublecmb'] = 0x0360;
9369 t['tildeoperator'] = 0x223C;
9370 t['tildeoverlaycmb'] = 0x0334;
9371 t['tildeverticalcmb'] = 0x033E;
9372 t['timescircle'] = 0x2297;
9373 t['tipehahebrew'] = 0x0596;
9374 t['tipehalefthebrew'] = 0x0596;
9375 t['tippigurmukhi'] = 0x0A70;
9376 t['titlocyrilliccmb'] = 0x0483;
9377 t['tiwnarmenian'] = 0x057F;
9378 t['tlinebelow'] = 0x1E6F;
9379 t['tmonospace'] = 0xFF54;
9380 t['toarmenian'] = 0x0569;
9381 t['tohiragana'] = 0x3068;
9382 t['tokatakana'] = 0x30C8;
9383 t['tokatakanahalfwidth'] = 0xFF84;
9384 t['tonebarextrahighmod'] = 0x02E5;
9385 t['tonebarextralowmod'] = 0x02E9;
9386 t['tonebarhighmod'] = 0x02E6;
9387 t['tonebarlowmod'] = 0x02E8;
9388 t['tonebarmidmod'] = 0x02E7;
9389 t['tonefive'] = 0x01BD;
9390 t['tonesix'] = 0x0185;
9391 t['tonetwo'] = 0x01A8;
9392 t['tonos'] = 0x0384;
9393 t['tonsquare'] = 0x3327;
9394 t['topatakthai'] = 0x0E0F;
9395 t['tortoiseshellbracketleft'] = 0x3014;
9396 t['tortoiseshellbracketleftsmall'] = 0xFE5D;
9397 t['tortoiseshellbracketleftvertical'] = 0xFE39;
9398 t['tortoiseshellbracketright'] = 0x3015;
9399 t['tortoiseshellbracketrightsmall'] = 0xFE5E;
9400 t['tortoiseshellbracketrightvertical'] = 0xFE3A;
9401 t['totaothai'] = 0x0E15;
9402 t['tpalatalhook'] = 0x01AB;
9403 t['tparen'] = 0x24AF;
9404 t['trademark'] = 0x2122;
9405 t['trademarksans'] = 0xF8EA;
9406 t['trademarkserif'] = 0xF6DB;
9407 t['tretroflexhook'] = 0x0288;
9408 t['triagdn'] = 0x25BC;
9409 t['triaglf'] = 0x25C4;
9410 t['triagrt'] = 0x25BA;
9411 t['triagup'] = 0x25B2;
9412 t['ts'] = 0x02A6;
9413 t['tsadi'] = 0x05E6;
9414 t['tsadidagesh'] = 0xFB46;
9415 t['tsadidageshhebrew'] = 0xFB46;
9416 t['tsadihebrew'] = 0x05E6;
9417 t['tsecyrillic'] = 0x0446;
9418 t['tsere'] = 0x05B5;
9419 t['tsere12'] = 0x05B5;
9420 t['tsere1e'] = 0x05B5;
9421 t['tsere2b'] = 0x05B5;
9422 t['tserehebrew'] = 0x05B5;
9423 t['tserenarrowhebrew'] = 0x05B5;
9424 t['tserequarterhebrew'] = 0x05B5;
9425 t['tserewidehebrew'] = 0x05B5;
9426 t['tshecyrillic'] = 0x045B;
9427 t['tsuperior'] = 0xF6F3;
9428 t['ttabengali'] = 0x099F;
9429 t['ttadeva'] = 0x091F;
9430 t['ttagujarati'] = 0x0A9F;
9431 t['ttagurmukhi'] = 0x0A1F;
9432 t['tteharabic'] = 0x0679;
9433 t['ttehfinalarabic'] = 0xFB67;
9434 t['ttehinitialarabic'] = 0xFB68;
9435 t['ttehmedialarabic'] = 0xFB69;
9436 t['tthabengali'] = 0x09A0;
9437 t['tthadeva'] = 0x0920;
9438 t['tthagujarati'] = 0x0AA0;
9439 t['tthagurmukhi'] = 0x0A20;
9440 t['tturned'] = 0x0287;
9441 t['tuhiragana'] = 0x3064;
9442 t['tukatakana'] = 0x30C4;
9443 t['tukatakanahalfwidth'] = 0xFF82;
9444 t['tusmallhiragana'] = 0x3063;
9445 t['tusmallkatakana'] = 0x30C3;
9446 t['tusmallkatakanahalfwidth'] = 0xFF6F;
9447 t['twelvecircle'] = 0x246B;
9448 t['twelveparen'] = 0x247F;
9449 t['twelveperiod'] = 0x2493;
9450 t['twelveroman'] = 0x217B;
9451 t['twentycircle'] = 0x2473;
9452 t['twentyhangzhou'] = 0x5344;
9453 t['twentyparen'] = 0x2487;
9454 t['twentyperiod'] = 0x249B;
9455 t['two'] = 0x0032;
9456 t['twoarabic'] = 0x0662;
9457 t['twobengali'] = 0x09E8;
9458 t['twocircle'] = 0x2461;
9459 t['twocircleinversesansserif'] = 0x278B;
9460 t['twodeva'] = 0x0968;
9461 t['twodotenleader'] = 0x2025;
9462 t['twodotleader'] = 0x2025;
9463 t['twodotleadervertical'] = 0xFE30;
9464 t['twogujarati'] = 0x0AE8;
9465 t['twogurmukhi'] = 0x0A68;
9466 t['twohackarabic'] = 0x0662;
9467 t['twohangzhou'] = 0x3022;
9468 t['twoideographicparen'] = 0x3221;
9469 t['twoinferior'] = 0x2082;
9470 t['twomonospace'] = 0xFF12;
9471 t['twonumeratorbengali'] = 0x09F5;
9472 t['twooldstyle'] = 0xF732;
9473 t['twoparen'] = 0x2475;
9474 t['twoperiod'] = 0x2489;
9475 t['twopersian'] = 0x06F2;
9476 t['tworoman'] = 0x2171;
9477 t['twostroke'] = 0x01BB;
9478 t['twosuperior'] = 0x00B2;
9479 t['twothai'] = 0x0E52;
9480 t['twothirds'] = 0x2154;
9481 t['u'] = 0x0075;
9482 t['uacute'] = 0x00FA;
9483 t['ubar'] = 0x0289;
9484 t['ubengali'] = 0x0989;
9485 t['ubopomofo'] = 0x3128;
9486 t['ubreve'] = 0x016D;
9487 t['ucaron'] = 0x01D4;
9488 t['ucircle'] = 0x24E4;
9489 t['ucircumflex'] = 0x00FB;
9490 t['ucircumflexbelow'] = 0x1E77;
9491 t['ucyrillic'] = 0x0443;
9492 t['udattadeva'] = 0x0951;
9493 t['udblacute'] = 0x0171;
9494 t['udblgrave'] = 0x0215;
9495 t['udeva'] = 0x0909;
9496 t['udieresis'] = 0x00FC;
9497 t['udieresisacute'] = 0x01D8;
9498 t['udieresisbelow'] = 0x1E73;
9499 t['udieresiscaron'] = 0x01DA;
9500 t['udieresiscyrillic'] = 0x04F1;
9501 t['udieresisgrave'] = 0x01DC;
9502 t['udieresismacron'] = 0x01D6;
9503 t['udotbelow'] = 0x1EE5;
9504 t['ugrave'] = 0x00F9;
9505 t['ugujarati'] = 0x0A89;
9506 t['ugurmukhi'] = 0x0A09;
9507 t['uhiragana'] = 0x3046;
9508 t['uhookabove'] = 0x1EE7;
9509 t['uhorn'] = 0x01B0;
9510 t['uhornacute'] = 0x1EE9;
9511 t['uhorndotbelow'] = 0x1EF1;
9512 t['uhorngrave'] = 0x1EEB;
9513 t['uhornhookabove'] = 0x1EED;
9514 t['uhorntilde'] = 0x1EEF;
9515 t['uhungarumlaut'] = 0x0171;
9516 t['uhungarumlautcyrillic'] = 0x04F3;
9517 t['uinvertedbreve'] = 0x0217;
9518 t['ukatakana'] = 0x30A6;
9519 t['ukatakanahalfwidth'] = 0xFF73;
9520 t['ukcyrillic'] = 0x0479;
9521 t['ukorean'] = 0x315C;
9522 t['umacron'] = 0x016B;
9523 t['umacroncyrillic'] = 0x04EF;
9524 t['umacrondieresis'] = 0x1E7B;
9525 t['umatragurmukhi'] = 0x0A41;
9526 t['umonospace'] = 0xFF55;
9527 t['underscore'] = 0x005F;
9528 t['underscoredbl'] = 0x2017;
9529 t['underscoremonospace'] = 0xFF3F;
9530 t['underscorevertical'] = 0xFE33;
9531 t['underscorewavy'] = 0xFE4F;
9532 t['union'] = 0x222A;
9533 t['universal'] = 0x2200;
9534 t['uogonek'] = 0x0173;
9535 t['uparen'] = 0x24B0;
9536 t['upblock'] = 0x2580;
9537 t['upperdothebrew'] = 0x05C4;
9538 t['upsilon'] = 0x03C5;
9539 t['upsilondieresis'] = 0x03CB;
9540 t['upsilondieresistonos'] = 0x03B0;
9541 t['upsilonlatin'] = 0x028A;
9542 t['upsilontonos'] = 0x03CD;
9543 t['uptackbelowcmb'] = 0x031D;
9544 t['uptackmod'] = 0x02D4;
9545 t['uragurmukhi'] = 0x0A73;
9546 t['uring'] = 0x016F;
9547 t['ushortcyrillic'] = 0x045E;
9548 t['usmallhiragana'] = 0x3045;
9549 t['usmallkatakana'] = 0x30A5;
9550 t['usmallkatakanahalfwidth'] = 0xFF69;
9551 t['ustraightcyrillic'] = 0x04AF;
9552 t['ustraightstrokecyrillic'] = 0x04B1;
9553 t['utilde'] = 0x0169;
9554 t['utildeacute'] = 0x1E79;
9555 t['utildebelow'] = 0x1E75;
9556 t['uubengali'] = 0x098A;
9557 t['uudeva'] = 0x090A;
9558 t['uugujarati'] = 0x0A8A;
9559 t['uugurmukhi'] = 0x0A0A;
9560 t['uumatragurmukhi'] = 0x0A42;
9561 t['uuvowelsignbengali'] = 0x09C2;
9562 t['uuvowelsigndeva'] = 0x0942;
9563 t['uuvowelsigngujarati'] = 0x0AC2;
9564 t['uvowelsignbengali'] = 0x09C1;
9565 t['uvowelsigndeva'] = 0x0941;
9566 t['uvowelsigngujarati'] = 0x0AC1;
9567 t['v'] = 0x0076;
9568 t['vadeva'] = 0x0935;
9569 t['vagujarati'] = 0x0AB5;
9570 t['vagurmukhi'] = 0x0A35;
9571 t['vakatakana'] = 0x30F7;
9572 t['vav'] = 0x05D5;
9573 t['vavdagesh'] = 0xFB35;
9574 t['vavdagesh65'] = 0xFB35;
9575 t['vavdageshhebrew'] = 0xFB35;
9576 t['vavhebrew'] = 0x05D5;
9577 t['vavholam'] = 0xFB4B;
9578 t['vavholamhebrew'] = 0xFB4B;
9579 t['vavvavhebrew'] = 0x05F0;
9580 t['vavyodhebrew'] = 0x05F1;
9581 t['vcircle'] = 0x24E5;
9582 t['vdotbelow'] = 0x1E7F;
9583 t['vecyrillic'] = 0x0432;
9584 t['veharabic'] = 0x06A4;
9585 t['vehfinalarabic'] = 0xFB6B;
9586 t['vehinitialarabic'] = 0xFB6C;
9587 t['vehmedialarabic'] = 0xFB6D;
9588 t['vekatakana'] = 0x30F9;
9589 t['venus'] = 0x2640;
9590 t['verticalbar'] = 0x007C;
9591 t['verticallineabovecmb'] = 0x030D;
9592 t['verticallinebelowcmb'] = 0x0329;
9593 t['verticallinelowmod'] = 0x02CC;
9594 t['verticallinemod'] = 0x02C8;
9595 t['vewarmenian'] = 0x057E;
9596 t['vhook'] = 0x028B;
9597 t['vikatakana'] = 0x30F8;
9598 t['viramabengali'] = 0x09CD;
9599 t['viramadeva'] = 0x094D;
9600 t['viramagujarati'] = 0x0ACD;
9601 t['visargabengali'] = 0x0983;
9602 t['visargadeva'] = 0x0903;
9603 t['visargagujarati'] = 0x0A83;
9604 t['vmonospace'] = 0xFF56;
9605 t['voarmenian'] = 0x0578;
9606 t['voicediterationhiragana'] = 0x309E;
9607 t['voicediterationkatakana'] = 0x30FE;
9608 t['voicedmarkkana'] = 0x309B;
9609 t['voicedmarkkanahalfwidth'] = 0xFF9E;
9610 t['vokatakana'] = 0x30FA;
9611 t['vparen'] = 0x24B1;
9612 t['vtilde'] = 0x1E7D;
9613 t['vturned'] = 0x028C;
9614 t['vuhiragana'] = 0x3094;
9615 t['vukatakana'] = 0x30F4;
9616 t['w'] = 0x0077;
9617 t['wacute'] = 0x1E83;
9618 t['waekorean'] = 0x3159;
9619 t['wahiragana'] = 0x308F;
9620 t['wakatakana'] = 0x30EF;
9621 t['wakatakanahalfwidth'] = 0xFF9C;
9622 t['wakorean'] = 0x3158;
9623 t['wasmallhiragana'] = 0x308E;
9624 t['wasmallkatakana'] = 0x30EE;
9625 t['wattosquare'] = 0x3357;
9626 t['wavedash'] = 0x301C;
9627 t['wavyunderscorevertical'] = 0xFE34;
9628 t['wawarabic'] = 0x0648;
9629 t['wawfinalarabic'] = 0xFEEE;
9630 t['wawhamzaabovearabic'] = 0x0624;
9631 t['wawhamzaabovefinalarabic'] = 0xFE86;
9632 t['wbsquare'] = 0x33DD;
9633 t['wcircle'] = 0x24E6;
9634 t['wcircumflex'] = 0x0175;
9635 t['wdieresis'] = 0x1E85;
9636 t['wdotaccent'] = 0x1E87;
9637 t['wdotbelow'] = 0x1E89;
9638 t['wehiragana'] = 0x3091;
9639 t['weierstrass'] = 0x2118;
9640 t['wekatakana'] = 0x30F1;
9641 t['wekorean'] = 0x315E;
9642 t['weokorean'] = 0x315D;
9643 t['wgrave'] = 0x1E81;
9644 t['whitebullet'] = 0x25E6;
9645 t['whitecircle'] = 0x25CB;
9646 t['whitecircleinverse'] = 0x25D9;
9647 t['whitecornerbracketleft'] = 0x300E;
9648 t['whitecornerbracketleftvertical'] = 0xFE43;
9649 t['whitecornerbracketright'] = 0x300F;
9650 t['whitecornerbracketrightvertical'] = 0xFE44;
9651 t['whitediamond'] = 0x25C7;
9652 t['whitediamondcontainingblacksmalldiamond'] = 0x25C8;
9653 t['whitedownpointingsmalltriangle'] = 0x25BF;
9654 t['whitedownpointingtriangle'] = 0x25BD;
9655 t['whiteleftpointingsmalltriangle'] = 0x25C3;
9656 t['whiteleftpointingtriangle'] = 0x25C1;
9657 t['whitelenticularbracketleft'] = 0x3016;
9658 t['whitelenticularbracketright'] = 0x3017;
9659 t['whiterightpointingsmalltriangle'] = 0x25B9;
9660 t['whiterightpointingtriangle'] = 0x25B7;
9661 t['whitesmallsquare'] = 0x25AB;
9662 t['whitesmilingface'] = 0x263A;
9663 t['whitesquare'] = 0x25A1;
9664 t['whitestar'] = 0x2606;
9665 t['whitetelephone'] = 0x260F;
9666 t['whitetortoiseshellbracketleft'] = 0x3018;
9667 t['whitetortoiseshellbracketright'] = 0x3019;
9668 t['whiteuppointingsmalltriangle'] = 0x25B5;
9669 t['whiteuppointingtriangle'] = 0x25B3;
9670 t['wihiragana'] = 0x3090;
9671 t['wikatakana'] = 0x30F0;
9672 t['wikorean'] = 0x315F;
9673 t['wmonospace'] = 0xFF57;
9674 t['wohiragana'] = 0x3092;
9675 t['wokatakana'] = 0x30F2;
9676 t['wokatakanahalfwidth'] = 0xFF66;
9677 t['won'] = 0x20A9;
9678 t['wonmonospace'] = 0xFFE6;
9679 t['wowaenthai'] = 0x0E27;
9680 t['wparen'] = 0x24B2;
9681 t['wring'] = 0x1E98;
9682 t['wsuperior'] = 0x02B7;
9683 t['wturned'] = 0x028D;
9684 t['wynn'] = 0x01BF;
9685 t['x'] = 0x0078;
9686 t['xabovecmb'] = 0x033D;
9687 t['xbopomofo'] = 0x3112;
9688 t['xcircle'] = 0x24E7;
9689 t['xdieresis'] = 0x1E8D;
9690 t['xdotaccent'] = 0x1E8B;
9691 t['xeharmenian'] = 0x056D;
9692 t['xi'] = 0x03BE;
9693 t['xmonospace'] = 0xFF58;
9694 t['xparen'] = 0x24B3;
9695 t['xsuperior'] = 0x02E3;
9696 t['y'] = 0x0079;
9697 t['yaadosquare'] = 0x334E;
9698 t['yabengali'] = 0x09AF;
9699 t['yacute'] = 0x00FD;
9700 t['yadeva'] = 0x092F;
9701 t['yaekorean'] = 0x3152;
9702 t['yagujarati'] = 0x0AAF;
9703 t['yagurmukhi'] = 0x0A2F;
9704 t['yahiragana'] = 0x3084;
9705 t['yakatakana'] = 0x30E4;
9706 t['yakatakanahalfwidth'] = 0xFF94;
9707 t['yakorean'] = 0x3151;
9708 t['yamakkanthai'] = 0x0E4E;
9709 t['yasmallhiragana'] = 0x3083;
9710 t['yasmallkatakana'] = 0x30E3;
9711 t['yasmallkatakanahalfwidth'] = 0xFF6C;
9712 t['yatcyrillic'] = 0x0463;
9713 t['ycircle'] = 0x24E8;
9714 t['ycircumflex'] = 0x0177;
9715 t['ydieresis'] = 0x00FF;
9716 t['ydotaccent'] = 0x1E8F;
9717 t['ydotbelow'] = 0x1EF5;
9718 t['yeharabic'] = 0x064A;
9719 t['yehbarreearabic'] = 0x06D2;
9720 t['yehbarreefinalarabic'] = 0xFBAF;
9721 t['yehfinalarabic'] = 0xFEF2;
9722 t['yehhamzaabovearabic'] = 0x0626;
9723 t['yehhamzaabovefinalarabic'] = 0xFE8A;
9724 t['yehhamzaaboveinitialarabic'] = 0xFE8B;
9725 t['yehhamzaabovemedialarabic'] = 0xFE8C;
9726 t['yehinitialarabic'] = 0xFEF3;
9727 t['yehmedialarabic'] = 0xFEF4;
9728 t['yehmeeminitialarabic'] = 0xFCDD;
9729 t['yehmeemisolatedarabic'] = 0xFC58;
9730 t['yehnoonfinalarabic'] = 0xFC94;
9731 t['yehthreedotsbelowarabic'] = 0x06D1;
9732 t['yekorean'] = 0x3156;
9733 t['yen'] = 0x00A5;
9734 t['yenmonospace'] = 0xFFE5;
9735 t['yeokorean'] = 0x3155;
9736 t['yeorinhieuhkorean'] = 0x3186;
9737 t['yerahbenyomohebrew'] = 0x05AA;
9738 t['yerahbenyomolefthebrew'] = 0x05AA;
9739 t['yericyrillic'] = 0x044B;
9740 t['yerudieresiscyrillic'] = 0x04F9;
9741 t['yesieungkorean'] = 0x3181;
9742 t['yesieungpansioskorean'] = 0x3183;
9743 t['yesieungsioskorean'] = 0x3182;
9744 t['yetivhebrew'] = 0x059A;
9745 t['ygrave'] = 0x1EF3;
9746 t['yhook'] = 0x01B4;
9747 t['yhookabove'] = 0x1EF7;
9748 t['yiarmenian'] = 0x0575;
9749 t['yicyrillic'] = 0x0457;
9750 t['yikorean'] = 0x3162;
9751 t['yinyang'] = 0x262F;
9752 t['yiwnarmenian'] = 0x0582;
9753 t['ymonospace'] = 0xFF59;
9754 t['yod'] = 0x05D9;
9755 t['yoddagesh'] = 0xFB39;
9756 t['yoddageshhebrew'] = 0xFB39;
9757 t['yodhebrew'] = 0x05D9;
9758 t['yodyodhebrew'] = 0x05F2;
9759 t['yodyodpatahhebrew'] = 0xFB1F;
9760 t['yohiragana'] = 0x3088;
9761 t['yoikorean'] = 0x3189;
9762 t['yokatakana'] = 0x30E8;
9763 t['yokatakanahalfwidth'] = 0xFF96;
9764 t['yokorean'] = 0x315B;
9765 t['yosmallhiragana'] = 0x3087;
9766 t['yosmallkatakana'] = 0x30E7;
9767 t['yosmallkatakanahalfwidth'] = 0xFF6E;
9768 t['yotgreek'] = 0x03F3;
9769 t['yoyaekorean'] = 0x3188;
9770 t['yoyakorean'] = 0x3187;
9771 t['yoyakthai'] = 0x0E22;
9772 t['yoyingthai'] = 0x0E0D;
9773 t['yparen'] = 0x24B4;
9774 t['ypogegrammeni'] = 0x037A;
9775 t['ypogegrammenigreekcmb'] = 0x0345;
9776 t['yr'] = 0x01A6;
9777 t['yring'] = 0x1E99;
9778 t['ysuperior'] = 0x02B8;
9779 t['ytilde'] = 0x1EF9;
9780 t['yturned'] = 0x028E;
9781 t['yuhiragana'] = 0x3086;
9782 t['yuikorean'] = 0x318C;
9783 t['yukatakana'] = 0x30E6;
9784 t['yukatakanahalfwidth'] = 0xFF95;
9785 t['yukorean'] = 0x3160;
9786 t['yusbigcyrillic'] = 0x046B;
9787 t['yusbigiotifiedcyrillic'] = 0x046D;
9788 t['yuslittlecyrillic'] = 0x0467;
9789 t['yuslittleiotifiedcyrillic'] = 0x0469;
9790 t['yusmallhiragana'] = 0x3085;
9791 t['yusmallkatakana'] = 0x30E5;
9792 t['yusmallkatakanahalfwidth'] = 0xFF6D;
9793 t['yuyekorean'] = 0x318B;
9794 t['yuyeokorean'] = 0x318A;
9795 t['yyabengali'] = 0x09DF;
9796 t['yyadeva'] = 0x095F;
9797 t['z'] = 0x007A;
9798 t['zaarmenian'] = 0x0566;
9799 t['zacute'] = 0x017A;
9800 t['zadeva'] = 0x095B;
9801 t['zagurmukhi'] = 0x0A5B;
9802 t['zaharabic'] = 0x0638;
9803 t['zahfinalarabic'] = 0xFEC6;
9804 t['zahinitialarabic'] = 0xFEC7;
9805 t['zahiragana'] = 0x3056;
9806 t['zahmedialarabic'] = 0xFEC8;
9807 t['zainarabic'] = 0x0632;
9808 t['zainfinalarabic'] = 0xFEB0;
9809 t['zakatakana'] = 0x30B6;
9810 t['zaqefgadolhebrew'] = 0x0595;
9811 t['zaqefqatanhebrew'] = 0x0594;
9812 t['zarqahebrew'] = 0x0598;
9813 t['zayin'] = 0x05D6;
9814 t['zayindagesh'] = 0xFB36;
9815 t['zayindageshhebrew'] = 0xFB36;
9816 t['zayinhebrew'] = 0x05D6;
9817 t['zbopomofo'] = 0x3117;
9818 t['zcaron'] = 0x017E;
9819 t['zcircle'] = 0x24E9;
9820 t['zcircumflex'] = 0x1E91;
9821 t['zcurl'] = 0x0291;
9822 t['zdot'] = 0x017C;
9823 t['zdotaccent'] = 0x017C;
9824 t['zdotbelow'] = 0x1E93;
9825 t['zecyrillic'] = 0x0437;
9826 t['zedescendercyrillic'] = 0x0499;
9827 t['zedieresiscyrillic'] = 0x04DF;
9828 t['zehiragana'] = 0x305C;
9829 t['zekatakana'] = 0x30BC;
9830 t['zero'] = 0x0030;
9831 t['zeroarabic'] = 0x0660;
9832 t['zerobengali'] = 0x09E6;
9833 t['zerodeva'] = 0x0966;
9834 t['zerogujarati'] = 0x0AE6;
9835 t['zerogurmukhi'] = 0x0A66;
9836 t['zerohackarabic'] = 0x0660;
9837 t['zeroinferior'] = 0x2080;
9838 t['zeromonospace'] = 0xFF10;
9839 t['zerooldstyle'] = 0xF730;
9840 t['zeropersian'] = 0x06F0;
9841 t['zerosuperior'] = 0x2070;
9842 t['zerothai'] = 0x0E50;
9843 t['zerowidthjoiner'] = 0xFEFF;
9844 t['zerowidthnonjoiner'] = 0x200C;
9845 t['zerowidthspace'] = 0x200B;
9846 t['zeta'] = 0x03B6;
9847 t['zhbopomofo'] = 0x3113;
9848 t['zhearmenian'] = 0x056A;
9849 t['zhebrevecyrillic'] = 0x04C2;
9850 t['zhecyrillic'] = 0x0436;
9851 t['zhedescendercyrillic'] = 0x0497;
9852 t['zhedieresiscyrillic'] = 0x04DD;
9853 t['zihiragana'] = 0x3058;
9854 t['zikatakana'] = 0x30B8;
9855 t['zinorhebrew'] = 0x05AE;
9856 t['zlinebelow'] = 0x1E95;
9857 t['zmonospace'] = 0xFF5A;
9858 t['zohiragana'] = 0x305E;
9859 t['zokatakana'] = 0x30BE;
9860 t['zparen'] = 0x24B5;
9861 t['zretroflexhook'] = 0x0290;
9862 t['zstroke'] = 0x01B6;
9863 t['zuhiragana'] = 0x305A;
9864 t['zukatakana'] = 0x30BA;
9865 t['.notdef'] = 0x0000;
9866});
9867
9868var getDingbatsGlyphsUnicode = getLookupTableFactory(function (t) {
9869 t['space'] = 0x0020;
9870 t['a1'] = 0x2701;
9871 t['a2'] = 0x2702;
9872 t['a202'] = 0x2703;
9873 t['a3'] = 0x2704;
9874 t['a4'] = 0x260E;
9875 t['a5'] = 0x2706;
9876 t['a119'] = 0x2707;
9877 t['a118'] = 0x2708;
9878 t['a117'] = 0x2709;
9879 t['a11'] = 0x261B;
9880 t['a12'] = 0x261E;
9881 t['a13'] = 0x270C;
9882 t['a14'] = 0x270D;
9883 t['a15'] = 0x270E;
9884 t['a16'] = 0x270F;
9885 t['a105'] = 0x2710;
9886 t['a17'] = 0x2711;
9887 t['a18'] = 0x2712;
9888 t['a19'] = 0x2713;
9889 t['a20'] = 0x2714;
9890 t['a21'] = 0x2715;
9891 t['a22'] = 0x2716;
9892 t['a23'] = 0x2717;
9893 t['a24'] = 0x2718;
9894 t['a25'] = 0x2719;
9895 t['a26'] = 0x271A;
9896 t['a27'] = 0x271B;
9897 t['a28'] = 0x271C;
9898 t['a6'] = 0x271D;
9899 t['a7'] = 0x271E;
9900 t['a8'] = 0x271F;
9901 t['a9'] = 0x2720;
9902 t['a10'] = 0x2721;
9903 t['a29'] = 0x2722;
9904 t['a30'] = 0x2723;
9905 t['a31'] = 0x2724;
9906 t['a32'] = 0x2725;
9907 t['a33'] = 0x2726;
9908 t['a34'] = 0x2727;
9909 t['a35'] = 0x2605;
9910 t['a36'] = 0x2729;
9911 t['a37'] = 0x272A;
9912 t['a38'] = 0x272B;
9913 t['a39'] = 0x272C;
9914 t['a40'] = 0x272D;
9915 t['a41'] = 0x272E;
9916 t['a42'] = 0x272F;
9917 t['a43'] = 0x2730;
9918 t['a44'] = 0x2731;
9919 t['a45'] = 0x2732;
9920 t['a46'] = 0x2733;
9921 t['a47'] = 0x2734;
9922 t['a48'] = 0x2735;
9923 t['a49'] = 0x2736;
9924 t['a50'] = 0x2737;
9925 t['a51'] = 0x2738;
9926 t['a52'] = 0x2739;
9927 t['a53'] = 0x273A;
9928 t['a54'] = 0x273B;
9929 t['a55'] = 0x273C;
9930 t['a56'] = 0x273D;
9931 t['a57'] = 0x273E;
9932 t['a58'] = 0x273F;
9933 t['a59'] = 0x2740;
9934 t['a60'] = 0x2741;
9935 t['a61'] = 0x2742;
9936 t['a62'] = 0x2743;
9937 t['a63'] = 0x2744;
9938 t['a64'] = 0x2745;
9939 t['a65'] = 0x2746;
9940 t['a66'] = 0x2747;
9941 t['a67'] = 0x2748;
9942 t['a68'] = 0x2749;
9943 t['a69'] = 0x274A;
9944 t['a70'] = 0x274B;
9945 t['a71'] = 0x25CF;
9946 t['a72'] = 0x274D;
9947 t['a73'] = 0x25A0;
9948 t['a74'] = 0x274F;
9949 t['a203'] = 0x2750;
9950 t['a75'] = 0x2751;
9951 t['a204'] = 0x2752;
9952 t['a76'] = 0x25B2;
9953 t['a77'] = 0x25BC;
9954 t['a78'] = 0x25C6;
9955 t['a79'] = 0x2756;
9956 t['a81'] = 0x25D7;
9957 t['a82'] = 0x2758;
9958 t['a83'] = 0x2759;
9959 t['a84'] = 0x275A;
9960 t['a97'] = 0x275B;
9961 t['a98'] = 0x275C;
9962 t['a99'] = 0x275D;
9963 t['a100'] = 0x275E;
9964 t['a101'] = 0x2761;
9965 t['a102'] = 0x2762;
9966 t['a103'] = 0x2763;
9967 t['a104'] = 0x2764;
9968 t['a106'] = 0x2765;
9969 t['a107'] = 0x2766;
9970 t['a108'] = 0x2767;
9971 t['a112'] = 0x2663;
9972 t['a111'] = 0x2666;
9973 t['a110'] = 0x2665;
9974 t['a109'] = 0x2660;
9975 t['a120'] = 0x2460;
9976 t['a121'] = 0x2461;
9977 t['a122'] = 0x2462;
9978 t['a123'] = 0x2463;
9979 t['a124'] = 0x2464;
9980 t['a125'] = 0x2465;
9981 t['a126'] = 0x2466;
9982 t['a127'] = 0x2467;
9983 t['a128'] = 0x2468;
9984 t['a129'] = 0x2469;
9985 t['a130'] = 0x2776;
9986 t['a131'] = 0x2777;
9987 t['a132'] = 0x2778;
9988 t['a133'] = 0x2779;
9989 t['a134'] = 0x277A;
9990 t['a135'] = 0x277B;
9991 t['a136'] = 0x277C;
9992 t['a137'] = 0x277D;
9993 t['a138'] = 0x277E;
9994 t['a139'] = 0x277F;
9995 t['a140'] = 0x2780;
9996 t['a141'] = 0x2781;
9997 t['a142'] = 0x2782;
9998 t['a143'] = 0x2783;
9999 t['a144'] = 0x2784;
10000 t['a145'] = 0x2785;
10001 t['a146'] = 0x2786;
10002 t['a147'] = 0x2787;
10003 t['a148'] = 0x2788;
10004 t['a149'] = 0x2789;
10005 t['a150'] = 0x278A;
10006 t['a151'] = 0x278B;
10007 t['a152'] = 0x278C;
10008 t['a153'] = 0x278D;
10009 t['a154'] = 0x278E;
10010 t['a155'] = 0x278F;
10011 t['a156'] = 0x2790;
10012 t['a157'] = 0x2791;
10013 t['a158'] = 0x2792;
10014 t['a159'] = 0x2793;
10015 t['a160'] = 0x2794;
10016 t['a161'] = 0x2192;
10017 t['a163'] = 0x2194;
10018 t['a164'] = 0x2195;
10019 t['a196'] = 0x2798;
10020 t['a165'] = 0x2799;
10021 t['a192'] = 0x279A;
10022 t['a166'] = 0x279B;
10023 t['a167'] = 0x279C;
10024 t['a168'] = 0x279D;
10025 t['a169'] = 0x279E;
10026 t['a170'] = 0x279F;
10027 t['a171'] = 0x27A0;
10028 t['a172'] = 0x27A1;
10029 t['a173'] = 0x27A2;
10030 t['a162'] = 0x27A3;
10031 t['a174'] = 0x27A4;
10032 t['a175'] = 0x27A5;
10033 t['a176'] = 0x27A6;
10034 t['a177'] = 0x27A7;
10035 t['a178'] = 0x27A8;
10036 t['a179'] = 0x27A9;
10037 t['a193'] = 0x27AA;
10038 t['a180'] = 0x27AB;
10039 t['a199'] = 0x27AC;
10040 t['a181'] = 0x27AD;
10041 t['a200'] = 0x27AE;
10042 t['a182'] = 0x27AF;
10043 t['a201'] = 0x27B1;
10044 t['a183'] = 0x27B2;
10045 t['a184'] = 0x27B3;
10046 t['a197'] = 0x27B4;
10047 t['a185'] = 0x27B5;
10048 t['a194'] = 0x27B6;
10049 t['a198'] = 0x27B7;
10050 t['a186'] = 0x27B8;
10051 t['a195'] = 0x27B9;
10052 t['a187'] = 0x27BA;
10053 t['a188'] = 0x27BB;
10054 t['a189'] = 0x27BC;
10055 t['a190'] = 0x27BD;
10056 t['a191'] = 0x27BE;
10057 t['a89'] = 0x2768; // 0xF8D7
10058 t['a90'] = 0x2769; // 0xF8D8
10059 t['a93'] = 0x276A; // 0xF8D9
10060 t['a94'] = 0x276B; // 0xF8DA
10061 t['a91'] = 0x276C; // 0xF8DB
10062 t['a92'] = 0x276D; // 0xF8DC
10063 t['a205'] = 0x276E; // 0xF8DD
10064 t['a85'] = 0x276F; // 0xF8DE
10065 t['a206'] = 0x2770; // 0xF8DF
10066 t['a86'] = 0x2771; // 0xF8E0
10067 t['a87'] = 0x2772; // 0xF8E1
10068 t['a88'] = 0x2773; // 0xF8E2
10069 t['a95'] = 0x2774; // 0xF8E3
10070 t['a96'] = 0x2775; // 0xF8E4
10071 t['.notdef'] = 0x0000;
10072});
10073
10074exports.getGlyphsUnicode = getGlyphsUnicode;
10075exports.getDingbatsGlyphsUnicode = getDingbatsGlyphsUnicode;
10076}));
10077
10078
10079(function (root, factory) {
10080 {
10081 factory((root.pdfjsCoreJbig2 = {}), root.pdfjsSharedUtil,
10082 root.pdfjsCoreArithmeticDecoder);
10083 }
10084}(this, function (exports, sharedUtil, coreArithmeticDecoder) {
10085
10086var error = sharedUtil.error;
10087var log2 = sharedUtil.log2;
10088var readInt8 = sharedUtil.readInt8;
10089var readUint16 = sharedUtil.readUint16;
10090var readUint32 = sharedUtil.readUint32;
10091var shadow = sharedUtil.shadow;
10092var ArithmeticDecoder = coreArithmeticDecoder.ArithmeticDecoder;
10093
10094var Jbig2Image = (function Jbig2ImageClosure() {
10095 // Utility data structures
10096 function ContextCache() {}
10097
10098 ContextCache.prototype = {
10099 getContexts: function(id) {
10100 if (id in this) {
10101 return this[id];
10102 }
10103 return (this[id] = new Int8Array(1 << 16));
10104 }
10105 };
10106
10107 function DecodingContext(data, start, end) {
10108 this.data = data;
10109 this.start = start;
10110 this.end = end;
10111 }
10112
10113 DecodingContext.prototype = {
10114 get decoder() {
10115 var decoder = new ArithmeticDecoder(this.data, this.start, this.end);
10116 return shadow(this, 'decoder', decoder);
10117 },
10118 get contextCache() {
10119 var cache = new ContextCache();
10120 return shadow(this, 'contextCache', cache);
10121 }
10122 };
10123
10124 // Annex A. Arithmetic Integer Decoding Procedure
10125 // A.2 Procedure for decoding values
10126 function decodeInteger(contextCache, procedure, decoder) {
10127 var contexts = contextCache.getContexts(procedure);
10128 var prev = 1;
10129
10130 function readBits(length) {
10131 var v = 0;
10132 for (var i = 0; i < length; i++) {
10133 var bit = decoder.readBit(contexts, prev);
10134 prev = (prev < 256 ? (prev << 1) | bit :
10135 (((prev << 1) | bit) & 511) | 256);
10136 v = (v << 1) | bit;
10137 }
10138 return v >>> 0;
10139 }
10140
10141 var sign = readBits(1);
10142 var value = readBits(1) ?
10143 (readBits(1) ?
10144 (readBits(1) ?
10145 (readBits(1) ?
10146 (readBits(1) ?
10147 (readBits(32) + 4436) :
10148 readBits(12) + 340) :
10149 readBits(8) + 84) :
10150 readBits(6) + 20) :
10151 readBits(4) + 4) :
10152 readBits(2);
10153 return (sign === 0 ? value : (value > 0 ? -value : null));
10154 }
10155
10156 // A.3 The IAID decoding procedure
10157 function decodeIAID(contextCache, decoder, codeLength) {
10158 var contexts = contextCache.getContexts('IAID');
10159
10160 var prev = 1;
10161 for (var i = 0; i < codeLength; i++) {
10162 var bit = decoder.readBit(contexts, prev);
10163 prev = (prev << 1) | bit;
10164 }
10165 if (codeLength < 31) {
10166 return prev & ((1 << codeLength) - 1);
10167 }
10168 return prev & 0x7FFFFFFF;
10169 }
10170
10171 // 7.3 Segment types
10172 var SegmentTypes = [
10173 'SymbolDictionary', null, null, null, 'IntermediateTextRegion', null,
10174 'ImmediateTextRegion', 'ImmediateLosslessTextRegion', null, null, null,
10175 null, null, null, null, null, 'patternDictionary', null, null, null,
10176 'IntermediateHalftoneRegion', null, 'ImmediateHalftoneRegion',
10177 'ImmediateLosslessHalftoneRegion', null, null, null, null, null, null, null,
10178 null, null, null, null, null, 'IntermediateGenericRegion', null,
10179 'ImmediateGenericRegion', 'ImmediateLosslessGenericRegion',
10180 'IntermediateGenericRefinementRegion', null,
10181 'ImmediateGenericRefinementRegion',
10182 'ImmediateLosslessGenericRefinementRegion', null, null, null, null,
10183 'PageInformation', 'EndOfPage', 'EndOfStripe', 'EndOfFile', 'Profiles',
10184 'Tables', null, null, null, null, null, null, null, null,
10185 'Extension'
10186 ];
10187
10188 var CodingTemplates = [
10189 [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1},
10190 {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: 2, y: -1},
10191 {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}],
10192 [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: 2, y: -2},
10193 {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1},
10194 {x: 2, y: -1}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}],
10195 [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1},
10196 {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -2, y: 0},
10197 {x: -1, y: 0}],
10198 [{x: -3, y: -1}, {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1},
10199 {x: 1, y: -1}, {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}]
10200 ];
10201
10202 var RefinementTemplates = [
10203 {
10204 coding: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}],
10205 reference: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}, {x: 0, y: 0},
10206 {x: 1, y: 0}, {x: -1, y: 1}, {x: 0, y: 1}, {x: 1, y: 1}]
10207 },
10208 {
10209 coding: [{x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}],
10210 reference: [{x: 0, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, {x: 1, y: 0},
10211 {x: 0, y: 1}, {x: 1, y: 1}]
10212 }
10213 ];
10214
10215 // See 6.2.5.7 Decoding the bitmap.
10216 var ReusedContexts = [
10217 0x9B25, // 10011 0110010 0101
10218 0x0795, // 0011 110010 101
10219 0x00E5, // 001 11001 01
10220 0x0195 // 011001 0101
10221 ];
10222
10223 var RefinementReusedContexts = [
10224 0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference)
10225 0x0008 // '0000' + '001000'
10226 ];
10227
10228 function decodeBitmapTemplate0(width, height, decodingContext) {
10229 var decoder = decodingContext.decoder;
10230 var contexts = decodingContext.contextCache.getContexts('GB');
10231 var contextLabel, i, j, pixel, row, row1, row2, bitmap = [];
10232
10233 // ...ooooo....
10234 // ..ooooooo... Context template for current pixel (X)
10235 // .ooooX...... (concatenate values of 'o'-pixels to get contextLabel)
10236 var OLD_PIXEL_MASK = 0x7BF7; // 01111 0111111 0111
10237
10238 for (i = 0; i < height; i++) {
10239 row = bitmap[i] = new Uint8Array(width);
10240 row1 = (i < 1) ? row : bitmap[i - 1];
10241 row2 = (i < 2) ? row : bitmap[i - 2];
10242
10243 // At the beginning of each row:
10244 // Fill contextLabel with pixels that are above/right of (X)
10245 contextLabel = (row2[0] << 13) | (row2[1] << 12) | (row2[2] << 11) |
10246 (row1[0] << 7) | (row1[1] << 6) | (row1[2] << 5) |
10247 (row1[3] << 4);
10248
10249 for (j = 0; j < width; j++) {
10250 row[j] = pixel = decoder.readBit(contexts, contextLabel);
10251
10252 // At each pixel: Clear contextLabel pixels that are shifted
10253 // out of the context, then add new ones.
10254 contextLabel = ((contextLabel & OLD_PIXEL_MASK) << 1) |
10255 (j + 3 < width ? row2[j + 3] << 11 : 0) |
10256 (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel;
10257 }
10258 }
10259
10260 return bitmap;
10261 }
10262
10263 // 6.2 Generic Region Decoding Procedure
10264 function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at,
10265 decodingContext) {
10266 if (mmr) {
10267 error('JBIG2 error: MMR encoding is not supported');
10268 }
10269
10270 // Use optimized version for the most common case
10271 if (templateIndex === 0 && !skip && !prediction && at.length === 4 &&
10272 at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 &&
10273 at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) {
10274 return decodeBitmapTemplate0(width, height, decodingContext);
10275 }
10276
10277 var useskip = !!skip;
10278 var template = CodingTemplates[templateIndex].concat(at);
10279
10280 // Sorting is non-standard, and it is not required. But sorting increases
10281 // the number of template bits that can be reused from the previous
10282 // contextLabel in the main loop.
10283 template.sort(function (a, b) {
10284 return (a.y - b.y) || (a.x - b.x);
10285 });
10286
10287 var templateLength = template.length;
10288 var templateX = new Int8Array(templateLength);
10289 var templateY = new Int8Array(templateLength);
10290 var changingTemplateEntries = [];
10291 var reuseMask = 0, minX = 0, maxX = 0, minY = 0;
10292 var c, k;
10293
10294 for (k = 0; k < templateLength; k++) {
10295 templateX[k] = template[k].x;
10296 templateY[k] = template[k].y;
10297 minX = Math.min(minX, template[k].x);
10298 maxX = Math.max(maxX, template[k].x);
10299 minY = Math.min(minY, template[k].y);
10300 // Check if the template pixel appears in two consecutive context labels,
10301 // so it can be reused. Otherwise, we add it to the list of changing
10302 // template entries.
10303 if (k < templateLength - 1 &&
10304 template[k].y === template[k + 1].y &&
10305 template[k].x === template[k + 1].x - 1) {
10306 reuseMask |= 1 << (templateLength - 1 - k);
10307 } else {
10308 changingTemplateEntries.push(k);
10309 }
10310 }
10311 var changingEntriesLength = changingTemplateEntries.length;
10312
10313 var changingTemplateX = new Int8Array(changingEntriesLength);
10314 var changingTemplateY = new Int8Array(changingEntriesLength);
10315 var changingTemplateBit = new Uint16Array(changingEntriesLength);
10316 for (c = 0; c < changingEntriesLength; c++) {
10317 k = changingTemplateEntries[c];
10318 changingTemplateX[c] = template[k].x;
10319 changingTemplateY[c] = template[k].y;
10320 changingTemplateBit[c] = 1 << (templateLength - 1 - k);
10321 }
10322
10323 // Get the safe bounding box edges from the width, height, minX, maxX, minY
10324 var sbb_left = -minX;
10325 var sbb_top = -minY;
10326 var sbb_right = width - maxX;
10327
10328 var pseudoPixelContext = ReusedContexts[templateIndex];
10329 var row = new Uint8Array(width);
10330 var bitmap = [];
10331
10332 var decoder = decodingContext.decoder;
10333 var contexts = decodingContext.contextCache.getContexts('GB');
10334
10335 var ltp = 0, j, i0, j0, contextLabel = 0, bit, shift;
10336 for (var i = 0; i < height; i++) {
10337 if (prediction) {
10338 var sltp = decoder.readBit(contexts, pseudoPixelContext);
10339 ltp ^= sltp;
10340 if (ltp) {
10341 bitmap.push(row); // duplicate previous row
10342 continue;
10343 }
10344 }
10345 row = new Uint8Array(row);
10346 bitmap.push(row);
10347 for (j = 0; j < width; j++) {
10348 if (useskip && skip[i][j]) {
10349 row[j] = 0;
10350 continue;
10351 }
10352 // Are we in the middle of a scanline, so we can reuse contextLabel
10353 // bits?
10354 if (j >= sbb_left && j < sbb_right && i >= sbb_top) {
10355 // If yes, we can just shift the bits that are reusable and only
10356 // fetch the remaining ones.
10357 contextLabel = (contextLabel << 1) & reuseMask;
10358 for (k = 0; k < changingEntriesLength; k++) {
10359 i0 = i + changingTemplateY[k];
10360 j0 = j + changingTemplateX[k];
10361 bit = bitmap[i0][j0];
10362 if (bit) {
10363 bit = changingTemplateBit[k];
10364 contextLabel |= bit;
10365 }
10366 }
10367 } else {
10368 // compute the contextLabel from scratch
10369 contextLabel = 0;
10370 shift = templateLength - 1;
10371 for (k = 0; k < templateLength; k++, shift--) {
10372 j0 = j + templateX[k];
10373 if (j0 >= 0 && j0 < width) {
10374 i0 = i + templateY[k];
10375 if (i0 >= 0) {
10376 bit = bitmap[i0][j0];
10377 if (bit) {
10378 contextLabel |= bit << shift;
10379 }
10380 }
10381 }
10382 }
10383 }
10384 var pixel = decoder.readBit(contexts, contextLabel);
10385 row[j] = pixel;
10386 }
10387 }
10388 return bitmap;
10389 }
10390
10391 // 6.3.2 Generic Refinement Region Decoding Procedure
10392 function decodeRefinement(width, height, templateIndex, referenceBitmap,
10393 offsetX, offsetY, prediction, at,
10394 decodingContext) {
10395 var codingTemplate = RefinementTemplates[templateIndex].coding;
10396 if (templateIndex === 0) {
10397 codingTemplate = codingTemplate.concat([at[0]]);
10398 }
10399 var codingTemplateLength = codingTemplate.length;
10400 var codingTemplateX = new Int32Array(codingTemplateLength);
10401 var codingTemplateY = new Int32Array(codingTemplateLength);
10402 var k;
10403 for (k = 0; k < codingTemplateLength; k++) {
10404 codingTemplateX[k] = codingTemplate[k].x;
10405 codingTemplateY[k] = codingTemplate[k].y;
10406 }
10407
10408 var referenceTemplate = RefinementTemplates[templateIndex].reference;
10409 if (templateIndex === 0) {
10410 referenceTemplate = referenceTemplate.concat([at[1]]);
10411 }
10412 var referenceTemplateLength = referenceTemplate.length;
10413 var referenceTemplateX = new Int32Array(referenceTemplateLength);
10414 var referenceTemplateY = new Int32Array(referenceTemplateLength);
10415 for (k = 0; k < referenceTemplateLength; k++) {
10416 referenceTemplateX[k] = referenceTemplate[k].x;
10417 referenceTemplateY[k] = referenceTemplate[k].y;
10418 }
10419 var referenceWidth = referenceBitmap[0].length;
10420 var referenceHeight = referenceBitmap.length;
10421
10422 var pseudoPixelContext = RefinementReusedContexts[templateIndex];
10423 var bitmap = [];
10424
10425 var decoder = decodingContext.decoder;
10426 var contexts = decodingContext.contextCache.getContexts('GR');
10427
10428 var ltp = 0;
10429 for (var i = 0; i < height; i++) {
10430 if (prediction) {
10431 var sltp = decoder.readBit(contexts, pseudoPixelContext);
10432 ltp ^= sltp;
10433 if (ltp) {
10434 error('JBIG2 error: prediction is not supported');
10435 }
10436 }
10437 var row = new Uint8Array(width);
10438 bitmap.push(row);
10439 for (var j = 0; j < width; j++) {
10440 var i0, j0;
10441 var contextLabel = 0;
10442 for (k = 0; k < codingTemplateLength; k++) {
10443 i0 = i + codingTemplateY[k];
10444 j0 = j + codingTemplateX[k];
10445 if (i0 < 0 || j0 < 0 || j0 >= width) {
10446 contextLabel <<= 1; // out of bound pixel
10447 } else {
10448 contextLabel = (contextLabel << 1) | bitmap[i0][j0];
10449 }
10450 }
10451 for (k = 0; k < referenceTemplateLength; k++) {
10452 i0 = i + referenceTemplateY[k] + offsetY;
10453 j0 = j + referenceTemplateX[k] + offsetX;
10454 if (i0 < 0 || i0 >= referenceHeight || j0 < 0 ||
10455 j0 >= referenceWidth) {
10456 contextLabel <<= 1; // out of bound pixel
10457 } else {
10458 contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0];
10459 }
10460 }
10461 var pixel = decoder.readBit(contexts, contextLabel);
10462 row[j] = pixel;
10463 }
10464 }
10465
10466 return bitmap;
10467 }
10468
10469 // 6.5.5 Decoding the symbol dictionary
10470 function decodeSymbolDictionary(huffman, refinement, symbols,
10471 numberOfNewSymbols, numberOfExportedSymbols,
10472 huffmanTables, templateIndex, at,
10473 refinementTemplateIndex, refinementAt,
10474 decodingContext) {
10475 if (huffman) {
10476 error('JBIG2 error: huffman is not supported');
10477 }
10478
10479 var newSymbols = [];
10480 var currentHeight = 0;
10481 var symbolCodeLength = log2(symbols.length + numberOfNewSymbols);
10482
10483 var decoder = decodingContext.decoder;
10484 var contextCache = decodingContext.contextCache;
10485
10486 while (newSymbols.length < numberOfNewSymbols) {
10487 var deltaHeight = decodeInteger(contextCache, 'IADH', decoder); // 6.5.6
10488 currentHeight += deltaHeight;
10489 var currentWidth = 0;
10490 var totalWidth = 0;
10491 while (true) {
10492 var deltaWidth = decodeInteger(contextCache, 'IADW', decoder); // 6.5.7
10493 if (deltaWidth === null) {
10494 break; // OOB
10495 }
10496 currentWidth += deltaWidth;
10497 totalWidth += currentWidth;
10498 var bitmap;
10499 if (refinement) {
10500 // 6.5.8.2 Refinement/aggregate-coded symbol bitmap
10501 var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder);
10502 if (numberOfInstances > 1) {
10503 bitmap = decodeTextRegion(huffman, refinement,
10504 currentWidth, currentHeight, 0,
10505 numberOfInstances, 1, //strip size
10506 symbols.concat(newSymbols),
10507 symbolCodeLength,
10508 0, //transposed
10509 0, //ds offset
10510 1, //top left 7.4.3.1.1
10511 0, //OR operator
10512 huffmanTables,
10513 refinementTemplateIndex, refinementAt,
10514 decodingContext);
10515 } else {
10516 var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
10517 var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3
10518 var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4
10519 var symbol = (symbolId < symbols.length ? symbols[symbolId] :
10520 newSymbols[symbolId - symbols.length]);
10521 bitmap = decodeRefinement(currentWidth, currentHeight,
10522 refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt,
10523 decodingContext);
10524 }
10525 } else {
10526 // 6.5.8.1 Direct-coded symbol bitmap
10527 bitmap = decodeBitmap(false, currentWidth, currentHeight,
10528 templateIndex, false, null, at, decodingContext);
10529 }
10530 newSymbols.push(bitmap);
10531 }
10532 }
10533 // 6.5.10 Exported symbols
10534 var exportedSymbols = [];
10535 var flags = [], currentFlag = false;
10536 var totalSymbolsLength = symbols.length + numberOfNewSymbols;
10537 while (flags.length < totalSymbolsLength) {
10538 var runLength = decodeInteger(contextCache, 'IAEX', decoder);
10539 while (runLength--) {
10540 flags.push(currentFlag);
10541 }
10542 currentFlag = !currentFlag;
10543 }
10544 for (var i = 0, ii = symbols.length; i < ii; i++) {
10545 if (flags[i]) {
10546 exportedSymbols.push(symbols[i]);
10547 }
10548 }
10549 for (var j = 0; j < numberOfNewSymbols; i++, j++) {
10550 if (flags[i]) {
10551 exportedSymbols.push(newSymbols[j]);
10552 }
10553 }
10554 return exportedSymbols;
10555 }
10556
10557 function decodeTextRegion(huffman, refinement, width, height,
10558 defaultPixelValue, numberOfSymbolInstances,
10559 stripSize, inputSymbols, symbolCodeLength,
10560 transposed, dsOffset, referenceCorner,
10561 combinationOperator, huffmanTables,
10562 refinementTemplateIndex, refinementAt,
10563 decodingContext) {
10564 if (huffman) {
10565 error('JBIG2 error: huffman is not supported');
10566 }
10567
10568 // Prepare bitmap
10569 var bitmap = [];
10570 var i, row;
10571 for (i = 0; i < height; i++) {
10572 row = new Uint8Array(width);
10573 if (defaultPixelValue) {
10574 for (var j = 0; j < width; j++) {
10575 row[j] = defaultPixelValue;
10576 }
10577 }
10578 bitmap.push(row);
10579 }
10580
10581 var decoder = decodingContext.decoder;
10582 var contextCache = decodingContext.contextCache;
10583 var stripT = -decodeInteger(contextCache, 'IADT', decoder); // 6.4.6
10584 var firstS = 0;
10585 i = 0;
10586 while (i < numberOfSymbolInstances) {
10587 var deltaT = decodeInteger(contextCache, 'IADT', decoder); // 6.4.6
10588 stripT += deltaT;
10589
10590 var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder); // 6.4.7
10591 firstS += deltaFirstS;
10592 var currentS = firstS;
10593 do {
10594 var currentT = (stripSize === 1 ? 0 :
10595 decodeInteger(contextCache, 'IAIT', decoder)); // 6.4.9
10596 var t = stripSize * stripT + currentT;
10597 var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
10598 var applyRefinement = (refinement &&
10599 decodeInteger(contextCache, 'IARI', decoder));
10600 var symbolBitmap = inputSymbols[symbolId];
10601 var symbolWidth = symbolBitmap[0].length;
10602 var symbolHeight = symbolBitmap.length;
10603 if (applyRefinement) {
10604 var rdw = decodeInteger(contextCache, 'IARDW', decoder); // 6.4.11.1
10605 var rdh = decodeInteger(contextCache, 'IARDH', decoder); // 6.4.11.2
10606 var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3
10607 var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4
10608 symbolWidth += rdw;
10609 symbolHeight += rdh;
10610 symbolBitmap = decodeRefinement(symbolWidth, symbolHeight,
10611 refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx,
10612 (rdh >> 1) + rdy, false, refinementAt,
10613 decodingContext);
10614 }
10615 var offsetT = t - ((referenceCorner & 1) ? 0 : symbolHeight);
10616 var offsetS = currentS - ((referenceCorner & 2) ? symbolWidth : 0);
10617 var s2, t2, symbolRow;
10618 if (transposed) {
10619 // Place Symbol Bitmap from T1,S1
10620 for (s2 = 0; s2 < symbolHeight; s2++) {
10621 row = bitmap[offsetS + s2];
10622 if (!row) {
10623 continue;
10624 }
10625 symbolRow = symbolBitmap[s2];
10626 // To ignore Parts of Symbol bitmap which goes
10627 // outside bitmap region
10628 var maxWidth = Math.min(width - offsetT, symbolWidth);
10629 switch (combinationOperator) {
10630 case 0: // OR
10631 for (t2 = 0; t2 < maxWidth; t2++) {
10632 row[offsetT + t2] |= symbolRow[t2];
10633 }
10634 break;
10635 case 2: // XOR
10636 for (t2 = 0; t2 < maxWidth; t2++) {
10637 row[offsetT + t2] ^= symbolRow[t2];
10638 }
10639 break;
10640 default:
10641 error('JBIG2 error: operator ' + combinationOperator +
10642 ' is not supported');
10643 }
10644 }
10645 currentS += symbolHeight - 1;
10646 } else {
10647 for (t2 = 0; t2 < symbolHeight; t2++) {
10648 row = bitmap[offsetT + t2];
10649 if (!row) {
10650 continue;
10651 }
10652 symbolRow = symbolBitmap[t2];
10653 switch (combinationOperator) {
10654 case 0: // OR
10655 for (s2 = 0; s2 < symbolWidth; s2++) {
10656 row[offsetS + s2] |= symbolRow[s2];
10657 }
10658 break;
10659 case 2: // XOR
10660 for (s2 = 0; s2 < symbolWidth; s2++) {
10661 row[offsetS + s2] ^= symbolRow[s2];
10662 }
10663 break;
10664 default:
10665 error('JBIG2 error: operator ' + combinationOperator +
10666 ' is not supported');
10667 }
10668 }
10669 currentS += symbolWidth - 1;
10670 }
10671 i++;
10672 var deltaS = decodeInteger(contextCache, 'IADS', decoder); // 6.4.8
10673 if (deltaS === null) {
10674 break; // OOB
10675 }
10676 currentS += deltaS + dsOffset;
10677 } while (true);
10678 }
10679 return bitmap;
10680 }
10681
10682 function readSegmentHeader(data, start) {
10683 var segmentHeader = {};
10684 segmentHeader.number = readUint32(data, start);
10685 var flags = data[start + 4];
10686 var segmentType = flags & 0x3F;
10687 if (!SegmentTypes[segmentType]) {
10688 error('JBIG2 error: invalid segment type: ' + segmentType);
10689 }
10690 segmentHeader.type = segmentType;
10691 segmentHeader.typeName = SegmentTypes[segmentType];
10692 segmentHeader.deferredNonRetain = !!(flags & 0x80);
10693
10694 var pageAssociationFieldSize = !!(flags & 0x40);
10695 var referredFlags = data[start + 5];
10696 var referredToCount = (referredFlags >> 5) & 7;
10697 var retainBits = [referredFlags & 31];
10698 var position = start + 6;
10699 if (referredFlags === 7) {
10700 referredToCount = readUint32(data, position - 1) & 0x1FFFFFFF;
10701 position += 3;
10702 var bytes = (referredToCount + 7) >> 3;
10703 retainBits[0] = data[position++];
10704 while (--bytes > 0) {
10705 retainBits.push(data[position++]);
10706 }
10707 } else if (referredFlags === 5 || referredFlags === 6) {
10708 error('JBIG2 error: invalid referred-to flags');
10709 }
10710
10711 segmentHeader.retainBits = retainBits;
10712 var referredToSegmentNumberSize = (segmentHeader.number <= 256 ? 1 :
10713 (segmentHeader.number <= 65536 ? 2 : 4));
10714 var referredTo = [];
10715 var i, ii;
10716 for (i = 0; i < referredToCount; i++) {
10717 var number = (referredToSegmentNumberSize === 1 ? data[position] :
10718 (referredToSegmentNumberSize === 2 ? readUint16(data, position) :
10719 readUint32(data, position)));
10720 referredTo.push(number);
10721 position += referredToSegmentNumberSize;
10722 }
10723 segmentHeader.referredTo = referredTo;
10724 if (!pageAssociationFieldSize) {
10725 segmentHeader.pageAssociation = data[position++];
10726 } else {
10727 segmentHeader.pageAssociation = readUint32(data, position);
10728 position += 4;
10729 }
10730 segmentHeader.length = readUint32(data, position);
10731 position += 4;
10732
10733 if (segmentHeader.length === 0xFFFFFFFF) {
10734 // 7.2.7 Segment data length, unknown segment length
10735 if (segmentType === 38) { // ImmediateGenericRegion
10736 var genericRegionInfo = readRegionSegmentInformation(data, position);
10737 var genericRegionSegmentFlags = data[position +
10738 RegionSegmentInformationFieldLength];
10739 var genericRegionMmr = !!(genericRegionSegmentFlags & 1);
10740 // searching for the segment end
10741 var searchPatternLength = 6;
10742 var searchPattern = new Uint8Array(searchPatternLength);
10743 if (!genericRegionMmr) {
10744 searchPattern[0] = 0xFF;
10745 searchPattern[1] = 0xAC;
10746 }
10747 searchPattern[2] = (genericRegionInfo.height >>> 24) & 0xFF;
10748 searchPattern[3] = (genericRegionInfo.height >> 16) & 0xFF;
10749 searchPattern[4] = (genericRegionInfo.height >> 8) & 0xFF;
10750 searchPattern[5] = genericRegionInfo.height & 0xFF;
10751 for (i = position, ii = data.length; i < ii; i++) {
10752 var j = 0;
10753 while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
10754 j++;
10755 }
10756 if (j === searchPatternLength) {
10757 segmentHeader.length = i + searchPatternLength;
10758 break;
10759 }
10760 }
10761 if (segmentHeader.length === 0xFFFFFFFF) {
10762 error('JBIG2 error: segment end was not found');
10763 }
10764 } else {
10765 error('JBIG2 error: invalid unknown segment length');
10766 }
10767 }
10768 segmentHeader.headerEnd = position;
10769 return segmentHeader;
10770 }
10771
10772 function readSegments(header, data, start, end) {
10773 var segments = [];
10774 var position = start;
10775 while (position < end) {
10776 var segmentHeader = readSegmentHeader(data, position);
10777 position = segmentHeader.headerEnd;
10778 var segment = {
10779 header: segmentHeader,
10780 data: data
10781 };
10782 if (!header.randomAccess) {
10783 segment.start = position;
10784 position += segmentHeader.length;
10785 segment.end = position;
10786 }
10787 segments.push(segment);
10788 if (segmentHeader.type === 51) {
10789 break; // end of file is found
10790 }
10791 }
10792 if (header.randomAccess) {
10793 for (var i = 0, ii = segments.length; i < ii; i++) {
10794 segments[i].start = position;
10795 position += segments[i].header.length;
10796 segments[i].end = position;
10797 }
10798 }
10799 return segments;
10800 }
10801
10802 // 7.4.1 Region segment information field
10803 function readRegionSegmentInformation(data, start) {
10804 return {
10805 width: readUint32(data, start),
10806 height: readUint32(data, start + 4),
10807 x: readUint32(data, start + 8),
10808 y: readUint32(data, start + 12),
10809 combinationOperator: data[start + 16] & 7
10810 };
10811 }
10812 var RegionSegmentInformationFieldLength = 17;
10813
10814 function processSegment(segment, visitor) {
10815 var header = segment.header;
10816
10817 var data = segment.data, position = segment.start, end = segment.end;
10818 var args, at, i, atLength;
10819 switch (header.type) {
10820 case 0: // SymbolDictionary
10821 // 7.4.2 Symbol dictionary segment syntax
10822 var dictionary = {};
10823 var dictionaryFlags = readUint16(data, position); // 7.4.2.1.1
10824 dictionary.huffman = !!(dictionaryFlags & 1);
10825 dictionary.refinement = !!(dictionaryFlags & 2);
10826 dictionary.huffmanDHSelector = (dictionaryFlags >> 2) & 3;
10827 dictionary.huffmanDWSelector = (dictionaryFlags >> 4) & 3;
10828 dictionary.bitmapSizeSelector = (dictionaryFlags >> 6) & 1;
10829 dictionary.aggregationInstancesSelector = (dictionaryFlags >> 7) & 1;
10830 dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);
10831 dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);
10832 dictionary.template = (dictionaryFlags >> 10) & 3;
10833 dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1;
10834 position += 2;
10835 if (!dictionary.huffman) {
10836 atLength = dictionary.template === 0 ? 4 : 1;
10837 at = [];
10838 for (i = 0; i < atLength; i++) {
10839 at.push({
10840 x: readInt8(data, position),
10841 y: readInt8(data, position + 1)
10842 });
10843 position += 2;
10844 }
10845 dictionary.at = at;
10846 }
10847 if (dictionary.refinement && !dictionary.refinementTemplate) {
10848 at = [];
10849 for (i = 0; i < 2; i++) {
10850 at.push({
10851 x: readInt8(data, position),
10852 y: readInt8(data, position + 1)
10853 });
10854 position += 2;
10855 }
10856 dictionary.refinementAt = at;
10857 }
10858 dictionary.numberOfExportedSymbols = readUint32(data, position);
10859 position += 4;
10860 dictionary.numberOfNewSymbols = readUint32(data, position);
10861 position += 4;
10862 args = [dictionary, header.number, header.referredTo,
10863 data, position, end];
10864 break;
10865 case 6: // ImmediateTextRegion
10866 case 7: // ImmediateLosslessTextRegion
10867 var textRegion = {};
10868 textRegion.info = readRegionSegmentInformation(data, position);
10869 position += RegionSegmentInformationFieldLength;
10870 var textRegionSegmentFlags = readUint16(data, position);
10871 position += 2;
10872 textRegion.huffman = !!(textRegionSegmentFlags & 1);
10873 textRegion.refinement = !!(textRegionSegmentFlags & 2);
10874 textRegion.stripSize = 1 << ((textRegionSegmentFlags >> 2) & 3);
10875 textRegion.referenceCorner = (textRegionSegmentFlags >> 4) & 3;
10876 textRegion.transposed = !!(textRegionSegmentFlags & 64);
10877 textRegion.combinationOperator = (textRegionSegmentFlags >> 7) & 3;
10878 textRegion.defaultPixelValue = (textRegionSegmentFlags >> 9) & 1;
10879 textRegion.dsOffset = (textRegionSegmentFlags << 17) >> 27;
10880 textRegion.refinementTemplate = (textRegionSegmentFlags >> 15) & 1;
10881 if (textRegion.huffman) {
10882 var textRegionHuffmanFlags = readUint16(data, position);
10883 position += 2;
10884 textRegion.huffmanFS = (textRegionHuffmanFlags) & 3;
10885 textRegion.huffmanDS = (textRegionHuffmanFlags >> 2) & 3;
10886 textRegion.huffmanDT = (textRegionHuffmanFlags >> 4) & 3;
10887 textRegion.huffmanRefinementDW = (textRegionHuffmanFlags >> 6) & 3;
10888 textRegion.huffmanRefinementDH = (textRegionHuffmanFlags >> 8) & 3;
10889 textRegion.huffmanRefinementDX = (textRegionHuffmanFlags >> 10) & 3;
10890 textRegion.huffmanRefinementDY = (textRegionHuffmanFlags >> 12) & 3;
10891 textRegion.huffmanRefinementSizeSelector =
10892 !!(textRegionHuffmanFlags & 14);
10893 }
10894 if (textRegion.refinement && !textRegion.refinementTemplate) {
10895 at = [];
10896 for (i = 0; i < 2; i++) {
10897 at.push({
10898 x: readInt8(data, position),
10899 y: readInt8(data, position + 1)
10900 });
10901 position += 2;
10902 }
10903 textRegion.refinementAt = at;
10904 }
10905 textRegion.numberOfSymbolInstances = readUint32(data, position);
10906 position += 4;
10907 // TODO 7.4.3.1.7 Symbol ID Huffman table decoding
10908 if (textRegion.huffman) {
10909 error('JBIG2 error: huffman is not supported');
10910 }
10911 args = [textRegion, header.referredTo, data, position, end];
10912 break;
10913 case 38: // ImmediateGenericRegion
10914 case 39: // ImmediateLosslessGenericRegion
10915 var genericRegion = {};
10916 genericRegion.info = readRegionSegmentInformation(data, position);
10917 position += RegionSegmentInformationFieldLength;
10918 var genericRegionSegmentFlags = data[position++];
10919 genericRegion.mmr = !!(genericRegionSegmentFlags & 1);
10920 genericRegion.template = (genericRegionSegmentFlags >> 1) & 3;
10921 genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
10922 if (!genericRegion.mmr) {
10923 atLength = genericRegion.template === 0 ? 4 : 1;
10924 at = [];
10925 for (i = 0; i < atLength; i++) {
10926 at.push({
10927 x: readInt8(data, position),
10928 y: readInt8(data, position + 1)
10929 });
10930 position += 2;
10931 }
10932 genericRegion.at = at;
10933 }
10934 args = [genericRegion, data, position, end];
10935 break;
10936 case 48: // PageInformation
10937 var pageInfo = {
10938 width: readUint32(data, position),
10939 height: readUint32(data, position + 4),
10940 resolutionX: readUint32(data, position + 8),
10941 resolutionY: readUint32(data, position + 12)
10942 };
10943 if (pageInfo.height === 0xFFFFFFFF) {
10944 delete pageInfo.height;
10945 }
10946 var pageSegmentFlags = data[position + 16];
10947 var pageStripingInformation = readUint16(data, position + 17);
10948 pageInfo.lossless = !!(pageSegmentFlags & 1);
10949 pageInfo.refinement = !!(pageSegmentFlags & 2);
10950 pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1;
10951 pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3;
10952 pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
10953 pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
10954 args = [pageInfo];
10955 break;
10956 case 49: // EndOfPage
10957 break;
10958 case 50: // EndOfStripe
10959 break;
10960 case 51: // EndOfFile
10961 break;
10962 case 62: // 7.4.15 defines 2 extension types which
10963 // are comments and can be ignored.
10964 break;
10965 default:
10966 error('JBIG2 error: segment type ' + header.typeName + '(' +
10967 header.type + ') is not implemented');
10968 }
10969 var callbackName = 'on' + header.typeName;
10970 if (callbackName in visitor) {
10971 visitor[callbackName].apply(visitor, args);
10972 }
10973 }
10974
10975 function processSegments(segments, visitor) {
10976 for (var i = 0, ii = segments.length; i < ii; i++) {
10977 processSegment(segments[i], visitor);
10978 }
10979 }
10980
10981 function parseJbig2(data, start, end) {
10982 var position = start;
10983 if (data[position] !== 0x97 || data[position + 1] !== 0x4A ||
10984 data[position + 2] !== 0x42 || data[position + 3] !== 0x32 ||
10985 data[position + 4] !== 0x0D || data[position + 5] !== 0x0A ||
10986 data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) {
10987 error('JBIG2 error: invalid header');
10988 }
10989 var header = {};
10990 position += 8;
10991 var flags = data[position++];
10992 header.randomAccess = !(flags & 1);
10993 if (!(flags & 2)) {
10994 header.numberOfPages = readUint32(data, position);
10995 position += 4;
10996 }
10997 var segments = readSegments(header, data, position, end);
10998 error('Not implemented');
10999 // processSegments(segments, new SimpleSegmentVisitor());
11000 }
11001
11002 function parseJbig2Chunks(chunks) {
11003 var visitor = new SimpleSegmentVisitor();
11004 for (var i = 0, ii = chunks.length; i < ii; i++) {
11005 var chunk = chunks[i];
11006 var segments = readSegments({}, chunk.data, chunk.start, chunk.end);
11007 processSegments(segments, visitor);
11008 }
11009 return visitor.buffer;
11010 }
11011
11012 function SimpleSegmentVisitor() {}
11013
11014 SimpleSegmentVisitor.prototype = {
11015 onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) {
11016 this.currentPageInfo = info;
11017 var rowSize = (info.width + 7) >> 3;
11018 var buffer = new Uint8Array(rowSize * info.height);
11019 // The contents of ArrayBuffers are initialized to 0.
11020 // Fill the buffer with 0xFF only if info.defaultPixelValue is set
11021 if (info.defaultPixelValue) {
11022 for (var i = 0, ii = buffer.length; i < ii; i++) {
11023 buffer[i] = 0xFF;
11024 }
11025 }
11026 this.buffer = buffer;
11027 },
11028 drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) {
11029 var pageInfo = this.currentPageInfo;
11030 var width = regionInfo.width, height = regionInfo.height;
11031 var rowSize = (pageInfo.width + 7) >> 3;
11032 var combinationOperator = pageInfo.combinationOperatorOverride ?
11033 regionInfo.combinationOperator : pageInfo.combinationOperator;
11034 var buffer = this.buffer;
11035 var mask0 = 128 >> (regionInfo.x & 7);
11036 var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
11037 var i, j, mask, offset;
11038 switch (combinationOperator) {
11039 case 0: // OR
11040 for (i = 0; i < height; i++) {
11041 mask = mask0;
11042 offset = offset0;
11043 for (j = 0; j < width; j++) {
11044 if (bitmap[i][j]) {
11045 buffer[offset] |= mask;
11046 }
11047 mask >>= 1;
11048 if (!mask) {
11049 mask = 128;
11050 offset++;
11051 }
11052 }
11053 offset0 += rowSize;
11054 }
11055 break;
11056 case 2: // XOR
11057 for (i = 0; i < height; i++) {
11058 mask = mask0;
11059 offset = offset0;
11060 for (j = 0; j < width; j++) {
11061 if (bitmap[i][j]) {
11062 buffer[offset] ^= mask;
11063 }
11064 mask >>= 1;
11065 if (!mask) {
11066 mask = 128;
11067 offset++;
11068 }
11069 }
11070 offset0 += rowSize;
11071 }
11072 break;
11073 default:
11074 error('JBIG2 error: operator ' + combinationOperator +
11075 ' is not supported');
11076 }
11077 },
11078 onImmediateGenericRegion:
11079 function SimpleSegmentVisitor_onImmediateGenericRegion(region, data,
11080 start, end) {
11081 var regionInfo = region.info;
11082 var decodingContext = new DecodingContext(data, start, end);
11083 var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height,
11084 region.template, region.prediction, null,
11085 region.at, decodingContext);
11086 this.drawBitmap(regionInfo, bitmap);
11087 },
11088 onImmediateLosslessGenericRegion:
11089 function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() {
11090 this.onImmediateGenericRegion.apply(this, arguments);
11091 },
11092 onSymbolDictionary:
11093 function SimpleSegmentVisitor_onSymbolDictionary(dictionary,
11094 currentSegment,
11095 referredSegments,
11096 data, start, end) {
11097 var huffmanTables;
11098 if (dictionary.huffman) {
11099 error('JBIG2 error: huffman is not supported');
11100 }
11101
11102 // Combines exported symbols from all referred segments
11103 var symbols = this.symbols;
11104 if (!symbols) {
11105 this.symbols = symbols = {};
11106 }
11107
11108 var inputSymbols = [];
11109 for (var i = 0, ii = referredSegments.length; i < ii; i++) {
11110 inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]);
11111 }
11112
11113 var decodingContext = new DecodingContext(data, start, end);
11114 symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman,
11115 dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols,
11116 dictionary.numberOfExportedSymbols, huffmanTables,
11117 dictionary.template, dictionary.at,
11118 dictionary.refinementTemplate, dictionary.refinementAt,
11119 decodingContext);
11120 },
11121 onImmediateTextRegion:
11122 function SimpleSegmentVisitor_onImmediateTextRegion(region,
11123 referredSegments,
11124 data, start, end) {
11125 var regionInfo = region.info;
11126 var huffmanTables;
11127
11128 // Combines exported symbols from all referred segments
11129 var symbols = this.symbols;
11130 var inputSymbols = [];
11131 for (var i = 0, ii = referredSegments.length; i < ii; i++) {
11132 inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]);
11133 }
11134 var symbolCodeLength = log2(inputSymbols.length);
11135
11136 var decodingContext = new DecodingContext(data, start, end);
11137 var bitmap = decodeTextRegion(region.huffman, region.refinement,
11138 regionInfo.width, regionInfo.height, region.defaultPixelValue,
11139 region.numberOfSymbolInstances, region.stripSize, inputSymbols,
11140 symbolCodeLength, region.transposed, region.dsOffset,
11141 region.referenceCorner, region.combinationOperator, huffmanTables,
11142 region.refinementTemplate, region.refinementAt, decodingContext);
11143 this.drawBitmap(regionInfo, bitmap);
11144 },
11145 onImmediateLosslessTextRegion:
11146 function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
11147 this.onImmediateTextRegion.apply(this, arguments);
11148 }
11149 };
11150
11151 function Jbig2Image() {}
11152
11153 Jbig2Image.prototype = {
11154 parseChunks: function Jbig2Image_parseChunks(chunks) {
11155 return parseJbig2Chunks(chunks);
11156 }
11157 };
11158
11159 return Jbig2Image;
11160})();
11161
11162exports.Jbig2Image = Jbig2Image;
11163}));
11164
11165
11166(function (root, factory) {
11167 {
11168 factory((root.pdfjsCoreJpg = {}), root.pdfjsSharedUtil);
11169 }
11170}(this, function (exports, sharedUtil) {
11171
11172var error = sharedUtil.error;
11173
11174/**
11175 * This code was forked from https://github.com/notmasteryet/jpgjs.
11176 * The original version was created by GitHub user notmasteryet.
11177 *
11178 * - The JPEG specification can be found in the ITU CCITT Recommendation T.81
11179 * (www.w3.org/Graphics/JPEG/itu-t81.pdf)
11180 * - The JFIF specification can be found in the JPEG File Interchange Format
11181 * (www.w3.org/Graphics/JPEG/jfif3.pdf)
11182 * - The Adobe Application-Specific JPEG markers in the
11183 * Supporting the DCT Filters in PostScript Level 2, Technical Note #5116
11184 * (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
11185 */
11186
11187var JpegImage = (function JpegImageClosure() {
11188 var dctZigZag = new Uint8Array([
11189 0,
11190 1, 8,
11191 16, 9, 2,
11192 3, 10, 17, 24,
11193 32, 25, 18, 11, 4,
11194 5, 12, 19, 26, 33, 40,
11195 48, 41, 34, 27, 20, 13, 6,
11196 7, 14, 21, 28, 35, 42, 49, 56,
11197 57, 50, 43, 36, 29, 22, 15,
11198 23, 30, 37, 44, 51, 58,
11199 59, 52, 45, 38, 31,
11200 39, 46, 53, 60,
11201 61, 54, 47,
11202 55, 62,
11203 63
11204 ]);
11205
11206 var dctCos1 = 4017; // cos(pi/16)
11207 var dctSin1 = 799; // sin(pi/16)
11208 var dctCos3 = 3406; // cos(3*pi/16)
11209 var dctSin3 = 2276; // sin(3*pi/16)
11210 var dctCos6 = 1567; // cos(6*pi/16)
11211 var dctSin6 = 3784; // sin(6*pi/16)
11212 var dctSqrt2 = 5793; // sqrt(2)
11213 var dctSqrt1d2 = 2896; // sqrt(2) / 2
11214
11215 function JpegImage() {
11216 this.decodeTransform = null;
11217 this.colorTransform = -1;
11218 }
11219
11220 function buildHuffmanTable(codeLengths, values) {
11221 var k = 0, code = [], i, j, length = 16;
11222 while (length > 0 && !codeLengths[length - 1]) {
11223 length--;
11224 }
11225 code.push({children: [], index: 0});
11226 var p = code[0], q;
11227 for (i = 0; i < length; i++) {
11228 for (j = 0; j < codeLengths[i]; j++) {
11229 p = code.pop();
11230 p.children[p.index] = values[k];
11231 while (p.index > 0) {
11232 p = code.pop();
11233 }
11234 p.index++;
11235 code.push(p);
11236 while (code.length <= i) {
11237 code.push(q = {children: [], index: 0});
11238 p.children[p.index] = q.children;
11239 p = q;
11240 }
11241 k++;
11242 }
11243 if (i + 1 < length) {
11244 // p here points to last code
11245 code.push(q = {children: [], index: 0});
11246 p.children[p.index] = q.children;
11247 p = q;
11248 }
11249 }
11250 return code[0].children;
11251 }
11252
11253 function getBlockBufferOffset(component, row, col) {
11254 return 64 * ((component.blocksPerLine + 1) * row + col);
11255 }
11256
11257 function decodeScan(data, offset, frame, components, resetInterval,
11258 spectralStart, spectralEnd, successivePrev, successive) {
11259 var mcusPerLine = frame.mcusPerLine;
11260 var progressive = frame.progressive;
11261
11262 var startOffset = offset, bitsData = 0, bitsCount = 0;
11263
11264 function readBit() {
11265 if (bitsCount > 0) {
11266 bitsCount--;
11267 return (bitsData >> bitsCount) & 1;
11268 }
11269 bitsData = data[offset++];
11270 if (bitsData === 0xFF) {
11271 var nextByte = data[offset++];
11272 if (nextByte) {
11273 error('JPEG error: unexpected marker ' +
11274 ((bitsData << 8) | nextByte).toString(16));
11275 }
11276 // unstuff 0
11277 }
11278 bitsCount = 7;
11279 return bitsData >>> 7;
11280 }
11281
11282 function decodeHuffman(tree) {
11283 var node = tree;
11284 while (true) {
11285 node = node[readBit()];
11286 if (typeof node === 'number') {
11287 return node;
11288 }
11289 if (typeof node !== 'object') {
11290 error('JPEG error: invalid huffman sequence');
11291 }
11292 }
11293 }
11294
11295 function receive(length) {
11296 var n = 0;
11297 while (length > 0) {
11298 n = (n << 1) | readBit();
11299 length--;
11300 }
11301 return n;
11302 }
11303
11304 function receiveAndExtend(length) {
11305 if (length === 1) {
11306 return readBit() === 1 ? 1 : -1;
11307 }
11308 var n = receive(length);
11309 if (n >= 1 << (length - 1)) {
11310 return n;
11311 }
11312 return n + (-1 << length) + 1;
11313 }
11314
11315 function decodeBaseline(component, offset) {
11316 var t = decodeHuffman(component.huffmanTableDC);
11317 var diff = t === 0 ? 0 : receiveAndExtend(t);
11318 component.blockData[offset] = (component.pred += diff);
11319 var k = 1;
11320 while (k < 64) {
11321 var rs = decodeHuffman(component.huffmanTableAC);
11322 var s = rs & 15, r = rs >> 4;
11323 if (s === 0) {
11324 if (r < 15) {
11325 break;
11326 }
11327 k += 16;
11328 continue;
11329 }
11330 k += r;
11331 var z = dctZigZag[k];
11332 component.blockData[offset + z] = receiveAndExtend(s);
11333 k++;
11334 }
11335 }
11336
11337 function decodeDCFirst(component, offset) {
11338 var t = decodeHuffman(component.huffmanTableDC);
11339 var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
11340 component.blockData[offset] = (component.pred += diff);
11341 }
11342
11343 function decodeDCSuccessive(component, offset) {
11344 component.blockData[offset] |= readBit() << successive;
11345 }
11346
11347 var eobrun = 0;
11348 function decodeACFirst(component, offset) {
11349 if (eobrun > 0) {
11350 eobrun--;
11351 return;
11352 }
11353 var k = spectralStart, e = spectralEnd;
11354 while (k <= e) {
11355 var rs = decodeHuffman(component.huffmanTableAC);
11356 var s = rs & 15, r = rs >> 4;
11357 if (s === 0) {
11358 if (r < 15) {
11359 eobrun = receive(r) + (1 << r) - 1;
11360 break;
11361 }
11362 k += 16;
11363 continue;
11364 }
11365 k += r;
11366 var z = dctZigZag[k];
11367 component.blockData[offset + z] =
11368 receiveAndExtend(s) * (1 << successive);
11369 k++;
11370 }
11371 }
11372
11373 var successiveACState = 0, successiveACNextValue;
11374 function decodeACSuccessive(component, offset) {
11375 var k = spectralStart;
11376 var e = spectralEnd;
11377 var r = 0;
11378 var s;
11379 var rs;
11380 while (k <= e) {
11381 var z = dctZigZag[k];
11382 switch (successiveACState) {
11383 case 0: // initial state
11384 rs = decodeHuffman(component.huffmanTableAC);
11385 s = rs & 15;
11386 r = rs >> 4;
11387 if (s === 0) {
11388 if (r < 15) {
11389 eobrun = receive(r) + (1 << r);
11390 successiveACState = 4;
11391 } else {
11392 r = 16;
11393 successiveACState = 1;
11394 }
11395 } else {
11396 if (s !== 1) {
11397 error('JPEG error: invalid ACn encoding');
11398 }
11399 successiveACNextValue = receiveAndExtend(s);
11400 successiveACState = r ? 2 : 3;
11401 }
11402 continue;
11403 case 1: // skipping r zero items
11404 case 2:
11405 if (component.blockData[offset + z]) {
11406 component.blockData[offset + z] += (readBit() << successive);
11407 } else {
11408 r--;
11409 if (r === 0) {
11410 successiveACState = successiveACState === 2 ? 3 : 0;
11411 }
11412 }
11413 break;
11414 case 3: // set value for a zero item
11415 if (component.blockData[offset + z]) {
11416 component.blockData[offset + z] += (readBit() << successive);
11417 } else {
11418 component.blockData[offset + z] =
11419 successiveACNextValue << successive;
11420 successiveACState = 0;
11421 }
11422 break;
11423 case 4: // eob
11424 if (component.blockData[offset + z]) {
11425 component.blockData[offset + z] += (readBit() << successive);
11426 }
11427 break;
11428 }
11429 k++;
11430 }
11431 if (successiveACState === 4) {
11432 eobrun--;
11433 if (eobrun === 0) {
11434 successiveACState = 0;
11435 }
11436 }
11437 }
11438
11439 function decodeMcu(component, decode, mcu, row, col) {
11440 var mcuRow = (mcu / mcusPerLine) | 0;
11441 var mcuCol = mcu % mcusPerLine;
11442 var blockRow = mcuRow * component.v + row;
11443 var blockCol = mcuCol * component.h + col;
11444 var offset = getBlockBufferOffset(component, blockRow, blockCol);
11445 decode(component, offset);
11446 }
11447
11448 function decodeBlock(component, decode, mcu) {
11449 var blockRow = (mcu / component.blocksPerLine) | 0;
11450 var blockCol = mcu % component.blocksPerLine;
11451 var offset = getBlockBufferOffset(component, blockRow, blockCol);
11452 decode(component, offset);
11453 }
11454
11455 var componentsLength = components.length;
11456 var component, i, j, k, n;
11457 var decodeFn;
11458 if (progressive) {
11459 if (spectralStart === 0) {
11460 decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
11461 } else {
11462 decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
11463 }
11464 } else {
11465 decodeFn = decodeBaseline;
11466 }
11467
11468 var mcu = 0, marker;
11469 var mcuExpected;
11470 if (componentsLength === 1) {
11471 mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
11472 } else {
11473 mcuExpected = mcusPerLine * frame.mcusPerColumn;
11474 }
11475 if (!resetInterval) {
11476 resetInterval = mcuExpected;
11477 }
11478
11479 var h, v;
11480 while (mcu < mcuExpected) {
11481 // reset interval stuff
11482 for (i = 0; i < componentsLength; i++) {
11483 components[i].pred = 0;
11484 }
11485 eobrun = 0;
11486
11487 if (componentsLength === 1) {
11488 component = components[0];
11489 for (n = 0; n < resetInterval; n++) {
11490 decodeBlock(component, decodeFn, mcu);
11491 mcu++;
11492 }
11493 } else {
11494 for (n = 0; n < resetInterval; n++) {
11495 for (i = 0; i < componentsLength; i++) {
11496 component = components[i];
11497 h = component.h;
11498 v = component.v;
11499 for (j = 0; j < v; j++) {
11500 for (k = 0; k < h; k++) {
11501 decodeMcu(component, decodeFn, mcu, j, k);
11502 }
11503 }
11504 }
11505 mcu++;
11506 }
11507 }
11508
11509 // find marker
11510 bitsCount = 0;
11511 marker = (data[offset] << 8) | data[offset + 1];
11512 // Some bad images seem to pad Scan blocks with zero bytes, skip past
11513 // those to attempt to find a valid marker (fixes issue4090.pdf).
11514 while (data[offset] === 0x00 && offset < data.length - 1) {
11515 offset++;
11516 marker = (data[offset] << 8) | data[offset + 1];
11517 }
11518 if (marker <= 0xFF00) {
11519 error('JPEG error: marker was not found');
11520 }
11521
11522 if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx
11523 offset += 2;
11524 } else {
11525 break;
11526 }
11527 }
11528
11529 return offset - startOffset;
11530 }
11531
11532 // A port of poppler's IDCT method which in turn is taken from:
11533 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
11534 // 'Practical Fast 1-D DCT Algorithms with 11 Multiplications',
11535 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
11536 // 988-991.
11537 function quantizeAndInverse(component, blockBufferOffset, p) {
11538 var qt = component.quantizationTable, blockData = component.blockData;
11539 var v0, v1, v2, v3, v4, v5, v6, v7;
11540 var p0, p1, p2, p3, p4, p5, p6, p7;
11541 var t;
11542
11543 if (!qt) {
11544 error('JPEG error: missing required Quantization Table.');
11545 }
11546
11547 // inverse DCT on rows
11548 for (var row = 0; row < 64; row += 8) {
11549 // gather block data
11550 p0 = blockData[blockBufferOffset + row];
11551 p1 = blockData[blockBufferOffset + row + 1];
11552 p2 = blockData[blockBufferOffset + row + 2];
11553 p3 = blockData[blockBufferOffset + row + 3];
11554 p4 = blockData[blockBufferOffset + row + 4];
11555 p5 = blockData[blockBufferOffset + row + 5];
11556 p6 = blockData[blockBufferOffset + row + 6];
11557 p7 = blockData[blockBufferOffset + row + 7];
11558
11559 // dequant p0
11560 p0 *= qt[row];
11561
11562 // check for all-zero AC coefficients
11563 if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
11564 t = (dctSqrt2 * p0 + 512) >> 10;
11565 p[row] = t;
11566 p[row + 1] = t;
11567 p[row + 2] = t;
11568 p[row + 3] = t;
11569 p[row + 4] = t;
11570 p[row + 5] = t;
11571 p[row + 6] = t;
11572 p[row + 7] = t;
11573 continue;
11574 }
11575 // dequant p1 ... p7
11576 p1 *= qt[row + 1];
11577 p2 *= qt[row + 2];
11578 p3 *= qt[row + 3];
11579 p4 *= qt[row + 4];
11580 p5 *= qt[row + 5];
11581 p6 *= qt[row + 6];
11582 p7 *= qt[row + 7];
11583
11584 // stage 4
11585 v0 = (dctSqrt2 * p0 + 128) >> 8;
11586 v1 = (dctSqrt2 * p4 + 128) >> 8;
11587 v2 = p2;
11588 v3 = p6;
11589 v4 = (dctSqrt1d2 * (p1 - p7) + 128) >> 8;
11590 v7 = (dctSqrt1d2 * (p1 + p7) + 128) >> 8;
11591 v5 = p3 << 4;
11592 v6 = p5 << 4;
11593
11594 // stage 3
11595 v0 = (v0 + v1 + 1) >> 1;
11596 v1 = v0 - v1;
11597 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
11598 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
11599 v3 = t;
11600 v4 = (v4 + v6 + 1) >> 1;
11601 v6 = v4 - v6;
11602 v7 = (v7 + v5 + 1) >> 1;
11603 v5 = v7 - v5;
11604
11605 // stage 2
11606 v0 = (v0 + v3 + 1) >> 1;
11607 v3 = v0 - v3;
11608 v1 = (v1 + v2 + 1) >> 1;
11609 v2 = v1 - v2;
11610 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
11611 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
11612 v7 = t;
11613 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
11614 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
11615 v6 = t;
11616
11617 // stage 1
11618 p[row] = v0 + v7;
11619 p[row + 7] = v0 - v7;
11620 p[row + 1] = v1 + v6;
11621 p[row + 6] = v1 - v6;
11622 p[row + 2] = v2 + v5;
11623 p[row + 5] = v2 - v5;
11624 p[row + 3] = v3 + v4;
11625 p[row + 4] = v3 - v4;
11626 }
11627
11628 // inverse DCT on columns
11629 for (var col = 0; col < 8; ++col) {
11630 p0 = p[col];
11631 p1 = p[col + 8];
11632 p2 = p[col + 16];
11633 p3 = p[col + 24];
11634 p4 = p[col + 32];
11635 p5 = p[col + 40];
11636 p6 = p[col + 48];
11637 p7 = p[col + 56];
11638
11639 // check for all-zero AC coefficients
11640 if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
11641 t = (dctSqrt2 * p0 + 8192) >> 14;
11642 // convert to 8 bit
11643 t = (t < -2040) ? 0 : (t >= 2024) ? 255 : (t + 2056) >> 4;
11644 blockData[blockBufferOffset + col] = t;
11645 blockData[blockBufferOffset + col + 8] = t;
11646 blockData[blockBufferOffset + col + 16] = t;
11647 blockData[blockBufferOffset + col + 24] = t;
11648 blockData[blockBufferOffset + col + 32] = t;
11649 blockData[blockBufferOffset + col + 40] = t;
11650 blockData[blockBufferOffset + col + 48] = t;
11651 blockData[blockBufferOffset + col + 56] = t;
11652 continue;
11653 }
11654
11655 // stage 4
11656 v0 = (dctSqrt2 * p0 + 2048) >> 12;
11657 v1 = (dctSqrt2 * p4 + 2048) >> 12;
11658 v2 = p2;
11659 v3 = p6;
11660 v4 = (dctSqrt1d2 * (p1 - p7) + 2048) >> 12;
11661 v7 = (dctSqrt1d2 * (p1 + p7) + 2048) >> 12;
11662 v5 = p3;
11663 v6 = p5;
11664
11665 // stage 3
11666 // Shift v0 by 128.5 << 5 here, so we don't need to shift p0...p7 when
11667 // converting to UInt8 range later.
11668 v0 = ((v0 + v1 + 1) >> 1) + 4112;
11669 v1 = v0 - v1;
11670 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
11671 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
11672 v3 = t;
11673 v4 = (v4 + v6 + 1) >> 1;
11674 v6 = v4 - v6;
11675 v7 = (v7 + v5 + 1) >> 1;
11676 v5 = v7 - v5;
11677
11678 // stage 2
11679 v0 = (v0 + v3 + 1) >> 1;
11680 v3 = v0 - v3;
11681 v1 = (v1 + v2 + 1) >> 1;
11682 v2 = v1 - v2;
11683 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
11684 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
11685 v7 = t;
11686 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
11687 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
11688 v6 = t;
11689
11690 // stage 1
11691 p0 = v0 + v7;
11692 p7 = v0 - v7;
11693 p1 = v1 + v6;
11694 p6 = v1 - v6;
11695 p2 = v2 + v5;
11696 p5 = v2 - v5;
11697 p3 = v3 + v4;
11698 p4 = v3 - v4;
11699
11700 // convert to 8-bit integers
11701 p0 = (p0 < 16) ? 0 : (p0 >= 4080) ? 255 : p0 >> 4;
11702 p1 = (p1 < 16) ? 0 : (p1 >= 4080) ? 255 : p1 >> 4;
11703 p2 = (p2 < 16) ? 0 : (p2 >= 4080) ? 255 : p2 >> 4;
11704 p3 = (p3 < 16) ? 0 : (p3 >= 4080) ? 255 : p3 >> 4;
11705 p4 = (p4 < 16) ? 0 : (p4 >= 4080) ? 255 : p4 >> 4;
11706 p5 = (p5 < 16) ? 0 : (p5 >= 4080) ? 255 : p5 >> 4;
11707 p6 = (p6 < 16) ? 0 : (p6 >= 4080) ? 255 : p6 >> 4;
11708 p7 = (p7 < 16) ? 0 : (p7 >= 4080) ? 255 : p7 >> 4;
11709
11710 // store block data
11711 blockData[blockBufferOffset + col] = p0;
11712 blockData[blockBufferOffset + col + 8] = p1;
11713 blockData[blockBufferOffset + col + 16] = p2;
11714 blockData[blockBufferOffset + col + 24] = p3;
11715 blockData[blockBufferOffset + col + 32] = p4;
11716 blockData[blockBufferOffset + col + 40] = p5;
11717 blockData[blockBufferOffset + col + 48] = p6;
11718 blockData[blockBufferOffset + col + 56] = p7;
11719 }
11720 }
11721
11722 function buildComponentData(frame, component) {
11723 var blocksPerLine = component.blocksPerLine;
11724 var blocksPerColumn = component.blocksPerColumn;
11725 var computationBuffer = new Int16Array(64);
11726
11727 for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
11728 for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
11729 var offset = getBlockBufferOffset(component, blockRow, blockCol);
11730 quantizeAndInverse(component, offset, computationBuffer);
11731 }
11732 }
11733 return component.blockData;
11734 }
11735
11736 function clamp0to255(a) {
11737 return a <= 0 ? 0 : a >= 255 ? 255 : a;
11738 }
11739
11740 JpegImage.prototype = {
11741 parse: function parse(data) {
11742
11743 function readUint16() {
11744 var value = (data[offset] << 8) | data[offset + 1];
11745 offset += 2;
11746 return value;
11747 }
11748
11749 function readDataBlock() {
11750 var length = readUint16();
11751 var array = data.subarray(offset, offset + length - 2);
11752 offset += array.length;
11753 return array;
11754 }
11755
11756 function prepareComponents(frame) {
11757 var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);
11758 var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
11759 for (var i = 0; i < frame.components.length; i++) {
11760 component = frame.components[i];
11761 var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) *
11762 component.h / frame.maxH);
11763 var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) *
11764 component.v / frame.maxV);
11765 var blocksPerLineForMcu = mcusPerLine * component.h;
11766 var blocksPerColumnForMcu = mcusPerColumn * component.v;
11767
11768 var blocksBufferSize = 64 * blocksPerColumnForMcu *
11769 (blocksPerLineForMcu + 1);
11770 component.blockData = new Int16Array(blocksBufferSize);
11771 component.blocksPerLine = blocksPerLine;
11772 component.blocksPerColumn = blocksPerColumn;
11773 }
11774 frame.mcusPerLine = mcusPerLine;
11775 frame.mcusPerColumn = mcusPerColumn;
11776 }
11777
11778 var offset = 0;
11779 var jfif = null;
11780 var adobe = null;
11781 var frame, resetInterval;
11782 var quantizationTables = [];
11783 var huffmanTablesAC = [], huffmanTablesDC = [];
11784 var fileMarker = readUint16();
11785 if (fileMarker !== 0xFFD8) { // SOI (Start of Image)
11786 error('JPEG error: SOI not found');
11787 }
11788
11789 fileMarker = readUint16();
11790 while (fileMarker !== 0xFFD9) { // EOI (End of image)
11791 var i, j, l;
11792 switch(fileMarker) {
11793 case 0xFFE0: // APP0 (Application Specific)
11794 case 0xFFE1: // APP1
11795 case 0xFFE2: // APP2
11796 case 0xFFE3: // APP3
11797 case 0xFFE4: // APP4
11798 case 0xFFE5: // APP5
11799 case 0xFFE6: // APP6
11800 case 0xFFE7: // APP7
11801 case 0xFFE8: // APP8
11802 case 0xFFE9: // APP9
11803 case 0xFFEA: // APP10
11804 case 0xFFEB: // APP11
11805 case 0xFFEC: // APP12
11806 case 0xFFED: // APP13
11807 case 0xFFEE: // APP14
11808 case 0xFFEF: // APP15
11809 case 0xFFFE: // COM (Comment)
11810 var appData = readDataBlock();
11811
11812 if (fileMarker === 0xFFE0) {
11813 if (appData[0] === 0x4A && appData[1] === 0x46 &&
11814 appData[2] === 0x49 && appData[3] === 0x46 &&
11815 appData[4] === 0) { // 'JFIF\x00'
11816 jfif = {
11817 version: { major: appData[5], minor: appData[6] },
11818 densityUnits: appData[7],
11819 xDensity: (appData[8] << 8) | appData[9],
11820 yDensity: (appData[10] << 8) | appData[11],
11821 thumbWidth: appData[12],
11822 thumbHeight: appData[13],
11823 thumbData: appData.subarray(14, 14 +
11824 3 * appData[12] * appData[13])
11825 };
11826 }
11827 }
11828 // TODO APP1 - Exif
11829 if (fileMarker === 0xFFEE) {
11830 if (appData[0] === 0x41 && appData[1] === 0x64 &&
11831 appData[2] === 0x6F && appData[3] === 0x62 &&
11832 appData[4] === 0x65) { // 'Adobe'
11833 adobe = {
11834 version: (appData[5] << 8) | appData[6],
11835 flags0: (appData[7] << 8) | appData[8],
11836 flags1: (appData[9] << 8) | appData[10],
11837 transformCode: appData[11]
11838 };
11839 }
11840 }
11841 break;
11842
11843 case 0xFFDB: // DQT (Define Quantization Tables)
11844 var quantizationTablesLength = readUint16();
11845 var quantizationTablesEnd = quantizationTablesLength + offset - 2;
11846 var z;
11847 while (offset < quantizationTablesEnd) {
11848 var quantizationTableSpec = data[offset++];
11849 var tableData = new Uint16Array(64);
11850 if ((quantizationTableSpec >> 4) === 0) { // 8 bit values
11851 for (j = 0; j < 64; j++) {
11852 z = dctZigZag[j];
11853 tableData[z] = data[offset++];
11854 }
11855 } else if ((quantizationTableSpec >> 4) === 1) { //16 bit
11856 for (j = 0; j < 64; j++) {
11857 z = dctZigZag[j];
11858 tableData[z] = readUint16();
11859 }
11860 } else {
11861 error('JPEG error: DQT - invalid table spec');
11862 }
11863 quantizationTables[quantizationTableSpec & 15] = tableData;
11864 }
11865 break;
11866
11867 case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT)
11868 case 0xFFC1: // SOF1 (Start of Frame, Extended DCT)
11869 case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT)
11870 if (frame) {
11871 error('JPEG error: Only single frame JPEGs supported');
11872 }
11873 readUint16(); // skip data length
11874 frame = {};
11875 frame.extended = (fileMarker === 0xFFC1);
11876 frame.progressive = (fileMarker === 0xFFC2);
11877 frame.precision = data[offset++];
11878 frame.scanLines = readUint16();
11879 frame.samplesPerLine = readUint16();
11880 frame.components = [];
11881 frame.componentIds = {};
11882 var componentsCount = data[offset++], componentId;
11883 var maxH = 0, maxV = 0;
11884 for (i = 0; i < componentsCount; i++) {
11885 componentId = data[offset];
11886 var h = data[offset + 1] >> 4;
11887 var v = data[offset + 1] & 15;
11888 if (maxH < h) {
11889 maxH = h;
11890 }
11891 if (maxV < v) {
11892 maxV = v;
11893 }
11894 var qId = data[offset + 2];
11895 l = frame.components.push({
11896 h: h,
11897 v: v,
11898 quantizationId: qId,
11899 quantizationTable: null, // See comment below.
11900 });
11901 frame.componentIds[componentId] = l - 1;
11902 offset += 3;
11903 }
11904 frame.maxH = maxH;
11905 frame.maxV = maxV;
11906 prepareComponents(frame);
11907 break;
11908
11909 case 0xFFC4: // DHT (Define Huffman Tables)
11910 var huffmanLength = readUint16();
11911 for (i = 2; i < huffmanLength;) {
11912 var huffmanTableSpec = data[offset++];
11913 var codeLengths = new Uint8Array(16);
11914 var codeLengthSum = 0;
11915 for (j = 0; j < 16; j++, offset++) {
11916 codeLengthSum += (codeLengths[j] = data[offset]);
11917 }
11918 var huffmanValues = new Uint8Array(codeLengthSum);
11919 for (j = 0; j < codeLengthSum; j++, offset++) {
11920 huffmanValues[j] = data[offset];
11921 }
11922 i += 17 + codeLengthSum;
11923
11924 ((huffmanTableSpec >> 4) === 0 ?
11925 huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] =
11926 buildHuffmanTable(codeLengths, huffmanValues);
11927 }
11928 break;
11929
11930 case 0xFFDD: // DRI (Define Restart Interval)
11931 readUint16(); // skip data length
11932 resetInterval = readUint16();
11933 break;
11934
11935 case 0xFFDA: // SOS (Start of Scan)
11936 var scanLength = readUint16();
11937 var selectorsCount = data[offset++];
11938 var components = [], component;
11939 for (i = 0; i < selectorsCount; i++) {
11940 var componentIndex = frame.componentIds[data[offset++]];
11941 component = frame.components[componentIndex];
11942 var tableSpec = data[offset++];
11943 component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
11944 component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
11945 components.push(component);
11946 }
11947 var spectralStart = data[offset++];
11948 var spectralEnd = data[offset++];
11949 var successiveApproximation = data[offset++];
11950 var processed = decodeScan(data, offset,
11951 frame, components, resetInterval,
11952 spectralStart, spectralEnd,
11953 successiveApproximation >> 4, successiveApproximation & 15);
11954 offset += processed;
11955 break;
11956
11957 case 0xFFFF: // Fill bytes
11958 if (data[offset] !== 0xFF) { // Avoid skipping a valid marker.
11959 offset--;
11960 }
11961 break;
11962
11963 default:
11964 if (data[offset - 3] === 0xFF &&
11965 data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
11966 // could be incorrect encoding -- last 0xFF byte of the previous
11967 // block was eaten by the encoder
11968 offset -= 3;
11969 break;
11970 }
11971 error('JPEG error: unknown marker ' + fileMarker.toString(16));
11972 }
11973 fileMarker = readUint16();
11974 }
11975
11976 this.width = frame.samplesPerLine;
11977 this.height = frame.scanLines;
11978 this.jfif = jfif;
11979 this.adobe = adobe;
11980 this.components = [];
11981 for (i = 0; i < frame.components.length; i++) {
11982 component = frame.components[i];
11983
11984 // Prevent errors when DQT markers are placed after SOF{n} markers,
11985 // by assigning the `quantizationTable` entry after the entire image
11986 // has been parsed (fixes issue7406.pdf).
11987 var quantizationTable = quantizationTables[component.quantizationId];
11988 if (quantizationTable) {
11989 component.quantizationTable = quantizationTable;
11990 }
11991
11992 this.components.push({
11993 output: buildComponentData(frame, component),
11994 scaleX: component.h / frame.maxH,
11995 scaleY: component.v / frame.maxV,
11996 blocksPerLine: component.blocksPerLine,
11997 blocksPerColumn: component.blocksPerColumn
11998 });
11999 }
12000 this.numComponents = this.components.length;
12001 },
12002
12003 _getLinearizedBlockData: function getLinearizedBlockData(width, height) {
12004 var scaleX = this.width / width, scaleY = this.height / height;
12005
12006 var component, componentScaleX, componentScaleY, blocksPerScanline;
12007 var x, y, i, j, k;
12008 var index;
12009 var offset = 0;
12010 var output;
12011 var numComponents = this.components.length;
12012 var dataLength = width * height * numComponents;
12013 var data = new Uint8Array(dataLength);
12014 var xScaleBlockOffset = new Uint32Array(width);
12015 var mask3LSB = 0xfffffff8; // used to clear the 3 LSBs
12016
12017 for (i = 0; i < numComponents; i++) {
12018 component = this.components[i];
12019 componentScaleX = component.scaleX * scaleX;
12020 componentScaleY = component.scaleY * scaleY;
12021 offset = i;
12022 output = component.output;
12023 blocksPerScanline = (component.blocksPerLine + 1) << 3;
12024 // precalculate the xScaleBlockOffset
12025 for (x = 0; x < width; x++) {
12026 j = 0 | (x * componentScaleX);
12027 xScaleBlockOffset[x] = ((j & mask3LSB) << 3) | (j & 7);
12028 }
12029 // linearize the blocks of the component
12030 for (y = 0; y < height; y++) {
12031 j = 0 | (y * componentScaleY);
12032 index = blocksPerScanline * (j & mask3LSB) | ((j & 7) << 3);
12033 for (x = 0; x < width; x++) {
12034 data[offset] = output[index + xScaleBlockOffset[x]];
12035 offset += numComponents;
12036 }
12037 }
12038 }
12039
12040 // decodeTransform contains pairs of multiplier (-256..256) and additive
12041 var transform = this.decodeTransform;
12042 if (transform) {
12043 for (i = 0; i < dataLength;) {
12044 for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) {
12045 data[i] = ((data[i] * transform[k]) >> 8) + transform[k + 1];
12046 }
12047 }
12048 }
12049 return data;
12050 },
12051
12052 _isColorConversionNeeded: function isColorConversionNeeded() {
12053 if (this.adobe && this.adobe.transformCode) {
12054 // The adobe transform marker overrides any previous setting
12055 return true;
12056 } else if (this.numComponents === 3) {
12057 if (!this.adobe && this.colorTransform === 0) {
12058 // If the Adobe transform marker is not present and the image
12059 // dictionary has a 'ColorTransform' entry, explicitly set to `0`,
12060 // then the colours should *not* be transformed.
12061 return false;
12062 }
12063 return true;
12064 } else { // `this.numComponents !== 3`
12065 if (!this.adobe && this.colorTransform === 1) {
12066 // If the Adobe transform marker is not present and the image
12067 // dictionary has a 'ColorTransform' entry, explicitly set to `1`,
12068 // then the colours should be transformed.
12069 return true;
12070 }
12071 return false;
12072 }
12073 },
12074
12075 _convertYccToRgb: function convertYccToRgb(data) {
12076 var Y, Cb, Cr;
12077 for (var i = 0, length = data.length; i < length; i += 3) {
12078 Y = data[i ];
12079 Cb = data[i + 1];
12080 Cr = data[i + 2];
12081 data[i ] = clamp0to255(Y - 179.456 + 1.402 * Cr);
12082 data[i + 1] = clamp0to255(Y + 135.459 - 0.344 * Cb - 0.714 * Cr);
12083 data[i + 2] = clamp0to255(Y - 226.816 + 1.772 * Cb);
12084 }
12085 return data;
12086 },
12087
12088 _convertYcckToRgb: function convertYcckToRgb(data) {
12089 var Y, Cb, Cr, k;
12090 var offset = 0;
12091 for (var i = 0, length = data.length; i < length; i += 4) {
12092 Y = data[i];
12093 Cb = data[i + 1];
12094 Cr = data[i + 2];
12095 k = data[i + 3];
12096
12097 var r = -122.67195406894 +
12098 Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr -
12099 5.4080610064599e-5 * Y + 0.00048449797120281 * k -
12100 0.154362151871126) +
12101 Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y -
12102 0.00477271405408747 * k + 1.53380253221734) +
12103 Y * (0.000961250184130688 * Y - 0.00266257332283933 * k +
12104 0.48357088451265) +
12105 k * (-0.000336197177618394 * k + 0.484791561490776);
12106
12107 var g = 107.268039397724 +
12108 Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr +
12109 0.000659397001245577 * Y + 0.000426105652938837 * k -
12110 0.176491792462875) +
12111 Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y +
12112 0.000770482631801132 * k - 0.151051492775562) +
12113 Y * (0.00126935368114843 * Y - 0.00265090189010898 * k +
12114 0.25802910206845) +
12115 k * (-0.000318913117588328 * k - 0.213742400323665);
12116
12117 var b = -20.810012546947 +
12118 Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr +
12119 0.0020741088115012 * Y - 0.00288260236853442 * k +
12120 0.814272968359295) +
12121 Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y +
12122 0.000560833691242812 * k - 0.195152027534049) +
12123 Y * (0.00174418132927582 * Y - 0.00255243321439347 * k +
12124 0.116935020465145) +
12125 k * (-0.000343531996510555 * k + 0.24165260232407);
12126
12127 data[offset++] = clamp0to255(r);
12128 data[offset++] = clamp0to255(g);
12129 data[offset++] = clamp0to255(b);
12130 }
12131 return data;
12132 },
12133
12134 _convertYcckToCmyk: function convertYcckToCmyk(data) {
12135 var Y, Cb, Cr;
12136 for (var i = 0, length = data.length; i < length; i += 4) {
12137 Y = data[i];
12138 Cb = data[i + 1];
12139 Cr = data[i + 2];
12140 data[i ] = clamp0to255(434.456 - Y - 1.402 * Cr);
12141 data[i + 1] = clamp0to255(119.541 - Y + 0.344 * Cb + 0.714 * Cr);
12142 data[i + 2] = clamp0to255(481.816 - Y - 1.772 * Cb);
12143 // K in data[i + 3] is unchanged
12144 }
12145 return data;
12146 },
12147
12148 _convertCmykToRgb: function convertCmykToRgb(data) {
12149 var c, m, y, k;
12150 var offset = 0;
12151 var min = -255 * 255 * 255;
12152 var scale = 1 / 255 / 255;
12153 for (var i = 0, length = data.length; i < length; i += 4) {
12154 c = data[i];
12155 m = data[i + 1];
12156 y = data[i + 2];
12157 k = data[i + 3];
12158
12159 var r =
12160 c * (-4.387332384609988 * c + 54.48615194189176 * m +
12161 18.82290502165302 * y + 212.25662451639585 * k -
12162 72734.4411664936) +
12163 m * (1.7149763477362134 * m - 5.6096736904047315 * y -
12164 17.873870861415444 * k - 1401.7366389350734) +
12165 y * (-2.5217340131683033 * y - 21.248923337353073 * k +
12166 4465.541406466231) -
12167 k * (21.86122147463605 * k + 48317.86113160301);
12168 var g =
12169 c * (8.841041422036149 * c + 60.118027045597366 * m +
12170 6.871425592049007 * y + 31.159100130055922 * k -
12171 20220.756542821975) +
12172 m * (-15.310361306967817 * m + 17.575251261109482 * y +
12173 131.35250912493976 * k - 48691.05921601825) +
12174 y * (4.444339102852739 * y + 9.8632861493405 * k -
12175 6341.191035517494) -
12176 k * (20.737325471181034 * k + 47890.15695978492);
12177 var b =
12178 c * (0.8842522430003296 * c + 8.078677503112928 * m +
12179 30.89978309703729 * y - 0.23883238689178934 * k -
12180 3616.812083916688) +
12181 m * (10.49593273432072 * m + 63.02378494754052 * y +
12182 50.606957656360734 * k - 28620.90484698408) +
12183 y * (0.03296041114873217 * y + 115.60384449646641 * k -
12184 49363.43385999684) -
12185 k * (22.33816807309886 * k + 45932.16563550634);
12186
12187 data[offset++] = r >= 0 ? 255 : r <= min ? 0 : 255 + r * scale | 0;
12188 data[offset++] = g >= 0 ? 255 : g <= min ? 0 : 255 + g * scale | 0;
12189 data[offset++] = b >= 0 ? 255 : b <= min ? 0 : 255 + b * scale | 0;
12190 }
12191 return data;
12192 },
12193
12194 getData: function getData(width, height, forceRGBoutput) {
12195 if (this.numComponents > 4) {
12196 error('JPEG error: Unsupported color mode');
12197 }
12198 // type of data: Uint8Array(width * height * numComponents)
12199 var data = this._getLinearizedBlockData(width, height);
12200
12201 if (this.numComponents === 1 && forceRGBoutput) {
12202 var dataLength = data.length;
12203 var rgbData = new Uint8Array(dataLength * 3);
12204 var offset = 0;
12205 for (var i = 0; i < dataLength; i++) {
12206 var grayColor = data[i];
12207 rgbData[offset++] = grayColor;
12208 rgbData[offset++] = grayColor;
12209 rgbData[offset++] = grayColor;
12210 }
12211 return rgbData;
12212 } else if (this.numComponents === 3 && this._isColorConversionNeeded()) {
12213 return this._convertYccToRgb(data);
12214 } else if (this.numComponents === 4) {
12215 if (this._isColorConversionNeeded()) {
12216 if (forceRGBoutput) {
12217 return this._convertYcckToRgb(data);
12218 } else {
12219 return this._convertYcckToCmyk(data);
12220 }
12221 } else if (forceRGBoutput) {
12222 return this._convertCmykToRgb(data);
12223 }
12224 }
12225 return data;
12226 }
12227 };
12228
12229 return JpegImage;
12230})();
12231
12232exports.JpegImage = JpegImage;
12233}));
12234
12235
12236(function (root, factory) {
12237 {
12238 factory((root.pdfjsCoreJpx = {}), root.pdfjsSharedUtil,
12239 root.pdfjsCoreArithmeticDecoder);
12240 }
12241}(this, function (exports, sharedUtil, coreArithmeticDecoder) {
12242
12243var info = sharedUtil.info;
12244var warn = sharedUtil.warn;
12245var error = sharedUtil.error;
12246var log2 = sharedUtil.log2;
12247var readUint16 = sharedUtil.readUint16;
12248var readUint32 = sharedUtil.readUint32;
12249var ArithmeticDecoder = coreArithmeticDecoder.ArithmeticDecoder;
12250
12251var JpxImage = (function JpxImageClosure() {
12252 // Table E.1
12253 var SubbandsGainLog2 = {
12254 'LL': 0,
12255 'LH': 1,
12256 'HL': 1,
12257 'HH': 2
12258 };
12259 function JpxImage() {
12260 this.failOnCorruptedImage = false;
12261 }
12262 JpxImage.prototype = {
12263 parse: function JpxImage_parse(data) {
12264
12265 var head = readUint16(data, 0);
12266 // No box header, immediate start of codestream (SOC)
12267 if (head === 0xFF4F) {
12268 this.parseCodestream(data, 0, data.length);
12269 return;
12270 }
12271
12272 var position = 0, length = data.length;
12273 while (position < length) {
12274 var headerSize = 8;
12275 var lbox = readUint32(data, position);
12276 var tbox = readUint32(data, position + 4);
12277 position += headerSize;
12278 if (lbox === 1) {
12279 // XLBox: read UInt64 according to spec.
12280 // JavaScript's int precision of 53 bit should be sufficient here.
12281 lbox = readUint32(data, position) * 4294967296 +
12282 readUint32(data, position + 4);
12283 position += 8;
12284 headerSize += 8;
12285 }
12286 if (lbox === 0) {
12287 lbox = length - position + headerSize;
12288 }
12289 if (lbox < headerSize) {
12290 error('JPX Error: Invalid box field size');
12291 }
12292 var dataLength = lbox - headerSize;
12293 var jumpDataLength = true;
12294 switch (tbox) {
12295 case 0x6A703268: // 'jp2h'
12296 jumpDataLength = false; // parsing child boxes
12297 break;
12298 case 0x636F6C72: // 'colr'
12299 // Colorspaces are not used, the CS from the PDF is used.
12300 var method = data[position];
12301 if (method === 1) {
12302 // enumerated colorspace
12303 var colorspace = readUint32(data, position + 3);
12304 switch (colorspace) {
12305 case 16: // this indicates a sRGB colorspace
12306 case 17: // this indicates a grayscale colorspace
12307 case 18: // this indicates a YUV colorspace
12308 break;
12309 default:
12310 warn('Unknown colorspace ' + colorspace);
12311 break;
12312 }
12313 } else if (method === 2) {
12314 info('ICC profile not supported');
12315 }
12316 break;
12317 case 0x6A703263: // 'jp2c'
12318 this.parseCodestream(data, position, position + dataLength);
12319 break;
12320 case 0x6A502020: // 'jP\024\024'
12321 if (0x0d0a870a !== readUint32(data, position)) {
12322 warn('Invalid JP2 signature');
12323 }
12324 break;
12325 // The following header types are valid but currently not used:
12326 case 0x6A501A1A: // 'jP\032\032'
12327 case 0x66747970: // 'ftyp'
12328 case 0x72726571: // 'rreq'
12329 case 0x72657320: // 'res '
12330 case 0x69686472: // 'ihdr'
12331 break;
12332 default:
12333 var headerType = String.fromCharCode((tbox >> 24) & 0xFF,
12334 (tbox >> 16) & 0xFF,
12335 (tbox >> 8) & 0xFF,
12336 tbox & 0xFF);
12337 warn('Unsupported header type ' + tbox + ' (' + headerType + ')');
12338 break;
12339 }
12340 if (jumpDataLength) {
12341 position += dataLength;
12342 }
12343 }
12344 },
12345 parseImageProperties: function JpxImage_parseImageProperties(stream) {
12346 var newByte = stream.getByte();
12347 while (newByte >= 0) {
12348 var oldByte = newByte;
12349 newByte = stream.getByte();
12350 var code = (oldByte << 8) | newByte;
12351 // Image and tile size (SIZ)
12352 if (code === 0xFF51) {
12353 stream.skip(4);
12354 var Xsiz = stream.getInt32() >>> 0; // Byte 4
12355 var Ysiz = stream.getInt32() >>> 0; // Byte 8
12356 var XOsiz = stream.getInt32() >>> 0; // Byte 12
12357 var YOsiz = stream.getInt32() >>> 0; // Byte 16
12358 stream.skip(16);
12359 var Csiz = stream.getUint16(); // Byte 36
12360 this.width = Xsiz - XOsiz;
12361 this.height = Ysiz - YOsiz;
12362 this.componentsCount = Csiz;
12363 // Results are always returned as Uint8Arrays
12364 this.bitsPerComponent = 8;
12365 return;
12366 }
12367 }
12368 error('JPX Error: No size marker found in JPX stream');
12369 },
12370 parseCodestream: function JpxImage_parseCodestream(data, start, end) {
12371 var context = {};
12372 var doNotRecover = false;
12373 try {
12374 var position = start;
12375 while (position + 1 < end) {
12376 var code = readUint16(data, position);
12377 position += 2;
12378
12379 var length = 0, j, sqcd, spqcds, spqcdSize, scalarExpounded, tile;
12380 switch (code) {
12381 case 0xFF4F: // Start of codestream (SOC)
12382 context.mainHeader = true;
12383 break;
12384 case 0xFFD9: // End of codestream (EOC)
12385 break;
12386 case 0xFF51: // Image and tile size (SIZ)
12387 length = readUint16(data, position);
12388 var siz = {};
12389 siz.Xsiz = readUint32(data, position + 4);
12390 siz.Ysiz = readUint32(data, position + 8);
12391 siz.XOsiz = readUint32(data, position + 12);
12392 siz.YOsiz = readUint32(data, position + 16);
12393 siz.XTsiz = readUint32(data, position + 20);
12394 siz.YTsiz = readUint32(data, position + 24);
12395 siz.XTOsiz = readUint32(data, position + 28);
12396 siz.YTOsiz = readUint32(data, position + 32);
12397 var componentsCount = readUint16(data, position + 36);
12398 siz.Csiz = componentsCount;
12399 var components = [];
12400 j = position + 38;
12401 for (var i = 0; i < componentsCount; i++) {
12402 var component = {
12403 precision: (data[j] & 0x7F) + 1,
12404 isSigned: !!(data[j] & 0x80),
12405 XRsiz: data[j + 1],
12406 YRsiz: data[j + 1]
12407 };
12408 calculateComponentDimensions(component, siz);
12409 components.push(component);
12410 }
12411 context.SIZ = siz;
12412 context.components = components;
12413 calculateTileGrids(context, components);
12414 context.QCC = [];
12415 context.COC = [];
12416 break;
12417 case 0xFF5C: // Quantization default (QCD)
12418 length = readUint16(data, position);
12419 var qcd = {};
12420 j = position + 2;
12421 sqcd = data[j++];
12422 switch (sqcd & 0x1F) {
12423 case 0:
12424 spqcdSize = 8;
12425 scalarExpounded = true;
12426 break;
12427 case 1:
12428 spqcdSize = 16;
12429 scalarExpounded = false;
12430 break;
12431 case 2:
12432 spqcdSize = 16;
12433 scalarExpounded = true;
12434 break;
12435 default:
12436 throw new Error('Invalid SQcd value ' + sqcd);
12437 }
12438 qcd.noQuantization = (spqcdSize === 8);
12439 qcd.scalarExpounded = scalarExpounded;
12440 qcd.guardBits = sqcd >> 5;
12441 spqcds = [];
12442 while (j < length + position) {
12443 var spqcd = {};
12444 if (spqcdSize === 8) {
12445 spqcd.epsilon = data[j++] >> 3;
12446 spqcd.mu = 0;
12447 } else {
12448 spqcd.epsilon = data[j] >> 3;
12449 spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
12450 j += 2;
12451 }
12452 spqcds.push(spqcd);
12453 }
12454 qcd.SPqcds = spqcds;
12455 if (context.mainHeader) {
12456 context.QCD = qcd;
12457 } else {
12458 context.currentTile.QCD = qcd;
12459 context.currentTile.QCC = [];
12460 }
12461 break;
12462 case 0xFF5D: // Quantization component (QCC)
12463 length = readUint16(data, position);
12464 var qcc = {};
12465 j = position + 2;
12466 var cqcc;
12467 if (context.SIZ.Csiz < 257) {
12468 cqcc = data[j++];
12469 } else {
12470 cqcc = readUint16(data, j);
12471 j += 2;
12472 }
12473 sqcd = data[j++];
12474 switch (sqcd & 0x1F) {
12475 case 0:
12476 spqcdSize = 8;
12477 scalarExpounded = true;
12478 break;
12479 case 1:
12480 spqcdSize = 16;
12481 scalarExpounded = false;
12482 break;
12483 case 2:
12484 spqcdSize = 16;
12485 scalarExpounded = true;
12486 break;
12487 default:
12488 throw new Error('Invalid SQcd value ' + sqcd);
12489 }
12490 qcc.noQuantization = (spqcdSize === 8);
12491 qcc.scalarExpounded = scalarExpounded;
12492 qcc.guardBits = sqcd >> 5;
12493 spqcds = [];
12494 while (j < (length + position)) {
12495 spqcd = {};
12496 if (spqcdSize === 8) {
12497 spqcd.epsilon = data[j++] >> 3;
12498 spqcd.mu = 0;
12499 } else {
12500 spqcd.epsilon = data[j] >> 3;
12501 spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
12502 j += 2;
12503 }
12504 spqcds.push(spqcd);
12505 }
12506 qcc.SPqcds = spqcds;
12507 if (context.mainHeader) {
12508 context.QCC[cqcc] = qcc;
12509 } else {
12510 context.currentTile.QCC[cqcc] = qcc;
12511 }
12512 break;
12513 case 0xFF52: // Coding style default (COD)
12514 length = readUint16(data, position);
12515 var cod = {};
12516 j = position + 2;
12517 var scod = data[j++];
12518 cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
12519 cod.sopMarkerUsed = !!(scod & 2);
12520 cod.ephMarkerUsed = !!(scod & 4);
12521 cod.progressionOrder = data[j++];
12522 cod.layersCount = readUint16(data, j);
12523 j += 2;
12524 cod.multipleComponentTransform = data[j++];
12525
12526 cod.decompositionLevelsCount = data[j++];
12527 cod.xcb = (data[j++] & 0xF) + 2;
12528 cod.ycb = (data[j++] & 0xF) + 2;
12529 var blockStyle = data[j++];
12530 cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
12531 cod.resetContextProbabilities = !!(blockStyle & 2);
12532 cod.terminationOnEachCodingPass = !!(blockStyle & 4);
12533 cod.verticalyStripe = !!(blockStyle & 8);
12534 cod.predictableTermination = !!(blockStyle & 16);
12535 cod.segmentationSymbolUsed = !!(blockStyle & 32);
12536 cod.reversibleTransformation = data[j++];
12537 if (cod.entropyCoderWithCustomPrecincts) {
12538 var precinctsSizes = [];
12539 while (j < length + position) {
12540 var precinctsSize = data[j++];
12541 precinctsSizes.push({
12542 PPx: precinctsSize & 0xF,
12543 PPy: precinctsSize >> 4
12544 });
12545 }
12546 cod.precinctsSizes = precinctsSizes;
12547 }
12548 var unsupported = [];
12549 if (cod.selectiveArithmeticCodingBypass) {
12550 unsupported.push('selectiveArithmeticCodingBypass');
12551 }
12552 if (cod.resetContextProbabilities) {
12553 unsupported.push('resetContextProbabilities');
12554 }
12555 if (cod.terminationOnEachCodingPass) {
12556 unsupported.push('terminationOnEachCodingPass');
12557 }
12558 if (cod.verticalyStripe) {
12559 unsupported.push('verticalyStripe');
12560 }
12561 if (cod.predictableTermination) {
12562 unsupported.push('predictableTermination');
12563 }
12564 if (unsupported.length > 0) {
12565 doNotRecover = true;
12566 throw new Error('Unsupported COD options (' +
12567 unsupported.join(', ') + ')');
12568 }
12569 if (context.mainHeader) {
12570 context.COD = cod;
12571 } else {
12572 context.currentTile.COD = cod;
12573 context.currentTile.COC = [];
12574 }
12575 break;
12576 case 0xFF90: // Start of tile-part (SOT)
12577 length = readUint16(data, position);
12578 tile = {};
12579 tile.index = readUint16(data, position + 2);
12580 tile.length = readUint32(data, position + 4);
12581 tile.dataEnd = tile.length + position - 2;
12582 tile.partIndex = data[position + 8];
12583 tile.partsCount = data[position + 9];
12584
12585 context.mainHeader = false;
12586 if (tile.partIndex === 0) {
12587 // reset component specific settings
12588 tile.COD = context.COD;
12589 tile.COC = context.COC.slice(0); // clone of the global COC
12590 tile.QCD = context.QCD;
12591 tile.QCC = context.QCC.slice(0); // clone of the global COC
12592 }
12593 context.currentTile = tile;
12594 break;
12595 case 0xFF93: // Start of data (SOD)
12596 tile = context.currentTile;
12597 if (tile.partIndex === 0) {
12598 initializeTile(context, tile.index);
12599 buildPackets(context);
12600 }
12601
12602 // moving to the end of the data
12603 length = tile.dataEnd - position;
12604 parseTilePackets(context, data, position, length);
12605 break;
12606 case 0xFF55: // Tile-part lengths, main header (TLM)
12607 case 0xFF57: // Packet length, main header (PLM)
12608 case 0xFF58: // Packet length, tile-part header (PLT)
12609 case 0xFF64: // Comment (COM)
12610 length = readUint16(data, position);
12611 // skipping content
12612 break;
12613 case 0xFF53: // Coding style component (COC)
12614 throw new Error('Codestream code 0xFF53 (COC) is ' +
12615 'not implemented');
12616 default:
12617 throw new Error('Unknown codestream code: ' + code.toString(16));
12618 }
12619 position += length;
12620 }
12621 } catch (e) {
12622 if (doNotRecover || this.failOnCorruptedImage) {
12623 error('JPX Error: ' + e.message);
12624 } else {
12625 warn('JPX: Trying to recover from: ' + e.message);
12626 }
12627 }
12628 this.tiles = transformComponents(context);
12629 this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
12630 this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
12631 this.componentsCount = context.SIZ.Csiz;
12632 }
12633 };
12634 function calculateComponentDimensions(component, siz) {
12635 // Section B.2 Component mapping
12636 component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
12637 component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
12638 component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
12639 component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
12640 component.width = component.x1 - component.x0;
12641 component.height = component.y1 - component.y0;
12642 }
12643 function calculateTileGrids(context, components) {
12644 var siz = context.SIZ;
12645 // Section B.3 Division into tile and tile-components
12646 var tile, tiles = [];
12647 var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
12648 var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
12649 for (var q = 0; q < numYtiles; q++) {
12650 for (var p = 0; p < numXtiles; p++) {
12651 tile = {};
12652 tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
12653 tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
12654 tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
12655 tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
12656 tile.width = tile.tx1 - tile.tx0;
12657 tile.height = tile.ty1 - tile.ty0;
12658 tile.components = [];
12659 tiles.push(tile);
12660 }
12661 }
12662 context.tiles = tiles;
12663
12664 var componentsCount = siz.Csiz;
12665 for (var i = 0, ii = componentsCount; i < ii; i++) {
12666 var component = components[i];
12667 for (var j = 0, jj = tiles.length; j < jj; j++) {
12668 var tileComponent = {};
12669 tile = tiles[j];
12670 tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
12671 tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
12672 tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
12673 tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
12674 tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
12675 tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
12676 tile.components[i] = tileComponent;
12677 }
12678 }
12679 }
12680 function getBlocksDimensions(context, component, r) {
12681 var codOrCoc = component.codingStyleParameters;
12682 var result = {};
12683 if (!codOrCoc.entropyCoderWithCustomPrecincts) {
12684 result.PPx = 15;
12685 result.PPy = 15;
12686 } else {
12687 result.PPx = codOrCoc.precinctsSizes[r].PPx;
12688 result.PPy = codOrCoc.precinctsSizes[r].PPy;
12689 }
12690 // calculate codeblock size as described in section B.7
12691 result.xcb_ = (r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) :
12692 Math.min(codOrCoc.xcb, result.PPx));
12693 result.ycb_ = (r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) :
12694 Math.min(codOrCoc.ycb, result.PPy));
12695 return result;
12696 }
12697 function buildPrecincts(context, resolution, dimensions) {
12698 // Section B.6 Division resolution to precincts
12699 var precinctWidth = 1 << dimensions.PPx;
12700 var precinctHeight = 1 << dimensions.PPy;
12701 // Jasper introduces codeblock groups for mapping each subband codeblocks
12702 // to precincts. Precinct partition divides a resolution according to width
12703 // and height parameters. The subband that belongs to the resolution level
12704 // has a different size than the level, unless it is the zero resolution.
12705
12706 // From Jasper documentation: jpeg2000.pdf, section K: Tier-2 coding:
12707 // The precinct partitioning for a particular subband is derived from a
12708 // partitioning of its parent LL band (i.e., the LL band at the next higher
12709 // resolution level)... The LL band associated with each resolution level is
12710 // divided into precincts... Each of the resulting precinct regions is then
12711 // mapped into its child subbands (if any) at the next lower resolution
12712 // level. This is accomplished by using the coordinate transformation
12713 // (u, v) = (ceil(x/2), ceil(y/2)) where (x, y) and (u, v) are the
12714 // coordinates of a point in the LL band and child subband, respectively.
12715 var isZeroRes = resolution.resLevel === 0;
12716 var precinctWidthInSubband = 1 << (dimensions.PPx + (isZeroRes ? 0 : -1));
12717 var precinctHeightInSubband = 1 << (dimensions.PPy + (isZeroRes ? 0 : -1));
12718 var numprecinctswide = (resolution.trx1 > resolution.trx0 ?
12719 Math.ceil(resolution.trx1 / precinctWidth) -
12720 Math.floor(resolution.trx0 / precinctWidth) : 0);
12721 var numprecinctshigh = (resolution.try1 > resolution.try0 ?
12722 Math.ceil(resolution.try1 / precinctHeight) -
12723 Math.floor(resolution.try0 / precinctHeight) : 0);
12724 var numprecincts = numprecinctswide * numprecinctshigh;
12725
12726 resolution.precinctParameters = {
12727 precinctWidth: precinctWidth,
12728 precinctHeight: precinctHeight,
12729 numprecinctswide: numprecinctswide,
12730 numprecinctshigh: numprecinctshigh,
12731 numprecincts: numprecincts,
12732 precinctWidthInSubband: precinctWidthInSubband,
12733 precinctHeightInSubband: precinctHeightInSubband
12734 };
12735 }
12736 function buildCodeblocks(context, subband, dimensions) {
12737 // Section B.7 Division sub-band into code-blocks
12738 var xcb_ = dimensions.xcb_;
12739 var ycb_ = dimensions.ycb_;
12740 var codeblockWidth = 1 << xcb_;
12741 var codeblockHeight = 1 << ycb_;
12742 var cbx0 = subband.tbx0 >> xcb_;
12743 var cby0 = subband.tby0 >> ycb_;
12744 var cbx1 = (subband.tbx1 + codeblockWidth - 1) >> xcb_;
12745 var cby1 = (subband.tby1 + codeblockHeight - 1) >> ycb_;
12746 var precinctParameters = subband.resolution.precinctParameters;
12747 var codeblocks = [];
12748 var precincts = [];
12749 var i, j, codeblock, precinctNumber;
12750 for (j = cby0; j < cby1; j++) {
12751 for (i = cbx0; i < cbx1; i++) {
12752 codeblock = {
12753 cbx: i,
12754 cby: j,
12755 tbx0: codeblockWidth * i,
12756 tby0: codeblockHeight * j,
12757 tbx1: codeblockWidth * (i + 1),
12758 tby1: codeblockHeight * (j + 1)
12759 };
12760
12761 codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
12762 codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
12763 codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
12764 codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
12765
12766 // Calculate precinct number for this codeblock, codeblock position
12767 // should be relative to its subband, use actual dimension and position
12768 // See comment about codeblock group width and height
12769 var pi = Math.floor((codeblock.tbx0_ - subband.tbx0) /
12770 precinctParameters.precinctWidthInSubband);
12771 var pj = Math.floor((codeblock.tby0_ - subband.tby0) /
12772 precinctParameters.precinctHeightInSubband);
12773 precinctNumber = pi + (pj * precinctParameters.numprecinctswide);
12774
12775 codeblock.precinctNumber = precinctNumber;
12776 codeblock.subbandType = subband.type;
12777 codeblock.Lblock = 3;
12778
12779 if (codeblock.tbx1_ <= codeblock.tbx0_ ||
12780 codeblock.tby1_ <= codeblock.tby0_) {
12781 continue;
12782 }
12783 codeblocks.push(codeblock);
12784 // building precinct for the sub-band
12785 var precinct = precincts[precinctNumber];
12786 if (precinct !== undefined) {
12787 if (i < precinct.cbxMin) {
12788 precinct.cbxMin = i;
12789 } else if (i > precinct.cbxMax) {
12790 precinct.cbxMax = i;
12791 }
12792 if (j < precinct.cbyMin) {
12793 precinct.cbxMin = j;
12794 } else if (j > precinct.cbyMax) {
12795 precinct.cbyMax = j;
12796 }
12797 } else {
12798 precincts[precinctNumber] = precinct = {
12799 cbxMin: i,
12800 cbyMin: j,
12801 cbxMax: i,
12802 cbyMax: j
12803 };
12804 }
12805 codeblock.precinct = precinct;
12806 }
12807 }
12808 subband.codeblockParameters = {
12809 codeblockWidth: xcb_,
12810 codeblockHeight: ycb_,
12811 numcodeblockwide: cbx1 - cbx0 + 1,
12812 numcodeblockhigh: cby1 - cby0 + 1
12813 };
12814 subband.codeblocks = codeblocks;
12815 subband.precincts = precincts;
12816 }
12817 function createPacket(resolution, precinctNumber, layerNumber) {
12818 var precinctCodeblocks = [];
12819 // Section B.10.8 Order of info in packet
12820 var subbands = resolution.subbands;
12821 // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence
12822 for (var i = 0, ii = subbands.length; i < ii; i++) {
12823 var subband = subbands[i];
12824 var codeblocks = subband.codeblocks;
12825 for (var j = 0, jj = codeblocks.length; j < jj; j++) {
12826 var codeblock = codeblocks[j];
12827 if (codeblock.precinctNumber !== precinctNumber) {
12828 continue;
12829 }
12830 precinctCodeblocks.push(codeblock);
12831 }
12832 }
12833 return {
12834 layerNumber: layerNumber,
12835 codeblocks: precinctCodeblocks
12836 };
12837 }
12838 function LayerResolutionComponentPositionIterator(context) {
12839 var siz = context.SIZ;
12840 var tileIndex = context.currentTile.index;
12841 var tile = context.tiles[tileIndex];
12842 var layersCount = tile.codingStyleDefaultParameters.layersCount;
12843 var componentsCount = siz.Csiz;
12844 var maxDecompositionLevelsCount = 0;
12845 for (var q = 0; q < componentsCount; q++) {
12846 maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
12847 tile.components[q].codingStyleParameters.decompositionLevelsCount);
12848 }
12849
12850 var l = 0, r = 0, i = 0, k = 0;
12851
12852 this.nextPacket = function JpxImage_nextPacket() {
12853 // Section B.12.1.1 Layer-resolution-component-position
12854 for (; l < layersCount; l++) {
12855 for (; r <= maxDecompositionLevelsCount; r++) {
12856 for (; i < componentsCount; i++) {
12857 var component = tile.components[i];
12858 if (r > component.codingStyleParameters.decompositionLevelsCount) {
12859 continue;
12860 }
12861
12862 var resolution = component.resolutions[r];
12863 var numprecincts = resolution.precinctParameters.numprecincts;
12864 for (; k < numprecincts;) {
12865 var packet = createPacket(resolution, k, l);
12866 k++;
12867 return packet;
12868 }
12869 k = 0;
12870 }
12871 i = 0;
12872 }
12873 r = 0;
12874 }
12875 error('JPX Error: Out of packets');
12876 };
12877 }
12878 function ResolutionLayerComponentPositionIterator(context) {
12879 var siz = context.SIZ;
12880 var tileIndex = context.currentTile.index;
12881 var tile = context.tiles[tileIndex];
12882 var layersCount = tile.codingStyleDefaultParameters.layersCount;
12883 var componentsCount = siz.Csiz;
12884 var maxDecompositionLevelsCount = 0;
12885 for (var q = 0; q < componentsCount; q++) {
12886 maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
12887 tile.components[q].codingStyleParameters.decompositionLevelsCount);
12888 }
12889
12890 var r = 0, l = 0, i = 0, k = 0;
12891
12892 this.nextPacket = function JpxImage_nextPacket() {
12893 // Section B.12.1.2 Resolution-layer-component-position
12894 for (; r <= maxDecompositionLevelsCount; r++) {
12895 for (; l < layersCount; l++) {
12896 for (; i < componentsCount; i++) {
12897 var component = tile.components[i];
12898 if (r > component.codingStyleParameters.decompositionLevelsCount) {
12899 continue;
12900 }
12901
12902 var resolution = component.resolutions[r];
12903 var numprecincts = resolution.precinctParameters.numprecincts;
12904 for (; k < numprecincts;) {
12905 var packet = createPacket(resolution, k, l);
12906 k++;
12907 return packet;
12908 }
12909 k = 0;
12910 }
12911 i = 0;
12912 }
12913 l = 0;
12914 }
12915 error('JPX Error: Out of packets');
12916 };
12917 }
12918 function ResolutionPositionComponentLayerIterator(context) {
12919 var siz = context.SIZ;
12920 var tileIndex = context.currentTile.index;
12921 var tile = context.tiles[tileIndex];
12922 var layersCount = tile.codingStyleDefaultParameters.layersCount;
12923 var componentsCount = siz.Csiz;
12924 var l, r, c, p;
12925 var maxDecompositionLevelsCount = 0;
12926 for (c = 0; c < componentsCount; c++) {
12927 var component = tile.components[c];
12928 maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
12929 component.codingStyleParameters.decompositionLevelsCount);
12930 }
12931 var maxNumPrecinctsInLevel = new Int32Array(
12932 maxDecompositionLevelsCount + 1);
12933 for (r = 0; r <= maxDecompositionLevelsCount; ++r) {
12934 var maxNumPrecincts = 0;
12935 for (c = 0; c < componentsCount; ++c) {
12936 var resolutions = tile.components[c].resolutions;
12937 if (r < resolutions.length) {
12938 maxNumPrecincts = Math.max(maxNumPrecincts,
12939 resolutions[r].precinctParameters.numprecincts);
12940 }
12941 }
12942 maxNumPrecinctsInLevel[r] = maxNumPrecincts;
12943 }
12944 l = 0;
12945 r = 0;
12946 c = 0;
12947 p = 0;
12948
12949 this.nextPacket = function JpxImage_nextPacket() {
12950 // Section B.12.1.3 Resolution-position-component-layer
12951 for (; r <= maxDecompositionLevelsCount; r++) {
12952 for (; p < maxNumPrecinctsInLevel[r]; p++) {
12953 for (; c < componentsCount; c++) {
12954 var component = tile.components[c];
12955 if (r > component.codingStyleParameters.decompositionLevelsCount) {
12956 continue;
12957 }
12958 var resolution = component.resolutions[r];
12959 var numprecincts = resolution.precinctParameters.numprecincts;
12960 if (p >= numprecincts) {
12961 continue;
12962 }
12963 for (; l < layersCount;) {
12964 var packet = createPacket(resolution, p, l);
12965 l++;
12966 return packet;
12967 }
12968 l = 0;
12969 }
12970 c = 0;
12971 }
12972 p = 0;
12973 }
12974 error('JPX Error: Out of packets');
12975 };
12976 }
12977 function PositionComponentResolutionLayerIterator(context) {
12978 var siz = context.SIZ;
12979 var tileIndex = context.currentTile.index;
12980 var tile = context.tiles[tileIndex];
12981 var layersCount = tile.codingStyleDefaultParameters.layersCount;
12982 var componentsCount = siz.Csiz;
12983 var precinctsSizes = getPrecinctSizesInImageScale(tile);
12984 var precinctsIterationSizes = precinctsSizes;
12985 var l = 0, r = 0, c = 0, px = 0, py = 0;
12986
12987 this.nextPacket = function JpxImage_nextPacket() {
12988 // Section B.12.1.4 Position-component-resolution-layer
12989 for (; py < precinctsIterationSizes.maxNumHigh; py++) {
12990 for (; px < precinctsIterationSizes.maxNumWide; px++) {
12991 for (; c < componentsCount; c++) {
12992 var component = tile.components[c];
12993 var decompositionLevelsCount =
12994 component.codingStyleParameters.decompositionLevelsCount;
12995 for (; r <= decompositionLevelsCount; r++) {
12996 var resolution = component.resolutions[r];
12997 var sizeInImageScale =
12998 precinctsSizes.components[c].resolutions[r];
12999 var k = getPrecinctIndexIfExist(
13000 px,
13001 py,
13002 sizeInImageScale,
13003 precinctsIterationSizes,
13004 resolution);
13005 if (k === null) {
13006 continue;
13007 }
13008 for (; l < layersCount;) {
13009 var packet = createPacket(resolution, k, l);
13010 l++;
13011 return packet;
13012 }
13013 l = 0;
13014 }
13015 r = 0;
13016 }
13017 c = 0;
13018 }
13019 px = 0;
13020 }
13021 error('JPX Error: Out of packets');
13022 };
13023 }
13024 function ComponentPositionResolutionLayerIterator(context) {
13025 var siz = context.SIZ;
13026 var tileIndex = context.currentTile.index;
13027 var tile = context.tiles[tileIndex];
13028 var layersCount = tile.codingStyleDefaultParameters.layersCount;
13029 var componentsCount = siz.Csiz;
13030 var precinctsSizes = getPrecinctSizesInImageScale(tile);
13031 var l = 0, r = 0, c = 0, px = 0, py = 0;
13032
13033 this.nextPacket = function JpxImage_nextPacket() {
13034 // Section B.12.1.5 Component-position-resolution-layer
13035 for (; c < componentsCount; ++c) {
13036 var component = tile.components[c];
13037 var precinctsIterationSizes = precinctsSizes.components[c];
13038 var decompositionLevelsCount =
13039 component.codingStyleParameters.decompositionLevelsCount;
13040 for (; py < precinctsIterationSizes.maxNumHigh; py++) {
13041 for (; px < precinctsIterationSizes.maxNumWide; px++) {
13042 for (; r <= decompositionLevelsCount; r++) {
13043 var resolution = component.resolutions[r];
13044 var sizeInImageScale = precinctsIterationSizes.resolutions[r];
13045 var k = getPrecinctIndexIfExist(
13046 px,
13047 py,
13048 sizeInImageScale,
13049 precinctsIterationSizes,
13050 resolution);
13051 if (k === null) {
13052 continue;
13053 }
13054 for (; l < layersCount;) {
13055 var packet = createPacket(resolution, k, l);
13056 l++;
13057 return packet;
13058 }
13059 l = 0;
13060 }
13061 r = 0;
13062 }
13063 px = 0;
13064 }
13065 py = 0;
13066 }
13067 error('JPX Error: Out of packets');
13068 };
13069 }
13070 function getPrecinctIndexIfExist(
13071 pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) {
13072 var posX = pxIndex * precinctIterationSizes.minWidth;
13073 var posY = pyIndex * precinctIterationSizes.minHeight;
13074 if (posX % sizeInImageScale.width !== 0 ||
13075 posY % sizeInImageScale.height !== 0) {
13076 return null;
13077 }
13078 var startPrecinctRowIndex =
13079 (posY / sizeInImageScale.width) *
13080 resolution.precinctParameters.numprecinctswide;
13081 return (posX / sizeInImageScale.height) + startPrecinctRowIndex;
13082 }
13083 function getPrecinctSizesInImageScale(tile) {
13084 var componentsCount = tile.components.length;
13085 var minWidth = Number.MAX_VALUE;
13086 var minHeight = Number.MAX_VALUE;
13087 var maxNumWide = 0;
13088 var maxNumHigh = 0;
13089 var sizePerComponent = new Array(componentsCount);
13090 for (var c = 0; c < componentsCount; c++) {
13091 var component = tile.components[c];
13092 var decompositionLevelsCount =
13093 component.codingStyleParameters.decompositionLevelsCount;
13094 var sizePerResolution = new Array(decompositionLevelsCount + 1);
13095 var minWidthCurrentComponent = Number.MAX_VALUE;
13096 var minHeightCurrentComponent = Number.MAX_VALUE;
13097 var maxNumWideCurrentComponent = 0;
13098 var maxNumHighCurrentComponent = 0;
13099 var scale = 1;
13100 for (var r = decompositionLevelsCount; r >= 0; --r) {
13101 var resolution = component.resolutions[r];
13102 var widthCurrentResolution =
13103 scale * resolution.precinctParameters.precinctWidth;
13104 var heightCurrentResolution =
13105 scale * resolution.precinctParameters.precinctHeight;
13106 minWidthCurrentComponent = Math.min(
13107 minWidthCurrentComponent,
13108 widthCurrentResolution);
13109 minHeightCurrentComponent = Math.min(
13110 minHeightCurrentComponent,
13111 heightCurrentResolution);
13112 maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent,
13113 resolution.precinctParameters.numprecinctswide);
13114 maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent,
13115 resolution.precinctParameters.numprecinctshigh);
13116 sizePerResolution[r] = {
13117 width: widthCurrentResolution,
13118 height: heightCurrentResolution
13119 };
13120 scale <<= 1;
13121 }
13122 minWidth = Math.min(minWidth, minWidthCurrentComponent);
13123 minHeight = Math.min(minHeight, minHeightCurrentComponent);
13124 maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent);
13125 maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent);
13126 sizePerComponent[c] = {
13127 resolutions: sizePerResolution,
13128 minWidth: minWidthCurrentComponent,
13129 minHeight: minHeightCurrentComponent,
13130 maxNumWide: maxNumWideCurrentComponent,
13131 maxNumHigh: maxNumHighCurrentComponent
13132 };
13133 }
13134 return {
13135 components: sizePerComponent,
13136 minWidth: minWidth,
13137 minHeight: minHeight,
13138 maxNumWide: maxNumWide,
13139 maxNumHigh: maxNumHigh
13140 };
13141 }
13142 function buildPackets(context) {
13143 var siz = context.SIZ;
13144 var tileIndex = context.currentTile.index;
13145 var tile = context.tiles[tileIndex];
13146 var componentsCount = siz.Csiz;
13147 // Creating resolutions and sub-bands for each component
13148 for (var c = 0; c < componentsCount; c++) {
13149 var component = tile.components[c];
13150 var decompositionLevelsCount =
13151 component.codingStyleParameters.decompositionLevelsCount;
13152 // Section B.5 Resolution levels and sub-bands
13153 var resolutions = [];
13154 var subbands = [];
13155 for (var r = 0; r <= decompositionLevelsCount; r++) {
13156 var blocksDimensions = getBlocksDimensions(context, component, r);
13157 var resolution = {};
13158 var scale = 1 << (decompositionLevelsCount - r);
13159 resolution.trx0 = Math.ceil(component.tcx0 / scale);
13160 resolution.try0 = Math.ceil(component.tcy0 / scale);
13161 resolution.trx1 = Math.ceil(component.tcx1 / scale);
13162 resolution.try1 = Math.ceil(component.tcy1 / scale);
13163 resolution.resLevel = r;
13164 buildPrecincts(context, resolution, blocksDimensions);
13165 resolutions.push(resolution);
13166
13167 var subband;
13168 if (r === 0) {
13169 // one sub-band (LL) with last decomposition
13170 subband = {};
13171 subband.type = 'LL';
13172 subband.tbx0 = Math.ceil(component.tcx0 / scale);
13173 subband.tby0 = Math.ceil(component.tcy0 / scale);
13174 subband.tbx1 = Math.ceil(component.tcx1 / scale);
13175 subband.tby1 = Math.ceil(component.tcy1 / scale);
13176 subband.resolution = resolution;
13177 buildCodeblocks(context, subband, blocksDimensions);
13178 subbands.push(subband);
13179 resolution.subbands = [subband];
13180 } else {
13181 var bscale = 1 << (decompositionLevelsCount - r + 1);
13182 var resolutionSubbands = [];
13183 // three sub-bands (HL, LH and HH) with rest of decompositions
13184 subband = {};
13185 subband.type = 'HL';
13186 subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
13187 subband.tby0 = Math.ceil(component.tcy0 / bscale);
13188 subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
13189 subband.tby1 = Math.ceil(component.tcy1 / bscale);
13190 subband.resolution = resolution;
13191 buildCodeblocks(context, subband, blocksDimensions);
13192 subbands.push(subband);
13193 resolutionSubbands.push(subband);
13194
13195 subband = {};
13196 subband.type = 'LH';
13197 subband.tbx0 = Math.ceil(component.tcx0 / bscale);
13198 subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
13199 subband.tbx1 = Math.ceil(component.tcx1 / bscale);
13200 subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
13201 subband.resolution = resolution;
13202 buildCodeblocks(context, subband, blocksDimensions);
13203 subbands.push(subband);
13204 resolutionSubbands.push(subband);
13205
13206 subband = {};
13207 subband.type = 'HH';
13208 subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
13209 subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
13210 subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
13211 subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
13212 subband.resolution = resolution;
13213 buildCodeblocks(context, subband, blocksDimensions);
13214 subbands.push(subband);
13215 resolutionSubbands.push(subband);
13216
13217 resolution.subbands = resolutionSubbands;
13218 }
13219 }
13220 component.resolutions = resolutions;
13221 component.subbands = subbands;
13222 }
13223 // Generate the packets sequence
13224 var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
13225 switch (progressionOrder) {
13226 case 0:
13227 tile.packetsIterator =
13228 new LayerResolutionComponentPositionIterator(context);
13229 break;
13230 case 1:
13231 tile.packetsIterator =
13232 new ResolutionLayerComponentPositionIterator(context);
13233 break;
13234 case 2:
13235 tile.packetsIterator =
13236 new ResolutionPositionComponentLayerIterator(context);
13237 break;
13238 case 3:
13239 tile.packetsIterator =
13240 new PositionComponentResolutionLayerIterator(context);
13241 break;
13242 case 4:
13243 tile.packetsIterator =
13244 new ComponentPositionResolutionLayerIterator(context);
13245 break;
13246 default:
13247 error('JPX Error: Unsupported progression order ' + progressionOrder);
13248 }
13249 }
13250 function parseTilePackets(context, data, offset, dataLength) {
13251 var position = 0;
13252 var buffer, bufferSize = 0, skipNextBit = false;
13253 function readBits(count) {
13254 while (bufferSize < count) {
13255 var b = data[offset + position];
13256 position++;
13257 if (skipNextBit) {
13258 buffer = (buffer << 7) | b;
13259 bufferSize += 7;
13260 skipNextBit = false;
13261 } else {
13262 buffer = (buffer << 8) | b;
13263 bufferSize += 8;
13264 }
13265 if (b === 0xFF) {
13266 skipNextBit = true;
13267 }
13268 }
13269 bufferSize -= count;
13270 return (buffer >>> bufferSize) & ((1 << count) - 1);
13271 }
13272 function skipMarkerIfEqual(value) {
13273 if (data[offset + position - 1] === 0xFF &&
13274 data[offset + position] === value) {
13275 skipBytes(1);
13276 return true;
13277 } else if (data[offset + position] === 0xFF &&
13278 data[offset + position + 1] === value) {
13279 skipBytes(2);
13280 return true;
13281 }
13282 return false;
13283 }
13284 function skipBytes(count) {
13285 position += count;
13286 }
13287 function alignToByte() {
13288 bufferSize = 0;
13289 if (skipNextBit) {
13290 position++;
13291 skipNextBit = false;
13292 }
13293 }
13294 function readCodingpasses() {
13295 if (readBits(1) === 0) {
13296 return 1;
13297 }
13298 if (readBits(1) === 0) {
13299 return 2;
13300 }
13301 var value = readBits(2);
13302 if (value < 3) {
13303 return value + 3;
13304 }
13305 value = readBits(5);
13306 if (value < 31) {
13307 return value + 6;
13308 }
13309 value = readBits(7);
13310 return value + 37;
13311 }
13312 var tileIndex = context.currentTile.index;
13313 var tile = context.tiles[tileIndex];
13314 var sopMarkerUsed = context.COD.sopMarkerUsed;
13315 var ephMarkerUsed = context.COD.ephMarkerUsed;
13316 var packetsIterator = tile.packetsIterator;
13317 while (position < dataLength) {
13318 alignToByte();
13319 if (sopMarkerUsed && skipMarkerIfEqual(0x91)) {
13320 // Skip also marker segment length and packet sequence ID
13321 skipBytes(4);
13322 }
13323 var packet = packetsIterator.nextPacket();
13324 if (!readBits(1)) {
13325 continue;
13326 }
13327 var layerNumber = packet.layerNumber;
13328 var queue = [], codeblock;
13329 for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) {
13330 codeblock = packet.codeblocks[i];
13331 var precinct = codeblock.precinct;
13332 var codeblockColumn = codeblock.cbx - precinct.cbxMin;
13333 var codeblockRow = codeblock.cby - precinct.cbyMin;
13334 var codeblockIncluded = false;
13335 var firstTimeInclusion = false;
13336 var valueReady;
13337 if (codeblock['included'] !== undefined) {
13338 codeblockIncluded = !!readBits(1);
13339 } else {
13340 // reading inclusion tree
13341 precinct = codeblock.precinct;
13342 var inclusionTree, zeroBitPlanesTree;
13343 if (precinct['inclusionTree'] !== undefined) {
13344 inclusionTree = precinct.inclusionTree;
13345 } else {
13346 // building inclusion and zero bit-planes trees
13347 var width = precinct.cbxMax - precinct.cbxMin + 1;
13348 var height = precinct.cbyMax - precinct.cbyMin + 1;
13349 inclusionTree = new InclusionTree(width, height, layerNumber);
13350 zeroBitPlanesTree = new TagTree(width, height);
13351 precinct.inclusionTree = inclusionTree;
13352 precinct.zeroBitPlanesTree = zeroBitPlanesTree;
13353 }
13354
13355 if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
13356 while (true) {
13357 if (readBits(1)) {
13358 valueReady = !inclusionTree.nextLevel();
13359 if (valueReady) {
13360 codeblock.included = true;
13361 codeblockIncluded = firstTimeInclusion = true;
13362 break;
13363 }
13364 } else {
13365 inclusionTree.incrementValue(layerNumber);
13366 break;
13367 }
13368 }
13369 }
13370 }
13371 if (!codeblockIncluded) {
13372 continue;
13373 }
13374 if (firstTimeInclusion) {
13375 zeroBitPlanesTree = precinct.zeroBitPlanesTree;
13376 zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
13377 while (true) {
13378 if (readBits(1)) {
13379 valueReady = !zeroBitPlanesTree.nextLevel();
13380 if (valueReady) {
13381 break;
13382 }
13383 } else {
13384 zeroBitPlanesTree.incrementValue();
13385 }
13386 }
13387 codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
13388 }
13389 var codingpasses = readCodingpasses();
13390 while (readBits(1)) {
13391 codeblock.Lblock++;
13392 }
13393 var codingpassesLog2 = log2(codingpasses);
13394 // rounding down log2
13395 var bits = ((codingpasses < (1 << codingpassesLog2)) ?
13396 codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock;
13397 var codedDataLength = readBits(bits);
13398 queue.push({
13399 codeblock: codeblock,
13400 codingpasses: codingpasses,
13401 dataLength: codedDataLength
13402 });
13403 }
13404 alignToByte();
13405 if (ephMarkerUsed) {
13406 skipMarkerIfEqual(0x92);
13407 }
13408 while (queue.length > 0) {
13409 var packetItem = queue.shift();
13410 codeblock = packetItem.codeblock;
13411 if (codeblock['data'] === undefined) {
13412 codeblock.data = [];
13413 }
13414 codeblock.data.push({
13415 data: data,
13416 start: offset + position,
13417 end: offset + position + packetItem.dataLength,
13418 codingpasses: packetItem.codingpasses
13419 });
13420 position += packetItem.dataLength;
13421 }
13422 }
13423 return position;
13424 }
13425 function copyCoefficients(coefficients, levelWidth, levelHeight, subband,
13426 delta, mb, reversible, segmentationSymbolUsed) {
13427 var x0 = subband.tbx0;
13428 var y0 = subband.tby0;
13429 var width = subband.tbx1 - subband.tbx0;
13430 var codeblocks = subband.codeblocks;
13431 var right = subband.type.charAt(0) === 'H' ? 1 : 0;
13432 var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0;
13433
13434 for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
13435 var codeblock = codeblocks[i];
13436 var blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
13437 var blockHeight = codeblock.tby1_ - codeblock.tby0_;
13438 if (blockWidth === 0 || blockHeight === 0) {
13439 continue;
13440 }
13441 if (codeblock['data'] === undefined) {
13442 continue;
13443 }
13444
13445 var bitModel, currentCodingpassType;
13446 bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType,
13447 codeblock.zeroBitPlanes, mb);
13448 currentCodingpassType = 2; // first bit plane starts from cleanup
13449
13450 // collect data
13451 var data = codeblock.data, totalLength = 0, codingpasses = 0;
13452 var j, jj, dataItem;
13453 for (j = 0, jj = data.length; j < jj; j++) {
13454 dataItem = data[j];
13455 totalLength += dataItem.end - dataItem.start;
13456 codingpasses += dataItem.codingpasses;
13457 }
13458 var encodedData = new Uint8Array(totalLength);
13459 var position = 0;
13460 for (j = 0, jj = data.length; j < jj; j++) {
13461 dataItem = data[j];
13462 var chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
13463 encodedData.set(chunk, position);
13464 position += chunk.length;
13465 }
13466 // decoding the item
13467 var decoder = new ArithmeticDecoder(encodedData, 0, totalLength);
13468 bitModel.setDecoder(decoder);
13469
13470 for (j = 0; j < codingpasses; j++) {
13471 switch (currentCodingpassType) {
13472 case 0:
13473 bitModel.runSignificancePropagationPass();
13474 break;
13475 case 1:
13476 bitModel.runMagnitudeRefinementPass();
13477 break;
13478 case 2:
13479 bitModel.runCleanupPass();
13480 if (segmentationSymbolUsed) {
13481 bitModel.checkSegmentationSymbol();
13482 }
13483 break;
13484 }
13485 currentCodingpassType = (currentCodingpassType + 1) % 3;
13486 }
13487
13488 var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width;
13489 var sign = bitModel.coefficentsSign;
13490 var magnitude = bitModel.coefficentsMagnitude;
13491 var bitsDecoded = bitModel.bitsDecoded;
13492 var magnitudeCorrection = reversible ? 0 : 0.5;
13493 var k, n, nb;
13494 position = 0;
13495 // Do the interleaving of Section F.3.3 here, so we do not need
13496 // to copy later. LL level is not interleaved, just copied.
13497 var interleave = (subband.type !== 'LL');
13498 for (j = 0; j < blockHeight; j++) {
13499 var row = (offset / width) | 0; // row in the non-interleaved subband
13500 var levelOffset = 2 * row * (levelWidth - width) + right + bottom;
13501 for (k = 0; k < blockWidth; k++) {
13502 n = magnitude[position];
13503 if (n !== 0) {
13504 n = (n + magnitudeCorrection) * delta;
13505 if (sign[position] !== 0) {
13506 n = -n;
13507 }
13508 nb = bitsDecoded[position];
13509 var pos = interleave ? (levelOffset + (offset << 1)) : offset;
13510 if (reversible && (nb >= mb)) {
13511 coefficients[pos] = n;
13512 } else {
13513 coefficients[pos] = n * (1 << (mb - nb));
13514 }
13515 }
13516 offset++;
13517 position++;
13518 }
13519 offset += width - blockWidth;
13520 }
13521 }
13522 }
13523 function transformTile(context, tile, c) {
13524 var component = tile.components[c];
13525 var codingStyleParameters = component.codingStyleParameters;
13526 var quantizationParameters = component.quantizationParameters;
13527 var decompositionLevelsCount =
13528 codingStyleParameters.decompositionLevelsCount;
13529 var spqcds = quantizationParameters.SPqcds;
13530 var scalarExpounded = quantizationParameters.scalarExpounded;
13531 var guardBits = quantizationParameters.guardBits;
13532 var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
13533 var precision = context.components[c].precision;
13534
13535 var reversible = codingStyleParameters.reversibleTransformation;
13536 var transform = (reversible ? new ReversibleTransform() :
13537 new IrreversibleTransform());
13538
13539 var subbandCoefficients = [];
13540 var b = 0;
13541 for (var i = 0; i <= decompositionLevelsCount; i++) {
13542 var resolution = component.resolutions[i];
13543
13544 var width = resolution.trx1 - resolution.trx0;
13545 var height = resolution.try1 - resolution.try0;
13546 // Allocate space for the whole sublevel.
13547 var coefficients = new Float32Array(width * height);
13548
13549 for (var j = 0, jj = resolution.subbands.length; j < jj; j++) {
13550 var mu, epsilon;
13551 if (!scalarExpounded) {
13552 // formula E-5
13553 mu = spqcds[0].mu;
13554 epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
13555 } else {
13556 mu = spqcds[b].mu;
13557 epsilon = spqcds[b].epsilon;
13558 b++;
13559 }
13560
13561 var subband = resolution.subbands[j];
13562 var gainLog2 = SubbandsGainLog2[subband.type];
13563
13564 // calculate quantization coefficient (Section E.1.1.1)
13565 var delta = (reversible ? 1 :
13566 Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048));
13567 var mb = (guardBits + epsilon - 1);
13568
13569 // In the first resolution level, copyCoefficients will fill the
13570 // whole array with coefficients. In the succeeding passes,
13571 // copyCoefficients will consecutively fill in the values that belong
13572 // to the interleaved positions of the HL, LH, and HH coefficients.
13573 // The LL coefficients will then be interleaved in Transform.iterate().
13574 copyCoefficients(coefficients, width, height, subband, delta, mb,
13575 reversible, segmentationSymbolUsed);
13576 }
13577 subbandCoefficients.push({
13578 width: width,
13579 height: height,
13580 items: coefficients
13581 });
13582 }
13583
13584 var result = transform.calculate(subbandCoefficients,
13585 component.tcx0, component.tcy0);
13586 return {
13587 left: component.tcx0,
13588 top: component.tcy0,
13589 width: result.width,
13590 height: result.height,
13591 items: result.items
13592 };
13593 }
13594 function transformComponents(context) {
13595 var siz = context.SIZ;
13596 var components = context.components;
13597 var componentsCount = siz.Csiz;
13598 var resultImages = [];
13599 for (var i = 0, ii = context.tiles.length; i < ii; i++) {
13600 var tile = context.tiles[i];
13601 var transformedTiles = [];
13602 var c;
13603 for (c = 0; c < componentsCount; c++) {
13604 transformedTiles[c] = transformTile(context, tile, c);
13605 }
13606 var tile0 = transformedTiles[0];
13607 var out = new Uint8Array(tile0.items.length * componentsCount);
13608 var result = {
13609 left: tile0.left,
13610 top: tile0.top,
13611 width: tile0.width,
13612 height: tile0.height,
13613 items: out
13614 };
13615
13616 // Section G.2.2 Inverse multi component transform
13617 var shift, offset, max, min, maxK;
13618 var pos = 0, j, jj, y0, y1, y2, r, g, b, k, val;
13619 if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
13620 var fourComponents = componentsCount === 4;
13621 var y0items = transformedTiles[0].items;
13622 var y1items = transformedTiles[1].items;
13623 var y2items = transformedTiles[2].items;
13624 var y3items = fourComponents ? transformedTiles[3].items : null;
13625
13626 // HACK: The multiple component transform formulas below assume that
13627 // all components have the same precision. With this in mind, we
13628 // compute shift and offset only once.
13629 shift = components[0].precision - 8;
13630 offset = (128 << shift) + 0.5;
13631 max = 255 * (1 << shift);
13632 maxK = max * 0.5;
13633 min = -maxK;
13634
13635 var component0 = tile.components[0];
13636 var alpha01 = componentsCount - 3;
13637 jj = y0items.length;
13638 if (!component0.codingStyleParameters.reversibleTransformation) {
13639 // inverse irreversible multiple component transform
13640 for (j = 0; j < jj; j++, pos += alpha01) {
13641 y0 = y0items[j] + offset;
13642 y1 = y1items[j];
13643 y2 = y2items[j];
13644 r = y0 + 1.402 * y2;
13645 g = y0 - 0.34413 * y1 - 0.71414 * y2;
13646 b = y0 + 1.772 * y1;
13647 out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift;
13648 out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift;
13649 out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift;
13650 }
13651 } else {
13652 // inverse reversible multiple component transform
13653 for (j = 0; j < jj; j++, pos += alpha01) {
13654 y0 = y0items[j] + offset;
13655 y1 = y1items[j];
13656 y2 = y2items[j];
13657 g = y0 - ((y2 + y1) >> 2);
13658 r = g + y2;
13659 b = g + y1;
13660 out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift;
13661 out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift;
13662 out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift;
13663 }
13664 }
13665 if (fourComponents) {
13666 for (j = 0, pos = 3; j < jj; j++, pos += 4) {
13667 k = y3items[j];
13668 out[pos] = k <= min ? 0 : k >= maxK ? 255 : (k + offset) >> shift;
13669 }
13670 }
13671 } else { // no multi-component transform
13672 for (c = 0; c < componentsCount; c++) {
13673 var items = transformedTiles[c].items;
13674 shift = components[c].precision - 8;
13675 offset = (128 << shift) + 0.5;
13676 max = (127.5 * (1 << shift));
13677 min = -max;
13678 for (pos = c, j = 0, jj = items.length; j < jj; j++) {
13679 val = items[j];
13680 out[pos] = val <= min ? 0 :
13681 val >= max ? 255 : (val + offset) >> shift;
13682 pos += componentsCount;
13683 }
13684 }
13685 }
13686 resultImages.push(result);
13687 }
13688 return resultImages;
13689 }
13690 function initializeTile(context, tileIndex) {
13691 var siz = context.SIZ;
13692 var componentsCount = siz.Csiz;
13693 var tile = context.tiles[tileIndex];
13694 for (var c = 0; c < componentsCount; c++) {
13695 var component = tile.components[c];
13696 var qcdOrQcc = (context.currentTile.QCC[c] !== undefined ?
13697 context.currentTile.QCC[c] : context.currentTile.QCD);
13698 component.quantizationParameters = qcdOrQcc;
13699 var codOrCoc = (context.currentTile.COC[c] !== undefined ?
13700 context.currentTile.COC[c] : context.currentTile.COD);
13701 component.codingStyleParameters = codOrCoc;
13702 }
13703 tile.codingStyleDefaultParameters = context.currentTile.COD;
13704 }
13705
13706 // Section B.10.2 Tag trees
13707 var TagTree = (function TagTreeClosure() {
13708 function TagTree(width, height) {
13709 var levelsLength = log2(Math.max(width, height)) + 1;
13710 this.levels = [];
13711 for (var i = 0; i < levelsLength; i++) {
13712 var level = {
13713 width: width,
13714 height: height,
13715 items: []
13716 };
13717 this.levels.push(level);
13718 width = Math.ceil(width / 2);
13719 height = Math.ceil(height / 2);
13720 }
13721 }
13722 TagTree.prototype = {
13723 reset: function TagTree_reset(i, j) {
13724 var currentLevel = 0, value = 0, level;
13725 while (currentLevel < this.levels.length) {
13726 level = this.levels[currentLevel];
13727 var index = i + j * level.width;
13728 if (level.items[index] !== undefined) {
13729 value = level.items[index];
13730 break;
13731 }
13732 level.index = index;
13733 i >>= 1;
13734 j >>= 1;
13735 currentLevel++;
13736 }
13737 currentLevel--;
13738 level = this.levels[currentLevel];
13739 level.items[level.index] = value;
13740 this.currentLevel = currentLevel;
13741 delete this.value;
13742 },
13743 incrementValue: function TagTree_incrementValue() {
13744 var level = this.levels[this.currentLevel];
13745 level.items[level.index]++;
13746 },
13747 nextLevel: function TagTree_nextLevel() {
13748 var currentLevel = this.currentLevel;
13749 var level = this.levels[currentLevel];
13750 var value = level.items[level.index];
13751 currentLevel--;
13752 if (currentLevel < 0) {
13753 this.value = value;
13754 return false;
13755 }
13756
13757 this.currentLevel = currentLevel;
13758 level = this.levels[currentLevel];
13759 level.items[level.index] = value;
13760 return true;
13761 }
13762 };
13763 return TagTree;
13764 })();
13765
13766 var InclusionTree = (function InclusionTreeClosure() {
13767 function InclusionTree(width, height, defaultValue) {
13768 var levelsLength = log2(Math.max(width, height)) + 1;
13769 this.levels = [];
13770 for (var i = 0; i < levelsLength; i++) {
13771 var items = new Uint8Array(width * height);
13772 for (var j = 0, jj = items.length; j < jj; j++) {
13773 items[j] = defaultValue;
13774 }
13775
13776 var level = {
13777 width: width,
13778 height: height,
13779 items: items
13780 };
13781 this.levels.push(level);
13782
13783 width = Math.ceil(width / 2);
13784 height = Math.ceil(height / 2);
13785 }
13786 }
13787 InclusionTree.prototype = {
13788 reset: function InclusionTree_reset(i, j, stopValue) {
13789 var currentLevel = 0;
13790 while (currentLevel < this.levels.length) {
13791 var level = this.levels[currentLevel];
13792 var index = i + j * level.width;
13793 level.index = index;
13794 var value = level.items[index];
13795
13796 if (value === 0xFF) {
13797 break;
13798 }
13799
13800 if (value > stopValue) {
13801 this.currentLevel = currentLevel;
13802 // already know about this one, propagating the value to top levels
13803 this.propagateValues();
13804 return false;
13805 }
13806
13807 i >>= 1;
13808 j >>= 1;
13809 currentLevel++;
13810 }
13811 this.currentLevel = currentLevel - 1;
13812 return true;
13813 },
13814 incrementValue: function InclusionTree_incrementValue(stopValue) {
13815 var level = this.levels[this.currentLevel];
13816 level.items[level.index] = stopValue + 1;
13817 this.propagateValues();
13818 },
13819 propagateValues: function InclusionTree_propagateValues() {
13820 var levelIndex = this.currentLevel;
13821 var level = this.levels[levelIndex];
13822 var currentValue = level.items[level.index];
13823 while (--levelIndex >= 0) {
13824 level = this.levels[levelIndex];
13825 level.items[level.index] = currentValue;
13826 }
13827 },
13828 nextLevel: function InclusionTree_nextLevel() {
13829 var currentLevel = this.currentLevel;
13830 var level = this.levels[currentLevel];
13831 var value = level.items[level.index];
13832 level.items[level.index] = 0xFF;
13833 currentLevel--;
13834 if (currentLevel < 0) {
13835 return false;
13836 }
13837
13838 this.currentLevel = currentLevel;
13839 level = this.levels[currentLevel];
13840 level.items[level.index] = value;
13841 return true;
13842 }
13843 };
13844 return InclusionTree;
13845 })();
13846
13847 // Section D. Coefficient bit modeling
13848 var BitModel = (function BitModelClosure() {
13849 var UNIFORM_CONTEXT = 17;
13850 var RUNLENGTH_CONTEXT = 18;
13851 // Table D-1
13852 // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4),
13853 // vv - sum of Vi (0..2), and hh - sum of Hi (0..2)
13854 var LLAndLHContextsLabel = new Uint8Array([
13855 0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4,
13856 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6,
13857 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8
13858 ]);
13859 var HLContextLabel = new Uint8Array([
13860 0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8,
13861 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3,
13862 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8
13863 ]);
13864 var HHContextLabel = new Uint8Array([
13865 0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5,
13866 5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8,
13867 8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8
13868 ]);
13869
13870 function BitModel(width, height, subband, zeroBitPlanes, mb) {
13871 this.width = width;
13872 this.height = height;
13873
13874 this.contextLabelTable = (subband === 'HH' ? HHContextLabel :
13875 (subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel));
13876
13877 var coefficientCount = width * height;
13878
13879 // coefficients outside the encoding region treated as insignificant
13880 // add border state cells for significanceState
13881 this.neighborsSignificance = new Uint8Array(coefficientCount);
13882 this.coefficentsSign = new Uint8Array(coefficientCount);
13883 this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) :
13884 mb > 6 ? new Uint16Array(coefficientCount) :
13885 new Uint8Array(coefficientCount);
13886 this.processingFlags = new Uint8Array(coefficientCount);
13887
13888 var bitsDecoded = new Uint8Array(coefficientCount);
13889 if (zeroBitPlanes !== 0) {
13890 for (var i = 0; i < coefficientCount; i++) {
13891 bitsDecoded[i] = zeroBitPlanes;
13892 }
13893 }
13894 this.bitsDecoded = bitsDecoded;
13895
13896 this.reset();
13897 }
13898
13899 BitModel.prototype = {
13900 setDecoder: function BitModel_setDecoder(decoder) {
13901 this.decoder = decoder;
13902 },
13903 reset: function BitModel_reset() {
13904 // We have 17 contexts that are accessed via context labels,
13905 // plus the uniform and runlength context.
13906 this.contexts = new Int8Array(19);
13907
13908 // Contexts are packed into 1 byte:
13909 // highest 7 bits carry the index, lowest bit carries mps
13910 this.contexts[0] = (4 << 1) | 0;
13911 this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0;
13912 this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0;
13913 },
13914 setNeighborsSignificance:
13915 function BitModel_setNeighborsSignificance(row, column, index) {
13916 var neighborsSignificance = this.neighborsSignificance;
13917 var width = this.width, height = this.height;
13918 var left = (column > 0);
13919 var right = (column + 1 < width);
13920 var i;
13921
13922 if (row > 0) {
13923 i = index - width;
13924 if (left) {
13925 neighborsSignificance[i - 1] += 0x10;
13926 }
13927 if (right) {
13928 neighborsSignificance[i + 1] += 0x10;
13929 }
13930 neighborsSignificance[i] += 0x04;
13931 }
13932
13933 if (row + 1 < height) {
13934 i = index + width;
13935 if (left) {
13936 neighborsSignificance[i - 1] += 0x10;
13937 }
13938 if (right) {
13939 neighborsSignificance[i + 1] += 0x10;
13940 }
13941 neighborsSignificance[i] += 0x04;
13942 }
13943
13944 if (left) {
13945 neighborsSignificance[index - 1] += 0x01;
13946 }
13947 if (right) {
13948 neighborsSignificance[index + 1] += 0x01;
13949 }
13950 neighborsSignificance[index] |= 0x80;
13951 },
13952 runSignificancePropagationPass:
13953 function BitModel_runSignificancePropagationPass() {
13954 var decoder = this.decoder;
13955 var width = this.width, height = this.height;
13956 var coefficentsMagnitude = this.coefficentsMagnitude;
13957 var coefficentsSign = this.coefficentsSign;
13958 var neighborsSignificance = this.neighborsSignificance;
13959 var processingFlags = this.processingFlags;
13960 var contexts = this.contexts;
13961 var labels = this.contextLabelTable;
13962 var bitsDecoded = this.bitsDecoded;
13963 var processedInverseMask = ~1;
13964 var processedMask = 1;
13965 var firstMagnitudeBitMask = 2;
13966
13967 for (var i0 = 0; i0 < height; i0 += 4) {
13968 for (var j = 0; j < width; j++) {
13969 var index = i0 * width + j;
13970 for (var i1 = 0; i1 < 4; i1++, index += width) {
13971 var i = i0 + i1;
13972 if (i >= height) {
13973 break;
13974 }
13975 // clear processed flag first
13976 processingFlags[index] &= processedInverseMask;
13977
13978 if (coefficentsMagnitude[index] ||
13979 !neighborsSignificance[index]) {
13980 continue;
13981 }
13982
13983 var contextLabel = labels[neighborsSignificance[index]];
13984 var decision = decoder.readBit(contexts, contextLabel);
13985 if (decision) {
13986 var sign = this.decodeSignBit(i, j, index);
13987 coefficentsSign[index] = sign;
13988 coefficentsMagnitude[index] = 1;
13989 this.setNeighborsSignificance(i, j, index);
13990 processingFlags[index] |= firstMagnitudeBitMask;
13991 }
13992 bitsDecoded[index]++;
13993 processingFlags[index] |= processedMask;
13994 }
13995 }
13996 }
13997 },
13998 decodeSignBit: function BitModel_decodeSignBit(row, column, index) {
13999 var width = this.width, height = this.height;
14000 var coefficentsMagnitude = this.coefficentsMagnitude;
14001 var coefficentsSign = this.coefficentsSign;
14002 var contribution, sign0, sign1, significance1;
14003 var contextLabel, decoded;
14004
14005 // calculate horizontal contribution
14006 significance1 = (column > 0 && coefficentsMagnitude[index - 1] !== 0);
14007 if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
14008 sign1 = coefficentsSign[index + 1];
14009 if (significance1) {
14010 sign0 = coefficentsSign[index - 1];
14011 contribution = 1 - sign1 - sign0;
14012 } else {
14013 contribution = 1 - sign1 - sign1;
14014 }
14015 } else if (significance1) {
14016 sign0 = coefficentsSign[index - 1];
14017 contribution = 1 - sign0 - sign0;
14018 } else {
14019 contribution = 0;
14020 }
14021 var horizontalContribution = 3 * contribution;
14022
14023 // calculate vertical contribution and combine with the horizontal
14024 significance1 = (row > 0 && coefficentsMagnitude[index - width] !== 0);
14025 if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
14026 sign1 = coefficentsSign[index + width];
14027 if (significance1) {
14028 sign0 = coefficentsSign[index - width];
14029 contribution = 1 - sign1 - sign0 + horizontalContribution;
14030 } else {
14031 contribution = 1 - sign1 - sign1 + horizontalContribution;
14032 }
14033 } else if (significance1) {
14034 sign0 = coefficentsSign[index - width];
14035 contribution = 1 - sign0 - sign0 + horizontalContribution;
14036 } else {
14037 contribution = horizontalContribution;
14038 }
14039
14040 if (contribution >= 0) {
14041 contextLabel = 9 + contribution;
14042 decoded = this.decoder.readBit(this.contexts, contextLabel);
14043 } else {
14044 contextLabel = 9 - contribution;
14045 decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
14046 }
14047 return decoded;
14048 },
14049 runMagnitudeRefinementPass:
14050 function BitModel_runMagnitudeRefinementPass() {
14051 var decoder = this.decoder;
14052 var width = this.width, height = this.height;
14053 var coefficentsMagnitude = this.coefficentsMagnitude;
14054 var neighborsSignificance = this.neighborsSignificance;
14055 var contexts = this.contexts;
14056 var bitsDecoded = this.bitsDecoded;
14057 var processingFlags = this.processingFlags;
14058 var processedMask = 1;
14059 var firstMagnitudeBitMask = 2;
14060 var length = width * height;
14061 var width4 = width * 4;
14062
14063 for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) {
14064 indexNext = Math.min(length, index0 + width4);
14065 for (var j = 0; j < width; j++) {
14066 for (var index = index0 + j; index < indexNext; index += width) {
14067
14068 // significant but not those that have just become
14069 if (!coefficentsMagnitude[index] ||
14070 (processingFlags[index] & processedMask) !== 0) {
14071 continue;
14072 }
14073
14074 var contextLabel = 16;
14075 if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
14076 processingFlags[index] ^= firstMagnitudeBitMask;
14077 // first refinement
14078 var significance = neighborsSignificance[index] & 127;
14079 contextLabel = significance === 0 ? 15 : 14;
14080 }
14081
14082 var bit = decoder.readBit(contexts, contextLabel);
14083 coefficentsMagnitude[index] =
14084 (coefficentsMagnitude[index] << 1) | bit;
14085 bitsDecoded[index]++;
14086 processingFlags[index] |= processedMask;
14087 }
14088 }
14089 }
14090 },
14091 runCleanupPass: function BitModel_runCleanupPass() {
14092 var decoder = this.decoder;
14093 var width = this.width, height = this.height;
14094 var neighborsSignificance = this.neighborsSignificance;
14095 var coefficentsMagnitude = this.coefficentsMagnitude;
14096 var coefficentsSign = this.coefficentsSign;
14097 var contexts = this.contexts;
14098 var labels = this.contextLabelTable;
14099 var bitsDecoded = this.bitsDecoded;
14100 var processingFlags = this.processingFlags;
14101 var processedMask = 1;
14102 var firstMagnitudeBitMask = 2;
14103 var oneRowDown = width;
14104 var twoRowsDown = width * 2;
14105 var threeRowsDown = width * 3;
14106 var iNext;
14107 for (var i0 = 0; i0 < height; i0 = iNext) {
14108 iNext = Math.min(i0 + 4, height);
14109 var indexBase = i0 * width;
14110 var checkAllEmpty = i0 + 3 < height;
14111 for (var j = 0; j < width; j++) {
14112 var index0 = indexBase + j;
14113 // using the property: labels[neighborsSignificance[index]] === 0
14114 // when neighborsSignificance[index] === 0
14115 var allEmpty = (checkAllEmpty &&
14116 processingFlags[index0] === 0 &&
14117 processingFlags[index0 + oneRowDown] === 0 &&
14118 processingFlags[index0 + twoRowsDown] === 0 &&
14119 processingFlags[index0 + threeRowsDown] === 0 &&
14120 neighborsSignificance[index0] === 0 &&
14121 neighborsSignificance[index0 + oneRowDown] === 0 &&
14122 neighborsSignificance[index0 + twoRowsDown] === 0 &&
14123 neighborsSignificance[index0 + threeRowsDown] === 0);
14124 var i1 = 0, index = index0;
14125 var i = i0, sign;
14126 if (allEmpty) {
14127 var hasSignificantCoefficent =
14128 decoder.readBit(contexts, RUNLENGTH_CONTEXT);
14129 if (!hasSignificantCoefficent) {
14130 bitsDecoded[index0]++;
14131 bitsDecoded[index0 + oneRowDown]++;
14132 bitsDecoded[index0 + twoRowsDown]++;
14133 bitsDecoded[index0 + threeRowsDown]++;
14134 continue; // next column
14135 }
14136 i1 = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
14137 decoder.readBit(contexts, UNIFORM_CONTEXT);
14138 if (i1 !== 0) {
14139 i = i0 + i1;
14140 index += i1 * width;
14141 }
14142
14143 sign = this.decodeSignBit(i, j, index);
14144 coefficentsSign[index] = sign;
14145 coefficentsMagnitude[index] = 1;
14146 this.setNeighborsSignificance(i, j, index);
14147 processingFlags[index] |= firstMagnitudeBitMask;
14148
14149 index = index0;
14150 for (var i2 = i0; i2 <= i; i2++, index += width) {
14151 bitsDecoded[index]++;
14152 }
14153
14154 i1++;
14155 }
14156 for (i = i0 + i1; i < iNext; i++, index += width) {
14157 if (coefficentsMagnitude[index] ||
14158 (processingFlags[index] & processedMask) !== 0) {
14159 continue;
14160 }
14161
14162 var contextLabel = labels[neighborsSignificance[index]];
14163 var decision = decoder.readBit(contexts, contextLabel);
14164 if (decision === 1) {
14165 sign = this.decodeSignBit(i, j, index);
14166 coefficentsSign[index] = sign;
14167 coefficentsMagnitude[index] = 1;
14168 this.setNeighborsSignificance(i, j, index);
14169 processingFlags[index] |= firstMagnitudeBitMask;
14170 }
14171 bitsDecoded[index]++;
14172 }
14173 }
14174 }
14175 },
14176 checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() {
14177 var decoder = this.decoder;
14178 var contexts = this.contexts;
14179 var symbol = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 3) |
14180 (decoder.readBit(contexts, UNIFORM_CONTEXT) << 2) |
14181 (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
14182 decoder.readBit(contexts, UNIFORM_CONTEXT);
14183 if (symbol !== 0xA) {
14184 error('JPX Error: Invalid segmentation symbol');
14185 }
14186 }
14187 };
14188
14189 return BitModel;
14190 })();
14191
14192 // Section F, Discrete wavelet transformation
14193 var Transform = (function TransformClosure() {
14194 function Transform() {}
14195
14196 Transform.prototype.calculate =
14197 function transformCalculate(subbands, u0, v0) {
14198 var ll = subbands[0];
14199 for (var i = 1, ii = subbands.length; i < ii; i++) {
14200 ll = this.iterate(ll, subbands[i], u0, v0);
14201 }
14202 return ll;
14203 };
14204 Transform.prototype.extend = function extend(buffer, offset, size) {
14205 // Section F.3.7 extending... using max extension of 4
14206 var i1 = offset - 1, j1 = offset + 1;
14207 var i2 = offset + size - 2, j2 = offset + size;
14208 buffer[i1--] = buffer[j1++];
14209 buffer[j2++] = buffer[i2--];
14210 buffer[i1--] = buffer[j1++];
14211 buffer[j2++] = buffer[i2--];
14212 buffer[i1--] = buffer[j1++];
14213 buffer[j2++] = buffer[i2--];
14214 buffer[i1] = buffer[j1];
14215 buffer[j2] = buffer[i2];
14216 };
14217 Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh,
14218 u0, v0) {
14219 var llWidth = ll.width, llHeight = ll.height, llItems = ll.items;
14220 var width = hl_lh_hh.width;
14221 var height = hl_lh_hh.height;
14222 var items = hl_lh_hh.items;
14223 var i, j, k, l, u, v;
14224
14225 // Interleave LL according to Section F.3.3
14226 for (k = 0, i = 0; i < llHeight; i++) {
14227 l = i * 2 * width;
14228 for (j = 0; j < llWidth; j++, k++, l += 2) {
14229 items[l] = llItems[k];
14230 }
14231 }
14232 // The LL band is not needed anymore.
14233 llItems = ll.items = null;
14234
14235 var bufferPadding = 4;
14236 var rowBuffer = new Float32Array(width + 2 * bufferPadding);
14237
14238 // Section F.3.4 HOR_SR
14239 if (width === 1) {
14240 // if width = 1, when u0 even keep items as is, when odd divide by 2
14241 if ((u0 & 1) !== 0) {
14242 for (v = 0, k = 0; v < height; v++, k += width) {
14243 items[k] *= 0.5;
14244 }
14245 }
14246 } else {
14247 for (v = 0, k = 0; v < height; v++, k += width) {
14248 rowBuffer.set(items.subarray(k, k + width), bufferPadding);
14249
14250 this.extend(rowBuffer, bufferPadding, width);
14251 this.filter(rowBuffer, bufferPadding, width);
14252
14253 items.set(
14254 rowBuffer.subarray(bufferPadding, bufferPadding + width),
14255 k);
14256 }
14257 }
14258
14259 // Accesses to the items array can take long, because it may not fit into
14260 // CPU cache and has to be fetched from main memory. Since subsequent
14261 // accesses to the items array are not local when reading columns, we
14262 // have a cache miss every time. To reduce cache misses, get up to
14263 // 'numBuffers' items at a time and store them into the individual
14264 // buffers. The colBuffers should be small enough to fit into CPU cache.
14265 var numBuffers = 16;
14266 var colBuffers = [];
14267 for (i = 0; i < numBuffers; i++) {
14268 colBuffers.push(new Float32Array(height + 2 * bufferPadding));
14269 }
14270 var b, currentBuffer = 0;
14271 ll = bufferPadding + height;
14272
14273 // Section F.3.5 VER_SR
14274 if (height === 1) {
14275 // if height = 1, when v0 even keep items as is, when odd divide by 2
14276 if ((v0 & 1) !== 0) {
14277 for (u = 0; u < width; u++) {
14278 items[u] *= 0.5;
14279 }
14280 }
14281 } else {
14282 for (u = 0; u < width; u++) {
14283 // if we ran out of buffers, copy several image columns at once
14284 if (currentBuffer === 0) {
14285 numBuffers = Math.min(width - u, numBuffers);
14286 for (k = u, l = bufferPadding; l < ll; k += width, l++) {
14287 for (b = 0; b < numBuffers; b++) {
14288 colBuffers[b][l] = items[k + b];
14289 }
14290 }
14291 currentBuffer = numBuffers;
14292 }
14293
14294 currentBuffer--;
14295 var buffer = colBuffers[currentBuffer];
14296 this.extend(buffer, bufferPadding, height);
14297 this.filter(buffer, bufferPadding, height);
14298
14299 // If this is last buffer in this group of buffers, flush all buffers.
14300 if (currentBuffer === 0) {
14301 k = u - numBuffers + 1;
14302 for (l = bufferPadding; l < ll; k += width, l++) {
14303 for (b = 0; b < numBuffers; b++) {
14304 items[k + b] = colBuffers[b][l];
14305 }
14306 }
14307 }
14308 }
14309 }
14310
14311 return {
14312 width: width,
14313 height: height,
14314 items: items
14315 };
14316 };
14317 return Transform;
14318 })();
14319
14320 // Section 3.8.2 Irreversible 9-7 filter
14321 var IrreversibleTransform = (function IrreversibleTransformClosure() {
14322 function IrreversibleTransform() {
14323 Transform.call(this);
14324 }
14325
14326 IrreversibleTransform.prototype = Object.create(Transform.prototype);
14327 IrreversibleTransform.prototype.filter =
14328 function irreversibleTransformFilter(x, offset, length) {
14329 var len = length >> 1;
14330 offset = offset | 0;
14331 var j, n, current, next;
14332
14333 var alpha = -1.586134342059924;
14334 var beta = -0.052980118572961;
14335 var gamma = 0.882911075530934;
14336 var delta = 0.443506852043971;
14337 var K = 1.230174104914001;
14338 var K_ = 1 / K;
14339
14340 // step 1 is combined with step 3
14341
14342 // step 2
14343 j = offset - 3;
14344 for (n = len + 4; n--; j += 2) {
14345 x[j] *= K_;
14346 }
14347
14348 // step 1 & 3
14349 j = offset - 2;
14350 current = delta * x[j -1];
14351 for (n = len + 3; n--; j += 2) {
14352 next = delta * x[j + 1];
14353 x[j] = K * x[j] - current - next;
14354 if (n--) {
14355 j += 2;
14356 current = delta * x[j + 1];
14357 x[j] = K * x[j] - current - next;
14358 } else {
14359 break;
14360 }
14361 }
14362
14363 // step 4
14364 j = offset - 1;
14365 current = gamma * x[j - 1];
14366 for (n = len + 2; n--; j += 2) {
14367 next = gamma * x[j + 1];
14368 x[j] -= current + next;
14369 if (n--) {
14370 j += 2;
14371 current = gamma * x[j + 1];
14372 x[j] -= current + next;
14373 } else {
14374 break;
14375 }
14376 }
14377
14378 // step 5
14379 j = offset;
14380 current = beta * x[j - 1];
14381 for (n = len + 1; n--; j += 2) {
14382 next = beta * x[j + 1];
14383 x[j] -= current + next;
14384 if (n--) {
14385 j += 2;
14386 current = beta * x[j + 1];
14387 x[j] -= current + next;
14388 } else {
14389 break;
14390 }
14391 }
14392
14393 // step 6
14394 if (len !== 0) {
14395 j = offset + 1;
14396 current = alpha * x[j - 1];
14397 for (n = len; n--; j += 2) {
14398 next = alpha * x[j + 1];
14399 x[j] -= current + next;
14400 if (n--) {
14401 j += 2;
14402 current = alpha * x[j + 1];
14403 x[j] -= current + next;
14404 } else {
14405 break;
14406 }
14407 }
14408 }
14409 };
14410
14411 return IrreversibleTransform;
14412 })();
14413
14414 // Section 3.8.1 Reversible 5-3 filter
14415 var ReversibleTransform = (function ReversibleTransformClosure() {
14416 function ReversibleTransform() {
14417 Transform.call(this);
14418 }
14419
14420 ReversibleTransform.prototype = Object.create(Transform.prototype);
14421 ReversibleTransform.prototype.filter =
14422 function reversibleTransformFilter(x, offset, length) {
14423 var len = length >> 1;
14424 offset = offset | 0;
14425 var j, n;
14426
14427 for (j = offset, n = len + 1; n--; j += 2) {
14428 x[j] -= (x[j - 1] + x[j + 1] + 2) >> 2;
14429 }
14430
14431 for (j = offset + 1, n = len; n--; j += 2) {
14432 x[j] += (x[j - 1] + x[j + 1]) >> 1;
14433 }
14434 };
14435
14436 return ReversibleTransform;
14437 })();
14438
14439 return JpxImage;
14440})();
14441
14442exports.JpxImage = JpxImage;
14443}));
14444
14445
14446(function (root, factory) {
14447 {
14448 factory((root.pdfjsCoreMetrics = {}), root.pdfjsSharedUtil);
14449 }
14450}(this, function (exports, sharedUtil) {
14451var getLookupTableFactory = sharedUtil.getLookupTableFactory;
14452
14453// The Metrics object contains glyph widths (in glyph space units).
14454// As per PDF spec, for most fonts (Type 3 being an exception) a glyph
14455// space unit corresponds to 1/1000th of text space unit.
14456var getMetrics = getLookupTableFactory(function (t) {
14457 t['Courier'] = 600;
14458 t['Courier-Bold'] = 600;
14459 t['Courier-BoldOblique'] = 600;
14460 t['Courier-Oblique'] = 600;
14461 t['Helvetica'] = getLookupTableFactory(function (t) {
14462 t['space'] = 278;
14463 t['exclam'] = 278;
14464 t['quotedbl'] = 355;
14465 t['numbersign'] = 556;
14466 t['dollar'] = 556;
14467 t['percent'] = 889;
14468 t['ampersand'] = 667;
14469 t['quoteright'] = 222;
14470 t['parenleft'] = 333;
14471 t['parenright'] = 333;
14472 t['asterisk'] = 389;
14473 t['plus'] = 584;
14474 t['comma'] = 278;
14475 t['hyphen'] = 333;
14476 t['period'] = 278;
14477 t['slash'] = 278;
14478 t['zero'] = 556;
14479 t['one'] = 556;
14480 t['two'] = 556;
14481 t['three'] = 556;
14482 t['four'] = 556;
14483 t['five'] = 556;
14484 t['six'] = 556;
14485 t['seven'] = 556;
14486 t['eight'] = 556;
14487 t['nine'] = 556;
14488 t['colon'] = 278;
14489 t['semicolon'] = 278;
14490 t['less'] = 584;
14491 t['equal'] = 584;
14492 t['greater'] = 584;
14493 t['question'] = 556;
14494 t['at'] = 1015;
14495 t['A'] = 667;
14496 t['B'] = 667;
14497 t['C'] = 722;
14498 t['D'] = 722;
14499 t['E'] = 667;
14500 t['F'] = 611;
14501 t['G'] = 778;
14502 t['H'] = 722;
14503 t['I'] = 278;
14504 t['J'] = 500;
14505 t['K'] = 667;
14506 t['L'] = 556;
14507 t['M'] = 833;
14508 t['N'] = 722;
14509 t['O'] = 778;
14510 t['P'] = 667;
14511 t['Q'] = 778;
14512 t['R'] = 722;
14513 t['S'] = 667;
14514 t['T'] = 611;
14515 t['U'] = 722;
14516 t['V'] = 667;
14517 t['W'] = 944;
14518 t['X'] = 667;
14519 t['Y'] = 667;
14520 t['Z'] = 611;
14521 t['bracketleft'] = 278;
14522 t['backslash'] = 278;
14523 t['bracketright'] = 278;
14524 t['asciicircum'] = 469;
14525 t['underscore'] = 556;
14526 t['quoteleft'] = 222;
14527 t['a'] = 556;
14528 t['b'] = 556;
14529 t['c'] = 500;
14530 t['d'] = 556;
14531 t['e'] = 556;
14532 t['f'] = 278;
14533 t['g'] = 556;
14534 t['h'] = 556;
14535 t['i'] = 222;
14536 t['j'] = 222;
14537 t['k'] = 500;
14538 t['l'] = 222;
14539 t['m'] = 833;
14540 t['n'] = 556;
14541 t['o'] = 556;
14542 t['p'] = 556;
14543 t['q'] = 556;
14544 t['r'] = 333;
14545 t['s'] = 500;
14546 t['t'] = 278;
14547 t['u'] = 556;
14548 t['v'] = 500;
14549 t['w'] = 722;
14550 t['x'] = 500;
14551 t['y'] = 500;
14552 t['z'] = 500;
14553 t['braceleft'] = 334;
14554 t['bar'] = 260;
14555 t['braceright'] = 334;
14556 t['asciitilde'] = 584;
14557 t['exclamdown'] = 333;
14558 t['cent'] = 556;
14559 t['sterling'] = 556;
14560 t['fraction'] = 167;
14561 t['yen'] = 556;
14562 t['florin'] = 556;
14563 t['section'] = 556;
14564 t['currency'] = 556;
14565 t['quotesingle'] = 191;
14566 t['quotedblleft'] = 333;
14567 t['guillemotleft'] = 556;
14568 t['guilsinglleft'] = 333;
14569 t['guilsinglright'] = 333;
14570 t['fi'] = 500;
14571 t['fl'] = 500;
14572 t['endash'] = 556;
14573 t['dagger'] = 556;
14574 t['daggerdbl'] = 556;
14575 t['periodcentered'] = 278;
14576 t['paragraph'] = 537;
14577 t['bullet'] = 350;
14578 t['quotesinglbase'] = 222;
14579 t['quotedblbase'] = 333;
14580 t['quotedblright'] = 333;
14581 t['guillemotright'] = 556;
14582 t['ellipsis'] = 1000;
14583 t['perthousand'] = 1000;
14584 t['questiondown'] = 611;
14585 t['grave'] = 333;
14586 t['acute'] = 333;
14587 t['circumflex'] = 333;
14588 t['tilde'] = 333;
14589 t['macron'] = 333;
14590 t['breve'] = 333;
14591 t['dotaccent'] = 333;
14592 t['dieresis'] = 333;
14593 t['ring'] = 333;
14594 t['cedilla'] = 333;
14595 t['hungarumlaut'] = 333;
14596 t['ogonek'] = 333;
14597 t['caron'] = 333;
14598 t['emdash'] = 1000;
14599 t['AE'] = 1000;
14600 t['ordfeminine'] = 370;
14601 t['Lslash'] = 556;
14602 t['Oslash'] = 778;
14603 t['OE'] = 1000;
14604 t['ordmasculine'] = 365;
14605 t['ae'] = 889;
14606 t['dotlessi'] = 278;
14607 t['lslash'] = 222;
14608 t['oslash'] = 611;
14609 t['oe'] = 944;
14610 t['germandbls'] = 611;
14611 t['Idieresis'] = 278;
14612 t['eacute'] = 556;
14613 t['abreve'] = 556;
14614 t['uhungarumlaut'] = 556;
14615 t['ecaron'] = 556;
14616 t['Ydieresis'] = 667;
14617 t['divide'] = 584;
14618 t['Yacute'] = 667;
14619 t['Acircumflex'] = 667;
14620 t['aacute'] = 556;
14621 t['Ucircumflex'] = 722;
14622 t['yacute'] = 500;
14623 t['scommaaccent'] = 500;
14624 t['ecircumflex'] = 556;
14625 t['Uring'] = 722;
14626 t['Udieresis'] = 722;
14627 t['aogonek'] = 556;
14628 t['Uacute'] = 722;
14629 t['uogonek'] = 556;
14630 t['Edieresis'] = 667;
14631 t['Dcroat'] = 722;
14632 t['commaaccent'] = 250;
14633 t['copyright'] = 737;
14634 t['Emacron'] = 667;
14635 t['ccaron'] = 500;
14636 t['aring'] = 556;
14637 t['Ncommaaccent'] = 722;
14638 t['lacute'] = 222;
14639 t['agrave'] = 556;
14640 t['Tcommaaccent'] = 611;
14641 t['Cacute'] = 722;
14642 t['atilde'] = 556;
14643 t['Edotaccent'] = 667;
14644 t['scaron'] = 500;
14645 t['scedilla'] = 500;
14646 t['iacute'] = 278;
14647 t['lozenge'] = 471;
14648 t['Rcaron'] = 722;
14649 t['Gcommaaccent'] = 778;
14650 t['ucircumflex'] = 556;
14651 t['acircumflex'] = 556;
14652 t['Amacron'] = 667;
14653 t['rcaron'] = 333;
14654 t['ccedilla'] = 500;
14655 t['Zdotaccent'] = 611;
14656 t['Thorn'] = 667;
14657 t['Omacron'] = 778;
14658 t['Racute'] = 722;
14659 t['Sacute'] = 667;
14660 t['dcaron'] = 643;
14661 t['Umacron'] = 722;
14662 t['uring'] = 556;
14663 t['threesuperior'] = 333;
14664 t['Ograve'] = 778;
14665 t['Agrave'] = 667;
14666 t['Abreve'] = 667;
14667 t['multiply'] = 584;
14668 t['uacute'] = 556;
14669 t['Tcaron'] = 611;
14670 t['partialdiff'] = 476;
14671 t['ydieresis'] = 500;
14672 t['Nacute'] = 722;
14673 t['icircumflex'] = 278;
14674 t['Ecircumflex'] = 667;
14675 t['adieresis'] = 556;
14676 t['edieresis'] = 556;
14677 t['cacute'] = 500;
14678 t['nacute'] = 556;
14679 t['umacron'] = 556;
14680 t['Ncaron'] = 722;
14681 t['Iacute'] = 278;
14682 t['plusminus'] = 584;
14683 t['brokenbar'] = 260;
14684 t['registered'] = 737;
14685 t['Gbreve'] = 778;
14686 t['Idotaccent'] = 278;
14687 t['summation'] = 600;
14688 t['Egrave'] = 667;
14689 t['racute'] = 333;
14690 t['omacron'] = 556;
14691 t['Zacute'] = 611;
14692 t['Zcaron'] = 611;
14693 t['greaterequal'] = 549;
14694 t['Eth'] = 722;
14695 t['Ccedilla'] = 722;
14696 t['lcommaaccent'] = 222;
14697 t['tcaron'] = 317;
14698 t['eogonek'] = 556;
14699 t['Uogonek'] = 722;
14700 t['Aacute'] = 667;
14701 t['Adieresis'] = 667;
14702 t['egrave'] = 556;
14703 t['zacute'] = 500;
14704 t['iogonek'] = 222;
14705 t['Oacute'] = 778;
14706 t['oacute'] = 556;
14707 t['amacron'] = 556;
14708 t['sacute'] = 500;
14709 t['idieresis'] = 278;
14710 t['Ocircumflex'] = 778;
14711 t['Ugrave'] = 722;
14712 t['Delta'] = 612;
14713 t['thorn'] = 556;
14714 t['twosuperior'] = 333;
14715 t['Odieresis'] = 778;
14716 t['mu'] = 556;
14717 t['igrave'] = 278;
14718 t['ohungarumlaut'] = 556;
14719 t['Eogonek'] = 667;
14720 t['dcroat'] = 556;
14721 t['threequarters'] = 834;
14722 t['Scedilla'] = 667;
14723 t['lcaron'] = 299;
14724 t['Kcommaaccent'] = 667;
14725 t['Lacute'] = 556;
14726 t['trademark'] = 1000;
14727 t['edotaccent'] = 556;
14728 t['Igrave'] = 278;
14729 t['Imacron'] = 278;
14730 t['Lcaron'] = 556;
14731 t['onehalf'] = 834;
14732 t['lessequal'] = 549;
14733 t['ocircumflex'] = 556;
14734 t['ntilde'] = 556;
14735 t['Uhungarumlaut'] = 722;
14736 t['Eacute'] = 667;
14737 t['emacron'] = 556;
14738 t['gbreve'] = 556;
14739 t['onequarter'] = 834;
14740 t['Scaron'] = 667;
14741 t['Scommaaccent'] = 667;
14742 t['Ohungarumlaut'] = 778;
14743 t['degree'] = 400;
14744 t['ograve'] = 556;
14745 t['Ccaron'] = 722;
14746 t['ugrave'] = 556;
14747 t['radical'] = 453;
14748 t['Dcaron'] = 722;
14749 t['rcommaaccent'] = 333;
14750 t['Ntilde'] = 722;
14751 t['otilde'] = 556;
14752 t['Rcommaaccent'] = 722;
14753 t['Lcommaaccent'] = 556;
14754 t['Atilde'] = 667;
14755 t['Aogonek'] = 667;
14756 t['Aring'] = 667;
14757 t['Otilde'] = 778;
14758 t['zdotaccent'] = 500;
14759 t['Ecaron'] = 667;
14760 t['Iogonek'] = 278;
14761 t['kcommaaccent'] = 500;
14762 t['minus'] = 584;
14763 t['Icircumflex'] = 278;
14764 t['ncaron'] = 556;
14765 t['tcommaaccent'] = 278;
14766 t['logicalnot'] = 584;
14767 t['odieresis'] = 556;
14768 t['udieresis'] = 556;
14769 t['notequal'] = 549;
14770 t['gcommaaccent'] = 556;
14771 t['eth'] = 556;
14772 t['zcaron'] = 500;
14773 t['ncommaaccent'] = 556;
14774 t['onesuperior'] = 333;
14775 t['imacron'] = 278;
14776 t['Euro'] = 556;
14777 });
14778 t['Helvetica-Bold'] = getLookupTableFactory(function (t) {
14779 t['space'] = 278;
14780 t['exclam'] = 333;
14781 t['quotedbl'] = 474;
14782 t['numbersign'] = 556;
14783 t['dollar'] = 556;
14784 t['percent'] = 889;
14785 t['ampersand'] = 722;
14786 t['quoteright'] = 278;
14787 t['parenleft'] = 333;
14788 t['parenright'] = 333;
14789 t['asterisk'] = 389;
14790 t['plus'] = 584;
14791 t['comma'] = 278;
14792 t['hyphen'] = 333;
14793 t['period'] = 278;
14794 t['slash'] = 278;
14795 t['zero'] = 556;
14796 t['one'] = 556;
14797 t['two'] = 556;
14798 t['three'] = 556;
14799 t['four'] = 556;
14800 t['five'] = 556;
14801 t['six'] = 556;
14802 t['seven'] = 556;
14803 t['eight'] = 556;
14804 t['nine'] = 556;
14805 t['colon'] = 333;
14806 t['semicolon'] = 333;
14807 t['less'] = 584;
14808 t['equal'] = 584;
14809 t['greater'] = 584;
14810 t['question'] = 611;
14811 t['at'] = 975;
14812 t['A'] = 722;
14813 t['B'] = 722;
14814 t['C'] = 722;
14815 t['D'] = 722;
14816 t['E'] = 667;
14817 t['F'] = 611;
14818 t['G'] = 778;
14819 t['H'] = 722;
14820 t['I'] = 278;
14821 t['J'] = 556;
14822 t['K'] = 722;
14823 t['L'] = 611;
14824 t['M'] = 833;
14825 t['N'] = 722;
14826 t['O'] = 778;
14827 t['P'] = 667;
14828 t['Q'] = 778;
14829 t['R'] = 722;
14830 t['S'] = 667;
14831 t['T'] = 611;
14832 t['U'] = 722;
14833 t['V'] = 667;
14834 t['W'] = 944;
14835 t['X'] = 667;
14836 t['Y'] = 667;
14837 t['Z'] = 611;
14838 t['bracketleft'] = 333;
14839 t['backslash'] = 278;
14840 t['bracketright'] = 333;
14841 t['asciicircum'] = 584;
14842 t['underscore'] = 556;
14843 t['quoteleft'] = 278;
14844 t['a'] = 556;
14845 t['b'] = 611;
14846 t['c'] = 556;
14847 t['d'] = 611;
14848 t['e'] = 556;
14849 t['f'] = 333;
14850 t['g'] = 611;
14851 t['h'] = 611;
14852 t['i'] = 278;
14853 t['j'] = 278;
14854 t['k'] = 556;
14855 t['l'] = 278;
14856 t['m'] = 889;
14857 t['n'] = 611;
14858 t['o'] = 611;
14859 t['p'] = 611;
14860 t['q'] = 611;
14861 t['r'] = 389;
14862 t['s'] = 556;
14863 t['t'] = 333;
14864 t['u'] = 611;
14865 t['v'] = 556;
14866 t['w'] = 778;
14867 t['x'] = 556;
14868 t['y'] = 556;
14869 t['z'] = 500;
14870 t['braceleft'] = 389;
14871 t['bar'] = 280;
14872 t['braceright'] = 389;
14873 t['asciitilde'] = 584;
14874 t['exclamdown'] = 333;
14875 t['cent'] = 556;
14876 t['sterling'] = 556;
14877 t['fraction'] = 167;
14878 t['yen'] = 556;
14879 t['florin'] = 556;
14880 t['section'] = 556;
14881 t['currency'] = 556;
14882 t['quotesingle'] = 238;
14883 t['quotedblleft'] = 500;
14884 t['guillemotleft'] = 556;
14885 t['guilsinglleft'] = 333;
14886 t['guilsinglright'] = 333;
14887 t['fi'] = 611;
14888 t['fl'] = 611;
14889 t['endash'] = 556;
14890 t['dagger'] = 556;
14891 t['daggerdbl'] = 556;
14892 t['periodcentered'] = 278;
14893 t['paragraph'] = 556;
14894 t['bullet'] = 350;
14895 t['quotesinglbase'] = 278;
14896 t['quotedblbase'] = 500;
14897 t['quotedblright'] = 500;
14898 t['guillemotright'] = 556;
14899 t['ellipsis'] = 1000;
14900 t['perthousand'] = 1000;
14901 t['questiondown'] = 611;
14902 t['grave'] = 333;
14903 t['acute'] = 333;
14904 t['circumflex'] = 333;
14905 t['tilde'] = 333;
14906 t['macron'] = 333;
14907 t['breve'] = 333;
14908 t['dotaccent'] = 333;
14909 t['dieresis'] = 333;
14910 t['ring'] = 333;
14911 t['cedilla'] = 333;
14912 t['hungarumlaut'] = 333;
14913 t['ogonek'] = 333;
14914 t['caron'] = 333;
14915 t['emdash'] = 1000;
14916 t['AE'] = 1000;
14917 t['ordfeminine'] = 370;
14918 t['Lslash'] = 611;
14919 t['Oslash'] = 778;
14920 t['OE'] = 1000;
14921 t['ordmasculine'] = 365;
14922 t['ae'] = 889;
14923 t['dotlessi'] = 278;
14924 t['lslash'] = 278;
14925 t['oslash'] = 611;
14926 t['oe'] = 944;
14927 t['germandbls'] = 611;
14928 t['Idieresis'] = 278;
14929 t['eacute'] = 556;
14930 t['abreve'] = 556;
14931 t['uhungarumlaut'] = 611;
14932 t['ecaron'] = 556;
14933 t['Ydieresis'] = 667;
14934 t['divide'] = 584;
14935 t['Yacute'] = 667;
14936 t['Acircumflex'] = 722;
14937 t['aacute'] = 556;
14938 t['Ucircumflex'] = 722;
14939 t['yacute'] = 556;
14940 t['scommaaccent'] = 556;
14941 t['ecircumflex'] = 556;
14942 t['Uring'] = 722;
14943 t['Udieresis'] = 722;
14944 t['aogonek'] = 556;
14945 t['Uacute'] = 722;
14946 t['uogonek'] = 611;
14947 t['Edieresis'] = 667;
14948 t['Dcroat'] = 722;
14949 t['commaaccent'] = 250;
14950 t['copyright'] = 737;
14951 t['Emacron'] = 667;
14952 t['ccaron'] = 556;
14953 t['aring'] = 556;
14954 t['Ncommaaccent'] = 722;
14955 t['lacute'] = 278;
14956 t['agrave'] = 556;
14957 t['Tcommaaccent'] = 611;
14958 t['Cacute'] = 722;
14959 t['atilde'] = 556;
14960 t['Edotaccent'] = 667;
14961 t['scaron'] = 556;
14962 t['scedilla'] = 556;
14963 t['iacute'] = 278;
14964 t['lozenge'] = 494;
14965 t['Rcaron'] = 722;
14966 t['Gcommaaccent'] = 778;
14967 t['ucircumflex'] = 611;
14968 t['acircumflex'] = 556;
14969 t['Amacron'] = 722;
14970 t['rcaron'] = 389;
14971 t['ccedilla'] = 556;
14972 t['Zdotaccent'] = 611;
14973 t['Thorn'] = 667;
14974 t['Omacron'] = 778;
14975 t['Racute'] = 722;
14976 t['Sacute'] = 667;
14977 t['dcaron'] = 743;
14978 t['Umacron'] = 722;
14979 t['uring'] = 611;
14980 t['threesuperior'] = 333;
14981 t['Ograve'] = 778;
14982 t['Agrave'] = 722;
14983 t['Abreve'] = 722;
14984 t['multiply'] = 584;
14985 t['uacute'] = 611;
14986 t['Tcaron'] = 611;
14987 t['partialdiff'] = 494;
14988 t['ydieresis'] = 556;
14989 t['Nacute'] = 722;
14990 t['icircumflex'] = 278;
14991 t['Ecircumflex'] = 667;
14992 t['adieresis'] = 556;
14993 t['edieresis'] = 556;
14994 t['cacute'] = 556;
14995 t['nacute'] = 611;
14996 t['umacron'] = 611;
14997 t['Ncaron'] = 722;
14998 t['Iacute'] = 278;
14999 t['plusminus'] = 584;
15000 t['brokenbar'] = 280;
15001 t['registered'] = 737;
15002 t['Gbreve'] = 778;
15003 t['Idotaccent'] = 278;
15004 t['summation'] = 600;
15005 t['Egrave'] = 667;
15006 t['racute'] = 389;
15007 t['omacron'] = 611;
15008 t['Zacute'] = 611;
15009 t['Zcaron'] = 611;
15010 t['greaterequal'] = 549;
15011 t['Eth'] = 722;
15012 t['Ccedilla'] = 722;
15013 t['lcommaaccent'] = 278;
15014 t['tcaron'] = 389;
15015 t['eogonek'] = 556;
15016 t['Uogonek'] = 722;
15017 t['Aacute'] = 722;
15018 t['Adieresis'] = 722;
15019 t['egrave'] = 556;
15020 t['zacute'] = 500;
15021 t['iogonek'] = 278;
15022 t['Oacute'] = 778;
15023 t['oacute'] = 611;
15024 t['amacron'] = 556;
15025 t['sacute'] = 556;
15026 t['idieresis'] = 278;
15027 t['Ocircumflex'] = 778;
15028 t['Ugrave'] = 722;
15029 t['Delta'] = 612;
15030 t['thorn'] = 611;
15031 t['twosuperior'] = 333;
15032 t['Odieresis'] = 778;
15033 t['mu'] = 611;
15034 t['igrave'] = 278;
15035 t['ohungarumlaut'] = 611;
15036 t['Eogonek'] = 667;
15037 t['dcroat'] = 611;
15038 t['threequarters'] = 834;
15039 t['Scedilla'] = 667;
15040 t['lcaron'] = 400;
15041 t['Kcommaaccent'] = 722;
15042 t['Lacute'] = 611;
15043 t['trademark'] = 1000;
15044 t['edotaccent'] = 556;
15045 t['Igrave'] = 278;
15046 t['Imacron'] = 278;
15047 t['Lcaron'] = 611;
15048 t['onehalf'] = 834;
15049 t['lessequal'] = 549;
15050 t['ocircumflex'] = 611;
15051 t['ntilde'] = 611;
15052 t['Uhungarumlaut'] = 722;
15053 t['Eacute'] = 667;
15054 t['emacron'] = 556;
15055 t['gbreve'] = 611;
15056 t['onequarter'] = 834;
15057 t['Scaron'] = 667;
15058 t['Scommaaccent'] = 667;
15059 t['Ohungarumlaut'] = 778;
15060 t['degree'] = 400;
15061 t['ograve'] = 611;
15062 t['Ccaron'] = 722;
15063 t['ugrave'] = 611;
15064 t['radical'] = 549;
15065 t['Dcaron'] = 722;
15066 t['rcommaaccent'] = 389;
15067 t['Ntilde'] = 722;
15068 t['otilde'] = 611;
15069 t['Rcommaaccent'] = 722;
15070 t['Lcommaaccent'] = 611;
15071 t['Atilde'] = 722;
15072 t['Aogonek'] = 722;
15073 t['Aring'] = 722;
15074 t['Otilde'] = 778;
15075 t['zdotaccent'] = 500;
15076 t['Ecaron'] = 667;
15077 t['Iogonek'] = 278;
15078 t['kcommaaccent'] = 556;
15079 t['minus'] = 584;
15080 t['Icircumflex'] = 278;
15081 t['ncaron'] = 611;
15082 t['tcommaaccent'] = 333;
15083 t['logicalnot'] = 584;
15084 t['odieresis'] = 611;
15085 t['udieresis'] = 611;
15086 t['notequal'] = 549;
15087 t['gcommaaccent'] = 611;
15088 t['eth'] = 611;
15089 t['zcaron'] = 500;
15090 t['ncommaaccent'] = 611;
15091 t['onesuperior'] = 333;
15092 t['imacron'] = 278;
15093 t['Euro'] = 556;
15094 });
15095 t['Helvetica-BoldOblique'] = getLookupTableFactory(function (t) {
15096 t['space'] = 278;
15097 t['exclam'] = 333;
15098 t['quotedbl'] = 474;
15099 t['numbersign'] = 556;
15100 t['dollar'] = 556;
15101 t['percent'] = 889;
15102 t['ampersand'] = 722;
15103 t['quoteright'] = 278;
15104 t['parenleft'] = 333;
15105 t['parenright'] = 333;
15106 t['asterisk'] = 389;
15107 t['plus'] = 584;
15108 t['comma'] = 278;
15109 t['hyphen'] = 333;
15110 t['period'] = 278;
15111 t['slash'] = 278;
15112 t['zero'] = 556;
15113 t['one'] = 556;
15114 t['two'] = 556;
15115 t['three'] = 556;
15116 t['four'] = 556;
15117 t['five'] = 556;
15118 t['six'] = 556;
15119 t['seven'] = 556;
15120 t['eight'] = 556;
15121 t['nine'] = 556;
15122 t['colon'] = 333;
15123 t['semicolon'] = 333;
15124 t['less'] = 584;
15125 t['equal'] = 584;
15126 t['greater'] = 584;
15127 t['question'] = 611;
15128 t['at'] = 975;
15129 t['A'] = 722;
15130 t['B'] = 722;
15131 t['C'] = 722;
15132 t['D'] = 722;
15133 t['E'] = 667;
15134 t['F'] = 611;
15135 t['G'] = 778;
15136 t['H'] = 722;
15137 t['I'] = 278;
15138 t['J'] = 556;
15139 t['K'] = 722;
15140 t['L'] = 611;
15141 t['M'] = 833;
15142 t['N'] = 722;
15143 t['O'] = 778;
15144 t['P'] = 667;
15145 t['Q'] = 778;
15146 t['R'] = 722;
15147 t['S'] = 667;
15148 t['T'] = 611;
15149 t['U'] = 722;
15150 t['V'] = 667;
15151 t['W'] = 944;
15152 t['X'] = 667;
15153 t['Y'] = 667;
15154 t['Z'] = 611;
15155 t['bracketleft'] = 333;
15156 t['backslash'] = 278;
15157 t['bracketright'] = 333;
15158 t['asciicircum'] = 584;
15159 t['underscore'] = 556;
15160 t['quoteleft'] = 278;
15161 t['a'] = 556;
15162 t['b'] = 611;
15163 t['c'] = 556;
15164 t['d'] = 611;
15165 t['e'] = 556;
15166 t['f'] = 333;
15167 t['g'] = 611;
15168 t['h'] = 611;
15169 t['i'] = 278;
15170 t['j'] = 278;
15171 t['k'] = 556;
15172 t['l'] = 278;
15173 t['m'] = 889;
15174 t['n'] = 611;
15175 t['o'] = 611;
15176 t['p'] = 611;
15177 t['q'] = 611;
15178 t['r'] = 389;
15179 t['s'] = 556;
15180 t['t'] = 333;
15181 t['u'] = 611;
15182 t['v'] = 556;
15183 t['w'] = 778;
15184 t['x'] = 556;
15185 t['y'] = 556;
15186 t['z'] = 500;
15187 t['braceleft'] = 389;
15188 t['bar'] = 280;
15189 t['braceright'] = 389;
15190 t['asciitilde'] = 584;
15191 t['exclamdown'] = 333;
15192 t['cent'] = 556;
15193 t['sterling'] = 556;
15194 t['fraction'] = 167;
15195 t['yen'] = 556;
15196 t['florin'] = 556;
15197 t['section'] = 556;
15198 t['currency'] = 556;
15199 t['quotesingle'] = 238;
15200 t['quotedblleft'] = 500;
15201 t['guillemotleft'] = 556;
15202 t['guilsinglleft'] = 333;
15203 t['guilsinglright'] = 333;
15204 t['fi'] = 611;
15205 t['fl'] = 611;
15206 t['endash'] = 556;
15207 t['dagger'] = 556;
15208 t['daggerdbl'] = 556;
15209 t['periodcentered'] = 278;
15210 t['paragraph'] = 556;
15211 t['bullet'] = 350;
15212 t['quotesinglbase'] = 278;
15213 t['quotedblbase'] = 500;
15214 t['quotedblright'] = 500;
15215 t['guillemotright'] = 556;
15216 t['ellipsis'] = 1000;
15217 t['perthousand'] = 1000;
15218 t['questiondown'] = 611;
15219 t['grave'] = 333;
15220 t['acute'] = 333;
15221 t['circumflex'] = 333;
15222 t['tilde'] = 333;
15223 t['macron'] = 333;
15224 t['breve'] = 333;
15225 t['dotaccent'] = 333;
15226 t['dieresis'] = 333;
15227 t['ring'] = 333;
15228 t['cedilla'] = 333;
15229 t['hungarumlaut'] = 333;
15230 t['ogonek'] = 333;
15231 t['caron'] = 333;
15232 t['emdash'] = 1000;
15233 t['AE'] = 1000;
15234 t['ordfeminine'] = 370;
15235 t['Lslash'] = 611;
15236 t['Oslash'] = 778;
15237 t['OE'] = 1000;
15238 t['ordmasculine'] = 365;
15239 t['ae'] = 889;
15240 t['dotlessi'] = 278;
15241 t['lslash'] = 278;
15242 t['oslash'] = 611;
15243 t['oe'] = 944;
15244 t['germandbls'] = 611;
15245 t['Idieresis'] = 278;
15246 t['eacute'] = 556;
15247 t['abreve'] = 556;
15248 t['uhungarumlaut'] = 611;
15249 t['ecaron'] = 556;
15250 t['Ydieresis'] = 667;
15251 t['divide'] = 584;
15252 t['Yacute'] = 667;
15253 t['Acircumflex'] = 722;
15254 t['aacute'] = 556;
15255 t['Ucircumflex'] = 722;
15256 t['yacute'] = 556;
15257 t['scommaaccent'] = 556;
15258 t['ecircumflex'] = 556;
15259 t['Uring'] = 722;
15260 t['Udieresis'] = 722;
15261 t['aogonek'] = 556;
15262 t['Uacute'] = 722;
15263 t['uogonek'] = 611;
15264 t['Edieresis'] = 667;
15265 t['Dcroat'] = 722;
15266 t['commaaccent'] = 250;
15267 t['copyright'] = 737;
15268 t['Emacron'] = 667;
15269 t['ccaron'] = 556;
15270 t['aring'] = 556;
15271 t['Ncommaaccent'] = 722;
15272 t['lacute'] = 278;
15273 t['agrave'] = 556;
15274 t['Tcommaaccent'] = 611;
15275 t['Cacute'] = 722;
15276 t['atilde'] = 556;
15277 t['Edotaccent'] = 667;
15278 t['scaron'] = 556;
15279 t['scedilla'] = 556;
15280 t['iacute'] = 278;
15281 t['lozenge'] = 494;
15282 t['Rcaron'] = 722;
15283 t['Gcommaaccent'] = 778;
15284 t['ucircumflex'] = 611;
15285 t['acircumflex'] = 556;
15286 t['Amacron'] = 722;
15287 t['rcaron'] = 389;
15288 t['ccedilla'] = 556;
15289 t['Zdotaccent'] = 611;
15290 t['Thorn'] = 667;
15291 t['Omacron'] = 778;
15292 t['Racute'] = 722;
15293 t['Sacute'] = 667;
15294 t['dcaron'] = 743;
15295 t['Umacron'] = 722;
15296 t['uring'] = 611;
15297 t['threesuperior'] = 333;
15298 t['Ograve'] = 778;
15299 t['Agrave'] = 722;
15300 t['Abreve'] = 722;
15301 t['multiply'] = 584;
15302 t['uacute'] = 611;
15303 t['Tcaron'] = 611;
15304 t['partialdiff'] = 494;
15305 t['ydieresis'] = 556;
15306 t['Nacute'] = 722;
15307 t['icircumflex'] = 278;
15308 t['Ecircumflex'] = 667;
15309 t['adieresis'] = 556;
15310 t['edieresis'] = 556;
15311 t['cacute'] = 556;
15312 t['nacute'] = 611;
15313 t['umacron'] = 611;
15314 t['Ncaron'] = 722;
15315 t['Iacute'] = 278;
15316 t['plusminus'] = 584;
15317 t['brokenbar'] = 280;
15318 t['registered'] = 737;
15319 t['Gbreve'] = 778;
15320 t['Idotaccent'] = 278;
15321 t['summation'] = 600;
15322 t['Egrave'] = 667;
15323 t['racute'] = 389;
15324 t['omacron'] = 611;
15325 t['Zacute'] = 611;
15326 t['Zcaron'] = 611;
15327 t['greaterequal'] = 549;
15328 t['Eth'] = 722;
15329 t['Ccedilla'] = 722;
15330 t['lcommaaccent'] = 278;
15331 t['tcaron'] = 389;
15332 t['eogonek'] = 556;
15333 t['Uogonek'] = 722;
15334 t['Aacute'] = 722;
15335 t['Adieresis'] = 722;
15336 t['egrave'] = 556;
15337 t['zacute'] = 500;
15338 t['iogonek'] = 278;
15339 t['Oacute'] = 778;
15340 t['oacute'] = 611;
15341 t['amacron'] = 556;
15342 t['sacute'] = 556;
15343 t['idieresis'] = 278;
15344 t['Ocircumflex'] = 778;
15345 t['Ugrave'] = 722;
15346 t['Delta'] = 612;
15347 t['thorn'] = 611;
15348 t['twosuperior'] = 333;
15349 t['Odieresis'] = 778;
15350 t['mu'] = 611;
15351 t['igrave'] = 278;
15352 t['ohungarumlaut'] = 611;
15353 t['Eogonek'] = 667;
15354 t['dcroat'] = 611;
15355 t['threequarters'] = 834;
15356 t['Scedilla'] = 667;
15357 t['lcaron'] = 400;
15358 t['Kcommaaccent'] = 722;
15359 t['Lacute'] = 611;
15360 t['trademark'] = 1000;
15361 t['edotaccent'] = 556;
15362 t['Igrave'] = 278;
15363 t['Imacron'] = 278;
15364 t['Lcaron'] = 611;
15365 t['onehalf'] = 834;
15366 t['lessequal'] = 549;
15367 t['ocircumflex'] = 611;
15368 t['ntilde'] = 611;
15369 t['Uhungarumlaut'] = 722;
15370 t['Eacute'] = 667;
15371 t['emacron'] = 556;
15372 t['gbreve'] = 611;
15373 t['onequarter'] = 834;
15374 t['Scaron'] = 667;
15375 t['Scommaaccent'] = 667;
15376 t['Ohungarumlaut'] = 778;
15377 t['degree'] = 400;
15378 t['ograve'] = 611;
15379 t['Ccaron'] = 722;
15380 t['ugrave'] = 611;
15381 t['radical'] = 549;
15382 t['Dcaron'] = 722;
15383 t['rcommaaccent'] = 389;
15384 t['Ntilde'] = 722;
15385 t['otilde'] = 611;
15386 t['Rcommaaccent'] = 722;
15387 t['Lcommaaccent'] = 611;
15388 t['Atilde'] = 722;
15389 t['Aogonek'] = 722;
15390 t['Aring'] = 722;
15391 t['Otilde'] = 778;
15392 t['zdotaccent'] = 500;
15393 t['Ecaron'] = 667;
15394 t['Iogonek'] = 278;
15395 t['kcommaaccent'] = 556;
15396 t['minus'] = 584;
15397 t['Icircumflex'] = 278;
15398 t['ncaron'] = 611;
15399 t['tcommaaccent'] = 333;
15400 t['logicalnot'] = 584;
15401 t['odieresis'] = 611;
15402 t['udieresis'] = 611;
15403 t['notequal'] = 549;
15404 t['gcommaaccent'] = 611;
15405 t['eth'] = 611;
15406 t['zcaron'] = 500;
15407 t['ncommaaccent'] = 611;
15408 t['onesuperior'] = 333;
15409 t['imacron'] = 278;
15410 t['Euro'] = 556;
15411 });
15412 t['Helvetica-Oblique'] = getLookupTableFactory(function (t) {
15413 t['space'] = 278;
15414 t['exclam'] = 278;
15415 t['quotedbl'] = 355;
15416 t['numbersign'] = 556;
15417 t['dollar'] = 556;
15418 t['percent'] = 889;
15419 t['ampersand'] = 667;
15420 t['quoteright'] = 222;
15421 t['parenleft'] = 333;
15422 t['parenright'] = 333;
15423 t['asterisk'] = 389;
15424 t['plus'] = 584;
15425 t['comma'] = 278;
15426 t['hyphen'] = 333;
15427 t['period'] = 278;
15428 t['slash'] = 278;
15429 t['zero'] = 556;
15430 t['one'] = 556;
15431 t['two'] = 556;
15432 t['three'] = 556;
15433 t['four'] = 556;
15434 t['five'] = 556;
15435 t['six'] = 556;
15436 t['seven'] = 556;
15437 t['eight'] = 556;
15438 t['nine'] = 556;
15439 t['colon'] = 278;
15440 t['semicolon'] = 278;
15441 t['less'] = 584;
15442 t['equal'] = 584;
15443 t['greater'] = 584;
15444 t['question'] = 556;
15445 t['at'] = 1015;
15446 t['A'] = 667;
15447 t['B'] = 667;
15448 t['C'] = 722;
15449 t['D'] = 722;
15450 t['E'] = 667;
15451 t['F'] = 611;
15452 t['G'] = 778;
15453 t['H'] = 722;
15454 t['I'] = 278;
15455 t['J'] = 500;
15456 t['K'] = 667;
15457 t['L'] = 556;
15458 t['M'] = 833;
15459 t['N'] = 722;
15460 t['O'] = 778;
15461 t['P'] = 667;
15462 t['Q'] = 778;
15463 t['R'] = 722;
15464 t['S'] = 667;
15465 t['T'] = 611;
15466 t['U'] = 722;
15467 t['V'] = 667;
15468 t['W'] = 944;
15469 t['X'] = 667;
15470 t['Y'] = 667;
15471 t['Z'] = 611;
15472 t['bracketleft'] = 278;
15473 t['backslash'] = 278;
15474 t['bracketright'] = 278;
15475 t['asciicircum'] = 469;
15476 t['underscore'] = 556;
15477 t['quoteleft'] = 222;
15478 t['a'] = 556;
15479 t['b'] = 556;
15480 t['c'] = 500;
15481 t['d'] = 556;
15482 t['e'] = 556;
15483 t['f'] = 278;
15484 t['g'] = 556;
15485 t['h'] = 556;
15486 t['i'] = 222;
15487 t['j'] = 222;
15488 t['k'] = 500;
15489 t['l'] = 222;
15490 t['m'] = 833;
15491 t['n'] = 556;
15492 t['o'] = 556;
15493 t['p'] = 556;
15494 t['q'] = 556;
15495 t['r'] = 333;
15496 t['s'] = 500;
15497 t['t'] = 278;
15498 t['u'] = 556;
15499 t['v'] = 500;
15500 t['w'] = 722;
15501 t['x'] = 500;
15502 t['y'] = 500;
15503 t['z'] = 500;
15504 t['braceleft'] = 334;
15505 t['bar'] = 260;
15506 t['braceright'] = 334;
15507 t['asciitilde'] = 584;
15508 t['exclamdown'] = 333;
15509 t['cent'] = 556;
15510 t['sterling'] = 556;
15511 t['fraction'] = 167;
15512 t['yen'] = 556;
15513 t['florin'] = 556;
15514 t['section'] = 556;
15515 t['currency'] = 556;
15516 t['quotesingle'] = 191;
15517 t['quotedblleft'] = 333;
15518 t['guillemotleft'] = 556;
15519 t['guilsinglleft'] = 333;
15520 t['guilsinglright'] = 333;
15521 t['fi'] = 500;
15522 t['fl'] = 500;
15523 t['endash'] = 556;
15524 t['dagger'] = 556;
15525 t['daggerdbl'] = 556;
15526 t['periodcentered'] = 278;
15527 t['paragraph'] = 537;
15528 t['bullet'] = 350;
15529 t['quotesinglbase'] = 222;
15530 t['quotedblbase'] = 333;
15531 t['quotedblright'] = 333;
15532 t['guillemotright'] = 556;
15533 t['ellipsis'] = 1000;
15534 t['perthousand'] = 1000;
15535 t['questiondown'] = 611;
15536 t['grave'] = 333;
15537 t['acute'] = 333;
15538 t['circumflex'] = 333;
15539 t['tilde'] = 333;
15540 t['macron'] = 333;
15541 t['breve'] = 333;
15542 t['dotaccent'] = 333;
15543 t['dieresis'] = 333;
15544 t['ring'] = 333;
15545 t['cedilla'] = 333;
15546 t['hungarumlaut'] = 333;
15547 t['ogonek'] = 333;
15548 t['caron'] = 333;
15549 t['emdash'] = 1000;
15550 t['AE'] = 1000;
15551 t['ordfeminine'] = 370;
15552 t['Lslash'] = 556;
15553 t['Oslash'] = 778;
15554 t['OE'] = 1000;
15555 t['ordmasculine'] = 365;
15556 t['ae'] = 889;
15557 t['dotlessi'] = 278;
15558 t['lslash'] = 222;
15559 t['oslash'] = 611;
15560 t['oe'] = 944;
15561 t['germandbls'] = 611;
15562 t['Idieresis'] = 278;
15563 t['eacute'] = 556;
15564 t['abreve'] = 556;
15565 t['uhungarumlaut'] = 556;
15566 t['ecaron'] = 556;
15567 t['Ydieresis'] = 667;
15568 t['divide'] = 584;
15569 t['Yacute'] = 667;
15570 t['Acircumflex'] = 667;
15571 t['aacute'] = 556;
15572 t['Ucircumflex'] = 722;
15573 t['yacute'] = 500;
15574 t['scommaaccent'] = 500;
15575 t['ecircumflex'] = 556;
15576 t['Uring'] = 722;
15577 t['Udieresis'] = 722;
15578 t['aogonek'] = 556;
15579 t['Uacute'] = 722;
15580 t['uogonek'] = 556;
15581 t['Edieresis'] = 667;
15582 t['Dcroat'] = 722;
15583 t['commaaccent'] = 250;
15584 t['copyright'] = 737;
15585 t['Emacron'] = 667;
15586 t['ccaron'] = 500;
15587 t['aring'] = 556;
15588 t['Ncommaaccent'] = 722;
15589 t['lacute'] = 222;
15590 t['agrave'] = 556;
15591 t['Tcommaaccent'] = 611;
15592 t['Cacute'] = 722;
15593 t['atilde'] = 556;
15594 t['Edotaccent'] = 667;
15595 t['scaron'] = 500;
15596 t['scedilla'] = 500;
15597 t['iacute'] = 278;
15598 t['lozenge'] = 471;
15599 t['Rcaron'] = 722;
15600 t['Gcommaaccent'] = 778;
15601 t['ucircumflex'] = 556;
15602 t['acircumflex'] = 556;
15603 t['Amacron'] = 667;
15604 t['rcaron'] = 333;
15605 t['ccedilla'] = 500;
15606 t['Zdotaccent'] = 611;
15607 t['Thorn'] = 667;
15608 t['Omacron'] = 778;
15609 t['Racute'] = 722;
15610 t['Sacute'] = 667;
15611 t['dcaron'] = 643;
15612 t['Umacron'] = 722;
15613 t['uring'] = 556;
15614 t['threesuperior'] = 333;
15615 t['Ograve'] = 778;
15616 t['Agrave'] = 667;
15617 t['Abreve'] = 667;
15618 t['multiply'] = 584;
15619 t['uacute'] = 556;
15620 t['Tcaron'] = 611;
15621 t['partialdiff'] = 476;
15622 t['ydieresis'] = 500;
15623 t['Nacute'] = 722;
15624 t['icircumflex'] = 278;
15625 t['Ecircumflex'] = 667;
15626 t['adieresis'] = 556;
15627 t['edieresis'] = 556;
15628 t['cacute'] = 500;
15629 t['nacute'] = 556;
15630 t['umacron'] = 556;
15631 t['Ncaron'] = 722;
15632 t['Iacute'] = 278;
15633 t['plusminus'] = 584;
15634 t['brokenbar'] = 260;
15635 t['registered'] = 737;
15636 t['Gbreve'] = 778;
15637 t['Idotaccent'] = 278;
15638 t['summation'] = 600;
15639 t['Egrave'] = 667;
15640 t['racute'] = 333;
15641 t['omacron'] = 556;
15642 t['Zacute'] = 611;
15643 t['Zcaron'] = 611;
15644 t['greaterequal'] = 549;
15645 t['Eth'] = 722;
15646 t['Ccedilla'] = 722;
15647 t['lcommaaccent'] = 222;
15648 t['tcaron'] = 317;
15649 t['eogonek'] = 556;
15650 t['Uogonek'] = 722;
15651 t['Aacute'] = 667;
15652 t['Adieresis'] = 667;
15653 t['egrave'] = 556;
15654 t['zacute'] = 500;
15655 t['iogonek'] = 222;
15656 t['Oacute'] = 778;
15657 t['oacute'] = 556;
15658 t['amacron'] = 556;
15659 t['sacute'] = 500;
15660 t['idieresis'] = 278;
15661 t['Ocircumflex'] = 778;
15662 t['Ugrave'] = 722;
15663 t['Delta'] = 612;
15664 t['thorn'] = 556;
15665 t['twosuperior'] = 333;
15666 t['Odieresis'] = 778;
15667 t['mu'] = 556;
15668 t['igrave'] = 278;
15669 t['ohungarumlaut'] = 556;
15670 t['Eogonek'] = 667;
15671 t['dcroat'] = 556;
15672 t['threequarters'] = 834;
15673 t['Scedilla'] = 667;
15674 t['lcaron'] = 299;
15675 t['Kcommaaccent'] = 667;
15676 t['Lacute'] = 556;
15677 t['trademark'] = 1000;
15678 t['edotaccent'] = 556;
15679 t['Igrave'] = 278;
15680 t['Imacron'] = 278;
15681 t['Lcaron'] = 556;
15682 t['onehalf'] = 834;
15683 t['lessequal'] = 549;
15684 t['ocircumflex'] = 556;
15685 t['ntilde'] = 556;
15686 t['Uhungarumlaut'] = 722;
15687 t['Eacute'] = 667;
15688 t['emacron'] = 556;
15689 t['gbreve'] = 556;
15690 t['onequarter'] = 834;
15691 t['Scaron'] = 667;
15692 t['Scommaaccent'] = 667;
15693 t['Ohungarumlaut'] = 778;
15694 t['degree'] = 400;
15695 t['ograve'] = 556;
15696 t['Ccaron'] = 722;
15697 t['ugrave'] = 556;
15698 t['radical'] = 453;
15699 t['Dcaron'] = 722;
15700 t['rcommaaccent'] = 333;
15701 t['Ntilde'] = 722;
15702 t['otilde'] = 556;
15703 t['Rcommaaccent'] = 722;
15704 t['Lcommaaccent'] = 556;
15705 t['Atilde'] = 667;
15706 t['Aogonek'] = 667;
15707 t['Aring'] = 667;
15708 t['Otilde'] = 778;
15709 t['zdotaccent'] = 500;
15710 t['Ecaron'] = 667;
15711 t['Iogonek'] = 278;
15712 t['kcommaaccent'] = 500;
15713 t['minus'] = 584;
15714 t['Icircumflex'] = 278;
15715 t['ncaron'] = 556;
15716 t['tcommaaccent'] = 278;
15717 t['logicalnot'] = 584;
15718 t['odieresis'] = 556;
15719 t['udieresis'] = 556;
15720 t['notequal'] = 549;
15721 t['gcommaaccent'] = 556;
15722 t['eth'] = 556;
15723 t['zcaron'] = 500;
15724 t['ncommaaccent'] = 556;
15725 t['onesuperior'] = 333;
15726 t['imacron'] = 278;
15727 t['Euro'] = 556;
15728 });
15729 t['Symbol'] = getLookupTableFactory(function (t) {
15730 t['space'] = 250;
15731 t['exclam'] = 333;
15732 t['universal'] = 713;
15733 t['numbersign'] = 500;
15734 t['existential'] = 549;
15735 t['percent'] = 833;
15736 t['ampersand'] = 778;
15737 t['suchthat'] = 439;
15738 t['parenleft'] = 333;
15739 t['parenright'] = 333;
15740 t['asteriskmath'] = 500;
15741 t['plus'] = 549;
15742 t['comma'] = 250;
15743 t['minus'] = 549;
15744 t['period'] = 250;
15745 t['slash'] = 278;
15746 t['zero'] = 500;
15747 t['one'] = 500;
15748 t['two'] = 500;
15749 t['three'] = 500;
15750 t['four'] = 500;
15751 t['five'] = 500;
15752 t['six'] = 500;
15753 t['seven'] = 500;
15754 t['eight'] = 500;
15755 t['nine'] = 500;
15756 t['colon'] = 278;
15757 t['semicolon'] = 278;
15758 t['less'] = 549;
15759 t['equal'] = 549;
15760 t['greater'] = 549;
15761 t['question'] = 444;
15762 t['congruent'] = 549;
15763 t['Alpha'] = 722;
15764 t['Beta'] = 667;
15765 t['Chi'] = 722;
15766 t['Delta'] = 612;
15767 t['Epsilon'] = 611;
15768 t['Phi'] = 763;
15769 t['Gamma'] = 603;
15770 t['Eta'] = 722;
15771 t['Iota'] = 333;
15772 t['theta1'] = 631;
15773 t['Kappa'] = 722;
15774 t['Lambda'] = 686;
15775 t['Mu'] = 889;
15776 t['Nu'] = 722;
15777 t['Omicron'] = 722;
15778 t['Pi'] = 768;
15779 t['Theta'] = 741;
15780 t['Rho'] = 556;
15781 t['Sigma'] = 592;
15782 t['Tau'] = 611;
15783 t['Upsilon'] = 690;
15784 t['sigma1'] = 439;
15785 t['Omega'] = 768;
15786 t['Xi'] = 645;
15787 t['Psi'] = 795;
15788 t['Zeta'] = 611;
15789 t['bracketleft'] = 333;
15790 t['therefore'] = 863;
15791 t['bracketright'] = 333;
15792 t['perpendicular'] = 658;
15793 t['underscore'] = 500;
15794 t['radicalex'] = 500;
15795 t['alpha'] = 631;
15796 t['beta'] = 549;
15797 t['chi'] = 549;
15798 t['delta'] = 494;
15799 t['epsilon'] = 439;
15800 t['phi'] = 521;
15801 t['gamma'] = 411;
15802 t['eta'] = 603;
15803 t['iota'] = 329;
15804 t['phi1'] = 603;
15805 t['kappa'] = 549;
15806 t['lambda'] = 549;
15807 t['mu'] = 576;
15808 t['nu'] = 521;
15809 t['omicron'] = 549;
15810 t['pi'] = 549;
15811 t['theta'] = 521;
15812 t['rho'] = 549;
15813 t['sigma'] = 603;
15814 t['tau'] = 439;
15815 t['upsilon'] = 576;
15816 t['omega1'] = 713;
15817 t['omega'] = 686;
15818 t['xi'] = 493;
15819 t['psi'] = 686;
15820 t['zeta'] = 494;
15821 t['braceleft'] = 480;
15822 t['bar'] = 200;
15823 t['braceright'] = 480;
15824 t['similar'] = 549;
15825 t['Euro'] = 750;
15826 t['Upsilon1'] = 620;
15827 t['minute'] = 247;
15828 t['lessequal'] = 549;
15829 t['fraction'] = 167;
15830 t['infinity'] = 713;
15831 t['florin'] = 500;
15832 t['club'] = 753;
15833 t['diamond'] = 753;
15834 t['heart'] = 753;
15835 t['spade'] = 753;
15836 t['arrowboth'] = 1042;
15837 t['arrowleft'] = 987;
15838 t['arrowup'] = 603;
15839 t['arrowright'] = 987;
15840 t['arrowdown'] = 603;
15841 t['degree'] = 400;
15842 t['plusminus'] = 549;
15843 t['second'] = 411;
15844 t['greaterequal'] = 549;
15845 t['multiply'] = 549;
15846 t['proportional'] = 713;
15847 t['partialdiff'] = 494;
15848 t['bullet'] = 460;
15849 t['divide'] = 549;
15850 t['notequal'] = 549;
15851 t['equivalence'] = 549;
15852 t['approxequal'] = 549;
15853 t['ellipsis'] = 1000;
15854 t['arrowvertex'] = 603;
15855 t['arrowhorizex'] = 1000;
15856 t['carriagereturn'] = 658;
15857 t['aleph'] = 823;
15858 t['Ifraktur'] = 686;
15859 t['Rfraktur'] = 795;
15860 t['weierstrass'] = 987;
15861 t['circlemultiply'] = 768;
15862 t['circleplus'] = 768;
15863 t['emptyset'] = 823;
15864 t['intersection'] = 768;
15865 t['union'] = 768;
15866 t['propersuperset'] = 713;
15867 t['reflexsuperset'] = 713;
15868 t['notsubset'] = 713;
15869 t['propersubset'] = 713;
15870 t['reflexsubset'] = 713;
15871 t['element'] = 713;
15872 t['notelement'] = 713;
15873 t['angle'] = 768;
15874 t['gradient'] = 713;
15875 t['registerserif'] = 790;
15876 t['copyrightserif'] = 790;
15877 t['trademarkserif'] = 890;
15878 t['product'] = 823;
15879 t['radical'] = 549;
15880 t['dotmath'] = 250;
15881 t['logicalnot'] = 713;
15882 t['logicaland'] = 603;
15883 t['logicalor'] = 603;
15884 t['arrowdblboth'] = 1042;
15885 t['arrowdblleft'] = 987;
15886 t['arrowdblup'] = 603;
15887 t['arrowdblright'] = 987;
15888 t['arrowdbldown'] = 603;
15889 t['lozenge'] = 494;
15890 t['angleleft'] = 329;
15891 t['registersans'] = 790;
15892 t['copyrightsans'] = 790;
15893 t['trademarksans'] = 786;
15894 t['summation'] = 713;
15895 t['parenlefttp'] = 384;
15896 t['parenleftex'] = 384;
15897 t['parenleftbt'] = 384;
15898 t['bracketlefttp'] = 384;
15899 t['bracketleftex'] = 384;
15900 t['bracketleftbt'] = 384;
15901 t['bracelefttp'] = 494;
15902 t['braceleftmid'] = 494;
15903 t['braceleftbt'] = 494;
15904 t['braceex'] = 494;
15905 t['angleright'] = 329;
15906 t['integral'] = 274;
15907 t['integraltp'] = 686;
15908 t['integralex'] = 686;
15909 t['integralbt'] = 686;
15910 t['parenrighttp'] = 384;
15911 t['parenrightex'] = 384;
15912 t['parenrightbt'] = 384;
15913 t['bracketrighttp'] = 384;
15914 t['bracketrightex'] = 384;
15915 t['bracketrightbt'] = 384;
15916 t['bracerighttp'] = 494;
15917 t['bracerightmid'] = 494;
15918 t['bracerightbt'] = 494;
15919 t['apple'] = 790;
15920 });
15921 t['Times-Roman'] = getLookupTableFactory(function (t) {
15922 t['space'] = 250;
15923 t['exclam'] = 333;
15924 t['quotedbl'] = 408;
15925 t['numbersign'] = 500;
15926 t['dollar'] = 500;
15927 t['percent'] = 833;
15928 t['ampersand'] = 778;
15929 t['quoteright'] = 333;
15930 t['parenleft'] = 333;
15931 t['parenright'] = 333;
15932 t['asterisk'] = 500;
15933 t['plus'] = 564;
15934 t['comma'] = 250;
15935 t['hyphen'] = 333;
15936 t['period'] = 250;
15937 t['slash'] = 278;
15938 t['zero'] = 500;
15939 t['one'] = 500;
15940 t['two'] = 500;
15941 t['three'] = 500;
15942 t['four'] = 500;
15943 t['five'] = 500;
15944 t['six'] = 500;
15945 t['seven'] = 500;
15946 t['eight'] = 500;
15947 t['nine'] = 500;
15948 t['colon'] = 278;
15949 t['semicolon'] = 278;
15950 t['less'] = 564;
15951 t['equal'] = 564;
15952 t['greater'] = 564;
15953 t['question'] = 444;
15954 t['at'] = 921;
15955 t['A'] = 722;
15956 t['B'] = 667;
15957 t['C'] = 667;
15958 t['D'] = 722;
15959 t['E'] = 611;
15960 t['F'] = 556;
15961 t['G'] = 722;
15962 t['H'] = 722;
15963 t['I'] = 333;
15964 t['J'] = 389;
15965 t['K'] = 722;
15966 t['L'] = 611;
15967 t['M'] = 889;
15968 t['N'] = 722;
15969 t['O'] = 722;
15970 t['P'] = 556;
15971 t['Q'] = 722;
15972 t['R'] = 667;
15973 t['S'] = 556;
15974 t['T'] = 611;
15975 t['U'] = 722;
15976 t['V'] = 722;
15977 t['W'] = 944;
15978 t['X'] = 722;
15979 t['Y'] = 722;
15980 t['Z'] = 611;
15981 t['bracketleft'] = 333;
15982 t['backslash'] = 278;
15983 t['bracketright'] = 333;
15984 t['asciicircum'] = 469;
15985 t['underscore'] = 500;
15986 t['quoteleft'] = 333;
15987 t['a'] = 444;
15988 t['b'] = 500;
15989 t['c'] = 444;
15990 t['d'] = 500;
15991 t['e'] = 444;
15992 t['f'] = 333;
15993 t['g'] = 500;
15994 t['h'] = 500;
15995 t['i'] = 278;
15996 t['j'] = 278;
15997 t['k'] = 500;
15998 t['l'] = 278;
15999 t['m'] = 778;
16000 t['n'] = 500;
16001 t['o'] = 500;
16002 t['p'] = 500;
16003 t['q'] = 500;
16004 t['r'] = 333;
16005 t['s'] = 389;
16006 t['t'] = 278;
16007 t['u'] = 500;
16008 t['v'] = 500;
16009 t['w'] = 722;
16010 t['x'] = 500;
16011 t['y'] = 500;
16012 t['z'] = 444;
16013 t['braceleft'] = 480;
16014 t['bar'] = 200;
16015 t['braceright'] = 480;
16016 t['asciitilde'] = 541;
16017 t['exclamdown'] = 333;
16018 t['cent'] = 500;
16019 t['sterling'] = 500;
16020 t['fraction'] = 167;
16021 t['yen'] = 500;
16022 t['florin'] = 500;
16023 t['section'] = 500;
16024 t['currency'] = 500;
16025 t['quotesingle'] = 180;
16026 t['quotedblleft'] = 444;
16027 t['guillemotleft'] = 500;
16028 t['guilsinglleft'] = 333;
16029 t['guilsinglright'] = 333;
16030 t['fi'] = 556;
16031 t['fl'] = 556;
16032 t['endash'] = 500;
16033 t['dagger'] = 500;
16034 t['daggerdbl'] = 500;
16035 t['periodcentered'] = 250;
16036 t['paragraph'] = 453;
16037 t['bullet'] = 350;
16038 t['quotesinglbase'] = 333;
16039 t['quotedblbase'] = 444;
16040 t['quotedblright'] = 444;
16041 t['guillemotright'] = 500;
16042 t['ellipsis'] = 1000;
16043 t['perthousand'] = 1000;
16044 t['questiondown'] = 444;
16045 t['grave'] = 333;
16046 t['acute'] = 333;
16047 t['circumflex'] = 333;
16048 t['tilde'] = 333;
16049 t['macron'] = 333;
16050 t['breve'] = 333;
16051 t['dotaccent'] = 333;
16052 t['dieresis'] = 333;
16053 t['ring'] = 333;
16054 t['cedilla'] = 333;
16055 t['hungarumlaut'] = 333;
16056 t['ogonek'] = 333;
16057 t['caron'] = 333;
16058 t['emdash'] = 1000;
16059 t['AE'] = 889;
16060 t['ordfeminine'] = 276;
16061 t['Lslash'] = 611;
16062 t['Oslash'] = 722;
16063 t['OE'] = 889;
16064 t['ordmasculine'] = 310;
16065 t['ae'] = 667;
16066 t['dotlessi'] = 278;
16067 t['lslash'] = 278;
16068 t['oslash'] = 500;
16069 t['oe'] = 722;
16070 t['germandbls'] = 500;
16071 t['Idieresis'] = 333;
16072 t['eacute'] = 444;
16073 t['abreve'] = 444;
16074 t['uhungarumlaut'] = 500;
16075 t['ecaron'] = 444;
16076 t['Ydieresis'] = 722;
16077 t['divide'] = 564;
16078 t['Yacute'] = 722;
16079 t['Acircumflex'] = 722;
16080 t['aacute'] = 444;
16081 t['Ucircumflex'] = 722;
16082 t['yacute'] = 500;
16083 t['scommaaccent'] = 389;
16084 t['ecircumflex'] = 444;
16085 t['Uring'] = 722;
16086 t['Udieresis'] = 722;
16087 t['aogonek'] = 444;
16088 t['Uacute'] = 722;
16089 t['uogonek'] = 500;
16090 t['Edieresis'] = 611;
16091 t['Dcroat'] = 722;
16092 t['commaaccent'] = 250;
16093 t['copyright'] = 760;
16094 t['Emacron'] = 611;
16095 t['ccaron'] = 444;
16096 t['aring'] = 444;
16097 t['Ncommaaccent'] = 722;
16098 t['lacute'] = 278;
16099 t['agrave'] = 444;
16100 t['Tcommaaccent'] = 611;
16101 t['Cacute'] = 667;
16102 t['atilde'] = 444;
16103 t['Edotaccent'] = 611;
16104 t['scaron'] = 389;
16105 t['scedilla'] = 389;
16106 t['iacute'] = 278;
16107 t['lozenge'] = 471;
16108 t['Rcaron'] = 667;
16109 t['Gcommaaccent'] = 722;
16110 t['ucircumflex'] = 500;
16111 t['acircumflex'] = 444;
16112 t['Amacron'] = 722;
16113 t['rcaron'] = 333;
16114 t['ccedilla'] = 444;
16115 t['Zdotaccent'] = 611;
16116 t['Thorn'] = 556;
16117 t['Omacron'] = 722;
16118 t['Racute'] = 667;
16119 t['Sacute'] = 556;
16120 t['dcaron'] = 588;
16121 t['Umacron'] = 722;
16122 t['uring'] = 500;
16123 t['threesuperior'] = 300;
16124 t['Ograve'] = 722;
16125 t['Agrave'] = 722;
16126 t['Abreve'] = 722;
16127 t['multiply'] = 564;
16128 t['uacute'] = 500;
16129 t['Tcaron'] = 611;
16130 t['partialdiff'] = 476;
16131 t['ydieresis'] = 500;
16132 t['Nacute'] = 722;
16133 t['icircumflex'] = 278;
16134 t['Ecircumflex'] = 611;
16135 t['adieresis'] = 444;
16136 t['edieresis'] = 444;
16137 t['cacute'] = 444;
16138 t['nacute'] = 500;
16139 t['umacron'] = 500;
16140 t['Ncaron'] = 722;
16141 t['Iacute'] = 333;
16142 t['plusminus'] = 564;
16143 t['brokenbar'] = 200;
16144 t['registered'] = 760;
16145 t['Gbreve'] = 722;
16146 t['Idotaccent'] = 333;
16147 t['summation'] = 600;
16148 t['Egrave'] = 611;
16149 t['racute'] = 333;
16150 t['omacron'] = 500;
16151 t['Zacute'] = 611;
16152 t['Zcaron'] = 611;
16153 t['greaterequal'] = 549;
16154 t['Eth'] = 722;
16155 t['Ccedilla'] = 667;
16156 t['lcommaaccent'] = 278;
16157 t['tcaron'] = 326;
16158 t['eogonek'] = 444;
16159 t['Uogonek'] = 722;
16160 t['Aacute'] = 722;
16161 t['Adieresis'] = 722;
16162 t['egrave'] = 444;
16163 t['zacute'] = 444;
16164 t['iogonek'] = 278;
16165 t['Oacute'] = 722;
16166 t['oacute'] = 500;
16167 t['amacron'] = 444;
16168 t['sacute'] = 389;
16169 t['idieresis'] = 278;
16170 t['Ocircumflex'] = 722;
16171 t['Ugrave'] = 722;
16172 t['Delta'] = 612;
16173 t['thorn'] = 500;
16174 t['twosuperior'] = 300;
16175 t['Odieresis'] = 722;
16176 t['mu'] = 500;
16177 t['igrave'] = 278;
16178 t['ohungarumlaut'] = 500;
16179 t['Eogonek'] = 611;
16180 t['dcroat'] = 500;
16181 t['threequarters'] = 750;
16182 t['Scedilla'] = 556;
16183 t['lcaron'] = 344;
16184 t['Kcommaaccent'] = 722;
16185 t['Lacute'] = 611;
16186 t['trademark'] = 980;
16187 t['edotaccent'] = 444;
16188 t['Igrave'] = 333;
16189 t['Imacron'] = 333;
16190 t['Lcaron'] = 611;
16191 t['onehalf'] = 750;
16192 t['lessequal'] = 549;
16193 t['ocircumflex'] = 500;
16194 t['ntilde'] = 500;
16195 t['Uhungarumlaut'] = 722;
16196 t['Eacute'] = 611;
16197 t['emacron'] = 444;
16198 t['gbreve'] = 500;
16199 t['onequarter'] = 750;
16200 t['Scaron'] = 556;
16201 t['Scommaaccent'] = 556;
16202 t['Ohungarumlaut'] = 722;
16203 t['degree'] = 400;
16204 t['ograve'] = 500;
16205 t['Ccaron'] = 667;
16206 t['ugrave'] = 500;
16207 t['radical'] = 453;
16208 t['Dcaron'] = 722;
16209 t['rcommaaccent'] = 333;
16210 t['Ntilde'] = 722;
16211 t['otilde'] = 500;
16212 t['Rcommaaccent'] = 667;
16213 t['Lcommaaccent'] = 611;
16214 t['Atilde'] = 722;
16215 t['Aogonek'] = 722;
16216 t['Aring'] = 722;
16217 t['Otilde'] = 722;
16218 t['zdotaccent'] = 444;
16219 t['Ecaron'] = 611;
16220 t['Iogonek'] = 333;
16221 t['kcommaaccent'] = 500;
16222 t['minus'] = 564;
16223 t['Icircumflex'] = 333;
16224 t['ncaron'] = 500;
16225 t['tcommaaccent'] = 278;
16226 t['logicalnot'] = 564;
16227 t['odieresis'] = 500;
16228 t['udieresis'] = 500;
16229 t['notequal'] = 549;
16230 t['gcommaaccent'] = 500;
16231 t['eth'] = 500;
16232 t['zcaron'] = 444;
16233 t['ncommaaccent'] = 500;
16234 t['onesuperior'] = 300;
16235 t['imacron'] = 278;
16236 t['Euro'] = 500;
16237 });
16238 t['Times-Bold'] = getLookupTableFactory(function (t) {
16239 t['space'] = 250;
16240 t['exclam'] = 333;
16241 t['quotedbl'] = 555;
16242 t['numbersign'] = 500;
16243 t['dollar'] = 500;
16244 t['percent'] = 1000;
16245 t['ampersand'] = 833;
16246 t['quoteright'] = 333;
16247 t['parenleft'] = 333;
16248 t['parenright'] = 333;
16249 t['asterisk'] = 500;
16250 t['plus'] = 570;
16251 t['comma'] = 250;
16252 t['hyphen'] = 333;
16253 t['period'] = 250;
16254 t['slash'] = 278;
16255 t['zero'] = 500;
16256 t['one'] = 500;
16257 t['two'] = 500;
16258 t['three'] = 500;
16259 t['four'] = 500;
16260 t['five'] = 500;
16261 t['six'] = 500;
16262 t['seven'] = 500;
16263 t['eight'] = 500;
16264 t['nine'] = 500;
16265 t['colon'] = 333;
16266 t['semicolon'] = 333;
16267 t['less'] = 570;
16268 t['equal'] = 570;
16269 t['greater'] = 570;
16270 t['question'] = 500;
16271 t['at'] = 930;
16272 t['A'] = 722;
16273 t['B'] = 667;
16274 t['C'] = 722;
16275 t['D'] = 722;
16276 t['E'] = 667;
16277 t['F'] = 611;
16278 t['G'] = 778;
16279 t['H'] = 778;
16280 t['I'] = 389;
16281 t['J'] = 500;
16282 t['K'] = 778;
16283 t['L'] = 667;
16284 t['M'] = 944;
16285 t['N'] = 722;
16286 t['O'] = 778;
16287 t['P'] = 611;
16288 t['Q'] = 778;
16289 t['R'] = 722;
16290 t['S'] = 556;
16291 t['T'] = 667;
16292 t['U'] = 722;
16293 t['V'] = 722;
16294 t['W'] = 1000;
16295 t['X'] = 722;
16296 t['Y'] = 722;
16297 t['Z'] = 667;
16298 t['bracketleft'] = 333;
16299 t['backslash'] = 278;
16300 t['bracketright'] = 333;
16301 t['asciicircum'] = 581;
16302 t['underscore'] = 500;
16303 t['quoteleft'] = 333;
16304 t['a'] = 500;
16305 t['b'] = 556;
16306 t['c'] = 444;
16307 t['d'] = 556;
16308 t['e'] = 444;
16309 t['f'] = 333;
16310 t['g'] = 500;
16311 t['h'] = 556;
16312 t['i'] = 278;
16313 t['j'] = 333;
16314 t['k'] = 556;
16315 t['l'] = 278;
16316 t['m'] = 833;
16317 t['n'] = 556;
16318 t['o'] = 500;
16319 t['p'] = 556;
16320 t['q'] = 556;
16321 t['r'] = 444;
16322 t['s'] = 389;
16323 t['t'] = 333;
16324 t['u'] = 556;
16325 t['v'] = 500;
16326 t['w'] = 722;
16327 t['x'] = 500;
16328 t['y'] = 500;
16329 t['z'] = 444;
16330 t['braceleft'] = 394;
16331 t['bar'] = 220;
16332 t['braceright'] = 394;
16333 t['asciitilde'] = 520;
16334 t['exclamdown'] = 333;
16335 t['cent'] = 500;
16336 t['sterling'] = 500;
16337 t['fraction'] = 167;
16338 t['yen'] = 500;
16339 t['florin'] = 500;
16340 t['section'] = 500;
16341 t['currency'] = 500;
16342 t['quotesingle'] = 278;
16343 t['quotedblleft'] = 500;
16344 t['guillemotleft'] = 500;
16345 t['guilsinglleft'] = 333;
16346 t['guilsinglright'] = 333;
16347 t['fi'] = 556;
16348 t['fl'] = 556;
16349 t['endash'] = 500;
16350 t['dagger'] = 500;
16351 t['daggerdbl'] = 500;
16352 t['periodcentered'] = 250;
16353 t['paragraph'] = 540;
16354 t['bullet'] = 350;
16355 t['quotesinglbase'] = 333;
16356 t['quotedblbase'] = 500;
16357 t['quotedblright'] = 500;
16358 t['guillemotright'] = 500;
16359 t['ellipsis'] = 1000;
16360 t['perthousand'] = 1000;
16361 t['questiondown'] = 500;
16362 t['grave'] = 333;
16363 t['acute'] = 333;
16364 t['circumflex'] = 333;
16365 t['tilde'] = 333;
16366 t['macron'] = 333;
16367 t['breve'] = 333;
16368 t['dotaccent'] = 333;
16369 t['dieresis'] = 333;
16370 t['ring'] = 333;
16371 t['cedilla'] = 333;
16372 t['hungarumlaut'] = 333;
16373 t['ogonek'] = 333;
16374 t['caron'] = 333;
16375 t['emdash'] = 1000;
16376 t['AE'] = 1000;
16377 t['ordfeminine'] = 300;
16378 t['Lslash'] = 667;
16379 t['Oslash'] = 778;
16380 t['OE'] = 1000;
16381 t['ordmasculine'] = 330;
16382 t['ae'] = 722;
16383 t['dotlessi'] = 278;
16384 t['lslash'] = 278;
16385 t['oslash'] = 500;
16386 t['oe'] = 722;
16387 t['germandbls'] = 556;
16388 t['Idieresis'] = 389;
16389 t['eacute'] = 444;
16390 t['abreve'] = 500;
16391 t['uhungarumlaut'] = 556;
16392 t['ecaron'] = 444;
16393 t['Ydieresis'] = 722;
16394 t['divide'] = 570;
16395 t['Yacute'] = 722;
16396 t['Acircumflex'] = 722;
16397 t['aacute'] = 500;
16398 t['Ucircumflex'] = 722;
16399 t['yacute'] = 500;
16400 t['scommaaccent'] = 389;
16401 t['ecircumflex'] = 444;
16402 t['Uring'] = 722;
16403 t['Udieresis'] = 722;
16404 t['aogonek'] = 500;
16405 t['Uacute'] = 722;
16406 t['uogonek'] = 556;
16407 t['Edieresis'] = 667;
16408 t['Dcroat'] = 722;
16409 t['commaaccent'] = 250;
16410 t['copyright'] = 747;
16411 t['Emacron'] = 667;
16412 t['ccaron'] = 444;
16413 t['aring'] = 500;
16414 t['Ncommaaccent'] = 722;
16415 t['lacute'] = 278;
16416 t['agrave'] = 500;
16417 t['Tcommaaccent'] = 667;
16418 t['Cacute'] = 722;
16419 t['atilde'] = 500;
16420 t['Edotaccent'] = 667;
16421 t['scaron'] = 389;
16422 t['scedilla'] = 389;
16423 t['iacute'] = 278;
16424 t['lozenge'] = 494;
16425 t['Rcaron'] = 722;
16426 t['Gcommaaccent'] = 778;
16427 t['ucircumflex'] = 556;
16428 t['acircumflex'] = 500;
16429 t['Amacron'] = 722;
16430 t['rcaron'] = 444;
16431 t['ccedilla'] = 444;
16432 t['Zdotaccent'] = 667;
16433 t['Thorn'] = 611;
16434 t['Omacron'] = 778;
16435 t['Racute'] = 722;
16436 t['Sacute'] = 556;
16437 t['dcaron'] = 672;
16438 t['Umacron'] = 722;
16439 t['uring'] = 556;
16440 t['threesuperior'] = 300;
16441 t['Ograve'] = 778;
16442 t['Agrave'] = 722;
16443 t['Abreve'] = 722;
16444 t['multiply'] = 570;
16445 t['uacute'] = 556;
16446 t['Tcaron'] = 667;
16447 t['partialdiff'] = 494;
16448 t['ydieresis'] = 500;
16449 t['Nacute'] = 722;
16450 t['icircumflex'] = 278;
16451 t['Ecircumflex'] = 667;
16452 t['adieresis'] = 500;
16453 t['edieresis'] = 444;
16454 t['cacute'] = 444;
16455 t['nacute'] = 556;
16456 t['umacron'] = 556;
16457 t['Ncaron'] = 722;
16458 t['Iacute'] = 389;
16459 t['plusminus'] = 570;
16460 t['brokenbar'] = 220;
16461 t['registered'] = 747;
16462 t['Gbreve'] = 778;
16463 t['Idotaccent'] = 389;
16464 t['summation'] = 600;
16465 t['Egrave'] = 667;
16466 t['racute'] = 444;
16467 t['omacron'] = 500;
16468 t['Zacute'] = 667;
16469 t['Zcaron'] = 667;
16470 t['greaterequal'] = 549;
16471 t['Eth'] = 722;
16472 t['Ccedilla'] = 722;
16473 t['lcommaaccent'] = 278;
16474 t['tcaron'] = 416;
16475 t['eogonek'] = 444;
16476 t['Uogonek'] = 722;
16477 t['Aacute'] = 722;
16478 t['Adieresis'] = 722;
16479 t['egrave'] = 444;
16480 t['zacute'] = 444;
16481 t['iogonek'] = 278;
16482 t['Oacute'] = 778;
16483 t['oacute'] = 500;
16484 t['amacron'] = 500;
16485 t['sacute'] = 389;
16486 t['idieresis'] = 278;
16487 t['Ocircumflex'] = 778;
16488 t['Ugrave'] = 722;
16489 t['Delta'] = 612;
16490 t['thorn'] = 556;
16491 t['twosuperior'] = 300;
16492 t['Odieresis'] = 778;
16493 t['mu'] = 556;
16494 t['igrave'] = 278;
16495 t['ohungarumlaut'] = 500;
16496 t['Eogonek'] = 667;
16497 t['dcroat'] = 556;
16498 t['threequarters'] = 750;
16499 t['Scedilla'] = 556;
16500 t['lcaron'] = 394;
16501 t['Kcommaaccent'] = 778;
16502 t['Lacute'] = 667;
16503 t['trademark'] = 1000;
16504 t['edotaccent'] = 444;
16505 t['Igrave'] = 389;
16506 t['Imacron'] = 389;
16507 t['Lcaron'] = 667;
16508 t['onehalf'] = 750;
16509 t['lessequal'] = 549;
16510 t['ocircumflex'] = 500;
16511 t['ntilde'] = 556;
16512 t['Uhungarumlaut'] = 722;
16513 t['Eacute'] = 667;
16514 t['emacron'] = 444;
16515 t['gbreve'] = 500;
16516 t['onequarter'] = 750;
16517 t['Scaron'] = 556;
16518 t['Scommaaccent'] = 556;
16519 t['Ohungarumlaut'] = 778;
16520 t['degree'] = 400;
16521 t['ograve'] = 500;
16522 t['Ccaron'] = 722;
16523 t['ugrave'] = 556;
16524 t['radical'] = 549;
16525 t['Dcaron'] = 722;
16526 t['rcommaaccent'] = 444;
16527 t['Ntilde'] = 722;
16528 t['otilde'] = 500;
16529 t['Rcommaaccent'] = 722;
16530 t['Lcommaaccent'] = 667;
16531 t['Atilde'] = 722;
16532 t['Aogonek'] = 722;
16533 t['Aring'] = 722;
16534 t['Otilde'] = 778;
16535 t['zdotaccent'] = 444;
16536 t['Ecaron'] = 667;
16537 t['Iogonek'] = 389;
16538 t['kcommaaccent'] = 556;
16539 t['minus'] = 570;
16540 t['Icircumflex'] = 389;
16541 t['ncaron'] = 556;
16542 t['tcommaaccent'] = 333;
16543 t['logicalnot'] = 570;
16544 t['odieresis'] = 500;
16545 t['udieresis'] = 556;
16546 t['notequal'] = 549;
16547 t['gcommaaccent'] = 500;
16548 t['eth'] = 500;
16549 t['zcaron'] = 444;
16550 t['ncommaaccent'] = 556;
16551 t['onesuperior'] = 300;
16552 t['imacron'] = 278;
16553 t['Euro'] = 500;
16554 });
16555 t['Times-BoldItalic'] = getLookupTableFactory(function (t) {
16556 t['space'] = 250;
16557 t['exclam'] = 389;
16558 t['quotedbl'] = 555;
16559 t['numbersign'] = 500;
16560 t['dollar'] = 500;
16561 t['percent'] = 833;
16562 t['ampersand'] = 778;
16563 t['quoteright'] = 333;
16564 t['parenleft'] = 333;
16565 t['parenright'] = 333;
16566 t['asterisk'] = 500;
16567 t['plus'] = 570;
16568 t['comma'] = 250;
16569 t['hyphen'] = 333;
16570 t['period'] = 250;
16571 t['slash'] = 278;
16572 t['zero'] = 500;
16573 t['one'] = 500;
16574 t['two'] = 500;
16575 t['three'] = 500;
16576 t['four'] = 500;
16577 t['five'] = 500;
16578 t['six'] = 500;
16579 t['seven'] = 500;
16580 t['eight'] = 500;
16581 t['nine'] = 500;
16582 t['colon'] = 333;
16583 t['semicolon'] = 333;
16584 t['less'] = 570;
16585 t['equal'] = 570;
16586 t['greater'] = 570;
16587 t['question'] = 500;
16588 t['at'] = 832;
16589 t['A'] = 667;
16590 t['B'] = 667;
16591 t['C'] = 667;
16592 t['D'] = 722;
16593 t['E'] = 667;
16594 t['F'] = 667;
16595 t['G'] = 722;
16596 t['H'] = 778;
16597 t['I'] = 389;
16598 t['J'] = 500;
16599 t['K'] = 667;
16600 t['L'] = 611;
16601 t['M'] = 889;
16602 t['N'] = 722;
16603 t['O'] = 722;
16604 t['P'] = 611;
16605 t['Q'] = 722;
16606 t['R'] = 667;
16607 t['S'] = 556;
16608 t['T'] = 611;
16609 t['U'] = 722;
16610 t['V'] = 667;
16611 t['W'] = 889;
16612 t['X'] = 667;
16613 t['Y'] = 611;
16614 t['Z'] = 611;
16615 t['bracketleft'] = 333;
16616 t['backslash'] = 278;
16617 t['bracketright'] = 333;
16618 t['asciicircum'] = 570;
16619 t['underscore'] = 500;
16620 t['quoteleft'] = 333;
16621 t['a'] = 500;
16622 t['b'] = 500;
16623 t['c'] = 444;
16624 t['d'] = 500;
16625 t['e'] = 444;
16626 t['f'] = 333;
16627 t['g'] = 500;
16628 t['h'] = 556;
16629 t['i'] = 278;
16630 t['j'] = 278;
16631 t['k'] = 500;
16632 t['l'] = 278;
16633 t['m'] = 778;
16634 t['n'] = 556;
16635 t['o'] = 500;
16636 t['p'] = 500;
16637 t['q'] = 500;
16638 t['r'] = 389;
16639 t['s'] = 389;
16640 t['t'] = 278;
16641 t['u'] = 556;
16642 t['v'] = 444;
16643 t['w'] = 667;
16644 t['x'] = 500;
16645 t['y'] = 444;
16646 t['z'] = 389;
16647 t['braceleft'] = 348;
16648 t['bar'] = 220;
16649 t['braceright'] = 348;
16650 t['asciitilde'] = 570;
16651 t['exclamdown'] = 389;
16652 t['cent'] = 500;
16653 t['sterling'] = 500;
16654 t['fraction'] = 167;
16655 t['yen'] = 500;
16656 t['florin'] = 500;
16657 t['section'] = 500;
16658 t['currency'] = 500;
16659 t['quotesingle'] = 278;
16660 t['quotedblleft'] = 500;
16661 t['guillemotleft'] = 500;
16662 t['guilsinglleft'] = 333;
16663 t['guilsinglright'] = 333;
16664 t['fi'] = 556;
16665 t['fl'] = 556;
16666 t['endash'] = 500;
16667 t['dagger'] = 500;
16668 t['daggerdbl'] = 500;
16669 t['periodcentered'] = 250;
16670 t['paragraph'] = 500;
16671 t['bullet'] = 350;
16672 t['quotesinglbase'] = 333;
16673 t['quotedblbase'] = 500;
16674 t['quotedblright'] = 500;
16675 t['guillemotright'] = 500;
16676 t['ellipsis'] = 1000;
16677 t['perthousand'] = 1000;
16678 t['questiondown'] = 500;
16679 t['grave'] = 333;
16680 t['acute'] = 333;
16681 t['circumflex'] = 333;
16682 t['tilde'] = 333;
16683 t['macron'] = 333;
16684 t['breve'] = 333;
16685 t['dotaccent'] = 333;
16686 t['dieresis'] = 333;
16687 t['ring'] = 333;
16688 t['cedilla'] = 333;
16689 t['hungarumlaut'] = 333;
16690 t['ogonek'] = 333;
16691 t['caron'] = 333;
16692 t['emdash'] = 1000;
16693 t['AE'] = 944;
16694 t['ordfeminine'] = 266;
16695 t['Lslash'] = 611;
16696 t['Oslash'] = 722;
16697 t['OE'] = 944;
16698 t['ordmasculine'] = 300;
16699 t['ae'] = 722;
16700 t['dotlessi'] = 278;
16701 t['lslash'] = 278;
16702 t['oslash'] = 500;
16703 t['oe'] = 722;
16704 t['germandbls'] = 500;
16705 t['Idieresis'] = 389;
16706 t['eacute'] = 444;
16707 t['abreve'] = 500;
16708 t['uhungarumlaut'] = 556;
16709 t['ecaron'] = 444;
16710 t['Ydieresis'] = 611;
16711 t['divide'] = 570;
16712 t['Yacute'] = 611;
16713 t['Acircumflex'] = 667;
16714 t['aacute'] = 500;
16715 t['Ucircumflex'] = 722;
16716 t['yacute'] = 444;
16717 t['scommaaccent'] = 389;
16718 t['ecircumflex'] = 444;
16719 t['Uring'] = 722;
16720 t['Udieresis'] = 722;
16721 t['aogonek'] = 500;
16722 t['Uacute'] = 722;
16723 t['uogonek'] = 556;
16724 t['Edieresis'] = 667;
16725 t['Dcroat'] = 722;
16726 t['commaaccent'] = 250;
16727 t['copyright'] = 747;
16728 t['Emacron'] = 667;
16729 t['ccaron'] = 444;
16730 t['aring'] = 500;
16731 t['Ncommaaccent'] = 722;
16732 t['lacute'] = 278;
16733 t['agrave'] = 500;
16734 t['Tcommaaccent'] = 611;
16735 t['Cacute'] = 667;
16736 t['atilde'] = 500;
16737 t['Edotaccent'] = 667;
16738 t['scaron'] = 389;
16739 t['scedilla'] = 389;
16740 t['iacute'] = 278;
16741 t['lozenge'] = 494;
16742 t['Rcaron'] = 667;
16743 t['Gcommaaccent'] = 722;
16744 t['ucircumflex'] = 556;
16745 t['acircumflex'] = 500;
16746 t['Amacron'] = 667;
16747 t['rcaron'] = 389;
16748 t['ccedilla'] = 444;
16749 t['Zdotaccent'] = 611;
16750 t['Thorn'] = 611;
16751 t['Omacron'] = 722;
16752 t['Racute'] = 667;
16753 t['Sacute'] = 556;
16754 t['dcaron'] = 608;
16755 t['Umacron'] = 722;
16756 t['uring'] = 556;
16757 t['threesuperior'] = 300;
16758 t['Ograve'] = 722;
16759 t['Agrave'] = 667;
16760 t['Abreve'] = 667;
16761 t['multiply'] = 570;
16762 t['uacute'] = 556;
16763 t['Tcaron'] = 611;
16764 t['partialdiff'] = 494;
16765 t['ydieresis'] = 444;
16766 t['Nacute'] = 722;
16767 t['icircumflex'] = 278;
16768 t['Ecircumflex'] = 667;
16769 t['adieresis'] = 500;
16770 t['edieresis'] = 444;
16771 t['cacute'] = 444;
16772 t['nacute'] = 556;
16773 t['umacron'] = 556;
16774 t['Ncaron'] = 722;
16775 t['Iacute'] = 389;
16776 t['plusminus'] = 570;
16777 t['brokenbar'] = 220;
16778 t['registered'] = 747;
16779 t['Gbreve'] = 722;
16780 t['Idotaccent'] = 389;
16781 t['summation'] = 600;
16782 t['Egrave'] = 667;
16783 t['racute'] = 389;
16784 t['omacron'] = 500;
16785 t['Zacute'] = 611;
16786 t['Zcaron'] = 611;
16787 t['greaterequal'] = 549;
16788 t['Eth'] = 722;
16789 t['Ccedilla'] = 667;
16790 t['lcommaaccent'] = 278;
16791 t['tcaron'] = 366;
16792 t['eogonek'] = 444;
16793 t['Uogonek'] = 722;
16794 t['Aacute'] = 667;
16795 t['Adieresis'] = 667;
16796 t['egrave'] = 444;
16797 t['zacute'] = 389;
16798 t['iogonek'] = 278;
16799 t['Oacute'] = 722;
16800 t['oacute'] = 500;
16801 t['amacron'] = 500;
16802 t['sacute'] = 389;
16803 t['idieresis'] = 278;
16804 t['Ocircumflex'] = 722;
16805 t['Ugrave'] = 722;
16806 t['Delta'] = 612;
16807 t['thorn'] = 500;
16808 t['twosuperior'] = 300;
16809 t['Odieresis'] = 722;
16810 t['mu'] = 576;
16811 t['igrave'] = 278;
16812 t['ohungarumlaut'] = 500;
16813 t['Eogonek'] = 667;
16814 t['dcroat'] = 500;
16815 t['threequarters'] = 750;
16816 t['Scedilla'] = 556;
16817 t['lcaron'] = 382;
16818 t['Kcommaaccent'] = 667;
16819 t['Lacute'] = 611;
16820 t['trademark'] = 1000;
16821 t['edotaccent'] = 444;
16822 t['Igrave'] = 389;
16823 t['Imacron'] = 389;
16824 t['Lcaron'] = 611;
16825 t['onehalf'] = 750;
16826 t['lessequal'] = 549;
16827 t['ocircumflex'] = 500;
16828 t['ntilde'] = 556;
16829 t['Uhungarumlaut'] = 722;
16830 t['Eacute'] = 667;
16831 t['emacron'] = 444;
16832 t['gbreve'] = 500;
16833 t['onequarter'] = 750;
16834 t['Scaron'] = 556;
16835 t['Scommaaccent'] = 556;
16836 t['Ohungarumlaut'] = 722;
16837 t['degree'] = 400;
16838 t['ograve'] = 500;
16839 t['Ccaron'] = 667;
16840 t['ugrave'] = 556;
16841 t['radical'] = 549;
16842 t['Dcaron'] = 722;
16843 t['rcommaaccent'] = 389;
16844 t['Ntilde'] = 722;
16845 t['otilde'] = 500;
16846 t['Rcommaaccent'] = 667;
16847 t['Lcommaaccent'] = 611;
16848 t['Atilde'] = 667;
16849 t['Aogonek'] = 667;
16850 t['Aring'] = 667;
16851 t['Otilde'] = 722;
16852 t['zdotaccent'] = 389;
16853 t['Ecaron'] = 667;
16854 t['Iogonek'] = 389;
16855 t['kcommaaccent'] = 500;
16856 t['minus'] = 606;
16857 t['Icircumflex'] = 389;
16858 t['ncaron'] = 556;
16859 t['tcommaaccent'] = 278;
16860 t['logicalnot'] = 606;
16861 t['odieresis'] = 500;
16862 t['udieresis'] = 556;
16863 t['notequal'] = 549;
16864 t['gcommaaccent'] = 500;
16865 t['eth'] = 500;
16866 t['zcaron'] = 389;
16867 t['ncommaaccent'] = 556;
16868 t['onesuperior'] = 300;
16869 t['imacron'] = 278;
16870 t['Euro'] = 500;
16871 });
16872 t['Times-Italic'] = getLookupTableFactory(function (t) {
16873 t['space'] = 250;
16874 t['exclam'] = 333;
16875 t['quotedbl'] = 420;
16876 t['numbersign'] = 500;
16877 t['dollar'] = 500;
16878 t['percent'] = 833;
16879 t['ampersand'] = 778;
16880 t['quoteright'] = 333;
16881 t['parenleft'] = 333;
16882 t['parenright'] = 333;
16883 t['asterisk'] = 500;
16884 t['plus'] = 675;
16885 t['comma'] = 250;
16886 t['hyphen'] = 333;
16887 t['period'] = 250;
16888 t['slash'] = 278;
16889 t['zero'] = 500;
16890 t['one'] = 500;
16891 t['two'] = 500;
16892 t['three'] = 500;
16893 t['four'] = 500;
16894 t['five'] = 500;
16895 t['six'] = 500;
16896 t['seven'] = 500;
16897 t['eight'] = 500;
16898 t['nine'] = 500;
16899 t['colon'] = 333;
16900 t['semicolon'] = 333;
16901 t['less'] = 675;
16902 t['equal'] = 675;
16903 t['greater'] = 675;
16904 t['question'] = 500;
16905 t['at'] = 920;
16906 t['A'] = 611;
16907 t['B'] = 611;
16908 t['C'] = 667;
16909 t['D'] = 722;
16910 t['E'] = 611;
16911 t['F'] = 611;
16912 t['G'] = 722;
16913 t['H'] = 722;
16914 t['I'] = 333;
16915 t['J'] = 444;
16916 t['K'] = 667;
16917 t['L'] = 556;
16918 t['M'] = 833;
16919 t['N'] = 667;
16920 t['O'] = 722;
16921 t['P'] = 611;
16922 t['Q'] = 722;
16923 t['R'] = 611;
16924 t['S'] = 500;
16925 t['T'] = 556;
16926 t['U'] = 722;
16927 t['V'] = 611;
16928 t['W'] = 833;
16929 t['X'] = 611;
16930 t['Y'] = 556;
16931 t['Z'] = 556;
16932 t['bracketleft'] = 389;
16933 t['backslash'] = 278;
16934 t['bracketright'] = 389;
16935 t['asciicircum'] = 422;
16936 t['underscore'] = 500;
16937 t['quoteleft'] = 333;
16938 t['a'] = 500;
16939 t['b'] = 500;
16940 t['c'] = 444;
16941 t['d'] = 500;
16942 t['e'] = 444;
16943 t['f'] = 278;
16944 t['g'] = 500;
16945 t['h'] = 500;
16946 t['i'] = 278;
16947 t['j'] = 278;
16948 t['k'] = 444;
16949 t['l'] = 278;
16950 t['m'] = 722;
16951 t['n'] = 500;
16952 t['o'] = 500;
16953 t['p'] = 500;
16954 t['q'] = 500;
16955 t['r'] = 389;
16956 t['s'] = 389;
16957 t['t'] = 278;
16958 t['u'] = 500;
16959 t['v'] = 444;
16960 t['w'] = 667;
16961 t['x'] = 444;
16962 t['y'] = 444;
16963 t['z'] = 389;
16964 t['braceleft'] = 400;
16965 t['bar'] = 275;
16966 t['braceright'] = 400;
16967 t['asciitilde'] = 541;
16968 t['exclamdown'] = 389;
16969 t['cent'] = 500;
16970 t['sterling'] = 500;
16971 t['fraction'] = 167;
16972 t['yen'] = 500;
16973 t['florin'] = 500;
16974 t['section'] = 500;
16975 t['currency'] = 500;
16976 t['quotesingle'] = 214;
16977 t['quotedblleft'] = 556;
16978 t['guillemotleft'] = 500;
16979 t['guilsinglleft'] = 333;
16980 t['guilsinglright'] = 333;
16981 t['fi'] = 500;
16982 t['fl'] = 500;
16983 t['endash'] = 500;
16984 t['dagger'] = 500;
16985 t['daggerdbl'] = 500;
16986 t['periodcentered'] = 250;
16987 t['paragraph'] = 523;
16988 t['bullet'] = 350;
16989 t['quotesinglbase'] = 333;
16990 t['quotedblbase'] = 556;
16991 t['quotedblright'] = 556;
16992 t['guillemotright'] = 500;
16993 t['ellipsis'] = 889;
16994 t['perthousand'] = 1000;
16995 t['questiondown'] = 500;
16996 t['grave'] = 333;
16997 t['acute'] = 333;
16998 t['circumflex'] = 333;
16999 t['tilde'] = 333;
17000 t['macron'] = 333;
17001 t['breve'] = 333;
17002 t['dotaccent'] = 333;
17003 t['dieresis'] = 333;
17004 t['ring'] = 333;
17005 t['cedilla'] = 333;
17006 t['hungarumlaut'] = 333;
17007 t['ogonek'] = 333;
17008 t['caron'] = 333;
17009 t['emdash'] = 889;
17010 t['AE'] = 889;
17011 t['ordfeminine'] = 276;
17012 t['Lslash'] = 556;
17013 t['Oslash'] = 722;
17014 t['OE'] = 944;
17015 t['ordmasculine'] = 310;
17016 t['ae'] = 667;
17017 t['dotlessi'] = 278;
17018 t['lslash'] = 278;
17019 t['oslash'] = 500;
17020 t['oe'] = 667;
17021 t['germandbls'] = 500;
17022 t['Idieresis'] = 333;
17023 t['eacute'] = 444;
17024 t['abreve'] = 500;
17025 t['uhungarumlaut'] = 500;
17026 t['ecaron'] = 444;
17027 t['Ydieresis'] = 556;
17028 t['divide'] = 675;
17029 t['Yacute'] = 556;
17030 t['Acircumflex'] = 611;
17031 t['aacute'] = 500;
17032 t['Ucircumflex'] = 722;
17033 t['yacute'] = 444;
17034 t['scommaaccent'] = 389;
17035 t['ecircumflex'] = 444;
17036 t['Uring'] = 722;
17037 t['Udieresis'] = 722;
17038 t['aogonek'] = 500;
17039 t['Uacute'] = 722;
17040 t['uogonek'] = 500;
17041 t['Edieresis'] = 611;
17042 t['Dcroat'] = 722;
17043 t['commaaccent'] = 250;
17044 t['copyright'] = 760;
17045 t['Emacron'] = 611;
17046 t['ccaron'] = 444;
17047 t['aring'] = 500;
17048 t['Ncommaaccent'] = 667;
17049 t['lacute'] = 278;
17050 t['agrave'] = 500;
17051 t['Tcommaaccent'] = 556;
17052 t['Cacute'] = 667;
17053 t['atilde'] = 500;
17054 t['Edotaccent'] = 611;
17055 t['scaron'] = 389;
17056 t['scedilla'] = 389;
17057 t['iacute'] = 278;
17058 t['lozenge'] = 471;
17059 t['Rcaron'] = 611;
17060 t['Gcommaaccent'] = 722;
17061 t['ucircumflex'] = 500;
17062 t['acircumflex'] = 500;
17063 t['Amacron'] = 611;
17064 t['rcaron'] = 389;
17065 t['ccedilla'] = 444;
17066 t['Zdotaccent'] = 556;
17067 t['Thorn'] = 611;
17068 t['Omacron'] = 722;
17069 t['Racute'] = 611;
17070 t['Sacute'] = 500;
17071 t['dcaron'] = 544;
17072 t['Umacron'] = 722;
17073 t['uring'] = 500;
17074 t['threesuperior'] = 300;
17075 t['Ograve'] = 722;
17076 t['Agrave'] = 611;
17077 t['Abreve'] = 611;
17078 t['multiply'] = 675;
17079 t['uacute'] = 500;
17080 t['Tcaron'] = 556;
17081 t['partialdiff'] = 476;
17082 t['ydieresis'] = 444;
17083 t['Nacute'] = 667;
17084 t['icircumflex'] = 278;
17085 t['Ecircumflex'] = 611;
17086 t['adieresis'] = 500;
17087 t['edieresis'] = 444;
17088 t['cacute'] = 444;
17089 t['nacute'] = 500;
17090 t['umacron'] = 500;
17091 t['Ncaron'] = 667;
17092 t['Iacute'] = 333;
17093 t['plusminus'] = 675;
17094 t['brokenbar'] = 275;
17095 t['registered'] = 760;
17096 t['Gbreve'] = 722;
17097 t['Idotaccent'] = 333;
17098 t['summation'] = 600;
17099 t['Egrave'] = 611;
17100 t['racute'] = 389;
17101 t['omacron'] = 500;
17102 t['Zacute'] = 556;
17103 t['Zcaron'] = 556;
17104 t['greaterequal'] = 549;
17105 t['Eth'] = 722;
17106 t['Ccedilla'] = 667;
17107 t['lcommaaccent'] = 278;
17108 t['tcaron'] = 300;
17109 t['eogonek'] = 444;
17110 t['Uogonek'] = 722;
17111 t['Aacute'] = 611;
17112 t['Adieresis'] = 611;
17113 t['egrave'] = 444;
17114 t['zacute'] = 389;
17115 t['iogonek'] = 278;
17116 t['Oacute'] = 722;
17117 t['oacute'] = 500;
17118 t['amacron'] = 500;
17119 t['sacute'] = 389;
17120 t['idieresis'] = 278;
17121 t['Ocircumflex'] = 722;
17122 t['Ugrave'] = 722;
17123 t['Delta'] = 612;
17124 t['thorn'] = 500;
17125 t['twosuperior'] = 300;
17126 t['Odieresis'] = 722;
17127 t['mu'] = 500;
17128 t['igrave'] = 278;
17129 t['ohungarumlaut'] = 500;
17130 t['Eogonek'] = 611;
17131 t['dcroat'] = 500;
17132 t['threequarters'] = 750;
17133 t['Scedilla'] = 500;
17134 t['lcaron'] = 300;
17135 t['Kcommaaccent'] = 667;
17136 t['Lacute'] = 556;
17137 t['trademark'] = 980;
17138 t['edotaccent'] = 444;
17139 t['Igrave'] = 333;
17140 t['Imacron'] = 333;
17141 t['Lcaron'] = 611;
17142 t['onehalf'] = 750;
17143 t['lessequal'] = 549;
17144 t['ocircumflex'] = 500;
17145 t['ntilde'] = 500;
17146 t['Uhungarumlaut'] = 722;
17147 t['Eacute'] = 611;
17148 t['emacron'] = 444;
17149 t['gbreve'] = 500;
17150 t['onequarter'] = 750;
17151 t['Scaron'] = 500;
17152 t['Scommaaccent'] = 500;
17153 t['Ohungarumlaut'] = 722;
17154 t['degree'] = 400;
17155 t['ograve'] = 500;
17156 t['Ccaron'] = 667;
17157 t['ugrave'] = 500;
17158 t['radical'] = 453;
17159 t['Dcaron'] = 722;
17160 t['rcommaaccent'] = 389;
17161 t['Ntilde'] = 667;
17162 t['otilde'] = 500;
17163 t['Rcommaaccent'] = 611;
17164 t['Lcommaaccent'] = 556;
17165 t['Atilde'] = 611;
17166 t['Aogonek'] = 611;
17167 t['Aring'] = 611;
17168 t['Otilde'] = 722;
17169 t['zdotaccent'] = 389;
17170 t['Ecaron'] = 611;
17171 t['Iogonek'] = 333;
17172 t['kcommaaccent'] = 444;
17173 t['minus'] = 675;
17174 t['Icircumflex'] = 333;
17175 t['ncaron'] = 500;
17176 t['tcommaaccent'] = 278;
17177 t['logicalnot'] = 675;
17178 t['odieresis'] = 500;
17179 t['udieresis'] = 500;
17180 t['notequal'] = 549;
17181 t['gcommaaccent'] = 500;
17182 t['eth'] = 500;
17183 t['zcaron'] = 389;
17184 t['ncommaaccent'] = 500;
17185 t['onesuperior'] = 300;
17186 t['imacron'] = 278;
17187 t['Euro'] = 500;
17188 });
17189 t['ZapfDingbats'] = getLookupTableFactory(function (t) {
17190 t['space'] = 278;
17191 t['a1'] = 974;
17192 t['a2'] = 961;
17193 t['a202'] = 974;
17194 t['a3'] = 980;
17195 t['a4'] = 719;
17196 t['a5'] = 789;
17197 t['a119'] = 790;
17198 t['a118'] = 791;
17199 t['a117'] = 690;
17200 t['a11'] = 960;
17201 t['a12'] = 939;
17202 t['a13'] = 549;
17203 t['a14'] = 855;
17204 t['a15'] = 911;
17205 t['a16'] = 933;
17206 t['a105'] = 911;
17207 t['a17'] = 945;
17208 t['a18'] = 974;
17209 t['a19'] = 755;
17210 t['a20'] = 846;
17211 t['a21'] = 762;
17212 t['a22'] = 761;
17213 t['a23'] = 571;
17214 t['a24'] = 677;
17215 t['a25'] = 763;
17216 t['a26'] = 760;
17217 t['a27'] = 759;
17218 t['a28'] = 754;
17219 t['a6'] = 494;
17220 t['a7'] = 552;
17221 t['a8'] = 537;
17222 t['a9'] = 577;
17223 t['a10'] = 692;
17224 t['a29'] = 786;
17225 t['a30'] = 788;
17226 t['a31'] = 788;
17227 t['a32'] = 790;
17228 t['a33'] = 793;
17229 t['a34'] = 794;
17230 t['a35'] = 816;
17231 t['a36'] = 823;
17232 t['a37'] = 789;
17233 t['a38'] = 841;
17234 t['a39'] = 823;
17235 t['a40'] = 833;
17236 t['a41'] = 816;
17237 t['a42'] = 831;
17238 t['a43'] = 923;
17239 t['a44'] = 744;
17240 t['a45'] = 723;
17241 t['a46'] = 749;
17242 t['a47'] = 790;
17243 t['a48'] = 792;
17244 t['a49'] = 695;
17245 t['a50'] = 776;
17246 t['a51'] = 768;
17247 t['a52'] = 792;
17248 t['a53'] = 759;
17249 t['a54'] = 707;
17250 t['a55'] = 708;
17251 t['a56'] = 682;
17252 t['a57'] = 701;
17253 t['a58'] = 826;
17254 t['a59'] = 815;
17255 t['a60'] = 789;
17256 t['a61'] = 789;
17257 t['a62'] = 707;
17258 t['a63'] = 687;
17259 t['a64'] = 696;
17260 t['a65'] = 689;
17261 t['a66'] = 786;
17262 t['a67'] = 787;
17263 t['a68'] = 713;
17264 t['a69'] = 791;
17265 t['a70'] = 785;
17266 t['a71'] = 791;
17267 t['a72'] = 873;
17268 t['a73'] = 761;
17269 t['a74'] = 762;
17270 t['a203'] = 762;
17271 t['a75'] = 759;
17272 t['a204'] = 759;
17273 t['a76'] = 892;
17274 t['a77'] = 892;
17275 t['a78'] = 788;
17276 t['a79'] = 784;
17277 t['a81'] = 438;
17278 t['a82'] = 138;
17279 t['a83'] = 277;
17280 t['a84'] = 415;
17281 t['a97'] = 392;
17282 t['a98'] = 392;
17283 t['a99'] = 668;
17284 t['a100'] = 668;
17285 t['a89'] = 390;
17286 t['a90'] = 390;
17287 t['a93'] = 317;
17288 t['a94'] = 317;
17289 t['a91'] = 276;
17290 t['a92'] = 276;
17291 t['a205'] = 509;
17292 t['a85'] = 509;
17293 t['a206'] = 410;
17294 t['a86'] = 410;
17295 t['a87'] = 234;
17296 t['a88'] = 234;
17297 t['a95'] = 334;
17298 t['a96'] = 334;
17299 t['a101'] = 732;
17300 t['a102'] = 544;
17301 t['a103'] = 544;
17302 t['a104'] = 910;
17303 t['a106'] = 667;
17304 t['a107'] = 760;
17305 t['a108'] = 760;
17306 t['a112'] = 776;
17307 t['a111'] = 595;
17308 t['a110'] = 694;
17309 t['a109'] = 626;
17310 t['a120'] = 788;
17311 t['a121'] = 788;
17312 t['a122'] = 788;
17313 t['a123'] = 788;
17314 t['a124'] = 788;
17315 t['a125'] = 788;
17316 t['a126'] = 788;
17317 t['a127'] = 788;
17318 t['a128'] = 788;
17319 t['a129'] = 788;
17320 t['a130'] = 788;
17321 t['a131'] = 788;
17322 t['a132'] = 788;
17323 t['a133'] = 788;
17324 t['a134'] = 788;
17325 t['a135'] = 788;
17326 t['a136'] = 788;
17327 t['a137'] = 788;
17328 t['a138'] = 788;
17329 t['a139'] = 788;
17330 t['a140'] = 788;
17331 t['a141'] = 788;
17332 t['a142'] = 788;
17333 t['a143'] = 788;
17334 t['a144'] = 788;
17335 t['a145'] = 788;
17336 t['a146'] = 788;
17337 t['a147'] = 788;
17338 t['a148'] = 788;
17339 t['a149'] = 788;
17340 t['a150'] = 788;
17341 t['a151'] = 788;
17342 t['a152'] = 788;
17343 t['a153'] = 788;
17344 t['a154'] = 788;
17345 t['a155'] = 788;
17346 t['a156'] = 788;
17347 t['a157'] = 788;
17348 t['a158'] = 788;
17349 t['a159'] = 788;
17350 t['a160'] = 894;
17351 t['a161'] = 838;
17352 t['a163'] = 1016;
17353 t['a164'] = 458;
17354 t['a196'] = 748;
17355 t['a165'] = 924;
17356 t['a192'] = 748;
17357 t['a166'] = 918;
17358 t['a167'] = 927;
17359 t['a168'] = 928;
17360 t['a169'] = 928;
17361 t['a170'] = 834;
17362 t['a171'] = 873;
17363 t['a172'] = 828;
17364 t['a173'] = 924;
17365 t['a162'] = 924;
17366 t['a174'] = 917;
17367 t['a175'] = 930;
17368 t['a176'] = 931;
17369 t['a177'] = 463;
17370 t['a178'] = 883;
17371 t['a179'] = 836;
17372 t['a193'] = 836;
17373 t['a180'] = 867;
17374 t['a199'] = 867;
17375 t['a181'] = 696;
17376 t['a200'] = 696;
17377 t['a182'] = 874;
17378 t['a201'] = 874;
17379 t['a183'] = 760;
17380 t['a184'] = 946;
17381 t['a197'] = 771;
17382 t['a185'] = 865;
17383 t['a194'] = 771;
17384 t['a198'] = 888;
17385 t['a186'] = 967;
17386 t['a195'] = 888;
17387 t['a187'] = 831;
17388 t['a188'] = 873;
17389 t['a189'] = 927;
17390 t['a190'] = 970;
17391 t['a191'] = 918;
17392 });
17393});
17394
17395exports.getMetrics = getMetrics;
17396}));
17397
17398
17399
17400(function (root, factory) {
17401 {
17402 factory((root.pdfjsCoreMurmurHash3 = {}), root.pdfjsSharedUtil);
17403 }
17404}(this, function (exports, sharedUtil) {
17405
17406var Uint32ArrayView = sharedUtil.Uint32ArrayView;
17407
17408var MurmurHash3_64 = (function MurmurHash3_64Closure (seed) {
17409 // Workaround for missing math precision in JS.
17410 var MASK_HIGH = 0xffff0000;
17411 var MASK_LOW = 0xffff;
17412
17413 function MurmurHash3_64 (seed) {
17414 var SEED = 0xc3d2e1f0;
17415 this.h1 = seed ? seed & 0xffffffff : SEED;
17416 this.h2 = seed ? seed & 0xffffffff : SEED;
17417 }
17418
17419 var alwaysUseUint32ArrayView = false;
17420 // old webkits have issues with non-aligned arrays
17421 try {
17422 new Uint32Array(new Uint8Array(5).buffer, 0, 1);
17423 } catch (e) {
17424 alwaysUseUint32ArrayView = true;
17425 }
17426
17427 MurmurHash3_64.prototype = {
17428 update: function MurmurHash3_64_update(input) {
17429 var useUint32ArrayView = alwaysUseUint32ArrayView;
17430 var i;
17431 if (typeof input === 'string') {
17432 var data = new Uint8Array(input.length * 2);
17433 var length = 0;
17434 for (i = 0; i < input.length; i++) {
17435 var code = input.charCodeAt(i);
17436 if (code <= 0xff) {
17437 data[length++] = code;
17438 }
17439 else {
17440 data[length++] = code >>> 8;
17441 data[length++] = code & 0xff;
17442 }
17443 }
17444 } else if (input instanceof Uint8Array) {
17445 data = input;
17446 length = data.length;
17447 } else if (typeof input === 'object' && ('length' in input)) {
17448 // processing regular arrays as well, e.g. for IE9
17449 data = input;
17450 length = data.length;
17451 useUint32ArrayView = true;
17452 } else {
17453 throw new Error('Wrong data format in MurmurHash3_64_update. ' +
17454 'Input must be a string or array.');
17455 }
17456
17457 var blockCounts = length >> 2;
17458 var tailLength = length - blockCounts * 4;
17459 // we don't care about endianness here
17460 var dataUint32 = useUint32ArrayView ?
17461 new Uint32ArrayView(data, blockCounts) :
17462 new Uint32Array(data.buffer, 0, blockCounts);
17463 var k1 = 0;
17464 var k2 = 0;
17465 var h1 = this.h1;
17466 var h2 = this.h2;
17467 var C1 = 0xcc9e2d51;
17468 var C2 = 0x1b873593;
17469 var C1_LOW = C1 & MASK_LOW;
17470 var C2_LOW = C2 & MASK_LOW;
17471
17472 for (i = 0; i < blockCounts; i++) {
17473 if (i & 1) {
17474 k1 = dataUint32[i];
17475 k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW);
17476 k1 = k1 << 15 | k1 >>> 17;
17477 k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW);
17478 h1 ^= k1;
17479 h1 = h1 << 13 | h1 >>> 19;
17480 h1 = h1 * 5 + 0xe6546b64;
17481 } else {
17482 k2 = dataUint32[i];
17483 k2 = (k2 * C1 & MASK_HIGH) | (k2 * C1_LOW & MASK_LOW);
17484 k2 = k2 << 15 | k2 >>> 17;
17485 k2 = (k2 * C2 & MASK_HIGH) | (k2 * C2_LOW & MASK_LOW);
17486 h2 ^= k2;
17487 h2 = h2 << 13 | h2 >>> 19;
17488 h2 = h2 * 5 + 0xe6546b64;
17489 }
17490 }
17491
17492 k1 = 0;
17493
17494 switch (tailLength) {
17495 case 3:
17496 k1 ^= data[blockCounts * 4 + 2] << 16;
17497 /* falls through */
17498 case 2:
17499 k1 ^= data[blockCounts * 4 + 1] << 8;
17500 /* falls through */
17501 case 1:
17502 k1 ^= data[blockCounts * 4];
17503 /* falls through */
17504 k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW);
17505 k1 = k1 << 15 | k1 >>> 17;
17506 k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW);
17507 if (blockCounts & 1) {
17508 h1 ^= k1;
17509 } else {
17510 h2 ^= k1;
17511 }
17512 }
17513
17514 this.h1 = h1;
17515 this.h2 = h2;
17516 return this;
17517 },
17518
17519 hexdigest: function MurmurHash3_64_hexdigest () {
17520 var h1 = this.h1;
17521 var h2 = this.h2;
17522
17523 h1 ^= h2 >>> 1;
17524 h1 = (h1 * 0xed558ccd & MASK_HIGH) | (h1 * 0x8ccd & MASK_LOW);
17525 h2 = (h2 * 0xff51afd7 & MASK_HIGH) |
17526 (((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16);
17527 h1 ^= h2 >>> 1;
17528 h1 = (h1 * 0x1a85ec53 & MASK_HIGH) | (h1 * 0xec53 & MASK_LOW);
17529 h2 = (h2 * 0xc4ceb9fe & MASK_HIGH) |
17530 (((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16);
17531 h1 ^= h2 >>> 1;
17532
17533 for (var i = 0, arr = [h1, h2], str = ''; i < arr.length; i++) {
17534 var hex = (arr[i] >>> 0).toString(16);
17535 while (hex.length < 8) {
17536 hex = '0' + hex;
17537 }
17538 str += hex;
17539 }
17540
17541 return str;
17542 }
17543 };
17544
17545 return MurmurHash3_64;
17546})();
17547
17548exports.MurmurHash3_64 = MurmurHash3_64;
17549}));
17550
17551
17552(function (root, factory) {
17553 {
17554 factory((root.pdfjsCorePrimitives = {}), root.pdfjsSharedUtil);
17555 }
17556}(this, function (exports, sharedUtil) {
17557
17558var isArray = sharedUtil.isArray;
17559
17560var Name = (function NameClosure() {
17561 function Name(name) {
17562 this.name = name;
17563 }
17564
17565 Name.prototype = {};
17566
17567 var nameCache = Object.create(null);
17568
17569 Name.get = function Name_get(name) {
17570 var nameValue = nameCache[name];
17571 return (nameValue ? nameValue : (nameCache[name] = new Name(name)));
17572 };
17573
17574 return Name;
17575})();
17576
17577var Cmd = (function CmdClosure() {
17578 function Cmd(cmd) {
17579 this.cmd = cmd;
17580 }
17581
17582 Cmd.prototype = {};
17583
17584 var cmdCache = Object.create(null);
17585
17586 Cmd.get = function Cmd_get(cmd) {
17587 var cmdValue = cmdCache[cmd];
17588 return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd)));
17589 };
17590
17591 return Cmd;
17592})();
17593
17594var Dict = (function DictClosure() {
17595 var nonSerializable = function nonSerializableClosure() {
17596 return nonSerializable; // creating closure on some variable
17597 };
17598
17599 // xref is optional
17600 function Dict(xref) {
17601 // Map should only be used internally, use functions below to access.
17602 this.map = Object.create(null);
17603 this.xref = xref;
17604 this.objId = null;
17605 this.__nonSerializable__ = nonSerializable; // disable cloning of the Dict
17606 }
17607
17608 Dict.prototype = {
17609 assignXref: function Dict_assignXref(newXref) {
17610 this.xref = newXref;
17611 },
17612
17613 // automatically dereferences Ref objects
17614 get: function Dict_get(key1, key2, key3) {
17615 var value;
17616 var xref = this.xref;
17617 if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map ||
17618 typeof key2 === 'undefined') {
17619 return xref ? xref.fetchIfRef(value) : value;
17620 }
17621 if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map ||
17622 typeof key3 === 'undefined') {
17623 return xref ? xref.fetchIfRef(value) : value;
17624 }
17625 value = this.map[key3] || null;
17626 return xref ? xref.fetchIfRef(value) : value;
17627 },
17628
17629 // Same as get(), but returns a promise and uses fetchIfRefAsync().
17630 getAsync: function Dict_getAsync(key1, key2, key3) {
17631 var value;
17632 var xref = this.xref;
17633 if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map ||
17634 typeof key2 === 'undefined') {
17635 if (xref) {
17636 return xref.fetchIfRefAsync(value);
17637 }
17638 return Promise.resolve(value);
17639 }
17640 if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map ||
17641 typeof key3 === 'undefined') {
17642 if (xref) {
17643 return xref.fetchIfRefAsync(value);
17644 }
17645 return Promise.resolve(value);
17646 }
17647 value = this.map[key3] || null;
17648 if (xref) {
17649 return xref.fetchIfRefAsync(value);
17650 }
17651 return Promise.resolve(value);
17652 },
17653
17654 // Same as get(), but dereferences all elements if the result is an Array.
17655 getArray: function Dict_getArray(key1, key2, key3) {
17656 var value = this.get(key1, key2, key3);
17657 var xref = this.xref;
17658 if (!isArray(value) || !xref) {
17659 return value;
17660 }
17661 value = value.slice(); // Ensure that we don't modify the Dict data.
17662 for (var i = 0, ii = value.length; i < ii; i++) {
17663 if (!isRef(value[i])) {
17664 continue;
17665 }
17666 value[i] = xref.fetch(value[i]);
17667 }
17668 return value;
17669 },
17670
17671 // no dereferencing
17672 getRaw: function Dict_getRaw(key) {
17673 return this.map[key];
17674 },
17675
17676 getKeys: function Dict_getKeys() {
17677 return Object.keys(this.map);
17678 },
17679
17680 set: function Dict_set(key, value) {
17681 this.map[key] = value;
17682 },
17683
17684 has: function Dict_has(key) {
17685 return key in this.map;
17686 },
17687
17688 forEach: function Dict_forEach(callback) {
17689 for (var key in this.map) {
17690 callback(key, this.get(key));
17691 }
17692 }
17693 };
17694
17695 Dict.empty = new Dict(null);
17696
17697 Dict.merge = function Dict_merge(xref, dictArray) {
17698 var mergedDict = new Dict(xref);
17699
17700 for (var i = 0, ii = dictArray.length; i < ii; i++) {
17701 var dict = dictArray[i];
17702 if (!isDict(dict)) {
17703 continue;
17704 }
17705 for (var keyName in dict.map) {
17706 if (mergedDict.map[keyName]) {
17707 continue;
17708 }
17709 mergedDict.map[keyName] = dict.map[keyName];
17710 }
17711 }
17712 return mergedDict;
17713 };
17714
17715 return Dict;
17716})();
17717
17718var Ref = (function RefClosure() {
17719 function Ref(num, gen) {
17720 this.num = num;
17721 this.gen = gen;
17722 }
17723
17724 Ref.prototype = {
17725 toString: function Ref_toString() {
17726 // This function is hot, so we make the string as compact as possible.
17727 // |this.gen| is almost always zero, so we treat that case specially.
17728 var str = this.num + 'R';
17729 if (this.gen !== 0) {
17730 str += this.gen;
17731 }
17732 return str;
17733 }
17734 };
17735
17736 return Ref;
17737})();
17738
17739// The reference is identified by number and generation.
17740// This structure stores only one instance of the reference.
17741var RefSet = (function RefSetClosure() {
17742 function RefSet() {
17743 this.dict = Object.create(null);
17744 }
17745
17746 RefSet.prototype = {
17747 has: function RefSet_has(ref) {
17748 return ref.toString() in this.dict;
17749 },
17750
17751 put: function RefSet_put(ref) {
17752 this.dict[ref.toString()] = true;
17753 },
17754
17755 remove: function RefSet_remove(ref) {
17756 delete this.dict[ref.toString()];
17757 }
17758 };
17759
17760 return RefSet;
17761})();
17762
17763var RefSetCache = (function RefSetCacheClosure() {
17764 function RefSetCache() {
17765 this.dict = Object.create(null);
17766 }
17767
17768 RefSetCache.prototype = {
17769 get: function RefSetCache_get(ref) {
17770 return this.dict[ref.toString()];
17771 },
17772
17773 has: function RefSetCache_has(ref) {
17774 return ref.toString() in this.dict;
17775 },
17776
17777 put: function RefSetCache_put(ref, obj) {
17778 this.dict[ref.toString()] = obj;
17779 },
17780
17781 putAlias: function RefSetCache_putAlias(ref, aliasRef) {
17782 this.dict[ref.toString()] = this.get(aliasRef);
17783 },
17784
17785 forEach: function RefSetCache_forEach(fn, thisArg) {
17786 for (var i in this.dict) {
17787 fn.call(thisArg, this.dict[i]);
17788 }
17789 },
17790
17791 clear: function RefSetCache_clear() {
17792 this.dict = Object.create(null);
17793 }
17794 };
17795
17796 return RefSetCache;
17797})();
17798
17799function isName(v, name) {
17800 return v instanceof Name && (name === undefined || v.name === name);
17801}
17802
17803function isCmd(v, cmd) {
17804 return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
17805}
17806
17807function isDict(v, type) {
17808 return v instanceof Dict &&
17809 (type === undefined || isName(v.get('Type'), type));
17810}
17811
17812function isRef(v) {
17813 return v instanceof Ref;
17814}
17815
17816function isRefsEqual(v1, v2) {
17817 return v1.num === v2.num && v1.gen === v2.gen;
17818}
17819
17820function isStream(v) {
17821 return typeof v === 'object' && v !== null && v.getBytes !== undefined;
17822}
17823
17824exports.Cmd = Cmd;
17825exports.Dict = Dict;
17826exports.Name = Name;
17827exports.Ref = Ref;
17828exports.RefSet = RefSet;
17829exports.RefSetCache = RefSetCache;
17830exports.isCmd = isCmd;
17831exports.isDict = isDict;
17832exports.isName = isName;
17833exports.isRef = isRef;
17834exports.isRefsEqual = isRefsEqual;
17835exports.isStream = isStream;
17836}));
17837
17838
17839(function (root, factory) {
17840 {
17841 factory((root.pdfjsCoreStandardFonts = {}), root.pdfjsSharedUtil);
17842 }
17843}(this, function (exports, sharedUtil) {
17844 var getLookupTableFactory = sharedUtil.getLookupTableFactory;
17845
17846 /**
17847 * Hold a map of decoded fonts and of the standard fourteen Type1
17848 * fonts and their acronyms.
17849 */
17850 var getStdFontMap = getLookupTableFactory(function (t) {
17851 t['ArialNarrow'] = 'Helvetica';
17852 t['ArialNarrow-Bold'] = 'Helvetica-Bold';
17853 t['ArialNarrow-BoldItalic'] = 'Helvetica-BoldOblique';
17854 t['ArialNarrow-Italic'] = 'Helvetica-Oblique';
17855 t['ArialBlack'] = 'Helvetica';
17856 t['ArialBlack-Bold'] = 'Helvetica-Bold';
17857 t['ArialBlack-BoldItalic'] = 'Helvetica-BoldOblique';
17858 t['ArialBlack-Italic'] = 'Helvetica-Oblique';
17859 t['Arial'] = 'Helvetica';
17860 t['Arial-Bold'] = 'Helvetica-Bold';
17861 t['Arial-BoldItalic'] = 'Helvetica-BoldOblique';
17862 t['Arial-Italic'] = 'Helvetica-Oblique';
17863 t['Arial-BoldItalicMT'] = 'Helvetica-BoldOblique';
17864 t['Arial-BoldMT'] = 'Helvetica-Bold';
17865 t['Arial-ItalicMT'] = 'Helvetica-Oblique';
17866 t['ArialMT'] = 'Helvetica';
17867 t['Courier-Bold'] = 'Courier-Bold';
17868 t['Courier-BoldItalic'] = 'Courier-BoldOblique';
17869 t['Courier-Italic'] = 'Courier-Oblique';
17870 t['CourierNew'] = 'Courier';
17871 t['CourierNew-Bold'] = 'Courier-Bold';
17872 t['CourierNew-BoldItalic'] = 'Courier-BoldOblique';
17873 t['CourierNew-Italic'] = 'Courier-Oblique';
17874 t['CourierNewPS-BoldItalicMT'] = 'Courier-BoldOblique';
17875 t['CourierNewPS-BoldMT'] = 'Courier-Bold';
17876 t['CourierNewPS-ItalicMT'] = 'Courier-Oblique';
17877 t['CourierNewPSMT'] = 'Courier';
17878 t['Helvetica'] = 'Helvetica';
17879 t['Helvetica-Bold'] = 'Helvetica-Bold';
17880 t['Helvetica-BoldItalic'] = 'Helvetica-BoldOblique';
17881 t['Helvetica-BoldOblique'] = 'Helvetica-BoldOblique';
17882 t['Helvetica-Italic'] = 'Helvetica-Oblique';
17883 t['Helvetica-Oblique'] = 'Helvetica-Oblique';
17884 t['Symbol-Bold'] = 'Symbol';
17885 t['Symbol-BoldItalic'] = 'Symbol';
17886 t['Symbol-Italic'] = 'Symbol';
17887 t['TimesNewRoman'] = 'Times-Roman';
17888 t['TimesNewRoman-Bold'] = 'Times-Bold';
17889 t['TimesNewRoman-BoldItalic'] = 'Times-BoldItalic';
17890 t['TimesNewRoman-Italic'] = 'Times-Italic';
17891 t['TimesNewRomanPS'] = 'Times-Roman';
17892 t['TimesNewRomanPS-Bold'] = 'Times-Bold';
17893 t['TimesNewRomanPS-BoldItalic'] = 'Times-BoldItalic';
17894 t['TimesNewRomanPS-BoldItalicMT'] = 'Times-BoldItalic';
17895 t['TimesNewRomanPS-BoldMT'] = 'Times-Bold';
17896 t['TimesNewRomanPS-Italic'] = 'Times-Italic';
17897 t['TimesNewRomanPS-ItalicMT'] = 'Times-Italic';
17898 t['TimesNewRomanPSMT'] = 'Times-Roman';
17899 t['TimesNewRomanPSMT-Bold'] = 'Times-Bold';
17900 t['TimesNewRomanPSMT-BoldItalic'] = 'Times-BoldItalic';
17901 t['TimesNewRomanPSMT-Italic'] = 'Times-Italic';
17902 });
17903
17904 /**
17905 * Holds the map of the non-standard fonts that might be included as
17906 * a standard fonts without glyph data.
17907 */
17908 var getNonStdFontMap = getLookupTableFactory(function (t) {
17909 t['CenturyGothic'] = 'Helvetica';
17910 t['CenturyGothic-Bold'] = 'Helvetica-Bold';
17911 t['CenturyGothic-BoldItalic'] = 'Helvetica-BoldOblique';
17912 t['CenturyGothic-Italic'] = 'Helvetica-Oblique';
17913 t['ComicSansMS'] = 'Comic Sans MS';
17914 t['ComicSansMS-Bold'] = 'Comic Sans MS-Bold';
17915 t['ComicSansMS-BoldItalic'] = 'Comic Sans MS-BoldItalic';
17916 t['ComicSansMS-Italic'] = 'Comic Sans MS-Italic';
17917 t['LucidaConsole'] = 'Courier';
17918 t['LucidaConsole-Bold'] = 'Courier-Bold';
17919 t['LucidaConsole-BoldItalic'] = 'Courier-BoldOblique';
17920 t['LucidaConsole-Italic'] = 'Courier-Oblique';
17921 t['MS-Gothic'] = 'MS Gothic';
17922 t['MS-Gothic-Bold'] = 'MS Gothic-Bold';
17923 t['MS-Gothic-BoldItalic'] = 'MS Gothic-BoldItalic';
17924 t['MS-Gothic-Italic'] = 'MS Gothic-Italic';
17925 t['MS-Mincho'] = 'MS Mincho';
17926 t['MS-Mincho-Bold'] = 'MS Mincho-Bold';
17927 t['MS-Mincho-BoldItalic'] = 'MS Mincho-BoldItalic';
17928 t['MS-Mincho-Italic'] = 'MS Mincho-Italic';
17929 t['MS-PGothic'] = 'MS PGothic';
17930 t['MS-PGothic-Bold'] = 'MS PGothic-Bold';
17931 t['MS-PGothic-BoldItalic'] = 'MS PGothic-BoldItalic';
17932 t['MS-PGothic-Italic'] = 'MS PGothic-Italic';
17933 t['MS-PMincho'] = 'MS PMincho';
17934 t['MS-PMincho-Bold'] = 'MS PMincho-Bold';
17935 t['MS-PMincho-BoldItalic'] = 'MS PMincho-BoldItalic';
17936 t['MS-PMincho-Italic'] = 'MS PMincho-Italic';
17937 t['Wingdings'] = 'ZapfDingbats';
17938 });
17939
17940 var getSerifFonts = getLookupTableFactory(function (t) {
17941 t['Adobe Jenson'] = true;
17942 t['Adobe Text'] = true;
17943 t['Albertus'] = true;
17944 t['Aldus'] = true;
17945 t['Alexandria'] = true;
17946 t['Algerian'] = true;
17947 t['American Typewriter'] = true;
17948 t['Antiqua'] = true;
17949 t['Apex'] = true;
17950 t['Arno'] = true;
17951 t['Aster'] = true;
17952 t['Aurora'] = true;
17953 t['Baskerville'] = true;
17954 t['Bell'] = true;
17955 t['Bembo'] = true;
17956 t['Bembo Schoolbook'] = true;
17957 t['Benguiat'] = true;
17958 t['Berkeley Old Style'] = true;
17959 t['Bernhard Modern'] = true;
17960 t['Berthold City'] = true;
17961 t['Bodoni'] = true;
17962 t['Bauer Bodoni'] = true;
17963 t['Book Antiqua'] = true;
17964 t['Bookman'] = true;
17965 t['Bordeaux Roman'] = true;
17966 t['Californian FB'] = true;
17967 t['Calisto'] = true;
17968 t['Calvert'] = true;
17969 t['Capitals'] = true;
17970 t['Cambria'] = true;
17971 t['Cartier'] = true;
17972 t['Caslon'] = true;
17973 t['Catull'] = true;
17974 t['Centaur'] = true;
17975 t['Century Old Style'] = true;
17976 t['Century Schoolbook'] = true;
17977 t['Chaparral'] = true;
17978 t['Charis SIL'] = true;
17979 t['Cheltenham'] = true;
17980 t['Cholla Slab'] = true;
17981 t['Clarendon'] = true;
17982 t['Clearface'] = true;
17983 t['Cochin'] = true;
17984 t['Colonna'] = true;
17985 t['Computer Modern'] = true;
17986 t['Concrete Roman'] = true;
17987 t['Constantia'] = true;
17988 t['Cooper Black'] = true;
17989 t['Corona'] = true;
17990 t['Ecotype'] = true;
17991 t['Egyptienne'] = true;
17992 t['Elephant'] = true;
17993 t['Excelsior'] = true;
17994 t['Fairfield'] = true;
17995 t['FF Scala'] = true;
17996 t['Folkard'] = true;
17997 t['Footlight'] = true;
17998 t['FreeSerif'] = true;
17999 t['Friz Quadrata'] = true;
18000 t['Garamond'] = true;
18001 t['Gentium'] = true;
18002 t['Georgia'] = true;
18003 t['Gloucester'] = true;
18004 t['Goudy Old Style'] = true;
18005 t['Goudy Schoolbook'] = true;
18006 t['Goudy Pro Font'] = true;
18007 t['Granjon'] = true;
18008 t['Guardian Egyptian'] = true;
18009 t['Heather'] = true;
18010 t['Hercules'] = true;
18011 t['High Tower Text'] = true;
18012 t['Hiroshige'] = true;
18013 t['Hoefler Text'] = true;
18014 t['Humana Serif'] = true;
18015 t['Imprint'] = true;
18016 t['Ionic No. 5'] = true;
18017 t['Janson'] = true;
18018 t['Joanna'] = true;
18019 t['Korinna'] = true;
18020 t['Lexicon'] = true;
18021 t['Liberation Serif'] = true;
18022 t['Linux Libertine'] = true;
18023 t['Literaturnaya'] = true;
18024 t['Lucida'] = true;
18025 t['Lucida Bright'] = true;
18026 t['Melior'] = true;
18027 t['Memphis'] = true;
18028 t['Miller'] = true;
18029 t['Minion'] = true;
18030 t['Modern'] = true;
18031 t['Mona Lisa'] = true;
18032 t['Mrs Eaves'] = true;
18033 t['MS Serif'] = true;
18034 t['Museo Slab'] = true;
18035 t['New York'] = true;
18036 t['Nimbus Roman'] = true;
18037 t['NPS Rawlinson Roadway'] = true;
18038 t['Palatino'] = true;
18039 t['Perpetua'] = true;
18040 t['Plantin'] = true;
18041 t['Plantin Schoolbook'] = true;
18042 t['Playbill'] = true;
18043 t['Poor Richard'] = true;
18044 t['Rawlinson Roadway'] = true;
18045 t['Renault'] = true;
18046 t['Requiem'] = true;
18047 t['Rockwell'] = true;
18048 t['Roman'] = true;
18049 t['Rotis Serif'] = true;
18050 t['Sabon'] = true;
18051 t['Scala'] = true;
18052 t['Seagull'] = true;
18053 t['Sistina'] = true;
18054 t['Souvenir'] = true;
18055 t['STIX'] = true;
18056 t['Stone Informal'] = true;
18057 t['Stone Serif'] = true;
18058 t['Sylfaen'] = true;
18059 t['Times'] = true;
18060 t['Trajan'] = true;
18061 t['Trinité'] = true;
18062 t['Trump Mediaeval'] = true;
18063 t['Utopia'] = true;
18064 t['Vale Type'] = true;
18065 t['Bitstream Vera'] = true;
18066 t['Vera Serif'] = true;
18067 t['Versailles'] = true;
18068 t['Wanted'] = true;
18069 t['Weiss'] = true;
18070 t['Wide Latin'] = true;
18071 t['Windsor'] = true;
18072 t['XITS'] = true;
18073 });
18074
18075 var getSymbolsFonts = getLookupTableFactory(function (t) {
18076 t['Dingbats'] = true;
18077 t['Symbol'] = true;
18078 t['ZapfDingbats'] = true;
18079 });
18080
18081 // Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID
18082 // fonts, but does not embed the CID to GID mapping. The mapping is incomplete
18083 // for all glyphs, but common for some set of the standard fonts.
18084 var getGlyphMapForStandardFonts = getLookupTableFactory(function (t) {
18085 t[2] = 10; t[3] = 32; t[4] = 33; t[5] = 34; t[6] = 35; t[7] = 36; t[8] = 37;
18086 t[9] = 38; t[10] = 39; t[11] = 40; t[12] = 41; t[13] = 42; t[14] = 43;
18087 t[15] = 44; t[16] = 45; t[17] = 46; t[18] = 47; t[19] = 48; t[20] = 49;
18088 t[21] = 50; t[22] = 51; t[23] = 52; t[24] = 53; t[25] = 54; t[26] = 55;
18089 t[27] = 56; t[28] = 57; t[29] = 58; t[30] = 894; t[31] = 60; t[32] = 61;
18090 t[33] = 62; t[34] = 63; t[35] = 64; t[36] = 65; t[37] = 66; t[38] = 67;
18091 t[39] = 68; t[40] = 69; t[41] = 70; t[42] = 71; t[43] = 72; t[44] = 73;
18092 t[45] = 74; t[46] = 75; t[47] = 76; t[48] = 77; t[49] = 78; t[50] = 79;
18093 t[51] = 80; t[52] = 81; t[53] = 82; t[54] = 83; t[55] = 84; t[56] = 85;
18094 t[57] = 86; t[58] = 87; t[59] = 88; t[60] = 89; t[61] = 90; t[62] = 91;
18095 t[63] = 92; t[64] = 93; t[65] = 94; t[66] = 95; t[67] = 96; t[68] = 97;
18096 t[69] = 98; t[70] = 99; t[71] = 100; t[72] = 101; t[73] = 102; t[74] = 103;
18097 t[75] = 104; t[76] = 105; t[77] = 106; t[78] = 107; t[79] = 108;
18098 t[80] = 109; t[81] = 110; t[82] = 111; t[83] = 112; t[84] = 113;
18099 t[85] = 114; t[86] = 115; t[87] = 116; t[88] = 117; t[89] = 118;
18100 t[90] = 119; t[91] = 120; t[92] = 121; t[93] = 122; t[94] = 123;
18101 t[95] = 124; t[96] = 125; t[97] = 126; t[98] = 196; t[99] = 197;
18102 t[100] = 199; t[101] = 201; t[102] = 209; t[103] = 214; t[104] = 220;
18103 t[105] = 225; t[106] = 224; t[107] = 226; t[108] = 228; t[109] = 227;
18104 t[110] = 229; t[111] = 231; t[112] = 233; t[113] = 232; t[114] = 234;
18105 t[115] = 235; t[116] = 237; t[117] = 236; t[118] = 238; t[119] = 239;
18106 t[120] = 241; t[121] = 243; t[122] = 242; t[123] = 244; t[124] = 246;
18107 t[125] = 245; t[126] = 250; t[127] = 249; t[128] = 251; t[129] = 252;
18108 t[130] = 8224; t[131] = 176; t[132] = 162; t[133] = 163; t[134] = 167;
18109 t[135] = 8226; t[136] = 182; t[137] = 223; t[138] = 174; t[139] = 169;
18110 t[140] = 8482; t[141] = 180; t[142] = 168; t[143] = 8800; t[144] = 198;
18111 t[145] = 216; t[146] = 8734; t[147] = 177; t[148] = 8804; t[149] = 8805;
18112 t[150] = 165; t[151] = 181; t[152] = 8706; t[153] = 8721; t[154] = 8719;
18113 t[156] = 8747; t[157] = 170; t[158] = 186; t[159] = 8486; t[160] = 230;
18114 t[161] = 248; t[162] = 191; t[163] = 161; t[164] = 172; t[165] = 8730;
18115 t[166] = 402; t[167] = 8776; t[168] = 8710; t[169] = 171; t[170] = 187;
18116 t[171] = 8230; t[210] = 218; t[223] = 711; t[224] = 321; t[225] = 322;
18117 t[227] = 353; t[229] = 382; t[234] = 253; t[252] = 263; t[253] = 268;
18118 t[254] = 269; t[258] = 258; t[260] = 260; t[261] = 261; t[265] = 280;
18119 t[266] = 281; t[268] = 283; t[269] = 313; t[275] = 323; t[276] = 324;
18120 t[278] = 328; t[284] = 345; t[285] = 346; t[286] = 347; t[292] = 367;
18121 t[295] = 377; t[296] = 378; t[298] = 380; t[305] = 963; t[306] = 964;
18122 t[307] = 966; t[308] = 8215; t[309] = 8252; t[310] = 8319; t[311] = 8359;
18123 t[312] = 8592; t[313] = 8593; t[337] = 9552; t[493] = 1039;
18124 t[494] = 1040; t[705] = 1524; t[706] = 8362; t[710] = 64288; t[711] = 64298;
18125 t[759] = 1617; t[761] = 1776; t[763] = 1778; t[775] = 1652; t[777] = 1764;
18126 t[778] = 1780; t[779] = 1781; t[780] = 1782; t[782] = 771; t[783] = 64726;
18127 t[786] = 8363; t[788] = 8532; t[790] = 768; t[791] = 769; t[792] = 768;
18128 t[795] = 803; t[797] = 64336; t[798] = 64337; t[799] = 64342;
18129 t[800] = 64343; t[801] = 64344; t[802] = 64345; t[803] = 64362;
18130 t[804] = 64363; t[805] = 64364; t[2424] = 7821; t[2425] = 7822;
18131 t[2426] = 7823; t[2427] = 7824; t[2428] = 7825; t[2429] = 7826;
18132 t[2430] = 7827; t[2433] = 7682; t[2678] = 8045; t[2679] = 8046;
18133 t[2830] = 1552; t[2838] = 686; t[2840] = 751; t[2842] = 753; t[2843] = 754;
18134 t[2844] = 755; t[2846] = 757; t[2856] = 767; t[2857] = 848; t[2858] = 849;
18135 t[2862] = 853; t[2863] = 854; t[2864] = 855; t[2865] = 861; t[2866] = 862;
18136 t[2906] = 7460; t[2908] = 7462; t[2909] = 7463; t[2910] = 7464;
18137 t[2912] = 7466; t[2913] = 7467; t[2914] = 7468; t[2916] = 7470;
18138 t[2917] = 7471; t[2918] = 7472; t[2920] = 7474; t[2921] = 7475;
18139 t[2922] = 7476; t[2924] = 7478; t[2925] = 7479; t[2926] = 7480;
18140 t[2928] = 7482; t[2929] = 7483; t[2930] = 7484; t[2932] = 7486;
18141 t[2933] = 7487; t[2934] = 7488; t[2936] = 7490; t[2937] = 7491;
18142 t[2938] = 7492; t[2940] = 7494; t[2941] = 7495; t[2942] = 7496;
18143 t[2944] = 7498; t[2946] = 7500; t[2948] = 7502; t[2950] = 7504;
18144 t[2951] = 7505; t[2952] = 7506; t[2954] = 7508; t[2955] = 7509;
18145 t[2956] = 7510; t[2958] = 7512; t[2959] = 7513; t[2960] = 7514;
18146 t[2962] = 7516; t[2963] = 7517; t[2964] = 7518; t[2966] = 7520;
18147 t[2967] = 7521; t[2968] = 7522; t[2970] = 7524; t[2971] = 7525;
18148 t[2972] = 7526; t[2974] = 7528; t[2975] = 7529; t[2976] = 7530;
18149 t[2978] = 1537; t[2979] = 1538; t[2980] = 1539; t[2982] = 1549;
18150 t[2983] = 1551; t[2984] = 1552; t[2986] = 1554; t[2987] = 1555;
18151 t[2988] = 1556; t[2990] = 1623; t[2991] = 1624; t[2995] = 1775;
18152 t[2999] = 1791; t[3002] = 64290; t[3003] = 64291; t[3004] = 64292;
18153 t[3006] = 64294; t[3007] = 64295; t[3008] = 64296; t[3011] = 1900;
18154 t[3014] = 8223; t[3015] = 8244; t[3017] = 7532; t[3018] = 7533;
18155 t[3019] = 7534; t[3075] = 7590; t[3076] = 7591; t[3079] = 7594;
18156 t[3080] = 7595; t[3083] = 7598; t[3084] = 7599; t[3087] = 7602;
18157 t[3088] = 7603; t[3091] = 7606; t[3092] = 7607; t[3095] = 7610;
18158 t[3096] = 7611; t[3099] = 7614; t[3100] = 7615; t[3103] = 7618;
18159 t[3104] = 7619; t[3107] = 8337; t[3108] = 8338; t[3116] = 1884;
18160 t[3119] = 1885; t[3120] = 1885; t[3123] = 1886; t[3124] = 1886;
18161 t[3127] = 1887; t[3128] = 1887; t[3131] = 1888; t[3132] = 1888;
18162 t[3135] = 1889; t[3136] = 1889; t[3139] = 1890; t[3140] = 1890;
18163 t[3143] = 1891; t[3144] = 1891; t[3147] = 1892; t[3148] = 1892;
18164 t[3153] = 580; t[3154] = 581; t[3157] = 584; t[3158] = 585; t[3161] = 588;
18165 t[3162] = 589; t[3165] = 891; t[3166] = 892; t[3169] = 1274; t[3170] = 1275;
18166 t[3173] = 1278; t[3174] = 1279; t[3181] = 7622; t[3182] = 7623;
18167 t[3282] = 11799; t[3316] = 578; t[3379] = 42785; t[3393] = 1159;
18168 t[3416] = 8377;
18169 });
18170
18171 // The glyph map for ArialBlack differs slightly from the glyph map used for
18172 // other well-known standard fonts. Hence we use this (incomplete) CID to GID
18173 // mapping to adjust the glyph map for non-embedded ArialBlack fonts.
18174 var getSupplementalGlyphMapForArialBlack =
18175 getLookupTableFactory(function (t) {
18176 t[227] = 322; t[264] = 261; t[291] = 346;
18177 });
18178
18179 exports.getStdFontMap = getStdFontMap;
18180 exports.getNonStdFontMap = getNonStdFontMap;
18181 exports.getSerifFonts = getSerifFonts;
18182 exports.getSymbolsFonts = getSymbolsFonts;
18183 exports.getGlyphMapForStandardFonts = getGlyphMapForStandardFonts;
18184 exports.getSupplementalGlyphMapForArialBlack =
18185 getSupplementalGlyphMapForArialBlack;
18186}));
18187
18188
18189(function (root, factory) {
18190 {
18191 factory((root.pdfjsCoreUnicode = {}), root.pdfjsSharedUtil);
18192 }
18193}(this, function (exports, sharedUtil) {
18194 var getLookupTableFactory = sharedUtil.getLookupTableFactory;
18195
18196 // Some characters, e.g. copyrightserif, are mapped to the private use area
18197 // and might not be displayed using standard fonts. Mapping/hacking well-known
18198 // chars to the similar equivalents in the normal characters range.
18199 var getSpecialPUASymbols = getLookupTableFactory(function (t) {
18200 t[63721] = 0x00A9; // copyrightsans (0xF8E9) => copyright
18201 t[63193] = 0x00A9; // copyrightserif (0xF6D9) => copyright
18202 t[63720] = 0x00AE; // registersans (0xF8E8) => registered
18203 t[63194] = 0x00AE; // registerserif (0xF6DA) => registered
18204 t[63722] = 0x2122; // trademarksans (0xF8EA) => trademark
18205 t[63195] = 0x2122; // trademarkserif (0xF6DB) => trademark
18206 t[63729] = 0x23A7; // bracelefttp (0xF8F1)
18207 t[63730] = 0x23A8; // braceleftmid (0xF8F2)
18208 t[63731] = 0x23A9; // braceleftbt (0xF8F3)
18209 t[63740] = 0x23AB; // bracerighttp (0xF8FC)
18210 t[63741] = 0x23AC; // bracerightmid (0xF8FD)
18211 t[63742] = 0x23AD; // bracerightbt (0xF8FE)
18212 t[63726] = 0x23A1; // bracketlefttp (0xF8EE)
18213 t[63727] = 0x23A2; // bracketleftex (0xF8EF)
18214 t[63728] = 0x23A3; // bracketleftbt (0xF8F0)
18215 t[63737] = 0x23A4; // bracketrighttp (0xF8F9)
18216 t[63738] = 0x23A5; // bracketrightex (0xF8FA)
18217 t[63739] = 0x23A6; // bracketrightbt (0xF8FB)
18218 t[63723] = 0x239B; // parenlefttp (0xF8EB)
18219 t[63724] = 0x239C; // parenleftex (0xF8EC)
18220 t[63725] = 0x239D; // parenleftbt (0xF8ED)
18221 t[63734] = 0x239E; // parenrighttp (0xF8F6)
18222 t[63735] = 0x239F; // parenrightex (0xF8F7)
18223 t[63736] = 0x23A0; // parenrightbt (0xF8F8)
18224 });
18225
18226 function mapSpecialUnicodeValues(code) {
18227 if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials unicode block.
18228 return 0;
18229 } else if (code >= 0xF600 && code <= 0xF8FF) {
18230 return (getSpecialPUASymbols()[code] || code);
18231 }
18232 return code;
18233 }
18234
18235 function getUnicodeForGlyph(name, glyphsUnicodeMap) {
18236 var unicode = glyphsUnicodeMap[name];
18237 if (unicode !== undefined) {
18238 return unicode;
18239 }
18240 if (!name) {
18241 return -1;
18242 }
18243 // Try to recover valid Unicode values from 'uniXXXX'/'uXXXX{XX}' glyphs.
18244 if (name[0] === 'u') {
18245 var nameLen = name.length, hexStr;
18246
18247 if (nameLen === 7 && name[1] === 'n' && name[2] === 'i') { // 'uniXXXX'
18248 hexStr = name.substr(3);
18249 } else if (nameLen >= 5 && nameLen <= 7) { // 'uXXXX{XX}'
18250 hexStr = name.substr(1);
18251 } else {
18252 return -1;
18253 }
18254 // Check for upper-case hexadecimal characters, to avoid false positives.
18255 if (hexStr === hexStr.toUpperCase()) {
18256 unicode = parseInt(hexStr, 16);
18257 if (unicode >= 0) {
18258 return unicode;
18259 }
18260 }
18261 }
18262 return -1;
18263 }
18264
18265 var UnicodeRanges = [
18266 { 'begin': 0x0000, 'end': 0x007F }, // Basic Latin
18267 { 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement
18268 { 'begin': 0x0100, 'end': 0x017F }, // Latin Extended-A
18269 { 'begin': 0x0180, 'end': 0x024F }, // Latin Extended-B
18270 { 'begin': 0x0250, 'end': 0x02AF }, // IPA Extensions
18271 { 'begin': 0x02B0, 'end': 0x02FF }, // Spacing Modifier Letters
18272 { 'begin': 0x0300, 'end': 0x036F }, // Combining Diacritical Marks
18273 { 'begin': 0x0370, 'end': 0x03FF }, // Greek and Coptic
18274 { 'begin': 0x2C80, 'end': 0x2CFF }, // Coptic
18275 { 'begin': 0x0400, 'end': 0x04FF }, // Cyrillic
18276 { 'begin': 0x0530, 'end': 0x058F }, // Armenian
18277 { 'begin': 0x0590, 'end': 0x05FF }, // Hebrew
18278 { 'begin': 0xA500, 'end': 0xA63F }, // Vai
18279 { 'begin': 0x0600, 'end': 0x06FF }, // Arabic
18280 { 'begin': 0x07C0, 'end': 0x07FF }, // NKo
18281 { 'begin': 0x0900, 'end': 0x097F }, // Devanagari
18282 { 'begin': 0x0980, 'end': 0x09FF }, // Bengali
18283 { 'begin': 0x0A00, 'end': 0x0A7F }, // Gurmukhi
18284 { 'begin': 0x0A80, 'end': 0x0AFF }, // Gujarati
18285 { 'begin': 0x0B00, 'end': 0x0B7F }, // Oriya
18286 { 'begin': 0x0B80, 'end': 0x0BFF }, // Tamil
18287 { 'begin': 0x0C00, 'end': 0x0C7F }, // Telugu
18288 { 'begin': 0x0C80, 'end': 0x0CFF }, // Kannada
18289 { 'begin': 0x0D00, 'end': 0x0D7F }, // Malayalam
18290 { 'begin': 0x0E00, 'end': 0x0E7F }, // Thai
18291 { 'begin': 0x0E80, 'end': 0x0EFF }, // Lao
18292 { 'begin': 0x10A0, 'end': 0x10FF }, // Georgian
18293 { 'begin': 0x1B00, 'end': 0x1B7F }, // Balinese
18294 { 'begin': 0x1100, 'end': 0x11FF }, // Hangul Jamo
18295 { 'begin': 0x1E00, 'end': 0x1EFF }, // Latin Extended Additional
18296 { 'begin': 0x1F00, 'end': 0x1FFF }, // Greek Extended
18297 { 'begin': 0x2000, 'end': 0x206F }, // General Punctuation
18298 { 'begin': 0x2070, 'end': 0x209F }, // Superscripts And Subscripts
18299 { 'begin': 0x20A0, 'end': 0x20CF }, // Currency Symbol
18300 { 'begin': 0x20D0, 'end': 0x20FF }, // Combining Diacritical Marks
18301 { 'begin': 0x2100, 'end': 0x214F }, // Letterlike Symbols
18302 { 'begin': 0x2150, 'end': 0x218F }, // Number Forms
18303 { 'begin': 0x2190, 'end': 0x21FF }, // Arrows
18304 { 'begin': 0x2200, 'end': 0x22FF }, // Mathematical Operators
18305 { 'begin': 0x2300, 'end': 0x23FF }, // Miscellaneous Technical
18306 { 'begin': 0x2400, 'end': 0x243F }, // Control Pictures
18307 { 'begin': 0x2440, 'end': 0x245F }, // Optical Character Recognition
18308 { 'begin': 0x2460, 'end': 0x24FF }, // Enclosed Alphanumerics
18309 { 'begin': 0x2500, 'end': 0x257F }, // Box Drawing
18310 { 'begin': 0x2580, 'end': 0x259F }, // Block Elements
18311 { 'begin': 0x25A0, 'end': 0x25FF }, // Geometric Shapes
18312 { 'begin': 0x2600, 'end': 0x26FF }, // Miscellaneous Symbols
18313 { 'begin': 0x2700, 'end': 0x27BF }, // Dingbats
18314 { 'begin': 0x3000, 'end': 0x303F }, // CJK Symbols And Punctuation
18315 { 'begin': 0x3040, 'end': 0x309F }, // Hiragana
18316 { 'begin': 0x30A0, 'end': 0x30FF }, // Katakana
18317 { 'begin': 0x3100, 'end': 0x312F }, // Bopomofo
18318 { 'begin': 0x3130, 'end': 0x318F }, // Hangul Compatibility Jamo
18319 { 'begin': 0xA840, 'end': 0xA87F }, // Phags-pa
18320 { 'begin': 0x3200, 'end': 0x32FF }, // Enclosed CJK Letters And Months
18321 { 'begin': 0x3300, 'end': 0x33FF }, // CJK Compatibility
18322 { 'begin': 0xAC00, 'end': 0xD7AF }, // Hangul Syllables
18323 { 'begin': 0xD800, 'end': 0xDFFF }, // Non-Plane 0 *
18324 { 'begin': 0x10900, 'end': 0x1091F }, // Phoenicia
18325 { 'begin': 0x4E00, 'end': 0x9FFF }, // CJK Unified Ideographs
18326 { 'begin': 0xE000, 'end': 0xF8FF }, // Private Use Area (plane 0)
18327 { 'begin': 0x31C0, 'end': 0x31EF }, // CJK Strokes
18328 { 'begin': 0xFB00, 'end': 0xFB4F }, // Alphabetic Presentation Forms
18329 { 'begin': 0xFB50, 'end': 0xFDFF }, // Arabic Presentation Forms-A
18330 { 'begin': 0xFE20, 'end': 0xFE2F }, // Combining Half Marks
18331 { 'begin': 0xFE10, 'end': 0xFE1F }, // Vertical Forms
18332 { 'begin': 0xFE50, 'end': 0xFE6F }, // Small Form Variants
18333 { 'begin': 0xFE70, 'end': 0xFEFF }, // Arabic Presentation Forms-B
18334 { 'begin': 0xFF00, 'end': 0xFFEF }, // Halfwidth And Fullwidth Forms
18335 { 'begin': 0xFFF0, 'end': 0xFFFF }, // Specials
18336 { 'begin': 0x0F00, 'end': 0x0FFF }, // Tibetan
18337 { 'begin': 0x0700, 'end': 0x074F }, // Syriac
18338 { 'begin': 0x0780, 'end': 0x07BF }, // Thaana
18339 { 'begin': 0x0D80, 'end': 0x0DFF }, // Sinhala
18340 { 'begin': 0x1000, 'end': 0x109F }, // Myanmar
18341 { 'begin': 0x1200, 'end': 0x137F }, // Ethiopic
18342 { 'begin': 0x13A0, 'end': 0x13FF }, // Cherokee
18343 { 'begin': 0x1400, 'end': 0x167F }, // Unified Canadian Aboriginal Syllabics
18344 { 'begin': 0x1680, 'end': 0x169F }, // Ogham
18345 { 'begin': 0x16A0, 'end': 0x16FF }, // Runic
18346 { 'begin': 0x1780, 'end': 0x17FF }, // Khmer
18347 { 'begin': 0x1800, 'end': 0x18AF }, // Mongolian
18348 { 'begin': 0x2800, 'end': 0x28FF }, // Braille Patterns
18349 { 'begin': 0xA000, 'end': 0xA48F }, // Yi Syllables
18350 { 'begin': 0x1700, 'end': 0x171F }, // Tagalog
18351 { 'begin': 0x10300, 'end': 0x1032F }, // Old Italic
18352 { 'begin': 0x10330, 'end': 0x1034F }, // Gothic
18353 { 'begin': 0x10400, 'end': 0x1044F }, // Deseret
18354 { 'begin': 0x1D000, 'end': 0x1D0FF }, // Byzantine Musical Symbols
18355 { 'begin': 0x1D400, 'end': 0x1D7FF }, // Mathematical Alphanumeric Symbols
18356 { 'begin': 0xFF000, 'end': 0xFFFFD }, // Private Use (plane 15)
18357 { 'begin': 0xFE00, 'end': 0xFE0F }, // Variation Selectors
18358 { 'begin': 0xE0000, 'end': 0xE007F }, // Tags
18359 { 'begin': 0x1900, 'end': 0x194F }, // Limbu
18360 { 'begin': 0x1950, 'end': 0x197F }, // Tai Le
18361 { 'begin': 0x1980, 'end': 0x19DF }, // New Tai Lue
18362 { 'begin': 0x1A00, 'end': 0x1A1F }, // Buginese
18363 { 'begin': 0x2C00, 'end': 0x2C5F }, // Glagolitic
18364 { 'begin': 0x2D30, 'end': 0x2D7F }, // Tifinagh
18365 { 'begin': 0x4DC0, 'end': 0x4DFF }, // Yijing Hexagram Symbols
18366 { 'begin': 0xA800, 'end': 0xA82F }, // Syloti Nagri
18367 { 'begin': 0x10000, 'end': 0x1007F }, // Linear B Syllabary
18368 { 'begin': 0x10140, 'end': 0x1018F }, // Ancient Greek Numbers
18369 { 'begin': 0x10380, 'end': 0x1039F }, // Ugaritic
18370 { 'begin': 0x103A0, 'end': 0x103DF }, // Old Persian
18371 { 'begin': 0x10450, 'end': 0x1047F }, // Shavian
18372 { 'begin': 0x10480, 'end': 0x104AF }, // Osmanya
18373 { 'begin': 0x10800, 'end': 0x1083F }, // Cypriot Syllabary
18374 { 'begin': 0x10A00, 'end': 0x10A5F }, // Kharoshthi
18375 { 'begin': 0x1D300, 'end': 0x1D35F }, // Tai Xuan Jing Symbols
18376 { 'begin': 0x12000, 'end': 0x123FF }, // Cuneiform
18377 { 'begin': 0x1D360, 'end': 0x1D37F }, // Counting Rod Numerals
18378 { 'begin': 0x1B80, 'end': 0x1BBF }, // Sundanese
18379 { 'begin': 0x1C00, 'end': 0x1C4F }, // Lepcha
18380 { 'begin': 0x1C50, 'end': 0x1C7F }, // Ol Chiki
18381 { 'begin': 0xA880, 'end': 0xA8DF }, // Saurashtra
18382 { 'begin': 0xA900, 'end': 0xA92F }, // Kayah Li
18383 { 'begin': 0xA930, 'end': 0xA95F }, // Rejang
18384 { 'begin': 0xAA00, 'end': 0xAA5F }, // Cham
18385 { 'begin': 0x10190, 'end': 0x101CF }, // Ancient Symbols
18386 { 'begin': 0x101D0, 'end': 0x101FF }, // Phaistos Disc
18387 { 'begin': 0x102A0, 'end': 0x102DF }, // Carian
18388 { 'begin': 0x1F030, 'end': 0x1F09F } // Domino Tiles
18389 ];
18390
18391 function getUnicodeRangeFor(value) {
18392 for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) {
18393 var range = UnicodeRanges[i];
18394 if (value >= range.begin && value < range.end) {
18395 return i;
18396 }
18397 }
18398 return -1;
18399 }
18400
18401 function isRTLRangeFor(value) {
18402 var range = UnicodeRanges[13];
18403 if (value >= range.begin && value < range.end) {
18404 return true;
18405 }
18406 range = UnicodeRanges[11];
18407 if (value >= range.begin && value < range.end) {
18408 return true;
18409 }
18410 return false;
18411 }
18412
18413 // The normalization table is obtained by filtering the Unicode characters
18414 // database with <compat> entries.
18415 var getNormalizedUnicodes = getLookupTableFactory(function (t) {
18416 t['\u00A8'] = '\u0020\u0308';
18417 t['\u00AF'] = '\u0020\u0304';
18418 t['\u00B4'] = '\u0020\u0301';
18419 t['\u00B5'] = '\u03BC';
18420 t['\u00B8'] = '\u0020\u0327';
18421 t['\u0132'] = '\u0049\u004A';
18422 t['\u0133'] = '\u0069\u006A';
18423 t['\u013F'] = '\u004C\u00B7';
18424 t['\u0140'] = '\u006C\u00B7';
18425 t['\u0149'] = '\u02BC\u006E';
18426 t['\u017F'] = '\u0073';
18427 t['\u01C4'] = '\u0044\u017D';
18428 t['\u01C5'] = '\u0044\u017E';
18429 t['\u01C6'] = '\u0064\u017E';
18430 t['\u01C7'] = '\u004C\u004A';
18431 t['\u01C8'] = '\u004C\u006A';
18432 t['\u01C9'] = '\u006C\u006A';
18433 t['\u01CA'] = '\u004E\u004A';
18434 t['\u01CB'] = '\u004E\u006A';
18435 t['\u01CC'] = '\u006E\u006A';
18436 t['\u01F1'] = '\u0044\u005A';
18437 t['\u01F2'] = '\u0044\u007A';
18438 t['\u01F3'] = '\u0064\u007A';
18439 t['\u02D8'] = '\u0020\u0306';
18440 t['\u02D9'] = '\u0020\u0307';
18441 t['\u02DA'] = '\u0020\u030A';
18442 t['\u02DB'] = '\u0020\u0328';
18443 t['\u02DC'] = '\u0020\u0303';
18444 t['\u02DD'] = '\u0020\u030B';
18445 t['\u037A'] = '\u0020\u0345';
18446 t['\u0384'] = '\u0020\u0301';
18447 t['\u03D0'] = '\u03B2';
18448 t['\u03D1'] = '\u03B8';
18449 t['\u03D2'] = '\u03A5';
18450 t['\u03D5'] = '\u03C6';
18451 t['\u03D6'] = '\u03C0';
18452 t['\u03F0'] = '\u03BA';
18453 t['\u03F1'] = '\u03C1';
18454 t['\u03F2'] = '\u03C2';
18455 t['\u03F4'] = '\u0398';
18456 t['\u03F5'] = '\u03B5';
18457 t['\u03F9'] = '\u03A3';
18458 t['\u0587'] = '\u0565\u0582';
18459 t['\u0675'] = '\u0627\u0674';
18460 t['\u0676'] = '\u0648\u0674';
18461 t['\u0677'] = '\u06C7\u0674';
18462 t['\u0678'] = '\u064A\u0674';
18463 t['\u0E33'] = '\u0E4D\u0E32';
18464 t['\u0EB3'] = '\u0ECD\u0EB2';
18465 t['\u0EDC'] = '\u0EAB\u0E99';
18466 t['\u0EDD'] = '\u0EAB\u0EA1';
18467 t['\u0F77'] = '\u0FB2\u0F81';
18468 t['\u0F79'] = '\u0FB3\u0F81';
18469 t['\u1E9A'] = '\u0061\u02BE';
18470 t['\u1FBD'] = '\u0020\u0313';
18471 t['\u1FBF'] = '\u0020\u0313';
18472 t['\u1FC0'] = '\u0020\u0342';
18473 t['\u1FFE'] = '\u0020\u0314';
18474 t['\u2002'] = '\u0020';
18475 t['\u2003'] = '\u0020';
18476 t['\u2004'] = '\u0020';
18477 t['\u2005'] = '\u0020';
18478 t['\u2006'] = '\u0020';
18479 t['\u2008'] = '\u0020';
18480 t['\u2009'] = '\u0020';
18481 t['\u200A'] = '\u0020';
18482 t['\u2017'] = '\u0020\u0333';
18483 t['\u2024'] = '\u002E';
18484 t['\u2025'] = '\u002E\u002E';
18485 t['\u2026'] = '\u002E\u002E\u002E';
18486 t['\u2033'] = '\u2032\u2032';
18487 t['\u2034'] = '\u2032\u2032\u2032';
18488 t['\u2036'] = '\u2035\u2035';
18489 t['\u2037'] = '\u2035\u2035\u2035';
18490 t['\u203C'] = '\u0021\u0021';
18491 t['\u203E'] = '\u0020\u0305';
18492 t['\u2047'] = '\u003F\u003F';
18493 t['\u2048'] = '\u003F\u0021';
18494 t['\u2049'] = '\u0021\u003F';
18495 t['\u2057'] = '\u2032\u2032\u2032\u2032';
18496 t['\u205F'] = '\u0020';
18497 t['\u20A8'] = '\u0052\u0073';
18498 t['\u2100'] = '\u0061\u002F\u0063';
18499 t['\u2101'] = '\u0061\u002F\u0073';
18500 t['\u2103'] = '\u00B0\u0043';
18501 t['\u2105'] = '\u0063\u002F\u006F';
18502 t['\u2106'] = '\u0063\u002F\u0075';
18503 t['\u2107'] = '\u0190';
18504 t['\u2109'] = '\u00B0\u0046';
18505 t['\u2116'] = '\u004E\u006F';
18506 t['\u2121'] = '\u0054\u0045\u004C';
18507 t['\u2135'] = '\u05D0';
18508 t['\u2136'] = '\u05D1';
18509 t['\u2137'] = '\u05D2';
18510 t['\u2138'] = '\u05D3';
18511 t['\u213B'] = '\u0046\u0041\u0058';
18512 t['\u2160'] = '\u0049';
18513 t['\u2161'] = '\u0049\u0049';
18514 t['\u2162'] = '\u0049\u0049\u0049';
18515 t['\u2163'] = '\u0049\u0056';
18516 t['\u2164'] = '\u0056';
18517 t['\u2165'] = '\u0056\u0049';
18518 t['\u2166'] = '\u0056\u0049\u0049';
18519 t['\u2167'] = '\u0056\u0049\u0049\u0049';
18520 t['\u2168'] = '\u0049\u0058';
18521 t['\u2169'] = '\u0058';
18522 t['\u216A'] = '\u0058\u0049';
18523 t['\u216B'] = '\u0058\u0049\u0049';
18524 t['\u216C'] = '\u004C';
18525 t['\u216D'] = '\u0043';
18526 t['\u216E'] = '\u0044';
18527 t['\u216F'] = '\u004D';
18528 t['\u2170'] = '\u0069';
18529 t['\u2171'] = '\u0069\u0069';
18530 t['\u2172'] = '\u0069\u0069\u0069';
18531 t['\u2173'] = '\u0069\u0076';
18532 t['\u2174'] = '\u0076';
18533 t['\u2175'] = '\u0076\u0069';
18534 t['\u2176'] = '\u0076\u0069\u0069';
18535 t['\u2177'] = '\u0076\u0069\u0069\u0069';
18536 t['\u2178'] = '\u0069\u0078';
18537 t['\u2179'] = '\u0078';
18538 t['\u217A'] = '\u0078\u0069';
18539 t['\u217B'] = '\u0078\u0069\u0069';
18540 t['\u217C'] = '\u006C';
18541 t['\u217D'] = '\u0063';
18542 t['\u217E'] = '\u0064';
18543 t['\u217F'] = '\u006D';
18544 t['\u222C'] = '\u222B\u222B';
18545 t['\u222D'] = '\u222B\u222B\u222B';
18546 t['\u222F'] = '\u222E\u222E';
18547 t['\u2230'] = '\u222E\u222E\u222E';
18548 t['\u2474'] = '\u0028\u0031\u0029';
18549 t['\u2475'] = '\u0028\u0032\u0029';
18550 t['\u2476'] = '\u0028\u0033\u0029';
18551 t['\u2477'] = '\u0028\u0034\u0029';
18552 t['\u2478'] = '\u0028\u0035\u0029';
18553 t['\u2479'] = '\u0028\u0036\u0029';
18554 t['\u247A'] = '\u0028\u0037\u0029';
18555 t['\u247B'] = '\u0028\u0038\u0029';
18556 t['\u247C'] = '\u0028\u0039\u0029';
18557 t['\u247D'] = '\u0028\u0031\u0030\u0029';
18558 t['\u247E'] = '\u0028\u0031\u0031\u0029';
18559 t['\u247F'] = '\u0028\u0031\u0032\u0029';
18560 t['\u2480'] = '\u0028\u0031\u0033\u0029';
18561 t['\u2481'] = '\u0028\u0031\u0034\u0029';
18562 t['\u2482'] = '\u0028\u0031\u0035\u0029';
18563 t['\u2483'] = '\u0028\u0031\u0036\u0029';
18564 t['\u2484'] = '\u0028\u0031\u0037\u0029';
18565 t['\u2485'] = '\u0028\u0031\u0038\u0029';
18566 t['\u2486'] = '\u0028\u0031\u0039\u0029';
18567 t['\u2487'] = '\u0028\u0032\u0030\u0029';
18568 t['\u2488'] = '\u0031\u002E';
18569 t['\u2489'] = '\u0032\u002E';
18570 t['\u248A'] = '\u0033\u002E';
18571 t['\u248B'] = '\u0034\u002E';
18572 t['\u248C'] = '\u0035\u002E';
18573 t['\u248D'] = '\u0036\u002E';
18574 t['\u248E'] = '\u0037\u002E';
18575 t['\u248F'] = '\u0038\u002E';
18576 t['\u2490'] = '\u0039\u002E';
18577 t['\u2491'] = '\u0031\u0030\u002E';
18578 t['\u2492'] = '\u0031\u0031\u002E';
18579 t['\u2493'] = '\u0031\u0032\u002E';
18580 t['\u2494'] = '\u0031\u0033\u002E';
18581 t['\u2495'] = '\u0031\u0034\u002E';
18582 t['\u2496'] = '\u0031\u0035\u002E';
18583 t['\u2497'] = '\u0031\u0036\u002E';
18584 t['\u2498'] = '\u0031\u0037\u002E';
18585 t['\u2499'] = '\u0031\u0038\u002E';
18586 t['\u249A'] = '\u0031\u0039\u002E';
18587 t['\u249B'] = '\u0032\u0030\u002E';
18588 t['\u249C'] = '\u0028\u0061\u0029';
18589 t['\u249D'] = '\u0028\u0062\u0029';
18590 t['\u249E'] = '\u0028\u0063\u0029';
18591 t['\u249F'] = '\u0028\u0064\u0029';
18592 t['\u24A0'] = '\u0028\u0065\u0029';
18593 t['\u24A1'] = '\u0028\u0066\u0029';
18594 t['\u24A2'] = '\u0028\u0067\u0029';
18595 t['\u24A3'] = '\u0028\u0068\u0029';
18596 t['\u24A4'] = '\u0028\u0069\u0029';
18597 t['\u24A5'] = '\u0028\u006A\u0029';
18598 t['\u24A6'] = '\u0028\u006B\u0029';
18599 t['\u24A7'] = '\u0028\u006C\u0029';
18600 t['\u24A8'] = '\u0028\u006D\u0029';
18601 t['\u24A9'] = '\u0028\u006E\u0029';
18602 t['\u24AA'] = '\u0028\u006F\u0029';
18603 t['\u24AB'] = '\u0028\u0070\u0029';
18604 t['\u24AC'] = '\u0028\u0071\u0029';
18605 t['\u24AD'] = '\u0028\u0072\u0029';
18606 t['\u24AE'] = '\u0028\u0073\u0029';
18607 t['\u24AF'] = '\u0028\u0074\u0029';
18608 t['\u24B0'] = '\u0028\u0075\u0029';
18609 t['\u24B1'] = '\u0028\u0076\u0029';
18610 t['\u24B2'] = '\u0028\u0077\u0029';
18611 t['\u24B3'] = '\u0028\u0078\u0029';
18612 t['\u24B4'] = '\u0028\u0079\u0029';
18613 t['\u24B5'] = '\u0028\u007A\u0029';
18614 t['\u2A0C'] = '\u222B\u222B\u222B\u222B';
18615 t['\u2A74'] = '\u003A\u003A\u003D';
18616 t['\u2A75'] = '\u003D\u003D';
18617 t['\u2A76'] = '\u003D\u003D\u003D';
18618 t['\u2E9F'] = '\u6BCD';
18619 t['\u2EF3'] = '\u9F9F';
18620 t['\u2F00'] = '\u4E00';
18621 t['\u2F01'] = '\u4E28';
18622 t['\u2F02'] = '\u4E36';
18623 t['\u2F03'] = '\u4E3F';
18624 t['\u2F04'] = '\u4E59';
18625 t['\u2F05'] = '\u4E85';
18626 t['\u2F06'] = '\u4E8C';
18627 t['\u2F07'] = '\u4EA0';
18628 t['\u2F08'] = '\u4EBA';
18629 t['\u2F09'] = '\u513F';
18630 t['\u2F0A'] = '\u5165';
18631 t['\u2F0B'] = '\u516B';
18632 t['\u2F0C'] = '\u5182';
18633 t['\u2F0D'] = '\u5196';
18634 t['\u2F0E'] = '\u51AB';
18635 t['\u2F0F'] = '\u51E0';
18636 t['\u2F10'] = '\u51F5';
18637 t['\u2F11'] = '\u5200';
18638 t['\u2F12'] = '\u529B';
18639 t['\u2F13'] = '\u52F9';
18640 t['\u2F14'] = '\u5315';
18641 t['\u2F15'] = '\u531A';
18642 t['\u2F16'] = '\u5338';
18643 t['\u2F17'] = '\u5341';
18644 t['\u2F18'] = '\u535C';
18645 t['\u2F19'] = '\u5369';
18646 t['\u2F1A'] = '\u5382';
18647 t['\u2F1B'] = '\u53B6';
18648 t['\u2F1C'] = '\u53C8';
18649 t['\u2F1D'] = '\u53E3';
18650 t['\u2F1E'] = '\u56D7';
18651 t['\u2F1F'] = '\u571F';
18652 t['\u2F20'] = '\u58EB';
18653 t['\u2F21'] = '\u5902';
18654 t['\u2F22'] = '\u590A';
18655 t['\u2F23'] = '\u5915';
18656 t['\u2F24'] = '\u5927';
18657 t['\u2F25'] = '\u5973';
18658 t['\u2F26'] = '\u5B50';
18659 t['\u2F27'] = '\u5B80';
18660 t['\u2F28'] = '\u5BF8';
18661 t['\u2F29'] = '\u5C0F';
18662 t['\u2F2A'] = '\u5C22';
18663 t['\u2F2B'] = '\u5C38';
18664 t['\u2F2C'] = '\u5C6E';
18665 t['\u2F2D'] = '\u5C71';
18666 t['\u2F2E'] = '\u5DDB';
18667 t['\u2F2F'] = '\u5DE5';
18668 t['\u2F30'] = '\u5DF1';
18669 t['\u2F31'] = '\u5DFE';
18670 t['\u2F32'] = '\u5E72';
18671 t['\u2F33'] = '\u5E7A';
18672 t['\u2F34'] = '\u5E7F';
18673 t['\u2F35'] = '\u5EF4';
18674 t['\u2F36'] = '\u5EFE';
18675 t['\u2F37'] = '\u5F0B';
18676 t['\u2F38'] = '\u5F13';
18677 t['\u2F39'] = '\u5F50';
18678 t['\u2F3A'] = '\u5F61';
18679 t['\u2F3B'] = '\u5F73';
18680 t['\u2F3C'] = '\u5FC3';
18681 t['\u2F3D'] = '\u6208';
18682 t['\u2F3E'] = '\u6236';
18683 t['\u2F3F'] = '\u624B';
18684 t['\u2F40'] = '\u652F';
18685 t['\u2F41'] = '\u6534';
18686 t['\u2F42'] = '\u6587';
18687 t['\u2F43'] = '\u6597';
18688 t['\u2F44'] = '\u65A4';
18689 t['\u2F45'] = '\u65B9';
18690 t['\u2F46'] = '\u65E0';
18691 t['\u2F47'] = '\u65E5';
18692 t['\u2F48'] = '\u66F0';
18693 t['\u2F49'] = '\u6708';
18694 t['\u2F4A'] = '\u6728';
18695 t['\u2F4B'] = '\u6B20';
18696 t['\u2F4C'] = '\u6B62';
18697 t['\u2F4D'] = '\u6B79';
18698 t['\u2F4E'] = '\u6BB3';
18699 t['\u2F4F'] = '\u6BCB';
18700 t['\u2F50'] = '\u6BD4';
18701 t['\u2F51'] = '\u6BDB';
18702 t['\u2F52'] = '\u6C0F';
18703 t['\u2F53'] = '\u6C14';
18704 t['\u2F54'] = '\u6C34';
18705 t['\u2F55'] = '\u706B';
18706 t['\u2F56'] = '\u722A';
18707 t['\u2F57'] = '\u7236';
18708 t['\u2F58'] = '\u723B';
18709 t['\u2F59'] = '\u723F';
18710 t['\u2F5A'] = '\u7247';
18711 t['\u2F5B'] = '\u7259';
18712 t['\u2F5C'] = '\u725B';
18713 t['\u2F5D'] = '\u72AC';
18714 t['\u2F5E'] = '\u7384';
18715 t['\u2F5F'] = '\u7389';
18716 t['\u2F60'] = '\u74DC';
18717 t['\u2F61'] = '\u74E6';
18718 t['\u2F62'] = '\u7518';
18719 t['\u2F63'] = '\u751F';
18720 t['\u2F64'] = '\u7528';
18721 t['\u2F65'] = '\u7530';
18722 t['\u2F66'] = '\u758B';
18723 t['\u2F67'] = '\u7592';
18724 t['\u2F68'] = '\u7676';
18725 t['\u2F69'] = '\u767D';
18726 t['\u2F6A'] = '\u76AE';
18727 t['\u2F6B'] = '\u76BF';
18728 t['\u2F6C'] = '\u76EE';
18729 t['\u2F6D'] = '\u77DB';
18730 t['\u2F6E'] = '\u77E2';
18731 t['\u2F6F'] = '\u77F3';
18732 t['\u2F70'] = '\u793A';
18733 t['\u2F71'] = '\u79B8';
18734 t['\u2F72'] = '\u79BE';
18735 t['\u2F73'] = '\u7A74';
18736 t['\u2F74'] = '\u7ACB';
18737 t['\u2F75'] = '\u7AF9';
18738 t['\u2F76'] = '\u7C73';
18739 t['\u2F77'] = '\u7CF8';
18740 t['\u2F78'] = '\u7F36';
18741 t['\u2F79'] = '\u7F51';
18742 t['\u2F7A'] = '\u7F8A';
18743 t['\u2F7B'] = '\u7FBD';
18744 t['\u2F7C'] = '\u8001';
18745 t['\u2F7D'] = '\u800C';
18746 t['\u2F7E'] = '\u8012';
18747 t['\u2F7F'] = '\u8033';
18748 t['\u2F80'] = '\u807F';
18749 t['\u2F81'] = '\u8089';
18750 t['\u2F82'] = '\u81E3';
18751 t['\u2F83'] = '\u81EA';
18752 t['\u2F84'] = '\u81F3';
18753 t['\u2F85'] = '\u81FC';
18754 t['\u2F86'] = '\u820C';
18755 t['\u2F87'] = '\u821B';
18756 t['\u2F88'] = '\u821F';
18757 t['\u2F89'] = '\u826E';
18758 t['\u2F8A'] = '\u8272';
18759 t['\u2F8B'] = '\u8278';
18760 t['\u2F8C'] = '\u864D';
18761 t['\u2F8D'] = '\u866B';
18762 t['\u2F8E'] = '\u8840';
18763 t['\u2F8F'] = '\u884C';
18764 t['\u2F90'] = '\u8863';
18765 t['\u2F91'] = '\u897E';
18766 t['\u2F92'] = '\u898B';
18767 t['\u2F93'] = '\u89D2';
18768 t['\u2F94'] = '\u8A00';
18769 t['\u2F95'] = '\u8C37';
18770 t['\u2F96'] = '\u8C46';
18771 t['\u2F97'] = '\u8C55';
18772 t['\u2F98'] = '\u8C78';
18773 t['\u2F99'] = '\u8C9D';
18774 t['\u2F9A'] = '\u8D64';
18775 t['\u2F9B'] = '\u8D70';
18776 t['\u2F9C'] = '\u8DB3';
18777 t['\u2F9D'] = '\u8EAB';
18778 t['\u2F9E'] = '\u8ECA';
18779 t['\u2F9F'] = '\u8F9B';
18780 t['\u2FA0'] = '\u8FB0';
18781 t['\u2FA1'] = '\u8FB5';
18782 t['\u2FA2'] = '\u9091';
18783 t['\u2FA3'] = '\u9149';
18784 t['\u2FA4'] = '\u91C6';
18785 t['\u2FA5'] = '\u91CC';
18786 t['\u2FA6'] = '\u91D1';
18787 t['\u2FA7'] = '\u9577';
18788 t['\u2FA8'] = '\u9580';
18789 t['\u2FA9'] = '\u961C';
18790 t['\u2FAA'] = '\u96B6';
18791 t['\u2FAB'] = '\u96B9';
18792 t['\u2FAC'] = '\u96E8';
18793 t['\u2FAD'] = '\u9751';
18794 t['\u2FAE'] = '\u975E';
18795 t['\u2FAF'] = '\u9762';
18796 t['\u2FB0'] = '\u9769';
18797 t['\u2FB1'] = '\u97CB';
18798 t['\u2FB2'] = '\u97ED';
18799 t['\u2FB3'] = '\u97F3';
18800 t['\u2FB4'] = '\u9801';
18801 t['\u2FB5'] = '\u98A8';
18802 t['\u2FB6'] = '\u98DB';
18803 t['\u2FB7'] = '\u98DF';
18804 t['\u2FB8'] = '\u9996';
18805 t['\u2FB9'] = '\u9999';
18806 t['\u2FBA'] = '\u99AC';
18807 t['\u2FBB'] = '\u9AA8';
18808 t['\u2FBC'] = '\u9AD8';
18809 t['\u2FBD'] = '\u9ADF';
18810 t['\u2FBE'] = '\u9B25';
18811 t['\u2FBF'] = '\u9B2F';
18812 t['\u2FC0'] = '\u9B32';
18813 t['\u2FC1'] = '\u9B3C';
18814 t['\u2FC2'] = '\u9B5A';
18815 t['\u2FC3'] = '\u9CE5';
18816 t['\u2FC4'] = '\u9E75';
18817 t['\u2FC5'] = '\u9E7F';
18818 t['\u2FC6'] = '\u9EA5';
18819 t['\u2FC7'] = '\u9EBB';
18820 t['\u2FC8'] = '\u9EC3';
18821 t['\u2FC9'] = '\u9ECD';
18822 t['\u2FCA'] = '\u9ED1';
18823 t['\u2FCB'] = '\u9EF9';
18824 t['\u2FCC'] = '\u9EFD';
18825 t['\u2FCD'] = '\u9F0E';
18826 t['\u2FCE'] = '\u9F13';
18827 t['\u2FCF'] = '\u9F20';
18828 t['\u2FD0'] = '\u9F3B';
18829 t['\u2FD1'] = '\u9F4A';
18830 t['\u2FD2'] = '\u9F52';
18831 t['\u2FD3'] = '\u9F8D';
18832 t['\u2FD4'] = '\u9F9C';
18833 t['\u2FD5'] = '\u9FA0';
18834 t['\u3036'] = '\u3012';
18835 t['\u3038'] = '\u5341';
18836 t['\u3039'] = '\u5344';
18837 t['\u303A'] = '\u5345';
18838 t['\u309B'] = '\u0020\u3099';
18839 t['\u309C'] = '\u0020\u309A';
18840 t['\u3131'] = '\u1100';
18841 t['\u3132'] = '\u1101';
18842 t['\u3133'] = '\u11AA';
18843 t['\u3134'] = '\u1102';
18844 t['\u3135'] = '\u11AC';
18845 t['\u3136'] = '\u11AD';
18846 t['\u3137'] = '\u1103';
18847 t['\u3138'] = '\u1104';
18848 t['\u3139'] = '\u1105';
18849 t['\u313A'] = '\u11B0';
18850 t['\u313B'] = '\u11B1';
18851 t['\u313C'] = '\u11B2';
18852 t['\u313D'] = '\u11B3';
18853 t['\u313E'] = '\u11B4';
18854 t['\u313F'] = '\u11B5';
18855 t['\u3140'] = '\u111A';
18856 t['\u3141'] = '\u1106';
18857 t['\u3142'] = '\u1107';
18858 t['\u3143'] = '\u1108';
18859 t['\u3144'] = '\u1121';
18860 t['\u3145'] = '\u1109';
18861 t['\u3146'] = '\u110A';
18862 t['\u3147'] = '\u110B';
18863 t['\u3148'] = '\u110C';
18864 t['\u3149'] = '\u110D';
18865 t['\u314A'] = '\u110E';
18866 t['\u314B'] = '\u110F';
18867 t['\u314C'] = '\u1110';
18868 t['\u314D'] = '\u1111';
18869 t['\u314E'] = '\u1112';
18870 t['\u314F'] = '\u1161';
18871 t['\u3150'] = '\u1162';
18872 t['\u3151'] = '\u1163';
18873 t['\u3152'] = '\u1164';
18874 t['\u3153'] = '\u1165';
18875 t['\u3154'] = '\u1166';
18876 t['\u3155'] = '\u1167';
18877 t['\u3156'] = '\u1168';
18878 t['\u3157'] = '\u1169';
18879 t['\u3158'] = '\u116A';
18880 t['\u3159'] = '\u116B';
18881 t['\u315A'] = '\u116C';
18882 t['\u315B'] = '\u116D';
18883 t['\u315C'] = '\u116E';
18884 t['\u315D'] = '\u116F';
18885 t['\u315E'] = '\u1170';
18886 t['\u315F'] = '\u1171';
18887 t['\u3160'] = '\u1172';
18888 t['\u3161'] = '\u1173';
18889 t['\u3162'] = '\u1174';
18890 t['\u3163'] = '\u1175';
18891 t['\u3164'] = '\u1160';
18892 t['\u3165'] = '\u1114';
18893 t['\u3166'] = '\u1115';
18894 t['\u3167'] = '\u11C7';
18895 t['\u3168'] = '\u11C8';
18896 t['\u3169'] = '\u11CC';
18897 t['\u316A'] = '\u11CE';
18898 t['\u316B'] = '\u11D3';
18899 t['\u316C'] = '\u11D7';
18900 t['\u316D'] = '\u11D9';
18901 t['\u316E'] = '\u111C';
18902 t['\u316F'] = '\u11DD';
18903 t['\u3170'] = '\u11DF';
18904 t['\u3171'] = '\u111D';
18905 t['\u3172'] = '\u111E';
18906 t['\u3173'] = '\u1120';
18907 t['\u3174'] = '\u1122';
18908 t['\u3175'] = '\u1123';
18909 t['\u3176'] = '\u1127';
18910 t['\u3177'] = '\u1129';
18911 t['\u3178'] = '\u112B';
18912 t['\u3179'] = '\u112C';
18913 t['\u317A'] = '\u112D';
18914 t['\u317B'] = '\u112E';
18915 t['\u317C'] = '\u112F';
18916 t['\u317D'] = '\u1132';
18917 t['\u317E'] = '\u1136';
18918 t['\u317F'] = '\u1140';
18919 t['\u3180'] = '\u1147';
18920 t['\u3181'] = '\u114C';
18921 t['\u3182'] = '\u11F1';
18922 t['\u3183'] = '\u11F2';
18923 t['\u3184'] = '\u1157';
18924 t['\u3185'] = '\u1158';
18925 t['\u3186'] = '\u1159';
18926 t['\u3187'] = '\u1184';
18927 t['\u3188'] = '\u1185';
18928 t['\u3189'] = '\u1188';
18929 t['\u318A'] = '\u1191';
18930 t['\u318B'] = '\u1192';
18931 t['\u318C'] = '\u1194';
18932 t['\u318D'] = '\u119E';
18933 t['\u318E'] = '\u11A1';
18934 t['\u3200'] = '\u0028\u1100\u0029';
18935 t['\u3201'] = '\u0028\u1102\u0029';
18936 t['\u3202'] = '\u0028\u1103\u0029';
18937 t['\u3203'] = '\u0028\u1105\u0029';
18938 t['\u3204'] = '\u0028\u1106\u0029';
18939 t['\u3205'] = '\u0028\u1107\u0029';
18940 t['\u3206'] = '\u0028\u1109\u0029';
18941 t['\u3207'] = '\u0028\u110B\u0029';
18942 t['\u3208'] = '\u0028\u110C\u0029';
18943 t['\u3209'] = '\u0028\u110E\u0029';
18944 t['\u320A'] = '\u0028\u110F\u0029';
18945 t['\u320B'] = '\u0028\u1110\u0029';
18946 t['\u320C'] = '\u0028\u1111\u0029';
18947 t['\u320D'] = '\u0028\u1112\u0029';
18948 t['\u320E'] = '\u0028\u1100\u1161\u0029';
18949 t['\u320F'] = '\u0028\u1102\u1161\u0029';
18950 t['\u3210'] = '\u0028\u1103\u1161\u0029';
18951 t['\u3211'] = '\u0028\u1105\u1161\u0029';
18952 t['\u3212'] = '\u0028\u1106\u1161\u0029';
18953 t['\u3213'] = '\u0028\u1107\u1161\u0029';
18954 t['\u3214'] = '\u0028\u1109\u1161\u0029';
18955 t['\u3215'] = '\u0028\u110B\u1161\u0029';
18956 t['\u3216'] = '\u0028\u110C\u1161\u0029';
18957 t['\u3217'] = '\u0028\u110E\u1161\u0029';
18958 t['\u3218'] = '\u0028\u110F\u1161\u0029';
18959 t['\u3219'] = '\u0028\u1110\u1161\u0029';
18960 t['\u321A'] = '\u0028\u1111\u1161\u0029';
18961 t['\u321B'] = '\u0028\u1112\u1161\u0029';
18962 t['\u321C'] = '\u0028\u110C\u116E\u0029';
18963 t['\u321D'] = '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029';
18964 t['\u321E'] = '\u0028\u110B\u1169\u1112\u116E\u0029';
18965 t['\u3220'] = '\u0028\u4E00\u0029';
18966 t['\u3221'] = '\u0028\u4E8C\u0029';
18967 t['\u3222'] = '\u0028\u4E09\u0029';
18968 t['\u3223'] = '\u0028\u56DB\u0029';
18969 t['\u3224'] = '\u0028\u4E94\u0029';
18970 t['\u3225'] = '\u0028\u516D\u0029';
18971 t['\u3226'] = '\u0028\u4E03\u0029';
18972 t['\u3227'] = '\u0028\u516B\u0029';
18973 t['\u3228'] = '\u0028\u4E5D\u0029';
18974 t['\u3229'] = '\u0028\u5341\u0029';
18975 t['\u322A'] = '\u0028\u6708\u0029';
18976 t['\u322B'] = '\u0028\u706B\u0029';
18977 t['\u322C'] = '\u0028\u6C34\u0029';
18978 t['\u322D'] = '\u0028\u6728\u0029';
18979 t['\u322E'] = '\u0028\u91D1\u0029';
18980 t['\u322F'] = '\u0028\u571F\u0029';
18981 t['\u3230'] = '\u0028\u65E5\u0029';
18982 t['\u3231'] = '\u0028\u682A\u0029';
18983 t['\u3232'] = '\u0028\u6709\u0029';
18984 t['\u3233'] = '\u0028\u793E\u0029';
18985 t['\u3234'] = '\u0028\u540D\u0029';
18986 t['\u3235'] = '\u0028\u7279\u0029';
18987 t['\u3236'] = '\u0028\u8CA1\u0029';
18988 t['\u3237'] = '\u0028\u795D\u0029';
18989 t['\u3238'] = '\u0028\u52B4\u0029';
18990 t['\u3239'] = '\u0028\u4EE3\u0029';
18991 t['\u323A'] = '\u0028\u547C\u0029';
18992 t['\u323B'] = '\u0028\u5B66\u0029';
18993 t['\u323C'] = '\u0028\u76E3\u0029';
18994 t['\u323D'] = '\u0028\u4F01\u0029';
18995 t['\u323E'] = '\u0028\u8CC7\u0029';
18996 t['\u323F'] = '\u0028\u5354\u0029';
18997 t['\u3240'] = '\u0028\u796D\u0029';
18998 t['\u3241'] = '\u0028\u4F11\u0029';
18999 t['\u3242'] = '\u0028\u81EA\u0029';
19000 t['\u3243'] = '\u0028\u81F3\u0029';
19001 t['\u32C0'] = '\u0031\u6708';
19002 t['\u32C1'] = '\u0032\u6708';
19003 t['\u32C2'] = '\u0033\u6708';
19004 t['\u32C3'] = '\u0034\u6708';
19005 t['\u32C4'] = '\u0035\u6708';
19006 t['\u32C5'] = '\u0036\u6708';
19007 t['\u32C6'] = '\u0037\u6708';
19008 t['\u32C7'] = '\u0038\u6708';
19009 t['\u32C8'] = '\u0039\u6708';
19010 t['\u32C9'] = '\u0031\u0030\u6708';
19011 t['\u32CA'] = '\u0031\u0031\u6708';
19012 t['\u32CB'] = '\u0031\u0032\u6708';
19013 t['\u3358'] = '\u0030\u70B9';
19014 t['\u3359'] = '\u0031\u70B9';
19015 t['\u335A'] = '\u0032\u70B9';
19016 t['\u335B'] = '\u0033\u70B9';
19017 t['\u335C'] = '\u0034\u70B9';
19018 t['\u335D'] = '\u0035\u70B9';
19019 t['\u335E'] = '\u0036\u70B9';
19020 t['\u335F'] = '\u0037\u70B9';
19021 t['\u3360'] = '\u0038\u70B9';
19022 t['\u3361'] = '\u0039\u70B9';
19023 t['\u3362'] = '\u0031\u0030\u70B9';
19024 t['\u3363'] = '\u0031\u0031\u70B9';
19025 t['\u3364'] = '\u0031\u0032\u70B9';
19026 t['\u3365'] = '\u0031\u0033\u70B9';
19027 t['\u3366'] = '\u0031\u0034\u70B9';
19028 t['\u3367'] = '\u0031\u0035\u70B9';
19029 t['\u3368'] = '\u0031\u0036\u70B9';
19030 t['\u3369'] = '\u0031\u0037\u70B9';
19031 t['\u336A'] = '\u0031\u0038\u70B9';
19032 t['\u336B'] = '\u0031\u0039\u70B9';
19033 t['\u336C'] = '\u0032\u0030\u70B9';
19034 t['\u336D'] = '\u0032\u0031\u70B9';
19035 t['\u336E'] = '\u0032\u0032\u70B9';
19036 t['\u336F'] = '\u0032\u0033\u70B9';
19037 t['\u3370'] = '\u0032\u0034\u70B9';
19038 t['\u33E0'] = '\u0031\u65E5';
19039 t['\u33E1'] = '\u0032\u65E5';
19040 t['\u33E2'] = '\u0033\u65E5';
19041 t['\u33E3'] = '\u0034\u65E5';
19042 t['\u33E4'] = '\u0035\u65E5';
19043 t['\u33E5'] = '\u0036\u65E5';
19044 t['\u33E6'] = '\u0037\u65E5';
19045 t['\u33E7'] = '\u0038\u65E5';
19046 t['\u33E8'] = '\u0039\u65E5';
19047 t['\u33E9'] = '\u0031\u0030\u65E5';
19048 t['\u33EA'] = '\u0031\u0031\u65E5';
19049 t['\u33EB'] = '\u0031\u0032\u65E5';
19050 t['\u33EC'] = '\u0031\u0033\u65E5';
19051 t['\u33ED'] = '\u0031\u0034\u65E5';
19052 t['\u33EE'] = '\u0031\u0035\u65E5';
19053 t['\u33EF'] = '\u0031\u0036\u65E5';
19054 t['\u33F0'] = '\u0031\u0037\u65E5';
19055 t['\u33F1'] = '\u0031\u0038\u65E5';
19056 t['\u33F2'] = '\u0031\u0039\u65E5';
19057 t['\u33F3'] = '\u0032\u0030\u65E5';
19058 t['\u33F4'] = '\u0032\u0031\u65E5';
19059 t['\u33F5'] = '\u0032\u0032\u65E5';
19060 t['\u33F6'] = '\u0032\u0033\u65E5';
19061 t['\u33F7'] = '\u0032\u0034\u65E5';
19062 t['\u33F8'] = '\u0032\u0035\u65E5';
19063 t['\u33F9'] = '\u0032\u0036\u65E5';
19064 t['\u33FA'] = '\u0032\u0037\u65E5';
19065 t['\u33FB'] = '\u0032\u0038\u65E5';
19066 t['\u33FC'] = '\u0032\u0039\u65E5';
19067 t['\u33FD'] = '\u0033\u0030\u65E5';
19068 t['\u33FE'] = '\u0033\u0031\u65E5';
19069 t['\uFB00'] = '\u0066\u0066';
19070 t['\uFB01'] = '\u0066\u0069';
19071 t['\uFB02'] = '\u0066\u006C';
19072 t['\uFB03'] = '\u0066\u0066\u0069';
19073 t['\uFB04'] = '\u0066\u0066\u006C';
19074 t['\uFB05'] = '\u017F\u0074';
19075 t['\uFB06'] = '\u0073\u0074';
19076 t['\uFB13'] = '\u0574\u0576';
19077 t['\uFB14'] = '\u0574\u0565';
19078 t['\uFB15'] = '\u0574\u056B';
19079 t['\uFB16'] = '\u057E\u0576';
19080 t['\uFB17'] = '\u0574\u056D';
19081 t['\uFB4F'] = '\u05D0\u05DC';
19082 t['\uFB50'] = '\u0671';
19083 t['\uFB51'] = '\u0671';
19084 t['\uFB52'] = '\u067B';
19085 t['\uFB53'] = '\u067B';
19086 t['\uFB54'] = '\u067B';
19087 t['\uFB55'] = '\u067B';
19088 t['\uFB56'] = '\u067E';
19089 t['\uFB57'] = '\u067E';
19090 t['\uFB58'] = '\u067E';
19091 t['\uFB59'] = '\u067E';
19092 t['\uFB5A'] = '\u0680';
19093 t['\uFB5B'] = '\u0680';
19094 t['\uFB5C'] = '\u0680';
19095 t['\uFB5D'] = '\u0680';
19096 t['\uFB5E'] = '\u067A';
19097 t['\uFB5F'] = '\u067A';
19098 t['\uFB60'] = '\u067A';
19099 t['\uFB61'] = '\u067A';
19100 t['\uFB62'] = '\u067F';
19101 t['\uFB63'] = '\u067F';
19102 t['\uFB64'] = '\u067F';
19103 t['\uFB65'] = '\u067F';
19104 t['\uFB66'] = '\u0679';
19105 t['\uFB67'] = '\u0679';
19106 t['\uFB68'] = '\u0679';
19107 t['\uFB69'] = '\u0679';
19108 t['\uFB6A'] = '\u06A4';
19109 t['\uFB6B'] = '\u06A4';
19110 t['\uFB6C'] = '\u06A4';
19111 t['\uFB6D'] = '\u06A4';
19112 t['\uFB6E'] = '\u06A6';
19113 t['\uFB6F'] = '\u06A6';
19114 t['\uFB70'] = '\u06A6';
19115 t['\uFB71'] = '\u06A6';
19116 t['\uFB72'] = '\u0684';
19117 t['\uFB73'] = '\u0684';
19118 t['\uFB74'] = '\u0684';
19119 t['\uFB75'] = '\u0684';
19120 t['\uFB76'] = '\u0683';
19121 t['\uFB77'] = '\u0683';
19122 t['\uFB78'] = '\u0683';
19123 t['\uFB79'] = '\u0683';
19124 t['\uFB7A'] = '\u0686';
19125 t['\uFB7B'] = '\u0686';
19126 t['\uFB7C'] = '\u0686';
19127 t['\uFB7D'] = '\u0686';
19128 t['\uFB7E'] = '\u0687';
19129 t['\uFB7F'] = '\u0687';
19130 t['\uFB80'] = '\u0687';
19131 t['\uFB81'] = '\u0687';
19132 t['\uFB82'] = '\u068D';
19133 t['\uFB83'] = '\u068D';
19134 t['\uFB84'] = '\u068C';
19135 t['\uFB85'] = '\u068C';
19136 t['\uFB86'] = '\u068E';
19137 t['\uFB87'] = '\u068E';
19138 t['\uFB88'] = '\u0688';
19139 t['\uFB89'] = '\u0688';
19140 t['\uFB8A'] = '\u0698';
19141 t['\uFB8B'] = '\u0698';
19142 t['\uFB8C'] = '\u0691';
19143 t['\uFB8D'] = '\u0691';
19144 t['\uFB8E'] = '\u06A9';
19145 t['\uFB8F'] = '\u06A9';
19146 t['\uFB90'] = '\u06A9';
19147 t['\uFB91'] = '\u06A9';
19148 t['\uFB92'] = '\u06AF';
19149 t['\uFB93'] = '\u06AF';
19150 t['\uFB94'] = '\u06AF';
19151 t['\uFB95'] = '\u06AF';
19152 t['\uFB96'] = '\u06B3';
19153 t['\uFB97'] = '\u06B3';
19154 t['\uFB98'] = '\u06B3';
19155 t['\uFB99'] = '\u06B3';
19156 t['\uFB9A'] = '\u06B1';
19157 t['\uFB9B'] = '\u06B1';
19158 t['\uFB9C'] = '\u06B1';
19159 t['\uFB9D'] = '\u06B1';
19160 t['\uFB9E'] = '\u06BA';
19161 t['\uFB9F'] = '\u06BA';
19162 t['\uFBA0'] = '\u06BB';
19163 t['\uFBA1'] = '\u06BB';
19164 t['\uFBA2'] = '\u06BB';
19165 t['\uFBA3'] = '\u06BB';
19166 t['\uFBA4'] = '\u06C0';
19167 t['\uFBA5'] = '\u06C0';
19168 t['\uFBA6'] = '\u06C1';
19169 t['\uFBA7'] = '\u06C1';
19170 t['\uFBA8'] = '\u06C1';
19171 t['\uFBA9'] = '\u06C1';
19172 t['\uFBAA'] = '\u06BE';
19173 t['\uFBAB'] = '\u06BE';
19174 t['\uFBAC'] = '\u06BE';
19175 t['\uFBAD'] = '\u06BE';
19176 t['\uFBAE'] = '\u06D2';
19177 t['\uFBAF'] = '\u06D2';
19178 t['\uFBB0'] = '\u06D3';
19179 t['\uFBB1'] = '\u06D3';
19180 t['\uFBD3'] = '\u06AD';
19181 t['\uFBD4'] = '\u06AD';
19182 t['\uFBD5'] = '\u06AD';
19183 t['\uFBD6'] = '\u06AD';
19184 t['\uFBD7'] = '\u06C7';
19185 t['\uFBD8'] = '\u06C7';
19186 t['\uFBD9'] = '\u06C6';
19187 t['\uFBDA'] = '\u06C6';
19188 t['\uFBDB'] = '\u06C8';
19189 t['\uFBDC'] = '\u06C8';
19190 t['\uFBDD'] = '\u0677';
19191 t['\uFBDE'] = '\u06CB';
19192 t['\uFBDF'] = '\u06CB';
19193 t['\uFBE0'] = '\u06C5';
19194 t['\uFBE1'] = '\u06C5';
19195 t['\uFBE2'] = '\u06C9';
19196 t['\uFBE3'] = '\u06C9';
19197 t['\uFBE4'] = '\u06D0';
19198 t['\uFBE5'] = '\u06D0';
19199 t['\uFBE6'] = '\u06D0';
19200 t['\uFBE7'] = '\u06D0';
19201 t['\uFBE8'] = '\u0649';
19202 t['\uFBE9'] = '\u0649';
19203 t['\uFBEA'] = '\u0626\u0627';
19204 t['\uFBEB'] = '\u0626\u0627';
19205 t['\uFBEC'] = '\u0626\u06D5';
19206 t['\uFBED'] = '\u0626\u06D5';
19207 t['\uFBEE'] = '\u0626\u0648';
19208 t['\uFBEF'] = '\u0626\u0648';
19209 t['\uFBF0'] = '\u0626\u06C7';
19210 t['\uFBF1'] = '\u0626\u06C7';
19211 t['\uFBF2'] = '\u0626\u06C6';
19212 t['\uFBF3'] = '\u0626\u06C6';
19213 t['\uFBF4'] = '\u0626\u06C8';
19214 t['\uFBF5'] = '\u0626\u06C8';
19215 t['\uFBF6'] = '\u0626\u06D0';
19216 t['\uFBF7'] = '\u0626\u06D0';
19217 t['\uFBF8'] = '\u0626\u06D0';
19218 t['\uFBF9'] = '\u0626\u0649';
19219 t['\uFBFA'] = '\u0626\u0649';
19220 t['\uFBFB'] = '\u0626\u0649';
19221 t['\uFBFC'] = '\u06CC';
19222 t['\uFBFD'] = '\u06CC';
19223 t['\uFBFE'] = '\u06CC';
19224 t['\uFBFF'] = '\u06CC';
19225 t['\uFC00'] = '\u0626\u062C';
19226 t['\uFC01'] = '\u0626\u062D';
19227 t['\uFC02'] = '\u0626\u0645';
19228 t['\uFC03'] = '\u0626\u0649';
19229 t['\uFC04'] = '\u0626\u064A';
19230 t['\uFC05'] = '\u0628\u062C';
19231 t['\uFC06'] = '\u0628\u062D';
19232 t['\uFC07'] = '\u0628\u062E';
19233 t['\uFC08'] = '\u0628\u0645';
19234 t['\uFC09'] = '\u0628\u0649';
19235 t['\uFC0A'] = '\u0628\u064A';
19236 t['\uFC0B'] = '\u062A\u062C';
19237 t['\uFC0C'] = '\u062A\u062D';
19238 t['\uFC0D'] = '\u062A\u062E';
19239 t['\uFC0E'] = '\u062A\u0645';
19240 t['\uFC0F'] = '\u062A\u0649';
19241 t['\uFC10'] = '\u062A\u064A';
19242 t['\uFC11'] = '\u062B\u062C';
19243 t['\uFC12'] = '\u062B\u0645';
19244 t['\uFC13'] = '\u062B\u0649';
19245 t['\uFC14'] = '\u062B\u064A';
19246 t['\uFC15'] = '\u062C\u062D';
19247 t['\uFC16'] = '\u062C\u0645';
19248 t['\uFC17'] = '\u062D\u062C';
19249 t['\uFC18'] = '\u062D\u0645';
19250 t['\uFC19'] = '\u062E\u062C';
19251 t['\uFC1A'] = '\u062E\u062D';
19252 t['\uFC1B'] = '\u062E\u0645';
19253 t['\uFC1C'] = '\u0633\u062C';
19254 t['\uFC1D'] = '\u0633\u062D';
19255 t['\uFC1E'] = '\u0633\u062E';
19256 t['\uFC1F'] = '\u0633\u0645';
19257 t['\uFC20'] = '\u0635\u062D';
19258 t['\uFC21'] = '\u0635\u0645';
19259 t['\uFC22'] = '\u0636\u062C';
19260 t['\uFC23'] = '\u0636\u062D';
19261 t['\uFC24'] = '\u0636\u062E';
19262 t['\uFC25'] = '\u0636\u0645';
19263 t['\uFC26'] = '\u0637\u062D';
19264 t['\uFC27'] = '\u0637\u0645';
19265 t['\uFC28'] = '\u0638\u0645';
19266 t['\uFC29'] = '\u0639\u062C';
19267 t['\uFC2A'] = '\u0639\u0645';
19268 t['\uFC2B'] = '\u063A\u062C';
19269 t['\uFC2C'] = '\u063A\u0645';
19270 t['\uFC2D'] = '\u0641\u062C';
19271 t['\uFC2E'] = '\u0641\u062D';
19272 t['\uFC2F'] = '\u0641\u062E';
19273 t['\uFC30'] = '\u0641\u0645';
19274 t['\uFC31'] = '\u0641\u0649';
19275 t['\uFC32'] = '\u0641\u064A';
19276 t['\uFC33'] = '\u0642\u062D';
19277 t['\uFC34'] = '\u0642\u0645';
19278 t['\uFC35'] = '\u0642\u0649';
19279 t['\uFC36'] = '\u0642\u064A';
19280 t['\uFC37'] = '\u0643\u0627';
19281 t['\uFC38'] = '\u0643\u062C';
19282 t['\uFC39'] = '\u0643\u062D';
19283 t['\uFC3A'] = '\u0643\u062E';
19284 t['\uFC3B'] = '\u0643\u0644';
19285 t['\uFC3C'] = '\u0643\u0645';
19286 t['\uFC3D'] = '\u0643\u0649';
19287 t['\uFC3E'] = '\u0643\u064A';
19288 t['\uFC3F'] = '\u0644\u062C';
19289 t['\uFC40'] = '\u0644\u062D';
19290 t['\uFC41'] = '\u0644\u062E';
19291 t['\uFC42'] = '\u0644\u0645';
19292 t['\uFC43'] = '\u0644\u0649';
19293 t['\uFC44'] = '\u0644\u064A';
19294 t['\uFC45'] = '\u0645\u062C';
19295 t['\uFC46'] = '\u0645\u062D';
19296 t['\uFC47'] = '\u0645\u062E';
19297 t['\uFC48'] = '\u0645\u0645';
19298 t['\uFC49'] = '\u0645\u0649';
19299 t['\uFC4A'] = '\u0645\u064A';
19300 t['\uFC4B'] = '\u0646\u062C';
19301 t['\uFC4C'] = '\u0646\u062D';
19302 t['\uFC4D'] = '\u0646\u062E';
19303 t['\uFC4E'] = '\u0646\u0645';
19304 t['\uFC4F'] = '\u0646\u0649';
19305 t['\uFC50'] = '\u0646\u064A';
19306 t['\uFC51'] = '\u0647\u062C';
19307 t['\uFC52'] = '\u0647\u0645';
19308 t['\uFC53'] = '\u0647\u0649';
19309 t['\uFC54'] = '\u0647\u064A';
19310 t['\uFC55'] = '\u064A\u062C';
19311 t['\uFC56'] = '\u064A\u062D';
19312 t['\uFC57'] = '\u064A\u062E';
19313 t['\uFC58'] = '\u064A\u0645';
19314 t['\uFC59'] = '\u064A\u0649';
19315 t['\uFC5A'] = '\u064A\u064A';
19316 t['\uFC5B'] = '\u0630\u0670';
19317 t['\uFC5C'] = '\u0631\u0670';
19318 t['\uFC5D'] = '\u0649\u0670';
19319 t['\uFC5E'] = '\u0020\u064C\u0651';
19320 t['\uFC5F'] = '\u0020\u064D\u0651';
19321 t['\uFC60'] = '\u0020\u064E\u0651';
19322 t['\uFC61'] = '\u0020\u064F\u0651';
19323 t['\uFC62'] = '\u0020\u0650\u0651';
19324 t['\uFC63'] = '\u0020\u0651\u0670';
19325 t['\uFC64'] = '\u0626\u0631';
19326 t['\uFC65'] = '\u0626\u0632';
19327 t['\uFC66'] = '\u0626\u0645';
19328 t['\uFC67'] = '\u0626\u0646';
19329 t['\uFC68'] = '\u0626\u0649';
19330 t['\uFC69'] = '\u0626\u064A';
19331 t['\uFC6A'] = '\u0628\u0631';
19332 t['\uFC6B'] = '\u0628\u0632';
19333 t['\uFC6C'] = '\u0628\u0645';
19334 t['\uFC6D'] = '\u0628\u0646';
19335 t['\uFC6E'] = '\u0628\u0649';
19336 t['\uFC6F'] = '\u0628\u064A';
19337 t['\uFC70'] = '\u062A\u0631';
19338 t['\uFC71'] = '\u062A\u0632';
19339 t['\uFC72'] = '\u062A\u0645';
19340 t['\uFC73'] = '\u062A\u0646';
19341 t['\uFC74'] = '\u062A\u0649';
19342 t['\uFC75'] = '\u062A\u064A';
19343 t['\uFC76'] = '\u062B\u0631';
19344 t['\uFC77'] = '\u062B\u0632';
19345 t['\uFC78'] = '\u062B\u0645';
19346 t['\uFC79'] = '\u062B\u0646';
19347 t['\uFC7A'] = '\u062B\u0649';
19348 t['\uFC7B'] = '\u062B\u064A';
19349 t['\uFC7C'] = '\u0641\u0649';
19350 t['\uFC7D'] = '\u0641\u064A';
19351 t['\uFC7E'] = '\u0642\u0649';
19352 t['\uFC7F'] = '\u0642\u064A';
19353 t['\uFC80'] = '\u0643\u0627';
19354 t['\uFC81'] = '\u0643\u0644';
19355 t['\uFC82'] = '\u0643\u0645';
19356 t['\uFC83'] = '\u0643\u0649';
19357 t['\uFC84'] = '\u0643\u064A';
19358 t['\uFC85'] = '\u0644\u0645';
19359 t['\uFC86'] = '\u0644\u0649';
19360 t['\uFC87'] = '\u0644\u064A';
19361 t['\uFC88'] = '\u0645\u0627';
19362 t['\uFC89'] = '\u0645\u0645';
19363 t['\uFC8A'] = '\u0646\u0631';
19364 t['\uFC8B'] = '\u0646\u0632';
19365 t['\uFC8C'] = '\u0646\u0645';
19366 t['\uFC8D'] = '\u0646\u0646';
19367 t['\uFC8E'] = '\u0646\u0649';
19368 t['\uFC8F'] = '\u0646\u064A';
19369 t['\uFC90'] = '\u0649\u0670';
19370 t['\uFC91'] = '\u064A\u0631';
19371 t['\uFC92'] = '\u064A\u0632';
19372 t['\uFC93'] = '\u064A\u0645';
19373 t['\uFC94'] = '\u064A\u0646';
19374 t['\uFC95'] = '\u064A\u0649';
19375 t['\uFC96'] = '\u064A\u064A';
19376 t['\uFC97'] = '\u0626\u062C';
19377 t['\uFC98'] = '\u0626\u062D';
19378 t['\uFC99'] = '\u0626\u062E';
19379 t['\uFC9A'] = '\u0626\u0645';
19380 t['\uFC9B'] = '\u0626\u0647';
19381 t['\uFC9C'] = '\u0628\u062C';
19382 t['\uFC9D'] = '\u0628\u062D';
19383 t['\uFC9E'] = '\u0628\u062E';
19384 t['\uFC9F'] = '\u0628\u0645';
19385 t['\uFCA0'] = '\u0628\u0647';
19386 t['\uFCA1'] = '\u062A\u062C';
19387 t['\uFCA2'] = '\u062A\u062D';
19388 t['\uFCA3'] = '\u062A\u062E';
19389 t['\uFCA4'] = '\u062A\u0645';
19390 t['\uFCA5'] = '\u062A\u0647';
19391 t['\uFCA6'] = '\u062B\u0645';
19392 t['\uFCA7'] = '\u062C\u062D';
19393 t['\uFCA8'] = '\u062C\u0645';
19394 t['\uFCA9'] = '\u062D\u062C';
19395 t['\uFCAA'] = '\u062D\u0645';
19396 t['\uFCAB'] = '\u062E\u062C';
19397 t['\uFCAC'] = '\u062E\u0645';
19398 t['\uFCAD'] = '\u0633\u062C';
19399 t['\uFCAE'] = '\u0633\u062D';
19400 t['\uFCAF'] = '\u0633\u062E';
19401 t['\uFCB0'] = '\u0633\u0645';
19402 t['\uFCB1'] = '\u0635\u062D';
19403 t['\uFCB2'] = '\u0635\u062E';
19404 t['\uFCB3'] = '\u0635\u0645';
19405 t['\uFCB4'] = '\u0636\u062C';
19406 t['\uFCB5'] = '\u0636\u062D';
19407 t['\uFCB6'] = '\u0636\u062E';
19408 t['\uFCB7'] = '\u0636\u0645';
19409 t['\uFCB8'] = '\u0637\u062D';
19410 t['\uFCB9'] = '\u0638\u0645';
19411 t['\uFCBA'] = '\u0639\u062C';
19412 t['\uFCBB'] = '\u0639\u0645';
19413 t['\uFCBC'] = '\u063A\u062C';
19414 t['\uFCBD'] = '\u063A\u0645';
19415 t['\uFCBE'] = '\u0641\u062C';
19416 t['\uFCBF'] = '\u0641\u062D';
19417 t['\uFCC0'] = '\u0641\u062E';
19418 t['\uFCC1'] = '\u0641\u0645';
19419 t['\uFCC2'] = '\u0642\u062D';
19420 t['\uFCC3'] = '\u0642\u0645';
19421 t['\uFCC4'] = '\u0643\u062C';
19422 t['\uFCC5'] = '\u0643\u062D';
19423 t['\uFCC6'] = '\u0643\u062E';
19424 t['\uFCC7'] = '\u0643\u0644';
19425 t['\uFCC8'] = '\u0643\u0645';
19426 t['\uFCC9'] = '\u0644\u062C';
19427 t['\uFCCA'] = '\u0644\u062D';
19428 t['\uFCCB'] = '\u0644\u062E';
19429 t['\uFCCC'] = '\u0644\u0645';
19430 t['\uFCCD'] = '\u0644\u0647';
19431 t['\uFCCE'] = '\u0645\u062C';
19432 t['\uFCCF'] = '\u0645\u062D';
19433 t['\uFCD0'] = '\u0645\u062E';
19434 t['\uFCD1'] = '\u0645\u0645';
19435 t['\uFCD2'] = '\u0646\u062C';
19436 t['\uFCD3'] = '\u0646\u062D';
19437 t['\uFCD4'] = '\u0646\u062E';
19438 t['\uFCD5'] = '\u0646\u0645';
19439 t['\uFCD6'] = '\u0646\u0647';
19440 t['\uFCD7'] = '\u0647\u062C';
19441 t['\uFCD8'] = '\u0647\u0645';
19442 t['\uFCD9'] = '\u0647\u0670';
19443 t['\uFCDA'] = '\u064A\u062C';
19444 t['\uFCDB'] = '\u064A\u062D';
19445 t['\uFCDC'] = '\u064A\u062E';
19446 t['\uFCDD'] = '\u064A\u0645';
19447 t['\uFCDE'] = '\u064A\u0647';
19448 t['\uFCDF'] = '\u0626\u0645';
19449 t['\uFCE0'] = '\u0626\u0647';
19450 t['\uFCE1'] = '\u0628\u0645';
19451 t['\uFCE2'] = '\u0628\u0647';
19452 t['\uFCE3'] = '\u062A\u0645';
19453 t['\uFCE4'] = '\u062A\u0647';
19454 t['\uFCE5'] = '\u062B\u0645';
19455 t['\uFCE6'] = '\u062B\u0647';
19456 t['\uFCE7'] = '\u0633\u0645';
19457 t['\uFCE8'] = '\u0633\u0647';
19458 t['\uFCE9'] = '\u0634\u0645';
19459 t['\uFCEA'] = '\u0634\u0647';
19460 t['\uFCEB'] = '\u0643\u0644';
19461 t['\uFCEC'] = '\u0643\u0645';
19462 t['\uFCED'] = '\u0644\u0645';
19463 t['\uFCEE'] = '\u0646\u0645';
19464 t['\uFCEF'] = '\u0646\u0647';
19465 t['\uFCF0'] = '\u064A\u0645';
19466 t['\uFCF1'] = '\u064A\u0647';
19467 t['\uFCF2'] = '\u0640\u064E\u0651';
19468 t['\uFCF3'] = '\u0640\u064F\u0651';
19469 t['\uFCF4'] = '\u0640\u0650\u0651';
19470 t['\uFCF5'] = '\u0637\u0649';
19471 t['\uFCF6'] = '\u0637\u064A';
19472 t['\uFCF7'] = '\u0639\u0649';
19473 t['\uFCF8'] = '\u0639\u064A';
19474 t['\uFCF9'] = '\u063A\u0649';
19475 t['\uFCFA'] = '\u063A\u064A';
19476 t['\uFCFB'] = '\u0633\u0649';
19477 t['\uFCFC'] = '\u0633\u064A';
19478 t['\uFCFD'] = '\u0634\u0649';
19479 t['\uFCFE'] = '\u0634\u064A';
19480 t['\uFCFF'] = '\u062D\u0649';
19481 t['\uFD00'] = '\u062D\u064A';
19482 t['\uFD01'] = '\u062C\u0649';
19483 t['\uFD02'] = '\u062C\u064A';
19484 t['\uFD03'] = '\u062E\u0649';
19485 t['\uFD04'] = '\u062E\u064A';
19486 t['\uFD05'] = '\u0635\u0649';
19487 t['\uFD06'] = '\u0635\u064A';
19488 t['\uFD07'] = '\u0636\u0649';
19489 t['\uFD08'] = '\u0636\u064A';
19490 t['\uFD09'] = '\u0634\u062C';
19491 t['\uFD0A'] = '\u0634\u062D';
19492 t['\uFD0B'] = '\u0634\u062E';
19493 t['\uFD0C'] = '\u0634\u0645';
19494 t['\uFD0D'] = '\u0634\u0631';
19495 t['\uFD0E'] = '\u0633\u0631';
19496 t['\uFD0F'] = '\u0635\u0631';
19497 t['\uFD10'] = '\u0636\u0631';
19498 t['\uFD11'] = '\u0637\u0649';
19499 t['\uFD12'] = '\u0637\u064A';
19500 t['\uFD13'] = '\u0639\u0649';
19501 t['\uFD14'] = '\u0639\u064A';
19502 t['\uFD15'] = '\u063A\u0649';
19503 t['\uFD16'] = '\u063A\u064A';
19504 t['\uFD17'] = '\u0633\u0649';
19505 t['\uFD18'] = '\u0633\u064A';
19506 t['\uFD19'] = '\u0634\u0649';
19507 t['\uFD1A'] = '\u0634\u064A';
19508 t['\uFD1B'] = '\u062D\u0649';
19509 t['\uFD1C'] = '\u062D\u064A';
19510 t['\uFD1D'] = '\u062C\u0649';
19511 t['\uFD1E'] = '\u062C\u064A';
19512 t['\uFD1F'] = '\u062E\u0649';
19513 t['\uFD20'] = '\u062E\u064A';
19514 t['\uFD21'] = '\u0635\u0649';
19515 t['\uFD22'] = '\u0635\u064A';
19516 t['\uFD23'] = '\u0636\u0649';
19517 t['\uFD24'] = '\u0636\u064A';
19518 t['\uFD25'] = '\u0634\u062C';
19519 t['\uFD26'] = '\u0634\u062D';
19520 t['\uFD27'] = '\u0634\u062E';
19521 t['\uFD28'] = '\u0634\u0645';
19522 t['\uFD29'] = '\u0634\u0631';
19523 t['\uFD2A'] = '\u0633\u0631';
19524 t['\uFD2B'] = '\u0635\u0631';
19525 t['\uFD2C'] = '\u0636\u0631';
19526 t['\uFD2D'] = '\u0634\u062C';
19527 t['\uFD2E'] = '\u0634\u062D';
19528 t['\uFD2F'] = '\u0634\u062E';
19529 t['\uFD30'] = '\u0634\u0645';
19530 t['\uFD31'] = '\u0633\u0647';
19531 t['\uFD32'] = '\u0634\u0647';
19532 t['\uFD33'] = '\u0637\u0645';
19533 t['\uFD34'] = '\u0633\u062C';
19534 t['\uFD35'] = '\u0633\u062D';
19535 t['\uFD36'] = '\u0633\u062E';
19536 t['\uFD37'] = '\u0634\u062C';
19537 t['\uFD38'] = '\u0634\u062D';
19538 t['\uFD39'] = '\u0634\u062E';
19539 t['\uFD3A'] = '\u0637\u0645';
19540 t['\uFD3B'] = '\u0638\u0645';
19541 t['\uFD3C'] = '\u0627\u064B';
19542 t['\uFD3D'] = '\u0627\u064B';
19543 t['\uFD50'] = '\u062A\u062C\u0645';
19544 t['\uFD51'] = '\u062A\u062D\u062C';
19545 t['\uFD52'] = '\u062A\u062D\u062C';
19546 t['\uFD53'] = '\u062A\u062D\u0645';
19547 t['\uFD54'] = '\u062A\u062E\u0645';
19548 t['\uFD55'] = '\u062A\u0645\u062C';
19549 t['\uFD56'] = '\u062A\u0645\u062D';
19550 t['\uFD57'] = '\u062A\u0645\u062E';
19551 t['\uFD58'] = '\u062C\u0645\u062D';
19552 t['\uFD59'] = '\u062C\u0645\u062D';
19553 t['\uFD5A'] = '\u062D\u0645\u064A';
19554 t['\uFD5B'] = '\u062D\u0645\u0649';
19555 t['\uFD5C'] = '\u0633\u062D\u062C';
19556 t['\uFD5D'] = '\u0633\u062C\u062D';
19557 t['\uFD5E'] = '\u0633\u062C\u0649';
19558 t['\uFD5F'] = '\u0633\u0645\u062D';
19559 t['\uFD60'] = '\u0633\u0645\u062D';
19560 t['\uFD61'] = '\u0633\u0645\u062C';
19561 t['\uFD62'] = '\u0633\u0645\u0645';
19562 t['\uFD63'] = '\u0633\u0645\u0645';
19563 t['\uFD64'] = '\u0635\u062D\u062D';
19564 t['\uFD65'] = '\u0635\u062D\u062D';
19565 t['\uFD66'] = '\u0635\u0645\u0645';
19566 t['\uFD67'] = '\u0634\u062D\u0645';
19567 t['\uFD68'] = '\u0634\u062D\u0645';
19568 t['\uFD69'] = '\u0634\u062C\u064A';
19569 t['\uFD6A'] = '\u0634\u0645\u062E';
19570 t['\uFD6B'] = '\u0634\u0645\u062E';
19571 t['\uFD6C'] = '\u0634\u0645\u0645';
19572 t['\uFD6D'] = '\u0634\u0645\u0645';
19573 t['\uFD6E'] = '\u0636\u062D\u0649';
19574 t['\uFD6F'] = '\u0636\u062E\u0645';
19575 t['\uFD70'] = '\u0636\u062E\u0645';
19576 t['\uFD71'] = '\u0637\u0645\u062D';
19577 t['\uFD72'] = '\u0637\u0645\u062D';
19578 t['\uFD73'] = '\u0637\u0645\u0645';
19579 t['\uFD74'] = '\u0637\u0645\u064A';
19580 t['\uFD75'] = '\u0639\u062C\u0645';
19581 t['\uFD76'] = '\u0639\u0645\u0645';
19582 t['\uFD77'] = '\u0639\u0645\u0645';
19583 t['\uFD78'] = '\u0639\u0645\u0649';
19584 t['\uFD79'] = '\u063A\u0645\u0645';
19585 t['\uFD7A'] = '\u063A\u0645\u064A';
19586 t['\uFD7B'] = '\u063A\u0645\u0649';
19587 t['\uFD7C'] = '\u0641\u062E\u0645';
19588 t['\uFD7D'] = '\u0641\u062E\u0645';
19589 t['\uFD7E'] = '\u0642\u0645\u062D';
19590 t['\uFD7F'] = '\u0642\u0645\u0645';
19591 t['\uFD80'] = '\u0644\u062D\u0645';
19592 t['\uFD81'] = '\u0644\u062D\u064A';
19593 t['\uFD82'] = '\u0644\u062D\u0649';
19594 t['\uFD83'] = '\u0644\u062C\u062C';
19595 t['\uFD84'] = '\u0644\u062C\u062C';
19596 t['\uFD85'] = '\u0644\u062E\u0645';
19597 t['\uFD86'] = '\u0644\u062E\u0645';
19598 t['\uFD87'] = '\u0644\u0645\u062D';
19599 t['\uFD88'] = '\u0644\u0645\u062D';
19600 t['\uFD89'] = '\u0645\u062D\u062C';
19601 t['\uFD8A'] = '\u0645\u062D\u0645';
19602 t['\uFD8B'] = '\u0645\u062D\u064A';
19603 t['\uFD8C'] = '\u0645\u062C\u062D';
19604 t['\uFD8D'] = '\u0645\u062C\u0645';
19605 t['\uFD8E'] = '\u0645\u062E\u062C';
19606 t['\uFD8F'] = '\u0645\u062E\u0645';
19607 t['\uFD92'] = '\u0645\u062C\u062E';
19608 t['\uFD93'] = '\u0647\u0645\u062C';
19609 t['\uFD94'] = '\u0647\u0645\u0645';
19610 t['\uFD95'] = '\u0646\u062D\u0645';
19611 t['\uFD96'] = '\u0646\u062D\u0649';
19612 t['\uFD97'] = '\u0646\u062C\u0645';
19613 t['\uFD98'] = '\u0646\u062C\u0645';
19614 t['\uFD99'] = '\u0646\u062C\u0649';
19615 t['\uFD9A'] = '\u0646\u0645\u064A';
19616 t['\uFD9B'] = '\u0646\u0645\u0649';
19617 t['\uFD9C'] = '\u064A\u0645\u0645';
19618 t['\uFD9D'] = '\u064A\u0645\u0645';
19619 t['\uFD9E'] = '\u0628\u062E\u064A';
19620 t['\uFD9F'] = '\u062A\u062C\u064A';
19621 t['\uFDA0'] = '\u062A\u062C\u0649';
19622 t['\uFDA1'] = '\u062A\u062E\u064A';
19623 t['\uFDA2'] = '\u062A\u062E\u0649';
19624 t['\uFDA3'] = '\u062A\u0645\u064A';
19625 t['\uFDA4'] = '\u062A\u0645\u0649';
19626 t['\uFDA5'] = '\u062C\u0645\u064A';
19627 t['\uFDA6'] = '\u062C\u062D\u0649';
19628 t['\uFDA7'] = '\u062C\u0645\u0649';
19629 t['\uFDA8'] = '\u0633\u062E\u0649';
19630 t['\uFDA9'] = '\u0635\u062D\u064A';
19631 t['\uFDAA'] = '\u0634\u062D\u064A';
19632 t['\uFDAB'] = '\u0636\u062D\u064A';
19633 t['\uFDAC'] = '\u0644\u062C\u064A';
19634 t['\uFDAD'] = '\u0644\u0645\u064A';
19635 t['\uFDAE'] = '\u064A\u062D\u064A';
19636 t['\uFDAF'] = '\u064A\u062C\u064A';
19637 t['\uFDB0'] = '\u064A\u0645\u064A';
19638 t['\uFDB1'] = '\u0645\u0645\u064A';
19639 t['\uFDB2'] = '\u0642\u0645\u064A';
19640 t['\uFDB3'] = '\u0646\u062D\u064A';
19641 t['\uFDB4'] = '\u0642\u0645\u062D';
19642 t['\uFDB5'] = '\u0644\u062D\u0645';
19643 t['\uFDB6'] = '\u0639\u0645\u064A';
19644 t['\uFDB7'] = '\u0643\u0645\u064A';
19645 t['\uFDB8'] = '\u0646\u062C\u062D';
19646 t['\uFDB9'] = '\u0645\u062E\u064A';
19647 t['\uFDBA'] = '\u0644\u062C\u0645';
19648 t['\uFDBB'] = '\u0643\u0645\u0645';
19649 t['\uFDBC'] = '\u0644\u062C\u0645';
19650 t['\uFDBD'] = '\u0646\u062C\u062D';
19651 t['\uFDBE'] = '\u062C\u062D\u064A';
19652 t['\uFDBF'] = '\u062D\u062C\u064A';
19653 t['\uFDC0'] = '\u0645\u062C\u064A';
19654 t['\uFDC1'] = '\u0641\u0645\u064A';
19655 t['\uFDC2'] = '\u0628\u062D\u064A';
19656 t['\uFDC3'] = '\u0643\u0645\u0645';
19657 t['\uFDC4'] = '\u0639\u062C\u0645';
19658 t['\uFDC5'] = '\u0635\u0645\u0645';
19659 t['\uFDC6'] = '\u0633\u062E\u064A';
19660 t['\uFDC7'] = '\u0646\u062C\u064A';
19661 t['\uFE49'] = '\u203E';
19662 t['\uFE4A'] = '\u203E';
19663 t['\uFE4B'] = '\u203E';
19664 t['\uFE4C'] = '\u203E';
19665 t['\uFE4D'] = '\u005F';
19666 t['\uFE4E'] = '\u005F';
19667 t['\uFE4F'] = '\u005F';
19668 t['\uFE80'] = '\u0621';
19669 t['\uFE81'] = '\u0622';
19670 t['\uFE82'] = '\u0622';
19671 t['\uFE83'] = '\u0623';
19672 t['\uFE84'] = '\u0623';
19673 t['\uFE85'] = '\u0624';
19674 t['\uFE86'] = '\u0624';
19675 t['\uFE87'] = '\u0625';
19676 t['\uFE88'] = '\u0625';
19677 t['\uFE89'] = '\u0626';
19678 t['\uFE8A'] = '\u0626';
19679 t['\uFE8B'] = '\u0626';
19680 t['\uFE8C'] = '\u0626';
19681 t['\uFE8D'] = '\u0627';
19682 t['\uFE8E'] = '\u0627';
19683 t['\uFE8F'] = '\u0628';
19684 t['\uFE90'] = '\u0628';
19685 t['\uFE91'] = '\u0628';
19686 t['\uFE92'] = '\u0628';
19687 t['\uFE93'] = '\u0629';
19688 t['\uFE94'] = '\u0629';
19689 t['\uFE95'] = '\u062A';
19690 t['\uFE96'] = '\u062A';
19691 t['\uFE97'] = '\u062A';
19692 t['\uFE98'] = '\u062A';
19693 t['\uFE99'] = '\u062B';
19694 t['\uFE9A'] = '\u062B';
19695 t['\uFE9B'] = '\u062B';
19696 t['\uFE9C'] = '\u062B';
19697 t['\uFE9D'] = '\u062C';
19698 t['\uFE9E'] = '\u062C';
19699 t['\uFE9F'] = '\u062C';
19700 t['\uFEA0'] = '\u062C';
19701 t['\uFEA1'] = '\u062D';
19702 t['\uFEA2'] = '\u062D';
19703 t['\uFEA3'] = '\u062D';
19704 t['\uFEA4'] = '\u062D';
19705 t['\uFEA5'] = '\u062E';
19706 t['\uFEA6'] = '\u062E';
19707 t['\uFEA7'] = '\u062E';
19708 t['\uFEA8'] = '\u062E';
19709 t['\uFEA9'] = '\u062F';
19710 t['\uFEAA'] = '\u062F';
19711 t['\uFEAB'] = '\u0630';
19712 t['\uFEAC'] = '\u0630';
19713 t['\uFEAD'] = '\u0631';
19714 t['\uFEAE'] = '\u0631';
19715 t['\uFEAF'] = '\u0632';
19716 t['\uFEB0'] = '\u0632';
19717 t['\uFEB1'] = '\u0633';
19718 t['\uFEB2'] = '\u0633';
19719 t['\uFEB3'] = '\u0633';
19720 t['\uFEB4'] = '\u0633';
19721 t['\uFEB5'] = '\u0634';
19722 t['\uFEB6'] = '\u0634';
19723 t['\uFEB7'] = '\u0634';
19724 t['\uFEB8'] = '\u0634';
19725 t['\uFEB9'] = '\u0635';
19726 t['\uFEBA'] = '\u0635';
19727 t['\uFEBB'] = '\u0635';
19728 t['\uFEBC'] = '\u0635';
19729 t['\uFEBD'] = '\u0636';
19730 t['\uFEBE'] = '\u0636';
19731 t['\uFEBF'] = '\u0636';
19732 t['\uFEC0'] = '\u0636';
19733 t['\uFEC1'] = '\u0637';
19734 t['\uFEC2'] = '\u0637';
19735 t['\uFEC3'] = '\u0637';
19736 t['\uFEC4'] = '\u0637';
19737 t['\uFEC5'] = '\u0638';
19738 t['\uFEC6'] = '\u0638';
19739 t['\uFEC7'] = '\u0638';
19740 t['\uFEC8'] = '\u0638';
19741 t['\uFEC9'] = '\u0639';
19742 t['\uFECA'] = '\u0639';
19743 t['\uFECB'] = '\u0639';
19744 t['\uFECC'] = '\u0639';
19745 t['\uFECD'] = '\u063A';
19746 t['\uFECE'] = '\u063A';
19747 t['\uFECF'] = '\u063A';
19748 t['\uFED0'] = '\u063A';
19749 t['\uFED1'] = '\u0641';
19750 t['\uFED2'] = '\u0641';
19751 t['\uFED3'] = '\u0641';
19752 t['\uFED4'] = '\u0641';
19753 t['\uFED5'] = '\u0642';
19754 t['\uFED6'] = '\u0642';
19755 t['\uFED7'] = '\u0642';
19756 t['\uFED8'] = '\u0642';
19757 t['\uFED9'] = '\u0643';
19758 t['\uFEDA'] = '\u0643';
19759 t['\uFEDB'] = '\u0643';
19760 t['\uFEDC'] = '\u0643';
19761 t['\uFEDD'] = '\u0644';
19762 t['\uFEDE'] = '\u0644';
19763 t['\uFEDF'] = '\u0644';
19764 t['\uFEE0'] = '\u0644';
19765 t['\uFEE1'] = '\u0645';
19766 t['\uFEE2'] = '\u0645';
19767 t['\uFEE3'] = '\u0645';
19768 t['\uFEE4'] = '\u0645';
19769 t['\uFEE5'] = '\u0646';
19770 t['\uFEE6'] = '\u0646';
19771 t['\uFEE7'] = '\u0646';
19772 t['\uFEE8'] = '\u0646';
19773 t['\uFEE9'] = '\u0647';
19774 t['\uFEEA'] = '\u0647';
19775 t['\uFEEB'] = '\u0647';
19776 t['\uFEEC'] = '\u0647';
19777 t['\uFEED'] = '\u0648';
19778 t['\uFEEE'] = '\u0648';
19779 t['\uFEEF'] = '\u0649';
19780 t['\uFEF0'] = '\u0649';
19781 t['\uFEF1'] = '\u064A';
19782 t['\uFEF2'] = '\u064A';
19783 t['\uFEF3'] = '\u064A';
19784 t['\uFEF4'] = '\u064A';
19785 t['\uFEF5'] = '\u0644\u0622';
19786 t['\uFEF6'] = '\u0644\u0622';
19787 t['\uFEF7'] = '\u0644\u0623';
19788 t['\uFEF8'] = '\u0644\u0623';
19789 t['\uFEF9'] = '\u0644\u0625';
19790 t['\uFEFA'] = '\u0644\u0625';
19791 t['\uFEFB'] = '\u0644\u0627';
19792 t['\uFEFC'] = '\u0644\u0627';
19793 });
19794
19795 function reverseIfRtl(chars) {
19796 var charsLength = chars.length;
19797 //reverse an arabic ligature
19798 if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) {
19799 return chars;
19800 }
19801 var s = '';
19802 for (var ii = charsLength - 1; ii >= 0; ii--) {
19803 s += chars[ii];
19804 }
19805 return s;
19806 }
19807
19808 exports.mapSpecialUnicodeValues = mapSpecialUnicodeValues;
19809 exports.reverseIfRtl = reverseIfRtl;
19810 exports.getUnicodeRangeFor = getUnicodeRangeFor;
19811 exports.getNormalizedUnicodes = getNormalizedUnicodes;
19812 exports.getUnicodeForGlyph = getUnicodeForGlyph;
19813}));
19814
19815
19816(function (root, factory) {
19817 {
19818 factory((root.pdfjsCoreStream = {}), root.pdfjsSharedUtil,
19819 root.pdfjsCorePrimitives, root.pdfjsCoreJbig2, root.pdfjsCoreJpg,
19820 root.pdfjsCoreJpx);
19821 }
19822}(this, function (exports, sharedUtil, corePrimitives, coreJbig2, coreJpg,
19823 coreJpx) {
19824
19825var Util = sharedUtil.Util;
19826var error = sharedUtil.error;
19827var info = sharedUtil.info;
19828var isInt = sharedUtil.isInt;
19829var isArray = sharedUtil.isArray;
19830var createObjectURL = sharedUtil.createObjectURL;
19831var shadow = sharedUtil.shadow;
19832var warn = sharedUtil.warn;
19833var isSpace = sharedUtil.isSpace;
19834var Dict = corePrimitives.Dict;
19835var isDict = corePrimitives.isDict;
19836var Jbig2Image = coreJbig2.Jbig2Image;
19837var JpegImage = coreJpg.JpegImage;
19838var JpxImage = coreJpx.JpxImage;
19839
19840var Stream = (function StreamClosure() {
19841 function Stream(arrayBuffer, start, length, dict) {
19842 this.bytes = (arrayBuffer instanceof Uint8Array ?
19843 arrayBuffer : new Uint8Array(arrayBuffer));
19844 this.start = start || 0;
19845 this.pos = this.start;
19846 this.end = (start + length) || this.bytes.length;
19847 this.dict = dict;
19848 }
19849
19850 // required methods for a stream. if a particular stream does not
19851 // implement these, an error should be thrown
19852 Stream.prototype = {
19853 get length() {
19854 return this.end - this.start;
19855 },
19856 get isEmpty() {
19857 return this.length === 0;
19858 },
19859 getByte: function Stream_getByte() {
19860 if (this.pos >= this.end) {
19861 return -1;
19862 }
19863 return this.bytes[this.pos++];
19864 },
19865 getUint16: function Stream_getUint16() {
19866 var b0 = this.getByte();
19867 var b1 = this.getByte();
19868 if (b0 === -1 || b1 === -1) {
19869 return -1;
19870 }
19871 return (b0 << 8) + b1;
19872 },
19873 getInt32: function Stream_getInt32() {
19874 var b0 = this.getByte();
19875 var b1 = this.getByte();
19876 var b2 = this.getByte();
19877 var b3 = this.getByte();
19878 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
19879 },
19880 // returns subarray of original buffer
19881 // should only be read
19882 getBytes: function Stream_getBytes(length) {
19883 var bytes = this.bytes;
19884 var pos = this.pos;
19885 var strEnd = this.end;
19886
19887 if (!length) {
19888 return bytes.subarray(pos, strEnd);
19889 }
19890 var end = pos + length;
19891 if (end > strEnd) {
19892 end = strEnd;
19893 }
19894 this.pos = end;
19895 return bytes.subarray(pos, end);
19896 },
19897 peekByte: function Stream_peekByte() {
19898 var peekedByte = this.getByte();
19899 this.pos--;
19900 return peekedByte;
19901 },
19902 peekBytes: function Stream_peekBytes(length) {
19903 var bytes = this.getBytes(length);
19904 this.pos -= bytes.length;
19905 return bytes;
19906 },
19907 skip: function Stream_skip(n) {
19908 if (!n) {
19909 n = 1;
19910 }
19911 this.pos += n;
19912 },
19913 reset: function Stream_reset() {
19914 this.pos = this.start;
19915 },
19916 moveStart: function Stream_moveStart() {
19917 this.start = this.pos;
19918 },
19919 makeSubStream: function Stream_makeSubStream(start, length, dict) {
19920 return new Stream(this.bytes.buffer, start, length, dict);
19921 },
19922 isStream: true
19923 };
19924
19925 return Stream;
19926})();
19927
19928var StringStream = (function StringStreamClosure() {
19929 function StringStream(str) {
19930 var length = str.length;
19931 var bytes = new Uint8Array(length);
19932 for (var n = 0; n < length; ++n) {
19933 bytes[n] = str.charCodeAt(n);
19934 }
19935 Stream.call(this, bytes);
19936 }
19937
19938 StringStream.prototype = Stream.prototype;
19939
19940 return StringStream;
19941})();
19942
19943// super class for the decoding streams
19944var DecodeStream = (function DecodeStreamClosure() {
19945 // Lots of DecodeStreams are created whose buffers are never used. For these
19946 // we share a single empty buffer. This is (a) space-efficient and (b) avoids
19947 // having special cases that would be required if we used |null| for an empty
19948 // buffer.
19949 var emptyBuffer = new Uint8Array(0);
19950
19951 function DecodeStream(maybeMinBufferLength) {
19952 this.pos = 0;
19953 this.bufferLength = 0;
19954 this.eof = false;
19955 this.buffer = emptyBuffer;
19956 this.minBufferLength = 512;
19957 if (maybeMinBufferLength) {
19958 // Compute the first power of two that is as big as maybeMinBufferLength.
19959 while (this.minBufferLength < maybeMinBufferLength) {
19960 this.minBufferLength *= 2;
19961 }
19962 }
19963 }
19964
19965 DecodeStream.prototype = {
19966 get isEmpty() {
19967 while (!this.eof && this.bufferLength === 0) {
19968 this.readBlock();
19969 }
19970 return this.bufferLength === 0;
19971 },
19972 ensureBuffer: function DecodeStream_ensureBuffer(requested) {
19973 var buffer = this.buffer;
19974 if (requested <= buffer.byteLength) {
19975 return buffer;
19976 }
19977 var size = this.minBufferLength;
19978 while (size < requested) {
19979 size *= 2;
19980 }
19981 var buffer2 = new Uint8Array(size);
19982 buffer2.set(buffer);
19983 return (this.buffer = buffer2);
19984 },
19985 getByte: function DecodeStream_getByte() {
19986 var pos = this.pos;
19987 while (this.bufferLength <= pos) {
19988 if (this.eof) {
19989 return -1;
19990 }
19991 this.readBlock();
19992 }
19993 return this.buffer[this.pos++];
19994 },
19995 getUint16: function DecodeStream_getUint16() {
19996 var b0 = this.getByte();
19997 var b1 = this.getByte();
19998 if (b0 === -1 || b1 === -1) {
19999 return -1;
20000 }
20001 return (b0 << 8) + b1;
20002 },
20003 getInt32: function DecodeStream_getInt32() {
20004 var b0 = this.getByte();
20005 var b1 = this.getByte();
20006 var b2 = this.getByte();
20007 var b3 = this.getByte();
20008 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
20009 },
20010 getBytes: function DecodeStream_getBytes(length) {
20011 var end, pos = this.pos;
20012
20013 if (length) {
20014 this.ensureBuffer(pos + length);
20015 end = pos + length;
20016
20017 while (!this.eof && this.bufferLength < end) {
20018 this.readBlock();
20019 }
20020 var bufEnd = this.bufferLength;
20021 if (end > bufEnd) {
20022 end = bufEnd;
20023 }
20024 } else {
20025 while (!this.eof) {
20026 this.readBlock();
20027 }
20028 end = this.bufferLength;
20029 }
20030
20031 this.pos = end;
20032 return this.buffer.subarray(pos, end);
20033 },
20034 peekByte: function DecodeStream_peekByte() {
20035 var peekedByte = this.getByte();
20036 this.pos--;
20037 return peekedByte;
20038 },
20039 peekBytes: function DecodeStream_peekBytes(length) {
20040 var bytes = this.getBytes(length);
20041 this.pos -= bytes.length;
20042 return bytes;
20043 },
20044 makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
20045 var end = start + length;
20046 while (this.bufferLength <= end && !this.eof) {
20047 this.readBlock();
20048 }
20049 return new Stream(this.buffer, start, length, dict);
20050 },
20051 skip: function DecodeStream_skip(n) {
20052 if (!n) {
20053 n = 1;
20054 }
20055 this.pos += n;
20056 },
20057 reset: function DecodeStream_reset() {
20058 this.pos = 0;
20059 },
20060 getBaseStreams: function DecodeStream_getBaseStreams() {
20061 if (this.str && this.str.getBaseStreams) {
20062 return this.str.getBaseStreams();
20063 }
20064 return [];
20065 }
20066 };
20067
20068 return DecodeStream;
20069})();
20070
20071var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
20072 function StreamsSequenceStream(streams) {
20073 this.streams = streams;
20074 DecodeStream.call(this, /* maybeLength = */ null);
20075 }
20076
20077 StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
20078
20079 StreamsSequenceStream.prototype.readBlock =
20080 function streamSequenceStreamReadBlock() {
20081
20082 var streams = this.streams;
20083 if (streams.length === 0) {
20084 this.eof = true;
20085 return;
20086 }
20087 var stream = streams.shift();
20088 var chunk = stream.getBytes();
20089 var bufferLength = this.bufferLength;
20090 var newLength = bufferLength + chunk.length;
20091 var buffer = this.ensureBuffer(newLength);
20092 buffer.set(chunk, bufferLength);
20093 this.bufferLength = newLength;
20094 };
20095
20096 StreamsSequenceStream.prototype.getBaseStreams =
20097 function StreamsSequenceStream_getBaseStreams() {
20098
20099 var baseStreams = [];
20100 for (var i = 0, ii = this.streams.length; i < ii; i++) {
20101 var stream = this.streams[i];
20102 if (stream.getBaseStreams) {
20103 Util.appendToArray(baseStreams, stream.getBaseStreams());
20104 }
20105 }
20106 return baseStreams;
20107 };
20108
20109 return StreamsSequenceStream;
20110})();
20111
20112var FlateStream = (function FlateStreamClosure() {
20113 var codeLenCodeMap = new Int32Array([
20114 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
20115 ]);
20116
20117 var lengthDecode = new Int32Array([
20118 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a,
20119 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f,
20120 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073,
20121 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102
20122 ]);
20123
20124 var distDecode = new Int32Array([
20125 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d,
20126 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1,
20127 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01,
20128 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001
20129 ]);
20130
20131 var fixedLitCodeTab = [new Int32Array([
20132 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0,
20133 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0,
20134 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0,
20135 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0,
20136 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8,
20137 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8,
20138 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8,
20139 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8,
20140 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4,
20141 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4,
20142 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4,
20143 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4,
20144 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc,
20145 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec,
20146 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc,
20147 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc,
20148 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2,
20149 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2,
20150 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2,
20151 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2,
20152 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca,
20153 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea,
20154 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da,
20155 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa,
20156 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6,
20157 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6,
20158 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6,
20159 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6,
20160 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce,
20161 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee,
20162 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de,
20163 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe,
20164 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1,
20165 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1,
20166 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1,
20167 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1,
20168 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9,
20169 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9,
20170 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9,
20171 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9,
20172 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5,
20173 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5,
20174 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5,
20175 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5,
20176 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd,
20177 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed,
20178 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd,
20179 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd,
20180 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3,
20181 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3,
20182 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3,
20183 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3,
20184 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb,
20185 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb,
20186 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db,
20187 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb,
20188 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7,
20189 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7,
20190 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7,
20191 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7,
20192 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf,
20193 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef,
20194 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df,
20195 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff
20196 ]), 9];
20197
20198 var fixedDistCodeTab = [new Int32Array([
20199 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c,
20200 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000,
20201 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d,
20202 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
20203 ]), 5];
20204
20205 function FlateStream(str, maybeLength) {
20206 this.str = str;
20207 this.dict = str.dict;
20208
20209 var cmf = str.getByte();
20210 var flg = str.getByte();
20211 if (cmf === -1 || flg === -1) {
20212 error('Invalid header in flate stream: ' + cmf + ', ' + flg);
20213 }
20214 if ((cmf & 0x0f) !== 0x08) {
20215 error('Unknown compression method in flate stream: ' + cmf + ', ' + flg);
20216 }
20217 if ((((cmf << 8) + flg) % 31) !== 0) {
20218 error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg);
20219 }
20220 if (flg & 0x20) {
20221 error('FDICT bit set in flate stream: ' + cmf + ', ' + flg);
20222 }
20223
20224 this.codeSize = 0;
20225 this.codeBuf = 0;
20226
20227 DecodeStream.call(this, maybeLength);
20228 }
20229
20230 FlateStream.prototype = Object.create(DecodeStream.prototype);
20231
20232 FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
20233 var str = this.str;
20234 var codeSize = this.codeSize;
20235 var codeBuf = this.codeBuf;
20236
20237 var b;
20238 while (codeSize < bits) {
20239 if ((b = str.getByte()) === -1) {
20240 error('Bad encoding in flate stream');
20241 }
20242 codeBuf |= b << codeSize;
20243 codeSize += 8;
20244 }
20245 b = codeBuf & ((1 << bits) - 1);
20246 this.codeBuf = codeBuf >> bits;
20247 this.codeSize = codeSize -= bits;
20248
20249 return b;
20250 };
20251
20252 FlateStream.prototype.getCode = function FlateStream_getCode(table) {
20253 var str = this.str;
20254 var codes = table[0];
20255 var maxLen = table[1];
20256 var codeSize = this.codeSize;
20257 var codeBuf = this.codeBuf;
20258
20259 var b;
20260 while (codeSize < maxLen) {
20261 if ((b = str.getByte()) === -1) {
20262 // premature end of stream. code might however still be valid.
20263 // codeSize < codeLen check below guards against incomplete codeVal.
20264 break;
20265 }
20266 codeBuf |= (b << codeSize);
20267 codeSize += 8;
20268 }
20269 var code = codes[codeBuf & ((1 << maxLen) - 1)];
20270 var codeLen = code >> 16;
20271 var codeVal = code & 0xffff;
20272 if (codeLen < 1 || codeSize < codeLen) {
20273 error('Bad encoding in flate stream');
20274 }
20275 this.codeBuf = (codeBuf >> codeLen);
20276 this.codeSize = (codeSize - codeLen);
20277 return codeVal;
20278 };
20279
20280 FlateStream.prototype.generateHuffmanTable =
20281 function flateStreamGenerateHuffmanTable(lengths) {
20282 var n = lengths.length;
20283
20284 // find max code length
20285 var maxLen = 0;
20286 var i;
20287 for (i = 0; i < n; ++i) {
20288 if (lengths[i] > maxLen) {
20289 maxLen = lengths[i];
20290 }
20291 }
20292
20293 // build the table
20294 var size = 1 << maxLen;
20295 var codes = new Int32Array(size);
20296 for (var len = 1, code = 0, skip = 2;
20297 len <= maxLen;
20298 ++len, code <<= 1, skip <<= 1) {
20299 for (var val = 0; val < n; ++val) {
20300 if (lengths[val] === len) {
20301 // bit-reverse the code
20302 var code2 = 0;
20303 var t = code;
20304 for (i = 0; i < len; ++i) {
20305 code2 = (code2 << 1) | (t & 1);
20306 t >>= 1;
20307 }
20308
20309 // fill the table entries
20310 for (i = code2; i < size; i += skip) {
20311 codes[i] = (len << 16) | val;
20312 }
20313 ++code;
20314 }
20315 }
20316 }
20317
20318 return [codes, maxLen];
20319 };
20320
20321 FlateStream.prototype.readBlock = function FlateStream_readBlock() {
20322 var buffer, len;
20323 var str = this.str;
20324 // read block header
20325 var hdr = this.getBits(3);
20326 if (hdr & 1) {
20327 this.eof = true;
20328 }
20329 hdr >>= 1;
20330
20331 if (hdr === 0) { // uncompressed block
20332 var b;
20333
20334 if ((b = str.getByte()) === -1) {
20335 error('Bad block header in flate stream');
20336 }
20337 var blockLen = b;
20338 if ((b = str.getByte()) === -1) {
20339 error('Bad block header in flate stream');
20340 }
20341 blockLen |= (b << 8);
20342 if ((b = str.getByte()) === -1) {
20343 error('Bad block header in flate stream');
20344 }
20345 var check = b;
20346 if ((b = str.getByte()) === -1) {
20347 error('Bad block header in flate stream');
20348 }
20349 check |= (b << 8);
20350 if (check !== (~blockLen & 0xffff) &&
20351 (blockLen !== 0 || check !== 0)) {
20352 // Ignoring error for bad "empty" block (see issue 1277)
20353 error('Bad uncompressed block length in flate stream');
20354 }
20355
20356 this.codeBuf = 0;
20357 this.codeSize = 0;
20358
20359 var bufferLength = this.bufferLength;
20360 buffer = this.ensureBuffer(bufferLength + blockLen);
20361 var end = bufferLength + blockLen;
20362 this.bufferLength = end;
20363 if (blockLen === 0) {
20364 if (str.peekByte() === -1) {
20365 this.eof = true;
20366 }
20367 } else {
20368 for (var n = bufferLength; n < end; ++n) {
20369 if ((b = str.getByte()) === -1) {
20370 this.eof = true;
20371 break;
20372 }
20373 buffer[n] = b;
20374 }
20375 }
20376 return;
20377 }
20378
20379 var litCodeTable;
20380 var distCodeTable;
20381 if (hdr === 1) { // compressed block, fixed codes
20382 litCodeTable = fixedLitCodeTab;
20383 distCodeTable = fixedDistCodeTab;
20384 } else if (hdr === 2) { // compressed block, dynamic codes
20385 var numLitCodes = this.getBits(5) + 257;
20386 var numDistCodes = this.getBits(5) + 1;
20387 var numCodeLenCodes = this.getBits(4) + 4;
20388
20389 // build the code lengths code table
20390 var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);
20391
20392 var i;
20393 for (i = 0; i < numCodeLenCodes; ++i) {
20394 codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3);
20395 }
20396 var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
20397
20398 // build the literal and distance code tables
20399 len = 0;
20400 i = 0;
20401 var codes = numLitCodes + numDistCodes;
20402 var codeLengths = new Uint8Array(codes);
20403 var bitsLength, bitsOffset, what;
20404 while (i < codes) {
20405 var code = this.getCode(codeLenCodeTab);
20406 if (code === 16) {
20407 bitsLength = 2; bitsOffset = 3; what = len;
20408 } else if (code === 17) {
20409 bitsLength = 3; bitsOffset = 3; what = (len = 0);
20410 } else if (code === 18) {
20411 bitsLength = 7; bitsOffset = 11; what = (len = 0);
20412 } else {
20413 codeLengths[i++] = len = code;
20414 continue;
20415 }
20416
20417 var repeatLength = this.getBits(bitsLength) + bitsOffset;
20418 while (repeatLength-- > 0) {
20419 codeLengths[i++] = what;
20420 }
20421 }
20422
20423 litCodeTable =
20424 this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));
20425 distCodeTable =
20426 this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));
20427 } else {
20428 error('Unknown block type in flate stream');
20429 }
20430
20431 buffer = this.buffer;
20432 var limit = buffer ? buffer.length : 0;
20433 var pos = this.bufferLength;
20434 while (true) {
20435 var code1 = this.getCode(litCodeTable);
20436 if (code1 < 256) {
20437 if (pos + 1 >= limit) {
20438 buffer = this.ensureBuffer(pos + 1);
20439 limit = buffer.length;
20440 }
20441 buffer[pos++] = code1;
20442 continue;
20443 }
20444 if (code1 === 256) {
20445 this.bufferLength = pos;
20446 return;
20447 }
20448 code1 -= 257;
20449 code1 = lengthDecode[code1];
20450 var code2 = code1 >> 16;
20451 if (code2 > 0) {
20452 code2 = this.getBits(code2);
20453 }
20454 len = (code1 & 0xffff) + code2;
20455 code1 = this.getCode(distCodeTable);
20456 code1 = distDecode[code1];
20457 code2 = code1 >> 16;
20458 if (code2 > 0) {
20459 code2 = this.getBits(code2);
20460 }
20461 var dist = (code1 & 0xffff) + code2;
20462 if (pos + len >= limit) {
20463 buffer = this.ensureBuffer(pos + len);
20464 limit = buffer.length;
20465 }
20466 for (var k = 0; k < len; ++k, ++pos) {
20467 buffer[pos] = buffer[pos - dist];
20468 }
20469 }
20470 };
20471
20472 return FlateStream;
20473})();
20474
20475var PredictorStream = (function PredictorStreamClosure() {
20476 function PredictorStream(str, maybeLength, params) {
20477 if (!isDict(params)) {
20478 return str; // no prediction
20479 }
20480 var predictor = this.predictor = params.get('Predictor') || 1;
20481
20482 if (predictor <= 1) {
20483 return str; // no prediction
20484 }
20485 if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
20486 error('Unsupported predictor: ' + predictor);
20487 }
20488
20489 if (predictor === 2) {
20490 this.readBlock = this.readBlockTiff;
20491 } else {
20492 this.readBlock = this.readBlockPng;
20493 }
20494
20495 this.str = str;
20496 this.dict = str.dict;
20497
20498 var colors = this.colors = params.get('Colors') || 1;
20499 var bits = this.bits = params.get('BitsPerComponent') || 8;
20500 var columns = this.columns = params.get('Columns') || 1;
20501
20502 this.pixBytes = (colors * bits + 7) >> 3;
20503 this.rowBytes = (columns * colors * bits + 7) >> 3;
20504
20505 DecodeStream.call(this, maybeLength);
20506 return this;
20507 }
20508
20509 PredictorStream.prototype = Object.create(DecodeStream.prototype);
20510
20511 PredictorStream.prototype.readBlockTiff =
20512 function predictorStreamReadBlockTiff() {
20513 var rowBytes = this.rowBytes;
20514
20515 var bufferLength = this.bufferLength;
20516 var buffer = this.ensureBuffer(bufferLength + rowBytes);
20517
20518 var bits = this.bits;
20519 var colors = this.colors;
20520
20521 var rawBytes = this.str.getBytes(rowBytes);
20522 this.eof = !rawBytes.length;
20523 if (this.eof) {
20524 return;
20525 }
20526
20527 var inbuf = 0, outbuf = 0;
20528 var inbits = 0, outbits = 0;
20529 var pos = bufferLength;
20530 var i;
20531
20532 if (bits === 1) {
20533 for (i = 0; i < rowBytes; ++i) {
20534 var c = rawBytes[i];
20535 inbuf = (inbuf << 8) | c;
20536 // bitwise addition is exclusive or
20537 // first shift inbuf and then add
20538 buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF;
20539 // truncate inbuf (assumes colors < 16)
20540 inbuf &= 0xFFFF;
20541 }
20542 } else if (bits === 8) {
20543 for (i = 0; i < colors; ++i) {
20544 buffer[pos++] = rawBytes[i];
20545 }
20546 for (; i < rowBytes; ++i) {
20547 buffer[pos] = buffer[pos - colors] + rawBytes[i];
20548 pos++;
20549 }
20550 } else {
20551 var compArray = new Uint8Array(colors + 1);
20552 var bitMask = (1 << bits) - 1;
20553 var j = 0, k = bufferLength;
20554 var columns = this.columns;
20555 for (i = 0; i < columns; ++i) {
20556 for (var kk = 0; kk < colors; ++kk) {
20557 if (inbits < bits) {
20558 inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF);
20559 inbits += 8;
20560 }
20561 compArray[kk] = (compArray[kk] +
20562 (inbuf >> (inbits - bits))) & bitMask;
20563 inbits -= bits;
20564 outbuf = (outbuf << bits) | compArray[kk];
20565 outbits += bits;
20566 if (outbits >= 8) {
20567 buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF;
20568 outbits -= 8;
20569 }
20570 }
20571 }
20572 if (outbits > 0) {
20573 buffer[k++] = (outbuf << (8 - outbits)) +
20574 (inbuf & ((1 << (8 - outbits)) - 1));
20575 }
20576 }
20577 this.bufferLength += rowBytes;
20578 };
20579
20580 PredictorStream.prototype.readBlockPng =
20581 function predictorStreamReadBlockPng() {
20582
20583 var rowBytes = this.rowBytes;
20584 var pixBytes = this.pixBytes;
20585
20586 var predictor = this.str.getByte();
20587 var rawBytes = this.str.getBytes(rowBytes);
20588 this.eof = !rawBytes.length;
20589 if (this.eof) {
20590 return;
20591 }
20592
20593 var bufferLength = this.bufferLength;
20594 var buffer = this.ensureBuffer(bufferLength + rowBytes);
20595
20596 var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
20597 if (prevRow.length === 0) {
20598 prevRow = new Uint8Array(rowBytes);
20599 }
20600
20601 var i, j = bufferLength, up, c;
20602 switch (predictor) {
20603 case 0:
20604 for (i = 0; i < rowBytes; ++i) {
20605 buffer[j++] = rawBytes[i];
20606 }
20607 break;
20608 case 1:
20609 for (i = 0; i < pixBytes; ++i) {
20610 buffer[j++] = rawBytes[i];
20611 }
20612 for (; i < rowBytes; ++i) {
20613 buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF;
20614 j++;
20615 }
20616 break;
20617 case 2:
20618 for (i = 0; i < rowBytes; ++i) {
20619 buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
20620 }
20621 break;
20622 case 3:
20623 for (i = 0; i < pixBytes; ++i) {
20624 buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
20625 }
20626 for (; i < rowBytes; ++i) {
20627 buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) +
20628 rawBytes[i]) & 0xFF;
20629 j++;
20630 }
20631 break;
20632 case 4:
20633 // we need to save the up left pixels values. the simplest way
20634 // is to create a new buffer
20635 for (i = 0; i < pixBytes; ++i) {
20636 up = prevRow[i];
20637 c = rawBytes[i];
20638 buffer[j++] = up + c;
20639 }
20640 for (; i < rowBytes; ++i) {
20641 up = prevRow[i];
20642 var upLeft = prevRow[i - pixBytes];
20643 var left = buffer[j - pixBytes];
20644 var p = left + up - upLeft;
20645
20646 var pa = p - left;
20647 if (pa < 0) {
20648 pa = -pa;
20649 }
20650 var pb = p - up;
20651 if (pb < 0) {
20652 pb = -pb;
20653 }
20654 var pc = p - upLeft;
20655 if (pc < 0) {
20656 pc = -pc;
20657 }
20658
20659 c = rawBytes[i];
20660 if (pa <= pb && pa <= pc) {
20661 buffer[j++] = left + c;
20662 } else if (pb <= pc) {
20663 buffer[j++] = up + c;
20664 } else {
20665 buffer[j++] = upLeft + c;
20666 }
20667 }
20668 break;
20669 default:
20670 error('Unsupported predictor: ' + predictor);
20671 }
20672 this.bufferLength += rowBytes;
20673 };
20674
20675 return PredictorStream;
20676})();
20677
20678/**
20679 * Depending on the type of JPEG a JpegStream is handled in different ways. For
20680 * JPEG's that are supported natively such as DeviceGray and DeviceRGB the image
20681 * data is stored and then loaded by the browser. For unsupported JPEG's we use
20682 * a library to decode these images and the stream behaves like all the other
20683 * DecodeStreams.
20684 */
20685var JpegStream = (function JpegStreamClosure() {
20686 function JpegStream(stream, maybeLength, dict) {
20687 // Some images may contain 'junk' before the SOI (start-of-image) marker.
20688 // Note: this seems to mainly affect inline images.
20689 var ch;
20690 while ((ch = stream.getByte()) !== -1) {
20691 if (ch === 0xFF) { // Find the first byte of the SOI marker (0xFFD8).
20692 stream.skip(-1); // Reset the stream position to the SOI.
20693 break;
20694 }
20695 }
20696 this.stream = stream;
20697 this.maybeLength = maybeLength;
20698 this.dict = dict;
20699
20700 DecodeStream.call(this, maybeLength);
20701 }
20702
20703 JpegStream.prototype = Object.create(DecodeStream.prototype);
20704
20705 Object.defineProperty(JpegStream.prototype, 'bytes', {
20706 get: function JpegStream_bytes() {
20707 // If this.maybeLength is null, we'll get the entire stream.
20708 return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
20709 },
20710 configurable: true
20711 });
20712
20713 JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) {
20714 if (this.bufferLength) {
20715 return;
20716 }
20717 var jpegImage = new JpegImage();
20718
20719 // Checking if values need to be transformed before conversion.
20720 var decodeArr = this.dict.getArray('Decode', 'D');
20721 if (this.forceRGB && isArray(decodeArr)) {
20722 var bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
20723 var decodeArrLength = decodeArr.length;
20724 var transform = new Int32Array(decodeArrLength);
20725 var transformNeeded = false;
20726 var maxValue = (1 << bitsPerComponent) - 1;
20727 for (var i = 0; i < decodeArrLength; i += 2) {
20728 transform[i] = ((decodeArr[i + 1] - decodeArr[i]) * 256) | 0;
20729 transform[i + 1] = (decodeArr[i] * maxValue) | 0;
20730 if (transform[i] !== 256 || transform[i + 1] !== 0) {
20731 transformNeeded = true;
20732 }
20733 }
20734 if (transformNeeded) {
20735 jpegImage.decodeTransform = transform;
20736 }
20737 }
20738 // Fetching the 'ColorTransform' entry, if it exists.
20739 var decodeParams = this.dict.get('DecodeParms', 'DP');
20740 if (isDict(decodeParams)) {
20741 var colorTransform = decodeParams.get('ColorTransform');
20742 if (isInt(colorTransform)) {
20743 jpegImage.colorTransform = colorTransform;
20744 }
20745 }
20746
20747 jpegImage.parse(this.bytes);
20748 var data = jpegImage.getData(this.drawWidth, this.drawHeight,
20749 this.forceRGB);
20750 this.buffer = data;
20751 this.bufferLength = data.length;
20752 this.eof = true;
20753 };
20754
20755 JpegStream.prototype.getBytes = function JpegStream_getBytes(length) {
20756 this.ensureBuffer();
20757 return this.buffer;
20758 };
20759
20760 JpegStream.prototype.getIR = function JpegStream_getIR(forceDataSchema) {
20761 return createObjectURL(this.bytes, 'image/jpeg', forceDataSchema);
20762 };
20763
20764 return JpegStream;
20765})();
20766
20767/**
20768 * For JPEG 2000's we use a library to decode these images and
20769 * the stream behaves like all the other DecodeStreams.
20770 */
20771var JpxStream = (function JpxStreamClosure() {
20772 function JpxStream(stream, maybeLength, dict) {
20773 this.stream = stream;
20774 this.maybeLength = maybeLength;
20775 this.dict = dict;
20776
20777 DecodeStream.call(this, maybeLength);
20778 }
20779
20780 JpxStream.prototype = Object.create(DecodeStream.prototype);
20781
20782 Object.defineProperty(JpxStream.prototype, 'bytes', {
20783 get: function JpxStream_bytes() {
20784 // If this.maybeLength is null, we'll get the entire stream.
20785 return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
20786 },
20787 configurable: true
20788 });
20789
20790 JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) {
20791 if (this.bufferLength) {
20792 return;
20793 }
20794
20795 var jpxImage = new JpxImage();
20796 jpxImage.parse(this.bytes);
20797
20798 var width = jpxImage.width;
20799 var height = jpxImage.height;
20800 var componentsCount = jpxImage.componentsCount;
20801 var tileCount = jpxImage.tiles.length;
20802 if (tileCount === 1) {
20803 this.buffer = jpxImage.tiles[0].items;
20804 } else {
20805 var data = new Uint8Array(width * height * componentsCount);
20806
20807 for (var k = 0; k < tileCount; k++) {
20808 var tileComponents = jpxImage.tiles[k];
20809 var tileWidth = tileComponents.width;
20810 var tileHeight = tileComponents.height;
20811 var tileLeft = tileComponents.left;
20812 var tileTop = tileComponents.top;
20813
20814 var src = tileComponents.items;
20815 var srcPosition = 0;
20816 var dataPosition = (width * tileTop + tileLeft) * componentsCount;
20817 var imgRowSize = width * componentsCount;
20818 var tileRowSize = tileWidth * componentsCount;
20819
20820 for (var j = 0; j < tileHeight; j++) {
20821 var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize);
20822 data.set(rowBytes, dataPosition);
20823 srcPosition += tileRowSize;
20824 dataPosition += imgRowSize;
20825 }
20826 }
20827 this.buffer = data;
20828 }
20829 this.bufferLength = this.buffer.length;
20830 this.eof = true;
20831 };
20832
20833 return JpxStream;
20834})();
20835
20836/**
20837 * For JBIG2's we use a library to decode these images and
20838 * the stream behaves like all the other DecodeStreams.
20839 */
20840var Jbig2Stream = (function Jbig2StreamClosure() {
20841 function Jbig2Stream(stream, maybeLength, dict) {
20842 this.stream = stream;
20843 this.maybeLength = maybeLength;
20844 this.dict = dict;
20845
20846 DecodeStream.call(this, maybeLength);
20847 }
20848
20849 Jbig2Stream.prototype = Object.create(DecodeStream.prototype);
20850
20851 Object.defineProperty(Jbig2Stream.prototype, 'bytes', {
20852 get: function Jbig2Stream_bytes() {
20853 // If this.maybeLength is null, we'll get the entire stream.
20854 return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
20855 },
20856 configurable: true
20857 });
20858
20859 Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) {
20860 if (this.bufferLength) {
20861 return;
20862 }
20863
20864 var jbig2Image = new Jbig2Image();
20865
20866 var chunks = [];
20867 var decodeParams = this.dict.getArray('DecodeParms', 'DP');
20868
20869 // According to the PDF specification, DecodeParms can be either
20870 // a dictionary, or an array whose elements are dictionaries.
20871 if (isArray(decodeParams)) {
20872 if (decodeParams.length > 1) {
20873 warn('JBIG2 - \'DecodeParms\' array with multiple elements ' +
20874 'not supported.');
20875 }
20876 decodeParams = decodeParams[0];
20877 }
20878 if (decodeParams && decodeParams.has('JBIG2Globals')) {
20879 var globalsStream = decodeParams.get('JBIG2Globals');
20880 var globals = globalsStream.getBytes();
20881 chunks.push({data: globals, start: 0, end: globals.length});
20882 }
20883 chunks.push({data: this.bytes, start: 0, end: this.bytes.length});
20884 var data = jbig2Image.parseChunks(chunks);
20885 var dataLength = data.length;
20886
20887 // JBIG2 had black as 1 and white as 0, inverting the colors
20888 for (var i = 0; i < dataLength; i++) {
20889 data[i] ^= 0xFF;
20890 }
20891
20892 this.buffer = data;
20893 this.bufferLength = dataLength;
20894 this.eof = true;
20895 };
20896
20897 return Jbig2Stream;
20898})();
20899
20900var DecryptStream = (function DecryptStreamClosure() {
20901 function DecryptStream(str, maybeLength, decrypt) {
20902 this.str = str;
20903 this.dict = str.dict;
20904 this.decrypt = decrypt;
20905 this.nextChunk = null;
20906 this.initialized = false;
20907
20908 DecodeStream.call(this, maybeLength);
20909 }
20910
20911 var chunkSize = 512;
20912
20913 DecryptStream.prototype = Object.create(DecodeStream.prototype);
20914
20915 DecryptStream.prototype.readBlock = function DecryptStream_readBlock() {
20916 var chunk;
20917 if (this.initialized) {
20918 chunk = this.nextChunk;
20919 } else {
20920 chunk = this.str.getBytes(chunkSize);
20921 this.initialized = true;
20922 }
20923 if (!chunk || chunk.length === 0) {
20924 this.eof = true;
20925 return;
20926 }
20927 this.nextChunk = this.str.getBytes(chunkSize);
20928 var hasMoreData = this.nextChunk && this.nextChunk.length > 0;
20929
20930 var decrypt = this.decrypt;
20931 chunk = decrypt(chunk, !hasMoreData);
20932
20933 var bufferLength = this.bufferLength;
20934 var i, n = chunk.length;
20935 var buffer = this.ensureBuffer(bufferLength + n);
20936 for (i = 0; i < n; i++) {
20937 buffer[bufferLength++] = chunk[i];
20938 }
20939 this.bufferLength = bufferLength;
20940 };
20941
20942 return DecryptStream;
20943})();
20944
20945var Ascii85Stream = (function Ascii85StreamClosure() {
20946 function Ascii85Stream(str, maybeLength) {
20947 this.str = str;
20948 this.dict = str.dict;
20949 this.input = new Uint8Array(5);
20950
20951 // Most streams increase in size when decoded, but Ascii85 streams
20952 // typically shrink by ~20%.
20953 if (maybeLength) {
20954 maybeLength = 0.8 * maybeLength;
20955 }
20956 DecodeStream.call(this, maybeLength);
20957 }
20958
20959 Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
20960
20961 Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
20962 var TILDA_CHAR = 0x7E; // '~'
20963 var Z_LOWER_CHAR = 0x7A; // 'z'
20964 var EOF = -1;
20965
20966 var str = this.str;
20967
20968 var c = str.getByte();
20969 while (isSpace(c)) {
20970 c = str.getByte();
20971 }
20972
20973 if (c === EOF || c === TILDA_CHAR) {
20974 this.eof = true;
20975 return;
20976 }
20977
20978 var bufferLength = this.bufferLength, buffer;
20979 var i;
20980
20981 // special code for z
20982 if (c === Z_LOWER_CHAR) {
20983 buffer = this.ensureBuffer(bufferLength + 4);
20984 for (i = 0; i < 4; ++i) {
20985 buffer[bufferLength + i] = 0;
20986 }
20987 this.bufferLength += 4;
20988 } else {
20989 var input = this.input;
20990 input[0] = c;
20991 for (i = 1; i < 5; ++i) {
20992 c = str.getByte();
20993 while (isSpace(c)) {
20994 c = str.getByte();
20995 }
20996
20997 input[i] = c;
20998
20999 if (c === EOF || c === TILDA_CHAR) {
21000 break;
21001 }
21002 }
21003 buffer = this.ensureBuffer(bufferLength + i - 1);
21004 this.bufferLength += i - 1;
21005
21006 // partial ending;
21007 if (i < 5) {
21008 for (; i < 5; ++i) {
21009 input[i] = 0x21 + 84;
21010 }
21011 this.eof = true;
21012 }
21013 var t = 0;
21014 for (i = 0; i < 5; ++i) {
21015 t = t * 85 + (input[i] - 0x21);
21016 }
21017
21018 for (i = 3; i >= 0; --i) {
21019 buffer[bufferLength + i] = t & 0xFF;
21020 t >>= 8;
21021 }
21022 }
21023 };
21024
21025 return Ascii85Stream;
21026})();
21027
21028var AsciiHexStream = (function AsciiHexStreamClosure() {
21029 function AsciiHexStream(str, maybeLength) {
21030 this.str = str;
21031 this.dict = str.dict;
21032
21033 this.firstDigit = -1;
21034
21035 // Most streams increase in size when decoded, but AsciiHex streams shrink
21036 // by 50%.
21037 if (maybeLength) {
21038 maybeLength = 0.5 * maybeLength;
21039 }
21040 DecodeStream.call(this, maybeLength);
21041 }
21042
21043 AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
21044
21045 AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() {
21046 var UPSTREAM_BLOCK_SIZE = 8000;
21047 var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE);
21048 if (!bytes.length) {
21049 this.eof = true;
21050 return;
21051 }
21052
21053 var maxDecodeLength = (bytes.length + 1) >> 1;
21054 var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength);
21055 var bufferLength = this.bufferLength;
21056
21057 var firstDigit = this.firstDigit;
21058 for (var i = 0, ii = bytes.length; i < ii; i++) {
21059 var ch = bytes[i], digit;
21060 if (ch >= 0x30 && ch <= 0x39) { // '0'-'9'
21061 digit = ch & 0x0F;
21062 } else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) {
21063 // 'A'-'Z', 'a'-'z'
21064 digit = (ch & 0x0F) + 9;
21065 } else if (ch === 0x3E) { // '>'
21066 this.eof = true;
21067 break;
21068 } else { // probably whitespace
21069 continue; // ignoring
21070 }
21071 if (firstDigit < 0) {
21072 firstDigit = digit;
21073 } else {
21074 buffer[bufferLength++] = (firstDigit << 4) | digit;
21075 firstDigit = -1;
21076 }
21077 }
21078 if (firstDigit >= 0 && this.eof) {
21079 // incomplete byte
21080 buffer[bufferLength++] = (firstDigit << 4);
21081 firstDigit = -1;
21082 }
21083 this.firstDigit = firstDigit;
21084 this.bufferLength = bufferLength;
21085 };
21086
21087 return AsciiHexStream;
21088})();
21089
21090var RunLengthStream = (function RunLengthStreamClosure() {
21091 function RunLengthStream(str, maybeLength) {
21092 this.str = str;
21093 this.dict = str.dict;
21094
21095 DecodeStream.call(this, maybeLength);
21096 }
21097
21098 RunLengthStream.prototype = Object.create(DecodeStream.prototype);
21099
21100 RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() {
21101 // The repeatHeader has following format. The first byte defines type of run
21102 // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes
21103 // (in addition to the second byte from the header), n = 129 through 255 -
21104 // duplicate the second byte from the header (257 - n) times, n = 128 - end.
21105 var repeatHeader = this.str.getBytes(2);
21106 if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) {
21107 this.eof = true;
21108 return;
21109 }
21110
21111 var buffer;
21112 var bufferLength = this.bufferLength;
21113 var n = repeatHeader[0];
21114 if (n < 128) {
21115 // copy n bytes
21116 buffer = this.ensureBuffer(bufferLength + n + 1);
21117 buffer[bufferLength++] = repeatHeader[1];
21118 if (n > 0) {
21119 var source = this.str.getBytes(n);
21120 buffer.set(source, bufferLength);
21121 bufferLength += n;
21122 }
21123 } else {
21124 n = 257 - n;
21125 var b = repeatHeader[1];
21126 buffer = this.ensureBuffer(bufferLength + n + 1);
21127 for (var i = 0; i < n; i++) {
21128 buffer[bufferLength++] = b;
21129 }
21130 }
21131 this.bufferLength = bufferLength;
21132 };
21133
21134 return RunLengthStream;
21135})();
21136
21137var CCITTFaxStream = (function CCITTFaxStreamClosure() {
21138
21139 var ccittEOL = -2;
21140 var ccittEOF = -1;
21141 var twoDimPass = 0;
21142 var twoDimHoriz = 1;
21143 var twoDimVert0 = 2;
21144 var twoDimVertR1 = 3;
21145 var twoDimVertL1 = 4;
21146 var twoDimVertR2 = 5;
21147 var twoDimVertL2 = 6;
21148 var twoDimVertR3 = 7;
21149 var twoDimVertL3 = 8;
21150
21151 var twoDimTable = [
21152 [-1, -1], [-1, -1], // 000000x
21153 [7, twoDimVertL3], // 0000010
21154 [7, twoDimVertR3], // 0000011
21155 [6, twoDimVertL2], [6, twoDimVertL2], // 000010x
21156 [6, twoDimVertR2], [6, twoDimVertR2], // 000011x
21157 [4, twoDimPass], [4, twoDimPass], // 0001xxx
21158 [4, twoDimPass], [4, twoDimPass],
21159 [4, twoDimPass], [4, twoDimPass],
21160 [4, twoDimPass], [4, twoDimPass],
21161 [3, twoDimHoriz], [3, twoDimHoriz], // 001xxxx
21162 [3, twoDimHoriz], [3, twoDimHoriz],
21163 [3, twoDimHoriz], [3, twoDimHoriz],
21164 [3, twoDimHoriz], [3, twoDimHoriz],
21165 [3, twoDimHoriz], [3, twoDimHoriz],
21166 [3, twoDimHoriz], [3, twoDimHoriz],
21167 [3, twoDimHoriz], [3, twoDimHoriz],
21168 [3, twoDimHoriz], [3, twoDimHoriz],
21169 [3, twoDimVertL1], [3, twoDimVertL1], // 010xxxx
21170 [3, twoDimVertL1], [3, twoDimVertL1],
21171 [3, twoDimVertL1], [3, twoDimVertL1],
21172 [3, twoDimVertL1], [3, twoDimVertL1],
21173 [3, twoDimVertL1], [3, twoDimVertL1],
21174 [3, twoDimVertL1], [3, twoDimVertL1],
21175 [3, twoDimVertL1], [3, twoDimVertL1],
21176 [3, twoDimVertL1], [3, twoDimVertL1],
21177 [3, twoDimVertR1], [3, twoDimVertR1], // 011xxxx
21178 [3, twoDimVertR1], [3, twoDimVertR1],
21179 [3, twoDimVertR1], [3, twoDimVertR1],
21180 [3, twoDimVertR1], [3, twoDimVertR1],
21181 [3, twoDimVertR1], [3, twoDimVertR1],
21182 [3, twoDimVertR1], [3, twoDimVertR1],
21183 [3, twoDimVertR1], [3, twoDimVertR1],
21184 [3, twoDimVertR1], [3, twoDimVertR1],
21185 [1, twoDimVert0], [1, twoDimVert0], // 1xxxxxx
21186 [1, twoDimVert0], [1, twoDimVert0],
21187 [1, twoDimVert0], [1, twoDimVert0],
21188 [1, twoDimVert0], [1, twoDimVert0],
21189 [1, twoDimVert0], [1, twoDimVert0],
21190 [1, twoDimVert0], [1, twoDimVert0],
21191 [1, twoDimVert0], [1, twoDimVert0],
21192 [1, twoDimVert0], [1, twoDimVert0],
21193 [1, twoDimVert0], [1, twoDimVert0],
21194 [1, twoDimVert0], [1, twoDimVert0],
21195 [1, twoDimVert0], [1, twoDimVert0],
21196 [1, twoDimVert0], [1, twoDimVert0],
21197 [1, twoDimVert0], [1, twoDimVert0],
21198 [1, twoDimVert0], [1, twoDimVert0],
21199 [1, twoDimVert0], [1, twoDimVert0],
21200 [1, twoDimVert0], [1, twoDimVert0],
21201 [1, twoDimVert0], [1, twoDimVert0],
21202 [1, twoDimVert0], [1, twoDimVert0],
21203 [1, twoDimVert0], [1, twoDimVert0],
21204 [1, twoDimVert0], [1, twoDimVert0],
21205 [1, twoDimVert0], [1, twoDimVert0],
21206 [1, twoDimVert0], [1, twoDimVert0],
21207 [1, twoDimVert0], [1, twoDimVert0],
21208 [1, twoDimVert0], [1, twoDimVert0],
21209 [1, twoDimVert0], [1, twoDimVert0],
21210 [1, twoDimVert0], [1, twoDimVert0],
21211 [1, twoDimVert0], [1, twoDimVert0],
21212 [1, twoDimVert0], [1, twoDimVert0],
21213 [1, twoDimVert0], [1, twoDimVert0],
21214 [1, twoDimVert0], [1, twoDimVert0],
21215 [1, twoDimVert0], [1, twoDimVert0],
21216 [1, twoDimVert0], [1, twoDimVert0]
21217 ];
21218
21219 var whiteTable1 = [
21220 [-1, -1], // 00000
21221 [12, ccittEOL], // 00001
21222 [-1, -1], [-1, -1], // 0001x
21223 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 001xx
21224 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 010xx
21225 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 011xx
21226 [11, 1792], [11, 1792], // 1000x
21227 [12, 1984], // 10010
21228 [12, 2048], // 10011
21229 [12, 2112], // 10100
21230 [12, 2176], // 10101
21231 [12, 2240], // 10110
21232 [12, 2304], // 10111
21233 [11, 1856], [11, 1856], // 1100x
21234 [11, 1920], [11, 1920], // 1101x
21235 [12, 2368], // 11100
21236 [12, 2432], // 11101
21237 [12, 2496], // 11110
21238 [12, 2560] // 11111
21239 ];
21240
21241 var whiteTable2 = [
21242 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000000xx
21243 [8, 29], [8, 29], // 00000010x
21244 [8, 30], [8, 30], // 00000011x
21245 [8, 45], [8, 45], // 00000100x
21246 [8, 46], [8, 46], // 00000101x
21247 [7, 22], [7, 22], [7, 22], [7, 22], // 0000011xx
21248 [7, 23], [7, 23], [7, 23], [7, 23], // 0000100xx
21249 [8, 47], [8, 47], // 00001010x
21250 [8, 48], [8, 48], // 00001011x
21251 [6, 13], [6, 13], [6, 13], [6, 13], // 000011xxx
21252 [6, 13], [6, 13], [6, 13], [6, 13],
21253 [7, 20], [7, 20], [7, 20], [7, 20], // 0001000xx
21254 [8, 33], [8, 33], // 00010010x
21255 [8, 34], [8, 34], // 00010011x
21256 [8, 35], [8, 35], // 00010100x
21257 [8, 36], [8, 36], // 00010101x
21258 [8, 37], [8, 37], // 00010110x
21259 [8, 38], [8, 38], // 00010111x
21260 [7, 19], [7, 19], [7, 19], [7, 19], // 0001100xx
21261 [8, 31], [8, 31], // 00011010x
21262 [8, 32], [8, 32], // 00011011x
21263 [6, 1], [6, 1], [6, 1], [6, 1], // 000111xxx
21264 [6, 1], [6, 1], [6, 1], [6, 1],
21265 [6, 12], [6, 12], [6, 12], [6, 12], // 001000xxx
21266 [6, 12], [6, 12], [6, 12], [6, 12],
21267 [8, 53], [8, 53], // 00100100x
21268 [8, 54], [8, 54], // 00100101x
21269 [7, 26], [7, 26], [7, 26], [7, 26], // 0010011xx
21270 [8, 39], [8, 39], // 00101000x
21271 [8, 40], [8, 40], // 00101001x
21272 [8, 41], [8, 41], // 00101010x
21273 [8, 42], [8, 42], // 00101011x
21274 [8, 43], [8, 43], // 00101100x
21275 [8, 44], [8, 44], // 00101101x
21276 [7, 21], [7, 21], [7, 21], [7, 21], // 0010111xx
21277 [7, 28], [7, 28], [7, 28], [7, 28], // 0011000xx
21278 [8, 61], [8, 61], // 00110010x
21279 [8, 62], [8, 62], // 00110011x
21280 [8, 63], [8, 63], // 00110100x
21281 [8, 0], [8, 0], // 00110101x
21282 [8, 320], [8, 320], // 00110110x
21283 [8, 384], [8, 384], // 00110111x
21284 [5, 10], [5, 10], [5, 10], [5, 10], // 00111xxxx
21285 [5, 10], [5, 10], [5, 10], [5, 10],
21286 [5, 10], [5, 10], [5, 10], [5, 10],
21287 [5, 10], [5, 10], [5, 10], [5, 10],
21288 [5, 11], [5, 11], [5, 11], [5, 11], // 01000xxxx
21289 [5, 11], [5, 11], [5, 11], [5, 11],
21290 [5, 11], [5, 11], [5, 11], [5, 11],
21291 [5, 11], [5, 11], [5, 11], [5, 11],
21292 [7, 27], [7, 27], [7, 27], [7, 27], // 0100100xx
21293 [8, 59], [8, 59], // 01001010x
21294 [8, 60], [8, 60], // 01001011x
21295 [9, 1472], // 010011000
21296 [9, 1536], // 010011001
21297 [9, 1600], // 010011010
21298 [9, 1728], // 010011011
21299 [7, 18], [7, 18], [7, 18], [7, 18], // 0100111xx
21300 [7, 24], [7, 24], [7, 24], [7, 24], // 0101000xx
21301 [8, 49], [8, 49], // 01010010x
21302 [8, 50], [8, 50], // 01010011x
21303 [8, 51], [8, 51], // 01010100x
21304 [8, 52], [8, 52], // 01010101x
21305 [7, 25], [7, 25], [7, 25], [7, 25], // 0101011xx
21306 [8, 55], [8, 55], // 01011000x
21307 [8, 56], [8, 56], // 01011001x
21308 [8, 57], [8, 57], // 01011010x
21309 [8, 58], [8, 58], // 01011011x
21310 [6, 192], [6, 192], [6, 192], [6, 192], // 010111xxx
21311 [6, 192], [6, 192], [6, 192], [6, 192],
21312 [6, 1664], [6, 1664], [6, 1664], [6, 1664], // 011000xxx
21313 [6, 1664], [6, 1664], [6, 1664], [6, 1664],
21314 [8, 448], [8, 448], // 01100100x
21315 [8, 512], [8, 512], // 01100101x
21316 [9, 704], // 011001100
21317 [9, 768], // 011001101
21318 [8, 640], [8, 640], // 01100111x
21319 [8, 576], [8, 576], // 01101000x
21320 [9, 832], // 011010010
21321 [9, 896], // 011010011
21322 [9, 960], // 011010100
21323 [9, 1024], // 011010101
21324 [9, 1088], // 011010110
21325 [9, 1152], // 011010111
21326 [9, 1216], // 011011000
21327 [9, 1280], // 011011001
21328 [9, 1344], // 011011010
21329 [9, 1408], // 011011011
21330 [7, 256], [7, 256], [7, 256], [7, 256], // 0110111xx
21331 [4, 2], [4, 2], [4, 2], [4, 2], // 0111xxxxx
21332 [4, 2], [4, 2], [4, 2], [4, 2],
21333 [4, 2], [4, 2], [4, 2], [4, 2],
21334 [4, 2], [4, 2], [4, 2], [4, 2],
21335 [4, 2], [4, 2], [4, 2], [4, 2],
21336 [4, 2], [4, 2], [4, 2], [4, 2],
21337 [4, 2], [4, 2], [4, 2], [4, 2],
21338 [4, 2], [4, 2], [4, 2], [4, 2],
21339 [4, 3], [4, 3], [4, 3], [4, 3], // 1000xxxxx
21340 [4, 3], [4, 3], [4, 3], [4, 3],
21341 [4, 3], [4, 3], [4, 3], [4, 3],
21342 [4, 3], [4, 3], [4, 3], [4, 3],
21343 [4, 3], [4, 3], [4, 3], [4, 3],
21344 [4, 3], [4, 3], [4, 3], [4, 3],
21345 [4, 3], [4, 3], [4, 3], [4, 3],
21346 [4, 3], [4, 3], [4, 3], [4, 3],
21347 [5, 128], [5, 128], [5, 128], [5, 128], // 10010xxxx
21348 [5, 128], [5, 128], [5, 128], [5, 128],
21349 [5, 128], [5, 128], [5, 128], [5, 128],
21350 [5, 128], [5, 128], [5, 128], [5, 128],
21351 [5, 8], [5, 8], [5, 8], [5, 8], // 10011xxxx
21352 [5, 8], [5, 8], [5, 8], [5, 8],
21353 [5, 8], [5, 8], [5, 8], [5, 8],
21354 [5, 8], [5, 8], [5, 8], [5, 8],
21355 [5, 9], [5, 9], [5, 9], [5, 9], // 10100xxxx
21356 [5, 9], [5, 9], [5, 9], [5, 9],
21357 [5, 9], [5, 9], [5, 9], [5, 9],
21358 [5, 9], [5, 9], [5, 9], [5, 9],
21359 [6, 16], [6, 16], [6, 16], [6, 16], // 101010xxx
21360 [6, 16], [6, 16], [6, 16], [6, 16],
21361 [6, 17], [6, 17], [6, 17], [6, 17], // 101011xxx
21362 [6, 17], [6, 17], [6, 17], [6, 17],
21363 [4, 4], [4, 4], [4, 4], [4, 4], // 1011xxxxx
21364 [4, 4], [4, 4], [4, 4], [4, 4],
21365 [4, 4], [4, 4], [4, 4], [4, 4],
21366 [4, 4], [4, 4], [4, 4], [4, 4],
21367 [4, 4], [4, 4], [4, 4], [4, 4],
21368 [4, 4], [4, 4], [4, 4], [4, 4],
21369 [4, 4], [4, 4], [4, 4], [4, 4],
21370 [4, 4], [4, 4], [4, 4], [4, 4],
21371 [4, 5], [4, 5], [4, 5], [4, 5], // 1100xxxxx
21372 [4, 5], [4, 5], [4, 5], [4, 5],
21373 [4, 5], [4, 5], [4, 5], [4, 5],
21374 [4, 5], [4, 5], [4, 5], [4, 5],
21375 [4, 5], [4, 5], [4, 5], [4, 5],
21376 [4, 5], [4, 5], [4, 5], [4, 5],
21377 [4, 5], [4, 5], [4, 5], [4, 5],
21378 [4, 5], [4, 5], [4, 5], [4, 5],
21379 [6, 14], [6, 14], [6, 14], [6, 14], // 110100xxx
21380 [6, 14], [6, 14], [6, 14], [6, 14],
21381 [6, 15], [6, 15], [6, 15], [6, 15], // 110101xxx
21382 [6, 15], [6, 15], [6, 15], [6, 15],
21383 [5, 64], [5, 64], [5, 64], [5, 64], // 11011xxxx
21384 [5, 64], [5, 64], [5, 64], [5, 64],
21385 [5, 64], [5, 64], [5, 64], [5, 64],
21386 [5, 64], [5, 64], [5, 64], [5, 64],
21387 [4, 6], [4, 6], [4, 6], [4, 6], // 1110xxxxx
21388 [4, 6], [4, 6], [4, 6], [4, 6],
21389 [4, 6], [4, 6], [4, 6], [4, 6],
21390 [4, 6], [4, 6], [4, 6], [4, 6],
21391 [4, 6], [4, 6], [4, 6], [4, 6],
21392 [4, 6], [4, 6], [4, 6], [4, 6],
21393 [4, 6], [4, 6], [4, 6], [4, 6],
21394 [4, 6], [4, 6], [4, 6], [4, 6],
21395 [4, 7], [4, 7], [4, 7], [4, 7], // 1111xxxxx
21396 [4, 7], [4, 7], [4, 7], [4, 7],
21397 [4, 7], [4, 7], [4, 7], [4, 7],
21398 [4, 7], [4, 7], [4, 7], [4, 7],
21399 [4, 7], [4, 7], [4, 7], [4, 7],
21400 [4, 7], [4, 7], [4, 7], [4, 7],
21401 [4, 7], [4, 7], [4, 7], [4, 7],
21402 [4, 7], [4, 7], [4, 7], [4, 7]
21403 ];
21404
21405 var blackTable1 = [
21406 [-1, -1], [-1, -1], // 000000000000x
21407 [12, ccittEOL], [12, ccittEOL], // 000000000001x
21408 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000001xx
21409 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000010xx
21410 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000011xx
21411 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000100xx
21412 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000101xx
21413 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000110xx
21414 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000111xx
21415 [11, 1792], [11, 1792], [11, 1792], [11, 1792], // 00000001000xx
21416 [12, 1984], [12, 1984], // 000000010010x
21417 [12, 2048], [12, 2048], // 000000010011x
21418 [12, 2112], [12, 2112], // 000000010100x
21419 [12, 2176], [12, 2176], // 000000010101x
21420 [12, 2240], [12, 2240], // 000000010110x
21421 [12, 2304], [12, 2304], // 000000010111x
21422 [11, 1856], [11, 1856], [11, 1856], [11, 1856], // 00000001100xx
21423 [11, 1920], [11, 1920], [11, 1920], [11, 1920], // 00000001101xx
21424 [12, 2368], [12, 2368], // 000000011100x
21425 [12, 2432], [12, 2432], // 000000011101x
21426 [12, 2496], [12, 2496], // 000000011110x
21427 [12, 2560], [12, 2560], // 000000011111x
21428 [10, 18], [10, 18], [10, 18], [10, 18], // 0000001000xxx
21429 [10, 18], [10, 18], [10, 18], [10, 18],
21430 [12, 52], [12, 52], // 000000100100x
21431 [13, 640], // 0000001001010
21432 [13, 704], // 0000001001011
21433 [13, 768], // 0000001001100
21434 [13, 832], // 0000001001101
21435 [12, 55], [12, 55], // 000000100111x
21436 [12, 56], [12, 56], // 000000101000x
21437 [13, 1280], // 0000001010010
21438 [13, 1344], // 0000001010011
21439 [13, 1408], // 0000001010100
21440 [13, 1472], // 0000001010101
21441 [12, 59], [12, 59], // 000000101011x
21442 [12, 60], [12, 60], // 000000101100x
21443 [13, 1536], // 0000001011010
21444 [13, 1600], // 0000001011011
21445 [11, 24], [11, 24], [11, 24], [11, 24], // 00000010111xx
21446 [11, 25], [11, 25], [11, 25], [11, 25], // 00000011000xx
21447 [13, 1664], // 0000001100100
21448 [13, 1728], // 0000001100101
21449 [12, 320], [12, 320], // 000000110011x
21450 [12, 384], [12, 384], // 000000110100x
21451 [12, 448], [12, 448], // 000000110101x
21452 [13, 512], // 0000001101100
21453 [13, 576], // 0000001101101
21454 [12, 53], [12, 53], // 000000110111x
21455 [12, 54], [12, 54], // 000000111000x
21456 [13, 896], // 0000001110010
21457 [13, 960], // 0000001110011
21458 [13, 1024], // 0000001110100
21459 [13, 1088], // 0000001110101
21460 [13, 1152], // 0000001110110
21461 [13, 1216], // 0000001110111
21462 [10, 64], [10, 64], [10, 64], [10, 64], // 0000001111xxx
21463 [10, 64], [10, 64], [10, 64], [10, 64]
21464 ];
21465
21466 var blackTable2 = [
21467 [8, 13], [8, 13], [8, 13], [8, 13], // 00000100xxxx
21468 [8, 13], [8, 13], [8, 13], [8, 13],
21469 [8, 13], [8, 13], [8, 13], [8, 13],
21470 [8, 13], [8, 13], [8, 13], [8, 13],
21471 [11, 23], [11, 23], // 00000101000x
21472 [12, 50], // 000001010010
21473 [12, 51], // 000001010011
21474 [12, 44], // 000001010100
21475 [12, 45], // 000001010101
21476 [12, 46], // 000001010110
21477 [12, 47], // 000001010111
21478 [12, 57], // 000001011000
21479 [12, 58], // 000001011001
21480 [12, 61], // 000001011010
21481 [12, 256], // 000001011011
21482 [10, 16], [10, 16], [10, 16], [10, 16], // 0000010111xx
21483 [10, 17], [10, 17], [10, 17], [10, 17], // 0000011000xx
21484 [12, 48], // 000001100100
21485 [12, 49], // 000001100101
21486 [12, 62], // 000001100110
21487 [12, 63], // 000001100111
21488 [12, 30], // 000001101000
21489 [12, 31], // 000001101001
21490 [12, 32], // 000001101010
21491 [12, 33], // 000001101011
21492 [12, 40], // 000001101100
21493 [12, 41], // 000001101101
21494 [11, 22], [11, 22], // 00000110111x
21495 [8, 14], [8, 14], [8, 14], [8, 14], // 00000111xxxx
21496 [8, 14], [8, 14], [8, 14], [8, 14],
21497 [8, 14], [8, 14], [8, 14], [8, 14],
21498 [8, 14], [8, 14], [8, 14], [8, 14],
21499 [7, 10], [7, 10], [7, 10], [7, 10], // 0000100xxxxx
21500 [7, 10], [7, 10], [7, 10], [7, 10],
21501 [7, 10], [7, 10], [7, 10], [7, 10],
21502 [7, 10], [7, 10], [7, 10], [7, 10],
21503 [7, 10], [7, 10], [7, 10], [7, 10],
21504 [7, 10], [7, 10], [7, 10], [7, 10],
21505 [7, 10], [7, 10], [7, 10], [7, 10],
21506 [7, 10], [7, 10], [7, 10], [7, 10],
21507 [7, 11], [7, 11], [7, 11], [7, 11], // 0000101xxxxx
21508 [7, 11], [7, 11], [7, 11], [7, 11],
21509 [7, 11], [7, 11], [7, 11], [7, 11],
21510 [7, 11], [7, 11], [7, 11], [7, 11],
21511 [7, 11], [7, 11], [7, 11], [7, 11],
21512 [7, 11], [7, 11], [7, 11], [7, 11],
21513 [7, 11], [7, 11], [7, 11], [7, 11],
21514 [7, 11], [7, 11], [7, 11], [7, 11],
21515 [9, 15], [9, 15], [9, 15], [9, 15], // 000011000xxx
21516 [9, 15], [9, 15], [9, 15], [9, 15],
21517 [12, 128], // 000011001000
21518 [12, 192], // 000011001001
21519 [12, 26], // 000011001010
21520 [12, 27], // 000011001011
21521 [12, 28], // 000011001100
21522 [12, 29], // 000011001101
21523 [11, 19], [11, 19], // 00001100111x
21524 [11, 20], [11, 20], // 00001101000x
21525 [12, 34], // 000011010010
21526 [12, 35], // 000011010011
21527 [12, 36], // 000011010100
21528 [12, 37], // 000011010101
21529 [12, 38], // 000011010110
21530 [12, 39], // 000011010111
21531 [11, 21], [11, 21], // 00001101100x
21532 [12, 42], // 000011011010
21533 [12, 43], // 000011011011
21534 [10, 0], [10, 0], [10, 0], [10, 0], // 0000110111xx
21535 [7, 12], [7, 12], [7, 12], [7, 12], // 0000111xxxxx
21536 [7, 12], [7, 12], [7, 12], [7, 12],
21537 [7, 12], [7, 12], [7, 12], [7, 12],
21538 [7, 12], [7, 12], [7, 12], [7, 12],
21539 [7, 12], [7, 12], [7, 12], [7, 12],
21540 [7, 12], [7, 12], [7, 12], [7, 12],
21541 [7, 12], [7, 12], [7, 12], [7, 12],
21542 [7, 12], [7, 12], [7, 12], [7, 12]
21543 ];
21544
21545 var blackTable3 = [
21546 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000xx
21547 [6, 9], // 000100
21548 [6, 8], // 000101
21549 [5, 7], [5, 7], // 00011x
21550 [4, 6], [4, 6], [4, 6], [4, 6], // 0010xx
21551 [4, 5], [4, 5], [4, 5], [4, 5], // 0011xx
21552 [3, 1], [3, 1], [3, 1], [3, 1], // 010xxx
21553 [3, 1], [3, 1], [3, 1], [3, 1],
21554 [3, 4], [3, 4], [3, 4], [3, 4], // 011xxx
21555 [3, 4], [3, 4], [3, 4], [3, 4],
21556 [2, 3], [2, 3], [2, 3], [2, 3], // 10xxxx
21557 [2, 3], [2, 3], [2, 3], [2, 3],
21558 [2, 3], [2, 3], [2, 3], [2, 3],
21559 [2, 3], [2, 3], [2, 3], [2, 3],
21560 [2, 2], [2, 2], [2, 2], [2, 2], // 11xxxx
21561 [2, 2], [2, 2], [2, 2], [2, 2],
21562 [2, 2], [2, 2], [2, 2], [2, 2],
21563 [2, 2], [2, 2], [2, 2], [2, 2]
21564 ];
21565
21566 function CCITTFaxStream(str, maybeLength, params) {
21567 this.str = str;
21568 this.dict = str.dict;
21569
21570 params = params || Dict.empty;
21571
21572 this.encoding = params.get('K') || 0;
21573 this.eoline = params.get('EndOfLine') || false;
21574 this.byteAlign = params.get('EncodedByteAlign') || false;
21575 this.columns = params.get('Columns') || 1728;
21576 this.rows = params.get('Rows') || 0;
21577 var eoblock = params.get('EndOfBlock');
21578 if (eoblock === null || eoblock === undefined) {
21579 eoblock = true;
21580 }
21581 this.eoblock = eoblock;
21582 this.black = params.get('BlackIs1') || false;
21583
21584 this.codingLine = new Uint32Array(this.columns + 1);
21585 this.refLine = new Uint32Array(this.columns + 2);
21586
21587 this.codingLine[0] = this.columns;
21588 this.codingPos = 0;
21589
21590 this.row = 0;
21591 this.nextLine2D = this.encoding < 0;
21592 this.inputBits = 0;
21593 this.inputBuf = 0;
21594 this.outputBits = 0;
21595
21596 var code1;
21597 while ((code1 = this.lookBits(12)) === 0) {
21598 this.eatBits(1);
21599 }
21600 if (code1 === 1) {
21601 this.eatBits(12);
21602 }
21603 if (this.encoding > 0) {
21604 this.nextLine2D = !this.lookBits(1);
21605 this.eatBits(1);
21606 }
21607
21608 DecodeStream.call(this, maybeLength);
21609 }
21610
21611 CCITTFaxStream.prototype = Object.create(DecodeStream.prototype);
21612
21613 CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() {
21614 while (!this.eof) {
21615 var c = this.lookChar();
21616 this.ensureBuffer(this.bufferLength + 1);
21617 this.buffer[this.bufferLength++] = c;
21618 }
21619 };
21620
21621 CCITTFaxStream.prototype.addPixels =
21622 function ccittFaxStreamAddPixels(a1, blackPixels) {
21623 var codingLine = this.codingLine;
21624 var codingPos = this.codingPos;
21625
21626 if (a1 > codingLine[codingPos]) {
21627 if (a1 > this.columns) {
21628 info('row is wrong length');
21629 this.err = true;
21630 a1 = this.columns;
21631 }
21632 if ((codingPos & 1) ^ blackPixels) {
21633 ++codingPos;
21634 }
21635
21636 codingLine[codingPos] = a1;
21637 }
21638 this.codingPos = codingPos;
21639 };
21640
21641 CCITTFaxStream.prototype.addPixelsNeg =
21642 function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
21643 var codingLine = this.codingLine;
21644 var codingPos = this.codingPos;
21645
21646 if (a1 > codingLine[codingPos]) {
21647 if (a1 > this.columns) {
21648 info('row is wrong length');
21649 this.err = true;
21650 a1 = this.columns;
21651 }
21652 if ((codingPos & 1) ^ blackPixels) {
21653 ++codingPos;
21654 }
21655
21656 codingLine[codingPos] = a1;
21657 } else if (a1 < codingLine[codingPos]) {
21658 if (a1 < 0) {
21659 info('invalid code');
21660 this.err = true;
21661 a1 = 0;
21662 }
21663 while (codingPos > 0 && a1 < codingLine[codingPos - 1]) {
21664 --codingPos;
21665 }
21666 codingLine[codingPos] = a1;
21667 }
21668
21669 this.codingPos = codingPos;
21670 };
21671
21672 CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() {
21673 var refLine = this.refLine;
21674 var codingLine = this.codingLine;
21675 var columns = this.columns;
21676
21677 var refPos, blackPixels, bits, i;
21678
21679 if (this.outputBits === 0) {
21680 if (this.eof) {
21681 return null;
21682 }
21683 this.err = false;
21684
21685 var code1, code2, code3;
21686 if (this.nextLine2D) {
21687 for (i = 0; codingLine[i] < columns; ++i) {
21688 refLine[i] = codingLine[i];
21689 }
21690 refLine[i++] = columns;
21691 refLine[i] = columns;
21692 codingLine[0] = 0;
21693 this.codingPos = 0;
21694 refPos = 0;
21695 blackPixels = 0;
21696
21697 while (codingLine[this.codingPos] < columns) {
21698 code1 = this.getTwoDimCode();
21699 switch (code1) {
21700 case twoDimPass:
21701 this.addPixels(refLine[refPos + 1], blackPixels);
21702 if (refLine[refPos + 1] < columns) {
21703 refPos += 2;
21704 }
21705 break;
21706 case twoDimHoriz:
21707 code1 = code2 = 0;
21708 if (blackPixels) {
21709 do {
21710 code1 += (code3 = this.getBlackCode());
21711 } while (code3 >= 64);
21712 do {
21713 code2 += (code3 = this.getWhiteCode());
21714 } while (code3 >= 64);
21715 } else {
21716 do {
21717 code1 += (code3 = this.getWhiteCode());
21718 } while (code3 >= 64);
21719 do {
21720 code2 += (code3 = this.getBlackCode());
21721 } while (code3 >= 64);
21722 }
21723 this.addPixels(codingLine[this.codingPos] +
21724 code1, blackPixels);
21725 if (codingLine[this.codingPos] < columns) {
21726 this.addPixels(codingLine[this.codingPos] + code2,
21727 blackPixels ^ 1);
21728 }
21729 while (refLine[refPos] <= codingLine[this.codingPos] &&
21730 refLine[refPos] < columns) {
21731 refPos += 2;
21732 }
21733 break;
21734 case twoDimVertR3:
21735 this.addPixels(refLine[refPos] + 3, blackPixels);
21736 blackPixels ^= 1;
21737 if (codingLine[this.codingPos] < columns) {
21738 ++refPos;
21739 while (refLine[refPos] <= codingLine[this.codingPos] &&
21740 refLine[refPos] < columns) {
21741 refPos += 2;
21742 }
21743 }
21744 break;
21745 case twoDimVertR2:
21746 this.addPixels(refLine[refPos] + 2, blackPixels);
21747 blackPixels ^= 1;
21748 if (codingLine[this.codingPos] < columns) {
21749 ++refPos;
21750 while (refLine[refPos] <= codingLine[this.codingPos] &&
21751 refLine[refPos] < columns) {
21752 refPos += 2;
21753 }
21754 }
21755 break;
21756 case twoDimVertR1:
21757 this.addPixels(refLine[refPos] + 1, blackPixels);
21758 blackPixels ^= 1;
21759 if (codingLine[this.codingPos] < columns) {
21760 ++refPos;
21761 while (refLine[refPos] <= codingLine[this.codingPos] &&
21762 refLine[refPos] < columns) {
21763 refPos += 2;
21764 }
21765 }
21766 break;
21767 case twoDimVert0:
21768 this.addPixels(refLine[refPos], blackPixels);
21769 blackPixels ^= 1;
21770 if (codingLine[this.codingPos] < columns) {
21771 ++refPos;
21772 while (refLine[refPos] <= codingLine[this.codingPos] &&
21773 refLine[refPos] < columns) {
21774 refPos += 2;
21775 }
21776 }
21777 break;
21778 case twoDimVertL3:
21779 this.addPixelsNeg(refLine[refPos] - 3, blackPixels);
21780 blackPixels ^= 1;
21781 if (codingLine[this.codingPos] < columns) {
21782 if (refPos > 0) {
21783 --refPos;
21784 } else {
21785 ++refPos;
21786 }
21787 while (refLine[refPos] <= codingLine[this.codingPos] &&
21788 refLine[refPos] < columns) {
21789 refPos += 2;
21790 }
21791 }
21792 break;
21793 case twoDimVertL2:
21794 this.addPixelsNeg(refLine[refPos] - 2, blackPixels);
21795 blackPixels ^= 1;
21796 if (codingLine[this.codingPos] < columns) {
21797 if (refPos > 0) {
21798 --refPos;
21799 } else {
21800 ++refPos;
21801 }
21802 while (refLine[refPos] <= codingLine[this.codingPos] &&
21803 refLine[refPos] < columns) {
21804 refPos += 2;
21805 }
21806 }
21807 break;
21808 case twoDimVertL1:
21809 this.addPixelsNeg(refLine[refPos] - 1, blackPixels);
21810 blackPixels ^= 1;
21811 if (codingLine[this.codingPos] < columns) {
21812 if (refPos > 0) {
21813 --refPos;
21814 } else {
21815 ++refPos;
21816 }
21817 while (refLine[refPos] <= codingLine[this.codingPos] &&
21818 refLine[refPos] < columns) {
21819 refPos += 2;
21820 }
21821 }
21822 break;
21823 case ccittEOF:
21824 this.addPixels(columns, 0);
21825 this.eof = true;
21826 break;
21827 default:
21828 info('bad 2d code');
21829 this.addPixels(columns, 0);
21830 this.err = true;
21831 }
21832 }
21833 } else {
21834 codingLine[0] = 0;
21835 this.codingPos = 0;
21836 blackPixels = 0;
21837 while (codingLine[this.codingPos] < columns) {
21838 code1 = 0;
21839 if (blackPixels) {
21840 do {
21841 code1 += (code3 = this.getBlackCode());
21842 } while (code3 >= 64);
21843 } else {
21844 do {
21845 code1 += (code3 = this.getWhiteCode());
21846 } while (code3 >= 64);
21847 }
21848 this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
21849 blackPixels ^= 1;
21850 }
21851 }
21852
21853 var gotEOL = false;
21854
21855 if (this.byteAlign) {
21856 this.inputBits &= ~7;
21857 }
21858
21859 if (!this.eoblock && this.row === this.rows - 1) {
21860 this.eof = true;
21861 } else {
21862 code1 = this.lookBits(12);
21863 if (this.eoline) {
21864 while (code1 !== ccittEOF && code1 !== 1) {
21865 this.eatBits(1);
21866 code1 = this.lookBits(12);
21867 }
21868 } else {
21869 while (code1 === 0) {
21870 this.eatBits(1);
21871 code1 = this.lookBits(12);
21872 }
21873 }
21874 if (code1 === 1) {
21875 this.eatBits(12);
21876 gotEOL = true;
21877 } else if (code1 === ccittEOF) {
21878 this.eof = true;
21879 }
21880 }
21881
21882 if (!this.eof && this.encoding > 0) {
21883 this.nextLine2D = !this.lookBits(1);
21884 this.eatBits(1);
21885 }
21886
21887 if (this.eoblock && gotEOL && this.byteAlign) {
21888 code1 = this.lookBits(12);
21889 if (code1 === 1) {
21890 this.eatBits(12);
21891 if (this.encoding > 0) {
21892 this.lookBits(1);
21893 this.eatBits(1);
21894 }
21895 if (this.encoding >= 0) {
21896 for (i = 0; i < 4; ++i) {
21897 code1 = this.lookBits(12);
21898 if (code1 !== 1) {
21899 info('bad rtc code: ' + code1);
21900 }
21901 this.eatBits(12);
21902 if (this.encoding > 0) {
21903 this.lookBits(1);
21904 this.eatBits(1);
21905 }
21906 }
21907 }
21908 this.eof = true;
21909 }
21910 } else if (this.err && this.eoline) {
21911 while (true) {
21912 code1 = this.lookBits(13);
21913 if (code1 === ccittEOF) {
21914 this.eof = true;
21915 return null;
21916 }
21917 if ((code1 >> 1) === 1) {
21918 break;
21919 }
21920 this.eatBits(1);
21921 }
21922 this.eatBits(12);
21923 if (this.encoding > 0) {
21924 this.eatBits(1);
21925 this.nextLine2D = !(code1 & 1);
21926 }
21927 }
21928
21929 if (codingLine[0] > 0) {
21930 this.outputBits = codingLine[this.codingPos = 0];
21931 } else {
21932 this.outputBits = codingLine[this.codingPos = 1];
21933 }
21934 this.row++;
21935 }
21936
21937 var c;
21938 if (this.outputBits >= 8) {
21939 c = (this.codingPos & 1) ? 0 : 0xFF;
21940 this.outputBits -= 8;
21941 if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
21942 this.codingPos++;
21943 this.outputBits = (codingLine[this.codingPos] -
21944 codingLine[this.codingPos - 1]);
21945 }
21946 } else {
21947 bits = 8;
21948 c = 0;
21949 do {
21950 if (this.outputBits > bits) {
21951 c <<= bits;
21952 if (!(this.codingPos & 1)) {
21953 c |= 0xFF >> (8 - bits);
21954 }
21955 this.outputBits -= bits;
21956 bits = 0;
21957 } else {
21958 c <<= this.outputBits;
21959 if (!(this.codingPos & 1)) {
21960 c |= 0xFF >> (8 - this.outputBits);
21961 }
21962 bits -= this.outputBits;
21963 this.outputBits = 0;
21964 if (codingLine[this.codingPos] < columns) {
21965 this.codingPos++;
21966 this.outputBits = (codingLine[this.codingPos] -
21967 codingLine[this.codingPos - 1]);
21968 } else if (bits > 0) {
21969 c <<= bits;
21970 bits = 0;
21971 }
21972 }
21973 } while (bits);
21974 }
21975 if (this.black) {
21976 c ^= 0xFF;
21977 }
21978 return c;
21979 };
21980
21981 // This functions returns the code found from the table.
21982 // The start and end parameters set the boundaries for searching the table.
21983 // The limit parameter is optional. Function returns an array with three
21984 // values. The first array element indicates whether a valid code is being
21985 // returned. The second array element is the actual code. The third array
21986 // element indicates whether EOF was reached.
21987 CCITTFaxStream.prototype.findTableCode =
21988 function ccittFaxStreamFindTableCode(start, end, table, limit) {
21989
21990 var limitValue = limit || 0;
21991 for (var i = start; i <= end; ++i) {
21992 var code = this.lookBits(i);
21993 if (code === ccittEOF) {
21994 return [true, 1, false];
21995 }
21996 if (i < end) {
21997 code <<= end - i;
21998 }
21999 if (!limitValue || code >= limitValue) {
22000 var p = table[code - limitValue];
22001 if (p[0] === i) {
22002 this.eatBits(i);
22003 return [true, p[1], true];
22004 }
22005 }
22006 }
22007 return [false, 0, false];
22008 };
22009
22010 CCITTFaxStream.prototype.getTwoDimCode =
22011 function ccittFaxStreamGetTwoDimCode() {
22012
22013 var code = 0;
22014 var p;
22015 if (this.eoblock) {
22016 code = this.lookBits(7);
22017 p = twoDimTable[code];
22018 if (p && p[0] > 0) {
22019 this.eatBits(p[0]);
22020 return p[1];
22021 }
22022 } else {
22023 var result = this.findTableCode(1, 7, twoDimTable);
22024 if (result[0] && result[2]) {
22025 return result[1];
22026 }
22027 }
22028 info('Bad two dim code');
22029 return ccittEOF;
22030 };
22031
22032 CCITTFaxStream.prototype.getWhiteCode =
22033 function ccittFaxStreamGetWhiteCode() {
22034
22035 var code = 0;
22036 var p;
22037 if (this.eoblock) {
22038 code = this.lookBits(12);
22039 if (code === ccittEOF) {
22040 return 1;
22041 }
22042
22043 if ((code >> 5) === 0) {
22044 p = whiteTable1[code];
22045 } else {
22046 p = whiteTable2[code >> 3];
22047 }
22048
22049 if (p[0] > 0) {
22050 this.eatBits(p[0]);
22051 return p[1];
22052 }
22053 } else {
22054 var result = this.findTableCode(1, 9, whiteTable2);
22055 if (result[0]) {
22056 return result[1];
22057 }
22058
22059 result = this.findTableCode(11, 12, whiteTable1);
22060 if (result[0]) {
22061 return result[1];
22062 }
22063 }
22064 info('bad white code');
22065 this.eatBits(1);
22066 return 1;
22067 };
22068
22069 CCITTFaxStream.prototype.getBlackCode =
22070 function ccittFaxStreamGetBlackCode() {
22071
22072 var code, p;
22073 if (this.eoblock) {
22074 code = this.lookBits(13);
22075 if (code === ccittEOF) {
22076 return 1;
22077 }
22078 if ((code >> 7) === 0) {
22079 p = blackTable1[code];
22080 } else if ((code >> 9) === 0 && (code >> 7) !== 0) {
22081 p = blackTable2[(code >> 1) - 64];
22082 } else {
22083 p = blackTable3[code >> 7];
22084 }
22085
22086 if (p[0] > 0) {
22087 this.eatBits(p[0]);
22088 return p[1];
22089 }
22090 } else {
22091 var result = this.findTableCode(2, 6, blackTable3);
22092 if (result[0]) {
22093 return result[1];
22094 }
22095
22096 result = this.findTableCode(7, 12, blackTable2, 64);
22097 if (result[0]) {
22098 return result[1];
22099 }
22100
22101 result = this.findTableCode(10, 13, blackTable1);
22102 if (result[0]) {
22103 return result[1];
22104 }
22105 }
22106 info('bad black code');
22107 this.eatBits(1);
22108 return 1;
22109 };
22110
22111 CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) {
22112 var c;
22113 while (this.inputBits < n) {
22114 if ((c = this.str.getByte()) === -1) {
22115 if (this.inputBits === 0) {
22116 return ccittEOF;
22117 }
22118 return ((this.inputBuf << (n - this.inputBits)) &
22119 (0xFFFF >> (16 - n)));
22120 }
22121 this.inputBuf = (this.inputBuf << 8) | c;
22122 this.inputBits += 8;
22123 }
22124 return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
22125 };
22126
22127 CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) {
22128 if ((this.inputBits -= n) < 0) {
22129 this.inputBits = 0;
22130 }
22131 };
22132
22133 return CCITTFaxStream;
22134})();
22135
22136var LZWStream = (function LZWStreamClosure() {
22137 function LZWStream(str, maybeLength, earlyChange) {
22138 this.str = str;
22139 this.dict = str.dict;
22140 this.cachedData = 0;
22141 this.bitsCached = 0;
22142
22143 var maxLzwDictionarySize = 4096;
22144 var lzwState = {
22145 earlyChange: earlyChange,
22146 codeLength: 9,
22147 nextCode: 258,
22148 dictionaryValues: new Uint8Array(maxLzwDictionarySize),
22149 dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
22150 dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
22151 currentSequence: new Uint8Array(maxLzwDictionarySize),
22152 currentSequenceLength: 0
22153 };
22154 for (var i = 0; i < 256; ++i) {
22155 lzwState.dictionaryValues[i] = i;
22156 lzwState.dictionaryLengths[i] = 1;
22157 }
22158 this.lzwState = lzwState;
22159
22160 DecodeStream.call(this, maybeLength);
22161 }
22162
22163 LZWStream.prototype = Object.create(DecodeStream.prototype);
22164
22165 LZWStream.prototype.readBits = function LZWStream_readBits(n) {
22166 var bitsCached = this.bitsCached;
22167 var cachedData = this.cachedData;
22168 while (bitsCached < n) {
22169 var c = this.str.getByte();
22170 if (c === -1) {
22171 this.eof = true;
22172 return null;
22173 }
22174 cachedData = (cachedData << 8) | c;
22175 bitsCached += 8;
22176 }
22177 this.bitsCached = (bitsCached -= n);
22178 this.cachedData = cachedData;
22179 this.lastCode = null;
22180 return (cachedData >>> bitsCached) & ((1 << n) - 1);
22181 };
22182
22183 LZWStream.prototype.readBlock = function LZWStream_readBlock() {
22184 var blockSize = 512;
22185 var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
22186 var i, j, q;
22187
22188 var lzwState = this.lzwState;
22189 if (!lzwState) {
22190 return; // eof was found
22191 }
22192
22193 var earlyChange = lzwState.earlyChange;
22194 var nextCode = lzwState.nextCode;
22195 var dictionaryValues = lzwState.dictionaryValues;
22196 var dictionaryLengths = lzwState.dictionaryLengths;
22197 var dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
22198 var codeLength = lzwState.codeLength;
22199 var prevCode = lzwState.prevCode;
22200 var currentSequence = lzwState.currentSequence;
22201 var currentSequenceLength = lzwState.currentSequenceLength;
22202
22203 var decodedLength = 0;
22204 var currentBufferLength = this.bufferLength;
22205 var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
22206
22207 for (i = 0; i < blockSize; i++) {
22208 var code = this.readBits(codeLength);
22209 var hasPrev = currentSequenceLength > 0;
22210 if (code < 256) {
22211 currentSequence[0] = code;
22212 currentSequenceLength = 1;
22213 } else if (code >= 258) {
22214 if (code < nextCode) {
22215 currentSequenceLength = dictionaryLengths[code];
22216 for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
22217 currentSequence[j] = dictionaryValues[q];
22218 q = dictionaryPrevCodes[q];
22219 }
22220 } else {
22221 currentSequence[currentSequenceLength++] = currentSequence[0];
22222 }
22223 } else if (code === 256) {
22224 codeLength = 9;
22225 nextCode = 258;
22226 currentSequenceLength = 0;
22227 continue;
22228 } else {
22229 this.eof = true;
22230 delete this.lzwState;
22231 break;
22232 }
22233
22234 if (hasPrev) {
22235 dictionaryPrevCodes[nextCode] = prevCode;
22236 dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
22237 dictionaryValues[nextCode] = currentSequence[0];
22238 nextCode++;
22239 codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ?
22240 codeLength : Math.min(Math.log(nextCode + earlyChange) /
22241 0.6931471805599453 + 1, 12) | 0;
22242 }
22243 prevCode = code;
22244
22245 decodedLength += currentSequenceLength;
22246 if (estimatedDecodedSize < decodedLength) {
22247 do {
22248 estimatedDecodedSize += decodedSizeDelta;
22249 } while (estimatedDecodedSize < decodedLength);
22250 buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
22251 }
22252 for (j = 0; j < currentSequenceLength; j++) {
22253 buffer[currentBufferLength++] = currentSequence[j];
22254 }
22255 }
22256 lzwState.nextCode = nextCode;
22257 lzwState.codeLength = codeLength;
22258 lzwState.prevCode = prevCode;
22259 lzwState.currentSequenceLength = currentSequenceLength;
22260
22261 this.bufferLength = currentBufferLength;
22262 };
22263
22264 return LZWStream;
22265})();
22266
22267var NullStream = (function NullStreamClosure() {
22268 function NullStream() {
22269 Stream.call(this, new Uint8Array(0));
22270 }
22271
22272 NullStream.prototype = Stream.prototype;
22273
22274 return NullStream;
22275})();
22276
22277exports.Ascii85Stream = Ascii85Stream;
22278exports.AsciiHexStream = AsciiHexStream;
22279exports.CCITTFaxStream = CCITTFaxStream;
22280exports.DecryptStream = DecryptStream;
22281exports.DecodeStream = DecodeStream;
22282exports.FlateStream = FlateStream;
22283exports.Jbig2Stream = Jbig2Stream;
22284exports.JpegStream = JpegStream;
22285exports.JpxStream = JpxStream;
22286exports.NullStream = NullStream;
22287exports.PredictorStream = PredictorStream;
22288exports.RunLengthStream = RunLengthStream;
22289exports.Stream = Stream;
22290exports.StreamsSequenceStream = StreamsSequenceStream;
22291exports.StringStream = StringStream;
22292exports.LZWStream = LZWStream;
22293}));
22294
22295
22296(function (root, factory) {
22297 {
22298 factory((root.pdfjsCoreCrypto = {}), root.pdfjsSharedUtil,
22299 root.pdfjsCorePrimitives, root.pdfjsCoreStream);
22300 }
22301}(this, function (exports, sharedUtil, corePrimitives, coreStream) {
22302
22303var PasswordException = sharedUtil.PasswordException;
22304var PasswordResponses = sharedUtil.PasswordResponses;
22305var bytesToString = sharedUtil.bytesToString;
22306var error = sharedUtil.error;
22307var isInt = sharedUtil.isInt;
22308var stringToBytes = sharedUtil.stringToBytes;
22309var utf8StringToString = sharedUtil.utf8StringToString;
22310var warn = sharedUtil.warn;
22311var Name = corePrimitives.Name;
22312var isName = corePrimitives.isName;
22313var isDict = corePrimitives.isDict;
22314var DecryptStream = coreStream.DecryptStream;
22315
22316var ARCFourCipher = (function ARCFourCipherClosure() {
22317 function ARCFourCipher(key) {
22318 this.a = 0;
22319 this.b = 0;
22320 var s = new Uint8Array(256);
22321 var i, j = 0, tmp, keyLength = key.length;
22322 for (i = 0; i < 256; ++i) {
22323 s[i] = i;
22324 }
22325 for (i = 0; i < 256; ++i) {
22326 tmp = s[i];
22327 j = (j + tmp + key[i % keyLength]) & 0xFF;
22328 s[i] = s[j];
22329 s[j] = tmp;
22330 }
22331 this.s = s;
22332 }
22333
22334 ARCFourCipher.prototype = {
22335 encryptBlock: function ARCFourCipher_encryptBlock(data) {
22336 var i, n = data.length, tmp, tmp2;
22337 var a = this.a, b = this.b, s = this.s;
22338 var output = new Uint8Array(n);
22339 for (i = 0; i < n; ++i) {
22340 a = (a + 1) & 0xFF;
22341 tmp = s[a];
22342 b = (b + tmp) & 0xFF;
22343 tmp2 = s[b];
22344 s[a] = tmp2;
22345 s[b] = tmp;
22346 output[i] = data[i] ^ s[(tmp + tmp2) & 0xFF];
22347 }
22348 this.a = a;
22349 this.b = b;
22350 return output;
22351 }
22352 };
22353 ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
22354
22355 return ARCFourCipher;
22356})();
22357
22358var calculateMD5 = (function calculateMD5Closure() {
22359 var r = new Uint8Array([
22360 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
22361 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
22362 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
22363 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]);
22364
22365 var k = new Int32Array([
22366 -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426,
22367 -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162,
22368 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632,
22369 643717713, -373897302, -701558691, 38016083, -660478335, -405537848,
22370 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784,
22371 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556,
22372 -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222,
22373 -722521979, 76029189, -640364487, -421815835, 530742520, -995338651,
22374 -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606,
22375 -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649,
22376 -145523070, -1120210379, 718787259, -343485551]);
22377
22378 function hash(data, offset, length) {
22379 var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878;
22380 // pre-processing
22381 var paddedLength = (length + 72) & ~63; // data + 9 extra bytes
22382 var padded = new Uint8Array(paddedLength);
22383 var i, j, n;
22384 for (i = 0; i < length; ++i) {
22385 padded[i] = data[offset++];
22386 }
22387 padded[i++] = 0x80;
22388 n = paddedLength - 8;
22389 while (i < n) {
22390 padded[i++] = 0;
22391 }
22392 padded[i++] = (length << 3) & 0xFF;
22393 padded[i++] = (length >> 5) & 0xFF;
22394 padded[i++] = (length >> 13) & 0xFF;
22395 padded[i++] = (length >> 21) & 0xFF;
22396 padded[i++] = (length >>> 29) & 0xFF;
22397 padded[i++] = 0;
22398 padded[i++] = 0;
22399 padded[i++] = 0;
22400 var w = new Int32Array(16);
22401 for (i = 0; i < paddedLength;) {
22402 for (j = 0; j < 16; ++j, i += 4) {
22403 w[j] = (padded[i] | (padded[i + 1] << 8) |
22404 (padded[i + 2] << 16) | (padded[i + 3] << 24));
22405 }
22406 var a = h0, b = h1, c = h2, d = h3, f, g;
22407 for (j = 0; j < 64; ++j) {
22408 if (j < 16) {
22409 f = (b & c) | ((~b) & d);
22410 g = j;
22411 } else if (j < 32) {
22412 f = (d & b) | ((~d) & c);
22413 g = (5 * j + 1) & 15;
22414 } else if (j < 48) {
22415 f = b ^ c ^ d;
22416 g = (3 * j + 5) & 15;
22417 } else {
22418 f = c ^ (b | (~d));
22419 g = (7 * j) & 15;
22420 }
22421 var tmp = d, rotateArg = (a + f + k[j] + w[g]) | 0, rotate = r[j];
22422 d = c;
22423 c = b;
22424 b = (b + ((rotateArg << rotate) | (rotateArg >>> (32 - rotate)))) | 0;
22425 a = tmp;
22426 }
22427 h0 = (h0 + a) | 0;
22428 h1 = (h1 + b) | 0;
22429 h2 = (h2 + c) | 0;
22430 h3 = (h3 + d) | 0;
22431 }
22432 return new Uint8Array([
22433 h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >>> 24) & 0xFF,
22434 h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >>> 24) & 0xFF,
22435 h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >>> 24) & 0xFF,
22436 h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >>> 24) & 0xFF
22437 ]);
22438 }
22439
22440 return hash;
22441})();
22442var Word64 = (function Word64Closure() {
22443 function Word64(highInteger, lowInteger) {
22444 this.high = highInteger | 0;
22445 this.low = lowInteger | 0;
22446 }
22447 Word64.prototype = {
22448 and: function Word64_and(word) {
22449 this.high &= word.high;
22450 this.low &= word.low;
22451 },
22452 xor: function Word64_xor(word) {
22453 this.high ^= word.high;
22454 this.low ^= word.low;
22455 },
22456
22457 or: function Word64_or(word) {
22458 this.high |= word.high;
22459 this.low |= word.low;
22460 },
22461
22462 shiftRight: function Word64_shiftRight(places) {
22463 if (places >= 32) {
22464 this.low = (this.high >>> (places - 32)) | 0;
22465 this.high = 0;
22466 } else {
22467 this.low = (this.low >>> places) | (this.high << (32 - places));
22468 this.high = (this.high >>> places) | 0;
22469 }
22470 },
22471
22472 shiftLeft: function Word64_shiftLeft(places) {
22473 if (places >= 32) {
22474 this.high = this.low << (places - 32);
22475 this.low = 0;
22476 } else {
22477 this.high = (this.high << places) | (this.low >>> (32 - places));
22478 this.low = this.low << places;
22479 }
22480 },
22481
22482 rotateRight: function Word64_rotateRight(places) {
22483 var low, high;
22484 if (places & 32) {
22485 high = this.low;
22486 low = this.high;
22487 } else {
22488 low = this.low;
22489 high = this.high;
22490 }
22491 places &= 31;
22492 this.low = (low >>> places) | (high << (32 - places));
22493 this.high = (high >>> places) | (low << (32 - places));
22494 },
22495
22496 not: function Word64_not() {
22497 this.high = ~this.high;
22498 this.low = ~this.low;
22499 },
22500
22501 add: function Word64_add(word) {
22502 var lowAdd = (this.low >>> 0) + (word.low >>> 0);
22503 var highAdd = (this.high >>> 0) + (word.high >>> 0);
22504 if (lowAdd > 0xFFFFFFFF) {
22505 highAdd += 1;
22506 }
22507 this.low = lowAdd | 0;
22508 this.high = highAdd | 0;
22509 },
22510
22511 copyTo: function Word64_copyTo(bytes, offset) {
22512 bytes[offset] = (this.high >>> 24) & 0xFF;
22513 bytes[offset + 1] = (this.high >> 16) & 0xFF;
22514 bytes[offset + 2] = (this.high >> 8) & 0xFF;
22515 bytes[offset + 3] = this.high & 0xFF;
22516 bytes[offset + 4] = (this.low >>> 24) & 0xFF;
22517 bytes[offset + 5] = (this.low >> 16) & 0xFF;
22518 bytes[offset + 6] = (this.low >> 8) & 0xFF;
22519 bytes[offset + 7] = this.low & 0xFF;
22520 },
22521
22522 assign: function Word64_assign(word) {
22523 this.high = word.high;
22524 this.low = word.low;
22525 }
22526 };
22527 return Word64;
22528})();
22529
22530var calculateSHA256 = (function calculateSHA256Closure() {
22531 function rotr(x, n) {
22532 return (x >>> n) | (x << 32 - n);
22533 }
22534
22535 function ch(x, y, z) {
22536 return (x & y) ^ (~x & z);
22537 }
22538
22539 function maj(x, y, z) {
22540 return (x & y) ^ (x & z) ^ (y & z);
22541 }
22542
22543 function sigma(x) {
22544 return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
22545 }
22546
22547 function sigmaPrime(x) {
22548 return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
22549 }
22550
22551 function littleSigma(x) {
22552 return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3;
22553 }
22554
22555 function littleSigmaPrime(x) {
22556 return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10;
22557 }
22558
22559 var k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
22560 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
22561 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
22562 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
22563 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
22564 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
22565 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
22566 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
22567 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
22568 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
22569 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
22570 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
22571 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
22572 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
22573 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
22574 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
22575
22576 function hash(data, offset, length) {
22577 // initial hash values
22578 var h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372,
22579 h3 = 0xa54ff53a, h4 = 0x510e527f, h5 = 0x9b05688c,
22580 h6 = 0x1f83d9ab, h7 = 0x5be0cd19;
22581 // pre-processing
22582 var paddedLength = Math.ceil((length + 9) / 64) * 64;
22583 var padded = new Uint8Array(paddedLength);
22584 var i, j, n;
22585 for (i = 0; i < length; ++i) {
22586 padded[i] = data[offset++];
22587 }
22588 padded[i++] = 0x80;
22589 n = paddedLength - 8;
22590 while (i < n) {
22591 padded[i++] = 0;
22592 }
22593 padded[i++] = 0;
22594 padded[i++] = 0;
22595 padded[i++] = 0;
22596 padded[i++] = (length >>> 29) & 0xFF;
22597 padded[i++] = (length >> 21) & 0xFF;
22598 padded[i++] = (length >> 13) & 0xFF;
22599 padded[i++] = (length >> 5) & 0xFF;
22600 padded[i++] = (length << 3) & 0xFF;
22601 var w = new Uint32Array(64);
22602 // for each 512 bit block
22603 for (i = 0; i < paddedLength;) {
22604 for (j = 0; j < 16; ++j) {
22605 w[j] = (padded[i] << 24 | (padded[i + 1] << 16) |
22606 (padded[i + 2] << 8) | (padded[i + 3]));
22607 i += 4;
22608 }
22609
22610 for (j = 16; j < 64; ++j) {
22611 w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] +
22612 littleSigma(w[j - 15]) + w[j - 16] | 0;
22613 }
22614 var a = h0, b = h1, c = h2, d = h3, e = h4,
22615 f = h5, g = h6, h = h7, t1, t2;
22616 for (j = 0; j < 64; ++j) {
22617 t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j];
22618 t2 = sigma(a) + maj(a, b, c);
22619 h = g;
22620 g = f;
22621 f = e;
22622 e = (d + t1) | 0;
22623 d = c;
22624 c = b;
22625 b = a;
22626 a = (t1 + t2) | 0;
22627 }
22628 h0 = (h0 + a) | 0;
22629 h1 = (h1 + b) | 0;
22630 h2 = (h2 + c) | 0;
22631 h3 = (h3 + d) | 0;
22632 h4 = (h4 + e) | 0;
22633 h5 = (h5 + f) | 0;
22634 h6 = (h6 + g) | 0;
22635 h7 = (h7 + h) | 0;
22636 }
22637 return new Uint8Array([
22638 (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, (h0) & 0xFF,
22639 (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, (h1) & 0xFF,
22640 (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, (h2) & 0xFF,
22641 (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, (h3) & 0xFF,
22642 (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, (h4) & 0xFF,
22643 (h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, (h5) & 0xFF,
22644 (h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, (h6) & 0xFF,
22645 (h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, (h7) & 0xFF
22646 ]);
22647 }
22648
22649 return hash;
22650})();
22651
22652var calculateSHA512 = (function calculateSHA512Closure() {
22653 function ch(result, x, y, z, tmp) {
22654 result.assign(x);
22655 result.and(y);
22656 tmp.assign(x);
22657 tmp.not();
22658 tmp.and(z);
22659 result.xor(tmp);
22660 }
22661
22662 function maj(result, x, y, z, tmp) {
22663 result.assign(x);
22664 result.and(y);
22665 tmp.assign(x);
22666 tmp.and(z);
22667 result.xor(tmp);
22668 tmp.assign(y);
22669 tmp.and(z);
22670 result.xor(tmp);
22671 }
22672
22673 function sigma(result, x, tmp) {
22674 result.assign(x);
22675 result.rotateRight(28);
22676 tmp.assign(x);
22677 tmp.rotateRight(34);
22678 result.xor(tmp);
22679 tmp.assign(x);
22680 tmp.rotateRight(39);
22681 result.xor(tmp);
22682 }
22683
22684 function sigmaPrime(result, x, tmp) {
22685 result.assign(x);
22686 result.rotateRight(14);
22687 tmp.assign(x);
22688 tmp.rotateRight(18);
22689 result.xor(tmp);
22690 tmp.assign(x);
22691 tmp.rotateRight(41);
22692 result.xor(tmp);
22693 }
22694
22695 function littleSigma(result, x, tmp) {
22696 result.assign(x);
22697 result.rotateRight(1);
22698 tmp.assign(x);
22699 tmp.rotateRight(8);
22700 result.xor(tmp);
22701 tmp.assign(x);
22702 tmp.shiftRight(7);
22703 result.xor(tmp);
22704 }
22705
22706 function littleSigmaPrime(result, x, tmp) {
22707 result.assign(x);
22708 result.rotateRight(19);
22709 tmp.assign(x);
22710 tmp.rotateRight(61);
22711 result.xor(tmp);
22712 tmp.assign(x);
22713 tmp.shiftRight(6);
22714 result.xor(tmp);
22715 }
22716
22717 var k = [
22718 new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd),
22719 new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc),
22720 new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019),
22721 new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118),
22722 new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe),
22723 new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2),
22724 new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1),
22725 new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694),
22726 new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3),
22727 new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65),
22728 new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483),
22729 new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5),
22730 new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210),
22731 new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4),
22732 new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725),
22733 new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70),
22734 new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926),
22735 new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df),
22736 new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8),
22737 new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b),
22738 new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001),
22739 new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30),
22740 new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910),
22741 new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8),
22742 new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53),
22743 new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8),
22744 new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb),
22745 new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3),
22746 new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60),
22747 new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec),
22748 new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9),
22749 new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b),
22750 new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207),
22751 new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178),
22752 new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6),
22753 new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b),
22754 new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493),
22755 new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c),
22756 new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a),
22757 new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)];
22758
22759 function hash(data, offset, length, mode384) {
22760 mode384 = !!mode384;
22761 // initial hash values
22762 var h0, h1, h2, h3, h4, h5, h6, h7;
22763 if (!mode384) {
22764 h0 = new Word64(0x6a09e667, 0xf3bcc908);
22765 h1 = new Word64(0xbb67ae85, 0x84caa73b);
22766 h2 = new Word64(0x3c6ef372, 0xfe94f82b);
22767 h3 = new Word64(0xa54ff53a, 0x5f1d36f1);
22768 h4 = new Word64(0x510e527f, 0xade682d1);
22769 h5 = new Word64(0x9b05688c, 0x2b3e6c1f);
22770 h6 = new Word64(0x1f83d9ab, 0xfb41bd6b);
22771 h7 = new Word64(0x5be0cd19, 0x137e2179);
22772 }
22773 else {
22774 // SHA384 is exactly the same
22775 // except with different starting values and a trimmed result
22776 h0 = new Word64(0xcbbb9d5d, 0xc1059ed8);
22777 h1 = new Word64(0x629a292a, 0x367cd507);
22778 h2 = new Word64(0x9159015a, 0x3070dd17);
22779 h3 = new Word64(0x152fecd8, 0xf70e5939);
22780 h4 = new Word64(0x67332667, 0xffc00b31);
22781 h5 = new Word64(0x8eb44a87, 0x68581511);
22782 h6 = new Word64(0xdb0c2e0d, 0x64f98fa7);
22783 h7 = new Word64(0x47b5481d, 0xbefa4fa4);
22784 }
22785
22786 // pre-processing
22787 var paddedLength = Math.ceil((length + 17) / 128) * 128;
22788 var padded = new Uint8Array(paddedLength);
22789 var i, j, n;
22790 for (i = 0; i < length; ++i) {
22791 padded[i] = data[offset++];
22792 }
22793 padded[i++] = 0x80;
22794 n = paddedLength - 16;
22795 while (i < n) {
22796 padded[i++] = 0;
22797 }
22798 padded[i++] = 0;
22799 padded[i++] = 0;
22800 padded[i++] = 0;
22801 padded[i++] = 0;
22802 padded[i++] = 0;
22803 padded[i++] = 0;
22804 padded[i++] = 0;
22805 padded[i++] = 0;
22806 padded[i++] = 0;
22807 padded[i++] = 0;
22808 padded[i++] = 0;
22809 padded[i++] = (length >>> 29) & 0xFF;
22810 padded[i++] = (length >> 21) & 0xFF;
22811 padded[i++] = (length >> 13) & 0xFF;
22812 padded[i++] = (length >> 5) & 0xFF;
22813 padded[i++] = (length << 3) & 0xFF;
22814
22815 var w = new Array(80);
22816 for (i = 0; i < 80; i++) {
22817 w[i] = new Word64(0, 0);
22818 }
22819 var a = new Word64(0, 0), b = new Word64(0, 0), c = new Word64(0, 0);
22820 var d = new Word64(0, 0), e = new Word64(0, 0), f = new Word64(0, 0);
22821 var g = new Word64(0, 0), h = new Word64(0, 0);
22822 var t1 = new Word64(0, 0), t2 = new Word64(0, 0);
22823 var tmp1 = new Word64(0, 0), tmp2 = new Word64(0, 0), tmp3;
22824
22825 // for each 1024 bit block
22826 for (i = 0; i < paddedLength;) {
22827 for (j = 0; j < 16; ++j) {
22828 w[j].high = (padded[i] << 24) | (padded[i + 1] << 16) |
22829 (padded[i + 2] << 8) | (padded[i + 3]);
22830 w[j].low = (padded[i + 4]) << 24 | (padded[i + 5]) << 16 |
22831 (padded[i + 6]) << 8 | (padded[i + 7]);
22832 i += 8;
22833 }
22834 for (j = 16; j < 80; ++j) {
22835 tmp3 = w[j];
22836 littleSigmaPrime(tmp3, w[j - 2], tmp2);
22837 tmp3.add(w[j - 7]);
22838 littleSigma(tmp1, w[j - 15], tmp2);
22839 tmp3.add(tmp1);
22840 tmp3.add(w[j - 16]);
22841 }
22842
22843 a.assign(h0); b.assign(h1); c.assign(h2); d.assign(h3);
22844 e.assign(h4); f.assign(h5); g.assign(h6); h.assign(h7);
22845 for (j = 0; j < 80; ++j) {
22846 t1.assign(h);
22847 sigmaPrime(tmp1, e, tmp2);
22848 t1.add(tmp1);
22849 ch(tmp1, e, f, g, tmp2);
22850 t1.add(tmp1);
22851 t1.add(k[j]);
22852 t1.add(w[j]);
22853
22854 sigma(t2, a, tmp2);
22855 maj(tmp1, a, b, c, tmp2);
22856 t2.add(tmp1);
22857
22858 tmp3 = h;
22859 h = g;
22860 g = f;
22861 f = e;
22862 d.add(t1);
22863 e = d;
22864 d = c;
22865 c = b;
22866 b = a;
22867 tmp3.assign(t1);
22868 tmp3.add(t2);
22869 a = tmp3;
22870 }
22871 h0.add(a);
22872 h1.add(b);
22873 h2.add(c);
22874 h3.add(d);
22875 h4.add(e);
22876 h5.add(f);
22877 h6.add(g);
22878 h7.add(h);
22879 }
22880
22881 var result;
22882 if (!mode384) {
22883 result = new Uint8Array(64);
22884 h0.copyTo(result,0);
22885 h1.copyTo(result,8);
22886 h2.copyTo(result,16);
22887 h3.copyTo(result,24);
22888 h4.copyTo(result,32);
22889 h5.copyTo(result,40);
22890 h6.copyTo(result,48);
22891 h7.copyTo(result,56);
22892 }
22893 else {
22894 result = new Uint8Array(48);
22895 h0.copyTo(result,0);
22896 h1.copyTo(result,8);
22897 h2.copyTo(result,16);
22898 h3.copyTo(result,24);
22899 h4.copyTo(result,32);
22900 h5.copyTo(result,40);
22901 }
22902 return result;
22903 }
22904
22905 return hash;
22906})();
22907var calculateSHA384 = (function calculateSHA384Closure() {
22908 function hash(data, offset, length) {
22909 return calculateSHA512(data, offset, length, true);
22910 }
22911
22912 return hash;
22913})();
22914var NullCipher = (function NullCipherClosure() {
22915 function NullCipher() {
22916 }
22917
22918 NullCipher.prototype = {
22919 decryptBlock: function NullCipher_decryptBlock(data) {
22920 return data;
22921 }
22922 };
22923
22924 return NullCipher;
22925})();
22926
22927var AES128Cipher = (function AES128CipherClosure() {
22928 var rcon = new Uint8Array([
22929 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
22930 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
22931 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
22932 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
22933 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
22934 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,
22935 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
22936 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
22937 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,
22938 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e,
22939 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
22940 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
22941 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02,
22942 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
22943 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
22944 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
22945 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb,
22946 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
22947 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
22948 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
22949 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
22950 0x74, 0xe8, 0xcb, 0x8d]);
22951
22952 var s = new Uint8Array([
22953 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
22954 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
22955 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
22956 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
22957 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
22958 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
22959 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
22960 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
22961 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
22962 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
22963 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
22964 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
22965 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
22966 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
22967 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
22968 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
22969 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
22970 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
22971 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
22972 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
22973 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
22974 0xb0, 0x54, 0xbb, 0x16]);
22975
22976 var inv_s = new Uint8Array([
22977 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
22978 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
22979 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
22980 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
22981 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
22982 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
22983 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
22984 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
22985 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
22986 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
22987 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
22988 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
22989 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
22990 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
22991 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
22992 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
22993 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
22994 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
22995 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
22996 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
22997 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
22998 0x55, 0x21, 0x0c, 0x7d]);
22999 var mixCol = new Uint8Array(256);
23000 for (var i = 0; i < 256; i++) {
23001 if (i < 128) {
23002 mixCol[i] = i << 1;
23003 } else {
23004 mixCol[i] = (i << 1) ^ 0x1b;
23005 }
23006 }
23007 var mix = new Uint32Array([
23008 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927,
23009 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45,
23010 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb,
23011 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381,
23012 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf,
23013 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66,
23014 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28,
23015 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012,
23016 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
23017 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e,
23018 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd,
23019 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7,
23020 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89,
23021 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b,
23022 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815,
23023 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f,
23024 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa,
23025 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8,
23026 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36,
23027 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
23028 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742,
23029 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea,
23030 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4,
23031 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e,
23032 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360,
23033 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502,
23034 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87,
23035 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd,
23036 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3,
23037 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621,
23038 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
23039 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55,
23040 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26,
23041 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844,
23042 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba,
23043 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480,
23044 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce,
23045 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67,
23046 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929,
23047 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713,
23048 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed,
23049 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
23050 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
23051
23052 function expandKey128(cipherKey) {
23053 var b = 176, result = new Uint8Array(b);
23054 result.set(cipherKey);
23055 for (var j = 16, i = 1; j < b; ++i) {
23056 // RotWord
23057 var t1 = result[j - 3], t2 = result[j - 2],
23058 t3 = result[j - 1], t4 = result[j - 4];
23059 // SubWord
23060 t1 = s[t1];
23061 t2 = s[t2];
23062 t3 = s[t3];
23063 t4 = s[t4];
23064 // Rcon
23065 t1 = t1 ^ rcon[i];
23066 for (var n = 0; n < 4; ++n) {
23067 result[j] = (t1 ^= result[j - 16]);
23068 j++;
23069 result[j] = (t2 ^= result[j - 16]);
23070 j++;
23071 result[j] = (t3 ^= result[j - 16]);
23072 j++;
23073 result[j] = (t4 ^= result[j - 16]);
23074 j++;
23075 }
23076 }
23077 return result;
23078 }
23079
23080 function decrypt128(input, key) {
23081 var state = new Uint8Array(16);
23082 state.set(input);
23083 var i, j, k;
23084 var t, u, v;
23085 // AddRoundKey
23086 for (j = 0, k = 160; j < 16; ++j, ++k) {
23087 state[j] ^= key[k];
23088 }
23089 for (i = 9; i >= 1; --i) {
23090 // InvShiftRows
23091 t = state[13];
23092 state[13] = state[9];
23093 state[9] = state[5];
23094 state[5] = state[1];
23095 state[1] = t;
23096 t = state[14];
23097 u = state[10];
23098 state[14] = state[6];
23099 state[10] = state[2];
23100 state[6] = t;
23101 state[2] = u;
23102 t = state[15];
23103 u = state[11];
23104 v = state[7];
23105 state[15] = state[3];
23106 state[11] = t;
23107 state[7] = u;
23108 state[3] = v;
23109 // InvSubBytes
23110 for (j = 0; j < 16; ++j) {
23111 state[j] = inv_s[state[j]];
23112 }
23113 // AddRoundKey
23114 for (j = 0, k = i * 16; j < 16; ++j, ++k) {
23115 state[j] ^= key[k];
23116 }
23117 // InvMixColumns
23118 for (j = 0; j < 16; j += 4) {
23119 var s0 = mix[state[j]], s1 = mix[state[j + 1]],
23120 s2 = mix[state[j + 2]], s3 = mix[state[j + 3]];
23121 t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^
23122 (s3 >>> 24) ^ (s3 << 8));
23123 state[j] = (t >>> 24) & 0xFF;
23124 state[j + 1] = (t >> 16) & 0xFF;
23125 state[j + 2] = (t >> 8) & 0xFF;
23126 state[j + 3] = t & 0xFF;
23127 }
23128 }
23129 // InvShiftRows
23130 t = state[13];
23131 state[13] = state[9];
23132 state[9] = state[5];
23133 state[5] = state[1];
23134 state[1] = t;
23135 t = state[14];
23136 u = state[10];
23137 state[14] = state[6];
23138 state[10] = state[2];
23139 state[6] = t;
23140 state[2] = u;
23141 t = state[15];
23142 u = state[11];
23143 v = state[7];
23144 state[15] = state[3];
23145 state[11] = t;
23146 state[7] = u;
23147 state[3] = v;
23148 for (j = 0; j < 16; ++j) {
23149 // InvSubBytes
23150 state[j] = inv_s[state[j]];
23151 // AddRoundKey
23152 state[j] ^= key[j];
23153 }
23154 return state;
23155 }
23156
23157 function encrypt128(input, key) {
23158 var t, u, v, k;
23159 var state = new Uint8Array(16);
23160 state.set(input);
23161 for (j = 0; j < 16; ++j) {
23162 // AddRoundKey
23163 state[j] ^= key[j];
23164 }
23165
23166 for (i = 1; i < 10; i++) {
23167 //SubBytes
23168 for (j = 0; j < 16; ++j) {
23169 state[j] = s[state[j]];
23170 }
23171 //ShiftRows
23172 v = state[1];
23173 state[1] = state[5];
23174 state[5] = state[9];
23175 state[9] = state[13];
23176 state[13] = v;
23177 v = state[2];
23178 u = state[6];
23179 state[2] = state[10];
23180 state[6] = state[14];
23181 state[10] = v;
23182 state[14] = u;
23183 v = state[3];
23184 u = state[7];
23185 t = state[11];
23186 state[3] = state[15];
23187 state[7] = v;
23188 state[11] = u;
23189 state[15] = t;
23190 //MixColumns
23191 for (var j = 0; j < 16; j += 4) {
23192 var s0 = state[j + 0], s1 = state[j + 1];
23193 var s2 = state[j + 2], s3 = state[j + 3];
23194 t = s0 ^ s1 ^ s2 ^ s3;
23195 state[j + 0] ^= t ^ mixCol[s0 ^ s1];
23196 state[j + 1] ^= t ^ mixCol[s1 ^ s2];
23197 state[j + 2] ^= t ^ mixCol[s2 ^ s3];
23198 state[j + 3] ^= t ^ mixCol[s3 ^ s0];
23199 }
23200 //AddRoundKey
23201 for (j = 0, k = i * 16; j < 16; ++j, ++k) {
23202 state[j] ^= key[k];
23203 }
23204 }
23205
23206 //SubBytes
23207 for (j = 0; j < 16; ++j) {
23208 state[j] = s[state[j]];
23209 }
23210 //ShiftRows
23211 v = state[1];
23212 state[1] = state[5];
23213 state[5] = state[9];
23214 state[9] = state[13];
23215 state[13] = v;
23216 v = state[2];
23217 u = state[6];
23218 state[2] = state[10];
23219 state[6] = state[14];
23220 state[10] = v;
23221 state[14] = u;
23222 v = state[3];
23223 u = state[7];
23224 t = state[11];
23225 state[3] = state[15];
23226 state[7] = v;
23227 state[11] = u;
23228 state[15] = t;
23229 //AddRoundKey
23230 for (j = 0, k = 160; j < 16; ++j, ++k) {
23231 state[j] ^= key[k];
23232 }
23233 return state;
23234 }
23235
23236 function AES128Cipher(key) {
23237 this.key = expandKey128(key);
23238 this.buffer = new Uint8Array(16);
23239 this.bufferPosition = 0;
23240 }
23241
23242 function decryptBlock2(data, finalize) {
23243 var i, j, ii, sourceLength = data.length,
23244 buffer = this.buffer, bufferLength = this.bufferPosition,
23245 result = [], iv = this.iv;
23246 for (i = 0; i < sourceLength; ++i) {
23247 buffer[bufferLength] = data[i];
23248 ++bufferLength;
23249 if (bufferLength < 16) {
23250 continue;
23251 }
23252 // buffer is full, decrypting
23253 var plain = decrypt128(buffer, this.key);
23254 // xor-ing the IV vector to get plain text
23255 for (j = 0; j < 16; ++j) {
23256 plain[j] ^= iv[j];
23257 }
23258 iv = buffer;
23259 result.push(plain);
23260 buffer = new Uint8Array(16);
23261 bufferLength = 0;
23262 }
23263 // saving incomplete buffer
23264 this.buffer = buffer;
23265 this.bufferLength = bufferLength;
23266 this.iv = iv;
23267 if (result.length === 0) {
23268 return new Uint8Array([]);
23269 }
23270 // combining plain text blocks into one
23271 var outputLength = 16 * result.length;
23272 if (finalize) {
23273 // undo a padding that is described in RFC 2898
23274 var lastBlock = result[result.length - 1];
23275 var psLen = lastBlock[15];
23276 if (psLen <= 16) {
23277 for (i = 15, ii = 16 - psLen; i >= ii; --i) {
23278 if (lastBlock[i] !== psLen) {
23279 // Invalid padding, assume that the block has no padding.
23280 psLen = 0;
23281 break;
23282 }
23283 }
23284 outputLength -= psLen;
23285 result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
23286 }
23287 }
23288 var output = new Uint8Array(outputLength);
23289 for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
23290 output.set(result[i], j);
23291 }
23292 return output;
23293 }
23294
23295 AES128Cipher.prototype = {
23296 decryptBlock: function AES128Cipher_decryptBlock(data, finalize) {
23297 var i, sourceLength = data.length;
23298 var buffer = this.buffer, bufferLength = this.bufferPosition;
23299 // waiting for IV values -- they are at the start of the stream
23300 for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {
23301 buffer[bufferLength] = data[i];
23302 }
23303 if (bufferLength < 16) {
23304 // need more data
23305 this.bufferLength = bufferLength;
23306 return new Uint8Array([]);
23307 }
23308 this.iv = buffer;
23309 this.buffer = new Uint8Array(16);
23310 this.bufferLength = 0;
23311 // starting decryption
23312 this.decryptBlock = decryptBlock2;
23313 return this.decryptBlock(data.subarray(16), finalize);
23314 },
23315 encrypt: function AES128Cipher_encrypt(data, iv) {
23316 var i, j, ii, sourceLength = data.length,
23317 buffer = this.buffer, bufferLength = this.bufferPosition,
23318 result = [];
23319 if (!iv) {
23320 iv = new Uint8Array(16);
23321 }
23322 for (i = 0; i < sourceLength; ++i) {
23323 buffer[bufferLength] = data[i];
23324 ++bufferLength;
23325 if (bufferLength < 16) {
23326 continue;
23327 }
23328 for (j = 0; j < 16; ++j) {
23329 buffer[j] ^= iv[j];
23330 }
23331
23332 // buffer is full, encrypting
23333 var cipher = encrypt128(buffer, this.key);
23334 iv = cipher;
23335 result.push(cipher);
23336 buffer = new Uint8Array(16);
23337 bufferLength = 0;
23338 }
23339 // saving incomplete buffer
23340 this.buffer = buffer;
23341 this.bufferLength = bufferLength;
23342 this.iv = iv;
23343 if (result.length === 0) {
23344 return new Uint8Array([]);
23345 }
23346 // combining plain text blocks into one
23347 var outputLength = 16 * result.length;
23348 var output = new Uint8Array(outputLength);
23349 for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
23350 output.set(result[i], j);
23351 }
23352 return output;
23353 }
23354 };
23355
23356 return AES128Cipher;
23357})();
23358
23359var AES256Cipher = (function AES256CipherClosure() {
23360 var rcon = new Uint8Array([
23361 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
23362 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
23363 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
23364 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
23365 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
23366 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,
23367 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
23368 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
23369 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,
23370 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e,
23371 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
23372 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
23373 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02,
23374 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
23375 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
23376 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
23377 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb,
23378 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
23379 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
23380 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
23381 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
23382 0x74, 0xe8, 0xcb, 0x8d]);
23383
23384 var s = new Uint8Array([
23385 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
23386 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
23387 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
23388 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
23389 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
23390 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
23391 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
23392 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
23393 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
23394 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
23395 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
23396 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
23397 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
23398 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
23399 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
23400 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
23401 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
23402 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
23403 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
23404 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
23405 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
23406 0xb0, 0x54, 0xbb, 0x16]);
23407
23408 var inv_s = new Uint8Array([
23409 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
23410 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
23411 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
23412 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
23413 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
23414 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
23415 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
23416 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
23417 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
23418 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
23419 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
23420 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
23421 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
23422 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
23423 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
23424 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
23425 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
23426 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
23427 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
23428 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
23429 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
23430 0x55, 0x21, 0x0c, 0x7d]);
23431
23432 var mixCol = new Uint8Array(256);
23433 for (var i = 0; i < 256; i++) {
23434 if (i < 128) {
23435 mixCol[i] = i << 1;
23436 } else {
23437 mixCol[i] = (i << 1) ^ 0x1b;
23438 }
23439 }
23440 var mix = new Uint32Array([
23441 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927,
23442 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45,
23443 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb,
23444 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381,
23445 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf,
23446 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66,
23447 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28,
23448 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012,
23449 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
23450 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e,
23451 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd,
23452 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7,
23453 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89,
23454 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b,
23455 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815,
23456 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f,
23457 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa,
23458 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8,
23459 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36,
23460 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
23461 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742,
23462 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea,
23463 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4,
23464 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e,
23465 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360,
23466 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502,
23467 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87,
23468 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd,
23469 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3,
23470 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621,
23471 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
23472 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55,
23473 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26,
23474 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844,
23475 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba,
23476 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480,
23477 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce,
23478 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67,
23479 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929,
23480 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713,
23481 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed,
23482 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
23483 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
23484
23485 function expandKey256(cipherKey) {
23486 var b = 240, result = new Uint8Array(b);
23487 var r = 1;
23488
23489 result.set(cipherKey);
23490 for (var j = 32, i = 1; j < b; ++i) {
23491 if (j % 32 === 16) {
23492 t1 = s[t1];
23493 t2 = s[t2];
23494 t3 = s[t3];
23495 t4 = s[t4];
23496 } else if (j % 32 === 0) {
23497 // RotWord
23498 var t1 = result[j - 3], t2 = result[j - 2],
23499 t3 = result[j - 1], t4 = result[j - 4];
23500 // SubWord
23501 t1 = s[t1];
23502 t2 = s[t2];
23503 t3 = s[t3];
23504 t4 = s[t4];
23505 // Rcon
23506 t1 = t1 ^ r;
23507 if ((r <<= 1) >= 256) {
23508 r = (r ^ 0x1b) & 0xFF;
23509 }
23510 }
23511
23512 for (var n = 0; n < 4; ++n) {
23513 result[j] = (t1 ^= result[j - 32]);
23514 j++;
23515 result[j] = (t2 ^= result[j - 32]);
23516 j++;
23517 result[j] = (t3 ^= result[j - 32]);
23518 j++;
23519 result[j] = (t4 ^= result[j - 32]);
23520 j++;
23521 }
23522 }
23523 return result;
23524 }
23525
23526 function decrypt256(input, key) {
23527 var state = new Uint8Array(16);
23528 state.set(input);
23529 var i, j, k;
23530 var t, u, v;
23531 // AddRoundKey
23532 for (j = 0, k = 224; j < 16; ++j, ++k) {
23533 state[j] ^= key[k];
23534 }
23535 for (i = 13; i >= 1; --i) {
23536 // InvShiftRows
23537 t = state[13];
23538 state[13] = state[9];
23539 state[9] = state[5];
23540 state[5] = state[1];
23541 state[1] = t;
23542 t = state[14];
23543 u = state[10];
23544 state[14] = state[6];
23545 state[10] = state[2];
23546 state[6] = t;
23547 state[2] = u;
23548 t = state[15];
23549 u = state[11];
23550 v = state[7];
23551 state[15] = state[3];
23552 state[11] = t;
23553 state[7] = u;
23554 state[3] = v;
23555 // InvSubBytes
23556 for (j = 0; j < 16; ++j) {
23557 state[j] = inv_s[state[j]];
23558 }
23559 // AddRoundKey
23560 for (j = 0, k = i * 16; j < 16; ++j, ++k) {
23561 state[j] ^= key[k];
23562 }
23563 // InvMixColumns
23564 for (j = 0; j < 16; j += 4) {
23565 var s0 = mix[state[j]], s1 = mix[state[j + 1]],
23566 s2 = mix[state[j + 2]], s3 = mix[state[j + 3]];
23567 t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^
23568 (s3 >>> 24) ^ (s3 << 8));
23569 state[j] = (t >>> 24) & 0xFF;
23570 state[j + 1] = (t >> 16) & 0xFF;
23571 state[j + 2] = (t >> 8) & 0xFF;
23572 state[j + 3] = t & 0xFF;
23573 }
23574 }
23575 // InvShiftRows
23576 t = state[13];
23577 state[13] = state[9];
23578 state[9] = state[5];
23579 state[5] = state[1];
23580 state[1] = t;
23581 t = state[14];
23582 u = state[10];
23583 state[14] = state[6];
23584 state[10] = state[2];
23585 state[6] = t;
23586 state[2] = u;
23587 t = state[15];
23588 u = state[11];
23589 v = state[7];
23590 state[15] = state[3];
23591 state[11] = t;
23592 state[7] = u;
23593 state[3] = v;
23594 for (j = 0; j < 16; ++j) {
23595 // InvSubBytes
23596 state[j] = inv_s[state[j]];
23597 // AddRoundKey
23598 state[j] ^= key[j];
23599 }
23600 return state;
23601 }
23602
23603 function encrypt256(input, key) {
23604 var t, u, v, k;
23605 var state = new Uint8Array(16);
23606 state.set(input);
23607 for (j = 0; j < 16; ++j) {
23608 // AddRoundKey
23609 state[j] ^= key[j];
23610 }
23611
23612 for (i = 1; i < 14; i++) {
23613 //SubBytes
23614 for (j = 0; j < 16; ++j) {
23615 state[j] = s[state[j]];
23616 }
23617 //ShiftRows
23618 v = state[1];
23619 state[1] = state[5];
23620 state[5] = state[9];
23621 state[9] = state[13];
23622 state[13] = v;
23623 v = state[2];
23624 u = state[6];
23625 state[2] = state[10];
23626 state[6] = state[14];
23627 state[10] = v;
23628 state[14] = u;
23629 v = state[3];
23630 u = state[7];
23631 t = state[11];
23632 state[3] = state[15];
23633 state[7] = v;
23634 state[11] = u;
23635 state[15] = t;
23636 //MixColumns
23637 for (var j = 0; j < 16; j += 4) {
23638 var s0 = state[j + 0], s1 = state[j + 1];
23639 var s2 = state[j + 2], s3 = state[j + 3];
23640 t = s0 ^ s1 ^ s2 ^ s3;
23641 state[j + 0] ^= t ^ mixCol[s0 ^ s1];
23642 state[j + 1] ^= t ^ mixCol[s1 ^ s2];
23643 state[j + 2] ^= t ^ mixCol[s2 ^ s3];
23644 state[j + 3] ^= t ^ mixCol[s3 ^ s0];
23645 }
23646 //AddRoundKey
23647 for (j = 0, k = i * 16; j < 16; ++j, ++k) {
23648 state[j] ^= key[k];
23649 }
23650 }
23651
23652 //SubBytes
23653 for (j = 0; j < 16; ++j) {
23654 state[j] = s[state[j]];
23655 }
23656 //ShiftRows
23657 v = state[1];
23658 state[1] = state[5];
23659 state[5] = state[9];
23660 state[9] = state[13];
23661 state[13] = v;
23662 v = state[2];
23663 u = state[6];
23664 state[2] = state[10];
23665 state[6] = state[14];
23666 state[10] = v;
23667 state[14] = u;
23668 v = state[3];
23669 u = state[7];
23670 t = state[11];
23671 state[3] = state[15];
23672 state[7] = v;
23673 state[11] = u;
23674 state[15] = t;
23675 //AddRoundKey
23676 for (j = 0, k = 224; j < 16; ++j, ++k) {
23677 state[j] ^= key[k];
23678 }
23679
23680 return state;
23681
23682 }
23683
23684 function AES256Cipher(key) {
23685 this.key = expandKey256(key);
23686 this.buffer = new Uint8Array(16);
23687 this.bufferPosition = 0;
23688 }
23689
23690 function decryptBlock2(data, finalize) {
23691 var i, j, ii, sourceLength = data.length,
23692 buffer = this.buffer, bufferLength = this.bufferPosition,
23693 result = [], iv = this.iv;
23694
23695 for (i = 0; i < sourceLength; ++i) {
23696 buffer[bufferLength] = data[i];
23697 ++bufferLength;
23698 if (bufferLength < 16) {
23699 continue;
23700 }
23701 // buffer is full, decrypting
23702 var plain = decrypt256(buffer, this.key);
23703 // xor-ing the IV vector to get plain text
23704 for (j = 0; j < 16; ++j) {
23705 plain[j] ^= iv[j];
23706 }
23707 iv = buffer;
23708 result.push(plain);
23709 buffer = new Uint8Array(16);
23710 bufferLength = 0;
23711 }
23712 // saving incomplete buffer
23713 this.buffer = buffer;
23714 this.bufferLength = bufferLength;
23715 this.iv = iv;
23716 if (result.length === 0) {
23717 return new Uint8Array([]);
23718 }
23719 // combining plain text blocks into one
23720 var outputLength = 16 * result.length;
23721 if (finalize) {
23722 // undo a padding that is described in RFC 2898
23723 var lastBlock = result[result.length - 1];
23724 var psLen = lastBlock[15];
23725 if (psLen <= 16) {
23726 for (i = 15, ii = 16 - psLen; i >= ii; --i) {
23727 if (lastBlock[i] !== psLen) {
23728 // Invalid padding, assume that the block has no padding.
23729 psLen = 0;
23730 break;
23731 }
23732 }
23733 outputLength -= psLen;
23734 result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
23735 }
23736 }
23737 var output = new Uint8Array(outputLength);
23738 for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
23739 output.set(result[i], j);
23740 }
23741 return output;
23742
23743 }
23744
23745 AES256Cipher.prototype = {
23746 decryptBlock: function AES256Cipher_decryptBlock(data, finalize, iv) {
23747 var i, sourceLength = data.length;
23748 var buffer = this.buffer, bufferLength = this.bufferPosition;
23749 // if not supplied an IV wait for IV values
23750 // they are at the start of the stream
23751 if (iv) {
23752 this.iv = iv;
23753 } else {
23754 for (i = 0; bufferLength < 16 &&
23755 i < sourceLength; ++i, ++bufferLength) {
23756 buffer[bufferLength] = data[i];
23757 }
23758 if (bufferLength < 16) {
23759 //need more data
23760 this.bufferLength = bufferLength;
23761 return new Uint8Array([]);
23762 }
23763 this.iv = buffer;
23764 data = data.subarray(16);
23765 }
23766 this.buffer = new Uint8Array(16);
23767 this.bufferLength = 0;
23768 // starting decryption
23769 this.decryptBlock = decryptBlock2;
23770 return this.decryptBlock(data, finalize);
23771 },
23772 encrypt: function AES256Cipher_encrypt(data, iv) {
23773 var i, j, ii, sourceLength = data.length,
23774 buffer = this.buffer, bufferLength = this.bufferPosition,
23775 result = [];
23776 if (!iv) {
23777 iv = new Uint8Array(16);
23778 }
23779 for (i = 0; i < sourceLength; ++i) {
23780 buffer[bufferLength] = data[i];
23781 ++bufferLength;
23782 if (bufferLength < 16) {
23783 continue;
23784 }
23785 for (j = 0; j < 16; ++j) {
23786 buffer[j] ^= iv[j];
23787 }
23788
23789 // buffer is full, encrypting
23790 var cipher = encrypt256(buffer, this.key);
23791 this.iv = cipher;
23792 result.push(cipher);
23793 buffer = new Uint8Array(16);
23794 bufferLength = 0;
23795 }
23796 // saving incomplete buffer
23797 this.buffer = buffer;
23798 this.bufferLength = bufferLength;
23799 this.iv = iv;
23800 if (result.length === 0) {
23801 return new Uint8Array([]);
23802 }
23803 // combining plain text blocks into one
23804 var outputLength = 16 * result.length;
23805 var output = new Uint8Array(outputLength);
23806 for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
23807 output.set(result[i], j);
23808 }
23809 return output;
23810 }
23811 };
23812
23813 return AES256Cipher;
23814})();
23815
23816var PDF17 = (function PDF17Closure() {
23817
23818 function compareByteArrays(array1, array2) {
23819 if (array1.length !== array2.length) {
23820 return false;
23821 }
23822 for (var i = 0; i < array1.length; i++) {
23823 if (array1[i] !== array2[i]) {
23824 return false;
23825 }
23826 }
23827 return true;
23828 }
23829
23830 function PDF17() {
23831 }
23832
23833 PDF17.prototype = {
23834 checkOwnerPassword: function PDF17_checkOwnerPassword(password,
23835 ownerValidationSalt,
23836 userBytes,
23837 ownerPassword) {
23838 var hashData = new Uint8Array(password.length + 56);
23839 hashData.set(password, 0);
23840 hashData.set(ownerValidationSalt, password.length);
23841 hashData.set(userBytes, password.length + ownerValidationSalt.length);
23842 var result = calculateSHA256(hashData, 0, hashData.length);
23843 return compareByteArrays(result, ownerPassword);
23844 },
23845 checkUserPassword: function PDF17_checkUserPassword(password,
23846 userValidationSalt,
23847 userPassword) {
23848 var hashData = new Uint8Array(password.length + 8);
23849 hashData.set(password, 0);
23850 hashData.set(userValidationSalt, password.length);
23851 var result = calculateSHA256(hashData, 0, hashData.length);
23852 return compareByteArrays(result, userPassword);
23853 },
23854 getOwnerKey: function PDF17_getOwnerKey(password, ownerKeySalt, userBytes,
23855 ownerEncryption) {
23856 var hashData = new Uint8Array(password.length + 56);
23857 hashData.set(password, 0);
23858 hashData.set(ownerKeySalt, password.length);
23859 hashData.set(userBytes, password.length + ownerKeySalt.length);
23860 var key = calculateSHA256(hashData, 0, hashData.length);
23861 var cipher = new AES256Cipher(key);
23862 return cipher.decryptBlock(ownerEncryption,
23863 false,
23864 new Uint8Array(16));
23865
23866 },
23867 getUserKey: function PDF17_getUserKey(password, userKeySalt,
23868 userEncryption) {
23869 var hashData = new Uint8Array(password.length + 8);
23870 hashData.set(password, 0);
23871 hashData.set(userKeySalt, password.length);
23872 //key is the decryption key for the UE string
23873 var key = calculateSHA256(hashData, 0, hashData.length);
23874 var cipher = new AES256Cipher(key);
23875 return cipher.decryptBlock(userEncryption,
23876 false,
23877 new Uint8Array(16));
23878 }
23879 };
23880 return PDF17;
23881})();
23882
23883var PDF20 = (function PDF20Closure() {
23884
23885 function concatArrays(array1, array2) {
23886 var t = new Uint8Array(array1.length + array2.length);
23887 t.set(array1, 0);
23888 t.set(array2, array1.length);
23889 return t;
23890 }
23891
23892 function calculatePDF20Hash(password, input, userBytes) {
23893 //This refers to Algorithm 2.B as defined in ISO 32000-2
23894 var k = calculateSHA256(input, 0, input.length).subarray(0, 32);
23895 var e = [0];
23896 var i = 0;
23897 while (i < 64 || e[e.length - 1] > i - 32) {
23898 var arrayLength = password.length + k.length + userBytes.length;
23899
23900 var k1 = new Uint8Array(arrayLength * 64);
23901 var array = concatArrays(password, k);
23902 array = concatArrays(array, userBytes);
23903 for (var j = 0, pos = 0; j < 64; j++, pos += arrayLength) {
23904 k1.set(array, pos);
23905 }
23906 //AES128 CBC NO PADDING with
23907 //first 16 bytes of k as the key and the second 16 as the iv.
23908 var cipher = new AES128Cipher(k.subarray(0, 16));
23909 e = cipher.encrypt(k1, k.subarray(16, 32));
23910 //Now we have to take the first 16 bytes of an unsigned
23911 //big endian integer... and compute the remainder
23912 //modulo 3.... That is a fairly large number and
23913 //JavaScript isn't going to handle that well...
23914 //So we're using a trick that allows us to perform
23915 //modulo math byte by byte
23916 var remainder = 0;
23917 for (var z = 0; z < 16; z++) {
23918 remainder *= (256 % 3);
23919 remainder %= 3;
23920 remainder += ((e[z] >>> 0) % 3);
23921 remainder %= 3;
23922 }
23923 if (remainder === 0) {
23924 k = calculateSHA256(e, 0, e.length);
23925 }
23926 else if (remainder === 1) {
23927 k = calculateSHA384(e, 0, e.length);
23928 }
23929 else if (remainder === 2) {
23930 k = calculateSHA512(e, 0, e.length);
23931 }
23932 i++;
23933 }
23934 return k.subarray(0, 32);
23935 }
23936
23937 function PDF20() {
23938 }
23939
23940 function compareByteArrays(array1, array2) {
23941 if (array1.length !== array2.length) {
23942 return false;
23943 }
23944 for (var i = 0; i < array1.length; i++) {
23945 if (array1[i] !== array2[i]) {
23946 return false;
23947 }
23948 }
23949 return true;
23950 }
23951
23952 PDF20.prototype = {
23953 hash: function PDF20_hash(password, concatBytes, userBytes) {
23954 return calculatePDF20Hash(password, concatBytes, userBytes);
23955 },
23956 checkOwnerPassword: function PDF20_checkOwnerPassword(password,
23957 ownerValidationSalt,
23958 userBytes,
23959 ownerPassword) {
23960 var hashData = new Uint8Array(password.length + 56);
23961 hashData.set(password, 0);
23962 hashData.set(ownerValidationSalt, password.length);
23963 hashData.set(userBytes, password.length + ownerValidationSalt.length);
23964 var result = calculatePDF20Hash(password, hashData, userBytes);
23965 return compareByteArrays(result, ownerPassword);
23966 },
23967 checkUserPassword: function PDF20_checkUserPassword(password,
23968 userValidationSalt,
23969 userPassword) {
23970 var hashData = new Uint8Array(password.length + 8);
23971 hashData.set(password, 0);
23972 hashData.set(userValidationSalt, password.length);
23973 var result = calculatePDF20Hash(password, hashData, []);
23974 return compareByteArrays(result, userPassword);
23975 },
23976 getOwnerKey: function PDF20_getOwnerKey(password, ownerKeySalt, userBytes,
23977 ownerEncryption) {
23978 var hashData = new Uint8Array(password.length + 56);
23979 hashData.set(password, 0);
23980 hashData.set(ownerKeySalt, password.length);
23981 hashData.set(userBytes, password.length + ownerKeySalt.length);
23982 var key = calculatePDF20Hash(password, hashData, userBytes);
23983 var cipher = new AES256Cipher(key);
23984 return cipher.decryptBlock(ownerEncryption,
23985 false,
23986 new Uint8Array(16));
23987
23988 },
23989 getUserKey: function PDF20_getUserKey(password, userKeySalt,
23990 userEncryption) {
23991 var hashData = new Uint8Array(password.length + 8);
23992 hashData.set(password, 0);
23993 hashData.set(userKeySalt, password.length);
23994 //key is the decryption key for the UE string
23995 var key = calculatePDF20Hash(password, hashData, []);
23996 var cipher = new AES256Cipher(key);
23997 return cipher.decryptBlock(userEncryption,
23998 false,
23999 new Uint8Array(16));
24000 }
24001 };
24002 return PDF20;
24003})();
24004
24005var CipherTransform = (function CipherTransformClosure() {
24006 function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
24007 this.stringCipherConstructor = stringCipherConstructor;
24008 this.streamCipherConstructor = streamCipherConstructor;
24009 }
24010
24011 CipherTransform.prototype = {
24012 createStream: function CipherTransform_createStream(stream, length) {
24013 var cipher = new this.streamCipherConstructor();
24014 return new DecryptStream(stream, length,
24015 function cipherTransformDecryptStream(data, finalize) {
24016 return cipher.decryptBlock(data, finalize);
24017 }
24018 );
24019 },
24020 decryptString: function CipherTransform_decryptString(s) {
24021 var cipher = new this.stringCipherConstructor();
24022 var data = stringToBytes(s);
24023 data = cipher.decryptBlock(data, true);
24024 return bytesToString(data);
24025 }
24026 };
24027 return CipherTransform;
24028})();
24029
24030var CipherTransformFactory = (function CipherTransformFactoryClosure() {
24031 var defaultPasswordBytes = new Uint8Array([
24032 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
24033 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
24034 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
24035 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
24036
24037 function createEncryptionKey20(revision, password, ownerPassword,
24038 ownerValidationSalt, ownerKeySalt, uBytes,
24039 userPassword, userValidationSalt, userKeySalt,
24040 ownerEncryption, userEncryption, perms) {
24041 if (password) {
24042 var passwordLength = Math.min(127, password.length);
24043 password = password.subarray(0, passwordLength);
24044 } else {
24045 password = [];
24046 }
24047 var pdfAlgorithm;
24048 if (revision === 6) {
24049 pdfAlgorithm = new PDF20();
24050 } else {
24051 pdfAlgorithm = new PDF17();
24052 }
24053
24054 if (pdfAlgorithm.checkUserPassword(password, userValidationSalt,
24055 userPassword)) {
24056 return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption);
24057 } else if (password.length && pdfAlgorithm.checkOwnerPassword(password,
24058 ownerValidationSalt,
24059 uBytes,
24060 ownerPassword)) {
24061 return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes,
24062 ownerEncryption);
24063 }
24064
24065 return null;
24066 }
24067
24068 function prepareKeyData(fileId, password, ownerPassword, userPassword,
24069 flags, revision, keyLength, encryptMetadata) {
24070 var hashDataSize = 40 + ownerPassword.length + fileId.length;
24071 var hashData = new Uint8Array(hashDataSize), i = 0, j, n;
24072 if (password) {
24073 n = Math.min(32, password.length);
24074 for (; i < n; ++i) {
24075 hashData[i] = password[i];
24076 }
24077 }
24078 j = 0;
24079 while (i < 32) {
24080 hashData[i++] = defaultPasswordBytes[j++];
24081 }
24082 // as now the padded password in the hashData[0..i]
24083 for (j = 0, n = ownerPassword.length; j < n; ++j) {
24084 hashData[i++] = ownerPassword[j];
24085 }
24086 hashData[i++] = flags & 0xFF;
24087 hashData[i++] = (flags >> 8) & 0xFF;
24088 hashData[i++] = (flags >> 16) & 0xFF;
24089 hashData[i++] = (flags >>> 24) & 0xFF;
24090 for (j = 0, n = fileId.length; j < n; ++j) {
24091 hashData[i++] = fileId[j];
24092 }
24093 if (revision >= 4 && !encryptMetadata) {
24094 hashData[i++] = 0xFF;
24095 hashData[i++] = 0xFF;
24096 hashData[i++] = 0xFF;
24097 hashData[i++] = 0xFF;
24098 }
24099 var hash = calculateMD5(hashData, 0, i);
24100 var keyLengthInBytes = keyLength >> 3;
24101 if (revision >= 3) {
24102 for (j = 0; j < 50; ++j) {
24103 hash = calculateMD5(hash, 0, keyLengthInBytes);
24104 }
24105 }
24106 var encryptionKey = hash.subarray(0, keyLengthInBytes);
24107 var cipher, checkData;
24108
24109 if (revision >= 3) {
24110 for (i = 0; i < 32; ++i) {
24111 hashData[i] = defaultPasswordBytes[i];
24112 }
24113 for (j = 0, n = fileId.length; j < n; ++j) {
24114 hashData[i++] = fileId[j];
24115 }
24116 cipher = new ARCFourCipher(encryptionKey);
24117 checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
24118 n = encryptionKey.length;
24119 var derivedKey = new Uint8Array(n), k;
24120 for (j = 1; j <= 19; ++j) {
24121 for (k = 0; k < n; ++k) {
24122 derivedKey[k] = encryptionKey[k] ^ j;
24123 }
24124 cipher = new ARCFourCipher(derivedKey);
24125 checkData = cipher.encryptBlock(checkData);
24126 }
24127 for (j = 0, n = checkData.length; j < n; ++j) {
24128 if (userPassword[j] !== checkData[j]) {
24129 return null;
24130 }
24131 }
24132 } else {
24133 cipher = new ARCFourCipher(encryptionKey);
24134 checkData = cipher.encryptBlock(defaultPasswordBytes);
24135 for (j = 0, n = checkData.length; j < n; ++j) {
24136 if (userPassword[j] !== checkData[j]) {
24137 return null;
24138 }
24139 }
24140 }
24141 return encryptionKey;
24142 }
24143
24144 function decodeUserPassword(password, ownerPassword, revision, keyLength) {
24145 var hashData = new Uint8Array(32), i = 0, j, n;
24146 n = Math.min(32, password.length);
24147 for (; i < n; ++i) {
24148 hashData[i] = password[i];
24149 }
24150 j = 0;
24151 while (i < 32) {
24152 hashData[i++] = defaultPasswordBytes[j++];
24153 }
24154 var hash = calculateMD5(hashData, 0, i);
24155 var keyLengthInBytes = keyLength >> 3;
24156 if (revision >= 3) {
24157 for (j = 0; j < 50; ++j) {
24158 hash = calculateMD5(hash, 0, hash.length);
24159 }
24160 }
24161
24162 var cipher, userPassword;
24163 if (revision >= 3) {
24164 userPassword = ownerPassword;
24165 var derivedKey = new Uint8Array(keyLengthInBytes), k;
24166 for (j = 19; j >= 0; j--) {
24167 for (k = 0; k < keyLengthInBytes; ++k) {
24168 derivedKey[k] = hash[k] ^ j;
24169 }
24170 cipher = new ARCFourCipher(derivedKey);
24171 userPassword = cipher.encryptBlock(userPassword);
24172 }
24173 } else {
24174 cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes));
24175 userPassword = cipher.encryptBlock(ownerPassword);
24176 }
24177 return userPassword;
24178 }
24179
24180 var identityName = Name.get('Identity');
24181
24182 function CipherTransformFactory(dict, fileId, password) {
24183 var filter = dict.get('Filter');
24184 if (!isName(filter, 'Standard')) {
24185 error('unknown encryption method');
24186 }
24187 this.dict = dict;
24188 var algorithm = dict.get('V');
24189 if (!isInt(algorithm) ||
24190 (algorithm !== 1 && algorithm !== 2 && algorithm !== 4 &&
24191 algorithm !== 5)) {
24192 error('unsupported encryption algorithm');
24193 }
24194 this.algorithm = algorithm;
24195 var keyLength = dict.get('Length');
24196 if (!keyLength) {
24197 // Spec asks to rely on encryption dictionary's Length entry, however
24198 // some PDFs don't have it. Trying to recover.
24199 if (algorithm <= 3) {
24200 // For 1 and 2 it's fixed to 40-bit, for 3 40-bit is a minimal value.
24201 keyLength = 40;
24202 } else {
24203 // Trying to find default handler -- it usually has Length.
24204 var cfDict = dict.get('CF');
24205 var streamCryptoName = dict.get('StmF');
24206 if (isDict(cfDict) && isName(streamCryptoName)) {
24207 var handlerDict = cfDict.get(streamCryptoName.name);
24208 keyLength = (handlerDict && handlerDict.get('Length')) || 128;
24209 if (keyLength < 40) {
24210 // Sometimes it's incorrect value of bits, generators specify bytes.
24211 keyLength <<= 3;
24212 }
24213 }
24214 }
24215 }
24216 if (!isInt(keyLength) ||
24217 keyLength < 40 || (keyLength % 8) !== 0) {
24218 error('invalid key length');
24219 }
24220
24221 // prepare keys
24222 var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32);
24223 var userPassword = stringToBytes(dict.get('U')).subarray(0, 32);
24224 var flags = dict.get('P');
24225 var revision = dict.get('R');
24226 // meaningful when V is 4 or 5
24227 var encryptMetadata = ((algorithm === 4 || algorithm === 5) &&
24228 dict.get('EncryptMetadata') !== false);
24229 this.encryptMetadata = encryptMetadata;
24230
24231 var fileIdBytes = stringToBytes(fileId);
24232 var passwordBytes;
24233 if (password) {
24234 if (revision === 6) {
24235 try {
24236 password = utf8StringToString(password);
24237 } catch (ex) {
24238 warn('CipherTransformFactory: ' +
24239 'Unable to convert UTF8 encoded password.');
24240 }
24241 }
24242 passwordBytes = stringToBytes(password);
24243 }
24244
24245 var encryptionKey;
24246 if (algorithm !== 5) {
24247 encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
24248 ownerPassword, userPassword, flags,
24249 revision, keyLength, encryptMetadata);
24250 }
24251 else {
24252 var ownerValidationSalt = stringToBytes(dict.get('O')).subarray(32, 40);
24253 var ownerKeySalt = stringToBytes(dict.get('O')).subarray(40, 48);
24254 var uBytes = stringToBytes(dict.get('U')).subarray(0, 48);
24255 var userValidationSalt = stringToBytes(dict.get('U')).subarray(32, 40);
24256 var userKeySalt = stringToBytes(dict.get('U')).subarray(40, 48);
24257 var ownerEncryption = stringToBytes(dict.get('OE'));
24258 var userEncryption = stringToBytes(dict.get('UE'));
24259 var perms = stringToBytes(dict.get('Perms'));
24260 encryptionKey =
24261 createEncryptionKey20(revision, passwordBytes,
24262 ownerPassword, ownerValidationSalt,
24263 ownerKeySalt, uBytes,
24264 userPassword, userValidationSalt,
24265 userKeySalt, ownerEncryption,
24266 userEncryption, perms);
24267 }
24268 if (!encryptionKey && !password) {
24269 throw new PasswordException('No password given',
24270 PasswordResponses.NEED_PASSWORD);
24271 } else if (!encryptionKey && password) {
24272 // Attempting use the password as an owner password
24273 var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword,
24274 revision, keyLength);
24275 encryptionKey = prepareKeyData(fileIdBytes, decodedPassword,
24276 ownerPassword, userPassword, flags,
24277 revision, keyLength, encryptMetadata);
24278 }
24279
24280 if (!encryptionKey) {
24281 throw new PasswordException('Incorrect Password',
24282 PasswordResponses.INCORRECT_PASSWORD);
24283 }
24284
24285 this.encryptionKey = encryptionKey;
24286
24287 if (algorithm >= 4) {
24288 this.cf = dict.get('CF');
24289 this.stmf = dict.get('StmF') || identityName;
24290 this.strf = dict.get('StrF') || identityName;
24291 this.eff = dict.get('EFF') || this.stmf;
24292 }
24293 }
24294
24295 function buildObjectKey(num, gen, encryptionKey, isAes) {
24296 var key = new Uint8Array(encryptionKey.length + 9), i, n;
24297 for (i = 0, n = encryptionKey.length; i < n; ++i) {
24298 key[i] = encryptionKey[i];
24299 }
24300 key[i++] = num & 0xFF;
24301 key[i++] = (num >> 8) & 0xFF;
24302 key[i++] = (num >> 16) & 0xFF;
24303 key[i++] = gen & 0xFF;
24304 key[i++] = (gen >> 8) & 0xFF;
24305 if (isAes) {
24306 key[i++] = 0x73;
24307 key[i++] = 0x41;
24308 key[i++] = 0x6C;
24309 key[i++] = 0x54;
24310 }
24311 var hash = calculateMD5(key, 0, i);
24312 return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
24313 }
24314
24315 function buildCipherConstructor(cf, name, num, gen, key) {
24316 var cryptFilter = cf.get(name.name);
24317 var cfm;
24318 if (cryptFilter !== null && cryptFilter !== undefined) {
24319 cfm = cryptFilter.get('CFM');
24320 }
24321 if (!cfm || cfm.name === 'None') {
24322 return function cipherTransformFactoryBuildCipherConstructorNone() {
24323 return new NullCipher();
24324 };
24325 }
24326 if ('V2' === cfm.name) {
24327 return function cipherTransformFactoryBuildCipherConstructorV2() {
24328 return new ARCFourCipher(buildObjectKey(num, gen, key, false));
24329 };
24330 }
24331 if ('AESV2' === cfm.name) {
24332 return function cipherTransformFactoryBuildCipherConstructorAESV2() {
24333 return new AES128Cipher(buildObjectKey(num, gen, key, true));
24334 };
24335 }
24336 if ('AESV3' === cfm.name) {
24337 return function cipherTransformFactoryBuildCipherConstructorAESV3() {
24338 return new AES256Cipher(key);
24339 };
24340 }
24341 error('Unknown crypto method');
24342 }
24343
24344 CipherTransformFactory.prototype = {
24345 createCipherTransform:
24346 function CipherTransformFactory_createCipherTransform(num, gen) {
24347 if (this.algorithm === 4 || this.algorithm === 5) {
24348 return new CipherTransform(
24349 buildCipherConstructor(this.cf, this.stmf,
24350 num, gen, this.encryptionKey),
24351 buildCipherConstructor(this.cf, this.strf,
24352 num, gen, this.encryptionKey));
24353 }
24354 // algorithms 1 and 2
24355 var key = buildObjectKey(num, gen, this.encryptionKey, false);
24356 var cipherConstructor = function buildCipherCipherConstructor() {
24357 return new ARCFourCipher(key);
24358 };
24359 return new CipherTransform(cipherConstructor, cipherConstructor);
24360 }
24361 };
24362
24363 return CipherTransformFactory;
24364})();
24365
24366exports.AES128Cipher = AES128Cipher;
24367exports.AES256Cipher = AES256Cipher;
24368exports.ARCFourCipher = ARCFourCipher;
24369exports.CipherTransformFactory = CipherTransformFactory;
24370exports.PDF17 = PDF17;
24371exports.PDF20 = PDF20;
24372exports.calculateMD5 = calculateMD5;
24373exports.calculateSHA256 = calculateSHA256;
24374exports.calculateSHA384 = calculateSHA384;
24375exports.calculateSHA512 = calculateSHA512;
24376}));
24377
24378(function (root, factory) {
24379 {
24380 factory((root.pdfjsCoreFontRenderer = {}), root.pdfjsSharedUtil,
24381 root.pdfjsCoreStream, root.pdfjsCoreGlyphList, root.pdfjsCoreEncodings,
24382 root.pdfjsCoreCFFParser);
24383 }
24384}(this, function (exports, sharedUtil, coreStream, coreGlyphList,
24385 coreEncodings, coreCFFParser) {
24386
24387var Util = sharedUtil.Util;
24388var bytesToString = sharedUtil.bytesToString;
24389var error = sharedUtil.error;
24390var Stream = coreStream.Stream;
24391var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode;
24392var StandardEncoding = coreEncodings.StandardEncoding;
24393var CFFParser = coreCFFParser.CFFParser;
24394
24395var FontRendererFactory = (function FontRendererFactoryClosure() {
24396 function getLong(data, offset) {
24397 return (data[offset] << 24) | (data[offset + 1] << 16) |
24398 (data[offset + 2] << 8) | data[offset + 3];
24399 }
24400
24401 function getUshort(data, offset) {
24402 return (data[offset] << 8) | data[offset + 1];
24403 }
24404
24405 function parseCmap(data, start, end) {
24406 var offset = (getUshort(data, start + 2) === 1 ?
24407 getLong(data, start + 8) : getLong(data, start + 16));
24408 var format = getUshort(data, start + offset);
24409 var length, ranges, p, i;
24410 if (format === 4) {
24411 length = getUshort(data, start + offset + 2);
24412 var segCount = getUshort(data, start + offset + 6) >> 1;
24413 p = start + offset + 14;
24414 ranges = [];
24415 for (i = 0; i < segCount; i++, p += 2) {
24416 ranges[i] = {end: getUshort(data, p)};
24417 }
24418 p += 2;
24419 for (i = 0; i < segCount; i++, p += 2) {
24420 ranges[i].start = getUshort(data, p);
24421 }
24422 for (i = 0; i < segCount; i++, p += 2) {
24423 ranges[i].idDelta = getUshort(data, p);
24424 }
24425 for (i = 0; i < segCount; i++, p += 2) {
24426 var idOffset = getUshort(data, p);
24427 if (idOffset === 0) {
24428 continue;
24429 }
24430 ranges[i].ids = [];
24431 for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
24432 ranges[i].ids[j] = getUshort(data, p + idOffset);
24433 idOffset += 2;
24434 }
24435 }
24436 return ranges;
24437 } else if (format === 12) {
24438 length = getLong(data, start + offset + 4);
24439 var groups = getLong(data, start + offset + 12);
24440 p = start + offset + 16;
24441 ranges = [];
24442 for (i = 0; i < groups; i++) {
24443 ranges.push({
24444 start: getLong(data, p),
24445 end: getLong(data, p + 4),
24446 idDelta: getLong(data, p + 8) - getLong(data, p)
24447 });
24448 p += 12;
24449 }
24450 return ranges;
24451 }
24452 error('not supported cmap: ' + format);
24453 }
24454
24455 function parseCff(data, start, end, seacAnalysisEnabled) {
24456 var properties = {};
24457 var parser = new CFFParser(new Stream(data, start, end - start),
24458 properties, seacAnalysisEnabled);
24459 var cff = parser.parse();
24460 return {
24461 glyphs: cff.charStrings.objects,
24462 subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex &&
24463 cff.topDict.privateDict.subrsIndex.objects),
24464 gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects
24465 };
24466 }
24467
24468 function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
24469 var itemSize, itemDecode;
24470 if (isGlyphLocationsLong) {
24471 itemSize = 4;
24472 itemDecode = function fontItemDecodeLong(data, offset) {
24473 return (data[offset] << 24) | (data[offset + 1] << 16) |
24474 (data[offset + 2] << 8) | data[offset + 3];
24475 };
24476 } else {
24477 itemSize = 2;
24478 itemDecode = function fontItemDecode(data, offset) {
24479 return (data[offset] << 9) | (data[offset + 1] << 1);
24480 };
24481 }
24482 var glyphs = [];
24483 var startOffset = itemDecode(loca, 0);
24484 for (var j = itemSize; j < loca.length; j += itemSize) {
24485 var endOffset = itemDecode(loca, j);
24486 glyphs.push(glyf.subarray(startOffset, endOffset));
24487 startOffset = endOffset;
24488 }
24489 return glyphs;
24490 }
24491
24492 function lookupCmap(ranges, unicode) {
24493 var code = unicode.charCodeAt(0), gid = 0;
24494 var l = 0, r = ranges.length - 1;
24495 while (l < r) {
24496 var c = (l + r + 1) >> 1;
24497 if (code < ranges[c].start) {
24498 r = c - 1;
24499 } else {
24500 l = c;
24501 }
24502 }
24503 if (ranges[l].start <= code && code <= ranges[l].end) {
24504 gid = (ranges[l].idDelta + (ranges[l].ids ?
24505 ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF;
24506 }
24507 return {
24508 charCode: code,
24509 glyphId: gid,
24510 };
24511 }
24512
24513 function compileGlyf(code, cmds, font) {
24514 function moveTo(x, y) {
24515 cmds.push({cmd: 'moveTo', args: [x, y]});
24516 }
24517 function lineTo(x, y) {
24518 cmds.push({cmd: 'lineTo', args: [x, y]});
24519 }
24520 function quadraticCurveTo(xa, ya, x, y) {
24521 cmds.push({cmd: 'quadraticCurveTo', args: [xa, ya, x, y]});
24522 }
24523
24524 var i = 0;
24525 var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
24526 var flags;
24527 var x = 0, y = 0;
24528 i += 10;
24529 if (numberOfContours < 0) {
24530 // composite glyph
24531 do {
24532 flags = (code[i] << 8) | code[i + 1];
24533 var glyphIndex = (code[i + 2] << 8) | code[i + 3];
24534 i += 4;
24535 var arg1, arg2;
24536 if ((flags & 0x01)) {
24537 arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
24538 arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16;
24539 i += 4;
24540 } else {
24541 arg1 = code[i++]; arg2 = code[i++];
24542 }
24543 if ((flags & 0x02)) {
24544 x = arg1;
24545 y = arg2;
24546 } else {
24547 x = 0; y = 0; // TODO "they are points" ?
24548 }
24549 var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0;
24550 if ((flags & 0x08)) {
24551 scaleX =
24552 scaleY = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
24553 i += 2;
24554 } else if ((flags & 0x40)) {
24555 scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
24556 scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
24557 i += 4;
24558 } else if ((flags & 0x80)) {
24559 scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
24560 scale01 = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
24561 scale10 = ((code[i + 4] << 24) | (code[i + 5] << 16)) / 1073741824;
24562 scaleY = ((code[i + 6] << 24) | (code[i + 7] << 16)) / 1073741824;
24563 i += 8;
24564 }
24565 var subglyph = font.glyphs[glyphIndex];
24566 if (subglyph) {
24567 cmds.push({cmd: 'save'});
24568 cmds.push({cmd: 'transform',
24569 args: [scaleX, scale01, scale10, scaleY, x, y]});
24570 compileGlyf(subglyph, cmds, font);
24571 cmds.push({cmd: 'restore'});
24572 }
24573 } while ((flags & 0x20));
24574 } else {
24575 // simple glyph
24576 var endPtsOfContours = [];
24577 var j, jj;
24578 for (j = 0; j < numberOfContours; j++) {
24579 endPtsOfContours.push((code[i] << 8) | code[i + 1]);
24580 i += 2;
24581 }
24582 var instructionLength = (code[i] << 8) | code[i + 1];
24583 i += 2 + instructionLength; // skipping the instructions
24584 var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1;
24585 var points = [];
24586 while (points.length < numberOfPoints) {
24587 flags = code[i++];
24588 var repeat = 1;
24589 if ((flags & 0x08)) {
24590 repeat += code[i++];
24591 }
24592 while (repeat-- > 0) {
24593 points.push({flags: flags});
24594 }
24595 }
24596 for (j = 0; j < numberOfPoints; j++) {
24597 switch (points[j].flags & 0x12) {
24598 case 0x00:
24599 x += ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
24600 i += 2;
24601 break;
24602 case 0x02:
24603 x -= code[i++];
24604 break;
24605 case 0x12:
24606 x += code[i++];
24607 break;
24608 }
24609 points[j].x = x;
24610 }
24611 for (j = 0; j < numberOfPoints; j++) {
24612 switch (points[j].flags & 0x24) {
24613 case 0x00:
24614 y += ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
24615 i += 2;
24616 break;
24617 case 0x04:
24618 y -= code[i++];
24619 break;
24620 case 0x24:
24621 y += code[i++];
24622 break;
24623 }
24624 points[j].y = y;
24625 }
24626
24627 var startPoint = 0;
24628 for (i = 0; i < numberOfContours; i++) {
24629 var endPoint = endPtsOfContours[i];
24630 // contours might have implicit points, which is located in the middle
24631 // between two neighboring off-curve points
24632 var contour = points.slice(startPoint, endPoint + 1);
24633 if ((contour[0].flags & 1)) {
24634 contour.push(contour[0]); // using start point at the contour end
24635 } else if ((contour[contour.length - 1].flags & 1)) {
24636 // first is off-curve point, trying to use one from the end
24637 contour.unshift(contour[contour.length - 1]);
24638 } else {
24639 // start and end are off-curve points, creating implicit one
24640 var p = {
24641 flags: 1,
24642 x: (contour[0].x + contour[contour.length - 1].x) / 2,
24643 y: (contour[0].y + contour[contour.length - 1].y) / 2
24644 };
24645 contour.unshift(p);
24646 contour.push(p);
24647 }
24648 moveTo(contour[0].x, contour[0].y);
24649 for (j = 1, jj = contour.length; j < jj; j++) {
24650 if ((contour[j].flags & 1)) {
24651 lineTo(contour[j].x, contour[j].y);
24652 } else if ((contour[j + 1].flags & 1)){
24653 quadraticCurveTo(contour[j].x, contour[j].y,
24654 contour[j + 1].x, contour[j + 1].y);
24655 j++;
24656 } else {
24657 quadraticCurveTo(contour[j].x, contour[j].y,
24658 (contour[j].x + contour[j + 1].x) / 2,
24659 (contour[j].y + contour[j + 1].y) / 2);
24660 }
24661 }
24662 startPoint = endPoint + 1;
24663 }
24664 }
24665 }
24666
24667 function compileCharString(code, cmds, font) {
24668 var stack = [];
24669 var x = 0, y = 0;
24670 var stems = 0;
24671
24672 function moveTo(x, y) {
24673 cmds.push({cmd: 'moveTo', args: [x, y]});
24674 }
24675 function lineTo(x, y) {
24676 cmds.push({cmd: 'lineTo', args: [x, y]});
24677 }
24678 function bezierCurveTo(x1, y1, x2, y2, x, y) {
24679 cmds.push({cmd: 'bezierCurveTo', args: [x1, y1, x2, y2, x, y]});
24680 }
24681
24682 function parse(code) {
24683 var i = 0;
24684 while (i < code.length) {
24685 var stackClean = false;
24686 var v = code[i++];
24687 var xa, xb, ya, yb, y1, y2, y3, n, subrCode;
24688 switch (v) {
24689 case 1: // hstem
24690 stems += stack.length >> 1;
24691 stackClean = true;
24692 break;
24693 case 3: // vstem
24694 stems += stack.length >> 1;
24695 stackClean = true;
24696 break;
24697 case 4: // vmoveto
24698 y += stack.pop();
24699 moveTo(x, y);
24700 stackClean = true;
24701 break;
24702 case 5: // rlineto
24703 while (stack.length > 0) {
24704 x += stack.shift();
24705 y += stack.shift();
24706 lineTo(x, y);
24707 }
24708 break;
24709 case 6: // hlineto
24710 while (stack.length > 0) {
24711 x += stack.shift();
24712 lineTo(x, y);
24713 if (stack.length === 0) {
24714 break;
24715 }
24716 y += stack.shift();
24717 lineTo(x, y);
24718 }
24719 break;
24720 case 7: // vlineto
24721 while (stack.length > 0) {
24722 y += stack.shift();
24723 lineTo(x, y);
24724 if (stack.length === 0) {
24725 break;
24726 }
24727 x += stack.shift();
24728 lineTo(x, y);
24729 }
24730 break;
24731 case 8: // rrcurveto
24732 while (stack.length > 0) {
24733 xa = x + stack.shift(); ya = y + stack.shift();
24734 xb = xa + stack.shift(); yb = ya + stack.shift();
24735 x = xb + stack.shift(); y = yb + stack.shift();
24736 bezierCurveTo(xa, ya, xb, yb, x, y);
24737 }
24738 break;
24739 case 10: // callsubr
24740 n = stack.pop() + font.subrsBias;
24741 subrCode = font.subrs[n];
24742 if (subrCode) {
24743 parse(subrCode);
24744 }
24745 break;
24746 case 11: // return
24747 return;
24748 case 12:
24749 v = code[i++];
24750 switch (v) {
24751 case 34: // flex
24752 xa = x + stack.shift();
24753 xb = xa + stack.shift(); y1 = y + stack.shift();
24754 x = xb + stack.shift();
24755 bezierCurveTo(xa, y, xb, y1, x, y1);
24756 xa = x + stack.shift();
24757 xb = xa + stack.shift();
24758 x = xb + stack.shift();
24759 bezierCurveTo(xa, y1, xb, y, x, y);
24760 break;
24761 case 35: // flex
24762 xa = x + stack.shift(); ya = y + stack.shift();
24763 xb = xa + stack.shift(); yb = ya + stack.shift();
24764 x = xb + stack.shift(); y = yb + stack.shift();
24765 bezierCurveTo(xa, ya, xb, yb, x, y);
24766 xa = x + stack.shift(); ya = y + stack.shift();
24767 xb = xa + stack.shift(); yb = ya + stack.shift();
24768 x = xb + stack.shift(); y = yb + stack.shift();
24769 bezierCurveTo(xa, ya, xb, yb, x, y);
24770 stack.pop(); // fd
24771 break;
24772 case 36: // hflex1
24773 xa = x + stack.shift(); y1 = y + stack.shift();
24774 xb = xa + stack.shift(); y2 = y1 + stack.shift();
24775 x = xb + stack.shift();
24776 bezierCurveTo(xa, y1, xb, y2, x, y2);
24777 xa = x + stack.shift();
24778 xb = xa + stack.shift(); y3 = y2 + stack.shift();
24779 x = xb + stack.shift();
24780 bezierCurveTo(xa, y2, xb, y3, x, y);
24781 break;
24782 case 37: // flex1
24783 var x0 = x, y0 = y;
24784 xa = x + stack.shift(); ya = y + stack.shift();
24785 xb = xa + stack.shift(); yb = ya + stack.shift();
24786 x = xb + stack.shift(); y = yb + stack.shift();
24787 bezierCurveTo(xa, ya, xb, yb, x, y);
24788 xa = x + stack.shift(); ya = y + stack.shift();
24789 xb = xa + stack.shift(); yb = ya + stack.shift();
24790 x = xb; y = yb;
24791 if (Math.abs(x - x0) > Math.abs(y - y0)) {
24792 x += stack.shift();
24793 } else {
24794 y += stack.shift();
24795 }
24796 bezierCurveTo(xa, ya, xb, yb, x, y);
24797 break;
24798 default:
24799 error('unknown operator: 12 ' + v);
24800 }
24801 break;
24802 case 14: // endchar
24803 if (stack.length >= 4) {
24804 var achar = stack.pop();
24805 var bchar = stack.pop();
24806 y = stack.pop();
24807 x = stack.pop();
24808 cmds.push({cmd: 'save'});
24809 cmds.push({cmd: 'translate', args: [x, y]});
24810 var cmap = lookupCmap(font.cmap, String.fromCharCode(
24811 font.glyphNameMap[StandardEncoding[achar]]));
24812 compileCharString(font.glyphs[cmap.glyphId], cmds, font);
24813 cmds.push({cmd: 'restore'});
24814
24815 cmap = lookupCmap(font.cmap, String.fromCharCode(
24816 font.glyphNameMap[StandardEncoding[bchar]]));
24817 compileCharString(font.glyphs[cmap.glyphId], cmds, font);
24818 }
24819 return;
24820 case 18: // hstemhm
24821 stems += stack.length >> 1;
24822 stackClean = true;
24823 break;
24824 case 19: // hintmask
24825 stems += stack.length >> 1;
24826 i += (stems + 7) >> 3;
24827 stackClean = true;
24828 break;
24829 case 20: // cntrmask
24830 stems += stack.length >> 1;
24831 i += (stems + 7) >> 3;
24832 stackClean = true;
24833 break;
24834 case 21: // rmoveto
24835 y += stack.pop();
24836 x += stack.pop();
24837 moveTo(x, y);
24838 stackClean = true;
24839 break;
24840 case 22: // hmoveto
24841 x += stack.pop();
24842 moveTo(x, y);
24843 stackClean = true;
24844 break;
24845 case 23: // vstemhm
24846 stems += stack.length >> 1;
24847 stackClean = true;
24848 break;
24849 case 24: // rcurveline
24850 while (stack.length > 2) {
24851 xa = x + stack.shift(); ya = y + stack.shift();
24852 xb = xa + stack.shift(); yb = ya + stack.shift();
24853 x = xb + stack.shift(); y = yb + stack.shift();
24854 bezierCurveTo(xa, ya, xb, yb, x, y);
24855 }
24856 x += stack.shift();
24857 y += stack.shift();
24858 lineTo(x, y);
24859 break;
24860 case 25: // rlinecurve
24861 while (stack.length > 6) {
24862 x += stack.shift();
24863 y += stack.shift();
24864 lineTo(x, y);
24865 }
24866 xa = x + stack.shift(); ya = y + stack.shift();
24867 xb = xa + stack.shift(); yb = ya + stack.shift();
24868 x = xb + stack.shift(); y = yb + stack.shift();
24869 bezierCurveTo(xa, ya, xb, yb, x, y);
24870 break;
24871 case 26: // vvcurveto
24872 if (stack.length % 2) {
24873 x += stack.shift();
24874 }
24875 while (stack.length > 0) {
24876 xa = x; ya = y + stack.shift();
24877 xb = xa + stack.shift(); yb = ya + stack.shift();
24878 x = xb; y = yb + stack.shift();
24879 bezierCurveTo(xa, ya, xb, yb, x, y);
24880 }
24881 break;
24882 case 27: // hhcurveto
24883 if (stack.length % 2) {
24884 y += stack.shift();
24885 }
24886 while (stack.length > 0) {
24887 xa = x + stack.shift(); ya = y;
24888 xb = xa + stack.shift(); yb = ya + stack.shift();
24889 x = xb + stack.shift(); y = yb;
24890 bezierCurveTo(xa, ya, xb, yb, x, y);
24891 }
24892 break;
24893 case 28:
24894 stack.push(((code[i] << 24) | (code[i + 1] << 16)) >> 16);
24895 i += 2;
24896 break;
24897 case 29: // callgsubr
24898 n = stack.pop() + font.gsubrsBias;
24899 subrCode = font.gsubrs[n];
24900 if (subrCode) {
24901 parse(subrCode);
24902 }
24903 break;
24904 case 30: // vhcurveto
24905 while (stack.length > 0) {
24906 xa = x; ya = y + stack.shift();
24907 xb = xa + stack.shift(); yb = ya + stack.shift();
24908 x = xb + stack.shift();
24909 y = yb + (stack.length === 1 ? stack.shift() : 0);
24910 bezierCurveTo(xa, ya, xb, yb, x, y);
24911 if (stack.length === 0) {
24912 break;
24913 }
24914
24915 xa = x + stack.shift(); ya = y;
24916 xb = xa + stack.shift(); yb = ya + stack.shift();
24917 y = yb + stack.shift();
24918 x = xb + (stack.length === 1 ? stack.shift() : 0);
24919 bezierCurveTo(xa, ya, xb, yb, x, y);
24920 }
24921 break;
24922 case 31: // hvcurveto
24923 while (stack.length > 0) {
24924 xa = x + stack.shift(); ya = y;
24925 xb = xa + stack.shift(); yb = ya + stack.shift();
24926 y = yb + stack.shift();
24927 x = xb + (stack.length === 1 ? stack.shift() : 0);
24928 bezierCurveTo(xa, ya, xb, yb, x, y);
24929 if (stack.length === 0) {
24930 break;
24931 }
24932
24933 xa = x; ya = y + stack.shift();
24934 xb = xa + stack.shift(); yb = ya + stack.shift();
24935 x = xb + stack.shift();
24936 y = yb + (stack.length === 1 ? stack.shift() : 0);
24937 bezierCurveTo(xa, ya, xb, yb, x, y);
24938 }
24939 break;
24940 default:
24941 if (v < 32) {
24942 error('unknown operator: ' + v);
24943 }
24944 if (v < 247) {
24945 stack.push(v - 139);
24946 } else if (v < 251) {
24947 stack.push((v - 247) * 256 + code[i++] + 108);
24948 } else if (v < 255) {
24949 stack.push(-(v - 251) * 256 - code[i++] - 108);
24950 } else {
24951 stack.push(((code[i] << 24) | (code[i + 1] << 16) |
24952 (code[i + 2] << 8) | code[i + 3]) / 65536);
24953 i += 4;
24954 }
24955 break;
24956 }
24957 if (stackClean) {
24958 stack.length = 0;
24959 }
24960 }
24961 }
24962 parse(code);
24963 }
24964
24965 var noop = '';
24966
24967 function CompiledFont(fontMatrix) {
24968 this.compiledGlyphs = Object.create(null);
24969 this.compiledCharCodeToGlyphId = Object.create(null);
24970 this.fontMatrix = fontMatrix;
24971 }
24972 CompiledFont.prototype = {
24973 getPathJs: function (unicode) {
24974 var cmap = lookupCmap(this.cmap, unicode);
24975 var fn = this.compiledGlyphs[cmap.glyphId];
24976 if (!fn) {
24977 fn = this.compileGlyph(this.glyphs[cmap.glyphId]);
24978 this.compiledGlyphs[cmap.glyphId] = fn;
24979 }
24980 if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) {
24981 this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId;
24982 }
24983 return fn;
24984 },
24985
24986 compileGlyph: function (code) {
24987 if (!code || code.length === 0 || code[0] === 14) {
24988 return noop;
24989 }
24990
24991 var cmds = [];
24992 cmds.push({cmd: 'save'});
24993 cmds.push({cmd: 'transform', args: this.fontMatrix.slice()});
24994 cmds.push({cmd: 'scale', args: ['size', '-size']});
24995
24996 this.compileGlyphImpl(code, cmds);
24997
24998 cmds.push({cmd: 'restore'});
24999
25000 return cmds;
25001 },
25002
25003 compileGlyphImpl: function () {
25004 error('Children classes should implement this.');
25005 },
25006
25007 hasBuiltPath: function (unicode) {
25008 var cmap = lookupCmap(this.cmap, unicode);
25009 return (this.compiledGlyphs[cmap.glyphId] !== undefined &&
25010 this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined);
25011 }
25012 };
25013
25014 function TrueTypeCompiled(glyphs, cmap, fontMatrix) {
25015 fontMatrix = fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0];
25016 CompiledFont.call(this, fontMatrix);
25017
25018 this.glyphs = glyphs;
25019 this.cmap = cmap;
25020 }
25021
25022 Util.inherit(TrueTypeCompiled, CompiledFont, {
25023 compileGlyphImpl: function (code, cmds) {
25024 compileGlyf(code, cmds, this);
25025 }
25026 });
25027
25028 function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) {
25029 fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0];
25030 CompiledFont.call(this, fontMatrix);
25031
25032 this.glyphs = cffInfo.glyphs;
25033 this.gsubrs = cffInfo.gsubrs || [];
25034 this.subrs = cffInfo.subrs || [];
25035 this.cmap = cmap;
25036 this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
25037
25038 this.gsubrsBias = (this.gsubrs.length < 1240 ?
25039 107 : (this.gsubrs.length < 33900 ? 1131 : 32768));
25040 this.subrsBias = (this.subrs.length < 1240 ?
25041 107 : (this.subrs.length < 33900 ? 1131 : 32768));
25042 }
25043
25044 Util.inherit(Type2Compiled, CompiledFont, {
25045 compileGlyphImpl: function (code, cmds) {
25046 compileCharString(code, cmds, this);
25047 }
25048 });
25049
25050
25051 return {
25052 create: function FontRendererFactory_create(font, seacAnalysisEnabled) {
25053 var data = new Uint8Array(font.data);
25054 var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
25055 var numTables = getUshort(data, 4);
25056 for (var i = 0, p = 12; i < numTables; i++, p += 16) {
25057 var tag = bytesToString(data.subarray(p, p + 4));
25058 var offset = getLong(data, p + 8);
25059 var length = getLong(data, p + 12);
25060 switch (tag) {
25061 case 'cmap':
25062 cmap = parseCmap(data, offset, offset + length);
25063 break;
25064 case 'glyf':
25065 glyf = data.subarray(offset, offset + length);
25066 break;
25067 case 'loca':
25068 loca = data.subarray(offset, offset + length);
25069 break;
25070 case 'head':
25071 unitsPerEm = getUshort(data, offset + 18);
25072 indexToLocFormat = getUshort(data, offset + 50);
25073 break;
25074 case 'CFF ':
25075 cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
25076 break;
25077 }
25078 }
25079
25080 if (glyf) {
25081 var fontMatrix = (!unitsPerEm ? font.fontMatrix :
25082 [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]);
25083 return new TrueTypeCompiled(
25084 parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
25085 } else {
25086 return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
25087 }
25088 }
25089 };
25090})();
25091
25092exports.FontRendererFactory = FontRendererFactory;
25093}));
25094
25095
25096(function (root, factory) {
25097 {
25098 factory((root.pdfjsCoreParser = {}), root.pdfjsSharedUtil,
25099 root.pdfjsCorePrimitives, root.pdfjsCoreStream);
25100 }
25101}(this, function (exports, sharedUtil, corePrimitives, coreStream) {
25102
25103var MissingDataException = sharedUtil.MissingDataException;
25104var StreamType = sharedUtil.StreamType;
25105var assert = sharedUtil.assert;
25106var error = sharedUtil.error;
25107var info = sharedUtil.info;
25108var isArray = sharedUtil.isArray;
25109var isInt = sharedUtil.isInt;
25110var isNum = sharedUtil.isNum;
25111var isString = sharedUtil.isString;
25112var warn = sharedUtil.warn;
25113var Cmd = corePrimitives.Cmd;
25114var Dict = corePrimitives.Dict;
25115var Name = corePrimitives.Name;
25116var Ref = corePrimitives.Ref;
25117var isCmd = corePrimitives.isCmd;
25118var isDict = corePrimitives.isDict;
25119var isName = corePrimitives.isName;
25120var Ascii85Stream = coreStream.Ascii85Stream;
25121var AsciiHexStream = coreStream.AsciiHexStream;
25122var CCITTFaxStream = coreStream.CCITTFaxStream;
25123var FlateStream = coreStream.FlateStream;
25124var Jbig2Stream = coreStream.Jbig2Stream;
25125var JpegStream = coreStream.JpegStream;
25126var JpxStream = coreStream.JpxStream;
25127var LZWStream = coreStream.LZWStream;
25128var NullStream = coreStream.NullStream;
25129var PredictorStream = coreStream.PredictorStream;
25130var RunLengthStream = coreStream.RunLengthStream;
25131
25132var EOF = {};
25133
25134function isEOF(v) {
25135 return (v === EOF);
25136}
25137
25138var MAX_LENGTH_TO_CACHE = 1000;
25139
25140var Parser = (function ParserClosure() {
25141 function Parser(lexer, allowStreams, xref, recoveryMode) {
25142 this.lexer = lexer;
25143 this.allowStreams = allowStreams;
25144 this.xref = xref;
25145 this.recoveryMode = recoveryMode || false;
25146 this.imageCache = Object.create(null);
25147 this.refill();
25148 }
25149
25150 Parser.prototype = {
25151 refill: function Parser_refill() {
25152 this.buf1 = this.lexer.getObj();
25153 this.buf2 = this.lexer.getObj();
25154 },
25155 shift: function Parser_shift() {
25156 if (isCmd(this.buf2, 'ID')) {
25157 this.buf1 = this.buf2;
25158 this.buf2 = null;
25159 } else {
25160 this.buf1 = this.buf2;
25161 this.buf2 = this.lexer.getObj();
25162 }
25163 },
25164 tryShift: function Parser_tryShift() {
25165 try {
25166 this.shift();
25167 return true;
25168 } catch (e) {
25169 if (e instanceof MissingDataException) {
25170 throw e;
25171 }
25172 // Upon failure, the caller should reset this.lexer.pos to a known good
25173 // state and call this.shift() twice to reset the buffers.
25174 return false;
25175 }
25176 },
25177 getObj: function Parser_getObj(cipherTransform) {
25178 var buf1 = this.buf1;
25179 this.shift();
25180
25181 if (buf1 instanceof Cmd) {
25182 switch (buf1.cmd) {
25183 case 'BI': // inline image
25184 return this.makeInlineImage(cipherTransform);
25185 case '[': // array
25186 var array = [];
25187 while (!isCmd(this.buf1, ']') && !isEOF(this.buf1)) {
25188 array.push(this.getObj(cipherTransform));
25189 }
25190 if (isEOF(this.buf1)) {
25191 if (!this.recoveryMode) {
25192 error('End of file inside array');
25193 }
25194 return array;
25195 }
25196 this.shift();
25197 return array;
25198 case '<<': // dictionary or stream
25199 var dict = new Dict(this.xref);
25200 while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
25201 if (!isName(this.buf1)) {
25202 info('Malformed dictionary: key must be a name object');
25203 this.shift();
25204 continue;
25205 }
25206
25207 var key = this.buf1.name;
25208 this.shift();
25209 if (isEOF(this.buf1)) {
25210 break;
25211 }
25212 dict.set(key, this.getObj(cipherTransform));
25213 }
25214 if (isEOF(this.buf1)) {
25215 if (!this.recoveryMode) {
25216 error('End of file inside dictionary');
25217 }
25218 return dict;
25219 }
25220
25221 // Stream objects are not allowed inside content streams or
25222 // object streams.
25223 if (isCmd(this.buf2, 'stream')) {
25224 return (this.allowStreams ?
25225 this.makeStream(dict, cipherTransform) : dict);
25226 }
25227 this.shift();
25228 return dict;
25229 default: // simple object
25230 return buf1;
25231 }
25232 }
25233
25234 if (isInt(buf1)) { // indirect reference or integer
25235 var num = buf1;
25236 if (isInt(this.buf1) && isCmd(this.buf2, 'R')) {
25237 var ref = new Ref(num, this.buf1);
25238 this.shift();
25239 this.shift();
25240 return ref;
25241 }
25242 return num;
25243 }
25244
25245 if (isString(buf1)) { // string
25246 var str = buf1;
25247 if (cipherTransform) {
25248 str = cipherTransform.decryptString(str);
25249 }
25250 return str;
25251 }
25252
25253 // simple object
25254 return buf1;
25255 },
25256 /**
25257 * Find the end of the stream by searching for the /EI\s/.
25258 * @returns {number} The inline stream length.
25259 */
25260 findDefaultInlineStreamEnd:
25261 function Parser_findDefaultInlineStreamEnd(stream) {
25262 var E = 0x45, I = 0x49, SPACE = 0x20, LF = 0xA, CR = 0xD;
25263 var startPos = stream.pos, state = 0, ch, i, n, followingBytes;
25264 while ((ch = stream.getByte()) !== -1) {
25265 if (state === 0) {
25266 state = (ch === E) ? 1 : 0;
25267 } else if (state === 1) {
25268 state = (ch === I) ? 2 : 0;
25269 } else {
25270 assert(state === 2);
25271 if (ch === SPACE || ch === LF || ch === CR) {
25272 // Let's check the next five bytes are ASCII... just be sure.
25273 n = 5;
25274 followingBytes = stream.peekBytes(n);
25275 for (i = 0; i < n; i++) {
25276 ch = followingBytes[i];
25277 if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) {
25278 // Not a LF, CR, SPACE or any visible ASCII character, i.e.
25279 // it's binary stuff. Resetting the state.
25280 state = 0;
25281 break;
25282 }
25283 }
25284 if (state === 2) {
25285 break; // Finished!
25286 }
25287 } else {
25288 state = 0;
25289 }
25290 }
25291 }
25292 return ((stream.pos - 4) - startPos);
25293 },
25294 /**
25295 * Find the EOI (end-of-image) marker 0xFFD9 of the stream.
25296 * @returns {number} The inline stream length.
25297 */
25298 findDCTDecodeInlineStreamEnd:
25299 function Parser_findDCTDecodeInlineStreamEnd(stream) {
25300 var startPos = stream.pos, foundEOI = false, b, markerLength, length;
25301 while ((b = stream.getByte()) !== -1) {
25302 if (b !== 0xFF) { // Not a valid marker.
25303 continue;
25304 }
25305 switch (stream.getByte()) {
25306 case 0x00: // Byte stuffing.
25307 // 0xFF00 appears to be a very common byte sequence in JPEG images.
25308 break;
25309
25310 case 0xFF: // Fill byte.
25311 // Avoid skipping a valid marker, resetting the stream position.
25312 stream.skip(-1);
25313 break;
25314
25315 case 0xD9: // EOI
25316 foundEOI = true;
25317 break;
25318
25319 case 0xC0: // SOF0
25320 case 0xC1: // SOF1
25321 case 0xC2: // SOF2
25322 case 0xC3: // SOF3
25323
25324 case 0xC5: // SOF5
25325 case 0xC6: // SOF6
25326 case 0xC7: // SOF7
25327
25328 case 0xC9: // SOF9
25329 case 0xCA: // SOF10
25330 case 0xCB: // SOF11
25331
25332 case 0xCD: // SOF13
25333 case 0xCE: // SOF14
25334 case 0xCF: // SOF15
25335
25336 case 0xC4: // DHT
25337 case 0xCC: // DAC
25338
25339 case 0xDA: // SOS
25340 case 0xDB: // DQT
25341 case 0xDC: // DNL
25342 case 0xDD: // DRI
25343 case 0xDE: // DHP
25344 case 0xDF: // EXP
25345
25346 case 0xE0: // APP0
25347 case 0xE1: // APP1
25348 case 0xE2: // APP2
25349 case 0xE3: // APP3
25350 case 0xE4: // APP4
25351 case 0xE5: // APP5
25352 case 0xE6: // APP6
25353 case 0xE7: // APP7
25354 case 0xE8: // APP8
25355 case 0xE9: // APP9
25356 case 0xEA: // APP10
25357 case 0xEB: // APP11
25358 case 0xEC: // APP12
25359 case 0xED: // APP13
25360 case 0xEE: // APP14
25361 case 0xEF: // APP15
25362
25363 case 0xFE: // COM
25364 // The marker should be followed by the length of the segment.
25365 markerLength = stream.getUint16();
25366 if (markerLength > 2) {
25367 // |markerLength| contains the byte length of the marker segment,
25368 // including its own length (2 bytes) and excluding the marker.
25369 stream.skip(markerLength - 2); // Jump to the next marker.
25370 } else {
25371 // The marker length is invalid, resetting the stream position.
25372 stream.skip(-2);
25373 }
25374 break;
25375 }
25376 if (foundEOI) {
25377 break;
25378 }
25379 }
25380 length = stream.pos - startPos;
25381 if (b === -1) {
25382 warn('Inline DCTDecode image stream: ' +
25383 'EOI marker not found, searching for /EI/ instead.');
25384 stream.skip(-length); // Reset the stream position.
25385 return this.findDefaultInlineStreamEnd(stream);
25386 }
25387 this.inlineStreamSkipEI(stream);
25388 return length;
25389 },
25390 /**
25391 * Find the EOD (end-of-data) marker '~>' (i.e. TILDE + GT) of the stream.
25392 * @returns {number} The inline stream length.
25393 */
25394 findASCII85DecodeInlineStreamEnd:
25395 function Parser_findASCII85DecodeInlineStreamEnd(stream) {
25396 var TILDE = 0x7E, GT = 0x3E;
25397 var startPos = stream.pos, ch, length;
25398 while ((ch = stream.getByte()) !== -1) {
25399 if (ch === TILDE && stream.peekByte() === GT) {
25400 stream.skip();
25401 break;
25402 }
25403 }
25404 length = stream.pos - startPos;
25405 if (ch === -1) {
25406 warn('Inline ASCII85Decode image stream: ' +
25407 'EOD marker not found, searching for /EI/ instead.');
25408 stream.skip(-length); // Reset the stream position.
25409 return this.findDefaultInlineStreamEnd(stream);
25410 }
25411 this.inlineStreamSkipEI(stream);
25412 return length;
25413 },
25414 /**
25415 * Find the EOD (end-of-data) marker '>' (i.e. GT) of the stream.
25416 * @returns {number} The inline stream length.
25417 */
25418 findASCIIHexDecodeInlineStreamEnd:
25419 function Parser_findASCIIHexDecodeInlineStreamEnd(stream) {
25420 var GT = 0x3E;
25421 var startPos = stream.pos, ch, length;
25422 while ((ch = stream.getByte()) !== -1) {
25423 if (ch === GT) {
25424 break;
25425 }
25426 }
25427 length = stream.pos - startPos;
25428 if (ch === -1) {
25429 warn('Inline ASCIIHexDecode image stream: ' +
25430 'EOD marker not found, searching for /EI/ instead.');
25431 stream.skip(-length); // Reset the stream position.
25432 return this.findDefaultInlineStreamEnd(stream);
25433 }
25434 this.inlineStreamSkipEI(stream);
25435 return length;
25436 },
25437 /**
25438 * Skip over the /EI/ for streams where we search for an EOD marker.
25439 */
25440 inlineStreamSkipEI: function Parser_inlineStreamSkipEI(stream) {
25441 var E = 0x45, I = 0x49;
25442 var state = 0, ch;
25443 while ((ch = stream.getByte()) !== -1) {
25444 if (state === 0) {
25445 state = (ch === E) ? 1 : 0;
25446 } else if (state === 1) {
25447 state = (ch === I) ? 2 : 0;
25448 } else if (state === 2) {
25449 break;
25450 }
25451 }
25452 },
25453 makeInlineImage: function Parser_makeInlineImage(cipherTransform) {
25454 var lexer = this.lexer;
25455 var stream = lexer.stream;
25456
25457 // Parse dictionary.
25458 var dict = new Dict(this.xref);
25459 while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
25460 if (!isName(this.buf1)) {
25461 error('Dictionary key must be a name object');
25462 }
25463 var key = this.buf1.name;
25464 this.shift();
25465 if (isEOF(this.buf1)) {
25466 break;
25467 }
25468 dict.set(key, this.getObj(cipherTransform));
25469 }
25470
25471 // Extract the name of the first (i.e. the current) image filter.
25472 var filter = dict.get('Filter', 'F'), filterName;
25473 if (isName(filter)) {
25474 filterName = filter.name;
25475 } else if (isArray(filter) && isName(filter[0])) {
25476 filterName = filter[0].name;
25477 }
25478
25479 // Parse image stream.
25480 var startPos = stream.pos, length, i, ii;
25481 if (filterName === 'DCTDecode' || filterName === 'DCT') {
25482 length = this.findDCTDecodeInlineStreamEnd(stream);
25483 } else if (filterName === 'ASCII85Decide' || filterName === 'A85') {
25484 length = this.findASCII85DecodeInlineStreamEnd(stream);
25485 } else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') {
25486 length = this.findASCIIHexDecodeInlineStreamEnd(stream);
25487 } else {
25488 length = this.findDefaultInlineStreamEnd(stream);
25489 }
25490 var imageStream = stream.makeSubStream(startPos, length, dict);
25491
25492 // Cache all images below the MAX_LENGTH_TO_CACHE threshold by their
25493 // adler32 checksum.
25494 var adler32;
25495 if (length < MAX_LENGTH_TO_CACHE) {
25496 var imageBytes = imageStream.getBytes();
25497 imageStream.reset();
25498
25499 var a = 1;
25500 var b = 0;
25501 for (i = 0, ii = imageBytes.length; i < ii; ++i) {
25502 // No modulo required in the loop if imageBytes.length < 5552.
25503 a += imageBytes[i] & 0xff;
25504 b += a;
25505 }
25506 adler32 = ((b % 65521) << 16) | (a % 65521);
25507
25508 if (this.imageCache.adler32 === adler32) {
25509 this.buf2 = Cmd.get('EI');
25510 this.shift();
25511
25512 this.imageCache[adler32].reset();
25513 return this.imageCache[adler32];
25514 }
25515 }
25516
25517 if (cipherTransform) {
25518 imageStream = cipherTransform.createStream(imageStream, length);
25519 }
25520
25521 imageStream = this.filter(imageStream, dict, length);
25522 imageStream.dict = dict;
25523 if (adler32 !== undefined) {
25524 imageStream.cacheKey = 'inline_' + length + '_' + adler32;
25525 this.imageCache[adler32] = imageStream;
25526 }
25527
25528 this.buf2 = Cmd.get('EI');
25529 this.shift();
25530
25531 return imageStream;
25532 },
25533 makeStream: function Parser_makeStream(dict, cipherTransform) {
25534 var lexer = this.lexer;
25535 var stream = lexer.stream;
25536
25537 // get stream start position
25538 lexer.skipToNextLine();
25539 var pos = stream.pos - 1;
25540
25541 // get length
25542 var length = dict.get('Length');
25543 if (!isInt(length)) {
25544 info('Bad ' + length + ' attribute in stream');
25545 length = 0;
25546 }
25547
25548 // skip over the stream data
25549 stream.pos = pos + length;
25550 lexer.nextChar();
25551
25552 // Shift '>>' and check whether the new object marks the end of the stream
25553 if (this.tryShift() && isCmd(this.buf2, 'endstream')) {
25554 this.shift(); // 'stream'
25555 } else {
25556 // bad stream length, scanning for endstream
25557 stream.pos = pos;
25558 var SCAN_BLOCK_SIZE = 2048;
25559 var ENDSTREAM_SIGNATURE_LENGTH = 9;
25560 var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65,
25561 0x61, 0x6D];
25562 var skipped = 0, found = false, i, j;
25563 while (stream.pos < stream.end) {
25564 var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE);
25565 var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH;
25566 if (scanLength <= 0) {
25567 break;
25568 }
25569 found = false;
25570 i = 0;
25571 while (i < scanLength) {
25572 j = 0;
25573 while (j < ENDSTREAM_SIGNATURE_LENGTH &&
25574 scanBytes[i + j] === ENDSTREAM_SIGNATURE[j]) {
25575 j++;
25576 }
25577 if (j >= ENDSTREAM_SIGNATURE_LENGTH) {
25578 found = true;
25579 break;
25580 }
25581 i++;
25582 }
25583 if (found) {
25584 skipped += i;
25585 stream.pos += i;
25586 break;
25587 }
25588 skipped += scanLength;
25589 stream.pos += scanLength;
25590 }
25591 if (!found) {
25592 error('Missing endstream');
25593 }
25594 length = skipped;
25595
25596 lexer.nextChar();
25597 this.shift();
25598 this.shift();
25599 }
25600 this.shift(); // 'endstream'
25601
25602 stream = stream.makeSubStream(pos, length, dict);
25603 if (cipherTransform) {
25604 stream = cipherTransform.createStream(stream, length);
25605 }
25606 stream = this.filter(stream, dict, length);
25607 stream.dict = dict;
25608 return stream;
25609 },
25610 filter: function Parser_filter(stream, dict, length) {
25611 var filter = dict.get('Filter', 'F');
25612 var params = dict.get('DecodeParms', 'DP');
25613 if (isName(filter)) {
25614 return this.makeFilter(stream, filter.name, length, params);
25615 }
25616
25617 var maybeLength = length;
25618 if (isArray(filter)) {
25619 var filterArray = filter;
25620 var paramsArray = params;
25621 for (var i = 0, ii = filterArray.length; i < ii; ++i) {
25622 filter = filterArray[i];
25623 if (!isName(filter)) {
25624 error('Bad filter name: ' + filter);
25625 }
25626
25627 params = null;
25628 if (isArray(paramsArray) && (i in paramsArray)) {
25629 params = paramsArray[i];
25630 }
25631 stream = this.makeFilter(stream, filter.name, maybeLength, params);
25632 // after the first stream the length variable is invalid
25633 maybeLength = null;
25634 }
25635 }
25636 return stream;
25637 },
25638 makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) {
25639 if (stream.dict.get('Length') === 0 && !maybeLength) {
25640 warn('Empty "' + name + '" stream.');
25641 return new NullStream(stream);
25642 }
25643 try {
25644 if (params && this.xref) {
25645 params = this.xref.fetchIfRef(params);
25646 }
25647 var xrefStreamStats = this.xref.stats.streamTypes;
25648 if (name === 'FlateDecode' || name === 'Fl') {
25649 xrefStreamStats[StreamType.FLATE] = true;
25650 if (params) {
25651 return new PredictorStream(new FlateStream(stream, maybeLength),
25652 maybeLength, params);
25653 }
25654 return new FlateStream(stream, maybeLength);
25655 }
25656 if (name === 'LZWDecode' || name === 'LZW') {
25657 xrefStreamStats[StreamType.LZW] = true;
25658 var earlyChange = 1;
25659 if (params) {
25660 if (params.has('EarlyChange')) {
25661 earlyChange = params.get('EarlyChange');
25662 }
25663 return new PredictorStream(
25664 new LZWStream(stream, maybeLength, earlyChange),
25665 maybeLength, params);
25666 }
25667 return new LZWStream(stream, maybeLength, earlyChange);
25668 }
25669 if (name === 'DCTDecode' || name === 'DCT') {
25670 xrefStreamStats[StreamType.DCT] = true;
25671 return new JpegStream(stream, maybeLength, stream.dict);
25672 }
25673 if (name === 'JPXDecode' || name === 'JPX') {
25674 xrefStreamStats[StreamType.JPX] = true;
25675 return new JpxStream(stream, maybeLength, stream.dict);
25676 }
25677 if (name === 'ASCII85Decode' || name === 'A85') {
25678 xrefStreamStats[StreamType.A85] = true;
25679 return new Ascii85Stream(stream, maybeLength);
25680 }
25681 if (name === 'ASCIIHexDecode' || name === 'AHx') {
25682 xrefStreamStats[StreamType.AHX] = true;
25683 return new AsciiHexStream(stream, maybeLength);
25684 }
25685 if (name === 'CCITTFaxDecode' || name === 'CCF') {
25686 xrefStreamStats[StreamType.CCF] = true;
25687 return new CCITTFaxStream(stream, maybeLength, params);
25688 }
25689 if (name === 'RunLengthDecode' || name === 'RL') {
25690 xrefStreamStats[StreamType.RL] = true;
25691 return new RunLengthStream(stream, maybeLength);
25692 }
25693 if (name === 'JBIG2Decode') {
25694 xrefStreamStats[StreamType.JBIG] = true;
25695 return new Jbig2Stream(stream, maybeLength, stream.dict);
25696 }
25697 warn('filter "' + name + '" not supported yet');
25698 return stream;
25699 } catch (ex) {
25700 if (ex instanceof MissingDataException) {
25701 throw ex;
25702 }
25703 warn('Invalid stream: \"' + ex + '\"');
25704 return new NullStream(stream);
25705 }
25706 }
25707 };
25708
25709 return Parser;
25710})();
25711
25712var Lexer = (function LexerClosure() {
25713 function Lexer(stream, knownCommands) {
25714 this.stream = stream;
25715 this.nextChar();
25716
25717 // While lexing, we build up many strings one char at a time. Using += for
25718 // this can result in lots of garbage strings. It's better to build an
25719 // array of single-char strings and then join() them together at the end.
25720 // And reusing a single array (i.e. |this.strBuf|) over and over for this
25721 // purpose uses less memory than using a new array for each string.
25722 this.strBuf = [];
25723
25724 // The PDFs might have "glued" commands with other commands, operands or
25725 // literals, e.g. "q1". The knownCommands is a dictionary of the valid
25726 // commands and their prefixes. The prefixes are built the following way:
25727 // if there a command that is a prefix of the other valid command or
25728 // literal (e.g. 'f' and 'false') the following prefixes must be included,
25729 // 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no
25730 // other commands or literals as a prefix. The knowCommands is optional.
25731 this.knownCommands = knownCommands;
25732 }
25733
25734 // A '1' in this array means the character is white space. A '1' or
25735 // '2' means the character ends a name or command.
25736 var specialChars = [
25737 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
25738 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
25739 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
25740 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
25741 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
25742 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
25743 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
25744 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
25745 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
25746 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
25747 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
25748 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
25749 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
25750 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
25751 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
25752 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
25753 ];
25754
25755 function toHexDigit(ch) {
25756 if (ch >= 0x30 && ch <= 0x39) { // '0'-'9'
25757 return ch & 0x0F;
25758 }
25759 if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) {
25760 // 'A'-'F', 'a'-'f'
25761 return (ch & 0x0F) + 9;
25762 }
25763 return -1;
25764 }
25765
25766 Lexer.prototype = {
25767 nextChar: function Lexer_nextChar() {
25768 return (this.currentChar = this.stream.getByte());
25769 },
25770 peekChar: function Lexer_peekChar() {
25771 return this.stream.peekByte();
25772 },
25773 getNumber: function Lexer_getNumber() {
25774 var ch = this.currentChar;
25775 var eNotation = false;
25776 var divideBy = 0; // different from 0 if it's a floating point value
25777 var sign = 1;
25778
25779 if (ch === 0x2D) { // '-'
25780 sign = -1;
25781 ch = this.nextChar();
25782
25783 if (ch === 0x2D) { // '-'
25784 // Ignore double negative (this is consistent with Adobe Reader).
25785 ch = this.nextChar();
25786 }
25787 } else if (ch === 0x2B) { // '+'
25788 ch = this.nextChar();
25789 }
25790 if (ch === 0x2E) { // '.'
25791 divideBy = 10;
25792 ch = this.nextChar();
25793 }
25794 if (ch < 0x30 || ch > 0x39) { // '0' - '9'
25795 error('Invalid number: ' + String.fromCharCode(ch));
25796 return 0;
25797 }
25798
25799 var baseValue = ch - 0x30; // '0'
25800 var powerValue = 0;
25801 var powerValueSign = 1;
25802
25803 while ((ch = this.nextChar()) >= 0) {
25804 if (0x30 <= ch && ch <= 0x39) { // '0' - '9'
25805 var currentDigit = ch - 0x30; // '0'
25806 if (eNotation) { // We are after an 'e' or 'E'
25807 powerValue = powerValue * 10 + currentDigit;
25808 } else {
25809 if (divideBy !== 0) { // We are after a point
25810 divideBy *= 10;
25811 }
25812 baseValue = baseValue * 10 + currentDigit;
25813 }
25814 } else if (ch === 0x2E) { // '.'
25815 if (divideBy === 0) {
25816 divideBy = 1;
25817 } else {
25818 // A number can have only one '.'
25819 break;
25820 }
25821 } else if (ch === 0x2D) { // '-'
25822 // ignore minus signs in the middle of numbers to match
25823 // Adobe's behavior
25824 warn('Badly formatted number');
25825 } else if (ch === 0x45 || ch === 0x65) { // 'E', 'e'
25826 // 'E' can be either a scientific notation or the beginning of a new
25827 // operator
25828 ch = this.peekChar();
25829 if (ch === 0x2B || ch === 0x2D) { // '+', '-'
25830 powerValueSign = (ch === 0x2D) ? -1 : 1;
25831 this.nextChar(); // Consume the sign character
25832 } else if (ch < 0x30 || ch > 0x39) { // '0' - '9'
25833 // The 'E' must be the beginning of a new operator
25834 break;
25835 }
25836 eNotation = true;
25837 } else {
25838 // the last character doesn't belong to us
25839 break;
25840 }
25841 }
25842
25843 if (divideBy !== 0) {
25844 baseValue /= divideBy;
25845 }
25846 if (eNotation) {
25847 baseValue *= Math.pow(10, powerValueSign * powerValue);
25848 }
25849 return sign * baseValue;
25850 },
25851 getString: function Lexer_getString() {
25852 var numParen = 1;
25853 var done = false;
25854 var strBuf = this.strBuf;
25855 strBuf.length = 0;
25856
25857 var ch = this.nextChar();
25858 while (true) {
25859 var charBuffered = false;
25860 switch (ch | 0) {
25861 case -1:
25862 warn('Unterminated string');
25863 done = true;
25864 break;
25865 case 0x28: // '('
25866 ++numParen;
25867 strBuf.push('(');
25868 break;
25869 case 0x29: // ')'
25870 if (--numParen === 0) {
25871 this.nextChar(); // consume strings ')'
25872 done = true;
25873 } else {
25874 strBuf.push(')');
25875 }
25876 break;
25877 case 0x5C: // '\\'
25878 ch = this.nextChar();
25879 switch (ch) {
25880 case -1:
25881 warn('Unterminated string');
25882 done = true;
25883 break;
25884 case 0x6E: // 'n'
25885 strBuf.push('\n');
25886 break;
25887 case 0x72: // 'r'
25888 strBuf.push('\r');
25889 break;
25890 case 0x74: // 't'
25891 strBuf.push('\t');
25892 break;
25893 case 0x62: // 'b'
25894 strBuf.push('\b');
25895 break;
25896 case 0x66: // 'f'
25897 strBuf.push('\f');
25898 break;
25899 case 0x5C: // '\'
25900 case 0x28: // '('
25901 case 0x29: // ')'
25902 strBuf.push(String.fromCharCode(ch));
25903 break;
25904 case 0x30: case 0x31: case 0x32: case 0x33: // '0'-'3'
25905 case 0x34: case 0x35: case 0x36: case 0x37: // '4'-'7'
25906 var x = ch & 0x0F;
25907 ch = this.nextChar();
25908 charBuffered = true;
25909 if (ch >= 0x30 && ch <= 0x37) { // '0'-'7'
25910 x = (x << 3) + (ch & 0x0F);
25911 ch = this.nextChar();
25912 if (ch >= 0x30 && ch <= 0x37) { // '0'-'7'
25913 charBuffered = false;
25914 x = (x << 3) + (ch & 0x0F);
25915 }
25916 }
25917 strBuf.push(String.fromCharCode(x));
25918 break;
25919 case 0x0D: // CR
25920 if (this.peekChar() === 0x0A) { // LF
25921 this.nextChar();
25922 }
25923 break;
25924 case 0x0A: // LF
25925 break;
25926 default:
25927 strBuf.push(String.fromCharCode(ch));
25928 break;
25929 }
25930 break;
25931 default:
25932 strBuf.push(String.fromCharCode(ch));
25933 break;
25934 }
25935 if (done) {
25936 break;
25937 }
25938 if (!charBuffered) {
25939 ch = this.nextChar();
25940 }
25941 }
25942 return strBuf.join('');
25943 },
25944 getName: function Lexer_getName() {
25945 var ch, previousCh;
25946 var strBuf = this.strBuf;
25947 strBuf.length = 0;
25948 while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
25949 if (ch === 0x23) { // '#'
25950 ch = this.nextChar();
25951 if (specialChars[ch]) {
25952 warn('Lexer_getName: ' +
25953 'NUMBER SIGN (#) should be followed by a hexadecimal number.');
25954 strBuf.push('#');
25955 break;
25956 }
25957 var x = toHexDigit(ch);
25958 if (x !== -1) {
25959 previousCh = ch;
25960 ch = this.nextChar();
25961 var x2 = toHexDigit(ch);
25962 if (x2 === -1) {
25963 warn('Lexer_getName: Illegal digit (' +
25964 String.fromCharCode(ch) +') in hexadecimal number.');
25965 strBuf.push('#', String.fromCharCode(previousCh));
25966 if (specialChars[ch]) {
25967 break;
25968 }
25969 strBuf.push(String.fromCharCode(ch));
25970 continue;
25971 }
25972 strBuf.push(String.fromCharCode((x << 4) | x2));
25973 } else {
25974 strBuf.push('#', String.fromCharCode(ch));
25975 }
25976 } else {
25977 strBuf.push(String.fromCharCode(ch));
25978 }
25979 }
25980 if (strBuf.length > 127) {
25981 warn('name token is longer than allowed by the spec: ' + strBuf.length);
25982 }
25983 return Name.get(strBuf.join(''));
25984 },
25985 getHexString: function Lexer_getHexString() {
25986 var strBuf = this.strBuf;
25987 strBuf.length = 0;
25988 var ch = this.currentChar;
25989 var isFirstHex = true;
25990 var firstDigit;
25991 var secondDigit;
25992 while (true) {
25993 if (ch < 0) {
25994 warn('Unterminated hex string');
25995 break;
25996 } else if (ch === 0x3E) { // '>'
25997 this.nextChar();
25998 break;
25999 } else if (specialChars[ch] === 1) {
26000 ch = this.nextChar();
26001 continue;
26002 } else {
26003 if (isFirstHex) {
26004 firstDigit = toHexDigit(ch);
26005 if (firstDigit === -1) {
26006 warn('Ignoring invalid character "' + ch + '" in hex string');
26007 ch = this.nextChar();
26008 continue;
26009 }
26010 } else {
26011 secondDigit = toHexDigit(ch);
26012 if (secondDigit === -1) {
26013 warn('Ignoring invalid character "' + ch + '" in hex string');
26014 ch = this.nextChar();
26015 continue;
26016 }
26017 strBuf.push(String.fromCharCode((firstDigit << 4) | secondDigit));
26018 }
26019 isFirstHex = !isFirstHex;
26020 ch = this.nextChar();
26021 }
26022 }
26023 return strBuf.join('');
26024 },
26025 getObj: function Lexer_getObj() {
26026 // skip whitespace and comments
26027 var comment = false;
26028 var ch = this.currentChar;
26029 while (true) {
26030 if (ch < 0) {
26031 return EOF;
26032 }
26033 if (comment) {
26034 if (ch === 0x0A || ch === 0x0D) { // LF, CR
26035 comment = false;
26036 }
26037 } else if (ch === 0x25) { // '%'
26038 comment = true;
26039 } else if (specialChars[ch] !== 1) {
26040 break;
26041 }
26042 ch = this.nextChar();
26043 }
26044
26045 // start reading token
26046 switch (ch | 0) {
26047 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
26048 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
26049 case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
26050 return this.getNumber();
26051 case 0x28: // '('
26052 return this.getString();
26053 case 0x2F: // '/'
26054 return this.getName();
26055 // array punctuation
26056 case 0x5B: // '['
26057 this.nextChar();
26058 return Cmd.get('[');
26059 case 0x5D: // ']'
26060 this.nextChar();
26061 return Cmd.get(']');
26062 // hex string or dict punctuation
26063 case 0x3C: // '<'
26064 ch = this.nextChar();
26065 if (ch === 0x3C) {
26066 // dict punctuation
26067 this.nextChar();
26068 return Cmd.get('<<');
26069 }
26070 return this.getHexString();
26071 // dict punctuation
26072 case 0x3E: // '>'
26073 ch = this.nextChar();
26074 if (ch === 0x3E) {
26075 this.nextChar();
26076 return Cmd.get('>>');
26077 }
26078 return Cmd.get('>');
26079 case 0x7B: // '{'
26080 this.nextChar();
26081 return Cmd.get('{');
26082 case 0x7D: // '}'
26083 this.nextChar();
26084 return Cmd.get('}');
26085 case 0x29: // ')'
26086 error('Illegal character: ' + ch);
26087 break;
26088 }
26089
26090 // command
26091 var str = String.fromCharCode(ch);
26092 var knownCommands = this.knownCommands;
26093 var knownCommandFound = knownCommands && knownCommands[str] !== undefined;
26094 while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
26095 // stop if known command is found and next character does not make
26096 // the str a command
26097 var possibleCommand = str + String.fromCharCode(ch);
26098 if (knownCommandFound && knownCommands[possibleCommand] === undefined) {
26099 break;
26100 }
26101 if (str.length === 128) {
26102 error('Command token too long: ' + str.length);
26103 }
26104 str = possibleCommand;
26105 knownCommandFound = knownCommands && knownCommands[str] !== undefined;
26106 }
26107 if (str === 'true') {
26108 return true;
26109 }
26110 if (str === 'false') {
26111 return false;
26112 }
26113 if (str === 'null') {
26114 return null;
26115 }
26116 return Cmd.get(str);
26117 },
26118 skipToNextLine: function Lexer_skipToNextLine() {
26119 var ch = this.currentChar;
26120 while (ch >= 0) {
26121 if (ch === 0x0D) { // CR
26122 ch = this.nextChar();
26123 if (ch === 0x0A) { // LF
26124 this.nextChar();
26125 }
26126 break;
26127 } else if (ch === 0x0A) { // LF
26128 this.nextChar();
26129 break;
26130 }
26131 ch = this.nextChar();
26132 }
26133 }
26134 };
26135
26136 return Lexer;
26137})();
26138
26139var Linearization = {
26140 create: function LinearizationCreate(stream) {
26141 function getInt(name, allowZeroValue) {
26142 var obj = linDict.get(name);
26143 if (isInt(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) {
26144 return obj;
26145 }
26146 throw new Error('The "' + name + '" parameter in the linearization ' +
26147 'dictionary is invalid.');
26148 }
26149 function getHints() {
26150 var hints = linDict.get('H'), hintsLength, item;
26151 if (isArray(hints) &&
26152 ((hintsLength = hints.length) === 2 || hintsLength === 4)) {
26153 for (var index = 0; index < hintsLength; index++) {
26154 if (!(isInt(item = hints[index]) && item > 0)) {
26155 throw new Error('Hint (' + index +
26156 ') in the linearization dictionary is invalid.');
26157 }
26158 }
26159 return hints;
26160 }
26161 throw new Error('Hint array in the linearization dictionary is invalid.');
26162 }
26163 var parser = new Parser(new Lexer(stream), false, null);
26164 var obj1 = parser.getObj();
26165 var obj2 = parser.getObj();
26166 var obj3 = parser.getObj();
26167 var linDict = parser.getObj();
26168 var obj, length;
26169 if (!(isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') && isDict(linDict) &&
26170 isNum(obj = linDict.get('Linearized')) && obj > 0)) {
26171 return null; // No valid linearization dictionary found.
26172 } else if ((length = getInt('L')) !== stream.length) {
26173 throw new Error('The "L" parameter in the linearization dictionary ' +
26174 'does not equal the stream length.');
26175 }
26176 return {
26177 length: length,
26178 hints: getHints(),
26179 objectNumberFirst: getInt('O'),
26180 endFirst: getInt('E'),
26181 numPages: getInt('N'),
26182 mainXRefEntriesOffset: getInt('T'),
26183 pageFirst: (linDict.has('P') ? getInt('P', true) : 0)
26184 };
26185 }
26186};
26187
26188exports.EOF = EOF;
26189exports.Lexer = Lexer;
26190exports.Linearization = Linearization;
26191exports.Parser = Parser;
26192exports.isEOF = isEOF;
26193}));
26194
26195
26196(function (root, factory) {
26197 {
26198 factory((root.pdfjsCoreType1Parser = {}), root.pdfjsSharedUtil,
26199 root.pdfjsCoreStream, root.pdfjsCoreEncodings);
26200 }
26201}(this, function (exports, sharedUtil, coreStream, coreEncodings) {
26202
26203var warn = sharedUtil.warn;
26204var isSpace = sharedUtil.isSpace;
26205var Stream = coreStream.Stream;
26206var getEncoding = coreEncodings.getEncoding;
26207
26208// Hinting is currently disabled due to unknown problems on windows
26209// in tracemonkey and various other pdfs with type1 fonts.
26210var HINTING_ENABLED = false;
26211
26212/*
26213 * CharStrings are encoded following the the CharString Encoding sequence
26214 * describe in Chapter 6 of the "Adobe Type1 Font Format" specification.
26215 * The value in a byte indicates a command, a number, or subsequent bytes
26216 * that are to be interpreted in a special way.
26217 *
26218 * CharString Number Encoding:
26219 * A CharString byte containing the values from 32 through 255 inclusive
26220 * indicate an integer. These values are decoded in four ranges.
26221 *
26222 * 1. A CharString byte containing a value, v, between 32 and 246 inclusive,
26223 * indicate the integer v - 139. Thus, the integer values from -107 through
26224 * 107 inclusive may be encoded in single byte.
26225 *
26226 * 2. A CharString byte containing a value, v, between 247 and 250 inclusive,
26227 * indicates an integer involving the next byte, w, according to the formula:
26228 * [(v - 247) x 256] + w + 108
26229 *
26230 * 3. A CharString byte containing a value, v, between 251 and 254 inclusive,
26231 * indicates an integer involving the next byte, w, according to the formula:
26232 * -[(v - 251) * 256] - w - 108
26233 *
26234 * 4. A CharString containing the value 255 indicates that the next 4 bytes
26235 * are a two complement signed integer. The first of these bytes contains the
26236 * highest order bits, the second byte contains the next higher order bits
26237 * and the fourth byte contain the lowest order bits.
26238 *
26239 *
26240 * CharString Command Encoding:
26241 * CharStrings commands are encoded in 1 or 2 bytes.
26242 *
26243 * Single byte commands are encoded in 1 byte that contains a value between
26244 * 0 and 31 inclusive.
26245 * If a command byte contains the value 12, then the value in the next byte
26246 * indicates a command. This "escape" mechanism allows many extra commands
26247 * to be encoded and this encoding technique helps to minimize the length of
26248 * the charStrings.
26249 */
26250var Type1CharString = (function Type1CharStringClosure() {
26251 var COMMAND_MAP = {
26252 'hstem': [1],
26253 'vstem': [3],
26254 'vmoveto': [4],
26255 'rlineto': [5],
26256 'hlineto': [6],
26257 'vlineto': [7],
26258 'rrcurveto': [8],
26259 'callsubr': [10],
26260 'flex': [12, 35],
26261 'drop' : [12, 18],
26262 'endchar': [14],
26263 'rmoveto': [21],
26264 'hmoveto': [22],
26265 'vhcurveto': [30],
26266 'hvcurveto': [31]
26267 };
26268
26269 function Type1CharString() {
26270 this.width = 0;
26271 this.lsb = 0;
26272 this.flexing = false;
26273 this.output = [];
26274 this.stack = [];
26275 }
26276
26277 Type1CharString.prototype = {
26278 convert: function Type1CharString_convert(encoded, subrs,
26279 seacAnalysisEnabled) {
26280 var count = encoded.length;
26281 var error = false;
26282 var wx, sbx, subrNumber;
26283 for (var i = 0; i < count; i++) {
26284 var value = encoded[i];
26285 if (value < 32) {
26286 if (value === 12) {
26287 value = (value << 8) + encoded[++i];
26288 }
26289 switch (value) {
26290 case 1: // hstem
26291 if (!HINTING_ENABLED) {
26292 this.stack = [];
26293 break;
26294 }
26295 error = this.executeCommand(2, COMMAND_MAP.hstem);
26296 break;
26297 case 3: // vstem
26298 if (!HINTING_ENABLED) {
26299 this.stack = [];
26300 break;
26301 }
26302 error = this.executeCommand(2, COMMAND_MAP.vstem);
26303 break;
26304 case 4: // vmoveto
26305 if (this.flexing) {
26306 if (this.stack.length < 1) {
26307 error = true;
26308 break;
26309 }
26310 // Add the dx for flex and but also swap the values so they are
26311 // the right order.
26312 var dy = this.stack.pop();
26313 this.stack.push(0, dy);
26314 break;
26315 }
26316 error = this.executeCommand(1, COMMAND_MAP.vmoveto);
26317 break;
26318 case 5: // rlineto
26319 error = this.executeCommand(2, COMMAND_MAP.rlineto);
26320 break;
26321 case 6: // hlineto
26322 error = this.executeCommand(1, COMMAND_MAP.hlineto);
26323 break;
26324 case 7: // vlineto
26325 error = this.executeCommand(1, COMMAND_MAP.vlineto);
26326 break;
26327 case 8: // rrcurveto
26328 error = this.executeCommand(6, COMMAND_MAP.rrcurveto);
26329 break;
26330 case 9: // closepath
26331 // closepath is a Type1 command that does not take argument and is
26332 // useless in Type2 and it can simply be ignored.
26333 this.stack = [];
26334 break;
26335 case 10: // callsubr
26336 if (this.stack.length < 1) {
26337 error = true;
26338 break;
26339 }
26340 subrNumber = this.stack.pop();
26341 error = this.convert(subrs[subrNumber], subrs,
26342 seacAnalysisEnabled);
26343 break;
26344 case 11: // return
26345 return error;
26346 case 13: // hsbw
26347 if (this.stack.length < 2) {
26348 error = true;
26349 break;
26350 }
26351 // To convert to type2 we have to move the width value to the
26352 // first part of the charstring and then use hmoveto with lsb.
26353 wx = this.stack.pop();
26354 sbx = this.stack.pop();
26355 this.lsb = sbx;
26356 this.width = wx;
26357 this.stack.push(wx, sbx);
26358 error = this.executeCommand(2, COMMAND_MAP.hmoveto);
26359 break;
26360 case 14: // endchar
26361 this.output.push(COMMAND_MAP.endchar[0]);
26362 break;
26363 case 21: // rmoveto
26364 if (this.flexing) {
26365 break;
26366 }
26367 error = this.executeCommand(2, COMMAND_MAP.rmoveto);
26368 break;
26369 case 22: // hmoveto
26370 if (this.flexing) {
26371 // Add the dy for flex.
26372 this.stack.push(0);
26373 break;
26374 }
26375 error = this.executeCommand(1, COMMAND_MAP.hmoveto);
26376 break;
26377 case 30: // vhcurveto
26378 error = this.executeCommand(4, COMMAND_MAP.vhcurveto);
26379 break;
26380 case 31: // hvcurveto
26381 error = this.executeCommand(4, COMMAND_MAP.hvcurveto);
26382 break;
26383 case (12 << 8) + 0: // dotsection
26384 // dotsection is a Type1 command to specify some hinting feature
26385 // for dots that do not take a parameter and it can safely be
26386 // ignored for Type2.
26387 this.stack = [];
26388 break;
26389 case (12 << 8) + 1: // vstem3
26390 if (!HINTING_ENABLED) {
26391 this.stack = [];
26392 break;
26393 }
26394 // [vh]stem3 are Type1 only and Type2 supports [vh]stem with
26395 // multiple parameters, so instead of returning [vh]stem3 take a
26396 // shortcut and return [vhstem] instead.
26397 error = this.executeCommand(2, COMMAND_MAP.vstem);
26398 break;
26399 case (12 << 8) + 2: // hstem3
26400 if (!HINTING_ENABLED) {
26401 this.stack = [];
26402 break;
26403 }
26404 // See vstem3.
26405 error = this.executeCommand(2, COMMAND_MAP.hstem);
26406 break;
26407 case (12 << 8) + 6: // seac
26408 // seac is like type 2's special endchar but it doesn't use the
26409 // first argument asb, so remove it.
26410 if (seacAnalysisEnabled) {
26411 this.seac = this.stack.splice(-4, 4);
26412 error = this.executeCommand(0, COMMAND_MAP.endchar);
26413 } else {
26414 error = this.executeCommand(4, COMMAND_MAP.endchar);
26415 }
26416 break;
26417 case (12 << 8) + 7: // sbw
26418 if (this.stack.length < 4) {
26419 error = true;
26420 break;
26421 }
26422 // To convert to type2 we have to move the width value to the
26423 // first part of the charstring and then use rmoveto with
26424 // (dx, dy). The height argument will not be used for vmtx and
26425 // vhea tables reconstruction -- ignoring it.
26426 var wy = this.stack.pop();
26427 wx = this.stack.pop();
26428 var sby = this.stack.pop();
26429 sbx = this.stack.pop();
26430 this.lsb = sbx;
26431 this.width = wx;
26432 this.stack.push(wx, sbx, sby);
26433 error = this.executeCommand(3, COMMAND_MAP.rmoveto);
26434 break;
26435 case (12 << 8) + 12: // div
26436 if (this.stack.length < 2) {
26437 error = true;
26438 break;
26439 }
26440 var num2 = this.stack.pop();
26441 var num1 = this.stack.pop();
26442 this.stack.push(num1 / num2);
26443 break;
26444 case (12 << 8) + 16: // callothersubr
26445 if (this.stack.length < 2) {
26446 error = true;
26447 break;
26448 }
26449 subrNumber = this.stack.pop();
26450 var numArgs = this.stack.pop();
26451 if (subrNumber === 0 && numArgs === 3) {
26452 var flexArgs = this.stack.splice(this.stack.length - 17, 17);
26453 this.stack.push(
26454 flexArgs[2] + flexArgs[0], // bcp1x + rpx
26455 flexArgs[3] + flexArgs[1], // bcp1y + rpy
26456 flexArgs[4], // bcp2x
26457 flexArgs[5], // bcp2y
26458 flexArgs[6], // p2x
26459 flexArgs[7], // p2y
26460 flexArgs[8], // bcp3x
26461 flexArgs[9], // bcp3y
26462 flexArgs[10], // bcp4x
26463 flexArgs[11], // bcp4y
26464 flexArgs[12], // p3x
26465 flexArgs[13], // p3y
26466 flexArgs[14] // flexDepth
26467 // 15 = finalx unused by flex
26468 // 16 = finaly unused by flex
26469 );
26470 error = this.executeCommand(13, COMMAND_MAP.flex, true);
26471 this.flexing = false;
26472 this.stack.push(flexArgs[15], flexArgs[16]);
26473 } else if (subrNumber === 1 && numArgs === 0) {
26474 this.flexing = true;
26475 }
26476 break;
26477 case (12 << 8) + 17: // pop
26478 // Ignore this since it is only used with othersubr.
26479 break;
26480 case (12 << 8) + 33: // setcurrentpoint
26481 // Ignore for now.
26482 this.stack = [];
26483 break;
26484 default:
26485 warn('Unknown type 1 charstring command of "' + value + '"');
26486 break;
26487 }
26488 if (error) {
26489 break;
26490 }
26491 continue;
26492 } else if (value <= 246) {
26493 value = value - 139;
26494 } else if (value <= 250) {
26495 value = ((value - 247) * 256) + encoded[++i] + 108;
26496 } else if (value <= 254) {
26497 value = -((value - 251) * 256) - encoded[++i] - 108;
26498 } else {
26499 value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 |
26500 (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;
26501 }
26502 this.stack.push(value);
26503 }
26504 return error;
26505 },
26506
26507 executeCommand: function(howManyArgs, command, keepStack) {
26508 var stackLength = this.stack.length;
26509 if (howManyArgs > stackLength) {
26510 return true;
26511 }
26512 var start = stackLength - howManyArgs;
26513 for (var i = start; i < stackLength; i++) {
26514 var value = this.stack[i];
26515 if (value === (value | 0)) { // int
26516 this.output.push(28, (value >> 8) & 0xff, value & 0xff);
26517 } else { // fixed point
26518 value = (65536 * value) | 0;
26519 this.output.push(255,
26520 (value >> 24) & 0xFF,
26521 (value >> 16) & 0xFF,
26522 (value >> 8) & 0xFF,
26523 value & 0xFF);
26524 }
26525 }
26526 this.output.push.apply(this.output, command);
26527 if (keepStack) {
26528 this.stack.splice(start, howManyArgs);
26529 } else {
26530 this.stack.length = 0;
26531 }
26532 return false;
26533 }
26534 };
26535
26536 return Type1CharString;
26537})();
26538
26539/*
26540 * Type1Parser encapsulate the needed code for parsing a Type1 font
26541 * program. Some of its logic depends on the Type2 charstrings
26542 * structure.
26543 * Note: this doesn't really parse the font since that would require evaluation
26544 * of PostScript, but it is possible in most cases to extract what we need
26545 * without a full parse.
26546 */
26547var Type1Parser = (function Type1ParserClosure() {
26548 /*
26549 * Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence
26550 * of Plaintext Bytes. The function took a key as a parameter which can be
26551 * for decrypting the eexec block of for decoding charStrings.
26552 */
26553 var EEXEC_ENCRYPT_KEY = 55665;
26554 var CHAR_STRS_ENCRYPT_KEY = 4330;
26555
26556 function isHexDigit(code) {
26557 return code >= 48 && code <= 57 || // '0'-'9'
26558 code >= 65 && code <= 70 || // 'A'-'F'
26559 code >= 97 && code <= 102; // 'a'-'f'
26560 }
26561
26562 function decrypt(data, key, discardNumber) {
26563 if (discardNumber >= data.length) {
26564 return new Uint8Array(0);
26565 }
26566 var r = key | 0, c1 = 52845, c2 = 22719, i, j;
26567 for (i = 0; i < discardNumber; i++) {
26568 r = ((data[i] + r) * c1 + c2) & ((1 << 16) - 1);
26569 }
26570 var count = data.length - discardNumber;
26571 var decrypted = new Uint8Array(count);
26572 for (i = discardNumber, j = 0; j < count; i++, j++) {
26573 var value = data[i];
26574 decrypted[j] = value ^ (r >> 8);
26575 r = ((value + r) * c1 + c2) & ((1 << 16) - 1);
26576 }
26577 return decrypted;
26578 }
26579
26580 function decryptAscii(data, key, discardNumber) {
26581 var r = key | 0, c1 = 52845, c2 = 22719;
26582 var count = data.length, maybeLength = count >>> 1;
26583 var decrypted = new Uint8Array(maybeLength);
26584 var i, j;
26585 for (i = 0, j = 0; i < count; i++) {
26586 var digit1 = data[i];
26587 if (!isHexDigit(digit1)) {
26588 continue;
26589 }
26590 i++;
26591 var digit2;
26592 while (i < count && !isHexDigit(digit2 = data[i])) {
26593 i++;
26594 }
26595 if (i < count) {
26596 var value = parseInt(String.fromCharCode(digit1, digit2), 16);
26597 decrypted[j++] = value ^ (r >> 8);
26598 r = ((value + r) * c1 + c2) & ((1 << 16) - 1);
26599 }
26600 }
26601 return Array.prototype.slice.call(decrypted, discardNumber, j);
26602 }
26603
26604 function isSpecial(c) {
26605 return c === 0x2F || // '/'
26606 c === 0x5B || c === 0x5D || // '[', ']'
26607 c === 0x7B || c === 0x7D || // '{', '}'
26608 c === 0x28 || c === 0x29; // '(', ')'
26609 }
26610
26611 function Type1Parser(stream, encrypted, seacAnalysisEnabled) {
26612 if (encrypted) {
26613 var data = stream.getBytes();
26614 var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) &&
26615 isHexDigit(data[2]) && isHexDigit(data[3]));
26616 stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) :
26617 decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
26618 }
26619 this.seacAnalysisEnabled = !!seacAnalysisEnabled;
26620
26621 this.stream = stream;
26622 this.nextChar();
26623 }
26624
26625 Type1Parser.prototype = {
26626 readNumberArray: function Type1Parser_readNumberArray() {
26627 this.getToken(); // read '[' or '{' (arrays can start with either)
26628 var array = [];
26629 while (true) {
26630 var token = this.getToken();
26631 if (token === null || token === ']' || token === '}') {
26632 break;
26633 }
26634 array.push(parseFloat(token || 0));
26635 }
26636 return array;
26637 },
26638
26639 readNumber: function Type1Parser_readNumber() {
26640 var token = this.getToken();
26641 return parseFloat(token || 0);
26642 },
26643
26644 readInt: function Type1Parser_readInt() {
26645 // Use '| 0' to prevent setting a double into length such as the double
26646 // does not flow into the loop variable.
26647 var token = this.getToken();
26648 return parseInt(token || 0, 10) | 0;
26649 },
26650
26651 readBoolean: function Type1Parser_readBoolean() {
26652 var token = this.getToken();
26653
26654 // Use 1 and 0 since that's what type2 charstrings use.
26655 return token === 'true' ? 1 : 0;
26656 },
26657
26658 nextChar : function Type1_nextChar() {
26659 return (this.currentChar = this.stream.getByte());
26660 },
26661
26662 getToken: function Type1Parser_getToken() {
26663 // Eat whitespace and comments.
26664 var comment = false;
26665 var ch = this.currentChar;
26666 while (true) {
26667 if (ch === -1) {
26668 return null;
26669 }
26670
26671 if (comment) {
26672 if (ch === 0x0A || ch === 0x0D) {
26673 comment = false;
26674 }
26675 } else if (ch === 0x25) { // '%'
26676 comment = true;
26677 } else if (!isSpace(ch)) {
26678 break;
26679 }
26680 ch = this.nextChar();
26681 }
26682 if (isSpecial(ch)) {
26683 this.nextChar();
26684 return String.fromCharCode(ch);
26685 }
26686 var token = '';
26687 do {
26688 token += String.fromCharCode(ch);
26689 ch = this.nextChar();
26690 } while (ch >= 0 && !isSpace(ch) && !isSpecial(ch));
26691 return token;
26692 },
26693
26694 /*
26695 * Returns an object containing a Subrs array and a CharStrings
26696 * array extracted from and eexec encrypted block of data
26697 */
26698 extractFontProgram: function Type1Parser_extractFontProgram() {
26699 var stream = this.stream;
26700
26701 var subrs = [], charstrings = [];
26702 var privateData = Object.create(null);
26703 privateData['lenIV'] = 4;
26704 var program = {
26705 subrs: [],
26706 charstrings: [],
26707 properties: {
26708 'privateData': privateData
26709 }
26710 };
26711 var token, length, data, lenIV, encoded;
26712 while ((token = this.getToken()) !== null) {
26713 if (token !== '/') {
26714 continue;
26715 }
26716 token = this.getToken();
26717 switch (token) {
26718 case 'CharStrings':
26719 // The number immediately following CharStrings must be greater or
26720 // equal to the number of CharStrings.
26721 this.getToken();
26722 this.getToken(); // read in 'dict'
26723 this.getToken(); // read in 'dup'
26724 this.getToken(); // read in 'begin'
26725 while(true) {
26726 token = this.getToken();
26727 if (token === null || token === 'end') {
26728 break;
26729 }
26730
26731 if (token !== '/') {
26732 continue;
26733 }
26734 var glyph = this.getToken();
26735 length = this.readInt();
26736 this.getToken(); // read in 'RD' or '-|'
26737 data = stream.makeSubStream(stream.pos, length);
26738 lenIV = program.properties.privateData['lenIV'];
26739 encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV);
26740 // Skip past the required space and binary data.
26741 stream.skip(length);
26742 this.nextChar();
26743 token = this.getToken(); // read in 'ND' or '|-'
26744 if (token === 'noaccess') {
26745 this.getToken(); // read in 'def'
26746 }
26747 charstrings.push({
26748 glyph: glyph,
26749 encoded: encoded
26750 });
26751 }
26752 break;
26753 case 'Subrs':
26754 var num = this.readInt();
26755 this.getToken(); // read in 'array'
26756 while ((token = this.getToken()) === 'dup') {
26757 var index = this.readInt();
26758 length = this.readInt();
26759 this.getToken(); // read in 'RD' or '-|'
26760 data = stream.makeSubStream(stream.pos, length);
26761 lenIV = program.properties.privateData['lenIV'];
26762 encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV);
26763 // Skip past the required space and binary data.
26764 stream.skip(length);
26765 this.nextChar();
26766 token = this.getToken(); // read in 'NP' or '|'
26767 if (token === 'noaccess') {
26768 this.getToken(); // read in 'put'
26769 }
26770 subrs[index] = encoded;
26771 }
26772 break;
26773 case 'BlueValues':
26774 case 'OtherBlues':
26775 case 'FamilyBlues':
26776 case 'FamilyOtherBlues':
26777 var blueArray = this.readNumberArray();
26778 // *Blue* values may contain invalid data: disables reading of
26779 // those values when hinting is disabled.
26780 if (blueArray.length > 0 && (blueArray.length % 2) === 0 &&
26781 HINTING_ENABLED) {
26782 program.properties.privateData[token] = blueArray;
26783 }
26784 break;
26785 case 'StemSnapH':
26786 case 'StemSnapV':
26787 program.properties.privateData[token] = this.readNumberArray();
26788 break;
26789 case 'StdHW':
26790 case 'StdVW':
26791 program.properties.privateData[token] =
26792 this.readNumberArray()[0];
26793 break;
26794 case 'BlueShift':
26795 case 'lenIV':
26796 case 'BlueFuzz':
26797 case 'BlueScale':
26798 case 'LanguageGroup':
26799 case 'ExpansionFactor':
26800 program.properties.privateData[token] = this.readNumber();
26801 break;
26802 case 'ForceBold':
26803 program.properties.privateData[token] = this.readBoolean();
26804 break;
26805 }
26806 }
26807
26808 for (var i = 0; i < charstrings.length; i++) {
26809 glyph = charstrings[i].glyph;
26810 encoded = charstrings[i].encoded;
26811 var charString = new Type1CharString();
26812 var error = charString.convert(encoded, subrs,
26813 this.seacAnalysisEnabled);
26814 var output = charString.output;
26815 if (error) {
26816 // It seems when FreeType encounters an error while evaluating a glyph
26817 // that it completely ignores the glyph so we'll mimic that behaviour
26818 // here and put an endchar to make the validator happy.
26819 output = [14];
26820 }
26821 program.charstrings.push({
26822 glyphName: glyph,
26823 charstring: output,
26824 width: charString.width,
26825 lsb: charString.lsb,
26826 seac: charString.seac
26827 });
26828 }
26829
26830 return program;
26831 },
26832
26833 extractFontHeader: function Type1Parser_extractFontHeader(properties) {
26834 var token;
26835 while ((token = this.getToken()) !== null) {
26836 if (token !== '/') {
26837 continue;
26838 }
26839 token = this.getToken();
26840 switch (token) {
26841 case 'FontMatrix':
26842 var matrix = this.readNumberArray();
26843 properties.fontMatrix = matrix;
26844 break;
26845 case 'Encoding':
26846 var encodingArg = this.getToken();
26847 var encoding;
26848 if (!/^\d+$/.test(encodingArg)) {
26849 // encoding name is specified
26850 encoding = getEncoding(encodingArg);
26851 } else {
26852 encoding = [];
26853 var size = parseInt(encodingArg, 10) | 0;
26854 this.getToken(); // read in 'array'
26855
26856 for (var j = 0; j < size; j++) {
26857 token = this.getToken();
26858 // skipping till first dup or def (e.g. ignoring for statement)
26859 while (token !== 'dup' && token !== 'def') {
26860 token = this.getToken();
26861 if (token === null) {
26862 return; // invalid header
26863 }
26864 }
26865 if (token === 'def') {
26866 break; // read all array data
26867 }
26868 var index = this.readInt();
26869 this.getToken(); // read in '/'
26870 var glyph = this.getToken();
26871 encoding[index] = glyph;
26872 this.getToken(); // read the in 'put'
26873 }
26874 }
26875 properties.builtInEncoding = encoding;
26876 break;
26877 case 'FontBBox':
26878 var fontBBox = this.readNumberArray();
26879 // adjusting ascent/descent
26880 properties.ascent = fontBBox[3];
26881 properties.descent = fontBBox[1];
26882 properties.ascentScaled = true;
26883 break;
26884 }
26885 }
26886 }
26887 };
26888
26889 return Type1Parser;
26890})();
26891
26892exports.Type1Parser = Type1Parser;
26893}));
26894
26895
26896(function (root, factory) {
26897 {
26898 factory((root.pdfjsCoreCMap = {}), root.pdfjsSharedUtil,
26899 root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreParser);
26900 }
26901}(this, function (exports, sharedUtil, corePrimitives, coreStream, coreParser) {
26902
26903var Util = sharedUtil.Util;
26904var assert = sharedUtil.assert;
26905var warn = sharedUtil.warn;
26906var error = sharedUtil.error;
26907var isInt = sharedUtil.isInt;
26908var isString = sharedUtil.isString;
26909var MissingDataException = sharedUtil.MissingDataException;
26910var isName = corePrimitives.isName;
26911var isCmd = corePrimitives.isCmd;
26912var isStream = corePrimitives.isStream;
26913var StringStream = coreStream.StringStream;
26914var Lexer = coreParser.Lexer;
26915var isEOF = coreParser.isEOF;
26916
26917var BUILT_IN_CMAPS = [
26918// << Start unicode maps.
26919'Adobe-GB1-UCS2',
26920'Adobe-CNS1-UCS2',
26921'Adobe-Japan1-UCS2',
26922'Adobe-Korea1-UCS2',
26923// >> End unicode maps.
26924'78-EUC-H',
26925'78-EUC-V',
26926'78-H',
26927'78-RKSJ-H',
26928'78-RKSJ-V',
26929'78-V',
26930'78ms-RKSJ-H',
26931'78ms-RKSJ-V',
26932'83pv-RKSJ-H',
26933'90ms-RKSJ-H',
26934'90ms-RKSJ-V',
26935'90msp-RKSJ-H',
26936'90msp-RKSJ-V',
26937'90pv-RKSJ-H',
26938'90pv-RKSJ-V',
26939'Add-H',
26940'Add-RKSJ-H',
26941'Add-RKSJ-V',
26942'Add-V',
26943'Adobe-CNS1-0',
26944'Adobe-CNS1-1',
26945'Adobe-CNS1-2',
26946'Adobe-CNS1-3',
26947'Adobe-CNS1-4',
26948'Adobe-CNS1-5',
26949'Adobe-CNS1-6',
26950'Adobe-GB1-0',
26951'Adobe-GB1-1',
26952'Adobe-GB1-2',
26953'Adobe-GB1-3',
26954'Adobe-GB1-4',
26955'Adobe-GB1-5',
26956'Adobe-Japan1-0',
26957'Adobe-Japan1-1',
26958'Adobe-Japan1-2',
26959'Adobe-Japan1-3',
26960'Adobe-Japan1-4',
26961'Adobe-Japan1-5',
26962'Adobe-Japan1-6',
26963'Adobe-Korea1-0',
26964'Adobe-Korea1-1',
26965'Adobe-Korea1-2',
26966'B5-H',
26967'B5-V',
26968'B5pc-H',
26969'B5pc-V',
26970'CNS-EUC-H',
26971'CNS-EUC-V',
26972'CNS1-H',
26973'CNS1-V',
26974'CNS2-H',
26975'CNS2-V',
26976'ETHK-B5-H',
26977'ETHK-B5-V',
26978'ETen-B5-H',
26979'ETen-B5-V',
26980'ETenms-B5-H',
26981'ETenms-B5-V',
26982'EUC-H',
26983'EUC-V',
26984'Ext-H',
26985'Ext-RKSJ-H',
26986'Ext-RKSJ-V',
26987'Ext-V',
26988'GB-EUC-H',
26989'GB-EUC-V',
26990'GB-H',
26991'GB-V',
26992'GBK-EUC-H',
26993'GBK-EUC-V',
26994'GBK2K-H',
26995'GBK2K-V',
26996'GBKp-EUC-H',
26997'GBKp-EUC-V',
26998'GBT-EUC-H',
26999'GBT-EUC-V',
27000'GBT-H',
27001'GBT-V',
27002'GBTpc-EUC-H',
27003'GBTpc-EUC-V',
27004'GBpc-EUC-H',
27005'GBpc-EUC-V',
27006'H',
27007'HKdla-B5-H',
27008'HKdla-B5-V',
27009'HKdlb-B5-H',
27010'HKdlb-B5-V',
27011'HKgccs-B5-H',
27012'HKgccs-B5-V',
27013'HKm314-B5-H',
27014'HKm314-B5-V',
27015'HKm471-B5-H',
27016'HKm471-B5-V',
27017'HKscs-B5-H',
27018'HKscs-B5-V',
27019'Hankaku',
27020'Hiragana',
27021'KSC-EUC-H',
27022'KSC-EUC-V',
27023'KSC-H',
27024'KSC-Johab-H',
27025'KSC-Johab-V',
27026'KSC-V',
27027'KSCms-UHC-H',
27028'KSCms-UHC-HW-H',
27029'KSCms-UHC-HW-V',
27030'KSCms-UHC-V',
27031'KSCpc-EUC-H',
27032'KSCpc-EUC-V',
27033'Katakana',
27034'NWP-H',
27035'NWP-V',
27036'RKSJ-H',
27037'RKSJ-V',
27038'Roman',
27039'UniCNS-UCS2-H',
27040'UniCNS-UCS2-V',
27041'UniCNS-UTF16-H',
27042'UniCNS-UTF16-V',
27043'UniCNS-UTF32-H',
27044'UniCNS-UTF32-V',
27045'UniCNS-UTF8-H',
27046'UniCNS-UTF8-V',
27047'UniGB-UCS2-H',
27048'UniGB-UCS2-V',
27049'UniGB-UTF16-H',
27050'UniGB-UTF16-V',
27051'UniGB-UTF32-H',
27052'UniGB-UTF32-V',
27053'UniGB-UTF8-H',
27054'UniGB-UTF8-V',
27055'UniJIS-UCS2-H',
27056'UniJIS-UCS2-HW-H',
27057'UniJIS-UCS2-HW-V',
27058'UniJIS-UCS2-V',
27059'UniJIS-UTF16-H',
27060'UniJIS-UTF16-V',
27061'UniJIS-UTF32-H',
27062'UniJIS-UTF32-V',
27063'UniJIS-UTF8-H',
27064'UniJIS-UTF8-V',
27065'UniJIS2004-UTF16-H',
27066'UniJIS2004-UTF16-V',
27067'UniJIS2004-UTF32-H',
27068'UniJIS2004-UTF32-V',
27069'UniJIS2004-UTF8-H',
27070'UniJIS2004-UTF8-V',
27071'UniJISPro-UCS2-HW-V',
27072'UniJISPro-UCS2-V',
27073'UniJISPro-UTF8-V',
27074'UniJISX0213-UTF32-H',
27075'UniJISX0213-UTF32-V',
27076'UniJISX02132004-UTF32-H',
27077'UniJISX02132004-UTF32-V',
27078'UniKS-UCS2-H',
27079'UniKS-UCS2-V',
27080'UniKS-UTF16-H',
27081'UniKS-UTF16-V',
27082'UniKS-UTF32-H',
27083'UniKS-UTF32-V',
27084'UniKS-UTF8-H',
27085'UniKS-UTF8-V',
27086'V',
27087'WP-Symbol'];
27088
27089// CMap, not to be confused with TrueType's cmap.
27090var CMap = (function CMapClosure() {
27091 function CMap(builtInCMap) {
27092 // Codespace ranges are stored as follows:
27093 // [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]]
27094 // where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...]
27095 this.codespaceRanges = [[], [], [], []];
27096 this.numCodespaceRanges = 0;
27097 // Map entries have one of two forms.
27098 // - cid chars are 16-bit unsigned integers, stored as integers.
27099 // - bf chars are variable-length byte sequences, stored as strings, with
27100 // one byte per character.
27101 this._map = [];
27102 this.name = '';
27103 this.vertical = false;
27104 this.useCMap = null;
27105 this.builtInCMap = builtInCMap;
27106 }
27107 CMap.prototype = {
27108 addCodespaceRange: function(n, low, high) {
27109 this.codespaceRanges[n - 1].push(low, high);
27110 this.numCodespaceRanges++;
27111 },
27112
27113 mapCidRange: function(low, high, dstLow) {
27114 while (low <= high) {
27115 this._map[low++] = dstLow++;
27116 }
27117 },
27118
27119 mapBfRange: function(low, high, dstLow) {
27120 var lastByte = dstLow.length - 1;
27121 while (low <= high) {
27122 this._map[low++] = dstLow;
27123 // Only the last byte has to be incremented.
27124 dstLow = dstLow.substr(0, lastByte) +
27125 String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
27126 }
27127 },
27128
27129 mapBfRangeToArray: function(low, high, array) {
27130 var i = 0, ii = array.length;
27131 while (low <= high && i < ii) {
27132 this._map[low] = array[i++];
27133 ++low;
27134 }
27135 },
27136
27137 // This is used for both bf and cid chars.
27138 mapOne: function(src, dst) {
27139 this._map[src] = dst;
27140 },
27141
27142 lookup: function(code) {
27143 return this._map[code];
27144 },
27145
27146 contains: function(code) {
27147 return this._map[code] !== undefined;
27148 },
27149
27150 forEach: function(callback) {
27151 // Most maps have fewer than 65536 entries, and for those we use normal
27152 // array iteration. But really sparse tables are possible -- e.g. with
27153 // indices in the *billions*. For such tables we use for..in, which isn't
27154 // ideal because it stringifies the indices for all present elements, but
27155 // it does avoid iterating over every undefined entry.
27156 var map = this._map;
27157 var length = map.length;
27158 var i;
27159 if (length <= 0x10000) {
27160 for (i = 0; i < length; i++) {
27161 if (map[i] !== undefined) {
27162 callback(i, map[i]);
27163 }
27164 }
27165 } else {
27166 for (i in this._map) {
27167 callback(i, map[i]);
27168 }
27169 }
27170 },
27171
27172 charCodeOf: function(value) {
27173 return this._map.indexOf(value);
27174 },
27175
27176 getMap: function() {
27177 return this._map;
27178 },
27179
27180 readCharCode: function(str, offset, out) {
27181 var c = 0;
27182 var codespaceRanges = this.codespaceRanges;
27183 var codespaceRangesLen = this.codespaceRanges.length;
27184 // 9.7.6.2 CMap Mapping
27185 // The code length is at most 4.
27186 for (var n = 0; n < codespaceRangesLen; n++) {
27187 c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0;
27188 // Check each codespace range to see if it falls within.
27189 var codespaceRange = codespaceRanges[n];
27190 for (var k = 0, kk = codespaceRange.length; k < kk;) {
27191 var low = codespaceRange[k++];
27192 var high = codespaceRange[k++];
27193 if (c >= low && c <= high) {
27194 out.charcode = c;
27195 out.length = n + 1;
27196 return;
27197 }
27198 }
27199 }
27200 out.charcode = 0;
27201 out.length = 1;
27202 },
27203
27204 get length() {
27205 return this._map.length;
27206 },
27207
27208 get isIdentityCMap() {
27209 if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
27210 return false;
27211 }
27212 if (this._map.length !== 0x10000) {
27213 return false;
27214 }
27215 for (var i = 0; i < 0x10000; i++) {
27216 if (this._map[i] !== i) {
27217 return false;
27218 }
27219 }
27220 return true;
27221 }
27222 };
27223 return CMap;
27224})();
27225
27226// A special case of CMap, where the _map array implicitly has a length of
27227// 65536 and each element is equal to its index.
27228var IdentityCMap = (function IdentityCMapClosure() {
27229 function IdentityCMap(vertical, n) {
27230 CMap.call(this);
27231 this.vertical = vertical;
27232 this.addCodespaceRange(n, 0, 0xffff);
27233 }
27234 Util.inherit(IdentityCMap, CMap, {});
27235
27236 IdentityCMap.prototype = {
27237 addCodespaceRange: CMap.prototype.addCodespaceRange,
27238
27239 mapCidRange: function(low, high, dstLow) {
27240 error('should not call mapCidRange');
27241 },
27242
27243 mapBfRange: function(low, high, dstLow) {
27244 error('should not call mapBfRange');
27245 },
27246
27247 mapBfRangeToArray: function(low, high, array) {
27248 error('should not call mapBfRangeToArray');
27249 },
27250
27251 mapOne: function(src, dst) {
27252 error('should not call mapCidOne');
27253 },
27254
27255 lookup: function(code) {
27256 return (isInt(code) && code <= 0xffff) ? code : undefined;
27257 },
27258
27259 contains: function(code) {
27260 return isInt(code) && code <= 0xffff;
27261 },
27262
27263 forEach: function(callback) {
27264 for (var i = 0; i <= 0xffff; i++) {
27265 callback(i, i);
27266 }
27267 },
27268
27269 charCodeOf: function(value) {
27270 return (isInt(value) && value <= 0xffff) ? value : -1;
27271 },
27272
27273 getMap: function() {
27274 // Sometimes identity maps must be instantiated, but it's rare.
27275 var map = new Array(0x10000);
27276 for (var i = 0; i <= 0xffff; i++) {
27277 map[i] = i;
27278 }
27279 return map;
27280 },
27281
27282 readCharCode: CMap.prototype.readCharCode,
27283
27284 get length() {
27285 return 0x10000;
27286 },
27287
27288 get isIdentityCMap() {
27289 error('should not access .isIdentityCMap');
27290 }
27291 };
27292
27293 return IdentityCMap;
27294})();
27295
27296var BinaryCMapReader = (function BinaryCMapReaderClosure() {
27297 function fetchBinaryData(url) {
27298 return new Promise(function (resolve, reject) {
27299 var request = new XMLHttpRequest();
27300 request.open('GET', url, true);
27301 request.responseType = 'arraybuffer';
27302 request.onreadystatechange = function () {
27303 if (request.readyState === XMLHttpRequest.DONE) {
27304 if (!request.response || request.status !== 200 &&
27305 request.status !== 0) {
27306 reject(new Error('Unable to get binary cMap at: ' + url));
27307 } else {
27308 resolve(new Uint8Array(request.response));
27309 }
27310 }
27311 };
27312 request.send(null);
27313 });
27314 }
27315
27316 function hexToInt(a, size) {
27317 var n = 0;
27318 for (var i = 0; i <= size; i++) {
27319 n = (n << 8) | a[i];
27320 }
27321 return n >>> 0;
27322 }
27323
27324 function hexToStr(a, size) {
27325 // This code is hot. Special-case some common values to avoid creating an
27326 // object with subarray().
27327 if (size === 1) {
27328 return String.fromCharCode(a[0], a[1]);
27329 }
27330 if (size === 3) {
27331 return String.fromCharCode(a[0], a[1], a[2], a[3]);
27332 }
27333 return String.fromCharCode.apply(null, a.subarray(0, size + 1));
27334 }
27335
27336 function addHex(a, b, size) {
27337 var c = 0;
27338 for (var i = size; i >= 0; i--) {
27339 c += a[i] + b[i];
27340 a[i] = c & 255;
27341 c >>= 8;
27342 }
27343 }
27344
27345 function incHex(a, size) {
27346 var c = 1;
27347 for (var i = size; i >= 0 && c > 0; i--) {
27348 c += a[i];
27349 a[i] = c & 255;
27350 c >>= 8;
27351 }
27352 }
27353
27354 var MAX_NUM_SIZE = 16;
27355 var MAX_ENCODED_NUM_SIZE = 19; // ceil(MAX_NUM_SIZE * 7 / 8)
27356
27357 function BinaryCMapStream(data) {
27358 this.buffer = data;
27359 this.pos = 0;
27360 this.end = data.length;
27361 this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
27362 }
27363
27364 BinaryCMapStream.prototype = {
27365 readByte: function () {
27366 if (this.pos >= this.end) {
27367 return -1;
27368 }
27369 return this.buffer[this.pos++];
27370 },
27371 readNumber: function () {
27372 var n = 0;
27373 var last;
27374 do {
27375 var b = this.readByte();
27376 if (b < 0) {
27377 error('unexpected EOF in bcmap');
27378 }
27379 last = !(b & 0x80);
27380 n = (n << 7) | (b & 0x7F);
27381 } while (!last);
27382 return n;
27383 },
27384 readSigned: function () {
27385 var n = this.readNumber();
27386 return (n & 1) ? ~(n >>> 1) : n >>> 1;
27387 },
27388 readHex: function (num, size) {
27389 num.set(this.buffer.subarray(this.pos,
27390 this.pos + size + 1));
27391 this.pos += size + 1;
27392 },
27393 readHexNumber: function (num, size) {
27394 var last;
27395 var stack = this.tmpBuf, sp = 0;
27396 do {
27397 var b = this.readByte();
27398 if (b < 0) {
27399 error('unexpected EOF in bcmap');
27400 }
27401 last = !(b & 0x80);
27402 stack[sp++] = b & 0x7F;
27403 } while (!last);
27404 var i = size, buffer = 0, bufferSize = 0;
27405 while (i >= 0) {
27406 while (bufferSize < 8 && stack.length > 0) {
27407 buffer = (stack[--sp] << bufferSize) | buffer;
27408 bufferSize += 7;
27409 }
27410 num[i] = buffer & 255;
27411 i--;
27412 buffer >>= 8;
27413 bufferSize -= 8;
27414 }
27415 },
27416 readHexSigned: function (num, size) {
27417 this.readHexNumber(num, size);
27418 var sign = num[size] & 1 ? 255 : 0;
27419 var c = 0;
27420 for (var i = 0; i <= size; i++) {
27421 c = ((c & 1) << 8) | num[i];
27422 num[i] = (c >> 1) ^ sign;
27423 }
27424 },
27425 readString: function () {
27426 var len = this.readNumber();
27427 var s = '';
27428 for (var i = 0; i < len; i++) {
27429 s += String.fromCharCode(this.readNumber());
27430 }
27431 return s;
27432 }
27433 };
27434
27435 function processBinaryCMap(url, cMap, extend) {
27436 return fetchBinaryData(url).then(function (data) {
27437 var stream = new BinaryCMapStream(data);
27438 var header = stream.readByte();
27439 cMap.vertical = !!(header & 1);
27440
27441 var useCMap = null;
27442 var start = new Uint8Array(MAX_NUM_SIZE);
27443 var end = new Uint8Array(MAX_NUM_SIZE);
27444 var char = new Uint8Array(MAX_NUM_SIZE);
27445 var charCode = new Uint8Array(MAX_NUM_SIZE);
27446 var tmp = new Uint8Array(MAX_NUM_SIZE);
27447 var code;
27448
27449 var b;
27450 while ((b = stream.readByte()) >= 0) {
27451 var type = b >> 5;
27452 if (type === 7) { // metadata, e.g. comment or usecmap
27453 switch (b & 0x1F) {
27454 case 0:
27455 stream.readString(); // skipping comment
27456 break;
27457 case 1:
27458 useCMap = stream.readString();
27459 break;
27460 }
27461 continue;
27462 }
27463 var sequence = !!(b & 0x10);
27464 var dataSize = b & 15;
27465
27466 assert(dataSize + 1 <= MAX_NUM_SIZE);
27467
27468 var ucs2DataSize = 1;
27469 var subitemsCount = stream.readNumber();
27470 var i;
27471 switch (type) {
27472 case 0: // codespacerange
27473 stream.readHex(start, dataSize);
27474 stream.readHexNumber(end, dataSize);
27475 addHex(end, start, dataSize);
27476 cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize),
27477 hexToInt(end, dataSize));
27478 for (i = 1; i < subitemsCount; i++) {
27479 incHex(end, dataSize);
27480 stream.readHexNumber(start, dataSize);
27481 addHex(start, end, dataSize);
27482 stream.readHexNumber(end, dataSize);
27483 addHex(end, start, dataSize);
27484 cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize),
27485 hexToInt(end, dataSize));
27486 }
27487 break;
27488 case 1: // notdefrange
27489 stream.readHex(start, dataSize);
27490 stream.readHexNumber(end, dataSize);
27491 addHex(end, start, dataSize);
27492 code = stream.readNumber();
27493 // undefined range, skipping
27494 for (i = 1; i < subitemsCount; i++) {
27495 incHex(end, dataSize);
27496 stream.readHexNumber(start, dataSize);
27497 addHex(start, end, dataSize);
27498 stream.readHexNumber(end, dataSize);
27499 addHex(end, start, dataSize);
27500 code = stream.readNumber();
27501 // nop
27502 }
27503 break;
27504 case 2: // cidchar
27505 stream.readHex(char, dataSize);
27506 code = stream.readNumber();
27507 cMap.mapOne(hexToInt(char, dataSize), code);
27508 for (i = 1; i < subitemsCount; i++) {
27509 incHex(char, dataSize);
27510 if (!sequence) {
27511 stream.readHexNumber(tmp, dataSize);
27512 addHex(char, tmp, dataSize);
27513 }
27514 code = stream.readSigned() + (code + 1);
27515 cMap.mapOne(hexToInt(char, dataSize), code);
27516 }
27517 break;
27518 case 3: // cidrange
27519 stream.readHex(start, dataSize);
27520 stream.readHexNumber(end, dataSize);
27521 addHex(end, start, dataSize);
27522 code = stream.readNumber();
27523 cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize),
27524 code);
27525 for (i = 1; i < subitemsCount; i++) {
27526 incHex(end, dataSize);
27527 if (!sequence) {
27528 stream.readHexNumber(start, dataSize);
27529 addHex(start, end, dataSize);
27530 } else {
27531 start.set(end);
27532 }
27533 stream.readHexNumber(end, dataSize);
27534 addHex(end, start, dataSize);
27535 code = stream.readNumber();
27536 cMap.mapCidRange(hexToInt(start, dataSize),
27537 hexToInt(end, dataSize), code);
27538 }
27539 break;
27540 case 4: // bfchar
27541 stream.readHex(char, ucs2DataSize);
27542 stream.readHex(charCode, dataSize);
27543 cMap.mapOne(hexToInt(char, ucs2DataSize),
27544 hexToStr(charCode, dataSize));
27545 for (i = 1; i < subitemsCount; i++) {
27546 incHex(char, ucs2DataSize);
27547 if (!sequence) {
27548 stream.readHexNumber(tmp, ucs2DataSize);
27549 addHex(char, tmp, ucs2DataSize);
27550 }
27551 incHex(charCode, dataSize);
27552 stream.readHexSigned(tmp, dataSize);
27553 addHex(charCode, tmp, dataSize);
27554 cMap.mapOne(hexToInt(char, ucs2DataSize),
27555 hexToStr(charCode, dataSize));
27556 }
27557 break;
27558 case 5: // bfrange
27559 stream.readHex(start, ucs2DataSize);
27560 stream.readHexNumber(end, ucs2DataSize);
27561 addHex(end, start, ucs2DataSize);
27562 stream.readHex(charCode, dataSize);
27563 cMap.mapBfRange(hexToInt(start, ucs2DataSize),
27564 hexToInt(end, ucs2DataSize),
27565 hexToStr(charCode, dataSize));
27566 for (i = 1; i < subitemsCount; i++) {
27567 incHex(end, ucs2DataSize);
27568 if (!sequence) {
27569 stream.readHexNumber(start, ucs2DataSize);
27570 addHex(start, end, ucs2DataSize);
27571 } else {
27572 start.set(end);
27573 }
27574 stream.readHexNumber(end, ucs2DataSize);
27575 addHex(end, start, ucs2DataSize);
27576 stream.readHex(charCode, dataSize);
27577 cMap.mapBfRange(hexToInt(start, ucs2DataSize),
27578 hexToInt(end, ucs2DataSize),
27579 hexToStr(charCode, dataSize));
27580 }
27581 break;
27582 default:
27583 error('Unknown type: ' + type);
27584 break;
27585 }
27586 }
27587
27588 if (useCMap) {
27589 return extend(useCMap);
27590 }
27591 return cMap;
27592 });
27593 }
27594
27595 function BinaryCMapReader() {}
27596
27597 BinaryCMapReader.prototype = {
27598 read: processBinaryCMap
27599 };
27600
27601 return BinaryCMapReader;
27602})();
27603
27604var CMapFactory = (function CMapFactoryClosure() {
27605 function strToInt(str) {
27606 var a = 0;
27607 for (var i = 0; i < str.length; i++) {
27608 a = (a << 8) | str.charCodeAt(i);
27609 }
27610 return a >>> 0;
27611 }
27612
27613 function expectString(obj) {
27614 if (!isString(obj)) {
27615 error('Malformed CMap: expected string.');
27616 }
27617 }
27618
27619 function expectInt(obj) {
27620 if (!isInt(obj)) {
27621 error('Malformed CMap: expected int.');
27622 }
27623 }
27624
27625 function parseBfChar(cMap, lexer) {
27626 while (true) {
27627 var obj = lexer.getObj();
27628 if (isEOF(obj)) {
27629 break;
27630 }
27631 if (isCmd(obj, 'endbfchar')) {
27632 return;
27633 }
27634 expectString(obj);
27635 var src = strToInt(obj);
27636 obj = lexer.getObj();
27637 // TODO are /dstName used?
27638 expectString(obj);
27639 var dst = obj;
27640 cMap.mapOne(src, dst);
27641 }
27642 }
27643
27644 function parseBfRange(cMap, lexer) {
27645 while (true) {
27646 var obj = lexer.getObj();
27647 if (isEOF(obj)) {
27648 break;
27649 }
27650 if (isCmd(obj, 'endbfrange')) {
27651 return;
27652 }
27653 expectString(obj);
27654 var low = strToInt(obj);
27655 obj = lexer.getObj();
27656 expectString(obj);
27657 var high = strToInt(obj);
27658 obj = lexer.getObj();
27659 if (isInt(obj) || isString(obj)) {
27660 var dstLow = isInt(obj) ? String.fromCharCode(obj) : obj;
27661 cMap.mapBfRange(low, high, dstLow);
27662 } else if (isCmd(obj, '[')) {
27663 obj = lexer.getObj();
27664 var array = [];
27665 while (!isCmd(obj, ']') && !isEOF(obj)) {
27666 array.push(obj);
27667 obj = lexer.getObj();
27668 }
27669 cMap.mapBfRangeToArray(low, high, array);
27670 } else {
27671 break;
27672 }
27673 }
27674 error('Invalid bf range.');
27675 }
27676
27677 function parseCidChar(cMap, lexer) {
27678 while (true) {
27679 var obj = lexer.getObj();
27680 if (isEOF(obj)) {
27681 break;
27682 }
27683 if (isCmd(obj, 'endcidchar')) {
27684 return;
27685 }
27686 expectString(obj);
27687 var src = strToInt(obj);
27688 obj = lexer.getObj();
27689 expectInt(obj);
27690 var dst = obj;
27691 cMap.mapOne(src, dst);
27692 }
27693 }
27694
27695 function parseCidRange(cMap, lexer) {
27696 while (true) {
27697 var obj = lexer.getObj();
27698 if (isEOF(obj)) {
27699 break;
27700 }
27701 if (isCmd(obj, 'endcidrange')) {
27702 return;
27703 }
27704 expectString(obj);
27705 var low = strToInt(obj);
27706 obj = lexer.getObj();
27707 expectString(obj);
27708 var high = strToInt(obj);
27709 obj = lexer.getObj();
27710 expectInt(obj);
27711 var dstLow = obj;
27712 cMap.mapCidRange(low, high, dstLow);
27713 }
27714 }
27715
27716 function parseCodespaceRange(cMap, lexer) {
27717 while (true) {
27718 var obj = lexer.getObj();
27719 if (isEOF(obj)) {
27720 break;
27721 }
27722 if (isCmd(obj, 'endcodespacerange')) {
27723 return;
27724 }
27725 if (!isString(obj)) {
27726 break;
27727 }
27728 var low = strToInt(obj);
27729 obj = lexer.getObj();
27730 if (!isString(obj)) {
27731 break;
27732 }
27733 var high = strToInt(obj);
27734 cMap.addCodespaceRange(obj.length, low, high);
27735 }
27736 error('Invalid codespace range.');
27737 }
27738
27739 function parseWMode(cMap, lexer) {
27740 var obj = lexer.getObj();
27741 if (isInt(obj)) {
27742 cMap.vertical = !!obj;
27743 }
27744 }
27745
27746 function parseCMapName(cMap, lexer) {
27747 var obj = lexer.getObj();
27748 if (isName(obj) && isString(obj.name)) {
27749 cMap.name = obj.name;
27750 }
27751 }
27752
27753 function parseCMap(cMap, lexer, builtInCMapParams, useCMap) {
27754 var previous;
27755 var embededUseCMap;
27756 objLoop: while (true) {
27757 try {
27758 var obj = lexer.getObj();
27759 if (isEOF(obj)) {
27760 break;
27761 } else if (isName(obj)) {
27762 if (obj.name === 'WMode') {
27763 parseWMode(cMap, lexer);
27764 } else if (obj.name === 'CMapName') {
27765 parseCMapName(cMap, lexer);
27766 }
27767 previous = obj;
27768 } else if (isCmd(obj)) {
27769 switch (obj.cmd) {
27770 case 'endcmap':
27771 break objLoop;
27772 case 'usecmap':
27773 if (isName(previous)) {
27774 embededUseCMap = previous.name;
27775 }
27776 break;
27777 case 'begincodespacerange':
27778 parseCodespaceRange(cMap, lexer);
27779 break;
27780 case 'beginbfchar':
27781 parseBfChar(cMap, lexer);
27782 break;
27783 case 'begincidchar':
27784 parseCidChar(cMap, lexer);
27785 break;
27786 case 'beginbfrange':
27787 parseBfRange(cMap, lexer);
27788 break;
27789 case 'begincidrange':
27790 parseCidRange(cMap, lexer);
27791 break;
27792 }
27793 }
27794 } catch (ex) {
27795 if (ex instanceof MissingDataException) {
27796 throw ex;
27797 }
27798 warn('Invalid cMap data: ' + ex);
27799 continue;
27800 }
27801 }
27802
27803 if (!useCMap && embededUseCMap) {
27804 // Load the usecmap definition from the file only if there wasn't one
27805 // specified.
27806 useCMap = embededUseCMap;
27807 }
27808 if (useCMap) {
27809 return extendCMap(cMap, builtInCMapParams, useCMap);
27810 }
27811 return Promise.resolve(cMap);
27812 }
27813
27814 function extendCMap(cMap, builtInCMapParams, useCMap) {
27815 return createBuiltInCMap(useCMap, builtInCMapParams).then(
27816 function(newCMap) {
27817 cMap.useCMap = newCMap;
27818 // If there aren't any code space ranges defined clone all the parent ones
27819 // into this cMap.
27820 if (cMap.numCodespaceRanges === 0) {
27821 var useCodespaceRanges = cMap.useCMap.codespaceRanges;
27822 for (var i = 0; i < useCodespaceRanges.length; i++) {
27823 cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();
27824 }
27825 cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;
27826 }
27827 // Merge the map into the current one, making sure not to override
27828 // any previously defined entries.
27829 cMap.useCMap.forEach(function(key, value) {
27830 if (!cMap.contains(key)) {
27831 cMap.mapOne(key, cMap.useCMap.lookup(key));
27832 }
27833 });
27834
27835 return cMap;
27836 });
27837 }
27838
27839 function parseBinaryCMap(name, builtInCMapParams) {
27840 var url = builtInCMapParams.url + name + '.bcmap';
27841 var cMap = new CMap(true);
27842 return new BinaryCMapReader().read(url, cMap, function (useCMap) {
27843 return extendCMap(cMap, builtInCMapParams, useCMap);
27844 });
27845 }
27846
27847 function createBuiltInCMap(name, builtInCMapParams) {
27848 if (name === 'Identity-H') {
27849 return Promise.resolve(new IdentityCMap(false, 2));
27850 } else if (name === 'Identity-V') {
27851 return Promise.resolve(new IdentityCMap(true, 2));
27852 }
27853 if (BUILT_IN_CMAPS.indexOf(name) === -1) {
27854 return Promise.reject(new Error('Unknown cMap name: ' + name));
27855 }
27856 assert(builtInCMapParams, 'built-in cMap parameters are not provided');
27857
27858 if (builtInCMapParams.packed) {
27859 return parseBinaryCMap(name, builtInCMapParams);
27860 }
27861
27862 return new Promise(function (resolve, reject) {
27863 var url = builtInCMapParams.url + name;
27864 var request = new XMLHttpRequest();
27865 request.onreadystatechange = function () {
27866 if (request.readyState === XMLHttpRequest.DONE) {
27867 if (request.status === 200 || request.status === 0) {
27868 var cMap = new CMap(true);
27869 var lexer = new Lexer(new StringStream(request.responseText));
27870 parseCMap(cMap, lexer, builtInCMapParams, null).then(
27871 function (parsedCMap) {
27872 resolve(parsedCMap);
27873 });
27874 } else {
27875 reject(new Error('Unable to get cMap at: ' + url));
27876 }
27877 }
27878 };
27879 request.open('GET', url, true);
27880 request.send(null);
27881 });
27882 }
27883
27884 return {
27885 create: function (encoding, builtInCMapParams, useCMap) {
27886 if (isName(encoding)) {
27887 return createBuiltInCMap(encoding.name, builtInCMapParams);
27888 } else if (isStream(encoding)) {
27889 var cMap = new CMap();
27890 var lexer = new Lexer(encoding);
27891 return parseCMap(cMap, lexer, builtInCMapParams, useCMap).then(
27892 function (parsedCMap) {
27893 if (parsedCMap.isIdentityCMap) {
27894 return createBuiltInCMap(parsedCMap.name, builtInCMapParams);
27895 }
27896 return parsedCMap;
27897 });
27898 }
27899 return Promise.reject(new Error('Encoding required.'));
27900 }
27901 };
27902})();
27903
27904exports.CMap = CMap;
27905exports.CMapFactory = CMapFactory;
27906exports.IdentityCMap = IdentityCMap;
27907}));
27908
27909
27910(function (root, factory) {
27911 {
27912 factory((root.pdfjsCoreFonts = {}), root.pdfjsSharedUtil,
27913 root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreGlyphList,
27914 root.pdfjsCoreFontRenderer, root.pdfjsCoreEncodings,
27915 root.pdfjsCoreStandardFonts, root.pdfjsCoreUnicode,
27916 root.pdfjsCoreType1Parser, root.pdfjsCoreCFFParser);
27917 }
27918}(this, function (exports, sharedUtil, corePrimitives, coreStream,
27919 coreGlyphList, coreFontRenderer, coreEncodings,
27920 coreStandardFonts, coreUnicode, coreType1Parser,
27921 coreCFFParser) {
27922
27923var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
27924var FontType = sharedUtil.FontType;
27925var assert = sharedUtil.assert;
27926var bytesToString = sharedUtil.bytesToString;
27927var error = sharedUtil.error;
27928var info = sharedUtil.info;
27929var isArray = sharedUtil.isArray;
27930var isInt = sharedUtil.isInt;
27931var isNum = sharedUtil.isNum;
27932var readUint32 = sharedUtil.readUint32;
27933var shadow = sharedUtil.shadow;
27934var string32 = sharedUtil.string32;
27935var warn = sharedUtil.warn;
27936var MissingDataException = sharedUtil.MissingDataException;
27937var isSpace = sharedUtil.isSpace;
27938var Stream = coreStream.Stream;
27939var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode;
27940var getDingbatsGlyphsUnicode = coreGlyphList.getDingbatsGlyphsUnicode;
27941var FontRendererFactory = coreFontRenderer.FontRendererFactory;
27942var StandardEncoding = coreEncodings.StandardEncoding;
27943var MacRomanEncoding = coreEncodings.MacRomanEncoding;
27944var SymbolSetEncoding = coreEncodings.SymbolSetEncoding;
27945var ZapfDingbatsEncoding = coreEncodings.ZapfDingbatsEncoding;
27946var getEncoding = coreEncodings.getEncoding;
27947var getStdFontMap = coreStandardFonts.getStdFontMap;
27948var getNonStdFontMap = coreStandardFonts.getNonStdFontMap;
27949var getGlyphMapForStandardFonts = coreStandardFonts.getGlyphMapForStandardFonts;
27950var getSupplementalGlyphMapForArialBlack =
27951 coreStandardFonts.getSupplementalGlyphMapForArialBlack;
27952var getUnicodeRangeFor = coreUnicode.getUnicodeRangeFor;
27953var mapSpecialUnicodeValues = coreUnicode.mapSpecialUnicodeValues;
27954var getUnicodeForGlyph = coreUnicode.getUnicodeForGlyph;
27955var Type1Parser = coreType1Parser.Type1Parser;
27956var CFFStandardStrings = coreCFFParser.CFFStandardStrings;
27957var CFFParser = coreCFFParser.CFFParser;
27958var CFFCompiler = coreCFFParser.CFFCompiler;
27959var CFF = coreCFFParser.CFF;
27960var CFFHeader = coreCFFParser.CFFHeader;
27961var CFFTopDict = coreCFFParser.CFFTopDict;
27962var CFFPrivateDict = coreCFFParser.CFFPrivateDict;
27963var CFFStrings = coreCFFParser.CFFStrings;
27964var CFFIndex = coreCFFParser.CFFIndex;
27965var CFFCharset = coreCFFParser.CFFCharset;
27966
27967// Unicode Private Use Area
27968var PRIVATE_USE_OFFSET_START = 0xE000;
27969var PRIVATE_USE_OFFSET_END = 0xF8FF;
27970var SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = false;
27971
27972// PDF Glyph Space Units are one Thousandth of a TextSpace Unit
27973// except for Type 3 fonts
27974var PDF_GLYPH_SPACE_UNITS = 1000;
27975
27976// Accented charactars are not displayed properly on Windows, using this flag
27977// to control analysis of seac charstrings.
27978var SEAC_ANALYSIS_ENABLED = false;
27979
27980var FontFlags = {
27981 FixedPitch: 1,
27982 Serif: 2,
27983 Symbolic: 4,
27984 Script: 8,
27985 Nonsymbolic: 32,
27986 Italic: 64,
27987 AllCap: 65536,
27988 SmallCap: 131072,
27989 ForceBold: 262144
27990};
27991
27992var MacStandardGlyphOrdering = [
27993 '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl',
27994 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft',
27995 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
27996 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
27997 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at',
27998 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
27999 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft',
28000 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b',
28001 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
28002 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
28003 'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde',
28004 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis',
28005 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
28006 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve',
28007 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex',
28008 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet',
28009 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute',
28010 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal',
28011 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi',
28012 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash',
28013 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin',
28014 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis',
28015 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash',
28016 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright',
28017 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency',
28018 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered',
28019 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex',
28020 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex',
28021 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute',
28022 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron',
28023 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron',
28024 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar',
28025 'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply',
28026 'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter',
28027 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla',
28028 'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];
28029
28030function adjustWidths(properties) {
28031 if (!properties.fontMatrix) {
28032 return;
28033 }
28034 if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) {
28035 return;
28036 }
28037 // adjusting width to fontMatrix scale
28038 var scale = 0.001 / properties.fontMatrix[0];
28039 var glyphsWidths = properties.widths;
28040 for (var glyph in glyphsWidths) {
28041 glyphsWidths[glyph] *= scale;
28042 }
28043 properties.defaultWidth *= scale;
28044}
28045
28046function adjustToUnicode(properties, builtInEncoding) {
28047 if (properties.hasIncludedToUnicodeMap) {
28048 return; // The font dictionary has a `ToUnicode` entry.
28049 }
28050 if (properties.hasEncoding) {
28051 return; // The font dictionary has an `Encoding` entry.
28052 }
28053 if (builtInEncoding === properties.defaultEncoding) {
28054 return; // No point in trying to adjust `toUnicode` if the encodings match.
28055 }
28056 if (properties.toUnicode instanceof IdentityToUnicodeMap) {
28057 return;
28058 }
28059 var toUnicode = [], glyphsUnicodeMap = getGlyphsUnicode();
28060 for (var charCode in builtInEncoding) {
28061 var glyphName = builtInEncoding[charCode];
28062 var unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
28063 if (unicode !== -1) {
28064 toUnicode[charCode] = String.fromCharCode(unicode);
28065 }
28066 }
28067 properties.toUnicode.amend(toUnicode);
28068}
28069
28070function getFontType(type, subtype) {
28071 switch (type) {
28072 case 'Type1':
28073 return subtype === 'Type1C' ? FontType.TYPE1C : FontType.TYPE1;
28074 case 'CIDFontType0':
28075 return subtype === 'CIDFontType0C' ? FontType.CIDFONTTYPE0C :
28076 FontType.CIDFONTTYPE0;
28077 case 'OpenType':
28078 return FontType.OPENTYPE;
28079 case 'TrueType':
28080 return FontType.TRUETYPE;
28081 case 'CIDFontType2':
28082 return FontType.CIDFONTTYPE2;
28083 case 'MMType1':
28084 return FontType.MMTYPE1;
28085 case 'Type0':
28086 return FontType.TYPE0;
28087 default:
28088 return FontType.UNKNOWN;
28089 }
28090}
28091
28092// Some bad PDF generators, e.g. Scribus PDF, include glyph names
28093// in a 'uniXXXX' format -- attempting to recover proper ones.
28094function recoverGlyphName(name, glyphsUnicodeMap) {
28095 if (glyphsUnicodeMap[name] !== undefined) {
28096 return name;
28097 }
28098 // The glyph name is non-standard, trying to recover.
28099 var unicode = getUnicodeForGlyph(name, glyphsUnicodeMap);
28100 if (unicode !== -1) {
28101 for (var key in glyphsUnicodeMap) {
28102 if (glyphsUnicodeMap[key] === unicode) {
28103 return key;
28104 }
28105 }
28106 }
28107 info('Unable to recover a standard glyph name for: ' + name);
28108 return name;
28109}
28110
28111var Glyph = (function GlyphClosure() {
28112 function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId,
28113 isSpace, isInFont) {
28114 this.fontChar = fontChar;
28115 this.unicode = unicode;
28116 this.accent = accent;
28117 this.width = width;
28118 this.vmetric = vmetric;
28119 this.operatorListId = operatorListId;
28120 this.isSpace = isSpace;
28121 this.isInFont = isInFont;
28122 }
28123
28124 Glyph.prototype.matchesForCache = function(fontChar, unicode, accent, width,
28125 vmetric, operatorListId, isSpace,
28126 isInFont) {
28127 return this.fontChar === fontChar &&
28128 this.unicode === unicode &&
28129 this.accent === accent &&
28130 this.width === width &&
28131 this.vmetric === vmetric &&
28132 this.operatorListId === operatorListId &&
28133 this.isSpace === isSpace &&
28134 this.isInFont === isInFont;
28135 };
28136
28137 return Glyph;
28138})();
28139
28140var ToUnicodeMap = (function ToUnicodeMapClosure() {
28141 function ToUnicodeMap(cmap) {
28142 // The elements of this._map can be integers or strings, depending on how
28143 // |cmap| was created.
28144 this._map = cmap;
28145 }
28146
28147 ToUnicodeMap.prototype = {
28148 get length() {
28149 return this._map.length;
28150 },
28151
28152 forEach: function(callback) {
28153 for (var charCode in this._map) {
28154 callback(charCode, this._map[charCode].charCodeAt(0));
28155 }
28156 },
28157
28158 has: function(i) {
28159 return this._map[i] !== undefined;
28160 },
28161
28162 get: function(i) {
28163 return this._map[i];
28164 },
28165
28166 charCodeOf: function(v) {
28167 return this._map.indexOf(v);
28168 },
28169
28170 amend: function (map) {
28171 for (var charCode in map) {
28172 this._map[charCode] = map[charCode];
28173 }
28174 },
28175 };
28176
28177 return ToUnicodeMap;
28178})();
28179
28180var IdentityToUnicodeMap = (function IdentityToUnicodeMapClosure() {
28181 function IdentityToUnicodeMap(firstChar, lastChar) {
28182 this.firstChar = firstChar;
28183 this.lastChar = lastChar;
28184 }
28185
28186 IdentityToUnicodeMap.prototype = {
28187 get length() {
28188 return (this.lastChar + 1) - this.firstChar;
28189 },
28190
28191 forEach: function (callback) {
28192 for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) {
28193 callback(i, i);
28194 }
28195 },
28196
28197 has: function (i) {
28198 return this.firstChar <= i && i <= this.lastChar;
28199 },
28200
28201 get: function (i) {
28202 if (this.firstChar <= i && i <= this.lastChar) {
28203 return String.fromCharCode(i);
28204 }
28205 return undefined;
28206 },
28207
28208 charCodeOf: function (v) {
28209 return (isInt(v) && v >= this.firstChar && v <= this.lastChar) ? v : -1;
28210 },
28211
28212 amend: function (map) {
28213 error('Should not call amend()');
28214 },
28215 };
28216
28217 return IdentityToUnicodeMap;
28218})();
28219
28220var OpenTypeFileBuilder = (function OpenTypeFileBuilderClosure() {
28221 function writeInt16(dest, offset, num) {
28222 dest[offset] = (num >> 8) & 0xFF;
28223 dest[offset + 1] = num & 0xFF;
28224 }
28225
28226 function writeInt32(dest, offset, num) {
28227 dest[offset] = (num >> 24) & 0xFF;
28228 dest[offset + 1] = (num >> 16) & 0xFF;
28229 dest[offset + 2] = (num >> 8) & 0xFF;
28230 dest[offset + 3] = num & 0xFF;
28231 }
28232
28233 function writeData(dest, offset, data) {
28234 var i, ii;
28235 if (data instanceof Uint8Array) {
28236 dest.set(data, offset);
28237 } else if (typeof data === 'string') {
28238 for (i = 0, ii = data.length; i < ii; i++) {
28239 dest[offset++] = data.charCodeAt(i) & 0xFF;
28240 }
28241 } else {
28242 // treating everything else as array
28243 for (i = 0, ii = data.length; i < ii; i++) {
28244 dest[offset++] = data[i] & 0xFF;
28245 }
28246 }
28247 }
28248
28249 function OpenTypeFileBuilder(sfnt) {
28250 this.sfnt = sfnt;
28251 this.tables = Object.create(null);
28252 }
28253
28254 OpenTypeFileBuilder.getSearchParams =
28255 function OpenTypeFileBuilder_getSearchParams(entriesCount, entrySize) {
28256 var maxPower2 = 1, log2 = 0;
28257 while ((maxPower2 ^ entriesCount) > maxPower2) {
28258 maxPower2 <<= 1;
28259 log2++;
28260 }
28261 var searchRange = maxPower2 * entrySize;
28262 return {
28263 range: searchRange,
28264 entry: log2,
28265 rangeShift: entrySize * entriesCount - searchRange
28266 };
28267 };
28268
28269 var OTF_HEADER_SIZE = 12;
28270 var OTF_TABLE_ENTRY_SIZE = 16;
28271
28272 OpenTypeFileBuilder.prototype = {
28273 toArray: function OpenTypeFileBuilder_toArray() {
28274 var sfnt = this.sfnt;
28275
28276 // Tables needs to be written by ascendant alphabetic order
28277 var tables = this.tables;
28278 var tablesNames = Object.keys(tables);
28279 tablesNames.sort();
28280 var numTables = tablesNames.length;
28281
28282 var i, j, jj, table, tableName;
28283 // layout the tables data
28284 var offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE;
28285 var tableOffsets = [offset];
28286 for (i = 0; i < numTables; i++) {
28287 table = tables[tablesNames[i]];
28288 var paddedLength = ((table.length + 3) & ~3) >>> 0;
28289 offset += paddedLength;
28290 tableOffsets.push(offset);
28291 }
28292
28293 var file = new Uint8Array(offset);
28294 // write the table data first (mostly for checksum)
28295 for (i = 0; i < numTables; i++) {
28296 table = tables[tablesNames[i]];
28297 writeData(file, tableOffsets[i], table);
28298 }
28299
28300 // sfnt version (4 bytes)
28301 if (sfnt === 'true') {
28302 // Windows hates the Mac TrueType sfnt version number
28303 sfnt = string32(0x00010000);
28304 }
28305 file[0] = sfnt.charCodeAt(0) & 0xFF;
28306 file[1] = sfnt.charCodeAt(1) & 0xFF;
28307 file[2] = sfnt.charCodeAt(2) & 0xFF;
28308 file[3] = sfnt.charCodeAt(3) & 0xFF;
28309
28310 // numTables (2 bytes)
28311 writeInt16(file, 4, numTables);
28312
28313 var searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16);
28314
28315 // searchRange (2 bytes)
28316 writeInt16(file, 6, searchParams.range);
28317 // entrySelector (2 bytes)
28318 writeInt16(file, 8, searchParams.entry);
28319 // rangeShift (2 bytes)
28320 writeInt16(file, 10, searchParams.rangeShift);
28321
28322 offset = OTF_HEADER_SIZE;
28323 // writing table entries
28324 for (i = 0; i < numTables; i++) {
28325 tableName = tablesNames[i];
28326 file[offset] = tableName.charCodeAt(0) & 0xFF;
28327 file[offset + 1] = tableName.charCodeAt(1) & 0xFF;
28328 file[offset + 2] = tableName.charCodeAt(2) & 0xFF;
28329 file[offset + 3] = tableName.charCodeAt(3) & 0xFF;
28330
28331 // checksum
28332 var checksum = 0;
28333 for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) {
28334 var quad = readUint32(file, j);
28335 checksum = (checksum + quad) >>> 0;
28336 }
28337 writeInt32(file, offset + 4, checksum);
28338
28339 // offset
28340 writeInt32(file, offset + 8, tableOffsets[i]);
28341 // length
28342 writeInt32(file, offset + 12, tables[tableName].length);
28343
28344 offset += OTF_TABLE_ENTRY_SIZE;
28345 }
28346 return file;
28347 },
28348
28349 addTable: function OpenTypeFileBuilder_addTable(tag, data) {
28350 if (tag in this.tables) {
28351 throw new Error('Table ' + tag + ' already exists');
28352 }
28353 this.tables[tag] = data;
28354 }
28355 };
28356
28357 return OpenTypeFileBuilder;
28358})();
28359
28360// Problematic Unicode characters in the fonts that needs to be moved to avoid
28361// issues when they are painted on the canvas, e.g. complex-script shaping or
28362// control/whitespace characters. The ranges are listed in pairs: the first item
28363// is a code of the first problematic code, the second one is the next
28364// non-problematic code. The ranges must be in sorted order.
28365var ProblematicCharRanges = new Int32Array([
28366 // Control characters.
28367 0x0000, 0x0020,
28368 0x007F, 0x00A1,
28369 0x00AD, 0x00AE,
28370 // Chars that is used in complex-script shaping.
28371 0x0600, 0x0780,
28372 0x08A0, 0x10A0,
28373 0x1780, 0x1800,
28374 0x1C00, 0x1C50,
28375 // General punctuation chars.
28376 0x2000, 0x2010,
28377 0x2011, 0x2012,
28378 0x2028, 0x2030,
28379 0x205F, 0x2070,
28380 0x25CC, 0x25CD,
28381 0x3000, 0x3001,
28382 // Chars that is used in complex-script shaping.
28383 0xAA60, 0xAA80,
28384 // Specials Unicode block.
28385 0xFFF0, 0x10000
28386]);
28387
28388
28389/**
28390 * 'Font' is the class the outside world should use, it encapsulate all the font
28391 * decoding logics whatever type it is (assuming the font type is supported).
28392 *
28393 * For example to read a Type1 font and to attach it to the document:
28394 * var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
28395 * type1Font.bind();
28396 */
28397var Font = (function FontClosure() {
28398 function Font(name, file, properties) {
28399 var charCode, glyphName, unicode;
28400
28401 this.name = name;
28402 this.loadedName = properties.loadedName;
28403 this.isType3Font = properties.isType3Font;
28404 this.sizes = [];
28405 this.missingFile = false;
28406
28407 this.glyphCache = Object.create(null);
28408
28409 var names = name.split('+');
28410 names = names.length > 1 ? names[1] : names[0];
28411 names = names.split(/[-,_]/g)[0];
28412 this.isSerifFont = !!(properties.flags & FontFlags.Serif);
28413 this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
28414 this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);
28415
28416 var type = properties.type;
28417 var subtype = properties.subtype;
28418 this.type = type;
28419
28420 this.fallbackName = (this.isMonospace ? 'monospace' :
28421 (this.isSerifFont ? 'serif' : 'sans-serif'));
28422
28423 this.differences = properties.differences;
28424 this.widths = properties.widths;
28425 this.defaultWidth = properties.defaultWidth;
28426 this.composite = properties.composite;
28427 this.wideChars = properties.wideChars;
28428 this.cMap = properties.cMap;
28429 this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;
28430 this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;
28431 this.fontMatrix = properties.fontMatrix;
28432 this.bbox = properties.bbox;
28433
28434 this.toUnicode = properties.toUnicode;
28435
28436 this.toFontChar = [];
28437
28438 if (properties.type === 'Type3') {
28439 for (charCode = 0; charCode < 256; charCode++) {
28440 this.toFontChar[charCode] = (this.differences[charCode] ||
28441 properties.defaultEncoding[charCode]);
28442 }
28443 this.fontType = FontType.TYPE3;
28444 return;
28445 }
28446
28447 this.cidEncoding = properties.cidEncoding;
28448 this.vertical = properties.vertical;
28449 if (this.vertical) {
28450 this.vmetrics = properties.vmetrics;
28451 this.defaultVMetrics = properties.defaultVMetrics;
28452 }
28453 var glyphsUnicodeMap;
28454 if (!file || file.isEmpty) {
28455 if (file) {
28456 // Some bad PDF generators will include empty font files,
28457 // attempting to recover by assuming that no file exists.
28458 warn('Font file is empty in "' + name + '" (' + this.loadedName + ')');
28459 }
28460
28461 this.missingFile = true;
28462 // The file data is not specified. Trying to fix the font name
28463 // to be used with the canvas.font.
28464 var fontName = name.replace(/[,_]/g, '-');
28465 var stdFontMap = getStdFontMap(), nonStdFontMap = getNonStdFontMap();
28466 var isStandardFont = !!stdFontMap[fontName] ||
28467 !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]);
28468 fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
28469
28470 this.bold = (fontName.search(/bold/gi) !== -1);
28471 this.italic = ((fontName.search(/oblique/gi) !== -1) ||
28472 (fontName.search(/italic/gi) !== -1));
28473
28474 // Use 'name' instead of 'fontName' here because the original
28475 // name ArialBlack for example will be replaced by Helvetica.
28476 this.black = (name.search(/Black/g) !== -1);
28477
28478 // if at least one width is present, remeasure all chars when exists
28479 this.remeasure = Object.keys(this.widths).length > 0;
28480 if (isStandardFont && type === 'CIDFontType2' &&
28481 properties.cidEncoding.indexOf('Identity-') === 0) {
28482 var GlyphMapForStandardFonts = getGlyphMapForStandardFonts();
28483 // Standard fonts might be embedded as CID font without glyph mapping.
28484 // Building one based on GlyphMapForStandardFonts.
28485 var map = [];
28486 for (charCode in GlyphMapForStandardFonts) {
28487 map[+charCode] = GlyphMapForStandardFonts[charCode];
28488 }
28489 if (/ArialBlack/i.test(name)) {
28490 var SupplementalGlyphMapForArialBlack =
28491 getSupplementalGlyphMapForArialBlack();
28492 for (charCode in SupplementalGlyphMapForArialBlack) {
28493 map[+charCode] = SupplementalGlyphMapForArialBlack[charCode];
28494 }
28495 }
28496 var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap;
28497 if (!isIdentityUnicode) {
28498 this.toUnicode.forEach(function(charCode, unicodeCharCode) {
28499 map[+charCode] = unicodeCharCode;
28500 });
28501 }
28502 this.toFontChar = map;
28503 this.toUnicode = new ToUnicodeMap(map);
28504 } else if (/Symbol/i.test(fontName)) {
28505 this.toFontChar = buildToFontChar(SymbolSetEncoding, getGlyphsUnicode(),
28506 properties.differences);
28507 } else if (/Dingbats/i.test(fontName)) {
28508 if (/Wingdings/i.test(name)) {
28509 warn('Non-embedded Wingdings font, falling back to ZapfDingbats.');
28510 }
28511 this.toFontChar = buildToFontChar(ZapfDingbatsEncoding,
28512 getDingbatsGlyphsUnicode(),
28513 properties.differences);
28514 } else if (isStandardFont) {
28515 this.toFontChar = buildToFontChar(properties.defaultEncoding,
28516 getGlyphsUnicode(),
28517 properties.differences);
28518 } else {
28519 glyphsUnicodeMap = getGlyphsUnicode();
28520 this.toUnicode.forEach(function(charCode, unicodeCharCode) {
28521 if (!this.composite) {
28522 glyphName = (properties.differences[charCode] ||
28523 properties.defaultEncoding[charCode]);
28524 unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
28525 if (unicode !== -1) {
28526 unicodeCharCode = unicode;
28527 }
28528 }
28529 this.toFontChar[charCode] = unicodeCharCode;
28530 }.bind(this));
28531 }
28532 this.loadedName = fontName.split('-')[0];
28533 this.loading = false;
28534 this.fontType = getFontType(type, subtype);
28535 return;
28536 }
28537
28538 // Some fonts might use wrong font types for Type1C or CIDFontType0C
28539 if (subtype === 'Type1C') {
28540 if (type !== 'Type1' && type !== 'MMType1') {
28541 // Some TrueType fonts by mistake claim Type1C
28542 if (isTrueTypeFile(file)) {
28543 subtype = 'TrueType';
28544 } else {
28545 type = 'Type1';
28546 }
28547 } else if (isOpenTypeFile(file)) {
28548 // Sometimes the type/subtype can be a complete lie (see issue7598.pdf).
28549 type = subtype = 'OpenType';
28550 }
28551 }
28552 if (subtype === 'CIDFontType0C' && type !== 'CIDFontType0') {
28553 type = 'CIDFontType0';
28554 }
28555 if (subtype === 'OpenType') {
28556 type = 'OpenType';
28557 }
28558 // Some CIDFontType0C fonts by mistake claim CIDFontType0.
28559 if (type === 'CIDFontType0') {
28560 if (isType1File(file)) {
28561 subtype = 'CIDFontType0';
28562 } else if (isOpenTypeFile(file)) {
28563 // Sometimes the type/subtype can be a complete lie (see issue6782.pdf).
28564 type = subtype = 'OpenType';
28565 } else {
28566 subtype = 'CIDFontType0C';
28567 }
28568 }
28569
28570 var data;
28571 switch (type) {
28572 case 'MMType1':
28573 info('MMType1 font (' + name + '), falling back to Type1.');
28574 /* falls through */
28575 case 'Type1':
28576 case 'CIDFontType0':
28577 this.mimetype = 'font/opentype';
28578
28579 var cff = (subtype === 'Type1C' || subtype === 'CIDFontType0C') ?
28580 new CFFFont(file, properties) : new Type1Font(name, file, properties);
28581
28582 adjustWidths(properties);
28583
28584 // Wrap the CFF data inside an OTF font file
28585 data = this.convert(name, cff, properties);
28586 break;
28587
28588 case 'OpenType':
28589 case 'TrueType':
28590 case 'CIDFontType2':
28591 this.mimetype = 'font/opentype';
28592
28593 // Repair the TrueType file. It is can be damaged in the point of
28594 // view of the sanitizer
28595 data = this.checkAndRepair(name, file, properties);
28596 if (this.isOpenType) {
28597 adjustWidths(properties);
28598
28599 type = 'OpenType';
28600 }
28601 break;
28602
28603 default:
28604 error('Font ' + type + ' is not supported');
28605 break;
28606 }
28607
28608 this.data = data;
28609 this.fontType = getFontType(type, subtype);
28610
28611 // Transfer some properties again that could change during font conversion
28612 this.fontMatrix = properties.fontMatrix;
28613 this.widths = properties.widths;
28614 this.defaultWidth = properties.defaultWidth;
28615 this.toUnicode = properties.toUnicode;
28616 this.encoding = properties.baseEncoding;
28617 this.seacMap = properties.seacMap;
28618
28619 this.loading = true;
28620 }
28621
28622 Font.getFontID = (function () {
28623 var ID = 1;
28624 return function Font_getFontID() {
28625 return String(ID++);
28626 };
28627 })();
28628
28629 function int16(b0, b1) {
28630 return (b0 << 8) + b1;
28631 }
28632
28633 function signedInt16(b0, b1) {
28634 var value = (b0 << 8) + b1;
28635 return value & (1 << 15) ? value - 0x10000 : value;
28636 }
28637
28638 function int32(b0, b1, b2, b3) {
28639 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
28640 }
28641
28642 function string16(value) {
28643 return String.fromCharCode((value >> 8) & 0xff, value & 0xff);
28644 }
28645
28646 function safeString16(value) {
28647 // clamp value to the 16-bit int range
28648 value = (value > 0x7FFF ? 0x7FFF : (value < -0x8000 ? -0x8000 : value));
28649 return String.fromCharCode((value >> 8) & 0xff, value & 0xff);
28650 }
28651
28652 function isTrueTypeFile(file) {
28653 var header = file.peekBytes(4);
28654 return readUint32(header, 0) === 0x00010000;
28655 }
28656
28657 function isOpenTypeFile(file) {
28658 var header = file.peekBytes(4);
28659 return bytesToString(header) === 'OTTO';
28660 }
28661
28662 function isType1File(file) {
28663 var header = file.peekBytes(2);
28664 // All Type1 font programs must begin with the comment '%!' (0x25 + 0x21).
28665 if (header[0] === 0x25 && header[1] === 0x21) {
28666 return true;
28667 }
28668 // ... obviously some fonts violate that part of the specification,
28669 // please refer to the comment in |Type1Font| below.
28670 if (header[0] === 0x80 && header[1] === 0x01) { // pfb file header.
28671 return true;
28672 }
28673 return false;
28674 }
28675
28676 function buildToFontChar(encoding, glyphsUnicodeMap, differences) {
28677 var toFontChar = [], unicode;
28678 for (var i = 0, ii = encoding.length; i < ii; i++) {
28679 unicode = getUnicodeForGlyph(encoding[i], glyphsUnicodeMap);
28680 if (unicode !== -1) {
28681 toFontChar[i] = unicode;
28682 }
28683 }
28684 for (var charCode in differences) {
28685 unicode = getUnicodeForGlyph(differences[charCode], glyphsUnicodeMap);
28686 if (unicode !== -1) {
28687 toFontChar[+charCode] = unicode;
28688 }
28689 }
28690 return toFontChar;
28691 }
28692
28693 /**
28694 * Helper function for |adjustMapping|.
28695 * @return {boolean}
28696 */
28697 function isProblematicUnicodeLocation(code) {
28698 // Using binary search to find a range start.
28699 var i = 0, j = ProblematicCharRanges.length - 1;
28700 while (i < j) {
28701 var c = (i + j + 1) >> 1;
28702 if (code < ProblematicCharRanges[c]) {
28703 j = c - 1;
28704 } else {
28705 i = c;
28706 }
28707 }
28708 // Even index means code in problematic range.
28709 return !(i & 1);
28710 }
28711
28712 /**
28713 * Rebuilds the char code to glyph ID map by trying to replace the char codes
28714 * with their unicode value. It also moves char codes that are in known
28715 * problematic locations.
28716 * @return {Object} Two properties:
28717 * 'toFontChar' - maps original char codes(the value that will be read
28718 * from commands such as show text) to the char codes that will be used in the
28719 * font that we build
28720 * 'charCodeToGlyphId' - maps the new font char codes to glyph ids
28721 */
28722 function adjustMapping(charCodeToGlyphId, properties) {
28723 var toUnicode = properties.toUnicode;
28724 var isSymbolic = !!(properties.flags & FontFlags.Symbolic);
28725 var isIdentityUnicode =
28726 properties.toUnicode instanceof IdentityToUnicodeMap;
28727 var newMap = Object.create(null);
28728 var toFontChar = [];
28729 var usedFontCharCodes = [];
28730 var nextAvailableFontCharCode = PRIVATE_USE_OFFSET_START;
28731 for (var originalCharCode in charCodeToGlyphId) {
28732 originalCharCode |= 0;
28733 var glyphId = charCodeToGlyphId[originalCharCode];
28734 var fontCharCode = originalCharCode;
28735 // First try to map the value to a unicode position if a non identity map
28736 // was created.
28737 if (!isIdentityUnicode && toUnicode.has(originalCharCode)) {
28738 var unicode = toUnicode.get(fontCharCode);
28739 // TODO: Try to map ligatures to the correct spot.
28740 if (unicode.length === 1) {
28741 fontCharCode = unicode.charCodeAt(0);
28742 }
28743 }
28744 // Try to move control characters, special characters and already mapped
28745 // characters to the private use area since they will not be drawn by
28746 // canvas if left in their current position. Also, move characters if the
28747 // font was symbolic and there is only an identity unicode map since the
28748 // characters probably aren't in the correct position (fixes an issue
28749 // with firefox and thuluthfont).
28750 if ((usedFontCharCodes[fontCharCode] !== undefined ||
28751 isProblematicUnicodeLocation(fontCharCode) ||
28752 (isSymbolic && isIdentityUnicode)) &&
28753 nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) { // Room left.
28754 // Loop to try and find a free spot in the private use area.
28755 do {
28756 fontCharCode = nextAvailableFontCharCode++;
28757
28758 if (SKIP_PRIVATE_USE_RANGE_F000_TO_F01F && fontCharCode === 0xF000) {
28759 fontCharCode = 0xF020;
28760 nextAvailableFontCharCode = fontCharCode + 1;
28761 }
28762
28763 } while (usedFontCharCodes[fontCharCode] !== undefined &&
28764 nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END);
28765 }
28766
28767 newMap[fontCharCode] = glyphId;
28768 toFontChar[originalCharCode] = fontCharCode;
28769 usedFontCharCodes[fontCharCode] = true;
28770 }
28771 return {
28772 toFontChar: toFontChar,
28773 charCodeToGlyphId: newMap,
28774 nextAvailableFontCharCode: nextAvailableFontCharCode
28775 };
28776 }
28777
28778 function getRanges(glyphs, numGlyphs) {
28779 // Array.sort() sorts by characters, not numerically, so convert to an
28780 // array of characters.
28781 var codes = [];
28782 for (var charCode in glyphs) {
28783 // Remove an invalid glyph ID mappings to make OTS happy.
28784 if (glyphs[charCode] >= numGlyphs) {
28785 continue;
28786 }
28787 codes.push({ fontCharCode: charCode | 0, glyphId: glyphs[charCode] });
28788 }
28789 codes.sort(function fontGetRangesSort(a, b) {
28790 return a.fontCharCode - b.fontCharCode;
28791 });
28792
28793 // Split the sorted codes into ranges.
28794 var ranges = [];
28795 var length = codes.length;
28796 for (var n = 0; n < length; ) {
28797 var start = codes[n].fontCharCode;
28798 var codeIndices = [codes[n].glyphId];
28799 ++n;
28800 var end = start;
28801 while (n < length && end + 1 === codes[n].fontCharCode) {
28802 codeIndices.push(codes[n].glyphId);
28803 ++end;
28804 ++n;
28805 if (end === 0xFFFF) {
28806 break;
28807 }
28808 }
28809 ranges.push([start, end, codeIndices]);
28810 }
28811
28812 return ranges;
28813 }
28814
28815 function createCmapTable(glyphs, numGlyphs) {
28816 var ranges = getRanges(glyphs, numGlyphs);
28817 var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1;
28818 var cmap = '\x00\x00' + // version
28819 string16(numTables) + // numTables
28820 '\x00\x03' + // platformID
28821 '\x00\x01' + // encodingID
28822 string32(4 + numTables * 8); // start of the table record
28823
28824 var i, ii, j, jj;
28825 for (i = ranges.length - 1; i >= 0; --i) {
28826 if (ranges[i][0] <= 0xFFFF) { break; }
28827 }
28828 var bmpLength = i + 1;
28829
28830 if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) {
28831 ranges[i][1] = 0xFFFE;
28832 }
28833 var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0;
28834 var segCount = bmpLength + trailingRangesCount;
28835 var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2);
28836
28837 // Fill up the 4 parallel arrays describing the segments.
28838 var startCount = '';
28839 var endCount = '';
28840 var idDeltas = '';
28841 var idRangeOffsets = '';
28842 var glyphsIds = '';
28843 var bias = 0;
28844
28845 var range, start, end, codes;
28846 for (i = 0, ii = bmpLength; i < ii; i++) {
28847 range = ranges[i];
28848 start = range[0];
28849 end = range[1];
28850 startCount += string16(start);
28851 endCount += string16(end);
28852 codes = range[2];
28853 var contiguous = true;
28854 for (j = 1, jj = codes.length; j < jj; ++j) {
28855 if (codes[j] !== codes[j - 1] + 1) {
28856 contiguous = false;
28857 break;
28858 }
28859 }
28860 if (!contiguous) {
28861 var offset = (segCount - i) * 2 + bias * 2;
28862 bias += (end - start + 1);
28863
28864 idDeltas += string16(0);
28865 idRangeOffsets += string16(offset);
28866
28867 for (j = 0, jj = codes.length; j < jj; ++j) {
28868 glyphsIds += string16(codes[j]);
28869 }
28870 } else {
28871 var startCode = codes[0];
28872
28873 idDeltas += string16((startCode - start) & 0xFFFF);
28874 idRangeOffsets += string16(0);
28875 }
28876 }
28877
28878 if (trailingRangesCount > 0) {
28879 endCount += '\xFF\xFF';
28880 startCount += '\xFF\xFF';
28881 idDeltas += '\x00\x01';
28882 idRangeOffsets += '\x00\x00';
28883 }
28884
28885 var format314 = '\x00\x00' + // language
28886 string16(2 * segCount) +
28887 string16(searchParams.range) +
28888 string16(searchParams.entry) +
28889 string16(searchParams.rangeShift) +
28890 endCount + '\x00\x00' + startCount +
28891 idDeltas + idRangeOffsets + glyphsIds;
28892
28893 var format31012 = '';
28894 var header31012 = '';
28895 if (numTables > 1) {
28896 cmap += '\x00\x03' + // platformID
28897 '\x00\x0A' + // encodingID
28898 string32(4 + numTables * 8 +
28899 4 + format314.length); // start of the table record
28900 format31012 = '';
28901 for (i = 0, ii = ranges.length; i < ii; i++) {
28902 range = ranges[i];
28903 start = range[0];
28904 codes = range[2];
28905 var code = codes[0];
28906 for (j = 1, jj = codes.length; j < jj; ++j) {
28907 if (codes[j] !== codes[j - 1] + 1) {
28908 end = range[0] + j - 1;
28909 format31012 += string32(start) + // startCharCode
28910 string32(end) + // endCharCode
28911 string32(code); // startGlyphID
28912 start = end + 1;
28913 code = codes[j];
28914 }
28915 }
28916 format31012 += string32(start) + // startCharCode
28917 string32(range[1]) + // endCharCode
28918 string32(code); // startGlyphID
28919 }
28920 header31012 = '\x00\x0C' + // format
28921 '\x00\x00' + // reserved
28922 string32(format31012.length + 16) + // length
28923 '\x00\x00\x00\x00' + // language
28924 string32(format31012.length / 12); // nGroups
28925 }
28926
28927 return cmap + '\x00\x04' + // format
28928 string16(format314.length + 4) + // length
28929 format314 + header31012 + format31012;
28930 }
28931
28932 function validateOS2Table(os2) {
28933 var stream = new Stream(os2.data);
28934 var version = stream.getUint16();
28935 // TODO verify all OS/2 tables fields, but currently we validate only those
28936 // that give us issues
28937 stream.getBytes(60); // skipping type, misc sizes, panose, unicode ranges
28938 var selection = stream.getUint16();
28939 if (version < 4 && (selection & 0x0300)) {
28940 return false;
28941 }
28942 var firstChar = stream.getUint16();
28943 var lastChar = stream.getUint16();
28944 if (firstChar > lastChar) {
28945 return false;
28946 }
28947 stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap
28948 var usWinAscent = stream.getUint16();
28949 if (usWinAscent === 0) { // makes font unreadable by windows
28950 return false;
28951 }
28952
28953 // OS/2 appears to be valid, resetting some fields
28954 os2.data[8] = os2.data[9] = 0; // IE rejects fonts if fsType != 0
28955 return true;
28956 }
28957
28958 function createOS2Table(properties, charstrings, override) {
28959 override = override || {
28960 unitsPerEm: 0,
28961 yMax: 0,
28962 yMin: 0,
28963 ascent: 0,
28964 descent: 0
28965 };
28966
28967 var ulUnicodeRange1 = 0;
28968 var ulUnicodeRange2 = 0;
28969 var ulUnicodeRange3 = 0;
28970 var ulUnicodeRange4 = 0;
28971
28972 var firstCharIndex = null;
28973 var lastCharIndex = 0;
28974
28975 if (charstrings) {
28976 for (var code in charstrings) {
28977 code |= 0;
28978 if (firstCharIndex > code || !firstCharIndex) {
28979 firstCharIndex = code;
28980 }
28981 if (lastCharIndex < code) {
28982 lastCharIndex = code;
28983 }
28984
28985 var position = getUnicodeRangeFor(code);
28986 if (position < 32) {
28987 ulUnicodeRange1 |= 1 << position;
28988 } else if (position < 64) {
28989 ulUnicodeRange2 |= 1 << position - 32;
28990 } else if (position < 96) {
28991 ulUnicodeRange3 |= 1 << position - 64;
28992 } else if (position < 123) {
28993 ulUnicodeRange4 |= 1 << position - 96;
28994 } else {
28995 error('Unicode ranges Bits > 123 are reserved for internal usage');
28996 }
28997 }
28998 } else {
28999 // TODO
29000 firstCharIndex = 0;
29001 lastCharIndex = 255;
29002 }
29003
29004 var bbox = properties.bbox || [0, 0, 0, 0];
29005 var unitsPerEm = (override.unitsPerEm ||
29006 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]);
29007
29008 // if the font units differ to the PDF glyph space units
29009 // then scale up the values
29010 var scale = (properties.ascentScaled ? 1.0 :
29011 unitsPerEm / PDF_GLYPH_SPACE_UNITS);
29012
29013 var typoAscent = (override.ascent ||
29014 Math.round(scale * (properties.ascent || bbox[3])));
29015 var typoDescent = (override.descent ||
29016 Math.round(scale * (properties.descent || bbox[1])));
29017 if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {
29018 typoDescent = -typoDescent; // fixing incorrect descent
29019 }
29020 var winAscent = override.yMax || typoAscent;
29021 var winDescent = -override.yMin || -typoDescent;
29022
29023 return '\x00\x03' + // version
29024 '\x02\x24' + // xAvgCharWidth
29025 '\x01\xF4' + // usWeightClass
29026 '\x00\x05' + // usWidthClass
29027 '\x00\x00' + // fstype (0 to let the font loads via font-face on IE)
29028 '\x02\x8A' + // ySubscriptXSize
29029 '\x02\xBB' + // ySubscriptYSize
29030 '\x00\x00' + // ySubscriptXOffset
29031 '\x00\x8C' + // ySubscriptYOffset
29032 '\x02\x8A' + // ySuperScriptXSize
29033 '\x02\xBB' + // ySuperScriptYSize
29034 '\x00\x00' + // ySuperScriptXOffset
29035 '\x01\xDF' + // ySuperScriptYOffset
29036 '\x00\x31' + // yStrikeOutSize
29037 '\x01\x02' + // yStrikeOutPosition
29038 '\x00\x00' + // sFamilyClass
29039 '\x00\x00\x06' +
29040 String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) +
29041 '\x00\x00\x00\x00\x00\x00' + // Panose
29042 string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31)
29043 string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63)
29044 string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95)
29045 string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127)
29046 '\x2A\x32\x31\x2A' + // achVendID
29047 string16(properties.italicAngle ? 1 : 0) + // fsSelection
29048 string16(firstCharIndex ||
29049 properties.firstChar) + // usFirstCharIndex
29050 string16(lastCharIndex || properties.lastChar) + // usLastCharIndex
29051 string16(typoAscent) + // sTypoAscender
29052 string16(typoDescent) + // sTypoDescender
29053 '\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value)
29054 string16(winAscent) + // usWinAscent
29055 string16(winDescent) + // usWinDescent
29056 '\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31)
29057 '\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63)
29058 string16(properties.xHeight) + // sxHeight
29059 string16(properties.capHeight) + // sCapHeight
29060 string16(0) + // usDefaultChar
29061 string16(firstCharIndex || properties.firstChar) + // usBreakChar
29062 '\x00\x03'; // usMaxContext
29063 }
29064
29065 function createPostTable(properties) {
29066 var angle = Math.floor(properties.italicAngle * (Math.pow(2, 16)));
29067 return ('\x00\x03\x00\x00' + // Version number
29068 string32(angle) + // italicAngle
29069 '\x00\x00' + // underlinePosition
29070 '\x00\x00' + // underlineThickness
29071 string32(properties.fixedPitch) + // isFixedPitch
29072 '\x00\x00\x00\x00' + // minMemType42
29073 '\x00\x00\x00\x00' + // maxMemType42
29074 '\x00\x00\x00\x00' + // minMemType1
29075 '\x00\x00\x00\x00'); // maxMemType1
29076 }
29077
29078 function createNameTable(name, proto) {
29079 if (!proto) {
29080 proto = [[], []]; // no strings and unicode strings
29081 }
29082
29083 var strings = [
29084 proto[0][0] || 'Original licence', // 0.Copyright
29085 proto[0][1] || name, // 1.Font family
29086 proto[0][2] || 'Unknown', // 2.Font subfamily (font weight)
29087 proto[0][3] || 'uniqueID', // 3.Unique ID
29088 proto[0][4] || name, // 4.Full font name
29089 proto[0][5] || 'Version 0.11', // 5.Version
29090 proto[0][6] || '', // 6.Postscript name
29091 proto[0][7] || 'Unknown', // 7.Trademark
29092 proto[0][8] || 'Unknown', // 8.Manufacturer
29093 proto[0][9] || 'Unknown' // 9.Designer
29094 ];
29095
29096 // Mac want 1-byte per character strings while Windows want
29097 // 2-bytes per character, so duplicate the names table
29098 var stringsUnicode = [];
29099 var i, ii, j, jj, str;
29100 for (i = 0, ii = strings.length; i < ii; i++) {
29101 str = proto[1][i] || strings[i];
29102
29103 var strBufUnicode = [];
29104 for (j = 0, jj = str.length; j < jj; j++) {
29105 strBufUnicode.push(string16(str.charCodeAt(j)));
29106 }
29107 stringsUnicode.push(strBufUnicode.join(''));
29108 }
29109
29110 var names = [strings, stringsUnicode];
29111 var platforms = ['\x00\x01', '\x00\x03'];
29112 var encodings = ['\x00\x00', '\x00\x01'];
29113 var languages = ['\x00\x00', '\x04\x09'];
29114
29115 var namesRecordCount = strings.length * platforms.length;
29116 var nameTable =
29117 '\x00\x00' + // format
29118 string16(namesRecordCount) + // Number of names Record
29119 string16(namesRecordCount * 12 + 6); // Storage
29120
29121 // Build the name records field
29122 var strOffset = 0;
29123 for (i = 0, ii = platforms.length; i < ii; i++) {
29124 var strs = names[i];
29125 for (j = 0, jj = strs.length; j < jj; j++) {
29126 str = strs[j];
29127 var nameRecord =
29128 platforms[i] + // platform ID
29129 encodings[i] + // encoding ID
29130 languages[i] + // language ID
29131 string16(j) + // name ID
29132 string16(str.length) +
29133 string16(strOffset);
29134 nameTable += nameRecord;
29135 strOffset += str.length;
29136 }
29137 }
29138
29139 nameTable += strings.join('') + stringsUnicode.join('');
29140 return nameTable;
29141 }
29142
29143 Font.prototype = {
29144 name: null,
29145 font: null,
29146 mimetype: null,
29147 encoding: null,
29148 get renderer() {
29149 var renderer = FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED);
29150 return shadow(this, 'renderer', renderer);
29151 },
29152
29153 exportData: function Font_exportData() {
29154 // TODO remove enumerating of the properties, e.g. hardcode exact names.
29155 var data = {};
29156 for (var i in this) {
29157 if (this.hasOwnProperty(i)) {
29158 data[i] = this[i];
29159 }
29160 }
29161 return data;
29162 },
29163
29164 checkAndRepair: function Font_checkAndRepair(name, font, properties) {
29165 function readTableEntry(file) {
29166 var tag = bytesToString(file.getBytes(4));
29167
29168 var checksum = file.getInt32() >>> 0;
29169 var offset = file.getInt32() >>> 0;
29170 var length = file.getInt32() >>> 0;
29171
29172 // Read the table associated data
29173 var previousPosition = file.pos;
29174 file.pos = file.start ? file.start : 0;
29175 file.skip(offset);
29176 var data = file.getBytes(length);
29177 file.pos = previousPosition;
29178
29179 if (tag === 'head') {
29180 // clearing checksum adjustment
29181 data[8] = data[9] = data[10] = data[11] = 0;
29182 data[17] |= 0x20; //Set font optimized for cleartype flag
29183 }
29184
29185 return {
29186 tag: tag,
29187 checksum: checksum,
29188 length: length,
29189 offset: offset,
29190 data: data
29191 };
29192 }
29193
29194 function readOpenTypeHeader(ttf) {
29195 return {
29196 version: bytesToString(ttf.getBytes(4)),
29197 numTables: ttf.getUint16(),
29198 searchRange: ttf.getUint16(),
29199 entrySelector: ttf.getUint16(),
29200 rangeShift: ttf.getUint16()
29201 };
29202 }
29203
29204 /**
29205 * Read the appropriate subtable from the cmap according to 9.6.6.4 from
29206 * PDF spec
29207 */
29208 function readCmapTable(cmap, font, isSymbolicFont, hasEncoding) {
29209 if (!cmap) {
29210 warn('No cmap table available.');
29211 return {
29212 platformId: -1,
29213 encodingId: -1,
29214 mappings: [],
29215 hasShortCmap: false
29216 };
29217 }
29218 var segment;
29219 var start = (font.start ? font.start : 0) + cmap.offset;
29220 font.pos = start;
29221
29222 var version = font.getUint16();
29223 var numTables = font.getUint16();
29224
29225 var potentialTable;
29226 var canBreak = false;
29227 // There's an order of preference in terms of which cmap subtable to
29228 // use:
29229 // - non-symbolic fonts the preference is a 3,1 table then a 1,0 table
29230 // - symbolic fonts the preference is a 3,0 table then a 1,0 table
29231 // The following takes advantage of the fact that the tables are sorted
29232 // to work.
29233 for (var i = 0; i < numTables; i++) {
29234 var platformId = font.getUint16();
29235 var encodingId = font.getUint16();
29236 var offset = font.getInt32() >>> 0;
29237 var useTable = false;
29238
29239 if (platformId === 0 && encodingId === 0) {
29240 useTable = true;
29241 // Continue the loop since there still may be a higher priority
29242 // table.
29243 } else if (platformId === 1 && encodingId === 0) {
29244 useTable = true;
29245 // Continue the loop since there still may be a higher priority
29246 // table.
29247 } else if (platformId === 3 && encodingId === 1 &&
29248 ((!isSymbolicFont && hasEncoding) || !potentialTable)) {
29249 useTable = true;
29250 if (!isSymbolicFont) {
29251 canBreak = true;
29252 }
29253 } else if (isSymbolicFont && platformId === 3 && encodingId === 0) {
29254 useTable = true;
29255 canBreak = true;
29256 }
29257
29258 if (useTable) {
29259 potentialTable = {
29260 platformId: platformId,
29261 encodingId: encodingId,
29262 offset: offset
29263 };
29264 }
29265 if (canBreak) {
29266 break;
29267 }
29268 }
29269
29270 if (potentialTable) {
29271 font.pos = start + potentialTable.offset;
29272 }
29273 if (!potentialTable || font.peekByte() === -1) {
29274 warn('Could not find a preferred cmap table.');
29275 return {
29276 platformId: -1,
29277 encodingId: -1,
29278 mappings: [],
29279 hasShortCmap: false
29280 };
29281 }
29282
29283 var format = font.getUint16();
29284 var length = font.getUint16();
29285 var language = font.getUint16();
29286
29287 var hasShortCmap = false;
29288 var mappings = [];
29289 var j, glyphId;
29290
29291 // TODO(mack): refactor this cmap subtable reading logic out
29292 if (format === 0) {
29293 for (j = 0; j < 256; j++) {
29294 var index = font.getByte();
29295 if (!index) {
29296 continue;
29297 }
29298 mappings.push({
29299 charCode: j,
29300 glyphId: index
29301 });
29302 }
29303 hasShortCmap = true;
29304 } else if (format === 4) {
29305 // re-creating the table in format 4 since the encoding
29306 // might be changed
29307 var segCount = (font.getUint16() >> 1);
29308 font.getBytes(6); // skipping range fields
29309 var segIndex, segments = [];
29310 for (segIndex = 0; segIndex < segCount; segIndex++) {
29311 segments.push({ end: font.getUint16() });
29312 }
29313 font.getUint16();
29314 for (segIndex = 0; segIndex < segCount; segIndex++) {
29315 segments[segIndex].start = font.getUint16();
29316 }
29317
29318 for (segIndex = 0; segIndex < segCount; segIndex++) {
29319 segments[segIndex].delta = font.getUint16();
29320 }
29321
29322 var offsetsCount = 0;
29323 for (segIndex = 0; segIndex < segCount; segIndex++) {
29324 segment = segments[segIndex];
29325 var rangeOffset = font.getUint16();
29326 if (!rangeOffset) {
29327 segment.offsetIndex = -1;
29328 continue;
29329 }
29330
29331 var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex);
29332 segment.offsetIndex = offsetIndex;
29333 offsetsCount = Math.max(offsetsCount, offsetIndex +
29334 segment.end - segment.start + 1);
29335 }
29336
29337 var offsets = [];
29338 for (j = 0; j < offsetsCount; j++) {
29339 offsets.push(font.getUint16());
29340 }
29341
29342 for (segIndex = 0; segIndex < segCount; segIndex++) {
29343 segment = segments[segIndex];
29344 start = segment.start;
29345 var end = segment.end;
29346 var delta = segment.delta;
29347 offsetIndex = segment.offsetIndex;
29348
29349 for (j = start; j <= end; j++) {
29350 if (j === 0xFFFF) {
29351 continue;
29352 }
29353
29354 glyphId = (offsetIndex < 0 ?
29355 j : offsets[offsetIndex + j - start]);
29356 glyphId = (glyphId + delta) & 0xFFFF;
29357 if (glyphId === 0) {
29358 continue;
29359 }
29360 mappings.push({
29361 charCode: j,
29362 glyphId: glyphId
29363 });
29364 }
29365 }
29366 } else if (format === 6) {
29367 // Format 6 is a 2-bytes dense mapping, which means the font data
29368 // lives glue together even if they are pretty far in the unicode
29369 // table. (This looks weird, so I can have missed something), this
29370 // works on Linux but seems to fails on Mac so let's rewrite the
29371 // cmap table to a 3-1-4 style
29372 var firstCode = font.getUint16();
29373 var entryCount = font.getUint16();
29374
29375 for (j = 0; j < entryCount; j++) {
29376 glyphId = font.getUint16();
29377 var charCode = firstCode + j;
29378
29379 mappings.push({
29380 charCode: charCode,
29381 glyphId: glyphId
29382 });
29383 }
29384 } else {
29385 warn('cmap table has unsupported format: ' + format);
29386 return {
29387 platformId: -1,
29388 encodingId: -1,
29389 mappings: [],
29390 hasShortCmap: false
29391 };
29392 }
29393
29394 // removing duplicate entries
29395 mappings.sort(function (a, b) {
29396 return a.charCode - b.charCode;
29397 });
29398 for (i = 1; i < mappings.length; i++) {
29399 if (mappings[i - 1].charCode === mappings[i].charCode) {
29400 mappings.splice(i, 1);
29401 i--;
29402 }
29403 }
29404
29405 return {
29406 platformId: potentialTable.platformId,
29407 encodingId: potentialTable.encodingId,
29408 mappings: mappings,
29409 hasShortCmap: hasShortCmap
29410 };
29411 }
29412
29413 function sanitizeMetrics(font, header, metrics, numGlyphs) {
29414 if (!header) {
29415 if (metrics) {
29416 metrics.data = null;
29417 }
29418 return;
29419 }
29420
29421 font.pos = (font.start ? font.start : 0) + header.offset;
29422 font.pos += header.length - 2;
29423 var numOfMetrics = font.getUint16();
29424
29425 if (numOfMetrics > numGlyphs) {
29426 info('The numOfMetrics (' + numOfMetrics + ') should not be ' +
29427 'greater than the numGlyphs (' + numGlyphs + ')');
29428 // Reduce numOfMetrics if it is greater than numGlyphs
29429 numOfMetrics = numGlyphs;
29430 header.data[34] = (numOfMetrics & 0xff00) >> 8;
29431 header.data[35] = numOfMetrics & 0x00ff;
29432 }
29433
29434 var numOfSidebearings = numGlyphs - numOfMetrics;
29435 var numMissing = numOfSidebearings -
29436 ((metrics.length - numOfMetrics * 4) >> 1);
29437
29438 if (numMissing > 0) {
29439 // For each missing glyph, we set both the width and lsb to 0 (zero).
29440 // Since we need to add two properties for each glyph, this explains
29441 // the use of |numMissing * 2| when initializing the typed array.
29442 var entries = new Uint8Array(metrics.length + numMissing * 2);
29443 entries.set(metrics.data);
29444 metrics.data = entries;
29445 }
29446 }
29447
29448 function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart,
29449 hintsValid) {
29450 if (sourceEnd - sourceStart <= 12) {
29451 // glyph with data less than 12 is invalid one
29452 return 0;
29453 }
29454 var glyf = source.subarray(sourceStart, sourceEnd);
29455 var contoursCount = (glyf[0] << 8) | glyf[1];
29456 if (contoursCount & 0x8000) {
29457 // complex glyph, writing as is
29458 dest.set(glyf, destStart);
29459 return glyf.length;
29460 }
29461
29462 var i, j = 10, flagsCount = 0;
29463 for (i = 0; i < contoursCount; i++) {
29464 var endPoint = (glyf[j] << 8) | glyf[j + 1];
29465 flagsCount = endPoint + 1;
29466 j += 2;
29467 }
29468 // skipping instructions
29469 var instructionsStart = j;
29470 var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
29471 j += 2 + instructionsLength;
29472 var instructionsEnd = j;
29473 // validating flags
29474 var coordinatesLength = 0;
29475 for (i = 0; i < flagsCount; i++) {
29476 var flag = glyf[j++];
29477 if (flag & 0xC0) {
29478 // reserved flags must be zero, cleaning up
29479 glyf[j - 1] = flag & 0x3F;
29480 }
29481 var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) +
29482 ((flag & 4) ? 1 : (flag & 32) ? 0 : 2);
29483 coordinatesLength += xyLength;
29484 if (flag & 8) {
29485 var repeat = glyf[j++];
29486 i += repeat;
29487 coordinatesLength += repeat * xyLength;
29488 }
29489 }
29490 // glyph without coordinates will be rejected
29491 if (coordinatesLength === 0) {
29492 return 0;
29493 }
29494 var glyphDataLength = j + coordinatesLength;
29495 if (glyphDataLength > glyf.length) {
29496 // not enough data for coordinates
29497 return 0;
29498 }
29499 if (!hintsValid && instructionsLength > 0) {
29500 dest.set(glyf.subarray(0, instructionsStart), destStart);
29501 dest.set([0, 0], destStart + instructionsStart);
29502 dest.set(glyf.subarray(instructionsEnd, glyphDataLength),
29503 destStart + instructionsStart + 2);
29504 glyphDataLength -= instructionsLength;
29505 if (glyf.length - glyphDataLength > 3) {
29506 glyphDataLength = (glyphDataLength + 3) & ~3;
29507 }
29508 return glyphDataLength;
29509 }
29510 if (glyf.length - glyphDataLength > 3) {
29511 // truncating and aligning to 4 bytes the long glyph data
29512 glyphDataLength = (glyphDataLength + 3) & ~3;
29513 dest.set(glyf.subarray(0, glyphDataLength), destStart);
29514 return glyphDataLength;
29515 }
29516 // glyph data is fine
29517 dest.set(glyf, destStart);
29518 return glyf.length;
29519 }
29520
29521 function sanitizeHead(head, numGlyphs, locaLength) {
29522 var data = head.data;
29523
29524 // Validate version:
29525 // Should always be 0x00010000
29526 var version = int32(data[0], data[1], data[2], data[3]);
29527 if (version >> 16 !== 1) {
29528 info('Attempting to fix invalid version in head table: ' + version);
29529 data[0] = 0;
29530 data[1] = 1;
29531 data[2] = 0;
29532 data[3] = 0;
29533 }
29534
29535 var indexToLocFormat = int16(data[50], data[51]);
29536 if (indexToLocFormat < 0 || indexToLocFormat > 1) {
29537 info('Attempting to fix invalid indexToLocFormat in head table: ' +
29538 indexToLocFormat);
29539
29540 // The value of indexToLocFormat should be 0 if the loca table
29541 // consists of short offsets, and should be 1 if the loca table
29542 // consists of long offsets.
29543 //
29544 // The number of entries in the loca table should be numGlyphs + 1.
29545 //
29546 // Using this information, we can work backwards to deduce if the
29547 // size of each offset in the loca table, and thus figure out the
29548 // appropriate value for indexToLocFormat.
29549
29550 var numGlyphsPlusOne = numGlyphs + 1;
29551 if (locaLength === numGlyphsPlusOne << 1) {
29552 // 0x0000 indicates the loca table consists of short offsets
29553 data[50] = 0;
29554 data[51] = 0;
29555 } else if (locaLength === numGlyphsPlusOne << 2) {
29556 // 0x0001 indicates the loca table consists of long offsets
29557 data[50] = 0;
29558 data[51] = 1;
29559 } else {
29560 warn('Could not fix indexToLocFormat: ' + indexToLocFormat);
29561 }
29562 }
29563 }
29564
29565 function sanitizeGlyphLocations(loca, glyf, numGlyphs,
29566 isGlyphLocationsLong, hintsValid,
29567 dupFirstEntry) {
29568 var itemSize, itemDecode, itemEncode;
29569 if (isGlyphLocationsLong) {
29570 itemSize = 4;
29571 itemDecode = function fontItemDecodeLong(data, offset) {
29572 return (data[offset] << 24) | (data[offset + 1] << 16) |
29573 (data[offset + 2] << 8) | data[offset + 3];
29574 };
29575 itemEncode = function fontItemEncodeLong(data, offset, value) {
29576 data[offset] = (value >>> 24) & 0xFF;
29577 data[offset + 1] = (value >> 16) & 0xFF;
29578 data[offset + 2] = (value >> 8) & 0xFF;
29579 data[offset + 3] = value & 0xFF;
29580 };
29581 } else {
29582 itemSize = 2;
29583 itemDecode = function fontItemDecode(data, offset) {
29584 return (data[offset] << 9) | (data[offset + 1] << 1);
29585 };
29586 itemEncode = function fontItemEncode(data, offset, value) {
29587 data[offset] = (value >> 9) & 0xFF;
29588 data[offset + 1] = (value >> 1) & 0xFF;
29589 };
29590 }
29591 var locaData = loca.data;
29592 var locaDataSize = itemSize * (1 + numGlyphs);
29593 // is loca.data too short or long?
29594 if (locaData.length !== locaDataSize) {
29595 locaData = new Uint8Array(locaDataSize);
29596 locaData.set(loca.data.subarray(0, locaDataSize));
29597 loca.data = locaData;
29598 }
29599 // removing the invalid glyphs
29600 var oldGlyfData = glyf.data;
29601 var oldGlyfDataLength = oldGlyfData.length;
29602 var newGlyfData = new Uint8Array(oldGlyfDataLength);
29603 var startOffset = itemDecode(locaData, 0);
29604 var writeOffset = 0;
29605 var missingGlyphData = Object.create(null);
29606 itemEncode(locaData, 0, writeOffset);
29607 var i, j;
29608 for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
29609 var endOffset = itemDecode(locaData, j);
29610 if (endOffset > oldGlyfDataLength &&
29611 ((oldGlyfDataLength + 3) & ~3) === endOffset) {
29612 // Aspose breaks fonts by aligning the glyphs to the qword, but not
29613 // the glyf table size, which makes last glyph out of range.
29614 endOffset = oldGlyfDataLength;
29615 }
29616 if (endOffset > oldGlyfDataLength) {
29617 // glyph end offset points outside glyf data, rejecting the glyph
29618 itemEncode(locaData, j, writeOffset);
29619 startOffset = endOffset;
29620 continue;
29621 }
29622
29623 if (startOffset === endOffset) {
29624 missingGlyphData[i] = true;
29625 }
29626
29627 var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
29628 newGlyfData, writeOffset, hintsValid);
29629 writeOffset += newLength;
29630 itemEncode(locaData, j, writeOffset);
29631 startOffset = endOffset;
29632 }
29633
29634 if (writeOffset === 0) {
29635 // glyf table cannot be empty -- redoing the glyf and loca tables
29636 // to have single glyph with one point
29637 var simpleGlyph = new Uint8Array(
29638 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]);
29639 for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
29640 itemEncode(locaData, j, simpleGlyph.length);
29641 }
29642 glyf.data = simpleGlyph;
29643 return missingGlyphData;
29644 }
29645
29646 if (dupFirstEntry) {
29647 var firstEntryLength = itemDecode(locaData, itemSize);
29648 if (newGlyfData.length > firstEntryLength + writeOffset) {
29649 glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
29650 } else {
29651 glyf.data = new Uint8Array(firstEntryLength + writeOffset);
29652 glyf.data.set(newGlyfData.subarray(0, writeOffset));
29653 }
29654 glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);
29655 itemEncode(loca.data, locaData.length - itemSize,
29656 writeOffset + firstEntryLength);
29657 } else {
29658 glyf.data = newGlyfData.subarray(0, writeOffset);
29659 }
29660 return missingGlyphData;
29661 }
29662
29663 function readPostScriptTable(post, properties, maxpNumGlyphs) {
29664 var start = (font.start ? font.start : 0) + post.offset;
29665 font.pos = start;
29666
29667 var length = post.length, end = start + length;
29668 var version = font.getInt32();
29669 // skip rest to the tables
29670 font.getBytes(28);
29671
29672 var glyphNames;
29673 var valid = true;
29674 var i;
29675
29676 switch (version) {
29677 case 0x00010000:
29678 glyphNames = MacStandardGlyphOrdering;
29679 break;
29680 case 0x00020000:
29681 var numGlyphs = font.getUint16();
29682 if (numGlyphs !== maxpNumGlyphs) {
29683 valid = false;
29684 break;
29685 }
29686 var glyphNameIndexes = [];
29687 for (i = 0; i < numGlyphs; ++i) {
29688 var index = font.getUint16();
29689 if (index >= 32768) {
29690 valid = false;
29691 break;
29692 }
29693 glyphNameIndexes.push(index);
29694 }
29695 if (!valid) {
29696 break;
29697 }
29698 var customNames = [];
29699 var strBuf = [];
29700 while (font.pos < end) {
29701 var stringLength = font.getByte();
29702 strBuf.length = stringLength;
29703 for (i = 0; i < stringLength; ++i) {
29704 strBuf[i] = String.fromCharCode(font.getByte());
29705 }
29706 customNames.push(strBuf.join(''));
29707 }
29708 glyphNames = [];
29709 for (i = 0; i < numGlyphs; ++i) {
29710 var j = glyphNameIndexes[i];
29711 if (j < 258) {
29712 glyphNames.push(MacStandardGlyphOrdering[j]);
29713 continue;
29714 }
29715 glyphNames.push(customNames[j - 258]);
29716 }
29717 break;
29718 case 0x00030000:
29719 break;
29720 default:
29721 warn('Unknown/unsupported post table version ' + version);
29722 valid = false;
29723 if (properties.defaultEncoding) {
29724 glyphNames = properties.defaultEncoding;
29725 }
29726 break;
29727 }
29728 properties.glyphNames = glyphNames;
29729 return valid;
29730 }
29731
29732 function readNameTable(nameTable) {
29733 var start = (font.start ? font.start : 0) + nameTable.offset;
29734 font.pos = start;
29735
29736 var names = [[], []];
29737 var length = nameTable.length, end = start + length;
29738 var format = font.getUint16();
29739 var FORMAT_0_HEADER_LENGTH = 6;
29740 if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) {
29741 // unsupported name table format or table "too" small
29742 return names;
29743 }
29744 var numRecords = font.getUint16();
29745 var stringsStart = font.getUint16();
29746 var records = [];
29747 var NAME_RECORD_LENGTH = 12;
29748 var i, ii;
29749
29750 for (i = 0; i < numRecords &&
29751 font.pos + NAME_RECORD_LENGTH <= end; i++) {
29752 var r = {
29753 platform: font.getUint16(),
29754 encoding: font.getUint16(),
29755 language: font.getUint16(),
29756 name: font.getUint16(),
29757 length: font.getUint16(),
29758 offset: font.getUint16()
29759 };
29760 // using only Macintosh and Windows platform/encoding names
29761 if ((r.platform === 1 && r.encoding === 0 && r.language === 0) ||
29762 (r.platform === 3 && r.encoding === 1 && r.language === 0x409)) {
29763 records.push(r);
29764 }
29765 }
29766 for (i = 0, ii = records.length; i < ii; i++) {
29767 var record = records[i];
29768 if (record.length <= 0) {
29769 continue; // Nothing to process, ignoring.
29770 }
29771 var pos = start + stringsStart + record.offset;
29772 if (pos + record.length > end) {
29773 continue; // outside of name table, ignoring
29774 }
29775 font.pos = pos;
29776 var nameIndex = record.name;
29777 if (record.encoding) {
29778 // unicode
29779 var str = '';
29780 for (var j = 0, jj = record.length; j < jj; j += 2) {
29781 str += String.fromCharCode(font.getUint16());
29782 }
29783 names[1][nameIndex] = str;
29784 } else {
29785 names[0][nameIndex] = bytesToString(font.getBytes(record.length));
29786 }
29787 }
29788 return names;
29789 }
29790
29791 var TTOpsStackDeltas = [
29792 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5,
29793 -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1,
29794 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1,
29795 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2,
29796 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1,
29797 -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1,
29798 -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29799 -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1,
29800 -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2];
29801 // 0xC0-DF == -1 and 0xE0-FF == -2
29802
29803 function sanitizeTTProgram(table, ttContext) {
29804 var data = table.data;
29805 var i = 0, j, n, b, funcId, pc, lastEndf = 0, lastDeff = 0;
29806 var stack = [];
29807 var callstack = [];
29808 var functionsCalled = [];
29809 var tooComplexToFollowFunctions =
29810 ttContext.tooComplexToFollowFunctions;
29811 var inFDEF = false, ifLevel = 0, inELSE = 0;
29812 for (var ii = data.length; i < ii;) {
29813 var op = data[i++];
29814 // The TrueType instruction set docs can be found at
29815 // https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html
29816 if (op === 0x40) { // NPUSHB - pushes n bytes
29817 n = data[i++];
29818 if (inFDEF || inELSE) {
29819 i += n;
29820 } else {
29821 for (j = 0; j < n; j++) {
29822 stack.push(data[i++]);
29823 }
29824 }
29825 } else if (op === 0x41) { // NPUSHW - pushes n words
29826 n = data[i++];
29827 if (inFDEF || inELSE) {
29828 i += n * 2;
29829 } else {
29830 for (j = 0; j < n; j++) {
29831 b = data[i++];
29832 stack.push((b << 8) | data[i++]);
29833 }
29834 }
29835 } else if ((op & 0xF8) === 0xB0) { // PUSHB - pushes bytes
29836 n = op - 0xB0 + 1;
29837 if (inFDEF || inELSE) {
29838 i += n;
29839 } else {
29840 for (j = 0; j < n; j++) {
29841 stack.push(data[i++]);
29842 }
29843 }
29844 } else if ((op & 0xF8) === 0xB8) { // PUSHW - pushes words
29845 n = op - 0xB8 + 1;
29846 if (inFDEF || inELSE) {
29847 i += n * 2;
29848 } else {
29849 for (j = 0; j < n; j++) {
29850 b = data[i++];
29851 stack.push((b << 8) | data[i++]);
29852 }
29853 }
29854 } else if (op === 0x2B && !tooComplexToFollowFunctions) { // CALL
29855 if (!inFDEF && !inELSE) {
29856 // collecting inforamtion about which functions are used
29857 funcId = stack[stack.length - 1];
29858 ttContext.functionsUsed[funcId] = true;
29859 if (funcId in ttContext.functionsStackDeltas) {
29860 stack.length += ttContext.functionsStackDeltas[funcId];
29861 } else if (funcId in ttContext.functionsDefined &&
29862 functionsCalled.indexOf(funcId) < 0) {
29863 callstack.push({data: data, i: i, stackTop: stack.length - 1});
29864 functionsCalled.push(funcId);
29865 pc = ttContext.functionsDefined[funcId];
29866 if (!pc) {
29867 warn('TT: CALL non-existent function');
29868 ttContext.hintsValid = false;
29869 return;
29870 }
29871 data = pc.data;
29872 i = pc.i;
29873 }
29874 }
29875 } else if (op === 0x2C && !tooComplexToFollowFunctions) { // FDEF
29876 if (inFDEF || inELSE) {
29877 warn('TT: nested FDEFs not allowed');
29878 tooComplexToFollowFunctions = true;
29879 }
29880 inFDEF = true;
29881 // collecting inforamtion about which functions are defined
29882 lastDeff = i;
29883 funcId = stack.pop();
29884 ttContext.functionsDefined[funcId] = {data: data, i: i};
29885 } else if (op === 0x2D) { // ENDF - end of function
29886 if (inFDEF) {
29887 inFDEF = false;
29888 lastEndf = i;
29889 } else {
29890 pc = callstack.pop();
29891 if (!pc) {
29892 warn('TT: ENDF bad stack');
29893 ttContext.hintsValid = false;
29894 return;
29895 }
29896 funcId = functionsCalled.pop();
29897 data = pc.data;
29898 i = pc.i;
29899 ttContext.functionsStackDeltas[funcId] =
29900 stack.length - pc.stackTop;
29901 }
29902 } else if (op === 0x89) { // IDEF - instruction definition
29903 if (inFDEF || inELSE) {
29904 warn('TT: nested IDEFs not allowed');
29905 tooComplexToFollowFunctions = true;
29906 }
29907 inFDEF = true;
29908 // recording it as a function to track ENDF
29909 lastDeff = i;
29910 } else if (op === 0x58) { // IF
29911 ++ifLevel;
29912 } else if (op === 0x1B) { // ELSE
29913 inELSE = ifLevel;
29914 } else if (op === 0x59) { // EIF
29915 if (inELSE === ifLevel) {
29916 inELSE = 0;
29917 }
29918 --ifLevel;
29919 } else if (op === 0x1C) { // JMPR
29920 if (!inFDEF && !inELSE) {
29921 var offset = stack[stack.length - 1];
29922 // only jumping forward to prevent infinite loop
29923 if (offset > 0) {
29924 i += offset - 1;
29925 }
29926 }
29927 }
29928 // Adjusting stack not extactly, but just enough to get function id
29929 if (!inFDEF && !inELSE) {
29930 var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] :
29931 op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0;
29932 if (op >= 0x71 && op <= 0x75) {
29933 n = stack.pop();
29934 if (n === n) {
29935 stackDelta = -n * 2;
29936 }
29937 }
29938 while (stackDelta < 0 && stack.length > 0) {
29939 stack.pop();
29940 stackDelta++;
29941 }
29942 while (stackDelta > 0) {
29943 stack.push(NaN); // pushing any number into stack
29944 stackDelta--;
29945 }
29946 }
29947 }
29948 ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions;
29949 var content = [data];
29950 if (i > data.length) {
29951 content.push(new Uint8Array(i - data.length));
29952 }
29953 if (lastDeff > lastEndf) {
29954 warn('TT: complementing a missing function tail');
29955 // new function definition started, but not finished
29956 // complete function by [CLEAR, ENDF]
29957 content.push(new Uint8Array([0x22, 0x2D]));
29958 }
29959 foldTTTable(table, content);
29960 }
29961
29962 function checkInvalidFunctions(ttContext, maxFunctionDefs) {
29963 if (ttContext.tooComplexToFollowFunctions) {
29964 return;
29965 }
29966 if (ttContext.functionsDefined.length > maxFunctionDefs) {
29967 warn('TT: more functions defined than expected');
29968 ttContext.hintsValid = false;
29969 return;
29970 }
29971 for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) {
29972 if (j > maxFunctionDefs) {
29973 warn('TT: invalid function id: ' + j);
29974 ttContext.hintsValid = false;
29975 return;
29976 }
29977 if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) {
29978 warn('TT: undefined function: ' + j);
29979 ttContext.hintsValid = false;
29980 return;
29981 }
29982 }
29983 }
29984
29985 function foldTTTable(table, content) {
29986 if (content.length > 1) {
29987 // concatenating the content items
29988 var newLength = 0;
29989 var j, jj;
29990 for (j = 0, jj = content.length; j < jj; j++) {
29991 newLength += content[j].length;
29992 }
29993 newLength = (newLength + 3) & ~3;
29994 var result = new Uint8Array(newLength);
29995 var pos = 0;
29996 for (j = 0, jj = content.length; j < jj; j++) {
29997 result.set(content[j], pos);
29998 pos += content[j].length;
29999 }
30000 table.data = result;
30001 table.length = newLength;
30002 }
30003 }
30004
30005 function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) {
30006 var ttContext = {
30007 functionsDefined: [],
30008 functionsUsed: [],
30009 functionsStackDeltas: [],
30010 tooComplexToFollowFunctions: false,
30011 hintsValid: true
30012 };
30013 if (fpgm) {
30014 sanitizeTTProgram(fpgm, ttContext);
30015 }
30016 if (prep) {
30017 sanitizeTTProgram(prep, ttContext);
30018 }
30019 if (fpgm) {
30020 checkInvalidFunctions(ttContext, maxFunctionDefs);
30021 }
30022 if (cvt && (cvt.length & 1)) {
30023 var cvtData = new Uint8Array(cvt.length + 1);
30024 cvtData.set(cvt.data);
30025 cvt.data = cvtData;
30026 }
30027 return ttContext.hintsValid;
30028 }
30029
30030 // The following steps modify the original font data, making copy
30031 font = new Stream(new Uint8Array(font.getBytes()));
30032
30033 var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp',
30034 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF '];
30035
30036 var header = readOpenTypeHeader(font);
30037 var numTables = header.numTables;
30038 var cff, cffFile;
30039
30040 var tables = Object.create(null);
30041 tables['OS/2'] = null;
30042 tables['cmap'] = null;
30043 tables['head'] = null;
30044 tables['hhea'] = null;
30045 tables['hmtx'] = null;
30046 tables['maxp'] = null;
30047 tables['name'] = null;
30048 tables['post'] = null;
30049
30050 var table;
30051 for (var i = 0; i < numTables; i++) {
30052 table = readTableEntry(font);
30053 if (VALID_TABLES.indexOf(table.tag) < 0) {
30054 continue; // skipping table if it's not a required or optional table
30055 }
30056 if (table.length === 0) {
30057 continue; // skipping empty tables
30058 }
30059 tables[table.tag] = table;
30060 }
30061
30062 var isTrueType = !tables['CFF '];
30063 if (!isTrueType) {
30064 // OpenType font
30065 if ((header.version === 'OTTO' && properties.type !== 'CIDFontType2') ||
30066 !tables['head'] || !tables['hhea'] || !tables['maxp'] ||
30067 !tables['post']) {
30068 // no major tables: throwing everything at CFFFont
30069 cffFile = new Stream(tables['CFF '].data);
30070 cff = new CFFFont(cffFile, properties);
30071
30072 adjustWidths(properties);
30073
30074 return this.convert(name, cff, properties);
30075 }
30076
30077 delete tables['glyf'];
30078 delete tables['loca'];
30079 delete tables['fpgm'];
30080 delete tables['prep'];
30081 delete tables['cvt '];
30082 this.isOpenType = true;
30083 } else {
30084 if (!tables['loca']) {
30085 error('Required "loca" table is not found');
30086 }
30087 if (!tables['glyf']) {
30088 warn('Required "glyf" table is not found -- trying to recover.');
30089 // Note: We use `sanitizeGlyphLocations` to add dummy glyf data below.
30090 tables['glyf'] = {
30091 tag: 'glyf',
30092 data: new Uint8Array(0),
30093 };
30094 }
30095 this.isOpenType = false;
30096 }
30097
30098 if (!tables['maxp']) {
30099 error('Required "maxp" table is not found');
30100 }
30101
30102 font.pos = (font.start || 0) + tables['maxp'].offset;
30103 var version = font.getInt32();
30104 var numGlyphs = font.getUint16();
30105 var maxFunctionDefs = 0;
30106 if (version >= 0x00010000 && tables['maxp'].length >= 22) {
30107 // maxZones can be invalid
30108 font.pos += 8;
30109 var maxZones = font.getUint16();
30110 if (maxZones > 2) { // reset to 2 if font has invalid maxZones
30111 tables['maxp'].data[14] = 0;
30112 tables['maxp'].data[15] = 2;
30113 }
30114 font.pos += 4;
30115 maxFunctionDefs = font.getUint16();
30116 }
30117
30118 var dupFirstEntry = false;
30119 if (properties.type === 'CIDFontType2' && properties.toUnicode &&
30120 properties.toUnicode.get(0) > '\u0000') {
30121 // oracle's defect (see 3427), duplicating first entry
30122 dupFirstEntry = true;
30123 numGlyphs++;
30124 tables['maxp'].data[4] = numGlyphs >> 8;
30125 tables['maxp'].data[5] = numGlyphs & 255;
30126 }
30127
30128 var hintsValid = sanitizeTTPrograms(tables['fpgm'], tables['prep'],
30129 tables['cvt '], maxFunctionDefs);
30130 if (!hintsValid) {
30131 delete tables['fpgm'];
30132 delete tables['prep'];
30133 delete tables['cvt '];
30134 }
30135
30136 // Ensure the hmtx table contains the advance width and
30137 // sidebearings information for numGlyphs in the maxp table
30138 sanitizeMetrics(font, tables['hhea'], tables['hmtx'], numGlyphs);
30139
30140 if (!tables['head']) {
30141 error('Required "head" table is not found');
30142 }
30143
30144 sanitizeHead(tables['head'], numGlyphs,
30145 isTrueType ? tables['loca'].length : 0);
30146
30147 var missingGlyphs = Object.create(null);
30148 if (isTrueType) {
30149 var isGlyphLocationsLong = int16(tables['head'].data[50],
30150 tables['head'].data[51]);
30151 missingGlyphs = sanitizeGlyphLocations(tables['loca'], tables['glyf'],
30152 numGlyphs, isGlyphLocationsLong,
30153 hintsValid, dupFirstEntry);
30154 }
30155
30156 if (!tables['hhea']) {
30157 error('Required "hhea" table is not found');
30158 }
30159
30160 // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
30161 // Sometimes it's 0. That needs to be fixed
30162 if (tables['hhea'].data[10] === 0 && tables['hhea'].data[11] === 0) {
30163 tables['hhea'].data[10] = 0xFF;
30164 tables['hhea'].data[11] = 0xFF;
30165 }
30166
30167 // Extract some more font properties from the OpenType head and
30168 // hhea tables; yMin and descent value are always negative.
30169 var metricsOverride = {
30170 unitsPerEm: int16(tables['head'].data[18], tables['head'].data[19]),
30171 yMax: int16(tables['head'].data[42], tables['head'].data[43]),
30172 yMin: signedInt16(tables['head'].data[38], tables['head'].data[39]),
30173 ascent: int16(tables['hhea'].data[4], tables['hhea'].data[5]),
30174 descent: signedInt16(tables['hhea'].data[6], tables['hhea'].data[7])
30175 };
30176
30177 // PDF FontDescriptor metrics lie -- using data from actual font.
30178 this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm;
30179 this.descent = metricsOverride.descent / metricsOverride.unitsPerEm;
30180
30181 // The 'post' table has glyphs names.
30182 if (tables['post']) {
30183 var valid = readPostScriptTable(tables['post'], properties, numGlyphs);
30184 if (!valid) {
30185 tables['post'] = null;
30186 }
30187 }
30188
30189 var charCodeToGlyphId = [], charCode;
30190 var toUnicode = properties.toUnicode, widths = properties.widths;
30191 var skipToUnicode = (toUnicode instanceof IdentityToUnicodeMap ||
30192 toUnicode.length === 0x10000);
30193
30194 // Helper function to try to skip mapping of empty glyphs.
30195 // Note: In some cases, just relying on the glyph data doesn't work,
30196 // hence we also use a few heuristics to fix various PDF files.
30197 function hasGlyph(glyphId, charCode, widthCode) {
30198 if (!missingGlyphs[glyphId]) {
30199 return true;
30200 }
30201 if (!skipToUnicode && charCode >= 0 && toUnicode.has(charCode)) {
30202 return true;
30203 }
30204 if (widths && widthCode >= 0 && isNum(widths[widthCode])) {
30205 return true;
30206 }
30207 return false;
30208 }
30209
30210 if (properties.type === 'CIDFontType2') {
30211 var cidToGidMap = properties.cidToGidMap || [];
30212 var isCidToGidMapEmpty = cidToGidMap.length === 0;
30213
30214 properties.cMap.forEach(function(charCode, cid) {
30215 assert(cid <= 0xffff, 'Max size of CID is 65,535');
30216 var glyphId = -1;
30217 if (isCidToGidMapEmpty) {
30218 glyphId = cid;
30219 } else if (cidToGidMap[cid] !== undefined) {
30220 glyphId = cidToGidMap[cid];
30221 }
30222
30223 if (glyphId >= 0 && glyphId < numGlyphs &&
30224 hasGlyph(glyphId, charCode, cid)) {
30225 charCodeToGlyphId[charCode] = glyphId;
30226 }
30227 });
30228 if (dupFirstEntry && (isCidToGidMapEmpty || !charCodeToGlyphId[0])) {
30229 // We don't duplicate the first entry in the `charCodeToGlyphId` map
30230 // if the font has a `CIDToGIDMap` which has already mapped the first
30231 // entry to a non-zero `glyphId` (fixes issue7544.pdf).
30232 charCodeToGlyphId[0] = numGlyphs - 1;
30233 }
30234 } else {
30235 // Most of the following logic in this code branch is based on the
30236 // 9.6.6.4 of the PDF spec.
30237 var cmapTable = readCmapTable(tables['cmap'], font, this.isSymbolicFont,
30238 properties.hasEncoding);
30239 var cmapPlatformId = cmapTable.platformId;
30240 var cmapEncodingId = cmapTable.encodingId;
30241 var cmapMappings = cmapTable.mappings;
30242 var cmapMappingsLength = cmapMappings.length;
30243
30244 // The spec seems to imply that if the font is symbolic the encoding
30245 // should be ignored, this doesn't appear to work for 'preistabelle.pdf'
30246 // where the the font is symbolic and it has an encoding.
30247 if (properties.hasEncoding &&
30248 (cmapPlatformId === 3 && cmapEncodingId === 1 ||
30249 cmapPlatformId === 1 && cmapEncodingId === 0) ||
30250 (cmapPlatformId === -1 && cmapEncodingId === -1 && // Temporary hack
30251 !!getEncoding(properties.baseEncodingName))) { // Temporary hack
30252 // When no preferred cmap table was found and |baseEncodingName| is
30253 // one of the predefined encodings, we seem to obtain a better
30254 // |charCodeToGlyphId| map from the code below (fixes bug 1057544).
30255 // TODO: Note that this is a hack which should be removed as soon as
30256 // we have proper support for more exotic cmap tables.
30257
30258 var baseEncoding = [];
30259 if (properties.baseEncodingName === 'MacRomanEncoding' ||
30260 properties.baseEncodingName === 'WinAnsiEncoding') {
30261 baseEncoding = getEncoding(properties.baseEncodingName);
30262 }
30263 var glyphsUnicodeMap = getGlyphsUnicode();
30264 for (charCode = 0; charCode < 256; charCode++) {
30265 var glyphName, standardGlyphName;
30266 if (this.differences && charCode in this.differences) {
30267 glyphName = this.differences[charCode];
30268 } else if (charCode in baseEncoding &&
30269 baseEncoding[charCode] !== '') {
30270 glyphName = baseEncoding[charCode];
30271 } else {
30272 glyphName = StandardEncoding[charCode];
30273 }
30274 if (!glyphName) {
30275 continue;
30276 }
30277 // Ensure that non-standard glyph names are resolved to valid ones.
30278 standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
30279
30280 var unicodeOrCharCode, isUnicode = false;
30281 if (cmapPlatformId === 3 && cmapEncodingId === 1) {
30282 unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName];
30283 isUnicode = true;
30284 } else if (cmapPlatformId === 1 && cmapEncodingId === 0) {
30285 // TODO: the encoding needs to be updated with mac os table.
30286 unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName);
30287 }
30288
30289 var found = false;
30290 for (i = 0; i < cmapMappingsLength; ++i) {
30291 if (cmapMappings[i].charCode !== unicodeOrCharCode) {
30292 continue;
30293 }
30294 var code = isUnicode ? charCode : unicodeOrCharCode;
30295 if (hasGlyph(cmapMappings[i].glyphId, code, -1)) {
30296 charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
30297 found = true;
30298 break;
30299 }
30300 }
30301 if (!found && properties.glyphNames) {
30302 // Try to map using the post table.
30303 var glyphId = properties.glyphNames.indexOf(glyphName);
30304 // The post table ought to use the same kind of glyph names as the
30305 // `differences` array, but check the standard ones as a fallback.
30306 if (glyphId === -1 && standardGlyphName !== glyphName) {
30307 glyphId = properties.glyphNames.indexOf(standardGlyphName);
30308 }
30309 if (glyphId > 0 && hasGlyph(glyphId, -1, -1)) {
30310 charCodeToGlyphId[charCode] = glyphId;
30311 found = true;
30312 }
30313 }
30314 if (!found) {
30315 charCodeToGlyphId[charCode] = 0; // notdef
30316 }
30317 }
30318 } else if (cmapPlatformId === 0 && cmapEncodingId === 0) {
30319 // Default Unicode semantics, use the charcodes as is.
30320 for (i = 0; i < cmapMappingsLength; ++i) {
30321 charCodeToGlyphId[cmapMappings[i].charCode] =
30322 cmapMappings[i].glyphId;
30323 }
30324 } else {
30325 // For (3, 0) cmap tables:
30326 // The charcode key being stored in charCodeToGlyphId is the lower
30327 // byte of the two-byte charcodes of the cmap table since according to
30328 // the spec: 'each byte from the string shall be prepended with the
30329 // high byte of the range [of charcodes in the cmap table], to form
30330 // a two-byte character, which shall be used to select the
30331 // associated glyph description from the subtable'.
30332 //
30333 // For (1, 0) cmap tables:
30334 // 'single bytes from the string shall be used to look up the
30335 // associated glyph descriptions from the subtable'. This means
30336 // charcodes in the cmap will be single bytes, so no-op since
30337 // glyph.charCode & 0xFF === glyph.charCode
30338 for (i = 0; i < cmapMappingsLength; ++i) {
30339 charCode = cmapMappings[i].charCode & 0xFF;
30340 charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
30341 }
30342 }
30343 }
30344
30345 if (charCodeToGlyphId.length === 0) {
30346 // defines at least one glyph
30347 charCodeToGlyphId[0] = 0;
30348 }
30349
30350 // Converting glyphs and ids into font's cmap table
30351 var newMapping = adjustMapping(charCodeToGlyphId, properties);
30352 this.toFontChar = newMapping.toFontChar;
30353 tables['cmap'] = {
30354 tag: 'cmap',
30355 data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphs)
30356 };
30357
30358 if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) {
30359 tables['OS/2'] = {
30360 tag: 'OS/2',
30361 data: createOS2Table(properties, newMapping.charCodeToGlyphId,
30362 metricsOverride)
30363 };
30364 }
30365
30366 // Rewrite the 'post' table if needed
30367 if (!tables['post']) {
30368 tables['post'] = {
30369 tag: 'post',
30370 data: createPostTable(properties)
30371 };
30372 }
30373
30374 if (!isTrueType) {
30375 try {
30376 // Trying to repair CFF file
30377 cffFile = new Stream(tables['CFF '].data);
30378 var parser = new CFFParser(cffFile, properties,
30379 SEAC_ANALYSIS_ENABLED);
30380 cff = parser.parse();
30381 var compiler = new CFFCompiler(cff);
30382 tables['CFF '].data = compiler.compile();
30383 } catch (e) {
30384 warn('Failed to compile font ' + properties.loadedName);
30385 }
30386 }
30387
30388 // Re-creating 'name' table
30389 if (!tables['name']) {
30390 tables['name'] = {
30391 tag: 'name',
30392 data: createNameTable(this.name)
30393 };
30394 } else {
30395 // ... using existing 'name' table as prototype
30396 var namePrototype = readNameTable(tables['name']);
30397 tables['name'].data = createNameTable(name, namePrototype);
30398 }
30399
30400 var builder = new OpenTypeFileBuilder(header.version);
30401 for (var tableTag in tables) {
30402 builder.addTable(tableTag, tables[tableTag].data);
30403 }
30404 return builder.toArray();
30405 },
30406
30407 convert: function Font_convert(fontName, font, properties) {
30408 // TODO: Check the charstring widths to determine this.
30409 properties.fixedPitch = false;
30410
30411 if (properties.builtInEncoding) {
30412 // For Type1 fonts that do not include either `ToUnicode` or `Encoding`
30413 // data, attempt to use the `builtInEncoding` to improve text selection.
30414 adjustToUnicode(properties, properties.builtInEncoding);
30415 }
30416
30417 var mapping = font.getGlyphMapping(properties);
30418 var newMapping = adjustMapping(mapping, properties);
30419 this.toFontChar = newMapping.toFontChar;
30420 var numGlyphs = font.numGlyphs;
30421
30422 function getCharCodes(charCodeToGlyphId, glyphId) {
30423 var charCodes = null;
30424 for (var charCode in charCodeToGlyphId) {
30425 if (glyphId === charCodeToGlyphId[charCode]) {
30426 if (!charCodes) {
30427 charCodes = [];
30428 }
30429 charCodes.push(charCode | 0);
30430 }
30431 }
30432 return charCodes;
30433 }
30434
30435 function createCharCode(charCodeToGlyphId, glyphId) {
30436 for (var charCode in charCodeToGlyphId) {
30437 if (glyphId === charCodeToGlyphId[charCode]) {
30438 return charCode | 0;
30439 }
30440 }
30441 newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] =
30442 glyphId;
30443 return newMapping.nextAvailableFontCharCode++;
30444 }
30445
30446 var seacs = font.seacs;
30447 if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) {
30448 var matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX;
30449 var charset = font.getCharset();
30450 var seacMap = Object.create(null);
30451 for (var glyphId in seacs) {
30452 glyphId |= 0;
30453 var seac = seacs[glyphId];
30454 var baseGlyphName = StandardEncoding[seac[2]];
30455 var accentGlyphName = StandardEncoding[seac[3]];
30456 var baseGlyphId = charset.indexOf(baseGlyphName);
30457 var accentGlyphId = charset.indexOf(accentGlyphName);
30458 if (baseGlyphId < 0 || accentGlyphId < 0) {
30459 continue;
30460 }
30461 var accentOffset = {
30462 x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4],
30463 y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5]
30464 };
30465
30466 var charCodes = getCharCodes(mapping, glyphId);
30467 if (!charCodes) {
30468 // There's no point in mapping it if the char code was never mapped
30469 // to begin with.
30470 continue;
30471 }
30472 for (var i = 0, ii = charCodes.length; i < ii; i++) {
30473 var charCode = charCodes[i];
30474 // Find a fontCharCode that maps to the base and accent glyphs.
30475 // If one doesn't exists, create it.
30476 var charCodeToGlyphId = newMapping.charCodeToGlyphId;
30477 var baseFontCharCode = createCharCode(charCodeToGlyphId,
30478 baseGlyphId);
30479 var accentFontCharCode = createCharCode(charCodeToGlyphId,
30480 accentGlyphId);
30481 seacMap[charCode] = {
30482 baseFontCharCode: baseFontCharCode,
30483 accentFontCharCode: accentFontCharCode,
30484 accentOffset: accentOffset
30485 };
30486 }
30487 }
30488 properties.seacMap = seacMap;
30489 }
30490
30491 var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
30492
30493 var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F');
30494 // PostScript Font Program
30495 builder.addTable('CFF ', font.data);
30496 // OS/2 and Windows Specific metrics
30497 builder.addTable('OS/2', createOS2Table(properties,
30498 newMapping.charCodeToGlyphId));
30499 // Character to glyphs mapping
30500 builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId,
30501 numGlyphs));
30502 // Font header
30503 builder.addTable('head',
30504 '\x00\x01\x00\x00' + // Version number
30505 '\x00\x00\x10\x00' + // fontRevision
30506 '\x00\x00\x00\x00' + // checksumAdjustement
30507 '\x5F\x0F\x3C\xF5' + // magicNumber
30508 '\x00\x00' + // Flags
30509 safeString16(unitsPerEm) + // unitsPerEM
30510 '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date
30511 '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date
30512 '\x00\x00' + // xMin
30513 safeString16(properties.descent) + // yMin
30514 '\x0F\xFF' + // xMax
30515 safeString16(properties.ascent) + // yMax
30516 string16(properties.italicAngle ? 2 : 0) + // macStyle
30517 '\x00\x11' + // lowestRecPPEM
30518 '\x00\x00' + // fontDirectionHint
30519 '\x00\x00' + // indexToLocFormat
30520 '\x00\x00'); // glyphDataFormat
30521
30522 // Horizontal header
30523 builder.addTable('hhea',
30524 '\x00\x01\x00\x00' + // Version number
30525 safeString16(properties.ascent) + // Typographic Ascent
30526 safeString16(properties.descent) + // Typographic Descent
30527 '\x00\x00' + // Line Gap
30528 '\xFF\xFF' + // advanceWidthMax
30529 '\x00\x00' + // minLeftSidebearing
30530 '\x00\x00' + // minRightSidebearing
30531 '\x00\x00' + // xMaxExtent
30532 safeString16(properties.capHeight) + // caretSlopeRise
30533 safeString16(Math.tan(properties.italicAngle) *
30534 properties.xHeight) + // caretSlopeRun
30535 '\x00\x00' + // caretOffset
30536 '\x00\x00' + // -reserved-
30537 '\x00\x00' + // -reserved-
30538 '\x00\x00' + // -reserved-
30539 '\x00\x00' + // -reserved-
30540 '\x00\x00' + // metricDataFormat
30541 string16(numGlyphs)); // Number of HMetrics
30542
30543 // Horizontal metrics
30544 builder.addTable('hmtx', (function fontFieldsHmtx() {
30545 var charstrings = font.charstrings;
30546 var cffWidths = font.cff ? font.cff.widths : null;
30547 var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
30548 for (var i = 1, ii = numGlyphs; i < ii; i++) {
30549 var width = 0;
30550 if (charstrings) {
30551 var charstring = charstrings[i - 1];
30552 width = 'width' in charstring ? charstring.width : 0;
30553 } else if (cffWidths) {
30554 width = Math.ceil(cffWidths[i] || 0);
30555 }
30556 hmtx += string16(width) + string16(0);
30557 }
30558 return hmtx;
30559 })());
30560
30561 // Maximum profile
30562 builder.addTable('maxp',
30563 '\x00\x00\x50\x00' + // Version number
30564 string16(numGlyphs)); // Num of glyphs
30565
30566 // Naming tables
30567 builder.addTable('name', createNameTable(fontName));
30568
30569 // PostScript information
30570 builder.addTable('post', createPostTable(properties));
30571
30572 return builder.toArray();
30573 },
30574
30575 get spaceWidth() {
30576 if ('_shadowWidth' in this) {
30577 return this._shadowWidth;
30578 }
30579
30580 // trying to estimate space character width
30581 var possibleSpaceReplacements = ['space', 'minus', 'one', 'i', 'I'];
30582 var width;
30583 for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
30584 var glyphName = possibleSpaceReplacements[i];
30585 // if possible, getting width by glyph name
30586 if (glyphName in this.widths) {
30587 width = this.widths[glyphName];
30588 break;
30589 }
30590 var glyphsUnicodeMap = getGlyphsUnicode();
30591 var glyphUnicode = glyphsUnicodeMap[glyphName];
30592 // finding the charcode via unicodeToCID map
30593 var charcode = 0;
30594 if (this.composite) {
30595 if (this.cMap.contains(glyphUnicode)) {
30596 charcode = this.cMap.lookup(glyphUnicode);
30597 }
30598 }
30599 // ... via toUnicode map
30600 if (!charcode && this.toUnicode) {
30601 charcode = this.toUnicode.charCodeOf(glyphUnicode);
30602 }
30603 // setting it to unicode if negative or undefined
30604 if (charcode <= 0) {
30605 charcode = glyphUnicode;
30606 }
30607 // trying to get width via charcode
30608 width = this.widths[charcode];
30609 if (width) {
30610 break; // the non-zero width found
30611 }
30612 }
30613 width = width || this.defaultWidth;
30614 // Do not shadow the property here. See discussion:
30615 // https://github.com/mozilla/pdf.js/pull/2127#discussion_r1662280
30616 this._shadowWidth = width;
30617 return width;
30618 },
30619
30620 charToGlyph: function Font_charToGlyph(charcode, isSpace) {
30621 var fontCharCode, width, operatorListId;
30622
30623 var widthCode = charcode;
30624 if (this.cMap && this.cMap.contains(charcode)) {
30625 widthCode = this.cMap.lookup(charcode);
30626 }
30627 width = this.widths[widthCode];
30628 width = isNum(width) ? width : this.defaultWidth;
30629 var vmetric = this.vmetrics && this.vmetrics[widthCode];
30630
30631 var unicode = this.toUnicode.get(charcode) || charcode;
30632 if (typeof unicode === 'number') {
30633 unicode = String.fromCharCode(unicode);
30634 }
30635
30636 var isInFont = charcode in this.toFontChar;
30637 // First try the toFontChar map, if it's not there then try falling
30638 // back to the char code.
30639 fontCharCode = this.toFontChar[charcode] || charcode;
30640 if (this.missingFile) {
30641 fontCharCode = mapSpecialUnicodeValues(fontCharCode);
30642 }
30643
30644 if (this.isType3Font) {
30645 // Font char code in this case is actually a glyph name.
30646 operatorListId = fontCharCode;
30647 }
30648
30649 var accent = null;
30650 if (this.seacMap && this.seacMap[charcode]) {
30651 isInFont = true;
30652 var seac = this.seacMap[charcode];
30653 fontCharCode = seac.baseFontCharCode;
30654 accent = {
30655 fontChar: String.fromCharCode(seac.accentFontCharCode),
30656 offset: seac.accentOffset
30657 };
30658 }
30659
30660 var fontChar = String.fromCharCode(fontCharCode);
30661
30662 var glyph = this.glyphCache[charcode];
30663 if (!glyph ||
30664 !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric,
30665 operatorListId, isSpace, isInFont)) {
30666 glyph = new Glyph(fontChar, unicode, accent, width, vmetric,
30667 operatorListId, isSpace, isInFont);
30668 this.glyphCache[charcode] = glyph;
30669 }
30670 return glyph;
30671 },
30672
30673 charsToGlyphs: function Font_charsToGlyphs(chars) {
30674 var charsCache = this.charsCache;
30675 var glyphs, glyph, charcode;
30676
30677 // if we translated this string before, just grab it from the cache
30678 if (charsCache) {
30679 glyphs = charsCache[chars];
30680 if (glyphs) {
30681 return glyphs;
30682 }
30683 }
30684
30685 // lazily create the translation cache
30686 if (!charsCache) {
30687 charsCache = this.charsCache = Object.create(null);
30688 }
30689
30690 glyphs = [];
30691 var charsCacheKey = chars;
30692 var i = 0, ii;
30693
30694 if (this.cMap) {
30695 // composite fonts have multi-byte strings convert the string from
30696 // single-byte to multi-byte
30697 var c = Object.create(null);
30698 while (i < chars.length) {
30699 this.cMap.readCharCode(chars, i, c);
30700 charcode = c.charcode;
30701 var length = c.length;
30702 i += length;
30703 // Space is char with code 0x20 and length 1 in multiple-byte codes.
30704 var isSpace = length === 1 && chars.charCodeAt(i - 1) === 0x20;
30705 glyph = this.charToGlyph(charcode, isSpace);
30706 glyphs.push(glyph);
30707 }
30708 } else {
30709 for (i = 0, ii = chars.length; i < ii; ++i) {
30710 charcode = chars.charCodeAt(i);
30711 glyph = this.charToGlyph(charcode, charcode === 0x20);
30712 glyphs.push(glyph);
30713 }
30714 }
30715
30716 // Enter the translated string into the cache
30717 return (charsCache[charsCacheKey] = glyphs);
30718 }
30719 };
30720
30721 return Font;
30722})();
30723
30724var ErrorFont = (function ErrorFontClosure() {
30725 function ErrorFont(error) {
30726 this.error = error;
30727 this.loadedName = 'g_font_error';
30728 this.loading = false;
30729 }
30730
30731 ErrorFont.prototype = {
30732 charsToGlyphs: function ErrorFont_charsToGlyphs() {
30733 return [];
30734 },
30735 exportData: function ErrorFont_exportData() {
30736 return {error: this.error};
30737 }
30738 };
30739
30740 return ErrorFont;
30741})();
30742
30743/**
30744 * Shared logic for building a char code to glyph id mapping for Type1 and
30745 * simple CFF fonts. See section 9.6.6.2 of the spec.
30746 * @param {Object} properties Font properties object.
30747 * @param {Object} builtInEncoding The encoding contained within the actual font
30748 * data.
30749 * @param {Array} glyphNames Array of glyph names where the index is the
30750 * glyph ID.
30751 * @returns {Object} A char code to glyph ID map.
30752 */
30753function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {
30754 var charCodeToGlyphId = Object.create(null);
30755 var glyphId, charCode, baseEncoding;
30756
30757 if (properties.baseEncodingName) {
30758 // If a valid base encoding name was used, the mapping is initialized with
30759 // that.
30760 baseEncoding = getEncoding(properties.baseEncodingName);
30761 for (charCode = 0; charCode < baseEncoding.length; charCode++) {
30762 glyphId = glyphNames.indexOf(baseEncoding[charCode]);
30763 if (glyphId >= 0) {
30764 charCodeToGlyphId[charCode] = glyphId;
30765 } else {
30766 charCodeToGlyphId[charCode] = 0; // notdef
30767 }
30768 }
30769 } else if (!!(properties.flags & FontFlags.Symbolic)) {
30770 // For a symbolic font the encoding should be the fonts built-in
30771 // encoding.
30772 for (charCode in builtInEncoding) {
30773 charCodeToGlyphId[charCode] = builtInEncoding[charCode];
30774 }
30775 } else {
30776 // For non-symbolic fonts that don't have a base encoding the standard
30777 // encoding should be used.
30778 baseEncoding = StandardEncoding;
30779 for (charCode = 0; charCode < baseEncoding.length; charCode++) {
30780 glyphId = glyphNames.indexOf(baseEncoding[charCode]);
30781 if (glyphId >= 0) {
30782 charCodeToGlyphId[charCode] = glyphId;
30783 } else {
30784 charCodeToGlyphId[charCode] = 0; // notdef
30785 }
30786 }
30787 }
30788
30789 // Lastly, merge in the differences.
30790 var differences = properties.differences, glyphsUnicodeMap;
30791 if (differences) {
30792 for (charCode in differences) {
30793 var glyphName = differences[charCode];
30794 glyphId = glyphNames.indexOf(glyphName);
30795
30796 if (glyphId === -1) {
30797 if (!glyphsUnicodeMap) {
30798 glyphsUnicodeMap = getGlyphsUnicode();
30799 }
30800 var standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
30801 if (standardGlyphName !== glyphName) {
30802 glyphId = glyphNames.indexOf(standardGlyphName);
30803 }
30804 }
30805 if (glyphId >= 0) {
30806 charCodeToGlyphId[charCode] = glyphId;
30807 } else {
30808 charCodeToGlyphId[charCode] = 0; // notdef
30809 }
30810 }
30811 }
30812 return charCodeToGlyphId;
30813}
30814
30815// Type1Font is also a CIDFontType0.
30816var Type1Font = (function Type1FontClosure() {
30817 function findBlock(streamBytes, signature, startIndex) {
30818 var streamBytesLength = streamBytes.length;
30819 var signatureLength = signature.length;
30820 var scanLength = streamBytesLength - signatureLength;
30821
30822 var i = startIndex, j, found = false;
30823 while (i < scanLength) {
30824 j = 0;
30825 while (j < signatureLength && streamBytes[i + j] === signature[j]) {
30826 j++;
30827 }
30828 if (j >= signatureLength) { // `signature` found, skip over whitespace.
30829 i += j;
30830 while (i < streamBytesLength && isSpace(streamBytes[i])) {
30831 i++;
30832 }
30833 found = true;
30834 break;
30835 }
30836 i++;
30837 }
30838 return {
30839 found: found,
30840 length: i,
30841 };
30842 }
30843
30844 function getHeaderBlock(stream, suggestedLength) {
30845 var EEXEC_SIGNATURE = [0x65, 0x65, 0x78, 0x65, 0x63];
30846
30847 var streamStartPos = stream.pos; // Save the initial stream position.
30848 var headerBytes, headerBytesLength, block;
30849 try {
30850 headerBytes = stream.getBytes(suggestedLength);
30851 headerBytesLength = headerBytes.length;
30852 } catch (ex) {
30853 if (ex instanceof MissingDataException) {
30854 throw ex;
30855 }
30856 // Ignore errors if the `suggestedLength` is huge enough that a Uint8Array
30857 // cannot hold the result of `getBytes`, and fallback to simply checking
30858 // the entire stream (fixes issue3928.pdf).
30859 }
30860
30861 if (headerBytesLength === suggestedLength) {
30862 // Most of the time `suggestedLength` is correct, so to speed things up we
30863 // initially only check the last few bytes to see if the header was found.
30864 // Otherwise we (potentially) check the entire stream to prevent errors in
30865 // `Type1Parser` (fixes issue5686.pdf).
30866 block = findBlock(headerBytes, EEXEC_SIGNATURE,
30867 suggestedLength - 2 * EEXEC_SIGNATURE.length);
30868
30869 if (block.found && block.length === suggestedLength) {
30870 return {
30871 stream: new Stream(headerBytes),
30872 length: suggestedLength,
30873 };
30874 }
30875 }
30876 warn('Invalid "Length1" property in Type1 font -- trying to recover.');
30877 stream.pos = streamStartPos; // Reset the stream position.
30878
30879 var SCAN_BLOCK_LENGTH = 2048;
30880 var actualLength;
30881 while (true) {
30882 var scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
30883 block = findBlock(scanBytes, EEXEC_SIGNATURE, 0);
30884
30885 if (block.length === 0) {
30886 break;
30887 }
30888 stream.pos += block.length; // Update the stream position.
30889
30890 if (block.found) {
30891 actualLength = stream.pos - streamStartPos;
30892 break;
30893 }
30894 }
30895 stream.pos = streamStartPos; // Reset the stream position.
30896
30897 if (actualLength) {
30898 return {
30899 stream: new Stream(stream.getBytes(actualLength)),
30900 length: actualLength,
30901 };
30902 }
30903 warn('Unable to recover "Length1" property in Type1 font -- using as is.');
30904 return {
30905 stream: new Stream(stream.getBytes(suggestedLength)),
30906 length: suggestedLength,
30907 };
30908 }
30909
30910 function getEexecBlock(stream, suggestedLength) {
30911 // We should ideally parse the eexec block to ensure that `suggestedLength`
30912 // is correct, so we don't truncate the block data if it's too small.
30913 // However, this would also require checking if the fixed-content portion
30914 // exists (using the 'Length3' property), and ensuring that it's valid.
30915 //
30916 // Given that `suggestedLength` almost always is correct, all the validation
30917 // would require a great deal of unnecessary parsing for most fonts.
30918 // To save time, we always fetch the entire stream instead, which also avoid
30919 // issues if `suggestedLength` is huge (see comment in `getHeaderBlock`).
30920 //
30921 // NOTE: This means that the function can include the fixed-content portion
30922 // in the returned eexec block. In practice this does *not* seem to matter,
30923 // since `Type1Parser_extractFontProgram` will skip over any non-commands.
30924 var eexecBytes = stream.getBytes();
30925 return {
30926 stream: new Stream(eexecBytes),
30927 length: eexecBytes.length,
30928 };
30929 }
30930
30931 function Type1Font(name, file, properties) {
30932 // Some bad generators embed pfb file as is, we have to strip 6-byte header.
30933 // Also, length1 and length2 might be off by 6 bytes as well.
30934 // http://www.math.ubc.ca/~cass/piscript/type1.pdf
30935 var PFB_HEADER_SIZE = 6;
30936 var headerBlockLength = properties.length1;
30937 var eexecBlockLength = properties.length2;
30938 var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
30939 var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
30940 if (pfbHeaderPresent) {
30941 file.skip(PFB_HEADER_SIZE);
30942 headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
30943 (pfbHeader[3] << 8) | pfbHeader[2];
30944 }
30945
30946 // Get the data block containing glyphs and subrs information
30947 var headerBlock = getHeaderBlock(file, headerBlockLength);
30948 headerBlockLength = headerBlock.length;
30949 var headerBlockParser = new Type1Parser(headerBlock.stream, false,
30950 SEAC_ANALYSIS_ENABLED);
30951 headerBlockParser.extractFontHeader(properties);
30952
30953 if (pfbHeaderPresent) {
30954 pfbHeader = file.getBytes(PFB_HEADER_SIZE);
30955 eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
30956 (pfbHeader[3] << 8) | pfbHeader[2];
30957 }
30958
30959 // Decrypt the data blocks and retrieve it's content
30960 var eexecBlock = getEexecBlock(file, eexecBlockLength);
30961 eexecBlockLength = eexecBlock.length;
30962 var eexecBlockParser = new Type1Parser(eexecBlock.stream, true,
30963 SEAC_ANALYSIS_ENABLED);
30964 var data = eexecBlockParser.extractFontProgram();
30965 for (var info in data.properties) {
30966 properties[info] = data.properties[info];
30967 }
30968
30969 var charstrings = data.charstrings;
30970 var type2Charstrings = this.getType2Charstrings(charstrings);
30971 var subrs = this.getType2Subrs(data.subrs);
30972
30973 this.charstrings = charstrings;
30974 this.data = this.wrap(name, type2Charstrings, this.charstrings,
30975 subrs, properties);
30976 this.seacs = this.getSeacs(data.charstrings);
30977 }
30978
30979 Type1Font.prototype = {
30980 get numGlyphs() {
30981 return this.charstrings.length + 1;
30982 },
30983
30984 getCharset: function Type1Font_getCharset() {
30985 var charset = ['.notdef'];
30986 var charstrings = this.charstrings;
30987 for (var glyphId = 0; glyphId < charstrings.length; glyphId++) {
30988 charset.push(charstrings[glyphId].glyphName);
30989 }
30990 return charset;
30991 },
30992
30993 getGlyphMapping: function Type1Font_getGlyphMapping(properties) {
30994 var charstrings = this.charstrings;
30995 var glyphNames = ['.notdef'], glyphId;
30996 for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
30997 glyphNames.push(charstrings[glyphId].glyphName);
30998 }
30999 var encoding = properties.builtInEncoding;
31000 if (encoding) {
31001 var builtInEncoding = Object.create(null);
31002 for (var charCode in encoding) {
31003 glyphId = glyphNames.indexOf(encoding[charCode]);
31004 if (glyphId >= 0) {
31005 builtInEncoding[charCode] = glyphId;
31006 }
31007 }
31008 }
31009
31010 return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
31011 },
31012
31013 getSeacs: function Type1Font_getSeacs(charstrings) {
31014 var i, ii;
31015 var seacMap = [];
31016 for (i = 0, ii = charstrings.length; i < ii; i++) {
31017 var charstring = charstrings[i];
31018 if (charstring.seac) {
31019 // Offset by 1 for .notdef
31020 seacMap[i + 1] = charstring.seac;
31021 }
31022 }
31023 return seacMap;
31024 },
31025
31026 getType2Charstrings: function Type1Font_getType2Charstrings(
31027 type1Charstrings) {
31028 var type2Charstrings = [];
31029 for (var i = 0, ii = type1Charstrings.length; i < ii; i++) {
31030 type2Charstrings.push(type1Charstrings[i].charstring);
31031 }
31032 return type2Charstrings;
31033 },
31034
31035 getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
31036 var bias = 0;
31037 var count = type1Subrs.length;
31038 if (count < 1133) {
31039 bias = 107;
31040 } else if (count < 33769) {
31041 bias = 1131;
31042 } else {
31043 bias = 32768;
31044 }
31045
31046 // Add a bunch of empty subrs to deal with the Type2 bias
31047 var type2Subrs = [];
31048 var i;
31049 for (i = 0; i < bias; i++) {
31050 type2Subrs.push([0x0B]);
31051 }
31052
31053 for (i = 0; i < count; i++) {
31054 type2Subrs.push(type1Subrs[i]);
31055 }
31056
31057 return type2Subrs;
31058 },
31059
31060 wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs,
31061 properties) {
31062 var cff = new CFF();
31063 cff.header = new CFFHeader(1, 0, 4, 4);
31064
31065 cff.names = [name];
31066
31067 var topDict = new CFFTopDict();
31068 // CFF strings IDs 0...390 are predefined names, so refering
31069 // to entries in our own String INDEX starts at SID 391.
31070 topDict.setByName('version', 391);
31071 topDict.setByName('Notice', 392);
31072 topDict.setByName('FullName', 393);
31073 topDict.setByName('FamilyName', 394);
31074 topDict.setByName('Weight', 395);
31075 topDict.setByName('Encoding', null); // placeholder
31076 topDict.setByName('FontMatrix', properties.fontMatrix);
31077 topDict.setByName('FontBBox', properties.bbox);
31078 topDict.setByName('charset', null); // placeholder
31079 topDict.setByName('CharStrings', null); // placeholder
31080 topDict.setByName('Private', null); // placeholder
31081 cff.topDict = topDict;
31082
31083 var strings = new CFFStrings();
31084 strings.add('Version 0.11'); // Version
31085 strings.add('See original notice'); // Notice
31086 strings.add(name); // FullName
31087 strings.add(name); // FamilyName
31088 strings.add('Medium'); // Weight
31089 cff.strings = strings;
31090
31091 cff.globalSubrIndex = new CFFIndex();
31092
31093 var count = glyphs.length;
31094 var charsetArray = [0];
31095 var i, ii;
31096 for (i = 0; i < count; i++) {
31097 var index = CFFStandardStrings.indexOf(charstrings[i].glyphName);
31098 // TODO: Insert the string and correctly map it. Previously it was
31099 // thought mapping names that aren't in the standard strings to .notdef
31100 // was fine, however in issue818 when mapping them all to .notdef the
31101 // adieresis glyph no longer worked.
31102 if (index === -1) {
31103 index = 0;
31104 }
31105 charsetArray.push((index >> 8) & 0xff, index & 0xff);
31106 }
31107 cff.charset = new CFFCharset(false, 0, [], charsetArray);
31108
31109 var charStringsIndex = new CFFIndex();
31110 charStringsIndex.add([0x8B, 0x0E]); // .notdef
31111 for (i = 0; i < count; i++) {
31112 var glyph = glyphs[i];
31113 // If the CharString outline is empty, replace it with .notdef to
31114 // prevent OTS from rejecting the font (fixes bug1252420.pdf).
31115 if (glyph.length === 0) {
31116 charStringsIndex.add([0x8B, 0x0E]); // .notdef
31117 continue;
31118 }
31119 charStringsIndex.add(glyph);
31120 }
31121 cff.charStrings = charStringsIndex;
31122
31123 var privateDict = new CFFPrivateDict();
31124 privateDict.setByName('Subrs', null); // placeholder
31125 var fields = [
31126 'BlueValues',
31127 'OtherBlues',
31128 'FamilyBlues',
31129 'FamilyOtherBlues',
31130 'StemSnapH',
31131 'StemSnapV',
31132 'BlueShift',
31133 'BlueFuzz',
31134 'BlueScale',
31135 'LanguageGroup',
31136 'ExpansionFactor',
31137 'ForceBold',
31138 'StdHW',
31139 'StdVW'
31140 ];
31141 for (i = 0, ii = fields.length; i < ii; i++) {
31142 var field = fields[i];
31143 if (!(field in properties.privateData)) {
31144 continue;
31145 }
31146 var value = properties.privateData[field];
31147 if (isArray(value)) {
31148 // All of the private dictionary array data in CFF must be stored as
31149 // "delta-encoded" numbers.
31150 for (var j = value.length - 1; j > 0; j--) {
31151 value[j] -= value[j - 1]; // ... difference from previous value
31152 }
31153 }
31154 privateDict.setByName(field, value);
31155 }
31156 cff.topDict.privateDict = privateDict;
31157
31158 var subrIndex = new CFFIndex();
31159 for (i = 0, ii = subrs.length; i < ii; i++) {
31160 subrIndex.add(subrs[i]);
31161 }
31162 privateDict.subrsIndex = subrIndex;
31163
31164 var compiler = new CFFCompiler(cff);
31165 return compiler.compile();
31166 }
31167 };
31168
31169 return Type1Font;
31170})();
31171
31172var CFFFont = (function CFFFontClosure() {
31173 function CFFFont(file, properties) {
31174 this.properties = properties;
31175
31176 var parser = new CFFParser(file, properties, SEAC_ANALYSIS_ENABLED);
31177 this.cff = parser.parse();
31178 var compiler = new CFFCompiler(this.cff);
31179 this.seacs = this.cff.seacs;
31180 try {
31181 this.data = compiler.compile();
31182 } catch (e) {
31183 warn('Failed to compile font ' + properties.loadedName);
31184 // There may have just been an issue with the compiler, set the data
31185 // anyway and hope the font loaded.
31186 this.data = file;
31187 }
31188 }
31189
31190 CFFFont.prototype = {
31191 get numGlyphs() {
31192 return this.cff.charStrings.count;
31193 },
31194 getCharset: function CFFFont_getCharset() {
31195 return this.cff.charset.charset;
31196 },
31197 getGlyphMapping: function CFFFont_getGlyphMapping() {
31198 var cff = this.cff;
31199 var properties = this.properties;
31200 var charsets = cff.charset.charset;
31201 var charCodeToGlyphId;
31202 var glyphId;
31203
31204 if (properties.composite) {
31205 charCodeToGlyphId = Object.create(null);
31206 if (cff.isCIDFont) {
31207 // If the font is actually a CID font then we should use the charset
31208 // to map CIDs to GIDs.
31209 for (glyphId = 0; glyphId < charsets.length; glyphId++) {
31210 var cid = charsets[glyphId];
31211 var charCode = properties.cMap.charCodeOf(cid);
31212 charCodeToGlyphId[charCode] = glyphId;
31213 }
31214 } else {
31215 // If it is NOT actually a CID font then CIDs should be mapped
31216 // directly to GIDs.
31217 for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) {
31218 charCodeToGlyphId[glyphId] = glyphId;
31219 }
31220 }
31221 return charCodeToGlyphId;
31222 }
31223
31224 var encoding = cff.encoding ? cff.encoding.encoding : null;
31225 charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets);
31226 return charCodeToGlyphId;
31227 }
31228 };
31229
31230 return CFFFont;
31231})();
31232
31233// Workaround for seac on Windows.
31234(function checkSeacSupport() {
31235 if (typeof navigator !== 'undefined' && /Windows/.test(navigator.userAgent)) {
31236 SEAC_ANALYSIS_ENABLED = true;
31237 }
31238})();
31239
31240// Workaround for Private Use Area characters in Chrome on Windows
31241// http://code.google.com/p/chromium/issues/detail?id=122465
31242// https://github.com/mozilla/pdf.js/issues/1689
31243(function checkChromeWindows() {
31244 if (typeof navigator !== 'undefined' &&
31245 /Windows.*Chrome/.test(navigator.userAgent)) {
31246 SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = true;
31247 }
31248})();
31249
31250exports.SEAC_ANALYSIS_ENABLED = SEAC_ANALYSIS_ENABLED;
31251exports.ErrorFont = ErrorFont;
31252exports.Font = Font;
31253exports.FontFlags = FontFlags;
31254exports.IdentityToUnicodeMap = IdentityToUnicodeMap;
31255exports.ToUnicodeMap = ToUnicodeMap;
31256exports.getFontType = getFontType;
31257}));
31258
31259
31260(function (root, factory) {
31261 {
31262 factory((root.pdfjsCorePsParser = {}), root.pdfjsSharedUtil,
31263 root.pdfjsCoreParser);
31264 }
31265}(this, function (exports, sharedUtil, coreParser) {
31266
31267var error = sharedUtil.error;
31268var isSpace = sharedUtil.isSpace;
31269var EOF = coreParser.EOF;
31270
31271var PostScriptParser = (function PostScriptParserClosure() {
31272 function PostScriptParser(lexer) {
31273 this.lexer = lexer;
31274 this.operators = [];
31275 this.token = null;
31276 this.prev = null;
31277 }
31278 PostScriptParser.prototype = {
31279 nextToken: function PostScriptParser_nextToken() {
31280 this.prev = this.token;
31281 this.token = this.lexer.getToken();
31282 },
31283 accept: function PostScriptParser_accept(type) {
31284 if (this.token.type === type) {
31285 this.nextToken();
31286 return true;
31287 }
31288 return false;
31289 },
31290 expect: function PostScriptParser_expect(type) {
31291 if (this.accept(type)) {
31292 return true;
31293 }
31294 error('Unexpected symbol: found ' + this.token.type + ' expected ' +
31295 type + '.');
31296 },
31297 parse: function PostScriptParser_parse() {
31298 this.nextToken();
31299 this.expect(PostScriptTokenTypes.LBRACE);
31300 this.parseBlock();
31301 this.expect(PostScriptTokenTypes.RBRACE);
31302 return this.operators;
31303 },
31304 parseBlock: function PostScriptParser_parseBlock() {
31305 while (true) {
31306 if (this.accept(PostScriptTokenTypes.NUMBER)) {
31307 this.operators.push(this.prev.value);
31308 } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
31309 this.operators.push(this.prev.value);
31310 } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
31311 this.parseCondition();
31312 } else {
31313 return;
31314 }
31315 }
31316 },
31317 parseCondition: function PostScriptParser_parseCondition() {
31318 // Add two place holders that will be updated later
31319 var conditionLocation = this.operators.length;
31320 this.operators.push(null, null);
31321
31322 this.parseBlock();
31323 this.expect(PostScriptTokenTypes.RBRACE);
31324 if (this.accept(PostScriptTokenTypes.IF)) {
31325 // The true block is right after the 'if' so it just falls through on
31326 // true else it jumps and skips the true block.
31327 this.operators[conditionLocation] = this.operators.length;
31328 this.operators[conditionLocation + 1] = 'jz';
31329 } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
31330 var jumpLocation = this.operators.length;
31331 this.operators.push(null, null);
31332 var endOfTrue = this.operators.length;
31333 this.parseBlock();
31334 this.expect(PostScriptTokenTypes.RBRACE);
31335 this.expect(PostScriptTokenTypes.IFELSE);
31336 // The jump is added at the end of the true block to skip the false
31337 // block.
31338 this.operators[jumpLocation] = this.operators.length;
31339 this.operators[jumpLocation + 1] = 'j';
31340
31341 this.operators[conditionLocation] = endOfTrue;
31342 this.operators[conditionLocation + 1] = 'jz';
31343 } else {
31344 error('PS Function: error parsing conditional.');
31345 }
31346 }
31347 };
31348 return PostScriptParser;
31349})();
31350
31351var PostScriptTokenTypes = {
31352 LBRACE: 0,
31353 RBRACE: 1,
31354 NUMBER: 2,
31355 OPERATOR: 3,
31356 IF: 4,
31357 IFELSE: 5
31358};
31359
31360var PostScriptToken = (function PostScriptTokenClosure() {
31361 function PostScriptToken(type, value) {
31362 this.type = type;
31363 this.value = value;
31364 }
31365
31366 var opCache = Object.create(null);
31367
31368 PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
31369 var opValue = opCache[op];
31370 if (opValue) {
31371 return opValue;
31372 }
31373 return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
31374 };
31375
31376 PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
31377 '{');
31378 PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
31379 '}');
31380 PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
31381 PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
31382 'IFELSE');
31383 return PostScriptToken;
31384})();
31385
31386var PostScriptLexer = (function PostScriptLexerClosure() {
31387 function PostScriptLexer(stream) {
31388 this.stream = stream;
31389 this.nextChar();
31390
31391 this.strBuf = [];
31392 }
31393 PostScriptLexer.prototype = {
31394 nextChar: function PostScriptLexer_nextChar() {
31395 return (this.currentChar = this.stream.getByte());
31396 },
31397 getToken: function PostScriptLexer_getToken() {
31398 var comment = false;
31399 var ch = this.currentChar;
31400
31401 // skip comments
31402 while (true) {
31403 if (ch < 0) {
31404 return EOF;
31405 }
31406
31407 if (comment) {
31408 if (ch === 0x0A || ch === 0x0D) {
31409 comment = false;
31410 }
31411 } else if (ch === 0x25) { // '%'
31412 comment = true;
31413 } else if (!isSpace(ch)) {
31414 break;
31415 }
31416 ch = this.nextChar();
31417 }
31418 switch (ch | 0) {
31419 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
31420 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
31421 case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
31422 return new PostScriptToken(PostScriptTokenTypes.NUMBER,
31423 this.getNumber());
31424 case 0x7B: // '{'
31425 this.nextChar();
31426 return PostScriptToken.LBRACE;
31427 case 0x7D: // '}'
31428 this.nextChar();
31429 return PostScriptToken.RBRACE;
31430 }
31431 // operator
31432 var strBuf = this.strBuf;
31433 strBuf.length = 0;
31434 strBuf[0] = String.fromCharCode(ch);
31435
31436 while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
31437 ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
31438 strBuf.push(String.fromCharCode(ch));
31439 }
31440 var str = strBuf.join('');
31441 switch (str.toLowerCase()) {
31442 case 'if':
31443 return PostScriptToken.IF;
31444 case 'ifelse':
31445 return PostScriptToken.IFELSE;
31446 default:
31447 return PostScriptToken.getOperator(str);
31448 }
31449 },
31450 getNumber: function PostScriptLexer_getNumber() {
31451 var ch = this.currentChar;
31452 var strBuf = this.strBuf;
31453 strBuf.length = 0;
31454 strBuf[0] = String.fromCharCode(ch);
31455
31456 while ((ch = this.nextChar()) >= 0) {
31457 if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
31458 ch === 0x2D || ch === 0x2E) { // '-', '.'
31459 strBuf.push(String.fromCharCode(ch));
31460 } else {
31461 break;
31462 }
31463 }
31464 var value = parseFloat(strBuf.join(''));
31465 if (isNaN(value)) {
31466 error('Invalid floating point number: ' + value);
31467 }
31468 return value;
31469 }
31470 };
31471 return PostScriptLexer;
31472})();
31473
31474exports.PostScriptLexer = PostScriptLexer;
31475exports.PostScriptParser = PostScriptParser;
31476}));
31477
31478
31479(function (root, factory) {
31480 {
31481 factory((root.pdfjsCoreFunction = {}), root.pdfjsSharedUtil,
31482 root.pdfjsCorePrimitives, root.pdfjsCorePsParser);
31483 }
31484}(this, function (exports, sharedUtil, corePrimitives, corePsParser) {
31485
31486var error = sharedUtil.error;
31487var info = sharedUtil.info;
31488var isArray = sharedUtil.isArray;
31489var isBool = sharedUtil.isBool;
31490var isDict = corePrimitives.isDict;
31491var isStream = corePrimitives.isStream;
31492var PostScriptLexer = corePsParser.PostScriptLexer;
31493var PostScriptParser = corePsParser.PostScriptParser;
31494
31495var PDFFunction = (function PDFFunctionClosure() {
31496 var CONSTRUCT_SAMPLED = 0;
31497 var CONSTRUCT_INTERPOLATED = 2;
31498 var CONSTRUCT_STICHED = 3;
31499 var CONSTRUCT_POSTSCRIPT = 4;
31500
31501 return {
31502 getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
31503 str) {
31504 var i, ii;
31505 var length = 1;
31506 for (i = 0, ii = size.length; i < ii; i++) {
31507 length *= size[i];
31508 }
31509 length *= outputSize;
31510
31511 var array = new Array(length);
31512 var codeSize = 0;
31513 var codeBuf = 0;
31514 // 32 is a valid bps so shifting won't work
31515 var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
31516
31517 var strBytes = str.getBytes((length * bps + 7) / 8);
31518 var strIdx = 0;
31519 for (i = 0; i < length; i++) {
31520 while (codeSize < bps) {
31521 codeBuf <<= 8;
31522 codeBuf |= strBytes[strIdx++];
31523 codeSize += 8;
31524 }
31525 codeSize -= bps;
31526 array[i] = (codeBuf >> codeSize) * sampleMul;
31527 codeBuf &= (1 << codeSize) - 1;
31528 }
31529 return array;
31530 },
31531
31532 getIR: function PDFFunction_getIR(xref, fn) {
31533 var dict = fn.dict;
31534 if (!dict) {
31535 dict = fn;
31536 }
31537
31538 var types = [this.constructSampled,
31539 null,
31540 this.constructInterpolated,
31541 this.constructStiched,
31542 this.constructPostScript];
31543
31544 var typeNum = dict.get('FunctionType');
31545 var typeFn = types[typeNum];
31546 if (!typeFn) {
31547 error('Unknown type of function');
31548 }
31549
31550 return typeFn.call(this, fn, dict, xref);
31551 },
31552
31553 fromIR: function PDFFunction_fromIR(IR) {
31554 var type = IR[0];
31555 switch (type) {
31556 case CONSTRUCT_SAMPLED:
31557 return this.constructSampledFromIR(IR);
31558 case CONSTRUCT_INTERPOLATED:
31559 return this.constructInterpolatedFromIR(IR);
31560 case CONSTRUCT_STICHED:
31561 return this.constructStichedFromIR(IR);
31562 //case CONSTRUCT_POSTSCRIPT:
31563 default:
31564 return this.constructPostScriptFromIR(IR);
31565 }
31566 },
31567
31568 parse: function PDFFunction_parse(xref, fn) {
31569 var IR = this.getIR(xref, fn);
31570 return this.fromIR(IR);
31571 },
31572
31573 parseArray: function PDFFunction_parseArray(xref, fnObj) {
31574 if (!isArray(fnObj)) {
31575 // not an array -- parsing as regular function
31576 return this.parse(xref, fnObj);
31577 }
31578
31579 var fnArray = [];
31580 for (var j = 0, jj = fnObj.length; j < jj; j++) {
31581 var obj = xref.fetchIfRef(fnObj[j]);
31582 fnArray.push(PDFFunction.parse(xref, obj));
31583 }
31584 return function (src, srcOffset, dest, destOffset) {
31585 for (var i = 0, ii = fnArray.length; i < ii; i++) {
31586 fnArray[i](src, srcOffset, dest, destOffset + i);
31587 }
31588 };
31589 },
31590
31591 constructSampled: function PDFFunction_constructSampled(str, dict) {
31592 function toMultiArray(arr) {
31593 var inputLength = arr.length;
31594 var out = [];
31595 var index = 0;
31596 for (var i = 0; i < inputLength; i += 2) {
31597 out[index] = [arr[i], arr[i + 1]];
31598 ++index;
31599 }
31600 return out;
31601 }
31602 var domain = dict.getArray('Domain');
31603 var range = dict.getArray('Range');
31604
31605 if (!domain || !range) {
31606 error('No domain or range');
31607 }
31608
31609 var inputSize = domain.length / 2;
31610 var outputSize = range.length / 2;
31611
31612 domain = toMultiArray(domain);
31613 range = toMultiArray(range);
31614
31615 var size = dict.get('Size');
31616 var bps = dict.get('BitsPerSample');
31617 var order = dict.get('Order') || 1;
31618 if (order !== 1) {
31619 // No description how cubic spline interpolation works in PDF32000:2008
31620 // As in poppler, ignoring order, linear interpolation may work as good
31621 info('No support for cubic spline interpolation: ' + order);
31622 }
31623
31624 var encode = dict.getArray('Encode');
31625 if (!encode) {
31626 encode = [];
31627 for (var i = 0; i < inputSize; ++i) {
31628 encode.push(0);
31629 encode.push(size[i] - 1);
31630 }
31631 }
31632 encode = toMultiArray(encode);
31633
31634 var decode = dict.getArray('Decode');
31635 if (!decode) {
31636 decode = range;
31637 } else {
31638 decode = toMultiArray(decode);
31639 }
31640
31641 var samples = this.getSampleArray(size, outputSize, bps, str);
31642
31643 return [
31644 CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
31645 outputSize, Math.pow(2, bps) - 1, range
31646 ];
31647 },
31648
31649 constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
31650 // See chapter 3, page 109 of the PDF reference
31651 function interpolate(x, xmin, xmax, ymin, ymax) {
31652 return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
31653 }
31654
31655 return function constructSampledFromIRResult(src, srcOffset,
31656 dest, destOffset) {
31657 // See chapter 3, page 110 of the PDF reference.
31658 var m = IR[1];
31659 var domain = IR[2];
31660 var encode = IR[3];
31661 var decode = IR[4];
31662 var samples = IR[5];
31663 var size = IR[6];
31664 var n = IR[7];
31665 //var mask = IR[8];
31666 var range = IR[9];
31667
31668 // Building the cube vertices: its part and sample index
31669 // http://rjwagner49.com/Mathematics/Interpolation.pdf
31670 var cubeVertices = 1 << m;
31671 var cubeN = new Float64Array(cubeVertices);
31672 var cubeVertex = new Uint32Array(cubeVertices);
31673 var i, j;
31674 for (j = 0; j < cubeVertices; j++) {
31675 cubeN[j] = 1;
31676 }
31677
31678 var k = n, pos = 1;
31679 // Map x_i to y_j for 0 <= i < m using the sampled function.
31680 for (i = 0; i < m; ++i) {
31681 // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
31682 var domain_2i = domain[i][0];
31683 var domain_2i_1 = domain[i][1];
31684 var xi = Math.min(Math.max(src[srcOffset +i], domain_2i),
31685 domain_2i_1);
31686
31687 // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
31688 // Encode_2i, Encode_2i+1)
31689 var e = interpolate(xi, domain_2i, domain_2i_1,
31690 encode[i][0], encode[i][1]);
31691
31692 // e_i' = min(max(e_i, 0), Size_i - 1)
31693 var size_i = size[i];
31694 e = Math.min(Math.max(e, 0), size_i - 1);
31695
31696 // Adjusting the cube: N and vertex sample index
31697 var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
31698 var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
31699 var n1 = e - e0; // (e - e0) / (e1 - e0);
31700 var offset0 = e0 * k;
31701 var offset1 = offset0 + k; // e1 * k
31702 for (j = 0; j < cubeVertices; j++) {
31703 if (j & pos) {
31704 cubeN[j] *= n1;
31705 cubeVertex[j] += offset1;
31706 } else {
31707 cubeN[j] *= n0;
31708 cubeVertex[j] += offset0;
31709 }
31710 }
31711
31712 k *= size_i;
31713 pos <<= 1;
31714 }
31715
31716 for (j = 0; j < n; ++j) {
31717 // Sum all cube vertices' samples portions
31718 var rj = 0;
31719 for (i = 0; i < cubeVertices; i++) {
31720 rj += samples[cubeVertex[i] + j] * cubeN[i];
31721 }
31722
31723 // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
31724 // Decode_2j, Decode_2j+1)
31725 rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
31726
31727 // y_j = min(max(r_j, range_2j), range_2j+1)
31728 dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]),
31729 range[j][1]);
31730 }
31731 };
31732 },
31733
31734 constructInterpolated: function PDFFunction_constructInterpolated(str,
31735 dict) {
31736 var c0 = dict.getArray('C0') || [0];
31737 var c1 = dict.getArray('C1') || [1];
31738 var n = dict.get('N');
31739
31740 if (!isArray(c0) || !isArray(c1)) {
31741 error('Illegal dictionary for interpolated function');
31742 }
31743
31744 var length = c0.length;
31745 var diff = [];
31746 for (var i = 0; i < length; ++i) {
31747 diff.push(c1[i] - c0[i]);
31748 }
31749
31750 return [CONSTRUCT_INTERPOLATED, c0, diff, n];
31751 },
31752
31753 constructInterpolatedFromIR:
31754 function PDFFunction_constructInterpolatedFromIR(IR) {
31755 var c0 = IR[1];
31756 var diff = IR[2];
31757 var n = IR[3];
31758
31759 var length = diff.length;
31760
31761 return function constructInterpolatedFromIRResult(src, srcOffset,
31762 dest, destOffset) {
31763 var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n);
31764
31765 for (var j = 0; j < length; ++j) {
31766 dest[destOffset + j] = c0[j] + (x * diff[j]);
31767 }
31768 };
31769 },
31770
31771 constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
31772 var domain = dict.getArray('Domain');
31773
31774 if (!domain) {
31775 error('No domain');
31776 }
31777
31778 var inputSize = domain.length / 2;
31779 if (inputSize !== 1) {
31780 error('Bad domain for stiched function');
31781 }
31782
31783 var fnRefs = dict.get('Functions');
31784 var fns = [];
31785 for (var i = 0, ii = fnRefs.length; i < ii; ++i) {
31786 fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i])));
31787 }
31788
31789 var bounds = dict.getArray('Bounds');
31790 var encode = dict.getArray('Encode');
31791
31792 return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
31793 },
31794
31795 constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) {
31796 var domain = IR[1];
31797 var bounds = IR[2];
31798 var encode = IR[3];
31799 var fnsIR = IR[4];
31800 var fns = [];
31801 var tmpBuf = new Float32Array(1);
31802
31803 for (var i = 0, ii = fnsIR.length; i < ii; i++) {
31804 fns.push(PDFFunction.fromIR(fnsIR[i]));
31805 }
31806
31807 return function constructStichedFromIRResult(src, srcOffset,
31808 dest, destOffset) {
31809 var clip = function constructStichedFromIRClip(v, min, max) {
31810 if (v > max) {
31811 v = max;
31812 } else if (v < min) {
31813 v = min;
31814 }
31815 return v;
31816 };
31817
31818 // clip to domain
31819 var v = clip(src[srcOffset], domain[0], domain[1]);
31820 // calculate which bound the value is in
31821 for (var i = 0, ii = bounds.length; i < ii; ++i) {
31822 if (v < bounds[i]) {
31823 break;
31824 }
31825 }
31826
31827 // encode value into domain of function
31828 var dmin = domain[0];
31829 if (i > 0) {
31830 dmin = bounds[i - 1];
31831 }
31832 var dmax = domain[1];
31833 if (i < bounds.length) {
31834 dmax = bounds[i];
31835 }
31836
31837 var rmin = encode[2 * i];
31838 var rmax = encode[2 * i + 1];
31839
31840 // Prevent the value from becoming NaN as a result
31841 // of division by zero (fixes issue6113.pdf).
31842 tmpBuf[0] = dmin === dmax ? rmin :
31843 rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
31844
31845 // call the appropriate function
31846 fns[i](tmpBuf, 0, dest, destOffset);
31847 };
31848 },
31849
31850 constructPostScript: function PDFFunction_constructPostScript(fn, dict,
31851 xref) {
31852 var domain = dict.getArray('Domain');
31853 var range = dict.getArray('Range');
31854
31855 if (!domain) {
31856 error('No domain.');
31857 }
31858
31859 if (!range) {
31860 error('No range.');
31861 }
31862
31863 var lexer = new PostScriptLexer(fn);
31864 var parser = new PostScriptParser(lexer);
31865 var code = parser.parse();
31866
31867 return [CONSTRUCT_POSTSCRIPT, domain, range, code];
31868 },
31869
31870 constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(
31871 IR) {
31872 var domain = IR[1];
31873 var range = IR[2];
31874 var code = IR[3];
31875
31876 var compiled = (new PostScriptCompiler()).compile(code, domain, range);
31877 if (compiled) {
31878 // Compiled function consists of simple expressions such as addition,
31879 // subtraction, Math.max, and also contains 'var' and 'return'
31880 // statements. See the generation in the PostScriptCompiler below.
31881 /*jshint -W054 */
31882 return new Function('src', 'srcOffset', 'dest', 'destOffset', compiled);
31883 }
31884
31885 info('Unable to compile PS function');
31886
31887 var numOutputs = range.length >> 1;
31888 var numInputs = domain.length >> 1;
31889 var evaluator = new PostScriptEvaluator(code);
31890 // Cache the values for a big speed up, the cache size is limited though
31891 // since the number of possible values can be huge from a PS function.
31892 var cache = Object.create(null);
31893 // The MAX_CACHE_SIZE is set to ~4x the maximum number of distinct values
31894 // seen in our tests.
31895 var MAX_CACHE_SIZE = 2048 * 4;
31896 var cache_available = MAX_CACHE_SIZE;
31897 var tmpBuf = new Float32Array(numInputs);
31898
31899 return function constructPostScriptFromIRResult(src, srcOffset,
31900 dest, destOffset) {
31901 var i, value;
31902 var key = '';
31903 var input = tmpBuf;
31904 for (i = 0; i < numInputs; i++) {
31905 value = src[srcOffset + i];
31906 input[i] = value;
31907 key += value + '_';
31908 }
31909
31910 var cachedValue = cache[key];
31911 if (cachedValue !== undefined) {
31912 dest.set(cachedValue, destOffset);
31913 return;
31914 }
31915
31916 var output = new Float32Array(numOutputs);
31917 var stack = evaluator.execute(input);
31918 var stackIndex = stack.length - numOutputs;
31919 for (i = 0; i < numOutputs; i++) {
31920 value = stack[stackIndex + i];
31921 var bound = range[i * 2];
31922 if (value < bound) {
31923 value = bound;
31924 } else {
31925 bound = range[i * 2 +1];
31926 if (value > bound) {
31927 value = bound;
31928 }
31929 }
31930 output[i] = value;
31931 }
31932 if (cache_available > 0) {
31933 cache_available--;
31934 cache[key] = output;
31935 }
31936 dest.set(output, destOffset);
31937 };
31938 }
31939 };
31940})();
31941
31942function isPDFFunction(v) {
31943 var fnDict;
31944 if (typeof v !== 'object') {
31945 return false;
31946 } else if (isDict(v)) {
31947 fnDict = v;
31948 } else if (isStream(v)) {
31949 fnDict = v.dict;
31950 } else {
31951 return false;
31952 }
31953 return fnDict.has('FunctionType');
31954}
31955
31956var PostScriptStack = (function PostScriptStackClosure() {
31957 var MAX_STACK_SIZE = 100;
31958 function PostScriptStack(initialStack) {
31959 this.stack = !initialStack ? [] :
31960 Array.prototype.slice.call(initialStack, 0);
31961 }
31962
31963 PostScriptStack.prototype = {
31964 push: function PostScriptStack_push(value) {
31965 if (this.stack.length >= MAX_STACK_SIZE) {
31966 error('PostScript function stack overflow.');
31967 }
31968 this.stack.push(value);
31969 },
31970 pop: function PostScriptStack_pop() {
31971 if (this.stack.length <= 0) {
31972 error('PostScript function stack underflow.');
31973 }
31974 return this.stack.pop();
31975 },
31976 copy: function PostScriptStack_copy(n) {
31977 if (this.stack.length + n >= MAX_STACK_SIZE) {
31978 error('PostScript function stack overflow.');
31979 }
31980 var stack = this.stack;
31981 for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
31982 stack.push(stack[i]);
31983 }
31984 },
31985 index: function PostScriptStack_index(n) {
31986 this.push(this.stack[this.stack.length - n - 1]);
31987 },
31988 // rotate the last n stack elements p times
31989 roll: function PostScriptStack_roll(n, p) {
31990 var stack = this.stack;
31991 var l = stack.length - n;
31992 var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
31993 for (i = l, j = r; i < j; i++, j--) {
31994 t = stack[i]; stack[i] = stack[j]; stack[j] = t;
31995 }
31996 for (i = l, j = c - 1; i < j; i++, j--) {
31997 t = stack[i]; stack[i] = stack[j]; stack[j] = t;
31998 }
31999 for (i = c, j = r; i < j; i++, j--) {
32000 t = stack[i]; stack[i] = stack[j]; stack[j] = t;
32001 }
32002 }
32003 };
32004 return PostScriptStack;
32005})();
32006var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
32007 function PostScriptEvaluator(operators) {
32008 this.operators = operators;
32009 }
32010 PostScriptEvaluator.prototype = {
32011 execute: function PostScriptEvaluator_execute(initialStack) {
32012 var stack = new PostScriptStack(initialStack);
32013 var counter = 0;
32014 var operators = this.operators;
32015 var length = operators.length;
32016 var operator, a, b;
32017 while (counter < length) {
32018 operator = operators[counter++];
32019 if (typeof operator === 'number') {
32020 // Operator is really an operand and should be pushed to the stack.
32021 stack.push(operator);
32022 continue;
32023 }
32024 switch (operator) {
32025 // non standard ps operators
32026 case 'jz': // jump if false
32027 b = stack.pop();
32028 a = stack.pop();
32029 if (!a) {
32030 counter = b;
32031 }
32032 break;
32033 case 'j': // jump
32034 a = stack.pop();
32035 counter = a;
32036 break;
32037
32038 // all ps operators in alphabetical order (excluding if/ifelse)
32039 case 'abs':
32040 a = stack.pop();
32041 stack.push(Math.abs(a));
32042 break;
32043 case 'add':
32044 b = stack.pop();
32045 a = stack.pop();
32046 stack.push(a + b);
32047 break;
32048 case 'and':
32049 b = stack.pop();
32050 a = stack.pop();
32051 if (isBool(a) && isBool(b)) {
32052 stack.push(a && b);
32053 } else {
32054 stack.push(a & b);
32055 }
32056 break;
32057 case 'atan':
32058 a = stack.pop();
32059 stack.push(Math.atan(a));
32060 break;
32061 case 'bitshift':
32062 b = stack.pop();
32063 a = stack.pop();
32064 if (a > 0) {
32065 stack.push(a << b);
32066 } else {
32067 stack.push(a >> b);
32068 }
32069 break;
32070 case 'ceiling':
32071 a = stack.pop();
32072 stack.push(Math.ceil(a));
32073 break;
32074 case 'copy':
32075 a = stack.pop();
32076 stack.copy(a);
32077 break;
32078 case 'cos':
32079 a = stack.pop();
32080 stack.push(Math.cos(a));
32081 break;
32082 case 'cvi':
32083 a = stack.pop() | 0;
32084 stack.push(a);
32085 break;
32086 case 'cvr':
32087 // noop
32088 break;
32089 case 'div':
32090 b = stack.pop();
32091 a = stack.pop();
32092 stack.push(a / b);
32093 break;
32094 case 'dup':
32095 stack.copy(1);
32096 break;
32097 case 'eq':
32098 b = stack.pop();
32099 a = stack.pop();
32100 stack.push(a === b);
32101 break;
32102 case 'exch':
32103 stack.roll(2, 1);
32104 break;
32105 case 'exp':
32106 b = stack.pop();
32107 a = stack.pop();
32108 stack.push(Math.pow(a, b));
32109 break;
32110 case 'false':
32111 stack.push(false);
32112 break;
32113 case 'floor':
32114 a = stack.pop();
32115 stack.push(Math.floor(a));
32116 break;
32117 case 'ge':
32118 b = stack.pop();
32119 a = stack.pop();
32120 stack.push(a >= b);
32121 break;
32122 case 'gt':
32123 b = stack.pop();
32124 a = stack.pop();
32125 stack.push(a > b);
32126 break;
32127 case 'idiv':
32128 b = stack.pop();
32129 a = stack.pop();
32130 stack.push((a / b) | 0);
32131 break;
32132 case 'index':
32133 a = stack.pop();
32134 stack.index(a);
32135 break;
32136 case 'le':
32137 b = stack.pop();
32138 a = stack.pop();
32139 stack.push(a <= b);
32140 break;
32141 case 'ln':
32142 a = stack.pop();
32143 stack.push(Math.log(a));
32144 break;
32145 case 'log':
32146 a = stack.pop();
32147 stack.push(Math.log(a) / Math.LN10);
32148 break;
32149 case 'lt':
32150 b = stack.pop();
32151 a = stack.pop();
32152 stack.push(a < b);
32153 break;
32154 case 'mod':
32155 b = stack.pop();
32156 a = stack.pop();
32157 stack.push(a % b);
32158 break;
32159 case 'mul':
32160 b = stack.pop();
32161 a = stack.pop();
32162 stack.push(a * b);
32163 break;
32164 case 'ne':
32165 b = stack.pop();
32166 a = stack.pop();
32167 stack.push(a !== b);
32168 break;
32169 case 'neg':
32170 a = stack.pop();
32171 stack.push(-a);
32172 break;
32173 case 'not':
32174 a = stack.pop();
32175 if (isBool(a)) {
32176 stack.push(!a);
32177 } else {
32178 stack.push(~a);
32179 }
32180 break;
32181 case 'or':
32182 b = stack.pop();
32183 a = stack.pop();
32184 if (isBool(a) && isBool(b)) {
32185 stack.push(a || b);
32186 } else {
32187 stack.push(a | b);
32188 }
32189 break;
32190 case 'pop':
32191 stack.pop();
32192 break;
32193 case 'roll':
32194 b = stack.pop();
32195 a = stack.pop();
32196 stack.roll(a, b);
32197 break;
32198 case 'round':
32199 a = stack.pop();
32200 stack.push(Math.round(a));
32201 break;
32202 case 'sin':
32203 a = stack.pop();
32204 stack.push(Math.sin(a));
32205 break;
32206 case 'sqrt':
32207 a = stack.pop();
32208 stack.push(Math.sqrt(a));
32209 break;
32210 case 'sub':
32211 b = stack.pop();
32212 a = stack.pop();
32213 stack.push(a - b);
32214 break;
32215 case 'true':
32216 stack.push(true);
32217 break;
32218 case 'truncate':
32219 a = stack.pop();
32220 a = a < 0 ? Math.ceil(a) : Math.floor(a);
32221 stack.push(a);
32222 break;
32223 case 'xor':
32224 b = stack.pop();
32225 a = stack.pop();
32226 if (isBool(a) && isBool(b)) {
32227 stack.push(a !== b);
32228 } else {
32229 stack.push(a ^ b);
32230 }
32231 break;
32232 default:
32233 error('Unknown operator ' + operator);
32234 break;
32235 }
32236 }
32237 return stack.stack;
32238 }
32239 };
32240 return PostScriptEvaluator;
32241})();
32242
32243// Most of the PDFs functions consist of simple operations such as:
32244// roll, exch, sub, cvr, pop, index, dup, mul, if, gt, add.
32245//
32246// We can compile most of such programs, and at the same moment, we can
32247// optimize some expressions using basic math properties. Keeping track of
32248// min/max values will allow us to avoid extra Math.min/Math.max calls.
32249var PostScriptCompiler = (function PostScriptCompilerClosure() {
32250 function AstNode(type) {
32251 this.type = type;
32252 }
32253 AstNode.prototype.visit = function (visitor) {
32254 throw new Error('abstract method');
32255 };
32256
32257 function AstArgument(index, min, max) {
32258 AstNode.call(this, 'args');
32259 this.index = index;
32260 this.min = min;
32261 this.max = max;
32262 }
32263 AstArgument.prototype = Object.create(AstNode.prototype);
32264 AstArgument.prototype.visit = function (visitor) {
32265 visitor.visitArgument(this);
32266 };
32267
32268 function AstLiteral(number) {
32269 AstNode.call(this, 'literal');
32270 this.number = number;
32271 this.min = number;
32272 this.max = number;
32273 }
32274 AstLiteral.prototype = Object.create(AstNode.prototype);
32275 AstLiteral.prototype.visit = function (visitor) {
32276 visitor.visitLiteral(this);
32277 };
32278
32279 function AstBinaryOperation(op, arg1, arg2, min, max) {
32280 AstNode.call(this, 'binary');
32281 this.op = op;
32282 this.arg1 = arg1;
32283 this.arg2 = arg2;
32284 this.min = min;
32285 this.max = max;
32286 }
32287 AstBinaryOperation.prototype = Object.create(AstNode.prototype);
32288 AstBinaryOperation.prototype.visit = function (visitor) {
32289 visitor.visitBinaryOperation(this);
32290 };
32291
32292 function AstMin(arg, max) {
32293 AstNode.call(this, 'max');
32294 this.arg = arg;
32295 this.min = arg.min;
32296 this.max = max;
32297 }
32298 AstMin.prototype = Object.create(AstNode.prototype);
32299 AstMin.prototype.visit = function (visitor) {
32300 visitor.visitMin(this);
32301 };
32302
32303 function AstVariable(index, min, max) {
32304 AstNode.call(this, 'var');
32305 this.index = index;
32306 this.min = min;
32307 this.max = max;
32308 }
32309 AstVariable.prototype = Object.create(AstNode.prototype);
32310 AstVariable.prototype.visit = function (visitor) {
32311 visitor.visitVariable(this);
32312 };
32313
32314 function AstVariableDefinition(variable, arg) {
32315 AstNode.call(this, 'definition');
32316 this.variable = variable;
32317 this.arg = arg;
32318 }
32319 AstVariableDefinition.prototype = Object.create(AstNode.prototype);
32320 AstVariableDefinition.prototype.visit = function (visitor) {
32321 visitor.visitVariableDefinition(this);
32322 };
32323
32324 function ExpressionBuilderVisitor() {
32325 this.parts = [];
32326 }
32327 ExpressionBuilderVisitor.prototype = {
32328 visitArgument: function (arg) {
32329 this.parts.push('Math.max(', arg.min, ', Math.min(',
32330 arg.max, ', src[srcOffset + ', arg.index, ']))');
32331 },
32332 visitVariable: function (variable) {
32333 this.parts.push('v', variable.index);
32334 },
32335 visitLiteral: function (literal) {
32336 this.parts.push(literal.number);
32337 },
32338 visitBinaryOperation: function (operation) {
32339 this.parts.push('(');
32340 operation.arg1.visit(this);
32341 this.parts.push(' ', operation.op, ' ');
32342 operation.arg2.visit(this);
32343 this.parts.push(')');
32344 },
32345 visitVariableDefinition: function (definition) {
32346 this.parts.push('var ');
32347 definition.variable.visit(this);
32348 this.parts.push(' = ');
32349 definition.arg.visit(this);
32350 this.parts.push(';');
32351 },
32352 visitMin: function (max) {
32353 this.parts.push('Math.min(');
32354 max.arg.visit(this);
32355 this.parts.push(', ', max.max, ')');
32356 },
32357 toString: function () {
32358 return this.parts.join('');
32359 }
32360 };
32361
32362 function buildAddOperation(num1, num2) {
32363 if (num2.type === 'literal' && num2.number === 0) {
32364 // optimization: second operand is 0
32365 return num1;
32366 }
32367 if (num1.type === 'literal' && num1.number === 0) {
32368 // optimization: first operand is 0
32369 return num2;
32370 }
32371 if (num2.type === 'literal' && num1.type === 'literal') {
32372 // optimization: operands operand are literals
32373 return new AstLiteral(num1.number + num2.number);
32374 }
32375 return new AstBinaryOperation('+', num1, num2,
32376 num1.min + num2.min, num1.max + num2.max);
32377 }
32378
32379 function buildMulOperation(num1, num2) {
32380 if (num2.type === 'literal') {
32381 // optimization: second operands is a literal...
32382 if (num2.number === 0) {
32383 return new AstLiteral(0); // and it's 0
32384 } else if (num2.number === 1) {
32385 return num1; // and it's 1
32386 } else if (num1.type === 'literal') {
32387 // ... and first operands is a literal too
32388 return new AstLiteral(num1.number * num2.number);
32389 }
32390 }
32391 if (num1.type === 'literal') {
32392 // optimization: first operands is a literal...
32393 if (num1.number === 0) {
32394 return new AstLiteral(0); // and it's 0
32395 } else if (num1.number === 1) {
32396 return num2; // and it's 1
32397 }
32398 }
32399 var min = Math.min(num1.min * num2.min, num1.min * num2.max,
32400 num1.max * num2.min, num1.max * num2.max);
32401 var max = Math.max(num1.min * num2.min, num1.min * num2.max,
32402 num1.max * num2.min, num1.max * num2.max);
32403 return new AstBinaryOperation('*', num1, num2, min, max);
32404 }
32405
32406 function buildSubOperation(num1, num2) {
32407 if (num2.type === 'literal') {
32408 // optimization: second operands is a literal...
32409 if (num2.number === 0) {
32410 return num1; // ... and it's 0
32411 } else if (num1.type === 'literal') {
32412 // ... and first operands is a literal too
32413 return new AstLiteral(num1.number - num2.number);
32414 }
32415 }
32416 if (num2.type === 'binary' && num2.op === '-' &&
32417 num1.type === 'literal' && num1.number === 1 &&
32418 num2.arg1.type === 'literal' && num2.arg1.number === 1) {
32419 // optimization for case: 1 - (1 - x)
32420 return num2.arg2;
32421 }
32422 return new AstBinaryOperation('-', num1, num2,
32423 num1.min - num2.max, num1.max - num2.min);
32424 }
32425
32426 function buildMinOperation(num1, max) {
32427 if (num1.min >= max) {
32428 // optimization: num1 min value is not less than required max
32429 return new AstLiteral(max); // just returning max
32430 } else if (num1.max <= max) {
32431 // optimization: num1 max value is not greater than required max
32432 return num1; // just returning an argument
32433 }
32434 return new AstMin(num1, max);
32435 }
32436
32437 function PostScriptCompiler() {}
32438 PostScriptCompiler.prototype = {
32439 compile: function PostScriptCompiler_compile(code, domain, range) {
32440 var stack = [];
32441 var i, ii;
32442 var instructions = [];
32443 var inputSize = domain.length >> 1, outputSize = range.length >> 1;
32444 var lastRegister = 0;
32445 var n, j;
32446 var num1, num2, ast1, ast2, tmpVar, item;
32447 for (i = 0; i < inputSize; i++) {
32448 stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1]));
32449 }
32450
32451 for (i = 0, ii = code.length; i < ii; i++) {
32452 item = code[i];
32453 if (typeof item === 'number') {
32454 stack.push(new AstLiteral(item));
32455 continue;
32456 }
32457
32458 switch (item) {
32459 case 'add':
32460 if (stack.length < 2) {
32461 return null;
32462 }
32463 num2 = stack.pop();
32464 num1 = stack.pop();
32465 stack.push(buildAddOperation(num1, num2));
32466 break;
32467 case 'cvr':
32468 if (stack.length < 1) {
32469 return null;
32470 }
32471 break;
32472 case 'mul':
32473 if (stack.length < 2) {
32474 return null;
32475 }
32476 num2 = stack.pop();
32477 num1 = stack.pop();
32478 stack.push(buildMulOperation(num1, num2));
32479 break;
32480 case 'sub':
32481 if (stack.length < 2) {
32482 return null;
32483 }
32484 num2 = stack.pop();
32485 num1 = stack.pop();
32486 stack.push(buildSubOperation(num1, num2));
32487 break;
32488 case 'exch':
32489 if (stack.length < 2) {
32490 return null;
32491 }
32492 ast1 = stack.pop(); ast2 = stack.pop();
32493 stack.push(ast1, ast2);
32494 break;
32495 case 'pop':
32496 if (stack.length < 1) {
32497 return null;
32498 }
32499 stack.pop();
32500 break;
32501 case 'index':
32502 if (stack.length < 1) {
32503 return null;
32504 }
32505 num1 = stack.pop();
32506 if (num1.type !== 'literal') {
32507 return null;
32508 }
32509 n = num1.number;
32510 if (n < 0 || (n|0) !== n || stack.length < n) {
32511 return null;
32512 }
32513 ast1 = stack[stack.length - n - 1];
32514 if (ast1.type === 'literal' || ast1.type === 'var') {
32515 stack.push(ast1);
32516 break;
32517 }
32518 tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
32519 stack[stack.length - n - 1] = tmpVar;
32520 stack.push(tmpVar);
32521 instructions.push(new AstVariableDefinition(tmpVar, ast1));
32522 break;
32523 case 'dup':
32524 if (stack.length < 1) {
32525 return null;
32526 }
32527 if (typeof code[i + 1] === 'number' && code[i + 2] === 'gt' &&
32528 code[i + 3] === i + 7 && code[i + 4] === 'jz' &&
32529 code[i + 5] === 'pop' && code[i + 6] === code[i + 1]) {
32530 // special case of the commands sequence for the min operation
32531 num1 = stack.pop();
32532 stack.push(buildMinOperation(num1, code[i + 1]));
32533 i += 6;
32534 break;
32535 }
32536 ast1 = stack[stack.length - 1];
32537 if (ast1.type === 'literal' || ast1.type === 'var') {
32538 // we don't have to save into intermediate variable a literal or
32539 // variable.
32540 stack.push(ast1);
32541 break;
32542 }
32543 tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
32544 stack[stack.length - 1] = tmpVar;
32545 stack.push(tmpVar);
32546 instructions.push(new AstVariableDefinition(tmpVar, ast1));
32547 break;
32548 case 'roll':
32549 if (stack.length < 2) {
32550 return null;
32551 }
32552 num2 = stack.pop();
32553 num1 = stack.pop();
32554 if (num2.type !== 'literal' || num1.type !== 'literal') {
32555 // both roll operands must be numbers
32556 return null;
32557 }
32558 j = num2.number;
32559 n = num1.number;
32560 if (n <= 0 || (n|0) !== n || (j|0) !== j || stack.length < n) {
32561 // ... and integers
32562 return null;
32563 }
32564 j = ((j % n) + n) % n;
32565 if (j === 0) {
32566 break; // just skipping -- there are nothing to rotate
32567 }
32568 Array.prototype.push.apply(stack,
32569 stack.splice(stack.length - n, n - j));
32570 break;
32571 default:
32572 return null; // unsupported operator
32573 }
32574 }
32575
32576 if (stack.length !== outputSize) {
32577 return null;
32578 }
32579
32580 var result = [];
32581 instructions.forEach(function (instruction) {
32582 var statementBuilder = new ExpressionBuilderVisitor();
32583 instruction.visit(statementBuilder);
32584 result.push(statementBuilder.toString());
32585 });
32586 stack.forEach(function (expr, i) {
32587 var statementBuilder = new ExpressionBuilderVisitor();
32588 expr.visit(statementBuilder);
32589 var min = range[i * 2], max = range[i * 2 + 1];
32590 var out = [statementBuilder.toString()];
32591 if (min > expr.min) {
32592 out.unshift('Math.max(', min, ', ');
32593 out.push(')');
32594 }
32595 if (max < expr.max) {
32596 out.unshift('Math.min(', max, ', ');
32597 out.push(')');
32598 }
32599 out.unshift('dest[destOffset + ', i, '] = ');
32600 out.push(';');
32601 result.push(out.join(''));
32602 });
32603 return result.join('\n');
32604 }
32605 };
32606
32607 return PostScriptCompiler;
32608})();
32609
32610exports.isPDFFunction = isPDFFunction;
32611exports.PDFFunction = PDFFunction;
32612exports.PostScriptEvaluator = PostScriptEvaluator;
32613exports.PostScriptCompiler = PostScriptCompiler;
32614}));
32615
32616
32617(function (root, factory) {
32618 {
32619 factory((root.pdfjsCoreColorSpace = {}), root.pdfjsSharedUtil,
32620 root.pdfjsCorePrimitives, root.pdfjsCoreFunction);
32621 }
32622}(this, function (exports, sharedUtil, corePrimitives, coreFunction) {
32623
32624var error = sharedUtil.error;
32625var info = sharedUtil.info;
32626var isArray = sharedUtil.isArray;
32627var isString = sharedUtil.isString;
32628var shadow = sharedUtil.shadow;
32629var warn = sharedUtil.warn;
32630var isDict = corePrimitives.isDict;
32631var isName = corePrimitives.isName;
32632var isStream = corePrimitives.isStream;
32633var PDFFunction = coreFunction.PDFFunction;
32634
32635var ColorSpace = (function ColorSpaceClosure() {
32636 /**
32637 * Resizes an RGB image with 3 components.
32638 * @param {TypedArray} src - The source buffer.
32639 * @param {Number} bpc - Number of bits per component.
32640 * @param {Number} w1 - Original width.
32641 * @param {Number} h1 - Original height.
32642 * @param {Number} w2 - New width.
32643 * @param {Number} h2 - New height.
32644 * @param {Number} alpha01 - Size reserved for the alpha channel.
32645 * @param {TypedArray} dest - The destination buffer.
32646 */
32647 function resizeRgbImage(src, bpc, w1, h1, w2, h2, alpha01, dest) {
32648 var COMPONENTS = 3;
32649 alpha01 = alpha01 !== 1 ? 0 : alpha01;
32650 var xRatio = w1 / w2;
32651 var yRatio = h1 / h2;
32652 var i, j, py, newIndex = 0, oldIndex;
32653 var xScaled = new Uint16Array(w2);
32654 var w1Scanline = w1 * COMPONENTS;
32655
32656 for (i = 0; i < w2; i++) {
32657 xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
32658 }
32659 for (i = 0; i < h2; i++) {
32660 py = Math.floor(i * yRatio) * w1Scanline;
32661 for (j = 0; j < w2; j++) {
32662 oldIndex = py + xScaled[j];
32663 dest[newIndex++] = src[oldIndex++];
32664 dest[newIndex++] = src[oldIndex++];
32665 dest[newIndex++] = src[oldIndex++];
32666 newIndex += alpha01;
32667 }
32668 }
32669 }
32670
32671 // Constructor should define this.numComps, this.defaultColor, this.name
32672 function ColorSpace() {
32673 error('should not call ColorSpace constructor');
32674 }
32675
32676 ColorSpace.prototype = {
32677 /**
32678 * Converts the color value to the RGB color. The color components are
32679 * located in the src array starting from the srcOffset. Returns the array
32680 * of the rgb components, each value ranging from [0,255].
32681 */
32682 getRgb: function ColorSpace_getRgb(src, srcOffset) {
32683 var rgb = new Uint8Array(3);
32684 this.getRgbItem(src, srcOffset, rgb, 0);
32685 return rgb;
32686 },
32687 /**
32688 * Converts the color value to the RGB color, similar to the getRgb method.
32689 * The result placed into the dest array starting from the destOffset.
32690 */
32691 getRgbItem: function ColorSpace_getRgbItem(src, srcOffset,
32692 dest, destOffset) {
32693 error('Should not call ColorSpace.getRgbItem');
32694 },
32695 /**
32696 * Converts the specified number of the color values to the RGB colors.
32697 * The colors are located in the src array starting from the srcOffset.
32698 * The result is placed into the dest array starting from the destOffset.
32699 * The src array items shall be in [0,2^bits) range, the dest array items
32700 * will be in [0,255] range. alpha01 indicates how many alpha components
32701 * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
32702 * array).
32703 */
32704 getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
32705 dest, destOffset, bits,
32706 alpha01) {
32707 error('Should not call ColorSpace.getRgbBuffer');
32708 },
32709 /**
32710 * Determines the number of bytes required to store the result of the
32711 * conversion done by the getRgbBuffer method. As in getRgbBuffer,
32712 * |alpha01| is either 0 (RGB output) or 1 (RGBA output).
32713 */
32714 getOutputLength: function ColorSpace_getOutputLength(inputLength,
32715 alpha01) {
32716 error('Should not call ColorSpace.getOutputLength');
32717 },
32718 /**
32719 * Returns true if source data will be equal the result/output data.
32720 */
32721 isPassthrough: function ColorSpace_isPassthrough(bits) {
32722 return false;
32723 },
32724 /**
32725 * Fills in the RGB colors in the destination buffer. alpha01 indicates
32726 * how many alpha components there are in the dest array; it will be either
32727 * 0 (RGB array) or 1 (RGBA array).
32728 */
32729 fillRgb: function ColorSpace_fillRgb(dest, originalWidth,
32730 originalHeight, width, height,
32731 actualHeight, bpc, comps, alpha01) {
32732 var count = originalWidth * originalHeight;
32733 var rgbBuf = null;
32734 var numComponentColors = 1 << bpc;
32735 var needsResizing = originalHeight !== height || originalWidth !== width;
32736 var i, ii;
32737
32738 if (this.isPassthrough(bpc)) {
32739 rgbBuf = comps;
32740 } else if (this.numComps === 1 && count > numComponentColors &&
32741 this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') {
32742 // Optimization: create a color map when there is just one component and
32743 // we are converting more colors than the size of the color map. We
32744 // don't build the map if the colorspace is gray or rgb since those
32745 // methods are faster than building a map. This mainly offers big speed
32746 // ups for indexed and alternate colorspaces.
32747 //
32748 // TODO it may be worth while to cache the color map. While running
32749 // testing I never hit a cache so I will leave that out for now (perhaps
32750 // we are reparsing colorspaces too much?).
32751 var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) :
32752 new Uint16Array(numComponentColors);
32753 var key;
32754 for (i = 0; i < numComponentColors; i++) {
32755 allColors[i] = i;
32756 }
32757 var colorMap = new Uint8Array(numComponentColors * 3);
32758 this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc,
32759 /* alpha01 = */ 0);
32760
32761 var destPos, rgbPos;
32762 if (!needsResizing) {
32763 // Fill in the RGB values directly into |dest|.
32764 destPos = 0;
32765 for (i = 0; i < count; ++i) {
32766 key = comps[i] * 3;
32767 dest[destPos++] = colorMap[key];
32768 dest[destPos++] = colorMap[key + 1];
32769 dest[destPos++] = colorMap[key + 2];
32770 destPos += alpha01;
32771 }
32772 } else {
32773 rgbBuf = new Uint8Array(count * 3);
32774 rgbPos = 0;
32775 for (i = 0; i < count; ++i) {
32776 key = comps[i] * 3;
32777 rgbBuf[rgbPos++] = colorMap[key];
32778 rgbBuf[rgbPos++] = colorMap[key + 1];
32779 rgbBuf[rgbPos++] = colorMap[key + 2];
32780 }
32781 }
32782 } else {
32783 if (!needsResizing) {
32784 // Fill in the RGB values directly into |dest|.
32785 this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc,
32786 alpha01);
32787 } else {
32788 rgbBuf = new Uint8Array(count * 3);
32789 this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc,
32790 /* alpha01 = */ 0);
32791 }
32792 }
32793
32794 if (rgbBuf) {
32795 if (needsResizing) {
32796 resizeRgbImage(rgbBuf, bpc, originalWidth, originalHeight,
32797 width, height, alpha01, dest);
32798 } else {
32799 rgbPos = 0;
32800 destPos = 0;
32801 for (i = 0, ii = width * actualHeight; i < ii; i++) {
32802 dest[destPos++] = rgbBuf[rgbPos++];
32803 dest[destPos++] = rgbBuf[rgbPos++];
32804 dest[destPos++] = rgbBuf[rgbPos++];
32805 destPos += alpha01;
32806 }
32807 }
32808 }
32809 },
32810 /**
32811 * True if the colorspace has components in the default range of [0, 1].
32812 * This should be true for all colorspaces except for lab color spaces
32813 * which are [0,100], [-128, 127], [-128, 127].
32814 */
32815 usesZeroToOneRange: true
32816 };
32817
32818 ColorSpace.parse = function ColorSpace_parse(cs, xref, res) {
32819 var IR = ColorSpace.parseToIR(cs, xref, res);
32820 if (IR instanceof AlternateCS) {
32821 return IR;
32822 }
32823 return ColorSpace.fromIR(IR);
32824 };
32825
32826 ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
32827 var name = isArray(IR) ? IR[0] : IR;
32828 var whitePoint, blackPoint, gamma;
32829
32830 switch (name) {
32831 case 'DeviceGrayCS':
32832 return this.singletons.gray;
32833 case 'DeviceRgbCS':
32834 return this.singletons.rgb;
32835 case 'DeviceCmykCS':
32836 return this.singletons.cmyk;
32837 case 'CalGrayCS':
32838 whitePoint = IR[1];
32839 blackPoint = IR[2];
32840 gamma = IR[3];
32841 return new CalGrayCS(whitePoint, blackPoint, gamma);
32842 case 'CalRGBCS':
32843 whitePoint = IR[1];
32844 blackPoint = IR[2];
32845 gamma = IR[3];
32846 var matrix = IR[4];
32847 return new CalRGBCS(whitePoint, blackPoint, gamma, matrix);
32848 case 'PatternCS':
32849 var basePatternCS = IR[1];
32850 if (basePatternCS) {
32851 basePatternCS = ColorSpace.fromIR(basePatternCS);
32852 }
32853 return new PatternCS(basePatternCS);
32854 case 'IndexedCS':
32855 var baseIndexedCS = IR[1];
32856 var hiVal = IR[2];
32857 var lookup = IR[3];
32858 return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup);
32859 case 'AlternateCS':
32860 var numComps = IR[1];
32861 var alt = IR[2];
32862 var tintFnIR = IR[3];
32863
32864 return new AlternateCS(numComps, ColorSpace.fromIR(alt),
32865 PDFFunction.fromIR(tintFnIR));
32866 case 'LabCS':
32867 whitePoint = IR[1];
32868 blackPoint = IR[2];
32869 var range = IR[3];
32870 return new LabCS(whitePoint, blackPoint, range);
32871 default:
32872 error('Unknown name ' + name);
32873 }
32874 return null;
32875 };
32876
32877 ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) {
32878 if (isName(cs)) {
32879 var colorSpaces = res.get('ColorSpace');
32880 if (isDict(colorSpaces)) {
32881 var refcs = colorSpaces.get(cs.name);
32882 if (refcs) {
32883 cs = refcs;
32884 }
32885 }
32886 }
32887
32888 cs = xref.fetchIfRef(cs);
32889 var mode;
32890
32891 if (isName(cs)) {
32892 mode = cs.name;
32893 this.mode = mode;
32894
32895 switch (mode) {
32896 case 'DeviceGray':
32897 case 'G':
32898 return 'DeviceGrayCS';
32899 case 'DeviceRGB':
32900 case 'RGB':
32901 return 'DeviceRgbCS';
32902 case 'DeviceCMYK':
32903 case 'CMYK':
32904 return 'DeviceCmykCS';
32905 case 'Pattern':
32906 return ['PatternCS', null];
32907 default:
32908 error('unrecognized colorspace ' + mode);
32909 }
32910 } else if (isArray(cs)) {
32911 mode = xref.fetchIfRef(cs[0]).name;
32912 this.mode = mode;
32913 var numComps, params, alt, whitePoint, blackPoint, gamma;
32914
32915 switch (mode) {
32916 case 'DeviceGray':
32917 case 'G':
32918 return 'DeviceGrayCS';
32919 case 'DeviceRGB':
32920 case 'RGB':
32921 return 'DeviceRgbCS';
32922 case 'DeviceCMYK':
32923 case 'CMYK':
32924 return 'DeviceCmykCS';
32925 case 'CalGray':
32926 params = xref.fetchIfRef(cs[1]);
32927 whitePoint = params.getArray('WhitePoint');
32928 blackPoint = params.getArray('BlackPoint');
32929 gamma = params.get('Gamma');
32930 return ['CalGrayCS', whitePoint, blackPoint, gamma];
32931 case 'CalRGB':
32932 params = xref.fetchIfRef(cs[1]);
32933 whitePoint = params.getArray('WhitePoint');
32934 blackPoint = params.getArray('BlackPoint');
32935 gamma = params.getArray('Gamma');
32936 var matrix = params.getArray('Matrix');
32937 return ['CalRGBCS', whitePoint, blackPoint, gamma, matrix];
32938 case 'ICCBased':
32939 var stream = xref.fetchIfRef(cs[1]);
32940 var dict = stream.dict;
32941 numComps = dict.get('N');
32942 alt = dict.get('Alternate');
32943 if (alt) {
32944 var altIR = ColorSpace.parseToIR(alt, xref, res);
32945 // Parse the /Alternate CS to ensure that the number of components
32946 // are correct, and also (indirectly) that it is not a PatternCS.
32947 var altCS = ColorSpace.fromIR(altIR);
32948 if (altCS.numComps === numComps) {
32949 return altIR;
32950 }
32951 warn('ICCBased color space: Ignoring incorrect /Alternate entry.');
32952 }
32953 if (numComps === 1) {
32954 return 'DeviceGrayCS';
32955 } else if (numComps === 3) {
32956 return 'DeviceRgbCS';
32957 } else if (numComps === 4) {
32958 return 'DeviceCmykCS';
32959 }
32960 break;
32961 case 'Pattern':
32962 var basePatternCS = cs[1] || null;
32963 if (basePatternCS) {
32964 basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
32965 }
32966 return ['PatternCS', basePatternCS];
32967 case 'Indexed':
32968 case 'I':
32969 var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
32970 var hiVal = xref.fetchIfRef(cs[2]) + 1;
32971 var lookup = xref.fetchIfRef(cs[3]);
32972 if (isStream(lookup)) {
32973 lookup = lookup.getBytes();
32974 }
32975 return ['IndexedCS', baseIndexedCS, hiVal, lookup];
32976 case 'Separation':
32977 case 'DeviceN':
32978 var name = xref.fetchIfRef(cs[1]);
32979 numComps = 1;
32980 if (isName(name)) {
32981 numComps = 1;
32982 } else if (isArray(name)) {
32983 numComps = name.length;
32984 }
32985 alt = ColorSpace.parseToIR(cs[2], xref, res);
32986 var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3]));
32987 return ['AlternateCS', numComps, alt, tintFnIR];
32988 case 'Lab':
32989 params = xref.fetchIfRef(cs[1]);
32990 whitePoint = params.getArray('WhitePoint');
32991 blackPoint = params.getArray('BlackPoint');
32992 var range = params.getArray('Range');
32993 return ['LabCS', whitePoint, blackPoint, range];
32994 default:
32995 error('unimplemented color space object "' + mode + '"');
32996 }
32997 } else {
32998 error('unrecognized color space object: "' + cs + '"');
32999 }
33000 return null;
33001 };
33002 /**
33003 * Checks if a decode map matches the default decode map for a color space.
33004 * This handles the general decode maps where there are two values per
33005 * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
33006 * This does not handle Lab, Indexed, or Pattern decode maps since they are
33007 * slightly different.
33008 * @param {Array} decode Decode map (usually from an image).
33009 * @param {Number} n Number of components the color space has.
33010 */
33011 ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) {
33012 if (!isArray(decode)) {
33013 return true;
33014 }
33015
33016 if (n * 2 !== decode.length) {
33017 warn('The decode map is not the correct length');
33018 return true;
33019 }
33020 for (var i = 0, ii = decode.length; i < ii; i += 2) {
33021 if (decode[i] !== 0 || decode[i + 1] !== 1) {
33022 return false;
33023 }
33024 }
33025 return true;
33026 };
33027
33028 ColorSpace.singletons = {
33029 get gray() {
33030 return shadow(this, 'gray', new DeviceGrayCS());
33031 },
33032 get rgb() {
33033 return shadow(this, 'rgb', new DeviceRgbCS());
33034 },
33035 get cmyk() {
33036 return shadow(this, 'cmyk', new DeviceCmykCS());
33037 }
33038 };
33039
33040 return ColorSpace;
33041})();
33042
33043/**
33044 * Alternate color space handles both Separation and DeviceN color spaces. A
33045 * Separation color space is actually just a DeviceN with one color component.
33046 * Both color spaces use a tinting function to convert colors to a base color
33047 * space.
33048 */
33049var AlternateCS = (function AlternateCSClosure() {
33050 function AlternateCS(numComps, base, tintFn) {
33051 this.name = 'Alternate';
33052 this.numComps = numComps;
33053 this.defaultColor = new Float32Array(numComps);
33054 for (var i = 0; i < numComps; ++i) {
33055 this.defaultColor[i] = 1;
33056 }
33057 this.base = base;
33058 this.tintFn = tintFn;
33059 this.tmpBuf = new Float32Array(base.numComps);
33060 }
33061
33062 AlternateCS.prototype = {
33063 getRgb: ColorSpace.prototype.getRgb,
33064 getRgbItem: function AlternateCS_getRgbItem(src, srcOffset,
33065 dest, destOffset) {
33066 var tmpBuf = this.tmpBuf;
33067 this.tintFn(src, srcOffset, tmpBuf, 0);
33068 this.base.getRgbItem(tmpBuf, 0, dest, destOffset);
33069 },
33070 getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count,
33071 dest, destOffset, bits,
33072 alpha01) {
33073 var tintFn = this.tintFn;
33074 var base = this.base;
33075 var scale = 1 / ((1 << bits) - 1);
33076 var baseNumComps = base.numComps;
33077 var usesZeroToOneRange = base.usesZeroToOneRange;
33078 var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) &&
33079 alpha01 === 0;
33080 var pos = isPassthrough ? destOffset : 0;
33081 var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count);
33082 var numComps = this.numComps;
33083
33084 var scaled = new Float32Array(numComps);
33085 var tinted = new Float32Array(baseNumComps);
33086 var i, j;
33087 if (usesZeroToOneRange) {
33088 for (i = 0; i < count; i++) {
33089 for (j = 0; j < numComps; j++) {
33090 scaled[j] = src[srcOffset++] * scale;
33091 }
33092 tintFn(scaled, 0, tinted, 0);
33093 for (j = 0; j < baseNumComps; j++) {
33094 baseBuf[pos++] = tinted[j] * 255;
33095 }
33096 }
33097 } else {
33098 for (i = 0; i < count; i++) {
33099 for (j = 0; j < numComps; j++) {
33100 scaled[j] = src[srcOffset++] * scale;
33101 }
33102 tintFn(scaled, 0, tinted, 0);
33103 base.getRgbItem(tinted, 0, baseBuf, pos);
33104 pos += baseNumComps;
33105 }
33106 }
33107 if (!isPassthrough) {
33108 base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01);
33109 }
33110 },
33111 getOutputLength: function AlternateCS_getOutputLength(inputLength,
33112 alpha01) {
33113 return this.base.getOutputLength(inputLength *
33114 this.base.numComps / this.numComps,
33115 alpha01);
33116 },
33117 isPassthrough: ColorSpace.prototype.isPassthrough,
33118 fillRgb: ColorSpace.prototype.fillRgb,
33119 isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
33120 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
33121 },
33122 usesZeroToOneRange: true
33123 };
33124
33125 return AlternateCS;
33126})();
33127
33128var PatternCS = (function PatternCSClosure() {
33129 function PatternCS(baseCS) {
33130 this.name = 'Pattern';
33131 this.base = baseCS;
33132 }
33133 PatternCS.prototype = {};
33134
33135 return PatternCS;
33136})();
33137
33138var IndexedCS = (function IndexedCSClosure() {
33139 function IndexedCS(base, highVal, lookup) {
33140 this.name = 'Indexed';
33141 this.numComps = 1;
33142 this.defaultColor = new Uint8Array([0]);
33143 this.base = base;
33144 this.highVal = highVal;
33145
33146 var baseNumComps = base.numComps;
33147 var length = baseNumComps * highVal;
33148 var lookupArray;
33149
33150 if (isStream(lookup)) {
33151 lookupArray = new Uint8Array(length);
33152 var bytes = lookup.getBytes(length);
33153 lookupArray.set(bytes);
33154 } else if (isString(lookup)) {
33155 lookupArray = new Uint8Array(length);
33156 for (var i = 0; i < length; ++i) {
33157 lookupArray[i] = lookup.charCodeAt(i);
33158 }
33159 } else if (lookup instanceof Uint8Array || lookup instanceof Array) {
33160 lookupArray = lookup;
33161 } else {
33162 error('Unrecognized lookup table: ' + lookup);
33163 }
33164 this.lookup = lookupArray;
33165 }
33166
33167 IndexedCS.prototype = {
33168 getRgb: ColorSpace.prototype.getRgb,
33169 getRgbItem: function IndexedCS_getRgbItem(src, srcOffset,
33170 dest, destOffset) {
33171 var numComps = this.base.numComps;
33172 var start = src[srcOffset] * numComps;
33173 this.base.getRgbItem(this.lookup, start, dest, destOffset);
33174 },
33175 getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count,
33176 dest, destOffset, bits,
33177 alpha01) {
33178 var base = this.base;
33179 var numComps = base.numComps;
33180 var outputDelta = base.getOutputLength(numComps, alpha01);
33181 var lookup = this.lookup;
33182
33183 for (var i = 0; i < count; ++i) {
33184 var lookupPos = src[srcOffset++] * numComps;
33185 base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);
33186 destOffset += outputDelta;
33187 }
33188 },
33189 getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) {
33190 return this.base.getOutputLength(inputLength * this.base.numComps,
33191 alpha01);
33192 },
33193 isPassthrough: ColorSpace.prototype.isPassthrough,
33194 fillRgb: ColorSpace.prototype.fillRgb,
33195 isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
33196 // indexed color maps shouldn't be changed
33197 return true;
33198 },
33199 usesZeroToOneRange: true
33200 };
33201 return IndexedCS;
33202})();
33203
33204var DeviceGrayCS = (function DeviceGrayCSClosure() {
33205 function DeviceGrayCS() {
33206 this.name = 'DeviceGray';
33207 this.numComps = 1;
33208 this.defaultColor = new Float32Array([0]);
33209 }
33210
33211 DeviceGrayCS.prototype = {
33212 getRgb: ColorSpace.prototype.getRgb,
33213 getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset,
33214 dest, destOffset) {
33215 var c = (src[srcOffset] * 255) | 0;
33216 c = c < 0 ? 0 : c > 255 ? 255 : c;
33217 dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
33218 },
33219 getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count,
33220 dest, destOffset, bits,
33221 alpha01) {
33222 var scale = 255 / ((1 << bits) - 1);
33223 var j = srcOffset, q = destOffset;
33224 for (var i = 0; i < count; ++i) {
33225 var c = (scale * src[j++]) | 0;
33226 dest[q++] = c;
33227 dest[q++] = c;
33228 dest[q++] = c;
33229 q += alpha01;
33230 }
33231 },
33232 getOutputLength: function DeviceGrayCS_getOutputLength(inputLength,
33233 alpha01) {
33234 return inputLength * (3 + alpha01);
33235 },
33236 isPassthrough: ColorSpace.prototype.isPassthrough,
33237 fillRgb: ColorSpace.prototype.fillRgb,
33238 isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
33239 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
33240 },
33241 usesZeroToOneRange: true
33242 };
33243 return DeviceGrayCS;
33244})();
33245
33246var DeviceRgbCS = (function DeviceRgbCSClosure() {
33247 function DeviceRgbCS() {
33248 this.name = 'DeviceRGB';
33249 this.numComps = 3;
33250 this.defaultColor = new Float32Array([0, 0, 0]);
33251 }
33252 DeviceRgbCS.prototype = {
33253 getRgb: ColorSpace.prototype.getRgb,
33254 getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset,
33255 dest, destOffset) {
33256 var r = (src[srcOffset] * 255) | 0;
33257 var g = (src[srcOffset + 1] * 255) | 0;
33258 var b = (src[srcOffset + 2] * 255) | 0;
33259 dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r;
33260 dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g;
33261 dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b;
33262 },
33263 getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count,
33264 dest, destOffset, bits,
33265 alpha01) {
33266 if (bits === 8 && alpha01 === 0) {
33267 dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);
33268 return;
33269 }
33270 var scale = 255 / ((1 << bits) - 1);
33271 var j = srcOffset, q = destOffset;
33272 for (var i = 0; i < count; ++i) {
33273 dest[q++] = (scale * src[j++]) | 0;
33274 dest[q++] = (scale * src[j++]) | 0;
33275 dest[q++] = (scale * src[j++]) | 0;
33276 q += alpha01;
33277 }
33278 },
33279 getOutputLength: function DeviceRgbCS_getOutputLength(inputLength,
33280 alpha01) {
33281 return (inputLength * (3 + alpha01) / 3) | 0;
33282 },
33283 isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
33284 return bits === 8;
33285 },
33286 fillRgb: ColorSpace.prototype.fillRgb,
33287 isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
33288 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
33289 },
33290 usesZeroToOneRange: true
33291 };
33292 return DeviceRgbCS;
33293})();
33294
33295var DeviceCmykCS = (function DeviceCmykCSClosure() {
33296 // The coefficients below was found using numerical analysis: the method of
33297 // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
33298 // where color_value is the tabular value from the table of sampled RGB colors
33299 // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
33300 // CMYK color conversion using the estimation below:
33301 // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
33302 function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
33303 var c = src[srcOffset + 0] * srcScale;
33304 var m = src[srcOffset + 1] * srcScale;
33305 var y = src[srcOffset + 2] * srcScale;
33306 var k = src[srcOffset + 3] * srcScale;
33307
33308 var r =
33309 (c * (-4.387332384609988 * c + 54.48615194189176 * m +
33310 18.82290502165302 * y + 212.25662451639585 * k +
33311 -285.2331026137004) +
33312 m * (1.7149763477362134 * m - 5.6096736904047315 * y +
33313 -17.873870861415444 * k - 5.497006427196366) +
33314 y * (-2.5217340131683033 * y - 21.248923337353073 * k +
33315 17.5119270841813) +
33316 k * (-21.86122147463605 * k - 189.48180835922747) + 255) | 0;
33317 var g =
33318 (c * (8.841041422036149 * c + 60.118027045597366 * m +
33319 6.871425592049007 * y + 31.159100130055922 * k +
33320 -79.2970844816548) +
33321 m * (-15.310361306967817 * m + 17.575251261109482 * y +
33322 131.35250912493976 * k - 190.9453302588951) +
33323 y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) +
33324 k * (-20.737325471181034 * k - 187.80453709719578) + 255) | 0;
33325 var b =
33326 (c * (0.8842522430003296 * c + 8.078677503112928 * m +
33327 30.89978309703729 * y - 0.23883238689178934 * k +
33328 -14.183576799673286) +
33329 m * (10.49593273432072 * m + 63.02378494754052 * y +
33330 50.606957656360734 * k - 112.23884253719248) +
33331 y * (0.03296041114873217 * y + 115.60384449646641 * k +
33332 -193.58209356861505) +
33333 k * (-22.33816807309886 * k - 180.12613974708367) + 255) | 0;
33334
33335 dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r;
33336 dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g;
33337 dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b;
33338 }
33339
33340 function DeviceCmykCS() {
33341 this.name = 'DeviceCMYK';
33342 this.numComps = 4;
33343 this.defaultColor = new Float32Array([0, 0, 0, 1]);
33344 }
33345 DeviceCmykCS.prototype = {
33346 getRgb: ColorSpace.prototype.getRgb,
33347 getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset,
33348 dest, destOffset) {
33349 convertToRgb(src, srcOffset, 1, dest, destOffset);
33350 },
33351 getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count,
33352 dest, destOffset, bits,
33353 alpha01) {
33354 var scale = 1 / ((1 << bits) - 1);
33355 for (var i = 0; i < count; i++) {
33356 convertToRgb(src, srcOffset, scale, dest, destOffset);
33357 srcOffset += 4;
33358 destOffset += 3 + alpha01;
33359 }
33360 },
33361 getOutputLength: function DeviceCmykCS_getOutputLength(inputLength,
33362 alpha01) {
33363 return (inputLength / 4 * (3 + alpha01)) | 0;
33364 },
33365 isPassthrough: ColorSpace.prototype.isPassthrough,
33366 fillRgb: ColorSpace.prototype.fillRgb,
33367 isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
33368 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
33369 },
33370 usesZeroToOneRange: true
33371 };
33372
33373 return DeviceCmykCS;
33374})();
33375
33376//
33377// CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245
33378//
33379var CalGrayCS = (function CalGrayCSClosure() {
33380 function CalGrayCS(whitePoint, blackPoint, gamma) {
33381 this.name = 'CalGray';
33382 this.numComps = 1;
33383 this.defaultColor = new Float32Array([0]);
33384
33385 if (!whitePoint) {
33386 error('WhitePoint missing - required for color space CalGray');
33387 }
33388 blackPoint = blackPoint || [0, 0, 0];
33389 gamma = gamma || 1;
33390
33391 // Translate arguments to spec variables.
33392 this.XW = whitePoint[0];
33393 this.YW = whitePoint[1];
33394 this.ZW = whitePoint[2];
33395
33396 this.XB = blackPoint[0];
33397 this.YB = blackPoint[1];
33398 this.ZB = blackPoint[2];
33399
33400 this.G = gamma;
33401
33402 // Validate variables as per spec.
33403 if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
33404 error('Invalid WhitePoint components for ' + this.name +
33405 ', no fallback available');
33406 }
33407
33408 if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
33409 info('Invalid BlackPoint for ' + this.name + ', falling back to default');
33410 this.XB = this.YB = this.ZB = 0;
33411 }
33412
33413 if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
33414 warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB +
33415 ', ZB: ' + this.ZB + ', only default values are supported.');
33416 }
33417
33418 if (this.G < 1) {
33419 info('Invalid Gamma: ' + this.G + ' for ' + this.name +
33420 ', falling back to default');
33421 this.G = 1;
33422 }
33423 }
33424
33425 function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
33426 // A represents a gray component of a calibrated gray space.
33427 // A <---> AG in the spec
33428 var A = src[srcOffset] * scale;
33429 var AG = Math.pow(A, cs.G);
33430
33431 // Computes L as per spec. ( = cs.YW * AG )
33432 // Except if other than default BlackPoint values are used.
33433 var L = cs.YW * AG;
33434 // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4.
33435 // Convert values to rgb range [0, 255].
33436 var val = Math.max(295.8 * Math.pow(L, 0.333333333333333333) - 40.8, 0) | 0;
33437 dest[destOffset] = val;
33438 dest[destOffset + 1] = val;
33439 dest[destOffset + 2] = val;
33440 }
33441
33442 CalGrayCS.prototype = {
33443 getRgb: ColorSpace.prototype.getRgb,
33444 getRgbItem: function CalGrayCS_getRgbItem(src, srcOffset,
33445 dest, destOffset) {
33446 convertToRgb(this, src, srcOffset, dest, destOffset, 1);
33447 },
33448 getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count,
33449 dest, destOffset, bits,
33450 alpha01) {
33451 var scale = 1 / ((1 << bits) - 1);
33452
33453 for (var i = 0; i < count; ++i) {
33454 convertToRgb(this, src, srcOffset, dest, destOffset, scale);
33455 srcOffset += 1;
33456 destOffset += 3 + alpha01;
33457 }
33458 },
33459 getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) {
33460 return inputLength * (3 + alpha01);
33461 },
33462 isPassthrough: ColorSpace.prototype.isPassthrough,
33463 fillRgb: ColorSpace.prototype.fillRgb,
33464 isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) {
33465 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
33466 },
33467 usesZeroToOneRange: true
33468 };
33469 return CalGrayCS;
33470})();
33471
33472//
33473// CalRGBCS: Based on "PDF Reference, Sixth Ed", p.247
33474//
33475var CalRGBCS = (function CalRGBCSClosure() {
33476
33477 // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these
33478 // matrices.
33479 var BRADFORD_SCALE_MATRIX = new Float32Array([
33480 0.8951, 0.2664, -0.1614,
33481 -0.7502, 1.7135, 0.0367,
33482 0.0389, -0.0685, 1.0296]);
33483
33484 var BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([
33485 0.9869929, -0.1470543, 0.1599627,
33486 0.4323053, 0.5183603, 0.0492912,
33487 -0.0085287, 0.0400428, 0.9684867]);
33488
33489 // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html.
33490 var SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([
33491 3.2404542, -1.5371385, -0.4985314,
33492 -0.9692660, 1.8760108, 0.0415560,
33493 0.0556434, -0.2040259, 1.0572252]);
33494
33495 var FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
33496
33497 var tempNormalizeMatrix = new Float32Array(3);
33498 var tempConvertMatrix1 = new Float32Array(3);
33499 var tempConvertMatrix2 = new Float32Array(3);
33500
33501 var DECODE_L_CONSTANT = Math.pow(((8 + 16) / 116), 3) / 8.0;
33502
33503 function CalRGBCS(whitePoint, blackPoint, gamma, matrix) {
33504 this.name = 'CalRGB';
33505 this.numComps = 3;
33506 this.defaultColor = new Float32Array(3);
33507
33508 if (!whitePoint) {
33509 error('WhitePoint missing - required for color space CalRGB');
33510 }
33511 blackPoint = blackPoint || new Float32Array(3);
33512 gamma = gamma || new Float32Array([1, 1, 1]);
33513 matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
33514
33515 // Translate arguments to spec variables.
33516 var XW = whitePoint[0];
33517 var YW = whitePoint[1];
33518 var ZW = whitePoint[2];
33519 this.whitePoint = whitePoint;
33520
33521 var XB = blackPoint[0];
33522 var YB = blackPoint[1];
33523 var ZB = blackPoint[2];
33524 this.blackPoint = blackPoint;
33525
33526 this.GR = gamma[0];
33527 this.GG = gamma[1];
33528 this.GB = gamma[2];
33529
33530 this.MXA = matrix[0];
33531 this.MYA = matrix[1];
33532 this.MZA = matrix[2];
33533 this.MXB = matrix[3];
33534 this.MYB = matrix[4];
33535 this.MZB = matrix[5];
33536 this.MXC = matrix[6];
33537 this.MYC = matrix[7];
33538 this.MZC = matrix[8];
33539
33540 // Validate variables as per spec.
33541 if (XW < 0 || ZW < 0 || YW !== 1) {
33542 error('Invalid WhitePoint components for ' + this.name +
33543 ', no fallback available');
33544 }
33545
33546 if (XB < 0 || YB < 0 || ZB < 0) {
33547 info('Invalid BlackPoint for ' + this.name + ' [' + XB + ', ' + YB +
33548 ', ' + ZB + '], falling back to default');
33549 this.blackPoint = new Float32Array(3);
33550 }
33551
33552 if (this.GR < 0 || this.GG < 0 || this.GB < 0) {
33553 info('Invalid Gamma [' + this.GR + ', ' + this.GG + ', ' + this.GB +
33554 '] for ' + this.name + ', falling back to default');
33555 this.GR = this.GG = this.GB = 1;
33556 }
33557
33558 if (this.MXA < 0 || this.MYA < 0 || this.MZA < 0 ||
33559 this.MXB < 0 || this.MYB < 0 || this.MZB < 0 ||
33560 this.MXC < 0 || this.MYC < 0 || this.MZC < 0) {
33561 info('Invalid Matrix for ' + this.name + ' [' +
33562 this.MXA + ', ' + this.MYA + ', ' + this.MZA +
33563 this.MXB + ', ' + this.MYB + ', ' + this.MZB +
33564 this.MXC + ', ' + this.MYC + ', ' + this.MZC +
33565 '], falling back to default');
33566 this.MXA = this.MYB = this.MZC = 1;
33567 this.MXB = this.MYA = this.MZA = this.MXC = this.MYC = this.MZB = 0;
33568 }
33569 }
33570
33571 function matrixProduct(a, b, result) {
33572 result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
33573 result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
33574 result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
33575 }
33576
33577 function convertToFlat(sourceWhitePoint, LMS, result) {
33578 result[0] = LMS[0] * 1 / sourceWhitePoint[0];
33579 result[1] = LMS[1] * 1 / sourceWhitePoint[1];
33580 result[2] = LMS[2] * 1 / sourceWhitePoint[2];
33581 }
33582
33583 function convertToD65(sourceWhitePoint, LMS, result) {
33584 var D65X = 0.95047;
33585 var D65Y = 1;
33586 var D65Z = 1.08883;
33587
33588 result[0] = LMS[0] * D65X / sourceWhitePoint[0];
33589 result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
33590 result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
33591 }
33592
33593 function sRGBTransferFunction(color) {
33594 // See http://en.wikipedia.org/wiki/SRGB.
33595 if (color <= 0.0031308){
33596 return adjustToRange(0, 1, 12.92 * color);
33597 }
33598
33599 return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055);
33600 }
33601
33602 function adjustToRange(min, max, value) {
33603 return Math.max(min, Math.min(max, value));
33604 }
33605
33606 function decodeL(L) {
33607 if (L < 0) {
33608 return -decodeL(-L);
33609 }
33610
33611 if (L > 8.0) {
33612 return Math.pow(((L + 16) / 116), 3);
33613 }
33614
33615 return L * DECODE_L_CONSTANT;
33616 }
33617
33618 function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
33619
33620 // In case the blackPoint is already the default blackPoint then there is
33621 // no need to do compensation.
33622 if (sourceBlackPoint[0] === 0 &&
33623 sourceBlackPoint[1] === 0 &&
33624 sourceBlackPoint[2] === 0) {
33625 result[0] = XYZ_Flat[0];
33626 result[1] = XYZ_Flat[1];
33627 result[2] = XYZ_Flat[2];
33628 return;
33629 }
33630
33631 // For the blackPoint calculation details, please see
33632 // http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/
33633 // AdobeBPC.pdf.
33634 // The destination blackPoint is the default blackPoint [0, 0, 0].
33635 var zeroDecodeL = decodeL(0);
33636
33637 var X_DST = zeroDecodeL;
33638 var X_SRC = decodeL(sourceBlackPoint[0]);
33639
33640 var Y_DST = zeroDecodeL;
33641 var Y_SRC = decodeL(sourceBlackPoint[1]);
33642
33643 var Z_DST = zeroDecodeL;
33644 var Z_SRC = decodeL(sourceBlackPoint[2]);
33645
33646 var X_Scale = (1 - X_DST) / (1 - X_SRC);
33647 var X_Offset = 1 - X_Scale;
33648
33649 var Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
33650 var Y_Offset = 1 - Y_Scale;
33651
33652 var Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
33653 var Z_Offset = 1 - Z_Scale;
33654
33655 result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
33656 result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
33657 result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
33658 }
33659
33660 function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
33661
33662 // In case the whitePoint is already flat then there is no need to do
33663 // normalization.
33664 if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
33665 result[0] = XYZ_In[0];
33666 result[1] = XYZ_In[1];
33667 result[2] = XYZ_In[2];
33668 return;
33669 }
33670
33671 var LMS = result;
33672 matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
33673
33674 var LMS_Flat = tempNormalizeMatrix;
33675 convertToFlat(sourceWhitePoint, LMS, LMS_Flat);
33676
33677 matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result);
33678 }
33679
33680 function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
33681
33682 var LMS = result;
33683 matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
33684
33685 var LMS_D65 = tempNormalizeMatrix;
33686 convertToD65(sourceWhitePoint, LMS, LMS_D65);
33687
33688 matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result);
33689 }
33690
33691 function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
33692 // A, B and C represent a red, green and blue components of a calibrated
33693 // rgb space.
33694 var A = adjustToRange(0, 1, src[srcOffset] * scale);
33695 var B = adjustToRange(0, 1, src[srcOffset + 1] * scale);
33696 var C = adjustToRange(0, 1, src[srcOffset + 2] * scale);
33697
33698 // A <---> AGR in the spec
33699 // B <---> BGG in the spec
33700 // C <---> CGB in the spec
33701 var AGR = Math.pow(A, cs.GR);
33702 var BGG = Math.pow(B, cs.GG);
33703 var CGB = Math.pow(C, cs.GB);
33704
33705 // Computes intermediate variables L, M, N as per spec.
33706 // To decode X, Y, Z values map L, M, N directly to them.
33707 var X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB;
33708 var Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB;
33709 var Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB;
33710
33711 // The following calculations are based on this document:
33712 // http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/
33713 // AdobeBPC.pdf.
33714 var XYZ = tempConvertMatrix1;
33715 XYZ[0] = X;
33716 XYZ[1] = Y;
33717 XYZ[2] = Z;
33718 var XYZ_Flat = tempConvertMatrix2;
33719
33720 normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat);
33721
33722 var XYZ_Black = tempConvertMatrix1;
33723 compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black);
33724
33725 var XYZ_D65 = tempConvertMatrix2;
33726 normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65);
33727
33728 var SRGB = tempConvertMatrix1;
33729 matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
33730
33731 var sR = sRGBTransferFunction(SRGB[0]);
33732 var sG = sRGBTransferFunction(SRGB[1]);
33733 var sB = sRGBTransferFunction(SRGB[2]);
33734
33735 // Convert the values to rgb range [0, 255].
33736 dest[destOffset] = Math.round(sR * 255);
33737 dest[destOffset + 1] = Math.round(sG * 255);
33738 dest[destOffset + 2] = Math.round(sB * 255);
33739 }
33740
33741 CalRGBCS.prototype = {
33742 getRgb: function CalRGBCS_getRgb(src, srcOffset) {
33743 var rgb = new Uint8Array(3);
33744 this.getRgbItem(src, srcOffset, rgb, 0);
33745 return rgb;
33746 },
33747 getRgbItem: function CalRGBCS_getRgbItem(src, srcOffset,
33748 dest, destOffset) {
33749 convertToRgb(this, src, srcOffset, dest, destOffset, 1);
33750 },
33751 getRgbBuffer: function CalRGBCS_getRgbBuffer(src, srcOffset, count,
33752 dest, destOffset, bits,
33753 alpha01) {
33754 var scale = 1 / ((1 << bits) - 1);
33755
33756 for (var i = 0; i < count; ++i) {
33757 convertToRgb(this, src, srcOffset, dest, destOffset, scale);
33758 srcOffset += 3;
33759 destOffset += 3 + alpha01;
33760 }
33761 },
33762 getOutputLength: function CalRGBCS_getOutputLength(inputLength, alpha01) {
33763 return (inputLength * (3 + alpha01) / 3) | 0;
33764 },
33765 isPassthrough: ColorSpace.prototype.isPassthrough,
33766 fillRgb: ColorSpace.prototype.fillRgb,
33767 isDefaultDecode: function CalRGBCS_isDefaultDecode(decodeMap) {
33768 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
33769 },
33770 usesZeroToOneRange: true
33771 };
33772 return CalRGBCS;
33773})();
33774
33775//
33776// LabCS: Based on "PDF Reference, Sixth Ed", p.250
33777//
33778var LabCS = (function LabCSClosure() {
33779 function LabCS(whitePoint, blackPoint, range) {
33780 this.name = 'Lab';
33781 this.numComps = 3;
33782 this.defaultColor = new Float32Array([0, 0, 0]);
33783
33784 if (!whitePoint) {
33785 error('WhitePoint missing - required for color space Lab');
33786 }
33787 blackPoint = blackPoint || [0, 0, 0];
33788 range = range || [-100, 100, -100, 100];
33789
33790 // Translate args to spec variables
33791 this.XW = whitePoint[0];
33792 this.YW = whitePoint[1];
33793 this.ZW = whitePoint[2];
33794 this.amin = range[0];
33795 this.amax = range[1];
33796 this.bmin = range[2];
33797 this.bmax = range[3];
33798
33799 // These are here just for completeness - the spec doesn't offer any
33800 // formulas that use BlackPoint in Lab
33801 this.XB = blackPoint[0];
33802 this.YB = blackPoint[1];
33803 this.ZB = blackPoint[2];
33804
33805 // Validate vars as per spec
33806 if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
33807 error('Invalid WhitePoint components, no fallback available');
33808 }
33809
33810 if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
33811 info('Invalid BlackPoint, falling back to default');
33812 this.XB = this.YB = this.ZB = 0;
33813 }
33814
33815 if (this.amin > this.amax || this.bmin > this.bmax) {
33816 info('Invalid Range, falling back to defaults');
33817 this.amin = -100;
33818 this.amax = 100;
33819 this.bmin = -100;
33820 this.bmax = 100;
33821 }
33822 }
33823
33824 // Function g(x) from spec
33825 function fn_g(x) {
33826 if (x >= 6 / 29) {
33827 return x * x * x;
33828 } else {
33829 return (108 / 841) * (x - 4 / 29);
33830 }
33831 }
33832
33833 function decode(value, high1, low2, high2) {
33834 return low2 + (value) * (high2 - low2) / (high1);
33835 }
33836
33837 // If decoding is needed maxVal should be 2^bits per component - 1.
33838 function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) {
33839 // XXX: Lab input is in the range of [0, 100], [amin, amax], [bmin, bmax]
33840 // not the usual [0, 1]. If a command like setFillColor is used the src
33841 // values will already be within the correct range. However, if we are
33842 // converting an image we have to map the values to the correct range given
33843 // above.
33844 // Ls,as,bs <---> L*,a*,b* in the spec
33845 var Ls = src[srcOffset];
33846 var as = src[srcOffset + 1];
33847 var bs = src[srcOffset + 2];
33848 if (maxVal !== false) {
33849 Ls = decode(Ls, maxVal, 0, 100);
33850 as = decode(as, maxVal, cs.amin, cs.amax);
33851 bs = decode(bs, maxVal, cs.bmin, cs.bmax);
33852 }
33853
33854 // Adjust limits of 'as' and 'bs'
33855 as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
33856 bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
33857
33858 // Computes intermediate variables X,Y,Z as per spec
33859 var M = (Ls + 16) / 116;
33860 var L = M + (as / 500);
33861 var N = M - (bs / 200);
33862
33863 var X = cs.XW * fn_g(L);
33864 var Y = cs.YW * fn_g(M);
33865 var Z = cs.ZW * fn_g(N);
33866
33867 var r, g, b;
33868 // Using different conversions for D50 and D65 white points,
33869 // per http://www.color.org/srgb.pdf
33870 if (cs.ZW < 1) {
33871 // Assuming D50 (X=0.9642, Y=1.00, Z=0.8249)
33872 r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
33873 g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
33874 b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
33875 } else {
33876 // Assuming D65 (X=0.9505, Y=1.00, Z=1.0888)
33877 r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
33878 g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
33879 b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
33880 }
33881 // clamp color values to [0,1] range then convert to [0,255] range.
33882 dest[destOffset] = r <= 0 ? 0 : r >= 1 ? 255 : Math.sqrt(r) * 255 | 0;
33883 dest[destOffset + 1] = g <= 0 ? 0 : g >= 1 ? 255 : Math.sqrt(g) * 255 | 0;
33884 dest[destOffset + 2] = b <= 0 ? 0 : b >= 1 ? 255 : Math.sqrt(b) * 255 | 0;
33885 }
33886
33887 LabCS.prototype = {
33888 getRgb: ColorSpace.prototype.getRgb,
33889 getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) {
33890 convertToRgb(this, src, srcOffset, false, dest, destOffset);
33891 },
33892 getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count,
33893 dest, destOffset, bits,
33894 alpha01) {
33895 var maxVal = (1 << bits) - 1;
33896 for (var i = 0; i < count; i++) {
33897 convertToRgb(this, src, srcOffset, maxVal, dest, destOffset);
33898 srcOffset += 3;
33899 destOffset += 3 + alpha01;
33900 }
33901 },
33902 getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) {
33903 return (inputLength * (3 + alpha01) / 3) | 0;
33904 },
33905 isPassthrough: ColorSpace.prototype.isPassthrough,
33906 fillRgb: ColorSpace.prototype.fillRgb,
33907 isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
33908 // XXX: Decoding is handled with the lab conversion because of the strange
33909 // ranges that are used.
33910 return true;
33911 },
33912 usesZeroToOneRange: false
33913 };
33914 return LabCS;
33915})();
33916
33917exports.ColorSpace = ColorSpace;
33918}));
33919
33920
33921(function (root, factory) {
33922 {
33923 factory((root.pdfjsCoreImage = {}), root.pdfjsSharedUtil,
33924 root.pdfjsCorePrimitives, root.pdfjsCoreColorSpace, root.pdfjsCoreStream,
33925 root.pdfjsCoreJpx);
33926 }
33927}(this, function (exports, sharedUtil, corePrimitives, coreColorSpace,
33928 coreStream, coreJpx) {
33929
33930var ImageKind = sharedUtil.ImageKind;
33931var assert = sharedUtil.assert;
33932var error = sharedUtil.error;
33933var info = sharedUtil.info;
33934var isArray = sharedUtil.isArray;
33935var warn = sharedUtil.warn;
33936var Name = corePrimitives.Name;
33937var isStream = corePrimitives.isStream;
33938var ColorSpace = coreColorSpace.ColorSpace;
33939var DecodeStream = coreStream.DecodeStream;
33940var JpegStream = coreStream.JpegStream;
33941var JpxImage = coreJpx.JpxImage;
33942
33943var PDFImage = (function PDFImageClosure() {
33944 /**
33945 * Decodes the image using native decoder if possible. Resolves the promise
33946 * when the image data is ready.
33947 */
33948 function handleImageData(image, nativeDecoder) {
33949 if (nativeDecoder && nativeDecoder.canDecode(image)) {
33950 return nativeDecoder.decode(image);
33951 } else {
33952 return Promise.resolve(image);
33953 }
33954 }
33955
33956 /**
33957 * Decode and clamp a value. The formula is different from the spec because we
33958 * don't decode to float range [0,1], we decode it in the [0,max] range.
33959 */
33960 function decodeAndClamp(value, addend, coefficient, max) {
33961 value = addend + value * coefficient;
33962 // Clamp the value to the range
33963 return (value < 0 ? 0 : (value > max ? max : value));
33964 }
33965
33966 /**
33967 * Resizes an image mask with 1 component.
33968 * @param {TypedArray} src - The source buffer.
33969 * @param {Number} bpc - Number of bits per component.
33970 * @param {Number} w1 - Original width.
33971 * @param {Number} h1 - Original height.
33972 * @param {Number} w2 - New width.
33973 * @param {Number} h2 - New height.
33974 * @returns {TypedArray} The resized image mask buffer.
33975 */
33976 function resizeImageMask(src, bpc, w1, h1, w2, h2) {
33977 var length = w2 * h2;
33978 var dest = (bpc <= 8 ? new Uint8Array(length) :
33979 (bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length)));
33980 var xRatio = w1 / w2;
33981 var yRatio = h1 / h2;
33982 var i, j, py, newIndex = 0, oldIndex;
33983 var xScaled = new Uint16Array(w2);
33984 var w1Scanline = w1;
33985
33986 for (i = 0; i < w2; i++) {
33987 xScaled[i] = Math.floor(i * xRatio);
33988 }
33989 for (i = 0; i < h2; i++) {
33990 py = Math.floor(i * yRatio) * w1Scanline;
33991 for (j = 0; j < w2; j++) {
33992 oldIndex = py + xScaled[j];
33993 dest[newIndex++] = src[oldIndex];
33994 }
33995 }
33996 return dest;
33997 }
33998
33999 function PDFImage(xref, res, image, inline, smask, mask, isMask) {
34000 this.image = image;
34001 var dict = image.dict;
34002 if (dict.has('Filter')) {
34003 var filter = dict.get('Filter').name;
34004 if (filter === 'JPXDecode') {
34005 var jpxImage = new JpxImage();
34006 jpxImage.parseImageProperties(image.stream);
34007 image.stream.reset();
34008 image.bitsPerComponent = jpxImage.bitsPerComponent;
34009 image.numComps = jpxImage.componentsCount;
34010 } else if (filter === 'JBIG2Decode') {
34011 image.bitsPerComponent = 1;
34012 image.numComps = 1;
34013 }
34014 }
34015 // TODO cache rendered images?
34016
34017 this.width = dict.get('Width', 'W');
34018 this.height = dict.get('Height', 'H');
34019
34020 if (this.width < 1 || this.height < 1) {
34021 error('Invalid image width: ' + this.width + ' or height: ' +
34022 this.height);
34023 }
34024
34025 this.interpolate = dict.get('Interpolate', 'I') || false;
34026 this.imageMask = dict.get('ImageMask', 'IM') || false;
34027 this.matte = dict.get('Matte') || false;
34028
34029 var bitsPerComponent = image.bitsPerComponent;
34030 if (!bitsPerComponent) {
34031 bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
34032 if (!bitsPerComponent) {
34033 if (this.imageMask) {
34034 bitsPerComponent = 1;
34035 } else {
34036 error('Bits per component missing in image: ' + this.imageMask);
34037 }
34038 }
34039 }
34040 this.bpc = bitsPerComponent;
34041
34042 if (!this.imageMask) {
34043 var colorSpace = dict.get('ColorSpace', 'CS');
34044 if (!colorSpace) {
34045 info('JPX images (which do not require color spaces)');
34046 switch (image.numComps) {
34047 case 1:
34048 colorSpace = Name.get('DeviceGray');
34049 break;
34050 case 3:
34051 colorSpace = Name.get('DeviceRGB');
34052 break;
34053 case 4:
34054 colorSpace = Name.get('DeviceCMYK');
34055 break;
34056 default:
34057 error('JPX images with ' + this.numComps +
34058 ' color components not supported.');
34059 }
34060 }
34061 this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
34062 this.numComps = this.colorSpace.numComps;
34063 }
34064
34065 this.decode = dict.getArray('Decode', 'D');
34066 this.needsDecode = false;
34067 if (this.decode &&
34068 ((this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode)) ||
34069 (isMask && !ColorSpace.isDefaultDecode(this.decode, 1)))) {
34070 this.needsDecode = true;
34071 // Do some preprocessing to avoid more math.
34072 var max = (1 << bitsPerComponent) - 1;
34073 this.decodeCoefficients = [];
34074 this.decodeAddends = [];
34075 for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
34076 var dmin = this.decode[i];
34077 var dmax = this.decode[i + 1];
34078 this.decodeCoefficients[j] = dmax - dmin;
34079 this.decodeAddends[j] = max * dmin;
34080 }
34081 }
34082
34083 if (smask) {
34084 this.smask = new PDFImage(xref, res, smask, false);
34085 } else if (mask) {
34086 if (isStream(mask)) {
34087 var maskDict = mask.dict, imageMask = maskDict.get('ImageMask', 'IM');
34088 if (!imageMask) {
34089 warn('Ignoring /Mask in image without /ImageMask.');
34090 } else {
34091 this.mask = new PDFImage(xref, res, mask, false, null, null, true);
34092 }
34093 } else {
34094 // Color key mask (just an array).
34095 this.mask = mask;
34096 }
34097 }
34098 }
34099 /**
34100 * Handles processing of image data and returns the Promise that is resolved
34101 * with a PDFImage when the image is ready to be used.
34102 */
34103 PDFImage.buildImage = function PDFImage_buildImage(handler, xref,
34104 res, image, inline,
34105 nativeDecoder) {
34106 var imagePromise = handleImageData(image, nativeDecoder);
34107 var smaskPromise;
34108 var maskPromise;
34109
34110 var smask = image.dict.get('SMask');
34111 var mask = image.dict.get('Mask');
34112
34113 if (smask) {
34114 smaskPromise = handleImageData(smask, nativeDecoder);
34115 maskPromise = Promise.resolve(null);
34116 } else {
34117 smaskPromise = Promise.resolve(null);
34118 if (mask) {
34119 if (isStream(mask)) {
34120 maskPromise = handleImageData(mask, nativeDecoder);
34121 } else if (isArray(mask)) {
34122 maskPromise = Promise.resolve(mask);
34123 } else {
34124 warn('Unsupported mask format.');
34125 maskPromise = Promise.resolve(null);
34126 }
34127 } else {
34128 maskPromise = Promise.resolve(null);
34129 }
34130 }
34131 return Promise.all([imagePromise, smaskPromise, maskPromise]).then(
34132 function(results) {
34133 var imageData = results[0];
34134 var smaskData = results[1];
34135 var maskData = results[2];
34136 return new PDFImage(xref, res, imageData, inline, smaskData, maskData);
34137 });
34138 };
34139
34140 PDFImage.createMask =
34141 function PDFImage_createMask(imgArray, width, height,
34142 imageIsFromDecodeStream, inverseDecode) {
34143
34144 // |imgArray| might not contain full data for every pixel of the mask, so
34145 // we need to distinguish between |computedLength| and |actualLength|.
34146 // In particular, if inverseDecode is true, then the array we return must
34147 // have a length of |computedLength|.
34148
34149 var computedLength = ((width + 7) >> 3) * height;
34150 var actualLength = imgArray.byteLength;
34151 var haveFullData = computedLength === actualLength;
34152 var data, i;
34153
34154 if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) {
34155 // imgArray came from a DecodeStream and its data is in an appropriate
34156 // form, so we can just transfer it.
34157 data = imgArray;
34158 } else if (!inverseDecode) {
34159 data = new Uint8Array(actualLength);
34160 data.set(imgArray);
34161 } else {
34162 data = new Uint8Array(computedLength);
34163 data.set(imgArray);
34164 for (i = actualLength; i < computedLength; i++) {
34165 data[i] = 0xff;
34166 }
34167 }
34168
34169 // If necessary, invert the original mask data (but not any extra we might
34170 // have added above). It's safe to modify the array -- whether it's the
34171 // original or a copy, we're about to transfer it anyway, so nothing else
34172 // in this thread can be relying on its contents.
34173 if (inverseDecode) {
34174 for (i = 0; i < actualLength; i++) {
34175 data[i] = ~data[i];
34176 }
34177 }
34178
34179 return {data: data, width: width, height: height};
34180 };
34181
34182 PDFImage.prototype = {
34183 get drawWidth() {
34184 return Math.max(this.width,
34185 this.smask && this.smask.width || 0,
34186 this.mask && this.mask.width || 0);
34187 },
34188
34189 get drawHeight() {
34190 return Math.max(this.height,
34191 this.smask && this.smask.height || 0,
34192 this.mask && this.mask.height || 0);
34193 },
34194
34195 decodeBuffer: function PDFImage_decodeBuffer(buffer) {
34196 var bpc = this.bpc;
34197 var numComps = this.numComps;
34198
34199 var decodeAddends = this.decodeAddends;
34200 var decodeCoefficients = this.decodeCoefficients;
34201 var max = (1 << bpc) - 1;
34202 var i, ii;
34203
34204 if (bpc === 1) {
34205 // If the buffer needed decode that means it just needs to be inverted.
34206 for (i = 0, ii = buffer.length; i < ii; i++) {
34207 buffer[i] = +!(buffer[i]);
34208 }
34209 return;
34210 }
34211 var index = 0;
34212 for (i = 0, ii = this.width * this.height; i < ii; i++) {
34213 for (var j = 0; j < numComps; j++) {
34214 buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j],
34215 decodeCoefficients[j], max);
34216 index++;
34217 }
34218 }
34219 },
34220
34221 getComponents: function PDFImage_getComponents(buffer) {
34222 var bpc = this.bpc;
34223
34224 // This image doesn't require any extra work.
34225 if (bpc === 8) {
34226 return buffer;
34227 }
34228
34229 var width = this.width;
34230 var height = this.height;
34231 var numComps = this.numComps;
34232
34233 var length = width * height * numComps;
34234 var bufferPos = 0;
34235 var output = (bpc <= 8 ? new Uint8Array(length) :
34236 (bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length)));
34237 var rowComps = width * numComps;
34238
34239 var max = (1 << bpc) - 1;
34240 var i = 0, ii, buf;
34241
34242 if (bpc === 1) {
34243 // Optimization for reading 1 bpc images.
34244 var mask, loop1End, loop2End;
34245 for (var j = 0; j < height; j++) {
34246 loop1End = i + (rowComps & ~7);
34247 loop2End = i + rowComps;
34248
34249 // unroll loop for all full bytes
34250 while (i < loop1End) {
34251 buf = buffer[bufferPos++];
34252 output[i] = (buf >> 7) & 1;
34253 output[i + 1] = (buf >> 6) & 1;
34254 output[i + 2] = (buf >> 5) & 1;
34255 output[i + 3] = (buf >> 4) & 1;
34256 output[i + 4] = (buf >> 3) & 1;
34257 output[i + 5] = (buf >> 2) & 1;
34258 output[i + 6] = (buf >> 1) & 1;
34259 output[i + 7] = buf & 1;
34260 i += 8;
34261 }
34262
34263 // handle remaining bits
34264 if (i < loop2End) {
34265 buf = buffer[bufferPos++];
34266 mask = 128;
34267 while (i < loop2End) {
34268 output[i++] = +!!(buf & mask);
34269 mask >>= 1;
34270 }
34271 }
34272 }
34273 } else {
34274 // The general case that handles all other bpc values.
34275 var bits = 0;
34276 buf = 0;
34277 for (i = 0, ii = length; i < ii; ++i) {
34278 if (i % rowComps === 0) {
34279 buf = 0;
34280 bits = 0;
34281 }
34282
34283 while (bits < bpc) {
34284 buf = (buf << 8) | buffer[bufferPos++];
34285 bits += 8;
34286 }
34287
34288 var remainingBits = bits - bpc;
34289 var value = buf >> remainingBits;
34290 output[i] = (value < 0 ? 0 : (value > max ? max : value));
34291 buf = buf & ((1 << remainingBits) - 1);
34292 bits = remainingBits;
34293 }
34294 }
34295 return output;
34296 },
34297
34298 fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height,
34299 actualHeight, image) {
34300 var smask = this.smask;
34301 var mask = this.mask;
34302 var alphaBuf, sw, sh, i, ii, j;
34303
34304 if (smask) {
34305 sw = smask.width;
34306 sh = smask.height;
34307 alphaBuf = new Uint8Array(sw * sh);
34308 smask.fillGrayBuffer(alphaBuf);
34309 if (sw !== width || sh !== height) {
34310 alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh,
34311 width, height);
34312 }
34313 } else if (mask) {
34314 if (mask instanceof PDFImage) {
34315 sw = mask.width;
34316 sh = mask.height;
34317 alphaBuf = new Uint8Array(sw * sh);
34318 mask.numComps = 1;
34319 mask.fillGrayBuffer(alphaBuf);
34320
34321 // Need to invert values in rgbaBuf
34322 for (i = 0, ii = sw * sh; i < ii; ++i) {
34323 alphaBuf[i] = 255 - alphaBuf[i];
34324 }
34325
34326 if (sw !== width || sh !== height) {
34327 alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh,
34328 width, height);
34329 }
34330 } else if (isArray(mask)) {
34331 // Color key mask: if any of the components are outside the range
34332 // then they should be painted.
34333 alphaBuf = new Uint8Array(width * height);
34334 var numComps = this.numComps;
34335 for (i = 0, ii = width * height; i < ii; ++i) {
34336 var opacity = 0;
34337 var imageOffset = i * numComps;
34338 for (j = 0; j < numComps; ++j) {
34339 var color = image[imageOffset + j];
34340 var maskOffset = j * 2;
34341 if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {
34342 opacity = 255;
34343 break;
34344 }
34345 }
34346 alphaBuf[i] = opacity;
34347 }
34348 } else {
34349 error('Unknown mask format.');
34350 }
34351 }
34352
34353 if (alphaBuf) {
34354 for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
34355 rgbaBuf[j] = alphaBuf[i];
34356 }
34357 } else {
34358 // No mask.
34359 for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
34360 rgbaBuf[j] = 255;
34361 }
34362 }
34363 },
34364
34365 undoPreblend: function PDFImage_undoPreblend(buffer, width, height) {
34366 var matte = this.smask && this.smask.matte;
34367 if (!matte) {
34368 return;
34369 }
34370 var matteRgb = this.colorSpace.getRgb(matte, 0);
34371 var matteR = matteRgb[0];
34372 var matteG = matteRgb[1];
34373 var matteB = matteRgb[2];
34374 var length = width * height * 4;
34375 var r, g, b;
34376 for (var i = 0; i < length; i += 4) {
34377 var alpha = buffer[i + 3];
34378 if (alpha === 0) {
34379 // according formula we have to get Infinity in all components
34380 // making it white (typical paper color) should be okay
34381 buffer[i] = 255;
34382 buffer[i + 1] = 255;
34383 buffer[i + 2] = 255;
34384 continue;
34385 }
34386 var k = 255 / alpha;
34387 r = (buffer[i] - matteR) * k + matteR;
34388 g = (buffer[i + 1] - matteG) * k + matteG;
34389 b = (buffer[i + 2] - matteB) * k + matteB;
34390 buffer[i] = r <= 0 ? 0 : r >= 255 ? 255 : r | 0;
34391 buffer[i + 1] = g <= 0 ? 0 : g >= 255 ? 255 : g | 0;
34392 buffer[i + 2] = b <= 0 ? 0 : b >= 255 ? 255 : b | 0;
34393 }
34394 },
34395
34396 createImageData: function PDFImage_createImageData(forceRGBA) {
34397 var drawWidth = this.drawWidth;
34398 var drawHeight = this.drawHeight;
34399 var imgData = { // other fields are filled in below
34400 width: drawWidth,
34401 height: drawHeight
34402 };
34403
34404 var numComps = this.numComps;
34405 var originalWidth = this.width;
34406 var originalHeight = this.height;
34407 var bpc = this.bpc;
34408
34409 // Rows start at byte boundary.
34410 var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
34411 var imgArray;
34412
34413 if (!forceRGBA) {
34414 // If it is a 1-bit-per-pixel grayscale (i.e. black-and-white) image
34415 // without any complications, we pass a same-sized copy to the main
34416 // thread rather than expanding by 32x to RGBA form. This saves *lots*
34417 // of memory for many scanned documents. It's also much faster.
34418 //
34419 // Similarly, if it is a 24-bit-per pixel RGB image without any
34420 // complications, we avoid expanding by 1.333x to RGBA form.
34421 var kind;
34422 if (this.colorSpace.name === 'DeviceGray' && bpc === 1) {
34423 kind = ImageKind.GRAYSCALE_1BPP;
34424 } else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 &&
34425 !this.needsDecode) {
34426 kind = ImageKind.RGB_24BPP;
34427 }
34428 if (kind && !this.smask && !this.mask &&
34429 drawWidth === originalWidth && drawHeight === originalHeight) {
34430 imgData.kind = kind;
34431
34432 imgArray = this.getImageBytes(originalHeight * rowBytes);
34433 // If imgArray came from a DecodeStream, we're safe to transfer it
34434 // (and thus detach its underlying buffer) because it will constitute
34435 // the entire DecodeStream's data. But if it came from a Stream, we
34436 // need to copy it because it'll only be a portion of the Stream's
34437 // data, and the rest will be read later on.
34438 if (this.image instanceof DecodeStream) {
34439 imgData.data = imgArray;
34440 } else {
34441 var newArray = new Uint8Array(imgArray.length);
34442 newArray.set(imgArray);
34443 imgData.data = newArray;
34444 }
34445 if (this.needsDecode) {
34446 // Invert the buffer (which must be grayscale if we reached here).
34447 assert(kind === ImageKind.GRAYSCALE_1BPP);
34448 var buffer = imgData.data;
34449 for (var i = 0, ii = buffer.length; i < ii; i++) {
34450 buffer[i] ^= 0xff;
34451 }
34452 }
34453 return imgData;
34454 }
34455 if (this.image instanceof JpegStream && !this.smask && !this.mask &&
34456 (this.colorSpace.name === 'DeviceGray' ||
34457 this.colorSpace.name === 'DeviceRGB' ||
34458 this.colorSpace.name === 'DeviceCMYK')) {
34459 imgData.kind = ImageKind.RGB_24BPP;
34460 imgData.data = this.getImageBytes(originalHeight * rowBytes,
34461 drawWidth, drawHeight, true);
34462 return imgData;
34463 }
34464 }
34465
34466 imgArray = this.getImageBytes(originalHeight * rowBytes);
34467 // imgArray can be incomplete (e.g. after CCITT fax encoding).
34468 var actualHeight = 0 | (imgArray.length / rowBytes *
34469 drawHeight / originalHeight);
34470
34471 var comps = this.getComponents(imgArray);
34472
34473 // If opacity data is present, use RGBA_32BPP form. Otherwise, use the
34474 // more compact RGB_24BPP form if allowable.
34475 var alpha01, maybeUndoPreblend;
34476 if (!forceRGBA && !this.smask && !this.mask) {
34477 imgData.kind = ImageKind.RGB_24BPP;
34478 imgData.data = new Uint8Array(drawWidth * drawHeight * 3);
34479 alpha01 = 0;
34480 maybeUndoPreblend = false;
34481 } else {
34482 imgData.kind = ImageKind.RGBA_32BPP;
34483 imgData.data = new Uint8Array(drawWidth * drawHeight * 4);
34484 alpha01 = 1;
34485 maybeUndoPreblend = true;
34486
34487 // Color key masking (opacity) must be performed before decoding.
34488 this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight,
34489 comps);
34490 }
34491
34492 if (this.needsDecode) {
34493 this.decodeBuffer(comps);
34494 }
34495 this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight,
34496 drawWidth, drawHeight, actualHeight, bpc, comps,
34497 alpha01);
34498 if (maybeUndoPreblend) {
34499 this.undoPreblend(imgData.data, drawWidth, actualHeight);
34500 }
34501
34502 return imgData;
34503 },
34504
34505 fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) {
34506 var numComps = this.numComps;
34507 if (numComps !== 1) {
34508 error('Reading gray scale from a color image: ' + numComps);
34509 }
34510
34511 var width = this.width;
34512 var height = this.height;
34513 var bpc = this.bpc;
34514
34515 // rows start at byte boundary
34516 var rowBytes = (width * numComps * bpc + 7) >> 3;
34517 var imgArray = this.getImageBytes(height * rowBytes);
34518
34519 var comps = this.getComponents(imgArray);
34520 var i, length;
34521
34522 if (bpc === 1) {
34523 // inline decoding (= inversion) for 1 bpc images
34524 length = width * height;
34525 if (this.needsDecode) {
34526 // invert and scale to {0, 255}
34527 for (i = 0; i < length; ++i) {
34528 buffer[i] = (comps[i] - 1) & 255;
34529 }
34530 } else {
34531 // scale to {0, 255}
34532 for (i = 0; i < length; ++i) {
34533 buffer[i] = (-comps[i]) & 255;
34534 }
34535 }
34536 return;
34537 }
34538
34539 if (this.needsDecode) {
34540 this.decodeBuffer(comps);
34541 }
34542 length = width * height;
34543 // we aren't using a colorspace so we need to scale the value
34544 var scale = 255 / ((1 << bpc) - 1);
34545 for (i = 0; i < length; ++i) {
34546 buffer[i] = (scale * comps[i]) | 0;
34547 }
34548 },
34549
34550 getImageBytes: function PDFImage_getImageBytes(length,
34551 drawWidth, drawHeight,
34552 forceRGB) {
34553 this.image.reset();
34554 this.image.drawWidth = drawWidth || this.width;
34555 this.image.drawHeight = drawHeight || this.height;
34556 this.image.forceRGB = !!forceRGB;
34557 return this.image.getBytes(length);
34558 }
34559 };
34560 return PDFImage;
34561})();
34562
34563exports.PDFImage = PDFImage;
34564}));
34565
34566
34567(function (root, factory) {
34568 {
34569 factory((root.pdfjsCoreObj = {}), root.pdfjsSharedUtil,
34570 root.pdfjsCorePrimitives, root.pdfjsCoreCrypto, root.pdfjsCoreParser,
34571 root.pdfjsCoreChunkedStream, root.pdfjsCoreColorSpace);
34572 }
34573}(this, function (exports, sharedUtil, corePrimitives, coreCrypto, coreParser,
34574 coreChunkedStream, coreColorSpace) {
34575
34576var InvalidPDFException = sharedUtil.InvalidPDFException;
34577var MissingDataException = sharedUtil.MissingDataException;
34578var XRefParseException = sharedUtil.XRefParseException;
34579var assert = sharedUtil.assert;
34580var bytesToString = sharedUtil.bytesToString;
34581var createPromiseCapability = sharedUtil.createPromiseCapability;
34582var error = sharedUtil.error;
34583var info = sharedUtil.info;
34584var isArray = sharedUtil.isArray;
34585var isInt = sharedUtil.isInt;
34586var isString = sharedUtil.isString;
34587var shadow = sharedUtil.shadow;
34588var stringToPDFString = sharedUtil.stringToPDFString;
34589var stringToUTF8String = sharedUtil.stringToUTF8String;
34590var warn = sharedUtil.warn;
34591var isValidUrl = sharedUtil.isValidUrl;
34592var Util = sharedUtil.Util;
34593var Ref = corePrimitives.Ref;
34594var RefSet = corePrimitives.RefSet;
34595var RefSetCache = corePrimitives.RefSetCache;
34596var isName = corePrimitives.isName;
34597var isCmd = corePrimitives.isCmd;
34598var isDict = corePrimitives.isDict;
34599var isRef = corePrimitives.isRef;
34600var isRefsEqual = corePrimitives.isRefsEqual;
34601var isStream = corePrimitives.isStream;
34602var CipherTransformFactory = coreCrypto.CipherTransformFactory;
34603var Lexer = coreParser.Lexer;
34604var Parser = coreParser.Parser;
34605var ChunkedStream = coreChunkedStream.ChunkedStream;
34606var ColorSpace = coreColorSpace.ColorSpace;
34607
34608var Catalog = (function CatalogClosure() {
34609 function Catalog(pdfManager, xref, pageFactory) {
34610 this.pdfManager = pdfManager;
34611 this.xref = xref;
34612 this.catDict = xref.getCatalogObj();
34613 this.fontCache = new RefSetCache();
34614 assert(isDict(this.catDict),
34615 'catalog object is not a dictionary');
34616
34617 // TODO refactor to move getPage() to the PDFDocument.
34618 this.pageFactory = pageFactory;
34619 this.pagePromises = [];
34620 }
34621
34622 Catalog.prototype = {
34623 get metadata() {
34624 var streamRef = this.catDict.getRaw('Metadata');
34625 if (!isRef(streamRef)) {
34626 return shadow(this, 'metadata', null);
34627 }
34628
34629 var encryptMetadata = (!this.xref.encrypt ? false :
34630 this.xref.encrypt.encryptMetadata);
34631
34632 var stream = this.xref.fetch(streamRef, !encryptMetadata);
34633 var metadata;
34634 if (stream && isDict(stream.dict)) {
34635 var type = stream.dict.get('Type');
34636 var subtype = stream.dict.get('Subtype');
34637
34638 if (isName(type, 'Metadata') && isName(subtype, 'XML')) {
34639 // XXX: This should examine the charset the XML document defines,
34640 // however since there are currently no real means to decode
34641 // arbitrary charsets, let's just hope that the author of the PDF
34642 // was reasonable enough to stick with the XML default charset,
34643 // which is UTF-8.
34644 try {
34645 metadata = stringToUTF8String(bytesToString(stream.getBytes()));
34646 } catch (e) {
34647 info('Skipping invalid metadata.');
34648 }
34649 }
34650 }
34651
34652 return shadow(this, 'metadata', metadata);
34653 },
34654 get toplevelPagesDict() {
34655 var pagesObj = this.catDict.get('Pages');
34656 assert(isDict(pagesObj), 'invalid top-level pages dictionary');
34657 // shadow the prototype getter
34658 return shadow(this, 'toplevelPagesDict', pagesObj);
34659 },
34660 get documentOutline() {
34661 var obj = null;
34662 try {
34663 obj = this.readDocumentOutline();
34664 } catch (ex) {
34665 if (ex instanceof MissingDataException) {
34666 throw ex;
34667 }
34668 warn('Unable to read document outline');
34669 }
34670 return shadow(this, 'documentOutline', obj);
34671 },
34672 readDocumentOutline: function Catalog_readDocumentOutline() {
34673 var obj = this.catDict.get('Outlines');
34674 if (!isDict(obj)) {
34675 return null;
34676 }
34677 obj = obj.getRaw('First');
34678 if (!isRef(obj)) {
34679 return null;
34680 }
34681 var root = { items: [] };
34682 var queue = [{obj: obj, parent: root}];
34683 // To avoid recursion, keep track of the already processed items.
34684 var processed = new RefSet();
34685 processed.put(obj);
34686 var xref = this.xref, blackColor = new Uint8Array(3);
34687
34688 while (queue.length > 0) {
34689 var i = queue.shift();
34690 var outlineDict = xref.fetchIfRef(i.obj);
34691 if (outlineDict === null) {
34692 continue;
34693 }
34694 assert(outlineDict.has('Title'), 'Invalid outline item');
34695
34696 var actionDict = outlineDict.get('A'), dest = null, url = null;
34697 if (actionDict) {
34698 var destEntry = actionDict.get('D');
34699 if (destEntry) {
34700 dest = destEntry;
34701 } else {
34702 var uriEntry = actionDict.get('URI');
34703 if (isString(uriEntry) && isValidUrl(uriEntry, false)) {
34704 url = uriEntry;
34705 }
34706 }
34707 } else if (outlineDict.has('Dest')) {
34708 dest = outlineDict.getRaw('Dest');
34709 if (isName(dest)) {
34710 dest = dest.name;
34711 }
34712 }
34713 var title = outlineDict.get('Title');
34714 var flags = outlineDict.get('F') || 0;
34715
34716 var color = outlineDict.getArray('C'), rgbColor = blackColor;
34717 // We only need to parse the color when it's valid, and non-default.
34718 if (isArray(color) && color.length === 3 &&
34719 (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) {
34720 rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
34721 }
34722 var outlineItem = {
34723 dest: dest,
34724 url: url,
34725 title: stringToPDFString(title),
34726 color: rgbColor,
34727 count: outlineDict.get('Count'),
34728 bold: !!(flags & 2),
34729 italic: !!(flags & 1),
34730 items: []
34731 };
34732 i.parent.items.push(outlineItem);
34733 obj = outlineDict.getRaw('First');
34734 if (isRef(obj) && !processed.has(obj)) {
34735 queue.push({obj: obj, parent: outlineItem});
34736 processed.put(obj);
34737 }
34738 obj = outlineDict.getRaw('Next');
34739 if (isRef(obj) && !processed.has(obj)) {
34740 queue.push({obj: obj, parent: i.parent});
34741 processed.put(obj);
34742 }
34743 }
34744 return (root.items.length > 0 ? root.items : null);
34745 },
34746 get numPages() {
34747 var obj = this.toplevelPagesDict.get('Count');
34748 assert(
34749 isInt(obj),
34750 'page count in top level pages object is not an integer'
34751 );
34752 // shadow the prototype getter
34753 return shadow(this, 'num', obj);
34754 },
34755 get destinations() {
34756 function fetchDestination(dest) {
34757 return isDict(dest) ? dest.get('D') : dest;
34758 }
34759
34760 var xref = this.xref;
34761 var dests = {}, nameTreeRef, nameDictionaryRef;
34762 var obj = this.catDict.get('Names');
34763 if (obj && obj.has('Dests')) {
34764 nameTreeRef = obj.getRaw('Dests');
34765 } else if (this.catDict.has('Dests')) {
34766 nameDictionaryRef = this.catDict.get('Dests');
34767 }
34768
34769 if (nameDictionaryRef) {
34770 // reading simple destination dictionary
34771 obj = nameDictionaryRef;
34772 obj.forEach(function catalogForEach(key, value) {
34773 if (!value) {
34774 return;
34775 }
34776 dests[key] = fetchDestination(value);
34777 });
34778 }
34779 if (nameTreeRef) {
34780 var nameTree = new NameTree(nameTreeRef, xref);
34781 var names = nameTree.getAll();
34782 for (var name in names) {
34783 dests[name] = fetchDestination(names[name]);
34784 }
34785 }
34786 return shadow(this, 'destinations', dests);
34787 },
34788 getDestination: function Catalog_getDestination(destinationId) {
34789 function fetchDestination(dest) {
34790 return isDict(dest) ? dest.get('D') : dest;
34791 }
34792
34793 var xref = this.xref;
34794 var dest = null, nameTreeRef, nameDictionaryRef;
34795 var obj = this.catDict.get('Names');
34796 if (obj && obj.has('Dests')) {
34797 nameTreeRef = obj.getRaw('Dests');
34798 } else if (this.catDict.has('Dests')) {
34799 nameDictionaryRef = this.catDict.get('Dests');
34800 }
34801
34802 if (nameDictionaryRef) { // Simple destination dictionary.
34803 var value = nameDictionaryRef.get(destinationId);
34804 if (value) {
34805 dest = fetchDestination(value);
34806 }
34807 }
34808 if (nameTreeRef) {
34809 var nameTree = new NameTree(nameTreeRef, xref);
34810 dest = fetchDestination(nameTree.get(destinationId));
34811 }
34812 return dest;
34813 },
34814
34815 get pageLabels() {
34816 var obj = null;
34817 try {
34818 obj = this.readPageLabels();
34819 } catch (ex) {
34820 if (ex instanceof MissingDataException) {
34821 throw ex;
34822 }
34823 warn('Unable to read page labels.');
34824 }
34825 return shadow(this, 'pageLabels', obj);
34826 },
34827 readPageLabels: function Catalog_readPageLabels() {
34828 var obj = this.catDict.getRaw('PageLabels');
34829 if (!obj) {
34830 return null;
34831 }
34832 var pageLabels = new Array(this.numPages);
34833 var style = null;
34834 var prefix = '';
34835 var start = 1;
34836
34837 var numberTree = new NumberTree(obj, this.xref);
34838 var nums = numberTree.getAll();
34839 var currentLabel = '', currentIndex = 1;
34840
34841 for (var i = 0, ii = this.numPages; i < ii; i++) {
34842 if (i in nums) {
34843 var labelDict = nums[i];
34844 assert(isDict(labelDict), 'The PageLabel is not a dictionary.');
34845
34846 var type = labelDict.get('Type');
34847 assert(!type || isName(type, 'PageLabel'),
34848 'Invalid type in PageLabel dictionary.');
34849
34850 var s = labelDict.get('S');
34851 assert(!s || isName(s), 'Invalid style in PageLabel dictionary.');
34852 style = (s ? s.name : null);
34853
34854 prefix = labelDict.get('P') || '';
34855 assert(isString(prefix), 'Invalid prefix in PageLabel dictionary.');
34856
34857 start = labelDict.get('St') || 1;
34858 assert(isInt(start), 'Invalid start in PageLabel dictionary.');
34859 currentIndex = start;
34860 }
34861
34862 switch (style) {
34863 case 'D':
34864 currentLabel = currentIndex;
34865 break;
34866 case 'R':
34867 case 'r':
34868 currentLabel = Util.toRoman(currentIndex, style === 'r');
34869 break;
34870 case 'A':
34871 case 'a':
34872 var LIMIT = 26; // Use only the characters A--Z, or a--z.
34873 var A_UPPER_CASE = 0x41, A_LOWER_CASE = 0x61;
34874
34875 var baseCharCode = (style === 'a' ? A_LOWER_CASE : A_UPPER_CASE);
34876 var letterIndex = currentIndex - 1;
34877 var character = String.fromCharCode(baseCharCode +
34878 (letterIndex % LIMIT));
34879 var charBuf = [];
34880 for (var j = 0, jj = (letterIndex / LIMIT) | 0; j <= jj; j++) {
34881 charBuf.push(character);
34882 }
34883 currentLabel = charBuf.join('');
34884 break;
34885 default:
34886 assert(!style,
34887 'Invalid style "' + style + '" in PageLabel dictionary.');
34888 }
34889 pageLabels[i] = prefix + currentLabel;
34890
34891 currentLabel = '';
34892 currentIndex++;
34893 }
34894 return pageLabels;
34895 },
34896
34897 get attachments() {
34898 var xref = this.xref;
34899 var attachments = null, nameTreeRef;
34900 var obj = this.catDict.get('Names');
34901 if (obj) {
34902 nameTreeRef = obj.getRaw('EmbeddedFiles');
34903 }
34904
34905 if (nameTreeRef) {
34906 var nameTree = new NameTree(nameTreeRef, xref);
34907 var names = nameTree.getAll();
34908 for (var name in names) {
34909 var fs = new FileSpec(names[name], xref);
34910 if (!attachments) {
34911 attachments = Object.create(null);
34912 }
34913 attachments[stringToPDFString(name)] = fs.serializable;
34914 }
34915 }
34916 return shadow(this, 'attachments', attachments);
34917 },
34918 get javaScript() {
34919 var xref = this.xref;
34920 var obj = this.catDict.get('Names');
34921
34922 var javaScript = [];
34923 function appendIfJavaScriptDict(jsDict) {
34924 var type = jsDict.get('S');
34925 if (!isName(type, 'JavaScript')) {
34926 return;
34927 }
34928 var js = jsDict.get('JS');
34929 if (isStream(js)) {
34930 js = bytesToString(js.getBytes());
34931 } else if (!isString(js)) {
34932 return;
34933 }
34934 javaScript.push(stringToPDFString(js));
34935 }
34936 if (obj && obj.has('JavaScript')) {
34937 var nameTree = new NameTree(obj.getRaw('JavaScript'), xref);
34938 var names = nameTree.getAll();
34939 for (var name in names) {
34940 // We don't really use the JavaScript right now. This code is
34941 // defensive so we don't cause errors on document load.
34942 var jsDict = names[name];
34943 if (isDict(jsDict)) {
34944 appendIfJavaScriptDict(jsDict);
34945 }
34946 }
34947 }
34948
34949 // Append OpenAction actions to javaScript array
34950 var openactionDict = this.catDict.get('OpenAction');
34951 if (isDict(openactionDict, 'Action')) {
34952 var actionType = openactionDict.get('S');
34953 if (isName(actionType, 'Named')) {
34954 // The named Print action is not a part of the PDF 1.7 specification,
34955 // but is supported by many PDF readers/writers (including Adobe's).
34956 var action = openactionDict.get('N');
34957 if (isName(action, 'Print')) {
34958 javaScript.push('print({});');
34959 }
34960 } else {
34961 appendIfJavaScriptDict(openactionDict);
34962 }
34963 }
34964
34965 return shadow(this, 'javaScript', javaScript);
34966 },
34967
34968 cleanup: function Catalog_cleanup() {
34969 var promises = [];
34970 this.fontCache.forEach(function (promise) {
34971 promises.push(promise);
34972 });
34973 return Promise.all(promises).then(function (translatedFonts) {
34974 for (var i = 0, ii = translatedFonts.length; i < ii; i++) {
34975 var font = translatedFonts[i].dict;
34976 delete font.translated;
34977 }
34978 this.fontCache.clear();
34979 }.bind(this));
34980 },
34981
34982 getPage: function Catalog_getPage(pageIndex) {
34983 if (!(pageIndex in this.pagePromises)) {
34984 this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then(
34985 function (a) {
34986 var dict = a[0];
34987 var ref = a[1];
34988 return this.pageFactory.createPage(pageIndex, dict, ref,
34989 this.fontCache);
34990 }.bind(this)
34991 );
34992 }
34993 return this.pagePromises[pageIndex];
34994 },
34995
34996 getPageDict: function Catalog_getPageDict(pageIndex) {
34997 var capability = createPromiseCapability();
34998 var nodesToVisit = [this.catDict.getRaw('Pages')];
34999 var currentPageIndex = 0;
35000 var xref = this.xref;
35001 var checkAllKids = false;
35002
35003 function next() {
35004 while (nodesToVisit.length) {
35005 var currentNode = nodesToVisit.pop();
35006
35007 if (isRef(currentNode)) {
35008 xref.fetchAsync(currentNode).then(function (obj) {
35009 if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) {
35010 if (pageIndex === currentPageIndex) {
35011 capability.resolve([obj, currentNode]);
35012 } else {
35013 currentPageIndex++;
35014 next();
35015 }
35016 return;
35017 }
35018 nodesToVisit.push(obj);
35019 next();
35020 }, capability.reject);
35021 return;
35022 }
35023
35024 // Must be a child page dictionary.
35025 assert(
35026 isDict(currentNode),
35027 'page dictionary kid reference points to wrong type of object'
35028 );
35029 var count = currentNode.get('Count');
35030 // If the current node doesn't have any children, avoid getting stuck
35031 // in an empty node further down in the tree (see issue5644.pdf).
35032 if (count === 0) {
35033 checkAllKids = true;
35034 }
35035 // Skip nodes where the page can't be.
35036 if (currentPageIndex + count <= pageIndex) {
35037 currentPageIndex += count;
35038 continue;
35039 }
35040
35041 var kids = currentNode.get('Kids');
35042 assert(isArray(kids), 'page dictionary kids object is not an array');
35043 if (!checkAllKids && count === kids.length) {
35044 // Nodes that don't have the page have been skipped and this is the
35045 // bottom of the tree which means the page requested must be a
35046 // descendant of this pages node. Ideally we would just resolve the
35047 // promise with the page ref here, but there is the case where more
35048 // pages nodes could link to single a page (see issue 3666 pdf). To
35049 // handle this push it back on the queue so if it is a pages node it
35050 // will be descended into.
35051 nodesToVisit = [kids[pageIndex - currentPageIndex]];
35052 currentPageIndex = pageIndex;
35053 continue;
35054 } else {
35055 for (var last = kids.length - 1; last >= 0; last--) {
35056 nodesToVisit.push(kids[last]);
35057 }
35058 }
35059 }
35060 capability.reject('Page index ' + pageIndex + ' not found.');
35061 }
35062 next();
35063 return capability.promise;
35064 },
35065
35066 getPageIndex: function Catalog_getPageIndex(pageRef) {
35067 // The page tree nodes have the count of all the leaves below them. To get
35068 // how many pages are before we just have to walk up the tree and keep
35069 // adding the count of siblings to the left of the node.
35070 var xref = this.xref;
35071 function pagesBeforeRef(kidRef) {
35072 var total = 0;
35073 var parentRef;
35074 return xref.fetchAsync(kidRef).then(function (node) {
35075 if (isRefsEqual(kidRef, pageRef) && !isDict(node, 'Page') &&
35076 !(isDict(node) && !node.has('Type') && node.has('Contents'))) {
35077 throw new Error('The reference does not point to a /Page Dict.');
35078 }
35079 if (!node) {
35080 return null;
35081 }
35082 assert(isDict(node), 'node must be a Dict.');
35083 parentRef = node.getRaw('Parent');
35084 return node.getAsync('Parent');
35085 }).then(function (parent) {
35086 if (!parent) {
35087 return null;
35088 }
35089 assert(isDict(parent), 'parent must be a Dict.');
35090 return parent.getAsync('Kids');
35091 }).then(function (kids) {
35092 if (!kids) {
35093 return null;
35094 }
35095 var kidPromises = [];
35096 var found = false;
35097 for (var i = 0; i < kids.length; i++) {
35098 var kid = kids[i];
35099 assert(isRef(kid), 'kid must be a Ref.');
35100 if (kid.num === kidRef.num) {
35101 found = true;
35102 break;
35103 }
35104 kidPromises.push(xref.fetchAsync(kid).then(function (kid) {
35105 if (kid.has('Count')) {
35106 var count = kid.get('Count');
35107 total += count;
35108 } else { // page leaf node
35109 total++;
35110 }
35111 }));
35112 }
35113 if (!found) {
35114 error('kid ref not found in parents kids');
35115 }
35116 return Promise.all(kidPromises).then(function () {
35117 return [total, parentRef];
35118 });
35119 });
35120 }
35121
35122 var total = 0;
35123 function next(ref) {
35124 return pagesBeforeRef(ref).then(function (args) {
35125 if (!args) {
35126 return total;
35127 }
35128 var count = args[0];
35129 var parentRef = args[1];
35130 total += count;
35131 return next(parentRef);
35132 });
35133 }
35134
35135 return next(pageRef);
35136 }
35137 };
35138
35139 return Catalog;
35140})();
35141
35142var XRef = (function XRefClosure() {
35143 function XRef(stream, password) {
35144 this.stream = stream;
35145 this.entries = [];
35146 this.xrefstms = Object.create(null);
35147 // prepare the XRef cache
35148 this.cache = [];
35149 this.password = password;
35150 this.stats = {
35151 streamTypes: [],
35152 fontTypes: []
35153 };
35154 }
35155
35156 XRef.prototype = {
35157 setStartXRef: function XRef_setStartXRef(startXRef) {
35158 // Store the starting positions of xref tables as we process them
35159 // so we can recover from missing data errors
35160 this.startXRefQueue = [startXRef];
35161 },
35162
35163 parse: function XRef_parse(recoveryMode) {
35164 var trailerDict;
35165 if (!recoveryMode) {
35166 trailerDict = this.readXRef();
35167 } else {
35168 warn('Indexing all PDF objects');
35169 trailerDict = this.indexObjects();
35170 }
35171 trailerDict.assignXref(this);
35172 this.trailer = trailerDict;
35173 var encrypt = trailerDict.get('Encrypt');
35174 if (encrypt) {
35175 var ids = trailerDict.get('ID');
35176 var fileId = (ids && ids.length) ? ids[0] : '';
35177 this.encrypt = new CipherTransformFactory(encrypt, fileId,
35178 this.password);
35179 }
35180
35181 // get the root dictionary (catalog) object
35182 if (!(this.root = trailerDict.get('Root'))) {
35183 error('Invalid root reference');
35184 }
35185 },
35186
35187 processXRefTable: function XRef_processXRefTable(parser) {
35188 if (!('tableState' in this)) {
35189 // Stores state of the table as we process it so we can resume
35190 // from middle of table in case of missing data error
35191 this.tableState = {
35192 entryNum: 0,
35193 streamPos: parser.lexer.stream.pos,
35194 parserBuf1: parser.buf1,
35195 parserBuf2: parser.buf2
35196 };
35197 }
35198
35199 var obj = this.readXRefTable(parser);
35200
35201 // Sanity check
35202 if (!isCmd(obj, 'trailer')) {
35203 error('Invalid XRef table: could not find trailer dictionary');
35204 }
35205 // Read trailer dictionary, e.g.
35206 // trailer
35207 // << /Size 22
35208 // /Root 20R
35209 // /Info 10R
35210 // /ID [ <81b14aafa313db63dbd6f981e49f94f4> ]
35211 // >>
35212 // The parser goes through the entire stream << ... >> and provides
35213 // a getter interface for the key-value table
35214 var dict = parser.getObj();
35215
35216 // The pdflib PDF generator can generate a nested trailer dictionary
35217 if (!isDict(dict) && dict.dict) {
35218 dict = dict.dict;
35219 }
35220 if (!isDict(dict)) {
35221 error('Invalid XRef table: could not parse trailer dictionary');
35222 }
35223 delete this.tableState;
35224
35225 return dict;
35226 },
35227
35228 readXRefTable: function XRef_readXRefTable(parser) {
35229 // Example of cross-reference table:
35230 // xref
35231 // 0 1 <-- subsection header (first obj #, obj count)
35232 // 0000000000 65535 f <-- actual object (offset, generation #, f/n)
35233 // 23 2 <-- subsection header ... and so on ...
35234 // 0000025518 00002 n
35235 // 0000025635 00000 n
35236 // trailer
35237 // ...
35238
35239 var stream = parser.lexer.stream;
35240 var tableState = this.tableState;
35241 stream.pos = tableState.streamPos;
35242 parser.buf1 = tableState.parserBuf1;
35243 parser.buf2 = tableState.parserBuf2;
35244
35245 // Outer loop is over subsection headers
35246 var obj;
35247
35248 while (true) {
35249 if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) {
35250 if (isCmd(obj = parser.getObj(), 'trailer')) {
35251 break;
35252 }
35253 tableState.firstEntryNum = obj;
35254 tableState.entryCount = parser.getObj();
35255 }
35256
35257 var first = tableState.firstEntryNum;
35258 var count = tableState.entryCount;
35259 if (!isInt(first) || !isInt(count)) {
35260 error('Invalid XRef table: wrong types in subsection header');
35261 }
35262 // Inner loop is over objects themselves
35263 for (var i = tableState.entryNum; i < count; i++) {
35264 tableState.streamPos = stream.pos;
35265 tableState.entryNum = i;
35266 tableState.parserBuf1 = parser.buf1;
35267 tableState.parserBuf2 = parser.buf2;
35268
35269 var entry = {};
35270 entry.offset = parser.getObj();
35271 entry.gen = parser.getObj();
35272 var type = parser.getObj();
35273
35274 if (isCmd(type, 'f')) {
35275 entry.free = true;
35276 } else if (isCmd(type, 'n')) {
35277 entry.uncompressed = true;
35278 }
35279
35280 // Validate entry obj
35281 if (!isInt(entry.offset) || !isInt(entry.gen) ||
35282 !(entry.free || entry.uncompressed)) {
35283 error('Invalid entry in XRef subsection: ' + first + ', ' + count);
35284 }
35285
35286 // The first xref table entry, i.e. obj 0, should be free. Attempting
35287 // to adjust an incorrect first obj # (fixes issue 3248 and 7229).
35288 if (i === 0 && entry.free && first === 1) {
35289 first = 0;
35290 }
35291
35292 if (!this.entries[i + first]) {
35293 this.entries[i + first] = entry;
35294 }
35295 }
35296
35297 tableState.entryNum = 0;
35298 tableState.streamPos = stream.pos;
35299 tableState.parserBuf1 = parser.buf1;
35300 tableState.parserBuf2 = parser.buf2;
35301 delete tableState.firstEntryNum;
35302 delete tableState.entryCount;
35303 }
35304
35305 // Sanity check: as per spec, first object must be free
35306 if (this.entries[0] && !this.entries[0].free) {
35307 error('Invalid XRef table: unexpected first object');
35308 }
35309 return obj;
35310 },
35311
35312 processXRefStream: function XRef_processXRefStream(stream) {
35313 if (!('streamState' in this)) {
35314 // Stores state of the stream as we process it so we can resume
35315 // from middle of stream in case of missing data error
35316 var streamParameters = stream.dict;
35317 var byteWidths = streamParameters.get('W');
35318 var range = streamParameters.get('Index');
35319 if (!range) {
35320 range = [0, streamParameters.get('Size')];
35321 }
35322
35323 this.streamState = {
35324 entryRanges: range,
35325 byteWidths: byteWidths,
35326 entryNum: 0,
35327 streamPos: stream.pos
35328 };
35329 }
35330 this.readXRefStream(stream);
35331 delete this.streamState;
35332
35333 return stream.dict;
35334 },
35335
35336 readXRefStream: function XRef_readXRefStream(stream) {
35337 var i, j;
35338 var streamState = this.streamState;
35339 stream.pos = streamState.streamPos;
35340
35341 var byteWidths = streamState.byteWidths;
35342 var typeFieldWidth = byteWidths[0];
35343 var offsetFieldWidth = byteWidths[1];
35344 var generationFieldWidth = byteWidths[2];
35345
35346 var entryRanges = streamState.entryRanges;
35347 while (entryRanges.length > 0) {
35348 var first = entryRanges[0];
35349 var n = entryRanges[1];
35350
35351 if (!isInt(first) || !isInt(n)) {
35352 error('Invalid XRef range fields: ' + first + ', ' + n);
35353 }
35354 if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) ||
35355 !isInt(generationFieldWidth)) {
35356 error('Invalid XRef entry fields length: ' + first + ', ' + n);
35357 }
35358 for (i = streamState.entryNum; i < n; ++i) {
35359 streamState.entryNum = i;
35360 streamState.streamPos = stream.pos;
35361
35362 var type = 0, offset = 0, generation = 0;
35363 for (j = 0; j < typeFieldWidth; ++j) {
35364 type = (type << 8) | stream.getByte();
35365 }
35366 // if type field is absent, its default value is 1
35367 if (typeFieldWidth === 0) {
35368 type = 1;
35369 }
35370 for (j = 0; j < offsetFieldWidth; ++j) {
35371 offset = (offset << 8) | stream.getByte();
35372 }
35373 for (j = 0; j < generationFieldWidth; ++j) {
35374 generation = (generation << 8) | stream.getByte();
35375 }
35376 var entry = {};
35377 entry.offset = offset;
35378 entry.gen = generation;
35379 switch (type) {
35380 case 0:
35381 entry.free = true;
35382 break;
35383 case 1:
35384 entry.uncompressed = true;
35385 break;
35386 case 2:
35387 break;
35388 default:
35389 error('Invalid XRef entry type: ' + type);
35390 }
35391 if (!this.entries[first + i]) {
35392 this.entries[first + i] = entry;
35393 }
35394 }
35395
35396 streamState.entryNum = 0;
35397 streamState.streamPos = stream.pos;
35398 entryRanges.splice(0, 2);
35399 }
35400 },
35401
35402 indexObjects: function XRef_indexObjects() {
35403 // Simple scan through the PDF content to find objects,
35404 // trailers and XRef streams.
35405 var TAB = 0x9, LF = 0xA, CR = 0xD, SPACE = 0x20;
35406 var PERCENT = 0x25, LT = 0x3C;
35407
35408 function readToken(data, offset) {
35409 var token = '', ch = data[offset];
35410 while (ch !== LF && ch !== CR && ch !== LT) {
35411 if (++offset >= data.length) {
35412 break;
35413 }
35414 token += String.fromCharCode(ch);
35415 ch = data[offset];
35416 }
35417 return token;
35418 }
35419 function skipUntil(data, offset, what) {
35420 var length = what.length, dataLength = data.length;
35421 var skipped = 0;
35422 // finding byte sequence
35423 while (offset < dataLength) {
35424 var i = 0;
35425 while (i < length && data[offset + i] === what[i]) {
35426 ++i;
35427 }
35428 if (i >= length) {
35429 break; // sequence found
35430 }
35431 offset++;
35432 skipped++;
35433 }
35434 return skipped;
35435 }
35436 var objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
35437 var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
35438 var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114,
35439 101, 102]);
35440 var endobjBytes = new Uint8Array([101, 110, 100, 111, 98, 106]);
35441 var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
35442
35443 // Clear out any existing entries, since they may be bogus.
35444 this.entries.length = 0;
35445
35446 var stream = this.stream;
35447 stream.pos = 0;
35448 var buffer = stream.getBytes();
35449 var position = stream.start, length = buffer.length;
35450 var trailers = [], xrefStms = [];
35451 while (position < length) {
35452 var ch = buffer[position];
35453 if (ch === TAB || ch === LF || ch === CR || ch === SPACE) {
35454 ++position;
35455 continue;
35456 }
35457 if (ch === PERCENT) { // %-comment
35458 do {
35459 ++position;
35460 if (position >= length) {
35461 break;
35462 }
35463 ch = buffer[position];
35464 } while (ch !== LF && ch !== CR);
35465 continue;
35466 }
35467 var token = readToken(buffer, position);
35468 var m;
35469 if (token.indexOf('xref') === 0 &&
35470 (token.length === 4 || /\s/.test(token[4]))) {
35471 position += skipUntil(buffer, position, trailerBytes);
35472 trailers.push(position);
35473 position += skipUntil(buffer, position, startxrefBytes);
35474 } else if ((m = objRegExp.exec(token))) {
35475 if (typeof this.entries[m[1]] === 'undefined') {
35476 this.entries[m[1]] = {
35477 offset: position - stream.start,
35478 gen: m[2] | 0,
35479 uncompressed: true
35480 };
35481 }
35482 var contentLength = skipUntil(buffer, position, endobjBytes) + 7;
35483 var content = buffer.subarray(position, position + contentLength);
35484
35485 // checking XRef stream suspect
35486 // (it shall have '/XRef' and next char is not a letter)
35487 var xrefTagOffset = skipUntil(content, 0, xrefBytes);
35488 if (xrefTagOffset < contentLength &&
35489 content[xrefTagOffset + 5] < 64) {
35490 xrefStms.push(position - stream.start);
35491 this.xrefstms[position - stream.start] = 1; // Avoid recursion
35492 }
35493
35494 position += contentLength;
35495 } else if (token.indexOf('trailer') === 0 &&
35496 (token.length === 7 || /\s/.test(token[7]))) {
35497 trailers.push(position);
35498 position += skipUntil(buffer, position, startxrefBytes);
35499 } else {
35500 position += token.length + 1;
35501 }
35502 }
35503 // reading XRef streams
35504 var i, ii;
35505 for (i = 0, ii = xrefStms.length; i < ii; ++i) {
35506 this.startXRefQueue.push(xrefStms[i]);
35507 this.readXRef(/* recoveryMode */ true);
35508 }
35509 // finding main trailer
35510 var dict;
35511 for (i = 0, ii = trailers.length; i < ii; ++i) {
35512 stream.pos = trailers[i];
35513 var parser = new Parser(new Lexer(stream), /* allowStreams = */ true,
35514 /* xref = */ this, /* recoveryMode = */ true);
35515 var obj = parser.getObj();
35516 if (!isCmd(obj, 'trailer')) {
35517 continue;
35518 }
35519 // read the trailer dictionary
35520 dict = parser.getObj();
35521 if (!isDict(dict)) {
35522 continue;
35523 }
35524 // taking the first one with 'ID'
35525 if (dict.has('ID')) {
35526 return dict;
35527 }
35528 }
35529 // no tailer with 'ID', taking last one (if exists)
35530 if (dict) {
35531 return dict;
35532 }
35533 // nothing helps
35534 // calling error() would reject worker with an UnknownErrorException.
35535 throw new InvalidPDFException('Invalid PDF structure');
35536 },
35537
35538 readXRef: function XRef_readXRef(recoveryMode) {
35539 var stream = this.stream;
35540
35541 try {
35542 while (this.startXRefQueue.length) {
35543 var startXRef = this.startXRefQueue[0];
35544
35545 stream.pos = startXRef + stream.start;
35546
35547 var parser = new Parser(new Lexer(stream), true, this);
35548 var obj = parser.getObj();
35549 var dict;
35550
35551 // Get dictionary
35552 if (isCmd(obj, 'xref')) {
35553 // Parse end-of-file XRef
35554 dict = this.processXRefTable(parser);
35555 if (!this.topDict) {
35556 this.topDict = dict;
35557 }
35558
35559 // Recursively get other XRefs 'XRefStm', if any
35560 obj = dict.get('XRefStm');
35561 if (isInt(obj)) {
35562 var pos = obj;
35563 // ignore previously loaded xref streams
35564 // (possible infinite recursion)
35565 if (!(pos in this.xrefstms)) {
35566 this.xrefstms[pos] = 1;
35567 this.startXRefQueue.push(pos);
35568 }
35569 }
35570 } else if (isInt(obj)) {
35571 // Parse in-stream XRef
35572 if (!isInt(parser.getObj()) ||
35573 !isCmd(parser.getObj(), 'obj') ||
35574 !isStream(obj = parser.getObj())) {
35575 error('Invalid XRef stream');
35576 }
35577 dict = this.processXRefStream(obj);
35578 if (!this.topDict) {
35579 this.topDict = dict;
35580 }
35581 if (!dict) {
35582 error('Failed to read XRef stream');
35583 }
35584 } else {
35585 error('Invalid XRef stream header');
35586 }
35587
35588 // Recursively get previous dictionary, if any
35589 obj = dict.get('Prev');
35590 if (isInt(obj)) {
35591 this.startXRefQueue.push(obj);
35592 } else if (isRef(obj)) {
35593 // The spec says Prev must not be a reference, i.e. "/Prev NNN"
35594 // This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R"
35595 this.startXRefQueue.push(obj.num);
35596 }
35597
35598 this.startXRefQueue.shift();
35599 }
35600
35601 return this.topDict;
35602 } catch (e) {
35603 if (e instanceof MissingDataException) {
35604 throw e;
35605 }
35606 info('(while reading XRef): ' + e);
35607 }
35608
35609 if (recoveryMode) {
35610 return;
35611 }
35612 throw new XRefParseException();
35613 },
35614
35615 getEntry: function XRef_getEntry(i) {
35616 var xrefEntry = this.entries[i];
35617 if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {
35618 return xrefEntry;
35619 }
35620 return null;
35621 },
35622
35623 fetchIfRef: function XRef_fetchIfRef(obj) {
35624 if (!isRef(obj)) {
35625 return obj;
35626 }
35627 return this.fetch(obj);
35628 },
35629
35630 fetch: function XRef_fetch(ref, suppressEncryption) {
35631 assert(isRef(ref), 'ref object is not a reference');
35632 var num = ref.num;
35633 if (num in this.cache) {
35634 var cacheEntry = this.cache[num];
35635 return cacheEntry;
35636 }
35637
35638 var xrefEntry = this.getEntry(num);
35639
35640 // the referenced entry can be free
35641 if (xrefEntry === null) {
35642 return (this.cache[num] = null);
35643 }
35644
35645 if (xrefEntry.uncompressed) {
35646 xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption);
35647 } else {
35648 xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption);
35649 }
35650 if (isDict(xrefEntry)){
35651 xrefEntry.objId = ref.toString();
35652 } else if (isStream(xrefEntry)) {
35653 xrefEntry.dict.objId = ref.toString();
35654 }
35655 return xrefEntry;
35656 },
35657
35658 fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry,
35659 suppressEncryption) {
35660 var gen = ref.gen;
35661 var num = ref.num;
35662 if (xrefEntry.gen !== gen) {
35663 error('inconsistent generation in XRef');
35664 }
35665 var stream = this.stream.makeSubStream(xrefEntry.offset +
35666 this.stream.start);
35667 var parser = new Parser(new Lexer(stream), true, this);
35668 var obj1 = parser.getObj();
35669 var obj2 = parser.getObj();
35670 var obj3 = parser.getObj();
35671 if (!isInt(obj1) || parseInt(obj1, 10) !== num ||
35672 !isInt(obj2) || parseInt(obj2, 10) !== gen ||
35673 !isCmd(obj3)) {
35674 error('bad XRef entry');
35675 }
35676 if (!isCmd(obj3, 'obj')) {
35677 // some bad PDFs use "obj1234" and really mean 1234
35678 if (obj3.cmd.indexOf('obj') === 0) {
35679 num = parseInt(obj3.cmd.substring(3), 10);
35680 if (!isNaN(num)) {
35681 return num;
35682 }
35683 }
35684 error('bad XRef entry');
35685 }
35686 if (this.encrypt && !suppressEncryption) {
35687 xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen));
35688 } else {
35689 xrefEntry = parser.getObj();
35690 }
35691 if (!isStream(xrefEntry)) {
35692 this.cache[num] = xrefEntry;
35693 }
35694 return xrefEntry;
35695 },
35696
35697 fetchCompressed: function XRef_fetchCompressed(xrefEntry,
35698 suppressEncryption) {
35699 var tableOffset = xrefEntry.offset;
35700 var stream = this.fetch(new Ref(tableOffset, 0));
35701 if (!isStream(stream)) {
35702 error('bad ObjStm stream');
35703 }
35704 var first = stream.dict.get('First');
35705 var n = stream.dict.get('N');
35706 if (!isInt(first) || !isInt(n)) {
35707 error('invalid first and n parameters for ObjStm stream');
35708 }
35709 var parser = new Parser(new Lexer(stream), false, this);
35710 parser.allowStreams = true;
35711 var i, entries = [], num, nums = [];
35712 // read the object numbers to populate cache
35713 for (i = 0; i < n; ++i) {
35714 num = parser.getObj();
35715 if (!isInt(num)) {
35716 error('invalid object number in the ObjStm stream: ' + num);
35717 }
35718 nums.push(num);
35719 var offset = parser.getObj();
35720 if (!isInt(offset)) {
35721 error('invalid object offset in the ObjStm stream: ' + offset);
35722 }
35723 }
35724 // read stream objects for cache
35725 for (i = 0; i < n; ++i) {
35726 entries.push(parser.getObj());
35727 // The ObjStm should not contain 'endobj'. If it's present, skip over it
35728 // to support corrupt PDFs (fixes issue 5241, bug 898610, bug 1037816).
35729 if (isCmd(parser.buf1, 'endobj')) {
35730 parser.shift();
35731 }
35732 num = nums[i];
35733 var entry = this.entries[num];
35734 if (entry && entry.offset === tableOffset && entry.gen === i) {
35735 this.cache[num] = entries[i];
35736 }
35737 }
35738 xrefEntry = entries[xrefEntry.gen];
35739 if (xrefEntry === undefined) {
35740 error('bad XRef entry for compressed object');
35741 }
35742 return xrefEntry;
35743 },
35744
35745 fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) {
35746 if (!isRef(obj)) {
35747 return Promise.resolve(obj);
35748 }
35749 return this.fetchAsync(obj);
35750 },
35751
35752 fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) {
35753 var streamManager = this.stream.manager;
35754 var xref = this;
35755 return new Promise(function tryFetch(resolve, reject) {
35756 try {
35757 resolve(xref.fetch(ref, suppressEncryption));
35758 } catch (e) {
35759 if (e instanceof MissingDataException) {
35760 streamManager.requestRange(e.begin, e.end).then(function () {
35761 tryFetch(resolve, reject);
35762 }, reject);
35763 return;
35764 }
35765 reject(e);
35766 }
35767 });
35768 },
35769
35770 getCatalogObj: function XRef_getCatalogObj() {
35771 return this.root;
35772 }
35773 };
35774
35775 return XRef;
35776})();
35777
35778/**
35779 * A NameTree/NumberTree is like a Dict but has some advantageous properties,
35780 * see the specification (7.9.6 and 7.9.7) for additional details.
35781 * TODO: implement all the Dict functions and make this more efficient.
35782 */
35783var NameOrNumberTree = (function NameOrNumberTreeClosure() {
35784 function NameOrNumberTree(root, xref) {
35785 throw new Error('Cannot initialize NameOrNumberTree.');
35786 }
35787
35788 NameOrNumberTree.prototype = {
35789 getAll: function NameOrNumberTree_getAll() {
35790 var dict = Object.create(null);
35791 if (!this.root) {
35792 return dict;
35793 }
35794 var xref = this.xref;
35795 // Reading Name/Number tree.
35796 var processed = new RefSet();
35797 processed.put(this.root);
35798 var queue = [this.root];
35799 while (queue.length > 0) {
35800 var i, n;
35801 var obj = xref.fetchIfRef(queue.shift());
35802 if (!isDict(obj)) {
35803 continue;
35804 }
35805 if (obj.has('Kids')) {
35806 var kids = obj.get('Kids');
35807 for (i = 0, n = kids.length; i < n; i++) {
35808 var kid = kids[i];
35809 assert(!processed.has(kid),
35810 'Duplicate entry in "' + this._type + '" tree.');
35811 queue.push(kid);
35812 processed.put(kid);
35813 }
35814 continue;
35815 }
35816 var entries = obj.get(this._type);
35817 if (isArray(entries)) {
35818 for (i = 0, n = entries.length; i < n; i += 2) {
35819 dict[xref.fetchIfRef(entries[i])] = xref.fetchIfRef(entries[i + 1]);
35820 }
35821 }
35822 }
35823 return dict;
35824 },
35825
35826 get: function NameOrNumberTree_get(key) {
35827 if (!this.root) {
35828 return null;
35829 }
35830
35831 var xref = this.xref;
35832 var kidsOrEntries = xref.fetchIfRef(this.root);
35833 var loopCount = 0;
35834 var MAX_LEVELS = 10;
35835 var l, r, m;
35836
35837 // Perform a binary search to quickly find the entry that
35838 // contains the key we are looking for.
35839 while (kidsOrEntries.has('Kids')) {
35840 if (++loopCount > MAX_LEVELS) {
35841 warn('Search depth limit reached for "' + this._type + '" tree.');
35842 return null;
35843 }
35844
35845 var kids = kidsOrEntries.get('Kids');
35846 if (!isArray(kids)) {
35847 return null;
35848 }
35849
35850 l = 0;
35851 r = kids.length - 1;
35852 while (l <= r) {
35853 m = (l + r) >> 1;
35854 var kid = xref.fetchIfRef(kids[m]);
35855 var limits = kid.get('Limits');
35856
35857 if (key < xref.fetchIfRef(limits[0])) {
35858 r = m - 1;
35859 } else if (key > xref.fetchIfRef(limits[1])) {
35860 l = m + 1;
35861 } else {
35862 kidsOrEntries = xref.fetchIfRef(kids[m]);
35863 break;
35864 }
35865 }
35866 if (l > r) {
35867 return null;
35868 }
35869 }
35870
35871 // If we get here, then we have found the right entry. Now go through the
35872 // entries in the dictionary until we find the key we're looking for.
35873 var entries = kidsOrEntries.get(this._type);
35874 if (isArray(entries)) {
35875 // Perform a binary search to reduce the lookup time.
35876 l = 0;
35877 r = entries.length - 2;
35878 while (l <= r) {
35879 // Check only even indices (0, 2, 4, ...) because the
35880 // odd indices contain the actual data.
35881 m = (l + r) & ~1;
35882 var currentKey = xref.fetchIfRef(entries[m]);
35883 if (key < currentKey) {
35884 r = m - 2;
35885 } else if (key > currentKey) {
35886 l = m + 2;
35887 } else {
35888 return xref.fetchIfRef(entries[m + 1]);
35889 }
35890 }
35891 }
35892 return null;
35893 }
35894 };
35895 return NameOrNumberTree;
35896})();
35897
35898var NameTree = (function NameTreeClosure() {
35899 function NameTree(root, xref) {
35900 this.root = root;
35901 this.xref = xref;
35902 this._type = 'Names';
35903 }
35904
35905 Util.inherit(NameTree, NameOrNumberTree, {});
35906
35907 return NameTree;
35908})();
35909
35910var NumberTree = (function NumberTreeClosure() {
35911 function NumberTree(root, xref) {
35912 this.root = root;
35913 this.xref = xref;
35914 this._type = 'Nums';
35915 }
35916
35917 Util.inherit(NumberTree, NameOrNumberTree, {});
35918
35919 return NumberTree;
35920})();
35921
35922/**
35923 * "A PDF file can refer to the contents of another file by using a File
35924 * Specification (PDF 1.1)", see the spec (7.11) for more details.
35925 * NOTE: Only embedded files are supported (as part of the attachments support)
35926 * TODO: support the 'URL' file system (with caching if !/V), portable
35927 * collections attributes and related files (/RF)
35928 */
35929var FileSpec = (function FileSpecClosure() {
35930 function FileSpec(root, xref) {
35931 if (!root || !isDict(root)) {
35932 return;
35933 }
35934 this.xref = xref;
35935 this.root = root;
35936 if (root.has('FS')) {
35937 this.fs = root.get('FS');
35938 }
35939 this.description = root.has('Desc') ?
35940 stringToPDFString(root.get('Desc')) :
35941 '';
35942 if (root.has('RF')) {
35943 warn('Related file specifications are not supported');
35944 }
35945 this.contentAvailable = true;
35946 if (!root.has('EF')) {
35947 this.contentAvailable = false;
35948 warn('Non-embedded file specifications are not supported');
35949 }
35950 }
35951
35952 function pickPlatformItem(dict) {
35953 // Look for the filename in this order:
35954 // UF, F, Unix, Mac, DOS
35955 if (dict.has('UF')) {
35956 return dict.get('UF');
35957 } else if (dict.has('F')) {
35958 return dict.get('F');
35959 } else if (dict.has('Unix')) {
35960 return dict.get('Unix');
35961 } else if (dict.has('Mac')) {
35962 return dict.get('Mac');
35963 } else if (dict.has('DOS')) {
35964 return dict.get('DOS');
35965 } else {
35966 return null;
35967 }
35968 }
35969
35970 FileSpec.prototype = {
35971 get filename() {
35972 if (!this._filename && this.root) {
35973 var filename = pickPlatformItem(this.root) || 'unnamed';
35974 this._filename = stringToPDFString(filename).
35975 replace(/\\\\/g, '\\').
35976 replace(/\\\//g, '/').
35977 replace(/\\/g, '/');
35978 }
35979 return this._filename;
35980 },
35981 get content() {
35982 if (!this.contentAvailable) {
35983 return null;
35984 }
35985 if (!this.contentRef && this.root) {
35986 this.contentRef = pickPlatformItem(this.root.get('EF'));
35987 }
35988 var content = null;
35989 if (this.contentRef) {
35990 var xref = this.xref;
35991 var fileObj = xref.fetchIfRef(this.contentRef);
35992 if (fileObj && isStream(fileObj)) {
35993 content = fileObj.getBytes();
35994 } else {
35995 warn('Embedded file specification points to non-existing/invalid ' +
35996 'content');
35997 }
35998 } else {
35999 warn('Embedded file specification does not have a content');
36000 }
36001 return content;
36002 },
36003 get serializable() {
36004 return {
36005 filename: this.filename,
36006 content: this.content
36007 };
36008 }
36009 };
36010 return FileSpec;
36011})();
36012
36013/**
36014 * A helper for loading missing data in object graphs. It traverses the graph
36015 * depth first and queues up any objects that have missing data. Once it has
36016 * has traversed as many objects that are available it attempts to bundle the
36017 * missing data requests and then resume from the nodes that weren't ready.
36018 *
36019 * NOTE: It provides protection from circular references by keeping track of
36020 * of loaded references. However, you must be careful not to load any graphs
36021 * that have references to the catalog or other pages since that will cause the
36022 * entire PDF document object graph to be traversed.
36023 */
36024var ObjectLoader = (function() {
36025 function mayHaveChildren(value) {
36026 return isRef(value) || isDict(value) || isArray(value) || isStream(value);
36027 }
36028
36029 function addChildren(node, nodesToVisit) {
36030 var value;
36031 if (isDict(node) || isStream(node)) {
36032 var map;
36033 if (isDict(node)) {
36034 map = node.map;
36035 } else {
36036 map = node.dict.map;
36037 }
36038 for (var key in map) {
36039 value = map[key];
36040 if (mayHaveChildren(value)) {
36041 nodesToVisit.push(value);
36042 }
36043 }
36044 } else if (isArray(node)) {
36045 for (var i = 0, ii = node.length; i < ii; i++) {
36046 value = node[i];
36047 if (mayHaveChildren(value)) {
36048 nodesToVisit.push(value);
36049 }
36050 }
36051 }
36052 }
36053
36054 function ObjectLoader(obj, keys, xref) {
36055 this.obj = obj;
36056 this.keys = keys;
36057 this.xref = xref;
36058 this.refSet = null;
36059 this.capability = null;
36060 }
36061
36062 ObjectLoader.prototype = {
36063 load: function ObjectLoader_load() {
36064 var keys = this.keys;
36065 this.capability = createPromiseCapability();
36066 // Don't walk the graph if all the data is already loaded.
36067 if (!(this.xref.stream instanceof ChunkedStream) ||
36068 this.xref.stream.getMissingChunks().length === 0) {
36069 this.capability.resolve();
36070 return this.capability.promise;
36071 }
36072
36073 this.refSet = new RefSet();
36074 // Setup the initial nodes to visit.
36075 var nodesToVisit = [];
36076 for (var i = 0; i < keys.length; i++) {
36077 nodesToVisit.push(this.obj[keys[i]]);
36078 }
36079
36080 this._walk(nodesToVisit);
36081 return this.capability.promise;
36082 },
36083
36084 _walk: function ObjectLoader_walk(nodesToVisit) {
36085 var nodesToRevisit = [];
36086 var pendingRequests = [];
36087 // DFS walk of the object graph.
36088 while (nodesToVisit.length) {
36089 var currentNode = nodesToVisit.pop();
36090
36091 // Only references or chunked streams can cause missing data exceptions.
36092 if (isRef(currentNode)) {
36093 // Skip nodes that have already been visited.
36094 if (this.refSet.has(currentNode)) {
36095 continue;
36096 }
36097 try {
36098 var ref = currentNode;
36099 this.refSet.put(ref);
36100 currentNode = this.xref.fetch(currentNode);
36101 } catch (e) {
36102 if (!(e instanceof MissingDataException)) {
36103 throw e;
36104 }
36105 nodesToRevisit.push(currentNode);
36106 pendingRequests.push({ begin: e.begin, end: e.end });
36107 }
36108 }
36109 if (currentNode && currentNode.getBaseStreams) {
36110 var baseStreams = currentNode.getBaseStreams();
36111 var foundMissingData = false;
36112 for (var i = 0; i < baseStreams.length; i++) {
36113 var stream = baseStreams[i];
36114 if (stream.getMissingChunks && stream.getMissingChunks().length) {
36115 foundMissingData = true;
36116 pendingRequests.push({
36117 begin: stream.start,
36118 end: stream.end
36119 });
36120 }
36121 }
36122 if (foundMissingData) {
36123 nodesToRevisit.push(currentNode);
36124 }
36125 }
36126
36127 addChildren(currentNode, nodesToVisit);
36128 }
36129
36130 if (pendingRequests.length) {
36131 this.xref.stream.manager.requestRanges(pendingRequests).then(
36132 function pendingRequestCallback() {
36133 nodesToVisit = nodesToRevisit;
36134 for (var i = 0; i < nodesToRevisit.length; i++) {
36135 var node = nodesToRevisit[i];
36136 // Remove any reference nodes from the currrent refset so they
36137 // aren't skipped when we revist them.
36138 if (isRef(node)) {
36139 this.refSet.remove(node);
36140 }
36141 }
36142 this._walk(nodesToVisit);
36143 }.bind(this), this.capability.reject);
36144 return;
36145 }
36146 // Everything is loaded.
36147 this.refSet = null;
36148 this.capability.resolve();
36149 }
36150 };
36151
36152 return ObjectLoader;
36153})();
36154
36155exports.Catalog = Catalog;
36156exports.ObjectLoader = ObjectLoader;
36157exports.XRef = XRef;
36158exports.FileSpec = FileSpec;
36159}));
36160
36161
36162(function (root, factory) {
36163 {
36164 factory((root.pdfjsCorePattern = {}), root.pdfjsSharedUtil,
36165 root.pdfjsCorePrimitives, root.pdfjsCoreFunction,
36166 root.pdfjsCoreColorSpace);
36167 }
36168}(this, function (exports, sharedUtil, corePrimitives, coreFunction,
36169 coreColorSpace) {
36170
36171var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES;
36172var MissingDataException = sharedUtil.MissingDataException;
36173var Util = sharedUtil.Util;
36174var assert = sharedUtil.assert;
36175var error = sharedUtil.error;
36176var info = sharedUtil.info;
36177var warn = sharedUtil.warn;
36178var isStream = corePrimitives.isStream;
36179var PDFFunction = coreFunction.PDFFunction;
36180var ColorSpace = coreColorSpace.ColorSpace;
36181
36182var ShadingType = {
36183 FUNCTION_BASED: 1,
36184 AXIAL: 2,
36185 RADIAL: 3,
36186 FREE_FORM_MESH: 4,
36187 LATTICE_FORM_MESH: 5,
36188 COONS_PATCH_MESH: 6,
36189 TENSOR_PATCH_MESH: 7
36190};
36191
36192var Pattern = (function PatternClosure() {
36193 // Constructor should define this.getPattern
36194 function Pattern() {
36195 error('should not call Pattern constructor');
36196 }
36197
36198 Pattern.prototype = {
36199 // Input: current Canvas context
36200 // Output: the appropriate fillStyle or strokeStyle
36201 getPattern: function Pattern_getPattern(ctx) {
36202 error('Should not call Pattern.getStyle: ' + ctx);
36203 }
36204 };
36205
36206 Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
36207 res, handler) {
36208
36209 var dict = isStream(shading) ? shading.dict : shading;
36210 var type = dict.get('ShadingType');
36211
36212 try {
36213 switch (type) {
36214 case ShadingType.AXIAL:
36215 case ShadingType.RADIAL:
36216 // Both radial and axial shadings are handled by RadialAxial shading.
36217 return new Shadings.RadialAxial(dict, matrix, xref, res);
36218 case ShadingType.FREE_FORM_MESH:
36219 case ShadingType.LATTICE_FORM_MESH:
36220 case ShadingType.COONS_PATCH_MESH:
36221 case ShadingType.TENSOR_PATCH_MESH:
36222 return new Shadings.Mesh(shading, matrix, xref, res);
36223 default:
36224 throw new Error('Unsupported ShadingType: ' + type);
36225 }
36226 } catch (ex) {
36227 if (ex instanceof MissingDataException) {
36228 throw ex;
36229 }
36230 handler.send('UnsupportedFeature',
36231 {featureId: UNSUPPORTED_FEATURES.shadingPattern});
36232 warn(ex);
36233 return new Shadings.Dummy();
36234 }
36235 };
36236 return Pattern;
36237})();
36238
36239var Shadings = {};
36240
36241// A small number to offset the first/last color stops so we can insert ones to
36242// support extend. Number.MIN_VALUE is too small and breaks the extend.
36243Shadings.SMALL_NUMBER = 1e-6;
36244
36245// Radial and axial shading have very similar implementations
36246// If needed, the implementations can be broken into two classes
36247Shadings.RadialAxial = (function RadialAxialClosure() {
36248 function RadialAxial(dict, matrix, xref, res) {
36249 this.matrix = matrix;
36250 this.coordsArr = dict.getArray('Coords');
36251 this.shadingType = dict.get('ShadingType');
36252 this.type = 'Pattern';
36253 var cs = dict.get('ColorSpace', 'CS');
36254 cs = ColorSpace.parse(cs, xref, res);
36255 this.cs = cs;
36256
36257 var t0 = 0.0, t1 = 1.0;
36258 if (dict.has('Domain')) {
36259 var domainArr = dict.getArray('Domain');
36260 t0 = domainArr[0];
36261 t1 = domainArr[1];
36262 }
36263
36264 var extendStart = false, extendEnd = false;
36265 if (dict.has('Extend')) {
36266 var extendArr = dict.getArray('Extend');
36267 extendStart = extendArr[0];
36268 extendEnd = extendArr[1];
36269 }
36270
36271 if (this.shadingType === ShadingType.RADIAL &&
36272 (!extendStart || !extendEnd)) {
36273 // Radial gradient only currently works if either circle is fully within
36274 // the other circle.
36275 var x1 = this.coordsArr[0];
36276 var y1 = this.coordsArr[1];
36277 var r1 = this.coordsArr[2];
36278 var x2 = this.coordsArr[3];
36279 var y2 = this.coordsArr[4];
36280 var r2 = this.coordsArr[5];
36281 var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
36282 if (r1 <= r2 + distance &&
36283 r2 <= r1 + distance) {
36284 warn('Unsupported radial gradient.');
36285 }
36286 }
36287
36288 this.extendStart = extendStart;
36289 this.extendEnd = extendEnd;
36290
36291 var fnObj = dict.get('Function');
36292 var fn = PDFFunction.parseArray(xref, fnObj);
36293
36294 // 10 samples seems good enough for now, but probably won't work
36295 // if there are sharp color changes. Ideally, we would implement
36296 // the spec faithfully and add lossless optimizations.
36297 var diff = t1 - t0;
36298 var step = diff / 10;
36299
36300 var colorStops = this.colorStops = [];
36301
36302 // Protect against bad domains so we don't end up in an infinte loop below.
36303 if (t0 >= t1 || step <= 0) {
36304 // Acrobat doesn't seem to handle these cases so we'll ignore for
36305 // now.
36306 info('Bad shading domain.');
36307 return;
36308 }
36309
36310 var color = new Float32Array(cs.numComps), ratio = new Float32Array(1);
36311 var rgbColor;
36312 for (var i = t0; i <= t1; i += step) {
36313 ratio[0] = i;
36314 fn(ratio, 0, color, 0);
36315 rgbColor = cs.getRgb(color, 0);
36316 var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
36317 colorStops.push([(i - t0) / diff, cssColor]);
36318 }
36319
36320 var background = 'transparent';
36321 if (dict.has('Background')) {
36322 rgbColor = cs.getRgb(dict.get('Background'), 0);
36323 background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
36324 }
36325
36326 if (!extendStart) {
36327 // Insert a color stop at the front and offset the first real color stop
36328 // so it doesn't conflict with the one we insert.
36329 colorStops.unshift([0, background]);
36330 colorStops[1][0] += Shadings.SMALL_NUMBER;
36331 }
36332 if (!extendEnd) {
36333 // Same idea as above in extendStart but for the end.
36334 colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
36335 colorStops.push([1, background]);
36336 }
36337
36338 this.colorStops = colorStops;
36339 }
36340
36341 RadialAxial.prototype = {
36342 getIR: function RadialAxial_getIR() {
36343 var coordsArr = this.coordsArr;
36344 var shadingType = this.shadingType;
36345 var type, p0, p1, r0, r1;
36346 if (shadingType === ShadingType.AXIAL) {
36347 p0 = [coordsArr[0], coordsArr[1]];
36348 p1 = [coordsArr[2], coordsArr[3]];
36349 r0 = null;
36350 r1 = null;
36351 type = 'axial';
36352 } else if (shadingType === ShadingType.RADIAL) {
36353 p0 = [coordsArr[0], coordsArr[1]];
36354 p1 = [coordsArr[3], coordsArr[4]];
36355 r0 = coordsArr[2];
36356 r1 = coordsArr[5];
36357 type = 'radial';
36358 } else {
36359 error('getPattern type unknown: ' + shadingType);
36360 }
36361
36362 var matrix = this.matrix;
36363 if (matrix) {
36364 p0 = Util.applyTransform(p0, matrix);
36365 p1 = Util.applyTransform(p1, matrix);
36366 if (shadingType === ShadingType.RADIAL) {
36367 var scale = Util.singularValueDecompose2dScale(matrix);
36368 r0 *= scale[0];
36369 r1 *= scale[1];
36370 }
36371 }
36372
36373 return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
36374 }
36375 };
36376
36377 return RadialAxial;
36378})();
36379
36380// All mesh shading. For now, they will be presented as set of the triangles
36381// to be drawn on the canvas and rgb color for each vertex.
36382Shadings.Mesh = (function MeshClosure() {
36383 function MeshStreamReader(stream, context) {
36384 this.stream = stream;
36385 this.context = context;
36386 this.buffer = 0;
36387 this.bufferLength = 0;
36388
36389 var numComps = context.numComps;
36390 this.tmpCompsBuf = new Float32Array(numComps);
36391 var csNumComps = context.colorSpace.numComps;
36392 this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) :
36393 this.tmpCompsBuf;
36394 }
36395 MeshStreamReader.prototype = {
36396 get hasData() {
36397 if (this.stream.end) {
36398 return this.stream.pos < this.stream.end;
36399 }
36400 if (this.bufferLength > 0) {
36401 return true;
36402 }
36403 var nextByte = this.stream.getByte();
36404 if (nextByte < 0) {
36405 return false;
36406 }
36407 this.buffer = nextByte;
36408 this.bufferLength = 8;
36409 return true;
36410 },
36411 readBits: function MeshStreamReader_readBits(n) {
36412 var buffer = this.buffer;
36413 var bufferLength = this.bufferLength;
36414 if (n === 32) {
36415 if (bufferLength === 0) {
36416 return ((this.stream.getByte() << 24) |
36417 (this.stream.getByte() << 16) | (this.stream.getByte() << 8) |
36418 this.stream.getByte()) >>> 0;
36419 }
36420 buffer = (buffer << 24) | (this.stream.getByte() << 16) |
36421 (this.stream.getByte() << 8) | this.stream.getByte();
36422 var nextByte = this.stream.getByte();
36423 this.buffer = nextByte & ((1 << bufferLength) - 1);
36424 return ((buffer << (8 - bufferLength)) |
36425 ((nextByte & 0xFF) >> bufferLength)) >>> 0;
36426 }
36427 if (n === 8 && bufferLength === 0) {
36428 return this.stream.getByte();
36429 }
36430 while (bufferLength < n) {
36431 buffer = (buffer << 8) | this.stream.getByte();
36432 bufferLength += 8;
36433 }
36434 bufferLength -= n;
36435 this.bufferLength = bufferLength;
36436 this.buffer = buffer & ((1 << bufferLength) - 1);
36437 return buffer >> bufferLength;
36438 },
36439 align: function MeshStreamReader_align() {
36440 this.buffer = 0;
36441 this.bufferLength = 0;
36442 },
36443 readFlag: function MeshStreamReader_readFlag() {
36444 return this.readBits(this.context.bitsPerFlag);
36445 },
36446 readCoordinate: function MeshStreamReader_readCoordinate() {
36447 var bitsPerCoordinate = this.context.bitsPerCoordinate;
36448 var xi = this.readBits(bitsPerCoordinate);
36449 var yi = this.readBits(bitsPerCoordinate);
36450 var decode = this.context.decode;
36451 var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) :
36452 2.3283064365386963e-10; // 2 ^ -32
36453 return [
36454 xi * scale * (decode[1] - decode[0]) + decode[0],
36455 yi * scale * (decode[3] - decode[2]) + decode[2]
36456 ];
36457 },
36458 readComponents: function MeshStreamReader_readComponents() {
36459 var numComps = this.context.numComps;
36460 var bitsPerComponent = this.context.bitsPerComponent;
36461 var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) :
36462 2.3283064365386963e-10; // 2 ^ -32
36463 var decode = this.context.decode;
36464 var components = this.tmpCompsBuf;
36465 for (var i = 0, j = 4; i < numComps; i++, j += 2) {
36466 var ci = this.readBits(bitsPerComponent);
36467 components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
36468 }
36469 var color = this.tmpCsCompsBuf;
36470 if (this.context.colorFn) {
36471 this.context.colorFn(components, 0, color, 0);
36472 }
36473 return this.context.colorSpace.getRgb(color, 0);
36474 }
36475 };
36476
36477 function decodeType4Shading(mesh, reader) {
36478 var coords = mesh.coords;
36479 var colors = mesh.colors;
36480 var operators = [];
36481 var ps = []; // not maintaining cs since that will match ps
36482 var verticesLeft = 0; // assuming we have all data to start a new triangle
36483 while (reader.hasData) {
36484 var f = reader.readFlag();
36485 var coord = reader.readCoordinate();
36486 var color = reader.readComponents();
36487 if (verticesLeft === 0) { // ignoring flags if we started a triangle
36488 assert(0 <= f && f <= 2, 'Unknown type4 flag');
36489 switch (f) {
36490 case 0:
36491 verticesLeft = 3;
36492 break;
36493 case 1:
36494 ps.push(ps[ps.length - 2], ps[ps.length - 1]);
36495 verticesLeft = 1;
36496 break;
36497 case 2:
36498 ps.push(ps[ps.length - 3], ps[ps.length - 1]);
36499 verticesLeft = 1;
36500 break;
36501 }
36502 operators.push(f);
36503 }
36504 ps.push(coords.length);
36505 coords.push(coord);
36506 colors.push(color);
36507 verticesLeft--;
36508
36509 reader.align();
36510 }
36511 mesh.figures.push({
36512 type: 'triangles',
36513 coords: new Int32Array(ps),
36514 colors: new Int32Array(ps),
36515 });
36516 }
36517
36518 function decodeType5Shading(mesh, reader, verticesPerRow) {
36519 var coords = mesh.coords;
36520 var colors = mesh.colors;
36521 var ps = []; // not maintaining cs since that will match ps
36522 while (reader.hasData) {
36523 var coord = reader.readCoordinate();
36524 var color = reader.readComponents();
36525 ps.push(coords.length);
36526 coords.push(coord);
36527 colors.push(color);
36528 }
36529 mesh.figures.push({
36530 type: 'lattice',
36531 coords: new Int32Array(ps),
36532 colors: new Int32Array(ps),
36533 verticesPerRow: verticesPerRow
36534 });
36535 }
36536
36537 var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
36538 var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
36539
36540 var TRIANGLE_DENSITY = 20; // count of triangles per entire mesh bounds
36541
36542 var getB = (function getBClosure() {
36543 function buildB(count) {
36544 var lut = [];
36545 for (var i = 0; i <= count; i++) {
36546 var t = i / count, t_ = 1 - t;
36547 lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_,
36548 3 * t * t * t_, t * t * t]));
36549 }
36550 return lut;
36551 }
36552 var cache = [];
36553 return function getB(count) {
36554 if (!cache[count]) {
36555 cache[count] = buildB(count);
36556 }
36557 return cache[count];
36558 };
36559 })();
36560
36561 function buildFigureFromPatch(mesh, index) {
36562 var figure = mesh.figures[index];
36563 assert(figure.type === 'patch', 'Unexpected patch mesh figure');
36564
36565 var coords = mesh.coords, colors = mesh.colors;
36566 var pi = figure.coords;
36567 var ci = figure.colors;
36568
36569 var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0],
36570 coords[pi[12]][0], coords[pi[15]][0]);
36571 var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1],
36572 coords[pi[12]][1], coords[pi[15]][1]);
36573 var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0],
36574 coords[pi[12]][0], coords[pi[15]][0]);
36575 var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1],
36576 coords[pi[12]][1], coords[pi[15]][1]);
36577 var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY /
36578 (mesh.bounds[2] - mesh.bounds[0]));
36579 splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
36580 Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
36581 var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY /
36582 (mesh.bounds[3] - mesh.bounds[1]));
36583 splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
36584 Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
36585
36586 var verticesPerRow = splitXBy + 1;
36587 var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
36588 var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
36589 var k = 0;
36590 var cl = new Uint8Array(3), cr = new Uint8Array(3);
36591 var c0 = colors[ci[0]], c1 = colors[ci[1]],
36592 c2 = colors[ci[2]], c3 = colors[ci[3]];
36593 var bRow = getB(splitYBy), bCol = getB(splitXBy);
36594 for (var row = 0; row <= splitYBy; row++) {
36595 cl[0] = ((c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy) | 0;
36596 cl[1] = ((c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy) | 0;
36597 cl[2] = ((c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy) | 0;
36598
36599 cr[0] = ((c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy) | 0;
36600 cr[1] = ((c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy) | 0;
36601 cr[2] = ((c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy) | 0;
36602
36603 for (var col = 0; col <= splitXBy; col++, k++) {
36604 if ((row === 0 || row === splitYBy) &&
36605 (col === 0 || col === splitXBy)) {
36606 continue;
36607 }
36608 var x = 0, y = 0;
36609 var q = 0;
36610 for (var i = 0; i <= 3; i++) {
36611 for (var j = 0; j <= 3; j++, q++) {
36612 var m = bRow[row][i] * bCol[col][j];
36613 x += coords[pi[q]][0] * m;
36614 y += coords[pi[q]][1] * m;
36615 }
36616 }
36617 figureCoords[k] = coords.length;
36618 coords.push([x, y]);
36619 figureColors[k] = colors.length;
36620 var newColor = new Uint8Array(3);
36621 newColor[0] = ((cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy) | 0;
36622 newColor[1] = ((cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy) | 0;
36623 newColor[2] = ((cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy) | 0;
36624 colors.push(newColor);
36625 }
36626 }
36627 figureCoords[0] = pi[0];
36628 figureColors[0] = ci[0];
36629 figureCoords[splitXBy] = pi[3];
36630 figureColors[splitXBy] = ci[1];
36631 figureCoords[verticesPerRow * splitYBy] = pi[12];
36632 figureColors[verticesPerRow * splitYBy] = ci[2];
36633 figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
36634 figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
36635
36636 mesh.figures[index] = {
36637 type: 'lattice',
36638 coords: figureCoords,
36639 colors: figureColors,
36640 verticesPerRow: verticesPerRow
36641 };
36642 }
36643
36644 function decodeType6Shading(mesh, reader) {
36645 // A special case of Type 7. The p11, p12, p21, p22 automatically filled
36646 var coords = mesh.coords;
36647 var colors = mesh.colors;
36648 var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33
36649 var cs = new Int32Array(4); // c00, c30, c03, c33
36650 while (reader.hasData) {
36651 var f = reader.readFlag();
36652 assert(0 <= f && f <= 3, 'Unknown type6 flag');
36653 var i, ii;
36654 var pi = coords.length;
36655 for (i = 0, ii = (f !== 0 ? 8 : 12); i < ii; i++) {
36656 coords.push(reader.readCoordinate());
36657 }
36658 var ci = colors.length;
36659 for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) {
36660 colors.push(reader.readComponents());
36661 }
36662 var tmp1, tmp2, tmp3, tmp4;
36663 switch (f) {
36664 case 0:
36665 ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6;
36666 ps[ 8] = pi + 2; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7;
36667 ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 8;
36668 ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9;
36669 cs[2] = ci + 1; cs[3] = ci + 2;
36670 cs[0] = ci; cs[1] = ci + 3;
36671 break;
36672 case 1:
36673 tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15];
36674 ps[12] = tmp4; ps[13] = pi + 0; ps[14] = pi + 1; ps[15] = pi + 2;
36675 ps[ 8] = tmp3; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 3;
36676 ps[ 4] = tmp2; /* calculated below */ ps[ 7] = pi + 4;
36677 ps[ 0] = tmp1; ps[ 1] = pi + 7; ps[ 2] = pi + 6; ps[ 3] = pi + 5;
36678 tmp1 = cs[2]; tmp2 = cs[3];
36679 cs[2] = tmp2; cs[3] = ci;
36680 cs[0] = tmp1; cs[1] = ci + 1;
36681 break;
36682 case 2:
36683 tmp1 = ps[15];
36684 tmp2 = ps[11];
36685 ps[12] = ps[3]; ps[13] = pi + 0; ps[14] = pi + 1; ps[15] = pi + 2;
36686 ps[ 8] = ps[7]; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 3;
36687 ps[ 4] = tmp2; /* calculated below */ ps[ 7] = pi + 4;
36688 ps[ 0] = tmp1; ps[ 1] = pi + 7; ps[ 2] = pi + 6; ps[ 3] = pi + 5;
36689 tmp1 = cs[3];
36690 cs[2] = cs[1]; cs[3] = ci;
36691 cs[0] = tmp1; cs[1] = ci + 1;
36692 break;
36693 case 3:
36694 ps[12] = ps[0]; ps[13] = pi + 0; ps[14] = pi + 1; ps[15] = pi + 2;
36695 ps[ 8] = ps[1]; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 3;
36696 ps[ 4] = ps[2]; /* calculated below */ ps[ 7] = pi + 4;
36697 ps[ 0] = ps[3]; ps[ 1] = pi + 7; ps[ 2] = pi + 6; ps[ 3] = pi + 5;
36698 cs[2] = cs[0]; cs[3] = ci;
36699 cs[0] = cs[1]; cs[1] = ci + 1;
36700 break;
36701 }
36702 // set p11, p12, p21, p22
36703 ps[5] = coords.length;
36704 coords.push([
36705 (-4 * coords[ps[0]][0] - coords[ps[15]][0] +
36706 6 * (coords[ps[4]][0] + coords[ps[1]][0]) -
36707 2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
36708 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
36709 (-4 * coords[ps[0]][1] - coords[ps[15]][1] +
36710 6 * (coords[ps[4]][1] + coords[ps[1]][1]) -
36711 2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
36712 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
36713 ]);
36714 ps[6] = coords.length;
36715 coords.push([
36716 (-4 * coords[ps[3]][0] - coords[ps[12]][0] +
36717 6 * (coords[ps[2]][0] + coords[ps[7]][0]) -
36718 2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
36719 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
36720 (-4 * coords[ps[3]][1] - coords[ps[12]][1] +
36721 6 * (coords[ps[2]][1] + coords[ps[7]][1]) -
36722 2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
36723 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
36724 ]);
36725 ps[9] = coords.length;
36726 coords.push([
36727 (-4 * coords[ps[12]][0] - coords[ps[3]][0] +
36728 6 * (coords[ps[8]][0] + coords[ps[13]][0]) -
36729 2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
36730 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
36731 (-4 * coords[ps[12]][1] - coords[ps[3]][1] +
36732 6 * (coords[ps[8]][1] + coords[ps[13]][1]) -
36733 2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
36734 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
36735 ]);
36736 ps[10] = coords.length;
36737 coords.push([
36738 (-4 * coords[ps[15]][0] - coords[ps[0]][0] +
36739 6 * (coords[ps[11]][0] + coords[ps[14]][0]) -
36740 2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
36741 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
36742 (-4 * coords[ps[15]][1] - coords[ps[0]][1] +
36743 6 * (coords[ps[11]][1] + coords[ps[14]][1]) -
36744 2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
36745 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
36746 ]);
36747 mesh.figures.push({
36748 type: 'patch',
36749 coords: new Int32Array(ps), // making copies of ps and cs
36750 colors: new Int32Array(cs)
36751 });
36752 }
36753 }
36754
36755 function decodeType7Shading(mesh, reader) {
36756 var coords = mesh.coords;
36757 var colors = mesh.colors;
36758 var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33
36759 var cs = new Int32Array(4); // c00, c30, c03, c33
36760 while (reader.hasData) {
36761 var f = reader.readFlag();
36762 assert(0 <= f && f <= 3, 'Unknown type7 flag');
36763 var i, ii;
36764 var pi = coords.length;
36765 for (i = 0, ii = (f !== 0 ? 12 : 16); i < ii; i++) {
36766 coords.push(reader.readCoordinate());
36767 }
36768 var ci = colors.length;
36769 for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) {
36770 colors.push(reader.readComponents());
36771 }
36772 var tmp1, tmp2, tmp3, tmp4;
36773 switch (f) {
36774 case 0:
36775 ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6;
36776 ps[ 8] = pi + 2; ps[ 9] = pi + 13; ps[10] = pi + 14; ps[11] = pi + 7;
36777 ps[ 4] = pi + 1; ps[ 5] = pi + 12; ps[ 6] = pi + 15; ps[ 7] = pi + 8;
36778 ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9;
36779 cs[2] = ci + 1; cs[3] = ci + 2;
36780 cs[0] = ci; cs[1] = ci + 3;
36781 break;
36782 case 1:
36783 tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15];
36784 ps[12] = tmp4; ps[13] = pi + 0; ps[14] = pi + 1; ps[15] = pi + 2;
36785 ps[ 8] = tmp3; ps[ 9] = pi + 9; ps[10] = pi + 10; ps[11] = pi + 3;
36786 ps[ 4] = tmp2; ps[ 5] = pi + 8; ps[ 6] = pi + 11; ps[ 7] = pi + 4;
36787 ps[ 0] = tmp1; ps[ 1] = pi + 7; ps[ 2] = pi + 6; ps[ 3] = pi + 5;
36788 tmp1 = cs[2]; tmp2 = cs[3];
36789 cs[2] = tmp2; cs[3] = ci;
36790 cs[0] = tmp1; cs[1] = ci + 1;
36791 break;
36792 case 2:
36793 tmp1 = ps[15];
36794 tmp2 = ps[11];
36795 ps[12] = ps[3]; ps[13] = pi + 0; ps[14] = pi + 1; ps[15] = pi + 2;
36796 ps[ 8] = ps[7]; ps[ 9] = pi + 9; ps[10] = pi + 10; ps[11] = pi + 3;
36797 ps[ 4] = tmp2; ps[ 5] = pi + 8; ps[ 6] = pi + 11; ps[ 7] = pi + 4;
36798 ps[ 0] = tmp1; ps[ 1] = pi + 7; ps[ 2] = pi + 6; ps[ 3] = pi + 5;
36799 tmp1 = cs[3];
36800 cs[2] = cs[1]; cs[3] = ci;
36801 cs[0] = tmp1; cs[1] = ci + 1;
36802 break;
36803 case 3:
36804 ps[12] = ps[0]; ps[13] = pi + 0; ps[14] = pi + 1; ps[15] = pi + 2;
36805 ps[ 8] = ps[1]; ps[ 9] = pi + 9; ps[10] = pi + 10; ps[11] = pi + 3;
36806 ps[ 4] = ps[2]; ps[ 5] = pi + 8; ps[ 6] = pi + 11; ps[ 7] = pi + 4;
36807 ps[ 0] = ps[3]; ps[ 1] = pi + 7; ps[ 2] = pi + 6; ps[ 3] = pi + 5;
36808 cs[2] = cs[0]; cs[3] = ci;
36809 cs[0] = cs[1]; cs[1] = ci + 1;
36810 break;
36811 }
36812 mesh.figures.push({
36813 type: 'patch',
36814 coords: new Int32Array(ps), // making copies of ps and cs
36815 colors: new Int32Array(cs)
36816 });
36817 }
36818 }
36819
36820 function updateBounds(mesh) {
36821 var minX = mesh.coords[0][0], minY = mesh.coords[0][1],
36822 maxX = minX, maxY = minY;
36823 for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
36824 var x = mesh.coords[i][0], y = mesh.coords[i][1];
36825 minX = minX > x ? x : minX;
36826 minY = minY > y ? y : minY;
36827 maxX = maxX < x ? x : maxX;
36828 maxY = maxY < y ? y : maxY;
36829 }
36830 mesh.bounds = [minX, minY, maxX, maxY];
36831 }
36832
36833 function packData(mesh) {
36834 var i, ii, j, jj;
36835
36836 var coords = mesh.coords;
36837 var coordsPacked = new Float32Array(coords.length * 2);
36838 for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
36839 var xy = coords[i];
36840 coordsPacked[j++] = xy[0];
36841 coordsPacked[j++] = xy[1];
36842 }
36843 mesh.coords = coordsPacked;
36844
36845 var colors = mesh.colors;
36846 var colorsPacked = new Uint8Array(colors.length * 3);
36847 for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
36848 var c = colors[i];
36849 colorsPacked[j++] = c[0];
36850 colorsPacked[j++] = c[1];
36851 colorsPacked[j++] = c[2];
36852 }
36853 mesh.colors = colorsPacked;
36854
36855 var figures = mesh.figures;
36856 for (i = 0, ii = figures.length; i < ii; i++) {
36857 var figure = figures[i], ps = figure.coords, cs = figure.colors;
36858 for (j = 0, jj = ps.length; j < jj; j++) {
36859 ps[j] *= 2;
36860 cs[j] *= 3;
36861 }
36862 }
36863 }
36864
36865 function Mesh(stream, matrix, xref, res) {
36866 assert(isStream(stream), 'Mesh data is not a stream');
36867 var dict = stream.dict;
36868 this.matrix = matrix;
36869 this.shadingType = dict.get('ShadingType');
36870 this.type = 'Pattern';
36871 this.bbox = dict.getArray('BBox');
36872 var cs = dict.get('ColorSpace', 'CS');
36873 cs = ColorSpace.parse(cs, xref, res);
36874 this.cs = cs;
36875 this.background = dict.has('Background') ?
36876 cs.getRgb(dict.get('Background'), 0) : null;
36877
36878 var fnObj = dict.get('Function');
36879 var fn = fnObj ? PDFFunction.parseArray(xref, fnObj) : null;
36880
36881 this.coords = [];
36882 this.colors = [];
36883 this.figures = [];
36884
36885 var decodeContext = {
36886 bitsPerCoordinate: dict.get('BitsPerCoordinate'),
36887 bitsPerComponent: dict.get('BitsPerComponent'),
36888 bitsPerFlag: dict.get('BitsPerFlag'),
36889 decode: dict.getArray('Decode'),
36890 colorFn: fn,
36891 colorSpace: cs,
36892 numComps: fn ? 1 : cs.numComps
36893 };
36894 var reader = new MeshStreamReader(stream, decodeContext);
36895
36896 var patchMesh = false;
36897 switch (this.shadingType) {
36898 case ShadingType.FREE_FORM_MESH:
36899 decodeType4Shading(this, reader);
36900 break;
36901 case ShadingType.LATTICE_FORM_MESH:
36902 var verticesPerRow = dict.get('VerticesPerRow') | 0;
36903 assert(verticesPerRow >= 2, 'Invalid VerticesPerRow');
36904 decodeType5Shading(this, reader, verticesPerRow);
36905 break;
36906 case ShadingType.COONS_PATCH_MESH:
36907 decodeType6Shading(this, reader);
36908 patchMesh = true;
36909 break;
36910 case ShadingType.TENSOR_PATCH_MESH:
36911 decodeType7Shading(this, reader);
36912 patchMesh = true;
36913 break;
36914 default:
36915 error('Unsupported mesh type.');
36916 break;
36917 }
36918
36919 if (patchMesh) {
36920 // dirty bounds calculation for determining, how dense shall be triangles
36921 updateBounds(this);
36922 for (var i = 0, ii = this.figures.length; i < ii; i++) {
36923 buildFigureFromPatch(this, i);
36924 }
36925 }
36926 // calculate bounds
36927 updateBounds(this);
36928
36929 packData(this);
36930 }
36931
36932 Mesh.prototype = {
36933 getIR: function Mesh_getIR() {
36934 return ['Mesh', this.shadingType, this.coords, this.colors, this.figures,
36935 this.bounds, this.matrix, this.bbox, this.background];
36936 }
36937 };
36938
36939 return Mesh;
36940})();
36941
36942Shadings.Dummy = (function DummyClosure() {
36943 function Dummy() {
36944 this.type = 'Pattern';
36945 }
36946
36947 Dummy.prototype = {
36948 getIR: function Dummy_getIR() {
36949 return ['Dummy'];
36950 }
36951 };
36952 return Dummy;
36953})();
36954
36955function getTilingPatternIR(operatorList, dict, args) {
36956 var matrix = dict.getArray('Matrix');
36957 var bbox = dict.getArray('BBox');
36958 var xstep = dict.get('XStep');
36959 var ystep = dict.get('YStep');
36960 var paintType = dict.get('PaintType');
36961 var tilingType = dict.get('TilingType');
36962
36963 return [
36964 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep,
36965 paintType, tilingType
36966 ];
36967}
36968
36969exports.Pattern = Pattern;
36970exports.getTilingPatternIR = getTilingPatternIR;
36971}));
36972
36973
36974(function (root, factory) {
36975 {
36976 factory((root.pdfjsCoreEvaluator = {}), root.pdfjsSharedUtil,
36977 root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreParser,
36978 root.pdfjsCoreImage, root.pdfjsCoreColorSpace, root.pdfjsCoreMurmurHash3,
36979 root.pdfjsCoreFonts, root.pdfjsCoreFunction, root.pdfjsCorePattern,
36980 root.pdfjsCoreCMap, root.pdfjsCoreMetrics, root.pdfjsCoreBidi,
36981 root.pdfjsCoreEncodings, root.pdfjsCoreStandardFonts,
36982 root.pdfjsCoreUnicode, root.pdfjsCoreGlyphList);
36983 }
36984}(this, function (exports, sharedUtil, corePrimitives, coreStream, coreParser,
36985 coreImage, coreColorSpace, coreMurmurHash3, coreFonts,
36986 coreFunction, corePattern, coreCMap, coreMetrics, coreBidi,
36987 coreEncodings, coreStandardFonts, coreUnicode,
36988 coreGlyphList) {
36989
36990var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX;
36991var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX;
36992var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES;
36993var ImageKind = sharedUtil.ImageKind;
36994var OPS = sharedUtil.OPS;
36995var TextRenderingMode = sharedUtil.TextRenderingMode;
36996var Util = sharedUtil.Util;
36997var assert = sharedUtil.assert;
36998var createPromiseCapability = sharedUtil.createPromiseCapability;
36999var error = sharedUtil.error;
37000var info = sharedUtil.info;
37001var isArray = sharedUtil.isArray;
37002var isNum = sharedUtil.isNum;
37003var isString = sharedUtil.isString;
37004var getLookupTableFactory = sharedUtil.getLookupTableFactory;
37005var warn = sharedUtil.warn;
37006var Dict = corePrimitives.Dict;
37007var Name = corePrimitives.Name;
37008var isCmd = corePrimitives.isCmd;
37009var isDict = corePrimitives.isDict;
37010var isName = corePrimitives.isName;
37011var isRef = corePrimitives.isRef;
37012var isStream = corePrimitives.isStream;
37013var DecodeStream = coreStream.DecodeStream;
37014var JpegStream = coreStream.JpegStream;
37015var Stream = coreStream.Stream;
37016var Lexer = coreParser.Lexer;
37017var Parser = coreParser.Parser;
37018var isEOF = coreParser.isEOF;
37019var PDFImage = coreImage.PDFImage;
37020var ColorSpace = coreColorSpace.ColorSpace;
37021var MurmurHash3_64 = coreMurmurHash3.MurmurHash3_64;
37022var ErrorFont = coreFonts.ErrorFont;
37023var FontFlags = coreFonts.FontFlags;
37024var Font = coreFonts.Font;
37025var IdentityToUnicodeMap = coreFonts.IdentityToUnicodeMap;
37026var ToUnicodeMap = coreFonts.ToUnicodeMap;
37027var getFontType = coreFonts.getFontType;
37028var isPDFFunction = coreFunction.isPDFFunction;
37029var PDFFunction = coreFunction.PDFFunction;
37030var Pattern = corePattern.Pattern;
37031var getTilingPatternIR = corePattern.getTilingPatternIR;
37032var CMapFactory = coreCMap.CMapFactory;
37033var IdentityCMap = coreCMap.IdentityCMap;
37034var getMetrics = coreMetrics.getMetrics;
37035var bidi = coreBidi.bidi;
37036var WinAnsiEncoding = coreEncodings.WinAnsiEncoding;
37037var StandardEncoding = coreEncodings.StandardEncoding;
37038var MacRomanEncoding = coreEncodings.MacRomanEncoding;
37039var SymbolSetEncoding = coreEncodings.SymbolSetEncoding;
37040var ZapfDingbatsEncoding = coreEncodings.ZapfDingbatsEncoding;
37041var getEncoding = coreEncodings.getEncoding;
37042var getStdFontMap = coreStandardFonts.getStdFontMap;
37043var getSerifFonts = coreStandardFonts.getSerifFonts;
37044var getSymbolsFonts = coreStandardFonts.getSymbolsFonts;
37045var getNormalizedUnicodes = coreUnicode.getNormalizedUnicodes;
37046var reverseIfRtl = coreUnicode.reverseIfRtl;
37047var getUnicodeForGlyph = coreUnicode.getUnicodeForGlyph;
37048var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode;
37049
37050var PartialEvaluator = (function PartialEvaluatorClosure() {
37051 var DefaultPartialEvaluatorOptions = {
37052 forceDataSchema: false,
37053 maxImageSize: -1,
37054 disableFontFace: false,
37055 cMapOptions: { url: null, packed: false }
37056 };
37057
37058 function NativeImageDecoder(xref, resources, handler, forceDataSchema) {
37059 this.xref = xref;
37060 this.resources = resources;
37061 this.handler = handler;
37062 this.forceDataSchema = forceDataSchema;
37063 }
37064 NativeImageDecoder.prototype = {
37065 canDecode: function (image) {
37066 return image instanceof JpegStream &&
37067 NativeImageDecoder.isDecodable(image, this.xref, this.resources);
37068 },
37069 decode: function (image) {
37070 // For natively supported JPEGs send them to the main thread for decoding.
37071 var dict = image.dict;
37072 var colorSpace = dict.get('ColorSpace', 'CS');
37073 colorSpace = ColorSpace.parse(colorSpace, this.xref, this.resources);
37074 var numComps = colorSpace.numComps;
37075 var decodePromise = this.handler.sendWithPromise('JpegDecode',
37076 [image.getIR(this.forceDataSchema), numComps]);
37077 return decodePromise.then(function (message) {
37078 var data = message.data;
37079 return new Stream(data, 0, data.length, image.dict);
37080 });
37081 }
37082 };
37083 /**
37084 * Checks if the image can be decoded and displayed by the browser without any
37085 * further processing such as color space conversions.
37086 */
37087 NativeImageDecoder.isSupported =
37088 function NativeImageDecoder_isSupported(image, xref, res) {
37089 var dict = image.dict;
37090 if (dict.has('DecodeParms') || dict.has('DP')) {
37091 return false;
37092 }
37093 var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res);
37094 return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') &&
37095 cs.isDefaultDecode(dict.getArray('Decode', 'D'));
37096 };
37097 /**
37098 * Checks if the image can be decoded by the browser.
37099 */
37100 NativeImageDecoder.isDecodable =
37101 function NativeImageDecoder_isDecodable(image, xref, res) {
37102 var dict = image.dict;
37103 if (dict.has('DecodeParms') || dict.has('DP')) {
37104 return false;
37105 }
37106 var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res);
37107 return (cs.numComps === 1 || cs.numComps === 3) &&
37108 cs.isDefaultDecode(dict.getArray('Decode', 'D'));
37109 };
37110
37111 function PartialEvaluator(pdfManager, xref, handler, pageIndex,
37112 uniquePrefix, idCounters, fontCache, options) {
37113 this.pdfManager = pdfManager;
37114 this.xref = xref;
37115 this.handler = handler;
37116 this.pageIndex = pageIndex;
37117 this.uniquePrefix = uniquePrefix;
37118 this.idCounters = idCounters;
37119 this.fontCache = fontCache;
37120 this.options = options || DefaultPartialEvaluatorOptions;
37121 }
37122
37123 // Trying to minimize Date.now() usage and check every 100 time
37124 var TIME_SLOT_DURATION_MS = 20;
37125 var CHECK_TIME_EVERY = 100;
37126 function TimeSlotManager() {
37127 this.reset();
37128 }
37129 TimeSlotManager.prototype = {
37130 check: function TimeSlotManager_check() {
37131 if (++this.checked < CHECK_TIME_EVERY) {
37132 return false;
37133 }
37134 this.checked = 0;
37135 return this.endTime <= Date.now();
37136 },
37137 reset: function TimeSlotManager_reset() {
37138 this.endTime = Date.now() + TIME_SLOT_DURATION_MS;
37139 this.checked = 0;
37140 }
37141 };
37142
37143 var deferred = Promise.resolve();
37144
37145 var TILING_PATTERN = 1, SHADING_PATTERN = 2;
37146
37147 PartialEvaluator.prototype = {
37148 hasBlendModes: function PartialEvaluator_hasBlendModes(resources) {
37149 if (!isDict(resources)) {
37150 return false;
37151 }
37152
37153 var processed = Object.create(null);
37154 if (resources.objId) {
37155 processed[resources.objId] = true;
37156 }
37157
37158 var nodes = [resources], xref = this.xref;
37159 while (nodes.length) {
37160 var key, i, ii;
37161 var node = nodes.shift();
37162 // First check the current resources for blend modes.
37163 var graphicStates = node.get('ExtGState');
37164 if (isDict(graphicStates)) {
37165 var graphicStatesKeys = graphicStates.getKeys();
37166 for (i = 0, ii = graphicStatesKeys.length; i < ii; i++) {
37167 key = graphicStatesKeys[i];
37168
37169 var graphicState = graphicStates.get(key);
37170 var bm = graphicState.get('BM');
37171 if (isName(bm) && bm.name !== 'Normal') {
37172 return true;
37173 }
37174 }
37175 }
37176 // Descend into the XObjects to look for more resources and blend modes.
37177 var xObjects = node.get('XObject');
37178 if (!isDict(xObjects)) {
37179 continue;
37180 }
37181 var xObjectsKeys = xObjects.getKeys();
37182 for (i = 0, ii = xObjectsKeys.length; i < ii; i++) {
37183 key = xObjectsKeys[i];
37184
37185 var xObject = xObjects.getRaw(key);
37186 if (isRef(xObject)) {
37187 if (processed[xObject.toString()]) {
37188 // The XObject has already been processed, and by avoiding a
37189 // redundant `xref.fetch` we can *significantly* reduce the load
37190 // time for badly generated PDF files (fixes issue6961.pdf).
37191 continue;
37192 }
37193 xObject = xref.fetch(xObject);
37194 }
37195 if (!isStream(xObject)) {
37196 continue;
37197 }
37198 if (xObject.dict.objId) {
37199 if (processed[xObject.dict.objId]) {
37200 // stream has objId and is processed already
37201 continue;
37202 }
37203 processed[xObject.dict.objId] = true;
37204 }
37205 var xResources = xObject.dict.get('Resources');
37206 // Checking objId to detect an infinite loop.
37207 if (isDict(xResources) &&
37208 (!xResources.objId || !processed[xResources.objId])) {
37209 nodes.push(xResources);
37210 if (xResources.objId) {
37211 processed[xResources.objId] = true;
37212 }
37213 }
37214 }
37215 }
37216 return false;
37217 },
37218
37219 buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
37220 xobj, smask,
37221 operatorList,
37222 task,
37223 initialState) {
37224 var matrix = xobj.dict.getArray('Matrix');
37225 var bbox = xobj.dict.getArray('BBox');
37226 var group = xobj.dict.get('Group');
37227 if (group) {
37228 var groupOptions = {
37229 matrix: matrix,
37230 bbox: bbox,
37231 smask: smask,
37232 isolated: false,
37233 knockout: false
37234 };
37235
37236 var groupSubtype = group.get('S');
37237 var colorSpace;
37238 if (isName(groupSubtype, 'Transparency')) {
37239 groupOptions.isolated = (group.get('I') || false);
37240 groupOptions.knockout = (group.get('K') || false);
37241 colorSpace = (group.has('CS') ?
37242 ColorSpace.parse(group.get('CS'), this.xref, resources) : null);
37243 }
37244
37245 if (smask && smask.backdrop) {
37246 colorSpace = colorSpace || ColorSpace.singletons.rgb;
37247 smask.backdrop = colorSpace.getRgb(smask.backdrop, 0);
37248 }
37249
37250 operatorList.addOp(OPS.beginGroup, [groupOptions]);
37251 }
37252
37253 operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]);
37254
37255 return this.getOperatorList(xobj, task,
37256 (xobj.dict.get('Resources') || resources), operatorList, initialState).
37257 then(function () {
37258 operatorList.addOp(OPS.paintFormXObjectEnd, []);
37259
37260 if (group) {
37261 operatorList.addOp(OPS.endGroup, [groupOptions]);
37262 }
37263 });
37264 },
37265
37266 buildPaintImageXObject:
37267 function PartialEvaluator_buildPaintImageXObject(resources, image,
37268 inline, operatorList,
37269 cacheKey, imageCache) {
37270 var self = this;
37271 var dict = image.dict;
37272 var w = dict.get('Width', 'W');
37273 var h = dict.get('Height', 'H');
37274
37275 if (!(w && isNum(w)) || !(h && isNum(h))) {
37276 warn('Image dimensions are missing, or not numbers.');
37277 return;
37278 }
37279 var maxImageSize = this.options.maxImageSize;
37280 if (maxImageSize !== -1 && w * h > maxImageSize) {
37281 warn('Image exceeded maximum allowed size and was removed.');
37282 return;
37283 }
37284
37285 var imageMask = (dict.get('ImageMask', 'IM') || false);
37286 var imgData, args;
37287 if (imageMask) {
37288 // This depends on a tmpCanvas being filled with the
37289 // current fillStyle, such that processing the pixel
37290 // data can't be done here. Instead of creating a
37291 // complete PDFImage, only read the information needed
37292 // for later.
37293
37294 var width = dict.get('Width', 'W');
37295 var height = dict.get('Height', 'H');
37296 var bitStrideLength = (width + 7) >> 3;
37297 var imgArray = image.getBytes(bitStrideLength * height);
37298 var decode = dict.getArray('Decode', 'D');
37299 var inverseDecode = (!!decode && decode[0] > 0);
37300
37301 imgData = PDFImage.createMask(imgArray, width, height,
37302 image instanceof DecodeStream,
37303 inverseDecode);
37304 imgData.cached = true;
37305 args = [imgData];
37306 operatorList.addOp(OPS.paintImageMaskXObject, args);
37307 if (cacheKey) {
37308 imageCache[cacheKey] = {
37309 fn: OPS.paintImageMaskXObject,
37310 args: args
37311 };
37312 }
37313 return;
37314 }
37315
37316 var softMask = (dict.get('SMask', 'SM') || false);
37317 var mask = (dict.get('Mask') || false);
37318
37319 var SMALL_IMAGE_DIMENSIONS = 200;
37320 // Inlining small images into the queue as RGB data
37321 if (inline && !softMask && !mask && !(image instanceof JpegStream) &&
37322 (w + h) < SMALL_IMAGE_DIMENSIONS) {
37323 var imageObj = new PDFImage(this.xref, resources, image,
37324 inline, null, null);
37325 // We force the use of RGBA_32BPP images here, because we can't handle
37326 // any other kind.
37327 imgData = imageObj.createImageData(/* forceRGBA = */ true);
37328 operatorList.addOp(OPS.paintInlineImageXObject, [imgData]);
37329 return;
37330 }
37331
37332 // If there is no imageMask, create the PDFImage and a lot
37333 // of image processing can be done here.
37334 var uniquePrefix = (this.uniquePrefix || '');
37335 var objId = 'img_' + uniquePrefix + (++this.idCounters.obj);
37336 operatorList.addDependency(objId);
37337 args = [objId, w, h];
37338
37339 if (!softMask && !mask && image instanceof JpegStream &&
37340 NativeImageDecoder.isSupported(image, this.xref, resources)) {
37341 // These JPEGs don't need any more processing so we can just send it.
37342 operatorList.addOp(OPS.paintJpegXObject, args);
37343 this.handler.send('obj',
37344 [objId, this.pageIndex, 'JpegStream',
37345 image.getIR(this.options.forceDataSchema)]);
37346 return;
37347 }
37348
37349 // Creates native image decoder only if a JPEG image or mask is present.
37350 var nativeImageDecoder = null;
37351 if (image instanceof JpegStream || mask instanceof JpegStream ||
37352 softMask instanceof JpegStream) {
37353 nativeImageDecoder = new NativeImageDecoder(self.xref, resources,
37354 self.handler, self.options.forceDataSchema);
37355 }
37356
37357 PDFImage.buildImage(self.handler, self.xref, resources, image, inline,
37358 nativeImageDecoder).
37359 then(function(imageObj) {
37360 var imgData = imageObj.createImageData(/* forceRGBA = */ false);
37361 self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData],
37362 [imgData.data.buffer]);
37363 }).then(undefined, function (reason) {
37364 warn('Unable to decode image: ' + reason);
37365 self.handler.send('obj', [objId, self.pageIndex, 'Image', null]);
37366 });
37367
37368 operatorList.addOp(OPS.paintImageXObject, args);
37369 if (cacheKey) {
37370 imageCache[cacheKey] = {
37371 fn: OPS.paintImageXObject,
37372 args: args
37373 };
37374 }
37375 },
37376
37377 handleSMask: function PartialEvaluator_handleSmask(smask, resources,
37378 operatorList, task,
37379 stateManager) {
37380 var smaskContent = smask.get('G');
37381 var smaskOptions = {
37382 subtype: smask.get('S').name,
37383 backdrop: smask.get('BC')
37384 };
37385
37386 // The SMask might have a alpha/luminosity value transfer function --
37387 // we will build a map of integer values in range 0..255 to be fast.
37388 var transferObj = smask.get('TR');
37389 if (isPDFFunction(transferObj)) {
37390 var transferFn = PDFFunction.parse(this.xref, transferObj);
37391 var transferMap = new Uint8Array(256);
37392 var tmp = new Float32Array(1);
37393 for (var i = 0; i < 256; i++) {
37394 tmp[0] = i / 255;
37395 transferFn(tmp, 0, tmp, 0);
37396 transferMap[i] = (tmp[0] * 255) | 0;
37397 }
37398 smaskOptions.transferMap = transferMap;
37399 }
37400
37401 return this.buildFormXObject(resources, smaskContent, smaskOptions,
37402 operatorList, task, stateManager.state.clone());
37403 },
37404
37405 handleTilingType:
37406 function PartialEvaluator_handleTilingType(fn, args, resources,
37407 pattern, patternDict,
37408 operatorList, task) {
37409 // Create an IR of the pattern code.
37410 var tilingOpList = new OperatorList();
37411 // Merge the available resources, to prevent issues when the patternDict
37412 // is missing some /Resources entries (fixes issue6541.pdf).
37413 var resourcesArray = [patternDict.get('Resources'), resources];
37414 var patternResources = Dict.merge(this.xref, resourcesArray);
37415
37416 return this.getOperatorList(pattern, task, patternResources,
37417 tilingOpList).then(function () {
37418 // Add the dependencies to the parent operator list so they are
37419 // resolved before sub operator list is executed synchronously.
37420 operatorList.addDependencies(tilingOpList.dependencies);
37421 operatorList.addOp(fn, getTilingPatternIR({
37422 fnArray: tilingOpList.fnArray,
37423 argsArray: tilingOpList.argsArray
37424 }, patternDict, args));
37425 });
37426 },
37427
37428 handleSetFont:
37429 function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef,
37430 operatorList, task, state) {
37431 // TODO(mack): Not needed?
37432 var fontName;
37433 if (fontArgs) {
37434 fontArgs = fontArgs.slice();
37435 fontName = fontArgs[0].name;
37436 }
37437
37438 var self = this;
37439 return this.loadFont(fontName, fontRef, this.xref, resources).then(
37440 function (translated) {
37441 if (!translated.font.isType3Font) {
37442 return translated;
37443 }
37444 return translated.loadType3Data(self, resources, operatorList, task).
37445 then(function () {
37446 return translated;
37447 }, function (reason) {
37448 // Error in the font data -- sending unsupported feature notification.
37449 self.handler.send('UnsupportedFeature',
37450 {featureId: UNSUPPORTED_FEATURES.font});
37451 return new TranslatedFont('g_font_error',
37452 new ErrorFont('Type3 font load error: ' + reason), translated.font);
37453 });
37454 }).then(function (translated) {
37455 state.font = translated.font;
37456 translated.send(self.handler);
37457 return translated.loadedName;
37458 });
37459 },
37460
37461 handleText: function PartialEvaluator_handleText(chars, state) {
37462 var font = state.font;
37463 var glyphs = font.charsToGlyphs(chars);
37464 var isAddToPathSet = !!(state.textRenderingMode &
37465 TextRenderingMode.ADD_TO_PATH_FLAG);
37466 if (font.data && (isAddToPathSet || this.options.disableFontFace)) {
37467 var buildPath = function (fontChar) {
37468 if (!font.renderer.hasBuiltPath(fontChar)) {
37469 var path = font.renderer.getPathJs(fontChar);
37470 this.handler.send('commonobj', [
37471 font.loadedName + '_path_' + fontChar,
37472 'FontPath',
37473 path
37474 ]);
37475 }
37476 }.bind(this);
37477
37478 for (var i = 0, ii = glyphs.length; i < ii; i++) {
37479 var glyph = glyphs[i];
37480 buildPath(glyph.fontChar);
37481
37482 // If the glyph has an accent we need to build a path for its
37483 // fontChar too, otherwise CanvasGraphics_paintChar will fail.
37484 var accent = glyph.accent;
37485 if (accent && accent.fontChar) {
37486 buildPath(accent.fontChar);
37487 }
37488 }
37489 }
37490
37491 return glyphs;
37492 },
37493
37494 setGState: function PartialEvaluator_setGState(resources, gState,
37495 operatorList, task,
37496 xref, stateManager) {
37497 // This array holds the converted/processed state data.
37498 var gStateObj = [];
37499 var gStateKeys = gState.getKeys();
37500 var self = this;
37501 var promise = Promise.resolve();
37502 for (var i = 0, ii = gStateKeys.length; i < ii; i++) {
37503 var key = gStateKeys[i];
37504 var value = gState.get(key);
37505 switch (key) {
37506 case 'Type':
37507 break;
37508 case 'LW':
37509 case 'LC':
37510 case 'LJ':
37511 case 'ML':
37512 case 'D':
37513 case 'RI':
37514 case 'FL':
37515 case 'CA':
37516 case 'ca':
37517 gStateObj.push([key, value]);
37518 break;
37519 case 'Font':
37520 promise = promise.then(function () {
37521 return self.handleSetFont(resources, null, value[0], operatorList,
37522 task, stateManager.state).
37523 then(function (loadedName) {
37524 operatorList.addDependency(loadedName);
37525 gStateObj.push([key, [loadedName, value[1]]]);
37526 });
37527 });
37528 break;
37529 case 'BM':
37530 gStateObj.push([key, value]);
37531 break;
37532 case 'SMask':
37533 if (isName(value, 'None')) {
37534 gStateObj.push([key, false]);
37535 break;
37536 }
37537 if (isDict(value)) {
37538 promise = promise.then(function (dict) {
37539 return self.handleSMask(dict, resources, operatorList,
37540 task, stateManager);
37541 }.bind(this, value));
37542 gStateObj.push([key, true]);
37543 } else {
37544 warn('Unsupported SMask type');
37545 }
37546
37547 break;
37548 // Only generate info log messages for the following since
37549 // they are unlikely to have a big impact on the rendering.
37550 case 'OP':
37551 case 'op':
37552 case 'OPM':
37553 case 'BG':
37554 case 'BG2':
37555 case 'UCR':
37556 case 'UCR2':
37557 case 'TR':
37558 case 'TR2':
37559 case 'HT':
37560 case 'SM':
37561 case 'SA':
37562 case 'AIS':
37563 case 'TK':
37564 // TODO implement these operators.
37565 info('graphic state operator ' + key);
37566 break;
37567 default:
37568 info('Unknown graphic state operator ' + key);
37569 break;
37570 }
37571 }
37572 return promise.then(function () {
37573 if (gStateObj.length > 0) {
37574 operatorList.addOp(OPS.setGState, [gStateObj]);
37575 }
37576 });
37577 },
37578
37579 loadFont: function PartialEvaluator_loadFont(fontName, font, xref,
37580 resources) {
37581
37582 function errorFont() {
37583 return Promise.resolve(new TranslatedFont('g_font_error',
37584 new ErrorFont('Font ' + fontName + ' is not available'), font));
37585 }
37586 var fontRef;
37587 if (font) { // Loading by ref.
37588 assert(isRef(font));
37589 fontRef = font;
37590 } else { // Loading by name.
37591 var fontRes = resources.get('Font');
37592 if (fontRes) {
37593 fontRef = fontRes.getRaw(fontName);
37594 } else {
37595 warn('fontRes not available');
37596 return errorFont();
37597 }
37598 }
37599 if (!fontRef) {
37600 warn('fontRef not available');
37601 return errorFont();
37602 }
37603
37604 if (this.fontCache.has(fontRef)) {
37605 return this.fontCache.get(fontRef);
37606 }
37607
37608 font = xref.fetchIfRef(fontRef);
37609 if (!isDict(font)) {
37610 return errorFont();
37611 }
37612
37613 // We are holding `font.translated` references just for `fontRef`s that
37614 // are not actually `Ref`s, but rather `Dict`s. See explanation below.
37615 if (font.translated) {
37616 return font.translated;
37617 }
37618
37619 var fontCapability = createPromiseCapability();
37620
37621 var preEvaluatedFont = this.preEvaluateFont(font, xref);
37622 var descriptor = preEvaluatedFont.descriptor;
37623
37624 var fontRefIsRef = isRef(fontRef), fontID;
37625 if (fontRefIsRef) {
37626 fontID = fontRef.toString();
37627 }
37628
37629 if (isDict(descriptor)) {
37630 if (!descriptor.fontAliases) {
37631 descriptor.fontAliases = Object.create(null);
37632 }
37633
37634 var fontAliases = descriptor.fontAliases;
37635 var hash = preEvaluatedFont.hash;
37636 if (fontAliases[hash]) {
37637 var aliasFontRef = fontAliases[hash].aliasRef;
37638 if (fontRefIsRef && aliasFontRef &&
37639 this.fontCache.has(aliasFontRef)) {
37640 this.fontCache.putAlias(fontRef, aliasFontRef);
37641 return this.fontCache.get(fontRef);
37642 }
37643 } else {
37644 fontAliases[hash] = {
37645 fontID: Font.getFontID()
37646 };
37647 }
37648
37649 if (fontRefIsRef) {
37650 fontAliases[hash].aliasRef = fontRef;
37651 }
37652 fontID = fontAliases[hash].fontID;
37653 }
37654
37655 // Workaround for bad PDF generators that reference fonts incorrectly,
37656 // where `fontRef` is a `Dict` rather than a `Ref` (fixes bug946506.pdf).
37657 // In this case we should not put the font into `this.fontCache` (which is
37658 // a `RefSetCache`), since it's not meaningful to use a `Dict` as a key.
37659 //
37660 // However, if we don't cache the font it's not possible to remove it
37661 // when `cleanup` is triggered from the API, which causes issues on
37662 // subsequent rendering operations (see issue7403.pdf).
37663 // A simple workaround would be to just not hold `font.translated`
37664 // references in this case, but this would force us to unnecessarily load
37665 // the same fonts over and over.
37666 //
37667 // Instead, we cheat a bit by attempting to use a modified `fontID` as a
37668 // key in `this.fontCache`, to allow the font to be cached.
37669 // NOTE: This works because `RefSetCache` calls `toString()` on provided
37670 // keys. Also, since `fontRef` is used when getting cached fonts,
37671 // we'll not accidentally match fonts cached with the `fontID`.
37672 if (fontRefIsRef) {
37673 this.fontCache.put(fontRef, fontCapability.promise);
37674 } else {
37675 if (!fontID) {
37676 fontID = (this.uniquePrefix || 'F_') + (++this.idCounters.obj);
37677 }
37678 this.fontCache.put('id_' + fontID, fontCapability.promise);
37679 }
37680 assert(fontID, 'The "fontID" must be defined.');
37681
37682 // Keep track of each font we translated so the caller can
37683 // load them asynchronously before calling display on a page.
37684 font.loadedName = 'g_' + this.pdfManager.docId + '_f' + fontID;
37685
37686 font.translated = fontCapability.promise;
37687
37688 // TODO move promises into translate font
37689 var translatedPromise;
37690 try {
37691 translatedPromise = this.translateFont(preEvaluatedFont, xref);
37692 } catch (e) {
37693 translatedPromise = Promise.reject(e);
37694 }
37695
37696 var self = this;
37697 translatedPromise.then(function (translatedFont) {
37698 if (translatedFont.fontType !== undefined) {
37699 var xrefFontStats = xref.stats.fontTypes;
37700 xrefFontStats[translatedFont.fontType] = true;
37701 }
37702
37703 fontCapability.resolve(new TranslatedFont(font.loadedName,
37704 translatedFont, font));
37705 }, function (reason) {
37706 // TODO fontCapability.reject?
37707 // Error in the font data -- sending unsupported feature notification.
37708 self.handler.send('UnsupportedFeature',
37709 {featureId: UNSUPPORTED_FEATURES.font});
37710
37711 try {
37712 // error, but it's still nice to have font type reported
37713 var descriptor = preEvaluatedFont.descriptor;
37714 var fontFile3 = descriptor && descriptor.get('FontFile3');
37715 var subtype = fontFile3 && fontFile3.get('Subtype');
37716 var fontType = getFontType(preEvaluatedFont.type,
37717 subtype && subtype.name);
37718 var xrefFontStats = xref.stats.fontTypes;
37719 xrefFontStats[fontType] = true;
37720 } catch (ex) { }
37721
37722 fontCapability.resolve(new TranslatedFont(font.loadedName,
37723 new ErrorFont(reason instanceof Error ? reason.message : reason),
37724 font));
37725 });
37726 return fontCapability.promise;
37727 },
37728
37729 buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) {
37730 var lastIndex = operatorList.length - 1;
37731 if (!args) {
37732 args = [];
37733 }
37734 if (lastIndex < 0 ||
37735 operatorList.fnArray[lastIndex] !== OPS.constructPath) {
37736 operatorList.addOp(OPS.constructPath, [[fn], args]);
37737 } else {
37738 var opArgs = operatorList.argsArray[lastIndex];
37739 opArgs[0].push(fn);
37740 Array.prototype.push.apply(opArgs[1], args);
37741 }
37742 },
37743
37744 handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args,
37745 cs, patterns, resources, task, xref) {
37746 // compile tiling patterns
37747 var patternName = args[args.length - 1];
37748 // SCN/scn applies patterns along with normal colors
37749 var pattern;
37750 if (isName(patternName) &&
37751 (pattern = patterns.get(patternName.name))) {
37752 var dict = (isStream(pattern) ? pattern.dict : pattern);
37753 var typeNum = dict.get('PatternType');
37754
37755 if (typeNum === TILING_PATTERN) {
37756 var color = cs.base ? cs.base.getRgb(args, 0) : null;
37757 return this.handleTilingType(fn, color, resources, pattern,
37758 dict, operatorList, task);
37759 } else if (typeNum === SHADING_PATTERN) {
37760 var shading = dict.get('Shading');
37761 var matrix = dict.getArray('Matrix');
37762 pattern = Pattern.parseShading(shading, matrix, xref, resources,
37763 this.handler);
37764 operatorList.addOp(fn, pattern.getIR());
37765 return Promise.resolve();
37766 } else {
37767 return Promise.reject('Unknown PatternType: ' + typeNum);
37768 }
37769 }
37770 // TODO shall we fail here?
37771 operatorList.addOp(fn, args);
37772 return Promise.resolve();
37773 },
37774
37775 getOperatorList: function PartialEvaluator_getOperatorList(stream,
37776 task,
37777 resources,
37778 operatorList,
37779 initialState) {
37780
37781 var self = this;
37782 var xref = this.xref;
37783 var imageCache = Object.create(null);
37784
37785 assert(operatorList);
37786
37787 resources = (resources || Dict.empty);
37788 var xobjs = (resources.get('XObject') || Dict.empty);
37789 var patterns = (resources.get('Pattern') || Dict.empty);
37790 var stateManager = new StateManager(initialState || new EvalState());
37791 var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
37792 var timeSlotManager = new TimeSlotManager();
37793
37794 return new Promise(function promiseBody(resolve, reject) {
37795 var next = function (promise) {
37796 promise.then(function () {
37797 try {
37798 promiseBody(resolve, reject);
37799 } catch (ex) {
37800 reject(ex);
37801 }
37802 }, reject);
37803 };
37804 task.ensureNotTerminated();
37805 timeSlotManager.reset();
37806 var stop, operation = {}, i, ii, cs;
37807 while (!(stop = timeSlotManager.check())) {
37808 // The arguments parsed by read() are used beyond this loop, so we
37809 // cannot reuse the same array on each iteration. Therefore we pass
37810 // in |null| as the initial value (see the comment on
37811 // EvaluatorPreprocessor_read() for why).
37812 operation.args = null;
37813 if (!(preprocessor.read(operation))) {
37814 break;
37815 }
37816 var args = operation.args;
37817 var fn = operation.fn;
37818
37819 switch (fn | 0) {
37820 case OPS.paintXObject:
37821 if (args[0].code) {
37822 break;
37823 }
37824 // eagerly compile XForm objects
37825 var name = args[0].name;
37826 if (!name) {
37827 warn('XObject must be referred to by name.');
37828 continue;
37829 }
37830 if (imageCache[name] !== undefined) {
37831 operatorList.addOp(imageCache[name].fn, imageCache[name].args);
37832 args = null;
37833 continue;
37834 }
37835
37836 var xobj = xobjs.get(name);
37837 if (xobj) {
37838 assert(isStream(xobj), 'XObject should be a stream');
37839
37840 var type = xobj.dict.get('Subtype');
37841 assert(isName(type), 'XObject should have a Name subtype');
37842
37843 if (type.name === 'Form') {
37844 stateManager.save();
37845 next(self.buildFormXObject(resources, xobj, null,
37846 operatorList, task,
37847 stateManager.state.clone()).
37848 then(function () {
37849 stateManager.restore();
37850 }));
37851 return;
37852 } else if (type.name === 'Image') {
37853 self.buildPaintImageXObject(resources, xobj, false,
37854 operatorList, name, imageCache);
37855 args = null;
37856 continue;
37857 } else if (type.name === 'PS') {
37858 // PostScript XObjects are unused when viewing documents.
37859 // See section 4.7.1 of Adobe's PDF reference.
37860 info('Ignored XObject subtype PS');
37861 continue;
37862 } else {
37863 error('Unhandled XObject subtype ' + type.name);
37864 }
37865 }
37866 break;
37867 case OPS.setFont:
37868 var fontSize = args[1];
37869 // eagerly collect all fonts
37870 next(self.handleSetFont(resources, args, null, operatorList,
37871 task, stateManager.state).
37872 then(function (loadedName) {
37873 operatorList.addDependency(loadedName);
37874 operatorList.addOp(OPS.setFont, [loadedName, fontSize]);
37875 }));
37876 return;
37877 case OPS.endInlineImage:
37878 var cacheKey = args[0].cacheKey;
37879 if (cacheKey) {
37880 var cacheEntry = imageCache[cacheKey];
37881 if (cacheEntry !== undefined) {
37882 operatorList.addOp(cacheEntry.fn, cacheEntry.args);
37883 args = null;
37884 continue;
37885 }
37886 }
37887 self.buildPaintImageXObject(resources, args[0], true,
37888 operatorList, cacheKey, imageCache);
37889 args = null;
37890 continue;
37891 case OPS.showText:
37892 args[0] = self.handleText(args[0], stateManager.state);
37893 break;
37894 case OPS.showSpacedText:
37895 var arr = args[0];
37896 var combinedGlyphs = [];
37897 var arrLength = arr.length;
37898 var state = stateManager.state;
37899 for (i = 0; i < arrLength; ++i) {
37900 var arrItem = arr[i];
37901 if (isString(arrItem)) {
37902 Array.prototype.push.apply(combinedGlyphs,
37903 self.handleText(arrItem, state));
37904 } else if (isNum(arrItem)) {
37905 combinedGlyphs.push(arrItem);
37906 }
37907 }
37908 args[0] = combinedGlyphs;
37909 fn = OPS.showText;
37910 break;
37911 case OPS.nextLineShowText:
37912 operatorList.addOp(OPS.nextLine);
37913 args[0] = self.handleText(args[0], stateManager.state);
37914 fn = OPS.showText;
37915 break;
37916 case OPS.nextLineSetSpacingShowText:
37917 operatorList.addOp(OPS.nextLine);
37918 operatorList.addOp(OPS.setWordSpacing, [args.shift()]);
37919 operatorList.addOp(OPS.setCharSpacing, [args.shift()]);
37920 args[0] = self.handleText(args[0], stateManager.state);
37921 fn = OPS.showText;
37922 break;
37923 case OPS.setTextRenderingMode:
37924 stateManager.state.textRenderingMode = args[0];
37925 break;
37926
37927 case OPS.setFillColorSpace:
37928 stateManager.state.fillColorSpace =
37929 ColorSpace.parse(args[0], xref, resources);
37930 continue;
37931 case OPS.setStrokeColorSpace:
37932 stateManager.state.strokeColorSpace =
37933 ColorSpace.parse(args[0], xref, resources);
37934 continue;
37935 case OPS.setFillColor:
37936 cs = stateManager.state.fillColorSpace;
37937 args = cs.getRgb(args, 0);
37938 fn = OPS.setFillRGBColor;
37939 break;
37940 case OPS.setStrokeColor:
37941 cs = stateManager.state.strokeColorSpace;
37942 args = cs.getRgb(args, 0);
37943 fn = OPS.setStrokeRGBColor;
37944 break;
37945 case OPS.setFillGray:
37946 stateManager.state.fillColorSpace = ColorSpace.singletons.gray;
37947 args = ColorSpace.singletons.gray.getRgb(args, 0);
37948 fn = OPS.setFillRGBColor;
37949 break;
37950 case OPS.setStrokeGray:
37951 stateManager.state.strokeColorSpace = ColorSpace.singletons.gray;
37952 args = ColorSpace.singletons.gray.getRgb(args, 0);
37953 fn = OPS.setStrokeRGBColor;
37954 break;
37955 case OPS.setFillCMYKColor:
37956 stateManager.state.fillColorSpace = ColorSpace.singletons.cmyk;
37957 args = ColorSpace.singletons.cmyk.getRgb(args, 0);
37958 fn = OPS.setFillRGBColor;
37959 break;
37960 case OPS.setStrokeCMYKColor:
37961 stateManager.state.strokeColorSpace = ColorSpace.singletons.cmyk;
37962 args = ColorSpace.singletons.cmyk.getRgb(args, 0);
37963 fn = OPS.setStrokeRGBColor;
37964 break;
37965 case OPS.setFillRGBColor:
37966 stateManager.state.fillColorSpace = ColorSpace.singletons.rgb;
37967 args = ColorSpace.singletons.rgb.getRgb(args, 0);
37968 break;
37969 case OPS.setStrokeRGBColor:
37970 stateManager.state.strokeColorSpace = ColorSpace.singletons.rgb;
37971 args = ColorSpace.singletons.rgb.getRgb(args, 0);
37972 break;
37973 case OPS.setFillColorN:
37974 cs = stateManager.state.fillColorSpace;
37975 if (cs.name === 'Pattern') {
37976 next(self.handleColorN(operatorList, OPS.setFillColorN, args,
37977 cs, patterns, resources, task, xref));
37978 return;
37979 }
37980 args = cs.getRgb(args, 0);
37981 fn = OPS.setFillRGBColor;
37982 break;
37983 case OPS.setStrokeColorN:
37984 cs = stateManager.state.strokeColorSpace;
37985 if (cs.name === 'Pattern') {
37986 next(self.handleColorN(operatorList, OPS.setStrokeColorN, args,
37987 cs, patterns, resources, task, xref));
37988 return;
37989 }
37990 args = cs.getRgb(args, 0);
37991 fn = OPS.setStrokeRGBColor;
37992 break;
37993
37994 case OPS.shadingFill:
37995 var shadingRes = resources.get('Shading');
37996 if (!shadingRes) {
37997 error('No shading resource found');
37998 }
37999
38000 var shading = shadingRes.get(args[0].name);
38001 if (!shading) {
38002 error('No shading object found');
38003 }
38004
38005 var shadingFill = Pattern.parseShading(shading, null, xref,
38006 resources, self.handler);
38007 var patternIR = shadingFill.getIR();
38008 args = [patternIR];
38009 fn = OPS.shadingFill;
38010 break;
38011 case OPS.setGState:
38012 var dictName = args[0];
38013 var extGState = resources.get('ExtGState');
38014
38015 if (!isDict(extGState) || !extGState.has(dictName.name)) {
38016 break;
38017 }
38018
38019 var gState = extGState.get(dictName.name);
38020 next(self.setGState(resources, gState, operatorList, task, xref,
38021 stateManager));
38022 return;
38023 case OPS.moveTo:
38024 case OPS.lineTo:
38025 case OPS.curveTo:
38026 case OPS.curveTo2:
38027 case OPS.curveTo3:
38028 case OPS.closePath:
38029 self.buildPath(operatorList, fn, args);
38030 continue;
38031 case OPS.rectangle:
38032 self.buildPath(operatorList, fn, args);
38033 continue;
38034 case OPS.markPoint:
38035 case OPS.markPointProps:
38036 case OPS.beginMarkedContent:
38037 case OPS.beginMarkedContentProps:
38038 case OPS.endMarkedContent:
38039 case OPS.beginCompat:
38040 case OPS.endCompat:
38041 // Ignore operators where the corresponding handlers are known to
38042 // be no-op in CanvasGraphics (display/canvas.js). This prevents
38043 // serialization errors and is also a bit more efficient.
38044 // We could also try to serialize all objects in a general way,
38045 // e.g. as done in https://github.com/mozilla/pdf.js/pull/6266,
38046 // but doing so is meaningless without knowing the semantics.
38047 continue;
38048 default:
38049 // Note: Ignore the operator if it has `Dict` arguments, since
38050 // those are non-serializable, otherwise postMessage will throw
38051 // "An object could not be cloned.".
38052 if (args !== null) {
38053 for (i = 0, ii = args.length; i < ii; i++) {
38054 if (args[i] instanceof Dict) {
38055 break;
38056 }
38057 }
38058 if (i < ii) {
38059 warn('getOperatorList - ignoring operator: ' + fn);
38060 continue;
38061 }
38062 }
38063 }
38064 operatorList.addOp(fn, args);
38065 }
38066 if (stop) {
38067 next(deferred);
38068 return;
38069 }
38070 // Some PDFs don't close all restores inside object/form.
38071 // Closing those for them.
38072 for (i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
38073 operatorList.addOp(OPS.restore, []);
38074 }
38075 resolve();
38076 });
38077 },
38078
38079 getTextContent:
38080 function PartialEvaluator_getTextContent(stream, task, resources,
38081 stateManager,
38082 normalizeWhitespace,
38083 combineTextItems) {
38084
38085 stateManager = (stateManager || new StateManager(new TextState()));
38086
38087 var WhitespaceRegexp = /\s/g;
38088
38089 var textContent = {
38090 items: [],
38091 styles: Object.create(null)
38092 };
38093 var textContentItem = {
38094 initialized: false,
38095 str: [],
38096 width: 0,
38097 height: 0,
38098 vertical: false,
38099 lastAdvanceWidth: 0,
38100 lastAdvanceHeight: 0,
38101 textAdvanceScale: 0,
38102 spaceWidth: 0,
38103 fakeSpaceMin: Infinity,
38104 fakeMultiSpaceMin: Infinity,
38105 fakeMultiSpaceMax: -0,
38106 textRunBreakAllowed: false,
38107 transform: null,
38108 fontName: null
38109 };
38110 var SPACE_FACTOR = 0.3;
38111 var MULTI_SPACE_FACTOR = 1.5;
38112 var MULTI_SPACE_FACTOR_MAX = 4;
38113
38114 var self = this;
38115 var xref = this.xref;
38116
38117 resources = (xref.fetchIfRef(resources) || Dict.empty);
38118
38119 // The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
38120 var xobjs = null;
38121 var xobjsCache = Object.create(null);
38122
38123 var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
38124
38125 var textState;
38126
38127 function ensureTextContentItem() {
38128 if (textContentItem.initialized) {
38129 return textContentItem;
38130 }
38131 var font = textState.font;
38132 if (!(font.loadedName in textContent.styles)) {
38133 textContent.styles[font.loadedName] = {
38134 fontFamily: font.fallbackName,
38135 ascent: font.ascent,
38136 descent: font.descent,
38137 vertical: font.vertical
38138 };
38139 }
38140 textContentItem.fontName = font.loadedName;
38141
38142 // 9.4.4 Text Space Details
38143 var tsm = [textState.fontSize * textState.textHScale, 0,
38144 0, textState.fontSize,
38145 0, textState.textRise];
38146
38147 if (font.isType3Font &&
38148 textState.fontMatrix !== FONT_IDENTITY_MATRIX &&
38149 textState.fontSize === 1) {
38150 var glyphHeight = font.bbox[3] - font.bbox[1];
38151 if (glyphHeight > 0) {
38152 glyphHeight = glyphHeight * textState.fontMatrix[3];
38153 tsm[3] *= glyphHeight;
38154 }
38155 }
38156
38157 var trm = Util.transform(textState.ctm,
38158 Util.transform(textState.textMatrix, tsm));
38159 textContentItem.transform = trm;
38160 if (!font.vertical) {
38161 textContentItem.width = 0;
38162 textContentItem.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]);
38163 textContentItem.vertical = false;
38164 } else {
38165 textContentItem.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]);
38166 textContentItem.height = 0;
38167 textContentItem.vertical = true;
38168 }
38169
38170 var a = textState.textLineMatrix[0];
38171 var b = textState.textLineMatrix[1];
38172 var scaleLineX = Math.sqrt(a * a + b * b);
38173 a = textState.ctm[0];
38174 b = textState.ctm[1];
38175 var scaleCtmX = Math.sqrt(a * a + b * b);
38176 textContentItem.textAdvanceScale = scaleCtmX * scaleLineX;
38177 textContentItem.lastAdvanceWidth = 0;
38178 textContentItem.lastAdvanceHeight = 0;
38179
38180 var spaceWidth = font.spaceWidth / 1000 * textState.fontSize;
38181 if (spaceWidth) {
38182 textContentItem.spaceWidth = spaceWidth;
38183 textContentItem.fakeSpaceMin = spaceWidth * SPACE_FACTOR;
38184 textContentItem.fakeMultiSpaceMin = spaceWidth * MULTI_SPACE_FACTOR;
38185 textContentItem.fakeMultiSpaceMax =
38186 spaceWidth * MULTI_SPACE_FACTOR_MAX;
38187 // It's okay for monospace fonts to fake as much space as needed.
38188 textContentItem.textRunBreakAllowed = !font.isMonospace;
38189 } else {
38190 textContentItem.spaceWidth = 0;
38191 textContentItem.fakeSpaceMin = Infinity;
38192 textContentItem.fakeMultiSpaceMin = Infinity;
38193 textContentItem.fakeMultiSpaceMax = 0;
38194 textContentItem.textRunBreakAllowed = false;
38195 }
38196
38197
38198 textContentItem.initialized = true;
38199 return textContentItem;
38200 }
38201
38202 function replaceWhitespace(str) {
38203 // Replaces all whitespaces with standard spaces (0x20), to avoid
38204 // alignment issues between the textLayer and the canvas if the text
38205 // contains e.g. tabs (fixes issue6612.pdf).
38206 var i = 0, ii = str.length, code;
38207 while (i < ii && (code = str.charCodeAt(i)) >= 0x20 && code <= 0x7F) {
38208 i++;
38209 }
38210 return (i < ii ? str.replace(WhitespaceRegexp, ' ') : str);
38211 }
38212
38213 function runBidiTransform(textChunk) {
38214 var str = textChunk.str.join('');
38215 var bidiResult = bidi(str, -1, textChunk.vertical);
38216 return {
38217 str: (normalizeWhitespace ? replaceWhitespace(bidiResult.str) :
38218 bidiResult.str),
38219 dir: bidiResult.dir,
38220 width: textChunk.width,
38221 height: textChunk.height,
38222 transform: textChunk.transform,
38223 fontName: textChunk.fontName
38224 };
38225 }
38226
38227 function handleSetFont(fontName, fontRef) {
38228 return self.loadFont(fontName, fontRef, xref, resources).
38229 then(function (translated) {
38230 textState.font = translated.font;
38231 textState.fontMatrix = translated.font.fontMatrix ||
38232 FONT_IDENTITY_MATRIX;
38233 });
38234 }
38235
38236 function buildTextContentItem(chars) {
38237 var font = textState.font;
38238 var textChunk = ensureTextContentItem();
38239 var width = 0;
38240 var height = 0;
38241 var glyphs = font.charsToGlyphs(chars);
38242 var defaultVMetrics = font.defaultVMetrics;
38243 for (var i = 0; i < glyphs.length; i++) {
38244 var glyph = glyphs[i];
38245 var vMetricX = null;
38246 var vMetricY = null;
38247 var glyphWidth = null;
38248 if (font.vertical) {
38249 if (glyph.vmetric) {
38250 glyphWidth = glyph.vmetric[0];
38251 vMetricX = glyph.vmetric[1];
38252 vMetricY = glyph.vmetric[2];
38253 } else {
38254 glyphWidth = glyph.width;
38255 vMetricX = glyph.width * 0.5;
38256 vMetricY = defaultVMetrics[2];
38257 }
38258 } else {
38259 glyphWidth = glyph.width;
38260 }
38261
38262 var glyphUnicode = glyph.unicode;
38263 var NormalizedUnicodes = getNormalizedUnicodes();
38264 if (NormalizedUnicodes[glyphUnicode] !== undefined) {
38265 glyphUnicode = NormalizedUnicodes[glyphUnicode];
38266 }
38267 glyphUnicode = reverseIfRtl(glyphUnicode);
38268
38269 // The following will calculate the x and y of the individual glyphs.
38270 // if (font.vertical) {
38271 // tsm[4] -= vMetricX * Math.abs(textState.fontSize) *
38272 // textState.fontMatrix[0];
38273 // tsm[5] -= vMetricY * textState.fontSize *
38274 // textState.fontMatrix[0];
38275 // }
38276 // var trm = Util.transform(textState.textMatrix, tsm);
38277 // var pt = Util.applyTransform([trm[4], trm[5]], textState.ctm);
38278 // var x = pt[0];
38279 // var y = pt[1];
38280
38281 var charSpacing = textState.charSpacing;
38282 if (glyph.isSpace) {
38283 var wordSpacing = textState.wordSpacing;
38284 charSpacing += wordSpacing;
38285 if (wordSpacing > 0) {
38286 addFakeSpaces(wordSpacing, textChunk.str);
38287 }
38288 }
38289
38290 var tx = 0;
38291 var ty = 0;
38292 if (!font.vertical) {
38293 var w0 = glyphWidth * textState.fontMatrix[0];
38294 tx = (w0 * textState.fontSize + charSpacing) *
38295 textState.textHScale;
38296 width += tx;
38297 } else {
38298 var w1 = glyphWidth * textState.fontMatrix[0];
38299 ty = w1 * textState.fontSize + charSpacing;
38300 height += ty;
38301 }
38302 textState.translateTextMatrix(tx, ty);
38303
38304 textChunk.str.push(glyphUnicode);
38305 }
38306
38307 if (!font.vertical) {
38308 textChunk.lastAdvanceWidth = width;
38309 textChunk.width += width * textChunk.textAdvanceScale;
38310 } else {
38311 textChunk.lastAdvanceHeight = height;
38312 textChunk.height += Math.abs(height * textChunk.textAdvanceScale);
38313 }
38314
38315 return textChunk;
38316 }
38317
38318 function addFakeSpaces(width, strBuf) {
38319 if (width < textContentItem.fakeSpaceMin) {
38320 return;
38321 }
38322 if (width < textContentItem.fakeMultiSpaceMin) {
38323 strBuf.push(' ');
38324 return;
38325 }
38326 var fakeSpaces = Math.round(width / textContentItem.spaceWidth);
38327 while (fakeSpaces-- > 0) {
38328 strBuf.push(' ');
38329 }
38330 }
38331
38332 function flushTextContentItem() {
38333 if (!textContentItem.initialized) {
38334 return;
38335 }
38336 textContent.items.push(runBidiTransform(textContentItem));
38337
38338 textContentItem.initialized = false;
38339 textContentItem.str.length = 0;
38340 }
38341
38342 var timeSlotManager = new TimeSlotManager();
38343
38344 return new Promise(function promiseBody(resolve, reject) {
38345 var next = function (promise) {
38346 promise.then(function () {
38347 try {
38348 promiseBody(resolve, reject);
38349 } catch (ex) {
38350 reject(ex);
38351 }
38352 }, reject);
38353 };
38354 task.ensureNotTerminated();
38355 timeSlotManager.reset();
38356 var stop, operation = {}, args = [];
38357 while (!(stop = timeSlotManager.check())) {
38358 // The arguments parsed by read() are not used beyond this loop, so
38359 // we can reuse the same array on every iteration, thus avoiding
38360 // unnecessary allocations.
38361 args.length = 0;
38362 operation.args = args;
38363 if (!(preprocessor.read(operation))) {
38364 break;
38365 }
38366 textState = stateManager.state;
38367 var fn = operation.fn;
38368 args = operation.args;
38369 var advance, diff;
38370
38371 switch (fn | 0) {
38372 case OPS.setFont:
38373 // Optimization to ignore multiple identical Tf commands.
38374 var fontNameArg = args[0].name, fontSizeArg = args[1];
38375 if (textState.font && fontNameArg === textState.fontName &&
38376 fontSizeArg === textState.fontSize) {
38377 break;
38378 }
38379
38380 flushTextContentItem();
38381 textState.fontName = fontNameArg;
38382 textState.fontSize = fontSizeArg;
38383 next(handleSetFont(fontNameArg, null));
38384 return;
38385 case OPS.setTextRise:
38386 flushTextContentItem();
38387 textState.textRise = args[0];
38388 break;
38389 case OPS.setHScale:
38390 flushTextContentItem();
38391 textState.textHScale = args[0] / 100;
38392 break;
38393 case OPS.setLeading:
38394 flushTextContentItem();
38395 textState.leading = args[0];
38396 break;
38397 case OPS.moveText:
38398 // Optimization to treat same line movement as advance
38399 var isSameTextLine = !textState.font ? false :
38400 ((textState.font.vertical ? args[0] : args[1]) === 0);
38401 advance = args[0] - args[1];
38402 if (combineTextItems &&
38403 isSameTextLine && textContentItem.initialized &&
38404 advance > 0 &&
38405 advance <= textContentItem.fakeMultiSpaceMax) {
38406 textState.translateTextLineMatrix(args[0], args[1]);
38407 textContentItem.width +=
38408 (args[0] - textContentItem.lastAdvanceWidth);
38409 textContentItem.height +=
38410 (args[1] - textContentItem.lastAdvanceHeight);
38411 diff = (args[0] - textContentItem.lastAdvanceWidth) -
38412 (args[1] - textContentItem.lastAdvanceHeight);
38413 addFakeSpaces(diff, textContentItem.str);
38414 break;
38415 }
38416
38417 flushTextContentItem();
38418 textState.translateTextLineMatrix(args[0], args[1]);
38419 textState.textMatrix = textState.textLineMatrix.slice();
38420 break;
38421 case OPS.setLeadingMoveText:
38422 flushTextContentItem();
38423 textState.leading = -args[1];
38424 textState.translateTextLineMatrix(args[0], args[1]);
38425 textState.textMatrix = textState.textLineMatrix.slice();
38426 break;
38427 case OPS.nextLine:
38428 flushTextContentItem();
38429 textState.carriageReturn();
38430 break;
38431 case OPS.setTextMatrix:
38432 // Optimization to treat same line movement as advance.
38433 advance = textState.calcTextLineMatrixAdvance(
38434 args[0], args[1], args[2], args[3], args[4], args[5]);
38435 if (combineTextItems &&
38436 advance !== null && textContentItem.initialized &&
38437 advance.value > 0 &&
38438 advance.value <= textContentItem.fakeMultiSpaceMax) {
38439 textState.translateTextLineMatrix(advance.width,
38440 advance.height);
38441 textContentItem.width +=
38442 (advance.width - textContentItem.lastAdvanceWidth);
38443 textContentItem.height +=
38444 (advance.height - textContentItem.lastAdvanceHeight);
38445 diff = (advance.width - textContentItem.lastAdvanceWidth) -
38446 (advance.height - textContentItem.lastAdvanceHeight);
38447 addFakeSpaces(diff, textContentItem.str);
38448 break;
38449 }
38450
38451 flushTextContentItem();
38452 textState.setTextMatrix(args[0], args[1], args[2], args[3],
38453 args[4], args[5]);
38454 textState.setTextLineMatrix(args[0], args[1], args[2], args[3],
38455 args[4], args[5]);
38456 break;
38457 case OPS.setCharSpacing:
38458 textState.charSpacing = args[0];
38459 break;
38460 case OPS.setWordSpacing:
38461 textState.wordSpacing = args[0];
38462 break;
38463 case OPS.beginText:
38464 flushTextContentItem();
38465 textState.textMatrix = IDENTITY_MATRIX.slice();
38466 textState.textLineMatrix = IDENTITY_MATRIX.slice();
38467 break;
38468 case OPS.showSpacedText:
38469 var items = args[0];
38470 var offset;
38471 for (var j = 0, jj = items.length; j < jj; j++) {
38472 if (typeof items[j] === 'string') {
38473 buildTextContentItem(items[j]);
38474 } else {
38475 ensureTextContentItem();
38476
38477 // PDF Specification 5.3.2 states:
38478 // The number is expressed in thousandths of a unit of text
38479 // space.
38480 // This amount is subtracted from the current horizontal or
38481 // vertical coordinate, depending on the writing mode.
38482 // In the default coordinate system, a positive adjustment
38483 // has the effect of moving the next glyph painted either to
38484 // the left or down by the given amount.
38485 advance = items[j] * textState.fontSize / 1000;
38486 var breakTextRun = false;
38487 if (textState.font.vertical) {
38488 offset = advance *
38489 (textState.textHScale * textState.textMatrix[2] +
38490 textState.textMatrix[3]);
38491 textState.translateTextMatrix(0, advance);
38492 breakTextRun = textContentItem.textRunBreakAllowed &&
38493 advance > textContentItem.fakeMultiSpaceMax;
38494 if (!breakTextRun) {
38495 // Value needs to be added to height to paint down.
38496 textContentItem.height += offset;
38497 }
38498 } else {
38499 advance = -advance;
38500 offset = advance * (
38501 textState.textHScale * textState.textMatrix[0] +
38502 textState.textMatrix[1]);
38503 textState.translateTextMatrix(advance, 0);
38504 breakTextRun = textContentItem.textRunBreakAllowed &&
38505 advance > textContentItem.fakeMultiSpaceMax;
38506 if (!breakTextRun) {
38507 // Value needs to be subtracted from width to paint left.
38508 textContentItem.width += offset;
38509 }
38510 }
38511 if (breakTextRun) {
38512 flushTextContentItem();
38513 } else if (advance > 0) {
38514 addFakeSpaces(advance, textContentItem.str);
38515 }
38516 }
38517 }
38518 break;
38519 case OPS.showText:
38520 buildTextContentItem(args[0]);
38521 break;
38522 case OPS.nextLineShowText:
38523 flushTextContentItem();
38524 textState.carriageReturn();
38525 buildTextContentItem(args[0]);
38526 break;
38527 case OPS.nextLineSetSpacingShowText:
38528 flushTextContentItem();
38529 textState.wordSpacing = args[0];
38530 textState.charSpacing = args[1];
38531 textState.carriageReturn();
38532 buildTextContentItem(args[2]);
38533 break;
38534 case OPS.paintXObject:
38535 flushTextContentItem();
38536 if (args[0].code) {
38537 break;
38538 }
38539
38540 if (!xobjs) {
38541 xobjs = (resources.get('XObject') || Dict.empty);
38542 }
38543
38544 var name = args[0].name;
38545 if (xobjsCache.key === name) {
38546 if (xobjsCache.texts) {
38547 Util.appendToArray(textContent.items, xobjsCache.texts.items);
38548 Util.extendObj(textContent.styles, xobjsCache.texts.styles);
38549 }
38550 break;
38551 }
38552
38553 var xobj = xobjs.get(name);
38554 if (!xobj) {
38555 break;
38556 }
38557 assert(isStream(xobj), 'XObject should be a stream');
38558
38559 var type = xobj.dict.get('Subtype');
38560 assert(isName(type), 'XObject should have a Name subtype');
38561
38562 if ('Form' !== type.name) {
38563 xobjsCache.key = name;
38564 xobjsCache.texts = null;
38565 break;
38566 }
38567
38568 stateManager.save();
38569 var matrix = xobj.dict.getArray('Matrix');
38570 if (isArray(matrix) && matrix.length === 6) {
38571 stateManager.transform(matrix);
38572 }
38573
38574 next(self.getTextContent(xobj, task,
38575 xobj.dict.get('Resources') || resources, stateManager,
38576 normalizeWhitespace, combineTextItems).then(
38577 function (formTextContent) {
38578 Util.appendToArray(textContent.items, formTextContent.items);
38579 Util.extendObj(textContent.styles, formTextContent.styles);
38580 stateManager.restore();
38581
38582 xobjsCache.key = name;
38583 xobjsCache.texts = formTextContent;
38584 }));
38585 return;
38586 case OPS.setGState:
38587 flushTextContentItem();
38588 var dictName = args[0];
38589 var extGState = resources.get('ExtGState');
38590
38591 if (!isDict(extGState) || !isName(dictName)) {
38592 break;
38593 }
38594 var gState = extGState.get(dictName.name);
38595 if (!isDict(gState)) {
38596 break;
38597 }
38598 var gStateFont = gState.get('Font');
38599 if (gStateFont) {
38600 textState.fontName = null;
38601 textState.fontSize = gStateFont[1];
38602 next(handleSetFont(null, gStateFont[0]));
38603 return;
38604 }
38605 break;
38606 } // switch
38607 } // while
38608 if (stop) {
38609 next(deferred);
38610 return;
38611 }
38612 flushTextContentItem();
38613 resolve(textContent);
38614 });
38615 },
38616
38617 extractDataStructures:
38618 function PartialEvaluator_extractDataStructures(dict, baseDict,
38619 xref, properties) {
38620 // 9.10.2
38621 var toUnicode = (dict.get('ToUnicode') || baseDict.get('ToUnicode'));
38622 var toUnicodePromise = toUnicode ?
38623 this.readToUnicode(toUnicode) : Promise.resolve(undefined);
38624
38625 if (properties.composite) {
38626 // CIDSystemInfo helps to match CID to glyphs
38627 var cidSystemInfo = dict.get('CIDSystemInfo');
38628 if (isDict(cidSystemInfo)) {
38629 properties.cidSystemInfo = {
38630 registry: cidSystemInfo.get('Registry'),
38631 ordering: cidSystemInfo.get('Ordering'),
38632 supplement: cidSystemInfo.get('Supplement')
38633 };
38634 }
38635
38636 var cidToGidMap = dict.get('CIDToGIDMap');
38637 if (isStream(cidToGidMap)) {
38638 properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
38639 }
38640 }
38641
38642 // Based on 9.6.6 of the spec the encoding can come from multiple places
38643 // and depends on the font type. The base encoding and differences are
38644 // read here, but the encoding that is actually used is chosen during
38645 // glyph mapping in the font.
38646 // TODO: Loading the built in encoding in the font would allow the
38647 // differences to be merged in here not require us to hold on to it.
38648 var differences = [];
38649 var baseEncodingName = null;
38650 var encoding;
38651 if (dict.has('Encoding')) {
38652 encoding = dict.get('Encoding');
38653 if (isDict(encoding)) {
38654 baseEncodingName = encoding.get('BaseEncoding');
38655 baseEncodingName = (isName(baseEncodingName) ?
38656 baseEncodingName.name : null);
38657 // Load the differences between the base and original
38658 if (encoding.has('Differences')) {
38659 var diffEncoding = encoding.get('Differences');
38660 var index = 0;
38661 for (var j = 0, jj = diffEncoding.length; j < jj; j++) {
38662 var data = xref.fetchIfRef(diffEncoding[j]);
38663 if (isNum(data)) {
38664 index = data;
38665 } else if (isName(data)) {
38666 differences[index++] = data.name;
38667 } else {
38668 error('Invalid entry in \'Differences\' array: ' + data);
38669 }
38670 }
38671 }
38672 } else if (isName(encoding)) {
38673 baseEncodingName = encoding.name;
38674 } else {
38675 error('Encoding is not a Name nor a Dict');
38676 }
38677 // According to table 114 if the encoding is a named encoding it must be
38678 // one of these predefined encodings.
38679 if ((baseEncodingName !== 'MacRomanEncoding' &&
38680 baseEncodingName !== 'MacExpertEncoding' &&
38681 baseEncodingName !== 'WinAnsiEncoding')) {
38682 baseEncodingName = null;
38683 }
38684 }
38685
38686 if (baseEncodingName) {
38687 properties.defaultEncoding = getEncoding(baseEncodingName).slice();
38688 } else {
38689 encoding = (properties.type === 'TrueType' ?
38690 WinAnsiEncoding : StandardEncoding);
38691 // The Symbolic attribute can be misused for regular fonts
38692 // Heuristic: we have to check if the font is a standard one also
38693 if (!!(properties.flags & FontFlags.Symbolic)) {
38694 encoding = MacRomanEncoding;
38695 if (!properties.file) {
38696 if (/Symbol/i.test(properties.name)) {
38697 encoding = SymbolSetEncoding;
38698 } else if (/Dingbats/i.test(properties.name)) {
38699 encoding = ZapfDingbatsEncoding;
38700 }
38701 }
38702 }
38703 properties.defaultEncoding = encoding;
38704 }
38705
38706 properties.differences = differences;
38707 properties.baseEncodingName = baseEncodingName;
38708 properties.hasEncoding = !!baseEncodingName || differences.length > 0;
38709 properties.dict = dict;
38710 return toUnicodePromise.then(function(toUnicode) {
38711 properties.toUnicode = toUnicode;
38712 return this.buildToUnicode(properties);
38713 }.bind(this)).then(function (toUnicode) {
38714 properties.toUnicode = toUnicode;
38715 return properties;
38716 });
38717 },
38718
38719 /**
38720 * Builds a char code to unicode map based on section 9.10 of the spec.
38721 * @param {Object} properties Font properties object.
38722 * @return {Promise} A Promise that is resolved with a
38723 * {ToUnicodeMap|IdentityToUnicodeMap} object.
38724 */
38725 buildToUnicode: function PartialEvaluator_buildToUnicode(properties) {
38726 properties.hasIncludedToUnicodeMap =
38727 !!properties.toUnicode && properties.toUnicode.length > 0;
38728 // Section 9.10.2 Mapping Character Codes to Unicode Values
38729 if (properties.hasIncludedToUnicodeMap) {
38730 return Promise.resolve(properties.toUnicode);
38731 }
38732 // According to the spec if the font is a simple font we should only map
38733 // to unicode if the base encoding is MacRoman, MacExpert, or WinAnsi or
38734 // the differences array only contains adobe standard or symbol set names,
38735 // in pratice it seems better to always try to create a toUnicode
38736 // map based of the default encoding.
38737 var toUnicode, charcode, glyphName;
38738 if (!properties.composite /* is simple font */) {
38739 toUnicode = [];
38740 var encoding = properties.defaultEncoding.slice();
38741 var baseEncodingName = properties.baseEncodingName;
38742 // Merge in the differences array.
38743 var differences = properties.differences;
38744 for (charcode in differences) {
38745 glyphName = differences[charcode];
38746 if (glyphName === '.notdef') {
38747 // Skip .notdef to prevent rendering errors, e.g. boxes appearing
38748 // where there should be spaces (fixes issue5256.pdf).
38749 continue;
38750 }
38751 encoding[charcode] = glyphName;
38752 }
38753 var glyphsUnicodeMap = getGlyphsUnicode();
38754 for (charcode in encoding) {
38755 // a) Map the character code to a character name.
38756 glyphName = encoding[charcode];
38757 // b) Look up the character name in the Adobe Glyph List (see the
38758 // Bibliography) to obtain the corresponding Unicode value.
38759 if (glyphName === '') {
38760 continue;
38761 } else if (glyphsUnicodeMap[glyphName] === undefined) {
38762 // (undocumented) c) Few heuristics to recognize unknown glyphs
38763 // NOTE: Adobe Reader does not do this step, but OSX Preview does
38764 var code = 0;
38765 switch (glyphName[0]) {
38766 case 'G': // Gxx glyph
38767 if (glyphName.length === 3) {
38768 code = parseInt(glyphName.substr(1), 16);
38769 }
38770 break;
38771 case 'g': // g00xx glyph
38772 if (glyphName.length === 5) {
38773 code = parseInt(glyphName.substr(1), 16);
38774 }
38775 break;
38776 case 'C': // Cddd glyph
38777 case 'c': // cddd glyph
38778 if (glyphName.length >= 3) {
38779 code = +glyphName.substr(1);
38780 }
38781 break;
38782 default:
38783 // 'uniXXXX'/'uXXXX{XX}' glyphs
38784 var unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap);
38785 if (unicode !== -1) {
38786 code = unicode;
38787 }
38788 }
38789 if (code) {
38790 // If |baseEncodingName| is one the predefined encodings,
38791 // and |code| equals |charcode|, using the glyph defined in the
38792 // baseEncoding seems to yield a better |toUnicode| mapping
38793 // (fixes issue 5070).
38794 if (baseEncodingName && code === +charcode) {
38795 var baseEncoding = getEncoding(baseEncodingName);
38796 if (baseEncoding && (glyphName = baseEncoding[charcode])) {
38797 toUnicode[charcode] =
38798 String.fromCharCode(glyphsUnicodeMap[glyphName]);
38799 continue;
38800 }
38801 }
38802 toUnicode[charcode] = String.fromCharCode(code);
38803 }
38804 continue;
38805 }
38806 toUnicode[charcode] =
38807 String.fromCharCode(glyphsUnicodeMap[glyphName]);
38808 }
38809 return Promise.resolve(new ToUnicodeMap(toUnicode));
38810 }
38811 // If the font is a composite font that uses one of the predefined CMaps
38812 // listed in Table 118 (except Identity–H and Identity–V) or whose
38813 // descendant CIDFont uses the Adobe-GB1, Adobe-CNS1, Adobe-Japan1, or
38814 // Adobe-Korea1 character collection:
38815 if (properties.composite && (
38816 (properties.cMap.builtInCMap &&
38817 !(properties.cMap instanceof IdentityCMap)) ||
38818 (properties.cidSystemInfo.registry === 'Adobe' &&
38819 (properties.cidSystemInfo.ordering === 'GB1' ||
38820 properties.cidSystemInfo.ordering === 'CNS1' ||
38821 properties.cidSystemInfo.ordering === 'Japan1' ||
38822 properties.cidSystemInfo.ordering === 'Korea1')))) {
38823 // Then:
38824 // a) Map the character code to a character identifier (CID) according
38825 // to the font’s CMap.
38826 // b) Obtain the registry and ordering of the character collection used
38827 // by the font’s CMap (for example, Adobe and Japan1) from its
38828 // CIDSystemInfo dictionary.
38829 var registry = properties.cidSystemInfo.registry;
38830 var ordering = properties.cidSystemInfo.ordering;
38831 // c) Construct a second CMap name by concatenating the registry and
38832 // ordering obtained in step (b) in the format registry–ordering–UCS2
38833 // (for example, Adobe–Japan1–UCS2).
38834 var ucs2CMapName = Name.get(registry + '-' + ordering + '-UCS2');
38835 // d) Obtain the CMap with the name constructed in step (c) (available
38836 // from the ASN Web site; see the Bibliography).
38837 return CMapFactory.create(ucs2CMapName, this.options.cMapOptions,
38838 null).then(
38839 function (ucs2CMap) {
38840 var cMap = properties.cMap;
38841 toUnicode = [];
38842 cMap.forEach(function(charcode, cid) {
38843 assert(cid <= 0xffff, 'Max size of CID is 65,535');
38844 // e) Map the CID obtained in step (a) according to the CMap
38845 // obtained in step (d), producing a Unicode value.
38846 var ucs2 = ucs2CMap.lookup(cid);
38847 if (ucs2) {
38848 toUnicode[charcode] =
38849 String.fromCharCode((ucs2.charCodeAt(0) << 8) +
38850 ucs2.charCodeAt(1));
38851 }
38852 });
38853 return new ToUnicodeMap(toUnicode);
38854 });
38855 }
38856
38857 // The viewer's choice, just use an identity map.
38858 return Promise.resolve(new IdentityToUnicodeMap(properties.firstChar,
38859 properties.lastChar));
38860 },
38861
38862 readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) {
38863 var cmapObj = toUnicode;
38864 if (isName(cmapObj)) {
38865 return CMapFactory.create(cmapObj, this.options.cMapOptions, null).then(
38866 function (cmap) {
38867 if (cmap instanceof IdentityCMap) {
38868 return new IdentityToUnicodeMap(0, 0xFFFF);
38869 }
38870 return new ToUnicodeMap(cmap.getMap());
38871 });
38872 } else if (isStream(cmapObj)) {
38873 return CMapFactory.create(cmapObj, this.options.cMapOptions, null).then(
38874 function (cmap) {
38875 if (cmap instanceof IdentityCMap) {
38876 return new IdentityToUnicodeMap(0, 0xFFFF);
38877 }
38878 var map = new Array(cmap.length);
38879 // Convert UTF-16BE
38880 // NOTE: cmap can be a sparse array, so use forEach instead of for(;;)
38881 // to iterate over all keys.
38882 cmap.forEach(function(charCode, token) {
38883 var str = [];
38884 for (var k = 0; k < token.length; k += 2) {
38885 var w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
38886 if ((w1 & 0xF800) !== 0xD800) { // w1 < 0xD800 || w1 > 0xDFFF
38887 str.push(w1);
38888 continue;
38889 }
38890 k += 2;
38891 var w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
38892 str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
38893 }
38894 map[charCode] = String.fromCharCode.apply(String, str);
38895 });
38896 return new ToUnicodeMap(map);
38897 });
38898 }
38899 return Promise.resolve(null);
38900 },
38901
38902 readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) {
38903 // Extract the encoding from the CIDToGIDMap
38904 var glyphsData = cidToGidStream.getBytes();
38905
38906 // Set encoding 0 to later verify the font has an encoding
38907 var result = [];
38908 for (var j = 0, jj = glyphsData.length; j < jj; j++) {
38909 var glyphID = (glyphsData[j++] << 8) | glyphsData[j];
38910 if (glyphID === 0) {
38911 continue;
38912 }
38913 var code = j >> 1;
38914 result[code] = glyphID;
38915 }
38916 return result;
38917 },
38918
38919 extractWidths: function PartialEvaluator_extractWidths(dict, xref,
38920 descriptor,
38921 properties) {
38922 var glyphsWidths = [];
38923 var defaultWidth = 0;
38924 var glyphsVMetrics = [];
38925 var defaultVMetrics;
38926 var i, ii, j, jj, start, code, widths;
38927 if (properties.composite) {
38928 defaultWidth = dict.get('DW') || 1000;
38929
38930 widths = dict.get('W');
38931 if (widths) {
38932 for (i = 0, ii = widths.length; i < ii; i++) {
38933 start = widths[i++];
38934 code = xref.fetchIfRef(widths[i]);
38935 if (isArray(code)) {
38936 for (j = 0, jj = code.length; j < jj; j++) {
38937 glyphsWidths[start++] = code[j];
38938 }
38939 } else {
38940 var width = widths[++i];
38941 for (j = start; j <= code; j++) {
38942 glyphsWidths[j] = width;
38943 }
38944 }
38945 }
38946 }
38947
38948 if (properties.vertical) {
38949 var vmetrics = (dict.get('DW2') || [880, -1000]);
38950 defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]];
38951 vmetrics = dict.get('W2');
38952 if (vmetrics) {
38953 for (i = 0, ii = vmetrics.length; i < ii; i++) {
38954 start = vmetrics[i++];
38955 code = xref.fetchIfRef(vmetrics[i]);
38956 if (isArray(code)) {
38957 for (j = 0, jj = code.length; j < jj; j++) {
38958 glyphsVMetrics[start++] = [code[j++], code[j++], code[j]];
38959 }
38960 } else {
38961 var vmetric = [vmetrics[++i], vmetrics[++i], vmetrics[++i]];
38962 for (j = start; j <= code; j++) {
38963 glyphsVMetrics[j] = vmetric;
38964 }
38965 }
38966 }
38967 }
38968 }
38969 } else {
38970 var firstChar = properties.firstChar;
38971 widths = dict.get('Widths');
38972 if (widths) {
38973 j = firstChar;
38974 for (i = 0, ii = widths.length; i < ii; i++) {
38975 glyphsWidths[j++] = widths[i];
38976 }
38977 defaultWidth = (parseFloat(descriptor.get('MissingWidth')) || 0);
38978 } else {
38979 // Trying get the BaseFont metrics (see comment above).
38980 var baseFontName = dict.get('BaseFont');
38981 if (isName(baseFontName)) {
38982 var metrics = this.getBaseFontMetrics(baseFontName.name);
38983
38984 glyphsWidths = this.buildCharCodeToWidth(metrics.widths,
38985 properties);
38986 defaultWidth = metrics.defaultWidth;
38987 }
38988 }
38989 }
38990
38991 // Heuristic: detection of monospace font by checking all non-zero widths
38992 var isMonospace = true;
38993 var firstWidth = defaultWidth;
38994 for (var glyph in glyphsWidths) {
38995 var glyphWidth = glyphsWidths[glyph];
38996 if (!glyphWidth) {
38997 continue;
38998 }
38999 if (!firstWidth) {
39000 firstWidth = glyphWidth;
39001 continue;
39002 }
39003 if (firstWidth !== glyphWidth) {
39004 isMonospace = false;
39005 break;
39006 }
39007 }
39008 if (isMonospace) {
39009 properties.flags |= FontFlags.FixedPitch;
39010 }
39011
39012 properties.defaultWidth = defaultWidth;
39013 properties.widths = glyphsWidths;
39014 properties.defaultVMetrics = defaultVMetrics;
39015 properties.vmetrics = glyphsVMetrics;
39016 },
39017
39018 isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) {
39019 // Simulating descriptor flags attribute
39020 var fontNameWoStyle = baseFontName.split('-')[0];
39021 return (fontNameWoStyle in getSerifFonts()) ||
39022 (fontNameWoStyle.search(/serif/gi) !== -1);
39023 },
39024
39025 getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
39026 var defaultWidth = 0;
39027 var widths = [];
39028 var monospace = false;
39029 var stdFontMap = getStdFontMap();
39030 var lookupName = (stdFontMap[name] || name);
39031 var Metrics = getMetrics();
39032
39033 if (!(lookupName in Metrics)) {
39034 // Use default fonts for looking up font metrics if the passed
39035 // font is not a base font
39036 if (this.isSerifFont(name)) {
39037 lookupName = 'Times-Roman';
39038 } else {
39039 lookupName = 'Helvetica';
39040 }
39041 }
39042 var glyphWidths = Metrics[lookupName];
39043
39044 if (isNum(glyphWidths)) {
39045 defaultWidth = glyphWidths;
39046 monospace = true;
39047 } else {
39048 widths = glyphWidths(); // expand lazy widths array
39049 }
39050
39051 return {
39052 defaultWidth: defaultWidth,
39053 monospace: monospace,
39054 widths: widths
39055 };
39056 },
39057
39058 buildCharCodeToWidth:
39059 function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName,
39060 properties) {
39061 var widths = Object.create(null);
39062 var differences = properties.differences;
39063 var encoding = properties.defaultEncoding;
39064 for (var charCode = 0; charCode < 256; charCode++) {
39065 if (charCode in differences &&
39066 widthsByGlyphName[differences[charCode]]) {
39067 widths[charCode] = widthsByGlyphName[differences[charCode]];
39068 continue;
39069 }
39070 if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {
39071 widths[charCode] = widthsByGlyphName[encoding[charCode]];
39072 continue;
39073 }
39074 }
39075 return widths;
39076 },
39077
39078 preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict, xref) {
39079 var baseDict = dict;
39080 var type = dict.get('Subtype');
39081 assert(isName(type), 'invalid font Subtype');
39082
39083 var composite = false;
39084 var uint8array;
39085 if (type.name === 'Type0') {
39086 // If font is a composite
39087 // - get the descendant font
39088 // - set the type according to the descendant font
39089 // - get the FontDescriptor from the descendant font
39090 var df = dict.get('DescendantFonts');
39091 if (!df) {
39092 error('Descendant fonts are not specified');
39093 }
39094 dict = (isArray(df) ? xref.fetchIfRef(df[0]) : df);
39095
39096 type = dict.get('Subtype');
39097 assert(isName(type), 'invalid font Subtype');
39098 composite = true;
39099 }
39100
39101 var descriptor = dict.get('FontDescriptor');
39102 if (descriptor) {
39103 var hash = new MurmurHash3_64();
39104 var encoding = baseDict.getRaw('Encoding');
39105 if (isName(encoding)) {
39106 hash.update(encoding.name);
39107 } else if (isRef(encoding)) {
39108 hash.update(encoding.toString());
39109 } else if (isDict(encoding)) {
39110 var keys = encoding.getKeys();
39111 for (var i = 0, ii = keys.length; i < ii; i++) {
39112 var entry = encoding.getRaw(keys[i]);
39113 if (isName(entry)) {
39114 hash.update(entry.name);
39115 } else if (isRef(entry)) {
39116 hash.update(entry.toString());
39117 } else if (isArray(entry)) { // 'Differences' entry.
39118 // Ideally we should check the contents of the array, but to avoid
39119 // parsing it here and then again in |extractDataStructures|,
39120 // we only use the array length for now (fixes bug1157493.pdf).
39121 hash.update(entry.length.toString());
39122 }
39123 }
39124 }
39125
39126 var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode');
39127 if (isStream(toUnicode)) {
39128 var stream = toUnicode.str || toUnicode;
39129 uint8array = stream.buffer ?
39130 new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) :
39131 new Uint8Array(stream.bytes.buffer,
39132 stream.start, stream.end - stream.start);
39133 hash.update(uint8array);
39134
39135 } else if (isName(toUnicode)) {
39136 hash.update(toUnicode.name);
39137 }
39138
39139 var widths = dict.get('Widths') || baseDict.get('Widths');
39140 if (widths) {
39141 uint8array = new Uint8Array(new Uint32Array(widths).buffer);
39142 hash.update(uint8array);
39143 }
39144 }
39145
39146 return {
39147 descriptor: descriptor,
39148 dict: dict,
39149 baseDict: baseDict,
39150 composite: composite,
39151 type: type.name,
39152 hash: hash ? hash.hexdigest() : ''
39153 };
39154 },
39155
39156 translateFont: function PartialEvaluator_translateFont(preEvaluatedFont,
39157 xref) {
39158 var baseDict = preEvaluatedFont.baseDict;
39159 var dict = preEvaluatedFont.dict;
39160 var composite = preEvaluatedFont.composite;
39161 var descriptor = preEvaluatedFont.descriptor;
39162 var type = preEvaluatedFont.type;
39163 var maxCharIndex = (composite ? 0xFFFF : 0xFF);
39164 var cMapOptions = this.options.cMapOptions;
39165 var properties;
39166
39167 if (!descriptor) {
39168 if (type === 'Type3') {
39169 // FontDescriptor is only required for Type3 fonts when the document
39170 // is a tagged pdf. Create a barbebones one to get by.
39171 descriptor = new Dict(null);
39172 descriptor.set('FontName', Name.get(type));
39173 descriptor.set('FontBBox', dict.getArray('FontBBox'));
39174 } else {
39175 // Before PDF 1.5 if the font was one of the base 14 fonts, having a
39176 // FontDescriptor was not required.
39177 // This case is here for compatibility.
39178 var baseFontName = dict.get('BaseFont');
39179 if (!isName(baseFontName)) {
39180 error('Base font is not specified');
39181 }
39182
39183 // Using base font name as a font name.
39184 baseFontName = baseFontName.name.replace(/[,_]/g, '-');
39185 var metrics = this.getBaseFontMetrics(baseFontName);
39186
39187 // Simulating descriptor flags attribute
39188 var fontNameWoStyle = baseFontName.split('-')[0];
39189 var flags =
39190 (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) |
39191 (metrics.monospace ? FontFlags.FixedPitch : 0) |
39192 (getSymbolsFonts()[fontNameWoStyle] ? FontFlags.Symbolic :
39193 FontFlags.Nonsymbolic);
39194
39195 properties = {
39196 type: type,
39197 name: baseFontName,
39198 widths: metrics.widths,
39199 defaultWidth: metrics.defaultWidth,
39200 flags: flags,
39201 firstChar: 0,
39202 lastChar: maxCharIndex
39203 };
39204 return this.extractDataStructures(dict, dict, xref, properties).then(
39205 function (properties) {
39206 properties.widths = this.buildCharCodeToWidth(metrics.widths,
39207 properties);
39208 return new Font(baseFontName, null, properties);
39209 }.bind(this));
39210 }
39211 }
39212
39213 // According to the spec if 'FontDescriptor' is declared, 'FirstChar',
39214 // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem
39215 // to ignore this rule when a variant of a standard font is used.
39216 // TODO Fill the width array depending on which of the base font this is
39217 // a variant.
39218 var firstChar = (dict.get('FirstChar') || 0);
39219 var lastChar = (dict.get('LastChar') || maxCharIndex);
39220
39221 var fontName = descriptor.get('FontName');
39222 var baseFont = dict.get('BaseFont');
39223 // Some bad PDFs have a string as the font name.
39224 if (isString(fontName)) {
39225 fontName = Name.get(fontName);
39226 }
39227 if (isString(baseFont)) {
39228 baseFont = Name.get(baseFont);
39229 }
39230
39231 if (type !== 'Type3') {
39232 var fontNameStr = fontName && fontName.name;
39233 var baseFontStr = baseFont && baseFont.name;
39234 if (fontNameStr !== baseFontStr) {
39235 info('The FontDescriptor\'s FontName is "' + fontNameStr +
39236 '" but should be the same as the Font\'s BaseFont "' +
39237 baseFontStr + '"');
39238 // Workaround for cases where e.g. fontNameStr = 'Arial' and
39239 // baseFontStr = 'Arial,Bold' (needed when no font file is embedded).
39240 if (fontNameStr && baseFontStr &&
39241 baseFontStr.indexOf(fontNameStr) === 0) {
39242 fontName = baseFont;
39243 }
39244 }
39245 }
39246 fontName = (fontName || baseFont);
39247
39248 assert(isName(fontName), 'invalid font name');
39249
39250 var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
39251 if (fontFile) {
39252 if (fontFile.dict) {
39253 var subtype = fontFile.dict.get('Subtype');
39254 if (subtype) {
39255 subtype = subtype.name;
39256 }
39257 var length1 = fontFile.dict.get('Length1');
39258 var length2 = fontFile.dict.get('Length2');
39259 var length3 = fontFile.dict.get('Length3');
39260 }
39261 }
39262
39263 properties = {
39264 type: type,
39265 name: fontName.name,
39266 subtype: subtype,
39267 file: fontFile,
39268 length1: length1,
39269 length2: length2,
39270 length3: length3,
39271 loadedName: baseDict.loadedName,
39272 composite: composite,
39273 wideChars: composite,
39274 fixedPitch: false,
39275 fontMatrix: (dict.getArray('FontMatrix') || FONT_IDENTITY_MATRIX),
39276 firstChar: firstChar || 0,
39277 lastChar: (lastChar || maxCharIndex),
39278 bbox: descriptor.getArray('FontBBox'),
39279 ascent: descriptor.get('Ascent'),
39280 descent: descriptor.get('Descent'),
39281 xHeight: descriptor.get('XHeight'),
39282 capHeight: descriptor.get('CapHeight'),
39283 flags: descriptor.get('Flags'),
39284 italicAngle: descriptor.get('ItalicAngle'),
39285 coded: false
39286 };
39287
39288 var cMapPromise;
39289 if (composite) {
39290 var cidEncoding = baseDict.get('Encoding');
39291 if (isName(cidEncoding)) {
39292 properties.cidEncoding = cidEncoding.name;
39293 }
39294 cMapPromise = CMapFactory.create(cidEncoding, cMapOptions, null).then(
39295 function (cMap) {
39296 properties.cMap = cMap;
39297 properties.vertical = properties.cMap.vertical;
39298 });
39299 } else {
39300 cMapPromise = Promise.resolve(undefined);
39301 }
39302
39303 return cMapPromise.then(function () {
39304 return this.extractDataStructures(dict, baseDict, xref, properties);
39305 }.bind(this)).then(function (properties) {
39306 this.extractWidths(dict, xref, descriptor, properties);
39307
39308 if (type === 'Type3') {
39309 properties.isType3Font = true;
39310 }
39311
39312 return new Font(fontName.name, fontFile, properties);
39313 }.bind(this));
39314 }
39315 };
39316
39317 return PartialEvaluator;
39318})();
39319
39320var TranslatedFont = (function TranslatedFontClosure() {
39321 function TranslatedFont(loadedName, font, dict) {
39322 this.loadedName = loadedName;
39323 this.font = font;
39324 this.dict = dict;
39325 this.type3Loaded = null;
39326 this.sent = false;
39327 }
39328 TranslatedFont.prototype = {
39329 send: function (handler) {
39330 if (this.sent) {
39331 return;
39332 }
39333 var fontData = this.font.exportData();
39334 handler.send('commonobj', [
39335 this.loadedName,
39336 'Font',
39337 fontData
39338 ]);
39339 this.sent = true;
39340 },
39341 loadType3Data: function (evaluator, resources, parentOperatorList, task) {
39342 assert(this.font.isType3Font);
39343
39344 if (this.type3Loaded) {
39345 return this.type3Loaded;
39346 }
39347
39348 var translatedFont = this.font;
39349 var loadCharProcsPromise = Promise.resolve();
39350 var charProcs = this.dict.get('CharProcs');
39351 var fontResources = this.dict.get('Resources') || resources;
39352 var charProcKeys = charProcs.getKeys();
39353 var charProcOperatorList = Object.create(null);
39354 for (var i = 0, n = charProcKeys.length; i < n; ++i) {
39355 loadCharProcsPromise = loadCharProcsPromise.then(function (key) {
39356 var glyphStream = charProcs.get(key);
39357 var operatorList = new OperatorList();
39358 return evaluator.getOperatorList(glyphStream, task, fontResources,
39359 operatorList).then(function () {
39360 charProcOperatorList[key] = operatorList.getIR();
39361
39362 // Add the dependencies to the parent operator list so they are
39363 // resolved before sub operator list is executed synchronously.
39364 parentOperatorList.addDependencies(operatorList.dependencies);
39365 }, function (reason) {
39366 warn('Type3 font resource \"' + key + '\" is not available');
39367 var operatorList = new OperatorList();
39368 charProcOperatorList[key] = operatorList.getIR();
39369 });
39370 }.bind(this, charProcKeys[i]));
39371 }
39372 this.type3Loaded = loadCharProcsPromise.then(function () {
39373 translatedFont.charProcOperatorList = charProcOperatorList;
39374 });
39375 return this.type3Loaded;
39376 }
39377 };
39378 return TranslatedFont;
39379})();
39380
39381var OperatorList = (function OperatorListClosure() {
39382 var CHUNK_SIZE = 1000;
39383 var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size
39384
39385 function getTransfers(queue) {
39386 var transfers = [];
39387 var fnArray = queue.fnArray, argsArray = queue.argsArray;
39388 for (var i = 0, ii = queue.length; i < ii; i++) {
39389 switch (fnArray[i]) {
39390 case OPS.paintInlineImageXObject:
39391 case OPS.paintInlineImageXObjectGroup:
39392 case OPS.paintImageMaskXObject:
39393 var arg = argsArray[i][0]; // first param in imgData
39394 if (!arg.cached) {
39395 transfers.push(arg.data.buffer);
39396 }
39397 break;
39398 }
39399 }
39400 return transfers;
39401 }
39402
39403 function OperatorList(intent, messageHandler, pageIndex) {
39404 this.messageHandler = messageHandler;
39405 this.fnArray = [];
39406 this.argsArray = [];
39407 this.dependencies = Object.create(null);
39408 this._totalLength = 0;
39409 this.pageIndex = pageIndex;
39410 this.intent = intent;
39411 }
39412
39413 OperatorList.prototype = {
39414 get length() {
39415 return this.argsArray.length;
39416 },
39417
39418 /**
39419 * @returns {number} The total length of the entire operator list,
39420 * since `this.length === 0` after flushing.
39421 */
39422 get totalLength() {
39423 return (this._totalLength + this.length);
39424 },
39425
39426 addOp: function(fn, args) {
39427 this.fnArray.push(fn);
39428 this.argsArray.push(args);
39429 if (this.messageHandler) {
39430 if (this.fnArray.length >= CHUNK_SIZE) {
39431 this.flush();
39432 } else if (this.fnArray.length >= CHUNK_SIZE_ABOUT &&
39433 (fn === OPS.restore || fn === OPS.endText)) {
39434 // heuristic to flush on boundary of restore or endText
39435 this.flush();
39436 }
39437 }
39438 },
39439
39440 addDependency: function(dependency) {
39441 if (dependency in this.dependencies) {
39442 return;
39443 }
39444 this.dependencies[dependency] = true;
39445 this.addOp(OPS.dependency, [dependency]);
39446 },
39447
39448 addDependencies: function(dependencies) {
39449 for (var key in dependencies) {
39450 this.addDependency(key);
39451 }
39452 },
39453
39454 addOpList: function(opList) {
39455 Util.extendObj(this.dependencies, opList.dependencies);
39456 for (var i = 0, ii = opList.length; i < ii; i++) {
39457 this.addOp(opList.fnArray[i], opList.argsArray[i]);
39458 }
39459 },
39460
39461 getIR: function() {
39462 return {
39463 fnArray: this.fnArray,
39464 argsArray: this.argsArray,
39465 length: this.length
39466 };
39467 },
39468
39469 flush: function(lastChunk) {
39470 if (this.intent !== 'oplist') {
39471 new QueueOptimizer().optimize(this);
39472 }
39473 var transfers = getTransfers(this);
39474 var length = this.length;
39475 this._totalLength += length;
39476
39477 this.messageHandler.send('RenderPageChunk', {
39478 operatorList: {
39479 fnArray: this.fnArray,
39480 argsArray: this.argsArray,
39481 lastChunk: lastChunk,
39482 length: length
39483 },
39484 pageIndex: this.pageIndex,
39485 intent: this.intent
39486 }, transfers);
39487 this.dependencies = Object.create(null);
39488 this.fnArray.length = 0;
39489 this.argsArray.length = 0;
39490 }
39491 };
39492
39493 return OperatorList;
39494})();
39495
39496var StateManager = (function StateManagerClosure() {
39497 function StateManager(initialState) {
39498 this.state = initialState;
39499 this.stateStack = [];
39500 }
39501 StateManager.prototype = {
39502 save: function () {
39503 var old = this.state;
39504 this.stateStack.push(this.state);
39505 this.state = old.clone();
39506 },
39507 restore: function () {
39508 var prev = this.stateStack.pop();
39509 if (prev) {
39510 this.state = prev;
39511 }
39512 },
39513 transform: function (args) {
39514 this.state.ctm = Util.transform(this.state.ctm, args);
39515 }
39516 };
39517 return StateManager;
39518})();
39519
39520var TextState = (function TextStateClosure() {
39521 function TextState() {
39522 this.ctm = new Float32Array(IDENTITY_MATRIX);
39523 this.fontName = null;
39524 this.fontSize = 0;
39525 this.font = null;
39526 this.fontMatrix = FONT_IDENTITY_MATRIX;
39527 this.textMatrix = IDENTITY_MATRIX.slice();
39528 this.textLineMatrix = IDENTITY_MATRIX.slice();
39529 this.charSpacing = 0;
39530 this.wordSpacing = 0;
39531 this.leading = 0;
39532 this.textHScale = 1;
39533 this.textRise = 0;
39534 }
39535
39536 TextState.prototype = {
39537 setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
39538 var m = this.textMatrix;
39539 m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f;
39540 },
39541 setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
39542 var m = this.textLineMatrix;
39543 m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f;
39544 },
39545 translateTextMatrix: function TextState_translateTextMatrix(x, y) {
39546 var m = this.textMatrix;
39547 m[4] = m[0] * x + m[2] * y + m[4];
39548 m[5] = m[1] * x + m[3] * y + m[5];
39549 },
39550 translateTextLineMatrix: function TextState_translateTextMatrix(x, y) {
39551 var m = this.textLineMatrix;
39552 m[4] = m[0] * x + m[2] * y + m[4];
39553 m[5] = m[1] * x + m[3] * y + m[5];
39554 },
39555 calcTextLineMatrixAdvance:
39556 function TextState_calcTextLineMatrixAdvance(a, b, c, d, e, f) {
39557 var font = this.font;
39558 if (!font) {
39559 return null;
39560 }
39561 var m = this.textLineMatrix;
39562 if (!(a === m[0] && b === m[1] && c === m[2] && d === m[3])) {
39563 return null;
39564 }
39565 var txDiff = e - m[4], tyDiff = f - m[5];
39566 if ((font.vertical && txDiff !== 0) || (!font.vertical && tyDiff !== 0)) {
39567 return null;
39568 }
39569 var tx, ty, denominator = a * d - b * c;
39570 if (font.vertical) {
39571 tx = -tyDiff * c / denominator;
39572 ty = tyDiff * a / denominator;
39573 } else {
39574 tx = txDiff * d / denominator;
39575 ty = -txDiff * b / denominator;
39576 }
39577 return { width: tx, height: ty, value: (font.vertical ? ty : tx), };
39578 },
39579 calcRenderMatrix: function TextState_calcRendeMatrix(ctm) {
39580 // 9.4.4 Text Space Details
39581 var tsm = [this.fontSize * this.textHScale, 0,
39582 0, this.fontSize,
39583 0, this.textRise];
39584 return Util.transform(ctm, Util.transform(this.textMatrix, tsm));
39585 },
39586 carriageReturn: function TextState_carriageReturn() {
39587 this.translateTextLineMatrix(0, -this.leading);
39588 this.textMatrix = this.textLineMatrix.slice();
39589 },
39590 clone: function TextState_clone() {
39591 var clone = Object.create(this);
39592 clone.textMatrix = this.textMatrix.slice();
39593 clone.textLineMatrix = this.textLineMatrix.slice();
39594 clone.fontMatrix = this.fontMatrix.slice();
39595 return clone;
39596 }
39597 };
39598 return TextState;
39599})();
39600
39601var EvalState = (function EvalStateClosure() {
39602 function EvalState() {
39603 this.ctm = new Float32Array(IDENTITY_MATRIX);
39604 this.font = null;
39605 this.textRenderingMode = TextRenderingMode.FILL;
39606 this.fillColorSpace = ColorSpace.singletons.gray;
39607 this.strokeColorSpace = ColorSpace.singletons.gray;
39608 }
39609 EvalState.prototype = {
39610 clone: function CanvasExtraState_clone() {
39611 return Object.create(this);
39612 },
39613 };
39614 return EvalState;
39615})();
39616
39617var EvaluatorPreprocessor = (function EvaluatorPreprocessorClosure() {
39618 // Specifies properties for each command
39619 //
39620 // If variableArgs === true: [0, `numArgs`] expected
39621 // If variableArgs === false: exactly `numArgs` expected
39622 var getOPMap = getLookupTableFactory(function (t) {
39623 // Graphic state
39624 t['w'] = { id: OPS.setLineWidth, numArgs: 1, variableArgs: false };
39625 t['J'] = { id: OPS.setLineCap, numArgs: 1, variableArgs: false };
39626 t['j'] = { id: OPS.setLineJoin, numArgs: 1, variableArgs: false };
39627 t['M'] = { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false };
39628 t['d'] = { id: OPS.setDash, numArgs: 2, variableArgs: false };
39629 t['ri'] = { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false };
39630 t['i'] = { id: OPS.setFlatness, numArgs: 1, variableArgs: false };
39631 t['gs'] = { id: OPS.setGState, numArgs: 1, variableArgs: false };
39632 t['q'] = { id: OPS.save, numArgs: 0, variableArgs: false };
39633 t['Q'] = { id: OPS.restore, numArgs: 0, variableArgs: false };
39634 t['cm'] = { id: OPS.transform, numArgs: 6, variableArgs: false };
39635
39636 // Path
39637 t['m'] = { id: OPS.moveTo, numArgs: 2, variableArgs: false };
39638 t['l'] = { id: OPS.lineTo, numArgs: 2, variableArgs: false };
39639 t['c'] = { id: OPS.curveTo, numArgs: 6, variableArgs: false };
39640 t['v'] = { id: OPS.curveTo2, numArgs: 4, variableArgs: false };
39641 t['y'] = { id: OPS.curveTo3, numArgs: 4, variableArgs: false };
39642 t['h'] = { id: OPS.closePath, numArgs: 0, variableArgs: false };
39643 t['re'] = { id: OPS.rectangle, numArgs: 4, variableArgs: false };
39644 t['S'] = { id: OPS.stroke, numArgs: 0, variableArgs: false };
39645 t['s'] = { id: OPS.closeStroke, numArgs: 0, variableArgs: false };
39646 t['f'] = { id: OPS.fill, numArgs: 0, variableArgs: false };
39647 t['F'] = { id: OPS.fill, numArgs: 0, variableArgs: false };
39648 t['f*'] = { id: OPS.eoFill, numArgs: 0, variableArgs: false };
39649 t['B'] = { id: OPS.fillStroke, numArgs: 0, variableArgs: false };
39650 t['B*'] = { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false };
39651 t['b'] = { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false };
39652 t['b*'] = { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false };
39653 t['n'] = { id: OPS.endPath, numArgs: 0, variableArgs: false };
39654
39655 // Clipping
39656 t['W'] = { id: OPS.clip, numArgs: 0, variableArgs: false };
39657 t['W*'] = { id: OPS.eoClip, numArgs: 0, variableArgs: false };
39658
39659 // Text
39660 t['BT'] = { id: OPS.beginText, numArgs: 0, variableArgs: false };
39661 t['ET'] = { id: OPS.endText, numArgs: 0, variableArgs: false };
39662 t['Tc'] = { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false };
39663 t['Tw'] = { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false };
39664 t['Tz'] = { id: OPS.setHScale, numArgs: 1, variableArgs: false };
39665 t['TL'] = { id: OPS.setLeading, numArgs: 1, variableArgs: false };
39666 t['Tf'] = { id: OPS.setFont, numArgs: 2, variableArgs: false };
39667 t['Tr'] = { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false };
39668 t['Ts'] = { id: OPS.setTextRise, numArgs: 1, variableArgs: false };
39669 t['Td'] = { id: OPS.moveText, numArgs: 2, variableArgs: false };
39670 t['TD'] = { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false };
39671 t['Tm'] = { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false };
39672 t['T*'] = { id: OPS.nextLine, numArgs: 0, variableArgs: false };
39673 t['Tj'] = { id: OPS.showText, numArgs: 1, variableArgs: false };
39674 t['TJ'] = { id: OPS.showSpacedText, numArgs: 1, variableArgs: false };
39675 t['\''] = { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false };
39676 t['"'] = { id: OPS.nextLineSetSpacingShowText, numArgs: 3,
39677 variableArgs: false };
39678
39679 // Type3 fonts
39680 t['d0'] = { id: OPS.setCharWidth, numArgs: 2, variableArgs: false };
39681 t['d1'] = { id: OPS.setCharWidthAndBounds, numArgs: 6,
39682 variableArgs: false };
39683
39684 // Color
39685 t['CS'] = { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false };
39686 t['cs'] = { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false };
39687 t['SC'] = { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true };
39688 t['SCN'] = { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true };
39689 t['sc'] = { id: OPS.setFillColor, numArgs: 4, variableArgs: true };
39690 t['scn'] = { id: OPS.setFillColorN, numArgs: 33, variableArgs: true };
39691 t['G'] = { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false };
39692 t['g'] = { id: OPS.setFillGray, numArgs: 1, variableArgs: false };
39693 t['RG'] = { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false };
39694 t['rg'] = { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false };
39695 t['K'] = { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false };
39696 t['k'] = { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false };
39697
39698 // Shading
39699 t['sh'] = { id: OPS.shadingFill, numArgs: 1, variableArgs: false };
39700
39701 // Images
39702 t['BI'] = { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false };
39703 t['ID'] = { id: OPS.beginImageData, numArgs: 0, variableArgs: false };
39704 t['EI'] = { id: OPS.endInlineImage, numArgs: 1, variableArgs: false };
39705
39706 // XObjects
39707 t['Do'] = { id: OPS.paintXObject, numArgs: 1, variableArgs: false };
39708 t['MP'] = { id: OPS.markPoint, numArgs: 1, variableArgs: false };
39709 t['DP'] = { id: OPS.markPointProps, numArgs: 2, variableArgs: false };
39710 t['BMC'] = { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false };
39711 t['BDC'] = { id: OPS.beginMarkedContentProps, numArgs: 2,
39712 variableArgs: false };
39713 t['EMC'] = { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false };
39714
39715 // Compatibility
39716 t['BX'] = { id: OPS.beginCompat, numArgs: 0, variableArgs: false };
39717 t['EX'] = { id: OPS.endCompat, numArgs: 0, variableArgs: false };
39718
39719 // (reserved partial commands for the lexer)
39720 t['BM'] = null;
39721 t['BD'] = null;
39722 t['true'] = null;
39723 t['fa'] = null;
39724 t['fal'] = null;
39725 t['fals'] = null;
39726 t['false'] = null;
39727 t['nu'] = null;
39728 t['nul'] = null;
39729 t['null'] = null;
39730 });
39731
39732 function EvaluatorPreprocessor(stream, xref, stateManager) {
39733 this.opMap = getOPMap();
39734 // TODO(mduan): pass array of knownCommands rather than this.opMap
39735 // dictionary
39736 this.parser = new Parser(new Lexer(stream, this.opMap), false, xref);
39737 this.stateManager = stateManager;
39738 this.nonProcessedArgs = [];
39739 }
39740
39741 EvaluatorPreprocessor.prototype = {
39742 get savedStatesDepth() {
39743 return this.stateManager.stateStack.length;
39744 },
39745
39746 // |operation| is an object with two fields:
39747 //
39748 // - |fn| is an out param.
39749 //
39750 // - |args| is an inout param. On entry, it should have one of two values.
39751 //
39752 // - An empty array. This indicates that the caller is providing the
39753 // array in which the args will be stored in. The caller should use
39754 // this value if it can reuse a single array for each call to read().
39755 //
39756 // - |null|. This indicates that the caller needs this function to create
39757 // the array in which any args are stored in. If there are zero args,
39758 // this function will leave |operation.args| as |null| (thus avoiding
39759 // allocations that would occur if we used an empty array to represent
39760 // zero arguments). Otherwise, it will replace |null| with a new array
39761 // containing the arguments. The caller should use this value if it
39762 // cannot reuse an array for each call to read().
39763 //
39764 // These two modes are present because this function is very hot and so
39765 // avoiding allocations where possible is worthwhile.
39766 //
39767 read: function EvaluatorPreprocessor_read(operation) {
39768 var args = operation.args;
39769 while (true) {
39770 var obj = this.parser.getObj();
39771 if (isCmd(obj)) {
39772 var cmd = obj.cmd;
39773 // Check that the command is valid
39774 var opSpec = this.opMap[cmd];
39775 if (!opSpec) {
39776 warn('Unknown command "' + cmd + '"');
39777 continue;
39778 }
39779
39780 var fn = opSpec.id;
39781 var numArgs = opSpec.numArgs;
39782 var argsLength = args !== null ? args.length : 0;
39783
39784 if (!opSpec.variableArgs) {
39785 // Postscript commands can be nested, e.g. /F2 /GS2 gs 5.711 Tf
39786 if (argsLength !== numArgs) {
39787 var nonProcessedArgs = this.nonProcessedArgs;
39788 while (argsLength > numArgs) {
39789 nonProcessedArgs.push(args.shift());
39790 argsLength--;
39791 }
39792 while (argsLength < numArgs && nonProcessedArgs.length !== 0) {
39793 if (!args) {
39794 args = [];
39795 }
39796 args.unshift(nonProcessedArgs.pop());
39797 argsLength++;
39798 }
39799 }
39800
39801 if (argsLength < numArgs) {
39802 // If we receive too few args, it's not possible to possible
39803 // to execute the command, so skip the command
39804 info('Command ' + fn + ': because expected ' +
39805 numArgs + ' args, but received ' + argsLength +
39806 ' args; skipping');
39807 args = null;
39808 continue;
39809 }
39810 } else if (argsLength > numArgs) {
39811 info('Command ' + fn + ': expected [0,' + numArgs +
39812 '] args, but received ' + argsLength + ' args');
39813 }
39814
39815 // TODO figure out how to type-check vararg functions
39816 this.preprocessCommand(fn, args);
39817
39818 operation.fn = fn;
39819 operation.args = args;
39820 return true;
39821 } else {
39822 if (isEOF(obj)) {
39823 return false; // no more commands
39824 }
39825 // argument
39826 if (obj !== null) {
39827 if (!args) {
39828 args = [];
39829 }
39830 args.push(obj);
39831 assert(args.length <= 33, 'Too many arguments');
39832 }
39833 }
39834 }
39835 },
39836
39837 preprocessCommand:
39838 function EvaluatorPreprocessor_preprocessCommand(fn, args) {
39839 switch (fn | 0) {
39840 case OPS.save:
39841 this.stateManager.save();
39842 break;
39843 case OPS.restore:
39844 this.stateManager.restore();
39845 break;
39846 case OPS.transform:
39847 this.stateManager.transform(args);
39848 break;
39849 }
39850 }
39851 };
39852 return EvaluatorPreprocessor;
39853})();
39854
39855var QueueOptimizer = (function QueueOptimizerClosure() {
39856 function addState(parentState, pattern, fn) {
39857 var state = parentState;
39858 for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
39859 var item = pattern[i];
39860 state = (state[item] || (state[item] = []));
39861 }
39862 state[pattern[pattern.length - 1]] = fn;
39863 }
39864
39865 function handlePaintSolidColorImageMask(iFirstSave, count, fnArray,
39866 argsArray) {
39867 // Handles special case of mainly LaTeX documents which use image masks to
39868 // draw lines with the current fill style.
39869 // 'count' groups of (save, transform, paintImageMaskXObject, restore)+
39870 // have been found at iFirstSave.
39871 var iFirstPIMXO = iFirstSave + 2;
39872 for (var i = 0; i < count; i++) {
39873 var arg = argsArray[iFirstPIMXO + 4 * i];
39874 var imageMask = arg.length === 1 && arg[0];
39875 if (imageMask && imageMask.width === 1 && imageMask.height === 1 &&
39876 (!imageMask.data.length ||
39877 (imageMask.data.length === 1 && imageMask.data[0] === 0))) {
39878 fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask;
39879 continue;
39880 }
39881 break;
39882 }
39883 return count - i;
39884 }
39885
39886 var InitialState = [];
39887
39888 // This replaces (save, transform, paintInlineImageXObject, restore)+
39889 // sequences with one |paintInlineImageXObjectGroup| operation.
39890 addState(InitialState,
39891 [OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore],
39892 function foundInlineImageGroup(context) {
39893 var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
39894 var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
39895 var MAX_WIDTH = 1000;
39896 var IMAGE_PADDING = 1;
39897
39898 var fnArray = context.fnArray, argsArray = context.argsArray;
39899 var curr = context.iCurr;
39900 var iFirstSave = curr - 3;
39901 var iFirstTransform = curr - 2;
39902 var iFirstPIIXO = curr - 1;
39903
39904 // Look for the quartets.
39905 var i = iFirstSave + 4;
39906 var ii = fnArray.length;
39907 while (i + 3 < ii) {
39908 if (fnArray[i] !== OPS.save ||
39909 fnArray[i + 1] !== OPS.transform ||
39910 fnArray[i + 2] !== OPS.paintInlineImageXObject ||
39911 fnArray[i + 3] !== OPS.restore) {
39912 break; // ops don't match
39913 }
39914 i += 4;
39915 }
39916
39917 // At this point, i is the index of the first op past the last valid
39918 // quartet.
39919 var count = Math.min((i - iFirstSave) / 4,
39920 MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
39921 if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
39922 return i;
39923 }
39924
39925 // assuming that heights of those image is too small (~1 pixel)
39926 // packing as much as possible by lines
39927 var maxX = 0;
39928 var map = [], maxLineHeight = 0;
39929 var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING;
39930 var q;
39931 for (q = 0; q < count; q++) {
39932 var transform = argsArray[iFirstTransform + (q << 2)];
39933 var img = argsArray[iFirstPIIXO + (q << 2)][0];
39934 if (currentX + img.width > MAX_WIDTH) {
39935 // starting new line
39936 maxX = Math.max(maxX, currentX);
39937 currentY += maxLineHeight + 2 * IMAGE_PADDING;
39938 currentX = 0;
39939 maxLineHeight = 0;
39940 }
39941 map.push({
39942 transform: transform,
39943 x: currentX, y: currentY,
39944 w: img.width, h: img.height
39945 });
39946 currentX += img.width + 2 * IMAGE_PADDING;
39947 maxLineHeight = Math.max(maxLineHeight, img.height);
39948 }
39949 var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
39950 var imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
39951 var imgData = new Uint8Array(imgWidth * imgHeight * 4);
39952 var imgRowSize = imgWidth << 2;
39953 for (q = 0; q < count; q++) {
39954 var data = argsArray[iFirstPIIXO + (q << 2)][0].data;
39955 // Copy image by lines and extends pixels into padding.
39956 var rowSize = map[q].w << 2;
39957 var dataOffset = 0;
39958 var offset = (map[q].x + map[q].y * imgWidth) << 2;
39959 imgData.set(data.subarray(0, rowSize), offset - imgRowSize);
39960 for (var k = 0, kk = map[q].h; k < kk; k++) {
39961 imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);
39962 dataOffset += rowSize;
39963 offset += imgRowSize;
39964 }
39965 imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset);
39966 while (offset >= 0) {
39967 data[offset - 4] = data[offset];
39968 data[offset - 3] = data[offset + 1];
39969 data[offset - 2] = data[offset + 2];
39970 data[offset - 1] = data[offset + 3];
39971 data[offset + rowSize] = data[offset + rowSize - 4];
39972 data[offset + rowSize + 1] = data[offset + rowSize - 3];
39973 data[offset + rowSize + 2] = data[offset + rowSize - 2];
39974 data[offset + rowSize + 3] = data[offset + rowSize - 1];
39975 offset -= imgRowSize;
39976 }
39977 }
39978
39979 // Replace queue items.
39980 fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup);
39981 argsArray.splice(iFirstSave, count * 4,
39982 [{ width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP,
39983 data: imgData }, map]);
39984
39985 return iFirstSave + 1;
39986 });
39987
39988 // This replaces (save, transform, paintImageMaskXObject, restore)+
39989 // sequences with one |paintImageMaskXObjectGroup| or one
39990 // |paintImageMaskXObjectRepeat| operation.
39991 addState(InitialState,
39992 [OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore],
39993 function foundImageMaskGroup(context) {
39994 var MIN_IMAGES_IN_MASKS_BLOCK = 10;
39995 var MAX_IMAGES_IN_MASKS_BLOCK = 100;
39996 var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
39997
39998 var fnArray = context.fnArray, argsArray = context.argsArray;
39999 var curr = context.iCurr;
40000 var iFirstSave = curr - 3;
40001 var iFirstTransform = curr - 2;
40002 var iFirstPIMXO = curr - 1;
40003
40004 // Look for the quartets.
40005 var i = iFirstSave + 4;
40006 var ii = fnArray.length;
40007 while (i + 3 < ii) {
40008 if (fnArray[i] !== OPS.save ||
40009 fnArray[i + 1] !== OPS.transform ||
40010 fnArray[i + 2] !== OPS.paintImageMaskXObject ||
40011 fnArray[i + 3] !== OPS.restore) {
40012 break; // ops don't match
40013 }
40014 i += 4;
40015 }
40016
40017 // At this point, i is the index of the first op past the last valid
40018 // quartet.
40019 var count = (i - iFirstSave) / 4;
40020 count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray,
40021 argsArray);
40022 if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
40023 return i;
40024 }
40025
40026 var q;
40027 var isSameImage = false;
40028 var iTransform, transformArgs;
40029 var firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
40030 if (argsArray[iFirstTransform][1] === 0 &&
40031 argsArray[iFirstTransform][2] === 0) {
40032 isSameImage = true;
40033 var firstTransformArg0 = argsArray[iFirstTransform][0];
40034 var firstTransformArg3 = argsArray[iFirstTransform][3];
40035 iTransform = iFirstTransform + 4;
40036 var iPIMXO = iFirstPIMXO + 4;
40037 for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
40038 transformArgs = argsArray[iTransform];
40039 if (argsArray[iPIMXO][0] !== firstPIMXOArg0 ||
40040 transformArgs[0] !== firstTransformArg0 ||
40041 transformArgs[1] !== 0 ||
40042 transformArgs[2] !== 0 ||
40043 transformArgs[3] !== firstTransformArg3) {
40044 if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
40045 isSameImage = false;
40046 } else {
40047 count = q;
40048 }
40049 break; // different image or transform
40050 }
40051 }
40052 }
40053
40054 if (isSameImage) {
40055 count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);
40056 var positions = new Float32Array(count * 2);
40057 iTransform = iFirstTransform;
40058 for (q = 0; q < count; q++, iTransform += 4) {
40059 transformArgs = argsArray[iTransform];
40060 positions[(q << 1)] = transformArgs[4];
40061 positions[(q << 1) + 1] = transformArgs[5];
40062 }
40063
40064 // Replace queue items.
40065 fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat);
40066 argsArray.splice(iFirstSave, count * 4,
40067 [firstPIMXOArg0, firstTransformArg0, firstTransformArg3, positions]);
40068 } else {
40069 count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
40070 var images = [];
40071 for (q = 0; q < count; q++) {
40072 transformArgs = argsArray[iFirstTransform + (q << 2)];
40073 var maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
40074 images.push({ data: maskParams.data, width: maskParams.width,
40075 height: maskParams.height,
40076 transform: transformArgs });
40077 }
40078
40079 // Replace queue items.
40080 fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup);
40081 argsArray.splice(iFirstSave, count * 4, [images]);
40082 }
40083
40084 return iFirstSave + 1;
40085 });
40086
40087 // This replaces (save, transform, paintImageXObject, restore)+ sequences
40088 // with one paintImageXObjectRepeat operation, if the |transform| and
40089 // |paintImageXObjectRepeat| ops are appropriate.
40090 addState(InitialState,
40091 [OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore],
40092 function (context) {
40093 var MIN_IMAGES_IN_BLOCK = 3;
40094 var MAX_IMAGES_IN_BLOCK = 1000;
40095
40096 var fnArray = context.fnArray, argsArray = context.argsArray;
40097 var curr = context.iCurr;
40098 var iFirstSave = curr - 3;
40099 var iFirstTransform = curr - 2;
40100 var iFirstPIXO = curr - 1;
40101 var iFirstRestore = curr;
40102
40103 if (argsArray[iFirstTransform][1] !== 0 ||
40104 argsArray[iFirstTransform][2] !== 0) {
40105 return iFirstRestore + 1; // transform has the wrong form
40106 }
40107
40108 // Look for the quartets.
40109 var firstPIXOArg0 = argsArray[iFirstPIXO][0];
40110 var firstTransformArg0 = argsArray[iFirstTransform][0];
40111 var firstTransformArg3 = argsArray[iFirstTransform][3];
40112 var i = iFirstSave + 4;
40113 var ii = fnArray.length;
40114 while (i + 3 < ii) {
40115 if (fnArray[i] !== OPS.save ||
40116 fnArray[i + 1] !== OPS.transform ||
40117 fnArray[i + 2] !== OPS.paintImageXObject ||
40118 fnArray[i + 3] !== OPS.restore) {
40119 break; // ops don't match
40120 }
40121 if (argsArray[i + 1][0] !== firstTransformArg0 ||
40122 argsArray[i + 1][1] !== 0 ||
40123 argsArray[i + 1][2] !== 0 ||
40124 argsArray[i + 1][3] !== firstTransformArg3) {
40125 break; // transforms don't match
40126 }
40127 if (argsArray[i + 2][0] !== firstPIXOArg0) {
40128 break; // images don't match
40129 }
40130 i += 4;
40131 }
40132
40133 // At this point, i is the index of the first op past the last valid
40134 // quartet.
40135 var count = Math.min((i - iFirstSave) / 4, MAX_IMAGES_IN_BLOCK);
40136 if (count < MIN_IMAGES_IN_BLOCK) {
40137 return i;
40138 }
40139
40140 // Extract the (x,y) positions from all of the matching transforms.
40141 var positions = new Float32Array(count * 2);
40142 var iTransform = iFirstTransform;
40143 for (var q = 0; q < count; q++, iTransform += 4) {
40144 var transformArgs = argsArray[iTransform];
40145 positions[(q << 1)] = transformArgs[4];
40146 positions[(q << 1) + 1] = transformArgs[5];
40147 }
40148
40149 // Replace queue items.
40150 var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3,
40151 positions];
40152 fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat);
40153 argsArray.splice(iFirstSave, count * 4, args);
40154
40155 return iFirstSave + 1;
40156 });
40157
40158 // This replaces (beginText, setFont, setTextMatrix, showText, endText)+
40159 // sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+
40160 // sequences, if the font for each one is the same.
40161 addState(InitialState,
40162 [OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText],
40163 function (context) {
40164 var MIN_CHARS_IN_BLOCK = 3;
40165 var MAX_CHARS_IN_BLOCK = 1000;
40166
40167 var fnArray = context.fnArray, argsArray = context.argsArray;
40168 var curr = context.iCurr;
40169 var iFirstBeginText = curr - 4;
40170 var iFirstSetFont = curr - 3;
40171 var iFirstSetTextMatrix = curr - 2;
40172 var iFirstShowText = curr - 1;
40173 var iFirstEndText = curr;
40174
40175 // Look for the quintets.
40176 var firstSetFontArg0 = argsArray[iFirstSetFont][0];
40177 var firstSetFontArg1 = argsArray[iFirstSetFont][1];
40178 var i = iFirstBeginText + 5;
40179 var ii = fnArray.length;
40180 while (i + 4 < ii) {
40181 if (fnArray[i] !== OPS.beginText ||
40182 fnArray[i + 1] !== OPS.setFont ||
40183 fnArray[i + 2] !== OPS.setTextMatrix ||
40184 fnArray[i + 3] !== OPS.showText ||
40185 fnArray[i + 4] !== OPS.endText) {
40186 break; // ops don't match
40187 }
40188 if (argsArray[i + 1][0] !== firstSetFontArg0 ||
40189 argsArray[i + 1][1] !== firstSetFontArg1) {
40190 break; // fonts don't match
40191 }
40192 i += 5;
40193 }
40194
40195 // At this point, i is the index of the first op past the last valid
40196 // quintet.
40197 var count = Math.min(((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK);
40198 if (count < MIN_CHARS_IN_BLOCK) {
40199 return i;
40200 }
40201
40202 // If the preceding quintet is (<something>, setFont, setTextMatrix,
40203 // showText, endText), include that as well. (E.g. <something> might be
40204 // |dependency|.)
40205 var iFirst = iFirstBeginText;
40206 if (iFirstBeginText >= 4 &&
40207 fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] &&
40208 fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] &&
40209 fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] &&
40210 fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] &&
40211 argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 &&
40212 argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
40213 count++;
40214 iFirst -= 5;
40215 }
40216
40217 // Remove (endText, beginText, setFont) trios.
40218 var iEndText = iFirst + 4;
40219 for (var q = 1; q < count; q++) {
40220 fnArray.splice(iEndText, 3);
40221 argsArray.splice(iEndText, 3);
40222 iEndText += 2;
40223 }
40224
40225 return iEndText + 1;
40226 });
40227
40228 function QueueOptimizer() {}
40229
40230 QueueOptimizer.prototype = {
40231 optimize: function QueueOptimizer_optimize(queue) {
40232 var fnArray = queue.fnArray, argsArray = queue.argsArray;
40233 var context = {
40234 iCurr: 0,
40235 fnArray: fnArray,
40236 argsArray: argsArray
40237 };
40238 var state;
40239 var i = 0, ii = fnArray.length;
40240 while (i < ii) {
40241 state = (state || InitialState)[fnArray[i]];
40242 if (typeof state === 'function') { // we found some handler
40243 context.iCurr = i;
40244 // state() returns the index of the first non-matching op (if we
40245 // didn't match) or the first op past the modified ops (if we did
40246 // match and replace).
40247 i = state(context);
40248 state = undefined; // reset the state machine
40249 ii = context.fnArray.length;
40250 } else {
40251 i++;
40252 }
40253 }
40254 }
40255 };
40256 return QueueOptimizer;
40257})();
40258
40259exports.OperatorList = OperatorList;
40260exports.PartialEvaluator = PartialEvaluator;
40261}));
40262
40263
40264(function (root, factory) {
40265 {
40266 factory((root.pdfjsCoreAnnotation = {}), root.pdfjsSharedUtil,
40267 root.pdfjsCorePrimitives, root.pdfjsCoreStream, root.pdfjsCoreColorSpace,
40268 root.pdfjsCoreObj, root.pdfjsCoreEvaluator);
40269 }
40270}(this, function (exports, sharedUtil, corePrimitives, coreStream,
40271 coreColorSpace, coreObj, coreEvaluator) {
40272
40273var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
40274var AnnotationFieldFlag = sharedUtil.AnnotationFieldFlag;
40275var AnnotationFlag = sharedUtil.AnnotationFlag;
40276var AnnotationType = sharedUtil.AnnotationType;
40277var OPS = sharedUtil.OPS;
40278var Util = sharedUtil.Util;
40279var isBool = sharedUtil.isBool;
40280var isString = sharedUtil.isString;
40281var isArray = sharedUtil.isArray;
40282var isInt = sharedUtil.isInt;
40283var isValidUrl = sharedUtil.isValidUrl;
40284var stringToBytes = sharedUtil.stringToBytes;
40285var stringToPDFString = sharedUtil.stringToPDFString;
40286var stringToUTF8String = sharedUtil.stringToUTF8String;
40287var warn = sharedUtil.warn;
40288var Dict = corePrimitives.Dict;
40289var isDict = corePrimitives.isDict;
40290var isName = corePrimitives.isName;
40291var isRef = corePrimitives.isRef;
40292var Stream = coreStream.Stream;
40293var ColorSpace = coreColorSpace.ColorSpace;
40294var ObjectLoader = coreObj.ObjectLoader;
40295var FileSpec = coreObj.FileSpec;
40296var OperatorList = coreEvaluator.OperatorList;
40297
40298/**
40299 * @class
40300 * @alias AnnotationFactory
40301 */
40302function AnnotationFactory() {}
40303AnnotationFactory.prototype = /** @lends AnnotationFactory.prototype */ {
40304 /**
40305 * @param {XRef} xref
40306 * @param {Object} ref
40307 * @param {string} uniquePrefix
40308 * @param {Object} idCounters
40309 * @returns {Annotation}
40310 */
40311 create: function AnnotationFactory_create(xref, ref,
40312 uniquePrefix, idCounters) {
40313 var dict = xref.fetchIfRef(ref);
40314 if (!isDict(dict)) {
40315 return;
40316 }
40317 var id = isRef(ref) ? ref.toString() :
40318 'annot_' + (uniquePrefix || '') + (++idCounters.obj);
40319
40320 // Determine the annotation's subtype.
40321 var subtype = dict.get('Subtype');
40322 subtype = isName(subtype) ? subtype.name : null;
40323
40324 // Return the right annotation object based on the subtype and field type.
40325 var parameters = {
40326 xref: xref,
40327 dict: dict,
40328 ref: isRef(ref) ? ref : null,
40329 subtype: subtype,
40330 id: id,
40331 };
40332
40333 switch (subtype) {
40334 case 'Link':
40335 return new LinkAnnotation(parameters);
40336
40337 case 'Text':
40338 return new TextAnnotation(parameters);
40339
40340 case 'Widget':
40341 var fieldType = Util.getInheritableProperty(dict, 'FT');
40342 fieldType = isName(fieldType) ? fieldType.name : null;
40343
40344 switch (fieldType) {
40345 case 'Tx':
40346 return new TextWidgetAnnotation(parameters);
40347 }
40348 warn('Unimplemented widget field type "' + fieldType + '", ' +
40349 'falling back to base field type.');
40350 return new WidgetAnnotation(parameters);
40351
40352 case 'Popup':
40353 return new PopupAnnotation(parameters);
40354
40355 case 'Highlight':
40356 return new HighlightAnnotation(parameters);
40357
40358 case 'Underline':
40359 return new UnderlineAnnotation(parameters);
40360
40361 case 'Squiggly':
40362 return new SquigglyAnnotation(parameters);
40363
40364 case 'StrikeOut':
40365 return new StrikeOutAnnotation(parameters);
40366
40367 case 'FileAttachment':
40368 return new FileAttachmentAnnotation(parameters);
40369
40370 default:
40371 if (!subtype) {
40372 warn('Annotation is missing the required /Subtype.');
40373 } else {
40374 warn('Unimplemented annotation type "' + subtype + '", ' +
40375 'falling back to base annotation.');
40376 }
40377 return new Annotation(parameters);
40378 }
40379 }
40380};
40381
40382var Annotation = (function AnnotationClosure() {
40383 // 12.5.5: Algorithm: Appearance streams
40384 function getTransformMatrix(rect, bbox, matrix) {
40385 var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix);
40386 var minX = bounds[0];
40387 var minY = bounds[1];
40388 var maxX = bounds[2];
40389 var maxY = bounds[3];
40390
40391 if (minX === maxX || minY === maxY) {
40392 // From real-life file, bbox was [0, 0, 0, 0]. In this case,
40393 // just apply the transform for rect
40394 return [1, 0, 0, 1, rect[0], rect[1]];
40395 }
40396
40397 var xRatio = (rect[2] - rect[0]) / (maxX - minX);
40398 var yRatio = (rect[3] - rect[1]) / (maxY - minY);
40399 return [
40400 xRatio,
40401 0,
40402 0,
40403 yRatio,
40404 rect[0] - minX * xRatio,
40405 rect[1] - minY * yRatio
40406 ];
40407 }
40408
40409 function getDefaultAppearance(dict) {
40410 var appearanceState = dict.get('AP');
40411 if (!isDict(appearanceState)) {
40412 return;
40413 }
40414
40415 var appearance;
40416 var appearances = appearanceState.get('N');
40417 if (isDict(appearances)) {
40418 var as = dict.get('AS');
40419 if (as && appearances.has(as.name)) {
40420 appearance = appearances.get(as.name);
40421 }
40422 } else {
40423 appearance = appearances;
40424 }
40425 return appearance;
40426 }
40427
40428 function Annotation(params) {
40429 var dict = params.dict;
40430
40431 this.setFlags(dict.get('F'));
40432 this.setRectangle(dict.getArray('Rect'));
40433 this.setColor(dict.getArray('C'));
40434 this.setBorderStyle(dict);
40435 this.appearance = getDefaultAppearance(dict);
40436
40437 // Expose public properties using a data object.
40438 this.data = {};
40439 this.data.id = params.id;
40440 this.data.subtype = params.subtype;
40441 this.data.annotationFlags = this.flags;
40442 this.data.rect = this.rectangle;
40443 this.data.color = this.color;
40444 this.data.borderStyle = this.borderStyle;
40445 this.data.hasAppearance = !!this.appearance;
40446 }
40447
40448 Annotation.prototype = {
40449 /**
40450 * @private
40451 */
40452 _hasFlag: function Annotation_hasFlag(flags, flag) {
40453 return !!(flags & flag);
40454 },
40455
40456 /**
40457 * @private
40458 */
40459 _isViewable: function Annotation_isViewable(flags) {
40460 return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
40461 !this._hasFlag(flags, AnnotationFlag.HIDDEN) &&
40462 !this._hasFlag(flags, AnnotationFlag.NOVIEW);
40463 },
40464
40465 /**
40466 * @private
40467 */
40468 _isPrintable: function AnnotationFlag_isPrintable(flags) {
40469 return this._hasFlag(flags, AnnotationFlag.PRINT) &&
40470 !this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
40471 !this._hasFlag(flags, AnnotationFlag.HIDDEN);
40472 },
40473
40474 /**
40475 * @return {boolean}
40476 */
40477 get viewable() {
40478 if (this.flags === 0) {
40479 return true;
40480 }
40481 return this._isViewable(this.flags);
40482 },
40483
40484 /**
40485 * @return {boolean}
40486 */
40487 get printable() {
40488 if (this.flags === 0) {
40489 return false;
40490 }
40491 return this._isPrintable(this.flags);
40492 },
40493
40494 /**
40495 * Set the flags.
40496 *
40497 * @public
40498 * @memberof Annotation
40499 * @param {number} flags - Unsigned 32-bit integer specifying annotation
40500 * characteristics
40501 * @see {@link shared/util.js}
40502 */
40503 setFlags: function Annotation_setFlags(flags) {
40504 this.flags = (isInt(flags) && flags > 0) ? flags : 0;
40505 },
40506
40507 /**
40508 * Check if a provided flag is set.
40509 *
40510 * @public
40511 * @memberof Annotation
40512 * @param {number} flag - Hexadecimal representation for an annotation
40513 * characteristic
40514 * @return {boolean}
40515 * @see {@link shared/util.js}
40516 */
40517 hasFlag: function Annotation_hasFlag(flag) {
40518 return this._hasFlag(this.flags, flag);
40519 },
40520
40521 /**
40522 * Set the rectangle.
40523 *
40524 * @public
40525 * @memberof Annotation
40526 * @param {Array} rectangle - The rectangle array with exactly four entries
40527 */
40528 setRectangle: function Annotation_setRectangle(rectangle) {
40529 if (isArray(rectangle) && rectangle.length === 4) {
40530 this.rectangle = Util.normalizeRect(rectangle);
40531 } else {
40532 this.rectangle = [0, 0, 0, 0];
40533 }
40534 },
40535
40536 /**
40537 * Set the color and take care of color space conversion.
40538 *
40539 * @public
40540 * @memberof Annotation
40541 * @param {Array} color - The color array containing either 0
40542 * (transparent), 1 (grayscale), 3 (RGB) or
40543 * 4 (CMYK) elements
40544 */
40545 setColor: function Annotation_setColor(color) {
40546 var rgbColor = new Uint8Array(3); // Black in RGB color space (default)
40547 if (!isArray(color)) {
40548 this.color = rgbColor;
40549 return;
40550 }
40551
40552 switch (color.length) {
40553 case 0: // Transparent, which we indicate with a null value
40554 this.color = null;
40555 break;
40556
40557 case 1: // Convert grayscale to RGB
40558 ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
40559 this.color = rgbColor;
40560 break;
40561
40562 case 3: // Convert RGB percentages to RGB
40563 ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
40564 this.color = rgbColor;
40565 break;
40566
40567 case 4: // Convert CMYK to RGB
40568 ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
40569 this.color = rgbColor;
40570 break;
40571
40572 default:
40573 this.color = rgbColor;
40574 break;
40575 }
40576 },
40577
40578 /**
40579 * Set the border style (as AnnotationBorderStyle object).
40580 *
40581 * @public
40582 * @memberof Annotation
40583 * @param {Dict} borderStyle - The border style dictionary
40584 */
40585 setBorderStyle: function Annotation_setBorderStyle(borderStyle) {
40586 this.borderStyle = new AnnotationBorderStyle();
40587 if (!isDict(borderStyle)) {
40588 return;
40589 }
40590 if (borderStyle.has('BS')) {
40591 var dict = borderStyle.get('BS');
40592 var dictType = dict.get('Type');
40593
40594 if (!dictType || isName(dictType, 'Border')) {
40595 this.borderStyle.setWidth(dict.get('W'));
40596 this.borderStyle.setStyle(dict.get('S'));
40597 this.borderStyle.setDashArray(dict.getArray('D'));
40598 }
40599 } else if (borderStyle.has('Border')) {
40600 var array = borderStyle.getArray('Border');
40601 if (isArray(array) && array.length >= 3) {
40602 this.borderStyle.setHorizontalCornerRadius(array[0]);
40603 this.borderStyle.setVerticalCornerRadius(array[1]);
40604 this.borderStyle.setWidth(array[2]);
40605
40606 if (array.length === 4) { // Dash array available
40607 this.borderStyle.setDashArray(array[3]);
40608 }
40609 }
40610 } else {
40611 // There are no border entries in the dictionary. According to the
40612 // specification, we should draw a solid border of width 1 in that
40613 // case, but Adobe Reader did not implement that part of the
40614 // specification and instead draws no border at all, so we do the same.
40615 // See also https://github.com/mozilla/pdf.js/issues/6179.
40616 this.borderStyle.setWidth(0);
40617 }
40618 },
40619
40620 /**
40621 * Prepare the annotation for working with a popup in the display layer.
40622 *
40623 * @private
40624 * @memberof Annotation
40625 * @param {Dict} dict - The annotation's data dictionary
40626 */
40627 _preparePopup: function Annotation_preparePopup(dict) {
40628 if (!dict.has('C')) {
40629 // Fall back to the default background color.
40630 this.data.color = null;
40631 }
40632
40633 this.data.hasPopup = dict.has('Popup');
40634 this.data.title = stringToPDFString(dict.get('T') || '');
40635 this.data.contents = stringToPDFString(dict.get('Contents') || '');
40636 },
40637
40638 loadResources: function Annotation_loadResources(keys) {
40639 return new Promise(function (resolve, reject) {
40640 this.appearance.dict.getAsync('Resources').then(function (resources) {
40641 if (!resources) {
40642 resolve();
40643 return;
40644 }
40645 var objectLoader = new ObjectLoader(resources.map,
40646 keys,
40647 resources.xref);
40648 objectLoader.load().then(function() {
40649 resolve(resources);
40650 }, reject);
40651 }, reject);
40652 }.bind(this));
40653 },
40654
40655 getOperatorList: function Annotation_getOperatorList(evaluator, task,
40656 renderForms) {
40657 if (!this.appearance) {
40658 return Promise.resolve(new OperatorList());
40659 }
40660
40661 var data = this.data;
40662 var appearanceDict = this.appearance.dict;
40663 var resourcesPromise = this.loadResources([
40664 'ExtGState',
40665 'ColorSpace',
40666 'Pattern',
40667 'Shading',
40668 'XObject',
40669 'Font'
40670 // ProcSet
40671 // Properties
40672 ]);
40673 var bbox = appearanceDict.getArray('BBox') || [0, 0, 1, 1];
40674 var matrix = appearanceDict.getArray('Matrix') || [1, 0, 0, 1, 0 ,0];
40675 var transform = getTransformMatrix(data.rect, bbox, matrix);
40676 var self = this;
40677
40678 return resourcesPromise.then(function(resources) {
40679 var opList = new OperatorList();
40680 opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
40681 return evaluator.getOperatorList(self.appearance, task,
40682 resources, opList).
40683 then(function () {
40684 opList.addOp(OPS.endAnnotation, []);
40685 self.appearance.reset();
40686 return opList;
40687 });
40688 });
40689 }
40690 };
40691
40692 Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
40693 annotations, opList, partialEvaluator, task, intent, renderForms) {
40694 var annotationPromises = [];
40695 for (var i = 0, n = annotations.length; i < n; ++i) {
40696 if ((intent === 'display' && annotations[i].viewable) ||
40697 (intent === 'print' && annotations[i].printable)) {
40698 annotationPromises.push(
40699 annotations[i].getOperatorList(partialEvaluator, task, renderForms));
40700 }
40701 }
40702 return Promise.all(annotationPromises).then(function(operatorLists) {
40703 opList.addOp(OPS.beginAnnotations, []);
40704 for (var i = 0, n = operatorLists.length; i < n; ++i) {
40705 opList.addOpList(operatorLists[i]);
40706 }
40707 opList.addOp(OPS.endAnnotations, []);
40708 });
40709 };
40710
40711 return Annotation;
40712})();
40713
40714/**
40715 * Contains all data regarding an annotation's border style.
40716 *
40717 * @class
40718 */
40719var AnnotationBorderStyle = (function AnnotationBorderStyleClosure() {
40720 /**
40721 * @constructor
40722 * @private
40723 */
40724 function AnnotationBorderStyle() {
40725 this.width = 1;
40726 this.style = AnnotationBorderStyleType.SOLID;
40727 this.dashArray = [3];
40728 this.horizontalCornerRadius = 0;
40729 this.verticalCornerRadius = 0;
40730 }
40731
40732 AnnotationBorderStyle.prototype = {
40733 /**
40734 * Set the width.
40735 *
40736 * @public
40737 * @memberof AnnotationBorderStyle
40738 * @param {integer} width - The width
40739 */
40740 setWidth: function AnnotationBorderStyle_setWidth(width) {
40741 if (width === (width | 0)) {
40742 this.width = width;
40743 }
40744 },
40745
40746 /**
40747 * Set the style.
40748 *
40749 * @public
40750 * @memberof AnnotationBorderStyle
40751 * @param {Object} style - The style object
40752 * @see {@link shared/util.js}
40753 */
40754 setStyle: function AnnotationBorderStyle_setStyle(style) {
40755 if (!style) {
40756 return;
40757 }
40758 switch (style.name) {
40759 case 'S':
40760 this.style = AnnotationBorderStyleType.SOLID;
40761 break;
40762
40763 case 'D':
40764 this.style = AnnotationBorderStyleType.DASHED;
40765 break;
40766
40767 case 'B':
40768 this.style = AnnotationBorderStyleType.BEVELED;
40769 break;
40770
40771 case 'I':
40772 this.style = AnnotationBorderStyleType.INSET;
40773 break;
40774
40775 case 'U':
40776 this.style = AnnotationBorderStyleType.UNDERLINE;
40777 break;
40778
40779 default:
40780 break;
40781 }
40782 },
40783
40784 /**
40785 * Set the dash array.
40786 *
40787 * @public
40788 * @memberof AnnotationBorderStyle
40789 * @param {Array} dashArray - The dash array with at least one element
40790 */
40791 setDashArray: function AnnotationBorderStyle_setDashArray(dashArray) {
40792 // We validate the dash array, but we do not use it because CSS does not
40793 // allow us to change spacing of dashes. For more information, visit
40794 // http://www.w3.org/TR/css3-background/#the-border-style.
40795 if (isArray(dashArray) && dashArray.length > 0) {
40796 // According to the PDF specification: the elements in a dashArray
40797 // shall be numbers that are nonnegative and not all equal to zero.
40798 var isValid = true;
40799 var allZeros = true;
40800 for (var i = 0, len = dashArray.length; i < len; i++) {
40801 var element = dashArray[i];
40802 var validNumber = (+element >= 0);
40803 if (!validNumber) {
40804 isValid = false;
40805 break;
40806 } else if (element > 0) {
40807 allZeros = false;
40808 }
40809 }
40810 if (isValid && !allZeros) {
40811 this.dashArray = dashArray;
40812 } else {
40813 this.width = 0; // Adobe behavior when the array is invalid.
40814 }
40815 } else if (dashArray) {
40816 this.width = 0; // Adobe behavior when the array is invalid.
40817 }
40818 },
40819
40820 /**
40821 * Set the horizontal corner radius (from a Border dictionary).
40822 *
40823 * @public
40824 * @memberof AnnotationBorderStyle
40825 * @param {integer} radius - The horizontal corner radius
40826 */
40827 setHorizontalCornerRadius:
40828 function AnnotationBorderStyle_setHorizontalCornerRadius(radius) {
40829 if (radius === (radius | 0)) {
40830 this.horizontalCornerRadius = radius;
40831 }
40832 },
40833
40834 /**
40835 * Set the vertical corner radius (from a Border dictionary).
40836 *
40837 * @public
40838 * @memberof AnnotationBorderStyle
40839 * @param {integer} radius - The vertical corner radius
40840 */
40841 setVerticalCornerRadius:
40842 function AnnotationBorderStyle_setVerticalCornerRadius(radius) {
40843 if (radius === (radius | 0)) {
40844 this.verticalCornerRadius = radius;
40845 }
40846 }
40847 };
40848
40849 return AnnotationBorderStyle;
40850})();
40851
40852var WidgetAnnotation = (function WidgetAnnotationClosure() {
40853 function WidgetAnnotation(params) {
40854 Annotation.call(this, params);
40855
40856 var dict = params.dict;
40857 var data = this.data;
40858
40859 data.annotationType = AnnotationType.WIDGET;
40860 data.fieldValue = stringToPDFString(
40861 Util.getInheritableProperty(dict, 'V') || '');
40862 data.alternativeText = stringToPDFString(dict.get('TU') || '');
40863 data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || '';
40864 var fieldType = Util.getInheritableProperty(dict, 'FT');
40865 data.fieldType = isName(fieldType) ? fieldType.name : null;
40866 this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty;
40867
40868 data.fieldFlags = Util.getInheritableProperty(dict, 'Ff');
40869 if (!isInt(data.fieldFlags) || data.fieldFlags < 0) {
40870 data.fieldFlags = 0;
40871 }
40872
40873 // Hide signatures because we cannot validate them.
40874 if (data.fieldType === 'Sig') {
40875 this.setFlags(AnnotationFlag.HIDDEN);
40876 }
40877
40878 // Building the full field name by collecting the field and
40879 // its ancestors 'T' data and joining them using '.'.
40880 var fieldName = [];
40881 var namedItem = dict;
40882 var ref = params.ref;
40883 while (namedItem) {
40884 var parent = namedItem.get('Parent');
40885 var parentRef = namedItem.getRaw('Parent');
40886 var name = namedItem.get('T');
40887 if (name) {
40888 fieldName.unshift(stringToPDFString(name));
40889 } else if (parent && ref) {
40890 // The field name is absent, that means more than one field
40891 // with the same name may exist. Replacing the empty name
40892 // with the '`' plus index in the parent's 'Kids' array.
40893 // This is not in the PDF spec but necessary to id the
40894 // the input controls.
40895 var kids = parent.get('Kids');
40896 var j, jj;
40897 for (j = 0, jj = kids.length; j < jj; j++) {
40898 var kidRef = kids[j];
40899 if (kidRef.num === ref.num && kidRef.gen === ref.gen) {
40900 break;
40901 }
40902 }
40903 fieldName.unshift('`' + j);
40904 }
40905 namedItem = parent;
40906 ref = parentRef;
40907 }
40908 data.fullName = fieldName.join('.');
40909 }
40910
40911 Util.inherit(WidgetAnnotation, Annotation, {
40912 /**
40913 * Check if a provided field flag is set.
40914 *
40915 * @public
40916 * @memberof WidgetAnnotation
40917 * @param {number} flag - Hexadecimal representation for an annotation
40918 * field characteristic
40919 * @return {boolean}
40920 * @see {@link shared/util.js}
40921 */
40922 hasFieldFlag: function WidgetAnnotation_hasFieldFlag(flag) {
40923 return !!(this.data.fieldFlags & flag);
40924 },
40925 });
40926
40927 return WidgetAnnotation;
40928})();
40929
40930var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
40931 function TextWidgetAnnotation(params) {
40932 WidgetAnnotation.call(this, params);
40933
40934 // Determine the alignment of text in the field.
40935 var alignment = Util.getInheritableProperty(params.dict, 'Q');
40936 if (!isInt(alignment) || alignment < 0 || alignment > 2) {
40937 alignment = null;
40938 }
40939 this.data.textAlignment = alignment;
40940
40941 // Determine the maximum length of text in the field.
40942 var maximumLength = Util.getInheritableProperty(params.dict, 'MaxLen');
40943 if (!isInt(maximumLength) || maximumLength < 0) {
40944 maximumLength = null;
40945 }
40946 this.data.maxLen = maximumLength;
40947
40948 // Process field flags for the display layer.
40949 this.data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
40950 this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE);
40951 this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) &&
40952 !this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) &&
40953 !this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) &&
40954 !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
40955 this.data.maxLen !== null;
40956 }
40957
40958 Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
40959 getOperatorList:
40960 function TextWidgetAnnotation_getOperatorList(evaluator, task,
40961 renderForms) {
40962 var operatorList = new OperatorList();
40963
40964 // Do not render form elements on the canvas when interactive forms are
40965 // enabled. The display layer is responsible for rendering them instead.
40966 if (renderForms) {
40967 return Promise.resolve(operatorList);
40968 }
40969
40970 if (this.appearance) {
40971 return Annotation.prototype.getOperatorList.call(this, evaluator, task,
40972 renderForms);
40973 }
40974
40975 // Even if there is an appearance stream, ignore it. This is the
40976 // behaviour used by Adobe Reader.
40977 if (!this.data.defaultAppearance) {
40978 return Promise.resolve(operatorList);
40979 }
40980
40981 var stream = new Stream(stringToBytes(this.data.defaultAppearance));
40982 return evaluator.getOperatorList(stream, task, this.fieldResources,
40983 operatorList).
40984 then(function () {
40985 return operatorList;
40986 });
40987 }
40988 });
40989
40990 return TextWidgetAnnotation;
40991})();
40992
40993var TextAnnotation = (function TextAnnotationClosure() {
40994 var DEFAULT_ICON_SIZE = 22; // px
40995
40996 function TextAnnotation(parameters) {
40997 Annotation.call(this, parameters);
40998
40999 this.data.annotationType = AnnotationType.TEXT;
41000
41001 if (this.data.hasAppearance) {
41002 this.data.name = 'NoIcon';
41003 } else {
41004 this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;
41005 this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;
41006 this.data.name = parameters.dict.has('Name') ?
41007 parameters.dict.get('Name').name : 'Note';
41008 }
41009 this._preparePopup(parameters.dict);
41010 }
41011
41012 Util.inherit(TextAnnotation, Annotation, {});
41013
41014 return TextAnnotation;
41015})();
41016
41017var LinkAnnotation = (function LinkAnnotationClosure() {
41018 function LinkAnnotation(params) {
41019 Annotation.call(this, params);
41020
41021 var dict = params.dict;
41022 var data = this.data;
41023 data.annotationType = AnnotationType.LINK;
41024
41025 var action = dict.get('A'), url, dest;
41026 if (action && isDict(action)) {
41027 var linkType = action.get('S').name;
41028 switch (linkType) {
41029 case 'URI':
41030 url = action.get('URI');
41031 if (isName(url)) {
41032 // Some bad PDFs do not put parentheses around relative URLs.
41033 url = '/' + url.name;
41034 } else if (url) {
41035 url = addDefaultProtocolToUrl(url);
41036 }
41037 // TODO: pdf spec mentions urls can be relative to a Base
41038 // entry in the dictionary.
41039 break;
41040
41041 case 'GoTo':
41042 dest = action.get('D');
41043 break;
41044
41045 case 'GoToR':
41046 var urlDict = action.get('F');
41047 if (isDict(urlDict)) {
41048 // We assume that we found a FileSpec dictionary
41049 // and fetch the URL without checking any further.
41050 url = urlDict.get('F') || null;
41051 } else if (isString(urlDict)) {
41052 url = urlDict;
41053 }
41054
41055 // NOTE: the destination is relative to the *remote* document.
41056 var remoteDest = action.get('D');
41057 if (remoteDest) {
41058 if (isName(remoteDest)) {
41059 remoteDest = remoteDest.name;
41060 }
41061 if (isString(url)) {
41062 var baseUrl = url.split('#')[0];
41063 if (isString(remoteDest)) {
41064 // In practice, a named destination may contain only a number.
41065 // If that happens, use the '#nameddest=' form to avoid the link
41066 // redirecting to a page, instead of the correct destination.
41067 url = baseUrl + '#' +
41068 (/^\d+$/.test(remoteDest) ? 'nameddest=' : '') + remoteDest;
41069 } else if (isArray(remoteDest)) {
41070 url = baseUrl + '#' + JSON.stringify(remoteDest);
41071 }
41072 }
41073 }
41074 // The 'NewWindow' property, equal to `LinkTarget.BLANK`.
41075 var newWindow = action.get('NewWindow');
41076 if (isBool(newWindow)) {
41077 data.newWindow = newWindow;
41078 }
41079 break;
41080
41081 case 'Named':
41082 data.action = action.get('N').name;
41083 break;
41084
41085 default:
41086 warn('unrecognized link type: ' + linkType);
41087 }
41088 } else if (dict.has('Dest')) { // Simple destination link.
41089 dest = dict.get('Dest');
41090 }
41091
41092 if (url) {
41093 if (isValidUrl(url, /* allowRelative = */ false)) {
41094 data.url = tryConvertUrlEncoding(url);
41095 }
41096 }
41097 if (dest) {
41098 data.dest = isName(dest) ? dest.name : dest;
41099 }
41100 }
41101
41102 // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
41103 function addDefaultProtocolToUrl(url) {
41104 if (isString(url) && url.indexOf('www.') === 0) {
41105 return ('http://' + url);
41106 }
41107 return url;
41108 }
41109
41110 function tryConvertUrlEncoding(url) {
41111 // According to ISO 32000-1:2008, section 12.6.4.7, URIs should be encoded
41112 // in 7-bit ASCII. Some bad PDFs use UTF-8 encoding, see Bugzilla 1122280.
41113 try {
41114 return stringToUTF8String(url);
41115 } catch (e) {
41116 return url;
41117 }
41118 }
41119
41120 Util.inherit(LinkAnnotation, Annotation, {});
41121
41122 return LinkAnnotation;
41123})();
41124
41125var PopupAnnotation = (function PopupAnnotationClosure() {
41126 function PopupAnnotation(parameters) {
41127 Annotation.call(this, parameters);
41128
41129 this.data.annotationType = AnnotationType.POPUP;
41130
41131 var dict = parameters.dict;
41132 var parentItem = dict.get('Parent');
41133 if (!parentItem) {
41134 warn('Popup annotation has a missing or invalid parent annotation.');
41135 return;
41136 }
41137
41138 this.data.parentId = dict.getRaw('Parent').toString();
41139 this.data.title = stringToPDFString(parentItem.get('T') || '');
41140 this.data.contents = stringToPDFString(parentItem.get('Contents') || '');
41141
41142 if (!parentItem.has('C')) {
41143 // Fall back to the default background color.
41144 this.data.color = null;
41145 } else {
41146 this.setColor(parentItem.getArray('C'));
41147 this.data.color = this.color;
41148 }
41149
41150 // If the Popup annotation is not viewable, but the parent annotation is,
41151 // that is most likely a bug. Fallback to inherit the flags from the parent
41152 // annotation (this is consistent with the behaviour in Adobe Reader).
41153 if (!this.viewable) {
41154 var parentFlags = parentItem.get('F');
41155 if (this._isViewable(parentFlags)) {
41156 this.setFlags(parentFlags);
41157 }
41158 }
41159 }
41160
41161 Util.inherit(PopupAnnotation, Annotation, {});
41162
41163 return PopupAnnotation;
41164})();
41165
41166var HighlightAnnotation = (function HighlightAnnotationClosure() {
41167 function HighlightAnnotation(parameters) {
41168 Annotation.call(this, parameters);
41169
41170 this.data.annotationType = AnnotationType.HIGHLIGHT;
41171 this._preparePopup(parameters.dict);
41172
41173 // PDF viewers completely ignore any border styles.
41174 this.data.borderStyle.setWidth(0);
41175 }
41176
41177 Util.inherit(HighlightAnnotation, Annotation, {});
41178
41179 return HighlightAnnotation;
41180})();
41181
41182var UnderlineAnnotation = (function UnderlineAnnotationClosure() {
41183 function UnderlineAnnotation(parameters) {
41184 Annotation.call(this, parameters);
41185
41186 this.data.annotationType = AnnotationType.UNDERLINE;
41187 this._preparePopup(parameters.dict);
41188
41189 // PDF viewers completely ignore any border styles.
41190 this.data.borderStyle.setWidth(0);
41191 }
41192
41193 Util.inherit(UnderlineAnnotation, Annotation, {});
41194
41195 return UnderlineAnnotation;
41196})();
41197
41198var SquigglyAnnotation = (function SquigglyAnnotationClosure() {
41199 function SquigglyAnnotation(parameters) {
41200 Annotation.call(this, parameters);
41201
41202 this.data.annotationType = AnnotationType.SQUIGGLY;
41203 this._preparePopup(parameters.dict);
41204
41205 // PDF viewers completely ignore any border styles.
41206 this.data.borderStyle.setWidth(0);
41207 }
41208
41209 Util.inherit(SquigglyAnnotation, Annotation, {});
41210
41211 return SquigglyAnnotation;
41212})();
41213
41214var StrikeOutAnnotation = (function StrikeOutAnnotationClosure() {
41215 function StrikeOutAnnotation(parameters) {
41216 Annotation.call(this, parameters);
41217
41218 this.data.annotationType = AnnotationType.STRIKEOUT;
41219 this._preparePopup(parameters.dict);
41220
41221 // PDF viewers completely ignore any border styles.
41222 this.data.borderStyle.setWidth(0);
41223 }
41224
41225 Util.inherit(StrikeOutAnnotation, Annotation, {});
41226
41227 return StrikeOutAnnotation;
41228})();
41229
41230var FileAttachmentAnnotation = (function FileAttachmentAnnotationClosure() {
41231 function FileAttachmentAnnotation(parameters) {
41232 Annotation.call(this, parameters);
41233
41234 var file = new FileSpec(parameters.dict.get('FS'), parameters.xref);
41235
41236 this.data.annotationType = AnnotationType.FILEATTACHMENT;
41237 this.data.file = file.serializable;
41238 this._preparePopup(parameters.dict);
41239 }
41240
41241 Util.inherit(FileAttachmentAnnotation, Annotation, {});
41242
41243 return FileAttachmentAnnotation;
41244})();
41245
41246exports.Annotation = Annotation;
41247exports.AnnotationBorderStyle = AnnotationBorderStyle;
41248exports.AnnotationFactory = AnnotationFactory;
41249}));
41250
41251
41252(function (root, factory) {
41253 {
41254 factory((root.pdfjsCoreDocument = {}), root.pdfjsSharedUtil,
41255 root.pdfjsCorePrimitives, root.pdfjsCoreStream,
41256 root.pdfjsCoreObj, root.pdfjsCoreParser, root.pdfjsCoreCrypto,
41257 root.pdfjsCoreEvaluator, root.pdfjsCoreAnnotation);
41258 }
41259}(this, function (exports, sharedUtil, corePrimitives, coreStream, coreObj,
41260 coreParser, coreCrypto, coreEvaluator, coreAnnotation) {
41261
41262var MissingDataException = sharedUtil.MissingDataException;
41263var Util = sharedUtil.Util;
41264var assert = sharedUtil.assert;
41265var error = sharedUtil.error;
41266var info = sharedUtil.info;
41267var isArray = sharedUtil.isArray;
41268var isArrayBuffer = sharedUtil.isArrayBuffer;
41269var isString = sharedUtil.isString;
41270var shadow = sharedUtil.shadow;
41271var stringToBytes = sharedUtil.stringToBytes;
41272var stringToPDFString = sharedUtil.stringToPDFString;
41273var warn = sharedUtil.warn;
41274var isSpace = sharedUtil.isSpace;
41275var Dict = corePrimitives.Dict;
41276var isDict = corePrimitives.isDict;
41277var isName = corePrimitives.isName;
41278var isStream = corePrimitives.isStream;
41279var NullStream = coreStream.NullStream;
41280var Stream = coreStream.Stream;
41281var StreamsSequenceStream = coreStream.StreamsSequenceStream;
41282var Catalog = coreObj.Catalog;
41283var ObjectLoader = coreObj.ObjectLoader;
41284var XRef = coreObj.XRef;
41285var Linearization = coreParser.Linearization;
41286var calculateMD5 = coreCrypto.calculateMD5;
41287var OperatorList = coreEvaluator.OperatorList;
41288var PartialEvaluator = coreEvaluator.PartialEvaluator;
41289var Annotation = coreAnnotation.Annotation;
41290var AnnotationFactory = coreAnnotation.AnnotationFactory;
41291
41292var Page = (function PageClosure() {
41293
41294 var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
41295
41296 function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) {
41297 this.pdfManager = pdfManager;
41298 this.pageIndex = pageIndex;
41299 this.pageDict = pageDict;
41300 this.xref = xref;
41301 this.ref = ref;
41302 this.fontCache = fontCache;
41303 this.uniquePrefix = 'p' + this.pageIndex + '_';
41304 this.idCounters = {
41305 obj: 0
41306 };
41307 this.evaluatorOptions = pdfManager.evaluatorOptions;
41308 this.resourcesPromise = null;
41309 }
41310
41311 Page.prototype = {
41312 getPageProp: function Page_getPageProp(key) {
41313 return this.pageDict.get(key);
41314 },
41315
41316 getInheritedPageProp: function Page_getInheritedPageProp(key) {
41317 var dict = this.pageDict, valueArray = null, loopCount = 0;
41318 var MAX_LOOP_COUNT = 100;
41319 // Always walk up the entire parent chain, to be able to find
41320 // e.g. \Resources placed on multiple levels of the tree.
41321 while (dict) {
41322 var value = dict.get(key);
41323 if (value) {
41324 if (!valueArray) {
41325 valueArray = [];
41326 }
41327 valueArray.push(value);
41328 }
41329 if (++loopCount > MAX_LOOP_COUNT) {
41330 warn('Page_getInheritedPageProp: maximum loop count exceeded.');
41331 break;
41332 }
41333 dict = dict.get('Parent');
41334 }
41335 if (!valueArray) {
41336 return Dict.empty;
41337 }
41338 if (valueArray.length === 1 || !isDict(valueArray[0]) ||
41339 loopCount > MAX_LOOP_COUNT) {
41340 return valueArray[0];
41341 }
41342 return Dict.merge(this.xref, valueArray);
41343 },
41344
41345 get content() {
41346 return this.getPageProp('Contents');
41347 },
41348
41349 get resources() {
41350 // For robustness: The spec states that a \Resources entry has to be
41351 // present, but can be empty. Some document omit it still, in this case
41352 // we return an empty dictionary.
41353 return shadow(this, 'resources', this.getInheritedPageProp('Resources'));
41354 },
41355
41356 get mediaBox() {
41357 var obj = this.getInheritedPageProp('MediaBox');
41358 // Reset invalid media box to letter size.
41359 if (!isArray(obj) || obj.length !== 4) {
41360 obj = LETTER_SIZE_MEDIABOX;
41361 }
41362 return shadow(this, 'mediaBox', obj);
41363 },
41364
41365 get view() {
41366 var mediaBox = this.mediaBox;
41367 var cropBox = this.getInheritedPageProp('CropBox');
41368 if (!isArray(cropBox) || cropBox.length !== 4) {
41369 return shadow(this, 'view', mediaBox);
41370 }
41371
41372 // From the spec, 6th ed., p.963:
41373 // "The crop, bleed, trim, and art boxes should not ordinarily
41374 // extend beyond the boundaries of the media box. If they do, they are
41375 // effectively reduced to their intersection with the media box."
41376 cropBox = Util.intersect(cropBox, mediaBox);
41377 if (!cropBox) {
41378 return shadow(this, 'view', mediaBox);
41379 }
41380 return shadow(this, 'view', cropBox);
41381 },
41382
41383 get rotate() {
41384 var rotate = this.getInheritedPageProp('Rotate') || 0;
41385 // Normalize rotation so it's a multiple of 90 and between 0 and 270
41386 if (rotate % 90 !== 0) {
41387 rotate = 0;
41388 } else if (rotate >= 360) {
41389 rotate = rotate % 360;
41390 } else if (rotate < 0) {
41391 // The spec doesn't cover negatives, assume its counterclockwise
41392 // rotation. The following is the other implementation of modulo.
41393 rotate = ((rotate % 360) + 360) % 360;
41394 }
41395 return shadow(this, 'rotate', rotate);
41396 },
41397
41398 getContentStream: function Page_getContentStream() {
41399 var content = this.content;
41400 var stream;
41401 if (isArray(content)) {
41402 // fetching items
41403 var xref = this.xref;
41404 var i, n = content.length;
41405 var streams = [];
41406 for (i = 0; i < n; ++i) {
41407 streams.push(xref.fetchIfRef(content[i]));
41408 }
41409 stream = new StreamsSequenceStream(streams);
41410 } else if (isStream(content)) {
41411 stream = content;
41412 } else {
41413 // replacing non-existent page content with empty one
41414 stream = new NullStream();
41415 }
41416 return stream;
41417 },
41418
41419 loadResources: function Page_loadResources(keys) {
41420 if (!this.resourcesPromise) {
41421 // TODO: add async getInheritedPageProp and remove this.
41422 this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
41423 }
41424 return this.resourcesPromise.then(function resourceSuccess() {
41425 var objectLoader = new ObjectLoader(this.resources.map,
41426 keys,
41427 this.xref);
41428 return objectLoader.load();
41429 }.bind(this));
41430 },
41431
41432 getOperatorList: function Page_getOperatorList(handler, task, intent,
41433 renderInteractiveForms) {
41434 var self = this;
41435
41436 var pdfManager = this.pdfManager;
41437 var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
41438 []);
41439 var resourcesPromise = this.loadResources([
41440 'ExtGState',
41441 'ColorSpace',
41442 'Pattern',
41443 'Shading',
41444 'XObject',
41445 'Font'
41446 // ProcSet
41447 // Properties
41448 ]);
41449
41450 var partialEvaluator = new PartialEvaluator(pdfManager, this.xref,
41451 handler, this.pageIndex,
41452 this.uniquePrefix,
41453 this.idCounters,
41454 this.fontCache,
41455 this.evaluatorOptions);
41456
41457 var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
41458 var pageListPromise = dataPromises.then(function(data) {
41459 var contentStream = data[0];
41460 var opList = new OperatorList(intent, handler, self.pageIndex);
41461
41462 handler.send('StartRenderPage', {
41463 transparency: partialEvaluator.hasBlendModes(self.resources),
41464 pageIndex: self.pageIndex,
41465 intent: intent
41466 });
41467 return partialEvaluator.getOperatorList(contentStream, task,
41468 self.resources, opList).then(function () {
41469 return opList;
41470 });
41471 });
41472
41473 var annotationsPromise = pdfManager.ensure(this, 'annotations');
41474 return Promise.all([pageListPromise, annotationsPromise]).then(
41475 function(datas) {
41476 var pageOpList = datas[0];
41477 var annotations = datas[1];
41478
41479 if (annotations.length === 0) {
41480 pageOpList.flush(true);
41481 return pageOpList;
41482 }
41483
41484 var annotationsReadyPromise = Annotation.appendToOperatorList(
41485 annotations, pageOpList, partialEvaluator, task, intent,
41486 renderInteractiveForms);
41487 return annotationsReadyPromise.then(function () {
41488 pageOpList.flush(true);
41489 return pageOpList;
41490 });
41491 });
41492 },
41493
41494 extractTextContent: function Page_extractTextContent(task,
41495 normalizeWhitespace,
41496 combineTextItems) {
41497 var handler = {
41498 on: function nullHandlerOn() {},
41499 send: function nullHandlerSend() {}
41500 };
41501
41502 var self = this;
41503
41504 var pdfManager = this.pdfManager;
41505 var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
41506 []);
41507
41508 var resourcesPromise = this.loadResources([
41509 'ExtGState',
41510 'XObject',
41511 'Font'
41512 ]);
41513
41514 var dataPromises = Promise.all([contentStreamPromise,
41515 resourcesPromise]);
41516 return dataPromises.then(function(data) {
41517 var contentStream = data[0];
41518 var partialEvaluator = new PartialEvaluator(pdfManager, self.xref,
41519 handler, self.pageIndex,
41520 self.uniquePrefix,
41521 self.idCounters,
41522 self.fontCache,
41523 self.evaluatorOptions);
41524
41525 return partialEvaluator.getTextContent(contentStream,
41526 task,
41527 self.resources,
41528 /* stateManager = */ null,
41529 normalizeWhitespace,
41530 combineTextItems);
41531 });
41532 },
41533
41534 getAnnotationsData: function Page_getAnnotationsData(intent) {
41535 var annotations = this.annotations;
41536 var annotationsData = [];
41537 for (var i = 0, n = annotations.length; i < n; ++i) {
41538 if (intent) {
41539 if (!(intent === 'display' && annotations[i].viewable) &&
41540 !(intent === 'print' && annotations[i].printable)) {
41541 continue;
41542 }
41543 }
41544 annotationsData.push(annotations[i].data);
41545 }
41546 return annotationsData;
41547 },
41548
41549 get annotations() {
41550 var annotations = [];
41551 var annotationRefs = this.getInheritedPageProp('Annots') || [];
41552 var annotationFactory = new AnnotationFactory();
41553 for (var i = 0, n = annotationRefs.length; i < n; ++i) {
41554 var annotationRef = annotationRefs[i];
41555 var annotation = annotationFactory.create(this.xref, annotationRef,
41556 this.uniquePrefix,
41557 this.idCounters);
41558 if (annotation) {
41559 annotations.push(annotation);
41560 }
41561 }
41562 return shadow(this, 'annotations', annotations);
41563 }
41564 };
41565
41566 return Page;
41567})();
41568
41569/**
41570 * The `PDFDocument` holds all the data of the PDF file. Compared to the
41571 * `PDFDoc`, this one doesn't have any job management code.
41572 * Right now there exists one PDFDocument on the main thread + one object
41573 * for each worker. If there is no worker support enabled, there are two
41574 * `PDFDocument` objects on the main thread created.
41575 */
41576var PDFDocument = (function PDFDocumentClosure() {
41577 var FINGERPRINT_FIRST_BYTES = 1024;
41578 var EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' +
41579 '\x00\x00\x00\x00\x00\x00\x00\x00\x00';
41580
41581 function PDFDocument(pdfManager, arg, password) {
41582 if (isStream(arg)) {
41583 init.call(this, pdfManager, arg, password);
41584 } else if (isArrayBuffer(arg)) {
41585 init.call(this, pdfManager, new Stream(arg), password);
41586 } else {
41587 error('PDFDocument: Unknown argument type');
41588 }
41589 }
41590
41591 function init(pdfManager, stream, password) {
41592 assert(stream.length > 0, 'stream must have data');
41593 this.pdfManager = pdfManager;
41594 this.stream = stream;
41595 var xref = new XRef(this.stream, password, pdfManager);
41596 this.xref = xref;
41597 }
41598
41599 function find(stream, needle, limit, backwards) {
41600 var pos = stream.pos;
41601 var end = stream.end;
41602 var strBuf = [];
41603 if (pos + limit > end) {
41604 limit = end - pos;
41605 }
41606 for (var n = 0; n < limit; ++n) {
41607 strBuf.push(String.fromCharCode(stream.getByte()));
41608 }
41609 var str = strBuf.join('');
41610 stream.pos = pos;
41611 var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
41612 if (index === -1) {
41613 return false; /* not found */
41614 }
41615 stream.pos += index;
41616 return true; /* found */
41617 }
41618
41619 var DocumentInfoValidators = {
41620 get entries() {
41621 // Lazily build this since all the validation functions below are not
41622 // defined until after this file loads.
41623 return shadow(this, 'entries', {
41624 Title: isString,
41625 Author: isString,
41626 Subject: isString,
41627 Keywords: isString,
41628 Creator: isString,
41629 Producer: isString,
41630 CreationDate: isString,
41631 ModDate: isString,
41632 Trapped: isName
41633 });
41634 }
41635 };
41636
41637 PDFDocument.prototype = {
41638 parse: function PDFDocument_parse(recoveryMode) {
41639 this.setup(recoveryMode);
41640 var version = this.catalog.catDict.get('Version');
41641 if (isName(version)) {
41642 this.pdfFormatVersion = version.name;
41643 }
41644 try {
41645 // checking if AcroForm is present
41646 this.acroForm = this.catalog.catDict.get('AcroForm');
41647 if (this.acroForm) {
41648 this.xfa = this.acroForm.get('XFA');
41649 var fields = this.acroForm.get('Fields');
41650 if ((!fields || !isArray(fields) || fields.length === 0) &&
41651 !this.xfa) {
41652 // no fields and no XFA -- not a form (?)
41653 this.acroForm = null;
41654 }
41655 }
41656 } catch (ex) {
41657 info('Something wrong with AcroForm entry');
41658 this.acroForm = null;
41659 }
41660 },
41661
41662 get linearization() {
41663 var linearization = null;
41664 if (this.stream.length) {
41665 try {
41666 linearization = Linearization.create(this.stream);
41667 } catch (err) {
41668 if (err instanceof MissingDataException) {
41669 throw err;
41670 }
41671 info(err);
41672 }
41673 }
41674 // shadow the prototype getter with a data property
41675 return shadow(this, 'linearization', linearization);
41676 },
41677 get startXRef() {
41678 var stream = this.stream;
41679 var startXRef = 0;
41680 var linearization = this.linearization;
41681 if (linearization) {
41682 // Find end of first obj.
41683 stream.reset();
41684 if (find(stream, 'endobj', 1024)) {
41685 startXRef = stream.pos + 6;
41686 }
41687 } else {
41688 // Find startxref by jumping backward from the end of the file.
41689 var step = 1024;
41690 var found = false, pos = stream.end;
41691 while (!found && pos > 0) {
41692 pos -= step - 'startxref'.length;
41693 if (pos < 0) {
41694 pos = 0;
41695 }
41696 stream.pos = pos;
41697 found = find(stream, 'startxref', step, true);
41698 }
41699 if (found) {
41700 stream.skip(9);
41701 var ch;
41702 do {
41703 ch = stream.getByte();
41704 } while (isSpace(ch));
41705 var str = '';
41706 while (ch >= 0x20 && ch <= 0x39) { // < '9'
41707 str += String.fromCharCode(ch);
41708 ch = stream.getByte();
41709 }
41710 startXRef = parseInt(str, 10);
41711 if (isNaN(startXRef)) {
41712 startXRef = 0;
41713 }
41714 }
41715 }
41716 // shadow the prototype getter with a data property
41717 return shadow(this, 'startXRef', startXRef);
41718 },
41719 get mainXRefEntriesOffset() {
41720 var mainXRefEntriesOffset = 0;
41721 var linearization = this.linearization;
41722 if (linearization) {
41723 mainXRefEntriesOffset = linearization.mainXRefEntriesOffset;
41724 }
41725 // shadow the prototype getter with a data property
41726 return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset);
41727 },
41728 // Find the header, remove leading garbage and setup the stream
41729 // starting from the header.
41730 checkHeader: function PDFDocument_checkHeader() {
41731 var stream = this.stream;
41732 stream.reset();
41733 if (find(stream, '%PDF-', 1024)) {
41734 // Found the header, trim off any garbage before it.
41735 stream.moveStart();
41736 // Reading file format version
41737 var MAX_VERSION_LENGTH = 12;
41738 var version = '', ch;
41739 while ((ch = stream.getByte()) > 0x20) { // SPACE
41740 if (version.length >= MAX_VERSION_LENGTH) {
41741 break;
41742 }
41743 version += String.fromCharCode(ch);
41744 }
41745 if (!this.pdfFormatVersion) {
41746 // removing "%PDF-"-prefix
41747 this.pdfFormatVersion = version.substring(5);
41748 }
41749 return;
41750 }
41751 // May not be a PDF file, continue anyway.
41752 },
41753 parseStartXRef: function PDFDocument_parseStartXRef() {
41754 var startXRef = this.startXRef;
41755 this.xref.setStartXRef(startXRef);
41756 },
41757 setup: function PDFDocument_setup(recoveryMode) {
41758 this.xref.parse(recoveryMode);
41759 var self = this;
41760 var pageFactory = {
41761 createPage: function (pageIndex, dict, ref, fontCache) {
41762 return new Page(self.pdfManager, self.xref, pageIndex, dict, ref,
41763 fontCache);
41764 }
41765 };
41766 this.catalog = new Catalog(this.pdfManager, this.xref, pageFactory);
41767 },
41768 get numPages() {
41769 var linearization = this.linearization;
41770 var num = linearization ? linearization.numPages : this.catalog.numPages;
41771 // shadow the prototype getter
41772 return shadow(this, 'numPages', num);
41773 },
41774 get documentInfo() {
41775 var docInfo = {
41776 PDFFormatVersion: this.pdfFormatVersion,
41777 IsAcroFormPresent: !!this.acroForm,
41778 IsXFAPresent: !!this.xfa
41779 };
41780 var infoDict;
41781 try {
41782 infoDict = this.xref.trailer.get('Info');
41783 } catch (err) {
41784 info('The document information dictionary is invalid.');
41785 }
41786 if (infoDict) {
41787 var validEntries = DocumentInfoValidators.entries;
41788 // Only fill the document info with valid entries from the spec.
41789 for (var key in validEntries) {
41790 if (infoDict.has(key)) {
41791 var value = infoDict.get(key);
41792 // Make sure the value conforms to the spec.
41793 if (validEntries[key](value)) {
41794 docInfo[key] = (typeof value !== 'string' ?
41795 value : stringToPDFString(value));
41796 } else {
41797 info('Bad value in document info for "' + key + '"');
41798 }
41799 }
41800 }
41801 }
41802 return shadow(this, 'documentInfo', docInfo);
41803 },
41804 get fingerprint() {
41805 var xref = this.xref, hash, fileID = '';
41806 var idArray = xref.trailer.get('ID');
41807
41808 if (idArray && isArray(idArray) && idArray[0] && isString(idArray[0]) &&
41809 idArray[0] !== EMPTY_FINGERPRINT) {
41810 hash = stringToBytes(idArray[0]);
41811 } else {
41812 if (this.stream.ensureRange) {
41813 this.stream.ensureRange(0,
41814 Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end));
41815 }
41816 hash = calculateMD5(this.stream.bytes.subarray(0,
41817 FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);
41818 }
41819
41820 for (var i = 0, n = hash.length; i < n; i++) {
41821 var hex = hash[i].toString(16);
41822 fileID += hex.length === 1 ? '0' + hex : hex;
41823 }
41824
41825 return shadow(this, 'fingerprint', fileID);
41826 },
41827
41828 getPage: function PDFDocument_getPage(pageIndex) {
41829 return this.catalog.getPage(pageIndex);
41830 },
41831
41832 cleanup: function PDFDocument_cleanup() {
41833 return this.catalog.cleanup();
41834 }
41835 };
41836
41837 return PDFDocument;
41838})();
41839
41840exports.Page = Page;
41841exports.PDFDocument = PDFDocument;
41842}));
41843
41844
41845(function (root, factory) {
41846 {
41847 factory((root.pdfjsCorePdfManager = {}), root.pdfjsSharedUtil,
41848 root.pdfjsCoreStream, root.pdfjsCoreChunkedStream,
41849 root.pdfjsCoreDocument);
41850 }
41851}(this, function (exports, sharedUtil, coreStream, coreChunkedStream,
41852 coreDocument) {
41853
41854var NotImplementedException = sharedUtil.NotImplementedException;
41855var MissingDataException = sharedUtil.MissingDataException;
41856var createPromiseCapability = sharedUtil.createPromiseCapability;
41857var Util = sharedUtil.Util;
41858var Stream = coreStream.Stream;
41859var ChunkedStreamManager = coreChunkedStream.ChunkedStreamManager;
41860var PDFDocument = coreDocument.PDFDocument;
41861
41862var BasePdfManager = (function BasePdfManagerClosure() {
41863 function BasePdfManager() {
41864 throw new Error('Cannot initialize BaseManagerManager');
41865 }
41866
41867 BasePdfManager.prototype = {
41868 get docId() {
41869 return this._docId;
41870 },
41871
41872 onLoadedStream: function BasePdfManager_onLoadedStream() {
41873 throw new NotImplementedException();
41874 },
41875
41876 ensureDoc: function BasePdfManager_ensureDoc(prop, args) {
41877 return this.ensure(this.pdfDocument, prop, args);
41878 },
41879
41880 ensureXRef: function BasePdfManager_ensureXRef(prop, args) {
41881 return this.ensure(this.pdfDocument.xref, prop, args);
41882 },
41883
41884 ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) {
41885 return this.ensure(this.pdfDocument.catalog, prop, args);
41886 },
41887
41888 getPage: function BasePdfManager_getPage(pageIndex) {
41889 return this.pdfDocument.getPage(pageIndex);
41890 },
41891
41892 cleanup: function BasePdfManager_cleanup() {
41893 return this.pdfDocument.cleanup();
41894 },
41895
41896 ensure: function BasePdfManager_ensure(obj, prop, args) {
41897 return new NotImplementedException();
41898 },
41899
41900 requestRange: function BasePdfManager_requestRange(begin, end) {
41901 return new NotImplementedException();
41902 },
41903
41904 requestLoadedStream: function BasePdfManager_requestLoadedStream() {
41905 return new NotImplementedException();
41906 },
41907
41908 sendProgressiveData: function BasePdfManager_sendProgressiveData(chunk) {
41909 return new NotImplementedException();
41910 },
41911
41912 updatePassword: function BasePdfManager_updatePassword(password) {
41913 this.pdfDocument.xref.password = this.password = password;
41914 if (this._passwordChangedCapability) {
41915 this._passwordChangedCapability.resolve();
41916 }
41917 },
41918
41919 passwordChanged: function BasePdfManager_passwordChanged() {
41920 this._passwordChangedCapability = createPromiseCapability();
41921 return this._passwordChangedCapability.promise;
41922 },
41923
41924 terminate: function BasePdfManager_terminate() {
41925 return new NotImplementedException();
41926 }
41927 };
41928
41929 return BasePdfManager;
41930})();
41931
41932var LocalPdfManager = (function LocalPdfManagerClosure() {
41933 function LocalPdfManager(docId, data, password, evaluatorOptions) {
41934 this._docId = docId;
41935 this.evaluatorOptions = evaluatorOptions;
41936 var stream = new Stream(data);
41937 this.pdfDocument = new PDFDocument(this, stream, password);
41938 this._loadedStreamCapability = createPromiseCapability();
41939 this._loadedStreamCapability.resolve(stream);
41940 }
41941
41942 Util.inherit(LocalPdfManager, BasePdfManager, {
41943 ensure: function LocalPdfManager_ensure(obj, prop, args) {
41944 return new Promise(function (resolve, reject) {
41945 try {
41946 var value = obj[prop];
41947 var result;
41948 if (typeof value === 'function') {
41949 result = value.apply(obj, args);
41950 } else {
41951 result = value;
41952 }
41953 resolve(result);
41954 } catch (e) {
41955 reject(e);
41956 }
41957 });
41958 },
41959
41960 requestRange: function LocalPdfManager_requestRange(begin, end) {
41961 return Promise.resolve();
41962 },
41963
41964 requestLoadedStream: function LocalPdfManager_requestLoadedStream() {
41965 return;
41966 },
41967
41968 onLoadedStream: function LocalPdfManager_onLoadedStream() {
41969 return this._loadedStreamCapability.promise;
41970 },
41971
41972 terminate: function LocalPdfManager_terminate() {
41973 return;
41974 }
41975 });
41976
41977 return LocalPdfManager;
41978})();
41979
41980var NetworkPdfManager = (function NetworkPdfManagerClosure() {
41981 function NetworkPdfManager(docId, pdfNetworkStream, args, evaluatorOptions) {
41982 this._docId = docId;
41983 this.msgHandler = args.msgHandler;
41984 this.evaluatorOptions = evaluatorOptions;
41985
41986 var params = {
41987 msgHandler: args.msgHandler,
41988 url: args.url,
41989 length: args.length,
41990 disableAutoFetch: args.disableAutoFetch,
41991 rangeChunkSize: args.rangeChunkSize
41992 };
41993 this.streamManager = new ChunkedStreamManager(pdfNetworkStream, params);
41994 this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(),
41995 args.password);
41996 }
41997
41998 Util.inherit(NetworkPdfManager, BasePdfManager, {
41999 ensure: function NetworkPdfManager_ensure(obj, prop, args) {
42000 var pdfManager = this;
42001
42002 return new Promise(function (resolve, reject) {
42003 function ensureHelper() {
42004 try {
42005 var result;
42006 var value = obj[prop];
42007 if (typeof value === 'function') {
42008 result = value.apply(obj, args);
42009 } else {
42010 result = value;
42011 }
42012 resolve(result);
42013 } catch(e) {
42014 if (!(e instanceof MissingDataException)) {
42015 reject(e);
42016 return;
42017 }
42018 pdfManager.streamManager.requestRange(e.begin, e.end).
42019 then(ensureHelper, reject);
42020 }
42021 }
42022
42023 ensureHelper();
42024 });
42025 },
42026
42027 requestRange: function NetworkPdfManager_requestRange(begin, end) {
42028 return this.streamManager.requestRange(begin, end);
42029 },
42030
42031 requestLoadedStream: function NetworkPdfManager_requestLoadedStream() {
42032 this.streamManager.requestAllChunks();
42033 },
42034
42035 sendProgressiveData:
42036 function NetworkPdfManager_sendProgressiveData(chunk) {
42037 this.streamManager.onReceiveData({ chunk: chunk });
42038 },
42039
42040 onLoadedStream: function NetworkPdfManager_onLoadedStream() {
42041 return this.streamManager.onLoadedStream();
42042 },
42043
42044 terminate: function NetworkPdfManager_terminate() {
42045 this.streamManager.abort();
42046 }
42047 });
42048
42049 return NetworkPdfManager;
42050})();
42051
42052exports.LocalPdfManager = LocalPdfManager;
42053exports.NetworkPdfManager = NetworkPdfManager;
42054}));
42055
42056
42057(function (root, factory) {
42058 {
42059 factory((root.pdfjsCoreWorker = {}), root.pdfjsSharedUtil,
42060 root.pdfjsCorePrimitives, root.pdfjsCorePdfManager);
42061 }
42062}(this, function (exports, sharedUtil, corePrimitives, corePdfManager) {
42063
42064var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES;
42065var InvalidPDFException = sharedUtil.InvalidPDFException;
42066var MessageHandler = sharedUtil.MessageHandler;
42067var MissingPDFException = sharedUtil.MissingPDFException;
42068var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
42069var PasswordException = sharedUtil.PasswordException;
42070var PasswordResponses = sharedUtil.PasswordResponses;
42071var UnknownErrorException = sharedUtil.UnknownErrorException;
42072var XRefParseException = sharedUtil.XRefParseException;
42073var arrayByteLength = sharedUtil.arrayByteLength;
42074var arraysToBytes = sharedUtil.arraysToBytes;
42075var assert = sharedUtil.assert;
42076var createPromiseCapability = sharedUtil.createPromiseCapability;
42077var error = sharedUtil.error;
42078var info = sharedUtil.info;
42079var warn = sharedUtil.warn;
42080var setVerbosityLevel = sharedUtil.setVerbosityLevel;
42081var Ref = corePrimitives.Ref;
42082var LocalPdfManager = corePdfManager.LocalPdfManager;
42083var NetworkPdfManager = corePdfManager.NetworkPdfManager;
42084var globalScope = sharedUtil.globalScope;
42085
42086var WorkerTask = (function WorkerTaskClosure() {
42087 function WorkerTask(name) {
42088 this.name = name;
42089 this.terminated = false;
42090 this._capability = createPromiseCapability();
42091 }
42092
42093 WorkerTask.prototype = {
42094 get finished() {
42095 return this._capability.promise;
42096 },
42097
42098 finish: function () {
42099 this._capability.resolve();
42100 },
42101
42102 terminate: function () {
42103 this.terminated = true;
42104 },
42105
42106 ensureNotTerminated: function () {
42107 if (this.terminated) {
42108 throw new Error('Worker task was terminated');
42109 }
42110 }
42111 };
42112
42113 return WorkerTask;
42114})();
42115
42116
42117/** @implements {IPDFStream} */
42118var PDFWorkerStream = (function PDFWorkerStreamClosure() {
42119 function PDFWorkerStream(params, msgHandler) {
42120 this._queuedChunks = [];
42121 var initialData = params.initialData;
42122 if (initialData && initialData.length > 0) {
42123 this._queuedChunks.push(initialData);
42124 }
42125 this._msgHandler = msgHandler;
42126
42127 this._isRangeSupported = !(params.disableRange);
42128 this._isStreamingSupported = !(params.disableStream);
42129 this._contentLength = params.length;
42130
42131 this._fullRequestReader = null;
42132 this._rangeReaders = [];
42133
42134 msgHandler.on('OnDataRange', this._onReceiveData.bind(this));
42135 msgHandler.on('OnDataProgress', this._onProgress.bind(this));
42136 }
42137 PDFWorkerStream.prototype = {
42138 _onReceiveData: function PDFWorkerStream_onReceiveData(args) {
42139 if (args.begin === undefined) {
42140 if (this._fullRequestReader) {
42141 this._fullRequestReader._enqueue(args.chunk);
42142 } else {
42143 this._queuedChunks.push(args.chunk);
42144 }
42145 } else {
42146 var found = this._rangeReaders.some(function (rangeReader) {
42147 if (rangeReader._begin !== args.begin) {
42148 return false;
42149 }
42150 rangeReader._enqueue(args.chunk);
42151 return true;
42152 });
42153 assert(found);
42154 }
42155 },
42156
42157 _onProgress: function PDFWorkerStream_onProgress(evt) {
42158 if (this._rangeReaders.length > 0) {
42159 // Reporting to first range reader.
42160 var firstReader = this._rangeReaders[0];
42161 if (firstReader.onProgress) {
42162 firstReader.onProgress({loaded: evt.loaded});
42163 }
42164 }
42165 },
42166
42167 _removeRangeReader: function PDFWorkerStream_removeRangeReader(reader) {
42168 var i = this._rangeReaders.indexOf(reader);
42169 if (i >= 0) {
42170 this._rangeReaders.splice(i, 1);
42171 }
42172 },
42173
42174 getFullReader: function PDFWorkerStream_getFullReader() {
42175 assert(!this._fullRequestReader);
42176 var queuedChunks = this._queuedChunks;
42177 this._queuedChunks = null;
42178 return new PDFWorkerStreamReader(this, queuedChunks);
42179 },
42180
42181 getRangeReader: function PDFWorkerStream_getRangeReader(begin, end) {
42182 var reader = new PDFWorkerStreamRangeReader(this, begin, end);
42183 this._msgHandler.send('RequestDataRange', { begin: begin, end: end });
42184 this._rangeReaders.push(reader);
42185 return reader;
42186 },
42187
42188 cancelAllRequests: function PDFWorkerStream_cancelAllRequests(reason) {
42189 if (this._fullRequestReader) {
42190 this._fullRequestReader.cancel(reason);
42191 }
42192 var readers = this._rangeReaders.slice(0);
42193 readers.forEach(function (rangeReader) {
42194 rangeReader.cancel(reason);
42195 });
42196 }
42197 };
42198
42199 /** @implements {IPDFStreamReader} */
42200 function PDFWorkerStreamReader(stream, queuedChunks) {
42201 this._stream = stream;
42202 this._done = false;
42203 this._queuedChunks = queuedChunks || [];
42204 this._requests = [];
42205 this._headersReady = Promise.resolve();
42206 stream._fullRequestReader = this;
42207
42208 this.onProgress = null; // not used
42209 }
42210 PDFWorkerStreamReader.prototype = {
42211 _enqueue: function PDFWorkerStreamReader_enqueue(chunk) {
42212 if (this._done) {
42213 return; // ignore new data
42214 }
42215 if (this._requests.length > 0) {
42216 var requestCapability = this._requests.shift();
42217 requestCapability.resolve({value: chunk, done: false});
42218 return;
42219 }
42220 this._queuedChunks.push(chunk);
42221 },
42222
42223 get headersReady() {
42224 return this._headersReady;
42225 },
42226
42227 get isRangeSupported() {
42228 return this._stream._isRangeSupported;
42229 },
42230
42231 get isStreamingSupported() {
42232 return this._stream._isStreamingSupported;
42233 },
42234
42235 get contentLength() {
42236 return this._stream._contentLength;
42237 },
42238
42239 read: function PDFWorkerStreamReader_read() {
42240 if (this._queuedChunks.length > 0) {
42241 var chunk = this._queuedChunks.shift();
42242 return Promise.resolve({value: chunk, done: false});
42243 }
42244 if (this._done) {
42245 return Promise.resolve({value: undefined, done: true});
42246 }
42247 var requestCapability = createPromiseCapability();
42248 this._requests.push(requestCapability);
42249 return requestCapability.promise;
42250 },
42251
42252 cancel: function PDFWorkerStreamReader_cancel(reason) {
42253 this._done = true;
42254 this._requests.forEach(function (requestCapability) {
42255 requestCapability.resolve({value: undefined, done: true});
42256 });
42257 this._requests = [];
42258 }
42259 };
42260
42261 /** @implements {IPDFStreamRangeReader} */
42262 function PDFWorkerStreamRangeReader(stream, begin, end) {
42263 this._stream = stream;
42264 this._begin = begin;
42265 this._end = end;
42266 this._queuedChunk = null;
42267 this._requests = [];
42268 this._done = false;
42269
42270 this.onProgress = null;
42271 }
42272 PDFWorkerStreamRangeReader.prototype = {
42273 _enqueue: function PDFWorkerStreamRangeReader_enqueue(chunk) {
42274 if (this._done) {
42275 return; // ignore new data
42276 }
42277 if (this._requests.length === 0) {
42278 this._queuedChunk = chunk;
42279 } else {
42280 var requestsCapability = this._requests.shift();
42281 requestsCapability.resolve({value: chunk, done: false});
42282 this._requests.forEach(function (requestCapability) {
42283 requestCapability.resolve({value: undefined, done: true});
42284 });
42285 this._requests = [];
42286 }
42287 this._done = true;
42288 this._stream._removeRangeReader(this);
42289 },
42290
42291 get isStreamingSupported() {
42292 return false;
42293 },
42294
42295 read: function PDFWorkerStreamRangeReader_read() {
42296 if (this._queuedChunk) {
42297 return Promise.resolve({value: this._queuedChunk, done: false});
42298 }
42299 if (this._done) {
42300 return Promise.resolve({value: undefined, done: true});
42301 }
42302 var requestCapability = createPromiseCapability();
42303 this._requests.push(requestCapability);
42304 return requestCapability.promise;
42305 },
42306
42307 cancel: function PDFWorkerStreamRangeReader_cancel(reason) {
42308 this._done = true;
42309 this._requests.forEach(function (requestCapability) {
42310 requestCapability.resolve({value: undefined, done: true});
42311 });
42312 this._requests = [];
42313 this._stream._removeRangeReader(this);
42314 }
42315 };
42316
42317 return PDFWorkerStream;
42318})();
42319
42320/** @type IPDFStream */
42321var PDFNetworkStream;
42322
42323/**
42324 * Sets PDFNetworkStream class to be used as alternative PDF data transport.
42325 * @param {IPDFStream} cls - the PDF data transport.
42326 */
42327function setPDFNetworkStreamClass(cls) {
42328 PDFNetworkStream = cls;
42329}
42330
42331var WorkerMessageHandler = {
42332 setup: function wphSetup(handler, port) {
42333 var testMessageProcessed = false;
42334 handler.on('test', function wphSetupTest(data) {
42335 if (testMessageProcessed) {
42336 return; // we already processed 'test' message once
42337 }
42338 testMessageProcessed = true;
42339
42340 // check if Uint8Array can be sent to worker
42341 if (!(data instanceof Uint8Array)) {
42342 handler.send('test', 'main', false);
42343 return;
42344 }
42345 // making sure postMessage transfers are working
42346 var supportTransfers = data[0] === 255;
42347 handler.postMessageTransfers = supportTransfers;
42348 // check if the response property is supported by xhr
42349 var xhr = new XMLHttpRequest();
42350 var responseExists = 'response' in xhr;
42351 // check if the property is actually implemented
42352 try {
42353 var dummy = xhr.responseType;
42354 } catch (e) {
42355 responseExists = false;
42356 }
42357 if (!responseExists) {
42358 handler.send('test', false);
42359 return;
42360 }
42361 handler.send('test', {
42362 supportTypedArray: true,
42363 supportTransfers: supportTransfers
42364 });
42365 });
42366
42367 handler.on('configure', function wphConfigure(data) {
42368 setVerbosityLevel(data.verbosity);
42369 });
42370
42371 handler.on('GetDocRequest', function wphSetupDoc(data) {
42372 return WorkerMessageHandler.createDocumentHandler(data, port);
42373 });
42374 },
42375 createDocumentHandler: function wphCreateDocumentHandler(docParams, port) {
42376 // This context is actually holds references on pdfManager and handler,
42377 // until the latter is destroyed.
42378 var pdfManager;
42379 var terminated = false;
42380 var cancelXHRs = null;
42381 var WorkerTasks = [];
42382
42383 var docId = docParams.docId;
42384 var workerHandlerName = docParams.docId + '_worker';
42385 var handler = new MessageHandler(workerHandlerName, docId, port);
42386
42387 // Ensure that postMessage transfers are correctly enabled/disabled,
42388 // to prevent "DataCloneError" in older versions of IE (see issue 6957).
42389 handler.postMessageTransfers = docParams.postMessageTransfers;
42390
42391 function ensureNotTerminated() {
42392 if (terminated) {
42393 throw new Error('Worker was terminated');
42394 }
42395 }
42396
42397 function startWorkerTask(task) {
42398 WorkerTasks.push(task);
42399 }
42400
42401 function finishWorkerTask(task) {
42402 task.finish();
42403 var i = WorkerTasks.indexOf(task);
42404 WorkerTasks.splice(i, 1);
42405 }
42406
42407 function loadDocument(recoveryMode) {
42408 var loadDocumentCapability = createPromiseCapability();
42409
42410 var parseSuccess = function parseSuccess() {
42411 var numPagesPromise = pdfManager.ensureDoc('numPages');
42412 var fingerprintPromise = pdfManager.ensureDoc('fingerprint');
42413 var encryptedPromise = pdfManager.ensureXRef('encrypt');
42414 Promise.all([numPagesPromise, fingerprintPromise,
42415 encryptedPromise]).then(function onDocReady(results) {
42416 var doc = {
42417 numPages: results[0],
42418 fingerprint: results[1],
42419 encrypted: !!results[2],
42420 };
42421 loadDocumentCapability.resolve(doc);
42422 },
42423 parseFailure);
42424 };
42425
42426 var parseFailure = function parseFailure(e) {
42427 loadDocumentCapability.reject(e);
42428 };
42429
42430 pdfManager.ensureDoc('checkHeader', []).then(function() {
42431 pdfManager.ensureDoc('parseStartXRef', []).then(function() {
42432 pdfManager.ensureDoc('parse', [recoveryMode]).then(
42433 parseSuccess, parseFailure);
42434 }, parseFailure);
42435 }, parseFailure);
42436
42437 return loadDocumentCapability.promise;
42438 }
42439
42440 function getPdfManager(data, evaluatorOptions) {
42441 var pdfManagerCapability = createPromiseCapability();
42442 var pdfManager;
42443
42444 var source = data.source;
42445 if (source.data) {
42446 try {
42447 pdfManager = new LocalPdfManager(docId, source.data, source.password,
42448 evaluatorOptions);
42449 pdfManagerCapability.resolve(pdfManager);
42450 } catch (ex) {
42451 pdfManagerCapability.reject(ex);
42452 }
42453 return pdfManagerCapability.promise;
42454 }
42455
42456 var pdfStream;
42457 try {
42458 if (source.chunkedViewerLoading) {
42459 pdfStream = new PDFWorkerStream(source, handler);
42460 } else {
42461 assert(PDFNetworkStream, 'pdfjs/core/network module is not loaded');
42462 pdfStream = new PDFNetworkStream(data);
42463 }
42464 } catch (ex) {
42465 pdfManagerCapability.reject(ex);
42466 return pdfManagerCapability.promise;
42467 }
42468
42469 var fullRequest = pdfStream.getFullReader();
42470 fullRequest.headersReady.then(function () {
42471 if (!fullRequest.isStreamingSupported ||
42472 !fullRequest.isRangeSupported) {
42473 // If stream or range are disabled, it's our only way to report
42474 // loading progress.
42475 fullRequest.onProgress = function (evt) {
42476 handler.send('DocProgress', {
42477 loaded: evt.loaded,
42478 total: evt.total
42479 });
42480 };
42481 }
42482
42483 if (!fullRequest.isRangeSupported) {
42484 return;
42485 }
42486
42487 // We don't need auto-fetch when streaming is enabled.
42488 var disableAutoFetch = source.disableAutoFetch ||
42489 fullRequest.isStreamingSupported;
42490 pdfManager = new NetworkPdfManager(docId, pdfStream, {
42491 msgHandler: handler,
42492 url: source.url,
42493 password: source.password,
42494 length: fullRequest.contentLength,
42495 disableAutoFetch: disableAutoFetch,
42496 rangeChunkSize: source.rangeChunkSize
42497 }, evaluatorOptions);
42498 pdfManagerCapability.resolve(pdfManager);
42499 cancelXHRs = null;
42500 }).catch(function (reason) {
42501 pdfManagerCapability.reject(reason);
42502 cancelXHRs = null;
42503 });
42504
42505 var cachedChunks = [], loaded = 0;
42506 var flushChunks = function () {
42507 var pdfFile = arraysToBytes(cachedChunks);
42508 if (source.length && pdfFile.length !== source.length) {
42509 warn('reported HTTP length is different from actual');
42510 }
42511 // the data is array, instantiating directly from it
42512 try {
42513 pdfManager = new LocalPdfManager(docId, pdfFile, source.password,
42514 evaluatorOptions);
42515 pdfManagerCapability.resolve(pdfManager);
42516 } catch (ex) {
42517 pdfManagerCapability.reject(ex);
42518 }
42519 cachedChunks = [];
42520 };
42521 var readPromise = new Promise(function (resolve, reject) {
42522 var readChunk = function (chunk) {
42523 try {
42524 ensureNotTerminated();
42525 if (chunk.done) {
42526 if (!pdfManager) {
42527 flushChunks();
42528 }
42529 cancelXHRs = null;
42530 return;
42531 }
42532
42533 var data = chunk.value;
42534 loaded += arrayByteLength(data);
42535 if (!fullRequest.isStreamingSupported) {
42536 handler.send('DocProgress', {
42537 loaded: loaded,
42538 total: Math.max(loaded, fullRequest.contentLength || 0)
42539 });
42540 }
42541
42542 if (pdfManager) {
42543 pdfManager.sendProgressiveData(data);
42544 } else {
42545 cachedChunks.push(data);
42546 }
42547
42548 fullRequest.read().then(readChunk, reject);
42549 } catch (e) {
42550 reject(e);
42551 }
42552 };
42553 fullRequest.read().then(readChunk, reject);
42554 });
42555 readPromise.catch(function (e) {
42556 pdfManagerCapability.reject(e);
42557 cancelXHRs = null;
42558 });
42559
42560 cancelXHRs = function () {
42561 pdfStream.cancelAllRequests('abort');
42562 };
42563
42564 return pdfManagerCapability.promise;
42565 }
42566
42567 var setupDoc = function(data) {
42568 var onSuccess = function(doc) {
42569 ensureNotTerminated();
42570 handler.send('GetDoc', { pdfInfo: doc });
42571 };
42572
42573 var onFailure = function(e) {
42574 if (e instanceof PasswordException) {
42575 if (e.code === PasswordResponses.NEED_PASSWORD) {
42576 handler.send('NeedPassword', e);
42577 } else if (e.code === PasswordResponses.INCORRECT_PASSWORD) {
42578 handler.send('IncorrectPassword', e);
42579 }
42580 } else if (e instanceof InvalidPDFException) {
42581 handler.send('InvalidPDF', e);
42582 } else if (e instanceof MissingPDFException) {
42583 handler.send('MissingPDF', e);
42584 } else if (e instanceof UnexpectedResponseException) {
42585 handler.send('UnexpectedResponse', e);
42586 } else {
42587 handler.send('UnknownError',
42588 new UnknownErrorException(e.message, e.toString()));
42589 }
42590 };
42591
42592 ensureNotTerminated();
42593
42594 var cMapOptions = {
42595 url: data.cMapUrl === undefined ? null : data.cMapUrl,
42596 packed: data.cMapPacked === true
42597 };
42598 var evaluatorOptions = {
42599 forceDataSchema: data.disableCreateObjectURL,
42600 maxImageSize: data.maxImageSize === undefined ? -1 : data.maxImageSize,
42601 disableFontFace: data.disableFontFace,
42602 cMapOptions: cMapOptions
42603 };
42604
42605 getPdfManager(data, evaluatorOptions).then(function (newPdfManager) {
42606 if (terminated) {
42607 // We were in a process of setting up the manager, but it got
42608 // terminated in the middle.
42609 newPdfManager.terminate();
42610 throw new Error('Worker was terminated');
42611 }
42612
42613 pdfManager = newPdfManager;
42614 handler.send('PDFManagerReady', null);
42615 pdfManager.onLoadedStream().then(function(stream) {
42616 handler.send('DataLoaded', { length: stream.bytes.byteLength });
42617 });
42618 }).then(function pdfManagerReady() {
42619 ensureNotTerminated();
42620
42621 loadDocument(false).then(onSuccess, function loadFailure(ex) {
42622 ensureNotTerminated();
42623
42624 // Try again with recoveryMode == true
42625 if (!(ex instanceof XRefParseException)) {
42626 if (ex instanceof PasswordException) {
42627 // after password exception prepare to receive a new password
42628 // to repeat loading
42629 pdfManager.passwordChanged().then(pdfManagerReady);
42630 }
42631
42632 onFailure(ex);
42633 return;
42634 }
42635
42636 pdfManager.requestLoadedStream();
42637 pdfManager.onLoadedStream().then(function() {
42638 ensureNotTerminated();
42639
42640 loadDocument(true).then(onSuccess, onFailure);
42641 });
42642 }, onFailure);
42643 }, onFailure);
42644 };
42645
42646 handler.on('GetPage', function wphSetupGetPage(data) {
42647 return pdfManager.getPage(data.pageIndex).then(function(page) {
42648 var rotatePromise = pdfManager.ensure(page, 'rotate');
42649 var refPromise = pdfManager.ensure(page, 'ref');
42650 var viewPromise = pdfManager.ensure(page, 'view');
42651
42652 return Promise.all([rotatePromise, refPromise, viewPromise]).then(
42653 function(results) {
42654 return {
42655 rotate: results[0],
42656 ref: results[1],
42657 view: results[2]
42658 };
42659 });
42660 });
42661 });
42662
42663 handler.on('GetPageIndex', function wphSetupGetPageIndex(data) {
42664 var ref = new Ref(data.ref.num, data.ref.gen);
42665 var catalog = pdfManager.pdfDocument.catalog;
42666 return catalog.getPageIndex(ref);
42667 });
42668
42669 handler.on('GetDestinations',
42670 function wphSetupGetDestinations(data) {
42671 return pdfManager.ensureCatalog('destinations');
42672 }
42673 );
42674
42675 handler.on('GetDestination',
42676 function wphSetupGetDestination(data) {
42677 return pdfManager.ensureCatalog('getDestination', [data.id]);
42678 }
42679 );
42680
42681 handler.on('GetPageLabels',
42682 function wphSetupGetPageLabels(data) {
42683 return pdfManager.ensureCatalog('pageLabels');
42684 }
42685 );
42686
42687 handler.on('GetAttachments',
42688 function wphSetupGetAttachments(data) {
42689 return pdfManager.ensureCatalog('attachments');
42690 }
42691 );
42692
42693 handler.on('GetJavaScript',
42694 function wphSetupGetJavaScript(data) {
42695 return pdfManager.ensureCatalog('javaScript');
42696 }
42697 );
42698
42699 handler.on('GetOutline',
42700 function wphSetupGetOutline(data) {
42701 return pdfManager.ensureCatalog('documentOutline');
42702 }
42703 );
42704
42705 handler.on('GetMetadata',
42706 function wphSetupGetMetadata(data) {
42707 return Promise.all([pdfManager.ensureDoc('documentInfo'),
42708 pdfManager.ensureCatalog('metadata')]);
42709 }
42710 );
42711
42712 handler.on('GetData', function wphSetupGetData(data) {
42713 pdfManager.requestLoadedStream();
42714 return pdfManager.onLoadedStream().then(function(stream) {
42715 return stream.bytes;
42716 });
42717 });
42718
42719 handler.on('GetStats',
42720 function wphSetupGetStats(data) {
42721 return pdfManager.pdfDocument.xref.stats;
42722 }
42723 );
42724
42725 handler.on('UpdatePassword', function wphSetupUpdatePassword(data) {
42726 pdfManager.updatePassword(data);
42727 });
42728
42729 handler.on('GetAnnotations', function wphSetupGetAnnotations(data) {
42730 return pdfManager.getPage(data.pageIndex).then(function(page) {
42731 return pdfManager.ensure(page, 'getAnnotationsData', [data.intent]);
42732 });
42733 });
42734
42735 handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
42736 var pageIndex = data.pageIndex;
42737 pdfManager.getPage(pageIndex).then(function(page) {
42738 var task = new WorkerTask('RenderPageRequest: page ' + pageIndex);
42739 startWorkerTask(task);
42740
42741 var pageNum = pageIndex + 1;
42742 var start = Date.now();
42743 // Pre compile the pdf page and fetch the fonts/images.
42744 page.getOperatorList(handler, task, data.intent,
42745 data.renderInteractiveForms).then(
42746 function(operatorList) {
42747 finishWorkerTask(task);
42748
42749 info('page=' + pageNum + ' - getOperatorList: time=' +
42750 (Date.now() - start) + 'ms, len=' + operatorList.totalLength);
42751 }, function(e) {
42752 finishWorkerTask(task);
42753 if (task.terminated) {
42754 return; // ignoring errors from the terminated thread
42755 }
42756
42757 // For compatibility with older behavior, generating unknown
42758 // unsupported feature notification on errors.
42759 handler.send('UnsupportedFeature',
42760 {featureId: UNSUPPORTED_FEATURES.unknown});
42761
42762 var minimumStackMessage =
42763 'worker.js: while trying to getPage() and getOperatorList()';
42764
42765 var wrappedException;
42766
42767 // Turn the error into an obj that can be serialized
42768 if (typeof e === 'string') {
42769 wrappedException = {
42770 message: e,
42771 stack: minimumStackMessage
42772 };
42773 } else if (typeof e === 'object') {
42774 wrappedException = {
42775 message: e.message || e.toString(),
42776 stack: e.stack || minimumStackMessage
42777 };
42778 } else {
42779 wrappedException = {
42780 message: 'Unknown exception type: ' + (typeof e),
42781 stack: minimumStackMessage
42782 };
42783 }
42784
42785 handler.send('PageError', {
42786 pageNum: pageNum,
42787 error: wrappedException,
42788 intent: data.intent
42789 });
42790 });
42791 });
42792 }, this);
42793
42794 handler.on('GetTextContent', function wphExtractText(data) {
42795 var pageIndex = data.pageIndex;
42796 var normalizeWhitespace = data.normalizeWhitespace;
42797 var combineTextItems = data.combineTextItems;
42798 return pdfManager.getPage(pageIndex).then(function(page) {
42799 var task = new WorkerTask('GetTextContent: page ' + pageIndex);
42800 startWorkerTask(task);
42801 var pageNum = pageIndex + 1;
42802 var start = Date.now();
42803 return page.extractTextContent(task, normalizeWhitespace,
42804 combineTextItems).then(
42805 function(textContent) {
42806 finishWorkerTask(task);
42807 info('text indexing: page=' + pageNum + ' - time=' +
42808 (Date.now() - start) + 'ms');
42809 return textContent;
42810 }, function (reason) {
42811 finishWorkerTask(task);
42812 if (task.terminated) {
42813 return; // ignoring errors from the terminated thread
42814 }
42815 throw reason;
42816 });
42817 });
42818 });
42819
42820 handler.on('Cleanup', function wphCleanup(data) {
42821 return pdfManager.cleanup();
42822 });
42823
42824 handler.on('Terminate', function wphTerminate(data) {
42825 terminated = true;
42826 if (pdfManager) {
42827 pdfManager.terminate();
42828 pdfManager = null;
42829 }
42830 if (cancelXHRs) {
42831 cancelXHRs();
42832 }
42833
42834 var waitOn = [];
42835 WorkerTasks.forEach(function (task) {
42836 waitOn.push(task.finished);
42837 task.terminate();
42838 });
42839
42840 return Promise.all(waitOn).then(function () {
42841 // Notice that even if we destroying handler, resolved response promise
42842 // must be sent back.
42843 handler.destroy();
42844 handler = null;
42845 });
42846 });
42847
42848 handler.on('Ready', function wphReady(data) {
42849 setupDoc(docParams);
42850 docParams = null; // we don't need docParams anymore -- saving memory.
42851 });
42852 return workerHandlerName;
42853 }
42854};
42855
42856function initializeWorker() {
42857 if (!('console' in globalScope)) {
42858 var consoleTimer = {};
42859
42860 var workerConsole = {
42861 log: function log() {
42862 var args = Array.prototype.slice.call(arguments);
42863 globalScope.postMessage({
42864 targetName: 'main',
42865 action: 'console_log',
42866 data: args
42867 });
42868 },
42869
42870 error: function error() {
42871 var args = Array.prototype.slice.call(arguments);
42872 globalScope.postMessage({
42873 targetName: 'main',
42874 action: 'console_error',
42875 data: args
42876 });
42877 throw 'pdf.js execution error';
42878 },
42879
42880 time: function time(name) {
42881 consoleTimer[name] = Date.now();
42882 },
42883
42884 timeEnd: function timeEnd(name) {
42885 var time = consoleTimer[name];
42886 if (!time) {
42887 error('Unknown timer name ' + name);
42888 }
42889 this.log('Timer:', name, Date.now() - time);
42890 }
42891 };
42892
42893 globalScope.console = workerConsole;
42894 }
42895
42896 var handler = new MessageHandler('worker', 'main', self);
42897 WorkerMessageHandler.setup(handler, self);
42898 handler.send('ready', null);
42899}
42900
42901// Worker thread (and not node.js)?
42902if (typeof window === 'undefined' &&
42903 !(typeof module !== 'undefined' && module.require)) {
42904 initializeWorker();
42905}
42906
42907exports.setPDFNetworkStreamClass = setPDFNetworkStreamClass;
42908exports.WorkerTask = WorkerTask;
42909exports.WorkerMessageHandler = WorkerMessageHandler;
42910}));
42911
42912
42913
42914
42915var NetworkManager = (function NetworkManagerClosure() {
42916
42917 var OK_RESPONSE = 200;
42918 var PARTIAL_CONTENT_RESPONSE = 206;
42919
42920 function NetworkManager(url, args) {
42921 this.url = url;
42922 args = args || {};
42923 this.isHttp = /^https?:/i.test(url);
42924 this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
42925 this.withCredentials = args.withCredentials || false;
42926 this.getXhr = args.getXhr ||
42927 function NetworkManager_getXhr() {
42928 return new XMLHttpRequest();
42929 };
42930
42931 this.currXhrId = 0;
42932 this.pendingRequests = Object.create(null);
42933 this.loadedRequests = Object.create(null);
42934 }
42935
42936 function getArrayBuffer(xhr) {
42937 var data = xhr.response;
42938 if (typeof data !== 'string') {
42939 return data;
42940 }
42941 var length = data.length;
42942 var array = new Uint8Array(length);
42943 for (var i = 0; i < length; i++) {
42944 array[i] = data.charCodeAt(i) & 0xFF;
42945 }
42946 return array.buffer;
42947 }
42948
42949 var supportsMozChunked = (function supportsMozChunkedClosure() {
42950 try {
42951 var x = new XMLHttpRequest();
42952 // Firefox 37- required .open() to be called before setting responseType.
42953 // https://bugzilla.mozilla.org/show_bug.cgi?id=707484
42954 // Even though the URL is not visited, .open() could fail if the URL is
42955 // blocked, e.g. via the connect-src CSP directive or the NoScript addon.
42956 // When this error occurs, this feature detection method will mistakenly
42957 // report that moz-chunked-arraybuffer is not supported in Firefox 37-.
42958 x.open('GET', 'https://example.com');
42959 x.responseType = 'moz-chunked-arraybuffer';
42960 return x.responseType === 'moz-chunked-arraybuffer';
42961 } catch (e) {
42962 return false;
42963 }
42964 })();
42965
42966 NetworkManager.prototype = {
42967 requestRange: function NetworkManager_requestRange(begin, end, listeners) {
42968 var args = {
42969 begin: begin,
42970 end: end
42971 };
42972 for (var prop in listeners) {
42973 args[prop] = listeners[prop];
42974 }
42975 return this.request(args);
42976 },
42977
42978 requestFull: function NetworkManager_requestFull(listeners) {
42979 return this.request(listeners);
42980 },
42981
42982 request: function NetworkManager_request(args) {
42983 var xhr = this.getXhr();
42984 var xhrId = this.currXhrId++;
42985 var pendingRequest = this.pendingRequests[xhrId] = {
42986 xhr: xhr
42987 };
42988
42989 xhr.open('GET', this.url);
42990 xhr.withCredentials = this.withCredentials;
42991 for (var property in this.httpHeaders) {
42992 var value = this.httpHeaders[property];
42993 if (typeof value === 'undefined') {
42994 continue;
42995 }
42996 xhr.setRequestHeader(property, value);
42997 }
42998 if (this.isHttp && 'begin' in args && 'end' in args) {
42999 var rangeStr = args.begin + '-' + (args.end - 1);
43000 xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
43001 pendingRequest.expectedStatus = 206;
43002 } else {
43003 pendingRequest.expectedStatus = 200;
43004 }
43005
43006 var useMozChunkedLoading = supportsMozChunked && !!args.onProgressiveData;
43007 if (useMozChunkedLoading) {
43008 xhr.responseType = 'moz-chunked-arraybuffer';
43009 pendingRequest.onProgressiveData = args.onProgressiveData;
43010 pendingRequest.mozChunked = true;
43011 } else {
43012 xhr.responseType = 'arraybuffer';
43013 }
43014
43015 if (args.onError) {
43016 xhr.onerror = function(evt) {
43017 args.onError(xhr.status);
43018 };
43019 }
43020 xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
43021 xhr.onprogress = this.onProgress.bind(this, xhrId);
43022
43023 pendingRequest.onHeadersReceived = args.onHeadersReceived;
43024 pendingRequest.onDone = args.onDone;
43025 pendingRequest.onError = args.onError;
43026 pendingRequest.onProgress = args.onProgress;
43027
43028 xhr.send(null);
43029
43030 return xhrId;
43031 },
43032
43033 onProgress: function NetworkManager_onProgress(xhrId, evt) {
43034 var pendingRequest = this.pendingRequests[xhrId];
43035 if (!pendingRequest) {
43036 // Maybe abortRequest was called...
43037 return;
43038 }
43039
43040 if (pendingRequest.mozChunked) {
43041 var chunk = getArrayBuffer(pendingRequest.xhr);
43042 pendingRequest.onProgressiveData(chunk);
43043 }
43044
43045 var onProgress = pendingRequest.onProgress;
43046 if (onProgress) {
43047 onProgress(evt);
43048 }
43049 },
43050
43051 onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
43052 var pendingRequest = this.pendingRequests[xhrId];
43053 if (!pendingRequest) {
43054 // Maybe abortRequest was called...
43055 return;
43056 }
43057
43058 var xhr = pendingRequest.xhr;
43059 if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
43060 pendingRequest.onHeadersReceived();
43061 delete pendingRequest.onHeadersReceived;
43062 }
43063
43064 if (xhr.readyState !== 4) {
43065 return;
43066 }
43067
43068 if (!(xhrId in this.pendingRequests)) {
43069 // The XHR request might have been aborted in onHeadersReceived()
43070 // callback, in which case we should abort request
43071 return;
43072 }
43073
43074 delete this.pendingRequests[xhrId];
43075
43076 // success status == 0 can be on ftp, file and other protocols
43077 if (xhr.status === 0 && this.isHttp) {
43078 if (pendingRequest.onError) {
43079 pendingRequest.onError(xhr.status);
43080 }
43081 return;
43082 }
43083 var xhrStatus = xhr.status || OK_RESPONSE;
43084
43085 // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
43086 // "A server MAY ignore the Range header". This means it's possible to
43087 // get a 200 rather than a 206 response from a range request.
43088 var ok_response_on_range_request =
43089 xhrStatus === OK_RESPONSE &&
43090 pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
43091
43092 if (!ok_response_on_range_request &&
43093 xhrStatus !== pendingRequest.expectedStatus) {
43094 if (pendingRequest.onError) {
43095 pendingRequest.onError(xhr.status);
43096 }
43097 return;
43098 }
43099
43100 this.loadedRequests[xhrId] = true;
43101
43102 var chunk = getArrayBuffer(xhr);
43103 if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
43104 var rangeHeader = xhr.getResponseHeader('Content-Range');
43105 var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
43106 var begin = parseInt(matches[1], 10);
43107 pendingRequest.onDone({
43108 begin: begin,
43109 chunk: chunk
43110 });
43111 } else if (pendingRequest.onProgressiveData) {
43112 pendingRequest.onDone(null);
43113 } else if (chunk) {
43114 pendingRequest.onDone({
43115 begin: 0,
43116 chunk: chunk
43117 });
43118 } else if (pendingRequest.onError) {
43119 pendingRequest.onError(xhr.status);
43120 }
43121 },
43122
43123 hasPendingRequests: function NetworkManager_hasPendingRequests() {
43124 for (var xhrId in this.pendingRequests) {
43125 return true;
43126 }
43127 return false;
43128 },
43129
43130 getRequestXhr: function NetworkManager_getXhr(xhrId) {
43131 return this.pendingRequests[xhrId].xhr;
43132 },
43133
43134 isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
43135 return !!(this.pendingRequests[xhrId].onProgressiveData);
43136 },
43137
43138 isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
43139 return xhrId in this.pendingRequests;
43140 },
43141
43142 isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
43143 return xhrId in this.loadedRequests;
43144 },
43145
43146 abortAllRequests: function NetworkManager_abortAllRequests() {
43147 for (var xhrId in this.pendingRequests) {
43148 this.abortRequest(xhrId | 0);
43149 }
43150 },
43151
43152 abortRequest: function NetworkManager_abortRequest(xhrId) {
43153 var xhr = this.pendingRequests[xhrId].xhr;
43154 delete this.pendingRequests[xhrId];
43155 xhr.abort();
43156 }
43157 };
43158
43159 return NetworkManager;
43160})();
43161
43162(function (root, factory) {
43163 {
43164 factory((root.pdfjsCoreNetwork = {}), root.pdfjsSharedUtil,
43165 root.pdfjsCoreWorker);
43166 }
43167}(this, function (exports, sharedUtil, coreWorker) {
43168
43169 var assert = sharedUtil.assert;
43170 var createPromiseCapability = sharedUtil.createPromiseCapability;
43171 var isInt = sharedUtil.isInt;
43172 var MissingPDFException = sharedUtil.MissingPDFException;
43173 var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
43174
43175 /** @implements {IPDFStream} */
43176 function PDFNetworkStream(options) {
43177 this._options = options;
43178 var source = options.source;
43179 this._manager = new NetworkManager(source.url, {
43180 httpHeaders: source.httpHeaders,
43181 withCredentials: source.withCredentials
43182 });
43183 this._rangeChunkSize = source.rangeChunkSize;
43184 this._fullRequestReader = null;
43185 this._rangeRequestReaders = [];
43186 }
43187
43188 PDFNetworkStream.prototype = {
43189 _onRangeRequestReaderClosed:
43190 function PDFNetworkStream_onRangeRequestReaderClosed(reader) {
43191 var i = this._rangeRequestReaders.indexOf(reader);
43192 if (i >= 0) {
43193 this._rangeRequestReaders.splice(i, 1);
43194 }
43195 },
43196
43197 getFullReader: function PDFNetworkStream_getFullReader() {
43198 assert(!this._fullRequestReader);
43199 this._fullRequestReader =
43200 new PDFNetworkStreamFullRequestReader(this._manager, this._options);
43201 return this._fullRequestReader;
43202 },
43203
43204 getRangeReader: function PDFNetworkStream_getRangeReader(begin, end) {
43205 var reader = new PDFNetworkStreamRangeRequestReader(this._manager,
43206 begin, end);
43207 reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
43208 this._rangeRequestReaders.push(reader);
43209 return reader;
43210 },
43211
43212 cancelAllRequests: function PDFNetworkStream_cancelAllRequests(reason) {
43213 if (this._fullRequestReader) {
43214 this._fullRequestReader.cancel(reason);
43215 }
43216 var readers = this._rangeRequestReaders.slice(0);
43217 readers.forEach(function (reader) {
43218 reader.cancel(reason);
43219 });
43220 }
43221 };
43222
43223 /** @implements {IPDFStreamReader} */
43224 function PDFNetworkStreamFullRequestReader(manager, options) {
43225 this._manager = manager;
43226
43227 var source = options.source;
43228 var args = {
43229 onHeadersReceived: this._onHeadersReceived.bind(this),
43230 onProgressiveData: source.disableStream ? null :
43231 this._onProgressiveData.bind(this),
43232 onDone: this._onDone.bind(this),
43233 onError: this._onError.bind(this),
43234 onProgress: this._onProgress.bind(this)
43235 };
43236 this._url = source.url;
43237 this._fullRequestId = manager.requestFull(args);
43238 this._headersReceivedCapability = createPromiseCapability();
43239 this._disableRange = options.disableRange || false;
43240 this._contentLength = source.length; // optional
43241 this._rangeChunkSize = source.rangeChunkSize;
43242 if (!this._rangeChunkSize && !this._disableRange) {
43243 this._disableRange = true;
43244 }
43245
43246 this._isStreamingSupported = false;
43247 this._isRangeSupported = false;
43248
43249 this._cachedChunks = [];
43250 this._requests = [];
43251 this._done = false;
43252 this._storedError = undefined;
43253
43254 this.onProgress = null;
43255 }
43256
43257 PDFNetworkStreamFullRequestReader.prototype = {
43258 _validateRangeRequestCapabilities: function
43259 PDFNetworkStreamFullRequestReader_validateRangeRequestCapabilities() {
43260
43261 if (this._disableRange) {
43262 return false;
43263 }
43264
43265 var networkManager = this._manager;
43266 var fullRequestXhrId = this._fullRequestId;
43267 var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId);
43268 if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') {
43269 return false;
43270 }
43271
43272 var contentEncoding =
43273 fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity';
43274 if (contentEncoding !== 'identity') {
43275 return false;
43276 }
43277
43278 var length = fullRequestXhr.getResponseHeader('Content-Length');
43279 length = parseInt(length, 10);
43280 if (!isInt(length)) {
43281 return false;
43282 }
43283
43284 this._contentLength = length; // setting right content length
43285
43286 if (length <= 2 * this._rangeChunkSize) {
43287 // The file size is smaller than the size of two chunks, so it does
43288 // not make any sense to abort the request and retry with a range
43289 // request.
43290 return false;
43291 }
43292
43293 return true;
43294 },
43295
43296 _onHeadersReceived:
43297 function PDFNetworkStreamFullRequestReader_onHeadersReceived() {
43298
43299 if (this._validateRangeRequestCapabilities()) {
43300 this._isRangeSupported = true;
43301 }
43302
43303 var networkManager = this._manager;
43304 var fullRequestXhrId = this._fullRequestId;
43305 if (networkManager.isStreamingRequest(fullRequestXhrId)) {
43306 // We can continue fetching when progressive loading is enabled,
43307 // and we don't need the autoFetch feature.
43308 this._isStreamingSupported = true;
43309 } else if (this._isRangeSupported) {
43310 // NOTE: by cancelling the full request, and then issuing range
43311 // requests, there will be an issue for sites where you can only
43312 // request the pdf once. However, if this is the case, then the
43313 // server should not be returning that it can support range
43314 // requests.
43315 networkManager.abortRequest(fullRequestXhrId);
43316 }
43317
43318 this._headersReceivedCapability.resolve();
43319 },
43320
43321 _onProgressiveData:
43322 function PDFNetworkStreamFullRequestReader_onProgressiveData(chunk) {
43323 if (this._requests.length > 0) {
43324 var requestCapability = this._requests.shift();
43325 requestCapability.resolve({value: chunk, done: false});
43326 } else {
43327 this._cachedChunks.push(chunk);
43328 }
43329 },
43330
43331 _onDone: function PDFNetworkStreamFullRequestReader_onDone(args) {
43332 if (args) {
43333 this._onProgressiveData(args.chunk);
43334 }
43335 this._done = true;
43336 if (this._cachedChunks.length > 0) {
43337 return;
43338 }
43339 this._requests.forEach(function (requestCapability) {
43340 requestCapability.resolve({value: undefined, done: true});
43341 });
43342 this._requests = [];
43343 },
43344
43345 _onError: function PDFNetworkStreamFullRequestReader_onError(status) {
43346 var url = this._url;
43347 var exception;
43348 if (status === 404 || status === 0 && /^file:/.test(url)) {
43349 exception = new MissingPDFException('Missing PDF "' + url + '".');
43350 } else {
43351 exception = new UnexpectedResponseException(
43352 'Unexpected server response (' + status +
43353 ') while retrieving PDF "' + url + '".', status);
43354 }
43355 this._storedError = exception;
43356 this._headersReceivedCapability.reject(exception);
43357 this._requests.forEach(function (requestCapability) {
43358 requestCapability.reject(exception);
43359 });
43360 this._requests = [];
43361 this._cachedChunks = [];
43362 },
43363
43364 _onProgress: function PDFNetworkStreamFullRequestReader_onProgress(data) {
43365 if (this.onProgress) {
43366 this.onProgress({
43367 loaded: data.loaded,
43368 total: data.lengthComputable ? data.total : this._contentLength
43369 });
43370 }
43371 },
43372
43373 get isRangeSupported() {
43374 return this._isRangeSupported;
43375 },
43376
43377 get isStreamingSupported() {
43378 return this._isStreamingSupported;
43379 },
43380
43381 get contentLength() {
43382 return this._contentLength;
43383 },
43384
43385 get headersReady() {
43386 return this._headersReceivedCapability.promise;
43387 },
43388
43389 read: function PDFNetworkStreamFullRequestReader_read() {
43390 if (this._storedError) {
43391 return Promise.reject(this._storedError);
43392 }
43393 if (this._cachedChunks.length > 0) {
43394 var chunk = this._cachedChunks.shift();
43395 return Promise.resolve(chunk);
43396 }
43397 if (this._done) {
43398 return Promise.resolve({value: undefined, done: true});
43399 }
43400 var requestCapability = createPromiseCapability();
43401 this._requests.push(requestCapability);
43402 return requestCapability.promise;
43403 },
43404
43405 cancel: function PDFNetworkStreamFullRequestReader_cancel(reason) {
43406 this._done = true;
43407 this._headersReceivedCapability.reject(reason);
43408 this._requests.forEach(function (requestCapability) {
43409 requestCapability.resolve({value: undefined, done: true});
43410 });
43411 this._requests = [];
43412 if (this._manager.isPendingRequest(this._fullRequestId)) {
43413 this._manager.abortRequest(this._fullRequestId);
43414 }
43415 this._fullRequestReader = null;
43416 }
43417 };
43418
43419 /** @implements {IPDFStreamRangeReader} */
43420 function PDFNetworkStreamRangeRequestReader(manager, begin, end) {
43421 this._manager = manager;
43422 var args = {
43423 onDone: this._onDone.bind(this),
43424 onProgress: this._onProgress.bind(this)
43425 };
43426 this._requestId = manager.requestRange(begin, end, args);
43427 this._requests = [];
43428 this._queuedChunk = null;
43429 this._done = false;
43430
43431 this.onProgress = null;
43432 this.onClosed = null;
43433 }
43434
43435 PDFNetworkStreamRangeRequestReader.prototype = {
43436 _close: function PDFNetworkStreamRangeRequestReader_close() {
43437 if (this.onClosed) {
43438 this.onClosed(this);
43439 }
43440 },
43441
43442 _onDone: function PDFNetworkStreamRangeRequestReader_onDone(data) {
43443 var chunk = data.chunk;
43444 if (this._requests.length > 0) {
43445 var requestCapability = this._requests.shift();
43446 requestCapability.resolve({value: chunk, done: false});
43447 } else {
43448 this._queuedChunk = chunk;
43449 }
43450 this._done = true;
43451 this._requests.forEach(function (requestCapability) {
43452 requestCapability.resolve({value: undefined, done: true});
43453 });
43454 this._requests = [];
43455 this._close();
43456 },
43457
43458 _onProgress: function PDFNetworkStreamRangeRequestReader_onProgress(evt) {
43459 if (!this.isStreamingSupported && this.onProgress) {
43460 this.onProgress({
43461 loaded: evt.loaded
43462 });
43463 }
43464 },
43465
43466 get isStreamingSupported() {
43467 return false; // TODO allow progressive range bytes loading
43468 },
43469
43470 read: function PDFNetworkStreamRangeRequestReader_read() {
43471 if (this._queuedChunk !== null) {
43472 var chunk = this._queuedChunk;
43473 this._queuedChunk = null;
43474 return Promise.resolve({value: chunk, done: false});
43475 }
43476 if (this._done) {
43477 return Promise.resolve({value: undefined, done: true});
43478 }
43479 var requestCapability = createPromiseCapability();
43480 this._requests.push(requestCapability);
43481 return requestCapability.promise;
43482 },
43483
43484 cancel: function PDFNetworkStreamRangeRequestReader_cancel(reason) {
43485 this._done = true;
43486 this._requests.forEach(function (requestCapability) {
43487 requestCapability.resolve({value: undefined, done: true});
43488 });
43489 this._requests = [];
43490 if (this._manager.isPendingRequest(this._requestId)) {
43491 this._manager.abortRequest(this._requestId);
43492 }
43493 this._close();
43494 }
43495 };
43496
43497 coreWorker.setPDFNetworkStreamClass(PDFNetworkStream);
43498
43499 exports.PDFNetworkStream = PDFNetworkStream;
43500 exports.NetworkManager = NetworkManager;
43501}));
43502 }).call(pdfjsLibs);
43503
43504 exports.WorkerMessageHandler = pdfjsLibs.pdfjsCoreWorker.WorkerMessageHandler;
43505}));
43506