diff options
Diffstat (limited to 'static/dist/js/pdf.worker.js')
-rw-r--r-- | static/dist/js/pdf.worker.js | 43506 |
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) { | ||
21 | define('pdfjs-dist/build/pdf.worker', ['exports'], factory); | ||
22 | } else if (typeof exports !== 'undefined') { | ||
23 | factory(exports); | ||
24 | } else { | ||
25 | factory((root.pdfjsDistBuildPdfWorker = {})); | ||
26 | } | ||
27 | }(this, function (exports) { | ||
28 | // Use strict in our context only - users might not want it | ||
29 | 'use strict'; | ||
30 | |||
31 | var pdfjsVersion = '1.6.210'; | ||
32 | var 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 | */ | ||
58 | var 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 | |||
217 | exports.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 | |||
629 | exports.bidi = bidi; | ||
630 | })); | ||
631 | |||
632 | |||
633 | (function (root, factory) { | ||
634 | { | ||
635 | factory((root.pdfjsCoreCharsets = {})); | ||
636 | } | ||
637 | }(this, function (exports) { | ||
638 | |||
639 | var 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 | |||
676 | var 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 | |||
716 | var 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 | |||
739 | exports.ISOAdobeCharset = ISOAdobeCharset; | ||
740 | exports.ExpertCharset = ExpertCharset; | ||
741 | exports.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 | |||
1036 | var globalScope = (typeof window !== 'undefined') ? window : | ||
1037 | (typeof global !== 'undefined') ? global : | ||
1038 | (typeof self !== 'undefined') ? self : this; | ||
1039 | |||
1040 | var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; | ||
1041 | |||
1042 | var 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 | |||
1055 | var ImageKind = { | ||
1056 | GRAYSCALE_1BPP: 1, | ||
1057 | RGB_24BPP: 2, | ||
1058 | RGBA_32BPP: 3 | ||
1059 | }; | ||
1060 | |||
1061 | var 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 | |||
1090 | var 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 | |||
1103 | var 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 | |||
1125 | var AnnotationBorderStyleType = { | ||
1126 | SOLID: 1, | ||
1127 | DASHED: 2, | ||
1128 | BEVELED: 3, | ||
1129 | INSET: 4, | ||
1130 | UNDERLINE: 5 | ||
1131 | }; | ||
1132 | |||
1133 | var 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 | |||
1146 | var 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 | |||
1160 | var VERBOSITY_LEVELS = { | ||
1161 | errors: 0, | ||
1162 | warnings: 1, | ||
1163 | infos: 5 | ||
1164 | }; | ||
1165 | |||
1166 | // All the possible operations for an operator list. | ||
1167 | var 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 | |||
1263 | var verbosity = VERBOSITY_LEVELS.warnings; | ||
1264 | |||
1265 | function setVerbosityLevel(level) { | ||
1266 | verbosity = level; | ||
1267 | } | ||
1268 | |||
1269 | function 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. | ||
1276 | function info(msg) { | ||
1277 | if (verbosity >= VERBOSITY_LEVELS.infos) { | ||
1278 | console.log('Info: ' + msg); | ||
1279 | } | ||
1280 | } | ||
1281 | |||
1282 | // Non-fatal warnings. | ||
1283 | function 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. | ||
1290 | function 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. | ||
1296 | function 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 | |||
1304 | function 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 | |||
1312 | function assert(cond, msg) { | ||
1313 | if (!cond) { | ||
1314 | error(msg); | ||
1315 | } | ||
1316 | } | ||
1317 | |||
1318 | var 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. | ||
1328 | function 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. | ||
1343 | function 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 | |||
1366 | function 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 | |||
1374 | function 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 | |||
1386 | var PasswordResponses = { | ||
1387 | NEED_PASSWORD: 1, | ||
1388 | INCORRECT_PASSWORD: 2 | ||
1389 | }; | ||
1390 | |||
1391 | var 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 | |||
1404 | var 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 | |||
1417 | var 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 | |||
1429 | var 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 | |||
1441 | var 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 | |||
1455 | var 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 | |||
1467 | var 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 | |||
1481 | var 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 | |||
1493 | var NullCharactersRegExp = /\x00/g; | ||
1494 | |||
1495 | function 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 | |||
1503 | function 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 | |||
1520 | function 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 | */ | ||
1535 | function 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 | */ | ||
1548 | function 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 | |||
1579 | function string32(value) { | ||
1580 | return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff, | ||
1581 | (value >> 8) & 0xff, value & 0xff); | ||
1582 | } | ||
1583 | |||
1584 | function log2(x) { | ||
1585 | var n = 1, i = 0; | ||
1586 | while (x > n) { | ||
1587 | n <<= 1; | ||
1588 | i++; | ||
1589 | } | ||
1590 | return i; | ||
1591 | } | ||
1592 | |||
1593 | function readInt8(data, start) { | ||
1594 | return (data[start] << 24) >> 24; | ||
1595 | } | ||
1596 | |||
1597 | function readUint16(data, offset) { | ||
1598 | return (data[offset] << 8) | data[offset + 1]; | ||
1599 | } | ||
1600 | |||
1601 | function 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 | ||
1608 | function 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. | ||
1616 | function isEvalSupported() { | ||
1617 | try { | ||
1618 | /* jshint evil: true */ | ||
1619 | new Function(''); | ||
1620 | return true; | ||
1621 | } catch (e) { | ||
1622 | return false; | ||
1623 | } | ||
1624 | } | ||
1625 | |||
1626 | var 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 | |||
1666 | exports.Uint32ArrayView = Uint32ArrayView; | ||
1667 | |||
1668 | var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; | ||
1669 | |||
1670 | var 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 | */ | ||
1923 | var 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 | |||
2054 | var 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 | |||
2066 | function 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 | |||
2083 | function stringToUTF8String(str) { | ||
2084 | return decodeURIComponent(escape(str)); | ||
2085 | } | ||
2086 | |||
2087 | function utf8StringToString(str) { | ||
2088 | return unescape(encodeURIComponent(str)); | ||
2089 | } | ||
2090 | |||
2091 | function isEmptyObj(obj) { | ||
2092 | for (var key in obj) { | ||
2093 | return false; | ||
2094 | } | ||
2095 | return true; | ||
2096 | } | ||
2097 | |||
2098 | function isBool(v) { | ||
2099 | return typeof v === 'boolean'; | ||
2100 | } | ||
2101 | |||
2102 | function isInt(v) { | ||
2103 | return typeof v === 'number' && ((v | 0) === v); | ||
2104 | } | ||
2105 | |||
2106 | function isNum(v) { | ||
2107 | return typeof v === 'number'; | ||
2108 | } | ||
2109 | |||
2110 | function isString(v) { | ||
2111 | return typeof v === 'string'; | ||
2112 | } | ||
2113 | |||
2114 | function isArray(v) { | ||
2115 | return v instanceof Array; | ||
2116 | } | ||
2117 | |||
2118 | function 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. | ||
2123 | function 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 | */ | ||
2143 | function 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 | |||
2499 | var 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 | |||
2559 | var 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 | |||
2566 | var 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 | |||
2592 | function 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 | |||
2657 | MessageHandler.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 | |||
2726 | function 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 | |||
3380 | exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX; | ||
3381 | exports.IDENTITY_MATRIX = IDENTITY_MATRIX; | ||
3382 | exports.OPS = OPS; | ||
3383 | exports.VERBOSITY_LEVELS = VERBOSITY_LEVELS; | ||
3384 | exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; | ||
3385 | exports.AnnotationBorderStyleType = AnnotationBorderStyleType; | ||
3386 | exports.AnnotationFieldFlag = AnnotationFieldFlag; | ||
3387 | exports.AnnotationFlag = AnnotationFlag; | ||
3388 | exports.AnnotationType = AnnotationType; | ||
3389 | exports.FontType = FontType; | ||
3390 | exports.ImageKind = ImageKind; | ||
3391 | exports.InvalidPDFException = InvalidPDFException; | ||
3392 | exports.MessageHandler = MessageHandler; | ||
3393 | exports.MissingDataException = MissingDataException; | ||
3394 | exports.MissingPDFException = MissingPDFException; | ||
3395 | exports.NotImplementedException = NotImplementedException; | ||
3396 | exports.PageViewport = PageViewport; | ||
3397 | exports.PasswordException = PasswordException; | ||
3398 | exports.PasswordResponses = PasswordResponses; | ||
3399 | exports.StatTimer = StatTimer; | ||
3400 | exports.StreamType = StreamType; | ||
3401 | exports.TextRenderingMode = TextRenderingMode; | ||
3402 | exports.UnexpectedResponseException = UnexpectedResponseException; | ||
3403 | exports.UnknownErrorException = UnknownErrorException; | ||
3404 | exports.Util = Util; | ||
3405 | exports.XRefParseException = XRefParseException; | ||
3406 | exports.arrayByteLength = arrayByteLength; | ||
3407 | exports.arraysToBytes = arraysToBytes; | ||
3408 | exports.assert = assert; | ||
3409 | exports.bytesToString = bytesToString; | ||
3410 | exports.createBlob = createBlob; | ||
3411 | exports.createPromiseCapability = createPromiseCapability; | ||
3412 | exports.createObjectURL = createObjectURL; | ||
3413 | exports.deprecated = deprecated; | ||
3414 | exports.error = error; | ||
3415 | exports.getLookupTableFactory = getLookupTableFactory; | ||
3416 | exports.getVerbosityLevel = getVerbosityLevel; | ||
3417 | exports.globalScope = globalScope; | ||
3418 | exports.info = info; | ||
3419 | exports.isArray = isArray; | ||
3420 | exports.isArrayBuffer = isArrayBuffer; | ||
3421 | exports.isBool = isBool; | ||
3422 | exports.isEmptyObj = isEmptyObj; | ||
3423 | exports.isInt = isInt; | ||
3424 | exports.isNum = isNum; | ||
3425 | exports.isString = isString; | ||
3426 | exports.isSpace = isSpace; | ||
3427 | exports.isSameOrigin = isSameOrigin; | ||
3428 | exports.isValidUrl = isValidUrl; | ||
3429 | exports.isLittleEndian = isLittleEndian; | ||
3430 | exports.isEvalSupported = isEvalSupported; | ||
3431 | exports.loadJpegStream = loadJpegStream; | ||
3432 | exports.log2 = log2; | ||
3433 | exports.readInt8 = readInt8; | ||
3434 | exports.readUint16 = readUint16; | ||
3435 | exports.readUint32 = readUint32; | ||
3436 | exports.removeNullCharacters = removeNullCharacters; | ||
3437 | exports.setVerbosityLevel = setVerbosityLevel; | ||
3438 | exports.shadow = shadow; | ||
3439 | exports.string32 = string32; | ||
3440 | exports.stringToBytes = stringToBytes; | ||
3441 | exports.stringToPDFString = stringToPDFString; | ||
3442 | exports.stringToUTF8String = stringToUTF8String; | ||
3443 | exports.utf8StringToString = utf8StringToString; | ||
3444 | exports.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 | |||
3455 | var error = sharedUtil.error; | ||
3456 | var info = sharedUtil.info; | ||
3457 | var bytesToString = sharedUtil.bytesToString; | ||
3458 | var warn = sharedUtil.warn; | ||
3459 | var isArray = sharedUtil.isArray; | ||
3460 | var Util = sharedUtil.Util; | ||
3461 | var stringToBytes = sharedUtil.stringToBytes; | ||
3462 | var assert = sharedUtil.assert; | ||
3463 | var ISOAdobeCharset = coreCharsets.ISOAdobeCharset; | ||
3464 | var ExpertCharset = coreCharsets.ExpertCharset; | ||
3465 | var ExpertSubsetCharset = coreCharsets.ExpertSubsetCharset; | ||
3466 | var StandardEncoding = coreEncodings.StandardEncoding; | ||
3467 | var ExpertEncoding = coreEncodings.ExpertEncoding; | ||
3468 | |||
3469 | // Maximum subroutine call depth of type 2 chartrings. Matches OTS. | ||
3470 | var 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 | */ | ||
3476 | var 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 | |||
3545 | var 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 | ||
4331 | var 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 | |||
4352 | var 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 | |||
4362 | var 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 | |||
4386 | var 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 | |||
4410 | var 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 | |||
4491 | var 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 | |||
4543 | var 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 | |||
4576 | var CFFCharsetPredefinedTypes = { | ||
4577 | ISO_ADOBE: 0, | ||
4578 | EXPERT: 1, | ||
4579 | EXPERT_SUBSET: 2 | ||
4580 | }; | ||
4581 | var 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 | |||
4591 | var 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 | |||
4601 | var 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. | ||
4619 | var 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. | ||
4671 | var 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 | |||
5078 | exports.CFFStandardStrings = CFFStandardStrings; | ||
5079 | exports.CFFParser = CFFParser; | ||
5080 | exports.CFF = CFF; | ||
5081 | exports.CFFHeader = CFFHeader; | ||
5082 | exports.CFFStrings = CFFStrings; | ||
5083 | exports.CFFIndex = CFFIndex; | ||
5084 | exports.CFFCharset = CFFCharset; | ||
5085 | exports.CFFTopDict = CFFTopDict; | ||
5086 | exports.CFFPrivateDict = CFFPrivateDict; | ||
5087 | exports.CFFCompiler = CFFCompiler; | ||
5088 | })); | ||
5089 | |||
5090 | |||
5091 | (function (root, factory) { | ||
5092 | { | ||
5093 | factory((root.pdfjsCoreChunkedStream = {}), root.pdfjsSharedUtil); | ||
5094 | } | ||
5095 | }(this, function (exports, sharedUtil) { | ||
5096 | |||
5097 | var MissingDataException = sharedUtil.MissingDataException; | ||
5098 | var arrayByteLength = sharedUtil.arrayByteLength; | ||
5099 | var arraysToBytes = sharedUtil.arraysToBytes; | ||
5100 | var assert = sharedUtil.assert; | ||
5101 | var createPromiseCapability = sharedUtil.createPromiseCapability; | ||
5102 | var isInt = sharedUtil.isInt; | ||
5103 | var isEmptyObj = sharedUtil.isEmptyObj; | ||
5104 | |||
5105 | var 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 | |||
5349 | var 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 | |||
5649 | exports.ChunkedStream = ChunkedStream; | ||
5650 | exports.ChunkedStreamManager = ChunkedStreamManager; | ||
5651 | })); | ||
5652 | |||
5653 | |||
5654 | (function (root, factory) { | ||
5655 | { | ||
5656 | factory((root.pdfjsCoreGlyphList = {}), root.pdfjsSharedUtil); | ||
5657 | } | ||
5658 | }(this, function (exports, sharedUtil) { | ||
5659 | var getLookupTableFactory = sharedUtil.getLookupTableFactory; | ||
5660 | |||
5661 | var 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 | |||
9868 | var 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 | |||
10074 | exports.getGlyphsUnicode = getGlyphsUnicode; | ||
10075 | exports.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 | |||
10086 | var error = sharedUtil.error; | ||
10087 | var log2 = sharedUtil.log2; | ||
10088 | var readInt8 = sharedUtil.readInt8; | ||
10089 | var readUint16 = sharedUtil.readUint16; | ||
10090 | var readUint32 = sharedUtil.readUint32; | ||
10091 | var shadow = sharedUtil.shadow; | ||
10092 | var ArithmeticDecoder = coreArithmeticDecoder.ArithmeticDecoder; | ||
10093 | |||
10094 | var 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 | |||
11162 | exports.Jbig2Image = Jbig2Image; | ||
11163 | })); | ||
11164 | |||
11165 | |||
11166 | (function (root, factory) { | ||
11167 | { | ||
11168 | factory((root.pdfjsCoreJpg = {}), root.pdfjsSharedUtil); | ||
11169 | } | ||
11170 | }(this, function (exports, sharedUtil) { | ||
11171 | |||
11172 | var 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 | |||
11187 | var 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 | |||
12232 | exports.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 | |||
12243 | var info = sharedUtil.info; | ||
12244 | var warn = sharedUtil.warn; | ||
12245 | var error = sharedUtil.error; | ||
12246 | var log2 = sharedUtil.log2; | ||
12247 | var readUint16 = sharedUtil.readUint16; | ||
12248 | var readUint32 = sharedUtil.readUint32; | ||
12249 | var ArithmeticDecoder = coreArithmeticDecoder.ArithmeticDecoder; | ||
12250 | |||
12251 | var 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 | |||
14442 | exports.JpxImage = JpxImage; | ||
14443 | })); | ||
14444 | |||
14445 | |||
14446 | (function (root, factory) { | ||
14447 | { | ||
14448 | factory((root.pdfjsCoreMetrics = {}), root.pdfjsSharedUtil); | ||
14449 | } | ||
14450 | }(this, function (exports, sharedUtil) { | ||
14451 | var 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. | ||
14456 | var 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 | |||
17395 | exports.getMetrics = getMetrics; | ||
17396 | })); | ||
17397 | |||
17398 | |||
17399 | |||
17400 | (function (root, factory) { | ||
17401 | { | ||
17402 | factory((root.pdfjsCoreMurmurHash3 = {}), root.pdfjsSharedUtil); | ||
17403 | } | ||
17404 | }(this, function (exports, sharedUtil) { | ||
17405 | |||
17406 | var Uint32ArrayView = sharedUtil.Uint32ArrayView; | ||
17407 | |||
17408 | var 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 | |||
17548 | exports.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 | |||
17558 | var isArray = sharedUtil.isArray; | ||
17559 | |||
17560 | var 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 | |||
17577 | var 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 | |||
17594 | var 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 | |||
17718 | var 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. | ||
17741 | var 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 | |||
17763 | var 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 | |||
17799 | function isName(v, name) { | ||
17800 | return v instanceof Name && (name === undefined || v.name === name); | ||
17801 | } | ||
17802 | |||
17803 | function isCmd(v, cmd) { | ||
17804 | return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); | ||
17805 | } | ||
17806 | |||
17807 | function isDict(v, type) { | ||
17808 | return v instanceof Dict && | ||
17809 | (type === undefined || isName(v.get('Type'), type)); | ||
17810 | } | ||
17811 | |||
17812 | function isRef(v) { | ||
17813 | return v instanceof Ref; | ||
17814 | } | ||
17815 | |||
17816 | function isRefsEqual(v1, v2) { | ||
17817 | return v1.num === v2.num && v1.gen === v2.gen; | ||
17818 | } | ||
17819 | |||
17820 | function isStream(v) { | ||
17821 | return typeof v === 'object' && v !== null && v.getBytes !== undefined; | ||
17822 | } | ||
17823 | |||
17824 | exports.Cmd = Cmd; | ||
17825 | exports.Dict = Dict; | ||
17826 | exports.Name = Name; | ||
17827 | exports.Ref = Ref; | ||
17828 | exports.RefSet = RefSet; | ||
17829 | exports.RefSetCache = RefSetCache; | ||
17830 | exports.isCmd = isCmd; | ||
17831 | exports.isDict = isDict; | ||
17832 | exports.isName = isName; | ||
17833 | exports.isRef = isRef; | ||
17834 | exports.isRefsEqual = isRefsEqual; | ||
17835 | exports.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 | |||
19825 | var Util = sharedUtil.Util; | ||
19826 | var error = sharedUtil.error; | ||
19827 | var info = sharedUtil.info; | ||
19828 | var isInt = sharedUtil.isInt; | ||
19829 | var isArray = sharedUtil.isArray; | ||
19830 | var createObjectURL = sharedUtil.createObjectURL; | ||
19831 | var shadow = sharedUtil.shadow; | ||
19832 | var warn = sharedUtil.warn; | ||
19833 | var isSpace = sharedUtil.isSpace; | ||
19834 | var Dict = corePrimitives.Dict; | ||
19835 | var isDict = corePrimitives.isDict; | ||
19836 | var Jbig2Image = coreJbig2.Jbig2Image; | ||
19837 | var JpegImage = coreJpg.JpegImage; | ||
19838 | var JpxImage = coreJpx.JpxImage; | ||
19839 | |||
19840 | var 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 | |||
19928 | var 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 | ||
19944 | var 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 | |||
20071 | var 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 | |||
20112 | var 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 | |||
20475 | var 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 | */ | ||
20685 | var 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 | */ | ||
20771 | var 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 | */ | ||
20840 | var 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 | |||
20900 | var 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 | |||
20945 | var 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 | |||
21028 | var 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 | |||
21090 | var 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 | |||
21137 | var 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 | |||
22136 | var 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 | |||
22267 | var 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 | |||
22277 | exports.Ascii85Stream = Ascii85Stream; | ||
22278 | exports.AsciiHexStream = AsciiHexStream; | ||
22279 | exports.CCITTFaxStream = CCITTFaxStream; | ||
22280 | exports.DecryptStream = DecryptStream; | ||
22281 | exports.DecodeStream = DecodeStream; | ||
22282 | exports.FlateStream = FlateStream; | ||
22283 | exports.Jbig2Stream = Jbig2Stream; | ||
22284 | exports.JpegStream = JpegStream; | ||
22285 | exports.JpxStream = JpxStream; | ||
22286 | exports.NullStream = NullStream; | ||
22287 | exports.PredictorStream = PredictorStream; | ||
22288 | exports.RunLengthStream = RunLengthStream; | ||
22289 | exports.Stream = Stream; | ||
22290 | exports.StreamsSequenceStream = StreamsSequenceStream; | ||
22291 | exports.StringStream = StringStream; | ||
22292 | exports.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 | |||
22303 | var PasswordException = sharedUtil.PasswordException; | ||
22304 | var PasswordResponses = sharedUtil.PasswordResponses; | ||
22305 | var bytesToString = sharedUtil.bytesToString; | ||
22306 | var error = sharedUtil.error; | ||
22307 | var isInt = sharedUtil.isInt; | ||
22308 | var stringToBytes = sharedUtil.stringToBytes; | ||
22309 | var utf8StringToString = sharedUtil.utf8StringToString; | ||
22310 | var warn = sharedUtil.warn; | ||
22311 | var Name = corePrimitives.Name; | ||
22312 | var isName = corePrimitives.isName; | ||
22313 | var isDict = corePrimitives.isDict; | ||
22314 | var DecryptStream = coreStream.DecryptStream; | ||
22315 | |||
22316 | var 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 | |||
22358 | var 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 | })(); | ||
22442 | var 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 | |||
22530 | var 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 | |||
22652 | var 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 | })(); | ||
22907 | var calculateSHA384 = (function calculateSHA384Closure() { | ||
22908 | function hash(data, offset, length) { | ||
22909 | return calculateSHA512(data, offset, length, true); | ||
22910 | } | ||
22911 | |||
22912 | return hash; | ||
22913 | })(); | ||
22914 | var 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 | |||
22927 | var 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 | |||
23359 | var 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 | |||
23816 | var 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 | |||
23883 | var 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 | |||
24005 | var 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 | |||
24030 | var 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 | |||
24366 | exports.AES128Cipher = AES128Cipher; | ||
24367 | exports.AES256Cipher = AES256Cipher; | ||
24368 | exports.ARCFourCipher = ARCFourCipher; | ||
24369 | exports.CipherTransformFactory = CipherTransformFactory; | ||
24370 | exports.PDF17 = PDF17; | ||
24371 | exports.PDF20 = PDF20; | ||
24372 | exports.calculateMD5 = calculateMD5; | ||
24373 | exports.calculateSHA256 = calculateSHA256; | ||
24374 | exports.calculateSHA384 = calculateSHA384; | ||
24375 | exports.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 | |||
24387 | var Util = sharedUtil.Util; | ||
24388 | var bytesToString = sharedUtil.bytesToString; | ||
24389 | var error = sharedUtil.error; | ||
24390 | var Stream = coreStream.Stream; | ||
24391 | var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode; | ||
24392 | var StandardEncoding = coreEncodings.StandardEncoding; | ||
24393 | var CFFParser = coreCFFParser.CFFParser; | ||
24394 | |||
24395 | var 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 | |||
25092 | exports.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 | |||
25103 | var MissingDataException = sharedUtil.MissingDataException; | ||
25104 | var StreamType = sharedUtil.StreamType; | ||
25105 | var assert = sharedUtil.assert; | ||
25106 | var error = sharedUtil.error; | ||
25107 | var info = sharedUtil.info; | ||
25108 | var isArray = sharedUtil.isArray; | ||
25109 | var isInt = sharedUtil.isInt; | ||
25110 | var isNum = sharedUtil.isNum; | ||
25111 | var isString = sharedUtil.isString; | ||
25112 | var warn = sharedUtil.warn; | ||
25113 | var Cmd = corePrimitives.Cmd; | ||
25114 | var Dict = corePrimitives.Dict; | ||
25115 | var Name = corePrimitives.Name; | ||
25116 | var Ref = corePrimitives.Ref; | ||
25117 | var isCmd = corePrimitives.isCmd; | ||
25118 | var isDict = corePrimitives.isDict; | ||
25119 | var isName = corePrimitives.isName; | ||
25120 | var Ascii85Stream = coreStream.Ascii85Stream; | ||
25121 | var AsciiHexStream = coreStream.AsciiHexStream; | ||
25122 | var CCITTFaxStream = coreStream.CCITTFaxStream; | ||
25123 | var FlateStream = coreStream.FlateStream; | ||
25124 | var Jbig2Stream = coreStream.Jbig2Stream; | ||
25125 | var JpegStream = coreStream.JpegStream; | ||
25126 | var JpxStream = coreStream.JpxStream; | ||
25127 | var LZWStream = coreStream.LZWStream; | ||
25128 | var NullStream = coreStream.NullStream; | ||
25129 | var PredictorStream = coreStream.PredictorStream; | ||
25130 | var RunLengthStream = coreStream.RunLengthStream; | ||
25131 | |||
25132 | var EOF = {}; | ||
25133 | |||
25134 | function isEOF(v) { | ||
25135 | return (v === EOF); | ||
25136 | } | ||
25137 | |||
25138 | var MAX_LENGTH_TO_CACHE = 1000; | ||
25139 | |||
25140 | var 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 | |||
25712 | var 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 | |||
26139 | var 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 | |||
26188 | exports.EOF = EOF; | ||
26189 | exports.Lexer = Lexer; | ||
26190 | exports.Linearization = Linearization; | ||
26191 | exports.Parser = Parser; | ||
26192 | exports.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 | |||
26203 | var warn = sharedUtil.warn; | ||
26204 | var isSpace = sharedUtil.isSpace; | ||
26205 | var Stream = coreStream.Stream; | ||
26206 | var 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. | ||
26210 | var 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 | */ | ||
26250 | var 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 | */ | ||
26547 | var 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 | |||
26892 | exports.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 | |||
26903 | var Util = sharedUtil.Util; | ||
26904 | var assert = sharedUtil.assert; | ||
26905 | var warn = sharedUtil.warn; | ||
26906 | var error = sharedUtil.error; | ||
26907 | var isInt = sharedUtil.isInt; | ||
26908 | var isString = sharedUtil.isString; | ||
26909 | var MissingDataException = sharedUtil.MissingDataException; | ||
26910 | var isName = corePrimitives.isName; | ||
26911 | var isCmd = corePrimitives.isCmd; | ||
26912 | var isStream = corePrimitives.isStream; | ||
26913 | var StringStream = coreStream.StringStream; | ||
26914 | var Lexer = coreParser.Lexer; | ||
26915 | var isEOF = coreParser.isEOF; | ||
26916 | |||
26917 | var 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. | ||
27090 | var 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. | ||
27228 | var 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 | |||
27296 | var 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 | |||
27604 | var 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 | |||
27904 | exports.CMap = CMap; | ||
27905 | exports.CMapFactory = CMapFactory; | ||
27906 | exports.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 | |||
27923 | var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX; | ||
27924 | var FontType = sharedUtil.FontType; | ||
27925 | var assert = sharedUtil.assert; | ||
27926 | var bytesToString = sharedUtil.bytesToString; | ||
27927 | var error = sharedUtil.error; | ||
27928 | var info = sharedUtil.info; | ||
27929 | var isArray = sharedUtil.isArray; | ||
27930 | var isInt = sharedUtil.isInt; | ||
27931 | var isNum = sharedUtil.isNum; | ||
27932 | var readUint32 = sharedUtil.readUint32; | ||
27933 | var shadow = sharedUtil.shadow; | ||
27934 | var string32 = sharedUtil.string32; | ||
27935 | var warn = sharedUtil.warn; | ||
27936 | var MissingDataException = sharedUtil.MissingDataException; | ||
27937 | var isSpace = sharedUtil.isSpace; | ||
27938 | var Stream = coreStream.Stream; | ||
27939 | var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode; | ||
27940 | var getDingbatsGlyphsUnicode = coreGlyphList.getDingbatsGlyphsUnicode; | ||
27941 | var FontRendererFactory = coreFontRenderer.FontRendererFactory; | ||
27942 | var StandardEncoding = coreEncodings.StandardEncoding; | ||
27943 | var MacRomanEncoding = coreEncodings.MacRomanEncoding; | ||
27944 | var SymbolSetEncoding = coreEncodings.SymbolSetEncoding; | ||
27945 | var ZapfDingbatsEncoding = coreEncodings.ZapfDingbatsEncoding; | ||
27946 | var getEncoding = coreEncodings.getEncoding; | ||
27947 | var getStdFontMap = coreStandardFonts.getStdFontMap; | ||
27948 | var getNonStdFontMap = coreStandardFonts.getNonStdFontMap; | ||
27949 | var getGlyphMapForStandardFonts = coreStandardFonts.getGlyphMapForStandardFonts; | ||
27950 | var getSupplementalGlyphMapForArialBlack = | ||
27951 | coreStandardFonts.getSupplementalGlyphMapForArialBlack; | ||
27952 | var getUnicodeRangeFor = coreUnicode.getUnicodeRangeFor; | ||
27953 | var mapSpecialUnicodeValues = coreUnicode.mapSpecialUnicodeValues; | ||
27954 | var getUnicodeForGlyph = coreUnicode.getUnicodeForGlyph; | ||
27955 | var Type1Parser = coreType1Parser.Type1Parser; | ||
27956 | var CFFStandardStrings = coreCFFParser.CFFStandardStrings; | ||
27957 | var CFFParser = coreCFFParser.CFFParser; | ||
27958 | var CFFCompiler = coreCFFParser.CFFCompiler; | ||
27959 | var CFF = coreCFFParser.CFF; | ||
27960 | var CFFHeader = coreCFFParser.CFFHeader; | ||
27961 | var CFFTopDict = coreCFFParser.CFFTopDict; | ||
27962 | var CFFPrivateDict = coreCFFParser.CFFPrivateDict; | ||
27963 | var CFFStrings = coreCFFParser.CFFStrings; | ||
27964 | var CFFIndex = coreCFFParser.CFFIndex; | ||
27965 | var CFFCharset = coreCFFParser.CFFCharset; | ||
27966 | |||
27967 | // Unicode Private Use Area | ||
27968 | var PRIVATE_USE_OFFSET_START = 0xE000; | ||
27969 | var PRIVATE_USE_OFFSET_END = 0xF8FF; | ||
27970 | var 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 | ||
27974 | var 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. | ||
27978 | var SEAC_ANALYSIS_ENABLED = false; | ||
27979 | |||
27980 | var 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 | |||
27992 | var 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 | |||
28030 | function 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 | |||
28046 | function 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 | |||
28070 | function 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. | ||
28094 | function 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 | |||
28111 | var 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 | |||
28140 | var 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 | |||
28180 | var 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 | |||
28220 | var 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. | ||
28365 | var 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 | */ | ||
28397 | var 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 | |||
30724 | var 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 | */ | ||
30753 | function 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. | ||
30816 | var 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 | |||
31172 | var 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 | |||
31250 | exports.SEAC_ANALYSIS_ENABLED = SEAC_ANALYSIS_ENABLED; | ||
31251 | exports.ErrorFont = ErrorFont; | ||
31252 | exports.Font = Font; | ||
31253 | exports.FontFlags = FontFlags; | ||
31254 | exports.IdentityToUnicodeMap = IdentityToUnicodeMap; | ||
31255 | exports.ToUnicodeMap = ToUnicodeMap; | ||
31256 | exports.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 | |||
31267 | var error = sharedUtil.error; | ||
31268 | var isSpace = sharedUtil.isSpace; | ||
31269 | var EOF = coreParser.EOF; | ||
31270 | |||
31271 | var 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 | |||
31351 | var PostScriptTokenTypes = { | ||
31352 | LBRACE: 0, | ||
31353 | RBRACE: 1, | ||
31354 | NUMBER: 2, | ||
31355 | OPERATOR: 3, | ||
31356 | IF: 4, | ||
31357 | IFELSE: 5 | ||
31358 | }; | ||
31359 | |||
31360 | var 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 | |||
31386 | var 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 | |||
31474 | exports.PostScriptLexer = PostScriptLexer; | ||
31475 | exports.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 | |||
31486 | var error = sharedUtil.error; | ||
31487 | var info = sharedUtil.info; | ||
31488 | var isArray = sharedUtil.isArray; | ||
31489 | var isBool = sharedUtil.isBool; | ||
31490 | var isDict = corePrimitives.isDict; | ||
31491 | var isStream = corePrimitives.isStream; | ||
31492 | var PostScriptLexer = corePsParser.PostScriptLexer; | ||
31493 | var PostScriptParser = corePsParser.PostScriptParser; | ||
31494 | |||
31495 | var 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 | |||
31942 | function 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 | |||
31956 | var 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 | })(); | ||
32006 | var 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. | ||
32249 | var 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 | |||
32610 | exports.isPDFFunction = isPDFFunction; | ||
32611 | exports.PDFFunction = PDFFunction; | ||
32612 | exports.PostScriptEvaluator = PostScriptEvaluator; | ||
32613 | exports.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 | |||
32624 | var error = sharedUtil.error; | ||
32625 | var info = sharedUtil.info; | ||
32626 | var isArray = sharedUtil.isArray; | ||
32627 | var isString = sharedUtil.isString; | ||
32628 | var shadow = sharedUtil.shadow; | ||
32629 | var warn = sharedUtil.warn; | ||
32630 | var isDict = corePrimitives.isDict; | ||
32631 | var isName = corePrimitives.isName; | ||
32632 | var isStream = corePrimitives.isStream; | ||
32633 | var PDFFunction = coreFunction.PDFFunction; | ||
32634 | |||
32635 | var 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 | */ | ||
33049 | var 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 | |||
33128 | var 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 | |||
33138 | var 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 | |||
33204 | var 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 | |||
33246 | var 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 | |||
33295 | var 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 | // | ||
33379 | var 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 | // | ||
33475 | var 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 | // | ||
33778 | var 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 | |||
33917 | exports.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 | |||
33930 | var ImageKind = sharedUtil.ImageKind; | ||
33931 | var assert = sharedUtil.assert; | ||
33932 | var error = sharedUtil.error; | ||
33933 | var info = sharedUtil.info; | ||
33934 | var isArray = sharedUtil.isArray; | ||
33935 | var warn = sharedUtil.warn; | ||
33936 | var Name = corePrimitives.Name; | ||
33937 | var isStream = corePrimitives.isStream; | ||
33938 | var ColorSpace = coreColorSpace.ColorSpace; | ||
33939 | var DecodeStream = coreStream.DecodeStream; | ||
33940 | var JpegStream = coreStream.JpegStream; | ||
33941 | var JpxImage = coreJpx.JpxImage; | ||
33942 | |||
33943 | var 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 | |||
34563 | exports.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 | |||
34576 | var InvalidPDFException = sharedUtil.InvalidPDFException; | ||
34577 | var MissingDataException = sharedUtil.MissingDataException; | ||
34578 | var XRefParseException = sharedUtil.XRefParseException; | ||
34579 | var assert = sharedUtil.assert; | ||
34580 | var bytesToString = sharedUtil.bytesToString; | ||
34581 | var createPromiseCapability = sharedUtil.createPromiseCapability; | ||
34582 | var error = sharedUtil.error; | ||
34583 | var info = sharedUtil.info; | ||
34584 | var isArray = sharedUtil.isArray; | ||
34585 | var isInt = sharedUtil.isInt; | ||
34586 | var isString = sharedUtil.isString; | ||
34587 | var shadow = sharedUtil.shadow; | ||
34588 | var stringToPDFString = sharedUtil.stringToPDFString; | ||
34589 | var stringToUTF8String = sharedUtil.stringToUTF8String; | ||
34590 | var warn = sharedUtil.warn; | ||
34591 | var isValidUrl = sharedUtil.isValidUrl; | ||
34592 | var Util = sharedUtil.Util; | ||
34593 | var Ref = corePrimitives.Ref; | ||
34594 | var RefSet = corePrimitives.RefSet; | ||
34595 | var RefSetCache = corePrimitives.RefSetCache; | ||
34596 | var isName = corePrimitives.isName; | ||
34597 | var isCmd = corePrimitives.isCmd; | ||
34598 | var isDict = corePrimitives.isDict; | ||
34599 | var isRef = corePrimitives.isRef; | ||
34600 | var isRefsEqual = corePrimitives.isRefsEqual; | ||
34601 | var isStream = corePrimitives.isStream; | ||
34602 | var CipherTransformFactory = coreCrypto.CipherTransformFactory; | ||
34603 | var Lexer = coreParser.Lexer; | ||
34604 | var Parser = coreParser.Parser; | ||
34605 | var ChunkedStream = coreChunkedStream.ChunkedStream; | ||
34606 | var ColorSpace = coreColorSpace.ColorSpace; | ||
34607 | |||
34608 | var 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 | |||
35142 | var 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 | */ | ||
35783 | var 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 | |||
35898 | var 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 | |||
35910 | var 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 | */ | ||
35929 | var 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 | */ | ||
36024 | var 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 | |||
36155 | exports.Catalog = Catalog; | ||
36156 | exports.ObjectLoader = ObjectLoader; | ||
36157 | exports.XRef = XRef; | ||
36158 | exports.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 | |||
36171 | var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES; | ||
36172 | var MissingDataException = sharedUtil.MissingDataException; | ||
36173 | var Util = sharedUtil.Util; | ||
36174 | var assert = sharedUtil.assert; | ||
36175 | var error = sharedUtil.error; | ||
36176 | var info = sharedUtil.info; | ||
36177 | var warn = sharedUtil.warn; | ||
36178 | var isStream = corePrimitives.isStream; | ||
36179 | var PDFFunction = coreFunction.PDFFunction; | ||
36180 | var ColorSpace = coreColorSpace.ColorSpace; | ||
36181 | |||
36182 | var 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 | |||
36192 | var 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 | |||
36239 | var 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. | ||
36243 | Shadings.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 | ||
36247 | Shadings.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. | ||
36382 | Shadings.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 | |||
36942 | Shadings.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 | |||
36955 | function 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 | |||
36969 | exports.Pattern = Pattern; | ||
36970 | exports.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 | |||
36990 | var FONT_IDENTITY_MATRIX = sharedUtil.FONT_IDENTITY_MATRIX; | ||
36991 | var IDENTITY_MATRIX = sharedUtil.IDENTITY_MATRIX; | ||
36992 | var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES; | ||
36993 | var ImageKind = sharedUtil.ImageKind; | ||
36994 | var OPS = sharedUtil.OPS; | ||
36995 | var TextRenderingMode = sharedUtil.TextRenderingMode; | ||
36996 | var Util = sharedUtil.Util; | ||
36997 | var assert = sharedUtil.assert; | ||
36998 | var createPromiseCapability = sharedUtil.createPromiseCapability; | ||
36999 | var error = sharedUtil.error; | ||
37000 | var info = sharedUtil.info; | ||
37001 | var isArray = sharedUtil.isArray; | ||
37002 | var isNum = sharedUtil.isNum; | ||
37003 | var isString = sharedUtil.isString; | ||
37004 | var getLookupTableFactory = sharedUtil.getLookupTableFactory; | ||
37005 | var warn = sharedUtil.warn; | ||
37006 | var Dict = corePrimitives.Dict; | ||
37007 | var Name = corePrimitives.Name; | ||
37008 | var isCmd = corePrimitives.isCmd; | ||
37009 | var isDict = corePrimitives.isDict; | ||
37010 | var isName = corePrimitives.isName; | ||
37011 | var isRef = corePrimitives.isRef; | ||
37012 | var isStream = corePrimitives.isStream; | ||
37013 | var DecodeStream = coreStream.DecodeStream; | ||
37014 | var JpegStream = coreStream.JpegStream; | ||
37015 | var Stream = coreStream.Stream; | ||
37016 | var Lexer = coreParser.Lexer; | ||
37017 | var Parser = coreParser.Parser; | ||
37018 | var isEOF = coreParser.isEOF; | ||
37019 | var PDFImage = coreImage.PDFImage; | ||
37020 | var ColorSpace = coreColorSpace.ColorSpace; | ||
37021 | var MurmurHash3_64 = coreMurmurHash3.MurmurHash3_64; | ||
37022 | var ErrorFont = coreFonts.ErrorFont; | ||
37023 | var FontFlags = coreFonts.FontFlags; | ||
37024 | var Font = coreFonts.Font; | ||
37025 | var IdentityToUnicodeMap = coreFonts.IdentityToUnicodeMap; | ||
37026 | var ToUnicodeMap = coreFonts.ToUnicodeMap; | ||
37027 | var getFontType = coreFonts.getFontType; | ||
37028 | var isPDFFunction = coreFunction.isPDFFunction; | ||
37029 | var PDFFunction = coreFunction.PDFFunction; | ||
37030 | var Pattern = corePattern.Pattern; | ||
37031 | var getTilingPatternIR = corePattern.getTilingPatternIR; | ||
37032 | var CMapFactory = coreCMap.CMapFactory; | ||
37033 | var IdentityCMap = coreCMap.IdentityCMap; | ||
37034 | var getMetrics = coreMetrics.getMetrics; | ||
37035 | var bidi = coreBidi.bidi; | ||
37036 | var WinAnsiEncoding = coreEncodings.WinAnsiEncoding; | ||
37037 | var StandardEncoding = coreEncodings.StandardEncoding; | ||
37038 | var MacRomanEncoding = coreEncodings.MacRomanEncoding; | ||
37039 | var SymbolSetEncoding = coreEncodings.SymbolSetEncoding; | ||
37040 | var ZapfDingbatsEncoding = coreEncodings.ZapfDingbatsEncoding; | ||
37041 | var getEncoding = coreEncodings.getEncoding; | ||
37042 | var getStdFontMap = coreStandardFonts.getStdFontMap; | ||
37043 | var getSerifFonts = coreStandardFonts.getSerifFonts; | ||
37044 | var getSymbolsFonts = coreStandardFonts.getSymbolsFonts; | ||
37045 | var getNormalizedUnicodes = coreUnicode.getNormalizedUnicodes; | ||
37046 | var reverseIfRtl = coreUnicode.reverseIfRtl; | ||
37047 | var getUnicodeForGlyph = coreUnicode.getUnicodeForGlyph; | ||
37048 | var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode; | ||
37049 | |||
37050 | var 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 | |||
39320 | var 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 | |||
39381 | var 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 | |||
39496 | var 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 | |||
39520 | var 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 | |||
39601 | var 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 | |||
39617 | var 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 | |||
39855 | var 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 | |||
40259 | exports.OperatorList = OperatorList; | ||
40260 | exports.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 | |||
40273 | var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType; | ||
40274 | var AnnotationFieldFlag = sharedUtil.AnnotationFieldFlag; | ||
40275 | var AnnotationFlag = sharedUtil.AnnotationFlag; | ||
40276 | var AnnotationType = sharedUtil.AnnotationType; | ||
40277 | var OPS = sharedUtil.OPS; | ||
40278 | var Util = sharedUtil.Util; | ||
40279 | var isBool = sharedUtil.isBool; | ||
40280 | var isString = sharedUtil.isString; | ||
40281 | var isArray = sharedUtil.isArray; | ||
40282 | var isInt = sharedUtil.isInt; | ||
40283 | var isValidUrl = sharedUtil.isValidUrl; | ||
40284 | var stringToBytes = sharedUtil.stringToBytes; | ||
40285 | var stringToPDFString = sharedUtil.stringToPDFString; | ||
40286 | var stringToUTF8String = sharedUtil.stringToUTF8String; | ||
40287 | var warn = sharedUtil.warn; | ||
40288 | var Dict = corePrimitives.Dict; | ||
40289 | var isDict = corePrimitives.isDict; | ||
40290 | var isName = corePrimitives.isName; | ||
40291 | var isRef = corePrimitives.isRef; | ||
40292 | var Stream = coreStream.Stream; | ||
40293 | var ColorSpace = coreColorSpace.ColorSpace; | ||
40294 | var ObjectLoader = coreObj.ObjectLoader; | ||
40295 | var FileSpec = coreObj.FileSpec; | ||
40296 | var OperatorList = coreEvaluator.OperatorList; | ||
40297 | |||
40298 | /** | ||
40299 | * @class | ||
40300 | * @alias AnnotationFactory | ||
40301 | */ | ||
40302 | function AnnotationFactory() {} | ||
40303 | AnnotationFactory.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 | |||
40382 | var 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 | */ | ||
40719 | var 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 | |||
40852 | var 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 | |||
40930 | var 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 | |||
40993 | var 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 | |||
41017 | var 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 | |||
41125 | var 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 | |||
41166 | var 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 | |||
41182 | var 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 | |||
41198 | var 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 | |||
41214 | var 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 | |||
41230 | var 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 | |||
41246 | exports.Annotation = Annotation; | ||
41247 | exports.AnnotationBorderStyle = AnnotationBorderStyle; | ||
41248 | exports.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 | |||
41262 | var MissingDataException = sharedUtil.MissingDataException; | ||
41263 | var Util = sharedUtil.Util; | ||
41264 | var assert = sharedUtil.assert; | ||
41265 | var error = sharedUtil.error; | ||
41266 | var info = sharedUtil.info; | ||
41267 | var isArray = sharedUtil.isArray; | ||
41268 | var isArrayBuffer = sharedUtil.isArrayBuffer; | ||
41269 | var isString = sharedUtil.isString; | ||
41270 | var shadow = sharedUtil.shadow; | ||
41271 | var stringToBytes = sharedUtil.stringToBytes; | ||
41272 | var stringToPDFString = sharedUtil.stringToPDFString; | ||
41273 | var warn = sharedUtil.warn; | ||
41274 | var isSpace = sharedUtil.isSpace; | ||
41275 | var Dict = corePrimitives.Dict; | ||
41276 | var isDict = corePrimitives.isDict; | ||
41277 | var isName = corePrimitives.isName; | ||
41278 | var isStream = corePrimitives.isStream; | ||
41279 | var NullStream = coreStream.NullStream; | ||
41280 | var Stream = coreStream.Stream; | ||
41281 | var StreamsSequenceStream = coreStream.StreamsSequenceStream; | ||
41282 | var Catalog = coreObj.Catalog; | ||
41283 | var ObjectLoader = coreObj.ObjectLoader; | ||
41284 | var XRef = coreObj.XRef; | ||
41285 | var Linearization = coreParser.Linearization; | ||
41286 | var calculateMD5 = coreCrypto.calculateMD5; | ||
41287 | var OperatorList = coreEvaluator.OperatorList; | ||
41288 | var PartialEvaluator = coreEvaluator.PartialEvaluator; | ||
41289 | var Annotation = coreAnnotation.Annotation; | ||
41290 | var AnnotationFactory = coreAnnotation.AnnotationFactory; | ||
41291 | |||
41292 | var 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 | */ | ||
41576 | var 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 | |||
41840 | exports.Page = Page; | ||
41841 | exports.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 | |||
41854 | var NotImplementedException = sharedUtil.NotImplementedException; | ||
41855 | var MissingDataException = sharedUtil.MissingDataException; | ||
41856 | var createPromiseCapability = sharedUtil.createPromiseCapability; | ||
41857 | var Util = sharedUtil.Util; | ||
41858 | var Stream = coreStream.Stream; | ||
41859 | var ChunkedStreamManager = coreChunkedStream.ChunkedStreamManager; | ||
41860 | var PDFDocument = coreDocument.PDFDocument; | ||
41861 | |||
41862 | var 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 | |||
41932 | var 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 | |||
41980 | var 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 | |||
42052 | exports.LocalPdfManager = LocalPdfManager; | ||
42053 | exports.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 | |||
42064 | var UNSUPPORTED_FEATURES = sharedUtil.UNSUPPORTED_FEATURES; | ||
42065 | var InvalidPDFException = sharedUtil.InvalidPDFException; | ||
42066 | var MessageHandler = sharedUtil.MessageHandler; | ||
42067 | var MissingPDFException = sharedUtil.MissingPDFException; | ||
42068 | var UnexpectedResponseException = sharedUtil.UnexpectedResponseException; | ||
42069 | var PasswordException = sharedUtil.PasswordException; | ||
42070 | var PasswordResponses = sharedUtil.PasswordResponses; | ||
42071 | var UnknownErrorException = sharedUtil.UnknownErrorException; | ||
42072 | var XRefParseException = sharedUtil.XRefParseException; | ||
42073 | var arrayByteLength = sharedUtil.arrayByteLength; | ||
42074 | var arraysToBytes = sharedUtil.arraysToBytes; | ||
42075 | var assert = sharedUtil.assert; | ||
42076 | var createPromiseCapability = sharedUtil.createPromiseCapability; | ||
42077 | var error = sharedUtil.error; | ||
42078 | var info = sharedUtil.info; | ||
42079 | var warn = sharedUtil.warn; | ||
42080 | var setVerbosityLevel = sharedUtil.setVerbosityLevel; | ||
42081 | var Ref = corePrimitives.Ref; | ||
42082 | var LocalPdfManager = corePdfManager.LocalPdfManager; | ||
42083 | var NetworkPdfManager = corePdfManager.NetworkPdfManager; | ||
42084 | var globalScope = sharedUtil.globalScope; | ||
42085 | |||
42086 | var 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} */ | ||
42118 | var 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 */ | ||
42321 | var PDFNetworkStream; | ||
42322 | |||
42323 | /** | ||
42324 | * Sets PDFNetworkStream class to be used as alternative PDF data transport. | ||
42325 | * @param {IPDFStream} cls - the PDF data transport. | ||
42326 | */ | ||
42327 | function setPDFNetworkStreamClass(cls) { | ||
42328 | PDFNetworkStream = cls; | ||
42329 | } | ||
42330 | |||
42331 | var 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 | |||
42856 | function 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)? | ||
42902 | if (typeof window === 'undefined' && | ||
42903 | !(typeof module !== 'undefined' && module.require)) { | ||
42904 | initializeWorker(); | ||
42905 | } | ||
42906 | |||
42907 | exports.setPDFNetworkStreamClass = setPDFNetworkStreamClass; | ||
42908 | exports.WorkerTask = WorkerTask; | ||
42909 | exports.WorkerMessageHandler = WorkerMessageHandler; | ||
42910 | })); | ||
42911 | |||
42912 | |||
42913 | |||
42914 | |||
42915 | var 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 | |||