| 1 |
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| 2 |
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ |
| 3 |
/* Copyright 2012 Mozilla Foundation |
| 4 |
* |
| 5 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 |
* you may not use this file except in compliance with the License. |
| 7 |
* You may obtain a copy of the License at |
| 8 |
* |
| 9 |
* http://www.apache.org/licenses/LICENSE-2.0 |
| 10 |
* |
| 11 |
* Unless required by applicable law or agreed to in writing, software |
| 12 |
* distributed under the License is distributed on an "AS IS" BASIS, |
| 13 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 |
* See the License for the specific language governing permissions and |
| 15 |
* limitations under the License. |
| 16 |
*/ |
| 17 |
/*jshint globalstrict: false */ |
| 18 |
/* globals PDFJS */ |
| 19 |
|
| 20 |
// Initializing PDFJS global object (if still undefined) |
| 21 |
if (typeof PDFJS === 'undefined') { |
| 22 |
(typeof window !== 'undefined' ? window : this).PDFJS = {}; |
| 23 |
} |
| 24 |
|
| 25 |
PDFJS.version = '1.1.114'; |
| 26 |
PDFJS.build = '3fd44fd'; |
| 27 |
|
| 28 |
(function pdfjsWrapper() { |
| 29 |
// Use strict in our context only - users might not want it |
| 30 |
'use strict'; |
| 31 |
|
| 32 |
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| 33 |
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ |
| 34 |
/* Copyright 2012 Mozilla Foundation |
| 35 |
* |
| 36 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
| 37 |
* you may not use this file except in compliance with the License. |
| 38 |
* You may obtain a copy of the License at |
| 39 |
* |
| 40 |
* http://www.apache.org/licenses/LICENSE-2.0 |
| 41 |
* |
| 42 |
* Unless required by applicable law or agreed to in writing, software |
| 43 |
* distributed under the License is distributed on an "AS IS" BASIS, |
| 44 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 45 |
* See the License for the specific language governing permissions and |
| 46 |
* limitations under the License. |
| 47 |
*/ |
| 48 |
/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL, |
| 49 |
Promise */ |
| 50 |
|
| 51 |
'use strict'; |
| 52 |
|
| 53 |
var globalScope = (typeof window === 'undefined') ? this : window; |
| 54 |
|
| 55 |
var isWorker = (typeof window === 'undefined'); |
| 56 |
|
| 57 |
var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; |
| 58 |
|
| 59 |
var TextRenderingMode = { |
| 60 |
FILL: 0, |
| 61 |
STROKE: 1, |
| 62 |
FILL_STROKE: 2, |
| 63 |
INVISIBLE: 3, |
| 64 |
FILL_ADD_TO_PATH: 4, |
| 65 |
STROKE_ADD_TO_PATH: 5, |
| 66 |
FILL_STROKE_ADD_TO_PATH: 6, |
| 67 |
ADD_TO_PATH: 7, |
| 68 |
FILL_STROKE_MASK: 3, |
| 69 |
ADD_TO_PATH_FLAG: 4 |
| 70 |
}; |
| 71 |
|
| 72 |
var ImageKind = { |
| 73 |
GRAYSCALE_1BPP: 1, |
| 74 |
RGB_24BPP: 2, |
| 75 |
RGBA_32BPP: 3 |
| 76 |
}; |
| 77 |
|
| 78 |
var AnnotationType = { |
| 79 |
WIDGET: 1, |
| 80 |
TEXT: 2, |
| 81 |
LINK: 3 |
| 82 |
}; |
| 83 |
|
| 84 |
var StreamType = { |
| 85 |
UNKNOWN: 0, |
| 86 |
FLATE: 1, |
| 87 |
LZW: 2, |
| 88 |
DCT: 3, |
| 89 |
JPX: 4, |
| 90 |
JBIG: 5, |
| 91 |
A85: 6, |
| 92 |
AHX: 7, |
| 93 |
CCF: 8, |
| 94 |
RL: 9 |
| 95 |
}; |
| 96 |
|
| 97 |
var FontType = { |
| 98 |
UNKNOWN: 0, |
| 99 |
TYPE1: 1, |
| 100 |
TYPE1C: 2, |
| 101 |
CIDFONTTYPE0: 3, |
| 102 |
CIDFONTTYPE0C: 4, |
| 103 |
TRUETYPE: 5, |
| 104 |
CIDFONTTYPE2: 6, |
| 105 |
TYPE3: 7, |
| 106 |
OPENTYPE: 8, |
| 107 |
TYPE0: 9, |
| 108 |
MMTYPE1: 10 |
| 109 |
}; |
| 110 |
|
| 111 |
// The global PDFJS object exposes the API |
| 112 |
// In production, it will be declared outside a global wrapper |
| 113 |
// In development, it will be declared here |
| 114 |
if (!globalScope.PDFJS) { |
| 115 |
globalScope.PDFJS = {}; |
| 116 |
} |
| 117 |
|
| 118 |
globalScope.PDFJS.pdfBug = false; |
| 119 |
|
| 120 |
PDFJS.VERBOSITY_LEVELS = { |
| 121 |
errors: 0, |
| 122 |
warnings: 1, |
| 123 |
infos: 5 |
| 124 |
}; |
| 125 |
|
| 126 |
// All the possible operations for an operator list. |
| 127 |
var OPS = PDFJS.OPS = { |
| 128 |
// Intentionally start from 1 so it is easy to spot bad operators that will be |
| 129 |
// 0's. |
| 130 |
dependency: 1, |
| 131 |
setLineWidth: 2, |
| 132 |
setLineCap: 3, |
| 133 |
setLineJoin: 4, |
| 134 |
setMiterLimit: 5, |
| 135 |
setDash: 6, |
| 136 |
setRenderingIntent: 7, |
| 137 |
setFlatness: 8, |
| 138 |
setGState: 9, |
| 139 |
save: 10, |
| 140 |
restore: 11, |
| 141 |
transform: 12, |
| 142 |
moveTo: 13, |
| 143 |
lineTo: 14, |
| 144 |
curveTo: 15, |
| 145 |
curveTo2: 16, |
| 146 |
curveTo3: 17, |
| 147 |
closePath: 18, |
| 148 |
rectangle: 19, |
| 149 |
stroke: 20, |
| 150 |
closeStroke: 21, |
| 151 |
fill: 22, |
| 152 |
eoFill: 23, |
| 153 |
fillStroke: 24, |
| 154 |
eoFillStroke: 25, |
| 155 |
closeFillStroke: 26, |
| 156 |
closeEOFillStroke: 27, |
| 157 |
endPath: 28, |
| 158 |
clip: 29, |
| 159 |
eoClip: 30, |
| 160 |
beginText: 31, |
| 161 |
endText: 32, |
| 162 |
setCharSpacing: 33, |
| 163 |
setWordSpacing: 34, |
| 164 |
setHScale: 35, |
| 165 |
setLeading: 36, |
| 166 |
setFont: 37, |
| 167 |
setTextRenderingMode: 38, |
| 168 |
setTextRise: 39, |
| 169 |
moveText: 40, |
| 170 |
setLeadingMoveText: 41, |
| 171 |
setTextMatrix: 42, |
| 172 |
nextLine: 43, |
| 173 |
showText: 44, |
| 174 |
showSpacedText: 45, |
| 175 |
nextLineShowText: 46, |
| 176 |
nextLineSetSpacingShowText: 47, |
| 177 |
setCharWidth: 48, |
| 178 |
setCharWidthAndBounds: 49, |
| 179 |
setStrokeColorSpace: 50, |
| 180 |
setFillColorSpace: 51, |
| 181 |
setStrokeColor: 52, |
| 182 |
setStrokeColorN: 53, |
| 183 |
setFillColor: 54, |
| 184 |
setFillColorN: 55, |
| 185 |
setStrokeGray: 56, |
| 186 |
setFillGray: 57, |
| 187 |
setStrokeRGBColor: 58, |
| 188 |
setFillRGBColor: 59, |
| 189 |
setStrokeCMYKColor: 60, |
| 190 |
setFillCMYKColor: 61, |
| 191 |
shadingFill: 62, |
| 192 |
beginInlineImage: 63, |
| 193 |
beginImageData: 64, |
| 194 |
endInlineImage: 65, |
| 195 |
paintXObject: 66, |
| 196 |
markPoint: 67, |
| 197 |
markPointProps: 68, |
| 198 |
beginMarkedContent: 69, |
| 199 |
beginMarkedContentProps: 70, |
| 200 |
endMarkedContent: 71, |
| 201 |
beginCompat: 72, |
| 202 |
endCompat: 73, |
| 203 |
paintFormXObjectBegin: 74, |
| 204 |
paintFormXObjectEnd: 75, |
| 205 |
beginGroup: 76, |
| 206 |
endGroup: 77, |
| 207 |
beginAnnotations: 78, |
| 208 |
endAnnotations: 79, |
| 209 |
beginAnnotation: 80, |
| 210 |
endAnnotation: 81, |
| 211 |
paintJpegXObject: 82, |
| 212 |
paintImageMaskXObject: 83, |
| 213 |
paintImageMaskXObjectGroup: 84, |
| 214 |
paintImageXObject: 85, |
| 215 |
paintInlineImageXObject: 86, |
| 216 |
paintInlineImageXObjectGroup: 87, |
| 217 |
paintImageXObjectRepeat: 88, |
| 218 |
paintImageMaskXObjectRepeat: 89, |
| 219 |
paintSolidColorImageMask: 90, |
| 220 |
constructPath: 91 |
| 221 |
}; |
| 222 |
|
| 223 |
// A notice for devs. These are good for things that are helpful to devs, such |
| 224 |
// as warning that Workers were disabled, which is important to devs but not |
| 225 |
// end users. |
| 226 |
function info(msg) { |
| 227 |
if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) { |
| 228 |
console.log('Info: ' + msg); |
| 229 |
} |
| 230 |
} |
| 231 |
|
| 232 |
// Non-fatal warnings. |
| 233 |
function warn(msg) { |
| 234 |
if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) { |
| 235 |
console.log('Warning: ' + msg); |
| 236 |
} |
| 237 |
} |
| 238 |
|
| 239 |
// Fatal errors that should trigger the fallback UI and halt execution by |
| 240 |
// throwing an exception. |
| 241 |
function error(msg) { |
| 242 |
if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.errors) { |
| 243 |
console.log('Error: ' + msg); |
| 244 |
console.log(backtrace()); |
| 245 |
} |
| 246 |
UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown); |
| 247 |
throw new Error(msg); |
| 248 |
} |
| 249 |
|
| 250 |
function backtrace() { |
| 251 |
try { |
| 252 |
throw new Error(); |
| 253 |
} catch (e) { |
| 254 |
return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; |
| 255 |
} |
| 256 |
} |
| 257 |
|
| 258 |
function assert(cond, msg) { |
| 259 |
if (!cond) { |
| 260 |
error(msg); |
| 261 |
} |
| 262 |
} |
| 263 |
|
| 264 |
var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = { |
| 265 |
unknown: 'unknown', |
| 266 |
forms: 'forms', |
| 267 |
javaScript: 'javaScript', |
| 268 |
smask: 'smask', |
| 269 |
shadingPattern: 'shadingPattern', |
| 270 |
font: 'font' |
| 271 |
}; |
| 272 |
|
| 273 |
var UnsupportedManager = PDFJS.UnsupportedManager = |
| 274 |
(function UnsupportedManagerClosure() { |
| 275 |
var listeners = []; |
| 276 |
return { |
| 277 |
listen: function (cb) { |
| 278 |
listeners.push(cb); |
| 279 |
}, |
| 280 |
notify: function (featureId) { |
| 281 |
warn('Unsupported feature "' + featureId + '"'); |
| 282 |
for (var i = 0, ii = listeners.length; i < ii; i++) { |
| 283 |
listeners[i](featureId); |
| 284 |
} |
| 285 |
} |
| 286 |
}; |
| 287 |
})(); |
| 288 |
|
| 289 |
// Combines two URLs. The baseUrl shall be absolute URL. If the url is an |
| 290 |
// absolute URL, it will be returned as is. |
| 291 |
function combineUrl(baseUrl, url) { |
| 292 |
if (!url) { |
| 293 |
return baseUrl; |
| 294 |
} |
| 295 |
if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) { |
| 296 |
return url; |
| 297 |
} |
| 298 |
var i; |
| 299 |
if (url.charAt(0) === '/') { |
| 300 |
// absolute path |
| 301 |
i = baseUrl.indexOf('://'); |
| 302 |
if (url.charAt(1) === '/') { |
| 303 |
++i; |
| 304 |
} else { |
| 305 |
i = baseUrl.indexOf('/', i + 3); |
| 306 |
} |
| 307 |
return baseUrl.substring(0, i) + url; |
| 308 |
} else { |
| 309 |
// relative path |
| 310 |
var pathLength = baseUrl.length; |
| 311 |
i = baseUrl.lastIndexOf('#'); |
| 312 |
pathLength = i >= 0 ? i : pathLength; |
| 313 |
i = baseUrl.lastIndexOf('?', pathLength); |
| 314 |
pathLength = i >= 0 ? i : pathLength; |
| 315 |
var prefixLength = baseUrl.lastIndexOf('/', pathLength); |
| 316 |
return baseUrl.substring(0, prefixLength + 1) + url; |
| 317 |
} |
| 318 |
} |
| 319 |
|
| 320 |
// Validates if URL is safe and allowed, e.g. to avoid XSS. |
| 321 |
function isValidUrl(url, allowRelative) { |
| 322 |
if (!url) { |
| 323 |
return false; |
| 324 |
} |
| 325 |
// RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1) |
| 326 |
// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) |
| 327 |
var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url); |
| 328 |
if (!protocol) { |
| 329 |
return allowRelative; |
| 330 |
} |
| 331 |
protocol = protocol[0].toLowerCase(); |
| 332 |
switch (protocol) { |
| 333 |
case 'http': |
| 334 |
case 'https': |
| 335 |
case 'ftp': |
| 336 |
case 'mailto': |
| 337 |
case 'tel': |
| 338 |
return true; |
| 339 |
default: |
| 340 |
return false; |
| 341 |
} |
| 342 |
} |
| 343 |
PDFJS.isValidUrl = isValidUrl; |
| 344 |
|
| 345 |
function shadow(obj, prop, value) { |
| 346 |
Object.defineProperty(obj, prop, { value: value, |
| 347 |
enumerable: true, |
| 348 |
configurable: true, |
| 349 |
writable: false }); |
| 350 |
return value; |
| 351 |
} |
| 352 |
PDFJS.shadow = shadow; |
| 353 |
|
| 354 |
var PasswordResponses = PDFJS.PasswordResponses = { |
| 355 |
NEED_PASSWORD: 1, |
| 356 |
INCORRECT_PASSWORD: 2 |
| 357 |
}; |
| 358 |
|
| 359 |
var PasswordException = (function PasswordExceptionClosure() { |
| 360 |
function PasswordException(msg, code) { |
| 361 |
this.name = 'PasswordException'; |
| 362 |
this.message = msg; |
| 363 |
this.code = code; |
| 364 |
} |
| 365 |
|
| 366 |
PasswordException.prototype = new Error(); |
| 367 |
PasswordException.constructor = PasswordException; |
| 368 |
|
| 369 |
return PasswordException; |
| 370 |
})(); |
| 371 |
PDFJS.PasswordException = PasswordException; |
| 372 |
|
| 373 |
var UnknownErrorException = (function UnknownErrorExceptionClosure() { |
| 374 |
function UnknownErrorException(msg, details) { |
| 375 |
this.name = 'UnknownErrorException'; |
| 376 |
this.message = msg; |
| 377 |
this.details = details; |
| 378 |
} |
| 379 |
|
| 380 |
UnknownErrorException.prototype = new Error(); |
| 381 |
UnknownErrorException.constructor = UnknownErrorException; |
| 382 |
|
| 383 |
return UnknownErrorException; |
| 384 |
})(); |
| 385 |
PDFJS.UnknownErrorException = UnknownErrorException; |
| 386 |
|
| 387 |
var InvalidPDFException = (function InvalidPDFExceptionClosure() { |
| 388 |
function InvalidPDFException(msg) { |
| 389 |
this.name = 'InvalidPDFException'; |
| 390 |
this.message = msg; |
| 391 |
} |
| 392 |
|
| 393 |
InvalidPDFException.prototype = new Error(); |
| 394 |
InvalidPDFException.constructor = InvalidPDFException; |
| 395 |
|
| 396 |
return InvalidPDFException; |
| 397 |
})(); |
| 398 |
PDFJS.InvalidPDFException = InvalidPDFException; |
| 399 |
|
| 400 |
var MissingPDFException = (function MissingPDFExceptionClosure() { |
| 401 |
function MissingPDFException(msg) { |
| 402 |
this.name = 'MissingPDFException'; |
| 403 |
this.message = msg; |
| 404 |
} |
| 405 |
|
| 406 |
MissingPDFException.prototype = new Error(); |
| 407 |
MissingPDFException.constructor = MissingPDFException; |
| 408 |
|
| 409 |
return MissingPDFException; |
| 410 |
})(); |
| 411 |
PDFJS.MissingPDFException = MissingPDFException; |
| 412 |
|
| 413 |
var UnexpectedResponseException = |
| 414 |
(function UnexpectedResponseExceptionClosure() { |
| 415 |
function UnexpectedResponseException(msg, status) { |
| 416 |
this.name = 'UnexpectedResponseException'; |
| 417 |
this.message = msg; |
| 418 |
this.status = status; |
| 419 |
} |
| 420 |
|
| 421 |
UnexpectedResponseException.prototype = new Error(); |
| 422 |
UnexpectedResponseException.constructor = UnexpectedResponseException; |
| 423 |
|
| 424 |
return UnexpectedResponseException; |
| 425 |
})(); |
| 426 |
PDFJS.UnexpectedResponseException = UnexpectedResponseException; |
| 427 |
|
| 428 |
var NotImplementedException = (function NotImplementedExceptionClosure() { |
| 429 |
function NotImplementedException(msg) { |
| 430 |
this.message = msg; |
| 431 |
} |
| 432 |
|
| 433 |
NotImplementedException.prototype = new Error(); |
| 434 |
NotImplementedException.prototype.name = 'NotImplementedException'; |
| 435 |
NotImplementedException.constructor = NotImplementedException; |
| 436 |
|
| 437 |
return NotImplementedException; |
| 438 |
})(); |
| 439 |
|
| 440 |
var MissingDataException = (function MissingDataExceptionClosure() { |
| 441 |
function MissingDataException(begin, end) { |
| 442 |
this.begin = begin; |
| 443 |
this.end = end; |
| 444 |
this.message = 'Missing data [' + begin + ', ' + end + ')'; |
| 445 |
} |
| 446 |
|
| 447 |
MissingDataException.prototype = new Error(); |
| 448 |
MissingDataException.prototype.name = 'MissingDataException'; |
| 449 |
MissingDataException.constructor = MissingDataException; |
| 450 |
|
| 451 |
return MissingDataException; |
| 452 |
})(); |
| 453 |
|
| 454 |
var XRefParseException = (function XRefParseExceptionClosure() { |
| 455 |
function XRefParseException(msg) { |
| 456 |
this.message = msg; |
| 457 |
} |
| 458 |
|
| 459 |
XRefParseException.prototype = new Error(); |
| 460 |
XRefParseException.prototype.name = 'XRefParseException'; |
| 461 |
XRefParseException.constructor = XRefParseException; |
| 462 |
|
| 463 |
return XRefParseException; |
| 464 |
})(); |
| 465 |
|
| 466 |
|
| 467 |
function bytesToString(bytes) { |
| 468 |
assert(bytes !== null && typeof bytes === 'object' && |
| 469 |
bytes.length !== undefined, 'Invalid argument for bytesToString'); |
| 470 |
var length = bytes.length; |
| 471 |
var MAX_ARGUMENT_COUNT = 8192; |
| 472 |
if (length < MAX_ARGUMENT_COUNT) { |
| 473 |
return String.fromCharCode.apply(null, bytes); |
| 474 |
} |
| 475 |
var strBuf = []; |
| 476 |
for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) { |
| 477 |
var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); |
| 478 |
var chunk = bytes.subarray(i, chunkEnd); |
| 479 |
strBuf.push(String.fromCharCode.apply(null, chunk)); |
| 480 |
} |
| 481 |
return strBuf.join(''); |
| 482 |
} |
| 483 |
|
| 484 |
function stringToBytes(str) { |
| 485 |
assert(typeof str === 'string', 'Invalid argument for stringToBytes'); |
| 486 |
var length = str.length; |
| 487 |
var bytes = new Uint8Array(length); |
| 488 |
for (var i = 0; i < length; ++i) { |
| 489 |
bytes[i] = str.charCodeAt(i) & 0xFF; |
| 490 |
} |
| 491 |
return bytes; |
| 492 |
} |
| 493 |
|
| 494 |
function string32(value) { |
| 495 |
return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff, |
| 496 |
(value >> 8) & 0xff, value & 0xff); |
| 497 |
} |
| 498 |
|
| 499 |
function log2(x) { |
| 500 |
var n = 1, i = 0; |
| 501 |
while (x > n) { |
| 502 |
n <<= 1; |
| 503 |
i++; |
| 504 |
} |
| 505 |
return i; |
| 506 |
} |
| 507 |
|
| 508 |
function readInt8(data, start) { |
| 509 |
return (data[start] << 24) >> 24; |
| 510 |
} |
| 511 |
|
| 512 |
function readUint16(data, offset) { |
| 513 |
return (data[offset] << 8) | data[offset + 1]; |
| 514 |
} |
| 515 |
|
| 516 |
function readUint32(data, offset) { |
| 517 |
return ((data[offset] << 24) | (data[offset + 1] << 16) | |
| 518 |
(data[offset + 2] << 8) | data[offset + 3]) >>> 0; |
| 519 |
} |
| 520 |
|
| 521 |
// Lazy test the endianness of the platform |
| 522 |
// NOTE: This will be 'true' for simulated TypedArrays |
| 523 |
function isLittleEndian() { |
| 524 |
var buffer8 = new Uint8Array(2); |
| 525 |
buffer8[0] = 1; |
| 526 |
var buffer16 = new Uint16Array(buffer8.buffer); |
| 527 |
return (buffer16[0] === 1); |
| 528 |
} |
| 529 |
|
| 530 |
Object.defineProperty(PDFJS, 'isLittleEndian', { |
| 531 |
configurable: true, |
| 532 |
get: function PDFJS_isLittleEndian() { |
| 533 |
return shadow(PDFJS, 'isLittleEndian', isLittleEndian()); |
| 534 |
} |
| 535 |
}); |
| 536 |
|
| 537 |
//#if !(FIREFOX || MOZCENTRAL || B2G || CHROME) |
| 538 |
//// Lazy test if the userAgant support CanvasTypedArrays |
| 539 |
function hasCanvasTypedArrays() { |
| 540 |
var canvas = document.createElement('canvas'); |
| 541 |
canvas.width = canvas.height = 1; |
| 542 |
var ctx = canvas.getContext('2d'); |
| 543 |
var imageData = ctx.createImageData(1, 1); |
| 544 |
return (typeof imageData.data.buffer !== 'undefined'); |
| 545 |
} |
| 546 |
|
| 547 |
Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', { |
| 548 |
configurable: true, |
| 549 |
get: function PDFJS_hasCanvasTypedArrays() { |
| 550 |
return shadow(PDFJS, 'hasCanvasTypedArrays', hasCanvasTypedArrays()); |
| 551 |
} |
| 552 |
}); |
| 553 |
|
| 554 |
var Uint32ArrayView = (function Uint32ArrayViewClosure() { |
| 555 |
|
| 556 |
function Uint32ArrayView(buffer, length) { |
| 557 |
this.buffer = buffer; |
| 558 |
this.byteLength = buffer.length; |
| 559 |
this.length = length === undefined ? (this.byteLength >> 2) : length; |
| 560 |
ensureUint32ArrayViewProps(this.length); |
| 561 |
} |
| 562 |
Uint32ArrayView.prototype = Object.create(null); |
| 563 |
|
| 564 |
var uint32ArrayViewSetters = 0; |
| 565 |
function createUint32ArrayProp(index) { |
| 566 |
return { |
| 567 |
get: function () { |
| 568 |
var buffer = this.buffer, offset = index << 2; |
| 569 |
return (buffer[offset] | (buffer[offset + 1] << 8) | |
| 570 |
(buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0; |
| 571 |
}, |
| 572 |
set: function (value) { |
| 573 |
var buffer = this.buffer, offset = index << 2; |
| 574 |
buffer[offset] = value & 255; |
| 575 |
buffer[offset + 1] = (value >> 8) & 255; |
| 576 |
buffer[offset + 2] = (value >> 16) & 255; |
| 577 |
buffer[offset + 3] = (value >>> 24) & 255; |
| 578 |
} |
| 579 |
}; |
| 580 |
} |
| 581 |
|
| 582 |
function ensureUint32ArrayViewProps(length) { |
| 583 |
while (uint32ArrayViewSetters < length) { |
| 584 |
Object.defineProperty(Uint32ArrayView.prototype, |
| 585 |
uint32ArrayViewSetters, |
| 586 |
createUint32ArrayProp(uint32ArrayViewSetters)); |
| 587 |
uint32ArrayViewSetters++; |
| 588 |
} |
| 589 |
} |
| 590 |
|
| 591 |
return Uint32ArrayView; |
| 592 |
})(); |
| 593 |
//#else |
| 594 |
//PDFJS.hasCanvasTypedArrays = true; |
| 595 |
//#endif |
| 596 |
|
| 597 |
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; |
| 598 |
|
| 599 |
var Util = PDFJS.Util = (function UtilClosure() { |
| 600 |
function Util() {} |
| 601 |
|
| 602 |
var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')']; |
| 603 |
|
| 604 |
// makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids |
| 605 |
// creating many intermediate strings. |
| 606 |
Util.makeCssRgb = function Util_makeCssRgb(r, g, b) { |
| 607 |
rgbBuf[1] = r; |
| 608 |
rgbBuf[3] = g; |
| 609 |
rgbBuf[5] = b; |
| 610 |
return rgbBuf.join(''); |
| 611 |
}; |
| 612 |
|
| 613 |
// Concatenates two transformation matrices together and returns the result. |
| 614 |
Util.transform = function Util_transform(m1, m2) { |
| 615 |
return [ |
| 616 |
m1[0] * m2[0] + m1[2] * m2[1], |
| 617 |
m1[1] * m2[0] + m1[3] * m2[1], |
| 618 |
m1[0] * m2[2] + m1[2] * m2[3], |
| 619 |
m1[1] * m2[2] + m1[3] * m2[3], |
| 620 |
m1[0] * m2[4] + m1[2] * m2[5] + m1[4], |
| 621 |
m1[1] * m2[4] + m1[3] * m2[5] + m1[5] |
| 622 |
]; |
| 623 |
}; |
| 624 |
|
| 625 |
// For 2d affine transforms |
| 626 |
Util.applyTransform = function Util_applyTransform(p, m) { |
| 627 |
var xt = p[0] * m[0] + p[1] * m[2] + m[4]; |
| 628 |
var yt = p[0] * m[1] + p[1] * m[3] + m[5]; |
| 629 |
return [xt, yt]; |
| 630 |
}; |
| 631 |
|
| 632 |
Util.applyInverseTransform = function Util_applyInverseTransform(p, m) { |
| 633 |
var d = m[0] * m[3] - m[1] * m[2]; |
| 634 |
var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; |
| 635 |
var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; |
| 636 |
return [xt, yt]; |
| 637 |
}; |
| 638 |
|
| 639 |
// Applies the transform to the rectangle and finds the minimum axially |
| 640 |
// aligned bounding box. |
| 641 |
Util.getAxialAlignedBoundingBox = |
| 642 |
function Util_getAxialAlignedBoundingBox(r, m) { |
| 643 |
|
| 644 |
var p1 = Util.applyTransform(r, m); |
| 645 |
var p2 = Util.applyTransform(r.slice(2, 4), m); |
| 646 |
var p3 = Util.applyTransform([r[0], r[3]], m); |
| 647 |
var p4 = Util.applyTransform([r[2], r[1]], m); |
| 648 |
return [ |
| 649 |
Math.min(p1[0], p2[0], p3[0], p4[0]), |
| 650 |
Math.min(p1[1], p2[1], p3[1], p4[1]), |
| 651 |
Math.max(p1[0], p2[0], p3[0], p4[0]), |
| 652 |
Math.max(p1[1], p2[1], p3[1], p4[1]) |
| 653 |
]; |
| 654 |
}; |
| 655 |
|
| 656 |
Util.inverseTransform = function Util_inverseTransform(m) { |
| 657 |
var d = m[0] * m[3] - m[1] * m[2]; |
| 658 |
return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, |
| 659 |
(m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; |
| 660 |
}; |
| 661 |
|
| 662 |
// Apply a generic 3d matrix M on a 3-vector v: |
| 663 |
// | a b c | | X | |
| 664 |
// | d e f | x | Y | |
| 665 |
// | g h i | | Z | |
| 666 |
// M is assumed to be serialized as [a,b,c,d,e,f,g,h,i], |
| 667 |
// with v as [X,Y,Z] |
| 668 |
Util.apply3dTransform = function Util_apply3dTransform(m, v) { |
| 669 |
return [ |
| 670 |
m[0] * v[0] + m[1] * v[1] + m[2] * v[2], |
| 671 |
m[3] * v[0] + m[4] * v[1] + m[5] * v[2], |
| 672 |
m[6] * v[0] + m[7] * v[1] + m[8] * v[2] |
| 673 |
]; |
| 674 |
}; |
| 675 |
|
| 676 |
// This calculation uses Singular Value Decomposition. |
| 677 |
// The SVD can be represented with formula A = USV. We are interested in the |
| 678 |
// matrix S here because it represents the scale values. |
| 679 |
Util.singularValueDecompose2dScale = |
| 680 |
function Util_singularValueDecompose2dScale(m) { |
| 681 |
|
| 682 |
var transpose = [m[0], m[2], m[1], m[3]]; |
| 683 |
|
| 684 |
// Multiply matrix m with its transpose. |
| 685 |
var a = m[0] * transpose[0] + m[1] * transpose[2]; |
| 686 |
var b = m[0] * transpose[1] + m[1] * transpose[3]; |
| 687 |
var c = m[2] * transpose[0] + m[3] * transpose[2]; |
| 688 |
var d = m[2] * transpose[1] + m[3] * transpose[3]; |
| 689 |
|
| 690 |
// Solve the second degree polynomial to get roots. |
| 691 |
var first = (a + d) / 2; |
| 692 |
var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2; |
| 693 |
var sx = first + second || 1; |
| 694 |
var sy = first - second || 1; |
| 695 |
|
| 696 |
// Scale values are the square roots of the eigenvalues. |
| 697 |
return [Math.sqrt(sx), Math.sqrt(sy)]; |
| 698 |
}; |
| 699 |
|
| 700 |
// Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) |
| 701 |
// For coordinate systems whose origin lies in the bottom-left, this |
| 702 |
// means normalization to (BL,TR) ordering. For systems with origin in the |
| 703 |
// top-left, this means (TL,BR) ordering. |
| 704 |
Util.normalizeRect = function Util_normalizeRect(rect) { |
| 705 |
var r = rect.slice(0); // clone rect |
| 706 |
if (rect[0] > rect[2]) { |
| 707 |
r[0] = rect[2]; |
| 708 |
r[2] = rect[0]; |
| 709 |
} |
| 710 |
if (rect[1] > rect[3]) { |
| 711 |
r[1] = rect[3]; |
| 712 |
r[3] = rect[1]; |
| 713 |
} |
| 714 |
return r; |
| 715 |
}; |
| 716 |
|
| 717 |
// Returns a rectangle [x1, y1, x2, y2] corresponding to the |
| 718 |
// intersection of rect1 and rect2. If no intersection, returns 'false' |
| 719 |
// The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] |
| 720 |
Util.intersect = function Util_intersect(rect1, rect2) { |
| 721 |
function compare(a, b) { |
| 722 |
return a - b; |
| 723 |
} |
| 724 |
|
| 725 |
// Order points along the axes |
| 726 |
var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare), |
| 727 |
orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare), |
| 728 |
result = []; |
| 729 |
|
| 730 |
rect1 = Util.normalizeRect(rect1); |
| 731 |
rect2 = Util.normalizeRect(rect2); |
| 732 |
|
| 733 |
// X: first and second points belong to different rectangles? |
| 734 |
if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) || |
| 735 |
(orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) { |
| 736 |
// Intersection must be between second and third points |
| 737 |
result[0] = orderedX[1]; |
| 738 |
result[2] = orderedX[2]; |
| 739 |
} else { |
| 740 |
return false; |
| 741 |
} |
| 742 |
|
| 743 |
// Y: first and second points belong to different rectangles? |
| 744 |
if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) || |
| 745 |
(orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) { |
| 746 |
// Intersection must be between second and third points |
| 747 |
result[1] = orderedY[1]; |
| 748 |
result[3] = orderedY[2]; |
| 749 |
} else { |
| 750 |
return false; |
| 751 |
} |
| 752 |
|
| 753 |
return result; |
| 754 |
}; |
| 755 |
|
| 756 |
Util.sign = function Util_sign(num) { |
| 757 |
return num < 0 ? -1 : 1; |
| 758 |
}; |
| 759 |
|
| 760 |
Util.appendToArray = function Util_appendToArray(arr1, arr2) { |
| 761 |
Array.prototype.push.apply(arr1, arr2); |
| 762 |
}; |
| 763 |
|
| 764 |
Util.prependToArray = function Util_prependToArray(arr1, arr2) { |
| 765 |
Array.prototype.unshift.apply(arr1, arr2); |
| 766 |
}; |
| 767 |
|
| 768 |
Util.extendObj = function extendObj(obj1, obj2) { |
| 769 |
for (var key in obj2) { |
| 770 |
obj1[key] = obj2[key]; |
| 771 |
} |
| 772 |
}; |
| 773 |
|
| 774 |
Util.getInheritableProperty = function Util_getInheritableProperty(dict, |
| 775 |
name) { |
| 776 |
while (dict && !dict.has(name)) { |
| 777 |
dict = dict.get('Parent'); |
| 778 |
} |
| 779 |
if (!dict) { |
| 780 |
return null; |
| 781 |
} |
| 782 |
return dict.get(name); |
| 783 |
}; |
| 784 |
|
| 785 |
Util.inherit = function Util_inherit(sub, base, prototype) { |
| 786 |
sub.prototype = Object.create(base.prototype); |
| 787 |
sub.prototype.constructor = sub; |
| 788 |
for (var prop in prototype) { |
| 789 |
sub.prototype[prop] = prototype[prop]; |
| 790 |
} |
| 791 |
}; |
| 792 |
|
| 793 |
Util.loadScript = function Util_loadScript(src, callback) { |
| 794 |
var script = document.createElement('script'); |
| 795 |
var loaded = false; |
| 796 |
script.setAttribute('src', src); |
| 797 |
if (callback) { |
| 798 |
script.onload = function() { |
| 799 |
if (!loaded) { |
| 800 |
callback(); |
| 801 |
} |
| 802 |
loaded = true; |
| 803 |
}; |
| 804 |
} |
| 805 |
document.getElementsByTagName('head')[0].appendChild(script); |
| 806 |
}; |
| 807 |
|
| 808 |
return Util; |
| 809 |
})(); |
| 810 |
|
| 811 |
/** |
| 812 |
* PDF page viewport created based on scale, rotation and offset. |
| 813 |
* @class |
| 814 |
* @alias PDFJS.PageViewport |
| 815 |
*/ |
| 816 |
var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() { |
| 817 |
/** |
| 818 |
* @constructor |
| 819 |
* @private |
| 820 |
* @param viewBox {Array} xMin, yMin, xMax and yMax coordinates. |
| 821 |
* @param scale {number} scale of the viewport. |
| 822 |
* @param rotation {number} rotations of the viewport in degrees. |
| 823 |
* @param offsetX {number} offset X |
| 824 |
* @param offsetY {number} offset Y |
| 825 |
* @param dontFlip {boolean} if true, axis Y will not be flipped. |
| 826 |
*/ |
| 827 |
function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) { |
| 828 |
this.viewBox = viewBox; |
| 829 |
this.scale = scale; |
| 830 |
this.rotation = rotation; |
| 831 |
this.offsetX = offsetX; |
| 832 |
this.offsetY = offsetY; |
| 833 |
|
| 834 |
// creating transform to convert pdf coordinate system to the normal |
| 835 |
// canvas like coordinates taking in account scale and rotation |
| 836 |
var centerX = (viewBox[2] + viewBox[0]) / 2; |
| 837 |
var centerY = (viewBox[3] + viewBox[1]) / 2; |
| 838 |
var rotateA, rotateB, rotateC, rotateD; |
| 839 |
rotation = rotation % 360; |
| 840 |
rotation = rotation < 0 ? rotation + 360 : rotation; |
| 841 |
switch (rotation) { |
| 842 |
case 180: |
| 843 |
rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1; |
| 844 |
break; |
| 845 |
case 90: |
| 846 |
rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0; |
| 847 |
break; |
| 848 |
case 270: |
| 849 |
rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0; |
| 850 |
break; |
| 851 |
//case 0: |
| 852 |
default: |
| 853 |
rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1; |
| 854 |
break; |
| 855 |
} |
| 856 |
|
| 857 |
if (dontFlip) { |
| 858 |
rotateC = -rotateC; rotateD = -rotateD; |
| 859 |
} |
| 860 |
|
| 861 |
var offsetCanvasX, offsetCanvasY; |
| 862 |
var width, height; |
| 863 |
if (rotateA === 0) { |
| 864 |
offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; |
| 865 |
offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; |
| 866 |
width = Math.abs(viewBox[3] - viewBox[1]) * scale; |
| 867 |
height = Math.abs(viewBox[2] - viewBox[0]) * scale; |
| 868 |
} else { |
| 869 |
offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; |
| 870 |
offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; |
| 871 |
width = Math.abs(viewBox[2] - viewBox[0]) * scale; |
| 872 |
height = Math.abs(viewBox[3] - viewBox[1]) * scale; |
| 873 |
} |
| 874 |
// creating transform for the following operations: |
| 875 |
// translate(-centerX, -centerY), rotate and flip vertically, |
| 876 |
// scale, and translate(offsetCanvasX, offsetCanvasY) |
| 877 |
this.transform = [ |
| 878 |
rotateA * scale, |
| 879 |
rotateB * scale, |
| 880 |
rotateC * scale, |
| 881 |
rotateD * scale, |
| 882 |
offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, |
| 883 |
offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY |
| 884 |
]; |
| 885 |
|
| 886 |
this.width = width; |
| 887 |
this.height = height; |
| 888 |
this.fontScale = scale; |
| 889 |
} |
| 890 |
PageViewport.prototype = /** @lends PDFJS.PageViewport.prototype */ { |
| 891 |
/** |
| 892 |
* Clones viewport with additional properties. |
| 893 |
* @param args {Object} (optional) If specified, may contain the 'scale' or |
| 894 |
* 'rotation' properties to override the corresponding properties in |
| 895 |
* the cloned viewport. |
| 896 |
* @returns {PDFJS.PageViewport} Cloned viewport. |
| 897 |
*/ |
| 898 |
clone: function PageViewPort_clone(args) { |
| 899 |
args = args || {}; |
| 900 |
var scale = 'scale' in args ? args.scale : this.scale; |
| 901 |
var rotation = 'rotation' in args ? args.rotation : this.rotation; |
| 902 |
return new PageViewport(this.viewBox.slice(), scale, rotation, |
| 903 |
this.offsetX, this.offsetY, args.dontFlip); |
| 904 |
}, |
| 905 |
/** |
| 906 |
* Converts PDF point to the viewport coordinates. For examples, useful for |
| 907 |
* converting PDF location into canvas pixel coordinates. |
| 908 |
* @param x {number} X coordinate. |
| 909 |
* @param y {number} Y coordinate. |
| 910 |
* @returns {Object} Object that contains 'x' and 'y' properties of the |
| 911 |
* point in the viewport coordinate space. |
| 912 |
* @see {@link convertToPdfPoint} |
| 913 |
* @see {@link convertToViewportRectangle} |
| 914 |
*/ |
| 915 |
convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) { |
| 916 |
return Util.applyTransform([x, y], this.transform); |
| 917 |
}, |
| 918 |
/** |
| 919 |
* Converts PDF rectangle to the viewport coordinates. |
| 920 |
* @param rect {Array} xMin, yMin, xMax and yMax coordinates. |
| 921 |
* @returns {Array} Contains corresponding coordinates of the rectangle |
| 922 |
* in the viewport coordinate space. |
| 923 |
* @see {@link convertToViewportPoint} |
| 924 |
*/ |
| 925 |
convertToViewportRectangle: |
| 926 |
function PageViewport_convertToViewportRectangle(rect) { |
| 927 |
var tl = Util.applyTransform([rect[0], rect[1]], this.transform); |
| 928 |
var br = Util.applyTransform([rect[2], rect[3]], this.transform); |
| 929 |
return [tl[0], tl[1], br[0], br[1]]; |
| 930 |
}, |
| 931 |
/** |
| 932 |
* Converts viewport coordinates to the PDF location. For examples, useful |
| 933 |
* for converting canvas pixel location into PDF one. |
| 934 |
* @param x {number} X coordinate. |
| 935 |
* @param y {number} Y coordinate. |
| 936 |
* @returns {Object} Object that contains 'x' and 'y' properties of the |
| 937 |
* point in the PDF coordinate space. |
| 938 |
* @see {@link convertToViewportPoint} |
| 939 |
*/ |
| 940 |
convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) { |
| 941 |
return Util.applyInverseTransform([x, y], this.transform); |
| 942 |
} |
| 943 |
}; |
| 944 |
return PageViewport; |
| 945 |
})(); |
| 946 |
|
| 947 |
var PDFStringTranslateTable = [ |
| 948 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 949 |
0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, |
| 950 |
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, |
| 951 |
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, |
| 952 |
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, |
| 953 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, |
| 954 |
0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, |
| 955 |
0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, |
| 956 |
0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC |
| 957 |
]; |
| 958 |
|
| 959 |
function stringToPDFString(str) { |
| 960 |
var i, n = str.length, strBuf = []; |
| 961 |
if (str[0] === '\xFE' && str[1] === '\xFF') { |
| 962 |
// UTF16BE BOM |
| 963 |
for (i = 2; i < n; i += 2) { |
| 964 |
strBuf.push(String.fromCharCode( |
| 965 |
(str.charCodeAt(i) << 8) | str.charCodeAt(i + 1))); |
| 966 |
} |
| 967 |
} else { |
| 968 |
for (i = 0; i < n; ++i) { |
| 969 |
var code = PDFStringTranslateTable[str.charCodeAt(i)]; |
| 970 |
strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); |
| 971 |
} |
| 972 |
} |
| 973 |
return strBuf.join(''); |
| 974 |
} |
| 975 |
|
| 976 |
function stringToUTF8String(str) { |
| 977 |
return decodeURIComponent(escape(str)); |
| 978 |
} |
| 979 |
|
| 980 |
function isEmptyObj(obj) { |
| 981 |
for (var key in obj) { |
| 982 |
return false; |
| 983 |
} |
| 984 |
return true; |
| 985 |
} |
| 986 |
|
| 987 |
function isBool(v) { |
| 988 |
return typeof v === 'boolean'; |
| 989 |
} |
| 990 |
|
| 991 |
function isInt(v) { |
| 992 |
return typeof v === 'number' && ((v | 0) === v); |
| 993 |
} |
| 994 |
|
| 995 |
function isNum(v) { |
| 996 |
return typeof v === 'number'; |
| 997 |
} |
| 998 |
|
| 999 |
function isString(v) { |
| 1000 |
return typeof v === 'string'; |
| 1001 |
} |
| 1002 |
|
| 1003 |
function isName(v) { |
| 1004 |
return v instanceof Name; |
| 1005 |
} |
| 1006 |
|
| 1007 |
function isCmd(v, cmd) { |
| 1008 |
return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); |
| 1009 |
} |
| 1010 |
|
| 1011 |
function isDict(v, type) { |
| 1012 |
if (!(v instanceof Dict)) { |
| 1013 |
return false; |
| 1014 |
} |
| 1015 |
if (!type) { |
| 1016 |
return true; |
| 1017 |
} |
| 1018 |
var dictType = v.get('Type'); |
| 1019 |
return isName(dictType) && dictType.name === type; |
| 1020 |
} |
| 1021 |
|
| 1022 |
function isArray(v) { |
| 1023 |
return v instanceof Array; |
| 1024 |
} |
| 1025 |
|
| 1026 |
function isStream(v) { |
| 1027 |
return typeof v === 'object' && v !== null && v.getBytes !== undefined; |
| 1028 |
} |
| 1029 |
|
| 1030 |
function isArrayBuffer(v) { |
| 1031 |
return typeof v === 'object' && v !== null && v.byteLength !== undefined; |
| 1032 |
} |
| 1033 |
|
| 1034 |
function isRef(v) { |
| 1035 |
return v instanceof Ref; |
| 1036 |
} |
| 1037 |
|
| 1038 |
/** |
| 1039 |
* Promise Capability object. |
| 1040 |
* |
| 1041 |
* @typedef {Object} PromiseCapability |
| 1042 |
* @property {Promise} promise - A promise object. |
| 1043 |
* @property {function} resolve - Fullfills the promise. |
| 1044 |
* @property {function} reject - Rejects the promise. |
| 1045 |
*/ |
| 1046 |
|
| 1047 |
/** |
| 1048 |
* Creates a promise capability object. |
| 1049 |
* @alias PDFJS.createPromiseCapability |
| 1050 |
* |
| 1051 |
* @return {PromiseCapability} A capability object contains: |
| 1052 |
* - a Promise, resolve and reject methods. |
| 1053 |
*/ |
| 1054 |
function createPromiseCapability() { |
| 1055 |
var capability = {}; |
| 1056 |
capability.promise = new Promise(function (resolve, reject) { |
| 1057 |
capability.resolve = resolve; |
| 1058 |
capability.reject = reject; |
| 1059 |
}); |
| 1060 |
return capability; |
| 1061 |
} |
| 1062 |
|
| 1063 |
PDFJS.createPromiseCapability = createPromiseCapability; |
| 1064 |
|
| 1065 |
/** |
| 1066 |
* Polyfill for Promises: |
| 1067 |
* The following promise implementation tries to generally implement the |
| 1068 |
* Promise/A+ spec. Some notable differences from other promise libaries are: |
| 1069 |
* - There currently isn't a seperate deferred and promise object. |
| 1070 |
* - Unhandled rejections eventually show an error if they aren't handled. |
| 1071 |
* |
| 1072 |
* Based off of the work in: |
| 1073 |
* https://bugzilla.mozilla.org/show_bug.cgi?id=810490 |
| 1074 |
*/ |
| 1075 |
(function PromiseClosure() { |
| 1076 |
if (globalScope.Promise) { |
| 1077 |
// Promises existing in the DOM/Worker, checking presence of all/resolve |
| 1078 |
if (typeof globalScope.Promise.all !== 'function') { |
| 1079 |
globalScope.Promise.all = function (iterable) { |
| 1080 |
var count = 0, results = [], resolve, reject; |
| 1081 |
var promise = new globalScope.Promise(function (resolve_, reject_) { |
| 1082 |
resolve = resolve_; |
| 1083 |
reject = reject_; |
| 1084 |
}); |
| 1085 |
iterable.forEach(function (p, i) { |
| 1086 |
count++; |
| 1087 |
p.then(function (result) { |
| 1088 |
results[i] = result; |
| 1089 |
count--; |
| 1090 |
if (count === 0) { |
| 1091 |
resolve(results); |
| 1092 |
} |
| 1093 |
}, reject); |
| 1094 |
}); |
| 1095 |
if (count === 0) { |
| 1096 |
resolve(results); |
| 1097 |
} |
| 1098 |
return promise; |
| 1099 |
}; |
| 1100 |
} |
| 1101 |
if (typeof globalScope.Promise.resolve !== 'function') { |
| 1102 |
globalScope.Promise.resolve = function (value) { |
| 1103 |
return new globalScope.Promise(function (resolve) { resolve(value); }); |
| 1104 |
}; |
| 1105 |
} |
| 1106 |
if (typeof globalScope.Promise.reject !== 'function') { |
| 1107 |
globalScope.Promise.reject = function (reason) { |
| 1108 |
return new globalScope.Promise(function (resolve, reject) { |
| 1109 |
reject(reason); |
| 1110 |
}); |
| 1111 |
}; |
| 1112 |
} |
| 1113 |
if (typeof globalScope.Promise.prototype.catch !== 'function') { |
| 1114 |
globalScope.Promise.prototype.catch = function (onReject) { |
| 1115 |
return globalScope.Promise.prototype.then(undefined, onReject); |
| 1116 |
}; |
| 1117 |
} |
| 1118 |
return; |
| 1119 |
} |
| 1120 |
//#if !MOZCENTRAL |
| 1121 |
var STATUS_PENDING = 0; |
| 1122 |
var STATUS_RESOLVED = 1; |
| 1123 |
var STATUS_REJECTED = 2; |
| 1124 |
|
| 1125 |
// In an attempt to avoid silent exceptions, unhandled rejections are |
| 1126 |
// tracked and if they aren't handled in a certain amount of time an |
| 1127 |
// error is logged. |
| 1128 |
var REJECTION_TIMEOUT = 500; |
| 1129 |
|
| 1130 |
var HandlerManager = { |
| 1131 |
handlers: [], |
| 1132 |
running: false, |
| 1133 |
unhandledRejections: [], |
| 1134 |
pendingRejectionCheck: false, |
| 1135 |
|
| 1136 |
scheduleHandlers: function scheduleHandlers(promise) { |
| 1137 |
if (promise._status === STATUS_PENDING) { |
| 1138 |
return; |
| 1139 |
} |
| 1140 |
|
| 1141 |
this.handlers = this.handlers.concat(promise._handlers); |
| 1142 |
promise._handlers = []; |
| 1143 |
|
| 1144 |
if (this.running) { |
| 1145 |
return; |
| 1146 |
} |
| 1147 |
this.running = true; |
| 1148 |
|
| 1149 |
setTimeout(this.runHandlers.bind(this), 0); |
| 1150 |
}, |
| 1151 |
|
| 1152 |
runHandlers: function runHandlers() { |
| 1153 |
var RUN_TIMEOUT = 1; // ms |
| 1154 |
var timeoutAt = Date.now() + RUN_TIMEOUT; |
| 1155 |
while (this.handlers.length > 0) { |
| 1156 |
var handler = this.handlers.shift(); |
| 1157 |
|
| 1158 |
var nextStatus = handler.thisPromise._status; |
| 1159 |
var nextValue = handler.thisPromise._value; |
| 1160 |
|
| 1161 |
try { |
| 1162 |
if (nextStatus === STATUS_RESOLVED) { |
| 1163 |
if (typeof handler.onResolve === 'function') { |
| 1164 |
nextValue = handler.onResolve(nextValue); |
| 1165 |
} |
| 1166 |
} else if (typeof handler.onReject === 'function') { |
| 1167 |
nextValue = handler.onReject(nextValue); |
| 1168 |
nextStatus = STATUS_RESOLVED; |
| 1169 |
|
| 1170 |
if (handler.thisPromise._unhandledRejection) { |
| 1171 |
this.removeUnhandeledRejection(handler.thisPromise); |
| 1172 |
} |
| 1173 |
} |
| 1174 |
} catch (ex) { |
| 1175 |
nextStatus = STATUS_REJECTED; |
| 1176 |
nextValue = ex; |
| 1177 |
} |
| 1178 |
|
| 1179 |
handler.nextPromise._updateStatus(nextStatus, nextValue); |
| 1180 |
if (Date.now() >= timeoutAt) { |
| 1181 |
break; |
| 1182 |
} |
| 1183 |
} |
| 1184 |
|
| 1185 |
if (this.handlers.length > 0) { |
| 1186 |
setTimeout(this.runHandlers.bind(this), 0); |
| 1187 |
return; |
| 1188 |
} |
| 1189 |
|
| 1190 |
this.running = false; |
| 1191 |
}, |
| 1192 |
|
| 1193 |
addUnhandledRejection: function addUnhandledRejection(promise) { |
| 1194 |
this.unhandledRejections.push({ |
| 1195 |
promise: promise, |
| 1196 |
time: Date.now() |
| 1197 |
}); |
| 1198 |
this.scheduleRejectionCheck(); |
| 1199 |
}, |
| 1200 |
|
| 1201 |
removeUnhandeledRejection: function removeUnhandeledRejection(promise) { |
| 1202 |
promise._unhandledRejection = false; |
| 1203 |
for (var i = 0; i < this.unhandledRejections.length; i++) { |
| 1204 |
if (this.unhandledRejections[i].promise === promise) { |
| 1205 |
this.unhandledRejections.splice(i); |
| 1206 |
i--; |
| 1207 |
} |
| 1208 |
} |
| 1209 |
}, |
| 1210 |
|
| 1211 |
scheduleRejectionCheck: function scheduleRejectionCheck() { |
| 1212 |
if (this.pendingRejectionCheck) { |
| 1213 |
return; |
| 1214 |
} |
| 1215 |
this.pendingRejectionCheck = true; |
| 1216 |
setTimeout(function rejectionCheck() { |
| 1217 |
this.pendingRejectionCheck = false; |
| 1218 |
var now = Date.now(); |
| 1219 |
for (var i = 0; i < this.unhandledRejections.length; i++) { |
| 1220 |
if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) { |
| 1221 |
var unhandled = this.unhandledRejections[i].promise._value; |
| 1222 |
var msg = 'Unhandled rejection: ' + unhandled; |
| 1223 |
if (unhandled.stack) { |
| 1224 |
msg += '\n' + unhandled.stack; |
| 1225 |
} |
| 1226 |
warn(msg); |
| 1227 |
this.unhandledRejections.splice(i); |
| 1228 |
i--; |
| 1229 |
} |
| 1230 |
} |
| 1231 |
if (this.unhandledRejections.length) { |
| 1232 |
this.scheduleRejectionCheck(); |
| 1233 |
} |
| 1234 |
}.bind(this), REJECTION_TIMEOUT); |
| 1235 |
} |
| 1236 |
}; |
| 1237 |
|
| 1238 |
function Promise(resolver) { |
| 1239 |
this._status = STATUS_PENDING; |
| 1240 |
this._handlers = []; |
| 1241 |
try { |
| 1242 |
resolver.call(this, this._resolve.bind(this), this._reject.bind(this)); |
| 1243 |
} catch (e) { |
| 1244 |
this._reject(e); |
| 1245 |
} |
| 1246 |
} |
| 1247 |
/** |
| 1248 |
* Builds a promise that is resolved when all the passed in promises are |
| 1249 |
* resolved. |
| 1250 |
* @param {array} array of data and/or promises to wait for. |
| 1251 |
* @return {Promise} New dependant promise. |
| 1252 |
*/ |
| 1253 |
Promise.all = function Promise_all(promises) { |
| 1254 |
var resolveAll, rejectAll; |
| 1255 |
var deferred = new Promise(function (resolve, reject) { |
| 1256 |
resolveAll = resolve; |
| 1257 |
rejectAll = reject; |
| 1258 |
}); |
| 1259 |
var unresolved = promises.length; |
| 1260 |
var results = []; |
| 1261 |
if (unresolved === 0) { |
| 1262 |
resolveAll(results); |
| 1263 |
return deferred; |
| 1264 |
} |
| 1265 |
function reject(reason) { |
| 1266 |
if (deferred._status === STATUS_REJECTED) { |
| 1267 |
return; |
| 1268 |
} |
| 1269 |
results = []; |
| 1270 |
rejectAll(reason); |
| 1271 |
} |
| 1272 |
for (var i = 0, ii = promises.length; i < ii; ++i) { |
| 1273 |
var promise = promises[i]; |
| 1274 |
var resolve = (function(i) { |
| 1275 |
return function(value) { |
| 1276 |
if (deferred._status === STATUS_REJECTED) { |
| 1277 |
return; |
| 1278 |
} |
| 1279 |
results[i] = value; |
| 1280 |
unresolved--; |
| 1281 |
if (unresolved === 0) { |
| 1282 |
resolveAll(results); |
| 1283 |
} |
| 1284 |
}; |
| 1285 |
})(i); |
| 1286 |
if (Promise.isPromise(promise)) { |
| 1287 |
promise.then(resolve, reject); |
| 1288 |
} else { |
| 1289 |
resolve(promise); |
| 1290 |
} |
| 1291 |
} |
| 1292 |
return deferred; |
| 1293 |
}; |
| 1294 |
|
| 1295 |
/** |
| 1296 |
* Checks if the value is likely a promise (has a 'then' function). |
| 1297 |
* @return {boolean} true if value is thenable |
| 1298 |
*/ |
| 1299 |
Promise.isPromise = function Promise_isPromise(value) { |
| 1300 |
return value && typeof value.then === 'function'; |
| 1301 |
}; |
| 1302 |
|
| 1303 |
/** |
| 1304 |
* Creates resolved promise |
| 1305 |
* @param value resolve value |
| 1306 |
* @returns {Promise} |
| 1307 |
*/ |
| 1308 |
Promise.resolve = function Promise_resolve(value) { |
| 1309 |
return new Promise(function (resolve) { resolve(value); }); |
| 1310 |
}; |
| 1311 |
|
| 1312 |
/** |
| 1313 |
* Creates rejected promise |
| 1314 |
* @param reason rejection value |
| 1315 |
* @returns {Promise} |
| 1316 |
*/ |
| 1317 |
Promise.reject = function Promise_reject(reason) { |
| 1318 |
return new Promise(function (resolve, reject) { reject(reason); }); |
| 1319 |
}; |
| 1320 |
|
| 1321 |
Promise.prototype = { |
| 1322 |
_status: null, |
| 1323 |
_value: null, |
| 1324 |
_handlers: null, |
| 1325 |
_unhandledRejection: null, |
| 1326 |
|
| 1327 |
_updateStatus: function Promise__updateStatus(status, value) { |
| 1328 |
if (this._status === STATUS_RESOLVED || |
| 1329 |
this._status === STATUS_REJECTED) { |
| 1330 |
return; |
| 1331 |
} |
| 1332 |
|
| 1333 |
if (status === STATUS_RESOLVED && |
| 1334 |
Promise.isPromise(value)) { |
| 1335 |
value.then(this._updateStatus.bind(this, STATUS_RESOLVED), |
| 1336 |
this._updateStatus.bind(this, STATUS_REJECTED)); |
| 1337 |
return; |
| 1338 |
} |
| 1339 |
|
| 1340 |
this._status = status; |
| 1341 |
this._value = value; |
| 1342 |
|
| 1343 |
if (status === STATUS_REJECTED && this._handlers.length === 0) { |
| 1344 |
this._unhandledRejection = true; |
| 1345 |
HandlerManager.addUnhandledRejection(this); |
| 1346 |
} |
| 1347 |
|
| 1348 |
HandlerManager.scheduleHandlers(this); |
| 1349 |
}, |
| 1350 |
|
| 1351 |
_resolve: function Promise_resolve(value) { |
| 1352 |
this._updateStatus(STATUS_RESOLVED, value); |
| 1353 |
}, |
| 1354 |
|
| 1355 |
_reject: function Promise_reject(reason) { |
| 1356 |
this._updateStatus(STATUS_REJECTED, reason); |
| 1357 |
}, |
| 1358 |
|
| 1359 |
then: function Promise_then(onResolve, onReject) { |
| 1360 |
var nextPromise = new Promise(function (resolve, reject) { |
| 1361 |
this.resolve = resolve; |
| 1362 |
this.reject = reject; |
| 1363 |
}); |
| 1364 |
this._handlers.push({ |
| 1365 |
thisPromise: this, |
| 1366 |
onResolve: onResolve, |
| 1367 |
onReject: onReject, |
| 1368 |
nextPromise: nextPromise |
| 1369 |
}); |
| 1370 |
HandlerManager.scheduleHandlers(this); |
| 1371 |
return nextPromise; |
| 1372 |
}, |
| 1373 |
|
| 1374 |
catch: function Promise_catch(onReject) { |
| 1375 |
return this.then(undefined, onReject); |
| 1376 |
} |
| 1377 |
}; |
| 1378 |
|
| 1379 |
globalScope.Promise = Promise; |
| 1380 |
//#else |
| 1381 |
//throw new Error('DOM Promise is not present'); |
| 1382 |
//#endif |
| 1383 |
})(); |
| 1384 |
|
| 1385 |
var StatTimer = (function StatTimerClosure() { |
| 1386 |
function rpad(str, pad, length) { |
| 1387 |
while (str.length < length) { |
| 1388 |
str += pad; |
| 1389 |
} |
| 1390 |
return str; |
| 1391 |
} |
| 1392 |
function StatTimer() { |
| 1393 |
this.started = {}; |
| 1394 |
this.times = []; |
| 1395 |
this.enabled = true; |
| 1396 |
} |
| 1397 |
StatTimer.prototype = { |
| 1398 |
time: function StatTimer_time(name) { |
| 1399 |
if (!this.enabled) { |
| 1400 |
return; |
| 1401 |
} |
| 1402 |
if (name in this.started) { |
| 1403 |
warn('Timer is already running for ' + name); |
| 1404 |
} |
| 1405 |
this.started[name] = Date.now(); |
| 1406 |
}, |
| 1407 |
timeEnd: function StatTimer_timeEnd(name) { |
| 1408 |
if (!this.enabled) { |
| 1409 |
return; |
| 1410 |
} |
| 1411 |
if (!(name in this.started)) { |
| 1412 |
warn('Timer has not been started for ' + name); |
| 1413 |
} |
| 1414 |
this.times.push({ |
| 1415 |
'name': name, |
| 1416 |
'start': this.started[name], |
| 1417 |
'end': Date.now() |
| 1418 |
}); |
| 1419 |
// Remove timer from started so it can be called again. |
| 1420 |
delete this.started[name]; |
| 1421 |
}, |
| 1422 |
toString: function StatTimer_toString() { |
| 1423 |
var i, ii; |
| 1424 |
var times = this.times; |
| 1425 |
var out = ''; |
| 1426 |
// Find the longest name for padding purposes. |
| 1427 |
var longest = 0; |
| 1428 |
for (i = 0, ii = times.length; i < ii; ++i) { |
| 1429 |
var name = times[i]['name']; |
| 1430 |
if (name.length > longest) { |
| 1431 |
longest = name.length; |
| 1432 |
} |
| 1433 |
} |
| 1434 |
for (i = 0, ii = times.length; i < ii; ++i) { |
| 1435 |
var span = times[i]; |
| 1436 |
var duration = span.end - span.start; |
| 1437 |
out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n'; |
| 1438 |
} |
| 1439 |
return out; |
| 1440 |
} |
| 1441 |
}; |
| 1442 |
return StatTimer; |
| 1443 |
})(); |
| 1444 |
|
| 1445 |
PDFJS.createBlob = function createBlob(data, contentType) { |
| 1446 |
if (typeof Blob !== 'undefined') { |
| 1447 |
return new Blob([data], { type: contentType }); |
| 1448 |
} |
| 1449 |
// Blob builder is deprecated in FF14 and removed in FF18. |
| 1450 |
var bb = new MozBlobBuilder(); |
| 1451 |
bb.append(data); |
| 1452 |
return bb.getBlob(contentType); |
| 1453 |
}; |
| 1454 |
|
| 1455 |
PDFJS.createObjectURL = (function createObjectURLClosure() { |
| 1456 |
// Blob/createObjectURL is not available, falling back to data schema. |
| 1457 |
var digits = |
| 1458 |
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; |
| 1459 |
|
| 1460 |
return function createObjectURL(data, contentType) { |
| 1461 |
if (!PDFJS.disableCreateObjectURL && |
| 1462 |
typeof URL !== 'undefined' && URL.createObjectURL) { |
| 1463 |
var blob = PDFJS.createBlob(data, contentType); |
| 1464 |
return URL.createObjectURL(blob); |
| 1465 |
} |
| 1466 |
|
| 1467 |
var buffer = 'data:' + contentType + ';base64,'; |
| 1468 |
for (var i = 0, ii = data.length; i < ii; i += 3) { |
| 1469 |
var b1 = data[i] & 0xFF; |
| 1470 |
var b2 = data[i + 1] & 0xFF; |
| 1471 |
var b3 = data[i + 2] & 0xFF; |
| 1472 |
var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); |
| 1473 |
var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; |
| 1474 |
var d4 = i + 2 < ii ? (b3 & 0x3F) : 64; |
| 1475 |
buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; |
| 1476 |
} |
| 1477 |
return buffer; |
| 1478 |
}; |
| 1479 |
})(); |
| 1480 |
|
| 1481 |
function MessageHandler(name, comObj) { |
| 1482 |
this.name = name; |
| 1483 |
this.comObj = comObj; |
| 1484 |
this.callbackIndex = 1; |
| 1485 |
this.postMessageTransfers = true; |
| 1486 |
var callbacksCapabilities = this.callbacksCapabilities = {}; |
| 1487 |
var ah = this.actionHandler = {}; |
| 1488 |
|
| 1489 |
ah['console_log'] = [function ahConsoleLog(data) { |
| 1490 |
console.log.apply(console, data); |
| 1491 |
}]; |
| 1492 |
ah['console_error'] = [function ahConsoleError(data) { |
| 1493 |
console.error.apply(console, data); |
| 1494 |
}]; |
| 1495 |
ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) { |
| 1496 |
UnsupportedManager.notify(data); |
| 1497 |
}]; |
| 1498 |
|
| 1499 |
comObj.onmessage = function messageHandlerComObjOnMessage(event) { |
| 1500 |
var data = event.data; |
| 1501 |
if (data.isReply) { |
| 1502 |
var callbackId = data.callbackId; |
| 1503 |
if (data.callbackId in callbacksCapabilities) { |
| 1504 |
var callback = callbacksCapabilities[callbackId]; |
| 1505 |
delete callbacksCapabilities[callbackId]; |
| 1506 |
if ('error' in data) { |
| 1507 |
callback.reject(data.error); |
| 1508 |
} else { |
| 1509 |
callback.resolve(data.data); |
| 1510 |
} |
| 1511 |
} else { |
| 1512 |
error('Cannot resolve callback ' + callbackId); |
| 1513 |
} |
| 1514 |
} else if (data.action in ah) { |
| 1515 |
var action = ah[data.action]; |
| 1516 |
if (data.callbackId) { |
| 1517 |
Promise.resolve().then(function () { |
| 1518 |
return action[0].call(action[1], data.data); |
| 1519 |
}).then(function (result) { |
| 1520 |
comObj.postMessage({ |
| 1521 |
isReply: true, |
| 1522 |
callbackId: data.callbackId, |
| 1523 |
data: result |
| 1524 |
}); |
| 1525 |
}, function (reason) { |
| 1526 |
comObj.postMessage({ |
| 1527 |
isReply: true, |
| 1528 |
callbackId: data.callbackId, |
| 1529 |
error: reason |
| 1530 |
}); |
| 1531 |
}); |
| 1532 |
} else { |
| 1533 |
action[0].call(action[1], data.data); |
| 1534 |
} |
| 1535 |
} else { |
| 1536 |
error('Unknown action from worker: ' + data.action); |
| 1537 |
} |
| 1538 |
}; |
| 1539 |
} |
| 1540 |
|
| 1541 |
MessageHandler.prototype = { |
| 1542 |
on: function messageHandlerOn(actionName, handler, scope) { |
| 1543 |
var ah = this.actionHandler; |
| 1544 |
if (ah[actionName]) { |
| 1545 |
error('There is already an actionName called "' + actionName + '"'); |
| 1546 |
} |
| 1547 |
ah[actionName] = [handler, scope]; |
| 1548 |
}, |
| 1549 |
/** |
| 1550 |
* Sends a message to the comObj to invoke the action with the supplied data. |
| 1551 |
* @param {String} actionName Action to call. |
| 1552 |
* @param {JSON} data JSON data to send. |
| 1553 |
* @param {Array} [transfers] Optional list of transfers/ArrayBuffers |
| 1554 |
*/ |
| 1555 |
send: function messageHandlerSend(actionName, data, transfers) { |
| 1556 |
var message = { |
| 1557 |
action: actionName, |
| 1558 |
data: data |
| 1559 |
}; |
| 1560 |
this.postMessage(message, transfers); |
| 1561 |
}, |
| 1562 |
/** |
| 1563 |
* Sends a message to the comObj to invoke the action with the supplied data. |
| 1564 |
* Expects that other side will callback with the response. |
| 1565 |
* @param {String} actionName Action to call. |
| 1566 |
* @param {JSON} data JSON data to send. |
| 1567 |
* @param {Array} [transfers] Optional list of transfers/ArrayBuffers. |
| 1568 |
* @returns {Promise} Promise to be resolved with response data. |
| 1569 |
*/ |
| 1570 |
sendWithPromise: |
| 1571 |
function messageHandlerSendWithPromise(actionName, data, transfers) { |
| 1572 |
var callbackId = this.callbackIndex++; |
| 1573 |
var message = { |
| 1574 |
action: actionName, |
| 1575 |
data: data, |
| 1576 |
callbackId: callbackId |
| 1577 |
}; |
| 1578 |
var capability = createPromiseCapability(); |
| 1579 |
this.callbacksCapabilities[callbackId] = capability; |
| 1580 |
try { |
| 1581 |
this.postMessage(message, transfers); |
| 1582 |
} catch (e) { |
| 1583 |
capability.reject(e); |
| 1584 |
} |
| 1585 |
return capability.promise; |
| 1586 |
}, |
| 1587 |
/** |
| 1588 |
* Sends raw message to the comObj. |
| 1589 |
* @private |
| 1590 |
* @param message {Object} Raw message. |
| 1591 |
* @param transfers List of transfers/ArrayBuffers, or undefined. |
| 1592 |
*/ |
| 1593 |
postMessage: function (message, transfers) { |
| 1594 |
if (transfers && this.postMessageTransfers) { |
| 1595 |
this.comObj.postMessage(message, transfers); |
| 1596 |
} else { |
| 1597 |
this.comObj.postMessage(message); |
| 1598 |
} |
| 1599 |
} |
| 1600 |
}; |
| 1601 |
|
| 1602 |
function loadJpegStream(id, imageUrl, objs) { |
| 1603 |
var img = new Image(); |
| 1604 |
img.onload = (function loadJpegStream_onloadClosure() { |
| 1605 |
objs.resolve(id, img); |
| 1606 |
}); |
| 1607 |
img.onerror = (function loadJpegStream_onerrorClosure() { |
| 1608 |
objs.resolve(id, null); |
| 1609 |
warn('Error during JPEG image loading'); |
| 1610 |
}); |
| 1611 |
img.src = imageUrl; |
| 1612 |
} |
| 1613 |
|
| 1614 |
|
| 1615 |
|
| 1616 |
//#if (FIREFOX || MOZCENTRAL) |
| 1617 |
// |
| 1618 |
//Components.utils.import('resource://gre/modules/Services.jsm'); |
| 1619 |
// |
| 1620 |
//var EXPORTED_SYMBOLS = ['NetworkManager']; |
| 1621 |
// |
| 1622 |
//var console = { |
| 1623 |
// log: function console_log(aMsg) { |
| 1624 |
// var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg); |
| 1625 |
// Services.console.logStringMessage(msg); |
| 1626 |
// // TODO(mack): dump() doesn't seem to work here... |
| 1627 |
// dump(msg + '\n'); |
| 1628 |
// } |
| 1629 |
//} |
| 1630 |
//#endif |
| 1631 |
|
| 1632 |
var NetworkManager = (function NetworkManagerClosure() { |
| 1633 |
|
| 1634 |
var OK_RESPONSE = 200; |
| 1635 |
var PARTIAL_CONTENT_RESPONSE = 206; |
| 1636 |
|
| 1637 |
function NetworkManager(url, args) { |
| 1638 |
this.url = url; |
| 1639 |
args = args || {}; |
| 1640 |
this.isHttp = /^https?:/i.test(url); |
| 1641 |
this.httpHeaders = (this.isHttp && args.httpHeaders) || {}; |
| 1642 |
this.withCredentials = args.withCredentials || false; |
| 1643 |
this.getXhr = args.getXhr || |
| 1644 |
function NetworkManager_getXhr() { |
| 1645 |
//#if B2G |
| 1646 |
// return new XMLHttpRequest({ mozSystem: true }); |
| 1647 |
//#else |
| 1648 |
return new XMLHttpRequest(); |
| 1649 |
//#endif |
| 1650 |
}; |
| 1651 |
|
| 1652 |
this.currXhrId = 0; |
| 1653 |
this.pendingRequests = {}; |
| 1654 |
this.loadedRequests = {}; |
| 1655 |
} |
| 1656 |
|
| 1657 |
function getArrayBuffer(xhr) { |
| 1658 |
var data = xhr.response; |
| 1659 |
if (typeof data !== 'string') { |
| 1660 |
return data; |
| 1661 |
} |
| 1662 |
var length = data.length; |
| 1663 |
var array = new Uint8Array(length); |
| 1664 |
for (var i = 0; i < length; i++) { |
| 1665 |
array[i] = data.charCodeAt(i) & 0xFF; |
| 1666 |
} |
| 1667 |
return array.buffer; |
| 1668 |
} |
| 1669 |
|
| 1670 |
NetworkManager.prototype = { |
| 1671 |
requestRange: function NetworkManager_requestRange(begin, end, listeners) { |
| 1672 |
var args = { |
| 1673 |
begin: begin, |
| 1674 |
end: end |
| 1675 |
}; |
| 1676 |
for (var prop in listeners) { |
| 1677 |
args[prop] = listeners[prop]; |
| 1678 |
} |
| 1679 |
return this.request(args); |
| 1680 |
}, |
| 1681 |
|
| 1682 |
requestFull: function NetworkManager_requestFull(listeners) { |
| 1683 |
return this.request(listeners); |
| 1684 |
}, |
| 1685 |
|
| 1686 |
request: function NetworkManager_request(args) { |
| 1687 |
var xhr = this.getXhr(); |
| 1688 |
var xhrId = this.currXhrId++; |
| 1689 |
var pendingRequest = this.pendingRequests[xhrId] = { |
| 1690 |
xhr: xhr |
| 1691 |
}; |
| 1692 |
|
| 1693 |
xhr.open('GET', this.url); |
| 1694 |
xhr.withCredentials = this.withCredentials; |
| 1695 |
for (var property in this.httpHeaders) { |
| 1696 |
var value = this.httpHeaders[property]; |
| 1697 |
if (typeof value === 'undefined') { |
| 1698 |
continue; |
| 1699 |
} |
| 1700 |
xhr.setRequestHeader(property, value); |
| 1701 |
} |
| 1702 |
if (this.isHttp && 'begin' in args && 'end' in args) { |
| 1703 |
var rangeStr = args.begin + '-' + (args.end - 1); |
| 1704 |
xhr.setRequestHeader('Range', 'bytes=' + rangeStr); |
| 1705 |
pendingRequest.expectedStatus = 206; |
| 1706 |
} else { |
| 1707 |
pendingRequest.expectedStatus = 200; |
| 1708 |
} |
| 1709 |
|
| 1710 |
if (args.onProgressiveData) { |
| 1711 |
// Some legacy browsers might throw an exception. |
| 1712 |
try { |
| 1713 |
xhr.responseType = 'moz-chunked-arraybuffer'; |
| 1714 |
} catch(e) {} |
| 1715 |
if (xhr.responseType === 'moz-chunked-arraybuffer') { |
| 1716 |
pendingRequest.onProgressiveData = args.onProgressiveData; |
| 1717 |
pendingRequest.mozChunked = true; |
| 1718 |
} else { |
| 1719 |
xhr.responseType = 'arraybuffer'; |
| 1720 |
} |
| 1721 |
} else { |
| 1722 |
xhr.responseType = 'arraybuffer'; |
| 1723 |
} |
| 1724 |
|
| 1725 |
if (args.onError) { |
| 1726 |
xhr.onerror = function(evt) { |
| 1727 |
args.onError(xhr.status); |
| 1728 |
}; |
| 1729 |
} |
| 1730 |
xhr.onreadystatechange = this.onStateChange.bind(this, xhrId); |
| 1731 |
xhr.onprogress = this.onProgress.bind(this, xhrId); |
| 1732 |
|
| 1733 |
pendingRequest.onHeadersReceived = args.onHeadersReceived; |
| 1734 |
pendingRequest.onDone = args.onDone; |
| 1735 |
pendingRequest.onError = args.onError; |
| 1736 |
pendingRequest.onProgress = args.onProgress; |
| 1737 |
|
| 1738 |
xhr.send(null); |
| 1739 |
|
| 1740 |
return xhrId; |
| 1741 |
}, |
| 1742 |
|
| 1743 |
onProgress: function NetworkManager_onProgress(xhrId, evt) { |
| 1744 |
var pendingRequest = this.pendingRequests[xhrId]; |
| 1745 |
if (!pendingRequest) { |
| 1746 |
// Maybe abortRequest was called... |
| 1747 |
return; |
| 1748 |
} |
| 1749 |
|
| 1750 |
if (pendingRequest.mozChunked) { |
| 1751 |
var chunk = getArrayBuffer(pendingRequest.xhr); |
| 1752 |
pendingRequest.onProgressiveData(chunk); |
| 1753 |
} |
| 1754 |
|
| 1755 |
var onProgress = pendingRequest.onProgress; |
| 1756 |
if (onProgress) { |
| 1757 |
onProgress(evt); |
| 1758 |
} |
| 1759 |
}, |
| 1760 |
|
| 1761 |
onStateChange: function NetworkManager_onStateChange(xhrId, evt) { |
| 1762 |
var pendingRequest = this.pendingRequests[xhrId]; |
| 1763 |
if (!pendingRequest) { |
| 1764 |
// Maybe abortRequest was called... |
| 1765 |
return; |
| 1766 |
} |
| 1767 |
|
| 1768 |
var xhr = pendingRequest.xhr; |
| 1769 |
if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { |
| 1770 |
pendingRequest.onHeadersReceived(); |
| 1771 |
delete pendingRequest.onHeadersReceived; |
| 1772 |
} |
| 1773 |
|
| 1774 |
if (xhr.readyState !== 4) { |
| 1775 |
return; |
| 1776 |
} |
| 1777 |
|
| 1778 |
if (!(xhrId in this.pendingRequests)) { |
| 1779 |
// The XHR request might have been aborted in onHeadersReceived() |
| 1780 |
// callback, in which case we should abort request |
| 1781 |
return; |
| 1782 |
} |
| 1783 |
|
| 1784 |
delete this.pendingRequests[xhrId]; |
| 1785 |
|
| 1786 |
// success status == 0 can be on ftp, file and other protocols |
| 1787 |
if (xhr.status === 0 && this.isHttp) { |
| 1788 |
if (pendingRequest.onError) { |
| 1789 |
pendingRequest.onError(xhr.status); |
| 1790 |
} |
| 1791 |
return; |
| 1792 |
} |
| 1793 |
var xhrStatus = xhr.status || OK_RESPONSE; |
| 1794 |
|
| 1795 |
// From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2: |
| 1796 |
// "A server MAY ignore the Range header". This means it's possible to |
| 1797 |
// get a 200 rather than a 206 response from a range request. |
| 1798 |
var ok_response_on_range_request = |
| 1799 |
xhrStatus === OK_RESPONSE && |
| 1800 |
pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; |
| 1801 |
|
| 1802 |
if (!ok_response_on_range_request && |
| 1803 |
xhrStatus !== pendingRequest.expectedStatus) { |
| 1804 |
if (pendingRequest.onError) { |
| 1805 |
pendingRequest.onError(xhr.status); |
| 1806 |
} |
| 1807 |
return; |
| 1808 |
} |
| 1809 |
|
| 1810 |
this.loadedRequests[xhrId] = true; |
| 1811 |
|
| 1812 |
var chunk = getArrayBuffer(xhr); |
| 1813 |
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { |
| 1814 |
var rangeHeader = xhr.getResponseHeader('Content-Range'); |
| 1815 |
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); |
| 1816 |
var begin = parseInt(matches[1], 10); |
| 1817 |
pendingRequest.onDone({ |
| 1818 |
begin: begin, |
| 1819 |
chunk: chunk |
| 1820 |
}); |
| 1821 |
} else if (pendingRequest.onProgressiveData) { |
| 1822 |
pendingRequest.onDone(null); |
| 1823 |
} else { |
| 1824 |
pendingRequest.onDone({ |
| 1825 |
begin: 0, |
| 1826 |
chunk: chunk |
| 1827 |
}); |
| 1828 |
} |
| 1829 |
}, |
| 1830 |
|
| 1831 |
hasPendingRequests: function NetworkManager_hasPendingRequests() { |
| 1832 |
for (var xhrId in this.pendingRequests) { |
| 1833 |
return true; |
| 1834 |
} |
| 1835 |
return false; |
| 1836 |
}, |
| 1837 |
|
| 1838 |
getRequestXhr: function NetworkManager_getXhr(xhrId) { |
| 1839 |
return this.pendingRequests[xhrId].xhr; |
| 1840 |
}, |
| 1841 |
|
| 1842 |
isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) { |
| 1843 |
return !!(this.pendingRequests[xhrId].onProgressiveData); |
| 1844 |
}, |
| 1845 |
|
| 1846 |
isPendingRequest: function NetworkManager_isPendingRequest(xhrId) { |
| 1847 |
return xhrId in this.pendingRequests; |
| 1848 |
}, |
| 1849 |
|
| 1850 |
isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) { |
| 1851 |
return xhrId in this.loadedRequests; |
| 1852 |
}, |
| 1853 |
|
| 1854 |
abortAllRequests: function NetworkManager_abortAllRequests() { |
| 1855 |
for (var xhrId in this.pendingRequests) { |
| 1856 |
this.abortRequest(xhrId | 0); |
| 1857 |
} |
| 1858 |
}, |
| 1859 |
|
| 1860 |
abortRequest: function NetworkManager_abortRequest(xhrId) { |
| 1861 |
var xhr = this.pendingRequests[xhrId].xhr; |
| 1862 |
delete this.pendingRequests[xhrId]; |
| 1863 |
xhr.abort(); |
| 1864 |
} |
| 1865 |
}; |
| 1866 |
|
| 1867 |
return NetworkManager; |
| 1868 |
})(); |
| 1869 |
|
| 1870 |
|
| 1871 |
var ChunkedStream = (function ChunkedStreamClosure() { |
| 1872 |
function ChunkedStream(length, chunkSize, manager) { |
| 1873 |
this.bytes = new Uint8Array(length); |
| 1874 |
this.start = 0; |
| 1875 |
this.pos = 0; |
| 1876 |
this.end = length; |
| 1877 |
this.chunkSize = chunkSize; |
| 1878 |
this.loadedChunks = []; |
| 1879 |
this.numChunksLoaded = 0; |
| 1880 |
this.numChunks = Math.ceil(length / chunkSize); |
| 1881 |
this.manager = manager; |
| 1882 |
this.progressiveDataLength = 0; |
| 1883 |
this.lastSuccessfulEnsureByteChunk = -1; // a single-entry cache |
| 1884 |
} |
| 1885 |
|
| 1886 |
// required methods for a stream. if a particular stream does not |
| 1887 |
// implement these, an error should be thrown |
| 1888 |
ChunkedStream.prototype = { |
| 1889 |
|
| 1890 |
getMissingChunks: function ChunkedStream_getMissingChunks() { |
| 1891 |
var chunks = []; |
| 1892 |
for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) { |
| 1893 |
if (!this.loadedChunks[chunk]) { |
| 1894 |
chunks.push(chunk); |
| 1895 |
} |
| 1896 |
} |
| 1897 |
return chunks; |
| 1898 |
}, |
| 1899 |
|
| 1900 |
getBaseStreams: function ChunkedStream_getBaseStreams() { |
| 1901 |
return [this]; |
| 1902 |
}, |
| 1903 |
|
| 1904 |
allChunksLoaded: function ChunkedStream_allChunksLoaded() { |
| 1905 |
return this.numChunksLoaded === this.numChunks; |
| 1906 |
}, |
| 1907 |
|
| 1908 |
onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) { |
| 1909 |
var end = begin + chunk.byteLength; |
| 1910 |
|
| 1911 |
assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin); |
| 1912 |
// Using this.length is inaccurate here since this.start can be moved |
| 1913 |
// See ChunkedStream.moveStart() |
| 1914 |
var length = this.bytes.length; |
| 1915 |
assert(end % this.chunkSize === 0 || end === length, |
| 1916 |
'Bad end offset: ' + end); |
| 1917 |
|
| 1918 |
this.bytes.set(new Uint8Array(chunk), begin); |
| 1919 |
var chunkSize = this.chunkSize; |
| 1920 |
var beginChunk = Math.floor(begin / chunkSize); |
| 1921 |
var endChunk = Math.floor((end - 1) / chunkSize) + 1; |
| 1922 |
var curChunk; |
| 1923 |
|
| 1924 |
for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) { |
| 1925 |
if (!this.loadedChunks[curChunk]) { |
| 1926 |
this.loadedChunks[curChunk] = true; |
| 1927 |
++this.numChunksLoaded; |
| 1928 |
} |
| 1929 |
} |
| 1930 |
}, |
| 1931 |
|
| 1932 |
onReceiveProgressiveData: |
| 1933 |
function ChunkedStream_onReceiveProgressiveData(data) { |
| 1934 |
var position = this.progressiveDataLength; |
| 1935 |
var beginChunk = Math.floor(position / this.chunkSize); |
| 1936 |
|
| 1937 |
this.bytes.set(new Uint8Array(data), position); |
| 1938 |
position += data.byteLength; |
| 1939 |
this.progressiveDataLength = position; |
| 1940 |
var endChunk = position >= this.end ? this.numChunks : |
| 1941 |
Math.floor(position / this.chunkSize); |
| 1942 |
var curChunk; |
| 1943 |
for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) { |
| 1944 |
if (!this.loadedChunks[curChunk]) { |
| 1945 |
this.loadedChunks[curChunk] = true; |
| 1946 |
++this.numChunksLoaded; |
| 1947 |
} |
| 1948 |
} |
| 1949 |
}, |
| 1950 |
|
| 1951 |
ensureByte: function ChunkedStream_ensureByte(pos) { |
| 1952 |
var chunk = Math.floor(pos / this.chunkSize); |
| 1953 |
if (chunk === this.lastSuccessfulEnsureByteChunk) { |
| 1954 |
return; |
| 1955 |
} |
| 1956 |
|
| 1957 |
if (!this.loadedChunks[chunk]) { |
| 1958 |
throw new MissingDataException(pos, pos + 1); |
| 1959 |
} |
| 1960 |
this.lastSuccessfulEnsureByteChunk = chunk; |
| 1961 |
}, |
| 1962 |
|
| 1963 |
ensureRange: function ChunkedStream_ensureRange(begin, end) { |
| 1964 |
if (begin >= end) { |
| 1965 |
return; |
| 1966 |
} |
| 1967 |
|
| 1968 |
if (end <= this.progressiveDataLength) { |
| 1969 |
return; |
| 1970 |
} |
| 1971 |
|
| 1972 |
var chunkSize = this.chunkSize; |
| 1973 |
var beginChunk = Math.floor(begin / chunkSize); |
| 1974 |
var endChunk = Math.floor((end - 1) / chunkSize) + 1; |
| 1975 |
for (var chunk = beginChunk; chunk < endChunk; ++chunk) { |
| 1976 |
if (!this.loadedChunks[chunk]) { |
| 1977 |
throw new MissingDataException(begin, end); |
| 1978 |
} |
| 1979 |
} |
| 1980 |
}, |
| 1981 |
|
| 1982 |
nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) { |
| 1983 |
var chunk, n; |
| 1984 |
for (chunk = beginChunk, n = this.numChunks; chunk < n; ++chunk) { |
| 1985 |
if (!this.loadedChunks[chunk]) { |
| 1986 |
return chunk; |
| 1987 |
} |
| 1988 |
} |
| 1989 |
// Wrap around to beginning |
| 1990 |
for (chunk = 0; chunk < beginChunk; ++chunk) { |
| 1991 |
if (!this.loadedChunks[chunk]) { |
| 1992 |
return chunk; |
| 1993 |
} |
| 1994 |
} |
| 1995 |
return null; |
| 1996 |
}, |
| 1997 |
|
| 1998 |
hasChunk: function ChunkedStream_hasChunk(chunk) { |
| 1999 |
return !!this.loadedChunks[chunk]; |
| 2000 |
}, |
| 2001 |
|
| 2002 |
get length() { |
| 2003 |
return this.end - this.start; |
| 2004 |
}, |
| 2005 |
|
| 2006 |
get isEmpty() { |
| 2007 |
return this.length === 0; |
| 2008 |
}, |
| 2009 |
|
| 2010 |
getByte: function ChunkedStream_getByte() { |
| 2011 |
var pos = this.pos; |
| 2012 |
if (pos >= this.end) { |
| 2013 |
return -1; |
| 2014 |
} |
| 2015 |
this.ensureByte(pos); |
| 2016 |
return this.bytes[this.pos++]; |
| 2017 |
}, |
| 2018 |
|
| 2019 |
getUint16: function ChunkedStream_getUint16() { |
| 2020 |
var b0 = this.getByte(); |
| 2021 |
var b1 = this.getByte(); |
| 2022 |
if (b0 === -1 || b1 === -1) { |
| 2023 |
return -1; |
| 2024 |
} |
| 2025 |
return (b0 << 8) + b1; |
| 2026 |
}, |
| 2027 |
|
| 2028 |
getInt32: function ChunkedStream_getInt32() { |
| 2029 |
var b0 = this.getByte(); |
| 2030 |
var b1 = this.getByte(); |
| 2031 |
var b2 = this.getByte(); |
| 2032 |
var b3 = this.getByte(); |
| 2033 |
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; |
| 2034 |
}, |
| 2035 |
|
| 2036 |
// returns subarray of original buffer |
| 2037 |
// should only be read |
| 2038 |
getBytes: function ChunkedStream_getBytes(length) { |
| 2039 |
var bytes = this.bytes; |
| 2040 |
var pos = this.pos; |
| 2041 |
var strEnd = this.end; |
| 2042 |
|
| 2043 |
if (!length) { |
| 2044 |
this.ensureRange(pos, strEnd); |
| 2045 |
return bytes.subarray(pos, strEnd); |
| 2046 |
} |
| 2047 |
|
| 2048 |
var end = pos + length; |
| 2049 |
if (end > strEnd) { |
| 2050 |
end = strEnd; |
| 2051 |
} |
| 2052 |
this.ensureRange(pos, end); |
| 2053 |
|
| 2054 |
this.pos = end; |
| 2055 |
return bytes.subarray(pos, end); |
| 2056 |
}, |
| 2057 |
|
| 2058 |
peekByte: function ChunkedStream_peekByte() { |
| 2059 |
var peekedByte = this.getByte(); |
| 2060 |
this.pos--; |
| 2061 |
return peekedByte; |
| 2062 |
}, |
| 2063 |
|
| 2064 |
peekBytes: function ChunkedStream_peekBytes(length) { |
| 2065 |
var bytes = this.getBytes(length); |
| 2066 |
this.pos -= bytes.length; |
| 2067 |
return bytes; |
| 2068 |
}, |
| 2069 |
|
| 2070 |
getByteRange: function ChunkedStream_getBytes(begin, end) { |
| 2071 |
this.ensureRange(begin, end); |
| 2072 |
return this.bytes.subarray(begin, end); |
| 2073 |
}, |
| 2074 |
|
| 2075 |
skip: function ChunkedStream_skip(n) { |
| 2076 |
if (!n) { |
| 2077 |
n = 1; |
| 2078 |
} |
| 2079 |
this.pos += n; |
| 2080 |
}, |
| 2081 |
|
| 2082 |
reset: function ChunkedStream_reset() { |
| 2083 |
this.pos = this.start; |
| 2084 |
}, |
| 2085 |
|
| 2086 |
moveStart: function ChunkedStream_moveStart() { |
| 2087 |
this.start = this.pos; |
| 2088 |
}, |
| 2089 |
|
| 2090 |
makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) { |
| 2091 |
this.ensureRange(start, start + length); |
| 2092 |
|
| 2093 |
function ChunkedStreamSubstream() {} |
| 2094 |
ChunkedStreamSubstream.prototype = Object.create(this); |
| 2095 |
ChunkedStreamSubstream.prototype.getMissingChunks = function() { |
| 2096 |
var chunkSize = this.chunkSize; |
| 2097 |
var beginChunk = Math.floor(this.start / chunkSize); |
| 2098 |
var endChunk = Math.floor((this.end - 1) / chunkSize) + 1; |
| 2099 |
var missingChunks = []; |
| 2100 |
for (var chunk = beginChunk; chunk < endChunk; ++chunk) { |
| 2101 |
if (!this.loadedChunks[chunk]) { |
| 2102 |
missingChunks.push(chunk); |
| 2103 |
} |
| 2104 |
} |
| 2105 |
return missingChunks; |
| 2106 |
}; |
| 2107 |
var subStream = new ChunkedStreamSubstream(); |
| 2108 |
subStream.pos = subStream.start = start; |
| 2109 |
subStream.end = start + length || this.end; |
| 2110 |
subStream.dict = dict; |
| 2111 |
return subStream; |
| 2112 |
}, |
| 2113 |
|
| 2114 |
isStream: true |
| 2115 |
}; |
| 2116 |
|
| 2117 |
return ChunkedStream; |
| 2118 |
})(); |
| 2119 |
|
| 2120 |
var ChunkedStreamManager = (function ChunkedStreamManagerClosure() { |
| 2121 |
|
| 2122 |
function ChunkedStreamManager(length, chunkSize, url, args) { |
| 2123 |
this.stream = new ChunkedStream(length, chunkSize, this); |
| 2124 |
this.length = length; |
| 2125 |
this.chunkSize = chunkSize; |
| 2126 |
this.url = url; |
| 2127 |
this.disableAutoFetch = args.disableAutoFetch; |
| 2128 |
var msgHandler = this.msgHandler = args.msgHandler; |
| 2129 |
|
| 2130 |
if (args.chunkedViewerLoading) { |
| 2131 |
msgHandler.on('OnDataRange', this.onReceiveData.bind(this)); |
| 2132 |
msgHandler.on('OnDataProgress', this.onProgress.bind(this)); |
| 2133 |
this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) { |
| 2134 |
msgHandler.send('RequestDataRange', { begin: begin, end: end }); |
| 2135 |
}; |
| 2136 |
} else { |
| 2137 |
|
| 2138 |
var getXhr = function getXhr() { |
| 2139 |
//#if B2G |
| 2140 |
// return new XMLHttpRequest({ mozSystem: true }); |
| 2141 |
//#else |
| 2142 |
return new XMLHttpRequest(); |
| 2143 |
//#endif |
| 2144 |
}; |
| 2145 |
this.networkManager = new NetworkManager(this.url, { |
| 2146 |
getXhr: getXhr, |
| 2147 |
httpHeaders: args.httpHeaders, |
| 2148 |
withCredentials: args.withCredentials |
| 2149 |
}); |
| 2150 |
this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) { |
| 2151 |
this.networkManager.requestRange(begin, end, { |
| 2152 |
onDone: this.onReceiveData.bind(this), |
| 2153 |
onProgress: this.onProgress.bind(this) |
| 2154 |
}); |
| 2155 |
}; |
| 2156 |
} |
| 2157 |
|
| 2158 |
this.currRequestId = 0; |
| 2159 |
|
| 2160 |
this.chunksNeededByRequest = {}; |
| 2161 |
this.requestsByChunk = {}; |
| 2162 |
this.callbacksByRequest = {}; |
| 2163 |
this.progressiveDataLength = 0; |
| 2164 |
|
| 2165 |
this._loadedStreamCapability = createPromiseCapability(); |
| 2166 |
|
| 2167 |
if (args.initialData) { |
| 2168 |
this.onReceiveData({chunk: args.initialData}); |
| 2169 |
} |
| 2170 |
} |
| 2171 |
|
| 2172 |
ChunkedStreamManager.prototype = { |
| 2173 |
onLoadedStream: function ChunkedStreamManager_getLoadedStream() { |
| 2174 |
return this._loadedStreamCapability.promise; |
| 2175 |
}, |
| 2176 |
|
| 2177 |
// Get all the chunks that are not yet loaded and groups them into |
| 2178 |
// contiguous ranges to load in as few requests as possible |
| 2179 |
requestAllChunks: function ChunkedStreamManager_requestAllChunks() { |
| 2180 |
var missingChunks = this.stream.getMissingChunks(); |
| 2181 |
this.requestChunks(missingChunks); |
| 2182 |
return this._loadedStreamCapability.promise; |
| 2183 |
}, |
| 2184 |
|
| 2185 |
requestChunks: function ChunkedStreamManager_requestChunks(chunks, |
| 2186 |
callback) { |
| 2187 |
var requestId = this.currRequestId++; |
| 2188 |
|
| 2189 |
var chunksNeeded; |
| 2190 |
var i, ii; |
| 2191 |
this.chunksNeededByRequest[requestId] = chunksNeeded = {}; |
| 2192 |
for (i = 0, ii = chunks.length; i < ii; i++) { |
| 2193 |
if (!this.stream.hasChunk(chunks[i])) { |
| 2194 |
chunksNeeded[chunks[i]] = true; |
| 2195 |
} |
| 2196 |
} |
| 2197 |
|
| 2198 |
if (isEmptyObj(chunksNeeded)) { |
| 2199 |
if (callback) { |
| 2200 |
callback(); |
| 2201 |
} |
| 2202 |
return; |
| 2203 |
} |
| 2204 |
|
| 2205 |
this.callbacksByRequest[requestId] = callback; |
| 2206 |
|
| 2207 |
var chunksToRequest = []; |
| 2208 |
for (var chunk in chunksNeeded) { |
| 2209 |
chunk = chunk | 0; |
| 2210 |
if (!(chunk in this.requestsByChunk)) { |
| 2211 |
this.requestsByChunk[chunk] = []; |
| 2212 |
chunksToRequest.push(chunk); |
| 2213 |
} |
| 2214 |
this.requestsByChunk[chunk].push(requestId); |
| 2215 |
} |
| 2216 |
|
| 2217 |
if (!chunksToRequest.length) { |
| 2218 |
return; |
| 2219 |
} |
| 2220 |
|
| 2221 |
var groupedChunksToRequest = this.groupChunks(chunksToRequest); |
| 2222 |
|
| 2223 |
for (i = 0; i < groupedChunksToRequest.length; ++i) { |
| 2224 |
var groupedChunk = groupedChunksToRequest[i]; |
| 2225 |
var begin = groupedChunk.beginChunk * this.chunkSize; |
| 2226 |
var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length); |
| 2227 |
this.sendRequest(begin, end); |
| 2228 |
} |
| 2229 |
}, |
| 2230 |
|
| 2231 |
getStream: function ChunkedStreamManager_getStream() { |
| 2232 |
return this.stream; |
| 2233 |
}, |
| 2234 |
|
| 2235 |
// Loads any chunks in the requested range that are not yet loaded |
| 2236 |
requestRange: function ChunkedStreamManager_requestRange( |
| 2237 |
begin, end, callback) { |
| 2238 |
|
| 2239 |
end = Math.min(end, this.length); |
| 2240 |
|
| 2241 |
var beginChunk = this.getBeginChunk(begin); |
| 2242 |
var endChunk = this.getEndChunk(end); |
| 2243 |
|
| 2244 |
var chunks = []; |
| 2245 |
for (var chunk = beginChunk; chunk < endChunk; ++chunk) { |
| 2246 |
chunks.push(chunk); |
| 2247 |
} |
| 2248 |
|
| 2249 |
this.requestChunks(chunks, callback); |
| 2250 |
}, |
| 2251 |
|
| 2252 |
requestRanges: function ChunkedStreamManager_requestRanges(ranges, |
| 2253 |
callback) { |
| 2254 |
ranges = ranges || []; |
| 2255 |
var chunksToRequest = []; |
| 2256 |
|
| 2257 |
for (var i = 0; i < ranges.length; i++) { |
| 2258 |
var beginChunk = this.getBeginChunk(ranges[i].begin); |
| 2259 |
var endChunk = this.getEndChunk(ranges[i].end); |
| 2260 |
for (var chunk = beginChunk; chunk < endChunk; ++chunk) { |
| 2261 |
if (chunksToRequest.indexOf(chunk) < 0) { |
| 2262 |
chunksToRequest.push(chunk); |
| 2263 |
} |
| 2264 |
} |
| 2265 |
} |
| 2266 |
|
| 2267 |
chunksToRequest.sort(function(a, b) { return a - b; }); |
| 2268 |
this.requestChunks(chunksToRequest, callback); |
| 2269 |
}, |
| 2270 |
|
| 2271 |
// Groups a sorted array of chunks into as few continguous larger |
| 2272 |
// chunks as possible |
| 2273 |
groupChunks: function ChunkedStreamManager_groupChunks(chunks) { |
| 2274 |
var groupedChunks = []; |
| 2275 |
var beginChunk = -1; |
| 2276 |
var prevChunk = -1; |
| 2277 |
for (var i = 0; i < chunks.length; ++i) { |
| 2278 |
var chunk = chunks[i]; |
| 2279 |
|
| 2280 |
if (beginChunk < 0) { |
| 2281 |
beginChunk = chunk; |
| 2282 |
} |
| 2283 |
|
| 2284 |
if (prevChunk >= 0 && prevChunk + 1 !== chunk) { |
| 2285 |
groupedChunks.push({ beginChunk: beginChunk, |
| 2286 |
endChunk: prevChunk + 1 }); |
| 2287 |
beginChunk = chunk; |
| 2288 |
} |
| 2289 |
if (i + 1 === chunks.length) { |
| 2290 |
groupedChunks.push({ beginChunk: beginChunk, |
| 2291 |
endChunk: chunk + 1 }); |
| 2292 |
} |
| 2293 |
|
| 2294 |
prevChunk = chunk; |
| 2295 |
} |
| 2296 |
return groupedChunks; |
| 2297 |
}, |
| 2298 |
|
| 2299 |
onProgress: function ChunkedStreamManager_onProgress(args) { |
| 2300 |
var bytesLoaded = (this.stream.numChunksLoaded * this.chunkSize + |
| 2301 |
args.loaded); |
| 2302 |
this.msgHandler.send('DocProgress', { |
| 2303 |
loaded: bytesLoaded, |
| 2304 |
total: this.length |
| 2305 |
}); |
| 2306 |
}, |
| 2307 |
|
| 2308 |
onReceiveData: function ChunkedStreamManager_onReceiveData(args) { |
| 2309 |
var chunk = args.chunk; |
| 2310 |
var isProgressive = args.begin === undefined; |
| 2311 |
var begin = isProgressive ? this.progressiveDataLength : args.begin; |
| 2312 |
var end = begin + chunk.byteLength; |
| 2313 |
|
| 2314 |
var beginChunk = Math.floor(begin / this.chunkSize); |
| 2315 |
var endChunk = end < this.length ? Math.floor(end / this.chunkSize) : |
| 2316 |
Math.ceil(end / this.chunkSize); |
| 2317 |
|
| 2318 |
if (isProgressive) { |
| 2319 |
this.stream.onReceiveProgressiveData(chunk); |
| 2320 |
this.progressiveDataLength = end; |
| 2321 |
} else { |
| 2322 |
this.stream.onReceiveData(begin, chunk); |
| 2323 |
} |
| 2324 |
|
| 2325 |
if (this.stream.allChunksLoaded()) { |
| 2326 |
this._loadedStreamCapability.resolve(this.stream); |
| 2327 |
} |
| 2328 |
|
| 2329 |
var loadedRequests = []; |
| 2330 |
var i, requestId; |
| 2331 |
for (chunk = beginChunk; chunk < endChunk; ++chunk) { |
| 2332 |
// The server might return more chunks than requested |
| 2333 |
var requestIds = this.requestsByChunk[chunk] || []; |
| 2334 |
delete this.requestsByChunk[chunk]; |
| 2335 |
|
| 2336 |
for (i = 0; i < requestIds.length; ++i) { |
| 2337 |
requestId = requestIds[i]; |
| 2338 |
var chunksNeeded = this.chunksNeededByRequest[requestId]; |
| 2339 |
if (chunk in chunksNeeded) { |
| 2340 |
delete chunksNeeded[chunk]; |
| 2341 |
} |
| 2342 |
|
| 2343 |
if (!isEmptyObj(chunksNeeded)) { |
| 2344 |
continue; |
| 2345 |
} |
| 2346 |
|
| 2347 |
loadedRequests.push(requestId); |
| 2348 |
} |
| 2349 |
} |
| 2350 |
|
| 2351 |
// If there are no pending requests, automatically fetch the next |
| 2352 |
// unfetched chunk of the PDF |
| 2353 |
if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) { |
| 2354 |
var nextEmptyChunk; |
| 2355 |
if (this.stream.numChunksLoaded === 1) { |
| 2356 |
// This is a special optimization so that after fetching the first |
| 2357 |
// chunk, rather than fetching the second chunk, we fetch the last |
| 2358 |
// chunk. |
| 2359 |
var lastChunk = this.stream.numChunks - 1; |
| 2360 |
if (!this.stream.hasChunk(lastChunk)) { |
| 2361 |
nextEmptyChunk = lastChunk; |
| 2362 |
} |
| 2363 |
} else { |
| 2364 |
nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); |
| 2365 |
} |
| 2366 |
if (isInt(nextEmptyChunk)) { |
| 2367 |
this.requestChunks([nextEmptyChunk]); |
| 2368 |
} |
| 2369 |
} |
| 2370 |
|
| 2371 |
for (i = 0; i < loadedRequests.length; ++i) { |
| 2372 |
requestId = loadedRequests[i]; |
| 2373 |
var callback = this.callbacksByRequest[requestId]; |
| 2374 |
delete this.callbacksByRequest[requestId]; |
| 2375 |
if (callback) { |
| 2376 |
callback(); |
| 2377 |
} |
| 2378 |
} |
| 2379 |
|
| 2380 |
this.msgHandler.send('DocProgress', { |
| 2381 |
loaded: this.stream.numChunksLoaded * this.chunkSize, |
| 2382 |
total: this.length |
| 2383 |
}); |
| 2384 |
}, |
| 2385 |
|
| 2386 |
onError: function ChunkedStreamManager_onError(err) { |
| 2387 |
this._loadedStreamCapability.reject(err); |
| 2388 |
}, |
| 2389 |
|
| 2390 |
getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) { |
| 2391 |
var chunk = Math.floor(begin / this.chunkSize); |
| 2392 |
return chunk; |
| 2393 |
}, |
| 2394 |
|
| 2395 |
getEndChunk: function ChunkedStreamManager_getEndChunk(end) { |
| 2396 |
if (end % this.chunkSize === 0) { |
| 2397 |
return end / this.chunkSize; |
| 2398 |
} |
| 2399 |
|
| 2400 |
// 0 -> 0 |
| 2401 |
// 1 -> 1 |
| 2402 |
// 99 -> 1 |
| 2403 |
// 100 -> 1 |
| 2404 |
// 101 -> 2 |
| 2405 |
var chunk = Math.floor((end - 1) / this.chunkSize) + 1; |
| 2406 |
return chunk; |
| 2407 |
} |
| 2408 |
}; |
| 2409 |
|
| 2410 |
return ChunkedStreamManager; |
| 2411 |
})(); |
| 2412 |
|
| 2413 |
|
| 2414 |
// The maximum number of bytes fetched per range request |
| 2415 |
var RANGE_CHUNK_SIZE = 65536; |
| 2416 |
|
| 2417 |
// TODO(mack): Make use of PDFJS.Util.inherit() when it becomes available |
| 2418 |
var BasePdfManager = (function BasePdfManagerClosure() { |
| 2419 |
function BasePdfManager() { |
| 2420 |
throw new Error('Cannot initialize BaseManagerManager'); |
| 2421 |
} |
| 2422 |
|
| 2423 |
BasePdfManager.prototype = { |
| 2424 |
onLoadedStream: function BasePdfManager_onLoadedStream() { |
| 2425 |
throw new NotImplementedException(); |
| 2426 |
}, |
| 2427 |
|
| 2428 |
ensureDoc: function BasePdfManager_ensureDoc(prop, args) { |
| 2429 |
return this.ensure(this.pdfDocument, prop, args); |
| 2430 |
}, |
| 2431 |
|
| 2432 |
ensureXRef: function BasePdfManager_ensureXRef(prop, args) { |
| 2433 |
return this.ensure(this.pdfDocument.xref, prop, args); |
| 2434 |
}, |
| 2435 |
|
| 2436 |
ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) { |
| 2437 |
return this.ensure(this.pdfDocument.catalog, prop, args); |
| 2438 |
}, |
| 2439 |
|
| 2440 |
getPage: function BasePdfManager_pagePage(pageIndex) { |
| 2441 |
return this.pdfDocument.getPage(pageIndex); |
| 2442 |
}, |
| 2443 |
|
| 2444 |
cleanup: function BasePdfManager_cleanup() { |
| 2445 |
return this.pdfDocument.cleanup(); |
| 2446 |
}, |
| 2447 |
|
| 2448 |
ensure: function BasePdfManager_ensure(obj, prop, args) { |
| 2449 |
return new NotImplementedException(); |
| 2450 |
}, |
| 2451 |
|
| 2452 |
requestRange: function BasePdfManager_ensure(begin, end) { |
| 2453 |
return new NotImplementedException(); |
| 2454 |
}, |
| 2455 |
|
| 2456 |
requestLoadedStream: function BasePdfManager_requestLoadedStream() { |
| 2457 |
return new NotImplementedException(); |
| 2458 |
}, |
| 2459 |
|
| 2460 |
sendProgressiveData: function BasePdfManager_sendProgressiveData(chunk) { |
| 2461 |
return new NotImplementedException(); |
| 2462 |
}, |
| 2463 |
|
| 2464 |
updatePassword: function BasePdfManager_updatePassword(password) { |
| 2465 |
this.pdfDocument.xref.password = this.password = password; |
| 2466 |
if (this._passwordChangedCapability) { |
| 2467 |
this._passwordChangedCapability.resolve(); |
| 2468 |
} |
| 2469 |
}, |
| 2470 |
|
| 2471 |
passwordChanged: function BasePdfManager_passwordChanged() { |
| 2472 |
this._passwordChangedCapability = createPromiseCapability(); |
| 2473 |
return this._passwordChangedCapability.promise; |
| 2474 |
}, |
| 2475 |
|
| 2476 |
terminate: function BasePdfManager_terminate() { |
| 2477 |
return new NotImplementedException(); |
| 2478 |
} |
| 2479 |
}; |
| 2480 |
|
| 2481 |
return BasePdfManager; |
| 2482 |
})(); |
| 2483 |
|
| 2484 |
var LocalPdfManager = (function LocalPdfManagerClosure() { |
| 2485 |
function LocalPdfManager(data, password) { |
| 2486 |
var stream = new Stream(data); |
| 2487 |
this.pdfDocument = new PDFDocument(this, stream, password); |
| 2488 |
this._loadedStreamCapability = createPromiseCapability(); |
| 2489 |
this._loadedStreamCapability.resolve(stream); |
| 2490 |
} |
| 2491 |
|
| 2492 |
LocalPdfManager.prototype = Object.create(BasePdfManager.prototype); |
| 2493 |
LocalPdfManager.prototype.constructor = LocalPdfManager; |
| 2494 |
|
| 2495 |
LocalPdfManager.prototype.ensure = |
| 2496 |
function LocalPdfManager_ensure(obj, prop, args) { |
| 2497 |
return new Promise(function (resolve, reject) { |
| 2498 |
try { |
| 2499 |
var value = obj[prop]; |
| 2500 |
var result; |
| 2501 |
if (typeof value === 'function') { |
| 2502 |
result = value.apply(obj, args); |
| 2503 |
} else { |
| 2504 |
result = value; |
| 2505 |
} |
| 2506 |
resolve(result); |
| 2507 |
} catch (e) { |
| 2508 |
reject(e); |
| 2509 |
} |
| 2510 |
}); |
| 2511 |
}; |
| 2512 |
|
| 2513 |
LocalPdfManager.prototype.requestRange = |
| 2514 |
function LocalPdfManager_requestRange(begin, end) { |
| 2515 |
return Promise.resolve(); |
| 2516 |
}; |
| 2517 |
|
| 2518 |
LocalPdfManager.prototype.requestLoadedStream = |
| 2519 |
function LocalPdfManager_requestLoadedStream() { |
| 2520 |
}; |
| 2521 |
|
| 2522 |
LocalPdfManager.prototype.onLoadedStream = |
| 2523 |
function LocalPdfManager_getLoadedStream() { |
| 2524 |
return this._loadedStreamCapability.promise; |
| 2525 |
}; |
| 2526 |
|
| 2527 |
LocalPdfManager.prototype.terminate = |
| 2528 |
function LocalPdfManager_terminate() { |
| 2529 |
return; |
| 2530 |
}; |
| 2531 |
|
| 2532 |
return LocalPdfManager; |
| 2533 |
})(); |
| 2534 |
|
| 2535 |
var NetworkPdfManager = (function NetworkPdfManagerClosure() { |
| 2536 |
function NetworkPdfManager(args, msgHandler) { |
| 2537 |
|
| 2538 |
this.msgHandler = msgHandler; |
| 2539 |
|
| 2540 |
var params = { |
| 2541 |
msgHandler: msgHandler, |
| 2542 |
httpHeaders: args.httpHeaders, |
| 2543 |
withCredentials: args.withCredentials, |
| 2544 |
chunkedViewerLoading: args.chunkedViewerLoading, |
| 2545 |
disableAutoFetch: args.disableAutoFetch, |
| 2546 |
initialData: args.initialData |
| 2547 |
}; |
| 2548 |
this.streamManager = new ChunkedStreamManager(args.length, RANGE_CHUNK_SIZE, |
| 2549 |
args.url, params); |
| 2550 |
|
| 2551 |
this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(), |
| 2552 |
args.password); |
| 2553 |
} |
| 2554 |
|
| 2555 |
NetworkPdfManager.prototype = Object.create(BasePdfManager.prototype); |
| 2556 |
NetworkPdfManager.prototype.constructor = NetworkPdfManager; |
| 2557 |
|
| 2558 |
NetworkPdfManager.prototype.ensure = |
| 2559 |
function NetworkPdfManager_ensure(obj, prop, args) { |
| 2560 |
var pdfManager = this; |
| 2561 |
|
| 2562 |
return new Promise(function (resolve, reject) { |
| 2563 |
function ensureHelper() { |
| 2564 |
try { |
| 2565 |
var result; |
| 2566 |
var value = obj[prop]; |
| 2567 |
if (typeof value === 'function') { |
| 2568 |
result = value.apply(obj, args); |
| 2569 |
} else { |
| 2570 |
result = value; |
| 2571 |
} |
| 2572 |
resolve(result); |
| 2573 |
} catch(e) { |
| 2574 |
if (!(e instanceof MissingDataException)) { |
| 2575 |
reject(e); |
| 2576 |
return; |
| 2577 |
} |
| 2578 |
pdfManager.streamManager.requestRange(e.begin, e.end, ensureHelper); |
| 2579 |
} |
| 2580 |
} |
| 2581 |
|
| 2582 |
ensureHelper(); |
| 2583 |
}); |
| 2584 |
}; |
| 2585 |
|
| 2586 |
NetworkPdfManager.prototype.requestRange = |
| 2587 |
function NetworkPdfManager_requestRange(begin, end) { |
| 2588 |
return new Promise(function (resolve) { |
| 2589 |
this.streamManager.requestRange(begin, end, function() { |
| 2590 |
resolve(); |
| 2591 |
}); |
| 2592 |
}.bind(this)); |
| 2593 |
}; |
| 2594 |
|
| 2595 |
NetworkPdfManager.prototype.requestLoadedStream = |
| 2596 |
function NetworkPdfManager_requestLoadedStream() { |
| 2597 |
this.streamManager.requestAllChunks(); |
| 2598 |
}; |
| 2599 |
|
| 2600 |
NetworkPdfManager.prototype.sendProgressiveData = |
| 2601 |
function NetworkPdfManager_sendProgressiveData(chunk) { |
| 2602 |
this.streamManager.onReceiveData({ chunk: chunk }); |
| 2603 |
}; |
| 2604 |
|
| 2605 |
NetworkPdfManager.prototype.onLoadedStream = |
| 2606 |
function NetworkPdfManager_getLoadedStream() { |
| 2607 |
return this.streamManager.onLoadedStream(); |
| 2608 |
}; |
| 2609 |
|
| 2610 |
NetworkPdfManager.prototype.terminate = |
| 2611 |
function NetworkPdfManager_terminate() { |
| 2612 |
this.streamManager.networkManager.abortAllRequests(); |
| 2613 |
}; |
| 2614 |
|
| 2615 |
return NetworkPdfManager; |
| 2616 |
})(); |
| 2617 |
|
| 2618 |
|
| 2619 |
var Page = (function PageClosure() { |
| 2620 |
|
| 2621 |
var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792]; |
| 2622 |
|
| 2623 |
function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) { |
| 2624 |
this.pdfManager = pdfManager; |
| 2625 |
this.pageIndex = pageIndex; |
| 2626 |
this.pageDict = pageDict; |
| 2627 |
this.xref = xref; |
| 2628 |
this.ref = ref; |
| 2629 |
this.fontCache = fontCache; |
| 2630 |
this.idCounters = { |
| 2631 |
obj: 0 |
| 2632 |
}; |
| 2633 |
this.resourcesPromise = null; |
| 2634 |
} |
| 2635 |
|
| 2636 |
Page.prototype = { |
| 2637 |
getPageProp: function Page_getPageProp(key) { |
| 2638 |
return this.pageDict.get(key); |
| 2639 |
}, |
| 2640 |
|
| 2641 |
getInheritedPageProp: function Page_inheritPageProp(key) { |
| 2642 |
var dict = this.pageDict; |
| 2643 |
var value = dict.get(key); |
| 2644 |
while (value === undefined) { |
| 2645 |
dict = dict.get('Parent'); |
| 2646 |
if (!dict) { |
| 2647 |
break; |
| 2648 |
} |
| 2649 |
value = dict.get(key); |
| 2650 |
} |
| 2651 |
return value; |
| 2652 |
}, |
| 2653 |
|
| 2654 |
get content() { |
| 2655 |
return this.getPageProp('Contents'); |
| 2656 |
}, |
| 2657 |
|
| 2658 |
get resources() { |
| 2659 |
var value = this.getInheritedPageProp('Resources'); |
| 2660 |
// For robustness: The spec states that a \Resources entry has to be |
| 2661 |
// present, but can be empty. Some document omit it still. In this case |
| 2662 |
// return an empty dictionary: |
| 2663 |
if (value === undefined) { |
| 2664 |
value = Dict.empty; |
| 2665 |
} |
| 2666 |
return shadow(this, 'resources', value); |
| 2667 |
}, |
| 2668 |
|
| 2669 |
get mediaBox() { |
| 2670 |
var obj = this.getInheritedPageProp('MediaBox'); |
| 2671 |
// Reset invalid media box to letter size. |
| 2672 |
if (!isArray(obj) || obj.length !== 4) { |
| 2673 |
obj = LETTER_SIZE_MEDIABOX; |
| 2674 |
} |
| 2675 |
return shadow(this, 'mediaBox', obj); |
| 2676 |
}, |
| 2677 |
|
| 2678 |
get view() { |
| 2679 |
var mediaBox = this.mediaBox; |
| 2680 |
var cropBox = this.getInheritedPageProp('CropBox'); |
| 2681 |
if (!isArray(cropBox) || cropBox.length !== 4) { |
| 2682 |
return shadow(this, 'view', mediaBox); |
| 2683 |
} |
| 2684 |
|
| 2685 |
// From the spec, 6th ed., p.963: |
| 2686 |
// "The crop, bleed, trim, and art boxes should not ordinarily |
| 2687 |
// extend beyond the boundaries of the media box. If they do, they are |
| 2688 |
// effectively reduced to their intersection with the media box." |
| 2689 |
cropBox = Util.intersect(cropBox, mediaBox); |
| 2690 |
if (!cropBox) { |
| 2691 |
return shadow(this, 'view', mediaBox); |
| 2692 |
} |
| 2693 |
return shadow(this, 'view', cropBox); |
| 2694 |
}, |
| 2695 |
|
| 2696 |
get annotationRefs() { |
| 2697 |
return shadow(this, 'annotationRefs', |
| 2698 |
this.getInheritedPageProp('Annots')); |
| 2699 |
}, |
| 2700 |
|
| 2701 |
get rotate() { |
| 2702 |
var rotate = this.getInheritedPageProp('Rotate') || 0; |
| 2703 |
// Normalize rotation so it's a multiple of 90 and between 0 and 270 |
| 2704 |
if (rotate % 90 !== 0) { |
| 2705 |
rotate = 0; |
| 2706 |
} else if (rotate >= 360) { |
| 2707 |
rotate = rotate % 360; |
| 2708 |
} else if (rotate < 0) { |
| 2709 |
// The spec doesn't cover negatives, assume its counterclockwise |
| 2710 |
// rotation. The following is the other implementation of modulo. |
| 2711 |
rotate = ((rotate % 360) + 360) % 360; |
| 2712 |
} |
| 2713 |
return shadow(this, 'rotate', rotate); |
| 2714 |
}, |
| 2715 |
|
| 2716 |
getContentStream: function Page_getContentStream() { |
| 2717 |
var content = this.content; |
| 2718 |
var stream; |
| 2719 |
if (isArray(content)) { |
| 2720 |
// fetching items |
| 2721 |
var xref = this.xref; |
| 2722 |
var i, n = content.length; |
| 2723 |
var streams = []; |
| 2724 |
for (i = 0; i < n; ++i) { |
| 2725 |
streams.push(xref.fetchIfRef(content[i])); |
| 2726 |
} |
| 2727 |
stream = new StreamsSequenceStream(streams); |
| 2728 |
} else if (isStream(content)) { |
| 2729 |
stream = content; |
| 2730 |
} else { |
| 2731 |
// replacing non-existent page content with empty one |
| 2732 |
stream = new NullStream(); |
| 2733 |
} |
| 2734 |
return stream; |
| 2735 |
}, |
| 2736 |
|
| 2737 |
loadResources: function Page_loadResources(keys) { |
| 2738 |
if (!this.resourcesPromise) { |
| 2739 |
// TODO: add async getInheritedPageProp and remove this. |
| 2740 |
this.resourcesPromise = this.pdfManager.ensure(this, 'resources'); |
| 2741 |
} |
| 2742 |
return this.resourcesPromise.then(function resourceSuccess() { |
| 2743 |
var objectLoader = new ObjectLoader(this.resources.map, |
| 2744 |
keys, |
| 2745 |
this.xref); |
| 2746 |
return objectLoader.load(); |
| 2747 |
}.bind(this)); |
| 2748 |
}, |
| 2749 |
|
| 2750 |
getOperatorList: function Page_getOperatorList(handler, intent) { |
| 2751 |
var self = this; |
| 2752 |
|
| 2753 |
var pdfManager = this.pdfManager; |
| 2754 |
var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', |
| 2755 |
[]); |
| 2756 |
var resourcesPromise = this.loadResources([ |
| 2757 |
'ExtGState', |
| 2758 |
'ColorSpace', |
| 2759 |
'Pattern', |
| 2760 |
'Shading', |
| 2761 |
'XObject', |
| 2762 |
'Font' |
| 2763 |
// ProcSet |
| 2764 |
// Properties |
| 2765 |
]); |
| 2766 |
|
| 2767 |
var partialEvaluator = new PartialEvaluator(pdfManager, this.xref, |
| 2768 |
handler, this.pageIndex, |
| 2769 |
'p' + this.pageIndex + '_', |
| 2770 |
this.idCounters, |
| 2771 |
this.fontCache); |
| 2772 |
|
| 2773 |
var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); |
| 2774 |
var pageListPromise = dataPromises.then(function(data) { |
| 2775 |
var contentStream = data[0]; |
| 2776 |
var opList = new OperatorList(intent, handler, self.pageIndex); |
| 2777 |
|
| 2778 |
handler.send('StartRenderPage', { |
| 2779 |
transparency: partialEvaluator.hasBlendModes(self.resources), |
| 2780 |
pageIndex: self.pageIndex, |
| 2781 |
intent: intent |
| 2782 |
}); |
| 2783 |
return partialEvaluator.getOperatorList(contentStream, self.resources, |
| 2784 |
opList).then(function () { |
| 2785 |
return opList; |
| 2786 |
}); |
| 2787 |
}); |
| 2788 |
|
| 2789 |
var annotationsPromise = pdfManager.ensure(this, 'annotations'); |
| 2790 |
return Promise.all([pageListPromise, annotationsPromise]).then( |
| 2791 |
function(datas) { |
| 2792 |
var pageOpList = datas[0]; |
| 2793 |
var annotations = datas[1]; |
| 2794 |
|
| 2795 |
if (annotations.length === 0) { |
| 2796 |
pageOpList.flush(true); |
| 2797 |
return pageOpList; |
| 2798 |
} |
| 2799 |
|
| 2800 |
var annotationsReadyPromise = Annotation.appendToOperatorList( |
| 2801 |
annotations, pageOpList, pdfManager, partialEvaluator, intent); |
| 2802 |
return annotationsReadyPromise.then(function () { |
| 2803 |
pageOpList.flush(true); |
| 2804 |
return pageOpList; |
| 2805 |
}); |
| 2806 |
}); |
| 2807 |
}, |
| 2808 |
|
| 2809 |
extractTextContent: function Page_extractTextContent() { |
| 2810 |
var handler = { |
| 2811 |
on: function nullHandlerOn() {}, |
| 2812 |
send: function nullHandlerSend() {} |
| 2813 |
}; |
| 2814 |
|
| 2815 |
var self = this; |
| 2816 |
|
| 2817 |
var pdfManager = this.pdfManager; |
| 2818 |
var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', |
| 2819 |
[]); |
| 2820 |
|
| 2821 |
var resourcesPromise = this.loadResources([ |
| 2822 |
'ExtGState', |
| 2823 |
'XObject', |
| 2824 |
'Font' |
| 2825 |
]); |
| 2826 |
|
| 2827 |
var dataPromises = Promise.all([contentStreamPromise, |
| 2828 |
resourcesPromise]); |
| 2829 |
return dataPromises.then(function(data) { |
| 2830 |
var contentStream = data[0]; |
| 2831 |
var partialEvaluator = new PartialEvaluator(pdfManager, self.xref, |
| 2832 |
handler, self.pageIndex, |
| 2833 |
'p' + self.pageIndex + '_', |
| 2834 |
self.idCounters, |
| 2835 |
self.fontCache); |
| 2836 |
|
| 2837 |
return partialEvaluator.getTextContent(contentStream, |
| 2838 |
self.resources); |
| 2839 |
}); |
| 2840 |
}, |
| 2841 |
|
| 2842 |
getAnnotationsData: function Page_getAnnotationsData() { |
| 2843 |
var annotations = this.annotations; |
| 2844 |
var annotationsData = []; |
| 2845 |
for (var i = 0, n = annotations.length; i < n; ++i) { |
| 2846 |
annotationsData.push(annotations[i].getData()); |
| 2847 |
} |
| 2848 |
return annotationsData; |
| 2849 |
}, |
| 2850 |
|
| 2851 |
get annotations() { |
| 2852 |
var annotations = []; |
| 2853 |
var annotationRefs = (this.annotationRefs || []); |
| 2854 |
for (var i = 0, n = annotationRefs.length; i < n; ++i) { |
| 2855 |
var annotationRef = annotationRefs[i]; |
| 2856 |
var annotation = Annotation.fromRef(this.xref, annotationRef); |
| 2857 |
if (annotation) { |
| 2858 |
annotations.push(annotation); |
| 2859 |
} |
| 2860 |
} |
| 2861 |
return shadow(this, 'annotations', annotations); |
| 2862 |
} |
| 2863 |
}; |
| 2864 |
|
| 2865 |
return Page; |
| 2866 |
})(); |
| 2867 |
|
| 2868 |
/** |
| 2869 |
* The `PDFDocument` holds all the data of the PDF file. Compared to the |
| 2870 |
* `PDFDoc`, this one doesn't have any job management code. |
| 2871 |
* Right now there exists one PDFDocument on the main thread + one object |
| 2872 |
* for each worker. If there is no worker support enabled, there are two |
| 2873 |
* `PDFDocument` objects on the main thread created. |
| 2874 |
*/ |
| 2875 |
var PDFDocument = (function PDFDocumentClosure() { |
| 2876 |
var FINGERPRINT_FIRST_BYTES = 1024; |
| 2877 |
var EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' + |
| 2878 |
'\x00\x00\x00\x00\x00\x00\x00\x00\x00'; |
| 2879 |
|
| 2880 |
function PDFDocument(pdfManager, arg, password) { |
| 2881 |
if (isStream(arg)) { |
| 2882 |
init.call(this, pdfManager, arg, password); |
| 2883 |
} else if (isArrayBuffer(arg)) { |
| 2884 |
init.call(this, pdfManager, new Stream(arg), password); |
| 2885 |
} else { |
| 2886 |
error('PDFDocument: Unknown argument type'); |
| 2887 |
} |
| 2888 |
} |
| 2889 |
|
| 2890 |
function init(pdfManager, stream, password) { |
| 2891 |
assert(stream.length > 0, 'stream must have data'); |
| 2892 |
this.pdfManager = pdfManager; |
| 2893 |
this.stream = stream; |
| 2894 |
var xref = new XRef(this.stream, password, pdfManager); |
| 2895 |
this.xref = xref; |
| 2896 |
} |
| 2897 |
|
| 2898 |
function find(stream, needle, limit, backwards) { |
| 2899 |
var pos = stream.pos; |
| 2900 |
var end = stream.end; |
| 2901 |
var strBuf = []; |
| 2902 |
if (pos + limit > end) { |
| 2903 |
limit = end - pos; |
| 2904 |
} |
| 2905 |
for (var n = 0; n < limit; ++n) { |
| 2906 |
strBuf.push(String.fromCharCode(stream.getByte())); |
| 2907 |
} |
| 2908 |
var str = strBuf.join(''); |
| 2909 |
stream.pos = pos; |
| 2910 |
var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle); |
| 2911 |
if (index === -1) { |
| 2912 |
return false; /* not found */ |
| 2913 |
} |
| 2914 |
stream.pos += index; |
| 2915 |
return true; /* found */ |
| 2916 |
} |
| 2917 |
|
| 2918 |
var DocumentInfoValidators = { |
| 2919 |
get entries() { |
| 2920 |
// Lazily build this since all the validation functions below are not |
| 2921 |
// defined until after this file loads. |
| 2922 |
return shadow(this, 'entries', { |
| 2923 |
Title: isString, |
| 2924 |
Author: isString, |
| 2925 |
Subject: isString, |
| 2926 |
Keywords: isString, |
| 2927 |
Creator: isString, |
| 2928 |
Producer: isString, |
| 2929 |
CreationDate: isString, |
| 2930 |
ModDate: isString, |
| 2931 |
Trapped: isName |
| 2932 |
}); |
| 2933 |
} |
| 2934 |
}; |
| 2935 |
|
| 2936 |
PDFDocument.prototype = { |
| 2937 |
parse: function PDFDocument_parse(recoveryMode) { |
| 2938 |
this.setup(recoveryMode); |
| 2939 |
try { |
| 2940 |
// checking if AcroForm is present |
| 2941 |
this.acroForm = this.catalog.catDict.get('AcroForm'); |
| 2942 |
if (this.acroForm) { |
| 2943 |
this.xfa = this.acroForm.get('XFA'); |
| 2944 |
var fields = this.acroForm.get('Fields'); |
| 2945 |
if ((!fields || !isArray(fields) || fields.length === 0) && |
| 2946 |
!this.xfa) { |
| 2947 |
// no fields and no XFA -- not a form (?) |
| 2948 |
this.acroForm = null; |
| 2949 |
} |
| 2950 |
} |
| 2951 |
} catch (ex) { |
| 2952 |
info('Something wrong with AcroForm entry'); |
| 2953 |
this.acroForm = null; |
| 2954 |
} |
| 2955 |
}, |
| 2956 |
|
| 2957 |
get linearization() { |
| 2958 |
var linearization = null; |
| 2959 |
if (this.stream.length) { |
| 2960 |
try { |
| 2961 |
linearization = Linearization.create(this.stream); |
| 2962 |
} catch (err) { |
| 2963 |
if (err instanceof MissingDataException) { |
| 2964 |
throw err; |
| 2965 |
} |
| 2966 |
info(err); |
| 2967 |
} |
| 2968 |
} |
| 2969 |
// shadow the prototype getter with a data property |
| 2970 |
return shadow(this, 'linearization', linearization); |
| 2971 |
}, |
| 2972 |
get startXRef() { |
| 2973 |
var stream = this.stream; |
| 2974 |
var startXRef = 0; |
| 2975 |
var linearization = this.linearization; |
| 2976 |
if (linearization) { |
| 2977 |
// Find end of first obj. |
| 2978 |
stream.reset(); |
| 2979 |
if (find(stream, 'endobj', 1024)) { |
| 2980 |
startXRef = stream.pos + 6; |
| 2981 |
} |
| 2982 |
} else { |
| 2983 |
// Find startxref by jumping backward from the end of the file. |
| 2984 |
var step = 1024; |
| 2985 |
var found = false, pos = stream.end; |
| 2986 |
while (!found && pos > 0) { |
| 2987 |
pos -= step - 'startxref'.length; |
| 2988 |
if (pos < 0) { |
| 2989 |
pos = 0; |
| 2990 |
} |
| 2991 |
stream.pos = pos; |
| 2992 |
found = find(stream, 'startxref', step, true); |
| 2993 |
} |
| 2994 |
if (found) { |
| 2995 |
stream.skip(9); |
| 2996 |
var ch; |
| 2997 |
do { |
| 2998 |
ch = stream.getByte(); |
| 2999 |
} while (Lexer.isSpace(ch)); |
| 3000 |
var str = ''; |
| 3001 |
while (ch >= 0x20 && ch <= 0x39) { // < '9' |
| 3002 |
str += String.fromCharCode(ch); |
| 3003 |
ch = stream.getByte(); |
| 3004 |
} |
| 3005 |
startXRef = parseInt(str, 10); |
| 3006 |
if (isNaN(startXRef)) { |
| 3007 |
startXRef = 0; |
| 3008 |
} |
| 3009 |
} |
| 3010 |
} |
| 3011 |
// shadow the prototype getter with a data property |
| 3012 |
return shadow(this, 'startXRef', startXRef); |
| 3013 |
}, |
| 3014 |
get mainXRefEntriesOffset() { |
| 3015 |
var mainXRefEntriesOffset = 0; |
| 3016 |
var linearization = this.linearization; |
| 3017 |
if (linearization) { |
| 3018 |
mainXRefEntriesOffset = linearization.mainXRefEntriesOffset; |
| 3019 |
} |
| 3020 |
// shadow the prototype getter with a data property |
| 3021 |
return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset); |
| 3022 |
}, |
| 3023 |
// Find the header, remove leading garbage and setup the stream |
| 3024 |
// starting from the header. |
| 3025 |
checkHeader: function PDFDocument_checkHeader() { |
| 3026 |
var stream = this.stream; |
| 3027 |
stream.reset(); |
| 3028 |
if (find(stream, '%PDF-', 1024)) { |
| 3029 |
// Found the header, trim off any garbage before it. |
| 3030 |
stream.moveStart(); |
| 3031 |
// Reading file format version |
| 3032 |
var MAX_VERSION_LENGTH = 12; |
| 3033 |
var version = '', ch; |
| 3034 |
while ((ch = stream.getByte()) > 0x20) { // SPACE |
| 3035 |
if (version.length >= MAX_VERSION_LENGTH) { |
| 3036 |
break; |
| 3037 |
} |
| 3038 |
version += String.fromCharCode(ch); |
| 3039 |
} |
| 3040 |
// removing "%PDF-"-prefix |
| 3041 |
this.pdfFormatVersion = version.substring(5); |
| 3042 |
return; |
| 3043 |
} |
| 3044 |
// May not be a PDF file, continue anyway. |
| 3045 |
}, |
| 3046 |
parseStartXRef: function PDFDocument_parseStartXRef() { |
| 3047 |
var startXRef = this.startXRef; |
| 3048 |
this.xref.setStartXRef(startXRef); |
| 3049 |
}, |
| 3050 |
setup: function PDFDocument_setup(recoveryMode) { |
| 3051 |
this.xref.parse(recoveryMode); |
| 3052 |
this.catalog = new Catalog(this.pdfManager, this.xref); |
| 3053 |
}, |
| 3054 |
get numPages() { |
| 3055 |
var linearization = this.linearization; |
| 3056 |
var num = linearization ? linearization.numPages : this.catalog.numPages; |
| 3057 |
// shadow the prototype getter |
| 3058 |
return shadow(this, 'numPages', num); |
| 3059 |
}, |
| 3060 |
get documentInfo() { |
| 3061 |
var docInfo = { |
| 3062 |
PDFFormatVersion: this.pdfFormatVersion, |
| 3063 |
IsAcroFormPresent: !!this.acroForm, |
| 3064 |
IsXFAPresent: !!this.xfa |
| 3065 |
}; |
| 3066 |
var infoDict; |
| 3067 |
try { |
| 3068 |
infoDict = this.xref.trailer.get('Info'); |
| 3069 |
} catch (err) { |
| 3070 |
info('The document information dictionary is invalid.'); |
| 3071 |
} |
| 3072 |
if (infoDict) { |
| 3073 |
var validEntries = DocumentInfoValidators.entries; |
| 3074 |
// Only fill the document info with valid entries from the spec. |
| 3075 |
for (var key in validEntries) { |
| 3076 |
if (infoDict.has(key)) { |
| 3077 |
var value = infoDict.get(key); |
| 3078 |
// Make sure the value conforms to the spec. |
| 3079 |
if (validEntries[key](value)) { |
| 3080 |
docInfo[key] = (typeof value !== 'string' ? |
| 3081 |
value : stringToPDFString(value)); |
| 3082 |
} else { |
| 3083 |
info('Bad value in document info for "' + key + '"'); |
| 3084 |
} |
| 3085 |
} |
| 3086 |
} |
| 3087 |
} |
| 3088 |
return shadow(this, 'documentInfo', docInfo); |
| 3089 |
}, |
| 3090 |
get fingerprint() { |
| 3091 |
var xref = this.xref, idArray, hash, fileID = ''; |
| 3092 |
|
| 3093 |
if (xref.trailer.has('ID')) { |
| 3094 |
idArray = xref.trailer.get('ID'); |
| 3095 |
} |
| 3096 |
if (idArray && isArray(idArray) && idArray[0] !== EMPTY_FINGERPRINT) { |
| 3097 |
hash = stringToBytes(idArray[0]); |
| 3098 |
} else { |
| 3099 |
if (this.stream.ensureRange) { |
| 3100 |
this.stream.ensureRange(0, |
| 3101 |
Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end)); |
| 3102 |
} |
| 3103 |
hash = calculateMD5(this.stream.bytes.subarray(0, |
| 3104 |
FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); |
| 3105 |
} |
| 3106 |
|
| 3107 |
for (var i = 0, n = hash.length; i < n; i++) { |
| 3108 |
var hex = hash[i].toString(16); |
| 3109 |
fileID += hex.length === 1 ? '0' + hex : hex; |
| 3110 |
} |
| 3111 |
|
| 3112 |
return shadow(this, 'fingerprint', fileID); |
| 3113 |
}, |
| 3114 |
|
| 3115 |
getPage: function PDFDocument_getPage(pageIndex) { |
| 3116 |
return this.catalog.getPage(pageIndex); |
| 3117 |
}, |
| 3118 |
|
| 3119 |
cleanup: function PDFDocument_cleanup() { |
| 3120 |
return this.catalog.cleanup(); |
| 3121 |
} |
| 3122 |
}; |
| 3123 |
|
| 3124 |
return PDFDocument; |
| 3125 |
})(); |
| 3126 |
|
| 3127 |
|
| 3128 |
var Name = (function NameClosure() { |
| 3129 |
function Name(name) { |
| 3130 |
this.name = name; |
| 3131 |
} |
| 3132 |
|
| 3133 |
Name.prototype = {}; |
| 3134 |
|
| 3135 |
var nameCache = {}; |
| 3136 |
|
| 3137 |
Name.get = function Name_get(name) { |
| 3138 |
var nameValue = nameCache[name]; |
| 3139 |
return (nameValue ? nameValue : (nameCache[name] = new Name(name))); |
| 3140 |
}; |
| 3141 |
|
| 3142 |
return Name; |
| 3143 |
})(); |
| 3144 |
|
| 3145 |
var Cmd = (function CmdClosure() { |
| 3146 |
function Cmd(cmd) { |
| 3147 |
this.cmd = cmd; |
| 3148 |
} |
| 3149 |
|
| 3150 |
Cmd.prototype = {}; |
| 3151 |
|
| 3152 |
var cmdCache = {}; |
| 3153 |
|
| 3154 |
Cmd.get = function Cmd_get(cmd) { |
| 3155 |
var cmdValue = cmdCache[cmd]; |
| 3156 |
return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd))); |
| 3157 |
}; |
| 3158 |
|
| 3159 |
return Cmd; |
| 3160 |
})(); |
| 3161 |
|
| 3162 |
var Dict = (function DictClosure() { |
| 3163 |
var nonSerializable = function nonSerializableClosure() { |
| 3164 |
return nonSerializable; // creating closure on some variable |
| 3165 |
}; |
| 3166 |
|
| 3167 |
var GETALL_DICTIONARY_TYPES_WHITELIST = { |
| 3168 |
'Background': true, |
| 3169 |
'ExtGState': true, |
| 3170 |
'Halftone': true, |
| 3171 |
'Layout': true, |
| 3172 |
'Mask': true, |
| 3173 |
'Pagination': true, |
| 3174 |
'Printing': true |
| 3175 |
}; |
| 3176 |
|
| 3177 |
function isRecursionAllowedFor(dict) { |
| 3178 |
if (!isName(dict.Type)) { |
| 3179 |
return true; |
| 3180 |
} |
| 3181 |
var dictType = dict.Type.name; |
| 3182 |
return GETALL_DICTIONARY_TYPES_WHITELIST[dictType] === true; |
| 3183 |
} |
| 3184 |
|
| 3185 |
// xref is optional |
| 3186 |
function Dict(xref) { |
| 3187 |
// Map should only be used internally, use functions below to access. |
| 3188 |
this.map = Object.create(null); |
| 3189 |
this.xref = xref; |
| 3190 |
this.objId = null; |
| 3191 |
this.__nonSerializable__ = nonSerializable; // disable cloning of the Dict |
| 3192 |
} |
| 3193 |
|
| 3194 |
Dict.prototype = { |
| 3195 |
assignXref: function Dict_assignXref(newXref) { |
| 3196 |
this.xref = newXref; |
| 3197 |
}, |
| 3198 |
|
| 3199 |
// automatically dereferences Ref objects |
| 3200 |
get: function Dict_get(key1, key2, key3) { |
| 3201 |
var value; |
| 3202 |
var xref = this.xref; |
| 3203 |
if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || |
| 3204 |
typeof key2 === 'undefined') { |
| 3205 |
return xref ? xref.fetchIfRef(value) : value; |
| 3206 |
} |
| 3207 |
if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || |
| 3208 |
typeof key3 === 'undefined') { |
| 3209 |
return xref ? xref.fetchIfRef(value) : value; |
| 3210 |
} |
| 3211 |
value = this.map[key3] || null; |
| 3212 |
return xref ? xref.fetchIfRef(value) : value; |
| 3213 |
}, |
| 3214 |
|
| 3215 |
// Same as get(), but returns a promise and uses fetchIfRefAsync(). |
| 3216 |
getAsync: function Dict_getAsync(key1, key2, key3) { |
| 3217 |
var value; |
| 3218 |
var xref = this.xref; |
| 3219 |
if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || |
| 3220 |
typeof key2 === 'undefined') { |
| 3221 |
if (xref) { |
| 3222 |
return xref.fetchIfRefAsync(value); |
| 3223 |
} |
| 3224 |
return Promise.resolve(value); |
| 3225 |
} |
| 3226 |
if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || |
| 3227 |
typeof key3 === 'undefined') { |
| 3228 |
if (xref) { |
| 3229 |
return xref.fetchIfRefAsync(value); |
| 3230 |
} |
| 3231 |
return Promise.resolve(value); |
| 3232 |
} |
| 3233 |
value = this.map[key3] || null; |
| 3234 |
if (xref) { |
| 3235 |
return xref.fetchIfRefAsync(value); |
| 3236 |
} |
| 3237 |
return Promise.resolve(value); |
| 3238 |
}, |
| 3239 |
|
| 3240 |
// no dereferencing |
| 3241 |
getRaw: function Dict_getRaw(key) { |
| 3242 |
return this.map[key]; |
| 3243 |
}, |
| 3244 |
|
| 3245 |
// creates new map and dereferences all Refs |
| 3246 |
getAll: function Dict_getAll() { |
| 3247 |
var all = Object.create(null); |
| 3248 |
var queue = null; |
| 3249 |
var key, obj; |
| 3250 |
for (key in this.map) { |
| 3251 |
obj = this.get(key); |
| 3252 |
if (obj instanceof Dict) { |
| 3253 |
if (isRecursionAllowedFor(obj)) { |
| 3254 |
(queue || (queue = [])).push({target: all, key: key, obj: obj}); |
| 3255 |
} else { |
| 3256 |
all[key] = this.getRaw(key); |
| 3257 |
} |
| 3258 |
} else { |
| 3259 |
all[key] = obj; |
| 3260 |
} |
| 3261 |
} |
| 3262 |
if (!queue) { |
| 3263 |
return all; |
| 3264 |
} |
| 3265 |
|
| 3266 |
// trying to take cyclic references into the account |
| 3267 |
var processed = Object.create(null); |
| 3268 |
while (queue.length > 0) { |
| 3269 |
var item = queue.shift(); |
| 3270 |
var itemObj = item.obj; |
| 3271 |
var objId = itemObj.objId; |
| 3272 |
if (objId && objId in processed) { |
| 3273 |
item.target[item.key] = processed[objId]; |
| 3274 |
continue; |
| 3275 |
} |
| 3276 |
var dereferenced = Object.create(null); |
| 3277 |
for (key in itemObj.map) { |
| 3278 |
obj = itemObj.get(key); |
| 3279 |
if (obj instanceof Dict) { |
| 3280 |
if (isRecursionAllowedFor(obj)) { |
| 3281 |
queue.push({target: dereferenced, key: key, obj: obj}); |
| 3282 |
} else { |
| 3283 |
dereferenced[key] = itemObj.getRaw(key); |
| 3284 |
} |
| 3285 |
} else { |
| 3286 |
dereferenced[key] = obj; |
| 3287 |
} |
| 3288 |
} |
| 3289 |
if (objId) { |
| 3290 |
processed[objId] = dereferenced; |
| 3291 |
} |
| 3292 |
item.target[item.key] = dereferenced; |
| 3293 |
} |
| 3294 |
return all; |
| 3295 |
}, |
| 3296 |
|
| 3297 |
getKeys: function Dict_getKeys() { |
| 3298 |
return Object.keys(this.map); |
| 3299 |
}, |
| 3300 |
|
| 3301 |
set: function Dict_set(key, value) { |
| 3302 |
this.map[key] = value; |
| 3303 |
}, |
| 3304 |
|
| 3305 |
has: function Dict_has(key) { |
| 3306 |
return key in this.map; |
| 3307 |
}, |
| 3308 |
|
| 3309 |
forEach: function Dict_forEach(callback) { |
| 3310 |
for (var key in this.map) { |
| 3311 |
callback(key, this.get(key)); |
| 3312 |
} |
| 3313 |
} |
| 3314 |
}; |
| 3315 |
|
| 3316 |
Dict.empty = new Dict(null); |
| 3317 |
|
| 3318 |
return Dict; |
| 3319 |
})(); |
| 3320 |
|
| 3321 |
var Ref = (function RefClosure() { |
| 3322 |
function Ref(num, gen) { |
| 3323 |
this.num = num; |
| 3324 |
this.gen = gen; |
| 3325 |
} |
| 3326 |
|
| 3327 |
Ref.prototype = { |
| 3328 |
toString: function Ref_toString() { |
| 3329 |
// This function is hot, so we make the string as compact as possible. |
| 3330 |
// |this.gen| is almost always zero, so we treat that case specially. |
| 3331 |
var str = this.num + 'R'; |
| 3332 |
if (this.gen !== 0) { |
| 3333 |
str += this.gen; |
| 3334 |
} |
| 3335 |
return str; |
| 3336 |
} |
| 3337 |
}; |
| 3338 |
|
| 3339 |
return Ref; |
| 3340 |
})(); |
| 3341 |
|
| 3342 |
// The reference is identified by number and generation. |
| 3343 |
// This structure stores only one instance of the reference. |
| 3344 |
var RefSet = (function RefSetClosure() { |
| 3345 |
function RefSet() { |
| 3346 |
this.dict = {}; |
| 3347 |
} |
| 3348 |
|
| 3349 |
RefSet.prototype = { |
| 3350 |
has: function RefSet_has(ref) { |
| 3351 |
return ref.toString() in this.dict; |
| 3352 |
}, |
| 3353 |
|
| 3354 |
put: function RefSet_put(ref) { |
| 3355 |
this.dict[ref.toString()] = true; |
| 3356 |
}, |
| 3357 |
|
| 3358 |
remove: function RefSet_remove(ref) { |
| 3359 |
delete this.dict[ref.toString()]; |
| 3360 |
} |
| 3361 |
}; |
| 3362 |
|
| 3363 |
return RefSet; |
| 3364 |
})(); |
| 3365 |
|
| 3366 |
var RefSetCache = (function RefSetCacheClosure() { |
| 3367 |
function RefSetCache() { |
| 3368 |
this.dict = Object.create(null); |
| 3369 |
} |
| 3370 |
|
| 3371 |
RefSetCache.prototype = { |
| 3372 |
get: function RefSetCache_get(ref) { |
| 3373 |
return this.dict[ref.toString()]; |
| 3374 |
}, |
| 3375 |
|
| 3376 |
has: function RefSetCache_has(ref) { |
| 3377 |
return ref.toString() in this.dict; |
| 3378 |
}, |
| 3379 |
|
| 3380 |
put: function RefSetCache_put(ref, obj) { |
| 3381 |
this.dict[ref.toString()] = obj; |
| 3382 |
}, |
| 3383 |
|
| 3384 |
putAlias: function RefSetCache_putAlias(ref, aliasRef) { |
| 3385 |
this.dict[ref.toString()] = this.get(aliasRef); |
| 3386 |
}, |
| 3387 |
|
| 3388 |
forEach: function RefSetCache_forEach(fn, thisArg) { |
| 3389 |
for (var i in this.dict) { |
| 3390 |
fn.call(thisArg, this.dict[i]); |
| 3391 |
} |
| 3392 |
}, |
| 3393 |
|
| 3394 |
clear: function RefSetCache_clear() { |
| 3395 |
this.dict = Object.create(null); |
| 3396 |
} |
| 3397 |
}; |
| 3398 |
|
| 3399 |
return RefSetCache; |
| 3400 |
})(); |
| 3401 |
|
| 3402 |
var Catalog = (function CatalogClosure() { |
| 3403 |
function Catalog(pdfManager, xref) { |
| 3404 |
this.pdfManager = pdfManager; |
| 3405 |
this.xref = xref; |
| 3406 |
this.catDict = xref.getCatalogObj(); |
| 3407 |
this.fontCache = new RefSetCache(); |
| 3408 |
assert(isDict(this.catDict), |
| 3409 |
'catalog object is not a dictionary'); |
| 3410 |
|
| 3411 |
this.pagePromises = []; |
| 3412 |
} |
| 3413 |
|
| 3414 |
Catalog.prototype = { |
| 3415 |
get metadata() { |
| 3416 |
var streamRef = this.catDict.getRaw('Metadata'); |
| 3417 |
if (!isRef(streamRef)) { |
| 3418 |
return shadow(this, 'metadata', null); |
| 3419 |
} |
| 3420 |
|
| 3421 |
var encryptMetadata = (!this.xref.encrypt ? false : |
| 3422 |
this.xref.encrypt.encryptMetadata); |
| 3423 |
|
| 3424 |
var stream = this.xref.fetch(streamRef, !encryptMetadata); |
| 3425 |
var metadata; |
| 3426 |
if (stream && isDict(stream.dict)) { |
| 3427 |
var type = stream.dict.get('Type'); |
| 3428 |
var subtype = stream.dict.get('Subtype'); |
| 3429 |
|
| 3430 |
if (isName(type) && isName(subtype) && |
| 3431 |
type.name === 'Metadata' && subtype.name === 'XML') { |
| 3432 |
// XXX: This should examine the charset the XML document defines, |
| 3433 |
// however since there are currently no real means to decode |
| 3434 |
// arbitrary charsets, let's just hope that the author of the PDF |
| 3435 |
// was reasonable enough to stick with the XML default charset, |
| 3436 |
// which is UTF-8. |
| 3437 |
try { |
| 3438 |
metadata = stringToUTF8String(bytesToString(stream.getBytes())); |
| 3439 |
} catch (e) { |
| 3440 |
info('Skipping invalid metadata.'); |
| 3441 |
} |
| 3442 |
} |
| 3443 |
} |
| 3444 |
|
| 3445 |
return shadow(this, 'metadata', metadata); |
| 3446 |
}, |
| 3447 |
get toplevelPagesDict() { |
| 3448 |
var pagesObj = this.catDict.get('Pages'); |
| 3449 |
assert(isDict(pagesObj), 'invalid top-level pages dictionary'); |
| 3450 |
// shadow the prototype getter |
| 3451 |
return shadow(this, 'toplevelPagesDict', pagesObj); |
| 3452 |
}, |
| 3453 |
get documentOutline() { |
| 3454 |
var obj = null; |
| 3455 |
try { |
| 3456 |
obj = this.readDocumentOutline(); |
| 3457 |
} catch (ex) { |
| 3458 |
if (ex instanceof MissingDataException) { |
| 3459 |
throw ex; |
| 3460 |
} |
| 3461 |
warn('Unable to read document outline'); |
| 3462 |
} |
| 3463 |
return shadow(this, 'documentOutline', obj); |
| 3464 |
}, |
| 3465 |
readDocumentOutline: function Catalog_readDocumentOutline() { |
| 3466 |
var xref = this.xref; |
| 3467 |
var obj = this.catDict.get('Outlines'); |
| 3468 |
var root = { items: [] }; |
| 3469 |
if (isDict(obj)) { |
| 3470 |
obj = obj.getRaw('First'); |
| 3471 |
var processed = new RefSet(); |
| 3472 |
if (isRef(obj)) { |
| 3473 |
var queue = [{obj: obj, parent: root}]; |
| 3474 |
// to avoid recursion keeping track of the items |
| 3475 |
// in the processed dictionary |
| 3476 |
processed.put(obj); |
| 3477 |
while (queue.length > 0) { |
| 3478 |
var i = queue.shift(); |
| 3479 |
var outlineDict = xref.fetchIfRef(i.obj); |
| 3480 |
if (outlineDict === null) { |
| 3481 |
continue; |
| 3482 |
} |
| 3483 |
if (!outlineDict.has('Title')) { |
| 3484 |
error('Invalid outline item'); |
| 3485 |
} |
| 3486 |
var dest = outlineDict.get('A'); |
| 3487 |
if (dest) { |
| 3488 |
dest = dest.get('D'); |
| 3489 |
} else if (outlineDict.has('Dest')) { |
| 3490 |
dest = outlineDict.getRaw('Dest'); |
| 3491 |
if (isName(dest)) { |
| 3492 |
dest = dest.name; |
| 3493 |
} |
| 3494 |
} |
| 3495 |
var title = outlineDict.get('Title'); |
| 3496 |
var outlineItem = { |
| 3497 |
dest: dest, |
| 3498 |
title: stringToPDFString(title), |
| 3499 |
color: outlineDict.get('C') || [0, 0, 0], |
| 3500 |
count: outlineDict.get('Count'), |
| 3501 |
bold: !!(outlineDict.get('F') & 2), |
| 3502 |
italic: !!(outlineDict.get('F') & 1), |
| 3503 |
items: [] |
| 3504 |
}; |
| 3505 |
i.parent.items.push(outlineItem); |
| 3506 |
obj = outlineDict.getRaw('First'); |
| 3507 |
if (isRef(obj) && !processed.has(obj)) { |
| 3508 |
queue.push({obj: obj, parent: outlineItem}); |
| 3509 |
processed.put(obj); |
| 3510 |
} |
| 3511 |
obj = outlineDict.getRaw('Next'); |
| 3512 |
if (isRef(obj) && !processed.has(obj)) { |
| 3513 |
queue.push({obj: obj, parent: i.parent}); |
| 3514 |
processed.put(obj); |
| 3515 |
} |
| 3516 |
} |
| 3517 |
} |
| 3518 |
} |
| 3519 |
return (root.items.length > 0 ? root.items : null); |
| 3520 |
}, |
| 3521 |
get numPages() { |
| 3522 |
var obj = this.toplevelPagesDict.get('Count'); |
| 3523 |
assert( |
| 3524 |
isInt(obj), |
| 3525 |
'page count in top level pages object is not an integer' |
| 3526 |
); |
| 3527 |
// shadow the prototype getter |
| 3528 |
return shadow(this, 'num', obj); |
| 3529 |
}, |
| 3530 |
get destinations() { |
| 3531 |
function fetchDestination(dest) { |
| 3532 |
return isDict(dest) ? dest.get('D') : dest; |
| 3533 |
} |
| 3534 |
|
| 3535 |
var xref = this.xref; |
| 3536 |
var dests = {}, nameTreeRef, nameDictionaryRef; |
| 3537 |
var obj = this.catDict.get('Names'); |
| 3538 |
if (obj && obj.has('Dests')) { |
| 3539 |
nameTreeRef = obj.getRaw('Dests'); |
| 3540 |
} else if (this.catDict.has('Dests')) { |
| 3541 |
nameDictionaryRef = this.catDict.get('Dests'); |
| 3542 |
} |
| 3543 |
|
| 3544 |
if (nameDictionaryRef) { |
| 3545 |
// reading simple destination dictionary |
| 3546 |
obj = nameDictionaryRef; |
| 3547 |
obj.forEach(function catalogForEach(key, value) { |
| 3548 |
if (!value) { |
| 3549 |
return; |
| 3550 |
} |
| 3551 |
dests[key] = fetchDestination(value); |
| 3552 |
}); |
| 3553 |
} |
| 3554 |
if (nameTreeRef) { |
| 3555 |
var nameTree = new NameTree(nameTreeRef, xref); |
| 3556 |
var names = nameTree.getAll(); |
| 3557 |
for (var name in names) { |
| 3558 |
if (!names.hasOwnProperty(name)) { |
| 3559 |
continue; |
| 3560 |
} |
| 3561 |
dests[name] = fetchDestination(names[name]); |
| 3562 |
} |
| 3563 |
} |
| 3564 |
return shadow(this, 'destinations', dests); |
| 3565 |
}, |
| 3566 |
getDestination: function Catalog_getDestination(destinationId) { |
| 3567 |
function fetchDestination(dest) { |
| 3568 |
return isDict(dest) ? dest.get('D') : dest; |
| 3569 |
} |
| 3570 |
|
| 3571 |
var xref = this.xref; |
| 3572 |
var dest, nameTreeRef, nameDictionaryRef; |
| 3573 |
var obj = this.catDict.get('Names'); |
| 3574 |
if (obj && obj.has('Dests')) { |
| 3575 |
nameTreeRef = obj.getRaw('Dests'); |
| 3576 |
} else if (this.catDict.has('Dests')) { |
| 3577 |
nameDictionaryRef = this.catDict.get('Dests'); |
| 3578 |
} |
| 3579 |
|
| 3580 |
if (nameDictionaryRef) { |
| 3581 |
// reading simple destination dictionary |
| 3582 |
obj = nameDictionaryRef; |
| 3583 |
obj.forEach(function catalogForEach(key, value) { |
| 3584 |
if (!value) { |
| 3585 |
return; |
| 3586 |
} |
| 3587 |
if (key === destinationId) { |
| 3588 |
dest = fetchDestination(value); |
| 3589 |
} |
| 3590 |
}); |
| 3591 |
} |
| 3592 |
if (nameTreeRef) { |
| 3593 |
var nameTree = new NameTree(nameTreeRef, xref); |
| 3594 |
dest = fetchDestination(nameTree.get(destinationId)); |
| 3595 |
} |
| 3596 |
return dest; |
| 3597 |
}, |
| 3598 |
get attachments() { |
| 3599 |
var xref = this.xref; |
| 3600 |
var attachments = null, nameTreeRef; |
| 3601 |
var obj = this.catDict.get('Names'); |
| 3602 |
if (obj) { |
| 3603 |
nameTreeRef = obj.getRaw('EmbeddedFiles'); |
| 3604 |
} |
| 3605 |
|
| 3606 |
if (nameTreeRef) { |
| 3607 |
var nameTree = new NameTree(nameTreeRef, xref); |
| 3608 |
var names = nameTree.getAll(); |
| 3609 |
for (var name in names) { |
| 3610 |
if (!names.hasOwnProperty(name)) { |
| 3611 |
continue; |
| 3612 |
} |
| 3613 |
var fs = new FileSpec(names[name], xref); |
| 3614 |
if (!attachments) { |
| 3615 |
attachments = {}; |
| 3616 |
} |
| 3617 |
attachments[stringToPDFString(name)] = fs.serializable; |
| 3618 |
} |
| 3619 |
} |
| 3620 |
return shadow(this, 'attachments', attachments); |
| 3621 |
}, |
| 3622 |
get javaScript() { |
| 3623 |
var xref = this.xref; |
| 3624 |
var obj = this.catDict.get('Names'); |
| 3625 |
|
| 3626 |
var javaScript = []; |
| 3627 |
if (obj && obj.has('JavaScript')) { |
| 3628 |
var nameTree = new NameTree(obj.getRaw('JavaScript'), xref); |
| 3629 |
var names = nameTree.getAll(); |
| 3630 |
for (var name in names) { |
| 3631 |
if (!names.hasOwnProperty(name)) { |
| 3632 |
continue; |
| 3633 |
} |
| 3634 |
// We don't really use the JavaScript right now. This code is |
| 3635 |
// defensive so we don't cause errors on document load. |
| 3636 |
var jsDict = names[name]; |
| 3637 |
if (!isDict(jsDict)) { |
| 3638 |
continue; |
| 3639 |
} |
| 3640 |
var type = jsDict.get('S'); |
| 3641 |
if (!isName(type) || type.name !== 'JavaScript') { |
| 3642 |
continue; |
| 3643 |
} |
| 3644 |
var js = jsDict.get('JS'); |
| 3645 |
if (!isString(js) && !isStream(js)) { |
| 3646 |
continue; |
| 3647 |
} |
| 3648 |
if (isStream(js)) { |
| 3649 |
js = bytesToString(js.getBytes()); |
| 3650 |
} |
| 3651 |
javaScript.push(stringToPDFString(js)); |
| 3652 |
} |
| 3653 |
} |
| 3654 |
|
| 3655 |
// Append OpenAction actions to javaScript array |
| 3656 |
var openactionDict = this.catDict.get('OpenAction'); |
| 3657 |
if (isDict(openactionDict)) { |
| 3658 |
var objType = openactionDict.get('Type'); |
| 3659 |
var actionType = openactionDict.get('S'); |
| 3660 |
var action = openactionDict.get('N'); |
| 3661 |
var isPrintAction = (isName(objType) && objType.name === 'Action' && |
| 3662 |
isName(actionType) && actionType.name === 'Named' && |
| 3663 |
isName(action) && action.name === 'Print'); |
| 3664 |
|
| 3665 |
if (isPrintAction) { |
| 3666 |
javaScript.push('print(true);'); |
| 3667 |
} |
| 3668 |
} |
| 3669 |
|
| 3670 |
return shadow(this, 'javaScript', javaScript); |
| 3671 |
}, |
| 3672 |
|
| 3673 |
cleanup: function Catalog_cleanup() { |
| 3674 |
var promises = []; |
| 3675 |
this.fontCache.forEach(function (promise) { |
| 3676 |
promises.push(promise); |
| 3677 |
}); |
| 3678 |
return Promise.all(promises).then(function (translatedFonts) { |
| 3679 |
for (var i = 0, ii = translatedFonts.length; i < ii; i++) { |
| 3680 |
var font = translatedFonts[i].dict; |
| 3681 |
delete font.translated; |
| 3682 |
} |
| 3683 |
this.fontCache.clear(); |
| 3684 |
}.bind(this)); |
| 3685 |
}, |
| 3686 |
|
| 3687 |
getPage: function Catalog_getPage(pageIndex) { |
| 3688 |
if (!(pageIndex in this.pagePromises)) { |
| 3689 |
this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then( |
| 3690 |
function (a) { |
| 3691 |
var dict = a[0]; |
| 3692 |
var ref = a[1]; |
| 3693 |
return new Page(this.pdfManager, this.xref, pageIndex, dict, ref, |
| 3694 |
this.fontCache); |
| 3695 |
}.bind(this) |
| 3696 |
); |
| 3697 |
} |
| 3698 |
return this.pagePromises[pageIndex]; |
| 3699 |
}, |
| 3700 |
|
| 3701 |
getPageDict: function Catalog_getPageDict(pageIndex) { |
| 3702 |
var capability = createPromiseCapability(); |
| 3703 |
var nodesToVisit = [this.catDict.getRaw('Pages')]; |
| 3704 |
var currentPageIndex = 0; |
| 3705 |
var xref = this.xref; |
| 3706 |
var checkAllKids = false; |
| 3707 |
|
| 3708 |
function next() { |
| 3709 |
while (nodesToVisit.length) { |
| 3710 |
var currentNode = nodesToVisit.pop(); |
| 3711 |
|
| 3712 |
if (isRef(currentNode)) { |
| 3713 |
xref.fetchAsync(currentNode).then(function (obj) { |
| 3714 |
if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) { |
| 3715 |
if (pageIndex === currentPageIndex) { |
| 3716 |
capability.resolve([obj, currentNode]); |
| 3717 |
} else { |
| 3718 |
currentPageIndex++; |
| 3719 |
next(); |
| 3720 |
} |
| 3721 |
return; |
| 3722 |
} |
| 3723 |
nodesToVisit.push(obj); |
| 3724 |
next(); |
| 3725 |
}, capability.reject); |
| 3726 |
return; |
| 3727 |
} |
| 3728 |
|
| 3729 |
// Must be a child page dictionary. |
| 3730 |
assert( |
| 3731 |
isDict(currentNode), |
| 3732 |
'page dictionary kid reference points to wrong type of object' |
| 3733 |
); |
| 3734 |
var count = currentNode.get('Count'); |
| 3735 |
// If the current node doesn't have any children, avoid getting stuck |
| 3736 |
// in an empty node further down in the tree (see issue5644.pdf). |
| 3737 |
if (count === 0) { |
| 3738 |
checkAllKids = true; |
| 3739 |
} |
| 3740 |
// Skip nodes where the page can't be. |
| 3741 |
if (currentPageIndex + count <= pageIndex) { |
| 3742 |
currentPageIndex += count; |
| 3743 |
continue; |
| 3744 |
} |
| 3745 |
|
| 3746 |
var kids = currentNode.get('Kids'); |
| 3747 |
assert(isArray(kids), 'page dictionary kids object is not an array'); |
| 3748 |
if (!checkAllKids && count === kids.length) { |
| 3749 |
// Nodes that don't have the page have been skipped and this is the |
| 3750 |
// bottom of the tree which means the page requested must be a |
| 3751 |
// descendant of this pages node. Ideally we would just resolve the |
| 3752 |
// promise with the page ref here, but there is the case where more |
| 3753 |
// pages nodes could link to single a page (see issue 3666 pdf). To |
| 3754 |
// handle this push it back on the queue so if it is a pages node it |
| 3755 |
// will be descended into. |
| 3756 |
nodesToVisit = [kids[pageIndex - currentPageIndex]]; |
| 3757 |
currentPageIndex = pageIndex; |
| 3758 |
continue; |
| 3759 |
} else { |
| 3760 |
for (var last = kids.length - 1; last >= 0; last--) { |
| 3761 |
nodesToVisit.push(kids[last]); |
| 3762 |
} |
| 3763 |
} |
| 3764 |
} |
| 3765 |
capability.reject('Page index ' + pageIndex + ' not found.'); |
| 3766 |
} |
| 3767 |
next(); |
| 3768 |
return capability.promise; |
| 3769 |
}, |
| 3770 |
|
| 3771 |
getPageIndex: function Catalog_getPageIndex(ref) { |
| 3772 |
// The page tree nodes have the count of all the leaves below them. To get |
| 3773 |
// how many pages are before we just have to walk up the tree and keep |
| 3774 |
// adding the count of siblings to the left of the node. |
| 3775 |
var xref = this.xref; |
| 3776 |
function pagesBeforeRef(kidRef) { |
| 3777 |
var total = 0; |
| 3778 |
var parentRef; |
| 3779 |
return xref.fetchAsync(kidRef).then(function (node) { |
| 3780 |
if (!node) { |
| 3781 |
return null; |
| 3782 |
} |
| 3783 |
parentRef = node.getRaw('Parent'); |
| 3784 |
return node.getAsync('Parent'); |
| 3785 |
}).then(function (parent) { |
| 3786 |
if (!parent) { |
| 3787 |
return null; |
| 3788 |
} |
| 3789 |
return parent.getAsync('Kids'); |
| 3790 |
}).then(function (kids) { |
| 3791 |
if (!kids) { |
| 3792 |
return null; |
| 3793 |
} |
| 3794 |
var kidPromises = []; |
| 3795 |
var found = false; |
| 3796 |
for (var i = 0; i < kids.length; i++) { |
| 3797 |
var kid = kids[i]; |
| 3798 |
assert(isRef(kid), 'kids must be a ref'); |
| 3799 |
if (kid.num === kidRef.num) { |
| 3800 |
found = true; |
| 3801 |
break; |
| 3802 |
} |
| 3803 |
kidPromises.push(xref.fetchAsync(kid).then(function (kid) { |
| 3804 |
if (kid.has('Count')) { |
| 3805 |
var count = kid.get('Count'); |
| 3806 |
total += count; |
| 3807 |
} else { // page leaf node |
| 3808 |
total++; |
| 3809 |
} |
| 3810 |
})); |
| 3811 |
} |
| 3812 |
if (!found) { |
| 3813 |
error('kid ref not found in parents kids'); |
| 3814 |
} |
| 3815 |
return Promise.all(kidPromises).then(function () { |
| 3816 |
return [total, parentRef]; |
| 3817 |
}); |
| 3818 |
}); |
| 3819 |
} |
| 3820 |
|
| 3821 |
var total = 0; |
| 3822 |
function next(ref) { |
| 3823 |
return pagesBeforeRef(ref).then(function (args) { |
| 3824 |
if (!args) { |
| 3825 |
return total; |
| 3826 |
} |
| 3827 |
var count = args[0]; |
| 3828 |
var parentRef = args[1]; |
| 3829 |
total += count; |
| 3830 |
return next(parentRef); |
| 3831 |
}); |
| 3832 |
} |
| 3833 |
|
| 3834 |
return next(ref); |
| 3835 |
} |
| 3836 |
}; |
| 3837 |
|
| 3838 |
return Catalog; |
| 3839 |
})(); |
| 3840 |
|
| 3841 |
var XRef = (function XRefClosure() { |
| 3842 |
function XRef(stream, password) { |
| 3843 |
this.stream = stream; |
| 3844 |
this.entries = []; |
| 3845 |
this.xrefstms = {}; |
| 3846 |
// prepare the XRef cache |
| 3847 |
this.cache = []; |
| 3848 |
this.password = password; |
| 3849 |
this.stats = { |
| 3850 |
streamTypes: [], |
| 3851 |
fontTypes: [] |
| 3852 |
}; |
| 3853 |
} |
| 3854 |
|
| 3855 |
XRef.prototype = { |
| 3856 |
setStartXRef: function XRef_setStartXRef(startXRef) { |
| 3857 |
// Store the starting positions of xref tables as we process them |
| 3858 |
// so we can recover from missing data errors |
| 3859 |
this.startXRefQueue = [startXRef]; |
| 3860 |
}, |
| 3861 |
|
| 3862 |
parse: function XRef_parse(recoveryMode) { |
| 3863 |
var trailerDict; |
| 3864 |
if (!recoveryMode) { |
| 3865 |
trailerDict = this.readXRef(); |
| 3866 |
} else { |
| 3867 |
warn('Indexing all PDF objects'); |
| 3868 |
trailerDict = this.indexObjects(); |
| 3869 |
} |
| 3870 |
trailerDict.assignXref(this); |
| 3871 |
this.trailer = trailerDict; |
| 3872 |
var encrypt = trailerDict.get('Encrypt'); |
| 3873 |
if (encrypt) { |
| 3874 |
var ids = trailerDict.get('ID'); |
| 3875 |
var fileId = (ids && ids.length) ? ids[0] : ''; |
| 3876 |
this.encrypt = new CipherTransformFactory(encrypt, fileId, |
| 3877 |
this.password); |
| 3878 |
} |
| 3879 |
|
| 3880 |
// get the root dictionary (catalog) object |
| 3881 |
if (!(this.root = trailerDict.get('Root'))) { |
| 3882 |
error('Invalid root reference'); |
| 3883 |
} |
| 3884 |
}, |
| 3885 |
|
| 3886 |
processXRefTable: function XRef_processXRefTable(parser) { |
| 3887 |
if (!('tableState' in this)) { |
| 3888 |
// Stores state of the table as we process it so we can resume |
| 3889 |
// from middle of table in case of missing data error |
| 3890 |
this.tableState = { |
| 3891 |
entryNum: 0, |
| 3892 |
streamPos: parser.lexer.stream.pos, |
| 3893 |
parserBuf1: parser.buf1, |
| 3894 |
parserBuf2: parser.buf2 |
| 3895 |
}; |
| 3896 |
} |
| 3897 |
|
| 3898 |
var obj = this.readXRefTable(parser); |
| 3899 |
|
| 3900 |
// Sanity check |
| 3901 |
if (!isCmd(obj, 'trailer')) { |
| 3902 |
error('Invalid XRef table: could not find trailer dictionary'); |
| 3903 |
} |
| 3904 |
// Read trailer dictionary, e.g. |
| 3905 |
// trailer |
| 3906 |
// << /Size 22 |
| 3907 |
// /Root 20R |
| 3908 |
// /Info 10R |
| 3909 |
// /ID [ <81b14aafa313db63dbd6f981e49f94f4> ] |
| 3910 |
// >> |
| 3911 |
// The parser goes through the entire stream << ... >> and provides |
| 3912 |
// a getter interface for the key-value table |
| 3913 |
var dict = parser.getObj(); |
| 3914 |
|
| 3915 |
// The pdflib PDF generator can generate a nested trailer dictionary |
| 3916 |
if (!isDict(dict) && dict.dict) { |
| 3917 |
dict = dict.dict; |
| 3918 |
} |
| 3919 |
if (!isDict(dict)) { |
| 3920 |
error('Invalid XRef table: could not parse trailer dictionary'); |
| 3921 |
} |
| 3922 |
delete this.tableState; |
| 3923 |
|
| 3924 |
return dict; |
| 3925 |
}, |
| 3926 |
|
| 3927 |
readXRefTable: function XRef_readXRefTable(parser) { |
| 3928 |
// Example of cross-reference table: |
| 3929 |
// xref |
| 3930 |
// 0 1 <-- subsection header (first obj #, obj count) |
| 3931 |
// 0000000000 65535 f <-- actual object (offset, generation #, f/n) |
| 3932 |
// 23 2 <-- subsection header ... and so on ... |
| 3933 |
// 0000025518 00002 n |
| 3934 |
// 0000025635 00000 n |
| 3935 |
// trailer |
| 3936 |
// ... |
| 3937 |
|
| 3938 |
var stream = parser.lexer.stream; |
| 3939 |
var tableState = this.tableState; |
| 3940 |
stream.pos = tableState.streamPos; |
| 3941 |
parser.buf1 = tableState.parserBuf1; |
| 3942 |
parser.buf2 = tableState.parserBuf2; |
| 3943 |
|
| 3944 |
// Outer loop is over subsection headers |
| 3945 |
var obj; |
| 3946 |
|
| 3947 |
while (true) { |
| 3948 |
if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) { |
| 3949 |
if (isCmd(obj = parser.getObj(), 'trailer')) { |
| 3950 |
break; |
| 3951 |
} |
| 3952 |
tableState.firstEntryNum = obj; |
| 3953 |
tableState.entryCount = parser.getObj(); |
| 3954 |
} |
| 3955 |
|
| 3956 |
var first = tableState.firstEntryNum; |
| 3957 |
var count = tableState.entryCount; |
| 3958 |
if (!isInt(first) || !isInt(count)) { |
| 3959 |
error('Invalid XRef table: wrong types in subsection header'); |
| 3960 |
} |
| 3961 |
// Inner loop is over objects themselves |
| 3962 |
for (var i = tableState.entryNum; i < count; i++) { |
| 3963 |
tableState.streamPos = stream.pos; |
| 3964 |
tableState.entryNum = i; |
| 3965 |
tableState.parserBuf1 = parser.buf1; |
| 3966 |
tableState.parserBuf2 = parser.buf2; |
| 3967 |
|
| 3968 |
var entry = {}; |
| 3969 |
entry.offset = parser.getObj(); |
| 3970 |
entry.gen = parser.getObj(); |
| 3971 |
var type = parser.getObj(); |
| 3972 |
|
| 3973 |
if (isCmd(type, 'f')) { |
| 3974 |
entry.free = true; |
| 3975 |
} else if (isCmd(type, 'n')) { |
| 3976 |
entry.uncompressed = true; |
| 3977 |
} |
| 3978 |
|
| 3979 |
// Validate entry obj |
| 3980 |
if (!isInt(entry.offset) || !isInt(entry.gen) || |
| 3981 |
!(entry.free || entry.uncompressed)) { |
| 3982 |
error('Invalid entry in XRef subsection: ' + first + ', ' + count); |
| 3983 |
} |
| 3984 |
|
| 3985 |
if (!this.entries[i + first]) { |
| 3986 |
this.entries[i + first] = entry; |
| 3987 |
} |
| 3988 |
} |
| 3989 |
|
| 3990 |
tableState.entryNum = 0; |
| 3991 |
tableState.streamPos = stream.pos; |
| 3992 |
tableState.parserBuf1 = parser.buf1; |
| 3993 |
tableState.parserBuf2 = parser.buf2; |
| 3994 |
delete tableState.firstEntryNum; |
| 3995 |
delete tableState.entryCount; |
| 3996 |
} |
| 3997 |
|
| 3998 |
// Per issue 3248: hp scanners generate bad XRef |
| 3999 |
if (first === 1 && this.entries[1] && this.entries[1].free) { |
| 4000 |
// shifting the entries |
| 4001 |
this.entries.shift(); |
| 4002 |
} |
| 4003 |
|
| 4004 |
// Sanity check: as per spec, first object must be free |
| 4005 |
if (this.entries[0] && !this.entries[0].free) { |
| 4006 |
error('Invalid XRef table: unexpected first object'); |
| 4007 |
} |
| 4008 |
return obj; |
| 4009 |
}, |
| 4010 |
|
| 4011 |
processXRefStream: function XRef_processXRefStream(stream) { |
| 4012 |
if (!('streamState' in this)) { |
| 4013 |
// Stores state of the stream as we process it so we can resume |
| 4014 |
// from middle of stream in case of missing data error |
| 4015 |
var streamParameters = stream.dict; |
| 4016 |
var byteWidths = streamParameters.get('W'); |
| 4017 |
var range = streamParameters.get('Index'); |
| 4018 |
if (!range) { |
| 4019 |
range = [0, streamParameters.get('Size')]; |
| 4020 |
} |
| 4021 |
|
| 4022 |
this.streamState = { |
| 4023 |
entryRanges: range, |
| 4024 |
byteWidths: byteWidths, |
| 4025 |
entryNum: 0, |
| 4026 |
streamPos: stream.pos |
| 4027 |
}; |
| 4028 |
} |
| 4029 |
this.readXRefStream(stream); |
| 4030 |
delete this.streamState; |
| 4031 |
|
| 4032 |
return stream.dict; |
| 4033 |
}, |
| 4034 |
|
| 4035 |
readXRefStream: function XRef_readXRefStream(stream) { |
| 4036 |
var i, j; |
| 4037 |
var streamState = this.streamState; |
| 4038 |
stream.pos = streamState.streamPos; |
| 4039 |
|
| 4040 |
var byteWidths = streamState.byteWidths; |
| 4041 |
var typeFieldWidth = byteWidths[0]; |
| 4042 |
var offsetFieldWidth = byteWidths[1]; |
| 4043 |
var generationFieldWidth = byteWidths[2]; |
| 4044 |
|
| 4045 |
var entryRanges = streamState.entryRanges; |
| 4046 |
while (entryRanges.length > 0) { |
| 4047 |
var first = entryRanges[0]; |
| 4048 |
var n = entryRanges[1]; |
| 4049 |
|
| 4050 |
if (!isInt(first) || !isInt(n)) { |
| 4051 |
error('Invalid XRef range fields: ' + first + ', ' + n); |
| 4052 |
} |
| 4053 |
if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) || |
| 4054 |
!isInt(generationFieldWidth)) { |
| 4055 |
error('Invalid XRef entry fields length: ' + first + ', ' + n); |
| 4056 |
} |
| 4057 |
for (i = streamState.entryNum; i < n; ++i) { |
| 4058 |
streamState.entryNum = i; |
| 4059 |
streamState.streamPos = stream.pos; |
| 4060 |
|
| 4061 |
var type = 0, offset = 0, generation = 0; |
| 4062 |
for (j = 0; j < typeFieldWidth; ++j) { |
| 4063 |
type = (type << 8) | stream.getByte(); |
| 4064 |
} |
| 4065 |
// if type field is absent, its default value is 1 |
| 4066 |
if (typeFieldWidth === 0) { |
| 4067 |
type = 1; |
| 4068 |
} |
| 4069 |
for (j = 0; j < offsetFieldWidth; ++j) { |
| 4070 |
offset = (offset << 8) | stream.getByte(); |
| 4071 |
} |
| 4072 |
for (j = 0; j < generationFieldWidth; ++j) { |
| 4073 |
generation = (generation << 8) | stream.getByte(); |
| 4074 |
} |
| 4075 |
var entry = {}; |
| 4076 |
entry.offset = offset; |
| 4077 |
entry.gen = generation; |
| 4078 |
switch (type) { |
| 4079 |
case 0: |
| 4080 |
entry.free = true; |
| 4081 |
break; |
| 4082 |
case 1: |
| 4083 |
entry.uncompressed = true; |
| 4084 |
break; |
| 4085 |
case 2: |
| 4086 |
break; |
| 4087 |
default: |
| 4088 |
error('Invalid XRef entry type: ' + type); |
| 4089 |
} |
| 4090 |
if (!this.entries[first + i]) { |
| 4091 |
this.entries[first + i] = entry; |
| 4092 |
} |
| 4093 |
} |
| 4094 |
|
| 4095 |
streamState.entryNum = 0; |
| 4096 |
streamState.streamPos = stream.pos; |
| 4097 |
entryRanges.splice(0, 2); |
| 4098 |
} |
| 4099 |
}, |
| 4100 |
|
| 4101 |
indexObjects: function XRef_indexObjects() { |
| 4102 |
// Simple scan through the PDF content to find objects, |
| 4103 |
// trailers and XRef streams. |
| 4104 |
function readToken(data, offset) { |
| 4105 |
var token = '', ch = data[offset]; |
| 4106 |
while (ch !== 13 && ch !== 10) { |
| 4107 |
if (++offset >= data.length) { |
| 4108 |
break; |
| 4109 |
} |
| 4110 |
token += String.fromCharCode(ch); |
| 4111 |
ch = data[offset]; |
| 4112 |
} |
| 4113 |
return token; |
| 4114 |
} |
| 4115 |
function skipUntil(data, offset, what) { |
| 4116 |
var length = what.length, dataLength = data.length; |
| 4117 |
var skipped = 0; |
| 4118 |
// finding byte sequence |
| 4119 |
while (offset < dataLength) { |
| 4120 |
var i = 0; |
| 4121 |
while (i < length && data[offset + i] === what[i]) { |
| 4122 |
++i; |
| 4123 |
} |
| 4124 |
if (i >= length) { |
| 4125 |
break; // sequence found |
| 4126 |
} |
| 4127 |
offset++; |
| 4128 |
skipped++; |
| 4129 |
} |
| 4130 |
return skipped; |
| 4131 |
} |
| 4132 |
var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]); |
| 4133 |
var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, |
| 4134 |
101, 102]); |
| 4135 |
var endobjBytes = new Uint8Array([101, 110, 100, 111, 98, 106]); |
| 4136 |
var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]); |
| 4137 |
|
| 4138 |
var stream = this.stream; |
| 4139 |
stream.pos = 0; |
| 4140 |
var buffer = stream.getBytes(); |
| 4141 |
var position = stream.start, length = buffer.length; |
| 4142 |
var trailers = [], xrefStms = []; |
| 4143 |
while (position < length) { |
| 4144 |
var ch = buffer[position]; |
| 4145 |
if (ch === 32 || ch === 9 || ch === 13 || ch === 10) { |
| 4146 |
++position; |
| 4147 |
continue; |
| 4148 |
} |
| 4149 |
if (ch === 37) { // %-comment |
| 4150 |
do { |
| 4151 |
++position; |
| 4152 |
if (position >= length) { |
| 4153 |
break; |
| 4154 |
} |
| 4155 |
ch = buffer[position]; |
| 4156 |
} while (ch !== 13 && ch !== 10); |
| 4157 |
continue; |
| 4158 |
} |
| 4159 |
var token = readToken(buffer, position); |
| 4160 |
var m; |
| 4161 |
if (token === 'xref') { |
| 4162 |
position += skipUntil(buffer, position, trailerBytes); |
| 4163 |
trailers.push(position); |
| 4164 |
position += skipUntil(buffer, position, startxrefBytes); |
| 4165 |
} else if ((m = /^(\d+)\s+(\d+)\s+obj\b/.exec(token))) { |
| 4166 |
this.entries[m[1]] = { |
| 4167 |
offset: position, |
| 4168 |
gen: m[2] | 0, |
| 4169 |
uncompressed: true |
| 4170 |
}; |
| 4171 |
|
| 4172 |
var contentLength = skipUntil(buffer, position, endobjBytes) + 7; |
| 4173 |
var content = buffer.subarray(position, position + contentLength); |
| 4174 |
|
| 4175 |
// checking XRef stream suspect |
| 4176 |
// (it shall have '/XRef' and next char is not a letter) |
| 4177 |
var xrefTagOffset = skipUntil(content, 0, xrefBytes); |
| 4178 |
if (xrefTagOffset < contentLength && |
| 4179 |
content[xrefTagOffset + 5] < 64) { |
| 4180 |
xrefStms.push(position); |
| 4181 |
this.xrefstms[position] = 1; // don't read it recursively |
| 4182 |
} |
| 4183 |
|
| 4184 |
position += contentLength; |
| 4185 |
} else { |
| 4186 |
position += token.length + 1; |
| 4187 |
} |
| 4188 |
} |
| 4189 |
// reading XRef streams |
| 4190 |
var i, ii; |
| 4191 |
for (i = 0, ii = xrefStms.length; i < ii; ++i) { |
| 4192 |
this.startXRefQueue.push(xrefStms[i]); |
| 4193 |
this.readXRef(/* recoveryMode */ true); |
| 4194 |
} |
| 4195 |
// finding main trailer |
| 4196 |
var dict; |
| 4197 |
for (i = 0, ii = trailers.length; i < ii; ++i) { |
| 4198 |
stream.pos = trailers[i]; |
| 4199 |
var parser = new Parser(new Lexer(stream), true, this); |
| 4200 |
var obj = parser.getObj(); |
| 4201 |
if (!isCmd(obj, 'trailer')) { |
| 4202 |
continue; |
| 4203 |
} |
| 4204 |
// read the trailer dictionary |
| 4205 |
if (!isDict(dict = parser.getObj())) { |
| 4206 |
continue; |
| 4207 |
} |
| 4208 |
// taking the first one with 'ID' |
| 4209 |
if (dict.has('ID')) { |
| 4210 |
return dict; |
| 4211 |
} |
| 4212 |
} |
| 4213 |
// no tailer with 'ID', taking last one (if exists) |
| 4214 |
if (dict) { |
| 4215 |
return dict; |
| 4216 |
} |
| 4217 |
// nothing helps |
| 4218 |
// calling error() would reject worker with an UnknownErrorException. |
| 4219 |
throw new InvalidPDFException('Invalid PDF structure'); |
| 4220 |
}, |
| 4221 |
|
| 4222 |
readXRef: function XRef_readXRef(recoveryMode) { |
| 4223 |
var stream = this.stream; |
| 4224 |
|
| 4225 |
try { |
| 4226 |
while (this.startXRefQueue.length) { |
| 4227 |
var startXRef = this.startXRefQueue[0]; |
| 4228 |
|
| 4229 |
stream.pos = startXRef + stream.start; |
| 4230 |
|
| 4231 |
var parser = new Parser(new Lexer(stream), true, this); |
| 4232 |
var obj = parser.getObj(); |
| 4233 |
var dict; |
| 4234 |
|
| 4235 |
// Get dictionary |
| 4236 |
if (isCmd(obj, 'xref')) { |
| 4237 |
// Parse end-of-file XRef |
| 4238 |
dict = this.processXRefTable(parser); |
| 4239 |
if (!this.topDict) { |
| 4240 |
this.topDict = dict; |
| 4241 |
} |
| 4242 |
|
| 4243 |
// Recursively get other XRefs 'XRefStm', if any |
| 4244 |
obj = dict.get('XRefStm'); |
| 4245 |
if (isInt(obj)) { |
| 4246 |
var pos = obj; |
| 4247 |
// ignore previously loaded xref streams |
| 4248 |
// (possible infinite recursion) |
| 4249 |
if (!(pos in this.xrefstms)) { |
| 4250 |
this.xrefstms[pos] = 1; |
| 4251 |
this.startXRefQueue.push(pos); |
| 4252 |
} |
| 4253 |
} |
| 4254 |
} else if (isInt(obj)) { |
| 4255 |
// Parse in-stream XRef |
| 4256 |
if (!isInt(parser.getObj()) || |
| 4257 |
!isCmd(parser.getObj(), 'obj') || |
| 4258 |
!isStream(obj = parser.getObj())) { |
| 4259 |
error('Invalid XRef stream'); |
| 4260 |
} |
| 4261 |
dict = this.processXRefStream(obj); |
| 4262 |
if (!this.topDict) { |
| 4263 |
this.topDict = dict; |
| 4264 |
} |
| 4265 |
if (!dict) { |
| 4266 |
error('Failed to read XRef stream'); |
| 4267 |
} |
| 4268 |
} else { |
| 4269 |
error('Invalid XRef stream header'); |
| 4270 |
} |
| 4271 |
|
| 4272 |
// Recursively get previous dictionary, if any |
| 4273 |
obj = dict.get('Prev'); |
| 4274 |
if (isInt(obj)) { |
| 4275 |
this.startXRefQueue.push(obj); |
| 4276 |
} else if (isRef(obj)) { |
| 4277 |
// The spec says Prev must not be a reference, i.e. "/Prev NNN" |
| 4278 |
// This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R" |
| 4279 |
this.startXRefQueue.push(obj.num); |
| 4280 |
} |
| 4281 |
|
| 4282 |
this.startXRefQueue.shift(); |
| 4283 |
} |
| 4284 |
|
| 4285 |
return this.topDict; |
| 4286 |
} catch (e) { |
| 4287 |
if (e instanceof MissingDataException) { |
| 4288 |
throw e; |
| 4289 |
} |
| 4290 |
info('(while reading XRef): ' + e); |
| 4291 |
} |
| 4292 |
|
| 4293 |
if (recoveryMode) { |
| 4294 |
return; |
| 4295 |
} |
| 4296 |
throw new XRefParseException(); |
| 4297 |
}, |
| 4298 |
|
| 4299 |
getEntry: function XRef_getEntry(i) { |
| 4300 |
var xrefEntry = this.entries[i]; |
| 4301 |
if (xrefEntry && !xrefEntry.free && xrefEntry.offset) { |
| 4302 |
return xrefEntry; |
| 4303 |
} |
| 4304 |
return null; |
| 4305 |
}, |
| 4306 |
|
| 4307 |
fetchIfRef: function XRef_fetchIfRef(obj) { |
| 4308 |
if (!isRef(obj)) { |
| 4309 |
return obj; |
| 4310 |
} |
| 4311 |
return this.fetch(obj); |
| 4312 |
}, |
| 4313 |
|
| 4314 |
fetch: function XRef_fetch(ref, suppressEncryption) { |
| 4315 |
assert(isRef(ref), 'ref object is not a reference'); |
| 4316 |
var num = ref.num; |
| 4317 |
if (num in this.cache) { |
| 4318 |
var cacheEntry = this.cache[num]; |
| 4319 |
return cacheEntry; |
| 4320 |
} |
| 4321 |
|
| 4322 |
var xrefEntry = this.getEntry(num); |
| 4323 |
|
| 4324 |
// the referenced entry can be free |
| 4325 |
if (xrefEntry === null) { |
| 4326 |
return (this.cache[num] = null); |
| 4327 |
} |
| 4328 |
|
| 4329 |
if (xrefEntry.uncompressed) { |
| 4330 |
xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption); |
| 4331 |
} else { |
| 4332 |
xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption); |
| 4333 |
} |
| 4334 |
if (isDict(xrefEntry)){ |
| 4335 |
xrefEntry.objId = ref.toString(); |
| 4336 |
} else if (isStream(xrefEntry)) { |
| 4337 |
xrefEntry.dict.objId = ref.toString(); |
| 4338 |
} |
| 4339 |
return xrefEntry; |
| 4340 |
}, |
| 4341 |
|
| 4342 |
fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry, |
| 4343 |
suppressEncryption) { |
| 4344 |
var gen = ref.gen; |
| 4345 |
var num = ref.num; |
| 4346 |
if (xrefEntry.gen !== gen) { |
| 4347 |
error('inconsistent generation in XRef'); |
| 4348 |
} |
| 4349 |
var stream = this.stream.makeSubStream(xrefEntry.offset + |
| 4350 |
this.stream.start); |
| 4351 |
var parser = new Parser(new Lexer(stream), true, this); |
| 4352 |
var obj1 = parser.getObj(); |
| 4353 |
var obj2 = parser.getObj(); |
| 4354 |
var obj3 = parser.getObj(); |
| 4355 |
if (!isInt(obj1) || parseInt(obj1, 10) !== num || |
| 4356 |
!isInt(obj2) || parseInt(obj2, 10) !== gen || |
| 4357 |
!isCmd(obj3)) { |
| 4358 |
error('bad XRef entry'); |
| 4359 |
} |
| 4360 |
if (!isCmd(obj3, 'obj')) { |
| 4361 |
// some bad PDFs use "obj1234" and really mean 1234 |
| 4362 |
if (obj3.cmd.indexOf('obj') === 0) { |
| 4363 |
num = parseInt(obj3.cmd.substring(3), 10); |
| 4364 |
if (!isNaN(num)) { |
| 4365 |
return num; |
| 4366 |
} |
| 4367 |
} |
| 4368 |
error('bad XRef entry'); |
| 4369 |
} |
| 4370 |
if (this.encrypt && !suppressEncryption) { |
| 4371 |
xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen)); |
| 4372 |
} else { |
| 4373 |
xrefEntry = parser.getObj(); |
| 4374 |
} |
| 4375 |
if (!isStream(xrefEntry)) { |
| 4376 |
this.cache[num] = xrefEntry; |
| 4377 |
} |
| 4378 |
return xrefEntry; |
| 4379 |
}, |
| 4380 |
|
| 4381 |
fetchCompressed: function XRef_fetchCompressed(xrefEntry, |
| 4382 |
suppressEncryption) { |
| 4383 |
var tableOffset = xrefEntry.offset; |
| 4384 |
var stream = this.fetch(new Ref(tableOffset, 0)); |
| 4385 |
if (!isStream(stream)) { |
| 4386 |
error('bad ObjStm stream'); |
| 4387 |
} |
| 4388 |
var first = stream.dict.get('First'); |
| 4389 |
var n = stream.dict.get('N'); |
| 4390 |
if (!isInt(first) || !isInt(n)) { |
| 4391 |
error('invalid first and n parameters for ObjStm stream'); |
| 4392 |
} |
| 4393 |
var parser = new Parser(new Lexer(stream), false, this); |
| 4394 |
parser.allowStreams = true; |
| 4395 |
var i, entries = [], num, nums = []; |
| 4396 |
// read the object numbers to populate cache |
| 4397 |
for (i = 0; i < n; ++i) { |
| 4398 |
num = parser.getObj(); |
| 4399 |
if (!isInt(num)) { |
| 4400 |
error('invalid object number in the ObjStm stream: ' + num); |
| 4401 |
} |
| 4402 |
nums.push(num); |
| 4403 |
var offset = parser.getObj(); |
| 4404 |
if (!isInt(offset)) { |
| 4405 |
error('invalid object offset in the ObjStm stream: ' + offset); |
| 4406 |
} |
| 4407 |
} |
| 4408 |
// read stream objects for cache |
| 4409 |
for (i = 0; i < n; ++i) { |
| 4410 |
entries.push(parser.getObj()); |
| 4411 |
num = nums[i]; |
| 4412 |
var entry = this.entries[num]; |
| 4413 |
if (entry && entry.offset === tableOffset && entry.gen === i) { |
| 4414 |
this.cache[num] = entries[i]; |
| 4415 |
} |
| 4416 |
} |
| 4417 |
xrefEntry = entries[xrefEntry.gen]; |
| 4418 |
if (xrefEntry === undefined) { |
| 4419 |
error('bad XRef entry for compressed object'); |
| 4420 |
} |
| 4421 |
return xrefEntry; |
| 4422 |
}, |
| 4423 |
|
| 4424 |
fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) { |
| 4425 |
if (!isRef(obj)) { |
| 4426 |
return Promise.resolve(obj); |
| 4427 |
} |
| 4428 |
return this.fetchAsync(obj); |
| 4429 |
}, |
| 4430 |
|
| 4431 |
fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) { |
| 4432 |
var streamManager = this.stream.manager; |
| 4433 |
var xref = this; |
| 4434 |
return new Promise(function tryFetch(resolve, reject) { |
| 4435 |
try { |
| 4436 |
resolve(xref.fetch(ref, suppressEncryption)); |
| 4437 |
} catch (e) { |
| 4438 |
if (e instanceof MissingDataException) { |
| 4439 |
streamManager.requestRange(e.begin, e.end, function () { |
| 4440 |
tryFetch(resolve, reject); |
| 4441 |
}); |
| 4442 |
return; |
| 4443 |
} |
| 4444 |
reject(e); |
| 4445 |
} |
| 4446 |
}); |
| 4447 |
}, |
| 4448 |
|
| 4449 |
getCatalogObj: function XRef_getCatalogObj() { |
| 4450 |
return this.root; |
| 4451 |
} |
| 4452 |
}; |
| 4453 |
|
| 4454 |
return XRef; |
| 4455 |
})(); |
| 4456 |
|
| 4457 |
/** |
| 4458 |
* A NameTree is like a Dict but has some advantageous properties, see the |
| 4459 |
* spec (7.9.6) for more details. |
| 4460 |
* TODO: implement all the Dict functions and make this more efficent. |
| 4461 |
*/ |
| 4462 |
var NameTree = (function NameTreeClosure() { |
| 4463 |
function NameTree(root, xref) { |
| 4464 |
this.root = root; |
| 4465 |
this.xref = xref; |
| 4466 |
} |
| 4467 |
|
| 4468 |
NameTree.prototype = { |
| 4469 |
getAll: function NameTree_getAll() { |
| 4470 |
var dict = {}; |
| 4471 |
if (!this.root) { |
| 4472 |
return dict; |
| 4473 |
} |
| 4474 |
var xref = this.xref; |
| 4475 |
// reading name tree |
| 4476 |
var processed = new RefSet(); |
| 4477 |
processed.put(this.root); |
| 4478 |
var queue = [this.root]; |
| 4479 |
while (queue.length > 0) { |
| 4480 |
var i, n; |
| 4481 |
var obj = xref.fetchIfRef(queue.shift()); |
| 4482 |
if (!isDict(obj)) { |
| 4483 |
continue; |
| 4484 |
} |
| 4485 |
if (obj.has('Kids')) { |
| 4486 |
var kids = obj.get('Kids'); |
| 4487 |
for (i = 0, n = kids.length; i < n; i++) { |
| 4488 |
var kid = kids[i]; |
| 4489 |
if (processed.has(kid)) { |
| 4490 |
error('invalid destinations'); |
| 4491 |
} |
| 4492 |
queue.push(kid); |
| 4493 |
processed.put(kid); |
| 4494 |
} |
| 4495 |
continue; |
| 4496 |
} |
| 4497 |
var names = obj.get('Names'); |
| 4498 |
if (names) { |
| 4499 |
for (i = 0, n = names.length; i < n; i += 2) { |
| 4500 |
dict[names[i]] = xref.fetchIfRef(names[i + 1]); |
| 4501 |
} |
| 4502 |
} |
| 4503 |
} |
| 4504 |
return dict; |
| 4505 |
}, |
| 4506 |
|
| 4507 |
get: function NameTree_get(destinationId) { |
| 4508 |
if (!this.root) { |
| 4509 |
return null; |
| 4510 |
} |
| 4511 |
|
| 4512 |
var xref = this.xref; |
| 4513 |
var kidsOrNames = xref.fetchIfRef(this.root); |
| 4514 |
var loopCount = 0; |
| 4515 |
var MAX_NAMES_LEVELS = 10; |
| 4516 |
var l, r, m; |
| 4517 |
|
| 4518 |
// Perform a binary search to quickly find the entry that |
| 4519 |
// contains the named destination we are looking for. |
| 4520 |
while (kidsOrNames.has('Kids')) { |
| 4521 |
loopCount++; |
| 4522 |
if (loopCount > MAX_NAMES_LEVELS) { |
| 4523 |
warn('Search depth limit for named destionations has been reached.'); |
| 4524 |
return null; |
| 4525 |
} |
| 4526 |
|
| 4527 |
var kids = kidsOrNames.get('Kids'); |
| 4528 |
if (!isArray(kids)) { |
| 4529 |
return null; |
| 4530 |
} |
| 4531 |
|
| 4532 |
l = 0; |
| 4533 |
r = kids.length - 1; |
| 4534 |
while (l <= r) { |
| 4535 |
m = (l + r) >> 1; |
| 4536 |
var kid = xref.fetchIfRef(kids[m]); |
| 4537 |
var limits = kid.get('Limits'); |
| 4538 |
|
| 4539 |
if (destinationId < limits[0]) { |
| 4540 |
r = m - 1; |
| 4541 |
} else if (destinationId > limits[1]) { |
| 4542 |
l = m + 1; |
| 4543 |
} else { |
| 4544 |
kidsOrNames = xref.fetchIfRef(kids[m]); |
| 4545 |
break; |
| 4546 |
} |
| 4547 |
} |
| 4548 |
if (l > r) { |
| 4549 |
return null; |
| 4550 |
} |
| 4551 |
} |
| 4552 |
|
| 4553 |
// If we get here, then we have found the right entry. Now |
| 4554 |
// go through the named destinations in the Named dictionary |
| 4555 |
// until we find the exact destination we're looking for. |
| 4556 |
var names = kidsOrNames.get('Names'); |
| 4557 |
if (isArray(names)) { |
| 4558 |
// Perform a binary search to reduce the lookup time. |
| 4559 |
l = 0; |
| 4560 |
r = names.length - 2; |
| 4561 |
while (l <= r) { |
| 4562 |
// Check only even indices (0, 2, 4, ...) because the |
| 4563 |
// odd indices contain the actual D array. |
| 4564 |
m = (l + r) & ~1; |
| 4565 |
if (destinationId < names[m]) { |
| 4566 |
r = m - 2; |
| 4567 |
} else if (destinationId > names[m]) { |
| 4568 |
l = m + 2; |
| 4569 |
} else { |
| 4570 |
return xref.fetchIfRef(names[m + 1]); |
| 4571 |
} |
| 4572 |
} |
| 4573 |
} |
| 4574 |
return null; |
| 4575 |
} |
| 4576 |
}; |
| 4577 |
return NameTree; |
| 4578 |
})(); |
| 4579 |
|
| 4580 |
/** |
| 4581 |
* "A PDF file can refer to the contents of another file by using a File |
| 4582 |
* Specification (PDF 1.1)", see the spec (7.11) for more details. |
| 4583 |
* NOTE: Only embedded files are supported (as part of the attachments support) |
| 4584 |
* TODO: support the 'URL' file system (with caching if !/V), portable |
| 4585 |
* collections attributes and related files (/RF) |
| 4586 |
*/ |
| 4587 |
var FileSpec = (function FileSpecClosure() { |
| 4588 |
function FileSpec(root, xref) { |
| 4589 |
if (!root || !isDict(root)) { |
| 4590 |
return; |
| 4591 |
} |
| 4592 |
this.xref = xref; |
| 4593 |
this.root = root; |
| 4594 |
if (root.has('FS')) { |
| 4595 |
this.fs = root.get('FS'); |
| 4596 |
} |
| 4597 |
this.description = root.has('Desc') ? |
| 4598 |
stringToPDFString(root.get('Desc')) : |
| 4599 |
''; |
| 4600 |
if (root.has('RF')) { |
| 4601 |
warn('Related file specifications are not supported'); |
| 4602 |
} |
| 4603 |
this.contentAvailable = true; |
| 4604 |
if (!root.has('EF')) { |
| 4605 |
this.contentAvailable = false; |
| 4606 |
warn('Non-embedded file specifications are not supported'); |
| 4607 |
} |
| 4608 |
} |
| 4609 |
|
| 4610 |
function pickPlatformItem(dict) { |
| 4611 |
// Look for the filename in this order: |
| 4612 |
// UF, F, Unix, Mac, DOS |
| 4613 |
if (dict.has('UF')) { |
| 4614 |
return dict.get('UF'); |
| 4615 |
} else if (dict.has('F')) { |
| 4616 |
return dict.get('F'); |
| 4617 |
} else if (dict.has('Unix')) { |
| 4618 |
return dict.get('Unix'); |
| 4619 |
} else if (dict.has('Mac')) { |
| 4620 |
return dict.get('Mac'); |
| 4621 |
} else if (dict.has('DOS')) { |
| 4622 |
return dict.get('DOS'); |
| 4623 |
} else { |
| 4624 |
return null; |
| 4625 |
} |
| 4626 |
} |
| 4627 |
|
| 4628 |
FileSpec.prototype = { |
| 4629 |
get filename() { |
| 4630 |
if (!this._filename && this.root) { |
| 4631 |
var filename = pickPlatformItem(this.root) || 'unnamed'; |
| 4632 |
this._filename = stringToPDFString(filename). |
| 4633 |
replace(/\\\\/g, '\\'). |
| 4634 |
replace(/\\\//g, '/'). |
| 4635 |
replace(/\\/g, '/'); |
| 4636 |
} |
| 4637 |
return this._filename; |
| 4638 |
}, |
| 4639 |
get content() { |
| 4640 |
if (!this.contentAvailable) { |
| 4641 |
return null; |
| 4642 |
} |
| 4643 |
if (!this.contentRef && this.root) { |
| 4644 |
this.contentRef = pickPlatformItem(this.root.get('EF')); |
| 4645 |
} |
| 4646 |
var content = null; |
| 4647 |
if (this.contentRef) { |
| 4648 |
var xref = this.xref; |
| 4649 |
var fileObj = xref.fetchIfRef(this.contentRef); |
| 4650 |
if (fileObj && isStream(fileObj)) { |
| 4651 |
content = fileObj.getBytes(); |
| 4652 |
} else { |
| 4653 |
warn('Embedded file specification points to non-existing/invalid ' + |
| 4654 |
'content'); |
| 4655 |
} |
| 4656 |
} else { |
| 4657 |
warn('Embedded file specification does not have a content'); |
| 4658 |
} |
| 4659 |
return content; |
| 4660 |
}, |
| 4661 |
get serializable() { |
| 4662 |
return { |
| 4663 |
filename: this.filename, |
| 4664 |
content: this.content |
| 4665 |
}; |
| 4666 |
} |
| 4667 |
}; |
| 4668 |
return FileSpec; |
| 4669 |
})(); |
| 4670 |
|
| 4671 |
/** |
| 4672 |
* A helper for loading missing data in object graphs. It traverses the graph |
| 4673 |
* depth first and queues up any objects that have missing data. Once it has |
| 4674 |
* has traversed as many objects that are available it attempts to bundle the |
| 4675 |
* missing data requests and then resume from the nodes that weren't ready. |
| 4676 |
* |
| 4677 |
* NOTE: It provides protection from circular references by keeping track of |
| 4678 |
* of loaded references. However, you must be careful not to load any graphs |
| 4679 |
* that have references to the catalog or other pages since that will cause the |
| 4680 |
* entire PDF document object graph to be traversed. |
| 4681 |
*/ |
| 4682 |
var ObjectLoader = (function() { |
| 4683 |
function mayHaveChildren(value) { |
| 4684 |
return isRef(value) || isDict(value) || isArray(value) || isStream(value); |
| 4685 |
} |
| 4686 |
|
| 4687 |
function addChildren(node, nodesToVisit) { |
| 4688 |
var value; |
| 4689 |
if (isDict(node) || isStream(node)) { |
| 4690 |
var map; |
| 4691 |
if (isDict(node)) { |
| 4692 |
map = node.map; |
| 4693 |
} else { |
| 4694 |
map = node.dict.map; |
| 4695 |
} |
| 4696 |
for (var key in map) { |
| 4697 |
value = map[key]; |
| 4698 |
if (mayHaveChildren(value)) { |
| 4699 |
nodesToVisit.push(value); |
| 4700 |
} |
| 4701 |
} |
| 4702 |
} else if (isArray(node)) { |
| 4703 |
for (var i = 0, ii = node.length; i < ii; i++) { |
| 4704 |
value = node[i]; |
| 4705 |
if (mayHaveChildren(value)) { |
| 4706 |
nodesToVisit.push(value); |
| 4707 |
} |
| 4708 |
} |
| 4709 |
} |
| 4710 |
} |
| 4711 |
|
| 4712 |
function ObjectLoader(obj, keys, xref) { |
| 4713 |
this.obj = obj; |
| 4714 |
this.keys = keys; |
| 4715 |
this.xref = xref; |
| 4716 |
this.refSet = null; |
| 4717 |
} |
| 4718 |
|
| 4719 |
ObjectLoader.prototype = { |
| 4720 |
load: function ObjectLoader_load() { |
| 4721 |
var keys = this.keys; |
| 4722 |
this.capability = createPromiseCapability(); |
| 4723 |
// Don't walk the graph if all the data is already loaded. |
| 4724 |
if (!(this.xref.stream instanceof ChunkedStream) || |
| 4725 |
this.xref.stream.getMissingChunks().length === 0) { |
| 4726 |
this.capability.resolve(); |
| 4727 |
return this.capability.promise; |
| 4728 |
} |
| 4729 |
|
| 4730 |
this.refSet = new RefSet(); |
| 4731 |
// Setup the initial nodes to visit. |
| 4732 |
var nodesToVisit = []; |
| 4733 |
for (var i = 0; i < keys.length; i++) { |
| 4734 |
nodesToVisit.push(this.obj[keys[i]]); |
| 4735 |
} |
| 4736 |
|
| 4737 |
this.walk(nodesToVisit); |
| 4738 |
return this.capability.promise; |
| 4739 |
}, |
| 4740 |
|
| 4741 |
walk: function ObjectLoader_walk(nodesToVisit) { |
| 4742 |
var nodesToRevisit = []; |
| 4743 |
var pendingRequests = []; |
| 4744 |
// DFS walk of the object graph. |
| 4745 |
while (nodesToVisit.length) { |
| 4746 |
var currentNode = nodesToVisit.pop(); |
| 4747 |
|
| 4748 |
// Only references or chunked streams can cause missing data exceptions. |
| 4749 |
if (isRef(currentNode)) { |
| 4750 |
// Skip nodes that have already been visited. |
| 4751 |
if (this.refSet.has(currentNode)) { |
| 4752 |
continue; |
| 4753 |
} |
| 4754 |
try { |
| 4755 |
var ref = currentNode; |
| 4756 |
this.refSet.put(ref); |
| 4757 |
currentNode = this.xref.fetch(currentNode); |
| 4758 |
} catch (e) { |
| 4759 |
if (!(e instanceof MissingDataException)) { |
| 4760 |
throw e; |
| 4761 |
} |
| 4762 |
nodesToRevisit.push(currentNode); |
| 4763 |
pendingRequests.push({ begin: e.begin, end: e.end }); |
| 4764 |
} |
| 4765 |
} |
| 4766 |
if (currentNode && currentNode.getBaseStreams) { |
| 4767 |
var baseStreams = currentNode.getBaseStreams(); |
| 4768 |
var foundMissingData = false; |
| 4769 |
for (var i = 0; i < baseStreams.length; i++) { |
| 4770 |
var stream = baseStreams[i]; |
| 4771 |
if (stream.getMissingChunks && stream.getMissingChunks().length) { |
| 4772 |
foundMissingData = true; |
| 4773 |
pendingRequests.push({ |
| 4774 |
begin: stream.start, |
| 4775 |
end: stream.end |
| 4776 |
}); |
| 4777 |
} |
| 4778 |
} |
| 4779 |
if (foundMissingData) { |
| 4780 |
nodesToRevisit.push(currentNode); |
| 4781 |
} |
| 4782 |
} |
| 4783 |
|
| 4784 |
addChildren(currentNode, nodesToVisit); |
| 4785 |
} |
| 4786 |
|
| 4787 |
if (pendingRequests.length) { |
| 4788 |
this.xref.stream.manager.requestRanges(pendingRequests, |
| 4789 |
function pendingRequestCallback() { |
| 4790 |
nodesToVisit = nodesToRevisit; |
| 4791 |
for (var i = 0; i < nodesToRevisit.length; i++) { |
| 4792 |
var node = nodesToRevisit[i]; |
| 4793 |
// Remove any reference nodes from the currrent refset so they |
| 4794 |
// aren't skipped when we revist them. |
| 4795 |
if (isRef(node)) { |
| 4796 |
this.refSet.remove(node); |
| 4797 |
} |
| 4798 |
} |
| 4799 |
this.walk(nodesToVisit); |
| 4800 |
}.bind(this)); |
| 4801 |
return; |
| 4802 |
} |
| 4803 |
// Everything is loaded. |
| 4804 |
this.refSet = null; |
| 4805 |
this.capability.resolve(); |
| 4806 |
} |
| 4807 |
}; |
| 4808 |
|
| 4809 |
return ObjectLoader; |
| 4810 |
})(); |
| 4811 |
|
| 4812 |
|
| 4813 |
var ISOAdobeCharset = [ |
| 4814 |
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', |
| 4815 |
'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', |
| 4816 |
'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', |
| 4817 |
'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', |
| 4818 |
'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', |
| 4819 |
'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', |
| 4820 |
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
| 4821 |
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', |
| 4822 |
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', |
| 4823 |
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', |
| 4824 |
'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', |
| 4825 |
'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', |
| 4826 |
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', |
| 4827 |
'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', |
| 4828 |
'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', |
| 4829 |
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', |
| 4830 |
'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', |
| 4831 |
'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', |
| 4832 |
'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', |
| 4833 |
'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', |
| 4834 |
'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', |
| 4835 |
'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', |
| 4836 |
'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', |
| 4837 |
'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', |
| 4838 |
'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', |
| 4839 |
'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', |
| 4840 |
'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', |
| 4841 |
'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', |
| 4842 |
'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', |
| 4843 |
'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', |
| 4844 |
'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', |
| 4845 |
'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', |
| 4846 |
'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', |
| 4847 |
'ugrave', 'yacute', 'ydieresis', 'zcaron' |
| 4848 |
]; |
| 4849 |
|
| 4850 |
var ExpertCharset = [ |
| 4851 |
'.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', |
| 4852 |
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', |
| 4853 |
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', |
| 4854 |
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', |
| 4855 |
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', |
| 4856 |
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', |
| 4857 |
'colon', 'semicolon', 'commasuperior', 'threequartersemdash', |
| 4858 |
'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', |
| 4859 |
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', |
| 4860 |
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', |
| 4861 |
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', |
| 4862 |
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', |
| 4863 |
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', |
| 4864 |
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', |
| 4865 |
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', |
| 4866 |
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', |
| 4867 |
'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', |
| 4868 |
'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', |
| 4869 |
'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', |
| 4870 |
'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', |
| 4871 |
'Cedillasmall', 'onequarter', 'onehalf', 'threequarters', |
| 4872 |
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', |
| 4873 |
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', |
| 4874 |
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', |
| 4875 |
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', |
| 4876 |
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', |
| 4877 |
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', |
| 4878 |
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', |
| 4879 |
'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', |
| 4880 |
'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', |
| 4881 |
'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', |
| 4882 |
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', |
| 4883 |
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', |
| 4884 |
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', |
| 4885 |
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', |
| 4886 |
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', |
| 4887 |
'Ydieresissmall' |
| 4888 |
]; |
| 4889 |
|
| 4890 |
var ExpertSubsetCharset = [ |
| 4891 |
'.notdef', 'space', 'dollaroldstyle', 'dollarsuperior', |
| 4892 |
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', |
| 4893 |
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', |
| 4894 |
'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', |
| 4895 |
'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', |
| 4896 |
'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', |
| 4897 |
'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior', |
| 4898 |
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', |
| 4899 |
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', |
| 4900 |
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', |
| 4901 |
'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted', |
| 4902 |
'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter', |
| 4903 |
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', |
| 4904 |
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', |
| 4905 |
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', |
| 4906 |
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', |
| 4907 |
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', |
| 4908 |
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', |
| 4909 |
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', |
| 4910 |
'periodinferior', 'commainferior' |
| 4911 |
]; |
| 4912 |
|
| 4913 |
|
| 4914 |
var DEFAULT_ICON_SIZE = 22; // px |
| 4915 |
var SUPPORTED_TYPES = ['Link', 'Text', 'Widget']; |
| 4916 |
|
| 4917 |
var Annotation = (function AnnotationClosure() { |
| 4918 |
// 12.5.5: Algorithm: Appearance streams |
| 4919 |
function getTransformMatrix(rect, bbox, matrix) { |
| 4920 |
var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix); |
| 4921 |
var minX = bounds[0]; |
| 4922 |
var minY = bounds[1]; |
| 4923 |
var maxX = bounds[2]; |
| 4924 |
var maxY = bounds[3]; |
| 4925 |
|
| 4926 |
if (minX === maxX || minY === maxY) { |
| 4927 |
// From real-life file, bbox was [0, 0, 0, 0]. In this case, |
| 4928 |
// just apply the transform for rect |
| 4929 |
return [1, 0, 0, 1, rect[0], rect[1]]; |
| 4930 |
} |
| 4931 |
|
| 4932 |
var xRatio = (rect[2] - rect[0]) / (maxX - minX); |
| 4933 |
var yRatio = (rect[3] - rect[1]) / (maxY - minY); |
| 4934 |
return [ |
| 4935 |
xRatio, |
| 4936 |
0, |
| 4937 |
0, |
| 4938 |
yRatio, |
| 4939 |
rect[0] - minX * xRatio, |
| 4940 |
rect[1] - minY * yRatio |
| 4941 |
]; |
| 4942 |
} |
| 4943 |
|
| 4944 |
function getDefaultAppearance(dict) { |
| 4945 |
var appearanceState = dict.get('AP'); |
| 4946 |
if (!isDict(appearanceState)) { |
| 4947 |
return; |
| 4948 |
} |
| 4949 |
|
| 4950 |
var appearance; |
| 4951 |
var appearances = appearanceState.get('N'); |
| 4952 |
if (isDict(appearances)) { |
| 4953 |
var as = dict.get('AS'); |
| 4954 |
if (as && appearances.has(as.name)) { |
| 4955 |
appearance = appearances.get(as.name); |
| 4956 |
} |
| 4957 |
} else { |
| 4958 |
appearance = appearances; |
| 4959 |
} |
| 4960 |
return appearance; |
| 4961 |
} |
| 4962 |
|
| 4963 |
function Annotation(params) { |
| 4964 |
var dict = params.dict; |
| 4965 |
var data = this.data = {}; |
| 4966 |
|
| 4967 |
data.subtype = dict.get('Subtype').name; |
| 4968 |
var rect = dict.get('Rect') || [0, 0, 0, 0]; |
| 4969 |
data.rect = Util.normalizeRect(rect); |
| 4970 |
data.annotationFlags = dict.get('F'); |
| 4971 |
|
| 4972 |
var color = dict.get('C'); |
| 4973 |
if (!color) { |
| 4974 |
// The PDF spec does not mention how a missing color array is interpreted. |
| 4975 |
// Adobe Reader seems to default to black in this case. |
| 4976 |
data.color = [0, 0, 0]; |
| 4977 |
} else if (isArray(color)) { |
| 4978 |
switch (color.length) { |
| 4979 |
case 0: |
| 4980 |
// Empty array denotes transparent border. |
| 4981 |
data.color = null; |
| 4982 |
break; |
| 4983 |
case 1: |
| 4984 |
// TODO: implement DeviceGray |
| 4985 |
break; |
| 4986 |
case 3: |
| 4987 |
data.color = color; |
| 4988 |
break; |
| 4989 |
case 4: |
| 4990 |
// TODO: implement DeviceCMYK |
| 4991 |
break; |
| 4992 |
} |
| 4993 |
} |
| 4994 |
|
| 4995 |
// Some types of annotations have border style dict which has more |
| 4996 |
// info than the border array |
| 4997 |
if (dict.has('BS')) { |
| 4998 |
var borderStyle = dict.get('BS'); |
| 4999 |
data.borderWidth = borderStyle.has('W') ? borderStyle.get('W') : 1; |
| 5000 |
} else { |
| 5001 |
var borderArray = dict.get('Border') || [0, 0, 1]; |
| 5002 |
data.borderWidth = borderArray[2] || 0; |
| 5003 |
|
| 5004 |
// TODO: implement proper support for annotations with line dash patterns. |
| 5005 |
var dashArray = borderArray[3]; |
| 5006 |
if (data.borderWidth > 0 && dashArray) { |
| 5007 |
if (!isArray(dashArray)) { |
| 5008 |
// Ignore the border if dashArray is not actually an array, |
| 5009 |
// this is consistent with the behaviour in Adobe Reader. |
| 5010 |
data.borderWidth = 0; |
| 5011 |
} else { |
| 5012 |
var dashArrayLength = dashArray.length; |
| 5013 |
if (dashArrayLength > 0) { |
| 5014 |
// According to the PDF specification: the elements in a dashArray |
| 5015 |
// shall be numbers that are nonnegative and not all equal to zero. |
| 5016 |
var isInvalid = false; |
| 5017 |
var numPositive = 0; |
| 5018 |
for (var i = 0; i < dashArrayLength; i++) { |
| 5019 |
var validNumber = (+dashArray[i] >= 0); |
| 5020 |
if (!validNumber) { |
| 5021 |
isInvalid = true; |
| 5022 |
break; |
| 5023 |
} else if (dashArray[i] > 0) { |
| 5024 |
numPositive++; |
| 5025 |
} |
| 5026 |
} |
| 5027 |
if (isInvalid || numPositive === 0) { |
| 5028 |
data.borderWidth = 0; |
| 5029 |
} |
| 5030 |
} |
| 5031 |
} |
| 5032 |
} |
| 5033 |
} |
| 5034 |
|
| 5035 |
this.appearance = getDefaultAppearance(dict); |
| 5036 |
data.hasAppearance = !!this.appearance; |
| 5037 |
data.id = params.ref.num; |
| 5038 |
} |
| 5039 |
|
| 5040 |
Annotation.prototype = { |
| 5041 |
|
| 5042 |
getData: function Annotation_getData() { |
| 5043 |
return this.data; |
| 5044 |
}, |
| 5045 |
|
| 5046 |
isInvisible: function Annotation_isInvisible() { |
| 5047 |
var data = this.data; |
| 5048 |
if (data && SUPPORTED_TYPES.indexOf(data.subtype) !== -1) { |
| 5049 |
return false; |
| 5050 |
} else { |
| 5051 |
return !!(data && |
| 5052 |
data.annotationFlags && // Default: not invisible |
| 5053 |
data.annotationFlags & 0x1); // Invisible |
| 5054 |
} |
| 5055 |
}, |
| 5056 |
|
| 5057 |
isViewable: function Annotation_isViewable() { |
| 5058 |
var data = this.data; |
| 5059 |
return !!(!this.isInvisible() && |
| 5060 |
data && |
| 5061 |
(!data.annotationFlags || |
| 5062 |
!(data.annotationFlags & 0x22)) && // Hidden or NoView |
| 5063 |
data.rect); // rectangle is necessary |
| 5064 |
}, |
| 5065 |
|
| 5066 |
isPrintable: function Annotation_isPrintable() { |
| 5067 |
var data = this.data; |
| 5068 |
return !!(!this.isInvisible() && |
| 5069 |
data && |
| 5070 |
data.annotationFlags && // Default: not printable |
| 5071 |
data.annotationFlags & 0x4 && // Print |
| 5072 |
!(data.annotationFlags & 0x2) && // Hidden |
| 5073 |
data.rect); // rectangle is necessary |
| 5074 |
}, |
| 5075 |
|
| 5076 |
loadResources: function Annotation_loadResources(keys) { |
| 5077 |
return new Promise(function (resolve, reject) { |
| 5078 |
this.appearance.dict.getAsync('Resources').then(function (resources) { |
| 5079 |
if (!resources) { |
| 5080 |
resolve(); |
| 5081 |
return; |
| 5082 |
} |
| 5083 |
var objectLoader = new ObjectLoader(resources.map, |
| 5084 |
keys, |
| 5085 |
resources.xref); |
| 5086 |
objectLoader.load().then(function() { |
| 5087 |
resolve(resources); |
| 5088 |
}, reject); |
| 5089 |
}, reject); |
| 5090 |
}.bind(this)); |
| 5091 |
}, |
| 5092 |
|
| 5093 |
getOperatorList: function Annotation_getOperatorList(evaluator) { |
| 5094 |
|
| 5095 |
if (!this.appearance) { |
| 5096 |
return Promise.resolve(new OperatorList()); |
| 5097 |
} |
| 5098 |
|
| 5099 |
var data = this.data; |
| 5100 |
|
| 5101 |
var appearanceDict = this.appearance.dict; |
| 5102 |
var resourcesPromise = this.loadResources([ |
| 5103 |
'ExtGState', |
| 5104 |
'ColorSpace', |
| 5105 |
'Pattern', |
| 5106 |
'Shading', |
| 5107 |
'XObject', |
| 5108 |
'Font' |
| 5109 |
// ProcSet |
| 5110 |
// Properties |
| 5111 |
]); |
| 5112 |
var bbox = appearanceDict.get('BBox') || [0, 0, 1, 1]; |
| 5113 |
var matrix = appearanceDict.get('Matrix') || [1, 0, 0, 1, 0 ,0]; |
| 5114 |
var transform = getTransformMatrix(data.rect, bbox, matrix); |
| 5115 |
var self = this; |
| 5116 |
|
| 5117 |
return resourcesPromise.then(function(resources) { |
| 5118 |
var opList = new OperatorList(); |
| 5119 |
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]); |
| 5120 |
return evaluator.getOperatorList(self.appearance, resources, opList). |
| 5121 |
then(function () { |
| 5122 |
opList.addOp(OPS.endAnnotation, []); |
| 5123 |
self.appearance.reset(); |
| 5124 |
return opList; |
| 5125 |
}); |
| 5126 |
}); |
| 5127 |
} |
| 5128 |
}; |
| 5129 |
|
| 5130 |
Annotation.getConstructor = |
| 5131 |
function Annotation_getConstructor(subtype, fieldType) { |
| 5132 |
|
| 5133 |
if (!subtype) { |
| 5134 |
return; |
| 5135 |
} |
| 5136 |
|
| 5137 |
// TODO(mack): Implement FreeText annotations |
| 5138 |
if (subtype === 'Link') { |
| 5139 |
return LinkAnnotation; |
| 5140 |
} else if (subtype === 'Text') { |
| 5141 |
return TextAnnotation; |
| 5142 |
} else if (subtype === 'Widget') { |
| 5143 |
if (!fieldType) { |
| 5144 |
return; |
| 5145 |
} |
| 5146 |
|
| 5147 |
if (fieldType === 'Tx') { |
| 5148 |
return TextWidgetAnnotation; |
| 5149 |
} else { |
| 5150 |
return WidgetAnnotation; |
| 5151 |
} |
| 5152 |
} else { |
| 5153 |
return Annotation; |
| 5154 |
} |
| 5155 |
}; |
| 5156 |
|
| 5157 |
Annotation.fromRef = function Annotation_fromRef(xref, ref) { |
| 5158 |
|
| 5159 |
var dict = xref.fetchIfRef(ref); |
| 5160 |
if (!isDict(dict)) { |
| 5161 |
return; |
| 5162 |
} |
| 5163 |
|
| 5164 |
var subtype = dict.get('Subtype'); |
| 5165 |
subtype = isName(subtype) ? subtype.name : ''; |
| 5166 |
if (!subtype) { |
| 5167 |
return; |
| 5168 |
} |
| 5169 |
|
| 5170 |
var fieldType = Util.getInheritableProperty(dict, 'FT'); |
| 5171 |
fieldType = isName(fieldType) ? fieldType.name : ''; |
| 5172 |
|
| 5173 |
var Constructor = Annotation.getConstructor(subtype, fieldType); |
| 5174 |
if (!Constructor) { |
| 5175 |
return; |
| 5176 |
} |
| 5177 |
|
| 5178 |
var params = { |
| 5179 |
dict: dict, |
| 5180 |
ref: ref, |
| 5181 |
}; |
| 5182 |
|
| 5183 |
var annotation = new Constructor(params); |
| 5184 |
|
| 5185 |
if (annotation.isViewable() || annotation.isPrintable()) { |
| 5186 |
return annotation; |
| 5187 |
} else { |
| 5188 |
if (SUPPORTED_TYPES.indexOf(subtype) === -1) { |
| 5189 |
warn('unimplemented annotation type: ' + subtype); |
| 5190 |
} |
| 5191 |
} |
| 5192 |
}; |
| 5193 |
|
| 5194 |
Annotation.appendToOperatorList = function Annotation_appendToOperatorList( |
| 5195 |
annotations, opList, pdfManager, partialEvaluator, intent) { |
| 5196 |
|
| 5197 |
function reject(e) { |
| 5198 |
annotationsReadyCapability.reject(e); |
| 5199 |
} |
| 5200 |
|
| 5201 |
var annotationsReadyCapability = createPromiseCapability(); |
| 5202 |
|
| 5203 |
var annotationPromises = []; |
| 5204 |
for (var i = 0, n = annotations.length; i < n; ++i) { |
| 5205 |
if (intent === 'display' && annotations[i].isViewable() || |
| 5206 |
intent === 'print' && annotations[i].isPrintable()) { |
| 5207 |
annotationPromises.push( |
| 5208 |
annotations[i].getOperatorList(partialEvaluator)); |
| 5209 |
} |
| 5210 |
} |
| 5211 |
Promise.all(annotationPromises).then(function(datas) { |
| 5212 |
opList.addOp(OPS.beginAnnotations, []); |
| 5213 |
for (var i = 0, n = datas.length; i < n; ++i) { |
| 5214 |
var annotOpList = datas[i]; |
| 5215 |
opList.addOpList(annotOpList); |
| 5216 |
} |
| 5217 |
opList.addOp(OPS.endAnnotations, []); |
| 5218 |
annotationsReadyCapability.resolve(); |
| 5219 |
}, reject); |
| 5220 |
|
| 5221 |
return annotationsReadyCapability.promise; |
| 5222 |
}; |
| 5223 |
|
| 5224 |
return Annotation; |
| 5225 |
})(); |
| 5226 |
|
| 5227 |
var WidgetAnnotation = (function WidgetAnnotationClosure() { |
| 5228 |
|
| 5229 |
function WidgetAnnotation(params) { |
| 5230 |
Annotation.call(this, params); |
| 5231 |
|
| 5232 |
var dict = params.dict; |
| 5233 |
var data = this.data; |
| 5234 |
|
| 5235 |
data.fieldValue = stringToPDFString( |
| 5236 |
Util.getInheritableProperty(dict, 'V') || ''); |
| 5237 |
data.alternativeText = stringToPDFString(dict.get('TU') || ''); |
| 5238 |
data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || ''; |
| 5239 |
var fieldType = Util.getInheritableProperty(dict, 'FT'); |
| 5240 |
data.fieldType = isName(fieldType) ? fieldType.name : ''; |
| 5241 |
data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0; |
| 5242 |
this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty; |
| 5243 |
|
| 5244 |
// Building the full field name by collecting the field and |
| 5245 |
// its ancestors 'T' data and joining them using '.'. |
| 5246 |
var fieldName = []; |
| 5247 |
var namedItem = dict; |
| 5248 |
var ref = params.ref; |
| 5249 |
while (namedItem) { |
| 5250 |
var parent = namedItem.get('Parent'); |
| 5251 |
var parentRef = namedItem.getRaw('Parent'); |
| 5252 |
var name = namedItem.get('T'); |
| 5253 |
if (name) { |
| 5254 |
fieldName.unshift(stringToPDFString(name)); |
| 5255 |
} else if (parent && ref) { |
| 5256 |
// The field name is absent, that means more than one field |
| 5257 |
// with the same name may exist. Replacing the empty name |
| 5258 |
// with the '`' plus index in the parent's 'Kids' array. |
| 5259 |
// This is not in the PDF spec but necessary to id the |
| 5260 |
// the input controls. |
| 5261 |
var kids = parent.get('Kids'); |
| 5262 |
var j, jj; |
| 5263 |
for (j = 0, jj = kids.length; j < jj; j++) { |
| 5264 |
var kidRef = kids[j]; |
| 5265 |
if (kidRef.num === ref.num && kidRef.gen === ref.gen) { |
| 5266 |
break; |
| 5267 |
} |
| 5268 |
} |
| 5269 |
fieldName.unshift('`' + j); |
| 5270 |
} |
| 5271 |
namedItem = parent; |
| 5272 |
ref = parentRef; |
| 5273 |
} |
| 5274 |
data.fullName = fieldName.join('.'); |
| 5275 |
} |
| 5276 |
|
| 5277 |
var parent = Annotation.prototype; |
| 5278 |
Util.inherit(WidgetAnnotation, Annotation, { |
| 5279 |
isViewable: function WidgetAnnotation_isViewable() { |
| 5280 |
if (this.data.fieldType === 'Sig') { |
| 5281 |
warn('unimplemented annotation type: Widget signature'); |
| 5282 |
return false; |
| 5283 |
} |
| 5284 |
|
| 5285 |
return parent.isViewable.call(this); |
| 5286 |
} |
| 5287 |
}); |
| 5288 |
|
| 5289 |
return WidgetAnnotation; |
| 5290 |
})(); |
| 5291 |
|
| 5292 |
var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { |
| 5293 |
function TextWidgetAnnotation(params) { |
| 5294 |
WidgetAnnotation.call(this, params); |
| 5295 |
|
| 5296 |
this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q'); |
| 5297 |
this.data.annotationType = AnnotationType.WIDGET; |
| 5298 |
this.data.hasHtml = !this.data.hasAppearance && !!this.data.fieldValue; |
| 5299 |
} |
| 5300 |
|
| 5301 |
Util.inherit(TextWidgetAnnotation, WidgetAnnotation, { |
| 5302 |
getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) { |
| 5303 |
if (this.appearance) { |
| 5304 |
return Annotation.prototype.getOperatorList.call(this, evaluator); |
| 5305 |
} |
| 5306 |
|
| 5307 |
var opList = new OperatorList(); |
| 5308 |
var data = this.data; |
| 5309 |
|
| 5310 |
// Even if there is an appearance stream, ignore it. This is the |
| 5311 |
// behaviour used by Adobe Reader. |
| 5312 |
if (!data.defaultAppearance) { |
| 5313 |
return Promise.resolve(opList); |
| 5314 |
} |
| 5315 |
|
| 5316 |
var stream = new Stream(stringToBytes(data.defaultAppearance)); |
| 5317 |
return evaluator.getOperatorList(stream, this.fieldResources, opList). |
| 5318 |
then(function () { |
| 5319 |
return opList; |
| 5320 |
}); |
| 5321 |
} |
| 5322 |
}); |
| 5323 |
|
| 5324 |
return TextWidgetAnnotation; |
| 5325 |
})(); |
| 5326 |
|
| 5327 |
var InteractiveAnnotation = (function InteractiveAnnotationClosure() { |
| 5328 |
function InteractiveAnnotation(params) { |
| 5329 |
Annotation.call(this, params); |
| 5330 |
|
| 5331 |
this.data.hasHtml = true; |
| 5332 |
} |
| 5333 |
|
| 5334 |
Util.inherit(InteractiveAnnotation, Annotation, { }); |
| 5335 |
|
| 5336 |
return InteractiveAnnotation; |
| 5337 |
})(); |
| 5338 |
|
| 5339 |
var TextAnnotation = (function TextAnnotationClosure() { |
| 5340 |
function TextAnnotation(params) { |
| 5341 |
InteractiveAnnotation.call(this, params); |
| 5342 |
|
| 5343 |
var dict = params.dict; |
| 5344 |
var data = this.data; |
| 5345 |
|
| 5346 |
var content = dict.get('Contents'); |
| 5347 |
var title = dict.get('T'); |
| 5348 |
data.annotationType = AnnotationType.TEXT; |
| 5349 |
data.content = stringToPDFString(content || ''); |
| 5350 |
data.title = stringToPDFString(title || ''); |
| 5351 |
|
| 5352 |
if (data.hasAppearance) { |
| 5353 |
data.name = 'NoIcon'; |
| 5354 |
} else { |
| 5355 |
data.rect[1] = data.rect[3] - DEFAULT_ICON_SIZE; |
| 5356 |
data.rect[2] = data.rect[0] + DEFAULT_ICON_SIZE; |
| 5357 |
data.name = dict.has('Name') ? dict.get('Name').name : 'Note'; |
| 5358 |
} |
| 5359 |
|
| 5360 |
if (dict.has('C')) { |
| 5361 |
data.hasBgColor = true; |
| 5362 |
} |
| 5363 |
} |
| 5364 |
|
| 5365 |
Util.inherit(TextAnnotation, InteractiveAnnotation, { }); |
| 5366 |
|
| 5367 |
return TextAnnotation; |
| 5368 |
})(); |
| 5369 |
|
| 5370 |
var LinkAnnotation = (function LinkAnnotationClosure() { |
| 5371 |
function LinkAnnotation(params) { |
| 5372 |
InteractiveAnnotation.call(this, params); |
| 5373 |
|
| 5374 |
var dict = params.dict; |
| 5375 |
var data = this.data; |
| 5376 |
data.annotationType = AnnotationType.LINK; |
| 5377 |
|
| 5378 |
var action = dict.get('A'); |
| 5379 |
if (action && isDict(action)) { |
| 5380 |
var linkType = action.get('S').name; |
| 5381 |
if (linkType === 'URI') { |
| 5382 |
var url = action.get('URI'); |
| 5383 |
if (isName(url)) { |
| 5384 |
// Some bad PDFs do not put parentheses around relative URLs. |
| 5385 |
url = '/' + url.name; |
| 5386 |
} else if (url) { |
| 5387 |
url = addDefaultProtocolToUrl(url); |
| 5388 |
} |
| 5389 |
// TODO: pdf spec mentions urls can be relative to a Base |
| 5390 |
// entry in the dictionary. |
| 5391 |
if (!isValidUrl(url, false)) { |
| 5392 |
url = ''; |
| 5393 |
} |
| 5394 |
data.url = url; |
| 5395 |
} else if (linkType === 'GoTo') { |
| 5396 |
data.dest = action.get('D'); |
| 5397 |
} else if (linkType === 'GoToR') { |
| 5398 |
var urlDict = action.get('F'); |
| 5399 |
if (isDict(urlDict)) { |
| 5400 |
// We assume that the 'url' is a Filspec dictionary |
| 5401 |
// and fetch the url without checking any further |
| 5402 |
url = urlDict.get('F') || ''; |
| 5403 |
} |
| 5404 |
|
| 5405 |
// TODO: pdf reference says that GoToR |
| 5406 |
// can also have 'NewWindow' attribute |
| 5407 |
if (!isValidUrl(url, false)) { |
| 5408 |
url = ''; |
| 5409 |
} |
| 5410 |
data.url = url; |
| 5411 |
data.dest = action.get('D'); |
| 5412 |
} else if (linkType === 'Named') { |
| 5413 |
data.action = action.get('N').name; |
| 5414 |
} else { |
| 5415 |
warn('unrecognized link type: ' + linkType); |
| 5416 |
} |
| 5417 |
} else if (dict.has('Dest')) { |
| 5418 |
// simple destination link |
| 5419 |
var dest = dict.get('Dest'); |
| 5420 |
data.dest = isName(dest) ? dest.name : dest; |
| 5421 |
} |
| 5422 |
} |
| 5423 |
|
| 5424 |
// Lets URLs beginning with 'www.' default to using the 'http://' protocol. |
| 5425 |
function addDefaultProtocolToUrl(url) { |
| 5426 |
if (url && url.indexOf('www.') === 0) { |
| 5427 |
return ('http://' + url); |
| 5428 |
} |
| 5429 |
return url; |
| 5430 |
} |
| 5431 |
|
| 5432 |
Util.inherit(LinkAnnotation, InteractiveAnnotation, { }); |
| 5433 |
|
| 5434 |
return LinkAnnotation; |
| 5435 |
})(); |
| 5436 |
|
| 5437 |
|
| 5438 |
var PDFFunction = (function PDFFunctionClosure() { |
| 5439 |
var CONSTRUCT_SAMPLED = 0; |
| 5440 |
var CONSTRUCT_INTERPOLATED = 2; |
| 5441 |
var CONSTRUCT_STICHED = 3; |
| 5442 |
var CONSTRUCT_POSTSCRIPT = 4; |
| 5443 |
|
| 5444 |
return { |
| 5445 |
getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps, |
| 5446 |
str) { |
| 5447 |
var i, ii; |
| 5448 |
var length = 1; |
| 5449 |
for (i = 0, ii = size.length; i < ii; i++) { |
| 5450 |
length *= size[i]; |
| 5451 |
} |
| 5452 |
length *= outputSize; |
| 5453 |
|
| 5454 |
var array = new Array(length); |
| 5455 |
var codeSize = 0; |
| 5456 |
var codeBuf = 0; |
| 5457 |
// 32 is a valid bps so shifting won't work |
| 5458 |
var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1); |
| 5459 |
|
| 5460 |
var strBytes = str.getBytes((length * bps + 7) / 8); |
| 5461 |
var strIdx = 0; |
| 5462 |
for (i = 0; i < length; i++) { |
| 5463 |
while (codeSize < bps) { |
| 5464 |
codeBuf <<= 8; |
| 5465 |
codeBuf |= strBytes[strIdx++]; |
| 5466 |
codeSize += 8; |
| 5467 |
} |
| 5468 |
codeSize -= bps; |
| 5469 |
array[i] = (codeBuf >> codeSize) * sampleMul; |
| 5470 |
codeBuf &= (1 << codeSize) - 1; |
| 5471 |
} |
| 5472 |
return array; |
| 5473 |
}, |
| 5474 |
|
| 5475 |
getIR: function PDFFunction_getIR(xref, fn) { |
| 5476 |
var dict = fn.dict; |
| 5477 |
if (!dict) { |
| 5478 |
dict = fn; |
| 5479 |
} |
| 5480 |
|
| 5481 |
var types = [this.constructSampled, |
| 5482 |
null, |
| 5483 |
this.constructInterpolated, |
| 5484 |
this.constructStiched, |
| 5485 |
this.constructPostScript]; |
| 5486 |
|
| 5487 |
var typeNum = dict.get('FunctionType'); |
| 5488 |
var typeFn = types[typeNum]; |
| 5489 |
if (!typeFn) { |
| 5490 |
error('Unknown type of function'); |
| 5491 |
} |
| 5492 |
|
| 5493 |
return typeFn.call(this, fn, dict, xref); |
| 5494 |
}, |
| 5495 |
|
| 5496 |
fromIR: function PDFFunction_fromIR(IR) { |
| 5497 |
var type = IR[0]; |
| 5498 |
switch (type) { |
| 5499 |
case CONSTRUCT_SAMPLED: |
| 5500 |
return this.constructSampledFromIR(IR); |
| 5501 |
case CONSTRUCT_INTERPOLATED: |
| 5502 |
return this.constructInterpolatedFromIR(IR); |
| 5503 |
case CONSTRUCT_STICHED: |
| 5504 |
return this.constructStichedFromIR(IR); |
| 5505 |
//case CONSTRUCT_POSTSCRIPT: |
| 5506 |
default: |
| 5507 |
return this.constructPostScriptFromIR(IR); |
| 5508 |
} |
| 5509 |
}, |
| 5510 |
|
| 5511 |
parse: function PDFFunction_parse(xref, fn) { |
| 5512 |
var IR = this.getIR(xref, fn); |
| 5513 |
return this.fromIR(IR); |
| 5514 |
}, |
| 5515 |
|
| 5516 |
parseArray: function PDFFunction_parseArray(xref, fnObj) { |
| 5517 |
if (!isArray(fnObj)) { |
| 5518 |
// not an array -- parsing as regular function |
| 5519 |
return this.parse(xref, fnObj); |
| 5520 |
} |
| 5521 |
|
| 5522 |
var fnArray = []; |
| 5523 |
for (var j = 0, jj = fnObj.length; j < jj; j++) { |
| 5524 |
var obj = xref.fetchIfRef(fnObj[j]); |
| 5525 |
fnArray.push(PDFFunction.parse(xref, obj)); |
| 5526 |
} |
| 5527 |
return function (src, srcOffset, dest, destOffset) { |
| 5528 |
for (var i = 0, ii = fnArray.length; i < ii; i++) { |
| 5529 |
fnArray[i](src, srcOffset, dest, destOffset + i); |
| 5530 |
} |
| 5531 |
}; |
| 5532 |
}, |
| 5533 |
|
| 5534 |
constructSampled: function PDFFunction_constructSampled(str, dict) { |
| 5535 |
function toMultiArray(arr) { |
| 5536 |
var inputLength = arr.length; |
| 5537 |
var out = []; |
| 5538 |
var index = 0; |
| 5539 |
for (var i = 0; i < inputLength; i += 2) { |
| 5540 |
out[index] = [arr[i], arr[i + 1]]; |
| 5541 |
++index; |
| 5542 |
} |
| 5543 |
return out; |
| 5544 |
} |
| 5545 |
var domain = dict.get('Domain'); |
| 5546 |
var range = dict.get('Range'); |
| 5547 |
|
| 5548 |
if (!domain || !range) { |
| 5549 |
error('No domain or range'); |
| 5550 |
} |
| 5551 |
|
| 5552 |
var inputSize = domain.length / 2; |
| 5553 |
var outputSize = range.length / 2; |
| 5554 |
|
| 5555 |
domain = toMultiArray(domain); |
| 5556 |
range = toMultiArray(range); |
| 5557 |
|
| 5558 |
var size = dict.get('Size'); |
| 5559 |
var bps = dict.get('BitsPerSample'); |
| 5560 |
var order = dict.get('Order') || 1; |
| 5561 |
if (order !== 1) { |
| 5562 |
// No description how cubic spline interpolation works in PDF32000:2008 |
| 5563 |
// As in poppler, ignoring order, linear interpolation may work as good |
| 5564 |
info('No support for cubic spline interpolation: ' + order); |
| 5565 |
} |
| 5566 |
|
| 5567 |
var encode = dict.get('Encode'); |
| 5568 |
if (!encode) { |
| 5569 |
encode = []; |
| 5570 |
for (var i = 0; i < inputSize; ++i) { |
| 5571 |
encode.push(0); |
| 5572 |
encode.push(size[i] - 1); |
| 5573 |
} |
| 5574 |
} |
| 5575 |
encode = toMultiArray(encode); |
| 5576 |
|
| 5577 |
var decode = dict.get('Decode'); |
| 5578 |
if (!decode) { |
| 5579 |
decode = range; |
| 5580 |
} else { |
| 5581 |
decode = toMultiArray(decode); |
| 5582 |
} |
| 5583 |
|
| 5584 |
var samples = this.getSampleArray(size, outputSize, bps, str); |
| 5585 |
|
| 5586 |
return [ |
| 5587 |
CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, |
| 5588 |
outputSize, Math.pow(2, bps) - 1, range |
| 5589 |
]; |
| 5590 |
}, |
| 5591 |
|
| 5592 |
constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) { |
| 5593 |
// See chapter 3, page 109 of the PDF reference |
| 5594 |
function interpolate(x, xmin, xmax, ymin, ymax) { |
| 5595 |
return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin))); |
| 5596 |
} |
| 5597 |
|
| 5598 |
return function constructSampledFromIRResult(src, srcOffset, |
| 5599 |
dest, destOffset) { |
| 5600 |
// See chapter 3, page 110 of the PDF reference. |
| 5601 |
var m = IR[1]; |
| 5602 |
var domain = IR[2]; |
| 5603 |
var encode = IR[3]; |
| 5604 |
var decode = IR[4]; |
| 5605 |
var samples = IR[5]; |
| 5606 |
var size = IR[6]; |
| 5607 |
var n = IR[7]; |
| 5608 |
//var mask = IR[8]; |
| 5609 |
var range = IR[9]; |
| 5610 |
|
| 5611 |
// Building the cube vertices: its part and sample index |
| 5612 |
// http://rjwagner49.com/Mathematics/Interpolation.pdf |
| 5613 |
var cubeVertices = 1 << m; |
| 5614 |
var cubeN = new Float64Array(cubeVertices); |
| 5615 |
var cubeVertex = new Uint32Array(cubeVertices); |
| 5616 |
var i, j; |
| 5617 |
for (j = 0; j < cubeVertices; j++) { |
| 5618 |
cubeN[j] = 1; |
| 5619 |
} |
| 5620 |
|
| 5621 |
var k = n, pos = 1; |
| 5622 |
// Map x_i to y_j for 0 <= i < m using the sampled function. |
| 5623 |
for (i = 0; i < m; ++i) { |
| 5624 |
// x_i' = min(max(x_i, Domain_2i), Domain_2i+1) |
| 5625 |
var domain_2i = domain[i][0]; |
| 5626 |
var domain_2i_1 = domain[i][1]; |
| 5627 |
var xi = Math.min(Math.max(src[srcOffset +i], domain_2i), |
| 5628 |
domain_2i_1); |
| 5629 |
|
| 5630 |
// e_i = Interpolate(x_i', Domain_2i, Domain_2i+1, |
| 5631 |
// Encode_2i, Encode_2i+1) |
| 5632 |
var e = interpolate(xi, domain_2i, domain_2i_1, |
| 5633 |
encode[i][0], encode[i][1]); |
| 5634 |
|
| 5635 |
// e_i' = min(max(e_i, 0), Size_i - 1) |
| 5636 |
var size_i = size[i]; |
| 5637 |
e = Math.min(Math.max(e, 0), size_i - 1); |
| 5638 |
|
| 5639 |
// Adjusting the cube: N and vertex sample index |
| 5640 |
var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1; |
| 5641 |
var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0); |
| 5642 |
var n1 = e - e0; // (e - e0) / (e1 - e0); |
| 5643 |
var offset0 = e0 * k; |
| 5644 |
var offset1 = offset0 + k; // e1 * k |
| 5645 |
for (j = 0; j < cubeVertices; j++) { |
| 5646 |
if (j & pos) { |
| 5647 |
cubeN[j] *= n1; |
| 5648 |
cubeVertex[j] += offset1; |
| 5649 |
} else { |
| 5650 |
cubeN[j] *= n0; |
| 5651 |
cubeVertex[j] += offset0; |
| 5652 |
} |
| 5653 |
} |
| 5654 |
|
| 5655 |
k *= size_i; |
| 5656 |
pos <<= 1; |
| 5657 |
} |
| 5658 |
|
| 5659 |
for (j = 0; j < n; ++j) { |
| 5660 |
// Sum all cube vertices' samples portions |
| 5661 |
var rj = 0; |
| 5662 |
for (i = 0; i < cubeVertices; i++) { |
| 5663 |
rj += samples[cubeVertex[i] + j] * cubeN[i]; |
| 5664 |
} |
| 5665 |
|
| 5666 |
// r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1, |
| 5667 |
// Decode_2j, Decode_2j+1) |
| 5668 |
rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]); |
| 5669 |
|
| 5670 |
// y_j = min(max(r_j, range_2j), range_2j+1) |
| 5671 |
dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), |
| 5672 |
range[j][1]); |
| 5673 |
} |
| 5674 |
}; |
| 5675 |
}, |
| 5676 |
|
| 5677 |
constructInterpolated: function PDFFunction_constructInterpolated(str, |
| 5678 |
dict) { |
| 5679 |
var c0 = dict.get('C0') || [0]; |
| 5680 |
var c1 = dict.get('C1') || [1]; |
| 5681 |
var n = dict.get('N'); |
| 5682 |
|
| 5683 |
if (!isArray(c0) || !isArray(c1)) { |
| 5684 |
error('Illegal dictionary for interpolated function'); |
| 5685 |
} |
| 5686 |
|
| 5687 |
var length = c0.length; |
| 5688 |
var diff = []; |
| 5689 |
for (var i = 0; i < length; ++i) { |
| 5690 |
diff.push(c1[i] - c0[i]); |
| 5691 |
} |
| 5692 |
|
| 5693 |
return [CONSTRUCT_INTERPOLATED, c0, diff, n]; |
| 5694 |
}, |
| 5695 |
|
| 5696 |
constructInterpolatedFromIR: |
| 5697 |
function PDFFunction_constructInterpolatedFromIR(IR) { |
| 5698 |
var c0 = IR[1]; |
| 5699 |
var diff = IR[2]; |
| 5700 |
var n = IR[3]; |
| 5701 |
|
| 5702 |
var length = diff.length; |
| 5703 |
|
| 5704 |
return function constructInterpolatedFromIRResult(src, srcOffset, |
| 5705 |
dest, destOffset) { |
| 5706 |
var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n); |
| 5707 |
|
| 5708 |
for (var j = 0; j < length; ++j) { |
| 5709 |
dest[destOffset + j] = c0[j] + (x * diff[j]); |
| 5710 |
} |
| 5711 |
}; |
| 5712 |
}, |
| 5713 |
|
| 5714 |
constructStiched: function PDFFunction_constructStiched(fn, dict, xref) { |
| 5715 |
var domain = dict.get('Domain'); |
| 5716 |
|
| 5717 |
if (!domain) { |
| 5718 |
error('No domain'); |
| 5719 |
} |
| 5720 |
|
| 5721 |
var inputSize = domain.length / 2; |
| 5722 |
if (inputSize !== 1) { |
| 5723 |
error('Bad domain for stiched function'); |
| 5724 |
} |
| 5725 |
|
| 5726 |
var fnRefs = dict.get('Functions'); |
| 5727 |
var fns = []; |
| 5728 |
for (var i = 0, ii = fnRefs.length; i < ii; ++i) { |
| 5729 |
fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i]))); |
| 5730 |
} |
| 5731 |
|
| 5732 |
var bounds = dict.get('Bounds'); |
| 5733 |
var encode = dict.get('Encode'); |
| 5734 |
|
| 5735 |
return [CONSTRUCT_STICHED, domain, bounds, encode, fns]; |
| 5736 |
}, |
| 5737 |
|
| 5738 |
constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) { |
| 5739 |
var domain = IR[1]; |
| 5740 |
var bounds = IR[2]; |
| 5741 |
var encode = IR[3]; |
| 5742 |
var fnsIR = IR[4]; |
| 5743 |
var fns = []; |
| 5744 |
var tmpBuf = new Float32Array(1); |
| 5745 |
|
| 5746 |
for (var i = 0, ii = fnsIR.length; i < ii; i++) { |
| 5747 |
fns.push(PDFFunction.fromIR(fnsIR[i])); |
| 5748 |
} |
| 5749 |
|
| 5750 |
return function constructStichedFromIRResult(src, srcOffset, |
| 5751 |
dest, destOffset) { |
| 5752 |
var clip = function constructStichedFromIRClip(v, min, max) { |
| 5753 |
if (v > max) { |
| 5754 |
v = max; |
| 5755 |
} else if (v < min) { |
| 5756 |
v = min; |
| 5757 |
} |
| 5758 |
return v; |
| 5759 |
}; |
| 5760 |
|
| 5761 |
// clip to domain |
| 5762 |
var v = clip(src[srcOffset], domain[0], domain[1]); |
| 5763 |
// calulate which bound the value is in |
| 5764 |
for (var i = 0, ii = bounds.length; i < ii; ++i) { |
| 5765 |
if (v < bounds[i]) { |
| 5766 |
break; |
| 5767 |
} |
| 5768 |
} |
| 5769 |
|
| 5770 |
// encode value into domain of function |
| 5771 |
var dmin = domain[0]; |
| 5772 |
if (i > 0) { |
| 5773 |
dmin = bounds[i - 1]; |
| 5774 |
} |
| 5775 |
var dmax = domain[1]; |
| 5776 |
if (i < bounds.length) { |
| 5777 |
dmax = bounds[i]; |
| 5778 |
} |
| 5779 |
|
| 5780 |
var rmin = encode[2 * i]; |
| 5781 |
var rmax = encode[2 * i + 1]; |
| 5782 |
|
| 5783 |
tmpBuf[0] = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); |
| 5784 |
|
| 5785 |
// call the appropriate function |
| 5786 |
fns[i](tmpBuf, 0, dest, destOffset); |
| 5787 |
}; |
| 5788 |
}, |
| 5789 |
|
| 5790 |
constructPostScript: function PDFFunction_constructPostScript(fn, dict, |
| 5791 |
xref) { |
| 5792 |
var domain = dict.get('Domain'); |
| 5793 |
var range = dict.get('Range'); |
| 5794 |
|
| 5795 |
if (!domain) { |
| 5796 |
error('No domain.'); |
| 5797 |
} |
| 5798 |
|
| 5799 |
if (!range) { |
| 5800 |
error('No range.'); |
| 5801 |
} |
| 5802 |
|
| 5803 |
var lexer = new PostScriptLexer(fn); |
| 5804 |
var parser = new PostScriptParser(lexer); |
| 5805 |
var code = parser.parse(); |
| 5806 |
|
| 5807 |
return [CONSTRUCT_POSTSCRIPT, domain, range, code]; |
| 5808 |
}, |
| 5809 |
|
| 5810 |
constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR( |
| 5811 |
IR) { |
| 5812 |
var domain = IR[1]; |
| 5813 |
var range = IR[2]; |
| 5814 |
var code = IR[3]; |
| 5815 |
|
| 5816 |
var compiled = (new PostScriptCompiler()).compile(code, domain, range); |
| 5817 |
if (compiled) { |
| 5818 |
// Compiled function consists of simple expressions such as addition, |
| 5819 |
// subtraction, Math.max, and also contains 'var' and 'return' |
| 5820 |
// statements. See the generation in the PostScriptCompiler below. |
| 5821 |
/*jshint -W054 */ |
| 5822 |
return new Function('src', 'srcOffset', 'dest', 'destOffset', compiled); |
| 5823 |
} |
| 5824 |
|
| 5825 |
info('Unable to compile PS function'); |
| 5826 |
|
| 5827 |
var numOutputs = range.length >> 1; |
| 5828 |
var numInputs = domain.length >> 1; |
| 5829 |
var evaluator = new PostScriptEvaluator(code); |
| 5830 |
// Cache the values for a big speed up, the cache size is limited though |
| 5831 |
// since the number of possible values can be huge from a PS function. |
| 5832 |
var cache = {}; |
| 5833 |
// The MAX_CACHE_SIZE is set to ~4x the maximum number of distinct values |
| 5834 |
// seen in our tests. |
| 5835 |
var MAX_CACHE_SIZE = 2048 * 4; |
| 5836 |
var cache_available = MAX_CACHE_SIZE; |
| 5837 |
var tmpBuf = new Float32Array(numInputs); |
| 5838 |
|
| 5839 |
return function constructPostScriptFromIRResult(src, srcOffset, |
| 5840 |
dest, destOffset) { |
| 5841 |
var i, value; |
| 5842 |
var key = ''; |
| 5843 |
var input = tmpBuf; |
| 5844 |
for (i = 0; i < numInputs; i++) { |
| 5845 |
value = src[srcOffset + i]; |
| 5846 |
input[i] = value; |
| 5847 |
key += value + '_'; |
| 5848 |
} |
| 5849 |
|
| 5850 |
var cachedValue = cache[key]; |
| 5851 |
if (cachedValue !== undefined) { |
| 5852 |
dest.set(cachedValue, destOffset); |
| 5853 |
return; |
| 5854 |
} |
| 5855 |
|
| 5856 |
var output = new Float32Array(numOutputs); |
| 5857 |
var stack = evaluator.execute(input); |
| 5858 |
var stackIndex = stack.length - numOutputs; |
| 5859 |
for (i = 0; i < numOutputs; i++) { |
| 5860 |
value = stack[stackIndex + i]; |
| 5861 |
var bound = range[i * 2]; |
| 5862 |
if (value < bound) { |
| 5863 |
value = bound; |
| 5864 |
} else { |
| 5865 |
bound = range[i * 2 +1]; |
| 5866 |
if (value > bound) { |
| 5867 |
value = bound; |
| 5868 |
} |
| 5869 |
} |
| 5870 |
output[i] = value; |
| 5871 |
} |
| 5872 |
if (cache_available > 0) { |
| 5873 |
cache_available--; |
| 5874 |
cache[key] = output; |
| 5875 |
} |
| 5876 |
dest.set(output, destOffset); |
| 5877 |
}; |
| 5878 |
} |
| 5879 |
}; |
| 5880 |
})(); |
| 5881 |
|
| 5882 |
function isPDFFunction(v) { |
| 5883 |
var fnDict; |
| 5884 |
if (typeof v !== 'object') { |
| 5885 |
return false; |
| 5886 |
} else if (isDict(v)) { |
| 5887 |
fnDict = v; |
| 5888 |
} else if (isStream(v)) { |
| 5889 |
fnDict = v.dict; |
| 5890 |
} else { |
| 5891 |
return false; |
| 5892 |
} |
| 5893 |
return fnDict.has('FunctionType'); |
| 5894 |
} |
| 5895 |
|
| 5896 |
var PostScriptStack = (function PostScriptStackClosure() { |
| 5897 |
var MAX_STACK_SIZE = 100; |
| 5898 |
function PostScriptStack(initialStack) { |
| 5899 |
this.stack = !initialStack ? [] : |
| 5900 |
Array.prototype.slice.call(initialStack, 0); |
| 5901 |
} |
| 5902 |
|
| 5903 |
PostScriptStack.prototype = { |
| 5904 |
push: function PostScriptStack_push(value) { |
| 5905 |
if (this.stack.length >= MAX_STACK_SIZE) { |
| 5906 |
error('PostScript function stack overflow.'); |
| 5907 |
} |
| 5908 |
this.stack.push(value); |
| 5909 |
}, |
| 5910 |
pop: function PostScriptStack_pop() { |
| 5911 |
if (this.stack.length <= 0) { |
| 5912 |
error('PostScript function stack underflow.'); |
| 5913 |
} |
| 5914 |
return this.stack.pop(); |
| 5915 |
}, |
| 5916 |
copy: function PostScriptStack_copy(n) { |
| 5917 |
if (this.stack.length + n >= MAX_STACK_SIZE) { |
| 5918 |
error('PostScript function stack overflow.'); |
| 5919 |
} |
| 5920 |
var stack = this.stack; |
| 5921 |
for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) { |
| 5922 |
stack.push(stack[i]); |
| 5923 |
} |
| 5924 |
}, |
| 5925 |
index: function PostScriptStack_index(n) { |
| 5926 |
this.push(this.stack[this.stack.length - n - 1]); |
| 5927 |
}, |
| 5928 |
// rotate the last n stack elements p times |
| 5929 |
roll: function PostScriptStack_roll(n, p) { |
| 5930 |
var stack = this.stack; |
| 5931 |
var l = stack.length - n; |
| 5932 |
var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t; |
| 5933 |
for (i = l, j = r; i < j; i++, j--) { |
| 5934 |
t = stack[i]; stack[i] = stack[j]; stack[j] = t; |
| 5935 |
} |
| 5936 |
for (i = l, j = c - 1; i < j; i++, j--) { |
| 5937 |
t = stack[i]; stack[i] = stack[j]; stack[j] = t; |
| 5938 |
} |
| 5939 |
for (i = c, j = r; i < j; i++, j--) { |
| 5940 |
t = stack[i]; stack[i] = stack[j]; stack[j] = t; |
| 5941 |
} |
| 5942 |
} |
| 5943 |
}; |
| 5944 |
return PostScriptStack; |
| 5945 |
})(); |
| 5946 |
var PostScriptEvaluator = (function PostScriptEvaluatorClosure() { |
| 5947 |
function PostScriptEvaluator(operators) { |
| 5948 |
this.operators = operators; |
| 5949 |
} |
| 5950 |
PostScriptEvaluator.prototype = { |
| 5951 |
execute: function PostScriptEvaluator_execute(initialStack) { |
| 5952 |
var stack = new PostScriptStack(initialStack); |
| 5953 |
var counter = 0; |
| 5954 |
var operators = this.operators; |
| 5955 |
var length = operators.length; |
| 5956 |
var operator, a, b; |
| 5957 |
while (counter < length) { |
| 5958 |
operator = operators[counter++]; |
| 5959 |
if (typeof operator === 'number') { |
| 5960 |
// Operator is really an operand and should be pushed to the stack. |
| 5961 |
stack.push(operator); |
| 5962 |
continue; |
| 5963 |
} |
| 5964 |
switch (operator) { |
| 5965 |
// non standard ps operators |
| 5966 |
case 'jz': // jump if false |
| 5967 |
b = stack.pop(); |
| 5968 |
a = stack.pop(); |
| 5969 |
if (!a) { |
| 5970 |
counter = b; |
| 5971 |
} |
| 5972 |
break; |
| 5973 |
case 'j': // jump |
| 5974 |
a = stack.pop(); |
| 5975 |
counter = a; |
| 5976 |
break; |
| 5977 |
|
| 5978 |
// all ps operators in alphabetical order (excluding if/ifelse) |
| 5979 |
case 'abs': |
| 5980 |
a = stack.pop(); |
| 5981 |
stack.push(Math.abs(a)); |
| 5982 |
break; |
| 5983 |
case 'add': |
| 5984 |
b = stack.pop(); |
| 5985 |
a = stack.pop(); |
| 5986 |
stack.push(a + b); |
| 5987 |
break; |
| 5988 |
case 'and': |
| 5989 |
b = stack.pop(); |
| 5990 |
a = stack.pop(); |
| 5991 |
if (isBool(a) && isBool(b)) { |
| 5992 |
stack.push(a && b); |
| 5993 |
} else { |
| 5994 |
stack.push(a & b); |
| 5995 |
} |
| 5996 |
break; |
| 5997 |
case 'atan': |
| 5998 |
a = stack.pop(); |
| 5999 |
stack.push(Math.atan(a)); |
| 6000 |
break; |
| 6001 |
case 'bitshift': |
| 6002 |
b = stack.pop(); |
| 6003 |
a = stack.pop(); |
| 6004 |
if (a > 0) { |
| 6005 |
stack.push(a << b); |
| 6006 |
} else { |
| 6007 |
stack.push(a >> b); |
| 6008 |
} |
| 6009 |
break; |
| 6010 |
case 'ceiling': |
| 6011 |
a = stack.pop(); |
| 6012 |
stack.push(Math.ceil(a)); |
| 6013 |
break; |
| 6014 |
case 'copy': |
| 6015 |
a = stack.pop(); |
| 6016 |
stack.copy(a); |
| 6017 |
break; |
| 6018 |
case 'cos': |
| 6019 |
a = stack.pop(); |
| 6020 |
stack.push(Math.cos(a)); |
| 6021 |
break; |
| 6022 |
case 'cvi': |
| 6023 |
a = stack.pop() | 0; |
| 6024 |
stack.push(a); |
| 6025 |
break; |
| 6026 |
case 'cvr': |
| 6027 |
// noop |
| 6028 |
break; |
| 6029 |
case 'div': |
| 6030 |
b = stack.pop(); |
| 6031 |
a = stack.pop(); |
| 6032 |
stack.push(a / b); |
| 6033 |
break; |
| 6034 |
case 'dup': |
| 6035 |
stack.copy(1); |
| 6036 |
break; |
| 6037 |
case 'eq': |
| 6038 |
b = stack.pop(); |
| 6039 |
a = stack.pop(); |
| 6040 |
stack.push(a === b); |
| 6041 |
break; |
| 6042 |
case 'exch': |
| 6043 |
stack.roll(2, 1); |
| 6044 |
break; |
| 6045 |
case 'exp': |
| 6046 |
b = stack.pop(); |
| 6047 |
a = stack.pop(); |
| 6048 |
stack.push(Math.pow(a, b)); |
| 6049 |
break; |
| 6050 |
case 'false': |
| 6051 |
stack.push(false); |
| 6052 |
break; |
| 6053 |
case 'floor': |
| 6054 |
a = stack.pop(); |
| 6055 |
stack.push(Math.floor(a)); |
| 6056 |
break; |
| 6057 |
case 'ge': |
| 6058 |
b = stack.pop(); |
| 6059 |
a = stack.pop(); |
| 6060 |
stack.push(a >= b); |
| 6061 |
break; |
| 6062 |
case 'gt': |
| 6063 |
b = stack.pop(); |
| 6064 |
a = stack.pop(); |
| 6065 |
stack.push(a > b); |
| 6066 |
break; |
| 6067 |
case 'idiv': |
| 6068 |
b = stack.pop(); |
| 6069 |
a = stack.pop(); |
| 6070 |
stack.push((a / b) | 0); |
| 6071 |
break; |
| 6072 |
case 'index': |
| 6073 |
a = stack.pop(); |
| 6074 |
stack.index(a); |
| 6075 |
break; |
| 6076 |
case 'le': |
| 6077 |
b = stack.pop(); |
| 6078 |
a = stack.pop(); |
| 6079 |
stack.push(a <= b); |
| 6080 |
break; |
| 6081 |
case 'ln': |
| 6082 |
a = stack.pop(); |
| 6083 |
stack.push(Math.log(a)); |
| 6084 |
break; |
| 6085 |
case 'log': |
| 6086 |
a = stack.pop(); |
| 6087 |
stack.push(Math.log(a) / Math.LN10); |
| 6088 |
break; |
| 6089 |
case 'lt': |
| 6090 |
b = stack.pop(); |
| 6091 |
a = stack.pop(); |
| 6092 |
stack.push(a < b); |
| 6093 |
break; |
| 6094 |
case 'mod': |
| 6095 |
b = stack.pop(); |
| 6096 |
a = stack.pop(); |
| 6097 |
stack.push(a % b); |
| 6098 |
break; |
| 6099 |
case 'mul': |
| 6100 |
b = stack.pop(); |
| 6101 |
a = stack.pop(); |
| 6102 |
stack.push(a * b); |
| 6103 |
break; |
| 6104 |
case 'ne': |
| 6105 |
b = stack.pop(); |
| 6106 |
a = stack.pop(); |
| 6107 |
stack.push(a !== b); |
| 6108 |
break; |
| 6109 |
case 'neg': |
| 6110 |
a = stack.pop(); |
| 6111 |
stack.push(-a); |
| 6112 |
break; |
| 6113 |
case 'not': |
| 6114 |
a = stack.pop(); |
| 6115 |
if (isBool(a)) { |
| 6116 |
stack.push(!a); |
| 6117 |
} else { |
| 6118 |
stack.push(~a); |
| 6119 |
} |
| 6120 |
break; |
| 6121 |
case 'or': |
| 6122 |
b = stack.pop(); |
| 6123 |
a = stack.pop(); |
| 6124 |
if (isBool(a) && isBool(b)) { |
| 6125 |
stack.push(a || b); |
| 6126 |
} else { |
| 6127 |
stack.push(a | b); |
| 6128 |
} |
| 6129 |
break; |
| 6130 |
case 'pop': |
| 6131 |
stack.pop(); |
| 6132 |
break; |
| 6133 |
case 'roll': |
| 6134 |
b = stack.pop(); |
| 6135 |
a = stack.pop(); |
| 6136 |
stack.roll(a, b); |
| 6137 |
break; |
| 6138 |
case 'round': |
| 6139 |
a = stack.pop(); |
| 6140 |
stack.push(Math.round(a)); |
| 6141 |
break; |
| 6142 |
case 'sin': |
| 6143 |
a = stack.pop(); |
| 6144 |
stack.push(Math.sin(a)); |
| 6145 |
break; |
| 6146 |
case 'sqrt': |
| 6147 |
a = stack.pop(); |
| 6148 |
stack.push(Math.sqrt(a)); |
| 6149 |
break; |
| 6150 |
case 'sub': |
| 6151 |
b = stack.pop(); |
| 6152 |
a = stack.pop(); |
| 6153 |
stack.push(a - b); |
| 6154 |
break; |
| 6155 |
case 'true': |
| 6156 |
stack.push(true); |
| 6157 |
break; |
| 6158 |
case 'truncate': |
| 6159 |
a = stack.pop(); |
| 6160 |
a = a < 0 ? Math.ceil(a) : Math.floor(a); |
| 6161 |
stack.push(a); |
| 6162 |
break; |
| 6163 |
case 'xor': |
| 6164 |
b = stack.pop(); |
| 6165 |
a = stack.pop(); |
| 6166 |
if (isBool(a) && isBool(b)) { |
| 6167 |
stack.push(a !== b); |
| 6168 |
} else { |
| 6169 |
stack.push(a ^ b); |
| 6170 |
} |
| 6171 |
break; |
| 6172 |
default: |
| 6173 |
error('Unknown operator ' + operator); |
| 6174 |
break; |
| 6175 |
} |
| 6176 |
} |
| 6177 |
return stack.stack; |
| 6178 |
} |
| 6179 |
}; |
| 6180 |
return PostScriptEvaluator; |
| 6181 |
})(); |
| 6182 |
|
| 6183 |
// Most of the PDFs functions consist of simple operations such as: |
| 6184 |
// roll, exch, sub, cvr, pop, index, dup, mul, if, gt, add. |
| 6185 |
// |
| 6186 |
// We can compile most of such programs, and at the same moment, we can |
| 6187 |
// optimize some expressions using basic math properties. Keeping track of |
| 6188 |
// min/max values will allow us to avoid extra Math.min/Math.max calls. |
| 6189 |
var PostScriptCompiler = (function PostScriptCompilerClosure() { |
| 6190 |
function AstNode(type) { |
| 6191 |
this.type = type; |
| 6192 |
} |
| 6193 |
AstNode.prototype.visit = function (visitor) { |
| 6194 |
throw new Error('abstract method'); |
| 6195 |
}; |
| 6196 |
|
| 6197 |
function AstArgument(index, min, max) { |
| 6198 |
AstNode.call(this, 'args'); |
| 6199 |
this.index = index; |
| 6200 |
this.min = min; |
| 6201 |
this.max = max; |
| 6202 |
} |
| 6203 |
AstArgument.prototype = Object.create(AstNode.prototype); |
| 6204 |
AstArgument.prototype.visit = function (visitor) { |
| 6205 |
visitor.visitArgument(this); |
| 6206 |
}; |
| 6207 |
|
| 6208 |
function AstLiteral(number) { |
| 6209 |
AstNode.call(this, 'literal'); |
| 6210 |
this.number = number; |
| 6211 |
this.min = number; |
| 6212 |
this.max = number; |
| 6213 |
} |
| 6214 |
AstLiteral.prototype = Object.create(AstNode.prototype); |
| 6215 |
AstLiteral.prototype.visit = function (visitor) { |
| 6216 |
visitor.visitLiteral(this); |
| 6217 |
}; |
| 6218 |
|
| 6219 |
function AstBinaryOperation(op, arg1, arg2, min, max) { |
| 6220 |
AstNode.call(this, 'binary'); |
| 6221 |
this.op = op; |
| 6222 |
this.arg1 = arg1; |
| 6223 |
this.arg2 = arg2; |
| 6224 |
this.min = min; |
| 6225 |
this.max = max; |
| 6226 |
} |
| 6227 |
AstBinaryOperation.prototype = Object.create(AstNode.prototype); |
| 6228 |
AstBinaryOperation.prototype.visit = function (visitor) { |
| 6229 |
visitor.visitBinaryOperation(this); |
| 6230 |
}; |
| 6231 |
|
| 6232 |
function AstMin(arg, max) { |
| 6233 |
AstNode.call(this, 'max'); |
| 6234 |
this.arg = arg; |
| 6235 |
this.min = arg.min; |
| 6236 |
this.max = max; |
| 6237 |
} |
| 6238 |
AstMin.prototype = Object.create(AstNode.prototype); |
| 6239 |
AstMin.prototype.visit = function (visitor) { |
| 6240 |
visitor.visitMin(this); |
| 6241 |
}; |
| 6242 |
|
| 6243 |
function AstVariable(index, min, max) { |
| 6244 |
AstNode.call(this, 'var'); |
| 6245 |
this.index = index; |
| 6246 |
this.min = min; |
| 6247 |
this.max = max; |
| 6248 |
} |
| 6249 |
AstVariable.prototype = Object.create(AstNode.prototype); |
| 6250 |
AstVariable.prototype.visit = function (visitor) { |
| 6251 |
visitor.visitVariable(this); |
| 6252 |
}; |
| 6253 |
|
| 6254 |
function AstVariableDefinition(variable, arg) { |
| 6255 |
AstNode.call(this, 'definition'); |
| 6256 |
this.variable = variable; |
| 6257 |
this.arg = arg; |
| 6258 |
} |
| 6259 |
AstVariableDefinition.prototype = Object.create(AstNode.prototype); |
| 6260 |
AstVariableDefinition.prototype.visit = function (visitor) { |
| 6261 |
visitor.visitVariableDefinition(this); |
| 6262 |
}; |
| 6263 |
|
| 6264 |
function ExpressionBuilderVisitor() { |
| 6265 |
this.parts = []; |
| 6266 |
} |
| 6267 |
ExpressionBuilderVisitor.prototype = { |
| 6268 |
visitArgument: function (arg) { |
| 6269 |
this.parts.push('Math.max(', arg.min, ', Math.min(', |
| 6270 |
arg.max, ', src[srcOffset + ', arg.index, ']))'); |
| 6271 |
}, |
| 6272 |
visitVariable: function (variable) { |
| 6273 |
this.parts.push('v', variable.index); |
| 6274 |
}, |
| 6275 |
visitLiteral: function (literal) { |
| 6276 |
this.parts.push(literal.number); |
| 6277 |
}, |
| 6278 |
visitBinaryOperation: function (operation) { |
| 6279 |
this.parts.push('('); |
| 6280 |
operation.arg1.visit(this); |
| 6281 |
this.parts.push(' ', operation.op, ' '); |
| 6282 |
operation.arg2.visit(this); |
| 6283 |
this.parts.push(')'); |
| 6284 |
}, |
| 6285 |
visitVariableDefinition: function (definition) { |
| 6286 |
this.parts.push('var '); |
| 6287 |
definition.variable.visit(this); |
| 6288 |
this.parts.push(' = '); |
| 6289 |
definition.arg.visit(this); |
| 6290 |
this.parts.push(';'); |
| 6291 |
}, |
| 6292 |
visitMin: function (max) { |
| 6293 |
this.parts.push('Math.min('); |
| 6294 |
max.arg.visit(this); |
| 6295 |
this.parts.push(', ', max.max, ')'); |
| 6296 |
}, |
| 6297 |
toString: function () { |
| 6298 |
return this.parts.join(''); |
| 6299 |
} |
| 6300 |
}; |
| 6301 |
|
| 6302 |
function buildAddOperation(num1, num2) { |
| 6303 |
if (num2.type === 'literal' && num2.number === 0) { |
| 6304 |
// optimization: second operand is 0 |
| 6305 |
return num1; |
| 6306 |
} |
| 6307 |
if (num1.type === 'literal' && num1.number === 0) { |
| 6308 |
// optimization: first operand is 0 |
| 6309 |
return num2; |
| 6310 |
} |
| 6311 |
if (num2.type === 'literal' && num1.type === 'literal') { |
| 6312 |
// optimization: operands operand are literals |
| 6313 |
return new AstLiteral(num1.number + num2.number); |
| 6314 |
} |
| 6315 |
return new AstBinaryOperation('+', num1, num2, |
| 6316 |
num1.min + num2.min, num1.max + num2.max); |
| 6317 |
} |
| 6318 |
|
| 6319 |
function buildMulOperation(num1, num2) { |
| 6320 |
if (num2.type === 'literal') { |
| 6321 |
// optimization: second operands is a literal... |
| 6322 |
if (num2.number === 0) { |
| 6323 |
return new AstLiteral(0); // and it's 0 |
| 6324 |
} else if (num2.number === 1) { |
| 6325 |
return num1; // and it's 1 |
| 6326 |
} else if (num1.type === 'literal') { |
| 6327 |
// ... and first operands is a literal too |
| 6328 |
return new AstLiteral(num1.number * num2.number); |
| 6329 |
} |
| 6330 |
} |
| 6331 |
if (num1.type === 'literal') { |
| 6332 |
// optimization: first operands is a literal... |
| 6333 |
if (num1.number === 0) { |
| 6334 |
return new AstLiteral(0); // and it's 0 |
| 6335 |
} else if (num1.number === 1) { |
| 6336 |
return num2; // and it's 1 |
| 6337 |
} |
| 6338 |
} |
| 6339 |
var min = Math.min(num1.min * num2.min, num1.min * num2.max, |
| 6340 |
num1.max * num2.min, num1.max * num2.max); |
| 6341 |
var max = Math.max(num1.min * num2.min, num1.min * num2.max, |
| 6342 |
num1.max * num2.min, num1.max * num2.max); |
| 6343 |
return new AstBinaryOperation('*', num1, num2, min, max); |
| 6344 |
} |
| 6345 |
|
| 6346 |
function buildSubOperation(num1, num2) { |
| 6347 |
if (num2.type === 'literal') { |
| 6348 |
// optimization: second operands is a literal... |
| 6349 |
if (num2.number === 0) { |
| 6350 |
return num1; // ... and it's 0 |
| 6351 |
} else if (num1.type === 'literal') { |
| 6352 |
// ... and first operands is a literal too |
| 6353 |
return new AstLiteral(num1.number - num2.number); |
| 6354 |
} |
| 6355 |
} |
| 6356 |
if (num2.type === 'binary' && num2.op === '-' && |
| 6357 |
num1.type === 'literal' && num1.number === 1 && |
| 6358 |
num2.arg1.type === 'literal' && num2.arg1.number === 1) { |
| 6359 |
// optimization for case: 1 - (1 - x) |
| 6360 |
return num2.arg2; |
| 6361 |
} |
| 6362 |
return new AstBinaryOperation('-', num1, num2, |
| 6363 |
num1.min - num2.max, num1.max - num2.min); |
| 6364 |
} |
| 6365 |
|
| 6366 |
function buildMinOperation(num1, max) { |
| 6367 |
if (num1.min >= max) { |
| 6368 |
// optimization: num1 min value is not less than required max |
| 6369 |
return new AstLiteral(max); // just returning max |
| 6370 |
} else if (num1.max <= max) { |
| 6371 |
// optimization: num1 max value is not greater than required max |
| 6372 |
return num1; // just returning an argument |
| 6373 |
} |
| 6374 |
return new AstMin(num1, max); |
| 6375 |
} |
| 6376 |
|
| 6377 |
function PostScriptCompiler() {} |
| 6378 |
PostScriptCompiler.prototype = { |
| 6379 |
compile: function PostScriptCompiler_compile(code, domain, range) { |
| 6380 |
var stack = []; |
| 6381 |
var i, ii; |
| 6382 |
var instructions = []; |
| 6383 |
var inputSize = domain.length >> 1, outputSize = range.length >> 1; |
| 6384 |
var lastRegister = 0; |
| 6385 |
var n, j, min, max; |
| 6386 |
var num1, num2, ast1, ast2, tmpVar, item; |
| 6387 |
for (i = 0; i < inputSize; i++) { |
| 6388 |
stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1])); |
| 6389 |
} |
| 6390 |
|
| 6391 |
for (i = 0, ii = code.length; i < ii; i++) { |
| 6392 |
item = code[i]; |
| 6393 |
if (typeof item === 'number') { |
| 6394 |
stack.push(new AstLiteral(item)); |
| 6395 |
continue; |
| 6396 |
} |
| 6397 |
|
| 6398 |
switch (item) { |
| 6399 |
case 'add': |
| 6400 |
if (stack.length < 2) { |
| 6401 |
return null; |
| 6402 |
} |
| 6403 |
num2 = stack.pop(); |
| 6404 |
num1 = stack.pop(); |
| 6405 |
stack.push(buildAddOperation(num1, num2)); |
| 6406 |
break; |
| 6407 |
case 'cvr': |
| 6408 |
if (stack.length < 1) { |
| 6409 |
return null; |
| 6410 |
} |
| 6411 |
break; |
| 6412 |
case 'mul': |
| 6413 |
if (stack.length < 2) { |
| 6414 |
return null; |
| 6415 |
} |
| 6416 |
num2 = stack.pop(); |
| 6417 |
num1 = stack.pop(); |
| 6418 |
stack.push(buildMulOperation(num1, num2)); |
| 6419 |
break; |
| 6420 |
case 'sub': |
| 6421 |
if (stack.length < 2) { |
| 6422 |
return null; |
| 6423 |
} |
| 6424 |
num2 = stack.pop(); |
| 6425 |
num1 = stack.pop(); |
| 6426 |
stack.push(buildSubOperation(num1, num2)); |
| 6427 |
break; |
| 6428 |
case 'exch': |
| 6429 |
if (stack.length < 2) { |
| 6430 |
return null; |
| 6431 |
} |
| 6432 |
ast1 = stack.pop(); ast2 = stack.pop(); |
| 6433 |
stack.push(ast1, ast2); |
| 6434 |
break; |
| 6435 |
case 'pop': |
| 6436 |
if (stack.length < 1) { |
| 6437 |
return null; |
| 6438 |
} |
| 6439 |
stack.pop(); |
| 6440 |
break; |
| 6441 |
case 'index': |
| 6442 |
if (stack.length < 1) { |
| 6443 |
return null; |
| 6444 |
} |
| 6445 |
num1 = stack.pop(); |
| 6446 |
if (num1.type !== 'literal') { |
| 6447 |
return null; |
| 6448 |
} |
| 6449 |
n = num1.number; |
| 6450 |
if (n < 0 || (n|0) !== n || stack.length < n) { |
| 6451 |
return null; |
| 6452 |
} |
| 6453 |
ast1 = stack[stack.length - n - 1]; |
| 6454 |
if (ast1.type === 'literal' || ast1.type === 'var') { |
| 6455 |
stack.push(ast1); |
| 6456 |
break; |
| 6457 |
} |
| 6458 |
tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); |
| 6459 |
stack[stack.length - n - 1] = tmpVar; |
| 6460 |
stack.push(tmpVar); |
| 6461 |
instructions.push(new AstVariableDefinition(tmpVar, ast1)); |
| 6462 |
break; |
| 6463 |
case 'dup': |
| 6464 |
if (stack.length < 1) { |
| 6465 |
return null; |
| 6466 |
} |
| 6467 |
if (typeof code[i + 1] === 'number' && code[i + 2] === 'gt' && |
| 6468 |
code[i + 3] === i + 7 && code[i + 4] === 'jz' && |
| 6469 |
code[i + 5] === 'pop' && code[i + 6] === code[i + 1]) { |
| 6470 |
// special case of the commands sequence for the min operation |
| 6471 |
num1 = stack.pop(); |
| 6472 |
stack.push(buildMinOperation(num1, code[i + 1])); |
| 6473 |
i += 6; |
| 6474 |
break; |
| 6475 |
} |
| 6476 |
ast1 = stack[stack.length - 1]; |
| 6477 |
if (ast1.type === 'literal' || ast1.type === 'var') { |
| 6478 |
// we don't have to save into intermediate variable a literal or |
| 6479 |
// variable. |
| 6480 |
stack.push(ast1); |
| 6481 |
break; |
| 6482 |
} |
| 6483 |
tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); |
| 6484 |
stack[stack.length - 1] = tmpVar; |
| 6485 |
stack.push(tmpVar); |
| 6486 |
instructions.push(new AstVariableDefinition(tmpVar, ast1)); |
| 6487 |
break; |
| 6488 |
case 'roll': |
| 6489 |
if (stack.length < 2) { |
| 6490 |
return null; |
| 6491 |
} |
| 6492 |
num2 = stack.pop(); |
| 6493 |
num1 = stack.pop(); |
| 6494 |
if (num2.type !== 'literal' || num1.type !== 'literal') { |
| 6495 |
// both roll operands must be numbers |
| 6496 |
return null; |
| 6497 |
} |
| 6498 |
j = num2.number; |
| 6499 |
n = num1.number; |
| 6500 |
if (n <= 0 || (n|0) !== n || (j|0) !== j || stack.length < n) { |
| 6501 |
// ... and integers |
| 6502 |
return null; |
| 6503 |
} |
| 6504 |
j = ((j % n) + n) % n; |
| 6505 |
if (j === 0) { |
| 6506 |
break; // just skipping -- there are nothing to rotate |
| 6507 |
} |
| 6508 |
Array.prototype.push.apply(stack, |
| 6509 |
stack.splice(stack.length - n, n - j)); |
| 6510 |
break; |
| 6511 |
default: |
| 6512 |
return null; // unsupported operator |
| 6513 |
} |
| 6514 |
} |
| 6515 |
|
| 6516 |
if (stack.length !== outputSize) { |
| 6517 |
return null; |
| 6518 |
} |
| 6519 |
|
| 6520 |
var result = []; |
| 6521 |
instructions.forEach(function (instruction) { |
| 6522 |
var statementBuilder = new ExpressionBuilderVisitor(); |
| 6523 |
instruction.visit(statementBuilder); |
| 6524 |
result.push(statementBuilder.toString()); |
| 6525 |
}); |
| 6526 |
stack.forEach(function (expr, i) { |
| 6527 |
var statementBuilder = new ExpressionBuilderVisitor(); |
| 6528 |
expr.visit(statementBuilder); |
| 6529 |
var min = range[i * 2], max = range[i * 2 + 1]; |
| 6530 |
var out = [statementBuilder.toString()]; |
| 6531 |
if (min > expr.min) { |
| 6532 |
out.unshift('Math.max(', min, ', '); |
| 6533 |
out.push(')'); |
| 6534 |
} |
| 6535 |
if (max < expr.max) { |
| 6536 |
out.unshift('Math.min(', max, ', '); |
| 6537 |
out.push(')'); |
| 6538 |
} |
| 6539 |
out.unshift('dest[destOffset + ', i, '] = '); |
| 6540 |
out.push(';'); |
| 6541 |
result.push(out.join('')); |
| 6542 |
}); |
| 6543 |
return result.join('\n'); |
| 6544 |
} |
| 6545 |
}; |
| 6546 |
|
| 6547 |
return PostScriptCompiler; |
| 6548 |
})(); |
| 6549 |
|
| 6550 |
|
| 6551 |
var ColorSpace = (function ColorSpaceClosure() { |
| 6552 |
// Constructor should define this.numComps, this.defaultColor, this.name |
| 6553 |
function ColorSpace() { |
| 6554 |
error('should not call ColorSpace constructor'); |
| 6555 |
} |
| 6556 |
|
| 6557 |
ColorSpace.prototype = { |
| 6558 |
/** |
| 6559 |
* Converts the color value to the RGB color. The color components are |
| 6560 |
* located in the src array starting from the srcOffset. Returns the array |
| 6561 |
* of the rgb components, each value ranging from [0,255]. |
| 6562 |
*/ |
| 6563 |
getRgb: function ColorSpace_getRgb(src, srcOffset) { |
| 6564 |
var rgb = new Uint8Array(3); |
| 6565 |
this.getRgbItem(src, srcOffset, rgb, 0); |
| 6566 |
return rgb; |
| 6567 |
}, |
| 6568 |
/** |
| 6569 |
* Converts the color value to the RGB color, similar to the getRgb method. |
| 6570 |
* The result placed into the dest array starting from the destOffset. |
| 6571 |
*/ |
| 6572 |
getRgbItem: function ColorSpace_getRgbItem(src, srcOffset, |
| 6573 |
dest, destOffset) { |
| 6574 |
error('Should not call ColorSpace.getRgbItem'); |
| 6575 |
}, |
| 6576 |
/** |
| 6577 |
* Converts the specified number of the color values to the RGB colors. |
| 6578 |
* The colors are located in the src array starting from the srcOffset. |
| 6579 |
* The result is placed into the dest array starting from the destOffset. |
| 6580 |
* The src array items shall be in [0,2^bits) range, the dest array items |
| 6581 |
* will be in [0,255] range. alpha01 indicates how many alpha components |
| 6582 |
* there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA |
| 6583 |
* array). |
| 6584 |
*/ |
| 6585 |
getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, |
| 6586 |
dest, destOffset, bits, |
| 6587 |
alpha01) { |
| 6588 |
error('Should not call ColorSpace.getRgbBuffer'); |
| 6589 |
}, |
| 6590 |
/** |
| 6591 |
* Determines the number of bytes required to store the result of the |
| 6592 |
* conversion done by the getRgbBuffer method. As in getRgbBuffer, |
| 6593 |
* |alpha01| is either 0 (RGB output) or 1 (RGBA output). |
| 6594 |
*/ |
| 6595 |
getOutputLength: function ColorSpace_getOutputLength(inputLength, |
| 6596 |
alpha01) { |
| 6597 |
error('Should not call ColorSpace.getOutputLength'); |
| 6598 |
}, |
| 6599 |
/** |
| 6600 |
* Returns true if source data will be equal the result/output data. |
| 6601 |
*/ |
| 6602 |
isPassthrough: function ColorSpace_isPassthrough(bits) { |
| 6603 |
return false; |
| 6604 |
}, |
| 6605 |
/** |
| 6606 |
* Fills in the RGB colors in the destination buffer. alpha01 indicates |
| 6607 |
* how many alpha components there are in the dest array; it will be either |
| 6608 |
* 0 (RGB array) or 1 (RGBA array). |
| 6609 |
*/ |
| 6610 |
fillRgb: function ColorSpace_fillRgb(dest, originalWidth, |
| 6611 |
originalHeight, width, height, |
| 6612 |
actualHeight, bpc, comps, alpha01) { |
| 6613 |
var count = originalWidth * originalHeight; |
| 6614 |
var rgbBuf = null; |
| 6615 |
var numComponentColors = 1 << bpc; |
| 6616 |
var needsResizing = originalHeight !== height || originalWidth !== width; |
| 6617 |
var i, ii; |
| 6618 |
|
| 6619 |
if (this.isPassthrough(bpc)) { |
| 6620 |
rgbBuf = comps; |
| 6621 |
} else if (this.numComps === 1 && count > numComponentColors && |
| 6622 |
this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { |
| 6623 |
// Optimization: create a color map when there is just one component and |
| 6624 |
// we are converting more colors than the size of the color map. We |
| 6625 |
// don't build the map if the colorspace is gray or rgb since those |
| 6626 |
// methods are faster than building a map. This mainly offers big speed |
| 6627 |
// ups for indexed and alternate colorspaces. |
| 6628 |
// |
| 6629 |
// TODO it may be worth while to cache the color map. While running |
| 6630 |
// testing I never hit a cache so I will leave that out for now (perhaps |
| 6631 |
// we are reparsing colorspaces too much?). |
| 6632 |
var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : |
| 6633 |
new Uint16Array(numComponentColors); |
| 6634 |
var key; |
| 6635 |
for (i = 0; i < numComponentColors; i++) { |
| 6636 |
allColors[i] = i; |
| 6637 |
} |
| 6638 |
var colorMap = new Uint8Array(numComponentColors * 3); |
| 6639 |
this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, |
| 6640 |
/* alpha01 = */ 0); |
| 6641 |
|
| 6642 |
var destPos, rgbPos; |
| 6643 |
if (!needsResizing) { |
| 6644 |
// Fill in the RGB values directly into |dest|. |
| 6645 |
destPos = 0; |
| 6646 |
for (i = 0; i < count; ++i) { |
| 6647 |
key = comps[i] * 3; |
| 6648 |
dest[destPos++] = colorMap[key]; |
| 6649 |
dest[destPos++] = colorMap[key + 1]; |
| 6650 |
dest[destPos++] = colorMap[key + 2]; |
| 6651 |
destPos += alpha01; |
| 6652 |
} |
| 6653 |
} else { |
| 6654 |
rgbBuf = new Uint8Array(count * 3); |
| 6655 |
rgbPos = 0; |
| 6656 |
for (i = 0; i < count; ++i) { |
| 6657 |
key = comps[i] * 3; |
| 6658 |
rgbBuf[rgbPos++] = colorMap[key]; |
| 6659 |
rgbBuf[rgbPos++] = colorMap[key + 1]; |
| 6660 |
rgbBuf[rgbPos++] = colorMap[key + 2]; |
| 6661 |
} |
| 6662 |
} |
| 6663 |
} else { |
| 6664 |
if (!needsResizing) { |
| 6665 |
// Fill in the RGB values directly into |dest|. |
| 6666 |
this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, |
| 6667 |
alpha01); |
| 6668 |
} else { |
| 6669 |
rgbBuf = new Uint8Array(count * 3); |
| 6670 |
this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, |
| 6671 |
/* alpha01 = */ 0); |
| 6672 |
} |
| 6673 |
} |
| 6674 |
|
| 6675 |
if (rgbBuf) { |
| 6676 |
if (needsResizing) { |
| 6677 |
PDFImage.resize(rgbBuf, bpc, 3, originalWidth, originalHeight, width, |
| 6678 |
height, dest, alpha01); |
| 6679 |
} else { |
| 6680 |
rgbPos = 0; |
| 6681 |
destPos = 0; |
| 6682 |
for (i = 0, ii = width * actualHeight; i < ii; i++) { |
| 6683 |
dest[destPos++] = rgbBuf[rgbPos++]; |
| 6684 |
dest[destPos++] = rgbBuf[rgbPos++]; |
| 6685 |
dest[destPos++] = rgbBuf[rgbPos++]; |
| 6686 |
destPos += alpha01; |
| 6687 |
} |
| 6688 |
} |
| 6689 |
} |
| 6690 |
}, |
| 6691 |
/** |
| 6692 |
* True if the colorspace has components in the default range of [0, 1]. |
| 6693 |
* This should be true for all colorspaces except for lab color spaces |
| 6694 |
* which are [0,100], [-128, 127], [-128, 127]. |
| 6695 |
*/ |
| 6696 |
usesZeroToOneRange: true |
| 6697 |
}; |
| 6698 |
|
| 6699 |
ColorSpace.parse = function ColorSpace_parse(cs, xref, res) { |
| 6700 |
var IR = ColorSpace.parseToIR(cs, xref, res); |
| 6701 |
if (IR instanceof AlternateCS) { |
| 6702 |
return IR; |
| 6703 |
} |
| 6704 |
return ColorSpace.fromIR(IR); |
| 6705 |
}; |
| 6706 |
|
| 6707 |
ColorSpace.fromIR = function ColorSpace_fromIR(IR) { |
| 6708 |
var name = isArray(IR) ? IR[0] : IR; |
| 6709 |
var whitePoint, blackPoint, gamma; |
| 6710 |
|
| 6711 |
switch (name) { |
| 6712 |
case 'DeviceGrayCS': |
| 6713 |
return this.singletons.gray; |
| 6714 |
case 'DeviceRgbCS': |
| 6715 |
return this.singletons.rgb; |
| 6716 |
case 'DeviceCmykCS': |
| 6717 |
return this.singletons.cmyk; |
| 6718 |
case 'CalGrayCS': |
| 6719 |
whitePoint = IR[1].WhitePoint; |
| 6720 |
blackPoint = IR[1].BlackPoint; |
| 6721 |
gamma = IR[1].Gamma; |
| 6722 |
return new CalGrayCS(whitePoint, blackPoint, gamma); |
| 6723 |
case 'CalRGBCS': |
| 6724 |
whitePoint = IR[1].WhitePoint; |
| 6725 |
blackPoint = IR[1].BlackPoint; |
| 6726 |
gamma = IR[1].Gamma; |
| 6727 |
var matrix = IR[1].Matrix; |
| 6728 |
return new CalRGBCS(whitePoint, blackPoint, gamma, matrix); |
| 6729 |
case 'PatternCS': |
| 6730 |
var basePatternCS = IR[1]; |
| 6731 |
if (basePatternCS) { |
| 6732 |
basePatternCS = ColorSpace.fromIR(basePatternCS); |
| 6733 |
} |
| 6734 |
return new PatternCS(basePatternCS); |
| 6735 |
case 'IndexedCS': |
| 6736 |
var baseIndexedCS = IR[1]; |
| 6737 |
var hiVal = IR[2]; |
| 6738 |
var lookup = IR[3]; |
| 6739 |
return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup); |
| 6740 |
case 'AlternateCS': |
| 6741 |
var numComps = IR[1]; |
| 6742 |
var alt = IR[2]; |
| 6743 |
var tintFnIR = IR[3]; |
| 6744 |
|
| 6745 |
return new AlternateCS(numComps, ColorSpace.fromIR(alt), |
| 6746 |
PDFFunction.fromIR(tintFnIR)); |
| 6747 |
case 'LabCS': |
| 6748 |
whitePoint = IR[1].WhitePoint; |
| 6749 |
blackPoint = IR[1].BlackPoint; |
| 6750 |
var range = IR[1].Range; |
| 6751 |
return new LabCS(whitePoint, blackPoint, range); |
| 6752 |
default: |
| 6753 |
error('Unknown name ' + name); |
| 6754 |
} |
| 6755 |
return null; |
| 6756 |
}; |
| 6757 |
|
| 6758 |
ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) { |
| 6759 |
if (isName(cs)) { |
| 6760 |
var colorSpaces = res.get('ColorSpace'); |
| 6761 |
if (isDict(colorSpaces)) { |
| 6762 |
var refcs = colorSpaces.get(cs.name); |
| 6763 |
if (refcs) { |
| 6764 |
cs = refcs; |
| 6765 |
} |
| 6766 |
} |
| 6767 |
} |
| 6768 |
|
| 6769 |
cs = xref.fetchIfRef(cs); |
| 6770 |
var mode; |
| 6771 |
|
| 6772 |
if (isName(cs)) { |
| 6773 |
mode = cs.name; |
| 6774 |
this.mode = mode; |
| 6775 |
|
| 6776 |
switch (mode) { |
| 6777 |
case 'DeviceGray': |
| 6778 |
case 'G': |
| 6779 |
return 'DeviceGrayCS'; |
| 6780 |
case 'DeviceRGB': |
| 6781 |
case 'RGB': |
| 6782 |
return 'DeviceRgbCS'; |
| 6783 |
case 'DeviceCMYK': |
| 6784 |
case 'CMYK': |
| 6785 |
return 'DeviceCmykCS'; |
| 6786 |
case 'Pattern': |
| 6787 |
return ['PatternCS', null]; |
| 6788 |
default: |
| 6789 |
error('unrecognized colorspace ' + mode); |
| 6790 |
} |
| 6791 |
} else if (isArray(cs)) { |
| 6792 |
mode = cs[0].name; |
| 6793 |
this.mode = mode; |
| 6794 |
var numComps, params; |
| 6795 |
|
| 6796 |
switch (mode) { |
| 6797 |
case 'DeviceGray': |
| 6798 |
case 'G': |
| 6799 |
return 'DeviceGrayCS'; |
| 6800 |
case 'DeviceRGB': |
| 6801 |
case 'RGB': |
| 6802 |
return 'DeviceRgbCS'; |
| 6803 |
case 'DeviceCMYK': |
| 6804 |
case 'CMYK': |
| 6805 |
return 'DeviceCmykCS'; |
| 6806 |
case 'CalGray': |
| 6807 |
params = xref.fetchIfRef(cs[1]).getAll(); |
| 6808 |
return ['CalGrayCS', params]; |
| 6809 |
case 'CalRGB': |
| 6810 |
params = xref.fetchIfRef(cs[1]).getAll(); |
| 6811 |
return ['CalRGBCS', params]; |
| 6812 |
case 'ICCBased': |
| 6813 |
var stream = xref.fetchIfRef(cs[1]); |
| 6814 |
var dict = stream.dict; |
| 6815 |
numComps = dict.get('N'); |
| 6816 |
if (numComps === 1) { |
| 6817 |
return 'DeviceGrayCS'; |
| 6818 |
} else if (numComps === 3) { |
| 6819 |
return 'DeviceRgbCS'; |
| 6820 |
} else if (numComps === 4) { |
| 6821 |
return 'DeviceCmykCS'; |
| 6822 |
} |
| 6823 |
break; |
| 6824 |
case 'Pattern': |
| 6825 |
var basePatternCS = cs[1]; |
| 6826 |
if (basePatternCS) { |
| 6827 |
basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res); |
| 6828 |
} |
| 6829 |
return ['PatternCS', basePatternCS]; |
| 6830 |
case 'Indexed': |
| 6831 |
case 'I': |
| 6832 |
var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res); |
| 6833 |
var hiVal = cs[2] + 1; |
| 6834 |
var lookup = xref.fetchIfRef(cs[3]); |
| 6835 |
if (isStream(lookup)) { |
| 6836 |
lookup = lookup.getBytes(); |
| 6837 |
} |
| 6838 |
return ['IndexedCS', baseIndexedCS, hiVal, lookup]; |
| 6839 |
case 'Separation': |
| 6840 |
case 'DeviceN': |
| 6841 |
var name = cs[1]; |
| 6842 |
numComps = 1; |
| 6843 |
if (isName(name)) { |
| 6844 |
numComps = 1; |
| 6845 |
} else if (isArray(name)) { |
| 6846 |
numComps = name.length; |
| 6847 |
} |
| 6848 |
var alt = ColorSpace.parseToIR(cs[2], xref, res); |
| 6849 |
var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3])); |
| 6850 |
return ['AlternateCS', numComps, alt, tintFnIR]; |
| 6851 |
case 'Lab': |
| 6852 |
params = cs[1].getAll(); |
| 6853 |
return ['LabCS', params]; |
| 6854 |
default: |
| 6855 |
error('unimplemented color space object "' + mode + '"'); |
| 6856 |
} |
| 6857 |
} else { |
| 6858 |
error('unrecognized color space object: "' + cs + '"'); |
| 6859 |
} |
| 6860 |
return null; |
| 6861 |
}; |
| 6862 |
/** |
| 6863 |
* Checks if a decode map matches the default decode map for a color space. |
| 6864 |
* This handles the general decode maps where there are two values per |
| 6865 |
* component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color. |
| 6866 |
* This does not handle Lab, Indexed, or Pattern decode maps since they are |
| 6867 |
* slightly different. |
| 6868 |
* @param {Array} decode Decode map (usually from an image). |
| 6869 |
* @param {Number} n Number of components the color space has. |
| 6870 |
*/ |
| 6871 |
ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) { |
| 6872 |
if (!decode) { |
| 6873 |
return true; |
| 6874 |
} |
| 6875 |
|
| 6876 |
if (n * 2 !== decode.length) { |
| 6877 |
warn('The decode map is not the correct length'); |
| 6878 |
return true; |
| 6879 |
} |
| 6880 |
for (var i = 0, ii = decode.length; i < ii; i += 2) { |
| 6881 |
if (decode[i] !== 0 || decode[i + 1] !== 1) { |
| 6882 |
return false; |
| 6883 |
} |
| 6884 |
} |
| 6885 |
return true; |
| 6886 |
}; |
| 6887 |
|
| 6888 |
ColorSpace.singletons = { |
| 6889 |
get gray() { |
| 6890 |
return shadow(this, 'gray', new DeviceGrayCS()); |
| 6891 |
}, |
| 6892 |
get rgb() { |
| 6893 |
return shadow(this, 'rgb', new DeviceRgbCS()); |
| 6894 |
}, |
| 6895 |
get cmyk() { |
| 6896 |
return shadow(this, 'cmyk', new DeviceCmykCS()); |
| 6897 |
} |
| 6898 |
}; |
| 6899 |
|
| 6900 |
return ColorSpace; |
| 6901 |
})(); |
| 6902 |
|
| 6903 |
/** |
| 6904 |
* Alternate color space handles both Separation and DeviceN color spaces. A |
| 6905 |
* Separation color space is actually just a DeviceN with one color component. |
| 6906 |
* Both color spaces use a tinting function to convert colors to a base color |
| 6907 |
* space. |
| 6908 |
*/ |
| 6909 |
var AlternateCS = (function AlternateCSClosure() { |
| 6910 |
function AlternateCS(numComps, base, tintFn) { |
| 6911 |
this.name = 'Alternate'; |
| 6912 |
this.numComps = numComps; |
| 6913 |
this.defaultColor = new Float32Array(numComps); |
| 6914 |
for (var i = 0; i < numComps; ++i) { |
| 6915 |
this.defaultColor[i] = 1; |
| 6916 |
} |
| 6917 |
this.base = base; |
| 6918 |
this.tintFn = tintFn; |
| 6919 |
this.tmpBuf = new Float32Array(base.numComps); |
| 6920 |
} |
| 6921 |
|
| 6922 |
AlternateCS.prototype = { |
| 6923 |
getRgb: ColorSpace.prototype.getRgb, |
| 6924 |
getRgbItem: function AlternateCS_getRgbItem(src, srcOffset, |
| 6925 |
dest, destOffset) { |
| 6926 |
var tmpBuf = this.tmpBuf; |
| 6927 |
this.tintFn(src, srcOffset, tmpBuf, 0); |
| 6928 |
this.base.getRgbItem(tmpBuf, 0, dest, destOffset); |
| 6929 |
}, |
| 6930 |
getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count, |
| 6931 |
dest, destOffset, bits, |
| 6932 |
alpha01) { |
| 6933 |
var tintFn = this.tintFn; |
| 6934 |
var base = this.base; |
| 6935 |
var scale = 1 / ((1 << bits) - 1); |
| 6936 |
var baseNumComps = base.numComps; |
| 6937 |
var usesZeroToOneRange = base.usesZeroToOneRange; |
| 6938 |
var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && |
| 6939 |
alpha01 === 0; |
| 6940 |
var pos = isPassthrough ? destOffset : 0; |
| 6941 |
var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count); |
| 6942 |
var numComps = this.numComps; |
| 6943 |
|
| 6944 |
var scaled = new Float32Array(numComps); |
| 6945 |
var tinted = new Float32Array(baseNumComps); |
| 6946 |
var i, j; |
| 6947 |
if (usesZeroToOneRange) { |
| 6948 |
for (i = 0; i < count; i++) { |
| 6949 |
for (j = 0; j < numComps; j++) { |
| 6950 |
scaled[j] = src[srcOffset++] * scale; |
| 6951 |
} |
| 6952 |
tintFn(scaled, 0, tinted, 0); |
| 6953 |
for (j = 0; j < baseNumComps; j++) { |
| 6954 |
baseBuf[pos++] = tinted[j] * 255; |
| 6955 |
} |
| 6956 |
} |
| 6957 |
} else { |
| 6958 |
for (i = 0; i < count; i++) { |
| 6959 |
for (j = 0; j < numComps; j++) { |
| 6960 |
scaled[j] = src[srcOffset++] * scale; |
| 6961 |
} |
| 6962 |
tintFn(scaled, 0, tinted, 0); |
| 6963 |
base.getRgbItem(tinted, 0, baseBuf, pos); |
| 6964 |
pos += baseNumComps; |
| 6965 |
} |
| 6966 |
} |
| 6967 |
if (!isPassthrough) { |
| 6968 |
base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); |
| 6969 |
} |
| 6970 |
}, |
| 6971 |
getOutputLength: function AlternateCS_getOutputLength(inputLength, |
| 6972 |
alpha01) { |
| 6973 |
return this.base.getOutputLength(inputLength * |
| 6974 |
this.base.numComps / this.numComps, |
| 6975 |
alpha01); |
| 6976 |
}, |
| 6977 |
isPassthrough: ColorSpace.prototype.isPassthrough, |
| 6978 |
fillRgb: ColorSpace.prototype.fillRgb, |
| 6979 |
isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) { |
| 6980 |
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
| 6981 |
}, |
| 6982 |
usesZeroToOneRange: true |
| 6983 |
}; |
| 6984 |
|
| 6985 |
return AlternateCS; |
| 6986 |
})(); |
| 6987 |
|
| 6988 |
var PatternCS = (function PatternCSClosure() { |
| 6989 |
function PatternCS(baseCS) { |
| 6990 |
this.name = 'Pattern'; |
| 6991 |
this.base = baseCS; |
| 6992 |
} |
| 6993 |
PatternCS.prototype = {}; |
| 6994 |
|
| 6995 |
return PatternCS; |
| 6996 |
})(); |
| 6997 |
|
| 6998 |
var IndexedCS = (function IndexedCSClosure() { |
| 6999 |
function IndexedCS(base, highVal, lookup) { |
| 7000 |
this.name = 'Indexed'; |
| 7001 |
this.numComps = 1; |
| 7002 |
this.defaultColor = new Uint8Array([0]); |
| 7003 |
this.base = base; |
| 7004 |
this.highVal = highVal; |
| 7005 |
|
| 7006 |
var baseNumComps = base.numComps; |
| 7007 |
var length = baseNumComps * highVal; |
| 7008 |
var lookupArray; |
| 7009 |
|
| 7010 |
if (isStream(lookup)) { |
| 7011 |
lookupArray = new Uint8Array(length); |
| 7012 |
var bytes = lookup.getBytes(length); |
| 7013 |
lookupArray.set(bytes); |
| 7014 |
} else if (isString(lookup)) { |
| 7015 |
lookupArray = new Uint8Array(length); |
| 7016 |
for (var i = 0; i < length; ++i) { |
| 7017 |
lookupArray[i] = lookup.charCodeAt(i); |
| 7018 |
} |
| 7019 |
} else if (lookup instanceof Uint8Array || lookup instanceof Array) { |
| 7020 |
lookupArray = lookup; |
| 7021 |
} else { |
| 7022 |
error('Unrecognized lookup table: ' + lookup); |
| 7023 |
} |
| 7024 |
this.lookup = lookupArray; |
| 7025 |
} |
| 7026 |
|
| 7027 |
IndexedCS.prototype = { |
| 7028 |
getRgb: ColorSpace.prototype.getRgb, |
| 7029 |
getRgbItem: function IndexedCS_getRgbItem(src, srcOffset, |
| 7030 |
dest, destOffset) { |
| 7031 |
var numComps = this.base.numComps; |
| 7032 |
var start = src[srcOffset] * numComps; |
| 7033 |
this.base.getRgbItem(this.lookup, start, dest, destOffset); |
| 7034 |
}, |
| 7035 |
getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count, |
| 7036 |
dest, destOffset, bits, |
| 7037 |
alpha01) { |
| 7038 |
var base = this.base; |
| 7039 |
var numComps = base.numComps; |
| 7040 |
var outputDelta = base.getOutputLength(numComps, alpha01); |
| 7041 |
var lookup = this.lookup; |
| 7042 |
|
| 7043 |
for (var i = 0; i < count; ++i) { |
| 7044 |
var lookupPos = src[srcOffset++] * numComps; |
| 7045 |
base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); |
| 7046 |
destOffset += outputDelta; |
| 7047 |
} |
| 7048 |
}, |
| 7049 |
getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) { |
| 7050 |
return this.base.getOutputLength(inputLength * this.base.numComps, |
| 7051 |
alpha01); |
| 7052 |
}, |
| 7053 |
isPassthrough: ColorSpace.prototype.isPassthrough, |
| 7054 |
fillRgb: ColorSpace.prototype.fillRgb, |
| 7055 |
isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) { |
| 7056 |
// indexed color maps shouldn't be changed |
| 7057 |
return true; |
| 7058 |
}, |
| 7059 |
usesZeroToOneRange: true |
| 7060 |
}; |
| 7061 |
return IndexedCS; |
| 7062 |
})(); |
| 7063 |
|
| 7064 |
var DeviceGrayCS = (function DeviceGrayCSClosure() { |
| 7065 |
function DeviceGrayCS() { |
| 7066 |
this.name = 'DeviceGray'; |
| 7067 |
this.numComps = 1; |
| 7068 |
this.defaultColor = new Float32Array([0]); |
| 7069 |
} |
| 7070 |
|
| 7071 |
DeviceGrayCS.prototype = { |
| 7072 |
getRgb: ColorSpace.prototype.getRgb, |
| 7073 |
getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset, |
| 7074 |
dest, destOffset) { |
| 7075 |
var c = (src[srcOffset] * 255) | 0; |
| 7076 |
c = c < 0 ? 0 : c > 255 ? 255 : c; |
| 7077 |
dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; |
| 7078 |
}, |
| 7079 |
getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count, |
| 7080 |
dest, destOffset, bits, |
| 7081 |
alpha01) { |
| 7082 |
var scale = 255 / ((1 << bits) - 1); |
| 7083 |
var j = srcOffset, q = destOffset; |
| 7084 |
for (var i = 0; i < count; ++i) { |
| 7085 |
var c = (scale * src[j++]) | 0; |
| 7086 |
dest[q++] = c; |
| 7087 |
dest[q++] = c; |
| 7088 |
dest[q++] = c; |
| 7089 |
q += alpha01; |
| 7090 |
} |
| 7091 |
}, |
| 7092 |
getOutputLength: function DeviceGrayCS_getOutputLength(inputLength, |
| 7093 |
alpha01) { |
| 7094 |
return inputLength * (3 + alpha01); |
| 7095 |
}, |
| 7096 |
isPassthrough: ColorSpace.prototype.isPassthrough, |
| 7097 |
fillRgb: ColorSpace.prototype.fillRgb, |
| 7098 |
isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) { |
| 7099 |
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
| 7100 |
}, |
| 7101 |
usesZeroToOneRange: true |
| 7102 |
}; |
| 7103 |
return DeviceGrayCS; |
| 7104 |
})(); |
| 7105 |
|
| 7106 |
var DeviceRgbCS = (function DeviceRgbCSClosure() { |
| 7107 |
function DeviceRgbCS() { |
| 7108 |
this.name = 'DeviceRGB'; |
| 7109 |
this.numComps = 3; |
| 7110 |
this.defaultColor = new Float32Array([0, 0, 0]); |
| 7111 |
} |
| 7112 |
DeviceRgbCS.prototype = { |
| 7113 |
getRgb: ColorSpace.prototype.getRgb, |
| 7114 |
getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset, |
| 7115 |
dest, destOffset) { |
| 7116 |
var r = (src[srcOffset] * 255) | 0; |
| 7117 |
var g = (src[srcOffset + 1] * 255) | 0; |
| 7118 |
var b = (src[srcOffset + 2] * 255) | 0; |
| 7119 |
dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r; |
| 7120 |
dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g; |
| 7121 |
dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b; |
| 7122 |
}, |
| 7123 |
getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count, |
| 7124 |
dest, destOffset, bits, |
| 7125 |
alpha01) { |
| 7126 |
if (bits === 8 && alpha01 === 0) { |
| 7127 |
dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); |
| 7128 |
return; |
| 7129 |
} |
| 7130 |
var scale = 255 / ((1 << bits) - 1); |
| 7131 |
var j = srcOffset, q = destOffset; |
| 7132 |
for (var i = 0; i < count; ++i) { |
| 7133 |
dest[q++] = (scale * src[j++]) | 0; |
| 7134 |
dest[q++] = (scale * src[j++]) | 0; |
| 7135 |
dest[q++] = (scale * src[j++]) | 0; |
| 7136 |
q += alpha01; |
| 7137 |
} |
| 7138 |
}, |
| 7139 |
getOutputLength: function DeviceRgbCS_getOutputLength(inputLength, |
| 7140 |
alpha01) { |
| 7141 |
return (inputLength * (3 + alpha01) / 3) | 0; |
| 7142 |
}, |
| 7143 |
isPassthrough: function DeviceRgbCS_isPassthrough(bits) { |
| 7144 |
return bits === 8; |
| 7145 |
}, |
| 7146 |
fillRgb: ColorSpace.prototype.fillRgb, |
| 7147 |
isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) { |
| 7148 |
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
| 7149 |
}, |
| 7150 |
usesZeroToOneRange: true |
| 7151 |
}; |
| 7152 |
return DeviceRgbCS; |
| 7153 |
})(); |
| 7154 |
|
| 7155 |
var DeviceCmykCS = (function DeviceCmykCSClosure() { |
| 7156 |
// The coefficients below was found using numerical analysis: the method of |
| 7157 |
// steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors, |
| 7158 |
// where color_value is the tabular value from the table of sampled RGB colors |
| 7159 |
// from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding |
| 7160 |
// CMYK color conversion using the estimation below: |
| 7161 |
// f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255 |
| 7162 |
function convertToRgb(src, srcOffset, srcScale, dest, destOffset) { |
| 7163 |
var c = src[srcOffset + 0] * srcScale; |
| 7164 |
var m = src[srcOffset + 1] * srcScale; |
| 7165 |
var y = src[srcOffset + 2] * srcScale; |
| 7166 |
var k = src[srcOffset + 3] * srcScale; |
| 7167 |
|
| 7168 |
var r = |
| 7169 |
(c * (-4.387332384609988 * c + 54.48615194189176 * m + |
| 7170 |
18.82290502165302 * y + 212.25662451639585 * k + |
| 7171 |
-285.2331026137004) + |
| 7172 |
m * (1.7149763477362134 * m - 5.6096736904047315 * y + |
| 7173 |
-17.873870861415444 * k - 5.497006427196366) + |
| 7174 |
y * (-2.5217340131683033 * y - 21.248923337353073 * k + |
| 7175 |
17.5119270841813) + |
| 7176 |
k * (-21.86122147463605 * k - 189.48180835922747) + 255) | 0; |
| 7177 |
var g = |
| 7178 |
(c * (8.841041422036149 * c + 60.118027045597366 * m + |
| 7179 |
6.871425592049007 * y + 31.159100130055922 * k + |
| 7180 |
-79.2970844816548) + |
| 7181 |
m * (-15.310361306967817 * m + 17.575251261109482 * y + |
| 7182 |
131.35250912493976 * k - 190.9453302588951) + |
| 7183 |
y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + |
| 7184 |
k * (-20.737325471181034 * k - 187.80453709719578) + 255) | 0; |
| 7185 |
var b = |
| 7186 |
(c * (0.8842522430003296 * c + 8.078677503112928 * m + |
| 7187 |
30.89978309703729 * y - 0.23883238689178934 * k + |
| 7188 |
-14.183576799673286) + |
| 7189 |
m * (10.49593273432072 * m + 63.02378494754052 * y + |
| 7190 |
50.606957656360734 * k - 112.23884253719248) + |
| 7191 |
y * (0.03296041114873217 * y + 115.60384449646641 * k + |
| 7192 |
-193.58209356861505) + |
| 7193 |
k * (-22.33816807309886 * k - 180.12613974708367) + 255) | 0; |
| 7194 |
|
| 7195 |
dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r; |
| 7196 |
dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g; |
| 7197 |
dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b; |
| 7198 |
} |
| 7199 |
|
| 7200 |
function DeviceCmykCS() { |
| 7201 |
this.name = 'DeviceCMYK'; |
| 7202 |
this.numComps = 4; |
| 7203 |
this.defaultColor = new Float32Array([0, 0, 0, 1]); |
| 7204 |
} |
| 7205 |
DeviceCmykCS.prototype = { |
| 7206 |
getRgb: ColorSpace.prototype.getRgb, |
| 7207 |
getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset, |
| 7208 |
dest, destOffset) { |
| 7209 |
convertToRgb(src, srcOffset, 1, dest, destOffset); |
| 7210 |
}, |
| 7211 |
getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count, |
| 7212 |
dest, destOffset, bits, |
| 7213 |
alpha01) { |
| 7214 |
var scale = 1 / ((1 << bits) - 1); |
| 7215 |
for (var i = 0; i < count; i++) { |
| 7216 |
convertToRgb(src, srcOffset, scale, dest, destOffset); |
| 7217 |
srcOffset += 4; |
| 7218 |
destOffset += 3 + alpha01; |
| 7219 |
} |
| 7220 |
}, |
| 7221 |
getOutputLength: function DeviceCmykCS_getOutputLength(inputLength, |
| 7222 |
alpha01) { |
| 7223 |
return (inputLength / 4 * (3 + alpha01)) | 0; |
| 7224 |
}, |
| 7225 |
isPassthrough: ColorSpace.prototype.isPassthrough, |
| 7226 |
fillRgb: ColorSpace.prototype.fillRgb, |
| 7227 |
isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { |
| 7228 |
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
| 7229 |
}, |
| 7230 |
usesZeroToOneRange: true |
| 7231 |
}; |
| 7232 |
|
| 7233 |
return DeviceCmykCS; |
| 7234 |
})(); |
| 7235 |
|
| 7236 |
// |
| 7237 |
// CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245 |
| 7238 |
// |
| 7239 |
var CalGrayCS = (function CalGrayCSClosure() { |
| 7240 |
function CalGrayCS(whitePoint, blackPoint, gamma) { |
| 7241 |
this.name = 'CalGray'; |
| 7242 |
this.numComps = 1; |
| 7243 |
this.defaultColor = new Float32Array([0]); |
| 7244 |
|
| 7245 |
if (!whitePoint) { |
| 7246 |
error('WhitePoint missing - required for color space CalGray'); |
| 7247 |
} |
| 7248 |
blackPoint = blackPoint || [0, 0, 0]; |
| 7249 |
gamma = gamma || 1; |
| 7250 |
|
| 7251 |
// Translate arguments to spec variables. |
| 7252 |
this.XW = whitePoint[0]; |
| 7253 |
this.YW = whitePoint[1]; |
| 7254 |
this.ZW = whitePoint[2]; |
| 7255 |
|
| 7256 |
this.XB = blackPoint[0]; |
| 7257 |
this.YB = blackPoint[1]; |
| 7258 |
this.ZB = blackPoint[2]; |
| 7259 |
|
| 7260 |
this.G = gamma; |
| 7261 |
|
| 7262 |
// Validate variables as per spec. |
| 7263 |
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { |
| 7264 |
error('Invalid WhitePoint components for ' + this.name + |
| 7265 |
', no fallback available'); |
| 7266 |
} |
| 7267 |
|
| 7268 |
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { |
| 7269 |
info('Invalid BlackPoint for ' + this.name + ', falling back to default'); |
| 7270 |
this.XB = this.YB = this.ZB = 0; |
| 7271 |
} |
| 7272 |
|
| 7273 |
if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { |
| 7274 |
warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB + |
| 7275 |
', ZB: ' + this.ZB + ', only default values are supported.'); |
| 7276 |
} |
| 7277 |
|
| 7278 |
if (this.G < 1) { |
| 7279 |
info('Invalid Gamma: ' + this.G + ' for ' + this.name + |
| 7280 |
', falling back to default'); |
| 7281 |
this.G = 1; |
| 7282 |
} |
| 7283 |
} |
| 7284 |
|
| 7285 |
function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { |
| 7286 |
// A represents a gray component of a calibrated gray space. |
| 7287 |
// A <---> AG in the spec |
| 7288 |
var A = src[srcOffset] * scale; |
| 7289 |
var AG = Math.pow(A, cs.G); |
| 7290 |
|
| 7291 |
// Computes L as per spec. ( = cs.YW * AG ) |
| 7292 |
// Except if other than default BlackPoint values are used. |
| 7293 |
var L = cs.YW * AG; |
| 7294 |
// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4. |
| 7295 |
// Convert values to rgb range [0, 255]. |
| 7296 |
var val = Math.max(295.8 * Math.pow(L, 0.333333333333333333) - 40.8, 0) | 0; |
| 7297 |
dest[destOffset] = val; |
| 7298 |
dest[destOffset + 1] = val; |
| 7299 |
dest[destOffset + 2] = val; |
| 7300 |
} |
| 7301 |
|
| 7302 |
CalGrayCS.prototype = { |
| 7303 |
getRgb: ColorSpace.prototype.getRgb, |
| 7304 |
getRgbItem: function CalGrayCS_getRgbItem(src, srcOffset, |
| 7305 |
dest, destOffset) { |
| 7306 |
convertToRgb(this, src, srcOffset, dest, destOffset, 1); |
| 7307 |
}, |
| 7308 |
getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count, |
| 7309 |
dest, destOffset, bits, |
| 7310 |
alpha01) { |
| 7311 |
var scale = 1 / ((1 << bits) - 1); |
| 7312 |
|
| 7313 |
for (var i = 0; i < count; ++i) { |
| 7314 |
convertToRgb(this, src, srcOffset, dest, destOffset, scale); |
| 7315 |
srcOffset += 1; |
| 7316 |
destOffset += 3 + alpha01; |
| 7317 |
} |
| 7318 |
}, |
| 7319 |
getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) { |
| 7320 |
return inputLength * (3 + alpha01); |
| 7321 |
}, |
| 7322 |
isPassthrough: ColorSpace.prototype.isPassthrough, |
| 7323 |
fillRgb: ColorSpace.prototype.fillRgb, |
| 7324 |
isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) { |
| 7325 |
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
| 7326 |
}, |
| 7327 |
usesZeroToOneRange: true |
| 7328 |
}; |
| 7329 |
return CalGrayCS; |
| 7330 |
})(); |
| 7331 |
|
| 7332 |
// |
| 7333 |
// CalRGBCS: Based on "PDF Reference, Sixth Ed", p.247 |
| 7334 |
// |
| 7335 |
var CalRGBCS = (function CalRGBCSClosure() { |
| 7336 |
|
| 7337 |
// See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these |
| 7338 |
// matrices. |
| 7339 |
var BRADFORD_SCALE_MATRIX = new Float32Array([ |
| 7340 |
0.8951, 0.2664, -0.1614, |
| 7341 |
-0.7502, 1.7135, 0.0367, |
| 7342 |
0.0389, -0.0685, 1.0296]); |
| 7343 |
|
| 7344 |
var BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([ |
| 7345 |
0.9869929, -0.1470543, 0.1599627, |
| 7346 |
0.4323053, 0.5183603, 0.0492912, |
| 7347 |
-0.0085287, 0.0400428, 0.9684867]); |
| 7348 |
|
| 7349 |
// See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html. |
| 7350 |
var SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([ |
| 7351 |
3.2404542, -1.5371385, -0.4985314, |
| 7352 |
-0.9692660, 1.8760108, 0.0415560, |
| 7353 |
0.0556434, -0.2040259, 1.0572252]); |
| 7354 |
|
| 7355 |
var FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]); |
| 7356 |
|
| 7357 |
var tempNormalizeMatrix = new Float32Array(3); |
| 7358 |
var tempConvertMatrix1 = new Float32Array(3); |
| 7359 |
var tempConvertMatrix2 = new Float32Array(3); |
| 7360 |
|
| 7361 |
var DECODE_L_CONSTANT = Math.pow(((8 + 16) / 116), 3) / 8.0; |
| 7362 |
|
| 7363 |
function CalRGBCS(whitePoint, blackPoint, gamma, matrix) { |
| 7364 |
this.name = 'CalRGB'; |
| 7365 |
this.numComps = 3; |
| 7366 |
this.defaultColor = new Float32Array(3); |
| 7367 |
|
| 7368 |
if (!whitePoint) { |
| 7369 |
error('WhitePoint missing - required for color space CalRGB'); |
| 7370 |
} |
| 7371 |
blackPoint = blackPoint || new Float32Array(3); |
| 7372 |
gamma = gamma || new Float32Array([1, 1, 1]); |
| 7373 |
matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]); |
| 7374 |
|
| 7375 |
// Translate arguments to spec variables. |
| 7376 |
var XW = whitePoint[0]; |
| 7377 |
var YW = whitePoint[1]; |
| 7378 |
var ZW = whitePoint[2]; |
| 7379 |
this.whitePoint = whitePoint; |
| 7380 |
|
| 7381 |
var XB = blackPoint[0]; |
| 7382 |
var YB = blackPoint[1]; |
| 7383 |
var ZB = blackPoint[2]; |
| 7384 |
this.blackPoint = blackPoint; |
| 7385 |
|
| 7386 |
this.GR = gamma[0]; |
| 7387 |
this.GG = gamma[1]; |
| 7388 |
this.GB = gamma[2]; |
| 7389 |
|
| 7390 |
this.MXA = matrix[0]; |
| 7391 |
this.MYA = matrix[1]; |
| 7392 |
this.MZA = matrix[2]; |
| 7393 |
this.MXB = matrix[3]; |
| 7394 |
this.MYB = matrix[4]; |
| 7395 |
this.MZB = matrix[5]; |
| 7396 |
this.MXC = matrix[6]; |
| 7397 |
this.MYC = matrix[7]; |
| 7398 |
this.MZC = matrix[8]; |
| 7399 |
|
| 7400 |
// Validate variables as per spec. |
| 7401 |
if (XW < 0 || ZW < 0 || YW !== 1) { |
| 7402 |
error('Invalid WhitePoint components for ' + this.name + |
| 7403 |
', no fallback available'); |
| 7404 |
} |
| 7405 |
|
| 7406 |
if (XB < 0 || YB < 0 || ZB < 0) { |
| 7407 |
info('Invalid BlackPoint for ' + this.name + ' [' + XB + ', ' + YB + |
| 7408 |
', ' + ZB + '], falling back to default'); |
| 7409 |
this.blackPoint = new Float32Array(3); |
| 7410 |
} |
| 7411 |
|
| 7412 |
if (this.GR < 0 || this.GG < 0 || this.GB < 0) { |
| 7413 |
info('Invalid Gamma [' + this.GR + ', ' + this.GG + ', ' + this.GB + |
| 7414 |
'] for ' + this.name + ', falling back to default'); |
| 7415 |
this.GR = this.GG = this.GB = 1; |
| 7416 |
} |
| 7417 |
|
| 7418 |
if (this.MXA < 0 || this.MYA < 0 || this.MZA < 0 || |
| 7419 |
this.MXB < 0 || this.MYB < 0 || this.MZB < 0 || |
| 7420 |
this.MXC < 0 || this.MYC < 0 || this.MZC < 0) { |
| 7421 |
info('Invalid Matrix for ' + this.name + ' [' + |
| 7422 |
this.MXA + ', ' + this.MYA + ', ' + this.MZA + |
| 7423 |
this.MXB + ', ' + this.MYB + ', ' + this.MZB + |
| 7424 |
this.MXC + ', ' + this.MYC + ', ' + this.MZC + |
| 7425 |
'], falling back to default'); |
| 7426 |
this.MXA = this.MYB = this.MZC = 1; |
| 7427 |
this.MXB = this.MYA = this.MZA = this.MXC = this.MYC = this.MZB = 0; |
| 7428 |
} |
| 7429 |
} |
| 7430 |
|
| 7431 |
function matrixProduct(a, b, result) { |
| 7432 |
result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; |
| 7433 |
result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2]; |
| 7434 |
result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2]; |
| 7435 |
} |
| 7436 |
|
| 7437 |
function convertToFlat(sourceWhitePoint, LMS, result) { |
| 7438 |
result[0] = LMS[0] * 1 / sourceWhitePoint[0]; |
| 7439 |
result[1] = LMS[1] * 1 / sourceWhitePoint[1]; |
| 7440 |
result[2] = LMS[2] * 1 / sourceWhitePoint[2]; |
| 7441 |
} |
| 7442 |
|
| 7443 |
function convertToD65(sourceWhitePoint, LMS, result) { |
| 7444 |
var D65X = 0.95047; |
| 7445 |
var D65Y = 1; |
| 7446 |
var D65Z = 1.08883; |
| 7447 |
|
| 7448 |
result[0] = LMS[0] * D65X / sourceWhitePoint[0]; |
| 7449 |
result[1] = LMS[1] * D65Y / sourceWhitePoint[1]; |
| 7450 |
result[2] = LMS[2] * D65Z / sourceWhitePoint[2]; |
| 7451 |
} |
| 7452 |
|
| 7453 |
function sRGBTransferFunction(color) { |
| 7454 |
// See http://en.wikipedia.org/wiki/SRGB. |
| 7455 |
if (color <= 0.0031308){ |
| 7456 |
return adjustToRange(0, 1, 12.92 * color); |
| 7457 |
} |
| 7458 |
|
| 7459 |
return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055); |
| 7460 |
} |
| 7461 |
|
| 7462 |
function adjustToRange(min, max, value) { |
| 7463 |
return Math.max(min, Math.min(max, value)); |
| 7464 |
} |
| 7465 |
|
| 7466 |
function decodeL(L) { |
| 7467 |
if (L < 0) { |
| 7468 |
return -decodeL(-L); |
| 7469 |
} |
| 7470 |
|
| 7471 |
if (L > 8.0) { |
| 7472 |
return Math.pow(((L + 16) / 116), 3); |
| 7473 |
} |
| 7474 |
|
| 7475 |
return L * DECODE_L_CONSTANT; |
| 7476 |
} |
| 7477 |
|
| 7478 |
function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) { |
| 7479 |
|
| 7480 |
// In case the blackPoint is already the default blackPoint then there is |
| 7481 |
// no need to do compensation. |
| 7482 |
if (sourceBlackPoint[0] === 0 && |
| 7483 |
sourceBlackPoint[1] === 0 && |
| 7484 |
sourceBlackPoint[2] === 0) { |
| 7485 |
result[0] = XYZ_Flat[0]; |
| 7486 |
result[1] = XYZ_Flat[1]; |
| 7487 |
result[2] = XYZ_Flat[2]; |
| 7488 |
return; |
| 7489 |
} |
| 7490 |
|
| 7491 |
// For the blackPoint calculation details, please see |
| 7492 |
// http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/ |
| 7493 |
// AdobeBPC.pdf. |
| 7494 |
// The destination blackPoint is the default blackPoint [0, 0, 0]. |
| 7495 |
var zeroDecodeL = decodeL(0); |
| 7496 |
|
| 7497 |
var X_DST = zeroDecodeL; |
| 7498 |
var X_SRC = decodeL(sourceBlackPoint[0]); |
| 7499 |
|
| 7500 |
var Y_DST = zeroDecodeL; |
| 7501 |
var Y_SRC = decodeL(sourceBlackPoint[1]); |
| 7502 |
|
| 7503 |
var Z_DST = zeroDecodeL; |
| 7504 |
var Z_SRC = decodeL(sourceBlackPoint[2]); |
| 7505 |
|
| 7506 |
var X_Scale = (1 - X_DST) / (1 - X_SRC); |
| 7507 |
var X_Offset = 1 - X_Scale; |
| 7508 |
|
| 7509 |
var Y_Scale = (1 - Y_DST) / (1 - Y_SRC); |
| 7510 |
var Y_Offset = 1 - Y_Scale; |
| 7511 |
|
| 7512 |
var Z_Scale = (1 - Z_DST) / (1 - Z_SRC); |
| 7513 |
var Z_Offset = 1 - Z_Scale; |
| 7514 |
|
| 7515 |
result[0] = XYZ_Flat[0] * X_Scale + X_Offset; |
| 7516 |
result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset; |
| 7517 |
result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset; |
| 7518 |
} |
| 7519 |
|
| 7520 |
function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) { |
| 7521 |
|
| 7522 |
// In case the whitePoint is already flat then there is no need to do |
| 7523 |
// normalization. |
| 7524 |
if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) { |
| 7525 |
result[0] = XYZ_In[0]; |
| 7526 |
result[1] = XYZ_In[1]; |
| 7527 |
result[2] = XYZ_In[2]; |
| 7528 |
return; |
| 7529 |
} |
| 7530 |
|
| 7531 |
var LMS = result; |
| 7532 |
matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); |
| 7533 |
|
| 7534 |
var LMS_Flat = tempNormalizeMatrix; |
| 7535 |
convertToFlat(sourceWhitePoint, LMS, LMS_Flat); |
| 7536 |
|
| 7537 |
matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result); |
| 7538 |
} |
| 7539 |
|
| 7540 |
function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) { |
| 7541 |
|
| 7542 |
var LMS = result; |
| 7543 |
matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); |
| 7544 |
|
| 7545 |
var LMS_D65 = tempNormalizeMatrix; |
| 7546 |
convertToD65(sourceWhitePoint, LMS, LMS_D65); |
| 7547 |
|
| 7548 |
matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result); |
| 7549 |
} |
| 7550 |
|
| 7551 |
function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { |
| 7552 |
// A, B and C represent a red, green and blue components of a calibrated |
| 7553 |
// rgb space. |
| 7554 |
var A = adjustToRange(0, 1, src[srcOffset] * scale); |
| 7555 |
var B = adjustToRange(0, 1, src[srcOffset + 1] * scale); |
| 7556 |
var C = adjustToRange(0, 1, src[srcOffset + 2] * scale); |
| 7557 |
|
| 7558 |
// A <---> AGR in the spec |
| 7559 |
// B <---> BGG in the spec |
| 7560 |
// C <---> CGB in the spec |
| 7561 |
var AGR = Math.pow(A, cs.GR); |
| 7562 |
var BGG = Math.pow(B, cs.GG); |
| 7563 |
var CGB = Math.pow(C, cs.GB); |
| 7564 |
|
| 7565 |
// Computes intermediate variables L, M, N as per spec. |
| 7566 |
// To decode X, Y, Z values map L, M, N directly to them. |
| 7567 |
var X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB; |
| 7568 |
var Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB; |
| 7569 |
var Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB; |
| 7570 |
|
| 7571 |
// The following calculations are based on this document: |
| 7572 |
// http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/ |
| 7573 |
// AdobeBPC.pdf. |
| 7574 |
var XYZ = tempConvertMatrix1; |
| 7575 |
XYZ[0] = X; |
| 7576 |
XYZ[1] = Y; |
| 7577 |
XYZ[2] = Z; |
| 7578 |
var XYZ_Flat = tempConvertMatrix2; |
| 7579 |
|
| 7580 |
normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat); |
| 7581 |
|
| 7582 |
var XYZ_Black = tempConvertMatrix1; |
| 7583 |
compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black); |
| 7584 |
|
| 7585 |
var XYZ_D65 = tempConvertMatrix2; |
| 7586 |
normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65); |
| 7587 |
|
| 7588 |
var SRGB = tempConvertMatrix1; |
| 7589 |
matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB); |
| 7590 |
|
| 7591 |
var sR = sRGBTransferFunction(SRGB[0]); |
| 7592 |
var sG = sRGBTransferFunction(SRGB[1]); |
| 7593 |
var sB = sRGBTransferFunction(SRGB[2]); |
| 7594 |
|
| 7595 |
// Convert the values to rgb range [0, 255]. |
| 7596 |
dest[destOffset] = Math.round(sR * 255); |
| 7597 |
dest[destOffset + 1] = Math.round(sG * 255); |
| 7598 |
dest[destOffset + 2] = Math.round(sB * 255); |
| 7599 |
} |
| 7600 |
|
| 7601 |
CalRGBCS.prototype = { |
| 7602 |
getRgb: function CalRGBCS_getRgb(src, srcOffset) { |
| 7603 |
var rgb = new Uint8Array(3); |
| 7604 |
this.getRgbItem(src, srcOffset, rgb, 0); |
| 7605 |
return rgb; |
| 7606 |
}, |
| 7607 |
getRgbItem: function CalRGBCS_getRgbItem(src, srcOffset, |
| 7608 |
dest, destOffset) { |
| 7609 |
convertToRgb(this, src, srcOffset, dest, destOffset, 1); |
| 7610 |
}, |
| 7611 |
getRgbBuffer: function CalRGBCS_getRgbBuffer(src, srcOffset, count, |
| 7612 |
dest, destOffset, bits, |
| 7613 |
alpha01) { |
| 7614 |
var scale = 1 / ((1 << bits) - 1); |
| 7615 |
|
| 7616 |
for (var i = 0; i < count; ++i) { |
| 7617 |
convertToRgb(this, src, srcOffset, dest, destOffset, scale); |
| 7618 |
srcOffset += 3; |
| 7619 |
destOffset += 3 + alpha01; |
| 7620 |
} |
| 7621 |
}, |
| 7622 |
getOutputLength: function CalRGBCS_getOutputLength(inputLength, alpha01) { |
| 7623 |
return (inputLength * (3 + alpha01) / 3) | 0; |
| 7624 |
}, |
| 7625 |
isPassthrough: ColorSpace.prototype.isPassthrough, |
| 7626 |
fillRgb: ColorSpace.prototype.fillRgb, |
| 7627 |
isDefaultDecode: function CalRGBCS_isDefaultDecode(decodeMap) { |
| 7628 |
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
| 7629 |
}, |
| 7630 |
usesZeroToOneRange: true |
| 7631 |
}; |
| 7632 |
return CalRGBCS; |
| 7633 |
})(); |
| 7634 |
|
| 7635 |
// |
| 7636 |
// LabCS: Based on "PDF Reference, Sixth Ed", p.250 |
| 7637 |
// |
| 7638 |
var LabCS = (function LabCSClosure() { |
| 7639 |
function LabCS(whitePoint, blackPoint, range) { |
| 7640 |
this.name = 'Lab'; |
| 7641 |
this.numComps = 3; |
| 7642 |
this.defaultColor = new Float32Array([0, 0, 0]); |
| 7643 |
|
| 7644 |
if (!whitePoint) { |
| 7645 |
error('WhitePoint missing - required for color space Lab'); |
| 7646 |
} |
| 7647 |
blackPoint = blackPoint || [0, 0, 0]; |
| 7648 |
range = range || [-100, 100, -100, 100]; |
| 7649 |
|
| 7650 |
// Translate args to spec variables |
| 7651 |
this.XW = whitePoint[0]; |
| 7652 |
this.YW = whitePoint[1]; |
| 7653 |
this.ZW = whitePoint[2]; |
| 7654 |
this.amin = range[0]; |
| 7655 |
this.amax = range[1]; |
| 7656 |
this.bmin = range[2]; |
| 7657 |
this.bmax = range[3]; |
| 7658 |
|
| 7659 |
// These are here just for completeness - the spec doesn't offer any |
| 7660 |
// formulas that use BlackPoint in Lab |
| 7661 |
this.XB = blackPoint[0]; |
| 7662 |
this.YB = blackPoint[1]; |
| 7663 |
this.ZB = blackPoint[2]; |
| 7664 |
|
| 7665 |
// Validate vars as per spec |
| 7666 |
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { |
| 7667 |
error('Invalid WhitePoint components, no fallback available'); |
| 7668 |
} |
| 7669 |
|
| 7670 |
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { |
| 7671 |
info('Invalid BlackPoint, falling back to default'); |
| 7672 |
this.XB = this.YB = this.ZB = 0; |
| 7673 |
} |
| 7674 |
|
| 7675 |
if (this.amin > this.amax || this.bmin > this.bmax) { |
| 7676 |
info('Invalid Range, falling back to defaults'); |
| 7677 |
this.amin = -100; |
| 7678 |
this.amax = 100; |
| 7679 |
this.bmin = -100; |
| 7680 |
this.bmax = 100; |
| 7681 |
} |
| 7682 |
} |
| 7683 |
|
| 7684 |
// Function g(x) from spec |
| 7685 |
function fn_g(x) { |
| 7686 |
if (x >= 6 / 29) { |
| 7687 |
return x * x * x; |
| 7688 |
} else { |
| 7689 |
return (108 / 841) * (x - 4 / 29); |
| 7690 |
} |
| 7691 |
} |
| 7692 |
|
| 7693 |
function decode(value, high1, low2, high2) { |
| 7694 |
return low2 + (value) * (high2 - low2) / (high1); |
| 7695 |
} |
| 7696 |
|
| 7697 |
// If decoding is needed maxVal should be 2^bits per component - 1. |
| 7698 |
function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) { |
| 7699 |
// XXX: Lab input is in the range of [0, 100], [amin, amax], [bmin, bmax] |
| 7700 |
// not the usual [0, 1]. If a command like setFillColor is used the src |
| 7701 |
// values will already be within the correct range. However, if we are |
| 7702 |
// converting an image we have to map the values to the correct range given |
| 7703 |
// above. |
| 7704 |
// Ls,as,bs <---> L*,a*,b* in the spec |
| 7705 |
var Ls = src[srcOffset]; |
| 7706 |
var as = src[srcOffset + 1]; |
| 7707 |
var bs = src[srcOffset + 2]; |
| 7708 |
if (maxVal !== false) { |
| 7709 |
Ls = decode(Ls, maxVal, 0, 100); |
| 7710 |
as = decode(as, maxVal, cs.amin, cs.amax); |
| 7711 |
bs = decode(bs, maxVal, cs.bmin, cs.bmax); |
| 7712 |
} |
| 7713 |
|
| 7714 |
// Adjust limits of 'as' and 'bs' |
| 7715 |
as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as; |
| 7716 |
bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs; |
| 7717 |
|
| 7718 |
// Computes intermediate variables X,Y,Z as per spec |
| 7719 |
var M = (Ls + 16) / 116; |
| 7720 |
var L = M + (as / 500); |
| 7721 |
var N = M - (bs / 200); |
| 7722 |
|
| 7723 |
var X = cs.XW * fn_g(L); |
| 7724 |
var Y = cs.YW * fn_g(M); |
| 7725 |
var Z = cs.ZW * fn_g(N); |
| 7726 |
|
| 7727 |
var r, g, b; |
| 7728 |
// Using different conversions for D50 and D65 white points, |
| 7729 |
// per http://www.color.org/srgb.pdf |
| 7730 |
if (cs.ZW < 1) { |
| 7731 |
// Assuming D50 (X=0.9642, Y=1.00, Z=0.8249) |
| 7732 |
r = X * 3.1339 + Y * -1.6170 + Z * -0.4906; |
| 7733 |
g = X * -0.9785 + Y * 1.9160 + Z * 0.0333; |
| 7734 |
b = X * 0.0720 + Y * -0.2290 + Z * 1.4057; |
| 7735 |
} else { |
| 7736 |
// Assuming D65 (X=0.9505, Y=1.00, Z=1.0888) |
| 7737 |
r = X * 3.2406 + Y * -1.5372 + Z * -0.4986; |
| 7738 |
g = X * -0.9689 + Y * 1.8758 + Z * 0.0415; |
| 7739 |
b = X * 0.0557 + Y * -0.2040 + Z * 1.0570; |
| 7740 |
} |
| 7741 |
// clamp color values to [0,1] range then convert to [0,255] range. |
| 7742 |
dest[destOffset] = r <= 0 ? 0 : r >= 1 ? 255 : Math.sqrt(r) * 255 | 0; |
| 7743 |
dest[destOffset + 1] = g <= 0 ? 0 : g >= 1 ? 255 : Math.sqrt(g) * 255 | 0; |
| 7744 |
dest[destOffset + 2] = b <= 0 ? 0 : b >= 1 ? 255 : Math.sqrt(b) * 255 | 0; |
| 7745 |
} |
| 7746 |
|
| 7747 |
LabCS.prototype = { |
| 7748 |
getRgb: ColorSpace.prototype.getRgb, |
| 7749 |
getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) { |
| 7750 |
convertToRgb(this, src, srcOffset, false, dest, destOffset); |
| 7751 |
}, |
| 7752 |
getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count, |
| 7753 |
dest, destOffset, bits, |
| 7754 |
alpha01) { |
| 7755 |
var maxVal = (1 << bits) - 1; |
| 7756 |
for (var i = 0; i < count; i++) { |
| 7757 |
convertToRgb(this, src, srcOffset, maxVal, dest, destOffset); |
| 7758 |
srcOffset += 3; |
| 7759 |
destOffset += 3 + alpha01; |
| 7760 |
} |
| 7761 |
}, |
| 7762 |
getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) { |
| 7763 |
return (inputLength * (3 + alpha01) / 3) | 0; |
| 7764 |
}, |
| 7765 |
isPassthrough: ColorSpace.prototype.isPassthrough, |
| 7766 |
fillRgb: ColorSpace.prototype.fillRgb, |
| 7767 |
isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) { |
| 7768 |
// XXX: Decoding is handled with the lab conversion because of the strange |
| 7769 |
// ranges that are used. |
| 7770 |
return true; |
| 7771 |
}, |
| 7772 |
usesZeroToOneRange: false |
| 7773 |
}; |
| 7774 |
return LabCS; |
| 7775 |
})(); |
| 7776 |
|
| 7777 |
|
| 7778 |
var ARCFourCipher = (function ARCFourCipherClosure() { |
| 7779 |
function ARCFourCipher(key) { |
| 7780 |
this.a = 0; |
| 7781 |
this.b = 0; |
| 7782 |
var s = new Uint8Array(256); |
| 7783 |
var i, j = 0, tmp, keyLength = key.length; |
| 7784 |
for (i = 0; i < 256; ++i) { |
| 7785 |
s[i] = i; |
| 7786 |
} |
| 7787 |
for (i = 0; i < 256; ++i) { |
| 7788 |
tmp = s[i]; |
| 7789 |
j = (j + tmp + key[i % keyLength]) & 0xFF; |
| 7790 |
s[i] = s[j]; |
| 7791 |
s[j] = tmp; |
| 7792 |
} |
| 7793 |
this.s = s; |
| 7794 |
} |
| 7795 |
|
| 7796 |
ARCFourCipher.prototype = { |
| 7797 |
encryptBlock: function ARCFourCipher_encryptBlock(data) { |
| 7798 |
var i, n = data.length, tmp, tmp2; |
| 7799 |
var a = this.a, b = this.b, s = this.s; |
| 7800 |
var output = new Uint8Array(n); |
| 7801 |
for (i = 0; i < n; ++i) { |
| 7802 |
a = (a + 1) & 0xFF; |
| 7803 |
tmp = s[a]; |
| 7804 |
b = (b + tmp) & 0xFF; |
| 7805 |
tmp2 = s[b]; |
| 7806 |
s[a] = tmp2; |
| 7807 |
s[b] = tmp; |
| 7808 |
output[i] = data[i] ^ s[(tmp + tmp2) & 0xFF]; |
| 7809 |
} |
| 7810 |
this.a = a; |
| 7811 |
this.b = b; |
| 7812 |
return output; |
| 7813 |
} |
| 7814 |
}; |
| 7815 |
ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock; |
| 7816 |
|
| 7817 |
return ARCFourCipher; |
| 7818 |
})(); |
| 7819 |
|
| 7820 |
var calculateMD5 = (function calculateMD5Closure() { |
| 7821 |
var r = new Uint8Array([ |
| 7822 |
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, |
| 7823 |
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, |
| 7824 |
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, |
| 7825 |
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]); |
| 7826 |
|
| 7827 |
var k = new Int32Array([ |
| 7828 |
-680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, |
| 7829 |
-1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, |
| 7830 |
1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, |
| 7831 |
643717713, -373897302, -701558691, 38016083, -660478335, -405537848, |
| 7832 |
568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, |
| 7833 |
1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, |
| 7834 |
-1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, |
| 7835 |
-722521979, 76029189, -640364487, -421815835, 530742520, -995338651, |
| 7836 |
-198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, |
| 7837 |
-1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, |
| 7838 |
-145523070, -1120210379, 718787259, -343485551]); |
| 7839 |
|
| 7840 |
function hash(data, offset, length) { |
| 7841 |
var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878; |
| 7842 |
// pre-processing |
| 7843 |
var paddedLength = (length + 72) & ~63; // data + 9 extra bytes |
| 7844 |
var padded = new Uint8Array(paddedLength); |
| 7845 |
var i, j, n; |
| 7846 |
for (i = 0; i < length; ++i) { |
| 7847 |
padded[i] = data[offset++]; |
| 7848 |
} |
| 7849 |
padded[i++] = 0x80; |
| 7850 |
n = paddedLength - 8; |
| 7851 |
while (i < n) { |
| 7852 |
padded[i++] = 0; |
| 7853 |
} |
| 7854 |
padded[i++] = (length << 3) & 0xFF; |
| 7855 |
padded[i++] = (length >> 5) & 0xFF; |
| 7856 |
padded[i++] = (length >> 13) & 0xFF; |
| 7857 |
padded[i++] = (length >> 21) & 0xFF; |
| 7858 |
padded[i++] = (length >>> 29) & 0xFF; |
| 7859 |
padded[i++] = 0; |
| 7860 |
padded[i++] = 0; |
| 7861 |
padded[i++] = 0; |
| 7862 |
var w = new Int32Array(16); |
| 7863 |
for (i = 0; i < paddedLength;) { |
| 7864 |
for (j = 0; j < 16; ++j, i += 4) { |
| 7865 |
w[j] = (padded[i] | (padded[i + 1] << 8) | |
| 7866 |
(padded[i + 2] << 16) | (padded[i + 3] << 24)); |
| 7867 |
} |
| 7868 |
var a = h0, b = h1, c = h2, d = h3, f, g; |
| 7869 |
for (j = 0; j < 64; ++j) { |
| 7870 |
if (j < 16) { |
| 7871 |
f = (b & c) | ((~b) & d); |
| 7872 |
g = j; |
| 7873 |
} else if (j < 32) { |
| 7874 |
f = (d & b) | ((~d) & c); |
| 7875 |
g = (5 * j + 1) & 15; |
| 7876 |
} else if (j < 48) { |
| 7877 |
f = b ^ c ^ d; |
| 7878 |
g = (3 * j + 5) & 15; |
| 7879 |
} else { |
| 7880 |
f = c ^ (b | (~d)); |
| 7881 |
g = (7 * j) & 15; |
| 7882 |
} |
| 7883 |
var tmp = d, rotateArg = (a + f + k[j] + w[g]) | 0, rotate = r[j]; |
| 7884 |
d = c; |
| 7885 |
c = b; |
| 7886 |
b = (b + ((rotateArg << rotate) | (rotateArg >>> (32 - rotate)))) | 0; |
| 7887 |
a = tmp; |
| 7888 |
} |
| 7889 |
h0 = (h0 + a) | 0; |
| 7890 |
h1 = (h1 + b) | 0; |
| 7891 |
h2 = (h2 + c) | 0; |
| 7892 |
h3 = (h3 + d) | 0; |
| 7893 |
} |
| 7894 |
return new Uint8Array([ |
| 7895 |
h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >>> 24) & 0xFF, |
| 7896 |
h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >>> 24) & 0xFF, |
| 7897 |
h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >>> 24) & 0xFF, |
| 7898 |
h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >>> 24) & 0xFF |
| 7899 |
]); |
| 7900 |
} |
| 7901 |
|
| 7902 |
return hash; |
| 7903 |
})(); |
| 7904 |
var Word64 = (function Word64Closure() { |
| 7905 |
function Word64(highInteger, lowInteger) { |
| 7906 |
this.high = highInteger | 0; |
| 7907 |
this.low = lowInteger | 0; |
| 7908 |
} |
| 7909 |
Word64.prototype = { |
| 7910 |
and: function Word64_and(word) { |
| 7911 |
this.high &= word.high; |
| 7912 |
this.low &= word.low; |
| 7913 |
}, |
| 7914 |
xor: function Word64_xor(word) { |
| 7915 |
this.high ^= word.high; |
| 7916 |
this.low ^= word.low; |
| 7917 |
}, |
| 7918 |
|
| 7919 |
or: function Word64_or(word) { |
| 7920 |
this.high |= word.high; |
| 7921 |
this.low |= word.low; |
| 7922 |
}, |
| 7923 |
|
| 7924 |
shiftRight: function Word64_shiftRight(places) { |
| 7925 |
if (places >= 32) { |
| 7926 |
this.low = (this.high >>> (places - 32)) | 0; |
| 7927 |
this.high = 0; |
| 7928 |
} else { |
| 7929 |
this.low = (this.low >>> places) | (this.high << (32 - places)); |
| 7930 |
this.high = (this.high >>> places) | 0; |
| 7931 |
} |
| 7932 |
}, |
| 7933 |
|
| 7934 |
shiftLeft: function Word64_shiftLeft(places) { |
| 7935 |
if (places >= 32) { |
| 7936 |
this.high = this.low << (places - 32); |
| 7937 |
this.low = 0; |
| 7938 |
} else { |
| 7939 |
this.high = (this.high << places) | (this.low >>> (32 - places)); |
| 7940 |
this.low = this.low << places; |
| 7941 |
} |
| 7942 |
}, |
| 7943 |
|
| 7944 |
rotateRight: function Word64_rotateRight(places) { |
| 7945 |
var low, high; |
| 7946 |
if (places & 32) { |
| 7947 |
high = this.low; |
| 7948 |
low = this.high; |
| 7949 |
} else { |
| 7950 |
low = this.low; |
| 7951 |
high = this.high; |
| 7952 |
} |
| 7953 |
places &= 31; |
| 7954 |
this.low = (low >>> places) | (high << (32 - places)); |
| 7955 |
this.high = (high >>> places) | (low << (32 - places)); |
| 7956 |
}, |
| 7957 |
|
| 7958 |
not: function Word64_not() { |
| 7959 |
this.high = ~this.high; |
| 7960 |
this.low = ~this.low; |
| 7961 |
}, |
| 7962 |
|
| 7963 |
add: function Word64_add(word) { |
| 7964 |
var lowAdd = (this.low >>> 0) + (word.low >>> 0); |
| 7965 |
var highAdd = (this.high >>> 0) + (word.high >>> 0); |
| 7966 |
if (lowAdd > 0xFFFFFFFF) { |
| 7967 |
highAdd += 1; |
| 7968 |
} |
| 7969 |
this.low = lowAdd | 0; |
| 7970 |
this.high = highAdd | 0; |
| 7971 |
}, |
| 7972 |
|
| 7973 |
copyTo: function Word64_copyTo(bytes, offset) { |
| 7974 |
bytes[offset] = (this.high >>> 24) & 0xFF; |
| 7975 |
bytes[offset + 1] = (this.high >> 16) & 0xFF; |
| 7976 |
bytes[offset + 2] = (this.high >> 8) & 0xFF; |
| 7977 |
bytes[offset + 3] = this.high & 0xFF; |
| 7978 |
bytes[offset + 4] = (this.low >>> 24) & 0xFF; |
| 7979 |
bytes[offset + 5] = (this.low >> 16) & 0xFF; |
| 7980 |
bytes[offset + 6] = (this.low >> 8) & 0xFF; |
| 7981 |
bytes[offset + 7] = this.low & 0xFF; |
| 7982 |
}, |
| 7983 |
|
| 7984 |
assign: function Word64_assign(word) { |
| 7985 |
this.high = word.high; |
| 7986 |
this.low = word.low; |
| 7987 |
} |
| 7988 |
}; |
| 7989 |
return Word64; |
| 7990 |
})(); |
| 7991 |
|
| 7992 |
var calculateSHA256 = (function calculateSHA256Closure() { |
| 7993 |
function rotr(x, n) { |
| 7994 |
return (x >>> n) | (x << 32 - n); |
| 7995 |
} |
| 7996 |
|
| 7997 |
function ch(x, y, z) { |
| 7998 |
return (x & y) ^ (~x & z); |
| 7999 |
} |
| 8000 |
|
| 8001 |
function maj(x, y, z) { |
| 8002 |
return (x & y) ^ (x & z) ^ (y & z); |
| 8003 |
} |
| 8004 |
|
| 8005 |
function sigma(x) { |
| 8006 |
return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); |
| 8007 |
} |
| 8008 |
|
| 8009 |
function sigmaPrime(x) { |
| 8010 |
return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); |
| 8011 |
} |
| 8012 |
|
| 8013 |
function littleSigma(x) { |
| 8014 |
return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3; |
| 8015 |
} |
| 8016 |
|
| 8017 |
function littleSigmaPrime(x) { |
| 8018 |
return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10; |
| 8019 |
} |
| 8020 |
|
| 8021 |
var k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, |
| 8022 |
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, |
| 8023 |
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, |
| 8024 |
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, |
| 8025 |
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, |
| 8026 |
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, |
| 8027 |
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, |
| 8028 |
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, |
| 8029 |
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, |
| 8030 |
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, |
| 8031 |
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, |
| 8032 |
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
| 8033 |
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, |
| 8034 |
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, |
| 8035 |
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, |
| 8036 |
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; |
| 8037 |
|
| 8038 |
function hash(data, offset, length) { |
| 8039 |
// initial hash values |
| 8040 |
var h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, |
| 8041 |
h3 = 0xa54ff53a, h4 = 0x510e527f, h5 = 0x9b05688c, |
| 8042 |
h6 = 0x1f83d9ab, h7 = 0x5be0cd19; |
| 8043 |
// pre-processing |
| 8044 |
var paddedLength = Math.ceil((length + 9) / 64) * 64; |
| 8045 |
var padded = new Uint8Array(paddedLength); |
| 8046 |
var i, j, n; |
| 8047 |
for (i = 0; i < length; ++i) { |
| 8048 |
padded[i] = data[offset++]; |
| 8049 |
} |
| 8050 |
padded[i++] = 0x80; |
| 8051 |
n = paddedLength - 8; |
| 8052 |
while (i < n) { |
| 8053 |
padded[i++] = 0; |
| 8054 |
} |
| 8055 |
padded[i++] = 0; |
| 8056 |
padded[i++] = 0; |
| 8057 |
padded[i++] = 0; |
| 8058 |
padded[i++] = (length >>> 29) & 0xFF; |
| 8059 |
padded[i++] = (length >> 21) & 0xFF; |
| 8060 |
padded[i++] = (length >> 13) & 0xFF; |
| 8061 |
padded[i++] = (length >> 5) & 0xFF; |
| 8062 |
padded[i++] = (length << 3) & 0xFF; |
| 8063 |
var w = new Uint32Array(64); |
| 8064 |
// for each 512 bit block |
| 8065 |
for (i = 0; i < paddedLength;) { |
| 8066 |
for (j = 0; j < 16; ++j) { |
| 8067 |
w[j] = (padded[i] << 24 | (padded[i + 1] << 16) | |
| 8068 |
(padded[i + 2] << 8) | (padded[i + 3])); |
| 8069 |
i += 4; |
| 8070 |
} |
| 8071 |
|
| 8072 |
for (j = 16; j < 64; ++j) { |
| 8073 |
w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + |
| 8074 |
littleSigma(w[j - 15]) + w[j - 16] | 0; |
| 8075 |
} |
| 8076 |
var a = h0, b = h1, c = h2, d = h3, e = h4, |
| 8077 |
f = h5, g = h6, h = h7, t1, t2; |
| 8078 |
for (j = 0; j < 64; ++j) { |
| 8079 |
t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j]; |
| 8080 |
t2 = sigma(a) + maj(a, b, c); |
| 8081 |
h = g; |
| 8082 |
g = f; |
| 8083 |
f = e; |
| 8084 |
e = (d + t1) | 0; |
| 8085 |
d = c; |
| 8086 |
c = b; |
| 8087 |
b = a; |
| 8088 |
a = (t1 + t2) | 0; |
| 8089 |
} |
| 8090 |
h0 = (h0 + a) | 0; |
| 8091 |
h1 = (h1 + b) | 0; |
| 8092 |
h2 = (h2 + c) | 0; |
| 8093 |
h3 = (h3 + d) | 0; |
| 8094 |
h4 = (h4 + e) | 0; |
| 8095 |
h5 = (h5 + f) | 0; |
| 8096 |
h6 = (h6 + g) | 0; |
| 8097 |
h7 = (h7 + h) | 0; |
| 8098 |
} |
| 8099 |
return new Uint8Array([ |
| 8100 |
(h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, (h0) & 0xFF, |
| 8101 |
(h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, (h1) & 0xFF, |
| 8102 |
(h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, (h2) & 0xFF, |
| 8103 |
(h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, (h3) & 0xFF, |
| 8104 |
(h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, (h4) & 0xFF, |
| 8105 |
(h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, (h5) & 0xFF, |
| 8106 |
(h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, (h6) & 0xFF, |
| 8107 |
(h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, (h7) & 0xFF |
| 8108 |
]); |
| 8109 |
} |
| 8110 |
|
| 8111 |
return hash; |
| 8112 |
})(); |
| 8113 |
|
| 8114 |
var calculateSHA512 = (function calculateSHA512Closure() { |
| 8115 |
function ch(result, x, y, z, tmp) { |
| 8116 |
result.assign(x); |
| 8117 |
result.and(y); |
| 8118 |
tmp.assign(x); |
| 8119 |
tmp.not(); |
| 8120 |
tmp.and(z); |
| 8121 |
result.xor(tmp); |
| 8122 |
} |
| 8123 |
|
| 8124 |
function maj(result, x, y, z, tmp) { |
| 8125 |
result.assign(x); |
| 8126 |
result.and(y); |
| 8127 |
tmp.assign(x); |
| 8128 |
tmp.and(z); |
| 8129 |
result.xor(tmp); |
| 8130 |
tmp.assign(y); |
| 8131 |
tmp.and(z); |
| 8132 |
result.xor(tmp); |
| 8133 |
} |
| 8134 |
|
| 8135 |
function sigma(result, x, tmp) { |
| 8136 |
result.assign(x); |
| 8137 |
result.rotateRight(28); |
| 8138 |
tmp.assign(x); |
| 8139 |
tmp.rotateRight(34); |
| 8140 |
result.xor(tmp); |
| 8141 |
tmp.assign(x); |
| 8142 |
tmp.rotateRight(39); |
| 8143 |
result.xor(tmp); |
| 8144 |
} |
| 8145 |
|
| 8146 |
function sigmaPrime(result, x, tmp) { |
| 8147 |
result.assign(x); |
| 8148 |
result.rotateRight(14); |
| 8149 |
tmp.assign(x); |
| 8150 |
tmp.rotateRight(18); |
| 8151 |
result.xor(tmp); |
| 8152 |
tmp.assign(x); |
| 8153 |
tmp.rotateRight(41); |
| 8154 |
result.xor(tmp); |
| 8155 |
} |
| 8156 |
|
| 8157 |
function littleSigma(result, x, tmp) { |
| 8158 |
result.assign(x); |
| 8159 |
result.rotateRight(1); |
| 8160 |
tmp.assign(x); |
| 8161 |
tmp.rotateRight(8); |
| 8162 |
result.xor(tmp); |
| 8163 |
tmp.assign(x); |
| 8164 |
tmp.shiftRight(7); |
| 8165 |
result.xor(tmp); |
| 8166 |
} |
| 8167 |
|
| 8168 |
function littleSigmaPrime(result, x, tmp) { |
| 8169 |
result.assign(x); |
| 8170 |
result.rotateRight(19); |
| 8171 |
tmp.assign(x); |
| 8172 |
tmp.rotateRight(61); |
| 8173 |
result.xor(tmp); |
| 8174 |
tmp.assign(x); |
| 8175 |
tmp.shiftRight(6); |
| 8176 |
result.xor(tmp); |
| 8177 |
} |
| 8178 |
|
| 8179 |
var k = [ |
| 8180 |
new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), |
| 8181 |
new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), |
| 8182 |
new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), |
| 8183 |
new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), |
| 8184 |
new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), |
| 8185 |
new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), |
| 8186 |
new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), |
| 8187 |
new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), |
| 8188 |
new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), |
| 8189 |
new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), |
| 8190 |
new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), |
| 8191 |
new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), |
| 8192 |
new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), |
| 8193 |
new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), |
| 8194 |
new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), |
| 8195 |
new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), |
| 8196 |
new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), |
| 8197 |
new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), |
| 8198 |
new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), |
| 8199 |
new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), |
| 8200 |
new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), |
| 8201 |
new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), |
| 8202 |
new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), |
| 8203 |
new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), |
| 8204 |
new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), |
| 8205 |
new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), |
| 8206 |
new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), |
| 8207 |
new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), |
| 8208 |
new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), |
| 8209 |
new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), |
| 8210 |
new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), |
| 8211 |
new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), |
| 8212 |
new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), |
| 8213 |
new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), |
| 8214 |
new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), |
| 8215 |
new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), |
| 8216 |
new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), |
| 8217 |
new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), |
| 8218 |
new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), |
| 8219 |
new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)]; |
| 8220 |
|
| 8221 |
function hash(data, offset, length, mode384) { |
| 8222 |
mode384 = !!mode384; |
| 8223 |
// initial hash values |
| 8224 |
var h0, h1, h2, h3, h4, h5, h6, h7; |
| 8225 |
if (!mode384) { |
| 8226 |
h0 = new Word64(0x6a09e667, 0xf3bcc908); |
| 8227 |
h1 = new Word64(0xbb67ae85, 0x84caa73b); |
| 8228 |
h2 = new Word64(0x3c6ef372, 0xfe94f82b); |
| 8229 |
h3 = new Word64(0xa54ff53a, 0x5f1d36f1); |
| 8230 |
h4 = new Word64(0x510e527f, 0xade682d1); |
| 8231 |
h5 = new Word64(0x9b05688c, 0x2b3e6c1f); |
| 8232 |
h6 = new Word64(0x1f83d9ab, 0xfb41bd6b); |
| 8233 |
h7 = new Word64(0x5be0cd19, 0x137e2179); |
| 8234 |
} |
| 8235 |
else { |
| 8236 |
// SHA384 is exactly the same |
| 8237 |
// except with different starting values and a trimmed result |
| 8238 |
h0 = new Word64(0xcbbb9d5d, 0xc1059ed8); |
| 8239 |
h1 = new Word64(0x629a292a, 0x367cd507); |
| 8240 |
h2 = new Word64(0x9159015a, 0x3070dd17); |
| 8241 |
h3 = new Word64(0x152fecd8, 0xf70e5939); |
| 8242 |
h4 = new Word64(0x67332667, 0xffc00b31); |
| 8243 |
h5 = new Word64(0x8eb44a87, 0x68581511); |
| 8244 |
h6 = new Word64(0xdb0c2e0d, 0x64f98fa7); |
| 8245 |
h7 = new Word64(0x47b5481d, 0xbefa4fa4); |
| 8246 |
} |
| 8247 |
|
| 8248 |
// pre-processing |
| 8249 |
var paddedLength = Math.ceil((length + 17) / 128) * 128; |
| 8250 |
var padded = new Uint8Array(paddedLength); |
| 8251 |
var i, j, n; |
| 8252 |
for (i = 0; i < length; ++i) { |
| 8253 |
padded[i] = data[offset++]; |
| 8254 |
} |
| 8255 |
padded[i++] = 0x80; |
| 8256 |
n = paddedLength - 16; |
| 8257 |
while (i < n) { |
| 8258 |
padded[i++] = 0; |
| 8259 |
} |
| 8260 |
padded[i++] = 0; |
| 8261 |
padded[i++] = 0; |
| 8262 |
padded[i++] = 0; |
| 8263 |
padded[i++] = 0; |
| 8264 |
padded[i++] = 0; |
| 8265 |
padded[i++] = 0; |
| 8266 |
padded[i++] = 0; |
| 8267 |
padded[i++] = 0; |
| 8268 |
padded[i++] = 0; |
| 8269 |
padded[i++] = 0; |
| 8270 |
padded[i++] = 0; |
| 8271 |
padded[i++] = (length >>> 29) & 0xFF; |
| 8272 |
padded[i++] = (length >> 21) & 0xFF; |
| 8273 |
padded[i++] = (length >> 13) & 0xFF; |
| 8274 |
padded[i++] = (length >> 5) & 0xFF; |
| 8275 |
padded[i++] = (length << 3) & 0xFF; |
| 8276 |
|
| 8277 |
var w = new Array(80); |
| 8278 |
for (i = 0; i < 80; i++) { |
| 8279 |
w[i] = new Word64(0, 0); |
| 8280 |
} |
| 8281 |
var a = new Word64(0, 0), b = new Word64(0, 0), c = new Word64(0, 0); |
| 8282 |
var d = new Word64(0, 0), e = new Word64(0, 0), f = new Word64(0, 0); |
| 8283 |
var g = new Word64(0, 0), h = new Word64(0, 0); |
| 8284 |
var t1 = new Word64(0, 0), t2 = new Word64(0, 0); |
| 8285 |
var tmp1 = new Word64(0, 0), tmp2 = new Word64(0, 0), tmp3; |
| 8286 |
|
| 8287 |
// for each 1024 bit block |
| 8288 |
for (i = 0; i < paddedLength;) { |
| 8289 |
for (j = 0; j < 16; ++j) { |
| 8290 |
w[j].high = (padded[i] << 24) | (padded[i + 1] << 16) | |
| 8291 |
(padded[i + 2] << 8) | (padded[i + 3]); |
| 8292 |
w[j].low = (padded[i + 4]) << 24 | (padded[i + 5]) << 16 | |
| 8293 |
(padded[i + 6]) << 8 | (padded[i + 7]); |
| 8294 |
i += 8; |
| 8295 |
} |
| 8296 |
for (j = 16; j < 80; ++j) { |
| 8297 |
tmp3 = w[j]; |
| 8298 |
littleSigmaPrime(tmp3, w[j - 2], tmp2); |
| 8299 |
tmp3.add(w[j - 7]); |
| 8300 |
littleSigma(tmp1, w[j - 15], tmp2); |
| 8301 |
tmp3.add(tmp1); |
| 8302 |
tmp3.add(w[j - 16]); |
| 8303 |
} |
| 8304 |
|
| 8305 |
a.assign(h0); b.assign(h1); c.assign(h2); d.assign(h3); |
| 8306 |
e.assign(h4); f.assign(h5); g.assign(h6); h.assign(h7); |
| 8307 |
for (j = 0; j < 80; ++j) { |
| 8308 |
t1.assign(h); |
| 8309 |
sigmaPrime(tmp1, e, tmp2); |
| 8310 |
t1.add(tmp1); |
| 8311 |
ch(tmp1, e, f, g, tmp2); |
| 8312 |
t1.add(tmp1); |
| 8313 |
t1.add(k[j]); |
| 8314 |
t1.add(w[j]); |
| 8315 |
|
| 8316 |
sigma(t2, a, tmp2); |
| 8317 |
maj(tmp1, a, b, c, tmp2); |
| 8318 |
t2.add(tmp1); |
| 8319 |
|
| 8320 |
tmp3 = h; |
| 8321 |
h = g; |
| 8322 |
g = f; |
| 8323 |
f = e; |
| 8324 |
d.add(t1); |
| 8325 |
e = d; |
| 8326 |
d = c; |
| 8327 |
c = b; |
| 8328 |
b = a; |
| 8329 |
tmp3.assign(t1); |
| 8330 |
tmp3.add(t2); |
| 8331 |
a = tmp3; |
| 8332 |
} |
| 8333 |
h0.add(a); |
| 8334 |
h1.add(b); |
| 8335 |
h2.add(c); |
| 8336 |
h3.add(d); |
| 8337 |
h4.add(e); |
| 8338 |
h5.add(f); |
| 8339 |
h6.add(g); |
| 8340 |
h7.add(h); |
| 8341 |
} |
| 8342 |
|
| 8343 |
var result; |
| 8344 |
if (!mode384) { |
| 8345 |
result = new Uint8Array(64); |
| 8346 |
h0.copyTo(result,0); |
| 8347 |
h1.copyTo(result,8); |
| 8348 |
h2.copyTo(result,16); |
| 8349 |
h3.copyTo(result,24); |
| 8350 |
h4.copyTo(result,32); |
| 8351 |
h5.copyTo(result,40); |
| 8352 |
h6.copyTo(result,48); |
| 8353 |
h7.copyTo(result,56); |
| 8354 |
} |
| 8355 |
else { |
| 8356 |
result = new Uint8Array(48); |
| 8357 |
h0.copyTo(result,0); |
| 8358 |
h1.copyTo(result,8); |
| 8359 |
h2.copyTo(result,16); |
| 8360 |
h3.copyTo(result,24); |
| 8361 |
h4.copyTo(result,32); |
| 8362 |
h5.copyTo(result,40); |
| 8363 |
} |
| 8364 |
return result; |
| 8365 |
} |
| 8366 |
|
| 8367 |
return hash; |
| 8368 |
})(); |
| 8369 |
var calculateSHA384 = (function calculateSHA384Closure() { |
| 8370 |
function hash(data, offset, length) { |
| 8371 |
return calculateSHA512(data, offset, length, true); |
| 8372 |
} |
| 8373 |
|
| 8374 |
return hash; |
| 8375 |
})(); |
| 8376 |
var NullCipher = (function NullCipherClosure() { |
| 8377 |
function NullCipher() { |
| 8378 |
} |
| 8379 |
|
| 8380 |
NullCipher.prototype = { |
| 8381 |
decryptBlock: function NullCipher_decryptBlock(data) { |
| 8382 |
return data; |
| 8383 |
} |
| 8384 |
}; |
| 8385 |
|
| 8386 |
return NullCipher; |
| 8387 |
})(); |
| 8388 |
|
| 8389 |
var AES128Cipher = (function AES128CipherClosure() { |
| 8390 |
var rcon = new Uint8Array([ |
| 8391 |
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, |
| 8392 |
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, |
| 8393 |
0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, |
| 8394 |
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, |
| 8395 |
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, |
| 8396 |
0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, |
| 8397 |
0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, |
| 8398 |
0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, |
| 8399 |
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, |
| 8400 |
0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, |
| 8401 |
0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, |
| 8402 |
0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, |
| 8403 |
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, |
| 8404 |
0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, |
| 8405 |
0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, |
| 8406 |
0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, |
| 8407 |
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, |
| 8408 |
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, |
| 8409 |
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, |
| 8410 |
0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, |
| 8411 |
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, |
| 8412 |
0x74, 0xe8, 0xcb, 0x8d]); |
| 8413 |
|
| 8414 |
var s = new Uint8Array([ |
| 8415 |
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, |
| 8416 |
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, |
| 8417 |
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, |
| 8418 |
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, |
| 8419 |
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, |
| 8420 |
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, |
| 8421 |
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, |
| 8422 |
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, |
| 8423 |
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, |
| 8424 |
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, |
| 8425 |
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, |
| 8426 |
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, |
| 8427 |
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, |
| 8428 |
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, |
| 8429 |
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, |
| 8430 |
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, |
| 8431 |
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, |
| 8432 |
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, |
| 8433 |
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, |
| 8434 |
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, |
| 8435 |
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, |
| 8436 |
0xb0, 0x54, 0xbb, 0x16]); |
| 8437 |
|
| 8438 |
var inv_s = new Uint8Array([ |
| 8439 |
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, |
| 8440 |
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, |
| 8441 |
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, |
| 8442 |
0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, |
| 8443 |
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, |
| 8444 |
0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, |
| 8445 |
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, |
| 8446 |
0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, |
| 8447 |
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, |
| 8448 |
0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, |
| 8449 |
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, |
| 8450 |
0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, |
| 8451 |
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, |
| 8452 |
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, |
| 8453 |
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, |
| 8454 |
0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, |
| 8455 |
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, |
| 8456 |
0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, |
| 8457 |
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, |
| 8458 |
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, |
| 8459 |
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, |
| 8460 |
0x55, 0x21, 0x0c, 0x7d]); |
| 8461 |
var mixCol = new Uint8Array(256); |
| 8462 |
for (var i = 0; i < 256; i++) { |
| 8463 |
if (i < 128) { |
| 8464 |
mixCol[i] = i << 1; |
| 8465 |
} else { |
| 8466 |
mixCol[i] = (i << 1) ^ 0x1b; |
| 8467 |
} |
| 8468 |
} |
| 8469 |
var mix = new Uint32Array([ |
| 8470 |
0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, |
| 8471 |
0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, |
| 8472 |
0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, |
| 8473 |
0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, |
| 8474 |
0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, |
| 8475 |
0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, |
| 8476 |
0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, |
| 8477 |
0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, |
| 8478 |
0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, |
| 8479 |
0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, |
| 8480 |
0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, |
| 8481 |
0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, |
| 8482 |
0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, |
| 8483 |
0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, |
| 8484 |
0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, |
| 8485 |
0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, |
| 8486 |
0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, |
| 8487 |
0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, |
| 8488 |
0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, |
| 8489 |
0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, |
| 8490 |
0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, |
| 8491 |
0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, |
| 8492 |
0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, |
| 8493 |
0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, |
| 8494 |
0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, |
| 8495 |
0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, |
| 8496 |
0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, |
| 8497 |
0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, |
| 8498 |
0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, |
| 8499 |
0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, |
| 8500 |
0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, |
| 8501 |
0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, |
| 8502 |
0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, |
| 8503 |
0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, |
| 8504 |
0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, |
| 8505 |
0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, |
| 8506 |
0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, |
| 8507 |
0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, |
| 8508 |
0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, |
| 8509 |
0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, |
| 8510 |
0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, |
| 8511 |
0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, |
| 8512 |
0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); |
| 8513 |
|
| 8514 |
function expandKey128(cipherKey) { |
| 8515 |
var b = 176, result = new Uint8Array(b); |
| 8516 |
result.set(cipherKey); |
| 8517 |
for (var j = 16, i = 1; j < b; ++i) { |
| 8518 |
// RotWord |
| 8519 |
var t1 = result[j - 3], t2 = result[j - 2], |
| 8520 |
t3 = result[j - 1], t4 = result[j - 4]; |
| 8521 |
// SubWord |
| 8522 |
t1 = s[t1]; |
| 8523 |
t2 = s[t2]; |
| 8524 |
t3 = s[t3]; |
| 8525 |
t4 = s[t4]; |
| 8526 |
// Rcon |
| 8527 |
t1 = t1 ^ rcon[i]; |
| 8528 |
for (var n = 0; n < 4; ++n) { |
| 8529 |
result[j] = (t1 ^= result[j - 16]); |
| 8530 |
j++; |
| 8531 |
result[j] = (t2 ^= result[j - 16]); |
| 8532 |
j++; |
| 8533 |
result[j] = (t3 ^= result[j - 16]); |
| 8534 |
j++; |
| 8535 |
result[j] = (t4 ^= result[j - 16]); |
| 8536 |
j++; |
| 8537 |
} |
| 8538 |
} |
| 8539 |
return result; |
| 8540 |
} |
| 8541 |
|
| 8542 |
function decrypt128(input, key) { |
| 8543 |
var state = new Uint8Array(16); |
| 8544 |
state.set(input); |
| 8545 |
var i, j, k; |
| 8546 |
var t, u, v; |
| 8547 |
// AddRoundKey |
| 8548 |
for (j = 0, k = 160; j < 16; ++j, ++k) { |
| 8549 |
state[j] ^= key[k]; |
| 8550 |
} |
| 8551 |
for (i = 9; i >= 1; --i) { |
| 8552 |
// InvShiftRows |
| 8553 |
t = state[13]; |
| 8554 |
state[13] = state[9]; |
| 8555 |
state[9] = state[5]; |
| 8556 |
state[5] = state[1]; |
| 8557 |
state[1] = t; |
| 8558 |
t = state[14]; |
| 8559 |
u = state[10]; |
| 8560 |
state[14] = state[6]; |
| 8561 |
state[10] = state[2]; |
| 8562 |
state[6] = t; |
| 8563 |
state[2] = u; |
| 8564 |
t = state[15]; |
| 8565 |
u = state[11]; |
| 8566 |
v = state[7]; |
| 8567 |
state[15] = state[3]; |
| 8568 |
state[11] = t; |
| 8569 |
state[7] = u; |
| 8570 |
state[3] = v; |
| 8571 |
// InvSubBytes |
| 8572 |
for (j = 0; j < 16; ++j) { |
| 8573 |
state[j] = inv_s[state[j]]; |
| 8574 |
} |
| 8575 |
// AddRoundKey |
| 8576 |
for (j = 0, k = i * 16; j < 16; ++j, ++k) { |
| 8577 |
state[j] ^= key[k]; |
| 8578 |
} |
| 8579 |
// InvMixColumns |
| 8580 |
for (j = 0; j < 16; j += 4) { |
| 8581 |
var s0 = mix[state[j]], s1 = mix[state[j + 1]], |
| 8582 |
s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; |
| 8583 |
t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ |
| 8584 |
(s3 >>> 24) ^ (s3 << 8)); |
| 8585 |
state[j] = (t >>> 24) & 0xFF; |
| 8586 |
state[j + 1] = (t >> 16) & 0xFF; |
| 8587 |
state[j + 2] = (t >> 8) & 0xFF; |
| 8588 |
state[j + 3] = t & 0xFF; |
| 8589 |
} |
| 8590 |
} |
| 8591 |
// InvShiftRows |
| 8592 |
t = state[13]; |
| 8593 |
state[13] = state[9]; |
| 8594 |
state[9] = state[5]; |
| 8595 |
state[5] = state[1]; |
| 8596 |
state[1] = t; |
| 8597 |
t = state[14]; |
| 8598 |
u = state[10]; |
| 8599 |
state[14] = state[6]; |
| 8600 |
state[10] = state[2]; |
| 8601 |
state[6] = t; |
| 8602 |
state[2] = u; |
| 8603 |
t = state[15]; |
| 8604 |
u = state[11]; |
| 8605 |
v = state[7]; |
| 8606 |
state[15] = state[3]; |
| 8607 |
state[11] = t; |
| 8608 |
state[7] = u; |
| 8609 |
state[3] = v; |
| 8610 |
for (j = 0; j < 16; ++j) { |
| 8611 |
// InvSubBytes |
| 8612 |
state[j] = inv_s[state[j]]; |
| 8613 |
// AddRoundKey |
| 8614 |
state[j] ^= key[j]; |
| 8615 |
} |
| 8616 |
return state; |
| 8617 |
} |
| 8618 |
|
| 8619 |
function encrypt128(input, key) { |
| 8620 |
var t, u, v, k; |
| 8621 |
var state = new Uint8Array(16); |
| 8622 |
state.set(input); |
| 8623 |
for (j = 0; j < 16; ++j) { |
| 8624 |
// AddRoundKey |
| 8625 |
state[j] ^= key[j]; |
| 8626 |
} |
| 8627 |
|
| 8628 |
for (i = 1; i < 10; i++) { |
| 8629 |
//SubBytes |
| 8630 |
for (j = 0; j < 16; ++j) { |
| 8631 |
state[j] = s[state[j]]; |
| 8632 |
} |
| 8633 |
//ShiftRows |
| 8634 |
v = state[1]; |
| 8635 |
state[1] = state[5]; |
| 8636 |
state[5] = state[9]; |
| 8637 |
state[9] = state[13]; |
| 8638 |
state[13] = v; |
| 8639 |
v = state[2]; |
| 8640 |
u = state[6]; |
| 8641 |
state[2] = state[10]; |
| 8642 |
state[6] = state[14]; |
| 8643 |
state[10] = v; |
| 8644 |
state[14] = u; |
| 8645 |
v = state[3]; |
| 8646 |
u = state[7]; |
| 8647 |
t = state[11]; |
| 8648 |
state[3] = state[15]; |
| 8649 |
state[7] = v; |
| 8650 |
state[11] = u; |
| 8651 |
state[15] = t; |
| 8652 |
//MixColumns |
| 8653 |
for (var j = 0; j < 16; j += 4) { |
| 8654 |
var s0 = state[j + 0], s1 = state[j + 1]; |
| 8655 |
var s2 = state[j + 2], s3 = state[j + 3]; |
| 8656 |
t = s0 ^ s1 ^ s2 ^ s3; |
| 8657 |
state[j + 0] ^= t ^ mixCol[s0 ^ s1]; |
| 8658 |
state[j + 1] ^= t ^ mixCol[s1 ^ s2]; |
| 8659 |
state[j + 2] ^= t ^ mixCol[s2 ^ s3]; |
| 8660 |
state[j + 3] ^= t ^ mixCol[s3 ^ s0]; |
| 8661 |
} |
| 8662 |
//AddRoundKey |
| 8663 |
for (j = 0, k = i * 16; j < 16; ++j, ++k) { |
| 8664 |
state[j] ^= key[k]; |
| 8665 |
} |
| 8666 |
} |
| 8667 |
|
| 8668 |
//SubBytes |
| 8669 |
for (j = 0; j < 16; ++j) { |
| 8670 |
state[j] = s[state[j]]; |
| 8671 |
} |
| 8672 |
//ShiftRows |
| 8673 |
v = state[1]; |
| 8674 |
state[1] = state[5]; |
| 8675 |
state[5] = state[9]; |
| 8676 |
state[9] = state[13]; |
| 8677 |
state[13] = v; |
| 8678 |
v = state[2]; |
| 8679 |
u = state[6]; |
| 8680 |
state[2] = state[10]; |
| 8681 |
state[6] = state[14]; |
| 8682 |
state[10] = v; |
| 8683 |
state[14] = u; |
| 8684 |
v = state[3]; |
| 8685 |
u = state[7]; |
| 8686 |
t = state[11]; |
| 8687 |
state[3] = state[15]; |
| 8688 |
state[7] = v; |
| 8689 |
state[11] = u; |
| 8690 |
state[15] = t; |
| 8691 |
//AddRoundKey |
| 8692 |
for (j = 0, k = 160; j < 16; ++j, ++k) { |
| 8693 |
state[j] ^= key[k]; |
| 8694 |
} |
| 8695 |
return state; |
| 8696 |
} |
| 8697 |
|
| 8698 |
function AES128Cipher(key) { |
| 8699 |
this.key = expandKey128(key); |
| 8700 |
this.buffer = new Uint8Array(16); |
| 8701 |
this.bufferPosition = 0; |
| 8702 |
} |
| 8703 |
|
| 8704 |
function decryptBlock2(data, finalize) { |
| 8705 |
var i, j, ii, sourceLength = data.length, |
| 8706 |
buffer = this.buffer, bufferLength = this.bufferPosition, |
| 8707 |
result = [], iv = this.iv; |
| 8708 |
for (i = 0; i < sourceLength; ++i) { |
| 8709 |
buffer[bufferLength] = data[i]; |
| 8710 |
++bufferLength; |
| 8711 |
if (bufferLength < 16) { |
| 8712 |
continue; |
| 8713 |
} |
| 8714 |
// buffer is full, decrypting |
| 8715 |
var plain = decrypt128(buffer, this.key); |
| 8716 |
// xor-ing the IV vector to get plain text |
| 8717 |
for (j = 0; j < 16; ++j) { |
| 8718 |
plain[j] ^= iv[j]; |
| 8719 |
} |
| 8720 |
iv = buffer; |
| 8721 |
result.push(plain); |
| 8722 |
buffer = new Uint8Array(16); |
| 8723 |
bufferLength = 0; |
| 8724 |
} |
| 8725 |
// saving incomplete buffer |
| 8726 |
this.buffer = buffer; |
| 8727 |
this.bufferLength = bufferLength; |
| 8728 |
this.iv = iv; |
| 8729 |
if (result.length === 0) { |
| 8730 |
return new Uint8Array([]); |
| 8731 |
} |
| 8732 |
// combining plain text blocks into one |
| 8733 |
var outputLength = 16 * result.length; |
| 8734 |
if (finalize) { |
| 8735 |
// undo a padding that is described in RFC 2898 |
| 8736 |
var lastBlock = result[result.length - 1]; |
| 8737 |
var psLen = lastBlock[15]; |
| 8738 |
if (psLen <= 16) { |
| 8739 |
for (i = 15, ii = 16 - psLen; i >= ii; --i) { |
| 8740 |
if (lastBlock[i] !== psLen) { |
| 8741 |
// Invalid padding, assume that the block has no padding. |
| 8742 |
psLen = 0; |
| 8743 |
break; |
| 8744 |
} |
| 8745 |
} |
| 8746 |
outputLength -= psLen; |
| 8747 |
result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); |
| 8748 |
} |
| 8749 |
} |
| 8750 |
var output = new Uint8Array(outputLength); |
| 8751 |
for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { |
| 8752 |
output.set(result[i], j); |
| 8753 |
} |
| 8754 |
return output; |
| 8755 |
} |
| 8756 |
|
| 8757 |
AES128Cipher.prototype = { |
| 8758 |
decryptBlock: function AES128Cipher_decryptBlock(data, finalize) { |
| 8759 |
var i, sourceLength = data.length; |
| 8760 |
var buffer = this.buffer, bufferLength = this.bufferPosition; |
| 8761 |
// waiting for IV values -- they are at the start of the stream |
| 8762 |
for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { |
| 8763 |
buffer[bufferLength] = data[i]; |
| 8764 |
} |
| 8765 |
if (bufferLength < 16) { |
| 8766 |
// need more data |
| 8767 |
this.bufferLength = bufferLength; |
| 8768 |
return new Uint8Array([]); |
| 8769 |
} |
| 8770 |
this.iv = buffer; |
| 8771 |
this.buffer = new Uint8Array(16); |
| 8772 |
this.bufferLength = 0; |
| 8773 |
// starting decryption |
| 8774 |
this.decryptBlock = decryptBlock2; |
| 8775 |
return this.decryptBlock(data.subarray(16), finalize); |
| 8776 |
}, |
| 8777 |
encrypt: function AES128Cipher_encrypt(data, iv) { |
| 8778 |
var i, j, ii, sourceLength = data.length, |
| 8779 |
buffer = this.buffer, bufferLength = this.bufferPosition, |
| 8780 |
result = []; |
| 8781 |
if (!iv) { |
| 8782 |
iv = new Uint8Array(16); |
| 8783 |
} |
| 8784 |
for (i = 0; i < sourceLength; ++i) { |
| 8785 |
buffer[bufferLength] = data[i]; |
| 8786 |
++bufferLength; |
| 8787 |
if (bufferLength < 16) { |
| 8788 |
continue; |
| 8789 |
} |
| 8790 |
for (j = 0; j < 16; ++j) { |
| 8791 |
buffer[j] ^= iv[j]; |
| 8792 |
} |
| 8793 |
|
| 8794 |
// buffer is full, encrypting |
| 8795 |
var cipher = encrypt128(buffer, this.key); |
| 8796 |
iv = cipher; |
| 8797 |
result.push(cipher); |
| 8798 |
buffer = new Uint8Array(16); |
| 8799 |
bufferLength = 0; |
| 8800 |
} |
| 8801 |
// saving incomplete buffer |
| 8802 |
this.buffer = buffer; |
| 8803 |
this.bufferLength = bufferLength; |
| 8804 |
this.iv = iv; |
| 8805 |
if (result.length === 0) { |
| 8806 |
return new Uint8Array([]); |
| 8807 |
} |
| 8808 |
// combining plain text blocks into one |
| 8809 |
var outputLength = 16 * result.length; |
| 8810 |
var output = new Uint8Array(outputLength); |
| 8811 |
for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { |
| 8812 |
output.set(result[i], j); |
| 8813 |
} |
| 8814 |
return output; |
| 8815 |
} |
| 8816 |
}; |
| 8817 |
|
| 8818 |
return AES128Cipher; |
| 8819 |
})(); |
| 8820 |
|
| 8821 |
var AES256Cipher = (function AES256CipherClosure() { |
| 8822 |
var rcon = new Uint8Array([ |
| 8823 |
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, |
| 8824 |
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, |
| 8825 |
0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, |
| 8826 |
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, |
| 8827 |
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, |
| 8828 |
0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, |
| 8829 |
0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, |
| 8830 |
0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, |
| 8831 |
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, |
| 8832 |
0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, |
| 8833 |
0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, |
| 8834 |
0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, |
| 8835 |
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, |
| 8836 |
0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, |
| 8837 |
0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, |
| 8838 |
0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, |
| 8839 |
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, |
| 8840 |
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, |
| 8841 |
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, |
| 8842 |
0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, |
| 8843 |
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, |
| 8844 |
0x74, 0xe8, 0xcb, 0x8d]); |
| 8845 |
|
| 8846 |
var s = new Uint8Array([ |
| 8847 |
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, |
| 8848 |
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, |
| 8849 |
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, |
| 8850 |
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, |
| 8851 |
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, |
| 8852 |
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, |
| 8853 |
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, |
| 8854 |
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, |
| 8855 |
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, |
| 8856 |
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, |
| 8857 |
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, |
| 8858 |
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, |
| 8859 |
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, |
| 8860 |
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, |
| 8861 |
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, |
| 8862 |
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, |
| 8863 |
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, |
| 8864 |
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, |
| 8865 |
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, |
| 8866 |
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, |
| 8867 |
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, |
| 8868 |
0xb0, 0x54, 0xbb, 0x16]); |
| 8869 |
|
| 8870 |
var inv_s = new Uint8Array([ |
| 8871 |
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, |
| 8872 |
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, |
| 8873 |
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, |
| 8874 |
0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, |
| 8875 |
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, |
| 8876 |
0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, |
| 8877 |
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, |
| 8878 |
0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, |
| 8879 |
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, |
| 8880 |
0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, |
| 8881 |
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, |
| 8882 |
0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, |
| 8883 |
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, |
| 8884 |
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, |
| 8885 |
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, |
| 8886 |
0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, |
| 8887 |
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, |
| 8888 |
0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, |
| 8889 |
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, |
| 8890 |
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, |
| 8891 |
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, |
| 8892 |
0x55, 0x21, 0x0c, 0x7d]); |
| 8893 |
|
| 8894 |
var mixCol = new Uint8Array(256); |
| 8895 |
for (var i = 0; i < 256; i++) { |
| 8896 |
if (i < 128) { |
| 8897 |
mixCol[i] = i << 1; |
| 8898 |
} else { |
| 8899 |
mixCol[i] = (i << 1) ^ 0x1b; |
| 8900 |
} |
| 8901 |
} |
| 8902 |
var mix = new Uint32Array([ |
| 8903 |
0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, |
| 8904 |
0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, |
| 8905 |
0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, |
| 8906 |
0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, |
| 8907 |
0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, |
| 8908 |
0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, |
| 8909 |
0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, |
| 8910 |
0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, |
| 8911 |
0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, |
| 8912 |
0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, |
| 8913 |
0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, |
| 8914 |
0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, |
| 8915 |
0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, |
| 8916 |
0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, |
| 8917 |
0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, |
| 8918 |
0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, |
| 8919 |
0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, |
| 8920 |
0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, |
| 8921 |
0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, |
| 8922 |
0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, |
| 8923 |
0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, |
| 8924 |
0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, |
| 8925 |
0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, |
| 8926 |
0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, |
| 8927 |
0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, |
| 8928 |
0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, |
| 8929 |
0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, |
| 8930 |
0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, |
| 8931 |
0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, |
| 8932 |
0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, |
| 8933 |
0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, |
| 8934 |
0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, |
| 8935 |
0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, |
| 8936 |
0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, |
| 8937 |
0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, |
| 8938 |
0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, |
| 8939 |
0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, |
| 8940 |
0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, |
| 8941 |
0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, |
| 8942 |
0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, |
| 8943 |
0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, |
| 8944 |
0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, |
| 8945 |
0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); |
| 8946 |
|
| 8947 |
function expandKey256(cipherKey) { |
| 8948 |
var b = 240, result = new Uint8Array(b); |
| 8949 |
var r = 1; |
| 8950 |
|
| 8951 |
result.set(cipherKey); |
| 8952 |
for (var j = 32, i = 1; j < b; ++i) { |
| 8953 |
if (j % 32 === 16) { |
| 8954 |
t1 = s[t1]; |
| 8955 |
t2 = s[t2]; |
| 8956 |
t3 = s[t3]; |
| 8957 |
t4 = s[t4]; |
| 8958 |
} else if (j % 32 === 0) { |
| 8959 |
// RotWord |
| 8960 |
var t1 = result[j - 3], t2 = result[j - 2], |
| 8961 |
t3 = result[j - 1], t4 = result[j - 4]; |
| 8962 |
// SubWord |
| 8963 |
t1 = s[t1]; |
| 8964 |
t2 = s[t2]; |
| 8965 |
t3 = s[t3]; |
| 8966 |
t4 = s[t4]; |
| 8967 |
// Rcon |
| 8968 |
t1 = t1 ^ r; |
| 8969 |
if ((r <<= 1) >= 256) { |
| 8970 |
r = (r ^ 0x1b) & 0xFF; |
| 8971 |
} |
| 8972 |
} |
| 8973 |
|
| 8974 |
for (var n = 0; n < 4; ++n) { |
| 8975 |
result[j] = (t1 ^= result[j - 32]); |
| 8976 |
j++; |
| 8977 |
result[j] = (t2 ^= result[j - 32]); |
| 8978 |
j++; |
| 8979 |
result[j] = (t3 ^= result[j - 32]); |
| 8980 |
j++; |
| 8981 |
result[j] = (t4 ^= result[j - 32]); |
| 8982 |
j++; |
| 8983 |
} |
| 8984 |
} |
| 8985 |
return result; |
| 8986 |
} |
| 8987 |
|
| 8988 |
function decrypt256(input, key) { |
| 8989 |
var state = new Uint8Array(16); |
| 8990 |
state.set(input); |
| 8991 |
var i, j, k; |
| 8992 |
var t, u, v; |
| 8993 |
// AddRoundKey |
| 8994 |
for (j = 0, k = 224; j < 16; ++j, ++k) { |
| 8995 |
state[j] ^= key[k]; |
| 8996 |
} |
| 8997 |
for (i = 13; i >= 1; --i) { |
| 8998 |
// InvShiftRows |
| 8999 |
t = state[13]; |
| 9000 |
state[13] = state[9]; |
| 9001 |
state[9] = state[5]; |
| 9002 |
state[5] = state[1]; |
| 9003 |
state[1] = t; |
| 9004 |
t = state[14]; |
| 9005 |
u = state[10]; |
| 9006 |
state[14] = state[6]; |
| 9007 |
state[10] = state[2]; |
| 9008 |
state[6] = t; |
| 9009 |
state[2] = u; |
| 9010 |
t = state[15]; |
| 9011 |
u = state[11]; |
| 9012 |
v = state[7]; |
| 9013 |
state[15] = state[3]; |
| 9014 |
state[11] = t; |
| 9015 |
state[7] = u; |
| 9016 |
state[3] = v; |
| 9017 |
// InvSubBytes |
| 9018 |
for (j = 0; j < 16; ++j) { |
| 9019 |
state[j] = inv_s[state[j]]; |
| 9020 |
} |
| 9021 |
// AddRoundKey |
| 9022 |
for (j = 0, k = i * 16; j < 16; ++j, ++k) { |
| 9023 |
state[j] ^= key[k]; |
| 9024 |
} |
| 9025 |
// InvMixColumns |
| 9026 |
for (j = 0; j < 16; j += 4) { |
| 9027 |
var s0 = mix[state[j]], s1 = mix[state[j + 1]], |
| 9028 |
s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; |
| 9029 |
t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ |
| 9030 |
(s3 >>> 24) ^ (s3 << 8)); |
| 9031 |
state[j] = (t >>> 24) & 0xFF; |
| 9032 |
state[j + 1] = (t >> 16) & 0xFF; |
| 9033 |
state[j + 2] = (t >> 8) & 0xFF; |
| 9034 |
state[j + 3] = t & 0xFF; |
| 9035 |
} |
| 9036 |
} |
| 9037 |
// InvShiftRows |
| 9038 |
t = state[13]; |
| 9039 |
state[13] = state[9]; |
| 9040 |
state[9] = state[5]; |
| 9041 |
state[5] = state[1]; |
| 9042 |
state[1] = t; |
| 9043 |
t = state[14]; |
| 9044 |
u = state[10]; |
| 9045 |
state[14] = state[6]; |
| 9046 |
state[10] = state[2]; |
| 9047 |
state[6] = t; |
| 9048 |
state[2] = u; |
| 9049 |
t = state[15]; |
| 9050 |
u = state[11]; |
| 9051 |
v = state[7]; |
| 9052 |
state[15] = state[3]; |
| 9053 |
state[11] = t; |
| 9054 |
state[7] = u; |
| 9055 |
state[3] = v; |
| 9056 |
for (j = 0; j < 16; ++j) { |
| 9057 |
// InvSubBytes |
| 9058 |
state[j] = inv_s[state[j]]; |
| 9059 |
// AddRoundKey |
| 9060 |
state[j] ^= key[j]; |
| 9061 |
} |
| 9062 |
return state; |
| 9063 |
} |
| 9064 |
|
| 9065 |
function encrypt256(input, key) { |
| 9066 |
var t, u, v, k; |
| 9067 |
var state = new Uint8Array(16); |
| 9068 |
state.set(input); |
| 9069 |
for (j = 0; j < 16; ++j) { |
| 9070 |
// AddRoundKey |
| 9071 |
state[j] ^= key[j]; |
| 9072 |
} |
| 9073 |
|
| 9074 |
for (i = 1; i < 14; i++) { |
| 9075 |
//SubBytes |
| 9076 |
for (j = 0; j < 16; ++j) { |
| 9077 |
state[j] = s[state[j]]; |
| 9078 |
} |
| 9079 |
//ShiftRows |
| 9080 |
v = state[1]; |
| 9081 |
state[1] = state[5]; |
| 9082 |
state[5] = state[9]; |
| 9083 |
state[9] = state[13]; |
| 9084 |
state[13] = v; |
| 9085 |
v = state[2]; |
| 9086 |
u = state[6]; |
| 9087 |
state[2] = state[10]; |
| 9088 |
state[6] = state[14]; |
| 9089 |
state[10] = v; |
| 9090 |
state[14] = u; |
| 9091 |
v = state[3]; |
| 9092 |
u = state[7]; |
| 9093 |
t = state[11]; |
| 9094 |
state[3] = state[15]; |
| 9095 |
state[7] = v; |
| 9096 |
state[11] = u; |
| 9097 |
state[15] = t; |
| 9098 |
//MixColumns |
| 9099 |
for (var j = 0; j < 16; j += 4) { |
| 9100 |
var s0 = state[j + 0], s1 = state[j + 1]; |
| 9101 |
var s2 = state[j + 2], s3 = state[j + 3]; |
| 9102 |
t = s0 ^ s1 ^ s2 ^ s3; |
| 9103 |
state[j + 0] ^= t ^ mixCol[s0 ^ s1]; |
| 9104 |
state[j + 1] ^= t ^ mixCol[s1 ^ s2]; |
| 9105 |
state[j + 2] ^= t ^ mixCol[s2 ^ s3]; |
| 9106 |
state[j + 3] ^= t ^ mixCol[s3 ^ s0]; |
| 9107 |
} |
| 9108 |
//AddRoundKey |
| 9109 |
for (j = 0, k = i * 16; j < 16; ++j, ++k) { |
| 9110 |
state[j] ^= key[k]; |
| 9111 |
} |
| 9112 |
} |
| 9113 |
|
| 9114 |
//SubBytes |
| 9115 |
for (j = 0; j < 16; ++j) { |
| 9116 |
state[j] = s[state[j]]; |
| 9117 |
} |
| 9118 |
//ShiftRows |
| 9119 |
v = state[1]; |
| 9120 |
state[1] = state[5]; |
| 9121 |
state[5] = state[9]; |
| 9122 |
state[9] = state[13]; |
| 9123 |
state[13] = v; |
| 9124 |
v = state[2]; |
| 9125 |
u = state[6]; |
| 9126 |
state[2] = state[10]; |
| 9127 |
state[6] = state[14]; |
| 9128 |
state[10] = v; |
| 9129 |
state[14] = u; |
| 9130 |
v = state[3]; |
| 9131 |
u = state[7]; |
| 9132 |
t = state[11]; |
| 9133 |
state[3] = state[15]; |
| 9134 |
state[7] = v; |
| 9135 |
state[11] = u; |
| 9136 |
state[15] = t; |
| 9137 |
//AddRoundKey |
| 9138 |
for (j = 0, k = 224; j < 16; ++j, ++k) { |
| 9139 |
state[j] ^= key[k]; |
| 9140 |
} |
| 9141 |
|
| 9142 |
return state; |
| 9143 |
|
| 9144 |
} |
| 9145 |
|
| 9146 |
function AES256Cipher(key) { |
| 9147 |
this.key = expandKey256(key); |
| 9148 |
this.buffer = new Uint8Array(16); |
| 9149 |
this.bufferPosition = 0; |
| 9150 |
} |
| 9151 |
|
| 9152 |
function decryptBlock2(data, finalize) { |
| 9153 |
var i, j, ii, sourceLength = data.length, |
| 9154 |
buffer = this.buffer, bufferLength = this.bufferPosition, |
| 9155 |
result = [], iv = this.iv; |
| 9156 |
|
| 9157 |
for (i = 0; i < sourceLength; ++i) { |
| 9158 |
buffer[bufferLength] = data[i]; |
| 9159 |
++bufferLength; |
| 9160 |
if (bufferLength < 16) { |
| 9161 |
continue; |
| 9162 |
} |
| 9163 |
// buffer is full, decrypting |
| 9164 |
var plain = decrypt256(buffer, this.key); |
| 9165 |
// xor-ing the IV vector to get plain text |
| 9166 |
for (j = 0; j < 16; ++j) { |
| 9167 |
plain[j] ^= iv[j]; |
| 9168 |
} |
| 9169 |
iv = buffer; |
| 9170 |
result.push(plain); |
| 9171 |
buffer = new Uint8Array(16); |
| 9172 |
bufferLength = 0; |
| 9173 |
} |
| 9174 |
// saving incomplete buffer |
| 9175 |
this.buffer = buffer; |
| 9176 |
this.bufferLength = bufferLength; |
| 9177 |
this.iv = iv; |
| 9178 |
if (result.length === 0) { |
| 9179 |
return new Uint8Array([]); |
| 9180 |
} |
| 9181 |
// combining plain text blocks into one |
| 9182 |
var outputLength = 16 * result.length; |
| 9183 |
if (finalize) { |
| 9184 |
// undo a padding that is described in RFC 2898 |
| 9185 |
var lastBlock = result[result.length - 1]; |
| 9186 |
var psLen = lastBlock[15]; |
| 9187 |
if (psLen <= 16) { |
| 9188 |
for (i = 15, ii = 16 - psLen; i >= ii; --i) { |
| 9189 |
if (lastBlock[i] !== psLen) { |
| 9190 |
// Invalid padding, assume that the block has no padding. |
| 9191 |
psLen = 0; |
| 9192 |
break; |
| 9193 |
} |
| 9194 |
} |
| 9195 |
outputLength -= psLen; |
| 9196 |
result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); |
| 9197 |
} |
| 9198 |
} |
| 9199 |
var output = new Uint8Array(outputLength); |
| 9200 |
for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { |
| 9201 |
output.set(result[i], j); |
| 9202 |
} |
| 9203 |
return output; |
| 9204 |
|
| 9205 |
} |
| 9206 |
|
| 9207 |
AES256Cipher.prototype = { |
| 9208 |
decryptBlock: function AES256Cipher_decryptBlock(data, finalize, iv) { |
| 9209 |
var i, sourceLength = data.length; |
| 9210 |
var buffer = this.buffer, bufferLength = this.bufferPosition; |
| 9211 |
// if not supplied an IV wait for IV values |
| 9212 |
// they are at the start of the stream |
| 9213 |
if (iv) { |
| 9214 |
this.iv = iv; |
| 9215 |
} else { |
| 9216 |
for (i = 0; bufferLength < 16 && |
| 9217 |
i < sourceLength; ++i, ++bufferLength) { |
| 9218 |
buffer[bufferLength] = data[i]; |
| 9219 |
} |
| 9220 |
if (bufferLength < 16) { |
| 9221 |
//need more data |
| 9222 |
this.bufferLength = bufferLength; |
| 9223 |
return new Uint8Array([]); |
| 9224 |
} |
| 9225 |
this.iv = buffer; |
| 9226 |
data = data.subarray(16); |
| 9227 |
} |
| 9228 |
this.buffer = new Uint8Array(16); |
| 9229 |
this.bufferLength = 0; |
| 9230 |
// starting decryption |
| 9231 |
this.decryptBlock = decryptBlock2; |
| 9232 |
return this.decryptBlock(data, finalize); |
| 9233 |
}, |
| 9234 |
encrypt: function AES256Cipher_encrypt(data, iv) { |
| 9235 |
var i, j, ii, sourceLength = data.length, |
| 9236 |
buffer = this.buffer, bufferLength = this.bufferPosition, |
| 9237 |
result = []; |
| 9238 |
if (!iv) { |
| 9239 |
iv = new Uint8Array(16); |
| 9240 |
} |
| 9241 |
for (i = 0; i < sourceLength; ++i) { |
| 9242 |
buffer[bufferLength] = data[i]; |
| 9243 |
++bufferLength; |
| 9244 |
if (bufferLength < 16) { |
| 9245 |
continue; |
| 9246 |
} |
| 9247 |
for (j = 0; j < 16; ++j) { |
| 9248 |
buffer[j] ^= iv[j]; |
| 9249 |
} |
| 9250 |
|
| 9251 |
// buffer is full, encrypting |
| 9252 |
var cipher = encrypt256(buffer, this.key); |
| 9253 |
this.iv = cipher; |
| 9254 |
result.push(cipher); |
| 9255 |
buffer = new Uint8Array(16); |
| 9256 |
bufferLength = 0; |
| 9257 |
} |
| 9258 |
// saving incomplete buffer |
| 9259 |
this.buffer = buffer; |
| 9260 |
this.bufferLength = bufferLength; |
| 9261 |
this.iv = iv; |
| 9262 |
if (result.length === 0) { |
| 9263 |
return new Uint8Array([]); |
| 9264 |
} |
| 9265 |
// combining plain text blocks into one |
| 9266 |
var outputLength = 16 * result.length; |
| 9267 |
var output = new Uint8Array(outputLength); |
| 9268 |
for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { |
| 9269 |
output.set(result[i], j); |
| 9270 |
} |
| 9271 |
return output; |
| 9272 |
} |
| 9273 |
}; |
| 9274 |
|
| 9275 |
return AES256Cipher; |
| 9276 |
})(); |
| 9277 |
|
| 9278 |
var PDF17 = (function PDF17Closure() { |
| 9279 |
|
| 9280 |
function compareByteArrays(array1, array2) { |
| 9281 |
if (array1.length !== array2.length) { |
| 9282 |
return false; |
| 9283 |
} |
| 9284 |
for (var i = 0; i < array1.length; i++) { |
| 9285 |
if (array1[i] !== array2[i]) { |
| 9286 |
return false; |
| 9287 |
} |
| 9288 |
} |
| 9289 |
return true; |
| 9290 |
} |
| 9291 |
|
| 9292 |
function PDF17() { |
| 9293 |
} |
| 9294 |
|
| 9295 |
PDF17.prototype = { |
| 9296 |
checkOwnerPassword: function PDF17_checkOwnerPassword(password, |
| 9297 |
ownerValidationSalt, |
| 9298 |
userBytes, |
| 9299 |
ownerPassword) { |
| 9300 |
var hashData = new Uint8Array(password.length + 56); |
| 9301 |
hashData.set(password, 0); |
| 9302 |
hashData.set(ownerValidationSalt, password.length); |
| 9303 |
hashData.set(userBytes, password.length + ownerValidationSalt.length); |
| 9304 |
var result = calculateSHA256(hashData, 0, hashData.length); |
| 9305 |
return compareByteArrays(result, ownerPassword); |
| 9306 |
}, |
| 9307 |
checkUserPassword: function PDF17_checkUserPassword(password, |
| 9308 |
userValidationSalt, |
| 9309 |
userPassword) { |
| 9310 |
var hashData = new Uint8Array(password.length + 8); |
| 9311 |
hashData.set(password, 0); |
| 9312 |
hashData.set(userValidationSalt, password.length); |
| 9313 |
var result = calculateSHA256(hashData, 0, hashData.length); |
| 9314 |
return compareByteArrays(result, userPassword); |
| 9315 |
}, |
| 9316 |
getOwnerKey: function PDF17_getOwnerKey(password, ownerKeySalt, userBytes, |
| 9317 |
ownerEncryption) { |
| 9318 |
var hashData = new Uint8Array(password.length + 56); |
| 9319 |
hashData.set(password, 0); |
| 9320 |
hashData.set(ownerKeySalt, password.length); |
| 9321 |
hashData.set(userBytes, password.length + ownerKeySalt.length); |
| 9322 |
var key = calculateSHA256(hashData, 0, hashData.length); |
| 9323 |
var cipher = new AES256Cipher(key); |
| 9324 |
return cipher.decryptBlock(ownerEncryption, |
| 9325 |
false, |
| 9326 |
new Uint8Array(16)); |
| 9327 |
|
| 9328 |
}, |
| 9329 |
getUserKey: function PDF17_getUserKey(password, userKeySalt, |
| 9330 |
userEncryption) { |
| 9331 |
var hashData = new Uint8Array(password.length + 8); |
| 9332 |
hashData.set(password, 0); |
| 9333 |
hashData.set(userKeySalt, password.length); |
| 9334 |
//key is the decryption key for the UE string |
| 9335 |
var key = calculateSHA256(hashData, 0, hashData.length); |
| 9336 |
var cipher = new AES256Cipher(key); |
| 9337 |
return cipher.decryptBlock(userEncryption, |
| 9338 |
false, |
| 9339 |
new Uint8Array(16)); |
| 9340 |
} |
| 9341 |
}; |
| 9342 |
return PDF17; |
| 9343 |
})(); |
| 9344 |
|
| 9345 |
var PDF20 = (function PDF20Closure() { |
| 9346 |
|
| 9347 |
function concatArrays(array1, array2) { |
| 9348 |
var t = new Uint8Array(array1.length + array2.length); |
| 9349 |
t.set(array1, 0); |
| 9350 |
t.set(array2, array1.length); |
| 9351 |
return t; |
| 9352 |
} |
| 9353 |
|
| 9354 |
function calculatePDF20Hash(password, input, userBytes) { |
| 9355 |
//This refers to Algorithm 2.B as defined in ISO 32000-2 |
| 9356 |
var k = calculateSHA256(input, 0, input.length).subarray(0, 32); |
| 9357 |
var e = [0]; |
| 9358 |
var i = 0; |
| 9359 |
while (i < 64 || e[e.length - 1] > i - 32) { |
| 9360 |
var arrayLength = password.length + k.length + userBytes.length; |
| 9361 |
|
| 9362 |
var k1 = new Uint8Array(arrayLength * 64); |
| 9363 |
var array = concatArrays(password, k); |
| 9364 |
array = concatArrays(array, userBytes); |
| 9365 |
for (var j = 0, pos = 0; j < 64; j++, pos += arrayLength) { |
| 9366 |
k1.set(array, pos); |
| 9367 |
} |
| 9368 |
//AES128 CBC NO PADDING with |
| 9369 |
//first 16 bytes of k as the key and the second 16 as the iv. |
| 9370 |
var cipher = new AES128Cipher(k.subarray(0, 16)); |
| 9371 |
e = cipher.encrypt(k1, k.subarray(16, 32)); |
| 9372 |
//Now we have to take the first 16 bytes of an unsigned |
| 9373 |
//big endian integer... and compute the remainder |
| 9374 |
//modulo 3.... That is a fairly large number and |
| 9375 |
//JavaScript isn't going to handle that well... |
| 9376 |
//So we're using a trick that allows us to perform |
| 9377 |
//modulo math byte by byte |
| 9378 |
var remainder = 0; |
| 9379 |
for (var z = 0; z < 16; z++) { |
| 9380 |
remainder *= (256 % 3); |
| 9381 |
remainder %= 3; |
| 9382 |
remainder += ((e[z] >>> 0) % 3); |
| 9383 |
remainder %= 3; |
| 9384 |
} |
| 9385 |
if (remainder === 0) { |
| 9386 |
k = calculateSHA256(e, 0, e.length); |
| 9387 |
} |
| 9388 |
else if (remainder === 1) { |
| 9389 |
k = calculateSHA384(e, 0, e.length); |
| 9390 |
} |
| 9391 |
else if (remainder === 2) { |
| 9392 |
k = calculateSHA512(e, 0, e.length); |
| 9393 |
} |
| 9394 |
i++; |
| 9395 |
} |
| 9396 |
return k.subarray(0, 32); |
| 9397 |
} |
| 9398 |
|
| 9399 |
function PDF20() { |
| 9400 |
} |
| 9401 |
|
| 9402 |
function compareByteArrays(array1, array2) { |
| 9403 |
if (array1.length !== array2.length) { |
| 9404 |
return false; |
| 9405 |
} |
| 9406 |
for (var i = 0; i < array1.length; i++) { |
| 9407 |
if (array1[i] !== array2[i]) { |
| 9408 |
return false; |
| 9409 |
} |
| 9410 |
} |
| 9411 |
return true; |
| 9412 |
} |
| 9413 |
|
| 9414 |
PDF20.prototype = { |
| 9415 |
hash: function PDF20_hash(password, concatBytes, userBytes) { |
| 9416 |
return calculatePDF20Hash(password, concatBytes, userBytes); |
| 9417 |
}, |
| 9418 |
checkOwnerPassword: function PDF20_checkOwnerPassword(password, |
| 9419 |
ownerValidationSalt, |
| 9420 |
userBytes, |
| 9421 |
ownerPassword) { |
| 9422 |
var hashData = new Uint8Array(password.length + 56); |
| 9423 |
hashData.set(password, 0); |
| 9424 |
hashData.set(ownerValidationSalt, password.length); |
| 9425 |
hashData.set(userBytes, password.length + ownerValidationSalt.length); |
| 9426 |
var result = calculatePDF20Hash(password, hashData, userBytes); |
| 9427 |
return compareByteArrays(result, ownerPassword); |
| 9428 |
}, |
| 9429 |
checkUserPassword: function PDF20_checkUserPassword(password, |
| 9430 |
userValidationSalt, |
| 9431 |
userPassword) { |
| 9432 |
var hashData = new Uint8Array(password.length + 8); |
| 9433 |
hashData.set(password, 0); |
| 9434 |
hashData.set(userValidationSalt, password.length); |
| 9435 |
var result = calculatePDF20Hash(password, hashData, []); |
| 9436 |
return compareByteArrays(result, userPassword); |
| 9437 |
}, |
| 9438 |
getOwnerKey: function PDF20_getOwnerKey(password, ownerKeySalt, userBytes, |
| 9439 |
ownerEncryption) { |
| 9440 |
var hashData = new Uint8Array(password.length + 56); |
| 9441 |
hashData.set(password, 0); |
| 9442 |
hashData.set(ownerKeySalt, password.length); |
| 9443 |
hashData.set(userBytes, password.length + ownerKeySalt.length); |
| 9444 |
var key = calculatePDF20Hash(password, hashData, userBytes); |
| 9445 |
var cipher = new AES256Cipher(key); |
| 9446 |
return cipher.decryptBlock(ownerEncryption, |
| 9447 |
false, |
| 9448 |
new Uint8Array(16)); |
| 9449 |
|
| 9450 |
}, |
| 9451 |
getUserKey: function PDF20_getUserKey(password, userKeySalt, |
| 9452 |
userEncryption) { |
| 9453 |
var hashData = new Uint8Array(password.length + 8); |
| 9454 |
hashData.set(password, 0); |
| 9455 |
hashData.set(userKeySalt, password.length); |
| 9456 |
//key is the decryption key for the UE string |
| 9457 |
var key = calculatePDF20Hash(password, hashData, []); |
| 9458 |
var cipher = new AES256Cipher(key); |
| 9459 |
return cipher.decryptBlock(userEncryption, |
| 9460 |
false, |
| 9461 |
new Uint8Array(16)); |
| 9462 |
} |
| 9463 |
}; |
| 9464 |
return PDF20; |
| 9465 |
})(); |
| 9466 |
|
| 9467 |
var CipherTransform = (function CipherTransformClosure() { |
| 9468 |
function CipherTransform(stringCipherConstructor, streamCipherConstructor) { |
| 9469 |
this.stringCipherConstructor = stringCipherConstructor; |
| 9470 |
this.streamCipherConstructor = streamCipherConstructor; |
| 9471 |
} |
| 9472 |
|
| 9473 |
CipherTransform.prototype = { |
| 9474 |
createStream: function CipherTransform_createStream(stream, length) { |
| 9475 |
var cipher = new this.streamCipherConstructor(); |
| 9476 |
return new DecryptStream(stream, length, |
| 9477 |
function cipherTransformDecryptStream(data, finalize) { |
| 9478 |
return cipher.decryptBlock(data, finalize); |
| 9479 |
} |
| 9480 |
); |
| 9481 |
}, |
| 9482 |
decryptString: function CipherTransform_decryptString(s) { |
| 9483 |
var cipher = new this.stringCipherConstructor(); |
| 9484 |
var data = stringToBytes(s); |
| 9485 |
data = cipher.decryptBlock(data, true); |
| 9486 |
return bytesToString(data); |
| 9487 |
} |
| 9488 |
}; |
| 9489 |
return CipherTransform; |
| 9490 |
})(); |
| 9491 |
|
| 9492 |
var CipherTransformFactory = (function CipherTransformFactoryClosure() { |
| 9493 |
var defaultPasswordBytes = new Uint8Array([ |
| 9494 |
0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, |
| 9495 |
0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, |
| 9496 |
0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, |
| 9497 |
0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]); |
| 9498 |
|
| 9499 |
function createEncryptionKey20(revision, password, ownerPassword, |
| 9500 |
ownerValidationSalt, ownerKeySalt, uBytes, |
| 9501 |
userPassword, userValidationSalt, userKeySalt, |
| 9502 |
ownerEncryption, userEncryption, perms) { |
| 9503 |
if (password) { |
| 9504 |
var passwordLength = Math.min(127, password.length); |
| 9505 |
password = password.subarray(0, passwordLength); |
| 9506 |
} else { |
| 9507 |
password = []; |
| 9508 |
} |
| 9509 |
var pdfAlgorithm; |
| 9510 |
if (revision === 6) { |
| 9511 |
pdfAlgorithm = new PDF20(); |
| 9512 |
} else { |
| 9513 |
pdfAlgorithm = new PDF17(); |
| 9514 |
} |
| 9515 |
|
| 9516 |
if (pdfAlgorithm) { |
| 9517 |
if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, |
| 9518 |
userPassword)) { |
| 9519 |
return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption); |
| 9520 |
} else if (pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, |
| 9521 |
uBytes, |
| 9522 |
ownerPassword)) { |
| 9523 |
return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, |
| 9524 |
ownerEncryption); |
| 9525 |
} |
| 9526 |
} |
| 9527 |
|
| 9528 |
return null; |
| 9529 |
} |
| 9530 |
|
| 9531 |
function prepareKeyData(fileId, password, ownerPassword, userPassword, |
| 9532 |
flags, revision, keyLength, encryptMetadata) { |
| 9533 |
var hashDataSize = 40 + ownerPassword.length + fileId.length; |
| 9534 |
var hashData = new Uint8Array(hashDataSize), i = 0, j, n; |
| 9535 |
if (password) { |
| 9536 |
n = Math.min(32, password.length); |
| 9537 |
for (; i < n; ++i) { |
| 9538 |
hashData[i] = password[i]; |
| 9539 |
} |
| 9540 |
} |
| 9541 |
j = 0; |
| 9542 |
while (i < 32) { |
| 9543 |
hashData[i++] = defaultPasswordBytes[j++]; |
| 9544 |
} |
| 9545 |
// as now the padded password in the hashData[0..i] |
| 9546 |
for (j = 0, n = ownerPassword.length; j < n; ++j) { |
| 9547 |
hashData[i++] = ownerPassword[j]; |
| 9548 |
} |
| 9549 |
hashData[i++] = flags & 0xFF; |
| 9550 |
hashData[i++] = (flags >> 8) & 0xFF; |
| 9551 |
hashData[i++] = (flags >> 16) & 0xFF; |
| 9552 |
hashData[i++] = (flags >>> 24) & 0xFF; |
| 9553 |
for (j = 0, n = fileId.length; j < n; ++j) { |
| 9554 |
hashData[i++] = fileId[j]; |
| 9555 |
} |
| 9556 |
if (revision >= 4 && !encryptMetadata) { |
| 9557 |
hashData[i++] = 0xFF; |
| 9558 |
hashData[i++] = 0xFF; |
| 9559 |
hashData[i++] = 0xFF; |
| 9560 |
hashData[i++] = 0xFF; |
| 9561 |
} |
| 9562 |
var hash = calculateMD5(hashData, 0, i); |
| 9563 |
var keyLengthInBytes = keyLength >> 3; |
| 9564 |
if (revision >= 3) { |
| 9565 |
for (j = 0; j < 50; ++j) { |
| 9566 |
hash = calculateMD5(hash, 0, keyLengthInBytes); |
| 9567 |
} |
| 9568 |
} |
| 9569 |
var encryptionKey = hash.subarray(0, keyLengthInBytes); |
| 9570 |
var cipher, checkData; |
| 9571 |
|
| 9572 |
if (revision >= 3) { |
| 9573 |
for (i = 0; i < 32; ++i) { |
| 9574 |
hashData[i] = defaultPasswordBytes[i]; |
| 9575 |
} |
| 9576 |
for (j = 0, n = fileId.length; j < n; ++j) { |
| 9577 |
hashData[i++] = fileId[j]; |
| 9578 |
} |
| 9579 |
cipher = new ARCFourCipher(encryptionKey); |
| 9580 |
checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); |
| 9581 |
n = encryptionKey.length; |
| 9582 |
var derivedKey = new Uint8Array(n), k; |
| 9583 |
for (j = 1; j <= 19; ++j) { |
| 9584 |
for (k = 0; k < n; ++k) { |
| 9585 |
derivedKey[k] = encryptionKey[k] ^ j; |
| 9586 |
} |
| 9587 |
cipher = new ARCFourCipher(derivedKey); |
| 9588 |
checkData = cipher.encryptBlock(checkData); |
| 9589 |
} |
| 9590 |
for (j = 0, n = checkData.length; j < n; ++j) { |
| 9591 |
if (userPassword[j] !== checkData[j]) { |
| 9592 |
return null; |
| 9593 |
} |
| 9594 |
} |
| 9595 |
} else { |
| 9596 |
cipher = new ARCFourCipher(encryptionKey); |
| 9597 |
checkData = cipher.encryptBlock(defaultPasswordBytes); |
| 9598 |
for (j = 0, n = checkData.length; j < n; ++j) { |
| 9599 |
if (userPassword[j] !== checkData[j]) { |
| 9600 |
return null; |
| 9601 |
} |
| 9602 |
} |
| 9603 |
} |
| 9604 |
return encryptionKey; |
| 9605 |
} |
| 9606 |
|
| 9607 |
function decodeUserPassword(password, ownerPassword, revision, keyLength) { |
| 9608 |
var hashData = new Uint8Array(32), i = 0, j, n; |
| 9609 |
n = Math.min(32, password.length); |
| 9610 |
for (; i < n; ++i) { |
| 9611 |
hashData[i] = password[i]; |
| 9612 |
} |
| 9613 |
j = 0; |
| 9614 |
while (i < 32) { |
| 9615 |
hashData[i++] = defaultPasswordBytes[j++]; |
| 9616 |
} |
| 9617 |
var hash = calculateMD5(hashData, 0, i); |
| 9618 |
var keyLengthInBytes = keyLength >> 3; |
| 9619 |
if (revision >= 3) { |
| 9620 |
for (j = 0; j < 50; ++j) { |
| 9621 |
hash = calculateMD5(hash, 0, hash.length); |
| 9622 |
} |
| 9623 |
} |
| 9624 |
|
| 9625 |
var cipher, userPassword; |
| 9626 |
if (revision >= 3) { |
| 9627 |
userPassword = ownerPassword; |
| 9628 |
var derivedKey = new Uint8Array(keyLengthInBytes), k; |
| 9629 |
for (j = 19; j >= 0; j--) { |
| 9630 |
for (k = 0; k < keyLengthInBytes; ++k) { |
| 9631 |
derivedKey[k] = hash[k] ^ j; |
| 9632 |
} |
| 9633 |
cipher = new ARCFourCipher(derivedKey); |
| 9634 |
userPassword = cipher.encryptBlock(userPassword); |
| 9635 |
} |
| 9636 |
} else { |
| 9637 |
cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes)); |
| 9638 |
userPassword = cipher.encryptBlock(ownerPassword); |
| 9639 |
} |
| 9640 |
return userPassword; |
| 9641 |
} |
| 9642 |
|
| 9643 |
var identityName = Name.get('Identity'); |
| 9644 |
|
| 9645 |
function CipherTransformFactory(dict, fileId, password) { |
| 9646 |
var filter = dict.get('Filter'); |
| 9647 |
if (!isName(filter) || filter.name !== 'Standard') { |
| 9648 |
error('unknown encryption method'); |
| 9649 |
} |
| 9650 |
this.dict = dict; |
| 9651 |
var algorithm = dict.get('V'); |
| 9652 |
if (!isInt(algorithm) || |
| 9653 |
(algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && |
| 9654 |
algorithm !== 5)) { |
| 9655 |
error('unsupported encryption algorithm'); |
| 9656 |
} |
| 9657 |
this.algorithm = algorithm; |
| 9658 |
var keyLength = dict.get('Length') || 40; |
| 9659 |
if (!isInt(keyLength) || |
| 9660 |
keyLength < 40 || (keyLength % 8) !== 0) { |
| 9661 |
error('invalid key length'); |
| 9662 |
} |
| 9663 |
|
| 9664 |
// prepare keys |
| 9665 |
var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32); |
| 9666 |
var userPassword = stringToBytes(dict.get('U')).subarray(0, 32); |
| 9667 |
var flags = dict.get('P'); |
| 9668 |
var revision = dict.get('R'); |
| 9669 |
// meaningful when V is 4 or 5 |
| 9670 |
var encryptMetadata = ((algorithm === 4 || algorithm === 5) && |
| 9671 |
dict.get('EncryptMetadata') !== false); |
| 9672 |
this.encryptMetadata = encryptMetadata; |
| 9673 |
|
| 9674 |
var fileIdBytes = stringToBytes(fileId); |
| 9675 |
var passwordBytes; |
| 9676 |
if (password) { |
| 9677 |
passwordBytes = stringToBytes(password); |
| 9678 |
} |
| 9679 |
|
| 9680 |
var encryptionKey; |
| 9681 |
if (algorithm !== 5) { |
| 9682 |
encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, |
| 9683 |
ownerPassword, userPassword, flags, |
| 9684 |
revision, keyLength, encryptMetadata); |
| 9685 |
} |
| 9686 |
else { |
| 9687 |
var ownerValidationSalt = stringToBytes(dict.get('O')).subarray(32, 40); |
| 9688 |
var ownerKeySalt = stringToBytes(dict.get('O')).subarray(40, 48); |
| 9689 |
var uBytes = stringToBytes(dict.get('U')).subarray(0, 48); |
| 9690 |
var userValidationSalt = stringToBytes(dict.get('U')).subarray(32, 40); |
| 9691 |
var userKeySalt = stringToBytes(dict.get('U')).subarray(40, 48); |
| 9692 |
var ownerEncryption = stringToBytes(dict.get('OE')); |
| 9693 |
var userEncryption = stringToBytes(dict.get('UE')); |
| 9694 |
var perms = stringToBytes(dict.get('Perms')); |
| 9695 |
encryptionKey = |
| 9696 |
createEncryptionKey20(revision, passwordBytes, |
| 9697 |
ownerPassword, ownerValidationSalt, |
| 9698 |
ownerKeySalt, uBytes, |
| 9699 |
userPassword, userValidationSalt, |
| 9700 |
userKeySalt, ownerEncryption, |
| 9701 |
userEncryption, perms); |
| 9702 |
} |
| 9703 |
if (!encryptionKey && !password) { |
| 9704 |
throw new PasswordException('No password given', |
| 9705 |
PasswordResponses.NEED_PASSWORD); |
| 9706 |
} else if (!encryptionKey && password) { |
| 9707 |
// Attempting use the password as an owner password |
| 9708 |
var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, |
| 9709 |
revision, keyLength); |
| 9710 |
encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, |
| 9711 |
ownerPassword, userPassword, flags, |
| 9712 |
revision, keyLength, encryptMetadata); |
| 9713 |
} |
| 9714 |
|
| 9715 |
if (!encryptionKey) { |
| 9716 |
throw new PasswordException('Incorrect Password', |
| 9717 |
PasswordResponses.INCORRECT_PASSWORD); |
| 9718 |
} |
| 9719 |
|
| 9720 |
this.encryptionKey = encryptionKey; |
| 9721 |
|
| 9722 |
if (algorithm >= 4) { |
| 9723 |
this.cf = dict.get('CF'); |
| 9724 |
this.stmf = dict.get('StmF') || identityName; |
| 9725 |
this.strf = dict.get('StrF') || identityName; |
| 9726 |
this.eff = dict.get('EFF') || this.stmf; |
| 9727 |
} |
| 9728 |
} |
| 9729 |
|
| 9730 |
function buildObjectKey(num, gen, encryptionKey, isAes) { |
| 9731 |
var key = new Uint8Array(encryptionKey.length + 9), i, n; |
| 9732 |
for (i = 0, n = encryptionKey.length; i < n; ++i) { |
| 9733 |
key[i] = encryptionKey[i]; |
| 9734 |
} |
| 9735 |
key[i++] = num & 0xFF; |
| 9736 |
key[i++] = (num >> 8) & 0xFF; |
| 9737 |
key[i++] = (num >> 16) & 0xFF; |
| 9738 |
key[i++] = gen & 0xFF; |
| 9739 |
key[i++] = (gen >> 8) & 0xFF; |
| 9740 |
if (isAes) { |
| 9741 |
key[i++] = 0x73; |
| 9742 |
key[i++] = 0x41; |
| 9743 |
key[i++] = 0x6C; |
| 9744 |
key[i++] = 0x54; |
| 9745 |
} |
| 9746 |
var hash = calculateMD5(key, 0, i); |
| 9747 |
return hash.subarray(0, Math.min(encryptionKey.length + 5, 16)); |
| 9748 |
} |
| 9749 |
|
| 9750 |
function buildCipherConstructor(cf, name, num, gen, key) { |
| 9751 |
var cryptFilter = cf.get(name.name); |
| 9752 |
var cfm; |
| 9753 |
if (cryptFilter !== null && cryptFilter !== undefined) { |
| 9754 |
cfm = cryptFilter.get('CFM'); |
| 9755 |
} |
| 9756 |
if (!cfm || cfm.name === 'None') { |
| 9757 |
return function cipherTransformFactoryBuildCipherConstructorNone() { |
| 9758 |
return new NullCipher(); |
| 9759 |
}; |
| 9760 |
} |
| 9761 |
if ('V2' === cfm.name) { |
| 9762 |
return function cipherTransformFactoryBuildCipherConstructorV2() { |
| 9763 |
return new ARCFourCipher(buildObjectKey(num, gen, key, false)); |
| 9764 |
}; |
| 9765 |
} |
| 9766 |
if ('AESV2' === cfm.name) { |
| 9767 |
return function cipherTransformFactoryBuildCipherConstructorAESV2() { |
| 9768 |
return new AES128Cipher(buildObjectKey(num, gen, key, true)); |
| 9769 |
}; |
| 9770 |
} |
| 9771 |
if ('AESV3' === cfm.name) { |
| 9772 |
return function cipherTransformFactoryBuildCipherConstructorAESV3() { |
| 9773 |
return new AES256Cipher(key); |
| 9774 |
}; |
| 9775 |
} |
| 9776 |
error('Unknown crypto method'); |
| 9777 |
} |
| 9778 |
|
| 9779 |
CipherTransformFactory.prototype = { |
| 9780 |
createCipherTransform: |
| 9781 |
function CipherTransformFactory_createCipherTransform(num, gen) { |
| 9782 |
if (this.algorithm === 4 || this.algorithm === 5) { |
| 9783 |
return new CipherTransform( |
| 9784 |
buildCipherConstructor(this.cf, this.stmf, |
| 9785 |
num, gen, this.encryptionKey), |
| 9786 |
buildCipherConstructor(this.cf, this.strf, |
| 9787 |
num, gen, this.encryptionKey)); |
| 9788 |
} |
| 9789 |
// algorithms 1 and 2 |
| 9790 |
var key = buildObjectKey(num, gen, this.encryptionKey, false); |
| 9791 |
var cipherConstructor = function buildCipherCipherConstructor() { |
| 9792 |
return new ARCFourCipher(key); |
| 9793 |
}; |
| 9794 |
return new CipherTransform(cipherConstructor, cipherConstructor); |
| 9795 |
} |
| 9796 |
}; |
| 9797 |
|
| 9798 |
return CipherTransformFactory; |
| 9799 |
})(); |
| 9800 |
|
| 9801 |
|
| 9802 |
var PatternType = { |
| 9803 |
FUNCTION_BASED: 1, |
| 9804 |
AXIAL: 2, |
| 9805 |
RADIAL: 3, |
| 9806 |
FREE_FORM_MESH: 4, |
| 9807 |
LATTICE_FORM_MESH: 5, |
| 9808 |
COONS_PATCH_MESH: 6, |
| 9809 |
TENSOR_PATCH_MESH: 7 |
| 9810 |
}; |
| 9811 |
|
| 9812 |
var Pattern = (function PatternClosure() { |
| 9813 |
// Constructor should define this.getPattern |
| 9814 |
function Pattern() { |
| 9815 |
error('should not call Pattern constructor'); |
| 9816 |
} |
| 9817 |
|
| 9818 |
Pattern.prototype = { |
| 9819 |
// Input: current Canvas context |
| 9820 |
// Output: the appropriate fillStyle or strokeStyle |
| 9821 |
getPattern: function Pattern_getPattern(ctx) { |
| 9822 |
error('Should not call Pattern.getStyle: ' + ctx); |
| 9823 |
} |
| 9824 |
}; |
| 9825 |
|
| 9826 |
Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, |
| 9827 |
res) { |
| 9828 |
|
| 9829 |
var dict = isStream(shading) ? shading.dict : shading; |
| 9830 |
var type = dict.get('ShadingType'); |
| 9831 |
|
| 9832 |
try { |
| 9833 |
switch (type) { |
| 9834 |
case PatternType.AXIAL: |
| 9835 |
case PatternType.RADIAL: |
| 9836 |
// Both radial and axial shadings are handled by RadialAxial shading. |
| 9837 |
return new Shadings.RadialAxial(dict, matrix, xref, res); |
| 9838 |
case PatternType.FREE_FORM_MESH: |
| 9839 |
case PatternType.LATTICE_FORM_MESH: |
| 9840 |
case PatternType.COONS_PATCH_MESH: |
| 9841 |
case PatternType.TENSOR_PATCH_MESH: |
| 9842 |
return new Shadings.Mesh(shading, matrix, xref, res); |
| 9843 |
default: |
| 9844 |
throw new Error('Unknown PatternType: ' + type); |
| 9845 |
} |
| 9846 |
} catch (ex) { |
| 9847 |
if (ex instanceof MissingDataException) { |
| 9848 |
throw ex; |
| 9849 |
} |
| 9850 |
UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern); |
| 9851 |
warn(ex); |
| 9852 |
return new Shadings.Dummy(); |
| 9853 |
} |
| 9854 |
}; |
| 9855 |
return Pattern; |
| 9856 |
})(); |
| 9857 |
|
| 9858 |
var Shadings = {}; |
| 9859 |
|
| 9860 |
// A small number to offset the first/last color stops so we can insert ones to |
| 9861 |
// support extend. Number.MIN_VALUE appears to be too small and breaks the |
| 9862 |
// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number |
| 9863 |
// internally so we have to go bigger. |
| 9864 |
Shadings.SMALL_NUMBER = 1e-2; |
| 9865 |
|
| 9866 |
// Radial and axial shading have very similar implementations |
| 9867 |
// If needed, the implementations can be broken into two classes |
| 9868 |
Shadings.RadialAxial = (function RadialAxialClosure() { |
| 9869 |
function RadialAxial(dict, matrix, xref, res) { |
| 9870 |
this.matrix = matrix; |
| 9871 |
this.coordsArr = dict.get('Coords'); |
| 9872 |
this.shadingType = dict.get('ShadingType'); |
| 9873 |
this.type = 'Pattern'; |
| 9874 |
var cs = dict.get('ColorSpace', 'CS'); |
| 9875 |
cs = ColorSpace.parse(cs, xref, res); |
| 9876 |
this.cs = cs; |
| 9877 |
|
| 9878 |
var t0 = 0.0, t1 = 1.0; |
| 9879 |
if (dict.has('Domain')) { |
| 9880 |
var domainArr = dict.get('Domain'); |
| 9881 |
t0 = domainArr[0]; |
| 9882 |
t1 = domainArr[1]; |
| 9883 |
} |
| 9884 |
|
| 9885 |
var extendStart = false, extendEnd = false; |
| 9886 |
if (dict.has('Extend')) { |
| 9887 |
var extendArr = dict.get('Extend'); |
| 9888 |
extendStart = extendArr[0]; |
| 9889 |
extendEnd = extendArr[1]; |
| 9890 |
} |
| 9891 |
|
| 9892 |
if (this.shadingType === PatternType.RADIAL && |
| 9893 |
(!extendStart || !extendEnd)) { |
| 9894 |
// Radial gradient only currently works if either circle is fully within |
| 9895 |
// the other circle. |
| 9896 |
var x1 = this.coordsArr[0]; |
| 9897 |
var y1 = this.coordsArr[1]; |
| 9898 |
var r1 = this.coordsArr[2]; |
| 9899 |
var x2 = this.coordsArr[3]; |
| 9900 |
var y2 = this.coordsArr[4]; |
| 9901 |
var r2 = this.coordsArr[5]; |
| 9902 |
var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); |
| 9903 |
if (r1 <= r2 + distance && |
| 9904 |
r2 <= r1 + distance) { |
| 9905 |
warn('Unsupported radial gradient.'); |
| 9906 |
} |
| 9907 |
} |
| 9908 |
|
| 9909 |
this.extendStart = extendStart; |
| 9910 |
this.extendEnd = extendEnd; |
| 9911 |
|
| 9912 |
var fnObj = dict.get('Function'); |
| 9913 |
var fn = PDFFunction.parseArray(xref, fnObj); |
| 9914 |
|
| 9915 |
// 10 samples seems good enough for now, but probably won't work |
| 9916 |
// if there are sharp color changes. Ideally, we would implement |
| 9917 |
// the spec faithfully and add lossless optimizations. |
| 9918 |
var diff = t1 - t0; |
| 9919 |
var step = diff / 10; |
| 9920 |
|
| 9921 |
var colorStops = this.colorStops = []; |
| 9922 |
|
| 9923 |
// Protect against bad domains so we don't end up in an infinte loop below. |
| 9924 |
if (t0 >= t1 || step <= 0) { |
| 9925 |
// Acrobat doesn't seem to handle these cases so we'll ignore for |
| 9926 |
// now. |
| 9927 |
info('Bad shading domain.'); |
| 9928 |
return; |
| 9929 |
} |
| 9930 |
|
| 9931 |
var color = new Float32Array(cs.numComps), ratio = new Float32Array(1); |
| 9932 |
var rgbColor; |
| 9933 |
for (var i = t0; i <= t1; i += step) { |
| 9934 |
ratio[0] = i; |
| 9935 |
fn(ratio, 0, color, 0); |
| 9936 |
rgbColor = cs.getRgb(color, 0); |
| 9937 |
var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); |
| 9938 |
colorStops.push([(i - t0) / diff, cssColor]); |
| 9939 |
} |
| 9940 |
|
| 9941 |
var background = 'transparent'; |
| 9942 |
if (dict.has('Background')) { |
| 9943 |
rgbColor = cs.getRgb(dict.get('Background'), 0); |
| 9944 |
background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); |
| 9945 |
} |
| 9946 |
|
| 9947 |
if (!extendStart) { |
| 9948 |
// Insert a color stop at the front and offset the first real color stop |
| 9949 |
// so it doesn't conflict with the one we insert. |
| 9950 |
colorStops.unshift([0, background]); |
| 9951 |
colorStops[1][0] += Shadings.SMALL_NUMBER; |
| 9952 |
} |
| 9953 |
if (!extendEnd) { |
| 9954 |
// Same idea as above in extendStart but for the end. |
| 9955 |
colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER; |
| 9956 |
colorStops.push([1, background]); |
| 9957 |
} |
| 9958 |
|
| 9959 |
this.colorStops = colorStops; |
| 9960 |
} |
| 9961 |
|
| 9962 |
RadialAxial.prototype = { |
| 9963 |
getIR: function RadialAxial_getIR() { |
| 9964 |
var coordsArr = this.coordsArr; |
| 9965 |
var shadingType = this.shadingType; |
| 9966 |
var type, p0, p1, r0, r1; |
| 9967 |
if (shadingType === PatternType.AXIAL) { |
| 9968 |
p0 = [coordsArr[0], coordsArr[1]]; |
| 9969 |
p1 = [coordsArr[2], coordsArr[3]]; |
| 9970 |
r0 = null; |
| 9971 |
r1 = null; |
| 9972 |
type = 'axial'; |
| 9973 |
} else if (shadingType === PatternType.RADIAL) { |
| 9974 |
p0 = [coordsArr[0], coordsArr[1]]; |
| 9975 |
p1 = [coordsArr[3], coordsArr[4]]; |
| 9976 |
r0 = coordsArr[2]; |
| 9977 |
r1 = coordsArr[5]; |
| 9978 |
type = 'radial'; |
| 9979 |
} else { |
| 9980 |
error('getPattern type unknown: ' + shadingType); |
| 9981 |
} |
| 9982 |
|
| 9983 |
var matrix = this.matrix; |
| 9984 |
if (matrix) { |
| 9985 |
p0 = Util.applyTransform(p0, matrix); |
| 9986 |
p1 = Util.applyTransform(p1, matrix); |
| 9987 |
} |
| 9988 |
|
| 9989 |
return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1]; |
| 9990 |
} |
| 9991 |
}; |
| 9992 |
|
| 9993 |
return RadialAxial; |
| 9994 |
})(); |
| 9995 |
|
| 9996 |
// All mesh shading. For now, they will be presented as set of the triangles |
| 9997 |
// to be drawn on the canvas and rgb color for each vertex. |
| 9998 |
Shadings.Mesh = (function MeshClosure() { |
| 9999 |
function MeshStreamReader(stream, context) { |
| 10000 |
this.stream = stream; |
| 10001 |
this.context = context; |
| 10002 |
this.buffer = 0; |
| 10003 |
this.bufferLength = 0; |
| 10004 |
|
| 10005 |
var numComps = context.numComps; |
| 10006 |
this.tmpCompsBuf = new Float32Array(numComps); |
| 10007 |
var csNumComps = context.colorSpace; |
| 10008 |
this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : |
| 10009 |
this.tmpCompsBuf; |
| 10010 |
} |
| 10011 |
MeshStreamReader.prototype = { |
| 10012 |
get hasData() { |
| 10013 |
if (this.stream.end) { |
| 10014 |
return this.stream.pos < this.stream.end; |
| 10015 |
} |
| 10016 |
if (this.bufferLength > 0) { |
| 10017 |
return true; |
| 10018 |
} |
| 10019 |
var nextByte = this.stream.getByte(); |
| 10020 |
if (nextByte < 0) { |
| 10021 |
return false; |
| 10022 |
} |
| 10023 |
this.buffer = nextByte; |
| 10024 |
this.bufferLength = 8; |
| 10025 |
return true; |
| 10026 |
}, |
| 10027 |
readBits: function MeshStreamReader_readBits(n) { |
| 10028 |
var buffer = this.buffer; |
| 10029 |
var bufferLength = this.bufferLength; |
| 10030 |
if (n === 32) { |
| 10031 |
if (bufferLength === 0) { |
| 10032 |
return ((this.stream.getByte() << 24) | |
| 10033 |
(this.stream.getByte() << 16) | (this.stream.getByte() << 8) | |
| 10034 |
this.stream.getByte()) >>> 0; |
| 10035 |
} |
| 10036 |
buffer = (buffer << 24) | (this.stream.getByte() << 16) | |
| 10037 |
(this.stream.getByte() << 8) | this.stream.getByte(); |
| 10038 |
var nextByte = this.stream.getByte(); |
| 10039 |
this.buffer = nextByte & ((1 << bufferLength) - 1); |
| 10040 |
return ((buffer << (8 - bufferLength)) | |
| 10041 |
((nextByte & 0xFF) >> bufferLength)) >>> 0; |
| 10042 |
} |
| 10043 |
if (n === 8 && bufferLength === 0) { |
| 10044 |
return this.stream.getByte(); |
| 10045 |
} |
| 10046 |
while (bufferLength < n) { |
| 10047 |
buffer = (buffer << 8) | this.stream.getByte(); |
| 10048 |
bufferLength += 8; |
| 10049 |
} |
| 10050 |
bufferLength -= n; |
| 10051 |
this.bufferLength = bufferLength; |
| 10052 |
this.buffer = buffer & ((1 << bufferLength) - 1); |
| 10053 |
return buffer >> bufferLength; |
| 10054 |
}, |
| 10055 |
align: function MeshStreamReader_align() { |
| 10056 |
this.buffer = 0; |
| 10057 |
this.bufferLength = 0; |
| 10058 |
}, |
| 10059 |
readFlag: function MeshStreamReader_readFlag() { |
| 10060 |
return this.readBits(this.context.bitsPerFlag); |
| 10061 |
}, |
| 10062 |
readCoordinate: function MeshStreamReader_readCoordinate() { |
| 10063 |
var bitsPerCoordinate = this.context.bitsPerCoordinate; |
| 10064 |
var xi = this.readBits(bitsPerCoordinate); |
| 10065 |
var yi = this.readBits(bitsPerCoordinate); |
| 10066 |
var decode = this.context.decode; |
| 10067 |
var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : |
| 10068 |
2.3283064365386963e-10; // 2 ^ -32 |
| 10069 |
return [ |
| 10070 |
xi * scale * (decode[1] - decode[0]) + decode[0], |
| 10071 |
yi * scale * (decode[3] - decode[2]) + decode[2] |
| 10072 |
]; |
| 10073 |
}, |
| 10074 |
readComponents: function MeshStreamReader_readComponents() { |
| 10075 |
var numComps = this.context.numComps; |
| 10076 |
var bitsPerComponent = this.context.bitsPerComponent; |
| 10077 |
var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : |
| 10078 |
2.3283064365386963e-10; // 2 ^ -32 |
| 10079 |
var decode = this.context.decode; |
| 10080 |
var components = this.tmpCompsBuf; |
| 10081 |
for (var i = 0, j = 4; i < numComps; i++, j += 2) { |
| 10082 |
var ci = this.readBits(bitsPerComponent); |
| 10083 |
components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j]; |
| 10084 |
} |
| 10085 |
var color = this.tmpCsCompsBuf; |
| 10086 |
if (this.context.colorFn) { |
| 10087 |
this.context.colorFn(components, 0, color, 0); |
| 10088 |
} |
| 10089 |
return this.context.colorSpace.getRgb(color, 0); |
| 10090 |
} |
| 10091 |
}; |
| 10092 |
|
| 10093 |
function decodeType4Shading(mesh, reader) { |
| 10094 |
var coords = mesh.coords; |
| 10095 |
var colors = mesh.colors; |
| 10096 |
var operators = []; |
| 10097 |
var ps = []; // not maintaining cs since that will match ps |
| 10098 |
var verticesLeft = 0; // assuming we have all data to start a new triangle |
| 10099 |
while (reader.hasData) { |
| 10100 |
var f = reader.readFlag(); |
| 10101 |
var coord = reader.readCoordinate(); |
| 10102 |
var color = reader.readComponents(); |
| 10103 |
if (verticesLeft === 0) { // ignoring flags if we started a triangle |
| 10104 |
assert(0 <= f && f <= 2, 'Unknown type4 flag'); |
| 10105 |
switch (f) { |
| 10106 |
case 0: |
| 10107 |
verticesLeft = 3; |
| 10108 |
break; |
| 10109 |
case 1: |
| 10110 |
ps.push(ps[ps.length - 2], ps[ps.length - 1]); |
| 10111 |
verticesLeft = 1; |
| 10112 |
break; |
| 10113 |
case 2: |
| 10114 |
ps.push(ps[ps.length - 3], ps[ps.length - 1]); |
| 10115 |
verticesLeft = 1; |
| 10116 |
break; |
| 10117 |
} |
| 10118 |
operators.push(f); |
| 10119 |
} |
| 10120 |
ps.push(coords.length); |
| 10121 |
coords.push(coord); |
| 10122 |
colors.push(color); |
| 10123 |
verticesLeft--; |
| 10124 |
|
| 10125 |
reader.align(); |
| 10126 |
} |
| 10127 |
|
| 10128 |
var psPacked = new Int32Array(ps); |
| 10129 |
|
| 10130 |
mesh.figures.push({ |
| 10131 |
type: 'triangles', |
| 10132 |
coords: psPacked, |
| 10133 |
colors: psPacked |
| 10134 |
}); |
| 10135 |
} |
| 10136 |
|
| 10137 |
function decodeType5Shading(mesh, reader, verticesPerRow) { |
| 10138 |
var coords = mesh.coords; |
| 10139 |
var colors = mesh.colors; |
| 10140 |
var ps = []; // not maintaining cs since that will match ps |
| 10141 |
while (reader.hasData) { |
| 10142 |
var coord = reader.readCoordinate(); |
| 10143 |
var color = reader.readComponents(); |
| 10144 |
ps.push(coords.length); |
| 10145 |
coords.push(coord); |
| 10146 |
colors.push(color); |
| 10147 |
} |
| 10148 |
|
| 10149 |
var psPacked = new Int32Array(ps); |
| 10150 |
|
| 10151 |
mesh.figures.push({ |
| 10152 |
type: 'lattice', |
| 10153 |
coords: psPacked, |
| 10154 |
colors: psPacked, |
| 10155 |
verticesPerRow: verticesPerRow |
| 10156 |
}); |
| 10157 |
} |
| 10158 |
|
| 10159 |
var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3; |
| 10160 |
var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20; |
| 10161 |
|
| 10162 |
var TRIANGLE_DENSITY = 20; // count of triangles per entire mesh bounds |
| 10163 |
|
| 10164 |
var getB = (function getBClosure() { |
| 10165 |
function buildB(count) { |
| 10166 |
var lut = []; |
| 10167 |
for (var i = 0; i <= count; i++) { |
| 10168 |
var t = i / count, t_ = 1 - t; |
| 10169 |
lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, |
| 10170 |
3 * t * t * t_, t * t * t])); |
| 10171 |
} |
| 10172 |
return lut; |
| 10173 |
} |
| 10174 |
var cache = []; |
| 10175 |
return function getB(count) { |
| 10176 |
if (!cache[count]) { |
| 10177 |
cache[count] = buildB(count); |
| 10178 |
} |
| 10179 |
return cache[count]; |
| 10180 |
}; |
| 10181 |
})(); |
| 10182 |
|
| 10183 |
function buildFigureFromPatch(mesh, index) { |
| 10184 |
var figure = mesh.figures[index]; |
| 10185 |
assert(figure.type === 'patch', 'Unexpected patch mesh figure'); |
| 10186 |
|
| 10187 |
var coords = mesh.coords, colors = mesh.colors; |
| 10188 |
var pi = figure.coords; |
| 10189 |
var ci = figure.colors; |
| 10190 |
|
| 10191 |
var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], |
| 10192 |
coords[pi[12]][0], coords[pi[15]][0]); |
| 10193 |
var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], |
| 10194 |
coords[pi[12]][1], coords[pi[15]][1]); |
| 10195 |
var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], |
| 10196 |
coords[pi[12]][0], coords[pi[15]][0]); |
| 10197 |
var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], |
| 10198 |
coords[pi[12]][1], coords[pi[15]][1]); |
| 10199 |
var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / |
| 10200 |
(mesh.bounds[2] - mesh.bounds[0])); |
| 10201 |
splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, |
| 10202 |
Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy)); |
| 10203 |
var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / |
| 10204 |
(mesh.bounds[3] - mesh.bounds[1])); |
| 10205 |
splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, |
| 10206 |
Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy)); |
| 10207 |
|
| 10208 |
var verticesPerRow = splitXBy + 1; |
| 10209 |
var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow); |
| 10210 |
var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow); |
| 10211 |
var k = 0; |
| 10212 |
var cl = new Uint8Array(3), cr = new Uint8Array(3); |
| 10213 |
var c0 = colors[ci[0]], c1 = colors[ci[1]], |
| 10214 |
c2 = colors[ci[2]], c3 = colors[ci[3]]; |
| 10215 |
var bRow = getB(splitYBy), bCol = getB(splitXBy); |
| 10216 |
for (var row = 0; row <= splitYBy; row++) { |
| 10217 |
cl[0] = ((c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy) | 0; |
| 10218 |
cl[1] = ((c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy) | 0; |
| 10219 |
cl[2] = ((c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy) | 0; |
| 10220 |
|
| 10221 |
cr[0] = ((c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy) | 0; |
| 10222 |
cr[1] = ((c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy) | 0; |
| 10223 |
cr[2] = ((c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy) | 0; |
| 10224 |
|
| 10225 |
for (var col = 0; col <= splitXBy; col++, k++) { |
| 10226 |
if ((row === 0 || row === splitYBy) && |
| 10227 |
(col === 0 || col === splitXBy)) { |
| 10228 |
continue; |
| 10229 |
} |
| 10230 |
var x = 0, y = 0; |
| 10231 |
var q = 0; |
| 10232 |
for (var i = 0; i <= 3; i++) { |
| 10233 |
for (var j = 0; j <= 3; j++, q++) { |
| 10234 |
var m = bRow[row][i] * bCol[col][j]; |
| 10235 |
x += coords[pi[q]][0] * m; |
| 10236 |
y += coords[pi[q]][1] * m; |
| 10237 |
} |
| 10238 |
} |
| 10239 |
figureCoords[k] = coords.length; |
| 10240 |
coords.push([x, y]); |
| 10241 |
figureColors[k] = colors.length; |
| 10242 |
var newColor = new Uint8Array(3); |
| 10243 |
newColor[0] = ((cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy) | 0; |
| 10244 |
newColor[1] = ((cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy) | 0; |
| 10245 |
newColor[2] = ((cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy) | 0; |
| 10246 |
colors.push(newColor); |
| 10247 |
} |
| 10248 |
} |
| 10249 |
figureCoords[0] = pi[0]; |
| 10250 |
figureColors[0] = ci[0]; |
| 10251 |
figureCoords[splitXBy] = pi[3]; |
| 10252 |
figureColors[splitXBy] = ci[1]; |
| 10253 |
figureCoords[verticesPerRow * splitYBy] = pi[12]; |
| 10254 |
figureColors[verticesPerRow * splitYBy] = ci[2]; |
| 10255 |
figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15]; |
| 10256 |
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3]; |
| 10257 |
|
| 10258 |
mesh.figures[index] = { |
| 10259 |
type: 'lattice', |
| 10260 |
coords: figureCoords, |
| 10261 |
colors: figureColors, |
| 10262 |
verticesPerRow: verticesPerRow |
| 10263 |
}; |
| 10264 |
} |
| 10265 |
|
| 10266 |
function decodeType6Shading(mesh, reader) { |
| 10267 |
// A special case of Type 7. The p11, p12, p21, p22 automatically filled |
| 10268 |
var coords = mesh.coords; |
| 10269 |
var colors = mesh.colors; |
| 10270 |
var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33 |
| 10271 |
var cs = new Int32Array(4); // c00, c30, c03, c33 |
| 10272 |
while (reader.hasData) { |
| 10273 |
var f = reader.readFlag(); |
| 10274 |
assert(0 <= f && f <= 3, 'Unknown type6 flag'); |
| 10275 |
var i, ii; |
| 10276 |
var pi = coords.length; |
| 10277 |
for (i = 0, ii = (f !== 0 ? 8 : 12); i < ii; i++) { |
| 10278 |
coords.push(reader.readCoordinate()); |
| 10279 |
} |
| 10280 |
var ci = colors.length; |
| 10281 |
for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) { |
| 10282 |
colors.push(reader.readComponents()); |
| 10283 |
} |
| 10284 |
var tmp1, tmp2, tmp3, tmp4; |
| 10285 |
switch (f) { |
| 10286 |
case 0: |
| 10287 |
ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6; |
| 10288 |
ps[ 8] = pi + 2; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7; |
| 10289 |
ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 8; |
| 10290 |
ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9; |
| 10291 |
cs[2] = ci + 1; cs[3] = ci + 2; |
| 10292 |
cs[0] = ci; cs[1] = ci + 3; |
| 10293 |
break; |
| 10294 |
case 1: |
| 10295 |
tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15]; |
| 10296 |
ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2; |
| 10297 |
ps[ 8] = pi + 6; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 1; |
| 10298 |
ps[ 4] = pi + 7; /* calculated below */ ps[ 7] = pi; |
| 10299 |
ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4; |
| 10300 |
tmp1 = cs[2]; tmp2 = cs[3]; |
| 10301 |
cs[2] = ci + 1; cs[3] = ci; |
| 10302 |
cs[0] = tmp1; cs[1] = tmp2; |
| 10303 |
break; |
| 10304 |
case 2: |
| 10305 |
ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5; |
| 10306 |
ps[ 8] = ps[11]; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 4; |
| 10307 |
ps[ 4] = ps[7]; /* calculated below */ ps[ 7] = pi + 3; |
| 10308 |
ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2; |
| 10309 |
cs[2] = cs[3]; cs[3] = ci + 1; |
| 10310 |
cs[0] = cs[1]; cs[1] = ci; |
| 10311 |
break; |
| 10312 |
case 3: |
| 10313 |
ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3]; |
| 10314 |
ps[ 8] = pi; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7; |
| 10315 |
ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 6; |
| 10316 |
ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5; |
| 10317 |
cs[2] = cs[0]; cs[3] = cs[1]; |
| 10318 |
cs[0] = ci; cs[1] = ci + 1; |
| 10319 |
break; |
| 10320 |
} |
| 10321 |
// set p11, p12, p21, p22 |
| 10322 |
ps[5] = coords.length; |
| 10323 |
coords.push([ |
| 10324 |
(-4 * coords[ps[0]][0] - coords[ps[15]][0] + |
| 10325 |
6 * (coords[ps[4]][0] + coords[ps[1]][0]) - |
| 10326 |
2 * (coords[ps[12]][0] + coords[ps[3]][0]) + |
| 10327 |
3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, |
| 10328 |
(-4 * coords[ps[0]][1] - coords[ps[15]][1] + |
| 10329 |
6 * (coords[ps[4]][1] + coords[ps[1]][1]) - |
| 10330 |
2 * (coords[ps[12]][1] + coords[ps[3]][1]) + |
| 10331 |
3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9 |
| 10332 |
]); |
| 10333 |
ps[6] = coords.length; |
| 10334 |
coords.push([ |
| 10335 |
(-4 * coords[ps[3]][0] - coords[ps[12]][0] + |
| 10336 |
6 * (coords[ps[2]][0] + coords[ps[7]][0]) - |
| 10337 |
2 * (coords[ps[0]][0] + coords[ps[15]][0]) + |
| 10338 |
3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, |
| 10339 |
(-4 * coords[ps[3]][1] - coords[ps[12]][1] + |
| 10340 |
6 * (coords[ps[2]][1] + coords[ps[7]][1]) - |
| 10341 |
2 * (coords[ps[0]][1] + coords[ps[15]][1]) + |
| 10342 |
3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9 |
| 10343 |
]); |
| 10344 |
ps[9] = coords.length; |
| 10345 |
coords.push([ |
| 10346 |
(-4 * coords[ps[12]][0] - coords[ps[3]][0] + |
| 10347 |
6 * (coords[ps[8]][0] + coords[ps[13]][0]) - |
| 10348 |
2 * (coords[ps[0]][0] + coords[ps[15]][0]) + |
| 10349 |
3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, |
| 10350 |
(-4 * coords[ps[12]][1] - coords[ps[3]][1] + |
| 10351 |
6 * (coords[ps[8]][1] + coords[ps[13]][1]) - |
| 10352 |
2 * (coords[ps[0]][1] + coords[ps[15]][1]) + |
| 10353 |
3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9 |
| 10354 |
]); |
| 10355 |
ps[10] = coords.length; |
| 10356 |
coords.push([ |
| 10357 |
(-4 * coords[ps[15]][0] - coords[ps[0]][0] + |
| 10358 |
6 * (coords[ps[11]][0] + coords[ps[14]][0]) - |
| 10359 |
2 * (coords[ps[12]][0] + coords[ps[3]][0]) + |
| 10360 |
3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, |
| 10361 |
(-4 * coords[ps[15]][1] - coords[ps[0]][1] + |
| 10362 |
6 * (coords[ps[11]][1] + coords[ps[14]][1]) - |
| 10363 |
2 * (coords[ps[12]][1] + coords[ps[3]][1]) + |
| 10364 |
3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9 |
| 10365 |
]); |
| 10366 |
mesh.figures.push({ |
| 10367 |
type: 'patch', |
| 10368 |
coords: new Int32Array(ps), // making copies of ps and cs |
| 10369 |
colors: new Int32Array(cs) |
| 10370 |
}); |
| 10371 |
} |
| 10372 |
} |
| 10373 |
|
| 10374 |
function decodeType7Shading(mesh, reader) { |
| 10375 |
var coords = mesh.coords; |
| 10376 |
var colors = mesh.colors; |
| 10377 |
var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33 |
| 10378 |
var cs = new Int32Array(4); // c00, c30, c03, c33 |
| 10379 |
while (reader.hasData) { |
| 10380 |
var f = reader.readFlag(); |
| 10381 |
assert(0 <= f && f <= 3, 'Unknown type7 flag'); |
| 10382 |
var i, ii; |
| 10383 |
var pi = coords.length; |
| 10384 |
for (i = 0, ii = (f !== 0 ? 12 : 16); i < ii; i++) { |
| 10385 |
coords.push(reader.readCoordinate()); |
| 10386 |
} |
| 10387 |
var ci = colors.length; |
| 10388 |
for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) { |
| 10389 |
colors.push(reader.readComponents()); |
| 10390 |
} |
| 10391 |
var tmp1, tmp2, tmp3, tmp4; |
| 10392 |
switch (f) { |
| 10393 |
case 0: |
| 10394 |
ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6; |
| 10395 |
ps[ 8] = pi + 2; ps[ 9] = pi + 13; ps[10] = pi + 14; ps[11] = pi + 7; |
| 10396 |
ps[ 4] = pi + 1; ps[ 5] = pi + 12; ps[ 6] = pi + 15; ps[ 7] = pi + 8; |
| 10397 |
ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9; |
| 10398 |
cs[2] = ci + 1; cs[3] = ci + 2; |
| 10399 |
cs[0] = ci; cs[1] = ci + 3; |
| 10400 |
break; |
| 10401 |
case 1: |
| 10402 |
tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15]; |
| 10403 |
ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2; |
| 10404 |
ps[ 8] = pi + 6; ps[ 9] = pi + 11; ps[10] = pi + 10; ps[11] = pi + 1; |
| 10405 |
ps[ 4] = pi + 7; ps[ 5] = pi + 8; ps[ 6] = pi + 9; ps[ 7] = pi; |
| 10406 |
ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4; |
| 10407 |
tmp1 = cs[2]; tmp2 = cs[3]; |
| 10408 |
cs[2] = ci + 1; cs[3] = ci; |
| 10409 |
cs[0] = tmp1; cs[1] = tmp2; |
| 10410 |
break; |
| 10411 |
case 2: |
| 10412 |
ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5; |
| 10413 |
ps[ 8] = ps[11]; ps[ 9] = pi + 8; ps[10] = pi + 11; ps[11] = pi + 4; |
| 10414 |
ps[ 4] = ps[7]; ps[ 5] = pi + 9; ps[ 6] = pi + 10; ps[ 7] = pi + 3; |
| 10415 |
ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2; |
| 10416 |
cs[2] = cs[3]; cs[3] = ci + 1; |
| 10417 |
cs[0] = cs[1]; cs[1] = ci; |
| 10418 |
break; |
| 10419 |
case 3: |
| 10420 |
ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3]; |
| 10421 |
ps[ 8] = pi; ps[ 9] = pi + 9; ps[10] = pi + 8; ps[11] = pi + 7; |
| 10422 |
ps[ 4] = pi + 1; ps[ 5] = pi + 10; ps[ 6] = pi + 11; ps[ 7] = pi + 6; |
| 10423 |
ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5; |
| 10424 |
cs[2] = cs[0]; cs[3] = cs[1]; |
| 10425 |
cs[0] = ci; cs[1] = ci + 1; |
| 10426 |
break; |
| 10427 |
} |
| 10428 |
mesh.figures.push({ |
| 10429 |
type: 'patch', |
| 10430 |
coords: new Int32Array(ps), // making copies of ps and cs |
| 10431 |
colors: new Int32Array(cs) |
| 10432 |
}); |
| 10433 |
} |
| 10434 |
} |
| 10435 |
|
| 10436 |
function updateBounds(mesh) { |
| 10437 |
var minX = mesh.coords[0][0], minY = mesh.coords[0][1], |
| 10438 |
maxX = minX, maxY = minY; |
| 10439 |
for (var i = 1, ii = mesh.coords.length; i < ii; i++) { |
| 10440 |
var x = mesh.coords[i][0], y = mesh.coords[i][1]; |
| 10441 |
minX = minX > x ? x : minX; |
| 10442 |
minY = minY > y ? y : minY; |
| 10443 |
maxX = maxX < x ? x : maxX; |
| 10444 |
maxY = maxY < y ? y : maxY; |
| 10445 |
} |
| 10446 |
mesh.bounds = [minX, minY, maxX, maxY]; |
| 10447 |
} |
| 10448 |
|
| 10449 |
function packData(mesh) { |
| 10450 |
var i, ii, j, jj; |
| 10451 |
|
| 10452 |
var coords = mesh.coords; |
| 10453 |
var coordsPacked = new Float32Array(coords.length * 2); |
| 10454 |
for (i = 0, j = 0, ii = coords.length; i < ii; i++) { |
| 10455 |
var xy = coords[i]; |
| 10456 |
coordsPacked[j++] = xy[0]; |
| 10457 |
coordsPacked[j++] = xy[1]; |
| 10458 |
} |
| 10459 |
mesh.coords = coordsPacked; |
| 10460 |
|
| 10461 |
var colors = mesh.colors; |
| 10462 |
var colorsPacked = new Uint8Array(colors.length * 3); |
| 10463 |
for (i = 0, j = 0, ii = colors.length; i < ii; i++) { |
| 10464 |
var c = colors[i]; |
| 10465 |
colorsPacked[j++] = c[0]; |
| 10466 |
colorsPacked[j++] = c[1]; |
| 10467 |
colorsPacked[j++] = c[2]; |
| 10468 |
} |
| 10469 |
mesh.colors = colorsPacked; |
| 10470 |
|
| 10471 |
var figures = mesh.figures; |
| 10472 |
for (i = 0, ii = figures.length; i < ii; i++) { |
| 10473 |
var figure = figures[i], ps = figure.coords, cs = figure.colors; |
| 10474 |
for (j = 0, jj = ps.length; j < jj; j++) { |
| 10475 |
ps[j] *= 2; |
| 10476 |
cs[j] *= 3; |
| 10477 |
} |
| 10478 |
} |
| 10479 |
} |
| 10480 |
|
| 10481 |
function Mesh(stream, matrix, xref, res) { |
| 10482 |
assert(isStream(stream), 'Mesh data is not a stream'); |
| 10483 |
var dict = stream.dict; |
| 10484 |
this.matrix = matrix; |
| 10485 |
this.shadingType = dict.get('ShadingType'); |
| 10486 |
this.type = 'Pattern'; |
| 10487 |
this.bbox = dict.get('BBox'); |
| 10488 |
var cs = dict.get('ColorSpace', 'CS'); |
| 10489 |
cs = ColorSpace.parse(cs, xref, res); |
| 10490 |
this.cs = cs; |
| 10491 |
this.background = dict.has('Background') ? |
| 10492 |
cs.getRgb(dict.get('Background'), 0) : null; |
| 10493 |
|
| 10494 |
var fnObj = dict.get('Function'); |
| 10495 |
var fn = fnObj ? PDFFunction.parseArray(xref, fnObj) : null; |
| 10496 |
|
| 10497 |
this.coords = []; |
| 10498 |
this.colors = []; |
| 10499 |
this.figures = []; |
| 10500 |
|
| 10501 |
var decodeContext = { |
| 10502 |
bitsPerCoordinate: dict.get('BitsPerCoordinate'), |
| 10503 |
bitsPerComponent: dict.get('BitsPerComponent'), |
| 10504 |
bitsPerFlag: dict.get('BitsPerFlag'), |
| 10505 |
decode: dict.get('Decode'), |
| 10506 |
colorFn: fn, |
| 10507 |
colorSpace: cs, |
| 10508 |
numComps: fn ? 1 : cs.numComps |
| 10509 |
}; |
| 10510 |
var reader = new MeshStreamReader(stream, decodeContext); |
| 10511 |
|
| 10512 |
var patchMesh = false; |
| 10513 |
switch (this.shadingType) { |
| 10514 |
case PatternType.FREE_FORM_MESH: |
| 10515 |
decodeType4Shading(this, reader); |
| 10516 |
break; |
| 10517 |
case PatternType.LATTICE_FORM_MESH: |
| 10518 |
var verticesPerRow = dict.get('VerticesPerRow') | 0; |
| 10519 |
assert(verticesPerRow >= 2, 'Invalid VerticesPerRow'); |
| 10520 |
decodeType5Shading(this, reader, verticesPerRow); |
| 10521 |
break; |
| 10522 |
case PatternType.COONS_PATCH_MESH: |
| 10523 |
decodeType6Shading(this, reader); |
| 10524 |
patchMesh = true; |
| 10525 |
break; |
| 10526 |
case PatternType.TENSOR_PATCH_MESH: |
| 10527 |
decodeType7Shading(this, reader); |
| 10528 |
patchMesh = true; |
| 10529 |
break; |
| 10530 |
default: |
| 10531 |
error('Unsupported mesh type.'); |
| 10532 |
break; |
| 10533 |
} |
| 10534 |
|
| 10535 |
if (patchMesh) { |
| 10536 |
// dirty bounds calculation for determining, how dense shall be triangles |
| 10537 |
updateBounds(this); |
| 10538 |
for (var i = 0, ii = this.figures.length; i < ii; i++) { |
| 10539 |
buildFigureFromPatch(this, i); |
| 10540 |
} |
| 10541 |
} |
| 10542 |
// calculate bounds |
| 10543 |
updateBounds(this); |
| 10544 |
|
| 10545 |
packData(this); |
| 10546 |
} |
| 10547 |
|
| 10548 |
Mesh.prototype = { |
| 10549 |
getIR: function Mesh_getIR() { |
| 10550 |
return ['Mesh', this.shadingType, this.coords, this.colors, this.figures, |
| 10551 |
this.bounds, this.matrix, this.bbox, this.background]; |
| 10552 |
} |
| 10553 |
}; |
| 10554 |
|
| 10555 |
return Mesh; |
| 10556 |
})(); |
| 10557 |
|
| 10558 |
Shadings.Dummy = (function DummyClosure() { |
| 10559 |
function Dummy() { |
| 10560 |
this.type = 'Pattern'; |
| 10561 |
} |
| 10562 |
|
| 10563 |
Dummy.prototype = { |
| 10564 |
getIR: function Dummy_getIR() { |
| 10565 |
return ['Dummy']; |
| 10566 |
} |
| 10567 |
}; |
| 10568 |
return Dummy; |
| 10569 |
})(); |
| 10570 |
|
| 10571 |
function getTilingPatternIR(operatorList, dict, args) { |
| 10572 |
var matrix = dict.get('Matrix'); |
| 10573 |
var bbox = dict.get('BBox'); |
| 10574 |
var xstep = dict.get('XStep'); |
| 10575 |
var ystep = dict.get('YStep'); |
| 10576 |
var paintType = dict.get('PaintType'); |
| 10577 |
var tilingType = dict.get('TilingType'); |
| 10578 |
|
| 10579 |
return [ |
| 10580 |
'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, |
| 10581 |
paintType, tilingType |
| 10582 |
]; |
| 10583 |
} |
| 10584 |
|
| 10585 |
|
| 10586 |
var PartialEvaluator = (function PartialEvaluatorClosure() { |
| 10587 |
function PartialEvaluator(pdfManager, xref, handler, pageIndex, |
| 10588 |
uniquePrefix, idCounters, fontCache) { |
| 10589 |
this.pdfManager = pdfManager; |
| 10590 |
this.xref = xref; |
| 10591 |
this.handler = handler; |
| 10592 |
this.pageIndex = pageIndex; |
| 10593 |
this.uniquePrefix = uniquePrefix; |
| 10594 |
this.idCounters = idCounters; |
| 10595 |
this.fontCache = fontCache; |
| 10596 |
} |
| 10597 |
|
| 10598 |
// Trying to minimize Date.now() usage and check every 100 time |
| 10599 |
var TIME_SLOT_DURATION_MS = 20; |
| 10600 |
var CHECK_TIME_EVERY = 100; |
| 10601 |
function TimeSlotManager() { |
| 10602 |
this.reset(); |
| 10603 |
} |
| 10604 |
TimeSlotManager.prototype = { |
| 10605 |
check: function TimeSlotManager_check() { |
| 10606 |
if (++this.checked < CHECK_TIME_EVERY) { |
| 10607 |
return false; |
| 10608 |
} |
| 10609 |
this.checked = 0; |
| 10610 |
return this.endTime <= Date.now(); |
| 10611 |
}, |
| 10612 |
reset: function TimeSlotManager_reset() { |
| 10613 |
this.endTime = Date.now() + TIME_SLOT_DURATION_MS; |
| 10614 |
this.checked = 0; |
| 10615 |
} |
| 10616 |
}; |
| 10617 |
|
| 10618 |
var deferred = Promise.resolve(); |
| 10619 |
|
| 10620 |
var TILING_PATTERN = 1, SHADING_PATTERN = 2; |
| 10621 |
|
| 10622 |
PartialEvaluator.prototype = { |
| 10623 |
hasBlendModes: function PartialEvaluator_hasBlendModes(resources) { |
| 10624 |
if (!isDict(resources)) { |
| 10625 |
return false; |
| 10626 |
} |
| 10627 |
|
| 10628 |
var processed = Object.create(null); |
| 10629 |
if (resources.objId) { |
| 10630 |
processed[resources.objId] = true; |
| 10631 |
} |
| 10632 |
|
| 10633 |
var nodes = [resources]; |
| 10634 |
while (nodes.length) { |
| 10635 |
var key; |
| 10636 |
var node = nodes.shift(); |
| 10637 |
// First check the current resources for blend modes. |
| 10638 |
var graphicStates = node.get('ExtGState'); |
| 10639 |
if (isDict(graphicStates)) { |
| 10640 |
graphicStates = graphicStates.getAll(); |
| 10641 |
for (key in graphicStates) { |
| 10642 |
var graphicState = graphicStates[key]; |
| 10643 |
var bm = graphicState['BM']; |
| 10644 |
if (isName(bm) && bm.name !== 'Normal') { |
| 10645 |
return true; |
| 10646 |
} |
| 10647 |
} |
| 10648 |
} |
| 10649 |
// Descend into the XObjects to look for more resources and blend modes. |
| 10650 |
var xObjects = node.get('XObject'); |
| 10651 |
if (!isDict(xObjects)) { |
| 10652 |
continue; |
| 10653 |
} |
| 10654 |
xObjects = xObjects.getAll(); |
| 10655 |
for (key in xObjects) { |
| 10656 |
var xObject = xObjects[key]; |
| 10657 |
if (!isStream(xObject)) { |
| 10658 |
continue; |
| 10659 |
} |
| 10660 |
if (xObject.dict.objId) { |
| 10661 |
if (processed[xObject.dict.objId]) { |
| 10662 |
// stream has objId and is processed already |
| 10663 |
continue; |
| 10664 |
} |
| 10665 |
processed[xObject.dict.objId] = true; |
| 10666 |
} |
| 10667 |
var xResources = xObject.dict.get('Resources'); |
| 10668 |
// Checking objId to detect an infinite loop. |
| 10669 |
if (isDict(xResources) && |
| 10670 |
(!xResources.objId || !processed[xResources.objId])) { |
| 10671 |
nodes.push(xResources); |
| 10672 |
if (xResources.objId) { |
| 10673 |
processed[xResources.objId] = true; |
| 10674 |
} |
| 10675 |
} |
| 10676 |
} |
| 10677 |
} |
| 10678 |
return false; |
| 10679 |
}, |
| 10680 |
|
| 10681 |
buildFormXObject: function PartialEvaluator_buildFormXObject(resources, |
| 10682 |
xobj, smask, |
| 10683 |
operatorList, |
| 10684 |
initialState) { |
| 10685 |
var matrix = xobj.dict.get('Matrix'); |
| 10686 |
var bbox = xobj.dict.get('BBox'); |
| 10687 |
var group = xobj.dict.get('Group'); |
| 10688 |
if (group) { |
| 10689 |
var groupOptions = { |
| 10690 |
matrix: matrix, |
| 10691 |
bbox: bbox, |
| 10692 |
smask: smask, |
| 10693 |
isolated: false, |
| 10694 |
knockout: false |
| 10695 |
}; |
| 10696 |
|
| 10697 |
var groupSubtype = group.get('S'); |
| 10698 |
var colorSpace; |
| 10699 |
if (isName(groupSubtype) && groupSubtype.name === 'Transparency') { |
| 10700 |
groupOptions.isolated = (group.get('I') || false); |
| 10701 |
groupOptions.knockout = (group.get('K') || false); |
| 10702 |
colorSpace = (group.has('CS') ? |
| 10703 |
ColorSpace.parse(group.get('CS'), this.xref, resources) : null); |
| 10704 |
} |
| 10705 |
|
| 10706 |
if (smask && smask.backdrop) { |
| 10707 |
colorSpace = colorSpace || ColorSpace.singletons.rgb; |
| 10708 |
smask.backdrop = colorSpace.getRgb(smask.backdrop, 0); |
| 10709 |
} |
| 10710 |
|
| 10711 |
operatorList.addOp(OPS.beginGroup, [groupOptions]); |
| 10712 |
} |
| 10713 |
|
| 10714 |
operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]); |
| 10715 |
|
| 10716 |
return this.getOperatorList(xobj, |
| 10717 |
(xobj.dict.get('Resources') || resources), operatorList, initialState). |
| 10718 |
then(function () { |
| 10719 |
operatorList.addOp(OPS.paintFormXObjectEnd, []); |
| 10720 |
|
| 10721 |
if (group) { |
| 10722 |
operatorList.addOp(OPS.endGroup, [groupOptions]); |
| 10723 |
} |
| 10724 |
}); |
| 10725 |
}, |
| 10726 |
|
| 10727 |
buildPaintImageXObject: |
| 10728 |
function PartialEvaluator_buildPaintImageXObject(resources, image, |
| 10729 |
inline, operatorList, |
| 10730 |
cacheKey, imageCache) { |
| 10731 |
var self = this; |
| 10732 |
var dict = image.dict; |
| 10733 |
var w = dict.get('Width', 'W'); |
| 10734 |
var h = dict.get('Height', 'H'); |
| 10735 |
|
| 10736 |
if (!(w && isNum(w)) || !(h && isNum(h))) { |
| 10737 |
warn('Image dimensions are missing, or not numbers.'); |
| 10738 |
return; |
| 10739 |
} |
| 10740 |
if (PDFJS.maxImageSize !== -1 && w * h > PDFJS.maxImageSize) { |
| 10741 |
warn('Image exceeded maximum allowed size and was removed.'); |
| 10742 |
return; |
| 10743 |
} |
| 10744 |
|
| 10745 |
var imageMask = (dict.get('ImageMask', 'IM') || false); |
| 10746 |
var imgData, args; |
| 10747 |
if (imageMask) { |
| 10748 |
// This depends on a tmpCanvas being filled with the |
| 10749 |
// current fillStyle, such that processing the pixel |
| 10750 |
// data can't be done here. Instead of creating a |
| 10751 |
// complete PDFImage, only read the information needed |
| 10752 |
// for later. |
| 10753 |
|
| 10754 |
var width = dict.get('Width', 'W'); |
| 10755 |
var height = dict.get('Height', 'H'); |
| 10756 |
var bitStrideLength = (width + 7) >> 3; |
| 10757 |
var imgArray = image.getBytes(bitStrideLength * height); |
| 10758 |
var decode = dict.get('Decode', 'D'); |
| 10759 |
var inverseDecode = (!!decode && decode[0] > 0); |
| 10760 |
|
| 10761 |
imgData = PDFImage.createMask(imgArray, width, height, |
| 10762 |
image instanceof DecodeStream, |
| 10763 |
inverseDecode); |
| 10764 |
imgData.cached = true; |
| 10765 |
args = [imgData]; |
| 10766 |
operatorList.addOp(OPS.paintImageMaskXObject, args); |
| 10767 |
if (cacheKey) { |
| 10768 |
imageCache[cacheKey] = { |
| 10769 |
fn: OPS.paintImageMaskXObject, |
| 10770 |
args: args |
| 10771 |
}; |
| 10772 |
} |
| 10773 |
return; |
| 10774 |
} |
| 10775 |
|
| 10776 |
var softMask = (dict.get('SMask', 'SM') || false); |
| 10777 |
var mask = (dict.get('Mask') || false); |
| 10778 |
|
| 10779 |
var SMALL_IMAGE_DIMENSIONS = 200; |
| 10780 |
// Inlining small images into the queue as RGB data |
| 10781 |
if (inline && !softMask && !mask && !(image instanceof JpegStream) && |
| 10782 |
(w + h) < SMALL_IMAGE_DIMENSIONS) { |
| 10783 |
var imageObj = new PDFImage(this.xref, resources, image, |
| 10784 |
inline, null, null); |
| 10785 |
// We force the use of RGBA_32BPP images here, because we can't handle |
| 10786 |
// any other kind. |
| 10787 |
imgData = imageObj.createImageData(/* forceRGBA = */ true); |
| 10788 |
operatorList.addOp(OPS.paintInlineImageXObject, [imgData]); |
| 10789 |
return; |
| 10790 |
} |
| 10791 |
|
| 10792 |
// If there is no imageMask, create the PDFImage and a lot |
| 10793 |
// of image processing can be done here. |
| 10794 |
var uniquePrefix = (this.uniquePrefix || ''); |
| 10795 |
var objId = 'img_' + uniquePrefix + (++this.idCounters.obj); |
| 10796 |
operatorList.addDependency(objId); |
| 10797 |
args = [objId, w, h]; |
| 10798 |
|
| 10799 |
if (!softMask && !mask && image instanceof JpegStream && |
| 10800 |
image.isNativelySupported(this.xref, resources)) { |
| 10801 |
// These JPEGs don't need any more processing so we can just send it. |
| 10802 |
operatorList.addOp(OPS.paintJpegXObject, args); |
| 10803 |
this.handler.send('obj', |
| 10804 |
[objId, this.pageIndex, 'JpegStream', image.getIR()]); |
| 10805 |
return; |
| 10806 |
} |
| 10807 |
|
| 10808 |
PDFImage.buildImage(self.handler, self.xref, resources, image, inline). |
| 10809 |
then(function(imageObj) { |
| 10810 |
var imgData = imageObj.createImageData(/* forceRGBA = */ false); |
| 10811 |
self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData], |
| 10812 |
[imgData.data.buffer]); |
| 10813 |
}).then(undefined, function (reason) { |
| 10814 |
warn('Unable to decode image: ' + reason); |
| 10815 |
self.handler.send('obj', [objId, self.pageIndex, 'Image', null]); |
| 10816 |
}); |
| 10817 |
|
| 10818 |
operatorList.addOp(OPS.paintImageXObject, args); |
| 10819 |
if (cacheKey) { |
| 10820 |
imageCache[cacheKey] = { |
| 10821 |
fn: OPS.paintImageXObject, |
| 10822 |
args: args |
| 10823 |
}; |
| 10824 |
} |
| 10825 |
}, |
| 10826 |
|
| 10827 |
handleSMask: function PartialEvaluator_handleSmask(smask, resources, |
| 10828 |
operatorList, |
| 10829 |
stateManager) { |
| 10830 |
var smaskContent = smask.get('G'); |
| 10831 |
var smaskOptions = { |
| 10832 |
subtype: smask.get('S').name, |
| 10833 |
backdrop: smask.get('BC') |
| 10834 |
}; |
| 10835 |
return this.buildFormXObject(resources, smaskContent, smaskOptions, |
| 10836 |
operatorList, stateManager.state.clone()); |
| 10837 |
}, |
| 10838 |
|
| 10839 |
handleTilingType: |
| 10840 |
function PartialEvaluator_handleTilingType(fn, args, resources, |
| 10841 |
pattern, patternDict, |
| 10842 |
operatorList) { |
| 10843 |
// Create an IR of the pattern code. |
| 10844 |
var tilingOpList = new OperatorList(); |
| 10845 |
return this.getOperatorList(pattern, |
| 10846 |
(patternDict.get('Resources') || resources), tilingOpList). |
| 10847 |
then(function () { |
| 10848 |
// Add the dependencies to the parent operator list so they are |
| 10849 |
// resolved before sub operator list is executed synchronously. |
| 10850 |
operatorList.addDependencies(tilingOpList.dependencies); |
| 10851 |
operatorList.addOp(fn, getTilingPatternIR({ |
| 10852 |
fnArray: tilingOpList.fnArray, |
| 10853 |
argsArray: tilingOpList.argsArray |
| 10854 |
}, patternDict, args)); |
| 10855 |
}); |
| 10856 |
}, |
| 10857 |
|
| 10858 |
handleSetFont: |
| 10859 |
function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, |
| 10860 |
operatorList, state) { |
| 10861 |
// TODO(mack): Not needed? |
| 10862 |
var fontName; |
| 10863 |
if (fontArgs) { |
| 10864 |
fontArgs = fontArgs.slice(); |
| 10865 |
fontName = fontArgs[0].name; |
| 10866 |
} |
| 10867 |
|
| 10868 |
var self = this; |
| 10869 |
return this.loadFont(fontName, fontRef, this.xref, resources).then( |
| 10870 |
function (translated) { |
| 10871 |
if (!translated.font.isType3Font) { |
| 10872 |
return translated; |
| 10873 |
} |
| 10874 |
return translated.loadType3Data(self, resources, operatorList).then( |
| 10875 |
function () { |
| 10876 |
return translated; |
| 10877 |
}); |
| 10878 |
}).then(function (translated) { |
| 10879 |
state.font = translated.font; |
| 10880 |
translated.send(self.handler); |
| 10881 |
return translated.loadedName; |
| 10882 |
}); |
| 10883 |
}, |
| 10884 |
|
| 10885 |
handleText: function PartialEvaluator_handleText(chars, state) { |
| 10886 |
var font = state.font; |
| 10887 |
var glyphs = font.charsToGlyphs(chars); |
| 10888 |
var isAddToPathSet = !!(state.textRenderingMode & |
| 10889 |
TextRenderingMode.ADD_TO_PATH_FLAG); |
| 10890 |
if (font.data && (isAddToPathSet || PDFJS.disableFontFace)) { |
| 10891 |
var buildPath = function (fontChar) { |
| 10892 |
if (!font.renderer.hasBuiltPath(fontChar)) { |
| 10893 |
var path = font.renderer.getPathJs(fontChar); |
| 10894 |
this.handler.send('commonobj', [ |
| 10895 |
font.loadedName + '_path_' + fontChar, |
| 10896 |
'FontPath', |
| 10897 |
path |
| 10898 |
]); |
| 10899 |
} |
| 10900 |
}.bind(this); |
| 10901 |
|
| 10902 |
for (var i = 0, ii = glyphs.length; i < ii; i++) { |
| 10903 |
var glyph = glyphs[i]; |
| 10904 |
if (glyph === null) { |
| 10905 |
continue; |
| 10906 |
} |
| 10907 |
buildPath(glyph.fontChar); |
| 10908 |
|
| 10909 |
// If the glyph has an accent we need to build a path for its |
| 10910 |
// fontChar too, otherwise CanvasGraphics_paintChar will fail. |
| 10911 |
var accent = glyph.accent; |
| 10912 |
if (accent && accent.fontChar) { |
| 10913 |
buildPath(accent.fontChar); |
| 10914 |
} |
| 10915 |
} |
| 10916 |
} |
| 10917 |
|
| 10918 |
return glyphs; |
| 10919 |
}, |
| 10920 |
|
| 10921 |
setGState: function PartialEvaluator_setGState(resources, gState, |
| 10922 |
operatorList, xref, |
| 10923 |
stateManager) { |
| 10924 |
// This array holds the converted/processed state data. |
| 10925 |
var gStateObj = []; |
| 10926 |
var gStateMap = gState.map; |
| 10927 |
var self = this; |
| 10928 |
var promise = Promise.resolve(); |
| 10929 |
for (var key in gStateMap) { |
| 10930 |
var value = gStateMap[key]; |
| 10931 |
switch (key) { |
| 10932 |
case 'Type': |
| 10933 |
break; |
| 10934 |
case 'LW': |
| 10935 |
case 'LC': |
| 10936 |
case 'LJ': |
| 10937 |
case 'ML': |
| 10938 |
case 'D': |
| 10939 |
case 'RI': |
| 10940 |
case 'FL': |
| 10941 |
case 'CA': |
| 10942 |
case 'ca': |
| 10943 |
gStateObj.push([key, value]); |
| 10944 |
break; |
| 10945 |
case 'Font': |
| 10946 |
promise = promise.then(function () { |
| 10947 |
return self.handleSetFont(resources, null, value[0], |
| 10948 |
operatorList, stateManager.state). |
| 10949 |
then(function (loadedName) { |
| 10950 |
operatorList.addDependency(loadedName); |
| 10951 |
gStateObj.push([key, [loadedName, value[1]]]); |
| 10952 |
}); |
| 10953 |
}); |
| 10954 |
break; |
| 10955 |
case 'BM': |
| 10956 |
gStateObj.push([key, value]); |
| 10957 |
break; |
| 10958 |
case 'SMask': |
| 10959 |
if (isName(value) && value.name === 'None') { |
| 10960 |
gStateObj.push([key, false]); |
| 10961 |
break; |
| 10962 |
} |
| 10963 |
var dict = xref.fetchIfRef(value); |
| 10964 |
if (isDict(dict)) { |
| 10965 |
promise = promise.then(function () { |
| 10966 |
return self.handleSMask(dict, resources, operatorList, |
| 10967 |
stateManager); |
| 10968 |
}); |
| 10969 |
gStateObj.push([key, true]); |
| 10970 |
} else { |
| 10971 |
warn('Unsupported SMask type'); |
| 10972 |
} |
| 10973 |
|
| 10974 |
break; |
| 10975 |
// Only generate info log messages for the following since |
| 10976 |
// they are unlikely to have a big impact on the rendering. |
| 10977 |
case 'OP': |
| 10978 |
case 'op': |
| 10979 |
case 'OPM': |
| 10980 |
case 'BG': |
| 10981 |
case 'BG2': |
| 10982 |
case 'UCR': |
| 10983 |
case 'UCR2': |
| 10984 |
case 'TR': |
| 10985 |
case 'TR2': |
| 10986 |
case 'HT': |
| 10987 |
case 'SM': |
| 10988 |
case 'SA': |
| 10989 |
case 'AIS': |
| 10990 |
case 'TK': |
| 10991 |
// TODO implement these operators. |
| 10992 |
info('graphic state operator ' + key); |
| 10993 |
break; |
| 10994 |
default: |
| 10995 |
info('Unknown graphic state operator ' + key); |
| 10996 |
break; |
| 10997 |
} |
| 10998 |
} |
| 10999 |
return promise.then(function () { |
| 11000 |
if (gStateObj.length >= 0) { |
| 11001 |
operatorList.addOp(OPS.setGState, [gStateObj]); |
| 11002 |
} |
| 11003 |
}); |
| 11004 |
}, |
| 11005 |
|
| 11006 |
loadFont: function PartialEvaluator_loadFont(fontName, font, xref, |
| 11007 |
resources) { |
| 11008 |
|
| 11009 |
function errorFont() { |
| 11010 |
return Promise.resolve(new TranslatedFont('g_font_error', |
| 11011 |
new ErrorFont('Font ' + fontName + ' is not available'), font)); |
| 11012 |
} |
| 11013 |
var fontRef; |
| 11014 |
if (font) { // Loading by ref. |
| 11015 |
assert(isRef(font)); |
| 11016 |
fontRef = font; |
| 11017 |
} else { // Loading by name. |
| 11018 |
var fontRes = resources.get('Font'); |
| 11019 |
if (fontRes) { |
| 11020 |
fontRef = fontRes.getRaw(fontName); |
| 11021 |
} else { |
| 11022 |
warn('fontRes not available'); |
| 11023 |
return errorFont(); |
| 11024 |
} |
| 11025 |
} |
| 11026 |
if (!fontRef) { |
| 11027 |
warn('fontRef not available'); |
| 11028 |
return errorFont(); |
| 11029 |
} |
| 11030 |
|
| 11031 |
if (this.fontCache.has(fontRef)) { |
| 11032 |
return this.fontCache.get(fontRef); |
| 11033 |
} |
| 11034 |
|
| 11035 |
font = xref.fetchIfRef(fontRef); |
| 11036 |
if (!isDict(font)) { |
| 11037 |
return errorFont(); |
| 11038 |
} |
| 11039 |
|
| 11040 |
// We are holding font.translated references just for fontRef that are not |
| 11041 |
// dictionaries (Dict). See explanation below. |
| 11042 |
if (font.translated) { |
| 11043 |
return font.translated; |
| 11044 |
} |
| 11045 |
|
| 11046 |
var fontCapability = createPromiseCapability(); |
| 11047 |
|
| 11048 |
var preEvaluatedFont = this.preEvaluateFont(font, xref); |
| 11049 |
var descriptor = preEvaluatedFont.descriptor; |
| 11050 |
var fontID = fontRef.num + '_' + fontRef.gen; |
| 11051 |
if (isDict(descriptor)) { |
| 11052 |
if (!descriptor.fontAliases) { |
| 11053 |
descriptor.fontAliases = Object.create(null); |
| 11054 |
} |
| 11055 |
|
| 11056 |
var fontAliases = descriptor.fontAliases; |
| 11057 |
var hash = preEvaluatedFont.hash; |
| 11058 |
if (fontAliases[hash]) { |
| 11059 |
var aliasFontRef = fontAliases[hash].aliasRef; |
| 11060 |
if (aliasFontRef && this.fontCache.has(aliasFontRef)) { |
| 11061 |
this.fontCache.putAlias(fontRef, aliasFontRef); |
| 11062 |
return this.fontCache.get(fontRef); |
| 11063 |
} |
| 11064 |
} |
| 11065 |
|
| 11066 |
if (!fontAliases[hash]) { |
| 11067 |
fontAliases[hash] = { |
| 11068 |
fontID: Font.getFontID() |
| 11069 |
}; |
| 11070 |
} |
| 11071 |
|
| 11072 |
fontAliases[hash].aliasRef = fontRef; |
| 11073 |
fontID = fontAliases[hash].fontID; |
| 11074 |
} |
| 11075 |
|
| 11076 |
// Workaround for bad PDF generators that don't reference fonts |
| 11077 |
// properly, i.e. by not using an object identifier. |
| 11078 |
// Check if the fontRef is a Dict (as opposed to a standard object), |
| 11079 |
// in which case we don't cache the font and instead reference it by |
| 11080 |
// fontName in font.loadedName below. |
| 11081 |
var fontRefIsDict = isDict(fontRef); |
| 11082 |
if (!fontRefIsDict) { |
| 11083 |
this.fontCache.put(fontRef, fontCapability.promise); |
| 11084 |
} |
| 11085 |
|
| 11086 |
// Keep track of each font we translated so the caller can |
| 11087 |
// load them asynchronously before calling display on a page. |
| 11088 |
font.loadedName = 'g_font_' + (fontRefIsDict ? |
| 11089 |
fontName.replace(/\W/g, '') : fontID); |
| 11090 |
|
| 11091 |
font.translated = fontCapability.promise; |
| 11092 |
|
| 11093 |
// TODO move promises into translate font |
| 11094 |
var translatedPromise; |
| 11095 |
try { |
| 11096 |
translatedPromise = Promise.resolve( |
| 11097 |
this.translateFont(preEvaluatedFont, xref)); |
| 11098 |
} catch (e) { |
| 11099 |
translatedPromise = Promise.reject(e); |
| 11100 |
} |
| 11101 |
|
| 11102 |
translatedPromise.then(function (translatedFont) { |
| 11103 |
if (translatedFont.fontType !== undefined) { |
| 11104 |
var xrefFontStats = xref.stats.fontTypes; |
| 11105 |
xrefFontStats[translatedFont.fontType] = true; |
| 11106 |
} |
| 11107 |
|
| 11108 |
fontCapability.resolve(new TranslatedFont(font.loadedName, |
| 11109 |
translatedFont, font)); |
| 11110 |
}, function (reason) { |
| 11111 |
// TODO fontCapability.reject? |
| 11112 |
UnsupportedManager.notify(UNSUPPORTED_FEATURES.font); |
| 11113 |
|
| 11114 |
try { |
| 11115 |
// error, but it's still nice to have font type reported |
| 11116 |
var descriptor = preEvaluatedFont.descriptor; |
| 11117 |
var fontFile3 = descriptor && descriptor.get('FontFile3'); |
| 11118 |
var subtype = fontFile3 && fontFile3.get('Subtype'); |
| 11119 |
var fontType = getFontType(preEvaluatedFont.type, |
| 11120 |
subtype && subtype.name); |
| 11121 |
var xrefFontStats = xref.stats.fontTypes; |
| 11122 |
xrefFontStats[fontType] = true; |
| 11123 |
} catch (ex) { } |
| 11124 |
|
| 11125 |
fontCapability.resolve(new TranslatedFont(font.loadedName, |
| 11126 |
new ErrorFont(reason instanceof Error ? reason.message : reason), |
| 11127 |
font)); |
| 11128 |
}); |
| 11129 |
return fontCapability.promise; |
| 11130 |
}, |
| 11131 |
|
| 11132 |
buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) { |
| 11133 |
var lastIndex = operatorList.length - 1; |
| 11134 |
if (!args) { |
| 11135 |
args = []; |
| 11136 |
} |
| 11137 |
if (lastIndex < 0 || |
| 11138 |
operatorList.fnArray[lastIndex] !== OPS.constructPath) { |
| 11139 |
operatorList.addOp(OPS.constructPath, [[fn], args]); |
| 11140 |
} else { |
| 11141 |
var opArgs = operatorList.argsArray[lastIndex]; |
| 11142 |
opArgs[0].push(fn); |
| 11143 |
Array.prototype.push.apply(opArgs[1], args); |
| 11144 |
} |
| 11145 |
}, |
| 11146 |
|
| 11147 |
handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args, |
| 11148 |
cs, patterns, resources, xref) { |
| 11149 |
// compile tiling patterns |
| 11150 |
var patternName = args[args.length - 1]; |
| 11151 |
// SCN/scn applies patterns along with normal colors |
| 11152 |
var pattern; |
| 11153 |
if (isName(patternName) && |
| 11154 |
(pattern = patterns.get(patternName.name))) { |
| 11155 |
var dict = (isStream(pattern) ? pattern.dict : pattern); |
| 11156 |
var typeNum = dict.get('PatternType'); |
| 11157 |
|
| 11158 |
if (typeNum === TILING_PATTERN) { |
| 11159 |
var color = cs.base ? cs.base.getRgb(args, 0) : null; |
| 11160 |
return this.handleTilingType(fn, color, resources, pattern, |
| 11161 |
dict, operatorList); |
| 11162 |
} else if (typeNum === SHADING_PATTERN) { |
| 11163 |
var shading = dict.get('Shading'); |
| 11164 |
var matrix = dict.get('Matrix'); |
| 11165 |
pattern = Pattern.parseShading(shading, matrix, xref, resources); |
| 11166 |
operatorList.addOp(fn, pattern.getIR()); |
| 11167 |
return Promise.resolve(); |
| 11168 |
} else { |
| 11169 |
return Promise.reject('Unknown PatternType: ' + typeNum); |
| 11170 |
} |
| 11171 |
} |
| 11172 |
// TODO shall we fail here? |
| 11173 |
operatorList.addOp(fn, args); |
| 11174 |
return Promise.resolve(); |
| 11175 |
}, |
| 11176 |
|
| 11177 |
getOperatorList: function PartialEvaluator_getOperatorList(stream, |
| 11178 |
resources, |
| 11179 |
operatorList, |
| 11180 |
initialState) { |
| 11181 |
|
| 11182 |
var self = this; |
| 11183 |
var xref = this.xref; |
| 11184 |
var imageCache = {}; |
| 11185 |
|
| 11186 |
assert(operatorList); |
| 11187 |
|
| 11188 |
resources = (resources || Dict.empty); |
| 11189 |
var xobjs = (resources.get('XObject') || Dict.empty); |
| 11190 |
var patterns = (resources.get('Pattern') || Dict.empty); |
| 11191 |
var stateManager = new StateManager(initialState || new EvalState()); |
| 11192 |
var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); |
| 11193 |
var timeSlotManager = new TimeSlotManager(); |
| 11194 |
|
| 11195 |
return new Promise(function next(resolve, reject) { |
| 11196 |
timeSlotManager.reset(); |
| 11197 |
var stop, operation = {}, i, ii, cs; |
| 11198 |
while (!(stop = timeSlotManager.check())) { |
| 11199 |
// The arguments parsed by read() are used beyond this loop, so we |
| 11200 |
// cannot reuse the same array on each iteration. Therefore we pass |
| 11201 |
// in |null| as the initial value (see the comment on |
| 11202 |
// EvaluatorPreprocessor_read() for why). |
| 11203 |
operation.args = null; |
| 11204 |
if (!(preprocessor.read(operation))) { |
| 11205 |
break; |
| 11206 |
} |
| 11207 |
var args = operation.args; |
| 11208 |
var fn = operation.fn; |
| 11209 |
|
| 11210 |
switch (fn | 0) { |
| 11211 |
case OPS.paintXObject: |
| 11212 |
if (args[0].code) { |
| 11213 |
break; |
| 11214 |
} |
| 11215 |
// eagerly compile XForm objects |
| 11216 |
var name = args[0].name; |
| 11217 |
if (imageCache[name] !== undefined) { |
| 11218 |
operatorList.addOp(imageCache[name].fn, imageCache[name].args); |
| 11219 |
args = null; |
| 11220 |
continue; |
| 11221 |
} |
| 11222 |
|
| 11223 |
var xobj = xobjs.get(name); |
| 11224 |
if (xobj) { |
| 11225 |
assert(isStream(xobj), 'XObject should be a stream'); |
| 11226 |
|
| 11227 |
var type = xobj.dict.get('Subtype'); |
| 11228 |
assert(isName(type), |
| 11229 |
'XObject should have a Name subtype'); |
| 11230 |
|
| 11231 |
if (type.name === 'Form') { |
| 11232 |
stateManager.save(); |
| 11233 |
return self.buildFormXObject(resources, xobj, null, |
| 11234 |
operatorList, |
| 11235 |
stateManager.state.clone()). |
| 11236 |
then(function () { |
| 11237 |
stateManager.restore(); |
| 11238 |
next(resolve, reject); |
| 11239 |
}, reject); |
| 11240 |
} else if (type.name === 'Image') { |
| 11241 |
self.buildPaintImageXObject(resources, xobj, false, |
| 11242 |
operatorList, name, imageCache); |
| 11243 |
args = null; |
| 11244 |
continue; |
| 11245 |
} else if (type.name === 'PS') { |
| 11246 |
// PostScript XObjects are unused when viewing documents. |
| 11247 |
// See section 4.7.1 of Adobe's PDF reference. |
| 11248 |
info('Ignored XObject subtype PS'); |
| 11249 |
continue; |
| 11250 |
} else { |
| 11251 |
error('Unhandled XObject subtype ' + type.name); |
| 11252 |
} |
| 11253 |
} |
| 11254 |
break; |
| 11255 |
case OPS.setFont: |
| 11256 |
var fontSize = args[1]; |
| 11257 |
// eagerly collect all fonts |
| 11258 |
return self.handleSetFont(resources, args, null, |
| 11259 |
operatorList, stateManager.state). |
| 11260 |
then(function (loadedName) { |
| 11261 |
operatorList.addDependency(loadedName); |
| 11262 |
operatorList.addOp(OPS.setFont, [loadedName, fontSize]); |
| 11263 |
next(resolve, reject); |
| 11264 |
}, reject); |
| 11265 |
case OPS.endInlineImage: |
| 11266 |
var cacheKey = args[0].cacheKey; |
| 11267 |
if (cacheKey) { |
| 11268 |
var cacheEntry = imageCache[cacheKey]; |
| 11269 |
if (cacheEntry !== undefined) { |
| 11270 |
operatorList.addOp(cacheEntry.fn, cacheEntry.args); |
| 11271 |
args = null; |
| 11272 |
continue; |
| 11273 |
} |
| 11274 |
} |
| 11275 |
self.buildPaintImageXObject(resources, args[0], true, |
| 11276 |
operatorList, cacheKey, imageCache); |
| 11277 |
args = null; |
| 11278 |
continue; |
| 11279 |
case OPS.showText: |
| 11280 |
args[0] = self.handleText(args[0], stateManager.state); |
| 11281 |
break; |
| 11282 |
case OPS.showSpacedText: |
| 11283 |
var arr = args[0]; |
| 11284 |
var combinedGlyphs = []; |
| 11285 |
var arrLength = arr.length; |
| 11286 |
for (i = 0; i < arrLength; ++i) { |
| 11287 |
var arrItem = arr[i]; |
| 11288 |
if (isString(arrItem)) { |
| 11289 |
Array.prototype.push.apply(combinedGlyphs, |
| 11290 |
self.handleText(arrItem, stateManager.state)); |
| 11291 |
} else if (isNum(arrItem)) { |
| 11292 |
combinedGlyphs.push(arrItem); |
| 11293 |
} |
| 11294 |
} |
| 11295 |
args[0] = combinedGlyphs; |
| 11296 |
fn = OPS.showText; |
| 11297 |
break; |
| 11298 |
case OPS.nextLineShowText: |
| 11299 |
operatorList.addOp(OPS.nextLine); |
| 11300 |
args[0] = self.handleText(args[0], stateManager.state); |
| 11301 |
fn = OPS.showText; |
| 11302 |
break; |
| 11303 |
case OPS.nextLineSetSpacingShowText: |
| 11304 |
operatorList.addOp(OPS.nextLine); |
| 11305 |
operatorList.addOp(OPS.setWordSpacing, [args.shift()]); |
| 11306 |
operatorList.addOp(OPS.setCharSpacing, [args.shift()]); |
| 11307 |
args[0] = self.handleText(args[0], stateManager.state); |
| 11308 |
fn = OPS.showText; |
| 11309 |
break; |
| 11310 |
case OPS.setTextRenderingMode: |
| 11311 |
stateManager.state.textRenderingMode = args[0]; |
| 11312 |
break; |
| 11313 |
|
| 11314 |
case OPS.setFillColorSpace: |
| 11315 |
stateManager.state.fillColorSpace = |
| 11316 |
ColorSpace.parse(args[0], xref, resources); |
| 11317 |
continue; |
| 11318 |
case OPS.setStrokeColorSpace: |
| 11319 |
stateManager.state.strokeColorSpace = |
| 11320 |
ColorSpace.parse(args[0], xref, resources); |
| 11321 |
continue; |
| 11322 |
case OPS.setFillColor: |
| 11323 |
cs = stateManager.state.fillColorSpace; |
| 11324 |
args = cs.getRgb(args, 0); |
| 11325 |
fn = OPS.setFillRGBColor; |
| 11326 |
break; |
| 11327 |
case OPS.setStrokeColor: |
| 11328 |
cs = stateManager.state.strokeColorSpace; |
| 11329 |
args = cs.getRgb(args, 0); |
| 11330 |
fn = OPS.setStrokeRGBColor; |
| 11331 |
break; |
| 11332 |
case OPS.setFillGray: |
| 11333 |
stateManager.state.fillColorSpace = ColorSpace.singletons.gray; |
| 11334 |
args = ColorSpace.singletons.gray.getRgb(args, 0); |
| 11335 |
fn = OPS.setFillRGBColor; |
| 11336 |
break; |
| 11337 |
case OPS.setStrokeGray: |
| 11338 |
stateManager.state.strokeColorSpace = ColorSpace.singletons.gray; |
| 11339 |
args = ColorSpace.singletons.gray.getRgb(args, 0); |
| 11340 |
fn = OPS.setStrokeRGBColor; |
| 11341 |
break; |
| 11342 |
case OPS.setFillCMYKColor: |
| 11343 |
stateManager.state.fillColorSpace = ColorSpace.singletons.cmyk; |
| 11344 |
args = ColorSpace.singletons.cmyk.getRgb(args, 0); |
| 11345 |
fn = OPS.setFillRGBColor; |
| 11346 |
break; |
| 11347 |
case OPS.setStrokeCMYKColor: |
| 11348 |
stateManager.state.strokeColorSpace = ColorSpace.singletons.cmyk; |
| 11349 |
args = ColorSpace.singletons.cmyk.getRgb(args, 0); |
| 11350 |
fn = OPS.setStrokeRGBColor; |
| 11351 |
break; |
| 11352 |
case OPS.setFillRGBColor: |
| 11353 |
stateManager.state.fillColorSpace = ColorSpace.singletons.rgb; |
| 11354 |
args = ColorSpace.singletons.rgb.getRgb(args, 0); |
| 11355 |
break; |
| 11356 |
case OPS.setStrokeRGBColor: |
| 11357 |
stateManager.state.strokeColorSpace = ColorSpace.singletons.rgb; |
| 11358 |
args = ColorSpace.singletons.rgb.getRgb(args, 0); |
| 11359 |
break; |
| 11360 |
case OPS.setFillColorN: |
| 11361 |
cs = stateManager.state.fillColorSpace; |
| 11362 |
if (cs.name === 'Pattern') { |
| 11363 |
return self.handleColorN(operatorList, OPS.setFillColorN, |
| 11364 |
args, cs, patterns, resources, xref).then(function() { |
| 11365 |
next(resolve, reject); |
| 11366 |
}, reject); |
| 11367 |
} |
| 11368 |
args = cs.getRgb(args, 0); |
| 11369 |
fn = OPS.setFillRGBColor; |
| 11370 |
break; |
| 11371 |
case OPS.setStrokeColorN: |
| 11372 |
cs = stateManager.state.strokeColorSpace; |
| 11373 |
if (cs.name === 'Pattern') { |
| 11374 |
return self.handleColorN(operatorList, OPS.setStrokeColorN, |
| 11375 |
args, cs, patterns, resources, xref).then(function() { |
| 11376 |
next(resolve, reject); |
| 11377 |
}, reject); |
| 11378 |
} |
| 11379 |
args = cs.getRgb(args, 0); |
| 11380 |
fn = OPS.setStrokeRGBColor; |
| 11381 |
break; |
| 11382 |
|
| 11383 |
case OPS.shadingFill: |
| 11384 |
var shadingRes = resources.get('Shading'); |
| 11385 |
if (!shadingRes) { |
| 11386 |
error('No shading resource found'); |
| 11387 |
} |
| 11388 |
|
| 11389 |
var shading = shadingRes.get(args[0].name); |
| 11390 |
if (!shading) { |
| 11391 |
error('No shading object found'); |
| 11392 |
} |
| 11393 |
|
| 11394 |
var shadingFill = Pattern.parseShading(shading, null, xref, |
| 11395 |
resources); |
| 11396 |
var patternIR = shadingFill.getIR(); |
| 11397 |
args = [patternIR]; |
| 11398 |
fn = OPS.shadingFill; |
| 11399 |
break; |
| 11400 |
case OPS.setGState: |
| 11401 |
var dictName = args[0]; |
| 11402 |
var extGState = resources.get('ExtGState'); |
| 11403 |
|
| 11404 |
if (!isDict(extGState) || !extGState.has(dictName.name)) { |
| 11405 |
break; |
| 11406 |
} |
| 11407 |
|
| 11408 |
var gState = extGState.get(dictName.name); |
| 11409 |
return self.setGState(resources, gState, operatorList, xref, |
| 11410 |
stateManager).then(function() { |
| 11411 |
next(resolve, reject); |
| 11412 |
}, reject); |
| 11413 |
case OPS.moveTo: |
| 11414 |
case OPS.lineTo: |
| 11415 |
case OPS.curveTo: |
| 11416 |
case OPS.curveTo2: |
| 11417 |
case OPS.curveTo3: |
| 11418 |
case OPS.closePath: |
| 11419 |
self.buildPath(operatorList, fn, args); |
| 11420 |
continue; |
| 11421 |
case OPS.rectangle: |
| 11422 |
self.buildPath(operatorList, fn, args); |
| 11423 |
continue; |
| 11424 |
} |
| 11425 |
operatorList.addOp(fn, args); |
| 11426 |
} |
| 11427 |
if (stop) { |
| 11428 |
deferred.then(function () { |
| 11429 |
next(resolve, reject); |
| 11430 |
}); |
| 11431 |
return; |
| 11432 |
} |
| 11433 |
// Some PDFs don't close all restores inside object/form. |
| 11434 |
// Closing those for them. |
| 11435 |
for (i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) { |
| 11436 |
operatorList.addOp(OPS.restore, []); |
| 11437 |
} |
| 11438 |
resolve(); |
| 11439 |
}); |
| 11440 |
}, |
| 11441 |
|
| 11442 |
getTextContent: function PartialEvaluator_getTextContent(stream, resources, |
| 11443 |
stateManager) { |
| 11444 |
|
| 11445 |
stateManager = (stateManager || new StateManager(new TextState())); |
| 11446 |
|
| 11447 |
var textContent = { |
| 11448 |
items: [], |
| 11449 |
styles: Object.create(null) |
| 11450 |
}; |
| 11451 |
var bidiTexts = textContent.items; |
| 11452 |
var SPACE_FACTOR = 0.3; |
| 11453 |
var MULTI_SPACE_FACTOR = 1.5; |
| 11454 |
|
| 11455 |
var self = this; |
| 11456 |
var xref = this.xref; |
| 11457 |
|
| 11458 |
resources = (xref.fetchIfRef(resources) || Dict.empty); |
| 11459 |
|
| 11460 |
// The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd. |
| 11461 |
var xobjs = null; |
| 11462 |
var xobjsCache = {}; |
| 11463 |
|
| 11464 |
var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); |
| 11465 |
|
| 11466 |
var textState; |
| 11467 |
|
| 11468 |
function newTextChunk() { |
| 11469 |
var font = textState.font; |
| 11470 |
if (!(font.loadedName in textContent.styles)) { |
| 11471 |
textContent.styles[font.loadedName] = { |
| 11472 |
fontFamily: font.fallbackName, |
| 11473 |
ascent: font.ascent, |
| 11474 |
descent: font.descent, |
| 11475 |
vertical: font.vertical |
| 11476 |
}; |
| 11477 |
} |
| 11478 |
return { |
| 11479 |
// |str| is initially an array which we push individual chars to, and |
| 11480 |
// then runBidi() overwrites it with the final string. |
| 11481 |
str: [], |
| 11482 |
dir: null, |
| 11483 |
width: 0, |
| 11484 |
height: 0, |
| 11485 |
transform: null, |
| 11486 |
fontName: font.loadedName |
| 11487 |
}; |
| 11488 |
} |
| 11489 |
|
| 11490 |
function runBidi(textChunk) { |
| 11491 |
var str = textChunk.str.join(''); |
| 11492 |
var bidiResult = PDFJS.bidi(str, -1, textState.font.vertical); |
| 11493 |
textChunk.str = bidiResult.str; |
| 11494 |
textChunk.dir = bidiResult.dir; |
| 11495 |
return textChunk; |
| 11496 |
} |
| 11497 |
|
| 11498 |
function handleSetFont(fontName, fontRef) { |
| 11499 |
return self.loadFont(fontName, fontRef, xref, resources). |
| 11500 |
then(function (translated) { |
| 11501 |
textState.font = translated.font; |
| 11502 |
textState.fontMatrix = translated.font.fontMatrix || |
| 11503 |
FONT_IDENTITY_MATRIX; |
| 11504 |
}); |
| 11505 |
} |
| 11506 |
|
| 11507 |
function buildTextGeometry(chars, textChunk) { |
| 11508 |
var font = textState.font; |
| 11509 |
textChunk = textChunk || newTextChunk(); |
| 11510 |
if (!textChunk.transform) { |
| 11511 |
// 9.4.4 Text Space Details |
| 11512 |
var tsm = [textState.fontSize * textState.textHScale, 0, |
| 11513 |
0, textState.fontSize, |
| 11514 |
0, textState.textRise]; |
| 11515 |
var trm = textChunk.transform = Util.transform(textState.ctm, |
| 11516 |
Util.transform(textState.textMatrix, tsm)); |
| 11517 |
if (!font.vertical) { |
| 11518 |
textChunk.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]); |
| 11519 |
} else { |
| 11520 |
textChunk.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]); |
| 11521 |
} |
| 11522 |
} |
| 11523 |
var width = 0; |
| 11524 |
var height = 0; |
| 11525 |
var glyphs = font.charsToGlyphs(chars); |
| 11526 |
var defaultVMetrics = font.defaultVMetrics; |
| 11527 |
for (var i = 0; i < glyphs.length; i++) { |
| 11528 |
var glyph = glyphs[i]; |
| 11529 |
if (!glyph) { // Previous glyph was a space. |
| 11530 |
width += textState.wordSpacing * textState.textHScale; |
| 11531 |
continue; |
| 11532 |
} |
| 11533 |
var vMetricX = null; |
| 11534 |
var vMetricY = null; |
| 11535 |
var glyphWidth = null; |
| 11536 |
if (font.vertical) { |
| 11537 |
if (glyph.vmetric) { |
| 11538 |
glyphWidth = glyph.vmetric[0]; |
| 11539 |
vMetricX = glyph.vmetric[1]; |
| 11540 |
vMetricY = glyph.vmetric[2]; |
| 11541 |
} else { |
| 11542 |
glyphWidth = glyph.width; |
| 11543 |
vMetricX = glyph.width * 0.5; |
| 11544 |
vMetricY = defaultVMetrics[2]; |
| 11545 |
} |
| 11546 |
} else { |
| 11547 |
glyphWidth = glyph.width; |
| 11548 |
} |
| 11549 |
|
| 11550 |
var glyphUnicode = glyph.unicode; |
| 11551 |
if (NormalizedUnicodes[glyphUnicode] !== undefined) { |
| 11552 |
glyphUnicode = NormalizedUnicodes[glyphUnicode]; |
| 11553 |
} |
| 11554 |
glyphUnicode = reverseIfRtl(glyphUnicode); |
| 11555 |
|
| 11556 |
// The following will calculate the x and y of the individual glyphs. |
| 11557 |
// if (font.vertical) { |
| 11558 |
// tsm[4] -= vMetricX * Math.abs(textState.fontSize) * |
| 11559 |
// textState.fontMatrix[0]; |
| 11560 |
// tsm[5] -= vMetricY * textState.fontSize * |
| 11561 |
// textState.fontMatrix[0]; |
| 11562 |
// } |
| 11563 |
// var trm = Util.transform(textState.textMatrix, tsm); |
| 11564 |
// var pt = Util.applyTransform([trm[4], trm[5]], textState.ctm); |
| 11565 |
// var x = pt[0]; |
| 11566 |
// var y = pt[1]; |
| 11567 |
|
| 11568 |
var tx = 0; |
| 11569 |
var ty = 0; |
| 11570 |
if (!font.vertical) { |
| 11571 |
var w0 = glyphWidth * textState.fontMatrix[0]; |
| 11572 |
tx = (w0 * textState.fontSize + textState.charSpacing) * |
| 11573 |
textState.textHScale; |
| 11574 |
width += tx; |
| 11575 |
} else { |
| 11576 |
var w1 = glyphWidth * textState.fontMatrix[0]; |
| 11577 |
ty = w1 * textState.fontSize + textState.charSpacing; |
| 11578 |
height += ty; |
| 11579 |
} |
| 11580 |
textState.translateTextMatrix(tx, ty); |
| 11581 |
|
| 11582 |
textChunk.str.push(glyphUnicode); |
| 11583 |
} |
| 11584 |
|
| 11585 |
var a = textState.textLineMatrix[0]; |
| 11586 |
var b = textState.textLineMatrix[1]; |
| 11587 |
var scaleLineX = Math.sqrt(a * a + b * b); |
| 11588 |
a = textState.ctm[0]; |
| 11589 |
b = textState.ctm[1]; |
| 11590 |
var scaleCtmX = Math.sqrt(a * a + b * b); |
| 11591 |
if (!font.vertical) { |
| 11592 |
textChunk.width += width * scaleCtmX * scaleLineX; |
| 11593 |
} else { |
| 11594 |
textChunk.height += Math.abs(height * scaleCtmX * scaleLineX); |
| 11595 |
} |
| 11596 |
return textChunk; |
| 11597 |
} |
| 11598 |
|
| 11599 |
var timeSlotManager = new TimeSlotManager(); |
| 11600 |
|
| 11601 |
return new Promise(function next(resolve, reject) { |
| 11602 |
timeSlotManager.reset(); |
| 11603 |
var stop, operation = {}, args = []; |
| 11604 |
while (!(stop = timeSlotManager.check())) { |
| 11605 |
// The arguments parsed by read() are not used beyond this loop, so |
| 11606 |
// we can reuse the same array on every iteration, thus avoiding |
| 11607 |
// unnecessary allocations. |
| 11608 |
args.length = 0; |
| 11609 |
operation.args = args; |
| 11610 |
if (!(preprocessor.read(operation))) { |
| 11611 |
break; |
| 11612 |
} |
| 11613 |
textState = stateManager.state; |
| 11614 |
var fn = operation.fn; |
| 11615 |
args = operation.args; |
| 11616 |
|
| 11617 |
switch (fn | 0) { |
| 11618 |
case OPS.setFont: |
| 11619 |
textState.fontSize = args[1]; |
| 11620 |
return handleSetFont(args[0].name).then(function() { |
| 11621 |
next(resolve, reject); |
| 11622 |
}, reject); |
| 11623 |
case OPS.setTextRise: |
| 11624 |
textState.textRise = args[0]; |
| 11625 |
break; |
| 11626 |
case OPS.setHScale: |
| 11627 |
textState.textHScale = args[0] / 100; |
| 11628 |
break; |
| 11629 |
case OPS.setLeading: |
| 11630 |
textState.leading = args[0]; |
| 11631 |
break; |
| 11632 |
case OPS.moveText: |
| 11633 |
textState.translateTextLineMatrix(args[0], args[1]); |
| 11634 |
textState.textMatrix = textState.textLineMatrix.slice(); |
| 11635 |
break; |
| 11636 |
case OPS.setLeadingMoveText: |
| 11637 |
textState.leading = -args[1]; |
| 11638 |
textState.translateTextLineMatrix(args[0], args[1]); |
| 11639 |
textState.textMatrix = textState.textLineMatrix.slice(); |
| 11640 |
break; |
| 11641 |
case OPS.nextLine: |
| 11642 |
textState.carriageReturn(); |
| 11643 |
break; |
| 11644 |
case OPS.setTextMatrix: |
| 11645 |
textState.setTextMatrix(args[0], args[1], args[2], args[3], |
| 11646 |
args[4], args[5]); |
| 11647 |
textState.setTextLineMatrix(args[0], args[1], args[2], args[3], |
| 11648 |
args[4], args[5]); |
| 11649 |
break; |
| 11650 |
case OPS.setCharSpacing: |
| 11651 |
textState.charSpacing = args[0]; |
| 11652 |
break; |
| 11653 |
case OPS.setWordSpacing: |
| 11654 |
textState.wordSpacing = args[0]; |
| 11655 |
break; |
| 11656 |
case OPS.beginText: |
| 11657 |
textState.textMatrix = IDENTITY_MATRIX.slice(); |
| 11658 |
textState.textLineMatrix = IDENTITY_MATRIX.slice(); |
| 11659 |
break; |
| 11660 |
case OPS.showSpacedText: |
| 11661 |
var items = args[0]; |
| 11662 |
var textChunk = newTextChunk(); |
| 11663 |
var offset; |
| 11664 |
for (var j = 0, jj = items.length; j < jj; j++) { |
| 11665 |
if (typeof items[j] === 'string') { |
| 11666 |
buildTextGeometry(items[j], textChunk); |
| 11667 |
} else { |
| 11668 |
var val = items[j] / 1000; |
| 11669 |
if (!textState.font.vertical) { |
| 11670 |
offset = -val * textState.fontSize * textState.textHScale * |
| 11671 |
textState.textMatrix[0]; |
| 11672 |
textState.translateTextMatrix(offset, 0); |
| 11673 |
textChunk.width += offset; |
| 11674 |
} else { |
| 11675 |
offset = -val * textState.fontSize * |
| 11676 |
textState.textMatrix[3]; |
| 11677 |
textState.translateTextMatrix(0, offset); |
| 11678 |
textChunk.height += offset; |
| 11679 |
} |
| 11680 |
if (items[j] < 0 && textState.font.spaceWidth > 0) { |
| 11681 |
var fakeSpaces = -items[j] / textState.font.spaceWidth; |
| 11682 |
if (fakeSpaces > MULTI_SPACE_FACTOR) { |
| 11683 |
fakeSpaces = Math.round(fakeSpaces); |
| 11684 |
while (fakeSpaces--) { |
| 11685 |
textChunk.str.push(' '); |
| 11686 |
} |
| 11687 |
} else if (fakeSpaces > SPACE_FACTOR) { |
| 11688 |
textChunk.str.push(' '); |
| 11689 |
} |
| 11690 |
} |
| 11691 |
} |
| 11692 |
} |
| 11693 |
bidiTexts.push(runBidi(textChunk)); |
| 11694 |
break; |
| 11695 |
case OPS.showText: |
| 11696 |
bidiTexts.push(runBidi(buildTextGeometry(args[0]))); |
| 11697 |
break; |
| 11698 |
case OPS.nextLineShowText: |
| 11699 |
textState.carriageReturn(); |
| 11700 |
bidiTexts.push(runBidi(buildTextGeometry(args[0]))); |
| 11701 |
break; |
| 11702 |
case OPS.nextLineSetSpacingShowText: |
| 11703 |
textState.wordSpacing = args[0]; |
| 11704 |
textState.charSpacing = args[1]; |
| 11705 |
textState.carriageReturn(); |
| 11706 |
bidiTexts.push(runBidi(buildTextGeometry(args[2]))); |
| 11707 |
break; |
| 11708 |
case OPS.paintXObject: |
| 11709 |
if (args[0].code) { |
| 11710 |
break; |
| 11711 |
} |
| 11712 |
|
| 11713 |
if (!xobjs) { |
| 11714 |
xobjs = (resources.get('XObject') || Dict.empty); |
| 11715 |
} |
| 11716 |
|
| 11717 |
var name = args[0].name; |
| 11718 |
if (xobjsCache.key === name) { |
| 11719 |
if (xobjsCache.texts) { |
| 11720 |
Util.appendToArray(bidiTexts, xobjsCache.texts.items); |
| 11721 |
Util.extendObj(textContent.styles, xobjsCache.texts.styles); |
| 11722 |
} |
| 11723 |
break; |
| 11724 |
} |
| 11725 |
|
| 11726 |
var xobj = xobjs.get(name); |
| 11727 |
if (!xobj) { |
| 11728 |
break; |
| 11729 |
} |
| 11730 |
assert(isStream(xobj), 'XObject should be a stream'); |
| 11731 |
|
| 11732 |
var type = xobj.dict.get('Subtype'); |
| 11733 |
assert(isName(type), |
| 11734 |
'XObject should have a Name subtype'); |
| 11735 |
|
| 11736 |
if ('Form' !== type.name) { |
| 11737 |
xobjsCache.key = name; |
| 11738 |
xobjsCache.texts = null; |
| 11739 |
break; |
| 11740 |
} |
| 11741 |
|
| 11742 |
stateManager.save(); |
| 11743 |
var matrix = xobj.dict.get('Matrix'); |
| 11744 |
if (isArray(matrix) && matrix.length === 6) { |
| 11745 |
stateManager.transform(matrix); |
| 11746 |
} |
| 11747 |
|
| 11748 |
return self.getTextContent(xobj, |
| 11749 |
xobj.dict.get('Resources') || resources, stateManager). |
| 11750 |
then(function (formTextContent) { |
| 11751 |
Util.appendToArray(bidiTexts, formTextContent.items); |
| 11752 |
Util.extendObj(textContent.styles, formTextContent.styles); |
| 11753 |
stateManager.restore(); |
| 11754 |
|
| 11755 |
xobjsCache.key = name; |
| 11756 |
xobjsCache.texts = formTextContent; |
| 11757 |
|
| 11758 |
next(resolve, reject); |
| 11759 |
}, reject); |
| 11760 |
case OPS.setGState: |
| 11761 |
var dictName = args[0]; |
| 11762 |
var extGState = resources.get('ExtGState'); |
| 11763 |
|
| 11764 |
if (!isDict(extGState) || !extGState.has(dictName.name)) { |
| 11765 |
break; |
| 11766 |
} |
| 11767 |
|
| 11768 |
var gsStateMap = extGState.get(dictName.name); |
| 11769 |
var gsStateFont = null; |
| 11770 |
for (var key in gsStateMap) { |
| 11771 |
if (key === 'Font') { |
| 11772 |
assert(!gsStateFont); |
| 11773 |
gsStateFont = gsStateMap[key]; |
| 11774 |
} |
| 11775 |
} |
| 11776 |
if (gsStateFont) { |
| 11777 |
textState.fontSize = gsStateFont[1]; |
| 11778 |
return handleSetFont(gsStateFont[0]).then(function() { |
| 11779 |
next(resolve, reject); |
| 11780 |
}, reject); |
| 11781 |
} |
| 11782 |
break; |
| 11783 |
} // switch |
| 11784 |
} // while |
| 11785 |
if (stop) { |
| 11786 |
deferred.then(function () { |
| 11787 |
next(resolve, reject); |
| 11788 |
}); |
| 11789 |
return; |
| 11790 |
} |
| 11791 |
resolve(textContent); |
| 11792 |
}); |
| 11793 |
}, |
| 11794 |
|
| 11795 |
extractDataStructures: function |
| 11796 |
partialEvaluatorExtractDataStructures(dict, baseDict, |
| 11797 |
xref, properties) { |
| 11798 |
// 9.10.2 |
| 11799 |
var toUnicode = (dict.get('ToUnicode') || baseDict.get('ToUnicode')); |
| 11800 |
if (toUnicode) { |
| 11801 |
properties.toUnicode = this.readToUnicode(toUnicode); |
| 11802 |
} |
| 11803 |
if (properties.composite) { |
| 11804 |
// CIDSystemInfo helps to match CID to glyphs |
| 11805 |
var cidSystemInfo = dict.get('CIDSystemInfo'); |
| 11806 |
if (isDict(cidSystemInfo)) { |
| 11807 |
properties.cidSystemInfo = { |
| 11808 |
registry: cidSystemInfo.get('Registry'), |
| 11809 |
ordering: cidSystemInfo.get('Ordering'), |
| 11810 |
supplement: cidSystemInfo.get('Supplement') |
| 11811 |
}; |
| 11812 |
} |
| 11813 |
|
| 11814 |
var cidToGidMap = dict.get('CIDToGIDMap'); |
| 11815 |
if (isStream(cidToGidMap)) { |
| 11816 |
properties.cidToGidMap = this.readCidToGidMap(cidToGidMap); |
| 11817 |
} |
| 11818 |
} |
| 11819 |
|
| 11820 |
// Based on 9.6.6 of the spec the encoding can come from multiple places |
| 11821 |
// and depends on the font type. The base encoding and differences are |
| 11822 |
// read here, but the encoding that is actually used is chosen during |
| 11823 |
// glyph mapping in the font. |
| 11824 |
// TODO: Loading the built in encoding in the font would allow the |
| 11825 |
// differences to be merged in here not require us to hold on to it. |
| 11826 |
var differences = []; |
| 11827 |
var baseEncodingName = null; |
| 11828 |
var encoding; |
| 11829 |
if (dict.has('Encoding')) { |
| 11830 |
encoding = dict.get('Encoding'); |
| 11831 |
if (isDict(encoding)) { |
| 11832 |
baseEncodingName = encoding.get('BaseEncoding'); |
| 11833 |
baseEncodingName = (isName(baseEncodingName) ? |
| 11834 |
baseEncodingName.name : null); |
| 11835 |
// Load the differences between the base and original |
| 11836 |
if (encoding.has('Differences')) { |
| 11837 |
var diffEncoding = encoding.get('Differences'); |
| 11838 |
var index = 0; |
| 11839 |
for (var j = 0, jj = diffEncoding.length; j < jj; j++) { |
| 11840 |
var data = diffEncoding[j]; |
| 11841 |
if (isNum(data)) { |
| 11842 |
index = data; |
| 11843 |
} else { |
| 11844 |
differences[index++] = data.name; |
| 11845 |
} |
| 11846 |
} |
| 11847 |
} |
| 11848 |
} else if (isName(encoding)) { |
| 11849 |
baseEncodingName = encoding.name; |
| 11850 |
} else { |
| 11851 |
error('Encoding is not a Name nor a Dict'); |
| 11852 |
} |
| 11853 |
// According to table 114 if the encoding is a named encoding it must be |
| 11854 |
// one of these predefined encodings. |
| 11855 |
if ((baseEncodingName !== 'MacRomanEncoding' && |
| 11856 |
baseEncodingName !== 'MacExpertEncoding' && |
| 11857 |
baseEncodingName !== 'WinAnsiEncoding')) { |
| 11858 |
baseEncodingName = null; |
| 11859 |
} |
| 11860 |
} |
| 11861 |
|
| 11862 |
if (baseEncodingName) { |
| 11863 |
properties.defaultEncoding = Encodings[baseEncodingName].slice(); |
| 11864 |
} else { |
| 11865 |
encoding = (properties.type === 'TrueType' ? |
| 11866 |
Encodings.WinAnsiEncoding : Encodings.StandardEncoding); |
| 11867 |
// The Symbolic attribute can be misused for regular fonts |
| 11868 |
// Heuristic: we have to check if the font is a standard one also |
| 11869 |
if (!!(properties.flags & FontFlags.Symbolic)) { |
| 11870 |
encoding = Encodings.MacRomanEncoding; |
| 11871 |
if (!properties.file) { |
| 11872 |
if (/Symbol/i.test(properties.name)) { |
| 11873 |
encoding = Encodings.SymbolSetEncoding; |
| 11874 |
} else if (/Dingbats/i.test(properties.name)) { |
| 11875 |
encoding = Encodings.ZapfDingbatsEncoding; |
| 11876 |
} |
| 11877 |
} |
| 11878 |
} |
| 11879 |
properties.defaultEncoding = encoding; |
| 11880 |
} |
| 11881 |
|
| 11882 |
properties.differences = differences; |
| 11883 |
properties.baseEncodingName = baseEncodingName; |
| 11884 |
properties.dict = dict; |
| 11885 |
}, |
| 11886 |
|
| 11887 |
readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) { |
| 11888 |
var cmap, cmapObj = toUnicode; |
| 11889 |
if (isName(cmapObj)) { |
| 11890 |
cmap = CMapFactory.create(cmapObj, |
| 11891 |
{ url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); |
| 11892 |
if (cmap instanceof IdentityCMap) { |
| 11893 |
return new IdentityToUnicodeMap(0, 0xFFFF); |
| 11894 |
} |
| 11895 |
return new ToUnicodeMap(cmap.getMap()); |
| 11896 |
} else if (isStream(cmapObj)) { |
| 11897 |
cmap = CMapFactory.create(cmapObj, |
| 11898 |
{ url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); |
| 11899 |
if (cmap instanceof IdentityCMap) { |
| 11900 |
return new IdentityToUnicodeMap(0, 0xFFFF); |
| 11901 |
} |
| 11902 |
cmap = cmap.getMap(); |
| 11903 |
// Convert UTF-16BE |
| 11904 |
// NOTE: cmap can be a sparse array, so use forEach instead of for(;;) |
| 11905 |
// to iterate over all keys. |
| 11906 |
cmap.forEach(function(token, i) { |
| 11907 |
var str = []; |
| 11908 |
for (var k = 0; k < token.length; k += 2) { |
| 11909 |
var w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); |
| 11910 |
if ((w1 & 0xF800) !== 0xD800) { // w1 < 0xD800 || w1 > 0xDFFF |
| 11911 |
str.push(w1); |
| 11912 |
continue; |
| 11913 |
} |
| 11914 |
k += 2; |
| 11915 |
var w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); |
| 11916 |
str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000); |
| 11917 |
} |
| 11918 |
cmap[i] = String.fromCharCode.apply(String, str); |
| 11919 |
}); |
| 11920 |
return new ToUnicodeMap(cmap); |
| 11921 |
} |
| 11922 |
return null; |
| 11923 |
}, |
| 11924 |
|
| 11925 |
readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) { |
| 11926 |
// Extract the encoding from the CIDToGIDMap |
| 11927 |
var glyphsData = cidToGidStream.getBytes(); |
| 11928 |
|
| 11929 |
// Set encoding 0 to later verify the font has an encoding |
| 11930 |
var result = []; |
| 11931 |
for (var j = 0, jj = glyphsData.length; j < jj; j++) { |
| 11932 |
var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; |
| 11933 |
if (glyphID === 0) { |
| 11934 |
continue; |
| 11935 |
} |
| 11936 |
var code = j >> 1; |
| 11937 |
result[code] = glyphID; |
| 11938 |
} |
| 11939 |
return result; |
| 11940 |
}, |
| 11941 |
|
| 11942 |
extractWidths: function PartialEvaluator_extractWidths(dict, xref, |
| 11943 |
descriptor, |
| 11944 |
properties) { |
| 11945 |
var glyphsWidths = []; |
| 11946 |
var defaultWidth = 0; |
| 11947 |
var glyphsVMetrics = []; |
| 11948 |
var defaultVMetrics; |
| 11949 |
var i, ii, j, jj, start, code, widths; |
| 11950 |
if (properties.composite) { |
| 11951 |
defaultWidth = dict.get('DW') || 1000; |
| 11952 |
|
| 11953 |
widths = dict.get('W'); |
| 11954 |
if (widths) { |
| 11955 |
for (i = 0, ii = widths.length; i < ii; i++) { |
| 11956 |
start = widths[i++]; |
| 11957 |
code = xref.fetchIfRef(widths[i]); |
| 11958 |
if (isArray(code)) { |
| 11959 |
for (j = 0, jj = code.length; j < jj; j++) { |
| 11960 |
glyphsWidths[start++] = code[j]; |
| 11961 |
} |
| 11962 |
} else { |
| 11963 |
var width = widths[++i]; |
| 11964 |
for (j = start; j <= code; j++) { |
| 11965 |
glyphsWidths[j] = width; |
| 11966 |
} |
| 11967 |
} |
| 11968 |
} |
| 11969 |
} |
| 11970 |
|
| 11971 |
if (properties.vertical) { |
| 11972 |
var vmetrics = (dict.get('DW2') || [880, -1000]); |
| 11973 |
defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]]; |
| 11974 |
vmetrics = dict.get('W2'); |
| 11975 |
if (vmetrics) { |
| 11976 |
for (i = 0, ii = vmetrics.length; i < ii; i++) { |
| 11977 |
start = vmetrics[i++]; |
| 11978 |
code = xref.fetchIfRef(vmetrics[i]); |
| 11979 |
if (isArray(code)) { |
| 11980 |
for (j = 0, jj = code.length; j < jj; j++) { |
| 11981 |
glyphsVMetrics[start++] = [code[j++], code[j++], code[j]]; |
| 11982 |
} |
| 11983 |
} else { |
| 11984 |
var vmetric = [vmetrics[++i], vmetrics[++i], vmetrics[++i]]; |
| 11985 |
for (j = start; j <= code; j++) { |
| 11986 |
glyphsVMetrics[j] = vmetric; |
| 11987 |
} |
| 11988 |
} |
| 11989 |
} |
| 11990 |
} |
| 11991 |
} |
| 11992 |
} else { |
| 11993 |
var firstChar = properties.firstChar; |
| 11994 |
widths = dict.get('Widths'); |
| 11995 |
if (widths) { |
| 11996 |
j = firstChar; |
| 11997 |
for (i = 0, ii = widths.length; i < ii; i++) { |
| 11998 |
glyphsWidths[j++] = widths[i]; |
| 11999 |
} |
| 12000 |
defaultWidth = (parseFloat(descriptor.get('MissingWidth')) || 0); |
| 12001 |
} else { |
| 12002 |
// Trying get the BaseFont metrics (see comment above). |
| 12003 |
var baseFontName = dict.get('BaseFont'); |
| 12004 |
if (isName(baseFontName)) { |
| 12005 |
var metrics = this.getBaseFontMetrics(baseFontName.name); |
| 12006 |
|
| 12007 |
glyphsWidths = this.buildCharCodeToWidth(metrics.widths, |
| 12008 |
properties); |
| 12009 |
defaultWidth = metrics.defaultWidth; |
| 12010 |
} |
| 12011 |
} |
| 12012 |
} |
| 12013 |
|
| 12014 |
// Heuristic: detection of monospace font by checking all non-zero widths |
| 12015 |
var isMonospace = true; |
| 12016 |
var firstWidth = defaultWidth; |
| 12017 |
for (var glyph in glyphsWidths) { |
| 12018 |
var glyphWidth = glyphsWidths[glyph]; |
| 12019 |
if (!glyphWidth) { |
| 12020 |
continue; |
| 12021 |
} |
| 12022 |
if (!firstWidth) { |
| 12023 |
firstWidth = glyphWidth; |
| 12024 |
continue; |
| 12025 |
} |
| 12026 |
if (firstWidth !== glyphWidth) { |
| 12027 |
isMonospace = false; |
| 12028 |
break; |
| 12029 |
} |
| 12030 |
} |
| 12031 |
if (isMonospace) { |
| 12032 |
properties.flags |= FontFlags.FixedPitch; |
| 12033 |
} |
| 12034 |
|
| 12035 |
properties.defaultWidth = defaultWidth; |
| 12036 |
properties.widths = glyphsWidths; |
| 12037 |
properties.defaultVMetrics = defaultVMetrics; |
| 12038 |
properties.vmetrics = glyphsVMetrics; |
| 12039 |
}, |
| 12040 |
|
| 12041 |
isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) { |
| 12042 |
// Simulating descriptor flags attribute |
| 12043 |
var fontNameWoStyle = baseFontName.split('-')[0]; |
| 12044 |
return (fontNameWoStyle in serifFonts) || |
| 12045 |
(fontNameWoStyle.search(/serif/gi) !== -1); |
| 12046 |
}, |
| 12047 |
|
| 12048 |
getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) { |
| 12049 |
var defaultWidth = 0; |
| 12050 |
var widths = []; |
| 12051 |
var monospace = false; |
| 12052 |
var lookupName = (stdFontMap[name] || name); |
| 12053 |
|
| 12054 |
if (!(lookupName in Metrics)) { |
| 12055 |
// Use default fonts for looking up font metrics if the passed |
| 12056 |
// font is not a base font |
| 12057 |
if (this.isSerifFont(name)) { |
| 12058 |
lookupName = 'Times-Roman'; |
| 12059 |
} else { |
| 12060 |
lookupName = 'Helvetica'; |
| 12061 |
} |
| 12062 |
} |
| 12063 |
var glyphWidths = Metrics[lookupName]; |
| 12064 |
|
| 12065 |
if (isNum(glyphWidths)) { |
| 12066 |
defaultWidth = glyphWidths; |
| 12067 |
monospace = true; |
| 12068 |
} else { |
| 12069 |
widths = glyphWidths; |
| 12070 |
} |
| 12071 |
|
| 12072 |
return { |
| 12073 |
defaultWidth: defaultWidth, |
| 12074 |
monospace: monospace, |
| 12075 |
widths: widths |
| 12076 |
}; |
| 12077 |
}, |
| 12078 |
|
| 12079 |
buildCharCodeToWidth: |
| 12080 |
function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName, |
| 12081 |
properties) { |
| 12082 |
var widths = Object.create(null); |
| 12083 |
var differences = properties.differences; |
| 12084 |
var encoding = properties.defaultEncoding; |
| 12085 |
for (var charCode = 0; charCode < 256; charCode++) { |
| 12086 |
if (charCode in differences && |
| 12087 |
widthsByGlyphName[differences[charCode]]) { |
| 12088 |
widths[charCode] = widthsByGlyphName[differences[charCode]]; |
| 12089 |
continue; |
| 12090 |
} |
| 12091 |
if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) { |
| 12092 |
widths[charCode] = widthsByGlyphName[encoding[charCode]]; |
| 12093 |
continue; |
| 12094 |
} |
| 12095 |
} |
| 12096 |
return widths; |
| 12097 |
}, |
| 12098 |
|
| 12099 |
preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict, xref) { |
| 12100 |
var baseDict = dict; |
| 12101 |
var type = dict.get('Subtype'); |
| 12102 |
assert(isName(type), 'invalid font Subtype'); |
| 12103 |
|
| 12104 |
var composite = false; |
| 12105 |
var uint8array; |
| 12106 |
if (type.name === 'Type0') { |
| 12107 |
// If font is a composite |
| 12108 |
// - get the descendant font |
| 12109 |
// - set the type according to the descendant font |
| 12110 |
// - get the FontDescriptor from the descendant font |
| 12111 |
var df = dict.get('DescendantFonts'); |
| 12112 |
if (!df) { |
| 12113 |
error('Descendant fonts are not specified'); |
| 12114 |
} |
| 12115 |
dict = (isArray(df) ? xref.fetchIfRef(df[0]) : df); |
| 12116 |
|
| 12117 |
type = dict.get('Subtype'); |
| 12118 |
assert(isName(type), 'invalid font Subtype'); |
| 12119 |
composite = true; |
| 12120 |
} |
| 12121 |
|
| 12122 |
var descriptor = dict.get('FontDescriptor'); |
| 12123 |
if (descriptor) { |
| 12124 |
var hash = new MurmurHash3_64(); |
| 12125 |
var encoding = baseDict.getRaw('Encoding'); |
| 12126 |
if (isName(encoding)) { |
| 12127 |
hash.update(encoding.name); |
| 12128 |
} else if (isRef(encoding)) { |
| 12129 |
hash.update(encoding.num + '_' + encoding.gen); |
| 12130 |
} else if (isDict(encoding)) { |
| 12131 |
var keys = encoding.getKeys(); |
| 12132 |
for (var i = 0, ii = keys.length; i < ii; i++) { |
| 12133 |
var entry = encoding.getRaw(keys[i]); |
| 12134 |
if (isName(entry)) { |
| 12135 |
hash.update(entry.name); |
| 12136 |
} else if (isRef(entry)) { |
| 12137 |
hash.update(entry.num + '_' + entry.gen); |
| 12138 |
} else if (isArray(entry)) { // 'Differences' entry. |
| 12139 |
// Ideally we should check the contents of the array, but to avoid |
| 12140 |
// parsing it here and then again in |extractDataStructures|, |
| 12141 |
// we only use the array length for now (fixes bug1157493.pdf). |
| 12142 |
hash.update(entry.length.toString()); |
| 12143 |
} |
| 12144 |
} |
| 12145 |
} |
| 12146 |
|
| 12147 |
var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode'); |
| 12148 |
if (isStream(toUnicode)) { |
| 12149 |
var stream = toUnicode.str || toUnicode; |
| 12150 |
uint8array = stream.buffer ? |
| 12151 |
new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : |
| 12152 |
new Uint8Array(stream.bytes.buffer, |
| 12153 |
stream.start, stream.end - stream.start); |
| 12154 |
hash.update(uint8array); |
| 12155 |
|
| 12156 |
} else if (isName(toUnicode)) { |
| 12157 |
hash.update(toUnicode.name); |
| 12158 |
} |
| 12159 |
|
| 12160 |
var widths = dict.get('Widths') || baseDict.get('Widths'); |
| 12161 |
if (widths) { |
| 12162 |
uint8array = new Uint8Array(new Uint32Array(widths).buffer); |
| 12163 |
hash.update(uint8array); |
| 12164 |
} |
| 12165 |
} |
| 12166 |
|
| 12167 |
return { |
| 12168 |
descriptor: descriptor, |
| 12169 |
dict: dict, |
| 12170 |
baseDict: baseDict, |
| 12171 |
composite: composite, |
| 12172 |
type: type.name, |
| 12173 |
hash: hash ? hash.hexdigest() : '' |
| 12174 |
}; |
| 12175 |
}, |
| 12176 |
|
| 12177 |
translateFont: function PartialEvaluator_translateFont(preEvaluatedFont, |
| 12178 |
xref) { |
| 12179 |
var baseDict = preEvaluatedFont.baseDict; |
| 12180 |
var dict = preEvaluatedFont.dict; |
| 12181 |
var composite = preEvaluatedFont.composite; |
| 12182 |
var descriptor = preEvaluatedFont.descriptor; |
| 12183 |
var type = preEvaluatedFont.type; |
| 12184 |
var maxCharIndex = (composite ? 0xFFFF : 0xFF); |
| 12185 |
var properties; |
| 12186 |
|
| 12187 |
if (!descriptor) { |
| 12188 |
if (type === 'Type3') { |
| 12189 |
// FontDescriptor is only required for Type3 fonts when the document |
| 12190 |
// is a tagged pdf. Create a barbebones one to get by. |
| 12191 |
descriptor = new Dict(null); |
| 12192 |
descriptor.set('FontName', Name.get(type)); |
| 12193 |
} else { |
| 12194 |
// Before PDF 1.5 if the font was one of the base 14 fonts, having a |
| 12195 |
// FontDescriptor was not required. |
| 12196 |
// This case is here for compatibility. |
| 12197 |
var baseFontName = dict.get('BaseFont'); |
| 12198 |
if (!isName(baseFontName)) { |
| 12199 |
error('Base font is not specified'); |
| 12200 |
} |
| 12201 |
|
| 12202 |
// Using base font name as a font name. |
| 12203 |
baseFontName = baseFontName.name.replace(/[,_]/g, '-'); |
| 12204 |
var metrics = this.getBaseFontMetrics(baseFontName); |
| 12205 |
|
| 12206 |
// Simulating descriptor flags attribute |
| 12207 |
var fontNameWoStyle = baseFontName.split('-')[0]; |
| 12208 |
var flags = |
| 12209 |
(this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | |
| 12210 |
(metrics.monospace ? FontFlags.FixedPitch : 0) | |
| 12211 |
(symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic : |
| 12212 |
FontFlags.Nonsymbolic); |
| 12213 |
|
| 12214 |
properties = { |
| 12215 |
type: type, |
| 12216 |
name: baseFontName, |
| 12217 |
widths: metrics.widths, |
| 12218 |
defaultWidth: metrics.defaultWidth, |
| 12219 |
flags: flags, |
| 12220 |
firstChar: 0, |
| 12221 |
lastChar: maxCharIndex |
| 12222 |
}; |
| 12223 |
this.extractDataStructures(dict, dict, xref, properties); |
| 12224 |
properties.widths = this.buildCharCodeToWidth(metrics.widths, |
| 12225 |
properties); |
| 12226 |
return new Font(baseFontName, null, properties); |
| 12227 |
} |
| 12228 |
} |
| 12229 |
|
| 12230 |
// According to the spec if 'FontDescriptor' is declared, 'FirstChar', |
| 12231 |
// 'LastChar' and 'Widths' should exist too, but some PDF encoders seem |
| 12232 |
// to ignore this rule when a variant of a standart font is used. |
| 12233 |
// TODO Fill the width array depending on which of the base font this is |
| 12234 |
// a variant. |
| 12235 |
var firstChar = (dict.get('FirstChar') || 0); |
| 12236 |
var lastChar = (dict.get('LastChar') || maxCharIndex); |
| 12237 |
|
| 12238 |
var fontName = descriptor.get('FontName'); |
| 12239 |
var baseFont = dict.get('BaseFont'); |
| 12240 |
// Some bad PDFs have a string as the font name. |
| 12241 |
if (isString(fontName)) { |
| 12242 |
fontName = Name.get(fontName); |
| 12243 |
} |
| 12244 |
if (isString(baseFont)) { |
| 12245 |
baseFont = Name.get(baseFont); |
| 12246 |
} |
| 12247 |
|
| 12248 |
if (type !== 'Type3') { |
| 12249 |
var fontNameStr = fontName && fontName.name; |
| 12250 |
var baseFontStr = baseFont && baseFont.name; |
| 12251 |
if (fontNameStr !== baseFontStr) { |
| 12252 |
info('The FontDescriptor\'s FontName is "' + fontNameStr + |
| 12253 |
'" but should be the same as the Font\'s BaseFont "' + |
| 12254 |
baseFontStr + '"'); |
| 12255 |
// Workaround for cases where e.g. fontNameStr = 'Arial' and |
| 12256 |
// baseFontStr = 'Arial,Bold' (needed when no font file is embedded). |
| 12257 |
if (fontNameStr && baseFontStr && |
| 12258 |
baseFontStr.indexOf(fontNameStr) === 0) { |
| 12259 |
fontName = baseFont; |
| 12260 |
} |
| 12261 |
} |
| 12262 |
} |
| 12263 |
fontName = (fontName || baseFont); |
| 12264 |
|
| 12265 |
assert(isName(fontName), 'invalid font name'); |
| 12266 |
|
| 12267 |
var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3'); |
| 12268 |
if (fontFile) { |
| 12269 |
if (fontFile.dict) { |
| 12270 |
var subtype = fontFile.dict.get('Subtype'); |
| 12271 |
if (subtype) { |
| 12272 |
subtype = subtype.name; |
| 12273 |
} |
| 12274 |
var length1 = fontFile.dict.get('Length1'); |
| 12275 |
var length2 = fontFile.dict.get('Length2'); |
| 12276 |
} |
| 12277 |
} |
| 12278 |
|
| 12279 |
properties = { |
| 12280 |
type: type, |
| 12281 |
name: fontName.name, |
| 12282 |
subtype: subtype, |
| 12283 |
file: fontFile, |
| 12284 |
length1: length1, |
| 12285 |
length2: length2, |
| 12286 |
loadedName: baseDict.loadedName, |
| 12287 |
composite: composite, |
| 12288 |
wideChars: composite, |
| 12289 |
fixedPitch: false, |
| 12290 |
fontMatrix: (dict.get('FontMatrix') || FONT_IDENTITY_MATRIX), |
| 12291 |
firstChar: firstChar || 0, |
| 12292 |
lastChar: (lastChar || maxCharIndex), |
| 12293 |
bbox: descriptor.get('FontBBox'), |
| 12294 |
ascent: descriptor.get('Ascent'), |
| 12295 |
descent: descriptor.get('Descent'), |
| 12296 |
xHeight: descriptor.get('XHeight'), |
| 12297 |
capHeight: descriptor.get('CapHeight'), |
| 12298 |
flags: descriptor.get('Flags'), |
| 12299 |
italicAngle: descriptor.get('ItalicAngle'), |
| 12300 |
coded: false |
| 12301 |
}; |
| 12302 |
|
| 12303 |
if (composite) { |
| 12304 |
var cidEncoding = baseDict.get('Encoding'); |
| 12305 |
if (isName(cidEncoding)) { |
| 12306 |
properties.cidEncoding = cidEncoding.name; |
| 12307 |
} |
| 12308 |
properties.cMap = CMapFactory.create(cidEncoding, |
| 12309 |
{ url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); |
| 12310 |
properties.vertical = properties.cMap.vertical; |
| 12311 |
} |
| 12312 |
this.extractDataStructures(dict, baseDict, xref, properties); |
| 12313 |
this.extractWidths(dict, xref, descriptor, properties); |
| 12314 |
|
| 12315 |
if (type === 'Type3') { |
| 12316 |
properties.isType3Font = true; |
| 12317 |
} |
| 12318 |
|
| 12319 |
return new Font(fontName.name, fontFile, properties); |
| 12320 |
} |
| 12321 |
}; |
| 12322 |
|
| 12323 |
return PartialEvaluator; |
| 12324 |
})(); |
| 12325 |
|
| 12326 |
var TranslatedFont = (function TranslatedFontClosure() { |
| 12327 |
function TranslatedFont(loadedName, font, dict) { |
| 12328 |
this.loadedName = loadedName; |
| 12329 |
this.font = font; |
| 12330 |
this.dict = dict; |
| 12331 |
this.type3Loaded = null; |
| 12332 |
this.sent = false; |
| 12333 |
} |
| 12334 |
TranslatedFont.prototype = { |
| 12335 |
send: function (handler) { |
| 12336 |
if (this.sent) { |
| 12337 |
return; |
| 12338 |
} |
| 12339 |
var fontData = this.font.exportData(); |
| 12340 |
handler.send('commonobj', [ |
| 12341 |
this.loadedName, |
| 12342 |
'Font', |
| 12343 |
fontData |
| 12344 |
]); |
| 12345 |
this.sent = true; |
| 12346 |
}, |
| 12347 |
loadType3Data: function (evaluator, resources, parentOperatorList) { |
| 12348 |
assert(this.font.isType3Font); |
| 12349 |
|
| 12350 |
if (this.type3Loaded) { |
| 12351 |
return this.type3Loaded; |
| 12352 |
} |
| 12353 |
|
| 12354 |
var translatedFont = this.font; |
| 12355 |
var loadCharProcsPromise = Promise.resolve(); |
| 12356 |
var charProcs = this.dict.get('CharProcs').getAll(); |
| 12357 |
var fontResources = this.dict.get('Resources') || resources; |
| 12358 |
var charProcKeys = Object.keys(charProcs); |
| 12359 |
var charProcOperatorList = {}; |
| 12360 |
for (var i = 0, n = charProcKeys.length; i < n; ++i) { |
| 12361 |
loadCharProcsPromise = loadCharProcsPromise.then(function (key) { |
| 12362 |
var glyphStream = charProcs[key]; |
| 12363 |
var operatorList = new OperatorList(); |
| 12364 |
return evaluator.getOperatorList(glyphStream, fontResources, |
| 12365 |
operatorList).then(function () { |
| 12366 |
charProcOperatorList[key] = operatorList.getIR(); |
| 12367 |
|
| 12368 |
// Add the dependencies to the parent operator list so they are |
| 12369 |
// resolved before sub operator list is executed synchronously. |
| 12370 |
parentOperatorList.addDependencies(operatorList.dependencies); |
| 12371 |
}, function (reason) { |
| 12372 |
warn('Type3 font resource \"' + key + '\" is not available'); |
| 12373 |
var operatorList = new OperatorList(); |
| 12374 |
charProcOperatorList[key] = operatorList.getIR(); |
| 12375 |
}); |
| 12376 |
}.bind(this, charProcKeys[i])); |
| 12377 |
} |
| 12378 |
this.type3Loaded = loadCharProcsPromise.then(function () { |
| 12379 |
translatedFont.charProcOperatorList = charProcOperatorList; |
| 12380 |
}); |
| 12381 |
return this.type3Loaded; |
| 12382 |
} |
| 12383 |
}; |
| 12384 |
return TranslatedFont; |
| 12385 |
})(); |
| 12386 |
|
| 12387 |
var OperatorList = (function OperatorListClosure() { |
| 12388 |
var CHUNK_SIZE = 1000; |
| 12389 |
var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size |
| 12390 |
|
| 12391 |
function getTransfers(queue) { |
| 12392 |
var transfers = []; |
| 12393 |
var fnArray = queue.fnArray, argsArray = queue.argsArray; |
| 12394 |
for (var i = 0, ii = queue.length; i < ii; i++) { |
| 12395 |
switch (fnArray[i]) { |
| 12396 |
case OPS.paintInlineImageXObject: |
| 12397 |
case OPS.paintInlineImageXObjectGroup: |
| 12398 |
case OPS.paintImageMaskXObject: |
| 12399 |
var arg = argsArray[i][0]; // first param in imgData |
| 12400 |
if (!arg.cached) { |
| 12401 |
transfers.push(arg.data.buffer); |
| 12402 |
} |
| 12403 |
break; |
| 12404 |
} |
| 12405 |
} |
| 12406 |
return transfers; |
| 12407 |
} |
| 12408 |
|
| 12409 |
function OperatorList(intent, messageHandler, pageIndex) { |
| 12410 |
this.messageHandler = messageHandler; |
| 12411 |
this.fnArray = []; |
| 12412 |
this.argsArray = []; |
| 12413 |
this.dependencies = {}; |
| 12414 |
this.pageIndex = pageIndex; |
| 12415 |
this.intent = intent; |
| 12416 |
} |
| 12417 |
|
| 12418 |
OperatorList.prototype = { |
| 12419 |
get length() { |
| 12420 |
return this.argsArray.length; |
| 12421 |
}, |
| 12422 |
|
| 12423 |
addOp: function(fn, args) { |
| 12424 |
this.fnArray.push(fn); |
| 12425 |
this.argsArray.push(args); |
| 12426 |
if (this.messageHandler) { |
| 12427 |
if (this.fnArray.length >= CHUNK_SIZE) { |
| 12428 |
this.flush(); |
| 12429 |
} else if (this.fnArray.length >= CHUNK_SIZE_ABOUT && |
| 12430 |
(fn === OPS.restore || fn === OPS.endText)) { |
| 12431 |
// heuristic to flush on boundary of restore or endText |
| 12432 |
this.flush(); |
| 12433 |
} |
| 12434 |
} |
| 12435 |
}, |
| 12436 |
|
| 12437 |
addDependency: function(dependency) { |
| 12438 |
if (dependency in this.dependencies) { |
| 12439 |
return; |
| 12440 |
} |
| 12441 |
this.dependencies[dependency] = true; |
| 12442 |
this.addOp(OPS.dependency, [dependency]); |
| 12443 |
}, |
| 12444 |
|
| 12445 |
addDependencies: function(dependencies) { |
| 12446 |
for (var key in dependencies) { |
| 12447 |
this.addDependency(key); |
| 12448 |
} |
| 12449 |
}, |
| 12450 |
|
| 12451 |
addOpList: function(opList) { |
| 12452 |
Util.extendObj(this.dependencies, opList.dependencies); |
| 12453 |
for (var i = 0, ii = opList.length; i < ii; i++) { |
| 12454 |
this.addOp(opList.fnArray[i], opList.argsArray[i]); |
| 12455 |
} |
| 12456 |
}, |
| 12457 |
|
| 12458 |
getIR: function() { |
| 12459 |
return { |
| 12460 |
fnArray: this.fnArray, |
| 12461 |
argsArray: this.argsArray, |
| 12462 |
length: this.length |
| 12463 |
}; |
| 12464 |
}, |
| 12465 |
|
| 12466 |
flush: function(lastChunk) { |
| 12467 |
if (this.intent !== 'oplist') { |
| 12468 |
new QueueOptimizer().optimize(this); |
| 12469 |
} |
| 12470 |
var transfers = getTransfers(this); |
| 12471 |
this.messageHandler.send('RenderPageChunk', { |
| 12472 |
operatorList: { |
| 12473 |
fnArray: this.fnArray, |
| 12474 |
argsArray: this.argsArray, |
| 12475 |
lastChunk: lastChunk, |
| 12476 |
length: this.length |
| 12477 |
}, |
| 12478 |
pageIndex: this.pageIndex, |
| 12479 |
intent: this.intent |
| 12480 |
}, transfers); |
| 12481 |
this.dependencies = {}; |
| 12482 |
this.fnArray.length = 0; |
| 12483 |
this.argsArray.length = 0; |
| 12484 |
} |
| 12485 |
}; |
| 12486 |
|
| 12487 |
return OperatorList; |
| 12488 |
})(); |
| 12489 |
|
| 12490 |
var StateManager = (function StateManagerClosure() { |
| 12491 |
function StateManager(initialState) { |
| 12492 |
this.state = initialState; |
| 12493 |
this.stateStack = []; |
| 12494 |
} |
| 12495 |
StateManager.prototype = { |
| 12496 |
save: function () { |
| 12497 |
var old = this.state; |
| 12498 |
this.stateStack.push(this.state); |
| 12499 |
this.state = old.clone(); |
| 12500 |
}, |
| 12501 |
restore: function () { |
| 12502 |
var prev = this.stateStack.pop(); |
| 12503 |
if (prev) { |
| 12504 |
this.state = prev; |
| 12505 |
} |
| 12506 |
}, |
| 12507 |
transform: function (args) { |
| 12508 |
this.state.ctm = Util.transform(this.state.ctm, args); |
| 12509 |
} |
| 12510 |
}; |
| 12511 |
return StateManager; |
| 12512 |
})(); |
| 12513 |
|
| 12514 |
var TextState = (function TextStateClosure() { |
| 12515 |
function TextState() { |
| 12516 |
this.ctm = new Float32Array(IDENTITY_MATRIX); |
| 12517 |
this.fontSize = 0; |
| 12518 |
this.font = null; |
| 12519 |
this.fontMatrix = FONT_IDENTITY_MATRIX; |
| 12520 |
this.textMatrix = IDENTITY_MATRIX.slice(); |
| 12521 |
this.textLineMatrix = IDENTITY_MATRIX.slice(); |
| 12522 |
this.charSpacing = 0; |
| 12523 |
this.wordSpacing = 0; |
| 12524 |
this.leading = 0; |
| 12525 |
this.textHScale = 1; |
| 12526 |
this.textRise = 0; |
| 12527 |
} |
| 12528 |
|
| 12529 |
TextState.prototype = { |
| 12530 |
setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { |
| 12531 |
var m = this.textMatrix; |
| 12532 |
m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; |
| 12533 |
}, |
| 12534 |
setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { |
| 12535 |
var m = this.textLineMatrix; |
| 12536 |
m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; |
| 12537 |
}, |
| 12538 |
translateTextMatrix: function TextState_translateTextMatrix(x, y) { |
| 12539 |
var m = this.textMatrix; |
| 12540 |
m[4] = m[0] * x + m[2] * y + m[4]; |
| 12541 |
m[5] = m[1] * x + m[3] * y + m[5]; |
| 12542 |
}, |
| 12543 |
translateTextLineMatrix: function TextState_translateTextMatrix(x, y) { |
| 12544 |
var m = this.textLineMatrix; |
| 12545 |
m[4] = m[0] * x + m[2] * y + m[4]; |
| 12546 |
m[5] = m[1] * x + m[3] * y + m[5]; |
| 12547 |
}, |
| 12548 |
calcRenderMatrix: function TextState_calcRendeMatrix(ctm) { |
| 12549 |
// 9.4.4 Text Space Details |
| 12550 |
var tsm = [this.fontSize * this.textHScale, 0, |
| 12551 |
0, this.fontSize, |
| 12552 |
0, this.textRise]; |
| 12553 |
return Util.transform(ctm, Util.transform(this.textMatrix, tsm)); |
| 12554 |
}, |
| 12555 |
carriageReturn: function TextState_carriageReturn() { |
| 12556 |
this.translateTextLineMatrix(0, -this.leading); |
| 12557 |
this.textMatrix = this.textLineMatrix.slice(); |
| 12558 |
}, |
| 12559 |
clone: function TextState_clone() { |
| 12560 |
var clone = Object.create(this); |
| 12561 |
clone.textMatrix = this.textMatrix.slice(); |
| 12562 |
clone.textLineMatrix = this.textLineMatrix.slice(); |
| 12563 |
clone.fontMatrix = this.fontMatrix.slice(); |
| 12564 |
return clone; |
| 12565 |
} |
| 12566 |
}; |
| 12567 |
return TextState; |
| 12568 |
})(); |
| 12569 |
|
| 12570 |
var EvalState = (function EvalStateClosure() { |
| 12571 |
function EvalState() { |
| 12572 |
this.ctm = new Float32Array(IDENTITY_MATRIX); |
| 12573 |
this.font = null; |
| 12574 |
this.textRenderingMode = TextRenderingMode.FILL; |
| 12575 |
this.fillColorSpace = ColorSpace.singletons.gray; |
| 12576 |
this.strokeColorSpace = ColorSpace.singletons.gray; |
| 12577 |
} |
| 12578 |
EvalState.prototype = { |
| 12579 |
clone: function CanvasExtraState_clone() { |
| 12580 |
return Object.create(this); |
| 12581 |
}, |
| 12582 |
}; |
| 12583 |
return EvalState; |
| 12584 |
})(); |
| 12585 |
|
| 12586 |
var EvaluatorPreprocessor = (function EvaluatorPreprocessorClosure() { |
| 12587 |
// Specifies properties for each command |
| 12588 |
// |
| 12589 |
// If variableArgs === true: [0, `numArgs`] expected |
| 12590 |
// If variableArgs === false: exactly `numArgs` expected |
| 12591 |
var OP_MAP = { |
| 12592 |
// Graphic state |
| 12593 |
w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false }, |
| 12594 |
J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false }, |
| 12595 |
j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false }, |
| 12596 |
M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false }, |
| 12597 |
d: { id: OPS.setDash, numArgs: 2, variableArgs: false }, |
| 12598 |
ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false }, |
| 12599 |
i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false }, |
| 12600 |
gs: { id: OPS.setGState, numArgs: 1, variableArgs: false }, |
| 12601 |
q: { id: OPS.save, numArgs: 0, variableArgs: false }, |
| 12602 |
Q: { id: OPS.restore, numArgs: 0, variableArgs: false }, |
| 12603 |
cm: { id: OPS.transform, numArgs: 6, variableArgs: false }, |
| 12604 |
|
| 12605 |
// Path |
| 12606 |
m: { id: OPS.moveTo, numArgs: 2, variableArgs: false }, |
| 12607 |
l: { id: OPS.lineTo, numArgs: 2, variableArgs: false }, |
| 12608 |
c: { id: OPS.curveTo, numArgs: 6, variableArgs: false }, |
| 12609 |
v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false }, |
| 12610 |
y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false }, |
| 12611 |
h: { id: OPS.closePath, numArgs: 0, variableArgs: false }, |
| 12612 |
re: { id: OPS.rectangle, numArgs: 4, variableArgs: false }, |
| 12613 |
S: { id: OPS.stroke, numArgs: 0, variableArgs: false }, |
| 12614 |
s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false }, |
| 12615 |
f: { id: OPS.fill, numArgs: 0, variableArgs: false }, |
| 12616 |
F: { id: OPS.fill, numArgs: 0, variableArgs: false }, |
| 12617 |
'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false }, |
| 12618 |
B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false }, |
| 12619 |
'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false }, |
| 12620 |
b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false }, |
| 12621 |
'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false }, |
| 12622 |
n: { id: OPS.endPath, numArgs: 0, variableArgs: false }, |
| 12623 |
|
| 12624 |
// Clipping |
| 12625 |
W: { id: OPS.clip, numArgs: 0, variableArgs: false }, |
| 12626 |
'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false }, |
| 12627 |
|
| 12628 |
// Text |
| 12629 |
BT: { id: OPS.beginText, numArgs: 0, variableArgs: false }, |
| 12630 |
ET: { id: OPS.endText, numArgs: 0, variableArgs: false }, |
| 12631 |
Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false }, |
| 12632 |
Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false }, |
| 12633 |
Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false }, |
| 12634 |
TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false }, |
| 12635 |
Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false }, |
| 12636 |
Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false }, |
| 12637 |
Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false }, |
| 12638 |
Td: { id: OPS.moveText, numArgs: 2, variableArgs: false }, |
| 12639 |
TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false }, |
| 12640 |
Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false }, |
| 12641 |
'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false }, |
| 12642 |
Tj: { id: OPS.showText, numArgs: 1, variableArgs: false }, |
| 12643 |
TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false }, |
| 12644 |
'\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false }, |
| 12645 |
'"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3, |
| 12646 |
variableArgs: false }, |
| 12647 |
|
| 12648 |
// Type3 fonts |
| 12649 |
d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false }, |
| 12650 |
d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false }, |
| 12651 |
|
| 12652 |
// Color |
| 12653 |
CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false }, |
| 12654 |
cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false }, |
| 12655 |
SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true }, |
| 12656 |
SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true }, |
| 12657 |
sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true }, |
| 12658 |
scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true }, |
| 12659 |
G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false }, |
| 12660 |
g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false }, |
| 12661 |
RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false }, |
| 12662 |
rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false }, |
| 12663 |
K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false }, |
| 12664 |
k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false }, |
| 12665 |
|
| 12666 |
// Shading |
| 12667 |
sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false }, |
| 12668 |
|
| 12669 |
// Images |
| 12670 |
BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false }, |
| 12671 |
ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false }, |
| 12672 |
EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false }, |
| 12673 |
|
| 12674 |
// XObjects |
| 12675 |
Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false }, |
| 12676 |
MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false }, |
| 12677 |
DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false }, |
| 12678 |
BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false }, |
| 12679 |
BDC: { id: OPS.beginMarkedContentProps, numArgs: 2, |
| 12680 |
variableArgs: false }, |
| 12681 |
EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false }, |
| 12682 |
|
| 12683 |
// Compatibility |
| 12684 |
BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false }, |
| 12685 |
EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false }, |
| 12686 |
|
| 12687 |
// (reserved partial commands for the lexer) |
| 12688 |
BM: null, |
| 12689 |
BD: null, |
| 12690 |
'true': null, |
| 12691 |
fa: null, |
| 12692 |
fal: null, |
| 12693 |
fals: null, |
| 12694 |
'false': null, |
| 12695 |
nu: null, |
| 12696 |
nul: null, |
| 12697 |
'null': null |
| 12698 |
}; |
| 12699 |
|
| 12700 |
function EvaluatorPreprocessor(stream, xref, stateManager) { |
| 12701 |
// TODO(mduan): pass array of knownCommands rather than OP_MAP |
| 12702 |
// dictionary |
| 12703 |
this.parser = new Parser(new Lexer(stream, OP_MAP), false, xref); |
| 12704 |
this.stateManager = stateManager; |
| 12705 |
this.nonProcessedArgs = []; |
| 12706 |
} |
| 12707 |
|
| 12708 |
EvaluatorPreprocessor.prototype = { |
| 12709 |
get savedStatesDepth() { |
| 12710 |
return this.stateManager.stateStack.length; |
| 12711 |
}, |
| 12712 |
|
| 12713 |
// |operation| is an object with two fields: |
| 12714 |
// |
| 12715 |
// - |fn| is an out param. |
| 12716 |
// |
| 12717 |
// - |args| is an inout param. On entry, it should have one of two values. |
| 12718 |
// |
| 12719 |
// - An empty array. This indicates that the caller is providing the |
| 12720 |
// array in which the args will be stored in. The caller should use |
| 12721 |
// this value if it can reuse a single array for each call to read(). |
| 12722 |
// |
| 12723 |
// - |null|. This indicates that the caller needs this function to create |
| 12724 |
// the array in which any args are stored in. If there are zero args, |
| 12725 |
// this function will leave |operation.args| as |null| (thus avoiding |
| 12726 |
// allocations that would occur if we used an empty array to represent |
| 12727 |
// zero arguments). Otherwise, it will replace |null| with a new array |
| 12728 |
// containing the arguments. The caller should use this value if it |
| 12729 |
// cannot reuse an array for each call to read(). |
| 12730 |
// |
| 12731 |
// These two modes are present because this function is very hot and so |
| 12732 |
// avoiding allocations where possible is worthwhile. |
| 12733 |
// |
| 12734 |
read: function EvaluatorPreprocessor_read(operation) { |
| 12735 |
var args = operation.args; |
| 12736 |
while (true) { |
| 12737 |
var obj = this.parser.getObj(); |
| 12738 |
if (isCmd(obj)) { |
| 12739 |
var cmd = obj.cmd; |
| 12740 |
// Check that the command is valid |
| 12741 |
var opSpec = OP_MAP[cmd]; |
| 12742 |
if (!opSpec) { |
| 12743 |
warn('Unknown command "' + cmd + '"'); |
| 12744 |
continue; |
| 12745 |
} |
| 12746 |
|
| 12747 |
var fn = opSpec.id; |
| 12748 |
var numArgs = opSpec.numArgs; |
| 12749 |
var argsLength = args !== null ? args.length : 0; |
| 12750 |
|
| 12751 |
if (!opSpec.variableArgs) { |
| 12752 |
// Postscript commands can be nested, e.g. /F2 /GS2 gs 5.711 Tf |
| 12753 |
if (argsLength !== numArgs) { |
| 12754 |
var nonProcessedArgs = this.nonProcessedArgs; |
| 12755 |
while (argsLength > numArgs) { |
| 12756 |
nonProcessedArgs.push(args.shift()); |
| 12757 |
argsLength--; |
| 12758 |
} |
| 12759 |
while (argsLength < numArgs && nonProcessedArgs.length !== 0) { |
| 12760 |
if (!args) { |
| 12761 |
args = []; |
| 12762 |
} |
| 12763 |
args.unshift(nonProcessedArgs.pop()); |
| 12764 |
argsLength++; |
| 12765 |
} |
| 12766 |
} |
| 12767 |
|
| 12768 |
if (argsLength < numArgs) { |
| 12769 |
// If we receive too few args, it's not possible to possible |
| 12770 |
// to execute the command, so skip the command |
| 12771 |
info('Command ' + fn + ': because expected ' + |
| 12772 |
numArgs + ' args, but received ' + argsLength + |
| 12773 |
' args; skipping'); |
| 12774 |
args = null; |
| 12775 |
continue; |
| 12776 |
} |
| 12777 |
} else if (argsLength > numArgs) { |
| 12778 |
info('Command ' + fn + ': expected [0,' + numArgs + |
| 12779 |
'] args, but received ' + argsLength + ' args'); |
| 12780 |
} |
| 12781 |
|
| 12782 |
// TODO figure out how to type-check vararg functions |
| 12783 |
this.preprocessCommand(fn, args); |
| 12784 |
|
| 12785 |
operation.fn = fn; |
| 12786 |
operation.args = args; |
| 12787 |
return true; |
| 12788 |
} else { |
| 12789 |
if (isEOF(obj)) { |
| 12790 |
return false; // no more commands |
| 12791 |
} |
| 12792 |
// argument |
| 12793 |
if (obj !== null) { |
| 12794 |
if (!args) { |
| 12795 |
args = []; |
| 12796 |
} |
| 12797 |
args.push((obj instanceof Dict ? obj.getAll() : obj)); |
| 12798 |
assert(args.length <= 33, 'Too many arguments'); |
| 12799 |
} |
| 12800 |
} |
| 12801 |
} |
| 12802 |
}, |
| 12803 |
|
| 12804 |
preprocessCommand: |
| 12805 |
function EvaluatorPreprocessor_preprocessCommand(fn, args) { |
| 12806 |
switch (fn | 0) { |
| 12807 |
case OPS.save: |
| 12808 |
this.stateManager.save(); |
| 12809 |
break; |
| 12810 |
case OPS.restore: |
| 12811 |
this.stateManager.restore(); |
| 12812 |
break; |
| 12813 |
case OPS.transform: |
| 12814 |
this.stateManager.transform(args); |
| 12815 |
break; |
| 12816 |
} |
| 12817 |
} |
| 12818 |
}; |
| 12819 |
return EvaluatorPreprocessor; |
| 12820 |
})(); |
| 12821 |
|
| 12822 |
var QueueOptimizer = (function QueueOptimizerClosure() { |
| 12823 |
function addState(parentState, pattern, fn) { |
| 12824 |
var state = parentState; |
| 12825 |
for (var i = 0, ii = pattern.length - 1; i < ii; i++) { |
| 12826 |
var item = pattern[i]; |
| 12827 |
state = (state[item] || (state[item] = [])); |
| 12828 |
} |
| 12829 |
state[pattern[pattern.length - 1]] = fn; |
| 12830 |
} |
| 12831 |
|
| 12832 |
function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, |
| 12833 |
argsArray) { |
| 12834 |
// Handles special case of mainly LaTeX documents which use image masks to |
| 12835 |
// draw lines with the current fill style. |
| 12836 |
// 'count' groups of (save, transform, paintImageMaskXObject, restore)+ |
| 12837 |
// have been found at iFirstSave. |
| 12838 |
var iFirstPIMXO = iFirstSave + 2; |
| 12839 |
for (var i = 0; i < count; i++) { |
| 12840 |
var arg = argsArray[iFirstPIMXO + 4 * i]; |
| 12841 |
var imageMask = arg.length === 1 && arg[0]; |
| 12842 |
if (imageMask && imageMask.width === 1 && imageMask.height === 1 && |
| 12843 |
(!imageMask.data.length || |
| 12844 |
(imageMask.data.length === 1 && imageMask.data[0] === 0))) { |
| 12845 |
fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask; |
| 12846 |
continue; |
| 12847 |
} |
| 12848 |
break; |
| 12849 |
} |
| 12850 |
return count - i; |
| 12851 |
} |
| 12852 |
|
| 12853 |
var InitialState = []; |
| 12854 |
|
| 12855 |
// This replaces (save, transform, paintInlineImageXObject, restore)+ |
| 12856 |
// sequences with one |paintInlineImageXObjectGroup| operation. |
| 12857 |
addState(InitialState, |
| 12858 |
[OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore], |
| 12859 |
function foundInlineImageGroup(context) { |
| 12860 |
var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10; |
| 12861 |
var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200; |
| 12862 |
var MAX_WIDTH = 1000; |
| 12863 |
var IMAGE_PADDING = 1; |
| 12864 |
|
| 12865 |
var fnArray = context.fnArray, argsArray = context.argsArray; |
| 12866 |
var curr = context.iCurr; |
| 12867 |
var iFirstSave = curr - 3; |
| 12868 |
var iFirstTransform = curr - 2; |
| 12869 |
var iFirstPIIXO = curr - 1; |
| 12870 |
|
| 12871 |
// Look for the quartets. |
| 12872 |
var i = iFirstSave + 4; |
| 12873 |
var ii = fnArray.length; |
| 12874 |
while (i + 3 < ii) { |
| 12875 |
if (fnArray[i] !== OPS.save || |
| 12876 |
fnArray[i + 1] !== OPS.transform || |
| 12877 |
fnArray[i + 2] !== OPS.paintInlineImageXObject || |
| 12878 |
fnArray[i + 3] !== OPS.restore) { |
| 12879 |
break; // ops don't match |
| 12880 |
} |
| 12881 |
i += 4; |
| 12882 |
} |
| 12883 |
|
| 12884 |
// At this point, i is the index of the first op past the last valid |
| 12885 |
// quartet. |
| 12886 |
var count = Math.min((i - iFirstSave) / 4, |
| 12887 |
MAX_IMAGES_IN_INLINE_IMAGES_BLOCK); |
| 12888 |
if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) { |
| 12889 |
return i; |
| 12890 |
} |
| 12891 |
|
| 12892 |
// assuming that heights of those image is too small (~1 pixel) |
| 12893 |
// packing as much as possible by lines |
| 12894 |
var maxX = 0; |
| 12895 |
var map = [], maxLineHeight = 0; |
| 12896 |
var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING; |
| 12897 |
var q; |
| 12898 |
for (q = 0; q < count; q++) { |
| 12899 |
var transform = argsArray[iFirstTransform + (q << 2)]; |
| 12900 |
var img = argsArray[iFirstPIIXO + (q << 2)][0]; |
| 12901 |
if (currentX + img.width > MAX_WIDTH) { |
| 12902 |
// starting new line |
| 12903 |
maxX = Math.max(maxX, currentX); |
| 12904 |
currentY += maxLineHeight + 2 * IMAGE_PADDING; |
| 12905 |
currentX = 0; |
| 12906 |
maxLineHeight = 0; |
| 12907 |
} |
| 12908 |
map.push({ |
| 12909 |
transform: transform, |
| 12910 |
x: currentX, y: currentY, |
| 12911 |
w: img.width, h: img.height |
| 12912 |
}); |
| 12913 |
currentX += img.width + 2 * IMAGE_PADDING; |
| 12914 |
maxLineHeight = Math.max(maxLineHeight, img.height); |
| 12915 |
} |
| 12916 |
var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING; |
| 12917 |
var imgHeight = currentY + maxLineHeight + IMAGE_PADDING; |
| 12918 |
var imgData = new Uint8Array(imgWidth * imgHeight * 4); |
| 12919 |
var imgRowSize = imgWidth << 2; |
| 12920 |
for (q = 0; q < count; q++) { |
| 12921 |
var data = argsArray[iFirstPIIXO + (q << 2)][0].data; |
| 12922 |
// Copy image by lines and extends pixels into padding. |
| 12923 |
var rowSize = map[q].w << 2; |
| 12924 |
var dataOffset = 0; |
| 12925 |
var offset = (map[q].x + map[q].y * imgWidth) << 2; |
| 12926 |
imgData.set(data.subarray(0, rowSize), offset - imgRowSize); |
| 12927 |
for (var k = 0, kk = map[q].h; k < kk; k++) { |
| 12928 |
imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset); |
| 12929 |
dataOffset += rowSize; |
| 12930 |
offset += imgRowSize; |
| 12931 |
} |
| 12932 |
imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset); |
| 12933 |
while (offset >= 0) { |
| 12934 |
data[offset - 4] = data[offset]; |
| 12935 |
data[offset - 3] = data[offset + 1]; |
| 12936 |
data[offset - 2] = data[offset + 2]; |
| 12937 |
data[offset - 1] = data[offset + 3]; |
| 12938 |
data[offset + rowSize] = data[offset + rowSize - 4]; |
| 12939 |
data[offset + rowSize + 1] = data[offset + rowSize - 3]; |
| 12940 |
data[offset + rowSize + 2] = data[offset + rowSize - 2]; |
| 12941 |
data[offset + rowSize + 3] = data[offset + rowSize - 1]; |
| 12942 |
offset -= imgRowSize; |
| 12943 |
} |
| 12944 |
} |
| 12945 |
|
| 12946 |
// Replace queue items. |
| 12947 |
fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup); |
| 12948 |
argsArray.splice(iFirstSave, count * 4, |
| 12949 |
[{ width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP, |
| 12950 |
data: imgData }, map]); |
| 12951 |
|
| 12952 |
return iFirstSave + 1; |
| 12953 |
}); |
| 12954 |
|
| 12955 |
// This replaces (save, transform, paintImageMaskXObject, restore)+ |
| 12956 |
// sequences with one |paintImageMaskXObjectGroup| or one |
| 12957 |
// |paintImageMaskXObjectRepeat| operation. |
| 12958 |
addState(InitialState, |
| 12959 |
[OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore], |
| 12960 |
function foundImageMaskGroup(context) { |
| 12961 |
var MIN_IMAGES_IN_MASKS_BLOCK = 10; |
| 12962 |
var MAX_IMAGES_IN_MASKS_BLOCK = 100; |
| 12963 |
var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000; |
| 12964 |
|
| 12965 |
var fnArray = context.fnArray, argsArray = context.argsArray; |
| 12966 |
var curr = context.iCurr; |
| 12967 |
var iFirstSave = curr - 3; |
| 12968 |
var iFirstTransform = curr - 2; |
| 12969 |
var iFirstPIMXO = curr - 1; |
| 12970 |
|
| 12971 |
// Look for the quartets. |
| 12972 |
var i = iFirstSave + 4; |
| 12973 |
var ii = fnArray.length; |
| 12974 |
while (i + 3 < ii) { |
| 12975 |
if (fnArray[i] !== OPS.save || |
| 12976 |
fnArray[i + 1] !== OPS.transform || |
| 12977 |
fnArray[i + 2] !== OPS.paintImageMaskXObject || |
| 12978 |
fnArray[i + 3] !== OPS.restore) { |
| 12979 |
break; // ops don't match |
| 12980 |
} |
| 12981 |
i += 4; |
| 12982 |
} |
| 12983 |
|
| 12984 |
// At this point, i is the index of the first op past the last valid |
| 12985 |
// quartet. |
| 12986 |
var count = (i - iFirstSave) / 4; |
| 12987 |
count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, |
| 12988 |
argsArray); |
| 12989 |
if (count < MIN_IMAGES_IN_MASKS_BLOCK) { |
| 12990 |
return i; |
| 12991 |
} |
| 12992 |
|
| 12993 |
var q; |
| 12994 |
var isSameImage = false; |
| 12995 |
var iTransform, transformArgs; |
| 12996 |
var firstPIMXOArg0 = argsArray[iFirstPIMXO][0]; |
| 12997 |
if (argsArray[iFirstTransform][1] === 0 && |
| 12998 |
argsArray[iFirstTransform][2] === 0) { |
| 12999 |
isSameImage = true; |
| 13000 |
var firstTransformArg0 = argsArray[iFirstTransform][0]; |
| 13001 |
var firstTransformArg3 = argsArray[iFirstTransform][3]; |
| 13002 |
iTransform = iFirstTransform + 4; |
| 13003 |
var iPIMXO = iFirstPIMXO + 4; |
| 13004 |
for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) { |
| 13005 |
transformArgs = argsArray[iTransform]; |
| 13006 |
if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || |
| 13007 |
transformArgs[0] !== firstTransformArg0 || |
| 13008 |
transformArgs[1] !== 0 || |
| 13009 |
transformArgs[2] !== 0 || |
| 13010 |
transformArgs[3] !== firstTransformArg3) { |
| 13011 |
if (q < MIN_IMAGES_IN_MASKS_BLOCK) { |
| 13012 |
isSameImage = false; |
| 13013 |
} else { |
| 13014 |
count = q; |
| 13015 |
} |
| 13016 |
break; // different image or transform |
| 13017 |
} |
| 13018 |
} |
| 13019 |
} |
| 13020 |
|
| 13021 |
if (isSameImage) { |
| 13022 |
count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK); |
| 13023 |
var positions = new Float32Array(count * 2); |
| 13024 |
iTransform = iFirstTransform; |
| 13025 |
for (q = 0; q < count; q++, iTransform += 4) { |
| 13026 |
transformArgs = argsArray[iTransform]; |
| 13027 |
positions[(q << 1)] = transformArgs[4]; |
| 13028 |
positions[(q << 1) + 1] = transformArgs[5]; |
| 13029 |
} |
| 13030 |
|
| 13031 |
// Replace queue items. |
| 13032 |
fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat); |
| 13033 |
argsArray.splice(iFirstSave, count * 4, |
| 13034 |
[firstPIMXOArg0, firstTransformArg0, firstTransformArg3, positions]); |
| 13035 |
} else { |
| 13036 |
count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK); |
| 13037 |
var images = []; |
| 13038 |
for (q = 0; q < count; q++) { |
| 13039 |
transformArgs = argsArray[iFirstTransform + (q << 2)]; |
| 13040 |
var maskParams = argsArray[iFirstPIMXO + (q << 2)][0]; |
| 13041 |
images.push({ data: maskParams.data, width: maskParams.width, |
| 13042 |
height: maskParams.height, |
| 13043 |
transform: transformArgs }); |
| 13044 |
} |
| 13045 |
|
| 13046 |
// Replace queue items. |
| 13047 |
fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup); |
| 13048 |
argsArray.splice(iFirstSave, count * 4, [images]); |
| 13049 |
} |
| 13050 |
|
| 13051 |
return iFirstSave + 1; |
| 13052 |
}); |
| 13053 |
|
| 13054 |
// This replaces (save, transform, paintImageXObject, restore)+ sequences |
| 13055 |
// with one paintImageXObjectRepeat operation, if the |transform| and |
| 13056 |
// |paintImageXObjectRepeat| ops are appropriate. |
| 13057 |
addState(InitialState, |
| 13058 |
[OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore], |
| 13059 |
function (context) { |
| 13060 |
var MIN_IMAGES_IN_BLOCK = 3; |
| 13061 |
var MAX_IMAGES_IN_BLOCK = 1000; |
| 13062 |
|
| 13063 |
var fnArray = context.fnArray, argsArray = context.argsArray; |
| 13064 |
var curr = context.iCurr; |
| 13065 |
var iFirstSave = curr - 3; |
| 13066 |
var iFirstTransform = curr - 2; |
| 13067 |
var iFirstPIXO = curr - 1; |
| 13068 |
var iFirstRestore = curr; |
| 13069 |
|
| 13070 |
if (argsArray[iFirstTransform][1] !== 0 || |
| 13071 |
argsArray[iFirstTransform][2] !== 0) { |
| 13072 |
return iFirstRestore + 1; // transform has the wrong form |
| 13073 |
} |
| 13074 |
|
| 13075 |
// Look for the quartets. |
| 13076 |
var firstPIXOArg0 = argsArray[iFirstPIXO][0]; |
| 13077 |
var firstTransformArg0 = argsArray[iFirstTransform][0]; |
| 13078 |
var firstTransformArg3 = argsArray[iFirstTransform][3]; |
| 13079 |
var i = iFirstSave + 4; |
| 13080 |
var ii = fnArray.length; |
| 13081 |
while (i + 3 < ii) { |
| 13082 |
if (fnArray[i] !== OPS.save || |
| 13083 |
fnArray[i + 1] !== OPS.transform || |
| 13084 |
fnArray[i + 2] !== OPS.paintImageXObject || |
| 13085 |
fnArray[i + 3] !== OPS.restore) { |
| 13086 |
break; // ops don't match |
| 13087 |
} |
| 13088 |
if (argsArray[i + 1][0] !== firstTransformArg0 || |
| 13089 |
argsArray[i + 1][1] !== 0 || |
| 13090 |
argsArray[i + 1][2] !== 0 || |
| 13091 |
argsArray[i + 1][3] !== firstTransformArg3) { |
| 13092 |
break; // transforms don't match |
| 13093 |
} |
| 13094 |
if (argsArray[i + 2][0] !== firstPIXOArg0) { |
| 13095 |
break; // images don't match |
| 13096 |
} |
| 13097 |
i += 4; |
| 13098 |
} |
| 13099 |
|
| 13100 |
// At this point, i is the index of the first op past the last valid |
| 13101 |
// quartet. |
| 13102 |
var count = Math.min((i - iFirstSave) / 4, MAX_IMAGES_IN_BLOCK); |
| 13103 |
if (count < MIN_IMAGES_IN_BLOCK) { |
| 13104 |
return i; |
| 13105 |
} |
| 13106 |
|
| 13107 |
// Extract the (x,y) positions from all of the matching transforms. |
| 13108 |
var positions = new Float32Array(count * 2); |
| 13109 |
var iTransform = iFirstTransform; |
| 13110 |
for (var q = 0; q < count; q++, iTransform += 4) { |
| 13111 |
var transformArgs = argsArray[iTransform]; |
| 13112 |
positions[(q << 1)] = transformArgs[4]; |
| 13113 |
positions[(q << 1) + 1] = transformArgs[5]; |
| 13114 |
} |
| 13115 |
|
| 13116 |
// Replace queue items. |
| 13117 |
var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, |
| 13118 |
positions]; |
| 13119 |
fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat); |
| 13120 |
argsArray.splice(iFirstSave, count * 4, args); |
| 13121 |
|
| 13122 |
return iFirstSave + 1; |
| 13123 |
}); |
| 13124 |
|
| 13125 |
// This replaces (beginText, setFont, setTextMatrix, showText, endText)+ |
| 13126 |
// sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+ |
| 13127 |
// sequences, if the font for each one is the same. |
| 13128 |
addState(InitialState, |
| 13129 |
[OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText], |
| 13130 |
function (context) { |
| 13131 |
var MIN_CHARS_IN_BLOCK = 3; |
| 13132 |
var MAX_CHARS_IN_BLOCK = 1000; |
| 13133 |
|
| 13134 |
var fnArray = context.fnArray, argsArray = context.argsArray; |
| 13135 |
var curr = context.iCurr; |
| 13136 |
var iFirstBeginText = curr - 4; |
| 13137 |
var iFirstSetFont = curr - 3; |
| 13138 |
var iFirstSetTextMatrix = curr - 2; |
| 13139 |
var iFirstShowText = curr - 1; |
| 13140 |
var iFirstEndText = curr; |
| 13141 |
|
| 13142 |
// Look for the quintets. |
| 13143 |
var firstSetFontArg0 = argsArray[iFirstSetFont][0]; |
| 13144 |
var firstSetFontArg1 = argsArray[iFirstSetFont][1]; |
| 13145 |
var i = iFirstBeginText + 5; |
| 13146 |
var ii = fnArray.length; |
| 13147 |
while (i + 4 < ii) { |
| 13148 |
if (fnArray[i] !== OPS.beginText || |
| 13149 |
fnArray[i + 1] !== OPS.setFont || |
| 13150 |
fnArray[i + 2] !== OPS.setTextMatrix || |
| 13151 |
fnArray[i + 3] !== OPS.showText || |
| 13152 |
fnArray[i + 4] !== OPS.endText) { |
| 13153 |
break; // ops don't match |
| 13154 |
} |
| 13155 |
if (argsArray[i + 1][0] !== firstSetFontArg0 || |
| 13156 |
argsArray[i + 1][1] !== firstSetFontArg1) { |
| 13157 |
break; // fonts don't match |
| 13158 |
} |
| 13159 |
i += 5; |
| 13160 |
} |
| 13161 |
|
| 13162 |
// At this point, i is the index of the first op past the last valid |
| 13163 |
// quintet. |
| 13164 |
var count = Math.min(((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK); |
| 13165 |
if (count < MIN_CHARS_IN_BLOCK) { |
| 13166 |
return i; |
| 13167 |
} |
| 13168 |
|
| 13169 |
// If the preceding quintet is (<something>, setFont, setTextMatrix, |
| 13170 |
// showText, endText), include that as well. (E.g. <something> might be |
| 13171 |
// |dependency|.) |
| 13172 |
var iFirst = iFirstBeginText; |
| 13173 |
if (iFirstBeginText >= 4 && |
| 13174 |
fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && |
| 13175 |
fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && |
| 13176 |
fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && |
| 13177 |
fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && |
| 13178 |
argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && |
| 13179 |
argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) { |
| 13180 |
count++; |
| 13181 |
iFirst -= 5; |
| 13182 |
} |
| 13183 |
|
| 13184 |
// Remove (endText, beginText, setFont) trios. |
| 13185 |
var iEndText = iFirst + 4; |
| 13186 |
for (var q = 1; q < count; q++) { |
| 13187 |
fnArray.splice(iEndText, 3); |
| 13188 |
argsArray.splice(iEndText, 3); |
| 13189 |
iEndText += 2; |
| 13190 |
} |
| 13191 |
|
| 13192 |
return iEndText + 1; |
| 13193 |
}); |
| 13194 |
|
| 13195 |
function QueueOptimizer() {} |
| 13196 |
|
| 13197 |
QueueOptimizer.prototype = { |
| 13198 |
optimize: function QueueOptimizer_optimize(queue) { |
| 13199 |
var fnArray = queue.fnArray, argsArray = queue.argsArray; |
| 13200 |
var context = { |
| 13201 |
iCurr: 0, |
| 13202 |
fnArray: fnArray, |
| 13203 |
argsArray: argsArray |
| 13204 |
}; |
| 13205 |
var state; |
| 13206 |
var i = 0, ii = fnArray.length; |
| 13207 |
while (i < ii) { |
| 13208 |
state = (state || InitialState)[fnArray[i]]; |
| 13209 |
if (typeof state === 'function') { // we found some handler |
| 13210 |
context.iCurr = i; |
| 13211 |
// state() returns the index of the first non-matching op (if we |
| 13212 |
// didn't match) or the first op past the modified ops (if we did |
| 13213 |
// match and replace). |
| 13214 |
i = state(context); |
| 13215 |
state = undefined; // reset the state machine |
| 13216 |
ii = context.fnArray.length; |
| 13217 |
} else { |
| 13218 |
i++; |
| 13219 |
} |
| 13220 |
} |
| 13221 |
} |
| 13222 |
}; |
| 13223 |
return QueueOptimizer; |
| 13224 |
})(); |
| 13225 |
|
| 13226 |
|
| 13227 |
var BUILT_IN_CMAPS = [ |
| 13228 |
// << Start unicode maps. |
| 13229 |
'Adobe-GB1-UCS2', |
| 13230 |
'Adobe-CNS1-UCS2', |
| 13231 |
'Adobe-Japan1-UCS2', |
| 13232 |
'Adobe-Korea1-UCS2', |
| 13233 |
// >> End unicode maps. |
| 13234 |
'78-EUC-H', |
| 13235 |
'78-EUC-V', |
| 13236 |
'78-H', |
| 13237 |
'78-RKSJ-H', |
| 13238 |
'78-RKSJ-V', |
| 13239 |
'78-V', |
| 13240 |
'78ms-RKSJ-H', |
| 13241 |
'78ms-RKSJ-V', |
| 13242 |
'83pv-RKSJ-H', |
| 13243 |
'90ms-RKSJ-H', |
| 13244 |
'90ms-RKSJ-V', |
| 13245 |
'90msp-RKSJ-H', |
| 13246 |
'90msp-RKSJ-V', |
| 13247 |
'90pv-RKSJ-H', |
| 13248 |
'90pv-RKSJ-V', |
| 13249 |
'Add-H', |
| 13250 |
'Add-RKSJ-H', |
| 13251 |
'Add-RKSJ-V', |
| 13252 |
'Add-V', |
| 13253 |
'Adobe-CNS1-0', |
| 13254 |
'Adobe-CNS1-1', |
| 13255 |
'Adobe-CNS1-2', |
| 13256 |
'Adobe-CNS1-3', |
| 13257 |
'Adobe-CNS1-4', |
| 13258 |
'Adobe-CNS1-5', |
| 13259 |
'Adobe-CNS1-6', |
| 13260 |
'Adobe-GB1-0', |
| 13261 |
'Adobe-GB1-1', |
| 13262 |
'Adobe-GB1-2', |
| 13263 |
'Adobe-GB1-3', |
| 13264 |
'Adobe-GB1-4', |
| 13265 |
'Adobe-GB1-5', |
| 13266 |
'Adobe-Japan1-0', |
| 13267 |
'Adobe-Japan1-1', |
| 13268 |
'Adobe-Japan1-2', |
| 13269 |
'Adobe-Japan1-3', |
| 13270 |
'Adobe-Japan1-4', |
| 13271 |
'Adobe-Japan1-5', |
| 13272 |
'Adobe-Japan1-6', |
| 13273 |
'Adobe-Korea1-0', |
| 13274 |
'Adobe-Korea1-1', |
| 13275 |
'Adobe-Korea1-2', |
| 13276 |
'B5-H', |
| 13277 |
'B5-V', |
| 13278 |
'B5pc-H', |
| 13279 |
'B5pc-V', |
| 13280 |
'CNS-EUC-H', |
| 13281 |
'CNS-EUC-V', |
| 13282 |
'CNS1-H', |
| 13283 |
'CNS1-V', |
| 13284 |
'CNS2-H', |
| 13285 |
'CNS2-V', |
| 13286 |
'ETHK-B5-H', |
| 13287 |
'ETHK-B5-V', |
| 13288 |
'ETen-B5-H', |
| 13289 |
'ETen-B5-V', |
| 13290 |
'ETenms-B5-H', |
| 13291 |
'ETenms-B5-V', |
| 13292 |
'EUC-H', |
| 13293 |
'EUC-V', |
| 13294 |
'Ext-H', |
| 13295 |
'Ext-RKSJ-H', |
| 13296 |
'Ext-RKSJ-V', |
| 13297 |
'Ext-V', |
| 13298 |
'GB-EUC-H', |
| 13299 |
'GB-EUC-V', |
| 13300 |
'GB-H', |
| 13301 |
'GB-V', |
| 13302 |
'GBK-EUC-H', |
| 13303 |
'GBK-EUC-V', |
| 13304 |
'GBK2K-H', |
| 13305 |
'GBK2K-V', |
| 13306 |
'GBKp-EUC-H', |
| 13307 |
'GBKp-EUC-V', |
| 13308 |
'GBT-EUC-H', |
| 13309 |
'GBT-EUC-V', |
| 13310 |
'GBT-H', |
| 13311 |
'GBT-V', |
| 13312 |
'GBTpc-EUC-H', |
| 13313 |
'GBTpc-EUC-V', |
| 13314 |
'GBpc-EUC-H', |
| 13315 |
'GBpc-EUC-V', |
| 13316 |
'H', |
| 13317 |
'HKdla-B5-H', |
| 13318 |
'HKdla-B5-V', |
| 13319 |
'HKdlb-B5-H', |
| 13320 |
'HKdlb-B5-V', |
| 13321 |
'HKgccs-B5-H', |
| 13322 |
'HKgccs-B5-V', |
| 13323 |
'HKm314-B5-H', |
| 13324 |
'HKm314-B5-V', |
| 13325 |
'HKm471-B5-H', |
| 13326 |
'HKm471-B5-V', |
| 13327 |
'HKscs-B5-H', |
| 13328 |
'HKscs-B5-V', |
| 13329 |
'Hankaku', |
| 13330 |
'Hiragana', |
| 13331 |
'KSC-EUC-H', |
| 13332 |
'KSC-EUC-V', |
| 13333 |
'KSC-H', |
| 13334 |
'KSC-Johab-H', |
| 13335 |
'KSC-Johab-V', |
| 13336 |
'KSC-V', |
| 13337 |
'KSCms-UHC-H', |
| 13338 |
'KSCms-UHC-HW-H', |
| 13339 |
'KSCms-UHC-HW-V', |
| 13340 |
'KSCms-UHC-V', |
| 13341 |
'KSCpc-EUC-H', |
| 13342 |
'KSCpc-EUC-V', |
| 13343 |
'Katakana', |
| 13344 |
'NWP-H', |
| 13345 |
'NWP-V', |
| 13346 |
'RKSJ-H', |
| 13347 |
'RKSJ-V', |
| 13348 |
'Roman', |
| 13349 |
'UniCNS-UCS2-H', |
| 13350 |
'UniCNS-UCS2-V', |
| 13351 |
'UniCNS-UTF16-H', |
| 13352 |
'UniCNS-UTF16-V', |
| 13353 |
'UniCNS-UTF32-H', |
| 13354 |
'UniCNS-UTF32-V', |
| 13355 |
'UniCNS-UTF8-H', |
| 13356 |
'UniCNS-UTF8-V', |
| 13357 |
'UniGB-UCS2-H', |
| 13358 |
'UniGB-UCS2-V', |
| 13359 |
'UniGB-UTF16-H', |
| 13360 |
'UniGB-UTF16-V', |
| 13361 |
'UniGB-UTF32-H', |
| 13362 |
'UniGB-UTF32-V', |
| 13363 |
'UniGB-UTF8-H', |
| 13364 |
'UniGB-UTF8-V', |
| 13365 |
'UniJIS-UCS2-H', |
| 13366 |
'UniJIS-UCS2-HW-H', |
| 13367 |
'UniJIS-UCS2-HW-V', |
| 13368 |
'UniJIS-UCS2-V', |
| 13369 |
'UniJIS-UTF16-H', |
| 13370 |
'UniJIS-UTF16-V', |
| 13371 |
'UniJIS-UTF32-H', |
| 13372 |
'UniJIS-UTF32-V', |
| 13373 |
'UniJIS-UTF8-H', |
| 13374 |
'UniJIS-UTF8-V', |
| 13375 |
'UniJIS2004-UTF16-H', |
| 13376 |
'UniJIS2004-UTF16-V', |
| 13377 |
'UniJIS2004-UTF32-H', |
| 13378 |
'UniJIS2004-UTF32-V', |
| 13379 |
'UniJIS2004-UTF8-H', |
| 13380 |
'UniJIS2004-UTF8-V', |
| 13381 |
'UniJISPro-UCS2-HW-V', |
| 13382 |
'UniJISPro-UCS2-V', |
| 13383 |
'UniJISPro-UTF8-V', |
| 13384 |
'UniJISX0213-UTF32-H', |
| 13385 |
'UniJISX0213-UTF32-V', |
| 13386 |
'UniJISX02132004-UTF32-H', |
| 13387 |
'UniJISX02132004-UTF32-V', |
| 13388 |
'UniKS-UCS2-H', |
| 13389 |
'UniKS-UCS2-V', |
| 13390 |
'UniKS-UTF16-H', |
| 13391 |
'UniKS-UTF16-V', |
| 13392 |
'UniKS-UTF32-H', |
| 13393 |
'UniKS-UTF32-V', |
| 13394 |
'UniKS-UTF8-H', |
| 13395 |
'UniKS-UTF8-V', |
| 13396 |
'V', |
| 13397 |
'WP-Symbol']; |
| 13398 |
|
| 13399 |
// CMap, not to be confused with TrueType's cmap. |
| 13400 |
var CMap = (function CMapClosure() { |
| 13401 |
function CMap(builtInCMap) { |
| 13402 |
// Codespace ranges are stored as follows: |
| 13403 |
// [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]] |
| 13404 |
// where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...] |
| 13405 |
this.codespaceRanges = [[], [], [], []]; |
| 13406 |
this.numCodespaceRanges = 0; |
| 13407 |
// Map entries have one of two forms. |
| 13408 |
// - cid chars are 16-bit unsigned integers, stored as integers. |
| 13409 |
// - bf chars are variable-length byte sequences, stored as strings, with |
| 13410 |
// one byte per character. |
| 13411 |
this._map = []; |
| 13412 |
this.name = ''; |
| 13413 |
this.vertical = false; |
| 13414 |
this.useCMap = null; |
| 13415 |
this.builtInCMap = builtInCMap; |
| 13416 |
} |
| 13417 |
CMap.prototype = { |
| 13418 |
addCodespaceRange: function(n, low, high) { |
| 13419 |
this.codespaceRanges[n - 1].push(low, high); |
| 13420 |
this.numCodespaceRanges++; |
| 13421 |
}, |
| 13422 |
|
| 13423 |
mapCidRange: function(low, high, dstLow) { |
| 13424 |
while (low <= high) { |
| 13425 |
this._map[low++] = dstLow++; |
| 13426 |
} |
| 13427 |
}, |
| 13428 |
|
| 13429 |
mapBfRange: function(low, high, dstLow) { |
| 13430 |
var lastByte = dstLow.length - 1; |
| 13431 |
while (low <= high) { |
| 13432 |
this._map[low++] = dstLow; |
| 13433 |
// Only the last byte has to be incremented. |
| 13434 |
dstLow = dstLow.substr(0, lastByte) + |
| 13435 |
String.fromCharCode(dstLow.charCodeAt(lastByte) + 1); |
| 13436 |
} |
| 13437 |
}, |
| 13438 |
|
| 13439 |
mapBfRangeToArray: function(low, high, array) { |
| 13440 |
var i = 0, ii = array.length; |
| 13441 |
while (low <= high && i < ii) { |
| 13442 |
this._map[low] = array[i++]; |
| 13443 |
++low; |
| 13444 |
} |
| 13445 |
}, |
| 13446 |
|
| 13447 |
// This is used for both bf and cid chars. |
| 13448 |
mapOne: function(src, dst) { |
| 13449 |
this._map[src] = dst; |
| 13450 |
}, |
| 13451 |
|
| 13452 |
lookup: function(code) { |
| 13453 |
return this._map[code]; |
| 13454 |
}, |
| 13455 |
|
| 13456 |
contains: function(code) { |
| 13457 |
return this._map[code] !== undefined; |
| 13458 |
}, |
| 13459 |
|
| 13460 |
forEach: function(callback) { |
| 13461 |
// Most maps have fewer than 65536 entries, and for those we use normal |
| 13462 |
// array iteration. But really sparse tables are possible -- e.g. with |
| 13463 |
// indices in the *billions*. For such tables we use for..in, which isn't |
| 13464 |
// ideal because it stringifies the indices for all present elements, but |
| 13465 |
// it does avoid iterating over every undefined entry. |
| 13466 |
var map = this._map; |
| 13467 |
var length = map.length; |
| 13468 |
var i; |
| 13469 |
if (length <= 0x10000) { |
| 13470 |
for (i = 0; i < length; i++) { |
| 13471 |
if (map[i] !== undefined) { |
| 13472 |
callback(i, map[i]); |
| 13473 |
} |
| 13474 |
} |
| 13475 |
} else { |
| 13476 |
for (i in this._map) { |
| 13477 |
callback(i, map[i]); |
| 13478 |
} |
| 13479 |
} |
| 13480 |
}, |
| 13481 |
|
| 13482 |
charCodeOf: function(value) { |
| 13483 |
return this._map.indexOf(value); |
| 13484 |
}, |
| 13485 |
|
| 13486 |
getMap: function() { |
| 13487 |
return this._map; |
| 13488 |
}, |
| 13489 |
|
| 13490 |
readCharCode: function(str, offset, out) { |
| 13491 |
var c = 0; |
| 13492 |
var codespaceRanges = this.codespaceRanges; |
| 13493 |
var codespaceRangesLen = this.codespaceRanges.length; |
| 13494 |
// 9.7.6.2 CMap Mapping |
| 13495 |
// The code length is at most 4. |
| 13496 |
for (var n = 0; n < codespaceRangesLen; n++) { |
| 13497 |
c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0; |
| 13498 |
// Check each codespace range to see if it falls within. |
| 13499 |
var codespaceRange = codespaceRanges[n]; |
| 13500 |
for (var k = 0, kk = codespaceRange.length; k < kk;) { |
| 13501 |
var low = codespaceRange[k++]; |
| 13502 |
var high = codespaceRange[k++]; |
| 13503 |
if (c >= low && c <= high) { |
| 13504 |
out.charcode = c; |
| 13505 |
out.length = n + 1; |
| 13506 |
return; |
| 13507 |
} |
| 13508 |
} |
| 13509 |
} |
| 13510 |
out.charcode = 0; |
| 13511 |
out.length = 1; |
| 13512 |
}, |
| 13513 |
|
| 13514 |
get isIdentityCMap() { |
| 13515 |
if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) { |
| 13516 |
return false; |
| 13517 |
} |
| 13518 |
if (this._map.length !== 0x10000) { |
| 13519 |
return false; |
| 13520 |
} |
| 13521 |
for (var i = 0; i < 0x10000; i++) { |
| 13522 |
if (this._map[i] !== i) { |
| 13523 |
return false; |
| 13524 |
} |
| 13525 |
} |
| 13526 |
return true; |
| 13527 |
} |
| 13528 |
}; |
| 13529 |
return CMap; |
| 13530 |
})(); |
| 13531 |
|
| 13532 |
// A special case of CMap, where the _map array implicitly has a length of |
| 13533 |
// 65536 and each element is equal to its index. |
| 13534 |
var IdentityCMap = (function IdentityCMapClosure() { |
| 13535 |
function IdentityCMap(vertical, n) { |
| 13536 |
CMap.call(this); |
| 13537 |
this.vertical = vertical; |
| 13538 |
this.addCodespaceRange(n, 0, 0xffff); |
| 13539 |
} |
| 13540 |
Util.inherit(IdentityCMap, CMap, {}); |
| 13541 |
|
| 13542 |
IdentityCMap.prototype = { |
| 13543 |
addCodespaceRange: CMap.prototype.addCodespaceRange, |
| 13544 |
|
| 13545 |
mapCidRange: function(low, high, dstLow) { |
| 13546 |
error('should not call mapCidRange'); |
| 13547 |
}, |
| 13548 |
|
| 13549 |
mapBfRange: function(low, high, dstLow) { |
| 13550 |
error('should not call mapBfRange'); |
| 13551 |
}, |
| 13552 |
|
| 13553 |
mapBfRangeToArray: function(low, high, array) { |
| 13554 |
error('should not call mapBfRangeToArray'); |
| 13555 |
}, |
| 13556 |
|
| 13557 |
mapOne: function(src, dst) { |
| 13558 |
error('should not call mapCidOne'); |
| 13559 |
}, |
| 13560 |
|
| 13561 |
lookup: function(code) { |
| 13562 |
return (isInt(code) && code <= 0xffff) ? code : undefined; |
| 13563 |
}, |
| 13564 |
|
| 13565 |
contains: function(code) { |
| 13566 |
return isInt(code) && code <= 0xffff; |
| 13567 |
}, |
| 13568 |
|
| 13569 |
forEach: function(callback) { |
| 13570 |
for (var i = 0; i <= 0xffff; i++) { |
| 13571 |
callback(i, i); |
| 13572 |
} |
| 13573 |
}, |
| 13574 |
|
| 13575 |
charCodeOf: function(value) { |
| 13576 |
return (isInt(value) && value <= 0xffff) ? value : -1; |
| 13577 |
}, |
| 13578 |
|
| 13579 |
getMap: function() { |
| 13580 |
// Sometimes identity maps must be instantiated, but it's rare. |
| 13581 |
var map = new Array(0x10000); |
| 13582 |
for (var i = 0; i <= 0xffff; i++) { |
| 13583 |
map[i] = i; |
| 13584 |
} |
| 13585 |
return map; |
| 13586 |
}, |
| 13587 |
|
| 13588 |
readCharCode: CMap.prototype.readCharCode, |
| 13589 |
|
| 13590 |
get isIdentityCMap() { |
| 13591 |
error('should not access .isIdentityCMap'); |
| 13592 |
} |
| 13593 |
}; |
| 13594 |
|
| 13595 |
return IdentityCMap; |
| 13596 |
})(); |
| 13597 |
|
| 13598 |
var BinaryCMapReader = (function BinaryCMapReaderClosure() { |
| 13599 |
function fetchBinaryData(url) { |
| 13600 |
var nonBinaryRequest = PDFJS.disableWorker; |
| 13601 |
var request = new XMLHttpRequest(); |
| 13602 |
request.open('GET', url, false); |
| 13603 |
if (!nonBinaryRequest) { |
| 13604 |
try { |
| 13605 |
request.responseType = 'arraybuffer'; |
| 13606 |
nonBinaryRequest = request.responseType !== 'arraybuffer'; |
| 13607 |
} catch (e) { |
| 13608 |
nonBinaryRequest = true; |
| 13609 |
} |
| 13610 |
} |
| 13611 |
if (nonBinaryRequest && request.overrideMimeType) { |
| 13612 |
request.overrideMimeType('text/plain; charset=x-user-defined'); |
| 13613 |
} |
| 13614 |
request.send(null); |
| 13615 |
if (nonBinaryRequest ? !request.responseText : !request.response) { |
| 13616 |
error('Unable to get binary cMap at: ' + url); |
| 13617 |
} |
| 13618 |
if (nonBinaryRequest) { |
| 13619 |
var data = Array.prototype.map.call(request.responseText, function (ch) { |
| 13620 |
return ch.charCodeAt(0) & 255; |
| 13621 |
}); |
| 13622 |
return new Uint8Array(data); |
| 13623 |
} |
| 13624 |
return new Uint8Array(request.response); |
| 13625 |
} |
| 13626 |
|
| 13627 |
function hexToInt(a, size) { |
| 13628 |
var n = 0; |
| 13629 |
for (var i = 0; i <= size; i++) { |
| 13630 |
n = (n << 8) | a[i]; |
| 13631 |
} |
| 13632 |
return n >>> 0; |
| 13633 |
} |
| 13634 |
|
| 13635 |
function hexToStr(a, size) { |
| 13636 |
// This code is hot. Special-case some common values to avoid creating an |
| 13637 |
// object with subarray(). |
| 13638 |
if (size === 1) { |
| 13639 |
return String.fromCharCode(a[0], a[1]); |
| 13640 |
} |
| 13641 |
if (size === 3) { |
| 13642 |
return String.fromCharCode(a[0], a[1], a[2], a[3]); |
| 13643 |
} |
| 13644 |
return String.fromCharCode.apply(null, a.subarray(0, size + 1)); |
| 13645 |
} |
| 13646 |
|
| 13647 |
function addHex(a, b, size) { |
| 13648 |
var c = 0; |
| 13649 |
for (var i = size; i >= 0; i--) { |
| 13650 |
c += a[i] + b[i]; |
| 13651 |
a[i] = c & 255; |
| 13652 |
c >>= 8; |
| 13653 |
} |
| 13654 |
} |
| 13655 |
|
| 13656 |
function incHex(a, size) { |
| 13657 |
var c = 1; |
| 13658 |
for (var i = size; i >= 0 && c > 0; i--) { |
| 13659 |
c += a[i]; |
| 13660 |
a[i] = c & 255; |
| 13661 |
c >>= 8; |
| 13662 |
} |
| 13663 |
} |
| 13664 |
|
| 13665 |
var MAX_NUM_SIZE = 16; |
| 13666 |
var MAX_ENCODED_NUM_SIZE = 19; // ceil(MAX_NUM_SIZE * 7 / 8) |
| 13667 |
|
| 13668 |
function BinaryCMapStream(data) { |
| 13669 |
this.buffer = data; |
| 13670 |
this.pos = 0; |
| 13671 |
this.end = data.length; |
| 13672 |
this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE); |
| 13673 |
} |
| 13674 |
|
| 13675 |
BinaryCMapStream.prototype = { |
| 13676 |
readByte: function () { |
| 13677 |
if (this.pos >= this.end) { |
| 13678 |
return -1; |
| 13679 |
} |
| 13680 |
return this.buffer[this.pos++]; |
| 13681 |
}, |
| 13682 |
readNumber: function () { |
| 13683 |
var n = 0; |
| 13684 |
var last; |
| 13685 |
do { |
| 13686 |
var b = this.readByte(); |
| 13687 |
if (b < 0) { |
| 13688 |
error('unexpected EOF in bcmap'); |
| 13689 |
} |
| 13690 |
last = !(b & 0x80); |
| 13691 |
n = (n << 7) | (b & 0x7F); |
| 13692 |
} while (!last); |
| 13693 |
return n; |
| 13694 |
}, |
| 13695 |
readSigned: function () { |
| 13696 |
var n = this.readNumber(); |
| 13697 |
return (n & 1) ? ~(n >>> 1) : n >>> 1; |
| 13698 |
}, |
| 13699 |
readHex: function (num, size) { |
| 13700 |
num.set(this.buffer.subarray(this.pos, |
| 13701 |
this.pos + size + 1)); |
| 13702 |
this.pos += size + 1; |
| 13703 |
}, |
| 13704 |
readHexNumber: function (num, size) { |
| 13705 |
var last; |
| 13706 |
var stack = this.tmpBuf, sp = 0; |
| 13707 |
do { |
| 13708 |
var b = this.readByte(); |
| 13709 |
if (b < 0) { |
| 13710 |
error('unexpected EOF in bcmap'); |
| 13711 |
} |
| 13712 |
last = !(b & 0x80); |
| 13713 |
stack[sp++] = b & 0x7F; |
| 13714 |
} while (!last); |
| 13715 |
var i = size, buffer = 0, bufferSize = 0; |
| 13716 |
while (i >= 0) { |
| 13717 |
while (bufferSize < 8 && stack.length > 0) { |
| 13718 |
buffer = (stack[--sp] << bufferSize) | buffer; |
| 13719 |
bufferSize += 7; |
| 13720 |
} |
| 13721 |
num[i] = buffer & 255; |
| 13722 |
i--; |
| 13723 |
buffer >>= 8; |
| 13724 |
bufferSize -= 8; |
| 13725 |
} |
| 13726 |
}, |
| 13727 |
readHexSigned: function (num, size) { |
| 13728 |
this.readHexNumber(num, size); |
| 13729 |
var sign = num[size] & 1 ? 255 : 0; |
| 13730 |
var c = 0; |
| 13731 |
for (var i = 0; i <= size; i++) { |
| 13732 |
c = ((c & 1) << 8) | num[i]; |
| 13733 |
num[i] = (c >> 1) ^ sign; |
| 13734 |
} |
| 13735 |
}, |
| 13736 |
readString: function () { |
| 13737 |
var len = this.readNumber(); |
| 13738 |
var s = ''; |
| 13739 |
for (var i = 0; i < len; i++) { |
| 13740 |
s += String.fromCharCode(this.readNumber()); |
| 13741 |
} |
| 13742 |
return s; |
| 13743 |
} |
| 13744 |
}; |
| 13745 |
|
| 13746 |
function processBinaryCMap(url, cMap, extend) { |
| 13747 |
var data = fetchBinaryData(url); |
| 13748 |
var stream = new BinaryCMapStream(data); |
| 13749 |
|
| 13750 |
var header = stream.readByte(); |
| 13751 |
cMap.vertical = !!(header & 1); |
| 13752 |
|
| 13753 |
var useCMap = null; |
| 13754 |
var start = new Uint8Array(MAX_NUM_SIZE); |
| 13755 |
var end = new Uint8Array(MAX_NUM_SIZE); |
| 13756 |
var char = new Uint8Array(MAX_NUM_SIZE); |
| 13757 |
var charCode = new Uint8Array(MAX_NUM_SIZE); |
| 13758 |
var tmp = new Uint8Array(MAX_NUM_SIZE); |
| 13759 |
var code; |
| 13760 |
|
| 13761 |
var b; |
| 13762 |
while ((b = stream.readByte()) >= 0) { |
| 13763 |
var type = b >> 5; |
| 13764 |
if (type === 7) { // metadata, e.g. comment or usecmap |
| 13765 |
switch (b & 0x1F) { |
| 13766 |
case 0: |
| 13767 |
stream.readString(); // skipping comment |
| 13768 |
break; |
| 13769 |
case 1: |
| 13770 |
useCMap = stream.readString(); |
| 13771 |
break; |
| 13772 |
} |
| 13773 |
continue; |
| 13774 |
} |
| 13775 |
var sequence = !!(b & 0x10); |
| 13776 |
var dataSize = b & 15; |
| 13777 |
|
| 13778 |
assert(dataSize + 1 <= MAX_NUM_SIZE); |
| 13779 |
|
| 13780 |
var ucs2DataSize = 1; |
| 13781 |
var subitemsCount = stream.readNumber(); |
| 13782 |
var i; |
| 13783 |
switch (type) { |
| 13784 |
case 0: // codespacerange |
| 13785 |
stream.readHex(start, dataSize); |
| 13786 |
stream.readHexNumber(end, dataSize); |
| 13787 |
addHex(end, start, dataSize); |
| 13788 |
cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), |
| 13789 |
hexToInt(end, dataSize)); |
| 13790 |
for (i = 1; i < subitemsCount; i++) { |
| 13791 |
incHex(end, dataSize); |
| 13792 |
stream.readHexNumber(start, dataSize); |
| 13793 |
addHex(start, end, dataSize); |
| 13794 |
stream.readHexNumber(end, dataSize); |
| 13795 |
addHex(end, start, dataSize); |
| 13796 |
cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), |
| 13797 |
hexToInt(end, dataSize)); |
| 13798 |
} |
| 13799 |
break; |
| 13800 |
case 1: // notdefrange |
| 13801 |
stream.readHex(start, dataSize); |
| 13802 |
stream.readHexNumber(end, dataSize); |
| 13803 |
addHex(end, start, dataSize); |
| 13804 |
code = stream.readNumber(); |
| 13805 |
// undefined range, skipping |
| 13806 |
for (i = 1; i < subitemsCount; i++) { |
| 13807 |
incHex(end, dataSize); |
| 13808 |
stream.readHexNumber(start, dataSize); |
| 13809 |
addHex(start, end, dataSize); |
| 13810 |
stream.readHexNumber(end, dataSize); |
| 13811 |
addHex(end, start, dataSize); |
| 13812 |
code = stream.readNumber(); |
| 13813 |
// nop |
| 13814 |
} |
| 13815 |
break; |
| 13816 |
case 2: // cidchar |
| 13817 |
stream.readHex(char, dataSize); |
| 13818 |
code = stream.readNumber(); |
| 13819 |
cMap.mapOne(hexToInt(char, dataSize), code); |
| 13820 |
for (i = 1; i < subitemsCount; i++) { |
| 13821 |
incHex(char, dataSize); |
| 13822 |
if (!sequence) { |
| 13823 |
stream.readHexNumber(tmp, dataSize); |
| 13824 |
addHex(char, tmp, dataSize); |
| 13825 |
} |
| 13826 |
code = stream.readSigned() + (code + 1); |
| 13827 |
cMap.mapOne(hexToInt(char, dataSize), code); |
| 13828 |
} |
| 13829 |
break; |
| 13830 |
case 3: // cidrange |
| 13831 |
stream.readHex(start, dataSize); |
| 13832 |
stream.readHexNumber(end, dataSize); |
| 13833 |
addHex(end, start, dataSize); |
| 13834 |
code = stream.readNumber(); |
| 13835 |
cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), |
| 13836 |
code); |
| 13837 |
for (i = 1; i < subitemsCount; i++) { |
| 13838 |
incHex(end, dataSize); |
| 13839 |
if (!sequence) { |
| 13840 |
stream.readHexNumber(start, dataSize); |
| 13841 |
addHex(start, end, dataSize); |
| 13842 |
} else { |
| 13843 |
start.set(end); |
| 13844 |
} |
| 13845 |
stream.readHexNumber(end, dataSize); |
| 13846 |
addHex(end, start, dataSize); |
| 13847 |
code = stream.readNumber(); |
| 13848 |
cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), |
| 13849 |
code); |
| 13850 |
} |
| 13851 |
break; |
| 13852 |
case 4: // bfchar |
| 13853 |
stream.readHex(char, ucs2DataSize); |
| 13854 |
stream.readHex(charCode, dataSize); |
| 13855 |
cMap.mapOne(hexToInt(char, ucs2DataSize), |
| 13856 |
hexToStr(charCode, dataSize)); |
| 13857 |
for (i = 1; i < subitemsCount; i++) { |
| 13858 |
incHex(char, ucs2DataSize); |
| 13859 |
if (!sequence) { |
| 13860 |
stream.readHexNumber(tmp, ucs2DataSize); |
| 13861 |
addHex(char, tmp, ucs2DataSize); |
| 13862 |
} |
| 13863 |
incHex(charCode, dataSize); |
| 13864 |
stream.readHexSigned(tmp, dataSize); |
| 13865 |
addHex(charCode, tmp, dataSize); |
| 13866 |
cMap.mapOne(hexToInt(char, ucs2DataSize), |
| 13867 |
hexToStr(charCode, dataSize)); |
| 13868 |
} |
| 13869 |
break; |
| 13870 |
case 5: // bfrange |
| 13871 |
stream.readHex(start, ucs2DataSize); |
| 13872 |
stream.readHexNumber(end, ucs2DataSize); |
| 13873 |
addHex(end, start, ucs2DataSize); |
| 13874 |
stream.readHex(charCode, dataSize); |
| 13875 |
cMap.mapBfRange(hexToInt(start, ucs2DataSize), |
| 13876 |
hexToInt(end, ucs2DataSize), |
| 13877 |
hexToStr(charCode, dataSize)); |
| 13878 |
for (i = 1; i < subitemsCount; i++) { |
| 13879 |
incHex(end, ucs2DataSize); |
| 13880 |
if (!sequence) { |
| 13881 |
stream.readHexNumber(start, ucs2DataSize); |
| 13882 |
addHex(start, end, ucs2DataSize); |
| 13883 |
} else { |
| 13884 |
start.set(end); |
| 13885 |
} |
| 13886 |
stream.readHexNumber(end, ucs2DataSize); |
| 13887 |
addHex(end, start, ucs2DataSize); |
| 13888 |
stream.readHex(charCode, dataSize); |
| 13889 |
cMap.mapBfRange(hexToInt(start, ucs2DataSize), |
| 13890 |
hexToInt(end, ucs2DataSize), |
| 13891 |
hexToStr(charCode, dataSize)); |
| 13892 |
} |
| 13893 |
break; |
| 13894 |
default: |
| 13895 |
error('Unknown type: ' + type); |
| 13896 |
break; |
| 13897 |
} |
| 13898 |
} |
| 13899 |
|
| 13900 |
if (useCMap) { |
| 13901 |
extend(useCMap); |
| 13902 |
} |
| 13903 |
return cMap; |
| 13904 |
} |
| 13905 |
|
| 13906 |
function BinaryCMapReader() {} |
| 13907 |
|
| 13908 |
BinaryCMapReader.prototype = { |
| 13909 |
read: processBinaryCMap |
| 13910 |
}; |
| 13911 |
|
| 13912 |
return BinaryCMapReader; |
| 13913 |
})(); |
| 13914 |
|
| 13915 |
var CMapFactory = (function CMapFactoryClosure() { |
| 13916 |
function strToInt(str) { |
| 13917 |
var a = 0; |
| 13918 |
for (var i = 0; i < str.length; i++) { |
| 13919 |
a = (a << 8) | str.charCodeAt(i); |
| 13920 |
} |
| 13921 |
return a >>> 0; |
| 13922 |
} |
| 13923 |
|
| 13924 |
function expectString(obj) { |
| 13925 |
if (!isString(obj)) { |
| 13926 |
error('Malformed CMap: expected string.'); |
| 13927 |
} |
| 13928 |
} |
| 13929 |
|
| 13930 |
function expectInt(obj) { |
| 13931 |
if (!isInt(obj)) { |
| 13932 |
error('Malformed CMap: expected int.'); |
| 13933 |
} |
| 13934 |
} |
| 13935 |
|
| 13936 |
function parseBfChar(cMap, lexer) { |
| 13937 |
while (true) { |
| 13938 |
var obj = lexer.getObj(); |
| 13939 |
if (isEOF(obj)) { |
| 13940 |
break; |
| 13941 |
} |
| 13942 |
if (isCmd(obj, 'endbfchar')) { |
| 13943 |
return; |
| 13944 |
} |
| 13945 |
expectString(obj); |
| 13946 |
var src = strToInt(obj); |
| 13947 |
obj = lexer.getObj(); |
| 13948 |
// TODO are /dstName used? |
| 13949 |
expectString(obj); |
| 13950 |
var dst = obj; |
| 13951 |
cMap.mapOne(src, dst); |
| 13952 |
} |
| 13953 |
} |
| 13954 |
|
| 13955 |
function parseBfRange(cMap, lexer) { |
| 13956 |
while (true) { |
| 13957 |
var obj = lexer.getObj(); |
| 13958 |
if (isEOF(obj)) { |
| 13959 |
break; |
| 13960 |
} |
| 13961 |
if (isCmd(obj, 'endbfrange')) { |
| 13962 |
return; |
| 13963 |
} |
| 13964 |
expectString(obj); |
| 13965 |
var low = strToInt(obj); |
| 13966 |
obj = lexer.getObj(); |
| 13967 |
expectString(obj); |
| 13968 |
var high = strToInt(obj); |
| 13969 |
obj = lexer.getObj(); |
| 13970 |
if (isInt(obj) || isString(obj)) { |
| 13971 |
var dstLow = isInt(obj) ? String.fromCharCode(obj) : obj; |
| 13972 |
cMap.mapBfRange(low, high, dstLow); |
| 13973 |
} else if (isCmd(obj, '[')) { |
| 13974 |
obj = lexer.getObj(); |
| 13975 |
var array = []; |
| 13976 |
while (!isCmd(obj, ']') && !isEOF(obj)) { |
| 13977 |
array.push(obj); |
| 13978 |
obj = lexer.getObj(); |
| 13979 |
} |
| 13980 |
cMap.mapBfRangeToArray(low, high, array); |
| 13981 |
} else { |
| 13982 |
break; |
| 13983 |
} |
| 13984 |
} |
| 13985 |
error('Invalid bf range.'); |
| 13986 |
} |
| 13987 |
|
| 13988 |
function parseCidChar(cMap, lexer) { |
| 13989 |
while (true) { |
| 13990 |
var obj = lexer.getObj(); |
| 13991 |
if (isEOF(obj)) { |
| 13992 |
break; |
| 13993 |
} |
| 13994 |
if (isCmd(obj, 'endcidchar')) { |
| 13995 |
return; |
| 13996 |
} |
| 13997 |
expectString(obj); |
| 13998 |
var src = strToInt(obj); |
| 13999 |
obj = lexer.getObj(); |
| 14000 |
expectInt(obj); |
| 14001 |
var dst = obj; |
| 14002 |
cMap.mapOne(src, dst); |
| 14003 |
} |
| 14004 |
} |
| 14005 |
|
| 14006 |
function parseCidRange(cMap, lexer) { |
| 14007 |
while (true) { |
| 14008 |
var obj = lexer.getObj(); |
| 14009 |
if (isEOF(obj)) { |
| 14010 |
break; |
| 14011 |
} |
| 14012 |
if (isCmd(obj, 'endcidrange')) { |
| 14013 |
return; |
| 14014 |
} |
| 14015 |
expectString(obj); |
| 14016 |
var low = strToInt(obj); |
| 14017 |
obj = lexer.getObj(); |
| 14018 |
expectString(obj); |
| 14019 |
var high = strToInt(obj); |
| 14020 |
obj = lexer.getObj(); |
| 14021 |
expectInt(obj); |
| 14022 |
var dstLow = obj; |
| 14023 |
cMap.mapCidRange(low, high, dstLow); |
| 14024 |
} |
| 14025 |
} |
| 14026 |
|
| 14027 |
function parseCodespaceRange(cMap, lexer) { |
| 14028 |
while (true) { |
| 14029 |
var obj = lexer.getObj(); |
| 14030 |
if (isEOF(obj)) { |
| 14031 |
break; |
| 14032 |
} |
| 14033 |
if (isCmd(obj, 'endcodespacerange')) { |
| 14034 |
return; |
| 14035 |
} |
| 14036 |
if (!isString(obj)) { |
| 14037 |
break; |
| 14038 |
} |
| 14039 |
var low = strToInt(obj); |
| 14040 |
obj = lexer.getObj(); |
| 14041 |
if (!isString(obj)) { |
| 14042 |
break; |
| 14043 |
} |
| 14044 |
var high = strToInt(obj); |
| 14045 |
cMap.addCodespaceRange(obj.length, low, high); |
| 14046 |
} |
| 14047 |
error('Invalid codespace range.'); |
| 14048 |
} |
| 14049 |
|
| 14050 |
function parseWMode(cMap, lexer) { |
| 14051 |
var obj = lexer.getObj(); |
| 14052 |
if (isInt(obj)) { |
| 14053 |
cMap.vertical = !!obj; |
| 14054 |
} |
| 14055 |
} |
| 14056 |
|
| 14057 |
function parseCMapName(cMap, lexer) { |
| 14058 |
var obj = lexer.getObj(); |
| 14059 |
if (isName(obj) && isString(obj.name)) { |
| 14060 |
cMap.name = obj.name; |
| 14061 |
} |
| 14062 |
} |
| 14063 |
|
| 14064 |
function parseCMap(cMap, lexer, builtInCMapParams, useCMap) { |
| 14065 |
var previous; |
| 14066 |
var embededUseCMap; |
| 14067 |
objLoop: while (true) { |
| 14068 |
var obj = lexer.getObj(); |
| 14069 |
if (isEOF(obj)) { |
| 14070 |
break; |
| 14071 |
} else if (isName(obj)) { |
| 14072 |
if (obj.name === 'WMode') { |
| 14073 |
parseWMode(cMap, lexer); |
| 14074 |
} else if (obj.name === 'CMapName') { |
| 14075 |
parseCMapName(cMap, lexer); |
| 14076 |
} |
| 14077 |
previous = obj; |
| 14078 |
} else if (isCmd(obj)) { |
| 14079 |
switch (obj.cmd) { |
| 14080 |
case 'endcmap': |
| 14081 |
break objLoop; |
| 14082 |
case 'usecmap': |
| 14083 |
if (isName(previous)) { |
| 14084 |
embededUseCMap = previous.name; |
| 14085 |
} |
| 14086 |
break; |
| 14087 |
case 'begincodespacerange': |
| 14088 |
parseCodespaceRange(cMap, lexer); |
| 14089 |
break; |
| 14090 |
case 'beginbfchar': |
| 14091 |
parseBfChar(cMap, lexer); |
| 14092 |
break; |
| 14093 |
case 'begincidchar': |
| 14094 |
parseCidChar(cMap, lexer); |
| 14095 |
break; |
| 14096 |
case 'beginbfrange': |
| 14097 |
parseBfRange(cMap, lexer); |
| 14098 |
break; |
| 14099 |
case 'begincidrange': |
| 14100 |
parseCidRange(cMap, lexer); |
| 14101 |
break; |
| 14102 |
} |
| 14103 |
} |
| 14104 |
} |
| 14105 |
|
| 14106 |
if (!useCMap && embededUseCMap) { |
| 14107 |
// Load the usecmap definition from the file only if there wasn't one |
| 14108 |
// specified. |
| 14109 |
useCMap = embededUseCMap; |
| 14110 |
} |
| 14111 |
if (useCMap) { |
| 14112 |
extendCMap(cMap, builtInCMapParams, useCMap); |
| 14113 |
} |
| 14114 |
} |
| 14115 |
|
| 14116 |
function extendCMap(cMap, builtInCMapParams, useCMap) { |
| 14117 |
cMap.useCMap = createBuiltInCMap(useCMap, builtInCMapParams); |
| 14118 |
// If there aren't any code space ranges defined clone all the parent ones |
| 14119 |
// into this cMap. |
| 14120 |
if (cMap.numCodespaceRanges === 0) { |
| 14121 |
var useCodespaceRanges = cMap.useCMap.codespaceRanges; |
| 14122 |
for (var i = 0; i < useCodespaceRanges.length; i++) { |
| 14123 |
cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); |
| 14124 |
} |
| 14125 |
cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; |
| 14126 |
} |
| 14127 |
// Merge the map into the current one, making sure not to override |
| 14128 |
// any previously defined entries. |
| 14129 |
cMap.useCMap.forEach(function(key, value) { |
| 14130 |
if (!cMap.contains(key)) { |
| 14131 |
cMap.mapOne(key, cMap.useCMap.lookup(key)); |
| 14132 |
} |
| 14133 |
}); |
| 14134 |
} |
| 14135 |
|
| 14136 |
function parseBinaryCMap(name, builtInCMapParams) { |
| 14137 |
var url = builtInCMapParams.url + name + '.bcmap'; |
| 14138 |
var cMap = new CMap(true); |
| 14139 |
new BinaryCMapReader().read(url, cMap, function (useCMap) { |
| 14140 |
extendCMap(cMap, builtInCMapParams, useCMap); |
| 14141 |
}); |
| 14142 |
return cMap; |
| 14143 |
} |
| 14144 |
|
| 14145 |
function createBuiltInCMap(name, builtInCMapParams) { |
| 14146 |
if (name === 'Identity-H') { |
| 14147 |
return new IdentityCMap(false, 2); |
| 14148 |
} else if (name === 'Identity-V') { |
| 14149 |
return new IdentityCMap(true, 2); |
| 14150 |
} |
| 14151 |
if (BUILT_IN_CMAPS.indexOf(name) === -1) { |
| 14152 |
error('Unknown cMap name: ' + name); |
| 14153 |
} |
| 14154 |
assert(builtInCMapParams, 'built-in cMap parameters are not provided'); |
| 14155 |
|
| 14156 |
if (builtInCMapParams.packed) { |
| 14157 |
return parseBinaryCMap(name, builtInCMapParams); |
| 14158 |
} |
| 14159 |
|
| 14160 |
var request = new XMLHttpRequest(); |
| 14161 |
var url = builtInCMapParams.url + name; |
| 14162 |
request.open('GET', url, false); |
| 14163 |
request.send(null); |
| 14164 |
if (!request.responseText) { |
| 14165 |
error('Unable to get cMap at: ' + url); |
| 14166 |
} |
| 14167 |
var cMap = new CMap(true); |
| 14168 |
var lexer = new Lexer(new StringStream(request.responseText)); |
| 14169 |
parseCMap(cMap, lexer, builtInCMapParams, null); |
| 14170 |
return cMap; |
| 14171 |
} |
| 14172 |
|
| 14173 |
return { |
| 14174 |
create: function (encoding, builtInCMapParams, useCMap) { |
| 14175 |
if (isName(encoding)) { |
| 14176 |
return createBuiltInCMap(encoding.name, builtInCMapParams); |
| 14177 |
} else if (isStream(encoding)) { |
| 14178 |
var cMap = new CMap(); |
| 14179 |
var lexer = new Lexer(encoding); |
| 14180 |
try { |
| 14181 |
parseCMap(cMap, lexer, builtInCMapParams, useCMap); |
| 14182 |
} catch (e) { |
| 14183 |
warn('Invalid CMap data. ' + e); |
| 14184 |
} |
| 14185 |
if (cMap.isIdentityCMap) { |
| 14186 |
return createBuiltInCMap(cMap.name, builtInCMapParams); |
| 14187 |
} |
| 14188 |
return cMap; |
| 14189 |
} |
| 14190 |
error('Encoding required.'); |
| 14191 |
} |
| 14192 |
}; |
| 14193 |
})(); |
| 14194 |
|
| 14195 |
|
| 14196 |
// Unicode Private Use Area |
| 14197 |
var PRIVATE_USE_OFFSET_START = 0xE000; |
| 14198 |
var PRIVATE_USE_OFFSET_END = 0xF8FF; |
| 14199 |
var SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = false; |
| 14200 |
|
| 14201 |
// PDF Glyph Space Units are one Thousandth of a TextSpace Unit |
| 14202 |
// except for Type 3 fonts |
| 14203 |
var PDF_GLYPH_SPACE_UNITS = 1000; |
| 14204 |
|
| 14205 |
// Hinting is currently disabled due to unknown problems on windows |
| 14206 |
// in tracemonkey and various other pdfs with type1 fonts. |
| 14207 |
var HINTING_ENABLED = false; |
| 14208 |
|
| 14209 |
// Accented charactars are not displayed properly on windows, using this flag |
| 14210 |
// to control analysis of seac charstrings. |
| 14211 |
var SEAC_ANALYSIS_ENABLED = false; |
| 14212 |
|
| 14213 |
var FontFlags = { |
| 14214 |
FixedPitch: 1, |
| 14215 |
Serif: 2, |
| 14216 |
Symbolic: 4, |
| 14217 |
Script: 8, |
| 14218 |
Nonsymbolic: 32, |
| 14219 |
Italic: 64, |
| 14220 |
AllCap: 65536, |
| 14221 |
SmallCap: 131072, |
| 14222 |
ForceBold: 262144 |
| 14223 |
}; |
| 14224 |
|
| 14225 |
var Encodings = { |
| 14226 |
ExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14227 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14228 |
'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', |
| 14229 |
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', |
| 14230 |
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', |
| 14231 |
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', |
| 14232 |
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', |
| 14233 |
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', |
| 14234 |
'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', |
| 14235 |
'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', |
| 14236 |
'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior', |
| 14237 |
'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', |
| 14238 |
'', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', |
| 14239 |
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', |
| 14240 |
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', |
| 14241 |
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', |
| 14242 |
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', |
| 14243 |
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', |
| 14244 |
'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '', |
| 14245 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14246 |
'', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', |
| 14247 |
'', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', |
| 14248 |
'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', |
| 14249 |
'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall', |
| 14250 |
'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters', |
| 14251 |
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', |
| 14252 |
'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior', |
| 14253 |
'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', |
| 14254 |
'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', |
| 14255 |
'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', |
| 14256 |
'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', |
| 14257 |
'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', |
| 14258 |
'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', |
| 14259 |
'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', |
| 14260 |
'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', |
| 14261 |
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', |
| 14262 |
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', |
| 14263 |
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', |
| 14264 |
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', |
| 14265 |
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', |
| 14266 |
'Ydieresissmall'], |
| 14267 |
MacExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14268 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14269 |
'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle', |
| 14270 |
'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', |
| 14271 |
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', |
| 14272 |
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', |
| 14273 |
'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', |
| 14274 |
'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', |
| 14275 |
'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '', |
| 14276 |
'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter', |
| 14277 |
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', |
| 14278 |
'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff', |
| 14279 |
'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', |
| 14280 |
'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', |
| 14281 |
'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', |
| 14282 |
'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', |
| 14283 |
'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', |
| 14284 |
'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', |
| 14285 |
'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '', |
| 14286 |
'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall', |
| 14287 |
'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall', |
| 14288 |
'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall', |
| 14289 |
'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall', |
| 14290 |
'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall', |
| 14291 |
'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '', |
| 14292 |
'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior', |
| 14293 |
'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior', |
| 14294 |
'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior', |
| 14295 |
'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '', |
| 14296 |
'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior', |
| 14297 |
'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall', |
| 14298 |
'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '', |
| 14299 |
'', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '', |
| 14300 |
'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior', |
| 14301 |
'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', |
| 14302 |
'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior', |
| 14303 |
'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior', |
| 14304 |
'', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall', |
| 14305 |
'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior', |
| 14306 |
'periodsuperior', 'Dotaccentsmall', 'Ringsmall'], |
| 14307 |
MacRomanEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14308 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14309 |
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', |
| 14310 |
'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', |
| 14311 |
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', |
| 14312 |
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', |
| 14313 |
'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', |
| 14314 |
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', |
| 14315 |
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', |
| 14316 |
'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', |
| 14317 |
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', |
| 14318 |
'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', |
| 14319 |
'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', |
| 14320 |
'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', |
| 14321 |
'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', |
| 14322 |
'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', |
| 14323 |
'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', |
| 14324 |
'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', |
| 14325 |
'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', |
| 14326 |
'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', |
| 14327 |
'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', |
| 14328 |
'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', |
| 14329 |
'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', |
| 14330 |
'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', |
| 14331 |
'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE', |
| 14332 |
'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', |
| 14333 |
'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', |
| 14334 |
'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', |
| 14335 |
'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand', |
| 14336 |
'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', |
| 14337 |
'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', |
| 14338 |
'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', |
| 14339 |
'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', |
| 14340 |
'ogonek', 'caron'], |
| 14341 |
StandardEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14342 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14343 |
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', |
| 14344 |
'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', |
| 14345 |
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', |
| 14346 |
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', |
| 14347 |
'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', |
| 14348 |
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', |
| 14349 |
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', |
| 14350 |
'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', |
| 14351 |
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', |
| 14352 |
'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', |
| 14353 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14354 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown', |
| 14355 |
'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', |
| 14356 |
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', |
| 14357 |
'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl', |
| 14358 |
'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', |
| 14359 |
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', |
| 14360 |
'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', |
| 14361 |
'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', |
| 14362 |
'', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '', |
| 14363 |
'', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', |
| 14364 |
'', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', |
| 14365 |
'', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'], |
| 14366 |
WinAnsiEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14367 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14368 |
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', |
| 14369 |
'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', |
| 14370 |
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', |
| 14371 |
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', |
| 14372 |
'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', |
| 14373 |
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', |
| 14374 |
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', |
| 14375 |
'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', |
| 14376 |
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', |
| 14377 |
'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', |
| 14378 |
'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase', |
| 14379 |
'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron', |
| 14380 |
'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft', |
| 14381 |
'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', |
| 14382 |
'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet', |
| 14383 |
'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling', |
| 14384 |
'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright', |
| 14385 |
'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered', |
| 14386 |
'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', |
| 14387 |
'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior', |
| 14388 |
'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters', |
| 14389 |
'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis', |
| 14390 |
'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', |
| 14391 |
'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', |
| 14392 |
'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', |
| 14393 |
'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', |
| 14394 |
'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', |
| 14395 |
'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', |
| 14396 |
'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve', |
| 14397 |
'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash', |
| 14398 |
'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn', |
| 14399 |
'ydieresis'], |
| 14400 |
SymbolSetEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14401 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14402 |
'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent', |
| 14403 |
'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus', |
| 14404 |
'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', |
| 14405 |
'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', |
| 14406 |
'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi', |
| 14407 |
'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa', |
| 14408 |
'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau', |
| 14409 |
'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft', |
| 14410 |
'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex', |
| 14411 |
'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', |
| 14412 |
'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', |
| 14413 |
'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', |
| 14414 |
'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '', |
| 14415 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14416 |
'', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal', |
| 14417 |
'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade', |
| 14418 |
'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree', |
| 14419 |
'plusminus', 'second', 'greaterequal', 'multiply', 'proportional', |
| 14420 |
'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence', |
| 14421 |
'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn', |
| 14422 |
'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply', |
| 14423 |
'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset', |
| 14424 |
'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element', |
| 14425 |
'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif', |
| 14426 |
'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot', |
| 14427 |
'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup', |
| 14428 |
'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans', |
| 14429 |
'copyrightsans', 'trademarksans', 'summation', 'parenlefttp', |
| 14430 |
'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex', |
| 14431 |
'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', |
| 14432 |
'', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt', |
| 14433 |
'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp', |
| 14434 |
'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid', |
| 14435 |
'bracerightbt'], |
| 14436 |
ZapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14437 |
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', |
| 14438 |
'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117', |
| 14439 |
'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19', |
| 14440 |
'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7', |
| 14441 |
'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36', |
| 14442 |
'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46', |
| 14443 |
'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56', |
| 14444 |
'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66', |
| 14445 |
'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75', |
| 14446 |
'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97', |
| 14447 |
'a98', 'a99', 'a100', '', 'a89', 'a90', 'a93', 'a94', 'a91', 'a92', 'a205', |
| 14448 |
'a85', 'a206', 'a86', 'a87', 'a88', 'a95', 'a96', '', '', '', '', '', '', |
| 14449 |
'', '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103', |
| 14450 |
'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120', |
| 14451 |
'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129', |
| 14452 |
'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138', |
| 14453 |
'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147', |
| 14454 |
'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156', |
| 14455 |
'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165', |
| 14456 |
'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173', |
| 14457 |
'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180', |
| 14458 |
'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197', 'a185', |
| 14459 |
'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190', 'a191'] |
| 14460 |
}; |
| 14461 |
|
| 14462 |
/** |
| 14463 |
* Hold a map of decoded fonts and of the standard fourteen Type1 |
| 14464 |
* fonts and their acronyms. |
| 14465 |
*/ |
| 14466 |
var stdFontMap = { |
| 14467 |
'ArialNarrow': 'Helvetica', |
| 14468 |
'ArialNarrow-Bold': 'Helvetica-Bold', |
| 14469 |
'ArialNarrow-BoldItalic': 'Helvetica-BoldOblique', |
| 14470 |
'ArialNarrow-Italic': 'Helvetica-Oblique', |
| 14471 |
'ArialBlack': 'Helvetica', |
| 14472 |
'ArialBlack-Bold': 'Helvetica-Bold', |
| 14473 |
'ArialBlack-BoldItalic': 'Helvetica-BoldOblique', |
| 14474 |
'ArialBlack-Italic': 'Helvetica-Oblique', |
| 14475 |
'Arial': 'Helvetica', |
| 14476 |
'Arial-Bold': 'Helvetica-Bold', |
| 14477 |
'Arial-BoldItalic': 'Helvetica-BoldOblique', |
| 14478 |
'Arial-Italic': 'Helvetica-Oblique', |
| 14479 |
'Arial-BoldItalicMT': 'Helvetica-BoldOblique', |
| 14480 |
'Arial-BoldMT': 'Helvetica-Bold', |
| 14481 |
'Arial-ItalicMT': 'Helvetica-Oblique', |
| 14482 |
'ArialMT': 'Helvetica', |
| 14483 |
'Courier-Bold': 'Courier-Bold', |
| 14484 |
'Courier-BoldItalic': 'Courier-BoldOblique', |
| 14485 |
'Courier-Italic': 'Courier-Oblique', |
| 14486 |
'CourierNew': 'Courier', |
| 14487 |
'CourierNew-Bold': 'Courier-Bold', |
| 14488 |
'CourierNew-BoldItalic': 'Courier-BoldOblique', |
| 14489 |
'CourierNew-Italic': 'Courier-Oblique', |
| 14490 |
'CourierNewPS-BoldItalicMT': 'Courier-BoldOblique', |
| 14491 |
'CourierNewPS-BoldMT': 'Courier-Bold', |
| 14492 |
'CourierNewPS-ItalicMT': 'Courier-Oblique', |
| 14493 |
'CourierNewPSMT': 'Courier', |
| 14494 |
'Helvetica': 'Helvetica', |
| 14495 |
'Helvetica-Bold': 'Helvetica-Bold', |
| 14496 |
'Helvetica-BoldItalic': 'Helvetica-BoldOblique', |
| 14497 |
'Helvetica-BoldOblique': 'Helvetica-BoldOblique', |
| 14498 |
'Helvetica-Italic': 'Helvetica-Oblique', |
| 14499 |
'Helvetica-Oblique':'Helvetica-Oblique', |
| 14500 |
'Symbol-Bold': 'Symbol', |
| 14501 |
'Symbol-BoldItalic': 'Symbol', |
| 14502 |
'Symbol-Italic': 'Symbol', |
| 14503 |
'TimesNewRoman': 'Times-Roman', |
| 14504 |
'TimesNewRoman-Bold': 'Times-Bold', |
| 14505 |
'TimesNewRoman-BoldItalic': 'Times-BoldItalic', |
| 14506 |
'TimesNewRoman-Italic': 'Times-Italic', |
| 14507 |
'TimesNewRomanPS': 'Times-Roman', |
| 14508 |
'TimesNewRomanPS-Bold': 'Times-Bold', |
| 14509 |
'TimesNewRomanPS-BoldItalic': 'Times-BoldItalic', |
| 14510 |
'TimesNewRomanPS-BoldItalicMT': 'Times-BoldItalic', |
| 14511 |
'TimesNewRomanPS-BoldMT': 'Times-Bold', |
| 14512 |
'TimesNewRomanPS-Italic': 'Times-Italic', |
| 14513 |
'TimesNewRomanPS-ItalicMT': 'Times-Italic', |
| 14514 |
'TimesNewRomanPSMT': 'Times-Roman', |
| 14515 |
'TimesNewRomanPSMT-Bold': 'Times-Bold', |
| 14516 |
'TimesNewRomanPSMT-BoldItalic': 'Times-BoldItalic', |
| 14517 |
'TimesNewRomanPSMT-Italic': 'Times-Italic' |
| 14518 |
}; |
| 14519 |
|
| 14520 |
/** |
| 14521 |
* Holds the map of the non-standard fonts that might be included as a standard |
| 14522 |
* fonts without glyph data. |
| 14523 |
*/ |
| 14524 |
var nonStdFontMap = { |
| 14525 |
'CenturyGothic': 'Helvetica', |
| 14526 |
'CenturyGothic-Bold': 'Helvetica-Bold', |
| 14527 |
'CenturyGothic-BoldItalic': 'Helvetica-BoldOblique', |
| 14528 |
'CenturyGothic-Italic': 'Helvetica-Oblique', |
| 14529 |
'ComicSansMS': 'Comic Sans MS', |
| 14530 |
'ComicSansMS-Bold': 'Comic Sans MS-Bold', |
| 14531 |
'ComicSansMS-BoldItalic': 'Comic Sans MS-BoldItalic', |
| 14532 |
'ComicSansMS-Italic': 'Comic Sans MS-Italic', |
| 14533 |
'LucidaConsole': 'Courier', |
| 14534 |
'LucidaConsole-Bold': 'Courier-Bold', |
| 14535 |
'LucidaConsole-BoldItalic': 'Courier-BoldOblique', |
| 14536 |
'LucidaConsole-Italic': 'Courier-Oblique', |
| 14537 |
'MS-Gothic': 'MS Gothic', |
| 14538 |
'MS-Gothic-Bold': 'MS Gothic-Bold', |
| 14539 |
'MS-Gothic-BoldItalic': 'MS Gothic-BoldItalic', |
| 14540 |
'MS-Gothic-Italic': 'MS Gothic-Italic', |
| 14541 |
'MS-Mincho': 'MS Mincho', |
| 14542 |
'MS-Mincho-Bold': 'MS Mincho-Bold', |
| 14543 |
'MS-Mincho-BoldItalic': 'MS Mincho-BoldItalic', |
| 14544 |
'MS-Mincho-Italic': 'MS Mincho-Italic', |
| 14545 |
'MS-PGothic': 'MS PGothic', |
| 14546 |
'MS-PGothic-Bold': 'MS PGothic-Bold', |
| 14547 |
'MS-PGothic-BoldItalic': 'MS PGothic-BoldItalic', |
| 14548 |
'MS-PGothic-Italic': 'MS PGothic-Italic', |
| 14549 |
'MS-PMincho': 'MS PMincho', |
| 14550 |
'MS-PMincho-Bold': 'MS PMincho-Bold', |
| 14551 |
'MS-PMincho-BoldItalic': 'MS PMincho-BoldItalic', |
| 14552 |
'MS-PMincho-Italic': 'MS PMincho-Italic', |
| 14553 |
'Wingdings': 'ZapfDingbats' |
| 14554 |
}; |
| 14555 |
|
| 14556 |
var serifFonts = { |
| 14557 |
'Adobe Jenson': true, 'Adobe Text': true, 'Albertus': true, |
| 14558 |
'Aldus': true, 'Alexandria': true, 'Algerian': true, |
| 14559 |
'American Typewriter': true, 'Antiqua': true, 'Apex': true, |
| 14560 |
'Arno': true, 'Aster': true, 'Aurora': true, |
| 14561 |
'Baskerville': true, 'Bell': true, 'Bembo': true, |
| 14562 |
'Bembo Schoolbook': true, 'Benguiat': true, 'Berkeley Old Style': true, |
| 14563 |
'Bernhard Modern': true, 'Berthold City': true, 'Bodoni': true, |
| 14564 |
'Bauer Bodoni': true, 'Book Antiqua': true, 'Bookman': true, |
| 14565 |
'Bordeaux Roman': true, 'Californian FB': true, 'Calisto': true, |
| 14566 |
'Calvert': true, 'Capitals': true, 'Cambria': true, |
| 14567 |
'Cartier': true, 'Caslon': true, 'Catull': true, |
| 14568 |
'Centaur': true, 'Century Old Style': true, 'Century Schoolbook': true, |
| 14569 |
'Chaparral': true, 'Charis SIL': true, 'Cheltenham': true, |
| 14570 |
'Cholla Slab': true, 'Clarendon': true, 'Clearface': true, |
| 14571 |
'Cochin': true, 'Colonna': true, 'Computer Modern': true, |
| 14572 |
'Concrete Roman': true, 'Constantia': true, 'Cooper Black': true, |
| 14573 |
'Corona': true, 'Ecotype': true, 'Egyptienne': true, |
| 14574 |
'Elephant': true, 'Excelsior': true, 'Fairfield': true, |
| 14575 |
'FF Scala': true, 'Folkard': true, 'Footlight': true, |
| 14576 |
'FreeSerif': true, 'Friz Quadrata': true, 'Garamond': true, |
| 14577 |
'Gentium': true, 'Georgia': true, 'Gloucester': true, |
| 14578 |
'Goudy Old Style': true, 'Goudy Schoolbook': true, 'Goudy Pro Font': true, |
| 14579 |
'Granjon': true, 'Guardian Egyptian': true, 'Heather': true, |
| 14580 |
'Hercules': true, 'High Tower Text': true, 'Hiroshige': true, |
| 14581 |
'Hoefler Text': true, 'Humana Serif': true, 'Imprint': true, |
| 14582 |
'Ionic No. 5': true, 'Janson': true, 'Joanna': true, |
| 14583 |
'Korinna': true, 'Lexicon': true, 'Liberation Serif': true, |
| 14584 |
'Linux Libertine': true, 'Literaturnaya': true, 'Lucida': true, |
| 14585 |
'Lucida Bright': true, 'Melior': true, 'Memphis': true, |
| 14586 |
'Miller': true, 'Minion': true, 'Modern': true, |
| 14587 |
'Mona Lisa': true, 'Mrs Eaves': true, 'MS Serif': true, |
| 14588 |
'Museo Slab': true, 'New York': true, 'Nimbus Roman': true, |
| 14589 |
'NPS Rawlinson Roadway': true, 'Palatino': true, 'Perpetua': true, |
| 14590 |
'Plantin': true, 'Plantin Schoolbook': true, 'Playbill': true, |
| 14591 |
'Poor Richard': true, 'Rawlinson Roadway': true, 'Renault': true, |
| 14592 |
'Requiem': true, 'Rockwell': true, 'Roman': true, |
| 14593 |
'Rotis Serif': true, 'Sabon': true, 'Scala': true, |
| 14594 |
'Seagull': true, 'Sistina': true, 'Souvenir': true, |
| 14595 |
'STIX': true, 'Stone Informal': true, 'Stone Serif': true, |
| 14596 |
'Sylfaen': true, 'Times': true, 'Trajan': true, |
| 14597 |
'Trinité': true, 'Trump Mediaeval': true, 'Utopia': true, |
| 14598 |
'Vale Type': true, 'Bitstream Vera': true, 'Vera Serif': true, |
| 14599 |
'Versailles': true, 'Wanted': true, 'Weiss': true, |
| 14600 |
'Wide Latin': true, 'Windsor': true, 'XITS': true |
| 14601 |
}; |
| 14602 |
|
| 14603 |
var symbolsFonts = { |
| 14604 |
'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true |
| 14605 |
}; |
| 14606 |
|
| 14607 |
// Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID fonts |
| 14608 |
// but does not embed the CID to GID mapping. The mapping is incomplete for all |
| 14609 |
// glyphs, but common for some set of the standard fonts. |
| 14610 |
var GlyphMapForStandardFonts = { |
| 14611 |
'2': 10, '3': 32, '4': 33, '5': 34, '6': 35, '7': 36, '8': 37, '9': 38, |
| 14612 |
'10': 39, '11': 40, '12': 41, '13': 42, '14': 43, '15': 44, '16': 45, |
| 14613 |
'17': 46, '18': 47, '19': 48, '20': 49, '21': 50, '22': 51, '23': 52, |
| 14614 |
'24': 53, '25': 54, '26': 55, '27': 56, '28': 57, '29': 58, '30': 894, |
| 14615 |
'31': 60, '32': 61, '33': 62, '34': 63, '35': 64, '36': 65, '37': 66, |
| 14616 |
'38': 67, '39': 68, '40': 69, '41': 70, '42': 71, '43': 72, '44': 73, |
| 14617 |
'45': 74, '46': 75, '47': 76, '48': 77, '49': 78, '50': 79, '51': 80, |
| 14618 |
'52': 81, '53': 82, '54': 83, '55': 84, '56': 85, '57': 86, '58': 87, |
| 14619 |
'59': 88, '60': 89, '61': 90, '62': 91, '63': 92, '64': 93, '65': 94, |
| 14620 |
'66': 95, '67': 96, '68': 97, '69': 98, '70': 99, '71': 100, '72': 101, |
| 14621 |
'73': 102, '74': 103, '75': 104, '76': 105, '77': 106, '78': 107, '79': 108, |
| 14622 |
'80': 109, '81': 110, '82': 111, '83': 112, '84': 113, '85': 114, '86': 115, |
| 14623 |
'87': 116, '88': 117, '89': 118, '90': 119, '91': 120, '92': 121, '93': 122, |
| 14624 |
'94': 123, '95': 124, '96': 125, '97': 126, '98': 196, '99': 197, '100': 199, |
| 14625 |
'101': 201, '102': 209, '103': 214, '104': 220, '105': 225, '106': 224, |
| 14626 |
'107': 226, '108': 228, '109': 227, '110': 229, '111': 231, '112': 233, |
| 14627 |
'113': 232, '114': 234, '115': 235, '116': 237, '117': 236, '118': 238, |
| 14628 |
'119': 239, '120': 241, '121': 243, '122': 242, '123': 244, '124': 246, |
| 14629 |
'125': 245, '126': 250, '127': 249, '128': 251, '129': 252, '130': 8224, |
| 14630 |
'131': 176, '132': 162, '133': 163, '134': 167, '135': 8226, '136': 182, |
| 14631 |
'137': 223, '138': 174, '139': 169, '140': 8482, '141': 180, '142': 168, |
| 14632 |
'143': 8800, '144': 198, '145': 216, '146': 8734, '147': 177, '148': 8804, |
| 14633 |
'149': 8805, '150': 165, '151': 181, '152': 8706, '153': 8721, '154': 8719, |
| 14634 |
'156': 8747, '157': 170, '158': 186, '159': 8486, '160': 230, '161': 248, |
| 14635 |
'162': 191, '163': 161, '164': 172, '165': 8730, '166': 402, '167': 8776, |
| 14636 |
'168': 8710, '169': 171, '170': 187, '171': 8230, '210': 218, '223': 711, |
| 14637 |
'224': 321, '225': 322, '227': 353, '229': 382, '234': 253, '252': 263, |
| 14638 |
'253': 268, '254': 269, '258': 258, '260': 260, '261': 261, '265': 280, |
| 14639 |
'266': 281, '268': 283, '269': 313, '275': 323, '276': 324, '278': 328, |
| 14640 |
'284': 345, '285': 346, '286': 347, '292': 367, '295': 377, '296': 378, |
| 14641 |
'298': 380, '305': 963, |
| 14642 |
'306': 964, '307': 966, '308': 8215, '309': 8252, '310': 8319, '311': 8359, |
| 14643 |
'312': 8592, '313': 8593, '337': 9552, '493': 1039, '494': 1040, '705': 1524, |
| 14644 |
'706': 8362, '710': 64288, '711': 64298, '759': 1617, '761': 1776, |
| 14645 |
'763': 1778, '775': 1652, '777': 1764, '778': 1780, '779': 1781, '780': 1782, |
| 14646 |
'782': 771, '783': 64726, '786': 8363, '788': 8532, '790': 768, '791': 769, |
| 14647 |
'792': 768, '795': 803, '797': 64336, '798': 64337, '799': 64342, |
| 14648 |
'800': 64343, '801': 64344, '802': 64345, '803': 64362, '804': 64363, |
| 14649 |
'805': 64364, '2424': 7821, '2425': 7822, '2426': 7823, '2427': 7824, |
| 14650 |
'2428': 7825, '2429': 7826, '2430': 7827, '2433': 7682, '2678': 8045, |
| 14651 |
'2679': 8046, '2830': 1552, '2838': 686, '2840': 751, '2842': 753, |
| 14652 |
'2843': 754, '2844': 755, '2846': 757, '2856': 767, '2857': 848, '2858': 849, |
| 14653 |
'2862': 853, '2863': 854, '2864': 855, '2865': 861, '2866': 862, '2906': 7460, |
| 14654 |
'2908': 7462, '2909': 7463, '2910': 7464, '2912': 7466, '2913': 7467, |
| 14655 |
'2914': 7468, '2916': 7470, '2917': 7471, '2918': 7472, '2920': 7474, |
| 14656 |
'2921': 7475, '2922': 7476, '2924': 7478, '2925': 7479, '2926': 7480, |
| 14657 |
'2928': 7482, '2929': 7483, '2930': 7484, '2932': 7486, '2933': 7487, |
| 14658 |
'2934': 7488, '2936': 7490, '2937': 7491, '2938': 7492, '2940': 7494, |
| 14659 |
'2941': 7495, '2942': 7496, '2944': 7498, '2946': 7500, '2948': 7502, |
| 14660 |
'2950': 7504, '2951': 7505, '2952': 7506, '2954': 7508, '2955': 7509, |
| 14661 |
'2956': 7510, '2958': 7512, '2959': 7513, '2960': 7514, '2962': 7516, |
| 14662 |
'2963': 7517, '2964': 7518, '2966': 7520, '2967': 7521, '2968': 7522, |
| 14663 |
'2970': 7524, '2971': 7525, '2972': 7526, '2974': 7528, '2975': 7529, |
| 14664 |
'2976': 7530, '2978': 1537, '2979': 1538, '2980': 1539, '2982': 1549, |
| 14665 |
'2983': 1551, '2984': 1552, '2986': 1554, '2987': 1555, '2988': 1556, |
| 14666 |
'2990': 1623, '2991': 1624, '2995': 1775, '2999': 1791, '3002': 64290, |
| 14667 |
'3003': 64291, '3004': 64292, '3006': 64294, '3007': 64295, '3008': 64296, |
| 14668 |
'3011': 1900, '3014': 8223, '3015': 8244, '3017': 7532, '3018': 7533, |
| 14669 |
'3019': 7534, '3075': 7590, '3076': 7591, '3079': 7594, '3080': 7595, |
| 14670 |
'3083': 7598, '3084': 7599, '3087': 7602, '3088': 7603, '3091': 7606, |
| 14671 |
'3092': 7607, '3095': 7610, '3096': 7611, '3099': 7614, '3100': 7615, |
| 14672 |
'3103': 7618, '3104': 7619, '3107': 8337, '3108': 8338, '3116': 1884, |
| 14673 |
'3119': 1885, '3120': 1885, '3123': 1886, '3124': 1886, '3127': 1887, |
| 14674 |
'3128': 1887, '3131': 1888, '3132': 1888, '3135': 1889, '3136': 1889, |
| 14675 |
'3139': 1890, '3140': 1890, '3143': 1891, '3144': 1891, '3147': 1892, |
| 14676 |
'3148': 1892, '3153': 580, '3154': 581, '3157': 584, '3158': 585, '3161': 588, |
| 14677 |
'3162': 589, '3165': 891, '3166': 892, '3169': 1274, '3170': 1275, |
| 14678 |
'3173': 1278, '3174': 1279, '3181': 7622, '3182': 7623, '3282': 11799, |
| 14679 |
'3316': 578, '3379': 42785, '3393': 1159, '3416': 8377 |
| 14680 |
}; |
| 14681 |
|
| 14682 |
// Some characters, e.g. copyrightserif, are mapped to the private use area and |
| 14683 |
// might not be displayed using standard fonts. Mapping/hacking well-known chars |
| 14684 |
// to the similar equivalents in the normal characters range. |
| 14685 |
var SpecialPUASymbols = { |
| 14686 |
'63721': 0x00A9, // copyrightsans (0xF8E9) => copyright |
| 14687 |
'63193': 0x00A9, // copyrightserif (0xF6D9) => copyright |
| 14688 |
'63720': 0x00AE, // registersans (0xF8E8) => registered |
| 14689 |
'63194': 0x00AE, // registerserif (0xF6DA) => registered |
| 14690 |
'63722': 0x2122, // trademarksans (0xF8EA) => trademark |
| 14691 |
'63195': 0x2122, // trademarkserif (0xF6DB) => trademark |
| 14692 |
'63729': 0x23A7, // bracelefttp (0xF8F1) |
| 14693 |
'63730': 0x23A8, // braceleftmid (0xF8F2) |
| 14694 |
'63731': 0x23A9, // braceleftbt (0xF8F3) |
| 14695 |
'63740': 0x23AB, // bracerighttp (0xF8FC) |
| 14696 |
'63741': 0x23AC, // bracerightmid (0xF8FD) |
| 14697 |
'63742': 0x23AD, // bracerightbt (0xF8FE) |
| 14698 |
'63726': 0x23A1, // bracketlefttp (0xF8EE) |
| 14699 |
'63727': 0x23A2, // bracketleftex (0xF8EF) |
| 14700 |
'63728': 0x23A3, // bracketleftbt (0xF8F0) |
| 14701 |
'63737': 0x23A4, // bracketrighttp (0xF8F9) |
| 14702 |
'63738': 0x23A5, // bracketrightex (0xF8FA) |
| 14703 |
'63739': 0x23A6, // bracketrightbt (0xF8FB) |
| 14704 |
'63723': 0x239B, // parenlefttp (0xF8EB) |
| 14705 |
'63724': 0x239C, // parenleftex (0xF8EC) |
| 14706 |
'63725': 0x239D, // parenleftbt (0xF8ED) |
| 14707 |
'63734': 0x239E, // parenrighttp (0xF8F6) |
| 14708 |
'63735': 0x239F, // parenrightex (0xF8F7) |
| 14709 |
'63736': 0x23A0, // parenrightbt (0xF8F8) |
| 14710 |
}; |
| 14711 |
function mapSpecialUnicodeValues(code) { |
| 14712 |
if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials unicode block. |
| 14713 |
return 0; |
| 14714 |
} else if (code >= 0xF600 && code <= 0xF8FF) { |
| 14715 |
return (SpecialPUASymbols[code] || code); |
| 14716 |
} |
| 14717 |
return code; |
| 14718 |
} |
| 14719 |
|
| 14720 |
var UnicodeRanges = [ |
| 14721 |
{ 'begin': 0x0000, 'end': 0x007F }, // Basic Latin |
| 14722 |
{ 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement |
| 14723 |
{ 'begin': 0x0100, 'end': 0x017F }, // Latin Extended-A |
| 14724 |
{ 'begin': 0x0180, 'end': 0x024F }, // Latin Extended-B |
| 14725 |
{ 'begin': 0x0250, 'end': 0x02AF }, // IPA Extensions |
| 14726 |
{ 'begin': 0x02B0, 'end': 0x02FF }, // Spacing Modifier Letters |
| 14727 |
{ 'begin': 0x0300, 'end': 0x036F }, // Combining Diacritical Marks |
| 14728 |
{ 'begin': 0x0370, 'end': 0x03FF }, // Greek and Coptic |
| 14729 |
{ 'begin': 0x2C80, 'end': 0x2CFF }, // Coptic |
| 14730 |
{ 'begin': 0x0400, 'end': 0x04FF }, // Cyrillic |
| 14731 |
{ 'begin': 0x0530, 'end': 0x058F }, // Armenian |
| 14732 |
{ 'begin': 0x0590, 'end': 0x05FF }, // Hebrew |
| 14733 |
{ 'begin': 0xA500, 'end': 0xA63F }, // Vai |
| 14734 |
{ 'begin': 0x0600, 'end': 0x06FF }, // Arabic |
| 14735 |
{ 'begin': 0x07C0, 'end': 0x07FF }, // NKo |
| 14736 |
{ 'begin': 0x0900, 'end': 0x097F }, // Devanagari |
| 14737 |
{ 'begin': 0x0980, 'end': 0x09FF }, // Bengali |
| 14738 |
{ 'begin': 0x0A00, 'end': 0x0A7F }, // Gurmukhi |
| 14739 |
{ 'begin': 0x0A80, 'end': 0x0AFF }, // Gujarati |
| 14740 |
{ 'begin': 0x0B00, 'end': 0x0B7F }, // Oriya |
| 14741 |
{ 'begin': 0x0B80, 'end': 0x0BFF }, // Tamil |
| 14742 |
{ 'begin': 0x0C00, 'end': 0x0C7F }, // Telugu |
| 14743 |
{ 'begin': 0x0C80, 'end': 0x0CFF }, // Kannada |
| 14744 |
{ 'begin': 0x0D00, 'end': 0x0D7F }, // Malayalam |
| 14745 |
{ 'begin': 0x0E00, 'end': 0x0E7F }, // Thai |
| 14746 |
{ 'begin': 0x0E80, 'end': 0x0EFF }, // Lao |
| 14747 |
{ 'begin': 0x10A0, 'end': 0x10FF }, // Georgian |
| 14748 |
{ 'begin': 0x1B00, 'end': 0x1B7F }, // Balinese |
| 14749 |
{ 'begin': 0x1100, 'end': 0x11FF }, // Hangul Jamo |
| 14750 |
{ 'begin': 0x1E00, 'end': 0x1EFF }, // Latin Extended Additional |
| 14751 |
{ 'begin': 0x1F00, 'end': 0x1FFF }, // Greek Extended |
| 14752 |
{ 'begin': 0x2000, 'end': 0x206F }, // General Punctuation |
| 14753 |
{ 'begin': 0x2070, 'end': 0x209F }, // Superscripts And Subscripts |
| 14754 |
{ 'begin': 0x20A0, 'end': 0x20CF }, // Currency Symbol |
| 14755 |
{ 'begin': 0x20D0, 'end': 0x20FF }, // Combining Diacritical Marks For Symbols |
| 14756 |
{ 'begin': 0x2100, 'end': 0x214F }, // Letterlike Symbols |
| 14757 |
{ 'begin': 0x2150, 'end': 0x218F }, // Number Forms |
| 14758 |
{ 'begin': 0x2190, 'end': 0x21FF }, // Arrows |
| 14759 |
{ 'begin': 0x2200, 'end': 0x22FF }, // Mathematical Operators |
| 14760 |
{ 'begin': 0x2300, 'end': 0x23FF }, // Miscellaneous Technical |
| 14761 |
{ 'begin': 0x2400, 'end': 0x243F }, // Control Pictures |
| 14762 |
{ 'begin': 0x2440, 'end': 0x245F }, // Optical Character Recognition |
| 14763 |
{ 'begin': 0x2460, 'end': 0x24FF }, // Enclosed Alphanumerics |
| 14764 |
{ 'begin': 0x2500, 'end': 0x257F }, // Box Drawing |
| 14765 |
{ 'begin': 0x2580, 'end': 0x259F }, // Block Elements |
| 14766 |
{ 'begin': 0x25A0, 'end': 0x25FF }, // Geometric Shapes |
| 14767 |
{ 'begin': 0x2600, 'end': 0x26FF }, // Miscellaneous Symbols |
| 14768 |
{ 'begin': 0x2700, 'end': 0x27BF }, // Dingbats |
| 14769 |
{ 'begin': 0x3000, 'end': 0x303F }, // CJK Symbols And Punctuation |
| 14770 |
{ 'begin': 0x3040, 'end': 0x309F }, // Hiragana |
| 14771 |
{ 'begin': 0x30A0, 'end': 0x30FF }, // Katakana |
| 14772 |
{ 'begin': 0x3100, 'end': 0x312F }, // Bopomofo |
| 14773 |
{ 'begin': 0x3130, 'end': 0x318F }, // Hangul Compatibility Jamo |
| 14774 |
{ 'begin': 0xA840, 'end': 0xA87F }, // Phags-pa |
| 14775 |
{ 'begin': 0x3200, 'end': 0x32FF }, // Enclosed CJK Letters And Months |
| 14776 |
{ 'begin': 0x3300, 'end': 0x33FF }, // CJK Compatibility |
| 14777 |
{ 'begin': 0xAC00, 'end': 0xD7AF }, // Hangul Syllables |
| 14778 |
{ 'begin': 0xD800, 'end': 0xDFFF }, // Non-Plane 0 * |
| 14779 |
{ 'begin': 0x10900, 'end': 0x1091F }, // Phoenicia |
| 14780 |
{ 'begin': 0x4E00, 'end': 0x9FFF }, // CJK Unified Ideographs |
| 14781 |
{ 'begin': 0xE000, 'end': 0xF8FF }, // Private Use Area (plane 0) |
| 14782 |
{ 'begin': 0x31C0, 'end': 0x31EF }, // CJK Strokes |
| 14783 |
{ 'begin': 0xFB00, 'end': 0xFB4F }, // Alphabetic Presentation Forms |
| 14784 |
{ 'begin': 0xFB50, 'end': 0xFDFF }, // Arabic Presentation Forms-A |
| 14785 |
{ 'begin': 0xFE20, 'end': 0xFE2F }, // Combining Half Marks |
| 14786 |
{ 'begin': 0xFE10, 'end': 0xFE1F }, // Vertical Forms |
| 14787 |
{ 'begin': 0xFE50, 'end': 0xFE6F }, // Small Form Variants |
| 14788 |
{ 'begin': 0xFE70, 'end': 0xFEFF }, // Arabic Presentation Forms-B |
| 14789 |
{ 'begin': 0xFF00, 'end': 0xFFEF }, // Halfwidth And Fullwidth Forms |
| 14790 |
{ 'begin': 0xFFF0, 'end': 0xFFFF }, // Specials |
| 14791 |
{ 'begin': 0x0F00, 'end': 0x0FFF }, // Tibetan |
| 14792 |
{ 'begin': 0x0700, 'end': 0x074F }, // Syriac |
| 14793 |
{ 'begin': 0x0780, 'end': 0x07BF }, // Thaana |
| 14794 |
{ 'begin': 0x0D80, 'end': 0x0DFF }, // Sinhala |
| 14795 |
{ 'begin': 0x1000, 'end': 0x109F }, // Myanmar |
| 14796 |
{ 'begin': 0x1200, 'end': 0x137F }, // Ethiopic |
| 14797 |
{ 'begin': 0x13A0, 'end': 0x13FF }, // Cherokee |
| 14798 |
{ 'begin': 0x1400, 'end': 0x167F }, // Unified Canadian Aboriginal Syllabics |
| 14799 |
{ 'begin': 0x1680, 'end': 0x169F }, // Ogham |
| 14800 |
{ 'begin': 0x16A0, 'end': 0x16FF }, // Runic |
| 14801 |
{ 'begin': 0x1780, 'end': 0x17FF }, // Khmer |
| 14802 |
{ 'begin': 0x1800, 'end': 0x18AF }, // Mongolian |
| 14803 |
{ 'begin': 0x2800, 'end': 0x28FF }, // Braille Patterns |
| 14804 |
{ 'begin': 0xA000, 'end': 0xA48F }, // Yi Syllables |
| 14805 |
{ 'begin': 0x1700, 'end': 0x171F }, // Tagalog |
| 14806 |
{ 'begin': 0x10300, 'end': 0x1032F }, // Old Italic |
| 14807 |
{ 'begin': 0x10330, 'end': 0x1034F }, // Gothic |
| 14808 |
{ 'begin': 0x10400, 'end': 0x1044F }, // Deseret |
| 14809 |
{ 'begin': 0x1D000, 'end': 0x1D0FF }, // Byzantine Musical Symbols |
| 14810 |
{ 'begin': 0x1D400, 'end': 0x1D7FF }, // Mathematical Alphanumeric Symbols |
| 14811 |
{ 'begin': 0xFF000, 'end': 0xFFFFD }, // Private Use (plane 15) |
| 14812 |
{ 'begin': 0xFE00, 'end': 0xFE0F }, // Variation Selectors |
| 14813 |
{ 'begin': 0xE0000, 'end': 0xE007F }, // Tags |
| 14814 |
{ 'begin': 0x1900, 'end': 0x194F }, // Limbu |
| 14815 |
{ 'begin': 0x1950, 'end': 0x197F }, // Tai Le |
| 14816 |
{ 'begin': 0x1980, 'end': 0x19DF }, // New Tai Lue |
| 14817 |
{ 'begin': 0x1A00, 'end': 0x1A1F }, // Buginese |
| 14818 |
{ 'begin': 0x2C00, 'end': 0x2C5F }, // Glagolitic |
| 14819 |
{ 'begin': 0x2D30, 'end': 0x2D7F }, // Tifinagh |
| 14820 |
{ 'begin': 0x4DC0, 'end': 0x4DFF }, // Yijing Hexagram Symbols |
| 14821 |
{ 'begin': 0xA800, 'end': 0xA82F }, // Syloti Nagri |
| 14822 |
{ 'begin': 0x10000, 'end': 0x1007F }, // Linear B Syllabary |
| 14823 |
{ 'begin': 0x10140, 'end': 0x1018F }, // Ancient Greek Numbers |
| 14824 |
{ 'begin': 0x10380, 'end': 0x1039F }, // Ugaritic |
| 14825 |
{ 'begin': 0x103A0, 'end': 0x103DF }, // Old Persian |
| 14826 |
{ 'begin': 0x10450, 'end': 0x1047F }, // Shavian |
| 14827 |
{ 'begin': 0x10480, 'end': 0x104AF }, // Osmanya |
| 14828 |
{ 'begin': 0x10800, 'end': 0x1083F }, // Cypriot Syllabary |
| 14829 |
{ 'begin': 0x10A00, 'end': 0x10A5F }, // Kharoshthi |
| 14830 |
{ 'begin': 0x1D300, 'end': 0x1D35F }, // Tai Xuan Jing Symbols |
| 14831 |
{ 'begin': 0x12000, 'end': 0x123FF }, // Cuneiform |
| 14832 |
{ 'begin': 0x1D360, 'end': 0x1D37F }, // Counting Rod Numerals |
| 14833 |
{ 'begin': 0x1B80, 'end': 0x1BBF }, // Sundanese |
| 14834 |
{ 'begin': 0x1C00, 'end': 0x1C4F }, // Lepcha |
| 14835 |
{ 'begin': 0x1C50, 'end': 0x1C7F }, // Ol Chiki |
| 14836 |
{ 'begin': 0xA880, 'end': 0xA8DF }, // Saurashtra |
| 14837 |
{ 'begin': 0xA900, 'end': 0xA92F }, // Kayah Li |
| 14838 |
{ 'begin': 0xA930, 'end': 0xA95F }, // Rejang |
| 14839 |
{ 'begin': 0xAA00, 'end': 0xAA5F }, // Cham |
| 14840 |
{ 'begin': 0x10190, 'end': 0x101CF }, // Ancient Symbols |
| 14841 |
{ 'begin': 0x101D0, 'end': 0x101FF }, // Phaistos Disc |
| 14842 |
{ 'begin': 0x102A0, 'end': 0x102DF }, // Carian |
| 14843 |
{ 'begin': 0x1F030, 'end': 0x1F09F } // Domino Tiles |
| 14844 |
]; |
| 14845 |
|
| 14846 |
var MacStandardGlyphOrdering = [ |
| 14847 |
'.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', |
| 14848 |
'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', |
| 14849 |
'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', |
| 14850 |
'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', |
| 14851 |
'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', |
| 14852 |
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', |
| 14853 |
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', |
| 14854 |
'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', |
| 14855 |
'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', |
| 14856 |
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', |
| 14857 |
'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', |
| 14858 |
'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', |
| 14859 |
'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', |
| 14860 |
'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', |
| 14861 |
'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', |
| 14862 |
'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', |
| 14863 |
'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', |
| 14864 |
'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', |
| 14865 |
'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', |
| 14866 |
'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', |
| 14867 |
'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', |
| 14868 |
'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', |
| 14869 |
'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', |
| 14870 |
'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', |
| 14871 |
'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', |
| 14872 |
'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', |
| 14873 |
'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', |
| 14874 |
'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', |
| 14875 |
'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', |
| 14876 |
'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', |
| 14877 |
'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', |
| 14878 |
'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', |
| 14879 |
'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', |
| 14880 |
'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter', |
| 14881 |
'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', |
| 14882 |
'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat']; |
| 14883 |
|
| 14884 |
function getUnicodeRangeFor(value) { |
| 14885 |
for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) { |
| 14886 |
var range = UnicodeRanges[i]; |
| 14887 |
if (value >= range.begin && value < range.end) { |
| 14888 |
return i; |
| 14889 |
} |
| 14890 |
} |
| 14891 |
return -1; |
| 14892 |
} |
| 14893 |
|
| 14894 |
function isRTLRangeFor(value) { |
| 14895 |
var range = UnicodeRanges[13]; |
| 14896 |
if (value >= range.begin && value < range.end) { |
| 14897 |
return true; |
| 14898 |
} |
| 14899 |
range = UnicodeRanges[11]; |
| 14900 |
if (value >= range.begin && value < range.end) { |
| 14901 |
return true; |
| 14902 |
} |
| 14903 |
return false; |
| 14904 |
} |
| 14905 |
|
| 14906 |
// The normalization table is obtained by filtering the Unicode characters |
| 14907 |
// database with <compat> entries. |
| 14908 |
var NormalizedUnicodes = { |
| 14909 |
'\u00A8': '\u0020\u0308', |
| 14910 |
'\u00AF': '\u0020\u0304', |
| 14911 |
'\u00B4': '\u0020\u0301', |
| 14912 |
'\u00B5': '\u03BC', |
| 14913 |
'\u00B8': '\u0020\u0327', |
| 14914 |
'\u0132': '\u0049\u004A', |
| 14915 |
'\u0133': '\u0069\u006A', |
| 14916 |
'\u013F': '\u004C\u00B7', |
| 14917 |
'\u0140': '\u006C\u00B7', |
| 14918 |
'\u0149': '\u02BC\u006E', |
| 14919 |
'\u017F': '\u0073', |
| 14920 |
'\u01C4': '\u0044\u017D', |
| 14921 |
'\u01C5': '\u0044\u017E', |
| 14922 |
'\u01C6': '\u0064\u017E', |
| 14923 |
'\u01C7': '\u004C\u004A', |
| 14924 |
'\u01C8': '\u004C\u006A', |
| 14925 |
'\u01C9': '\u006C\u006A', |
| 14926 |
'\u01CA': '\u004E\u004A', |
| 14927 |
'\u01CB': '\u004E\u006A', |
| 14928 |
'\u01CC': '\u006E\u006A', |
| 14929 |
'\u01F1': '\u0044\u005A', |
| 14930 |
'\u01F2': '\u0044\u007A', |
| 14931 |
'\u01F3': '\u0064\u007A', |
| 14932 |
'\u02D8': '\u0020\u0306', |
| 14933 |
'\u02D9': '\u0020\u0307', |
| 14934 |
'\u02DA': '\u0020\u030A', |
| 14935 |
'\u02DB': '\u0020\u0328', |
| 14936 |
'\u02DC': '\u0020\u0303', |
| 14937 |
'\u02DD': '\u0020\u030B', |
| 14938 |
'\u037A': '\u0020\u0345', |
| 14939 |
'\u0384': '\u0020\u0301', |
| 14940 |
'\u03D0': '\u03B2', |
| 14941 |
'\u03D1': '\u03B8', |
| 14942 |
'\u03D2': '\u03A5', |
| 14943 |
'\u03D5': '\u03C6', |
| 14944 |
'\u03D6': '\u03C0', |
| 14945 |
'\u03F0': '\u03BA', |
| 14946 |
'\u03F1': '\u03C1', |
| 14947 |
'\u03F2': '\u03C2', |
| 14948 |
'\u03F4': '\u0398', |
| 14949 |
'\u03F5': '\u03B5', |
| 14950 |
'\u03F9': '\u03A3', |
| 14951 |
'\u0587': '\u0565\u0582', |
| 14952 |
'\u0675': '\u0627\u0674', |
| 14953 |
'\u0676': '\u0648\u0674', |
| 14954 |
'\u0677': '\u06C7\u0674', |
| 14955 |
'\u0678': '\u064A\u0674', |
| 14956 |
'\u0E33': '\u0E4D\u0E32', |
| 14957 |
'\u0EB3': '\u0ECD\u0EB2', |
| 14958 |
'\u0EDC': '\u0EAB\u0E99', |
| 14959 |
'\u0EDD': '\u0EAB\u0EA1', |
| 14960 |
'\u0F77': '\u0FB2\u0F81', |
| 14961 |
'\u0F79': '\u0FB3\u0F81', |
| 14962 |
'\u1E9A': '\u0061\u02BE', |
| 14963 |
'\u1FBD': '\u0020\u0313', |
| 14964 |
'\u1FBF': '\u0020\u0313', |
| 14965 |
'\u1FC0': '\u0020\u0342', |
| 14966 |
'\u1FFE': '\u0020\u0314', |
| 14967 |
'\u2002': '\u0020', |
| 14968 |
'\u2003': '\u0020', |
| 14969 |
'\u2004': '\u0020', |
| 14970 |
'\u2005': '\u0020', |
| 14971 |
'\u2006': '\u0020', |
| 14972 |
'\u2008': '\u0020', |
| 14973 |
'\u2009': '\u0020', |
| 14974 |
'\u200A': '\u0020', |
| 14975 |
'\u2017': '\u0020\u0333', |
| 14976 |
'\u2024': '\u002E', |
| 14977 |
'\u2025': '\u002E\u002E', |
| 14978 |
'\u2026': '\u002E\u002E\u002E', |
| 14979 |
'\u2033': '\u2032\u2032', |
| 14980 |
'\u2034': '\u2032\u2032\u2032', |
| 14981 |
'\u2036': '\u2035\u2035', |
| 14982 |
'\u2037': '\u2035\u2035\u2035', |
| 14983 |
'\u203C': '\u0021\u0021', |
| 14984 |
'\u203E': '\u0020\u0305', |
| 14985 |
'\u2047': '\u003F\u003F', |
| 14986 |
'\u2048': '\u003F\u0021', |
| 14987 |
'\u2049': '\u0021\u003F', |
| 14988 |
'\u2057': '\u2032\u2032\u2032\u2032', |
| 14989 |
'\u205F': '\u0020', |
| 14990 |
'\u20A8': '\u0052\u0073', |
| 14991 |
'\u2100': '\u0061\u002F\u0063', |
| 14992 |
'\u2101': '\u0061\u002F\u0073', |
| 14993 |
'\u2103': '\u00B0\u0043', |
| 14994 |
'\u2105': '\u0063\u002F\u006F', |
| 14995 |
'\u2106': '\u0063\u002F\u0075', |
| 14996 |
'\u2107': '\u0190', |
| 14997 |
'\u2109': '\u00B0\u0046', |
| 14998 |
'\u2116': '\u004E\u006F', |
| 14999 |
'\u2121': '\u0054\u0045\u004C', |
| 15000 |
'\u2135': '\u05D0', |
| 15001 |
'\u2136': '\u05D1', |
| 15002 |
'\u2137': '\u05D2', |
| 15003 |
'\u2138': '\u05D3', |
| 15004 |
'\u213B': '\u0046\u0041\u0058', |
| 15005 |
'\u2160': '\u0049', |
| 15006 |
'\u2161': '\u0049\u0049', |
| 15007 |
'\u2162': '\u0049\u0049\u0049', |
| 15008 |
'\u2163': '\u0049\u0056', |
| 15009 |
'\u2164': '\u0056', |
| 15010 |
'\u2165': '\u0056\u0049', |
| 15011 |
'\u2166': '\u0056\u0049\u0049', |
| 15012 |
'\u2167': '\u0056\u0049\u0049\u0049', |
| 15013 |
'\u2168': '\u0049\u0058', |
| 15014 |
'\u2169': '\u0058', |
| 15015 |
'\u216A': '\u0058\u0049', |
| 15016 |
'\u216B': '\u0058\u0049\u0049', |
| 15017 |
'\u216C': '\u004C', |
| 15018 |
'\u216D': '\u0043', |
| 15019 |
'\u216E': '\u0044', |
| 15020 |
'\u216F': '\u004D', |
| 15021 |
'\u2170': '\u0069', |
| 15022 |
'\u2171': '\u0069\u0069', |
| 15023 |
'\u2172': '\u0069\u0069\u0069', |
| 15024 |
'\u2173': '\u0069\u0076', |
| 15025 |
'\u2174': '\u0076', |
| 15026 |
'\u2175': '\u0076\u0069', |
| 15027 |
'\u2176': '\u0076\u0069\u0069', |
| 15028 |
'\u2177': '\u0076\u0069\u0069\u0069', |
| 15029 |
'\u2178': '\u0069\u0078', |
| 15030 |
'\u2179': '\u0078', |
| 15031 |
'\u217A': '\u0078\u0069', |
| 15032 |
'\u217B': '\u0078\u0069\u0069', |
| 15033 |
'\u217C': '\u006C', |
| 15034 |
'\u217D': '\u0063', |
| 15035 |
'\u217E': '\u0064', |
| 15036 |
'\u217F': '\u006D', |
| 15037 |
'\u222C': '\u222B\u222B', |
| 15038 |
'\u222D': '\u222B\u222B\u222B', |
| 15039 |
'\u222F': '\u222E\u222E', |
| 15040 |
'\u2230': '\u222E\u222E\u222E', |
| 15041 |
'\u2474': '\u0028\u0031\u0029', |
| 15042 |
'\u2475': '\u0028\u0032\u0029', |
| 15043 |
'\u2476': '\u0028\u0033\u0029', |
| 15044 |
'\u2477': '\u0028\u0034\u0029', |
| 15045 |
'\u2478': '\u0028\u0035\u0029', |
| 15046 |
'\u2479': '\u0028\u0036\u0029', |
| 15047 |
'\u247A': '\u0028\u0037\u0029', |
| 15048 |
'\u247B': '\u0028\u0038\u0029', |
| 15049 |
'\u247C': '\u0028\u0039\u0029', |
| 15050 |
'\u247D': '\u0028\u0031\u0030\u0029', |
| 15051 |
'\u247E': '\u0028\u0031\u0031\u0029', |
| 15052 |
'\u247F': '\u0028\u0031\u0032\u0029', |
| 15053 |
'\u2480': '\u0028\u0031\u0033\u0029', |
| 15054 |
'\u2481': '\u0028\u0031\u0034\u0029', |
| 15055 |
'\u2482': '\u0028\u0031\u0035\u0029', |
| 15056 |
'\u2483': '\u0028\u0031\u0036\u0029', |
| 15057 |
'\u2484': '\u0028\u0031\u0037\u0029', |
| 15058 |
'\u2485': '\u0028\u0031\u0038\u0029', |
| 15059 |
'\u2486': '\u0028\u0031\u0039\u0029', |
| 15060 |
'\u2487': '\u0028\u0032\u0030\u0029', |
| 15061 |
'\u2488': '\u0031\u002E', |
| 15062 |
'\u2489': '\u0032\u002E', |
| 15063 |
'\u248A': '\u0033\u002E', |
| 15064 |
'\u248B': '\u0034\u002E', |
| 15065 |
'\u248C': '\u0035\u002E', |
| 15066 |
'\u248D': '\u0036\u002E', |
| 15067 |
'\u248E': '\u0037\u002E', |
| 15068 |
'\u248F': '\u0038\u002E', |
| 15069 |
'\u2490': '\u0039\u002E', |
| 15070 |
'\u2491': '\u0031\u0030\u002E', |
| 15071 |
'\u2492': '\u0031\u0031\u002E', |
| 15072 |
'\u2493': '\u0031\u0032\u002E', |
| 15073 |
'\u2494': '\u0031\u0033\u002E', |
| 15074 |
'\u2495': '\u0031\u0034\u002E', |
| 15075 |
'\u2496': '\u0031\u0035\u002E', |
| 15076 |
'\u2497': '\u0031\u0036\u002E', |
| 15077 |
'\u2498': '\u0031\u0037\u002E', |
| 15078 |
'\u2499': '\u0031\u0038\u002E', |
| 15079 |
'\u249A': '\u0031\u0039\u002E', |
| 15080 |
'\u249B': '\u0032\u0030\u002E', |
| 15081 |
'\u249C': '\u0028\u0061\u0029', |
| 15082 |
'\u249D': '\u0028\u0062\u0029', |
| 15083 |
'\u249E': '\u0028\u0063\u0029', |
| 15084 |
'\u249F': '\u0028\u0064\u0029', |
| 15085 |
'\u24A0': '\u0028\u0065\u0029', |
| 15086 |
'\u24A1': '\u0028\u0066\u0029', |
| 15087 |
'\u24A2': '\u0028\u0067\u0029', |
| 15088 |
'\u24A3': '\u0028\u0068\u0029', |
| 15089 |
'\u24A4': '\u0028\u0069\u0029', |
| 15090 |
'\u24A5': '\u0028\u006A\u0029', |
| 15091 |
'\u24A6': '\u0028\u006B\u0029', |
| 15092 |
'\u24A7': '\u0028\u006C\u0029', |
| 15093 |
'\u24A8': '\u0028\u006D\u0029', |
| 15094 |
'\u24A9': '\u0028\u006E\u0029', |
| 15095 |
'\u24AA': '\u0028\u006F\u0029', |
| 15096 |
'\u24AB': '\u0028\u0070\u0029', |
| 15097 |
'\u24AC': '\u0028\u0071\u0029', |
| 15098 |
'\u24AD': '\u0028\u0072\u0029', |
| 15099 |
'\u24AE': '\u0028\u0073\u0029', |
| 15100 |
'\u24AF': '\u0028\u0074\u0029', |
| 15101 |
'\u24B0': '\u0028\u0075\u0029', |
| 15102 |
'\u24B1': '\u0028\u0076\u0029', |
| 15103 |
'\u24B2': '\u0028\u0077\u0029', |
| 15104 |
'\u24B3': '\u0028\u0078\u0029', |
| 15105 |
'\u24B4': '\u0028\u0079\u0029', |
| 15106 |
'\u24B5': '\u0028\u007A\u0029', |
| 15107 |
'\u2A0C': '\u222B\u222B\u222B\u222B', |
| 15108 |
'\u2A74': '\u003A\u003A\u003D', |
| 15109 |
'\u2A75': '\u003D\u003D', |
| 15110 |
'\u2A76': '\u003D\u003D\u003D', |
| 15111 |
'\u2E9F': '\u6BCD', |
| 15112 |
'\u2EF3': '\u9F9F', |
| 15113 |
'\u2F00': '\u4E00', |
| 15114 |
'\u2F01': '\u4E28', |
| 15115 |
'\u2F02': '\u4E36', |
| 15116 |
'\u2F03': '\u4E3F', |
| 15117 |
'\u2F04': '\u4E59', |
| 15118 |
'\u2F05': '\u4E85', |
| 15119 |
'\u2F06': '\u4E8C', |
| 15120 |
'\u2F07': '\u4EA0', |
| 15121 |
'\u2F08': '\u4EBA', |
| 15122 |
'\u2F09': '\u513F', |
| 15123 |
'\u2F0A': '\u5165', |
| 15124 |
'\u2F0B': '\u516B', |
| 15125 |
'\u2F0C': '\u5182', |
| 15126 |
'\u2F0D': '\u5196', |
| 15127 |
'\u2F0E': '\u51AB', |
| 15128 |
'\u2F0F': '\u51E0', |
| 15129 |
'\u2F10': '\u51F5', |
| 15130 |
'\u2F11': '\u5200', |
| 15131 |
'\u2F12': '\u529B', |
| 15132 |
'\u2F13': '\u52F9', |
| 15133 |
'\u2F14': '\u5315', |
| 15134 |
'\u2F15': '\u531A', |
| 15135 |
'\u2F16': '\u5338', |
| 15136 |
'\u2F17': '\u5341', |
| 15137 |
'\u2F18': '\u535C', |
| 15138 |
'\u2F19': '\u5369', |
| 15139 |
'\u2F1A': '\u5382', |
| 15140 |
'\u2F1B': '\u53B6', |
| 15141 |
'\u2F1C': '\u53C8', |
| 15142 |
'\u2F1D': '\u53E3', |
| 15143 |
'\u2F1E': '\u56D7', |
| 15144 |
'\u2F1F': '\u571F', |
| 15145 |
'\u2F20': '\u58EB', |
| 15146 |
'\u2F21': '\u5902', |
| 15147 |
'\u2F22': '\u590A', |
| 15148 |
'\u2F23': '\u5915', |
| 15149 |
'\u2F24': '\u5927', |
| 15150 |
'\u2F25': '\u5973', |
| 15151 |
'\u2F26': '\u5B50', |
| 15152 |
'\u2F27': '\u5B80', |
| 15153 |
'\u2F28': '\u5BF8', |
| 15154 |
'\u2F29': '\u5C0F', |
| 15155 |
'\u2F2A': '\u5C22', |
| 15156 |
'\u2F2B': '\u5C38', |
| 15157 |
'\u2F2C': '\u5C6E', |
| 15158 |
'\u2F2D': '\u5C71', |
| 15159 |
'\u2F2E': '\u5DDB', |
| 15160 |
'\u2F2F': '\u5DE5', |
| 15161 |
'\u2F30': '\u5DF1', |
| 15162 |
'\u2F31': '\u5DFE', |
| 15163 |
'\u2F32': '\u5E72', |
| 15164 |
'\u2F33': '\u5E7A', |
| 15165 |
'\u2F34': '\u5E7F', |
| 15166 |
'\u2F35': '\u5EF4', |
| 15167 |
'\u2F36': '\u5EFE', |
| 15168 |
'\u2F37': '\u5F0B', |
| 15169 |
'\u2F38': '\u5F13', |
| 15170 |
'\u2F39': '\u5F50', |
| 15171 |
'\u2F3A': '\u5F61', |
| 15172 |
'\u2F3B': '\u5F73', |
| 15173 |
'\u2F3C': '\u5FC3', |
| 15174 |
'\u2F3D': '\u6208', |
| 15175 |
'\u2F3E': '\u6236', |
| 15176 |
'\u2F3F': '\u624B', |
| 15177 |
'\u2F40': '\u652F', |
| 15178 |
'\u2F41': '\u6534', |
| 15179 |
'\u2F42': '\u6587', |
| 15180 |
'\u2F43': '\u6597', |
| 15181 |
'\u2F44': '\u65A4', |
| 15182 |
'\u2F45': '\u65B9', |
| 15183 |
'\u2F46': '\u65E0', |
| 15184 |
'\u2F47': '\u65E5', |
| 15185 |
'\u2F48': '\u66F0', |
| 15186 |
'\u2F49': '\u6708', |
| 15187 |
'\u2F4A': '\u6728', |
| 15188 |
'\u2F4B': '\u6B20', |
| 15189 |
'\u2F4C': '\u6B62', |
| 15190 |
'\u2F4D': '\u6B79', |
| 15191 |
'\u2F4E': '\u6BB3', |
| 15192 |
'\u2F4F': '\u6BCB', |
| 15193 |
'\u2F50': '\u6BD4', |
| 15194 |
'\u2F51': '\u6BDB', |
| 15195 |
'\u2F52': '\u6C0F', |
| 15196 |
'\u2F53': '\u6C14', |
| 15197 |
'\u2F54': '\u6C34', |
| 15198 |
'\u2F55': '\u706B', |
| 15199 |
'\u2F56': '\u722A', |
| 15200 |
'\u2F57': '\u7236', |
| 15201 |
'\u2F58': '\u723B', |
| 15202 |
'\u2F59': '\u723F', |
| 15203 |
'\u2F5A': '\u7247', |
| 15204 |
'\u2F5B': '\u7259', |
| 15205 |
'\u2F5C': '\u725B', |
| 15206 |
'\u2F5D': '\u72AC', |
| 15207 |
'\u2F5E': '\u7384', |
| 15208 |
'\u2F5F': '\u7389', |
| 15209 |
'\u2F60': '\u74DC', |
| 15210 |
'\u2F61': '\u74E6', |
| 15211 |
'\u2F62': '\u7518', |
| 15212 |
'\u2F63': '\u751F', |
| 15213 |
'\u2F64': '\u7528', |
| 15214 |
'\u2F65': '\u7530', |
| 15215 |
'\u2F66': '\u758B', |
| 15216 |
'\u2F67': '\u7592', |
| 15217 |
'\u2F68': '\u7676', |
| 15218 |
'\u2F69': '\u767D', |
| 15219 |
'\u2F6A': '\u76AE', |
| 15220 |
'\u2F6B': '\u76BF', |
| 15221 |
'\u2F6C': '\u76EE', |
| 15222 |
'\u2F6D': '\u77DB', |
| 15223 |
'\u2F6E': '\u77E2', |
| 15224 |
'\u2F6F': '\u77F3', |
| 15225 |
'\u2F70': '\u793A', |
| 15226 |
'\u2F71': '\u79B8', |
| 15227 |
'\u2F72': '\u79BE', |
| 15228 |
'\u2F73': '\u7A74', |
| 15229 |
'\u2F74': '\u7ACB', |
| 15230 |
'\u2F75': '\u7AF9', |
| 15231 |
'\u2F76': '\u7C73', |
| 15232 |
'\u2F77': '\u7CF8', |
| 15233 |
'\u2F78': '\u7F36', |
| 15234 |
'\u2F79': '\u7F51', |
| 15235 |
'\u2F7A': '\u7F8A', |
| 15236 |
'\u2F7B': '\u7FBD', |
| 15237 |
'\u2F7C': '\u8001', |
| 15238 |
'\u2F7D': '\u800C', |
| 15239 |
'\u2F7E': '\u8012', |
| 15240 |
'\u2F7F': '\u8033', |
| 15241 |
'\u2F80': '\u807F', |
| 15242 |
'\u2F81': '\u8089', |
| 15243 |
'\u2F82': '\u81E3', |
| 15244 |
'\u2F83': '\u81EA', |
| 15245 |
'\u2F84': '\u81F3', |
| 15246 |
'\u2F85': '\u81FC', |
| 15247 |
'\u2F86': '\u820C', |
| 15248 |
'\u2F87': '\u821B', |
| 15249 |
'\u2F88': '\u821F', |
| 15250 |
'\u2F89': '\u826E', |
| 15251 |
'\u2F8A': '\u8272', |
| 15252 |
'\u2F8B': '\u8278', |
| 15253 |
'\u2F8C': '\u864D', |
| 15254 |
'\u2F8D': '\u866B', |
| 15255 |
'\u2F8E': '\u8840', |
| 15256 |
'\u2F8F': '\u884C', |
| 15257 |
'\u2F90': '\u8863', |
| 15258 |
'\u2F91': '\u897E', |
| 15259 |
'\u2F92': '\u898B', |
| 15260 |
'\u2F93': '\u89D2', |
| 15261 |
'\u2F94': '\u8A00', |
| 15262 |
'\u2F95': '\u8C37', |
| 15263 |
'\u2F96': '\u8C46', |
| 15264 |
'\u2F97': '\u8C55', |
| 15265 |
'\u2F98': '\u8C78', |
| 15266 |
'\u2F99': '\u8C9D', |
| 15267 |
'\u2F9A': '\u8D64', |
| 15268 |
'\u2F9B': '\u8D70', |
| 15269 |
'\u2F9C': '\u8DB3', |
| 15270 |
'\u2F9D': '\u8EAB', |
| 15271 |
'\u2F9E': '\u8ECA', |
| 15272 |
'\u2F9F': '\u8F9B', |
| 15273 |
'\u2FA0': '\u8FB0', |
| 15274 |
'\u2FA1': '\u8FB5', |
| 15275 |
'\u2FA2': '\u9091', |
| 15276 |
'\u2FA3': '\u9149', |
| 15277 |
'\u2FA4': '\u91C6', |
| 15278 |
'\u2FA5': '\u91CC', |
| 15279 |
'\u2FA6': '\u91D1', |
| 15280 |
'\u2FA7': '\u9577', |
| 15281 |
'\u2FA8': '\u9580', |
| 15282 |
'\u2FA9': '\u961C', |
| 15283 |
'\u2FAA': '\u96B6', |
| 15284 |
'\u2FAB': '\u96B9', |
| 15285 |
'\u2FAC': '\u96E8', |
| 15286 |
'\u2FAD': '\u9751', |
| 15287 |
'\u2FAE': '\u975E', |
| 15288 |
'\u2FAF': '\u9762', |
| 15289 |
'\u2FB0': '\u9769', |
| 15290 |
'\u2FB1': '\u97CB', |
| 15291 |
'\u2FB2': '\u97ED', |
| 15292 |
'\u2FB3': '\u97F3', |
| 15293 |
'\u2FB4': '\u9801', |
| 15294 |
'\u2FB5': '\u98A8', |
| 15295 |
'\u2FB6': '\u98DB', |
| 15296 |
'\u2FB7': '\u98DF', |
| 15297 |
'\u2FB8': '\u9996', |
| 15298 |
'\u2FB9': '\u9999', |
| 15299 |
'\u2FBA': '\u99AC', |
| 15300 |
'\u2FBB': '\u9AA8', |
| 15301 |
'\u2FBC': '\u9AD8', |
| 15302 |
'\u2FBD': '\u9ADF', |
| 15303 |
'\u2FBE': '\u9B25', |
| 15304 |
'\u2FBF': '\u9B2F', |
| 15305 |
'\u2FC0': '\u9B32', |
| 15306 |
'\u2FC1': '\u9B3C', |
| 15307 |
'\u2FC2': '\u9B5A', |
| 15308 |
'\u2FC3': '\u9CE5', |
| 15309 |
'\u2FC4': '\u9E75', |
| 15310 |
'\u2FC5': '\u9E7F', |
| 15311 |
'\u2FC6': '\u9EA5', |
| 15312 |
'\u2FC7': '\u9EBB', |
| 15313 |
'\u2FC8': '\u9EC3', |
| 15314 |
'\u2FC9': '\u9ECD', |
| 15315 |
'\u2FCA': '\u9ED1', |
| 15316 |
'\u2FCB': '\u9EF9', |
| 15317 |
'\u2FCC': '\u9EFD', |
| 15318 |
'\u2FCD': '\u9F0E', |
| 15319 |
'\u2FCE': '\u9F13', |
| 15320 |
'\u2FCF': '\u9F20', |
| 15321 |
'\u2FD0': '\u9F3B', |
| 15322 |
'\u2FD1': '\u9F4A', |
| 15323 |
'\u2FD2': '\u9F52', |
| 15324 |
'\u2FD3': '\u9F8D', |
| 15325 |
'\u2FD4': '\u9F9C', |
| 15326 |
'\u2FD5': '\u9FA0', |
| 15327 |
'\u3036': '\u3012', |
| 15328 |
'\u3038': '\u5341', |
| 15329 |
'\u3039': '\u5344', |
| 15330 |
'\u303A': '\u5345', |
| 15331 |
'\u309B': '\u0020\u3099', |
| 15332 |
'\u309C': '\u0020\u309A', |
| 15333 |
'\u3131': '\u1100', |
| 15334 |
'\u3132': '\u1101', |
| 15335 |
'\u3133': '\u11AA', |
| 15336 |
'\u3134': '\u1102', |
| 15337 |
'\u3135': '\u11AC', |
| 15338 |
'\u3136': '\u11AD', |
| 15339 |
'\u3137': '\u1103', |
| 15340 |
'\u3138': '\u1104', |
| 15341 |
'\u3139': '\u1105', |
| 15342 |
'\u313A': '\u11B0', |
| 15343 |
'\u313B': '\u11B1', |
| 15344 |
'\u313C': '\u11B2', |
| 15345 |
'\u313D': '\u11B3', |
| 15346 |
'\u313E': '\u11B4', |
| 15347 |
'\u313F': '\u11B5', |
| 15348 |
'\u3140': '\u111A', |
| 15349 |
'\u3141': '\u1106', |
| 15350 |
'\u3142': '\u1107', |
| 15351 |
'\u3143': '\u1108', |
| 15352 |
'\u3144': '\u1121', |
| 15353 |
'\u3145': '\u1109', |
| 15354 |
'\u3146': '\u110A', |
| 15355 |
'\u3147': '\u110B', |
| 15356 |
'\u3148': '\u110C', |
| 15357 |
'\u3149': '\u110D', |
| 15358 |
'\u314A': '\u110E', |
| 15359 |
'\u314B': '\u110F', |
| 15360 |
'\u314C': '\u1110', |
| 15361 |
'\u314D': '\u1111', |
| 15362 |
'\u314E': '\u1112', |
| 15363 |
'\u314F': '\u1161', |
| 15364 |
'\u3150': '\u1162', |
| 15365 |
'\u3151': '\u1163', |
| 15366 |
'\u3152': '\u1164', |
| 15367 |
'\u3153': '\u1165', |
| 15368 |
'\u3154': '\u1166', |
| 15369 |
'\u3155': '\u1167', |
| 15370 |
'\u3156': '\u1168', |
| 15371 |
'\u3157': '\u1169', |
| 15372 |
'\u3158': '\u116A', |
| 15373 |
'\u3159': '\u116B', |
| 15374 |
'\u315A': '\u116C', |
| 15375 |
'\u315B': '\u116D', |
| 15376 |
'\u315C': '\u116E', |
| 15377 |
'\u315D': '\u116F', |
| 15378 |
'\u315E': '\u1170', |
| 15379 |
'\u315F': '\u1171', |
| 15380 |
'\u3160': '\u1172', |
| 15381 |
'\u3161': '\u1173', |
| 15382 |
'\u3162': '\u1174', |
| 15383 |
'\u3163': '\u1175', |
| 15384 |
'\u3164': '\u1160', |
| 15385 |
'\u3165': '\u1114', |
| 15386 |
'\u3166': '\u1115', |
| 15387 |
'\u3167': '\u11C7', |
| 15388 |
'\u3168': '\u11C8', |
| 15389 |
'\u3169': '\u11CC', |
| 15390 |
'\u316A': '\u11CE', |
| 15391 |
'\u316B': '\u11D3', |
| 15392 |
'\u316C': '\u11D7', |
| 15393 |
'\u316D': '\u11D9', |
| 15394 |
'\u316E': '\u111C', |
| 15395 |
'\u316F': '\u11DD', |
| 15396 |
'\u3170': '\u11DF', |
| 15397 |
'\u3171': '\u111D', |
| 15398 |
'\u3172': '\u111E', |
| 15399 |
'\u3173': '\u1120', |
| 15400 |
'\u3174': '\u1122', |
| 15401 |
'\u3175': '\u1123', |
| 15402 |
'\u3176': '\u1127', |
| 15403 |
'\u3177': '\u1129', |
| 15404 |
'\u3178': '\u112B', |
| 15405 |
'\u3179': '\u112C', |
| 15406 |
'\u317A': '\u112D', |
| 15407 |
'\u317B': '\u112E', |
| 15408 |
'\u317C': '\u112F', |
| 15409 |
'\u317D': '\u1132', |
| 15410 |
'\u317E': '\u1136', |
| 15411 |
'\u317F': '\u1140', |
| 15412 |
'\u3180': '\u1147', |
| 15413 |
'\u3181': '\u114C', |
| 15414 |
'\u3182': '\u11F1', |
| 15415 |
'\u3183': '\u11F2', |
| 15416 |
'\u3184': '\u1157', |
| 15417 |
'\u3185': '\u1158', |
| 15418 |
'\u3186': '\u1159', |
| 15419 |
'\u3187': '\u1184', |
| 15420 |
'\u3188': '\u1185', |
| 15421 |
'\u3189': '\u1188', |
| 15422 |
'\u318A': '\u1191', |
| 15423 |
'\u318B': '\u1192', |
| 15424 |
'\u318C': '\u1194', |
| 15425 |
'\u318D': '\u119E', |
| 15426 |
'\u318E': '\u11A1', |
| 15427 |
'\u3200': '\u0028\u1100\u0029', |
| 15428 |
'\u3201': '\u0028\u1102\u0029', |
| 15429 |
'\u3202': '\u0028\u1103\u0029', |
| 15430 |
'\u3203': '\u0028\u1105\u0029', |
| 15431 |
'\u3204': '\u0028\u1106\u0029', |
| 15432 |
'\u3205': '\u0028\u1107\u0029', |
| 15433 |
'\u3206': '\u0028\u1109\u0029', |
| 15434 |
'\u3207': '\u0028\u110B\u0029', |
| 15435 |
'\u3208': '\u0028\u110C\u0029', |
| 15436 |
'\u3209': '\u0028\u110E\u0029', |
| 15437 |
'\u320A': '\u0028\u110F\u0029', |
| 15438 |
'\u320B': '\u0028\u1110\u0029', |
| 15439 |
'\u320C': '\u0028\u1111\u0029', |
| 15440 |
'\u320D': '\u0028\u1112\u0029', |
| 15441 |
'\u320E': '\u0028\u1100\u1161\u0029', |
| 15442 |
'\u320F': '\u0028\u1102\u1161\u0029', |
| 15443 |
'\u3210': '\u0028\u1103\u1161\u0029', |
| 15444 |
'\u3211': '\u0028\u1105\u1161\u0029', |
| 15445 |
'\u3212': '\u0028\u1106\u1161\u0029', |
| 15446 |
'\u3213': '\u0028\u1107\u1161\u0029', |
| 15447 |
'\u3214': '\u0028\u1109\u1161\u0029', |
| 15448 |
'\u3215': '\u0028\u110B\u1161\u0029', |
| 15449 |
'\u3216': '\u0028\u110C\u1161\u0029', |
| 15450 |
'\u3217': '\u0028\u110E\u1161\u0029', |
| 15451 |
'\u3218': '\u0028\u110F\u1161\u0029', |
| 15452 |
'\u3219': '\u0028\u1110\u1161\u0029', |
| 15453 |
'\u321A': '\u0028\u1111\u1161\u0029', |
| 15454 |
'\u321B': '\u0028\u1112\u1161\u0029', |
| 15455 |
'\u321C': '\u0028\u110C\u116E\u0029', |
| 15456 |
'\u321D': '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029', |
| 15457 |
'\u321E': '\u0028\u110B\u1169\u1112\u116E\u0029', |
| 15458 |
'\u3220': '\u0028\u4E00\u0029', |
| 15459 |
'\u3221': '\u0028\u4E8C\u0029', |
| 15460 |
'\u3222': '\u0028\u4E09\u0029', |
| 15461 |
'\u3223': '\u0028\u56DB\u0029', |
| 15462 |
'\u3224': '\u0028\u4E94\u0029', |
| 15463 |
'\u3225': '\u0028\u516D\u0029', |
| 15464 |
'\u3226': '\u0028\u4E03\u0029', |
| 15465 |
'\u3227': '\u0028\u516B\u0029', |
| 15466 |
'\u3228': '\u0028\u4E5D\u0029', |
| 15467 |
'\u3229': '\u0028\u5341\u0029', |
| 15468 |
'\u322A': '\u0028\u6708\u0029', |
| 15469 |
'\u322B': '\u0028\u706B\u0029', |
| 15470 |
'\u322C': '\u0028\u6C34\u0029', |
| 15471 |
'\u322D': '\u0028\u6728\u0029', |
| 15472 |
'\u322E': '\u0028\u91D1\u0029', |
| 15473 |
'\u322F': '\u0028\u571F\u0029', |
| 15474 |
'\u3230': '\u0028\u65E5\u0029', |
| 15475 |
'\u3231': '\u0028\u682A\u0029', |
| 15476 |
'\u3232': '\u0028\u6709\u0029', |
| 15477 |
'\u3233': '\u0028\u793E\u0029', |
| 15478 |
'\u3234': '\u0028\u540D\u0029', |
| 15479 |
'\u3235': '\u0028\u7279\u0029', |
| 15480 |
'\u3236': '\u0028\u8CA1\u0029', |
| 15481 |
'\u3237': '\u0028\u795D\u0029', |
| 15482 |
'\u3238': '\u0028\u52B4\u0029', |
| 15483 |
'\u3239': '\u0028\u4EE3\u0029', |
| 15484 |
'\u323A': '\u0028\u547C\u0029', |
| 15485 |
'\u323B': '\u0028\u5B66\u0029', |
| 15486 |
'\u323C': '\u0028\u76E3\u0029', |
| 15487 |
'\u323D': '\u0028\u4F01\u0029', |
| 15488 |
'\u323E': '\u0028\u8CC7\u0029', |
| 15489 |
'\u323F': '\u0028\u5354\u0029', |
| 15490 |
'\u3240': '\u0028\u796D\u0029', |
| 15491 |
'\u3241': '\u0028\u4F11\u0029', |
| 15492 |
'\u3242': '\u0028\u81EA\u0029', |
| 15493 |
'\u3243': '\u0028\u81F3\u0029', |
| 15494 |
'\u32C0': '\u0031\u6708', |
| 15495 |
'\u32C1': '\u0032\u6708', |
| 15496 |
'\u32C2': '\u0033\u6708', |
| 15497 |
'\u32C3': '\u0034\u6708', |
| 15498 |
'\u32C4': '\u0035\u6708', |
| 15499 |
'\u32C5': '\u0036\u6708', |
| 15500 |
'\u32C6': '\u0037\u6708', |
| 15501 |
'\u32C7': '\u0038\u6708', |
| 15502 |
'\u32C8': '\u0039\u6708', |
| 15503 |
'\u32C9': '\u0031\u0030\u6708', |
| 15504 |
'\u32CA': '\u0031\u0031\u6708', |
| 15505 |
'\u32CB': '\u0031\u0032\u6708', |
| 15506 |
'\u3358': '\u0030\u70B9', |
| 15507 |
'\u3359': '\u0031\u70B9', |
| 15508 |
'\u335A': '\u0032\u70B9', |
| 15509 |
'\u335B': '\u0033\u70B9', |
| 15510 |
'\u335C': '\u0034\u70B9', |
| 15511 |
'\u335D': '\u0035\u70B9', |
| 15512 |
'\u335E': '\u0036\u70B9', |
| 15513 |
'\u335F': '\u0037\u70B9', |
| 15514 |
'\u3360': '\u0038\u70B9', |
| 15515 |
'\u3361': '\u0039\u70B9', |
| 15516 |
'\u3362': '\u0031\u0030\u70B9', |
| 15517 |
'\u3363': '\u0031\u0031\u70B9', |
| 15518 |
'\u3364': '\u0031\u0032\u70B9', |
| 15519 |
'\u3365': '\u0031\u0033\u70B9', |
| 15520 |
'\u3366': '\u0031\u0034\u70B9', |
| 15521 |
'\u3367': '\u0031\u0035\u70B9', |
| 15522 |
'\u3368': '\u0031\u0036\u70B9', |
| 15523 |
'\u3369': '\u0031\u0037\u70B9', |
| 15524 |
'\u336A': '\u0031\u0038\u70B9', |
| 15525 |
'\u336B': '\u0031\u0039\u70B9', |
| 15526 |
'\u336C': '\u0032\u0030\u70B9', |
| 15527 |
'\u336D': '\u0032\u0031\u70B9', |
| 15528 |
'\u336E': '\u0032\u0032\u70B9', |
| 15529 |
'\u336F': '\u0032\u0033\u70B9', |
| 15530 |
'\u3370': '\u0032\u0034\u70B9', |
| 15531 |
'\u33E0': '\u0031\u65E5', |
| 15532 |
'\u33E1': '\u0032\u65E5', |
| 15533 |
'\u33E2': '\u0033\u65E5', |
| 15534 |
'\u33E3': '\u0034\u65E5', |
| 15535 |
'\u33E4': '\u0035\u65E5', |
| 15536 |
'\u33E5': '\u0036\u65E5', |
| 15537 |
'\u33E6': '\u0037\u65E5', |
| 15538 |
'\u33E7': '\u0038\u65E5', |
| 15539 |
'\u33E8': '\u0039\u65E5', |
| 15540 |
'\u33E9': '\u0031\u0030\u65E5', |
| 15541 |
'\u33EA': '\u0031\u0031\u65E5', |
| 15542 |
'\u33EB': '\u0031\u0032\u65E5', |
| 15543 |
'\u33EC': '\u0031\u0033\u65E5', |
| 15544 |
'\u33ED': '\u0031\u0034\u65E5', |
| 15545 |
'\u33EE': '\u0031\u0035\u65E5', |
| 15546 |
'\u33EF': '\u0031\u0036\u65E5', |
| 15547 |
'\u33F0': '\u0031\u0037\u65E5', |
| 15548 |
'\u33F1': '\u0031\u0038\u65E5', |
| 15549 |
'\u33F2': '\u0031\u0039\u65E5', |
| 15550 |
'\u33F3': '\u0032\u0030\u65E5', |
| 15551 |
'\u33F4': '\u0032\u0031\u65E5', |
| 15552 |
'\u33F5': '\u0032\u0032\u65E5', |
| 15553 |
'\u33F6': '\u0032\u0033\u65E5', |
| 15554 |
'\u33F7': '\u0032\u0034\u65E5', |
| 15555 |
'\u33F8': '\u0032\u0035\u65E5', |
| 15556 |
'\u33F9': '\u0032\u0036\u65E5', |
| 15557 |
'\u33FA': '\u0032\u0037\u65E5', |
| 15558 |
'\u33FB': '\u0032\u0038\u65E5', |
| 15559 |
'\u33FC': '\u0032\u0039\u65E5', |
| 15560 |
'\u33FD': '\u0033\u0030\u65E5', |
| 15561 |
'\u33FE': '\u0033\u0031\u65E5', |
| 15562 |
'\uFB00': '\u0066\u0066', |
| 15563 |
'\uFB01': '\u0066\u0069', |
| 15564 |
'\uFB02': '\u0066\u006C', |
| 15565 |
'\uFB03': '\u0066\u0066\u0069', |
| 15566 |
'\uFB04': '\u0066\u0066\u006C', |
| 15567 |
'\uFB05': '\u017F\u0074', |
| 15568 |
'\uFB06': '\u0073\u0074', |
| 15569 |
'\uFB13': '\u0574\u0576', |
| 15570 |
'\uFB14': '\u0574\u0565', |
| 15571 |
'\uFB15': '\u0574\u056B', |
| 15572 |
'\uFB16': '\u057E\u0576', |
| 15573 |
'\uFB17': '\u0574\u056D', |
| 15574 |
'\uFB4F': '\u05D0\u05DC', |
| 15575 |
'\uFB50': '\u0671', |
| 15576 |
'\uFB51': '\u0671', |
| 15577 |
'\uFB52': '\u067B', |
| 15578 |
'\uFB53': '\u067B', |
| 15579 |
'\uFB54': '\u067B', |
| 15580 |
'\uFB55': '\u067B', |
| 15581 |
'\uFB56': '\u067E', |
| 15582 |
'\uFB57': '\u067E', |
| 15583 |
'\uFB58': '\u067E', |
| 15584 |
'\uFB59': '\u067E', |
| 15585 |
'\uFB5A': '\u0680', |
| 15586 |
'\uFB5B': '\u0680', |
| 15587 |
'\uFB5C': '\u0680', |
| 15588 |
'\uFB5D': '\u0680', |
| 15589 |
'\uFB5E': '\u067A', |
| 15590 |
'\uFB5F': '\u067A', |
| 15591 |
'\uFB60': '\u067A', |
| 15592 |
'\uFB61': '\u067A', |
| 15593 |
'\uFB62': '\u067F', |
| 15594 |
'\uFB63': '\u067F', |
| 15595 |
'\uFB64': '\u067F', |
| 15596 |
'\uFB65': '\u067F', |
| 15597 |
'\uFB66': '\u0679', |
| 15598 |
'\uFB67': '\u0679', |
| 15599 |
'\uFB68': '\u0679', |
| 15600 |
'\uFB69': '\u0679', |
| 15601 |
'\uFB6A': '\u06A4', |
| 15602 |
'\uFB6B': '\u06A4', |
| 15603 |
'\uFB6C': '\u06A4', |
| 15604 |
'\uFB6D': '\u06A4', |
| 15605 |
'\uFB6E': '\u06A6', |
| 15606 |
'\uFB6F': '\u06A6', |
| 15607 |
'\uFB70': '\u06A6', |
| 15608 |
'\uFB71': '\u06A6', |
| 15609 |
'\uFB72': '\u0684', |
| 15610 |
'\uFB73': '\u0684', |
| 15611 |
'\uFB74': '\u0684', |
| 15612 |
'\uFB75': '\u0684', |
| 15613 |
'\uFB76': '\u0683', |
| 15614 |
'\uFB77': '\u0683', |
| 15615 |
'\uFB78': '\u0683', |
| 15616 |
'\uFB79': '\u0683', |
| 15617 |
'\uFB7A': '\u0686', |
| 15618 |
'\uFB7B': '\u0686', |
| 15619 |
'\uFB7C': '\u0686', |
| 15620 |
'\uFB7D': '\u0686', |
| 15621 |
'\uFB7E': '\u0687', |
| 15622 |
'\uFB7F': '\u0687', |
| 15623 |
'\uFB80': '\u0687', |
| 15624 |
'\uFB81': '\u0687', |
| 15625 |
'\uFB82': '\u068D', |
| 15626 |
'\uFB83': '\u068D', |
| 15627 |
'\uFB84': '\u068C', |
| 15628 |
'\uFB85': '\u068C', |
| 15629 |
'\uFB86': '\u068E', |
| 15630 |
'\uFB87': '\u068E', |
| 15631 |
'\uFB88': '\u0688', |
| 15632 |
'\uFB89': '\u0688', |
| 15633 |
'\uFB8A': '\u0698', |
| 15634 |
'\uFB8B': '\u0698', |
| 15635 |
'\uFB8C': '\u0691', |
| 15636 |
'\uFB8D': '\u0691', |
| 15637 |
'\uFB8E': '\u06A9', |
| 15638 |
'\uFB8F': '\u06A9', |
| 15639 |
'\uFB90': '\u06A9', |
| 15640 |
'\uFB91': '\u06A9', |
| 15641 |
'\uFB92': '\u06AF', |
| 15642 |
'\uFB93': '\u06AF', |
| 15643 |
'\uFB94': '\u06AF', |
| 15644 |
'\uFB95': '\u06AF', |
| 15645 |
'\uFB96': '\u06B3', |
| 15646 |
'\uFB97': '\u06B3', |
| 15647 |
'\uFB98': '\u06B3', |
| 15648 |
'\uFB99': '\u06B3', |
| 15649 |
'\uFB9A': '\u06B1', |
| 15650 |
'\uFB9B': '\u06B1', |
| 15651 |
'\uFB9C': '\u06B1', |
| 15652 |
'\uFB9D': '\u06B1', |
| 15653 |
'\uFB9E': '\u06BA', |
| 15654 |
'\uFB9F': '\u06BA', |
| 15655 |
'\uFBA0': '\u06BB', |
| 15656 |
'\uFBA1': '\u06BB', |
| 15657 |
'\uFBA2': '\u06BB', |
| 15658 |
'\uFBA3': '\u06BB', |
| 15659 |
'\uFBA4': '\u06C0', |
| 15660 |
'\uFBA5': '\u06C0', |
| 15661 |
'\uFBA6': '\u06C1', |
| 15662 |
'\uFBA7': '\u06C1', |
| 15663 |
'\uFBA8': '\u06C1', |
| 15664 |
'\uFBA9': '\u06C1', |
| 15665 |
'\uFBAA': '\u06BE', |
| 15666 |
'\uFBAB': '\u06BE', |
| 15667 |
'\uFBAC': '\u06BE', |
| 15668 |
'\uFBAD': '\u06BE', |
| 15669 |
'\uFBAE': '\u06D2', |
| 15670 |
'\uFBAF': '\u06D2', |
| 15671 |
'\uFBB0': '\u06D3', |
| 15672 |
'\uFBB1': '\u06D3', |
| 15673 |
'\uFBD3': '\u06AD', |
| 15674 |
'\uFBD4': '\u06AD', |
| 15675 |
'\uFBD5': '\u06AD', |
| 15676 |
'\uFBD6': '\u06AD', |
| 15677 |
'\uFBD7': '\u06C7', |
| 15678 |
'\uFBD8': '\u06C7', |
| 15679 |
'\uFBD9': '\u06C6', |
| 15680 |
'\uFBDA': '\u06C6', |
| 15681 |
'\uFBDB': '\u06C8', |
| 15682 |
'\uFBDC': '\u06C8', |
| 15683 |
'\uFBDD': '\u0677', |
| 15684 |
'\uFBDE': '\u06CB', |
| 15685 |
'\uFBDF': '\u06CB', |
| 15686 |
'\uFBE0': '\u06C5', |
| 15687 |
'\uFBE1': '\u06C5', |
| 15688 |
'\uFBE2': '\u06C9', |
| 15689 |
'\uFBE3': '\u06C9', |
| 15690 |
'\uFBE4': '\u06D0', |
| 15691 |
'\uFBE5': '\u06D0', |
| 15692 |
'\uFBE6': '\u06D0', |
| 15693 |
'\uFBE7': '\u06D0', |
| 15694 |
'\uFBE8': '\u0649', |
| 15695 |
'\uFBE9': '\u0649', |
| 15696 |
'\uFBEA': '\u0626\u0627', |
| 15697 |
'\uFBEB': '\u0626\u0627', |
| 15698 |
'\uFBEC': '\u0626\u06D5', |
| 15699 |
'\uFBED': '\u0626\u06D5', |
| 15700 |
'\uFBEE': '\u0626\u0648', |
| 15701 |
'\uFBEF': '\u0626\u0648', |
| 15702 |
'\uFBF0': '\u0626\u06C7', |
| 15703 |
'\uFBF1': '\u0626\u06C7', |
| 15704 |
'\uFBF2': '\u0626\u06C6', |
| 15705 |
'\uFBF3': '\u0626\u06C6', |
| 15706 |
'\uFBF4': '\u0626\u06C8', |
| 15707 |
'\uFBF5': '\u0626\u06C8', |
| 15708 |
'\uFBF6': '\u0626\u06D0', |
| 15709 |
'\uFBF7': '\u0626\u06D0', |
| 15710 |
'\uFBF8': '\u0626\u06D0', |
| 15711 |
'\uFBF9': '\u0626\u0649', |
| 15712 |
'\uFBFA': '\u0626\u0649', |
| 15713 |
'\uFBFB': '\u0626\u0649', |
| 15714 |
'\uFBFC': '\u06CC', |
| 15715 |
'\uFBFD': '\u06CC', |
| 15716 |
'\uFBFE': '\u06CC', |
| 15717 |
'\uFBFF': '\u06CC', |
| 15718 |
'\uFC00': '\u0626\u062C', |
| 15719 |
'\uFC01': '\u0626\u062D', |
| 15720 |
'\uFC02': '\u0626\u0645', |
| 15721 |
'\uFC03': '\u0626\u0649', |
| 15722 |
'\uFC04': '\u0626\u064A', |
| 15723 |
'\uFC05': '\u0628\u062C', |
| 15724 |
'\uFC06': '\u0628\u062D', |
| 15725 |
'\uFC07': '\u0628\u062E', |
| 15726 |
'\uFC08': '\u0628\u0645', |
| 15727 |
'\uFC09': '\u0628\u0649', |
| 15728 |
'\uFC0A': '\u0628\u064A', |
| 15729 |
'\uFC0B': '\u062A\u062C', |
| 15730 |
'\uFC0C': '\u062A\u062D', |
| 15731 |
'\uFC0D': '\u062A\u062E', |
| 15732 |
'\uFC0E': '\u062A\u0645', |
| 15733 |
'\uFC0F': '\u062A\u0649', |
| 15734 |
'\uFC10': '\u062A\u064A', |
| 15735 |
'\uFC11': '\u062B\u062C', |
| 15736 |
'\uFC12': '\u062B\u0645', |
| 15737 |
'\uFC13': '\u062B\u0649', |
| 15738 |
'\uFC14': '\u062B\u064A', |
| 15739 |
'\uFC15': '\u062C\u062D', |
| 15740 |
'\uFC16': '\u062C\u0645', |
| 15741 |
'\uFC17': '\u062D\u062C', |
| 15742 |
'\uFC18': '\u062D\u0645', |
| 15743 |
'\uFC19': '\u062E\u062C', |
| 15744 |
'\uFC1A': '\u062E\u062D', |
| 15745 |
'\uFC1B': '\u062E\u0645', |
| 15746 |
'\uFC1C': '\u0633\u062C', |
| 15747 |
'\uFC1D': '\u0633\u062D', |
| 15748 |
'\uFC1E': '\u0633\u062E', |
| 15749 |
'\uFC1F': '\u0633\u0645', |
| 15750 |
'\uFC20': '\u0635\u062D', |
| 15751 |
'\uFC21': '\u0635\u0645', |
| 15752 |
'\uFC22': '\u0636\u062C', |
| 15753 |
'\uFC23': '\u0636\u062D', |
| 15754 |
'\uFC24': '\u0636\u062E', |
| 15755 |
'\uFC25': '\u0636\u0645', |
| 15756 |
'\uFC26': '\u0637\u062D', |
| 15757 |
'\uFC27': '\u0637\u0645', |
| 15758 |
'\uFC28': '\u0638\u0645', |
| 15759 |
'\uFC29': '\u0639\u062C', |
| 15760 |
'\uFC2A': '\u0639\u0645', |
| 15761 |
'\uFC2B': '\u063A\u062C', |
| 15762 |
'\uFC2C': '\u063A\u0645', |
| 15763 |
'\uFC2D': '\u0641\u062C', |
| 15764 |
'\uFC2E': '\u0641\u062D', |
| 15765 |
'\uFC2F': '\u0641\u062E', |
| 15766 |
'\uFC30': '\u0641\u0645', |
| 15767 |
'\uFC31': '\u0641\u0649', |
| 15768 |
'\uFC32': '\u0641\u064A', |
| 15769 |
'\uFC33': '\u0642\u062D', |
| 15770 |
'\uFC34': '\u0642\u0645', |
| 15771 |
'\uFC35': '\u0642\u0649', |
| 15772 |
'\uFC36': '\u0642\u064A', |
| 15773 |
'\uFC37': '\u0643\u0627', |
| 15774 |
'\uFC38': '\u0643\u062C', |
| 15775 |
'\uFC39': '\u0643\u062D', |
| 15776 |
'\uFC3A': '\u0643\u062E', |
| 15777 |
'\uFC3B': '\u0643\u0644', |
| 15778 |
'\uFC3C': '\u0643\u0645', |
| 15779 |
'\uFC3D': '\u0643\u0649', |
| 15780 |
'\uFC3E': '\u0643\u064A', |
| 15781 |
'\uFC3F': '\u0644\u062C', |
| 15782 |
'\uFC40': '\u0644\u062D', |
| 15783 |
'\uFC41': '\u0644\u062E', |
| 15784 |
'\uFC42': '\u0644\u0645', |
| 15785 |
'\uFC43': '\u0644\u0649', |
| 15786 |
'\uFC44': '\u0644\u064A', |
| 15787 |
'\uFC45': '\u0645\u062C', |
| 15788 |
'\uFC46': '\u0645\u062D', |
| 15789 |
'\uFC47': '\u0645\u062E', |
| 15790 |
'\uFC48': '\u0645\u0645', |
| 15791 |
'\uFC49': '\u0645\u0649', |
| 15792 |
'\uFC4A': '\u0645\u064A', |
| 15793 |
'\uFC4B': '\u0646\u062C', |
| 15794 |
'\uFC4C': '\u0646\u062D', |
| 15795 |
'\uFC4D': '\u0646\u062E', |
| 15796 |
'\uFC4E': '\u0646\u0645', |
| 15797 |
'\uFC4F': '\u0646\u0649', |
| 15798 |
'\uFC50': '\u0646\u064A', |
| 15799 |
'\uFC51': '\u0647\u062C', |
| 15800 |
'\uFC52': '\u0647\u0645', |
| 15801 |
'\uFC53': '\u0647\u0649', |
| 15802 |
'\uFC54': '\u0647\u064A', |
| 15803 |
'\uFC55': '\u064A\u062C', |
| 15804 |
'\uFC56': '\u064A\u062D', |
| 15805 |
'\uFC57': '\u064A\u062E', |
| 15806 |
'\uFC58': '\u064A\u0645', |
| 15807 |
'\uFC59': '\u064A\u0649', |
| 15808 |
'\uFC5A': '\u064A\u064A', |
| 15809 |
'\uFC5B': '\u0630\u0670', |
| 15810 |
'\uFC5C': '\u0631\u0670', |
| 15811 |
'\uFC5D': '\u0649\u0670', |
| 15812 |
'\uFC5E': '\u0020\u064C\u0651', |
| 15813 |
'\uFC5F': '\u0020\u064D\u0651', |
| 15814 |
'\uFC60': '\u0020\u064E\u0651', |
| 15815 |
'\uFC61': '\u0020\u064F\u0651', |
| 15816 |
'\uFC62': '\u0020\u0650\u0651', |
| 15817 |
'\uFC63': '\u0020\u0651\u0670', |
| 15818 |
'\uFC64': '\u0626\u0631', |
| 15819 |
'\uFC65': '\u0626\u0632', |
| 15820 |
'\uFC66': '\u0626\u0645', |
| 15821 |
'\uFC67': '\u0626\u0646', |
| 15822 |
'\uFC68': '\u0626\u0649', |
| 15823 |
'\uFC69': '\u0626\u064A', |
| 15824 |
'\uFC6A': '\u0628\u0631', |
| 15825 |
'\uFC6B': '\u0628\u0632', |
| 15826 |
'\uFC6C': '\u0628\u0645', |
| 15827 |
'\uFC6D': '\u0628\u0646', |
| 15828 |
'\uFC6E': '\u0628\u0649', |
| 15829 |
'\uFC6F': '\u0628\u064A', |
| 15830 |
'\uFC70': '\u062A\u0631', |
| 15831 |
'\uFC71': '\u062A\u0632', |
| 15832 |
'\uFC72': '\u062A\u0645', |
| 15833 |
'\uFC73': '\u062A\u0646', |
| 15834 |
'\uFC74': '\u062A\u0649', |
| 15835 |
'\uFC75': '\u062A\u064A', |
| 15836 |
'\uFC76': '\u062B\u0631', |
| 15837 |
'\uFC77': '\u062B\u0632', |
| 15838 |
'\uFC78': '\u062B\u0645', |
| 15839 |
'\uFC79': '\u062B\u0646', |
| 15840 |
'\uFC7A': '\u062B\u0649', |
| 15841 |
'\uFC7B': '\u062B\u064A', |
| 15842 |
'\uFC7C': '\u0641\u0649', |
| 15843 |
'\uFC7D': '\u0641\u064A', |
| 15844 |
'\uFC7E': '\u0642\u0649', |
| 15845 |
'\uFC7F': '\u0642\u064A', |
| 15846 |
'\uFC80': '\u0643\u0627', |
| 15847 |
'\uFC81': '\u0643\u0644', |
| 15848 |
'\uFC82': '\u0643\u0645', |
| 15849 |
'\uFC83': '\u0643\u0649', |
| 15850 |
'\uFC84': '\u0643\u064A', |
| 15851 |
'\uFC85': '\u0644\u0645', |
| 15852 |
'\uFC86': '\u0644\u0649', |
| 15853 |
'\uFC87': '\u0644\u064A', |
| 15854 |
'\uFC88': '\u0645\u0627', |
| 15855 |
'\uFC89': '\u0645\u0645', |
| 15856 |
'\uFC8A': '\u0646\u0631', |
| 15857 |
'\uFC8B': '\u0646\u0632', |
| 15858 |
'\uFC8C': '\u0646\u0645', |
| 15859 |
'\uFC8D': '\u0646\u0646', |
| 15860 |
'\uFC8E': '\u0646\u0649', |
| 15861 |
'\uFC8F': '\u0646\u064A', |
| 15862 |
'\uFC90': '\u0649\u0670', |
| 15863 |
'\uFC91': '\u064A\u0631', |
| 15864 |
'\uFC92': '\u064A\u0632', |
| 15865 |
'\uFC93': '\u064A\u0645', |
| 15866 |
'\uFC94': '\u064A\u0646', |
| 15867 |
'\uFC95': '\u064A\u0649', |
| 15868 |
'\uFC96': '\u064A\u064A', |
| 15869 |
'\uFC97': '\u0626\u062C', |
| 15870 |
'\uFC98': '\u0626\u062D', |
| 15871 |
'\uFC99': '\u0626\u062E', |
| 15872 |
'\uFC9A': '\u0626\u0645', |
| 15873 |
'\uFC9B': '\u0626\u0647', |
| 15874 |
'\uFC9C': '\u0628\u062C', |
| 15875 |
'\uFC9D': '\u0628\u062D', |
| 15876 |
'\uFC9E': '\u0628\u062E', |
| 15877 |
'\uFC9F': '\u0628\u0645', |
| 15878 |
'\uFCA0': '\u0628\u0647', |
| 15879 |
'\uFCA1': '\u062A\u062C', |
| 15880 |
'\uFCA2': '\u062A\u062D', |
| 15881 |
'\uFCA3': '\u062A\u062E', |
| 15882 |
'\uFCA4': '\u062A\u0645', |
| 15883 |
'\uFCA5': '\u062A\u0647', |
| 15884 |
'\uFCA6': '\u062B\u0645', |
| 15885 |
'\uFCA7': '\u062C\u062D', |
| 15886 |
'\uFCA8': '\u062C\u0645', |
| 15887 |
'\uFCA9': '\u062D\u062C', |
| 15888 |
'\uFCAA': '\u062D\u0645', |
| 15889 |
'\uFCAB': '\u062E\u062C', |
| 15890 |
'\uFCAC': '\u062E\u0645', |
| 15891 |
'\uFCAD': '\u0633\u062C', |
| 15892 |
'\uFCAE': '\u0633\u062D', |
| 15893 |
'\uFCAF': '\u0633\u062E', |
| 15894 |
'\uFCB0': '\u0633\u0645', |
| 15895 |
'\uFCB1': '\u0635\u062D', |
| 15896 |
'\uFCB2': '\u0635\u062E', |
| 15897 |
'\uFCB3': '\u0635\u0645', |
| 15898 |
'\uFCB4': '\u0636\u062C', |
| 15899 |
'\uFCB5': '\u0636\u062D', |
| 15900 |
'\uFCB6': '\u0636\u062E', |
| 15901 |
'\uFCB7': '\u0636\u0645', |
| 15902 |
'\uFCB8': '\u0637\u062D', |
| 15903 |
'\uFCB9': '\u0638\u0645', |
| 15904 |
'\uFCBA': '\u0639\u062C', |
| 15905 |
'\uFCBB': '\u0639\u0645', |
| 15906 |
'\uFCBC': '\u063A\u062C', |
| 15907 |
'\uFCBD': '\u063A\u0645', |
| 15908 |
'\uFCBE': '\u0641\u062C', |
| 15909 |
'\uFCBF': '\u0641\u062D', |
| 15910 |
'\uFCC0': '\u0641\u062E', |
| 15911 |
'\uFCC1': '\u0641\u0645', |
| 15912 |
'\uFCC2': '\u0642\u062D', |
| 15913 |
'\uFCC3': '\u0642\u0645', |
| 15914 |
'\uFCC4': '\u0643\u062C', |
| 15915 |
'\uFCC5': '\u0643\u062D', |
| 15916 |
'\uFCC6': '\u0643\u062E', |
| 15917 |
'\uFCC7': '\u0643\u0644', |
| 15918 |
'\uFCC8': '\u0643\u0645', |
| 15919 |
'\uFCC9': '\u0644\u062C', |
| 15920 |
'\uFCCA': '\u0644\u062D', |
| 15921 |
'\uFCCB': '\u0644\u062E', |
| 15922 |
'\uFCCC': '\u0644\u0645', |
| 15923 |
'\uFCCD': '\u0644\u0647', |
| 15924 |
'\uFCCE': '\u0645\u062C', |
| 15925 |
'\uFCCF': '\u0645\u062D', |
| 15926 |
'\uFCD0': '\u0645\u062E', |
| 15927 |
'\uFCD1': '\u0645\u0645', |
| 15928 |
'\uFCD2': '\u0646\u062C', |
| 15929 |
'\uFCD3': '\u0646\u062D', |
| 15930 |
'\uFCD4': '\u0646\u062E', |
| 15931 |
'\uFCD5': '\u0646\u0645', |
| 15932 |
'\uFCD6': '\u0646\u0647', |
| 15933 |
'\uFCD7': '\u0647\u062C', |
| 15934 |
'\uFCD8': '\u0647\u0645', |
| 15935 |
'\uFCD9': '\u0647\u0670', |
| 15936 |
'\uFCDA': '\u064A\u062C', |
| 15937 |
'\uFCDB': '\u064A\u062D', |
| 15938 |
'\uFCDC': '\u064A\u062E', |
| 15939 |
'\uFCDD': '\u064A\u0645', |
| 15940 |
'\uFCDE': '\u064A\u0647', |
| 15941 |
'\uFCDF': '\u0626\u0645', |
| 15942 |
'\uFCE0': '\u0626\u0647', |
| 15943 |
'\uFCE1': '\u0628\u0645', |
| 15944 |
'\uFCE2': '\u0628\u0647', |
| 15945 |
'\uFCE3': '\u062A\u0645', |
| 15946 |
'\uFCE4': '\u062A\u0647', |
| 15947 |
'\uFCE5': '\u062B\u0645', |
| 15948 |
'\uFCE6': '\u062B\u0647', |
| 15949 |
'\uFCE7': '\u0633\u0645', |
| 15950 |
'\uFCE8': '\u0633\u0647', |
| 15951 |
'\uFCE9': '\u0634\u0645', |
| 15952 |
'\uFCEA': '\u0634\u0647', |
| 15953 |
'\uFCEB': '\u0643\u0644', |
| 15954 |
'\uFCEC': '\u0643\u0645', |
| 15955 |
'\uFCED': '\u0644\u0645', |
| 15956 |
'\uFCEE': '\u0646\u0645', |
| 15957 |
'\uFCEF': '\u0646\u0647', |
| 15958 |
'\uFCF0': '\u064A\u0645', |
| 15959 |
'\uFCF1': '\u064A\u0647', |
| 15960 |
'\uFCF2': '\u0640\u064E\u0651', |
| 15961 |
'\uFCF3': '\u0640\u064F\u0651', |
| 15962 |
'\uFCF4': '\u0640\u0650\u0651', |
| 15963 |
'\uFCF5': '\u0637\u0649', |
| 15964 |
'\uFCF6': '\u0637\u064A', |
| 15965 |
'\uFCF7': '\u0639\u0649', |
| 15966 |
'\uFCF8': '\u0639\u064A', |
| 15967 |
'\uFCF9': '\u063A\u0649', |
| 15968 |
'\uFCFA': '\u063A\u064A', |
| 15969 |
'\uFCFB': '\u0633\u0649', |
| 15970 |
'\uFCFC': '\u0633\u064A', |
| 15971 |
'\uFCFD': '\u0634\u0649', |
| 15972 |
'\uFCFE': '\u0634\u064A', |
| 15973 |
'\uFCFF': '\u062D\u0649', |
| 15974 |
'\uFD00': '\u062D\u064A', |
| 15975 |
'\uFD01': '\u062C\u0649', |
| 15976 |
'\uFD02': '\u062C\u064A', |
| 15977 |
'\uFD03': '\u062E\u0649', |
| 15978 |
'\uFD04': '\u062E\u064A', |
| 15979 |
'\uFD05': '\u0635\u0649', |
| 15980 |
'\uFD06': '\u0635\u064A', |
| 15981 |
'\uFD07': '\u0636\u0649', |
| 15982 |
'\uFD08': '\u0636\u064A', |
| 15983 |
'\uFD09': '\u0634\u062C', |
| 15984 |
'\uFD0A': '\u0634\u062D', |
| 15985 |
'\uFD0B': '\u0634\u062E', |
| 15986 |
'\uFD0C': '\u0634\u0645', |
| 15987 |
'\uFD0D': '\u0634\u0631', |
| 15988 |
'\uFD0E': '\u0633\u0631', |
| 15989 |
'\uFD0F': '\u0635\u0631', |
| 15990 |
'\uFD10': '\u0636\u0631', |
| 15991 |
'\uFD11': '\u0637\u0649', |
| 15992 |
'\uFD12': '\u0637\u064A', |
| 15993 |
'\uFD13': '\u0639\u0649', |
| 15994 |
'\uFD14': '\u0639\u064A', |
| 15995 |
'\uFD15': '\u063A\u0649', |
| 15996 |
'\uFD16': '\u063A\u064A', |
| 15997 |
'\uFD17': '\u0633\u0649', |
| 15998 |
'\uFD18': '\u0633\u064A', |
| 15999 |
'\uFD19': '\u0634\u0649', |
| 16000 |
'\uFD1A': '\u0634\u064A', |
| 16001 |
'\uFD1B': '\u062D\u0649', |
| 16002 |
'\uFD1C': '\u062D\u064A', |
| 16003 |
'\uFD1D': '\u062C\u0649', |
| 16004 |
'\uFD1E': '\u062C\u064A', |
| 16005 |
'\uFD1F': '\u062E\u0649', |
| 16006 |
'\uFD20': '\u062E\u064A', |
| 16007 |
'\uFD21': '\u0635\u0649', |
| 16008 |
'\uFD22': '\u0635\u064A', |
| 16009 |
'\uFD23': '\u0636\u0649', |
| 16010 |
'\uFD24': '\u0636\u064A', |
| 16011 |
'\uFD25': '\u0634\u062C', |
| 16012 |
'\uFD26': '\u0634\u062D', |
| 16013 |
'\uFD27': '\u0634\u062E', |
| 16014 |
'\uFD28': '\u0634\u0645', |
| 16015 |
'\uFD29': '\u0634\u0631', |
| 16016 |
'\uFD2A': '\u0633\u0631', |
| 16017 |
'\uFD2B': '\u0635\u0631', |
| 16018 |
'\uFD2C': '\u0636\u0631', |
| 16019 |
'\uFD2D': '\u0634\u062C', |
| 16020 |
'\uFD2E': '\u0634\u062D', |
| 16021 |
'\uFD2F': '\u0634\u062E', |
| 16022 |
'\uFD30': '\u0634\u0645', |
| 16023 |
'\uFD31': '\u0633\u0647', |
| 16024 |
'\uFD32': '\u0634\u0647', |
| 16025 |
'\uFD33': '\u0637\u0645', |
| 16026 |
'\uFD34': '\u0633\u062C', |
| 16027 |
'\uFD35': '\u0633\u062D', |
| 16028 |
'\uFD36': '\u0633\u062E', |
| 16029 |
'\uFD37': '\u0634\u062C', |
| 16030 |
'\uFD38': '\u0634\u062D', |
| 16031 |
'\uFD39': '\u0634\u062E', |
| 16032 |
'\uFD3A': '\u0637\u0645', |
| 16033 |
'\uFD3B': '\u0638\u0645', |
| 16034 |
'\uFD3C': '\u0627\u064B', |
| 16035 |
'\uFD3D': '\u0627\u064B', |
| 16036 |
'\uFD50': '\u062A\u062C\u0645', |
| 16037 |
'\uFD51': '\u062A\u062D\u062C', |
| 16038 |
'\uFD52': '\u062A\u062D\u062C', |
| 16039 |
'\uFD53': '\u062A\u062D\u0645', |
| 16040 |
'\uFD54': '\u062A\u062E\u0645', |
| 16041 |
'\uFD55': '\u062A\u0645\u062C', |
| 16042 |
'\uFD56': '\u062A\u0645\u062D', |
| 16043 |
'\uFD57': '\u062A\u0645\u062E', |
| 16044 |
'\uFD58': '\u062C\u0645\u062D', |
| 16045 |
'\uFD59': '\u062C\u0645\u062D', |
| 16046 |
'\uFD5A': '\u062D\u0645\u064A', |
| 16047 |
'\uFD5B': '\u062D\u0645\u0649', |
| 16048 |
'\uFD5C': '\u0633\u062D\u062C', |
| 16049 |
'\uFD5D': '\u0633\u062C\u062D', |
| 16050 |
'\uFD5E': '\u0633\u062C\u0649', |
| 16051 |
'\uFD5F': '\u0633\u0645\u062D', |
| 16052 |
'\uFD60': '\u0633\u0645\u062D', |
| 16053 |
'\uFD61': '\u0633\u0645\u062C', |
| 16054 |
'\uFD62': '\u0633\u0645\u0645', |
| 16055 |
'\uFD63': '\u0633\u0645\u0645', |
| 16056 |
'\uFD64': '\u0635\u062D\u062D', |
| 16057 |
'\uFD65': '\u0635\u062D\u062D', |
| 16058 |
'\uFD66': '\u0635\u0645\u0645', |
| 16059 |
'\uFD67': '\u0634\u062D\u0645', |
| 16060 |
'\uFD68': '\u0634\u062D\u0645', |
| 16061 |
'\uFD69': '\u0634\u062C\u064A', |
| 16062 |
'\uFD6A': '\u0634\u0645\u062E', |
| 16063 |
'\uFD6B': '\u0634\u0645\u062E', |
| 16064 |
'\uFD6C': '\u0634\u0645\u0645', |
| 16065 |
'\uFD6D': '\u0634\u0645\u0645', |
| 16066 |
'\uFD6E': '\u0636\u062D\u0649', |
| 16067 |
'\uFD6F': '\u0636\u062E\u0645', |
| 16068 |
'\uFD70': '\u0636\u062E\u0645', |
| 16069 |
'\uFD71': '\u0637\u0645\u062D', |
| 16070 |
'\uFD72': '\u0637\u0645\u062D', |
| 16071 |
'\uFD73': '\u0637\u0645\u0645', |
| 16072 |
'\uFD74': '\u0637\u0645\u064A', |
| 16073 |
'\uFD75': '\u0639\u062C\u0645', |
| 16074 |
'\uFD76': '\u0639\u0645\u0645', |
| 16075 |
'\uFD77': '\u0639\u0645\u0645', |
| 16076 |
'\uFD78': '\u0639\u0645\u0649', |
| 16077 |
'\uFD79': '\u063A\u0645\u0645', |
| 16078 |
'\uFD7A': '\u063A\u0645\u064A', |
| 16079 |
'\uFD7B': '\u063A\u0645\u0649', |
| 16080 |
'\uFD7C': '\u0641\u062E\u0645', |
| 16081 |
'\uFD7D': '\u0641\u062E\u0645', |
| 16082 |
'\uFD7E': '\u0642\u0645\u062D', |
| 16083 |
'\uFD7F': '\u0642\u0645\u0645', |
| 16084 |
'\uFD80': '\u0644\u062D\u0645', |
| 16085 |
'\uFD81': '\u0644\u062D\u064A', |
| 16086 |
'\uFD82': '\u0644\u062D\u0649', |
| 16087 |
'\uFD83': '\u0644\u062C\u062C', |
| 16088 |
'\uFD84': '\u0644\u062C\u062C', |
| 16089 |
'\uFD85': '\u0644\u062E\u0645', |
| 16090 |
'\uFD86': '\u0644\u062E\u0645', |
| 16091 |
'\uFD87': '\u0644\u0645\u062D', |
| 16092 |
'\uFD88': '\u0644\u0645\u062D', |
| 16093 |
'\uFD89': '\u0645\u062D\u062C', |
| 16094 |
'\uFD8A': '\u0645\u062D\u0645', |
| 16095 |
'\uFD8B': '\u0645\u062D\u064A', |
| 16096 |
'\uFD8C': '\u0645\u062C\u062D', |
| 16097 |
'\uFD8D': '\u0645\u062C\u0645', |
| 16098 |
'\uFD8E': '\u0645\u062E\u062C', |
| 16099 |
'\uFD8F': '\u0645\u062E\u0645', |
| 16100 |
'\uFD92': '\u0645\u062C\u062E', |
| 16101 |
'\uFD93': '\u0647\u0645\u062C', |
| 16102 |
'\uFD94': '\u0647\u0645\u0645', |
| 16103 |
'\uFD95': '\u0646\u062D\u0645', |
| 16104 |
'\uFD96': '\u0646\u062D\u0649', |
| 16105 |
'\uFD97': '\u0646\u062C\u0645', |
| 16106 |
'\uFD98': '\u0646\u062C\u0645', |
| 16107 |
'\uFD99': '\u0646\u062C\u0649', |
| 16108 |
'\uFD9A': '\u0646\u0645\u064A', |
| 16109 |
'\uFD9B': '\u0646\u0645\u0649', |
| 16110 |
'\uFD9C': '\u064A\u0645\u0645', |
| 16111 |
'\uFD9D': '\u064A\u0645\u0645', |
| 16112 |
'\uFD9E': '\u0628\u062E\u064A', |
| 16113 |
'\uFD9F': '\u062A\u062C\u064A', |
| 16114 |
'\uFDA0': '\u062A\u062C\u0649', |
| 16115 |
'\uFDA1': '\u062A\u062E\u064A', |
| 16116 |
'\uFDA2': '\u062A\u062E\u0649', |
| 16117 |
'\uFDA3': '\u062A\u0645\u064A', |
| 16118 |
'\uFDA4': '\u062A\u0645\u0649', |
| 16119 |
'\uFDA5': '\u062C\u0645\u064A', |
| 16120 |
'\uFDA6': '\u062C\u062D\u0649', |
| 16121 |
'\uFDA7': '\u062C\u0645\u0649', |
| 16122 |
'\uFDA8': '\u0633\u062E\u0649', |
| 16123 |
'\uFDA9': '\u0635\u062D\u064A', |
| 16124 |
'\uFDAA': '\u0634\u062D\u064A', |
| 16125 |
'\uFDAB': '\u0636\u062D\u064A', |
| 16126 |
'\uFDAC': '\u0644\u062C\u064A', |
| 16127 |
'\uFDAD': '\u0644\u0645\u064A', |
| 16128 |
'\uFDAE': '\u064A\u062D\u064A', |
| 16129 |
'\uFDAF': '\u064A\u062C\u064A', |
| 16130 |
'\uFDB0': '\u064A\u0645\u064A', |
| 16131 |
'\uFDB1': '\u0645\u0645\u064A', |
| 16132 |
'\uFDB2': '\u0642\u0645\u064A', |
| 16133 |
'\uFDB3': '\u0646\u062D\u064A', |
| 16134 |
'\uFDB4': '\u0642\u0645\u062D', |
| 16135 |
'\uFDB5': '\u0644\u062D\u0645', |
| 16136 |
'\uFDB6': '\u0639\u0645\u064A', |
| 16137 |
'\uFDB7': '\u0643\u0645\u064A', |
| 16138 |
'\uFDB8': '\u0646\u062C\u062D', |
| 16139 |
'\uFDB9': '\u0645\u062E\u064A', |
| 16140 |
'\uFDBA': '\u0644\u062C\u0645', |
| 16141 |
'\uFDBB': '\u0643\u0645\u0645', |
| 16142 |
'\uFDBC': '\u0644\u062C\u0645', |
| 16143 |
'\uFDBD': '\u0646\u062C\u062D', |
| 16144 |
'\uFDBE': '\u062C\u062D\u064A', |
| 16145 |
'\uFDBF': '\u062D\u062C\u064A', |
| 16146 |
'\uFDC0': '\u0645\u062C\u064A', |
| 16147 |
'\uFDC1': '\u0641\u0645\u064A', |
| 16148 |
'\uFDC2': '\u0628\u062D\u064A', |
| 16149 |
'\uFDC3': '\u0643\u0645\u0645', |
| 16150 |
'\uFDC4': '\u0639\u062C\u0645', |
| 16151 |
'\uFDC5': '\u0635\u0645\u0645', |
| 16152 |
'\uFDC6': '\u0633\u062E\u064A', |
| 16153 |
'\uFDC7': '\u0646\u062C\u064A', |
| 16154 |
'\uFE49': '\u203E', |
| 16155 |
'\uFE4A': '\u203E', |
| 16156 |
'\uFE4B': '\u203E', |
| 16157 |
'\uFE4C': '\u203E', |
| 16158 |
'\uFE4D': '\u005F', |
| 16159 |
'\uFE4E': '\u005F', |
| 16160 |
'\uFE4F': '\u005F', |
| 16161 |
'\uFE80': '\u0621', |
| 16162 |
'\uFE81': '\u0622', |
| 16163 |
'\uFE82': '\u0622', |
| 16164 |
'\uFE83': '\u0623', |
| 16165 |
'\uFE84': '\u0623', |
| 16166 |
'\uFE85': '\u0624', |
| 16167 |
'\uFE86': '\u0624', |
| 16168 |
'\uFE87': '\u0625', |
| 16169 |
'\uFE88': '\u0625', |
| 16170 |
'\uFE89': '\u0626', |
| 16171 |
'\uFE8A': '\u0626', |
| 16172 |
'\uFE8B': '\u0626', |
| 16173 |
'\uFE8C': '\u0626', |
| 16174 |
'\uFE8D': '\u0627', |
| 16175 |
'\uFE8E': '\u0627', |
| 16176 |
'\uFE8F': '\u0628', |
| 16177 |
'\uFE90': '\u0628', |
| 16178 |
'\uFE91': '\u0628', |
| 16179 |
'\uFE92': '\u0628', |
| 16180 |
'\uFE93': '\u0629', |
| 16181 |
'\uFE94': '\u0629', |
| 16182 |
'\uFE95': '\u062A', |
| 16183 |
'\uFE96': '\u062A', |
| 16184 |
'\uFE97': '\u062A', |
| 16185 |
'\uFE98': '\u062A', |
| 16186 |
'\uFE99': '\u062B', |
| 16187 |
'\uFE9A': '\u062B', |
| 16188 |
'\uFE9B': '\u062B', |
| 16189 |
'\uFE9C': '\u062B', |
| 16190 |
'\uFE9D': '\u062C', |
| 16191 |
'\uFE9E': '\u062C', |
| 16192 |
'\uFE9F': '\u062C', |
| 16193 |
'\uFEA0': '\u062C', |
| 16194 |
'\uFEA1': '\u062D', |
| 16195 |
'\uFEA2': '\u062D', |
| 16196 |
'\uFEA3': '\u062D', |
| 16197 |
'\uFEA4': '\u062D', |
| 16198 |
'\uFEA5': '\u062E', |
| 16199 |
'\uFEA6': '\u062E', |
| 16200 |
'\uFEA7': '\u062E', |
| 16201 |
'\uFEA8': '\u062E', |
| 16202 |
'\uFEA9': '\u062F', |
| 16203 |
'\uFEAA': '\u062F', |
| 16204 |
'\uFEAB': '\u0630', |
| 16205 |
'\uFEAC': '\u0630', |
| 16206 |
'\uFEAD': '\u0631', |
| 16207 |
'\uFEAE': '\u0631', |
| 16208 |
'\uFEAF': '\u0632', |
| 16209 |
'\uFEB0': '\u0632', |
| 16210 |
'\uFEB1': '\u0633', |
| 16211 |
'\uFEB2': '\u0633', |
| 16212 |
'\uFEB3': '\u0633', |
| 16213 |
'\uFEB4': '\u0633', |
| 16214 |
'\uFEB5': '\u0634', |
| 16215 |
'\uFEB6': '\u0634', |
| 16216 |
'\uFEB7': '\u0634', |
| 16217 |
'\uFEB8': '\u0634', |
| 16218 |
'\uFEB9': '\u0635', |
| 16219 |
'\uFEBA': '\u0635', |
| 16220 |
'\uFEBB': '\u0635', |
| 16221 |
'\uFEBC': '\u0635', |
| 16222 |
'\uFEBD': '\u0636', |
| 16223 |
'\uFEBE': '\u0636', |
| 16224 |
'\uFEBF': '\u0636', |
| 16225 |
'\uFEC0': '\u0636', |
| 16226 |
'\uFEC1': '\u0637', |
| 16227 |
'\uFEC2': '\u0637', |
| 16228 |
'\uFEC3': '\u0637', |
| 16229 |
'\uFEC4': '\u0637', |
| 16230 |
'\uFEC5': '\u0638', |
| 16231 |
'\uFEC6': '\u0638', |
| 16232 |
'\uFEC7': '\u0638', |
| 16233 |
'\uFEC8': '\u0638', |
| 16234 |
'\uFEC9': '\u0639', |
| 16235 |
'\uFECA': '\u0639', |
| 16236 |
'\uFECB': '\u0639', |
| 16237 |
'\uFECC': '\u0639', |
| 16238 |
'\uFECD': '\u063A', |
| 16239 |
'\uFECE': '\u063A', |
| 16240 |
'\uFECF': '\u063A', |
| 16241 |
'\uFED0': '\u063A', |
| 16242 |
'\uFED1': '\u0641', |
| 16243 |
'\uFED2': '\u0641', |
| 16244 |
'\uFED3': '\u0641', |
| 16245 |
'\uFED4': '\u0641', |
| 16246 |
'\uFED5': '\u0642', |
| 16247 |
'\uFED6': '\u0642', |
| 16248 |
'\uFED7': '\u0642', |
| 16249 |
'\uFED8': '\u0642', |
| 16250 |
'\uFED9': '\u0643', |
| 16251 |
'\uFEDA': '\u0643', |
| 16252 |
'\uFEDB': '\u0643', |
| 16253 |
'\uFEDC': '\u0643', |
| 16254 |
'\uFEDD': '\u0644', |
| 16255 |
'\uFEDE': '\u0644', |
| 16256 |
'\uFEDF': '\u0644', |
| 16257 |
'\uFEE0': '\u0644', |
| 16258 |
'\uFEE1': '\u0645', |
| 16259 |
'\uFEE2': '\u0645', |
| 16260 |
'\uFEE3': '\u0645', |
| 16261 |
'\uFEE4': '\u0645', |
| 16262 |
'\uFEE5': '\u0646', |
| 16263 |
'\uFEE6': '\u0646', |
| 16264 |
'\uFEE7': '\u0646', |
| 16265 |
'\uFEE8': '\u0646', |
| 16266 |
'\uFEE9': '\u0647', |
| 16267 |
'\uFEEA': '\u0647', |
| 16268 |
'\uFEEB': '\u0647', |
| 16269 |
'\uFEEC': '\u0647', |
| 16270 |
'\uFEED': '\u0648', |
| 16271 |
'\uFEEE': '\u0648', |
| 16272 |
'\uFEEF': '\u0649', |
| 16273 |
'\uFEF0': '\u0649', |
| 16274 |
'\uFEF1': '\u064A', |
| 16275 |
'\uFEF2': '\u064A', |
| 16276 |
'\uFEF3': '\u064A', |
| 16277 |
'\uFEF4': '\u064A', |
| 16278 |
'\uFEF5': '\u0644\u0622', |
| 16279 |
'\uFEF6': '\u0644\u0622', |
| 16280 |
'\uFEF7': '\u0644\u0623', |
| 16281 |
'\uFEF8': '\u0644\u0623', |
| 16282 |
'\uFEF9': '\u0644\u0625', |
| 16283 |
'\uFEFA': '\u0644\u0625', |
| 16284 |
'\uFEFB': '\u0644\u0627', |
| 16285 |
'\uFEFC': '\u0644\u0627' |
| 16286 |
}; |
| 16287 |
|
| 16288 |
function reverseIfRtl(chars) { |
| 16289 |
var charsLength = chars.length; |
| 16290 |
//reverse an arabic ligature |
| 16291 |
if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) { |
| 16292 |
return chars; |
| 16293 |
} |
| 16294 |
var s = ''; |
| 16295 |
for (var ii = charsLength - 1; ii >= 0; ii--) { |
| 16296 |
s += chars[ii]; |
| 16297 |
} |
| 16298 |
return s; |
| 16299 |
} |
| 16300 |
|
| 16301 |
function adjustWidths(properties) { |
| 16302 |
if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) { |
| 16303 |
return; |
| 16304 |
} |
| 16305 |
// adjusting width to fontMatrix scale |
| 16306 |
var scale = 0.001 / properties.fontMatrix[0]; |
| 16307 |
var glyphsWidths = properties.widths; |
| 16308 |
for (var glyph in glyphsWidths) { |
| 16309 |
glyphsWidths[glyph] *= scale; |
| 16310 |
} |
| 16311 |
properties.defaultWidth *= scale; |
| 16312 |
} |
| 16313 |
|
| 16314 |
function getFontType(type, subtype) { |
| 16315 |
switch (type) { |
| 16316 |
case 'Type1': |
| 16317 |
return subtype === 'Type1C' ? FontType.TYPE1C : FontType.TYPE1; |
| 16318 |
case 'CIDFontType0': |
| 16319 |
return subtype === 'CIDFontType0C' ? FontType.CIDFONTTYPE0C : |
| 16320 |
FontType.CIDFONTTYPE0; |
| 16321 |
case 'OpenType': |
| 16322 |
return FontType.OPENTYPE; |
| 16323 |
case 'TrueType': |
| 16324 |
return FontType.TRUETYPE; |
| 16325 |
case 'CIDFontType2': |
| 16326 |
return FontType.CIDFONTTYPE2; |
| 16327 |
case 'MMType1': |
| 16328 |
return FontType.MMTYPE1; |
| 16329 |
case 'Type0': |
| 16330 |
return FontType.TYPE0; |
| 16331 |
default: |
| 16332 |
return FontType.UNKNOWN; |
| 16333 |
} |
| 16334 |
} |
| 16335 |
|
| 16336 |
var Glyph = (function GlyphClosure() { |
| 16337 |
function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId) { |
| 16338 |
this.fontChar = fontChar; |
| 16339 |
this.unicode = unicode; |
| 16340 |
this.accent = accent; |
| 16341 |
this.width = width; |
| 16342 |
this.vmetric = vmetric; |
| 16343 |
this.operatorListId = operatorListId; |
| 16344 |
} |
| 16345 |
|
| 16346 |
Glyph.prototype.matchesForCache = |
| 16347 |
function(fontChar, unicode, accent, width, vmetric, operatorListId) { |
| 16348 |
return this.fontChar === fontChar && |
| 16349 |
this.unicode === unicode && |
| 16350 |
this.accent === accent && |
| 16351 |
this.width === width && |
| 16352 |
this.vmetric === vmetric && |
| 16353 |
this.operatorListId === operatorListId; |
| 16354 |
}; |
| 16355 |
|
| 16356 |
return Glyph; |
| 16357 |
})(); |
| 16358 |
|
| 16359 |
var ToUnicodeMap = (function ToUnicodeMapClosure() { |
| 16360 |
function ToUnicodeMap(cmap) { |
| 16361 |
// The elements of this._map can be integers or strings, depending on how |
| 16362 |
// |cmap| was created. |
| 16363 |
this._map = cmap; |
| 16364 |
} |
| 16365 |
|
| 16366 |
ToUnicodeMap.prototype = { |
| 16367 |
get length() { |
| 16368 |
return this._map.length; |
| 16369 |
}, |
| 16370 |
|
| 16371 |
forEach: function(callback) { |
| 16372 |
for (var charCode in this._map) { |
| 16373 |
callback(charCode, this._map[charCode].charCodeAt(0)); |
| 16374 |
} |
| 16375 |
}, |
| 16376 |
|
| 16377 |
has: function(i) { |
| 16378 |
return this._map[i] !== undefined; |
| 16379 |
}, |
| 16380 |
|
| 16381 |
get: function(i) { |
| 16382 |
return this._map[i]; |
| 16383 |
}, |
| 16384 |
|
| 16385 |
charCodeOf: function(v) { |
| 16386 |
return this._map.indexOf(v); |
| 16387 |
} |
| 16388 |
}; |
| 16389 |
|
| 16390 |
return ToUnicodeMap; |
| 16391 |
})(); |
| 16392 |
|
| 16393 |
var IdentityToUnicodeMap = (function IdentityToUnicodeMapClosure() { |
| 16394 |
function IdentityToUnicodeMap(firstChar, lastChar) { |
| 16395 |
this.firstChar = firstChar; |
| 16396 |
this.lastChar = lastChar; |
| 16397 |
} |
| 16398 |
|
| 16399 |
IdentityToUnicodeMap.prototype = { |
| 16400 |
get length() { |
| 16401 |
return (this.lastChar + 1) - this.firstChar; |
| 16402 |
}, |
| 16403 |
|
| 16404 |
forEach: function (callback) { |
| 16405 |
for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) { |
| 16406 |
callback(i, i); |
| 16407 |
} |
| 16408 |
}, |
| 16409 |
|
| 16410 |
has: function (i) { |
| 16411 |
return this.firstChar <= i && i <= this.lastChar; |
| 16412 |
}, |
| 16413 |
|
| 16414 |
get: function (i) { |
| 16415 |
if (this.firstChar <= i && i <= this.lastChar) { |
| 16416 |
return String.fromCharCode(i); |
| 16417 |
} |
| 16418 |
return undefined; |
| 16419 |
}, |
| 16420 |
|
| 16421 |
charCodeOf: function (v) { |
| 16422 |
error('should not call .charCodeOf'); |
| 16423 |
} |
| 16424 |
}; |
| 16425 |
|
| 16426 |
return IdentityToUnicodeMap; |
| 16427 |
})(); |
| 16428 |
|
| 16429 |
var OpenTypeFileBuilder = (function OpenTypeFileBuilderClosure() { |
| 16430 |
function writeInt16(dest, offset, num) { |
| 16431 |
dest[offset] = (num >> 8) & 0xFF; |
| 16432 |
dest[offset + 1] = num & 0xFF; |
| 16433 |
} |
| 16434 |
|
| 16435 |
function writeInt32(dest, offset, num) { |
| 16436 |
dest[offset] = (num >> 24) & 0xFF; |
| 16437 |
dest[offset + 1] = (num >> 16) & 0xFF; |
| 16438 |
dest[offset + 2] = (num >> 8) & 0xFF; |
| 16439 |
dest[offset + 3] = num & 0xFF; |
| 16440 |
} |
| 16441 |
|
| 16442 |
function writeData(dest, offset, data) { |
| 16443 |
var i, ii; |
| 16444 |
if (data instanceof Uint8Array) { |
| 16445 |
dest.set(data, offset); |
| 16446 |
} else if (typeof data === 'string') { |
| 16447 |
for (i = 0, ii = data.length; i < ii; i++) { |
| 16448 |
dest[offset++] = data.charCodeAt(i) & 0xFF; |
| 16449 |
} |
| 16450 |
} else { |
| 16451 |
// treating everything else as array |
| 16452 |
for (i = 0, ii = data.length; i < ii; i++) { |
| 16453 |
dest[offset++] = data[i] & 0xFF; |
| 16454 |
} |
| 16455 |
} |
| 16456 |
} |
| 16457 |
|
| 16458 |
function OpenTypeFileBuilder(sfnt) { |
| 16459 |
this.sfnt = sfnt; |
| 16460 |
this.tables = Object.create(null); |
| 16461 |
} |
| 16462 |
|
| 16463 |
OpenTypeFileBuilder.getSearchParams = |
| 16464 |
function OpenTypeFileBuilder_getSearchParams(entriesCount, entrySize) { |
| 16465 |
var maxPower2 = 1, log2 = 0; |
| 16466 |
while ((maxPower2 ^ entriesCount) > maxPower2) { |
| 16467 |
maxPower2 <<= 1; |
| 16468 |
log2++; |
| 16469 |
} |
| 16470 |
var searchRange = maxPower2 * entrySize; |
| 16471 |
return { |
| 16472 |
range: searchRange, |
| 16473 |
entry: log2, |
| 16474 |
rangeShift: entrySize * entriesCount - searchRange |
| 16475 |
}; |
| 16476 |
}; |
| 16477 |
|
| 16478 |
var OTF_HEADER_SIZE = 12; |
| 16479 |
var OTF_TABLE_ENTRY_SIZE = 16; |
| 16480 |
|
| 16481 |
OpenTypeFileBuilder.prototype = { |
| 16482 |
toArray: function OpenTypeFileBuilder_toArray() { |
| 16483 |
var sfnt = this.sfnt; |
| 16484 |
|
| 16485 |
// Tables needs to be written by ascendant alphabetic order |
| 16486 |
var tables = this.tables; |
| 16487 |
var tablesNames = Object.keys(tables); |
| 16488 |
tablesNames.sort(); |
| 16489 |
var numTables = tablesNames.length; |
| 16490 |
|
| 16491 |
var i, j, jj, table, tableName; |
| 16492 |
// layout the tables data |
| 16493 |
var offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE; |
| 16494 |
var tableOffsets = [offset]; |
| 16495 |
for (i = 0; i < numTables; i++) { |
| 16496 |
table = tables[tablesNames[i]]; |
| 16497 |
var paddedLength = ((table.length + 3) & ~3) >>> 0; |
| 16498 |
offset += paddedLength; |
| 16499 |
tableOffsets.push(offset); |
| 16500 |
} |
| 16501 |
|
| 16502 |
var file = new Uint8Array(offset); |
| 16503 |
// write the table data first (mostly for checksum) |
| 16504 |
for (i = 0; i < numTables; i++) { |
| 16505 |
table = tables[tablesNames[i]]; |
| 16506 |
writeData(file, tableOffsets[i], table); |
| 16507 |
} |
| 16508 |
|
| 16509 |
// sfnt version (4 bytes) |
| 16510 |
if (sfnt === 'true') { |
| 16511 |
// Windows hates the Mac TrueType sfnt version number |
| 16512 |
sfnt = string32(0x00010000); |
| 16513 |
} |
| 16514 |
file[0] = sfnt.charCodeAt(0) & 0xFF; |
| 16515 |
file[1] = sfnt.charCodeAt(1) & 0xFF; |
| 16516 |
file[2] = sfnt.charCodeAt(2) & 0xFF; |
| 16517 |
file[3] = sfnt.charCodeAt(3) & 0xFF; |
| 16518 |
|
| 16519 |
// numTables (2 bytes) |
| 16520 |
writeInt16(file, 4, numTables); |
| 16521 |
|
| 16522 |
var searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16); |
| 16523 |
|
| 16524 |
// searchRange (2 bytes) |
| 16525 |
writeInt16(file, 6, searchParams.range); |
| 16526 |
// entrySelector (2 bytes) |
| 16527 |
writeInt16(file, 8, searchParams.entry); |
| 16528 |
// rangeShift (2 bytes) |
| 16529 |
writeInt16(file, 10, searchParams.rangeShift); |
| 16530 |
|
| 16531 |
offset = OTF_HEADER_SIZE; |
| 16532 |
// writing table entries |
| 16533 |
for (i = 0; i < numTables; i++) { |
| 16534 |
tableName = tablesNames[i]; |
| 16535 |
file[offset] = tableName.charCodeAt(0) & 0xFF; |
| 16536 |
file[offset + 1] = tableName.charCodeAt(1) & 0xFF; |
| 16537 |
file[offset + 2] = tableName.charCodeAt(2) & 0xFF; |
| 16538 |
file[offset + 3] = tableName.charCodeAt(3) & 0xFF; |
| 16539 |
|
| 16540 |
// checksum |
| 16541 |
var checksum = 0; |
| 16542 |
for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) { |
| 16543 |
var quad = (file[j] << 24) + (file[j + 1] << 16) + |
| 16544 |
(file[j + 2] << 8) + file[j + 3]; |
| 16545 |
checksum = (checksum + quad) | 0; |
| 16546 |
} |
| 16547 |
writeInt32(file, offset + 4, checksum); |
| 16548 |
|
| 16549 |
// offset |
| 16550 |
writeInt32(file, offset + 8, tableOffsets[i]); |
| 16551 |
// length |
| 16552 |
writeInt32(file, offset + 12, tables[tableName].length); |
| 16553 |
|
| 16554 |
offset += OTF_TABLE_ENTRY_SIZE; |
| 16555 |
} |
| 16556 |
return file; |
| 16557 |
}, |
| 16558 |
|
| 16559 |
addTable: function OpenTypeFileBuilder_addTable(tag, data) { |
| 16560 |
if (tag in this.tables) { |
| 16561 |
throw new Error('Table ' + tag + ' already exists'); |
| 16562 |
} |
| 16563 |
this.tables[tag] = data; |
| 16564 |
} |
| 16565 |
}; |
| 16566 |
|
| 16567 |
return OpenTypeFileBuilder; |
| 16568 |
})(); |
| 16569 |
|
| 16570 |
/** |
| 16571 |
* 'Font' is the class the outside world should use, it encapsulate all the font |
| 16572 |
* decoding logics whatever type it is (assuming the font type is supported). |
| 16573 |
* |
| 16574 |
* For example to read a Type1 font and to attach it to the document: |
| 16575 |
* var type1Font = new Font("MyFontName", binaryFile, propertiesObject); |
| 16576 |
* type1Font.bind(); |
| 16577 |
*/ |
| 16578 |
var Font = (function FontClosure() { |
| 16579 |
function Font(name, file, properties) { |
| 16580 |
var charCode, glyphName, fontChar; |
| 16581 |
|
| 16582 |
this.name = name; |
| 16583 |
this.loadedName = properties.loadedName; |
| 16584 |
this.isType3Font = properties.isType3Font; |
| 16585 |
this.sizes = []; |
| 16586 |
|
| 16587 |
this.glyphCache = {}; |
| 16588 |
|
| 16589 |
var names = name.split('+'); |
| 16590 |
names = names.length > 1 ? names[1] : names[0]; |
| 16591 |
names = names.split(/[-,_]/g)[0]; |
| 16592 |
this.isSerifFont = !!(properties.flags & FontFlags.Serif); |
| 16593 |
this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); |
| 16594 |
this.isMonospace = !!(properties.flags & FontFlags.FixedPitch); |
| 16595 |
|
| 16596 |
var type = properties.type; |
| 16597 |
var subtype = properties.subtype; |
| 16598 |
this.type = type; |
| 16599 |
|
| 16600 |
this.fallbackName = (this.isMonospace ? 'monospace' : |
| 16601 |
(this.isSerifFont ? 'serif' : 'sans-serif')); |
| 16602 |
|
| 16603 |
this.differences = properties.differences; |
| 16604 |
this.widths = properties.widths; |
| 16605 |
this.defaultWidth = properties.defaultWidth; |
| 16606 |
this.composite = properties.composite; |
| 16607 |
this.wideChars = properties.wideChars; |
| 16608 |
this.cMap = properties.cMap; |
| 16609 |
this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS; |
| 16610 |
this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS; |
| 16611 |
this.fontMatrix = properties.fontMatrix; |
| 16612 |
|
| 16613 |
this.toUnicode = properties.toUnicode = this.buildToUnicode(properties); |
| 16614 |
|
| 16615 |
this.toFontChar = []; |
| 16616 |
|
| 16617 |
if (properties.type === 'Type3') { |
| 16618 |
for (charCode = 0; charCode < 256; charCode++) { |
| 16619 |
this.toFontChar[charCode] = (this.differences[charCode] || |
| 16620 |
properties.defaultEncoding[charCode]); |
| 16621 |
} |
| 16622 |
this.fontType = FontType.TYPE3; |
| 16623 |
return; |
| 16624 |
} |
| 16625 |
|
| 16626 |
this.cidEncoding = properties.cidEncoding; |
| 16627 |
this.vertical = properties.vertical; |
| 16628 |
if (this.vertical) { |
| 16629 |
this.vmetrics = properties.vmetrics; |
| 16630 |
this.defaultVMetrics = properties.defaultVMetrics; |
| 16631 |
} |
| 16632 |
|
| 16633 |
if (!file || file.isEmpty) { |
| 16634 |
if (file) { |
| 16635 |
// Some bad PDF generators will include empty font files, |
| 16636 |
// attempting to recover by assuming that no file exists. |
| 16637 |
warn('Font file is empty in "' + name + '" (' + this.loadedName + ')'); |
| 16638 |
} |
| 16639 |
|
| 16640 |
this.missingFile = true; |
| 16641 |
// The file data is not specified. Trying to fix the font name |
| 16642 |
// to be used with the canvas.font. |
| 16643 |
var fontName = name.replace(/[,_]/g, '-'); |
| 16644 |
var isStandardFont = !!stdFontMap[fontName] || |
| 16645 |
!!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]); |
| 16646 |
fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; |
| 16647 |
|
| 16648 |
this.bold = (fontName.search(/bold/gi) !== -1); |
| 16649 |
this.italic = ((fontName.search(/oblique/gi) !== -1) || |
| 16650 |
(fontName.search(/italic/gi) !== -1)); |
| 16651 |
|
| 16652 |
// Use 'name' instead of 'fontName' here because the original |
| 16653 |
// name ArialBlack for example will be replaced by Helvetica. |
| 16654 |
this.black = (name.search(/Black/g) !== -1); |
| 16655 |
|
| 16656 |
// if at least one width is present, remeasure all chars when exists |
| 16657 |
this.remeasure = Object.keys(this.widths).length > 0; |
| 16658 |
if (isStandardFont && type === 'CIDFontType2' && |
| 16659 |
properties.cidEncoding.indexOf('Identity-') === 0) { |
| 16660 |
// Standard fonts might be embedded as CID font without glyph mapping. |
| 16661 |
// Building one based on GlyphMapForStandardFonts. |
| 16662 |
var map = []; |
| 16663 |
for (var code in GlyphMapForStandardFonts) { |
| 16664 |
map[+code] = GlyphMapForStandardFonts[code]; |
| 16665 |
} |
| 16666 |
var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap; |
| 16667 |
if (!isIdentityUnicode) { |
| 16668 |
this.toUnicode.forEach(function(charCode, unicodeCharCode) { |
| 16669 |
map[+charCode] = unicodeCharCode; |
| 16670 |
}); |
| 16671 |
} |
| 16672 |
this.toFontChar = map; |
| 16673 |
this.toUnicode = new ToUnicodeMap(map); |
| 16674 |
} else if (/Symbol/i.test(fontName)) { |
| 16675 |
var symbols = Encodings.SymbolSetEncoding; |
| 16676 |
for (charCode in symbols) { |
| 16677 |
fontChar = GlyphsUnicode[symbols[charCode]]; |
| 16678 |
if (!fontChar) { |
| 16679 |
continue; |
| 16680 |
} |
| 16681 |
this.toFontChar[charCode] = fontChar; |
| 16682 |
} |
| 16683 |
for (charCode in properties.differences) { |
| 16684 |
fontChar = GlyphsUnicode[properties.differences[charCode]]; |
| 16685 |
if (!fontChar) { |
| 16686 |
continue; |
| 16687 |
} |
| 16688 |
this.toFontChar[charCode] = fontChar; |
| 16689 |
} |
| 16690 |
} else if (/Dingbats/i.test(fontName)) { |
| 16691 |
if (/Wingdings/i.test(name)) { |
| 16692 |
warn('Wingdings font without embedded font file, ' + |
| 16693 |
'falling back to the ZapfDingbats encoding.'); |
| 16694 |
} |
| 16695 |
var dingbats = Encodings.ZapfDingbatsEncoding; |
| 16696 |
for (charCode in dingbats) { |
| 16697 |
fontChar = DingbatsGlyphsUnicode[dingbats[charCode]]; |
| 16698 |
if (!fontChar) { |
| 16699 |
continue; |
| 16700 |
} |
| 16701 |
this.toFontChar[charCode] = fontChar; |
| 16702 |
} |
| 16703 |
for (charCode in properties.differences) { |
| 16704 |
fontChar = DingbatsGlyphsUnicode[properties.differences[charCode]]; |
| 16705 |
if (!fontChar) { |
| 16706 |
continue; |
| 16707 |
} |
| 16708 |
this.toFontChar[charCode] = fontChar; |
| 16709 |
} |
| 16710 |
} else if (isStandardFont) { |
| 16711 |
this.toFontChar = []; |
| 16712 |
for (charCode in properties.defaultEncoding) { |
| 16713 |
glyphName = (properties.differences[charCode] || |
| 16714 |
properties.defaultEncoding[charCode]); |
| 16715 |
this.toFontChar[charCode] = GlyphsUnicode[glyphName]; |
| 16716 |
} |
| 16717 |
} else { |
| 16718 |
var unicodeCharCode, notCidFont = (type.indexOf('CIDFontType') === -1); |
| 16719 |
this.toUnicode.forEach(function(charCode, unicodeCharCode) { |
| 16720 |
if (notCidFont) { |
| 16721 |
glyphName = (properties.differences[charCode] || |
| 16722 |
properties.defaultEncoding[charCode]); |
| 16723 |
unicodeCharCode = (GlyphsUnicode[glyphName] || unicodeCharCode); |
| 16724 |
} |
| 16725 |
this.toFontChar[charCode] = unicodeCharCode; |
| 16726 |
}.bind(this)); |
| 16727 |
} |
| 16728 |
this.loadedName = fontName.split('-')[0]; |
| 16729 |
this.loading = false; |
| 16730 |
this.fontType = getFontType(type, subtype); |
| 16731 |
return; |
| 16732 |
} |
| 16733 |
|
| 16734 |
// Some fonts might use wrong font types for Type1C or CIDFontType0C |
| 16735 |
if (subtype === 'Type1C' && (type !== 'Type1' && type !== 'MMType1')) { |
| 16736 |
// Some TrueType fonts by mistake claim Type1C |
| 16737 |
if (isTrueTypeFile(file)) { |
| 16738 |
subtype = 'TrueType'; |
| 16739 |
} else { |
| 16740 |
type = 'Type1'; |
| 16741 |
} |
| 16742 |
} |
| 16743 |
if (subtype === 'CIDFontType0C' && type !== 'CIDFontType0') { |
| 16744 |
type = 'CIDFontType0'; |
| 16745 |
} |
| 16746 |
if (subtype === 'OpenType') { |
| 16747 |
type = 'OpenType'; |
| 16748 |
} |
| 16749 |
// Some CIDFontType0C fonts by mistake claim CIDFontType0. |
| 16750 |
if (type === 'CIDFontType0') { |
| 16751 |
subtype = isType1File(file) ? 'CIDFontType0' : 'CIDFontType0C'; |
| 16752 |
} |
| 16753 |
|
| 16754 |
var data; |
| 16755 |
switch (type) { |
| 16756 |
case 'MMType1': |
| 16757 |
info('MMType1 font (' + name + '), falling back to Type1.'); |
| 16758 |
/* falls through */ |
| 16759 |
case 'Type1': |
| 16760 |
case 'CIDFontType0': |
| 16761 |
this.mimetype = 'font/opentype'; |
| 16762 |
|
| 16763 |
var cff = (subtype === 'Type1C' || subtype === 'CIDFontType0C') ? |
| 16764 |
new CFFFont(file, properties) : new Type1Font(name, file, properties); |
| 16765 |
|
| 16766 |
adjustWidths(properties); |
| 16767 |
|
| 16768 |
// Wrap the CFF data inside an OTF font file |
| 16769 |
data = this.convert(name, cff, properties); |
| 16770 |
break; |
| 16771 |
|
| 16772 |
case 'OpenType': |
| 16773 |
case 'TrueType': |
| 16774 |
case 'CIDFontType2': |
| 16775 |
this.mimetype = 'font/opentype'; |
| 16776 |
|
| 16777 |
// Repair the TrueType file. It is can be damaged in the point of |
| 16778 |
// view of the sanitizer |
| 16779 |
data = this.checkAndRepair(name, file, properties); |
| 16780 |
if (this.isOpenType) { |
| 16781 |
type = 'OpenType'; |
| 16782 |
} |
| 16783 |
break; |
| 16784 |
|
| 16785 |
default: |
| 16786 |
error('Font ' + type + ' is not supported'); |
| 16787 |
break; |
| 16788 |
} |
| 16789 |
|
| 16790 |
this.data = data; |
| 16791 |
this.fontType = getFontType(type, subtype); |
| 16792 |
|
| 16793 |
// Transfer some properties again that could change during font conversion |
| 16794 |
this.fontMatrix = properties.fontMatrix; |
| 16795 |
this.widths = properties.widths; |
| 16796 |
this.defaultWidth = properties.defaultWidth; |
| 16797 |
this.encoding = properties.baseEncoding; |
| 16798 |
this.seacMap = properties.seacMap; |
| 16799 |
|
| 16800 |
this.loading = true; |
| 16801 |
} |
| 16802 |
|
| 16803 |
Font.getFontID = (function () { |
| 16804 |
var ID = 1; |
| 16805 |
return function Font_getFontID() { |
| 16806 |
return String(ID++); |
| 16807 |
}; |
| 16808 |
})(); |
| 16809 |
|
| 16810 |
function int16(b0, b1) { |
| 16811 |
return (b0 << 8) + b1; |
| 16812 |
} |
| 16813 |
|
| 16814 |
function int32(b0, b1, b2, b3) { |
| 16815 |
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; |
| 16816 |
} |
| 16817 |
|
| 16818 |
function string16(value) { |
| 16819 |
return String.fromCharCode((value >> 8) & 0xff, value & 0xff); |
| 16820 |
} |
| 16821 |
|
| 16822 |
function safeString16(value) { |
| 16823 |
// clamp value to the 16-bit int range |
| 16824 |
value = (value > 0x7FFF ? 0x7FFF : (value < -0x8000 ? -0x8000 : value)); |
| 16825 |
return String.fromCharCode((value >> 8) & 0xff, value & 0xff); |
| 16826 |
} |
| 16827 |
|
| 16828 |
function isTrueTypeFile(file) { |
| 16829 |
var header = file.peekBytes(4); |
| 16830 |
return readUint32(header, 0) === 0x00010000; |
| 16831 |
} |
| 16832 |
|
| 16833 |
function isType1File(file) { |
| 16834 |
var header = file.peekBytes(2); |
| 16835 |
// All Type1 font programs must begin with the comment '%!' (0x25 + 0x21). |
| 16836 |
if (header[0] === 0x25 && header[1] === 0x21) { |
| 16837 |
return true; |
| 16838 |
} |
| 16839 |
// ... obviously some fonts violate that part of the specification, |
| 16840 |
// please refer to the comment in |Type1Font| below. |
| 16841 |
if (header[0] === 0x80 && header[1] === 0x01) { // pfb file header. |
| 16842 |
return true; |
| 16843 |
} |
| 16844 |
return false; |
| 16845 |
} |
| 16846 |
|
| 16847 |
/** |
| 16848 |
* Helper function for |adjustMapping|. |
| 16849 |
* @return {boolean} |
| 16850 |
*/ |
| 16851 |
function isProblematicUnicodeLocation(code) { |
| 16852 |
if (code <= 0x1F) { // Control chars |
| 16853 |
return true; |
| 16854 |
} |
| 16855 |
if (code >= 0x80 && code <= 0x9F) { // Control chars |
| 16856 |
return true; |
| 16857 |
} |
| 16858 |
if ((code >= 0x2000 && code <= 0x200F) || // General punctuation chars |
| 16859 |
(code >= 0x2028 && code <= 0x202F) || |
| 16860 |
(code >= 0x2060 && code <= 0x206F)) { |
| 16861 |
return true; |
| 16862 |
} |
| 16863 |
if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials Unicode block |
| 16864 |
return true; |
| 16865 |
} |
| 16866 |
switch (code) { |
| 16867 |
case 0x7F: // Control char |
| 16868 |
case 0xA0: // Non breaking space |
| 16869 |
case 0xAD: // Soft hyphen |
| 16870 |
case 0x0E33: // Thai character SARA AM |
| 16871 |
case 0x2011: // Non breaking hyphen |
| 16872 |
case 0x205F: // Medium mathematical space |
| 16873 |
case 0x25CC: // Dotted circle (combining mark) |
| 16874 |
return true; |
| 16875 |
} |
| 16876 |
return false; |
| 16877 |
} |
| 16878 |
|
| 16879 |
/** |
| 16880 |
* Rebuilds the char code to glyph ID map by trying to replace the char codes |
| 16881 |
* with their unicode value. It also moves char codes that are in known |
| 16882 |
* problematic locations. |
| 16883 |
* @return {Object} Two properties: |
| 16884 |
* 'toFontChar' - maps original char codes(the value that will be read |
| 16885 |
* from commands such as show text) to the char codes that will be used in the |
| 16886 |
* font that we build |
| 16887 |
* 'charCodeToGlyphId' - maps the new font char codes to glyph ids |
| 16888 |
*/ |
| 16889 |
function adjustMapping(charCodeToGlyphId, properties) { |
| 16890 |
var toUnicode = properties.toUnicode; |
| 16891 |
var isSymbolic = !!(properties.flags & FontFlags.Symbolic); |
| 16892 |
var isIdentityUnicode = |
| 16893 |
properties.toUnicode instanceof IdentityToUnicodeMap; |
| 16894 |
var newMap = Object.create(null); |
| 16895 |
var toFontChar = []; |
| 16896 |
var usedFontCharCodes = []; |
| 16897 |
var nextAvailableFontCharCode = PRIVATE_USE_OFFSET_START; |
| 16898 |
for (var originalCharCode in charCodeToGlyphId) { |
| 16899 |
originalCharCode |= 0; |
| 16900 |
var glyphId = charCodeToGlyphId[originalCharCode]; |
| 16901 |
var fontCharCode = originalCharCode; |
| 16902 |
// First try to map the value to a unicode position if a non identity map |
| 16903 |
// was created. |
| 16904 |
if (!isIdentityUnicode && toUnicode.has(originalCharCode)) { |
| 16905 |
var unicode = toUnicode.get(fontCharCode); |
| 16906 |
// TODO: Try to map ligatures to the correct spot. |
| 16907 |
if (unicode.length === 1) { |
| 16908 |
fontCharCode = unicode.charCodeAt(0); |
| 16909 |
} |
| 16910 |
} |
| 16911 |
// Try to move control characters, special characters and already mapped |
| 16912 |
// characters to the private use area since they will not be drawn by |
| 16913 |
// canvas if left in their current position. Also, move characters if the |
| 16914 |
// font was symbolic and there is only an identity unicode map since the |
| 16915 |
// characters probably aren't in the correct position (fixes an issue |
| 16916 |
// with firefox and thuluthfont). |
| 16917 |
if ((usedFontCharCodes[fontCharCode] !== undefined || |
| 16918 |
isProblematicUnicodeLocation(fontCharCode) || |
| 16919 |
(isSymbolic && isIdentityUnicode)) && |
| 16920 |
nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) { // Room left. |
| 16921 |
// Loop to try and find a free spot in the private use area. |
| 16922 |
do { |
| 16923 |
fontCharCode = nextAvailableFontCharCode++; |
| 16924 |
|
| 16925 |
if (SKIP_PRIVATE_USE_RANGE_F000_TO_F01F && fontCharCode === 0xF000) { |
| 16926 |
fontCharCode = 0xF020; |
| 16927 |
nextAvailableFontCharCode = fontCharCode + 1; |
| 16928 |
} |
| 16929 |
|
| 16930 |
} while (usedFontCharCodes[fontCharCode] !== undefined && |
| 16931 |
nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END); |
| 16932 |
} |
| 16933 |
|
| 16934 |
newMap[fontCharCode] = glyphId; |
| 16935 |
toFontChar[originalCharCode] = fontCharCode; |
| 16936 |
usedFontCharCodes[fontCharCode] = true; |
| 16937 |
} |
| 16938 |
return { |
| 16939 |
toFontChar: toFontChar, |
| 16940 |
charCodeToGlyphId: newMap, |
| 16941 |
nextAvailableFontCharCode: nextAvailableFontCharCode |
| 16942 |
}; |
| 16943 |
} |
| 16944 |
|
| 16945 |
function getRanges(glyphs) { |
| 16946 |
// Array.sort() sorts by characters, not numerically, so convert to an |
| 16947 |
// array of characters. |
| 16948 |
var codes = []; |
| 16949 |
for (var charCode in glyphs) { |
| 16950 |
codes.push({ fontCharCode: charCode | 0, glyphId: glyphs[charCode] }); |
| 16951 |
} |
| 16952 |
codes.sort(function fontGetRangesSort(a, b) { |
| 16953 |
return a.fontCharCode - b.fontCharCode; |
| 16954 |
}); |
| 16955 |
|
| 16956 |
// Split the sorted codes into ranges. |
| 16957 |
var ranges = []; |
| 16958 |
var length = codes.length; |
| 16959 |
for (var n = 0; n < length; ) { |
| 16960 |
var start = codes[n].fontCharCode; |
| 16961 |
var codeIndices = [codes[n].glyphId]; |
| 16962 |
++n; |
| 16963 |
var end = start; |
| 16964 |
while (n < length && end + 1 === codes[n].fontCharCode) { |
| 16965 |
codeIndices.push(codes[n].glyphId); |
| 16966 |
++end; |
| 16967 |
++n; |
| 16968 |
if (end === 0xFFFF) { |
| 16969 |
break; |
| 16970 |
} |
| 16971 |
} |
| 16972 |
ranges.push([start, end, codeIndices]); |
| 16973 |
} |
| 16974 |
|
| 16975 |
return ranges; |
| 16976 |
} |
| 16977 |
|
| 16978 |
function createCmapTable(glyphs) { |
| 16979 |
var ranges = getRanges(glyphs); |
| 16980 |
var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1; |
| 16981 |
var cmap = '\x00\x00' + // version |
| 16982 |
string16(numTables) + // numTables |
| 16983 |
'\x00\x03' + // platformID |
| 16984 |
'\x00\x01' + // encodingID |
| 16985 |
string32(4 + numTables * 8); // start of the table record |
| 16986 |
|
| 16987 |
var i, ii, j, jj; |
| 16988 |
for (i = ranges.length - 1; i >= 0; --i) { |
| 16989 |
if (ranges[i][0] <= 0xFFFF) { break; } |
| 16990 |
} |
| 16991 |
var bmpLength = i + 1; |
| 16992 |
|
| 16993 |
if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) { |
| 16994 |
ranges[i][1] = 0xFFFE; |
| 16995 |
} |
| 16996 |
var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0; |
| 16997 |
var segCount = bmpLength + trailingRangesCount; |
| 16998 |
var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2); |
| 16999 |
|
| 17000 |
// Fill up the 4 parallel arrays describing the segments. |
| 17001 |
var startCount = ''; |
| 17002 |
var endCount = ''; |
| 17003 |
var idDeltas = ''; |
| 17004 |
var idRangeOffsets = ''; |
| 17005 |
var glyphsIds = ''; |
| 17006 |
var bias = 0; |
| 17007 |
|
| 17008 |
var range, start, end, codes; |
| 17009 |
for (i = 0, ii = bmpLength; i < ii; i++) { |
| 17010 |
range = ranges[i]; |
| 17011 |
start = range[0]; |
| 17012 |
end = range[1]; |
| 17013 |
startCount += string16(start); |
| 17014 |
endCount += string16(end); |
| 17015 |
codes = range[2]; |
| 17016 |
var contiguous = true; |
| 17017 |
for (j = 1, jj = codes.length; j < jj; ++j) { |
| 17018 |
if (codes[j] !== codes[j - 1] + 1) { |
| 17019 |
contiguous = false; |
| 17020 |
break; |
| 17021 |
} |
| 17022 |
} |
| 17023 |
if (!contiguous) { |
| 17024 |
var offset = (segCount - i) * 2 + bias * 2; |
| 17025 |
bias += (end - start + 1); |
| 17026 |
|
| 17027 |
idDeltas += string16(0); |
| 17028 |
idRangeOffsets += string16(offset); |
| 17029 |
|
| 17030 |
for (j = 0, jj = codes.length; j < jj; ++j) { |
| 17031 |
glyphsIds += string16(codes[j]); |
| 17032 |
} |
| 17033 |
} else { |
| 17034 |
var startCode = codes[0]; |
| 17035 |
|
| 17036 |
idDeltas += string16((startCode - start) & 0xFFFF); |
| 17037 |
idRangeOffsets += string16(0); |
| 17038 |
} |
| 17039 |
} |
| 17040 |
|
| 17041 |
if (trailingRangesCount > 0) { |
| 17042 |
endCount += '\xFF\xFF'; |
| 17043 |
startCount += '\xFF\xFF'; |
| 17044 |
idDeltas += '\x00\x01'; |
| 17045 |
idRangeOffsets += '\x00\x00'; |
| 17046 |
} |
| 17047 |
|
| 17048 |
var format314 = '\x00\x00' + // language |
| 17049 |
string16(2 * segCount) + |
| 17050 |
string16(searchParams.range) + |
| 17051 |
string16(searchParams.entry) + |
| 17052 |
string16(searchParams.rangeShift) + |
| 17053 |
endCount + '\x00\x00' + startCount + |
| 17054 |
idDeltas + idRangeOffsets + glyphsIds; |
| 17055 |
|
| 17056 |
var format31012 = ''; |
| 17057 |
var header31012 = ''; |
| 17058 |
if (numTables > 1) { |
| 17059 |
cmap += '\x00\x03' + // platformID |
| 17060 |
'\x00\x0A' + // encodingID |
| 17061 |
string32(4 + numTables * 8 + |
| 17062 |
4 + format314.length); // start of the table record |
| 17063 |
format31012 = ''; |
| 17064 |
for (i = 0, ii = ranges.length; i < ii; i++) { |
| 17065 |
range = ranges[i]; |
| 17066 |
start = range[0]; |
| 17067 |
codes = range[2]; |
| 17068 |
var code = codes[0]; |
| 17069 |
for (j = 1, jj = codes.length; j < jj; ++j) { |
| 17070 |
if (codes[j] !== codes[j - 1] + 1) { |
| 17071 |
end = range[0] + j - 1; |
| 17072 |
format31012 += string32(start) + // startCharCode |
| 17073 |
string32(end) + // endCharCode |
| 17074 |
string32(code); // startGlyphID |
| 17075 |
start = end + 1; |
| 17076 |
code = codes[j]; |
| 17077 |
} |
| 17078 |
} |
| 17079 |
format31012 += string32(start) + // startCharCode |
| 17080 |
string32(range[1]) + // endCharCode |
| 17081 |
string32(code); // startGlyphID |
| 17082 |
} |
| 17083 |
header31012 = '\x00\x0C' + // format |
| 17084 |
'\x00\x00' + // reserved |
| 17085 |
string32(format31012.length + 16) + // length |
| 17086 |
'\x00\x00\x00\x00' + // language |
| 17087 |
string32(format31012.length / 12); // nGroups |
| 17088 |
} |
| 17089 |
|
| 17090 |
return cmap + '\x00\x04' + // format |
| 17091 |
string16(format314.length + 4) + // length |
| 17092 |
format314 + header31012 + format31012; |
| 17093 |
} |
| 17094 |
|
| 17095 |
function validateOS2Table(os2) { |
| 17096 |
var stream = new Stream(os2.data); |
| 17097 |
var version = stream.getUint16(); |
| 17098 |
// TODO verify all OS/2 tables fields, but currently we validate only those |
| 17099 |
// that give us issues |
| 17100 |
stream.getBytes(60); // skipping type, misc sizes, panose, unicode ranges |
| 17101 |
var selection = stream.getUint16(); |
| 17102 |
if (version < 4 && (selection & 0x0300)) { |
| 17103 |
return false; |
| 17104 |
} |
| 17105 |
var firstChar = stream.getUint16(); |
| 17106 |
var lastChar = stream.getUint16(); |
| 17107 |
if (firstChar > lastChar) { |
| 17108 |
return false; |
| 17109 |
} |
| 17110 |
stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap |
| 17111 |
var usWinAscent = stream.getUint16(); |
| 17112 |
if (usWinAscent === 0) { // makes font unreadable by windows |
| 17113 |
return false; |
| 17114 |
} |
| 17115 |
|
| 17116 |
// OS/2 appears to be valid, resetting some fields |
| 17117 |
os2.data[8] = os2.data[9] = 0; // IE rejects fonts if fsType != 0 |
| 17118 |
return true; |
| 17119 |
} |
| 17120 |
|
| 17121 |
function createOS2Table(properties, charstrings, override) { |
| 17122 |
override = override || { |
| 17123 |
unitsPerEm: 0, |
| 17124 |
yMax: 0, |
| 17125 |
yMin: 0, |
| 17126 |
ascent: 0, |
| 17127 |
descent: 0 |
| 17128 |
}; |
| 17129 |
|
| 17130 |
var ulUnicodeRange1 = 0; |
| 17131 |
var ulUnicodeRange2 = 0; |
| 17132 |
var ulUnicodeRange3 = 0; |
| 17133 |
var ulUnicodeRange4 = 0; |
| 17134 |
|
| 17135 |
var firstCharIndex = null; |
| 17136 |
var lastCharIndex = 0; |
| 17137 |
|
| 17138 |
if (charstrings) { |
| 17139 |
for (var code in charstrings) { |
| 17140 |
code |= 0; |
| 17141 |
if (firstCharIndex > code || !firstCharIndex) { |
| 17142 |
firstCharIndex = code; |
| 17143 |
} |
| 17144 |
if (lastCharIndex < code) { |
| 17145 |
lastCharIndex = code; |
| 17146 |
} |
| 17147 |
|
| 17148 |
var position = getUnicodeRangeFor(code); |
| 17149 |
if (position < 32) { |
| 17150 |
ulUnicodeRange1 |= 1 << position; |
| 17151 |
} else if (position < 64) { |
| 17152 |
ulUnicodeRange2 |= 1 << position - 32; |
| 17153 |
} else if (position < 96) { |
| 17154 |
ulUnicodeRange3 |= 1 << position - 64; |
| 17155 |
} else if (position < 123) { |
| 17156 |
ulUnicodeRange4 |= 1 << position - 96; |
| 17157 |
} else { |
| 17158 |
error('Unicode ranges Bits > 123 are reserved for internal usage'); |
| 17159 |
} |
| 17160 |
} |
| 17161 |
} else { |
| 17162 |
// TODO |
| 17163 |
firstCharIndex = 0; |
| 17164 |
lastCharIndex = 255; |
| 17165 |
} |
| 17166 |
|
| 17167 |
var bbox = properties.bbox || [0, 0, 0, 0]; |
| 17168 |
var unitsPerEm = (override.unitsPerEm || |
| 17169 |
1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]); |
| 17170 |
|
| 17171 |
// if the font units differ to the PDF glyph space units |
| 17172 |
// then scale up the values |
| 17173 |
var scale = (properties.ascentScaled ? 1.0 : |
| 17174 |
unitsPerEm / PDF_GLYPH_SPACE_UNITS); |
| 17175 |
|
| 17176 |
var typoAscent = (override.ascent || |
| 17177 |
Math.round(scale * (properties.ascent || bbox[3]))); |
| 17178 |
var typoDescent = (override.descent || |
| 17179 |
Math.round(scale * (properties.descent || bbox[1]))); |
| 17180 |
if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) { |
| 17181 |
typoDescent = -typoDescent; // fixing incorrect descent |
| 17182 |
} |
| 17183 |
var winAscent = override.yMax || typoAscent; |
| 17184 |
var winDescent = -override.yMin || -typoDescent; |
| 17185 |
|
| 17186 |
return '\x00\x03' + // version |
| 17187 |
'\x02\x24' + // xAvgCharWidth |
| 17188 |
'\x01\xF4' + // usWeightClass |
| 17189 |
'\x00\x05' + // usWidthClass |
| 17190 |
'\x00\x00' + // fstype (0 to let the font loads via font-face on IE) |
| 17191 |
'\x02\x8A' + // ySubscriptXSize |
| 17192 |
'\x02\xBB' + // ySubscriptYSize |
| 17193 |
'\x00\x00' + // ySubscriptXOffset |
| 17194 |
'\x00\x8C' + // ySubscriptYOffset |
| 17195 |
'\x02\x8A' + // ySuperScriptXSize |
| 17196 |
'\x02\xBB' + // ySuperScriptYSize |
| 17197 |
'\x00\x00' + // ySuperScriptXOffset |
| 17198 |
'\x01\xDF' + // ySuperScriptYOffset |
| 17199 |
'\x00\x31' + // yStrikeOutSize |
| 17200 |
'\x01\x02' + // yStrikeOutPosition |
| 17201 |
'\x00\x00' + // sFamilyClass |
| 17202 |
'\x00\x00\x06' + |
| 17203 |
String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + |
| 17204 |
'\x00\x00\x00\x00\x00\x00' + // Panose |
| 17205 |
string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31) |
| 17206 |
string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63) |
| 17207 |
string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95) |
| 17208 |
string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127) |
| 17209 |
'\x2A\x32\x31\x2A' + // achVendID |
| 17210 |
string16(properties.italicAngle ? 1 : 0) + // fsSelection |
| 17211 |
string16(firstCharIndex || |
| 17212 |
properties.firstChar) + // usFirstCharIndex |
| 17213 |
string16(lastCharIndex || properties.lastChar) + // usLastCharIndex |
| 17214 |
string16(typoAscent) + // sTypoAscender |
| 17215 |
string16(typoDescent) + // sTypoDescender |
| 17216 |
'\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value) |
| 17217 |
string16(winAscent) + // usWinAscent |
| 17218 |
string16(winDescent) + // usWinDescent |
| 17219 |
'\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31) |
| 17220 |
'\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63) |
| 17221 |
string16(properties.xHeight) + // sxHeight |
| 17222 |
string16(properties.capHeight) + // sCapHeight |
| 17223 |
string16(0) + // usDefaultChar |
| 17224 |
string16(firstCharIndex || properties.firstChar) + // usBreakChar |
| 17225 |
'\x00\x03'; // usMaxContext |
| 17226 |
} |
| 17227 |
|
| 17228 |
function createPostTable(properties) { |
| 17229 |
var angle = Math.floor(properties.italicAngle * (Math.pow(2, 16))); |
| 17230 |
return ('\x00\x03\x00\x00' + // Version number |
| 17231 |
string32(angle) + // italicAngle |
| 17232 |
'\x00\x00' + // underlinePosition |
| 17233 |
'\x00\x00' + // underlineThickness |
| 17234 |
string32(properties.fixedPitch) + // isFixedPitch |
| 17235 |
'\x00\x00\x00\x00' + // minMemType42 |
| 17236 |
'\x00\x00\x00\x00' + // maxMemType42 |
| 17237 |
'\x00\x00\x00\x00' + // minMemType1 |
| 17238 |
'\x00\x00\x00\x00'); // maxMemType1 |
| 17239 |
} |
| 17240 |
|
| 17241 |
function createNameTable(name, proto) { |
| 17242 |
if (!proto) { |
| 17243 |
proto = [[], []]; // no strings and unicode strings |
| 17244 |
} |
| 17245 |
|
| 17246 |
var strings = [ |
| 17247 |
proto[0][0] || 'Original licence', // 0.Copyright |
| 17248 |
proto[0][1] || name, // 1.Font family |
| 17249 |
proto[0][2] || 'Unknown', // 2.Font subfamily (font weight) |
| 17250 |
proto[0][3] || 'uniqueID', // 3.Unique ID |
| 17251 |
proto[0][4] || name, // 4.Full font name |
| 17252 |
proto[0][5] || 'Version 0.11', // 5.Version |
| 17253 |
proto[0][6] || '', // 6.Postscript name |
| 17254 |
proto[0][7] || 'Unknown', // 7.Trademark |
| 17255 |
proto[0][8] || 'Unknown', // 8.Manufacturer |
| 17256 |
proto[0][9] || 'Unknown' // 9.Designer |
| 17257 |
]; |
| 17258 |
|
| 17259 |
// Mac want 1-byte per character strings while Windows want |
| 17260 |
// 2-bytes per character, so duplicate the names table |
| 17261 |
var stringsUnicode = []; |
| 17262 |
var i, ii, j, jj, str; |
| 17263 |
for (i = 0, ii = strings.length; i < ii; i++) { |
| 17264 |
str = proto[1][i] || strings[i]; |
| 17265 |
|
| 17266 |
var strBufUnicode = []; |
| 17267 |
for (j = 0, jj = str.length; j < jj; j++) { |
| 17268 |
strBufUnicode.push(string16(str.charCodeAt(j))); |
| 17269 |
} |
| 17270 |
stringsUnicode.push(strBufUnicode.join('')); |
| 17271 |
} |
| 17272 |
|
| 17273 |
var names = [strings, stringsUnicode]; |
| 17274 |
var platforms = ['\x00\x01', '\x00\x03']; |
| 17275 |
var encodings = ['\x00\x00', '\x00\x01']; |
| 17276 |
var languages = ['\x00\x00', '\x04\x09']; |
| 17277 |
|
| 17278 |
var namesRecordCount = strings.length * platforms.length; |
| 17279 |
var nameTable = |
| 17280 |
'\x00\x00' + // format |
| 17281 |
string16(namesRecordCount) + // Number of names Record |
| 17282 |
string16(namesRecordCount * 12 + 6); // Storage |
| 17283 |
|
| 17284 |
// Build the name records field |
| 17285 |
var strOffset = 0; |
| 17286 |
for (i = 0, ii = platforms.length; i < ii; i++) { |
| 17287 |
var strs = names[i]; |
| 17288 |
for (j = 0, jj = strs.length; j < jj; j++) { |
| 17289 |
str = strs[j]; |
| 17290 |
var nameRecord = |
| 17291 |
platforms[i] + // platform ID |
| 17292 |
encodings[i] + // encoding ID |
| 17293 |
languages[i] + // language ID |
| 17294 |
string16(j) + // name ID |
| 17295 |
string16(str.length) + |
| 17296 |
string16(strOffset); |
| 17297 |
nameTable += nameRecord; |
| 17298 |
strOffset += str.length; |
| 17299 |
} |
| 17300 |
} |
| 17301 |
|
| 17302 |
nameTable += strings.join('') + stringsUnicode.join(''); |
| 17303 |
return nameTable; |
| 17304 |
} |
| 17305 |
|
| 17306 |
Font.prototype = { |
| 17307 |
name: null, |
| 17308 |
font: null, |
| 17309 |
mimetype: null, |
| 17310 |
encoding: null, |
| 17311 |
get renderer() { |
| 17312 |
var renderer = FontRendererFactory.create(this); |
| 17313 |
return shadow(this, 'renderer', renderer); |
| 17314 |
}, |
| 17315 |
|
| 17316 |
exportData: function Font_exportData() { |
| 17317 |
var data = {}; |
| 17318 |
for (var i in this) { |
| 17319 |
if (this.hasOwnProperty(i)) { |
| 17320 |
data[i] = this[i]; |
| 17321 |
} |
| 17322 |
} |
| 17323 |
return data; |
| 17324 |
}, |
| 17325 |
|
| 17326 |
checkAndRepair: function Font_checkAndRepair(name, font, properties) { |
| 17327 |
function readTableEntry(file) { |
| 17328 |
var tag = bytesToString(file.getBytes(4)); |
| 17329 |
|
| 17330 |
var checksum = file.getInt32(); |
| 17331 |
var offset = file.getInt32() >>> 0; |
| 17332 |
var length = file.getInt32() >>> 0; |
| 17333 |
|
| 17334 |
// Read the table associated data |
| 17335 |
var previousPosition = file.pos; |
| 17336 |
file.pos = file.start ? file.start : 0; |
| 17337 |
file.skip(offset); |
| 17338 |
var data = file.getBytes(length); |
| 17339 |
file.pos = previousPosition; |
| 17340 |
|
| 17341 |
if (tag === 'head') { |
| 17342 |
// clearing checksum adjustment |
| 17343 |
data[8] = data[9] = data[10] = data[11] = 0; |
| 17344 |
data[17] |= 0x20; //Set font optimized for cleartype flag |
| 17345 |
} |
| 17346 |
|
| 17347 |
return { |
| 17348 |
tag: tag, |
| 17349 |
checksum: checksum, |
| 17350 |
length: length, |
| 17351 |
offset: offset, |
| 17352 |
data: data |
| 17353 |
}; |
| 17354 |
} |
| 17355 |
|
| 17356 |
function readOpenTypeHeader(ttf) { |
| 17357 |
return { |
| 17358 |
version: bytesToString(ttf.getBytes(4)), |
| 17359 |
numTables: ttf.getUint16(), |
| 17360 |
searchRange: ttf.getUint16(), |
| 17361 |
entrySelector: ttf.getUint16(), |
| 17362 |
rangeShift: ttf.getUint16() |
| 17363 |
}; |
| 17364 |
} |
| 17365 |
|
| 17366 |
/** |
| 17367 |
* Read the appropriate subtable from the cmap according to 9.6.6.4 from |
| 17368 |
* PDF spec |
| 17369 |
*/ |
| 17370 |
function readCmapTable(cmap, font, isSymbolicFont) { |
| 17371 |
var segment; |
| 17372 |
var start = (font.start ? font.start : 0) + cmap.offset; |
| 17373 |
font.pos = start; |
| 17374 |
|
| 17375 |
var version = font.getUint16(); |
| 17376 |
var numTables = font.getUint16(); |
| 17377 |
|
| 17378 |
var potentialTable; |
| 17379 |
var canBreak = false; |
| 17380 |
// There's an order of preference in terms of which cmap subtable to |
| 17381 |
// use: |
| 17382 |
// - non-symbolic fonts the preference is a 3,1 table then a 1,0 table |
| 17383 |
// - symbolic fonts the preference is a 3,0 table then a 1,0 table |
| 17384 |
// The following takes advantage of the fact that the tables are sorted |
| 17385 |
// to work. |
| 17386 |
for (var i = 0; i < numTables; i++) { |
| 17387 |
var platformId = font.getUint16(); |
| 17388 |
var encodingId = font.getUint16(); |
| 17389 |
var offset = font.getInt32() >>> 0; |
| 17390 |
var useTable = false; |
| 17391 |
|
| 17392 |
if (platformId === 0 && encodingId === 0) { |
| 17393 |
useTable = true; |
| 17394 |
// Continue the loop since there still may be a higher priority |
| 17395 |
// table. |
| 17396 |
} else if (platformId === 1 && encodingId === 0) { |
| 17397 |
useTable = true; |
| 17398 |
// Continue the loop since there still may be a higher priority |
| 17399 |
// table. |
| 17400 |
} else if (platformId === 3 && encodingId === 1 && |
| 17401 |
(!isSymbolicFont || !potentialTable)) { |
| 17402 |
useTable = true; |
| 17403 |
if (!isSymbolicFont) { |
| 17404 |
canBreak = true; |
| 17405 |
} |
| 17406 |
} else if (isSymbolicFont && platformId === 3 && encodingId === 0) { |
| 17407 |
useTable = true; |
| 17408 |
canBreak = true; |
| 17409 |
} |
| 17410 |
|
| 17411 |
if (useTable) { |
| 17412 |
potentialTable = { |
| 17413 |
platformId: platformId, |
| 17414 |
encodingId: encodingId, |
| 17415 |
offset: offset |
| 17416 |
}; |
| 17417 |
} |
| 17418 |
if (canBreak) { |
| 17419 |
break; |
| 17420 |
} |
| 17421 |
} |
| 17422 |
|
| 17423 |
if (!potentialTable) { |
| 17424 |
warn('Could not find a preferred cmap table.'); |
| 17425 |
return { |
| 17426 |
platformId: -1, |
| 17427 |
encodingId: -1, |
| 17428 |
mappings: [], |
| 17429 |
hasShortCmap: false |
| 17430 |
}; |
| 17431 |
} |
| 17432 |
|
| 17433 |
font.pos = start + potentialTable.offset; |
| 17434 |
var format = font.getUint16(); |
| 17435 |
var length = font.getUint16(); |
| 17436 |
var language = font.getUint16(); |
| 17437 |
|
| 17438 |
var hasShortCmap = false; |
| 17439 |
var mappings = []; |
| 17440 |
var j, glyphId; |
| 17441 |
|
| 17442 |
// TODO(mack): refactor this cmap subtable reading logic out |
| 17443 |
if (format === 0) { |
| 17444 |
for (j = 0; j < 256; j++) { |
| 17445 |
var index = font.getByte(); |
| 17446 |
if (!index) { |
| 17447 |
continue; |
| 17448 |
} |
| 17449 |
mappings.push({ |
| 17450 |
charCode: j, |
| 17451 |
glyphId: index |
| 17452 |
}); |
| 17453 |
} |
| 17454 |
hasShortCmap = true; |
| 17455 |
} else if (format === 4) { |
| 17456 |
// re-creating the table in format 4 since the encoding |
| 17457 |
// might be changed |
| 17458 |
var segCount = (font.getUint16() >> 1); |
| 17459 |
font.getBytes(6); // skipping range fields |
| 17460 |
var segIndex, segments = []; |
| 17461 |
for (segIndex = 0; segIndex < segCount; segIndex++) { |
| 17462 |
segments.push({ end: font.getUint16() }); |
| 17463 |
} |
| 17464 |
font.getUint16(); |
| 17465 |
for (segIndex = 0; segIndex < segCount; segIndex++) { |
| 17466 |
segments[segIndex].start = font.getUint16(); |
| 17467 |
} |
| 17468 |
|
| 17469 |
for (segIndex = 0; segIndex < segCount; segIndex++) { |
| 17470 |
segments[segIndex].delta = font.getUint16(); |
| 17471 |
} |
| 17472 |
|
| 17473 |
var offsetsCount = 0; |
| 17474 |
for (segIndex = 0; segIndex < segCount; segIndex++) { |
| 17475 |
segment = segments[segIndex]; |
| 17476 |
var rangeOffset = font.getUint16(); |
| 17477 |
if (!rangeOffset) { |
| 17478 |
segment.offsetIndex = -1; |
| 17479 |
continue; |
| 17480 |
} |
| 17481 |
|
| 17482 |
var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex); |
| 17483 |
segment.offsetIndex = offsetIndex; |
| 17484 |
offsetsCount = Math.max(offsetsCount, offsetIndex + |
| 17485 |
segment.end - segment.start + 1); |
| 17486 |
} |
| 17487 |
|
| 17488 |
var offsets = []; |
| 17489 |
for (j = 0; j < offsetsCount; j++) { |
| 17490 |
offsets.push(font.getUint16()); |
| 17491 |
} |
| 17492 |
|
| 17493 |
for (segIndex = 0; segIndex < segCount; segIndex++) { |
| 17494 |
segment = segments[segIndex]; |
| 17495 |
start = segment.start; |
| 17496 |
var end = segment.end; |
| 17497 |
var delta = segment.delta; |
| 17498 |
offsetIndex = segment.offsetIndex; |
| 17499 |
|
| 17500 |
for (j = start; j <= end; j++) { |
| 17501 |
if (j === 0xFFFF) { |
| 17502 |
continue; |
| 17503 |
} |
| 17504 |
|
| 17505 |
glyphId = (offsetIndex < 0 ? |
| 17506 |
j : offsets[offsetIndex + j - start]); |
| 17507 |
glyphId = (glyphId + delta) & 0xFFFF; |
| 17508 |
if (glyphId === 0) { |
| 17509 |
continue; |
| 17510 |
} |
| 17511 |
mappings.push({ |
| 17512 |
charCode: j, |
| 17513 |
glyphId: glyphId |
| 17514 |
}); |
| 17515 |
} |
| 17516 |
} |
| 17517 |
} else if (format === 6) { |
| 17518 |
// Format 6 is a 2-bytes dense mapping, which means the font data |
| 17519 |
// lives glue together even if they are pretty far in the unicode |
| 17520 |
// table. (This looks weird, so I can have missed something), this |
| 17521 |
// works on Linux but seems to fails on Mac so let's rewrite the |
| 17522 |
// cmap table to a 3-1-4 style |
| 17523 |
var firstCode = font.getUint16(); |
| 17524 |
var entryCount = font.getUint16(); |
| 17525 |
|
| 17526 |
for (j = 0; j < entryCount; j++) { |
| 17527 |
glyphId = font.getUint16(); |
| 17528 |
var charCode = firstCode + j; |
| 17529 |
|
| 17530 |
mappings.push({ |
| 17531 |
charCode: charCode, |
| 17532 |
glyphId: glyphId |
| 17533 |
}); |
| 17534 |
} |
| 17535 |
} else { |
| 17536 |
error('cmap table has unsupported format: ' + format); |
| 17537 |
} |
| 17538 |
|
| 17539 |
// removing duplicate entries |
| 17540 |
mappings.sort(function (a, b) { |
| 17541 |
return a.charCode - b.charCode; |
| 17542 |
}); |
| 17543 |
for (i = 1; i < mappings.length; i++) { |
| 17544 |
if (mappings[i - 1].charCode === mappings[i].charCode) { |
| 17545 |
mappings.splice(i, 1); |
| 17546 |
i--; |
| 17547 |
} |
| 17548 |
} |
| 17549 |
|
| 17550 |
return { |
| 17551 |
platformId: potentialTable.platformId, |
| 17552 |
encodingId: potentialTable.encodingId, |
| 17553 |
mappings: mappings, |
| 17554 |
hasShortCmap: hasShortCmap |
| 17555 |
}; |
| 17556 |
} |
| 17557 |
|
| 17558 |
function sanitizeMetrics(font, header, metrics, numGlyphs) { |
| 17559 |
if (!header) { |
| 17560 |
if (metrics) { |
| 17561 |
metrics.data = null; |
| 17562 |
} |
| 17563 |
return; |
| 17564 |
} |
| 17565 |
|
| 17566 |
font.pos = (font.start ? font.start : 0) + header.offset; |
| 17567 |
font.pos += header.length - 2; |
| 17568 |
var numOfMetrics = font.getUint16(); |
| 17569 |
|
| 17570 |
if (numOfMetrics > numGlyphs) { |
| 17571 |
info('The numOfMetrics (' + numOfMetrics + ') should not be ' + |
| 17572 |
'greater than the numGlyphs (' + numGlyphs + ')'); |
| 17573 |
// Reduce numOfMetrics if it is greater than numGlyphs |
| 17574 |
numOfMetrics = numGlyphs; |
| 17575 |
header.data[34] = (numOfMetrics & 0xff00) >> 8; |
| 17576 |
header.data[35] = numOfMetrics & 0x00ff; |
| 17577 |
} |
| 17578 |
|
| 17579 |
var numOfSidebearings = numGlyphs - numOfMetrics; |
| 17580 |
var numMissing = numOfSidebearings - |
| 17581 |
((metrics.length - numOfMetrics * 4) >> 1); |
| 17582 |
|
| 17583 |
if (numMissing > 0) { |
| 17584 |
// For each missing glyph, we set both the width and lsb to 0 (zero). |
| 17585 |
// Since we need to add two properties for each glyph, this explains |
| 17586 |
// the use of |numMissing * 2| when initializing the typed array. |
| 17587 |
var entries = new Uint8Array(metrics.length + numMissing * 2); |
| 17588 |
entries.set(metrics.data); |
| 17589 |
metrics.data = entries; |
| 17590 |
} |
| 17591 |
} |
| 17592 |
|
| 17593 |
function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, |
| 17594 |
hintsValid) { |
| 17595 |
if (sourceEnd - sourceStart <= 12) { |
| 17596 |
// glyph with data less than 12 is invalid one |
| 17597 |
return 0; |
| 17598 |
} |
| 17599 |
var glyf = source.subarray(sourceStart, sourceEnd); |
| 17600 |
var contoursCount = (glyf[0] << 8) | glyf[1]; |
| 17601 |
if (contoursCount & 0x8000) { |
| 17602 |
// complex glyph, writing as is |
| 17603 |
dest.set(glyf, destStart); |
| 17604 |
return glyf.length; |
| 17605 |
} |
| 17606 |
|
| 17607 |
var i, j = 10, flagsCount = 0; |
| 17608 |
for (i = 0; i < contoursCount; i++) { |
| 17609 |
var endPoint = (glyf[j] << 8) | glyf[j + 1]; |
| 17610 |
flagsCount = endPoint + 1; |
| 17611 |
j += 2; |
| 17612 |
} |
| 17613 |
// skipping instructions |
| 17614 |
var instructionsStart = j; |
| 17615 |
var instructionsLength = (glyf[j] << 8) | glyf[j + 1]; |
| 17616 |
j += 2 + instructionsLength; |
| 17617 |
var instructionsEnd = j; |
| 17618 |
// validating flags |
| 17619 |
var coordinatesLength = 0; |
| 17620 |
for (i = 0; i < flagsCount; i++) { |
| 17621 |
var flag = glyf[j++]; |
| 17622 |
if (flag & 0xC0) { |
| 17623 |
// reserved flags must be zero, cleaning up |
| 17624 |
glyf[j - 1] = flag & 0x3F; |
| 17625 |
} |
| 17626 |
var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) + |
| 17627 |
((flag & 4) ? 1 : (flag & 32) ? 0 : 2); |
| 17628 |
coordinatesLength += xyLength; |
| 17629 |
if (flag & 8) { |
| 17630 |
var repeat = glyf[j++]; |
| 17631 |
i += repeat; |
| 17632 |
coordinatesLength += repeat * xyLength; |
| 17633 |
} |
| 17634 |
} |
| 17635 |
// glyph without coordinates will be rejected |
| 17636 |
if (coordinatesLength === 0) { |
| 17637 |
return 0; |
| 17638 |
} |
| 17639 |
var glyphDataLength = j + coordinatesLength; |
| 17640 |
if (glyphDataLength > glyf.length) { |
| 17641 |
// not enough data for coordinates |
| 17642 |
return 0; |
| 17643 |
} |
| 17644 |
if (!hintsValid && instructionsLength > 0) { |
| 17645 |
dest.set(glyf.subarray(0, instructionsStart), destStart); |
| 17646 |
dest.set([0, 0], destStart + instructionsStart); |
| 17647 |
dest.set(glyf.subarray(instructionsEnd, glyphDataLength), |
| 17648 |
destStart + instructionsStart + 2); |
| 17649 |
glyphDataLength -= instructionsLength; |
| 17650 |
if (glyf.length - glyphDataLength > 3) { |
| 17651 |
glyphDataLength = (glyphDataLength + 3) & ~3; |
| 17652 |
} |
| 17653 |
return glyphDataLength; |
| 17654 |
} |
| 17655 |
if (glyf.length - glyphDataLength > 3) { |
| 17656 |
// truncating and aligning to 4 bytes the long glyph data |
| 17657 |
glyphDataLength = (glyphDataLength + 3) & ~3; |
| 17658 |
dest.set(glyf.subarray(0, glyphDataLength), destStart); |
| 17659 |
return glyphDataLength; |
| 17660 |
} |
| 17661 |
// glyph data is fine |
| 17662 |
dest.set(glyf, destStart); |
| 17663 |
return glyf.length; |
| 17664 |
} |
| 17665 |
|
| 17666 |
function sanitizeHead(head, numGlyphs, locaLength) { |
| 17667 |
var data = head.data; |
| 17668 |
|
| 17669 |
// Validate version: |
| 17670 |
// Should always be 0x00010000 |
| 17671 |
var version = int32(data[0], data[1], data[2], data[3]); |
| 17672 |
if (version >> 16 !== 1) { |
| 17673 |
info('Attempting to fix invalid version in head table: ' + version); |
| 17674 |
data[0] = 0; |
| 17675 |
data[1] = 1; |
| 17676 |
data[2] = 0; |
| 17677 |
data[3] = 0; |
| 17678 |
} |
| 17679 |
|
| 17680 |
var indexToLocFormat = int16(data[50], data[51]); |
| 17681 |
if (indexToLocFormat < 0 || indexToLocFormat > 1) { |
| 17682 |
info('Attempting to fix invalid indexToLocFormat in head table: ' + |
| 17683 |
indexToLocFormat); |
| 17684 |
|
| 17685 |
// The value of indexToLocFormat should be 0 if the loca table |
| 17686 |
// consists of short offsets, and should be 1 if the loca table |
| 17687 |
// consists of long offsets. |
| 17688 |
// |
| 17689 |
// The number of entries in the loca table should be numGlyphs + 1. |
| 17690 |
// |
| 17691 |
// Using this information, we can work backwards to deduce if the |
| 17692 |
// size of each offset in the loca table, and thus figure out the |
| 17693 |
// appropriate value for indexToLocFormat. |
| 17694 |
|
| 17695 |
var numGlyphsPlusOne = numGlyphs + 1; |
| 17696 |
if (locaLength === numGlyphsPlusOne << 1) { |
| 17697 |
// 0x0000 indicates the loca table consists of short offsets |
| 17698 |
data[50] = 0; |
| 17699 |
data[51] = 0; |
| 17700 |
} else if (locaLength === numGlyphsPlusOne << 2) { |
| 17701 |
// 0x0001 indicates the loca table consists of long offsets |
| 17702 |
data[50] = 0; |
| 17703 |
data[51] = 1; |
| 17704 |
} else { |
| 17705 |
warn('Could not fix indexToLocFormat: ' + indexToLocFormat); |
| 17706 |
} |
| 17707 |
} |
| 17708 |
} |
| 17709 |
|
| 17710 |
function sanitizeGlyphLocations(loca, glyf, numGlyphs, |
| 17711 |
isGlyphLocationsLong, hintsValid, |
| 17712 |
dupFirstEntry) { |
| 17713 |
var itemSize, itemDecode, itemEncode; |
| 17714 |
if (isGlyphLocationsLong) { |
| 17715 |
itemSize = 4; |
| 17716 |
itemDecode = function fontItemDecodeLong(data, offset) { |
| 17717 |
return (data[offset] << 24) | (data[offset + 1] << 16) | |
| 17718 |
(data[offset + 2] << 8) | data[offset + 3]; |
| 17719 |
}; |
| 17720 |
itemEncode = function fontItemEncodeLong(data, offset, value) { |
| 17721 |
data[offset] = (value >>> 24) & 0xFF; |
| 17722 |
data[offset + 1] = (value >> 16) & 0xFF; |
| 17723 |
data[offset + 2] = (value >> 8) & 0xFF; |
| 17724 |
data[offset + 3] = value & 0xFF; |
| 17725 |
}; |
| 17726 |
} else { |
| 17727 |
itemSize = 2; |
| 17728 |
itemDecode = function fontItemDecode(data, offset) { |
| 17729 |
return (data[offset] << 9) | (data[offset + 1] << 1); |
| 17730 |
}; |
| 17731 |
itemEncode = function fontItemEncode(data, offset, value) { |
| 17732 |
data[offset] = (value >> 9) & 0xFF; |
| 17733 |
data[offset + 1] = (value >> 1) & 0xFF; |
| 17734 |
}; |
| 17735 |
} |
| 17736 |
var locaData = loca.data; |
| 17737 |
var locaDataSize = itemSize * (1 + numGlyphs); |
| 17738 |
// is loca.data too short or long? |
| 17739 |
if (locaData.length !== locaDataSize) { |
| 17740 |
locaData = new Uint8Array(locaDataSize); |
| 17741 |
locaData.set(loca.data.subarray(0, locaDataSize)); |
| 17742 |
loca.data = locaData; |
| 17743 |
} |
| 17744 |
// removing the invalid glyphs |
| 17745 |
var oldGlyfData = glyf.data; |
| 17746 |
var oldGlyfDataLength = oldGlyfData.length; |
| 17747 |
var newGlyfData = new Uint8Array(oldGlyfDataLength); |
| 17748 |
var startOffset = itemDecode(locaData, 0); |
| 17749 |
var writeOffset = 0; |
| 17750 |
var missingGlyphData = {}; |
| 17751 |
itemEncode(locaData, 0, writeOffset); |
| 17752 |
var i, j; |
| 17753 |
for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { |
| 17754 |
var endOffset = itemDecode(locaData, j); |
| 17755 |
if (endOffset > oldGlyfDataLength && |
| 17756 |
((oldGlyfDataLength + 3) & ~3) === endOffset) { |
| 17757 |
// Aspose breaks fonts by aligning the glyphs to the qword, but not |
| 17758 |
// the glyf table size, which makes last glyph out of range. |
| 17759 |
endOffset = oldGlyfDataLength; |
| 17760 |
} |
| 17761 |
if (endOffset > oldGlyfDataLength) { |
| 17762 |
// glyph end offset points outside glyf data, rejecting the glyph |
| 17763 |
itemEncode(locaData, j, writeOffset); |
| 17764 |
startOffset = endOffset; |
| 17765 |
continue; |
| 17766 |
} |
| 17767 |
|
| 17768 |
if (startOffset === endOffset) { |
| 17769 |
missingGlyphData[i] = true; |
| 17770 |
} |
| 17771 |
|
| 17772 |
var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, |
| 17773 |
newGlyfData, writeOffset, hintsValid); |
| 17774 |
writeOffset += newLength; |
| 17775 |
itemEncode(locaData, j, writeOffset); |
| 17776 |
startOffset = endOffset; |
| 17777 |
} |
| 17778 |
|
| 17779 |
if (writeOffset === 0) { |
| 17780 |
// glyf table cannot be empty -- redoing the glyf and loca tables |
| 17781 |
// to have single glyph with one point |
| 17782 |
var simpleGlyph = new Uint8Array( |
| 17783 |
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]); |
| 17784 |
for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { |
| 17785 |
itemEncode(locaData, j, simpleGlyph.length); |
| 17786 |
} |
| 17787 |
glyf.data = simpleGlyph; |
| 17788 |
return missingGlyphData; |
| 17789 |
} |
| 17790 |
|
| 17791 |
if (dupFirstEntry) { |
| 17792 |
var firstEntryLength = itemDecode(locaData, itemSize); |
| 17793 |
if (newGlyfData.length > firstEntryLength + writeOffset) { |
| 17794 |
glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); |
| 17795 |
} else { |
| 17796 |
glyf.data = new Uint8Array(firstEntryLength + writeOffset); |
| 17797 |
glyf.data.set(newGlyfData.subarray(0, writeOffset)); |
| 17798 |
} |
| 17799 |
glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset); |
| 17800 |
itemEncode(loca.data, locaData.length - itemSize, |
| 17801 |
writeOffset + firstEntryLength); |
| 17802 |
} else { |
| 17803 |
glyf.data = newGlyfData.subarray(0, writeOffset); |
| 17804 |
} |
| 17805 |
return missingGlyphData; |
| 17806 |
} |
| 17807 |
|
| 17808 |
function readPostScriptTable(post, properties, maxpNumGlyphs) { |
| 17809 |
var start = (font.start ? font.start : 0) + post.offset; |
| 17810 |
font.pos = start; |
| 17811 |
|
| 17812 |
var length = post.length, end = start + length; |
| 17813 |
var version = font.getInt32(); |
| 17814 |
// skip rest to the tables |
| 17815 |
font.getBytes(28); |
| 17816 |
|
| 17817 |
var glyphNames; |
| 17818 |
var valid = true; |
| 17819 |
var i; |
| 17820 |
|
| 17821 |
switch (version) { |
| 17822 |
case 0x00010000: |
| 17823 |
glyphNames = MacStandardGlyphOrdering; |
| 17824 |
break; |
| 17825 |
case 0x00020000: |
| 17826 |
var numGlyphs = font.getUint16(); |
| 17827 |
if (numGlyphs !== maxpNumGlyphs) { |
| 17828 |
valid = false; |
| 17829 |
break; |
| 17830 |
} |
| 17831 |
var glyphNameIndexes = []; |
| 17832 |
for (i = 0; i < numGlyphs; ++i) { |
| 17833 |
var index = font.getUint16(); |
| 17834 |
if (index >= 32768) { |
| 17835 |
valid = false; |
| 17836 |
break; |
| 17837 |
} |
| 17838 |
glyphNameIndexes.push(index); |
| 17839 |
} |
| 17840 |
if (!valid) { |
| 17841 |
break; |
| 17842 |
} |
| 17843 |
var customNames = []; |
| 17844 |
var strBuf = []; |
| 17845 |
while (font.pos < end) { |
| 17846 |
var stringLength = font.getByte(); |
| 17847 |
strBuf.length = stringLength; |
| 17848 |
for (i = 0; i < stringLength; ++i) { |
| 17849 |
strBuf[i] = String.fromCharCode(font.getByte()); |
| 17850 |
} |
| 17851 |
customNames.push(strBuf.join('')); |
| 17852 |
} |
| 17853 |
glyphNames = []; |
| 17854 |
for (i = 0; i < numGlyphs; ++i) { |
| 17855 |
var j = glyphNameIndexes[i]; |
| 17856 |
if (j < 258) { |
| 17857 |
glyphNames.push(MacStandardGlyphOrdering[j]); |
| 17858 |
continue; |
| 17859 |
} |
| 17860 |
glyphNames.push(customNames[j - 258]); |
| 17861 |
} |
| 17862 |
break; |
| 17863 |
case 0x00030000: |
| 17864 |
break; |
| 17865 |
default: |
| 17866 |
warn('Unknown/unsupported post table version ' + version); |
| 17867 |
valid = false; |
| 17868 |
break; |
| 17869 |
} |
| 17870 |
properties.glyphNames = glyphNames; |
| 17871 |
return valid; |
| 17872 |
} |
| 17873 |
|
| 17874 |
function readNameTable(nameTable) { |
| 17875 |
var start = (font.start ? font.start : 0) + nameTable.offset; |
| 17876 |
font.pos = start; |
| 17877 |
|
| 17878 |
var names = [[], []]; |
| 17879 |
var length = nameTable.length, end = start + length; |
| 17880 |
var format = font.getUint16(); |
| 17881 |
var FORMAT_0_HEADER_LENGTH = 6; |
| 17882 |
if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) { |
| 17883 |
// unsupported name table format or table "too" small |
| 17884 |
return names; |
| 17885 |
} |
| 17886 |
var numRecords = font.getUint16(); |
| 17887 |
var stringsStart = font.getUint16(); |
| 17888 |
var records = []; |
| 17889 |
var NAME_RECORD_LENGTH = 12; |
| 17890 |
var i, ii; |
| 17891 |
|
| 17892 |
for (i = 0; i < numRecords && |
| 17893 |
font.pos + NAME_RECORD_LENGTH <= end; i++) { |
| 17894 |
var r = { |
| 17895 |
platform: font.getUint16(), |
| 17896 |
encoding: font.getUint16(), |
| 17897 |
language: font.getUint16(), |
| 17898 |
name: font.getUint16(), |
| 17899 |
length: font.getUint16(), |
| 17900 |
offset: font.getUint16() |
| 17901 |
}; |
| 17902 |
// using only Macintosh and Windows platform/encoding names |
| 17903 |
if ((r.platform === 1 && r.encoding === 0 && r.language === 0) || |
| 17904 |
(r.platform === 3 && r.encoding === 1 && r.language === 0x409)) { |
| 17905 |
records.push(r); |
| 17906 |
} |
| 17907 |
} |
| 17908 |
for (i = 0, ii = records.length; i < ii; i++) { |
| 17909 |
var record = records[i]; |
| 17910 |
var pos = start + stringsStart + record.offset; |
| 17911 |
if (pos + record.length > end) { |
| 17912 |
continue; // outside of name table, ignoring |
| 17913 |
} |
| 17914 |
font.pos = pos; |
| 17915 |
var nameIndex = record.name; |
| 17916 |
if (record.encoding) { |
| 17917 |
// unicode |
| 17918 |
var str = ''; |
| 17919 |
for (var j = 0, jj = record.length; j < jj; j += 2) { |
| 17920 |
str += String.fromCharCode(font.getUint16()); |
| 17921 |
} |
| 17922 |
names[1][nameIndex] = str; |
| 17923 |
} else { |
| 17924 |
names[0][nameIndex] = bytesToString(font.getBytes(record.length)); |
| 17925 |
} |
| 17926 |
} |
| 17927 |
return names; |
| 17928 |
} |
| 17929 |
|
| 17930 |
var TTOpsStackDeltas = [ |
| 17931 |
0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, |
| 17932 |
-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, |
| 17933 |
1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, |
| 17934 |
0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, |
| 17935 |
0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, |
| 17936 |
-1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, |
| 17937 |
-1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 17938 |
-2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, |
| 17939 |
-999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2]; |
| 17940 |
// 0xC0-DF == -1 and 0xE0-FF == -2 |
| 17941 |
|
| 17942 |
function sanitizeTTProgram(table, ttContext) { |
| 17943 |
var data = table.data; |
| 17944 |
var i = 0, j, n, b, funcId, pc, lastEndf = 0, lastDeff = 0; |
| 17945 |
var stack = []; |
| 17946 |
var callstack = []; |
| 17947 |
var functionsCalled = []; |
| 17948 |
var tooComplexToFollowFunctions = |
| 17949 |
ttContext.tooComplexToFollowFunctions; |
| 17950 |
var inFDEF = false, ifLevel = 0, inELSE = 0; |
| 17951 |
for (var ii = data.length; i < ii;) { |
| 17952 |
var op = data[i++]; |
| 17953 |
// The TrueType instruction set docs can be found at |
| 17954 |
// https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html |
| 17955 |
if (op === 0x40) { // NPUSHB - pushes n bytes |
| 17956 |
n = data[i++]; |
| 17957 |
if (inFDEF || inELSE) { |
| 17958 |
i += n; |
| 17959 |
} else { |
| 17960 |
for (j = 0; j < n; j++) { |
| 17961 |
stack.push(data[i++]); |
| 17962 |
} |
| 17963 |
} |
| 17964 |
} else if (op === 0x41) { // NPUSHW - pushes n words |
| 17965 |
n = data[i++]; |
| 17966 |
if (inFDEF || inELSE) { |
| 17967 |
i += n * 2; |
| 17968 |
} else { |
| 17969 |
for (j = 0; j < n; j++) { |
| 17970 |
b = data[i++]; |
| 17971 |
stack.push((b << 8) | data[i++]); |
| 17972 |
} |
| 17973 |
} |
| 17974 |
} else if ((op & 0xF8) === 0xB0) { // PUSHB - pushes bytes |
| 17975 |
n = op - 0xB0 + 1; |
| 17976 |
if (inFDEF || inELSE) { |
| 17977 |
i += n; |
| 17978 |
} else { |
| 17979 |
for (j = 0; j < n; j++) { |
| 17980 |
stack.push(data[i++]); |
| 17981 |
} |
| 17982 |
} |
| 17983 |
} else if ((op & 0xF8) === 0xB8) { // PUSHW - pushes words |
| 17984 |
n = op - 0xB8 + 1; |
| 17985 |
if (inFDEF || inELSE) { |
| 17986 |
i += n * 2; |
| 17987 |
} else { |
| 17988 |
for (j = 0; j < n; j++) { |
| 17989 |
b = data[i++]; |
| 17990 |
stack.push((b << 8) | data[i++]); |
| 17991 |
} |
| 17992 |
} |
| 17993 |
} else if (op === 0x2B && !tooComplexToFollowFunctions) { // CALL |
| 17994 |
if (!inFDEF && !inELSE) { |
| 17995 |
// collecting inforamtion about which functions are used |
| 17996 |
funcId = stack[stack.length - 1]; |
| 17997 |
ttContext.functionsUsed[funcId] = true; |
| 17998 |
if (funcId in ttContext.functionsStackDeltas) { |
| 17999 |
stack.length += ttContext.functionsStackDeltas[funcId]; |
| 18000 |
} else if (funcId in ttContext.functionsDefined && |
| 18001 |
functionsCalled.indexOf(funcId) < 0) { |
| 18002 |
callstack.push({data: data, i: i, stackTop: stack.length - 1}); |
| 18003 |
functionsCalled.push(funcId); |
| 18004 |
pc = ttContext.functionsDefined[funcId]; |
| 18005 |
if (!pc) { |
| 18006 |
warn('TT: CALL non-existent function'); |
| 18007 |
ttContext.hintsValid = false; |
| 18008 |
return; |
| 18009 |
} |
| 18010 |
data = pc.data; |
| 18011 |
i = pc.i; |
| 18012 |
} |
| 18013 |
} |
| 18014 |
} else if (op === 0x2C && !tooComplexToFollowFunctions) { // FDEF |
| 18015 |
if (inFDEF || inELSE) { |
| 18016 |
warn('TT: nested FDEFs not allowed'); |
| 18017 |
tooComplexToFollowFunctions = true; |
| 18018 |
} |
| 18019 |
inFDEF = true; |
| 18020 |
// collecting inforamtion about which functions are defined |
| 18021 |
lastDeff = i; |
| 18022 |
funcId = stack.pop(); |
| 18023 |
ttContext.functionsDefined[funcId] = {data: data, i: i}; |
| 18024 |
} else if (op === 0x2D) { // ENDF - end of function |
| 18025 |
if (inFDEF) { |
| 18026 |
inFDEF = false; |
| 18027 |
lastEndf = i; |
| 18028 |
} else { |
| 18029 |
pc = callstack.pop(); |
| 18030 |
if (!pc) { |
| 18031 |
warn('TT: ENDF bad stack'); |
| 18032 |
ttContext.hintsValid = false; |
| 18033 |
return; |
| 18034 |
} |
| 18035 |
funcId = functionsCalled.pop(); |
| 18036 |
data = pc.data; |
| 18037 |
i = pc.i; |
| 18038 |
ttContext.functionsStackDeltas[funcId] = |
| 18039 |
stack.length - pc.stackTop; |
| 18040 |
} |
| 18041 |
} else if (op === 0x89) { // IDEF - instruction definition |
| 18042 |
if (inFDEF || inELSE) { |
| 18043 |
warn('TT: nested IDEFs not allowed'); |
| 18044 |
tooComplexToFollowFunctions = true; |
| 18045 |
} |
| 18046 |
inFDEF = true; |
| 18047 |
// recording it as a function to track ENDF |
| 18048 |
lastDeff = i; |
| 18049 |
} else if (op === 0x58) { // IF |
| 18050 |
++ifLevel; |
| 18051 |
} else if (op === 0x1B) { // ELSE |
| 18052 |
inELSE = ifLevel; |
| 18053 |
} else if (op === 0x59) { // EIF |
| 18054 |
if (inELSE === ifLevel) { |
| 18055 |
inELSE = 0; |
| 18056 |
} |
| 18057 |
--ifLevel; |
| 18058 |
} else if (op === 0x1C) { // JMPR |
| 18059 |
if (!inFDEF && !inELSE) { |
| 18060 |
var offset = stack[stack.length - 1]; |
| 18061 |
// only jumping forward to prevent infinite loop |
| 18062 |
if (offset > 0) { |
| 18063 |
i += offset - 1; |
| 18064 |
} |
| 18065 |
} |
| 18066 |
} |
| 18067 |
// Adjusting stack not extactly, but just enough to get function id |
| 18068 |
if (!inFDEF && !inELSE) { |
| 18069 |
var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : |
| 18070 |
op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0; |
| 18071 |
if (op >= 0x71 && op <= 0x75) { |
| 18072 |
n = stack.pop(); |
| 18073 |
if (n === n) { |
| 18074 |
stackDelta = -n * 2; |
| 18075 |
} |
| 18076 |
} |
| 18077 |
while (stackDelta < 0 && stack.length > 0) { |
| 18078 |
stack.pop(); |
| 18079 |
stackDelta++; |
| 18080 |
} |
| 18081 |
while (stackDelta > 0) { |
| 18082 |
stack.push(NaN); // pushing any number into stack |
| 18083 |
stackDelta--; |
| 18084 |
} |
| 18085 |
} |
| 18086 |
} |
| 18087 |
ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions; |
| 18088 |
var content = [data]; |
| 18089 |
if (i > data.length) { |
| 18090 |
content.push(new Uint8Array(i - data.length)); |
| 18091 |
} |
| 18092 |
if (lastDeff > lastEndf) { |
| 18093 |
warn('TT: complementing a missing function tail'); |
| 18094 |
// new function definition started, but not finished |
| 18095 |
// complete function by [CLEAR, ENDF] |
| 18096 |
content.push(new Uint8Array([0x22, 0x2D])); |
| 18097 |
} |
| 18098 |
foldTTTable(table, content); |
| 18099 |
} |
| 18100 |
|
| 18101 |
function checkInvalidFunctions(ttContext, maxFunctionDefs) { |
| 18102 |
if (ttContext.tooComplexToFollowFunctions) { |
| 18103 |
return; |
| 18104 |
} |
| 18105 |
if (ttContext.functionsDefined.length > maxFunctionDefs) { |
| 18106 |
warn('TT: more functions defined than expected'); |
| 18107 |
ttContext.hintsValid = false; |
| 18108 |
return; |
| 18109 |
} |
| 18110 |
for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) { |
| 18111 |
if (j > maxFunctionDefs) { |
| 18112 |
warn('TT: invalid function id: ' + j); |
| 18113 |
ttContext.hintsValid = false; |
| 18114 |
return; |
| 18115 |
} |
| 18116 |
if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) { |
| 18117 |
warn('TT: undefined function: ' + j); |
| 18118 |
ttContext.hintsValid = false; |
| 18119 |
return; |
| 18120 |
} |
| 18121 |
} |
| 18122 |
} |
| 18123 |
|
| 18124 |
function foldTTTable(table, content) { |
| 18125 |
if (content.length > 1) { |
| 18126 |
// concatenating the content items |
| 18127 |
var newLength = 0; |
| 18128 |
var j, jj; |
| 18129 |
for (j = 0, jj = content.length; j < jj; j++) { |
| 18130 |
newLength += content[j].length; |
| 18131 |
} |
| 18132 |
newLength = (newLength + 3) & ~3; |
| 18133 |
var result = new Uint8Array(newLength); |
| 18134 |
var pos = 0; |
| 18135 |
for (j = 0, jj = content.length; j < jj; j++) { |
| 18136 |
result.set(content[j], pos); |
| 18137 |
pos += content[j].length; |
| 18138 |
} |
| 18139 |
table.data = result; |
| 18140 |
table.length = newLength; |
| 18141 |
} |
| 18142 |
} |
| 18143 |
|
| 18144 |
function sanitizeTTPrograms(fpgm, prep, cvt) { |
| 18145 |
var ttContext = { |
| 18146 |
functionsDefined: [], |
| 18147 |
functionsUsed: [], |
| 18148 |
functionsStackDeltas: [], |
| 18149 |
tooComplexToFollowFunctions: false, |
| 18150 |
hintsValid: true |
| 18151 |
}; |
| 18152 |
if (fpgm) { |
| 18153 |
sanitizeTTProgram(fpgm, ttContext); |
| 18154 |
} |
| 18155 |
if (prep) { |
| 18156 |
sanitizeTTProgram(prep, ttContext); |
| 18157 |
} |
| 18158 |
if (fpgm) { |
| 18159 |
checkInvalidFunctions(ttContext, maxFunctionDefs); |
| 18160 |
} |
| 18161 |
if (cvt && (cvt.length & 1)) { |
| 18162 |
var cvtData = new Uint8Array(cvt.length + 1); |
| 18163 |
cvtData.set(cvt.data); |
| 18164 |
cvt.data = cvtData; |
| 18165 |
} |
| 18166 |
return ttContext.hintsValid; |
| 18167 |
} |
| 18168 |
|
| 18169 |
// The following steps modify the original font data, making copy |
| 18170 |
font = new Stream(new Uint8Array(font.getBytes())); |
| 18171 |
|
| 18172 |
var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp', |
| 18173 |
'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF ']; |
| 18174 |
|
| 18175 |
var header = readOpenTypeHeader(font); |
| 18176 |
var numTables = header.numTables; |
| 18177 |
var cff, cffFile; |
| 18178 |
|
| 18179 |
var tables = { 'OS/2': null, cmap: null, head: null, hhea: null, |
| 18180 |
hmtx: null, maxp: null, name: null, post: null }; |
| 18181 |
var table; |
| 18182 |
for (var i = 0; i < numTables; i++) { |
| 18183 |
table = readTableEntry(font); |
| 18184 |
if (VALID_TABLES.indexOf(table.tag) < 0) { |
| 18185 |
continue; // skipping table if it's not a required or optional table |
| 18186 |
} |
| 18187 |
if (table.length === 0) { |
| 18188 |
continue; // skipping empty tables |
| 18189 |
} |
| 18190 |
tables[table.tag] = table; |
| 18191 |
} |
| 18192 |
|
| 18193 |
var isTrueType = !tables['CFF ']; |
| 18194 |
if (!isTrueType) { |
| 18195 |
// OpenType font |
| 18196 |
if (header.version === 'OTTO' || |
| 18197 |
!tables.head || !tables.hhea || !tables.maxp || !tables.post) { |
| 18198 |
// no major tables: throwing everything at CFFFont |
| 18199 |
cffFile = new Stream(tables['CFF '].data); |
| 18200 |
cff = new CFFFont(cffFile, properties); |
| 18201 |
|
| 18202 |
return this.convert(name, cff, properties); |
| 18203 |
} |
| 18204 |
|
| 18205 |
delete tables.glyf; |
| 18206 |
delete tables.loca; |
| 18207 |
delete tables.fpgm; |
| 18208 |
delete tables.prep; |
| 18209 |
delete tables['cvt ']; |
| 18210 |
this.isOpenType = true; |
| 18211 |
} else { |
| 18212 |
if (!tables.glyf || !tables.loca) { |
| 18213 |
error('Required "glyf" or "loca" tables are not found'); |
| 18214 |
} |
| 18215 |
this.isOpenType = false; |
| 18216 |
} |
| 18217 |
|
| 18218 |
if (!tables.maxp) { |
| 18219 |
error('Required "maxp" table is not found'); |
| 18220 |
} |
| 18221 |
|
| 18222 |
font.pos = (font.start || 0) + tables.maxp.offset; |
| 18223 |
var version = font.getInt32(); |
| 18224 |
var numGlyphs = font.getUint16(); |
| 18225 |
var maxFunctionDefs = 0; |
| 18226 |
if (version >= 0x00010000 && tables.maxp.length >= 22) { |
| 18227 |
// maxZones can be invalid |
| 18228 |
font.pos += 8; |
| 18229 |
var maxZones = font.getUint16(); |
| 18230 |
if (maxZones > 2) { // reset to 2 if font has invalid maxZones |
| 18231 |
tables.maxp.data[14] = 0; |
| 18232 |
tables.maxp.data[15] = 2; |
| 18233 |
} |
| 18234 |
font.pos += 4; |
| 18235 |
maxFunctionDefs = font.getUint16(); |
| 18236 |
} |
| 18237 |
|
| 18238 |
var dupFirstEntry = false; |
| 18239 |
if (properties.type === 'CIDFontType2' && properties.toUnicode && |
| 18240 |
properties.toUnicode.get(0) > '\u0000') { |
| 18241 |
// oracle's defect (see 3427), duplicating first entry |
| 18242 |
dupFirstEntry = true; |
| 18243 |
numGlyphs++; |
| 18244 |
tables.maxp.data[4] = numGlyphs >> 8; |
| 18245 |
tables.maxp.data[5] = numGlyphs & 255; |
| 18246 |
} |
| 18247 |
|
| 18248 |
var hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, |
| 18249 |
tables['cvt '], maxFunctionDefs); |
| 18250 |
if (!hintsValid) { |
| 18251 |
delete tables.fpgm; |
| 18252 |
delete tables.prep; |
| 18253 |
delete tables['cvt ']; |
| 18254 |
} |
| 18255 |
|
| 18256 |
// Ensure the hmtx table contains the advance width and |
| 18257 |
// sidebearings information for numGlyphs in the maxp table |
| 18258 |
sanitizeMetrics(font, tables.hhea, tables.hmtx, numGlyphs); |
| 18259 |
|
| 18260 |
if (!tables.head) { |
| 18261 |
error('Required "head" table is not found'); |
| 18262 |
} |
| 18263 |
|
| 18264 |
sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); |
| 18265 |
|
| 18266 |
var missingGlyphs = {}; |
| 18267 |
if (isTrueType) { |
| 18268 |
var isGlyphLocationsLong = int16(tables.head.data[50], |
| 18269 |
tables.head.data[51]); |
| 18270 |
missingGlyphs = sanitizeGlyphLocations(tables.loca, tables.glyf, |
| 18271 |
numGlyphs, isGlyphLocationsLong, |
| 18272 |
hintsValid, dupFirstEntry); |
| 18273 |
} |
| 18274 |
|
| 18275 |
if (!tables.hhea) { |
| 18276 |
error('Required "hhea" table is not found'); |
| 18277 |
} |
| 18278 |
|
| 18279 |
// Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth |
| 18280 |
// Sometimes it's 0. That needs to be fixed |
| 18281 |
if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) { |
| 18282 |
tables.hhea.data[10] = 0xFF; |
| 18283 |
tables.hhea.data[11] = 0xFF; |
| 18284 |
} |
| 18285 |
|
| 18286 |
// The 'post' table has glyphs names. |
| 18287 |
if (tables.post) { |
| 18288 |
var valid = readPostScriptTable(tables.post, properties, numGlyphs); |
| 18289 |
if (!valid) { |
| 18290 |
tables.post = null; |
| 18291 |
} |
| 18292 |
} |
| 18293 |
|
| 18294 |
var charCodeToGlyphId = [], charCode, toUnicode = properties.toUnicode; |
| 18295 |
|
| 18296 |
function hasGlyph(glyphId, charCode) { |
| 18297 |
if (!missingGlyphs[glyphId]) { |
| 18298 |
return true; |
| 18299 |
} |
| 18300 |
if (charCode >= 0 && toUnicode.has(charCode)) { |
| 18301 |
return true; |
| 18302 |
} |
| 18303 |
return false; |
| 18304 |
} |
| 18305 |
|
| 18306 |
if (properties.type === 'CIDFontType2') { |
| 18307 |
var cidToGidMap = properties.cidToGidMap || []; |
| 18308 |
var isCidToGidMapEmpty = cidToGidMap.length === 0; |
| 18309 |
|
| 18310 |
properties.cMap.forEach(function(charCode, cid) { |
| 18311 |
assert(cid <= 0xffff, 'Max size of CID is 65,535'); |
| 18312 |
var glyphId = -1; |
| 18313 |
if (isCidToGidMapEmpty) { |
| 18314 |
glyphId = charCode; |
| 18315 |
} else if (cidToGidMap[cid] !== undefined) { |
| 18316 |
glyphId = cidToGidMap[cid]; |
| 18317 |
} |
| 18318 |
|
| 18319 |
if (glyphId >= 0 && glyphId < numGlyphs && |
| 18320 |
hasGlyph(glyphId, charCode)) { |
| 18321 |
charCodeToGlyphId[charCode] = glyphId; |
| 18322 |
} |
| 18323 |
}); |
| 18324 |
if (dupFirstEntry) { |
| 18325 |
charCodeToGlyphId[0] = numGlyphs - 1; |
| 18326 |
} |
| 18327 |
} else { |
| 18328 |
// Most of the following logic in this code branch is based on the |
| 18329 |
// 9.6.6.4 of the PDF spec. |
| 18330 |
var cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont); |
| 18331 |
var cmapPlatformId = cmapTable.platformId; |
| 18332 |
var cmapEncodingId = cmapTable.encodingId; |
| 18333 |
var cmapMappings = cmapTable.mappings; |
| 18334 |
var cmapMappingsLength = cmapMappings.length; |
| 18335 |
var hasEncoding = properties.differences.length || |
| 18336 |
!!properties.baseEncodingName; |
| 18337 |
|
| 18338 |
// The spec seems to imply that if the font is symbolic the encoding |
| 18339 |
// should be ignored, this doesn't appear to work for 'preistabelle.pdf' |
| 18340 |
// where the the font is symbolic and it has an encoding. |
| 18341 |
if (hasEncoding && |
| 18342 |
(cmapPlatformId === 3 && cmapEncodingId === 1 || |
| 18343 |
cmapPlatformId === 1 && cmapEncodingId === 0) || |
| 18344 |
(cmapPlatformId === -1 && cmapEncodingId === -1 && // Temporary hack |
| 18345 |
!!Encodings[properties.baseEncodingName])) { // Temporary hack |
| 18346 |
// When no preferred cmap table was found and |baseEncodingName| is |
| 18347 |
// one of the predefined encodings, we seem to obtain a better |
| 18348 |
// |charCodeToGlyphId| map from the code below (fixes bug 1057544). |
| 18349 |
// TODO: Note that this is a hack which should be removed as soon as |
| 18350 |
// we have proper support for more exotic cmap tables. |
| 18351 |
|
| 18352 |
var baseEncoding = []; |
| 18353 |
if (properties.baseEncodingName === 'MacRomanEncoding' || |
| 18354 |
properties.baseEncodingName === 'WinAnsiEncoding') { |
| 18355 |
baseEncoding = Encodings[properties.baseEncodingName]; |
| 18356 |
} |
| 18357 |
for (charCode = 0; charCode < 256; charCode++) { |
| 18358 |
var glyphName; |
| 18359 |
if (this.differences && charCode in this.differences) { |
| 18360 |
glyphName = this.differences[charCode]; |
| 18361 |
} else if (charCode in baseEncoding && |
| 18362 |
baseEncoding[charCode] !== '') { |
| 18363 |
glyphName = baseEncoding[charCode]; |
| 18364 |
} else { |
| 18365 |
glyphName = Encodings.StandardEncoding[charCode]; |
| 18366 |
} |
| 18367 |
if (!glyphName) { |
| 18368 |
continue; |
| 18369 |
} |
| 18370 |
var unicodeOrCharCode; |
| 18371 |
if (cmapPlatformId === 3 && cmapEncodingId === 1) { |
| 18372 |
unicodeOrCharCode = GlyphsUnicode[glyphName]; |
| 18373 |
} else if (cmapPlatformId === 1 && cmapEncodingId === 0) { |
| 18374 |
// TODO: the encoding needs to be updated with mac os table. |
| 18375 |
unicodeOrCharCode = Encodings.MacRomanEncoding.indexOf(glyphName); |
| 18376 |
} |
| 18377 |
|
| 18378 |
var found = false; |
| 18379 |
for (i = 0; i < cmapMappingsLength; ++i) { |
| 18380 |
if (cmapMappings[i].charCode === unicodeOrCharCode && |
| 18381 |
hasGlyph(cmapMappings[i].glyphId, unicodeOrCharCode)) { |
| 18382 |
charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; |
| 18383 |
found = true; |
| 18384 |
break; |
| 18385 |
} |
| 18386 |
} |
| 18387 |
if (!found && properties.glyphNames) { |
| 18388 |
// Try to map using the post table. There are currently no known |
| 18389 |
// pdfs that this fixes. |
| 18390 |
var glyphId = properties.glyphNames.indexOf(glyphName); |
| 18391 |
if (glyphId > 0 && hasGlyph(glyphId, -1)) { |
| 18392 |
charCodeToGlyphId[charCode] = glyphId; |
| 18393 |
} |
| 18394 |
} |
| 18395 |
} |
| 18396 |
} else if (cmapPlatformId === 0 && cmapEncodingId === 0) { |
| 18397 |
// Default Unicode semantics, use the charcodes as is. |
| 18398 |
for (i = 0; i < cmapMappingsLength; ++i) { |
| 18399 |
charCodeToGlyphId[cmapMappings[i].charCode] = |
| 18400 |
cmapMappings[i].glyphId; |
| 18401 |
} |
| 18402 |
} else { |
| 18403 |
// For (3, 0) cmap tables: |
| 18404 |
// The charcode key being stored in charCodeToGlyphId is the lower |
| 18405 |
// byte of the two-byte charcodes of the cmap table since according to |
| 18406 |
// the spec: 'each byte from the string shall be prepended with the |
| 18407 |
// high byte of the range [of charcodes in the cmap table], to form |
| 18408 |
// a two-byte character, which shall be used to select the |
| 18409 |
// associated glyph description from the subtable'. |
| 18410 |
// |
| 18411 |
// For (1, 0) cmap tables: |
| 18412 |
// 'single bytes from the string shall be used to look up the |
| 18413 |
// associated glyph descriptions from the subtable'. This means |
| 18414 |
// charcodes in the cmap will be single bytes, so no-op since |
| 18415 |
// glyph.charCode & 0xFF === glyph.charCode |
| 18416 |
for (i = 0; i < cmapMappingsLength; ++i) { |
| 18417 |
charCode = cmapMappings[i].charCode & 0xFF; |
| 18418 |
charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; |
| 18419 |
} |
| 18420 |
} |
| 18421 |
} |
| 18422 |
|
| 18423 |
if (charCodeToGlyphId.length === 0) { |
| 18424 |
// defines at least one glyph |
| 18425 |
charCodeToGlyphId[0] = 0; |
| 18426 |
} |
| 18427 |
|
| 18428 |
// Converting glyphs and ids into font's cmap table |
| 18429 |
var newMapping = adjustMapping(charCodeToGlyphId, properties); |
| 18430 |
this.toFontChar = newMapping.toFontChar; |
| 18431 |
tables.cmap = { |
| 18432 |
tag: 'cmap', |
| 18433 |
data: createCmapTable(newMapping.charCodeToGlyphId) |
| 18434 |
}; |
| 18435 |
|
| 18436 |
if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) { |
| 18437 |
// extract some more font properties from the OpenType head and |
| 18438 |
// hhea tables; yMin and descent value are always negative |
| 18439 |
var override = { |
| 18440 |
unitsPerEm: int16(tables.head.data[18], tables.head.data[19]), |
| 18441 |
yMax: int16(tables.head.data[42], tables.head.data[43]), |
| 18442 |
yMin: int16(tables.head.data[38], tables.head.data[39]) - 0x10000, |
| 18443 |
ascent: int16(tables.hhea.data[4], tables.hhea.data[5]), |
| 18444 |
descent: int16(tables.hhea.data[6], tables.hhea.data[7]) - 0x10000 |
| 18445 |
}; |
| 18446 |
|
| 18447 |
tables['OS/2'] = { |
| 18448 |
tag: 'OS/2', |
| 18449 |
data: createOS2Table(properties, newMapping.charCodeToGlyphId, |
| 18450 |
override) |
| 18451 |
}; |
| 18452 |
} |
| 18453 |
|
| 18454 |
// Rewrite the 'post' table if needed |
| 18455 |
if (!tables.post) { |
| 18456 |
tables.post = { |
| 18457 |
tag: 'post', |
| 18458 |
data: createPostTable(properties) |
| 18459 |
}; |
| 18460 |
} |
| 18461 |
|
| 18462 |
if (!isTrueType) { |
| 18463 |
try { |
| 18464 |
// Trying to repair CFF file |
| 18465 |
cffFile = new Stream(tables['CFF '].data); |
| 18466 |
var parser = new CFFParser(cffFile, properties); |
| 18467 |
cff = parser.parse(); |
| 18468 |
var compiler = new CFFCompiler(cff); |
| 18469 |
tables['CFF '].data = compiler.compile(); |
| 18470 |
} catch (e) { |
| 18471 |
warn('Failed to compile font ' + properties.loadedName); |
| 18472 |
} |
| 18473 |
} |
| 18474 |
|
| 18475 |
// Re-creating 'name' table |
| 18476 |
if (!tables.name) { |
| 18477 |
tables.name = { |
| 18478 |
tag: 'name', |
| 18479 |
data: createNameTable(this.name) |
| 18480 |
}; |
| 18481 |
} else { |
| 18482 |
// ... using existing 'name' table as prototype |
| 18483 |
var namePrototype = readNameTable(tables.name); |
| 18484 |
tables.name.data = createNameTable(name, namePrototype); |
| 18485 |
} |
| 18486 |
|
| 18487 |
var builder = new OpenTypeFileBuilder(header.version); |
| 18488 |
for (var tableTag in tables) { |
| 18489 |
builder.addTable(tableTag, tables[tableTag].data); |
| 18490 |
} |
| 18491 |
return builder.toArray(); |
| 18492 |
}, |
| 18493 |
|
| 18494 |
convert: function Font_convert(fontName, font, properties) { |
| 18495 |
// TODO: Check the charstring widths to determine this. |
| 18496 |
properties.fixedPitch = false; |
| 18497 |
|
| 18498 |
var mapping = font.getGlyphMapping(properties); |
| 18499 |
var newMapping = adjustMapping(mapping, properties); |
| 18500 |
this.toFontChar = newMapping.toFontChar; |
| 18501 |
var numGlyphs = font.numGlyphs; |
| 18502 |
|
| 18503 |
function getCharCodes(charCodeToGlyphId, glyphId) { |
| 18504 |
var charCodes = null; |
| 18505 |
for (var charCode in charCodeToGlyphId) { |
| 18506 |
if (glyphId === charCodeToGlyphId[charCode]) { |
| 18507 |
if (!charCodes) { |
| 18508 |
charCodes = []; |
| 18509 |
} |
| 18510 |
charCodes.push(charCode | 0); |
| 18511 |
} |
| 18512 |
} |
| 18513 |
return charCodes; |
| 18514 |
} |
| 18515 |
|
| 18516 |
function createCharCode(charCodeToGlyphId, glyphId) { |
| 18517 |
for (var charCode in charCodeToGlyphId) { |
| 18518 |
if (glyphId === charCodeToGlyphId[charCode]) { |
| 18519 |
return charCode | 0; |
| 18520 |
} |
| 18521 |
} |
| 18522 |
newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = |
| 18523 |
glyphId; |
| 18524 |
return newMapping.nextAvailableFontCharCode++; |
| 18525 |
} |
| 18526 |
|
| 18527 |
var seacs = font.seacs; |
| 18528 |
if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) { |
| 18529 |
var matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX; |
| 18530 |
var charset = font.getCharset(); |
| 18531 |
var seacMap = Object.create(null); |
| 18532 |
for (var glyphId in seacs) { |
| 18533 |
glyphId |= 0; |
| 18534 |
var seac = seacs[glyphId]; |
| 18535 |
var baseGlyphName = Encodings.StandardEncoding[seac[2]]; |
| 18536 |
var accentGlyphName = Encodings.StandardEncoding[seac[3]]; |
| 18537 |
var baseGlyphId = charset.indexOf(baseGlyphName); |
| 18538 |
var accentGlyphId = charset.indexOf(accentGlyphName); |
| 18539 |
if (baseGlyphId < 0 || accentGlyphId < 0) { |
| 18540 |
continue; |
| 18541 |
} |
| 18542 |
var accentOffset = { |
| 18543 |
x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4], |
| 18544 |
y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5] |
| 18545 |
}; |
| 18546 |
|
| 18547 |
var charCodes = getCharCodes(mapping, glyphId); |
| 18548 |
if (!charCodes) { |
| 18549 |
// There's no point in mapping it if the char code was never mapped |
| 18550 |
// to begin with. |
| 18551 |
continue; |
| 18552 |
} |
| 18553 |
for (var i = 0, ii = charCodes.length; i < ii; i++) { |
| 18554 |
var charCode = charCodes[i]; |
| 18555 |
// Find a fontCharCode that maps to the base and accent glyphs. |
| 18556 |
// If one doesn't exists, create it. |
| 18557 |
var charCodeToGlyphId = newMapping.charCodeToGlyphId; |
| 18558 |
var baseFontCharCode = createCharCode(charCodeToGlyphId, |
| 18559 |
baseGlyphId); |
| 18560 |
var accentFontCharCode = createCharCode(charCodeToGlyphId, |
| 18561 |
accentGlyphId); |
| 18562 |
seacMap[charCode] = { |
| 18563 |
baseFontCharCode: baseFontCharCode, |
| 18564 |
accentFontCharCode: accentFontCharCode, |
| 18565 |
accentOffset: accentOffset |
| 18566 |
}; |
| 18567 |
} |
| 18568 |
} |
| 18569 |
properties.seacMap = seacMap; |
| 18570 |
} |
| 18571 |
|
| 18572 |
var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]; |
| 18573 |
|
| 18574 |
var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F'); |
| 18575 |
// PostScript Font Program |
| 18576 |
builder.addTable('CFF ', font.data); |
| 18577 |
// OS/2 and Windows Specific metrics |
| 18578 |
builder.addTable('OS/2', createOS2Table(properties, |
| 18579 |
newMapping.charCodeToGlyphId)); |
| 18580 |
// Character to glyphs mapping |
| 18581 |
builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId)); |
| 18582 |
// Font header |
| 18583 |
builder.addTable('head', |
| 18584 |
'\x00\x01\x00\x00' + // Version number |
| 18585 |
'\x00\x00\x10\x00' + // fontRevision |
| 18586 |
'\x00\x00\x00\x00' + // checksumAdjustement |
| 18587 |
'\x5F\x0F\x3C\xF5' + // magicNumber |
| 18588 |
'\x00\x00' + // Flags |
| 18589 |
safeString16(unitsPerEm) + // unitsPerEM |
| 18590 |
'\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date |
| 18591 |
'\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date |
| 18592 |
'\x00\x00' + // xMin |
| 18593 |
safeString16(properties.descent) + // yMin |
| 18594 |
'\x0F\xFF' + // xMax |
| 18595 |
safeString16(properties.ascent) + // yMax |
| 18596 |
string16(properties.italicAngle ? 2 : 0) + // macStyle |
| 18597 |
'\x00\x11' + // lowestRecPPEM |
| 18598 |
'\x00\x00' + // fontDirectionHint |
| 18599 |
'\x00\x00' + // indexToLocFormat |
| 18600 |
'\x00\x00'); // glyphDataFormat |
| 18601 |
|
| 18602 |
// Horizontal header |
| 18603 |
builder.addTable('hhea', |
| 18604 |
'\x00\x01\x00\x00' + // Version number |
| 18605 |
safeString16(properties.ascent) + // Typographic Ascent |
| 18606 |
safeString16(properties.descent) + // Typographic Descent |
| 18607 |
'\x00\x00' + // Line Gap |
| 18608 |
'\xFF\xFF' + // advanceWidthMax |
| 18609 |
'\x00\x00' + // minLeftSidebearing |
| 18610 |
'\x00\x00' + // minRightSidebearing |
| 18611 |
'\x00\x00' + // xMaxExtent |
| 18612 |
safeString16(properties.capHeight) + // caretSlopeRise |
| 18613 |
safeString16(Math.tan(properties.italicAngle) * |
| 18614 |
properties.xHeight) + // caretSlopeRun |
| 18615 |
'\x00\x00' + // caretOffset |
| 18616 |
'\x00\x00' + // -reserved- |
| 18617 |
'\x00\x00' + // -reserved- |
| 18618 |
'\x00\x00' + // -reserved- |
| 18619 |
'\x00\x00' + // -reserved- |
| 18620 |
'\x00\x00' + // metricDataFormat |
| 18621 |
string16(numGlyphs)); // Number of HMetrics |
| 18622 |
|
| 18623 |
// Horizontal metrics |
| 18624 |
builder.addTable('hmtx', (function fontFieldsHmtx() { |
| 18625 |
var charstrings = font.charstrings; |
| 18626 |
var cffWidths = font.cff ? font.cff.widths : null; |
| 18627 |
var hmtx = '\x00\x00\x00\x00'; // Fake .notdef |
| 18628 |
for (var i = 1, ii = numGlyphs; i < ii; i++) { |
| 18629 |
var width = 0; |
| 18630 |
if (charstrings) { |
| 18631 |
var charstring = charstrings[i - 1]; |
| 18632 |
width = 'width' in charstring ? charstring.width : 0; |
| 18633 |
} else if (cffWidths) { |
| 18634 |
width = Math.ceil(cffWidths[i] || 0); |
| 18635 |
} |
| 18636 |
hmtx += string16(width) + string16(0); |
| 18637 |
} |
| 18638 |
return hmtx; |
| 18639 |
})()); |
| 18640 |
|
| 18641 |
// Maximum profile |
| 18642 |
builder.addTable('maxp', |
| 18643 |
'\x00\x00\x50\x00' + // Version number |
| 18644 |
string16(numGlyphs)); // Num of glyphs |
| 18645 |
|
| 18646 |
// Naming tables |
| 18647 |
builder.addTable('name', createNameTable(fontName)); |
| 18648 |
|
| 18649 |
// PostScript informations |
| 18650 |
builder.addTable('post', createPostTable(properties)); |
| 18651 |
|
| 18652 |
return builder.toArray(); |
| 18653 |
}, |
| 18654 |
|
| 18655 |
/** |
| 18656 |
* Builds a char code to unicode map based on section 9.10 of the spec. |
| 18657 |
* @param {Object} properties Font properties object. |
| 18658 |
* @return {Object} A ToUnicodeMap object. |
| 18659 |
*/ |
| 18660 |
buildToUnicode: function Font_buildToUnicode(properties) { |
| 18661 |
// Section 9.10.2 Mapping Character Codes to Unicode Values |
| 18662 |
if (properties.toUnicode && properties.toUnicode.length !== 0) { |
| 18663 |
return properties.toUnicode; |
| 18664 |
} |
| 18665 |
// According to the spec if the font is a simple font we should only map |
| 18666 |
// to unicode if the base encoding is MacRoman, MacExpert, or WinAnsi or |
| 18667 |
// the differences array only contains adobe standard or symbol set names, |
| 18668 |
// in pratice it seems better to always try to create a toUnicode |
| 18669 |
// map based of the default encoding. |
| 18670 |
var toUnicode, charcode; |
| 18671 |
if (!properties.composite /* is simple font */) { |
| 18672 |
toUnicode = []; |
| 18673 |
var encoding = properties.defaultEncoding.slice(); |
| 18674 |
var baseEncodingName = properties.baseEncodingName; |
| 18675 |
// Merge in the differences array. |
| 18676 |
var differences = properties.differences; |
| 18677 |
for (charcode in differences) { |
| 18678 |
encoding[charcode] = differences[charcode]; |
| 18679 |
} |
| 18680 |
for (charcode in encoding) { |
| 18681 |
// a) Map the character code to a character name. |
| 18682 |
var glyphName = encoding[charcode]; |
| 18683 |
// b) Look up the character name in the Adobe Glyph List (see the |
| 18684 |
// Bibliography) to obtain the corresponding Unicode value. |
| 18685 |
if (glyphName === '') { |
| 18686 |
continue; |
| 18687 |
} else if (GlyphsUnicode[glyphName] === undefined) { |
| 18688 |
// (undocumented) c) Few heuristics to recognize unknown glyphs |
| 18689 |
// NOTE: Adobe Reader does not do this step, but OSX Preview does |
| 18690 |
var code = 0; |
| 18691 |
switch (glyphName[0]) { |
| 18692 |
case 'G': // Gxx glyph |
| 18693 |
if (glyphName.length === 3) { |
| 18694 |
code = parseInt(glyphName.substr(1), 16); |
| 18695 |
} |
| 18696 |
break; |
| 18697 |
case 'g': // g00xx glyph |
| 18698 |
if (glyphName.length === 5) { |
| 18699 |
code = parseInt(glyphName.substr(1), 16); |
| 18700 |
} |
| 18701 |
break; |
| 18702 |
case 'C': // Cddd glyph |
| 18703 |
case 'c': // cddd glyph |
| 18704 |
if (glyphName.length >= 3) { |
| 18705 |
code = +glyphName.substr(1); |
| 18706 |
} |
| 18707 |
break; |
| 18708 |
} |
| 18709 |
if (code) { |
| 18710 |
// If |baseEncodingName| is one the predefined encodings, |
| 18711 |
// and |code| equals |charcode|, using the glyph defined in the |
| 18712 |
// baseEncoding seems to yield a better |toUnicode| mapping |
| 18713 |
// (fixes issue 5070). |
| 18714 |
if (baseEncodingName && code === +charcode) { |
| 18715 |
var baseEncoding = Encodings[baseEncodingName]; |
| 18716 |
if (baseEncoding && (glyphName = baseEncoding[charcode])) { |
| 18717 |
toUnicode[charcode] = |
| 18718 |
String.fromCharCode(GlyphsUnicode[glyphName]); |
| 18719 |
continue; |
| 18720 |
} |
| 18721 |
} |
| 18722 |
toUnicode[charcode] = String.fromCharCode(code); |
| 18723 |
} |
| 18724 |
continue; |
| 18725 |
} |
| 18726 |
toUnicode[charcode] = String.fromCharCode(GlyphsUnicode[glyphName]); |
| 18727 |
} |
| 18728 |
return new ToUnicodeMap(toUnicode); |
| 18729 |
} |
| 18730 |
// If the font is a composite font that uses one of the predefined CMaps |
| 18731 |
// listed in Table 118 (except Identity–H and Identity–V) or whose |
| 18732 |
// descendant CIDFont uses the Adobe-GB1, Adobe-CNS1, Adobe-Japan1, or |
| 18733 |
// Adobe-Korea1 character collection: |
| 18734 |
if (properties.composite && ( |
| 18735 |
(properties.cMap.builtInCMap && |
| 18736 |
!(properties.cMap instanceof IdentityCMap)) || |
| 18737 |
(properties.cidSystemInfo.registry === 'Adobe' && |
| 18738 |
(properties.cidSystemInfo.ordering === 'GB1' || |
| 18739 |
properties.cidSystemInfo.ordering === 'CNS1' || |
| 18740 |
properties.cidSystemInfo.ordering === 'Japan1' || |
| 18741 |
properties.cidSystemInfo.ordering === 'Korea1')))) { |
| 18742 |
// Then: |
| 18743 |
// a) Map the character code to a character identifier (CID) according |
| 18744 |
// to the font’s CMap. |
| 18745 |
// b) Obtain the registry and ordering of the character collection used |
| 18746 |
// by the font’s CMap (for example, Adobe and Japan1) from its |
| 18747 |
// CIDSystemInfo dictionary. |
| 18748 |
var registry = properties.cidSystemInfo.registry; |
| 18749 |
var ordering = properties.cidSystemInfo.ordering; |
| 18750 |
// c) Construct a second CMap name by concatenating the registry and |
| 18751 |
// ordering obtained in step (b) in the format registry–ordering–UCS2 |
| 18752 |
// (for example, Adobe–Japan1–UCS2). |
| 18753 |
var ucs2CMapName = new Name(registry + '-' + ordering + '-UCS2'); |
| 18754 |
// d) Obtain the CMap with the name constructed in step (c) (available |
| 18755 |
// from the ASN Web site; see the Bibliography). |
| 18756 |
var ucs2CMap = CMapFactory.create(ucs2CMapName, |
| 18757 |
{ url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); |
| 18758 |
var cMap = properties.cMap; |
| 18759 |
toUnicode = []; |
| 18760 |
cMap.forEach(function(charcode, cid) { |
| 18761 |
assert(cid <= 0xffff, 'Max size of CID is 65,535'); |
| 18762 |
// e) Map the CID obtained in step (a) according to the CMap obtained |
| 18763 |
// in step (d), producing a Unicode value. |
| 18764 |
var ucs2 = ucs2CMap.lookup(cid); |
| 18765 |
if (ucs2) { |
| 18766 |
toUnicode[charcode] = |
| 18767 |
String.fromCharCode((ucs2.charCodeAt(0) << 8) + |
| 18768 |
ucs2.charCodeAt(1)); |
| 18769 |
} |
| 18770 |
}); |
| 18771 |
return new ToUnicodeMap(toUnicode); |
| 18772 |
} |
| 18773 |
|
| 18774 |
// The viewer's choice, just use an identity map. |
| 18775 |
return new IdentityToUnicodeMap(properties.firstChar, |
| 18776 |
properties.lastChar); |
| 18777 |
}, |
| 18778 |
|
| 18779 |
get spaceWidth() { |
| 18780 |
if ('_shadowWidth' in this) { |
| 18781 |
return this._shadowWidth; |
| 18782 |
} |
| 18783 |
|
| 18784 |
// trying to estimate space character width |
| 18785 |
var possibleSpaceReplacements = ['space', 'minus', 'one', 'i']; |
| 18786 |
var width; |
| 18787 |
for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) { |
| 18788 |
var glyphName = possibleSpaceReplacements[i]; |
| 18789 |
// if possible, getting width by glyph name |
| 18790 |
if (glyphName in this.widths) { |
| 18791 |
width = this.widths[glyphName]; |
| 18792 |
break; |
| 18793 |
} |
| 18794 |
var glyphUnicode = GlyphsUnicode[glyphName]; |
| 18795 |
// finding the charcode via unicodeToCID map |
| 18796 |
var charcode = 0; |
| 18797 |
if (this.composite) { |
| 18798 |
if (this.cMap.contains(glyphUnicode)) { |
| 18799 |
charcode = this.cMap.lookup(glyphUnicode); |
| 18800 |
} |
| 18801 |
} |
| 18802 |
// ... via toUnicode map |
| 18803 |
if (!charcode && 'toUnicode' in this) { |
| 18804 |
charcode = this.toUnicode.charCodeOf(glyphUnicode); |
| 18805 |
} |
| 18806 |
// setting it to unicode if negative or undefined |
| 18807 |
if (charcode <= 0) { |
| 18808 |
charcode = glyphUnicode; |
| 18809 |
} |
| 18810 |
// trying to get width via charcode |
| 18811 |
width = this.widths[charcode]; |
| 18812 |
if (width) { |
| 18813 |
break; // the non-zero width found |
| 18814 |
} |
| 18815 |
} |
| 18816 |
width = width || this.defaultWidth; |
| 18817 |
// Do not shadow the property here. See discussion: |
| 18818 |
// https://github.com/mozilla/pdf.js/pull/2127#discussion_r1662280 |
| 18819 |
this._shadowWidth = width; |
| 18820 |
return width; |
| 18821 |
}, |
| 18822 |
|
| 18823 |
charToGlyph: function Font_charToGlyph(charcode) { |
| 18824 |
var fontCharCode, width, operatorListId; |
| 18825 |
|
| 18826 |
var widthCode = charcode; |
| 18827 |
if (this.cMap && this.cMap.contains(charcode)) { |
| 18828 |
widthCode = this.cMap.lookup(charcode); |
| 18829 |
} |
| 18830 |
width = this.widths[widthCode]; |
| 18831 |
width = isNum(width) ? width : this.defaultWidth; |
| 18832 |
var vmetric = this.vmetrics && this.vmetrics[widthCode]; |
| 18833 |
|
| 18834 |
var unicode = this.toUnicode.get(charcode) || charcode; |
| 18835 |
if (typeof unicode === 'number') { |
| 18836 |
unicode = String.fromCharCode(unicode); |
| 18837 |
} |
| 18838 |
|
| 18839 |
// First try the toFontChar map, if it's not there then try falling |
| 18840 |
// back to the char code. |
| 18841 |
fontCharCode = this.toFontChar[charcode] || charcode; |
| 18842 |
if (this.missingFile) { |
| 18843 |
fontCharCode = mapSpecialUnicodeValues(fontCharCode); |
| 18844 |
} |
| 18845 |
|
| 18846 |
if (this.isType3Font) { |
| 18847 |
// Font char code in this case is actually a glyph name. |
| 18848 |
operatorListId = fontCharCode; |
| 18849 |
} |
| 18850 |
|
| 18851 |
var accent = null; |
| 18852 |
if (this.seacMap && this.seacMap[charcode]) { |
| 18853 |
var seac = this.seacMap[charcode]; |
| 18854 |
fontCharCode = seac.baseFontCharCode; |
| 18855 |
accent = { |
| 18856 |
fontChar: String.fromCharCode(seac.accentFontCharCode), |
| 18857 |
offset: seac.accentOffset |
| 18858 |
}; |
| 18859 |
} |
| 18860 |
|
| 18861 |
var fontChar = String.fromCharCode(fontCharCode); |
| 18862 |
|
| 18863 |
var glyph = this.glyphCache[charcode]; |
| 18864 |
if (!glyph || |
| 18865 |
!glyph.matchesForCache(fontChar, unicode, accent, width, vmetric, |
| 18866 |
operatorListId)) { |
| 18867 |
glyph = new Glyph(fontChar, unicode, accent, width, vmetric, |
| 18868 |
operatorListId); |
| 18869 |
this.glyphCache[charcode] = glyph; |
| 18870 |
} |
| 18871 |
return glyph; |
| 18872 |
}, |
| 18873 |
|
| 18874 |
charsToGlyphs: function Font_charsToGlyphs(chars) { |
| 18875 |
var charsCache = this.charsCache; |
| 18876 |
var glyphs, glyph, charcode; |
| 18877 |
|
| 18878 |
// if we translated this string before, just grab it from the cache |
| 18879 |
if (charsCache) { |
| 18880 |
glyphs = charsCache[chars]; |
| 18881 |
if (glyphs) { |
| 18882 |
return glyphs; |
| 18883 |
} |
| 18884 |
} |
| 18885 |
|
| 18886 |
// lazily create the translation cache |
| 18887 |
if (!charsCache) { |
| 18888 |
charsCache = this.charsCache = Object.create(null); |
| 18889 |
} |
| 18890 |
|
| 18891 |
glyphs = []; |
| 18892 |
var charsCacheKey = chars; |
| 18893 |
var i = 0, ii; |
| 18894 |
|
| 18895 |
if (this.cMap) { |
| 18896 |
// composite fonts have multi-byte strings convert the string from |
| 18897 |
// single-byte to multi-byte |
| 18898 |
var c = {}; |
| 18899 |
while (i < chars.length) { |
| 18900 |
this.cMap.readCharCode(chars, i, c); |
| 18901 |
charcode = c.charcode; |
| 18902 |
var length = c.length; |
| 18903 |
i += length; |
| 18904 |
glyph = this.charToGlyph(charcode); |
| 18905 |
glyphs.push(glyph); |
| 18906 |
// placing null after each word break charcode (ASCII SPACE) |
| 18907 |
// Ignore occurences of 0x20 in multiple-byte codes. |
| 18908 |
if (length === 1 && chars.charCodeAt(i - 1) === 0x20) { |
| 18909 |
glyphs.push(null); |
| 18910 |
} |
| 18911 |
} |
| 18912 |
} else { |
| 18913 |
for (i = 0, ii = chars.length; i < ii; ++i) { |
| 18914 |
charcode = chars.charCodeAt(i); |
| 18915 |
glyph = this.charToGlyph(charcode); |
| 18916 |
glyphs.push(glyph); |
| 18917 |
if (charcode === 0x20) { |
| 18918 |
glyphs.push(null); |
| 18919 |
} |
| 18920 |
} |
| 18921 |
} |
| 18922 |
|
| 18923 |
// Enter the translated string into the cache |
| 18924 |
return (charsCache[charsCacheKey] = glyphs); |
| 18925 |
} |
| 18926 |
}; |
| 18927 |
|
| 18928 |
return Font; |
| 18929 |
})(); |
| 18930 |
|
| 18931 |
var ErrorFont = (function ErrorFontClosure() { |
| 18932 |
function ErrorFont(error) { |
| 18933 |
this.error = error; |
| 18934 |
this.loadedName = 'g_font_error'; |
| 18935 |
this.loading = false; |
| 18936 |
} |
| 18937 |
|
| 18938 |
ErrorFont.prototype = { |
| 18939 |
charsToGlyphs: function ErrorFont_charsToGlyphs() { |
| 18940 |
return []; |
| 18941 |
}, |
| 18942 |
exportData: function ErrorFont_exportData() { |
| 18943 |
return {error: this.error}; |
| 18944 |
} |
| 18945 |
}; |
| 18946 |
|
| 18947 |
return ErrorFont; |
| 18948 |
})(); |
| 18949 |
|
| 18950 |
/** |
| 18951 |
* Shared logic for building a char code to glyph id mapping for Type1 and |
| 18952 |
* simple CFF fonts. See section 9.6.6.2 of the spec. |
| 18953 |
* @param {Object} properties Font properties object. |
| 18954 |
* @param {Object} builtInEncoding The encoding contained within the actual font |
| 18955 |
* data. |
| 18956 |
* @param {Array} Array of glyph names where the index is the glyph ID. |
| 18957 |
* @returns {Object} A char code to glyph ID map. |
| 18958 |
*/ |
| 18959 |
function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) { |
| 18960 |
var charCodeToGlyphId = Object.create(null); |
| 18961 |
var glyphId, charCode, baseEncoding; |
| 18962 |
|
| 18963 |
if (properties.baseEncodingName) { |
| 18964 |
// If a valid base encoding name was used, the mapping is initialized with |
| 18965 |
// that. |
| 18966 |
baseEncoding = Encodings[properties.baseEncodingName]; |
| 18967 |
for (charCode = 0; charCode < baseEncoding.length; charCode++) { |
| 18968 |
glyphId = glyphNames.indexOf(baseEncoding[charCode]); |
| 18969 |
if (glyphId >= 0) { |
| 18970 |
charCodeToGlyphId[charCode] = glyphId; |
| 18971 |
} else { |
| 18972 |
charCodeToGlyphId[charCode] = 0; // notdef |
| 18973 |
} |
| 18974 |
} |
| 18975 |
} else if (!!(properties.flags & FontFlags.Symbolic)) { |
| 18976 |
// For a symbolic font the encoding should be the fonts built-in |
| 18977 |
// encoding. |
| 18978 |
for (charCode in builtInEncoding) { |
| 18979 |
charCodeToGlyphId[charCode] = builtInEncoding[charCode]; |
| 18980 |
} |
| 18981 |
} else { |
| 18982 |
// For non-symbolic fonts that don't have a base encoding the standard |
| 18983 |
// encoding should be used. |
| 18984 |
baseEncoding = Encodings.StandardEncoding; |
| 18985 |
for (charCode = 0; charCode < baseEncoding.length; charCode++) { |
| 18986 |
glyphId = glyphNames.indexOf(baseEncoding[charCode]); |
| 18987 |
if (glyphId >= 0) { |
| 18988 |
charCodeToGlyphId[charCode] = glyphId; |
| 18989 |
} else { |
| 18990 |
charCodeToGlyphId[charCode] = 0; // notdef |
| 18991 |
} |
| 18992 |
} |
| 18993 |
} |
| 18994 |
|
| 18995 |
// Lastly, merge in the differences. |
| 18996 |
var differences = properties.differences; |
| 18997 |
if (differences) { |
| 18998 |
for (charCode in differences) { |
| 18999 |
var glyphName = differences[charCode]; |
| 19000 |
glyphId = glyphNames.indexOf(glyphName); |
| 19001 |
if (glyphId >= 0) { |
| 19002 |
charCodeToGlyphId[charCode] = glyphId; |
| 19003 |
} else { |
| 19004 |
charCodeToGlyphId[charCode] = 0; // notdef |
| 19005 |
} |
| 19006 |
} |
| 19007 |
} |
| 19008 |
return charCodeToGlyphId; |
| 19009 |
} |
| 19010 |
|
| 19011 |
/* |
| 19012 |
* CharStrings are encoded following the the CharString Encoding sequence |
| 19013 |
* describe in Chapter 6 of the "Adobe Type1 Font Format" specification. |
| 19014 |
* The value in a byte indicates a command, a number, or subsequent bytes |
| 19015 |
* that are to be interpreted in a special way. |
| 19016 |
* |
| 19017 |
* CharString Number Encoding: |
| 19018 |
* A CharString byte containing the values from 32 through 255 inclusive |
| 19019 |
* indicate an integer. These values are decoded in four ranges. |
| 19020 |
* |
| 19021 |
* 1. A CharString byte containing a value, v, between 32 and 246 inclusive, |
| 19022 |
* indicate the integer v - 139. Thus, the integer values from -107 through |
| 19023 |
* 107 inclusive may be encoded in single byte. |
| 19024 |
* |
| 19025 |
* 2. A CharString byte containing a value, v, between 247 and 250 inclusive, |
| 19026 |
* indicates an integer involving the next byte, w, according to the formula: |
| 19027 |
* [(v - 247) x 256] + w + 108 |
| 19028 |
* |
| 19029 |
* 3. A CharString byte containing a value, v, between 251 and 254 inclusive, |
| 19030 |
* indicates an integer involving the next byte, w, according to the formula: |
| 19031 |
* -[(v - 251) * 256] - w - 108 |
| 19032 |
* |
| 19033 |
* 4. A CharString containing the value 255 indicates that the next 4 bytes |
| 19034 |
* are a two complement signed integer. The first of these bytes contains the |
| 19035 |
* highest order bits, the second byte contains the next higher order bits |
| 19036 |
* and the fourth byte contain the lowest order bits. |
| 19037 |
* |
| 19038 |
* |
| 19039 |
* CharString Command Encoding: |
| 19040 |
* CharStrings commands are encoded in 1 or 2 bytes. |
| 19041 |
* |
| 19042 |
* Single byte commands are encoded in 1 byte that contains a value between |
| 19043 |
* 0 and 31 inclusive. |
| 19044 |
* If a command byte contains the value 12, then the value in the next byte |
| 19045 |
* indicates a command. This "escape" mechanism allows many extra commands |
| 19046 |
* to be encoded and this encoding technique helps to minimize the length of |
| 19047 |
* the charStrings. |
| 19048 |
*/ |
| 19049 |
var Type1CharString = (function Type1CharStringClosure() { |
| 19050 |
var COMMAND_MAP = { |
| 19051 |
'hstem': [1], |
| 19052 |
'vstem': [3], |
| 19053 |
'vmoveto': [4], |
| 19054 |
'rlineto': [5], |
| 19055 |
'hlineto': [6], |
| 19056 |
'vlineto': [7], |
| 19057 |
'rrcurveto': [8], |
| 19058 |
'callsubr': [10], |
| 19059 |
'flex': [12, 35], |
| 19060 |
'drop' : [12, 18], |
| 19061 |
'endchar': [14], |
| 19062 |
'rmoveto': [21], |
| 19063 |
'hmoveto': [22], |
| 19064 |
'vhcurveto': [30], |
| 19065 |
'hvcurveto': [31] |
| 19066 |
}; |
| 19067 |
|
| 19068 |
function Type1CharString() { |
| 19069 |
this.width = 0; |
| 19070 |
this.lsb = 0; |
| 19071 |
this.flexing = false; |
| 19072 |
this.output = []; |
| 19073 |
this.stack = []; |
| 19074 |
} |
| 19075 |
|
| 19076 |
Type1CharString.prototype = { |
| 19077 |
convert: function Type1CharString_convert(encoded, subrs) { |
| 19078 |
var count = encoded.length; |
| 19079 |
var error = false; |
| 19080 |
var wx, sbx, subrNumber; |
| 19081 |
for (var i = 0; i < count; i++) { |
| 19082 |
var value = encoded[i]; |
| 19083 |
if (value < 32) { |
| 19084 |
if (value === 12) { |
| 19085 |
value = (value << 8) + encoded[++i]; |
| 19086 |
} |
| 19087 |
switch (value) { |
| 19088 |
case 1: // hstem |
| 19089 |
if (!HINTING_ENABLED) { |
| 19090 |
this.stack = []; |
| 19091 |
break; |
| 19092 |
} |
| 19093 |
error = this.executeCommand(2, COMMAND_MAP.hstem); |
| 19094 |
break; |
| 19095 |
case 3: // vstem |
| 19096 |
if (!HINTING_ENABLED) { |
| 19097 |
this.stack = []; |
| 19098 |
break; |
| 19099 |
} |
| 19100 |
error = this.executeCommand(2, COMMAND_MAP.vstem); |
| 19101 |
break; |
| 19102 |
case 4: // vmoveto |
| 19103 |
if (this.flexing) { |
| 19104 |
if (this.stack.length < 1) { |
| 19105 |
error = true; |
| 19106 |
break; |
| 19107 |
} |
| 19108 |
// Add the dx for flex and but also swap the values so they are |
| 19109 |
// the right order. |
| 19110 |
var dy = this.stack.pop(); |
| 19111 |
this.stack.push(0, dy); |
| 19112 |
break; |
| 19113 |
} |
| 19114 |
error = this.executeCommand(1, COMMAND_MAP.vmoveto); |
| 19115 |
break; |
| 19116 |
case 5: // rlineto |
| 19117 |
error = this.executeCommand(2, COMMAND_MAP.rlineto); |
| 19118 |
break; |
| 19119 |
case 6: // hlineto |
| 19120 |
error = this.executeCommand(1, COMMAND_MAP.hlineto); |
| 19121 |
break; |
| 19122 |
case 7: // vlineto |
| 19123 |
error = this.executeCommand(1, COMMAND_MAP.vlineto); |
| 19124 |
break; |
| 19125 |
case 8: // rrcurveto |
| 19126 |
error = this.executeCommand(6, COMMAND_MAP.rrcurveto); |
| 19127 |
break; |
| 19128 |
case 9: // closepath |
| 19129 |
// closepath is a Type1 command that does not take argument and is |
| 19130 |
// useless in Type2 and it can simply be ignored. |
| 19131 |
this.stack = []; |
| 19132 |
break; |
| 19133 |
case 10: // callsubr |
| 19134 |
if (this.stack.length < 1) { |
| 19135 |
error = true; |
| 19136 |
break; |
| 19137 |
} |
| 19138 |
subrNumber = this.stack.pop(); |
| 19139 |
error = this.convert(subrs[subrNumber], subrs); |
| 19140 |
break; |
| 19141 |
case 11: // return |
| 19142 |
return error; |
| 19143 |
case 13: // hsbw |
| 19144 |
if (this.stack.length < 2) { |
| 19145 |
error = true; |
| 19146 |
break; |
| 19147 |
} |
| 19148 |
// To convert to type2 we have to move the width value to the |
| 19149 |
// first part of the charstring and then use hmoveto with lsb. |
| 19150 |
wx = this.stack.pop(); |
| 19151 |
sbx = this.stack.pop(); |
| 19152 |
this.lsb = sbx; |
| 19153 |
this.width = wx; |
| 19154 |
this.stack.push(wx, sbx); |
| 19155 |
error = this.executeCommand(2, COMMAND_MAP.hmoveto); |
| 19156 |
break; |
| 19157 |
case 14: // endchar |
| 19158 |
this.output.push(COMMAND_MAP.endchar[0]); |
| 19159 |
break; |
| 19160 |
case 21: // rmoveto |
| 19161 |
if (this.flexing) { |
| 19162 |
break; |
| 19163 |
} |
| 19164 |
error = this.executeCommand(2, COMMAND_MAP.rmoveto); |
| 19165 |
break; |
| 19166 |
case 22: // hmoveto |
| 19167 |
if (this.flexing) { |
| 19168 |
// Add the dy for flex. |
| 19169 |
this.stack.push(0); |
| 19170 |
break; |
| 19171 |
} |
| 19172 |
error = this.executeCommand(1, COMMAND_MAP.hmoveto); |
| 19173 |
break; |
| 19174 |
case 30: // vhcurveto |
| 19175 |
error = this.executeCommand(4, COMMAND_MAP.vhcurveto); |
| 19176 |
break; |
| 19177 |
case 31: // hvcurveto |
| 19178 |
error = this.executeCommand(4, COMMAND_MAP.hvcurveto); |
| 19179 |
break; |
| 19180 |
case (12 << 8) + 0: // dotsection |
| 19181 |
// dotsection is a Type1 command to specify some hinting feature |
| 19182 |
// for dots that do not take a parameter and it can safely be |
| 19183 |
// ignored for Type2. |
| 19184 |
this.stack = []; |
| 19185 |
break; |
| 19186 |
case (12 << 8) + 1: // vstem3 |
| 19187 |
if (!HINTING_ENABLED) { |
| 19188 |
this.stack = []; |
| 19189 |
break; |
| 19190 |
} |
| 19191 |
// [vh]stem3 are Type1 only and Type2 supports [vh]stem with |
| 19192 |
// multiple parameters, so instead of returning [vh]stem3 take a |
| 19193 |
// shortcut and return [vhstem] instead. |
| 19194 |
error = this.executeCommand(2, COMMAND_MAP.vstem); |
| 19195 |
break; |
| 19196 |
case (12 << 8) + 2: // hstem3 |
| 19197 |
if (!HINTING_ENABLED) { |
| 19198 |
this.stack = []; |
| 19199 |
break; |
| 19200 |
} |
| 19201 |
// See vstem3. |
| 19202 |
error = this.executeCommand(2, COMMAND_MAP.hstem); |
| 19203 |
break; |
| 19204 |
case (12 << 8) + 6: // seac |
| 19205 |
// seac is like type 2's special endchar but it doesn't use the |
| 19206 |
// first argument asb, so remove it. |
| 19207 |
if (SEAC_ANALYSIS_ENABLED) { |
| 19208 |
this.seac = this.stack.splice(-4, 4); |
| 19209 |
error = this.executeCommand(0, COMMAND_MAP.endchar); |
| 19210 |
} else { |
| 19211 |
error = this.executeCommand(4, COMMAND_MAP.endchar); |
| 19212 |
} |
| 19213 |
break; |
| 19214 |
case (12 << 8) + 7: // sbw |
| 19215 |
if (this.stack.length < 4) { |
| 19216 |
error = true; |
| 19217 |
break; |
| 19218 |
} |
| 19219 |
// To convert to type2 we have to move the width value to the |
| 19220 |
// first part of the charstring and then use rmoveto with |
| 19221 |
// (dx, dy). The height argument will not be used for vmtx and |
| 19222 |
// vhea tables reconstruction -- ignoring it. |
| 19223 |
var wy = this.stack.pop(); |
| 19224 |
wx = this.stack.pop(); |
| 19225 |
var sby = this.stack.pop(); |
| 19226 |
sbx = this.stack.pop(); |
| 19227 |
this.lsb = sbx; |
| 19228 |
this.width = wx; |
| 19229 |
this.stack.push(wx, sbx, sby); |
| 19230 |
error = this.executeCommand(3, COMMAND_MAP.rmoveto); |
| 19231 |
break; |
| 19232 |
case (12 << 8) + 12: // div |
| 19233 |
if (this.stack.length < 2) { |
| 19234 |
error = true; |
| 19235 |
break; |
| 19236 |
} |
| 19237 |
var num2 = this.stack.pop(); |
| 19238 |
var num1 = this.stack.pop(); |
| 19239 |
this.stack.push(num1 / num2); |
| 19240 |
break; |
| 19241 |
case (12 << 8) + 16: // callothersubr |
| 19242 |
if (this.stack.length < 2) { |
| 19243 |
error = true; |
| 19244 |
break; |
| 19245 |
} |
| 19246 |
subrNumber = this.stack.pop(); |
| 19247 |
var numArgs = this.stack.pop(); |
| 19248 |
if (subrNumber === 0 && numArgs === 3) { |
| 19249 |
var flexArgs = this.stack.splice(this.stack.length - 17, 17); |
| 19250 |
this.stack.push( |
| 19251 |
flexArgs[2] + flexArgs[0], // bcp1x + rpx |
| 19252 |
flexArgs[3] + flexArgs[1], // bcp1y + rpy |
| 19253 |
flexArgs[4], // bcp2x |
| 19254 |
flexArgs[5], // bcp2y |
| 19255 |
flexArgs[6], // p2x |
| 19256 |
flexArgs[7], // p2y |
| 19257 |
flexArgs[8], // bcp3x |
| 19258 |
flexArgs[9], // bcp3y |
| 19259 |
flexArgs[10], // bcp4x |
| 19260 |
flexArgs[11], // bcp4y |
| 19261 |
flexArgs[12], // p3x |
| 19262 |
flexArgs[13], // p3y |
| 19263 |
flexArgs[14] // flexDepth |
| 19264 |
// 15 = finalx unused by flex |
| 19265 |
// 16 = finaly unused by flex |
| 19266 |
); |
| 19267 |
error = this.executeCommand(13, COMMAND_MAP.flex, true); |
| 19268 |
this.flexing = false; |
| 19269 |
this.stack.push(flexArgs[15], flexArgs[16]); |
| 19270 |
} else if (subrNumber === 1 && numArgs === 0) { |
| 19271 |
this.flexing = true; |
| 19272 |
} |
| 19273 |
break; |
| 19274 |
case (12 << 8) + 17: // pop |
| 19275 |
// Ignore this since it is only used with othersubr. |
| 19276 |
break; |
| 19277 |
case (12 << 8) + 33: // setcurrentpoint |
| 19278 |
// Ignore for now. |
| 19279 |
this.stack = []; |
| 19280 |
break; |
| 19281 |
default: |
| 19282 |
warn('Unknown type 1 charstring command of "' + value + '"'); |
| 19283 |
break; |
| 19284 |
} |
| 19285 |
if (error) { |
| 19286 |
break; |
| 19287 |
} |
| 19288 |
continue; |
| 19289 |
} else if (value <= 246) { |
| 19290 |
value = value - 139; |
| 19291 |
} else if (value <= 250) { |
| 19292 |
value = ((value - 247) * 256) + encoded[++i] + 108; |
| 19293 |
} else if (value <= 254) { |
| 19294 |
value = -((value - 251) * 256) - encoded[++i] - 108; |
| 19295 |
} else { |
| 19296 |
value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | |
| 19297 |
(encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0; |
| 19298 |
} |
| 19299 |
this.stack.push(value); |
| 19300 |
} |
| 19301 |
return error; |
| 19302 |
}, |
| 19303 |
|
| 19304 |
executeCommand: function(howManyArgs, command, keepStack) { |
| 19305 |
var stackLength = this.stack.length; |
| 19306 |
if (howManyArgs > stackLength) { |
| 19307 |
return true; |
| 19308 |
} |
| 19309 |
var start = stackLength - howManyArgs; |
| 19310 |
for (var i = start; i < stackLength; i++) { |
| 19311 |
var value = this.stack[i]; |
| 19312 |
if (value === (value | 0)) { // int |
| 19313 |
this.output.push(28, (value >> 8) & 0xff, value & 0xff); |
| 19314 |
} else { // fixed point |
| 19315 |
value = (65536 * value) | 0; |
| 19316 |
this.output.push(255, |
| 19317 |
(value >> 24) & 0xFF, |
| 19318 |
(value >> 16) & 0xFF, |
| 19319 |
(value >> 8) & 0xFF, |
| 19320 |
value & 0xFF); |
| 19321 |
} |
| 19322 |
} |
| 19323 |
this.output.push.apply(this.output, command); |
| 19324 |
if (keepStack) { |
| 19325 |
this.stack.splice(start, howManyArgs); |
| 19326 |
} else { |
| 19327 |
this.stack.length = 0; |
| 19328 |
} |
| 19329 |
return false; |
| 19330 |
} |
| 19331 |
}; |
| 19332 |
|
| 19333 |
return Type1CharString; |
| 19334 |
})(); |
| 19335 |
|
| 19336 |
/* |
| 19337 |
* Type1Parser encapsulate the needed code for parsing a Type1 font |
| 19338 |
* program. Some of its logic depends on the Type2 charstrings |
| 19339 |
* structure. |
| 19340 |
* Note: this doesn't really parse the font since that would require evaluation |
| 19341 |
* of PostScript, but it is possible in most cases to extract what we need |
| 19342 |
* without a full parse. |
| 19343 |
*/ |
| 19344 |
var Type1Parser = (function Type1ParserClosure() { |
| 19345 |
/* |
| 19346 |
* Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence |
| 19347 |
* of Plaintext Bytes. The function took a key as a parameter which can be |
| 19348 |
* for decrypting the eexec block of for decoding charStrings. |
| 19349 |
*/ |
| 19350 |
var EEXEC_ENCRYPT_KEY = 55665; |
| 19351 |
var CHAR_STRS_ENCRYPT_KEY = 4330; |
| 19352 |
|
| 19353 |
function isHexDigit(code) { |
| 19354 |
return code >= 48 && code <= 57 || // '0'-'9' |
| 19355 |
code >= 65 && code <= 70 || // 'A'-'F' |
| 19356 |
code >= 97 && code <= 102; // 'a'-'f' |
| 19357 |
} |
| 19358 |
|
| 19359 |
function decrypt(data, key, discardNumber) { |
| 19360 |
var r = key | 0, c1 = 52845, c2 = 22719; |
| 19361 |
var count = data.length; |
| 19362 |
var decrypted = new Uint8Array(count); |
| 19363 |
for (var i = 0; i < count; i++) { |
| 19364 |
var value = data[i]; |
| 19365 |
decrypted[i] = value ^ (r >> 8); |
| 19366 |
r = ((value + r) * c1 + c2) & ((1 << 16) - 1); |
| 19367 |
} |
| 19368 |
return Array.prototype.slice.call(decrypted, discardNumber); |
| 19369 |
} |
| 19370 |
|
| 19371 |
function decryptAscii(data, key, discardNumber) { |
| 19372 |
var r = key | 0, c1 = 52845, c2 = 22719; |
| 19373 |
var count = data.length, maybeLength = count >>> 1; |
| 19374 |
var decrypted = new Uint8Array(maybeLength); |
| 19375 |
var i, j; |
| 19376 |
for (i = 0, j = 0; i < count; i++) { |
| 19377 |
var digit1 = data[i]; |
| 19378 |
if (!isHexDigit(digit1)) { |
| 19379 |
continue; |
| 19380 |
} |
| 19381 |
i++; |
| 19382 |
var digit2; |
| 19383 |
while (i < count && !isHexDigit(digit2 = data[i])) { |
| 19384 |
i++; |
| 19385 |
} |
| 19386 |
if (i < count) { |
| 19387 |
var value = parseInt(String.fromCharCode(digit1, digit2), 16); |
| 19388 |
decrypted[j++] = value ^ (r >> 8); |
| 19389 |
r = ((value + r) * c1 + c2) & ((1 << 16) - 1); |
| 19390 |
} |
| 19391 |
} |
| 19392 |
return Array.prototype.slice.call(decrypted, discardNumber, j); |
| 19393 |
} |
| 19394 |
|
| 19395 |
function isSpecial(c) { |
| 19396 |
return c === 0x2F || // '/' |
| 19397 |
c === 0x5B || c === 0x5D || // '[', ']' |
| 19398 |
c === 0x7B || c === 0x7D || // '{', '}' |
| 19399 |
c === 0x28 || c === 0x29; // '(', ')' |
| 19400 |
} |
| 19401 |
|
| 19402 |
function Type1Parser(stream, encrypted) { |
| 19403 |
if (encrypted) { |
| 19404 |
var data = stream.getBytes(); |
| 19405 |
var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) && |
| 19406 |
isHexDigit(data[2]) && isHexDigit(data[3])); |
| 19407 |
stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : |
| 19408 |
decryptAscii(data, EEXEC_ENCRYPT_KEY, 4)); |
| 19409 |
} |
| 19410 |
this.stream = stream; |
| 19411 |
this.nextChar(); |
| 19412 |
} |
| 19413 |
|
| 19414 |
Type1Parser.prototype = { |
| 19415 |
readNumberArray: function Type1Parser_readNumberArray() { |
| 19416 |
this.getToken(); // read '[' or '{' (arrays can start with either) |
| 19417 |
var array = []; |
| 19418 |
while (true) { |
| 19419 |
var token = this.getToken(); |
| 19420 |
if (token === null || token === ']' || token === '}') { |
| 19421 |
break; |
| 19422 |
} |
| 19423 |
array.push(parseFloat(token || 0)); |
| 19424 |
} |
| 19425 |
return array; |
| 19426 |
}, |
| 19427 |
|
| 19428 |
readNumber: function Type1Parser_readNumber() { |
| 19429 |
var token = this.getToken(); |
| 19430 |
return parseFloat(token || 0); |
| 19431 |
}, |
| 19432 |
|
| 19433 |
readInt: function Type1Parser_readInt() { |
| 19434 |
// Use '| 0' to prevent setting a double into length such as the double |
| 19435 |
// does not flow into the loop variable. |
| 19436 |
var token = this.getToken(); |
| 19437 |
return parseInt(token || 0, 10) | 0; |
| 19438 |
}, |
| 19439 |
|
| 19440 |
readBoolean: function Type1Parser_readBoolean() { |
| 19441 |
var token = this.getToken(); |
| 19442 |
|
| 19443 |
// Use 1 and 0 since that's what type2 charstrings use. |
| 19444 |
return token === 'true' ? 1 : 0; |
| 19445 |
}, |
| 19446 |
|
| 19447 |
nextChar : function Type1_nextChar() { |
| 19448 |
return (this.currentChar = this.stream.getByte()); |
| 19449 |
}, |
| 19450 |
|
| 19451 |
getToken: function Type1Parser_getToken() { |
| 19452 |
// Eat whitespace and comments. |
| 19453 |
var comment = false; |
| 19454 |
var ch = this.currentChar; |
| 19455 |
while (true) { |
| 19456 |
if (ch === -1) { |
| 19457 |
return null; |
| 19458 |
} |
| 19459 |
|
| 19460 |
if (comment) { |
| 19461 |
if (ch === 0x0A || ch === 0x0D) { |
| 19462 |
comment = false; |
| 19463 |
} |
| 19464 |
} else if (ch === 0x25) { // '%' |
| 19465 |
comment = true; |
| 19466 |
} else if (!Lexer.isSpace(ch)) { |
| 19467 |
break; |
| 19468 |
} |
| 19469 |
ch = this.nextChar(); |
| 19470 |
} |
| 19471 |
if (isSpecial(ch)) { |
| 19472 |
this.nextChar(); |
| 19473 |
return String.fromCharCode(ch); |
| 19474 |
} |
| 19475 |
var token = ''; |
| 19476 |
do { |
| 19477 |
token += String.fromCharCode(ch); |
| 19478 |
ch = this.nextChar(); |
| 19479 |
} while (ch >= 0 && !Lexer.isSpace(ch) && !isSpecial(ch)); |
| 19480 |
return token; |
| 19481 |
}, |
| 19482 |
|
| 19483 |
/* |
| 19484 |
* Returns an object containing a Subrs array and a CharStrings |
| 19485 |
* array extracted from and eexec encrypted block of data |
| 19486 |
*/ |
| 19487 |
extractFontProgram: function Type1Parser_extractFontProgram() { |
| 19488 |
var stream = this.stream; |
| 19489 |
|
| 19490 |
var subrs = [], charstrings = []; |
| 19491 |
var program = { |
| 19492 |
subrs: [], |
| 19493 |
charstrings: [], |
| 19494 |
properties: { |
| 19495 |
'privateData': { |
| 19496 |
'lenIV': 4 |
| 19497 |
} |
| 19498 |
} |
| 19499 |
}; |
| 19500 |
var token, length, data, lenIV, encoded; |
| 19501 |
while ((token = this.getToken()) !== null) { |
| 19502 |
if (token !== '/') { |
| 19503 |
continue; |
| 19504 |
} |
| 19505 |
token = this.getToken(); |
| 19506 |
switch (token) { |
| 19507 |
case 'CharStrings': |
| 19508 |
// The number immediately following CharStrings must be greater or |
| 19509 |
// equal to the number of CharStrings. |
| 19510 |
this.getToken(); |
| 19511 |
this.getToken(); // read in 'dict' |
| 19512 |
this.getToken(); // read in 'dup' |
| 19513 |
this.getToken(); // read in 'begin' |
| 19514 |
while(true) { |
| 19515 |
token = this.getToken(); |
| 19516 |
if (token === null || token === 'end') { |
| 19517 |
break; |
| 19518 |
} |
| 19519 |
|
| 19520 |
if (token !== '/') { |
| 19521 |
continue; |
| 19522 |
} |
| 19523 |
var glyph = this.getToken(); |
| 19524 |
length = this.readInt(); |
| 19525 |
this.getToken(); // read in 'RD' or '-|' |
| 19526 |
data = stream.makeSubStream(stream.pos, length); |
| 19527 |
lenIV = program.properties.privateData['lenIV']; |
| 19528 |
encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV); |
| 19529 |
// Skip past the required space and binary data. |
| 19530 |
stream.skip(length); |
| 19531 |
this.nextChar(); |
| 19532 |
token = this.getToken(); // read in 'ND' or '|-' |
| 19533 |
if (token === 'noaccess') { |
| 19534 |
this.getToken(); // read in 'def' |
| 19535 |
} |
| 19536 |
charstrings.push({ |
| 19537 |
glyph: glyph, |
| 19538 |
encoded: encoded |
| 19539 |
}); |
| 19540 |
} |
| 19541 |
break; |
| 19542 |
case 'Subrs': |
| 19543 |
var num = this.readInt(); |
| 19544 |
this.getToken(); // read in 'array' |
| 19545 |
while ((token = this.getToken()) === 'dup') { |
| 19546 |
var index = this.readInt(); |
| 19547 |
length = this.readInt(); |
| 19548 |
this.getToken(); // read in 'RD' or '-|' |
| 19549 |
data = stream.makeSubStream(stream.pos, length); |
| 19550 |
lenIV = program.properties.privateData['lenIV']; |
| 19551 |
encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV); |
| 19552 |
// Skip past the required space and binary data. |
| 19553 |
stream.skip(length); |
| 19554 |
this.nextChar(); |
| 19555 |
token = this.getToken(); // read in 'NP' or '|' |
| 19556 |
if (token === 'noaccess') { |
| 19557 |
this.getToken(); // read in 'put' |
| 19558 |
} |
| 19559 |
subrs[index] = encoded; |
| 19560 |
} |
| 19561 |
break; |
| 19562 |
case 'BlueValues': |
| 19563 |
case 'OtherBlues': |
| 19564 |
case 'FamilyBlues': |
| 19565 |
case 'FamilyOtherBlues': |
| 19566 |
var blueArray = this.readNumberArray(); |
| 19567 |
// *Blue* values may contain invalid data: disables reading of |
| 19568 |
// those values when hinting is disabled. |
| 19569 |
if (blueArray.length > 0 && (blueArray.length % 2) === 0 && |
| 19570 |
HINTING_ENABLED) { |
| 19571 |
program.properties.privateData[token] = blueArray; |
| 19572 |
} |
| 19573 |
break; |
| 19574 |
case 'StemSnapH': |
| 19575 |
case 'StemSnapV': |
| 19576 |
program.properties.privateData[token] = this.readNumberArray(); |
| 19577 |
break; |
| 19578 |
case 'StdHW': |
| 19579 |
case 'StdVW': |
| 19580 |
program.properties.privateData[token] = |
| 19581 |
this.readNumberArray()[0]; |
| 19582 |
break; |
| 19583 |
case 'BlueShift': |
| 19584 |
case 'lenIV': |
| 19585 |
case 'BlueFuzz': |
| 19586 |
case 'BlueScale': |
| 19587 |
case 'LanguageGroup': |
| 19588 |
case 'ExpansionFactor': |
| 19589 |
program.properties.privateData[token] = this.readNumber(); |
| 19590 |
break; |
| 19591 |
case 'ForceBold': |
| 19592 |
program.properties.privateData[token] = this.readBoolean(); |
| 19593 |
break; |
| 19594 |
} |
| 19595 |
} |
| 19596 |
|
| 19597 |
for (var i = 0; i < charstrings.length; i++) { |
| 19598 |
glyph = charstrings[i].glyph; |
| 19599 |
encoded = charstrings[i].encoded; |
| 19600 |
var charString = new Type1CharString(); |
| 19601 |
var error = charString.convert(encoded, subrs); |
| 19602 |
var output = charString.output; |
| 19603 |
if (error) { |
| 19604 |
// It seems when FreeType encounters an error while evaluating a glyph |
| 19605 |
// that it completely ignores the glyph so we'll mimic that behaviour |
| 19606 |
// here and put an endchar to make the validator happy. |
| 19607 |
output = [14]; |
| 19608 |
} |
| 19609 |
program.charstrings.push({ |
| 19610 |
glyphName: glyph, |
| 19611 |
charstring: output, |
| 19612 |
width: charString.width, |
| 19613 |
lsb: charString.lsb, |
| 19614 |
seac: charString.seac |
| 19615 |
}); |
| 19616 |
} |
| 19617 |
|
| 19618 |
return program; |
| 19619 |
}, |
| 19620 |
|
| 19621 |
extractFontHeader: function Type1Parser_extractFontHeader(properties) { |
| 19622 |
var token; |
| 19623 |
while ((token = this.getToken()) !== null) { |
| 19624 |
if (token !== '/') { |
| 19625 |
continue; |
| 19626 |
} |
| 19627 |
token = this.getToken(); |
| 19628 |
switch (token) { |
| 19629 |
case 'FontMatrix': |
| 19630 |
var matrix = this.readNumberArray(); |
| 19631 |
properties.fontMatrix = matrix; |
| 19632 |
break; |
| 19633 |
case 'Encoding': |
| 19634 |
var encodingArg = this.getToken(); |
| 19635 |
var encoding; |
| 19636 |
if (!/^\d+$/.test(encodingArg)) { |
| 19637 |
// encoding name is specified |
| 19638 |
encoding = Encodings[encodingArg]; |
| 19639 |
} else { |
| 19640 |
encoding = []; |
| 19641 |
var size = parseInt(encodingArg, 10) | 0; |
| 19642 |
this.getToken(); // read in 'array' |
| 19643 |
|
| 19644 |
for (var j = 0; j < size; j++) { |
| 19645 |
token = this.getToken(); |
| 19646 |
// skipping till first dup or def (e.g. ignoring for statement) |
| 19647 |
while (token !== 'dup' && token !== 'def') { |
| 19648 |
token = this.getToken(); |
| 19649 |
if (token === null) { |
| 19650 |
return; // invalid header |
| 19651 |
} |
| 19652 |
} |
| 19653 |
if (token === 'def') { |
| 19654 |
break; // read all array data |
| 19655 |
} |
| 19656 |
var index = this.readInt(); |
| 19657 |
this.getToken(); // read in '/' |
| 19658 |
var glyph = this.getToken(); |
| 19659 |
encoding[index] = glyph; |
| 19660 |
this.getToken(); // read the in 'put' |
| 19661 |
} |
| 19662 |
} |
| 19663 |
properties.builtInEncoding = encoding; |
| 19664 |
break; |
| 19665 |
case 'FontBBox': |
| 19666 |
var fontBBox = this.readNumberArray(); |
| 19667 |
// adjusting ascent/descent |
| 19668 |
properties.ascent = fontBBox[3]; |
| 19669 |
properties.descent = fontBBox[1]; |
| 19670 |
properties.ascentScaled = true; |
| 19671 |
break; |
| 19672 |
} |
| 19673 |
} |
| 19674 |
} |
| 19675 |
}; |
| 19676 |
|
| 19677 |
return Type1Parser; |
| 19678 |
})(); |
| 19679 |
|
| 19680 |
/** |
| 19681 |
* The CFF class takes a Type1 file and wrap it into a |
| 19682 |
* 'Compact Font Format' which itself embed Type2 charstrings. |
| 19683 |
*/ |
| 19684 |
var CFFStandardStrings = [ |
| 19685 |
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', |
| 19686 |
'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', |
| 19687 |
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', |
| 19688 |
'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', |
| 19689 |
'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', |
| 19690 |
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', |
| 19691 |
'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', |
| 19692 |
'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', |
| 19693 |
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', |
| 19694 |
'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', |
| 19695 |
'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', |
| 19696 |
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', |
| 19697 |
'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', |
| 19698 |
'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', |
| 19699 |
'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', |
| 19700 |
'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', |
| 19701 |
'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', |
| 19702 |
'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', |
| 19703 |
'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', |
| 19704 |
'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', |
| 19705 |
'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', |
| 19706 |
'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', |
| 19707 |
'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', |
| 19708 |
'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', |
| 19709 |
'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', |
| 19710 |
'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', |
| 19711 |
'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', |
| 19712 |
'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', |
| 19713 |
'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', |
| 19714 |
'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', |
| 19715 |
'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', |
| 19716 |
'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', |
| 19717 |
'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', |
| 19718 |
'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', |
| 19719 |
'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', |
| 19720 |
'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', |
| 19721 |
'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', |
| 19722 |
'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', |
| 19723 |
'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', |
| 19724 |
'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', |
| 19725 |
'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', |
| 19726 |
'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', |
| 19727 |
'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', |
| 19728 |
'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', |
| 19729 |
'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', |
| 19730 |
'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', |
| 19731 |
'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', |
| 19732 |
'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', |
| 19733 |
'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', |
| 19734 |
'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth', |
| 19735 |
'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', |
| 19736 |
'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', |
| 19737 |
'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', |
| 19738 |
'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', |
| 19739 |
'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', |
| 19740 |
'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', |
| 19741 |
'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', |
| 19742 |
'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', |
| 19743 |
'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', |
| 19744 |
'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', |
| 19745 |
'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', |
| 19746 |
'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', |
| 19747 |
'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', |
| 19748 |
'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003', |
| 19749 |
'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold' |
| 19750 |
]; |
| 19751 |
|
| 19752 |
// Type1Font is also a CIDFontType0. |
| 19753 |
var Type1Font = function Type1Font(name, file, properties) { |
| 19754 |
// Some bad generators embed pfb file as is, we have to strip 6-byte headers. |
| 19755 |
// Also, length1 and length2 might be off by 6 bytes as well. |
| 19756 |
// http://www.math.ubc.ca/~cass/piscript/type1.pdf |
| 19757 |
var PFB_HEADER_SIZE = 6; |
| 19758 |
var headerBlockLength = properties.length1; |
| 19759 |
var eexecBlockLength = properties.length2; |
| 19760 |
var pfbHeader = file.peekBytes(PFB_HEADER_SIZE); |
| 19761 |
var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01; |
| 19762 |
if (pfbHeaderPresent) { |
| 19763 |
file.skip(PFB_HEADER_SIZE); |
| 19764 |
headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) | |
| 19765 |
(pfbHeader[3] << 8) | pfbHeader[2]; |
| 19766 |
} |
| 19767 |
|
| 19768 |
// Get the data block containing glyphs and subrs informations |
| 19769 |
var headerBlock = new Stream(file.getBytes(headerBlockLength)); |
| 19770 |
var headerBlockParser = new Type1Parser(headerBlock); |
| 19771 |
headerBlockParser.extractFontHeader(properties); |
| 19772 |
|
| 19773 |
if (pfbHeaderPresent) { |
| 19774 |
pfbHeader = file.getBytes(PFB_HEADER_SIZE); |
| 19775 |
eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) | |
| 19776 |
(pfbHeader[3] << 8) | pfbHeader[2]; |
| 19777 |
} |
| 19778 |
|
| 19779 |
// Decrypt the data blocks and retrieve it's content |
| 19780 |
var eexecBlock = new Stream(file.getBytes(eexecBlockLength)); |
| 19781 |
var eexecBlockParser = new Type1Parser(eexecBlock, true); |
| 19782 |
var data = eexecBlockParser.extractFontProgram(); |
| 19783 |
for (var info in data.properties) { |
| 19784 |
properties[info] = data.properties[info]; |
| 19785 |
} |
| 19786 |
|
| 19787 |
var charstrings = data.charstrings; |
| 19788 |
var type2Charstrings = this.getType2Charstrings(charstrings); |
| 19789 |
var subrs = this.getType2Subrs(data.subrs); |
| 19790 |
|
| 19791 |
this.charstrings = charstrings; |
| 19792 |
this.data = this.wrap(name, type2Charstrings, this.charstrings, |
| 19793 |
subrs, properties); |
| 19794 |
this.seacs = this.getSeacs(data.charstrings); |
| 19795 |
}; |
| 19796 |
|
| 19797 |
Type1Font.prototype = { |
| 19798 |
get numGlyphs() { |
| 19799 |
return this.charstrings.length + 1; |
| 19800 |
}, |
| 19801 |
|
| 19802 |
getCharset: function Type1Font_getCharset() { |
| 19803 |
var charset = ['.notdef']; |
| 19804 |
var charstrings = this.charstrings; |
| 19805 |
for (var glyphId = 0; glyphId < charstrings.length; glyphId++) { |
| 19806 |
charset.push(charstrings[glyphId].glyphName); |
| 19807 |
} |
| 19808 |
return charset; |
| 19809 |
}, |
| 19810 |
|
| 19811 |
getGlyphMapping: function Type1Font_getGlyphMapping(properties) { |
| 19812 |
var charstrings = this.charstrings; |
| 19813 |
var glyphNames = ['.notdef'], glyphId; |
| 19814 |
for (glyphId = 0; glyphId < charstrings.length; glyphId++) { |
| 19815 |
glyphNames.push(charstrings[glyphId].glyphName); |
| 19816 |
} |
| 19817 |
var encoding = properties.builtInEncoding; |
| 19818 |
if (encoding) { |
| 19819 |
var builtInEncoding = {}; |
| 19820 |
for (var charCode in encoding) { |
| 19821 |
glyphId = glyphNames.indexOf(encoding[charCode]); |
| 19822 |
if (glyphId >= 0) { |
| 19823 |
builtInEncoding[charCode] = glyphId; |
| 19824 |
} |
| 19825 |
} |
| 19826 |
} |
| 19827 |
|
| 19828 |
return type1FontGlyphMapping(properties, builtInEncoding, glyphNames); |
| 19829 |
}, |
| 19830 |
|
| 19831 |
getSeacs: function Type1Font_getSeacs(charstrings) { |
| 19832 |
var i, ii; |
| 19833 |
var seacMap = []; |
| 19834 |
for (i = 0, ii = charstrings.length; i < ii; i++) { |
| 19835 |
var charstring = charstrings[i]; |
| 19836 |
if (charstring.seac) { |
| 19837 |
// Offset by 1 for .notdef |
| 19838 |
seacMap[i + 1] = charstring.seac; |
| 19839 |
} |
| 19840 |
} |
| 19841 |
return seacMap; |
| 19842 |
}, |
| 19843 |
|
| 19844 |
getType2Charstrings: function Type1Font_getType2Charstrings( |
| 19845 |
type1Charstrings) { |
| 19846 |
var type2Charstrings = []; |
| 19847 |
for (var i = 0, ii = type1Charstrings.length; i < ii; i++) { |
| 19848 |
type2Charstrings.push(type1Charstrings[i].charstring); |
| 19849 |
} |
| 19850 |
return type2Charstrings; |
| 19851 |
}, |
| 19852 |
|
| 19853 |
getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) { |
| 19854 |
var bias = 0; |
| 19855 |
var count = type1Subrs.length; |
| 19856 |
if (count < 1133) { |
| 19857 |
bias = 107; |
| 19858 |
} else if (count < 33769) { |
| 19859 |
bias = 1131; |
| 19860 |
} else { |
| 19861 |
bias = 32768; |
| 19862 |
} |
| 19863 |
|
| 19864 |
// Add a bunch of empty subrs to deal with the Type2 bias |
| 19865 |
var type2Subrs = []; |
| 19866 |
var i; |
| 19867 |
for (i = 0; i < bias; i++) { |
| 19868 |
type2Subrs.push([0x0B]); |
| 19869 |
} |
| 19870 |
|
| 19871 |
for (i = 0; i < count; i++) { |
| 19872 |
type2Subrs.push(type1Subrs[i]); |
| 19873 |
} |
| 19874 |
|
| 19875 |
return type2Subrs; |
| 19876 |
}, |
| 19877 |
|
| 19878 |
wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) { |
| 19879 |
var cff = new CFF(); |
| 19880 |
cff.header = new CFFHeader(1, 0, 4, 4); |
| 19881 |
|
| 19882 |
cff.names = [name]; |
| 19883 |
|
| 19884 |
var topDict = new CFFTopDict(); |
| 19885 |
// CFF strings IDs 0...390 are predefined names, so refering |
| 19886 |
// to entries in our own String INDEX starts at SID 391. |
| 19887 |
topDict.setByName('version', 391); |
| 19888 |
topDict.setByName('Notice', 392); |
| 19889 |
topDict.setByName('FullName', 393); |
| 19890 |
topDict.setByName('FamilyName', 394); |
| 19891 |
topDict.setByName('Weight', 395); |
| 19892 |
topDict.setByName('Encoding', null); // placeholder |
| 19893 |
topDict.setByName('FontMatrix', properties.fontMatrix); |
| 19894 |
topDict.setByName('FontBBox', properties.bbox); |
| 19895 |
topDict.setByName('charset', null); // placeholder |
| 19896 |
topDict.setByName('CharStrings', null); // placeholder |
| 19897 |
topDict.setByName('Private', null); // placeholder |
| 19898 |
cff.topDict = topDict; |
| 19899 |
|
| 19900 |
var strings = new CFFStrings(); |
| 19901 |
strings.add('Version 0.11'); // Version |
| 19902 |
strings.add('See original notice'); // Notice |
| 19903 |
strings.add(name); // FullName |
| 19904 |
strings.add(name); // FamilyName |
| 19905 |
strings.add('Medium'); // Weight |
| 19906 |
cff.strings = strings; |
| 19907 |
|
| 19908 |
cff.globalSubrIndex = new CFFIndex(); |
| 19909 |
|
| 19910 |
var count = glyphs.length; |
| 19911 |
var charsetArray = [0]; |
| 19912 |
var i, ii; |
| 19913 |
for (i = 0; i < count; i++) { |
| 19914 |
var index = CFFStandardStrings.indexOf(charstrings[i].glyphName); |
| 19915 |
// TODO: Insert the string and correctly map it. Previously it was |
| 19916 |
// thought mapping names that aren't in the standard strings to .notdef |
| 19917 |
// was fine, however in issue818 when mapping them all to .notdef the |
| 19918 |
// adieresis glyph no longer worked. |
| 19919 |
if (index === -1) { |
| 19920 |
index = 0; |
| 19921 |
} |
| 19922 |
charsetArray.push((index >> 8) & 0xff, index & 0xff); |
| 19923 |
} |
| 19924 |
cff.charset = new CFFCharset(false, 0, [], charsetArray); |
| 19925 |
|
| 19926 |
var charStringsIndex = new CFFIndex(); |
| 19927 |
charStringsIndex.add([0x8B, 0x0E]); // .notdef |
| 19928 |
for (i = 0; i < count; i++) { |
| 19929 |
charStringsIndex.add(glyphs[i]); |
| 19930 |
} |
| 19931 |
cff.charStrings = charStringsIndex; |
| 19932 |
|
| 19933 |
var privateDict = new CFFPrivateDict(); |
| 19934 |
privateDict.setByName('Subrs', null); // placeholder |
| 19935 |
var fields = [ |
| 19936 |
'BlueValues', |
| 19937 |
'OtherBlues', |
| 19938 |
'FamilyBlues', |
| 19939 |
'FamilyOtherBlues', |
| 19940 |
'StemSnapH', |
| 19941 |
'StemSnapV', |
| 19942 |
'BlueShift', |
| 19943 |
'BlueFuzz', |
| 19944 |
'BlueScale', |
| 19945 |
'LanguageGroup', |
| 19946 |
'ExpansionFactor', |
| 19947 |
'ForceBold', |
| 19948 |
'StdHW', |
| 19949 |
'StdVW' |
| 19950 |
]; |
| 19951 |
for (i = 0, ii = fields.length; i < ii; i++) { |
| 19952 |
var field = fields[i]; |
| 19953 |
if (!properties.privateData.hasOwnProperty(field)) { |
| 19954 |
continue; |
| 19955 |
} |
| 19956 |
var value = properties.privateData[field]; |
| 19957 |
if (isArray(value)) { |
| 19958 |
// All of the private dictionary array data in CFF must be stored as |
| 19959 |
// "delta-encoded" numbers. |
| 19960 |
for (var j = value.length - 1; j > 0; j--) { |
| 19961 |
value[j] -= value[j - 1]; // ... difference from previous value |
| 19962 |
} |
| 19963 |
} |
| 19964 |
privateDict.setByName(field, value); |
| 19965 |
} |
| 19966 |
cff.topDict.privateDict = privateDict; |
| 19967 |
|
| 19968 |
var subrIndex = new CFFIndex(); |
| 19969 |
for (i = 0, ii = subrs.length; i < ii; i++) { |
| 19970 |
subrIndex.add(subrs[i]); |
| 19971 |
} |
| 19972 |
privateDict.subrsIndex = subrIndex; |
| 19973 |
|
| 19974 |
var compiler = new CFFCompiler(cff); |
| 19975 |
return compiler.compile(); |
| 19976 |
} |
| 19977 |
}; |
| 19978 |
|
| 19979 |
var CFFFont = (function CFFFontClosure() { |
| 19980 |
function CFFFont(file, properties) { |
| 19981 |
this.properties = properties; |
| 19982 |
|
| 19983 |
var parser = new CFFParser(file, properties); |
| 19984 |
this.cff = parser.parse(); |
| 19985 |
var compiler = new CFFCompiler(this.cff); |
| 19986 |
this.seacs = this.cff.seacs; |
| 19987 |
try { |
| 19988 |
this.data = compiler.compile(); |
| 19989 |
} catch (e) { |
| 19990 |
warn('Failed to compile font ' + properties.loadedName); |
| 19991 |
// There may have just been an issue with the compiler, set the data |
| 19992 |
// anyway and hope the font loaded. |
| 19993 |
this.data = file; |
| 19994 |
} |
| 19995 |
} |
| 19996 |
|
| 19997 |
CFFFont.prototype = { |
| 19998 |
get numGlyphs() { |
| 19999 |
return this.cff.charStrings.count; |
| 20000 |
}, |
| 20001 |
getCharset: function CFFFont_getCharset() { |
| 20002 |
return this.cff.charset.charset; |
| 20003 |
}, |
| 20004 |
getGlyphMapping: function CFFFont_getGlyphMapping() { |
| 20005 |
var cff = this.cff; |
| 20006 |
var properties = this.properties; |
| 20007 |
var charsets = cff.charset.charset; |
| 20008 |
var charCodeToGlyphId; |
| 20009 |
var glyphId; |
| 20010 |
|
| 20011 |
if (properties.composite) { |
| 20012 |
charCodeToGlyphId = Object.create(null); |
| 20013 |
if (cff.isCIDFont) { |
| 20014 |
// If the font is actually a CID font then we should use the charset |
| 20015 |
// to map CIDs to GIDs. |
| 20016 |
for (glyphId = 0; glyphId < charsets.length; glyphId++) { |
| 20017 |
var cid = charsets[glyphId]; |
| 20018 |
var charCode = properties.cMap.charCodeOf(cid); |
| 20019 |
charCodeToGlyphId[charCode] = glyphId; |
| 20020 |
} |
| 20021 |
} else { |
| 20022 |
// If it is NOT actually a CID font then CIDs should be mapped |
| 20023 |
// directly to GIDs. |
| 20024 |
for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) { |
| 20025 |
charCodeToGlyphId[glyphId] = glyphId; |
| 20026 |
} |
| 20027 |
} |
| 20028 |
return charCodeToGlyphId; |
| 20029 |
} |
| 20030 |
|
| 20031 |
var encoding = cff.encoding ? cff.encoding.encoding : null; |
| 20032 |
charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets); |
| 20033 |
return charCodeToGlyphId; |
| 20034 |
} |
| 20035 |
}; |
| 20036 |
|
| 20037 |
return CFFFont; |
| 20038 |
})(); |
| 20039 |
|
| 20040 |
var CFFParser = (function CFFParserClosure() { |
| 20041 |
var CharstringValidationData = [ |
| 20042 |
null, |
| 20043 |
{ id: 'hstem', min: 2, stackClearing: true, stem: true }, |
| 20044 |
null, |
| 20045 |
{ id: 'vstem', min: 2, stackClearing: true, stem: true }, |
| 20046 |
{ id: 'vmoveto', min: 1, stackClearing: true }, |
| 20047 |
{ id: 'rlineto', min: 2, resetStack: true }, |
| 20048 |
{ id: 'hlineto', min: 1, resetStack: true }, |
| 20049 |
{ id: 'vlineto', min: 1, resetStack: true }, |
| 20050 |
{ id: 'rrcurveto', min: 6, resetStack: true }, |
| 20051 |
null, |
| 20052 |
{ id: 'callsubr', min: 1, undefStack: true }, |
| 20053 |
{ id: 'return', min: 0, undefStack: true }, |
| 20054 |
null, // 12 |
| 20055 |
null, |
| 20056 |
{ id: 'endchar', min: 0, stackClearing: true }, |
| 20057 |
null, |
| 20058 |
null, |
| 20059 |
null, |
| 20060 |
{ id: 'hstemhm', min: 2, stackClearing: true, stem: true }, |
| 20061 |
{ id: 'hintmask', min: 0, stackClearing: true }, |
| 20062 |
{ id: 'cntrmask', min: 0, stackClearing: true }, |
| 20063 |
{ id: 'rmoveto', min: 2, stackClearing: true }, |
| 20064 |
{ id: 'hmoveto', min: 1, stackClearing: true }, |
| 20065 |
{ id: 'vstemhm', min: 2, stackClearing: true, stem: true }, |
| 20066 |
{ id: 'rcurveline', min: 8, resetStack: true }, |
| 20067 |
{ id: 'rlinecurve', min: 8, resetStack: true }, |
| 20068 |
{ id: 'vvcurveto', min: 4, resetStack: true }, |
| 20069 |
{ id: 'hhcurveto', min: 4, resetStack: true }, |
| 20070 |
null, // shortint |
| 20071 |
{ id: 'callgsubr', min: 1, undefStack: true }, |
| 20072 |
{ id: 'vhcurveto', min: 4, resetStack: true }, |
| 20073 |
{ id: 'hvcurveto', min: 4, resetStack: true } |
| 20074 |
]; |
| 20075 |
var CharstringValidationData12 = [ |
| 20076 |
null, |
| 20077 |
null, |
| 20078 |
null, |
| 20079 |
{ id: 'and', min: 2, stackDelta: -1 }, |
| 20080 |
{ id: 'or', min: 2, stackDelta: -1 }, |
| 20081 |
{ id: 'not', min: 1, stackDelta: 0 }, |
| 20082 |
null, |
| 20083 |
null, |
| 20084 |
null, |
| 20085 |
{ id: 'abs', min: 1, stackDelta: 0 }, |
| 20086 |
{ id: 'add', min: 2, stackDelta: -1, |
| 20087 |
stackFn: function stack_div(stack, index) { |
| 20088 |
stack[index - 2] = stack[index - 2] + stack[index - 1]; |
| 20089 |
} |
| 20090 |
}, |
| 20091 |
{ id: 'sub', min: 2, stackDelta: -1, |
| 20092 |
stackFn: function stack_div(stack, index) { |
| 20093 |
stack[index - 2] = stack[index - 2] - stack[index - 1]; |
| 20094 |
} |
| 20095 |
}, |
| 20096 |
{ id: 'div', min: 2, stackDelta: -1, |
| 20097 |
stackFn: function stack_div(stack, index) { |
| 20098 |
stack[index - 2] = stack[index - 2] / stack[index - 1]; |
| 20099 |
} |
| 20100 |
}, |
| 20101 |
null, |
| 20102 |
{ id: 'neg', min: 1, stackDelta: 0, |
| 20103 |
stackFn: function stack_div(stack, index) { |
| 20104 |
stack[index - 1] = -stack[index - 1]; |
| 20105 |
} |
| 20106 |
}, |
| 20107 |
{ id: 'eq', min: 2, stackDelta: -1 }, |
| 20108 |
null, |
| 20109 |
null, |
| 20110 |
{ id: 'drop', min: 1, stackDelta: -1 }, |
| 20111 |
null, |
| 20112 |
{ id: 'put', min: 2, stackDelta: -2 }, |
| 20113 |
{ id: 'get', min: 1, stackDelta: 0 }, |
| 20114 |
{ id: 'ifelse', min: 4, stackDelta: -3 }, |
| 20115 |
{ id: 'random', min: 0, stackDelta: 1 }, |
| 20116 |
{ id: 'mul', min: 2, stackDelta: -1, |
| 20117 |
stackFn: function stack_div(stack, index) { |
| 20118 |
stack[index - 2] = stack[index - 2] * stack[index - 1]; |
| 20119 |
} |
| 20120 |
}, |
| 20121 |
null, |
| 20122 |
{ id: 'sqrt', min: 1, stackDelta: 0 }, |
| 20123 |
{ id: 'dup', min: 1, stackDelta: 1 }, |
| 20124 |
{ id: 'exch', min: 2, stackDelta: 0 }, |
| 20125 |
{ id: 'index', min: 2, stackDelta: 0 }, |
| 20126 |
{ id: 'roll', min: 3, stackDelta: -2 }, |
| 20127 |
null, |
| 20128 |
null, |
| 20129 |
null, |
| 20130 |
{ id: 'hflex', min: 7, resetStack: true }, |
| 20131 |
{ id: 'flex', min: 13, resetStack: true }, |
| 20132 |
{ id: 'hflex1', min: 9, resetStack: true }, |
| 20133 |
{ id: 'flex1', min: 11, resetStack: true } |
| 20134 |
]; |
| 20135 |
|
| 20136 |
function CFFParser(file, properties) { |
| 20137 |
this.bytes = file.getBytes(); |
| 20138 |
this.properties = properties; |
| 20139 |
} |
| 20140 |
CFFParser.prototype = { |
| 20141 |
parse: function CFFParser_parse() { |
| 20142 |
var properties = this.properties; |
| 20143 |
var cff = new CFF(); |
| 20144 |
this.cff = cff; |
| 20145 |
|
| 20146 |
// The first five sections must be in order, all the others are reached |
| 20147 |
// via offsets contained in one of the below. |
| 20148 |
var header = this.parseHeader(); |
| 20149 |
var nameIndex = this.parseIndex(header.endPos); |
| 20150 |
var topDictIndex = this.parseIndex(nameIndex.endPos); |
| 20151 |
var stringIndex = this.parseIndex(topDictIndex.endPos); |
| 20152 |
var globalSubrIndex = this.parseIndex(stringIndex.endPos); |
| 20153 |
|
| 20154 |
var topDictParsed = this.parseDict(topDictIndex.obj.get(0)); |
| 20155 |
var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings); |
| 20156 |
|
| 20157 |
cff.header = header.obj; |
| 20158 |
cff.names = this.parseNameIndex(nameIndex.obj); |
| 20159 |
cff.strings = this.parseStringIndex(stringIndex.obj); |
| 20160 |
cff.topDict = topDict; |
| 20161 |
cff.globalSubrIndex = globalSubrIndex.obj; |
| 20162 |
|
| 20163 |
this.parsePrivateDict(cff.topDict); |
| 20164 |
|
| 20165 |
cff.isCIDFont = topDict.hasName('ROS'); |
| 20166 |
|
| 20167 |
var charStringOffset = topDict.getByName('CharStrings'); |
| 20168 |
var charStringsAndSeacs = this.parseCharStrings(charStringOffset); |
| 20169 |
cff.charStrings = charStringsAndSeacs.charStrings; |
| 20170 |
cff.seacs = charStringsAndSeacs.seacs; |
| 20171 |
cff.widths = charStringsAndSeacs.widths; |
| 20172 |
|
| 20173 |
var fontMatrix = topDict.getByName('FontMatrix'); |
| 20174 |
if (fontMatrix) { |
| 20175 |
properties.fontMatrix = fontMatrix; |
| 20176 |
} |
| 20177 |
|
| 20178 |
var fontBBox = topDict.getByName('FontBBox'); |
| 20179 |
if (fontBBox) { |
| 20180 |
// adjusting ascent/descent |
| 20181 |
properties.ascent = fontBBox[3]; |
| 20182 |
properties.descent = fontBBox[1]; |
| 20183 |
properties.ascentScaled = true; |
| 20184 |
} |
| 20185 |
|
| 20186 |
var charset, encoding; |
| 20187 |
if (cff.isCIDFont) { |
| 20188 |
var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj; |
| 20189 |
for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) { |
| 20190 |
var dictRaw = fdArrayIndex.get(i); |
| 20191 |
var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), |
| 20192 |
cff.strings); |
| 20193 |
this.parsePrivateDict(fontDict); |
| 20194 |
cff.fdArray.push(fontDict); |
| 20195 |
} |
| 20196 |
// cid fonts don't have an encoding |
| 20197 |
encoding = null; |
| 20198 |
charset = this.parseCharsets(topDict.getByName('charset'), |
| 20199 |
cff.charStrings.count, cff.strings, true); |
| 20200 |
cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), |
| 20201 |
cff.charStrings.count); |
| 20202 |
} else { |
| 20203 |
charset = this.parseCharsets(topDict.getByName('charset'), |
| 20204 |
cff.charStrings.count, cff.strings, false); |
| 20205 |
encoding = this.parseEncoding(topDict.getByName('Encoding'), |
| 20206 |
properties, |
| 20207 |
cff.strings, charset.charset); |
| 20208 |
} |
| 20209 |
cff.charset = charset; |
| 20210 |
cff.encoding = encoding; |
| 20211 |
|
| 20212 |
return cff; |
| 20213 |
}, |
| 20214 |
parseHeader: function CFFParser_parseHeader() { |
| 20215 |
var bytes = this.bytes; |
| 20216 |
var bytesLength = bytes.length; |
| 20217 |
var offset = 0; |
| 20218 |
|
| 20219 |
// Prevent an infinite loop, by checking that the offset is within the |
| 20220 |
// bounds of the bytes array. Necessary in empty, or invalid, font files. |
| 20221 |
while (offset < bytesLength && bytes[offset] !== 1) { |
| 20222 |
++offset; |
| 20223 |
} |
| 20224 |
if (offset >= bytesLength) { |
| 20225 |
error('Invalid CFF header'); |
| 20226 |
} else if (offset !== 0) { |
| 20227 |
info('cff data is shifted'); |
| 20228 |
bytes = bytes.subarray(offset); |
| 20229 |
this.bytes = bytes; |
| 20230 |
} |
| 20231 |
var major = bytes[0]; |
| 20232 |
var minor = bytes[1]; |
| 20233 |
var hdrSize = bytes[2]; |
| 20234 |
var offSize = bytes[3]; |
| 20235 |
var header = new CFFHeader(major, minor, hdrSize, offSize); |
| 20236 |
return { obj: header, endPos: hdrSize }; |
| 20237 |
}, |
| 20238 |
parseDict: function CFFParser_parseDict(dict) { |
| 20239 |
var pos = 0; |
| 20240 |
|
| 20241 |
function parseOperand() { |
| 20242 |
var value = dict[pos++]; |
| 20243 |
if (value === 30) { |
| 20244 |
return parseFloatOperand(pos); |
| 20245 |
} else if (value === 28) { |
| 20246 |
value = dict[pos++]; |
| 20247 |
value = ((value << 24) | (dict[pos++] << 16)) >> 16; |
| 20248 |
return value; |
| 20249 |
} else if (value === 29) { |
| 20250 |
value = dict[pos++]; |
| 20251 |
value = (value << 8) | dict[pos++]; |
| 20252 |
value = (value << 8) | dict[pos++]; |
| 20253 |
value = (value << 8) | dict[pos++]; |
| 20254 |
return value; |
| 20255 |
} else if (value >= 32 && value <= 246) { |
| 20256 |
return value - 139; |
| 20257 |
} else if (value >= 247 && value <= 250) { |
| 20258 |
return ((value - 247) * 256) + dict[pos++] + 108; |
| 20259 |
} else if (value >= 251 && value <= 254) { |
| 20260 |
return -((value - 251) * 256) - dict[pos++] - 108; |
| 20261 |
} else { |
| 20262 |
error('255 is not a valid DICT command'); |
| 20263 |
} |
| 20264 |
return -1; |
| 20265 |
} |
| 20266 |
|
| 20267 |
function parseFloatOperand() { |
| 20268 |
var str = ''; |
| 20269 |
var eof = 15; |
| 20270 |
var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', |
| 20271 |
'9', '.', 'E', 'E-', null, '-']; |
| 20272 |
var length = dict.length; |
| 20273 |
while (pos < length) { |
| 20274 |
var b = dict[pos++]; |
| 20275 |
var b1 = b >> 4; |
| 20276 |
var b2 = b & 15; |
| 20277 |
|
| 20278 |
if (b1 === eof) { |
| 20279 |
break; |
| 20280 |
} |
| 20281 |
str += lookup[b1]; |
| 20282 |
|
| 20283 |
if (b2 === eof) { |
| 20284 |
break; |
| 20285 |
} |
| 20286 |
str += lookup[b2]; |
| 20287 |
} |
| 20288 |
return parseFloat(str); |
| 20289 |
} |
| 20290 |
|
| 20291 |
var operands = []; |
| 20292 |
var entries = []; |
| 20293 |
|
| 20294 |
pos = 0; |
| 20295 |
var end = dict.length; |
| 20296 |
while (pos < end) { |
| 20297 |
var b = dict[pos]; |
| 20298 |
if (b <= 21) { |
| 20299 |
if (b === 12) { |
| 20300 |
b = (b << 8) | dict[++pos]; |
| 20301 |
} |
| 20302 |
entries.push([b, operands]); |
| 20303 |
operands = []; |
| 20304 |
++pos; |
| 20305 |
} else { |
| 20306 |
operands.push(parseOperand()); |
| 20307 |
} |
| 20308 |
} |
| 20309 |
return entries; |
| 20310 |
}, |
| 20311 |
parseIndex: function CFFParser_parseIndex(pos) { |
| 20312 |
var cffIndex = new CFFIndex(); |
| 20313 |
var bytes = this.bytes; |
| 20314 |
var count = (bytes[pos++] << 8) | bytes[pos++]; |
| 20315 |
var offsets = []; |
| 20316 |
var end = pos; |
| 20317 |
var i, ii; |
| 20318 |
|
| 20319 |
if (count !== 0) { |
| 20320 |
var offsetSize = bytes[pos++]; |
| 20321 |
// add 1 for offset to determine size of last object |
| 20322 |
var startPos = pos + ((count + 1) * offsetSize) - 1; |
| 20323 |
|
| 20324 |
for (i = 0, ii = count + 1; i < ii; ++i) { |
| 20325 |
var offset = 0; |
| 20326 |
for (var j = 0; j < offsetSize; ++j) { |
| 20327 |
offset <<= 8; |
| 20328 |
offset += bytes[pos++]; |
| 20329 |
} |
| 20330 |
offsets.push(startPos + offset); |
| 20331 |
} |
| 20332 |
end = offsets[count]; |
| 20333 |
} |
| 20334 |
for (i = 0, ii = offsets.length - 1; i < ii; ++i) { |
| 20335 |
var offsetStart = offsets[i]; |
| 20336 |
var offsetEnd = offsets[i + 1]; |
| 20337 |
cffIndex.add(bytes.subarray(offsetStart, offsetEnd)); |
| 20338 |
} |
| 20339 |
return {obj: cffIndex, endPos: end}; |
| 20340 |
}, |
| 20341 |
parseNameIndex: function CFFParser_parseNameIndex(index) { |
| 20342 |
var names = []; |
| 20343 |
for (var i = 0, ii = index.count; i < ii; ++i) { |
| 20344 |
var name = index.get(i); |
| 20345 |
// OTS doesn't allow names to be over 127 characters. |
| 20346 |
var length = Math.min(name.length, 127); |
| 20347 |
var data = []; |
| 20348 |
// OTS also only permits certain characters in the name. |
| 20349 |
for (var j = 0; j < length; ++j) { |
| 20350 |
var c = name[j]; |
| 20351 |
if (j === 0 && c === 0) { |
| 20352 |
data[j] = c; |
| 20353 |
continue; |
| 20354 |
} |
| 20355 |
if ((c < 33 || c > 126) || c === 91 /* [ */ || c === 93 /* ] */ || |
| 20356 |
c === 40 /* ( */ || c === 41 /* ) */ || c === 123 /* { */ || |
| 20357 |
c === 125 /* } */ || c === 60 /* < */ || c === 62 /* > */ || |
| 20358 |
c === 47 /* / */ || c === 37 /* % */ || c === 35 /* # */) { |
| 20359 |
data[j] = 95; |
| 20360 |
continue; |
| 20361 |
} |
| 20362 |
data[j] = c; |
| 20363 |
} |
| 20364 |
names.push(bytesToString(data)); |
| 20365 |
} |
| 20366 |
return names; |
| 20367 |
}, |
| 20368 |
parseStringIndex: function CFFParser_parseStringIndex(index) { |
| 20369 |
var strings = new CFFStrings(); |
| 20370 |
for (var i = 0, ii = index.count; i < ii; ++i) { |
| 20371 |
var data = index.get(i); |
| 20372 |
strings.add(bytesToString(data)); |
| 20373 |
} |
| 20374 |
return strings; |
| 20375 |
}, |
| 20376 |
createDict: function CFFParser_createDict(Type, dict, strings) { |
| 20377 |
var cffDict = new Type(strings); |
| 20378 |
for (var i = 0, ii = dict.length; i < ii; ++i) { |
| 20379 |
var pair = dict[i]; |
| 20380 |
var key = pair[0]; |
| 20381 |
var value = pair[1]; |
| 20382 |
cffDict.setByKey(key, value); |
| 20383 |
} |
| 20384 |
return cffDict; |
| 20385 |
}, |
| 20386 |
parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) { |
| 20387 |
var charStrings = this.parseIndex(charStringOffset).obj; |
| 20388 |
var seacs = []; |
| 20389 |
var widths = []; |
| 20390 |
var count = charStrings.count; |
| 20391 |
for (var i = 0; i < count; i++) { |
| 20392 |
var charstring = charStrings.get(i); |
| 20393 |
|
| 20394 |
var stackSize = 0; |
| 20395 |
var stack = []; |
| 20396 |
var undefStack = true; |
| 20397 |
var hints = 0; |
| 20398 |
var valid = true; |
| 20399 |
var data = charstring; |
| 20400 |
var length = data.length; |
| 20401 |
var firstStackClearing = true; |
| 20402 |
for (var j = 0; j < length;) { |
| 20403 |
var value = data[j++]; |
| 20404 |
var validationCommand = null; |
| 20405 |
if (value === 12) { |
| 20406 |
var q = data[j++]; |
| 20407 |
if (q === 0) { |
| 20408 |
// The CFF specification state that the 'dotsection' command |
| 20409 |
// (12, 0) is deprecated and treated as a no-op, but all Type2 |
| 20410 |
// charstrings processors should support them. Unfortunately |
| 20411 |
// the font sanitizer don't. As a workaround the sequence (12, 0) |
| 20412 |
// is replaced by a useless (0, hmoveto). |
| 20413 |
data[j - 2] = 139; |
| 20414 |
data[j - 1] = 22; |
| 20415 |
stackSize = 0; |
| 20416 |
} else { |
| 20417 |
validationCommand = CharstringValidationData12[q]; |
| 20418 |
} |
| 20419 |
} else if (value === 28) { // number (16 bit) |
| 20420 |
stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16; |
| 20421 |
j += 2; |
| 20422 |
stackSize++; |
| 20423 |
} else if (value === 14) { |
| 20424 |
if (stackSize >= 4) { |
| 20425 |
stackSize -= 4; |
| 20426 |
if (SEAC_ANALYSIS_ENABLED) { |
| 20427 |
seacs[i] = stack.slice(stackSize, stackSize + 4); |
| 20428 |
valid = false; |
| 20429 |
} |
| 20430 |
} |
| 20431 |
validationCommand = CharstringValidationData[value]; |
| 20432 |
} else if (value >= 32 && value <= 246) { // number |
| 20433 |
stack[stackSize] = value - 139; |
| 20434 |
stackSize++; |
| 20435 |
} else if (value >= 247 && value <= 254) { // number (+1 bytes) |
| 20436 |
stack[stackSize] = (value < 251 ? |
| 20437 |
((value - 247) << 8) + data[j] + 108 : |
| 20438 |
-((value - 251) << 8) - data[j] - 108); |
| 20439 |
j++; |
| 20440 |
stackSize++; |
| 20441 |
} else if (value === 255) { // number (32 bit) |
| 20442 |
stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) | |
| 20443 |
(data[j + 2] << 8) | data[j + 3]) / 65536; |
| 20444 |
j += 4; |
| 20445 |
stackSize++; |
| 20446 |
} else if (value === 19 || value === 20) { |
| 20447 |
hints += stackSize >> 1; |
| 20448 |
j += (hints + 7) >> 3; // skipping right amount of hints flag data |
| 20449 |
stackSize %= 2; |
| 20450 |
validationCommand = CharstringValidationData[value]; |
| 20451 |
} else { |
| 20452 |
validationCommand = CharstringValidationData[value]; |
| 20453 |
} |
| 20454 |
if (validationCommand) { |
| 20455 |
if (validationCommand.stem) { |
| 20456 |
hints += stackSize >> 1; |
| 20457 |
} |
| 20458 |
if ('min' in validationCommand) { |
| 20459 |
if (!undefStack && stackSize < validationCommand.min) { |
| 20460 |
warn('Not enough parameters for ' + validationCommand.id + |
| 20461 |
'; actual: ' + stackSize + |
| 20462 |
', expected: ' + validationCommand.min); |
| 20463 |
valid = false; |
| 20464 |
break; |
| 20465 |
} |
| 20466 |
} |
| 20467 |
if (firstStackClearing && validationCommand.stackClearing) { |
| 20468 |
firstStackClearing = false; |
| 20469 |
// the optional character width can be found before the first |
| 20470 |
// stack-clearing command arguments |
| 20471 |
stackSize -= validationCommand.min; |
| 20472 |
if (stackSize >= 2 && validationCommand.stem) { |
| 20473 |
// there are even amount of arguments for stem commands |
| 20474 |
stackSize %= 2; |
| 20475 |
} else if (stackSize > 1) { |
| 20476 |
warn('Found too many parameters for stack-clearing command'); |
| 20477 |
} |
| 20478 |
if (stackSize > 0 && stack[stackSize - 1] >= 0) { |
| 20479 |
widths[i] = stack[stackSize - 1]; |
| 20480 |
} |
| 20481 |
} |
| 20482 |
if ('stackDelta' in validationCommand) { |
| 20483 |
if ('stackFn' in validationCommand) { |
| 20484 |
validationCommand.stackFn(stack, stackSize); |
| 20485 |
} |
| 20486 |
stackSize += validationCommand.stackDelta; |
| 20487 |
} else if (validationCommand.stackClearing) { |
| 20488 |
stackSize = 0; |
| 20489 |
} else if (validationCommand.resetStack) { |
| 20490 |
stackSize = 0; |
| 20491 |
undefStack = false; |
| 20492 |
} else if (validationCommand.undefStack) { |
| 20493 |
stackSize = 0; |
| 20494 |
undefStack = true; |
| 20495 |
firstStackClearing = false; |
| 20496 |
} |
| 20497 |
} |
| 20498 |
} |
| 20499 |
if (!valid) { |
| 20500 |
// resetting invalid charstring to single 'endchar' |
| 20501 |
charStrings.set(i, new Uint8Array([14])); |
| 20502 |
} |
| 20503 |
} |
| 20504 |
return { charStrings: charStrings, seacs: seacs, widths: widths }; |
| 20505 |
}, |
| 20506 |
emptyPrivateDictionary: |
| 20507 |
function CFFParser_emptyPrivateDictionary(parentDict) { |
| 20508 |
var privateDict = this.createDict(CFFPrivateDict, [], |
| 20509 |
parentDict.strings); |
| 20510 |
parentDict.setByKey(18, [0, 0]); |
| 20511 |
parentDict.privateDict = privateDict; |
| 20512 |
}, |
| 20513 |
parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) { |
| 20514 |
// no private dict, do nothing |
| 20515 |
if (!parentDict.hasName('Private')) { |
| 20516 |
this.emptyPrivateDictionary(parentDict); |
| 20517 |
return; |
| 20518 |
} |
| 20519 |
var privateOffset = parentDict.getByName('Private'); |
| 20520 |
// make sure the params are formatted correctly |
| 20521 |
if (!isArray(privateOffset) || privateOffset.length !== 2) { |
| 20522 |
parentDict.removeByName('Private'); |
| 20523 |
return; |
| 20524 |
} |
| 20525 |
var size = privateOffset[0]; |
| 20526 |
var offset = privateOffset[1]; |
| 20527 |
// remove empty dicts or ones that refer to invalid location |
| 20528 |
if (size === 0 || offset >= this.bytes.length) { |
| 20529 |
this.emptyPrivateDictionary(parentDict); |
| 20530 |
return; |
| 20531 |
} |
| 20532 |
|
| 20533 |
var privateDictEnd = offset + size; |
| 20534 |
var dictData = this.bytes.subarray(offset, privateDictEnd); |
| 20535 |
var dict = this.parseDict(dictData); |
| 20536 |
var privateDict = this.createDict(CFFPrivateDict, dict, |
| 20537 |
parentDict.strings); |
| 20538 |
parentDict.privateDict = privateDict; |
| 20539 |
|
| 20540 |
// Parse the Subrs index also since it's relative to the private dict. |
| 20541 |
if (!privateDict.getByName('Subrs')) { |
| 20542 |
return; |
| 20543 |
} |
| 20544 |
var subrsOffset = privateDict.getByName('Subrs'); |
| 20545 |
var relativeOffset = offset + subrsOffset; |
| 20546 |
// Validate the offset. |
| 20547 |
if (subrsOffset === 0 || relativeOffset >= this.bytes.length) { |
| 20548 |
this.emptyPrivateDictionary(parentDict); |
| 20549 |
return; |
| 20550 |
} |
| 20551 |
var subrsIndex = this.parseIndex(relativeOffset); |
| 20552 |
privateDict.subrsIndex = subrsIndex.obj; |
| 20553 |
}, |
| 20554 |
parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) { |
| 20555 |
if (pos === 0) { |
| 20556 |
return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, |
| 20557 |
ISOAdobeCharset); |
| 20558 |
} else if (pos === 1) { |
| 20559 |
return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, |
| 20560 |
ExpertCharset); |
| 20561 |
} else if (pos === 2) { |
| 20562 |
return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, |
| 20563 |
ExpertSubsetCharset); |
| 20564 |
} |
| 20565 |
|
| 20566 |
var bytes = this.bytes; |
| 20567 |
var start = pos; |
| 20568 |
var format = bytes[pos++]; |
| 20569 |
var charset = ['.notdef']; |
| 20570 |
var id, count, i; |
| 20571 |
|
| 20572 |
// subtract 1 for the .notdef glyph |
| 20573 |
length -= 1; |
| 20574 |
|
| 20575 |
switch (format) { |
| 20576 |
case 0: |
| 20577 |
for (i = 0; i < length; i++) { |
| 20578 |
id = (bytes[pos++] << 8) | bytes[pos++]; |
| 20579 |
charset.push(cid ? id : strings.get(id)); |
| 20580 |
} |
| 20581 |
break; |
| 20582 |
case 1: |
| 20583 |
while (charset.length <= length) { |
| 20584 |
id = (bytes[pos++] << 8) | bytes[pos++]; |
| 20585 |
count = bytes[pos++]; |
| 20586 |
for (i = 0; i <= count; i++) { |
| 20587 |
charset.push(cid ? id++ : strings.get(id++)); |
| 20588 |
} |
| 20589 |
} |
| 20590 |
break; |
| 20591 |
case 2: |
| 20592 |
while (charset.length <= length) { |
| 20593 |
id = (bytes[pos++] << 8) | bytes[pos++]; |
| 20594 |
count = (bytes[pos++] << 8) | bytes[pos++]; |
| 20595 |
for (i = 0; i <= count; i++) { |
| 20596 |
charset.push(cid ? id++ : strings.get(id++)); |
| 20597 |
} |
| 20598 |
} |
| 20599 |
break; |
| 20600 |
default: |
| 20601 |
error('Unknown charset format'); |
| 20602 |
} |
| 20603 |
// Raw won't be needed if we actually compile the charset. |
| 20604 |
var end = pos; |
| 20605 |
var raw = bytes.subarray(start, end); |
| 20606 |
|
| 20607 |
return new CFFCharset(false, format, charset, raw); |
| 20608 |
}, |
| 20609 |
parseEncoding: function CFFParser_parseEncoding(pos, |
| 20610 |
properties, |
| 20611 |
strings, |
| 20612 |
charset) { |
| 20613 |
var encoding = {}; |
| 20614 |
var bytes = this.bytes; |
| 20615 |
var predefined = false; |
| 20616 |
var hasSupplement = false; |
| 20617 |
var format, i, ii; |
| 20618 |
var raw = null; |
| 20619 |
|
| 20620 |
function readSupplement() { |
| 20621 |
var supplementsCount = bytes[pos++]; |
| 20622 |
for (i = 0; i < supplementsCount; i++) { |
| 20623 |
var code = bytes[pos++]; |
| 20624 |
var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff); |
| 20625 |
encoding[code] = charset.indexOf(strings.get(sid)); |
| 20626 |
} |
| 20627 |
} |
| 20628 |
|
| 20629 |
if (pos === 0 || pos === 1) { |
| 20630 |
predefined = true; |
| 20631 |
format = pos; |
| 20632 |
var baseEncoding = pos ? Encodings.ExpertEncoding : |
| 20633 |
Encodings.StandardEncoding; |
| 20634 |
for (i = 0, ii = charset.length; i < ii; i++) { |
| 20635 |
var index = baseEncoding.indexOf(charset[i]); |
| 20636 |
if (index !== -1) { |
| 20637 |
encoding[index] = i; |
| 20638 |
} |
| 20639 |
} |
| 20640 |
} else { |
| 20641 |
var dataStart = pos; |
| 20642 |
format = bytes[pos++]; |
| 20643 |
switch (format & 0x7f) { |
| 20644 |
case 0: |
| 20645 |
var glyphsCount = bytes[pos++]; |
| 20646 |
for (i = 1; i <= glyphsCount; i++) { |
| 20647 |
encoding[bytes[pos++]] = i; |
| 20648 |
} |
| 20649 |
break; |
| 20650 |
|
| 20651 |
case 1: |
| 20652 |
var rangesCount = bytes[pos++]; |
| 20653 |
var gid = 1; |
| 20654 |
for (i = 0; i < rangesCount; i++) { |
| 20655 |
var start = bytes[pos++]; |
| 20656 |
var left = bytes[pos++]; |
| 20657 |
for (var j = start; j <= start + left; j++) { |
| 20658 |
encoding[j] = gid++; |
| 20659 |
} |
| 20660 |
} |
| 20661 |
break; |
| 20662 |
|
| 20663 |
default: |
| 20664 |
error('Unknow encoding format: ' + format + ' in CFF'); |
| 20665 |
break; |
| 20666 |
} |
| 20667 |
var dataEnd = pos; |
| 20668 |
if (format & 0x80) { |
| 20669 |
// The font sanitizer does not support CFF encoding with a |
| 20670 |
// supplement, since the encoding is not really used to map |
| 20671 |
// between gid to glyph, let's overwrite what is declared in |
| 20672 |
// the top dictionary to let the sanitizer think the font use |
| 20673 |
// StandardEncoding, that's a lie but that's ok. |
| 20674 |
bytes[dataStart] &= 0x7f; |
| 20675 |
readSupplement(); |
| 20676 |
hasSupplement = true; |
| 20677 |
} |
| 20678 |
raw = bytes.subarray(dataStart, dataEnd); |
| 20679 |
} |
| 20680 |
format = format & 0x7f; |
| 20681 |
return new CFFEncoding(predefined, format, encoding, raw); |
| 20682 |
}, |
| 20683 |
parseFDSelect: function CFFParser_parseFDSelect(pos, length) { |
| 20684 |
var start = pos; |
| 20685 |
var bytes = this.bytes; |
| 20686 |
var format = bytes[pos++]; |
| 20687 |
var fdSelect = []; |
| 20688 |
var i; |
| 20689 |
|
| 20690 |
switch (format) { |
| 20691 |
case 0: |
| 20692 |
for (i = 0; i < length; ++i) { |
| 20693 |
var id = bytes[pos++]; |
| 20694 |
fdSelect.push(id); |
| 20695 |
} |
| 20696 |
break; |
| 20697 |
case 3: |
| 20698 |
var rangesCount = (bytes[pos++] << 8) | bytes[pos++]; |
| 20699 |
for (i = 0; i < rangesCount; ++i) { |
| 20700 |
var first = (bytes[pos++] << 8) | bytes[pos++]; |
| 20701 |
var fdIndex = bytes[pos++]; |
| 20702 |
var next = (bytes[pos] << 8) | bytes[pos + 1]; |
| 20703 |
for (var j = first; j < next; ++j) { |
| 20704 |
fdSelect.push(fdIndex); |
| 20705 |
} |
| 20706 |
} |
| 20707 |
// Advance past the sentinel(next). |
| 20708 |
pos += 2; |
| 20709 |
break; |
| 20710 |
default: |
| 20711 |
error('Unknown fdselect format ' + format); |
| 20712 |
break; |
| 20713 |
} |
| 20714 |
var end = pos; |
| 20715 |
return new CFFFDSelect(fdSelect, bytes.subarray(start, end)); |
| 20716 |
} |
| 20717 |
}; |
| 20718 |
return CFFParser; |
| 20719 |
})(); |
| 20720 |
|
| 20721 |
// Compact Font Format |
| 20722 |
var CFF = (function CFFClosure() { |
| 20723 |
function CFF() { |
| 20724 |
this.header = null; |
| 20725 |
this.names = []; |
| 20726 |
this.topDict = null; |
| 20727 |
this.strings = new CFFStrings(); |
| 20728 |
this.globalSubrIndex = null; |
| 20729 |
|
| 20730 |
// The following could really be per font, but since we only have one font |
| 20731 |
// store them here. |
| 20732 |
this.encoding = null; |
| 20733 |
this.charset = null; |
| 20734 |
this.charStrings = null; |
| 20735 |
this.fdArray = []; |
| 20736 |
this.fdSelect = null; |
| 20737 |
|
| 20738 |
this.isCIDFont = false; |
| 20739 |
} |
| 20740 |
return CFF; |
| 20741 |
})(); |
| 20742 |
|
| 20743 |
var CFFHeader = (function CFFHeaderClosure() { |
| 20744 |
function CFFHeader(major, minor, hdrSize, offSize) { |
| 20745 |
this.major = major; |
| 20746 |
this.minor = minor; |
| 20747 |
this.hdrSize = hdrSize; |
| 20748 |
this.offSize = offSize; |
| 20749 |
} |
| 20750 |
return CFFHeader; |
| 20751 |
})(); |
| 20752 |
|
| 20753 |
var CFFStrings = (function CFFStringsClosure() { |
| 20754 |
function CFFStrings() { |
| 20755 |
this.strings = []; |
| 20756 |
} |
| 20757 |
CFFStrings.prototype = { |
| 20758 |
get: function CFFStrings_get(index) { |
| 20759 |
if (index >= 0 && index <= 390) { |
| 20760 |
return CFFStandardStrings[index]; |
| 20761 |
} |
| 20762 |
if (index - 391 <= this.strings.length) { |
| 20763 |
return this.strings[index - 391]; |
| 20764 |
} |
| 20765 |
return CFFStandardStrings[0]; |
| 20766 |
}, |
| 20767 |
add: function CFFStrings_add(value) { |
| 20768 |
this.strings.push(value); |
| 20769 |
}, |
| 20770 |
get count() { |
| 20771 |
return this.strings.length; |
| 20772 |
} |
| 20773 |
}; |
| 20774 |
return CFFStrings; |
| 20775 |
})(); |
| 20776 |
|
| 20777 |
var CFFIndex = (function CFFIndexClosure() { |
| 20778 |
function CFFIndex() { |
| 20779 |
this.objects = []; |
| 20780 |
this.length = 0; |
| 20781 |
} |
| 20782 |
CFFIndex.prototype = { |
| 20783 |
add: function CFFIndex_add(data) { |
| 20784 |
this.length += data.length; |
| 20785 |
this.objects.push(data); |
| 20786 |
}, |
| 20787 |
set: function CFFIndex_set(index, data) { |
| 20788 |
this.length += data.length - this.objects[index].length; |
| 20789 |
this.objects[index] = data; |
| 20790 |
}, |
| 20791 |
get: function CFFIndex_get(index) { |
| 20792 |
return this.objects[index]; |
| 20793 |
}, |
| 20794 |
get count() { |
| 20795 |
return this.objects.length; |
| 20796 |
} |
| 20797 |
}; |
| 20798 |
return CFFIndex; |
| 20799 |
})(); |
| 20800 |
|
| 20801 |
var CFFDict = (function CFFDictClosure() { |
| 20802 |
function CFFDict(tables, strings) { |
| 20803 |
this.keyToNameMap = tables.keyToNameMap; |
| 20804 |
this.nameToKeyMap = tables.nameToKeyMap; |
| 20805 |
this.defaults = tables.defaults; |
| 20806 |
this.types = tables.types; |
| 20807 |
this.opcodes = tables.opcodes; |
| 20808 |
this.order = tables.order; |
| 20809 |
this.strings = strings; |
| 20810 |
this.values = {}; |
| 20811 |
} |
| 20812 |
CFFDict.prototype = { |
| 20813 |
// value should always be an array |
| 20814 |
setByKey: function CFFDict_setByKey(key, value) { |
| 20815 |
if (!(key in this.keyToNameMap)) { |
| 20816 |
return false; |
| 20817 |
} |
| 20818 |
// ignore empty values |
| 20819 |
if (value.length === 0) { |
| 20820 |
return true; |
| 20821 |
} |
| 20822 |
var type = this.types[key]; |
| 20823 |
// remove the array wrapping these types of values |
| 20824 |
if (type === 'num' || type === 'sid' || type === 'offset') { |
| 20825 |
value = value[0]; |
| 20826 |
} |
| 20827 |
this.values[key] = value; |
| 20828 |
return true; |
| 20829 |
}, |
| 20830 |
setByName: function CFFDict_setByName(name, value) { |
| 20831 |
if (!(name in this.nameToKeyMap)) { |
| 20832 |
error('Invalid dictionary name "' + name + '"'); |
| 20833 |
} |
| 20834 |
this.values[this.nameToKeyMap[name]] = value; |
| 20835 |
}, |
| 20836 |
hasName: function CFFDict_hasName(name) { |
| 20837 |
return this.nameToKeyMap[name] in this.values; |
| 20838 |
}, |
| 20839 |
getByName: function CFFDict_getByName(name) { |
| 20840 |
if (!(name in this.nameToKeyMap)) { |
| 20841 |
error('Invalid dictionary name "' + name + '"'); |
| 20842 |
} |
| 20843 |
var key = this.nameToKeyMap[name]; |
| 20844 |
if (!(key in this.values)) { |
| 20845 |
return this.defaults[key]; |
| 20846 |
} |
| 20847 |
return this.values[key]; |
| 20848 |
}, |
| 20849 |
removeByName: function CFFDict_removeByName(name) { |
| 20850 |
delete this.values[this.nameToKeyMap[name]]; |
| 20851 |
} |
| 20852 |
}; |
| 20853 |
CFFDict.createTables = function CFFDict_createTables(layout) { |
| 20854 |
var tables = { |
| 20855 |
keyToNameMap: {}, |
| 20856 |
nameToKeyMap: {}, |
| 20857 |
defaults: {}, |
| 20858 |
types: {}, |
| 20859 |
opcodes: {}, |
| 20860 |
order: [] |
| 20861 |
}; |
| 20862 |
for (var i = 0, ii = layout.length; i < ii; ++i) { |
| 20863 |
var entry = layout[i]; |
| 20864 |
var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0]; |
| 20865 |
tables.keyToNameMap[key] = entry[1]; |
| 20866 |
tables.nameToKeyMap[entry[1]] = key; |
| 20867 |
tables.types[key] = entry[2]; |
| 20868 |
tables.defaults[key] = entry[3]; |
| 20869 |
tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]]; |
| 20870 |
tables.order.push(key); |
| 20871 |
} |
| 20872 |
return tables; |
| 20873 |
}; |
| 20874 |
return CFFDict; |
| 20875 |
})(); |
| 20876 |
|
| 20877 |
var CFFTopDict = (function CFFTopDictClosure() { |
| 20878 |
var layout = [ |
| 20879 |
[[12, 30], 'ROS', ['sid', 'sid', 'num'], null], |
| 20880 |
[[12, 20], 'SyntheticBase', 'num', null], |
| 20881 |
[0, 'version', 'sid', null], |
| 20882 |
[1, 'Notice', 'sid', null], |
| 20883 |
[[12, 0], 'Copyright', 'sid', null], |
| 20884 |
[2, 'FullName', 'sid', null], |
| 20885 |
[3, 'FamilyName', 'sid', null], |
| 20886 |
[4, 'Weight', 'sid', null], |
| 20887 |
[[12, 1], 'isFixedPitch', 'num', 0], |
| 20888 |
[[12, 2], 'ItalicAngle', 'num', 0], |
| 20889 |
[[12, 3], 'UnderlinePosition', 'num', -100], |
| 20890 |
[[12, 4], 'UnderlineThickness', 'num', 50], |
| 20891 |
[[12, 5], 'PaintType', 'num', 0], |
| 20892 |
[[12, 6], 'CharstringType', 'num', 2], |
| 20893 |
[[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'], |
| 20894 |
[0.001, 0, 0, 0.001, 0, 0]], |
| 20895 |
[13, 'UniqueID', 'num', null], |
| 20896 |
[5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]], |
| 20897 |
[[12, 8], 'StrokeWidth', 'num', 0], |
| 20898 |
[14, 'XUID', 'array', null], |
| 20899 |
[15, 'charset', 'offset', 0], |
| 20900 |
[16, 'Encoding', 'offset', 0], |
| 20901 |
[17, 'CharStrings', 'offset', 0], |
| 20902 |
[18, 'Private', ['offset', 'offset'], null], |
| 20903 |
[[12, 21], 'PostScript', 'sid', null], |
| 20904 |
[[12, 22], 'BaseFontName', 'sid', null], |
| 20905 |
[[12, 23], 'BaseFontBlend', 'delta', null], |
| 20906 |
[[12, 31], 'CIDFontVersion', 'num', 0], |
| 20907 |
[[12, 32], 'CIDFontRevision', 'num', 0], |
| 20908 |
[[12, 33], 'CIDFontType', 'num', 0], |
| 20909 |
[[12, 34], 'CIDCount', 'num', 8720], |
| 20910 |
[[12, 35], 'UIDBase', 'num', null], |
| 20911 |
// XXX: CID Fonts on DirectWrite 6.1 only seem to work if FDSelect comes |
| 20912 |
// before FDArray. |
| 20913 |
[[12, 37], 'FDSelect', 'offset', null], |
| 20914 |
[[12, 36], 'FDArray', 'offset', null], |
| 20915 |
[[12, 38], 'FontName', 'sid', null] |
| 20916 |
]; |
| 20917 |
var tables = null; |
| 20918 |
function CFFTopDict(strings) { |
| 20919 |
if (tables === null) { |
| 20920 |
tables = CFFDict.createTables(layout); |
| 20921 |
} |
| 20922 |
CFFDict.call(this, tables, strings); |
| 20923 |
this.privateDict = null; |
| 20924 |
} |
| 20925 |
CFFTopDict.prototype = Object.create(CFFDict.prototype); |
| 20926 |
return CFFTopDict; |
| 20927 |
})(); |
| 20928 |
|
| 20929 |
var CFFPrivateDict = (function CFFPrivateDictClosure() { |
| 20930 |
var layout = [ |
| 20931 |
[6, 'BlueValues', 'delta', null], |
| 20932 |
[7, 'OtherBlues', 'delta', null], |
| 20933 |
[8, 'FamilyBlues', 'delta', null], |
| 20934 |
[9, 'FamilyOtherBlues', 'delta', null], |
| 20935 |
[[12, 9], 'BlueScale', 'num', 0.039625], |
| 20936 |
[[12, 10], 'BlueShift', 'num', 7], |
| 20937 |
[[12, 11], 'BlueFuzz', 'num', 1], |
| 20938 |
[10, 'StdHW', 'num', null], |
| 20939 |
[11, 'StdVW', 'num', null], |
| 20940 |
[[12, 12], 'StemSnapH', 'delta', null], |
| 20941 |
[[12, 13], 'StemSnapV', 'delta', null], |
| 20942 |
[[12, 14], 'ForceBold', 'num', 0], |
| 20943 |
[[12, 17], 'LanguageGroup', 'num', 0], |
| 20944 |
[[12, 18], 'ExpansionFactor', 'num', 0.06], |
| 20945 |
[[12, 19], 'initialRandomSeed', 'num', 0], |
| 20946 |
[20, 'defaultWidthX', 'num', 0], |
| 20947 |
[21, 'nominalWidthX', 'num', 0], |
| 20948 |
[19, 'Subrs', 'offset', null] |
| 20949 |
]; |
| 20950 |
var tables = null; |
| 20951 |
function CFFPrivateDict(strings) { |
| 20952 |
if (tables === null) { |
| 20953 |
tables = CFFDict.createTables(layout); |
| 20954 |
} |
| 20955 |
CFFDict.call(this, tables, strings); |
| 20956 |
this.subrsIndex = null; |
| 20957 |
} |
| 20958 |
CFFPrivateDict.prototype = Object.create(CFFDict.prototype); |
| 20959 |
return CFFPrivateDict; |
| 20960 |
})(); |
| 20961 |
|
| 20962 |
var CFFCharsetPredefinedTypes = { |
| 20963 |
ISO_ADOBE: 0, |
| 20964 |
EXPERT: 1, |
| 20965 |
EXPERT_SUBSET: 2 |
| 20966 |
}; |
| 20967 |
var CFFCharset = (function CFFCharsetClosure() { |
| 20968 |
function CFFCharset(predefined, format, charset, raw) { |
| 20969 |
this.predefined = predefined; |
| 20970 |
this.format = format; |
| 20971 |
this.charset = charset; |
| 20972 |
this.raw = raw; |
| 20973 |
} |
| 20974 |
return CFFCharset; |
| 20975 |
})(); |
| 20976 |
|
| 20977 |
var CFFEncoding = (function CFFEncodingClosure() { |
| 20978 |
function CFFEncoding(predefined, format, encoding, raw) { |
| 20979 |
this.predefined = predefined; |
| 20980 |
this.format = format; |
| 20981 |
this.encoding = encoding; |
| 20982 |
this.raw = raw; |
| 20983 |
} |
| 20984 |
return CFFEncoding; |
| 20985 |
})(); |
| 20986 |
|
| 20987 |
var CFFFDSelect = (function CFFFDSelectClosure() { |
| 20988 |
function CFFFDSelect(fdSelect, raw) { |
| 20989 |
this.fdSelect = fdSelect; |
| 20990 |
this.raw = raw; |
| 20991 |
} |
| 20992 |
return CFFFDSelect; |
| 20993 |
})(); |
| 20994 |
|
| 20995 |
// Helper class to keep track of where an offset is within the data and helps |
| 20996 |
// filling in that offset once it's known. |
| 20997 |
var CFFOffsetTracker = (function CFFOffsetTrackerClosure() { |
| 20998 |
function CFFOffsetTracker() { |
| 20999 |
this.offsets = {}; |
| 21000 |
} |
| 21001 |
CFFOffsetTracker.prototype = { |
| 21002 |
isTracking: function CFFOffsetTracker_isTracking(key) { |
| 21003 |
return key in this.offsets; |
| 21004 |
}, |
| 21005 |
track: function CFFOffsetTracker_track(key, location) { |
| 21006 |
if (key in this.offsets) { |
| 21007 |
error('Already tracking location of ' + key); |
| 21008 |
} |
| 21009 |
this.offsets[key] = location; |
| 21010 |
}, |
| 21011 |
offset: function CFFOffsetTracker_offset(value) { |
| 21012 |
for (var key in this.offsets) { |
| 21013 |
this.offsets[key] += value; |
| 21014 |
} |
| 21015 |
}, |
| 21016 |
setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, |
| 21017 |
values, |
| 21018 |
output) { |
| 21019 |
if (!(key in this.offsets)) { |
| 21020 |
error('Not tracking location of ' + key); |
| 21021 |
} |
| 21022 |
var data = output.data; |
| 21023 |
var dataOffset = this.offsets[key]; |
| 21024 |
var size = 5; |
| 21025 |
for (var i = 0, ii = values.length; i < ii; ++i) { |
| 21026 |
var offset0 = i * size + dataOffset; |
| 21027 |
var offset1 = offset0 + 1; |
| 21028 |
var offset2 = offset0 + 2; |
| 21029 |
var offset3 = offset0 + 3; |
| 21030 |
var offset4 = offset0 + 4; |
| 21031 |
// It's easy to screw up offsets so perform this sanity check. |
| 21032 |
if (data[offset0] !== 0x1d || data[offset1] !== 0 || |
| 21033 |
data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) { |
| 21034 |
error('writing to an offset that is not empty'); |
| 21035 |
} |
| 21036 |
var value = values[i]; |
| 21037 |
data[offset0] = 0x1d; |
| 21038 |
data[offset1] = (value >> 24) & 0xFF; |
| 21039 |
data[offset2] = (value >> 16) & 0xFF; |
| 21040 |
data[offset3] = (value >> 8) & 0xFF; |
| 21041 |
data[offset4] = value & 0xFF; |
| 21042 |
} |
| 21043 |
} |
| 21044 |
}; |
| 21045 |
return CFFOffsetTracker; |
| 21046 |
})(); |
| 21047 |
|
| 21048 |
// Takes a CFF and converts it to the binary representation. |
| 21049 |
var CFFCompiler = (function CFFCompilerClosure() { |
| 21050 |
function CFFCompiler(cff) { |
| 21051 |
this.cff = cff; |
| 21052 |
} |
| 21053 |
CFFCompiler.prototype = { |
| 21054 |
compile: function CFFCompiler_compile() { |
| 21055 |
var cff = this.cff; |
| 21056 |
var output = { |
| 21057 |
data: [], |
| 21058 |
length: 0, |
| 21059 |
add: function CFFCompiler_add(data) { |
| 21060 |
this.data = this.data.concat(data); |
| 21061 |
this.length = this.data.length; |
| 21062 |
} |
| 21063 |
}; |
| 21064 |
|
| 21065 |
// Compile the five entries that must be in order. |
| 21066 |
var header = this.compileHeader(cff.header); |
| 21067 |
output.add(header); |
| 21068 |
|
| 21069 |
var nameIndex = this.compileNameIndex(cff.names); |
| 21070 |
output.add(nameIndex); |
| 21071 |
|
| 21072 |
if (cff.isCIDFont) { |
| 21073 |
// The spec is unclear on how font matrices should relate to each other |
| 21074 |
// when there is one in the main top dict and the sub top dicts. |
| 21075 |
// Windows handles this differently than linux and osx so we have to |
| 21076 |
// normalize to work on all. |
| 21077 |
// Rules based off of some mailing list discussions: |
| 21078 |
// - If main font has a matrix and subfont doesn't, use the main matrix. |
| 21079 |
// - If no main font matrix and there is a subfont matrix, use the |
| 21080 |
// subfont matrix. |
| 21081 |
// - If both have matrices, concat together. |
| 21082 |
// - If neither have matrices, use default. |
| 21083 |
// To make this work on all platforms we move the top matrix into each |
| 21084 |
// sub top dict and concat if necessary. |
| 21085 |
if (cff.topDict.hasName('FontMatrix')) { |
| 21086 |
var base = cff.topDict.getByName('FontMatrix'); |
| 21087 |
cff.topDict.removeByName('FontMatrix'); |
| 21088 |
for (var i = 0, ii = cff.fdArray.length; i < ii; i++) { |
| 21089 |
var subDict = cff.fdArray[i]; |
| 21090 |
var matrix = base.slice(0); |
| 21091 |
if (subDict.hasName('FontMatrix')) { |
| 21092 |
matrix = Util.transform(matrix, subDict.getByName('FontMatrix')); |
| 21093 |
} |
| 21094 |
subDict.setByName('FontMatrix', matrix); |
| 21095 |
} |
| 21096 |
} |
| 21097 |
} |
| 21098 |
|
| 21099 |
var compiled = this.compileTopDicts([cff.topDict], |
| 21100 |
output.length, |
| 21101 |
cff.isCIDFont); |
| 21102 |
output.add(compiled.output); |
| 21103 |
var topDictTracker = compiled.trackers[0]; |
| 21104 |
|
| 21105 |
var stringIndex = this.compileStringIndex(cff.strings.strings); |
| 21106 |
output.add(stringIndex); |
| 21107 |
|
| 21108 |
var globalSubrIndex = this.compileIndex(cff.globalSubrIndex); |
| 21109 |
output.add(globalSubrIndex); |
| 21110 |
|
| 21111 |
// Now start on the other entries that have no specfic order. |
| 21112 |
if (cff.encoding && cff.topDict.hasName('Encoding')) { |
| 21113 |
if (cff.encoding.predefined) { |
| 21114 |
topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], |
| 21115 |
output); |
| 21116 |
} else { |
| 21117 |
var encoding = this.compileEncoding(cff.encoding); |
| 21118 |
topDictTracker.setEntryLocation('Encoding', [output.length], output); |
| 21119 |
output.add(encoding); |
| 21120 |
} |
| 21121 |
} |
| 21122 |
|
| 21123 |
if (cff.charset && cff.topDict.hasName('charset')) { |
| 21124 |
if (cff.charset.predefined) { |
| 21125 |
topDictTracker.setEntryLocation('charset', [cff.charset.format], |
| 21126 |
output); |
| 21127 |
} else { |
| 21128 |
var charset = this.compileCharset(cff.charset); |
| 21129 |
topDictTracker.setEntryLocation('charset', [output.length], output); |
| 21130 |
output.add(charset); |
| 21131 |
} |
| 21132 |
} |
| 21133 |
|
| 21134 |
var charStrings = this.compileCharStrings(cff.charStrings); |
| 21135 |
topDictTracker.setEntryLocation('CharStrings', [output.length], output); |
| 21136 |
output.add(charStrings); |
| 21137 |
|
| 21138 |
if (cff.isCIDFont) { |
| 21139 |
// For some reason FDSelect must be in front of FDArray on windows. OSX |
| 21140 |
// and linux don't seem to care. |
| 21141 |
topDictTracker.setEntryLocation('FDSelect', [output.length], output); |
| 21142 |
var fdSelect = this.compileFDSelect(cff.fdSelect.raw); |
| 21143 |
output.add(fdSelect); |
| 21144 |
// It is unclear if the sub font dictionary can have CID related |
| 21145 |
// dictionary keys, but the sanitizer doesn't like them so remove them. |
| 21146 |
compiled = this.compileTopDicts(cff.fdArray, output.length, true); |
| 21147 |
topDictTracker.setEntryLocation('FDArray', [output.length], output); |
| 21148 |
output.add(compiled.output); |
| 21149 |
var fontDictTrackers = compiled.trackers; |
| 21150 |
|
| 21151 |
this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output); |
| 21152 |
} |
| 21153 |
|
| 21154 |
this.compilePrivateDicts([cff.topDict], [topDictTracker], output); |
| 21155 |
|
| 21156 |
// If the font data ends with INDEX whose object data is zero-length, |
| 21157 |
// the sanitizer will bail out. Add a dummy byte to avoid that. |
| 21158 |
output.add([0]); |
| 21159 |
|
| 21160 |
return output.data; |
| 21161 |
}, |
| 21162 |
encodeNumber: function CFFCompiler_encodeNumber(value) { |
| 21163 |
if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) { // isInt |
| 21164 |
return this.encodeInteger(value); |
| 21165 |
} else { |
| 21166 |
return this.encodeFloat(value); |
| 21167 |
} |
| 21168 |
}, |
| 21169 |
encodeFloat: function CFFCompiler_encodeFloat(num) { |
| 21170 |
var value = num.toString(); |
| 21171 |
|
| 21172 |
// rounding inaccurate doubles |
| 21173 |
var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value); |
| 21174 |
if (m) { |
| 21175 |
var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length)); |
| 21176 |
value = (Math.round(num * epsilon) / epsilon).toString(); |
| 21177 |
} |
| 21178 |
|
| 21179 |
var nibbles = ''; |
| 21180 |
var i, ii; |
| 21181 |
for (i = 0, ii = value.length; i < ii; ++i) { |
| 21182 |
var a = value[i]; |
| 21183 |
if (a === 'e') { |
| 21184 |
nibbles += value[++i] === '-' ? 'c' : 'b'; |
| 21185 |
} else if (a === '.') { |
| 21186 |
nibbles += 'a'; |
| 21187 |
} else if (a === '-') { |
| 21188 |
nibbles += 'e'; |
| 21189 |
} else { |
| 21190 |
nibbles += a; |
| 21191 |
} |
| 21192 |
} |
| 21193 |
nibbles += (nibbles.length & 1) ? 'f' : 'ff'; |
| 21194 |
var out = [30]; |
| 21195 |
for (i = 0, ii = nibbles.length; i < ii; i += 2) { |
| 21196 |
out.push(parseInt(nibbles.substr(i, 2), 16)); |
| 21197 |
} |
| 21198 |
return out; |
| 21199 |
}, |
| 21200 |
encodeInteger: function CFFCompiler_encodeInteger(value) { |
| 21201 |
var code; |
| 21202 |
if (value >= -107 && value <= 107) { |
| 21203 |
code = [value + 139]; |
| 21204 |
} else if (value >= 108 && value <= 1131) { |
| 21205 |
value = [value - 108]; |
| 21206 |
code = [(value >> 8) + 247, value & 0xFF]; |
| 21207 |
} else if (value >= -1131 && value <= -108) { |
| 21208 |
value = -value - 108; |
| 21209 |
code = [(value >> 8) + 251, value & 0xFF]; |
| 21210 |
} else if (value >= -32768 && value <= 32767) { |
| 21211 |
code = [0x1c, (value >> 8) & 0xFF, value & 0xFF]; |
| 21212 |
} else { |
| 21213 |
code = [0x1d, |
| 21214 |
(value >> 24) & 0xFF, |
| 21215 |
(value >> 16) & 0xFF, |
| 21216 |
(value >> 8) & 0xFF, |
| 21217 |
value & 0xFF]; |
| 21218 |
} |
| 21219 |
return code; |
| 21220 |
}, |
| 21221 |
compileHeader: function CFFCompiler_compileHeader(header) { |
| 21222 |
return [ |
| 21223 |
header.major, |
| 21224 |
header.minor, |
| 21225 |
header.hdrSize, |
| 21226 |
header.offSize |
| 21227 |
]; |
| 21228 |
}, |
| 21229 |
compileNameIndex: function CFFCompiler_compileNameIndex(names) { |
| 21230 |
var nameIndex = new CFFIndex(); |
| 21231 |
for (var i = 0, ii = names.length; i < ii; ++i) { |
| 21232 |
nameIndex.add(stringToBytes(names[i])); |
| 21233 |
} |
| 21234 |
return this.compileIndex(nameIndex); |
| 21235 |
}, |
| 21236 |
compileTopDicts: function CFFCompiler_compileTopDicts(dicts, |
| 21237 |
length, |
| 21238 |
removeCidKeys) { |
| 21239 |
var fontDictTrackers = []; |
| 21240 |
var fdArrayIndex = new CFFIndex(); |
| 21241 |
for (var i = 0, ii = dicts.length; i < ii; ++i) { |
| 21242 |
var fontDict = dicts[i]; |
| 21243 |
if (removeCidKeys) { |
| 21244 |
fontDict.removeByName('CIDFontVersion'); |
| 21245 |
fontDict.removeByName('CIDFontRevision'); |
| 21246 |
fontDict.removeByName('CIDFontType'); |
| 21247 |
fontDict.removeByName('CIDCount'); |
| 21248 |
fontDict.removeByName('UIDBase'); |
| 21249 |
} |
| 21250 |
var fontDictTracker = new CFFOffsetTracker(); |
| 21251 |
var fontDictData = this.compileDict(fontDict, fontDictTracker); |
| 21252 |
fontDictTrackers.push(fontDictTracker); |
| 21253 |
fdArrayIndex.add(fontDictData); |
| 21254 |
fontDictTracker.offset(length); |
| 21255 |
} |
| 21256 |
fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers); |
| 21257 |
return { |
| 21258 |
trackers: fontDictTrackers, |
| 21259 |
output: fdArrayIndex |
| 21260 |
}; |
| 21261 |
}, |
| 21262 |
compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, |
| 21263 |
trackers, |
| 21264 |
output) { |
| 21265 |
for (var i = 0, ii = dicts.length; i < ii; ++i) { |
| 21266 |
var fontDict = dicts[i]; |
| 21267 |
assert(fontDict.privateDict && fontDict.hasName('Private'), |
| 21268 |
'There must be an private dictionary.'); |
| 21269 |
var privateDict = fontDict.privateDict; |
| 21270 |
var privateDictTracker = new CFFOffsetTracker(); |
| 21271 |
var privateDictData = this.compileDict(privateDict, privateDictTracker); |
| 21272 |
|
| 21273 |
var outputLength = output.length; |
| 21274 |
privateDictTracker.offset(outputLength); |
| 21275 |
if (!privateDictData.length) { |
| 21276 |
// The private dictionary was empty, set the output length to zero to |
| 21277 |
// ensure the offset length isn't out of bounds in the eyes of the |
| 21278 |
// sanitizer. |
| 21279 |
outputLength = 0; |
| 21280 |
} |
| 21281 |
|
| 21282 |
trackers[i].setEntryLocation('Private', |
| 21283 |
[privateDictData.length, outputLength], |
| 21284 |
output); |
| 21285 |
output.add(privateDictData); |
| 21286 |
|
| 21287 |
if (privateDict.subrsIndex && privateDict.hasName('Subrs')) { |
| 21288 |
var subrs = this.compileIndex(privateDict.subrsIndex); |
| 21289 |
privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], |
| 21290 |
output); |
| 21291 |
output.add(subrs); |
| 21292 |
} |
| 21293 |
} |
| 21294 |
}, |
| 21295 |
compileDict: function CFFCompiler_compileDict(dict, offsetTracker) { |
| 21296 |
var out = []; |
| 21297 |
// The dictionary keys must be in a certain order. |
| 21298 |
var order = dict.order; |
| 21299 |
for (var i = 0; i < order.length; ++i) { |
| 21300 |
var key = order[i]; |
| 21301 |
if (!(key in dict.values)) { |
| 21302 |
continue; |
| 21303 |
} |
| 21304 |
var values = dict.values[key]; |
| 21305 |
var types = dict.types[key]; |
| 21306 |
if (!isArray(types)) { |
| 21307 |
types = [types]; |
| 21308 |
} |
| 21309 |
if (!isArray(values)) { |
| 21310 |
values = [values]; |
| 21311 |
} |
| 21312 |
|
| 21313 |
// Remove any empty dict values. |
| 21314 |
if (values.length === 0) { |
| 21315 |
continue; |
| 21316 |
} |
| 21317 |
|
| 21318 |
for (var j = 0, jj = types.length; j < jj; ++j) { |
| 21319 |
var type = types[j]; |
| 21320 |
var value = values[j]; |
| 21321 |
switch (type) { |
| 21322 |
case 'num': |
| 21323 |
case 'sid': |
| 21324 |
out = out.concat(this.encodeNumber(value)); |
| 21325 |
break; |
| 21326 |
case 'offset': |
| 21327 |
// For offsets we just insert a 32bit integer so we don't have to |
| 21328 |
// deal with figuring out the length of the offset when it gets |
| 21329 |
// replaced later on by the compiler. |
| 21330 |
var name = dict.keyToNameMap[key]; |
| 21331 |
// Some offsets have the offset and the length, so just record the |
| 21332 |
// position of the first one. |
| 21333 |
if (!offsetTracker.isTracking(name)) { |
| 21334 |
offsetTracker.track(name, out.length); |
| 21335 |
} |
| 21336 |
out = out.concat([0x1d, 0, 0, 0, 0]); |
| 21337 |
break; |
| 21338 |
case 'array': |
| 21339 |
case 'delta': |
| 21340 |
out = out.concat(this.encodeNumber(value)); |
| 21341 |
for (var k = 1, kk = values.length; k < kk; ++k) { |
| 21342 |
out = out.concat(this.encodeNumber(values[k])); |
| 21343 |
} |
| 21344 |
break; |
| 21345 |
default: |
| 21346 |
error('Unknown data type of ' + type); |
| 21347 |
break; |
| 21348 |
} |
| 21349 |
} |
| 21350 |
out = out.concat(dict.opcodes[key]); |
| 21351 |
} |
| 21352 |
return out; |
| 21353 |
}, |
| 21354 |
compileStringIndex: function CFFCompiler_compileStringIndex(strings) { |
| 21355 |
var stringIndex = new CFFIndex(); |
| 21356 |
for (var i = 0, ii = strings.length; i < ii; ++i) { |
| 21357 |
stringIndex.add(stringToBytes(strings[i])); |
| 21358 |
} |
| 21359 |
return this.compileIndex(stringIndex); |
| 21360 |
}, |
| 21361 |
compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() { |
| 21362 |
var globalSubrIndex = this.cff.globalSubrIndex; |
| 21363 |
this.out.writeByteArray(this.compileIndex(globalSubrIndex)); |
| 21364 |
}, |
| 21365 |
compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) { |
| 21366 |
return this.compileIndex(charStrings); |
| 21367 |
}, |
| 21368 |
compileCharset: function CFFCompiler_compileCharset(charset) { |
| 21369 |
return this.compileTypedArray(charset.raw); |
| 21370 |
}, |
| 21371 |
compileEncoding: function CFFCompiler_compileEncoding(encoding) { |
| 21372 |
return this.compileTypedArray(encoding.raw); |
| 21373 |
}, |
| 21374 |
compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) { |
| 21375 |
return this.compileTypedArray(fdSelect); |
| 21376 |
}, |
| 21377 |
compileTypedArray: function CFFCompiler_compileTypedArray(data) { |
| 21378 |
var out = []; |
| 21379 |
for (var i = 0, ii = data.length; i < ii; ++i) { |
| 21380 |
out[i] = data[i]; |
| 21381 |
} |
| 21382 |
return out; |
| 21383 |
}, |
| 21384 |
compileIndex: function CFFCompiler_compileIndex(index, trackers) { |
| 21385 |
trackers = trackers || []; |
| 21386 |
var objects = index.objects; |
| 21387 |
// First 2 bytes contains the number of objects contained into this index |
| 21388 |
var count = objects.length; |
| 21389 |
|
| 21390 |
// If there is no object, just create an index. This technically |
| 21391 |
// should just be [0, 0] but OTS has an issue with that. |
| 21392 |
if (count === 0) { |
| 21393 |
return [0, 0, 0]; |
| 21394 |
} |
| 21395 |
|
| 21396 |
var data = [(count >> 8) & 0xFF, count & 0xff]; |
| 21397 |
|
| 21398 |
var lastOffset = 1, i; |
| 21399 |
for (i = 0; i < count; ++i) { |
| 21400 |
lastOffset += objects[i].length; |
| 21401 |
} |
| 21402 |
|
| 21403 |
var offsetSize; |
| 21404 |
if (lastOffset < 0x100) { |
| 21405 |
offsetSize = 1; |
| 21406 |
} else if (lastOffset < 0x10000) { |
| 21407 |
offsetSize = 2; |
| 21408 |
} else if (lastOffset < 0x1000000) { |
| 21409 |
offsetSize = 3; |
| 21410 |
} else { |
| 21411 |
offsetSize = 4; |
| 21412 |
} |
| 21413 |
|
| 21414 |
// Next byte contains the offset size use to reference object in the file |
| 21415 |
data.push(offsetSize); |
| 21416 |
|
| 21417 |
// Add another offset after this one because we need a new offset |
| 21418 |
var relativeOffset = 1; |
| 21419 |
for (i = 0; i < count + 1; i++) { |
| 21420 |
if (offsetSize === 1) { |
| 21421 |
data.push(relativeOffset & 0xFF); |
| 21422 |
} else if (offsetSize === 2) { |
| 21423 |
data.push((relativeOffset >> 8) & 0xFF, |
| 21424 |
relativeOffset & 0xFF); |
| 21425 |
} else if (offsetSize === 3) { |
| 21426 |
data.push((relativeOffset >> 16) & 0xFF, |
| 21427 |
(relativeOffset >> 8) & 0xFF, |
| 21428 |
relativeOffset & 0xFF); |
| 21429 |
} else { |
| 21430 |
data.push((relativeOffset >>> 24) & 0xFF, |
| 21431 |
(relativeOffset >> 16) & 0xFF, |
| 21432 |
(relativeOffset >> 8) & 0xFF, |
| 21433 |
relativeOffset & 0xFF); |
| 21434 |
} |
| 21435 |
|
| 21436 |
if (objects[i]) { |
| 21437 |
relativeOffset += objects[i].length; |
| 21438 |
} |
| 21439 |
} |
| 21440 |
|
| 21441 |
for (i = 0; i < count; i++) { |
| 21442 |
// Notify the tracker where the object will be offset in the data. |
| 21443 |
if (trackers[i]) { |
| 21444 |
trackers[i].offset(data.length); |
| 21445 |
} |
| 21446 |
for (var j = 0, jj = objects[i].length; j < jj; j++) { |
| 21447 |
data.push(objects[i][j]); |
| 21448 |
} |
| 21449 |
} |
| 21450 |
return data; |
| 21451 |
} |
| 21452 |
}; |
| 21453 |
return CFFCompiler; |
| 21454 |
})(); |
| 21455 |
|
| 21456 |
// Workaround for seac on Windows. |
| 21457 |
(function checkSeacSupport() { |
| 21458 |
if (/Windows/.test(navigator.userAgent)) { |
| 21459 |
SEAC_ANALYSIS_ENABLED = true; |
| 21460 |
} |
| 21461 |
})(); |
| 21462 |
|
| 21463 |
// Workaround for Private Use Area characters in Chrome on Windows |
| 21464 |
// http://code.google.com/p/chromium/issues/detail?id=122465 |
| 21465 |
// https://github.com/mozilla/pdf.js/issues/1689 |
| 21466 |
(function checkChromeWindows() { |
| 21467 |
if (/Windows.*Chrome/.test(navigator.userAgent)) { |
| 21468 |
SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = true; |
| 21469 |
} |
| 21470 |
})(); |
| 21471 |
|
| 21472 |
|
| 21473 |
var FontRendererFactory = (function FontRendererFactoryClosure() { |
| 21474 |
function getLong(data, offset) { |
| 21475 |
return (data[offset] << 24) | (data[offset + 1] << 16) | |
| 21476 |
(data[offset + 2] << 8) | data[offset + 3]; |
| 21477 |
} |
| 21478 |
|
| 21479 |
function getUshort(data, offset) { |
| 21480 |
return (data[offset] << 8) | data[offset + 1]; |
| 21481 |
} |
| 21482 |
|
| 21483 |
function parseCmap(data, start, end) { |
| 21484 |
var offset = (getUshort(data, start + 2) === 1 ? |
| 21485 |
getLong(data, start + 8) : getLong(data, start + 16)); |
| 21486 |
var format = getUshort(data, start + offset); |
| 21487 |
var length, ranges, p, i; |
| 21488 |
if (format === 4) { |
| 21489 |
length = getUshort(data, start + offset + 2); |
| 21490 |
var segCount = getUshort(data, start + offset + 6) >> 1; |
| 21491 |
p = start + offset + 14; |
| 21492 |
ranges = []; |
| 21493 |
for (i = 0; i < segCount; i++, p += 2) { |
| 21494 |
ranges[i] = {end: getUshort(data, p)}; |
| 21495 |
} |
| 21496 |
p += 2; |
| 21497 |
for (i = 0; i < segCount; i++, p += 2) { |
| 21498 |
ranges[i].start = getUshort(data, p); |
| 21499 |
} |
| 21500 |
for (i = 0; i < segCount; i++, p += 2) { |
| 21501 |
ranges[i].idDelta = getUshort(data, p); |
| 21502 |
} |
| 21503 |
for (i = 0; i < segCount; i++, p += 2) { |
| 21504 |
var idOffset = getUshort(data, p); |
| 21505 |
if (idOffset === 0) { |
| 21506 |
continue; |
| 21507 |
} |
| 21508 |
ranges[i].ids = []; |
| 21509 |
for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) { |
| 21510 |
ranges[i].ids[j] = getUshort(data, p + idOffset); |
| 21511 |
idOffset += 2; |
| 21512 |
} |
| 21513 |
} |
| 21514 |
return ranges; |
| 21515 |
} else if (format === 12) { |
| 21516 |
length = getLong(data, start + offset + 4); |
| 21517 |
var groups = getLong(data, start + offset + 12); |
| 21518 |
p = start + offset + 16; |
| 21519 |
ranges = []; |
| 21520 |
for (i = 0; i < groups; i++) { |
| 21521 |
ranges.push({ |
| 21522 |
start: getLong(data, p), |
| 21523 |
end: getLong(data, p + 4), |
| 21524 |
idDelta: getLong(data, p + 8) - getLong(data, p) |
| 21525 |
}); |
| 21526 |
p += 12; |
| 21527 |
} |
| 21528 |
return ranges; |
| 21529 |
} |
| 21530 |
error('not supported cmap: ' + format); |
| 21531 |
} |
| 21532 |
|
| 21533 |
function parseCff(data, start, end) { |
| 21534 |
var properties = {}; |
| 21535 |
var parser = new CFFParser(new Stream(data, start, end - start), |
| 21536 |
properties); |
| 21537 |
var cff = parser.parse(); |
| 21538 |
return { |
| 21539 |
glyphs: cff.charStrings.objects, |
| 21540 |
subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && |
| 21541 |
cff.topDict.privateDict.subrsIndex.objects), |
| 21542 |
gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects |
| 21543 |
}; |
| 21544 |
} |
| 21545 |
|
| 21546 |
function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { |
| 21547 |
var itemSize, itemDecode; |
| 21548 |
if (isGlyphLocationsLong) { |
| 21549 |
itemSize = 4; |
| 21550 |
itemDecode = function fontItemDecodeLong(data, offset) { |
| 21551 |
return (data[offset] << 24) | (data[offset + 1] << 16) | |
| 21552 |
(data[offset + 2] << 8) | data[offset + 3]; |
| 21553 |
}; |
| 21554 |
} else { |
| 21555 |
itemSize = 2; |
| 21556 |
itemDecode = function fontItemDecode(data, offset) { |
| 21557 |
return (data[offset] << 9) | (data[offset + 1] << 1); |
| 21558 |
}; |
| 21559 |
} |
| 21560 |
var glyphs = []; |
| 21561 |
var startOffset = itemDecode(loca, 0); |
| 21562 |
for (var j = itemSize; j < loca.length; j += itemSize) { |
| 21563 |
var endOffset = itemDecode(loca, j); |
| 21564 |
glyphs.push(glyf.subarray(startOffset, endOffset)); |
| 21565 |
startOffset = endOffset; |
| 21566 |
} |
| 21567 |
return glyphs; |
| 21568 |
} |
| 21569 |
|
| 21570 |
function lookupCmap(ranges, unicode) { |
| 21571 |
var code = unicode.charCodeAt(0); |
| 21572 |
var l = 0, r = ranges.length - 1; |
| 21573 |
while (l < r) { |
| 21574 |
var c = (l + r + 1) >> 1; |
| 21575 |
if (code < ranges[c].start) { |
| 21576 |
r = c - 1; |
| 21577 |
} else { |
| 21578 |
l = c; |
| 21579 |
} |
| 21580 |
} |
| 21581 |
if (ranges[l].start <= code && code <= ranges[l].end) { |
| 21582 |
return (ranges[l].idDelta + (ranges[l].ids ? |
| 21583 |
ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF; |
| 21584 |
} |
| 21585 |
return 0; |
| 21586 |
} |
| 21587 |
|
| 21588 |
function compileGlyf(code, js, font) { |
| 21589 |
function moveTo(x, y) { |
| 21590 |
js.push('c.moveTo(' + x + ',' + y + ');'); |
| 21591 |
} |
| 21592 |
function lineTo(x, y) { |
| 21593 |
js.push('c.lineTo(' + x + ',' + y + ');'); |
| 21594 |
} |
| 21595 |
function quadraticCurveTo(xa, ya, x, y) { |
| 21596 |
js.push('c.quadraticCurveTo(' + xa + ',' + ya + ',' + |
| 21597 |
x + ',' + y + ');'); |
| 21598 |
} |
| 21599 |
|
| 21600 |
var i = 0; |
| 21601 |
var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16; |
| 21602 |
var flags; |
| 21603 |
var x = 0, y = 0; |
| 21604 |
i += 10; |
| 21605 |
if (numberOfContours < 0) { |
| 21606 |
// composite glyph |
| 21607 |
do { |
| 21608 |
flags = (code[i] << 8) | code[i + 1]; |
| 21609 |
var glyphIndex = (code[i + 2] << 8) | code[i + 3]; |
| 21610 |
i += 4; |
| 21611 |
var arg1, arg2; |
| 21612 |
if ((flags & 0x01)) { |
| 21613 |
arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16; |
| 21614 |
arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16; |
| 21615 |
i += 4; |
| 21616 |
} else { |
| 21617 |
arg1 = code[i++]; arg2 = code[i++]; |
| 21618 |
} |
| 21619 |
if ((flags & 0x02)) { |
| 21620 |
x = arg1; |
| 21621 |
y = arg2; |
| 21622 |
} else { |
| 21623 |
x = 0; y = 0; // TODO "they are points" ? |
| 21624 |
} |
| 21625 |
var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0; |
| 21626 |
if ((flags & 0x08)) { |
| 21627 |
scaleX = |
| 21628 |
scaleY = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; |
| 21629 |
i += 2; |
| 21630 |
} else if ((flags & 0x40)) { |
| 21631 |
scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; |
| 21632 |
scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824; |
| 21633 |
i += 4; |
| 21634 |
} else if ((flags & 0x80)) { |
| 21635 |
scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; |
| 21636 |
scale01 = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824; |
| 21637 |
scale10 = ((code[i + 4] << 24) | (code[i + 5] << 16)) / 1073741824; |
| 21638 |
scaleY = ((code[i + 6] << 24) | (code[i + 7] << 16)) / 1073741824; |
| 21639 |
i += 8; |
| 21640 |
} |
| 21641 |
var subglyph = font.glyphs[glyphIndex]; |
| 21642 |
if (subglyph) { |
| 21643 |
js.push('c.save();'); |
| 21644 |
js.push('c.transform(' + scaleX + ',' + scale01 + ',' + |
| 21645 |
scale10 + ',' + scaleY + ',' + x + ',' + y + ');'); |
| 21646 |
compileGlyf(subglyph, js, font); |
| 21647 |
js.push('c.restore();'); |
| 21648 |
} |
| 21649 |
} while ((flags & 0x20)); |
| 21650 |
} else { |
| 21651 |
// simple glyph |
| 21652 |
var endPtsOfContours = []; |
| 21653 |
var j, jj; |
| 21654 |
for (j = 0; j < numberOfContours; j++) { |
| 21655 |
endPtsOfContours.push((code[i] << 8) | code[i + 1]); |
| 21656 |
i += 2; |
| 21657 |
} |
| 21658 |
var instructionLength = (code[i] << 8) | code[i + 1]; |
| 21659 |
i += 2 + instructionLength; // skipping the instructions |
| 21660 |
var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1; |
| 21661 |
var points = []; |
| 21662 |
while (points.length < numberOfPoints) { |
| 21663 |
flags = code[i++]; |
| 21664 |
var repeat = 1; |
| 21665 |
if ((flags & 0x08)) { |
| 21666 |
repeat += code[i++]; |
| 21667 |
} |
| 21668 |
while (repeat-- > 0) { |
| 21669 |
points.push({flags: flags}); |
| 21670 |
} |
| 21671 |
} |
| 21672 |
for (j = 0; j < numberOfPoints; j++) { |
| 21673 |
switch (points[j].flags & 0x12) { |
| 21674 |
case 0x00: |
| 21675 |
x += ((code[i] << 24) | (code[i + 1] << 16)) >> 16; |
| 21676 |
i += 2; |
| 21677 |
break; |
| 21678 |
case 0x02: |
| 21679 |
x -= code[i++]; |
| 21680 |
break; |
| 21681 |
case 0x12: |
| 21682 |
x += code[i++]; |
| 21683 |
break; |
| 21684 |
} |
| 21685 |
points[j].x = x; |
| 21686 |
} |
| 21687 |
for (j = 0; j < numberOfPoints; j++) { |
| 21688 |
switch (points[j].flags & 0x24) { |
| 21689 |
case 0x00: |
| 21690 |
y += ((code[i] << 24) | (code[i + 1] << 16)) >> 16; |
| 21691 |
i += 2; |
| 21692 |
break; |
| 21693 |
case 0x04: |
| 21694 |
y -= code[i++]; |
| 21695 |
break; |
| 21696 |
case 0x24: |
| 21697 |
y += code[i++]; |
| 21698 |
break; |
| 21699 |
} |
| 21700 |
points[j].y = y; |
| 21701 |
} |
| 21702 |
|
| 21703 |
var startPoint = 0; |
| 21704 |
for (i = 0; i < numberOfContours; i++) { |
| 21705 |
var endPoint = endPtsOfContours[i]; |
| 21706 |
// contours might have implicit points, which is located in the middle |
| 21707 |
// between two neighboring off-curve points |
| 21708 |
var contour = points.slice(startPoint, endPoint + 1); |
| 21709 |
if ((contour[0].flags & 1)) { |
| 21710 |
contour.push(contour[0]); // using start point at the contour end |
| 21711 |
} else if ((contour[contour.length - 1].flags & 1)) { |
| 21712 |
// first is off-curve point, trying to use one from the end |
| 21713 |
contour.unshift(contour[contour.length - 1]); |
| 21714 |
} else { |
| 21715 |
// start and end are off-curve points, creating implicit one |
| 21716 |
var p = { |
| 21717 |
flags: 1, |
| 21718 |
x: (contour[0].x + contour[contour.length - 1].x) / 2, |
| 21719 |
y: (contour[0].y + contour[contour.length - 1].y) / 2 |
| 21720 |
}; |
| 21721 |
contour.unshift(p); |
| 21722 |
contour.push(p); |
| 21723 |
} |
| 21724 |
moveTo(contour[0].x, contour[0].y); |
| 21725 |
for (j = 1, jj = contour.length; j < jj; j++) { |
| 21726 |
if ((contour[j].flags & 1)) { |
| 21727 |
lineTo(contour[j].x, contour[j].y); |
| 21728 |
} else if ((contour[j + 1].flags & 1)){ |
| 21729 |
quadraticCurveTo(contour[j].x, contour[j].y, |
| 21730 |
contour[j + 1].x, contour[j + 1].y); |
| 21731 |
j++; |
| 21732 |
} else { |
| 21733 |
quadraticCurveTo(contour[j].x, contour[j].y, |
| 21734 |
(contour[j].x + contour[j + 1].x) / 2, |
| 21735 |
(contour[j].y + contour[j + 1].y) / 2); |
| 21736 |
} |
| 21737 |
} |
| 21738 |
startPoint = endPoint + 1; |
| 21739 |
} |
| 21740 |
} |
| 21741 |
} |
| 21742 |
|
| 21743 |
function compileCharString(code, js, font) { |
| 21744 |
var stack = []; |
| 21745 |
var x = 0, y = 0; |
| 21746 |
var stems = 0; |
| 21747 |
|
| 21748 |
function moveTo(x, y) { |
| 21749 |
js.push('c.moveTo(' + x + ',' + y + ');'); |
| 21750 |
} |
| 21751 |
function lineTo(x, y) { |
| 21752 |
js.push('c.lineTo(' + x + ',' + y + ');'); |
| 21753 |
} |
| 21754 |
function bezierCurveTo(x1, y1, x2, y2, x, y) { |
| 21755 |
js.push('c.bezierCurveTo(' + x1 + ',' + y1 + ',' + x2 + ',' + y2 + ',' + |
| 21756 |
x + ',' + y + ');'); |
| 21757 |
} |
| 21758 |
|
| 21759 |
function parse(code) { |
| 21760 |
var i = 0; |
| 21761 |
while (i < code.length) { |
| 21762 |
var stackClean = false; |
| 21763 |
var v = code[i++]; |
| 21764 |
var xa, xb, ya, yb, y1, y2, y3, n, subrCode; |
| 21765 |
switch (v) { |
| 21766 |
case 1: // hstem |
| 21767 |
stems += stack.length >> 1; |
| 21768 |
stackClean = true; |
| 21769 |
break; |
| 21770 |
case 3: // vstem |
| 21771 |
stems += stack.length >> 1; |
| 21772 |
stackClean = true; |
| 21773 |
break; |
| 21774 |
case 4: // vmoveto |
| 21775 |
y += stack.pop(); |
| 21776 |
moveTo(x, y); |
| 21777 |
stackClean = true; |
| 21778 |
break; |
| 21779 |
case 5: // rlineto |
| 21780 |
while (stack.length > 0) { |
| 21781 |
x += stack.shift(); |
| 21782 |
y += stack.shift(); |
| 21783 |
lineTo(x, y); |
| 21784 |
} |
| 21785 |
break; |
| 21786 |
case 6: // hlineto |
| 21787 |
while (stack.length > 0) { |
| 21788 |
x += stack.shift(); |
| 21789 |
lineTo(x, y); |
| 21790 |
if (stack.length === 0) { |
| 21791 |
break; |
| 21792 |
} |
| 21793 |
y += stack.shift(); |
| 21794 |
lineTo(x, y); |
| 21795 |
} |
| 21796 |
break; |
| 21797 |
case 7: // vlineto |
| 21798 |
while (stack.length > 0) { |
| 21799 |
y += stack.shift(); |
| 21800 |
lineTo(x, y); |
| 21801 |
if (stack.length === 0) { |
| 21802 |
break; |
| 21803 |
} |
| 21804 |
x += stack.shift(); |
| 21805 |
lineTo(x, y); |
| 21806 |
} |
| 21807 |
break; |
| 21808 |
case 8: // rrcurveto |
| 21809 |
while (stack.length > 0) { |
| 21810 |
xa = x + stack.shift(); ya = y + stack.shift(); |
| 21811 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21812 |
x = xb + stack.shift(); y = yb + stack.shift(); |
| 21813 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21814 |
} |
| 21815 |
break; |
| 21816 |
case 10: // callsubr |
| 21817 |
n = stack.pop() + font.subrsBias; |
| 21818 |
subrCode = font.subrs[n]; |
| 21819 |
if (subrCode) { |
| 21820 |
parse(subrCode); |
| 21821 |
} |
| 21822 |
break; |
| 21823 |
case 11: // return |
| 21824 |
return; |
| 21825 |
case 12: |
| 21826 |
v = code[i++]; |
| 21827 |
switch (v) { |
| 21828 |
case 34: // flex |
| 21829 |
xa = x + stack.shift(); |
| 21830 |
xb = xa + stack.shift(); y1 = y + stack.shift(); |
| 21831 |
x = xb + stack.shift(); |
| 21832 |
bezierCurveTo(xa, y, xb, y1, x, y1); |
| 21833 |
xa = x + stack.shift(); |
| 21834 |
xb = xa + stack.shift(); |
| 21835 |
x = xb + stack.shift(); |
| 21836 |
bezierCurveTo(xa, y1, xb, y, x, y); |
| 21837 |
break; |
| 21838 |
case 35: // flex |
| 21839 |
xa = x + stack.shift(); ya = y + stack.shift(); |
| 21840 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21841 |
x = xb + stack.shift(); y = yb + stack.shift(); |
| 21842 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21843 |
xa = x + stack.shift(); ya = y + stack.shift(); |
| 21844 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21845 |
x = xb + stack.shift(); y = yb + stack.shift(); |
| 21846 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21847 |
stack.pop(); // fd |
| 21848 |
break; |
| 21849 |
case 36: // hflex1 |
| 21850 |
xa = x + stack.shift(); y1 = y + stack.shift(); |
| 21851 |
xb = xa + stack.shift(); y2 = y1 + stack.shift(); |
| 21852 |
x = xb + stack.shift(); |
| 21853 |
bezierCurveTo(xa, y1, xb, y2, x, y2); |
| 21854 |
xa = x + stack.shift(); |
| 21855 |
xb = xa + stack.shift(); y3 = y2 + stack.shift(); |
| 21856 |
x = xb + stack.shift(); |
| 21857 |
bezierCurveTo(xa, y2, xb, y3, x, y); |
| 21858 |
break; |
| 21859 |
case 37: // flex1 |
| 21860 |
var x0 = x, y0 = y; |
| 21861 |
xa = x + stack.shift(); ya = y + stack.shift(); |
| 21862 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21863 |
x = xb + stack.shift(); y = yb + stack.shift(); |
| 21864 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21865 |
xa = x + stack.shift(); ya = y + stack.shift(); |
| 21866 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21867 |
x = xb; y = yb; |
| 21868 |
if (Math.abs(x - x0) > Math.abs(y - y0)) { |
| 21869 |
x += stack.shift(); |
| 21870 |
} else { |
| 21871 |
y += stack.shift(); |
| 21872 |
} |
| 21873 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21874 |
break; |
| 21875 |
default: |
| 21876 |
error('unknown operator: 12 ' + v); |
| 21877 |
} |
| 21878 |
break; |
| 21879 |
case 14: // endchar |
| 21880 |
if (stack.length >= 4) { |
| 21881 |
var achar = stack.pop(); |
| 21882 |
var bchar = stack.pop(); |
| 21883 |
y = stack.pop(); |
| 21884 |
x = stack.pop(); |
| 21885 |
js.push('c.save();'); |
| 21886 |
js.push('c.translate('+ x + ',' + y + ');'); |
| 21887 |
var gid = lookupCmap(font.cmap, String.fromCharCode( |
| 21888 |
font.glyphNameMap[Encodings.StandardEncoding[achar]])); |
| 21889 |
compileCharString(font.glyphs[gid], js, font); |
| 21890 |
js.push('c.restore();'); |
| 21891 |
|
| 21892 |
gid = lookupCmap(font.cmap, String.fromCharCode( |
| 21893 |
font.glyphNameMap[Encodings.StandardEncoding[bchar]])); |
| 21894 |
compileCharString(font.glyphs[gid], js, font); |
| 21895 |
} |
| 21896 |
return; |
| 21897 |
case 18: // hstemhm |
| 21898 |
stems += stack.length >> 1; |
| 21899 |
stackClean = true; |
| 21900 |
break; |
| 21901 |
case 19: // hintmask |
| 21902 |
stems += stack.length >> 1; |
| 21903 |
i += (stems + 7) >> 3; |
| 21904 |
stackClean = true; |
| 21905 |
break; |
| 21906 |
case 20: // cntrmask |
| 21907 |
stems += stack.length >> 1; |
| 21908 |
i += (stems + 7) >> 3; |
| 21909 |
stackClean = true; |
| 21910 |
break; |
| 21911 |
case 21: // rmoveto |
| 21912 |
y += stack.pop(); |
| 21913 |
x += stack.pop(); |
| 21914 |
moveTo(x, y); |
| 21915 |
stackClean = true; |
| 21916 |
break; |
| 21917 |
case 22: // hmoveto |
| 21918 |
x += stack.pop(); |
| 21919 |
moveTo(x, y); |
| 21920 |
stackClean = true; |
| 21921 |
break; |
| 21922 |
case 23: // vstemhm |
| 21923 |
stems += stack.length >> 1; |
| 21924 |
stackClean = true; |
| 21925 |
break; |
| 21926 |
case 24: // rcurveline |
| 21927 |
while (stack.length > 2) { |
| 21928 |
xa = x + stack.shift(); ya = y + stack.shift(); |
| 21929 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21930 |
x = xb + stack.shift(); y = yb + stack.shift(); |
| 21931 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21932 |
} |
| 21933 |
x += stack.shift(); |
| 21934 |
y += stack.shift(); |
| 21935 |
lineTo(x, y); |
| 21936 |
break; |
| 21937 |
case 25: // rlinecurve |
| 21938 |
while (stack.length > 6) { |
| 21939 |
x += stack.shift(); |
| 21940 |
y += stack.shift(); |
| 21941 |
lineTo(x, y); |
| 21942 |
} |
| 21943 |
xa = x + stack.shift(); ya = y + stack.shift(); |
| 21944 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21945 |
x = xb + stack.shift(); y = yb + stack.shift(); |
| 21946 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21947 |
break; |
| 21948 |
case 26: // vvcurveto |
| 21949 |
if (stack.length % 2) { |
| 21950 |
x += stack.shift(); |
| 21951 |
} |
| 21952 |
while (stack.length > 0) { |
| 21953 |
xa = x; ya = y + stack.shift(); |
| 21954 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21955 |
x = xb; y = yb + stack.shift(); |
| 21956 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21957 |
} |
| 21958 |
break; |
| 21959 |
case 27: // hhcurveto |
| 21960 |
if (stack.length % 2) { |
| 21961 |
y += stack.shift(); |
| 21962 |
} |
| 21963 |
while (stack.length > 0) { |
| 21964 |
xa = x + stack.shift(); ya = y; |
| 21965 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21966 |
x = xb + stack.shift(); y = yb; |
| 21967 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21968 |
} |
| 21969 |
break; |
| 21970 |
case 28: |
| 21971 |
stack.push(((code[i] << 24) | (code[i + 1] << 16)) >> 16); |
| 21972 |
i += 2; |
| 21973 |
break; |
| 21974 |
case 29: // callgsubr |
| 21975 |
n = stack.pop() + font.gsubrsBias; |
| 21976 |
subrCode = font.gsubrs[n]; |
| 21977 |
if (subrCode) { |
| 21978 |
parse(subrCode); |
| 21979 |
} |
| 21980 |
break; |
| 21981 |
case 30: // vhcurveto |
| 21982 |
while (stack.length > 0) { |
| 21983 |
xa = x; ya = y + stack.shift(); |
| 21984 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21985 |
x = xb + stack.shift(); |
| 21986 |
y = yb + (stack.length === 1 ? stack.shift() : 0); |
| 21987 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21988 |
if (stack.length === 0) { |
| 21989 |
break; |
| 21990 |
} |
| 21991 |
|
| 21992 |
xa = x + stack.shift(); ya = y; |
| 21993 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 21994 |
y = yb + stack.shift(); |
| 21995 |
x = xb + (stack.length === 1 ? stack.shift() : 0); |
| 21996 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 21997 |
} |
| 21998 |
break; |
| 21999 |
case 31: // hvcurveto |
| 22000 |
while (stack.length > 0) { |
| 22001 |
xa = x + stack.shift(); ya = y; |
| 22002 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 22003 |
y = yb + stack.shift(); |
| 22004 |
x = xb + (stack.length === 1 ? stack.shift() : 0); |
| 22005 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 22006 |
if (stack.length === 0) { |
| 22007 |
break; |
| 22008 |
} |
| 22009 |
|
| 22010 |
xa = x; ya = y + stack.shift(); |
| 22011 |
xb = xa + stack.shift(); yb = ya + stack.shift(); |
| 22012 |
x = xb + stack.shift(); |
| 22013 |
y = yb + (stack.length === 1 ? stack.shift() : 0); |
| 22014 |
bezierCurveTo(xa, ya, xb, yb, x, y); |
| 22015 |
} |
| 22016 |
break; |
| 22017 |
default: |
| 22018 |
if (v < 32) { |
| 22019 |
error('unknown operator: ' + v); |
| 22020 |
} |
| 22021 |
if (v < 247) { |
| 22022 |
stack.push(v - 139); |
| 22023 |
} else if (v < 251) { |
| 22024 |
stack.push((v - 247) * 256 + code[i++] + 108); |
| 22025 |
} else if (v < 255) { |
| 22026 |
stack.push(-(v - 251) * 256 - code[i++] - 108); |
| 22027 |
} else { |
| 22028 |
stack.push(((code[i] << 24) | (code[i + 1] << 16) | |
| 22029 |
(code[i + 2] << 8) | code[i + 3]) / 65536); |
| 22030 |
i += 4; |
| 22031 |
} |
| 22032 |
break; |
| 22033 |
} |
| 22034 |
if (stackClean) { |
| 22035 |
stack.length = 0; |
| 22036 |
} |
| 22037 |
} |
| 22038 |
} |
| 22039 |
parse(code); |
| 22040 |
} |
| 22041 |
|
| 22042 |
var noop = ''; |
| 22043 |
|
| 22044 |
function CompiledFont(fontMatrix) { |
| 22045 |
this.compiledGlyphs = {}; |
| 22046 |
this.fontMatrix = fontMatrix; |
| 22047 |
} |
| 22048 |
CompiledFont.prototype = { |
| 22049 |
getPathJs: function (unicode) { |
| 22050 |
var gid = lookupCmap(this.cmap, unicode); |
| 22051 |
var fn = this.compiledGlyphs[gid]; |
| 22052 |
if (!fn) { |
| 22053 |
this.compiledGlyphs[gid] = fn = this.compileGlyph(this.glyphs[gid]); |
| 22054 |
} |
| 22055 |
return fn; |
| 22056 |
}, |
| 22057 |
|
| 22058 |
compileGlyph: function (code) { |
| 22059 |
if (!code || code.length === 0 || code[0] === 14) { |
| 22060 |
return noop; |
| 22061 |
} |
| 22062 |
|
| 22063 |
var js = []; |
| 22064 |
js.push('c.save();'); |
| 22065 |
js.push('c.transform(' + this.fontMatrix.join(',') + ');'); |
| 22066 |
js.push('c.scale(size, -size);'); |
| 22067 |
|
| 22068 |
this.compileGlyphImpl(code, js); |
| 22069 |
|
| 22070 |
js.push('c.restore();'); |
| 22071 |
|
| 22072 |
return js.join('\n'); |
| 22073 |
}, |
| 22074 |
|
| 22075 |
compileGlyphImpl: function () { |
| 22076 |
error('Children classes should implement this.'); |
| 22077 |
}, |
| 22078 |
|
| 22079 |
hasBuiltPath: function (unicode) { |
| 22080 |
var gid = lookupCmap(this.cmap, unicode); |
| 22081 |
return gid in this.compiledGlyphs; |
| 22082 |
} |
| 22083 |
}; |
| 22084 |
|
| 22085 |
function TrueTypeCompiled(glyphs, cmap, fontMatrix) { |
| 22086 |
fontMatrix = fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]; |
| 22087 |
CompiledFont.call(this, fontMatrix); |
| 22088 |
|
| 22089 |
this.glyphs = glyphs; |
| 22090 |
this.cmap = cmap; |
| 22091 |
|
| 22092 |
this.compiledGlyphs = []; |
| 22093 |
} |
| 22094 |
|
| 22095 |
Util.inherit(TrueTypeCompiled, CompiledFont, { |
| 22096 |
compileGlyphImpl: function (code, js) { |
| 22097 |
compileGlyf(code, js, this); |
| 22098 |
} |
| 22099 |
}); |
| 22100 |
|
| 22101 |
function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) { |
| 22102 |
fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0]; |
| 22103 |
CompiledFont.call(this, fontMatrix); |
| 22104 |
this.glyphs = cffInfo.glyphs; |
| 22105 |
this.gsubrs = cffInfo.gsubrs || []; |
| 22106 |
this.subrs = cffInfo.subrs || []; |
| 22107 |
this.cmap = cmap; |
| 22108 |
this.glyphNameMap = glyphNameMap || GlyphsUnicode; |
| 22109 |
|
| 22110 |
this.compiledGlyphs = []; |
| 22111 |
this.gsubrsBias = (this.gsubrs.length < 1240 ? |
| 22112 |
107 : (this.gsubrs.length < 33900 ? 1131 : 32768)); |
| 22113 |
this.subrsBias = (this.subrs.length < 1240 ? |
| 22114 |
107 : (this.subrs.length < 33900 ? 1131 : 32768)); |
| 22115 |
} |
| 22116 |
|
| 22117 |
Util.inherit(Type2Compiled, CompiledFont, { |
| 22118 |
compileGlyphImpl: function (code, js) { |
| 22119 |
compileCharString(code, js, this); |
| 22120 |
} |
| 22121 |
}); |
| 22122 |
|
| 22123 |
|
| 22124 |
return { |
| 22125 |
create: function FontRendererFactory_create(font) { |
| 22126 |
var data = new Uint8Array(font.data); |
| 22127 |
var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; |
| 22128 |
var numTables = getUshort(data, 4); |
| 22129 |
for (var i = 0, p = 12; i < numTables; i++, p += 16) { |
| 22130 |
var tag = bytesToString(data.subarray(p, p + 4)); |
| 22131 |
var offset = getLong(data, p + 8); |
| 22132 |
var length = getLong(data, p + 12); |
| 22133 |
switch (tag) { |
| 22134 |
case 'cmap': |
| 22135 |
cmap = parseCmap(data, offset, offset + length); |
| 22136 |
break; |
| 22137 |
case 'glyf': |
| 22138 |
glyf = data.subarray(offset, offset + length); |
| 22139 |
break; |
| 22140 |
case 'loca': |
| 22141 |
loca = data.subarray(offset, offset + length); |
| 22142 |
break; |
| 22143 |
case 'head': |
| 22144 |
unitsPerEm = getUshort(data, offset + 18); |
| 22145 |
indexToLocFormat = getUshort(data, offset + 50); |
| 22146 |
break; |
| 22147 |
case 'CFF ': |
| 22148 |
cff = parseCff(data, offset, offset + length); |
| 22149 |
break; |
| 22150 |
} |
| 22151 |
} |
| 22152 |
|
| 22153 |
if (glyf) { |
| 22154 |
var fontMatrix = (!unitsPerEm ? font.fontMatrix : |
| 22155 |
[1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]); |
| 22156 |
return new TrueTypeCompiled( |
| 22157 |
parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); |
| 22158 |
} else { |
| 22159 |
return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap); |
| 22160 |
} |
| 22161 |
} |
| 22162 |
}; |
| 22163 |
})(); |
| 22164 |
|
| 22165 |
|
| 22166 |
var GlyphsUnicode = { |
| 22167 |
A: 0x0041, |
| 22168 |
AE: 0x00C6, |
| 22169 |
AEacute: 0x01FC, |
| 22170 |
AEmacron: 0x01E2, |
| 22171 |
AEsmall: 0xF7E6, |
| 22172 |
Aacute: 0x00C1, |
| 22173 |
Aacutesmall: 0xF7E1, |
| 22174 |
Abreve: 0x0102, |
| 22175 |
Abreveacute: 0x1EAE, |
| 22176 |
Abrevecyrillic: 0x04D0, |
| 22177 |
Abrevedotbelow: 0x1EB6, |
| 22178 |
Abrevegrave: 0x1EB0, |
| 22179 |
Abrevehookabove: 0x1EB2, |
| 22180 |
Abrevetilde: 0x1EB4, |
| 22181 |
Acaron: 0x01CD, |
| 22182 |
Acircle: 0x24B6, |
| 22183 |
Acircumflex: 0x00C2, |
| 22184 |
Acircumflexacute: 0x1EA4, |
| 22185 |
Acircumflexdotbelow: 0x1EAC, |
| 22186 |
Acircumflexgrave: 0x1EA6, |
| 22187 |
Acircumflexhookabove: 0x1EA8, |
| 22188 |
Acircumflexsmall: 0xF7E2, |
| 22189 |
Acircumflextilde: 0x1EAA, |
| 22190 |
Acute: 0xF6C9, |
| 22191 |
Acutesmall: 0xF7B4, |
| 22192 |
Acyrillic: 0x0410, |
| 22193 |
Adblgrave: 0x0200, |
| 22194 |
Adieresis: 0x00C4, |
| 22195 |
Adieresiscyrillic: 0x04D2, |
| 22196 |
Adieresismacron: 0x01DE, |
| 22197 |
Adieresissmall: 0xF7E4, |
| 22198 |
Adotbelow: 0x1EA0, |
| 22199 |
Adotmacron: 0x01E0, |
| 22200 |
Agrave: 0x00C0, |
| 22201 |
Agravesmall: 0xF7E0, |
| 22202 |
Ahookabove: 0x1EA2, |
| 22203 |
Aiecyrillic: 0x04D4, |
| 22204 |
Ainvertedbreve: 0x0202, |
| 22205 |
Alpha: 0x0391, |
| 22206 |
Alphatonos: 0x0386, |
| 22207 |
Amacron: 0x0100, |
| 22208 |
Amonospace: 0xFF21, |
| 22209 |
Aogonek: 0x0104, |
| 22210 |
Aring: 0x00C5, |
| 22211 |
Aringacute: 0x01FA, |
| 22212 |
Aringbelow: 0x1E00, |
| 22213 |
Aringsmall: 0xF7E5, |
| 22214 |
Asmall: 0xF761, |
| 22215 |
Atilde: 0x00C3, |
| 22216 |
Atildesmall: 0xF7E3, |
| 22217 |
Aybarmenian: 0x0531, |
| 22218 |
B: 0x0042, |
| 22219 |
Bcircle: 0x24B7, |
| 22220 |
Bdotaccent: 0x1E02, |
| 22221 |
Bdotbelow: 0x1E04, |
| 22222 |
Becyrillic: 0x0411, |
| 22223 |
Benarmenian: 0x0532, |
| 22224 |
Beta: 0x0392, |
| 22225 |
Bhook: 0x0181, |
| 22226 |
Blinebelow: 0x1E06, |
| 22227 |
Bmonospace: 0xFF22, |
| 22228 |
Brevesmall: 0xF6F4, |
| 22229 |
Bsmall: 0xF762, |
| 22230 |
Btopbar: 0x0182, |
| 22231 |
C: 0x0043, |
| 22232 |
Caarmenian: 0x053E, |
| 22233 |
Cacute: 0x0106, |
| 22234 |
Caron: 0xF6CA, |
| 22235 |
Caronsmall: 0xF6F5, |
| 22236 |
Ccaron: 0x010C, |
| 22237 |
Ccedilla: 0x00C7, |
| 22238 |
Ccedillaacute: 0x1E08, |
| 22239 |
Ccedillasmall: 0xF7E7, |
| 22240 |
Ccircle: 0x24B8, |
| 22241 |
Ccircumflex: 0x0108, |
| 22242 |
Cdot: 0x010A, |
| 22243 |
Cdotaccent: 0x010A, |
| 22244 |
Cedillasmall: 0xF7B8, |
| 22245 |
Chaarmenian: 0x0549, |
| 22246 |
Cheabkhasiancyrillic: 0x04BC, |
| 22247 |
Checyrillic: 0x0427, |
| 22248 |
Chedescenderabkhasiancyrillic: 0x04BE, |
| 22249 |
Chedescendercyrillic: 0x04B6, |
| 22250 |
Chedieresiscyrillic: 0x04F4, |
| 22251 |
Cheharmenian: 0x0543, |
| 22252 |
Chekhakassiancyrillic: 0x04CB, |
| 22253 |
Cheverticalstrokecyrillic: 0x04B8, |
| 22254 |
Chi: 0x03A7, |
| 22255 |
Chook: 0x0187, |
| 22256 |
Circumflexsmall: 0xF6F6, |
| 22257 |
Cmonospace: 0xFF23, |
| 22258 |
Coarmenian: 0x0551, |
| 22259 |
Csmall: 0xF763, |
| 22260 |
D: 0x0044, |
| 22261 |
DZ: 0x01F1, |
| 22262 |
DZcaron: 0x01C4, |
| 22263 |
Daarmenian: 0x0534, |
| 22264 |
Dafrican: 0x0189, |
| 22265 |
Dcaron: 0x010E, |
| 22266 |
Dcedilla: 0x1E10, |
| 22267 |
Dcircle: 0x24B9, |
| 22268 |
Dcircumflexbelow: 0x1E12, |
| 22269 |
Dcroat: 0x0110, |
| 22270 |
Ddotaccent: 0x1E0A, |
| 22271 |
Ddotbelow: 0x1E0C, |
| 22272 |
Decyrillic: 0x0414, |
| 22273 |
Deicoptic: 0x03EE, |
| 22274 |
Delta: 0x2206, |
| 22275 |
Deltagreek: 0x0394, |
| 22276 |
Dhook: 0x018A, |
| 22277 |
Dieresis: 0xF6CB, |
| 22278 |
DieresisAcute: 0xF6CC, |
| 22279 |
DieresisGrave: 0xF6CD, |
| 22280 |
Dieresissmall: 0xF7A8, |
| 22281 |
Digammagreek: 0x03DC, |
| 22282 |
Djecyrillic: 0x0402, |
| 22283 |
Dlinebelow: 0x1E0E, |
| 22284 |
Dmonospace: 0xFF24, |
| 22285 |
Dotaccentsmall: 0xF6F7, |
| 22286 |
Dslash: 0x0110, |
| 22287 |
Dsmall: 0xF764, |
| 22288 |
Dtopbar: 0x018B, |
| 22289 |
Dz: 0x01F2, |
| 22290 |
Dzcaron: 0x01C5, |
| 22291 |
Dzeabkhasiancyrillic: 0x04E0, |
| 22292 |
Dzecyrillic: 0x0405, |
| 22293 |
Dzhecyrillic: 0x040F, |
| 22294 |
E: 0x0045, |
| 22295 |
Eacute: 0x00C9, |
| 22296 |
Eacutesmall: 0xF7E9, |
| 22297 |
Ebreve: 0x0114, |
| 22298 |
Ecaron: 0x011A, |
| 22299 |
Ecedillabreve: 0x1E1C, |
| 22300 |
Echarmenian: 0x0535, |
| 22301 |
Ecircle: 0x24BA, |
| 22302 |
Ecircumflex: 0x00CA, |
| 22303 |
Ecircumflexacute: 0x1EBE, |
| 22304 |
Ecircumflexbelow: 0x1E18, |
| 22305 |
Ecircumflexdotbelow: 0x1EC6, |
| 22306 |
Ecircumflexgrave: 0x1EC0, |
| 22307 |
Ecircumflexhookabove: 0x1EC2, |
| 22308 |
Ecircumflexsmall: 0xF7EA, |
| 22309 |
Ecircumflextilde: 0x1EC4, |
| 22310 |
Ecyrillic: 0x0404, |
| 22311 |
Edblgrave: 0x0204, |
| 22312 |
Edieresis: 0x00CB, |
| 22313 |
Edieresissmall: 0xF7EB, |
| 22314 |
Edot: 0x0116, |
| 22315 |
Edotaccent: 0x0116, |
| 22316 |
Edotbelow: 0x1EB8, |
| 22317 |
Efcyrillic: 0x0424, |
| 22318 |
Egrave: 0x00C8, |
| 22319 |
Egravesmall: 0xF7E8, |
| 22320 |
Eharmenian: 0x0537, |
| 22321 |
Ehookabove: 0x1EBA, |
| 22322 |
Eightroman: 0x2167, |
| 22323 |
Einvertedbreve: 0x0206, |
| 22324 |
Eiotifiedcyrillic: 0x0464, |
| 22325 |
Elcyrillic: 0x041B, |
| 22326 |
Elevenroman: 0x216A, |
| 22327 |
Emacron: 0x0112, |
| 22328 |
Emacronacute: 0x1E16, |
| 22329 |
Emacrongrave: 0x1E14, |
| 22330 |
Emcyrillic: 0x041C, |
| 22331 |
Emonospace: 0xFF25, |
| 22332 |
Encyrillic: 0x041D, |
| 22333 |
Endescendercyrillic: 0x04A2, |
| 22334 |
Eng: 0x014A, |
| 22335 |
Enghecyrillic: 0x04A4, |
| 22336 |
Enhookcyrillic: 0x04C7, |
| 22337 |
Eogonek: 0x0118, |
| 22338 |
Eopen: 0x0190, |
| 22339 |
Epsilon: 0x0395, |
| 22340 |
Epsilontonos: 0x0388, |
| 22341 |
Ercyrillic: 0x0420, |
| 22342 |
Ereversed: 0x018E, |
| 22343 |
Ereversedcyrillic: 0x042D, |
| 22344 |
Escyrillic: 0x0421, |
| 22345 |
Esdescendercyrillic: 0x04AA, |
| 22346 |
Esh: 0x01A9, |
| 22347 |
Esmall: 0xF765, |
| 22348 |
Eta: 0x0397, |
| 22349 |
Etarmenian: 0x0538, |
| 22350 |
Etatonos: 0x0389, |
| 22351 |
Eth: 0x00D0, |
| 22352 |
Ethsmall: 0xF7F0, |
| 22353 |
Etilde: 0x1EBC, |
| 22354 |
Etildebelow: 0x1E1A, |
| 22355 |
Euro: 0x20AC, |
| 22356 |
Ezh: 0x01B7, |
| 22357 |
Ezhcaron: 0x01EE, |
| 22358 |
Ezhreversed: 0x01B8, |
| 22359 |
F: 0x0046, |
| 22360 |
Fcircle: 0x24BB, |
| 22361 |
Fdotaccent: 0x1E1E, |
| 22362 |
Feharmenian: 0x0556, |
| 22363 |
Feicoptic: 0x03E4, |
| 22364 |
Fhook: 0x0191, |
| 22365 |
Fitacyrillic: 0x0472, |
| 22366 |
Fiveroman: 0x2164, |
| 22367 |
Fmonospace: 0xFF26, |
| 22368 |
Fourroman: 0x2163, |
| 22369 |
Fsmall: 0xF766, |
| 22370 |
G: 0x0047, |
| 22371 |
GBsquare: 0x3387, |
| 22372 |
Gacute: 0x01F4, |
| 22373 |
Gamma: 0x0393, |
| 22374 |
Gammaafrican: 0x0194, |
| 22375 |
Gangiacoptic: 0x03EA, |
| 22376 |
Gbreve: 0x011E, |
| 22377 |
Gcaron: 0x01E6, |
| 22378 |
Gcedilla: 0x0122, |
| 22379 |
Gcircle: 0x24BC, |
| 22380 |
Gcircumflex: 0x011C, |
| 22381 |
Gcommaaccent: 0x0122, |
| 22382 |
Gdot: 0x0120, |
| 22383 |
Gdotaccent: 0x0120, |
| 22384 |
Gecyrillic: 0x0413, |
| 22385 |
Ghadarmenian: 0x0542, |
| 22386 |
Ghemiddlehookcyrillic: 0x0494, |
| 22387 |
Ghestrokecyrillic: 0x0492, |
| 22388 |
Gheupturncyrillic: 0x0490, |
| 22389 |
Ghook: 0x0193, |
| 22390 |
Gimarmenian: 0x0533, |
| 22391 |
Gjecyrillic: 0x0403, |
| 22392 |
Gmacron: 0x1E20, |
| 22393 |
Gmonospace: 0xFF27, |
| 22394 |
Grave: 0xF6CE, |
| 22395 |
Gravesmall: 0xF760, |
| 22396 |
Gsmall: 0xF767, |
| 22397 |
Gsmallhook: 0x029B, |
| 22398 |
Gstroke: 0x01E4, |
| 22399 |
H: 0x0048, |
| 22400 |
H18533: 0x25CF, |
| 22401 |
H18543: 0x25AA, |
| 22402 |
H18551: 0x25AB, |
| 22403 |
H22073: 0x25A1, |
| 22404 |
HPsquare: 0x33CB, |
| 22405 |
Haabkhasiancyrillic: 0x04A8, |
| 22406 |
Hadescendercyrillic: 0x04B2, |
| 22407 |
Hardsigncyrillic: 0x042A, |
| 22408 |
Hbar: 0x0126, |
| 22409 |
Hbrevebelow: 0x1E2A, |
| 22410 |
Hcedilla: 0x1E28, |
| 22411 |
Hcircle: 0x24BD, |
| 22412 |
Hcircumflex: 0x0124, |
| 22413 |
Hdieresis: 0x1E26, |
| 22414 |
Hdotaccent: 0x1E22, |
| 22415 |
Hdotbelow: 0x1E24, |
| 22416 |
Hmonospace: 0xFF28, |
| 22417 |
Hoarmenian: 0x0540, |
| 22418 |
Horicoptic: 0x03E8, |
| 22419 |
Hsmall: 0xF768, |
| 22420 |
Hungarumlaut: 0xF6CF, |
| 22421 |
Hungarumlautsmall: 0xF6F8, |
| 22422 |
Hzsquare: 0x3390, |
| 22423 |
I: 0x0049, |
| 22424 |
IAcyrillic: 0x042F, |
| 22425 |
IJ: 0x0132, |
| 22426 |
IUcyrillic: 0x042E, |
| 22427 |
Iacute: 0x00CD, |
| 22428 |
Iacutesmall: 0xF7ED, |
| 22429 |
Ibreve: 0x012C, |
| 22430 |
Icaron: 0x01CF, |
| 22431 |
Icircle: 0x24BE, |
| 22432 |
Icircumflex: 0x00CE, |
| 22433 |
Icircumflexsmall: 0xF7EE, |
| 22434 |
Icyrillic: 0x0406, |
| 22435 |
Idblgrave: 0x0208, |
| 22436 |
Idieresis: 0x00CF, |
| 22437 |
Idieresisacute: 0x1E2E, |
| 22438 |
Idieresiscyrillic: 0x04E4, |
| 22439 |
Idieresissmall: 0xF7EF, |
| 22440 |
Idot: 0x0130, |
| 22441 |
Idotaccent: 0x0130, |
| 22442 |
Idotbelow: 0x1ECA, |
| 22443 |
Iebrevecyrillic: 0x04D6, |
| 22444 |
Iecyrillic: 0x0415, |
| 22445 |
Ifraktur: 0x2111, |
| 22446 |
Igrave: 0x00CC, |
| 22447 |
Igravesmall: 0xF7EC, |
| 22448 |
Ihookabove: 0x1EC8, |
| 22449 |
Iicyrillic: 0x0418, |
| 22450 |
Iinvertedbreve: 0x020A, |
| 22451 |
Iishortcyrillic: 0x0419, |
| 22452 |
Imacron: 0x012A, |
| 22453 |
Imacroncyrillic: 0x04E2, |
| 22454 |
Imonospace: 0xFF29, |
| 22455 |
Iniarmenian: 0x053B, |
| 22456 |
Iocyrillic: 0x0401, |
| 22457 |
Iogonek: 0x012E, |
| 22458 |
Iota: 0x0399, |
| 22459 |
Iotaafrican: 0x0196, |
| 22460 |
Iotadieresis: 0x03AA, |
| 22461 |
Iotatonos: 0x038A, |
| 22462 |
Ismall: 0xF769, |
| 22463 |
Istroke: 0x0197, |
| 22464 |
Itilde: 0x0128, |
| 22465 |
Itildebelow: 0x1E2C, |
| 22466 |
Izhitsacyrillic: 0x0474, |
| 22467 |
Izhitsadblgravecyrillic: 0x0476, |
| 22468 |
J: 0x004A, |
| 22469 |
Jaarmenian: 0x0541, |
| 22470 |
Jcircle: 0x24BF, |
| 22471 |
Jcircumflex: 0x0134, |
| 22472 |
Jecyrillic: 0x0408, |
| 22473 |
Jheharmenian: 0x054B, |
| 22474 |
Jmonospace: 0xFF2A, |
| 22475 |
Jsmall: 0xF76A, |
| 22476 |
K: 0x004B, |
| 22477 |
KBsquare: 0x3385, |
| 22478 |
KKsquare: 0x33CD, |
| 22479 |
Kabashkircyrillic: 0x04A0, |
| 22480 |
Kacute: 0x1E30, |
| 22481 |
Kacyrillic: 0x041A, |
| 22482 |
Kadescendercyrillic: 0x049A, |
| 22483 |
Kahookcyrillic: 0x04C3, |
| 22484 |
Kappa: 0x039A, |
| 22485 |
Kastrokecyrillic: 0x049E, |
| 22486 |
Kaverticalstrokecyrillic: 0x049C, |
| 22487 |
Kcaron: 0x01E8, |
| 22488 |
Kcedilla: 0x0136, |
| 22489 |
Kcircle: 0x24C0, |
| 22490 |
Kcommaaccent: 0x0136, |
| 22491 |
Kdotbelow: 0x1E32, |
| 22492 |
Keharmenian: 0x0554, |
| 22493 |
Kenarmenian: 0x053F, |
| 22494 |
Khacyrillic: 0x0425, |
| 22495 |
Kheicoptic: 0x03E6, |
| 22496 |
Khook: 0x0198, |
| 22497 |
Kjecyrillic: 0x040C, |
| 22498 |
Klinebelow: 0x1E34, |
| 22499 |
Kmonospace: 0xFF2B, |
| 22500 |
Koppacyrillic: 0x0480, |
| 22501 |
Koppagreek: 0x03DE, |
| 22502 |
Ksicyrillic: 0x046E, |
| 22503 |
Ksmall: 0xF76B, |
| 22504 |
L: 0x004C, |
| 22505 |
LJ: 0x01C7, |
| 22506 |
LL: 0xF6BF, |
| 22507 |
Lacute: 0x0139, |
| 22508 |
Lambda: 0x039B, |
| 22509 |
Lcaron: 0x013D, |
| 22510 |
Lcedilla: 0x013B, |
| 22511 |
Lcircle: 0x24C1, |
| 22512 |
Lcircumflexbelow: 0x1E3C, |
| 22513 |
Lcommaaccent: 0x013B, |
| 22514 |
Ldot: 0x013F, |
| 22515 |
Ldotaccent: 0x013F, |
| 22516 |
Ldotbelow: 0x1E36, |
| 22517 |
Ldotbelowmacron: 0x1E38, |
| 22518 |
Liwnarmenian: 0x053C, |
| 22519 |
Lj: 0x01C8, |
| 22520 |
Ljecyrillic: 0x0409, |
| 22521 |
Llinebelow: 0x1E3A, |
| 22522 |
Lmonospace: 0xFF2C, |
| 22523 |
Lslash: 0x0141, |
| 22524 |
Lslashsmall: 0xF6F9, |
| 22525 |
Lsmall: 0xF76C, |
| 22526 |
M: 0x004D, |
| 22527 |
MBsquare: 0x3386, |
| 22528 |
Macron: 0xF6D0, |
| 22529 |
Macronsmall: 0xF7AF, |
| 22530 |
Macute: 0x1E3E, |
| 22531 |
Mcircle: 0x24C2, |
| 22532 |
Mdotaccent: 0x1E40, |
| 22533 |
Mdotbelow: 0x1E42, |
| 22534 |
Menarmenian: 0x0544, |
| 22535 |
Mmonospace: 0xFF2D, |
| 22536 |
Msmall: 0xF76D, |
| 22537 |
Mturned: 0x019C, |
| 22538 |
Mu: 0x039C, |
| 22539 |
N: 0x004E, |
| 22540 |
NJ: 0x01CA, |
| 22541 |
Nacute: 0x0143, |
| 22542 |
Ncaron: 0x0147, |
| 22543 |
Ncedilla: 0x0145, |
| 22544 |
Ncircle: 0x24C3, |
| 22545 |
Ncircumflexbelow: 0x1E4A, |
| 22546 |
Ncommaaccent: 0x0145, |
| 22547 |
Ndotaccent: 0x1E44, |
| 22548 |
Ndotbelow: 0x1E46, |
| 22549 |
Nhookleft: 0x019D, |
| 22550 |
Nineroman: 0x2168, |
| 22551 |
Nj: 0x01CB, |
| 22552 |
Njecyrillic: 0x040A, |
| 22553 |
Nlinebelow: 0x1E48, |
| 22554 |
Nmonospace: 0xFF2E, |
| 22555 |
Nowarmenian: 0x0546, |
| 22556 |
Nsmall: 0xF76E, |
| 22557 |
Ntilde: 0x00D1, |
| 22558 |
Ntildesmall: 0xF7F1, |
| 22559 |
Nu: 0x039D, |
| 22560 |
O: 0x004F, |
| 22561 |
OE: 0x0152, |
| 22562 |
OEsmall: 0xF6FA, |
| 22563 |
Oacute: 0x00D3, |
| 22564 |
Oacutesmall: 0xF7F3, |
| 22565 |
Obarredcyrillic: 0x04E8, |
| 22566 |
Obarreddieresiscyrillic: 0x04EA, |
| 22567 |
Obreve: 0x014E, |
| 22568 |
Ocaron: 0x01D1, |
| 22569 |
Ocenteredtilde: 0x019F, |
| 22570 |
Ocircle: 0x24C4, |
| 22571 |
Ocircumflex: 0x00D4, |
| 22572 |
Ocircumflexacute: 0x1ED0, |
| 22573 |
Ocircumflexdotbelow: 0x1ED8, |
| 22574 |
Ocircumflexgrave: 0x1ED2, |
| 22575 |
Ocircumflexhookabove: 0x1ED4, |
| 22576 |
Ocircumflexsmall: 0xF7F4, |
| 22577 |
Ocircumflextilde: 0x1ED6, |
| 22578 |
Ocyrillic: 0x041E, |
| 22579 |
Odblacute: 0x0150, |
| 22580 |
Odblgrave: 0x020C, |
| 22581 |
Odieresis: 0x00D6, |
| 22582 |
Odieresiscyrillic: 0x04E6, |
| 22583 |
Odieresissmall: 0xF7F6, |
| 22584 |
Odotbelow: 0x1ECC, |
| 22585 |
Ogoneksmall: 0xF6FB, |
| 22586 |
Ograve: 0x00D2, |
| 22587 |
Ogravesmall: 0xF7F2, |
| 22588 |
Oharmenian: 0x0555, |
| 22589 |
Ohm: 0x2126, |
| 22590 |
Ohookabove: 0x1ECE, |
| 22591 |
Ohorn: 0x01A0, |
| 22592 |
Ohornacute: 0x1EDA, |
| 22593 |
Ohorndotbelow: 0x1EE2, |
| 22594 |
Ohorngrave: 0x1EDC, |
| 22595 |
Ohornhookabove: 0x1EDE, |
| 22596 |
Ohorntilde: 0x1EE0, |
| 22597 |
Ohungarumlaut: 0x0150, |
| 22598 |
Oi: 0x01A2, |
| 22599 |
Oinvertedbreve: 0x020E, |
| 22600 |
Omacron: 0x014C, |
| 22601 |
Omacronacute: 0x1E52, |
| 22602 |
Omacrongrave: 0x1E50, |
| 22603 |
Omega: 0x2126, |
| 22604 |
Omegacyrillic: 0x0460, |
| 22605 |
Omegagreek: 0x03A9, |
| 22606 |
Omegaroundcyrillic: 0x047A, |
| 22607 |
Omegatitlocyrillic: 0x047C, |
| 22608 |
Omegatonos: 0x038F, |
| 22609 |
Omicron: 0x039F, |
| 22610 |
Omicrontonos: 0x038C, |
| 22611 |
Omonospace: 0xFF2F, |
| 22612 |
Oneroman: 0x2160, |
| 22613 |
Oogonek: 0x01EA, |
| 22614 |
Oogonekmacron: 0x01EC, |
| 22615 |
Oopen: 0x0186, |
| 22616 |
Oslash: 0x00D8, |
| 22617 |
Oslashacute: 0x01FE, |
| 22618 |
Oslashsmall: 0xF7F8, |
| 22619 |
Osmall: 0xF76F, |
| 22620 |
Ostrokeacute: 0x01FE, |
| 22621 |
Otcyrillic: 0x047E, |
| 22622 |
Otilde: 0x00D5, |
| 22623 |
Otildeacute: 0x1E4C, |
| 22624 |
Otildedieresis: 0x1E4E, |
| 22625 |
Otildesmall: 0xF7F5, |
| 22626 |
P: 0x0050, |
| 22627 |
Pacute: 0x1E54, |
| 22628 |
Pcircle: 0x24C5, |
| 22629 |
Pdotaccent: 0x1E56, |
| 22630 |
Pecyrillic: 0x041F, |
| 22631 |
Peharmenian: 0x054A, |
| 22632 |
Pemiddlehookcyrillic: 0x04A6, |
| 22633 |
Phi: 0x03A6, |
| 22634 |
Phook: 0x01A4, |
| 22635 |
Pi: 0x03A0, |
| 22636 |
Piwrarmenian: 0x0553, |
| 22637 |
Pmonospace: 0xFF30, |
| 22638 |
Psi: 0x03A8, |
| 22639 |
Psicyrillic: 0x0470, |
| 22640 |
Psmall: 0xF770, |
| 22641 |
Q: 0x0051, |
| 22642 |
Qcircle: 0x24C6, |
| 22643 |
Qmonospace: 0xFF31, |
| 22644 |
Qsmall: 0xF771, |
| 22645 |
R: 0x0052, |
| 22646 |
Raarmenian: 0x054C, |
| 22647 |
Racute: 0x0154, |
| 22648 |
Rcaron: 0x0158, |
| 22649 |
Rcedilla: 0x0156, |
| 22650 |
Rcircle: 0x24C7, |
| 22651 |
Rcommaaccent: 0x0156, |
| 22652 |
Rdblgrave: 0x0210, |
| 22653 |
Rdotaccent: 0x1E58, |
| 22654 |
Rdotbelow: 0x1E5A, |
| 22655 |
Rdotbelowmacron: 0x1E5C, |
| 22656 |
Reharmenian: 0x0550, |
| 22657 |
Rfraktur: 0x211C, |
| 22658 |
Rho: 0x03A1, |
| 22659 |
Ringsmall: 0xF6FC, |
| 22660 |
Rinvertedbreve: 0x0212, |
| 22661 |
Rlinebelow: 0x1E5E, |
| 22662 |
Rmonospace: 0xFF32, |
| 22663 |
Rsmall: 0xF772, |
| 22664 |
Rsmallinverted: 0x0281, |
| 22665 |
Rsmallinvertedsuperior: 0x02B6, |
| 22666 |
S: 0x0053, |
| 22667 |
SF010000: 0x250C, |
| 22668 |
SF020000: 0x2514, |
| 22669 |
SF030000: 0x2510, |
| 22670 |
SF040000: 0x2518, |
| 22671 |
SF050000: 0x253C, |
| 22672 |
SF060000: 0x252C, |
| 22673 |
SF070000: 0x2534, |
| 22674 |
SF080000: 0x251C, |
| 22675 |
SF090000: 0x2524, |
| 22676 |
SF100000: 0x2500, |
| 22677 |
SF110000: 0x2502, |
| 22678 |
SF190000: 0x2561, |
| 22679 |
SF200000: 0x2562, |
| 22680 |
SF210000: 0x2556, |
| 22681 |
SF220000: 0x2555, |
| 22682 |
SF230000: 0x2563, |
| 22683 |
SF240000: 0x2551, |
| 22684 |
SF250000: 0x2557, |
| 22685 |
SF260000: 0x255D, |
| 22686 |
SF270000: 0x255C, |
| 22687 |
SF280000: 0x255B, |
| 22688 |
SF360000: 0x255E, |
| 22689 |
SF370000: 0x255F, |
| 22690 |
SF380000: 0x255A, |
| 22691 |
SF390000: 0x2554, |
| 22692 |
SF400000: 0x2569, |
| 22693 |
SF410000: 0x2566, |
| 22694 |
SF420000: 0x2560, |
| 22695 |
SF430000: 0x2550, |
| 22696 |
SF440000: 0x256C, |
| 22697 |
SF450000: 0x2567, |
| 22698 |
SF460000: 0x2568, |
| 22699 |
SF470000: 0x2564, |
| 22700 |
SF480000: 0x2565, |
| 22701 |
SF490000: 0x2559, |
| 22702 |
SF500000: 0x2558, |
| 22703 |
SF510000: 0x2552, |
| 22704 |
SF520000: 0x2553, |
| 22705 |
SF530000: 0x256B, |
| 22706 |
SF540000: 0x256A, |
| 22707 |
Sacute: 0x015A, |
| 22708 |
Sacutedotaccent: 0x1E64, |
| 22709 |
Sampigreek: 0x03E0, |
| 22710 |
Scaron: 0x0160, |
| 22711 |
Scarondotaccent: 0x1E66, |
| 22712 |
Scaronsmall: 0xF6FD, |
| 22713 |
Scedilla: 0x015E, |
| 22714 |
Schwa: 0x018F, |
| 22715 |
Schwacyrillic: 0x04D8, |
| 22716 |
Schwadieresiscyrillic: 0x04DA, |
| 22717 |
Scircle: 0x24C8, |
| 22718 |
Scircumflex: 0x015C, |
| 22719 |
Scommaaccent: 0x0218, |
| 22720 |
Sdotaccent: 0x1E60, |
| 22721 |
Sdotbelow: 0x1E62, |
| 22722 |
Sdotbelowdotaccent: 0x1E68, |
| 22723 |
Seharmenian: 0x054D, |
| 22724 |
Sevenroman: 0x2166, |
| 22725 |
Shaarmenian: 0x0547, |
| 22726 |
Shacyrillic: 0x0428, |
| 22727 |
Shchacyrillic: 0x0429, |
| 22728 |
Sheicoptic: 0x03E2, |
| 22729 |
Shhacyrillic: 0x04BA, |
| 22730 |
Shimacoptic: 0x03EC, |
| 22731 |
Sigma: 0x03A3, |
| 22732 |
Sixroman: 0x2165, |
| 22733 |
Smonospace: 0xFF33, |
| 22734 |
Softsigncyrillic: 0x042C, |
| 22735 |
Ssmall: 0xF773, |
| 22736 |
Stigmagreek: 0x03DA, |
| 22737 |
T: 0x0054, |
| 22738 |
Tau: 0x03A4, |
| 22739 |
Tbar: 0x0166, |
| 22740 |
Tcaron: 0x0164, |
| 22741 |
Tcedilla: 0x0162, |
| 22742 |
Tcircle: 0x24C9, |
| 22743 |
Tcircumflexbelow: 0x1E70, |
| 22744 |
Tcommaaccent: 0x0162, |
| 22745 |
Tdotaccent: 0x1E6A, |
| 22746 |
Tdotbelow: 0x1E6C, |
| 22747 |
Tecyrillic: 0x0422, |
| 22748 |
Tedescendercyrillic: 0x04AC, |
| 22749 |
Tenroman: 0x2169, |
| 22750 |
Tetsecyrillic: 0x04B4, |
| 22751 |
Theta: 0x0398, |
| 22752 |
Thook: 0x01AC, |
| 22753 |
Thorn: 0x00DE, |
| 22754 |
Thornsmall: 0xF7FE, |
| 22755 |
Threeroman: 0x2162, |
| 22756 |
Tildesmall: 0xF6FE, |
| 22757 |
Tiwnarmenian: 0x054F, |
| 22758 |
Tlinebelow: 0x1E6E, |
| 22759 |
Tmonospace: 0xFF34, |
| 22760 |
Toarmenian: 0x0539, |
| 22761 |
Tonefive: 0x01BC, |
| 22762 |
Tonesix: 0x0184, |
| 22763 |
Tonetwo: 0x01A7, |
| 22764 |
Tretroflexhook: 0x01AE, |
| 22765 |
Tsecyrillic: 0x0426, |
| 22766 |
Tshecyrillic: 0x040B, |
| 22767 |
Tsmall: 0xF774, |
| 22768 |
Twelveroman: 0x216B, |
| 22769 |
Tworoman: 0x2161, |
| 22770 |
U: 0x0055, |
| 22771 |
Uacute: 0x00DA, |
| 22772 |
Uacutesmall: 0xF7FA, |
| 22773 |
Ubreve: 0x016C, |
| 22774 |
Ucaron: 0x01D3, |
| 22775 |
Ucircle: 0x24CA, |
| 22776 |
Ucircumflex: 0x00DB, |
| 22777 |
Ucircumflexbelow: 0x1E76, |
| 22778 |
Ucircumflexsmall: 0xF7FB, |
| 22779 |
Ucyrillic: 0x0423, |
| 22780 |
Udblacute: 0x0170, |
| 22781 |
Udblgrave: 0x0214, |
| 22782 |
Udieresis: 0x00DC, |
| 22783 |
Udieresisacute: 0x01D7, |
| 22784 |
Udieresisbelow: 0x1E72, |
| 22785 |
Udieresiscaron: 0x01D9, |
| 22786 |
Udieresiscyrillic: 0x04F0, |
| 22787 |
Udieresisgrave: 0x01DB, |
| 22788 |
Udieresismacron: 0x01D5, |
| 22789 |
Udieresissmall: 0xF7FC, |
| 22790 |
Udotbelow: 0x1EE4, |
| 22791 |
Ugrave: 0x00D9, |
| 22792 |
Ugravesmall: 0xF7F9, |
| 22793 |
Uhookabove: 0x1EE6, |
| 22794 |
Uhorn: 0x01AF, |
| 22795 |
Uhornacute: 0x1EE8, |
| 22796 |
Uhorndotbelow: 0x1EF0, |
| 22797 |
Uhorngrave: 0x1EEA, |
| 22798 |
Uhornhookabove: 0x1EEC, |
| 22799 |
Uhorntilde: 0x1EEE, |
| 22800 |
Uhungarumlaut: 0x0170, |
| 22801 |
Uhungarumlautcyrillic: 0x04F2, |
| 22802 |
Uinvertedbreve: 0x0216, |
| 22803 |
Ukcyrillic: 0x0478, |
| 22804 |
Umacron: 0x016A, |
| 22805 |
Umacroncyrillic: 0x04EE, |
| 22806 |
Umacrondieresis: 0x1E7A, |
| 22807 |
Umonospace: 0xFF35, |
| 22808 |
Uogonek: 0x0172, |
| 22809 |
Upsilon: 0x03A5, |
| 22810 |
Upsilon1: 0x03D2, |
| 22811 |
Upsilonacutehooksymbolgreek: 0x03D3, |
| 22812 |
Upsilonafrican: 0x01B1, |
| 22813 |
Upsilondieresis: 0x03AB, |
| 22814 |
Upsilondieresishooksymbolgreek: 0x03D4, |
| 22815 |
Upsilonhooksymbol: 0x03D2, |
| 22816 |
Upsilontonos: 0x038E, |
| 22817 |
Uring: 0x016E, |
| 22818 |
Ushortcyrillic: 0x040E, |
| 22819 |
Usmall: 0xF775, |
| 22820 |
Ustraightcyrillic: 0x04AE, |
| 22821 |
Ustraightstrokecyrillic: 0x04B0, |
| 22822 |
Utilde: 0x0168, |
| 22823 |
Utildeacute: 0x1E78, |
| 22824 |
Utildebelow: 0x1E74, |
| 22825 |
V: 0x0056, |
| 22826 |
Vcircle: 0x24CB, |
| 22827 |
Vdotbelow: 0x1E7E, |
| 22828 |
Vecyrillic: 0x0412, |
| 22829 |
Vewarmenian: 0x054E, |
| 22830 |
Vhook: 0x01B2, |
| 22831 |
Vmonospace: 0xFF36, |
| 22832 |
Voarmenian: 0x0548, |
| 22833 |
Vsmall: 0xF776, |
| 22834 |
Vtilde: 0x1E7C, |
| 22835 |
W: 0x0057, |
| 22836 |
Wacute: 0x1E82, |
| 22837 |
Wcircle: 0x24CC, |
| 22838 |
Wcircumflex: 0x0174, |
| 22839 |
Wdieresis: 0x1E84, |
| 22840 |
Wdotaccent: 0x1E86, |
| 22841 |
Wdotbelow: 0x1E88, |
| 22842 |
Wgrave: 0x1E80, |
| 22843 |
Wmonospace: 0xFF37, |
| 22844 |
Wsmall: 0xF777, |
| 22845 |
X: 0x0058, |
| 22846 |
Xcircle: 0x24CD, |
| 22847 |
Xdieresis: 0x1E8C, |
| 22848 |
Xdotaccent: 0x1E8A, |
| 22849 |
Xeharmenian: 0x053D, |
| 22850 |
Xi: 0x039E, |
| 22851 |
Xmonospace: 0xFF38, |
| 22852 |
Xsmall: 0xF778, |
| 22853 |
Y: 0x0059, |
| 22854 |
Yacute: 0x00DD, |
| 22855 |
Yacutesmall: 0xF7FD, |
| 22856 |
Yatcyrillic: 0x0462, |
| 22857 |
Ycircle: 0x24CE, |
| 22858 |
Ycircumflex: 0x0176, |
| 22859 |
Ydieresis: 0x0178, |
| 22860 |
Ydieresissmall: 0xF7FF, |
| 22861 |
Ydotaccent: 0x1E8E, |
| 22862 |
Ydotbelow: 0x1EF4, |
| 22863 |
Yericyrillic: 0x042B, |
| 22864 |
Yerudieresiscyrillic: 0x04F8, |
| 22865 |
Ygrave: 0x1EF2, |
| 22866 |
Yhook: 0x01B3, |
| 22867 |
Yhookabove: 0x1EF6, |
| 22868 |
Yiarmenian: 0x0545, |
| 22869 |
Yicyrillic: 0x0407, |
| 22870 |
Yiwnarmenian: 0x0552, |
| 22871 |
Ymonospace: 0xFF39, |
| 22872 |
Ysmall: 0xF779, |
| 22873 |
Ytilde: 0x1EF8, |
| 22874 |
Yusbigcyrillic: 0x046A, |
| 22875 |
Yusbigiotifiedcyrillic: 0x046C, |
| 22876 |
Yuslittlecyrillic: 0x0466, |
| 22877 |
Yuslittleiotifiedcyrillic: 0x0468, |
| 22878 |
Z: 0x005A, |
| 22879 |
Zaarmenian: 0x0536, |
| 22880 |
Zacute: 0x0179, |
| 22881 |
Zcaron: 0x017D, |
| 22882 |
Zcaronsmall: 0xF6FF, |
| 22883 |
Zcircle: 0x24CF, |
| 22884 |
Zcircumflex: 0x1E90, |
| 22885 |
Zdot: 0x017B, |
| 22886 |
Zdotaccent: 0x017B, |
| 22887 |
Zdotbelow: 0x1E92, |
| 22888 |
Zecyrillic: 0x0417, |
| 22889 |
Zedescendercyrillic: 0x0498, |
| 22890 |
Zedieresiscyrillic: 0x04DE, |
| 22891 |
Zeta: 0x0396, |
| 22892 |
Zhearmenian: 0x053A, |
| 22893 |
Zhebrevecyrillic: 0x04C1, |
| 22894 |
Zhecyrillic: 0x0416, |
| 22895 |
Zhedescendercyrillic: 0x0496, |
| 22896 |
Zhedieresiscyrillic: 0x04DC, |
| 22897 |
Zlinebelow: 0x1E94, |
| 22898 |
Zmonospace: 0xFF3A, |
| 22899 |
Zsmall: 0xF77A, |
| 22900 |
Zstroke: 0x01B5, |
| 22901 |
a: 0x0061, |
| 22902 |
aabengali: 0x0986, |
| 22903 |
aacute: 0x00E1, |
| 22904 |
aadeva: 0x0906, |
| 22905 |
aagujarati: 0x0A86, |
| 22906 |
aagurmukhi: 0x0A06, |
| 22907 |
aamatragurmukhi: 0x0A3E, |
| 22908 |
aarusquare: 0x3303, |
| 22909 |
aavowelsignbengali: 0x09BE, |
| 22910 |
aavowelsigndeva: 0x093E, |
| 22911 |
aavowelsigngujarati: 0x0ABE, |
| 22912 |
abbreviationmarkarmenian: 0x055F, |
| 22913 |
abbreviationsigndeva: 0x0970, |
| 22914 |
abengali: 0x0985, |
| 22915 |
abopomofo: 0x311A, |
| 22916 |
abreve: 0x0103, |
| 22917 |
abreveacute: 0x1EAF, |
| 22918 |
abrevecyrillic: 0x04D1, |
| 22919 |
abrevedotbelow: 0x1EB7, |
| 22920 |
abrevegrave: 0x1EB1, |
| 22921 |
abrevehookabove: 0x1EB3, |
| 22922 |
abrevetilde: 0x1EB5, |
| 22923 |
acaron: 0x01CE, |
| 22924 |
acircle: 0x24D0, |
| 22925 |
acircumflex: 0x00E2, |
| 22926 |
acircumflexacute: 0x1EA5, |
| 22927 |
acircumflexdotbelow: 0x1EAD, |
| 22928 |
acircumflexgrave: 0x1EA7, |
| 22929 |
acircumflexhookabove: 0x1EA9, |
| 22930 |
acircumflextilde: 0x1EAB, |
| 22931 |
acute: 0x00B4, |
| 22932 |
acutebelowcmb: 0x0317, |
| 22933 |
acutecmb: 0x0301, |
| 22934 |
acutecomb: 0x0301, |
| 22935 |
acutedeva: 0x0954, |
| 22936 |
acutelowmod: 0x02CF, |
| 22937 |
acutetonecmb: 0x0341, |
| 22938 |
acyrillic: 0x0430, |
| 22939 |
adblgrave: 0x0201, |
| 22940 |
addakgurmukhi: 0x0A71, |
| 22941 |
adeva: 0x0905, |
| 22942 |
adieresis: 0x00E4, |
| 22943 |
adieresiscyrillic: 0x04D3, |
| 22944 |
adieresismacron: 0x01DF, |
| 22945 |
adotbelow: 0x1EA1, |
| 22946 |
adotmacron: 0x01E1, |
| 22947 |
ae: 0x00E6, |
| 22948 |
aeacute: 0x01FD, |
| 22949 |
aekorean: 0x3150, |
| 22950 |
aemacron: 0x01E3, |
| 22951 |
afii00208: 0x2015, |
| 22952 |
afii08941: 0x20A4, |
| 22953 |
afii10017: 0x0410, |
| 22954 |
afii10018: 0x0411, |
| 22955 |
afii10019: 0x0412, |
| 22956 |
afii10020: 0x0413, |
| 22957 |
afii10021: 0x0414, |
| 22958 |
afii10022: 0x0415, |
| 22959 |
afii10023: 0x0401, |
| 22960 |
afii10024: 0x0416, |
| 22961 |
afii10025: 0x0417, |
| 22962 |
afii10026: 0x0418, |
| 22963 |
afii10027: 0x0419, |
| 22964 |
afii10028: 0x041A, |
| 22965 |
afii10029: 0x041B, |
| 22966 |
afii10030: 0x041C, |
| 22967 |
afii10031: 0x041D, |
| 22968 |
afii10032: 0x041E, |
| 22969 |
afii10033: 0x041F, |
| 22970 |
afii10034: 0x0420, |
| 22971 |
afii10035: 0x0421, |
| 22972 |
afii10036: 0x0422, |
| 22973 |
afii10037: 0x0423, |
| 22974 |
afii10038: 0x0424, |
| 22975 |
afii10039: 0x0425, |
| 22976 |
afii10040: 0x0426, |
| 22977 |
afii10041: 0x0427, |
| 22978 |
afii10042: 0x0428, |
| 22979 |
afii10043: 0x0429, |
| 22980 |
afii10044: 0x042A, |
| 22981 |
afii10045: 0x042B, |
| 22982 |
afii10046: 0x042C, |
| 22983 |
afii10047: 0x042D, |
| 22984 |
afii10048: 0x042E, |
| 22985 |
afii10049: 0x042F, |
| 22986 |
afii10050: 0x0490, |
| 22987 |
afii10051: 0x0402, |
| 22988 |
afii10052: 0x0403, |
| 22989 |
afii10053: 0x0404, |
| 22990 |
afii10054: 0x0405, |
| 22991 |
afii10055: 0x0406, |
| 22992 |
afii10056: 0x0407, |
| 22993 |
afii10057: 0x0408, |
| 22994 |
afii10058: 0x0409, |
| 22995 |
afii10059: 0x040A, |
| 22996 |
afii10060: 0x040B, |
| 22997 |
afii10061: 0x040C, |
| 22998 |
afii10062: 0x040E, |
| 22999 |
afii10063: 0xF6C4, |
| 23000 |
afii10064: 0xF6C5, |
| 23001 |
afii10065: 0x0430, |
| 23002 |
afii10066: 0x0431, |
| 23003 |
afii10067: 0x0432, |
| 23004 |
afii10068: 0x0433, |
| 23005 |
afii10069: 0x0434, |
| 23006 |
afii10070: 0x0435, |
| 23007 |
afii10071: 0x0451, |
| 23008 |
afii10072: 0x0436, |
| 23009 |
afii10073: 0x0437, |
| 23010 |
afii10074: 0x0438, |
| 23011 |
afii10075: 0x0439, |
| 23012 |
afii10076: 0x043A, |
| 23013 |
afii10077: 0x043B, |
| 23014 |
afii10078: 0x043C, |
| 23015 |
afii10079: 0x043D, |
| 23016 |
afii10080: 0x043E, |
| 23017 |
afii10081: 0x043F, |
| 23018 |
afii10082: 0x0440, |
| 23019 |
afii10083: 0x0441, |
| 23020 |
afii10084: 0x0442, |
| 23021 |
afii10085: 0x0443, |
| 23022 |
afii10086: 0x0444, |
| 23023 |
afii10087: 0x0445, |
| 23024 |
afii10088: 0x0446, |
| 23025 |
afii10089: 0x0447, |
| 23026 |
afii10090: 0x0448, |
| 23027 |
afii10091: 0x0449, |
| 23028 |
afii10092: 0x044A, |
| 23029 |
afii10093: 0x044B, |
| 23030 |
afii10094: 0x044C, |
| 23031 |
afii10095: 0x044D, |
| 23032 |
afii10096: 0x044E, |
| 23033 |
afii10097: 0x044F, |
| 23034 |
afii10098: 0x0491, |
| 23035 |
afii10099: 0x0452, |
| 23036 |
afii10100: 0x0453, |
| 23037 |
afii10101: 0x0454, |
| 23038 |
afii10102: 0x0455, |
| 23039 |
afii10103: 0x0456, |
| 23040 |
afii10104: 0x0457, |
| 23041 |
afii10105: 0x0458, |
| 23042 |
afii10106: 0x0459, |
| 23043 |
afii10107: 0x045A, |
| 23044 |
afii10108: 0x045B, |
| 23045 |
afii10109: 0x045C, |
| 23046 |
afii10110: 0x045E, |
| 23047 |
afii10145: 0x040F, |
| 23048 |
afii10146: 0x0462, |
| 23049 |
afii10147: 0x0472, |
| 23050 |
afii10148: 0x0474, |
| 23051 |
afii10192: 0xF6C6, |
| 23052 |
afii10193: 0x045F, |
| 23053 |
afii10194: 0x0463, |
| 23054 |
afii10195: 0x0473, |
| 23055 |
afii10196: 0x0475, |
| 23056 |
afii10831: 0xF6C7, |
| 23057 |
afii10832: 0xF6C8, |
| 23058 |
afii10846: 0x04D9, |
| 23059 |
afii299: 0x200E, |
| 23060 |
afii300: 0x200F, |
| 23061 |
afii301: 0x200D, |
| 23062 |
afii57381: 0x066A, |
| 23063 |
afii57388: 0x060C, |
| 23064 |
afii57392: 0x0660, |
| 23065 |
afii57393: 0x0661, |
| 23066 |
afii57394: 0x0662, |
| 23067 |
afii57395: 0x0663, |
| 23068 |
afii57396: 0x0664, |
| 23069 |
afii57397: 0x0665, |
| 23070 |
afii57398: 0x0666, |
| 23071 |
afii57399: 0x0667, |
| 23072 |
afii57400: 0x0668, |
| 23073 |
afii57401: 0x0669, |
| 23074 |
afii57403: 0x061B, |
| 23075 |
afii57407: 0x061F, |
| 23076 |
afii57409: 0x0621, |
| 23077 |
afii57410: 0x0622, |
| 23078 |
afii57411: 0x0623, |
| 23079 |
afii57412: 0x0624, |
| 23080 |
afii57413: 0x0625, |
| 23081 |
afii57414: 0x0626, |
| 23082 |
afii57415: 0x0627, |
| 23083 |
afii57416: 0x0628, |
| 23084 |
afii57417: 0x0629, |
| 23085 |
afii57418: 0x062A, |
| 23086 |
afii57419: 0x062B, |
| 23087 |
afii57420: 0x062C, |
| 23088 |
afii57421: 0x062D, |
| 23089 |
afii57422: 0x062E, |
| 23090 |
afii57423: 0x062F, |
| 23091 |
afii57424: 0x0630, |
| 23092 |
afii57425: 0x0631, |
| 23093 |
afii57426: 0x0632, |
| 23094 |
afii57427: 0x0633, |
| 23095 |
afii57428: 0x0634, |
| 23096 |
afii57429: 0x0635, |
| 23097 |
afii57430: 0x0636, |
| 23098 |
afii57431: 0x0637, |
| 23099 |
afii57432: 0x0638, |
| 23100 |
afii57433: 0x0639, |
| 23101 |
afii57434: 0x063A, |
| 23102 |
afii57440: 0x0640, |
| 23103 |
afii57441: 0x0641, |
| 23104 |
afii57442: 0x0642, |
| 23105 |
afii57443: 0x0643, |
| 23106 |
afii57444: 0x0644, |
| 23107 |
afii57445: 0x0645, |
| 23108 |
afii57446: 0x0646, |
| 23109 |
afii57448: 0x0648, |
| 23110 |
afii57449: 0x0649, |
| 23111 |
afii57450: 0x064A, |
| 23112 |
afii57451: 0x064B, |
| 23113 |
afii57452: 0x064C, |
| 23114 |
afii57453: 0x064D, |
| 23115 |
afii57454: 0x064E, |
| 23116 |
afii57455: 0x064F, |
| 23117 |
afii57456: 0x0650, |
| 23118 |
afii57457: 0x0651, |
| 23119 |
afii57458: 0x0652, |
| 23120 |
afii57470: 0x0647, |
| 23121 |
afii57505: 0x06A4, |
| 23122 |
afii57506: 0x067E, |
| 23123 |
afii57507: 0x0686, |
| 23124 |
afii57508: 0x0698, |
| 23125 |
afii57509: 0x06AF, |
| 23126 |
afii57511: 0x0679, |
| 23127 |
afii57512: 0x0688, |
| 23128 |
afii57513: 0x0691, |
| 23129 |
afii57514: 0x06BA, |
| 23130 |
afii57519: 0x06D2, |
| 23131 |
afii57534: 0x06D5, |
| 23132 |
afii57636: 0x20AA, |
| 23133 |
afii57645: 0x05BE, |
| 23134 |
afii57658: 0x05C3, |
| 23135 |
afii57664: 0x05D0, |
| 23136 |
afii57665: 0x05D1, |
| 23137 |
afii57666: 0x05D2, |
| 23138 |
afii57667: 0x05D3, |
| 23139 |
afii57668: 0x05D4, |
| 23140 |
afii57669: 0x05D5, |
| 23141 |
afii57670: 0x05D6, |
| 23142 |
afii57671: 0x05D7, |
| 23143 |
afii57672: 0x05D8, |
| 23144 |
afii57673: 0x05D9, |
| 23145 |
afii57674: 0x05DA, |
| 23146 |
afii57675: 0x05DB, |
| 23147 |
afii57676: 0x05DC, |
| 23148 |
afii57677: 0x05DD, |
| 23149 |
afii57678: 0x05DE, |
| 23150 |
afii57679: 0x05DF, |
| 23151 |
afii57680: 0x05E0, |
| 23152 |
afii57681: 0x05E1, |
| 23153 |
afii57682: 0x05E2, |
| 23154 |
afii57683: 0x05E3, |
| 23155 |
afii57684: 0x05E4, |
| 23156 |
afii57685: 0x05E5, |
| 23157 |
afii57686: 0x05E6, |
| 23158 |
afii57687: 0x05E7, |
| 23159 |
afii57688: 0x05E8, |
| 23160 |
afii57689: 0x05E9, |
| 23161 |
afii57690: 0x05EA, |
| 23162 |
afii57694: 0xFB2A, |
| 23163 |
afii57695: 0xFB2B, |
| 23164 |
afii57700: 0xFB4B, |
| 23165 |
afii57705: 0xFB1F, |
| 23166 |
afii57716: 0x05F0, |
| 23167 |
afii57717: 0x05F1, |
| 23168 |
afii57718: 0x05F2, |
| 23169 |
afii57723: 0xFB35, |
| 23170 |
afii57793: 0x05B4, |
| 23171 |
afii57794: 0x05B5, |
| 23172 |
afii57795: 0x05B6, |
| 23173 |
afii57796: 0x05BB, |
| 23174 |
afii57797: 0x05B8, |
| 23175 |
afii57798: 0x05B7, |
| 23176 |
afii57799: 0x05B0, |
| 23177 |
afii57800: 0x05B2, |
| 23178 |
afii57801: 0x05B1, |
| 23179 |
afii57802: 0x05B3, |
| 23180 |
afii57803: 0x05C2, |
| 23181 |
afii57804: 0x05C1, |
| 23182 |
afii57806: 0x05B9, |
| 23183 |
afii57807: 0x05BC, |
| 23184 |
afii57839: 0x05BD, |
| 23185 |
afii57841: 0x05BF, |
| 23186 |
afii57842: 0x05C0, |
| 23187 |
afii57929: 0x02BC, |
| 23188 |
afii61248: 0x2105, |
| 23189 |
afii61289: 0x2113, |
| 23190 |
afii61352: 0x2116, |
| 23191 |
afii61573: 0x202C, |
| 23192 |
afii61574: 0x202D, |
| 23193 |
afii61575: 0x202E, |
| 23194 |
afii61664: 0x200C, |
| 23195 |
afii63167: 0x066D, |
| 23196 |
afii64937: 0x02BD, |
| 23197 |
agrave: 0x00E0, |
| 23198 |
agujarati: 0x0A85, |
| 23199 |
agurmukhi: 0x0A05, |
| 23200 |
ahiragana: 0x3042, |
| 23201 |
ahookabove: 0x1EA3, |
| 23202 |
aibengali: 0x0990, |
| 23203 |
aibopomofo: 0x311E, |
| 23204 |
aideva: 0x0910, |
| 23205 |
aiecyrillic: 0x04D5, |
| 23206 |
aigujarati: 0x0A90, |
| 23207 |
aigurmukhi: 0x0A10, |
| 23208 |
aimatragurmukhi: 0x0A48, |
| 23209 |
ainarabic: 0x0639, |
| 23210 |
ainfinalarabic: 0xFECA, |
| 23211 |
aininitialarabic: 0xFECB, |
| 23212 |
ainmedialarabic: 0xFECC, |
| 23213 |
ainvertedbreve: 0x0203, |
| 23214 |
aivowelsignbengali: 0x09C8, |
| 23215 |
aivowelsigndeva: 0x0948, |
| 23216 |
aivowelsigngujarati: 0x0AC8, |
| 23217 |
akatakana: 0x30A2, |
| 23218 |
akatakanahalfwidth: 0xFF71, |
| 23219 |
akorean: 0x314F, |
| 23220 |
alef: 0x05D0, |
| 23221 |
alefarabic: 0x0627, |
| 23222 |
alefdageshhebrew: 0xFB30, |
| 23223 |
aleffinalarabic: 0xFE8E, |
| 23224 |
alefhamzaabovearabic: 0x0623, |
| 23225 |
alefhamzaabovefinalarabic: 0xFE84, |
| 23226 |
alefhamzabelowarabic: 0x0625, |
| 23227 |
alefhamzabelowfinalarabic: 0xFE88, |
| 23228 |
alefhebrew: 0x05D0, |
| 23229 |
aleflamedhebrew: 0xFB4F, |
| 23230 |
alefmaddaabovearabic: 0x0622, |
| 23231 |
alefmaddaabovefinalarabic: 0xFE82, |
| 23232 |
alefmaksuraarabic: 0x0649, |
| 23233 |
alefmaksurafinalarabic: 0xFEF0, |
| 23234 |
alefmaksurainitialarabic: 0xFEF3, |
| 23235 |
alefmaksuramedialarabic: 0xFEF4, |
| 23236 |
alefpatahhebrew: 0xFB2E, |
| 23237 |
alefqamatshebrew: 0xFB2F, |
| 23238 |
aleph: 0x2135, |
| 23239 |
allequal: 0x224C, |
| 23240 |
alpha: 0x03B1, |
| 23241 |
alphatonos: 0x03AC, |
| 23242 |
amacron: 0x0101, |
| 23243 |
amonospace: 0xFF41, |
| 23244 |
ampersand: 0x0026, |
| 23245 |
ampersandmonospace: 0xFF06, |
| 23246 |
ampersandsmall: 0xF726, |
| 23247 |
amsquare: 0x33C2, |
| 23248 |
anbopomofo: 0x3122, |
| 23249 |
angbopomofo: 0x3124, |
| 23250 |
angbracketleft: 0x3008, // This glyph is missing from Adobe's original list. |
| 23251 |
angbracketright: 0x3009, // This glyph is missing from Adobe's original list. |
| 23252 |
angkhankhuthai: 0x0E5A, |
| 23253 |
angle: 0x2220, |
| 23254 |
anglebracketleft: 0x3008, |
| 23255 |
anglebracketleftvertical: 0xFE3F, |
| 23256 |
anglebracketright: 0x3009, |
| 23257 |
anglebracketrightvertical: 0xFE40, |
| 23258 |
angleleft: 0x2329, |
| 23259 |
angleright: 0x232A, |
| 23260 |
angstrom: 0x212B, |
| 23261 |
anoteleia: 0x0387, |
| 23262 |
anudattadeva: 0x0952, |
| 23263 |
anusvarabengali: 0x0982, |
| 23264 |
anusvaradeva: 0x0902, |
| 23265 |
anusvaragujarati: 0x0A82, |
| 23266 |
aogonek: 0x0105, |
| 23267 |
apaatosquare: 0x3300, |
| 23268 |
aparen: 0x249C, |
| 23269 |
apostrophearmenian: 0x055A, |
| 23270 |
apostrophemod: 0x02BC, |
| 23271 |
apple: 0xF8FF, |
| 23272 |
approaches: 0x2250, |
| 23273 |
approxequal: 0x2248, |
| 23274 |
approxequalorimage: 0x2252, |
| 23275 |
approximatelyequal: 0x2245, |
| 23276 |
araeaekorean: 0x318E, |
| 23277 |
araeakorean: 0x318D, |
| 23278 |
arc: 0x2312, |
| 23279 |
arighthalfring: 0x1E9A, |
| 23280 |
aring: 0x00E5, |
| 23281 |
aringacute: 0x01FB, |
| 23282 |
aringbelow: 0x1E01, |
| 23283 |
arrowboth: 0x2194, |
| 23284 |
arrowdashdown: 0x21E3, |
| 23285 |
arrowdashleft: 0x21E0, |
| 23286 |
arrowdashright: 0x21E2, |
| 23287 |
arrowdashup: 0x21E1, |
| 23288 |
arrowdblboth: 0x21D4, |
| 23289 |
arrowdbldown: 0x21D3, |
| 23290 |
arrowdblleft: 0x21D0, |
| 23291 |
arrowdblright: 0x21D2, |
| 23292 |
arrowdblup: 0x21D1, |
| 23293 |
arrowdown: 0x2193, |
| 23294 |
arrowdownleft: 0x2199, |
| 23295 |
arrowdownright: 0x2198, |
| 23296 |
arrowdownwhite: 0x21E9, |
| 23297 |
arrowheaddownmod: 0x02C5, |
| 23298 |
arrowheadleftmod: 0x02C2, |
| 23299 |
arrowheadrightmod: 0x02C3, |
| 23300 |
arrowheadupmod: 0x02C4, |
| 23301 |
arrowhorizex: 0xF8E7, |
| 23302 |
arrowleft: 0x2190, |
| 23303 |
arrowleftdbl: 0x21D0, |
| 23304 |
arrowleftdblstroke: 0x21CD, |
| 23305 |
arrowleftoverright: 0x21C6, |
| 23306 |
arrowleftwhite: 0x21E6, |
| 23307 |
arrowright: 0x2192, |
| 23308 |
arrowrightdblstroke: 0x21CF, |
| 23309 |
arrowrightheavy: 0x279E, |
| 23310 |
arrowrightoverleft: 0x21C4, |
| 23311 |
arrowrightwhite: 0x21E8, |
| 23312 |
arrowtableft: 0x21E4, |
| 23313 |
arrowtabright: 0x21E5, |
| 23314 |
arrowup: 0x2191, |
| 23315 |
arrowupdn: 0x2195, |
| 23316 |
arrowupdnbse: 0x21A8, |
| 23317 |
arrowupdownbase: 0x21A8, |
| 23318 |
arrowupleft: 0x2196, |
| 23319 |
arrowupleftofdown: 0x21C5, |
| 23320 |
arrowupright: 0x2197, |
| 23321 |
arrowupwhite: 0x21E7, |
| 23322 |
arrowvertex: 0xF8E6, |
| 23323 |
asciicircum: 0x005E, |
| 23324 |
asciicircummonospace: 0xFF3E, |
| 23325 |
asciitilde: 0x007E, |
| 23326 |
asciitildemonospace: 0xFF5E, |
| 23327 |
ascript: 0x0251, |
| 23328 |
ascriptturned: 0x0252, |
| 23329 |
asmallhiragana: 0x3041, |
| 23330 |
asmallkatakana: 0x30A1, |
| 23331 |
asmallkatakanahalfwidth: 0xFF67, |
| 23332 |
asterisk: 0x002A, |
| 23333 |
asteriskaltonearabic: 0x066D, |
| 23334 |
asteriskarabic: 0x066D, |
| 23335 |
asteriskmath: 0x2217, |
| 23336 |
asteriskmonospace: 0xFF0A, |
| 23337 |
asterisksmall: 0xFE61, |
| 23338 |
asterism: 0x2042, |
| 23339 |
asuperior: 0xF6E9, |
| 23340 |
asymptoticallyequal: 0x2243, |
| 23341 |
at: 0x0040, |
| 23342 |
atilde: 0x00E3, |
| 23343 |
atmonospace: 0xFF20, |
| 23344 |
atsmall: 0xFE6B, |
| 23345 |
aturned: 0x0250, |
| 23346 |
aubengali: 0x0994, |
| 23347 |
aubopomofo: 0x3120, |
| 23348 |
audeva: 0x0914, |
| 23349 |
augujarati: 0x0A94, |
| 23350 |
augurmukhi: 0x0A14, |
| 23351 |
aulengthmarkbengali: 0x09D7, |
| 23352 |
aumatragurmukhi: 0x0A4C, |
| 23353 |
auvowelsignbengali: 0x09CC, |
| 23354 |
auvowelsigndeva: 0x094C, |
| 23355 |
auvowelsigngujarati: 0x0ACC, |
| 23356 |
avagrahadeva: 0x093D, |
| 23357 |
aybarmenian: 0x0561, |
| 23358 |
ayin: 0x05E2, |
| 23359 |
ayinaltonehebrew: 0xFB20, |
| 23360 |
ayinhebrew: 0x05E2, |
| 23361 |
b: 0x0062, |
| 23362 |
babengali: 0x09AC, |
| 23363 |
backslash: 0x005C, |
| 23364 |
backslashmonospace: 0xFF3C, |
| 23365 |
badeva: 0x092C, |
| 23366 |
bagujarati: 0x0AAC, |
| 23367 |
bagurmukhi: 0x0A2C, |
| 23368 |
bahiragana: 0x3070, |
| 23369 |
bahtthai: 0x0E3F, |
| 23370 |
bakatakana: 0x30D0, |
| 23371 |
bar: 0x007C, |
| 23372 |
barmonospace: 0xFF5C, |
| 23373 |
bbopomofo: 0x3105, |
| 23374 |
bcircle: 0x24D1, |
| 23375 |
bdotaccent: 0x1E03, |
| 23376 |
bdotbelow: 0x1E05, |
| 23377 |
beamedsixteenthnotes: 0x266C, |
| 23378 |
because: 0x2235, |
| 23379 |
becyrillic: 0x0431, |
| 23380 |
beharabic: 0x0628, |
| 23381 |
behfinalarabic: 0xFE90, |
| 23382 |
behinitialarabic: 0xFE91, |
| 23383 |
behiragana: 0x3079, |
| 23384 |
behmedialarabic: 0xFE92, |
| 23385 |
behmeeminitialarabic: 0xFC9F, |
| 23386 |
behmeemisolatedarabic: 0xFC08, |
| 23387 |
behnoonfinalarabic: 0xFC6D, |
| 23388 |
bekatakana: 0x30D9, |
| 23389 |
benarmenian: 0x0562, |
| 23390 |
bet: 0x05D1, |
| 23391 |
beta: 0x03B2, |
| 23392 |
betasymbolgreek: 0x03D0, |
| 23393 |
betdagesh: 0xFB31, |
| 23394 |
betdageshhebrew: 0xFB31, |
| 23395 |
bethebrew: 0x05D1, |
| 23396 |
betrafehebrew: 0xFB4C, |
| 23397 |
bhabengali: 0x09AD, |
| 23398 |
bhadeva: 0x092D, |
| 23399 |
bhagujarati: 0x0AAD, |
| 23400 |
bhagurmukhi: 0x0A2D, |
| 23401 |
bhook: 0x0253, |
| 23402 |
bihiragana: 0x3073, |
| 23403 |
bikatakana: 0x30D3, |
| 23404 |
bilabialclick: 0x0298, |
| 23405 |
bindigurmukhi: 0x0A02, |
| 23406 |
birusquare: 0x3331, |
| 23407 |
blackcircle: 0x25CF, |
| 23408 |
blackdiamond: 0x25C6, |
| 23409 |
blackdownpointingtriangle: 0x25BC, |
| 23410 |
blackleftpointingpointer: 0x25C4, |
| 23411 |
blackleftpointingtriangle: 0x25C0, |
| 23412 |
blacklenticularbracketleft: 0x3010, |
| 23413 |
blacklenticularbracketleftvertical: 0xFE3B, |
| 23414 |
blacklenticularbracketright: 0x3011, |
| 23415 |
blacklenticularbracketrightvertical: 0xFE3C, |
| 23416 |
blacklowerlefttriangle: 0x25E3, |
| 23417 |
blacklowerrighttriangle: 0x25E2, |
| 23418 |
blackrectangle: 0x25AC, |
| 23419 |
blackrightpointingpointer: 0x25BA, |
| 23420 |
blackrightpointingtriangle: 0x25B6, |
| 23421 |
blacksmallsquare: 0x25AA, |
| 23422 |
blacksmilingface: 0x263B, |
| 23423 |
blacksquare: 0x25A0, |
| 23424 |
blackstar: 0x2605, |
| 23425 |
blackupperlefttriangle: 0x25E4, |
| 23426 |
blackupperrighttriangle: 0x25E5, |
| 23427 |
blackuppointingsmalltriangle: 0x25B4, |
| 23428 |
blackuppointingtriangle: 0x25B2, |
| 23429 |
blank: 0x2423, |
| 23430 |
blinebelow: 0x1E07, |
| 23431 |
block: 0x2588, |
| 23432 |
bmonospace: 0xFF42, |
| 23433 |
bobaimaithai: 0x0E1A, |
| 23434 |
bohiragana: 0x307C, |
| 23435 |
bokatakana: 0x30DC, |
| 23436 |
bparen: 0x249D, |
| 23437 |
bqsquare: 0x33C3, |
| 23438 |
braceex: 0xF8F4, |
| 23439 |
braceleft: 0x007B, |
| 23440 |
braceleftbt: 0xF8F3, |
| 23441 |
braceleftmid: 0xF8F2, |
| 23442 |
braceleftmonospace: 0xFF5B, |
| 23443 |
braceleftsmall: 0xFE5B, |
| 23444 |
bracelefttp: 0xF8F1, |
| 23445 |
braceleftvertical: 0xFE37, |
| 23446 |
braceright: 0x007D, |
| 23447 |
bracerightbt: 0xF8FE, |
| 23448 |
bracerightmid: 0xF8FD, |
| 23449 |
bracerightmonospace: 0xFF5D, |
| 23450 |
bracerightsmall: 0xFE5C, |
| 23451 |
bracerighttp: 0xF8FC, |
| 23452 |
bracerightvertical: 0xFE38, |
| 23453 |
bracketleft: 0x005B, |
| 23454 |
bracketleftbt: 0xF8F0, |
| 23455 |
bracketleftex: 0xF8EF, |
| 23456 |
bracketleftmonospace: 0xFF3B, |
| 23457 |
bracketlefttp: 0xF8EE, |
| 23458 |
bracketright: 0x005D, |
| 23459 |
bracketrightbt: 0xF8FB, |
| 23460 |
bracketrightex: 0xF8FA, |
| 23461 |
bracketrightmonospace: 0xFF3D, |
| 23462 |
bracketrighttp: 0xF8F9, |
| 23463 |
breve: 0x02D8, |
| 23464 |
brevebelowcmb: 0x032E, |
| 23465 |
brevecmb: 0x0306, |
| 23466 |
breveinvertedbelowcmb: 0x032F, |
| 23467 |
breveinvertedcmb: 0x0311, |
| 23468 |
breveinverteddoublecmb: 0x0361, |
| 23469 |
bridgebelowcmb: 0x032A, |
| 23470 |
bridgeinvertedbelowcmb: 0x033A, |
| 23471 |
brokenbar: 0x00A6, |
| 23472 |
bstroke: 0x0180, |
| 23473 |
bsuperior: 0xF6EA, |
| 23474 |
btopbar: 0x0183, |
| 23475 |
buhiragana: 0x3076, |
| 23476 |
bukatakana: 0x30D6, |
| 23477 |
bullet: 0x2022, |
| 23478 |
bulletinverse: 0x25D8, |
| 23479 |
bulletoperator: 0x2219, |
| 23480 |
bullseye: 0x25CE, |
| 23481 |
c: 0x0063, |
| 23482 |
caarmenian: 0x056E, |
| 23483 |
cabengali: 0x099A, |
| 23484 |
cacute: 0x0107, |
| 23485 |
cadeva: 0x091A, |
| 23486 |
cagujarati: 0x0A9A, |
| 23487 |
cagurmukhi: 0x0A1A, |
| 23488 |
calsquare: 0x3388, |
| 23489 |
candrabindubengali: 0x0981, |
| 23490 |
candrabinducmb: 0x0310, |
| 23491 |
candrabindudeva: 0x0901, |
| 23492 |
candrabindugujarati: 0x0A81, |
| 23493 |
capslock: 0x21EA, |
| 23494 |
careof: 0x2105, |
| 23495 |
caron: 0x02C7, |
| 23496 |
caronbelowcmb: 0x032C, |
| 23497 |
caroncmb: 0x030C, |
| 23498 |
carriagereturn: 0x21B5, |
| 23499 |
cbopomofo: 0x3118, |
| 23500 |
ccaron: 0x010D, |
| 23501 |
ccedilla: 0x00E7, |
| 23502 |
ccedillaacute: 0x1E09, |
| 23503 |
ccircle: 0x24D2, |
| 23504 |
ccircumflex: 0x0109, |
| 23505 |
ccurl: 0x0255, |
| 23506 |
cdot: 0x010B, |
| 23507 |
cdotaccent: 0x010B, |
| 23508 |
cdsquare: 0x33C5, |
| 23509 |
cedilla: 0x00B8, |
| 23510 |
cedillacmb: 0x0327, |
| 23511 |
cent: 0x00A2, |
| 23512 |
centigrade: 0x2103, |
| 23513 |
centinferior: 0xF6DF, |
| 23514 |
centmonospace: 0xFFE0, |
| 23515 |
centoldstyle: 0xF7A2, |
| 23516 |
centsuperior: 0xF6E0, |
| 23517 |
chaarmenian: 0x0579, |
| 23518 |
chabengali: 0x099B, |
| 23519 |
chadeva: 0x091B, |
| 23520 |
chagujarati: 0x0A9B, |
| 23521 |
chagurmukhi: 0x0A1B, |
| 23522 |
chbopomofo: 0x3114, |
| 23523 |
cheabkhasiancyrillic: 0x04BD, |
| 23524 |
checkmark: 0x2713, |
| 23525 |
checyrillic: 0x0447, |
| 23526 |
chedescenderabkhasiancyrillic: 0x04BF, |
| 23527 |
chedescendercyrillic: 0x04B7, |
| 23528 |
chedieresiscyrillic: 0x04F5, |
| 23529 |
cheharmenian: 0x0573, |
| 23530 |
chekhakassiancyrillic: 0x04CC, |
| 23531 |
cheverticalstrokecyrillic: 0x04B9, |
| 23532 |
chi: 0x03C7, |
| 23533 |
chieuchacirclekorean: 0x3277, |
| 23534 |
chieuchaparenkorean: 0x3217, |
| 23535 |
chieuchcirclekorean: 0x3269, |
| 23536 |
chieuchkorean: 0x314A, |
| 23537 |
chieuchparenkorean: 0x3209, |
| 23538 |
chochangthai: 0x0E0A, |
| 23539 |
chochanthai: 0x0E08, |
| 23540 |
chochingthai: 0x0E09, |
| 23541 |
chochoethai: 0x0E0C, |
| 23542 |
chook: 0x0188, |
| 23543 |
cieucacirclekorean: 0x3276, |
| 23544 |
cieucaparenkorean: 0x3216, |
| 23545 |
cieuccirclekorean: 0x3268, |
| 23546 |
cieuckorean: 0x3148, |
| 23547 |
cieucparenkorean: 0x3208, |
| 23548 |
cieucuparenkorean: 0x321C, |
| 23549 |
circle: 0x25CB, |
| 23550 |
circlecopyrt: 0x00A9, // This glyph is missing from Adobe's original list. |
| 23551 |
circlemultiply: 0x2297, |
| 23552 |
circleot: 0x2299, |
| 23553 |
circleplus: 0x2295, |
| 23554 |
circlepostalmark: 0x3036, |
| 23555 |
circlewithlefthalfblack: 0x25D0, |
| 23556 |
circlewithrighthalfblack: 0x25D1, |
| 23557 |
circumflex: 0x02C6, |
| 23558 |
circumflexbelowcmb: 0x032D, |
| 23559 |
circumflexcmb: 0x0302, |
| 23560 |
clear: 0x2327, |
| 23561 |
clickalveolar: 0x01C2, |
| 23562 |
clickdental: 0x01C0, |
| 23563 |
clicklateral: 0x01C1, |
| 23564 |
clickretroflex: 0x01C3, |
| 23565 |
club: 0x2663, |
| 23566 |
clubsuitblack: 0x2663, |
| 23567 |
clubsuitwhite: 0x2667, |
| 23568 |
cmcubedsquare: 0x33A4, |
| 23569 |
cmonospace: 0xFF43, |
| 23570 |
cmsquaredsquare: 0x33A0, |
| 23571 |
coarmenian: 0x0581, |
| 23572 |
colon: 0x003A, |
| 23573 |
colonmonetary: 0x20A1, |
| 23574 |
colonmonospace: 0xFF1A, |
| 23575 |
colonsign: 0x20A1, |
| 23576 |
colonsmall: 0xFE55, |
| 23577 |
colontriangularhalfmod: 0x02D1, |
| 23578 |
colontriangularmod: 0x02D0, |
| 23579 |
comma: 0x002C, |
| 23580 |
commaabovecmb: 0x0313, |
| 23581 |
commaaboverightcmb: 0x0315, |
| 23582 |
commaaccent: 0xF6C3, |
| 23583 |
commaarabic: 0x060C, |
| 23584 |
commaarmenian: 0x055D, |
| 23585 |
commainferior: 0xF6E1, |
| 23586 |
commamonospace: 0xFF0C, |
| 23587 |
commareversedabovecmb: 0x0314, |
| 23588 |
commareversedmod: 0x02BD, |
| 23589 |
commasmall: 0xFE50, |
| 23590 |
commasuperior: 0xF6E2, |
| 23591 |
commaturnedabovecmb: 0x0312, |
| 23592 |
commaturnedmod: 0x02BB, |
| 23593 |
compass: 0x263C, |
| 23594 |
congruent: 0x2245, |
| 23595 |
contourintegral: 0x222E, |
| 23596 |
control: 0x2303, |
| 23597 |
controlACK: 0x0006, |
| 23598 |
controlBEL: 0x0007, |
| 23599 |
controlBS: 0x0008, |
| 23600 |
controlCAN: 0x0018, |
| 23601 |
controlCR: 0x000D, |
| 23602 |
controlDC1: 0x0011, |
| 23603 |
controlDC2: 0x0012, |
| 23604 |
controlDC3: 0x0013, |
| 23605 |
controlDC4: 0x0014, |
| 23606 |
controlDEL: 0x007F, |
| 23607 |
controlDLE: 0x0010, |
| 23608 |
controlEM: 0x0019, |
| 23609 |
controlENQ: 0x0005, |
| 23610 |
controlEOT: 0x0004, |
| 23611 |
controlESC: 0x001B, |
| 23612 |
controlETB: 0x0017, |
| 23613 |
controlETX: 0x0003, |
| 23614 |
controlFF: 0x000C, |
| 23615 |
controlFS: 0x001C, |
| 23616 |
controlGS: 0x001D, |
| 23617 |
controlHT: 0x0009, |
| 23618 |
controlLF: 0x000A, |
| 23619 |
controlNAK: 0x0015, |
| 23620 |
controlRS: 0x001E, |
| 23621 |
controlSI: 0x000F, |
| 23622 |
controlSO: 0x000E, |
| 23623 |
controlSOT: 0x0002, |
| 23624 |
controlSTX: 0x0001, |
| 23625 |
controlSUB: 0x001A, |
| 23626 |
controlSYN: 0x0016, |
| 23627 |
controlUS: 0x001F, |
| 23628 |
controlVT: 0x000B, |
| 23629 |
copyright: 0x00A9, |
| 23630 |
copyrightsans: 0xF8E9, |
| 23631 |
copyrightserif: 0xF6D9, |
| 23632 |
cornerbracketleft: 0x300C, |
| 23633 |
cornerbracketlefthalfwidth: 0xFF62, |
| 23634 |
cornerbracketleftvertical: 0xFE41, |
| 23635 |
cornerbracketright: 0x300D, |
| 23636 |
cornerbracketrighthalfwidth: 0xFF63, |
| 23637 |
cornerbracketrightvertical: 0xFE42, |
| 23638 |
corporationsquare: 0x337F, |
| 23639 |
cosquare: 0x33C7, |
| 23640 |
coverkgsquare: 0x33C6, |
| 23641 |
cparen: 0x249E, |
| 23642 |
cruzeiro: 0x20A2, |
| 23643 |
cstretched: 0x0297, |
| 23644 |
curlyand: 0x22CF, |
| 23645 |
curlyor: 0x22CE, |
| 23646 |
currency: 0x00A4, |
| 23647 |
cyrBreve: 0xF6D1, |
| 23648 |
cyrFlex: 0xF6D2, |
| 23649 |
cyrbreve: 0xF6D4, |
| 23650 |
cyrflex: 0xF6D5, |
| 23651 |
d: 0x0064, |
| 23652 |
daarmenian: 0x0564, |
| 23653 |
dabengali: 0x09A6, |
| 23654 |
dadarabic: 0x0636, |
| 23655 |
dadeva: 0x0926, |
| 23656 |
dadfinalarabic: 0xFEBE, |
| 23657 |
dadinitialarabic: 0xFEBF, |
| 23658 |
dadmedialarabic: 0xFEC0, |
| 23659 |
dagesh: 0x05BC, |
| 23660 |
dageshhebrew: 0x05BC, |
| 23661 |
dagger: 0x2020, |
| 23662 |
daggerdbl: 0x2021, |
| 23663 |
dagujarati: 0x0AA6, |
| 23664 |
dagurmukhi: 0x0A26, |
| 23665 |
dahiragana: 0x3060, |
| 23666 |
dakatakana: 0x30C0, |
| 23667 |
dalarabic: 0x062F, |
| 23668 |
dalet: 0x05D3, |
| 23669 |
daletdagesh: 0xFB33, |
| 23670 |
daletdageshhebrew: 0xFB33, |
| 23671 |
dalethebrew: 0x05D3, |
| 23672 |
dalfinalarabic: 0xFEAA, |
| 23673 |
dammaarabic: 0x064F, |
| 23674 |
dammalowarabic: 0x064F, |
| 23675 |
dammatanaltonearabic: 0x064C, |
| 23676 |
dammatanarabic: 0x064C, |
| 23677 |
danda: 0x0964, |
| 23678 |
dargahebrew: 0x05A7, |
| 23679 |
dargalefthebrew: 0x05A7, |
| 23680 |
dasiapneumatacyrilliccmb: 0x0485, |
| 23681 |
dblGrave: 0xF6D3, |
| 23682 |
dblanglebracketleft: 0x300A, |
| 23683 |
dblanglebracketleftvertical: 0xFE3D, |
| 23684 |
dblanglebracketright: 0x300B, |
| 23685 |
dblanglebracketrightvertical: 0xFE3E, |
| 23686 |
dblarchinvertedbelowcmb: 0x032B, |
| 23687 |
dblarrowleft: 0x21D4, |
| 23688 |
dblarrowright: 0x21D2, |
| 23689 |
dbldanda: 0x0965, |
| 23690 |
dblgrave: 0xF6D6, |
| 23691 |
dblgravecmb: 0x030F, |
| 23692 |
dblintegral: 0x222C, |
| 23693 |
dbllowline: 0x2017, |
| 23694 |
dbllowlinecmb: 0x0333, |
| 23695 |
dbloverlinecmb: 0x033F, |
| 23696 |
dblprimemod: 0x02BA, |
| 23697 |
dblverticalbar: 0x2016, |
| 23698 |
dblverticallineabovecmb: 0x030E, |
| 23699 |
dbopomofo: 0x3109, |
| 23700 |
dbsquare: 0x33C8, |
| 23701 |
dcaron: 0x010F, |
| 23702 |
dcedilla: 0x1E11, |
| 23703 |
dcircle: 0x24D3, |
| 23704 |
dcircumflexbelow: 0x1E13, |
| 23705 |
dcroat: 0x0111, |
| 23706 |
ddabengali: 0x09A1, |
| 23707 |
ddadeva: 0x0921, |
| 23708 |
ddagujarati: 0x0AA1, |
| 23709 |
ddagurmukhi: 0x0A21, |
| 23710 |
ddalarabic: 0x0688, |
| 23711 |
ddalfinalarabic: 0xFB89, |
| 23712 |
dddhadeva: 0x095C, |
| 23713 |
ddhabengali: 0x09A2, |
| 23714 |
ddhadeva: 0x0922, |
| 23715 |
ddhagujarati: 0x0AA2, |
| 23716 |
ddhagurmukhi: 0x0A22, |
| 23717 |
ddotaccent: 0x1E0B, |
| 23718 |
ddotbelow: 0x1E0D, |
| 23719 |
decimalseparatorarabic: 0x066B, |
| 23720 |
decimalseparatorpersian: 0x066B, |
| 23721 |
decyrillic: 0x0434, |
| 23722 |
degree: 0x00B0, |
| 23723 |
dehihebrew: 0x05AD, |
| 23724 |
dehiragana: 0x3067, |
| 23725 |
deicoptic: 0x03EF, |
| 23726 |
dekatakana: 0x30C7, |
| 23727 |
deleteleft: 0x232B, |
| 23728 |
deleteright: 0x2326, |
| 23729 |
delta: 0x03B4, |
| 23730 |
deltaturned: 0x018D, |
| 23731 |
denominatorminusonenumeratorbengali: 0x09F8, |
| 23732 |
dezh: 0x02A4, |
| 23733 |
dhabengali: 0x09A7, |
| 23734 |
dhadeva: 0x0927, |
| 23735 |
dhagujarati: 0x0AA7, |
| 23736 |
dhagurmukhi: 0x0A27, |
| 23737 |
dhook: 0x0257, |
| 23738 |
dialytikatonos: 0x0385, |
| 23739 |
dialytikatonoscmb: 0x0344, |
| 23740 |
diamond: 0x2666, |
| 23741 |
diamondsuitwhite: 0x2662, |
| 23742 |
dieresis: 0x00A8, |
| 23743 |
dieresisacute: 0xF6D7, |
| 23744 |
dieresisbelowcmb: 0x0324, |
| 23745 |
dieresiscmb: 0x0308, |
| 23746 |
dieresisgrave: 0xF6D8, |
| 23747 |
dieresistonos: 0x0385, |
| 23748 |
dihiragana: 0x3062, |
| 23749 |
dikatakana: 0x30C2, |
| 23750 |
dittomark: 0x3003, |
| 23751 |
divide: 0x00F7, |
| 23752 |
divides: 0x2223, |
| 23753 |
divisionslash: 0x2215, |
| 23754 |
djecyrillic: 0x0452, |
| 23755 |
dkshade: 0x2593, |
| 23756 |
dlinebelow: 0x1E0F, |
| 23757 |
dlsquare: 0x3397, |
| 23758 |
dmacron: 0x0111, |
| 23759 |
dmonospace: 0xFF44, |
| 23760 |
dnblock: 0x2584, |
| 23761 |
dochadathai: 0x0E0E, |
| 23762 |
dodekthai: 0x0E14, |
| 23763 |
dohiragana: 0x3069, |
| 23764 |
dokatakana: 0x30C9, |
| 23765 |
dollar: 0x0024, |
| 23766 |
dollarinferior: 0xF6E3, |
| 23767 |
dollarmonospace: 0xFF04, |
| 23768 |
dollaroldstyle: 0xF724, |
| 23769 |
dollarsmall: 0xFE69, |
| 23770 |
dollarsuperior: 0xF6E4, |
| 23771 |
dong: 0x20AB, |
| 23772 |
dorusquare: 0x3326, |
| 23773 |
dotaccent: 0x02D9, |
| 23774 |
dotaccentcmb: 0x0307, |
| 23775 |
dotbelowcmb: 0x0323, |
| 23776 |
dotbelowcomb: 0x0323, |
| 23777 |
dotkatakana: 0x30FB, |
| 23778 |
dotlessi: 0x0131, |
| 23779 |
dotlessj: 0xF6BE, |
| 23780 |
dotlessjstrokehook: 0x0284, |
| 23781 |
dotmath: 0x22C5, |
| 23782 |
dottedcircle: 0x25CC, |
| 23783 |
doubleyodpatah: 0xFB1F, |
| 23784 |
doubleyodpatahhebrew: 0xFB1F, |
| 23785 |
downtackbelowcmb: 0x031E, |
| 23786 |
downtackmod: 0x02D5, |
| 23787 |
dparen: 0x249F, |
| 23788 |
dsuperior: 0xF6EB, |
| 23789 |
dtail: 0x0256, |
| 23790 |
dtopbar: 0x018C, |
| 23791 |
duhiragana: 0x3065, |
| 23792 |
dukatakana: 0x30C5, |
| 23793 |
dz: 0x01F3, |
| 23794 |
dzaltone: 0x02A3, |
| 23795 |
dzcaron: 0x01C6, |
| 23796 |
dzcurl: 0x02A5, |
| 23797 |
dzeabkhasiancyrillic: 0x04E1, |
| 23798 |
dzecyrillic: 0x0455, |
| 23799 |
dzhecyrillic: 0x045F, |
| 23800 |
e: 0x0065, |
| 23801 |
eacute: 0x00E9, |
| 23802 |
earth: 0x2641, |
| 23803 |
ebengali: 0x098F, |
| 23804 |
ebopomofo: 0x311C, |
| 23805 |
ebreve: 0x0115, |
| 23806 |
ecandradeva: 0x090D, |
| 23807 |
ecandragujarati: 0x0A8D, |
| 23808 |
ecandravowelsigndeva: 0x0945, |
| 23809 |
ecandravowelsigngujarati: 0x0AC5, |
| 23810 |
ecaron: 0x011B, |
| 23811 |
ecedillabreve: 0x1E1D, |
| 23812 |
echarmenian: 0x0565, |
| 23813 |
echyiwnarmenian: 0x0587, |
| 23814 |
ecircle: 0x24D4, |
| 23815 |
ecircumflex: 0x00EA, |
| 23816 |
ecircumflexacute: 0x1EBF, |
| 23817 |
ecircumflexbelow: 0x1E19, |
| 23818 |
ecircumflexdotbelow: 0x1EC7, |
| 23819 |
ecircumflexgrave: 0x1EC1, |
| 23820 |
ecircumflexhookabove: 0x1EC3, |
| 23821 |
ecircumflextilde: 0x1EC5, |
| 23822 |
ecyrillic: 0x0454, |
| 23823 |
edblgrave: 0x0205, |
| 23824 |
edeva: 0x090F, |
| 23825 |
edieresis: 0x00EB, |
| 23826 |
edot: 0x0117, |
| 23827 |
edotaccent: 0x0117, |
| 23828 |
edotbelow: 0x1EB9, |
| 23829 |
eegurmukhi: 0x0A0F, |
| 23830 |
eematragurmukhi: 0x0A47, |
| 23831 |
efcyrillic: 0x0444, |
| 23832 |
egrave: 0x00E8, |
| 23833 |
egujarati: 0x0A8F, |
| 23834 |
eharmenian: 0x0567, |
| 23835 |
ehbopomofo: 0x311D, |
| 23836 |
ehiragana: 0x3048, |
| 23837 |
ehookabove: 0x1EBB, |
| 23838 |
eibopomofo: 0x311F, |
| 23839 |
eight: 0x0038, |
| 23840 |
eightarabic: 0x0668, |
| 23841 |
eightbengali: 0x09EE, |
| 23842 |
eightcircle: 0x2467, |
| 23843 |
eightcircleinversesansserif: 0x2791, |
| 23844 |
eightdeva: 0x096E, |
| 23845 |
eighteencircle: 0x2471, |
| 23846 |
eighteenparen: 0x2485, |
| 23847 |
eighteenperiod: 0x2499, |
| 23848 |
eightgujarati: 0x0AEE, |
| 23849 |
eightgurmukhi: 0x0A6E, |
| 23850 |
eighthackarabic: 0x0668, |
| 23851 |
eighthangzhou: 0x3028, |
| 23852 |
eighthnotebeamed: 0x266B, |
| 23853 |
eightideographicparen: 0x3227, |
| 23854 |
eightinferior: 0x2088, |
| 23855 |
eightmonospace: 0xFF18, |
| 23856 |
eightoldstyle: 0xF738, |
| 23857 |
eightparen: 0x247B, |
| 23858 |
eightperiod: 0x248F, |
| 23859 |
eightpersian: 0x06F8, |
| 23860 |
eightroman: 0x2177, |
| 23861 |
eightsuperior: 0x2078, |
| 23862 |
eightthai: 0x0E58, |
| 23863 |
einvertedbreve: 0x0207, |
| 23864 |
eiotifiedcyrillic: 0x0465, |
| 23865 |
ekatakana: 0x30A8, |
| 23866 |
ekatakanahalfwidth: 0xFF74, |
| 23867 |
ekonkargurmukhi: 0x0A74, |
| 23868 |
ekorean: 0x3154, |
| 23869 |
elcyrillic: 0x043B, |
| 23870 |
element: 0x2208, |
| 23871 |
elevencircle: 0x246A, |
| 23872 |
elevenparen: 0x247E, |
| 23873 |
elevenperiod: 0x2492, |
| 23874 |
elevenroman: 0x217A, |
| 23875 |
ellipsis: 0x2026, |
| 23876 |
ellipsisvertical: 0x22EE, |
| 23877 |
emacron: 0x0113, |
| 23878 |
emacronacute: 0x1E17, |
| 23879 |
emacrongrave: 0x1E15, |
| 23880 |
emcyrillic: 0x043C, |
| 23881 |
emdash: 0x2014, |
| 23882 |
emdashvertical: 0xFE31, |
| 23883 |
emonospace: 0xFF45, |
| 23884 |
emphasismarkarmenian: 0x055B, |
| 23885 |
emptyset: 0x2205, |
| 23886 |
enbopomofo: 0x3123, |
| 23887 |
encyrillic: 0x043D, |
| 23888 |
endash: 0x2013, |
| 23889 |
endashvertical: 0xFE32, |
| 23890 |
endescendercyrillic: 0x04A3, |
| 23891 |
eng: 0x014B, |
| 23892 |
engbopomofo: 0x3125, |
| 23893 |
enghecyrillic: 0x04A5, |
| 23894 |
enhookcyrillic: 0x04C8, |
| 23895 |
enspace: 0x2002, |
| 23896 |
eogonek: 0x0119, |
| 23897 |
eokorean: 0x3153, |
| 23898 |
eopen: 0x025B, |
| 23899 |
eopenclosed: 0x029A, |
| 23900 |
eopenreversed: 0x025C, |
| 23901 |
eopenreversedclosed: 0x025E, |
| 23902 |
eopenreversedhook: 0x025D, |
| 23903 |
eparen: 0x24A0, |
| 23904 |
epsilon: 0x03B5, |
| 23905 |
epsilontonos: 0x03AD, |
| 23906 |
equal: 0x003D, |
| 23907 |
equalmonospace: 0xFF1D, |
| 23908 |
equalsmall: 0xFE66, |
| 23909 |
equalsuperior: 0x207C, |
| 23910 |
equivalence: 0x2261, |
| 23911 |
erbopomofo: 0x3126, |
| 23912 |
ercyrillic: 0x0440, |
| 23913 |
ereversed: 0x0258, |
| 23914 |
ereversedcyrillic: 0x044D, |
| 23915 |
escyrillic: 0x0441, |
| 23916 |
esdescendercyrillic: 0x04AB, |
| 23917 |
esh: 0x0283, |
| 23918 |
eshcurl: 0x0286, |
| 23919 |
eshortdeva: 0x090E, |
| 23920 |
eshortvowelsigndeva: 0x0946, |
| 23921 |
eshreversedloop: 0x01AA, |
| 23922 |
eshsquatreversed: 0x0285, |
| 23923 |
esmallhiragana: 0x3047, |
| 23924 |
esmallkatakana: 0x30A7, |
| 23925 |
esmallkatakanahalfwidth: 0xFF6A, |
| 23926 |
estimated: 0x212E, |
| 23927 |
esuperior: 0xF6EC, |
| 23928 |
eta: 0x03B7, |
| 23929 |
etarmenian: 0x0568, |
| 23930 |
etatonos: 0x03AE, |
| 23931 |
eth: 0x00F0, |
| 23932 |
etilde: 0x1EBD, |
| 23933 |
etildebelow: 0x1E1B, |
| 23934 |
etnahtafoukhhebrew: 0x0591, |
| 23935 |
etnahtafoukhlefthebrew: 0x0591, |
| 23936 |
etnahtahebrew: 0x0591, |
| 23937 |
etnahtalefthebrew: 0x0591, |
| 23938 |
eturned: 0x01DD, |
| 23939 |
eukorean: 0x3161, |
| 23940 |
euro: 0x20AC, |
| 23941 |
evowelsignbengali: 0x09C7, |
| 23942 |
evowelsigndeva: 0x0947, |
| 23943 |
evowelsigngujarati: 0x0AC7, |
| 23944 |
exclam: 0x0021, |
| 23945 |
exclamarmenian: 0x055C, |
| 23946 |
exclamdbl: 0x203C, |
| 23947 |
exclamdown: 0x00A1, |
| 23948 |
exclamdownsmall: 0xF7A1, |
| 23949 |
exclammonospace: 0xFF01, |
| 23950 |
exclamsmall: 0xF721, |
| 23951 |
existential: 0x2203, |
| 23952 |
ezh: 0x0292, |
| 23953 |
ezhcaron: 0x01EF, |
| 23954 |
ezhcurl: 0x0293, |
| 23955 |
ezhreversed: 0x01B9, |
| 23956 |
ezhtail: 0x01BA, |
| 23957 |
f: 0x0066, |
| 23958 |
fadeva: 0x095E, |
| 23959 |
fagurmukhi: 0x0A5E, |
| 23960 |
fahrenheit: 0x2109, |
| 23961 |
fathaarabic: 0x064E, |
| 23962 |
fathalowarabic: 0x064E, |
| 23963 |
fathatanarabic: 0x064B, |
| 23964 |
fbopomofo: 0x3108, |
| 23965 |
fcircle: 0x24D5, |
| 23966 |
fdotaccent: 0x1E1F, |
| 23967 |
feharabic: 0x0641, |
| 23968 |
feharmenian: 0x0586, |
| 23969 |
fehfinalarabic: 0xFED2, |
| 23970 |
fehinitialarabic: 0xFED3, |
| 23971 |
fehmedialarabic: 0xFED4, |
| 23972 |
feicoptic: 0x03E5, |
| 23973 |
female: 0x2640, |
| 23974 |
ff: 0xFB00, |
| 23975 |
ffi: 0xFB03, |
| 23976 |
ffl: 0xFB04, |
| 23977 |
fi: 0xFB01, |
| 23978 |
fifteencircle: 0x246E, |
| 23979 |
fifteenparen: 0x2482, |
| 23980 |
fifteenperiod: 0x2496, |
| 23981 |
figuredash: 0x2012, |
| 23982 |
filledbox: 0x25A0, |
| 23983 |
filledrect: 0x25AC, |
| 23984 |
finalkaf: 0x05DA, |
| 23985 |
finalkafdagesh: 0xFB3A, |
| 23986 |
finalkafdageshhebrew: 0xFB3A, |
| 23987 |
finalkafhebrew: 0x05DA, |
| 23988 |
finalmem: 0x05DD, |
| 23989 |
finalmemhebrew: 0x05DD, |
| 23990 |
finalnun: 0x05DF, |
| 23991 |
finalnunhebrew: 0x05DF, |
| 23992 |
finalpe: 0x05E3, |
| 23993 |
finalpehebrew: 0x05E3, |
| 23994 |
finaltsadi: 0x05E5, |
| 23995 |
finaltsadihebrew: 0x05E5, |
| 23996 |
firsttonechinese: 0x02C9, |
| 23997 |
fisheye: 0x25C9, |
| 23998 |
fitacyrillic: 0x0473, |
| 23999 |
five: 0x0035, |
| 24000 |
fivearabic: 0x0665, |
| 24001 |
fivebengali: 0x09EB, |
| 24002 |
fivecircle: 0x2464, |
| 24003 |
fivecircleinversesansserif: 0x278E, |
| 24004 |
fivedeva: 0x096B, |
| 24005 |
fiveeighths: 0x215D, |
| 24006 |
fivegujarati: 0x0AEB, |
| 24007 |
fivegurmukhi: 0x0A6B, |
| 24008 |
fivehackarabic: 0x0665, |
| 24009 |
fivehangzhou: 0x3025, |
| 24010 |
fiveideographicparen: 0x3224, |
| 24011 |
fiveinferior: 0x2085, |
| 24012 |
fivemonospace: 0xFF15, |
| 24013 |
fiveoldstyle: 0xF735, |
| 24014 |
fiveparen: 0x2478, |
| 24015 |
fiveperiod: 0x248C, |
| 24016 |
fivepersian: 0x06F5, |
| 24017 |
fiveroman: 0x2174, |
| 24018 |
fivesuperior: 0x2075, |
| 24019 |
fivethai: 0x0E55, |
| 24020 |
fl: 0xFB02, |
| 24021 |
florin: 0x0192, |
| 24022 |
fmonospace: 0xFF46, |
| 24023 |
fmsquare: 0x3399, |
| 24024 |
fofanthai: 0x0E1F, |
| 24025 |
fofathai: 0x0E1D, |
| 24026 |
fongmanthai: 0x0E4F, |
| 24027 |
forall: 0x2200, |
| 24028 |
four: 0x0034, |
| 24029 |
fourarabic: 0x0664, |
| 24030 |
fourbengali: 0x09EA, |
| 24031 |
fourcircle: 0x2463, |
| 24032 |
fourcircleinversesansserif: 0x278D, |
| 24033 |
fourdeva: 0x096A, |
| 24034 |
fourgujarati: 0x0AEA, |
| 24035 |
fourgurmukhi: 0x0A6A, |
| 24036 |
fourhackarabic: 0x0664, |
| 24037 |
fourhangzhou: 0x3024, |
| 24038 |
fourideographicparen: 0x3223, |
| 24039 |
fourinferior: 0x2084, |
| 24040 |
fourmonospace: 0xFF14, |
| 24041 |
fournumeratorbengali: 0x09F7, |
| 24042 |
fouroldstyle: 0xF734, |
| 24043 |
fourparen: 0x2477, |
| 24044 |
fourperiod: 0x248B, |
| 24045 |
fourpersian: 0x06F4, |
| 24046 |
fourroman: 0x2173, |
| 24047 |
foursuperior: 0x2074, |
| 24048 |
fourteencircle: 0x246D, |
| 24049 |
fourteenparen: 0x2481, |
| 24050 |
fourteenperiod: 0x2495, |
| 24051 |
fourthai: 0x0E54, |
| 24052 |
fourthtonechinese: 0x02CB, |
| 24053 |
fparen: 0x24A1, |
| 24054 |
fraction: 0x2044, |
| 24055 |
franc: 0x20A3, |
| 24056 |
g: 0x0067, |
| 24057 |
gabengali: 0x0997, |
| 24058 |
gacute: 0x01F5, |
| 24059 |
gadeva: 0x0917, |
| 24060 |
gafarabic: 0x06AF, |
| 24061 |
gaffinalarabic: 0xFB93, |
| 24062 |
gafinitialarabic: 0xFB94, |
| 24063 |
gafmedialarabic: 0xFB95, |
| 24064 |
gagujarati: 0x0A97, |
| 24065 |
gagurmukhi: 0x0A17, |
| 24066 |
gahiragana: 0x304C, |
| 24067 |
gakatakana: 0x30AC, |
| 24068 |
gamma: 0x03B3, |
| 24069 |
gammalatinsmall: 0x0263, |
| 24070 |
gammasuperior: 0x02E0, |
| 24071 |
gangiacoptic: 0x03EB, |
| 24072 |
gbopomofo: 0x310D, |
| 24073 |
gbreve: 0x011F, |
| 24074 |
gcaron: 0x01E7, |
| 24075 |
gcedilla: 0x0123, |
| 24076 |
gcircle: 0x24D6, |
| 24077 |
gcircumflex: 0x011D, |
| 24078 |
gcommaaccent: 0x0123, |
| 24079 |
gdot: 0x0121, |
| 24080 |
gdotaccent: 0x0121, |
| 24081 |
gecyrillic: 0x0433, |
| 24082 |
gehiragana: 0x3052, |
| 24083 |
gekatakana: 0x30B2, |
| 24084 |
geometricallyequal: 0x2251, |
| 24085 |
gereshaccenthebrew: 0x059C, |
| 24086 |
gereshhebrew: 0x05F3, |
| 24087 |
gereshmuqdamhebrew: 0x059D, |
| 24088 |
germandbls: 0x00DF, |
| 24089 |
gershayimaccenthebrew: 0x059E, |
| 24090 |
gershayimhebrew: 0x05F4, |
| 24091 |
getamark: 0x3013, |
| 24092 |
ghabengali: 0x0998, |
| 24093 |
ghadarmenian: 0x0572, |
| 24094 |
ghadeva: 0x0918, |
| 24095 |
ghagujarati: 0x0A98, |
| 24096 |
ghagurmukhi: 0x0A18, |
| 24097 |
ghainarabic: 0x063A, |
| 24098 |
ghainfinalarabic: 0xFECE, |
| 24099 |
ghaininitialarabic: 0xFECF, |
| 24100 |
ghainmedialarabic: 0xFED0, |
| 24101 |
ghemiddlehookcyrillic: 0x0495, |
| 24102 |
ghestrokecyrillic: 0x0493, |
| 24103 |
gheupturncyrillic: 0x0491, |
| 24104 |
ghhadeva: 0x095A, |
| 24105 |
ghhagurmukhi: 0x0A5A, |
| 24106 |
ghook: 0x0260, |
| 24107 |
ghzsquare: 0x3393, |
| 24108 |
gihiragana: 0x304E, |
| 24109 |
gikatakana: 0x30AE, |
| 24110 |
gimarmenian: 0x0563, |
| 24111 |
gimel: 0x05D2, |
| 24112 |
gimeldagesh: 0xFB32, |
| 24113 |
gimeldageshhebrew: 0xFB32, |
| 24114 |
gimelhebrew: 0x05D2, |
| 24115 |
gjecyrillic: 0x0453, |
| 24116 |
glottalinvertedstroke: 0x01BE, |
| 24117 |
glottalstop: 0x0294, |
| 24118 |
glottalstopinverted: 0x0296, |
| 24119 |
glottalstopmod: 0x02C0, |
| 24120 |
glottalstopreversed: 0x0295, |
| 24121 |
glottalstopreversedmod: 0x02C1, |
| 24122 |
glottalstopreversedsuperior: 0x02E4, |
| 24123 |
glottalstopstroke: 0x02A1, |
| 24124 |
glottalstopstrokereversed: 0x02A2, |
| 24125 |
gmacron: 0x1E21, |
| 24126 |
gmonospace: 0xFF47, |
| 24127 |
gohiragana: 0x3054, |
| 24128 |
gokatakana: 0x30B4, |
| 24129 |
gparen: 0x24A2, |
| 24130 |
gpasquare: 0x33AC, |
| 24131 |
gradient: 0x2207, |
| 24132 |
grave: 0x0060, |
| 24133 |
gravebelowcmb: 0x0316, |
| 24134 |
gravecmb: 0x0300, |
| 24135 |
gravecomb: 0x0300, |
| 24136 |
gravedeva: 0x0953, |
| 24137 |
gravelowmod: 0x02CE, |
| 24138 |
gravemonospace: 0xFF40, |
| 24139 |
gravetonecmb: 0x0340, |
| 24140 |
greater: 0x003E, |
| 24141 |
greaterequal: 0x2265, |
| 24142 |
greaterequalorless: 0x22DB, |
| 24143 |
greatermonospace: 0xFF1E, |
| 24144 |
greaterorequivalent: 0x2273, |
| 24145 |
greaterorless: 0x2277, |
| 24146 |
greateroverequal: 0x2267, |
| 24147 |
greatersmall: 0xFE65, |
| 24148 |
gscript: 0x0261, |
| 24149 |
gstroke: 0x01E5, |
| 24150 |
guhiragana: 0x3050, |
| 24151 |
guillemotleft: 0x00AB, |
| 24152 |
guillemotright: 0x00BB, |
| 24153 |
guilsinglleft: 0x2039, |
| 24154 |
guilsinglright: 0x203A, |
| 24155 |
gukatakana: 0x30B0, |
| 24156 |
guramusquare: 0x3318, |
| 24157 |
gysquare: 0x33C9, |
| 24158 |
h: 0x0068, |
| 24159 |
haabkhasiancyrillic: 0x04A9, |
| 24160 |
haaltonearabic: 0x06C1, |
| 24161 |
habengali: 0x09B9, |
| 24162 |
hadescendercyrillic: 0x04B3, |
| 24163 |
hadeva: 0x0939, |
| 24164 |
hagujarati: 0x0AB9, |
| 24165 |
hagurmukhi: 0x0A39, |
| 24166 |
haharabic: 0x062D, |
| 24167 |
hahfinalarabic: 0xFEA2, |
| 24168 |
hahinitialarabic: 0xFEA3, |
| 24169 |
hahiragana: 0x306F, |
| 24170 |
hahmedialarabic: 0xFEA4, |
| 24171 |
haitusquare: 0x332A, |
| 24172 |
hakatakana: 0x30CF, |
| 24173 |
hakatakanahalfwidth: 0xFF8A, |
| 24174 |
halantgurmukhi: 0x0A4D, |
| 24175 |
hamzaarabic: 0x0621, |
| 24176 |
hamzalowarabic: 0x0621, |
| 24177 |
hangulfiller: 0x3164, |
| 24178 |
hardsigncyrillic: 0x044A, |
| 24179 |
harpoonleftbarbup: 0x21BC, |
| 24180 |
harpoonrightbarbup: 0x21C0, |
| 24181 |
hasquare: 0x33CA, |
| 24182 |
hatafpatah: 0x05B2, |
| 24183 |
hatafpatah16: 0x05B2, |
| 24184 |
hatafpatah23: 0x05B2, |
| 24185 |
hatafpatah2f: 0x05B2, |
| 24186 |
hatafpatahhebrew: 0x05B2, |
| 24187 |
hatafpatahnarrowhebrew: 0x05B2, |
| 24188 |
hatafpatahquarterhebrew: 0x05B2, |
| 24189 |
hatafpatahwidehebrew: 0x05B2, |
| 24190 |
hatafqamats: 0x05B3, |
| 24191 |
hatafqamats1b: 0x05B3, |
| 24192 |
hatafqamats28: 0x05B3, |
| 24193 |
hatafqamats34: 0x05B3, |
| 24194 |
hatafqamatshebrew: 0x05B3, |
| 24195 |
hatafqamatsnarrowhebrew: 0x05B3, |
| 24196 |
hatafqamatsquarterhebrew: 0x05B3, |
| 24197 |
hatafqamatswidehebrew: 0x05B3, |
| 24198 |
hatafsegol: 0x05B1, |
| 24199 |
hatafsegol17: 0x05B1, |
| 24200 |
hatafsegol24: 0x05B1, |
| 24201 |
hatafsegol30: 0x05B1, |
| 24202 |
hatafsegolhebrew: 0x05B1, |
| 24203 |
hatafsegolnarrowhebrew: 0x05B1, |
| 24204 |
hatafsegolquarterhebrew: 0x05B1, |
| 24205 |
hatafsegolwidehebrew: 0x05B1, |
| 24206 |
hbar: 0x0127, |
| 24207 |
hbopomofo: 0x310F, |
| 24208 |
hbrevebelow: 0x1E2B, |
| 24209 |
hcedilla: 0x1E29, |
| 24210 |
hcircle: 0x24D7, |
| 24211 |
hcircumflex: 0x0125, |
| 24212 |
hdieresis: 0x1E27, |
| 24213 |
hdotaccent: 0x1E23, |
| 24214 |
hdotbelow: 0x1E25, |
| 24215 |
he: 0x05D4, |
| 24216 |
heart: 0x2665, |
| 24217 |
heartsuitblack: 0x2665, |
| 24218 |
heartsuitwhite: 0x2661, |
| 24219 |
hedagesh: 0xFB34, |
| 24220 |
hedageshhebrew: 0xFB34, |
| 24221 |
hehaltonearabic: 0x06C1, |
| 24222 |
heharabic: 0x0647, |
| 24223 |
hehebrew: 0x05D4, |
| 24224 |
hehfinalaltonearabic: 0xFBA7, |
| 24225 |
hehfinalalttwoarabic: 0xFEEA, |
| 24226 |
hehfinalarabic: 0xFEEA, |
| 24227 |
hehhamzaabovefinalarabic: 0xFBA5, |
| 24228 |
hehhamzaaboveisolatedarabic: 0xFBA4, |
| 24229 |
hehinitialaltonearabic: 0xFBA8, |
| 24230 |
hehinitialarabic: 0xFEEB, |
| 24231 |
hehiragana: 0x3078, |
| 24232 |
hehmedialaltonearabic: 0xFBA9, |
| 24233 |
hehmedialarabic: 0xFEEC, |
| 24234 |
heiseierasquare: 0x337B, |
| 24235 |
hekatakana: 0x30D8, |
| 24236 |
hekatakanahalfwidth: 0xFF8D, |
| 24237 |
hekutaarusquare: 0x3336, |
| 24238 |
henghook: 0x0267, |
| 24239 |
herutusquare: 0x3339, |
| 24240 |
het: 0x05D7, |
| 24241 |
hethebrew: 0x05D7, |
| 24242 |
hhook: 0x0266, |
| 24243 |
hhooksuperior: 0x02B1, |
| 24244 |
hieuhacirclekorean: 0x327B, |
| 24245 |
hieuhaparenkorean: 0x321B, |
| 24246 |
hieuhcirclekorean: 0x326D, |
| 24247 |
hieuhkorean: 0x314E, |
| 24248 |
hieuhparenkorean: 0x320D, |
| 24249 |
hihiragana: 0x3072, |
| 24250 |
hikatakana: 0x30D2, |
| 24251 |
hikatakanahalfwidth: 0xFF8B, |
| 24252 |
hiriq: 0x05B4, |
| 24253 |
hiriq14: 0x05B4, |
| 24254 |
hiriq21: 0x05B4, |
| 24255 |
hiriq2d: 0x05B4, |
| 24256 |
hiriqhebrew: 0x05B4, |
| 24257 |
hiriqnarrowhebrew: 0x05B4, |
| 24258 |
hiriqquarterhebrew: 0x05B4, |
| 24259 |
hiriqwidehebrew: 0x05B4, |
| 24260 |
hlinebelow: 0x1E96, |
| 24261 |
hmonospace: 0xFF48, |
| 24262 |
hoarmenian: 0x0570, |
| 24263 |
hohipthai: 0x0E2B, |
| 24264 |
hohiragana: 0x307B, |
| 24265 |
hokatakana: 0x30DB, |
| 24266 |
hokatakanahalfwidth: 0xFF8E, |
| 24267 |
holam: 0x05B9, |
| 24268 |
holam19: 0x05B9, |
| 24269 |
holam26: 0x05B9, |
| 24270 |
holam32: 0x05B9, |
| 24271 |
holamhebrew: 0x05B9, |
| 24272 |
holamnarrowhebrew: 0x05B9, |
| 24273 |
holamquarterhebrew: 0x05B9, |
| 24274 |
holamwidehebrew: 0x05B9, |
| 24275 |
honokhukthai: 0x0E2E, |
| 24276 |
hookabovecomb: 0x0309, |
| 24277 |
hookcmb: 0x0309, |
| 24278 |
hookpalatalizedbelowcmb: 0x0321, |
| 24279 |
hookretroflexbelowcmb: 0x0322, |
| 24280 |
hoonsquare: 0x3342, |
| 24281 |
horicoptic: 0x03E9, |
| 24282 |
horizontalbar: 0x2015, |
| 24283 |
horncmb: 0x031B, |
| 24284 |
hotsprings: 0x2668, |
| 24285 |
house: 0x2302, |
| 24286 |
hparen: 0x24A3, |
| 24287 |
hsuperior: 0x02B0, |
| 24288 |
hturned: 0x0265, |
| 24289 |
huhiragana: 0x3075, |
| 24290 |
huiitosquare: 0x3333, |
| 24291 |
hukatakana: 0x30D5, |
| 24292 |
hukatakanahalfwidth: 0xFF8C, |
| 24293 |
hungarumlaut: 0x02DD, |
| 24294 |
hungarumlautcmb: 0x030B, |
| 24295 |
hv: 0x0195, |
| 24296 |
hyphen: 0x002D, |
| 24297 |
hypheninferior: 0xF6E5, |
| 24298 |
hyphenmonospace: 0xFF0D, |
| 24299 |
hyphensmall: 0xFE63, |
| 24300 |
hyphensuperior: 0xF6E6, |
| 24301 |
hyphentwo: 0x2010, |
| 24302 |
i: 0x0069, |
| 24303 |
iacute: 0x00ED, |
| 24304 |
iacyrillic: 0x044F, |
| 24305 |
ibengali: 0x0987, |
| 24306 |
ibopomofo: 0x3127, |
| 24307 |
ibreve: 0x012D, |
| 24308 |
icaron: 0x01D0, |
| 24309 |
icircle: 0x24D8, |
| 24310 |
icircumflex: 0x00EE, |
| 24311 |
icyrillic: 0x0456, |
| 24312 |
idblgrave: 0x0209, |
| 24313 |
ideographearthcircle: 0x328F, |
| 24314 |
ideographfirecircle: 0x328B, |
| 24315 |
ideographicallianceparen: 0x323F, |
| 24316 |
ideographiccallparen: 0x323A, |
| 24317 |
ideographiccentrecircle: 0x32A5, |
| 24318 |
ideographicclose: 0x3006, |
| 24319 |
ideographiccomma: 0x3001, |
| 24320 |
ideographiccommaleft: 0xFF64, |
| 24321 |
ideographiccongratulationparen: 0x3237, |
| 24322 |
ideographiccorrectcircle: 0x32A3, |
| 24323 |
ideographicearthparen: 0x322F, |
| 24324 |
ideographicenterpriseparen: 0x323D, |
| 24325 |
ideographicexcellentcircle: 0x329D, |
| 24326 |
ideographicfestivalparen: 0x3240, |
| 24327 |
ideographicfinancialcircle: 0x3296, |
| 24328 |
ideographicfinancialparen: 0x3236, |
| 24329 |
ideographicfireparen: 0x322B, |
| 24330 |
ideographichaveparen: 0x3232, |
| 24331 |
ideographichighcircle: 0x32A4, |
| 24332 |
ideographiciterationmark: 0x3005, |
| 24333 |
ideographiclaborcircle: 0x3298, |
| 24334 |
ideographiclaborparen: 0x3238, |
| 24335 |
ideographicleftcircle: 0x32A7, |
| 24336 |
ideographiclowcircle: 0x32A6, |
| 24337 |
ideographicmedicinecircle: 0x32A9, |
| 24338 |
ideographicmetalparen: 0x322E, |
| 24339 |
ideographicmoonparen: 0x322A, |
| 24340 |
ideographicnameparen: 0x3234, |
| 24341 |
ideographicperiod: 0x3002, |
| 24342 |
ideographicprintcircle: 0x329E, |
| 24343 |
ideographicreachparen: 0x3243, |
| 24344 |
ideographicrepresentparen: 0x3239, |
| 24345 |
ideographicresourceparen: 0x323E, |
| 24346 |
ideographicrightcircle: 0x32A8, |
| 24347 |
ideographicsecretcircle: 0x3299, |
| 24348 |
ideographicselfparen: 0x3242, |
| 24349 |
ideographicsocietyparen: 0x3233, |
| 24350 |
ideographicspace: 0x3000, |
| 24351 |
ideographicspecialparen: 0x3235, |
| 24352 |
ideographicstockparen: 0x3231, |
| 24353 |
ideographicstudyparen: 0x323B, |
| 24354 |
ideographicsunparen: 0x3230, |
| 24355 |
ideographicsuperviseparen: 0x323C, |
| 24356 |
ideographicwaterparen: 0x322C, |
| 24357 |
ideographicwoodparen: 0x322D, |
| 24358 |
ideographiczero: 0x3007, |
| 24359 |
ideographmetalcircle: 0x328E, |
| 24360 |
ideographmooncircle: 0x328A, |
| 24361 |
ideographnamecircle: 0x3294, |
| 24362 |
ideographsuncircle: 0x3290, |
| 24363 |
ideographwatercircle: 0x328C, |
| 24364 |
ideographwoodcircle: 0x328D, |
| 24365 |
ideva: 0x0907, |
| 24366 |
idieresis: 0x00EF, |
| 24367 |
idieresisacute: 0x1E2F, |
| 24368 |
idieresiscyrillic: 0x04E5, |
| 24369 |
idotbelow: 0x1ECB, |
| 24370 |
iebrevecyrillic: 0x04D7, |
| 24371 |
iecyrillic: 0x0435, |
| 24372 |
ieungacirclekorean: 0x3275, |
| 24373 |
ieungaparenkorean: 0x3215, |
| 24374 |
ieungcirclekorean: 0x3267, |
| 24375 |
ieungkorean: 0x3147, |
| 24376 |
ieungparenkorean: 0x3207, |
| 24377 |
igrave: 0x00EC, |
| 24378 |
igujarati: 0x0A87, |
| 24379 |
igurmukhi: 0x0A07, |
| 24380 |
ihiragana: 0x3044, |
| 24381 |
ihookabove: 0x1EC9, |
| 24382 |
iibengali: 0x0988, |
| 24383 |
iicyrillic: 0x0438, |
| 24384 |
iideva: 0x0908, |
| 24385 |
iigujarati: 0x0A88, |
| 24386 |
iigurmukhi: 0x0A08, |
| 24387 |
iimatragurmukhi: 0x0A40, |
| 24388 |
iinvertedbreve: 0x020B, |
| 24389 |
iishortcyrillic: 0x0439, |
| 24390 |
iivowelsignbengali: 0x09C0, |
| 24391 |
iivowelsigndeva: 0x0940, |
| 24392 |
iivowelsigngujarati: 0x0AC0, |
| 24393 |
ij: 0x0133, |
| 24394 |
ikatakana: 0x30A4, |
| 24395 |
ikatakanahalfwidth: 0xFF72, |
| 24396 |
ikorean: 0x3163, |
| 24397 |
ilde: 0x02DC, |
| 24398 |
iluyhebrew: 0x05AC, |
| 24399 |
imacron: 0x012B, |
| 24400 |
imacroncyrillic: 0x04E3, |
| 24401 |
imageorapproximatelyequal: 0x2253, |
| 24402 |
imatragurmukhi: 0x0A3F, |
| 24403 |
imonospace: 0xFF49, |
| 24404 |
increment: 0x2206, |
| 24405 |
infinity: 0x221E, |
| 24406 |
iniarmenian: 0x056B, |
| 24407 |
integral: 0x222B, |
| 24408 |
integralbottom: 0x2321, |
| 24409 |
integralbt: 0x2321, |
| 24410 |
integralex: 0xF8F5, |
| 24411 |
integraltop: 0x2320, |
| 24412 |
integraltp: 0x2320, |
| 24413 |
intersection: 0x2229, |
| 24414 |
intisquare: 0x3305, |
| 24415 |
invbullet: 0x25D8, |
| 24416 |
invcircle: 0x25D9, |
| 24417 |
invsmileface: 0x263B, |
| 24418 |
iocyrillic: 0x0451, |
| 24419 |
iogonek: 0x012F, |
| 24420 |
iota: 0x03B9, |
| 24421 |
iotadieresis: 0x03CA, |
| 24422 |
iotadieresistonos: 0x0390, |
| 24423 |
iotalatin: 0x0269, |
| 24424 |
iotatonos: 0x03AF, |
| 24425 |
iparen: 0x24A4, |
| 24426 |
irigurmukhi: 0x0A72, |
| 24427 |
ismallhiragana: 0x3043, |
| 24428 |
ismallkatakana: 0x30A3, |
| 24429 |
ismallkatakanahalfwidth: 0xFF68, |
| 24430 |
issharbengali: 0x09FA, |
| 24431 |
istroke: 0x0268, |
| 24432 |
isuperior: 0xF6ED, |
| 24433 |
iterationhiragana: 0x309D, |
| 24434 |
iterationkatakana: 0x30FD, |
| 24435 |
itilde: 0x0129, |
| 24436 |
itildebelow: 0x1E2D, |
| 24437 |
iubopomofo: 0x3129, |
| 24438 |
iucyrillic: 0x044E, |
| 24439 |
ivowelsignbengali: 0x09BF, |
| 24440 |
ivowelsigndeva: 0x093F, |
| 24441 |
ivowelsigngujarati: 0x0ABF, |
| 24442 |
izhitsacyrillic: 0x0475, |
| 24443 |
izhitsadblgravecyrillic: 0x0477, |
| 24444 |
j: 0x006A, |
| 24445 |
jaarmenian: 0x0571, |
| 24446 |
jabengali: 0x099C, |
| 24447 |
jadeva: 0x091C, |
| 24448 |
jagujarati: 0x0A9C, |
| 24449 |
jagurmukhi: 0x0A1C, |
| 24450 |
jbopomofo: 0x3110, |
| 24451 |
jcaron: 0x01F0, |
| 24452 |
jcircle: 0x24D9, |
| 24453 |
jcircumflex: 0x0135, |
| 24454 |
jcrossedtail: 0x029D, |
| 24455 |
jdotlessstroke: 0x025F, |
| 24456 |
jecyrillic: 0x0458, |
| 24457 |
jeemarabic: 0x062C, |
| 24458 |
jeemfinalarabic: 0xFE9E, |
| 24459 |
jeeminitialarabic: 0xFE9F, |
| 24460 |
jeemmedialarabic: 0xFEA0, |
| 24461 |
jeharabic: 0x0698, |
| 24462 |
jehfinalarabic: 0xFB8B, |
| 24463 |
jhabengali: 0x099D, |
| 24464 |
jhadeva: 0x091D, |
| 24465 |
jhagujarati: 0x0A9D, |
| 24466 |
jhagurmukhi: 0x0A1D, |
| 24467 |
jheharmenian: 0x057B, |
| 24468 |
jis: 0x3004, |
| 24469 |
jmonospace: 0xFF4A, |
| 24470 |
jparen: 0x24A5, |
| 24471 |
jsuperior: 0x02B2, |
| 24472 |
k: 0x006B, |
| 24473 |
kabashkircyrillic: 0x04A1, |
| 24474 |
kabengali: 0x0995, |
| 24475 |
kacute: 0x1E31, |
| 24476 |
kacyrillic: 0x043A, |
| 24477 |
kadescendercyrillic: 0x049B, |
| 24478 |
kadeva: 0x0915, |
| 24479 |
kaf: 0x05DB, |
| 24480 |
kafarabic: 0x0643, |
| 24481 |
kafdagesh: 0xFB3B, |
| 24482 |
kafdageshhebrew: 0xFB3B, |
| 24483 |
kaffinalarabic: 0xFEDA, |
| 24484 |
kafhebrew: 0x05DB, |
| 24485 |
kafinitialarabic: 0xFEDB, |
| 24486 |
kafmedialarabic: 0xFEDC, |
| 24487 |
kafrafehebrew: 0xFB4D, |
| 24488 |
kagujarati: 0x0A95, |
| 24489 |
kagurmukhi: 0x0A15, |
| 24490 |
kahiragana: 0x304B, |
| 24491 |
kahookcyrillic: 0x04C4, |
| 24492 |
kakatakana: 0x30AB, |
| 24493 |
kakatakanahalfwidth: 0xFF76, |
| 24494 |
kappa: 0x03BA, |
| 24495 |
kappasymbolgreek: 0x03F0, |
| 24496 |
kapyeounmieumkorean: 0x3171, |
| 24497 |
kapyeounphieuphkorean: 0x3184, |
| 24498 |
kapyeounpieupkorean: 0x3178, |
| 24499 |
kapyeounssangpieupkorean: 0x3179, |
| 24500 |
karoriisquare: 0x330D, |
| 24501 |
kashidaautoarabic: 0x0640, |
| 24502 |
kashidaautonosidebearingarabic: 0x0640, |
| 24503 |
kasmallkatakana: 0x30F5, |
| 24504 |
kasquare: 0x3384, |
| 24505 |
kasraarabic: 0x0650, |
| 24506 |
kasratanarabic: 0x064D, |
| 24507 |
kastrokecyrillic: 0x049F, |
| 24508 |
katahiraprolongmarkhalfwidth: 0xFF70, |
| 24509 |
kaverticalstrokecyrillic: 0x049D, |
| 24510 |
kbopomofo: 0x310E, |
| 24511 |
kcalsquare: 0x3389, |
| 24512 |
kcaron: 0x01E9, |
| 24513 |
kcedilla: 0x0137, |
| 24514 |
kcircle: 0x24DA, |
| 24515 |
kcommaaccent: 0x0137, |
| 24516 |
kdotbelow: 0x1E33, |
| 24517 |
keharmenian: 0x0584, |
| 24518 |
kehiragana: 0x3051, |
| 24519 |
kekatakana: 0x30B1, |
| 24520 |
kekatakanahalfwidth: 0xFF79, |
| 24521 |
kenarmenian: 0x056F, |
| 24522 |
kesmallkatakana: 0x30F6, |
| 24523 |
kgreenlandic: 0x0138, |
| 24524 |
khabengali: 0x0996, |
| 24525 |
khacyrillic: 0x0445, |
| 24526 |
khadeva: 0x0916, |
| 24527 |
khagujarati: 0x0A96, |
| 24528 |
khagurmukhi: 0x0A16, |
| 24529 |
khaharabic: 0x062E, |
| 24530 |
khahfinalarabic: 0xFEA6, |
| 24531 |
khahinitialarabic: 0xFEA7, |
| 24532 |
khahmedialarabic: 0xFEA8, |
| 24533 |
kheicoptic: 0x03E7, |
| 24534 |
khhadeva: 0x0959, |
| 24535 |
khhagurmukhi: 0x0A59, |
| 24536 |
khieukhacirclekorean: 0x3278, |
| 24537 |
khieukhaparenkorean: 0x3218, |
| 24538 |
khieukhcirclekorean: 0x326A, |
| 24539 |
khieukhkorean: 0x314B, |
| 24540 |
khieukhparenkorean: 0x320A, |
| 24541 |
khokhaithai: 0x0E02, |
| 24542 |
khokhonthai: 0x0E05, |
| 24543 |
khokhuatthai: 0x0E03, |
| 24544 |
khokhwaithai: 0x0E04, |
| 24545 |
khomutthai: 0x0E5B, |
| 24546 |
khook: 0x0199, |
| 24547 |
khorakhangthai: 0x0E06, |
| 24548 |
khzsquare: 0x3391, |
| 24549 |
kihiragana: 0x304D, |
| 24550 |
kikatakana: 0x30AD, |
| 24551 |
kikatakanahalfwidth: 0xFF77, |
| 24552 |
kiroguramusquare: 0x3315, |
| 24553 |
kiromeetorusquare: 0x3316, |
| 24554 |
kirosquare: 0x3314, |
| 24555 |
kiyeokacirclekorean: 0x326E, |
| 24556 |
kiyeokaparenkorean: 0x320E, |
| 24557 |
kiyeokcirclekorean: 0x3260, |
| 24558 |
kiyeokkorean: 0x3131, |
| 24559 |
kiyeokparenkorean: 0x3200, |
| 24560 |
kiyeoksioskorean: 0x3133, |
| 24561 |
kjecyrillic: 0x045C, |
| 24562 |
klinebelow: 0x1E35, |
| 24563 |
klsquare: 0x3398, |
| 24564 |
kmcubedsquare: 0x33A6, |
| 24565 |
kmonospace: 0xFF4B, |
| 24566 |
kmsquaredsquare: 0x33A2, |
| 24567 |
kohiragana: 0x3053, |
| 24568 |
kohmsquare: 0x33C0, |
| 24569 |
kokaithai: 0x0E01, |
| 24570 |
kokatakana: 0x30B3, |
| 24571 |
kokatakanahalfwidth: 0xFF7A, |
| 24572 |
kooposquare: 0x331E, |
| 24573 |
koppacyrillic: 0x0481, |
| 24574 |
koreanstandardsymbol: 0x327F, |
| 24575 |
koroniscmb: 0x0343, |
| 24576 |
kparen: 0x24A6, |
| 24577 |
kpasquare: 0x33AA, |
| 24578 |
ksicyrillic: 0x046F, |
| 24579 |
ktsquare: 0x33CF, |
| 24580 |
kturned: 0x029E, |
| 24581 |
kuhiragana: 0x304F, |
| 24582 |
kukatakana: 0x30AF, |
| 24583 |
kukatakanahalfwidth: 0xFF78, |
| 24584 |
kvsquare: 0x33B8, |
| 24585 |
kwsquare: 0x33BE, |
| 24586 |
l: 0x006C, |
| 24587 |
labengali: 0x09B2, |
| 24588 |
lacute: 0x013A, |
| 24589 |
ladeva: 0x0932, |
| 24590 |
lagujarati: 0x0AB2, |
| 24591 |
lagurmukhi: 0x0A32, |
| 24592 |
lakkhangyaothai: 0x0E45, |
| 24593 |
lamaleffinalarabic: 0xFEFC, |
| 24594 |
lamalefhamzaabovefinalarabic: 0xFEF8, |
| 24595 |
lamalefhamzaaboveisolatedarabic: 0xFEF7, |
| 24596 |
lamalefhamzabelowfinalarabic: 0xFEFA, |
| 24597 |
lamalefhamzabelowisolatedarabic: 0xFEF9, |
| 24598 |
lamalefisolatedarabic: 0xFEFB, |
| 24599 |
lamalefmaddaabovefinalarabic: 0xFEF6, |
| 24600 |
lamalefmaddaaboveisolatedarabic: 0xFEF5, |
| 24601 |
lamarabic: 0x0644, |
| 24602 |
lambda: 0x03BB, |
| 24603 |
lambdastroke: 0x019B, |
| 24604 |
lamed: 0x05DC, |
| 24605 |
lameddagesh: 0xFB3C, |
| 24606 |
lameddageshhebrew: 0xFB3C, |
| 24607 |
lamedhebrew: 0x05DC, |
| 24608 |
lamfinalarabic: 0xFEDE, |
| 24609 |
lamhahinitialarabic: 0xFCCA, |
| 24610 |
laminitialarabic: 0xFEDF, |
| 24611 |
lamjeeminitialarabic: 0xFCC9, |
| 24612 |
lamkhahinitialarabic: 0xFCCB, |
| 24613 |
lamlamhehisolatedarabic: 0xFDF2, |
| 24614 |
lammedialarabic: 0xFEE0, |
| 24615 |
lammeemhahinitialarabic: 0xFD88, |
| 24616 |
lammeeminitialarabic: 0xFCCC, |
| 24617 |
largecircle: 0x25EF, |
| 24618 |
lbar: 0x019A, |
| 24619 |
lbelt: 0x026C, |
| 24620 |
lbopomofo: 0x310C, |
| 24621 |
lcaron: 0x013E, |
| 24622 |
lcedilla: 0x013C, |
| 24623 |
lcircle: 0x24DB, |
| 24624 |
lcircumflexbelow: 0x1E3D, |
| 24625 |
lcommaaccent: 0x013C, |
| 24626 |
ldot: 0x0140, |
| 24627 |
ldotaccent: 0x0140, |
| 24628 |
ldotbelow: 0x1E37, |
| 24629 |
ldotbelowmacron: 0x1E39, |
| 24630 |
leftangleabovecmb: 0x031A, |
| 24631 |
lefttackbelowcmb: 0x0318, |
| 24632 |
less: 0x003C, |
| 24633 |
lessequal: 0x2264, |
| 24634 |
lessequalorgreater: 0x22DA, |
| 24635 |
lessmonospace: 0xFF1C, |
| 24636 |
lessorequivalent: 0x2272, |
| 24637 |
lessorgreater: 0x2276, |
| 24638 |
lessoverequal: 0x2266, |
| 24639 |
lesssmall: 0xFE64, |
| 24640 |
lezh: 0x026E, |
| 24641 |
lfblock: 0x258C, |
| 24642 |
lhookretroflex: 0x026D, |
| 24643 |
lira: 0x20A4, |
| 24644 |
liwnarmenian: 0x056C, |
| 24645 |
lj: 0x01C9, |
| 24646 |
ljecyrillic: 0x0459, |
| 24647 |
ll: 0xF6C0, |
| 24648 |
lladeva: 0x0933, |
| 24649 |
llagujarati: 0x0AB3, |
| 24650 |
llinebelow: 0x1E3B, |
| 24651 |
llladeva: 0x0934, |
| 24652 |
llvocalicbengali: 0x09E1, |
| 24653 |
llvocalicdeva: 0x0961, |
| 24654 |
llvocalicvowelsignbengali: 0x09E3, |
| 24655 |
llvocalicvowelsigndeva: 0x0963, |
| 24656 |
lmiddletilde: 0x026B, |
| 24657 |
lmonospace: 0xFF4C, |
| 24658 |
lmsquare: 0x33D0, |
| 24659 |
lochulathai: 0x0E2C, |
| 24660 |
logicaland: 0x2227, |
| 24661 |
logicalnot: 0x00AC, |
| 24662 |
logicalnotreversed: 0x2310, |
| 24663 |
logicalor: 0x2228, |
| 24664 |
lolingthai: 0x0E25, |
| 24665 |
longs: 0x017F, |
| 24666 |
lowlinecenterline: 0xFE4E, |
| 24667 |
lowlinecmb: 0x0332, |
| 24668 |
lowlinedashed: 0xFE4D, |
| 24669 |
lozenge: 0x25CA, |
| 24670 |
lparen: 0x24A7, |
| 24671 |
lslash: 0x0142, |
| 24672 |
lsquare: 0x2113, |
| 24673 |
lsuperior: 0xF6EE, |
| 24674 |
ltshade: 0x2591, |
| 24675 |
luthai: 0x0E26, |
| 24676 |
lvocalicbengali: 0x098C, |
| 24677 |
lvocalicdeva: 0x090C, |
| 24678 |
lvocalicvowelsignbengali: 0x09E2, |
| 24679 |
lvocalicvowelsigndeva: 0x0962, |
| 24680 |
lxsquare: 0x33D3, |
| 24681 |
m: 0x006D, |
| 24682 |
mabengali: 0x09AE, |
| 24683 |
macron: 0x00AF, |
| 24684 |
macronbelowcmb: 0x0331, |
| 24685 |
macroncmb: 0x0304, |
| 24686 |
macronlowmod: 0x02CD, |
| 24687 |
macronmonospace: 0xFFE3, |
| 24688 |
macute: 0x1E3F, |
| 24689 |
madeva: 0x092E, |
| 24690 |
magujarati: 0x0AAE, |
| 24691 |
magurmukhi: 0x0A2E, |
| 24692 |
mahapakhhebrew: 0x05A4, |
| 24693 |
mahapakhlefthebrew: 0x05A4, |
| 24694 |
mahiragana: 0x307E, |
| 24695 |
maichattawalowleftthai: 0xF895, |
| 24696 |
maichattawalowrightthai: 0xF894, |
| 24697 |
maichattawathai: 0x0E4B, |
| 24698 |
maichattawaupperleftthai: 0xF893, |
| 24699 |
maieklowleftthai: 0xF88C, |
| 24700 |
maieklowrightthai: 0xF88B, |
| 24701 |
maiekthai: 0x0E48, |
| 24702 |
maiekupperleftthai: 0xF88A, |
| 24703 |
maihanakatleftthai: 0xF884, |
| 24704 |
maihanakatthai: 0x0E31, |
| 24705 |
maitaikhuleftthai: 0xF889, |
| 24706 |
maitaikhuthai: 0x0E47, |
| 24707 |
maitholowleftthai: 0xF88F, |
| 24708 |
maitholowrightthai: 0xF88E, |
| 24709 |
maithothai: 0x0E49, |
| 24710 |
maithoupperleftthai: 0xF88D, |
| 24711 |
maitrilowleftthai: 0xF892, |
| 24712 |
maitrilowrightthai: 0xF891, |
| 24713 |
maitrithai: 0x0E4A, |
| 24714 |
maitriupperleftthai: 0xF890, |
| 24715 |
maiyamokthai: 0x0E46, |
| 24716 |
makatakana: 0x30DE, |
| 24717 |
makatakanahalfwidth: 0xFF8F, |
| 24718 |
male: 0x2642, |
| 24719 |
mansyonsquare: 0x3347, |
| 24720 |
maqafhebrew: 0x05BE, |
| 24721 |
mars: 0x2642, |
| 24722 |
masoracirclehebrew: 0x05AF, |
| 24723 |
masquare: 0x3383, |
| 24724 |
mbopomofo: 0x3107, |
| 24725 |
mbsquare: 0x33D4, |
| 24726 |
mcircle: 0x24DC, |
| 24727 |
mcubedsquare: 0x33A5, |
| 24728 |
mdotaccent: 0x1E41, |
| 24729 |
mdotbelow: 0x1E43, |
| 24730 |
meemarabic: 0x0645, |
| 24731 |
meemfinalarabic: 0xFEE2, |
| 24732 |
meeminitialarabic: 0xFEE3, |
| 24733 |
meemmedialarabic: 0xFEE4, |
| 24734 |
meemmeeminitialarabic: 0xFCD1, |
| 24735 |
meemmeemisolatedarabic: 0xFC48, |
| 24736 |
meetorusquare: 0x334D, |
| 24737 |
mehiragana: 0x3081, |
| 24738 |
meizierasquare: 0x337E, |
| 24739 |
mekatakana: 0x30E1, |
| 24740 |
mekatakanahalfwidth: 0xFF92, |
| 24741 |
mem: 0x05DE, |
| 24742 |
memdagesh: 0xFB3E, |
| 24743 |
memdageshhebrew: 0xFB3E, |
| 24744 |
memhebrew: 0x05DE, |
| 24745 |
menarmenian: 0x0574, |
| 24746 |
merkhahebrew: 0x05A5, |
| 24747 |
merkhakefulahebrew: 0x05A6, |
| 24748 |
merkhakefulalefthebrew: 0x05A6, |
| 24749 |
merkhalefthebrew: 0x05A5, |
| 24750 |
mhook: 0x0271, |
| 24751 |
mhzsquare: 0x3392, |
| 24752 |
middledotkatakanahalfwidth: 0xFF65, |
| 24753 |
middot: 0x00B7, |
| 24754 |
mieumacirclekorean: 0x3272, |
| 24755 |
mieumaparenkorean: 0x3212, |
| 24756 |
mieumcirclekorean: 0x3264, |
| 24757 |
mieumkorean: 0x3141, |
| 24758 |
mieumpansioskorean: 0x3170, |
| 24759 |
mieumparenkorean: 0x3204, |
| 24760 |
mieumpieupkorean: 0x316E, |
| 24761 |
mieumsioskorean: 0x316F, |
| 24762 |
mihiragana: 0x307F, |
| 24763 |
mikatakana: 0x30DF, |
| 24764 |
mikatakanahalfwidth: 0xFF90, |
| 24765 |
minus: 0x2212, |
| 24766 |
minusbelowcmb: 0x0320, |
| 24767 |
minuscircle: 0x2296, |
| 24768 |
minusmod: 0x02D7, |
| 24769 |
minusplus: 0x2213, |
| 24770 |
minute: 0x2032, |
| 24771 |
miribaarusquare: 0x334A, |
| 24772 |
mirisquare: 0x3349, |
| 24773 |
mlonglegturned: 0x0270, |
| 24774 |
mlsquare: 0x3396, |
| 24775 |
mmcubedsquare: 0x33A3, |
| 24776 |
mmonospace: 0xFF4D, |
| 24777 |
mmsquaredsquare: 0x339F, |
| 24778 |
mohiragana: 0x3082, |
| 24779 |
mohmsquare: 0x33C1, |
| 24780 |
mokatakana: 0x30E2, |
| 24781 |
mokatakanahalfwidth: 0xFF93, |
| 24782 |
molsquare: 0x33D6, |
| 24783 |
momathai: 0x0E21, |
| 24784 |
moverssquare: 0x33A7, |
| 24785 |
moverssquaredsquare: 0x33A8, |
| 24786 |
mparen: 0x24A8, |
| 24787 |
mpasquare: 0x33AB, |
| 24788 |
mssquare: 0x33B3, |
| 24789 |
msuperior: 0xF6EF, |
| 24790 |
mturned: 0x026F, |
| 24791 |
mu: 0x00B5, |
| 24792 |
mu1: 0x00B5, |
| 24793 |
muasquare: 0x3382, |
| 24794 |
muchgreater: 0x226B, |
| 24795 |
muchless: 0x226A, |
| 24796 |
mufsquare: 0x338C, |
| 24797 |
mugreek: 0x03BC, |
| 24798 |
mugsquare: 0x338D, |
| 24799 |
muhiragana: 0x3080, |
| 24800 |
mukatakana: 0x30E0, |
| 24801 |
mukatakanahalfwidth: 0xFF91, |
| 24802 |
mulsquare: 0x3395, |
| 24803 |
multiply: 0x00D7, |
| 24804 |
mumsquare: 0x339B, |
| 24805 |
munahhebrew: 0x05A3, |
| 24806 |
munahlefthebrew: 0x05A3, |
| 24807 |
musicalnote: 0x266A, |
| 24808 |
musicalnotedbl: 0x266B, |
| 24809 |
musicflatsign: 0x266D, |
| 24810 |
musicsharpsign: 0x266F, |
| 24811 |
mussquare: 0x33B2, |
| 24812 |
muvsquare: 0x33B6, |
| 24813 |
muwsquare: 0x33BC, |
| 24814 |
mvmegasquare: 0x33B9, |
| 24815 |
mvsquare: 0x33B7, |
| 24816 |
mwmegasquare: 0x33BF, |
| 24817 |
mwsquare: 0x33BD, |
| 24818 |
n: 0x006E, |
| 24819 |
nabengali: 0x09A8, |
| 24820 |
nabla: 0x2207, |
| 24821 |
nacute: 0x0144, |
| 24822 |
nadeva: 0x0928, |
| 24823 |
nagujarati: 0x0AA8, |
| 24824 |
nagurmukhi: 0x0A28, |
| 24825 |
nahiragana: 0x306A, |
| 24826 |
nakatakana: 0x30CA, |
| 24827 |
nakatakanahalfwidth: 0xFF85, |
| 24828 |
napostrophe: 0x0149, |
| 24829 |
nasquare: 0x3381, |
| 24830 |
nbopomofo: 0x310B, |
| 24831 |
nbspace: 0x00A0, |
| 24832 |
ncaron: 0x0148, |
| 24833 |
ncedilla: 0x0146, |
| 24834 |
ncircle: 0x24DD, |
| 24835 |
ncircumflexbelow: 0x1E4B, |
| 24836 |
ncommaaccent: 0x0146, |
| 24837 |
ndotaccent: 0x1E45, |
| 24838 |
ndotbelow: 0x1E47, |
| 24839 |
nehiragana: 0x306D, |
| 24840 |
nekatakana: 0x30CD, |
| 24841 |
nekatakanahalfwidth: 0xFF88, |
| 24842 |
newsheqelsign: 0x20AA, |
| 24843 |
nfsquare: 0x338B, |
| 24844 |
ngabengali: 0x0999, |
| 24845 |
ngadeva: 0x0919, |
| 24846 |
ngagujarati: 0x0A99, |
| 24847 |
ngagurmukhi: 0x0A19, |
| 24848 |
ngonguthai: 0x0E07, |
| 24849 |
nhiragana: 0x3093, |
| 24850 |
nhookleft: 0x0272, |
| 24851 |
nhookretroflex: 0x0273, |
| 24852 |
nieunacirclekorean: 0x326F, |
| 24853 |
nieunaparenkorean: 0x320F, |
| 24854 |
nieuncieuckorean: 0x3135, |
| 24855 |
nieuncirclekorean: 0x3261, |
| 24856 |
nieunhieuhkorean: 0x3136, |
| 24857 |
nieunkorean: 0x3134, |
| 24858 |
nieunpansioskorean: 0x3168, |
| 24859 |
nieunparenkorean: 0x3201, |
| 24860 |
nieunsioskorean: 0x3167, |
| 24861 |
nieuntikeutkorean: 0x3166, |
| 24862 |
nihiragana: 0x306B, |
| 24863 |
nikatakana: 0x30CB, |
| 24864 |
nikatakanahalfwidth: 0xFF86, |
| 24865 |
nikhahitleftthai: 0xF899, |
| 24866 |
nikhahitthai: 0x0E4D, |
| 24867 |
nine: 0x0039, |
| 24868 |
ninearabic: 0x0669, |
| 24869 |
ninebengali: 0x09EF, |
| 24870 |
ninecircle: 0x2468, |
| 24871 |
ninecircleinversesansserif: 0x2792, |
| 24872 |
ninedeva: 0x096F, |
| 24873 |
ninegujarati: 0x0AEF, |
| 24874 |
ninegurmukhi: 0x0A6F, |
| 24875 |
ninehackarabic: 0x0669, |
| 24876 |
ninehangzhou: 0x3029, |
| 24877 |
nineideographicparen: 0x3228, |
| 24878 |
nineinferior: 0x2089, |
| 24879 |
ninemonospace: 0xFF19, |
| 24880 |
nineoldstyle: 0xF739, |
| 24881 |
nineparen: 0x247C, |
| 24882 |
nineperiod: 0x2490, |
| 24883 |
ninepersian: 0x06F9, |
| 24884 |
nineroman: 0x2178, |
| 24885 |
ninesuperior: 0x2079, |
| 24886 |
nineteencircle: 0x2472, |
| 24887 |
nineteenparen: 0x2486, |
| 24888 |
nineteenperiod: 0x249A, |
| 24889 |
ninethai: 0x0E59, |
| 24890 |
nj: 0x01CC, |
| 24891 |
njecyrillic: 0x045A, |
| 24892 |
nkatakana: 0x30F3, |
| 24893 |
nkatakanahalfwidth: 0xFF9D, |
| 24894 |
nlegrightlong: 0x019E, |
| 24895 |
nlinebelow: 0x1E49, |
| 24896 |
nmonospace: 0xFF4E, |
| 24897 |
nmsquare: 0x339A, |
| 24898 |
nnabengali: 0x09A3, |
| 24899 |
nnadeva: 0x0923, |
| 24900 |
nnagujarati: 0x0AA3, |
| 24901 |
nnagurmukhi: 0x0A23, |
| 24902 |
nnnadeva: 0x0929, |
| 24903 |
nohiragana: 0x306E, |
| 24904 |
nokatakana: 0x30CE, |
| 24905 |
nokatakanahalfwidth: 0xFF89, |
| 24906 |
nonbreakingspace: 0x00A0, |
| 24907 |
nonenthai: 0x0E13, |
| 24908 |
nonuthai: 0x0E19, |
| 24909 |
noonarabic: 0x0646, |
| 24910 |
noonfinalarabic: 0xFEE6, |
| 24911 |
noonghunnaarabic: 0x06BA, |
| 24912 |
noonghunnafinalarabic: 0xFB9F, |
| 24913 |
nooninitialarabic: 0xFEE7, |
| 24914 |
noonjeeminitialarabic: 0xFCD2, |
| 24915 |
noonjeemisolatedarabic: 0xFC4B, |
| 24916 |
noonmedialarabic: 0xFEE8, |
| 24917 |
noonmeeminitialarabic: 0xFCD5, |
| 24918 |
noonmeemisolatedarabic: 0xFC4E, |
| 24919 |
noonnoonfinalarabic: 0xFC8D, |
| 24920 |
notcontains: 0x220C, |
| 24921 |
notelement: 0x2209, |
| 24922 |
notelementof: 0x2209, |
| 24923 |
notequal: 0x2260, |
| 24924 |
notgreater: 0x226F, |
| 24925 |
notgreaternorequal: 0x2271, |
| 24926 |
notgreaternorless: 0x2279, |
| 24927 |
notidentical: 0x2262, |
| 24928 |
notless: 0x226E, |
| 24929 |
notlessnorequal: 0x2270, |
| 24930 |
notparallel: 0x2226, |
| 24931 |
notprecedes: 0x2280, |
| 24932 |
notsubset: 0x2284, |
| 24933 |
notsucceeds: 0x2281, |
| 24934 |
notsuperset: 0x2285, |
| 24935 |
nowarmenian: 0x0576, |
| 24936 |
nparen: 0x24A9, |
| 24937 |
nssquare: 0x33B1, |
| 24938 |
nsuperior: 0x207F, |
| 24939 |
ntilde: 0x00F1, |
| 24940 |
nu: 0x03BD, |
| 24941 |
nuhiragana: 0x306C, |
| 24942 |
nukatakana: 0x30CC, |
| 24943 |
nukatakanahalfwidth: 0xFF87, |
| 24944 |
nuktabengali: 0x09BC, |
| 24945 |
nuktadeva: 0x093C, |
| 24946 |
nuktagujarati: 0x0ABC, |
| 24947 |
nuktagurmukhi: 0x0A3C, |
| 24948 |
numbersign: 0x0023, |
| 24949 |
numbersignmonospace: 0xFF03, |
| 24950 |
numbersignsmall: 0xFE5F, |
| 24951 |
numeralsigngreek: 0x0374, |
| 24952 |
numeralsignlowergreek: 0x0375, |
| 24953 |
numero: 0x2116, |
| 24954 |
nun: 0x05E0, |
| 24955 |
nundagesh: 0xFB40, |
| 24956 |
nundageshhebrew: 0xFB40, |
| 24957 |
nunhebrew: 0x05E0, |
| 24958 |
nvsquare: 0x33B5, |
| 24959 |
nwsquare: 0x33BB, |
| 24960 |
nyabengali: 0x099E, |
| 24961 |
nyadeva: 0x091E, |
| 24962 |
nyagujarati: 0x0A9E, |
| 24963 |
nyagurmukhi: 0x0A1E, |
| 24964 |
o: 0x006F, |
| 24965 |
oacute: 0x00F3, |
| 24966 |
oangthai: 0x0E2D, |
| 24967 |
obarred: 0x0275, |
| 24968 |
obarredcyrillic: 0x04E9, |
| 24969 |
obarreddieresiscyrillic: 0x04EB, |
| 24970 |
obengali: 0x0993, |
| 24971 |
obopomofo: 0x311B, |
| 24972 |
obreve: 0x014F, |
| 24973 |
ocandradeva: 0x0911, |
| 24974 |
ocandragujarati: 0x0A91, |
| 24975 |
ocandravowelsigndeva: 0x0949, |
| 24976 |
ocandravowelsigngujarati: 0x0AC9, |
| 24977 |
ocaron: 0x01D2, |
| 24978 |
ocircle: 0x24DE, |
| 24979 |
ocircumflex: 0x00F4, |
| 24980 |
ocircumflexacute: 0x1ED1, |
| 24981 |
ocircumflexdotbelow: 0x1ED9, |
| 24982 |
ocircumflexgrave: 0x1ED3, |
| 24983 |
ocircumflexhookabove: 0x1ED5, |
| 24984 |
ocircumflextilde: 0x1ED7, |
| 24985 |
ocyrillic: 0x043E, |
| 24986 |
odblacute: 0x0151, |
| 24987 |
odblgrave: 0x020D, |
| 24988 |
odeva: 0x0913, |
| 24989 |
odieresis: 0x00F6, |
| 24990 |
odieresiscyrillic: 0x04E7, |
| 24991 |
odotbelow: 0x1ECD, |
| 24992 |
oe: 0x0153, |
| 24993 |
oekorean: 0x315A, |
| 24994 |
ogonek: 0x02DB, |
| 24995 |
ogonekcmb: 0x0328, |
| 24996 |
ograve: 0x00F2, |
| 24997 |
ogujarati: 0x0A93, |
| 24998 |
oharmenian: 0x0585, |
| 24999 |
ohiragana: 0x304A, |
| 25000 |
ohookabove: 0x1ECF, |
| 25001 |
ohorn: 0x01A1, |
| 25002 |
ohornacute: 0x1EDB, |
| 25003 |
ohorndotbelow: 0x1EE3, |
| 25004 |
ohorngrave: 0x1EDD, |
| 25005 |
ohornhookabove: 0x1EDF, |
| 25006 |
ohorntilde: 0x1EE1, |
| 25007 |
ohungarumlaut: 0x0151, |
| 25008 |
oi: 0x01A3, |
| 25009 |
oinvertedbreve: 0x020F, |
| 25010 |
okatakana: 0x30AA, |
| 25011 |
okatakanahalfwidth: 0xFF75, |
| 25012 |
okorean: 0x3157, |
| 25013 |
olehebrew: 0x05AB, |
| 25014 |
omacron: 0x014D, |
| 25015 |
omacronacute: 0x1E53, |
| 25016 |
omacrongrave: 0x1E51, |
| 25017 |
omdeva: 0x0950, |
| 25018 |
omega: 0x03C9, |
| 25019 |
omega1: 0x03D6, |
| 25020 |
omegacyrillic: 0x0461, |
| 25021 |
omegalatinclosed: 0x0277, |
| 25022 |
omegaroundcyrillic: 0x047B, |
| 25023 |
omegatitlocyrillic: 0x047D, |
| 25024 |
omegatonos: 0x03CE, |
| 25025 |
omgujarati: 0x0AD0, |
| 25026 |
omicron: 0x03BF, |
| 25027 |
omicrontonos: 0x03CC, |
| 25028 |
omonospace: 0xFF4F, |
| 25029 |
one: 0x0031, |
| 25030 |
onearabic: 0x0661, |
| 25031 |
onebengali: 0x09E7, |
| 25032 |
onecircle: 0x2460, |
| 25033 |
onecircleinversesansserif: 0x278A, |
| 25034 |
onedeva: 0x0967, |
| 25035 |
onedotenleader: 0x2024, |
| 25036 |
oneeighth: 0x215B, |
| 25037 |
onefitted: 0xF6DC, |
| 25038 |
onegujarati: 0x0AE7, |
| 25039 |
onegurmukhi: 0x0A67, |
| 25040 |
onehackarabic: 0x0661, |
| 25041 |
onehalf: 0x00BD, |
| 25042 |
onehangzhou: 0x3021, |
| 25043 |
oneideographicparen: 0x3220, |
| 25044 |
oneinferior: 0x2081, |
| 25045 |
onemonospace: 0xFF11, |
| 25046 |
onenumeratorbengali: 0x09F4, |
| 25047 |
oneoldstyle: 0xF731, |
| 25048 |
oneparen: 0x2474, |
| 25049 |
oneperiod: 0x2488, |
| 25050 |
onepersian: 0x06F1, |
| 25051 |
onequarter: 0x00BC, |
| 25052 |
oneroman: 0x2170, |
| 25053 |
onesuperior: 0x00B9, |
| 25054 |
onethai: 0x0E51, |
| 25055 |
onethird: 0x2153, |
| 25056 |
oogonek: 0x01EB, |
| 25057 |
oogonekmacron: 0x01ED, |
| 25058 |
oogurmukhi: 0x0A13, |
| 25059 |
oomatragurmukhi: 0x0A4B, |
| 25060 |
oopen: 0x0254, |
| 25061 |
oparen: 0x24AA, |
| 25062 |
openbullet: 0x25E6, |
| 25063 |
option: 0x2325, |
| 25064 |
ordfeminine: 0x00AA, |
| 25065 |
ordmasculine: 0x00BA, |
| 25066 |
orthogonal: 0x221F, |
| 25067 |
oshortdeva: 0x0912, |
| 25068 |
oshortvowelsigndeva: 0x094A, |
| 25069 |
oslash: 0x00F8, |
| 25070 |
oslashacute: 0x01FF, |
| 25071 |
osmallhiragana: 0x3049, |
| 25072 |
osmallkatakana: 0x30A9, |
| 25073 |
osmallkatakanahalfwidth: 0xFF6B, |
| 25074 |
ostrokeacute: 0x01FF, |
| 25075 |
osuperior: 0xF6F0, |
| 25076 |
otcyrillic: 0x047F, |
| 25077 |
otilde: 0x00F5, |
| 25078 |
otildeacute: 0x1E4D, |
| 25079 |
otildedieresis: 0x1E4F, |
| 25080 |
oubopomofo: 0x3121, |
| 25081 |
overline: 0x203E, |
| 25082 |
overlinecenterline: 0xFE4A, |
| 25083 |
overlinecmb: 0x0305, |
| 25084 |
overlinedashed: 0xFE49, |
| 25085 |
overlinedblwavy: 0xFE4C, |
| 25086 |
overlinewavy: 0xFE4B, |
| 25087 |
overscore: 0x00AF, |
| 25088 |
ovowelsignbengali: 0x09CB, |
| 25089 |
ovowelsigndeva: 0x094B, |
| 25090 |
ovowelsigngujarati: 0x0ACB, |
| 25091 |
p: 0x0070, |
| 25092 |
paampssquare: 0x3380, |
| 25093 |
paasentosquare: 0x332B, |
| 25094 |
pabengali: 0x09AA, |
| 25095 |
pacute: 0x1E55, |
| 25096 |
padeva: 0x092A, |
| 25097 |
pagedown: 0x21DF, |
| 25098 |
pageup: 0x21DE, |
| 25099 |
pagujarati: 0x0AAA, |
| 25100 |
pagurmukhi: 0x0A2A, |
| 25101 |
pahiragana: 0x3071, |
| 25102 |
paiyannoithai: 0x0E2F, |
| 25103 |
pakatakana: 0x30D1, |
| 25104 |
palatalizationcyrilliccmb: 0x0484, |
| 25105 |
palochkacyrillic: 0x04C0, |
| 25106 |
pansioskorean: 0x317F, |
| 25107 |
paragraph: 0x00B6, |
| 25108 |
parallel: 0x2225, |
| 25109 |
parenleft: 0x0028, |
| 25110 |
parenleftaltonearabic: 0xFD3E, |
| 25111 |
parenleftbt: 0xF8ED, |
| 25112 |
parenleftex: 0xF8EC, |
| 25113 |
parenleftinferior: 0x208D, |
| 25114 |
parenleftmonospace: 0xFF08, |
| 25115 |
parenleftsmall: 0xFE59, |
| 25116 |
parenleftsuperior: 0x207D, |
| 25117 |
parenlefttp: 0xF8EB, |
| 25118 |
parenleftvertical: 0xFE35, |
| 25119 |
parenright: 0x0029, |
| 25120 |
parenrightaltonearabic: 0xFD3F, |
| 25121 |
parenrightbt: 0xF8F8, |
| 25122 |
parenrightex: 0xF8F7, |
| 25123 |
parenrightinferior: 0x208E, |
| 25124 |
parenrightmonospace: 0xFF09, |
| 25125 |
parenrightsmall: 0xFE5A, |
| 25126 |
parenrightsuperior: 0x207E, |
| 25127 |
parenrighttp: 0xF8F6, |
| 25128 |
parenrightvertical: 0xFE36, |
| 25129 |
partialdiff: 0x2202, |
| 25130 |
paseqhebrew: 0x05C0, |
| 25131 |
pashtahebrew: 0x0599, |
| 25132 |
pasquare: 0x33A9, |
| 25133 |
patah: 0x05B7, |
| 25134 |
patah11: 0x05B7, |
| 25135 |
patah1d: 0x05B7, |
| 25136 |
patah2a: 0x05B7, |
| 25137 |
patahhebrew: 0x05B7, |
| 25138 |
patahnarrowhebrew: 0x05B7, |
| 25139 |
patahquarterhebrew: 0x05B7, |
| 25140 |
patahwidehebrew: 0x05B7, |
| 25141 |
pazerhebrew: 0x05A1, |
| 25142 |
pbopomofo: 0x3106, |
| 25143 |
pcircle: 0x24DF, |
| 25144 |
pdotaccent: 0x1E57, |
| 25145 |
pe: 0x05E4, |
| 25146 |
pecyrillic: 0x043F, |
| 25147 |
pedagesh: 0xFB44, |
| 25148 |
pedageshhebrew: 0xFB44, |
| 25149 |
peezisquare: 0x333B, |
| 25150 |
pefinaldageshhebrew: 0xFB43, |
| 25151 |
peharabic: 0x067E, |
| 25152 |
peharmenian: 0x057A, |
| 25153 |
pehebrew: 0x05E4, |
| 25154 |
pehfinalarabic: 0xFB57, |
| 25155 |
pehinitialarabic: 0xFB58, |
| 25156 |
pehiragana: 0x307A, |
| 25157 |
pehmedialarabic: 0xFB59, |
| 25158 |
pekatakana: 0x30DA, |
| 25159 |
pemiddlehookcyrillic: 0x04A7, |
| 25160 |
perafehebrew: 0xFB4E, |
| 25161 |
percent: 0x0025, |
| 25162 |
percentarabic: 0x066A, |
| 25163 |
percentmonospace: 0xFF05, |
| 25164 |
percentsmall: 0xFE6A, |
| 25165 |
period: 0x002E, |
| 25166 |
periodarmenian: 0x0589, |
| 25167 |
periodcentered: 0x00B7, |
| 25168 |
periodhalfwidth: 0xFF61, |
| 25169 |
periodinferior: 0xF6E7, |
| 25170 |
periodmonospace: 0xFF0E, |
| 25171 |
periodsmall: 0xFE52, |
| 25172 |
periodsuperior: 0xF6E8, |
| 25173 |
perispomenigreekcmb: 0x0342, |
| 25174 |
perpendicular: 0x22A5, |
| 25175 |
perthousand: 0x2030, |
| 25176 |
peseta: 0x20A7, |
| 25177 |
pfsquare: 0x338A, |
| 25178 |
phabengali: 0x09AB, |
| 25179 |
phadeva: 0x092B, |
| 25180 |
phagujarati: 0x0AAB, |
| 25181 |
phagurmukhi: 0x0A2B, |
| 25182 |
phi: 0x03C6, |
| 25183 |
phi1: 0x03D5, |
| 25184 |
phieuphacirclekorean: 0x327A, |
| 25185 |
phieuphaparenkorean: 0x321A, |
| 25186 |
phieuphcirclekorean: 0x326C, |
| 25187 |
phieuphkorean: 0x314D, |
| 25188 |
phieuphparenkorean: 0x320C, |
| 25189 |
philatin: 0x0278, |
| 25190 |
phinthuthai: 0x0E3A, |
| 25191 |
phisymbolgreek: 0x03D5, |
| 25192 |
phook: 0x01A5, |
| 25193 |
phophanthai: 0x0E1E, |
| 25194 |
phophungthai: 0x0E1C, |
| 25195 |
phosamphaothai: 0x0E20, |
| 25196 |
pi: 0x03C0, |
| 25197 |
pieupacirclekorean: 0x3273, |
| 25198 |
pieupaparenkorean: 0x3213, |
| 25199 |
pieupcieuckorean: 0x3176, |
| 25200 |
pieupcirclekorean: 0x3265, |
| 25201 |
pieupkiyeokkorean: 0x3172, |
| 25202 |
pieupkorean: 0x3142, |
| 25203 |
pieupparenkorean: 0x3205, |
| 25204 |
pieupsioskiyeokkorean: 0x3174, |
| 25205 |
pieupsioskorean: 0x3144, |
| 25206 |
pieupsiostikeutkorean: 0x3175, |
| 25207 |
pieupthieuthkorean: 0x3177, |
| 25208 |
pieuptikeutkorean: 0x3173, |
| 25209 |
pihiragana: 0x3074, |
| 25210 |
pikatakana: 0x30D4, |
| 25211 |
pisymbolgreek: 0x03D6, |
| 25212 |
piwrarmenian: 0x0583, |
| 25213 |
plus: 0x002B, |
| 25214 |
plusbelowcmb: 0x031F, |
| 25215 |
pluscircle: 0x2295, |
| 25216 |
plusminus: 0x00B1, |
| 25217 |
plusmod: 0x02D6, |
| 25218 |
plusmonospace: 0xFF0B, |
| 25219 |
plussmall: 0xFE62, |
| 25220 |
plussuperior: 0x207A, |
| 25221 |
pmonospace: 0xFF50, |
| 25222 |
pmsquare: 0x33D8, |
| 25223 |
pohiragana: 0x307D, |
| 25224 |
pointingindexdownwhite: 0x261F, |
| 25225 |
pointingindexleftwhite: 0x261C, |
| 25226 |
pointingindexrightwhite: 0x261E, |
| 25227 |
pointingindexupwhite: 0x261D, |
| 25228 |
pokatakana: 0x30DD, |
| 25229 |
poplathai: 0x0E1B, |
| 25230 |
postalmark: 0x3012, |
| 25231 |
postalmarkface: 0x3020, |
| 25232 |
pparen: 0x24AB, |
| 25233 |
precedes: 0x227A, |
| 25234 |
prescription: 0x211E, |
| 25235 |
primemod: 0x02B9, |
| 25236 |
primereversed: 0x2035, |
| 25237 |
product: 0x220F, |
| 25238 |
projective: 0x2305, |
| 25239 |
prolongedkana: 0x30FC, |
| 25240 |
propellor: 0x2318, |
| 25241 |
propersubset: 0x2282, |
| 25242 |
propersuperset: 0x2283, |
| 25243 |
proportion: 0x2237, |
| 25244 |
proportional: 0x221D, |
| 25245 |
psi: 0x03C8, |
| 25246 |
psicyrillic: 0x0471, |
| 25247 |
psilipneumatacyrilliccmb: 0x0486, |
| 25248 |
pssquare: 0x33B0, |
| 25249 |
puhiragana: 0x3077, |
| 25250 |
pukatakana: 0x30D7, |
| 25251 |
pvsquare: 0x33B4, |
| 25252 |
pwsquare: 0x33BA, |
| 25253 |
q: 0x0071, |
| 25254 |
qadeva: 0x0958, |
| 25255 |
qadmahebrew: 0x05A8, |
| 25256 |
qafarabic: 0x0642, |
| 25257 |
qaffinalarabic: 0xFED6, |
| 25258 |
qafinitialarabic: 0xFED7, |
| 25259 |
qafmedialarabic: 0xFED8, |
| 25260 |
qamats: 0x05B8, |
| 25261 |
qamats10: 0x05B8, |
| 25262 |
qamats1a: 0x05B8, |
| 25263 |
qamats1c: 0x05B8, |
| 25264 |
qamats27: 0x05B8, |
| 25265 |
qamats29: 0x05B8, |
| 25266 |
qamats33: 0x05B8, |
| 25267 |
qamatsde: 0x05B8, |
| 25268 |
qamatshebrew: 0x05B8, |
| 25269 |
qamatsnarrowhebrew: 0x05B8, |
| 25270 |
qamatsqatanhebrew: 0x05B8, |
| 25271 |
qamatsqatannarrowhebrew: 0x05B8, |
| 25272 |
qamatsqatanquarterhebrew: 0x05B8, |
| 25273 |
qamatsqatanwidehebrew: 0x05B8, |
| 25274 |
qamatsquarterhebrew: 0x05B8, |
| 25275 |
qamatswidehebrew: 0x05B8, |
| 25276 |
qarneyparahebrew: 0x059F, |
| 25277 |
qbopomofo: 0x3111, |
| 25278 |
qcircle: 0x24E0, |
| 25279 |
qhook: 0x02A0, |
| 25280 |
qmonospace: 0xFF51, |
| 25281 |
qof: 0x05E7, |
| 25282 |
qofdagesh: 0xFB47, |
| 25283 |
qofdageshhebrew: 0xFB47, |
| 25284 |
qofhebrew: 0x05E7, |
| 25285 |
qparen: 0x24AC, |
| 25286 |
quarternote: 0x2669, |
| 25287 |
qubuts: 0x05BB, |
| 25288 |
qubuts18: 0x05BB, |
| 25289 |
qubuts25: 0x05BB, |
| 25290 |
qubuts31: 0x05BB, |
| 25291 |
qubutshebrew: 0x05BB, |
| 25292 |
qubutsnarrowhebrew: 0x05BB, |
| 25293 |
qubutsquarterhebrew: 0x05BB, |
| 25294 |
qubutswidehebrew: 0x05BB, |
| 25295 |
question: 0x003F, |
| 25296 |
questionarabic: 0x061F, |
| 25297 |
questionarmenian: 0x055E, |
| 25298 |
questiondown: 0x00BF, |
| 25299 |
questiondownsmall: 0xF7BF, |
| 25300 |
questiongreek: 0x037E, |
| 25301 |
questionmonospace: 0xFF1F, |
| 25302 |
questionsmall: 0xF73F, |
| 25303 |
quotedbl: 0x0022, |
| 25304 |
quotedblbase: 0x201E, |
| 25305 |
quotedblleft: 0x201C, |
| 25306 |
quotedblmonospace: 0xFF02, |
| 25307 |
quotedblprime: 0x301E, |
| 25308 |
quotedblprimereversed: 0x301D, |
| 25309 |
quotedblright: 0x201D, |
| 25310 |
quoteleft: 0x2018, |
| 25311 |
quoteleftreversed: 0x201B, |
| 25312 |
quotereversed: 0x201B, |
| 25313 |
quoteright: 0x2019, |
| 25314 |
quoterightn: 0x0149, |
| 25315 |
quotesinglbase: 0x201A, |
| 25316 |
quotesingle: 0x0027, |
| 25317 |
quotesinglemonospace: 0xFF07, |
| 25318 |
r: 0x0072, |
| 25319 |
raarmenian: 0x057C, |
| 25320 |
rabengali: 0x09B0, |
| 25321 |
racute: 0x0155, |
| 25322 |
radeva: 0x0930, |
| 25323 |
radical: 0x221A, |
| 25324 |
radicalex: 0xF8E5, |
| 25325 |
radoverssquare: 0x33AE, |
| 25326 |
radoverssquaredsquare: 0x33AF, |
| 25327 |
radsquare: 0x33AD, |
| 25328 |
rafe: 0x05BF, |
| 25329 |
rafehebrew: 0x05BF, |
| 25330 |
ragujarati: 0x0AB0, |
| 25331 |
ragurmukhi: 0x0A30, |
| 25332 |
rahiragana: 0x3089, |
| 25333 |
rakatakana: 0x30E9, |
| 25334 |
rakatakanahalfwidth: 0xFF97, |
| 25335 |
ralowerdiagonalbengali: 0x09F1, |
| 25336 |
ramiddlediagonalbengali: 0x09F0, |
| 25337 |
ramshorn: 0x0264, |
| 25338 |
ratio: 0x2236, |
| 25339 |
rbopomofo: 0x3116, |
| 25340 |
rcaron: 0x0159, |
| 25341 |
rcedilla: 0x0157, |
| 25342 |
rcircle: 0x24E1, |
| 25343 |
rcommaaccent: 0x0157, |
| 25344 |
rdblgrave: 0x0211, |
| 25345 |
rdotaccent: 0x1E59, |
| 25346 |
rdotbelow: 0x1E5B, |
| 25347 |
rdotbelowmacron: 0x1E5D, |
| 25348 |
referencemark: 0x203B, |
| 25349 |
reflexsubset: 0x2286, |
| 25350 |
reflexsuperset: 0x2287, |
| 25351 |
registered: 0x00AE, |
| 25352 |
registersans: 0xF8E8, |
| 25353 |
registerserif: 0xF6DA, |
| 25354 |
reharabic: 0x0631, |
| 25355 |
reharmenian: 0x0580, |
| 25356 |
rehfinalarabic: 0xFEAE, |
| 25357 |
rehiragana: 0x308C, |
| 25358 |
rekatakana: 0x30EC, |
| 25359 |
rekatakanahalfwidth: 0xFF9A, |
| 25360 |
resh: 0x05E8, |
| 25361 |
reshdageshhebrew: 0xFB48, |
| 25362 |
reshhebrew: 0x05E8, |
| 25363 |
reversedtilde: 0x223D, |
| 25364 |
reviahebrew: 0x0597, |
| 25365 |
reviamugrashhebrew: 0x0597, |
| 25366 |
revlogicalnot: 0x2310, |
| 25367 |
rfishhook: 0x027E, |
| 25368 |
rfishhookreversed: 0x027F, |
| 25369 |
rhabengali: 0x09DD, |
| 25370 |
rhadeva: 0x095D, |
| 25371 |
rho: 0x03C1, |
| 25372 |
rhook: 0x027D, |
| 25373 |
rhookturned: 0x027B, |
| 25374 |
rhookturnedsuperior: 0x02B5, |
| 25375 |
rhosymbolgreek: 0x03F1, |
| 25376 |
rhotichookmod: 0x02DE, |
| 25377 |
rieulacirclekorean: 0x3271, |
| 25378 |
rieulaparenkorean: 0x3211, |
| 25379 |
rieulcirclekorean: 0x3263, |
| 25380 |
rieulhieuhkorean: 0x3140, |
| 25381 |
rieulkiyeokkorean: 0x313A, |
| 25382 |
rieulkiyeoksioskorean: 0x3169, |
| 25383 |
rieulkorean: 0x3139, |
| 25384 |
rieulmieumkorean: 0x313B, |
| 25385 |
rieulpansioskorean: 0x316C, |
| 25386 |
rieulparenkorean: 0x3203, |
| 25387 |
rieulphieuphkorean: 0x313F, |
| 25388 |
rieulpieupkorean: 0x313C, |
| 25389 |
rieulpieupsioskorean: 0x316B, |
| 25390 |
rieulsioskorean: 0x313D, |
| 25391 |
rieulthieuthkorean: 0x313E, |
| 25392 |
rieultikeutkorean: 0x316A, |
| 25393 |
rieulyeorinhieuhkorean: 0x316D, |
| 25394 |
rightangle: 0x221F, |
| 25395 |
righttackbelowcmb: 0x0319, |
| 25396 |
righttriangle: 0x22BF, |
| 25397 |
rihiragana: 0x308A, |
| 25398 |
rikatakana: 0x30EA, |
| 25399 |
rikatakanahalfwidth: 0xFF98, |
| 25400 |
ring: 0x02DA, |
| 25401 |
ringbelowcmb: 0x0325, |
| 25402 |
ringcmb: 0x030A, |
| 25403 |
ringhalfleft: 0x02BF, |
| 25404 |
ringhalfleftarmenian: 0x0559, |
| 25405 |
ringhalfleftbelowcmb: 0x031C, |
| 25406 |
ringhalfleftcentered: 0x02D3, |
| 25407 |
ringhalfright: 0x02BE, |
| 25408 |
ringhalfrightbelowcmb: 0x0339, |
| 25409 |
ringhalfrightcentered: 0x02D2, |
| 25410 |
rinvertedbreve: 0x0213, |
| 25411 |
rittorusquare: 0x3351, |
| 25412 |
rlinebelow: 0x1E5F, |
| 25413 |
rlongleg: 0x027C, |
| 25414 |
rlonglegturned: 0x027A, |
| 25415 |
rmonospace: 0xFF52, |
| 25416 |
rohiragana: 0x308D, |
| 25417 |
rokatakana: 0x30ED, |
| 25418 |
rokatakanahalfwidth: 0xFF9B, |
| 25419 |
roruathai: 0x0E23, |
| 25420 |
rparen: 0x24AD, |
| 25421 |
rrabengali: 0x09DC, |
| 25422 |
rradeva: 0x0931, |
| 25423 |
rragurmukhi: 0x0A5C, |
| 25424 |
rreharabic: 0x0691, |
| 25425 |
rrehfinalarabic: 0xFB8D, |
| 25426 |
rrvocalicbengali: 0x09E0, |
| 25427 |
rrvocalicdeva: 0x0960, |
| 25428 |
rrvocalicgujarati: 0x0AE0, |
| 25429 |
rrvocalicvowelsignbengali: 0x09C4, |
| 25430 |
rrvocalicvowelsigndeva: 0x0944, |
| 25431 |
rrvocalicvowelsigngujarati: 0x0AC4, |
| 25432 |
rsuperior: 0xF6F1, |
| 25433 |
rtblock: 0x2590, |
| 25434 |
rturned: 0x0279, |
| 25435 |
rturnedsuperior: 0x02B4, |
| 25436 |
ruhiragana: 0x308B, |
| 25437 |
rukatakana: 0x30EB, |
| 25438 |
rukatakanahalfwidth: 0xFF99, |
| 25439 |
rupeemarkbengali: 0x09F2, |
| 25440 |
rupeesignbengali: 0x09F3, |
| 25441 |
rupiah: 0xF6DD, |
| 25442 |
ruthai: 0x0E24, |
| 25443 |
rvocalicbengali: 0x098B, |
| 25444 |
rvocalicdeva: 0x090B, |
| 25445 |
rvocalicgujarati: 0x0A8B, |
| 25446 |
rvocalicvowelsignbengali: 0x09C3, |
| 25447 |
rvocalicvowelsigndeva: 0x0943, |
| 25448 |
rvocalicvowelsigngujarati: 0x0AC3, |
| 25449 |
s: 0x0073, |
| 25450 |
sabengali: 0x09B8, |
| 25451 |
sacute: 0x015B, |
| 25452 |
sacutedotaccent: 0x1E65, |
| 25453 |
sadarabic: 0x0635, |
| 25454 |
sadeva: 0x0938, |
| 25455 |
sadfinalarabic: 0xFEBA, |
| 25456 |
sadinitialarabic: 0xFEBB, |
| 25457 |
sadmedialarabic: 0xFEBC, |
| 25458 |
sagujarati: 0x0AB8, |
| 25459 |
sagurmukhi: 0x0A38, |
| 25460 |
sahiragana: 0x3055, |
| 25461 |
sakatakana: 0x30B5, |
| 25462 |
sakatakanahalfwidth: 0xFF7B, |
| 25463 |
sallallahoualayhewasallamarabic: 0xFDFA, |
| 25464 |
samekh: 0x05E1, |
| 25465 |
samekhdagesh: 0xFB41, |
| 25466 |
samekhdageshhebrew: 0xFB41, |
| 25467 |
samekhhebrew: 0x05E1, |
| 25468 |
saraaathai: 0x0E32, |
| 25469 |
saraaethai: 0x0E41, |
| 25470 |
saraaimaimalaithai: 0x0E44, |
| 25471 |
saraaimaimuanthai: 0x0E43, |
| 25472 |
saraamthai: 0x0E33, |
| 25473 |
saraathai: 0x0E30, |
| 25474 |
saraethai: 0x0E40, |
| 25475 |
saraiileftthai: 0xF886, |
| 25476 |
saraiithai: 0x0E35, |
| 25477 |
saraileftthai: 0xF885, |
| 25478 |
saraithai: 0x0E34, |
| 25479 |
saraothai: 0x0E42, |
| 25480 |
saraueeleftthai: 0xF888, |
| 25481 |
saraueethai: 0x0E37, |
| 25482 |
saraueleftthai: 0xF887, |
| 25483 |
sarauethai: 0x0E36, |
| 25484 |
sarauthai: 0x0E38, |
| 25485 |
sarauuthai: 0x0E39, |
| 25486 |
sbopomofo: 0x3119, |
| 25487 |
scaron: 0x0161, |
| 25488 |
scarondotaccent: 0x1E67, |
| 25489 |
scedilla: 0x015F, |
| 25490 |
schwa: 0x0259, |
| 25491 |
schwacyrillic: 0x04D9, |
| 25492 |
schwadieresiscyrillic: 0x04DB, |
| 25493 |
schwahook: 0x025A, |
| 25494 |
scircle: 0x24E2, |
| 25495 |
scircumflex: 0x015D, |
| 25496 |
scommaaccent: 0x0219, |
| 25497 |
sdotaccent: 0x1E61, |
| 25498 |
sdotbelow: 0x1E63, |
| 25499 |
sdotbelowdotaccent: 0x1E69, |
| 25500 |
seagullbelowcmb: 0x033C, |
| 25501 |
second: 0x2033, |
| 25502 |
secondtonechinese: 0x02CA, |
| 25503 |
section: 0x00A7, |
| 25504 |
seenarabic: 0x0633, |
| 25505 |
seenfinalarabic: 0xFEB2, |
| 25506 |
seeninitialarabic: 0xFEB3, |
| 25507 |
seenmedialarabic: 0xFEB4, |
| 25508 |
segol: 0x05B6, |
| 25509 |
segol13: 0x05B6, |
| 25510 |
segol1f: 0x05B6, |
| 25511 |
segol2c: 0x05B6, |
| 25512 |
segolhebrew: 0x05B6, |
| 25513 |
segolnarrowhebrew: 0x05B6, |
| 25514 |
segolquarterhebrew: 0x05B6, |
| 25515 |
segoltahebrew: 0x0592, |
| 25516 |
segolwidehebrew: 0x05B6, |
| 25517 |
seharmenian: 0x057D, |
| 25518 |
sehiragana: 0x305B, |
| 25519 |
sekatakana: 0x30BB, |
| 25520 |
sekatakanahalfwidth: 0xFF7E, |
| 25521 |
semicolon: 0x003B, |
| 25522 |
semicolonarabic: 0x061B, |
| 25523 |
semicolonmonospace: 0xFF1B, |
| 25524 |
semicolonsmall: 0xFE54, |
| 25525 |
semivoicedmarkkana: 0x309C, |
| 25526 |
semivoicedmarkkanahalfwidth: 0xFF9F, |
| 25527 |
sentisquare: 0x3322, |
| 25528 |
sentosquare: 0x3323, |
| 25529 |
seven: 0x0037, |
| 25530 |
sevenarabic: 0x0667, |
| 25531 |
sevenbengali: 0x09ED, |
| 25532 |
sevencircle: 0x2466, |
| 25533 |
sevencircleinversesansserif: 0x2790, |
| 25534 |
sevendeva: 0x096D, |
| 25535 |
seveneighths: 0x215E, |
| 25536 |
sevengujarati: 0x0AED, |
| 25537 |
sevengurmukhi: 0x0A6D, |
| 25538 |
sevenhackarabic: 0x0667, |
| 25539 |
sevenhangzhou: 0x3027, |
| 25540 |
sevenideographicparen: 0x3226, |
| 25541 |
seveninferior: 0x2087, |
| 25542 |
sevenmonospace: 0xFF17, |
| 25543 |
sevenoldstyle: 0xF737, |
| 25544 |
sevenparen: 0x247A, |
| 25545 |
sevenperiod: 0x248E, |
| 25546 |
sevenpersian: 0x06F7, |
| 25547 |
sevenroman: 0x2176, |
| 25548 |
sevensuperior: 0x2077, |
| 25549 |
seventeencircle: 0x2470, |
| 25550 |
seventeenparen: 0x2484, |
| 25551 |
seventeenperiod: 0x2498, |
| 25552 |
seventhai: 0x0E57, |
| 25553 |
sfthyphen: 0x00AD, |
| 25554 |
shaarmenian: 0x0577, |
| 25555 |
shabengali: 0x09B6, |
| 25556 |
shacyrillic: 0x0448, |
| 25557 |
shaddaarabic: 0x0651, |
| 25558 |
shaddadammaarabic: 0xFC61, |
| 25559 |
shaddadammatanarabic: 0xFC5E, |
| 25560 |
shaddafathaarabic: 0xFC60, |
| 25561 |
shaddakasraarabic: 0xFC62, |
| 25562 |
shaddakasratanarabic: 0xFC5F, |
| 25563 |
shade: 0x2592, |
| 25564 |
shadedark: 0x2593, |
| 25565 |
shadelight: 0x2591, |
| 25566 |
shademedium: 0x2592, |
| 25567 |
shadeva: 0x0936, |
| 25568 |
shagujarati: 0x0AB6, |
| 25569 |
shagurmukhi: 0x0A36, |
| 25570 |
shalshelethebrew: 0x0593, |
| 25571 |
shbopomofo: 0x3115, |
| 25572 |
shchacyrillic: 0x0449, |
| 25573 |
sheenarabic: 0x0634, |
| 25574 |
sheenfinalarabic: 0xFEB6, |
| 25575 |
sheeninitialarabic: 0xFEB7, |
| 25576 |
sheenmedialarabic: 0xFEB8, |
| 25577 |
sheicoptic: 0x03E3, |
| 25578 |
sheqel: 0x20AA, |
| 25579 |
sheqelhebrew: 0x20AA, |
| 25580 |
sheva: 0x05B0, |
| 25581 |
sheva115: 0x05B0, |
| 25582 |
sheva15: 0x05B0, |
| 25583 |
sheva22: 0x05B0, |
| 25584 |
sheva2e: 0x05B0, |
| 25585 |
shevahebrew: 0x05B0, |
| 25586 |
shevanarrowhebrew: 0x05B0, |
| 25587 |
shevaquarterhebrew: 0x05B0, |
| 25588 |
shevawidehebrew: 0x05B0, |
| 25589 |
shhacyrillic: 0x04BB, |
| 25590 |
shimacoptic: 0x03ED, |
| 25591 |
shin: 0x05E9, |
| 25592 |
shindagesh: 0xFB49, |
| 25593 |
shindageshhebrew: 0xFB49, |
| 25594 |
shindageshshindot: 0xFB2C, |
| 25595 |
shindageshshindothebrew: 0xFB2C, |
| 25596 |
shindageshsindot: 0xFB2D, |
| 25597 |
shindageshsindothebrew: 0xFB2D, |
| 25598 |
shindothebrew: 0x05C1, |
| 25599 |
shinhebrew: 0x05E9, |
| 25600 |
shinshindot: 0xFB2A, |
| 25601 |
shinshindothebrew: 0xFB2A, |
| 25602 |
shinsindot: 0xFB2B, |
| 25603 |
shinsindothebrew: 0xFB2B, |
| 25604 |
shook: 0x0282, |
| 25605 |
sigma: 0x03C3, |
| 25606 |
sigma1: 0x03C2, |
| 25607 |
sigmafinal: 0x03C2, |
| 25608 |
sigmalunatesymbolgreek: 0x03F2, |
| 25609 |
sihiragana: 0x3057, |
| 25610 |
sikatakana: 0x30B7, |
| 25611 |
sikatakanahalfwidth: 0xFF7C, |
| 25612 |
siluqhebrew: 0x05BD, |
| 25613 |
siluqlefthebrew: 0x05BD, |
| 25614 |
similar: 0x223C, |
| 25615 |
sindothebrew: 0x05C2, |
| 25616 |
siosacirclekorean: 0x3274, |
| 25617 |
siosaparenkorean: 0x3214, |
| 25618 |
sioscieuckorean: 0x317E, |
| 25619 |
sioscirclekorean: 0x3266, |
| 25620 |
sioskiyeokkorean: 0x317A, |
| 25621 |
sioskorean: 0x3145, |
| 25622 |
siosnieunkorean: 0x317B, |
| 25623 |
siosparenkorean: 0x3206, |
| 25624 |
siospieupkorean: 0x317D, |
| 25625 |
siostikeutkorean: 0x317C, |
| 25626 |
six: 0x0036, |
| 25627 |
sixarabic: 0x0666, |
| 25628 |
sixbengali: 0x09EC, |
| 25629 |
sixcircle: 0x2465, |
| 25630 |
sixcircleinversesansserif: 0x278F, |
| 25631 |
sixdeva: 0x096C, |
| 25632 |
sixgujarati: 0x0AEC, |
| 25633 |
sixgurmukhi: 0x0A6C, |
| 25634 |
sixhackarabic: 0x0666, |
| 25635 |
sixhangzhou: 0x3026, |
| 25636 |
sixideographicparen: 0x3225, |
| 25637 |
sixinferior: 0x2086, |
| 25638 |
sixmonospace: 0xFF16, |
| 25639 |
sixoldstyle: 0xF736, |
| 25640 |
sixparen: 0x2479, |
| 25641 |
sixperiod: 0x248D, |
| 25642 |
sixpersian: 0x06F6, |
| 25643 |
sixroman: 0x2175, |
| 25644 |
sixsuperior: 0x2076, |
| 25645 |
sixteencircle: 0x246F, |
| 25646 |
sixteencurrencydenominatorbengali: 0x09F9, |
| 25647 |
sixteenparen: 0x2483, |
| 25648 |
sixteenperiod: 0x2497, |
| 25649 |
sixthai: 0x0E56, |
| 25650 |
slash: 0x002F, |
| 25651 |
slashmonospace: 0xFF0F, |
| 25652 |
slong: 0x017F, |
| 25653 |
slongdotaccent: 0x1E9B, |
| 25654 |
smileface: 0x263A, |
| 25655 |
smonospace: 0xFF53, |
| 25656 |
sofpasuqhebrew: 0x05C3, |
| 25657 |
softhyphen: 0x00AD, |
| 25658 |
softsigncyrillic: 0x044C, |
| 25659 |
sohiragana: 0x305D, |
| 25660 |
sokatakana: 0x30BD, |
| 25661 |
sokatakanahalfwidth: 0xFF7F, |
| 25662 |
soliduslongoverlaycmb: 0x0338, |
| 25663 |
solidusshortoverlaycmb: 0x0337, |
| 25664 |
sorusithai: 0x0E29, |
| 25665 |
sosalathai: 0x0E28, |
| 25666 |
sosothai: 0x0E0B, |
| 25667 |
sosuathai: 0x0E2A, |
| 25668 |
space: 0x0020, |
| 25669 |
spacehackarabic: 0x0020, |
| 25670 |
spade: 0x2660, |
| 25671 |
spadesuitblack: 0x2660, |
| 25672 |
spadesuitwhite: 0x2664, |
| 25673 |
sparen: 0x24AE, |
| 25674 |
squarebelowcmb: 0x033B, |
| 25675 |
squarecc: 0x33C4, |
| 25676 |
squarecm: 0x339D, |
| 25677 |
squarediagonalcrosshatchfill: 0x25A9, |
| 25678 |
squarehorizontalfill: 0x25A4, |
| 25679 |
squarekg: 0x338F, |
| 25680 |
squarekm: 0x339E, |
| 25681 |
squarekmcapital: 0x33CE, |
| 25682 |
squareln: 0x33D1, |
| 25683 |
squarelog: 0x33D2, |
| 25684 |
squaremg: 0x338E, |
| 25685 |
squaremil: 0x33D5, |
| 25686 |
squaremm: 0x339C, |
| 25687 |
squaremsquared: 0x33A1, |
| 25688 |
squareorthogonalcrosshatchfill: 0x25A6, |
| 25689 |
squareupperlefttolowerrightfill: 0x25A7, |
| 25690 |
squareupperrighttolowerleftfill: 0x25A8, |
| 25691 |
squareverticalfill: 0x25A5, |
| 25692 |
squarewhitewithsmallblack: 0x25A3, |
| 25693 |
srsquare: 0x33DB, |
| 25694 |
ssabengali: 0x09B7, |
| 25695 |
ssadeva: 0x0937, |
| 25696 |
ssagujarati: 0x0AB7, |
| 25697 |
ssangcieuckorean: 0x3149, |
| 25698 |
ssanghieuhkorean: 0x3185, |
| 25699 |
ssangieungkorean: 0x3180, |
| 25700 |
ssangkiyeokkorean: 0x3132, |
| 25701 |
ssangnieunkorean: 0x3165, |
| 25702 |
ssangpieupkorean: 0x3143, |
| 25703 |
ssangsioskorean: 0x3146, |
| 25704 |
ssangtikeutkorean: 0x3138, |
| 25705 |
ssuperior: 0xF6F2, |
| 25706 |
sterling: 0x00A3, |
| 25707 |
sterlingmonospace: 0xFFE1, |
| 25708 |
strokelongoverlaycmb: 0x0336, |
| 25709 |
strokeshortoverlaycmb: 0x0335, |
| 25710 |
subset: 0x2282, |
| 25711 |
subsetnotequal: 0x228A, |
| 25712 |
subsetorequal: 0x2286, |
| 25713 |
succeeds: 0x227B, |
| 25714 |
suchthat: 0x220B, |
| 25715 |
suhiragana: 0x3059, |
| 25716 |
sukatakana: 0x30B9, |
| 25717 |
sukatakanahalfwidth: 0xFF7D, |
| 25718 |
sukunarabic: 0x0652, |
| 25719 |
summation: 0x2211, |
| 25720 |
sun: 0x263C, |
| 25721 |
superset: 0x2283, |
| 25722 |
supersetnotequal: 0x228B, |
| 25723 |
supersetorequal: 0x2287, |
| 25724 |
svsquare: 0x33DC, |
| 25725 |
syouwaerasquare: 0x337C, |
| 25726 |
t: 0x0074, |
| 25727 |
tabengali: 0x09A4, |
| 25728 |
tackdown: 0x22A4, |
| 25729 |
tackleft: 0x22A3, |
| 25730 |
tadeva: 0x0924, |
| 25731 |
tagujarati: 0x0AA4, |
| 25732 |
tagurmukhi: 0x0A24, |
| 25733 |
taharabic: 0x0637, |
| 25734 |
tahfinalarabic: 0xFEC2, |
| 25735 |
tahinitialarabic: 0xFEC3, |
| 25736 |
tahiragana: 0x305F, |
| 25737 |
tahmedialarabic: 0xFEC4, |
| 25738 |
taisyouerasquare: 0x337D, |
| 25739 |
takatakana: 0x30BF, |
| 25740 |
takatakanahalfwidth: 0xFF80, |
| 25741 |
tatweelarabic: 0x0640, |
| 25742 |
tau: 0x03C4, |
| 25743 |
tav: 0x05EA, |
| 25744 |
tavdages: 0xFB4A, |
| 25745 |
tavdagesh: 0xFB4A, |
| 25746 |
tavdageshhebrew: 0xFB4A, |
| 25747 |
tavhebrew: 0x05EA, |
| 25748 |
tbar: 0x0167, |
| 25749 |
tbopomofo: 0x310A, |
| 25750 |
tcaron: 0x0165, |
| 25751 |
tccurl: 0x02A8, |
| 25752 |
tcedilla: 0x0163, |
| 25753 |
tcheharabic: 0x0686, |
| 25754 |
tchehfinalarabic: 0xFB7B, |
| 25755 |
tchehinitialarabic: 0xFB7C, |
| 25756 |
tchehmedialarabic: 0xFB7D, |
| 25757 |
tcircle: 0x24E3, |
| 25758 |
tcircumflexbelow: 0x1E71, |
| 25759 |
tcommaaccent: 0x0163, |
| 25760 |
tdieresis: 0x1E97, |
| 25761 |
tdotaccent: 0x1E6B, |
| 25762 |
tdotbelow: 0x1E6D, |
| 25763 |
tecyrillic: 0x0442, |
| 25764 |
tedescendercyrillic: 0x04AD, |
| 25765 |
teharabic: 0x062A, |
| 25766 |
tehfinalarabic: 0xFE96, |
| 25767 |
tehhahinitialarabic: 0xFCA2, |
| 25768 |
tehhahisolatedarabic: 0xFC0C, |
| 25769 |
tehinitialarabic: 0xFE97, |
| 25770 |
tehiragana: 0x3066, |
| 25771 |
tehjeeminitialarabic: 0xFCA1, |
| 25772 |
tehjeemisolatedarabic: 0xFC0B, |
| 25773 |
tehmarbutaarabic: 0x0629, |
| 25774 |
tehmarbutafinalarabic: 0xFE94, |
| 25775 |
tehmedialarabic: 0xFE98, |
| 25776 |
tehmeeminitialarabic: 0xFCA4, |
| 25777 |
tehmeemisolatedarabic: 0xFC0E, |
| 25778 |
tehnoonfinalarabic: 0xFC73, |
| 25779 |
tekatakana: 0x30C6, |
| 25780 |
tekatakanahalfwidth: 0xFF83, |
| 25781 |
telephone: 0x2121, |
| 25782 |
telephoneblack: 0x260E, |
| 25783 |
telishagedolahebrew: 0x05A0, |
| 25784 |
telishaqetanahebrew: 0x05A9, |
| 25785 |
tencircle: 0x2469, |
| 25786 |
tenideographicparen: 0x3229, |
| 25787 |
tenparen: 0x247D, |
| 25788 |
tenperiod: 0x2491, |
| 25789 |
tenroman: 0x2179, |
| 25790 |
tesh: 0x02A7, |
| 25791 |
tet: 0x05D8, |
| 25792 |
tetdagesh: 0xFB38, |
| 25793 |
tetdageshhebrew: 0xFB38, |
| 25794 |
tethebrew: 0x05D8, |
| 25795 |
tetsecyrillic: 0x04B5, |
| 25796 |
tevirhebrew: 0x059B, |
| 25797 |
tevirlefthebrew: 0x059B, |
| 25798 |
thabengali: 0x09A5, |
| 25799 |
thadeva: 0x0925, |
| 25800 |
thagujarati: 0x0AA5, |
| 25801 |
thagurmukhi: 0x0A25, |
| 25802 |
thalarabic: 0x0630, |
| 25803 |
thalfinalarabic: 0xFEAC, |
| 25804 |
thanthakhatlowleftthai: 0xF898, |
| 25805 |
thanthakhatlowrightthai: 0xF897, |
| 25806 |
thanthakhatthai: 0x0E4C, |
| 25807 |
thanthakhatupperleftthai: 0xF896, |
| 25808 |
theharabic: 0x062B, |
| 25809 |
thehfinalarabic: 0xFE9A, |
| 25810 |
thehinitialarabic: 0xFE9B, |
| 25811 |
thehmedialarabic: 0xFE9C, |
| 25812 |
thereexists: 0x2203, |
| 25813 |
therefore: 0x2234, |
| 25814 |
theta: 0x03B8, |
| 25815 |
theta1: 0x03D1, |
| 25816 |
thetasymbolgreek: 0x03D1, |
| 25817 |
thieuthacirclekorean: 0x3279, |
| 25818 |
thieuthaparenkorean: 0x3219, |
| 25819 |
thieuthcirclekorean: 0x326B, |
| 25820 |
thieuthkorean: 0x314C, |
| 25821 |
thieuthparenkorean: 0x320B, |
| 25822 |
thirteencircle: 0x246C, |
| 25823 |
thirteenparen: 0x2480, |
| 25824 |
thirteenperiod: 0x2494, |
| 25825 |
thonangmonthothai: 0x0E11, |
| 25826 |
thook: 0x01AD, |
| 25827 |
thophuthaothai: 0x0E12, |
| 25828 |
thorn: 0x00FE, |
| 25829 |
thothahanthai: 0x0E17, |
| 25830 |
thothanthai: 0x0E10, |
| 25831 |
thothongthai: 0x0E18, |
| 25832 |
thothungthai: 0x0E16, |
| 25833 |
thousandcyrillic: 0x0482, |
| 25834 |
thousandsseparatorarabic: 0x066C, |
| 25835 |
thousandsseparatorpersian: 0x066C, |
| 25836 |
three: 0x0033, |
| 25837 |
threearabic: 0x0663, |
| 25838 |
threebengali: 0x09E9, |
| 25839 |
threecircle: 0x2462, |
| 25840 |
threecircleinversesansserif: 0x278C, |
| 25841 |
threedeva: 0x0969, |
| 25842 |
threeeighths: 0x215C, |
| 25843 |
threegujarati: 0x0AE9, |
| 25844 |
threegurmukhi: 0x0A69, |
| 25845 |
threehackarabic: 0x0663, |
| 25846 |
threehangzhou: 0x3023, |
| 25847 |
threeideographicparen: 0x3222, |
| 25848 |
threeinferior: 0x2083, |
| 25849 |
threemonospace: 0xFF13, |
| 25850 |
threenumeratorbengali: 0x09F6, |
| 25851 |
threeoldstyle: 0xF733, |
| 25852 |
threeparen: 0x2476, |
| 25853 |
threeperiod: 0x248A, |
| 25854 |
threepersian: 0x06F3, |
| 25855 |
threequarters: 0x00BE, |
| 25856 |
threequartersemdash: 0xF6DE, |
| 25857 |
threeroman: 0x2172, |
| 25858 |
threesuperior: 0x00B3, |
| 25859 |
threethai: 0x0E53, |
| 25860 |
thzsquare: 0x3394, |
| 25861 |
tihiragana: 0x3061, |
| 25862 |
tikatakana: 0x30C1, |
| 25863 |
tikatakanahalfwidth: 0xFF81, |
| 25864 |
tikeutacirclekorean: 0x3270, |
| 25865 |
tikeutaparenkorean: 0x3210, |
| 25866 |
tikeutcirclekorean: 0x3262, |
| 25867 |
tikeutkorean: 0x3137, |
| 25868 |
tikeutparenkorean: 0x3202, |
| 25869 |
tilde: 0x02DC, |
| 25870 |
tildebelowcmb: 0x0330, |
| 25871 |
tildecmb: 0x0303, |
| 25872 |
tildecomb: 0x0303, |
| 25873 |
tildedoublecmb: 0x0360, |
| 25874 |
tildeoperator: 0x223C, |
| 25875 |
tildeoverlaycmb: 0x0334, |
| 25876 |
tildeverticalcmb: 0x033E, |
| 25877 |
timescircle: 0x2297, |
| 25878 |
tipehahebrew: 0x0596, |
| 25879 |
tipehalefthebrew: 0x0596, |
| 25880 |
tippigurmukhi: 0x0A70, |
| 25881 |
titlocyrilliccmb: 0x0483, |
| 25882 |
tiwnarmenian: 0x057F, |
| 25883 |
tlinebelow: 0x1E6F, |
| 25884 |
tmonospace: 0xFF54, |
| 25885 |
toarmenian: 0x0569, |
| 25886 |
tohiragana: 0x3068, |
| 25887 |
tokatakana: 0x30C8, |
| 25888 |
tokatakanahalfwidth: 0xFF84, |
| 25889 |
tonebarextrahighmod: 0x02E5, |
| 25890 |
tonebarextralowmod: 0x02E9, |
| 25891 |
tonebarhighmod: 0x02E6, |
| 25892 |
tonebarlowmod: 0x02E8, |
| 25893 |
tonebarmidmod: 0x02E7, |
| 25894 |
tonefive: 0x01BD, |
| 25895 |
tonesix: 0x0185, |
| 25896 |
tonetwo: 0x01A8, |
| 25897 |
tonos: 0x0384, |
| 25898 |
tonsquare: 0x3327, |
| 25899 |
topatakthai: 0x0E0F, |
| 25900 |
tortoiseshellbracketleft: 0x3014, |
| 25901 |
tortoiseshellbracketleftsmall: 0xFE5D, |
| 25902 |
tortoiseshellbracketleftvertical: 0xFE39, |
| 25903 |
tortoiseshellbracketright: 0x3015, |
| 25904 |
tortoiseshellbracketrightsmall: 0xFE5E, |
| 25905 |
tortoiseshellbracketrightvertical: 0xFE3A, |
| 25906 |
totaothai: 0x0E15, |
| 25907 |
tpalatalhook: 0x01AB, |
| 25908 |
tparen: 0x24AF, |
| 25909 |
trademark: 0x2122, |
| 25910 |
trademarksans: 0xF8EA, |
| 25911 |
trademarkserif: 0xF6DB, |
| 25912 |
tretroflexhook: 0x0288, |
| 25913 |
triagdn: 0x25BC, |
| 25914 |
triaglf: 0x25C4, |
| 25915 |
triagrt: 0x25BA, |
| 25916 |
triagup: 0x25B2, |
| 25917 |
ts: 0x02A6, |
| 25918 |
tsadi: 0x05E6, |
| 25919 |
tsadidagesh: 0xFB46, |
| 25920 |
tsadidageshhebrew: 0xFB46, |
| 25921 |
tsadihebrew: 0x05E6, |
| 25922 |
tsecyrillic: 0x0446, |
| 25923 |
tsere: 0x05B5, |
| 25924 |
tsere12: 0x05B5, |
| 25925 |
tsere1e: 0x05B5, |
| 25926 |
tsere2b: 0x05B5, |
| 25927 |
tserehebrew: 0x05B5, |
| 25928 |
tserenarrowhebrew: 0x05B5, |
| 25929 |
tserequarterhebrew: 0x05B5, |
| 25930 |
tserewidehebrew: 0x05B5, |
| 25931 |
tshecyrillic: 0x045B, |
| 25932 |
tsuperior: 0xF6F3, |
| 25933 |
ttabengali: 0x099F, |
| 25934 |
ttadeva: 0x091F, |
| 25935 |
ttagujarati: 0x0A9F, |
| 25936 |
ttagurmukhi: 0x0A1F, |
| 25937 |
tteharabic: 0x0679, |
| 25938 |
ttehfinalarabic: 0xFB67, |
| 25939 |
ttehinitialarabic: 0xFB68, |
| 25940 |
ttehmedialarabic: 0xFB69, |
| 25941 |
tthabengali: 0x09A0, |
| 25942 |
tthadeva: 0x0920, |
| 25943 |
tthagujarati: 0x0AA0, |
| 25944 |
tthagurmukhi: 0x0A20, |
| 25945 |
tturned: 0x0287, |
| 25946 |
tuhiragana: 0x3064, |
| 25947 |
tukatakana: 0x30C4, |
| 25948 |
tukatakanahalfwidth: 0xFF82, |
| 25949 |
tusmallhiragana: 0x3063, |
| 25950 |
tusmallkatakana: 0x30C3, |
| 25951 |
tusmallkatakanahalfwidth: 0xFF6F, |
| 25952 |
twelvecircle: 0x246B, |
| 25953 |
twelveparen: 0x247F, |
| 25954 |
twelveperiod: 0x2493, |
| 25955 |
twelveroman: 0x217B, |
| 25956 |
twentycircle: 0x2473, |
| 25957 |
twentyhangzhou: 0x5344, |
| 25958 |
twentyparen: 0x2487, |
| 25959 |
twentyperiod: 0x249B, |
| 25960 |
two: 0x0032, |
| 25961 |
twoarabic: 0x0662, |
| 25962 |
twobengali: 0x09E8, |
| 25963 |
twocircle: 0x2461, |
| 25964 |
twocircleinversesansserif: 0x278B, |
| 25965 |
twodeva: 0x0968, |
| 25966 |
twodotenleader: 0x2025, |
| 25967 |
twodotleader: 0x2025, |
| 25968 |
twodotleadervertical: 0xFE30, |
| 25969 |
twogujarati: 0x0AE8, |
| 25970 |
twogurmukhi: 0x0A68, |
| 25971 |
twohackarabic: 0x0662, |
| 25972 |
twohangzhou: 0x3022, |
| 25973 |
twoideographicparen: 0x3221, |
| 25974 |
twoinferior: 0x2082, |
| 25975 |
twomonospace: 0xFF12, |
| 25976 |
twonumeratorbengali: 0x09F5, |
| 25977 |
twooldstyle: 0xF732, |
| 25978 |
twoparen: 0x2475, |
| 25979 |
twoperiod: 0x2489, |
| 25980 |
twopersian: 0x06F2, |
| 25981 |
tworoman: 0x2171, |
| 25982 |
twostroke: 0x01BB, |
| 25983 |
twosuperior: 0x00B2, |
| 25984 |
twothai: 0x0E52, |
| 25985 |
twothirds: 0x2154, |
| 25986 |
u: 0x0075, |
| 25987 |
uacute: 0x00FA, |
| 25988 |
ubar: 0x0289, |
| 25989 |
ubengali: 0x0989, |
| 25990 |
ubopomofo: 0x3128, |
| 25991 |
ubreve: 0x016D, |
| 25992 |
ucaron: 0x01D4, |
| 25993 |
ucircle: 0x24E4, |
| 25994 |
ucircumflex: 0x00FB, |
| 25995 |
ucircumflexbelow: 0x1E77, |
| 25996 |
ucyrillic: 0x0443, |
| 25997 |
udattadeva: 0x0951, |
| 25998 |
udblacute: 0x0171, |
| 25999 |
udblgrave: 0x0215, |
| 26000 |
udeva: 0x0909, |
| 26001 |
udieresis: 0x00FC, |
| 26002 |
udieresisacute: 0x01D8, |
| 26003 |
udieresisbelow: 0x1E73, |
| 26004 |
udieresiscaron: 0x01DA, |
| 26005 |
udieresiscyrillic: 0x04F1, |
| 26006 |
udieresisgrave: 0x01DC, |
| 26007 |
udieresismacron: 0x01D6, |
| 26008 |
udotbelow: 0x1EE5, |
| 26009 |
ugrave: 0x00F9, |
| 26010 |
ugujarati: 0x0A89, |
| 26011 |
ugurmukhi: 0x0A09, |
| 26012 |
uhiragana: 0x3046, |
| 26013 |
uhookabove: 0x1EE7, |
| 26014 |
uhorn: 0x01B0, |
| 26015 |
uhornacute: 0x1EE9, |
| 26016 |
uhorndotbelow: 0x1EF1, |
| 26017 |
uhorngrave: 0x1EEB, |
| 26018 |
uhornhookabove: 0x1EED, |
| 26019 |
uhorntilde: 0x1EEF, |
| 26020 |
uhungarumlaut: 0x0171, |
| 26021 |
uhungarumlautcyrillic: 0x04F3, |
| 26022 |
uinvertedbreve: 0x0217, |
| 26023 |
ukatakana: 0x30A6, |
| 26024 |
ukatakanahalfwidth: 0xFF73, |
| 26025 |
ukcyrillic: 0x0479, |
| 26026 |
ukorean: 0x315C, |
| 26027 |
umacron: 0x016B, |
| 26028 |
umacroncyrillic: 0x04EF, |
| 26029 |
umacrondieresis: 0x1E7B, |
| 26030 |
umatragurmukhi: 0x0A41, |
| 26031 |
umonospace: 0xFF55, |
| 26032 |
underscore: 0x005F, |
| 26033 |
underscoredbl: 0x2017, |
| 26034 |
underscoremonospace: 0xFF3F, |
| 26035 |
underscorevertical: 0xFE33, |
| 26036 |
underscorewavy: 0xFE4F, |
| 26037 |
union: 0x222A, |
| 26038 |
universal: 0x2200, |
| 26039 |
uogonek: 0x0173, |
| 26040 |
uparen: 0x24B0, |
| 26041 |
upblock: 0x2580, |
| 26042 |
upperdothebrew: 0x05C4, |
| 26043 |
upsilon: 0x03C5, |
| 26044 |
upsilondieresis: 0x03CB, |
| 26045 |
upsilondieresistonos: 0x03B0, |
| 26046 |
upsilonlatin: 0x028A, |
| 26047 |
upsilontonos: 0x03CD, |
| 26048 |
uptackbelowcmb: 0x031D, |
| 26049 |
uptackmod: 0x02D4, |
| 26050 |
uragurmukhi: 0x0A73, |
| 26051 |
uring: 0x016F, |
| 26052 |
ushortcyrillic: 0x045E, |
| 26053 |
usmallhiragana: 0x3045, |
| 26054 |
usmallkatakana: 0x30A5, |
| 26055 |
usmallkatakanahalfwidth: 0xFF69, |
| 26056 |
ustraightcyrillic: 0x04AF, |
| 26057 |
ustraightstrokecyrillic: 0x04B1, |
| 26058 |
utilde: 0x0169, |
| 26059 |
utildeacute: 0x1E79, |
| 26060 |
utildebelow: 0x1E75, |
| 26061 |
uubengali: 0x098A, |
| 26062 |
uudeva: 0x090A, |
| 26063 |
uugujarati: 0x0A8A, |
| 26064 |
uugurmukhi: 0x0A0A, |
| 26065 |
uumatragurmukhi: 0x0A42, |
| 26066 |
uuvowelsignbengali: 0x09C2, |
| 26067 |
uuvowelsigndeva: 0x0942, |
| 26068 |
uuvowelsigngujarati: 0x0AC2, |
| 26069 |
uvowelsignbengali: 0x09C1, |
| 26070 |
uvowelsigndeva: 0x0941, |
| 26071 |
uvowelsigngujarati: 0x0AC1, |
| 26072 |
v: 0x0076, |
| 26073 |
vadeva: 0x0935, |
| 26074 |
vagujarati: 0x0AB5, |
| 26075 |
vagurmukhi: 0x0A35, |
| 26076 |
vakatakana: 0x30F7, |
| 26077 |
vav: 0x05D5, |
| 26078 |
vavdagesh: 0xFB35, |
| 26079 |
vavdagesh65: 0xFB35, |
| 26080 |
vavdageshhebrew: 0xFB35, |
| 26081 |
vavhebrew: 0x05D5, |
| 26082 |
vavholam: 0xFB4B, |
| 26083 |
vavholamhebrew: 0xFB4B, |
| 26084 |
vavvavhebrew: 0x05F0, |
| 26085 |
vavyodhebrew: 0x05F1, |
| 26086 |
vcircle: 0x24E5, |
| 26087 |
vdotbelow: 0x1E7F, |
| 26088 |
vecyrillic: 0x0432, |
| 26089 |
veharabic: 0x06A4, |
| 26090 |
vehfinalarabic: 0xFB6B, |
| 26091 |
vehinitialarabic: 0xFB6C, |
| 26092 |
vehmedialarabic: 0xFB6D, |
| 26093 |
vekatakana: 0x30F9, |
| 26094 |
venus: 0x2640, |
| 26095 |
verticalbar: 0x007C, |
| 26096 |
verticallineabovecmb: 0x030D, |
| 26097 |
verticallinebelowcmb: 0x0329, |
| 26098 |
verticallinelowmod: 0x02CC, |
| 26099 |
verticallinemod: 0x02C8, |
| 26100 |
vewarmenian: 0x057E, |
| 26101 |
vhook: 0x028B, |
| 26102 |
vikatakana: 0x30F8, |
| 26103 |
viramabengali: 0x09CD, |
| 26104 |
viramadeva: 0x094D, |
| 26105 |
viramagujarati: 0x0ACD, |
| 26106 |
visargabengali: 0x0983, |
| 26107 |
visargadeva: 0x0903, |
| 26108 |
visargagujarati: 0x0A83, |
| 26109 |
vmonospace: 0xFF56, |
| 26110 |
voarmenian: 0x0578, |
| 26111 |
voicediterationhiragana: 0x309E, |
| 26112 |
voicediterationkatakana: 0x30FE, |
| 26113 |
voicedmarkkana: 0x309B, |
| 26114 |
voicedmarkkanahalfwidth: 0xFF9E, |
| 26115 |
vokatakana: 0x30FA, |
| 26116 |
vparen: 0x24B1, |
| 26117 |
vtilde: 0x1E7D, |
| 26118 |
vturned: 0x028C, |
| 26119 |
vuhiragana: 0x3094, |
| 26120 |
vukatakana: 0x30F4, |
| 26121 |
w: 0x0077, |
| 26122 |
wacute: 0x1E83, |
| 26123 |
waekorean: 0x3159, |
| 26124 |
wahiragana: 0x308F, |
| 26125 |
wakatakana: 0x30EF, |
| 26126 |
wakatakanahalfwidth: 0xFF9C, |
| 26127 |
wakorean: 0x3158, |
| 26128 |
wasmallhiragana: 0x308E, |
| 26129 |
wasmallkatakana: 0x30EE, |
| 26130 |
wattosquare: 0x3357, |
| 26131 |
wavedash: 0x301C, |
| 26132 |
wavyunderscorevertical: 0xFE34, |
| 26133 |
wawarabic: 0x0648, |
| 26134 |
wawfinalarabic: 0xFEEE, |
| 26135 |
wawhamzaabovearabic: 0x0624, |
| 26136 |
wawhamzaabovefinalarabic: 0xFE86, |
| 26137 |
wbsquare: 0x33DD, |
| 26138 |
wcircle: 0x24E6, |
| 26139 |
wcircumflex: 0x0175, |
| 26140 |
wdieresis: 0x1E85, |
| 26141 |
wdotaccent: 0x1E87, |
| 26142 |
wdotbelow: 0x1E89, |
| 26143 |
wehiragana: 0x3091, |
| 26144 |
weierstrass: 0x2118, |
| 26145 |
wekatakana: 0x30F1, |
| 26146 |
wekorean: 0x315E, |
| 26147 |
weokorean: 0x315D, |
| 26148 |
wgrave: 0x1E81, |
| 26149 |
whitebullet: 0x25E6, |
| 26150 |
whitecircle: 0x25CB, |
| 26151 |
whitecircleinverse: 0x25D9, |
| 26152 |
whitecornerbracketleft: 0x300E, |
| 26153 |
whitecornerbracketleftvertical: 0xFE43, |
| 26154 |
whitecornerbracketright: 0x300F, |
| 26155 |
whitecornerbracketrightvertical: 0xFE44, |
| 26156 |
whitediamond: 0x25C7, |
| 26157 |
whitediamondcontainingblacksmalldiamond: 0x25C8, |
| 26158 |
whitedownpointingsmalltriangle: 0x25BF, |
| 26159 |
whitedownpointingtriangle: 0x25BD, |
| 26160 |
whiteleftpointingsmalltriangle: 0x25C3, |
| 26161 |
whiteleftpointingtriangle: 0x25C1, |
| 26162 |
whitelenticularbracketleft: 0x3016, |
| 26163 |
whitelenticularbracketright: 0x3017, |
| 26164 |
whiterightpointingsmalltriangle: 0x25B9, |
| 26165 |
whiterightpointingtriangle: 0x25B7, |
| 26166 |
whitesmallsquare: 0x25AB, |
| 26167 |
whitesmilingface: 0x263A, |
| 26168 |
whitesquare: 0x25A1, |
| 26169 |
whitestar: 0x2606, |
| 26170 |
whitetelephone: 0x260F, |
| 26171 |
whitetortoiseshellbracketleft: 0x3018, |
| 26172 |
whitetortoiseshellbracketright: 0x3019, |
| 26173 |
whiteuppointingsmalltriangle: 0x25B5, |
| 26174 |
whiteuppointingtriangle: 0x25B3, |
| 26175 |
wihiragana: 0x3090, |
| 26176 |
wikatakana: 0x30F0, |
| 26177 |
wikorean: 0x315F, |
| 26178 |
wmonospace: 0xFF57, |
| 26179 |
wohiragana: 0x3092, |
| 26180 |
wokatakana: 0x30F2, |
| 26181 |
wokatakanahalfwidth: 0xFF66, |
| 26182 |
won: 0x20A9, |
| 26183 |
wonmonospace: 0xFFE6, |
| 26184 |
wowaenthai: 0x0E27, |
| 26185 |
wparen: 0x24B2, |
| 26186 |
wring: 0x1E98, |
| 26187 |
wsuperior: 0x02B7, |
| 26188 |
wturned: 0x028D, |
| 26189 |
wynn: 0x01BF, |
| 26190 |
x: 0x0078, |
| 26191 |
xabovecmb: 0x033D, |
| 26192 |
xbopomofo: 0x3112, |
| 26193 |
xcircle: 0x24E7, |
| 26194 |
xdieresis: 0x1E8D, |
| 26195 |
xdotaccent: 0x1E8B, |
| 26196 |
xeharmenian: 0x056D, |
| 26197 |
xi: 0x03BE, |
| 26198 |
xmonospace: 0xFF58, |
| 26199 |
xparen: 0x24B3, |
| 26200 |
xsuperior: 0x02E3, |
| 26201 |
y: 0x0079, |
| 26202 |
yaadosquare: 0x334E, |
| 26203 |
yabengali: 0x09AF, |
| 26204 |
yacute: 0x00FD, |
| 26205 |
yadeva: 0x092F, |
| 26206 |
yaekorean: 0x3152, |
| 26207 |
yagujarati: 0x0AAF, |
| 26208 |
yagurmukhi: 0x0A2F, |
| 26209 |
yahiragana: 0x3084, |
| 26210 |
yakatakana: 0x30E4, |
| 26211 |
yakatakanahalfwidth: 0xFF94, |
| 26212 |
yakorean: 0x3151, |
| 26213 |
yamakkanthai: 0x0E4E, |
| 26214 |
yasmallhiragana: 0x3083, |
| 26215 |
yasmallkatakana: 0x30E3, |
| 26216 |
yasmallkatakanahalfwidth: 0xFF6C, |
| 26217 |
yatcyrillic: 0x0463, |
| 26218 |
ycircle: 0x24E8, |
| 26219 |
ycircumflex: 0x0177, |
| 26220 |
ydieresis: 0x00FF, |
| 26221 |
ydotaccent: 0x1E8F, |
| 26222 |
ydotbelow: 0x1EF5, |
| 26223 |
yeharabic: 0x064A, |
| 26224 |
yehbarreearabic: 0x06D2, |
| 26225 |
yehbarreefinalarabic: 0xFBAF, |
| 26226 |
yehfinalarabic: 0xFEF2, |
| 26227 |
yehhamzaabovearabic: 0x0626, |
| 26228 |
yehhamzaabovefinalarabic: 0xFE8A, |
| 26229 |
yehhamzaaboveinitialarabic: 0xFE8B, |
| 26230 |
yehhamzaabovemedialarabic: 0xFE8C, |
| 26231 |
yehinitialarabic: 0xFEF3, |
| 26232 |
yehmedialarabic: 0xFEF4, |
| 26233 |
yehmeeminitialarabic: 0xFCDD, |
| 26234 |
yehmeemisolatedarabic: 0xFC58, |
| 26235 |
yehnoonfinalarabic: 0xFC94, |
| 26236 |
yehthreedotsbelowarabic: 0x06D1, |
| 26237 |
yekorean: 0x3156, |
| 26238 |
yen: 0x00A5, |
| 26239 |
yenmonospace: 0xFFE5, |
| 26240 |
yeokorean: 0x3155, |
| 26241 |
yeorinhieuhkorean: 0x3186, |
| 26242 |
yerahbenyomohebrew: 0x05AA, |
| 26243 |
yerahbenyomolefthebrew: 0x05AA, |
| 26244 |
yericyrillic: 0x044B, |
| 26245 |
yerudieresiscyrillic: 0x04F9, |
| 26246 |
yesieungkorean: 0x3181, |
| 26247 |
yesieungpansioskorean: 0x3183, |
| 26248 |
yesieungsioskorean: 0x3182, |
| 26249 |
yetivhebrew: 0x059A, |
| 26250 |
ygrave: 0x1EF3, |
| 26251 |
yhook: 0x01B4, |
| 26252 |
yhookabove: 0x1EF7, |
| 26253 |
yiarmenian: 0x0575, |
| 26254 |
yicyrillic: 0x0457, |
| 26255 |
yikorean: 0x3162, |
| 26256 |
yinyang: 0x262F, |
| 26257 |
yiwnarmenian: 0x0582, |
| 26258 |
ymonospace: 0xFF59, |
| 26259 |
yod: 0x05D9, |
| 26260 |
yoddagesh: 0xFB39, |
| 26261 |
yoddageshhebrew: 0xFB39, |
| 26262 |
yodhebrew: 0x05D9, |
| 26263 |
yodyodhebrew: 0x05F2, |
| 26264 |
yodyodpatahhebrew: 0xFB1F, |
| 26265 |
yohiragana: 0x3088, |
| 26266 |
yoikorean: 0x3189, |
| 26267 |
yokatakana: 0x30E8, |
| 26268 |
yokatakanahalfwidth: 0xFF96, |
| 26269 |
yokorean: 0x315B, |
| 26270 |
yosmallhiragana: 0x3087, |
| 26271 |
yosmallkatakana: 0x30E7, |
| 26272 |
yosmallkatakanahalfwidth: 0xFF6E, |
| 26273 |
yotgreek: 0x03F3, |
| 26274 |
yoyaekorean: 0x3188, |
| 26275 |
yoyakorean: 0x3187, |
| 26276 |
yoyakthai: 0x0E22, |
| 26277 |
yoyingthai: 0x0E0D, |
| 26278 |
yparen: 0x24B4, |
| 26279 |
ypogegrammeni: 0x037A, |
| 26280 |
ypogegrammenigreekcmb: 0x0345, |
| 26281 |
yr: 0x01A6, |
| 26282 |
yring: 0x1E99, |
| 26283 |
ysuperior: 0x02B8, |
| 26284 |
ytilde: 0x1EF9, |
| 26285 |
yturned: 0x028E, |
| 26286 |
yuhiragana: 0x3086, |
| 26287 |
yuikorean: 0x318C, |
| 26288 |
yukatakana: 0x30E6, |
| 26289 |
yukatakanahalfwidth: 0xFF95, |
| 26290 |
yukorean: 0x3160, |
| 26291 |
yusbigcyrillic: 0x046B, |
| 26292 |
yusbigiotifiedcyrillic: 0x046D, |
| 26293 |
yuslittlecyrillic: 0x0467, |
| 26294 |
yuslittleiotifiedcyrillic: 0x0469, |
| 26295 |
yusmallhiragana: 0x3085, |
| 26296 |
yusmallkatakana: 0x30E5, |
| 26297 |
yusmallkatakanahalfwidth: 0xFF6D, |
| 26298 |
yuyekorean: 0x318B, |
| 26299 |
yuyeokorean: 0x318A, |
| 26300 |
yyabengali: 0x09DF, |
| 26301 |
yyadeva: 0x095F, |
| 26302 |
z: 0x007A, |
| 26303 |
zaarmenian: 0x0566, |
| 26304 |
zacute: 0x017A, |
| 26305 |
zadeva: 0x095B, |
| 26306 |
zagurmukhi: 0x0A5B, |
| 26307 |
zaharabic: 0x0638, |
| 26308 |
zahfinalarabic: 0xFEC6, |
| 26309 |
zahinitialarabic: 0xFEC7, |
| 26310 |
zahiragana: 0x3056, |
| 26311 |
zahmedialarabic: 0xFEC8, |
| 26312 |
zainarabic: 0x0632, |
| 26313 |
zainfinalarabic: 0xFEB0, |
| 26314 |
zakatakana: 0x30B6, |
| 26315 |
zaqefgadolhebrew: 0x0595, |
| 26316 |
zaqefqatanhebrew: 0x0594, |
| 26317 |
zarqahebrew: 0x0598, |
| 26318 |
zayin: 0x05D6, |
| 26319 |
zayindagesh: 0xFB36, |
| 26320 |
zayindageshhebrew: 0xFB36, |
| 26321 |
zayinhebrew: 0x05D6, |
| 26322 |
zbopomofo: 0x3117, |
| 26323 |
zcaron: 0x017E, |
| 26324 |
zcircle: 0x24E9, |
| 26325 |
zcircumflex: 0x1E91, |
| 26326 |
zcurl: 0x0291, |
| 26327 |
zdot: 0x017C, |
| 26328 |
zdotaccent: 0x017C, |
| 26329 |
zdotbelow: 0x1E93, |
| 26330 |
zecyrillic: 0x0437, |
| 26331 |
zedescendercyrillic: 0x0499, |
| 26332 |
zedieresiscyrillic: 0x04DF, |
| 26333 |
zehiragana: 0x305C, |
| 26334 |
zekatakana: 0x30BC, |
| 26335 |
zero: 0x0030, |
| 26336 |
zeroarabic: 0x0660, |
| 26337 |
zerobengali: 0x09E6, |
| 26338 |
zerodeva: 0x0966, |
| 26339 |
zerogujarati: 0x0AE6, |
| 26340 |
zerogurmukhi: 0x0A66, |
| 26341 |
zerohackarabic: 0x0660, |
| 26342 |
zeroinferior: 0x2080, |
| 26343 |
zeromonospace: 0xFF10, |
| 26344 |
zerooldstyle: 0xF730, |
| 26345 |
zeropersian: 0x06F0, |
| 26346 |
zerosuperior: 0x2070, |
| 26347 |
zerothai: 0x0E50, |
| 26348 |
zerowidthjoiner: 0xFEFF, |
| 26349 |
zerowidthnonjoiner: 0x200C, |
| 26350 |
zerowidthspace: 0x200B, |
| 26351 |
zeta: 0x03B6, |
| 26352 |
zhbopomofo: 0x3113, |
| 26353 |
zhearmenian: 0x056A, |
| 26354 |
zhebrevecyrillic: 0x04C2, |
| 26355 |
zhecyrillic: 0x0436, |
| 26356 |
zhedescendercyrillic: 0x0497, |
| 26357 |
zhedieresiscyrillic: 0x04DD, |
| 26358 |
zihiragana: 0x3058, |
| 26359 |
zikatakana: 0x30B8, |
| 26360 |
zinorhebrew: 0x05AE, |
| 26361 |
zlinebelow: 0x1E95, |
| 26362 |
zmonospace: 0xFF5A, |
| 26363 |
zohiragana: 0x305E, |
| 26364 |
zokatakana: 0x30BE, |
| 26365 |
zparen: 0x24B5, |
| 26366 |
zretroflexhook: 0x0290, |
| 26367 |
zstroke: 0x01B6, |
| 26368 |
zuhiragana: 0x305A, |
| 26369 |
zukatakana: 0x30BA, |
| 26370 |
'.notdef': 0x0000 |
| 26371 |
}; |
| 26372 |
|
| 26373 |
var DingbatsGlyphsUnicode = { |
| 26374 |
space: 0x0020, |
| 26375 |
a1: 0x2701, |
| 26376 |
a2: 0x2702, |
| 26377 |
a202: 0x2703, |
| 26378 |
a3: 0x2704, |
| 26379 |
a4: 0x260E, |
| 26380 |
a5: 0x2706, |
| 26381 |
a119: 0x2707, |
| 26382 |
a118: 0x2708, |
| 26383 |
a117: 0x2709, |
| 26384 |
a11: 0x261B, |
| 26385 |
a12: 0x261E, |
| 26386 |
a13: 0x270C, |
| 26387 |
a14: 0x270D, |
| 26388 |
a15: 0x270E, |
| 26389 |
a16: 0x270F, |
| 26390 |
a105: 0x2710, |
| 26391 |
a17: 0x2711, |
| 26392 |
a18: 0x2712, |
| 26393 |
a19: 0x2713, |
| 26394 |
a20: 0x2714, |
| 26395 |
a21: 0x2715, |
| 26396 |
a22: 0x2716, |
| 26397 |
a23: 0x2717, |
| 26398 |
a24: 0x2718, |
| 26399 |
a25: 0x2719, |
| 26400 |
a26: 0x271A, |
| 26401 |
a27: 0x271B, |
| 26402 |
a28: 0x271C, |
| 26403 |
a6: 0x271D, |
| 26404 |
a7: 0x271E, |
| 26405 |
a8: 0x271F, |
| 26406 |
a9: 0x2720, |
| 26407 |
a10: 0x2721, |
| 26408 |
a29: 0x2722, |
| 26409 |
a30: 0x2723, |
| 26410 |
a31: 0x2724, |
| 26411 |
a32: 0x2725, |
| 26412 |
a33: 0x2726, |
| 26413 |
a34: 0x2727, |
| 26414 |
a35: 0x2605, |
| 26415 |
a36: 0x2729, |
| 26416 |
a37: 0x272A, |
| 26417 |
a38: 0x272B, |
| 26418 |
a39: 0x272C, |
| 26419 |
a40: 0x272D, |
| 26420 |
a41: 0x272E, |
| 26421 |
a42: 0x272F, |
| 26422 |
a43: 0x2730, |
| 26423 |
a44: 0x2731, |
| 26424 |
a45: 0x2732, |
| 26425 |
a46: 0x2733, |
| 26426 |
a47: 0x2734, |
| 26427 |
a48: 0x2735, |
| 26428 |
a49: 0x2736, |
| 26429 |
a50: 0x2737, |
| 26430 |
a51: 0x2738, |
| 26431 |
a52: 0x2739, |
| 26432 |
a53: 0x273A, |
| 26433 |
a54: 0x273B, |
| 26434 |
a55: 0x273C, |
| 26435 |
a56: 0x273D, |
| 26436 |
a57: 0x273E, |
| 26437 |
a58: 0x273F, |
| 26438 |
a59: 0x2740, |
| 26439 |
a60: 0x2741, |
| 26440 |
a61: 0x2742, |
| 26441 |
a62: 0x2743, |
| 26442 |
a63: 0x2744, |
| 26443 |
a64: 0x2745, |
| 26444 |
a65: 0x2746, |
| 26445 |
a66: 0x2747, |
| 26446 |
a67: 0x2748, |
| 26447 |
a68: 0x2749, |
| 26448 |
a69: 0x274A, |
| 26449 |
a70: 0x274B, |
| 26450 |
a71: 0x25CF, |
| 26451 |
a72: 0x274D, |
| 26452 |
a73: 0x25A0, |
| 26453 |
a74: 0x274F, |
| 26454 |
a203: 0x2750, |
| 26455 |
a75: 0x2751, |
| 26456 |
a204: 0x2752, |
| 26457 |
a76: 0x25B2, |
| 26458 |
a77: 0x25BC, |
| 26459 |
a78: 0x25C6, |
| 26460 |
a79: 0x2756, |
| 26461 |
a81: 0x25D7, |
| 26462 |
a82: 0x2758, |
| 26463 |
a83: 0x2759, |
| 26464 |
a84: 0x275A, |
| 26465 |
a97: 0x275B, |
| 26466 |
a98: 0x275C, |
| 26467 |
a99: 0x275D, |
| 26468 |
a100: 0x275E, |
| 26469 |
a101: 0x2761, |
| 26470 |
a102: 0x2762, |
| 26471 |
a103: 0x2763, |
| 26472 |
a104: 0x2764, |
| 26473 |
a106: 0x2765, |
| 26474 |
a107: 0x2766, |
| 26475 |
a108: 0x2767, |
| 26476 |
a112: 0x2663, |
| 26477 |
a111: 0x2666, |
| 26478 |
a110: 0x2665, |
| 26479 |
a109: 0x2660, |
| 26480 |
a120: 0x2460, |
| 26481 |
a121: 0x2461, |
| 26482 |
a122: 0x2462, |
| 26483 |
a123: 0x2463, |
| 26484 |
a124: 0x2464, |
| 26485 |
a125: 0x2465, |
| 26486 |
a126: 0x2466, |
| 26487 |
a127: 0x2467, |
| 26488 |
a128: 0x2468, |
| 26489 |
a129: 0x2469, |
| 26490 |
a130: 0x2776, |
| 26491 |
a131: 0x2777, |
| 26492 |
a132: 0x2778, |
| 26493 |
a133: 0x2779, |
| 26494 |
a134: 0x277A, |
| 26495 |
a135: 0x277B, |
| 26496 |
a136: 0x277C, |
| 26497 |
a137: 0x277D, |
| 26498 |
a138: 0x277E, |
| 26499 |
a139: 0x277F, |
| 26500 |
a140: 0x2780, |
| 26501 |
a141: 0x2781, |
| 26502 |
a142: 0x2782, |
| 26503 |
a143: 0x2783, |
| 26504 |
a144: 0x2784, |
| 26505 |
a145: 0x2785, |
| 26506 |
a146: 0x2786, |
| 26507 |
a147: 0x2787, |
| 26508 |
a148: 0x2788, |
| 26509 |
a149: 0x2789, |
| 26510 |
a150: 0x278A, |
| 26511 |
a151: 0x278B, |
| 26512 |
a152: 0x278C, |
| 26513 |
a153: 0x278D, |
| 26514 |
a154: 0x278E, |
| 26515 |
a155: 0x278F, |
| 26516 |
a156: 0x2790, |
| 26517 |
a157: 0x2791, |
| 26518 |
a158: 0x2792, |
| 26519 |
a159: 0x2793, |
| 26520 |
a160: 0x2794, |
| 26521 |
a161: 0x2192, |
| 26522 |
a163: 0x2194, |
| 26523 |
a164: 0x2195, |
| 26524 |
a196: 0x2798, |
| 26525 |
a165: 0x2799, |
| 26526 |
a192: 0x279A, |
| 26527 |
a166: 0x279B, |
| 26528 |
a167: 0x279C, |
| 26529 |
a168: 0x279D, |
| 26530 |
a169: 0x279E, |
| 26531 |
a170: 0x279F, |
| 26532 |
a171: 0x27A0, |
| 26533 |
a172: 0x27A1, |
| 26534 |
a173: 0x27A2, |
| 26535 |
a162: 0x27A3, |
| 26536 |
a174: 0x27A4, |
| 26537 |
a175: 0x27A5, |
| 26538 |
a176: 0x27A6, |
| 26539 |
a177: 0x27A7, |
| 26540 |
a178: 0x27A8, |
| 26541 |
a179: 0x27A9, |
| 26542 |
a193: 0x27AA, |
| 26543 |
a180: 0x27AB, |
| 26544 |
a199: 0x27AC, |
| 26545 |
a181: 0x27AD, |
| 26546 |
a200: 0x27AE, |
| 26547 |
a182: 0x27AF, |
| 26548 |
a201: 0x27B1, |
| 26549 |
a183: 0x27B2, |
| 26550 |
a184: 0x27B3, |
| 26551 |
a197: 0x27B4, |
| 26552 |
a185: 0x27B5, |
| 26553 |
a194: 0x27B6, |
| 26554 |
a198: 0x27B7, |
| 26555 |
a186: 0x27B8, |
| 26556 |
a195: 0x27B9, |
| 26557 |
a187: 0x27BA, |
| 26558 |
a188: 0x27BB, |
| 26559 |
a189: 0x27BC, |
| 26560 |
a190: 0x27BD, |
| 26561 |
a191: 0x27BE, |
| 26562 |
a89: 0x2768, // 0xF8D7 |
| 26563 |
a90: 0x2769, // 0xF8D8 |
| 26564 |
a93: 0x276A, // 0xF8D9 |
| 26565 |
a94: 0x276B, // 0xF8DA |
| 26566 |
a91: 0x276C, // 0xF8DB |
| 26567 |
a92: 0x276D, // 0xF8DC |
| 26568 |
a205: 0x276E, // 0xF8DD |
| 26569 |
a85: 0x276F, // 0xF8DE |
| 26570 |
a206: 0x2770, // 0xF8DF |
| 26571 |
a86: 0x2771, // 0xF8E0 |
| 26572 |
a87: 0x2772, // 0xF8E1 |
| 26573 |
a88: 0x2773, // 0xF8E2 |
| 26574 |
a95: 0x2774, // 0xF8E3 |
| 26575 |
a96: 0x2775, // 0xF8E4 |
| 26576 |
'.notdef': 0x0000 |
| 26577 |
}; |
| 26578 |
|
| 26579 |
|
| 26580 |
var PDFImage = (function PDFImageClosure() { |
| 26581 |
/** |
| 26582 |
* Decode the image in the main thread if it supported. Resovles the promise |
| 26583 |
* when the image data is ready. |
| 26584 |
*/ |
| 26585 |
function handleImageData(handler, xref, res, image) { |
| 26586 |
if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) { |
| 26587 |
// For natively supported jpegs send them to the main thread for decoding. |
| 26588 |
var dict = image.dict; |
| 26589 |
var colorSpace = dict.get('ColorSpace', 'CS'); |
| 26590 |
colorSpace = ColorSpace.parse(colorSpace, xref, res); |
| 26591 |
var numComps = colorSpace.numComps; |
| 26592 |
var decodePromise = handler.sendWithPromise('JpegDecode', |
| 26593 |
[image.getIR(), numComps]); |
| 26594 |
return decodePromise.then(function (message) { |
| 26595 |
var data = message.data; |
| 26596 |
return new Stream(data, 0, data.length, image.dict); |
| 26597 |
}); |
| 26598 |
} else { |
| 26599 |
return Promise.resolve(image); |
| 26600 |
} |
| 26601 |
} |
| 26602 |
|
| 26603 |
/** |
| 26604 |
* Decode and clamp a value. The formula is different from the spec because we |
| 26605 |
* don't decode to float range [0,1], we decode it in the [0,max] range. |
| 26606 |
*/ |
| 26607 |
function decodeAndClamp(value, addend, coefficient, max) { |
| 26608 |
value = addend + value * coefficient; |
| 26609 |
// Clamp the value to the range |
| 26610 |
return (value < 0 ? 0 : (value > max ? max : value)); |
| 26611 |
} |
| 26612 |
|
| 26613 |
function PDFImage(xref, res, image, inline, smask, mask, isMask) { |
| 26614 |
this.image = image; |
| 26615 |
var dict = image.dict; |
| 26616 |
if (dict.has('Filter')) { |
| 26617 |
var filter = dict.get('Filter').name; |
| 26618 |
if (filter === 'JPXDecode') { |
| 26619 |
var jpxImage = new JpxImage(); |
| 26620 |
jpxImage.parseImageProperties(image.stream); |
| 26621 |
image.stream.reset(); |
| 26622 |
image.bitsPerComponent = jpxImage.bitsPerComponent; |
| 26623 |
image.numComps = jpxImage.componentsCount; |
| 26624 |
} else if (filter === 'JBIG2Decode') { |
| 26625 |
image.bitsPerComponent = 1; |
| 26626 |
image.numComps = 1; |
| 26627 |
} |
| 26628 |
} |
| 26629 |
// TODO cache rendered images? |
| 26630 |
|
| 26631 |
this.width = dict.get('Width', 'W'); |
| 26632 |
this.height = dict.get('Height', 'H'); |
| 26633 |
|
| 26634 |
if (this.width < 1 || this.height < 1) { |
| 26635 |
error('Invalid image width: ' + this.width + ' or height: ' + |
| 26636 |
this.height); |
| 26637 |
} |
| 26638 |
|
| 26639 |
this.interpolate = dict.get('Interpolate', 'I') || false; |
| 26640 |
this.imageMask = dict.get('ImageMask', 'IM') || false; |
| 26641 |
this.matte = dict.get('Matte') || false; |
| 26642 |
|
| 26643 |
var bitsPerComponent = image.bitsPerComponent; |
| 26644 |
if (!bitsPerComponent) { |
| 26645 |
bitsPerComponent = dict.get('BitsPerComponent', 'BPC'); |
| 26646 |
if (!bitsPerComponent) { |
| 26647 |
if (this.imageMask) { |
| 26648 |
bitsPerComponent = 1; |
| 26649 |
} else { |
| 26650 |
error('Bits per component missing in image: ' + this.imageMask); |
| 26651 |
} |
| 26652 |
} |
| 26653 |
} |
| 26654 |
this.bpc = bitsPerComponent; |
| 26655 |
|
| 26656 |
if (!this.imageMask) { |
| 26657 |
var colorSpace = dict.get('ColorSpace', 'CS'); |
| 26658 |
if (!colorSpace) { |
| 26659 |
info('JPX images (which do not require color spaces)'); |
| 26660 |
switch (image.numComps) { |
| 26661 |
case 1: |
| 26662 |
colorSpace = Name.get('DeviceGray'); |
| 26663 |
break; |
| 26664 |
case 3: |
| 26665 |
colorSpace = Name.get('DeviceRGB'); |
| 26666 |
break; |
| 26667 |
case 4: |
| 26668 |
colorSpace = Name.get('DeviceCMYK'); |
| 26669 |
break; |
| 26670 |
default: |
| 26671 |
error('JPX images with ' + this.numComps + |
| 26672 |
' color components not supported.'); |
| 26673 |
} |
| 26674 |
} |
| 26675 |
this.colorSpace = ColorSpace.parse(colorSpace, xref, res); |
| 26676 |
this.numComps = this.colorSpace.numComps; |
| 26677 |
} |
| 26678 |
|
| 26679 |
this.decode = dict.get('Decode', 'D'); |
| 26680 |
this.needsDecode = false; |
| 26681 |
if (this.decode && |
| 26682 |
((this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode)) || |
| 26683 |
(isMask && !ColorSpace.isDefaultDecode(this.decode, 1)))) { |
| 26684 |
this.needsDecode = true; |
| 26685 |
// Do some preprocessing to avoid more math. |
| 26686 |
var max = (1 << bitsPerComponent) - 1; |
| 26687 |
this.decodeCoefficients = []; |
| 26688 |
this.decodeAddends = []; |
| 26689 |
for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) { |
| 26690 |
var dmin = this.decode[i]; |
| 26691 |
var dmax = this.decode[i + 1]; |
| 26692 |
this.decodeCoefficients[j] = dmax - dmin; |
| 26693 |
this.decodeAddends[j] = max * dmin; |
| 26694 |
} |
| 26695 |
} |
| 26696 |
|
| 26697 |
if (smask) { |
| 26698 |
this.smask = new PDFImage(xref, res, smask, false); |
| 26699 |
} else if (mask) { |
| 26700 |
if (isStream(mask)) { |
| 26701 |
this.mask = new PDFImage(xref, res, mask, false, null, null, true); |
| 26702 |
} else { |
| 26703 |
// Color key mask (just an array). |
| 26704 |
this.mask = mask; |
| 26705 |
} |
| 26706 |
} |
| 26707 |
} |
| 26708 |
/** |
| 26709 |
* Handles processing of image data and returns the Promise that is resolved |
| 26710 |
* with a PDFImage when the image is ready to be used. |
| 26711 |
*/ |
| 26712 |
PDFImage.buildImage = function PDFImage_buildImage(handler, xref, |
| 26713 |
res, image, inline) { |
| 26714 |
var imagePromise = handleImageData(handler, xref, res, image); |
| 26715 |
var smaskPromise; |
| 26716 |
var maskPromise; |
| 26717 |
|
| 26718 |
var smask = image.dict.get('SMask'); |
| 26719 |
var mask = image.dict.get('Mask'); |
| 26720 |
|
| 26721 |
if (smask) { |
| 26722 |
smaskPromise = handleImageData(handler, xref, res, smask); |
| 26723 |
maskPromise = Promise.resolve(null); |
| 26724 |
} else { |
| 26725 |
smaskPromise = Promise.resolve(null); |
| 26726 |
if (mask) { |
| 26727 |
if (isStream(mask)) { |
| 26728 |
maskPromise = handleImageData(handler, xref, res, mask); |
| 26729 |
} else if (isArray(mask)) { |
| 26730 |
maskPromise = Promise.resolve(mask); |
| 26731 |
} else { |
| 26732 |
warn('Unsupported mask format.'); |
| 26733 |
maskPromise = Promise.resolve(null); |
| 26734 |
} |
| 26735 |
} else { |
| 26736 |
maskPromise = Promise.resolve(null); |
| 26737 |
} |
| 26738 |
} |
| 26739 |
return Promise.all([imagePromise, smaskPromise, maskPromise]).then( |
| 26740 |
function(results) { |
| 26741 |
var imageData = results[0]; |
| 26742 |
var smaskData = results[1]; |
| 26743 |
var maskData = results[2]; |
| 26744 |
return new PDFImage(xref, res, imageData, inline, smaskData, maskData); |
| 26745 |
}); |
| 26746 |
}; |
| 26747 |
|
| 26748 |
/** |
| 26749 |
* Resize an image using the nearest neighbor algorithm. Currently only |
| 26750 |
* supports one and three component images. |
| 26751 |
* @param {TypedArray} pixels The original image with one component. |
| 26752 |
* @param {Number} bpc Number of bits per component. |
| 26753 |
* @param {Number} components Number of color components, 1 or 3 is supported. |
| 26754 |
* @param {Number} w1 Original width. |
| 26755 |
* @param {Number} h1 Original height. |
| 26756 |
* @param {Number} w2 New width. |
| 26757 |
* @param {Number} h2 New height. |
| 26758 |
* @param {TypedArray} dest (Optional) The destination buffer. |
| 26759 |
* @param {Number} alpha01 (Optional) Size reserved for the alpha channel. |
| 26760 |
* @return {TypedArray} Resized image data. |
| 26761 |
*/ |
| 26762 |
PDFImage.resize = function PDFImage_resize(pixels, bpc, components, |
| 26763 |
w1, h1, w2, h2, dest, alpha01) { |
| 26764 |
|
| 26765 |
if (components !== 1 && components !== 3) { |
| 26766 |
error('Unsupported component count for resizing.'); |
| 26767 |
} |
| 26768 |
|
| 26769 |
var length = w2 * h2 * components; |
| 26770 |
var temp = dest ? dest : (bpc <= 8 ? new Uint8Array(length) : |
| 26771 |
(bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length))); |
| 26772 |
var xRatio = w1 / w2; |
| 26773 |
var yRatio = h1 / h2; |
| 26774 |
var i, j, py, newIndex = 0, oldIndex; |
| 26775 |
var xScaled = new Uint16Array(w2); |
| 26776 |
var w1Scanline = w1 * components; |
| 26777 |
if (alpha01 !== 1) { |
| 26778 |
alpha01 = 0; |
| 26779 |
} |
| 26780 |
|
| 26781 |
for (j = 0; j < w2; j++) { |
| 26782 |
xScaled[j] = Math.floor(j * xRatio) * components; |
| 26783 |
} |
| 26784 |
|
| 26785 |
if (components === 1) { |
| 26786 |
for (i = 0; i < h2; i++) { |
| 26787 |
py = Math.floor(i * yRatio) * w1Scanline; |
| 26788 |
for (j = 0; j < w2; j++) { |
| 26789 |
oldIndex = py + xScaled[j]; |
| 26790 |
temp[newIndex++] = pixels[oldIndex]; |
| 26791 |
} |
| 26792 |
} |
| 26793 |
} else if (components === 3) { |
| 26794 |
for (i = 0; i < h2; i++) { |
| 26795 |
py = Math.floor(i * yRatio) * w1Scanline; |
| 26796 |
for (j = 0; j < w2; j++) { |
| 26797 |
oldIndex = py + xScaled[j]; |
| 26798 |
temp[newIndex++] = pixels[oldIndex++]; |
| 26799 |
temp[newIndex++] = pixels[oldIndex++]; |
| 26800 |
temp[newIndex++] = pixels[oldIndex++]; |
| 26801 |
newIndex += alpha01; |
| 26802 |
} |
| 26803 |
} |
| 26804 |
} |
| 26805 |
return temp; |
| 26806 |
}; |
| 26807 |
|
| 26808 |
PDFImage.createMask = |
| 26809 |
function PDFImage_createMask(imgArray, width, height, |
| 26810 |
imageIsFromDecodeStream, inverseDecode) { |
| 26811 |
|
| 26812 |
// |imgArray| might not contain full data for every pixel of the mask, so |
| 26813 |
// we need to distinguish between |computedLength| and |actualLength|. |
| 26814 |
// In particular, if inverseDecode is true, then the array we return must |
| 26815 |
// have a length of |computedLength|. |
| 26816 |
|
| 26817 |
var computedLength = ((width + 7) >> 3) * height; |
| 26818 |
var actualLength = imgArray.byteLength; |
| 26819 |
var haveFullData = computedLength === actualLength; |
| 26820 |
var data, i; |
| 26821 |
|
| 26822 |
if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) { |
| 26823 |
// imgArray came from a DecodeStream and its data is in an appropriate |
| 26824 |
// form, so we can just transfer it. |
| 26825 |
data = imgArray; |
| 26826 |
} else if (!inverseDecode) { |
| 26827 |
data = new Uint8Array(actualLength); |
| 26828 |
data.set(imgArray); |
| 26829 |
} else { |
| 26830 |
data = new Uint8Array(computedLength); |
| 26831 |
data.set(imgArray); |
| 26832 |
for (i = actualLength; i < computedLength; i++) { |
| 26833 |
data[i] = 0xff; |
| 26834 |
} |
| 26835 |
} |
| 26836 |
|
| 26837 |
// If necessary, invert the original mask data (but not any extra we might |
| 26838 |
// have added above). It's safe to modify the array -- whether it's the |
| 26839 |
// original or a copy, we're about to transfer it anyway, so nothing else |
| 26840 |
// in this thread can be relying on its contents. |
| 26841 |
if (inverseDecode) { |
| 26842 |
for (i = 0; i < actualLength; i++) { |
| 26843 |
data[i] = ~data[i]; |
| 26844 |
} |
| 26845 |
} |
| 26846 |
|
| 26847 |
return {data: data, width: width, height: height}; |
| 26848 |
}; |
| 26849 |
|
| 26850 |
PDFImage.prototype = { |
| 26851 |
get drawWidth() { |
| 26852 |
return Math.max(this.width, |
| 26853 |
this.smask && this.smask.width || 0, |
| 26854 |
this.mask && this.mask.width || 0); |
| 26855 |
}, |
| 26856 |
|
| 26857 |
get drawHeight() { |
| 26858 |
return Math.max(this.height, |
| 26859 |
this.smask && this.smask.height || 0, |
| 26860 |
this.mask && this.mask.height || 0); |
| 26861 |
}, |
| 26862 |
|
| 26863 |
decodeBuffer: function PDFImage_decodeBuffer(buffer) { |
| 26864 |
var bpc = this.bpc; |
| 26865 |
var numComps = this.numComps; |
| 26866 |
|
| 26867 |
var decodeAddends = this.decodeAddends; |
| 26868 |
var decodeCoefficients = this.decodeCoefficients; |
| 26869 |
var max = (1 << bpc) - 1; |
| 26870 |
var i, ii; |
| 26871 |
|
| 26872 |
if (bpc === 1) { |
| 26873 |
// If the buffer needed decode that means it just needs to be inverted. |
| 26874 |
for (i = 0, ii = buffer.length; i < ii; i++) { |
| 26875 |
buffer[i] = +!(buffer[i]); |
| 26876 |
} |
| 26877 |
return; |
| 26878 |
} |
| 26879 |
var index = 0; |
| 26880 |
for (i = 0, ii = this.width * this.height; i < ii; i++) { |
| 26881 |
for (var j = 0; j < numComps; j++) { |
| 26882 |
buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], |
| 26883 |
decodeCoefficients[j], max); |
| 26884 |
index++; |
| 26885 |
} |
| 26886 |
} |
| 26887 |
}, |
| 26888 |
|
| 26889 |
getComponents: function PDFImage_getComponents(buffer) { |
| 26890 |
var bpc = this.bpc; |
| 26891 |
|
| 26892 |
// This image doesn't require any extra work. |
| 26893 |
if (bpc === 8) { |
| 26894 |
return buffer; |
| 26895 |
} |
| 26896 |
|
| 26897 |
var width = this.width; |
| 26898 |
var height = this.height; |
| 26899 |
var numComps = this.numComps; |
| 26900 |
|
| 26901 |
var length = width * height * numComps; |
| 26902 |
var bufferPos = 0; |
| 26903 |
var output = (bpc <= 8 ? new Uint8Array(length) : |
| 26904 |
(bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length))); |
| 26905 |
var rowComps = width * numComps; |
| 26906 |
|
| 26907 |
var max = (1 << bpc) - 1; |
| 26908 |
var i = 0, ii, buf; |
| 26909 |
|
| 26910 |
if (bpc === 1) { |
| 26911 |
// Optimization for reading 1 bpc images. |
| 26912 |
var mask, loop1End, loop2End; |
| 26913 |
for (var j = 0; j < height; j++) { |
| 26914 |
loop1End = i + (rowComps & ~7); |
| 26915 |
loop2End = i + rowComps; |
| 26916 |
|
| 26917 |
// unroll loop for all full bytes |
| 26918 |
while (i < loop1End) { |
| 26919 |
buf = buffer[bufferPos++]; |
| 26920 |
output[i] = (buf >> 7) & 1; |
| 26921 |
output[i + 1] = (buf >> 6) & 1; |
| 26922 |
output[i + 2] = (buf >> 5) & 1; |
| 26923 |
output[i + 3] = (buf >> 4) & 1; |
| 26924 |
output[i + 4] = (buf >> 3) & 1; |
| 26925 |
output[i + 5] = (buf >> 2) & 1; |
| 26926 |
output[i + 6] = (buf >> 1) & 1; |
| 26927 |
output[i + 7] = buf & 1; |
| 26928 |
i += 8; |
| 26929 |
} |
| 26930 |
|
| 26931 |
// handle remaing bits |
| 26932 |
if (i < loop2End) { |
| 26933 |
buf = buffer[bufferPos++]; |
| 26934 |
mask = 128; |
| 26935 |
while (i < loop2End) { |
| 26936 |
output[i++] = +!!(buf & mask); |
| 26937 |
mask >>= 1; |
| 26938 |
} |
| 26939 |
} |
| 26940 |
} |
| 26941 |
} else { |
| 26942 |
// The general case that handles all other bpc values. |
| 26943 |
var bits = 0; |
| 26944 |
buf = 0; |
| 26945 |
for (i = 0, ii = length; i < ii; ++i) { |
| 26946 |
if (i % rowComps === 0) { |
| 26947 |
buf = 0; |
| 26948 |
bits = 0; |
| 26949 |
} |
| 26950 |
|
| 26951 |
while (bits < bpc) { |
| 26952 |
buf = (buf << 8) | buffer[bufferPos++]; |
| 26953 |
bits += 8; |
| 26954 |
} |
| 26955 |
|
| 26956 |
var remainingBits = bits - bpc; |
| 26957 |
var value = buf >> remainingBits; |
| 26958 |
output[i] = (value < 0 ? 0 : (value > max ? max : value)); |
| 26959 |
buf = buf & ((1 << remainingBits) - 1); |
| 26960 |
bits = remainingBits; |
| 26961 |
} |
| 26962 |
} |
| 26963 |
return output; |
| 26964 |
}, |
| 26965 |
|
| 26966 |
fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height, |
| 26967 |
actualHeight, image) { |
| 26968 |
var smask = this.smask; |
| 26969 |
var mask = this.mask; |
| 26970 |
var alphaBuf, sw, sh, i, ii, j; |
| 26971 |
|
| 26972 |
if (smask) { |
| 26973 |
sw = smask.width; |
| 26974 |
sh = smask.height; |
| 26975 |
alphaBuf = new Uint8Array(sw * sh); |
| 26976 |
smask.fillGrayBuffer(alphaBuf); |
| 26977 |
if (sw !== width || sh !== height) { |
| 26978 |
alphaBuf = PDFImage.resize(alphaBuf, smask.bpc, 1, sw, sh, width, |
| 26979 |
height); |
| 26980 |
} |
| 26981 |
} else if (mask) { |
| 26982 |
if (mask instanceof PDFImage) { |
| 26983 |
sw = mask.width; |
| 26984 |
sh = mask.height; |
| 26985 |
alphaBuf = new Uint8Array(sw * sh); |
| 26986 |
mask.numComps = 1; |
| 26987 |
mask.fillGrayBuffer(alphaBuf); |
| 26988 |
|
| 26989 |
// Need to invert values in rgbaBuf |
| 26990 |
for (i = 0, ii = sw * sh; i < ii; ++i) { |
| 26991 |
alphaBuf[i] = 255 - alphaBuf[i]; |
| 26992 |
} |
| 26993 |
|
| 26994 |
if (sw !== width || sh !== height) { |
| 26995 |
alphaBuf = PDFImage.resize(alphaBuf, mask.bpc, 1, sw, sh, width, |
| 26996 |
height); |
| 26997 |
} |
| 26998 |
} else if (isArray(mask)) { |
| 26999 |
// Color key mask: if any of the compontents are outside the range |
| 27000 |
// then they should be painted. |
| 27001 |
alphaBuf = new Uint8Array(width * height); |
| 27002 |
var numComps = this.numComps; |
| 27003 |
for (i = 0, ii = width * height; i < ii; ++i) { |
| 27004 |
var opacity = 0; |
| 27005 |
var imageOffset = i * numComps; |
| 27006 |
for (j = 0; j < numComps; ++j) { |
| 27007 |
var color = image[imageOffset + j]; |
| 27008 |
var maskOffset = j * 2; |
| 27009 |
if (color < mask[maskOffset] || color > mask[maskOffset + 1]) { |
| 27010 |
opacity = 255; |
| 27011 |
break; |
| 27012 |
} |
| 27013 |
} |
| 27014 |
alphaBuf[i] = opacity; |
| 27015 |
} |
| 27016 |
} else { |
| 27017 |
error('Unknown mask format.'); |
| 27018 |
} |
| 27019 |
} |
| 27020 |
|
| 27021 |
if (alphaBuf) { |
| 27022 |
for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { |
| 27023 |
rgbaBuf[j] = alphaBuf[i]; |
| 27024 |
} |
| 27025 |
} else { |
| 27026 |
// No mask. |
| 27027 |
for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { |
| 27028 |
rgbaBuf[j] = 255; |
| 27029 |
} |
| 27030 |
} |
| 27031 |
}, |
| 27032 |
|
| 27033 |
undoPreblend: function PDFImage_undoPreblend(buffer, width, height) { |
| 27034 |
var matte = this.smask && this.smask.matte; |
| 27035 |
if (!matte) { |
| 27036 |
return; |
| 27037 |
} |
| 27038 |
var matteRgb = this.colorSpace.getRgb(matte, 0); |
| 27039 |
var matteR = matteRgb[0]; |
| 27040 |
var matteG = matteRgb[1]; |
| 27041 |
var matteB = matteRgb[2]; |
| 27042 |
var length = width * height * 4; |
| 27043 |
var r, g, b; |
| 27044 |
for (var i = 0; i < length; i += 4) { |
| 27045 |
var alpha = buffer[i + 3]; |
| 27046 |
if (alpha === 0) { |
| 27047 |
// according formula we have to get Infinity in all components |
| 27048 |
// making it white (typical paper color) should be okay |
| 27049 |
buffer[i] = 255; |
| 27050 |
buffer[i + 1] = 255; |
| 27051 |
buffer[i + 2] = 255; |
| 27052 |
continue; |
| 27053 |
} |
| 27054 |
var k = 255 / alpha; |
| 27055 |
r = (buffer[i] - matteR) * k + matteR; |
| 27056 |
g = (buffer[i + 1] - matteG) * k + matteG; |
| 27057 |
b = (buffer[i + 2] - matteB) * k + matteB; |
| 27058 |
buffer[i] = r <= 0 ? 0 : r >= 255 ? 255 : r | 0; |
| 27059 |
buffer[i + 1] = g <= 0 ? 0 : g >= 255 ? 255 : g | 0; |
| 27060 |
buffer[i + 2] = b <= 0 ? 0 : b >= 255 ? 255 : b | 0; |
| 27061 |
} |
| 27062 |
}, |
| 27063 |
|
| 27064 |
createImageData: function PDFImage_createImageData(forceRGBA) { |
| 27065 |
var drawWidth = this.drawWidth; |
| 27066 |
var drawHeight = this.drawHeight; |
| 27067 |
var imgData = { // other fields are filled in below |
| 27068 |
width: drawWidth, |
| 27069 |
height: drawHeight |
| 27070 |
}; |
| 27071 |
|
| 27072 |
var numComps = this.numComps; |
| 27073 |
var originalWidth = this.width; |
| 27074 |
var originalHeight = this.height; |
| 27075 |
var bpc = this.bpc; |
| 27076 |
|
| 27077 |
// Rows start at byte boundary. |
| 27078 |
var rowBytes = (originalWidth * numComps * bpc + 7) >> 3; |
| 27079 |
var imgArray; |
| 27080 |
|
| 27081 |
if (!forceRGBA) { |
| 27082 |
// If it is a 1-bit-per-pixel grayscale (i.e. black-and-white) image |
| 27083 |
// without any complications, we pass a same-sized copy to the main |
| 27084 |
// thread rather than expanding by 32x to RGBA form. This saves *lots* |
| 27085 |
// of memory for many scanned documents. It's also much faster. |
| 27086 |
// |
| 27087 |
// Similarly, if it is a 24-bit-per pixel RGB image without any |
| 27088 |
// complications, we avoid expanding by 1.333x to RGBA form. |
| 27089 |
var kind; |
| 27090 |
if (this.colorSpace.name === 'DeviceGray' && bpc === 1) { |
| 27091 |
kind = ImageKind.GRAYSCALE_1BPP; |
| 27092 |
} else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 && |
| 27093 |
!this.needsDecode) { |
| 27094 |
kind = ImageKind.RGB_24BPP; |
| 27095 |
} |
| 27096 |
if (kind && !this.smask && !this.mask && |
| 27097 |
drawWidth === originalWidth && drawHeight === originalHeight) { |
| 27098 |
imgData.kind = kind; |
| 27099 |
|
| 27100 |
imgArray = this.getImageBytes(originalHeight * rowBytes); |
| 27101 |
// If imgArray came from a DecodeStream, we're safe to transfer it |
| 27102 |
// (and thus neuter it) because it will constitute the entire |
| 27103 |
// DecodeStream's data. But if it came from a Stream, we need to |
| 27104 |
// copy it because it'll only be a portion of the Stream's data, and |
| 27105 |
// the rest will be read later on. |
| 27106 |
if (this.image instanceof DecodeStream) { |
| 27107 |
imgData.data = imgArray; |
| 27108 |
} else { |
| 27109 |
var newArray = new Uint8Array(imgArray.length); |
| 27110 |
newArray.set(imgArray); |
| 27111 |
imgData.data = newArray; |
| 27112 |
} |
| 27113 |
if (this.needsDecode) { |
| 27114 |
// Invert the buffer (which must be grayscale if we reached here). |
| 27115 |
assert(kind === ImageKind.GRAYSCALE_1BPP); |
| 27116 |
var buffer = imgData.data; |
| 27117 |
for (var i = 0, ii = buffer.length; i < ii; i++) { |
| 27118 |
buffer[i] ^= 0xff; |
| 27119 |
} |
| 27120 |
} |
| 27121 |
return imgData; |
| 27122 |
} |
| 27123 |
if (this.image instanceof JpegStream && !this.smask && !this.mask) { |
| 27124 |
imgData.kind = ImageKind.RGB_24BPP; |
| 27125 |
imgData.data = this.getImageBytes(originalHeight * rowBytes, |
| 27126 |
drawWidth, drawHeight, true); |
| 27127 |
return imgData; |
| 27128 |
} |
| 27129 |
} |
| 27130 |
|
| 27131 |
imgArray = this.getImageBytes(originalHeight * rowBytes); |
| 27132 |
// imgArray can be incomplete (e.g. after CCITT fax encoding). |
| 27133 |
var actualHeight = 0 | (imgArray.length / rowBytes * |
| 27134 |
drawHeight / originalHeight); |
| 27135 |
|
| 27136 |
var comps = this.getComponents(imgArray); |
| 27137 |
|
| 27138 |
// If opacity data is present, use RGBA_32BPP form. Otherwise, use the |
| 27139 |
// more compact RGB_24BPP form if allowable. |
| 27140 |
var alpha01, maybeUndoPreblend; |
| 27141 |
if (!forceRGBA && !this.smask && !this.mask) { |
| 27142 |
imgData.kind = ImageKind.RGB_24BPP; |
| 27143 |
imgData.data = new Uint8Array(drawWidth * drawHeight * 3); |
| 27144 |
alpha01 = 0; |
| 27145 |
maybeUndoPreblend = false; |
| 27146 |
} else { |
| 27147 |
imgData.kind = ImageKind.RGBA_32BPP; |
| 27148 |
imgData.data = new Uint8Array(drawWidth * drawHeight * 4); |
| 27149 |
alpha01 = 1; |
| 27150 |
maybeUndoPreblend = true; |
| 27151 |
|
| 27152 |
// Color key masking (opacity) must be performed before decoding. |
| 27153 |
this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight, |
| 27154 |
comps); |
| 27155 |
} |
| 27156 |
|
| 27157 |
if (this.needsDecode) { |
| 27158 |
this.decodeBuffer(comps); |
| 27159 |
} |
| 27160 |
this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight, |
| 27161 |
drawWidth, drawHeight, actualHeight, bpc, comps, |
| 27162 |
alpha01); |
| 27163 |
if (maybeUndoPreblend) { |
| 27164 |
this.undoPreblend(imgData.data, drawWidth, actualHeight); |
| 27165 |
} |
| 27166 |
|
| 27167 |
return imgData; |
| 27168 |
}, |
| 27169 |
|
| 27170 |
fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) { |
| 27171 |
var numComps = this.numComps; |
| 27172 |
if (numComps !== 1) { |
| 27173 |
error('Reading gray scale from a color image: ' + numComps); |
| 27174 |
} |
| 27175 |
|
| 27176 |
var width = this.width; |
| 27177 |
var height = this.height; |
| 27178 |
var bpc = this.bpc; |
| 27179 |
|
| 27180 |
// rows start at byte boundary |
| 27181 |
var rowBytes = (width * numComps * bpc + 7) >> 3; |
| 27182 |
var imgArray = this.getImageBytes(height * rowBytes); |
| 27183 |
|
| 27184 |
var comps = this.getComponents(imgArray); |
| 27185 |
var i, length; |
| 27186 |
|
| 27187 |
if (bpc === 1) { |
| 27188 |
// inline decoding (= inversion) for 1 bpc images |
| 27189 |
length = width * height; |
| 27190 |
if (this.needsDecode) { |
| 27191 |
// invert and scale to {0, 255} |
| 27192 |
for (i = 0; i < length; ++i) { |
| 27193 |
buffer[i] = (comps[i] - 1) & 255; |
| 27194 |
} |
| 27195 |
} else { |
| 27196 |
// scale to {0, 255} |
| 27197 |
for (i = 0; i < length; ++i) { |
| 27198 |
buffer[i] = (-comps[i]) & 255; |
| 27199 |
} |
| 27200 |
} |
| 27201 |
return; |
| 27202 |
} |
| 27203 |
|
| 27204 |
if (this.needsDecode) { |
| 27205 |
this.decodeBuffer(comps); |
| 27206 |
} |
| 27207 |
length = width * height; |
| 27208 |
// we aren't using a colorspace so we need to scale the value |
| 27209 |
var scale = 255 / ((1 << bpc) - 1); |
| 27210 |
for (i = 0; i < length; ++i) { |
| 27211 |
buffer[i] = (scale * comps[i]) | 0; |
| 27212 |
} |
| 27213 |
}, |
| 27214 |
|
| 27215 |
getImageBytes: function PDFImage_getImageBytes(length, |
| 27216 |
drawWidth, drawHeight, |
| 27217 |
forceRGB) { |
| 27218 |
this.image.reset(); |
| 27219 |
this.image.drawWidth = drawWidth || this.width; |
| 27220 |
this.image.drawHeight = drawHeight || this.height; |
| 27221 |
this.image.forceRGB = !!forceRGB; |
| 27222 |
return this.image.getBytes(length); |
| 27223 |
} |
| 27224 |
}; |
| 27225 |
return PDFImage; |
| 27226 |
})(); |
| 27227 |
|
| 27228 |
|
| 27229 |
// The Metrics object contains glyph widths (in glyph space units). |
| 27230 |
// As per PDF spec, for most fonts (Type 3 being an exception) a glyph |
| 27231 |
// space unit corresponds to 1/1000th of text space unit. |
| 27232 |
var Metrics = { |
| 27233 |
'Courier': 600, |
| 27234 |
'Courier-Bold': 600, |
| 27235 |
'Courier-BoldOblique': 600, |
| 27236 |
'Courier-Oblique': 600, |
| 27237 |
'Helvetica' : { |
| 27238 |
'space': 278, |
| 27239 |
'exclam': 278, |
| 27240 |
'quotedbl': 355, |
| 27241 |
'numbersign': 556, |
| 27242 |
'dollar': 556, |
| 27243 |
'percent': 889, |
| 27244 |
'ampersand': 667, |
| 27245 |
'quoteright': 222, |
| 27246 |
'parenleft': 333, |
| 27247 |
'parenright': 333, |
| 27248 |
'asterisk': 389, |
| 27249 |
'plus': 584, |
| 27250 |
'comma': 278, |
| 27251 |
'hyphen': 333, |
| 27252 |
'period': 278, |
| 27253 |
'slash': 278, |
| 27254 |
'zero': 556, |
| 27255 |
'one': 556, |
| 27256 |
'two': 556, |
| 27257 |
'three': 556, |
| 27258 |
'four': 556, |
| 27259 |
'five': 556, |
| 27260 |
'six': 556, |
| 27261 |
'seven': 556, |
| 27262 |
'eight': 556, |
| 27263 |
'nine': 556, |
| 27264 |
'colon': 278, |
| 27265 |
'semicolon': 278, |
| 27266 |
'less': 584, |
| 27267 |
'equal': 584, |
| 27268 |
'greater': 584, |
| 27269 |
'question': 556, |
| 27270 |
'at': 1015, |
| 27271 |
'A': 667, |
| 27272 |
'B': 667, |
| 27273 |
'C': 722, |
| 27274 |
'D': 722, |
| 27275 |
'E': 667, |
| 27276 |
'F': 611, |
| 27277 |
'G': 778, |
| 27278 |
'H': 722, |
| 27279 |
'I': 278, |
| 27280 |
'J': 500, |
| 27281 |
'K': 667, |
| 27282 |
'L': 556, |
| 27283 |
'M': 833, |
| 27284 |
'N': 722, |
| 27285 |
'O': 778, |
| 27286 |
'P': 667, |
| 27287 |
'Q': 778, |
| 27288 |
'R': 722, |
| 27289 |
'S': 667, |
| 27290 |
'T': 611, |
| 27291 |
'U': 722, |
| 27292 |
'V': 667, |
| 27293 |
'W': 944, |
| 27294 |
'X': 667, |
| 27295 |
'Y': 667, |
| 27296 |
'Z': 611, |
| 27297 |
'bracketleft': 278, |
| 27298 |
'backslash': 278, |
| 27299 |
'bracketright': 278, |
| 27300 |
'asciicircum': 469, |
| 27301 |
'underscore': 556, |
| 27302 |
'quoteleft': 222, |
| 27303 |
'a': 556, |
| 27304 |
'b': 556, |
| 27305 |
'c': 500, |
| 27306 |
'd': 556, |
| 27307 |
'e': 556, |
| 27308 |
'f': 278, |
| 27309 |
'g': 556, |
| 27310 |
'h': 556, |
| 27311 |
'i': 222, |
| 27312 |
'j': 222, |
| 27313 |
'k': 500, |
| 27314 |
'l': 222, |
| 27315 |
'm': 833, |
| 27316 |
'n': 556, |
| 27317 |
'o': 556, |
| 27318 |
'p': 556, |
| 27319 |
'q': 556, |
| 27320 |
'r': 333, |
| 27321 |
's': 500, |
| 27322 |
't': 278, |
| 27323 |
'u': 556, |
| 27324 |
'v': 500, |
| 27325 |
'w': 722, |
| 27326 |
'x': 500, |
| 27327 |
'y': 500, |
| 27328 |
'z': 500, |
| 27329 |
'braceleft': 334, |
| 27330 |
'bar': 260, |
| 27331 |
'braceright': 334, |
| 27332 |
'asciitilde': 584, |
| 27333 |
'exclamdown': 333, |
| 27334 |
'cent': 556, |
| 27335 |
'sterling': 556, |
| 27336 |
'fraction': 167, |
| 27337 |
'yen': 556, |
| 27338 |
'florin': 556, |
| 27339 |
'section': 556, |
| 27340 |
'currency': 556, |
| 27341 |
'quotesingle': 191, |
| 27342 |
'quotedblleft': 333, |
| 27343 |
'guillemotleft': 556, |
| 27344 |
'guilsinglleft': 333, |
| 27345 |
'guilsinglright': 333, |
| 27346 |
'fi': 500, |
| 27347 |
'fl': 500, |
| 27348 |
'endash': 556, |
| 27349 |
'dagger': 556, |
| 27350 |
'daggerdbl': 556, |
| 27351 |
'periodcentered': 278, |
| 27352 |
'paragraph': 537, |
| 27353 |
'bullet': 350, |
| 27354 |
'quotesinglbase': 222, |
| 27355 |
'quotedblbase': 333, |
| 27356 |
'quotedblright': 333, |
| 27357 |
'guillemotright': 556, |
| 27358 |
'ellipsis': 1000, |
| 27359 |
'perthousand': 1000, |
| 27360 |
'questiondown': 611, |
| 27361 |
'grave': 333, |
| 27362 |
'acute': 333, |
| 27363 |
'circumflex': 333, |
| 27364 |
'tilde': 333, |
| 27365 |
'macron': 333, |
| 27366 |
'breve': 333, |
| 27367 |
'dotaccent': 333, |
| 27368 |
'dieresis': 333, |
| 27369 |
'ring': 333, |
| 27370 |
'cedilla': 333, |
| 27371 |
'hungarumlaut': 333, |
| 27372 |
'ogonek': 333, |
| 27373 |
'caron': 333, |
| 27374 |
'emdash': 1000, |
| 27375 |
'AE': 1000, |
| 27376 |
'ordfeminine': 370, |
| 27377 |
'Lslash': 556, |
| 27378 |
'Oslash': 778, |
| 27379 |
'OE': 1000, |
| 27380 |
'ordmasculine': 365, |
| 27381 |
'ae': 889, |
| 27382 |
'dotlessi': 278, |
| 27383 |
'lslash': 222, |
| 27384 |
'oslash': 611, |
| 27385 |
'oe': 944, |
| 27386 |
'germandbls': 611, |
| 27387 |
'Idieresis': 278, |
| 27388 |
'eacute': 556, |
| 27389 |
'abreve': 556, |
| 27390 |
'uhungarumlaut': 556, |
| 27391 |
'ecaron': 556, |
| 27392 |
'Ydieresis': 667, |
| 27393 |
'divide': 584, |
| 27394 |
'Yacute': 667, |
| 27395 |
'Acircumflex': 667, |
| 27396 |
'aacute': 556, |
| 27397 |
'Ucircumflex': 722, |
| 27398 |
'yacute': 500, |
| 27399 |
'scommaaccent': 500, |
| 27400 |
'ecircumflex': 556, |
| 27401 |
'Uring': 722, |
| 27402 |
'Udieresis': 722, |
| 27403 |
'aogonek': 556, |
| 27404 |
'Uacute': 722, |
| 27405 |
'uogonek': 556, |
| 27406 |
'Edieresis': 667, |
| 27407 |
'Dcroat': 722, |
| 27408 |
'commaaccent': 250, |
| 27409 |
'copyright': 737, |
| 27410 |
'Emacron': 667, |
| 27411 |
'ccaron': 500, |
| 27412 |
'aring': 556, |
| 27413 |
'Ncommaaccent': 722, |
| 27414 |
'lacute': 222, |
| 27415 |
'agrave': 556, |
| 27416 |
'Tcommaaccent': 611, |
| 27417 |
'Cacute': 722, |
| 27418 |
'atilde': 556, |
| 27419 |
'Edotaccent': 667, |
| 27420 |
'scaron': 500, |
| 27421 |
'scedilla': 500, |
| 27422 |
'iacute': 278, |
| 27423 |
'lozenge': 471, |
| 27424 |
'Rcaron': 722, |
| 27425 |
'Gcommaaccent': 778, |
| 27426 |
'ucircumflex': 556, |
| 27427 |
'acircumflex': 556, |
| 27428 |
'Amacron': 667, |
| 27429 |
'rcaron': 333, |
| 27430 |
'ccedilla': 500, |
| 27431 |
'Zdotaccent': 611, |
| 27432 |
'Thorn': 667, |
| 27433 |
'Omacron': 778, |
| 27434 |
'Racute': 722, |
| 27435 |
'Sacute': 667, |
| 27436 |
'dcaron': 643, |
| 27437 |
'Umacron': 722, |
| 27438 |
'uring': 556, |
| 27439 |
'threesuperior': 333, |
| 27440 |
'Ograve': 778, |
| 27441 |
'Agrave': 667, |
| 27442 |
'Abreve': 667, |
| 27443 |
'multiply': 584, |
| 27444 |
'uacute': 556, |
| 27445 |
'Tcaron': 611, |
| 27446 |
'partialdiff': 476, |
| 27447 |
'ydieresis': 500, |
| 27448 |
'Nacute': 722, |
| 27449 |
'icircumflex': 278, |
| 27450 |
'Ecircumflex': 667, |
| 27451 |
'adieresis': 556, |
| 27452 |
'edieresis': 556, |
| 27453 |
'cacute': 500, |
| 27454 |
'nacute': 556, |
| 27455 |
'umacron': 556, |
| 27456 |
'Ncaron': 722, |
| 27457 |
'Iacute': 278, |
| 27458 |
'plusminus': 584, |
| 27459 |
'brokenbar': 260, |
| 27460 |
'registered': 737, |
| 27461 |
'Gbreve': 778, |
| 27462 |
'Idotaccent': 278, |
| 27463 |
'summation': 600, |
| 27464 |
'Egrave': 667, |
| 27465 |
'racute': 333, |
| 27466 |
'omacron': 556, |
| 27467 |
'Zacute': 611, |
| 27468 |
'Zcaron': 611, |
| 27469 |
'greaterequal': 549, |
| 27470 |
'Eth': 722, |
| 27471 |
'Ccedilla': 722, |
| 27472 |
'lcommaaccent': 222, |
| 27473 |
'tcaron': 317, |
| 27474 |
'eogonek': 556, |
| 27475 |
'Uogonek': 722, |
| 27476 |
'Aacute': 667, |
| 27477 |
'Adieresis': 667, |
| 27478 |
'egrave': 556, |
| 27479 |
'zacute': 500, |
| 27480 |
'iogonek': 222, |
| 27481 |
'Oacute': 778, |
| 27482 |
'oacute': 556, |
| 27483 |
'amacron': 556, |
| 27484 |
'sacute': 500, |
| 27485 |
'idieresis': 278, |
| 27486 |
'Ocircumflex': 778, |
| 27487 |
'Ugrave': 722, |
| 27488 |
'Delta': 612, |
| 27489 |
'thorn': 556, |
| 27490 |
'twosuperior': 333, |
| 27491 |
'Odieresis': 778, |
| 27492 |
'mu': 556, |
| 27493 |
'igrave': 278, |
| 27494 |
'ohungarumlaut': 556, |
| 27495 |
'Eogonek': 667, |
| 27496 |
'dcroat': 556, |
| 27497 |
'threequarters': 834, |
| 27498 |
'Scedilla': 667, |
| 27499 |
'lcaron': 299, |
| 27500 |
'Kcommaaccent': 667, |
| 27501 |
'Lacute': 556, |
| 27502 |
'trademark': 1000, |
| 27503 |
'edotaccent': 556, |
| 27504 |
'Igrave': 278, |
| 27505 |
'Imacron': 278, |
| 27506 |
'Lcaron': 556, |
| 27507 |
'onehalf': 834, |
| 27508 |
'lessequal': 549, |
| 27509 |
'ocircumflex': 556, |
| 27510 |
'ntilde': 556, |
| 27511 |
'Uhungarumlaut': 722, |
| 27512 |
'Eacute': 667, |
| 27513 |
'emacron': 556, |
| 27514 |
'gbreve': 556, |
| 27515 |
'onequarter': 834, |
| 27516 |
'Scaron': 667, |
| 27517 |
'Scommaaccent': 667, |
| 27518 |
'Ohungarumlaut': 778, |
| 27519 |
'degree': 400, |
| 27520 |
'ograve': 556, |
| 27521 |
'Ccaron': 722, |
| 27522 |
'ugrave': 556, |
| 27523 |
'radical': 453, |
| 27524 |
'Dcaron': 722, |
| 27525 |
'rcommaaccent': 333, |
| 27526 |
'Ntilde': 722, |
| 27527 |
'otilde': 556, |
| 27528 |
'Rcommaaccent': 722, |
| 27529 |
'Lcommaaccent': 556, |
| 27530 |
'Atilde': 667, |
| 27531 |
'Aogonek': 667, |
| 27532 |
'Aring': 667, |
| 27533 |
'Otilde': 778, |
| 27534 |
'zdotaccent': 500, |
| 27535 |
'Ecaron': 667, |
| 27536 |
'Iogonek': 278, |
| 27537 |
'kcommaaccent': 500, |
| 27538 |
'minus': 584, |
| 27539 |
'Icircumflex': 278, |
| 27540 |
'ncaron': 556, |
| 27541 |
'tcommaaccent': 278, |
| 27542 |
'logicalnot': 584, |
| 27543 |
'odieresis': 556, |
| 27544 |
'udieresis': 556, |
| 27545 |
'notequal': 549, |
| 27546 |
'gcommaaccent': 556, |
| 27547 |
'eth': 556, |
| 27548 |
'zcaron': 500, |
| 27549 |
'ncommaaccent': 556, |
| 27550 |
'onesuperior': 333, |
| 27551 |
'imacron': 278, |
| 27552 |
'Euro': 556 |
| 27553 |
}, |
| 27554 |
'Helvetica-Bold': { |
| 27555 |
'space': 278, |
| 27556 |
'exclam': 333, |
| 27557 |
'quotedbl': 474, |
| 27558 |
'numbersign': 556, |
| 27559 |
'dollar': 556, |
| 27560 |
'percent': 889, |
| 27561 |
'ampersand': 722, |
| 27562 |
'quoteright': 278, |
| 27563 |
'parenleft': 333, |
| 27564 |
'parenright': 333, |
| 27565 |
'asterisk': 389, |
| 27566 |
'plus': 584, |
| 27567 |
'comma': 278, |
| 27568 |
'hyphen': 333, |
| 27569 |
'period': 278, |
| 27570 |
'slash': 278, |
| 27571 |
'zero': 556, |
| 27572 |
'one': 556, |
| 27573 |
'two': 556, |
| 27574 |
'three': 556, |
| 27575 |
'four': 556, |
| 27576 |
'five': 556, |
| 27577 |
'six': 556, |
| 27578 |
'seven': 556, |
| 27579 |
'eight': 556, |
| 27580 |
'nine': 556, |
| 27581 |
'colon': 333, |
| 27582 |
'semicolon': 333, |
| 27583 |
'less': 584, |
| 27584 |
'equal': 584, |
| 27585 |
'greater': 584, |
| 27586 |
'question': 611, |
| 27587 |
'at': 975, |
| 27588 |
'A': 722, |
| 27589 |
'B': 722, |
| 27590 |
'C': 722, |
| 27591 |
'D': 722, |
| 27592 |
'E': 667, |
| 27593 |
'F': 611, |
| 27594 |
'G': 778, |
| 27595 |
'H': 722, |
| 27596 |
'I': 278, |
| 27597 |
'J': 556, |
| 27598 |
'K': 722, |
| 27599 |
'L': 611, |
| 27600 |
'M': 833, |
| 27601 |
'N': 722, |
| 27602 |
'O': 778, |
| 27603 |
'P': 667, |
| 27604 |
'Q': 778, |
| 27605 |
'R': 722, |
| 27606 |
'S': 667, |
| 27607 |
'T': 611, |
| 27608 |
'U': 722, |
| 27609 |
'V': 667, |
| 27610 |
'W': 944, |
| 27611 |
'X': 667, |
| 27612 |
'Y': 667, |
| 27613 |
'Z': 611, |
| 27614 |
'bracketleft': 333, |
| 27615 |
'backslash': 278, |
| 27616 |
'bracketright': 333, |
| 27617 |
'asciicircum': 584, |
| 27618 |
'underscore': 556, |
| 27619 |
'quoteleft': 278, |
| 27620 |
'a': 556, |
| 27621 |
'b': 611, |
| 27622 |
'c': 556, |
| 27623 |
'd': 611, |
| 27624 |
'e': 556, |
| 27625 |
'f': 333, |
| 27626 |
'g': 611, |
| 27627 |
'h': 611, |
| 27628 |
'i': 278, |
| 27629 |
'j': 278, |
| 27630 |
'k': 556, |
| 27631 |
'l': 278, |
| 27632 |
'm': 889, |
| 27633 |
'n': 611, |
| 27634 |
'o': 611, |
| 27635 |
'p': 611, |
| 27636 |
'q': 611, |
| 27637 |
'r': 389, |
| 27638 |
's': 556, |
| 27639 |
't': 333, |
| 27640 |
'u': 611, |
| 27641 |
'v': 556, |
| 27642 |
'w': 778, |
| 27643 |
'x': 556, |
| 27644 |
'y': 556, |
| 27645 |
'z': 500, |
| 27646 |
'braceleft': 389, |
| 27647 |
'bar': 280, |
| 27648 |
'braceright': 389, |
| 27649 |
'asciitilde': 584, |
| 27650 |
'exclamdown': 333, |
| 27651 |
'cent': 556, |
| 27652 |
'sterling': 556, |
| 27653 |
'fraction': 167, |
| 27654 |
'yen': 556, |
| 27655 |
'florin': 556, |
| 27656 |
'section': 556, |
| 27657 |
'currency': 556, |
| 27658 |
'quotesingle': 238, |
| 27659 |
'quotedblleft': 500, |
| 27660 |
'guillemotleft': 556, |
| 27661 |
'guilsinglleft': 333, |
| 27662 |
'guilsinglright': 333, |
| 27663 |
'fi': 611, |
| 27664 |
'fl': 611, |
| 27665 |
'endash': 556, |
| 27666 |
'dagger': 556, |
| 27667 |
'daggerdbl': 556, |
| 27668 |
'periodcentered': 278, |
| 27669 |
'paragraph': 556, |
| 27670 |
'bullet': 350, |
| 27671 |
'quotesinglbase': 278, |
| 27672 |
'quotedblbase': 500, |
| 27673 |
'quotedblright': 500, |
| 27674 |
'guillemotright': 556, |
| 27675 |
'ellipsis': 1000, |
| 27676 |
'perthousand': 1000, |
| 27677 |
'questiondown': 611, |
| 27678 |
'grave': 333, |
| 27679 |
'acute': 333, |
| 27680 |
'circumflex': 333, |
| 27681 |
'tilde': 333, |
| 27682 |
'macron': 333, |
| 27683 |
'breve': 333, |
| 27684 |
'dotaccent': 333, |
| 27685 |
'dieresis': 333, |
| 27686 |
'ring': 333, |
| 27687 |
'cedilla': 333, |
| 27688 |
'hungarumlaut': 333, |
| 27689 |
'ogonek': 333, |
| 27690 |
'caron': 333, |
| 27691 |
'emdash': 1000, |
| 27692 |
'AE': 1000, |
| 27693 |
'ordfeminine': 370, |
| 27694 |
'Lslash': 611, |
| 27695 |
'Oslash': 778, |
| 27696 |
'OE': 1000, |
| 27697 |
'ordmasculine': 365, |
| 27698 |
'ae': 889, |
| 27699 |
'dotlessi': 278, |
| 27700 |
'lslash': 278, |
| 27701 |
'oslash': 611, |
| 27702 |
'oe': 944, |
| 27703 |
'germandbls': 611, |
| 27704 |
'Idieresis': 278, |
| 27705 |
'eacute': 556, |
| 27706 |
'abreve': 556, |
| 27707 |
'uhungarumlaut': 611, |
| 27708 |
'ecaron': 556, |
| 27709 |
'Ydieresis': 667, |
| 27710 |
'divide': 584, |
| 27711 |
'Yacute': 667, |
| 27712 |
'Acircumflex': 722, |
| 27713 |
'aacute': 556, |
| 27714 |
'Ucircumflex': 722, |
| 27715 |
'yacute': 556, |
| 27716 |
'scommaaccent': 556, |
| 27717 |
'ecircumflex': 556, |
| 27718 |
'Uring': 722, |
| 27719 |
'Udieresis': 722, |
| 27720 |
'aogonek': 556, |
| 27721 |
'Uacute': 722, |
| 27722 |
'uogonek': 611, |
| 27723 |
'Edieresis': 667, |
| 27724 |
'Dcroat': 722, |
| 27725 |
'commaaccent': 250, |
| 27726 |
'copyright': 737, |
| 27727 |
'Emacron': 667, |
| 27728 |
'ccaron': 556, |
| 27729 |
'aring': 556, |
| 27730 |
'Ncommaaccent': 722, |
| 27731 |
'lacute': 278, |
| 27732 |
'agrave': 556, |
| 27733 |
'Tcommaaccent': 611, |
| 27734 |
'Cacute': 722, |
| 27735 |
'atilde': 556, |
| 27736 |
'Edotaccent': 667, |
| 27737 |
'scaron': 556, |
| 27738 |
'scedilla': 556, |
| 27739 |
'iacute': 278, |
| 27740 |
'lozenge': 494, |
| 27741 |
'Rcaron': 722, |
| 27742 |
'Gcommaaccent': 778, |
| 27743 |
'ucircumflex': 611, |
| 27744 |
'acircumflex': 556, |
| 27745 |
'Amacron': 722, |
| 27746 |
'rcaron': 389, |
| 27747 |
'ccedilla': 556, |
| 27748 |
'Zdotaccent': 611, |
| 27749 |
'Thorn': 667, |
| 27750 |
'Omacron': 778, |
| 27751 |
'Racute': 722, |
| 27752 |
'Sacute': 667, |
| 27753 |
'dcaron': 743, |
| 27754 |
'Umacron': 722, |
| 27755 |
'uring': 611, |
| 27756 |
'threesuperior': 333, |
| 27757 |
'Ograve': 778, |
| 27758 |
'Agrave': 722, |
| 27759 |
'Abreve': 722, |
| 27760 |
'multiply': 584, |
| 27761 |
'uacute': 611, |
| 27762 |
'Tcaron': 611, |
| 27763 |
'partialdiff': 494, |
| 27764 |
'ydieresis': 556, |
| 27765 |
'Nacute': 722, |
| 27766 |
'icircumflex': 278, |
| 27767 |
'Ecircumflex': 667, |
| 27768 |
'adieresis': 556, |
| 27769 |
'edieresis': 556, |
| 27770 |
'cacute': 556, |
| 27771 |
'nacute': 611, |
| 27772 |
'umacron': 611, |
| 27773 |
'Ncaron': 722, |
| 27774 |
'Iacute': 278, |
| 27775 |
'plusminus': 584, |
| 27776 |
'brokenbar': 280, |
| 27777 |
'registered': 737, |
| 27778 |
'Gbreve': 778, |
| 27779 |
'Idotaccent': 278, |
| 27780 |
'summation': 600, |
| 27781 |
'Egrave': 667, |
| 27782 |
'racute': 389, |
| 27783 |
'omacron': 611, |
| 27784 |
'Zacute': 611, |
| 27785 |
'Zcaron': 611, |
| 27786 |
'greaterequal': 549, |
| 27787 |
'Eth': 722, |
| 27788 |
'Ccedilla': 722, |
| 27789 |
'lcommaaccent': 278, |
| 27790 |
'tcaron': 389, |
| 27791 |
'eogonek': 556, |
| 27792 |
'Uogonek': 722, |
| 27793 |
'Aacute': 722, |
| 27794 |
'Adieresis': 722, |
| 27795 |
'egrave': 556, |
| 27796 |
'zacute': 500, |
| 27797 |
'iogonek': 278, |
| 27798 |
'Oacute': 778, |
| 27799 |
'oacute': 611, |
| 27800 |
'amacron': 556, |
| 27801 |
'sacute': 556, |
| 27802 |
'idieresis': 278, |
| 27803 |
'Ocircumflex': 778, |
| 27804 |
'Ugrave': 722, |
| 27805 |
'Delta': 612, |
| 27806 |
'thorn': 611, |
| 27807 |
'twosuperior': 333, |
| 27808 |
'Odieresis': 778, |
| 27809 |
'mu': 611, |
| 27810 |
'igrave': 278, |
| 27811 |
'ohungarumlaut': 611, |
| 27812 |
'Eogonek': 667, |
| 27813 |
'dcroat': 611, |
| 27814 |
'threequarters': 834, |
| 27815 |
'Scedilla': 667, |
| 27816 |
'lcaron': 400, |
| 27817 |
'Kcommaaccent': 722, |
| 27818 |
'Lacute': 611, |
| 27819 |
'trademark': 1000, |
| 27820 |
'edotaccent': 556, |
| 27821 |
'Igrave': 278, |
| 27822 |
'Imacron': 278, |
| 27823 |
'Lcaron': 611, |
| 27824 |
'onehalf': 834, |
| 27825 |
'lessequal': 549, |
| 27826 |
'ocircumflex': 611, |
| 27827 |
'ntilde': 611, |
| 27828 |
'Uhungarumlaut': 722, |
| 27829 |
'Eacute': 667, |
| 27830 |
'emacron': 556, |
| 27831 |
'gbreve': 611, |
| 27832 |
'onequarter': 834, |
| 27833 |
'Scaron': 667, |
| 27834 |
'Scommaaccent': 667, |
| 27835 |
'Ohungarumlaut': 778, |
| 27836 |
'degree': 400, |
| 27837 |
'ograve': 611, |
| 27838 |
'Ccaron': 722, |
| 27839 |
'ugrave': 611, |
| 27840 |
'radical': 549, |
| 27841 |
'Dcaron': 722, |
| 27842 |
'rcommaaccent': 389, |
| 27843 |
'Ntilde': 722, |
| 27844 |
'otilde': 611, |
| 27845 |
'Rcommaaccent': 722, |
| 27846 |
'Lcommaaccent': 611, |
| 27847 |
'Atilde': 722, |
| 27848 |
'Aogonek': 722, |
| 27849 |
'Aring': 722, |
| 27850 |
'Otilde': 778, |
| 27851 |
'zdotaccent': 500, |
| 27852 |
'Ecaron': 667, |
| 27853 |
'Iogonek': 278, |
| 27854 |
'kcommaaccent': 556, |
| 27855 |
'minus': 584, |
| 27856 |
'Icircumflex': 278, |
| 27857 |
'ncaron': 611, |
| 27858 |
'tcommaaccent': 333, |
| 27859 |
'logicalnot': 584, |
| 27860 |
'odieresis': 611, |
| 27861 |
'udieresis': 611, |
| 27862 |
'notequal': 549, |
| 27863 |
'gcommaaccent': 611, |
| 27864 |
'eth': 611, |
| 27865 |
'zcaron': 500, |
| 27866 |
'ncommaaccent': 611, |
| 27867 |
'onesuperior': 333, |
| 27868 |
'imacron': 278, |
| 27869 |
'Euro': 556 |
| 27870 |
}, |
| 27871 |
'Helvetica-BoldOblique': { |
| 27872 |
'space': 278, |
| 27873 |
'exclam': 333, |
| 27874 |
'quotedbl': 474, |
| 27875 |
'numbersign': 556, |
| 27876 |
'dollar': 556, |
| 27877 |
'percent': 889, |
| 27878 |
'ampersand': 722, |
| 27879 |
'quoteright': 278, |
| 27880 |
'parenleft': 333, |
| 27881 |
'parenright': 333, |
| 27882 |
'asterisk': 389, |
| 27883 |
'plus': 584, |
| 27884 |
'comma': 278, |
| 27885 |
'hyphen': 333, |
| 27886 |
'period': 278, |
| 27887 |
'slash': 278, |
| 27888 |
'zero': 556, |
| 27889 |
'one': 556, |
| 27890 |
'two': 556, |
| 27891 |
'three': 556, |
| 27892 |
'four': 556, |
| 27893 |
'five': 556, |
| 27894 |
'six': 556, |
| 27895 |
'seven': 556, |
| 27896 |
'eight': 556, |
| 27897 |
'nine': 556, |
| 27898 |
'colon': 333, |
| 27899 |
'semicolon': 333, |
| 27900 |
'less': 584, |
| 27901 |
'equal': 584, |
| 27902 |
'greater': 584, |
| 27903 |
'question': 611, |
| 27904 |
'at': 975, |
| 27905 |
'A': 722, |
| 27906 |
'B': 722, |
| 27907 |
'C': 722, |
| 27908 |
'D': 722, |
| 27909 |
'E': 667, |
| 27910 |
'F': 611, |
| 27911 |
'G': 778, |
| 27912 |
'H': 722, |
| 27913 |
'I': 278, |
| 27914 |
'J': 556, |
| 27915 |
'K': 722, |
| 27916 |
'L': 611, |
| 27917 |
'M': 833, |
| 27918 |
'N': 722, |
| 27919 |
'O': 778, |
| 27920 |
'P': 667, |
| 27921 |
'Q': 778, |
| 27922 |
'R': 722, |
| 27923 |
'S': 667, |
| 27924 |
'T': 611, |
| 27925 |
'U': 722, |
| 27926 |
'V': 667, |
| 27927 |
'W': 944, |
| 27928 |
'X': 667, |
| 27929 |
'Y': 667, |
| 27930 |
'Z': 611, |
| 27931 |
'bracketleft': 333, |
| 27932 |
'backslash': 278, |
| 27933 |
'bracketright': 333, |
| 27934 |
'asciicircum': 584, |
| 27935 |
'underscore': 556, |
| 27936 |
'quoteleft': 278, |
| 27937 |
'a': 556, |
| 27938 |
'b': 611, |
| 27939 |
'c': 556, |
| 27940 |
'd': 611, |
| 27941 |
'e': 556, |
| 27942 |
'f': 333, |
| 27943 |
'g': 611, |
| 27944 |
'h': 611, |
| 27945 |
'i': 278, |
| 27946 |
'j': 278, |
| 27947 |
'k': 556, |
| 27948 |
'l': 278, |
| 27949 |
'm': 889, |
| 27950 |
'n': 611, |
| 27951 |
'o': 611, |
| 27952 |
'p': 611, |
| 27953 |
'q': 611, |
| 27954 |
'r': 389, |
| 27955 |
's': 556, |
| 27956 |
't': 333, |
| 27957 |
'u': 611, |
| 27958 |
'v': 556, |
| 27959 |
'w': 778, |
| 27960 |
'x': 556, |
| 27961 |
'y': 556, |
| 27962 |
'z': 500, |
| 27963 |
'braceleft': 389, |
| 27964 |
'bar': 280, |
| 27965 |
'braceright': 389, |
| 27966 |
'asciitilde': 584, |
| 27967 |
'exclamdown': 333, |
| 27968 |
'cent': 556, |
| 27969 |
'sterling': 556, |
| 27970 |
'fraction': 167, |
| 27971 |
'yen': 556, |
| 27972 |
'florin': 556, |
| 27973 |
'section': 556, |
| 27974 |
'currency': 556, |
| 27975 |
'quotesingle': 238, |
| 27976 |
'quotedblleft': 500, |
| 27977 |
'guillemotleft': 556, |
| 27978 |
'guilsinglleft': 333, |
| 27979 |
'guilsinglright': 333, |
| 27980 |
'fi': 611, |
| 27981 |
'fl': 611, |
| 27982 |
'endash': 556, |
| 27983 |
'dagger': 556, |
| 27984 |
'daggerdbl': 556, |
| 27985 |
'periodcentered': 278, |
| 27986 |
'paragraph': 556, |
| 27987 |
'bullet': 350, |
| 27988 |
'quotesinglbase': 278, |
| 27989 |
'quotedblbase': 500, |
| 27990 |
'quotedblright': 500, |
| 27991 |
'guillemotright': 556, |
| 27992 |
'ellipsis': 1000, |
| 27993 |
'perthousand': 1000, |
| 27994 |
'questiondown': 611, |
| 27995 |
'grave': 333, |
| 27996 |
'acute': 333, |
| 27997 |
'circumflex': 333, |
| 27998 |
'tilde': 333, |
| 27999 |
'macron': 333, |
| 28000 |
'breve': 333, |
| 28001 |
'dotaccent': 333, |
| 28002 |
'dieresis': 333, |
| 28003 |
'ring': 333, |
| 28004 |
'cedilla': 333, |
| 28005 |
'hungarumlaut': 333, |
| 28006 |
'ogonek': 333, |
| 28007 |
'caron': 333, |
| 28008 |
'emdash': 1000, |
| 28009 |
'AE': 1000, |
| 28010 |
'ordfeminine': 370, |
| 28011 |
'Lslash': 611, |
| 28012 |
'Oslash': 778, |
| 28013 |
'OE': 1000, |
| 28014 |
'ordmasculine': 365, |
| 28015 |
'ae': 889, |
| 28016 |
'dotlessi': 278, |
| 28017 |
'lslash': 278, |
| 28018 |
'oslash': 611, |
| 28019 |
'oe': 944, |
| 28020 |
'germandbls': 611, |
| 28021 |
'Idieresis': 278, |
| 28022 |
'eacute': 556, |
| 28023 |
'abreve': 556, |
| 28024 |
'uhungarumlaut': 611, |
| 28025 |
'ecaron': 556, |
| 28026 |
'Ydieresis': 667, |
| 28027 |
'divide': 584, |
| 28028 |
'Yacute': 667, |
| 28029 |
'Acircumflex': 722, |
| 28030 |
'aacute': 556, |
| 28031 |
'Ucircumflex': 722, |
| 28032 |
'yacute': 556, |
| 28033 |
'scommaaccent': 556, |
| 28034 |
'ecircumflex': 556, |
| 28035 |
'Uring': 722, |
| 28036 |
'Udieresis': 722, |
| 28037 |
'aogonek': 556, |
| 28038 |
'Uacute': 722, |
| 28039 |
'uogonek': 611, |
| 28040 |
'Edieresis': 667, |
| 28041 |
'Dcroat': 722, |
| 28042 |
'commaaccent': 250, |
| 28043 |
'copyright': 737, |
| 28044 |
'Emacron': 667, |
| 28045 |
'ccaron': 556, |
| 28046 |
'aring': 556, |
| 28047 |
'Ncommaaccent': 722, |
| 28048 |
'lacute': 278, |
| 28049 |
'agrave': 556, |
| 28050 |
'Tcommaaccent': 611, |
| 28051 |
'Cacute': 722, |
| 28052 |
'atilde': 556, |
| 28053 |
'Edotaccent': 667, |
| 28054 |
'scaron': 556, |
| 28055 |
'scedilla': 556, |
| 28056 |
'iacute': 278, |
| 28057 |
'lozenge': 494, |
| 28058 |
'Rcaron': 722, |
| 28059 |
'Gcommaaccent': 778, |
| 28060 |
'ucircumflex': 611, |
| 28061 |
'acircumflex': 556, |
| 28062 |
'Amacron': 722, |
| 28063 |
'rcaron': 389, |
| 28064 |
'ccedilla': 556, |
| 28065 |
'Zdotaccent': 611, |
| 28066 |
'Thorn': 667, |
| 28067 |
'Omacron': 778, |
| 28068 |
'Racute': 722, |
| 28069 |
'Sacute': 667, |
| 28070 |
'dcaron': 743, |
| 28071 |
'Umacron': 722, |
| 28072 |
'uring': 611, |
| 28073 |
'threesuperior': 333, |
| 28074 |
'Ograve': 778, |
| 28075 |
'Agrave': 722, |
| 28076 |
'Abreve': 722, |
| 28077 |
'multiply': 584, |
| 28078 |
'uacute': 611, |
| 28079 |
'Tcaron': 611, |
| 28080 |
'partialdiff': 494, |
| 28081 |
'ydieresis': 556, |
| 28082 |
'Nacute': 722, |
| 28083 |
'icircumflex': 278, |
| 28084 |
'Ecircumflex': 667, |
| 28085 |
'adieresis': 556, |
| 28086 |
'edieresis': 556, |
| 28087 |
'cacute': 556, |
| 28088 |
'nacute': 611, |
| 28089 |
'umacron': 611, |
| 28090 |
'Ncaron': 722, |
| 28091 |
'Iacute': 278, |
| 28092 |
'plusminus': 584, |
| 28093 |
'brokenbar': 280, |
| 28094 |
'registered': 737, |
| 28095 |
'Gbreve': 778, |
| 28096 |
'Idotaccent': 278, |
| 28097 |
'summation': 600, |
| 28098 |
'Egrave': 667, |
| 28099 |
'racute': 389, |
| 28100 |
'omacron': 611, |
| 28101 |
'Zacute': 611, |
| 28102 |
'Zcaron': 611, |
| 28103 |
'greaterequal': 549, |
| 28104 |
'Eth': 722, |
| 28105 |
'Ccedilla': 722, |
| 28106 |
'lcommaaccent': 278, |
| 28107 |
'tcaron': 389, |
| 28108 |
'eogonek': 556, |
| 28109 |
'Uogonek': 722, |
| 28110 |
'Aacute': 722, |
| 28111 |
'Adieresis': 722, |
| 28112 |
'egrave': 556, |
| 28113 |
'zacute': 500, |
| 28114 |
'iogonek': 278, |
| 28115 |
'Oacute': 778, |
| 28116 |
'oacute': 611, |
| 28117 |
'amacron': 556, |
| 28118 |
'sacute': 556, |
| 28119 |
'idieresis': 278, |
| 28120 |
'Ocircumflex': 778, |
| 28121 |
'Ugrave': 722, |
| 28122 |
'Delta': 612, |
| 28123 |
'thorn': 611, |
| 28124 |
'twosuperior': 333, |
| 28125 |
'Odieresis': 778, |
| 28126 |
'mu': 611, |
| 28127 |
'igrave': 278, |
| 28128 |
'ohungarumlaut': 611, |
| 28129 |
'Eogonek': 667, |
| 28130 |
'dcroat': 611, |
| 28131 |
'threequarters': 834, |
| 28132 |
'Scedilla': 667, |
| 28133 |
'lcaron': 400, |
| 28134 |
'Kcommaaccent': 722, |
| 28135 |
'Lacute': 611, |
| 28136 |
'trademark': 1000, |
| 28137 |
'edotaccent': 556, |
| 28138 |
'Igrave': 278, |
| 28139 |
'Imacron': 278, |
| 28140 |
'Lcaron': 611, |
| 28141 |
'onehalf': 834, |
| 28142 |
'lessequal': 549, |
| 28143 |
'ocircumflex': 611, |
| 28144 |
'ntilde': 611, |
| 28145 |
'Uhungarumlaut': 722, |
| 28146 |
'Eacute': 667, |
| 28147 |
'emacron': 556, |
| 28148 |
'gbreve': 611, |
| 28149 |
'onequarter': 834, |
| 28150 |
'Scaron': 667, |
| 28151 |
'Scommaaccent': 667, |
| 28152 |
'Ohungarumlaut': 778, |
| 28153 |
'degree': 400, |
| 28154 |
'ograve': 611, |
| 28155 |
'Ccaron': 722, |
| 28156 |
'ugrave': 611, |
| 28157 |
'radical': 549, |
| 28158 |
'Dcaron': 722, |
| 28159 |
'rcommaaccent': 389, |
| 28160 |
'Ntilde': 722, |
| 28161 |
'otilde': 611, |
| 28162 |
'Rcommaaccent': 722, |
| 28163 |
'Lcommaaccent': 611, |
| 28164 |
'Atilde': 722, |
| 28165 |
'Aogonek': 722, |
| 28166 |
'Aring': 722, |
| 28167 |
'Otilde': 778, |
| 28168 |
'zdotaccent': 500, |
| 28169 |
'Ecaron': 667, |
| 28170 |
'Iogonek': 278, |
| 28171 |
'kcommaaccent': 556, |
| 28172 |
'minus': 584, |
| 28173 |
'Icircumflex': 278, |
| 28174 |
'ncaron': 611, |
| 28175 |
'tcommaaccent': 333, |
| 28176 |
'logicalnot': 584, |
| 28177 |
'odieresis': 611, |
| 28178 |
'udieresis': 611, |
| 28179 |
'notequal': 549, |
| 28180 |
'gcommaaccent': 611, |
| 28181 |
'eth': 611, |
| 28182 |
'zcaron': 500, |
| 28183 |
'ncommaaccent': 611, |
| 28184 |
'onesuperior': 333, |
| 28185 |
'imacron': 278, |
| 28186 |
'Euro': 556 |
| 28187 |
}, |
| 28188 |
'Helvetica-Oblique' : { |
| 28189 |
'space': 278, |
| 28190 |
'exclam': 278, |
| 28191 |
'quotedbl': 355, |
| 28192 |
'numbersign': 556, |
| 28193 |
'dollar': 556, |
| 28194 |
'percent': 889, |
| 28195 |
'ampersand': 667, |
| 28196 |
'quoteright': 222, |
| 28197 |
'parenleft': 333, |
| 28198 |
'parenright': 333, |
| 28199 |
'asterisk': 389, |
| 28200 |
'plus': 584, |
| 28201 |
'comma': 278, |
| 28202 |
'hyphen': 333, |
| 28203 |
'period': 278, |
| 28204 |
'slash': 278, |
| 28205 |
'zero': 556, |
| 28206 |
'one': 556, |
| 28207 |
'two': 556, |
| 28208 |
'three': 556, |
| 28209 |
'four': 556, |
| 28210 |
'five': 556, |
| 28211 |
'six': 556, |
| 28212 |
'seven': 556, |
| 28213 |
'eight': 556, |
| 28214 |
'nine': 556, |
| 28215 |
'colon': 278, |
| 28216 |
'semicolon': 278, |
| 28217 |
'less': 584, |
| 28218 |
'equal': 584, |
| 28219 |
'greater': 584, |
| 28220 |
'question': 556, |
| 28221 |
'at': 1015, |
| 28222 |
'A': 667, |
| 28223 |
'B': 667, |
| 28224 |
'C': 722, |
| 28225 |
'D': 722, |
| 28226 |
'E': 667, |
| 28227 |
'F': 611, |
| 28228 |
'G': 778, |
| 28229 |
'H': 722, |
| 28230 |
'I': 278, |
| 28231 |
'J': 500, |
| 28232 |
'K': 667, |
| 28233 |
'L': 556, |
| 28234 |
'M': 833, |
| 28235 |
'N': 722, |
| 28236 |
'O': 778, |
| 28237 |
'P': 667, |
| 28238 |
'Q': 778, |
| 28239 |
'R': 722, |
| 28240 |
'S': 667, |
| 28241 |
'T': 611, |
| 28242 |
'U': 722, |
| 28243 |
'V': 667, |
| 28244 |
'W': 944, |
| 28245 |
'X': 667, |
| 28246 |
'Y': 667, |
| 28247 |
'Z': 611, |
| 28248 |
'bracketleft': 278, |
| 28249 |
'backslash': 278, |
| 28250 |
'bracketright': 278, |
| 28251 |
'asciicircum': 469, |
| 28252 |
'underscore': 556, |
| 28253 |
'quoteleft': 222, |
| 28254 |
'a': 556, |
| 28255 |
'b': 556, |
| 28256 |
'c': 500, |
| 28257 |
'd': 556, |
| 28258 |
'e': 556, |
| 28259 |
'f': 278, |
| 28260 |
'g': 556, |
| 28261 |
'h': 556, |
| 28262 |
'i': 222, |
| 28263 |
'j': 222, |
| 28264 |
'k': 500, |
| 28265 |
'l': 222, |
| 28266 |
'm': 833, |
| 28267 |
'n': 556, |
| 28268 |
'o': 556, |
| 28269 |
'p': 556, |
| 28270 |
'q': 556, |
| 28271 |
'r': 333, |
| 28272 |
's': 500, |
| 28273 |
't': 278, |
| 28274 |
'u': 556, |
| 28275 |
'v': 500, |
| 28276 |
'w': 722, |
| 28277 |
'x': 500, |
| 28278 |
'y': 500, |
| 28279 |
'z': 500, |
| 28280 |
'braceleft': 334, |
| 28281 |
'bar': 260, |
| 28282 |
'braceright': 334, |
| 28283 |
'asciitilde': 584, |
| 28284 |
'exclamdown': 333, |
| 28285 |
'cent': 556, |
| 28286 |
'sterling': 556, |
| 28287 |
'fraction': 167, |
| 28288 |
'yen': 556, |
| 28289 |
'florin': 556, |
| 28290 |
'section': 556, |
| 28291 |
'currency': 556, |
| 28292 |
'quotesingle': 191, |
| 28293 |
'quotedblleft': 333, |
| 28294 |
'guillemotleft': 556, |
| 28295 |
'guilsinglleft': 333, |
| 28296 |
'guilsinglright': 333, |
| 28297 |
'fi': 500, |
| 28298 |
'fl': 500, |
| 28299 |
'endash': 556, |
| 28300 |
'dagger': 556, |
| 28301 |
'daggerdbl': 556, |
| 28302 |
'periodcentered': 278, |
| 28303 |
'paragraph': 537, |
| 28304 |
'bullet': 350, |
| 28305 |
'quotesinglbase': 222, |
| 28306 |
'quotedblbase': 333, |
| 28307 |
'quotedblright': 333, |
| 28308 |
'guillemotright': 556, |
| 28309 |
'ellipsis': 1000, |
| 28310 |
'perthousand': 1000, |
| 28311 |
'questiondown': 611, |
| 28312 |
'grave': 333, |
| 28313 |
'acute': 333, |
| 28314 |
'circumflex': 333, |
| 28315 |
'tilde': 333, |
| 28316 |
'macron': 333, |
| 28317 |
'breve': 333, |
| 28318 |
'dotaccent': 333, |
| 28319 |
'dieresis': 333, |
| 28320 |
'ring': 333, |
| 28321 |
'cedilla': 333, |
| 28322 |
'hungarumlaut': 333, |
| 28323 |
'ogonek': 333, |
| 28324 |
'caron': 333, |
| 28325 |
'emdash': 1000, |
| 28326 |
'AE': 1000, |
| 28327 |
'ordfeminine': 370, |
| 28328 |
'Lslash': 556, |
| 28329 |
'Oslash': 778, |
| 28330 |
'OE': 1000, |
| 28331 |
'ordmasculine': 365, |
| 28332 |
'ae': 889, |
| 28333 |
'dotlessi': 278, |
| 28334 |
'lslash': 222, |
| 28335 |
'oslash': 611, |
| 28336 |
'oe': 944, |
| 28337 |
'germandbls': 611, |
| 28338 |
'Idieresis': 278, |
| 28339 |
'eacute': 556, |
| 28340 |
'abreve': 556, |
| 28341 |
'uhungarumlaut': 556, |
| 28342 |
'ecaron': 556, |
| 28343 |
'Ydieresis': 667, |
| 28344 |
'divide': 584, |
| 28345 |
'Yacute': 667, |
| 28346 |
'Acircumflex': 667, |
| 28347 |
'aacute': 556, |
| 28348 |
'Ucircumflex': 722, |
| 28349 |
'yacute': 500, |
| 28350 |
'scommaaccent': 500, |
| 28351 |
'ecircumflex': 556, |
| 28352 |
'Uring': 722, |
| 28353 |
'Udieresis': 722, |
| 28354 |
'aogonek': 556, |
| 28355 |
'Uacute': 722, |
| 28356 |
'uogonek': 556, |
| 28357 |
'Edieresis': 667, |
| 28358 |
'Dcroat': 722, |
| 28359 |
'commaaccent': 250, |
| 28360 |
'copyright': 737, |
| 28361 |
'Emacron': 667, |
| 28362 |
'ccaron': 500, |
| 28363 |
'aring': 556, |
| 28364 |
'Ncommaaccent': 722, |
| 28365 |
'lacute': 222, |
| 28366 |
'agrave': 556, |
| 28367 |
'Tcommaaccent': 611, |
| 28368 |
'Cacute': 722, |
| 28369 |
'atilde': 556, |
| 28370 |
'Edotaccent': 667, |
| 28371 |
'scaron': 500, |
| 28372 |
'scedilla': 500, |
| 28373 |
'iacute': 278, |
| 28374 |
'lozenge': 471, |
| 28375 |
'Rcaron': 722, |
| 28376 |
'Gcommaaccent': 778, |
| 28377 |
'ucircumflex': 556, |
| 28378 |
'acircumflex': 556, |
| 28379 |
'Amacron': 667, |
| 28380 |
'rcaron': 333, |
| 28381 |
'ccedilla': 500, |
| 28382 |
'Zdotaccent': 611, |
| 28383 |
'Thorn': 667, |
| 28384 |
'Omacron': 778, |
| 28385 |
'Racute': 722, |
| 28386 |
'Sacute': 667, |
| 28387 |
'dcaron': 643, |
| 28388 |
'Umacron': 722, |
| 28389 |
'uring': 556, |
| 28390 |
'threesuperior': 333, |
| 28391 |
'Ograve': 778, |
| 28392 |
'Agrave': 667, |
| 28393 |
'Abreve': 667, |
| 28394 |
'multiply': 584, |
| 28395 |
'uacute': 556, |
| 28396 |
'Tcaron': 611, |
| 28397 |
'partialdiff': 476, |
| 28398 |
'ydieresis': 500, |
| 28399 |
'Nacute': 722, |
| 28400 |
'icircumflex': 278, |
| 28401 |
'Ecircumflex': 667, |
| 28402 |
'adieresis': 556, |
| 28403 |
'edieresis': 556, |
| 28404 |
'cacute': 500, |
| 28405 |
'nacute': 556, |
| 28406 |
'umacron': 556, |
| 28407 |
'Ncaron': 722, |
| 28408 |
'Iacute': 278, |
| 28409 |
'plusminus': 584, |
| 28410 |
'brokenbar': 260, |
| 28411 |
'registered': 737, |
| 28412 |
'Gbreve': 778, |
| 28413 |
'Idotaccent': 278, |
| 28414 |
'summation': 600, |
| 28415 |
'Egrave': 667, |
| 28416 |
'racute': 333, |
| 28417 |
'omacron': 556, |
| 28418 |
'Zacute': 611, |
| 28419 |
'Zcaron': 611, |
| 28420 |
'greaterequal': 549, |
| 28421 |
'Eth': 722, |
| 28422 |
'Ccedilla': 722, |
| 28423 |
'lcommaaccent': 222, |
| 28424 |
'tcaron': 317, |
| 28425 |
'eogonek': 556, |
| 28426 |
'Uogonek': 722, |
| 28427 |
'Aacute': 667, |
| 28428 |
'Adieresis': 667, |
| 28429 |
'egrave': 556, |
| 28430 |
'zacute': 500, |
| 28431 |
'iogonek': 222, |
| 28432 |
'Oacute': 778, |
| 28433 |
'oacute': 556, |
| 28434 |
'amacron': 556, |
| 28435 |
'sacute': 500, |
| 28436 |
'idieresis': 278, |
| 28437 |
'Ocircumflex': 778, |
| 28438 |
'Ugrave': 722, |
| 28439 |
'Delta': 612, |
| 28440 |
'thorn': 556, |
| 28441 |
'twosuperior': 333, |
| 28442 |
'Odieresis': 778, |
| 28443 |
'mu': 556, |
| 28444 |
'igrave': 278, |
| 28445 |
'ohungarumlaut': 556, |
| 28446 |
'Eogonek': 667, |
| 28447 |
'dcroat': 556, |
| 28448 |
'threequarters': 834, |
| 28449 |
'Scedilla': 667, |
| 28450 |
'lcaron': 299, |
| 28451 |
'Kcommaaccent': 667, |
| 28452 |
'Lacute': 556, |
| 28453 |
'trademark': 1000, |
| 28454 |
'edotaccent': 556, |
| 28455 |
'Igrave': 278, |
| 28456 |
'Imacron': 278, |
| 28457 |
'Lcaron': 556, |
| 28458 |
'onehalf': 834, |
| 28459 |
'lessequal': 549, |
| 28460 |
'ocircumflex': 556, |
| 28461 |
'ntilde': 556, |
| 28462 |
'Uhungarumlaut': 722, |
| 28463 |
'Eacute': 667, |
| 28464 |
'emacron': 556, |
| 28465 |
'gbreve': 556, |
| 28466 |
'onequarter': 834, |
| 28467 |
'Scaron': 667, |
| 28468 |
'Scommaaccent': 667, |
| 28469 |
'Ohungarumlaut': 778, |
| 28470 |
'degree': 400, |
| 28471 |
'ograve': 556, |
| 28472 |
'Ccaron': 722, |
| 28473 |
'ugrave': 556, |
| 28474 |
'radical': 453, |
| 28475 |
'Dcaron': 722, |
| 28476 |
'rcommaaccent': 333, |
| 28477 |
'Ntilde': 722, |
| 28478 |
'otilde': 556, |
| 28479 |
'Rcommaaccent': 722, |
| 28480 |
'Lcommaaccent': 556, |
| 28481 |
'Atilde': 667, |
| 28482 |
'Aogonek': 667, |
| 28483 |
'Aring': 667, |
| 28484 |
'Otilde': 778, |
| 28485 |
'zdotaccent': 500, |
| 28486 |
'Ecaron': 667, |
| 28487 |
'Iogonek': 278, |
| 28488 |
'kcommaaccent': 500, |
| 28489 |
'minus': 584, |
| 28490 |
'Icircumflex': 278, |
| 28491 |
'ncaron': 556, |
| 28492 |
'tcommaaccent': 278, |
| 28493 |
'logicalnot': 584, |
| 28494 |
'odieresis': 556, |
| 28495 |
'udieresis': 556, |
| 28496 |
'notequal': 549, |
| 28497 |
'gcommaaccent': 556, |
| 28498 |
'eth': 556, |
| 28499 |
'zcaron': 500, |
| 28500 |
'ncommaaccent': 556, |
| 28501 |
'onesuperior': 333, |
| 28502 |
'imacron': 278, |
| 28503 |
'Euro': 556 |
| 28504 |
}, |
| 28505 |
'Symbol': { |
| 28506 |
'space': 250, |
| 28507 |
'exclam': 333, |
| 28508 |
'universal': 713, |
| 28509 |
'numbersign': 500, |
| 28510 |
'existential': 549, |
| 28511 |
'percent': 833, |
| 28512 |
'ampersand': 778, |
| 28513 |
'suchthat': 439, |
| 28514 |
'parenleft': 333, |
| 28515 |
'parenright': 333, |
| 28516 |
'asteriskmath': 500, |
| 28517 |
'plus': 549, |
| 28518 |
'comma': 250, |
| 28519 |
'minus': 549, |
| 28520 |
'period': 250, |
| 28521 |
'slash': 278, |
| 28522 |
'zero': 500, |
| 28523 |
'one': 500, |
| 28524 |
'two': 500, |
| 28525 |
'three': 500, |
| 28526 |
'four': 500, |
| 28527 |
'five': 500, |
| 28528 |
'six': 500, |
| 28529 |
'seven': 500, |
| 28530 |
'eight': 500, |
| 28531 |
'nine': 500, |
| 28532 |
'colon': 278, |
| 28533 |
'semicolon': 278, |
| 28534 |
'less': 549, |
| 28535 |
'equal': 549, |
| 28536 |
'greater': 549, |
| 28537 |
'question': 444, |
| 28538 |
'congruent': 549, |
| 28539 |
'Alpha': 722, |
| 28540 |
'Beta': 667, |
| 28541 |
'Chi': 722, |
| 28542 |
'Delta': 612, |
| 28543 |
'Epsilon': 611, |
| 28544 |
'Phi': 763, |
| 28545 |
'Gamma': 603, |
| 28546 |
'Eta': 722, |
| 28547 |
'Iota': 333, |
| 28548 |
'theta1': 631, |
| 28549 |
'Kappa': 722, |
| 28550 |
'Lambda': 686, |
| 28551 |
'Mu': 889, |
| 28552 |
'Nu': 722, |
| 28553 |
'Omicron': 722, |
| 28554 |
'Pi': 768, |
| 28555 |
'Theta': 741, |
| 28556 |
'Rho': 556, |
| 28557 |
'Sigma': 592, |
| 28558 |
'Tau': 611, |
| 28559 |
'Upsilon': 690, |
| 28560 |
'sigma1': 439, |
| 28561 |
'Omega': 768, |
| 28562 |
'Xi': 645, |
| 28563 |
'Psi': 795, |
| 28564 |
'Zeta': 611, |
| 28565 |
'bracketleft': 333, |
| 28566 |
'therefore': 863, |
| 28567 |
'bracketright': 333, |
| 28568 |
'perpendicular': 658, |
| 28569 |
'underscore': 500, |
| 28570 |
'radicalex': 500, |
| 28571 |
'alpha': 631, |
| 28572 |
'beta': 549, |
| 28573 |
'chi': 549, |
| 28574 |
'delta': 494, |
| 28575 |
'epsilon': 439, |
| 28576 |
'phi': 521, |
| 28577 |
'gamma': 411, |
| 28578 |
'eta': 603, |
| 28579 |
'iota': 329, |
| 28580 |
'phi1': 603, |
| 28581 |
'kappa': 549, |
| 28582 |
'lambda': 549, |
| 28583 |
'mu': 576, |
| 28584 |
'nu': 521, |
| 28585 |
'omicron': 549, |
| 28586 |
'pi': 549, |
| 28587 |
'theta': 521, |
| 28588 |
'rho': 549, |
| 28589 |
'sigma': 603, |
| 28590 |
'tau': 439, |
| 28591 |
'upsilon': 576, |
| 28592 |
'omega1': 713, |
| 28593 |
'omega': 686, |
| 28594 |
'xi': 493, |
| 28595 |
'psi': 686, |
| 28596 |
'zeta': 494, |
| 28597 |
'braceleft': 480, |
| 28598 |
'bar': 200, |
| 28599 |
'braceright': 480, |
| 28600 |
'similar': 549, |
| 28601 |
'Euro': 750, |
| 28602 |
'Upsilon1': 620, |
| 28603 |
'minute': 247, |
| 28604 |
'lessequal': 549, |
| 28605 |
'fraction': 167, |
| 28606 |
'infinity': 713, |
| 28607 |
'florin': 500, |
| 28608 |
'club': 753, |
| 28609 |
'diamond': 753, |
| 28610 |
'heart': 753, |
| 28611 |
'spade': 753, |
| 28612 |
'arrowboth': 1042, |
| 28613 |
'arrowleft': 987, |
| 28614 |
'arrowup': 603, |
| 28615 |
'arrowright': 987, |
| 28616 |
'arrowdown': 603, |
| 28617 |
'degree': 400, |
| 28618 |
'plusminus': 549, |
| 28619 |
'second': 411, |
| 28620 |
'greaterequal': 549, |
| 28621 |
'multiply': 549, |
| 28622 |
'proportional': 713, |
| 28623 |
'partialdiff': 494, |
| 28624 |
'bullet': 460, |
| 28625 |
'divide': 549, |
| 28626 |
'notequal': 549, |
| 28627 |
'equivalence': 549, |
| 28628 |
'approxequal': 549, |
| 28629 |
'ellipsis': 1000, |
| 28630 |
'arrowvertex': 603, |
| 28631 |
'arrowhorizex': 1000, |
| 28632 |
'carriagereturn': 658, |
| 28633 |
'aleph': 823, |
| 28634 |
'Ifraktur': 686, |
| 28635 |
'Rfraktur': 795, |
| 28636 |
'weierstrass': 987, |
| 28637 |
'circlemultiply': 768, |
| 28638 |
'circleplus': 768, |
| 28639 |
'emptyset': 823, |
| 28640 |
'intersection': 768, |
| 28641 |
'union': 768, |
| 28642 |
'propersuperset': 713, |
| 28643 |
'reflexsuperset': 713, |
| 28644 |
'notsubset': 713, |
| 28645 |
'propersubset': 713, |
| 28646 |
'reflexsubset': 713, |
| 28647 |
'element': 713, |
| 28648 |
'notelement': 713, |
| 28649 |
'angle': 768, |
| 28650 |
'gradient': 713, |
| 28651 |
'registerserif': 790, |
| 28652 |
'copyrightserif': 790, |
| 28653 |
'trademarkserif': 890, |
| 28654 |
'product': 823, |
| 28655 |
'radical': 549, |
| 28656 |
'dotmath': 250, |
| 28657 |
'logicalnot': 713, |
| 28658 |
'logicaland': 603, |
| 28659 |
'logicalor': 603, |
| 28660 |
'arrowdblboth': 1042, |
| 28661 |
'arrowdblleft': 987, |
| 28662 |
'arrowdblup': 603, |
| 28663 |
'arrowdblright': 987, |
| 28664 |
'arrowdbldown': 603, |
| 28665 |
'lozenge': 494, |
| 28666 |
'angleleft': 329, |
| 28667 |
'registersans': 790, |
| 28668 |
'copyrightsans': 790, |
| 28669 |
'trademarksans': 786, |
| 28670 |
'summation': 713, |
| 28671 |
'parenlefttp': 384, |
| 28672 |
'parenleftex': 384, |
| 28673 |
'parenleftbt': 384, |
| 28674 |
'bracketlefttp': 384, |
| 28675 |
'bracketleftex': 384, |
| 28676 |
'bracketleftbt': 384, |
| 28677 |
'bracelefttp': 494, |
| 28678 |
'braceleftmid': 494, |
| 28679 |
'braceleftbt': 494, |
| 28680 |
'braceex': 494, |
| 28681 |
'angleright': 329, |
| 28682 |
'integral': 274, |
| 28683 |
'integraltp': 686, |
| 28684 |
'integralex': 686, |
| 28685 |
'integralbt': 686, |
| 28686 |
'parenrighttp': 384, |
| 28687 |
'parenrightex': 384, |
| 28688 |
'parenrightbt': 384, |
| 28689 |
'bracketrighttp': 384, |
| 28690 |
'bracketrightex': 384, |
| 28691 |
'bracketrightbt': 384, |
| 28692 |
'bracerighttp': 494, |
| 28693 |
'bracerightmid': 494, |
| 28694 |
'bracerightbt': 494, |
| 28695 |
'apple': 790 |
| 28696 |
}, |
| 28697 |
'Times-Roman': { |
| 28698 |
'space': 250, |
| 28699 |
'exclam': 333, |
| 28700 |
'quotedbl': 408, |
| 28701 |
'numbersign': 500, |
| 28702 |
'dollar': 500, |
| 28703 |
'percent': 833, |
| 28704 |
'ampersand': 778, |
| 28705 |
'quoteright': 333, |
| 28706 |
'parenleft': 333, |
| 28707 |
'parenright': 333, |
| 28708 |
'asterisk': 500, |
| 28709 |
'plus': 564, |
| 28710 |
'comma': 250, |
| 28711 |
'hyphen': 333, |
| 28712 |
'period': 250, |
| 28713 |
'slash': 278, |
| 28714 |
'zero': 500, |
| 28715 |
'one': 500, |
| 28716 |
'two': 500, |
| 28717 |
'three': 500, |
| 28718 |
'four': 500, |
| 28719 |
'five': 500, |
| 28720 |
'six': 500, |
| 28721 |
'seven': 500, |
| 28722 |
'eight': 500, |
| 28723 |
'nine': 500, |
| 28724 |
'colon': 278, |
| 28725 |
'semicolon': 278, |
| 28726 |
'less': 564, |
| 28727 |
'equal': 564, |
| 28728 |
'greater': 564, |
| 28729 |
'question': 444, |
| 28730 |
'at': 921, |
| 28731 |
'A': 722, |
| 28732 |
'B': 667, |
| 28733 |
'C': 667, |
| 28734 |
'D': 722, |
| 28735 |
'E': 611, |
| 28736 |
'F': 556, |
| 28737 |
'G': 722, |
| 28738 |
'H': 722, |
| 28739 |
'I': 333, |
| 28740 |
'J': 389, |
| 28741 |
'K': 722, |
| 28742 |
'L': 611, |
| 28743 |
'M': 889, |
| 28744 |
'N': 722, |
| 28745 |
'O': 722, |
| 28746 |
'P': 556, |
| 28747 |
'Q': 722, |
| 28748 |
'R': 667, |
| 28749 |
'S': 556, |
| 28750 |
'T': 611, |
| 28751 |
'U': 722, |
| 28752 |
'V': 722, |
| 28753 |
'W': 944, |
| 28754 |
'X': 722, |
| 28755 |
'Y': 722, |
| 28756 |
'Z': 611, |
| 28757 |
'bracketleft': 333, |
| 28758 |
'backslash': 278, |
| 28759 |
'bracketright': 333, |
| 28760 |
'asciicircum': 469, |
| 28761 |
'underscore': 500, |
| 28762 |
'quoteleft': 333, |
| 28763 |
'a': 444, |
| 28764 |
'b': 500, |
| 28765 |
'c': 444, |
| 28766 |
'd': 500, |
| 28767 |
'e': 444, |
| 28768 |
'f': 333, |
| 28769 |
'g': 500, |
| 28770 |
'h': 500, |
| 28771 |
'i': 278, |
| 28772 |
'j': 278, |
| 28773 |
'k': 500, |
| 28774 |
'l': 278, |
| 28775 |
'm': 778, |
| 28776 |
'n': 500, |
| 28777 |
'o': 500, |
| 28778 |
'p': 500, |
| 28779 |
'q': 500, |
| 28780 |
'r': 333, |
| 28781 |
's': 389, |
| 28782 |
't': 278, |
| 28783 |
'u': 500, |
| 28784 |
'v': 500, |
| 28785 |
'w': 722, |
| 28786 |
'x': 500, |
| 28787 |
'y': 500, |
| 28788 |
'z': 444, |
| 28789 |
'braceleft': 480, |
| 28790 |
'bar': 200, |
| 28791 |
'braceright': 480, |
| 28792 |
'asciitilde': 541, |
| 28793 |
'exclamdown': 333, |
| 28794 |
'cent': 500, |
| 28795 |
'sterling': 500, |
| 28796 |
'fraction': 167, |
| 28797 |
'yen': 500, |
| 28798 |
'florin': 500, |
| 28799 |
'section': 500, |
| 28800 |
'currency': 500, |
| 28801 |
'quotesingle': 180, |
| 28802 |
'quotedblleft': 444, |
| 28803 |
'guillemotleft': 500, |
| 28804 |
'guilsinglleft': 333, |
| 28805 |
'guilsinglright': 333, |
| 28806 |
'fi': 556, |
| 28807 |
'fl': 556, |
| 28808 |
'endash': 500, |
| 28809 |
'dagger': 500, |
| 28810 |
'daggerdbl': 500, |
| 28811 |
'periodcentered': 250, |
| 28812 |
'paragraph': 453, |
| 28813 |
'bullet': 350, |
| 28814 |
'quotesinglbase': 333, |
| 28815 |
'quotedblbase': 444, |
| 28816 |
'quotedblright': 444, |
| 28817 |
'guillemotright': 500, |
| 28818 |
'ellipsis': 1000, |
| 28819 |
'perthousand': 1000, |
| 28820 |
'questiondown': 444, |
| 28821 |
'grave': 333, |
| 28822 |
'acute': 333, |
| 28823 |
'circumflex': 333, |
| 28824 |
'tilde': 333, |
| 28825 |
'macron': 333, |
| 28826 |
'breve': 333, |
| 28827 |
'dotaccent': 333, |
| 28828 |
'dieresis': 333, |
| 28829 |
'ring': 333, |
| 28830 |
'cedilla': 333, |
| 28831 |
'hungarumlaut': 333, |
| 28832 |
'ogonek': 333, |
| 28833 |
'caron': 333, |
| 28834 |
'emdash': 1000, |
| 28835 |
'AE': 889, |
| 28836 |
'ordfeminine': 276, |
| 28837 |
'Lslash': 611, |
| 28838 |
'Oslash': 722, |
| 28839 |
'OE': 889, |
| 28840 |
'ordmasculine': 310, |
| 28841 |
'ae': 667, |
| 28842 |
'dotlessi': 278, |
| 28843 |
'lslash': 278, |
| 28844 |
'oslash': 500, |
| 28845 |
'oe': 722, |
| 28846 |
'germandbls': 500, |
| 28847 |
'Idieresis': 333, |
| 28848 |
'eacute': 444, |
| 28849 |
'abreve': 444, |
| 28850 |
'uhungarumlaut': 500, |
| 28851 |
'ecaron': 444, |
| 28852 |
'Ydieresis': 722, |
| 28853 |
'divide': 564, |
| 28854 |
'Yacute': 722, |
| 28855 |
'Acircumflex': 722, |
| 28856 |
'aacute': 444, |
| 28857 |
'Ucircumflex': 722, |
| 28858 |
'yacute': 500, |
| 28859 |
'scommaaccent': 389, |
| 28860 |
'ecircumflex': 444, |
| 28861 |
'Uring': 722, |
| 28862 |
'Udieresis': 722, |
| 28863 |
'aogonek': 444, |
| 28864 |
'Uacute': 722, |
| 28865 |
'uogonek': 500, |
| 28866 |
'Edieresis': 611, |
| 28867 |
'Dcroat': 722, |
| 28868 |
'commaaccent': 250, |
| 28869 |
'copyright': 760, |
| 28870 |
'Emacron': 611, |
| 28871 |
'ccaron': 444, |
| 28872 |
'aring': 444, |
| 28873 |
'Ncommaaccent': 722, |
| 28874 |
'lacute': 278, |
| 28875 |
'agrave': 444, |
| 28876 |
'Tcommaaccent': 611, |
| 28877 |
'Cacute': 667, |
| 28878 |
'atilde': 444, |
| 28879 |
'Edotaccent': 611, |
| 28880 |
'scaron': 389, |
| 28881 |
'scedilla': 389, |
| 28882 |
'iacute': 278, |
| 28883 |
'lozenge': 471, |
| 28884 |
'Rcaron': 667, |
| 28885 |
'Gcommaaccent': 722, |
| 28886 |
'ucircumflex': 500, |
| 28887 |
'acircumflex': 444, |
| 28888 |
'Amacron': 722, |
| 28889 |
'rcaron': 333, |
| 28890 |
'ccedilla': 444, |
| 28891 |
'Zdotaccent': 611, |
| 28892 |
'Thorn': 556, |
| 28893 |
'Omacron': 722, |
| 28894 |
'Racute': 667, |
| 28895 |
'Sacute': 556, |
| 28896 |
'dcaron': 588, |
| 28897 |
'Umacron': 722, |
| 28898 |
'uring': 500, |
| 28899 |
'threesuperior': 300, |
| 28900 |
'Ograve': 722, |
| 28901 |
'Agrave': 722, |
| 28902 |
'Abreve': 722, |
| 28903 |
'multiply': 564, |
| 28904 |
'uacute': 500, |
| 28905 |
'Tcaron': 611, |
| 28906 |
'partialdiff': 476, |
| 28907 |
'ydieresis': 500, |
| 28908 |
'Nacute': 722, |
| 28909 |
'icircumflex': 278, |
| 28910 |
'Ecircumflex': 611, |
| 28911 |
'adieresis': 444, |
| 28912 |
'edieresis': 444, |
| 28913 |
'cacute': 444, |
| 28914 |
'nacute': 500, |
| 28915 |
'umacron': 500, |
| 28916 |
'Ncaron': 722, |
| 28917 |
'Iacute': 333, |
| 28918 |
'plusminus': 564, |
| 28919 |
'brokenbar': 200, |
| 28920 |
'registered': 760, |
| 28921 |
'Gbreve': 722, |
| 28922 |
'Idotaccent': 333, |
| 28923 |
'summation': 600, |
| 28924 |
'Egrave': 611, |
| 28925 |
'racute': 333, |
| 28926 |
'omacron': 500, |
| 28927 |
'Zacute': 611, |
| 28928 |
'Zcaron': 611, |
| 28929 |
'greaterequal': 549, |
| 28930 |
'Eth': 722, |
| 28931 |
'Ccedilla': 667, |
| 28932 |
'lcommaaccent': 278, |
| 28933 |
'tcaron': 326, |
| 28934 |
'eogonek': 444, |
| 28935 |
'Uogonek': 722, |
| 28936 |
'Aacute': 722, |
| 28937 |
'Adieresis': 722, |
| 28938 |
'egrave': 444, |
| 28939 |
'zacute': 444, |
| 28940 |
'iogonek': 278, |
| 28941 |
'Oacute': 722, |
| 28942 |
'oacute': 500, |
| 28943 |
'amacron': 444, |
| 28944 |
'sacute': 389, |
| 28945 |
'idieresis': 278, |
| 28946 |
'Ocircumflex': 722, |
| 28947 |
'Ugrave': 722, |
| 28948 |
'Delta': 612, |
| 28949 |
'thorn': 500, |
| 28950 |
'twosuperior': 300, |
| 28951 |
'Odieresis': 722, |
| 28952 |
'mu': 500, |
| 28953 |
'igrave': 278, |
| 28954 |
'ohungarumlaut': 500, |
| 28955 |
'Eogonek': 611, |
| 28956 |
'dcroat': 500, |
| 28957 |
'threequarters': 750, |
| 28958 |
'Scedilla': 556, |
| 28959 |
'lcaron': 344, |
| 28960 |
'Kcommaaccent': 722, |
| 28961 |
'Lacute': 611, |
| 28962 |
'trademark': 980, |
| 28963 |
'edotaccent': 444, |
| 28964 |
'Igrave': 333, |
| 28965 |
'Imacron': 333, |
| 28966 |
'Lcaron': 611, |
| 28967 |
'onehalf': 750, |
| 28968 |
'lessequal': 549, |
| 28969 |
'ocircumflex': 500, |
| 28970 |
'ntilde': 500, |
| 28971 |
'Uhungarumlaut': 722, |
| 28972 |
'Eacute': 611, |
| 28973 |
'emacron': 444, |
| 28974 |
'gbreve': 500, |
| 28975 |
'onequarter': 750, |
| 28976 |
'Scaron': 556, |
| 28977 |
'Scommaaccent': 556, |
| 28978 |
'Ohungarumlaut': 722, |
| 28979 |
'degree': 400, |
| 28980 |
'ograve': 500, |
| 28981 |
'Ccaron': 667, |
| 28982 |
'ugrave': 500, |
| 28983 |
'radical': 453, |
| 28984 |
'Dcaron': 722, |
| 28985 |
'rcommaaccent': 333, |
| 28986 |
'Ntilde': 722, |
| 28987 |
'otilde': 500, |
| 28988 |
'Rcommaaccent': 667, |
| 28989 |
'Lcommaaccent': 611, |
| 28990 |
'Atilde': 722, |
| 28991 |
'Aogonek': 722, |
| 28992 |
'Aring': 722, |
| 28993 |
'Otilde': 722, |
| 28994 |
'zdotaccent': 444, |
| 28995 |
'Ecaron': 611, |
| 28996 |
'Iogonek': 333, |
| 28997 |
'kcommaaccent': 500, |
| 28998 |
'minus': 564, |
| 28999 |
'Icircumflex': 333, |
| 29000 |
'ncaron': 500, |
| 29001 |
'tcommaaccent': 278, |
| 29002 |
'logicalnot': 564, |
| 29003 |
'odieresis': 500, |
| 29004 |
'udieresis': 500, |
| 29005 |
'notequal': 549, |
| 29006 |
'gcommaaccent': 500, |
| 29007 |
'eth': 500, |
| 29008 |
'zcaron': 444, |
| 29009 |
'ncommaaccent': 500, |
| 29010 |
'onesuperior': 300, |
| 29011 |
'imacron': 278, |
| 29012 |
'Euro': 500 |
| 29013 |
}, |
| 29014 |
'Times-Bold': { |
| 29015 |
'space': 250, |
| 29016 |
'exclam': 333, |
| 29017 |
'quotedbl': 555, |
| 29018 |
'numbersign': 500, |
| 29019 |
'dollar': 500, |
| 29020 |
'percent': 1000, |
| 29021 |
'ampersand': 833, |
| 29022 |
'quoteright': 333, |
| 29023 |
'parenleft': 333, |
| 29024 |
'parenright': 333, |
| 29025 |
'asterisk': 500, |
| 29026 |
'plus': 570, |
| 29027 |
'comma': 250, |
| 29028 |
'hyphen': 333, |
| 29029 |
'period': 250, |
| 29030 |
'slash': 278, |
| 29031 |
'zero': 500, |
| 29032 |
'one': 500, |
| 29033 |
'two': 500, |
| 29034 |
'three': 500, |
| 29035 |
'four': 500, |
| 29036 |
'five': 500, |
| 29037 |
'six': 500, |
| 29038 |
'seven': 500, |
| 29039 |
'eight': 500, |
| 29040 |
'nine': 500, |
| 29041 |
'colon': 333, |
| 29042 |
'semicolon': 333, |
| 29043 |
'less': 570, |
| 29044 |
'equal': 570, |
| 29045 |
'greater': 570, |
| 29046 |
'question': 500, |
| 29047 |
'at': 930, |
| 29048 |
'A': 722, |
| 29049 |
'B': 667, |
| 29050 |
'C': 722, |
| 29051 |
'D': 722, |
| 29052 |
'E': 667, |
| 29053 |
'F': 611, |
| 29054 |
'G': 778, |
| 29055 |
'H': 778, |
| 29056 |
'I': 389, |
| 29057 |
'J': 500, |
| 29058 |
'K': 778, |
| 29059 |
'L': 667, |
| 29060 |
'M': 944, |
| 29061 |
'N': 722, |
| 29062 |
'O': 778, |
| 29063 |
'P': 611, |
| 29064 |
'Q': 778, |
| 29065 |
'R': 722, |
| 29066 |
'S': 556, |
| 29067 |
'T': 667, |
| 29068 |
'U': 722, |
| 29069 |
'V': 722, |
| 29070 |
'W': 1000, |
| 29071 |
'X': 722, |
| 29072 |
'Y': 722, |
| 29073 |
'Z': 667, |
| 29074 |
'bracketleft': 333, |
| 29075 |
'backslash': 278, |
| 29076 |
'bracketright': 333, |
| 29077 |
'asciicircum': 581, |
| 29078 |
'underscore': 500, |
| 29079 |
'quoteleft': 333, |
| 29080 |
'a': 500, |
| 29081 |
'b': 556, |
| 29082 |
'c': 444, |
| 29083 |
'd': 556, |
| 29084 |
'e': 444, |
| 29085 |
'f': 333, |
| 29086 |
'g': 500, |
| 29087 |
'h': 556, |
| 29088 |
'i': 278, |
| 29089 |
'j': 333, |
| 29090 |
'k': 556, |
| 29091 |
'l': 278, |
| 29092 |
'm': 833, |
| 29093 |
'n': 556, |
| 29094 |
'o': 500, |
| 29095 |
'p': 556, |
| 29096 |
'q': 556, |
| 29097 |
'r': 444, |
| 29098 |
's': 389, |
| 29099 |
't': 333, |
| 29100 |
'u': 556, |
| 29101 |
'v': 500, |
| 29102 |
'w': 722, |
| 29103 |
'x': 500, |
| 29104 |
'y': 500, |
| 29105 |
'z': 444, |
| 29106 |
'braceleft': 394, |
| 29107 |
'bar': 220, |
| 29108 |
'braceright': 394, |
| 29109 |
'asciitilde': 520, |
| 29110 |
'exclamdown': 333, |
| 29111 |
'cent': 500, |
| 29112 |
'sterling': 500, |
| 29113 |
'fraction': 167, |
| 29114 |
'yen': 500, |
| 29115 |
'florin': 500, |
| 29116 |
'section': 500, |
| 29117 |
'currency': 500, |
| 29118 |
'quotesingle': 278, |
| 29119 |
'quotedblleft': 500, |
| 29120 |
'guillemotleft': 500, |
| 29121 |
'guilsinglleft': 333, |
| 29122 |
'guilsinglright': 333, |
| 29123 |
'fi': 556, |
| 29124 |
'fl': 556, |
| 29125 |
'endash': 500, |
| 29126 |
'dagger': 500, |
| 29127 |
'daggerdbl': 500, |
| 29128 |
'periodcentered': 250, |
| 29129 |
'paragraph': 540, |
| 29130 |
'bullet': 350, |
| 29131 |
'quotesinglbase': 333, |
| 29132 |
'quotedblbase': 500, |
| 29133 |
'quotedblright': 500, |
| 29134 |
'guillemotright': 500, |
| 29135 |
'ellipsis': 1000, |
| 29136 |
'perthousand': 1000, |
| 29137 |
'questiondown': 500, |
| 29138 |
'grave': 333, |
| 29139 |
'acute': 333, |
| 29140 |
'circumflex': 333, |
| 29141 |
'tilde': 333, |
| 29142 |
'macron': 333, |
| 29143 |
'breve': 333, |
| 29144 |
'dotaccent': 333, |
| 29145 |
'dieresis': 333, |
| 29146 |
'ring': 333, |
| 29147 |
'cedilla': 333, |
| 29148 |
'hungarumlaut': 333, |
| 29149 |
'ogonek': 333, |
| 29150 |
'caron': 333, |
| 29151 |
'emdash': 1000, |
| 29152 |
'AE': 1000, |
| 29153 |
'ordfeminine': 300, |
| 29154 |
'Lslash': 667, |
| 29155 |
'Oslash': 778, |
| 29156 |
'OE': 1000, |
| 29157 |
'ordmasculine': 330, |
| 29158 |
'ae': 722, |
| 29159 |
'dotlessi': 278, |
| 29160 |
'lslash': 278, |
| 29161 |
'oslash': 500, |
| 29162 |
'oe': 722, |
| 29163 |
'germandbls': 556, |
| 29164 |
'Idieresis': 389, |
| 29165 |
'eacute': 444, |
| 29166 |
'abreve': 500, |
| 29167 |
'uhungarumlaut': 556, |
| 29168 |
'ecaron': 444, |
| 29169 |
'Ydieresis': 722, |
| 29170 |
'divide': 570, |
| 29171 |
'Yacute': 722, |
| 29172 |
'Acircumflex': 722, |
| 29173 |
'aacute': 500, |
| 29174 |
'Ucircumflex': 722, |
| 29175 |
'yacute': 500, |
| 29176 |
'scommaaccent': 389, |
| 29177 |
'ecircumflex': 444, |
| 29178 |
'Uring': 722, |
| 29179 |
'Udieresis': 722, |
| 29180 |
'aogonek': 500, |
| 29181 |
'Uacute': 722, |
| 29182 |
'uogonek': 556, |
| 29183 |
'Edieresis': 667, |
| 29184 |
'Dcroat': 722, |
| 29185 |
'commaaccent': 250, |
| 29186 |
'copyright': 747, |
| 29187 |
'Emacron': 667, |
| 29188 |
'ccaron': 444, |
| 29189 |
'aring': 500, |
| 29190 |
'Ncommaaccent': 722, |
| 29191 |
'lacute': 278, |
| 29192 |
'agrave': 500, |
| 29193 |
'Tcommaaccent': 667, |
| 29194 |
'Cacute': 722, |
| 29195 |
'atilde': 500, |
| 29196 |
'Edotaccent': 667, |
| 29197 |
'scaron': 389, |
| 29198 |
'scedilla': 389, |
| 29199 |
'iacute': 278, |
| 29200 |
'lozenge': 494, |
| 29201 |
'Rcaron': 722, |
| 29202 |
'Gcommaaccent': 778, |
| 29203 |
'ucircumflex': 556, |
| 29204 |
'acircumflex': 500, |
| 29205 |
'Amacron': 722, |
| 29206 |
'rcaron': 444, |
| 29207 |
'ccedilla': 444, |
| 29208 |
'Zdotaccent': 667, |
| 29209 |
'Thorn': 611, |
| 29210 |
'Omacron': 778, |
| 29211 |
'Racute': 722, |
| 29212 |
'Sacute': 556, |
| 29213 |
'dcaron': 672, |
| 29214 |
'Umacron': 722, |
| 29215 |
'uring': 556, |
| 29216 |
'threesuperior': 300, |
| 29217 |
'Ograve': 778, |
| 29218 |
'Agrave': 722, |
| 29219 |
'Abreve': 722, |
| 29220 |
'multiply': 570, |
| 29221 |
'uacute': 556, |
| 29222 |
'Tcaron': 667, |
| 29223 |
'partialdiff': 494, |
| 29224 |
'ydieresis': 500, |
| 29225 |
'Nacute': 722, |
| 29226 |
'icircumflex': 278, |
| 29227 |
'Ecircumflex': 667, |
| 29228 |
'adieresis': 500, |
| 29229 |
'edieresis': 444, |
| 29230 |
'cacute': 444, |
| 29231 |
'nacute': 556, |
| 29232 |
'umacron': 556, |
| 29233 |
'Ncaron': 722, |
| 29234 |
'Iacute': 389, |
| 29235 |
'plusminus': 570, |
| 29236 |
'brokenbar': 220, |
| 29237 |
'registered': 747, |
| 29238 |
'Gbreve': 778, |
| 29239 |
'Idotaccent': 389, |
| 29240 |
'summation': 600, |
| 29241 |
'Egrave': 667, |
| 29242 |
'racute': 444, |
| 29243 |
'omacron': 500, |
| 29244 |
'Zacute': 667, |
| 29245 |
'Zcaron': 667, |
| 29246 |
'greaterequal': 549, |
| 29247 |
'Eth': 722, |
| 29248 |
'Ccedilla': 722, |
| 29249 |
'lcommaaccent': 278, |
| 29250 |
'tcaron': 416, |
| 29251 |
'eogonek': 444, |
| 29252 |
'Uogonek': 722, |
| 29253 |
'Aacute': 722, |
| 29254 |
'Adieresis': 722, |
| 29255 |
'egrave': 444, |
| 29256 |
'zacute': 444, |
| 29257 |
'iogonek': 278, |
| 29258 |
'Oacute': 778, |
| 29259 |
'oacute': 500, |
| 29260 |
'amacron': 500, |
| 29261 |
'sacute': 389, |
| 29262 |
'idieresis': 278, |
| 29263 |
'Ocircumflex': 778, |
| 29264 |
'Ugrave': 722, |
| 29265 |
'Delta': 612, |
| 29266 |
'thorn': 556, |
| 29267 |
'twosuperior': 300, |
| 29268 |
'Odieresis': 778, |
| 29269 |
'mu': 556, |
| 29270 |
'igrave': 278, |
| 29271 |
'ohungarumlaut': 500, |
| 29272 |
'Eogonek': 667, |
| 29273 |
'dcroat': 556, |
| 29274 |
'threequarters': 750, |
| 29275 |
'Scedilla': 556, |
| 29276 |
'lcaron': 394, |
| 29277 |
'Kcommaaccent': 778, |
| 29278 |
'Lacute': 667, |
| 29279 |
'trademark': 1000, |
| 29280 |
'edotaccent': 444, |
| 29281 |
'Igrave': 389, |
| 29282 |
'Imacron': 389, |
| 29283 |
'Lcaron': 667, |
| 29284 |
'onehalf': 750, |
| 29285 |
'lessequal': 549, |
| 29286 |
'ocircumflex': 500, |
| 29287 |
'ntilde': 556, |
| 29288 |
'Uhungarumlaut': 722, |
| 29289 |
'Eacute': 667, |
| 29290 |
'emacron': 444, |
| 29291 |
'gbreve': 500, |
| 29292 |
'onequarter': 750, |
| 29293 |
'Scaron': 556, |
| 29294 |
'Scommaaccent': 556, |
| 29295 |
'Ohungarumlaut': 778, |
| 29296 |
'degree': 400, |
| 29297 |
'ograve': 500, |
| 29298 |
'Ccaron': 722, |
| 29299 |
'ugrave': 556, |
| 29300 |
'radical': 549, |
| 29301 |
'Dcaron': 722, |
| 29302 |
'rcommaaccent': 444, |
| 29303 |
'Ntilde': 722, |
| 29304 |
'otilde': 500, |
| 29305 |
'Rcommaaccent': 722, |
| 29306 |
'Lcommaaccent': 667, |
| 29307 |
'Atilde': 722, |
| 29308 |
'Aogonek': 722, |
| 29309 |
'Aring': 722, |
| 29310 |
'Otilde': 778, |
| 29311 |
'zdotaccent': 444, |
| 29312 |
'Ecaron': 667, |
| 29313 |
'Iogonek': 389, |
| 29314 |
'kcommaaccent': 556, |
| 29315 |
'minus': 570, |
| 29316 |
'Icircumflex': 389, |
| 29317 |
'ncaron': 556, |
| 29318 |
'tcommaaccent': 333, |
| 29319 |
'logicalnot': 570, |
| 29320 |
'odieresis': 500, |
| 29321 |
'udieresis': 556, |
| 29322 |
'notequal': 549, |
| 29323 |
'gcommaaccent': 500, |
| 29324 |
'eth': 500, |
| 29325 |
'zcaron': 444, |
| 29326 |
'ncommaaccent': 556, |
| 29327 |
'onesuperior': 300, |
| 29328 |
'imacron': 278, |
| 29329 |
'Euro': 500 |
| 29330 |
}, |
| 29331 |
'Times-BoldItalic': { |
| 29332 |
'space': 250, |
| 29333 |
'exclam': 389, |
| 29334 |
'quotedbl': 555, |
| 29335 |
'numbersign': 500, |
| 29336 |
'dollar': 500, |
| 29337 |
'percent': 833, |
| 29338 |
'ampersand': 778, |
| 29339 |
'quoteright': 333, |
| 29340 |
'parenleft': 333, |
| 29341 |
'parenright': 333, |
| 29342 |
'asterisk': 500, |
| 29343 |
'plus': 570, |
| 29344 |
'comma': 250, |
| 29345 |
'hyphen': 333, |
| 29346 |
'period': 250, |
| 29347 |
'slash': 278, |
| 29348 |
'zero': 500, |
| 29349 |
'one': 500, |
| 29350 |
'two': 500, |
| 29351 |
'three': 500, |
| 29352 |
'four': 500, |
| 29353 |
'five': 500, |
| 29354 |
'six': 500, |
| 29355 |
'seven': 500, |
| 29356 |
'eight': 500, |
| 29357 |
'nine': 500, |
| 29358 |
'colon': 333, |
| 29359 |
'semicolon': 333, |
| 29360 |
'less': 570, |
| 29361 |
'equal': 570, |
| 29362 |
'greater': 570, |
| 29363 |
'question': 500, |
| 29364 |
'at': 832, |
| 29365 |
'A': 667, |
| 29366 |
'B': 667, |
| 29367 |
'C': 667, |
| 29368 |
'D': 722, |
| 29369 |
'E': 667, |
| 29370 |
'F': 667, |
| 29371 |
'G': 722, |
| 29372 |
'H': 778, |
| 29373 |
'I': 389, |
| 29374 |
'J': 500, |
| 29375 |
'K': 667, |
| 29376 |
'L': 611, |
| 29377 |
'M': 889, |
| 29378 |
'N': 722, |
| 29379 |
'O': 722, |
| 29380 |
'P': 611, |
| 29381 |
'Q': 722, |
| 29382 |
'R': 667, |
| 29383 |
'S': 556, |
| 29384 |
'T': 611, |
| 29385 |
'U': 722, |
| 29386 |
'V': 667, |
| 29387 |
'W': 889, |
| 29388 |
'X': 667, |
| 29389 |
'Y': 611, |
| 29390 |
'Z': 611, |
| 29391 |
'bracketleft': 333, |
| 29392 |
'backslash': 278, |
| 29393 |
'bracketright': 333, |
| 29394 |
'asciicircum': 570, |
| 29395 |
'underscore': 500, |
| 29396 |
'quoteleft': 333, |
| 29397 |
'a': 500, |
| 29398 |
'b': 500, |
| 29399 |
'c': 444, |
| 29400 |
'd': 500, |
| 29401 |
'e': 444, |
| 29402 |
'f': 333, |
| 29403 |
'g': 500, |
| 29404 |
'h': 556, |
| 29405 |
'i': 278, |
| 29406 |
'j': 278, |
| 29407 |
'k': 500, |
| 29408 |
'l': 278, |
| 29409 |
'm': 778, |
| 29410 |
'n': 556, |
| 29411 |
'o': 500, |
| 29412 |
'p': 500, |
| 29413 |
'q': 500, |
| 29414 |
'r': 389, |
| 29415 |
's': 389, |
| 29416 |
't': 278, |
| 29417 |
'u': 556, |
| 29418 |
'v': 444, |
| 29419 |
'w': 667, |
| 29420 |
'x': 500, |
| 29421 |
'y': 444, |
| 29422 |
'z': 389, |
| 29423 |
'braceleft': 348, |
| 29424 |
'bar': 220, |
| 29425 |
'braceright': 348, |
| 29426 |
'asciitilde': 570, |
| 29427 |
'exclamdown': 389, |
| 29428 |
'cent': 500, |
| 29429 |
'sterling': 500, |
| 29430 |
'fraction': 167, |
| 29431 |
'yen': 500, |
| 29432 |
'florin': 500, |
| 29433 |
'section': 500, |
| 29434 |
'currency': 500, |
| 29435 |
'quotesingle': 278, |
| 29436 |
'quotedblleft': 500, |
| 29437 |
'guillemotleft': 500, |
| 29438 |
'guilsinglleft': 333, |
| 29439 |
'guilsinglright': 333, |
| 29440 |
'fi': 556, |
| 29441 |
'fl': 556, |
| 29442 |
'endash': 500, |
| 29443 |
'dagger': 500, |
| 29444 |
'daggerdbl': 500, |
| 29445 |
'periodcentered': 250, |
| 29446 |
'paragraph': 500, |
| 29447 |
'bullet': 350, |
| 29448 |
'quotesinglbase': 333, |
| 29449 |
'quotedblbase': 500, |
| 29450 |
'quotedblright': 500, |
| 29451 |
'guillemotright': 500, |
| 29452 |
'ellipsis': 1000, |
| 29453 |
'perthousand': 1000, |
| 29454 |
'questiondown': 500, |
| 29455 |
'grave': 333, |
| 29456 |
'acute': 333, |
| 29457 |
'circumflex': 333, |
| 29458 |
'tilde': 333, |
| 29459 |
'macron': 333, |
| 29460 |
'breve': 333, |
| 29461 |
'dotaccent': 333, |
| 29462 |
'dieresis': 333, |
| 29463 |
'ring': 333, |
| 29464 |
'cedilla': 333, |
| 29465 |
'hungarumlaut': 333, |
| 29466 |
'ogonek': 333, |
| 29467 |
'caron': 333, |
| 29468 |
'emdash': 1000, |
| 29469 |
'AE': 944, |
| 29470 |
'ordfeminine': 266, |
| 29471 |
'Lslash': 611, |
| 29472 |
'Oslash': 722, |
| 29473 |
'OE': 944, |
| 29474 |
'ordmasculine': 300, |
| 29475 |
'ae': 722, |
| 29476 |
'dotlessi': 278, |
| 29477 |
'lslash': 278, |
| 29478 |
'oslash': 500, |
| 29479 |
'oe': 722, |
| 29480 |
'germandbls': 500, |
| 29481 |
'Idieresis': 389, |
| 29482 |
'eacute': 444, |
| 29483 |
'abreve': 500, |
| 29484 |
'uhungarumlaut': 556, |
| 29485 |
'ecaron': 444, |
| 29486 |
'Ydieresis': 611, |
| 29487 |
'divide': 570, |
| 29488 |
'Yacute': 611, |
| 29489 |
'Acircumflex': 667, |
| 29490 |
'aacute': 500, |
| 29491 |
'Ucircumflex': 722, |
| 29492 |
'yacute': 444, |
| 29493 |
'scommaaccent': 389, |
| 29494 |
'ecircumflex': 444, |
| 29495 |
'Uring': 722, |
| 29496 |
'Udieresis': 722, |
| 29497 |
'aogonek': 500, |
| 29498 |
'Uacute': 722, |
| 29499 |
'uogonek': 556, |
| 29500 |
'Edieresis': 667, |
| 29501 |
'Dcroat': 722, |
| 29502 |
'commaaccent': 250, |
| 29503 |
'copyright': 747, |
| 29504 |
'Emacron': 667, |
| 29505 |
'ccaron': 444, |
| 29506 |
'aring': 500, |
| 29507 |
'Ncommaaccent': 722, |
| 29508 |
'lacute': 278, |
| 29509 |
'agrave': 500, |
| 29510 |
'Tcommaaccent': 611, |
| 29511 |
'Cacute': 667, |
| 29512 |
'atilde': 500, |
| 29513 |
'Edotaccent': 667, |
| 29514 |
'scaron': 389, |
| 29515 |
'scedilla': 389, |
| 29516 |
'iacute': 278, |
| 29517 |
'lozenge': 494, |
| 29518 |
'Rcaron': 667, |
| 29519 |
'Gcommaaccent': 722, |
| 29520 |
'ucircumflex': 556, |
| 29521 |
'acircumflex': 500, |
| 29522 |
'Amacron': 667, |
| 29523 |
'rcaron': 389, |
| 29524 |
'ccedilla': 444, |
| 29525 |
'Zdotaccent': 611, |
| 29526 |
'Thorn': 611, |
| 29527 |
'Omacron': 722, |
| 29528 |
'Racute': 667, |
| 29529 |
'Sacute': 556, |
| 29530 |
'dcaron': 608, |
| 29531 |
'Umacron': 722, |
| 29532 |
'uring': 556, |
| 29533 |
'threesuperior': 300, |
| 29534 |
'Ograve': 722, |
| 29535 |
'Agrave': 667, |
| 29536 |
'Abreve': 667, |
| 29537 |
'multiply': 570, |
| 29538 |
'uacute': 556, |
| 29539 |
'Tcaron': 611, |
| 29540 |
'partialdiff': 494, |
| 29541 |
'ydieresis': 444, |
| 29542 |
'Nacute': 722, |
| 29543 |
'icircumflex': 278, |
| 29544 |
'Ecircumflex': 667, |
| 29545 |
'adieresis': 500, |
| 29546 |
'edieresis': 444, |
| 29547 |
'cacute': 444, |
| 29548 |
'nacute': 556, |
| 29549 |
'umacron': 556, |
| 29550 |
'Ncaron': 722, |
| 29551 |
'Iacute': 389, |
| 29552 |
'plusminus': 570, |
| 29553 |
'brokenbar': 220, |
| 29554 |
'registered': 747, |
| 29555 |
'Gbreve': 722, |
| 29556 |
'Idotaccent': 389, |
| 29557 |
'summation': 600, |
| 29558 |
'Egrave': 667, |
| 29559 |
'racute': 389, |
| 29560 |
'omacron': 500, |
| 29561 |
'Zacute': 611, |
| 29562 |
'Zcaron': 611, |
| 29563 |
'greaterequal': 549, |
| 29564 |
'Eth': 722, |
| 29565 |
'Ccedilla': 667, |
| 29566 |
'lcommaaccent': 278, |
| 29567 |
'tcaron': 366, |
| 29568 |
'eogonek': 444, |
| 29569 |
'Uogonek': 722, |
| 29570 |
'Aacute': 667, |
| 29571 |
'Adieresis': 667, |
| 29572 |
'egrave': 444, |
| 29573 |
'zacute': 389, |
| 29574 |
'iogonek': 278, |
| 29575 |
'Oacute': 722, |
| 29576 |
'oacute': 500, |
| 29577 |
'amacron': 500, |
| 29578 |
'sacute': 389, |
| 29579 |
'idieresis': 278, |
| 29580 |
'Ocircumflex': 722, |
| 29581 |
'Ugrave': 722, |
| 29582 |
'Delta': 612, |
| 29583 |
'thorn': 500, |
| 29584 |
'twosuperior': 300, |
| 29585 |
'Odieresis': 722, |
| 29586 |
'mu': 576, |
| 29587 |
'igrave': 278, |
| 29588 |
'ohungarumlaut': 500, |
| 29589 |
'Eogonek': 667, |
| 29590 |
'dcroat': 500, |
| 29591 |
'threequarters': 750, |
| 29592 |
'Scedilla': 556, |
| 29593 |
'lcaron': 382, |
| 29594 |
'Kcommaaccent': 667, |
| 29595 |
'Lacute': 611, |
| 29596 |
'trademark': 1000, |
| 29597 |
'edotaccent': 444, |
| 29598 |
'Igrave': 389, |
| 29599 |
'Imacron': 389, |
| 29600 |
'Lcaron': 611, |
| 29601 |
'onehalf': 750, |
| 29602 |
'lessequal': 549, |
| 29603 |
'ocircumflex': 500, |
| 29604 |
'ntilde': 556, |
| 29605 |
'Uhungarumlaut': 722, |
| 29606 |
'Eacute': 667, |
| 29607 |
'emacron': 444, |
| 29608 |
'gbreve': 500, |
| 29609 |
'onequarter': 750, |
| 29610 |
'Scaron': 556, |
| 29611 |
'Scommaaccent': 556, |
| 29612 |
'Ohungarumlaut': 722, |
| 29613 |
'degree': 400, |
| 29614 |
'ograve': 500, |
| 29615 |
'Ccaron': 667, |
| 29616 |
'ugrave': 556, |
| 29617 |
'radical': 549, |
| 29618 |
'Dcaron': 722, |
| 29619 |
'rcommaaccent': 389, |
| 29620 |
'Ntilde': 722, |
| 29621 |
'otilde': 500, |
| 29622 |
'Rcommaaccent': 667, |
| 29623 |
'Lcommaaccent': 611, |
| 29624 |
'Atilde': 667, |
| 29625 |
'Aogonek': 667, |
| 29626 |
'Aring': 667, |
| 29627 |
'Otilde': 722, |
| 29628 |
'zdotaccent': 389, |
| 29629 |
'Ecaron': 667, |
| 29630 |
'Iogonek': 389, |
| 29631 |
'kcommaaccent': 500, |
| 29632 |
'minus': 606, |
| 29633 |
'Icircumflex': 389, |
| 29634 |
'ncaron': 556, |
| 29635 |
'tcommaaccent': 278, |
| 29636 |
'logicalnot': 606, |
| 29637 |
'odieresis': 500, |
| 29638 |
'udieresis': 556, |
| 29639 |
'notequal': 549, |
| 29640 |
'gcommaaccent': 500, |
| 29641 |
'eth': 500, |
| 29642 |
'zcaron': 389, |
| 29643 |
'ncommaaccent': 556, |
| 29644 |
'onesuperior': 300, |
| 29645 |
'imacron': 278, |
| 29646 |
'Euro': 500 |
| 29647 |
}, |
| 29648 |
'Times-Italic': { |
| 29649 |
'space': 250, |
| 29650 |
'exclam': 333, |
| 29651 |
'quotedbl': 420, |
| 29652 |
'numbersign': 500, |
| 29653 |
'dollar': 500, |
| 29654 |
'percent': 833, |
| 29655 |
'ampersand': 778, |
| 29656 |
'quoteright': 333, |
| 29657 |
'parenleft': 333, |
| 29658 |
'parenright': 333, |
| 29659 |
'asterisk': 500, |
| 29660 |
'plus': 675, |
| 29661 |
'comma': 250, |
| 29662 |
'hyphen': 333, |
| 29663 |
'period': 250, |
| 29664 |
'slash': 278, |
| 29665 |
'zero': 500, |
| 29666 |
'one': 500, |
| 29667 |
'two': 500, |
| 29668 |
'three': 500, |
| 29669 |
'four': 500, |
| 29670 |
'five': 500, |
| 29671 |
'six': 500, |
| 29672 |
'seven': 500, |
| 29673 |
'eight': 500, |
| 29674 |
'nine': 500, |
| 29675 |
'colon': 333, |
| 29676 |
'semicolon': 333, |
| 29677 |
'less': 675, |
| 29678 |
'equal': 675, |
| 29679 |
'greater': 675, |
| 29680 |
'question': 500, |
| 29681 |
'at': 920, |
| 29682 |
'A': 611, |
| 29683 |
'B': 611, |
| 29684 |
'C': 667, |
| 29685 |
'D': 722, |
| 29686 |
'E': 611, |
| 29687 |
'F': 611, |
| 29688 |
'G': 722, |
| 29689 |
'H': 722, |
| 29690 |
'I': 333, |
| 29691 |
'J': 444, |
| 29692 |
'K': 667, |
| 29693 |
'L': 556, |
| 29694 |
'M': 833, |
| 29695 |
'N': 667, |
| 29696 |
'O': 722, |
| 29697 |
'P': 611, |
| 29698 |
'Q': 722, |
| 29699 |
'R': 611, |
| 29700 |
'S': 500, |
| 29701 |
'T': 556, |
| 29702 |
'U': 722, |
| 29703 |
'V': 611, |
| 29704 |
'W': 833, |
| 29705 |
'X': 611, |
| 29706 |
'Y': 556, |
| 29707 |
'Z': 556, |
| 29708 |
'bracketleft': 389, |
| 29709 |
'backslash': 278, |
| 29710 |
'bracketright': 389, |
| 29711 |
'asciicircum': 422, |
| 29712 |
'underscore': 500, |
| 29713 |
'quoteleft': 333, |
| 29714 |
'a': 500, |
| 29715 |
'b': 500, |
| 29716 |
'c': 444, |
| 29717 |
'd': 500, |
| 29718 |
'e': 444, |
| 29719 |
'f': 278, |
| 29720 |
'g': 500, |
| 29721 |
'h': 500, |
| 29722 |
'i': 278, |
| 29723 |
'j': 278, |
| 29724 |
'k': 444, |
| 29725 |
'l': 278, |
| 29726 |
'm': 722, |
| 29727 |
'n': 500, |
| 29728 |
'o': 500, |
| 29729 |
'p': 500, |
| 29730 |
'q': 500, |
| 29731 |
'r': 389, |
| 29732 |
's': 389, |
| 29733 |
't': 278, |
| 29734 |
'u': 500, |
| 29735 |
'v': 444, |
| 29736 |
'w': 667, |
| 29737 |
'x': 444, |
| 29738 |
'y': 444, |
| 29739 |
'z': 389, |
| 29740 |
'braceleft': 400, |
| 29741 |
'bar': 275, |
| 29742 |
'braceright': 400, |
| 29743 |
'asciitilde': 541, |
| 29744 |
'exclamdown': 389, |
| 29745 |
'cent': 500, |
| 29746 |
'sterling': 500, |
| 29747 |
'fraction': 167, |
| 29748 |
'yen': 500, |
| 29749 |
'florin': 500, |
| 29750 |
'section': 500, |
| 29751 |
'currency': 500, |
| 29752 |
'quotesingle': 214, |
| 29753 |
'quotedblleft': 556, |
| 29754 |
'guillemotleft': 500, |
| 29755 |
'guilsinglleft': 333, |
| 29756 |
'guilsinglright': 333, |
| 29757 |
'fi': 500, |
| 29758 |
'fl': 500, |
| 29759 |
'endash': 500, |
| 29760 |
'dagger': 500, |
| 29761 |
'daggerdbl': 500, |
| 29762 |
'periodcentered': 250, |
| 29763 |
'paragraph': 523, |
| 29764 |
'bullet': 350, |
| 29765 |
'quotesinglbase': 333, |
| 29766 |
'quotedblbase': 556, |
| 29767 |
'quotedblright': 556, |
| 29768 |
'guillemotright': 500, |
| 29769 |
'ellipsis': 889, |
| 29770 |
'perthousand': 1000, |
| 29771 |
'questiondown': 500, |
| 29772 |
'grave': 333, |
| 29773 |
'acute': 333, |
| 29774 |
'circumflex': 333, |
| 29775 |
'tilde': 333, |
| 29776 |
'macron': 333, |
| 29777 |
'breve': 333, |
| 29778 |
'dotaccent': 333, |
| 29779 |
'dieresis': 333, |
| 29780 |
'ring': 333, |
| 29781 |
'cedilla': 333, |
| 29782 |
'hungarumlaut': 333, |
| 29783 |
'ogonek': 333, |
| 29784 |
'caron': 333, |
| 29785 |
'emdash': 889, |
| 29786 |
'AE': 889, |
| 29787 |
'ordfeminine': 276, |
| 29788 |
'Lslash': 556, |
| 29789 |
'Oslash': 722, |
| 29790 |
'OE': 944, |
| 29791 |
'ordmasculine': 310, |
| 29792 |
'ae': 667, |
| 29793 |
'dotlessi': 278, |
| 29794 |
'lslash': 278, |
| 29795 |
'oslash': 500, |
| 29796 |
'oe': 667, |
| 29797 |
'germandbls': 500, |
| 29798 |
'Idieresis': 333, |
| 29799 |
'eacute': 444, |
| 29800 |
'abreve': 500, |
| 29801 |
'uhungarumlaut': 500, |
| 29802 |
'ecaron': 444, |
| 29803 |
'Ydieresis': 556, |
| 29804 |
'divide': 675, |
| 29805 |
'Yacute': 556, |
| 29806 |
'Acircumflex': 611, |
| 29807 |
'aacute': 500, |
| 29808 |
'Ucircumflex': 722, |
| 29809 |
'yacute': 444, |
| 29810 |
'scommaaccent': 389, |
| 29811 |
'ecircumflex': 444, |
| 29812 |
'Uring': 722, |
| 29813 |
'Udieresis': 722, |
| 29814 |
'aogonek': 500, |
| 29815 |
'Uacute': 722, |
| 29816 |
'uogonek': 500, |
| 29817 |
'Edieresis': 611, |
| 29818 |
'Dcroat': 722, |
| 29819 |
'commaaccent': 250, |
| 29820 |
'copyright': 760, |
| 29821 |
'Emacron': 611, |
| 29822 |
'ccaron': 444, |
| 29823 |
'aring': 500, |
| 29824 |
'Ncommaaccent': 667, |
| 29825 |
'lacute': 278, |
| 29826 |
'agrave': 500, |
| 29827 |
'Tcommaaccent': 556, |
| 29828 |
'Cacute': 667, |
| 29829 |
'atilde': 500, |
| 29830 |
'Edotaccent': 611, |
| 29831 |
'scaron': 389, |
| 29832 |
'scedilla': 389, |
| 29833 |
'iacute': 278, |
| 29834 |
'lozenge': 471, |
| 29835 |
'Rcaron': 611, |
| 29836 |
'Gcommaaccent': 722, |
| 29837 |
'ucircumflex': 500, |
| 29838 |
'acircumflex': 500, |
| 29839 |
'Amacron': 611, |
| 29840 |
'rcaron': 389, |
| 29841 |
'ccedilla': 444, |
| 29842 |
'Zdotaccent': 556, |
| 29843 |
'Thorn': 611, |
| 29844 |
'Omacron': 722, |
| 29845 |
'Racute': 611, |
| 29846 |
'Sacute': 500, |
| 29847 |
'dcaron': 544, |
| 29848 |
'Umacron': 722, |
| 29849 |
'uring': 500, |
| 29850 |
'threesuperior': 300, |
| 29851 |
'Ograve': 722, |
| 29852 |
'Agrave': 611, |
| 29853 |
'Abreve': 611, |
| 29854 |
'multiply': 675, |
| 29855 |
'uacute': 500, |
| 29856 |
'Tcaron': 556, |
| 29857 |
'partialdiff': 476, |
| 29858 |
'ydieresis': 444, |
| 29859 |
'Nacute': 667, |
| 29860 |
'icircumflex': 278, |
| 29861 |
'Ecircumflex': 611, |
| 29862 |
'adieresis': 500, |
| 29863 |
'edieresis': 444, |
| 29864 |
'cacute': 444, |
| 29865 |
'nacute': 500, |
| 29866 |
'umacron': 500, |
| 29867 |
'Ncaron': 667, |
| 29868 |
'Iacute': 333, |
| 29869 |
'plusminus': 675, |
| 29870 |
'brokenbar': 275, |
| 29871 |
'registered': 760, |
| 29872 |
'Gbreve': 722, |
| 29873 |
'Idotaccent': 333, |
| 29874 |
'summation': 600, |
| 29875 |
'Egrave': 611, |
| 29876 |
'racute': 389, |
| 29877 |
'omacron': 500, |
| 29878 |
'Zacute': 556, |
| 29879 |
'Zcaron': 556, |
| 29880 |
'greaterequal': 549, |
| 29881 |
'Eth': 722, |
| 29882 |
'Ccedilla': 667, |
| 29883 |
'lcommaaccent': 278, |
| 29884 |
'tcaron': 300, |
| 29885 |
'eogonek': 444, |
| 29886 |
'Uogonek': 722, |
| 29887 |
'Aacute': 611, |
| 29888 |
'Adieresis': 611, |
| 29889 |
'egrave': 444, |
| 29890 |
'zacute': 389, |
| 29891 |
'iogonek': 278, |
| 29892 |
'Oacute': 722, |
| 29893 |
'oacute': 500, |
| 29894 |
'amacron': 500, |
| 29895 |
'sacute': 389, |
| 29896 |
'idieresis': 278, |
| 29897 |
'Ocircumflex': 722, |
| 29898 |
'Ugrave': 722, |
| 29899 |
'Delta': 612, |
| 29900 |
'thorn': 500, |
| 29901 |
'twosuperior': 300, |
| 29902 |
'Odieresis': 722, |
| 29903 |
'mu': 500, |
| 29904 |
'igrave': 278, |
| 29905 |
'ohungarumlaut': 500, |
| 29906 |
'Eogonek': 611, |
| 29907 |
'dcroat': 500, |
| 29908 |
'threequarters': 750, |
| 29909 |
'Scedilla': 500, |
| 29910 |
'lcaron': 300, |
| 29911 |
'Kcommaaccent': 667, |
| 29912 |
'Lacute': 556, |
| 29913 |
'trademark': 980, |
| 29914 |
'edotaccent': 444, |
| 29915 |
'Igrave': 333, |
| 29916 |
'Imacron': 333, |
| 29917 |
'Lcaron': 611, |
| 29918 |
'onehalf': 750, |
| 29919 |
'lessequal': 549, |
| 29920 |
'ocircumflex': 500, |
| 29921 |
'ntilde': 500, |
| 29922 |
'Uhungarumlaut': 722, |
| 29923 |
'Eacute': 611, |
| 29924 |
'emacron': 444, |
| 29925 |
'gbreve': 500, |
| 29926 |
'onequarter': 750, |
| 29927 |
'Scaron': 500, |
| 29928 |
'Scommaaccent': 500, |
| 29929 |
'Ohungarumlaut': 722, |
| 29930 |
'degree': 400, |
| 29931 |
'ograve': 500, |
| 29932 |
'Ccaron': 667, |
| 29933 |
'ugrave': 500, |
| 29934 |
'radical': 453, |
| 29935 |
'Dcaron': 722, |
| 29936 |
'rcommaaccent': 389, |
| 29937 |
'Ntilde': 667, |
| 29938 |
'otilde': 500, |
| 29939 |
'Rcommaaccent': 611, |
| 29940 |
'Lcommaaccent': 556, |
| 29941 |
'Atilde': 611, |
| 29942 |
'Aogonek': 611, |
| 29943 |
'Aring': 611, |
| 29944 |
'Otilde': 722, |
| 29945 |
'zdotaccent': 389, |
| 29946 |
'Ecaron': 611, |
| 29947 |
'Iogonek': 333, |
| 29948 |
'kcommaaccent': 444, |
| 29949 |
'minus': 675, |
| 29950 |
'Icircumflex': 333, |
| 29951 |
'ncaron': 500, |
| 29952 |
'tcommaaccent': 278, |
| 29953 |
'logicalnot': 675, |
| 29954 |
'odieresis': 500, |
| 29955 |
'udieresis': 500, |
| 29956 |
'notequal': 549, |
| 29957 |
'gcommaaccent': 500, |
| 29958 |
'eth': 500, |
| 29959 |
'zcaron': 389, |
| 29960 |
'ncommaaccent': 500, |
| 29961 |
'onesuperior': 300, |
| 29962 |
'imacron': 278, |
| 29963 |
'Euro': 500 |
| 29964 |
}, |
| 29965 |
'ZapfDingbats': { |
| 29966 |
'space': 278, |
| 29967 |
'a1': 974, |
| 29968 |
'a2': 961, |
| 29969 |
'a202': 974, |
| 29970 |
'a3': 980, |
| 29971 |
'a4': 719, |
| 29972 |
'a5': 789, |
| 29973 |
'a119': 790, |
| 29974 |
'a118': 791, |
| 29975 |
'a117': 690, |
| 29976 |
'a11': 960, |
| 29977 |
'a12': 939, |
| 29978 |
'a13': 549, |
| 29979 |
'a14': 855, |
| 29980 |
'a15': 911, |
| 29981 |
'a16': 933, |
| 29982 |
'a105': 911, |
| 29983 |
'a17': 945, |
| 29984 |
'a18': 974, |
| 29985 |
'a19': 755, |
| 29986 |
'a20': 846, |
| 29987 |
'a21': 762, |
| 29988 |
'a22': 761, |
| 29989 |
'a23': 571, |
| 29990 |
'a24': 677, |
| 29991 |
'a25': 763, |
| 29992 |
'a26': 760, |
| 29993 |
'a27': 759, |
| 29994 |
'a28': 754, |
| 29995 |
'a6': 494, |
| 29996 |
'a7': 552, |
| 29997 |
'a8': 537, |
| 29998 |
'a9': 577, |
| 29999 |
'a10': 692, |
| 30000 |
'a29': 786, |
| 30001 |
'a30': 788, |
| 30002 |
'a31': 788, |
| 30003 |
'a32': 790, |
| 30004 |
'a33': 793, |
| 30005 |
'a34': 794, |
| 30006 |
'a35': 816, |
| 30007 |
'a36': 823, |
| 30008 |
'a37': 789, |
| 30009 |
'a38': 841, |
| 30010 |
'a39': 823, |
| 30011 |
'a40': 833, |
| 30012 |
'a41': 816, |
| 30013 |
'a42': 831, |
| 30014 |
'a43': 923, |
| 30015 |
'a44': 744, |
| 30016 |
'a45': 723, |
| 30017 |
'a46': 749, |
| 30018 |
'a47': 790, |
| 30019 |
'a48': 792, |
| 30020 |
'a49': 695, |
| 30021 |
'a50': 776, |
| 30022 |
'a51': 768, |
| 30023 |
'a52': 792, |
| 30024 |
'a53': 759, |
| 30025 |
'a54': 707, |
| 30026 |
'a55': 708, |
| 30027 |
'a56': 682, |
| 30028 |
'a57': 701, |
| 30029 |
'a58': 826, |
| 30030 |
'a59': 815, |
| 30031 |
'a60': 789, |
| 30032 |
'a61': 789, |
| 30033 |
'a62': 707, |
| 30034 |
'a63': 687, |
| 30035 |
'a64': 696, |
| 30036 |
'a65': 689, |
| 30037 |
'a66': 786, |
| 30038 |
'a67': 787, |
| 30039 |
'a68': 713, |
| 30040 |
'a69': 791, |
| 30041 |
'a70': 785, |
| 30042 |
'a71': 791, |
| 30043 |
'a72': 873, |
| 30044 |
'a73': 761, |
| 30045 |
'a74': 762, |
| 30046 |
'a203': 762, |
| 30047 |
'a75': 759, |
| 30048 |
'a204': 759, |
| 30049 |
'a76': 892, |
| 30050 |
'a77': 892, |
| 30051 |
'a78': 788, |
| 30052 |
'a79': 784, |
| 30053 |
'a81': 438, |
| 30054 |
'a82': 138, |
| 30055 |
'a83': 277, |
| 30056 |
'a84': 415, |
| 30057 |
'a97': 392, |
| 30058 |
'a98': 392, |
| 30059 |
'a99': 668, |
| 30060 |
'a100': 668, |
| 30061 |
'a89': 390, |
| 30062 |
'a90': 390, |
| 30063 |
'a93': 317, |
| 30064 |
'a94': 317, |
| 30065 |
'a91': 276, |
| 30066 |
'a92': 276, |
| 30067 |
'a205': 509, |
| 30068 |
'a85': 509, |
| 30069 |
'a206': 410, |
| 30070 |
'a86': 410, |
| 30071 |
'a87': 234, |
| 30072 |
'a88': 234, |
| 30073 |
'a95': 334, |
| 30074 |
'a96': 334, |
| 30075 |
'a101': 732, |
| 30076 |
'a102': 544, |
| 30077 |
'a103': 544, |
| 30078 |
'a104': 910, |
| 30079 |
'a106': 667, |
| 30080 |
'a107': 760, |
| 30081 |
'a108': 760, |
| 30082 |
'a112': 776, |
| 30083 |
'a111': 595, |
| 30084 |
'a110': 694, |
| 30085 |
'a109': 626, |
| 30086 |
'a120': 788, |
| 30087 |
'a121': 788, |
| 30088 |
'a122': 788, |
| 30089 |
'a123': 788, |
| 30090 |
'a124': 788, |
| 30091 |
'a125': 788, |
| 30092 |
'a126': 788, |
| 30093 |
'a127': 788, |
| 30094 |
'a128': 788, |
| 30095 |
'a129': 788, |
| 30096 |
'a130': 788, |
| 30097 |
'a131': 788, |
| 30098 |
'a132': 788, |
| 30099 |
'a133': 788, |
| 30100 |
'a134': 788, |
| 30101 |
'a135': 788, |
| 30102 |
'a136': 788, |
| 30103 |
'a137': 788, |
| 30104 |
'a138': 788, |
| 30105 |
'a139': 788, |
| 30106 |
'a140': 788, |
| 30107 |
'a141': 788, |
| 30108 |
'a142': 788, |
| 30109 |
'a143': 788, |
| 30110 |
'a144': 788, |
| 30111 |
'a145': 788, |
| 30112 |
'a146': 788, |
| 30113 |
'a147': 788, |
| 30114 |
'a148': 788, |
| 30115 |
'a149': 788, |
| 30116 |
'a150': 788, |
| 30117 |
'a151': 788, |
| 30118 |
'a152': 788, |
| 30119 |
'a153': 788, |
| 30120 |
'a154': 788, |
| 30121 |
'a155': 788, |
| 30122 |
'a156': 788, |
| 30123 |
'a157': 788, |
| 30124 |
'a158': 788, |
| 30125 |
'a159': 788, |
| 30126 |
'a160': 894, |
| 30127 |
'a161': 838, |
| 30128 |
'a163': 1016, |
| 30129 |
'a164': 458, |
| 30130 |
'a196': 748, |
| 30131 |
'a165': 924, |
| 30132 |
'a192': 748, |
| 30133 |
'a166': 918, |
| 30134 |
'a167': 927, |
| 30135 |
'a168': 928, |
| 30136 |
'a169': 928, |
| 30137 |
'a170': 834, |
| 30138 |
'a171': 873, |
| 30139 |
'a172': 828, |
| 30140 |
'a173': 924, |
| 30141 |
'a162': 924, |
| 30142 |
'a174': 917, |
| 30143 |
'a175': 930, |
| 30144 |
'a176': 931, |
| 30145 |
'a177': 463, |
| 30146 |
'a178': 883, |
| 30147 |
'a179': 836, |
| 30148 |
'a193': 836, |
| 30149 |
'a180': 867, |
| 30150 |
'a199': 867, |
| 30151 |
'a181': 696, |
| 30152 |
'a200': 696, |
| 30153 |
'a182': 874, |
| 30154 |
'a201': 874, |
| 30155 |
'a183': 760, |
| 30156 |
'a184': 946, |
| 30157 |
'a197': 771, |
| 30158 |
'a185': 865, |
| 30159 |
'a194': 771, |
| 30160 |
'a198': 888, |
| 30161 |
'a186': 967, |
| 30162 |
'a195': 888, |
| 30163 |
'a187': 831, |
| 30164 |
'a188': 873, |
| 30165 |
'a189': 927, |
| 30166 |
'a190': 970, |
| 30167 |
'a191': 918 |
| 30168 |
} |
| 30169 |
}; |
| 30170 |
|
| 30171 |
|
| 30172 |
var EOF = {}; |
| 30173 |
|
| 30174 |
function isEOF(v) { |
| 30175 |
return (v === EOF); |
| 30176 |
} |
| 30177 |
|
| 30178 |
var MAX_LENGTH_TO_CACHE = 1000; |
| 30179 |
|
| 30180 |
var Parser = (function ParserClosure() { |
| 30181 |
function Parser(lexer, allowStreams, xref) { |
| 30182 |
this.lexer = lexer; |
| 30183 |
this.allowStreams = allowStreams; |
| 30184 |
this.xref = xref; |
| 30185 |
this.imageCache = {}; |
| 30186 |
this.refill(); |
| 30187 |
} |
| 30188 |
|
| 30189 |
Parser.prototype = { |
| 30190 |
refill: function Parser_refill() { |
| 30191 |
this.buf1 = this.lexer.getObj(); |
| 30192 |
this.buf2 = this.lexer.getObj(); |
| 30193 |
}, |
| 30194 |
shift: function Parser_shift() { |
| 30195 |
if (isCmd(this.buf2, 'ID')) { |
| 30196 |
this.buf1 = this.buf2; |
| 30197 |
this.buf2 = null; |
| 30198 |
} else { |
| 30199 |
this.buf1 = this.buf2; |
| 30200 |
this.buf2 = this.lexer.getObj(); |
| 30201 |
} |
| 30202 |
}, |
| 30203 |
getObj: function Parser_getObj(cipherTransform) { |
| 30204 |
var buf1 = this.buf1; |
| 30205 |
this.shift(); |
| 30206 |
|
| 30207 |
if (buf1 instanceof Cmd) { |
| 30208 |
switch (buf1.cmd) { |
| 30209 |
case 'BI': // inline image |
| 30210 |
return this.makeInlineImage(cipherTransform); |
| 30211 |
case '[': // array |
| 30212 |
var array = []; |
| 30213 |
while (!isCmd(this.buf1, ']') && !isEOF(this.buf1)) { |
| 30214 |
array.push(this.getObj(cipherTransform)); |
| 30215 |
} |
| 30216 |
if (isEOF(this.buf1)) { |
| 30217 |
error('End of file inside array'); |
| 30218 |
} |
| 30219 |
this.shift(); |
| 30220 |
return array; |
| 30221 |
case '<<': // dictionary or stream |
| 30222 |
var dict = new Dict(this.xref); |
| 30223 |
while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) { |
| 30224 |
if (!isName(this.buf1)) { |
| 30225 |
info('Malformed dictionary: key must be a name object'); |
| 30226 |
this.shift(); |
| 30227 |
continue; |
| 30228 |
} |
| 30229 |
|
| 30230 |
var key = this.buf1.name; |
| 30231 |
this.shift(); |
| 30232 |
if (isEOF(this.buf1)) { |
| 30233 |
break; |
| 30234 |
} |
| 30235 |
dict.set(key, this.getObj(cipherTransform)); |
| 30236 |
} |
| 30237 |
if (isEOF(this.buf1)) { |
| 30238 |
error('End of file inside dictionary'); |
| 30239 |
} |
| 30240 |
|
| 30241 |
// Stream objects are not allowed inside content streams or |
| 30242 |
// object streams. |
| 30243 |
if (isCmd(this.buf2, 'stream')) { |
| 30244 |
return (this.allowStreams ? |
| 30245 |
this.makeStream(dict, cipherTransform) : dict); |
| 30246 |
} |
| 30247 |
this.shift(); |
| 30248 |
return dict; |
| 30249 |
default: // simple object |
| 30250 |
return buf1; |
| 30251 |
} |
| 30252 |
} |
| 30253 |
|
| 30254 |
if (isInt(buf1)) { // indirect reference or integer |
| 30255 |
var num = buf1; |
| 30256 |
if (isInt(this.buf1) && isCmd(this.buf2, 'R')) { |
| 30257 |
var ref = new Ref(num, this.buf1); |
| 30258 |
this.shift(); |
| 30259 |
this.shift(); |
| 30260 |
return ref; |
| 30261 |
} |
| 30262 |
return num; |
| 30263 |
} |
| 30264 |
|
| 30265 |
if (isString(buf1)) { // string |
| 30266 |
var str = buf1; |
| 30267 |
if (cipherTransform) { |
| 30268 |
str = cipherTransform.decryptString(str); |
| 30269 |
} |
| 30270 |
return str; |
| 30271 |
} |
| 30272 |
|
| 30273 |
// simple object |
| 30274 |
return buf1; |
| 30275 |
}, |
| 30276 |
/** |
| 30277 |
* Find the end of the stream by searching for the /EI\s/. |
| 30278 |
* @returns {number} The inline stream length. |
| 30279 |
*/ |
| 30280 |
findDefaultInlineStreamEnd: |
| 30281 |
function Parser_findDefaultInlineStreamEnd(stream) { |
| 30282 |
var E = 0x45, I = 0x49, SPACE = 0x20, LF = 0xA, CR = 0xD; |
| 30283 |
var startPos = stream.pos, state = 0, ch, i, n, followingBytes; |
| 30284 |
while ((ch = stream.getByte()) !== -1) { |
| 30285 |
if (state === 0) { |
| 30286 |
state = (ch === E) ? 1 : 0; |
| 30287 |
} else if (state === 1) { |
| 30288 |
state = (ch === I) ? 2 : 0; |
| 30289 |
} else { |
| 30290 |
assert(state === 2); |
| 30291 |
if (ch === SPACE || ch === LF || ch === CR) { |
| 30292 |
// Let's check the next five bytes are ASCII... just be sure. |
| 30293 |
n = 5; |
| 30294 |
followingBytes = stream.peekBytes(n); |
| 30295 |
for (i = 0; i < n; i++) { |
| 30296 |
ch = followingBytes[i]; |
| 30297 |
if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) { |
| 30298 |
// Not a LF, CR, SPACE or any visible ASCII character, i.e. |
| 30299 |
// it's binary stuff. Resetting the state. |
| 30300 |
state = 0; |
| 30301 |
break; |
| 30302 |
} |
| 30303 |
} |
| 30304 |
if (state === 2) { |
| 30305 |
break; // Finished! |
| 30306 |
} |
| 30307 |
} else { |
| 30308 |
state = 0; |
| 30309 |
} |
| 30310 |
} |
| 30311 |
} |
| 30312 |
return ((stream.pos - 4) - startPos); |
| 30313 |
}, |
| 30314 |
/** |
| 30315 |
* Find the EOI (end-of-image) marker 0xFFD9 of the stream. |
| 30316 |
* @returns {number} The inline stream length. |
| 30317 |
*/ |
| 30318 |
findDCTDecodeInlineStreamEnd: |
| 30319 |
function Parser_findDCTDecodeInlineStreamEnd(stream) { |
| 30320 |
var startPos = stream.pos, foundEOI = false, b, markerLength, length; |
| 30321 |
while ((b = stream.getByte()) !== -1) { |
| 30322 |
if (b !== 0xFF) { // Not a valid marker. |
| 30323 |
continue; |
| 30324 |
} |
| 30325 |
switch (stream.getByte()) { |
| 30326 |
case 0x00: // Byte stuffing. |
| 30327 |
// 0xFF00 appears to be a very common byte sequence in JPEG images. |
| 30328 |
break; |
| 30329 |
|
| 30330 |
case 0xFF: // Fill byte. |
| 30331 |
// Avoid skipping a valid marker, resetting the stream position. |
| 30332 |
stream.skip(-1); |
| 30333 |
break; |
| 30334 |
|
| 30335 |
case 0xD9: // EOI |
| 30336 |
foundEOI = true; |
| 30337 |
break; |
| 30338 |
|
| 30339 |
case 0xC0: // SOF0 |
| 30340 |
case 0xC1: // SOF1 |
| 30341 |
case 0xC2: // SOF2 |
| 30342 |
case 0xC3: // SOF3 |
| 30343 |
|
| 30344 |
case 0xC5: // SOF5 |
| 30345 |
case 0xC6: // SOF6 |
| 30346 |
case 0xC7: // SOF7 |
| 30347 |
|
| 30348 |
case 0xC9: // SOF9 |
| 30349 |
case 0xCA: // SOF10 |
| 30350 |
case 0xCB: // SOF11 |
| 30351 |
|
| 30352 |
case 0xCD: // SOF13 |
| 30353 |
case 0xCE: // SOF14 |
| 30354 |
case 0xCF: // SOF15 |
| 30355 |
|
| 30356 |
case 0xC4: // DHT |
| 30357 |
case 0xCC: // DAC |
| 30358 |
|
| 30359 |
case 0xDA: // SOS |
| 30360 |
case 0xDB: // DQT |
| 30361 |
case 0xDC: // DNL |
| 30362 |
case 0xDD: // DRI |
| 30363 |
case 0xDE: // DHP |
| 30364 |
case 0xDF: // EXP |
| 30365 |
|
| 30366 |
case 0xE0: // APP0 |
| 30367 |
case 0xE1: // APP1 |
| 30368 |
case 0xE2: // APP2 |
| 30369 |
case 0xE3: // APP3 |
| 30370 |
case 0xE4: // APP4 |
| 30371 |
case 0xE5: // APP5 |
| 30372 |
case 0xE6: // APP6 |
| 30373 |
case 0xE7: // APP7 |
| 30374 |
case 0xE8: // APP8 |
| 30375 |
case 0xE9: // APP9 |
| 30376 |
case 0xEA: // APP10 |
| 30377 |
case 0xEB: // APP11 |
| 30378 |
case 0xEC: // APP12 |
| 30379 |
case 0xED: // APP13 |
| 30380 |
case 0xEE: // APP14 |
| 30381 |
case 0xEF: // APP15 |
| 30382 |
|
| 30383 |
case 0xFE: // COM |
| 30384 |
// The marker should be followed by the length of the segment. |
| 30385 |
markerLength = stream.getUint16(); |
| 30386 |
if (markerLength > 2) { |
| 30387 |
// |markerLength| contains the byte length of the marker segment, |
| 30388 |
// including its own length (2 bytes) and excluding the marker. |
| 30389 |
stream.skip(markerLength - 2); // Jump to the next marker. |
| 30390 |
} else { |
| 30391 |
// The marker length is invalid, resetting the stream position. |
| 30392 |
stream.skip(-2); |
| 30393 |
} |
| 30394 |
break; |
| 30395 |
} |
| 30396 |
if (foundEOI) { |
| 30397 |
break; |
| 30398 |
} |
| 30399 |
} |
| 30400 |
length = stream.pos - startPos; |
| 30401 |
if (b === -1) { |
| 30402 |
warn('Inline DCTDecode image stream: ' + |
| 30403 |
'EOI marker not found, searching for /EI/ instead.'); |
| 30404 |
stream.skip(-length); // Reset the stream position. |
| 30405 |
return this.findDefaultInlineStreamEnd(stream); |
| 30406 |
} |
| 30407 |
this.inlineStreamSkipEI(stream); |
| 30408 |
return length; |
| 30409 |
}, |
| 30410 |
/** |
| 30411 |
* Find the EOD (end-of-data) marker '~>' (i.e. TILDE + GT) of the stream. |
| 30412 |
* @returns {number} The inline stream length. |
| 30413 |
*/ |
| 30414 |
findASCII85DecodeInlineStreamEnd: |
| 30415 |
function Parser_findASCII85DecodeInlineStreamEnd(stream) { |
| 30416 |
var TILDE = 0x7E, GT = 0x3E; |
| 30417 |
var startPos = stream.pos, ch, length; |
| 30418 |
while ((ch = stream.getByte()) !== -1) { |
| 30419 |
if (ch === TILDE && stream.peekByte() === GT) { |
| 30420 |
stream.skip(); |
| 30421 |
break; |
| 30422 |
} |
| 30423 |
} |
| 30424 |
length = stream.pos - startPos; |
| 30425 |
if (ch === -1) { |
| 30426 |
warn('Inline ASCII85Decode image stream: ' + |
| 30427 |
'EOD marker not found, searching for /EI/ instead.'); |
| 30428 |
stream.skip(-length); // Reset the stream position. |
| 30429 |
return this.findDefaultInlineStreamEnd(stream); |
| 30430 |
} |
| 30431 |
this.inlineStreamSkipEI(stream); |
| 30432 |
return length; |
| 30433 |
}, |
| 30434 |
/** |
| 30435 |
* Find the EOD (end-of-data) marker '>' (i.e. GT) of the stream. |
| 30436 |
* @returns {number} The inline stream length. |
| 30437 |
*/ |
| 30438 |
findASCIIHexDecodeInlineStreamEnd: |
| 30439 |
function Parser_findASCIIHexDecodeInlineStreamEnd(stream) { |
| 30440 |
var GT = 0x3E; |
| 30441 |
var startPos = stream.pos, ch, length; |
| 30442 |
while ((ch = stream.getByte()) !== -1) { |
| 30443 |
if (ch === GT) { |
| 30444 |
break; |
| 30445 |
} |
| 30446 |
} |
| 30447 |
length = stream.pos - startPos; |
| 30448 |
if (ch === -1) { |
| 30449 |
warn('Inline ASCIIHexDecode image stream: ' + |
| 30450 |
'EOD marker not found, searching for /EI/ instead.'); |
| 30451 |
stream.skip(-length); // Reset the stream position. |
| 30452 |
return this.findDefaultInlineStreamEnd(stream); |
| 30453 |
} |
| 30454 |
this.inlineStreamSkipEI(stream); |
| 30455 |
return length; |
| 30456 |
}, |
| 30457 |
/** |
| 30458 |
* Skip over the /EI/ for streams where we search for an EOD marker. |
| 30459 |
*/ |
| 30460 |
inlineStreamSkipEI: function Parser_inlineStreamSkipEI(stream) { |
| 30461 |
var E = 0x45, I = 0x49; |
| 30462 |
var state = 0, ch; |
| 30463 |
while ((ch = stream.getByte()) !== -1) { |
| 30464 |
if (state === 0) { |
| 30465 |
state = (ch === E) ? 1 : 0; |
| 30466 |
} else if (state === 1) { |
| 30467 |
state = (ch === I) ? 2 : 0; |
| 30468 |
} else if (state === 2) { |
| 30469 |
break; |
| 30470 |
} |
| 30471 |
} |
| 30472 |
}, |
| 30473 |
makeInlineImage: function Parser_makeInlineImage(cipherTransform) { |
| 30474 |
var lexer = this.lexer; |
| 30475 |
var stream = lexer.stream; |
| 30476 |
|
| 30477 |
// Parse dictionary. |
| 30478 |
var dict = new Dict(null); |
| 30479 |
while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) { |
| 30480 |
if (!isName(this.buf1)) { |
| 30481 |
error('Dictionary key must be a name object'); |
| 30482 |
} |
| 30483 |
var key = this.buf1.name; |
| 30484 |
this.shift(); |
| 30485 |
if (isEOF(this.buf1)) { |
| 30486 |
break; |
| 30487 |
} |
| 30488 |
dict.set(key, this.getObj(cipherTransform)); |
| 30489 |
} |
| 30490 |
|
| 30491 |
// Extract the name of the first (i.e. the current) image filter. |
| 30492 |
var filter = this.fetchIfRef(dict.get('Filter', 'F')), filterName; |
| 30493 |
if (isName(filter)) { |
| 30494 |
filterName = filter.name; |
| 30495 |
} else if (isArray(filter) && isName(filter[0])) { |
| 30496 |
filterName = filter[0].name; |
| 30497 |
} |
| 30498 |
|
| 30499 |
// Parse image stream. |
| 30500 |
var startPos = stream.pos, length, i, ii; |
| 30501 |
if (filterName === 'DCTDecode' || filterName === 'DCT') { |
| 30502 |
length = this.findDCTDecodeInlineStreamEnd(stream); |
| 30503 |
} else if (filterName === 'ASCII85Decide' || filterName === 'A85') { |
| 30504 |
length = this.findASCII85DecodeInlineStreamEnd(stream); |
| 30505 |
} else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') { |
| 30506 |
length = this.findASCIIHexDecodeInlineStreamEnd(stream); |
| 30507 |
} else { |
| 30508 |
length = this.findDefaultInlineStreamEnd(stream); |
| 30509 |
} |
| 30510 |
var imageStream = stream.makeSubStream(startPos, length, dict); |
| 30511 |
|
| 30512 |
// Cache all images below the MAX_LENGTH_TO_CACHE threshold by their |
| 30513 |
// adler32 checksum. |
| 30514 |
var adler32; |
| 30515 |
if (length < MAX_LENGTH_TO_CACHE) { |
| 30516 |
var imageBytes = imageStream.getBytes(); |
| 30517 |
imageStream.reset(); |
| 30518 |
|
| 30519 |
var a = 1; |
| 30520 |
var b = 0; |
| 30521 |
for (i = 0, ii = imageBytes.length; i < ii; ++i) { |
| 30522 |
// No modulo required in the loop if imageBytes.length < 5552. |
| 30523 |
a += imageBytes[i] & 0xff; |
| 30524 |
b += a; |
| 30525 |
} |
| 30526 |
adler32 = ((b % 65521) << 16) | (a % 65521); |
| 30527 |
|
| 30528 |
if (this.imageCache.adler32 === adler32) { |
| 30529 |
this.buf2 = Cmd.get('EI'); |
| 30530 |
this.shift(); |
| 30531 |
|
| 30532 |
this.imageCache[adler32].reset(); |
| 30533 |
return this.imageCache[adler32]; |
| 30534 |
} |
| 30535 |
} |
| 30536 |
|
| 30537 |
if (cipherTransform) { |
| 30538 |
imageStream = cipherTransform.createStream(imageStream, length); |
| 30539 |
} |
| 30540 |
|
| 30541 |
imageStream = this.filter(imageStream, dict, length); |
| 30542 |
imageStream.dict = dict; |
| 30543 |
if (adler32 !== undefined) { |
| 30544 |
imageStream.cacheKey = 'inline_' + length + '_' + adler32; |
| 30545 |
this.imageCache[adler32] = imageStream; |
| 30546 |
} |
| 30547 |
|
| 30548 |
this.buf2 = Cmd.get('EI'); |
| 30549 |
this.shift(); |
| 30550 |
|
| 30551 |
return imageStream; |
| 30552 |
}, |
| 30553 |
fetchIfRef: function Parser_fetchIfRef(obj) { |
| 30554 |
// not relying on the xref.fetchIfRef -- xref might not be set |
| 30555 |
return (isRef(obj) ? this.xref.fetch(obj) : obj); |
| 30556 |
}, |
| 30557 |
makeStream: function Parser_makeStream(dict, cipherTransform) { |
| 30558 |
var lexer = this.lexer; |
| 30559 |
var stream = lexer.stream; |
| 30560 |
|
| 30561 |
// get stream start position |
| 30562 |
lexer.skipToNextLine(); |
| 30563 |
var pos = stream.pos - 1; |
| 30564 |
|
| 30565 |
// get length |
| 30566 |
var length = this.fetchIfRef(dict.get('Length')); |
| 30567 |
if (!isInt(length)) { |
| 30568 |
info('Bad ' + length + ' attribute in stream'); |
| 30569 |
length = 0; |
| 30570 |
} |
| 30571 |
|
| 30572 |
// skip over the stream data |
| 30573 |
stream.pos = pos + length; |
| 30574 |
lexer.nextChar(); |
| 30575 |
|
| 30576 |
this.shift(); // '>>' |
| 30577 |
this.shift(); // 'stream' |
| 30578 |
if (!isCmd(this.buf1, 'endstream')) { |
| 30579 |
// bad stream length, scanning for endstream |
| 30580 |
stream.pos = pos; |
| 30581 |
var SCAN_BLOCK_SIZE = 2048; |
| 30582 |
var ENDSTREAM_SIGNATURE_LENGTH = 9; |
| 30583 |
var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, |
| 30584 |
0x61, 0x6D]; |
| 30585 |
var skipped = 0, found = false, i, j; |
| 30586 |
while (stream.pos < stream.end) { |
| 30587 |
var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE); |
| 30588 |
var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH; |
| 30589 |
if (scanLength <= 0) { |
| 30590 |
break; |
| 30591 |
} |
| 30592 |
found = false; |
| 30593 |
for (i = 0, j = 0; i < scanLength; i++) { |
| 30594 |
var b = scanBytes[i]; |
| 30595 |
if (b !== ENDSTREAM_SIGNATURE[j]) { |
| 30596 |
i -= j; |
| 30597 |
j = 0; |
| 30598 |
} else { |
| 30599 |
j++; |
| 30600 |
if (j >= ENDSTREAM_SIGNATURE_LENGTH) { |
| 30601 |
i++; |
| 30602 |
found = true; |
| 30603 |
break; |
| 30604 |
} |
| 30605 |
} |
| 30606 |
} |
| 30607 |
if (found) { |
| 30608 |
skipped += i - ENDSTREAM_SIGNATURE_LENGTH; |
| 30609 |
stream.pos += i - ENDSTREAM_SIGNATURE_LENGTH; |
| 30610 |
break; |
| 30611 |
} |
| 30612 |
skipped += scanLength; |
| 30613 |
stream.pos += scanLength; |
| 30614 |
} |
| 30615 |
if (!found) { |
| 30616 |
error('Missing endstream'); |
| 30617 |
} |
| 30618 |
length = skipped; |
| 30619 |
|
| 30620 |
lexer.nextChar(); |
| 30621 |
this.shift(); |
| 30622 |
this.shift(); |
| 30623 |
} |
| 30624 |
this.shift(); // 'endstream' |
| 30625 |
|
| 30626 |
stream = stream.makeSubStream(pos, length, dict); |
| 30627 |
if (cipherTransform) { |
| 30628 |
stream = cipherTransform.createStream(stream, length); |
| 30629 |
} |
| 30630 |
stream = this.filter(stream, dict, length); |
| 30631 |
stream.dict = dict; |
| 30632 |
return stream; |
| 30633 |
}, |
| 30634 |
filter: function Parser_filter(stream, dict, length) { |
| 30635 |
var filter = this.fetchIfRef(dict.get('Filter', 'F')); |
| 30636 |
var params = this.fetchIfRef(dict.get('DecodeParms', 'DP')); |
| 30637 |
if (isName(filter)) { |
| 30638 |
return this.makeFilter(stream, filter.name, length, params); |
| 30639 |
} |
| 30640 |
|
| 30641 |
var maybeLength = length; |
| 30642 |
if (isArray(filter)) { |
| 30643 |
var filterArray = filter; |
| 30644 |
var paramsArray = params; |
| 30645 |
for (var i = 0, ii = filterArray.length; i < ii; ++i) { |
| 30646 |
filter = filterArray[i]; |
| 30647 |
if (!isName(filter)) { |
| 30648 |
error('Bad filter name: ' + filter); |
| 30649 |
} |
| 30650 |
|
| 30651 |
params = null; |
| 30652 |
if (isArray(paramsArray) && (i in paramsArray)) { |
| 30653 |
params = paramsArray[i]; |
| 30654 |
} |
| 30655 |
stream = this.makeFilter(stream, filter.name, maybeLength, params); |
| 30656 |
// after the first stream the length variable is invalid |
| 30657 |
maybeLength = null; |
| 30658 |
} |
| 30659 |
} |
| 30660 |
return stream; |
| 30661 |
}, |
| 30662 |
makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) { |
| 30663 |
if (stream.dict.get('Length') === 0) { |
| 30664 |
return new NullStream(stream); |
| 30665 |
} |
| 30666 |
try { |
| 30667 |
if (params) { |
| 30668 |
params = this.fetchIfRef(params); |
| 30669 |
} |
| 30670 |
var xrefStreamStats = this.xref.stats.streamTypes; |
| 30671 |
if (name === 'FlateDecode' || name === 'Fl') { |
| 30672 |
xrefStreamStats[StreamType.FLATE] = true; |
| 30673 |
if (params) { |
| 30674 |
return new PredictorStream(new FlateStream(stream, maybeLength), |
| 30675 |
maybeLength, params); |
| 30676 |
} |
| 30677 |
return new FlateStream(stream, maybeLength); |
| 30678 |
} |
| 30679 |
if (name === 'LZWDecode' || name === 'LZW') { |
| 30680 |
xrefStreamStats[StreamType.LZW] = true; |
| 30681 |
var earlyChange = 1; |
| 30682 |
if (params) { |
| 30683 |
if (params.has('EarlyChange')) { |
| 30684 |
earlyChange = params.get('EarlyChange'); |
| 30685 |
} |
| 30686 |
return new PredictorStream( |
| 30687 |
new LZWStream(stream, maybeLength, earlyChange), |
| 30688 |
maybeLength, params); |
| 30689 |
} |
| 30690 |
return new LZWStream(stream, maybeLength, earlyChange); |
| 30691 |
} |
| 30692 |
if (name === 'DCTDecode' || name === 'DCT') { |
| 30693 |
xrefStreamStats[StreamType.DCT] = true; |
| 30694 |
return new JpegStream(stream, maybeLength, stream.dict, this.xref); |
| 30695 |
} |
| 30696 |
if (name === 'JPXDecode' || name === 'JPX') { |
| 30697 |
xrefStreamStats[StreamType.JPX] = true; |
| 30698 |
return new JpxStream(stream, maybeLength, stream.dict); |
| 30699 |
} |
| 30700 |
if (name === 'ASCII85Decode' || name === 'A85') { |
| 30701 |
xrefStreamStats[StreamType.A85] = true; |
| 30702 |
return new Ascii85Stream(stream, maybeLength); |
| 30703 |
} |
| 30704 |
if (name === 'ASCIIHexDecode' || name === 'AHx') { |
| 30705 |
xrefStreamStats[StreamType.AHX] = true; |
| 30706 |
return new AsciiHexStream(stream, maybeLength); |
| 30707 |
} |
| 30708 |
if (name === 'CCITTFaxDecode' || name === 'CCF') { |
| 30709 |
xrefStreamStats[StreamType.CCF] = true; |
| 30710 |
return new CCITTFaxStream(stream, maybeLength, params); |
| 30711 |
} |
| 30712 |
if (name === 'RunLengthDecode' || name === 'RL') { |
| 30713 |
xrefStreamStats[StreamType.RL] = true; |
| 30714 |
return new RunLengthStream(stream, maybeLength); |
| 30715 |
} |
| 30716 |
if (name === 'JBIG2Decode') { |
| 30717 |
xrefStreamStats[StreamType.JBIG] = true; |
| 30718 |
return new Jbig2Stream(stream, maybeLength, stream.dict); |
| 30719 |
} |
| 30720 |
warn('filter "' + name + '" not supported yet'); |
| 30721 |
return stream; |
| 30722 |
} catch (ex) { |
| 30723 |
if (ex instanceof MissingDataException) { |
| 30724 |
throw ex; |
| 30725 |
} |
| 30726 |
warn('Invalid stream: \"' + ex + '\"'); |
| 30727 |
return new NullStream(stream); |
| 30728 |
} |
| 30729 |
} |
| 30730 |
}; |
| 30731 |
|
| 30732 |
return Parser; |
| 30733 |
})(); |
| 30734 |
|
| 30735 |
var Lexer = (function LexerClosure() { |
| 30736 |
function Lexer(stream, knownCommands) { |
| 30737 |
this.stream = stream; |
| 30738 |
this.nextChar(); |
| 30739 |
|
| 30740 |
// While lexing, we build up many strings one char at a time. Using += for |
| 30741 |
// this can result in lots of garbage strings. It's better to build an |
| 30742 |
// array of single-char strings and then join() them together at the end. |
| 30743 |
// And reusing a single array (i.e. |this.strBuf|) over and over for this |
| 30744 |
// purpose uses less memory than using a new array for each string. |
| 30745 |
this.strBuf = []; |
| 30746 |
|
| 30747 |
// The PDFs might have "glued" commands with other commands, operands or |
| 30748 |
// literals, e.g. "q1". The knownCommands is a dictionary of the valid |
| 30749 |
// commands and their prefixes. The prefixes are built the following way: |
| 30750 |
// if there a command that is a prefix of the other valid command or |
| 30751 |
// literal (e.g. 'f' and 'false') the following prefixes must be included, |
| 30752 |
// 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no |
| 30753 |
// other commands or literals as a prefix. The knowCommands is optional. |
| 30754 |
this.knownCommands = knownCommands; |
| 30755 |
} |
| 30756 |
|
| 30757 |
Lexer.isSpace = function Lexer_isSpace(ch) { |
| 30758 |
// Space is one of the following characters: SPACE, TAB, CR or LF. |
| 30759 |
return (ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A); |
| 30760 |
}; |
| 30761 |
|
| 30762 |
// A '1' in this array means the character is white space. A '1' or |
| 30763 |
// '2' means the character ends a name or command. |
| 30764 |
var specialChars = [ |
| 30765 |
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x |
| 30766 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x |
| 30767 |
1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x |
| 30768 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x |
| 30769 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x |
| 30770 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x |
| 30771 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x |
| 30772 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x |
| 30773 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x |
| 30774 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x |
| 30775 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax |
| 30776 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx |
| 30777 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx |
| 30778 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx |
| 30779 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex |
| 30780 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx |
| 30781 |
]; |
| 30782 |
|
| 30783 |
function toHexDigit(ch) { |
| 30784 |
if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' |
| 30785 |
return ch & 0x0F; |
| 30786 |
} |
| 30787 |
if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { |
| 30788 |
// 'A'-'F', 'a'-'f' |
| 30789 |
return (ch & 0x0F) + 9; |
| 30790 |
} |
| 30791 |
return -1; |
| 30792 |
} |
| 30793 |
|
| 30794 |
Lexer.prototype = { |
| 30795 |
nextChar: function Lexer_nextChar() { |
| 30796 |
return (this.currentChar = this.stream.getByte()); |
| 30797 |
}, |
| 30798 |
peekChar: function Lexer_peekChar() { |
| 30799 |
return this.stream.peekByte(); |
| 30800 |
}, |
| 30801 |
getNumber: function Lexer_getNumber() { |
| 30802 |
var ch = this.currentChar; |
| 30803 |
var eNotation = false; |
| 30804 |
var divideBy = 0; // different from 0 if it's a floating point value |
| 30805 |
var sign = 1; |
| 30806 |
|
| 30807 |
if (ch === 0x2D) { // '-' |
| 30808 |
sign = -1; |
| 30809 |
ch = this.nextChar(); |
| 30810 |
} else if (ch === 0x2B) { // '+' |
| 30811 |
ch = this.nextChar(); |
| 30812 |
} |
| 30813 |
if (ch === 0x2E) { // '.' |
| 30814 |
divideBy = 10; |
| 30815 |
ch = this.nextChar(); |
| 30816 |
} |
| 30817 |
if (ch < 0x30 || ch > 0x39) { // '0' - '9' |
| 30818 |
error('Invalid number: ' + String.fromCharCode(ch)); |
| 30819 |
return 0; |
| 30820 |
} |
| 30821 |
|
| 30822 |
var baseValue = ch - 0x30; // '0' |
| 30823 |
var powerValue = 0; |
| 30824 |
var powerValueSign = 1; |
| 30825 |
|
| 30826 |
while ((ch = this.nextChar()) >= 0) { |
| 30827 |
if (0x30 <= ch && ch <= 0x39) { // '0' - '9' |
| 30828 |
var currentDigit = ch - 0x30; // '0' |
| 30829 |
if (eNotation) { // We are after an 'e' or 'E' |
| 30830 |
powerValue = powerValue * 10 + currentDigit; |
| 30831 |
} else { |
| 30832 |
if (divideBy !== 0) { // We are after a point |
| 30833 |
divideBy *= 10; |
| 30834 |
} |
| 30835 |
baseValue = baseValue * 10 + currentDigit; |
| 30836 |
} |
| 30837 |
} else if (ch === 0x2E) { // '.' |
| 30838 |
if (divideBy === 0) { |
| 30839 |
divideBy = 1; |
| 30840 |
} else { |
| 30841 |
// A number can have only one '.' |
| 30842 |
break; |
| 30843 |
} |
| 30844 |
} else if (ch === 0x2D) { // '-' |
| 30845 |
// ignore minus signs in the middle of numbers to match |
| 30846 |
// Adobe's behavior |
| 30847 |
warn('Badly formated number'); |
| 30848 |
} else if (ch === 0x45 || ch === 0x65) { // 'E', 'e' |
| 30849 |
// 'E' can be either a scientific notation or the beginning of a new |
| 30850 |
// operator |
| 30851 |
ch = this.peekChar(); |
| 30852 |
if (ch === 0x2B || ch === 0x2D) { // '+', '-' |
| 30853 |
powerValueSign = (ch === 0x2D) ? -1 : 1; |
| 30854 |
this.nextChar(); // Consume the sign character |
| 30855 |
} else if (ch < 0x30 || ch > 0x39) { // '0' - '9' |
| 30856 |
// The 'E' must be the beginning of a new operator |
| 30857 |
break; |
| 30858 |
} |
| 30859 |
eNotation = true; |
| 30860 |
} else { |
| 30861 |
// the last character doesn't belong to us |
| 30862 |
break; |
| 30863 |
} |
| 30864 |
} |
| 30865 |
|
| 30866 |
if (divideBy !== 0) { |
| 30867 |
baseValue /= divideBy; |
| 30868 |
} |
| 30869 |
if (eNotation) { |
| 30870 |
baseValue *= Math.pow(10, powerValueSign * powerValue); |
| 30871 |
} |
| 30872 |
return sign * baseValue; |
| 30873 |
}, |
| 30874 |
getString: function Lexer_getString() { |
| 30875 |
var numParen = 1; |
| 30876 |
var done = false; |
| 30877 |
var strBuf = this.strBuf; |
| 30878 |
strBuf.length = 0; |
| 30879 |
|
| 30880 |
var ch = this.nextChar(); |
| 30881 |
while (true) { |
| 30882 |
var charBuffered = false; |
| 30883 |
switch (ch | 0) { |
| 30884 |
case -1: |
| 30885 |
warn('Unterminated string'); |
| 30886 |
done = true; |
| 30887 |
break; |
| 30888 |
case 0x28: // '(' |
| 30889 |
++numParen; |
| 30890 |
strBuf.push('('); |
| 30891 |
break; |
| 30892 |
case 0x29: // ')' |
| 30893 |
if (--numParen === 0) { |
| 30894 |
this.nextChar(); // consume strings ')' |
| 30895 |
done = true; |
| 30896 |
} else { |
| 30897 |
strBuf.push(')'); |
| 30898 |
} |
| 30899 |
break; |
| 30900 |
case 0x5C: // '\\' |
| 30901 |
ch = this.nextChar(); |
| 30902 |
switch (ch) { |
| 30903 |
case -1: |
| 30904 |
warn('Unterminated string'); |
| 30905 |
done = true; |
| 30906 |
break; |
| 30907 |
case 0x6E: // 'n' |
| 30908 |
strBuf.push('\n'); |
| 30909 |
break; |
| 30910 |
case 0x72: // 'r' |
| 30911 |
strBuf.push('\r'); |
| 30912 |
break; |
| 30913 |
case 0x74: // 't' |
| 30914 |
strBuf.push('\t'); |
| 30915 |
break; |
| 30916 |
case 0x62: // 'b' |
| 30917 |
strBuf.push('\b'); |
| 30918 |
break; |
| 30919 |
case 0x66: // 'f' |
| 30920 |
strBuf.push('\f'); |
| 30921 |
break; |
| 30922 |
case 0x5C: // '\' |
| 30923 |
case 0x28: // '(' |
| 30924 |
case 0x29: // ')' |
| 30925 |
strBuf.push(String.fromCharCode(ch)); |
| 30926 |
break; |
| 30927 |
case 0x30: case 0x31: case 0x32: case 0x33: // '0'-'3' |
| 30928 |
case 0x34: case 0x35: case 0x36: case 0x37: // '4'-'7' |
| 30929 |
var x = ch & 0x0F; |
| 30930 |
ch = this.nextChar(); |
| 30931 |
charBuffered = true; |
| 30932 |
if (ch >= 0x30 && ch <= 0x37) { // '0'-'7' |
| 30933 |
x = (x << 3) + (ch & 0x0F); |
| 30934 |
ch = this.nextChar(); |
| 30935 |
if (ch >= 0x30 && ch <= 0x37) { // '0'-'7' |
| 30936 |
charBuffered = false; |
| 30937 |
x = (x << 3) + (ch & 0x0F); |
| 30938 |
} |
| 30939 |
} |
| 30940 |
strBuf.push(String.fromCharCode(x)); |
| 30941 |
break; |
| 30942 |
case 0x0D: // CR |
| 30943 |
if (this.peekChar() === 0x0A) { // LF |
| 30944 |
this.nextChar(); |
| 30945 |
} |
| 30946 |
break; |
| 30947 |
case 0x0A: // LF |
| 30948 |
break; |
| 30949 |
default: |
| 30950 |
strBuf.push(String.fromCharCode(ch)); |
| 30951 |
break; |
| 30952 |
} |
| 30953 |
break; |
| 30954 |
default: |
| 30955 |
strBuf.push(String.fromCharCode(ch)); |
| 30956 |
break; |
| 30957 |
} |
| 30958 |
if (done) { |
| 30959 |
break; |
| 30960 |
} |
| 30961 |
if (!charBuffered) { |
| 30962 |
ch = this.nextChar(); |
| 30963 |
} |
| 30964 |
} |
| 30965 |
return strBuf.join(''); |
| 30966 |
}, |
| 30967 |
getName: function Lexer_getName() { |
| 30968 |
var ch; |
| 30969 |
var strBuf = this.strBuf; |
| 30970 |
strBuf.length = 0; |
| 30971 |
while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { |
| 30972 |
if (ch === 0x23) { // '#' |
| 30973 |
ch = this.nextChar(); |
| 30974 |
var x = toHexDigit(ch); |
| 30975 |
if (x !== -1) { |
| 30976 |
var x2 = toHexDigit(this.nextChar()); |
| 30977 |
if (x2 === -1) { |
| 30978 |
error('Illegal digit in hex char in name: ' + x2); |
| 30979 |
} |
| 30980 |
strBuf.push(String.fromCharCode((x << 4) | x2)); |
| 30981 |
} else { |
| 30982 |
strBuf.push('#', String.fromCharCode(ch)); |
| 30983 |
} |
| 30984 |
} else { |
| 30985 |
strBuf.push(String.fromCharCode(ch)); |
| 30986 |
} |
| 30987 |
} |
| 30988 |
if (strBuf.length > 128) { |
| 30989 |
error('Warning: name token is longer than allowed by the spec: ' + |
| 30990 |
strBuf.length); |
| 30991 |
} |
| 30992 |
return Name.get(strBuf.join('')); |
| 30993 |
}, |
| 30994 |
getHexString: function Lexer_getHexString() { |
| 30995 |
var strBuf = this.strBuf; |
| 30996 |
strBuf.length = 0; |
| 30997 |
var ch = this.currentChar; |
| 30998 |
var isFirstHex = true; |
| 30999 |
var firstDigit; |
| 31000 |
var secondDigit; |
| 31001 |
while (true) { |
| 31002 |
if (ch < 0) { |
| 31003 |
warn('Unterminated hex string'); |
| 31004 |
break; |
| 31005 |
} else if (ch === 0x3E) { // '>' |
| 31006 |
this.nextChar(); |
| 31007 |
break; |
| 31008 |
} else if (specialChars[ch] === 1) { |
| 31009 |
ch = this.nextChar(); |
| 31010 |
continue; |
| 31011 |
} else { |
| 31012 |
if (isFirstHex) { |
| 31013 |
firstDigit = toHexDigit(ch); |
| 31014 |
if (firstDigit === -1) { |
| 31015 |
warn('Ignoring invalid character "' + ch + '" in hex string'); |
| 31016 |
ch = this.nextChar(); |
| 31017 |
continue; |
| 31018 |
} |
| 31019 |
} else { |
| 31020 |
secondDigit = toHexDigit(ch); |
| 31021 |
if (secondDigit === -1) { |
| 31022 |
warn('Ignoring invalid character "' + ch + '" in hex string'); |
| 31023 |
ch = this.nextChar(); |
| 31024 |
continue; |
| 31025 |
} |
| 31026 |
strBuf.push(String.fromCharCode((firstDigit << 4) | secondDigit)); |
| 31027 |
} |
| 31028 |
isFirstHex = !isFirstHex; |
| 31029 |
ch = this.nextChar(); |
| 31030 |
} |
| 31031 |
} |
| 31032 |
return strBuf.join(''); |
| 31033 |
}, |
| 31034 |
getObj: function Lexer_getObj() { |
| 31035 |
// skip whitespace and comments |
| 31036 |
var comment = false; |
| 31037 |
var ch = this.currentChar; |
| 31038 |
while (true) { |
| 31039 |
if (ch < 0) { |
| 31040 |
return EOF; |
| 31041 |
} |
| 31042 |
if (comment) { |
| 31043 |
if (ch === 0x0A || ch === 0x0D) { // LF, CR |
| 31044 |
comment = false; |
| 31045 |
} |
| 31046 |
} else if (ch === 0x25) { // '%' |
| 31047 |
comment = true; |
| 31048 |
} else if (specialChars[ch] !== 1) { |
| 31049 |
break; |
| 31050 |
} |
| 31051 |
ch = this.nextChar(); |
| 31052 |
} |
| 31053 |
|
| 31054 |
// start reading token |
| 31055 |
switch (ch | 0) { |
| 31056 |
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4' |
| 31057 |
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9' |
| 31058 |
case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.' |
| 31059 |
return this.getNumber(); |
| 31060 |
case 0x28: // '(' |
| 31061 |
return this.getString(); |
| 31062 |
case 0x2F: // '/' |
| 31063 |
return this.getName(); |
| 31064 |
// array punctuation |
| 31065 |
case 0x5B: // '[' |
| 31066 |
this.nextChar(); |
| 31067 |
return Cmd.get('['); |
| 31068 |
case 0x5D: // ']' |
| 31069 |
this.nextChar(); |
| 31070 |
return Cmd.get(']'); |
| 31071 |
// hex string or dict punctuation |
| 31072 |
case 0x3C: // '<' |
| 31073 |
ch = this.nextChar(); |
| 31074 |
if (ch === 0x3C) { |
| 31075 |
// dict punctuation |
| 31076 |
this.nextChar(); |
| 31077 |
return Cmd.get('<<'); |
| 31078 |
} |
| 31079 |
return this.getHexString(); |
| 31080 |
// dict punctuation |
| 31081 |
case 0x3E: // '>' |
| 31082 |
ch = this.nextChar(); |
| 31083 |
if (ch === 0x3E) { |
| 31084 |
this.nextChar(); |
| 31085 |
return Cmd.get('>>'); |
| 31086 |
} |
| 31087 |
return Cmd.get('>'); |
| 31088 |
case 0x7B: // '{' |
| 31089 |
this.nextChar(); |
| 31090 |
return Cmd.get('{'); |
| 31091 |
case 0x7D: // '}' |
| 31092 |
this.nextChar(); |
| 31093 |
return Cmd.get('}'); |
| 31094 |
case 0x29: // ')' |
| 31095 |
error('Illegal character: ' + ch); |
| 31096 |
break; |
| 31097 |
} |
| 31098 |
|
| 31099 |
// command |
| 31100 |
var str = String.fromCharCode(ch); |
| 31101 |
var knownCommands = this.knownCommands; |
| 31102 |
var knownCommandFound = knownCommands && knownCommands[str] !== undefined; |
| 31103 |
while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { |
| 31104 |
// stop if known command is found and next character does not make |
| 31105 |
// the str a command |
| 31106 |
var possibleCommand = str + String.fromCharCode(ch); |
| 31107 |
if (knownCommandFound && knownCommands[possibleCommand] === undefined) { |
| 31108 |
break; |
| 31109 |
} |
| 31110 |
if (str.length === 128) { |
| 31111 |
error('Command token too long: ' + str.length); |
| 31112 |
} |
| 31113 |
str = possibleCommand; |
| 31114 |
knownCommandFound = knownCommands && knownCommands[str] !== undefined; |
| 31115 |
} |
| 31116 |
if (str === 'true') { |
| 31117 |
return true; |
| 31118 |
} |
| 31119 |
if (str === 'false') { |
| 31120 |
return false; |
| 31121 |
} |
| 31122 |
if (str === 'null') { |
| 31123 |
return null; |
| 31124 |
} |
| 31125 |
return Cmd.get(str); |
| 31126 |
}, |
| 31127 |
skipToNextLine: function Lexer_skipToNextLine() { |
| 31128 |
var ch = this.currentChar; |
| 31129 |
while (ch >= 0) { |
| 31130 |
if (ch === 0x0D) { // CR |
| 31131 |
ch = this.nextChar(); |
| 31132 |
if (ch === 0x0A) { // LF |
| 31133 |
this.nextChar(); |
| 31134 |
} |
| 31135 |
break; |
| 31136 |
} else if (ch === 0x0A) { // LF |
| 31137 |
this.nextChar(); |
| 31138 |
break; |
| 31139 |
} |
| 31140 |
ch = this.nextChar(); |
| 31141 |
} |
| 31142 |
} |
| 31143 |
}; |
| 31144 |
|
| 31145 |
return Lexer; |
| 31146 |
})(); |
| 31147 |
|
| 31148 |
var Linearization = { |
| 31149 |
create: function LinearizationCreate(stream) { |
| 31150 |
function getInt(name, allowZeroValue) { |
| 31151 |
var obj = linDict.get(name); |
| 31152 |
if (isInt(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) { |
| 31153 |
return obj; |
| 31154 |
} |
| 31155 |
throw new Error('The "' + name + '" parameter in the linearization ' + |
| 31156 |
'dictionary is invalid.'); |
| 31157 |
} |
| 31158 |
function getHints() { |
| 31159 |
var hints = linDict.get('H'), hintsLength, item; |
| 31160 |
if (isArray(hints) && |
| 31161 |
((hintsLength = hints.length) === 2 || hintsLength === 4)) { |
| 31162 |
for (var index = 0; index < hintsLength; index++) { |
| 31163 |
if (!(isInt(item = hints[index]) && item > 0)) { |
| 31164 |
throw new Error('Hint (' + index + |
| 31165 |
') in the linearization dictionary is invalid.'); |
| 31166 |
} |
| 31167 |
} |
| 31168 |
return hints; |
| 31169 |
} |
| 31170 |
throw new Error('Hint array in the linearization dictionary is invalid.'); |
| 31171 |
} |
| 31172 |
var parser = new Parser(new Lexer(stream), false, null); |
| 31173 |
var obj1 = parser.getObj(); |
| 31174 |
var obj2 = parser.getObj(); |
| 31175 |
var obj3 = parser.getObj(); |
| 31176 |
var linDict = parser.getObj(); |
| 31177 |
var obj, length; |
| 31178 |
if (!(isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') && isDict(linDict) && |
| 31179 |
isNum(obj = linDict.get('Linearized')) && obj > 0)) { |
| 31180 |
return null; // No valid linearization dictionary found. |
| 31181 |
} else if ((length = getInt('L')) !== stream.length) { |
| 31182 |
throw new Error('The "L" parameter in the linearization dictionary ' + |
| 31183 |
'does not equal the stream length.'); |
| 31184 |
} |
| 31185 |
return { |
| 31186 |
length: length, |
| 31187 |
hints: getHints(), |
| 31188 |
objectNumberFirst: getInt('O'), |
| 31189 |
endFirst: getInt('E'), |
| 31190 |
numPages: getInt('N'), |
| 31191 |
mainXRefEntriesOffset: getInt('T'), |
| 31192 |
pageFirst: (linDict.has('P') ? getInt('P', true) : 0) |
| 31193 |
}; |
| 31194 |
} |
| 31195 |
}; |
| 31196 |
|
| 31197 |
|
| 31198 |
var PostScriptParser = (function PostScriptParserClosure() { |
| 31199 |
function PostScriptParser(lexer) { |
| 31200 |
this.lexer = lexer; |
| 31201 |
this.operators = []; |
| 31202 |
this.token = null; |
| 31203 |
this.prev = null; |
| 31204 |
} |
| 31205 |
PostScriptParser.prototype = { |
| 31206 |
nextToken: function PostScriptParser_nextToken() { |
| 31207 |
this.prev = this.token; |
| 31208 |
this.token = this.lexer.getToken(); |
| 31209 |
}, |
| 31210 |
accept: function PostScriptParser_accept(type) { |
| 31211 |
if (this.token.type === type) { |
| 31212 |
this.nextToken(); |
| 31213 |
return true; |
| 31214 |
} |
| 31215 |
return false; |
| 31216 |
}, |
| 31217 |
expect: function PostScriptParser_expect(type) { |
| 31218 |
if (this.accept(type)) { |
| 31219 |
return true; |
| 31220 |
} |
| 31221 |
error('Unexpected symbol: found ' + this.token.type + ' expected ' + |
| 31222 |
type + '.'); |
| 31223 |
}, |
| 31224 |
parse: function PostScriptParser_parse() { |
| 31225 |
this.nextToken(); |
| 31226 |
this.expect(PostScriptTokenTypes.LBRACE); |
| 31227 |
this.parseBlock(); |
| 31228 |
this.expect(PostScriptTokenTypes.RBRACE); |
| 31229 |
return this.operators; |
| 31230 |
}, |
| 31231 |
parseBlock: function PostScriptParser_parseBlock() { |
| 31232 |
while (true) { |
| 31233 |
if (this.accept(PostScriptTokenTypes.NUMBER)) { |
| 31234 |
this.operators.push(this.prev.value); |
| 31235 |
} else if (this.accept(PostScriptTokenTypes.OPERATOR)) { |
| 31236 |
this.operators.push(this.prev.value); |
| 31237 |
} else if (this.accept(PostScriptTokenTypes.LBRACE)) { |
| 31238 |
this.parseCondition(); |
| 31239 |
} else { |
| 31240 |
return; |
| 31241 |
} |
| 31242 |
} |
| 31243 |
}, |
| 31244 |
parseCondition: function PostScriptParser_parseCondition() { |
| 31245 |
// Add two place holders that will be updated later |
| 31246 |
var conditionLocation = this.operators.length; |
| 31247 |
this.operators.push(null, null); |
| 31248 |
|
| 31249 |
this.parseBlock(); |
| 31250 |
this.expect(PostScriptTokenTypes.RBRACE); |
| 31251 |
if (this.accept(PostScriptTokenTypes.IF)) { |
| 31252 |
// The true block is right after the 'if' so it just falls through on |
| 31253 |
// true else it jumps and skips the true block. |
| 31254 |
this.operators[conditionLocation] = this.operators.length; |
| 31255 |
this.operators[conditionLocation + 1] = 'jz'; |
| 31256 |
} else if (this.accept(PostScriptTokenTypes.LBRACE)) { |
| 31257 |
var jumpLocation = this.operators.length; |
| 31258 |
this.operators.push(null, null); |
| 31259 |
var endOfTrue = this.operators.length; |
| 31260 |
this.parseBlock(); |
| 31261 |
this.expect(PostScriptTokenTypes.RBRACE); |
| 31262 |
this.expect(PostScriptTokenTypes.IFELSE); |
| 31263 |
// The jump is added at the end of the true block to skip the false |
| 31264 |
// block. |
| 31265 |
this.operators[jumpLocation] = this.operators.length; |
| 31266 |
this.operators[jumpLocation + 1] = 'j'; |
| 31267 |
|
| 31268 |
this.operators[conditionLocation] = endOfTrue; |
| 31269 |
this.operators[conditionLocation + 1] = 'jz'; |
| 31270 |
} else { |
| 31271 |
error('PS Function: error parsing conditional.'); |
| 31272 |
} |
| 31273 |
} |
| 31274 |
}; |
| 31275 |
return PostScriptParser; |
| 31276 |
})(); |
| 31277 |
|
| 31278 |
var PostScriptTokenTypes = { |
| 31279 |
LBRACE: 0, |
| 31280 |
RBRACE: 1, |
| 31281 |
NUMBER: 2, |
| 31282 |
OPERATOR: 3, |
| 31283 |
IF: 4, |
| 31284 |
IFELSE: 5 |
| 31285 |
}; |
| 31286 |
|
| 31287 |
var PostScriptToken = (function PostScriptTokenClosure() { |
| 31288 |
function PostScriptToken(type, value) { |
| 31289 |
this.type = type; |
| 31290 |
this.value = value; |
| 31291 |
} |
| 31292 |
|
| 31293 |
var opCache = {}; |
| 31294 |
|
| 31295 |
PostScriptToken.getOperator = function PostScriptToken_getOperator(op) { |
| 31296 |
var opValue = opCache[op]; |
| 31297 |
if (opValue) { |
| 31298 |
return opValue; |
| 31299 |
} |
| 31300 |
return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op); |
| 31301 |
}; |
| 31302 |
|
| 31303 |
PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE, |
| 31304 |
'{'); |
| 31305 |
PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE, |
| 31306 |
'}'); |
| 31307 |
PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF'); |
| 31308 |
PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE, |
| 31309 |
'IFELSE'); |
| 31310 |
return PostScriptToken; |
| 31311 |
})(); |
| 31312 |
|
| 31313 |
var PostScriptLexer = (function PostScriptLexerClosure() { |
| 31314 |
function PostScriptLexer(stream) { |
| 31315 |
this.stream = stream; |
| 31316 |
this.nextChar(); |
| 31317 |
|
| 31318 |
this.strBuf = []; |
| 31319 |
} |
| 31320 |
PostScriptLexer.prototype = { |
| 31321 |
nextChar: function PostScriptLexer_nextChar() { |
| 31322 |
return (this.currentChar = this.stream.getByte()); |
| 31323 |
}, |
| 31324 |
getToken: function PostScriptLexer_getToken() { |
| 31325 |
var comment = false; |
| 31326 |
var ch = this.currentChar; |
| 31327 |
|
| 31328 |
// skip comments |
| 31329 |
while (true) { |
| 31330 |
if (ch < 0) { |
| 31331 |
return EOF; |
| 31332 |
} |
| 31333 |
|
| 31334 |
if (comment) { |
| 31335 |
if (ch === 0x0A || ch === 0x0D) { |
| 31336 |
comment = false; |
| 31337 |
} |
| 31338 |
} else if (ch === 0x25) { // '%' |
| 31339 |
comment = true; |
| 31340 |
} else if (!Lexer.isSpace(ch)) { |
| 31341 |
break; |
| 31342 |
} |
| 31343 |
ch = this.nextChar(); |
| 31344 |
} |
| 31345 |
switch (ch | 0) { |
| 31346 |
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4' |
| 31347 |
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9' |
| 31348 |
case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.' |
| 31349 |
return new PostScriptToken(PostScriptTokenTypes.NUMBER, |
| 31350 |
this.getNumber()); |
| 31351 |
case 0x7B: // '{' |
| 31352 |
this.nextChar(); |
| 31353 |
return PostScriptToken.LBRACE; |
| 31354 |
case 0x7D: // '}' |
| 31355 |
this.nextChar(); |
| 31356 |
return PostScriptToken.RBRACE; |
| 31357 |
} |
| 31358 |
// operator |
| 31359 |
var strBuf = this.strBuf; |
| 31360 |
strBuf.length = 0; |
| 31361 |
strBuf[0] = String.fromCharCode(ch); |
| 31362 |
|
| 31363 |
while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z' |
| 31364 |
((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) { |
| 31365 |
strBuf.push(String.fromCharCode(ch)); |
| 31366 |
} |
| 31367 |
var str = strBuf.join(''); |
| 31368 |
switch (str.toLowerCase()) { |
| 31369 |
case 'if': |
| 31370 |
return PostScriptToken.IF; |
| 31371 |
case 'ifelse': |
| 31372 |
return PostScriptToken.IFELSE; |
| 31373 |
default: |
| 31374 |
return PostScriptToken.getOperator(str); |
| 31375 |
} |
| 31376 |
}, |
| 31377 |
getNumber: function PostScriptLexer_getNumber() { |
| 31378 |
var ch = this.currentChar; |
| 31379 |
var strBuf = this.strBuf; |
| 31380 |
strBuf.length = 0; |
| 31381 |
strBuf[0] = String.fromCharCode(ch); |
| 31382 |
|
| 31383 |
while ((ch = this.nextChar()) >= 0) { |
| 31384 |
if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9' |
| 31385 |
ch === 0x2D || ch === 0x2E) { // '-', '.' |
| 31386 |
strBuf.push(String.fromCharCode(ch)); |
| 31387 |
} else { |
| 31388 |
break; |
| 31389 |
} |
| 31390 |
} |
| 31391 |
var value = parseFloat(strBuf.join('')); |
| 31392 |
if (isNaN(value)) { |
| 31393 |
error('Invalid floating point number: ' + value); |
| 31394 |
} |
| 31395 |
return value; |
| 31396 |
} |
| 31397 |
}; |
| 31398 |
return PostScriptLexer; |
| 31399 |
})(); |
| 31400 |
|
| 31401 |
|
| 31402 |
var Stream = (function StreamClosure() { |
| 31403 |
function Stream(arrayBuffer, start, length, dict) { |
| 31404 |
this.bytes = (arrayBuffer instanceof Uint8Array ? |
| 31405 |
arrayBuffer : new Uint8Array(arrayBuffer)); |
| 31406 |
this.start = start || 0; |
| 31407 |
this.pos = this.start; |
| 31408 |
this.end = (start + length) || this.bytes.length; |
| 31409 |
this.dict = dict; |
| 31410 |
} |
| 31411 |
|
| 31412 |
// required methods for a stream. if a particular stream does not |
| 31413 |
// implement these, an error should be thrown |
| 31414 |
Stream.prototype = { |
| 31415 |
get length() { |
| 31416 |
return this.end - this.start; |
| 31417 |
}, |
| 31418 |
get isEmpty() { |
| 31419 |
return this.length === 0; |
| 31420 |
}, |
| 31421 |
getByte: function Stream_getByte() { |
| 31422 |
if (this.pos >= this.end) { |
| 31423 |
return -1; |
| 31424 |
} |
| 31425 |
return this.bytes[this.pos++]; |
| 31426 |
}, |
| 31427 |
getUint16: function Stream_getUint16() { |
| 31428 |
var b0 = this.getByte(); |
| 31429 |
var b1 = this.getByte(); |
| 31430 |
if (b0 === -1 || b1 === -1) { |
| 31431 |
return -1; |
| 31432 |
} |
| 31433 |
return (b0 << 8) + b1; |
| 31434 |
}, |
| 31435 |
getInt32: function Stream_getInt32() { |
| 31436 |
var b0 = this.getByte(); |
| 31437 |
var b1 = this.getByte(); |
| 31438 |
var b2 = this.getByte(); |
| 31439 |
var b3 = this.getByte(); |
| 31440 |
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; |
| 31441 |
}, |
| 31442 |
// returns subarray of original buffer |
| 31443 |
// should only be read |
| 31444 |
getBytes: function Stream_getBytes(length) { |
| 31445 |
var bytes = this.bytes; |
| 31446 |
var pos = this.pos; |
| 31447 |
var strEnd = this.end; |
| 31448 |
|
| 31449 |
if (!length) { |
| 31450 |
return bytes.subarray(pos, strEnd); |
| 31451 |
} |
| 31452 |
var end = pos + length; |
| 31453 |
if (end > strEnd) { |
| 31454 |
end = strEnd; |
| 31455 |
} |
| 31456 |
this.pos = end; |
| 31457 |
return bytes.subarray(pos, end); |
| 31458 |
}, |
| 31459 |
peekByte: function Stream_peekByte() { |
| 31460 |
var peekedByte = this.getByte(); |
| 31461 |
this.pos--; |
| 31462 |
return peekedByte; |
| 31463 |
}, |
| 31464 |
peekBytes: function Stream_peekBytes(length) { |
| 31465 |
var bytes = this.getBytes(length); |
| 31466 |
this.pos -= bytes.length; |
| 31467 |
return bytes; |
| 31468 |
}, |
| 31469 |
skip: function Stream_skip(n) { |
| 31470 |
if (!n) { |
| 31471 |
n = 1; |
| 31472 |
} |
| 31473 |
this.pos += n; |
| 31474 |
}, |
| 31475 |
reset: function Stream_reset() { |
| 31476 |
this.pos = this.start; |
| 31477 |
}, |
| 31478 |
moveStart: function Stream_moveStart() { |
| 31479 |
this.start = this.pos; |
| 31480 |
}, |
| 31481 |
makeSubStream: function Stream_makeSubStream(start, length, dict) { |
| 31482 |
return new Stream(this.bytes.buffer, start, length, dict); |
| 31483 |
}, |
| 31484 |
isStream: true |
| 31485 |
}; |
| 31486 |
|
| 31487 |
return Stream; |
| 31488 |
})(); |
| 31489 |
|
| 31490 |
var StringStream = (function StringStreamClosure() { |
| 31491 |
function StringStream(str) { |
| 31492 |
var length = str.length; |
| 31493 |
var bytes = new Uint8Array(length); |
| 31494 |
for (var n = 0; n < length; ++n) { |
| 31495 |
bytes[n] = str.charCodeAt(n); |
| 31496 |
} |
| 31497 |
Stream.call(this, bytes); |
| 31498 |
} |
| 31499 |
|
| 31500 |
StringStream.prototype = Stream.prototype; |
| 31501 |
|
| 31502 |
return StringStream; |
| 31503 |
})(); |
| 31504 |
|
| 31505 |
// super class for the decoding streams |
| 31506 |
var DecodeStream = (function DecodeStreamClosure() { |
| 31507 |
// Lots of DecodeStreams are created whose buffers are never used. For these |
| 31508 |
// we share a single empty buffer. This is (a) space-efficient and (b) avoids |
| 31509 |
// having special cases that would be required if we used |null| for an empty |
| 31510 |
// buffer. |
| 31511 |
var emptyBuffer = new Uint8Array(0); |
| 31512 |
|
| 31513 |
function DecodeStream(maybeMinBufferLength) { |
| 31514 |
this.pos = 0; |
| 31515 |
this.bufferLength = 0; |
| 31516 |
this.eof = false; |
| 31517 |
this.buffer = emptyBuffer; |
| 31518 |
this.minBufferLength = 512; |
| 31519 |
if (maybeMinBufferLength) { |
| 31520 |
// Compute the first power of two that is as big as maybeMinBufferLength. |
| 31521 |
while (this.minBufferLength < maybeMinBufferLength) { |
| 31522 |
this.minBufferLength *= 2; |
| 31523 |
} |
| 31524 |
} |
| 31525 |
} |
| 31526 |
|
| 31527 |
DecodeStream.prototype = { |
| 31528 |
get isEmpty() { |
| 31529 |
while (!this.eof && this.bufferLength === 0) { |
| 31530 |
this.readBlock(); |
| 31531 |
} |
| 31532 |
return this.bufferLength === 0; |
| 31533 |
}, |
| 31534 |
ensureBuffer: function DecodeStream_ensureBuffer(requested) { |
| 31535 |
var buffer = this.buffer; |
| 31536 |
if (requested <= buffer.byteLength) { |
| 31537 |
return buffer; |
| 31538 |
} |
| 31539 |
var size = this.minBufferLength; |
| 31540 |
while (size < requested) { |
| 31541 |
size *= 2; |
| 31542 |
} |
| 31543 |
var buffer2 = new Uint8Array(size); |
| 31544 |
buffer2.set(buffer); |
| 31545 |
return (this.buffer = buffer2); |
| 31546 |
}, |
| 31547 |
getByte: function DecodeStream_getByte() { |
| 31548 |
var pos = this.pos; |
| 31549 |
while (this.bufferLength <= pos) { |
| 31550 |
if (this.eof) { |
| 31551 |
return -1; |
| 31552 |
} |
| 31553 |
this.readBlock(); |
| 31554 |
} |
| 31555 |
return this.buffer[this.pos++]; |
| 31556 |
}, |
| 31557 |
getUint16: function DecodeStream_getUint16() { |
| 31558 |
var b0 = this.getByte(); |
| 31559 |
var b1 = this.getByte(); |
| 31560 |
if (b0 === -1 || b1 === -1) { |
| 31561 |
return -1; |
| 31562 |
} |
| 31563 |
return (b0 << 8) + b1; |
| 31564 |
}, |
| 31565 |
getInt32: function DecodeStream_getInt32() { |
| 31566 |
var b0 = this.getByte(); |
| 31567 |
var b1 = this.getByte(); |
| 31568 |
var b2 = this.getByte(); |
| 31569 |
var b3 = this.getByte(); |
| 31570 |
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; |
| 31571 |
}, |
| 31572 |
getBytes: function DecodeStream_getBytes(length) { |
| 31573 |
var end, pos = this.pos; |
| 31574 |
|
| 31575 |
if (length) { |
| 31576 |
this.ensureBuffer(pos + length); |
| 31577 |
end = pos + length; |
| 31578 |
|
| 31579 |
while (!this.eof && this.bufferLength < end) { |
| 31580 |
this.readBlock(); |
| 31581 |
} |
| 31582 |
var bufEnd = this.bufferLength; |
| 31583 |
if (end > bufEnd) { |
| 31584 |
end = bufEnd; |
| 31585 |
} |
| 31586 |
} else { |
| 31587 |
while (!this.eof) { |
| 31588 |
this.readBlock(); |
| 31589 |
} |
| 31590 |
end = this.bufferLength; |
| 31591 |
} |
| 31592 |
|
| 31593 |
this.pos = end; |
| 31594 |
return this.buffer.subarray(pos, end); |
| 31595 |
}, |
| 31596 |
peekByte: function DecodeStream_peekByte() { |
| 31597 |
var peekedByte = this.getByte(); |
| 31598 |
this.pos--; |
| 31599 |
return peekedByte; |
| 31600 |
}, |
| 31601 |
peekBytes: function DecodeStream_peekBytes(length) { |
| 31602 |
var bytes = this.getBytes(length); |
| 31603 |
this.pos -= bytes.length; |
| 31604 |
return bytes; |
| 31605 |
}, |
| 31606 |
makeSubStream: function DecodeStream_makeSubStream(start, length, dict) { |
| 31607 |
var end = start + length; |
| 31608 |
while (this.bufferLength <= end && !this.eof) { |
| 31609 |
this.readBlock(); |
| 31610 |
} |
| 31611 |
return new Stream(this.buffer, start, length, dict); |
| 31612 |
}, |
| 31613 |
skip: function DecodeStream_skip(n) { |
| 31614 |
if (!n) { |
| 31615 |
n = 1; |
| 31616 |
} |
| 31617 |
this.pos += n; |
| 31618 |
}, |
| 31619 |
reset: function DecodeStream_reset() { |
| 31620 |
this.pos = 0; |
| 31621 |
}, |
| 31622 |
getBaseStreams: function DecodeStream_getBaseStreams() { |
| 31623 |
if (this.str && this.str.getBaseStreams) { |
| 31624 |
return this.str.getBaseStreams(); |
| 31625 |
} |
| 31626 |
return []; |
| 31627 |
} |
| 31628 |
}; |
| 31629 |
|
| 31630 |
return DecodeStream; |
| 31631 |
})(); |
| 31632 |
|
| 31633 |
var StreamsSequenceStream = (function StreamsSequenceStreamClosure() { |
| 31634 |
function StreamsSequenceStream(streams) { |
| 31635 |
this.streams = streams; |
| 31636 |
DecodeStream.call(this, /* maybeLength = */ null); |
| 31637 |
} |
| 31638 |
|
| 31639 |
StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype); |
| 31640 |
|
| 31641 |
StreamsSequenceStream.prototype.readBlock = |
| 31642 |
function streamSequenceStreamReadBlock() { |
| 31643 |
|
| 31644 |
var streams = this.streams; |
| 31645 |
if (streams.length === 0) { |
| 31646 |
this.eof = true; |
| 31647 |
return; |
| 31648 |
} |
| 31649 |
var stream = streams.shift(); |
| 31650 |
var chunk = stream.getBytes(); |
| 31651 |
var bufferLength = this.bufferLength; |
| 31652 |
var newLength = bufferLength + chunk.length; |
| 31653 |
var buffer = this.ensureBuffer(newLength); |
| 31654 |
buffer.set(chunk, bufferLength); |
| 31655 |
this.bufferLength = newLength; |
| 31656 |
}; |
| 31657 |
|
| 31658 |
StreamsSequenceStream.prototype.getBaseStreams = |
| 31659 |
function StreamsSequenceStream_getBaseStreams() { |
| 31660 |
|
| 31661 |
var baseStreams = []; |
| 31662 |
for (var i = 0, ii = this.streams.length; i < ii; i++) { |
| 31663 |
var stream = this.streams[i]; |
| 31664 |
if (stream.getBaseStreams) { |
| 31665 |
Util.appendToArray(baseStreams, stream.getBaseStreams()); |
| 31666 |
} |
| 31667 |
} |
| 31668 |
return baseStreams; |
| 31669 |
}; |
| 31670 |
|
| 31671 |
return StreamsSequenceStream; |
| 31672 |
})(); |
| 31673 |
|
| 31674 |
var FlateStream = (function FlateStreamClosure() { |
| 31675 |
var codeLenCodeMap = new Int32Array([ |
| 31676 |
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 |
| 31677 |
]); |
| 31678 |
|
| 31679 |
var lengthDecode = new Int32Array([ |
| 31680 |
0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, |
| 31681 |
0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, |
| 31682 |
0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, |
| 31683 |
0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102 |
| 31684 |
]); |
| 31685 |
|
| 31686 |
var distDecode = new Int32Array([ |
| 31687 |
0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, |
| 31688 |
0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, |
| 31689 |
0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, |
| 31690 |
0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001 |
| 31691 |
]); |
| 31692 |
|
| 31693 |
var fixedLitCodeTab = [new Int32Array([ |
| 31694 |
0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, |
| 31695 |
0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, |
| 31696 |
0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, |
| 31697 |
0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, |
| 31698 |
0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, |
| 31699 |
0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, |
| 31700 |
0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, |
| 31701 |
0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, |
| 31702 |
0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, |
| 31703 |
0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, |
| 31704 |
0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, |
| 31705 |
0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, |
| 31706 |
0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, |
| 31707 |
0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, |
| 31708 |
0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, |
| 31709 |
0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, |
| 31710 |
0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, |
| 31711 |
0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, |
| 31712 |
0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, |
| 31713 |
0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, |
| 31714 |
0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, |
| 31715 |
0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, |
| 31716 |
0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, |
| 31717 |
0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, |
| 31718 |
0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, |
| 31719 |
0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, |
| 31720 |
0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, |
| 31721 |
0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, |
| 31722 |
0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, |
| 31723 |
0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, |
| 31724 |
0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, |
| 31725 |
0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, |
| 31726 |
0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, |
| 31727 |
0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, |
| 31728 |
0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, |
| 31729 |
0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, |
| 31730 |
0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, |
| 31731 |
0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, |
| 31732 |
0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, |
| 31733 |
0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, |
| 31734 |
0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, |
| 31735 |
0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, |
| 31736 |
0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, |
| 31737 |
0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, |
| 31738 |
0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, |
| 31739 |
0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, |
| 31740 |
0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, |
| 31741 |
0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, |
| 31742 |
0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, |
| 31743 |
0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, |
| 31744 |
0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, |
| 31745 |
0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, |
| 31746 |
0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, |
| 31747 |
0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, |
| 31748 |
0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, |
| 31749 |
0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, |
| 31750 |
0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, |
| 31751 |
0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, |
| 31752 |
0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, |
| 31753 |
0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, |
| 31754 |
0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, |
| 31755 |
0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, |
| 31756 |
0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, |
| 31757 |
0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff |
| 31758 |
]), 9]; |
| 31759 |
|
| 31760 |
var fixedDistCodeTab = [new Int32Array([ |
| 31761 |
0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, |
| 31762 |
0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, |
| 31763 |
0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, |
| 31764 |
0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 |
| 31765 |
]), 5]; |
| 31766 |
|
| 31767 |
function FlateStream(str, maybeLength) { |
| 31768 |
this.str = str; |
| 31769 |
this.dict = str.dict; |
| 31770 |
|
| 31771 |
var cmf = str.getByte(); |
| 31772 |
var flg = str.getByte(); |
| 31773 |
if (cmf === -1 || flg === -1) { |
| 31774 |
error('Invalid header in flate stream: ' + cmf + ', ' + flg); |
| 31775 |
} |
| 31776 |
if ((cmf & 0x0f) !== 0x08) { |
| 31777 |
error('Unknown compression method in flate stream: ' + cmf + ', ' + flg); |
| 31778 |
} |
| 31779 |
if ((((cmf << 8) + flg) % 31) !== 0) { |
| 31780 |
error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg); |
| 31781 |
} |
| 31782 |
if (flg & 0x20) { |
| 31783 |
error('FDICT bit set in flate stream: ' + cmf + ', ' + flg); |
| 31784 |
} |
| 31785 |
|
| 31786 |
this.codeSize = 0; |
| 31787 |
this.codeBuf = 0; |
| 31788 |
|
| 31789 |
DecodeStream.call(this, maybeLength); |
| 31790 |
} |
| 31791 |
|
| 31792 |
FlateStream.prototype = Object.create(DecodeStream.prototype); |
| 31793 |
|
| 31794 |
FlateStream.prototype.getBits = function FlateStream_getBits(bits) { |
| 31795 |
var str = this.str; |
| 31796 |
var codeSize = this.codeSize; |
| 31797 |
var codeBuf = this.codeBuf; |
| 31798 |
|
| 31799 |
var b; |
| 31800 |
while (codeSize < bits) { |
| 31801 |
if ((b = str.getByte()) === -1) { |
| 31802 |
error('Bad encoding in flate stream'); |
| 31803 |
} |
| 31804 |
codeBuf |= b << codeSize; |
| 31805 |
codeSize += 8; |
| 31806 |
} |
| 31807 |
b = codeBuf & ((1 << bits) - 1); |
| 31808 |
this.codeBuf = codeBuf >> bits; |
| 31809 |
this.codeSize = codeSize -= bits; |
| 31810 |
|
| 31811 |
return b; |
| 31812 |
}; |
| 31813 |
|
| 31814 |
FlateStream.prototype.getCode = function FlateStream_getCode(table) { |
| 31815 |
var str = this.str; |
| 31816 |
var codes = table[0]; |
| 31817 |
var maxLen = table[1]; |
| 31818 |
var codeSize = this.codeSize; |
| 31819 |
var codeBuf = this.codeBuf; |
| 31820 |
|
| 31821 |
var b; |
| 31822 |
while (codeSize < maxLen) { |
| 31823 |
if ((b = str.getByte()) === -1) { |
| 31824 |
// premature end of stream. code might however still be valid. |
| 31825 |
// codeSize < codeLen check below guards against incomplete codeVal. |
| 31826 |
break; |
| 31827 |
} |
| 31828 |
codeBuf |= (b << codeSize); |
| 31829 |
codeSize += 8; |
| 31830 |
} |
| 31831 |
var code = codes[codeBuf & ((1 << maxLen) - 1)]; |
| 31832 |
var codeLen = code >> 16; |
| 31833 |
var codeVal = code & 0xffff; |
| 31834 |
if (codeLen < 1 || codeSize < codeLen) { |
| 31835 |
error('Bad encoding in flate stream'); |
| 31836 |
} |
| 31837 |
this.codeBuf = (codeBuf >> codeLen); |
| 31838 |
this.codeSize = (codeSize - codeLen); |
| 31839 |
return codeVal; |
| 31840 |
}; |
| 31841 |
|
| 31842 |
FlateStream.prototype.generateHuffmanTable = |
| 31843 |
function flateStreamGenerateHuffmanTable(lengths) { |
| 31844 |
var n = lengths.length; |
| 31845 |
|
| 31846 |
// find max code length |
| 31847 |
var maxLen = 0; |
| 31848 |
var i; |
| 31849 |
for (i = 0; i < n; ++i) { |
| 31850 |
if (lengths[i] > maxLen) { |
| 31851 |
maxLen = lengths[i]; |
| 31852 |
} |
| 31853 |
} |
| 31854 |
|
| 31855 |
// build the table |
| 31856 |
var size = 1 << maxLen; |
| 31857 |
var codes = new Int32Array(size); |
| 31858 |
for (var len = 1, code = 0, skip = 2; |
| 31859 |
len <= maxLen; |
| 31860 |
++len, code <<= 1, skip <<= 1) { |
| 31861 |
for (var val = 0; val < n; ++val) { |
| 31862 |
if (lengths[val] === len) { |
| 31863 |
// bit-reverse the code |
| 31864 |
var code2 = 0; |
| 31865 |
var t = code; |
| 31866 |
for (i = 0; i < len; ++i) { |
| 31867 |
code2 = (code2 << 1) | (t & 1); |
| 31868 |
t >>= 1; |
| 31869 |
} |
| 31870 |
|
| 31871 |
// fill the table entries |
| 31872 |
for (i = code2; i < size; i += skip) { |
| 31873 |
codes[i] = (len << 16) | val; |
| 31874 |
} |
| 31875 |
++code; |
| 31876 |
} |
| 31877 |
} |
| 31878 |
} |
| 31879 |
|
| 31880 |
return [codes, maxLen]; |
| 31881 |
}; |
| 31882 |
|
| 31883 |
FlateStream.prototype.readBlock = function FlateStream_readBlock() { |
| 31884 |
var buffer, len; |
| 31885 |
var str = this.str; |
| 31886 |
// read block header |
| 31887 |
var hdr = this.getBits(3); |
| 31888 |
if (hdr & 1) { |
| 31889 |
this.eof = true; |
| 31890 |
} |
| 31891 |
hdr >>= 1; |
| 31892 |
|
| 31893 |
if (hdr === 0) { // uncompressed block |
| 31894 |
var b; |
| 31895 |
|
| 31896 |
if ((b = str.getByte()) === -1) { |
| 31897 |
error('Bad block header in flate stream'); |
| 31898 |
} |
| 31899 |
var blockLen = b; |
| 31900 |
if ((b = str.getByte()) === -1) { |
| 31901 |
error('Bad block header in flate stream'); |
| 31902 |
} |
| 31903 |
blockLen |= (b << 8); |
| 31904 |
if ((b = str.getByte()) === -1) { |
| 31905 |
error('Bad block header in flate stream'); |
| 31906 |
} |
| 31907 |
var check = b; |
| 31908 |
if ((b = str.getByte()) === -1) { |
| 31909 |
error('Bad block header in flate stream'); |
| 31910 |
} |
| 31911 |
check |= (b << 8); |
| 31912 |
if (check !== (~blockLen & 0xffff) && |
| 31913 |
(blockLen !== 0 || check !== 0)) { |
| 31914 |
// Ignoring error for bad "empty" block (see issue 1277) |
| 31915 |
error('Bad uncompressed block length in flate stream'); |
| 31916 |
} |
| 31917 |
|
| 31918 |
this.codeBuf = 0; |
| 31919 |
this.codeSize = 0; |
| 31920 |
|
| 31921 |
var bufferLength = this.bufferLength; |
| 31922 |
buffer = this.ensureBuffer(bufferLength + blockLen); |
| 31923 |
var end = bufferLength + blockLen; |
| 31924 |
this.bufferLength = end; |
| 31925 |
if (blockLen === 0) { |
| 31926 |
if (str.peekByte() === -1) { |
| 31927 |
this.eof = true; |
| 31928 |
} |
| 31929 |
} else { |
| 31930 |
for (var n = bufferLength; n < end; ++n) { |
| 31931 |
if ((b = str.getByte()) === -1) { |
| 31932 |
this.eof = true; |
| 31933 |
break; |
| 31934 |
} |
| 31935 |
buffer[n] = b; |
| 31936 |
} |
| 31937 |
} |
| 31938 |
return; |
| 31939 |
} |
| 31940 |
|
| 31941 |
var litCodeTable; |
| 31942 |
var distCodeTable; |
| 31943 |
if (hdr === 1) { // compressed block, fixed codes |
| 31944 |
litCodeTable = fixedLitCodeTab; |
| 31945 |
distCodeTable = fixedDistCodeTab; |
| 31946 |
} else if (hdr === 2) { // compressed block, dynamic codes |
| 31947 |
var numLitCodes = this.getBits(5) + 257; |
| 31948 |
var numDistCodes = this.getBits(5) + 1; |
| 31949 |
var numCodeLenCodes = this.getBits(4) + 4; |
| 31950 |
|
| 31951 |
// build the code lengths code table |
| 31952 |
var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); |
| 31953 |
|
| 31954 |
var i; |
| 31955 |
for (i = 0; i < numCodeLenCodes; ++i) { |
| 31956 |
codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3); |
| 31957 |
} |
| 31958 |
var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); |
| 31959 |
|
| 31960 |
// build the literal and distance code tables |
| 31961 |
len = 0; |
| 31962 |
i = 0; |
| 31963 |
var codes = numLitCodes + numDistCodes; |
| 31964 |
var codeLengths = new Uint8Array(codes); |
| 31965 |
var bitsLength, bitsOffset, what; |
| 31966 |
while (i < codes) { |
| 31967 |
var code = this.getCode(codeLenCodeTab); |
| 31968 |
if (code === 16) { |
| 31969 |
bitsLength = 2; bitsOffset = 3; what = len; |
| 31970 |
} else if (code === 17) { |
| 31971 |
bitsLength = 3; bitsOffset = 3; what = (len = 0); |
| 31972 |
} else if (code === 18) { |
| 31973 |
bitsLength = 7; bitsOffset = 11; what = (len = 0); |
| 31974 |
} else { |
| 31975 |
codeLengths[i++] = len = code; |
| 31976 |
continue; |
| 31977 |
} |
| 31978 |
|
| 31979 |
var repeatLength = this.getBits(bitsLength) + bitsOffset; |
| 31980 |
while (repeatLength-- > 0) { |
| 31981 |
codeLengths[i++] = what; |
| 31982 |
} |
| 31983 |
} |
| 31984 |
|
| 31985 |
litCodeTable = |
| 31986 |
this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); |
| 31987 |
distCodeTable = |
| 31988 |
this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); |
| 31989 |
} else { |
| 31990 |
error('Unknown block type in flate stream'); |
| 31991 |
} |
| 31992 |
|
| 31993 |
buffer = this.buffer; |
| 31994 |
var limit = buffer ? buffer.length : 0; |
| 31995 |
var pos = this.bufferLength; |
| 31996 |
while (true) { |
| 31997 |
var code1 = this.getCode(litCodeTable); |
| 31998 |
if (code1 < 256) { |
| 31999 |
if (pos + 1 >= limit) { |
| 32000 |
buffer = this.ensureBuffer(pos + 1); |
| 32001 |
limit = buffer.length; |
| 32002 |
} |
| 32003 |
buffer[pos++] = code1; |
| 32004 |
continue; |
| 32005 |
} |
| 32006 |
if (code1 === 256) { |
| 32007 |
this.bufferLength = pos; |
| 32008 |
return; |
| 32009 |
} |
| 32010 |
code1 -= 257; |
| 32011 |
code1 = lengthDecode[code1]; |
| 32012 |
var code2 = code1 >> 16; |
| 32013 |
if (code2 > 0) { |
| 32014 |
code2 = this.getBits(code2); |
| 32015 |
} |
| 32016 |
len = (code1 & 0xffff) + code2; |
| 32017 |
code1 = this.getCode(distCodeTable); |
| 32018 |
code1 = distDecode[code1]; |
| 32019 |
code2 = code1 >> 16; |
| 32020 |
if (code2 > 0) { |
| 32021 |
code2 = this.getBits(code2); |
| 32022 |
} |
| 32023 |
var dist = (code1 & 0xffff) + code2; |
| 32024 |
if (pos + len >= limit) { |
| 32025 |
buffer = this.ensureBuffer(pos + len); |
| 32026 |
limit = buffer.length; |
| 32027 |
} |
| 32028 |
for (var k = 0; k < len; ++k, ++pos) { |
| 32029 |
buffer[pos] = buffer[pos - dist]; |
| 32030 |
} |
| 32031 |
} |
| 32032 |
}; |
| 32033 |
|
| 32034 |
return FlateStream; |
| 32035 |
})(); |
| 32036 |
|
| 32037 |
var PredictorStream = (function PredictorStreamClosure() { |
| 32038 |
function PredictorStream(str, maybeLength, params) { |
| 32039 |
var predictor = this.predictor = params.get('Predictor') || 1; |
| 32040 |
|
| 32041 |
if (predictor <= 1) { |
| 32042 |
return str; // no prediction |
| 32043 |
} |
| 32044 |
if (predictor !== 2 && (predictor < 10 || predictor > 15)) { |
| 32045 |
error('Unsupported predictor: ' + predictor); |
| 32046 |
} |
| 32047 |
|
| 32048 |
if (predictor === 2) { |
| 32049 |
this.readBlock = this.readBlockTiff; |
| 32050 |
} else { |
| 32051 |
this.readBlock = this.readBlockPng; |
| 32052 |
} |
| 32053 |
|
| 32054 |
this.str = str; |
| 32055 |
this.dict = str.dict; |
| 32056 |
|
| 32057 |
var colors = this.colors = params.get('Colors') || 1; |
| 32058 |
var bits = this.bits = params.get('BitsPerComponent') || 8; |
| 32059 |
var columns = this.columns = params.get('Columns') || 1; |
| 32060 |
|
| 32061 |
this.pixBytes = (colors * bits + 7) >> 3; |
| 32062 |
this.rowBytes = (columns * colors * bits + 7) >> 3; |
| 32063 |
|
| 32064 |
DecodeStream.call(this, maybeLength); |
| 32065 |
return this; |
| 32066 |
} |
| 32067 |
|
| 32068 |
PredictorStream.prototype = Object.create(DecodeStream.prototype); |
| 32069 |
|
| 32070 |
PredictorStream.prototype.readBlockTiff = |
| 32071 |
function predictorStreamReadBlockTiff() { |
| 32072 |
var rowBytes = this.rowBytes; |
| 32073 |
|
| 32074 |
var bufferLength = this.bufferLength; |
| 32075 |
var buffer = this.ensureBuffer(bufferLength + rowBytes); |
| 32076 |
|
| 32077 |
var bits = this.bits; |
| 32078 |
var colors = this.colors; |
| 32079 |
|
| 32080 |
var rawBytes = this.str.getBytes(rowBytes); |
| 32081 |
this.eof = !rawBytes.length; |
| 32082 |
if (this.eof) { |
| 32083 |
return; |
| 32084 |
} |
| 32085 |
|
| 32086 |
var inbuf = 0, outbuf = 0; |
| 32087 |
var inbits = 0, outbits = 0; |
| 32088 |
var pos = bufferLength; |
| 32089 |
var i; |
| 32090 |
|
| 32091 |
if (bits === 1) { |
| 32092 |
for (i = 0; i < rowBytes; ++i) { |
| 32093 |
var c = rawBytes[i]; |
| 32094 |
inbuf = (inbuf << 8) | c; |
| 32095 |
// bitwise addition is exclusive or |
| 32096 |
// first shift inbuf and then add |
| 32097 |
buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF; |
| 32098 |
// truncate inbuf (assumes colors < 16) |
| 32099 |
inbuf &= 0xFFFF; |
| 32100 |
} |
| 32101 |
} else if (bits === 8) { |
| 32102 |
for (i = 0; i < colors; ++i) { |
| 32103 |
buffer[pos++] = rawBytes[i]; |
| 32104 |
} |
| 32105 |
for (; i < rowBytes; ++i) { |
| 32106 |
buffer[pos] = buffer[pos - colors] + rawBytes[i]; |
| 32107 |
pos++; |
| 32108 |
} |
| 32109 |
} else { |
| 32110 |
var compArray = new Uint8Array(colors + 1); |
| 32111 |
var bitMask = (1 << bits) - 1; |
| 32112 |
var j = 0, k = bufferLength; |
| 32113 |
var columns = this.columns; |
| 32114 |
for (i = 0; i < columns; ++i) { |
| 32115 |
for (var kk = 0; kk < colors; ++kk) { |
| 32116 |
if (inbits < bits) { |
| 32117 |
inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF); |
| 32118 |
inbits += 8; |
| 32119 |
} |
| 32120 |
compArray[kk] = (compArray[kk] + |
| 32121 |
(inbuf >> (inbits - bits))) & bitMask; |
| 32122 |
inbits -= bits; |
| 32123 |
outbuf = (outbuf << bits) | compArray[kk]; |
| 32124 |
outbits += bits; |
| 32125 |
if (outbits >= 8) { |
| 32126 |
buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF; |
| 32127 |
outbits -= 8; |
| 32128 |
} |
| 32129 |
} |
| 32130 |
} |
| 32131 |
if (outbits > 0) { |
| 32132 |
buffer[k++] = (outbuf << (8 - outbits)) + |
| 32133 |
(inbuf & ((1 << (8 - outbits)) - 1)); |
| 32134 |
} |
| 32135 |
} |
| 32136 |
this.bufferLength += rowBytes; |
| 32137 |
}; |
| 32138 |
|
| 32139 |
PredictorStream.prototype.readBlockPng = |
| 32140 |
function predictorStreamReadBlockPng() { |
| 32141 |
|
| 32142 |
var rowBytes = this.rowBytes; |
| 32143 |
var pixBytes = this.pixBytes; |
| 32144 |
|
| 32145 |
var predictor = this.str.getByte(); |
| 32146 |
var rawBytes = this.str.getBytes(rowBytes); |
| 32147 |
this.eof = !rawBytes.length; |
| 32148 |
if (this.eof) { |
| 32149 |
return; |
| 32150 |
} |
| 32151 |
|
| 32152 |
var bufferLength = this.bufferLength; |
| 32153 |
var buffer = this.ensureBuffer(bufferLength + rowBytes); |
| 32154 |
|
| 32155 |
var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); |
| 32156 |
if (prevRow.length === 0) { |
| 32157 |
prevRow = new Uint8Array(rowBytes); |
| 32158 |
} |
| 32159 |
|
| 32160 |
var i, j = bufferLength, up, c; |
| 32161 |
switch (predictor) { |
| 32162 |
case 0: |
| 32163 |
for (i = 0; i < rowBytes; ++i) { |
| 32164 |
buffer[j++] = rawBytes[i]; |
| 32165 |
} |
| 32166 |
break; |
| 32167 |
case 1: |
| 32168 |
for (i = 0; i < pixBytes; ++i) { |
| 32169 |
buffer[j++] = rawBytes[i]; |
| 32170 |
} |
| 32171 |
for (; i < rowBytes; ++i) { |
| 32172 |
buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF; |
| 32173 |
j++; |
| 32174 |
} |
| 32175 |
break; |
| 32176 |
case 2: |
| 32177 |
for (i = 0; i < rowBytes; ++i) { |
| 32178 |
buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF; |
| 32179 |
} |
| 32180 |
break; |
| 32181 |
case 3: |
| 32182 |
for (i = 0; i < pixBytes; ++i) { |
| 32183 |
buffer[j++] = (prevRow[i] >> 1) + rawBytes[i]; |
| 32184 |
} |
| 32185 |
for (; i < rowBytes; ++i) { |
| 32186 |
buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) + |
| 32187 |
rawBytes[i]) & 0xFF; |
| 32188 |
j++; |
| 32189 |
} |
| 32190 |
break; |
| 32191 |
case 4: |
| 32192 |
// we need to save the up left pixels values. the simplest way |
| 32193 |
// is to create a new buffer |
| 32194 |
for (i = 0; i < pixBytes; ++i) { |
| 32195 |
up = prevRow[i]; |
| 32196 |
c = rawBytes[i]; |
| 32197 |
buffer[j++] = up + c; |
| 32198 |
} |
| 32199 |
for (; i < rowBytes; ++i) { |
| 32200 |
up = prevRow[i]; |
| 32201 |
var upLeft = prevRow[i - pixBytes]; |
| 32202 |
var left = buffer[j - pixBytes]; |
| 32203 |
var p = left + up - upLeft; |
| 32204 |
|
| 32205 |
var pa = p - left; |
| 32206 |
if (pa < 0) { |
| 32207 |
pa = -pa; |
| 32208 |
} |
| 32209 |
var pb = p - up; |
| 32210 |
if (pb < 0) { |
| 32211 |
pb = -pb; |
| 32212 |
} |
| 32213 |
var pc = p - upLeft; |
| 32214 |
if (pc < 0) { |
| 32215 |
pc = -pc; |
| 32216 |
} |
| 32217 |
|
| 32218 |
c = rawBytes[i]; |
| 32219 |
if (pa <= pb && pa <= pc) { |
| 32220 |
buffer[j++] = left + c; |
| 32221 |
} else if (pb <= pc) { |
| 32222 |
buffer[j++] = up + c; |
| 32223 |
} else { |
| 32224 |
buffer[j++] = upLeft + c; |
| 32225 |
} |
| 32226 |
} |
| 32227 |
break; |
| 32228 |
default: |
| 32229 |
error('Unsupported predictor: ' + predictor); |
| 32230 |
} |
| 32231 |
this.bufferLength += rowBytes; |
| 32232 |
}; |
| 32233 |
|
| 32234 |
return PredictorStream; |
| 32235 |
})(); |
| 32236 |
|
| 32237 |
/** |
| 32238 |
* Depending on the type of JPEG a JpegStream is handled in different ways. For |
| 32239 |
* JPEG's that are supported natively such as DeviceGray and DeviceRGB the image |
| 32240 |
* data is stored and then loaded by the browser. For unsupported JPEG's we use |
| 32241 |
* a library to decode these images and the stream behaves like all the other |
| 32242 |
* DecodeStreams. |
| 32243 |
*/ |
| 32244 |
var JpegStream = (function JpegStreamClosure() { |
| 32245 |
function JpegStream(stream, maybeLength, dict, xref) { |
| 32246 |
// Some images may contain 'junk' before the SOI (start-of-image) marker. |
| 32247 |
// Note: this seems to mainly affect inline images. |
| 32248 |
var ch; |
| 32249 |
while ((ch = stream.getByte()) !== -1) { |
| 32250 |
if (ch === 0xFF) { // Find the first byte of the SOI marker (0xFFD8). |
| 32251 |
stream.skip(-1); // Reset the stream position to the SOI. |
| 32252 |
break; |
| 32253 |
} |
| 32254 |
} |
| 32255 |
this.stream = stream; |
| 32256 |
this.maybeLength = maybeLength; |
| 32257 |
this.dict = dict; |
| 32258 |
|
| 32259 |
DecodeStream.call(this, maybeLength); |
| 32260 |
} |
| 32261 |
|
| 32262 |
JpegStream.prototype = Object.create(DecodeStream.prototype); |
| 32263 |
|
| 32264 |
Object.defineProperty(JpegStream.prototype, 'bytes', { |
| 32265 |
get: function JpegStream_bytes() { |
| 32266 |
// If this.maybeLength is null, we'll get the entire stream. |
| 32267 |
return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); |
| 32268 |
}, |
| 32269 |
configurable: true |
| 32270 |
}); |
| 32271 |
|
| 32272 |
JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) { |
| 32273 |
if (this.bufferLength) { |
| 32274 |
return; |
| 32275 |
} |
| 32276 |
try { |
| 32277 |
var jpegImage = new JpegImage(); |
| 32278 |
|
| 32279 |
// checking if values needs to be transformed before conversion |
| 32280 |
if (this.forceRGB && this.dict && isArray(this.dict.get('Decode'))) { |
| 32281 |
var decodeArr = this.dict.get('Decode'); |
| 32282 |
var bitsPerComponent = this.dict.get('BitsPerComponent') || 8; |
| 32283 |
var decodeArrLength = decodeArr.length; |
| 32284 |
var transform = new Int32Array(decodeArrLength); |
| 32285 |
var transformNeeded = false; |
| 32286 |
var maxValue = (1 << bitsPerComponent) - 1; |
| 32287 |
for (var i = 0; i < decodeArrLength; i += 2) { |
| 32288 |
transform[i] = ((decodeArr[i + 1] - decodeArr[i]) * 256) | 0; |
| 32289 |
transform[i + 1] = (decodeArr[i] * maxValue) | 0; |
| 32290 |
if (transform[i] !== 256 || transform[i + 1] !== 0) { |
| 32291 |
transformNeeded = true; |
| 32292 |
} |
| 32293 |
} |
| 32294 |
if (transformNeeded) { |
| 32295 |
jpegImage.decodeTransform = transform; |
| 32296 |
} |
| 32297 |
} |
| 32298 |
|
| 32299 |
jpegImage.parse(this.bytes); |
| 32300 |
var data = jpegImage.getData(this.drawWidth, this.drawHeight, |
| 32301 |
this.forceRGB); |
| 32302 |
this.buffer = data; |
| 32303 |
this.bufferLength = data.length; |
| 32304 |
this.eof = true; |
| 32305 |
} catch (e) { |
| 32306 |
error('JPEG error: ' + e); |
| 32307 |
} |
| 32308 |
}; |
| 32309 |
|
| 32310 |
JpegStream.prototype.getBytes = function JpegStream_getBytes(length) { |
| 32311 |
this.ensureBuffer(); |
| 32312 |
return this.buffer; |
| 32313 |
}; |
| 32314 |
|
| 32315 |
JpegStream.prototype.getIR = function JpegStream_getIR() { |
| 32316 |
return PDFJS.createObjectURL(this.bytes, 'image/jpeg'); |
| 32317 |
}; |
| 32318 |
/** |
| 32319 |
* Checks if the image can be decoded and displayed by the browser without any |
| 32320 |
* further processing such as color space conversions. |
| 32321 |
*/ |
| 32322 |
JpegStream.prototype.isNativelySupported = |
| 32323 |
function JpegStream_isNativelySupported(xref, res) { |
| 32324 |
var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res); |
| 32325 |
return cs.name === 'DeviceGray' || cs.name === 'DeviceRGB'; |
| 32326 |
}; |
| 32327 |
/** |
| 32328 |
* Checks if the image can be decoded by the browser. |
| 32329 |
*/ |
| 32330 |
JpegStream.prototype.isNativelyDecodable = |
| 32331 |
function JpegStream_isNativelyDecodable(xref, res) { |
| 32332 |
var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res); |
| 32333 |
var numComps = cs.numComps; |
| 32334 |
return numComps === 1 || numComps === 3; |
| 32335 |
}; |
| 32336 |
|
| 32337 |
return JpegStream; |
| 32338 |
})(); |
| 32339 |
|
| 32340 |
/** |
| 32341 |
* For JPEG 2000's we use a library to decode these images and |
| 32342 |
* the stream behaves like all the other DecodeStreams. |
| 32343 |
*/ |
| 32344 |
var JpxStream = (function JpxStreamClosure() { |
| 32345 |
function JpxStream(stream, maybeLength, dict) { |
| 32346 |
this.stream = stream; |
| 32347 |
this.maybeLength = maybeLength; |
| 32348 |
this.dict = dict; |
| 32349 |
|
| 32350 |
DecodeStream.call(this, maybeLength); |
| 32351 |
} |
| 32352 |
|
| 32353 |
JpxStream.prototype = Object.create(DecodeStream.prototype); |
| 32354 |
|
| 32355 |
Object.defineProperty(JpxStream.prototype, 'bytes', { |
| 32356 |
get: function JpxStream_bytes() { |
| 32357 |
// If this.maybeLength is null, we'll get the entire stream. |
| 32358 |
return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); |
| 32359 |
}, |
| 32360 |
configurable: true |
| 32361 |
}); |
| 32362 |
|
| 32363 |
JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) { |
| 32364 |
if (this.bufferLength) { |
| 32365 |
return; |
| 32366 |
} |
| 32367 |
|
| 32368 |
var jpxImage = new JpxImage(); |
| 32369 |
jpxImage.parse(this.bytes); |
| 32370 |
|
| 32371 |
var width = jpxImage.width; |
| 32372 |
var height = jpxImage.height; |
| 32373 |
var componentsCount = jpxImage.componentsCount; |
| 32374 |
var tileCount = jpxImage.tiles.length; |
| 32375 |
if (tileCount === 1) { |
| 32376 |
this.buffer = jpxImage.tiles[0].items; |
| 32377 |
} else { |
| 32378 |
var data = new Uint8Array(width * height * componentsCount); |
| 32379 |
|
| 32380 |
for (var k = 0; k < tileCount; k++) { |
| 32381 |
var tileComponents = jpxImage.tiles[k]; |
| 32382 |
var tileWidth = tileComponents.width; |
| 32383 |
var tileHeight = tileComponents.height; |
| 32384 |
var tileLeft = tileComponents.left; |
| 32385 |
var tileTop = tileComponents.top; |
| 32386 |
|
| 32387 |
var src = tileComponents.items; |
| 32388 |
var srcPosition = 0; |
| 32389 |
var dataPosition = (width * tileTop + tileLeft) * componentsCount; |
| 32390 |
var imgRowSize = width * componentsCount; |
| 32391 |
var tileRowSize = tileWidth * componentsCount; |
| 32392 |
|
| 32393 |
for (var j = 0; j < tileHeight; j++) { |
| 32394 |
var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize); |
| 32395 |
data.set(rowBytes, dataPosition); |
| 32396 |
srcPosition += tileRowSize; |
| 32397 |
dataPosition += imgRowSize; |
| 32398 |
} |
| 32399 |
} |
| 32400 |
this.buffer = data; |
| 32401 |
} |
| 32402 |
this.bufferLength = this.buffer.length; |
| 32403 |
this.eof = true; |
| 32404 |
}; |
| 32405 |
|
| 32406 |
return JpxStream; |
| 32407 |
})(); |
| 32408 |
|
| 32409 |
/** |
| 32410 |
* For JBIG2's we use a library to decode these images and |
| 32411 |
* the stream behaves like all the other DecodeStreams. |
| 32412 |
*/ |
| 32413 |
var Jbig2Stream = (function Jbig2StreamClosure() { |
| 32414 |
function Jbig2Stream(stream, maybeLength, dict) { |
| 32415 |
this.stream = stream; |
| 32416 |
this.maybeLength = maybeLength; |
| 32417 |
this.dict = dict; |
| 32418 |
|
| 32419 |
DecodeStream.call(this, maybeLength); |
| 32420 |
} |
| 32421 |
|
| 32422 |
Jbig2Stream.prototype = Object.create(DecodeStream.prototype); |
| 32423 |
|
| 32424 |
Object.defineProperty(Jbig2Stream.prototype, 'bytes', { |
| 32425 |
get: function Jbig2Stream_bytes() { |
| 32426 |
// If this.maybeLength is null, we'll get the entire stream. |
| 32427 |
return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); |
| 32428 |
}, |
| 32429 |
configurable: true |
| 32430 |
}); |
| 32431 |
|
| 32432 |
Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) { |
| 32433 |
if (this.bufferLength) { |
| 32434 |
return; |
| 32435 |
} |
| 32436 |
|
| 32437 |
var jbig2Image = new Jbig2Image(); |
| 32438 |
|
| 32439 |
var chunks = [], xref = this.dict.xref; |
| 32440 |
var decodeParams = xref.fetchIfRef(this.dict.get('DecodeParms')); |
| 32441 |
|
| 32442 |
// According to the PDF specification, DecodeParms can be either |
| 32443 |
// a dictionary, or an array whose elements are dictionaries. |
| 32444 |
if (isArray(decodeParams)) { |
| 32445 |
if (decodeParams.length > 1) { |
| 32446 |
warn('JBIG2 - \'DecodeParms\' array with multiple elements ' + |
| 32447 |
'not supported.'); |
| 32448 |
} |
| 32449 |
decodeParams = xref.fetchIfRef(decodeParams[0]); |
| 32450 |
} |
| 32451 |
if (decodeParams && decodeParams.has('JBIG2Globals')) { |
| 32452 |
var globalsStream = decodeParams.get('JBIG2Globals'); |
| 32453 |
var globals = globalsStream.getBytes(); |
| 32454 |
chunks.push({data: globals, start: 0, end: globals.length}); |
| 32455 |
} |
| 32456 |
chunks.push({data: this.bytes, start: 0, end: this.bytes.length}); |
| 32457 |
var data = jbig2Image.parseChunks(chunks); |
| 32458 |
var dataLength = data.length; |
| 32459 |
|
| 32460 |
// JBIG2 had black as 1 and white as 0, inverting the colors |
| 32461 |
for (var i = 0; i < dataLength; i++) { |
| 32462 |
data[i] ^= 0xFF; |
| 32463 |
} |
| 32464 |
|
| 32465 |
this.buffer = data; |
| 32466 |
this.bufferLength = dataLength; |
| 32467 |
this.eof = true; |
| 32468 |
}; |
| 32469 |
|
| 32470 |
return Jbig2Stream; |
| 32471 |
})(); |
| 32472 |
|
| 32473 |
var DecryptStream = (function DecryptStreamClosure() { |
| 32474 |
function DecryptStream(str, maybeLength, decrypt) { |
| 32475 |
this.str = str; |
| 32476 |
this.dict = str.dict; |
| 32477 |
this.decrypt = decrypt; |
| 32478 |
this.nextChunk = null; |
| 32479 |
this.initialized = false; |
| 32480 |
|
| 32481 |
DecodeStream.call(this, maybeLength); |
| 32482 |
} |
| 32483 |
|
| 32484 |
var chunkSize = 512; |
| 32485 |
|
| 32486 |
DecryptStream.prototype = Object.create(DecodeStream.prototype); |
| 32487 |
|
| 32488 |
DecryptStream.prototype.readBlock = function DecryptStream_readBlock() { |
| 32489 |
var chunk; |
| 32490 |
if (this.initialized) { |
| 32491 |
chunk = this.nextChunk; |
| 32492 |
} else { |
| 32493 |
chunk = this.str.getBytes(chunkSize); |
| 32494 |
this.initialized = true; |
| 32495 |
} |
| 32496 |
if (!chunk || chunk.length === 0) { |
| 32497 |
this.eof = true; |
| 32498 |
return; |
| 32499 |
} |
| 32500 |
this.nextChunk = this.str.getBytes(chunkSize); |
| 32501 |
var hasMoreData = this.nextChunk && this.nextChunk.length > 0; |
| 32502 |
|
| 32503 |
var decrypt = this.decrypt; |
| 32504 |
chunk = decrypt(chunk, !hasMoreData); |
| 32505 |
|
| 32506 |
var bufferLength = this.bufferLength; |
| 32507 |
var i, n = chunk.length; |
| 32508 |
var buffer = this.ensureBuffer(bufferLength + n); |
| 32509 |
for (i = 0; i < n; i++) { |
| 32510 |
buffer[bufferLength++] = chunk[i]; |
| 32511 |
} |
| 32512 |
this.bufferLength = bufferLength; |
| 32513 |
}; |
| 32514 |
|
| 32515 |
return DecryptStream; |
| 32516 |
})(); |
| 32517 |
|
| 32518 |
var Ascii85Stream = (function Ascii85StreamClosure() { |
| 32519 |
function Ascii85Stream(str, maybeLength) { |
| 32520 |
this.str = str; |
| 32521 |
this.dict = str.dict; |
| 32522 |
this.input = new Uint8Array(5); |
| 32523 |
|
| 32524 |
// Most streams increase in size when decoded, but Ascii85 streams |
| 32525 |
// typically shrink by ~20%. |
| 32526 |
if (maybeLength) { |
| 32527 |
maybeLength = 0.8 * maybeLength; |
| 32528 |
} |
| 32529 |
DecodeStream.call(this, maybeLength); |
| 32530 |
} |
| 32531 |
|
| 32532 |
Ascii85Stream.prototype = Object.create(DecodeStream.prototype); |
| 32533 |
|
| 32534 |
Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() { |
| 32535 |
var TILDA_CHAR = 0x7E; // '~' |
| 32536 |
var Z_LOWER_CHAR = 0x7A; // 'z' |
| 32537 |
var EOF = -1; |
| 32538 |
|
| 32539 |
var str = this.str; |
| 32540 |
|
| 32541 |
var c = str.getByte(); |
| 32542 |
while (Lexer.isSpace(c)) { |
| 32543 |
c = str.getByte(); |
| 32544 |
} |
| 32545 |
|
| 32546 |
if (c === EOF || c === TILDA_CHAR) { |
| 32547 |
this.eof = true; |
| 32548 |
return; |
| 32549 |
} |
| 32550 |
|
| 32551 |
var bufferLength = this.bufferLength, buffer; |
| 32552 |
var i; |
| 32553 |
|
| 32554 |
// special code for z |
| 32555 |
if (c === Z_LOWER_CHAR) { |
| 32556 |
buffer = this.ensureBuffer(bufferLength + 4); |
| 32557 |
for (i = 0; i < 4; ++i) { |
| 32558 |
buffer[bufferLength + i] = 0; |
| 32559 |
} |
| 32560 |
this.bufferLength += 4; |
| 32561 |
} else { |
| 32562 |
var input = this.input; |
| 32563 |
input[0] = c; |
| 32564 |
for (i = 1; i < 5; ++i) { |
| 32565 |
c = str.getByte(); |
| 32566 |
while (Lexer.isSpace(c)) { |
| 32567 |
c = str.getByte(); |
| 32568 |
} |
| 32569 |
|
| 32570 |
input[i] = c; |
| 32571 |
|
| 32572 |
if (c === EOF || c === TILDA_CHAR) { |
| 32573 |
break; |
| 32574 |
} |
| 32575 |
} |
| 32576 |
buffer = this.ensureBuffer(bufferLength + i - 1); |
| 32577 |
this.bufferLength += i - 1; |
| 32578 |
|
| 32579 |
// partial ending; |
| 32580 |
if (i < 5) { |
| 32581 |
for (; i < 5; ++i) { |
| 32582 |
input[i] = 0x21 + 84; |
| 32583 |
} |
| 32584 |
this.eof = true; |
| 32585 |
} |
| 32586 |
var t = 0; |
| 32587 |
for (i = 0; i < 5; ++i) { |
| 32588 |
t = t * 85 + (input[i] - 0x21); |
| 32589 |
} |
| 32590 |
|
| 32591 |
for (i = 3; i >= 0; --i) { |
| 32592 |
buffer[bufferLength + i] = t & 0xFF; |
| 32593 |
t >>= 8; |
| 32594 |
} |
| 32595 |
} |
| 32596 |
}; |
| 32597 |
|
| 32598 |
return Ascii85Stream; |
| 32599 |
})(); |
| 32600 |
|
| 32601 |
var AsciiHexStream = (function AsciiHexStreamClosure() { |
| 32602 |
function AsciiHexStream(str, maybeLength) { |
| 32603 |
this.str = str; |
| 32604 |
this.dict = str.dict; |
| 32605 |
|
| 32606 |
this.firstDigit = -1; |
| 32607 |
|
| 32608 |
// Most streams increase in size when decoded, but AsciiHex streams shrink |
| 32609 |
// by 50%. |
| 32610 |
if (maybeLength) { |
| 32611 |
maybeLength = 0.5 * maybeLength; |
| 32612 |
} |
| 32613 |
DecodeStream.call(this, maybeLength); |
| 32614 |
} |
| 32615 |
|
| 32616 |
AsciiHexStream.prototype = Object.create(DecodeStream.prototype); |
| 32617 |
|
| 32618 |
AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() { |
| 32619 |
var UPSTREAM_BLOCK_SIZE = 8000; |
| 32620 |
var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE); |
| 32621 |
if (!bytes.length) { |
| 32622 |
this.eof = true; |
| 32623 |
return; |
| 32624 |
} |
| 32625 |
|
| 32626 |
var maxDecodeLength = (bytes.length + 1) >> 1; |
| 32627 |
var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); |
| 32628 |
var bufferLength = this.bufferLength; |
| 32629 |
|
| 32630 |
var firstDigit = this.firstDigit; |
| 32631 |
for (var i = 0, ii = bytes.length; i < ii; i++) { |
| 32632 |
var ch = bytes[i], digit; |
| 32633 |
if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' |
| 32634 |
digit = ch & 0x0F; |
| 32635 |
} else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { |
| 32636 |
// 'A'-'Z', 'a'-'z' |
| 32637 |
digit = (ch & 0x0F) + 9; |
| 32638 |
} else if (ch === 0x3E) { // '>' |
| 32639 |
this.eof = true; |
| 32640 |
break; |
| 32641 |
} else { // probably whitespace |
| 32642 |
continue; // ignoring |
| 32643 |
} |
| 32644 |
if (firstDigit < 0) { |
| 32645 |
firstDigit = digit; |
| 32646 |
} else { |
| 32647 |
buffer[bufferLength++] = (firstDigit << 4) | digit; |
| 32648 |
firstDigit = -1; |
| 32649 |
} |
| 32650 |
} |
| 32651 |
if (firstDigit >= 0 && this.eof) { |
| 32652 |
// incomplete byte |
| 32653 |
buffer[bufferLength++] = (firstDigit << 4); |
| 32654 |
firstDigit = -1; |
| 32655 |
} |
| 32656 |
this.firstDigit = firstDigit; |
| 32657 |
this.bufferLength = bufferLength; |
| 32658 |
}; |
| 32659 |
|
| 32660 |
return AsciiHexStream; |
| 32661 |
})(); |
| 32662 |
|
| 32663 |
var RunLengthStream = (function RunLengthStreamClosure() { |
| 32664 |
function RunLengthStream(str, maybeLength) { |
| 32665 |
this.str = str; |
| 32666 |
this.dict = str.dict; |
| 32667 |
|
| 32668 |
DecodeStream.call(this, maybeLength); |
| 32669 |
} |
| 32670 |
|
| 32671 |
RunLengthStream.prototype = Object.create(DecodeStream.prototype); |
| 32672 |
|
| 32673 |
RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() { |
| 32674 |
// The repeatHeader has following format. The first byte defines type of run |
| 32675 |
// and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes |
| 32676 |
// (in addition to the second byte from the header), n = 129 through 255 - |
| 32677 |
// duplicate the second byte from the header (257 - n) times, n = 128 - end. |
| 32678 |
var repeatHeader = this.str.getBytes(2); |
| 32679 |
if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) { |
| 32680 |
this.eof = true; |
| 32681 |
return; |
| 32682 |
} |
| 32683 |
|
| 32684 |
var buffer; |
| 32685 |
var bufferLength = this.bufferLength; |
| 32686 |
var n = repeatHeader[0]; |
| 32687 |
if (n < 128) { |
| 32688 |
// copy n bytes |
| 32689 |
buffer = this.ensureBuffer(bufferLength + n + 1); |
| 32690 |
buffer[bufferLength++] = repeatHeader[1]; |
| 32691 |
if (n > 0) { |
| 32692 |
var source = this.str.getBytes(n); |
| 32693 |
buffer.set(source, bufferLength); |
| 32694 |
bufferLength += n; |
| 32695 |
} |
| 32696 |
} else { |
| 32697 |
n = 257 - n; |
| 32698 |
var b = repeatHeader[1]; |
| 32699 |
buffer = this.ensureBuffer(bufferLength + n + 1); |
| 32700 |
for (var i = 0; i < n; i++) { |
| 32701 |
buffer[bufferLength++] = b; |
| 32702 |
} |
| 32703 |
} |
| 32704 |
this.bufferLength = bufferLength; |
| 32705 |
}; |
| 32706 |
|
| 32707 |
return RunLengthStream; |
| 32708 |
})(); |
| 32709 |
|
| 32710 |
var CCITTFaxStream = (function CCITTFaxStreamClosure() { |
| 32711 |
|
| 32712 |
var ccittEOL = -2; |
| 32713 |
var twoDimPass = 0; |
| 32714 |
var twoDimHoriz = 1; |
| 32715 |
var twoDimVert0 = 2; |
| 32716 |
var twoDimVertR1 = 3; |
| 32717 |
var twoDimVertL1 = 4; |
| 32718 |
var twoDimVertR2 = 5; |
| 32719 |
var twoDimVertL2 = 6; |
| 32720 |
var twoDimVertR3 = 7; |
| 32721 |
var twoDimVertL3 = 8; |
| 32722 |
|
| 32723 |
var twoDimTable = [ |
| 32724 |
[-1, -1], [-1, -1], // 000000x |
| 32725 |
[7, twoDimVertL3], // 0000010 |
| 32726 |
[7, twoDimVertR3], // 0000011 |
| 32727 |
[6, twoDimVertL2], [6, twoDimVertL2], // 000010x |
| 32728 |
[6, twoDimVertR2], [6, twoDimVertR2], // 000011x |
| 32729 |
[4, twoDimPass], [4, twoDimPass], // 0001xxx |
| 32730 |
[4, twoDimPass], [4, twoDimPass], |
| 32731 |
[4, twoDimPass], [4, twoDimPass], |
| 32732 |
[4, twoDimPass], [4, twoDimPass], |
| 32733 |
[3, twoDimHoriz], [3, twoDimHoriz], // 001xxxx |
| 32734 |
[3, twoDimHoriz], [3, twoDimHoriz], |
| 32735 |
[3, twoDimHoriz], [3, twoDimHoriz], |
| 32736 |
[3, twoDimHoriz], [3, twoDimHoriz], |
| 32737 |
[3, twoDimHoriz], [3, twoDimHoriz], |
| 32738 |
[3, twoDimHoriz], [3, twoDimHoriz], |
| 32739 |
[3, twoDimHoriz], [3, twoDimHoriz], |
| 32740 |
[3, twoDimHoriz], [3, twoDimHoriz], |
| 32741 |
[3, twoDimVertL1], [3, twoDimVertL1], // 010xxxx |
| 32742 |
[3, twoDimVertL1], [3, twoDimVertL1], |
| 32743 |
[3, twoDimVertL1], [3, twoDimVertL1], |
| 32744 |
[3, twoDimVertL1], [3, twoDimVertL1], |
| 32745 |
[3, twoDimVertL1], [3, twoDimVertL1], |
| 32746 |
[3, twoDimVertL1], [3, twoDimVertL1], |
| 32747 |
[3, twoDimVertL1], [3, twoDimVertL1], |
| 32748 |
[3, twoDimVertL1], [3, twoDimVertL1], |
| 32749 |
[3, twoDimVertR1], [3, twoDimVertR1], // 011xxxx |
| 32750 |
[3, twoDimVertR1], [3, twoDimVertR1], |
| 32751 |
[3, twoDimVertR1], [3, twoDimVertR1], |
| 32752 |
[3, twoDimVertR1], [3, twoDimVertR1], |
| 32753 |
[3, twoDimVertR1], [3, twoDimVertR1], |
| 32754 |
[3, twoDimVertR1], [3, twoDimVertR1], |
| 32755 |
[3, twoDimVertR1], [3, twoDimVertR1], |
| 32756 |
[3, twoDimVertR1], [3, twoDimVertR1], |
| 32757 |
[1, twoDimVert0], [1, twoDimVert0], // 1xxxxxx |
| 32758 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32759 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32760 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32761 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32762 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32763 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32764 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32765 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32766 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32767 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32768 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32769 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32770 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32771 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32772 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32773 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32774 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32775 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32776 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32777 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32778 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32779 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32780 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32781 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32782 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32783 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32784 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32785 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32786 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32787 |
[1, twoDimVert0], [1, twoDimVert0], |
| 32788 |
[1, twoDimVert0], [1, twoDimVert0] |
| 32789 |
]; |
| 32790 |
|
| 32791 |
var whiteTable1 = [ |
| 32792 |
[-1, -1], // 00000 |
| 32793 |
[12, ccittEOL], // 00001 |
| 32794 |
[-1, -1], [-1, -1], // 0001x |
| 32795 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 001xx |
| 32796 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 010xx |
| 32797 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 011xx |
| 32798 |
[11, 1792], [11, 1792], // 1000x |
| 32799 |
[12, 1984], // 10010 |
| 32800 |
[12, 2048], // 10011 |
| 32801 |
[12, 2112], // 10100 |
| 32802 |
[12, 2176], // 10101 |
| 32803 |
[12, 2240], // 10110 |
| 32804 |
[12, 2304], // 10111 |
| 32805 |
[11, 1856], [11, 1856], // 1100x |
| 32806 |
[11, 1920], [11, 1920], // 1101x |
| 32807 |
[12, 2368], // 11100 |
| 32808 |
[12, 2432], // 11101 |
| 32809 |
[12, 2496], // 11110 |
| 32810 |
[12, 2560] // 11111 |
| 32811 |
]; |
| 32812 |
|
| 32813 |
var whiteTable2 = [ |
| 32814 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000000xx |
| 32815 |
[8, 29], [8, 29], // 00000010x |
| 32816 |
[8, 30], [8, 30], // 00000011x |
| 32817 |
[8, 45], [8, 45], // 00000100x |
| 32818 |
[8, 46], [8, 46], // 00000101x |
| 32819 |
[7, 22], [7, 22], [7, 22], [7, 22], // 0000011xx |
| 32820 |
[7, 23], [7, 23], [7, 23], [7, 23], // 0000100xx |
| 32821 |
[8, 47], [8, 47], // 00001010x |
| 32822 |
[8, 48], [8, 48], // 00001011x |
| 32823 |
[6, 13], [6, 13], [6, 13], [6, 13], // 000011xxx |
| 32824 |
[6, 13], [6, 13], [6, 13], [6, 13], |
| 32825 |
[7, 20], [7, 20], [7, 20], [7, 20], // 0001000xx |
| 32826 |
[8, 33], [8, 33], // 00010010x |
| 32827 |
[8, 34], [8, 34], // 00010011x |
| 32828 |
[8, 35], [8, 35], // 00010100x |
| 32829 |
[8, 36], [8, 36], // 00010101x |
| 32830 |
[8, 37], [8, 37], // 00010110x |
| 32831 |
[8, 38], [8, 38], // 00010111x |
| 32832 |
[7, 19], [7, 19], [7, 19], [7, 19], // 0001100xx |
| 32833 |
[8, 31], [8, 31], // 00011010x |
| 32834 |
[8, 32], [8, 32], // 00011011x |
| 32835 |
[6, 1], [6, 1], [6, 1], [6, 1], // 000111xxx |
| 32836 |
[6, 1], [6, 1], [6, 1], [6, 1], |
| 32837 |
[6, 12], [6, 12], [6, 12], [6, 12], // 001000xxx |
| 32838 |
[6, 12], [6, 12], [6, 12], [6, 12], |
| 32839 |
[8, 53], [8, 53], // 00100100x |
| 32840 |
[8, 54], [8, 54], // 00100101x |
| 32841 |
[7, 26], [7, 26], [7, 26], [7, 26], // 0010011xx |
| 32842 |
[8, 39], [8, 39], // 00101000x |
| 32843 |
[8, 40], [8, 40], // 00101001x |
| 32844 |
[8, 41], [8, 41], // 00101010x |
| 32845 |
[8, 42], [8, 42], // 00101011x |
| 32846 |
[8, 43], [8, 43], // 00101100x |
| 32847 |
[8, 44], [8, 44], // 00101101x |
| 32848 |
[7, 21], [7, 21], [7, 21], [7, 21], // 0010111xx |
| 32849 |
[7, 28], [7, 28], [7, 28], [7, 28], // 0011000xx |
| 32850 |
[8, 61], [8, 61], // 00110010x |
| 32851 |
[8, 62], [8, 62], // 00110011x |
| 32852 |
[8, 63], [8, 63], // 00110100x |
| 32853 |
[8, 0], [8, 0], // 00110101x |
| 32854 |
[8, 320], [8, 320], // 00110110x |
| 32855 |
[8, 384], [8, 384], // 00110111x |
| 32856 |
[5, 10], [5, 10], [5, 10], [5, 10], // 00111xxxx |
| 32857 |
[5, 10], [5, 10], [5, 10], [5, 10], |
| 32858 |
[5, 10], [5, 10], [5, 10], [5, 10], |
| 32859 |
[5, 10], [5, 10], [5, 10], [5, 10], |
| 32860 |
[5, 11], [5, 11], [5, 11], [5, 11], // 01000xxxx |
| 32861 |
[5, 11], [5, 11], [5, 11], [5, 11], |
| 32862 |
[5, 11], [5, 11], [5, 11], [5, 11], |
| 32863 |
[5, 11], [5, 11], [5, 11], [5, 11], |
| 32864 |
[7, 27], [7, 27], [7, 27], [7, 27], // 0100100xx |
| 32865 |
[8, 59], [8, 59], // 01001010x |
| 32866 |
[8, 60], [8, 60], // 01001011x |
| 32867 |
[9, 1472], // 010011000 |
| 32868 |
[9, 1536], // 010011001 |
| 32869 |
[9, 1600], // 010011010 |
| 32870 |
[9, 1728], // 010011011 |
| 32871 |
[7, 18], [7, 18], [7, 18], [7, 18], // 0100111xx |
| 32872 |
[7, 24], [7, 24], [7, 24], [7, 24], // 0101000xx |
| 32873 |
[8, 49], [8, 49], // 01010010x |
| 32874 |
[8, 50], [8, 50], // 01010011x |
| 32875 |
[8, 51], [8, 51], // 01010100x |
| 32876 |
[8, 52], [8, 52], // 01010101x |
| 32877 |
[7, 25], [7, 25], [7, 25], [7, 25], // 0101011xx |
| 32878 |
[8, 55], [8, 55], // 01011000x |
| 32879 |
[8, 56], [8, 56], // 01011001x |
| 32880 |
[8, 57], [8, 57], // 01011010x |
| 32881 |
[8, 58], [8, 58], // 01011011x |
| 32882 |
[6, 192], [6, 192], [6, 192], [6, 192], // 010111xxx |
| 32883 |
[6, 192], [6, 192], [6, 192], [6, 192], |
| 32884 |
[6, 1664], [6, 1664], [6, 1664], [6, 1664], // 011000xxx |
| 32885 |
[6, 1664], [6, 1664], [6, 1664], [6, 1664], |
| 32886 |
[8, 448], [8, 448], // 01100100x |
| 32887 |
[8, 512], [8, 512], // 01100101x |
| 32888 |
[9, 704], // 011001100 |
| 32889 |
[9, 768], // 011001101 |
| 32890 |
[8, 640], [8, 640], // 01100111x |
| 32891 |
[8, 576], [8, 576], // 01101000x |
| 32892 |
[9, 832], // 011010010 |
| 32893 |
[9, 896], // 011010011 |
| 32894 |
[9, 960], // 011010100 |
| 32895 |
[9, 1024], // 011010101 |
| 32896 |
[9, 1088], // 011010110 |
| 32897 |
[9, 1152], // 011010111 |
| 32898 |
[9, 1216], // 011011000 |
| 32899 |
[9, 1280], // 011011001 |
| 32900 |
[9, 1344], // 011011010 |
| 32901 |
[9, 1408], // 011011011 |
| 32902 |
[7, 256], [7, 256], [7, 256], [7, 256], // 0110111xx |
| 32903 |
[4, 2], [4, 2], [4, 2], [4, 2], // 0111xxxxx |
| 32904 |
[4, 2], [4, 2], [4, 2], [4, 2], |
| 32905 |
[4, 2], [4, 2], [4, 2], [4, 2], |
| 32906 |
[4, 2], [4, 2], [4, 2], [4, 2], |
| 32907 |
[4, 2], [4, 2], [4, 2], [4, 2], |
| 32908 |
[4, 2], [4, 2], [4, 2], [4, 2], |
| 32909 |
[4, 2], [4, 2], [4, 2], [4, 2], |
| 32910 |
[4, 2], [4, 2], [4, 2], [4, 2], |
| 32911 |
[4, 3], [4, 3], [4, 3], [4, 3], // 1000xxxxx |
| 32912 |
[4, 3], [4, 3], [4, 3], [4, 3], |
| 32913 |
[4, 3], [4, 3], [4, 3], [4, 3], |
| 32914 |
[4, 3], [4, 3], [4, 3], [4, 3], |
| 32915 |
[4, 3], [4, 3], [4, 3], [4, 3], |
| 32916 |
[4, 3], [4, 3], [4, 3], [4, 3], |
| 32917 |
[4, 3], [4, 3], [4, 3], [4, 3], |
| 32918 |
[4, 3], [4, 3], [4, 3], [4, 3], |
| 32919 |
[5, 128], [5, 128], [5, 128], [5, 128], // 10010xxxx |
| 32920 |
[5, 128], [5, 128], [5, 128], [5, 128], |
| 32921 |
[5, 128], [5, 128], [5, 128], [5, 128], |
| 32922 |
[5, 128], [5, 128], [5, 128], [5, 128], |
| 32923 |
[5, 8], [5, 8], [5, 8], [5, 8], // 10011xxxx |
| 32924 |
[5, 8], [5, 8], [5, 8], [5, 8], |
| 32925 |
[5, 8], [5, 8], [5, 8], [5, 8], |
| 32926 |
[5, 8], [5, 8], [5, 8], [5, 8], |
| 32927 |
[5, 9], [5, 9], [5, 9], [5, 9], // 10100xxxx |
| 32928 |
[5, 9], [5, 9], [5, 9], [5, 9], |
| 32929 |
[5, 9], [5, 9], [5, 9], [5, 9], |
| 32930 |
[5, 9], [5, 9], [5, 9], [5, 9], |
| 32931 |
[6, 16], [6, 16], [6, 16], [6, 16], // 101010xxx |
| 32932 |
[6, 16], [6, 16], [6, 16], [6, 16], |
| 32933 |
[6, 17], [6, 17], [6, 17], [6, 17], // 101011xxx |
| 32934 |
[6, 17], [6, 17], [6, 17], [6, 17], |
| 32935 |
[4, 4], [4, 4], [4, 4], [4, 4], // 1011xxxxx |
| 32936 |
[4, 4], [4, 4], [4, 4], [4, 4], |
| 32937 |
[4, 4], [4, 4], [4, 4], [4, 4], |
| 32938 |
[4, 4], [4, 4], [4, 4], [4, 4], |
| 32939 |
[4, 4], [4, 4], [4, 4], [4, 4], |
| 32940 |
[4, 4], [4, 4], [4, 4], [4, 4], |
| 32941 |
[4, 4], [4, 4], [4, 4], [4, 4], |
| 32942 |
[4, 4], [4, 4], [4, 4], [4, 4], |
| 32943 |
[4, 5], [4, 5], [4, 5], [4, 5], // 1100xxxxx |
| 32944 |
[4, 5], [4, 5], [4, 5], [4, 5], |
| 32945 |
[4, 5], [4, 5], [4, 5], [4, 5], |
| 32946 |
[4, 5], [4, 5], [4, 5], [4, 5], |
| 32947 |
[4, 5], [4, 5], [4, 5], [4, 5], |
| 32948 |
[4, 5], [4, 5], [4, 5], [4, 5], |
| 32949 |
[4, 5], [4, 5], [4, 5], [4, 5], |
| 32950 |
[4, 5], [4, 5], [4, 5], [4, 5], |
| 32951 |
[6, 14], [6, 14], [6, 14], [6, 14], // 110100xxx |
| 32952 |
[6, 14], [6, 14], [6, 14], [6, 14], |
| 32953 |
[6, 15], [6, 15], [6, 15], [6, 15], // 110101xxx |
| 32954 |
[6, 15], [6, 15], [6, 15], [6, 15], |
| 32955 |
[5, 64], [5, 64], [5, 64], [5, 64], // 11011xxxx |
| 32956 |
[5, 64], [5, 64], [5, 64], [5, 64], |
| 32957 |
[5, 64], [5, 64], [5, 64], [5, 64], |
| 32958 |
[5, 64], [5, 64], [5, 64], [5, 64], |
| 32959 |
[4, 6], [4, 6], [4, 6], [4, 6], // 1110xxxxx |
| 32960 |
[4, 6], [4, 6], [4, 6], [4, 6], |
| 32961 |
[4, 6], [4, 6], [4, 6], [4, 6], |
| 32962 |
[4, 6], [4, 6], [4, 6], [4, 6], |
| 32963 |
[4, 6], [4, 6], [4, 6], [4, 6], |
| 32964 |
[4, 6], [4, 6], [4, 6], [4, 6], |
| 32965 |
[4, 6], [4, 6], [4, 6], [4, 6], |
| 32966 |
[4, 6], [4, 6], [4, 6], [4, 6], |
| 32967 |
[4, 7], [4, 7], [4, 7], [4, 7], // 1111xxxxx |
| 32968 |
[4, 7], [4, 7], [4, 7], [4, 7], |
| 32969 |
[4, 7], [4, 7], [4, 7], [4, 7], |
| 32970 |
[4, 7], [4, 7], [4, 7], [4, 7], |
| 32971 |
[4, 7], [4, 7], [4, 7], [4, 7], |
| 32972 |
[4, 7], [4, 7], [4, 7], [4, 7], |
| 32973 |
[4, 7], [4, 7], [4, 7], [4, 7], |
| 32974 |
[4, 7], [4, 7], [4, 7], [4, 7] |
| 32975 |
]; |
| 32976 |
|
| 32977 |
var blackTable1 = [ |
| 32978 |
[-1, -1], [-1, -1], // 000000000000x |
| 32979 |
[12, ccittEOL], [12, ccittEOL], // 000000000001x |
| 32980 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000001xx |
| 32981 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000010xx |
| 32982 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000011xx |
| 32983 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000100xx |
| 32984 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000101xx |
| 32985 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000110xx |
| 32986 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000111xx |
| 32987 |
[11, 1792], [11, 1792], [11, 1792], [11, 1792], // 00000001000xx |
| 32988 |
[12, 1984], [12, 1984], // 000000010010x |
| 32989 |
[12, 2048], [12, 2048], // 000000010011x |
| 32990 |
[12, 2112], [12, 2112], // 000000010100x |
| 32991 |
[12, 2176], [12, 2176], // 000000010101x |
| 32992 |
[12, 2240], [12, 2240], // 000000010110x |
| 32993 |
[12, 2304], [12, 2304], // 000000010111x |
| 32994 |
[11, 1856], [11, 1856], [11, 1856], [11, 1856], // 00000001100xx |
| 32995 |
[11, 1920], [11, 1920], [11, 1920], [11, 1920], // 00000001101xx |
| 32996 |
[12, 2368], [12, 2368], // 000000011100x |
| 32997 |
[12, 2432], [12, 2432], // 000000011101x |
| 32998 |
[12, 2496], [12, 2496], // 000000011110x |
| 32999 |
[12, 2560], [12, 2560], // 000000011111x |
| 33000 |
[10, 18], [10, 18], [10, 18], [10, 18], // 0000001000xxx |
| 33001 |
[10, 18], [10, 18], [10, 18], [10, 18], |
| 33002 |
[12, 52], [12, 52], // 000000100100x |
| 33003 |
[13, 640], // 0000001001010 |
| 33004 |
[13, 704], // 0000001001011 |
| 33005 |
[13, 768], // 0000001001100 |
| 33006 |
[13, 832], // 0000001001101 |
| 33007 |
[12, 55], [12, 55], // 000000100111x |
| 33008 |
[12, 56], [12, 56], // 000000101000x |
| 33009 |
[13, 1280], // 0000001010010 |
| 33010 |
[13, 1344], // 0000001010011 |
| 33011 |
[13, 1408], // 0000001010100 |
| 33012 |
[13, 1472], // 0000001010101 |
| 33013 |
[12, 59], [12, 59], // 000000101011x |
| 33014 |
[12, 60], [12, 60], // 000000101100x |
| 33015 |
[13, 1536], // 0000001011010 |
| 33016 |
[13, 1600], // 0000001011011 |
| 33017 |
[11, 24], [11, 24], [11, 24], [11, 24], // 00000010111xx |
| 33018 |
[11, 25], [11, 25], [11, 25], [11, 25], // 00000011000xx |
| 33019 |
[13, 1664], // 0000001100100 |
| 33020 |
[13, 1728], // 0000001100101 |
| 33021 |
[12, 320], [12, 320], // 000000110011x |
| 33022 |
[12, 384], [12, 384], // 000000110100x |
| 33023 |
[12, 448], [12, 448], // 000000110101x |
| 33024 |
[13, 512], // 0000001101100 |
| 33025 |
[13, 576], // 0000001101101 |
| 33026 |
[12, 53], [12, 53], // 000000110111x |
| 33027 |
[12, 54], [12, 54], // 000000111000x |
| 33028 |
[13, 896], // 0000001110010 |
| 33029 |
[13, 960], // 0000001110011 |
| 33030 |
[13, 1024], // 0000001110100 |
| 33031 |
[13, 1088], // 0000001110101 |
| 33032 |
[13, 1152], // 0000001110110 |
| 33033 |
[13, 1216], // 0000001110111 |
| 33034 |
[10, 64], [10, 64], [10, 64], [10, 64], // 0000001111xxx |
| 33035 |
[10, 64], [10, 64], [10, 64], [10, 64] |
| 33036 |
]; |
| 33037 |
|
| 33038 |
var blackTable2 = [ |
| 33039 |
[8, 13], [8, 13], [8, 13], [8, 13], // 00000100xxxx |
| 33040 |
[8, 13], [8, 13], [8, 13], [8, 13], |
| 33041 |
[8, 13], [8, 13], [8, 13], [8, 13], |
| 33042 |
[8, 13], [8, 13], [8, 13], [8, 13], |
| 33043 |
[11, 23], [11, 23], // 00000101000x |
| 33044 |
[12, 50], // 000001010010 |
| 33045 |
[12, 51], // 000001010011 |
| 33046 |
[12, 44], // 000001010100 |
| 33047 |
[12, 45], // 000001010101 |
| 33048 |
[12, 46], // 000001010110 |
| 33049 |
[12, 47], // 000001010111 |
| 33050 |
[12, 57], // 000001011000 |
| 33051 |
[12, 58], // 000001011001 |
| 33052 |
[12, 61], // 000001011010 |
| 33053 |
[12, 256], // 000001011011 |
| 33054 |
[10, 16], [10, 16], [10, 16], [10, 16], // 0000010111xx |
| 33055 |
[10, 17], [10, 17], [10, 17], [10, 17], // 0000011000xx |
| 33056 |
[12, 48], // 000001100100 |
| 33057 |
[12, 49], // 000001100101 |
| 33058 |
[12, 62], // 000001100110 |
| 33059 |
[12, 63], // 000001100111 |
| 33060 |
[12, 30], // 000001101000 |
| 33061 |
[12, 31], // 000001101001 |
| 33062 |
[12, 32], // 000001101010 |
| 33063 |
[12, 33], // 000001101011 |
| 33064 |
[12, 40], // 000001101100 |
| 33065 |
[12, 41], // 000001101101 |
| 33066 |
[11, 22], [11, 22], // 00000110111x |
| 33067 |
[8, 14], [8, 14], [8, 14], [8, 14], // 00000111xxxx |
| 33068 |
[8, 14], [8, 14], [8, 14], [8, 14], |
| 33069 |
[8, 14], [8, 14], [8, 14], [8, 14], |
| 33070 |
[8, 14], [8, 14], [8, 14], [8, 14], |
| 33071 |
[7, 10], [7, 10], [7, 10], [7, 10], // 0000100xxxxx |
| 33072 |
[7, 10], [7, 10], [7, 10], [7, 10], |
| 33073 |
[7, 10], [7, 10], [7, 10], [7, 10], |
| 33074 |
[7, 10], [7, 10], [7, 10], [7, 10], |
| 33075 |
[7, 10], [7, 10], [7, 10], [7, 10], |
| 33076 |
[7, 10], [7, 10], [7, 10], [7, 10], |
| 33077 |
[7, 10], [7, 10], [7, 10], [7, 10], |
| 33078 |
[7, 10], [7, 10], [7, 10], [7, 10], |
| 33079 |
[7, 11], [7, 11], [7, 11], [7, 11], // 0000101xxxxx |
| 33080 |
[7, 11], [7, 11], [7, 11], [7, 11], |
| 33081 |
[7, 11], [7, 11], [7, 11], [7, 11], |
| 33082 |
[7, 11], [7, 11], [7, 11], [7, 11], |
| 33083 |
[7, 11], [7, 11], [7, 11], [7, 11], |
| 33084 |
[7, 11], [7, 11], [7, 11], [7, 11], |
| 33085 |
[7, 11], [7, 11], [7, 11], [7, 11], |
| 33086 |
[7, 11], [7, 11], [7, 11], [7, 11], |
| 33087 |
[9, 15], [9, 15], [9, 15], [9, 15], // 000011000xxx |
| 33088 |
[9, 15], [9, 15], [9, 15], [9, 15], |
| 33089 |
[12, 128], // 000011001000 |
| 33090 |
[12, 192], // 000011001001 |
| 33091 |
[12, 26], // 000011001010 |
| 33092 |
[12, 27], // 000011001011 |
| 33093 |
[12, 28], // 000011001100 |
| 33094 |
[12, 29], // 000011001101 |
| 33095 |
[11, 19], [11, 19], // 00001100111x |
| 33096 |
[11, 20], [11, 20], // 00001101000x |
| 33097 |
[12, 34], // 000011010010 |
| 33098 |
[12, 35], // 000011010011 |
| 33099 |
[12, 36], // 000011010100 |
| 33100 |
[12, 37], // 000011010101 |
| 33101 |
[12, 38], // 000011010110 |
| 33102 |
[12, 39], // 000011010111 |
| 33103 |
[11, 21], [11, 21], // 00001101100x |
| 33104 |
[12, 42], // 000011011010 |
| 33105 |
[12, 43], // 000011011011 |
| 33106 |
[10, 0], [10, 0], [10, 0], [10, 0], // 0000110111xx |
| 33107 |
[7, 12], [7, 12], [7, 12], [7, 12], // 0000111xxxxx |
| 33108 |
[7, 12], [7, 12], [7, 12], [7, 12], |
| 33109 |
[7, 12], [7, 12], [7, 12], [7, 12], |
| 33110 |
[7, 12], [7, 12], [7, 12], [7, 12], |
| 33111 |
[7, 12], [7, 12], [7, 12], [7, 12], |
| 33112 |
[7, 12], [7, 12], [7, 12], [7, 12], |
| 33113 |
[7, 12], [7, 12], [7, 12], [7, 12], |
| 33114 |
[7, 12], [7, 12], [7, 12], [7, 12] |
| 33115 |
]; |
| 33116 |
|
| 33117 |
var blackTable3 = [ |
| 33118 |
[-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000xx |
| 33119 |
[6, 9], // 000100 |
| 33120 |
[6, 8], // 000101 |
| 33121 |
[5, 7], [5, 7], // 00011x |
| 33122 |
[4, 6], [4, 6], [4, 6], [4, 6], // 0010xx |
| 33123 |
[4, 5], [4, 5], [4, 5], [4, 5], // 0011xx |
| 33124 |
[3, 1], [3, 1], [3, 1], [3, 1], // 010xxx |
| 33125 |
[3, 1], [3, 1], [3, 1], [3, 1], |
| 33126 |
[3, 4], [3, 4], [3, 4], [3, 4], // 011xxx |
| 33127 |
[3, 4], [3, 4], [3, 4], [3, 4], |
| 33128 |
[2, 3], [2, 3], [2, 3], [2, 3], // 10xxxx |
| 33129 |
[2, 3], [2, 3], [2, 3], [2, 3], |
| 33130 |
[2, 3], [2, 3], [2, 3], [2, 3], |
| 33131 |
[2, 3], [2, 3], [2, 3], [2, 3], |
| 33132 |
[2, 2], [2, 2], [2, 2], [2, 2], // 11xxxx |
| 33133 |
[2, 2], [2, 2], [2, 2], [2, 2], |
| 33134 |
[2, 2], [2, 2], [2, 2], [2, 2], |
| 33135 |
[2, 2], [2, 2], [2, 2], [2, 2] |
| 33136 |
]; |
| 33137 |
|
| 33138 |
function CCITTFaxStream(str, maybeLength, params) { |
| 33139 |
this.str = str; |
| 33140 |
this.dict = str.dict; |
| 33141 |
|
| 33142 |
params = params || Dict.empty; |
| 33143 |
|
| 33144 |
this.encoding = params.get('K') || 0; |
| 33145 |
this.eoline = params.get('EndOfLine') || false; |
| 33146 |
this.byteAlign = params.get('EncodedByteAlign') || false; |
| 33147 |
this.columns = params.get('Columns') || 1728; |
| 33148 |
this.rows = params.get('Rows') || 0; |
| 33149 |
var eoblock = params.get('EndOfBlock'); |
| 33150 |
if (eoblock === null || eoblock === undefined) { |
| 33151 |
eoblock = true; |
| 33152 |
} |
| 33153 |
this.eoblock = eoblock; |
| 33154 |
this.black = params.get('BlackIs1') || false; |
| 33155 |
|
| 33156 |
this.codingLine = new Uint32Array(this.columns + 1); |
| 33157 |
this.refLine = new Uint32Array(this.columns + 2); |
| 33158 |
|
| 33159 |
this.codingLine[0] = this.columns; |
| 33160 |
this.codingPos = 0; |
| 33161 |
|
| 33162 |
this.row = 0; |
| 33163 |
this.nextLine2D = this.encoding < 0; |
| 33164 |
this.inputBits = 0; |
| 33165 |
this.inputBuf = 0; |
| 33166 |
this.outputBits = 0; |
| 33167 |
|
| 33168 |
var code1; |
| 33169 |
while ((code1 = this.lookBits(12)) === 0) { |
| 33170 |
this.eatBits(1); |
| 33171 |
} |
| 33172 |
if (code1 === 1) { |
| 33173 |
this.eatBits(12); |
| 33174 |
} |
| 33175 |
if (this.encoding > 0) { |
| 33176 |
this.nextLine2D = !this.lookBits(1); |
| 33177 |
this.eatBits(1); |
| 33178 |
} |
| 33179 |
|
| 33180 |
DecodeStream.call(this, maybeLength); |
| 33181 |
} |
| 33182 |
|
| 33183 |
CCITTFaxStream.prototype = Object.create(DecodeStream.prototype); |
| 33184 |
|
| 33185 |
CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() { |
| 33186 |
while (!this.eof) { |
| 33187 |
var c = this.lookChar(); |
| 33188 |
this.ensureBuffer(this.bufferLength + 1); |
| 33189 |
this.buffer[this.bufferLength++] = c; |
| 33190 |
} |
| 33191 |
}; |
| 33192 |
|
| 33193 |
CCITTFaxStream.prototype.addPixels = |
| 33194 |
function ccittFaxStreamAddPixels(a1, blackPixels) { |
| 33195 |
var codingLine = this.codingLine; |
| 33196 |
var codingPos = this.codingPos; |
| 33197 |
|
| 33198 |
if (a1 > codingLine[codingPos]) { |
| 33199 |
if (a1 > this.columns) { |
| 33200 |
info('row is wrong length'); |
| 33201 |
this.err = true; |
| 33202 |
a1 = this.columns; |
| 33203 |
} |
| 33204 |
if ((codingPos & 1) ^ blackPixels) { |
| 33205 |
++codingPos; |
| 33206 |
} |
| 33207 |
|
| 33208 |
codingLine[codingPos] = a1; |
| 33209 |
} |
| 33210 |
this.codingPos = codingPos; |
| 33211 |
}; |
| 33212 |
|
| 33213 |
CCITTFaxStream.prototype.addPixelsNeg = |
| 33214 |
function ccittFaxStreamAddPixelsNeg(a1, blackPixels) { |
| 33215 |
var codingLine = this.codingLine; |
| 33216 |
var codingPos = this.codingPos; |
| 33217 |
|
| 33218 |
if (a1 > codingLine[codingPos]) { |
| 33219 |
if (a1 > this.columns) { |
| 33220 |
info('row is wrong length'); |
| 33221 |
this.err = true; |
| 33222 |
a1 = this.columns; |
| 33223 |
} |
| 33224 |
if ((codingPos & 1) ^ blackPixels) { |
| 33225 |
++codingPos; |
| 33226 |
} |
| 33227 |
|
| 33228 |
codingLine[codingPos] = a1; |
| 33229 |
} else if (a1 < codingLine[codingPos]) { |
| 33230 |
if (a1 < 0) { |
| 33231 |
info('invalid code'); |
| 33232 |
this.err = true; |
| 33233 |
a1 = 0; |
| 33234 |
} |
| 33235 |
while (codingPos > 0 && a1 < codingLine[codingPos - 1]) { |
| 33236 |
--codingPos; |
| 33237 |
} |
| 33238 |
codingLine[codingPos] = a1; |
| 33239 |
} |
| 33240 |
|
| 33241 |
this.codingPos = codingPos; |
| 33242 |
}; |
| 33243 |
|
| 33244 |
CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() { |
| 33245 |
var refLine = this.refLine; |
| 33246 |
var codingLine = this.codingLine; |
| 33247 |
var columns = this.columns; |
| 33248 |
|
| 33249 |
var refPos, blackPixels, bits, i; |
| 33250 |
|
| 33251 |
if (this.outputBits === 0) { |
| 33252 |
if (this.eof) { |
| 33253 |
return null; |
| 33254 |
} |
| 33255 |
this.err = false; |
| 33256 |
|
| 33257 |
var code1, code2, code3; |
| 33258 |
if (this.nextLine2D) { |
| 33259 |
for (i = 0; codingLine[i] < columns; ++i) { |
| 33260 |
refLine[i] = codingLine[i]; |
| 33261 |
} |
| 33262 |
refLine[i++] = columns; |
| 33263 |
refLine[i] = columns; |
| 33264 |
codingLine[0] = 0; |
| 33265 |
this.codingPos = 0; |
| 33266 |
refPos = 0; |
| 33267 |
blackPixels = 0; |
| 33268 |
|
| 33269 |
while (codingLine[this.codingPos] < columns) { |
| 33270 |
code1 = this.getTwoDimCode(); |
| 33271 |
switch (code1) { |
| 33272 |
case twoDimPass: |
| 33273 |
this.addPixels(refLine[refPos + 1], blackPixels); |
| 33274 |
if (refLine[refPos + 1] < columns) { |
| 33275 |
refPos += 2; |
| 33276 |
} |
| 33277 |
break; |
| 33278 |
case twoDimHoriz: |
| 33279 |
code1 = code2 = 0; |
| 33280 |
if (blackPixels) { |
| 33281 |
do { |
| 33282 |
code1 += (code3 = this.getBlackCode()); |
| 33283 |
} while (code3 >= 64); |
| 33284 |
do { |
| 33285 |
code2 += (code3 = this.getWhiteCode()); |
| 33286 |
} while (code3 >= 64); |
| 33287 |
} else { |
| 33288 |
do { |
| 33289 |
code1 += (code3 = this.getWhiteCode()); |
| 33290 |
} while (code3 >= 64); |
| 33291 |
do { |
| 33292 |
code2 += (code3 = this.getBlackCode()); |
| 33293 |
} while (code3 >= 64); |
| 33294 |
} |
| 33295 |
this.addPixels(codingLine[this.codingPos] + |
| 33296 |
code1, blackPixels); |
| 33297 |
if (codingLine[this.codingPos] < columns) { |
| 33298 |
this.addPixels(codingLine[this.codingPos] + code2, |
| 33299 |
blackPixels ^ 1); |
| 33300 |
} |
| 33301 |
while (refLine[refPos] <= codingLine[this.codingPos] && |
| 33302 |
refLine[refPos] < columns) { |
| 33303 |
refPos += 2; |
| 33304 |
} |
| 33305 |
break; |
| 33306 |
case twoDimVertR3: |
| 33307 |
this.addPixels(refLine[refPos] + 3, blackPixels); |
| 33308 |
blackPixels ^= 1; |
| 33309 |
if (codingLine[this.codingPos] < columns) { |
| 33310 |
++refPos; |
| 33311 |
while (refLine[refPos] <= codingLine[this.codingPos] && |
| 33312 |
refLine[refPos] < columns) { |
| 33313 |
refPos += 2; |
| 33314 |
} |
| 33315 |
} |
| 33316 |
break; |
| 33317 |
case twoDimVertR2: |
| 33318 |
this.addPixels(refLine[refPos] + 2, blackPixels); |
| 33319 |
blackPixels ^= 1; |
| 33320 |
if (codingLine[this.codingPos] < columns) { |
| 33321 |
++refPos; |
| 33322 |
while (refLine[refPos] <= codingLine[this.codingPos] && |
| 33323 |
refLine[refPos] < columns) { |
| 33324 |
refPos += 2; |
| 33325 |
} |
| 33326 |
} |
| 33327 |
break; |
| 33328 |
case twoDimVertR1: |
| 33329 |
this.addPixels(refLine[refPos] + 1, blackPixels); |
| 33330 |
blackPixels ^= 1; |
| 33331 |
if (codingLine[this.codingPos] < columns) { |
| 33332 |
++refPos; |
| 33333 |
while (refLine[refPos] <= codingLine[this.codingPos] && |
| 33334 |
refLine[refPos] < columns) { |
| 33335 |
refPos += 2; |
| 33336 |
} |
| 33337 |
} |
| 33338 |
break; |
| 33339 |
case twoDimVert0: |
| 33340 |
this.addPixels(refLine[refPos], blackPixels); |
| 33341 |
blackPixels ^= 1; |
| 33342 |
if (codingLine[this.codingPos] < columns) { |
| 33343 |
++refPos; |
| 33344 |
while (refLine[refPos] <= codingLine[this.codingPos] && |
| 33345 |
refLine[refPos] < columns) { |
| 33346 |
refPos += 2; |
| 33347 |
} |
| 33348 |
} |
| 33349 |
break; |
| 33350 |
case twoDimVertL3: |
| 33351 |
this.addPixelsNeg(refLine[refPos] - 3, blackPixels); |
| 33352 |
blackPixels ^= 1; |
| 33353 |
if (codingLine[this.codingPos] < columns) { |
| 33354 |
if (refPos > 0) { |
| 33355 |
--refPos; |
| 33356 |
} else { |
| 33357 |
++refPos; |
| 33358 |
} |
| 33359 |
while (refLine[refPos] <= codingLine[this.codingPos] && |
| 33360 |
refLine[refPos] < columns) { |
| 33361 |
refPos += 2; |
| 33362 |
} |
| 33363 |
} |
| 33364 |
break; |
| 33365 |
case twoDimVertL2: |
| 33366 |
this.addPixelsNeg(refLine[refPos] - 2, blackPixels); |
| 33367 |
blackPixels ^= 1; |
| 33368 |
if (codingLine[this.codingPos] < columns) { |
| 33369 |
if (refPos > 0) { |
| 33370 |
--refPos; |
| 33371 |
} else { |
| 33372 |
++refPos; |
| 33373 |
} |
| 33374 |
while (refLine[refPos] <= codingLine[this.codingPos] && |
| 33375 |
refLine[refPos] < columns) { |
| 33376 |
refPos += 2; |
| 33377 |
} |
| 33378 |
} |
| 33379 |
break; |
| 33380 |
case twoDimVertL1: |
| 33381 |
this.addPixelsNeg(refLine[refPos] - 1, blackPixels); |
| 33382 |
blackPixels ^= 1; |
| 33383 |
if (codingLine[this.codingPos] < columns) { |
| 33384 |
if (refPos > 0) { |
| 33385 |
--refPos; |
| 33386 |
} else { |
| 33387 |
++refPos; |
| 33388 |
} |
| 33389 |
while (refLine[refPos] <= codingLine[this.codingPos] && |
| 33390 |
refLine[refPos] < columns) { |
| 33391 |
refPos += 2; |
| 33392 |
} |
| 33393 |
} |
| 33394 |
break; |
| 33395 |
case EOF: |
| 33396 |
this.addPixels(columns, 0); |
| 33397 |
this.eof = true; |
| 33398 |
break; |
| 33399 |
default: |
| 33400 |
info('bad 2d code'); |
| 33401 |
this.addPixels(columns, 0); |
| 33402 |
this.err = true; |
| 33403 |
} |
| 33404 |
} |
| 33405 |
} else { |
| 33406 |
codingLine[0] = 0; |
| 33407 |
this.codingPos = 0; |
| 33408 |
blackPixels = 0; |
| 33409 |
while (codingLine[this.codingPos] < columns) { |
| 33410 |
code1 = 0; |
| 33411 |
if (blackPixels) { |
| 33412 |
do { |
| 33413 |
code1 += (code3 = this.getBlackCode()); |
| 33414 |
} while (code3 >= 64); |
| 33415 |
} else { |
| 33416 |
do { |
| 33417 |
code1 += (code3 = this.getWhiteCode()); |
| 33418 |
} while (code3 >= 64); |
| 33419 |
} |
| 33420 |
this.addPixels(codingLine[this.codingPos] + code1, blackPixels); |
| 33421 |
blackPixels ^= 1; |
| 33422 |
} |
| 33423 |
} |
| 33424 |
|
| 33425 |
var gotEOL = false; |
| 33426 |
|
| 33427 |
if (this.byteAlign) { |
| 33428 |
this.inputBits &= ~7; |
| 33429 |
} |
| 33430 |
|
| 33431 |
if (!this.eoblock && this.row === this.rows - 1) { |
| 33432 |
this.eof = true; |
| 33433 |
} else { |
| 33434 |
code1 = this.lookBits(12); |
| 33435 |
if (this.eoline) { |
| 33436 |
while (code1 !== EOF && code1 !== 1) { |
| 33437 |
this.eatBits(1); |
| 33438 |
code1 = this.lookBits(12); |
| 33439 |
} |
| 33440 |
} else { |
| 33441 |
while (code1 === 0) { |
| 33442 |
this.eatBits(1); |
| 33443 |
code1 = this.lookBits(12); |
| 33444 |
} |
| 33445 |
} |
| 33446 |
if (code1 === 1) { |
| 33447 |
this.eatBits(12); |
| 33448 |
gotEOL = true; |
| 33449 |
} else if (code1 === EOF) { |
| 33450 |
this.eof = true; |
| 33451 |
} |
| 33452 |
} |
| 33453 |
|
| 33454 |
if (!this.eof && this.encoding > 0) { |
| 33455 |
this.nextLine2D = !this.lookBits(1); |
| 33456 |
this.eatBits(1); |
| 33457 |
} |
| 33458 |
|
| 33459 |
if (this.eoblock && gotEOL && this.byteAlign) { |
| 33460 |
code1 = this.lookBits(12); |
| 33461 |
if (code1 === 1) { |
| 33462 |
this.eatBits(12); |
| 33463 |
if (this.encoding > 0) { |
| 33464 |
this.lookBits(1); |
| 33465 |
this.eatBits(1); |
| 33466 |
} |
| 33467 |
if (this.encoding >= 0) { |
| 33468 |
for (i = 0; i < 4; ++i) { |
| 33469 |
code1 = this.lookBits(12); |
| 33470 |
if (code1 !== 1) { |
| 33471 |
info('bad rtc code: ' + code1); |
| 33472 |
} |
| 33473 |
this.eatBits(12); |
| 33474 |
if (this.encoding > 0) { |
| 33475 |
this.lookBits(1); |
| 33476 |
this.eatBits(1); |
| 33477 |
} |
| 33478 |
} |
| 33479 |
} |
| 33480 |
this.eof = true; |
| 33481 |
} |
| 33482 |
} else if (this.err && this.eoline) { |
| 33483 |
while (true) { |
| 33484 |
code1 = this.lookBits(13); |
| 33485 |
if (code1 === EOF) { |
| 33486 |
this.eof = true; |
| 33487 |
return null; |
| 33488 |
} |
| 33489 |
if ((code1 >> 1) === 1) { |
| 33490 |
break; |
| 33491 |
} |
| 33492 |
this.eatBits(1); |
| 33493 |
} |
| 33494 |
this.eatBits(12); |
| 33495 |
if (this.encoding > 0) { |
| 33496 |
this.eatBits(1); |
| 33497 |
this.nextLine2D = !(code1 & 1); |
| 33498 |
} |
| 33499 |
} |
| 33500 |
|
| 33501 |
if (codingLine[0] > 0) { |
| 33502 |
this.outputBits = codingLine[this.codingPos = 0]; |
| 33503 |
} else { |
| 33504 |
this.outputBits = codingLine[this.codingPos = 1]; |
| 33505 |
} |
| 33506 |
this.row++; |
| 33507 |
} |
| 33508 |
|
| 33509 |
var c; |
| 33510 |
if (this.outputBits >= 8) { |
| 33511 |
c = (this.codingPos & 1) ? 0 : 0xFF; |
| 33512 |
this.outputBits -= 8; |
| 33513 |
if (this.outputBits === 0 && codingLine[this.codingPos] < columns) { |
| 33514 |
this.codingPos++; |
| 33515 |
this.outputBits = (codingLine[this.codingPos] - |
| 33516 |
codingLine[this.codingPos - 1]); |
| 33517 |
} |
| 33518 |
} else { |
| 33519 |
bits = 8; |
| 33520 |
c = 0; |
| 33521 |
do { |
| 33522 |
if (this.outputBits > bits) { |
| 33523 |
c <<= bits; |
| 33524 |
if (!(this.codingPos & 1)) { |
| 33525 |
c |= 0xFF >> (8 - bits); |
| 33526 |
} |
| 33527 |
this.outputBits -= bits; |
| 33528 |
bits = 0; |
| 33529 |
} else { |
| 33530 |
c <<= this.outputBits; |
| 33531 |
if (!(this.codingPos & 1)) { |
| 33532 |
c |= 0xFF >> (8 - this.outputBits); |
| 33533 |
} |
| 33534 |
bits -= this.outputBits; |
| 33535 |
this.outputBits = 0; |
| 33536 |
if (codingLine[this.codingPos] < columns) { |
| 33537 |
this.codingPos++; |
| 33538 |
this.outputBits = (codingLine[this.codingPos] - |
| 33539 |
codingLine[this.codingPos - 1]); |
| 33540 |
} else if (bits > 0) { |
| 33541 |
c <<= bits; |
| 33542 |
bits = 0; |
| 33543 |
} |
| 33544 |
} |
| 33545 |
} while (bits); |
| 33546 |
} |
| 33547 |
if (this.black) { |
| 33548 |
c ^= 0xFF; |
| 33549 |
} |
| 33550 |
return c; |
| 33551 |
}; |
| 33552 |
|
| 33553 |
// This functions returns the code found from the table. |
| 33554 |
// The start and end parameters set the boundaries for searching the table. |
| 33555 |
// The limit parameter is optional. Function returns an array with three |
| 33556 |
// values. The first array element indicates whether a valid code is being |
| 33557 |
// returned. The second array element is the actual code. The third array |
| 33558 |
// element indicates whether EOF was reached. |
| 33559 |
CCITTFaxStream.prototype.findTableCode = |
| 33560 |
function ccittFaxStreamFindTableCode(start, end, table, limit) { |
| 33561 |
|
| 33562 |
var limitValue = limit || 0; |
| 33563 |
for (var i = start; i <= end; ++i) { |
| 33564 |
var code = this.lookBits(i); |
| 33565 |
if (code === EOF) { |
| 33566 |
return [true, 1, false]; |
| 33567 |
} |
| 33568 |
if (i < end) { |
| 33569 |
code <<= end - i; |
| 33570 |
} |
| 33571 |
if (!limitValue || code >= limitValue) { |
| 33572 |
var p = table[code - limitValue]; |
| 33573 |
if (p[0] === i) { |
| 33574 |
this.eatBits(i); |
| 33575 |
return [true, p[1], true]; |
| 33576 |
} |
| 33577 |
} |
| 33578 |
} |
| 33579 |
return [false, 0, false]; |
| 33580 |
}; |
| 33581 |
|
| 33582 |
CCITTFaxStream.prototype.getTwoDimCode = |
| 33583 |
function ccittFaxStreamGetTwoDimCode() { |
| 33584 |
|
| 33585 |
var code = 0; |
| 33586 |
var p; |
| 33587 |
if (this.eoblock) { |
| 33588 |
code = this.lookBits(7); |
| 33589 |
p = twoDimTable[code]; |
| 33590 |
if (p && p[0] > 0) { |
| 33591 |
this.eatBits(p[0]); |
| 33592 |
return p[1]; |
| 33593 |
} |
| 33594 |
} else { |
| 33595 |
var result = this.findTableCode(1, 7, twoDimTable); |
| 33596 |
if (result[0] && result[2]) { |
| 33597 |
return result[1]; |
| 33598 |
} |
| 33599 |
} |
| 33600 |
info('Bad two dim code'); |
| 33601 |
return EOF; |
| 33602 |
}; |
| 33603 |
|
| 33604 |
CCITTFaxStream.prototype.getWhiteCode = |
| 33605 |
function ccittFaxStreamGetWhiteCode() { |
| 33606 |
|
| 33607 |
var code = 0; |
| 33608 |
var p; |
| 33609 |
if (this.eoblock) { |
| 33610 |
code = this.lookBits(12); |
| 33611 |
if (code === EOF) { |
| 33612 |
return 1; |
| 33613 |
} |
| 33614 |
|
| 33615 |
if ((code >> 5) === 0) { |
| 33616 |
p = whiteTable1[code]; |
| 33617 |
} else { |
| 33618 |
p = whiteTable2[code >> 3]; |
| 33619 |
} |
| 33620 |
|
| 33621 |
if (p[0] > 0) { |
| 33622 |
this.eatBits(p[0]); |
| 33623 |
return p[1]; |
| 33624 |
} |
| 33625 |
} else { |
| 33626 |
var result = this.findTableCode(1, 9, whiteTable2); |
| 33627 |
if (result[0]) { |
| 33628 |
return result[1]; |
| 33629 |
} |
| 33630 |
|
| 33631 |
result = this.findTableCode(11, 12, whiteTable1); |
| 33632 |
if (result[0]) { |
| 33633 |
return result[1]; |
| 33634 |
} |
| 33635 |
} |
| 33636 |
info('bad white code'); |
| 33637 |
this.eatBits(1); |
| 33638 |
return 1; |
| 33639 |
}; |
| 33640 |
|
| 33641 |
CCITTFaxStream.prototype.getBlackCode = |
| 33642 |
function ccittFaxStreamGetBlackCode() { |
| 33643 |
|
| 33644 |
var code, p; |
| 33645 |
if (this.eoblock) { |
| 33646 |
code = this.lookBits(13); |
| 33647 |
if (code === EOF) { |
| 33648 |
return 1; |
| 33649 |
} |
| 33650 |
if ((code >> 7) === 0) { |
| 33651 |
p = blackTable1[code]; |
| 33652 |
} else if ((code >> 9) === 0 && (code >> 7) !== 0) { |
| 33653 |
p = blackTable2[(code >> 1) - 64]; |
| 33654 |
} else { |
| 33655 |
p = blackTable3[code >> 7]; |
| 33656 |
} |
| 33657 |
|
| 33658 |
if (p[0] > 0) { |
| 33659 |
this.eatBits(p[0]); |
| 33660 |
return p[1]; |
| 33661 |
} |
| 33662 |
} else { |
| 33663 |
var result = this.findTableCode(2, 6, blackTable3); |
| 33664 |
if (result[0]) { |
| 33665 |
return result[1]; |
| 33666 |
} |
| 33667 |
|
| 33668 |
result = this.findTableCode(7, 12, blackTable2, 64); |
| 33669 |
if (result[0]) { |
| 33670 |
return result[1]; |
| 33671 |
} |
| 33672 |
|
| 33673 |
result = this.findTableCode(10, 13, blackTable1); |
| 33674 |
if (result[0]) { |
| 33675 |
return result[1]; |
| 33676 |
} |
| 33677 |
} |
| 33678 |
info('bad black code'); |
| 33679 |
this.eatBits(1); |
| 33680 |
return 1; |
| 33681 |
}; |
| 33682 |
|
| 33683 |
CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) { |
| 33684 |
var c; |
| 33685 |
while (this.inputBits < n) { |
| 33686 |
if ((c = this.str.getByte()) === -1) { |
| 33687 |
if (this.inputBits === 0) { |
| 33688 |
return EOF; |
| 33689 |
} |
| 33690 |
return ((this.inputBuf << (n - this.inputBits)) & |
| 33691 |
(0xFFFF >> (16 - n))); |
| 33692 |
} |
| 33693 |
this.inputBuf = (this.inputBuf << 8) + c; |
| 33694 |
this.inputBits += 8; |
| 33695 |
} |
| 33696 |
return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n)); |
| 33697 |
}; |
| 33698 |
|
| 33699 |
CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) { |
| 33700 |
if ((this.inputBits -= n) < 0) { |
| 33701 |
this.inputBits = 0; |
| 33702 |
} |
| 33703 |
}; |
| 33704 |
|
| 33705 |
return CCITTFaxStream; |
| 33706 |
})(); |
| 33707 |
|
| 33708 |
var LZWStream = (function LZWStreamClosure() { |
| 33709 |
function LZWStream(str, maybeLength, earlyChange) { |
| 33710 |
this.str = str; |
| 33711 |
this.dict = str.dict; |
| 33712 |
this.cachedData = 0; |
| 33713 |
this.bitsCached = 0; |
| 33714 |
|
| 33715 |
var maxLzwDictionarySize = 4096; |
| 33716 |
var lzwState = { |
| 33717 |
earlyChange: earlyChange, |
| 33718 |
codeLength: 9, |
| 33719 |
nextCode: 258, |
| 33720 |
dictionaryValues: new Uint8Array(maxLzwDictionarySize), |
| 33721 |
dictionaryLengths: new Uint16Array(maxLzwDictionarySize), |
| 33722 |
dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), |
| 33723 |
currentSequence: new Uint8Array(maxLzwDictionarySize), |
| 33724 |
currentSequenceLength: 0 |
| 33725 |
}; |
| 33726 |
for (var i = 0; i < 256; ++i) { |
| 33727 |
lzwState.dictionaryValues[i] = i; |
| 33728 |
lzwState.dictionaryLengths[i] = 1; |
| 33729 |
} |
| 33730 |
this.lzwState = lzwState; |
| 33731 |
|
| 33732 |
DecodeStream.call(this, maybeLength); |
| 33733 |
} |
| 33734 |
|
| 33735 |
LZWStream.prototype = Object.create(DecodeStream.prototype); |
| 33736 |
|
| 33737 |
LZWStream.prototype.readBits = function LZWStream_readBits(n) { |
| 33738 |
var bitsCached = this.bitsCached; |
| 33739 |
var cachedData = this.cachedData; |
| 33740 |
while (bitsCached < n) { |
| 33741 |
var c = this.str.getByte(); |
| 33742 |
if (c === -1) { |
| 33743 |
this.eof = true; |
| 33744 |
return null; |
| 33745 |
} |
| 33746 |
cachedData = (cachedData << 8) | c; |
| 33747 |
bitsCached += 8; |
| 33748 |
} |
| 33749 |
this.bitsCached = (bitsCached -= n); |
| 33750 |
this.cachedData = cachedData; |
| 33751 |
this.lastCode = null; |
| 33752 |
return (cachedData >>> bitsCached) & ((1 << n) - 1); |
| 33753 |
}; |
| 33754 |
|
| 33755 |
LZWStream.prototype.readBlock = function LZWStream_readBlock() { |
| 33756 |
var blockSize = 512; |
| 33757 |
var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize; |
| 33758 |
var i, j, q; |
| 33759 |
|
| 33760 |
var lzwState = this.lzwState; |
| 33761 |
if (!lzwState) { |
| 33762 |
return; // eof was found |
| 33763 |
} |
| 33764 |
|
| 33765 |
var earlyChange = lzwState.earlyChange; |
| 33766 |
var nextCode = lzwState.nextCode; |
| 33767 |
var dictionaryValues = lzwState.dictionaryValues; |
| 33768 |
var dictionaryLengths = lzwState.dictionaryLengths; |
| 33769 |
var dictionaryPrevCodes = lzwState.dictionaryPrevCodes; |
| 33770 |
var codeLength = lzwState.codeLength; |
| 33771 |
var prevCode = lzwState.prevCode; |
| 33772 |
var currentSequence = lzwState.currentSequence; |
| 33773 |
var currentSequenceLength = lzwState.currentSequenceLength; |
| 33774 |
|
| 33775 |
var decodedLength = 0; |
| 33776 |
var currentBufferLength = this.bufferLength; |
| 33777 |
var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); |
| 33778 |
|
| 33779 |
for (i = 0; i < blockSize; i++) { |
| 33780 |
var code = this.readBits(codeLength); |
| 33781 |
var hasPrev = currentSequenceLength > 0; |
| 33782 |
if (code < 256) { |
| 33783 |
currentSequence[0] = code; |
| 33784 |
currentSequenceLength = 1; |
| 33785 |
} else if (code >= 258) { |
| 33786 |
if (code < nextCode) { |
| 33787 |
currentSequenceLength = dictionaryLengths[code]; |
| 33788 |
for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { |
| 33789 |
currentSequence[j] = dictionaryValues[q]; |
| 33790 |
q = dictionaryPrevCodes[q]; |
| 33791 |
} |
| 33792 |
} else { |
| 33793 |
currentSequence[currentSequenceLength++] = currentSequence[0]; |
| 33794 |
} |
| 33795 |
} else if (code === 256) { |
| 33796 |
codeLength = 9; |
| 33797 |
nextCode = 258; |
| 33798 |
currentSequenceLength = 0; |
| 33799 |
continue; |
| 33800 |
} else { |
| 33801 |
this.eof = true; |
| 33802 |
delete this.lzwState; |
| 33803 |
break; |
| 33804 |
} |
| 33805 |
|
| 33806 |
if (hasPrev) { |
| 33807 |
dictionaryPrevCodes[nextCode] = prevCode; |
| 33808 |
dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; |
| 33809 |
dictionaryValues[nextCode] = currentSequence[0]; |
| 33810 |
nextCode++; |
| 33811 |
codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ? |
| 33812 |
codeLength : Math.min(Math.log(nextCode + earlyChange) / |
| 33813 |
0.6931471805599453 + 1, 12) | 0; |
| 33814 |
} |
| 33815 |
prevCode = code; |
| 33816 |
|
| 33817 |
decodedLength += currentSequenceLength; |
| 33818 |
if (estimatedDecodedSize < decodedLength) { |
| 33819 |
do { |
| 33820 |
estimatedDecodedSize += decodedSizeDelta; |
| 33821 |
} while (estimatedDecodedSize < decodedLength); |
| 33822 |
buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); |
| 33823 |
} |
| 33824 |
for (j = 0; j < currentSequenceLength; j++) { |
| 33825 |
buffer[currentBufferLength++] = currentSequence[j]; |
| 33826 |
} |
| 33827 |
} |
| 33828 |
lzwState.nextCode = nextCode; |
| 33829 |
lzwState.codeLength = codeLength; |
| 33830 |
lzwState.prevCode = prevCode; |
| 33831 |
lzwState.currentSequenceLength = currentSequenceLength; |
| 33832 |
|
| 33833 |
this.bufferLength = currentBufferLength; |
| 33834 |
}; |
| 33835 |
|
| 33836 |
return LZWStream; |
| 33837 |
})(); |
| 33838 |
|
| 33839 |
var NullStream = (function NullStreamClosure() { |
| 33840 |
function NullStream() { |
| 33841 |
Stream.call(this, new Uint8Array(0)); |
| 33842 |
} |
| 33843 |
|
| 33844 |
NullStream.prototype = Stream.prototype; |
| 33845 |
|
| 33846 |
return NullStream; |
| 33847 |
})(); |
| 33848 |
|
| 33849 |
|
| 33850 |
var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { |
| 33851 |
setup: function wphSetup(handler) { |
| 33852 |
var pdfManager; |
| 33853 |
|
| 33854 |
function loadDocument(recoveryMode) { |
| 33855 |
var loadDocumentCapability = createPromiseCapability(); |
| 33856 |
|
| 33857 |
var parseSuccess = function parseSuccess() { |
| 33858 |
var numPagesPromise = pdfManager.ensureDoc('numPages'); |
| 33859 |
var fingerprintPromise = pdfManager.ensureDoc('fingerprint'); |
| 33860 |
var encryptedPromise = pdfManager.ensureXRef('encrypt'); |
| 33861 |
Promise.all([numPagesPromise, fingerprintPromise, |
| 33862 |
encryptedPromise]).then(function onDocReady(results) { |
| 33863 |
var doc = { |
| 33864 |
numPages: results[0], |
| 33865 |
fingerprint: results[1], |
| 33866 |
encrypted: !!results[2], |
| 33867 |
}; |
| 33868 |
loadDocumentCapability.resolve(doc); |
| 33869 |
}, |
| 33870 |
parseFailure); |
| 33871 |
}; |
| 33872 |
|
| 33873 |
var parseFailure = function parseFailure(e) { |
| 33874 |
loadDocumentCapability.reject(e); |
| 33875 |
}; |
| 33876 |
|
| 33877 |
pdfManager.ensureDoc('checkHeader', []).then(function() { |
| 33878 |
pdfManager.ensureDoc('parseStartXRef', []).then(function() { |
| 33879 |
pdfManager.ensureDoc('parse', [recoveryMode]).then( |
| 33880 |
parseSuccess, parseFailure); |
| 33881 |
}, parseFailure); |
| 33882 |
}, parseFailure); |
| 33883 |
|
| 33884 |
return loadDocumentCapability.promise; |
| 33885 |
} |
| 33886 |
|
| 33887 |
function getPdfManager(data) { |
| 33888 |
var pdfManagerCapability = createPromiseCapability(); |
| 33889 |
|
| 33890 |
var source = data.source; |
| 33891 |
var disableRange = data.disableRange; |
| 33892 |
if (source.data) { |
| 33893 |
try { |
| 33894 |
pdfManager = new LocalPdfManager(source.data, source.password); |
| 33895 |
pdfManagerCapability.resolve(); |
| 33896 |
} catch (ex) { |
| 33897 |
pdfManagerCapability.reject(ex); |
| 33898 |
} |
| 33899 |
return pdfManagerCapability.promise; |
| 33900 |
} else if (source.chunkedViewerLoading) { |
| 33901 |
try { |
| 33902 |
pdfManager = new NetworkPdfManager(source, handler); |
| 33903 |
pdfManagerCapability.resolve(); |
| 33904 |
} catch (ex) { |
| 33905 |
pdfManagerCapability.reject(ex); |
| 33906 |
} |
| 33907 |
return pdfManagerCapability.promise; |
| 33908 |
} |
| 33909 |
|
| 33910 |
var networkManager = new NetworkManager(source.url, { |
| 33911 |
httpHeaders: source.httpHeaders, |
| 33912 |
withCredentials: source.withCredentials |
| 33913 |
}); |
| 33914 |
var cachedChunks = []; |
| 33915 |
var fullRequestXhrId = networkManager.requestFull({ |
| 33916 |
onHeadersReceived: function onHeadersReceived() { |
| 33917 |
if (disableRange) { |
| 33918 |
return; |
| 33919 |
} |
| 33920 |
|
| 33921 |
var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId); |
| 33922 |
if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') { |
| 33923 |
return; |
| 33924 |
} |
| 33925 |
|
| 33926 |
var contentEncoding = |
| 33927 |
fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity'; |
| 33928 |
if (contentEncoding !== 'identity') { |
| 33929 |
return; |
| 33930 |
} |
| 33931 |
|
| 33932 |
var length = fullRequestXhr.getResponseHeader('Content-Length'); |
| 33933 |
length = parseInt(length, 10); |
| 33934 |
if (!isInt(length)) { |
| 33935 |
return; |
| 33936 |
} |
| 33937 |
source.length = length; |
| 33938 |
if (length <= 2 * RANGE_CHUNK_SIZE) { |
| 33939 |
// The file size is smaller than the size of two chunks, so it does |
| 33940 |
// not make any sense to abort the request and retry with a range |
| 33941 |
// request. |
| 33942 |
return; |
| 33943 |
} |
| 33944 |
|
| 33945 |
if (networkManager.isStreamingRequest(fullRequestXhrId)) { |
| 33946 |
// We can continue fetching when progressive loading is enabled, |
| 33947 |
// and we don't need the autoFetch feature. |
| 33948 |
source.disableAutoFetch = true; |
| 33949 |
} else { |
| 33950 |
// NOTE: by cancelling the full request, and then issuing range |
| 33951 |
// requests, there will be an issue for sites where you can only |
| 33952 |
// request the pdf once. However, if this is the case, then the |
| 33953 |
// server should not be returning that it can support range |
| 33954 |
// requests. |
| 33955 |
networkManager.abortRequest(fullRequestXhrId); |
| 33956 |
} |
| 33957 |
|
| 33958 |
try { |
| 33959 |
pdfManager = new NetworkPdfManager(source, handler); |
| 33960 |
pdfManagerCapability.resolve(pdfManager); |
| 33961 |
} catch (ex) { |
| 33962 |
pdfManagerCapability.reject(ex); |
| 33963 |
} |
| 33964 |
}, |
| 33965 |
|
| 33966 |
onProgressiveData: source.disableStream ? null : |
| 33967 |
function onProgressiveData(chunk) { |
| 33968 |
if (!pdfManager) { |
| 33969 |
cachedChunks.push(chunk); |
| 33970 |
return; |
| 33971 |
} |
| 33972 |
pdfManager.sendProgressiveData(chunk); |
| 33973 |
}, |
| 33974 |
|
| 33975 |
onDone: function onDone(args) { |
| 33976 |
if (pdfManager) { |
| 33977 |
return; // already processed |
| 33978 |
} |
| 33979 |
|
| 33980 |
var pdfFile; |
| 33981 |
if (args === null) { |
| 33982 |
// TODO add some streaming manager, e.g. for unknown length files. |
| 33983 |
// The data was returned in the onProgressiveData, combining... |
| 33984 |
var pdfFileLength = 0, pos = 0; |
| 33985 |
cachedChunks.forEach(function (chunk) { |
| 33986 |
pdfFileLength += chunk.byteLength; |
| 33987 |
}); |
| 33988 |
if (source.length && pdfFileLength !== source.length) { |
| 33989 |
warn('reported HTTP length is different from actual'); |
| 33990 |
} |
| 33991 |
var pdfFileArray = new Uint8Array(pdfFileLength); |
| 33992 |
cachedChunks.forEach(function (chunk) { |
| 33993 |
pdfFileArray.set(new Uint8Array(chunk), pos); |
| 33994 |
pos += chunk.byteLength; |
| 33995 |
}); |
| 33996 |
pdfFile = pdfFileArray.buffer; |
| 33997 |
} else { |
| 33998 |
pdfFile = args.chunk; |
| 33999 |
} |
| 34000 |
|
| 34001 |
// the data is array, instantiating directly from it |
| 34002 |
try { |
| 34003 |
pdfManager = new LocalPdfManager(pdfFile, source.password); |
| 34004 |
pdfManagerCapability.resolve(); |
| 34005 |
} catch (ex) { |
| 34006 |
pdfManagerCapability.reject(ex); |
| 34007 |
} |
| 34008 |
}, |
| 34009 |
|
| 34010 |
onError: function onError(status) { |
| 34011 |
var exception; |
| 34012 |
if (status === 404) { |
| 34013 |
exception = new MissingPDFException('Missing PDF "' + |
| 34014 |
source.url + '".'); |
| 34015 |
handler.send('MissingPDF', exception); |
| 34016 |
} else { |
| 34017 |
exception = new UnexpectedResponseException( |
| 34018 |
'Unexpected server response (' + status + |
| 34019 |
') while retrieving PDF "' + source.url + '".', status); |
| 34020 |
handler.send('UnexpectedResponse', exception); |
| 34021 |
} |
| 34022 |
}, |
| 34023 |
|
| 34024 |
onProgress: function onProgress(evt) { |
| 34025 |
handler.send('DocProgress', { |
| 34026 |
loaded: evt.loaded, |
| 34027 |
total: evt.lengthComputable ? evt.total : source.length |
| 34028 |
}); |
| 34029 |
} |
| 34030 |
}); |
| 34031 |
|
| 34032 |
return pdfManagerCapability.promise; |
| 34033 |
} |
| 34034 |
|
| 34035 |
handler.on('test', function wphSetupTest(data) { |
| 34036 |
// check if Uint8Array can be sent to worker |
| 34037 |
if (!(data instanceof Uint8Array)) { |
| 34038 |
handler.send('test', false); |
| 34039 |
return; |
| 34040 |
} |
| 34041 |
// making sure postMessage transfers are working |
| 34042 |
var supportTransfers = data[0] === 255; |
| 34043 |
handler.postMessageTransfers = supportTransfers; |
| 34044 |
// check if the response property is supported by xhr |
| 34045 |
var xhr = new XMLHttpRequest(); |
| 34046 |
var responseExists = 'response' in xhr; |
| 34047 |
// check if the property is actually implemented |
| 34048 |
try { |
| 34049 |
var dummy = xhr.responseType; |
| 34050 |
} catch (e) { |
| 34051 |
responseExists = false; |
| 34052 |
} |
| 34053 |
if (!responseExists) { |
| 34054 |
handler.send('test', false); |
| 34055 |
return; |
| 34056 |
} |
| 34057 |
handler.send('test', { |
| 34058 |
supportTypedArray: true, |
| 34059 |
supportTransfers: supportTransfers |
| 34060 |
}); |
| 34061 |
}); |
| 34062 |
|
| 34063 |
handler.on('GetDocRequest', function wphSetupDoc(data) { |
| 34064 |
|
| 34065 |
var onSuccess = function(doc) { |
| 34066 |
handler.send('GetDoc', { pdfInfo: doc }); |
| 34067 |
}; |
| 34068 |
|
| 34069 |
var onFailure = function(e) { |
| 34070 |
if (e instanceof PasswordException) { |
| 34071 |
if (e.code === PasswordResponses.NEED_PASSWORD) { |
| 34072 |
handler.send('NeedPassword', e); |
| 34073 |
} else if (e.code === PasswordResponses.INCORRECT_PASSWORD) { |
| 34074 |
handler.send('IncorrectPassword', e); |
| 34075 |
} |
| 34076 |
} else if (e instanceof InvalidPDFException) { |
| 34077 |
handler.send('InvalidPDF', e); |
| 34078 |
} else if (e instanceof MissingPDFException) { |
| 34079 |
handler.send('MissingPDF', e); |
| 34080 |
} else if (e instanceof UnexpectedResponseException) { |
| 34081 |
handler.send('UnexpectedResponse', e); |
| 34082 |
} else { |
| 34083 |
handler.send('UnknownError', |
| 34084 |
new UnknownErrorException(e.message, e.toString())); |
| 34085 |
} |
| 34086 |
}; |
| 34087 |
|
| 34088 |
PDFJS.maxImageSize = data.maxImageSize === undefined ? |
| 34089 |
-1 : data.maxImageSize; |
| 34090 |
PDFJS.disableFontFace = data.disableFontFace; |
| 34091 |
PDFJS.disableCreateObjectURL = data.disableCreateObjectURL; |
| 34092 |
PDFJS.verbosity = data.verbosity; |
| 34093 |
PDFJS.cMapUrl = data.cMapUrl === undefined ? |
| 34094 |
null : data.cMapUrl; |
| 34095 |
PDFJS.cMapPacked = data.cMapPacked === true; |
| 34096 |
|
| 34097 |
getPdfManager(data).then(function () { |
| 34098 |
handler.send('PDFManagerReady', null); |
| 34099 |
pdfManager.onLoadedStream().then(function(stream) { |
| 34100 |
handler.send('DataLoaded', { length: stream.bytes.byteLength }); |
| 34101 |
}); |
| 34102 |
}).then(function pdfManagerReady() { |
| 34103 |
loadDocument(false).then(onSuccess, function loadFailure(ex) { |
| 34104 |
// Try again with recoveryMode == true |
| 34105 |
if (!(ex instanceof XRefParseException)) { |
| 34106 |
if (ex instanceof PasswordException) { |
| 34107 |
// after password exception prepare to receive a new password |
| 34108 |
// to repeat loading |
| 34109 |
pdfManager.passwordChanged().then(pdfManagerReady); |
| 34110 |
} |
| 34111 |
|
| 34112 |
onFailure(ex); |
| 34113 |
return; |
| 34114 |
} |
| 34115 |
|
| 34116 |
pdfManager.requestLoadedStream(); |
| 34117 |
pdfManager.onLoadedStream().then(function() { |
| 34118 |
loadDocument(true).then(onSuccess, onFailure); |
| 34119 |
}); |
| 34120 |
}, onFailure); |
| 34121 |
}, onFailure); |
| 34122 |
}); |
| 34123 |
|
| 34124 |
handler.on('GetPage', function wphSetupGetPage(data) { |
| 34125 |
return pdfManager.getPage(data.pageIndex).then(function(page) { |
| 34126 |
var rotatePromise = pdfManager.ensure(page, 'rotate'); |
| 34127 |
var refPromise = pdfManager.ensure(page, 'ref'); |
| 34128 |
var viewPromise = pdfManager.ensure(page, 'view'); |
| 34129 |
|
| 34130 |
return Promise.all([rotatePromise, refPromise, viewPromise]).then( |
| 34131 |
function(results) { |
| 34132 |
return { |
| 34133 |
rotate: results[0], |
| 34134 |
ref: results[1], |
| 34135 |
view: results[2] |
| 34136 |
}; |
| 34137 |
}); |
| 34138 |
}); |
| 34139 |
}); |
| 34140 |
|
| 34141 |
handler.on('GetPageIndex', function wphSetupGetPageIndex(data) { |
| 34142 |
var ref = new Ref(data.ref.num, data.ref.gen); |
| 34143 |
var catalog = pdfManager.pdfDocument.catalog; |
| 34144 |
return catalog.getPageIndex(ref); |
| 34145 |
}); |
| 34146 |
|
| 34147 |
handler.on('GetDestinations', |
| 34148 |
function wphSetupGetDestinations(data) { |
| 34149 |
return pdfManager.ensureCatalog('destinations'); |
| 34150 |
} |
| 34151 |
); |
| 34152 |
|
| 34153 |
handler.on('GetDestination', |
| 34154 |
function wphSetupGetDestination(data) { |
| 34155 |
return pdfManager.ensureCatalog('getDestination', [ data.id ]); |
| 34156 |
} |
| 34157 |
); |
| 34158 |
|
| 34159 |
handler.on('GetAttachments', |
| 34160 |
function wphSetupGetAttachments(data) { |
| 34161 |
return pdfManager.ensureCatalog('attachments'); |
| 34162 |
} |
| 34163 |
); |
| 34164 |
|
| 34165 |
handler.on('GetJavaScript', |
| 34166 |
function wphSetupGetJavaScript(data) { |
| 34167 |
return pdfManager.ensureCatalog('javaScript'); |
| 34168 |
} |
| 34169 |
); |
| 34170 |
|
| 34171 |
handler.on('GetOutline', |
| 34172 |
function wphSetupGetOutline(data) { |
| 34173 |
return pdfManager.ensureCatalog('documentOutline'); |
| 34174 |
} |
| 34175 |
); |
| 34176 |
|
| 34177 |
handler.on('GetMetadata', |
| 34178 |
function wphSetupGetMetadata(data) { |
| 34179 |
return Promise.all([pdfManager.ensureDoc('documentInfo'), |
| 34180 |
pdfManager.ensureCatalog('metadata')]); |
| 34181 |
} |
| 34182 |
); |
| 34183 |
|
| 34184 |
handler.on('GetData', function wphSetupGetData(data) { |
| 34185 |
pdfManager.requestLoadedStream(); |
| 34186 |
return pdfManager.onLoadedStream().then(function(stream) { |
| 34187 |
return stream.bytes; |
| 34188 |
}); |
| 34189 |
}); |
| 34190 |
|
| 34191 |
handler.on('GetStats', |
| 34192 |
function wphSetupGetStats(data) { |
| 34193 |
return pdfManager.pdfDocument.xref.stats; |
| 34194 |
} |
| 34195 |
); |
| 34196 |
|
| 34197 |
handler.on('UpdatePassword', function wphSetupUpdatePassword(data) { |
| 34198 |
pdfManager.updatePassword(data); |
| 34199 |
}); |
| 34200 |
|
| 34201 |
handler.on('GetAnnotations', function wphSetupGetAnnotations(data) { |
| 34202 |
return pdfManager.getPage(data.pageIndex).then(function(page) { |
| 34203 |
return pdfManager.ensure(page, 'getAnnotationsData', []); |
| 34204 |
}); |
| 34205 |
}); |
| 34206 |
|
| 34207 |
handler.on('RenderPageRequest', function wphSetupRenderPage(data) { |
| 34208 |
pdfManager.getPage(data.pageIndex).then(function(page) { |
| 34209 |
|
| 34210 |
var pageNum = data.pageIndex + 1; |
| 34211 |
var start = Date.now(); |
| 34212 |
// Pre compile the pdf page and fetch the fonts/images. |
| 34213 |
page.getOperatorList(handler, data.intent).then(function(operatorList) { |
| 34214 |
|
| 34215 |
info('page=' + pageNum + ' - getOperatorList: time=' + |
| 34216 |
(Date.now() - start) + 'ms, len=' + operatorList.fnArray.length); |
| 34217 |
|
| 34218 |
}, function(e) { |
| 34219 |
|
| 34220 |
var minimumStackMessage = |
| 34221 |
'worker.js: while trying to getPage() and getOperatorList()'; |
| 34222 |
|
| 34223 |
var wrappedException; |
| 34224 |
|
| 34225 |
// Turn the error into an obj that can be serialized |
| 34226 |
if (typeof e === 'string') { |
| 34227 |
wrappedException = { |
| 34228 |
message: e, |
| 34229 |
stack: minimumStackMessage |
| 34230 |
}; |
| 34231 |
} else if (typeof e === 'object') { |
| 34232 |
wrappedException = { |
| 34233 |
message: e.message || e.toString(), |
| 34234 |
stack: e.stack || minimumStackMessage |
| 34235 |
}; |
| 34236 |
} else { |
| 34237 |
wrappedException = { |
| 34238 |
message: 'Unknown exception type: ' + (typeof e), |
| 34239 |
stack: minimumStackMessage |
| 34240 |
}; |
| 34241 |
} |
| 34242 |
|
| 34243 |
handler.send('PageError', { |
| 34244 |
pageNum: pageNum, |
| 34245 |
error: wrappedException, |
| 34246 |
intent: data.intent |
| 34247 |
}); |
| 34248 |
}); |
| 34249 |
}); |
| 34250 |
}, this); |
| 34251 |
|
| 34252 |
handler.on('GetTextContent', function wphExtractText(data) { |
| 34253 |
return pdfManager.getPage(data.pageIndex).then(function(page) { |
| 34254 |
var pageNum = data.pageIndex + 1; |
| 34255 |
var start = Date.now(); |
| 34256 |
return page.extractTextContent().then(function(textContent) { |
| 34257 |
info('text indexing: page=' + pageNum + ' - time=' + |
| 34258 |
(Date.now() - start) + 'ms'); |
| 34259 |
return textContent; |
| 34260 |
}); |
| 34261 |
}); |
| 34262 |
}); |
| 34263 |
|
| 34264 |
handler.on('Cleanup', function wphCleanup(data) { |
| 34265 |
return pdfManager.cleanup(); |
| 34266 |
}); |
| 34267 |
|
| 34268 |
handler.on('Terminate', function wphTerminate(data) { |
| 34269 |
pdfManager.terminate(); |
| 34270 |
}); |
| 34271 |
} |
| 34272 |
}; |
| 34273 |
|
| 34274 |
var consoleTimer = {}; |
| 34275 |
|
| 34276 |
var workerConsole = { |
| 34277 |
log: function log() { |
| 34278 |
var args = Array.prototype.slice.call(arguments); |
| 34279 |
globalScope.postMessage({ |
| 34280 |
action: 'console_log', |
| 34281 |
data: args |
| 34282 |
}); |
| 34283 |
}, |
| 34284 |
|
| 34285 |
error: function error() { |
| 34286 |
var args = Array.prototype.slice.call(arguments); |
| 34287 |
globalScope.postMessage({ |
| 34288 |
action: 'console_error', |
| 34289 |
data: args |
| 34290 |
}); |
| 34291 |
throw 'pdf.js execution error'; |
| 34292 |
}, |
| 34293 |
|
| 34294 |
time: function time(name) { |
| 34295 |
consoleTimer[name] = Date.now(); |
| 34296 |
}, |
| 34297 |
|
| 34298 |
timeEnd: function timeEnd(name) { |
| 34299 |
var time = consoleTimer[name]; |
| 34300 |
if (!time) { |
| 34301 |
error('Unknown timer name ' + name); |
| 34302 |
} |
| 34303 |
this.log('Timer:', name, Date.now() - time); |
| 34304 |
} |
| 34305 |
}; |
| 34306 |
|
| 34307 |
|
| 34308 |
// Worker thread? |
| 34309 |
if (typeof window === 'undefined') { |
| 34310 |
if (!('console' in globalScope)) { |
| 34311 |
globalScope.console = workerConsole; |
| 34312 |
} |
| 34313 |
|
| 34314 |
// Listen for unsupported features so we can pass them on to the main thread. |
| 34315 |
PDFJS.UnsupportedManager.listen(function (msg) { |
| 34316 |
globalScope.postMessage({ |
| 34317 |
action: '_unsupported_feature', |
| 34318 |
data: msg |
| 34319 |
}); |
| 34320 |
}); |
| 34321 |
|
| 34322 |
var handler = new MessageHandler('worker_processor', this); |
| 34323 |
WorkerMessageHandler.setup(handler); |
| 34324 |
} |
| 34325 |
|
| 34326 |
|
| 34327 |
/* This class implements the QM Coder decoding as defined in |
| 34328 |
* JPEG 2000 Part I Final Committee Draft Version 1.0 |
| 34329 |
* Annex C.3 Arithmetic decoding procedure |
| 34330 |
* available at http://www.jpeg.org/public/fcd15444-1.pdf |
| 34331 |
* |
| 34332 |
* The arithmetic decoder is used in conjunction with context models to decode |
| 34333 |
* JPEG2000 and JBIG2 streams. |
| 34334 |
*/ |
| 34335 |
var ArithmeticDecoder = (function ArithmeticDecoderClosure() { |
| 34336 |
// Table C-2 |
| 34337 |
var QeTable = [ |
| 34338 |
{qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1}, |
| 34339 |
{qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0}, |
| 34340 |
{qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0}, |
| 34341 |
{qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0}, |
| 34342 |
{qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0}, |
| 34343 |
{qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0}, |
| 34344 |
{qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1}, |
| 34345 |
{qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0}, |
| 34346 |
{qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0}, |
| 34347 |
{qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0}, |
| 34348 |
{qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0}, |
| 34349 |
{qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0}, |
| 34350 |
{qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0}, |
| 34351 |
{qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0}, |
| 34352 |
{qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1}, |
| 34353 |
{qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0}, |
| 34354 |
{qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0}, |
| 34355 |
{qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0}, |
| 34356 |
{qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0}, |
| 34357 |
{qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0}, |
| 34358 |
{qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0}, |
| 34359 |
{qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0}, |
| 34360 |
{qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0}, |
| 34361 |
{qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0}, |
| 34362 |
{qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0}, |
| 34363 |
{qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0}, |
| 34364 |
{qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0}, |
| 34365 |
{qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0}, |
| 34366 |
{qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0}, |
| 34367 |
{qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0}, |
| 34368 |
{qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0}, |
| 34369 |
{qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0}, |
| 34370 |
{qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0}, |
| 34371 |
{qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0}, |
| 34372 |
{qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0}, |
| 34373 |
{qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0}, |
| 34374 |
{qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0}, |
| 34375 |
{qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0}, |
| 34376 |
{qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0}, |
| 34377 |
{qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0}, |
| 34378 |
{qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0}, |
| 34379 |
{qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0}, |
| 34380 |
{qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0}, |
| 34381 |
{qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0}, |
| 34382 |
{qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0}, |
| 34383 |
{qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0}, |
| 34384 |
{qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0} |
| 34385 |
]; |
| 34386 |
|
| 34387 |
// C.3.5 Initialisation of the decoder (INITDEC) |
| 34388 |
function ArithmeticDecoder(data, start, end) { |
| 34389 |
this.data = data; |
| 34390 |
this.bp = start; |
| 34391 |
this.dataEnd = end; |
| 34392 |
|
| 34393 |
this.chigh = data[start]; |
| 34394 |
this.clow = 0; |
| 34395 |
|
| 34396 |
this.byteIn(); |
| 34397 |
|
| 34398 |
this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F); |
| 34399 |
this.clow = (this.clow << 7) & 0xFFFF; |
| 34400 |
this.ct -= 7; |
| 34401 |
this.a = 0x8000; |
| 34402 |
} |
| 34403 |
|
| 34404 |
ArithmeticDecoder.prototype = { |
| 34405 |
// C.3.4 Compressed data input (BYTEIN) |
| 34406 |
byteIn: function ArithmeticDecoder_byteIn() { |
| 34407 |
var data = this.data; |
| 34408 |
var bp = this.bp; |
| 34409 |
if (data[bp] === 0xFF) { |
| 34410 |
var b1 = data[bp + 1]; |
| 34411 |
if (b1 > 0x8F) { |
| 34412 |
this.clow += 0xFF00; |
| 34413 |
this.ct = 8; |
| 34414 |
} else { |
| 34415 |
bp++; |
| 34416 |
this.clow += (data[bp] << 9); |
| 34417 |
this.ct = 7; |
| 34418 |
this.bp = bp; |
| 34419 |
} |
| 34420 |
} else { |
| 34421 |
bp++; |
| 34422 |
this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00; |
| 34423 |
this.ct = 8; |
| 34424 |
this.bp = bp; |
| 34425 |
} |
| 34426 |
if (this.clow > 0xFFFF) { |
| 34427 |
this.chigh += (this.clow >> 16); |
| 34428 |
this.clow &= 0xFFFF; |
| 34429 |
} |
| 34430 |
}, |
| 34431 |
// C.3.2 Decoding a decision (DECODE) |
| 34432 |
readBit: function ArithmeticDecoder_readBit(contexts, pos) { |
| 34433 |
// contexts are packed into 1 byte: |
| 34434 |
// highest 7 bits carry cx.index, lowest bit carries cx.mps |
| 34435 |
var cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1; |
| 34436 |
var qeTableIcx = QeTable[cx_index]; |
| 34437 |
var qeIcx = qeTableIcx.qe; |
| 34438 |
var d; |
| 34439 |
var a = this.a - qeIcx; |
| 34440 |
|
| 34441 |
if (this.chigh < qeIcx) { |
| 34442 |
// exchangeLps |
| 34443 |
if (a < qeIcx) { |
| 34444 |
a = qeIcx; |
| 34445 |
d = cx_mps; |
| 34446 |
cx_index = qeTableIcx.nmps; |
| 34447 |
} else { |
| 34448 |
a = qeIcx; |
| 34449 |
d = 1 ^ cx_mps; |
| 34450 |
if (qeTableIcx.switchFlag === 1) { |
| 34451 |
cx_mps = d; |
| 34452 |
} |
| 34453 |
cx_index = qeTableIcx.nlps; |
| 34454 |
} |
| 34455 |
} else { |
| 34456 |
this.chigh -= qeIcx; |
| 34457 |
if ((a & 0x8000) !== 0) { |
| 34458 |
this.a = a; |
| 34459 |
return cx_mps; |
| 34460 |
} |
| 34461 |
// exchangeMps |
| 34462 |
if (a < qeIcx) { |
| 34463 |
d = 1 ^ cx_mps; |
| 34464 |
if (qeTableIcx.switchFlag === 1) { |
| 34465 |
cx_mps = d; |
| 34466 |
} |
| 34467 |
cx_index = qeTableIcx.nlps; |
| 34468 |
} else { |
| 34469 |
d = cx_mps; |
| 34470 |
cx_index = qeTableIcx.nmps; |
| 34471 |
} |
| 34472 |
} |
| 34473 |
// C.3.3 renormD; |
| 34474 |
do { |
| 34475 |
if (this.ct === 0) { |
| 34476 |
this.byteIn(); |
| 34477 |
} |
| 34478 |
|
| 34479 |
a <<= 1; |
| 34480 |
this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1); |
| 34481 |
this.clow = (this.clow << 1) & 0xFFFF; |
| 34482 |
this.ct--; |
| 34483 |
} while ((a & 0x8000) === 0); |
| 34484 |
this.a = a; |
| 34485 |
|
| 34486 |
contexts[pos] = cx_index << 1 | cx_mps; |
| 34487 |
return d; |
| 34488 |
} |
| 34489 |
}; |
| 34490 |
|
| 34491 |
return ArithmeticDecoder; |
| 34492 |
})(); |
| 34493 |
|
| 34494 |
|
| 34495 |
var JpegImage = (function jpegImage() { |
| 34496 |
var dctZigZag = new Uint8Array([ |
| 34497 |
0, |
| 34498 |
1, 8, |
| 34499 |
16, 9, 2, |
| 34500 |
3, 10, 17, 24, |
| 34501 |
32, 25, 18, 11, 4, |
| 34502 |
5, 12, 19, 26, 33, 40, |
| 34503 |
48, 41, 34, 27, 20, 13, 6, |
| 34504 |
7, 14, 21, 28, 35, 42, 49, 56, |
| 34505 |
57, 50, 43, 36, 29, 22, 15, |
| 34506 |
23, 30, 37, 44, 51, 58, |
| 34507 |
59, 52, 45, 38, 31, |
| 34508 |
39, 46, 53, 60, |
| 34509 |
61, 54, 47, |
| 34510 |
55, 62, |
| 34511 |
63 |
| 34512 |
]); |
| 34513 |
|
| 34514 |
var dctCos1 = 4017; // cos(pi/16) |
| 34515 |
var dctSin1 = 799; // sin(pi/16) |
| 34516 |
var dctCos3 = 3406; // cos(3*pi/16) |
| 34517 |
var dctSin3 = 2276; // sin(3*pi/16) |
| 34518 |
var dctCos6 = 1567; // cos(6*pi/16) |
| 34519 |
var dctSin6 = 3784; // sin(6*pi/16) |
| 34520 |
var dctSqrt2 = 5793; // sqrt(2) |
| 34521 |
var dctSqrt1d2 = 2896; // sqrt(2) / 2 |
| 34522 |
|
| 34523 |
function constructor() { |
| 34524 |
} |
| 34525 |
|
| 34526 |
function buildHuffmanTable(codeLengths, values) { |
| 34527 |
var k = 0, code = [], i, j, length = 16; |
| 34528 |
while (length > 0 && !codeLengths[length - 1]) { |
| 34529 |
length--; |
| 34530 |
} |
| 34531 |
code.push({children: [], index: 0}); |
| 34532 |
var p = code[0], q; |
| 34533 |
for (i = 0; i < length; i++) { |
| 34534 |
for (j = 0; j < codeLengths[i]; j++) { |
| 34535 |
p = code.pop(); |
| 34536 |
p.children[p.index] = values[k]; |
| 34537 |
while (p.index > 0) { |
| 34538 |
p = code.pop(); |
| 34539 |
} |
| 34540 |
p.index++; |
| 34541 |
code.push(p); |
| 34542 |
while (code.length <= i) { |
| 34543 |
code.push(q = {children: [], index: 0}); |
| 34544 |
p.children[p.index] = q.children; |
| 34545 |
p = q; |
| 34546 |
} |
| 34547 |
k++; |
| 34548 |
} |
| 34549 |
if (i + 1 < length) { |
| 34550 |
// p here points to last code |
| 34551 |
code.push(q = {children: [], index: 0}); |
| 34552 |
p.children[p.index] = q.children; |
| 34553 |
p = q; |
| 34554 |
} |
| 34555 |
} |
| 34556 |
return code[0].children; |
| 34557 |
} |
| 34558 |
|
| 34559 |
function getBlockBufferOffset(component, row, col) { |
| 34560 |
return 64 * ((component.blocksPerLine + 1) * row + col); |
| 34561 |
} |
| 34562 |
|
| 34563 |
function decodeScan(data, offset, frame, components, resetInterval, |
| 34564 |
spectralStart, spectralEnd, successivePrev, successive) { |
| 34565 |
var precision = frame.precision; |
| 34566 |
var samplesPerLine = frame.samplesPerLine; |
| 34567 |
var scanLines = frame.scanLines; |
| 34568 |
var mcusPerLine = frame.mcusPerLine; |
| 34569 |
var progressive = frame.progressive; |
| 34570 |
var maxH = frame.maxH, maxV = frame.maxV; |
| 34571 |
|
| 34572 |
var startOffset = offset, bitsData = 0, bitsCount = 0; |
| 34573 |
|
| 34574 |
function readBit() { |
| 34575 |
if (bitsCount > 0) { |
| 34576 |
bitsCount--; |
| 34577 |
return (bitsData >> bitsCount) & 1; |
| 34578 |
} |
| 34579 |
bitsData = data[offset++]; |
| 34580 |
if (bitsData === 0xFF) { |
| 34581 |
var nextByte = data[offset++]; |
| 34582 |
if (nextByte) { |
| 34583 |
throw 'unexpected marker: ' + |
| 34584 |
((bitsData << 8) | nextByte).toString(16); |
| 34585 |
} |
| 34586 |
// unstuff 0 |
| 34587 |
} |
| 34588 |
bitsCount = 7; |
| 34589 |
return bitsData >>> 7; |
| 34590 |
} |
| 34591 |
|
| 34592 |
function decodeHuffman(tree) { |
| 34593 |
var node = tree; |
| 34594 |
while (true) { |
| 34595 |
node = node[readBit()]; |
| 34596 |
if (typeof node === 'number') { |
| 34597 |
return node; |
| 34598 |
} |
| 34599 |
if (typeof node !== 'object') { |
| 34600 |
throw 'invalid huffman sequence'; |
| 34601 |
} |
| 34602 |
} |
| 34603 |
} |
| 34604 |
|
| 34605 |
function receive(length) { |
| 34606 |
var n = 0; |
| 34607 |
while (length > 0) { |
| 34608 |
n = (n << 1) | readBit(); |
| 34609 |
length--; |
| 34610 |
} |
| 34611 |
return n; |
| 34612 |
} |
| 34613 |
|
| 34614 |
function receiveAndExtend(length) { |
| 34615 |
if (length === 1) { |
| 34616 |
return readBit() === 1 ? 1 : -1; |
| 34617 |
} |
| 34618 |
var n = receive(length); |
| 34619 |
if (n >= 1 << (length - 1)) { |
| 34620 |
return n; |
| 34621 |
} |
| 34622 |
return n + (-1 << length) + 1; |
| 34623 |
} |
| 34624 |
|
| 34625 |
function decodeBaseline(component, offset) { |
| 34626 |
var t = decodeHuffman(component.huffmanTableDC); |
| 34627 |
var diff = t === 0 ? 0 : receiveAndExtend(t); |
| 34628 |
component.blockData[offset] = (component.pred += diff); |
| 34629 |
var k = 1; |
| 34630 |
while (k < 64) { |
| 34631 |
var rs = decodeHuffman(component.huffmanTableAC); |
| 34632 |
var s = rs & 15, r = rs >> 4; |
| 34633 |
if (s === 0) { |
| 34634 |
if (r < 15) { |
| 34635 |
break; |
| 34636 |
} |
| 34637 |
k += 16; |
| 34638 |
continue; |
| 34639 |
} |
| 34640 |
k += r; |
| 34641 |
var z = dctZigZag[k]; |
| 34642 |
component.blockData[offset + z] = receiveAndExtend(s); |
| 34643 |
k++; |
| 34644 |
} |
| 34645 |
} |
| 34646 |
|
| 34647 |
function decodeDCFirst(component, offset) { |
| 34648 |
var t = decodeHuffman(component.huffmanTableDC); |
| 34649 |
var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive); |
| 34650 |
component.blockData[offset] = (component.pred += diff); |
| 34651 |
} |
| 34652 |
|
| 34653 |
function decodeDCSuccessive(component, offset) { |
| 34654 |
component.blockData[offset] |= readBit() << successive; |
| 34655 |
} |
| 34656 |
|
| 34657 |
var eobrun = 0; |
| 34658 |
function decodeACFirst(component, offset) { |
| 34659 |
if (eobrun > 0) { |
| 34660 |
eobrun--; |
| 34661 |
return; |
| 34662 |
} |
| 34663 |
var k = spectralStart, e = spectralEnd; |
| 34664 |
while (k <= e) { |
| 34665 |
var rs = decodeHuffman(component.huffmanTableAC); |
| 34666 |
var s = rs & 15, r = rs >> 4; |
| 34667 |
if (s === 0) { |
| 34668 |
if (r < 15) { |
| 34669 |
eobrun = receive(r) + (1 << r) - 1; |
| 34670 |
break; |
| 34671 |
} |
| 34672 |
k += 16; |
| 34673 |
continue; |
| 34674 |
} |
| 34675 |
k += r; |
| 34676 |
var z = dctZigZag[k]; |
| 34677 |
component.blockData[offset + z] = |
| 34678 |
receiveAndExtend(s) * (1 << successive); |
| 34679 |
k++; |
| 34680 |
} |
| 34681 |
} |
| 34682 |
|
| 34683 |
var successiveACState = 0, successiveACNextValue; |
| 34684 |
function decodeACSuccessive(component, offset) { |
| 34685 |
var k = spectralStart; |
| 34686 |
var e = spectralEnd; |
| 34687 |
var r = 0; |
| 34688 |
var s; |
| 34689 |
var rs; |
| 34690 |
while (k <= e) { |
| 34691 |
var z = dctZigZag[k]; |
| 34692 |
switch (successiveACState) { |
| 34693 |
case 0: // initial state |
| 34694 |
rs = decodeHuffman(component.huffmanTableAC); |
| 34695 |
s = rs & 15; |
| 34696 |
r = rs >> 4; |
| 34697 |
if (s === 0) { |
| 34698 |
if (r < 15) { |
| 34699 |
eobrun = receive(r) + (1 << r); |
| 34700 |
successiveACState = 4; |
| 34701 |
} else { |
| 34702 |
r = 16; |
| 34703 |
successiveACState = 1; |
| 34704 |
} |
| 34705 |
} else { |
| 34706 |
if (s !== 1) { |
| 34707 |
throw 'invalid ACn encoding'; |
| 34708 |
} |
| 34709 |
successiveACNextValue = receiveAndExtend(s); |
| 34710 |
successiveACState = r ? 2 : 3; |
| 34711 |
} |
| 34712 |
continue; |
| 34713 |
case 1: // skipping r zero items |
| 34714 |
case 2: |
| 34715 |
if (component.blockData[offset + z]) { |
| 34716 |
component.blockData[offset + z] += (readBit() << successive); |
| 34717 |
} else { |
| 34718 |
r--; |
| 34719 |
if (r === 0) { |
| 34720 |
successiveACState = successiveACState === 2 ? 3 : 0; |
| 34721 |
} |
| 34722 |
} |
| 34723 |
break; |
| 34724 |
case 3: // set value for a zero item |
| 34725 |
if (component.blockData[offset + z]) { |
| 34726 |
component.blockData[offset + z] += (readBit() << successive); |
| 34727 |
} else { |
| 34728 |
component.blockData[offset + z] = |
| 34729 |
successiveACNextValue << successive; |
| 34730 |
successiveACState = 0; |
| 34731 |
} |
| 34732 |
break; |
| 34733 |
case 4: // eob |
| 34734 |
if (component.blockData[offset + z]) { |
| 34735 |
component.blockData[offset + z] += (readBit() << successive); |
| 34736 |
} |
| 34737 |
break; |
| 34738 |
} |
| 34739 |
k++; |
| 34740 |
} |
| 34741 |
if (successiveACState === 4) { |
| 34742 |
eobrun--; |
| 34743 |
if (eobrun === 0) { |
| 34744 |
successiveACState = 0; |
| 34745 |
} |
| 34746 |
} |
| 34747 |
} |
| 34748 |
|
| 34749 |
function decodeMcu(component, decode, mcu, row, col) { |
| 34750 |
var mcuRow = (mcu / mcusPerLine) | 0; |
| 34751 |
var mcuCol = mcu % mcusPerLine; |
| 34752 |
var blockRow = mcuRow * component.v + row; |
| 34753 |
var blockCol = mcuCol * component.h + col; |
| 34754 |
var offset = getBlockBufferOffset(component, blockRow, blockCol); |
| 34755 |
decode(component, offset); |
| 34756 |
} |
| 34757 |
|
| 34758 |
function decodeBlock(component, decode, mcu) { |
| 34759 |
var blockRow = (mcu / component.blocksPerLine) | 0; |
| 34760 |
var blockCol = mcu % component.blocksPerLine; |
| 34761 |
var offset = getBlockBufferOffset(component, blockRow, blockCol); |
| 34762 |
decode(component, offset); |
| 34763 |
} |
| 34764 |
|
| 34765 |
var componentsLength = components.length; |
| 34766 |
var component, i, j, k, n; |
| 34767 |
var decodeFn; |
| 34768 |
if (progressive) { |
| 34769 |
if (spectralStart === 0) { |
| 34770 |
decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; |
| 34771 |
} else { |
| 34772 |
decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; |
| 34773 |
} |
| 34774 |
} else { |
| 34775 |
decodeFn = decodeBaseline; |
| 34776 |
} |
| 34777 |
|
| 34778 |
var mcu = 0, marker; |
| 34779 |
var mcuExpected; |
| 34780 |
if (componentsLength === 1) { |
| 34781 |
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn; |
| 34782 |
} else { |
| 34783 |
mcuExpected = mcusPerLine * frame.mcusPerColumn; |
| 34784 |
} |
| 34785 |
if (!resetInterval) { |
| 34786 |
resetInterval = mcuExpected; |
| 34787 |
} |
| 34788 |
|
| 34789 |
var h, v; |
| 34790 |
while (mcu < mcuExpected) { |
| 34791 |
// reset interval stuff |
| 34792 |
for (i = 0; i < componentsLength; i++) { |
| 34793 |
components[i].pred = 0; |
| 34794 |
} |
| 34795 |
eobrun = 0; |
| 34796 |
|
| 34797 |
if (componentsLength === 1) { |
| 34798 |
component = components[0]; |
| 34799 |
for (n = 0; n < resetInterval; n++) { |
| 34800 |
decodeBlock(component, decodeFn, mcu); |
| 34801 |
mcu++; |
| 34802 |
} |
| 34803 |
} else { |
| 34804 |
for (n = 0; n < resetInterval; n++) { |
| 34805 |
for (i = 0; i < componentsLength; i++) { |
| 34806 |
component = components[i]; |
| 34807 |
h = component.h; |
| 34808 |
v = component.v; |
| 34809 |
for (j = 0; j < v; j++) { |
| 34810 |
for (k = 0; k < h; k++) { |
| 34811 |
decodeMcu(component, decodeFn, mcu, j, k); |
| 34812 |
} |
| 34813 |
} |
| 34814 |
} |
| 34815 |
mcu++; |
| 34816 |
} |
| 34817 |
} |
| 34818 |
|
| 34819 |
// find marker |
| 34820 |
bitsCount = 0; |
| 34821 |
marker = (data[offset] << 8) | data[offset + 1]; |
| 34822 |
if (marker <= 0xFF00) { |
| 34823 |
throw 'marker was not found'; |
| 34824 |
} |
| 34825 |
|
| 34826 |
if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx |
| 34827 |
offset += 2; |
| 34828 |
} else { |
| 34829 |
break; |
| 34830 |
} |
| 34831 |
} |
| 34832 |
|
| 34833 |
return offset - startOffset; |
| 34834 |
} |
| 34835 |
|
| 34836 |
// A port of poppler's IDCT method which in turn is taken from: |
| 34837 |
// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, |
| 34838 |
// 'Practical Fast 1-D DCT Algorithms with 11 Multiplications', |
| 34839 |
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, |
| 34840 |
// 988-991. |
| 34841 |
function quantizeAndInverse(component, blockBufferOffset, p) { |
| 34842 |
var qt = component.quantizationTable, blockData = component.blockData; |
| 34843 |
var v0, v1, v2, v3, v4, v5, v6, v7; |
| 34844 |
var p0, p1, p2, p3, p4, p5, p6, p7; |
| 34845 |
var t; |
| 34846 |
|
| 34847 |
// inverse DCT on rows |
| 34848 |
for (var row = 0; row < 64; row += 8) { |
| 34849 |
// gather block data |
| 34850 |
p0 = blockData[blockBufferOffset + row]; |
| 34851 |
p1 = blockData[blockBufferOffset + row + 1]; |
| 34852 |
p2 = blockData[blockBufferOffset + row + 2]; |
| 34853 |
p3 = blockData[blockBufferOffset + row + 3]; |
| 34854 |
p4 = blockData[blockBufferOffset + row + 4]; |
| 34855 |
p5 = blockData[blockBufferOffset + row + 5]; |
| 34856 |
p6 = blockData[blockBufferOffset + row + 6]; |
| 34857 |
p7 = blockData[blockBufferOffset + row + 7]; |
| 34858 |
|
| 34859 |
// dequant p0 |
| 34860 |
p0 *= qt[row]; |
| 34861 |
|
| 34862 |
// check for all-zero AC coefficients |
| 34863 |
if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { |
| 34864 |
t = (dctSqrt2 * p0 + 512) >> 10; |
| 34865 |
p[row] = t; |
| 34866 |
p[row + 1] = t; |
| 34867 |
p[row + 2] = t; |
| 34868 |
p[row + 3] = t; |
| 34869 |
p[row + 4] = t; |
| 34870 |
p[row + 5] = t; |
| 34871 |
p[row + 6] = t; |
| 34872 |
p[row + 7] = t; |
| 34873 |
continue; |
| 34874 |
} |
| 34875 |
// dequant p1 ... p7 |
| 34876 |
p1 *= qt[row + 1]; |
| 34877 |
p2 *= qt[row + 2]; |
| 34878 |
p3 *= qt[row + 3]; |
| 34879 |
p4 *= qt[row + 4]; |
| 34880 |
p5 *= qt[row + 5]; |
| 34881 |
p6 *= qt[row + 6]; |
| 34882 |
p7 *= qt[row + 7]; |
| 34883 |
|
| 34884 |
// stage 4 |
| 34885 |
v0 = (dctSqrt2 * p0 + 128) >> 8; |
| 34886 |
v1 = (dctSqrt2 * p4 + 128) >> 8; |
| 34887 |
v2 = p2; |
| 34888 |
v3 = p6; |
| 34889 |
v4 = (dctSqrt1d2 * (p1 - p7) + 128) >> 8; |
| 34890 |
v7 = (dctSqrt1d2 * (p1 + p7) + 128) >> 8; |
| 34891 |
v5 = p3 << 4; |
| 34892 |
v6 = p5 << 4; |
| 34893 |
|
| 34894 |
// stage 3 |
| 34895 |
v0 = (v0 + v1 + 1) >> 1; |
| 34896 |
v1 = v0 - v1; |
| 34897 |
t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; |
| 34898 |
v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; |
| 34899 |
v3 = t; |
| 34900 |
v4 = (v4 + v6 + 1) >> 1; |
| 34901 |
v6 = v4 - v6; |
| 34902 |
v7 = (v7 + v5 + 1) >> 1; |
| 34903 |
v5 = v7 - v5; |
| 34904 |
|
| 34905 |
// stage 2 |
| 34906 |
v0 = (v0 + v3 + 1) >> 1; |
| 34907 |
v3 = v0 - v3; |
| 34908 |
v1 = (v1 + v2 + 1) >> 1; |
| 34909 |
v2 = v1 - v2; |
| 34910 |
t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; |
| 34911 |
v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; |
| 34912 |
v7 = t; |
| 34913 |
t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; |
| 34914 |
v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; |
| 34915 |
v6 = t; |
| 34916 |
|
| 34917 |
// stage 1 |
| 34918 |
p[row] = v0 + v7; |
| 34919 |
p[row + 7] = v0 - v7; |
| 34920 |
p[row + 1] = v1 + v6; |
| 34921 |
p[row + 6] = v1 - v6; |
| 34922 |
p[row + 2] = v2 + v5; |
| 34923 |
p[row + 5] = v2 - v5; |
| 34924 |
p[row + 3] = v3 + v4; |
| 34925 |
p[row + 4] = v3 - v4; |
| 34926 |
} |
| 34927 |
|
| 34928 |
// inverse DCT on columns |
| 34929 |
for (var col = 0; col < 8; ++col) { |
| 34930 |
p0 = p[col]; |
| 34931 |
p1 = p[col + 8]; |
| 34932 |
p2 = p[col + 16]; |
| 34933 |
p3 = p[col + 24]; |
| 34934 |
p4 = p[col + 32]; |
| 34935 |
p5 = p[col + 40]; |
| 34936 |
p6 = p[col + 48]; |
| 34937 |
p7 = p[col + 56]; |
| 34938 |
|
| 34939 |
// check for all-zero AC coefficients |
| 34940 |
if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { |
| 34941 |
t = (dctSqrt2 * p0 + 8192) >> 14; |
| 34942 |
// convert to 8 bit |
| 34943 |
t = (t < -2040) ? 0 : (t >= 2024) ? 255 : (t + 2056) >> 4; |
| 34944 |
blockData[blockBufferOffset + col] = t; |
| 34945 |
blockData[blockBufferOffset + col + 8] = t; |
| 34946 |
blockData[blockBufferOffset + col + 16] = t; |
| 34947 |
blockData[blockBufferOffset + col + 24] = t; |
| 34948 |
blockData[blockBufferOffset + col + 32] = t; |
| 34949 |
blockData[blockBufferOffset + col + 40] = t; |
| 34950 |
blockData[blockBufferOffset + col + 48] = t; |
| 34951 |
blockData[blockBufferOffset + col + 56] = t; |
| 34952 |
continue; |
| 34953 |
} |
| 34954 |
|
| 34955 |
// stage 4 |
| 34956 |
v0 = (dctSqrt2 * p0 + 2048) >> 12; |
| 34957 |
v1 = (dctSqrt2 * p4 + 2048) >> 12; |
| 34958 |
v2 = p2; |
| 34959 |
v3 = p6; |
| 34960 |
v4 = (dctSqrt1d2 * (p1 - p7) + 2048) >> 12; |
| 34961 |
v7 = (dctSqrt1d2 * (p1 + p7) + 2048) >> 12; |
| 34962 |
v5 = p3; |
| 34963 |
v6 = p5; |
| 34964 |
|
| 34965 |
// stage 3 |
| 34966 |
// Shift v0 by 128.5 << 5 here, so we don't need to shift p0...p7 when |
| 34967 |
// converting to UInt8 range later. |
| 34968 |
v0 = ((v0 + v1 + 1) >> 1) + 4112; |
| 34969 |
v1 = v0 - v1; |
| 34970 |
t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; |
| 34971 |
v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; |
| 34972 |
v3 = t; |
| 34973 |
v4 = (v4 + v6 + 1) >> 1; |
| 34974 |
v6 = v4 - v6; |
| 34975 |
v7 = (v7 + v5 + 1) >> 1; |
| 34976 |
v5 = v7 - v5; |
| 34977 |
|
| 34978 |
// stage 2 |
| 34979 |
v0 = (v0 + v3 + 1) >> 1; |
| 34980 |
v3 = v0 - v3; |
| 34981 |
v1 = (v1 + v2 + 1) >> 1; |
| 34982 |
v2 = v1 - v2; |
| 34983 |
t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; |
| 34984 |
v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; |
| 34985 |
v7 = t; |
| 34986 |
t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; |
| 34987 |
v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; |
| 34988 |
v6 = t; |
| 34989 |
|
| 34990 |
// stage 1 |
| 34991 |
p0 = v0 + v7; |
| 34992 |
p7 = v0 - v7; |
| 34993 |
p1 = v1 + v6; |
| 34994 |
p6 = v1 - v6; |
| 34995 |
p2 = v2 + v5; |
| 34996 |
p5 = v2 - v5; |
| 34997 |
p3 = v3 + v4; |
| 34998 |
p4 = v3 - v4; |
| 34999 |
|
| 35000 |
// convert to 8-bit integers |
| 35001 |
p0 = (p0 < 16) ? 0 : (p0 >= 4080) ? 255 : p0 >> 4; |
| 35002 |
p1 = (p1 < 16) ? 0 : (p1 >= 4080) ? 255 : p1 >> 4; |
| 35003 |
p2 = (p2 < 16) ? 0 : (p2 >= 4080) ? 255 : p2 >> 4; |
| 35004 |
p3 = (p3 < 16) ? 0 : (p3 >= 4080) ? 255 : p3 >> 4; |
| 35005 |
p4 = (p4 < 16) ? 0 : (p4 >= 4080) ? 255 : p4 >> 4; |
| 35006 |
p5 = (p5 < 16) ? 0 : (p5 >= 4080) ? 255 : p5 >> 4; |
| 35007 |
p6 = (p6 < 16) ? 0 : (p6 >= 4080) ? 255 : p6 >> 4; |
| 35008 |
p7 = (p7 < 16) ? 0 : (p7 >= 4080) ? 255 : p7 >> 4; |
| 35009 |
|
| 35010 |
// store block data |
| 35011 |
blockData[blockBufferOffset + col] = p0; |
| 35012 |
blockData[blockBufferOffset + col + 8] = p1; |
| 35013 |
blockData[blockBufferOffset + col + 16] = p2; |
| 35014 |
blockData[blockBufferOffset + col + 24] = p3; |
| 35015 |
blockData[blockBufferOffset + col + 32] = p4; |
| 35016 |
blockData[blockBufferOffset + col + 40] = p5; |
| 35017 |
blockData[blockBufferOffset + col + 48] = p6; |
| 35018 |
blockData[blockBufferOffset + col + 56] = p7; |
| 35019 |
} |
| 35020 |
} |
| 35021 |
|
| 35022 |
function buildComponentData(frame, component) { |
| 35023 |
var blocksPerLine = component.blocksPerLine; |
| 35024 |
var blocksPerColumn = component.blocksPerColumn; |
| 35025 |
var computationBuffer = new Int16Array(64); |
| 35026 |
|
| 35027 |
for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { |
| 35028 |
for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { |
| 35029 |
var offset = getBlockBufferOffset(component, blockRow, blockCol); |
| 35030 |
quantizeAndInverse(component, offset, computationBuffer); |
| 35031 |
} |
| 35032 |
} |
| 35033 |
return component.blockData; |
| 35034 |
} |
| 35035 |
|
| 35036 |
function clamp0to255(a) { |
| 35037 |
return a <= 0 ? 0 : a >= 255 ? 255 : a; |
| 35038 |
} |
| 35039 |
|
| 35040 |
constructor.prototype = { |
| 35041 |
parse: function parse(data) { |
| 35042 |
|
| 35043 |
function readUint16() { |
| 35044 |
var value = (data[offset] << 8) | data[offset + 1]; |
| 35045 |
offset += 2; |
| 35046 |
return value; |
| 35047 |
} |
| 35048 |
|
| 35049 |
function readDataBlock() { |
| 35050 |
var length = readUint16(); |
| 35051 |
var array = data.subarray(offset, offset + length - 2); |
| 35052 |
offset += array.length; |
| 35053 |
return array; |
| 35054 |
} |
| 35055 |
|
| 35056 |
function prepareComponents(frame) { |
| 35057 |
var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH); |
| 35058 |
var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV); |
| 35059 |
for (var i = 0; i < frame.components.length; i++) { |
| 35060 |
component = frame.components[i]; |
| 35061 |
var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * |
| 35062 |
component.h / frame.maxH); |
| 35063 |
var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * |
| 35064 |
component.v / frame.maxV); |
| 35065 |
var blocksPerLineForMcu = mcusPerLine * component.h; |
| 35066 |
var blocksPerColumnForMcu = mcusPerColumn * component.v; |
| 35067 |
|
| 35068 |
var blocksBufferSize = 64 * blocksPerColumnForMcu * |
| 35069 |
(blocksPerLineForMcu + 1); |
| 35070 |
component.blockData = new Int16Array(blocksBufferSize); |
| 35071 |
component.blocksPerLine = blocksPerLine; |
| 35072 |
component.blocksPerColumn = blocksPerColumn; |
| 35073 |
} |
| 35074 |
frame.mcusPerLine = mcusPerLine; |
| 35075 |
frame.mcusPerColumn = mcusPerColumn; |
| 35076 |
} |
| 35077 |
|
| 35078 |
var offset = 0, length = data.length; |
| 35079 |
var jfif = null; |
| 35080 |
var adobe = null; |
| 35081 |
var pixels = null; |
| 35082 |
var frame, resetInterval; |
| 35083 |
var quantizationTables = []; |
| 35084 |
var huffmanTablesAC = [], huffmanTablesDC = []; |
| 35085 |
var fileMarker = readUint16(); |
| 35086 |
if (fileMarker !== 0xFFD8) { // SOI (Start of Image) |
| 35087 |
throw 'SOI not found'; |
| 35088 |
} |
| 35089 |
|
| 35090 |
fileMarker = readUint16(); |
| 35091 |
while (fileMarker !== 0xFFD9) { // EOI (End of image) |
| 35092 |
var i, j, l; |
| 35093 |
switch(fileMarker) { |
| 35094 |
case 0xFFE0: // APP0 (Application Specific) |
| 35095 |
case 0xFFE1: // APP1 |
| 35096 |
case 0xFFE2: // APP2 |
| 35097 |
case 0xFFE3: // APP3 |
| 35098 |
case 0xFFE4: // APP4 |
| 35099 |
case 0xFFE5: // APP5 |
| 35100 |
case 0xFFE6: // APP6 |
| 35101 |
case 0xFFE7: // APP7 |
| 35102 |
case 0xFFE8: // APP8 |
| 35103 |
case 0xFFE9: // APP9 |
| 35104 |
case 0xFFEA: // APP10 |
| 35105 |
case 0xFFEB: // APP11 |
| 35106 |
case 0xFFEC: // APP12 |
| 35107 |
case 0xFFED: // APP13 |
| 35108 |
case 0xFFEE: // APP14 |
| 35109 |
case 0xFFEF: // APP15 |
| 35110 |
case 0xFFFE: // COM (Comment) |
| 35111 |
var appData = readDataBlock(); |
| 35112 |
|
| 35113 |
if (fileMarker === 0xFFE0) { |
| 35114 |
if (appData[0] === 0x4A && appData[1] === 0x46 && |
| 35115 |
appData[2] === 0x49 && appData[3] === 0x46 && |
| 35116 |
appData[4] === 0) { // 'JFIF\x00' |
| 35117 |
jfif = { |
| 35118 |
version: { major: appData[5], minor: appData[6] }, |
| 35119 |
densityUnits: appData[7], |
| 35120 |
xDensity: (appData[8] << 8) | appData[9], |
| 35121 |
yDensity: (appData[10] << 8) | appData[11], |
| 35122 |
thumbWidth: appData[12], |
| 35123 |
thumbHeight: appData[13], |
| 35124 |
thumbData: appData.subarray(14, 14 + |
| 35125 |
3 * appData[12] * appData[13]) |
| 35126 |
}; |
| 35127 |
} |
| 35128 |
} |
| 35129 |
// TODO APP1 - Exif |
| 35130 |
if (fileMarker === 0xFFEE) { |
| 35131 |
if (appData[0] === 0x41 && appData[1] === 0x64 && |
| 35132 |
appData[2] === 0x6F && appData[3] === 0x62 && |
| 35133 |
appData[4] === 0x65) { // 'Adobe' |
| 35134 |
adobe = { |
| 35135 |
version: (appData[5] << 8) | appData[6], |
| 35136 |
flags0: (appData[7] << 8) | appData[8], |
| 35137 |
flags1: (appData[9] << 8) | appData[10], |
| 35138 |
transformCode: appData[11] |
| 35139 |
}; |
| 35140 |
} |
| 35141 |
} |
| 35142 |
break; |
| 35143 |
|
| 35144 |
case 0xFFDB: // DQT (Define Quantization Tables) |
| 35145 |
var quantizationTablesLength = readUint16(); |
| 35146 |
var quantizationTablesEnd = quantizationTablesLength + offset - 2; |
| 35147 |
var z; |
| 35148 |
while (offset < quantizationTablesEnd) { |
| 35149 |
var quantizationTableSpec = data[offset++]; |
| 35150 |
var tableData = new Uint16Array(64); |
| 35151 |
if ((quantizationTableSpec >> 4) === 0) { // 8 bit values |
| 35152 |
for (j = 0; j < 64; j++) { |
| 35153 |
z = dctZigZag[j]; |
| 35154 |
tableData[z] = data[offset++]; |
| 35155 |
} |
| 35156 |
} else if ((quantizationTableSpec >> 4) === 1) { //16 bit |
| 35157 |
for (j = 0; j < 64; j++) { |
| 35158 |
z = dctZigZag[j]; |
| 35159 |
tableData[z] = readUint16(); |
| 35160 |
} |
| 35161 |
} else { |
| 35162 |
throw 'DQT: invalid table spec'; |
| 35163 |
} |
| 35164 |
quantizationTables[quantizationTableSpec & 15] = tableData; |
| 35165 |
} |
| 35166 |
break; |
| 35167 |
|
| 35168 |
case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT) |
| 35169 |
case 0xFFC1: // SOF1 (Start of Frame, Extended DCT) |
| 35170 |
case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT) |
| 35171 |
if (frame) { |
| 35172 |
throw 'Only single frame JPEGs supported'; |
| 35173 |
} |
| 35174 |
readUint16(); // skip data length |
| 35175 |
frame = {}; |
| 35176 |
frame.extended = (fileMarker === 0xFFC1); |
| 35177 |
frame.progressive = (fileMarker === 0xFFC2); |
| 35178 |
frame.precision = data[offset++]; |
| 35179 |
frame.scanLines = readUint16(); |
| 35180 |
frame.samplesPerLine = readUint16(); |
| 35181 |
frame.components = []; |
| 35182 |
frame.componentIds = {}; |
| 35183 |
var componentsCount = data[offset++], componentId; |
| 35184 |
var maxH = 0, maxV = 0; |
| 35185 |
for (i = 0; i < componentsCount; i++) { |
| 35186 |
componentId = data[offset]; |
| 35187 |
var h = data[offset + 1] >> 4; |
| 35188 |
var v = data[offset + 1] & 15; |
| 35189 |
if (maxH < h) { |
| 35190 |
maxH = h; |
| 35191 |
} |
| 35192 |
if (maxV < v) { |
| 35193 |
maxV = v; |
| 35194 |
} |
| 35195 |
var qId = data[offset + 2]; |
| 35196 |
l = frame.components.push({ |
| 35197 |
h: h, |
| 35198 |
v: v, |
| 35199 |
quantizationTable: quantizationTables[qId] |
| 35200 |
}); |
| 35201 |
frame.componentIds[componentId] = l - 1; |
| 35202 |
offset += 3; |
| 35203 |
} |
| 35204 |
frame.maxH = maxH; |
| 35205 |
frame.maxV = maxV; |
| 35206 |
prepareComponents(frame); |
| 35207 |
break; |
| 35208 |
|
| 35209 |
case 0xFFC4: // DHT (Define Huffman Tables) |
| 35210 |
var huffmanLength = readUint16(); |
| 35211 |
for (i = 2; i < huffmanLength;) { |
| 35212 |
var huffmanTableSpec = data[offset++]; |
| 35213 |
var codeLengths = new Uint8Array(16); |
| 35214 |
var codeLengthSum = 0; |
| 35215 |
for (j = 0; j < 16; j++, offset++) { |
| 35216 |
codeLengthSum += (codeLengths[j] = data[offset]); |
| 35217 |
} |
| 35218 |
var huffmanValues = new Uint8Array(codeLengthSum); |
| 35219 |
for (j = 0; j < codeLengthSum; j++, offset++) { |
| 35220 |
huffmanValues[j] = data[offset]; |
| 35221 |
} |
| 35222 |
i += 17 + codeLengthSum; |
| 35223 |
|
| 35224 |
((huffmanTableSpec >> 4) === 0 ? |
| 35225 |
huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = |
| 35226 |
buildHuffmanTable(codeLengths, huffmanValues); |
| 35227 |
} |
| 35228 |
break; |
| 35229 |
|
| 35230 |
case 0xFFDD: // DRI (Define Restart Interval) |
| 35231 |
readUint16(); // skip data length |
| 35232 |
resetInterval = readUint16(); |
| 35233 |
break; |
| 35234 |
|
| 35235 |
case 0xFFDA: // SOS (Start of Scan) |
| 35236 |
var scanLength = readUint16(); |
| 35237 |
var selectorsCount = data[offset++]; |
| 35238 |
var components = [], component; |
| 35239 |
for (i = 0; i < selectorsCount; i++) { |
| 35240 |
var componentIndex = frame.componentIds[data[offset++]]; |
| 35241 |
component = frame.components[componentIndex]; |
| 35242 |
var tableSpec = data[offset++]; |
| 35243 |
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; |
| 35244 |
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; |
| 35245 |
components.push(component); |
| 35246 |
} |
| 35247 |
var spectralStart = data[offset++]; |
| 35248 |
var spectralEnd = data[offset++]; |
| 35249 |
var successiveApproximation = data[offset++]; |
| 35250 |
var processed = decodeScan(data, offset, |
| 35251 |
frame, components, resetInterval, |
| 35252 |
spectralStart, spectralEnd, |
| 35253 |
successiveApproximation >> 4, successiveApproximation & 15); |
| 35254 |
offset += processed; |
| 35255 |
break; |
| 35256 |
|
| 35257 |
case 0xFFFF: // Fill bytes |
| 35258 |
if (data[offset] !== 0xFF) { // Avoid skipping a valid marker. |
| 35259 |
offset--; |
| 35260 |
} |
| 35261 |
break; |
| 35262 |
|
| 35263 |
default: |
| 35264 |
if (data[offset - 3] === 0xFF && |
| 35265 |
data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) { |
| 35266 |
// could be incorrect encoding -- last 0xFF byte of the previous |
| 35267 |
// block was eaten by the encoder |
| 35268 |
offset -= 3; |
| 35269 |
break; |
| 35270 |
} |
| 35271 |
throw 'unknown JPEG marker ' + fileMarker.toString(16); |
| 35272 |
} |
| 35273 |
fileMarker = readUint16(); |
| 35274 |
} |
| 35275 |
|
| 35276 |
this.width = frame.samplesPerLine; |
| 35277 |
this.height = frame.scanLines; |
| 35278 |
this.jfif = jfif; |
| 35279 |
this.adobe = adobe; |
| 35280 |
this.components = []; |
| 35281 |
for (i = 0; i < frame.components.length; i++) { |
| 35282 |
component = frame.components[i]; |
| 35283 |
this.components.push({ |
| 35284 |
output: buildComponentData(frame, component), |
| 35285 |
scaleX: component.h / frame.maxH, |
| 35286 |
scaleY: component.v / frame.maxV, |
| 35287 |
blocksPerLine: component.blocksPerLine, |
| 35288 |
blocksPerColumn: component.blocksPerColumn |
| 35289 |
}); |
| 35290 |
} |
| 35291 |
this.numComponents = this.components.length; |
| 35292 |
}, |
| 35293 |
|
| 35294 |
_getLinearizedBlockData: function getLinearizedBlockData(width, height) { |
| 35295 |
var scaleX = this.width / width, scaleY = this.height / height; |
| 35296 |
|
| 35297 |
var component, componentScaleX, componentScaleY, blocksPerScanline; |
| 35298 |
var x, y, i, j, k; |
| 35299 |
var index; |
| 35300 |
var offset = 0; |
| 35301 |
var output; |
| 35302 |
var numComponents = this.components.length; |
| 35303 |
var dataLength = width * height * numComponents; |
| 35304 |
var data = new Uint8Array(dataLength); |
| 35305 |
var xScaleBlockOffset = new Uint32Array(width); |
| 35306 |
var mask3LSB = 0xfffffff8; // used to clear the 3 LSBs |
| 35307 |
|
| 35308 |
for (i = 0; i < numComponents; i++) { |
| 35309 |
component = this.components[i]; |
| 35310 |
componentScaleX = component.scaleX * scaleX; |
| 35311 |
componentScaleY = component.scaleY * scaleY; |
| 35312 |
offset = i; |
| 35313 |
output = component.output; |
| 35314 |
blocksPerScanline = (component.blocksPerLine + 1) << 3; |
| 35315 |
// precalculate the xScaleBlockOffset |
| 35316 |
for (x = 0; x < width; x++) { |
| 35317 |
j = 0 | (x * componentScaleX); |
| 35318 |
xScaleBlockOffset[x] = ((j & mask3LSB) << 3) | (j & 7); |
| 35319 |
} |
| 35320 |
// linearize the blocks of the component |
| 35321 |
for (y = 0; y < height; y++) { |
| 35322 |
j = 0 | (y * componentScaleY); |
| 35323 |
index = blocksPerScanline * (j & mask3LSB) | ((j & 7) << 3); |
| 35324 |
for (x = 0; x < width; x++) { |
| 35325 |
data[offset] = output[index + xScaleBlockOffset[x]]; |
| 35326 |
offset += numComponents; |
| 35327 |
} |
| 35328 |
} |
| 35329 |
} |
| 35330 |
|
| 35331 |
// decodeTransform contains pairs of multiplier (-256..256) and additive |
| 35332 |
var transform = this.decodeTransform; |
| 35333 |
if (transform) { |
| 35334 |
for (i = 0; i < dataLength;) { |
| 35335 |
for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) { |
| 35336 |
data[i] = ((data[i] * transform[k]) >> 8) + transform[k + 1]; |
| 35337 |
} |
| 35338 |
} |
| 35339 |
} |
| 35340 |
return data; |
| 35341 |
}, |
| 35342 |
|
| 35343 |
_isColorConversionNeeded: function isColorConversionNeeded() { |
| 35344 |
if (this.adobe && this.adobe.transformCode) { |
| 35345 |
// The adobe transform marker overrides any previous setting |
| 35346 |
return true; |
| 35347 |
} else if (this.numComponents === 3) { |
| 35348 |
return true; |
| 35349 |
} else { |
| 35350 |
return false; |
| 35351 |
} |
| 35352 |
}, |
| 35353 |
|
| 35354 |
_convertYccToRgb: function convertYccToRgb(data) { |
| 35355 |
var Y, Cb, Cr; |
| 35356 |
for (var i = 0, length = data.length; i < length; i += 3) { |
| 35357 |
Y = data[i ]; |
| 35358 |
Cb = data[i + 1]; |
| 35359 |
Cr = data[i + 2]; |
| 35360 |
data[i ] = clamp0to255(Y - 179.456 + 1.402 * Cr); |
| 35361 |
data[i + 1] = clamp0to255(Y + 135.459 - 0.344 * Cb - 0.714 * Cr); |
| 35362 |
data[i + 2] = clamp0to255(Y - 226.816 + 1.772 * Cb); |
| 35363 |
} |
| 35364 |
return data; |
| 35365 |
}, |
| 35366 |
|
| 35367 |
_convertYcckToRgb: function convertYcckToRgb(data) { |
| 35368 |
var Y, Cb, Cr, k; |
| 35369 |
var offset = 0; |
| 35370 |
for (var i = 0, length = data.length; i < length; i += 4) { |
| 35371 |
Y = data[i]; |
| 35372 |
Cb = data[i + 1]; |
| 35373 |
Cr = data[i + 2]; |
| 35374 |
k = data[i + 3]; |
| 35375 |
|
| 35376 |
var r = -122.67195406894 + |
| 35377 |
Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - |
| 35378 |
5.4080610064599e-5 * Y + 0.00048449797120281 * k - |
| 35379 |
0.154362151871126) + |
| 35380 |
Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - |
| 35381 |
0.00477271405408747 * k + 1.53380253221734) + |
| 35382 |
Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + |
| 35383 |
0.48357088451265) + |
| 35384 |
k * (-0.000336197177618394 * k + 0.484791561490776); |
| 35385 |
|
| 35386 |
var g = 107.268039397724 + |
| 35387 |
Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + |
| 35388 |
0.000659397001245577 * Y + 0.000426105652938837 * k - |
| 35389 |
0.176491792462875) + |
| 35390 |
Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + |
| 35391 |
0.000770482631801132 * k - 0.151051492775562) + |
| 35392 |
Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + |
| 35393 |
0.25802910206845) + |
| 35394 |
k * (-0.000318913117588328 * k - 0.213742400323665); |
| 35395 |
|
| 35396 |
var b = -20.810012546947 + |
| 35397 |
Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + |
| 35398 |
0.0020741088115012 * Y - 0.00288260236853442 * k + |
| 35399 |
0.814272968359295) + |
| 35400 |
Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + |
| 35401 |
0.000560833691242812 * k - 0.195152027534049) + |
| 35402 |
Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + |
| 35403 |
0.116935020465145) + |
| 35404 |
k * (-0.000343531996510555 * k + 0.24165260232407); |
| 35405 |
|
| 35406 |
data[offset++] = clamp0to255(r); |
| 35407 |
data[offset++] = clamp0to255(g); |
| 35408 |
data[offset++] = clamp0to255(b); |
| 35409 |
} |
| 35410 |
return data; |
| 35411 |
}, |
| 35412 |
|
| 35413 |
_convertYcckToCmyk: function convertYcckToCmyk(data) { |
| 35414 |
var Y, Cb, Cr; |
| 35415 |
for (var i = 0, length = data.length; i < length; i += 4) { |
| 35416 |
Y = data[i]; |
| 35417 |
Cb = data[i + 1]; |
| 35418 |
Cr = data[i + 2]; |
| 35419 |
data[i ] = clamp0to255(434.456 - Y - 1.402 * Cr); |
| 35420 |
data[i + 1] = clamp0to255(119.541 - Y + 0.344 * Cb + 0.714 * Cr); |
| 35421 |
data[i + 2] = clamp0to255(481.816 - Y - 1.772 * Cb); |
| 35422 |
// K in data[i + 3] is unchanged |
| 35423 |
} |
| 35424 |
return data; |
| 35425 |
}, |
| 35426 |
|
| 35427 |
_convertCmykToRgb: function convertCmykToRgb(data) { |
| 35428 |
var c, m, y, k; |
| 35429 |
var offset = 0; |
| 35430 |
var min = -255 * 255 * 255; |
| 35431 |
var scale = 1 / 255 / 255; |
| 35432 |
for (var i = 0, length = data.length; i < length; i += 4) { |
| 35433 |
c = data[i]; |
| 35434 |
m = data[i + 1]; |
| 35435 |
y = data[i + 2]; |
| 35436 |
k = data[i + 3]; |
| 35437 |
|
| 35438 |
var r = |
| 35439 |
c * (-4.387332384609988 * c + 54.48615194189176 * m + |
| 35440 |
18.82290502165302 * y + 212.25662451639585 * k - |
| 35441 |
72734.4411664936) + |
| 35442 |
m * (1.7149763477362134 * m - 5.6096736904047315 * y - |
| 35443 |
17.873870861415444 * k - 1401.7366389350734) + |
| 35444 |
y * (-2.5217340131683033 * y - 21.248923337353073 * k + |
| 35445 |
4465.541406466231) - |
| 35446 |
k * (21.86122147463605 * k + 48317.86113160301); |
| 35447 |
var g = |
| 35448 |
c * (8.841041422036149 * c + 60.118027045597366 * m + |
| 35449 |
6.871425592049007 * y + 31.159100130055922 * k - |
| 35450 |
20220.756542821975) + |
| 35451 |
m * (-15.310361306967817 * m + 17.575251261109482 * y + |
| 35452 |
131.35250912493976 * k - 48691.05921601825) + |
| 35453 |
y * (4.444339102852739 * y + 9.8632861493405 * k - |
| 35454 |
6341.191035517494) - |
| 35455 |
k * (20.737325471181034 * k + 47890.15695978492); |
| 35456 |
var b = |
| 35457 |
c * (0.8842522430003296 * c + 8.078677503112928 * m + |
| 35458 |
30.89978309703729 * y - 0.23883238689178934 * k - |
| 35459 |
3616.812083916688) + |
| 35460 |
m * (10.49593273432072 * m + 63.02378494754052 * y + |
| 35461 |
50.606957656360734 * k - 28620.90484698408) + |
| 35462 |
y * (0.03296041114873217 * y + 115.60384449646641 * k - |
| 35463 |
49363.43385999684) - |
| 35464 |
k * (22.33816807309886 * k + 45932.16563550634); |
| 35465 |
|
| 35466 |
data[offset++] = r >= 0 ? 255 : r <= min ? 0 : 255 + r * scale | 0; |
| 35467 |
data[offset++] = g >= 0 ? 255 : g <= min ? 0 : 255 + g * scale | 0; |
| 35468 |
data[offset++] = b >= 0 ? 255 : b <= min ? 0 : 255 + b * scale | 0; |
| 35469 |
} |
| 35470 |
return data; |
| 35471 |
}, |
| 35472 |
|
| 35473 |
getData: function getData(width, height, forceRGBoutput) { |
| 35474 |
if (this.numComponents > 4) { |
| 35475 |
throw 'Unsupported color mode'; |
| 35476 |
} |
| 35477 |
// type of data: Uint8Array(width * height * numComponents) |
| 35478 |
var data = this._getLinearizedBlockData(width, height); |
| 35479 |
|
| 35480 |
if (this.numComponents === 3) { |
| 35481 |
return this._convertYccToRgb(data); |
| 35482 |
} else if (this.numComponents === 4) { |
| 35483 |
if (this._isColorConversionNeeded()) { |
| 35484 |
if (forceRGBoutput) { |
| 35485 |
return this._convertYcckToRgb(data); |
| 35486 |
} else { |
| 35487 |
return this._convertYcckToCmyk(data); |
| 35488 |
} |
| 35489 |
} else if (forceRGBoutput) { |
| 35490 |
return this._convertCmykToRgb(data); |
| 35491 |
} |
| 35492 |
} |
| 35493 |
return data; |
| 35494 |
} |
| 35495 |
}; |
| 35496 |
|
| 35497 |
return constructor; |
| 35498 |
})(); |
| 35499 |
|
| 35500 |
|
| 35501 |
var JpxImage = (function JpxImageClosure() { |
| 35502 |
// Table E.1 |
| 35503 |
var SubbandsGainLog2 = { |
| 35504 |
'LL': 0, |
| 35505 |
'LH': 1, |
| 35506 |
'HL': 1, |
| 35507 |
'HH': 2 |
| 35508 |
}; |
| 35509 |
function JpxImage() { |
| 35510 |
this.failOnCorruptedImage = false; |
| 35511 |
} |
| 35512 |
JpxImage.prototype = { |
| 35513 |
parse: function JpxImage_parse(data) { |
| 35514 |
|
| 35515 |
var head = readUint16(data, 0); |
| 35516 |
// No box header, immediate start of codestream (SOC) |
| 35517 |
if (head === 0xFF4F) { |
| 35518 |
this.parseCodestream(data, 0, data.length); |
| 35519 |
return; |
| 35520 |
} |
| 35521 |
|
| 35522 |
var position = 0, length = data.length; |
| 35523 |
while (position < length) { |
| 35524 |
var headerSize = 8; |
| 35525 |
var lbox = readUint32(data, position); |
| 35526 |
var tbox = readUint32(data, position + 4); |
| 35527 |
position += headerSize; |
| 35528 |
if (lbox === 1) { |
| 35529 |
// XLBox: read UInt64 according to spec. |
| 35530 |
// JavaScript's int precision of 53 bit should be sufficient here. |
| 35531 |
lbox = readUint32(data, position) * 4294967296 + |
| 35532 |
readUint32(data, position + 4); |
| 35533 |
position += 8; |
| 35534 |
headerSize += 8; |
| 35535 |
} |
| 35536 |
if (lbox === 0) { |
| 35537 |
lbox = length - position + headerSize; |
| 35538 |
} |
| 35539 |
if (lbox < headerSize) { |
| 35540 |
throw new Error('JPX Error: Invalid box field size'); |
| 35541 |
} |
| 35542 |
var dataLength = lbox - headerSize; |
| 35543 |
var jumpDataLength = true; |
| 35544 |
switch (tbox) { |
| 35545 |
case 0x6A703268: // 'jp2h' |
| 35546 |
jumpDataLength = false; // parsing child boxes |
| 35547 |
break; |
| 35548 |
case 0x636F6C72: // 'colr' |
| 35549 |
// Colorspaces are not used, the CS from the PDF is used. |
| 35550 |
var method = data[position]; |
| 35551 |
var precedence = data[position + 1]; |
| 35552 |
var approximation = data[position + 2]; |
| 35553 |
if (method === 1) { |
| 35554 |
// enumerated colorspace |
| 35555 |
var colorspace = readUint32(data, position + 3); |
| 35556 |
switch (colorspace) { |
| 35557 |
case 16: // this indicates a sRGB colorspace |
| 35558 |
case 17: // this indicates a grayscale colorspace |
| 35559 |
case 18: // this indicates a YUV colorspace |
| 35560 |
break; |
| 35561 |
default: |
| 35562 |
warn('Unknown colorspace ' + colorspace); |
| 35563 |
break; |
| 35564 |
} |
| 35565 |
} else if (method === 2) { |
| 35566 |
info('ICC profile not supported'); |
| 35567 |
} |
| 35568 |
break; |
| 35569 |
case 0x6A703263: // 'jp2c' |
| 35570 |
this.parseCodestream(data, position, position + dataLength); |
| 35571 |
break; |
| 35572 |
case 0x6A502020: // 'jP\024\024' |
| 35573 |
if (0x0d0a870a !== readUint32(data, position)) { |
| 35574 |
warn('Invalid JP2 signature'); |
| 35575 |
} |
| 35576 |
break; |
| 35577 |
// The following header types are valid but currently not used: |
| 35578 |
case 0x6A501A1A: // 'jP\032\032' |
| 35579 |
case 0x66747970: // 'ftyp' |
| 35580 |
case 0x72726571: // 'rreq' |
| 35581 |
case 0x72657320: // 'res ' |
| 35582 |
case 0x69686472: // 'ihdr' |
| 35583 |
break; |
| 35584 |
default: |
| 35585 |
var headerType = String.fromCharCode((tbox >> 24) & 0xFF, |
| 35586 |
(tbox >> 16) & 0xFF, |
| 35587 |
(tbox >> 8) & 0xFF, |
| 35588 |
tbox & 0xFF); |
| 35589 |
warn('Unsupported header type ' + tbox + ' (' + headerType + ')'); |
| 35590 |
break; |
| 35591 |
} |
| 35592 |
if (jumpDataLength) { |
| 35593 |
position += dataLength; |
| 35594 |
} |
| 35595 |
} |
| 35596 |
}, |
| 35597 |
parseImageProperties: function JpxImage_parseImageProperties(stream) { |
| 35598 |
var newByte = stream.getByte(); |
| 35599 |
while (newByte >= 0) { |
| 35600 |
var oldByte = newByte; |
| 35601 |
newByte = stream.getByte(); |
| 35602 |
var code = (oldByte << 8) | newByte; |
| 35603 |
// Image and tile size (SIZ) |
| 35604 |
if (code === 0xFF51) { |
| 35605 |
stream.skip(4); |
| 35606 |
var Xsiz = stream.getInt32() >>> 0; // Byte 4 |
| 35607 |
var Ysiz = stream.getInt32() >>> 0; // Byte 8 |
| 35608 |
var XOsiz = stream.getInt32() >>> 0; // Byte 12 |
| 35609 |
var YOsiz = stream.getInt32() >>> 0; // Byte 16 |
| 35610 |
stream.skip(16); |
| 35611 |
var Csiz = stream.getUint16(); // Byte 36 |
| 35612 |
this.width = Xsiz - XOsiz; |
| 35613 |
this.height = Ysiz - YOsiz; |
| 35614 |
this.componentsCount = Csiz; |
| 35615 |
// Results are always returned as Uint8Arrays |
| 35616 |
this.bitsPerComponent = 8; |
| 35617 |
return; |
| 35618 |
} |
| 35619 |
} |
| 35620 |
throw new Error('JPX Error: No size marker found in JPX stream'); |
| 35621 |
}, |
| 35622 |
parseCodestream: function JpxImage_parseCodestream(data, start, end) { |
| 35623 |
var context = {}; |
| 35624 |
try { |
| 35625 |
var doNotRecover = false; |
| 35626 |
var position = start; |
| 35627 |
while (position + 1 < end) { |
| 35628 |
var code = readUint16(data, position); |
| 35629 |
position += 2; |
| 35630 |
|
| 35631 |
var length = 0, j, sqcd, spqcds, spqcdSize, scalarExpounded, tile; |
| 35632 |
switch (code) { |
| 35633 |
case 0xFF4F: // Start of codestream (SOC) |
| 35634 |
context.mainHeader = true; |
| 35635 |
break; |
| 35636 |
case 0xFFD9: // End of codestream (EOC) |
| 35637 |
break; |
| 35638 |
case 0xFF51: // Image and tile size (SIZ) |
| 35639 |
length = readUint16(data, position); |
| 35640 |
var siz = {}; |
| 35641 |
siz.Xsiz = readUint32(data, position + 4); |
| 35642 |
siz.Ysiz = readUint32(data, position + 8); |
| 35643 |
siz.XOsiz = readUint32(data, position + 12); |
| 35644 |
siz.YOsiz = readUint32(data, position + 16); |
| 35645 |
siz.XTsiz = readUint32(data, position + 20); |
| 35646 |
siz.YTsiz = readUint32(data, position + 24); |
| 35647 |
siz.XTOsiz = readUint32(data, position + 28); |
| 35648 |
siz.YTOsiz = readUint32(data, position + 32); |
| 35649 |
var componentsCount = readUint16(data, position + 36); |
| 35650 |
siz.Csiz = componentsCount; |
| 35651 |
var components = []; |
| 35652 |
j = position + 38; |
| 35653 |
for (var i = 0; i < componentsCount; i++) { |
| 35654 |
var component = { |
| 35655 |
precision: (data[j] & 0x7F) + 1, |
| 35656 |
isSigned: !!(data[j] & 0x80), |
| 35657 |
XRsiz: data[j + 1], |
| 35658 |
YRsiz: data[j + 1] |
| 35659 |
}; |
| 35660 |
calculateComponentDimensions(component, siz); |
| 35661 |
components.push(component); |
| 35662 |
} |
| 35663 |
context.SIZ = siz; |
| 35664 |
context.components = components; |
| 35665 |
calculateTileGrids(context, components); |
| 35666 |
context.QCC = []; |
| 35667 |
context.COC = []; |
| 35668 |
break; |
| 35669 |
case 0xFF5C: // Quantization default (QCD) |
| 35670 |
length = readUint16(data, position); |
| 35671 |
var qcd = {}; |
| 35672 |
j = position + 2; |
| 35673 |
sqcd = data[j++]; |
| 35674 |
switch (sqcd & 0x1F) { |
| 35675 |
case 0: |
| 35676 |
spqcdSize = 8; |
| 35677 |
scalarExpounded = true; |
| 35678 |
break; |
| 35679 |
case 1: |
| 35680 |
spqcdSize = 16; |
| 35681 |
scalarExpounded = false; |
| 35682 |
break; |
| 35683 |
case 2: |
| 35684 |
spqcdSize = 16; |
| 35685 |
scalarExpounded = true; |
| 35686 |
break; |
| 35687 |
default: |
| 35688 |
throw new Error('JPX Error: Invalid SQcd value ' + sqcd); |
| 35689 |
} |
| 35690 |
qcd.noQuantization = (spqcdSize === 8); |
| 35691 |
qcd.scalarExpounded = scalarExpounded; |
| 35692 |
qcd.guardBits = sqcd >> 5; |
| 35693 |
spqcds = []; |
| 35694 |
while (j < length + position) { |
| 35695 |
var spqcd = {}; |
| 35696 |
if (spqcdSize === 8) { |
| 35697 |
spqcd.epsilon = data[j++] >> 3; |
| 35698 |
spqcd.mu = 0; |
| 35699 |
} else { |
| 35700 |
spqcd.epsilon = data[j] >> 3; |
| 35701 |
spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1]; |
| 35702 |
j += 2; |
| 35703 |
} |
| 35704 |
spqcds.push(spqcd); |
| 35705 |
} |
| 35706 |
qcd.SPqcds = spqcds; |
| 35707 |
if (context.mainHeader) { |
| 35708 |
context.QCD = qcd; |
| 35709 |
} else { |
| 35710 |
context.currentTile.QCD = qcd; |
| 35711 |
context.currentTile.QCC = []; |
| 35712 |
} |
| 35713 |
break; |
| 35714 |
case 0xFF5D: // Quantization component (QCC) |
| 35715 |
length = readUint16(data, position); |
| 35716 |
var qcc = {}; |
| 35717 |
j = position + 2; |
| 35718 |
var cqcc; |
| 35719 |
if (context.SIZ.Csiz < 257) { |
| 35720 |
cqcc = data[j++]; |
| 35721 |
} else { |
| 35722 |
cqcc = readUint16(data, j); |
| 35723 |
j += 2; |
| 35724 |
} |
| 35725 |
sqcd = data[j++]; |
| 35726 |
switch (sqcd & 0x1F) { |
| 35727 |
case 0: |
| 35728 |
spqcdSize = 8; |
| 35729 |
scalarExpounded = true; |
| 35730 |
break; |
| 35731 |
case 1: |
| 35732 |
spqcdSize = 16; |
| 35733 |
scalarExpounded = false; |
| 35734 |
break; |
| 35735 |
case 2: |
| 35736 |
spqcdSize = 16; |
| 35737 |
scalarExpounded = true; |
| 35738 |
break; |
| 35739 |
default: |
| 35740 |
throw new Error('JPX Error: Invalid SQcd value ' + sqcd); |
| 35741 |
} |
| 35742 |
qcc.noQuantization = (spqcdSize === 8); |
| 35743 |
qcc.scalarExpounded = scalarExpounded; |
| 35744 |
qcc.guardBits = sqcd >> 5; |
| 35745 |
spqcds = []; |
| 35746 |
while (j < (length + position)) { |
| 35747 |
spqcd = {}; |
| 35748 |
if (spqcdSize === 8) { |
| 35749 |
spqcd.epsilon = data[j++] >> 3; |
| 35750 |
spqcd.mu = 0; |
| 35751 |
} else { |
| 35752 |
spqcd.epsilon = data[j] >> 3; |
| 35753 |
spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1]; |
| 35754 |
j += 2; |
| 35755 |
} |
| 35756 |
spqcds.push(spqcd); |
| 35757 |
} |
| 35758 |
qcc.SPqcds = spqcds; |
| 35759 |
if (context.mainHeader) { |
| 35760 |
context.QCC[cqcc] = qcc; |
| 35761 |
} else { |
| 35762 |
context.currentTile.QCC[cqcc] = qcc; |
| 35763 |
} |
| 35764 |
break; |
| 35765 |
case 0xFF52: // Coding style default (COD) |
| 35766 |
length = readUint16(data, position); |
| 35767 |
var cod = {}; |
| 35768 |
j = position + 2; |
| 35769 |
var scod = data[j++]; |
| 35770 |
cod.entropyCoderWithCustomPrecincts = !!(scod & 1); |
| 35771 |
cod.sopMarkerUsed = !!(scod & 2); |
| 35772 |
cod.ephMarkerUsed = !!(scod & 4); |
| 35773 |
cod.progressionOrder = data[j++]; |
| 35774 |
cod.layersCount = readUint16(data, j); |
| 35775 |
j += 2; |
| 35776 |
cod.multipleComponentTransform = data[j++]; |
| 35777 |
|
| 35778 |
cod.decompositionLevelsCount = data[j++]; |
| 35779 |
cod.xcb = (data[j++] & 0xF) + 2; |
| 35780 |
cod.ycb = (data[j++] & 0xF) + 2; |
| 35781 |
var blockStyle = data[j++]; |
| 35782 |
cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1); |
| 35783 |
cod.resetContextProbabilities = !!(blockStyle & 2); |
| 35784 |
cod.terminationOnEachCodingPass = !!(blockStyle & 4); |
| 35785 |
cod.verticalyStripe = !!(blockStyle & 8); |
| 35786 |
cod.predictableTermination = !!(blockStyle & 16); |
| 35787 |
cod.segmentationSymbolUsed = !!(blockStyle & 32); |
| 35788 |
cod.reversibleTransformation = data[j++]; |
| 35789 |
if (cod.entropyCoderWithCustomPrecincts) { |
| 35790 |
var precinctsSizes = []; |
| 35791 |
while (j < length + position) { |
| 35792 |
var precinctsSize = data[j++]; |
| 35793 |
precinctsSizes.push({ |
| 35794 |
PPx: precinctsSize & 0xF, |
| 35795 |
PPy: precinctsSize >> 4 |
| 35796 |
}); |
| 35797 |
} |
| 35798 |
cod.precinctsSizes = precinctsSizes; |
| 35799 |
} |
| 35800 |
var unsupported = []; |
| 35801 |
if (cod.selectiveArithmeticCodingBypass) { |
| 35802 |
unsupported.push('selectiveArithmeticCodingBypass'); |
| 35803 |
} |
| 35804 |
if (cod.resetContextProbabilities) { |
| 35805 |
unsupported.push('resetContextProbabilities'); |
| 35806 |
} |
| 35807 |
if (cod.terminationOnEachCodingPass) { |
| 35808 |
unsupported.push('terminationOnEachCodingPass'); |
| 35809 |
} |
| 35810 |
if (cod.verticalyStripe) { |
| 35811 |
unsupported.push('verticalyStripe'); |
| 35812 |
} |
| 35813 |
if (cod.predictableTermination) { |
| 35814 |
unsupported.push('predictableTermination'); |
| 35815 |
} |
| 35816 |
if (unsupported.length > 0) { |
| 35817 |
doNotRecover = true; |
| 35818 |
throw new Error('JPX Error: Unsupported COD options (' + |
| 35819 |
unsupported.join(', ') + ')'); |
| 35820 |
} |
| 35821 |
if (context.mainHeader) { |
| 35822 |
context.COD = cod; |
| 35823 |
} else { |
| 35824 |
context.currentTile.COD = cod; |
| 35825 |
context.currentTile.COC = []; |
| 35826 |
} |
| 35827 |
break; |
| 35828 |
case 0xFF90: // Start of tile-part (SOT) |
| 35829 |
length = readUint16(data, position); |
| 35830 |
tile = {}; |
| 35831 |
tile.index = readUint16(data, position + 2); |
| 35832 |
tile.length = readUint32(data, position + 4); |
| 35833 |
tile.dataEnd = tile.length + position - 2; |
| 35834 |
tile.partIndex = data[position + 8]; |
| 35835 |
tile.partsCount = data[position + 9]; |
| 35836 |
|
| 35837 |
context.mainHeader = false; |
| 35838 |
if (tile.partIndex === 0) { |
| 35839 |
// reset component specific settings |
| 35840 |
tile.COD = context.COD; |
| 35841 |
tile.COC = context.COC.slice(0); // clone of the global COC |
| 35842 |
tile.QCD = context.QCD; |
| 35843 |
tile.QCC = context.QCC.slice(0); // clone of the global COC |
| 35844 |
} |
| 35845 |
context.currentTile = tile; |
| 35846 |
break; |
| 35847 |
case 0xFF93: // Start of data (SOD) |
| 35848 |
tile = context.currentTile; |
| 35849 |
if (tile.partIndex === 0) { |
| 35850 |
initializeTile(context, tile.index); |
| 35851 |
buildPackets(context); |
| 35852 |
} |
| 35853 |
|
| 35854 |
// moving to the end of the data |
| 35855 |
length = tile.dataEnd - position; |
| 35856 |
parseTilePackets(context, data, position, length); |
| 35857 |
break; |
| 35858 |
case 0xFF55: // Tile-part lengths, main header (TLM) |
| 35859 |
case 0xFF57: // Packet length, main header (PLM) |
| 35860 |
case 0xFF58: // Packet length, tile-part header (PLT) |
| 35861 |
case 0xFF64: // Comment (COM) |
| 35862 |
length = readUint16(data, position); |
| 35863 |
// skipping content |
| 35864 |
break; |
| 35865 |
case 0xFF53: // Coding style component (COC) |
| 35866 |
throw new Error('JPX Error: Codestream code 0xFF53 (COC) is ' + |
| 35867 |
'not implemented'); |
| 35868 |
default: |
| 35869 |
throw new Error('JPX Error: Unknown codestream code: ' + |
| 35870 |
code.toString(16)); |
| 35871 |
} |
| 35872 |
position += length; |
| 35873 |
} |
| 35874 |
} catch (e) { |
| 35875 |
if (doNotRecover || this.failOnCorruptedImage) { |
| 35876 |
throw e; |
| 35877 |
} else { |
| 35878 |
warn('Trying to recover from ' + e.message); |
| 35879 |
} |
| 35880 |
} |
| 35881 |
this.tiles = transformComponents(context); |
| 35882 |
this.width = context.SIZ.Xsiz - context.SIZ.XOsiz; |
| 35883 |
this.height = context.SIZ.Ysiz - context.SIZ.YOsiz; |
| 35884 |
this.componentsCount = context.SIZ.Csiz; |
| 35885 |
} |
| 35886 |
}; |
| 35887 |
function calculateComponentDimensions(component, siz) { |
| 35888 |
// Section B.2 Component mapping |
| 35889 |
component.x0 = Math.ceil(siz.XOsiz / component.XRsiz); |
| 35890 |
component.x1 = Math.ceil(siz.Xsiz / component.XRsiz); |
| 35891 |
component.y0 = Math.ceil(siz.YOsiz / component.YRsiz); |
| 35892 |
component.y1 = Math.ceil(siz.Ysiz / component.YRsiz); |
| 35893 |
component.width = component.x1 - component.x0; |
| 35894 |
component.height = component.y1 - component.y0; |
| 35895 |
} |
| 35896 |
function calculateTileGrids(context, components) { |
| 35897 |
var siz = context.SIZ; |
| 35898 |
// Section B.3 Division into tile and tile-components |
| 35899 |
var tile, tiles = []; |
| 35900 |
var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz); |
| 35901 |
var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz); |
| 35902 |
for (var q = 0; q < numYtiles; q++) { |
| 35903 |
for (var p = 0; p < numXtiles; p++) { |
| 35904 |
tile = {}; |
| 35905 |
tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz); |
| 35906 |
tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz); |
| 35907 |
tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz); |
| 35908 |
tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz); |
| 35909 |
tile.width = tile.tx1 - tile.tx0; |
| 35910 |
tile.height = tile.ty1 - tile.ty0; |
| 35911 |
tile.components = []; |
| 35912 |
tiles.push(tile); |
| 35913 |
} |
| 35914 |
} |
| 35915 |
context.tiles = tiles; |
| 35916 |
|
| 35917 |
var componentsCount = siz.Csiz; |
| 35918 |
for (var i = 0, ii = componentsCount; i < ii; i++) { |
| 35919 |
var component = components[i]; |
| 35920 |
for (var j = 0, jj = tiles.length; j < jj; j++) { |
| 35921 |
var tileComponent = {}; |
| 35922 |
tile = tiles[j]; |
| 35923 |
tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz); |
| 35924 |
tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz); |
| 35925 |
tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz); |
| 35926 |
tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz); |
| 35927 |
tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0; |
| 35928 |
tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0; |
| 35929 |
tile.components[i] = tileComponent; |
| 35930 |
} |
| 35931 |
} |
| 35932 |
} |
| 35933 |
function getBlocksDimensions(context, component, r) { |
| 35934 |
var codOrCoc = component.codingStyleParameters; |
| 35935 |
var result = {}; |
| 35936 |
if (!codOrCoc.entropyCoderWithCustomPrecincts) { |
| 35937 |
result.PPx = 15; |
| 35938 |
result.PPy = 15; |
| 35939 |
} else { |
| 35940 |
result.PPx = codOrCoc.precinctsSizes[r].PPx; |
| 35941 |
result.PPy = codOrCoc.precinctsSizes[r].PPy; |
| 35942 |
} |
| 35943 |
// calculate codeblock size as described in section B.7 |
| 35944 |
result.xcb_ = (r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : |
| 35945 |
Math.min(codOrCoc.xcb, result.PPx)); |
| 35946 |
result.ycb_ = (r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : |
| 35947 |
Math.min(codOrCoc.ycb, result.PPy)); |
| 35948 |
return result; |
| 35949 |
} |
| 35950 |
function buildPrecincts(context, resolution, dimensions) { |
| 35951 |
// Section B.6 Division resolution to precincts |
| 35952 |
var precinctWidth = 1 << dimensions.PPx; |
| 35953 |
var precinctHeight = 1 << dimensions.PPy; |
| 35954 |
// Jasper introduces codeblock groups for mapping each subband codeblocks |
| 35955 |
// to precincts. Precinct partition divides a resolution according to width |
| 35956 |
// and height parameters. The subband that belongs to the resolution level |
| 35957 |
// has a different size than the level, unless it is the zero resolution. |
| 35958 |
|
| 35959 |
// From Jasper documentation: jpeg2000.pdf, section K: Tier-2 coding: |
| 35960 |
// The precinct partitioning for a particular subband is derived from a |
| 35961 |
// partitioning of its parent LL band (i.e., the LL band at the next higher |
| 35962 |
// resolution level)... The LL band associated with each resolution level is |
| 35963 |
// divided into precincts... Each of the resulting precinct regions is then |
| 35964 |
// mapped into its child subbands (if any) at the next lower resolution |
| 35965 |
// level. This is accomplished by using the coordinate transformation |
| 35966 |
// (u, v) = (ceil(x/2), ceil(y/2)) where (x, y) and (u, v) are the |
| 35967 |
// coordinates of a point in the LL band and child subband, respectively. |
| 35968 |
var isZeroRes = resolution.resLevel === 0; |
| 35969 |
var precinctWidthInSubband = 1 << (dimensions.PPx + (isZeroRes ? 0 : -1)); |
| 35970 |
var precinctHeightInSubband = 1 << (dimensions.PPy + (isZeroRes ? 0 : -1)); |
| 35971 |
var numprecinctswide = (resolution.trx1 > resolution.trx0 ? |
| 35972 |
Math.ceil(resolution.trx1 / precinctWidth) - |
| 35973 |
Math.floor(resolution.trx0 / precinctWidth) : 0); |
| 35974 |
var numprecinctshigh = (resolution.try1 > resolution.try0 ? |
| 35975 |
Math.ceil(resolution.try1 / precinctHeight) - |
| 35976 |
Math.floor(resolution.try0 / precinctHeight) : 0); |
| 35977 |
var numprecincts = numprecinctswide * numprecinctshigh; |
| 35978 |
|
| 35979 |
resolution.precinctParameters = { |
| 35980 |
precinctWidth: precinctWidth, |
| 35981 |
precinctHeight: precinctHeight, |
| 35982 |
numprecinctswide: numprecinctswide, |
| 35983 |
numprecinctshigh: numprecinctshigh, |
| 35984 |
numprecincts: numprecincts, |
| 35985 |
precinctWidthInSubband: precinctWidthInSubband, |
| 35986 |
precinctHeightInSubband: precinctHeightInSubband |
| 35987 |
}; |
| 35988 |
} |
| 35989 |
function buildCodeblocks(context, subband, dimensions) { |
| 35990 |
// Section B.7 Division sub-band into code-blocks |
| 35991 |
var xcb_ = dimensions.xcb_; |
| 35992 |
var ycb_ = dimensions.ycb_; |
| 35993 |
var codeblockWidth = 1 << xcb_; |
| 35994 |
var codeblockHeight = 1 << ycb_; |
| 35995 |
var cbx0 = subband.tbx0 >> xcb_; |
| 35996 |
var cby0 = subband.tby0 >> ycb_; |
| 35997 |
var cbx1 = (subband.tbx1 + codeblockWidth - 1) >> xcb_; |
| 35998 |
var cby1 = (subband.tby1 + codeblockHeight - 1) >> ycb_; |
| 35999 |
var precinctParameters = subband.resolution.precinctParameters; |
| 36000 |
var codeblocks = []; |
| 36001 |
var precincts = []; |
| 36002 |
var i, j, codeblock, precinctNumber; |
| 36003 |
for (j = cby0; j < cby1; j++) { |
| 36004 |
for (i = cbx0; i < cbx1; i++) { |
| 36005 |
codeblock = { |
| 36006 |
cbx: i, |
| 36007 |
cby: j, |
| 36008 |
tbx0: codeblockWidth * i, |
| 36009 |
tby0: codeblockHeight * j, |
| 36010 |
tbx1: codeblockWidth * (i + 1), |
| 36011 |
tby1: codeblockHeight * (j + 1) |
| 36012 |
}; |
| 36013 |
|
| 36014 |
codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0); |
| 36015 |
codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0); |
| 36016 |
codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1); |
| 36017 |
codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1); |
| 36018 |
|
| 36019 |
// Calculate precinct number for this codeblock, codeblock position |
| 36020 |
// should be relative to its subband, use actual dimension and position |
| 36021 |
// See comment about codeblock group width and height |
| 36022 |
var pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / |
| 36023 |
precinctParameters.precinctWidthInSubband); |
| 36024 |
var pj = Math.floor((codeblock.tby0_ - subband.tby0) / |
| 36025 |
precinctParameters.precinctHeightInSubband); |
| 36026 |
precinctNumber = pi + (pj * precinctParameters.numprecinctswide); |
| 36027 |
|
| 36028 |
codeblock.precinctNumber = precinctNumber; |
| 36029 |
codeblock.subbandType = subband.type; |
| 36030 |
codeblock.Lblock = 3; |
| 36031 |
|
| 36032 |
if (codeblock.tbx1_ <= codeblock.tbx0_ || |
| 36033 |
codeblock.tby1_ <= codeblock.tby0_) { |
| 36034 |
continue; |
| 36035 |
} |
| 36036 |
codeblocks.push(codeblock); |
| 36037 |
// building precinct for the sub-band |
| 36038 |
var precinct = precincts[precinctNumber]; |
| 36039 |
if (precinct !== undefined) { |
| 36040 |
if (i < precinct.cbxMin) { |
| 36041 |
precinct.cbxMin = i; |
| 36042 |
} else if (i > precinct.cbxMax) { |
| 36043 |
precinct.cbxMax = i; |
| 36044 |
} |
| 36045 |
if (j < precinct.cbyMin) { |
| 36046 |
precinct.cbxMin = j; |
| 36047 |
} else if (j > precinct.cbyMax) { |
| 36048 |
precinct.cbyMax = j; |
| 36049 |
} |
| 36050 |
} else { |
| 36051 |
precincts[precinctNumber] = precinct = { |
| 36052 |
cbxMin: i, |
| 36053 |
cbyMin: j, |
| 36054 |
cbxMax: i, |
| 36055 |
cbyMax: j |
| 36056 |
}; |
| 36057 |
} |
| 36058 |
codeblock.precinct = precinct; |
| 36059 |
} |
| 36060 |
} |
| 36061 |
subband.codeblockParameters = { |
| 36062 |
codeblockWidth: xcb_, |
| 36063 |
codeblockHeight: ycb_, |
| 36064 |
numcodeblockwide: cbx1 - cbx0 + 1, |
| 36065 |
numcodeblockhigh: cby1 - cby0 + 1 |
| 36066 |
}; |
| 36067 |
subband.codeblocks = codeblocks; |
| 36068 |
subband.precincts = precincts; |
| 36069 |
} |
| 36070 |
function createPacket(resolution, precinctNumber, layerNumber) { |
| 36071 |
var precinctCodeblocks = []; |
| 36072 |
// Section B.10.8 Order of info in packet |
| 36073 |
var subbands = resolution.subbands; |
| 36074 |
// sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence |
| 36075 |
for (var i = 0, ii = subbands.length; i < ii; i++) { |
| 36076 |
var subband = subbands[i]; |
| 36077 |
var codeblocks = subband.codeblocks; |
| 36078 |
for (var j = 0, jj = codeblocks.length; j < jj; j++) { |
| 36079 |
var codeblock = codeblocks[j]; |
| 36080 |
if (codeblock.precinctNumber !== precinctNumber) { |
| 36081 |
continue; |
| 36082 |
} |
| 36083 |
precinctCodeblocks.push(codeblock); |
| 36084 |
} |
| 36085 |
} |
| 36086 |
return { |
| 36087 |
layerNumber: layerNumber, |
| 36088 |
codeblocks: precinctCodeblocks |
| 36089 |
}; |
| 36090 |
} |
| 36091 |
function LayerResolutionComponentPositionIterator(context) { |
| 36092 |
var siz = context.SIZ; |
| 36093 |
var tileIndex = context.currentTile.index; |
| 36094 |
var tile = context.tiles[tileIndex]; |
| 36095 |
var layersCount = tile.codingStyleDefaultParameters.layersCount; |
| 36096 |
var componentsCount = siz.Csiz; |
| 36097 |
var maxDecompositionLevelsCount = 0; |
| 36098 |
for (var q = 0; q < componentsCount; q++) { |
| 36099 |
maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, |
| 36100 |
tile.components[q].codingStyleParameters.decompositionLevelsCount); |
| 36101 |
} |
| 36102 |
|
| 36103 |
var l = 0, r = 0, i = 0, k = 0; |
| 36104 |
|
| 36105 |
this.nextPacket = function JpxImage_nextPacket() { |
| 36106 |
// Section B.12.1.1 Layer-resolution-component-position |
| 36107 |
for (; l < layersCount; l++) { |
| 36108 |
for (; r <= maxDecompositionLevelsCount; r++) { |
| 36109 |
for (; i < componentsCount; i++) { |
| 36110 |
var component = tile.components[i]; |
| 36111 |
if (r > component.codingStyleParameters.decompositionLevelsCount) { |
| 36112 |
continue; |
| 36113 |
} |
| 36114 |
|
| 36115 |
var resolution = component.resolutions[r]; |
| 36116 |
var numprecincts = resolution.precinctParameters.numprecincts; |
| 36117 |
for (; k < numprecincts;) { |
| 36118 |
var packet = createPacket(resolution, k, l); |
| 36119 |
k++; |
| 36120 |
return packet; |
| 36121 |
} |
| 36122 |
k = 0; |
| 36123 |
} |
| 36124 |
i = 0; |
| 36125 |
} |
| 36126 |
r = 0; |
| 36127 |
} |
| 36128 |
throw new Error('JPX Error: Out of packets'); |
| 36129 |
}; |
| 36130 |
} |
| 36131 |
function ResolutionLayerComponentPositionIterator(context) { |
| 36132 |
var siz = context.SIZ; |
| 36133 |
var tileIndex = context.currentTile.index; |
| 36134 |
var tile = context.tiles[tileIndex]; |
| 36135 |
var layersCount = tile.codingStyleDefaultParameters.layersCount; |
| 36136 |
var componentsCount = siz.Csiz; |
| 36137 |
var maxDecompositionLevelsCount = 0; |
| 36138 |
for (var q = 0; q < componentsCount; q++) { |
| 36139 |
maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, |
| 36140 |
tile.components[q].codingStyleParameters.decompositionLevelsCount); |
| 36141 |
} |
| 36142 |
|
| 36143 |
var r = 0, l = 0, i = 0, k = 0; |
| 36144 |
|
| 36145 |
this.nextPacket = function JpxImage_nextPacket() { |
| 36146 |
// Section B.12.1.2 Resolution-layer-component-position |
| 36147 |
for (; r <= maxDecompositionLevelsCount; r++) { |
| 36148 |
for (; l < layersCount; l++) { |
| 36149 |
for (; i < componentsCount; i++) { |
| 36150 |
var component = tile.components[i]; |
| 36151 |
if (r > component.codingStyleParameters.decompositionLevelsCount) { |
| 36152 |
continue; |
| 36153 |
} |
| 36154 |
|
| 36155 |
var resolution = component.resolutions[r]; |
| 36156 |
var numprecincts = resolution.precinctParameters.numprecincts; |
| 36157 |
for (; k < numprecincts;) { |
| 36158 |
var packet = createPacket(resolution, k, l); |
| 36159 |
k++; |
| 36160 |
return packet; |
| 36161 |
} |
| 36162 |
k = 0; |
| 36163 |
} |
| 36164 |
i = 0; |
| 36165 |
} |
| 36166 |
l = 0; |
| 36167 |
} |
| 36168 |
throw new Error('JPX Error: Out of packets'); |
| 36169 |
}; |
| 36170 |
} |
| 36171 |
function ResolutionPositionComponentLayerIterator(context) { |
| 36172 |
var siz = context.SIZ; |
| 36173 |
var tileIndex = context.currentTile.index; |
| 36174 |
var tile = context.tiles[tileIndex]; |
| 36175 |
var layersCount = tile.codingStyleDefaultParameters.layersCount; |
| 36176 |
var componentsCount = siz.Csiz; |
| 36177 |
var l, r, c, p; |
| 36178 |
var maxDecompositionLevelsCount = 0; |
| 36179 |
for (c = 0; c < componentsCount; c++) { |
| 36180 |
var component = tile.components[c]; |
| 36181 |
maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, |
| 36182 |
component.codingStyleParameters.decompositionLevelsCount); |
| 36183 |
} |
| 36184 |
var maxNumPrecinctsInLevel = new Int32Array( |
| 36185 |
maxDecompositionLevelsCount + 1); |
| 36186 |
for (r = 0; r <= maxDecompositionLevelsCount; ++r) { |
| 36187 |
var maxNumPrecincts = 0; |
| 36188 |
for (c = 0; c < componentsCount; ++c) { |
| 36189 |
var resolutions = tile.components[c].resolutions; |
| 36190 |
if (r < resolutions.length) { |
| 36191 |
maxNumPrecincts = Math.max(maxNumPrecincts, |
| 36192 |
resolutions[r].precinctParameters.numprecincts); |
| 36193 |
} |
| 36194 |
} |
| 36195 |
maxNumPrecinctsInLevel[r] = maxNumPrecincts; |
| 36196 |
} |
| 36197 |
l = 0; |
| 36198 |
r = 0; |
| 36199 |
c = 0; |
| 36200 |
p = 0; |
| 36201 |
|
| 36202 |
this.nextPacket = function JpxImage_nextPacket() { |
| 36203 |
// Section B.12.1.3 Resolution-position-component-layer |
| 36204 |
for (; r <= maxDecompositionLevelsCount; r++) { |
| 36205 |
for (; p < maxNumPrecinctsInLevel[r]; p++) { |
| 36206 |
for (; c < componentsCount; c++) { |
| 36207 |
var component = tile.components[c]; |
| 36208 |
if (r > component.codingStyleParameters.decompositionLevelsCount) { |
| 36209 |
continue; |
| 36210 |
} |
| 36211 |
var resolution = component.resolutions[r]; |
| 36212 |
var numprecincts = resolution.precinctParameters.numprecincts; |
| 36213 |
if (p >= numprecincts) { |
| 36214 |
continue; |
| 36215 |
} |
| 36216 |
for (; l < layersCount;) { |
| 36217 |
var packet = createPacket(resolution, p, l); |
| 36218 |
l++; |
| 36219 |
return packet; |
| 36220 |
} |
| 36221 |
l = 0; |
| 36222 |
} |
| 36223 |
c = 0; |
| 36224 |
} |
| 36225 |
p = 0; |
| 36226 |
} |
| 36227 |
throw new Error('JPX Error: Out of packets'); |
| 36228 |
}; |
| 36229 |
} |
| 36230 |
function PositionComponentResolutionLayerIterator(context) { |
| 36231 |
var siz = context.SIZ; |
| 36232 |
var tileIndex = context.currentTile.index; |
| 36233 |
var tile = context.tiles[tileIndex]; |
| 36234 |
var layersCount = tile.codingStyleDefaultParameters.layersCount; |
| 36235 |
var componentsCount = siz.Csiz; |
| 36236 |
var precinctsSizes = getPrecinctSizesInImageScale(tile); |
| 36237 |
var precinctsIterationSizes = precinctsSizes; |
| 36238 |
var l = 0, r = 0, c = 0, px = 0, py = 0; |
| 36239 |
|
| 36240 |
this.nextPacket = function JpxImage_nextPacket() { |
| 36241 |
// Section B.12.1.4 Position-component-resolution-layer |
| 36242 |
for (; py < precinctsIterationSizes.maxNumHigh; py++) { |
| 36243 |
for (; px < precinctsIterationSizes.maxNumWide; px++) { |
| 36244 |
for (; c < componentsCount; c++) { |
| 36245 |
var component = tile.components[c]; |
| 36246 |
var decompositionLevelsCount = |
| 36247 |
component.codingStyleParameters.decompositionLevelsCount; |
| 36248 |
for (; r <= decompositionLevelsCount; r++) { |
| 36249 |
var resolution = component.resolutions[r]; |
| 36250 |
var sizeInImageScale = |
| 36251 |
precinctsSizes.components[c].resolutions[r]; |
| 36252 |
var k = getPrecinctIndexIfExist( |
| 36253 |
px, |
| 36254 |
py, |
| 36255 |
sizeInImageScale, |
| 36256 |
precinctsIterationSizes, |
| 36257 |
resolution); |
| 36258 |
if (k === null) { |
| 36259 |
continue; |
| 36260 |
} |
| 36261 |
for (; l < layersCount;) { |
| 36262 |
var packet = createPacket(resolution, k, l); |
| 36263 |
l++; |
| 36264 |
return packet; |
| 36265 |
} |
| 36266 |
l = 0; |
| 36267 |
} |
| 36268 |
r = 0; |
| 36269 |
} |
| 36270 |
c = 0; |
| 36271 |
} |
| 36272 |
px = 0; |
| 36273 |
} |
| 36274 |
throw new Error('JPX Error: Out of packets'); |
| 36275 |
}; |
| 36276 |
} |
| 36277 |
function ComponentPositionResolutionLayerIterator(context) { |
| 36278 |
var siz = context.SIZ; |
| 36279 |
var tileIndex = context.currentTile.index; |
| 36280 |
var tile = context.tiles[tileIndex]; |
| 36281 |
var layersCount = tile.codingStyleDefaultParameters.layersCount; |
| 36282 |
var componentsCount = siz.Csiz; |
| 36283 |
var precinctsSizes = getPrecinctSizesInImageScale(tile); |
| 36284 |
var l = 0, r = 0, c = 0, px = 0, py = 0; |
| 36285 |
|
| 36286 |
this.nextPacket = function JpxImage_nextPacket() { |
| 36287 |
// Section B.12.1.5 Component-position-resolution-layer |
| 36288 |
for (; c < componentsCount; ++c) { |
| 36289 |
var component = tile.components[c]; |
| 36290 |
var precinctsIterationSizes = precinctsSizes.components[c]; |
| 36291 |
var decompositionLevelsCount = |
| 36292 |
component.codingStyleParameters.decompositionLevelsCount; |
| 36293 |
for (; py < precinctsIterationSizes.maxNumHigh; py++) { |
| 36294 |
for (; px < precinctsIterationSizes.maxNumWide; px++) { |
| 36295 |
for (; r <= decompositionLevelsCount; r++) { |
| 36296 |
var resolution = component.resolutions[r]; |
| 36297 |
var sizeInImageScale = precinctsIterationSizes.resolutions[r]; |
| 36298 |
var k = getPrecinctIndexIfExist( |
| 36299 |
px, |
| 36300 |
py, |
| 36301 |
sizeInImageScale, |
| 36302 |
precinctsIterationSizes, |
| 36303 |
resolution); |
| 36304 |
if (k === null) { |
| 36305 |
continue; |
| 36306 |
} |
| 36307 |
for (; l < layersCount;) { |
| 36308 |
var packet = createPacket(resolution, k, l); |
| 36309 |
l++; |
| 36310 |
return packet; |
| 36311 |
} |
| 36312 |
l = 0; |
| 36313 |
} |
| 36314 |
r = 0; |
| 36315 |
} |
| 36316 |
px = 0; |
| 36317 |
} |
| 36318 |
py = 0; |
| 36319 |
} |
| 36320 |
throw new Error('JPX Error: Out of packets'); |
| 36321 |
}; |
| 36322 |
} |
| 36323 |
function getPrecinctIndexIfExist( |
| 36324 |
pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) { |
| 36325 |
var posX = pxIndex * precinctIterationSizes.minWidth; |
| 36326 |
var posY = pyIndex * precinctIterationSizes.minHeight; |
| 36327 |
if (posX % sizeInImageScale.width !== 0 || |
| 36328 |
posY % sizeInImageScale.height !== 0) { |
| 36329 |
return null; |
| 36330 |
} |
| 36331 |
var startPrecinctRowIndex = |
| 36332 |
(posY / sizeInImageScale.width) * |
| 36333 |
resolution.precinctParameters.numprecinctswide; |
| 36334 |
return (posX / sizeInImageScale.height) + startPrecinctRowIndex; |
| 36335 |
} |
| 36336 |
function getPrecinctSizesInImageScale(tile) { |
| 36337 |
var componentsCount = tile.components.length; |
| 36338 |
var minWidth = Number.MAX_VALUE; |
| 36339 |
var minHeight = Number.MAX_VALUE; |
| 36340 |
var maxNumWide = 0; |
| 36341 |
var maxNumHigh = 0; |
| 36342 |
var sizePerComponent = new Array(componentsCount); |
| 36343 |
for (var c = 0; c < componentsCount; c++) { |
| 36344 |
var component = tile.components[c]; |
| 36345 |
var decompositionLevelsCount = |
| 36346 |
component.codingStyleParameters.decompositionLevelsCount; |
| 36347 |
var sizePerResolution = new Array(decompositionLevelsCount + 1); |
| 36348 |
var minWidthCurrentComponent = Number.MAX_VALUE; |
| 36349 |
var minHeightCurrentComponent = Number.MAX_VALUE; |
| 36350 |
var maxNumWideCurrentComponent = 0; |
| 36351 |
var maxNumHighCurrentComponent = 0; |
| 36352 |
var scale = 1; |
| 36353 |
for (var r = decompositionLevelsCount; r >= 0; --r) { |
| 36354 |
var resolution = component.resolutions[r]; |
| 36355 |
var widthCurrentResolution = |
| 36356 |
scale * resolution.precinctParameters.precinctWidth; |
| 36357 |
var heightCurrentResolution = |
| 36358 |
scale * resolution.precinctParameters.precinctHeight; |
| 36359 |
minWidthCurrentComponent = Math.min( |
| 36360 |
minWidthCurrentComponent, |
| 36361 |
widthCurrentResolution); |
| 36362 |
minHeightCurrentComponent = Math.min( |
| 36363 |
minHeightCurrentComponent, |
| 36364 |
heightCurrentResolution); |
| 36365 |
maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, |
| 36366 |
resolution.precinctParameters.numprecinctswide); |
| 36367 |
maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, |
| 36368 |
resolution.precinctParameters.numprecinctshigh); |
| 36369 |
sizePerResolution[r] = { |
| 36370 |
width: widthCurrentResolution, |
| 36371 |
height: heightCurrentResolution |
| 36372 |
}; |
| 36373 |
scale <<= 1; |
| 36374 |
} |
| 36375 |
minWidth = Math.min(minWidth, minWidthCurrentComponent); |
| 36376 |
minHeight = Math.min(minHeight, minHeightCurrentComponent); |
| 36377 |
maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent); |
| 36378 |
maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent); |
| 36379 |
sizePerComponent[c] = { |
| 36380 |
resolutions: sizePerResolution, |
| 36381 |
minWidth: minWidthCurrentComponent, |
| 36382 |
minHeight: minHeightCurrentComponent, |
| 36383 |
maxNumWide: maxNumWideCurrentComponent, |
| 36384 |
maxNumHigh: maxNumHighCurrentComponent |
| 36385 |
}; |
| 36386 |
} |
| 36387 |
return { |
| 36388 |
components: sizePerComponent, |
| 36389 |
minWidth: minWidth, |
| 36390 |
minHeight: minHeight, |
| 36391 |
maxNumWide: maxNumWide, |
| 36392 |
maxNumHigh: maxNumHigh |
| 36393 |
}; |
| 36394 |
} |
| 36395 |
function buildPackets(context) { |
| 36396 |
var siz = context.SIZ; |
| 36397 |
var tileIndex = context.currentTile.index; |
| 36398 |
var tile = context.tiles[tileIndex]; |
| 36399 |
var componentsCount = siz.Csiz; |
| 36400 |
// Creating resolutions and sub-bands for each component |
| 36401 |
for (var c = 0; c < componentsCount; c++) { |
| 36402 |
var component = tile.components[c]; |
| 36403 |
var decompositionLevelsCount = |
| 36404 |
component.codingStyleParameters.decompositionLevelsCount; |
| 36405 |
// Section B.5 Resolution levels and sub-bands |
| 36406 |
var resolutions = []; |
| 36407 |
var subbands = []; |
| 36408 |
for (var r = 0; r <= decompositionLevelsCount; r++) { |
| 36409 |
var blocksDimensions = getBlocksDimensions(context, component, r); |
| 36410 |
var resolution = {}; |
| 36411 |
var scale = 1 << (decompositionLevelsCount - r); |
| 36412 |
resolution.trx0 = Math.ceil(component.tcx0 / scale); |
| 36413 |
resolution.try0 = Math.ceil(component.tcy0 / scale); |
| 36414 |
resolution.trx1 = Math.ceil(component.tcx1 / scale); |
| 36415 |
resolution.try1 = Math.ceil(component.tcy1 / scale); |
| 36416 |
resolution.resLevel = r; |
| 36417 |
buildPrecincts(context, resolution, blocksDimensions); |
| 36418 |
resolutions.push(resolution); |
| 36419 |
|
| 36420 |
var subband; |
| 36421 |
if (r === 0) { |
| 36422 |
// one sub-band (LL) with last decomposition |
| 36423 |
subband = {}; |
| 36424 |
subband.type = 'LL'; |
| 36425 |
subband.tbx0 = Math.ceil(component.tcx0 / scale); |
| 36426 |
subband.tby0 = Math.ceil(component.tcy0 / scale); |
| 36427 |
subband.tbx1 = Math.ceil(component.tcx1 / scale); |
| 36428 |
subband.tby1 = Math.ceil(component.tcy1 / scale); |
| 36429 |
subband.resolution = resolution; |
| 36430 |
buildCodeblocks(context, subband, blocksDimensions); |
| 36431 |
subbands.push(subband); |
| 36432 |
resolution.subbands = [subband]; |
| 36433 |
} else { |
| 36434 |
var bscale = 1 << (decompositionLevelsCount - r + 1); |
| 36435 |
var resolutionSubbands = []; |
| 36436 |
// three sub-bands (HL, LH and HH) with rest of decompositions |
| 36437 |
subband = {}; |
| 36438 |
subband.type = 'HL'; |
| 36439 |
subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); |
| 36440 |
subband.tby0 = Math.ceil(component.tcy0 / bscale); |
| 36441 |
subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); |
| 36442 |
subband.tby1 = Math.ceil(component.tcy1 / bscale); |
| 36443 |
subband.resolution = resolution; |
| 36444 |
buildCodeblocks(context, subband, blocksDimensions); |
| 36445 |
subbands.push(subband); |
| 36446 |
resolutionSubbands.push(subband); |
| 36447 |
|
| 36448 |
subband = {}; |
| 36449 |
subband.type = 'LH'; |
| 36450 |
subband.tbx0 = Math.ceil(component.tcx0 / bscale); |
| 36451 |
subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); |
| 36452 |
subband.tbx1 = Math.ceil(component.tcx1 / bscale); |
| 36453 |
subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); |
| 36454 |
subband.resolution = resolution; |
| 36455 |
buildCodeblocks(context, subband, blocksDimensions); |
| 36456 |
subbands.push(subband); |
| 36457 |
resolutionSubbands.push(subband); |
| 36458 |
|
| 36459 |
subband = {}; |
| 36460 |
subband.type = 'HH'; |
| 36461 |
subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); |
| 36462 |
subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); |
| 36463 |
subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); |
| 36464 |
subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); |
| 36465 |
subband.resolution = resolution; |
| 36466 |
buildCodeblocks(context, subband, blocksDimensions); |
| 36467 |
subbands.push(subband); |
| 36468 |
resolutionSubbands.push(subband); |
| 36469 |
|
| 36470 |
resolution.subbands = resolutionSubbands; |
| 36471 |
} |
| 36472 |
} |
| 36473 |
component.resolutions = resolutions; |
| 36474 |
component.subbands = subbands; |
| 36475 |
} |
| 36476 |
// Generate the packets sequence |
| 36477 |
var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder; |
| 36478 |
switch (progressionOrder) { |
| 36479 |
case 0: |
| 36480 |
tile.packetsIterator = |
| 36481 |
new LayerResolutionComponentPositionIterator(context); |
| 36482 |
break; |
| 36483 |
case 1: |
| 36484 |
tile.packetsIterator = |
| 36485 |
new ResolutionLayerComponentPositionIterator(context); |
| 36486 |
break; |
| 36487 |
case 2: |
| 36488 |
tile.packetsIterator = |
| 36489 |
new ResolutionPositionComponentLayerIterator(context); |
| 36490 |
break; |
| 36491 |
case 3: |
| 36492 |
tile.packetsIterator = |
| 36493 |
new PositionComponentResolutionLayerIterator(context); |
| 36494 |
break; |
| 36495 |
case 4: |
| 36496 |
tile.packetsIterator = |
| 36497 |
new ComponentPositionResolutionLayerIterator(context); |
| 36498 |
break; |
| 36499 |
default: |
| 36500 |
throw new Error('JPX Error: Unsupported progression order ' + |
| 36501 |
progressionOrder); |
| 36502 |
} |
| 36503 |
} |
| 36504 |
function parseTilePackets(context, data, offset, dataLength) { |
| 36505 |
var position = 0; |
| 36506 |
var buffer, bufferSize = 0, skipNextBit = false; |
| 36507 |
function readBits(count) { |
| 36508 |
while (bufferSize < count) { |
| 36509 |
var b = data[offset + position]; |
| 36510 |
position++; |
| 36511 |
if (skipNextBit) { |
| 36512 |
buffer = (buffer << 7) | b; |
| 36513 |
bufferSize += 7; |
| 36514 |
skipNextBit = false; |
| 36515 |
} else { |
| 36516 |
buffer = (buffer << 8) | b; |
| 36517 |
bufferSize += 8; |
| 36518 |
} |
| 36519 |
if (b === 0xFF) { |
| 36520 |
skipNextBit = true; |
| 36521 |
} |
| 36522 |
} |
| 36523 |
bufferSize -= count; |
| 36524 |
return (buffer >>> bufferSize) & ((1 << count) - 1); |
| 36525 |
} |
| 36526 |
function skipMarkerIfEqual(value) { |
| 36527 |
if (data[offset + position - 1] === 0xFF && |
| 36528 |
data[offset + position] === value) { |
| 36529 |
skipBytes(1); |
| 36530 |
return true; |
| 36531 |
} else if (data[offset + position] === 0xFF && |
| 36532 |
data[offset + position + 1] === value) { |
| 36533 |
skipBytes(2); |
| 36534 |
return true; |
| 36535 |
} |
| 36536 |
return false; |
| 36537 |
} |
| 36538 |
function skipBytes(count) { |
| 36539 |
position += count; |
| 36540 |
} |
| 36541 |
function alignToByte() { |
| 36542 |
bufferSize = 0; |
| 36543 |
if (skipNextBit) { |
| 36544 |
position++; |
| 36545 |
skipNextBit = false; |
| 36546 |
} |
| 36547 |
} |
| 36548 |
function readCodingpasses() { |
| 36549 |
if (readBits(1) === 0) { |
| 36550 |
return 1; |
| 36551 |
} |
| 36552 |
if (readBits(1) === 0) { |
| 36553 |
return 2; |
| 36554 |
} |
| 36555 |
var value = readBits(2); |
| 36556 |
if (value < 3) { |
| 36557 |
return value + 3; |
| 36558 |
} |
| 36559 |
value = readBits(5); |
| 36560 |
if (value < 31) { |
| 36561 |
return value + 6; |
| 36562 |
} |
| 36563 |
value = readBits(7); |
| 36564 |
return value + 37; |
| 36565 |
} |
| 36566 |
var tileIndex = context.currentTile.index; |
| 36567 |
var tile = context.tiles[tileIndex]; |
| 36568 |
var sopMarkerUsed = context.COD.sopMarkerUsed; |
| 36569 |
var ephMarkerUsed = context.COD.ephMarkerUsed; |
| 36570 |
var packetsIterator = tile.packetsIterator; |
| 36571 |
while (position < dataLength) { |
| 36572 |
alignToByte(); |
| 36573 |
if (sopMarkerUsed && skipMarkerIfEqual(0x91)) { |
| 36574 |
// Skip also marker segment length and packet sequence ID |
| 36575 |
skipBytes(4); |
| 36576 |
} |
| 36577 |
var packet = packetsIterator.nextPacket(); |
| 36578 |
if (!readBits(1)) { |
| 36579 |
continue; |
| 36580 |
} |
| 36581 |
var layerNumber = packet.layerNumber; |
| 36582 |
var queue = [], codeblock; |
| 36583 |
for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) { |
| 36584 |
codeblock = packet.codeblocks[i]; |
| 36585 |
var precinct = codeblock.precinct; |
| 36586 |
var codeblockColumn = codeblock.cbx - precinct.cbxMin; |
| 36587 |
var codeblockRow = codeblock.cby - precinct.cbyMin; |
| 36588 |
var codeblockIncluded = false; |
| 36589 |
var firstTimeInclusion = false; |
| 36590 |
var valueReady; |
| 36591 |
if (codeblock['included'] !== undefined) { |
| 36592 |
codeblockIncluded = !!readBits(1); |
| 36593 |
} else { |
| 36594 |
// reading inclusion tree |
| 36595 |
precinct = codeblock.precinct; |
| 36596 |
var inclusionTree, zeroBitPlanesTree; |
| 36597 |
if (precinct['inclusionTree'] !== undefined) { |
| 36598 |
inclusionTree = precinct.inclusionTree; |
| 36599 |
} else { |
| 36600 |
// building inclusion and zero bit-planes trees |
| 36601 |
var width = precinct.cbxMax - precinct.cbxMin + 1; |
| 36602 |
var height = precinct.cbyMax - precinct.cbyMin + 1; |
| 36603 |
inclusionTree = new InclusionTree(width, height, layerNumber); |
| 36604 |
zeroBitPlanesTree = new TagTree(width, height); |
| 36605 |
precinct.inclusionTree = inclusionTree; |
| 36606 |
precinct.zeroBitPlanesTree = zeroBitPlanesTree; |
| 36607 |
} |
| 36608 |
|
| 36609 |
if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) { |
| 36610 |
while (true) { |
| 36611 |
if (readBits(1)) { |
| 36612 |
valueReady = !inclusionTree.nextLevel(); |
| 36613 |
if (valueReady) { |
| 36614 |
codeblock.included = true; |
| 36615 |
codeblockIncluded = firstTimeInclusion = true; |
| 36616 |
break; |
| 36617 |
} |
| 36618 |
} else { |
| 36619 |
inclusionTree.incrementValue(layerNumber); |
| 36620 |
break; |
| 36621 |
} |
| 36622 |
} |
| 36623 |
} |
| 36624 |
} |
| 36625 |
if (!codeblockIncluded) { |
| 36626 |
continue; |
| 36627 |
} |
| 36628 |
if (firstTimeInclusion) { |
| 36629 |
zeroBitPlanesTree = precinct.zeroBitPlanesTree; |
| 36630 |
zeroBitPlanesTree.reset(codeblockColumn, codeblockRow); |
| 36631 |
while (true) { |
| 36632 |
if (readBits(1)) { |
| 36633 |
valueReady = !zeroBitPlanesTree.nextLevel(); |
| 36634 |
if (valueReady) { |
| 36635 |
break; |
| 36636 |
} |
| 36637 |
} else { |
| 36638 |
zeroBitPlanesTree.incrementValue(); |
| 36639 |
} |
| 36640 |
} |
| 36641 |
codeblock.zeroBitPlanes = zeroBitPlanesTree.value; |
| 36642 |
} |
| 36643 |
var codingpasses = readCodingpasses(); |
| 36644 |
while (readBits(1)) { |
| 36645 |
codeblock.Lblock++; |
| 36646 |
} |
| 36647 |
var codingpassesLog2 = log2(codingpasses); |
| 36648 |
// rounding down log2 |
| 36649 |
var bits = ((codingpasses < (1 << codingpassesLog2)) ? |
| 36650 |
codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock; |
| 36651 |
var codedDataLength = readBits(bits); |
| 36652 |
queue.push({ |
| 36653 |
codeblock: codeblock, |
| 36654 |
codingpasses: codingpasses, |
| 36655 |
dataLength: codedDataLength |
| 36656 |
}); |
| 36657 |
} |
| 36658 |
alignToByte(); |
| 36659 |
if (ephMarkerUsed) { |
| 36660 |
skipMarkerIfEqual(0x92); |
| 36661 |
} |
| 36662 |
while (queue.length > 0) { |
| 36663 |
var packetItem = queue.shift(); |
| 36664 |
codeblock = packetItem.codeblock; |
| 36665 |
if (codeblock['data'] === undefined) { |
| 36666 |
codeblock.data = []; |
| 36667 |
} |
| 36668 |
codeblock.data.push({ |
| 36669 |
data: data, |
| 36670 |
start: offset + position, |
| 36671 |
end: offset + position + packetItem.dataLength, |
| 36672 |
codingpasses: packetItem.codingpasses |
| 36673 |
}); |
| 36674 |
position += packetItem.dataLength; |
| 36675 |
} |
| 36676 |
} |
| 36677 |
return position; |
| 36678 |
} |
| 36679 |
function copyCoefficients(coefficients, levelWidth, levelHeight, subband, |
| 36680 |
delta, mb, reversible, segmentationSymbolUsed) { |
| 36681 |
var x0 = subband.tbx0; |
| 36682 |
var y0 = subband.tby0; |
| 36683 |
var width = subband.tbx1 - subband.tbx0; |
| 36684 |
var codeblocks = subband.codeblocks; |
| 36685 |
var right = subband.type.charAt(0) === 'H' ? 1 : 0; |
| 36686 |
var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0; |
| 36687 |
|
| 36688 |
for (var i = 0, ii = codeblocks.length; i < ii; ++i) { |
| 36689 |
var codeblock = codeblocks[i]; |
| 36690 |
var blockWidth = codeblock.tbx1_ - codeblock.tbx0_; |
| 36691 |
var blockHeight = codeblock.tby1_ - codeblock.tby0_; |
| 36692 |
if (blockWidth === 0 || blockHeight === 0) { |
| 36693 |
continue; |
| 36694 |
} |
| 36695 |
if (codeblock['data'] === undefined) { |
| 36696 |
continue; |
| 36697 |
} |
| 36698 |
|
| 36699 |
var bitModel, currentCodingpassType; |
| 36700 |
bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, |
| 36701 |
codeblock.zeroBitPlanes, mb); |
| 36702 |
currentCodingpassType = 2; // first bit plane starts from cleanup |
| 36703 |
|
| 36704 |
// collect data |
| 36705 |
var data = codeblock.data, totalLength = 0, codingpasses = 0; |
| 36706 |
var j, jj, dataItem; |
| 36707 |
for (j = 0, jj = data.length; j < jj; j++) { |
| 36708 |
dataItem = data[j]; |
| 36709 |
totalLength += dataItem.end - dataItem.start; |
| 36710 |
codingpasses += dataItem.codingpasses; |
| 36711 |
} |
| 36712 |
var encodedData = new Uint8Array(totalLength); |
| 36713 |
var position = 0; |
| 36714 |
for (j = 0, jj = data.length; j < jj; j++) { |
| 36715 |
dataItem = data[j]; |
| 36716 |
var chunk = dataItem.data.subarray(dataItem.start, dataItem.end); |
| 36717 |
encodedData.set(chunk, position); |
| 36718 |
position += chunk.length; |
| 36719 |
} |
| 36720 |
// decoding the item |
| 36721 |
var decoder = new ArithmeticDecoder(encodedData, 0, totalLength); |
| 36722 |
bitModel.setDecoder(decoder); |
| 36723 |
|
| 36724 |
for (j = 0; j < codingpasses; j++) { |
| 36725 |
switch (currentCodingpassType) { |
| 36726 |
case 0: |
| 36727 |
bitModel.runSignificancePropogationPass(); |
| 36728 |
break; |
| 36729 |
case 1: |
| 36730 |
bitModel.runMagnitudeRefinementPass(); |
| 36731 |
break; |
| 36732 |
case 2: |
| 36733 |
bitModel.runCleanupPass(); |
| 36734 |
if (segmentationSymbolUsed) { |
| 36735 |
bitModel.checkSegmentationSymbol(); |
| 36736 |
} |
| 36737 |
break; |
| 36738 |
} |
| 36739 |
currentCodingpassType = (currentCodingpassType + 1) % 3; |
| 36740 |
} |
| 36741 |
|
| 36742 |
var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width; |
| 36743 |
var sign = bitModel.coefficentsSign; |
| 36744 |
var magnitude = bitModel.coefficentsMagnitude; |
| 36745 |
var bitsDecoded = bitModel.bitsDecoded; |
| 36746 |
var magnitudeCorrection = reversible ? 0 : 0.5; |
| 36747 |
var k, n, nb; |
| 36748 |
position = 0; |
| 36749 |
// Do the interleaving of Section F.3.3 here, so we do not need |
| 36750 |
// to copy later. LL level is not interleaved, just copied. |
| 36751 |
var interleave = (subband.type !== 'LL'); |
| 36752 |
for (j = 0; j < blockHeight; j++) { |
| 36753 |
var row = (offset / width) | 0; // row in the non-interleaved subband |
| 36754 |
var levelOffset = 2 * row * (levelWidth - width) + right + bottom; |
| 36755 |
for (k = 0; k < blockWidth; k++) { |
| 36756 |
n = magnitude[position]; |
| 36757 |
if (n !== 0) { |
| 36758 |
n = (n + magnitudeCorrection) * delta; |
| 36759 |
if (sign[position] !== 0) { |
| 36760 |
n = -n; |
| 36761 |
} |
| 36762 |
nb = bitsDecoded[position]; |
| 36763 |
var pos = interleave ? (levelOffset + (offset << 1)) : offset; |
| 36764 |
if (reversible && (nb >= mb)) { |
| 36765 |
coefficients[pos] = n; |
| 36766 |
} else { |
| 36767 |
coefficients[pos] = n * (1 << (mb - nb)); |
| 36768 |
} |
| 36769 |
} |
| 36770 |
offset++; |
| 36771 |
position++; |
| 36772 |
} |
| 36773 |
offset += width - blockWidth; |
| 36774 |
} |
| 36775 |
} |
| 36776 |
} |
| 36777 |
function transformTile(context, tile, c) { |
| 36778 |
var component = tile.components[c]; |
| 36779 |
var codingStyleParameters = component.codingStyleParameters; |
| 36780 |
var quantizationParameters = component.quantizationParameters; |
| 36781 |
var decompositionLevelsCount = |
| 36782 |
codingStyleParameters.decompositionLevelsCount; |
| 36783 |
var spqcds = quantizationParameters.SPqcds; |
| 36784 |
var scalarExpounded = quantizationParameters.scalarExpounded; |
| 36785 |
var guardBits = quantizationParameters.guardBits; |
| 36786 |
var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed; |
| 36787 |
var precision = context.components[c].precision; |
| 36788 |
|
| 36789 |
var reversible = codingStyleParameters.reversibleTransformation; |
| 36790 |
var transform = (reversible ? new ReversibleTransform() : |
| 36791 |
new IrreversibleTransform()); |
| 36792 |
|
| 36793 |
var subbandCoefficients = []; |
| 36794 |
var b = 0; |
| 36795 |
for (var i = 0; i <= decompositionLevelsCount; i++) { |
| 36796 |
var resolution = component.resolutions[i]; |
| 36797 |
|
| 36798 |
var width = resolution.trx1 - resolution.trx0; |
| 36799 |
var height = resolution.try1 - resolution.try0; |
| 36800 |
// Allocate space for the whole sublevel. |
| 36801 |
var coefficients = new Float32Array(width * height); |
| 36802 |
|
| 36803 |
for (var j = 0, jj = resolution.subbands.length; j < jj; j++) { |
| 36804 |
var mu, epsilon; |
| 36805 |
if (!scalarExpounded) { |
| 36806 |
// formula E-5 |
| 36807 |
mu = spqcds[0].mu; |
| 36808 |
epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0); |
| 36809 |
} else { |
| 36810 |
mu = spqcds[b].mu; |
| 36811 |
epsilon = spqcds[b].epsilon; |
| 36812 |
b++; |
| 36813 |
} |
| 36814 |
|
| 36815 |
var subband = resolution.subbands[j]; |
| 36816 |
var gainLog2 = SubbandsGainLog2[subband.type]; |
| 36817 |
|
| 36818 |
// calulate quantization coefficient (Section E.1.1.1) |
| 36819 |
var delta = (reversible ? 1 : |
| 36820 |
Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048)); |
| 36821 |
var mb = (guardBits + epsilon - 1); |
| 36822 |
|
| 36823 |
// In the first resolution level, copyCoefficients will fill the |
| 36824 |
// whole array with coefficients. In the succeding passes, |
| 36825 |
// copyCoefficients will consecutively fill in the values that belong |
| 36826 |
// to the interleaved positions of the HL, LH, and HH coefficients. |
| 36827 |
// The LL coefficients will then be interleaved in Transform.iterate(). |
| 36828 |
copyCoefficients(coefficients, width, height, subband, delta, mb, |
| 36829 |
reversible, segmentationSymbolUsed); |
| 36830 |
} |
| 36831 |
subbandCoefficients.push({ |
| 36832 |
width: width, |
| 36833 |
height: height, |
| 36834 |
items: coefficients |
| 36835 |
}); |
| 36836 |
} |
| 36837 |
|
| 36838 |
var result = transform.calculate(subbandCoefficients, |
| 36839 |
component.tcx0, component.tcy0); |
| 36840 |
return { |
| 36841 |
left: component.tcx0, |
| 36842 |
top: component.tcy0, |
| 36843 |
width: result.width, |
| 36844 |
height: result.height, |
| 36845 |
items: result.items |
| 36846 |
}; |
| 36847 |
} |
| 36848 |
function transformComponents(context) { |
| 36849 |
var siz = context.SIZ; |
| 36850 |
var components = context.components; |
| 36851 |
var componentsCount = siz.Csiz; |
| 36852 |
var resultImages = []; |
| 36853 |
for (var i = 0, ii = context.tiles.length; i < ii; i++) { |
| 36854 |
var tile = context.tiles[i]; |
| 36855 |
var transformedTiles = []; |
| 36856 |
var c; |
| 36857 |
for (c = 0; c < componentsCount; c++) { |
| 36858 |
transformedTiles[c] = transformTile(context, tile, c); |
| 36859 |
} |
| 36860 |
var tile0 = transformedTiles[0]; |
| 36861 |
var out = new Uint8Array(tile0.items.length * componentsCount); |
| 36862 |
var result = { |
| 36863 |
left: tile0.left, |
| 36864 |
top: tile0.top, |
| 36865 |
width: tile0.width, |
| 36866 |
height: tile0.height, |
| 36867 |
items: out |
| 36868 |
}; |
| 36869 |
|
| 36870 |
// Section G.2.2 Inverse multi component transform |
| 36871 |
var shift, offset, max, min, maxK; |
| 36872 |
var pos = 0, j, jj, y0, y1, y2, r, g, b, k, val; |
| 36873 |
if (tile.codingStyleDefaultParameters.multipleComponentTransform) { |
| 36874 |
var fourComponents = componentsCount === 4; |
| 36875 |
var y0items = transformedTiles[0].items; |
| 36876 |
var y1items = transformedTiles[1].items; |
| 36877 |
var y2items = transformedTiles[2].items; |
| 36878 |
var y3items = fourComponents ? transformedTiles[3].items : null; |
| 36879 |
|
| 36880 |
// HACK: The multiple component transform formulas below assume that |
| 36881 |
// all components have the same precision. With this in mind, we |
| 36882 |
// compute shift and offset only once. |
| 36883 |
shift = components[0].precision - 8; |
| 36884 |
offset = (128 << shift) + 0.5; |
| 36885 |
max = 255 * (1 << shift); |
| 36886 |
maxK = max * 0.5; |
| 36887 |
min = -maxK; |
| 36888 |
|
| 36889 |
var component0 = tile.components[0]; |
| 36890 |
var alpha01 = componentsCount - 3; |
| 36891 |
jj = y0items.length; |
| 36892 |
if (!component0.codingStyleParameters.reversibleTransformation) { |
| 36893 |
// inverse irreversible multiple component transform |
| 36894 |
for (j = 0; j < jj; j++, pos += alpha01) { |
| 36895 |
y0 = y0items[j] + offset; |
| 36896 |
y1 = y1items[j]; |
| 36897 |
y2 = y2items[j]; |
| 36898 |
r = y0 + 1.402 * y2; |
| 36899 |
g = y0 - 0.34413 * y1 - 0.71414 * y2; |
| 36900 |
b = y0 + 1.772 * y1; |
| 36901 |
out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift; |
| 36902 |
out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift; |
| 36903 |
out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift; |
| 36904 |
} |
| 36905 |
} else { |
| 36906 |
// inverse reversible multiple component transform |
| 36907 |
for (j = 0; j < jj; j++, pos += alpha01) { |
| 36908 |
y0 = y0items[j] + offset; |
| 36909 |
y1 = y1items[j]; |
| 36910 |
y2 = y2items[j]; |
| 36911 |
g = y0 - ((y2 + y1) >> 2); |
| 36912 |
r = g + y2; |
| 36913 |
b = g + y1; |
| 36914 |
out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift; |
| 36915 |
out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift; |
| 36916 |
out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift; |
| 36917 |
} |
| 36918 |
} |
| 36919 |
if (fourComponents) { |
| 36920 |
for (j = 0, pos = 3; j < jj; j++, pos += 4) { |
| 36921 |
k = y3items[j]; |
| 36922 |
out[pos] = k <= min ? 0 : k >= maxK ? 255 : (k + offset) >> shift; |
| 36923 |
} |
| 36924 |
} |
| 36925 |
} else { // no multi-component transform |
| 36926 |
for (c = 0; c < componentsCount; c++) { |
| 36927 |
var items = transformedTiles[c].items; |
| 36928 |
shift = components[c].precision - 8; |
| 36929 |
offset = (128 << shift) + 0.5; |
| 36930 |
max = (127.5 * (1 << shift)); |
| 36931 |
min = -max; |
| 36932 |
for (pos = c, j = 0, jj = items.length; j < jj; j++) { |
| 36933 |
val = items[j]; |
| 36934 |
out[pos] = val <= min ? 0 : |
| 36935 |
val >= max ? 255 : (val + offset) >> shift; |
| 36936 |
pos += componentsCount; |
| 36937 |
} |
| 36938 |
} |
| 36939 |
} |
| 36940 |
resultImages.push(result); |
| 36941 |
} |
| 36942 |
return resultImages; |
| 36943 |
} |
| 36944 |
function initializeTile(context, tileIndex) { |
| 36945 |
var siz = context.SIZ; |
| 36946 |
var componentsCount = siz.Csiz; |
| 36947 |
var tile = context.tiles[tileIndex]; |
| 36948 |
for (var c = 0; c < componentsCount; c++) { |
| 36949 |
var component = tile.components[c]; |
| 36950 |
var qcdOrQcc = (context.currentTile.QCC[c] !== undefined ? |
| 36951 |
context.currentTile.QCC[c] : context.currentTile.QCD); |
| 36952 |
component.quantizationParameters = qcdOrQcc; |
| 36953 |
var codOrCoc = (context.currentTile.COC[c] !== undefined ? |
| 36954 |
context.currentTile.COC[c] : context.currentTile.COD); |
| 36955 |
component.codingStyleParameters = codOrCoc; |
| 36956 |
} |
| 36957 |
tile.codingStyleDefaultParameters = context.currentTile.COD; |
| 36958 |
} |
| 36959 |
|
| 36960 |
// Section B.10.2 Tag trees |
| 36961 |
var TagTree = (function TagTreeClosure() { |
| 36962 |
function TagTree(width, height) { |
| 36963 |
var levelsLength = log2(Math.max(width, height)) + 1; |
| 36964 |
this.levels = []; |
| 36965 |
for (var i = 0; i < levelsLength; i++) { |
| 36966 |
var level = { |
| 36967 |
width: width, |
| 36968 |
height: height, |
| 36969 |
items: [] |
| 36970 |
}; |
| 36971 |
this.levels.push(level); |
| 36972 |
width = Math.ceil(width / 2); |
| 36973 |
height = Math.ceil(height / 2); |
| 36974 |
} |
| 36975 |
} |
| 36976 |
TagTree.prototype = { |
| 36977 |
reset: function TagTree_reset(i, j) { |
| 36978 |
var currentLevel = 0, value = 0, level; |
| 36979 |
while (currentLevel < this.levels.length) { |
| 36980 |
level = this.levels[currentLevel]; |
| 36981 |
var index = i + j * level.width; |
| 36982 |
if (level.items[index] !== undefined) { |
| 36983 |
value = level.items[index]; |
| 36984 |
break; |
| 36985 |
} |
| 36986 |
level.index = index; |
| 36987 |
i >>= 1; |
| 36988 |
j >>= 1; |
| 36989 |
currentLevel++; |
| 36990 |
} |
| 36991 |
currentLevel--; |
| 36992 |
level = this.levels[currentLevel]; |
| 36993 |
level.items[level.index] = value; |
| 36994 |
this.currentLevel = currentLevel; |
| 36995 |
delete this.value; |
| 36996 |
}, |
| 36997 |
incrementValue: function TagTree_incrementValue() { |
| 36998 |
var level = this.levels[this.currentLevel]; |
| 36999 |
level.items[level.index]++; |
| 37000 |
}, |
| 37001 |
nextLevel: function TagTree_nextLevel() { |
| 37002 |
var currentLevel = this.currentLevel; |
| 37003 |
var level = this.levels[currentLevel]; |
| 37004 |
var value = level.items[level.index]; |
| 37005 |
currentLevel--; |
| 37006 |
if (currentLevel < 0) { |
| 37007 |
this.value = value; |
| 37008 |
return false; |
| 37009 |
} |
| 37010 |
|
| 37011 |
this.currentLevel = currentLevel; |
| 37012 |
level = this.levels[currentLevel]; |
| 37013 |
level.items[level.index] = value; |
| 37014 |
return true; |
| 37015 |
} |
| 37016 |
}; |
| 37017 |
return TagTree; |
| 37018 |
})(); |
| 37019 |
|
| 37020 |
var InclusionTree = (function InclusionTreeClosure() { |
| 37021 |
function InclusionTree(width, height, defaultValue) { |
| 37022 |
var levelsLength = log2(Math.max(width, height)) + 1; |
| 37023 |
this.levels = []; |
| 37024 |
for (var i = 0; i < levelsLength; i++) { |
| 37025 |
var items = new Uint8Array(width * height); |
| 37026 |
for (var j = 0, jj = items.length; j < jj; j++) { |
| 37027 |
items[j] = defaultValue; |
| 37028 |
} |
| 37029 |
|
| 37030 |
var level = { |
| 37031 |
width: width, |
| 37032 |
height: height, |
| 37033 |
items: items |
| 37034 |
}; |
| 37035 |
this.levels.push(level); |
| 37036 |
|
| 37037 |
width = Math.ceil(width / 2); |
| 37038 |
height = Math.ceil(height / 2); |
| 37039 |
} |
| 37040 |
} |
| 37041 |
InclusionTree.prototype = { |
| 37042 |
reset: function InclusionTree_reset(i, j, stopValue) { |
| 37043 |
var currentLevel = 0; |
| 37044 |
while (currentLevel < this.levels.length) { |
| 37045 |
var level = this.levels[currentLevel]; |
| 37046 |
var index = i + j * level.width; |
| 37047 |
level.index = index; |
| 37048 |
var value = level.items[index]; |
| 37049 |
|
| 37050 |
if (value === 0xFF) { |
| 37051 |
break; |
| 37052 |
} |
| 37053 |
|
| 37054 |
if (value > stopValue) { |
| 37055 |
this.currentLevel = currentLevel; |
| 37056 |
// already know about this one, propagating the value to top levels |
| 37057 |
this.propagateValues(); |
| 37058 |
return false; |
| 37059 |
} |
| 37060 |
|
| 37061 |
i >>= 1; |
| 37062 |
j >>= 1; |
| 37063 |
currentLevel++; |
| 37064 |
} |
| 37065 |
this.currentLevel = currentLevel - 1; |
| 37066 |
return true; |
| 37067 |
}, |
| 37068 |
incrementValue: function InclusionTree_incrementValue(stopValue) { |
| 37069 |
var level = this.levels[this.currentLevel]; |
| 37070 |
level.items[level.index] = stopValue + 1; |
| 37071 |
this.propagateValues(); |
| 37072 |
}, |
| 37073 |
propagateValues: function InclusionTree_propagateValues() { |
| 37074 |
var levelIndex = this.currentLevel; |
| 37075 |
var level = this.levels[levelIndex]; |
| 37076 |
var currentValue = level.items[level.index]; |
| 37077 |
while (--levelIndex >= 0) { |
| 37078 |
level = this.levels[levelIndex]; |
| 37079 |
level.items[level.index] = currentValue; |
| 37080 |
} |
| 37081 |
}, |
| 37082 |
nextLevel: function InclusionTree_nextLevel() { |
| 37083 |
var currentLevel = this.currentLevel; |
| 37084 |
var level = this.levels[currentLevel]; |
| 37085 |
var value = level.items[level.index]; |
| 37086 |
level.items[level.index] = 0xFF; |
| 37087 |
currentLevel--; |
| 37088 |
if (currentLevel < 0) { |
| 37089 |
return false; |
| 37090 |
} |
| 37091 |
|
| 37092 |
this.currentLevel = currentLevel; |
| 37093 |
level = this.levels[currentLevel]; |
| 37094 |
level.items[level.index] = value; |
| 37095 |
return true; |
| 37096 |
} |
| 37097 |
}; |
| 37098 |
return InclusionTree; |
| 37099 |
})(); |
| 37100 |
|
| 37101 |
// Section D. Coefficient bit modeling |
| 37102 |
var BitModel = (function BitModelClosure() { |
| 37103 |
var UNIFORM_CONTEXT = 17; |
| 37104 |
var RUNLENGTH_CONTEXT = 18; |
| 37105 |
// Table D-1 |
| 37106 |
// The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4), |
| 37107 |
// vv - sum of Vi (0..2), and hh - sum of Hi (0..2) |
| 37108 |
var LLAndLHContextsLabel = new Uint8Array([ |
| 37109 |
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, |
| 37110 |
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, |
| 37111 |
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 |
| 37112 |
]); |
| 37113 |
var HLContextLabel = new Uint8Array([ |
| 37114 |
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, |
| 37115 |
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, |
| 37116 |
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 |
| 37117 |
]); |
| 37118 |
var HHContextLabel = new Uint8Array([ |
| 37119 |
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, |
| 37120 |
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, |
| 37121 |
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 |
| 37122 |
]); |
| 37123 |
|
| 37124 |
function BitModel(width, height, subband, zeroBitPlanes, mb) { |
| 37125 |
this.width = width; |
| 37126 |
this.height = height; |
| 37127 |
|
| 37128 |
this.contextLabelTable = (subband === 'HH' ? HHContextLabel : |
| 37129 |
(subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel)); |
| 37130 |
|
| 37131 |
var coefficientCount = width * height; |
| 37132 |
|
| 37133 |
// coefficients outside the encoding region treated as insignificant |
| 37134 |
// add border state cells for significanceState |
| 37135 |
this.neighborsSignificance = new Uint8Array(coefficientCount); |
| 37136 |
this.coefficentsSign = new Uint8Array(coefficientCount); |
| 37137 |
this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) : |
| 37138 |
mb > 6 ? new Uint16Array(coefficientCount) : |
| 37139 |
new Uint8Array(coefficientCount); |
| 37140 |
this.processingFlags = new Uint8Array(coefficientCount); |
| 37141 |
|
| 37142 |
var bitsDecoded = new Uint8Array(coefficientCount); |
| 37143 |
if (zeroBitPlanes !== 0) { |
| 37144 |
for (var i = 0; i < coefficientCount; i++) { |
| 37145 |
bitsDecoded[i] = zeroBitPlanes; |
| 37146 |
} |
| 37147 |
} |
| 37148 |
this.bitsDecoded = bitsDecoded; |
| 37149 |
|
| 37150 |
this.reset(); |
| 37151 |
} |
| 37152 |
|
| 37153 |
BitModel.prototype = { |
| 37154 |
setDecoder: function BitModel_setDecoder(decoder) { |
| 37155 |
this.decoder = decoder; |
| 37156 |
}, |
| 37157 |
reset: function BitModel_reset() { |
| 37158 |
// We have 17 contexts that are accessed via context labels, |
| 37159 |
// plus the uniform and runlength context. |
| 37160 |
this.contexts = new Int8Array(19); |
| 37161 |
|
| 37162 |
// Contexts are packed into 1 byte: |
| 37163 |
// highest 7 bits carry the index, lowest bit carries mps |
| 37164 |
this.contexts[0] = (4 << 1) | 0; |
| 37165 |
this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0; |
| 37166 |
this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0; |
| 37167 |
}, |
| 37168 |
setNeighborsSignificance: |
| 37169 |
function BitModel_setNeighborsSignificance(row, column, index) { |
| 37170 |
var neighborsSignificance = this.neighborsSignificance; |
| 37171 |
var width = this.width, height = this.height; |
| 37172 |
var left = (column > 0); |
| 37173 |
var right = (column + 1 < width); |
| 37174 |
var i; |
| 37175 |
|
| 37176 |
if (row > 0) { |
| 37177 |
i = index - width; |
| 37178 |
if (left) { |
| 37179 |
neighborsSignificance[i - 1] += 0x10; |
| 37180 |
} |
| 37181 |
if (right) { |
| 37182 |
neighborsSignificance[i + 1] += 0x10; |
| 37183 |
} |
| 37184 |
neighborsSignificance[i] += 0x04; |
| 37185 |
} |
| 37186 |
|
| 37187 |
if (row + 1 < height) { |
| 37188 |
i = index + width; |
| 37189 |
if (left) { |
| 37190 |
neighborsSignificance[i - 1] += 0x10; |
| 37191 |
} |
| 37192 |
if (right) { |
| 37193 |
neighborsSignificance[i + 1] += 0x10; |
| 37194 |
} |
| 37195 |
neighborsSignificance[i] += 0x04; |
| 37196 |
} |
| 37197 |
|
| 37198 |
if (left) { |
| 37199 |
neighborsSignificance[index - 1] += 0x01; |
| 37200 |
} |
| 37201 |
if (right) { |
| 37202 |
neighborsSignificance[index + 1] += 0x01; |
| 37203 |
} |
| 37204 |
neighborsSignificance[index] |= 0x80; |
| 37205 |
}, |
| 37206 |
runSignificancePropogationPass: |
| 37207 |
function BitModel_runSignificancePropogationPass() { |
| 37208 |
var decoder = this.decoder; |
| 37209 |
var width = this.width, height = this.height; |
| 37210 |
var coefficentsMagnitude = this.coefficentsMagnitude; |
| 37211 |
var coefficentsSign = this.coefficentsSign; |
| 37212 |
var neighborsSignificance = this.neighborsSignificance; |
| 37213 |
var processingFlags = this.processingFlags; |
| 37214 |
var contexts = this.contexts; |
| 37215 |
var labels = this.contextLabelTable; |
| 37216 |
var bitsDecoded = this.bitsDecoded; |
| 37217 |
var processedInverseMask = ~1; |
| 37218 |
var processedMask = 1; |
| 37219 |
var firstMagnitudeBitMask = 2; |
| 37220 |
|
| 37221 |
for (var i0 = 0; i0 < height; i0 += 4) { |
| 37222 |
for (var j = 0; j < width; j++) { |
| 37223 |
var index = i0 * width + j; |
| 37224 |
for (var i1 = 0; i1 < 4; i1++, index += width) { |
| 37225 |
var i = i0 + i1; |
| 37226 |
if (i >= height) { |
| 37227 |
break; |
| 37228 |
} |
| 37229 |
// clear processed flag first |
| 37230 |
processingFlags[index] &= processedInverseMask; |
| 37231 |
|
| 37232 |
if (coefficentsMagnitude[index] || |
| 37233 |
!neighborsSignificance[index]) { |
| 37234 |
continue; |
| 37235 |
} |
| 37236 |
|
| 37237 |
var contextLabel = labels[neighborsSignificance[index]]; |
| 37238 |
var decision = decoder.readBit(contexts, contextLabel); |
| 37239 |
if (decision) { |
| 37240 |
var sign = this.decodeSignBit(i, j, index); |
| 37241 |
coefficentsSign[index] = sign; |
| 37242 |
coefficentsMagnitude[index] = 1; |
| 37243 |
this.setNeighborsSignificance(i, j, index); |
| 37244 |
processingFlags[index] |= firstMagnitudeBitMask; |
| 37245 |
} |
| 37246 |
bitsDecoded[index]++; |
| 37247 |
processingFlags[index] |= processedMask; |
| 37248 |
} |
| 37249 |
} |
| 37250 |
} |
| 37251 |
}, |
| 37252 |
decodeSignBit: function BitModel_decodeSignBit(row, column, index) { |
| 37253 |
var width = this.width, height = this.height; |
| 37254 |
var coefficentsMagnitude = this.coefficentsMagnitude; |
| 37255 |
var coefficentsSign = this.coefficentsSign; |
| 37256 |
var contribution, sign0, sign1, significance1; |
| 37257 |
var contextLabel, decoded; |
| 37258 |
|
| 37259 |
// calculate horizontal contribution |
| 37260 |
significance1 = (column > 0 && coefficentsMagnitude[index - 1] !== 0); |
| 37261 |
if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) { |
| 37262 |
sign1 = coefficentsSign[index + 1]; |
| 37263 |
if (significance1) { |
| 37264 |
sign0 = coefficentsSign[index - 1]; |
| 37265 |
contribution = 1 - sign1 - sign0; |
| 37266 |
} else { |
| 37267 |
contribution = 1 - sign1 - sign1; |
| 37268 |
} |
| 37269 |
} else if (significance1) { |
| 37270 |
sign0 = coefficentsSign[index - 1]; |
| 37271 |
contribution = 1 - sign0 - sign0; |
| 37272 |
} else { |
| 37273 |
contribution = 0; |
| 37274 |
} |
| 37275 |
var horizontalContribution = 3 * contribution; |
| 37276 |
|
| 37277 |
// calculate vertical contribution and combine with the horizontal |
| 37278 |
significance1 = (row > 0 && coefficentsMagnitude[index - width] !== 0); |
| 37279 |
if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) { |
| 37280 |
sign1 = coefficentsSign[index + width]; |
| 37281 |
if (significance1) { |
| 37282 |
sign0 = coefficentsSign[index - width]; |
| 37283 |
contribution = 1 - sign1 - sign0 + horizontalContribution; |
| 37284 |
} else { |
| 37285 |
contribution = 1 - sign1 - sign1 + horizontalContribution; |
| 37286 |
} |
| 37287 |
} else if (significance1) { |
| 37288 |
sign0 = coefficentsSign[index - width]; |
| 37289 |
contribution = 1 - sign0 - sign0 + horizontalContribution; |
| 37290 |
} else { |
| 37291 |
contribution = horizontalContribution; |
| 37292 |
} |
| 37293 |
|
| 37294 |
if (contribution >= 0) { |
| 37295 |
contextLabel = 9 + contribution; |
| 37296 |
decoded = this.decoder.readBit(this.contexts, contextLabel); |
| 37297 |
} else { |
| 37298 |
contextLabel = 9 - contribution; |
| 37299 |
decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1; |
| 37300 |
} |
| 37301 |
return decoded; |
| 37302 |
}, |
| 37303 |
runMagnitudeRefinementPass: |
| 37304 |
function BitModel_runMagnitudeRefinementPass() { |
| 37305 |
var decoder = this.decoder; |
| 37306 |
var width = this.width, height = this.height; |
| 37307 |
var coefficentsMagnitude = this.coefficentsMagnitude; |
| 37308 |
var neighborsSignificance = this.neighborsSignificance; |
| 37309 |
var contexts = this.contexts; |
| 37310 |
var bitsDecoded = this.bitsDecoded; |
| 37311 |
var processingFlags = this.processingFlags; |
| 37312 |
var processedMask = 1; |
| 37313 |
var firstMagnitudeBitMask = 2; |
| 37314 |
var length = width * height; |
| 37315 |
var width4 = width * 4; |
| 37316 |
|
| 37317 |
for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) { |
| 37318 |
indexNext = Math.min(length, index0 + width4); |
| 37319 |
for (var j = 0; j < width; j++) { |
| 37320 |
for (var index = index0 + j; index < indexNext; index += width) { |
| 37321 |
|
| 37322 |
// significant but not those that have just become |
| 37323 |
if (!coefficentsMagnitude[index] || |
| 37324 |
(processingFlags[index] & processedMask) !== 0) { |
| 37325 |
continue; |
| 37326 |
} |
| 37327 |
|
| 37328 |
var contextLabel = 16; |
| 37329 |
if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) { |
| 37330 |
processingFlags[index] ^= firstMagnitudeBitMask; |
| 37331 |
// first refinement |
| 37332 |
var significance = neighborsSignificance[index] & 127; |
| 37333 |
contextLabel = significance === 0 ? 15 : 14; |
| 37334 |
} |
| 37335 |
|
| 37336 |
var bit = decoder.readBit(contexts, contextLabel); |
| 37337 |
coefficentsMagnitude[index] = |
| 37338 |
(coefficentsMagnitude[index] << 1) | bit; |
| 37339 |
bitsDecoded[index]++; |
| 37340 |
processingFlags[index] |= processedMask; |
| 37341 |
} |
| 37342 |
} |
| 37343 |
} |
| 37344 |
}, |
| 37345 |
runCleanupPass: function BitModel_runCleanupPass() { |
| 37346 |
var decoder = this.decoder; |
| 37347 |
var width = this.width, height = this.height; |
| 37348 |
var neighborsSignificance = this.neighborsSignificance; |
| 37349 |
var coefficentsMagnitude = this.coefficentsMagnitude; |
| 37350 |
var coefficentsSign = this.coefficentsSign; |
| 37351 |
var contexts = this.contexts; |
| 37352 |
var labels = this.contextLabelTable; |
| 37353 |
var bitsDecoded = this.bitsDecoded; |
| 37354 |
var processingFlags = this.processingFlags; |
| 37355 |
var processedMask = 1; |
| 37356 |
var firstMagnitudeBitMask = 2; |
| 37357 |
var oneRowDown = width; |
| 37358 |
var twoRowsDown = width * 2; |
| 37359 |
var threeRowsDown = width * 3; |
| 37360 |
var iNext; |
| 37361 |
for (var i0 = 0; i0 < height; i0 = iNext) { |
| 37362 |
iNext = Math.min(i0 + 4, height); |
| 37363 |
var indexBase = i0 * width; |
| 37364 |
var checkAllEmpty = i0 + 3 < height; |
| 37365 |
for (var j = 0; j < width; j++) { |
| 37366 |
var index0 = indexBase + j; |
| 37367 |
// using the property: labels[neighborsSignificance[index]] === 0 |
| 37368 |
// when neighborsSignificance[index] === 0 |
| 37369 |
var allEmpty = (checkAllEmpty && |
| 37370 |
processingFlags[index0] === 0 && |
| 37371 |
processingFlags[index0 + oneRowDown] === 0 && |
| 37372 |
processingFlags[index0 + twoRowsDown] === 0 && |
| 37373 |
processingFlags[index0 + threeRowsDown] === 0 && |
| 37374 |
neighborsSignificance[index0] === 0 && |
| 37375 |
neighborsSignificance[index0 + oneRowDown] === 0 && |
| 37376 |
neighborsSignificance[index0 + twoRowsDown] === 0 && |
| 37377 |
neighborsSignificance[index0 + threeRowsDown] === 0); |
| 37378 |
var i1 = 0, index = index0; |
| 37379 |
var i = i0, sign; |
| 37380 |
if (allEmpty) { |
| 37381 |
var hasSignificantCoefficent = |
| 37382 |
decoder.readBit(contexts, RUNLENGTH_CONTEXT); |
| 37383 |
if (!hasSignificantCoefficent) { |
| 37384 |
bitsDecoded[index0]++; |
| 37385 |
bitsDecoded[index0 + oneRowDown]++; |
| 37386 |
bitsDecoded[index0 + twoRowsDown]++; |
| 37387 |
bitsDecoded[index0 + threeRowsDown]++; |
| 37388 |
continue; // next column |
| 37389 |
} |
| 37390 |
i1 = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) | |
| 37391 |
decoder.readBit(contexts, UNIFORM_CONTEXT); |
| 37392 |
if (i1 !== 0) { |
| 37393 |
i = i0 + i1; |
| 37394 |
index += i1 * width; |
| 37395 |
} |
| 37396 |
|
| 37397 |
sign = this.decodeSignBit(i, j, index); |
| 37398 |
coefficentsSign[index] = sign; |
| 37399 |
coefficentsMagnitude[index] = 1; |
| 37400 |
this.setNeighborsSignificance(i, j, index); |
| 37401 |
processingFlags[index] |= firstMagnitudeBitMask; |
| 37402 |
|
| 37403 |
index = index0; |
| 37404 |
for (var i2 = i0; i2 <= i; i2++, index += width) { |
| 37405 |
bitsDecoded[index]++; |
| 37406 |
} |
| 37407 |
|
| 37408 |
i1++; |
| 37409 |
} |
| 37410 |
for (i = i0 + i1; i < iNext; i++, index += width) { |
| 37411 |
if (coefficentsMagnitude[index] || |
| 37412 |
(processingFlags[index] & processedMask) !== 0) { |
| 37413 |
continue; |
| 37414 |
} |
| 37415 |
|
| 37416 |
var contextLabel = labels[neighborsSignificance[index]]; |
| 37417 |
var decision = decoder.readBit(contexts, contextLabel); |
| 37418 |
if (decision === 1) { |
| 37419 |
sign = this.decodeSignBit(i, j, index); |
| 37420 |
coefficentsSign[index] = sign; |
| 37421 |
coefficentsMagnitude[index] = 1; |
| 37422 |
this.setNeighborsSignificance(i, j, index); |
| 37423 |
processingFlags[index] |= firstMagnitudeBitMask; |
| 37424 |
} |
| 37425 |
bitsDecoded[index]++; |
| 37426 |
} |
| 37427 |
} |
| 37428 |
} |
| 37429 |
}, |
| 37430 |
checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() { |
| 37431 |
var decoder = this.decoder; |
| 37432 |
var contexts = this.contexts; |
| 37433 |
var symbol = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 3) | |
| 37434 |
(decoder.readBit(contexts, UNIFORM_CONTEXT) << 2) | |
| 37435 |
(decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) | |
| 37436 |
decoder.readBit(contexts, UNIFORM_CONTEXT); |
| 37437 |
if (symbol !== 0xA) { |
| 37438 |
throw new Error('JPX Error: Invalid segmentation symbol'); |
| 37439 |
} |
| 37440 |
} |
| 37441 |
}; |
| 37442 |
|
| 37443 |
return BitModel; |
| 37444 |
})(); |
| 37445 |
|
| 37446 |
// Section F, Discrete wavelet transformation |
| 37447 |
var Transform = (function TransformClosure() { |
| 37448 |
function Transform() {} |
| 37449 |
|
| 37450 |
Transform.prototype.calculate = |
| 37451 |
function transformCalculate(subbands, u0, v0) { |
| 37452 |
var ll = subbands[0]; |
| 37453 |
for (var i = 1, ii = subbands.length; i < ii; i++) { |
| 37454 |
ll = this.iterate(ll, subbands[i], u0, v0); |
| 37455 |
} |
| 37456 |
return ll; |
| 37457 |
}; |
| 37458 |
Transform.prototype.extend = function extend(buffer, offset, size) { |
| 37459 |
// Section F.3.7 extending... using max extension of 4 |
| 37460 |
var i1 = offset - 1, j1 = offset + 1; |
| 37461 |
var i2 = offset + size - 2, j2 = offset + size; |
| 37462 |
buffer[i1--] = buffer[j1++]; |
| 37463 |
buffer[j2++] = buffer[i2--]; |
| 37464 |
buffer[i1--] = buffer[j1++]; |
| 37465 |
buffer[j2++] = buffer[i2--]; |
| 37466 |
buffer[i1--] = buffer[j1++]; |
| 37467 |
buffer[j2++] = buffer[i2--]; |
| 37468 |
buffer[i1] = buffer[j1]; |
| 37469 |
buffer[j2] = buffer[i2]; |
| 37470 |
}; |
| 37471 |
Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh, |
| 37472 |
u0, v0) { |
| 37473 |
var llWidth = ll.width, llHeight = ll.height, llItems = ll.items; |
| 37474 |
var width = hl_lh_hh.width; |
| 37475 |
var height = hl_lh_hh.height; |
| 37476 |
var items = hl_lh_hh.items; |
| 37477 |
var i, j, k, l, u, v; |
| 37478 |
|
| 37479 |
// Interleave LL according to Section F.3.3 |
| 37480 |
for (k = 0, i = 0; i < llHeight; i++) { |
| 37481 |
l = i * 2 * width; |
| 37482 |
for (j = 0; j < llWidth; j++, k++, l += 2) { |
| 37483 |
items[l] = llItems[k]; |
| 37484 |
} |
| 37485 |
} |
| 37486 |
// The LL band is not needed anymore. |
| 37487 |
llItems = ll.items = null; |
| 37488 |
|
| 37489 |
var bufferPadding = 4; |
| 37490 |
var rowBuffer = new Float32Array(width + 2 * bufferPadding); |
| 37491 |
|
| 37492 |
// Section F.3.4 HOR_SR |
| 37493 |
if (width === 1) { |
| 37494 |
// if width = 1, when u0 even keep items as is, when odd divide by 2 |
| 37495 |
if ((u0 & 1) !== 0) { |
| 37496 |
for (v = 0, k = 0; v < height; v++, k += width) { |
| 37497 |
items[k] *= 0.5; |
| 37498 |
} |
| 37499 |
} |
| 37500 |
} else { |
| 37501 |
for (v = 0, k = 0; v < height; v++, k += width) { |
| 37502 |
rowBuffer.set(items.subarray(k, k + width), bufferPadding); |
| 37503 |
|
| 37504 |
this.extend(rowBuffer, bufferPadding, width); |
| 37505 |
this.filter(rowBuffer, bufferPadding, width); |
| 37506 |
|
| 37507 |
items.set( |
| 37508 |
rowBuffer.subarray(bufferPadding, bufferPadding + width), |
| 37509 |
k); |
| 37510 |
} |
| 37511 |
} |
| 37512 |
|
| 37513 |
// Accesses to the items array can take long, because it may not fit into |
| 37514 |
// CPU cache and has to be fetched from main memory. Since subsequent |
| 37515 |
// accesses to the items array are not local when reading columns, we |
| 37516 |
// have a cache miss every time. To reduce cache misses, get up to |
| 37517 |
// 'numBuffers' items at a time and store them into the individual |
| 37518 |
// buffers. The colBuffers should be small enough to fit into CPU cache. |
| 37519 |
var numBuffers = 16; |
| 37520 |
var colBuffers = []; |
| 37521 |
for (i = 0; i < numBuffers; i++) { |
| 37522 |
colBuffers.push(new Float32Array(height + 2 * bufferPadding)); |
| 37523 |
} |
| 37524 |
var b, currentBuffer = 0; |
| 37525 |
ll = bufferPadding + height; |
| 37526 |
|
| 37527 |
// Section F.3.5 VER_SR |
| 37528 |
if (height === 1) { |
| 37529 |
// if height = 1, when v0 even keep items as is, when odd divide by 2 |
| 37530 |
if ((v0 & 1) !== 0) { |
| 37531 |
for (u = 0; u < width; u++) { |
| 37532 |
items[u] *= 0.5; |
| 37533 |
} |
| 37534 |
} |
| 37535 |
} else { |
| 37536 |
for (u = 0; u < width; u++) { |
| 37537 |
// if we ran out of buffers, copy several image columns at once |
| 37538 |
if (currentBuffer === 0) { |
| 37539 |
numBuffers = Math.min(width - u, numBuffers); |
| 37540 |
for (k = u, l = bufferPadding; l < ll; k += width, l++) { |
| 37541 |
for (b = 0; b < numBuffers; b++) { |
| 37542 |
colBuffers[b][l] = items[k + b]; |
| 37543 |
} |
| 37544 |
} |
| 37545 |
currentBuffer = numBuffers; |
| 37546 |
} |
| 37547 |
|
| 37548 |
currentBuffer--; |
| 37549 |
var buffer = colBuffers[currentBuffer]; |
| 37550 |
this.extend(buffer, bufferPadding, height); |
| 37551 |
this.filter(buffer, bufferPadding, height); |
| 37552 |
|
| 37553 |
// If this is last buffer in this group of buffers, flush all buffers. |
| 37554 |
if (currentBuffer === 0) { |
| 37555 |
k = u - numBuffers + 1; |
| 37556 |
for (l = bufferPadding; l < ll; k += width, l++) { |
| 37557 |
for (b = 0; b < numBuffers; b++) { |
| 37558 |
items[k + b] = colBuffers[b][l]; |
| 37559 |
} |
| 37560 |
} |
| 37561 |
} |
| 37562 |
} |
| 37563 |
} |
| 37564 |
|
| 37565 |
return { |
| 37566 |
width: width, |
| 37567 |
height: height, |
| 37568 |
items: items |
| 37569 |
}; |
| 37570 |
}; |
| 37571 |
return Transform; |
| 37572 |
})(); |
| 37573 |
|
| 37574 |
// Section 3.8.2 Irreversible 9-7 filter |
| 37575 |
var IrreversibleTransform = (function IrreversibleTransformClosure() { |
| 37576 |
function IrreversibleTransform() { |
| 37577 |
Transform.call(this); |
| 37578 |
} |
| 37579 |
|
| 37580 |
IrreversibleTransform.prototype = Object.create(Transform.prototype); |
| 37581 |
IrreversibleTransform.prototype.filter = |
| 37582 |
function irreversibleTransformFilter(x, offset, length) { |
| 37583 |
var len = length >> 1; |
| 37584 |
offset = offset | 0; |
| 37585 |
var j, n, current, next; |
| 37586 |
|
| 37587 |
var alpha = -1.586134342059924; |
| 37588 |
var beta = -0.052980118572961; |
| 37589 |
var gamma = 0.882911075530934; |
| 37590 |
var delta = 0.443506852043971; |
| 37591 |
var K = 1.230174104914001; |
| 37592 |
var K_ = 1 / K; |
| 37593 |
|
| 37594 |
// step 1 is combined with step 3 |
| 37595 |
|
| 37596 |
// step 2 |
| 37597 |
j = offset - 3; |
| 37598 |
for (n = len + 4; n--; j += 2) { |
| 37599 |
x[j] *= K_; |
| 37600 |
} |
| 37601 |
|
| 37602 |
// step 1 & 3 |
| 37603 |
j = offset - 2; |
| 37604 |
current = delta * x[j -1]; |
| 37605 |
for (n = len + 3; n--; j += 2) { |
| 37606 |
next = delta * x[j + 1]; |
| 37607 |
x[j] = K * x[j] - current - next; |
| 37608 |
if (n--) { |
| 37609 |
j += 2; |
| 37610 |
current = delta * x[j + 1]; |
| 37611 |
x[j] = K * x[j] - current - next; |
| 37612 |
} else { |
| 37613 |
break; |
| 37614 |
} |
| 37615 |
} |
| 37616 |
|
| 37617 |
// step 4 |
| 37618 |
j = offset - 1; |
| 37619 |
current = gamma * x[j - 1]; |
| 37620 |
for (n = len + 2; n--; j += 2) { |
| 37621 |
next = gamma * x[j + 1]; |
| 37622 |
x[j] -= current + next; |
| 37623 |
if (n--) { |
| 37624 |
j += 2; |
| 37625 |
current = gamma * x[j + 1]; |
| 37626 |
x[j] -= current + next; |
| 37627 |
} else { |
| 37628 |
break; |
| 37629 |
} |
| 37630 |
} |
| 37631 |
|
| 37632 |
// step 5 |
| 37633 |
j = offset; |
| 37634 |
current = beta * x[j - 1]; |
| 37635 |
for (n = len + 1; n--; j += 2) { |
| 37636 |
next = beta * x[j + 1]; |
| 37637 |
x[j] -= current + next; |
| 37638 |
if (n--) { |
| 37639 |
j += 2; |
| 37640 |
current = beta * x[j + 1]; |
| 37641 |
x[j] -= current + next; |
| 37642 |
} else { |
| 37643 |
break; |
| 37644 |
} |
| 37645 |
} |
| 37646 |
|
| 37647 |
// step 6 |
| 37648 |
if (len !== 0) { |
| 37649 |
j = offset + 1; |
| 37650 |
current = alpha * x[j - 1]; |
| 37651 |
for (n = len; n--; j += 2) { |
| 37652 |
next = alpha * x[j + 1]; |
| 37653 |
x[j] -= current + next; |
| 37654 |
if (n--) { |
| 37655 |
j += 2; |
| 37656 |
current = alpha * x[j + 1]; |
| 37657 |
x[j] -= current + next; |
| 37658 |
} else { |
| 37659 |
break; |
| 37660 |
} |
| 37661 |
} |
| 37662 |
} |
| 37663 |
}; |
| 37664 |
|
| 37665 |
return IrreversibleTransform; |
| 37666 |
})(); |
| 37667 |
|
| 37668 |
// Section 3.8.1 Reversible 5-3 filter |
| 37669 |
var ReversibleTransform = (function ReversibleTransformClosure() { |
| 37670 |
function ReversibleTransform() { |
| 37671 |
Transform.call(this); |
| 37672 |
} |
| 37673 |
|
| 37674 |
ReversibleTransform.prototype = Object.create(Transform.prototype); |
| 37675 |
ReversibleTransform.prototype.filter = |
| 37676 |
function reversibleTransformFilter(x, offset, length) { |
| 37677 |
var len = length >> 1; |
| 37678 |
offset = offset | 0; |
| 37679 |
var j, n; |
| 37680 |
|
| 37681 |
for (j = offset, n = len + 1; n--; j += 2) { |
| 37682 |
x[j] -= (x[j - 1] + x[j + 1] + 2) >> 2; |
| 37683 |
} |
| 37684 |
|
| 37685 |
for (j = offset + 1, n = len; n--; j += 2) { |
| 37686 |
x[j] += (x[j - 1] + x[j + 1]) >> 1; |
| 37687 |
} |
| 37688 |
}; |
| 37689 |
|
| 37690 |
return ReversibleTransform; |
| 37691 |
})(); |
| 37692 |
|
| 37693 |
return JpxImage; |
| 37694 |
})(); |
| 37695 |
|
| 37696 |
|
| 37697 |
var Jbig2Image = (function Jbig2ImageClosure() { |
| 37698 |
// Utility data structures |
| 37699 |
function ContextCache() {} |
| 37700 |
|
| 37701 |
ContextCache.prototype = { |
| 37702 |
getContexts: function(id) { |
| 37703 |
if (id in this) { |
| 37704 |
return this[id]; |
| 37705 |
} |
| 37706 |
return (this[id] = new Int8Array(1 << 16)); |
| 37707 |
} |
| 37708 |
}; |
| 37709 |
|
| 37710 |
function DecodingContext(data, start, end) { |
| 37711 |
this.data = data; |
| 37712 |
this.start = start; |
| 37713 |
this.end = end; |
| 37714 |
} |
| 37715 |
|
| 37716 |
DecodingContext.prototype = { |
| 37717 |
get decoder() { |
| 37718 |
var decoder = new ArithmeticDecoder(this.data, this.start, this.end); |
| 37719 |
return shadow(this, 'decoder', decoder); |
| 37720 |
}, |
| 37721 |
get contextCache() { |
| 37722 |
var cache = new ContextCache(); |
| 37723 |
return shadow(this, 'contextCache', cache); |
| 37724 |
} |
| 37725 |
}; |
| 37726 |
|
| 37727 |
// Annex A. Arithmetic Integer Decoding Procedure |
| 37728 |
// A.2 Procedure for decoding values |
| 37729 |
function decodeInteger(contextCache, procedure, decoder) { |
| 37730 |
var contexts = contextCache.getContexts(procedure); |
| 37731 |
var prev = 1; |
| 37732 |
|
| 37733 |
function readBits(length) { |
| 37734 |
var v = 0; |
| 37735 |
for (var i = 0; i < length; i++) { |
| 37736 |
var bit = decoder.readBit(contexts, prev); |
| 37737 |
prev = (prev < 256 ? (prev << 1) | bit : |
| 37738 |
(((prev << 1) | bit) & 511) | 256); |
| 37739 |
v = (v << 1) | bit; |
| 37740 |
} |
| 37741 |
return v >>> 0; |
| 37742 |
} |
| 37743 |
|
| 37744 |
var sign = readBits(1); |
| 37745 |
var value = readBits(1) ? |
| 37746 |
(readBits(1) ? |
| 37747 |
(readBits(1) ? |
| 37748 |
(readBits(1) ? |
| 37749 |
(readBits(1) ? |
| 37750 |
(readBits(32) + 4436) : |
| 37751 |
readBits(12) + 340) : |
| 37752 |
readBits(8) + 84) : |
| 37753 |
readBits(6) + 20) : |
| 37754 |
readBits(4) + 4) : |
| 37755 |
readBits(2); |
| 37756 |
return (sign === 0 ? value : (value > 0 ? -value : null)); |
| 37757 |
} |
| 37758 |
|
| 37759 |
// A.3 The IAID decoding procedure |
| 37760 |
function decodeIAID(contextCache, decoder, codeLength) { |
| 37761 |
var contexts = contextCache.getContexts('IAID'); |
| 37762 |
|
| 37763 |
var prev = 1; |
| 37764 |
for (var i = 0; i < codeLength; i++) { |
| 37765 |
var bit = decoder.readBit(contexts, prev); |
| 37766 |
prev = (prev << 1) | bit; |
| 37767 |
} |
| 37768 |
if (codeLength < 31) { |
| 37769 |
return prev & ((1 << codeLength) - 1); |
| 37770 |
} |
| 37771 |
return prev & 0x7FFFFFFF; |
| 37772 |
} |
| 37773 |
|
| 37774 |
// 7.3 Segment types |
| 37775 |
var SegmentTypes = [ |
| 37776 |
'SymbolDictionary', null, null, null, 'IntermediateTextRegion', null, |
| 37777 |
'ImmediateTextRegion', 'ImmediateLosslessTextRegion', null, null, null, |
| 37778 |
null, null, null, null, null, 'patternDictionary', null, null, null, |
| 37779 |
'IntermediateHalftoneRegion', null, 'ImmediateHalftoneRegion', |
| 37780 |
'ImmediateLosslessHalftoneRegion', null, null, null, null, null, null, null, |
| 37781 |
null, null, null, null, null, 'IntermediateGenericRegion', null, |
| 37782 |
'ImmediateGenericRegion', 'ImmediateLosslessGenericRegion', |
| 37783 |
'IntermediateGenericRefinementRegion', null, |
| 37784 |
'ImmediateGenericRefinementRegion', |
| 37785 |
'ImmediateLosslessGenericRefinementRegion', null, null, null, null, |
| 37786 |
'PageInformation', 'EndOfPage', 'EndOfStripe', 'EndOfFile', 'Profiles', |
| 37787 |
'Tables', null, null, null, null, null, null, null, null, |
| 37788 |
'Extension' |
| 37789 |
]; |
| 37790 |
|
| 37791 |
var CodingTemplates = [ |
| 37792 |
[{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1}, |
| 37793 |
{x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: 2, y: -1}, |
| 37794 |
{x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}], |
| 37795 |
[{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: 2, y: -2}, |
| 37796 |
{x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, |
| 37797 |
{x: 2, y: -1}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}], |
| 37798 |
[{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1}, |
| 37799 |
{x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -2, y: 0}, |
| 37800 |
{x: -1, y: 0}], |
| 37801 |
[{x: -3, y: -1}, {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, |
| 37802 |
{x: 1, y: -1}, {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}] |
| 37803 |
]; |
| 37804 |
|
| 37805 |
var RefinementTemplates = [ |
| 37806 |
{ |
| 37807 |
coding: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}], |
| 37808 |
reference: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, |
| 37809 |
{x: 1, y: 0}, {x: -1, y: 1}, {x: 0, y: 1}, {x: 1, y: 1}] |
| 37810 |
}, |
| 37811 |
{ |
| 37812 |
coding: [{x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}], |
| 37813 |
reference: [{x: 0, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, {x: 1, y: 0}, |
| 37814 |
{x: 0, y: 1}, {x: 1, y: 1}] |
| 37815 |
} |
| 37816 |
]; |
| 37817 |
|
| 37818 |
// See 6.2.5.7 Decoding the bitmap. |
| 37819 |
var ReusedContexts = [ |
| 37820 |
0x9B25, // 10011 0110010 0101 |
| 37821 |
0x0795, // 0011 110010 101 |
| 37822 |
0x00E5, // 001 11001 01 |
| 37823 |
0x0195 // 011001 0101 |
| 37824 |
]; |
| 37825 |
|
| 37826 |
var RefinementReusedContexts = [ |
| 37827 |
0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference) |
| 37828 |
0x0008 // '0000' + '001000' |
| 37829 |
]; |
| 37830 |
|
| 37831 |
function decodeBitmapTemplate0(width, height, decodingContext) { |
| 37832 |
var decoder = decodingContext.decoder; |
| 37833 |
var contexts = decodingContext.contextCache.getContexts('GB'); |
| 37834 |
var contextLabel, i, j, pixel, row, row1, row2, bitmap = []; |
| 37835 |
|
| 37836 |
// ...ooooo.... |
| 37837 |
// ..ooooooo... Context template for current pixel (X) |
| 37838 |
// .ooooX...... (concatenate values of 'o'-pixels to get contextLabel) |
| 37839 |
var OLD_PIXEL_MASK = 0x7BF7; // 01111 0111111 0111 |
| 37840 |
|
| 37841 |
for (i = 0; i < height; i++) { |
| 37842 |
row = bitmap[i] = new Uint8Array(width); |
| 37843 |
row1 = (i < 1) ? row : bitmap[i - 1]; |
| 37844 |
row2 = (i < 2) ? row : bitmap[i - 2]; |
| 37845 |
|
| 37846 |
// At the beginning of each row: |
| 37847 |
// Fill contextLabel with pixels that are above/right of (X) |
| 37848 |
contextLabel = (row2[0] << 13) | (row2[1] << 12) | (row2[2] << 11) | |
| 37849 |
(row1[0] << 7) | (row1[1] << 6) | (row1[2] << 5) | |
| 37850 |
(row1[3] << 4); |
| 37851 |
|
| 37852 |
for (j = 0; j < width; j++) { |
| 37853 |
row[j] = pixel = decoder.readBit(contexts, contextLabel); |
| 37854 |
|
| 37855 |
// At each pixel: Clear contextLabel pixels that are shifted |
| 37856 |
// out of the context, then add new ones. |
| 37857 |
contextLabel = ((contextLabel & OLD_PIXEL_MASK) << 1) | |
| 37858 |
(j + 3 < width ? row2[j + 3] << 11 : 0) | |
| 37859 |
(j + 4 < width ? row1[j + 4] << 4 : 0) | pixel; |
| 37860 |
} |
| 37861 |
} |
| 37862 |
|
| 37863 |
return bitmap; |
| 37864 |
} |
| 37865 |
|
| 37866 |
// 6.2 Generic Region Decoding Procedure |
| 37867 |
function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, |
| 37868 |
decodingContext) { |
| 37869 |
if (mmr) { |
| 37870 |
error('JBIG2 error: MMR encoding is not supported'); |
| 37871 |
} |
| 37872 |
|
| 37873 |
// Use optimized version for the most common case |
| 37874 |
if (templateIndex === 0 && !skip && !prediction && at.length === 4 && |
| 37875 |
at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && |
| 37876 |
at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) { |
| 37877 |
return decodeBitmapTemplate0(width, height, decodingContext); |
| 37878 |
} |
| 37879 |
|
| 37880 |
var useskip = !!skip; |
| 37881 |
var template = CodingTemplates[templateIndex].concat(at); |
| 37882 |
|
| 37883 |
// Sorting is non-standard, and it is not required. But sorting increases |
| 37884 |
// the number of template bits that can be reused from the previous |
| 37885 |
// contextLabel in the main loop. |
| 37886 |
template.sort(function (a, b) { |
| 37887 |
return (a.y - b.y) || (a.x - b.x); |
| 37888 |
}); |
| 37889 |
|
| 37890 |
var templateLength = template.length; |
| 37891 |
var templateX = new Int8Array(templateLength); |
| 37892 |
var templateY = new Int8Array(templateLength); |
| 37893 |
var changingTemplateEntries = []; |
| 37894 |
var reuseMask = 0, minX = 0, maxX = 0, minY = 0; |
| 37895 |
var c, k; |
| 37896 |
|
| 37897 |
for (k = 0; k < templateLength; k++) { |
| 37898 |
templateX[k] = template[k].x; |
| 37899 |
templateY[k] = template[k].y; |
| 37900 |
minX = Math.min(minX, template[k].x); |
| 37901 |
maxX = Math.max(maxX, template[k].x); |
| 37902 |
minY = Math.min(minY, template[k].y); |
| 37903 |
// Check if the template pixel appears in two consecutive context labels, |
| 37904 |
// so it can be reused. Otherwise, we add it to the list of changing |
| 37905 |
// template entries. |
| 37906 |
if (k < templateLength - 1 && |
| 37907 |
template[k].y === template[k + 1].y && |
| 37908 |
template[k].x === template[k + 1].x - 1) { |
| 37909 |
reuseMask |= 1 << (templateLength - 1 - k); |
| 37910 |
} else { |
| 37911 |
changingTemplateEntries.push(k); |
| 37912 |
} |
| 37913 |
} |
| 37914 |
var changingEntriesLength = changingTemplateEntries.length; |
| 37915 |
|
| 37916 |
var changingTemplateX = new Int8Array(changingEntriesLength); |
| 37917 |
var changingTemplateY = new Int8Array(changingEntriesLength); |
| 37918 |
var changingTemplateBit = new Uint16Array(changingEntriesLength); |
| 37919 |
for (c = 0; c < changingEntriesLength; c++) { |
| 37920 |
k = changingTemplateEntries[c]; |
| 37921 |
changingTemplateX[c] = template[k].x; |
| 37922 |
changingTemplateY[c] = template[k].y; |
| 37923 |
changingTemplateBit[c] = 1 << (templateLength - 1 - k); |
| 37924 |
} |
| 37925 |
|
| 37926 |
// Get the safe bounding box edges from the width, height, minX, maxX, minY |
| 37927 |
var sbb_left = -minX; |
| 37928 |
var sbb_top = -minY; |
| 37929 |
var sbb_right = width - maxX; |
| 37930 |
|
| 37931 |
var pseudoPixelContext = ReusedContexts[templateIndex]; |
| 37932 |
var row = new Uint8Array(width); |
| 37933 |
var bitmap = []; |
| 37934 |
|
| 37935 |
var decoder = decodingContext.decoder; |
| 37936 |
var contexts = decodingContext.contextCache.getContexts('GB'); |
| 37937 |
|
| 37938 |
var ltp = 0, j, i0, j0, contextLabel = 0, bit, shift; |
| 37939 |
for (var i = 0; i < height; i++) { |
| 37940 |
if (prediction) { |
| 37941 |
var sltp = decoder.readBit(contexts, pseudoPixelContext); |
| 37942 |
ltp ^= sltp; |
| 37943 |
if (ltp) { |
| 37944 |
bitmap.push(row); // duplicate previous row |
| 37945 |
continue; |
| 37946 |
} |
| 37947 |
} |
| 37948 |
row = new Uint8Array(row); |
| 37949 |
bitmap.push(row); |
| 37950 |
for (j = 0; j < width; j++) { |
| 37951 |
if (useskip && skip[i][j]) { |
| 37952 |
row[j] = 0; |
| 37953 |
continue; |
| 37954 |
} |
| 37955 |
// Are we in the middle of a scanline, so we can reuse contextLabel |
| 37956 |
// bits? |
| 37957 |
if (j >= sbb_left && j < sbb_right && i >= sbb_top) { |
| 37958 |
// If yes, we can just shift the bits that are reusable and only |
| 37959 |
// fetch the remaining ones. |
| 37960 |
contextLabel = (contextLabel << 1) & reuseMask; |
| 37961 |
for (k = 0; k < changingEntriesLength; k++) { |
| 37962 |
i0 = i + changingTemplateY[k]; |
| 37963 |
j0 = j + changingTemplateX[k]; |
| 37964 |
bit = bitmap[i0][j0]; |
| 37965 |
if (bit) { |
| 37966 |
bit = changingTemplateBit[k]; |
| 37967 |
contextLabel |= bit; |
| 37968 |
} |
| 37969 |
} |
| 37970 |
} else { |
| 37971 |
// compute the contextLabel from scratch |
| 37972 |
contextLabel = 0; |
| 37973 |
shift = templateLength - 1; |
| 37974 |
for (k = 0; k < templateLength; k++, shift--) { |
| 37975 |
j0 = j + templateX[k]; |
| 37976 |
if (j0 >= 0 && j0 < width) { |
| 37977 |
i0 = i + templateY[k]; |
| 37978 |
if (i0 >= 0) { |
| 37979 |
bit = bitmap[i0][j0]; |
| 37980 |
if (bit) { |
| 37981 |
contextLabel |= bit << shift; |
| 37982 |
} |
| 37983 |
} |
| 37984 |
} |
| 37985 |
} |
| 37986 |
} |
| 37987 |
var pixel = decoder.readBit(contexts, contextLabel); |
| 37988 |
row[j] = pixel; |
| 37989 |
} |
| 37990 |
} |
| 37991 |
return bitmap; |
| 37992 |
} |
| 37993 |
|
| 37994 |
// 6.3.2 Generic Refinement Region Decoding Procedure |
| 37995 |
function decodeRefinement(width, height, templateIndex, referenceBitmap, |
| 37996 |
offsetX, offsetY, prediction, at, |
| 37997 |
decodingContext) { |
| 37998 |
var codingTemplate = RefinementTemplates[templateIndex].coding; |
| 37999 |
if (templateIndex === 0) { |
| 38000 |
codingTemplate = codingTemplate.concat([at[0]]); |
| 38001 |
} |
| 38002 |
var codingTemplateLength = codingTemplate.length; |
| 38003 |
var codingTemplateX = new Int32Array(codingTemplateLength); |
| 38004 |
var codingTemplateY = new Int32Array(codingTemplateLength); |
| 38005 |
var k; |
| 38006 |
for (k = 0; k < codingTemplateLength; k++) { |
| 38007 |
codingTemplateX[k] = codingTemplate[k].x; |
| 38008 |
codingTemplateY[k] = codingTemplate[k].y; |
| 38009 |
} |
| 38010 |
|
| 38011 |
var referenceTemplate = RefinementTemplates[templateIndex].reference; |
| 38012 |
if (templateIndex === 0) { |
| 38013 |
referenceTemplate = referenceTemplate.concat([at[1]]); |
| 38014 |
} |
| 38015 |
var referenceTemplateLength = referenceTemplate.length; |
| 38016 |
var referenceTemplateX = new Int32Array(referenceTemplateLength); |
| 38017 |
var referenceTemplateY = new Int32Array(referenceTemplateLength); |
| 38018 |
for (k = 0; k < referenceTemplateLength; k++) { |
| 38019 |
referenceTemplateX[k] = referenceTemplate[k].x; |
| 38020 |
referenceTemplateY[k] = referenceTemplate[k].y; |
| 38021 |
} |
| 38022 |
var referenceWidth = referenceBitmap[0].length; |
| 38023 |
var referenceHeight = referenceBitmap.length; |
| 38024 |
|
| 38025 |
var pseudoPixelContext = RefinementReusedContexts[templateIndex]; |
| 38026 |
var bitmap = []; |
| 38027 |
|
| 38028 |
var decoder = decodingContext.decoder; |
| 38029 |
var contexts = decodingContext.contextCache.getContexts('GR'); |
| 38030 |
|
| 38031 |
var ltp = 0; |
| 38032 |
for (var i = 0; i < height; i++) { |
| 38033 |
if (prediction) { |
| 38034 |
var sltp = decoder.readBit(contexts, pseudoPixelContext); |
| 38035 |
ltp ^= sltp; |
| 38036 |
if (ltp) { |
| 38037 |
error('JBIG2 error: prediction is not supported'); |
| 38038 |
} |
| 38039 |
} |
| 38040 |
var row = new Uint8Array(width); |
| 38041 |
bitmap.push(row); |
| 38042 |
for (var j = 0; j < width; j++) { |
| 38043 |
var i0, j0; |
| 38044 |
var contextLabel = 0; |
| 38045 |
for (k = 0; k < codingTemplateLength; k++) { |
| 38046 |
i0 = i + codingTemplateY[k]; |
| 38047 |
j0 = j + codingTemplateX[k]; |
| 38048 |
if (i0 < 0 || j0 < 0 || j0 >= width) { |
| 38049 |
contextLabel <<= 1; // out of bound pixel |
| 38050 |
} else { |
| 38051 |
contextLabel = (contextLabel << 1) | bitmap[i0][j0]; |
| 38052 |
} |
| 38053 |
} |
| 38054 |
for (k = 0; k < referenceTemplateLength; k++) { |
| 38055 |
i0 = i + referenceTemplateY[k] + offsetY; |
| 38056 |
j0 = j + referenceTemplateX[k] + offsetX; |
| 38057 |
if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || |
| 38058 |
j0 >= referenceWidth) { |
| 38059 |
contextLabel <<= 1; // out of bound pixel |
| 38060 |
} else { |
| 38061 |
contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0]; |
| 38062 |
} |
| 38063 |
} |
| 38064 |
var pixel = decoder.readBit(contexts, contextLabel); |
| 38065 |
row[j] = pixel; |
| 38066 |
} |
| 38067 |
} |
| 38068 |
|
| 38069 |
return bitmap; |
| 38070 |
} |
| 38071 |
|
| 38072 |
// 6.5.5 Decoding the symbol dictionary |
| 38073 |
function decodeSymbolDictionary(huffman, refinement, symbols, |
| 38074 |
numberOfNewSymbols, numberOfExportedSymbols, |
| 38075 |
huffmanTables, templateIndex, at, |
| 38076 |
refinementTemplateIndex, refinementAt, |
| 38077 |
decodingContext) { |
| 38078 |
if (huffman) { |
| 38079 |
error('JBIG2 error: huffman is not supported'); |
| 38080 |
} |
| 38081 |
|
| 38082 |
var newSymbols = []; |
| 38083 |
var currentHeight = 0; |
| 38084 |
var symbolCodeLength = log2(symbols.length + numberOfNewSymbols); |
| 38085 |
|
| 38086 |
var decoder = decodingContext.decoder; |
| 38087 |
var contextCache = decodingContext.contextCache; |
| 38088 |
|
| 38089 |
while (newSymbols.length < numberOfNewSymbols) { |
| 38090 |
var deltaHeight = decodeInteger(contextCache, 'IADH', decoder); // 6.5.6 |
| 38091 |
currentHeight += deltaHeight; |
| 38092 |
var currentWidth = 0; |
| 38093 |
var totalWidth = 0; |
| 38094 |
while (true) { |
| 38095 |
var deltaWidth = decodeInteger(contextCache, 'IADW', decoder); // 6.5.7 |
| 38096 |
if (deltaWidth === null) { |
| 38097 |
break; // OOB |
| 38098 |
} |
| 38099 |
currentWidth += deltaWidth; |
| 38100 |
totalWidth += currentWidth; |
| 38101 |
var bitmap; |
| 38102 |
if (refinement) { |
| 38103 |
// 6.5.8.2 Refinement/aggregate-coded symbol bitmap |
| 38104 |
var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder); |
| 38105 |
if (numberOfInstances > 1) { |
| 38106 |
bitmap = decodeTextRegion(huffman, refinement, |
| 38107 |
currentWidth, currentHeight, 0, |
| 38108 |
numberOfInstances, 1, //strip size |
| 38109 |
symbols.concat(newSymbols), |
| 38110 |
symbolCodeLength, |
| 38111 |
0, //transposed |
| 38112 |
0, //ds offset |
| 38113 |
1, //top left 7.4.3.1.1 |
| 38114 |
0, //OR operator |
| 38115 |
huffmanTables, |
| 38116 |
refinementTemplateIndex, refinementAt, |
| 38117 |
decodingContext); |
| 38118 |
} else { |
| 38119 |
var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); |
| 38120 |
var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3 |
| 38121 |
var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4 |
| 38122 |
var symbol = (symbolId < symbols.length ? symbols[symbolId] : |
| 38123 |
newSymbols[symbolId - symbols.length]); |
| 38124 |
bitmap = decodeRefinement(currentWidth, currentHeight, |
| 38125 |
refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, |
| 38126 |
decodingContext); |
| 38127 |
} |
| 38128 |
} else { |
| 38129 |
// 6.5.8.1 Direct-coded symbol bitmap |
| 38130 |
bitmap = decodeBitmap(false, currentWidth, currentHeight, |
| 38131 |
templateIndex, false, null, at, decodingContext); |
| 38132 |
} |
| 38133 |
newSymbols.push(bitmap); |
| 38134 |
} |
| 38135 |
} |
| 38136 |
// 6.5.10 Exported symbols |
| 38137 |
var exportedSymbols = []; |
| 38138 |
var flags = [], currentFlag = false; |
| 38139 |
var totalSymbolsLength = symbols.length + numberOfNewSymbols; |
| 38140 |
while (flags.length < totalSymbolsLength) { |
| 38141 |
var runLength = decodeInteger(contextCache, 'IAEX', decoder); |
| 38142 |
while (runLength--) { |
| 38143 |
flags.push(currentFlag); |
| 38144 |
} |
| 38145 |
currentFlag = !currentFlag; |
| 38146 |
} |
| 38147 |
for (var i = 0, ii = symbols.length; i < ii; i++) { |
| 38148 |
if (flags[i]) { |
| 38149 |
exportedSymbols.push(symbols[i]); |
| 38150 |
} |
| 38151 |
} |
| 38152 |
for (var j = 0; j < numberOfNewSymbols; i++, j++) { |
| 38153 |
if (flags[i]) { |
| 38154 |
exportedSymbols.push(newSymbols[j]); |
| 38155 |
} |
| 38156 |
} |
| 38157 |
return exportedSymbols; |
| 38158 |
} |
| 38159 |
|
| 38160 |
function decodeTextRegion(huffman, refinement, width, height, |
| 38161 |
defaultPixelValue, numberOfSymbolInstances, |
| 38162 |
stripSize, inputSymbols, symbolCodeLength, |
| 38163 |
transposed, dsOffset, referenceCorner, |
| 38164 |
combinationOperator, huffmanTables, |
| 38165 |
refinementTemplateIndex, refinementAt, |
| 38166 |
decodingContext) { |
| 38167 |
if (huffman) { |
| 38168 |
error('JBIG2 error: huffman is not supported'); |
| 38169 |
} |
| 38170 |
|
| 38171 |
// Prepare bitmap |
| 38172 |
var bitmap = []; |
| 38173 |
var i, row; |
| 38174 |
for (i = 0; i < height; i++) { |
| 38175 |
row = new Uint8Array(width); |
| 38176 |
if (defaultPixelValue) { |
| 38177 |
for (var j = 0; j < width; j++) { |
| 38178 |
row[j] = defaultPixelValue; |
| 38179 |
} |
| 38180 |
} |
| 38181 |
bitmap.push(row); |
| 38182 |
} |
| 38183 |
|
| 38184 |
var decoder = decodingContext.decoder; |
| 38185 |
var contextCache = decodingContext.contextCache; |
| 38186 |
var stripT = -decodeInteger(contextCache, 'IADT', decoder); // 6.4.6 |
| 38187 |
var firstS = 0; |
| 38188 |
i = 0; |
| 38189 |
while (i < numberOfSymbolInstances) { |
| 38190 |
var deltaT = decodeInteger(contextCache, 'IADT', decoder); // 6.4.6 |
| 38191 |
stripT += deltaT; |
| 38192 |
|
| 38193 |
var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder); // 6.4.7 |
| 38194 |
firstS += deltaFirstS; |
| 38195 |
var currentS = firstS; |
| 38196 |
do { |
| 38197 |
var currentT = (stripSize === 1 ? 0 : |
| 38198 |
decodeInteger(contextCache, 'IAIT', decoder)); // 6.4.9 |
| 38199 |
var t = stripSize * stripT + currentT; |
| 38200 |
var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); |
| 38201 |
var applyRefinement = (refinement && |
| 38202 |
decodeInteger(contextCache, 'IARI', decoder)); |
| 38203 |
var symbolBitmap = inputSymbols[symbolId]; |
| 38204 |
var symbolWidth = symbolBitmap[0].length; |
| 38205 |
var symbolHeight = symbolBitmap.length; |
| 38206 |
if (applyRefinement) { |
| 38207 |
var rdw = decodeInteger(contextCache, 'IARDW', decoder); // 6.4.11.1 |
| 38208 |
var rdh = decodeInteger(contextCache, 'IARDH', decoder); // 6.4.11.2 |
| 38209 |
var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3 |
| 38210 |
var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4 |
| 38211 |
symbolWidth += rdw; |
| 38212 |
symbolHeight += rdh; |
| 38213 |
symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, |
| 38214 |
refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, |
| 38215 |
(rdh >> 1) + rdy, false, refinementAt, |
| 38216 |
decodingContext); |
| 38217 |
} |
| 38218 |
var offsetT = t - ((referenceCorner & 1) ? 0 : symbolHeight); |
| 38219 |
var offsetS = currentS - ((referenceCorner & 2) ? symbolWidth : 0); |
| 38220 |
var s2, t2, symbolRow; |
| 38221 |
if (transposed) { |
| 38222 |
// Place Symbol Bitmap from T1,S1 |
| 38223 |
for (s2 = 0; s2 < symbolHeight; s2++) { |
| 38224 |
row = bitmap[offsetS + s2]; |
| 38225 |
if (!row) { |
| 38226 |
continue; |
| 38227 |
} |
| 38228 |
symbolRow = symbolBitmap[s2]; |
| 38229 |
// To ignore Parts of Symbol bitmap which goes |
| 38230 |
// outside bitmap region |
| 38231 |
var maxWidth = Math.min(width - offsetT, symbolWidth); |
| 38232 |
switch (combinationOperator) { |
| 38233 |
case 0: // OR |
| 38234 |
for (t2 = 0; t2 < maxWidth; t2++) { |
| 38235 |
row[offsetT + t2] |= symbolRow[t2]; |
| 38236 |
} |
| 38237 |
break; |
| 38238 |
case 2: // XOR |
| 38239 |
for (t2 = 0; t2 < maxWidth; t2++) { |
| 38240 |
row[offsetT + t2] ^= symbolRow[t2]; |
| 38241 |
} |
| 38242 |
break; |
| 38243 |
default: |
| 38244 |
error('JBIG2 error: operator ' + combinationOperator + |
| 38245 |
' is not supported'); |
| 38246 |
} |
| 38247 |
} |
| 38248 |
currentS += symbolHeight - 1; |
| 38249 |
} else { |
| 38250 |
for (t2 = 0; t2 < symbolHeight; t2++) { |
| 38251 |
row = bitmap[offsetT + t2]; |
| 38252 |
if (!row) { |
| 38253 |
continue; |
| 38254 |
} |
| 38255 |
symbolRow = symbolBitmap[t2]; |
| 38256 |
switch (combinationOperator) { |
| 38257 |
case 0: // OR |
| 38258 |
for (s2 = 0; s2 < symbolWidth; s2++) { |
| 38259 |
row[offsetS + s2] |= symbolRow[s2]; |
| 38260 |
} |
| 38261 |
break; |
| 38262 |
case 2: // XOR |
| 38263 |
for (s2 = 0; s2 < symbolWidth; s2++) { |
| 38264 |
row[offsetS + s2] ^= symbolRow[s2]; |
| 38265 |
} |
| 38266 |
break; |
| 38267 |
default: |
| 38268 |
error('JBIG2 error: operator ' + combinationOperator + |
| 38269 |
' is not supported'); |
| 38270 |
} |
| 38271 |
} |
| 38272 |
currentS += symbolWidth - 1; |
| 38273 |
} |
| 38274 |
i++; |
| 38275 |
var deltaS = decodeInteger(contextCache, 'IADS', decoder); // 6.4.8 |
| 38276 |
if (deltaS === null) { |
| 38277 |
break; // OOB |
| 38278 |
} |
| 38279 |
currentS += deltaS + dsOffset; |
| 38280 |
} while (true); |
| 38281 |
} |
| 38282 |
return bitmap; |
| 38283 |
} |
| 38284 |
|
| 38285 |
function readSegmentHeader(data, start) { |
| 38286 |
var segmentHeader = {}; |
| 38287 |
segmentHeader.number = readUint32(data, start); |
| 38288 |
var flags = data[start + 4]; |
| 38289 |
var segmentType = flags & 0x3F; |
| 38290 |
if (!SegmentTypes[segmentType]) { |
| 38291 |
error('JBIG2 error: invalid segment type: ' + segmentType); |
| 38292 |
} |
| 38293 |
segmentHeader.type = segmentType; |
| 38294 |
segmentHeader.typeName = SegmentTypes[segmentType]; |
| 38295 |
segmentHeader.deferredNonRetain = !!(flags & 0x80); |
| 38296 |
|
| 38297 |
var pageAssociationFieldSize = !!(flags & 0x40); |
| 38298 |
var referredFlags = data[start + 5]; |
| 38299 |
var referredToCount = (referredFlags >> 5) & 7; |
| 38300 |
var retainBits = [referredFlags & 31]; |
| 38301 |
var position = start + 6; |
| 38302 |
if (referredFlags === 7) { |
| 38303 |
referredToCount = readUint32(data, position - 1) & 0x1FFFFFFF; |
| 38304 |
position += 3; |
| 38305 |
var bytes = (referredToCount + 7) >> 3; |
| 38306 |
retainBits[0] = data[position++]; |
| 38307 |
while (--bytes > 0) { |
| 38308 |
retainBits.push(data[position++]); |
| 38309 |
} |
| 38310 |
} else if (referredFlags === 5 || referredFlags === 6) { |
| 38311 |
error('JBIG2 error: invalid referred-to flags'); |
| 38312 |
} |
| 38313 |
|
| 38314 |
segmentHeader.retainBits = retainBits; |
| 38315 |
var referredToSegmentNumberSize = (segmentHeader.number <= 256 ? 1 : |
| 38316 |
(segmentHeader.number <= 65536 ? 2 : 4)); |
| 38317 |
var referredTo = []; |
| 38318 |
var i, ii; |
| 38319 |
for (i = 0; i < referredToCount; i++) { |
| 38320 |
var number = (referredToSegmentNumberSize === 1 ? data[position] : |
| 38321 |
(referredToSegmentNumberSize === 2 ? readUint16(data, position) : |
| 38322 |
readUint32(data, position))); |
| 38323 |
referredTo.push(number); |
| 38324 |
position += referredToSegmentNumberSize; |
| 38325 |
} |
| 38326 |
segmentHeader.referredTo = referredTo; |
| 38327 |
if (!pageAssociationFieldSize) { |
| 38328 |
segmentHeader.pageAssociation = data[position++]; |
| 38329 |
} else { |
| 38330 |
segmentHeader.pageAssociation = readUint32(data, position); |
| 38331 |
position += 4; |
| 38332 |
} |
| 38333 |
segmentHeader.length = readUint32(data, position); |
| 38334 |
position += 4; |
| 38335 |
|
| 38336 |
if (segmentHeader.length === 0xFFFFFFFF) { |
| 38337 |
// 7.2.7 Segment data length, unknown segment length |
| 38338 |
if (segmentType === 38) { // ImmediateGenericRegion |
| 38339 |
var genericRegionInfo = readRegionSegmentInformation(data, position); |
| 38340 |
var genericRegionSegmentFlags = data[position + |
| 38341 |
RegionSegmentInformationFieldLength]; |
| 38342 |
var genericRegionMmr = !!(genericRegionSegmentFlags & 1); |
| 38343 |
// searching for the segment end |
| 38344 |
var searchPatternLength = 6; |
| 38345 |
var searchPattern = new Uint8Array(searchPatternLength); |
| 38346 |
if (!genericRegionMmr) { |
| 38347 |
searchPattern[0] = 0xFF; |
| 38348 |
searchPattern[1] = 0xAC; |
| 38349 |
} |
| 38350 |
searchPattern[2] = (genericRegionInfo.height >>> 24) & 0xFF; |
| 38351 |
searchPattern[3] = (genericRegionInfo.height >> 16) & 0xFF; |
| 38352 |
searchPattern[4] = (genericRegionInfo.height >> 8) & 0xFF; |
| 38353 |
searchPattern[5] = genericRegionInfo.height & 0xFF; |
| 38354 |
for (i = position, ii = data.length; i < ii; i++) { |
| 38355 |
var j = 0; |
| 38356 |
while (j < searchPatternLength && searchPattern[j] === data[i + j]) { |
| 38357 |
j++; |
| 38358 |
} |
| 38359 |
if (j === searchPatternLength) { |
| 38360 |
segmentHeader.length = i + searchPatternLength; |
| 38361 |
break; |
| 38362 |
} |
| 38363 |
} |
| 38364 |
if (segmentHeader.length === 0xFFFFFFFF) { |
| 38365 |
error('JBIG2 error: segment end was not found'); |
| 38366 |
} |
| 38367 |
} else { |
| 38368 |
error('JBIG2 error: invalid unknown segment length'); |
| 38369 |
} |
| 38370 |
} |
| 38371 |
segmentHeader.headerEnd = position; |
| 38372 |
return segmentHeader; |
| 38373 |
} |
| 38374 |
|
| 38375 |
function readSegments(header, data, start, end) { |
| 38376 |
var segments = []; |
| 38377 |
var position = start; |
| 38378 |
while (position < end) { |
| 38379 |
var segmentHeader = readSegmentHeader(data, position); |
| 38380 |
position = segmentHeader.headerEnd; |
| 38381 |
var segment = { |
| 38382 |
header: segmentHeader, |
| 38383 |
data: data |
| 38384 |
}; |
| 38385 |
if (!header.randomAccess) { |
| 38386 |
segment.start = position; |
| 38387 |
position += segmentHeader.length; |
| 38388 |
segment.end = position; |
| 38389 |
} |
| 38390 |
segments.push(segment); |
| 38391 |
if (segmentHeader.type === 51) { |
| 38392 |
break; // end of file is found |
| 38393 |
} |
| 38394 |
} |
| 38395 |
if (header.randomAccess) { |
| 38396 |
for (var i = 0, ii = segments.length; i < ii; i++) { |
| 38397 |
segments[i].start = position; |
| 38398 |
position += segments[i].header.length; |
| 38399 |
segments[i].end = position; |
| 38400 |
} |
| 38401 |
} |
| 38402 |
return segments; |
| 38403 |
} |
| 38404 |
|
| 38405 |
// 7.4.1 Region segment information field |
| 38406 |
function readRegionSegmentInformation(data, start) { |
| 38407 |
return { |
| 38408 |
width: readUint32(data, start), |
| 38409 |
height: readUint32(data, start + 4), |
| 38410 |
x: readUint32(data, start + 8), |
| 38411 |
y: readUint32(data, start + 12), |
| 38412 |
combinationOperator: data[start + 16] & 7 |
| 38413 |
}; |
| 38414 |
} |
| 38415 |
var RegionSegmentInformationFieldLength = 17; |
| 38416 |
|
| 38417 |
function processSegment(segment, visitor) { |
| 38418 |
var header = segment.header; |
| 38419 |
|
| 38420 |
var data = segment.data, position = segment.start, end = segment.end; |
| 38421 |
var args, at, i, atLength; |
| 38422 |
switch (header.type) { |
| 38423 |
case 0: // SymbolDictionary |
| 38424 |
// 7.4.2 Symbol dictionary segment syntax |
| 38425 |
var dictionary = {}; |
| 38426 |
var dictionaryFlags = readUint16(data, position); // 7.4.2.1.1 |
| 38427 |
dictionary.huffman = !!(dictionaryFlags & 1); |
| 38428 |
dictionary.refinement = !!(dictionaryFlags & 2); |
| 38429 |
dictionary.huffmanDHSelector = (dictionaryFlags >> 2) & 3; |
| 38430 |
dictionary.huffmanDWSelector = (dictionaryFlags >> 4) & 3; |
| 38431 |
dictionary.bitmapSizeSelector = (dictionaryFlags >> 6) & 1; |
| 38432 |
dictionary.aggregationInstancesSelector = (dictionaryFlags >> 7) & 1; |
| 38433 |
dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256); |
| 38434 |
dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512); |
| 38435 |
dictionary.template = (dictionaryFlags >> 10) & 3; |
| 38436 |
dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1; |
| 38437 |
position += 2; |
| 38438 |
if (!dictionary.huffman) { |
| 38439 |
atLength = dictionary.template === 0 ? 4 : 1; |
| 38440 |
at = []; |
| 38441 |
for (i = 0; i < atLength; i++) { |
| 38442 |
at.push({ |
| 38443 |
x: readInt8(data, position), |
| 38444 |
y: readInt8(data, position + 1) |
| 38445 |
}); |
| 38446 |
position += 2; |
| 38447 |
} |
| 38448 |
dictionary.at = at; |
| 38449 |
} |
| 38450 |
if (dictionary.refinement && !dictionary.refinementTemplate) { |
| 38451 |
at = []; |
| 38452 |
for (i = 0; i < 2; i++) { |
| 38453 |
at.push({ |
| 38454 |
x: readInt8(data, position), |
| 38455 |
y: readInt8(data, position + 1) |
| 38456 |
}); |
| 38457 |
position += 2; |
| 38458 |
} |
| 38459 |
dictionary.refinementAt = at; |
| 38460 |
} |
| 38461 |
dictionary.numberOfExportedSymbols = readUint32(data, position); |
| 38462 |
position += 4; |
| 38463 |
dictionary.numberOfNewSymbols = readUint32(data, position); |
| 38464 |
position += 4; |
| 38465 |
args = [dictionary, header.number, header.referredTo, |
| 38466 |
data, position, end]; |
| 38467 |
break; |
| 38468 |
case 6: // ImmediateTextRegion |
| 38469 |
case 7: // ImmediateLosslessTextRegion |
| 38470 |
var textRegion = {}; |
| 38471 |
textRegion.info = readRegionSegmentInformation(data, position); |
| 38472 |
position += RegionSegmentInformationFieldLength; |
| 38473 |
var textRegionSegmentFlags = readUint16(data, position); |
| 38474 |
position += 2; |
| 38475 |
textRegion.huffman = !!(textRegionSegmentFlags & 1); |
| 38476 |
textRegion.refinement = !!(textRegionSegmentFlags & 2); |
| 38477 |
textRegion.stripSize = 1 << ((textRegionSegmentFlags >> 2) & 3); |
| 38478 |
textRegion.referenceCorner = (textRegionSegmentFlags >> 4) & 3; |
| 38479 |
textRegion.transposed = !!(textRegionSegmentFlags & 64); |
| 38480 |
textRegion.combinationOperator = (textRegionSegmentFlags >> 7) & 3; |
| 38481 |
textRegion.defaultPixelValue = (textRegionSegmentFlags >> 9) & 1; |
| 38482 |
textRegion.dsOffset = (textRegionSegmentFlags << 17) >> 27; |
| 38483 |
textRegion.refinementTemplate = (textRegionSegmentFlags >> 15) & 1; |
| 38484 |
if (textRegion.huffman) { |
| 38485 |
var textRegionHuffmanFlags = readUint16(data, position); |
| 38486 |
position += 2; |
| 38487 |
textRegion.huffmanFS = (textRegionHuffmanFlags) & 3; |
| 38488 |
textRegion.huffmanDS = (textRegionHuffmanFlags >> 2) & 3; |
| 38489 |
textRegion.huffmanDT = (textRegionHuffmanFlags >> 4) & 3; |
| 38490 |
textRegion.huffmanRefinementDW = (textRegionHuffmanFlags >> 6) & 3; |
| 38491 |
textRegion.huffmanRefinementDH = (textRegionHuffmanFlags >> 8) & 3; |
| 38492 |
textRegion.huffmanRefinementDX = (textRegionHuffmanFlags >> 10) & 3; |
| 38493 |
textRegion.huffmanRefinementDY = (textRegionHuffmanFlags >> 12) & 3; |
| 38494 |
textRegion.huffmanRefinementSizeSelector = |
| 38495 |
!!(textRegionHuffmanFlags & 14); |
| 38496 |
} |
| 38497 |
if (textRegion.refinement && !textRegion.refinementTemplate) { |
| 38498 |
at = []; |
| 38499 |
for (i = 0; i < 2; i++) { |
| 38500 |
at.push({ |
| 38501 |
x: readInt8(data, position), |
| 38502 |
y: readInt8(data, position + 1) |
| 38503 |
}); |
| 38504 |
position += 2; |
| 38505 |
} |
| 38506 |
textRegion.refinementAt = at; |
| 38507 |
} |
| 38508 |
textRegion.numberOfSymbolInstances = readUint32(data, position); |
| 38509 |
position += 4; |
| 38510 |
// TODO 7.4.3.1.7 Symbol ID Huffman table decoding |
| 38511 |
if (textRegion.huffman) { |
| 38512 |
error('JBIG2 error: huffman is not supported'); |
| 38513 |
} |
| 38514 |
args = [textRegion, header.referredTo, data, position, end]; |
| 38515 |
break; |
| 38516 |
case 38: // ImmediateGenericRegion |
| 38517 |
case 39: // ImmediateLosslessGenericRegion |
| 38518 |
var genericRegion = {}; |
| 38519 |
genericRegion.info = readRegionSegmentInformation(data, position); |
| 38520 |
position += RegionSegmentInformationFieldLength; |
| 38521 |
var genericRegionSegmentFlags = data[position++]; |
| 38522 |
genericRegion.mmr = !!(genericRegionSegmentFlags & 1); |
| 38523 |
genericRegion.template = (genericRegionSegmentFlags >> 1) & 3; |
| 38524 |
genericRegion.prediction = !!(genericRegionSegmentFlags & 8); |
| 38525 |
if (!genericRegion.mmr) { |
| 38526 |
atLength = genericRegion.template === 0 ? 4 : 1; |
| 38527 |
at = []; |
| 38528 |
for (i = 0; i < atLength; i++) { |
| 38529 |
at.push({ |
| 38530 |
x: readInt8(data, position), |
| 38531 |
y: readInt8(data, position + 1) |
| 38532 |
}); |
| 38533 |
position += 2; |
| 38534 |
} |
| 38535 |
genericRegion.at = at; |
| 38536 |
} |
| 38537 |
args = [genericRegion, data, position, end]; |
| 38538 |
break; |
| 38539 |
case 48: // PageInformation |
| 38540 |
var pageInfo = { |
| 38541 |
width: readUint32(data, position), |
| 38542 |
height: readUint32(data, position + 4), |
| 38543 |
resolutionX: readUint32(data, position + 8), |
| 38544 |
resolutionY: readUint32(data, position + 12) |
| 38545 |
}; |
| 38546 |
if (pageInfo.height === 0xFFFFFFFF) { |
| 38547 |
delete pageInfo.height; |
| 38548 |
} |
| 38549 |
var pageSegmentFlags = data[position + 16]; |
| 38550 |
var pageStripingInformatiom = readUint16(data, position + 17); |
| 38551 |
pageInfo.lossless = !!(pageSegmentFlags & 1); |
| 38552 |
pageInfo.refinement = !!(pageSegmentFlags & 2); |
| 38553 |
pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1; |
| 38554 |
pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3; |
| 38555 |
pageInfo.requiresBuffer = !!(pageSegmentFlags & 32); |
| 38556 |
pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64); |
| 38557 |
args = [pageInfo]; |
| 38558 |
break; |
| 38559 |
case 49: // EndOfPage |
| 38560 |
break; |
| 38561 |
case 50: // EndOfStripe |
| 38562 |
break; |
| 38563 |
case 51: // EndOfFile |
| 38564 |
break; |
| 38565 |
case 62: // 7.4.15 defines 2 extension types which |
| 38566 |
// are comments and can be ignored. |
| 38567 |
break; |
| 38568 |
default: |
| 38569 |
error('JBIG2 error: segment type ' + header.typeName + '(' + |
| 38570 |
header.type + ') is not implemented'); |
| 38571 |
} |
| 38572 |
var callbackName = 'on' + header.typeName; |
| 38573 |
if (callbackName in visitor) { |
| 38574 |
visitor[callbackName].apply(visitor, args); |
| 38575 |
} |
| 38576 |
} |
| 38577 |
|
| 38578 |
function processSegments(segments, visitor) { |
| 38579 |
for (var i = 0, ii = segments.length; i < ii; i++) { |
| 38580 |
processSegment(segments[i], visitor); |
| 38581 |
} |
| 38582 |
} |
| 38583 |
|
| 38584 |
function parseJbig2(data, start, end) { |
| 38585 |
var position = start; |
| 38586 |
if (data[position] !== 0x97 || data[position + 1] !== 0x4A || |
| 38587 |
data[position + 2] !== 0x42 || data[position + 3] !== 0x32 || |
| 38588 |
data[position + 4] !== 0x0D || data[position + 5] !== 0x0A || |
| 38589 |
data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) { |
| 38590 |
error('JBIG2 error: invalid header'); |
| 38591 |
} |
| 38592 |
var header = {}; |
| 38593 |
position += 8; |
| 38594 |
var flags = data[position++]; |
| 38595 |
header.randomAccess = !(flags & 1); |
| 38596 |
if (!(flags & 2)) { |
| 38597 |
header.numberOfPages = readUint32(data, position); |
| 38598 |
position += 4; |
| 38599 |
} |
| 38600 |
var segments = readSegments(header, data, position, end); |
| 38601 |
error('Not implemented'); |
| 38602 |
// processSegments(segments, new SimpleSegmentVisitor()); |
| 38603 |
} |
| 38604 |
|
| 38605 |
function parseJbig2Chunks(chunks) { |
| 38606 |
var visitor = new SimpleSegmentVisitor(); |
| 38607 |
for (var i = 0, ii = chunks.length; i < ii; i++) { |
| 38608 |
var chunk = chunks[i]; |
| 38609 |
var segments = readSegments({}, chunk.data, chunk.start, chunk.end); |
| 38610 |
processSegments(segments, visitor); |
| 38611 |
} |
| 38612 |
return visitor.buffer; |
| 38613 |
} |
| 38614 |
|
| 38615 |
function SimpleSegmentVisitor() {} |
| 38616 |
|
| 38617 |
SimpleSegmentVisitor.prototype = { |
| 38618 |
onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) { |
| 38619 |
this.currentPageInfo = info; |
| 38620 |
var rowSize = (info.width + 7) >> 3; |
| 38621 |
var buffer = new Uint8Array(rowSize * info.height); |
| 38622 |
// The contents of ArrayBuffers are initialized to 0. |
| 38623 |
// Fill the buffer with 0xFF only if info.defaultPixelValue is set |
| 38624 |
if (info.defaultPixelValue) { |
| 38625 |
for (var i = 0, ii = buffer.length; i < ii; i++) { |
| 38626 |
buffer[i] = 0xFF; |
| 38627 |
} |
| 38628 |
} |
| 38629 |
this.buffer = buffer; |
| 38630 |
}, |
| 38631 |
drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) { |
| 38632 |
var pageInfo = this.currentPageInfo; |
| 38633 |
var width = regionInfo.width, height = regionInfo.height; |
| 38634 |
var rowSize = (pageInfo.width + 7) >> 3; |
| 38635 |
var combinationOperator = pageInfo.combinationOperatorOverride ? |
| 38636 |
regionInfo.combinationOperator : pageInfo.combinationOperator; |
| 38637 |
var buffer = this.buffer; |
| 38638 |
var mask0 = 128 >> (regionInfo.x & 7); |
| 38639 |
var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3); |
| 38640 |
var i, j, mask, offset; |
| 38641 |
switch (combinationOperator) { |
| 38642 |
case 0: // OR |
| 38643 |
for (i = 0; i < height; i++) { |
| 38644 |
mask = mask0; |
| 38645 |
offset = offset0; |
| 38646 |
for (j = 0; j < width; j++) { |
| 38647 |
if (bitmap[i][j]) { |
| 38648 |
buffer[offset] |= mask; |
| 38649 |
} |
| 38650 |
mask >>= 1; |
| 38651 |
if (!mask) { |
| 38652 |
mask = 128; |
| 38653 |
offset++; |
| 38654 |
} |
| 38655 |
} |
| 38656 |
offset0 += rowSize; |
| 38657 |
} |
| 38658 |
break; |
| 38659 |
case 2: // XOR |
| 38660 |
for (i = 0; i < height; i++) { |
| 38661 |
mask = mask0; |
| 38662 |
offset = offset0; |
| 38663 |
for (j = 0; j < width; j++) { |
| 38664 |
if (bitmap[i][j]) { |
| 38665 |
buffer[offset] ^= mask; |
| 38666 |
} |
| 38667 |
mask >>= 1; |
| 38668 |
if (!mask) { |
| 38669 |
mask = 128; |
| 38670 |
offset++; |
| 38671 |
} |
| 38672 |
} |
| 38673 |
offset0 += rowSize; |
| 38674 |
} |
| 38675 |
break; |
| 38676 |
default: |
| 38677 |
error('JBIG2 error: operator ' + combinationOperator + |
| 38678 |
' is not supported'); |
| 38679 |
} |
| 38680 |
}, |
| 38681 |
onImmediateGenericRegion: |
| 38682 |
function SimpleSegmentVisitor_onImmediateGenericRegion(region, data, |
| 38683 |
start, end) { |
| 38684 |
var regionInfo = region.info; |
| 38685 |
var decodingContext = new DecodingContext(data, start, end); |
| 38686 |
var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, |
| 38687 |
region.template, region.prediction, null, |
| 38688 |
region.at, decodingContext); |
| 38689 |
this.drawBitmap(regionInfo, bitmap); |
| 38690 |
}, |
| 38691 |
onImmediateLosslessGenericRegion: |
| 38692 |
function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() { |
| 38693 |
this.onImmediateGenericRegion.apply(this, arguments); |
| 38694 |
}, |
| 38695 |
onSymbolDictionary: |
| 38696 |
function SimpleSegmentVisitor_onSymbolDictionary(dictionary, |
| 38697 |
currentSegment, |
| 38698 |
referredSegments, |
| 38699 |
data, start, end) { |
| 38700 |
var huffmanTables; |
| 38701 |
if (dictionary.huffman) { |
| 38702 |
error('JBIG2 error: huffman is not supported'); |
| 38703 |
} |
| 38704 |
|
| 38705 |
// Combines exported symbols from all referred segments |
| 38706 |
var symbols = this.symbols; |
| 38707 |
if (!symbols) { |
| 38708 |
this.symbols = symbols = {}; |
| 38709 |
} |
| 38710 |
|
| 38711 |
var inputSymbols = []; |
| 38712 |
for (var i = 0, ii = referredSegments.length; i < ii; i++) { |
| 38713 |
inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); |
| 38714 |
} |
| 38715 |
|
| 38716 |
var decodingContext = new DecodingContext(data, start, end); |
| 38717 |
symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, |
| 38718 |
dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, |
| 38719 |
dictionary.numberOfExportedSymbols, huffmanTables, |
| 38720 |
dictionary.template, dictionary.at, |
| 38721 |
dictionary.refinementTemplate, dictionary.refinementAt, |
| 38722 |
decodingContext); |
| 38723 |
}, |
| 38724 |
onImmediateTextRegion: |
| 38725 |
function SimpleSegmentVisitor_onImmediateTextRegion(region, |
| 38726 |
referredSegments, |
| 38727 |
data, start, end) { |
| 38728 |
var regionInfo = region.info; |
| 38729 |
var huffmanTables; |
| 38730 |
|
| 38731 |
// Combines exported symbols from all referred segments |
| 38732 |
var symbols = this.symbols; |
| 38733 |
var inputSymbols = []; |
| 38734 |
for (var i = 0, ii = referredSegments.length; i < ii; i++) { |
| 38735 |
inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); |
| 38736 |
} |
| 38737 |
var symbolCodeLength = log2(inputSymbols.length); |
| 38738 |
|
| 38739 |
var decodingContext = new DecodingContext(data, start, end); |
| 38740 |
var bitmap = decodeTextRegion(region.huffman, region.refinement, |
| 38741 |
regionInfo.width, regionInfo.height, region.defaultPixelValue, |
| 38742 |
region.numberOfSymbolInstances, region.stripSize, inputSymbols, |
| 38743 |
symbolCodeLength, region.transposed, region.dsOffset, |
| 38744 |
region.referenceCorner, region.combinationOperator, huffmanTables, |
| 38745 |
region.refinementTemplate, region.refinementAt, decodingContext); |
| 38746 |
this.drawBitmap(regionInfo, bitmap); |
| 38747 |
}, |
| 38748 |
onImmediateLosslessTextRegion: |
| 38749 |
function SimpleSegmentVisitor_onImmediateLosslessTextRegion() { |
| 38750 |
this.onImmediateTextRegion.apply(this, arguments); |
| 38751 |
} |
| 38752 |
}; |
| 38753 |
|
| 38754 |
function Jbig2Image() {} |
| 38755 |
|
| 38756 |
Jbig2Image.prototype = { |
| 38757 |
parseChunks: function Jbig2Image_parseChunks(chunks) { |
| 38758 |
return parseJbig2Chunks(chunks); |
| 38759 |
} |
| 38760 |
}; |
| 38761 |
|
| 38762 |
return Jbig2Image; |
| 38763 |
})(); |
| 38764 |
|
| 38765 |
|
| 38766 |
var bidi = PDFJS.bidi = (function bidiClosure() { |
| 38767 |
// Character types for symbols from 0000 to 00FF. |
| 38768 |
var baseTypes = [ |
| 38769 |
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS', |
| 38770 |
'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', |
| 38771 |
'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON', |
| 38772 |
'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN', |
| 38773 |
'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON', |
| 38774 |
'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', |
| 38775 |
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', |
| 38776 |
'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', |
| 38777 |
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', |
| 38778 |
'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN', |
| 38779 |
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', |
| 38780 |
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', |
| 38781 |
'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON', |
| 38782 |
'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON', |
| 38783 |
'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', |
| 38784 |
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', |
| 38785 |
'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', |
| 38786 |
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', |
| 38787 |
'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L' |
| 38788 |
]; |
| 38789 |
|
| 38790 |
// Character types for symbols from 0600 to 06FF |
| 38791 |
var arabicTypes = [ |
| 38792 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38793 |
'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', |
| 38794 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38795 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38796 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38797 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38798 |
'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', |
| 38799 |
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', |
| 38800 |
'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', |
| 38801 |
'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL', |
| 38802 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38803 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38804 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38805 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38806 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38807 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38808 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38809 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38810 |
'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', |
| 38811 |
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM', |
| 38812 |
'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', |
| 38813 |
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL' |
| 38814 |
]; |
| 38815 |
|
| 38816 |
function isOdd(i) { |
| 38817 |
return (i & 1) !== 0; |
| 38818 |
} |
| 38819 |
|
| 38820 |
function isEven(i) { |
| 38821 |
return (i & 1) === 0; |
| 38822 |
} |
| 38823 |
|
| 38824 |
function findUnequal(arr, start, value) { |
| 38825 |
for (var j = start, jj = arr.length; j < jj; ++j) { |
| 38826 |
if (arr[j] !== value) { |
| 38827 |
return j; |
| 38828 |
} |
| 38829 |
} |
| 38830 |
return j; |
| 38831 |
} |
| 38832 |
|
| 38833 |
function setValues(arr, start, end, value) { |
| 38834 |
for (var j = start; j < end; ++j) { |
| 38835 |
arr[j] = value; |
| 38836 |
} |
| 38837 |
} |
| 38838 |
|
| 38839 |
function reverseValues(arr, start, end) { |
| 38840 |
for (var i = start, j = end - 1; i < j; ++i, --j) { |
| 38841 |
var temp = arr[i]; |
| 38842 |
arr[i] = arr[j]; |
| 38843 |
arr[j] = temp; |
| 38844 |
} |
| 38845 |
} |
| 38846 |
|
| 38847 |
function createBidiText(str, isLTR, vertical) { |
| 38848 |
return { |
| 38849 |
str: str, |
| 38850 |
dir: (vertical ? 'ttb' : (isLTR ? 'ltr' : 'rtl')) |
| 38851 |
}; |
| 38852 |
} |
| 38853 |
|
| 38854 |
// These are used in bidi(), which is called frequently. We re-use them on |
| 38855 |
// each call to avoid unnecessary allocations. |
| 38856 |
var chars = []; |
| 38857 |
var types = []; |
| 38858 |
|
| 38859 |
function bidi(str, startLevel, vertical) { |
| 38860 |
var isLTR = true; |
| 38861 |
var strLength = str.length; |
| 38862 |
if (strLength === 0 || vertical) { |
| 38863 |
return createBidiText(str, isLTR, vertical); |
| 38864 |
} |
| 38865 |
|
| 38866 |
// Get types and fill arrays |
| 38867 |
chars.length = strLength; |
| 38868 |
types.length = strLength; |
| 38869 |
var numBidi = 0; |
| 38870 |
|
| 38871 |
var i, ii; |
| 38872 |
for (i = 0; i < strLength; ++i) { |
| 38873 |
chars[i] = str.charAt(i); |
| 38874 |
|
| 38875 |
var charCode = str.charCodeAt(i); |
| 38876 |
var charType = 'L'; |
| 38877 |
if (charCode <= 0x00ff) { |
| 38878 |
charType = baseTypes[charCode]; |
| 38879 |
} else if (0x0590 <= charCode && charCode <= 0x05f4) { |
| 38880 |
charType = 'R'; |
| 38881 |
} else if (0x0600 <= charCode && charCode <= 0x06ff) { |
| 38882 |
charType = arabicTypes[charCode & 0xff]; |
| 38883 |
} else if (0x0700 <= charCode && charCode <= 0x08AC) { |
| 38884 |
charType = 'AL'; |
| 38885 |
} |
| 38886 |
if (charType === 'R' || charType === 'AL' || charType === 'AN') { |
| 38887 |
numBidi++; |
| 38888 |
} |
| 38889 |
types[i] = charType; |
| 38890 |
} |
| 38891 |
|
| 38892 |
// Detect the bidi method |
| 38893 |
// - If there are no rtl characters then no bidi needed |
| 38894 |
// - If less than 30% chars are rtl then string is primarily ltr |
| 38895 |
// - If more than 30% chars are rtl then string is primarily rtl |
| 38896 |
if (numBidi === 0) { |
| 38897 |
isLTR = true; |
| 38898 |
return createBidiText(str, isLTR); |
| 38899 |
} |
| 38900 |
|
| 38901 |
if (startLevel === -1) { |
| 38902 |
if ((strLength / numBidi) < 0.3) { |
| 38903 |
isLTR = true; |
| 38904 |
startLevel = 0; |
| 38905 |
} else { |
| 38906 |
isLTR = false; |
| 38907 |
startLevel = 1; |
| 38908 |
} |
| 38909 |
} |
| 38910 |
|
| 38911 |
var levels = []; |
| 38912 |
for (i = 0; i < strLength; ++i) { |
| 38913 |
levels[i] = startLevel; |
| 38914 |
} |
| 38915 |
|
| 38916 |
/* |
| 38917 |
X1-X10: skip most of this, since we are NOT doing the embeddings. |
| 38918 |
*/ |
| 38919 |
var e = (isOdd(startLevel) ? 'R' : 'L'); |
| 38920 |
var sor = e; |
| 38921 |
var eor = sor; |
| 38922 |
|
| 38923 |
/* |
| 38924 |
W1. Examine each non-spacing mark (NSM) in the level run, and change the |
| 38925 |
type of the NSM to the type of the previous character. If the NSM is at the |
| 38926 |
start of the level run, it will get the type of sor. |
| 38927 |
*/ |
| 38928 |
var lastType = sor; |
| 38929 |
for (i = 0; i < strLength; ++i) { |
| 38930 |
if (types[i] === 'NSM') { |
| 38931 |
types[i] = lastType; |
| 38932 |
} else { |
| 38933 |
lastType = types[i]; |
| 38934 |
} |
| 38935 |
} |
| 38936 |
|
| 38937 |
/* |
| 38938 |
W2. Search backwards from each instance of a European number until the |
| 38939 |
first strong type (R, L, AL, or sor) is found. If an AL is found, change |
| 38940 |
the type of the European number to Arabic number. |
| 38941 |
*/ |
| 38942 |
lastType = sor; |
| 38943 |
var t; |
| 38944 |
for (i = 0; i < strLength; ++i) { |
| 38945 |
t = types[i]; |
| 38946 |
if (t === 'EN') { |
| 38947 |
types[i] = (lastType === 'AL') ? 'AN' : 'EN'; |
| 38948 |
} else if (t === 'R' || t === 'L' || t === 'AL') { |
| 38949 |
lastType = t; |
| 38950 |
} |
| 38951 |
} |
| 38952 |
|
| 38953 |
/* |
| 38954 |
W3. Change all ALs to R. |
| 38955 |
*/ |
| 38956 |
for (i = 0; i < strLength; ++i) { |
| 38957 |
t = types[i]; |
| 38958 |
if (t === 'AL') { |
| 38959 |
types[i] = 'R'; |
| 38960 |
} |
| 38961 |
} |
| 38962 |
|
| 38963 |
/* |
| 38964 |
W4. A single European separator between two European numbers changes to a |
| 38965 |
European number. A single common separator between two numbers of the same |
| 38966 |
type changes to that type: |
| 38967 |
*/ |
| 38968 |
for (i = 1; i < strLength - 1; ++i) { |
| 38969 |
if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') { |
| 38970 |
types[i] = 'EN'; |
| 38971 |
} |
| 38972 |
if (types[i] === 'CS' && |
| 38973 |
(types[i - 1] === 'EN' || types[i - 1] === 'AN') && |
| 38974 |
types[i + 1] === types[i - 1]) { |
| 38975 |
types[i] = types[i - 1]; |
| 38976 |
} |
| 38977 |
} |
| 38978 |
|
| 38979 |
/* |
| 38980 |
W5. A sequence of European terminators adjacent to European numbers changes |
| 38981 |
to all European numbers: |
| 38982 |
*/ |
| 38983 |
for (i = 0; i < strLength; ++i) { |
| 38984 |
if (types[i] === 'EN') { |
| 38985 |
// do before |
| 38986 |
var j; |
| 38987 |
for (j = i - 1; j >= 0; --j) { |
| 38988 |
if (types[j] !== 'ET') { |
| 38989 |
break; |
| 38990 |
} |
| 38991 |
types[j] = 'EN'; |
| 38992 |
} |
| 38993 |
// do after |
| 38994 |
for (j = i + 1; j < strLength; --j) { |
| 38995 |
if (types[j] !== 'ET') { |
| 38996 |
break; |
| 38997 |
} |
| 38998 |
types[j] = 'EN'; |
| 38999 |
} |
| 39000 |
} |
| 39001 |
} |
| 39002 |
|
| 39003 |
/* |
| 39004 |
W6. Otherwise, separators and terminators change to Other Neutral: |
| 39005 |
*/ |
| 39006 |
for (i = 0; i < strLength; ++i) { |
| 39007 |
t = types[i]; |
| 39008 |
if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') { |
| 39009 |
types[i] = 'ON'; |
| 39010 |
} |
| 39011 |
} |
| 39012 |
|
| 39013 |
/* |
| 39014 |
W7. Search backwards from each instance of a European number until the |
| 39015 |
first strong type (R, L, or sor) is found. If an L is found, then change |
| 39016 |
the type of the European number to L. |
| 39017 |
*/ |
| 39018 |
lastType = sor; |
| 39019 |
for (i = 0; i < strLength; ++i) { |
| 39020 |
t = types[i]; |
| 39021 |
if (t === 'EN') { |
| 39022 |
types[i] = ((lastType === 'L') ? 'L' : 'EN'); |
| 39023 |
} else if (t === 'R' || t === 'L') { |
| 39024 |
lastType = t; |
| 39025 |
} |
| 39026 |
} |
| 39027 |
|
| 39028 |
/* |
| 39029 |
N1. A sequence of neutrals takes the direction of the surrounding strong |
| 39030 |
text if the text on both sides has the same direction. European and Arabic |
| 39031 |
numbers are treated as though they were R. Start-of-level-run (sor) and |
| 39032 |
end-of-level-run (eor) are used at level run boundaries. |
| 39033 |
*/ |
| 39034 |
for (i = 0; i < strLength; ++i) { |
| 39035 |
if (types[i] === 'ON') { |
| 39036 |
var end = findUnequal(types, i + 1, 'ON'); |
| 39037 |
var before = sor; |
| 39038 |
if (i > 0) { |
| 39039 |
before = types[i - 1]; |
| 39040 |
} |
| 39041 |
|
| 39042 |
var after = eor; |
| 39043 |
if (end + 1 < strLength) { |
| 39044 |
after = types[end + 1]; |
| 39045 |
} |
| 39046 |
if (before !== 'L') { |
| 39047 |
before = 'R'; |
| 39048 |
} |
| 39049 |
if (after !== 'L') { |
| 39050 |
after = 'R'; |
| 39051 |
} |
| 39052 |
if (before === after) { |
| 39053 |
setValues(types, i, end, before); |
| 39054 |
} |
| 39055 |
i = end - 1; // reset to end (-1 so next iteration is ok) |
| 39056 |
} |
| 39057 |
} |
| 39058 |
|
| 39059 |
/* |
| 39060 |
N2. Any remaining neutrals take the embedding direction. |
| 39061 |
*/ |
| 39062 |
for (i = 0; i < strLength; ++i) { |
| 39063 |
if (types[i] === 'ON') { |
| 39064 |
types[i] = e; |
| 39065 |
} |
| 39066 |
} |
| 39067 |
|
| 39068 |
/* |
| 39069 |
I1. For all characters with an even (left-to-right) embedding direction, |
| 39070 |
those of type R go up one level and those of type AN or EN go up two |
| 39071 |
levels. |
| 39072 |
I2. For all characters with an odd (right-to-left) embedding direction, |
| 39073 |
those of type L, EN or AN go up one level. |
| 39074 |
*/ |
| 39075 |
for (i = 0; i < strLength; ++i) { |
| 39076 |
t = types[i]; |
| 39077 |
if (isEven(levels[i])) { |
| 39078 |
if (t === 'R') { |
| 39079 |
levels[i] += 1; |
| 39080 |
} else if (t === 'AN' || t === 'EN') { |
| 39081 |
levels[i] += 2; |
| 39082 |
} |
| 39083 |
} else { // isOdd |
| 39084 |
if (t === 'L' || t === 'AN' || t === 'EN') { |
| 39085 |
levels[i] += 1; |
| 39086 |
} |
| 39087 |
} |
| 39088 |
} |
| 39089 |
|
| 39090 |
/* |
| 39091 |
L1. On each line, reset the embedding level of the following characters to |
| 39092 |
the paragraph embedding level: |
| 39093 |
|
| 39094 |
segment separators, |
| 39095 |
paragraph separators, |
| 39096 |
any sequence of whitespace characters preceding a segment separator or |
| 39097 |
paragraph separator, and any sequence of white space characters at the end |
| 39098 |
of the line. |
| 39099 |
*/ |
| 39100 |
|
| 39101 |
// don't bother as text is only single line |
| 39102 |
|
| 39103 |
/* |
| 39104 |
L2. From the highest level found in the text to the lowest odd level on |
| 39105 |
each line, reverse any contiguous sequence of characters that are at that |
| 39106 |
level or higher. |
| 39107 |
*/ |
| 39108 |
|
| 39109 |
// find highest level & lowest odd level |
| 39110 |
var highestLevel = -1; |
| 39111 |
var lowestOddLevel = 99; |
| 39112 |
var level; |
| 39113 |
for (i = 0, ii = levels.length; i < ii; ++i) { |
| 39114 |
level = levels[i]; |
| 39115 |
if (highestLevel < level) { |
| 39116 |
highestLevel = level; |
| 39117 |
} |
| 39118 |
if (lowestOddLevel > level && isOdd(level)) { |
| 39119 |
lowestOddLevel = level; |
| 39120 |
} |
| 39121 |
} |
| 39122 |
|
| 39123 |
// now reverse between those limits |
| 39124 |
for (level = highestLevel; level >= lowestOddLevel; --level) { |
| 39125 |
// find segments to reverse |
| 39126 |
var start = -1; |
| 39127 |
for (i = 0, ii = levels.length; i < ii; ++i) { |
| 39128 |
if (levels[i] < level) { |
| 39129 |
if (start >= 0) { |
| 39130 |
reverseValues(chars, start, i); |
| 39131 |
start = -1; |
| 39132 |
} |
| 39133 |
} else if (start < 0) { |
| 39134 |
start = i; |
| 39135 |
} |
| 39136 |
} |
| 39137 |
if (start >= 0) { |
| 39138 |
reverseValues(chars, start, levels.length); |
| 39139 |
} |
| 39140 |
} |
| 39141 |
|
| 39142 |
/* |
| 39143 |
L3. Combining marks applied to a right-to-left base character will at this |
| 39144 |
point precede their base character. If the rendering engine expects them to |
| 39145 |
follow the base characters in the final display process, then the ordering |
| 39146 |
of the marks and the base character must be reversed. |
| 39147 |
*/ |
| 39148 |
|
| 39149 |
// don't bother for now |
| 39150 |
|
| 39151 |
/* |
| 39152 |
L4. A character that possesses the mirrored property as specified by |
| 39153 |
Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved |
| 39154 |
directionality of that character is R. |
| 39155 |
*/ |
| 39156 |
|
| 39157 |
// don't mirror as characters are already mirrored in the pdf |
| 39158 |
|
| 39159 |
// Finally, return string |
| 39160 |
var result = ''; |
| 39161 |
for (i = 0, ii = chars.length; i < ii; ++i) { |
| 39162 |
var ch = chars[i]; |
| 39163 |
if (ch !== '<' && ch !== '>') { |
| 39164 |
result += ch; |
| 39165 |
} |
| 39166 |
} |
| 39167 |
return createBidiText(result, isLTR); |
| 39168 |
} |
| 39169 |
|
| 39170 |
return bidi; |
| 39171 |
})(); |
| 39172 |
|
| 39173 |
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| 39174 |
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ |
| 39175 |
|
| 39176 |
/* Copyright 2014 Opera Software ASA |
| 39177 |
* |
| 39178 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
| 39179 |
* you may not use this file except in compliance with the License. |
| 39180 |
* You may obtain a copy of the License at |
| 39181 |
* |
| 39182 |
* http://www.apache.org/licenses/LICENSE-2.0 |
| 39183 |
* |
| 39184 |
* Unless required by applicable law or agreed to in writing, software |
| 39185 |
* distributed under the License is distributed on an "AS IS" BASIS, |
| 39186 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 39187 |
* See the License for the specific language governing permissions and |
| 39188 |
* limitations under the License. |
| 39189 |
* |
| 39190 |
* |
| 39191 |
* Based on https://code.google.com/p/smhasher/wiki/MurmurHash3. |
| 39192 |
* Hashes roughly 100 KB per millisecond on i7 3.4 GHz. |
| 39193 |
*/ |
| 39194 |
/* globals Uint32ArrayView */ |
| 39195 |
|
| 39196 |
'use strict'; |
| 39197 |
|
| 39198 |
var MurmurHash3_64 = (function MurmurHash3_64Closure (seed) { |
| 39199 |
// Workaround for missing math precison in JS. |
| 39200 |
var MASK_HIGH = 0xffff0000; |
| 39201 |
var MASK_LOW = 0xffff; |
| 39202 |
|
| 39203 |
function MurmurHash3_64 (seed) { |
| 39204 |
var SEED = 0xc3d2e1f0; |
| 39205 |
this.h1 = seed ? seed & 0xffffffff : SEED; |
| 39206 |
this.h2 = seed ? seed & 0xffffffff : SEED; |
| 39207 |
} |
| 39208 |
|
| 39209 |
var alwaysUseUint32ArrayView = false; |
| 39210 |
//#if !(FIREFOX || MOZCENTRAL || B2G || CHROME) |
| 39211 |
// old webkits have issues with non-aligned arrays |
| 39212 |
try { |
| 39213 |
new Uint32Array(new Uint8Array(5).buffer, 0, 1); |
| 39214 |
} catch (e) { |
| 39215 |
alwaysUseUint32ArrayView = true; |
| 39216 |
} |
| 39217 |
//#endif |
| 39218 |
|
| 39219 |
MurmurHash3_64.prototype = { |
| 39220 |
update: function MurmurHash3_64_update(input) { |
| 39221 |
var useUint32ArrayView = alwaysUseUint32ArrayView; |
| 39222 |
var i; |
| 39223 |
if (typeof input === 'string') { |
| 39224 |
var data = new Uint8Array(input.length * 2); |
| 39225 |
var length = 0; |
| 39226 |
for (i = 0; i < input.length; i++) { |
| 39227 |
var code = input.charCodeAt(i); |
| 39228 |
if (code <= 0xff) { |
| 39229 |
data[length++] = code; |
| 39230 |
} |
| 39231 |
else { |
| 39232 |
data[length++] = code >>> 8; |
| 39233 |
data[length++] = code & 0xff; |
| 39234 |
} |
| 39235 |
} |
| 39236 |
} else if (input instanceof Uint8Array) { |
| 39237 |
data = input; |
| 39238 |
length = data.length; |
| 39239 |
} else if (typeof input === 'object' && ('length' in input)) { |
| 39240 |
// processing regular arrays as well, e.g. for IE9 |
| 39241 |
data = input; |
| 39242 |
length = data.length; |
| 39243 |
useUint32ArrayView = true; |
| 39244 |
} else { |
| 39245 |
throw new Error('Wrong data format in MurmurHash3_64_update. ' + |
| 39246 |
'Input must be a string or array.'); |
| 39247 |
} |
| 39248 |
|
| 39249 |
var blockCounts = length >> 2; |
| 39250 |
var tailLength = length - blockCounts * 4; |
| 39251 |
// we don't care about endianness here |
| 39252 |
var dataUint32 = useUint32ArrayView ? |
| 39253 |
new Uint32ArrayView(data, blockCounts) : |
| 39254 |
new Uint32Array(data.buffer, 0, blockCounts); |
| 39255 |
var k1 = 0; |
| 39256 |
var k2 = 0; |
| 39257 |
var h1 = this.h1; |
| 39258 |
var h2 = this.h2; |
| 39259 |
var C1 = 0xcc9e2d51; |
| 39260 |
var C2 = 0x1b873593; |
| 39261 |
var C1_LOW = C1 & MASK_LOW; |
| 39262 |
var C2_LOW = C2 & MASK_LOW; |
| 39263 |
|
| 39264 |
for (i = 0; i < blockCounts; i++) { |
| 39265 |
if (i & 1) { |
| 39266 |
k1 = dataUint32[i]; |
| 39267 |
k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW); |
| 39268 |
k1 = k1 << 15 | k1 >>> 17; |
| 39269 |
k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW); |
| 39270 |
h1 ^= k1; |
| 39271 |
h1 = h1 << 13 | h1 >>> 19; |
| 39272 |
h1 = h1 * 5 + 0xe6546b64; |
| 39273 |
} else { |
| 39274 |
k2 = dataUint32[i]; |
| 39275 |
k2 = (k2 * C1 & MASK_HIGH) | (k2 * C1_LOW & MASK_LOW); |
| 39276 |
k2 = k2 << 15 | k2 >>> 17; |
| 39277 |
k2 = (k2 * C2 & MASK_HIGH) | (k2 * C2_LOW & MASK_LOW); |
| 39278 |
h2 ^= k2; |
| 39279 |
h2 = h2 << 13 | h2 >>> 19; |
| 39280 |
h2 = h2 * 5 + 0xe6546b64; |
| 39281 |
} |
| 39282 |
} |
| 39283 |
|
| 39284 |
k1 = 0; |
| 39285 |
|
| 39286 |
switch (tailLength) { |
| 39287 |
case 3: |
| 39288 |
k1 ^= data[blockCounts * 4 + 2] << 16; |
| 39289 |
/* falls through */ |
| 39290 |
case 2: |
| 39291 |
k1 ^= data[blockCounts * 4 + 1] << 8; |
| 39292 |
/* falls through */ |
| 39293 |
case 1: |
| 39294 |
k1 ^= data[blockCounts * 4]; |
| 39295 |
/* falls through */ |
| 39296 |
k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW); |
| 39297 |
k1 = k1 << 15 | k1 >>> 17; |
| 39298 |
k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW); |
| 39299 |
if (blockCounts & 1) { |
| 39300 |
h1 ^= k1; |
| 39301 |
} else { |
| 39302 |
h2 ^= k1; |
| 39303 |
} |
| 39304 |
} |
| 39305 |
|
| 39306 |
this.h1 = h1; |
| 39307 |
this.h2 = h2; |
| 39308 |
return this; |
| 39309 |
}, |
| 39310 |
|
| 39311 |
hexdigest: function MurmurHash3_64_hexdigest () { |
| 39312 |
var h1 = this.h1; |
| 39313 |
var h2 = this.h2; |
| 39314 |
|
| 39315 |
h1 ^= h2 >>> 1; |
| 39316 |
h1 = (h1 * 0xed558ccd & MASK_HIGH) | (h1 * 0x8ccd & MASK_LOW); |
| 39317 |
h2 = (h2 * 0xff51afd7 & MASK_HIGH) | |
| 39318 |
(((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16); |
| 39319 |
h1 ^= h2 >>> 1; |
| 39320 |
h1 = (h1 * 0x1a85ec53 & MASK_HIGH) | (h1 * 0xec53 & MASK_LOW); |
| 39321 |
h2 = (h2 * 0xc4ceb9fe & MASK_HIGH) | |
| 39322 |
(((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16); |
| 39323 |
h1 ^= h2 >>> 1; |
| 39324 |
|
| 39325 |
for (var i = 0, arr = [h1, h2], str = ''; i < arr.length; i++) { |
| 39326 |
var hex = (arr[i] >>> 0).toString(16); |
| 39327 |
while (hex.length < 8) { |
| 39328 |
hex = '0' + hex; |
| 39329 |
} |
| 39330 |
str += hex; |
| 39331 |
} |
| 39332 |
|
| 39333 |
return str; |
| 39334 |
} |
| 39335 |
}; |
| 39336 |
|
| 39337 |
return MurmurHash3_64; |
| 39338 |
})(); |
| 39339 |
|
| 39340 |
|
| 39341 |
}).call((typeof window === 'undefined') ? this : window); |
| 39342 |
|
| 39343 |
if (!PDFJS.workerSrc && typeof document !== 'undefined') { |
| 39344 |
// workerSrc is not set -- using last script url to define default location |
| 39345 |
PDFJS.workerSrc = (function () { |
| 39346 |
'use strict'; |
| 39347 |
var scriptTagContainer = document.body || |
| 39348 |
document.getElementsByTagName('head')[0]; |
| 39349 |
var pdfjsSrc = scriptTagContainer.lastChild.src; |
| 39350 |
return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js'); |
| 39351 |
})(); |
| 39352 |
} |
| 39353 |
|
| 39354 |
|