browser/extensions/pdfjs/content/build/pdf.worker.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
michael@0 3 /* Copyright 2012 Mozilla Foundation
michael@0 4 *
michael@0 5 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 6 * you may not use this file except in compliance with the License.
michael@0 7 * You may obtain a copy of the License at
michael@0 8 *
michael@0 9 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 10 *
michael@0 11 * Unless required by applicable law or agreed to in writing, software
michael@0 12 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 14 * See the License for the specific language governing permissions and
michael@0 15 * limitations under the License.
michael@0 16 */
michael@0 17 /*jshint globalstrict: false */
michael@0 18
michael@0 19 // Initializing PDFJS global object (if still undefined)
michael@0 20 if (typeof PDFJS === 'undefined') {
michael@0 21 (typeof window !== 'undefined' ? window : this).PDFJS = {};
michael@0 22 }
michael@0 23
michael@0 24 PDFJS.version = '1.0.68';
michael@0 25 PDFJS.build = 'ead4cbf';
michael@0 26
michael@0 27 (function pdfjsWrapper() {
michael@0 28 // Use strict in our context only - users might not want it
michael@0 29 'use strict';
michael@0 30
michael@0 31 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 32 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
michael@0 33 /* Copyright 2012 Mozilla Foundation
michael@0 34 *
michael@0 35 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 36 * you may not use this file except in compliance with the License.
michael@0 37 * You may obtain a copy of the License at
michael@0 38 *
michael@0 39 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 40 *
michael@0 41 * Unless required by applicable law or agreed to in writing, software
michael@0 42 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 43 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 44 * See the License for the specific language governing permissions and
michael@0 45 * limitations under the License.
michael@0 46 */
michael@0 47 /* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL,
michael@0 48 Promise */
michael@0 49
michael@0 50 'use strict';
michael@0 51
michael@0 52 var globalScope = (typeof window === 'undefined') ? this : window;
michael@0 53
michael@0 54 var isWorker = (typeof window == 'undefined');
michael@0 55
michael@0 56 var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
michael@0 57
michael@0 58 var TextRenderingMode = {
michael@0 59 FILL: 0,
michael@0 60 STROKE: 1,
michael@0 61 FILL_STROKE: 2,
michael@0 62 INVISIBLE: 3,
michael@0 63 FILL_ADD_TO_PATH: 4,
michael@0 64 STROKE_ADD_TO_PATH: 5,
michael@0 65 FILL_STROKE_ADD_TO_PATH: 6,
michael@0 66 ADD_TO_PATH: 7,
michael@0 67 FILL_STROKE_MASK: 3,
michael@0 68 ADD_TO_PATH_FLAG: 4
michael@0 69 };
michael@0 70
michael@0 71 var ImageKind = {
michael@0 72 GRAYSCALE_1BPP: 1,
michael@0 73 RGB_24BPP: 2,
michael@0 74 RGBA_32BPP: 3
michael@0 75 };
michael@0 76
michael@0 77 // The global PDFJS object exposes the API
michael@0 78 // In production, it will be declared outside a global wrapper
michael@0 79 // In development, it will be declared here
michael@0 80 if (!globalScope.PDFJS) {
michael@0 81 globalScope.PDFJS = {};
michael@0 82 }
michael@0 83
michael@0 84 globalScope.PDFJS.pdfBug = false;
michael@0 85
michael@0 86 PDFJS.VERBOSITY_LEVELS = {
michael@0 87 errors: 0,
michael@0 88 warnings: 1,
michael@0 89 infos: 5
michael@0 90 };
michael@0 91
michael@0 92 // All the possible operations for an operator list.
michael@0 93 var OPS = PDFJS.OPS = {
michael@0 94 // Intentionally start from 1 so it is easy to spot bad operators that will be
michael@0 95 // 0's.
michael@0 96 dependency: 1,
michael@0 97 setLineWidth: 2,
michael@0 98 setLineCap: 3,
michael@0 99 setLineJoin: 4,
michael@0 100 setMiterLimit: 5,
michael@0 101 setDash: 6,
michael@0 102 setRenderingIntent: 7,
michael@0 103 setFlatness: 8,
michael@0 104 setGState: 9,
michael@0 105 save: 10,
michael@0 106 restore: 11,
michael@0 107 transform: 12,
michael@0 108 moveTo: 13,
michael@0 109 lineTo: 14,
michael@0 110 curveTo: 15,
michael@0 111 curveTo2: 16,
michael@0 112 curveTo3: 17,
michael@0 113 closePath: 18,
michael@0 114 rectangle: 19,
michael@0 115 stroke: 20,
michael@0 116 closeStroke: 21,
michael@0 117 fill: 22,
michael@0 118 eoFill: 23,
michael@0 119 fillStroke: 24,
michael@0 120 eoFillStroke: 25,
michael@0 121 closeFillStroke: 26,
michael@0 122 closeEOFillStroke: 27,
michael@0 123 endPath: 28,
michael@0 124 clip: 29,
michael@0 125 eoClip: 30,
michael@0 126 beginText: 31,
michael@0 127 endText: 32,
michael@0 128 setCharSpacing: 33,
michael@0 129 setWordSpacing: 34,
michael@0 130 setHScale: 35,
michael@0 131 setLeading: 36,
michael@0 132 setFont: 37,
michael@0 133 setTextRenderingMode: 38,
michael@0 134 setTextRise: 39,
michael@0 135 moveText: 40,
michael@0 136 setLeadingMoveText: 41,
michael@0 137 setTextMatrix: 42,
michael@0 138 nextLine: 43,
michael@0 139 showText: 44,
michael@0 140 showSpacedText: 45,
michael@0 141 nextLineShowText: 46,
michael@0 142 nextLineSetSpacingShowText: 47,
michael@0 143 setCharWidth: 48,
michael@0 144 setCharWidthAndBounds: 49,
michael@0 145 setStrokeColorSpace: 50,
michael@0 146 setFillColorSpace: 51,
michael@0 147 setStrokeColor: 52,
michael@0 148 setStrokeColorN: 53,
michael@0 149 setFillColor: 54,
michael@0 150 setFillColorN: 55,
michael@0 151 setStrokeGray: 56,
michael@0 152 setFillGray: 57,
michael@0 153 setStrokeRGBColor: 58,
michael@0 154 setFillRGBColor: 59,
michael@0 155 setStrokeCMYKColor: 60,
michael@0 156 setFillCMYKColor: 61,
michael@0 157 shadingFill: 62,
michael@0 158 beginInlineImage: 63,
michael@0 159 beginImageData: 64,
michael@0 160 endInlineImage: 65,
michael@0 161 paintXObject: 66,
michael@0 162 markPoint: 67,
michael@0 163 markPointProps: 68,
michael@0 164 beginMarkedContent: 69,
michael@0 165 beginMarkedContentProps: 70,
michael@0 166 endMarkedContent: 71,
michael@0 167 beginCompat: 72,
michael@0 168 endCompat: 73,
michael@0 169 paintFormXObjectBegin: 74,
michael@0 170 paintFormXObjectEnd: 75,
michael@0 171 beginGroup: 76,
michael@0 172 endGroup: 77,
michael@0 173 beginAnnotations: 78,
michael@0 174 endAnnotations: 79,
michael@0 175 beginAnnotation: 80,
michael@0 176 endAnnotation: 81,
michael@0 177 paintJpegXObject: 82,
michael@0 178 paintImageMaskXObject: 83,
michael@0 179 paintImageMaskXObjectGroup: 84,
michael@0 180 paintImageXObject: 85,
michael@0 181 paintInlineImageXObject: 86,
michael@0 182 paintInlineImageXObjectGroup: 87,
michael@0 183 paintImageXObjectRepeat: 88,
michael@0 184 paintImageMaskXObjectRepeat: 89,
michael@0 185 paintSolidColorImageMask: 90
michael@0 186 };
michael@0 187
michael@0 188 // A notice for devs. These are good for things that are helpful to devs, such
michael@0 189 // as warning that Workers were disabled, which is important to devs but not
michael@0 190 // end users.
michael@0 191 function info(msg) {
michael@0 192 if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) {
michael@0 193 console.log('Info: ' + msg);
michael@0 194 }
michael@0 195 }
michael@0 196
michael@0 197 // Non-fatal warnings.
michael@0 198 function warn(msg) {
michael@0 199 if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) {
michael@0 200 console.log('Warning: ' + msg);
michael@0 201 }
michael@0 202 }
michael@0 203
michael@0 204 // Fatal errors that should trigger the fallback UI and halt execution by
michael@0 205 // throwing an exception.
michael@0 206 function error(msg) {
michael@0 207 // If multiple arguments were passed, pass them all to the log function.
michael@0 208 if (arguments.length > 1) {
michael@0 209 var logArguments = ['Error:'];
michael@0 210 logArguments.push.apply(logArguments, arguments);
michael@0 211 console.log.apply(console, logArguments);
michael@0 212 // Join the arguments into a single string for the lines below.
michael@0 213 msg = [].join.call(arguments, ' ');
michael@0 214 } else {
michael@0 215 console.log('Error: ' + msg);
michael@0 216 }
michael@0 217 console.log(backtrace());
michael@0 218 UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
michael@0 219 throw new Error(msg);
michael@0 220 }
michael@0 221
michael@0 222 function backtrace() {
michael@0 223 try {
michael@0 224 throw new Error();
michael@0 225 } catch (e) {
michael@0 226 return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
michael@0 227 }
michael@0 228 }
michael@0 229
michael@0 230 function assert(cond, msg) {
michael@0 231 if (!cond) {
michael@0 232 error(msg);
michael@0 233 }
michael@0 234 }
michael@0 235
michael@0 236 var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
michael@0 237 unknown: 'unknown',
michael@0 238 forms: 'forms',
michael@0 239 javaScript: 'javaScript',
michael@0 240 smask: 'smask',
michael@0 241 shadingPattern: 'shadingPattern',
michael@0 242 font: 'font'
michael@0 243 };
michael@0 244
michael@0 245 var UnsupportedManager = PDFJS.UnsupportedManager =
michael@0 246 (function UnsupportedManagerClosure() {
michael@0 247 var listeners = [];
michael@0 248 return {
michael@0 249 listen: function (cb) {
michael@0 250 listeners.push(cb);
michael@0 251 },
michael@0 252 notify: function (featureId) {
michael@0 253 warn('Unsupported feature "' + featureId + '"');
michael@0 254 for (var i = 0, ii = listeners.length; i < ii; i++) {
michael@0 255 listeners[i](featureId);
michael@0 256 }
michael@0 257 }
michael@0 258 };
michael@0 259 })();
michael@0 260
michael@0 261 // Combines two URLs. The baseUrl shall be absolute URL. If the url is an
michael@0 262 // absolute URL, it will be returned as is.
michael@0 263 function combineUrl(baseUrl, url) {
michael@0 264 if (!url) {
michael@0 265 return baseUrl;
michael@0 266 }
michael@0 267 if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) {
michael@0 268 return url;
michael@0 269 }
michael@0 270 var i;
michael@0 271 if (url.charAt(0) == '/') {
michael@0 272 // absolute path
michael@0 273 i = baseUrl.indexOf('://');
michael@0 274 if (url.charAt(1) === '/') {
michael@0 275 ++i;
michael@0 276 } else {
michael@0 277 i = baseUrl.indexOf('/', i + 3);
michael@0 278 }
michael@0 279 return baseUrl.substring(0, i) + url;
michael@0 280 } else {
michael@0 281 // relative path
michael@0 282 var pathLength = baseUrl.length;
michael@0 283 i = baseUrl.lastIndexOf('#');
michael@0 284 pathLength = i >= 0 ? i : pathLength;
michael@0 285 i = baseUrl.lastIndexOf('?', pathLength);
michael@0 286 pathLength = i >= 0 ? i : pathLength;
michael@0 287 var prefixLength = baseUrl.lastIndexOf('/', pathLength);
michael@0 288 return baseUrl.substring(0, prefixLength + 1) + url;
michael@0 289 }
michael@0 290 }
michael@0 291
michael@0 292 // Validates if URL is safe and allowed, e.g. to avoid XSS.
michael@0 293 function isValidUrl(url, allowRelative) {
michael@0 294 if (!url) {
michael@0 295 return false;
michael@0 296 }
michael@0 297 // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1)
michael@0 298 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
michael@0 299 var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url);
michael@0 300 if (!protocol) {
michael@0 301 return allowRelative;
michael@0 302 }
michael@0 303 protocol = protocol[0].toLowerCase();
michael@0 304 switch (protocol) {
michael@0 305 case 'http':
michael@0 306 case 'https':
michael@0 307 case 'ftp':
michael@0 308 case 'mailto':
michael@0 309 return true;
michael@0 310 default:
michael@0 311 return false;
michael@0 312 }
michael@0 313 }
michael@0 314 PDFJS.isValidUrl = isValidUrl;
michael@0 315
michael@0 316 function shadow(obj, prop, value) {
michael@0 317 Object.defineProperty(obj, prop, { value: value,
michael@0 318 enumerable: true,
michael@0 319 configurable: true,
michael@0 320 writable: false });
michael@0 321 return value;
michael@0 322 }
michael@0 323
michael@0 324 var PasswordResponses = PDFJS.PasswordResponses = {
michael@0 325 NEED_PASSWORD: 1,
michael@0 326 INCORRECT_PASSWORD: 2
michael@0 327 };
michael@0 328
michael@0 329 var PasswordException = (function PasswordExceptionClosure() {
michael@0 330 function PasswordException(msg, code) {
michael@0 331 this.name = 'PasswordException';
michael@0 332 this.message = msg;
michael@0 333 this.code = code;
michael@0 334 }
michael@0 335
michael@0 336 PasswordException.prototype = new Error();
michael@0 337 PasswordException.constructor = PasswordException;
michael@0 338
michael@0 339 return PasswordException;
michael@0 340 })();
michael@0 341
michael@0 342 var UnknownErrorException = (function UnknownErrorExceptionClosure() {
michael@0 343 function UnknownErrorException(msg, details) {
michael@0 344 this.name = 'UnknownErrorException';
michael@0 345 this.message = msg;
michael@0 346 this.details = details;
michael@0 347 }
michael@0 348
michael@0 349 UnknownErrorException.prototype = new Error();
michael@0 350 UnknownErrorException.constructor = UnknownErrorException;
michael@0 351
michael@0 352 return UnknownErrorException;
michael@0 353 })();
michael@0 354
michael@0 355 var InvalidPDFException = (function InvalidPDFExceptionClosure() {
michael@0 356 function InvalidPDFException(msg) {
michael@0 357 this.name = 'InvalidPDFException';
michael@0 358 this.message = msg;
michael@0 359 }
michael@0 360
michael@0 361 InvalidPDFException.prototype = new Error();
michael@0 362 InvalidPDFException.constructor = InvalidPDFException;
michael@0 363
michael@0 364 return InvalidPDFException;
michael@0 365 })();
michael@0 366
michael@0 367 var MissingPDFException = (function MissingPDFExceptionClosure() {
michael@0 368 function MissingPDFException(msg) {
michael@0 369 this.name = 'MissingPDFException';
michael@0 370 this.message = msg;
michael@0 371 }
michael@0 372
michael@0 373 MissingPDFException.prototype = new Error();
michael@0 374 MissingPDFException.constructor = MissingPDFException;
michael@0 375
michael@0 376 return MissingPDFException;
michael@0 377 })();
michael@0 378
michael@0 379 var NotImplementedException = (function NotImplementedExceptionClosure() {
michael@0 380 function NotImplementedException(msg) {
michael@0 381 this.message = msg;
michael@0 382 }
michael@0 383
michael@0 384 NotImplementedException.prototype = new Error();
michael@0 385 NotImplementedException.prototype.name = 'NotImplementedException';
michael@0 386 NotImplementedException.constructor = NotImplementedException;
michael@0 387
michael@0 388 return NotImplementedException;
michael@0 389 })();
michael@0 390
michael@0 391 var MissingDataException = (function MissingDataExceptionClosure() {
michael@0 392 function MissingDataException(begin, end) {
michael@0 393 this.begin = begin;
michael@0 394 this.end = end;
michael@0 395 this.message = 'Missing data [' + begin + ', ' + end + ')';
michael@0 396 }
michael@0 397
michael@0 398 MissingDataException.prototype = new Error();
michael@0 399 MissingDataException.prototype.name = 'MissingDataException';
michael@0 400 MissingDataException.constructor = MissingDataException;
michael@0 401
michael@0 402 return MissingDataException;
michael@0 403 })();
michael@0 404
michael@0 405 var XRefParseException = (function XRefParseExceptionClosure() {
michael@0 406 function XRefParseException(msg) {
michael@0 407 this.message = msg;
michael@0 408 }
michael@0 409
michael@0 410 XRefParseException.prototype = new Error();
michael@0 411 XRefParseException.prototype.name = 'XRefParseException';
michael@0 412 XRefParseException.constructor = XRefParseException;
michael@0 413
michael@0 414 return XRefParseException;
michael@0 415 })();
michael@0 416
michael@0 417
michael@0 418 function bytesToString(bytes) {
michael@0 419 var length = bytes.length;
michael@0 420 var MAX_ARGUMENT_COUNT = 8192;
michael@0 421 if (length < MAX_ARGUMENT_COUNT) {
michael@0 422 return String.fromCharCode.apply(null, bytes);
michael@0 423 }
michael@0 424 var strBuf = [];
michael@0 425 for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
michael@0 426 var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
michael@0 427 var chunk = bytes.subarray(i, chunkEnd);
michael@0 428 strBuf.push(String.fromCharCode.apply(null, chunk));
michael@0 429 }
michael@0 430 return strBuf.join('');
michael@0 431 }
michael@0 432
michael@0 433 function stringToArray(str) {
michael@0 434 var length = str.length;
michael@0 435 var array = [];
michael@0 436 for (var i = 0; i < length; ++i) {
michael@0 437 array[i] = str.charCodeAt(i);
michael@0 438 }
michael@0 439 return array;
michael@0 440 }
michael@0 441
michael@0 442 function stringToBytes(str) {
michael@0 443 var length = str.length;
michael@0 444 var bytes = new Uint8Array(length);
michael@0 445 for (var i = 0; i < length; ++i) {
michael@0 446 bytes[i] = str.charCodeAt(i) & 0xFF;
michael@0 447 }
michael@0 448 return bytes;
michael@0 449 }
michael@0 450
michael@0 451 function string32(value) {
michael@0 452 return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff,
michael@0 453 (value >> 8) & 0xff, value & 0xff);
michael@0 454 }
michael@0 455
michael@0 456 function log2(x) {
michael@0 457 var n = 1, i = 0;
michael@0 458 while (x > n) {
michael@0 459 n <<= 1;
michael@0 460 i++;
michael@0 461 }
michael@0 462 return i;
michael@0 463 }
michael@0 464
michael@0 465 function readInt8(data, start) {
michael@0 466 return (data[start] << 24) >> 24;
michael@0 467 }
michael@0 468
michael@0 469 function readUint16(data, offset) {
michael@0 470 return (data[offset] << 8) | data[offset + 1];
michael@0 471 }
michael@0 472
michael@0 473 function readUint32(data, offset) {
michael@0 474 return ((data[offset] << 24) | (data[offset + 1] << 16) |
michael@0 475 (data[offset + 2] << 8) | data[offset + 3]) >>> 0;
michael@0 476 }
michael@0 477
michael@0 478 // Lazy test the endianness of the platform
michael@0 479 // NOTE: This will be 'true' for simulated TypedArrays
michael@0 480 function isLittleEndian() {
michael@0 481 var buffer8 = new Uint8Array(2);
michael@0 482 buffer8[0] = 1;
michael@0 483 var buffer16 = new Uint16Array(buffer8.buffer);
michael@0 484 return (buffer16[0] === 1);
michael@0 485 }
michael@0 486
michael@0 487 Object.defineProperty(PDFJS, 'isLittleEndian', {
michael@0 488 configurable: true,
michael@0 489 get: function PDFJS_isLittleEndian() {
michael@0 490 return shadow(PDFJS, 'isLittleEndian', isLittleEndian());
michael@0 491 }
michael@0 492 });
michael@0 493
michael@0 494 PDFJS.hasCanvasTypedArrays = true;
michael@0 495
michael@0 496 var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
michael@0 497
michael@0 498 var Util = PDFJS.Util = (function UtilClosure() {
michael@0 499 function Util() {}
michael@0 500
michael@0 501 Util.makeCssRgb = function Util_makeCssRgb(rgb) {
michael@0 502 return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
michael@0 503 };
michael@0 504
michael@0 505 Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) {
michael@0 506 var rgb = ColorSpace.singletons.cmyk.getRgb(cmyk, 0);
michael@0 507 return Util.makeCssRgb(rgb);
michael@0 508 };
michael@0 509
michael@0 510 // Concatenates two transformation matrices together and returns the result.
michael@0 511 Util.transform = function Util_transform(m1, m2) {
michael@0 512 return [
michael@0 513 m1[0] * m2[0] + m1[2] * m2[1],
michael@0 514 m1[1] * m2[0] + m1[3] * m2[1],
michael@0 515 m1[0] * m2[2] + m1[2] * m2[3],
michael@0 516 m1[1] * m2[2] + m1[3] * m2[3],
michael@0 517 m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
michael@0 518 m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
michael@0 519 ];
michael@0 520 };
michael@0 521
michael@0 522 // For 2d affine transforms
michael@0 523 Util.applyTransform = function Util_applyTransform(p, m) {
michael@0 524 var xt = p[0] * m[0] + p[1] * m[2] + m[4];
michael@0 525 var yt = p[0] * m[1] + p[1] * m[3] + m[5];
michael@0 526 return [xt, yt];
michael@0 527 };
michael@0 528
michael@0 529 Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
michael@0 530 var d = m[0] * m[3] - m[1] * m[2];
michael@0 531 var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
michael@0 532 var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
michael@0 533 return [xt, yt];
michael@0 534 };
michael@0 535
michael@0 536 // Applies the transform to the rectangle and finds the minimum axially
michael@0 537 // aligned bounding box.
michael@0 538 Util.getAxialAlignedBoundingBox =
michael@0 539 function Util_getAxialAlignedBoundingBox(r, m) {
michael@0 540
michael@0 541 var p1 = Util.applyTransform(r, m);
michael@0 542 var p2 = Util.applyTransform(r.slice(2, 4), m);
michael@0 543 var p3 = Util.applyTransform([r[0], r[3]], m);
michael@0 544 var p4 = Util.applyTransform([r[2], r[1]], m);
michael@0 545 return [
michael@0 546 Math.min(p1[0], p2[0], p3[0], p4[0]),
michael@0 547 Math.min(p1[1], p2[1], p3[1], p4[1]),
michael@0 548 Math.max(p1[0], p2[0], p3[0], p4[0]),
michael@0 549 Math.max(p1[1], p2[1], p3[1], p4[1])
michael@0 550 ];
michael@0 551 };
michael@0 552
michael@0 553 Util.inverseTransform = function Util_inverseTransform(m) {
michael@0 554 var d = m[0] * m[3] - m[1] * m[2];
michael@0 555 return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
michael@0 556 (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
michael@0 557 };
michael@0 558
michael@0 559 // Apply a generic 3d matrix M on a 3-vector v:
michael@0 560 // | a b c | | X |
michael@0 561 // | d e f | x | Y |
michael@0 562 // | g h i | | Z |
michael@0 563 // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
michael@0 564 // with v as [X,Y,Z]
michael@0 565 Util.apply3dTransform = function Util_apply3dTransform(m, v) {
michael@0 566 return [
michael@0 567 m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
michael@0 568 m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
michael@0 569 m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
michael@0 570 ];
michael@0 571 };
michael@0 572
michael@0 573 // This calculation uses Singular Value Decomposition.
michael@0 574 // The SVD can be represented with formula A = USV. We are interested in the
michael@0 575 // matrix S here because it represents the scale values.
michael@0 576 Util.singularValueDecompose2dScale =
michael@0 577 function Util_singularValueDecompose2dScale(m) {
michael@0 578
michael@0 579 var transpose = [m[0], m[2], m[1], m[3]];
michael@0 580
michael@0 581 // Multiply matrix m with its transpose.
michael@0 582 var a = m[0] * transpose[0] + m[1] * transpose[2];
michael@0 583 var b = m[0] * transpose[1] + m[1] * transpose[3];
michael@0 584 var c = m[2] * transpose[0] + m[3] * transpose[2];
michael@0 585 var d = m[2] * transpose[1] + m[3] * transpose[3];
michael@0 586
michael@0 587 // Solve the second degree polynomial to get roots.
michael@0 588 var first = (a + d) / 2;
michael@0 589 var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
michael@0 590 var sx = first + second || 1;
michael@0 591 var sy = first - second || 1;
michael@0 592
michael@0 593 // Scale values are the square roots of the eigenvalues.
michael@0 594 return [Math.sqrt(sx), Math.sqrt(sy)];
michael@0 595 };
michael@0 596
michael@0 597 // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
michael@0 598 // For coordinate systems whose origin lies in the bottom-left, this
michael@0 599 // means normalization to (BL,TR) ordering. For systems with origin in the
michael@0 600 // top-left, this means (TL,BR) ordering.
michael@0 601 Util.normalizeRect = function Util_normalizeRect(rect) {
michael@0 602 var r = rect.slice(0); // clone rect
michael@0 603 if (rect[0] > rect[2]) {
michael@0 604 r[0] = rect[2];
michael@0 605 r[2] = rect[0];
michael@0 606 }
michael@0 607 if (rect[1] > rect[3]) {
michael@0 608 r[1] = rect[3];
michael@0 609 r[3] = rect[1];
michael@0 610 }
michael@0 611 return r;
michael@0 612 };
michael@0 613
michael@0 614 // Returns a rectangle [x1, y1, x2, y2] corresponding to the
michael@0 615 // intersection of rect1 and rect2. If no intersection, returns 'false'
michael@0 616 // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
michael@0 617 Util.intersect = function Util_intersect(rect1, rect2) {
michael@0 618 function compare(a, b) {
michael@0 619 return a - b;
michael@0 620 }
michael@0 621
michael@0 622 // Order points along the axes
michael@0 623 var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
michael@0 624 orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
michael@0 625 result = [];
michael@0 626
michael@0 627 rect1 = Util.normalizeRect(rect1);
michael@0 628 rect2 = Util.normalizeRect(rect2);
michael@0 629
michael@0 630 // X: first and second points belong to different rectangles?
michael@0 631 if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
michael@0 632 (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
michael@0 633 // Intersection must be between second and third points
michael@0 634 result[0] = orderedX[1];
michael@0 635 result[2] = orderedX[2];
michael@0 636 } else {
michael@0 637 return false;
michael@0 638 }
michael@0 639
michael@0 640 // Y: first and second points belong to different rectangles?
michael@0 641 if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
michael@0 642 (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
michael@0 643 // Intersection must be between second and third points
michael@0 644 result[1] = orderedY[1];
michael@0 645 result[3] = orderedY[2];
michael@0 646 } else {
michael@0 647 return false;
michael@0 648 }
michael@0 649
michael@0 650 return result;
michael@0 651 };
michael@0 652
michael@0 653 Util.sign = function Util_sign(num) {
michael@0 654 return num < 0 ? -1 : 1;
michael@0 655 };
michael@0 656
michael@0 657 // TODO(mack): Rename appendToArray
michael@0 658 Util.concatenateToArray = function concatenateToArray(arr1, arr2) {
michael@0 659 Array.prototype.push.apply(arr1, arr2);
michael@0 660 };
michael@0 661
michael@0 662 Util.prependToArray = function concatenateToArray(arr1, arr2) {
michael@0 663 Array.prototype.unshift.apply(arr1, arr2);
michael@0 664 };
michael@0 665
michael@0 666 Util.extendObj = function extendObj(obj1, obj2) {
michael@0 667 for (var key in obj2) {
michael@0 668 obj1[key] = obj2[key];
michael@0 669 }
michael@0 670 };
michael@0 671
michael@0 672 Util.getInheritableProperty = function Util_getInheritableProperty(dict,
michael@0 673 name) {
michael@0 674 while (dict && !dict.has(name)) {
michael@0 675 dict = dict.get('Parent');
michael@0 676 }
michael@0 677 if (!dict) {
michael@0 678 return null;
michael@0 679 }
michael@0 680 return dict.get(name);
michael@0 681 };
michael@0 682
michael@0 683 Util.inherit = function Util_inherit(sub, base, prototype) {
michael@0 684 sub.prototype = Object.create(base.prototype);
michael@0 685 sub.prototype.constructor = sub;
michael@0 686 for (var prop in prototype) {
michael@0 687 sub.prototype[prop] = prototype[prop];
michael@0 688 }
michael@0 689 };
michael@0 690
michael@0 691 Util.loadScript = function Util_loadScript(src, callback) {
michael@0 692 var script = document.createElement('script');
michael@0 693 var loaded = false;
michael@0 694 script.setAttribute('src', src);
michael@0 695 if (callback) {
michael@0 696 script.onload = function() {
michael@0 697 if (!loaded) {
michael@0 698 callback();
michael@0 699 }
michael@0 700 loaded = true;
michael@0 701 };
michael@0 702 }
michael@0 703 document.getElementsByTagName('head')[0].appendChild(script);
michael@0 704 };
michael@0 705
michael@0 706 return Util;
michael@0 707 })();
michael@0 708
michael@0 709 var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
michael@0 710 function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
michael@0 711 this.viewBox = viewBox;
michael@0 712 this.scale = scale;
michael@0 713 this.rotation = rotation;
michael@0 714 this.offsetX = offsetX;
michael@0 715 this.offsetY = offsetY;
michael@0 716
michael@0 717 // creating transform to convert pdf coordinate system to the normal
michael@0 718 // canvas like coordinates taking in account scale and rotation
michael@0 719 var centerX = (viewBox[2] + viewBox[0]) / 2;
michael@0 720 var centerY = (viewBox[3] + viewBox[1]) / 2;
michael@0 721 var rotateA, rotateB, rotateC, rotateD;
michael@0 722 rotation = rotation % 360;
michael@0 723 rotation = rotation < 0 ? rotation + 360 : rotation;
michael@0 724 switch (rotation) {
michael@0 725 case 180:
michael@0 726 rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
michael@0 727 break;
michael@0 728 case 90:
michael@0 729 rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
michael@0 730 break;
michael@0 731 case 270:
michael@0 732 rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
michael@0 733 break;
michael@0 734 //case 0:
michael@0 735 default:
michael@0 736 rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
michael@0 737 break;
michael@0 738 }
michael@0 739
michael@0 740 if (dontFlip) {
michael@0 741 rotateC = -rotateC; rotateD = -rotateD;
michael@0 742 }
michael@0 743
michael@0 744 var offsetCanvasX, offsetCanvasY;
michael@0 745 var width, height;
michael@0 746 if (rotateA === 0) {
michael@0 747 offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
michael@0 748 offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
michael@0 749 width = Math.abs(viewBox[3] - viewBox[1]) * scale;
michael@0 750 height = Math.abs(viewBox[2] - viewBox[0]) * scale;
michael@0 751 } else {
michael@0 752 offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
michael@0 753 offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
michael@0 754 width = Math.abs(viewBox[2] - viewBox[0]) * scale;
michael@0 755 height = Math.abs(viewBox[3] - viewBox[1]) * scale;
michael@0 756 }
michael@0 757 // creating transform for the following operations:
michael@0 758 // translate(-centerX, -centerY), rotate and flip vertically,
michael@0 759 // scale, and translate(offsetCanvasX, offsetCanvasY)
michael@0 760 this.transform = [
michael@0 761 rotateA * scale,
michael@0 762 rotateB * scale,
michael@0 763 rotateC * scale,
michael@0 764 rotateD * scale,
michael@0 765 offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
michael@0 766 offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
michael@0 767 ];
michael@0 768
michael@0 769 this.width = width;
michael@0 770 this.height = height;
michael@0 771 this.fontScale = scale;
michael@0 772 }
michael@0 773 PageViewport.prototype = {
michael@0 774 clone: function PageViewPort_clone(args) {
michael@0 775 args = args || {};
michael@0 776 var scale = 'scale' in args ? args.scale : this.scale;
michael@0 777 var rotation = 'rotation' in args ? args.rotation : this.rotation;
michael@0 778 return new PageViewport(this.viewBox.slice(), scale, rotation,
michael@0 779 this.offsetX, this.offsetY, args.dontFlip);
michael@0 780 },
michael@0 781 convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
michael@0 782 return Util.applyTransform([x, y], this.transform);
michael@0 783 },
michael@0 784 convertToViewportRectangle:
michael@0 785 function PageViewport_convertToViewportRectangle(rect) {
michael@0 786 var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
michael@0 787 var br = Util.applyTransform([rect[2], rect[3]], this.transform);
michael@0 788 return [tl[0], tl[1], br[0], br[1]];
michael@0 789 },
michael@0 790 convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
michael@0 791 return Util.applyInverseTransform([x, y], this.transform);
michael@0 792 }
michael@0 793 };
michael@0 794 return PageViewport;
michael@0 795 })();
michael@0 796
michael@0 797 var PDFStringTranslateTable = [
michael@0 798 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
michael@0 799 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
michael@0 800 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,
michael@0 801 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,
michael@0 802 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,
michael@0 803 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014,
michael@0 804 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C,
michael@0 805 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160,
michael@0 806 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC
michael@0 807 ];
michael@0 808
michael@0 809 function stringToPDFString(str) {
michael@0 810 var i, n = str.length, strBuf = [];
michael@0 811 if (str[0] === '\xFE' && str[1] === '\xFF') {
michael@0 812 // UTF16BE BOM
michael@0 813 for (i = 2; i < n; i += 2) {
michael@0 814 strBuf.push(String.fromCharCode(
michael@0 815 (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)));
michael@0 816 }
michael@0 817 } else {
michael@0 818 for (i = 0; i < n; ++i) {
michael@0 819 var code = PDFStringTranslateTable[str.charCodeAt(i)];
michael@0 820 strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
michael@0 821 }
michael@0 822 }
michael@0 823 return strBuf.join('');
michael@0 824 }
michael@0 825
michael@0 826 function stringToUTF8String(str) {
michael@0 827 return decodeURIComponent(escape(str));
michael@0 828 }
michael@0 829
michael@0 830 function isEmptyObj(obj) {
michael@0 831 for (var key in obj) {
michael@0 832 return false;
michael@0 833 }
michael@0 834 return true;
michael@0 835 }
michael@0 836
michael@0 837 function isBool(v) {
michael@0 838 return typeof v == 'boolean';
michael@0 839 }
michael@0 840
michael@0 841 function isInt(v) {
michael@0 842 return typeof v == 'number' && ((v | 0) == v);
michael@0 843 }
michael@0 844
michael@0 845 function isNum(v) {
michael@0 846 return typeof v == 'number';
michael@0 847 }
michael@0 848
michael@0 849 function isString(v) {
michael@0 850 return typeof v == 'string';
michael@0 851 }
michael@0 852
michael@0 853 function isNull(v) {
michael@0 854 return v === null;
michael@0 855 }
michael@0 856
michael@0 857 function isName(v) {
michael@0 858 return v instanceof Name;
michael@0 859 }
michael@0 860
michael@0 861 function isCmd(v, cmd) {
michael@0 862 return v instanceof Cmd && (!cmd || v.cmd == cmd);
michael@0 863 }
michael@0 864
michael@0 865 function isDict(v, type) {
michael@0 866 if (!(v instanceof Dict)) {
michael@0 867 return false;
michael@0 868 }
michael@0 869 if (!type) {
michael@0 870 return true;
michael@0 871 }
michael@0 872 var dictType = v.get('Type');
michael@0 873 return isName(dictType) && dictType.name == type;
michael@0 874 }
michael@0 875
michael@0 876 function isArray(v) {
michael@0 877 return v instanceof Array;
michael@0 878 }
michael@0 879
michael@0 880 function isStream(v) {
michael@0 881 return typeof v == 'object' && v !== null && v !== undefined &&
michael@0 882 ('getBytes' in v);
michael@0 883 }
michael@0 884
michael@0 885 function isArrayBuffer(v) {
michael@0 886 return typeof v == 'object' && v !== null && v !== undefined &&
michael@0 887 ('byteLength' in v);
michael@0 888 }
michael@0 889
michael@0 890 function isRef(v) {
michael@0 891 return v instanceof Ref;
michael@0 892 }
michael@0 893
michael@0 894 function isPDFFunction(v) {
michael@0 895 var fnDict;
michael@0 896 if (typeof v != 'object') {
michael@0 897 return false;
michael@0 898 } else if (isDict(v)) {
michael@0 899 fnDict = v;
michael@0 900 } else if (isStream(v)) {
michael@0 901 fnDict = v.dict;
michael@0 902 } else {
michael@0 903 return false;
michael@0 904 }
michael@0 905 return fnDict.has('FunctionType');
michael@0 906 }
michael@0 907
michael@0 908 /**
michael@0 909 * Legacy support for PDFJS Promise implementation.
michael@0 910 * TODO remove eventually
michael@0 911 * @ignore
michael@0 912 */
michael@0 913 var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
michael@0 914 return function LegacyPromise() {
michael@0 915 var resolve, reject;
michael@0 916 var promise = new Promise(function (resolve_, reject_) {
michael@0 917 resolve = resolve_;
michael@0 918 reject = reject_;
michael@0 919 });
michael@0 920 promise.resolve = resolve;
michael@0 921 promise.reject = reject;
michael@0 922 return promise;
michael@0 923 };
michael@0 924 })();
michael@0 925
michael@0 926 /**
michael@0 927 * Polyfill for Promises:
michael@0 928 * The following promise implementation tries to generally implment the
michael@0 929 * Promise/A+ spec. Some notable differences from other promise libaries are:
michael@0 930 * - There currently isn't a seperate deferred and promise object.
michael@0 931 * - Unhandled rejections eventually show an error if they aren't handled.
michael@0 932 *
michael@0 933 * Based off of the work in:
michael@0 934 * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
michael@0 935 */
michael@0 936 (function PromiseClosure() {
michael@0 937 if (globalScope.Promise) {
michael@0 938 // Promises existing in the DOM/Worker, checking presence of all/resolve
michael@0 939 if (typeof globalScope.Promise.all !== 'function') {
michael@0 940 globalScope.Promise.all = function (iterable) {
michael@0 941 var count = 0, results = [], resolve, reject;
michael@0 942 var promise = new globalScope.Promise(function (resolve_, reject_) {
michael@0 943 resolve = resolve_;
michael@0 944 reject = reject_;
michael@0 945 });
michael@0 946 iterable.forEach(function (p, i) {
michael@0 947 count++;
michael@0 948 p.then(function (result) {
michael@0 949 results[i] = result;
michael@0 950 count--;
michael@0 951 if (count === 0) {
michael@0 952 resolve(results);
michael@0 953 }
michael@0 954 }, reject);
michael@0 955 });
michael@0 956 if (count === 0) {
michael@0 957 resolve(results);
michael@0 958 }
michael@0 959 return promise;
michael@0 960 };
michael@0 961 }
michael@0 962 if (typeof globalScope.Promise.resolve !== 'function') {
michael@0 963 globalScope.Promise.resolve = function (x) {
michael@0 964 return new globalScope.Promise(function (resolve) { resolve(x); });
michael@0 965 };
michael@0 966 }
michael@0 967 return;
michael@0 968 }
michael@0 969 throw new Error('DOM Promise is not present');
michael@0 970 })();
michael@0 971
michael@0 972 var StatTimer = (function StatTimerClosure() {
michael@0 973 function rpad(str, pad, length) {
michael@0 974 while (str.length < length) {
michael@0 975 str += pad;
michael@0 976 }
michael@0 977 return str;
michael@0 978 }
michael@0 979 function StatTimer() {
michael@0 980 this.started = {};
michael@0 981 this.times = [];
michael@0 982 this.enabled = true;
michael@0 983 }
michael@0 984 StatTimer.prototype = {
michael@0 985 time: function StatTimer_time(name) {
michael@0 986 if (!this.enabled) {
michael@0 987 return;
michael@0 988 }
michael@0 989 if (name in this.started) {
michael@0 990 warn('Timer is already running for ' + name);
michael@0 991 }
michael@0 992 this.started[name] = Date.now();
michael@0 993 },
michael@0 994 timeEnd: function StatTimer_timeEnd(name) {
michael@0 995 if (!this.enabled) {
michael@0 996 return;
michael@0 997 }
michael@0 998 if (!(name in this.started)) {
michael@0 999 warn('Timer has not been started for ' + name);
michael@0 1000 }
michael@0 1001 this.times.push({
michael@0 1002 'name': name,
michael@0 1003 'start': this.started[name],
michael@0 1004 'end': Date.now()
michael@0 1005 });
michael@0 1006 // Remove timer from started so it can be called again.
michael@0 1007 delete this.started[name];
michael@0 1008 },
michael@0 1009 toString: function StatTimer_toString() {
michael@0 1010 var i, ii;
michael@0 1011 var times = this.times;
michael@0 1012 var out = '';
michael@0 1013 // Find the longest name for padding purposes.
michael@0 1014 var longest = 0;
michael@0 1015 for (i = 0, ii = times.length; i < ii; ++i) {
michael@0 1016 var name = times[i]['name'];
michael@0 1017 if (name.length > longest) {
michael@0 1018 longest = name.length;
michael@0 1019 }
michael@0 1020 }
michael@0 1021 for (i = 0, ii = times.length; i < ii; ++i) {
michael@0 1022 var span = times[i];
michael@0 1023 var duration = span.end - span.start;
michael@0 1024 out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
michael@0 1025 }
michael@0 1026 return out;
michael@0 1027 }
michael@0 1028 };
michael@0 1029 return StatTimer;
michael@0 1030 })();
michael@0 1031
michael@0 1032 PDFJS.createBlob = function createBlob(data, contentType) {
michael@0 1033 if (typeof Blob !== 'undefined') {
michael@0 1034 return new Blob([data], { type: contentType });
michael@0 1035 }
michael@0 1036 // Blob builder is deprecated in FF14 and removed in FF18.
michael@0 1037 var bb = new MozBlobBuilder();
michael@0 1038 bb.append(data);
michael@0 1039 return bb.getBlob(contentType);
michael@0 1040 };
michael@0 1041
michael@0 1042 PDFJS.createObjectURL = (function createObjectURLClosure() {
michael@0 1043 // Blob/createObjectURL is not available, falling back to data schema.
michael@0 1044 var digits =
michael@0 1045 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
michael@0 1046
michael@0 1047 return function createObjectURL(data, contentType) {
michael@0 1048 if (!PDFJS.disableCreateObjectURL &&
michael@0 1049 typeof URL !== 'undefined' && URL.createObjectURL) {
michael@0 1050 var blob = PDFJS.createBlob(data, contentType);
michael@0 1051 return URL.createObjectURL(blob);
michael@0 1052 }
michael@0 1053
michael@0 1054 var buffer = 'data:' + contentType + ';base64,';
michael@0 1055 for (var i = 0, ii = data.length; i < ii; i += 3) {
michael@0 1056 var b1 = data[i] & 0xFF;
michael@0 1057 var b2 = data[i + 1] & 0xFF;
michael@0 1058 var b3 = data[i + 2] & 0xFF;
michael@0 1059 var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
michael@0 1060 var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
michael@0 1061 var d4 = i + 2 < ii ? (b3 & 0x3F) : 64;
michael@0 1062 buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
michael@0 1063 }
michael@0 1064 return buffer;
michael@0 1065 };
michael@0 1066 })();
michael@0 1067
michael@0 1068 function MessageHandler(name, comObj) {
michael@0 1069 this.name = name;
michael@0 1070 this.comObj = comObj;
michael@0 1071 this.callbackIndex = 1;
michael@0 1072 this.postMessageTransfers = true;
michael@0 1073 var callbacks = this.callbacks = {};
michael@0 1074 var ah = this.actionHandler = {};
michael@0 1075
michael@0 1076 ah['console_log'] = [function ahConsoleLog(data) {
michael@0 1077 console.log.apply(console, data);
michael@0 1078 }];
michael@0 1079 ah['console_error'] = [function ahConsoleError(data) {
michael@0 1080 console.error.apply(console, data);
michael@0 1081 }];
michael@0 1082 ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
michael@0 1083 UnsupportedManager.notify(data);
michael@0 1084 }];
michael@0 1085
michael@0 1086 comObj.onmessage = function messageHandlerComObjOnMessage(event) {
michael@0 1087 var data = event.data;
michael@0 1088 if (data.isReply) {
michael@0 1089 var callbackId = data.callbackId;
michael@0 1090 if (data.callbackId in callbacks) {
michael@0 1091 var callback = callbacks[callbackId];
michael@0 1092 delete callbacks[callbackId];
michael@0 1093 callback(data.data);
michael@0 1094 } else {
michael@0 1095 error('Cannot resolve callback ' + callbackId);
michael@0 1096 }
michael@0 1097 } else if (data.action in ah) {
michael@0 1098 var action = ah[data.action];
michael@0 1099 if (data.callbackId) {
michael@0 1100 var deferred = {};
michael@0 1101 var promise = new Promise(function (resolve, reject) {
michael@0 1102 deferred.resolve = resolve;
michael@0 1103 deferred.reject = reject;
michael@0 1104 });
michael@0 1105 deferred.promise = promise;
michael@0 1106 promise.then(function(resolvedData) {
michael@0 1107 comObj.postMessage({
michael@0 1108 isReply: true,
michael@0 1109 callbackId: data.callbackId,
michael@0 1110 data: resolvedData
michael@0 1111 });
michael@0 1112 });
michael@0 1113 action[0].call(action[1], data.data, deferred);
michael@0 1114 } else {
michael@0 1115 action[0].call(action[1], data.data);
michael@0 1116 }
michael@0 1117 } else {
michael@0 1118 error('Unkown action from worker: ' + data.action);
michael@0 1119 }
michael@0 1120 };
michael@0 1121 }
michael@0 1122
michael@0 1123 MessageHandler.prototype = {
michael@0 1124 on: function messageHandlerOn(actionName, handler, scope) {
michael@0 1125 var ah = this.actionHandler;
michael@0 1126 if (ah[actionName]) {
michael@0 1127 error('There is already an actionName called "' + actionName + '"');
michael@0 1128 }
michael@0 1129 ah[actionName] = [handler, scope];
michael@0 1130 },
michael@0 1131 /**
michael@0 1132 * Sends a message to the comObj to invoke the action with the supplied data.
michael@0 1133 * @param {String} actionName Action to call.
michael@0 1134 * @param {JSON} data JSON data to send.
michael@0 1135 * @param {function} [callback] Optional callback that will handle a reply.
michael@0 1136 * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
michael@0 1137 */
michael@0 1138 send: function messageHandlerSend(actionName, data, callback, transfers) {
michael@0 1139 var message = {
michael@0 1140 action: actionName,
michael@0 1141 data: data
michael@0 1142 };
michael@0 1143 if (callback) {
michael@0 1144 var callbackId = this.callbackIndex++;
michael@0 1145 this.callbacks[callbackId] = callback;
michael@0 1146 message.callbackId = callbackId;
michael@0 1147 }
michael@0 1148 if (transfers && this.postMessageTransfers) {
michael@0 1149 this.comObj.postMessage(message, transfers);
michael@0 1150 } else {
michael@0 1151 this.comObj.postMessage(message);
michael@0 1152 }
michael@0 1153 }
michael@0 1154 };
michael@0 1155
michael@0 1156 function loadJpegStream(id, imageUrl, objs) {
michael@0 1157 var img = new Image();
michael@0 1158 img.onload = (function loadJpegStream_onloadClosure() {
michael@0 1159 objs.resolve(id, img);
michael@0 1160 });
michael@0 1161 img.src = imageUrl;
michael@0 1162 }
michael@0 1163
michael@0 1164
michael@0 1165 var ColorSpace = (function ColorSpaceClosure() {
michael@0 1166 // Constructor should define this.numComps, this.defaultColor, this.name
michael@0 1167 function ColorSpace() {
michael@0 1168 error('should not call ColorSpace constructor');
michael@0 1169 }
michael@0 1170
michael@0 1171 ColorSpace.prototype = {
michael@0 1172 /**
michael@0 1173 * Converts the color value to the RGB color. The color components are
michael@0 1174 * located in the src array starting from the srcOffset. Returns the array
michael@0 1175 * of the rgb components, each value ranging from [0,255].
michael@0 1176 */
michael@0 1177 getRgb: function ColorSpace_getRgb(src, srcOffset) {
michael@0 1178 var rgb = new Uint8Array(3);
michael@0 1179 this.getRgbItem(src, srcOffset, rgb, 0);
michael@0 1180 return rgb;
michael@0 1181 },
michael@0 1182 /**
michael@0 1183 * Converts the color value to the RGB color, similar to the getRgb method.
michael@0 1184 * The result placed into the dest array starting from the destOffset.
michael@0 1185 */
michael@0 1186 getRgbItem: function ColorSpace_getRgbItem(src, srcOffset,
michael@0 1187 dest, destOffset) {
michael@0 1188 error('Should not call ColorSpace.getRgbItem');
michael@0 1189 },
michael@0 1190 /**
michael@0 1191 * Converts the specified number of the color values to the RGB colors.
michael@0 1192 * The colors are located in the src array starting from the srcOffset.
michael@0 1193 * The result is placed into the dest array starting from the destOffset.
michael@0 1194 * The src array items shall be in [0,2^bits) range, the dest array items
michael@0 1195 * will be in [0,255] range. alpha01 indicates how many alpha components
michael@0 1196 * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA
michael@0 1197 * array).
michael@0 1198 */
michael@0 1199 getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
michael@0 1200 dest, destOffset, bits,
michael@0 1201 alpha01) {
michael@0 1202 error('Should not call ColorSpace.getRgbBuffer');
michael@0 1203 },
michael@0 1204 /**
michael@0 1205 * Determines the number of bytes required to store the result of the
michael@0 1206 * conversion done by the getRgbBuffer method. As in getRgbBuffer,
michael@0 1207 * |alpha01| is either 0 (RGB output) or 1 (RGBA output).
michael@0 1208 */
michael@0 1209 getOutputLength: function ColorSpace_getOutputLength(inputLength,
michael@0 1210 alpha01) {
michael@0 1211 error('Should not call ColorSpace.getOutputLength');
michael@0 1212 },
michael@0 1213 /**
michael@0 1214 * Returns true if source data will be equal the result/output data.
michael@0 1215 */
michael@0 1216 isPassthrough: function ColorSpace_isPassthrough(bits) {
michael@0 1217 return false;
michael@0 1218 },
michael@0 1219 /**
michael@0 1220 * Fills in the RGB colors in the destination buffer. alpha01 indicates
michael@0 1221 * how many alpha components there are in the dest array; it will be either
michael@0 1222 * 0 (RGB array) or 1 (RGBA array).
michael@0 1223 */
michael@0 1224 fillRgb: function ColorSpace_fillRgb(dest, originalWidth,
michael@0 1225 originalHeight, width, height,
michael@0 1226 actualHeight, bpc, comps, alpha01) {
michael@0 1227 var count = originalWidth * originalHeight;
michael@0 1228 var rgbBuf = null;
michael@0 1229 var numComponentColors = 1 << bpc;
michael@0 1230 var needsResizing = originalHeight != height || originalWidth != width;
michael@0 1231 var i, ii;
michael@0 1232
michael@0 1233 if (this.isPassthrough(bpc)) {
michael@0 1234 rgbBuf = comps;
michael@0 1235 } else if (this.numComps === 1 && count > numComponentColors &&
michael@0 1236 this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') {
michael@0 1237 // Optimization: create a color map when there is just one component and
michael@0 1238 // we are converting more colors than the size of the color map. We
michael@0 1239 // don't build the map if the colorspace is gray or rgb since those
michael@0 1240 // methods are faster than building a map. This mainly offers big speed
michael@0 1241 // ups for indexed and alternate colorspaces.
michael@0 1242 //
michael@0 1243 // TODO it may be worth while to cache the color map. While running
michael@0 1244 // testing I never hit a cache so I will leave that out for now (perhaps
michael@0 1245 // we are reparsing colorspaces too much?).
michael@0 1246 var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) :
michael@0 1247 new Uint16Array(numComponentColors);
michael@0 1248 var key;
michael@0 1249 for (i = 0; i < numComponentColors; i++) {
michael@0 1250 allColors[i] = i;
michael@0 1251 }
michael@0 1252 var colorMap = new Uint8Array(numComponentColors * 3);
michael@0 1253 this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc,
michael@0 1254 /* alpha01 = */ 0);
michael@0 1255
michael@0 1256 var destPos, rgbPos;
michael@0 1257 if (!needsResizing) {
michael@0 1258 // Fill in the RGB values directly into |dest|.
michael@0 1259 destPos = 0;
michael@0 1260 for (i = 0; i < count; ++i) {
michael@0 1261 key = comps[i] * 3;
michael@0 1262 dest[destPos++] = colorMap[key];
michael@0 1263 dest[destPos++] = colorMap[key + 1];
michael@0 1264 dest[destPos++] = colorMap[key + 2];
michael@0 1265 destPos += alpha01;
michael@0 1266 }
michael@0 1267 } else {
michael@0 1268 rgbBuf = new Uint8Array(count * 3);
michael@0 1269 rgbPos = 0;
michael@0 1270 for (i = 0; i < count; ++i) {
michael@0 1271 key = comps[i] * 3;
michael@0 1272 rgbBuf[rgbPos++] = colorMap[key];
michael@0 1273 rgbBuf[rgbPos++] = colorMap[key + 1];
michael@0 1274 rgbBuf[rgbPos++] = colorMap[key + 2];
michael@0 1275 }
michael@0 1276 }
michael@0 1277 } else {
michael@0 1278 if (!needsResizing) {
michael@0 1279 // Fill in the RGB values directly into |dest|.
michael@0 1280 this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc,
michael@0 1281 alpha01);
michael@0 1282 } else {
michael@0 1283 rgbBuf = new Uint8Array(count * 3);
michael@0 1284 this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc,
michael@0 1285 /* alpha01 = */ 0);
michael@0 1286 }
michael@0 1287 }
michael@0 1288
michael@0 1289 if (rgbBuf) {
michael@0 1290 if (needsResizing) {
michael@0 1291 rgbBuf = PDFImage.resize(rgbBuf, bpc, 3, originalWidth,
michael@0 1292 originalHeight, width, height);
michael@0 1293 }
michael@0 1294 rgbPos = 0;
michael@0 1295 destPos = 0;
michael@0 1296 for (i = 0, ii = width * actualHeight; i < ii; i++) {
michael@0 1297 dest[destPos++] = rgbBuf[rgbPos++];
michael@0 1298 dest[destPos++] = rgbBuf[rgbPos++];
michael@0 1299 dest[destPos++] = rgbBuf[rgbPos++];
michael@0 1300 destPos += alpha01;
michael@0 1301 }
michael@0 1302 }
michael@0 1303 },
michael@0 1304 /**
michael@0 1305 * True if the colorspace has components in the default range of [0, 1].
michael@0 1306 * This should be true for all colorspaces except for lab color spaces
michael@0 1307 * which are [0,100], [-128, 127], [-128, 127].
michael@0 1308 */
michael@0 1309 usesZeroToOneRange: true
michael@0 1310 };
michael@0 1311
michael@0 1312 ColorSpace.parse = function ColorSpace_parse(cs, xref, res) {
michael@0 1313 var IR = ColorSpace.parseToIR(cs, xref, res);
michael@0 1314 if (IR instanceof AlternateCS) {
michael@0 1315 return IR;
michael@0 1316 }
michael@0 1317 return ColorSpace.fromIR(IR);
michael@0 1318 };
michael@0 1319
michael@0 1320 ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
michael@0 1321 var name = isArray(IR) ? IR[0] : IR;
michael@0 1322 var whitePoint, blackPoint;
michael@0 1323
michael@0 1324 switch (name) {
michael@0 1325 case 'DeviceGrayCS':
michael@0 1326 return this.singletons.gray;
michael@0 1327 case 'DeviceRgbCS':
michael@0 1328 return this.singletons.rgb;
michael@0 1329 case 'DeviceCmykCS':
michael@0 1330 return this.singletons.cmyk;
michael@0 1331 case 'CalGrayCS':
michael@0 1332 whitePoint = IR[1].WhitePoint;
michael@0 1333 blackPoint = IR[1].BlackPoint;
michael@0 1334 var gamma = IR[1].Gamma;
michael@0 1335 return new CalGrayCS(whitePoint, blackPoint, gamma);
michael@0 1336 case 'PatternCS':
michael@0 1337 var basePatternCS = IR[1];
michael@0 1338 if (basePatternCS) {
michael@0 1339 basePatternCS = ColorSpace.fromIR(basePatternCS);
michael@0 1340 }
michael@0 1341 return new PatternCS(basePatternCS);
michael@0 1342 case 'IndexedCS':
michael@0 1343 var baseIndexedCS = IR[1];
michael@0 1344 var hiVal = IR[2];
michael@0 1345 var lookup = IR[3];
michael@0 1346 return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup);
michael@0 1347 case 'AlternateCS':
michael@0 1348 var numComps = IR[1];
michael@0 1349 var alt = IR[2];
michael@0 1350 var tintFnIR = IR[3];
michael@0 1351
michael@0 1352 return new AlternateCS(numComps, ColorSpace.fromIR(alt),
michael@0 1353 PDFFunction.fromIR(tintFnIR));
michael@0 1354 case 'LabCS':
michael@0 1355 whitePoint = IR[1].WhitePoint;
michael@0 1356 blackPoint = IR[1].BlackPoint;
michael@0 1357 var range = IR[1].Range;
michael@0 1358 return new LabCS(whitePoint, blackPoint, range);
michael@0 1359 default:
michael@0 1360 error('Unkown name ' + name);
michael@0 1361 }
michael@0 1362 return null;
michael@0 1363 };
michael@0 1364
michael@0 1365 ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) {
michael@0 1366 if (isName(cs)) {
michael@0 1367 var colorSpaces = res.get('ColorSpace');
michael@0 1368 if (isDict(colorSpaces)) {
michael@0 1369 var refcs = colorSpaces.get(cs.name);
michael@0 1370 if (refcs) {
michael@0 1371 cs = refcs;
michael@0 1372 }
michael@0 1373 }
michael@0 1374 }
michael@0 1375
michael@0 1376 cs = xref.fetchIfRef(cs);
michael@0 1377 var mode;
michael@0 1378
michael@0 1379 if (isName(cs)) {
michael@0 1380 mode = cs.name;
michael@0 1381 this.mode = mode;
michael@0 1382
michael@0 1383 switch (mode) {
michael@0 1384 case 'DeviceGray':
michael@0 1385 case 'G':
michael@0 1386 return 'DeviceGrayCS';
michael@0 1387 case 'DeviceRGB':
michael@0 1388 case 'RGB':
michael@0 1389 return 'DeviceRgbCS';
michael@0 1390 case 'DeviceCMYK':
michael@0 1391 case 'CMYK':
michael@0 1392 return 'DeviceCmykCS';
michael@0 1393 case 'Pattern':
michael@0 1394 return ['PatternCS', null];
michael@0 1395 default:
michael@0 1396 error('unrecognized colorspace ' + mode);
michael@0 1397 }
michael@0 1398 } else if (isArray(cs)) {
michael@0 1399 mode = cs[0].name;
michael@0 1400 this.mode = mode;
michael@0 1401 var numComps, params;
michael@0 1402
michael@0 1403 switch (mode) {
michael@0 1404 case 'DeviceGray':
michael@0 1405 case 'G':
michael@0 1406 return 'DeviceGrayCS';
michael@0 1407 case 'DeviceRGB':
michael@0 1408 case 'RGB':
michael@0 1409 return 'DeviceRgbCS';
michael@0 1410 case 'DeviceCMYK':
michael@0 1411 case 'CMYK':
michael@0 1412 return 'DeviceCmykCS';
michael@0 1413 case 'CalGray':
michael@0 1414 params = cs[1].getAll();
michael@0 1415 return ['CalGrayCS', params];
michael@0 1416 case 'CalRGB':
michael@0 1417 return 'DeviceRgbCS';
michael@0 1418 case 'ICCBased':
michael@0 1419 var stream = xref.fetchIfRef(cs[1]);
michael@0 1420 var dict = stream.dict;
michael@0 1421 numComps = dict.get('N');
michael@0 1422 if (numComps == 1) {
michael@0 1423 return 'DeviceGrayCS';
michael@0 1424 } else if (numComps == 3) {
michael@0 1425 return 'DeviceRgbCS';
michael@0 1426 } else if (numComps == 4) {
michael@0 1427 return 'DeviceCmykCS';
michael@0 1428 }
michael@0 1429 break;
michael@0 1430 case 'Pattern':
michael@0 1431 var basePatternCS = cs[1];
michael@0 1432 if (basePatternCS) {
michael@0 1433 basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
michael@0 1434 }
michael@0 1435 return ['PatternCS', basePatternCS];
michael@0 1436 case 'Indexed':
michael@0 1437 case 'I':
michael@0 1438 var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
michael@0 1439 var hiVal = cs[2] + 1;
michael@0 1440 var lookup = xref.fetchIfRef(cs[3]);
michael@0 1441 if (isStream(lookup)) {
michael@0 1442 lookup = lookup.getBytes();
michael@0 1443 }
michael@0 1444 return ['IndexedCS', baseIndexedCS, hiVal, lookup];
michael@0 1445 case 'Separation':
michael@0 1446 case 'DeviceN':
michael@0 1447 var name = cs[1];
michael@0 1448 numComps = 1;
michael@0 1449 if (isName(name)) {
michael@0 1450 numComps = 1;
michael@0 1451 } else if (isArray(name)) {
michael@0 1452 numComps = name.length;
michael@0 1453 }
michael@0 1454 var alt = ColorSpace.parseToIR(cs[2], xref, res);
michael@0 1455 var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3]));
michael@0 1456 return ['AlternateCS', numComps, alt, tintFnIR];
michael@0 1457 case 'Lab':
michael@0 1458 params = cs[1].getAll();
michael@0 1459 return ['LabCS', params];
michael@0 1460 default:
michael@0 1461 error('unimplemented color space object "' + mode + '"');
michael@0 1462 }
michael@0 1463 } else {
michael@0 1464 error('unrecognized color space object: "' + cs + '"');
michael@0 1465 }
michael@0 1466 return null;
michael@0 1467 };
michael@0 1468 /**
michael@0 1469 * Checks if a decode map matches the default decode map for a color space.
michael@0 1470 * This handles the general decode maps where there are two values per
michael@0 1471 * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
michael@0 1472 * This does not handle Lab, Indexed, or Pattern decode maps since they are
michael@0 1473 * slightly different.
michael@0 1474 * @param {Array} decode Decode map (usually from an image).
michael@0 1475 * @param {Number} n Number of components the color space has.
michael@0 1476 */
michael@0 1477 ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) {
michael@0 1478 if (!decode) {
michael@0 1479 return true;
michael@0 1480 }
michael@0 1481
michael@0 1482 if (n * 2 !== decode.length) {
michael@0 1483 warn('The decode map is not the correct length');
michael@0 1484 return true;
michael@0 1485 }
michael@0 1486 for (var i = 0, ii = decode.length; i < ii; i += 2) {
michael@0 1487 if (decode[i] !== 0 || decode[i + 1] != 1) {
michael@0 1488 return false;
michael@0 1489 }
michael@0 1490 }
michael@0 1491 return true;
michael@0 1492 };
michael@0 1493
michael@0 1494 ColorSpace.singletons = {
michael@0 1495 get gray() {
michael@0 1496 return shadow(this, 'gray', new DeviceGrayCS());
michael@0 1497 },
michael@0 1498 get rgb() {
michael@0 1499 return shadow(this, 'rgb', new DeviceRgbCS());
michael@0 1500 },
michael@0 1501 get cmyk() {
michael@0 1502 return shadow(this, 'cmyk', new DeviceCmykCS());
michael@0 1503 }
michael@0 1504 };
michael@0 1505
michael@0 1506 return ColorSpace;
michael@0 1507 })();
michael@0 1508
michael@0 1509 /**
michael@0 1510 * Alternate color space handles both Separation and DeviceN color spaces. A
michael@0 1511 * Separation color space is actually just a DeviceN with one color component.
michael@0 1512 * Both color spaces use a tinting function to convert colors to a base color
michael@0 1513 * space.
michael@0 1514 */
michael@0 1515 var AlternateCS = (function AlternateCSClosure() {
michael@0 1516 function AlternateCS(numComps, base, tintFn) {
michael@0 1517 this.name = 'Alternate';
michael@0 1518 this.numComps = numComps;
michael@0 1519 this.defaultColor = new Float32Array(numComps);
michael@0 1520 for (var i = 0; i < numComps; ++i) {
michael@0 1521 this.defaultColor[i] = 1;
michael@0 1522 }
michael@0 1523 this.base = base;
michael@0 1524 this.tintFn = tintFn;
michael@0 1525 }
michael@0 1526
michael@0 1527 AlternateCS.prototype = {
michael@0 1528 getRgb: ColorSpace.prototype.getRgb,
michael@0 1529 getRgbItem: function AlternateCS_getRgbItem(src, srcOffset,
michael@0 1530 dest, destOffset) {
michael@0 1531 var baseNumComps = this.base.numComps;
michael@0 1532 var input = 'subarray' in src ?
michael@0 1533 src.subarray(srcOffset, srcOffset + this.numComps) :
michael@0 1534 Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps);
michael@0 1535 var tinted = this.tintFn(input);
michael@0 1536 this.base.getRgbItem(tinted, 0, dest, destOffset);
michael@0 1537 },
michael@0 1538 getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count,
michael@0 1539 dest, destOffset, bits,
michael@0 1540 alpha01) {
michael@0 1541 var tintFn = this.tintFn;
michael@0 1542 var base = this.base;
michael@0 1543 var scale = 1 / ((1 << bits) - 1);
michael@0 1544 var baseNumComps = base.numComps;
michael@0 1545 var usesZeroToOneRange = base.usesZeroToOneRange;
michael@0 1546 var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) &&
michael@0 1547 alpha01 === 0;
michael@0 1548 var pos = isPassthrough ? destOffset : 0;
michael@0 1549 var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count);
michael@0 1550 var numComps = this.numComps;
michael@0 1551
michael@0 1552 var scaled = new Float32Array(numComps);
michael@0 1553 var i, j;
michael@0 1554 for (i = 0; i < count; i++) {
michael@0 1555 for (j = 0; j < numComps; j++) {
michael@0 1556 scaled[j] = src[srcOffset++] * scale;
michael@0 1557 }
michael@0 1558 var tinted = tintFn(scaled);
michael@0 1559 if (usesZeroToOneRange) {
michael@0 1560 for (j = 0; j < baseNumComps; j++) {
michael@0 1561 baseBuf[pos++] = tinted[j] * 255;
michael@0 1562 }
michael@0 1563 } else {
michael@0 1564 base.getRgbItem(tinted, 0, baseBuf, pos);
michael@0 1565 pos += baseNumComps;
michael@0 1566 }
michael@0 1567 }
michael@0 1568 if (!isPassthrough) {
michael@0 1569 base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01);
michael@0 1570 }
michael@0 1571 },
michael@0 1572 getOutputLength: function AlternateCS_getOutputLength(inputLength,
michael@0 1573 alpha01) {
michael@0 1574 return this.base.getOutputLength(inputLength *
michael@0 1575 this.base.numComps / this.numComps,
michael@0 1576 alpha01);
michael@0 1577 },
michael@0 1578 isPassthrough: ColorSpace.prototype.isPassthrough,
michael@0 1579 fillRgb: ColorSpace.prototype.fillRgb,
michael@0 1580 isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
michael@0 1581 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
michael@0 1582 },
michael@0 1583 usesZeroToOneRange: true
michael@0 1584 };
michael@0 1585
michael@0 1586 return AlternateCS;
michael@0 1587 })();
michael@0 1588
michael@0 1589 var PatternCS = (function PatternCSClosure() {
michael@0 1590 function PatternCS(baseCS) {
michael@0 1591 this.name = 'Pattern';
michael@0 1592 this.base = baseCS;
michael@0 1593 }
michael@0 1594 PatternCS.prototype = {};
michael@0 1595
michael@0 1596 return PatternCS;
michael@0 1597 })();
michael@0 1598
michael@0 1599 var IndexedCS = (function IndexedCSClosure() {
michael@0 1600 function IndexedCS(base, highVal, lookup) {
michael@0 1601 this.name = 'Indexed';
michael@0 1602 this.numComps = 1;
michael@0 1603 this.defaultColor = new Uint8Array([0]);
michael@0 1604 this.base = base;
michael@0 1605 this.highVal = highVal;
michael@0 1606
michael@0 1607 var baseNumComps = base.numComps;
michael@0 1608 var length = baseNumComps * highVal;
michael@0 1609 var lookupArray;
michael@0 1610
michael@0 1611 if (isStream(lookup)) {
michael@0 1612 lookupArray = new Uint8Array(length);
michael@0 1613 var bytes = lookup.getBytes(length);
michael@0 1614 lookupArray.set(bytes);
michael@0 1615 } else if (isString(lookup)) {
michael@0 1616 lookupArray = new Uint8Array(length);
michael@0 1617 for (var i = 0; i < length; ++i) {
michael@0 1618 lookupArray[i] = lookup.charCodeAt(i);
michael@0 1619 }
michael@0 1620 } else if (lookup instanceof Uint8Array || lookup instanceof Array) {
michael@0 1621 lookupArray = lookup;
michael@0 1622 } else {
michael@0 1623 error('Unrecognized lookup table: ' + lookup);
michael@0 1624 }
michael@0 1625 this.lookup = lookupArray;
michael@0 1626 }
michael@0 1627
michael@0 1628 IndexedCS.prototype = {
michael@0 1629 getRgb: ColorSpace.prototype.getRgb,
michael@0 1630 getRgbItem: function IndexedCS_getRgbItem(src, srcOffset,
michael@0 1631 dest, destOffset) {
michael@0 1632 var numComps = this.base.numComps;
michael@0 1633 var start = src[srcOffset] * numComps;
michael@0 1634 this.base.getRgbItem(this.lookup, start, dest, destOffset);
michael@0 1635 },
michael@0 1636 getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count,
michael@0 1637 dest, destOffset, bits,
michael@0 1638 alpha01) {
michael@0 1639 var base = this.base;
michael@0 1640 var numComps = base.numComps;
michael@0 1641 var outputDelta = base.getOutputLength(numComps, alpha01);
michael@0 1642 var lookup = this.lookup;
michael@0 1643
michael@0 1644 for (var i = 0; i < count; ++i) {
michael@0 1645 var lookupPos = src[srcOffset++] * numComps;
michael@0 1646 base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);
michael@0 1647 destOffset += outputDelta;
michael@0 1648 }
michael@0 1649 },
michael@0 1650 getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) {
michael@0 1651 return this.base.getOutputLength(inputLength * this.base.numComps,
michael@0 1652 alpha01);
michael@0 1653 },
michael@0 1654 isPassthrough: ColorSpace.prototype.isPassthrough,
michael@0 1655 fillRgb: ColorSpace.prototype.fillRgb,
michael@0 1656 isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
michael@0 1657 // indexed color maps shouldn't be changed
michael@0 1658 return true;
michael@0 1659 },
michael@0 1660 usesZeroToOneRange: true
michael@0 1661 };
michael@0 1662 return IndexedCS;
michael@0 1663 })();
michael@0 1664
michael@0 1665 var DeviceGrayCS = (function DeviceGrayCSClosure() {
michael@0 1666 function DeviceGrayCS() {
michael@0 1667 this.name = 'DeviceGray';
michael@0 1668 this.numComps = 1;
michael@0 1669 this.defaultColor = new Float32Array([0]);
michael@0 1670 }
michael@0 1671
michael@0 1672 DeviceGrayCS.prototype = {
michael@0 1673 getRgb: ColorSpace.prototype.getRgb,
michael@0 1674 getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset,
michael@0 1675 dest, destOffset) {
michael@0 1676 var c = (src[srcOffset] * 255) | 0;
michael@0 1677 c = c < 0 ? 0 : c > 255 ? 255 : c;
michael@0 1678 dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
michael@0 1679 },
michael@0 1680 getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count,
michael@0 1681 dest, destOffset, bits,
michael@0 1682 alpha01) {
michael@0 1683 var scale = 255 / ((1 << bits) - 1);
michael@0 1684 var j = srcOffset, q = destOffset;
michael@0 1685 for (var i = 0; i < count; ++i) {
michael@0 1686 var c = (scale * src[j++]) | 0;
michael@0 1687 dest[q++] = c;
michael@0 1688 dest[q++] = c;
michael@0 1689 dest[q++] = c;
michael@0 1690 q += alpha01;
michael@0 1691 }
michael@0 1692 },
michael@0 1693 getOutputLength: function DeviceGrayCS_getOutputLength(inputLength,
michael@0 1694 alpha01) {
michael@0 1695 return inputLength * (3 + alpha01);
michael@0 1696 },
michael@0 1697 isPassthrough: ColorSpace.prototype.isPassthrough,
michael@0 1698 fillRgb: ColorSpace.prototype.fillRgb,
michael@0 1699 isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
michael@0 1700 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
michael@0 1701 },
michael@0 1702 usesZeroToOneRange: true
michael@0 1703 };
michael@0 1704 return DeviceGrayCS;
michael@0 1705 })();
michael@0 1706
michael@0 1707 var DeviceRgbCS = (function DeviceRgbCSClosure() {
michael@0 1708 function DeviceRgbCS() {
michael@0 1709 this.name = 'DeviceRGB';
michael@0 1710 this.numComps = 3;
michael@0 1711 this.defaultColor = new Float32Array([0, 0, 0]);
michael@0 1712 }
michael@0 1713 DeviceRgbCS.prototype = {
michael@0 1714 getRgb: ColorSpace.prototype.getRgb,
michael@0 1715 getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset,
michael@0 1716 dest, destOffset) {
michael@0 1717 var r = (src[srcOffset] * 255) | 0;
michael@0 1718 var g = (src[srcOffset + 1] * 255) | 0;
michael@0 1719 var b = (src[srcOffset + 2] * 255) | 0;
michael@0 1720 dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r;
michael@0 1721 dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g;
michael@0 1722 dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b;
michael@0 1723 },
michael@0 1724 getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count,
michael@0 1725 dest, destOffset, bits,
michael@0 1726 alpha01) {
michael@0 1727 if (bits === 8 && alpha01 === 0) {
michael@0 1728 dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);
michael@0 1729 return;
michael@0 1730 }
michael@0 1731 var scale = 255 / ((1 << bits) - 1);
michael@0 1732 var j = srcOffset, q = destOffset;
michael@0 1733 for (var i = 0; i < count; ++i) {
michael@0 1734 dest[q++] = (scale * src[j++]) | 0;
michael@0 1735 dest[q++] = (scale * src[j++]) | 0;
michael@0 1736 dest[q++] = (scale * src[j++]) | 0;
michael@0 1737 q += alpha01;
michael@0 1738 }
michael@0 1739 },
michael@0 1740 getOutputLength: function DeviceRgbCS_getOutputLength(inputLength,
michael@0 1741 alpha01) {
michael@0 1742 return (inputLength * (3 + alpha01) / 3) | 0;
michael@0 1743 },
michael@0 1744 isPassthrough: function DeviceRgbCS_isPassthrough(bits) {
michael@0 1745 return bits == 8;
michael@0 1746 },
michael@0 1747 fillRgb: ColorSpace.prototype.fillRgb,
michael@0 1748 isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
michael@0 1749 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
michael@0 1750 },
michael@0 1751 usesZeroToOneRange: true
michael@0 1752 };
michael@0 1753 return DeviceRgbCS;
michael@0 1754 })();
michael@0 1755
michael@0 1756 var DeviceCmykCS = (function DeviceCmykCSClosure() {
michael@0 1757 // The coefficients below was found using numerical analysis: the method of
michael@0 1758 // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors,
michael@0 1759 // where color_value is the tabular value from the table of sampled RGB colors
michael@0 1760 // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding
michael@0 1761 // CMYK color conversion using the estimation below:
michael@0 1762 // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255
michael@0 1763 function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
michael@0 1764 var c = src[srcOffset + 0] * srcScale;
michael@0 1765 var m = src[srcOffset + 1] * srcScale;
michael@0 1766 var y = src[srcOffset + 2] * srcScale;
michael@0 1767 var k = src[srcOffset + 3] * srcScale;
michael@0 1768
michael@0 1769 var r =
michael@0 1770 (c * (-4.387332384609988 * c + 54.48615194189176 * m +
michael@0 1771 18.82290502165302 * y + 212.25662451639585 * k +
michael@0 1772 -285.2331026137004) +
michael@0 1773 m * (1.7149763477362134 * m - 5.6096736904047315 * y +
michael@0 1774 -17.873870861415444 * k - 5.497006427196366) +
michael@0 1775 y * (-2.5217340131683033 * y - 21.248923337353073 * k +
michael@0 1776 17.5119270841813) +
michael@0 1777 k * (-21.86122147463605 * k - 189.48180835922747) + 255) | 0;
michael@0 1778 var g =
michael@0 1779 (c * (8.841041422036149 * c + 60.118027045597366 * m +
michael@0 1780 6.871425592049007 * y + 31.159100130055922 * k +
michael@0 1781 -79.2970844816548) +
michael@0 1782 m * (-15.310361306967817 * m + 17.575251261109482 * y +
michael@0 1783 131.35250912493976 * k - 190.9453302588951) +
michael@0 1784 y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) +
michael@0 1785 k * (-20.737325471181034 * k - 187.80453709719578) + 255) | 0;
michael@0 1786 var b =
michael@0 1787 (c * (0.8842522430003296 * c + 8.078677503112928 * m +
michael@0 1788 30.89978309703729 * y - 0.23883238689178934 * k +
michael@0 1789 -14.183576799673286) +
michael@0 1790 m * (10.49593273432072 * m + 63.02378494754052 * y +
michael@0 1791 50.606957656360734 * k - 112.23884253719248) +
michael@0 1792 y * (0.03296041114873217 * y + 115.60384449646641 * k +
michael@0 1793 -193.58209356861505) +
michael@0 1794 k * (-22.33816807309886 * k - 180.12613974708367) + 255) | 0;
michael@0 1795
michael@0 1796 dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r;
michael@0 1797 dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g;
michael@0 1798 dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b;
michael@0 1799 }
michael@0 1800
michael@0 1801 function DeviceCmykCS() {
michael@0 1802 this.name = 'DeviceCMYK';
michael@0 1803 this.numComps = 4;
michael@0 1804 this.defaultColor = new Float32Array([0, 0, 0, 1]);
michael@0 1805 }
michael@0 1806 DeviceCmykCS.prototype = {
michael@0 1807 getRgb: ColorSpace.prototype.getRgb,
michael@0 1808 getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset,
michael@0 1809 dest, destOffset) {
michael@0 1810 convertToRgb(src, srcOffset, 1, dest, destOffset);
michael@0 1811 },
michael@0 1812 getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count,
michael@0 1813 dest, destOffset, bits,
michael@0 1814 alpha01) {
michael@0 1815 var scale = 1 / ((1 << bits) - 1);
michael@0 1816 for (var i = 0; i < count; i++) {
michael@0 1817 convertToRgb(src, srcOffset, scale, dest, destOffset);
michael@0 1818 srcOffset += 4;
michael@0 1819 destOffset += 3 + alpha01;
michael@0 1820 }
michael@0 1821 },
michael@0 1822 getOutputLength: function DeviceCmykCS_getOutputLength(inputLength,
michael@0 1823 alpha01) {
michael@0 1824 return (inputLength / 4 * (3 + alpha01)) | 0;
michael@0 1825 },
michael@0 1826 isPassthrough: ColorSpace.prototype.isPassthrough,
michael@0 1827 fillRgb: ColorSpace.prototype.fillRgb,
michael@0 1828 isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
michael@0 1829 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
michael@0 1830 },
michael@0 1831 usesZeroToOneRange: true
michael@0 1832 };
michael@0 1833
michael@0 1834 return DeviceCmykCS;
michael@0 1835 })();
michael@0 1836
michael@0 1837 //
michael@0 1838 // CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245
michael@0 1839 //
michael@0 1840 var CalGrayCS = (function CalGrayCSClosure() {
michael@0 1841 function CalGrayCS(whitePoint, blackPoint, gamma) {
michael@0 1842 this.name = 'CalGray';
michael@0 1843 this.numComps = 1;
michael@0 1844 this.defaultColor = new Float32Array([0]);
michael@0 1845
michael@0 1846 if (!whitePoint) {
michael@0 1847 error('WhitePoint missing - required for color space CalGray');
michael@0 1848 }
michael@0 1849 blackPoint = blackPoint || [0, 0, 0];
michael@0 1850 gamma = gamma || 1;
michael@0 1851
michael@0 1852 // Translate arguments to spec variables.
michael@0 1853 this.XW = whitePoint[0];
michael@0 1854 this.YW = whitePoint[1];
michael@0 1855 this.ZW = whitePoint[2];
michael@0 1856
michael@0 1857 this.XB = blackPoint[0];
michael@0 1858 this.YB = blackPoint[1];
michael@0 1859 this.ZB = blackPoint[2];
michael@0 1860
michael@0 1861 this.G = gamma;
michael@0 1862
michael@0 1863 // Validate variables as per spec.
michael@0 1864 if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
michael@0 1865 error('Invalid WhitePoint components for ' + this.name +
michael@0 1866 ', no fallback available');
michael@0 1867 }
michael@0 1868
michael@0 1869 if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
michael@0 1870 info('Invalid BlackPoint for ' + this.name + ', falling back to default');
michael@0 1871 this.XB = this.YB = this.ZB = 0;
michael@0 1872 }
michael@0 1873
michael@0 1874 if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) {
michael@0 1875 warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB +
michael@0 1876 ', ZB: ' + this.ZB + ', only default values are supported.');
michael@0 1877 }
michael@0 1878
michael@0 1879 if (this.G < 1) {
michael@0 1880 info('Invalid Gamma: ' + this.G + ' for ' + this.name +
michael@0 1881 ', falling back to default');
michael@0 1882 this.G = 1;
michael@0 1883 }
michael@0 1884 }
michael@0 1885
michael@0 1886 function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
michael@0 1887 // A represents a gray component of a calibrated gray space.
michael@0 1888 // A <---> AG in the spec
michael@0 1889 var A = src[srcOffset] * scale;
michael@0 1890 var AG = Math.pow(A, cs.G);
michael@0 1891
michael@0 1892 // Computes intermediate variables M, L, N as per spec.
michael@0 1893 // Except if other than default BlackPoint values are used.
michael@0 1894 var M = cs.XW * AG;
michael@0 1895 var L = cs.YW * AG;
michael@0 1896 var N = cs.ZW * AG;
michael@0 1897
michael@0 1898 // Decode XYZ, as per spec.
michael@0 1899 var X = M;
michael@0 1900 var Y = L;
michael@0 1901 var Z = N;
michael@0 1902
michael@0 1903 // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4.
michael@0 1904 // This yields values in range [0, 100].
michael@0 1905 var Lstar = Math.max(116 * Math.pow(Y, 1 / 3) - 16, 0);
michael@0 1906
michael@0 1907 // Convert values to rgb range [0, 255].
michael@0 1908 dest[destOffset] = Lstar * 255 / 100;
michael@0 1909 dest[destOffset + 1] = Lstar * 255 / 100;
michael@0 1910 dest[destOffset + 2] = Lstar * 255 / 100;
michael@0 1911 }
michael@0 1912
michael@0 1913 CalGrayCS.prototype = {
michael@0 1914 getRgb: ColorSpace.prototype.getRgb,
michael@0 1915 getRgbItem: function CalGrayCS_getRgbItem(src, srcOffset,
michael@0 1916 dest, destOffset) {
michael@0 1917 convertToRgb(this, src, srcOffset, dest, destOffset, 1);
michael@0 1918 },
michael@0 1919 getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count,
michael@0 1920 dest, destOffset, bits,
michael@0 1921 alpha01) {
michael@0 1922 var scale = 1 / ((1 << bits) - 1);
michael@0 1923
michael@0 1924 for (var i = 0; i < count; ++i) {
michael@0 1925 convertToRgb(this, src, srcOffset, dest, destOffset, scale);
michael@0 1926 srcOffset += 1;
michael@0 1927 destOffset += 3 + alpha01;
michael@0 1928 }
michael@0 1929 },
michael@0 1930 getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) {
michael@0 1931 return inputLength * (3 + alpha01);
michael@0 1932 },
michael@0 1933 isPassthrough: ColorSpace.prototype.isPassthrough,
michael@0 1934 fillRgb: ColorSpace.prototype.fillRgb,
michael@0 1935 isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) {
michael@0 1936 return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
michael@0 1937 },
michael@0 1938 usesZeroToOneRange: true
michael@0 1939 };
michael@0 1940 return CalGrayCS;
michael@0 1941 })();
michael@0 1942
michael@0 1943 //
michael@0 1944 // LabCS: Based on "PDF Reference, Sixth Ed", p.250
michael@0 1945 //
michael@0 1946 var LabCS = (function LabCSClosure() {
michael@0 1947 function LabCS(whitePoint, blackPoint, range) {
michael@0 1948 this.name = 'Lab';
michael@0 1949 this.numComps = 3;
michael@0 1950 this.defaultColor = new Float32Array([0, 0, 0]);
michael@0 1951
michael@0 1952 if (!whitePoint) {
michael@0 1953 error('WhitePoint missing - required for color space Lab');
michael@0 1954 }
michael@0 1955 blackPoint = blackPoint || [0, 0, 0];
michael@0 1956 range = range || [-100, 100, -100, 100];
michael@0 1957
michael@0 1958 // Translate args to spec variables
michael@0 1959 this.XW = whitePoint[0];
michael@0 1960 this.YW = whitePoint[1];
michael@0 1961 this.ZW = whitePoint[2];
michael@0 1962 this.amin = range[0];
michael@0 1963 this.amax = range[1];
michael@0 1964 this.bmin = range[2];
michael@0 1965 this.bmax = range[3];
michael@0 1966
michael@0 1967 // These are here just for completeness - the spec doesn't offer any
michael@0 1968 // formulas that use BlackPoint in Lab
michael@0 1969 this.XB = blackPoint[0];
michael@0 1970 this.YB = blackPoint[1];
michael@0 1971 this.ZB = blackPoint[2];
michael@0 1972
michael@0 1973 // Validate vars as per spec
michael@0 1974 if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) {
michael@0 1975 error('Invalid WhitePoint components, no fallback available');
michael@0 1976 }
michael@0 1977
michael@0 1978 if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
michael@0 1979 info('Invalid BlackPoint, falling back to default');
michael@0 1980 this.XB = this.YB = this.ZB = 0;
michael@0 1981 }
michael@0 1982
michael@0 1983 if (this.amin > this.amax || this.bmin > this.bmax) {
michael@0 1984 info('Invalid Range, falling back to defaults');
michael@0 1985 this.amin = -100;
michael@0 1986 this.amax = 100;
michael@0 1987 this.bmin = -100;
michael@0 1988 this.bmax = 100;
michael@0 1989 }
michael@0 1990 }
michael@0 1991
michael@0 1992 // Function g(x) from spec
michael@0 1993 function fn_g(x) {
michael@0 1994 if (x >= 6 / 29) {
michael@0 1995 return x * x * x;
michael@0 1996 } else {
michael@0 1997 return (108 / 841) * (x - 4 / 29);
michael@0 1998 }
michael@0 1999 }
michael@0 2000
michael@0 2001 function decode(value, high1, low2, high2) {
michael@0 2002 return low2 + (value) * (high2 - low2) / (high1);
michael@0 2003 }
michael@0 2004
michael@0 2005 // If decoding is needed maxVal should be 2^bits per component - 1.
michael@0 2006 function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) {
michael@0 2007 // XXX: Lab input is in the range of [0, 100], [amin, amax], [bmin, bmax]
michael@0 2008 // not the usual [0, 1]. If a command like setFillColor is used the src
michael@0 2009 // values will already be within the correct range. However, if we are
michael@0 2010 // converting an image we have to map the values to the correct range given
michael@0 2011 // above.
michael@0 2012 // Ls,as,bs <---> L*,a*,b* in the spec
michael@0 2013 var Ls = src[srcOffset];
michael@0 2014 var as = src[srcOffset + 1];
michael@0 2015 var bs = src[srcOffset + 2];
michael@0 2016 if (maxVal !== false) {
michael@0 2017 Ls = decode(Ls, maxVal, 0, 100);
michael@0 2018 as = decode(as, maxVal, cs.amin, cs.amax);
michael@0 2019 bs = decode(bs, maxVal, cs.bmin, cs.bmax);
michael@0 2020 }
michael@0 2021
michael@0 2022 // Adjust limits of 'as' and 'bs'
michael@0 2023 as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
michael@0 2024 bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
michael@0 2025
michael@0 2026 // Computes intermediate variables X,Y,Z as per spec
michael@0 2027 var M = (Ls + 16) / 116;
michael@0 2028 var L = M + (as / 500);
michael@0 2029 var N = M - (bs / 200);
michael@0 2030
michael@0 2031 var X = cs.XW * fn_g(L);
michael@0 2032 var Y = cs.YW * fn_g(M);
michael@0 2033 var Z = cs.ZW * fn_g(N);
michael@0 2034
michael@0 2035 var r, g, b;
michael@0 2036 // Using different conversions for D50 and D65 white points,
michael@0 2037 // per http://www.color.org/srgb.pdf
michael@0 2038 if (cs.ZW < 1) {
michael@0 2039 // Assuming D50 (X=0.9642, Y=1.00, Z=0.8249)
michael@0 2040 r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
michael@0 2041 g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
michael@0 2042 b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
michael@0 2043 } else {
michael@0 2044 // Assuming D65 (X=0.9505, Y=1.00, Z=1.0888)
michael@0 2045 r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
michael@0 2046 g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
michael@0 2047 b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
michael@0 2048 }
michael@0 2049 // clamp color values to [0,1] range then convert to [0,255] range.
michael@0 2050 dest[destOffset] = r <= 0 ? 0 : r >= 1 ? 255 : Math.sqrt(r) * 255 | 0;
michael@0 2051 dest[destOffset + 1] = g <= 0 ? 0 : g >= 1 ? 255 : Math.sqrt(g) * 255 | 0;
michael@0 2052 dest[destOffset + 2] = b <= 0 ? 0 : b >= 1 ? 255 : Math.sqrt(b) * 255 | 0;
michael@0 2053 }
michael@0 2054
michael@0 2055 LabCS.prototype = {
michael@0 2056 getRgb: ColorSpace.prototype.getRgb,
michael@0 2057 getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) {
michael@0 2058 convertToRgb(this, src, srcOffset, false, dest, destOffset);
michael@0 2059 },
michael@0 2060 getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count,
michael@0 2061 dest, destOffset, bits,
michael@0 2062 alpha01) {
michael@0 2063 var maxVal = (1 << bits) - 1;
michael@0 2064 for (var i = 0; i < count; i++) {
michael@0 2065 convertToRgb(this, src, srcOffset, maxVal, dest, destOffset);
michael@0 2066 srcOffset += 3;
michael@0 2067 destOffset += 3 + alpha01;
michael@0 2068 }
michael@0 2069 },
michael@0 2070 getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) {
michael@0 2071 return (inputLength * (3 + alpha01) / 3) | 0;
michael@0 2072 },
michael@0 2073 isPassthrough: ColorSpace.prototype.isPassthrough,
michael@0 2074 isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
michael@0 2075 // XXX: Decoding is handled with the lab conversion because of the strange
michael@0 2076 // ranges that are used.
michael@0 2077 return true;
michael@0 2078 },
michael@0 2079 usesZeroToOneRange: false
michael@0 2080 };
michael@0 2081 return LabCS;
michael@0 2082 })();
michael@0 2083
michael@0 2084
michael@0 2085
michael@0 2086 var PDFFunction = (function PDFFunctionClosure() {
michael@0 2087 var CONSTRUCT_SAMPLED = 0;
michael@0 2088 var CONSTRUCT_INTERPOLATED = 2;
michael@0 2089 var CONSTRUCT_STICHED = 3;
michael@0 2090 var CONSTRUCT_POSTSCRIPT = 4;
michael@0 2091
michael@0 2092 return {
michael@0 2093 getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
michael@0 2094 str) {
michael@0 2095 var i, ii;
michael@0 2096 var length = 1;
michael@0 2097 for (i = 0, ii = size.length; i < ii; i++) {
michael@0 2098 length *= size[i];
michael@0 2099 }
michael@0 2100 length *= outputSize;
michael@0 2101
michael@0 2102 var array = [];
michael@0 2103 var codeSize = 0;
michael@0 2104 var codeBuf = 0;
michael@0 2105 // 32 is a valid bps so shifting won't work
michael@0 2106 var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
michael@0 2107
michael@0 2108 var strBytes = str.getBytes((length * bps + 7) / 8);
michael@0 2109 var strIdx = 0;
michael@0 2110 for (i = 0; i < length; i++) {
michael@0 2111 while (codeSize < bps) {
michael@0 2112 codeBuf <<= 8;
michael@0 2113 codeBuf |= strBytes[strIdx++];
michael@0 2114 codeSize += 8;
michael@0 2115 }
michael@0 2116 codeSize -= bps;
michael@0 2117 array.push((codeBuf >> codeSize) * sampleMul);
michael@0 2118 codeBuf &= (1 << codeSize) - 1;
michael@0 2119 }
michael@0 2120 return array;
michael@0 2121 },
michael@0 2122
michael@0 2123 getIR: function PDFFunction_getIR(xref, fn) {
michael@0 2124 var dict = fn.dict;
michael@0 2125 if (!dict) {
michael@0 2126 dict = fn;
michael@0 2127 }
michael@0 2128
michael@0 2129 var types = [this.constructSampled,
michael@0 2130 null,
michael@0 2131 this.constructInterpolated,
michael@0 2132 this.constructStiched,
michael@0 2133 this.constructPostScript];
michael@0 2134
michael@0 2135 var typeNum = dict.get('FunctionType');
michael@0 2136 var typeFn = types[typeNum];
michael@0 2137 if (!typeFn) {
michael@0 2138 error('Unknown type of function');
michael@0 2139 }
michael@0 2140
michael@0 2141 return typeFn.call(this, fn, dict, xref);
michael@0 2142 },
michael@0 2143
michael@0 2144 fromIR: function PDFFunction_fromIR(IR) {
michael@0 2145 var type = IR[0];
michael@0 2146 switch (type) {
michael@0 2147 case CONSTRUCT_SAMPLED:
michael@0 2148 return this.constructSampledFromIR(IR);
michael@0 2149 case CONSTRUCT_INTERPOLATED:
michael@0 2150 return this.constructInterpolatedFromIR(IR);
michael@0 2151 case CONSTRUCT_STICHED:
michael@0 2152 return this.constructStichedFromIR(IR);
michael@0 2153 //case CONSTRUCT_POSTSCRIPT:
michael@0 2154 default:
michael@0 2155 return this.constructPostScriptFromIR(IR);
michael@0 2156 }
michael@0 2157 },
michael@0 2158
michael@0 2159 parse: function PDFFunction_parse(xref, fn) {
michael@0 2160 var IR = this.getIR(xref, fn);
michael@0 2161 return this.fromIR(IR);
michael@0 2162 },
michael@0 2163
michael@0 2164 constructSampled: function PDFFunction_constructSampled(str, dict) {
michael@0 2165 function toMultiArray(arr) {
michael@0 2166 var inputLength = arr.length;
michael@0 2167 var out = [];
michael@0 2168 var index = 0;
michael@0 2169 for (var i = 0; i < inputLength; i += 2) {
michael@0 2170 out[index] = [arr[i], arr[i + 1]];
michael@0 2171 ++index;
michael@0 2172 }
michael@0 2173 return out;
michael@0 2174 }
michael@0 2175 var domain = dict.get('Domain');
michael@0 2176 var range = dict.get('Range');
michael@0 2177
michael@0 2178 if (!domain || !range) {
michael@0 2179 error('No domain or range');
michael@0 2180 }
michael@0 2181
michael@0 2182 var inputSize = domain.length / 2;
michael@0 2183 var outputSize = range.length / 2;
michael@0 2184
michael@0 2185 domain = toMultiArray(domain);
michael@0 2186 range = toMultiArray(range);
michael@0 2187
michael@0 2188 var size = dict.get('Size');
michael@0 2189 var bps = dict.get('BitsPerSample');
michael@0 2190 var order = dict.get('Order') || 1;
michael@0 2191 if (order !== 1) {
michael@0 2192 // No description how cubic spline interpolation works in PDF32000:2008
michael@0 2193 // As in poppler, ignoring order, linear interpolation may work as good
michael@0 2194 info('No support for cubic spline interpolation: ' + order);
michael@0 2195 }
michael@0 2196
michael@0 2197 var encode = dict.get('Encode');
michael@0 2198 if (!encode) {
michael@0 2199 encode = [];
michael@0 2200 for (var i = 0; i < inputSize; ++i) {
michael@0 2201 encode.push(0);
michael@0 2202 encode.push(size[i] - 1);
michael@0 2203 }
michael@0 2204 }
michael@0 2205 encode = toMultiArray(encode);
michael@0 2206
michael@0 2207 var decode = dict.get('Decode');
michael@0 2208 if (!decode) {
michael@0 2209 decode = range;
michael@0 2210 } else {
michael@0 2211 decode = toMultiArray(decode);
michael@0 2212 }
michael@0 2213
michael@0 2214 var samples = this.getSampleArray(size, outputSize, bps, str);
michael@0 2215
michael@0 2216 return [
michael@0 2217 CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
michael@0 2218 outputSize, Math.pow(2, bps) - 1, range
michael@0 2219 ];
michael@0 2220 },
michael@0 2221
michael@0 2222 constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
michael@0 2223 // See chapter 3, page 109 of the PDF reference
michael@0 2224 function interpolate(x, xmin, xmax, ymin, ymax) {
michael@0 2225 return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
michael@0 2226 }
michael@0 2227
michael@0 2228 return function constructSampledFromIRResult(args) {
michael@0 2229 // See chapter 3, page 110 of the PDF reference.
michael@0 2230 var m = IR[1];
michael@0 2231 var domain = IR[2];
michael@0 2232 var encode = IR[3];
michael@0 2233 var decode = IR[4];
michael@0 2234 var samples = IR[5];
michael@0 2235 var size = IR[6];
michael@0 2236 var n = IR[7];
michael@0 2237 //var mask = IR[8];
michael@0 2238 var range = IR[9];
michael@0 2239
michael@0 2240 if (m != args.length) {
michael@0 2241 error('Incorrect number of arguments: ' + m + ' != ' +
michael@0 2242 args.length);
michael@0 2243 }
michael@0 2244
michael@0 2245 var x = args;
michael@0 2246
michael@0 2247 // Building the cube vertices: its part and sample index
michael@0 2248 // http://rjwagner49.com/Mathematics/Interpolation.pdf
michael@0 2249 var cubeVertices = 1 << m;
michael@0 2250 var cubeN = new Float64Array(cubeVertices);
michael@0 2251 var cubeVertex = new Uint32Array(cubeVertices);
michael@0 2252 var i, j;
michael@0 2253 for (j = 0; j < cubeVertices; j++) {
michael@0 2254 cubeN[j] = 1;
michael@0 2255 }
michael@0 2256
michael@0 2257 var k = n, pos = 1;
michael@0 2258 // Map x_i to y_j for 0 <= i < m using the sampled function.
michael@0 2259 for (i = 0; i < m; ++i) {
michael@0 2260 // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
michael@0 2261 var domain_2i = domain[i][0];
michael@0 2262 var domain_2i_1 = domain[i][1];
michael@0 2263 var xi = Math.min(Math.max(x[i], domain_2i), domain_2i_1);
michael@0 2264
michael@0 2265 // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
michael@0 2266 // Encode_2i, Encode_2i+1)
michael@0 2267 var e = interpolate(xi, domain_2i, domain_2i_1,
michael@0 2268 encode[i][0], encode[i][1]);
michael@0 2269
michael@0 2270 // e_i' = min(max(e_i, 0), Size_i - 1)
michael@0 2271 var size_i = size[i];
michael@0 2272 e = Math.min(Math.max(e, 0), size_i - 1);
michael@0 2273
michael@0 2274 // Adjusting the cube: N and vertex sample index
michael@0 2275 var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
michael@0 2276 var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
michael@0 2277 var n1 = e - e0; // (e - e0) / (e1 - e0);
michael@0 2278 var offset0 = e0 * k;
michael@0 2279 var offset1 = offset0 + k; // e1 * k
michael@0 2280 for (j = 0; j < cubeVertices; j++) {
michael@0 2281 if (j & pos) {
michael@0 2282 cubeN[j] *= n1;
michael@0 2283 cubeVertex[j] += offset1;
michael@0 2284 } else {
michael@0 2285 cubeN[j] *= n0;
michael@0 2286 cubeVertex[j] += offset0;
michael@0 2287 }
michael@0 2288 }
michael@0 2289
michael@0 2290 k *= size_i;
michael@0 2291 pos <<= 1;
michael@0 2292 }
michael@0 2293
michael@0 2294 var y = new Float64Array(n);
michael@0 2295 for (j = 0; j < n; ++j) {
michael@0 2296 // Sum all cube vertices' samples portions
michael@0 2297 var rj = 0;
michael@0 2298 for (i = 0; i < cubeVertices; i++) {
michael@0 2299 rj += samples[cubeVertex[i] + j] * cubeN[i];
michael@0 2300 }
michael@0 2301
michael@0 2302 // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
michael@0 2303 // Decode_2j, Decode_2j+1)
michael@0 2304 rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
michael@0 2305
michael@0 2306 // y_j = min(max(r_j, range_2j), range_2j+1)
michael@0 2307 y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
michael@0 2308 }
michael@0 2309
michael@0 2310 return y;
michael@0 2311 };
michael@0 2312 },
michael@0 2313
michael@0 2314 constructInterpolated: function PDFFunction_constructInterpolated(str,
michael@0 2315 dict) {
michael@0 2316 var c0 = dict.get('C0') || [0];
michael@0 2317 var c1 = dict.get('C1') || [1];
michael@0 2318 var n = dict.get('N');
michael@0 2319
michael@0 2320 if (!isArray(c0) || !isArray(c1)) {
michael@0 2321 error('Illegal dictionary for interpolated function');
michael@0 2322 }
michael@0 2323
michael@0 2324 var length = c0.length;
michael@0 2325 var diff = [];
michael@0 2326 for (var i = 0; i < length; ++i) {
michael@0 2327 diff.push(c1[i] - c0[i]);
michael@0 2328 }
michael@0 2329
michael@0 2330 return [CONSTRUCT_INTERPOLATED, c0, diff, n];
michael@0 2331 },
michael@0 2332
michael@0 2333 constructInterpolatedFromIR:
michael@0 2334 function PDFFunction_constructInterpolatedFromIR(IR) {
michael@0 2335 var c0 = IR[1];
michael@0 2336 var diff = IR[2];
michael@0 2337 var n = IR[3];
michael@0 2338
michael@0 2339 var length = diff.length;
michael@0 2340
michael@0 2341 return function constructInterpolatedFromIRResult(args) {
michael@0 2342 var x = n == 1 ? args[0] : Math.pow(args[0], n);
michael@0 2343
michael@0 2344 var out = [];
michael@0 2345 for (var j = 0; j < length; ++j) {
michael@0 2346 out.push(c0[j] + (x * diff[j]));
michael@0 2347 }
michael@0 2348
michael@0 2349 return out;
michael@0 2350
michael@0 2351 };
michael@0 2352 },
michael@0 2353
michael@0 2354 constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
michael@0 2355 var domain = dict.get('Domain');
michael@0 2356
michael@0 2357 if (!domain) {
michael@0 2358 error('No domain');
michael@0 2359 }
michael@0 2360
michael@0 2361 var inputSize = domain.length / 2;
michael@0 2362 if (inputSize != 1) {
michael@0 2363 error('Bad domain for stiched function');
michael@0 2364 }
michael@0 2365
michael@0 2366 var fnRefs = dict.get('Functions');
michael@0 2367 var fns = [];
michael@0 2368 for (var i = 0, ii = fnRefs.length; i < ii; ++i) {
michael@0 2369 fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i])));
michael@0 2370 }
michael@0 2371
michael@0 2372 var bounds = dict.get('Bounds');
michael@0 2373 var encode = dict.get('Encode');
michael@0 2374
michael@0 2375 return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
michael@0 2376 },
michael@0 2377
michael@0 2378 constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) {
michael@0 2379 var domain = IR[1];
michael@0 2380 var bounds = IR[2];
michael@0 2381 var encode = IR[3];
michael@0 2382 var fnsIR = IR[4];
michael@0 2383 var fns = [];
michael@0 2384
michael@0 2385 for (var i = 0, ii = fnsIR.length; i < ii; i++) {
michael@0 2386 fns.push(PDFFunction.fromIR(fnsIR[i]));
michael@0 2387 }
michael@0 2388
michael@0 2389 return function constructStichedFromIRResult(args) {
michael@0 2390 var clip = function constructStichedFromIRClip(v, min, max) {
michael@0 2391 if (v > max) {
michael@0 2392 v = max;
michael@0 2393 } else if (v < min) {
michael@0 2394 v = min;
michael@0 2395 }
michael@0 2396 return v;
michael@0 2397 };
michael@0 2398
michael@0 2399 // clip to domain
michael@0 2400 var v = clip(args[0], domain[0], domain[1]);
michael@0 2401 // calulate which bound the value is in
michael@0 2402 for (var i = 0, ii = bounds.length; i < ii; ++i) {
michael@0 2403 if (v < bounds[i]) {
michael@0 2404 break;
michael@0 2405 }
michael@0 2406 }
michael@0 2407
michael@0 2408 // encode value into domain of function
michael@0 2409 var dmin = domain[0];
michael@0 2410 if (i > 0) {
michael@0 2411 dmin = bounds[i - 1];
michael@0 2412 }
michael@0 2413 var dmax = domain[1];
michael@0 2414 if (i < bounds.length) {
michael@0 2415 dmax = bounds[i];
michael@0 2416 }
michael@0 2417
michael@0 2418 var rmin = encode[2 * i];
michael@0 2419 var rmax = encode[2 * i + 1];
michael@0 2420
michael@0 2421 var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
michael@0 2422
michael@0 2423 // call the appropriate function
michael@0 2424 return fns[i]([v2]);
michael@0 2425 };
michael@0 2426 },
michael@0 2427
michael@0 2428 constructPostScript: function PDFFunction_constructPostScript(fn, dict,
michael@0 2429 xref) {
michael@0 2430 var domain = dict.get('Domain');
michael@0 2431 var range = dict.get('Range');
michael@0 2432
michael@0 2433 if (!domain) {
michael@0 2434 error('No domain.');
michael@0 2435 }
michael@0 2436
michael@0 2437 if (!range) {
michael@0 2438 error('No range.');
michael@0 2439 }
michael@0 2440
michael@0 2441 var lexer = new PostScriptLexer(fn);
michael@0 2442 var parser = new PostScriptParser(lexer);
michael@0 2443 var code = parser.parse();
michael@0 2444
michael@0 2445 return [CONSTRUCT_POSTSCRIPT, domain, range, code];
michael@0 2446 },
michael@0 2447
michael@0 2448 constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(
michael@0 2449 IR) {
michael@0 2450 var domain = IR[1];
michael@0 2451 var range = IR[2];
michael@0 2452 var code = IR[3];
michael@0 2453 var numOutputs = range.length / 2;
michael@0 2454 var evaluator = new PostScriptEvaluator(code);
michael@0 2455 // Cache the values for a big speed up, the cache size is limited though
michael@0 2456 // since the number of possible values can be huge from a PS function.
michael@0 2457 var cache = new FunctionCache();
michael@0 2458 return function constructPostScriptFromIRResult(args) {
michael@0 2459 var initialStack = [];
michael@0 2460 for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
michael@0 2461 initialStack.push(args[i]);
michael@0 2462 }
michael@0 2463
michael@0 2464 var key = initialStack.join('_');
michael@0 2465 if (cache.has(key)) {
michael@0 2466 return cache.get(key);
michael@0 2467 }
michael@0 2468
michael@0 2469 var stack = evaluator.execute(initialStack);
michael@0 2470 var transformed = [];
michael@0 2471 for (i = numOutputs - 1; i >= 0; --i) {
michael@0 2472 var out = stack.pop();
michael@0 2473 var rangeIndex = 2 * i;
michael@0 2474 if (out < range[rangeIndex]) {
michael@0 2475 out = range[rangeIndex];
michael@0 2476 } else if (out > range[rangeIndex + 1]) {
michael@0 2477 out = range[rangeIndex + 1];
michael@0 2478 }
michael@0 2479 transformed[i] = out;
michael@0 2480 }
michael@0 2481 cache.set(key, transformed);
michael@0 2482 return transformed;
michael@0 2483 };
michael@0 2484 }
michael@0 2485 };
michael@0 2486 })();
michael@0 2487
michael@0 2488 var FunctionCache = (function FunctionCacheClosure() {
michael@0 2489 // Of 10 PDF's with type4 functions the maxium number of distinct values seen
michael@0 2490 // was 256. This still may need some tweaking in the future though.
michael@0 2491 var MAX_CACHE_SIZE = 1024;
michael@0 2492 function FunctionCache() {
michael@0 2493 this.cache = {};
michael@0 2494 this.total = 0;
michael@0 2495 }
michael@0 2496 FunctionCache.prototype = {
michael@0 2497 has: function FunctionCache_has(key) {
michael@0 2498 return key in this.cache;
michael@0 2499 },
michael@0 2500 get: function FunctionCache_get(key) {
michael@0 2501 return this.cache[key];
michael@0 2502 },
michael@0 2503 set: function FunctionCache_set(key, value) {
michael@0 2504 if (this.total < MAX_CACHE_SIZE) {
michael@0 2505 this.cache[key] = value;
michael@0 2506 this.total++;
michael@0 2507 }
michael@0 2508 }
michael@0 2509 };
michael@0 2510 return FunctionCache;
michael@0 2511 })();
michael@0 2512
michael@0 2513 var PostScriptStack = (function PostScriptStackClosure() {
michael@0 2514 var MAX_STACK_SIZE = 100;
michael@0 2515 function PostScriptStack(initialStack) {
michael@0 2516 this.stack = initialStack || [];
michael@0 2517 }
michael@0 2518
michael@0 2519 PostScriptStack.prototype = {
michael@0 2520 push: function PostScriptStack_push(value) {
michael@0 2521 if (this.stack.length >= MAX_STACK_SIZE) {
michael@0 2522 error('PostScript function stack overflow.');
michael@0 2523 }
michael@0 2524 this.stack.push(value);
michael@0 2525 },
michael@0 2526 pop: function PostScriptStack_pop() {
michael@0 2527 if (this.stack.length <= 0) {
michael@0 2528 error('PostScript function stack underflow.');
michael@0 2529 }
michael@0 2530 return this.stack.pop();
michael@0 2531 },
michael@0 2532 copy: function PostScriptStack_copy(n) {
michael@0 2533 if (this.stack.length + n >= MAX_STACK_SIZE) {
michael@0 2534 error('PostScript function stack overflow.');
michael@0 2535 }
michael@0 2536 var stack = this.stack;
michael@0 2537 for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
michael@0 2538 stack.push(stack[i]);
michael@0 2539 }
michael@0 2540 },
michael@0 2541 index: function PostScriptStack_index(n) {
michael@0 2542 this.push(this.stack[this.stack.length - n - 1]);
michael@0 2543 },
michael@0 2544 // rotate the last n stack elements p times
michael@0 2545 roll: function PostScriptStack_roll(n, p) {
michael@0 2546 var stack = this.stack;
michael@0 2547 var l = stack.length - n;
michael@0 2548 var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
michael@0 2549 for (i = l, j = r; i < j; i++, j--) {
michael@0 2550 t = stack[i]; stack[i] = stack[j]; stack[j] = t;
michael@0 2551 }
michael@0 2552 for (i = l, j = c - 1; i < j; i++, j--) {
michael@0 2553 t = stack[i]; stack[i] = stack[j]; stack[j] = t;
michael@0 2554 }
michael@0 2555 for (i = c, j = r; i < j; i++, j--) {
michael@0 2556 t = stack[i]; stack[i] = stack[j]; stack[j] = t;
michael@0 2557 }
michael@0 2558 }
michael@0 2559 };
michael@0 2560 return PostScriptStack;
michael@0 2561 })();
michael@0 2562 var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
michael@0 2563 function PostScriptEvaluator(operators) {
michael@0 2564 this.operators = operators;
michael@0 2565 }
michael@0 2566 PostScriptEvaluator.prototype = {
michael@0 2567 execute: function PostScriptEvaluator_execute(initialStack) {
michael@0 2568 var stack = new PostScriptStack(initialStack);
michael@0 2569 var counter = 0;
michael@0 2570 var operators = this.operators;
michael@0 2571 var length = operators.length;
michael@0 2572 var operator, a, b;
michael@0 2573 while (counter < length) {
michael@0 2574 operator = operators[counter++];
michael@0 2575 if (typeof operator == 'number') {
michael@0 2576 // Operator is really an operand and should be pushed to the stack.
michael@0 2577 stack.push(operator);
michael@0 2578 continue;
michael@0 2579 }
michael@0 2580 switch (operator) {
michael@0 2581 // non standard ps operators
michael@0 2582 case 'jz': // jump if false
michael@0 2583 b = stack.pop();
michael@0 2584 a = stack.pop();
michael@0 2585 if (!a) {
michael@0 2586 counter = b;
michael@0 2587 }
michael@0 2588 break;
michael@0 2589 case 'j': // jump
michael@0 2590 a = stack.pop();
michael@0 2591 counter = a;
michael@0 2592 break;
michael@0 2593
michael@0 2594 // all ps operators in alphabetical order (excluding if/ifelse)
michael@0 2595 case 'abs':
michael@0 2596 a = stack.pop();
michael@0 2597 stack.push(Math.abs(a));
michael@0 2598 break;
michael@0 2599 case 'add':
michael@0 2600 b = stack.pop();
michael@0 2601 a = stack.pop();
michael@0 2602 stack.push(a + b);
michael@0 2603 break;
michael@0 2604 case 'and':
michael@0 2605 b = stack.pop();
michael@0 2606 a = stack.pop();
michael@0 2607 if (isBool(a) && isBool(b)) {
michael@0 2608 stack.push(a && b);
michael@0 2609 } else {
michael@0 2610 stack.push(a & b);
michael@0 2611 }
michael@0 2612 break;
michael@0 2613 case 'atan':
michael@0 2614 a = stack.pop();
michael@0 2615 stack.push(Math.atan(a));
michael@0 2616 break;
michael@0 2617 case 'bitshift':
michael@0 2618 b = stack.pop();
michael@0 2619 a = stack.pop();
michael@0 2620 if (a > 0) {
michael@0 2621 stack.push(a << b);
michael@0 2622 } else {
michael@0 2623 stack.push(a >> b);
michael@0 2624 }
michael@0 2625 break;
michael@0 2626 case 'ceiling':
michael@0 2627 a = stack.pop();
michael@0 2628 stack.push(Math.ceil(a));
michael@0 2629 break;
michael@0 2630 case 'copy':
michael@0 2631 a = stack.pop();
michael@0 2632 stack.copy(a);
michael@0 2633 break;
michael@0 2634 case 'cos':
michael@0 2635 a = stack.pop();
michael@0 2636 stack.push(Math.cos(a));
michael@0 2637 break;
michael@0 2638 case 'cvi':
michael@0 2639 a = stack.pop() | 0;
michael@0 2640 stack.push(a);
michael@0 2641 break;
michael@0 2642 case 'cvr':
michael@0 2643 // noop
michael@0 2644 break;
michael@0 2645 case 'div':
michael@0 2646 b = stack.pop();
michael@0 2647 a = stack.pop();
michael@0 2648 stack.push(a / b);
michael@0 2649 break;
michael@0 2650 case 'dup':
michael@0 2651 stack.copy(1);
michael@0 2652 break;
michael@0 2653 case 'eq':
michael@0 2654 b = stack.pop();
michael@0 2655 a = stack.pop();
michael@0 2656 stack.push(a == b);
michael@0 2657 break;
michael@0 2658 case 'exch':
michael@0 2659 stack.roll(2, 1);
michael@0 2660 break;
michael@0 2661 case 'exp':
michael@0 2662 b = stack.pop();
michael@0 2663 a = stack.pop();
michael@0 2664 stack.push(Math.pow(a, b));
michael@0 2665 break;
michael@0 2666 case 'false':
michael@0 2667 stack.push(false);
michael@0 2668 break;
michael@0 2669 case 'floor':
michael@0 2670 a = stack.pop();
michael@0 2671 stack.push(Math.floor(a));
michael@0 2672 break;
michael@0 2673 case 'ge':
michael@0 2674 b = stack.pop();
michael@0 2675 a = stack.pop();
michael@0 2676 stack.push(a >= b);
michael@0 2677 break;
michael@0 2678 case 'gt':
michael@0 2679 b = stack.pop();
michael@0 2680 a = stack.pop();
michael@0 2681 stack.push(a > b);
michael@0 2682 break;
michael@0 2683 case 'idiv':
michael@0 2684 b = stack.pop();
michael@0 2685 a = stack.pop();
michael@0 2686 stack.push((a / b) | 0);
michael@0 2687 break;
michael@0 2688 case 'index':
michael@0 2689 a = stack.pop();
michael@0 2690 stack.index(a);
michael@0 2691 break;
michael@0 2692 case 'le':
michael@0 2693 b = stack.pop();
michael@0 2694 a = stack.pop();
michael@0 2695 stack.push(a <= b);
michael@0 2696 break;
michael@0 2697 case 'ln':
michael@0 2698 a = stack.pop();
michael@0 2699 stack.push(Math.log(a));
michael@0 2700 break;
michael@0 2701 case 'log':
michael@0 2702 a = stack.pop();
michael@0 2703 stack.push(Math.log(a) / Math.LN10);
michael@0 2704 break;
michael@0 2705 case 'lt':
michael@0 2706 b = stack.pop();
michael@0 2707 a = stack.pop();
michael@0 2708 stack.push(a < b);
michael@0 2709 break;
michael@0 2710 case 'mod':
michael@0 2711 b = stack.pop();
michael@0 2712 a = stack.pop();
michael@0 2713 stack.push(a % b);
michael@0 2714 break;
michael@0 2715 case 'mul':
michael@0 2716 b = stack.pop();
michael@0 2717 a = stack.pop();
michael@0 2718 stack.push(a * b);
michael@0 2719 break;
michael@0 2720 case 'ne':
michael@0 2721 b = stack.pop();
michael@0 2722 a = stack.pop();
michael@0 2723 stack.push(a != b);
michael@0 2724 break;
michael@0 2725 case 'neg':
michael@0 2726 a = stack.pop();
michael@0 2727 stack.push(-b);
michael@0 2728 break;
michael@0 2729 case 'not':
michael@0 2730 a = stack.pop();
michael@0 2731 if (isBool(a) && isBool(b)) {
michael@0 2732 stack.push(a && b);
michael@0 2733 } else {
michael@0 2734 stack.push(a & b);
michael@0 2735 }
michael@0 2736 break;
michael@0 2737 case 'or':
michael@0 2738 b = stack.pop();
michael@0 2739 a = stack.pop();
michael@0 2740 if (isBool(a) && isBool(b)) {
michael@0 2741 stack.push(a || b);
michael@0 2742 } else {
michael@0 2743 stack.push(a | b);
michael@0 2744 }
michael@0 2745 break;
michael@0 2746 case 'pop':
michael@0 2747 stack.pop();
michael@0 2748 break;
michael@0 2749 case 'roll':
michael@0 2750 b = stack.pop();
michael@0 2751 a = stack.pop();
michael@0 2752 stack.roll(a, b);
michael@0 2753 break;
michael@0 2754 case 'round':
michael@0 2755 a = stack.pop();
michael@0 2756 stack.push(Math.round(a));
michael@0 2757 break;
michael@0 2758 case 'sin':
michael@0 2759 a = stack.pop();
michael@0 2760 stack.push(Math.sin(a));
michael@0 2761 break;
michael@0 2762 case 'sqrt':
michael@0 2763 a = stack.pop();
michael@0 2764 stack.push(Math.sqrt(a));
michael@0 2765 break;
michael@0 2766 case 'sub':
michael@0 2767 b = stack.pop();
michael@0 2768 a = stack.pop();
michael@0 2769 stack.push(a - b);
michael@0 2770 break;
michael@0 2771 case 'true':
michael@0 2772 stack.push(true);
michael@0 2773 break;
michael@0 2774 case 'truncate':
michael@0 2775 a = stack.pop();
michael@0 2776 a = a < 0 ? Math.ceil(a) : Math.floor(a);
michael@0 2777 stack.push(a);
michael@0 2778 break;
michael@0 2779 case 'xor':
michael@0 2780 b = stack.pop();
michael@0 2781 a = stack.pop();
michael@0 2782 if (isBool(a) && isBool(b)) {
michael@0 2783 stack.push(a != b);
michael@0 2784 } else {
michael@0 2785 stack.push(a ^ b);
michael@0 2786 }
michael@0 2787 break;
michael@0 2788 default:
michael@0 2789 error('Unknown operator ' + operator);
michael@0 2790 break;
michael@0 2791 }
michael@0 2792 }
michael@0 2793 return stack.stack;
michael@0 2794 }
michael@0 2795 };
michael@0 2796 return PostScriptEvaluator;
michael@0 2797 })();
michael@0 2798
michael@0 2799
michael@0 2800 var HIGHLIGHT_OFFSET = 4; // px
michael@0 2801 var SUPPORTED_TYPES = ['Link', 'Text', 'Widget'];
michael@0 2802
michael@0 2803 var Annotation = (function AnnotationClosure() {
michael@0 2804 // 12.5.5: Algorithm: Appearance streams
michael@0 2805 function getTransformMatrix(rect, bbox, matrix) {
michael@0 2806 var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix);
michael@0 2807 var minX = bounds[0];
michael@0 2808 var minY = bounds[1];
michael@0 2809 var maxX = bounds[2];
michael@0 2810 var maxY = bounds[3];
michael@0 2811
michael@0 2812 if (minX === maxX || minY === maxY) {
michael@0 2813 // From real-life file, bbox was [0, 0, 0, 0]. In this case,
michael@0 2814 // just apply the transform for rect
michael@0 2815 return [1, 0, 0, 1, rect[0], rect[1]];
michael@0 2816 }
michael@0 2817
michael@0 2818 var xRatio = (rect[2] - rect[0]) / (maxX - minX);
michael@0 2819 var yRatio = (rect[3] - rect[1]) / (maxY - minY);
michael@0 2820 return [
michael@0 2821 xRatio,
michael@0 2822 0,
michael@0 2823 0,
michael@0 2824 yRatio,
michael@0 2825 rect[0] - minX * xRatio,
michael@0 2826 rect[1] - minY * yRatio
michael@0 2827 ];
michael@0 2828 }
michael@0 2829
michael@0 2830 function getDefaultAppearance(dict) {
michael@0 2831 var appearanceState = dict.get('AP');
michael@0 2832 if (!isDict(appearanceState)) {
michael@0 2833 return;
michael@0 2834 }
michael@0 2835
michael@0 2836 var appearance;
michael@0 2837 var appearances = appearanceState.get('N');
michael@0 2838 if (isDict(appearances)) {
michael@0 2839 var as = dict.get('AS');
michael@0 2840 if (as && appearances.has(as.name)) {
michael@0 2841 appearance = appearances.get(as.name);
michael@0 2842 }
michael@0 2843 } else {
michael@0 2844 appearance = appearances;
michael@0 2845 }
michael@0 2846 return appearance;
michael@0 2847 }
michael@0 2848
michael@0 2849 function Annotation(params) {
michael@0 2850 if (params.data) {
michael@0 2851 this.data = params.data;
michael@0 2852 return;
michael@0 2853 }
michael@0 2854
michael@0 2855 var dict = params.dict;
michael@0 2856 var data = this.data = {};
michael@0 2857
michael@0 2858 data.subtype = dict.get('Subtype').name;
michael@0 2859 var rect = dict.get('Rect') || [0, 0, 0, 0];
michael@0 2860 data.rect = Util.normalizeRect(rect);
michael@0 2861 data.annotationFlags = dict.get('F');
michael@0 2862
michael@0 2863 var color = dict.get('C');
michael@0 2864 if (isArray(color) && color.length === 3) {
michael@0 2865 // TODO(mack): currently only supporting rgb; need support different
michael@0 2866 // colorspaces
michael@0 2867 data.color = color;
michael@0 2868 } else {
michael@0 2869 data.color = [0, 0, 0];
michael@0 2870 }
michael@0 2871
michael@0 2872 // Some types of annotations have border style dict which has more
michael@0 2873 // info than the border array
michael@0 2874 if (dict.has('BS')) {
michael@0 2875 var borderStyle = dict.get('BS');
michael@0 2876 data.borderWidth = borderStyle.has('W') ? borderStyle.get('W') : 1;
michael@0 2877 } else {
michael@0 2878 var borderArray = dict.get('Border') || [0, 0, 1];
michael@0 2879 data.borderWidth = borderArray[2] || 0;
michael@0 2880
michael@0 2881 // TODO: implement proper support for annotations with line dash patterns.
michael@0 2882 var dashArray = borderArray[3];
michael@0 2883 if (data.borderWidth > 0 && dashArray && isArray(dashArray)) {
michael@0 2884 var dashArrayLength = dashArray.length;
michael@0 2885 if (dashArrayLength > 0) {
michael@0 2886 // According to the PDF specification: the elements in a dashArray
michael@0 2887 // shall be numbers that are nonnegative and not all equal to zero.
michael@0 2888 var isInvalid = false;
michael@0 2889 var numPositive = 0;
michael@0 2890 for (var i = 0; i < dashArrayLength; i++) {
michael@0 2891 var validNumber = (+dashArray[i] >= 0);
michael@0 2892 if (!validNumber) {
michael@0 2893 isInvalid = true;
michael@0 2894 break;
michael@0 2895 } else if (dashArray[i] > 0) {
michael@0 2896 numPositive++;
michael@0 2897 }
michael@0 2898 }
michael@0 2899 if (isInvalid || numPositive === 0) {
michael@0 2900 data.borderWidth = 0;
michael@0 2901 }
michael@0 2902 }
michael@0 2903 }
michael@0 2904 }
michael@0 2905
michael@0 2906 this.appearance = getDefaultAppearance(dict);
michael@0 2907 data.hasAppearance = !!this.appearance;
michael@0 2908 data.id = params.ref.num;
michael@0 2909 }
michael@0 2910
michael@0 2911 Annotation.prototype = {
michael@0 2912
michael@0 2913 getData: function Annotation_getData() {
michael@0 2914 return this.data;
michael@0 2915 },
michael@0 2916
michael@0 2917 hasHtml: function Annotation_hasHtml() {
michael@0 2918 return false;
michael@0 2919 },
michael@0 2920
michael@0 2921 getHtmlElement: function Annotation_getHtmlElement(commonObjs) {
michael@0 2922 throw new NotImplementedException(
michael@0 2923 'getHtmlElement() should be implemented in subclass');
michael@0 2924 },
michael@0 2925
michael@0 2926 // TODO(mack): Remove this, it's not really that helpful.
michael@0 2927 getEmptyContainer: function Annotation_getEmptyContainer(tagName, rect,
michael@0 2928 borderWidth) {
michael@0 2929 assert(!isWorker,
michael@0 2930 'getEmptyContainer() should be called from main thread');
michael@0 2931
michael@0 2932 var bWidth = borderWidth || 0;
michael@0 2933
michael@0 2934 rect = rect || this.data.rect;
michael@0 2935 var element = document.createElement(tagName);
michael@0 2936 element.style.borderWidth = bWidth + 'px';
michael@0 2937 var width = rect[2] - rect[0] - 2 * bWidth;
michael@0 2938 var height = rect[3] - rect[1] - 2 * bWidth;
michael@0 2939 element.style.width = width + 'px';
michael@0 2940 element.style.height = height + 'px';
michael@0 2941 return element;
michael@0 2942 },
michael@0 2943
michael@0 2944 isInvisible: function Annotation_isInvisible() {
michael@0 2945 var data = this.data;
michael@0 2946 if (data && SUPPORTED_TYPES.indexOf(data.subtype) !== -1) {
michael@0 2947 return false;
michael@0 2948 } else {
michael@0 2949 return !!(data &&
michael@0 2950 data.annotationFlags && // Default: not invisible
michael@0 2951 data.annotationFlags & 0x1); // Invisible
michael@0 2952 }
michael@0 2953 },
michael@0 2954
michael@0 2955 isViewable: function Annotation_isViewable() {
michael@0 2956 var data = this.data;
michael@0 2957 return !!(!this.isInvisible() &&
michael@0 2958 data &&
michael@0 2959 (!data.annotationFlags ||
michael@0 2960 !(data.annotationFlags & 0x22)) && // Hidden or NoView
michael@0 2961 data.rect); // rectangle is nessessary
michael@0 2962 },
michael@0 2963
michael@0 2964 isPrintable: function Annotation_isPrintable() {
michael@0 2965 var data = this.data;
michael@0 2966 return !!(!this.isInvisible() &&
michael@0 2967 data &&
michael@0 2968 data.annotationFlags && // Default: not printable
michael@0 2969 data.annotationFlags & 0x4 && // Print
michael@0 2970 data.rect); // rectangle is nessessary
michael@0 2971 },
michael@0 2972
michael@0 2973 loadResources: function(keys) {
michael@0 2974 var promise = new LegacyPromise();
michael@0 2975 this.appearance.dict.getAsync('Resources').then(function(resources) {
michael@0 2976 if (!resources) {
michael@0 2977 promise.resolve();
michael@0 2978 return;
michael@0 2979 }
michael@0 2980 var objectLoader = new ObjectLoader(resources.map,
michael@0 2981 keys,
michael@0 2982 resources.xref);
michael@0 2983 objectLoader.load().then(function() {
michael@0 2984 promise.resolve(resources);
michael@0 2985 });
michael@0 2986 }.bind(this));
michael@0 2987
michael@0 2988 return promise;
michael@0 2989 },
michael@0 2990
michael@0 2991 getOperatorList: function Annotation_getOperatorList(evaluator) {
michael@0 2992
michael@0 2993 var promise = new LegacyPromise();
michael@0 2994
michael@0 2995 if (!this.appearance) {
michael@0 2996 promise.resolve(new OperatorList());
michael@0 2997 return promise;
michael@0 2998 }
michael@0 2999
michael@0 3000 var data = this.data;
michael@0 3001
michael@0 3002 var appearanceDict = this.appearance.dict;
michael@0 3003 var resourcesPromise = this.loadResources([
michael@0 3004 'ExtGState',
michael@0 3005 'ColorSpace',
michael@0 3006 'Pattern',
michael@0 3007 'Shading',
michael@0 3008 'XObject',
michael@0 3009 'Font'
michael@0 3010 // ProcSet
michael@0 3011 // Properties
michael@0 3012 ]);
michael@0 3013 var bbox = appearanceDict.get('BBox') || [0, 0, 1, 1];
michael@0 3014 var matrix = appearanceDict.get('Matrix') || [1, 0, 0, 1, 0 ,0];
michael@0 3015 var transform = getTransformMatrix(data.rect, bbox, matrix);
michael@0 3016
michael@0 3017 resourcesPromise.then(function(resources) {
michael@0 3018 var opList = new OperatorList();
michael@0 3019 opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
michael@0 3020 evaluator.getOperatorList(this.appearance, resources, opList);
michael@0 3021 opList.addOp(OPS.endAnnotation, []);
michael@0 3022 promise.resolve(opList);
michael@0 3023
michael@0 3024 this.appearance.reset();
michael@0 3025 }.bind(this));
michael@0 3026
michael@0 3027 return promise;
michael@0 3028 }
michael@0 3029 };
michael@0 3030
michael@0 3031 Annotation.getConstructor =
michael@0 3032 function Annotation_getConstructor(subtype, fieldType) {
michael@0 3033
michael@0 3034 if (!subtype) {
michael@0 3035 return;
michael@0 3036 }
michael@0 3037
michael@0 3038 // TODO(mack): Implement FreeText annotations
michael@0 3039 if (subtype === 'Link') {
michael@0 3040 return LinkAnnotation;
michael@0 3041 } else if (subtype === 'Text') {
michael@0 3042 return TextAnnotation;
michael@0 3043 } else if (subtype === 'Widget') {
michael@0 3044 if (!fieldType) {
michael@0 3045 return;
michael@0 3046 }
michael@0 3047
michael@0 3048 if (fieldType === 'Tx') {
michael@0 3049 return TextWidgetAnnotation;
michael@0 3050 } else {
michael@0 3051 return WidgetAnnotation;
michael@0 3052 }
michael@0 3053 } else {
michael@0 3054 return Annotation;
michael@0 3055 }
michael@0 3056 };
michael@0 3057
michael@0 3058 // TODO(mack): Support loading annotation from data
michael@0 3059 Annotation.fromData = function Annotation_fromData(data) {
michael@0 3060 var subtype = data.subtype;
michael@0 3061 var fieldType = data.fieldType;
michael@0 3062 var Constructor = Annotation.getConstructor(subtype, fieldType);
michael@0 3063 if (Constructor) {
michael@0 3064 return new Constructor({ data: data });
michael@0 3065 }
michael@0 3066 };
michael@0 3067
michael@0 3068 Annotation.fromRef = function Annotation_fromRef(xref, ref) {
michael@0 3069
michael@0 3070 var dict = xref.fetchIfRef(ref);
michael@0 3071 if (!isDict(dict)) {
michael@0 3072 return;
michael@0 3073 }
michael@0 3074
michael@0 3075 var subtype = dict.get('Subtype');
michael@0 3076 subtype = isName(subtype) ? subtype.name : '';
michael@0 3077 if (!subtype) {
michael@0 3078 return;
michael@0 3079 }
michael@0 3080
michael@0 3081 var fieldType = Util.getInheritableProperty(dict, 'FT');
michael@0 3082 fieldType = isName(fieldType) ? fieldType.name : '';
michael@0 3083
michael@0 3084 var Constructor = Annotation.getConstructor(subtype, fieldType);
michael@0 3085 if (!Constructor) {
michael@0 3086 return;
michael@0 3087 }
michael@0 3088
michael@0 3089 var params = {
michael@0 3090 dict: dict,
michael@0 3091 ref: ref,
michael@0 3092 };
michael@0 3093
michael@0 3094 var annotation = new Constructor(params);
michael@0 3095
michael@0 3096 if (annotation.isViewable() || annotation.isPrintable()) {
michael@0 3097 return annotation;
michael@0 3098 } else {
michael@0 3099 warn('unimplemented annotation type: ' + subtype);
michael@0 3100 }
michael@0 3101 };
michael@0 3102
michael@0 3103 Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
michael@0 3104 annotations, opList, pdfManager, partialEvaluator, intent) {
michael@0 3105
michael@0 3106 function reject(e) {
michael@0 3107 annotationsReadyPromise.reject(e);
michael@0 3108 }
michael@0 3109
michael@0 3110 var annotationsReadyPromise = new LegacyPromise();
michael@0 3111
michael@0 3112 var annotationPromises = [];
michael@0 3113 for (var i = 0, n = annotations.length; i < n; ++i) {
michael@0 3114 if (intent === 'display' && annotations[i].isViewable() ||
michael@0 3115 intent === 'print' && annotations[i].isPrintable()) {
michael@0 3116 annotationPromises.push(
michael@0 3117 annotations[i].getOperatorList(partialEvaluator));
michael@0 3118 }
michael@0 3119 }
michael@0 3120 Promise.all(annotationPromises).then(function(datas) {
michael@0 3121 opList.addOp(OPS.beginAnnotations, []);
michael@0 3122 for (var i = 0, n = datas.length; i < n; ++i) {
michael@0 3123 var annotOpList = datas[i];
michael@0 3124 opList.addOpList(annotOpList);
michael@0 3125 }
michael@0 3126 opList.addOp(OPS.endAnnotations, []);
michael@0 3127 annotationsReadyPromise.resolve();
michael@0 3128 }, reject);
michael@0 3129
michael@0 3130 return annotationsReadyPromise;
michael@0 3131 };
michael@0 3132
michael@0 3133 return Annotation;
michael@0 3134 })();
michael@0 3135 PDFJS.Annotation = Annotation;
michael@0 3136
michael@0 3137
michael@0 3138 var WidgetAnnotation = (function WidgetAnnotationClosure() {
michael@0 3139
michael@0 3140 function WidgetAnnotation(params) {
michael@0 3141 Annotation.call(this, params);
michael@0 3142
michael@0 3143 if (params.data) {
michael@0 3144 return;
michael@0 3145 }
michael@0 3146
michael@0 3147 var dict = params.dict;
michael@0 3148 var data = this.data;
michael@0 3149
michael@0 3150 data.fieldValue = stringToPDFString(
michael@0 3151 Util.getInheritableProperty(dict, 'V') || '');
michael@0 3152 data.alternativeText = stringToPDFString(dict.get('TU') || '');
michael@0 3153 data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || '';
michael@0 3154 var fieldType = Util.getInheritableProperty(dict, 'FT');
michael@0 3155 data.fieldType = isName(fieldType) ? fieldType.name : '';
michael@0 3156 data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0;
michael@0 3157 this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty;
michael@0 3158
michael@0 3159 // Building the full field name by collecting the field and
michael@0 3160 // its ancestors 'T' data and joining them using '.'.
michael@0 3161 var fieldName = [];
michael@0 3162 var namedItem = dict;
michael@0 3163 var ref = params.ref;
michael@0 3164 while (namedItem) {
michael@0 3165 var parent = namedItem.get('Parent');
michael@0 3166 var parentRef = namedItem.getRaw('Parent');
michael@0 3167 var name = namedItem.get('T');
michael@0 3168 if (name) {
michael@0 3169 fieldName.unshift(stringToPDFString(name));
michael@0 3170 } else {
michael@0 3171 // The field name is absent, that means more than one field
michael@0 3172 // with the same name may exist. Replacing the empty name
michael@0 3173 // with the '`' plus index in the parent's 'Kids' array.
michael@0 3174 // This is not in the PDF spec but necessary to id the
michael@0 3175 // the input controls.
michael@0 3176 var kids = parent.get('Kids');
michael@0 3177 var j, jj;
michael@0 3178 for (j = 0, jj = kids.length; j < jj; j++) {
michael@0 3179 var kidRef = kids[j];
michael@0 3180 if (kidRef.num == ref.num && kidRef.gen == ref.gen) {
michael@0 3181 break;
michael@0 3182 }
michael@0 3183 }
michael@0 3184 fieldName.unshift('`' + j);
michael@0 3185 }
michael@0 3186 namedItem = parent;
michael@0 3187 ref = parentRef;
michael@0 3188 }
michael@0 3189 data.fullName = fieldName.join('.');
michael@0 3190 }
michael@0 3191
michael@0 3192 var parent = Annotation.prototype;
michael@0 3193 Util.inherit(WidgetAnnotation, Annotation, {
michael@0 3194 isViewable: function WidgetAnnotation_isViewable() {
michael@0 3195 if (this.data.fieldType === 'Sig') {
michael@0 3196 warn('unimplemented annotation type: Widget signature');
michael@0 3197 return false;
michael@0 3198 }
michael@0 3199
michael@0 3200 return parent.isViewable.call(this);
michael@0 3201 }
michael@0 3202 });
michael@0 3203
michael@0 3204 return WidgetAnnotation;
michael@0 3205 })();
michael@0 3206
michael@0 3207 var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
michael@0 3208 function TextWidgetAnnotation(params) {
michael@0 3209 WidgetAnnotation.call(this, params);
michael@0 3210
michael@0 3211 if (params.data) {
michael@0 3212 return;
michael@0 3213 }
michael@0 3214
michael@0 3215 this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q');
michael@0 3216 }
michael@0 3217
michael@0 3218 // TODO(mack): This dupes some of the logic in CanvasGraphics.setFont()
michael@0 3219 function setTextStyles(element, item, fontObj) {
michael@0 3220
michael@0 3221 var style = element.style;
michael@0 3222 style.fontSize = item.fontSize + 'px';
michael@0 3223 style.direction = item.fontDirection < 0 ? 'rtl': 'ltr';
michael@0 3224
michael@0 3225 if (!fontObj) {
michael@0 3226 return;
michael@0 3227 }
michael@0 3228
michael@0 3229 style.fontWeight = fontObj.black ?
michael@0 3230 (fontObj.bold ? 'bolder' : 'bold') :
michael@0 3231 (fontObj.bold ? 'bold' : 'normal');
michael@0 3232 style.fontStyle = fontObj.italic ? 'italic' : 'normal';
michael@0 3233
michael@0 3234 var fontName = fontObj.loadedName;
michael@0 3235 var fontFamily = fontName ? '"' + fontName + '", ' : '';
michael@0 3236 // Use a reasonable default font if the font doesn't specify a fallback
michael@0 3237 var fallbackName = fontObj.fallbackName || 'Helvetica, sans-serif';
michael@0 3238 style.fontFamily = fontFamily + fallbackName;
michael@0 3239 }
michael@0 3240
michael@0 3241
michael@0 3242 Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
michael@0 3243 hasHtml: function TextWidgetAnnotation_hasHtml() {
michael@0 3244 return !this.data.hasAppearance && !!this.data.fieldValue;
michael@0 3245 },
michael@0 3246
michael@0 3247 getHtmlElement: function TextWidgetAnnotation_getHtmlElement(commonObjs) {
michael@0 3248 assert(!isWorker, 'getHtmlElement() shall be called from main thread');
michael@0 3249
michael@0 3250 var item = this.data;
michael@0 3251
michael@0 3252 var element = this.getEmptyContainer('div');
michael@0 3253 element.style.display = 'table';
michael@0 3254
michael@0 3255 var content = document.createElement('div');
michael@0 3256 content.textContent = item.fieldValue;
michael@0 3257 var textAlignment = item.textAlignment;
michael@0 3258 content.style.textAlign = ['left', 'center', 'right'][textAlignment];
michael@0 3259 content.style.verticalAlign = 'middle';
michael@0 3260 content.style.display = 'table-cell';
michael@0 3261
michael@0 3262 var fontObj = item.fontRefName ?
michael@0 3263 commonObjs.getData(item.fontRefName) : null;
michael@0 3264 setTextStyles(content, item, fontObj);
michael@0 3265
michael@0 3266 element.appendChild(content);
michael@0 3267
michael@0 3268 return element;
michael@0 3269 },
michael@0 3270
michael@0 3271 getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
michael@0 3272 if (this.appearance) {
michael@0 3273 return Annotation.prototype.getOperatorList.call(this, evaluator);
michael@0 3274 }
michael@0 3275
michael@0 3276 var promise = new LegacyPromise();
michael@0 3277 var opList = new OperatorList();
michael@0 3278 var data = this.data;
michael@0 3279
michael@0 3280 // Even if there is an appearance stream, ignore it. This is the
michael@0 3281 // behaviour used by Adobe Reader.
michael@0 3282
michael@0 3283 var defaultAppearance = data.defaultAppearance;
michael@0 3284 if (!defaultAppearance) {
michael@0 3285 promise.resolve(opList);
michael@0 3286 return promise;
michael@0 3287 }
michael@0 3288
michael@0 3289 // Include any font resources found in the default appearance
michael@0 3290
michael@0 3291 var stream = new Stream(stringToBytes(defaultAppearance));
michael@0 3292 evaluator.getOperatorList(stream, this.fieldResources, opList);
michael@0 3293 var appearanceFnArray = opList.fnArray;
michael@0 3294 var appearanceArgsArray = opList.argsArray;
michael@0 3295 var fnArray = [];
michael@0 3296
michael@0 3297 // TODO(mack): Add support for stroke color
michael@0 3298 data.rgb = [0, 0, 0];
michael@0 3299 // TODO THIS DOESN'T MAKE ANY SENSE SINCE THE fnArray IS EMPTY!
michael@0 3300 for (var i = 0, n = fnArray.length; i < n; ++i) {
michael@0 3301 var fnId = appearanceFnArray[i];
michael@0 3302 var args = appearanceArgsArray[i];
michael@0 3303
michael@0 3304 if (fnId === OPS.setFont) {
michael@0 3305 data.fontRefName = args[0];
michael@0 3306 var size = args[1];
michael@0 3307 if (size < 0) {
michael@0 3308 data.fontDirection = -1;
michael@0 3309 data.fontSize = -size;
michael@0 3310 } else {
michael@0 3311 data.fontDirection = 1;
michael@0 3312 data.fontSize = size;
michael@0 3313 }
michael@0 3314 } else if (fnId === OPS.setFillRGBColor) {
michael@0 3315 data.rgb = args;
michael@0 3316 } else if (fnId === OPS.setFillGray) {
michael@0 3317 var rgbValue = args[0] * 255;
michael@0 3318 data.rgb = [rgbValue, rgbValue, rgbValue];
michael@0 3319 }
michael@0 3320 }
michael@0 3321 promise.resolve(opList);
michael@0 3322 return promise;
michael@0 3323 }
michael@0 3324 });
michael@0 3325
michael@0 3326 return TextWidgetAnnotation;
michael@0 3327 })();
michael@0 3328
michael@0 3329 var InteractiveAnnotation = (function InteractiveAnnotationClosure() {
michael@0 3330 function InteractiveAnnotation(params) {
michael@0 3331 Annotation.call(this, params);
michael@0 3332 }
michael@0 3333
michael@0 3334 Util.inherit(InteractiveAnnotation, Annotation, {
michael@0 3335 hasHtml: function InteractiveAnnotation_hasHtml() {
michael@0 3336 return true;
michael@0 3337 },
michael@0 3338
michael@0 3339 highlight: function InteractiveAnnotation_highlight() {
michael@0 3340 if (this.highlightElement &&
michael@0 3341 this.highlightElement.hasAttribute('hidden')) {
michael@0 3342 this.highlightElement.removeAttribute('hidden');
michael@0 3343 }
michael@0 3344 },
michael@0 3345
michael@0 3346 unhighlight: function InteractiveAnnotation_unhighlight() {
michael@0 3347 if (this.highlightElement &&
michael@0 3348 !this.highlightElement.hasAttribute('hidden')) {
michael@0 3349 this.highlightElement.setAttribute('hidden', true);
michael@0 3350 }
michael@0 3351 },
michael@0 3352
michael@0 3353 initContainer: function InteractiveAnnotation_initContainer() {
michael@0 3354
michael@0 3355 var item = this.data;
michael@0 3356 var rect = item.rect;
michael@0 3357
michael@0 3358 var container = this.getEmptyContainer('section', rect, item.borderWidth);
michael@0 3359 container.style.backgroundColor = item.color;
michael@0 3360
michael@0 3361 var color = item.color;
michael@0 3362 var rgb = [];
michael@0 3363 for (var i = 0; i < 3; ++i) {
michael@0 3364 rgb[i] = Math.round(color[i] * 255);
michael@0 3365 }
michael@0 3366 item.colorCssRgb = Util.makeCssRgb(rgb);
michael@0 3367
michael@0 3368 var highlight = document.createElement('div');
michael@0 3369 highlight.className = 'annotationHighlight';
michael@0 3370 highlight.style.left = highlight.style.top = -HIGHLIGHT_OFFSET + 'px';
michael@0 3371 highlight.style.right = highlight.style.bottom = -HIGHLIGHT_OFFSET + 'px';
michael@0 3372 highlight.setAttribute('hidden', true);
michael@0 3373
michael@0 3374 this.highlightElement = highlight;
michael@0 3375 container.appendChild(this.highlightElement);
michael@0 3376
michael@0 3377 return container;
michael@0 3378 }
michael@0 3379 });
michael@0 3380
michael@0 3381 return InteractiveAnnotation;
michael@0 3382 })();
michael@0 3383
michael@0 3384 var TextAnnotation = (function TextAnnotationClosure() {
michael@0 3385 function TextAnnotation(params) {
michael@0 3386 InteractiveAnnotation.call(this, params);
michael@0 3387
michael@0 3388 if (params.data) {
michael@0 3389 return;
michael@0 3390 }
michael@0 3391
michael@0 3392 var dict = params.dict;
michael@0 3393 var data = this.data;
michael@0 3394
michael@0 3395 var content = dict.get('Contents');
michael@0 3396 var title = dict.get('T');
michael@0 3397 data.content = stringToPDFString(content || '');
michael@0 3398 data.title = stringToPDFString(title || '');
michael@0 3399
michael@0 3400 if (data.hasAppearance) {
michael@0 3401 data.name = 'NoIcon';
michael@0 3402 } else {
michael@0 3403 data.name = dict.has('Name') ? dict.get('Name').name : 'Note';
michael@0 3404 }
michael@0 3405
michael@0 3406 if (dict.has('C')) {
michael@0 3407 data.hasBgColor = true;
michael@0 3408 }
michael@0 3409 }
michael@0 3410
michael@0 3411 var ANNOT_MIN_SIZE = 10;
michael@0 3412
michael@0 3413 Util.inherit(TextAnnotation, InteractiveAnnotation, {
michael@0 3414
michael@0 3415 getHtmlElement: function TextAnnotation_getHtmlElement(commonObjs) {
michael@0 3416 assert(!isWorker, 'getHtmlElement() shall be called from main thread');
michael@0 3417
michael@0 3418 var item = this.data;
michael@0 3419 var rect = item.rect;
michael@0 3420
michael@0 3421 // sanity check because of OOo-generated PDFs
michael@0 3422 if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) {
michael@0 3423 rect[3] = rect[1] + ANNOT_MIN_SIZE;
michael@0 3424 }
michael@0 3425 if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) {
michael@0 3426 rect[2] = rect[0] + (rect[3] - rect[1]); // make it square
michael@0 3427 }
michael@0 3428
michael@0 3429 var container = this.initContainer();
michael@0 3430 container.className = 'annotText';
michael@0 3431
michael@0 3432 var image = document.createElement('img');
michael@0 3433 image.style.height = container.style.height;
michael@0 3434 image.style.width = container.style.width;
michael@0 3435 var iconName = item.name;
michael@0 3436 image.src = PDFJS.imageResourcesPath + 'annotation-' +
michael@0 3437 iconName.toLowerCase() + '.svg';
michael@0 3438 image.alt = '[{{type}} Annotation]';
michael@0 3439 image.dataset.l10nId = 'text_annotation_type';
michael@0 3440 image.dataset.l10nArgs = JSON.stringify({type: iconName});
michael@0 3441
michael@0 3442 var contentWrapper = document.createElement('div');
michael@0 3443 contentWrapper.className = 'annotTextContentWrapper';
michael@0 3444 contentWrapper.style.left = Math.floor(rect[2] - rect[0] + 5) + 'px';
michael@0 3445 contentWrapper.style.top = '-10px';
michael@0 3446
michael@0 3447 var content = document.createElement('div');
michael@0 3448 content.className = 'annotTextContent';
michael@0 3449 content.setAttribute('hidden', true);
michael@0 3450
michael@0 3451 var i, ii;
michael@0 3452 if (item.hasBgColor) {
michael@0 3453 var color = item.color;
michael@0 3454 var rgb = [];
michael@0 3455 for (i = 0; i < 3; ++i) {
michael@0 3456 // Enlighten the color (70%)
michael@0 3457 var c = Math.round(color[i] * 255);
michael@0 3458 rgb[i] = Math.round((255 - c) * 0.7) + c;
michael@0 3459 }
michael@0 3460 content.style.backgroundColor = Util.makeCssRgb(rgb);
michael@0 3461 }
michael@0 3462
michael@0 3463 var title = document.createElement('h1');
michael@0 3464 var text = document.createElement('p');
michael@0 3465 title.textContent = item.title;
michael@0 3466
michael@0 3467 if (!item.content && !item.title) {
michael@0 3468 content.setAttribute('hidden', true);
michael@0 3469 } else {
michael@0 3470 var e = document.createElement('span');
michael@0 3471 var lines = item.content.split(/(?:\r\n?|\n)/);
michael@0 3472 for (i = 0, ii = lines.length; i < ii; ++i) {
michael@0 3473 var line = lines[i];
michael@0 3474 e.appendChild(document.createTextNode(line));
michael@0 3475 if (i < (ii - 1)) {
michael@0 3476 e.appendChild(document.createElement('br'));
michael@0 3477 }
michael@0 3478 }
michael@0 3479 text.appendChild(e);
michael@0 3480
michael@0 3481 var pinned = false;
michael@0 3482
michael@0 3483 var showAnnotation = function showAnnotation(pin) {
michael@0 3484 if (pin) {
michael@0 3485 pinned = true;
michael@0 3486 }
michael@0 3487 if (content.hasAttribute('hidden')) {
michael@0 3488 container.style.zIndex += 1;
michael@0 3489 content.removeAttribute('hidden');
michael@0 3490 }
michael@0 3491 };
michael@0 3492
michael@0 3493 var hideAnnotation = function hideAnnotation(unpin) {
michael@0 3494 if (unpin) {
michael@0 3495 pinned = false;
michael@0 3496 }
michael@0 3497 if (!content.hasAttribute('hidden') && !pinned) {
michael@0 3498 container.style.zIndex -= 1;
michael@0 3499 content.setAttribute('hidden', true);
michael@0 3500 }
michael@0 3501 };
michael@0 3502
michael@0 3503 var toggleAnnotation = function toggleAnnotation() {
michael@0 3504 if (pinned) {
michael@0 3505 hideAnnotation(true);
michael@0 3506 } else {
michael@0 3507 showAnnotation(true);
michael@0 3508 }
michael@0 3509 };
michael@0 3510
michael@0 3511 image.addEventListener('click', function image_clickHandler() {
michael@0 3512 toggleAnnotation();
michael@0 3513 }, false);
michael@0 3514 image.addEventListener('mouseover', function image_mouseOverHandler() {
michael@0 3515 showAnnotation();
michael@0 3516 }, false);
michael@0 3517 image.addEventListener('mouseout', function image_mouseOutHandler() {
michael@0 3518 hideAnnotation();
michael@0 3519 }, false);
michael@0 3520
michael@0 3521 content.addEventListener('click', function content_clickHandler() {
michael@0 3522 hideAnnotation(true);
michael@0 3523 }, false);
michael@0 3524 }
michael@0 3525
michael@0 3526 content.appendChild(title);
michael@0 3527 content.appendChild(text);
michael@0 3528 contentWrapper.appendChild(content);
michael@0 3529 container.appendChild(image);
michael@0 3530 container.appendChild(contentWrapper);
michael@0 3531
michael@0 3532 return container;
michael@0 3533 }
michael@0 3534 });
michael@0 3535
michael@0 3536 return TextAnnotation;
michael@0 3537 })();
michael@0 3538
michael@0 3539 var LinkAnnotation = (function LinkAnnotationClosure() {
michael@0 3540 function LinkAnnotation(params) {
michael@0 3541 InteractiveAnnotation.call(this, params);
michael@0 3542
michael@0 3543 if (params.data) {
michael@0 3544 return;
michael@0 3545 }
michael@0 3546
michael@0 3547 var dict = params.dict;
michael@0 3548 var data = this.data;
michael@0 3549
michael@0 3550 var action = dict.get('A');
michael@0 3551 if (action) {
michael@0 3552 var linkType = action.get('S').name;
michael@0 3553 if (linkType === 'URI') {
michael@0 3554 var url = action.get('URI');
michael@0 3555 if (isName(url)) {
michael@0 3556 // Some bad PDFs do not put parentheses around relative URLs.
michael@0 3557 url = '/' + url.name;
michael@0 3558 } else if (url) {
michael@0 3559 url = addDefaultProtocolToUrl(url);
michael@0 3560 }
michael@0 3561 // TODO: pdf spec mentions urls can be relative to a Base
michael@0 3562 // entry in the dictionary.
michael@0 3563 if (!isValidUrl(url, false)) {
michael@0 3564 url = '';
michael@0 3565 }
michael@0 3566 data.url = url;
michael@0 3567 } else if (linkType === 'GoTo') {
michael@0 3568 data.dest = action.get('D');
michael@0 3569 } else if (linkType === 'GoToR') {
michael@0 3570 var urlDict = action.get('F');
michael@0 3571 if (isDict(urlDict)) {
michael@0 3572 // We assume that the 'url' is a Filspec dictionary
michael@0 3573 // and fetch the url without checking any further
michael@0 3574 url = urlDict.get('F') || '';
michael@0 3575 }
michael@0 3576
michael@0 3577 // TODO: pdf reference says that GoToR
michael@0 3578 // can also have 'NewWindow' attribute
michael@0 3579 if (!isValidUrl(url, false)) {
michael@0 3580 url = '';
michael@0 3581 }
michael@0 3582 data.url = url;
michael@0 3583 data.dest = action.get('D');
michael@0 3584 } else if (linkType === 'Named') {
michael@0 3585 data.action = action.get('N').name;
michael@0 3586 } else {
michael@0 3587 warn('unrecognized link type: ' + linkType);
michael@0 3588 }
michael@0 3589 } else if (dict.has('Dest')) {
michael@0 3590 // simple destination link
michael@0 3591 var dest = dict.get('Dest');
michael@0 3592 data.dest = isName(dest) ? dest.name : dest;
michael@0 3593 }
michael@0 3594 }
michael@0 3595
michael@0 3596 // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
michael@0 3597 function addDefaultProtocolToUrl(url) {
michael@0 3598 if (url && url.indexOf('www.') === 0) {
michael@0 3599 return ('http://' + url);
michael@0 3600 }
michael@0 3601 return url;
michael@0 3602 }
michael@0 3603
michael@0 3604 Util.inherit(LinkAnnotation, InteractiveAnnotation, {
michael@0 3605 hasOperatorList: function LinkAnnotation_hasOperatorList() {
michael@0 3606 return false;
michael@0 3607 },
michael@0 3608
michael@0 3609 getHtmlElement: function LinkAnnotation_getHtmlElement(commonObjs) {
michael@0 3610
michael@0 3611 var container = this.initContainer();
michael@0 3612 container.className = 'annotLink';
michael@0 3613
michael@0 3614 var item = this.data;
michael@0 3615
michael@0 3616 container.style.borderColor = item.colorCssRgb;
michael@0 3617 container.style.borderStyle = 'solid';
michael@0 3618
michael@0 3619 var link = document.createElement('a');
michael@0 3620 link.href = link.title = this.data.url || '';
michael@0 3621
michael@0 3622 container.appendChild(link);
michael@0 3623
michael@0 3624 return container;
michael@0 3625 }
michael@0 3626 });
michael@0 3627
michael@0 3628 return LinkAnnotation;
michael@0 3629 })();
michael@0 3630
michael@0 3631
michael@0 3632 var ChunkedStream = (function ChunkedStreamClosure() {
michael@0 3633 function ChunkedStream(length, chunkSize, manager) {
michael@0 3634 this.bytes = new Uint8Array(length);
michael@0 3635 this.start = 0;
michael@0 3636 this.pos = 0;
michael@0 3637 this.end = length;
michael@0 3638 this.chunkSize = chunkSize;
michael@0 3639 this.loadedChunks = [];
michael@0 3640 this.numChunksLoaded = 0;
michael@0 3641 this.numChunks = Math.ceil(length / chunkSize);
michael@0 3642 this.manager = manager;
michael@0 3643 this.initialDataLength = 0;
michael@0 3644 }
michael@0 3645
michael@0 3646 // required methods for a stream. if a particular stream does not
michael@0 3647 // implement these, an error should be thrown
michael@0 3648 ChunkedStream.prototype = {
michael@0 3649
michael@0 3650 getMissingChunks: function ChunkedStream_getMissingChunks() {
michael@0 3651 var chunks = [];
michael@0 3652 for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) {
michael@0 3653 if (!(chunk in this.loadedChunks)) {
michael@0 3654 chunks.push(chunk);
michael@0 3655 }
michael@0 3656 }
michael@0 3657 return chunks;
michael@0 3658 },
michael@0 3659
michael@0 3660 getBaseStreams: function ChunkedStream_getBaseStreams() {
michael@0 3661 return [this];
michael@0 3662 },
michael@0 3663
michael@0 3664 allChunksLoaded: function ChunkedStream_allChunksLoaded() {
michael@0 3665 return this.numChunksLoaded === this.numChunks;
michael@0 3666 },
michael@0 3667
michael@0 3668 onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) {
michael@0 3669 var end = begin + chunk.byteLength;
michael@0 3670
michael@0 3671 assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin);
michael@0 3672 // Using this.length is inaccurate here since this.start can be moved
michael@0 3673 // See ChunkedStream.moveStart()
michael@0 3674 var length = this.bytes.length;
michael@0 3675 assert(end % this.chunkSize === 0 || end === length,
michael@0 3676 'Bad end offset: ' + end);
michael@0 3677
michael@0 3678 this.bytes.set(new Uint8Array(chunk), begin);
michael@0 3679 var chunkSize = this.chunkSize;
michael@0 3680 var beginChunk = Math.floor(begin / chunkSize);
michael@0 3681 var endChunk = Math.floor((end - 1) / chunkSize) + 1;
michael@0 3682 var curChunk;
michael@0 3683
michael@0 3684 for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
michael@0 3685 if (!(curChunk in this.loadedChunks)) {
michael@0 3686 this.loadedChunks[curChunk] = true;
michael@0 3687 ++this.numChunksLoaded;
michael@0 3688 }
michael@0 3689 }
michael@0 3690 },
michael@0 3691
michael@0 3692 onReceiveInitialData: function ChunkedStream_onReceiveInitialData(data) {
michael@0 3693 this.bytes.set(data);
michael@0 3694 this.initialDataLength = data.length;
michael@0 3695 var endChunk = (this.end === data.length ?
michael@0 3696 this.numChunks : Math.floor(data.length / this.chunkSize));
michael@0 3697 for (var i = 0; i < endChunk; i++) {
michael@0 3698 this.loadedChunks[i] = true;
michael@0 3699 ++this.numChunksLoaded;
michael@0 3700 }
michael@0 3701 },
michael@0 3702
michael@0 3703 ensureRange: function ChunkedStream_ensureRange(begin, end) {
michael@0 3704 if (begin >= end) {
michael@0 3705 return;
michael@0 3706 }
michael@0 3707
michael@0 3708 if (end <= this.initialDataLength) {
michael@0 3709 return;
michael@0 3710 }
michael@0 3711
michael@0 3712 var chunkSize = this.chunkSize;
michael@0 3713 var beginChunk = Math.floor(begin / chunkSize);
michael@0 3714 var endChunk = Math.floor((end - 1) / chunkSize) + 1;
michael@0 3715 for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
michael@0 3716 if (!(chunk in this.loadedChunks)) {
michael@0 3717 throw new MissingDataException(begin, end);
michael@0 3718 }
michael@0 3719 }
michael@0 3720 },
michael@0 3721
michael@0 3722 nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) {
michael@0 3723 var chunk, n;
michael@0 3724 for (chunk = beginChunk, n = this.numChunks; chunk < n; ++chunk) {
michael@0 3725 if (!(chunk in this.loadedChunks)) {
michael@0 3726 return chunk;
michael@0 3727 }
michael@0 3728 }
michael@0 3729 // Wrap around to beginning
michael@0 3730 for (chunk = 0; chunk < beginChunk; ++chunk) {
michael@0 3731 if (!(chunk in this.loadedChunks)) {
michael@0 3732 return chunk;
michael@0 3733 }
michael@0 3734 }
michael@0 3735 return null;
michael@0 3736 },
michael@0 3737
michael@0 3738 hasChunk: function ChunkedStream_hasChunk(chunk) {
michael@0 3739 return chunk in this.loadedChunks;
michael@0 3740 },
michael@0 3741
michael@0 3742 get length() {
michael@0 3743 return this.end - this.start;
michael@0 3744 },
michael@0 3745
michael@0 3746 getByte: function ChunkedStream_getByte() {
michael@0 3747 var pos = this.pos;
michael@0 3748 if (pos >= this.end) {
michael@0 3749 return -1;
michael@0 3750 }
michael@0 3751 this.ensureRange(pos, pos + 1);
michael@0 3752 return this.bytes[this.pos++];
michael@0 3753 },
michael@0 3754
michael@0 3755 getUint16: function ChunkedStream_getUint16() {
michael@0 3756 var b0 = this.getByte();
michael@0 3757 var b1 = this.getByte();
michael@0 3758 return (b0 << 8) + b1;
michael@0 3759 },
michael@0 3760
michael@0 3761 getInt32: function ChunkedStream_getInt32() {
michael@0 3762 var b0 = this.getByte();
michael@0 3763 var b1 = this.getByte();
michael@0 3764 var b2 = this.getByte();
michael@0 3765 var b3 = this.getByte();
michael@0 3766 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
michael@0 3767 },
michael@0 3768
michael@0 3769 // returns subarray of original buffer
michael@0 3770 // should only be read
michael@0 3771 getBytes: function ChunkedStream_getBytes(length) {
michael@0 3772 var bytes = this.bytes;
michael@0 3773 var pos = this.pos;
michael@0 3774 var strEnd = this.end;
michael@0 3775
michael@0 3776 if (!length) {
michael@0 3777 this.ensureRange(pos, strEnd);
michael@0 3778 return bytes.subarray(pos, strEnd);
michael@0 3779 }
michael@0 3780
michael@0 3781 var end = pos + length;
michael@0 3782 if (end > strEnd) {
michael@0 3783 end = strEnd;
michael@0 3784 }
michael@0 3785 this.ensureRange(pos, end);
michael@0 3786
michael@0 3787 this.pos = end;
michael@0 3788 return bytes.subarray(pos, end);
michael@0 3789 },
michael@0 3790
michael@0 3791 peekBytes: function ChunkedStream_peekBytes(length) {
michael@0 3792 var bytes = this.getBytes(length);
michael@0 3793 this.pos -= bytes.length;
michael@0 3794 return bytes;
michael@0 3795 },
michael@0 3796
michael@0 3797 getByteRange: function ChunkedStream_getBytes(begin, end) {
michael@0 3798 this.ensureRange(begin, end);
michael@0 3799 return this.bytes.subarray(begin, end);
michael@0 3800 },
michael@0 3801
michael@0 3802 skip: function ChunkedStream_skip(n) {
michael@0 3803 if (!n) {
michael@0 3804 n = 1;
michael@0 3805 }
michael@0 3806 this.pos += n;
michael@0 3807 },
michael@0 3808
michael@0 3809 reset: function ChunkedStream_reset() {
michael@0 3810 this.pos = this.start;
michael@0 3811 },
michael@0 3812
michael@0 3813 moveStart: function ChunkedStream_moveStart() {
michael@0 3814 this.start = this.pos;
michael@0 3815 },
michael@0 3816
michael@0 3817 makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) {
michael@0 3818 this.ensureRange(start, start + length);
michael@0 3819
michael@0 3820 function ChunkedStreamSubstream() {}
michael@0 3821 ChunkedStreamSubstream.prototype = Object.create(this);
michael@0 3822 ChunkedStreamSubstream.prototype.getMissingChunks = function() {
michael@0 3823 var chunkSize = this.chunkSize;
michael@0 3824 var beginChunk = Math.floor(this.start / chunkSize);
michael@0 3825 var endChunk = Math.floor((this.end - 1) / chunkSize) + 1;
michael@0 3826 var missingChunks = [];
michael@0 3827 for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
michael@0 3828 if (!(chunk in this.loadedChunks)) {
michael@0 3829 missingChunks.push(chunk);
michael@0 3830 }
michael@0 3831 }
michael@0 3832 return missingChunks;
michael@0 3833 };
michael@0 3834 var subStream = new ChunkedStreamSubstream();
michael@0 3835 subStream.pos = subStream.start = start;
michael@0 3836 subStream.end = start + length || this.end;
michael@0 3837 subStream.dict = dict;
michael@0 3838 return subStream;
michael@0 3839 },
michael@0 3840
michael@0 3841 isStream: true
michael@0 3842 };
michael@0 3843
michael@0 3844 return ChunkedStream;
michael@0 3845 })();
michael@0 3846
michael@0 3847 var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
michael@0 3848
michael@0 3849 function ChunkedStreamManager(length, chunkSize, url, args) {
michael@0 3850 this.stream = new ChunkedStream(length, chunkSize, this);
michael@0 3851 this.length = length;
michael@0 3852 this.chunkSize = chunkSize;
michael@0 3853 this.url = url;
michael@0 3854 this.disableAutoFetch = args.disableAutoFetch;
michael@0 3855 var msgHandler = this.msgHandler = args.msgHandler;
michael@0 3856
michael@0 3857 if (args.chunkedViewerLoading) {
michael@0 3858 msgHandler.on('OnDataRange', this.onReceiveData.bind(this));
michael@0 3859 msgHandler.on('OnDataProgress', this.onProgress.bind(this));
michael@0 3860 this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) {
michael@0 3861 msgHandler.send('RequestDataRange', { begin: begin, end: end });
michael@0 3862 };
michael@0 3863 } else {
michael@0 3864
michael@0 3865 var getXhr = function getXhr() {
michael@0 3866 return new XMLHttpRequest();
michael@0 3867 };
michael@0 3868 this.networkManager = new NetworkManager(this.url, {
michael@0 3869 getXhr: getXhr,
michael@0 3870 httpHeaders: args.httpHeaders,
michael@0 3871 withCredentials: args.withCredentials
michael@0 3872 });
michael@0 3873 this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) {
michael@0 3874 this.networkManager.requestRange(begin, end, {
michael@0 3875 onDone: this.onReceiveData.bind(this),
michael@0 3876 onProgress: this.onProgress.bind(this)
michael@0 3877 });
michael@0 3878 };
michael@0 3879 }
michael@0 3880
michael@0 3881 this.currRequestId = 0;
michael@0 3882
michael@0 3883 this.chunksNeededByRequest = {};
michael@0 3884 this.requestsByChunk = {};
michael@0 3885 this.callbacksByRequest = {};
michael@0 3886
michael@0 3887 this.loadedStream = new LegacyPromise();
michael@0 3888 if (args.initialData) {
michael@0 3889 this.setInitialData(args.initialData);
michael@0 3890 }
michael@0 3891 }
michael@0 3892
michael@0 3893 ChunkedStreamManager.prototype = {
michael@0 3894
michael@0 3895 setInitialData: function ChunkedStreamManager_setInitialData(data) {
michael@0 3896 this.stream.onReceiveInitialData(data);
michael@0 3897 if (this.stream.allChunksLoaded()) {
michael@0 3898 this.loadedStream.resolve(this.stream);
michael@0 3899 } else if (this.msgHandler) {
michael@0 3900 this.msgHandler.send('DocProgress', {
michael@0 3901 loaded: data.length,
michael@0 3902 total: this.length
michael@0 3903 });
michael@0 3904 }
michael@0 3905 },
michael@0 3906
michael@0 3907 onLoadedStream: function ChunkedStreamManager_getLoadedStream() {
michael@0 3908 return this.loadedStream;
michael@0 3909 },
michael@0 3910
michael@0 3911 // Get all the chunks that are not yet loaded and groups them into
michael@0 3912 // contiguous ranges to load in as few requests as possible
michael@0 3913 requestAllChunks: function ChunkedStreamManager_requestAllChunks() {
michael@0 3914 var missingChunks = this.stream.getMissingChunks();
michael@0 3915 this.requestChunks(missingChunks);
michael@0 3916 return this.loadedStream;
michael@0 3917 },
michael@0 3918
michael@0 3919 requestChunks: function ChunkedStreamManager_requestChunks(chunks,
michael@0 3920 callback) {
michael@0 3921 var requestId = this.currRequestId++;
michael@0 3922
michael@0 3923 var chunksNeeded;
michael@0 3924 var i, ii;
michael@0 3925 this.chunksNeededByRequest[requestId] = chunksNeeded = {};
michael@0 3926 for (i = 0, ii = chunks.length; i < ii; i++) {
michael@0 3927 if (!this.stream.hasChunk(chunks[i])) {
michael@0 3928 chunksNeeded[chunks[i]] = true;
michael@0 3929 }
michael@0 3930 }
michael@0 3931
michael@0 3932 if (isEmptyObj(chunksNeeded)) {
michael@0 3933 if (callback) {
michael@0 3934 callback();
michael@0 3935 }
michael@0 3936 return;
michael@0 3937 }
michael@0 3938
michael@0 3939 this.callbacksByRequest[requestId] = callback;
michael@0 3940
michael@0 3941 var chunksToRequest = [];
michael@0 3942 for (var chunk in chunksNeeded) {
michael@0 3943 chunk = chunk | 0;
michael@0 3944 if (!(chunk in this.requestsByChunk)) {
michael@0 3945 this.requestsByChunk[chunk] = [];
michael@0 3946 chunksToRequest.push(chunk);
michael@0 3947 }
michael@0 3948 this.requestsByChunk[chunk].push(requestId);
michael@0 3949 }
michael@0 3950
michael@0 3951 if (!chunksToRequest.length) {
michael@0 3952 return;
michael@0 3953 }
michael@0 3954
michael@0 3955 var groupedChunksToRequest = this.groupChunks(chunksToRequest);
michael@0 3956
michael@0 3957 for (i = 0; i < groupedChunksToRequest.length; ++i) {
michael@0 3958 var groupedChunk = groupedChunksToRequest[i];
michael@0 3959 var begin = groupedChunk.beginChunk * this.chunkSize;
michael@0 3960 var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length);
michael@0 3961 this.sendRequest(begin, end);
michael@0 3962 }
michael@0 3963 },
michael@0 3964
michael@0 3965 getStream: function ChunkedStreamManager_getStream() {
michael@0 3966 return this.stream;
michael@0 3967 },
michael@0 3968
michael@0 3969 // Loads any chunks in the requested range that are not yet loaded
michael@0 3970 requestRange: function ChunkedStreamManager_requestRange(
michael@0 3971 begin, end, callback) {
michael@0 3972
michael@0 3973 end = Math.min(end, this.length);
michael@0 3974
michael@0 3975 var beginChunk = this.getBeginChunk(begin);
michael@0 3976 var endChunk = this.getEndChunk(end);
michael@0 3977
michael@0 3978 var chunks = [];
michael@0 3979 for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
michael@0 3980 chunks.push(chunk);
michael@0 3981 }
michael@0 3982
michael@0 3983 this.requestChunks(chunks, callback);
michael@0 3984 },
michael@0 3985
michael@0 3986 requestRanges: function ChunkedStreamManager_requestRanges(ranges,
michael@0 3987 callback) {
michael@0 3988 ranges = ranges || [];
michael@0 3989 var chunksToRequest = [];
michael@0 3990
michael@0 3991 for (var i = 0; i < ranges.length; i++) {
michael@0 3992 var beginChunk = this.getBeginChunk(ranges[i].begin);
michael@0 3993 var endChunk = this.getEndChunk(ranges[i].end);
michael@0 3994 for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
michael@0 3995 if (chunksToRequest.indexOf(chunk) < 0) {
michael@0 3996 chunksToRequest.push(chunk);
michael@0 3997 }
michael@0 3998 }
michael@0 3999 }
michael@0 4000
michael@0 4001 chunksToRequest.sort(function(a, b) { return a - b; });
michael@0 4002 this.requestChunks(chunksToRequest, callback);
michael@0 4003 },
michael@0 4004
michael@0 4005 // Groups a sorted array of chunks into as few continguous larger
michael@0 4006 // chunks as possible
michael@0 4007 groupChunks: function ChunkedStreamManager_groupChunks(chunks) {
michael@0 4008 var groupedChunks = [];
michael@0 4009 var beginChunk = -1;
michael@0 4010 var prevChunk = -1;
michael@0 4011 for (var i = 0; i < chunks.length; ++i) {
michael@0 4012 var chunk = chunks[i];
michael@0 4013
michael@0 4014 if (beginChunk < 0) {
michael@0 4015 beginChunk = chunk;
michael@0 4016 }
michael@0 4017
michael@0 4018 if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
michael@0 4019 groupedChunks.push({ beginChunk: beginChunk,
michael@0 4020 endChunk: prevChunk + 1 });
michael@0 4021 beginChunk = chunk;
michael@0 4022 }
michael@0 4023 if (i + 1 === chunks.length) {
michael@0 4024 groupedChunks.push({ beginChunk: beginChunk,
michael@0 4025 endChunk: chunk + 1 });
michael@0 4026 }
michael@0 4027
michael@0 4028 prevChunk = chunk;
michael@0 4029 }
michael@0 4030 return groupedChunks;
michael@0 4031 },
michael@0 4032
michael@0 4033 onProgress: function ChunkedStreamManager_onProgress(args) {
michael@0 4034 var bytesLoaded = (this.stream.numChunksLoaded * this.chunkSize +
michael@0 4035 args.loaded);
michael@0 4036 this.msgHandler.send('DocProgress', {
michael@0 4037 loaded: bytesLoaded,
michael@0 4038 total: this.length
michael@0 4039 });
michael@0 4040 },
michael@0 4041
michael@0 4042 onReceiveData: function ChunkedStreamManager_onReceiveData(args) {
michael@0 4043 var chunk = args.chunk;
michael@0 4044 var begin = args.begin;
michael@0 4045 var end = begin + chunk.byteLength;
michael@0 4046
michael@0 4047 var beginChunk = this.getBeginChunk(begin);
michael@0 4048 var endChunk = this.getEndChunk(end);
michael@0 4049
michael@0 4050 this.stream.onReceiveData(begin, chunk);
michael@0 4051 if (this.stream.allChunksLoaded()) {
michael@0 4052 this.loadedStream.resolve(this.stream);
michael@0 4053 }
michael@0 4054
michael@0 4055 var loadedRequests = [];
michael@0 4056 var i, requestId;
michael@0 4057 for (chunk = beginChunk; chunk < endChunk; ++chunk) {
michael@0 4058 // The server might return more chunks than requested
michael@0 4059 var requestIds = this.requestsByChunk[chunk] || [];
michael@0 4060 delete this.requestsByChunk[chunk];
michael@0 4061
michael@0 4062 for (i = 0; i < requestIds.length; ++i) {
michael@0 4063 requestId = requestIds[i];
michael@0 4064 var chunksNeeded = this.chunksNeededByRequest[requestId];
michael@0 4065 if (chunk in chunksNeeded) {
michael@0 4066 delete chunksNeeded[chunk];
michael@0 4067 }
michael@0 4068
michael@0 4069 if (!isEmptyObj(chunksNeeded)) {
michael@0 4070 continue;
michael@0 4071 }
michael@0 4072
michael@0 4073 loadedRequests.push(requestId);
michael@0 4074 }
michael@0 4075 }
michael@0 4076
michael@0 4077 // If there are no pending requests, automatically fetch the next
michael@0 4078 // unfetched chunk of the PDF
michael@0 4079 if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) {
michael@0 4080 var nextEmptyChunk;
michael@0 4081 if (this.stream.numChunksLoaded === 1) {
michael@0 4082 // This is a special optimization so that after fetching the first
michael@0 4083 // chunk, rather than fetching the second chunk, we fetch the last
michael@0 4084 // chunk.
michael@0 4085 var lastChunk = this.stream.numChunks - 1;
michael@0 4086 if (!this.stream.hasChunk(lastChunk)) {
michael@0 4087 nextEmptyChunk = lastChunk;
michael@0 4088 }
michael@0 4089 } else {
michael@0 4090 nextEmptyChunk = this.stream.nextEmptyChunk(endChunk);
michael@0 4091 }
michael@0 4092 if (isInt(nextEmptyChunk)) {
michael@0 4093 this.requestChunks([nextEmptyChunk]);
michael@0 4094 }
michael@0 4095 }
michael@0 4096
michael@0 4097 for (i = 0; i < loadedRequests.length; ++i) {
michael@0 4098 requestId = loadedRequests[i];
michael@0 4099 var callback = this.callbacksByRequest[requestId];
michael@0 4100 delete this.callbacksByRequest[requestId];
michael@0 4101 if (callback) {
michael@0 4102 callback();
michael@0 4103 }
michael@0 4104 }
michael@0 4105
michael@0 4106 this.msgHandler.send('DocProgress', {
michael@0 4107 loaded: this.stream.numChunksLoaded * this.chunkSize,
michael@0 4108 total: this.length
michael@0 4109 });
michael@0 4110 },
michael@0 4111
michael@0 4112 getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) {
michael@0 4113 var chunk = Math.floor(begin / this.chunkSize);
michael@0 4114 return chunk;
michael@0 4115 },
michael@0 4116
michael@0 4117 getEndChunk: function ChunkedStreamManager_getEndChunk(end) {
michael@0 4118 if (end % this.chunkSize === 0) {
michael@0 4119 return end / this.chunkSize;
michael@0 4120 }
michael@0 4121
michael@0 4122 // 0 -> 0
michael@0 4123 // 1 -> 1
michael@0 4124 // 99 -> 1
michael@0 4125 // 100 -> 1
michael@0 4126 // 101 -> 2
michael@0 4127 var chunk = Math.floor((end - 1) / this.chunkSize) + 1;
michael@0 4128 return chunk;
michael@0 4129 }
michael@0 4130 };
michael@0 4131
michael@0 4132 return ChunkedStreamManager;
michael@0 4133 })();
michael@0 4134
michael@0 4135
michael@0 4136
michael@0 4137 // The maximum number of bytes fetched per range request
michael@0 4138 var RANGE_CHUNK_SIZE = 65536;
michael@0 4139
michael@0 4140 // TODO(mack): Make use of PDFJS.Util.inherit() when it becomes available
michael@0 4141 var BasePdfManager = (function BasePdfManagerClosure() {
michael@0 4142 function BasePdfManager() {
michael@0 4143 throw new Error('Cannot initialize BaseManagerManager');
michael@0 4144 }
michael@0 4145
michael@0 4146 BasePdfManager.prototype = {
michael@0 4147 onLoadedStream: function BasePdfManager_onLoadedStream() {
michael@0 4148 throw new NotImplementedException();
michael@0 4149 },
michael@0 4150
michael@0 4151 ensureDoc: function BasePdfManager_ensureDoc(prop, args) {
michael@0 4152 return this.ensure(this.pdfDocument, prop, args);
michael@0 4153 },
michael@0 4154
michael@0 4155 ensureXRef: function BasePdfManager_ensureXRef(prop, args) {
michael@0 4156 return this.ensure(this.pdfDocument.xref, prop, args);
michael@0 4157 },
michael@0 4158
michael@0 4159 ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) {
michael@0 4160 return this.ensure(this.pdfDocument.catalog, prop, args);
michael@0 4161 },
michael@0 4162
michael@0 4163 getPage: function BasePdfManager_pagePage(pageIndex) {
michael@0 4164 return this.pdfDocument.getPage(pageIndex);
michael@0 4165 },
michael@0 4166
michael@0 4167 cleanup: function BasePdfManager_cleanup() {
michael@0 4168 return this.pdfDocument.cleanup();
michael@0 4169 },
michael@0 4170
michael@0 4171 ensure: function BasePdfManager_ensure(obj, prop, args) {
michael@0 4172 return new NotImplementedException();
michael@0 4173 },
michael@0 4174
michael@0 4175 requestRange: function BasePdfManager_ensure(begin, end) {
michael@0 4176 return new NotImplementedException();
michael@0 4177 },
michael@0 4178
michael@0 4179 requestLoadedStream: function BasePdfManager_requestLoadedStream() {
michael@0 4180 return new NotImplementedException();
michael@0 4181 },
michael@0 4182
michael@0 4183 updatePassword: function BasePdfManager_updatePassword(password) {
michael@0 4184 this.pdfDocument.xref.password = this.password = password;
michael@0 4185 if (this.passwordChangedPromise) {
michael@0 4186 this.passwordChangedPromise.resolve();
michael@0 4187 }
michael@0 4188 },
michael@0 4189
michael@0 4190 terminate: function BasePdfManager_terminate() {
michael@0 4191 return new NotImplementedException();
michael@0 4192 }
michael@0 4193 };
michael@0 4194
michael@0 4195 return BasePdfManager;
michael@0 4196 })();
michael@0 4197
michael@0 4198 var LocalPdfManager = (function LocalPdfManagerClosure() {
michael@0 4199 function LocalPdfManager(data, password) {
michael@0 4200 var stream = new Stream(data);
michael@0 4201 this.pdfDocument = new PDFDocument(this, stream, password);
michael@0 4202 this.loadedStream = new LegacyPromise();
michael@0 4203 this.loadedStream.resolve(stream);
michael@0 4204 }
michael@0 4205
michael@0 4206 LocalPdfManager.prototype = Object.create(BasePdfManager.prototype);
michael@0 4207 LocalPdfManager.prototype.constructor = LocalPdfManager;
michael@0 4208
michael@0 4209 LocalPdfManager.prototype.ensure =
michael@0 4210 function LocalPdfManager_ensure(obj, prop, args) {
michael@0 4211 var promise = new LegacyPromise();
michael@0 4212 try {
michael@0 4213 var value = obj[prop];
michael@0 4214 var result;
michael@0 4215 if (typeof(value) === 'function') {
michael@0 4216 result = value.apply(obj, args);
michael@0 4217 } else {
michael@0 4218 result = value;
michael@0 4219 }
michael@0 4220 promise.resolve(result);
michael@0 4221 } catch (e) {
michael@0 4222 console.log(e.stack);
michael@0 4223 promise.reject(e);
michael@0 4224 }
michael@0 4225 return promise;
michael@0 4226 };
michael@0 4227
michael@0 4228 LocalPdfManager.prototype.requestRange =
michael@0 4229 function LocalPdfManager_requestRange(begin, end) {
michael@0 4230 var promise = new LegacyPromise();
michael@0 4231 promise.resolve();
michael@0 4232 return promise;
michael@0 4233 };
michael@0 4234
michael@0 4235 LocalPdfManager.prototype.requestLoadedStream =
michael@0 4236 function LocalPdfManager_requestLoadedStream() {
michael@0 4237 };
michael@0 4238
michael@0 4239 LocalPdfManager.prototype.onLoadedStream =
michael@0 4240 function LocalPdfManager_getLoadedStream() {
michael@0 4241 return this.loadedStream;
michael@0 4242 };
michael@0 4243
michael@0 4244 LocalPdfManager.prototype.terminate =
michael@0 4245 function LocalPdfManager_terminate() {
michael@0 4246 return;
michael@0 4247 };
michael@0 4248
michael@0 4249 return LocalPdfManager;
michael@0 4250 })();
michael@0 4251
michael@0 4252 var NetworkPdfManager = (function NetworkPdfManagerClosure() {
michael@0 4253 function NetworkPdfManager(args, msgHandler) {
michael@0 4254
michael@0 4255 this.msgHandler = msgHandler;
michael@0 4256
michael@0 4257 var params = {
michael@0 4258 msgHandler: msgHandler,
michael@0 4259 httpHeaders: args.httpHeaders,
michael@0 4260 withCredentials: args.withCredentials,
michael@0 4261 chunkedViewerLoading: args.chunkedViewerLoading,
michael@0 4262 disableAutoFetch: args.disableAutoFetch,
michael@0 4263 initialData: args.initialData
michael@0 4264 };
michael@0 4265 this.streamManager = new ChunkedStreamManager(args.length, RANGE_CHUNK_SIZE,
michael@0 4266 args.url, params);
michael@0 4267
michael@0 4268 this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(),
michael@0 4269 args.password);
michael@0 4270 }
michael@0 4271
michael@0 4272 NetworkPdfManager.prototype = Object.create(BasePdfManager.prototype);
michael@0 4273 NetworkPdfManager.prototype.constructor = NetworkPdfManager;
michael@0 4274
michael@0 4275 NetworkPdfManager.prototype.ensure =
michael@0 4276 function NetworkPdfManager_ensure(obj, prop, args) {
michael@0 4277 var promise = new LegacyPromise();
michael@0 4278 this.ensureHelper(promise, obj, prop, args);
michael@0 4279 return promise;
michael@0 4280 };
michael@0 4281
michael@0 4282 NetworkPdfManager.prototype.ensureHelper =
michael@0 4283 function NetworkPdfManager_ensureHelper(promise, obj, prop, args) {
michael@0 4284 try {
michael@0 4285 var result;
michael@0 4286 var value = obj[prop];
michael@0 4287 if (typeof(value) === 'function') {
michael@0 4288 result = value.apply(obj, args);
michael@0 4289 } else {
michael@0 4290 result = value;
michael@0 4291 }
michael@0 4292 promise.resolve(result);
michael@0 4293 } catch(e) {
michael@0 4294 if (!(e instanceof MissingDataException)) {
michael@0 4295 console.log(e.stack);
michael@0 4296 promise.reject(e);
michael@0 4297 return;
michael@0 4298 }
michael@0 4299
michael@0 4300 this.streamManager.requestRange(e.begin, e.end, function() {
michael@0 4301 this.ensureHelper(promise, obj, prop, args);
michael@0 4302 }.bind(this));
michael@0 4303 }
michael@0 4304 };
michael@0 4305
michael@0 4306 NetworkPdfManager.prototype.requestRange =
michael@0 4307 function NetworkPdfManager_requestRange(begin, end) {
michael@0 4308 var promise = new LegacyPromise();
michael@0 4309 this.streamManager.requestRange(begin, end, function() {
michael@0 4310 promise.resolve();
michael@0 4311 });
michael@0 4312 return promise;
michael@0 4313 };
michael@0 4314
michael@0 4315 NetworkPdfManager.prototype.requestLoadedStream =
michael@0 4316 function NetworkPdfManager_requestLoadedStream() {
michael@0 4317 this.streamManager.requestAllChunks();
michael@0 4318 };
michael@0 4319
michael@0 4320 NetworkPdfManager.prototype.onLoadedStream =
michael@0 4321 function NetworkPdfManager_getLoadedStream() {
michael@0 4322 return this.streamManager.onLoadedStream();
michael@0 4323 };
michael@0 4324
michael@0 4325 NetworkPdfManager.prototype.terminate =
michael@0 4326 function NetworkPdfManager_terminate() {
michael@0 4327 this.streamManager.networkManager.abortAllRequests();
michael@0 4328 };
michael@0 4329
michael@0 4330 return NetworkPdfManager;
michael@0 4331 })();
michael@0 4332
michael@0 4333
michael@0 4334
michael@0 4335 var Page = (function PageClosure() {
michael@0 4336
michael@0 4337 var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
michael@0 4338
michael@0 4339 function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) {
michael@0 4340 this.pdfManager = pdfManager;
michael@0 4341 this.pageIndex = pageIndex;
michael@0 4342 this.pageDict = pageDict;
michael@0 4343 this.xref = xref;
michael@0 4344 this.ref = ref;
michael@0 4345 this.fontCache = fontCache;
michael@0 4346 this.idCounters = {
michael@0 4347 obj: 0
michael@0 4348 };
michael@0 4349 this.resourcesPromise = null;
michael@0 4350 }
michael@0 4351
michael@0 4352 Page.prototype = {
michael@0 4353 getPageProp: function Page_getPageProp(key) {
michael@0 4354 return this.pageDict.get(key);
michael@0 4355 },
michael@0 4356
michael@0 4357 getInheritedPageProp: function Page_inheritPageProp(key) {
michael@0 4358 var dict = this.pageDict;
michael@0 4359 var value = dict.get(key);
michael@0 4360 while (value === undefined) {
michael@0 4361 dict = dict.get('Parent');
michael@0 4362 if (!dict) {
michael@0 4363 break;
michael@0 4364 }
michael@0 4365 value = dict.get(key);
michael@0 4366 }
michael@0 4367 return value;
michael@0 4368 },
michael@0 4369
michael@0 4370 get content() {
michael@0 4371 return this.getPageProp('Contents');
michael@0 4372 },
michael@0 4373
michael@0 4374 get resources() {
michael@0 4375 var value = this.getInheritedPageProp('Resources');
michael@0 4376 // For robustness: The spec states that a \Resources entry has to be
michael@0 4377 // present, but can be empty. Some document omit it still. In this case
michael@0 4378 // return an empty dictionary:
michael@0 4379 if (value === undefined) {
michael@0 4380 value = Dict.empty;
michael@0 4381 }
michael@0 4382 return shadow(this, 'resources', value);
michael@0 4383 },
michael@0 4384
michael@0 4385 get mediaBox() {
michael@0 4386 var obj = this.getInheritedPageProp('MediaBox');
michael@0 4387 // Reset invalid media box to letter size.
michael@0 4388 if (!isArray(obj) || obj.length !== 4) {
michael@0 4389 obj = LETTER_SIZE_MEDIABOX;
michael@0 4390 }
michael@0 4391 return shadow(this, 'mediaBox', obj);
michael@0 4392 },
michael@0 4393
michael@0 4394 get view() {
michael@0 4395 var mediaBox = this.mediaBox;
michael@0 4396 var cropBox = this.getInheritedPageProp('CropBox');
michael@0 4397 if (!isArray(cropBox) || cropBox.length !== 4) {
michael@0 4398 return shadow(this, 'view', mediaBox);
michael@0 4399 }
michael@0 4400
michael@0 4401 // From the spec, 6th ed., p.963:
michael@0 4402 // "The crop, bleed, trim, and art boxes should not ordinarily
michael@0 4403 // extend beyond the boundaries of the media box. If they do, they are
michael@0 4404 // effectively reduced to their intersection with the media box."
michael@0 4405 cropBox = Util.intersect(cropBox, mediaBox);
michael@0 4406 if (!cropBox) {
michael@0 4407 return shadow(this, 'view', mediaBox);
michael@0 4408 }
michael@0 4409 return shadow(this, 'view', cropBox);
michael@0 4410 },
michael@0 4411
michael@0 4412 get annotationRefs() {
michael@0 4413 return shadow(this, 'annotationRefs',
michael@0 4414 this.getInheritedPageProp('Annots'));
michael@0 4415 },
michael@0 4416
michael@0 4417 get rotate() {
michael@0 4418 var rotate = this.getInheritedPageProp('Rotate') || 0;
michael@0 4419 // Normalize rotation so it's a multiple of 90 and between 0 and 270
michael@0 4420 if (rotate % 90 !== 0) {
michael@0 4421 rotate = 0;
michael@0 4422 } else if (rotate >= 360) {
michael@0 4423 rotate = rotate % 360;
michael@0 4424 } else if (rotate < 0) {
michael@0 4425 // The spec doesn't cover negatives, assume its counterclockwise
michael@0 4426 // rotation. The following is the other implementation of modulo.
michael@0 4427 rotate = ((rotate % 360) + 360) % 360;
michael@0 4428 }
michael@0 4429 return shadow(this, 'rotate', rotate);
michael@0 4430 },
michael@0 4431
michael@0 4432 getContentStream: function Page_getContentStream() {
michael@0 4433 var content = this.content;
michael@0 4434 var stream;
michael@0 4435 if (isArray(content)) {
michael@0 4436 // fetching items
michael@0 4437 var xref = this.xref;
michael@0 4438 var i, n = content.length;
michael@0 4439 var streams = [];
michael@0 4440 for (i = 0; i < n; ++i) {
michael@0 4441 streams.push(xref.fetchIfRef(content[i]));
michael@0 4442 }
michael@0 4443 stream = new StreamsSequenceStream(streams);
michael@0 4444 } else if (isStream(content)) {
michael@0 4445 stream = content;
michael@0 4446 } else {
michael@0 4447 // replacing non-existent page content with empty one
michael@0 4448 stream = new NullStream();
michael@0 4449 }
michael@0 4450 return stream;
michael@0 4451 },
michael@0 4452
michael@0 4453 loadResources: function(keys) {
michael@0 4454 if (!this.resourcesPromise) {
michael@0 4455 // TODO: add async getInheritedPageProp and remove this.
michael@0 4456 this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
michael@0 4457 }
michael@0 4458 var promise = new LegacyPromise();
michael@0 4459 this.resourcesPromise.then(function resourceSuccess() {
michael@0 4460 var objectLoader = new ObjectLoader(this.resources.map,
michael@0 4461 keys,
michael@0 4462 this.xref);
michael@0 4463 objectLoader.load().then(function objectLoaderSuccess() {
michael@0 4464 promise.resolve();
michael@0 4465 });
michael@0 4466 }.bind(this));
michael@0 4467 return promise;
michael@0 4468 },
michael@0 4469
michael@0 4470 getOperatorList: function Page_getOperatorList(handler, intent) {
michael@0 4471 var self = this;
michael@0 4472 var promise = new LegacyPromise();
michael@0 4473
michael@0 4474 function reject(e) {
michael@0 4475 promise.reject(e);
michael@0 4476 }
michael@0 4477
michael@0 4478 var pageListPromise = new LegacyPromise();
michael@0 4479
michael@0 4480 var pdfManager = this.pdfManager;
michael@0 4481 var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
michael@0 4482 []);
michael@0 4483 var resourcesPromise = this.loadResources([
michael@0 4484 'ExtGState',
michael@0 4485 'ColorSpace',
michael@0 4486 'Pattern',
michael@0 4487 'Shading',
michael@0 4488 'XObject',
michael@0 4489 'Font'
michael@0 4490 // ProcSet
michael@0 4491 // Properties
michael@0 4492 ]);
michael@0 4493
michael@0 4494 var partialEvaluator = new PartialEvaluator(pdfManager, this.xref,
michael@0 4495 handler, this.pageIndex,
michael@0 4496 'p' + this.pageIndex + '_',
michael@0 4497 this.idCounters,
michael@0 4498 this.fontCache);
michael@0 4499
michael@0 4500 var dataPromises = Promise.all([contentStreamPromise, resourcesPromise],
michael@0 4501 reject);
michael@0 4502 dataPromises.then(function(data) {
michael@0 4503 var contentStream = data[0];
michael@0 4504 var opList = new OperatorList(intent, handler, self.pageIndex);
michael@0 4505
michael@0 4506 handler.send('StartRenderPage', {
michael@0 4507 transparency: partialEvaluator.hasBlendModes(self.resources),
michael@0 4508 pageIndex: self.pageIndex,
michael@0 4509 intent: intent
michael@0 4510 });
michael@0 4511 partialEvaluator.getOperatorList(contentStream, self.resources, opList);
michael@0 4512 pageListPromise.resolve(opList);
michael@0 4513 });
michael@0 4514
michael@0 4515 var annotationsPromise = pdfManager.ensure(this, 'annotations');
michael@0 4516 Promise.all([pageListPromise, annotationsPromise]).then(function(datas) {
michael@0 4517 var pageOpList = datas[0];
michael@0 4518 var annotations = datas[1];
michael@0 4519
michael@0 4520 if (annotations.length === 0) {
michael@0 4521 pageOpList.flush(true);
michael@0 4522 promise.resolve(pageOpList);
michael@0 4523 return;
michael@0 4524 }
michael@0 4525
michael@0 4526 var annotationsReadyPromise = Annotation.appendToOperatorList(
michael@0 4527 annotations, pageOpList, pdfManager, partialEvaluator, intent);
michael@0 4528 annotationsReadyPromise.then(function () {
michael@0 4529 pageOpList.flush(true);
michael@0 4530 promise.resolve(pageOpList);
michael@0 4531 }, reject);
michael@0 4532 }, reject);
michael@0 4533
michael@0 4534 return promise;
michael@0 4535 },
michael@0 4536
michael@0 4537 extractTextContent: function Page_extractTextContent() {
michael@0 4538 var handler = {
michael@0 4539 on: function nullHandlerOn() {},
michael@0 4540 send: function nullHandlerSend() {}
michael@0 4541 };
michael@0 4542
michael@0 4543 var self = this;
michael@0 4544
michael@0 4545 var pdfManager = this.pdfManager;
michael@0 4546 var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
michael@0 4547 []);
michael@0 4548
michael@0 4549 var resourcesPromise = this.loadResources([
michael@0 4550 'ExtGState',
michael@0 4551 'XObject',
michael@0 4552 'Font'
michael@0 4553 ]);
michael@0 4554
michael@0 4555 var dataPromises = Promise.all([contentStreamPromise,
michael@0 4556 resourcesPromise]);
michael@0 4557 return dataPromises.then(function(data) {
michael@0 4558 var contentStream = data[0];
michael@0 4559 var partialEvaluator = new PartialEvaluator(pdfManager, self.xref,
michael@0 4560 handler, self.pageIndex,
michael@0 4561 'p' + self.pageIndex + '_',
michael@0 4562 self.idCounters,
michael@0 4563 self.fontCache);
michael@0 4564
michael@0 4565 return partialEvaluator.getTextContent(contentStream,
michael@0 4566 self.resources);
michael@0 4567 });
michael@0 4568 },
michael@0 4569
michael@0 4570 getAnnotationsData: function Page_getAnnotationsData() {
michael@0 4571 var annotations = this.annotations;
michael@0 4572 var annotationsData = [];
michael@0 4573 for (var i = 0, n = annotations.length; i < n; ++i) {
michael@0 4574 annotationsData.push(annotations[i].getData());
michael@0 4575 }
michael@0 4576 return annotationsData;
michael@0 4577 },
michael@0 4578
michael@0 4579 get annotations() {
michael@0 4580 var annotations = [];
michael@0 4581 var annotationRefs = (this.annotationRefs || []);
michael@0 4582 for (var i = 0, n = annotationRefs.length; i < n; ++i) {
michael@0 4583 var annotationRef = annotationRefs[i];
michael@0 4584 var annotation = Annotation.fromRef(this.xref, annotationRef);
michael@0 4585 if (annotation) {
michael@0 4586 annotations.push(annotation);
michael@0 4587 }
michael@0 4588 }
michael@0 4589 return shadow(this, 'annotations', annotations);
michael@0 4590 }
michael@0 4591 };
michael@0 4592
michael@0 4593 return Page;
michael@0 4594 })();
michael@0 4595
michael@0 4596 /**
michael@0 4597 * The `PDFDocument` holds all the data of the PDF file. Compared to the
michael@0 4598 * `PDFDoc`, this one doesn't have any job management code.
michael@0 4599 * Right now there exists one PDFDocument on the main thread + one object
michael@0 4600 * for each worker. If there is no worker support enabled, there are two
michael@0 4601 * `PDFDocument` objects on the main thread created.
michael@0 4602 */
michael@0 4603 var PDFDocument = (function PDFDocumentClosure() {
michael@0 4604 function PDFDocument(pdfManager, arg, password) {
michael@0 4605 if (isStream(arg)) {
michael@0 4606 init.call(this, pdfManager, arg, password);
michael@0 4607 } else if (isArrayBuffer(arg)) {
michael@0 4608 init.call(this, pdfManager, new Stream(arg), password);
michael@0 4609 } else {
michael@0 4610 error('PDFDocument: Unknown argument type');
michael@0 4611 }
michael@0 4612 }
michael@0 4613
michael@0 4614 function init(pdfManager, stream, password) {
michael@0 4615 assert(stream.length > 0, 'stream must have data');
michael@0 4616 this.pdfManager = pdfManager;
michael@0 4617 this.stream = stream;
michael@0 4618 var xref = new XRef(this.stream, password, pdfManager);
michael@0 4619 this.xref = xref;
michael@0 4620 }
michael@0 4621
michael@0 4622 function find(stream, needle, limit, backwards) {
michael@0 4623 var pos = stream.pos;
michael@0 4624 var end = stream.end;
michael@0 4625 var strBuf = [];
michael@0 4626 if (pos + limit > end) {
michael@0 4627 limit = end - pos;
michael@0 4628 }
michael@0 4629 for (var n = 0; n < limit; ++n) {
michael@0 4630 strBuf.push(String.fromCharCode(stream.getByte()));
michael@0 4631 }
michael@0 4632 var str = strBuf.join('');
michael@0 4633 stream.pos = pos;
michael@0 4634 var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
michael@0 4635 if (index == -1) {
michael@0 4636 return false; /* not found */
michael@0 4637 }
michael@0 4638 stream.pos += index;
michael@0 4639 return true; /* found */
michael@0 4640 }
michael@0 4641
michael@0 4642 var DocumentInfoValidators = {
michael@0 4643 get entries() {
michael@0 4644 // Lazily build this since all the validation functions below are not
michael@0 4645 // defined until after this file loads.
michael@0 4646 return shadow(this, 'entries', {
michael@0 4647 Title: isString,
michael@0 4648 Author: isString,
michael@0 4649 Subject: isString,
michael@0 4650 Keywords: isString,
michael@0 4651 Creator: isString,
michael@0 4652 Producer: isString,
michael@0 4653 CreationDate: isString,
michael@0 4654 ModDate: isString,
michael@0 4655 Trapped: isName
michael@0 4656 });
michael@0 4657 }
michael@0 4658 };
michael@0 4659
michael@0 4660 PDFDocument.prototype = {
michael@0 4661 parse: function PDFDocument_parse(recoveryMode) {
michael@0 4662 this.setup(recoveryMode);
michael@0 4663 try {
michael@0 4664 // checking if AcroForm is present
michael@0 4665 this.acroForm = this.catalog.catDict.get('AcroForm');
michael@0 4666 if (this.acroForm) {
michael@0 4667 this.xfa = this.acroForm.get('XFA');
michael@0 4668 var fields = this.acroForm.get('Fields');
michael@0 4669 if ((!fields || !isArray(fields) || fields.length === 0) &&
michael@0 4670 !this.xfa) {
michael@0 4671 // no fields and no XFA -- not a form (?)
michael@0 4672 this.acroForm = null;
michael@0 4673 }
michael@0 4674 }
michael@0 4675 } catch (ex) {
michael@0 4676 info('Something wrong with AcroForm entry');
michael@0 4677 this.acroForm = null;
michael@0 4678 }
michael@0 4679 },
michael@0 4680
michael@0 4681 get linearization() {
michael@0 4682 var length = this.stream.length;
michael@0 4683 var linearization = false;
michael@0 4684 if (length) {
michael@0 4685 try {
michael@0 4686 linearization = new Linearization(this.stream);
michael@0 4687 if (linearization.length != length) {
michael@0 4688 linearization = false;
michael@0 4689 }
michael@0 4690 } catch (err) {
michael@0 4691 if (err instanceof MissingDataException) {
michael@0 4692 throw err;
michael@0 4693 }
michael@0 4694
michael@0 4695 info('The linearization data is not available ' +
michael@0 4696 'or unreadable PDF data is found');
michael@0 4697 linearization = false;
michael@0 4698 }
michael@0 4699 }
michael@0 4700 // shadow the prototype getter with a data property
michael@0 4701 return shadow(this, 'linearization', linearization);
michael@0 4702 },
michael@0 4703 get startXRef() {
michael@0 4704 var stream = this.stream;
michael@0 4705 var startXRef = 0;
michael@0 4706 var linearization = this.linearization;
michael@0 4707 if (linearization) {
michael@0 4708 // Find end of first obj.
michael@0 4709 stream.reset();
michael@0 4710 if (find(stream, 'endobj', 1024)) {
michael@0 4711 startXRef = stream.pos + 6;
michael@0 4712 }
michael@0 4713 } else {
michael@0 4714 // Find startxref by jumping backward from the end of the file.
michael@0 4715 var step = 1024;
michael@0 4716 var found = false, pos = stream.end;
michael@0 4717 while (!found && pos > 0) {
michael@0 4718 pos -= step - 'startxref'.length;
michael@0 4719 if (pos < 0) {
michael@0 4720 pos = 0;
michael@0 4721 }
michael@0 4722 stream.pos = pos;
michael@0 4723 found = find(stream, 'startxref', step, true);
michael@0 4724 }
michael@0 4725 if (found) {
michael@0 4726 stream.skip(9);
michael@0 4727 var ch;
michael@0 4728 do {
michael@0 4729 ch = stream.getByte();
michael@0 4730 } while (Lexer.isSpace(ch));
michael@0 4731 var str = '';
michael@0 4732 while (ch >= 0x20 && ch <= 0x39) { // < '9'
michael@0 4733 str += String.fromCharCode(ch);
michael@0 4734 ch = stream.getByte();
michael@0 4735 }
michael@0 4736 startXRef = parseInt(str, 10);
michael@0 4737 if (isNaN(startXRef)) {
michael@0 4738 startXRef = 0;
michael@0 4739 }
michael@0 4740 }
michael@0 4741 }
michael@0 4742 // shadow the prototype getter with a data property
michael@0 4743 return shadow(this, 'startXRef', startXRef);
michael@0 4744 },
michael@0 4745 get mainXRefEntriesOffset() {
michael@0 4746 var mainXRefEntriesOffset = 0;
michael@0 4747 var linearization = this.linearization;
michael@0 4748 if (linearization) {
michael@0 4749 mainXRefEntriesOffset = linearization.mainXRefEntriesOffset;
michael@0 4750 }
michael@0 4751 // shadow the prototype getter with a data property
michael@0 4752 return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset);
michael@0 4753 },
michael@0 4754 // Find the header, remove leading garbage and setup the stream
michael@0 4755 // starting from the header.
michael@0 4756 checkHeader: function PDFDocument_checkHeader() {
michael@0 4757 var stream = this.stream;
michael@0 4758 stream.reset();
michael@0 4759 if (find(stream, '%PDF-', 1024)) {
michael@0 4760 // Found the header, trim off any garbage before it.
michael@0 4761 stream.moveStart();
michael@0 4762 // Reading file format version
michael@0 4763 var MAX_VERSION_LENGTH = 12;
michael@0 4764 var version = '', ch;
michael@0 4765 while ((ch = stream.getByte()) > 0x20) { // SPACE
michael@0 4766 if (version.length >= MAX_VERSION_LENGTH) {
michael@0 4767 break;
michael@0 4768 }
michael@0 4769 version += String.fromCharCode(ch);
michael@0 4770 }
michael@0 4771 // removing "%PDF-"-prefix
michael@0 4772 this.pdfFormatVersion = version.substring(5);
michael@0 4773 return;
michael@0 4774 }
michael@0 4775 // May not be a PDF file, continue anyway.
michael@0 4776 },
michael@0 4777 parseStartXRef: function PDFDocument_parseStartXRef() {
michael@0 4778 var startXRef = this.startXRef;
michael@0 4779 this.xref.setStartXRef(startXRef);
michael@0 4780 },
michael@0 4781 setup: function PDFDocument_setup(recoveryMode) {
michael@0 4782 this.xref.parse(recoveryMode);
michael@0 4783 this.catalog = new Catalog(this.pdfManager, this.xref);
michael@0 4784 },
michael@0 4785 get numPages() {
michael@0 4786 var linearization = this.linearization;
michael@0 4787 var num = linearization ? linearization.numPages : this.catalog.numPages;
michael@0 4788 // shadow the prototype getter
michael@0 4789 return shadow(this, 'numPages', num);
michael@0 4790 },
michael@0 4791 get documentInfo() {
michael@0 4792 var docInfo = {
michael@0 4793 PDFFormatVersion: this.pdfFormatVersion,
michael@0 4794 IsAcroFormPresent: !!this.acroForm,
michael@0 4795 IsXFAPresent: !!this.xfa
michael@0 4796 };
michael@0 4797 var infoDict;
michael@0 4798 try {
michael@0 4799 infoDict = this.xref.trailer.get('Info');
michael@0 4800 } catch (err) {
michael@0 4801 info('The document information dictionary is invalid.');
michael@0 4802 }
michael@0 4803 if (infoDict) {
michael@0 4804 var validEntries = DocumentInfoValidators.entries;
michael@0 4805 // Only fill the document info with valid entries from the spec.
michael@0 4806 for (var key in validEntries) {
michael@0 4807 if (infoDict.has(key)) {
michael@0 4808 var value = infoDict.get(key);
michael@0 4809 // Make sure the value conforms to the spec.
michael@0 4810 if (validEntries[key](value)) {
michael@0 4811 docInfo[key] = (typeof value !== 'string' ?
michael@0 4812 value : stringToPDFString(value));
michael@0 4813 } else {
michael@0 4814 info('Bad value in document info for "' + key + '"');
michael@0 4815 }
michael@0 4816 }
michael@0 4817 }
michael@0 4818 }
michael@0 4819 return shadow(this, 'documentInfo', docInfo);
michael@0 4820 },
michael@0 4821 get fingerprint() {
michael@0 4822 var xref = this.xref, hash, fileID = '';
michael@0 4823
michael@0 4824 if (xref.trailer.has('ID')) {
michael@0 4825 hash = stringToBytes(xref.trailer.get('ID')[0]);
michael@0 4826 } else {
michael@0 4827 hash = calculateMD5(this.stream.bytes.subarray(0, 100), 0, 100);
michael@0 4828 }
michael@0 4829
michael@0 4830 for (var i = 0, n = hash.length; i < n; i++) {
michael@0 4831 fileID += hash[i].toString(16);
michael@0 4832 }
michael@0 4833
michael@0 4834 return shadow(this, 'fingerprint', fileID);
michael@0 4835 },
michael@0 4836
michael@0 4837 getPage: function PDFDocument_getPage(pageIndex) {
michael@0 4838 return this.catalog.getPage(pageIndex);
michael@0 4839 },
michael@0 4840
michael@0 4841 cleanup: function PDFDocument_cleanup() {
michael@0 4842 return this.catalog.cleanup();
michael@0 4843 }
michael@0 4844 };
michael@0 4845
michael@0 4846 return PDFDocument;
michael@0 4847 })();
michael@0 4848
michael@0 4849
michael@0 4850
michael@0 4851 var Name = (function NameClosure() {
michael@0 4852 function Name(name) {
michael@0 4853 this.name = name;
michael@0 4854 }
michael@0 4855
michael@0 4856 Name.prototype = {};
michael@0 4857
michael@0 4858 var nameCache = {};
michael@0 4859
michael@0 4860 Name.get = function Name_get(name) {
michael@0 4861 var nameValue = nameCache[name];
michael@0 4862 return (nameValue ? nameValue : (nameCache[name] = new Name(name)));
michael@0 4863 };
michael@0 4864
michael@0 4865 return Name;
michael@0 4866 })();
michael@0 4867
michael@0 4868 var Cmd = (function CmdClosure() {
michael@0 4869 function Cmd(cmd) {
michael@0 4870 this.cmd = cmd;
michael@0 4871 }
michael@0 4872
michael@0 4873 Cmd.prototype = {};
michael@0 4874
michael@0 4875 var cmdCache = {};
michael@0 4876
michael@0 4877 Cmd.get = function Cmd_get(cmd) {
michael@0 4878 var cmdValue = cmdCache[cmd];
michael@0 4879 return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd)));
michael@0 4880 };
michael@0 4881
michael@0 4882 return Cmd;
michael@0 4883 })();
michael@0 4884
michael@0 4885 var Dict = (function DictClosure() {
michael@0 4886 var nonSerializable = function nonSerializableClosure() {
michael@0 4887 return nonSerializable; // creating closure on some variable
michael@0 4888 };
michael@0 4889
michael@0 4890 var GETALL_DICTIONARY_TYPES_WHITELIST = {
michael@0 4891 'Background': true,
michael@0 4892 'ExtGState': true,
michael@0 4893 'Halftone': true,
michael@0 4894 'Layout': true,
michael@0 4895 'Mask': true,
michael@0 4896 'Pagination': true,
michael@0 4897 'Printing': true
michael@0 4898 };
michael@0 4899
michael@0 4900 function isRecursionAllowedFor(dict) {
michael@0 4901 if (!isName(dict.Type)) {
michael@0 4902 return true;
michael@0 4903 }
michael@0 4904 var dictType = dict.Type.name;
michael@0 4905 return GETALL_DICTIONARY_TYPES_WHITELIST[dictType] === true;
michael@0 4906 }
michael@0 4907
michael@0 4908 // xref is optional
michael@0 4909 function Dict(xref) {
michael@0 4910 // Map should only be used internally, use functions below to access.
michael@0 4911 this.map = Object.create(null);
michael@0 4912 this.xref = xref;
michael@0 4913 this.objId = null;
michael@0 4914 this.__nonSerializable__ = nonSerializable; // disable cloning of the Dict
michael@0 4915 }
michael@0 4916
michael@0 4917 Dict.prototype = {
michael@0 4918 assignXref: function Dict_assignXref(newXref) {
michael@0 4919 this.xref = newXref;
michael@0 4920 },
michael@0 4921
michael@0 4922 // automatically dereferences Ref objects
michael@0 4923 get: function Dict_get(key1, key2, key3) {
michael@0 4924 var value;
michael@0 4925 var xref = this.xref;
michael@0 4926 if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
michael@0 4927 typeof key2 == 'undefined') {
michael@0 4928 return xref ? xref.fetchIfRef(value) : value;
michael@0 4929 }
michael@0 4930 if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map ||
michael@0 4931 typeof key3 == 'undefined') {
michael@0 4932 return xref ? xref.fetchIfRef(value) : value;
michael@0 4933 }
michael@0 4934 value = this.map[key3] || null;
michael@0 4935 return xref ? xref.fetchIfRef(value) : value;
michael@0 4936 },
michael@0 4937
michael@0 4938 // Same as get(), but returns a promise and uses fetchIfRefAsync().
michael@0 4939 getAsync: function Dict_getAsync(key1, key2, key3) {
michael@0 4940 var value;
michael@0 4941 var promise;
michael@0 4942 var xref = this.xref;
michael@0 4943 if (typeof (value = this.map[key1]) !== undefined || key1 in this.map ||
michael@0 4944 typeof key2 === undefined) {
michael@0 4945 if (xref) {
michael@0 4946 return xref.fetchIfRefAsync(value);
michael@0 4947 }
michael@0 4948 promise = new LegacyPromise();
michael@0 4949 promise.resolve(value);
michael@0 4950 return promise;
michael@0 4951 }
michael@0 4952 if (typeof (value = this.map[key2]) !== undefined || key2 in this.map ||
michael@0 4953 typeof key3 === undefined) {
michael@0 4954 if (xref) {
michael@0 4955 return xref.fetchIfRefAsync(value);
michael@0 4956 }
michael@0 4957 promise = new LegacyPromise();
michael@0 4958 promise.resolve(value);
michael@0 4959 return promise;
michael@0 4960 }
michael@0 4961 value = this.map[key3] || null;
michael@0 4962 if (xref) {
michael@0 4963 return xref.fetchIfRefAsync(value);
michael@0 4964 }
michael@0 4965 promise = new LegacyPromise();
michael@0 4966 promise.resolve(value);
michael@0 4967 return promise;
michael@0 4968 },
michael@0 4969
michael@0 4970 // no dereferencing
michael@0 4971 getRaw: function Dict_getRaw(key) {
michael@0 4972 return this.map[key];
michael@0 4973 },
michael@0 4974
michael@0 4975 // creates new map and dereferences all Refs
michael@0 4976 getAll: function Dict_getAll() {
michael@0 4977 var all = Object.create(null);
michael@0 4978 var queue = null;
michael@0 4979 var key, obj;
michael@0 4980 for (key in this.map) {
michael@0 4981 obj = this.get(key);
michael@0 4982 if (obj instanceof Dict) {
michael@0 4983 if (isRecursionAllowedFor(obj)) {
michael@0 4984 (queue || (queue = [])).push({target: all, key: key, obj: obj});
michael@0 4985 } else {
michael@0 4986 all[key] = this.getRaw(key);
michael@0 4987 }
michael@0 4988 } else {
michael@0 4989 all[key] = obj;
michael@0 4990 }
michael@0 4991 }
michael@0 4992 if (!queue) {
michael@0 4993 return all;
michael@0 4994 }
michael@0 4995
michael@0 4996 // trying to take cyclic references into the account
michael@0 4997 var processed = Object.create(null);
michael@0 4998 while (queue.length > 0) {
michael@0 4999 var item = queue.shift();
michael@0 5000 var itemObj = item.obj;
michael@0 5001 var objId = itemObj.objId;
michael@0 5002 if (objId && objId in processed) {
michael@0 5003 item.target[item.key] = processed[objId];
michael@0 5004 continue;
michael@0 5005 }
michael@0 5006 var dereferenced = Object.create(null);
michael@0 5007 for (key in itemObj.map) {
michael@0 5008 obj = itemObj.get(key);
michael@0 5009 if (obj instanceof Dict) {
michael@0 5010 if (isRecursionAllowedFor(obj)) {
michael@0 5011 queue.push({target: dereferenced, key: key, obj: obj});
michael@0 5012 } else {
michael@0 5013 dereferenced[key] = itemObj.getRaw(key);
michael@0 5014 }
michael@0 5015 } else {
michael@0 5016 dereferenced[key] = obj;
michael@0 5017 }
michael@0 5018 }
michael@0 5019 if (objId) {
michael@0 5020 processed[objId] = dereferenced;
michael@0 5021 }
michael@0 5022 item.target[item.key] = dereferenced;
michael@0 5023 }
michael@0 5024 return all;
michael@0 5025 },
michael@0 5026
michael@0 5027 set: function Dict_set(key, value) {
michael@0 5028 this.map[key] = value;
michael@0 5029 },
michael@0 5030
michael@0 5031 has: function Dict_has(key) {
michael@0 5032 return key in this.map;
michael@0 5033 },
michael@0 5034
michael@0 5035 forEach: function Dict_forEach(callback) {
michael@0 5036 for (var key in this.map) {
michael@0 5037 callback(key, this.get(key));
michael@0 5038 }
michael@0 5039 }
michael@0 5040 };
michael@0 5041
michael@0 5042 Dict.empty = new Dict(null);
michael@0 5043
michael@0 5044 return Dict;
michael@0 5045 })();
michael@0 5046
michael@0 5047 var Ref = (function RefClosure() {
michael@0 5048 function Ref(num, gen) {
michael@0 5049 this.num = num;
michael@0 5050 this.gen = gen;
michael@0 5051 }
michael@0 5052
michael@0 5053 Ref.prototype = {};
michael@0 5054
michael@0 5055 return Ref;
michael@0 5056 })();
michael@0 5057
michael@0 5058 // The reference is identified by number and generation.
michael@0 5059 // This structure stores only one instance of the reference.
michael@0 5060 var RefSet = (function RefSetClosure() {
michael@0 5061 function RefSet() {
michael@0 5062 this.dict = {};
michael@0 5063 }
michael@0 5064
michael@0 5065 RefSet.prototype = {
michael@0 5066 has: function RefSet_has(ref) {
michael@0 5067 return ('R' + ref.num + '.' + ref.gen) in this.dict;
michael@0 5068 },
michael@0 5069
michael@0 5070 put: function RefSet_put(ref) {
michael@0 5071 this.dict['R' + ref.num + '.' + ref.gen] = true;
michael@0 5072 },
michael@0 5073
michael@0 5074 remove: function RefSet_remove(ref) {
michael@0 5075 delete this.dict['R' + ref.num + '.' + ref.gen];
michael@0 5076 }
michael@0 5077 };
michael@0 5078
michael@0 5079 return RefSet;
michael@0 5080 })();
michael@0 5081
michael@0 5082 var RefSetCache = (function RefSetCacheClosure() {
michael@0 5083 function RefSetCache() {
michael@0 5084 this.dict = Object.create(null);
michael@0 5085 }
michael@0 5086
michael@0 5087 RefSetCache.prototype = {
michael@0 5088 get: function RefSetCache_get(ref) {
michael@0 5089 return this.dict['R' + ref.num + '.' + ref.gen];
michael@0 5090 },
michael@0 5091
michael@0 5092 has: function RefSetCache_has(ref) {
michael@0 5093 return ('R' + ref.num + '.' + ref.gen) in this.dict;
michael@0 5094 },
michael@0 5095
michael@0 5096 put: function RefSetCache_put(ref, obj) {
michael@0 5097 this.dict['R' + ref.num + '.' + ref.gen] = obj;
michael@0 5098 },
michael@0 5099
michael@0 5100 putAlias: function RefSetCache_putAlias(ref, aliasRef) {
michael@0 5101 this.dict['R' + ref.num + '.' + ref.gen] = this.get(aliasRef);
michael@0 5102 },
michael@0 5103
michael@0 5104 forEach: function RefSetCache_forEach(fn, thisArg) {
michael@0 5105 for (var i in this.dict) {
michael@0 5106 fn.call(thisArg, this.dict[i]);
michael@0 5107 }
michael@0 5108 },
michael@0 5109
michael@0 5110 clear: function RefSetCache_clear() {
michael@0 5111 this.dict = Object.create(null);
michael@0 5112 }
michael@0 5113 };
michael@0 5114
michael@0 5115 return RefSetCache;
michael@0 5116 })();
michael@0 5117
michael@0 5118 var Catalog = (function CatalogClosure() {
michael@0 5119 function Catalog(pdfManager, xref) {
michael@0 5120 this.pdfManager = pdfManager;
michael@0 5121 this.xref = xref;
michael@0 5122 this.catDict = xref.getCatalogObj();
michael@0 5123 this.fontCache = new RefSetCache();
michael@0 5124 assert(isDict(this.catDict),
michael@0 5125 'catalog object is not a dictionary');
michael@0 5126
michael@0 5127 this.pagePromises = [];
michael@0 5128 }
michael@0 5129
michael@0 5130 Catalog.prototype = {
michael@0 5131 get metadata() {
michael@0 5132 var streamRef = this.catDict.getRaw('Metadata');
michael@0 5133 if (!isRef(streamRef)) {
michael@0 5134 return shadow(this, 'metadata', null);
michael@0 5135 }
michael@0 5136
michael@0 5137 var encryptMetadata = (!this.xref.encrypt ? false :
michael@0 5138 this.xref.encrypt.encryptMetadata);
michael@0 5139
michael@0 5140 var stream = this.xref.fetch(streamRef, !encryptMetadata);
michael@0 5141 var metadata;
michael@0 5142 if (stream && isDict(stream.dict)) {
michael@0 5143 var type = stream.dict.get('Type');
michael@0 5144 var subtype = stream.dict.get('Subtype');
michael@0 5145
michael@0 5146 if (isName(type) && isName(subtype) &&
michael@0 5147 type.name === 'Metadata' && subtype.name === 'XML') {
michael@0 5148 // XXX: This should examine the charset the XML document defines,
michael@0 5149 // however since there are currently no real means to decode
michael@0 5150 // arbitrary charsets, let's just hope that the author of the PDF
michael@0 5151 // was reasonable enough to stick with the XML default charset,
michael@0 5152 // which is UTF-8.
michael@0 5153 try {
michael@0 5154 metadata = stringToUTF8String(bytesToString(stream.getBytes()));
michael@0 5155 } catch (e) {
michael@0 5156 info('Skipping invalid metadata.');
michael@0 5157 }
michael@0 5158 }
michael@0 5159 }
michael@0 5160
michael@0 5161 return shadow(this, 'metadata', metadata);
michael@0 5162 },
michael@0 5163 get toplevelPagesDict() {
michael@0 5164 var pagesObj = this.catDict.get('Pages');
michael@0 5165 assert(isDict(pagesObj), 'invalid top-level pages dictionary');
michael@0 5166 // shadow the prototype getter
michael@0 5167 return shadow(this, 'toplevelPagesDict', pagesObj);
michael@0 5168 },
michael@0 5169 get documentOutline() {
michael@0 5170 var obj = null;
michael@0 5171 try {
michael@0 5172 obj = this.readDocumentOutline();
michael@0 5173 } catch (ex) {
michael@0 5174 if (ex instanceof MissingDataException) {
michael@0 5175 throw ex;
michael@0 5176 }
michael@0 5177 warn('Unable to read document outline');
michael@0 5178 }
michael@0 5179 return shadow(this, 'documentOutline', obj);
michael@0 5180 },
michael@0 5181 readDocumentOutline: function Catalog_readDocumentOutline() {
michael@0 5182 var xref = this.xref;
michael@0 5183 var obj = this.catDict.get('Outlines');
michael@0 5184 var root = { items: [] };
michael@0 5185 if (isDict(obj)) {
michael@0 5186 obj = obj.getRaw('First');
michael@0 5187 var processed = new RefSet();
michael@0 5188 if (isRef(obj)) {
michael@0 5189 var queue = [{obj: obj, parent: root}];
michael@0 5190 // to avoid recursion keeping track of the items
michael@0 5191 // in the processed dictionary
michael@0 5192 processed.put(obj);
michael@0 5193 while (queue.length > 0) {
michael@0 5194 var i = queue.shift();
michael@0 5195 var outlineDict = xref.fetchIfRef(i.obj);
michael@0 5196 if (outlineDict === null) {
michael@0 5197 continue;
michael@0 5198 }
michael@0 5199 if (!outlineDict.has('Title')) {
michael@0 5200 error('Invalid outline item');
michael@0 5201 }
michael@0 5202 var dest = outlineDict.get('A');
michael@0 5203 if (dest) {
michael@0 5204 dest = dest.get('D');
michael@0 5205 } else if (outlineDict.has('Dest')) {
michael@0 5206 dest = outlineDict.getRaw('Dest');
michael@0 5207 if (isName(dest)) {
michael@0 5208 dest = dest.name;
michael@0 5209 }
michael@0 5210 }
michael@0 5211 var title = outlineDict.get('Title');
michael@0 5212 var outlineItem = {
michael@0 5213 dest: dest,
michael@0 5214 title: stringToPDFString(title),
michael@0 5215 color: outlineDict.get('C') || [0, 0, 0],
michael@0 5216 count: outlineDict.get('Count'),
michael@0 5217 bold: !!(outlineDict.get('F') & 2),
michael@0 5218 italic: !!(outlineDict.get('F') & 1),
michael@0 5219 items: []
michael@0 5220 };
michael@0 5221 i.parent.items.push(outlineItem);
michael@0 5222 obj = outlineDict.getRaw('First');
michael@0 5223 if (isRef(obj) && !processed.has(obj)) {
michael@0 5224 queue.push({obj: obj, parent: outlineItem});
michael@0 5225 processed.put(obj);
michael@0 5226 }
michael@0 5227 obj = outlineDict.getRaw('Next');
michael@0 5228 if (isRef(obj) && !processed.has(obj)) {
michael@0 5229 queue.push({obj: obj, parent: i.parent});
michael@0 5230 processed.put(obj);
michael@0 5231 }
michael@0 5232 }
michael@0 5233 }
michael@0 5234 }
michael@0 5235 return (root.items.length > 0 ? root.items : null);
michael@0 5236 },
michael@0 5237 get numPages() {
michael@0 5238 var obj = this.toplevelPagesDict.get('Count');
michael@0 5239 assert(
michael@0 5240 isInt(obj),
michael@0 5241 'page count in top level pages object is not an integer'
michael@0 5242 );
michael@0 5243 // shadow the prototype getter
michael@0 5244 return shadow(this, 'num', obj);
michael@0 5245 },
michael@0 5246 get destinations() {
michael@0 5247 function fetchDestination(dest) {
michael@0 5248 return isDict(dest) ? dest.get('D') : dest;
michael@0 5249 }
michael@0 5250
michael@0 5251 var xref = this.xref;
michael@0 5252 var dests = {}, nameTreeRef, nameDictionaryRef;
michael@0 5253 var obj = this.catDict.get('Names');
michael@0 5254 if (obj) {
michael@0 5255 nameTreeRef = obj.getRaw('Dests');
michael@0 5256 } else if (this.catDict.has('Dests')) {
michael@0 5257 nameDictionaryRef = this.catDict.get('Dests');
michael@0 5258 }
michael@0 5259
michael@0 5260 if (nameDictionaryRef) {
michael@0 5261 // reading simple destination dictionary
michael@0 5262 obj = nameDictionaryRef;
michael@0 5263 obj.forEach(function catalogForEach(key, value) {
michael@0 5264 if (!value) {
michael@0 5265 return;
michael@0 5266 }
michael@0 5267 dests[key] = fetchDestination(value);
michael@0 5268 });
michael@0 5269 }
michael@0 5270 if (nameTreeRef) {
michael@0 5271 var nameTree = new NameTree(nameTreeRef, xref);
michael@0 5272 var names = nameTree.getAll();
michael@0 5273 for (var name in names) {
michael@0 5274 if (!names.hasOwnProperty(name)) {
michael@0 5275 continue;
michael@0 5276 }
michael@0 5277 dests[name] = fetchDestination(names[name]);
michael@0 5278 }
michael@0 5279 }
michael@0 5280 return shadow(this, 'destinations', dests);
michael@0 5281 },
michael@0 5282 get attachments() {
michael@0 5283 var xref = this.xref;
michael@0 5284 var attachments, nameTreeRef;
michael@0 5285 var obj = this.catDict.get('Names');
michael@0 5286 if (obj) {
michael@0 5287 nameTreeRef = obj.getRaw('EmbeddedFiles');
michael@0 5288 }
michael@0 5289
michael@0 5290 if (nameTreeRef) {
michael@0 5291 var nameTree = new NameTree(nameTreeRef, xref);
michael@0 5292 var names = nameTree.getAll();
michael@0 5293 for (var name in names) {
michael@0 5294 if (!names.hasOwnProperty(name)) {
michael@0 5295 continue;
michael@0 5296 }
michael@0 5297 var fs = new FileSpec(names[name], xref);
michael@0 5298 if (!attachments) {
michael@0 5299 attachments = {};
michael@0 5300 }
michael@0 5301 attachments[stringToPDFString(name)] = fs.serializable;
michael@0 5302 }
michael@0 5303 }
michael@0 5304 return shadow(this, 'attachments', attachments);
michael@0 5305 },
michael@0 5306 get javaScript() {
michael@0 5307 var xref = this.xref;
michael@0 5308 var obj = this.catDict.get('Names');
michael@0 5309
michael@0 5310 var javaScript = [];
michael@0 5311 if (obj && obj.has('JavaScript')) {
michael@0 5312 var nameTree = new NameTree(obj.getRaw('JavaScript'), xref);
michael@0 5313 var names = nameTree.getAll();
michael@0 5314 for (var name in names) {
michael@0 5315 if (!names.hasOwnProperty(name)) {
michael@0 5316 continue;
michael@0 5317 }
michael@0 5318 // We don't really use the JavaScript right now. This code is
michael@0 5319 // defensive so we don't cause errors on document load.
michael@0 5320 var jsDict = names[name];
michael@0 5321 if (!isDict(jsDict)) {
michael@0 5322 continue;
michael@0 5323 }
michael@0 5324 var type = jsDict.get('S');
michael@0 5325 if (!isName(type) || type.name !== 'JavaScript') {
michael@0 5326 continue;
michael@0 5327 }
michael@0 5328 var js = jsDict.get('JS');
michael@0 5329 if (!isString(js) && !isStream(js)) {
michael@0 5330 continue;
michael@0 5331 }
michael@0 5332 if (isStream(js)) {
michael@0 5333 js = bytesToString(js.getBytes());
michael@0 5334 }
michael@0 5335 javaScript.push(stringToPDFString(js));
michael@0 5336 }
michael@0 5337 }
michael@0 5338 return shadow(this, 'javaScript', javaScript);
michael@0 5339 },
michael@0 5340
michael@0 5341 cleanup: function Catalog_cleanup() {
michael@0 5342 this.fontCache.forEach(function (font) {
michael@0 5343 delete font.sent;
michael@0 5344 delete font.translated;
michael@0 5345 });
michael@0 5346 this.fontCache.clear();
michael@0 5347 },
michael@0 5348
michael@0 5349 getPage: function Catalog_getPage(pageIndex) {
michael@0 5350 if (!(pageIndex in this.pagePromises)) {
michael@0 5351 this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then(
michael@0 5352 function (a) {
michael@0 5353 var dict = a[0];
michael@0 5354 var ref = a[1];
michael@0 5355 return new Page(this.pdfManager, this.xref, pageIndex, dict, ref,
michael@0 5356 this.fontCache);
michael@0 5357 }.bind(this)
michael@0 5358 );
michael@0 5359 }
michael@0 5360 return this.pagePromises[pageIndex];
michael@0 5361 },
michael@0 5362
michael@0 5363 getPageDict: function Catalog_getPageDict(pageIndex) {
michael@0 5364 var promise = new LegacyPromise();
michael@0 5365 var nodesToVisit = [this.catDict.getRaw('Pages')];
michael@0 5366 var currentPageIndex = 0;
michael@0 5367 var xref = this.xref;
michael@0 5368
michael@0 5369 function next() {
michael@0 5370 while (nodesToVisit.length) {
michael@0 5371 var currentNode = nodesToVisit.pop();
michael@0 5372
michael@0 5373 if (isRef(currentNode)) {
michael@0 5374 xref.fetchAsync(currentNode).then(function (obj) {
michael@0 5375 if ((isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids')))) {
michael@0 5376 if (pageIndex === currentPageIndex) {
michael@0 5377 promise.resolve([obj, currentNode]);
michael@0 5378 } else {
michael@0 5379 currentPageIndex++;
michael@0 5380 next();
michael@0 5381 }
michael@0 5382 return;
michael@0 5383 }
michael@0 5384 nodesToVisit.push(obj);
michael@0 5385 next();
michael@0 5386 }.bind(this), promise.reject.bind(promise));
michael@0 5387 return;
michael@0 5388 }
michael@0 5389
michael@0 5390 // must be a child page dictionary
michael@0 5391 assert(
michael@0 5392 isDict(currentNode),
michael@0 5393 'page dictionary kid reference points to wrong type of object'
michael@0 5394 );
michael@0 5395 var count = currentNode.get('Count');
michael@0 5396 // Skip nodes where the page can't be.
michael@0 5397 if (currentPageIndex + count <= pageIndex) {
michael@0 5398 currentPageIndex += count;
michael@0 5399 continue;
michael@0 5400 }
michael@0 5401
michael@0 5402 var kids = currentNode.get('Kids');
michael@0 5403 assert(isArray(kids), 'page dictionary kids object is not an array');
michael@0 5404 if (count === kids.length) {
michael@0 5405 // Nodes that don't have the page have been skipped and this is the
michael@0 5406 // bottom of the tree which means the page requested must be a
michael@0 5407 // descendant of this pages node. Ideally we would just resolve the
michael@0 5408 // promise with the page ref here, but there is the case where more
michael@0 5409 // pages nodes could link to single a page (see issue 3666 pdf). To
michael@0 5410 // handle this push it back on the queue so if it is a pages node it
michael@0 5411 // will be descended into.
michael@0 5412 nodesToVisit = [kids[pageIndex - currentPageIndex]];
michael@0 5413 currentPageIndex = pageIndex;
michael@0 5414 continue;
michael@0 5415 } else {
michael@0 5416 for (var last = kids.length - 1; last >= 0; last--) {
michael@0 5417 nodesToVisit.push(kids[last]);
michael@0 5418 }
michael@0 5419 }
michael@0 5420 }
michael@0 5421 promise.reject('Page index ' + pageIndex + ' not found.');
michael@0 5422 }
michael@0 5423 next();
michael@0 5424 return promise;
michael@0 5425 },
michael@0 5426
michael@0 5427 getPageIndex: function Catalog_getPageIndex(ref) {
michael@0 5428 // The page tree nodes have the count of all the leaves below them. To get
michael@0 5429 // how many pages are before we just have to walk up the tree and keep
michael@0 5430 // adding the count of siblings to the left of the node.
michael@0 5431 var xref = this.xref;
michael@0 5432 function pagesBeforeRef(kidRef) {
michael@0 5433 var total = 0;
michael@0 5434 var parentRef;
michael@0 5435 return xref.fetchAsync(kidRef).then(function (node) {
michael@0 5436 if (!node) {
michael@0 5437 return null;
michael@0 5438 }
michael@0 5439 parentRef = node.getRaw('Parent');
michael@0 5440 return node.getAsync('Parent');
michael@0 5441 }).then(function (parent) {
michael@0 5442 if (!parent) {
michael@0 5443 return null;
michael@0 5444 }
michael@0 5445 return parent.getAsync('Kids');
michael@0 5446 }).then(function (kids) {
michael@0 5447 if (!kids) {
michael@0 5448 return null;
michael@0 5449 }
michael@0 5450 var kidPromises = [];
michael@0 5451 var found = false;
michael@0 5452 for (var i = 0; i < kids.length; i++) {
michael@0 5453 var kid = kids[i];
michael@0 5454 assert(isRef(kid), 'kids must be a ref');
michael@0 5455 if (kid.num == kidRef.num) {
michael@0 5456 found = true;
michael@0 5457 break;
michael@0 5458 }
michael@0 5459 kidPromises.push(xref.fetchAsync(kid).then(function (kid) {
michael@0 5460 if (kid.has('Count')) {
michael@0 5461 var count = kid.get('Count');
michael@0 5462 total += count;
michael@0 5463 } else { // page leaf node
michael@0 5464 total++;
michael@0 5465 }
michael@0 5466 }));
michael@0 5467 }
michael@0 5468 if (!found) {
michael@0 5469 error('kid ref not found in parents kids');
michael@0 5470 }
michael@0 5471 return Promise.all(kidPromises).then(function () {
michael@0 5472 return [total, parentRef];
michael@0 5473 });
michael@0 5474 });
michael@0 5475 }
michael@0 5476
michael@0 5477 var total = 0;
michael@0 5478 function next(ref) {
michael@0 5479 return pagesBeforeRef(ref).then(function (args) {
michael@0 5480 if (!args) {
michael@0 5481 return total;
michael@0 5482 }
michael@0 5483 var count = args[0];
michael@0 5484 var parentRef = args[1];
michael@0 5485 total += count;
michael@0 5486 return next(parentRef);
michael@0 5487 });
michael@0 5488 }
michael@0 5489
michael@0 5490 return next(ref);
michael@0 5491 }
michael@0 5492 };
michael@0 5493
michael@0 5494 return Catalog;
michael@0 5495 })();
michael@0 5496
michael@0 5497 var XRef = (function XRefClosure() {
michael@0 5498 function XRef(stream, password) {
michael@0 5499 this.stream = stream;
michael@0 5500 this.entries = [];
michael@0 5501 this.xrefstms = {};
michael@0 5502 // prepare the XRef cache
michael@0 5503 this.cache = [];
michael@0 5504 this.password = password;
michael@0 5505 }
michael@0 5506
michael@0 5507 XRef.prototype = {
michael@0 5508 setStartXRef: function XRef_setStartXRef(startXRef) {
michael@0 5509 // Store the starting positions of xref tables as we process them
michael@0 5510 // so we can recover from missing data errors
michael@0 5511 this.startXRefQueue = [startXRef];
michael@0 5512 },
michael@0 5513
michael@0 5514 parse: function XRef_parse(recoveryMode) {
michael@0 5515 var trailerDict;
michael@0 5516 if (!recoveryMode) {
michael@0 5517 trailerDict = this.readXRef();
michael@0 5518 } else {
michael@0 5519 warn('Indexing all PDF objects');
michael@0 5520 trailerDict = this.indexObjects();
michael@0 5521 }
michael@0 5522 trailerDict.assignXref(this);
michael@0 5523 this.trailer = trailerDict;
michael@0 5524 var encrypt = trailerDict.get('Encrypt');
michael@0 5525 if (encrypt) {
michael@0 5526 var ids = trailerDict.get('ID');
michael@0 5527 var fileId = (ids && ids.length) ? ids[0] : '';
michael@0 5528 this.encrypt = new CipherTransformFactory(encrypt, fileId,
michael@0 5529 this.password);
michael@0 5530 }
michael@0 5531
michael@0 5532 // get the root dictionary (catalog) object
michael@0 5533 if (!(this.root = trailerDict.get('Root'))) {
michael@0 5534 error('Invalid root reference');
michael@0 5535 }
michael@0 5536 },
michael@0 5537
michael@0 5538 processXRefTable: function XRef_processXRefTable(parser) {
michael@0 5539 if (!('tableState' in this)) {
michael@0 5540 // Stores state of the table as we process it so we can resume
michael@0 5541 // from middle of table in case of missing data error
michael@0 5542 this.tableState = {
michael@0 5543 entryNum: 0,
michael@0 5544 streamPos: parser.lexer.stream.pos,
michael@0 5545 parserBuf1: parser.buf1,
michael@0 5546 parserBuf2: parser.buf2
michael@0 5547 };
michael@0 5548 }
michael@0 5549
michael@0 5550 var obj = this.readXRefTable(parser);
michael@0 5551
michael@0 5552 // Sanity check
michael@0 5553 if (!isCmd(obj, 'trailer')) {
michael@0 5554 error('Invalid XRef table: could not find trailer dictionary');
michael@0 5555 }
michael@0 5556 // Read trailer dictionary, e.g.
michael@0 5557 // trailer
michael@0 5558 // << /Size 22
michael@0 5559 // /Root 20R
michael@0 5560 // /Info 10R
michael@0 5561 // /ID [ <81b14aafa313db63dbd6f981e49f94f4> ]
michael@0 5562 // >>
michael@0 5563 // The parser goes through the entire stream << ... >> and provides
michael@0 5564 // a getter interface for the key-value table
michael@0 5565 var dict = parser.getObj();
michael@0 5566 if (!isDict(dict)) {
michael@0 5567 error('Invalid XRef table: could not parse trailer dictionary');
michael@0 5568 }
michael@0 5569 delete this.tableState;
michael@0 5570
michael@0 5571 return dict;
michael@0 5572 },
michael@0 5573
michael@0 5574 readXRefTable: function XRef_readXRefTable(parser) {
michael@0 5575 // Example of cross-reference table:
michael@0 5576 // xref
michael@0 5577 // 0 1 <-- subsection header (first obj #, obj count)
michael@0 5578 // 0000000000 65535 f <-- actual object (offset, generation #, f/n)
michael@0 5579 // 23 2 <-- subsection header ... and so on ...
michael@0 5580 // 0000025518 00002 n
michael@0 5581 // 0000025635 00000 n
michael@0 5582 // trailer
michael@0 5583 // ...
michael@0 5584
michael@0 5585 var stream = parser.lexer.stream;
michael@0 5586 var tableState = this.tableState;
michael@0 5587 stream.pos = tableState.streamPos;
michael@0 5588 parser.buf1 = tableState.parserBuf1;
michael@0 5589 parser.buf2 = tableState.parserBuf2;
michael@0 5590
michael@0 5591 // Outer loop is over subsection headers
michael@0 5592 var obj;
michael@0 5593
michael@0 5594 while (true) {
michael@0 5595 if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) {
michael@0 5596 if (isCmd(obj = parser.getObj(), 'trailer')) {
michael@0 5597 break;
michael@0 5598 }
michael@0 5599 tableState.firstEntryNum = obj;
michael@0 5600 tableState.entryCount = parser.getObj();
michael@0 5601 }
michael@0 5602
michael@0 5603 var first = tableState.firstEntryNum;
michael@0 5604 var count = tableState.entryCount;
michael@0 5605 if (!isInt(first) || !isInt(count)) {
michael@0 5606 error('Invalid XRef table: wrong types in subsection header');
michael@0 5607 }
michael@0 5608 // Inner loop is over objects themselves
michael@0 5609 for (var i = tableState.entryNum; i < count; i++) {
michael@0 5610 tableState.streamPos = stream.pos;
michael@0 5611 tableState.entryNum = i;
michael@0 5612 tableState.parserBuf1 = parser.buf1;
michael@0 5613 tableState.parserBuf2 = parser.buf2;
michael@0 5614
michael@0 5615 var entry = {};
michael@0 5616 entry.offset = parser.getObj();
michael@0 5617 entry.gen = parser.getObj();
michael@0 5618 var type = parser.getObj();
michael@0 5619
michael@0 5620 if (isCmd(type, 'f')) {
michael@0 5621 entry.free = true;
michael@0 5622 } else if (isCmd(type, 'n')) {
michael@0 5623 entry.uncompressed = true;
michael@0 5624 }
michael@0 5625
michael@0 5626 // Validate entry obj
michael@0 5627 if (!isInt(entry.offset) || !isInt(entry.gen) ||
michael@0 5628 !(entry.free || entry.uncompressed)) {
michael@0 5629 console.log(entry.offset, entry.gen, entry.free,
michael@0 5630 entry.uncompressed);
michael@0 5631 error('Invalid entry in XRef subsection: ' + first + ', ' + count);
michael@0 5632 }
michael@0 5633
michael@0 5634 if (!this.entries[i + first]) {
michael@0 5635 this.entries[i + first] = entry;
michael@0 5636 }
michael@0 5637 }
michael@0 5638
michael@0 5639 tableState.entryNum = 0;
michael@0 5640 tableState.streamPos = stream.pos;
michael@0 5641 tableState.parserBuf1 = parser.buf1;
michael@0 5642 tableState.parserBuf2 = parser.buf2;
michael@0 5643 delete tableState.firstEntryNum;
michael@0 5644 delete tableState.entryCount;
michael@0 5645 }
michael@0 5646
michael@0 5647 // Per issue 3248: hp scanners generate bad XRef
michael@0 5648 if (first === 1 && this.entries[1] && this.entries[1].free) {
michael@0 5649 // shifting the entries
michael@0 5650 this.entries.shift();
michael@0 5651 }
michael@0 5652
michael@0 5653 // Sanity check: as per spec, first object must be free
michael@0 5654 if (this.entries[0] && !this.entries[0].free) {
michael@0 5655 error('Invalid XRef table: unexpected first object');
michael@0 5656 }
michael@0 5657 return obj;
michael@0 5658 },
michael@0 5659
michael@0 5660 processXRefStream: function XRef_processXRefStream(stream) {
michael@0 5661 if (!('streamState' in this)) {
michael@0 5662 // Stores state of the stream as we process it so we can resume
michael@0 5663 // from middle of stream in case of missing data error
michael@0 5664 var streamParameters = stream.dict;
michael@0 5665 var byteWidths = streamParameters.get('W');
michael@0 5666 var range = streamParameters.get('Index');
michael@0 5667 if (!range) {
michael@0 5668 range = [0, streamParameters.get('Size')];
michael@0 5669 }
michael@0 5670
michael@0 5671 this.streamState = {
michael@0 5672 entryRanges: range,
michael@0 5673 byteWidths: byteWidths,
michael@0 5674 entryNum: 0,
michael@0 5675 streamPos: stream.pos
michael@0 5676 };
michael@0 5677 }
michael@0 5678 this.readXRefStream(stream);
michael@0 5679 delete this.streamState;
michael@0 5680
michael@0 5681 return stream.dict;
michael@0 5682 },
michael@0 5683
michael@0 5684 readXRefStream: function XRef_readXRefStream(stream) {
michael@0 5685 var i, j;
michael@0 5686 var streamState = this.streamState;
michael@0 5687 stream.pos = streamState.streamPos;
michael@0 5688
michael@0 5689 var byteWidths = streamState.byteWidths;
michael@0 5690 var typeFieldWidth = byteWidths[0];
michael@0 5691 var offsetFieldWidth = byteWidths[1];
michael@0 5692 var generationFieldWidth = byteWidths[2];
michael@0 5693
michael@0 5694 var entryRanges = streamState.entryRanges;
michael@0 5695 while (entryRanges.length > 0) {
michael@0 5696 var first = entryRanges[0];
michael@0 5697 var n = entryRanges[1];
michael@0 5698
michael@0 5699 if (!isInt(first) || !isInt(n)) {
michael@0 5700 error('Invalid XRef range fields: ' + first + ', ' + n);
michael@0 5701 }
michael@0 5702 if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) ||
michael@0 5703 !isInt(generationFieldWidth)) {
michael@0 5704 error('Invalid XRef entry fields length: ' + first + ', ' + n);
michael@0 5705 }
michael@0 5706 for (i = streamState.entryNum; i < n; ++i) {
michael@0 5707 streamState.entryNum = i;
michael@0 5708 streamState.streamPos = stream.pos;
michael@0 5709
michael@0 5710 var type = 0, offset = 0, generation = 0;
michael@0 5711 for (j = 0; j < typeFieldWidth; ++j) {
michael@0 5712 type = (type << 8) | stream.getByte();
michael@0 5713 }
michael@0 5714 // if type field is absent, its default value is 1
michael@0 5715 if (typeFieldWidth === 0) {
michael@0 5716 type = 1;
michael@0 5717 }
michael@0 5718 for (j = 0; j < offsetFieldWidth; ++j) {
michael@0 5719 offset = (offset << 8) | stream.getByte();
michael@0 5720 }
michael@0 5721 for (j = 0; j < generationFieldWidth; ++j) {
michael@0 5722 generation = (generation << 8) | stream.getByte();
michael@0 5723 }
michael@0 5724 var entry = {};
michael@0 5725 entry.offset = offset;
michael@0 5726 entry.gen = generation;
michael@0 5727 switch (type) {
michael@0 5728 case 0:
michael@0 5729 entry.free = true;
michael@0 5730 break;
michael@0 5731 case 1:
michael@0 5732 entry.uncompressed = true;
michael@0 5733 break;
michael@0 5734 case 2:
michael@0 5735 break;
michael@0 5736 default:
michael@0 5737 error('Invalid XRef entry type: ' + type);
michael@0 5738 }
michael@0 5739 if (!this.entries[first + i]) {
michael@0 5740 this.entries[first + i] = entry;
michael@0 5741 }
michael@0 5742 }
michael@0 5743
michael@0 5744 streamState.entryNum = 0;
michael@0 5745 streamState.streamPos = stream.pos;
michael@0 5746 entryRanges.splice(0, 2);
michael@0 5747 }
michael@0 5748 },
michael@0 5749
michael@0 5750 indexObjects: function XRef_indexObjects() {
michael@0 5751 // Simple scan through the PDF content to find objects,
michael@0 5752 // trailers and XRef streams.
michael@0 5753 function readToken(data, offset) {
michael@0 5754 var token = '', ch = data[offset];
michael@0 5755 while (ch !== 13 && ch !== 10) {
michael@0 5756 if (++offset >= data.length) {
michael@0 5757 break;
michael@0 5758 }
michael@0 5759 token += String.fromCharCode(ch);
michael@0 5760 ch = data[offset];
michael@0 5761 }
michael@0 5762 return token;
michael@0 5763 }
michael@0 5764 function skipUntil(data, offset, what) {
michael@0 5765 var length = what.length, dataLength = data.length;
michael@0 5766 var skipped = 0;
michael@0 5767 // finding byte sequence
michael@0 5768 while (offset < dataLength) {
michael@0 5769 var i = 0;
michael@0 5770 while (i < length && data[offset + i] == what[i]) {
michael@0 5771 ++i;
michael@0 5772 }
michael@0 5773 if (i >= length) {
michael@0 5774 break; // sequence found
michael@0 5775 }
michael@0 5776 offset++;
michael@0 5777 skipped++;
michael@0 5778 }
michael@0 5779 return skipped;
michael@0 5780 }
michael@0 5781 var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
michael@0 5782 var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114,
michael@0 5783 101, 102]);
michael@0 5784 var endobjBytes = new Uint8Array([101, 110, 100, 111, 98, 106]);
michael@0 5785 var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
michael@0 5786
michael@0 5787 var stream = this.stream;
michael@0 5788 stream.pos = 0;
michael@0 5789 var buffer = stream.getBytes();
michael@0 5790 var position = stream.start, length = buffer.length;
michael@0 5791 var trailers = [], xrefStms = [];
michael@0 5792 while (position < length) {
michael@0 5793 var ch = buffer[position];
michael@0 5794 if (ch === 32 || ch === 9 || ch === 13 || ch === 10) {
michael@0 5795 ++position;
michael@0 5796 continue;
michael@0 5797 }
michael@0 5798 if (ch === 37) { // %-comment
michael@0 5799 do {
michael@0 5800 ++position;
michael@0 5801 if (position >= length) {
michael@0 5802 break;
michael@0 5803 }
michael@0 5804 ch = buffer[position];
michael@0 5805 } while (ch !== 13 && ch !== 10);
michael@0 5806 continue;
michael@0 5807 }
michael@0 5808 var token = readToken(buffer, position);
michael@0 5809 var m;
michael@0 5810 if (token === 'xref') {
michael@0 5811 position += skipUntil(buffer, position, trailerBytes);
michael@0 5812 trailers.push(position);
michael@0 5813 position += skipUntil(buffer, position, startxrefBytes);
michael@0 5814 } else if ((m = /^(\d+)\s+(\d+)\s+obj\b/.exec(token))) {
michael@0 5815 this.entries[m[1]] = {
michael@0 5816 offset: position,
michael@0 5817 gen: m[2] | 0,
michael@0 5818 uncompressed: true
michael@0 5819 };
michael@0 5820
michael@0 5821 var contentLength = skipUntil(buffer, position, endobjBytes) + 7;
michael@0 5822 var content = buffer.subarray(position, position + contentLength);
michael@0 5823
michael@0 5824 // checking XRef stream suspect
michael@0 5825 // (it shall have '/XRef' and next char is not a letter)
michael@0 5826 var xrefTagOffset = skipUntil(content, 0, xrefBytes);
michael@0 5827 if (xrefTagOffset < contentLength &&
michael@0 5828 content[xrefTagOffset + 5] < 64) {
michael@0 5829 xrefStms.push(position);
michael@0 5830 this.xrefstms[position] = 1; // don't read it recursively
michael@0 5831 }
michael@0 5832
michael@0 5833 position += contentLength;
michael@0 5834 } else {
michael@0 5835 position += token.length + 1;
michael@0 5836 }
michael@0 5837 }
michael@0 5838 // reading XRef streams
michael@0 5839 var i, ii;
michael@0 5840 for (i = 0, ii = xrefStms.length; i < ii; ++i) {
michael@0 5841 this.startXRefQueue.push(xrefStms[i]);
michael@0 5842 this.readXRef(/* recoveryMode */ true);
michael@0 5843 }
michael@0 5844 // finding main trailer
michael@0 5845 var dict;
michael@0 5846 for (i = 0, ii = trailers.length; i < ii; ++i) {
michael@0 5847 stream.pos = trailers[i];
michael@0 5848 var parser = new Parser(new Lexer(stream), true, null);
michael@0 5849 var obj = parser.getObj();
michael@0 5850 if (!isCmd(obj, 'trailer')) {
michael@0 5851 continue;
michael@0 5852 }
michael@0 5853 // read the trailer dictionary
michael@0 5854 if (!isDict(dict = parser.getObj())) {
michael@0 5855 continue;
michael@0 5856 }
michael@0 5857 // taking the first one with 'ID'
michael@0 5858 if (dict.has('ID')) {
michael@0 5859 return dict;
michael@0 5860 }
michael@0 5861 }
michael@0 5862 // no tailer with 'ID', taking last one (if exists)
michael@0 5863 if (dict) {
michael@0 5864 return dict;
michael@0 5865 }
michael@0 5866 // nothing helps
michael@0 5867 // calling error() would reject worker with an UnknownErrorException.
michael@0 5868 throw new InvalidPDFException('Invalid PDF structure');
michael@0 5869 },
michael@0 5870
michael@0 5871 readXRef: function XRef_readXRef(recoveryMode) {
michael@0 5872 var stream = this.stream;
michael@0 5873
michael@0 5874 try {
michael@0 5875 while (this.startXRefQueue.length) {
michael@0 5876 var startXRef = this.startXRefQueue[0];
michael@0 5877
michael@0 5878 stream.pos = startXRef + stream.start;
michael@0 5879
michael@0 5880 var parser = new Parser(new Lexer(stream), true, null);
michael@0 5881 var obj = parser.getObj();
michael@0 5882 var dict;
michael@0 5883
michael@0 5884 // Get dictionary
michael@0 5885 if (isCmd(obj, 'xref')) {
michael@0 5886 // Parse end-of-file XRef
michael@0 5887 dict = this.processXRefTable(parser);
michael@0 5888 if (!this.topDict) {
michael@0 5889 this.topDict = dict;
michael@0 5890 }
michael@0 5891
michael@0 5892 // Recursively get other XRefs 'XRefStm', if any
michael@0 5893 obj = dict.get('XRefStm');
michael@0 5894 if (isInt(obj)) {
michael@0 5895 var pos = obj;
michael@0 5896 // ignore previously loaded xref streams
michael@0 5897 // (possible infinite recursion)
michael@0 5898 if (!(pos in this.xrefstms)) {
michael@0 5899 this.xrefstms[pos] = 1;
michael@0 5900 this.startXRefQueue.push(pos);
michael@0 5901 }
michael@0 5902 }
michael@0 5903 } else if (isInt(obj)) {
michael@0 5904 // Parse in-stream XRef
michael@0 5905 if (!isInt(parser.getObj()) ||
michael@0 5906 !isCmd(parser.getObj(), 'obj') ||
michael@0 5907 !isStream(obj = parser.getObj())) {
michael@0 5908 error('Invalid XRef stream');
michael@0 5909 }
michael@0 5910 dict = this.processXRefStream(obj);
michael@0 5911 if (!this.topDict) {
michael@0 5912 this.topDict = dict;
michael@0 5913 }
michael@0 5914 if (!dict) {
michael@0 5915 error('Failed to read XRef stream');
michael@0 5916 }
michael@0 5917 } else {
michael@0 5918 error('Invalid XRef stream header');
michael@0 5919 }
michael@0 5920
michael@0 5921 // Recursively get previous dictionary, if any
michael@0 5922 obj = dict.get('Prev');
michael@0 5923 if (isInt(obj)) {
michael@0 5924 this.startXRefQueue.push(obj);
michael@0 5925 } else if (isRef(obj)) {
michael@0 5926 // The spec says Prev must not be a reference, i.e. "/Prev NNN"
michael@0 5927 // This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R"
michael@0 5928 this.startXRefQueue.push(obj.num);
michael@0 5929 }
michael@0 5930
michael@0 5931 this.startXRefQueue.shift();
michael@0 5932 }
michael@0 5933
michael@0 5934 return this.topDict;
michael@0 5935 } catch (e) {
michael@0 5936 if (e instanceof MissingDataException) {
michael@0 5937 throw e;
michael@0 5938 }
michael@0 5939 info('(while reading XRef): ' + e);
michael@0 5940 }
michael@0 5941
michael@0 5942 if (recoveryMode) {
michael@0 5943 return;
michael@0 5944 }
michael@0 5945 throw new XRefParseException();
michael@0 5946 },
michael@0 5947
michael@0 5948 getEntry: function XRef_getEntry(i) {
michael@0 5949 var xrefEntry = this.entries[i];
michael@0 5950 if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {
michael@0 5951 return xrefEntry;
michael@0 5952 }
michael@0 5953 return null;
michael@0 5954 },
michael@0 5955
michael@0 5956 fetchIfRef: function XRef_fetchIfRef(obj) {
michael@0 5957 if (!isRef(obj)) {
michael@0 5958 return obj;
michael@0 5959 }
michael@0 5960 return this.fetch(obj);
michael@0 5961 },
michael@0 5962
michael@0 5963 fetch: function XRef_fetch(ref, suppressEncryption) {
michael@0 5964 assert(isRef(ref), 'ref object is not a reference');
michael@0 5965 var num = ref.num;
michael@0 5966 if (num in this.cache) {
michael@0 5967 var cacheEntry = this.cache[num];
michael@0 5968 return cacheEntry;
michael@0 5969 }
michael@0 5970
michael@0 5971 var xrefEntry = this.getEntry(num);
michael@0 5972
michael@0 5973 // the referenced entry can be free
michael@0 5974 if (xrefEntry === null) {
michael@0 5975 return (this.cache[num] = null);
michael@0 5976 }
michael@0 5977
michael@0 5978 if (xrefEntry.uncompressed) {
michael@0 5979 xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption);
michael@0 5980 } else {
michael@0 5981 xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption);
michael@0 5982 }
michael@0 5983
michael@0 5984 if (isDict(xrefEntry)) {
michael@0 5985 xrefEntry.objId = 'R' + ref.num + '.' + ref.gen;
michael@0 5986 }
michael@0 5987 return xrefEntry;
michael@0 5988 },
michael@0 5989
michael@0 5990 fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry,
michael@0 5991 suppressEncryption) {
michael@0 5992 var gen = ref.gen;
michael@0 5993 var num = ref.num;
michael@0 5994 if (xrefEntry.gen !== gen) {
michael@0 5995 error('inconsistent generation in XRef');
michael@0 5996 }
michael@0 5997 var stream = this.stream.makeSubStream(xrefEntry.offset +
michael@0 5998 this.stream.start);
michael@0 5999 var parser = new Parser(new Lexer(stream), true, this);
michael@0 6000 var obj1 = parser.getObj();
michael@0 6001 var obj2 = parser.getObj();
michael@0 6002 var obj3 = parser.getObj();
michael@0 6003 if (!isInt(obj1) || parseInt(obj1, 10) !== num ||
michael@0 6004 !isInt(obj2) || parseInt(obj2, 10) !== gen ||
michael@0 6005 !isCmd(obj3)) {
michael@0 6006 error('bad XRef entry');
michael@0 6007 }
michael@0 6008 if (!isCmd(obj3, 'obj')) {
michael@0 6009 // some bad PDFs use "obj1234" and really mean 1234
michael@0 6010 if (obj3.cmd.indexOf('obj') === 0) {
michael@0 6011 num = parseInt(obj3.cmd.substring(3), 10);
michael@0 6012 if (!isNaN(num)) {
michael@0 6013 return num;
michael@0 6014 }
michael@0 6015 }
michael@0 6016 error('bad XRef entry');
michael@0 6017 }
michael@0 6018 if (this.encrypt && !suppressEncryption) {
michael@0 6019 try {
michael@0 6020 xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num,
michael@0 6021 gen));
michael@0 6022 } catch (ex) {
michael@0 6023 // Almost all streams must be encrypted, but sometimes
michael@0 6024 // they are not, probably due to some broken generators.
michael@0 6025 // Retrying without encryption...
michael@0 6026 return this.fetch(ref, true);
michael@0 6027 }
michael@0 6028 } else {
michael@0 6029 xrefEntry = parser.getObj();
michael@0 6030 }
michael@0 6031 if (!isStream(xrefEntry)) {
michael@0 6032 this.cache[num] = xrefEntry;
michael@0 6033 }
michael@0 6034 return xrefEntry;
michael@0 6035 },
michael@0 6036
michael@0 6037 fetchCompressed: function XRef_fetchCompressed(xrefEntry,
michael@0 6038 suppressEncryption) {
michael@0 6039 var tableOffset = xrefEntry.offset;
michael@0 6040 var stream = this.fetch(new Ref(tableOffset, 0));
michael@0 6041 if (!isStream(stream)) {
michael@0 6042 error('bad ObjStm stream');
michael@0 6043 }
michael@0 6044 var first = stream.dict.get('First');
michael@0 6045 var n = stream.dict.get('N');
michael@0 6046 if (!isInt(first) || !isInt(n)) {
michael@0 6047 error('invalid first and n parameters for ObjStm stream');
michael@0 6048 }
michael@0 6049 var parser = new Parser(new Lexer(stream), false, this);
michael@0 6050 parser.allowStreams = true;
michael@0 6051 var i, entries = [], num, nums = [];
michael@0 6052 // read the object numbers to populate cache
michael@0 6053 for (i = 0; i < n; ++i) {
michael@0 6054 num = parser.getObj();
michael@0 6055 if (!isInt(num)) {
michael@0 6056 error('invalid object number in the ObjStm stream: ' + num);
michael@0 6057 }
michael@0 6058 nums.push(num);
michael@0 6059 var offset = parser.getObj();
michael@0 6060 if (!isInt(offset)) {
michael@0 6061 error('invalid object offset in the ObjStm stream: ' + offset);
michael@0 6062 }
michael@0 6063 }
michael@0 6064 // read stream objects for cache
michael@0 6065 for (i = 0; i < n; ++i) {
michael@0 6066 entries.push(parser.getObj());
michael@0 6067 num = nums[i];
michael@0 6068 var entry = this.entries[num];
michael@0 6069 if (entry && entry.offset === tableOffset && entry.gen === i) {
michael@0 6070 this.cache[num] = entries[i];
michael@0 6071 }
michael@0 6072 }
michael@0 6073 xrefEntry = entries[xrefEntry.gen];
michael@0 6074 if (xrefEntry === undefined) {
michael@0 6075 error('bad XRef entry for compressed object');
michael@0 6076 }
michael@0 6077 return xrefEntry;
michael@0 6078 },
michael@0 6079
michael@0 6080 fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) {
michael@0 6081 if (!isRef(obj)) {
michael@0 6082 var promise = new LegacyPromise();
michael@0 6083 promise.resolve(obj);
michael@0 6084 return promise;
michael@0 6085 }
michael@0 6086 return this.fetchAsync(obj);
michael@0 6087 },
michael@0 6088
michael@0 6089 fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) {
michael@0 6090 var promise = new LegacyPromise();
michael@0 6091 var tryFetch = function (promise) {
michael@0 6092 try {
michael@0 6093 promise.resolve(this.fetch(ref, suppressEncryption));
michael@0 6094 } catch (e) {
michael@0 6095 if (e instanceof MissingDataException) {
michael@0 6096 this.stream.manager.requestRange(e.begin, e.end, tryFetch);
michael@0 6097 return;
michael@0 6098 }
michael@0 6099 promise.reject(e);
michael@0 6100 }
michael@0 6101 }.bind(this, promise);
michael@0 6102 tryFetch();
michael@0 6103 return promise;
michael@0 6104 },
michael@0 6105
michael@0 6106 getCatalogObj: function XRef_getCatalogObj() {
michael@0 6107 return this.root;
michael@0 6108 }
michael@0 6109 };
michael@0 6110
michael@0 6111 return XRef;
michael@0 6112 })();
michael@0 6113
michael@0 6114 /**
michael@0 6115 * A NameTree is like a Dict but has some advantageous properties, see the
michael@0 6116 * spec (7.9.6) for more details.
michael@0 6117 * TODO: implement all the Dict functions and make this more efficent.
michael@0 6118 */
michael@0 6119 var NameTree = (function NameTreeClosure() {
michael@0 6120 function NameTree(root, xref) {
michael@0 6121 this.root = root;
michael@0 6122 this.xref = xref;
michael@0 6123 }
michael@0 6124
michael@0 6125 NameTree.prototype = {
michael@0 6126 getAll: function NameTree_getAll() {
michael@0 6127 var dict = {};
michael@0 6128 if (!this.root) {
michael@0 6129 return dict;
michael@0 6130 }
michael@0 6131 var xref = this.xref;
michael@0 6132 // reading name tree
michael@0 6133 var processed = new RefSet();
michael@0 6134 processed.put(this.root);
michael@0 6135 var queue = [this.root];
michael@0 6136 while (queue.length > 0) {
michael@0 6137 var i, n;
michael@0 6138 var obj = xref.fetchIfRef(queue.shift());
michael@0 6139 if (!isDict(obj)) {
michael@0 6140 continue;
michael@0 6141 }
michael@0 6142 if (obj.has('Kids')) {
michael@0 6143 var kids = obj.get('Kids');
michael@0 6144 for (i = 0, n = kids.length; i < n; i++) {
michael@0 6145 var kid = kids[i];
michael@0 6146 if (processed.has(kid)) {
michael@0 6147 error('invalid destinations');
michael@0 6148 }
michael@0 6149 queue.push(kid);
michael@0 6150 processed.put(kid);
michael@0 6151 }
michael@0 6152 continue;
michael@0 6153 }
michael@0 6154 var names = obj.get('Names');
michael@0 6155 if (names) {
michael@0 6156 for (i = 0, n = names.length; i < n; i += 2) {
michael@0 6157 dict[names[i]] = xref.fetchIfRef(names[i + 1]);
michael@0 6158 }
michael@0 6159 }
michael@0 6160 }
michael@0 6161 return dict;
michael@0 6162 }
michael@0 6163 };
michael@0 6164 return NameTree;
michael@0 6165 })();
michael@0 6166
michael@0 6167 /**
michael@0 6168 * "A PDF file can refer to the contents of another file by using a File
michael@0 6169 * Specification (PDF 1.1)", see the spec (7.11) for more details.
michael@0 6170 * NOTE: Only embedded files are supported (as part of the attachments support)
michael@0 6171 * TODO: support the 'URL' file system (with caching if !/V), portable
michael@0 6172 * collections attributes and related files (/RF)
michael@0 6173 */
michael@0 6174 var FileSpec = (function FileSpecClosure() {
michael@0 6175 function FileSpec(root, xref) {
michael@0 6176 if (!root || !isDict(root)) {
michael@0 6177 return;
michael@0 6178 }
michael@0 6179 this.xref = xref;
michael@0 6180 this.root = root;
michael@0 6181 if (root.has('FS')) {
michael@0 6182 this.fs = root.get('FS');
michael@0 6183 }
michael@0 6184 this.description = root.has('Desc') ?
michael@0 6185 stringToPDFString(root.get('Desc')) :
michael@0 6186 '';
michael@0 6187 if (root.has('RF')) {
michael@0 6188 warn('Related file specifications are not supported');
michael@0 6189 }
michael@0 6190 this.contentAvailable = true;
michael@0 6191 if (!root.has('EF')) {
michael@0 6192 this.contentAvailable = false;
michael@0 6193 warn('Non-embedded file specifications are not supported');
michael@0 6194 }
michael@0 6195 }
michael@0 6196
michael@0 6197 function pickPlatformItem(dict) {
michael@0 6198 // Look for the filename in this order:
michael@0 6199 // UF, F, Unix, Mac, DOS
michael@0 6200 if (dict.has('UF')) {
michael@0 6201 return dict.get('UF');
michael@0 6202 } else if (dict.has('F')) {
michael@0 6203 return dict.get('F');
michael@0 6204 } else if (dict.has('Unix')) {
michael@0 6205 return dict.get('Unix');
michael@0 6206 } else if (dict.has('Mac')) {
michael@0 6207 return dict.get('Mac');
michael@0 6208 } else if (dict.has('DOS')) {
michael@0 6209 return dict.get('DOS');
michael@0 6210 } else {
michael@0 6211 return null;
michael@0 6212 }
michael@0 6213 }
michael@0 6214
michael@0 6215 FileSpec.prototype = {
michael@0 6216 get filename() {
michael@0 6217 if (!this._filename && this.root) {
michael@0 6218 var filename = pickPlatformItem(this.root) || 'unnamed';
michael@0 6219 this._filename = stringToPDFString(filename).
michael@0 6220 replace(/\\\\/g, '\\').
michael@0 6221 replace(/\\\//g, '/').
michael@0 6222 replace(/\\/g, '/');
michael@0 6223 }
michael@0 6224 return this._filename;
michael@0 6225 },
michael@0 6226 get content() {
michael@0 6227 if (!this.contentAvailable) {
michael@0 6228 return null;
michael@0 6229 }
michael@0 6230 if (!this.contentRef && this.root) {
michael@0 6231 this.contentRef = pickPlatformItem(this.root.get('EF'));
michael@0 6232 }
michael@0 6233 var content = null;
michael@0 6234 if (this.contentRef) {
michael@0 6235 var xref = this.xref;
michael@0 6236 var fileObj = xref.fetchIfRef(this.contentRef);
michael@0 6237 if (fileObj && isStream(fileObj)) {
michael@0 6238 content = fileObj.getBytes();
michael@0 6239 } else {
michael@0 6240 warn('Embedded file specification points to non-existing/invalid ' +
michael@0 6241 'content');
michael@0 6242 }
michael@0 6243 } else {
michael@0 6244 warn('Embedded file specification does not have a content');
michael@0 6245 }
michael@0 6246 return content;
michael@0 6247 },
michael@0 6248 get serializable() {
michael@0 6249 return {
michael@0 6250 filename: this.filename,
michael@0 6251 content: this.content
michael@0 6252 };
michael@0 6253 }
michael@0 6254 };
michael@0 6255 return FileSpec;
michael@0 6256 })();
michael@0 6257
michael@0 6258 /**
michael@0 6259 * A helper for loading missing data in object graphs. It traverses the graph
michael@0 6260 * depth first and queues up any objects that have missing data. Once it has
michael@0 6261 * has traversed as many objects that are available it attempts to bundle the
michael@0 6262 * missing data requests and then resume from the nodes that weren't ready.
michael@0 6263 *
michael@0 6264 * NOTE: It provides protection from circular references by keeping track of
michael@0 6265 * of loaded references. However, you must be careful not to load any graphs
michael@0 6266 * that have references to the catalog or other pages since that will cause the
michael@0 6267 * entire PDF document object graph to be traversed.
michael@0 6268 */
michael@0 6269 var ObjectLoader = (function() {
michael@0 6270 function mayHaveChildren(value) {
michael@0 6271 return isRef(value) || isDict(value) || isArray(value) || isStream(value);
michael@0 6272 }
michael@0 6273
michael@0 6274 function addChildren(node, nodesToVisit) {
michael@0 6275 var value;
michael@0 6276 if (isDict(node) || isStream(node)) {
michael@0 6277 var map;
michael@0 6278 if (isDict(node)) {
michael@0 6279 map = node.map;
michael@0 6280 } else {
michael@0 6281 map = node.dict.map;
michael@0 6282 }
michael@0 6283 for (var key in map) {
michael@0 6284 value = map[key];
michael@0 6285 if (mayHaveChildren(value)) {
michael@0 6286 nodesToVisit.push(value);
michael@0 6287 }
michael@0 6288 }
michael@0 6289 } else if (isArray(node)) {
michael@0 6290 for (var i = 0, ii = node.length; i < ii; i++) {
michael@0 6291 value = node[i];
michael@0 6292 if (mayHaveChildren(value)) {
michael@0 6293 nodesToVisit.push(value);
michael@0 6294 }
michael@0 6295 }
michael@0 6296 }
michael@0 6297 }
michael@0 6298
michael@0 6299 function ObjectLoader(obj, keys, xref) {
michael@0 6300 this.obj = obj;
michael@0 6301 this.keys = keys;
michael@0 6302 this.xref = xref;
michael@0 6303 this.refSet = null;
michael@0 6304 }
michael@0 6305
michael@0 6306 ObjectLoader.prototype = {
michael@0 6307 load: function ObjectLoader_load() {
michael@0 6308 var keys = this.keys;
michael@0 6309 this.promise = new LegacyPromise();
michael@0 6310 // Don't walk the graph if all the data is already loaded.
michael@0 6311 if (!(this.xref.stream instanceof ChunkedStream) ||
michael@0 6312 this.xref.stream.getMissingChunks().length === 0) {
michael@0 6313 this.promise.resolve();
michael@0 6314 return this.promise;
michael@0 6315 }
michael@0 6316
michael@0 6317 this.refSet = new RefSet();
michael@0 6318 // Setup the initial nodes to visit.
michael@0 6319 var nodesToVisit = [];
michael@0 6320 for (var i = 0; i < keys.length; i++) {
michael@0 6321 nodesToVisit.push(this.obj[keys[i]]);
michael@0 6322 }
michael@0 6323
michael@0 6324 this.walk(nodesToVisit);
michael@0 6325 return this.promise;
michael@0 6326 },
michael@0 6327
michael@0 6328 walk: function ObjectLoader_walk(nodesToVisit) {
michael@0 6329 var nodesToRevisit = [];
michael@0 6330 var pendingRequests = [];
michael@0 6331 // DFS walk of the object graph.
michael@0 6332 while (nodesToVisit.length) {
michael@0 6333 var currentNode = nodesToVisit.pop();
michael@0 6334
michael@0 6335 // Only references or chunked streams can cause missing data exceptions.
michael@0 6336 if (isRef(currentNode)) {
michael@0 6337 // Skip nodes that have already been visited.
michael@0 6338 if (this.refSet.has(currentNode)) {
michael@0 6339 continue;
michael@0 6340 }
michael@0 6341 try {
michael@0 6342 var ref = currentNode;
michael@0 6343 this.refSet.put(ref);
michael@0 6344 currentNode = this.xref.fetch(currentNode);
michael@0 6345 } catch (e) {
michael@0 6346 if (!(e instanceof MissingDataException)) {
michael@0 6347 throw e;
michael@0 6348 }
michael@0 6349 nodesToRevisit.push(currentNode);
michael@0 6350 pendingRequests.push({ begin: e.begin, end: e.end });
michael@0 6351 }
michael@0 6352 }
michael@0 6353 if (currentNode && currentNode.getBaseStreams) {
michael@0 6354 var baseStreams = currentNode.getBaseStreams();
michael@0 6355 var foundMissingData = false;
michael@0 6356 for (var i = 0; i < baseStreams.length; i++) {
michael@0 6357 var stream = baseStreams[i];
michael@0 6358 if (stream.getMissingChunks && stream.getMissingChunks().length) {
michael@0 6359 foundMissingData = true;
michael@0 6360 pendingRequests.push({
michael@0 6361 begin: stream.start,
michael@0 6362 end: stream.end
michael@0 6363 });
michael@0 6364 }
michael@0 6365 }
michael@0 6366 if (foundMissingData) {
michael@0 6367 nodesToRevisit.push(currentNode);
michael@0 6368 }
michael@0 6369 }
michael@0 6370
michael@0 6371 addChildren(currentNode, nodesToVisit);
michael@0 6372 }
michael@0 6373
michael@0 6374 if (pendingRequests.length) {
michael@0 6375 this.xref.stream.manager.requestRanges(pendingRequests,
michael@0 6376 function pendingRequestCallback() {
michael@0 6377 nodesToVisit = nodesToRevisit;
michael@0 6378 for (var i = 0; i < nodesToRevisit.length; i++) {
michael@0 6379 var node = nodesToRevisit[i];
michael@0 6380 // Remove any reference nodes from the currrent refset so they
michael@0 6381 // aren't skipped when we revist them.
michael@0 6382 if (isRef(node)) {
michael@0 6383 this.refSet.remove(node);
michael@0 6384 }
michael@0 6385 }
michael@0 6386 this.walk(nodesToVisit);
michael@0 6387 }.bind(this));
michael@0 6388 return;
michael@0 6389 }
michael@0 6390 // Everything is loaded.
michael@0 6391 this.refSet = null;
michael@0 6392 this.promise.resolve();
michael@0 6393 }
michael@0 6394 };
michael@0 6395
michael@0 6396 return ObjectLoader;
michael@0 6397 })();
michael@0 6398
michael@0 6399
michael@0 6400 var ISOAdobeCharset = [
michael@0 6401 '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
michael@0 6402 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
michael@0 6403 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
michael@0 6404 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
michael@0 6405 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
michael@0 6406 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
michael@0 6407 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
michael@0 6408 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
michael@0 6409 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
michael@0 6410 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
michael@0 6411 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
michael@0 6412 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
michael@0 6413 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
michael@0 6414 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
michael@0 6415 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
michael@0 6416 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
michael@0 6417 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
michael@0 6418 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
michael@0 6419 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
michael@0 6420 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
michael@0 6421 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
michael@0 6422 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
michael@0 6423 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
michael@0 6424 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
michael@0 6425 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
michael@0 6426 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
michael@0 6427 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
michael@0 6428 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
michael@0 6429 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
michael@0 6430 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
michael@0 6431 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
michael@0 6432 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
michael@0 6433 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
michael@0 6434 'ugrave', 'yacute', 'ydieresis', 'zcaron'
michael@0 6435 ];
michael@0 6436
michael@0 6437 var ExpertCharset = [
michael@0 6438 '.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
michael@0 6439 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
michael@0 6440 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
michael@0 6441 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
michael@0 6442 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
michael@0 6443 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
michael@0 6444 'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
michael@0 6445 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
michael@0 6446 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
michael@0 6447 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
michael@0 6448 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
michael@0 6449 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
michael@0 6450 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
michael@0 6451 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
michael@0 6452 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
michael@0 6453 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
michael@0 6454 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
michael@0 6455 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
michael@0 6456 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
michael@0 6457 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
michael@0 6458 'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
michael@0 6459 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
michael@0 6460 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
michael@0 6461 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
michael@0 6462 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
michael@0 6463 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
michael@0 6464 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
michael@0 6465 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
michael@0 6466 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
michael@0 6467 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall',
michael@0 6468 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
michael@0 6469 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
michael@0 6470 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
michael@0 6471 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
michael@0 6472 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
michael@0 6473 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
michael@0 6474 'Ydieresissmall'
michael@0 6475 ];
michael@0 6476
michael@0 6477 var ExpertSubsetCharset = [
michael@0 6478 '.notdef', 'space', 'dollaroldstyle', 'dollarsuperior',
michael@0 6479 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
michael@0 6480 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
michael@0 6481 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
michael@0 6482 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
michael@0 6483 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
michael@0 6484 'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior',
michael@0 6485 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
michael@0 6486 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
michael@0 6487 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
michael@0 6488 'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted',
michael@0 6489 'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter',
michael@0 6490 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
michael@0 6491 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
michael@0 6492 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
michael@0 6493 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
michael@0 6494 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
michael@0 6495 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
michael@0 6496 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
michael@0 6497 'periodinferior', 'commainferior'
michael@0 6498 ];
michael@0 6499
michael@0 6500
michael@0 6501
michael@0 6502 var CIDToUnicodeMaps = {
michael@0 6503 'Adobe-Japan1': [[32, 160], {f: 12, c: 33}, [45, 8209], {f: 46, c: 46}, 165,
michael@0 6504 {f: 2, c: 93}, [95, 818], [96, 768], {f: 27, c: 97}, 166, 125, [732, 771],
michael@0 6505 [700, 8217], 92, [699, 8216], 124, [126, 8764], {f: 3, c: 161}, 8260, 402,
michael@0 6506 0, 164, 8220, 171, {f: 2, c: 8249}, {f: 2, c: 64257}, [8210, 8211], 0, 0,
michael@0 6507 [183, 8729], 0, 8226, 8218, 8222, 8221, 187, 0, 0, 191, {f: 2, c: 769},
michael@0 6508 [175, 772], {f: 3, c: 774}, 778, [184, 807], 779, 808, 780, [822, 8212],
michael@0 6509 198, 170, 321, 216, 338, 186, 230, 305, 322, 248, 339, 223, 173, 169, 172,
michael@0 6510 174, 0, 0, {f: 2, c: 178}, 181, 185, {f: 3, c: 188}, {f: 6, c: 192},
michael@0 6511 {f: 16, c: 199}, 0, {f: 6, c: 217}, {f: 6, c: 224}, {f: 16, c: 231}, 0,
michael@0 6512 {f: 7, c: 249}, 352, 376, 381, [773, 8254], 353, 8482, 382, 0, 8194,
michael@0 6513 {f: 59, c: 33}, 165, {f: 31, c: 93}, 65512, {f: 2, c: 125}, 0,
michael@0 6514 {f: 63, c: 65377}, {s: 243}, [8195, 12288],
michael@0 6515 {f: 2, c: 12289}, 65292, 65294, 12539, {f: 2, c: 65306}, 65311, 65281,
michael@0 6516 {f: 2, c: 12443}, 180, 65344, 168, 65342, 65507, 65343, {f: 2, c: 12541},
michael@0 6517 {f: 2, c: 12445}, 12291, 20189, {f: 3, c: 12293}, 12540, 8213, 8208, 65295,
michael@0 6518 65340, [12316, 65374], 8214, 65372, 8230, 8229, {s: 4}, {f: 2, c: 65288},
michael@0 6519 {f: 2, c: 12308}, 65339, 65341, 65371, 65373, {f: 10, c: 12296}, 65291,
michael@0 6520 [8722, 65293], 177, 215, 247, 65309, 8800, 65308, 65310, {f: 2, c: 8806},
michael@0 6521 8734, 8756, 9794, 9792, 176, {f: 2, c: 8242}, 8451, 65509, 65284,
michael@0 6522 {f: 2, c: 65504}, 65285, 65283, 65286, 65290, 65312, 167, 9734, 9733, 9675,
michael@0 6523 9679, 9678, 9671, 9670, 9633, 9632, 9651, 9650, 9661, 9660, 8251, 12306,
michael@0 6524 8594, {f: 2, c: 8592}, 8595, 12307, 8712, 8715, {f: 2, c: 8838},
michael@0 6525 {f: 2, c: 8834}, 8746, 8745, {f: 2, c: 8743}, 65506, 8658, 8660, 8704,
michael@0 6526 8707, 8736, 8869, 8978, 8706, 8711, 8801, 8786, {f: 2, c: 8810}, 8730,
michael@0 6527 8765, 8733, 8757, {f: 2, c: 8747}, 8491, 8240, 9839, 9837, 9834,
michael@0 6528 {f: 2, c: 8224}, 182, 9711, {f: 10, c: 65296}, {f: 26, c: 65313},
michael@0 6529 {f: 26, c: 65345}, {f: 83, c: 12353}, {f: 86, c: 12449}, {f: 17, c: 913},
michael@0 6530 {f: 7, c: 931}, {f: 17, c: 945}, {f: 7, c: 963}, {f: 6, c: 1040}, 1025,
michael@0 6531 {f: 32, c: 1046}, 1105, {f: 26, c: 1078}, 20124, 21782, 23043, 38463,
michael@0 6532 21696, 24859, 25384, 23030, 36898, 33909, 33564, 31312, 24746, 25569,
michael@0 6533 28197, 26093, 33894, 33446, 39925, 26771, 22311, 26017, 25201, 23451,
michael@0 6534 22992, 34427, 39156, 32098, 32190, 39822, 25110, 31903, 34999, 23433,
michael@0 6535 24245, 25353, 26263, 26696, 38343, 38797, 26447, 20197, 20234, 20301,
michael@0 6536 20381, 20553, 22258, 22839, 22996, 23041, 23561, 24799, 24847, 24944,
michael@0 6537 26131, 26885, 28858, 30031, 30064, 31227, 32173, 32239, 32963, 33806,
michael@0 6538 [12176, 34915], 35586, 36949, 36986, 21307, 20117, 20133, 22495, 32946,
michael@0 6539 37057, 30959, [12032, 19968], 22769, 28322, 36920, 31282, 33576, 33419,
michael@0 6540 39983, 20801, 21360, 21693, 21729, 22240, 23035, 24341, 39154, 28139,
michael@0 6541 32996, 34093, 38498, 38512, 38560, 38907, 21515, 21491, 23431, 28879,
michael@0 6542 [12155, 32701], 36802, [12204, 38632], 21359, 40284, 31418, 19985, 30867,
michael@0 6543 [12165, 33276], 28198, 22040, 21764, 27421, 34074, 39995, 23013, 21417,
michael@0 6544 28006, [12128, 29916], 38287, 22082, 20113, 36939, 38642, 33615, 39180,
michael@0 6545 21473, 21942, 23344, 24433, 26144, 26355, 26628, 27704, 27891, 27945,
michael@0 6546 29787, 30408, 31310, 38964, 33521, 34907, 35424, 37613, 28082, 30123,
michael@0 6547 30410, 39365, 24742, 35585, 36234, 38322, 27022, 21421, 20870, 22290,
michael@0 6548 22576, 22852, 23476, 24310, 24616, 25513, 25588, 27839, 28436, 28814,
michael@0 6549 28948, 29017, 29141, 29503, 32257, 33398, 33489, 34199, 36960, 37467,
michael@0 6550 40219, 22633, 26044, 27738, 29989, 20985, 22830, 22885, 24448, 24540,
michael@0 6551 25276, 26106, 27178, 27431, 27572, 29579, 32705, 35158, 40236, 40206,
michael@0 6552 [12009, 40644], 23713, 27798, 33659, 20740, 23627, 25014, 33222, 26742,
michael@0 6553 29281, [12036, 20057], 20474, 21368, 24681, 28201, 31311, [12211, 38899],
michael@0 6554 19979, 21270, 20206, 20309, 20285, 20385, 20339, 21152, 21487, 22025,
michael@0 6555 22799, 23233, 23478, 23521, 31185, 26247, 26524, 26550, 27468, 27827,
michael@0 6556 [12117, 28779], 29634, 31117, [12146, 31166], 31292, 31623, 33457, 33499,
michael@0 6557 33540, 33655, 33775, 33747, 34662, 35506, 22057, 36008, 36838, 36942,
michael@0 6558 38686, 34442, 20420, 23784, 25105, [12123, 29273], 30011, 33253, 33469,
michael@0 6559 34558, 36032, 38597, 39187, 39381, 20171, 20250, 35299, 22238, 22602,
michael@0 6560 22730, 24315, 24555, 24618, 24724, 24674, 25040, 25106, 25296, 25913,
michael@0 6561 39745, 26214, 26800, 28023, 28784, 30028, 30342, 32117, 33445, 34809,
michael@0 6562 38283, 38542, [12185, 35997], 20977, 21182, 22806, 21683, 23475, 23830,
michael@0 6563 24936, 27010, 28079, 30861, 33995, 34903, 35442, 37799, 39608, 28012,
michael@0 6564 39336, 34521, 22435, 26623, 34510, 37390, 21123, 22151, 21508, 24275,
michael@0 6565 25313, 25785, 26684, 26680, 27579, 29554, 30906, 31339, 35226,
michael@0 6566 [12179, 35282], 36203, 36611, 37101, 38307, 38548, [12208, 38761], 23398,
michael@0 6567 23731, 27005, {f: 2, c: 38989}, 25499, 31520, 27179, 27263, 26806, 39949,
michael@0 6568 28511, 21106, 21917, 24688, 25324, 27963, 28167, 28369, 33883, 35088,
michael@0 6569 36676, 19988, 39993, 21494, 26907, 27194, 38788, 26666, 20828, 31427,
michael@0 6570 33970, 37340, 37772, 22107, 40232, 26658, 33541, 33841, 31909, 21000,
michael@0 6571 33477, [12129, 29926], 20094, 20355, 20896, 23506, 21002, 21208, 21223,
michael@0 6572 24059, 21914, 22570, 23014, 23436, 23448, 23515, [12082, 24178], 24185,
michael@0 6573 24739, 24863, 24931, 25022, 25563, 25954, 26577, 26707, 26874, 27454,
michael@0 6574 27475, 27735, 28450, 28567, 28485, 29872, [12130, 29976], 30435, 30475,
michael@0 6575 31487, 31649, 31777, 32233, [12152, 32566], 32752, 32925, 33382, 33694,
michael@0 6576 35251, 35532, 36011, 36996, 37969, 38291, 38289, 38306, 38501, 38867,
michael@0 6577 39208, 33304, 20024, 21547, 23736, 24012, 29609, 30284, 30524, 23721,
michael@0 6578 32747, 36107, 38593, 38929, 38996, 39000, 20225, 20238, 21361, 21916,
michael@0 6579 22120, 22522, 22855, 23305, 23492, 23696, 24076, 24190, 24524, 25582,
michael@0 6580 26426, 26071, 26082, 26399, 26827, 26820, 27231, 24112, 27589, 27671,
michael@0 6581 27773, 30079, 31048, 23395, 31232, 32000, 24509, 35215, 35352, 36020,
michael@0 6582 36215, 36556, 36637, 39138, 39438, [12004, 12225, 39740], [12018, 20096],
michael@0 6583 20605, 20736, 22931, 23452, 25135, 25216, 25836, 27450, 29344, 30097,
michael@0 6584 31047, 32681, 34811, 35516, 35696, 25516, 33738, 38816, 21513, 21507,
michael@0 6585 21931, 26708, 27224, 35440, 30759, 26485, [12233, 40653], 21364, 23458,
michael@0 6586 33050, 34384, 36870, 19992, 20037, 20167, 20241, 21450, 21560, 23470,
michael@0 6587 [12088, 24339], 24613, 25937, 26429, 27714, 27762, 27875, 28792, 29699,
michael@0 6588 31350, 31406, 31496, 32026, 31998, 32102, 26087, [12124, 29275], 21435,
michael@0 6589 23621, 24040, 25298, 25312, 25369, 28192, 34394, 35377, 36317, 37624,
michael@0 6590 28417, 31142, [12226, 39770], 20136, {f: 2, c: 20139}, 20379, 20384, 20689,
michael@0 6591 20807, 31478, 20849, 20982, 21332, 21281, 21375, 21483, 21932, 22659,
michael@0 6592 23777, 24375, 24394, 24623, 24656, 24685, 25375, 25945, 27211, 27841,
michael@0 6593 29378, 29421, 30703, 33016, 33029, 33288, 34126, 37111, 37857, 38911,
michael@0 6594 39255, 39514, 20208, 20957, 23597, 26241, 26989, 23616, 26354, 26997,
michael@0 6595 [12127, 29577], 26704, 31873, 20677, 21220, 22343, [12081, 24062], 37670,
michael@0 6596 [12100, 26020], 27427, 27453, 29748, 31105, 31165, 31563, 32202, 33465,
michael@0 6597 33740, 34943, 35167, 35641, 36817, [12198, 37329], 21535, 37504, 20061,
michael@0 6598 20534, 21477, 21306, 29399, 29590, 30697, 33510, 36527, 39366, 39368,
michael@0 6599 39378, 20855, 24858, 34398, 21936, 31354, 20598, 23507, 36935, 38533,
michael@0 6600 20018, 27355, 37351, 23633, 23624, 25496, 31391, 27795, 38772, 36705,
michael@0 6601 31402, 29066, 38536, 31874, 26647, 32368, 26705, 37740, 21234, 21531,
michael@0 6602 34219, 35347, 32676, 36557, 37089, 21350, 34952, 31041, 20418, 20670,
michael@0 6603 21009, 20804, 21843, 22317, 29674, 22411, 22865, 24418, 24452, 24693,
michael@0 6604 24950, 24935, 25001, 25522, 25658, 25964, 26223, 26690, 28179, 30054,
michael@0 6605 31293, 31995, 32076, 32153, 32331, 32619, 33550, 33610, 34509, 35336,
michael@0 6606 35427, 35686, 36605, 38938, 40335, 33464, 36814, 39912, 21127, 25119,
michael@0 6607 25731, 28608, 38553, 26689, 20625, [12107, 27424], 27770, 28500,
michael@0 6608 [12147, 31348], 32080, [12174, 34880], 35363, [12105, 26376], 20214, 20537,
michael@0 6609 20518, 20581, 20860, 21048, 21091, 21927, 22287, 22533, 23244, 24314,
michael@0 6610 25010, 25080, 25331, 25458, 26908, 27177, 29309, [12125, 29356], 29486,
michael@0 6611 30740, 30831, 32121, 30476, 32937, [12178, 35211], 35609, 36066, 36562,
michael@0 6612 36963, 37749, 38522, 38997, 39443, 40568, 20803, 21407, 21427, 24187,
michael@0 6613 24358, 28187, 28304, [12126, 29572], 29694, 32067, 33335, [12180, 35328],
michael@0 6614 35578, 38480, 20046, 20491, 21476, 21628, 22266, 22993, 23396,
michael@0 6615 [12080, 24049], 24235, 24359, [12094, 25144], 25925, 26543, 28246, 29392,
michael@0 6616 31946, 34996, 32929, 32993, 33776, [11969, 34382], 35463, 36328, 37431,
michael@0 6617 38599, 39015, [12238, 40723], 20116, 20114, 20237, 21320, 21577, 21566,
michael@0 6618 23087, 24460, 24481, 24735, 26791, 27278, 29786, 30849, 35486, 35492,
michael@0 6619 35703, 37264, 20062, 39881, 20132, 20348, 20399, 20505, 20502, 20809,
michael@0 6620 20844, 21151, 21177, 21246, 21402, [12061, 21475], 21521, 21518, 21897,
michael@0 6621 22353, 22434, 22909, 23380, 23389, 23439, [12079, 24037], 24039, 24055,
michael@0 6622 24184, 24195, 24218, 24247, 24344, 24658, 24908, 25239, 25304, 25511,
michael@0 6623 25915, 26114, 26179, 26356, 26477, 26657, 26775, 27083, 27743, 27946,
michael@0 6624 28009, 28207, 28317, 30002, 30343, 30828, 31295, 31968, 32005, 32024,
michael@0 6625 32094, 32177, 32789, 32771, 32943, 32945, 33108, 33167, 33322, 33618,
michael@0 6626 [12175, 34892], 34913, 35611, 36002, 36092, 37066, 37237, 37489, 30783,
michael@0 6627 37628, 38308, 38477, 38917, [12217, 39321], [12220, 39640], 40251, 21083,
michael@0 6628 21163, 21495, 21512, 22741, 25335, 28640, 35946, 36703, 40633, 20811,
michael@0 6629 21051, 21578, 22269, 31296, 37239, 40288, [12234, 40658], 29508, 28425,
michael@0 6630 33136, 29969, 24573, 24794, [12219, 39592], 29403, 36796, 27492, 38915,
michael@0 6631 20170, 22256, 22372, 22718, 23130, 24680, 25031, 26127, 26118, 26681,
michael@0 6632 26801, 28151, 30165, 32058, [12169, 33390], 39746, 20123, 20304, 21449,
michael@0 6633 21766, 23919, 24038, 24046, 26619, 27801, 29811, 30722, 35408, 37782,
michael@0 6634 35039, 22352, 24231, 25387, 20661, 20652, 20877, 26368, 21705, 22622,
michael@0 6635 22971, 23472, 24425, 25165, 25505, 26685, 27507, 28168, 28797, 37319,
michael@0 6636 29312, 30741, 30758, 31085, 25998, 32048, 33756, 35009, 36617, 38555,
michael@0 6637 21092, 22312, 26448, 32618, 36001, 20916, 22338, 38442, 22586, 27018,
michael@0 6638 32948, 21682, 23822, 22524, 30869, 40442, 20316, 21066, 21643, 25662,
michael@0 6639 26152, 26388, 26613, 31364, 31574, 32034, 37679, 26716, 39853, 31545,
michael@0 6640 21273, 20874, 21047, 23519, 25334, 25774, 25830, 26413, 27578, 34217,
michael@0 6641 38609, 30352, 39894, 25420, 37638, 39851, [12139, 30399], 26194, 19977,
michael@0 6642 20632, 21442, [12077, 23665], 24808, 25746, 25955, 26719, 29158, 29642,
michael@0 6643 29987, 31639, 32386, 34453, 35715, 36059, 37240, 39184, 26028, 26283,
michael@0 6644 27531, 20181, 20180, 20282, 20351, 21050, 21496, 21490, 21987, 22235,
michael@0 6645 [12064, 22763], 22987, 22985, 23039, [12070, 23376], 23629, 24066, 24107,
michael@0 6646 24535, 24605, 25351, [12096, 25903], 23388, 26031, 26045, 26088, 26525,
michael@0 6647 [12108, 27490], 27515, [12114, 27663], 29509, 31049, 31169, [12151, 31992],
michael@0 6648 32025, 32043, 32930, 33026, [12164, 33267], 35222, 35422, 35433, 35430,
michael@0 6649 35468, 35566, 36039, 36060, 38604, 39164, [12013, 27503], 20107, 20284,
michael@0 6650 20365, 20816, 23383, 23546, 24904, 25345, 26178, 27425, 28363, 27835,
michael@0 6651 29246, 29885, 30164, 30913, [12144, 31034], [12157, 32780], [12159, 32819],
michael@0 6652 [12163, 33258], 33940, 36766, 27728, [12229, 40575], 24335, 35672, 40235,
michael@0 6653 31482, 36600, 23437, 38635, 19971, 21489, 22519, 22833, 23241, 23460,
michael@0 6654 24713, 28287, 28422, 30142, 36074, 23455, 34048, 31712, 20594, 26612,
michael@0 6655 33437, 23649, 34122, 32286, 33294, 20889, 23556, 25448, 36198, 26012,
michael@0 6656 29038, 31038, 32023, 32773, 35613, [12190, 36554], 36974, 34503, 37034,
michael@0 6657 20511, 21242, 23610, 26451, 28796, 29237, 37196, 37320, 37675, 33509,
michael@0 6658 23490, 24369, 24825, 20027, 21462, 23432, [12095, 25163], 26417, 27530,
michael@0 6659 29417, 29664, 31278, 33131, 36259, 37202, [12216, 39318], 20754, 21463,
michael@0 6660 21610, 23551, 25480, 27193, 32172, 38656, 22234, 21454, 21608, 23447,
michael@0 6661 23601, 24030, 20462, 24833, 25342, 27954, 31168, 31179, 32066, 32333,
michael@0 6662 32722, 33261, [12168, 33311], 33936, 34886, 35186, 35728, 36468, 36655,
michael@0 6663 36913, 37195, 37228, 38598, 37276, 20160, 20303, 20805, [12055, 21313],
michael@0 6664 24467, 25102, 26580, 27713, 28171, 29539, 32294, 37325, 37507, 21460,
michael@0 6665 22809, 23487, 28113, 31069, 32302, 31899, 22654, 29087, 20986, 34899,
michael@0 6666 36848, 20426, 23803, 26149, 30636, 31459, 33308, 39423, 20934, 24490,
michael@0 6667 26092, 26991, 27529, 28147, 28310, 28516, 30462, 32020, 24033, 36981,
michael@0 6668 37255, 38918, 20966, 21021, 25152, 26257, 26329, 28186, 24246, 32210,
michael@0 6669 32626, 26360, 34223, 34295, 35576, 21161, 21465, [12069, 22899], 24207,
michael@0 6670 24464, 24661, 37604, 38500, 20663, 20767, 21213, 21280, 21319, 21484,
michael@0 6671 21736, 21830, 21809, 22039, 22888, 22974, 23100, 23477, 23558,
michael@0 6672 [12073, 23567], 23569, 23578, 24196, 24202, 24288, 24432, 25215, 25220,
michael@0 6673 25307, 25484, 25463, 26119, 26124, 26157, 26230, 26494, 26786, 27167,
michael@0 6674 27189, 27836, 28040, 28169, 28248, 28988, 28966, 29031, 30151, 30465,
michael@0 6675 30813, 30977, 31077, 31216, 31456, 31505, 31911, 32057, 32918, 33750,
michael@0 6676 33931, 34121, 34909, 35059, 35359, 35388, 35412, 35443, 35937, 36062,
michael@0 6677 37284, 37478, 37758, 37912, 38556, 38808, 19978, 19976, 19998, 20055,
michael@0 6678 20887, 21104, 22478, 22580, 22732, 23330, 24120, 24773, 25854, 26465,
michael@0 6679 26454, 27972, 29366, 30067, 31331, 33976, 35698, 37304, 37664, 22065,
michael@0 6680 22516, 39166, 25325, 26893, 27542, 29165, 32340, 32887, [12170, 33394],
michael@0 6681 35302, [12215, 39135], 34645, 36785, 23611, 20280, 20449, 20405, 21767,
michael@0 6682 23072, 23517, 23529, [12092, 24515], 24910, 25391, 26032, 26187, 26862,
michael@0 6683 27035, 28024, 28145, 30003, 30137, 30495, 31070, 31206, 32051,
michael@0 6684 [12162, 33251], 33455, 34218, 35242, 35386, [12189, 36523], [12191, 36763],
michael@0 6685 36914, 37341, 38663, [12040, 20154], 20161, 20995, 22645, 22764, 23563,
michael@0 6686 29978, 23613, 33102, 35338, 36805, 38499, 38765, 31525, 35535, 38920,
michael@0 6687 37218, 22259, 21416, 36887, 21561, 22402, 24101, 25512, [12116, 27700],
michael@0 6688 28810, 30561, 31883, 32736, 34928, 36930, 37204, 37648, 37656, 38543,
michael@0 6689 29790, 39620, 23815, 23913, 25968, 26530, 36264, 38619, 25454, 26441,
michael@0 6690 26905, 33733, 38935, 38592, 35070, 28548, 25722, [12072, 23544], 19990,
michael@0 6691 28716, 30045, 26159, 20932, 21046, 21218, 22995, 24449, 24615, 25104,
michael@0 6692 25919, 25972, 26143, 26228, 26866, 26646, 27491, 28165, 29298,
michael@0 6693 [12131, 29983], 30427, 31934, 32854, 22768, 35069, [11972, 35199], 35488,
michael@0 6694 35475, 35531, 36893, 37266, [11992, 38738], 38745, [12011, 25993], 31246,
michael@0 6695 33030, 38587, 24109, 24796, 25114, 26021, 26132, 26512, [12143, 30707],
michael@0 6696 31309, 31821, 32318, 33034, 36012, [12186, 36196], 36321, 36447, 30889,
michael@0 6697 20999, 25305, 25509, 25666, 25240, 35373, 31363, 31680, 35500, 38634,
michael@0 6698 32118, [12166, 33292], 34633, 20185, 20808, 21315, 21344, 23459, 23554,
michael@0 6699 23574, 24029, 25126, 25159, 25776, 26643, 26676, 27849, 27973, 27927,
michael@0 6700 26579, 28508, 29006, 29053, 26059, 31359, 31661, 32218, 32330, 32680,
michael@0 6701 33146, [12167, 33307], 33337, 34214, 35438, 36046, 36341, 36984, 36983,
michael@0 6702 37549, 37521, 38275, 39854, 21069, 21892, 28472, 28982, 20840, 31109,
michael@0 6703 32341, 33203, 31950, 22092, 22609, 23720, 25514, 26366, 26365, 26970,
michael@0 6704 29401, 30095, 30094, 30990, 31062, 31199, 31895, 32032, 32068, 34311,
michael@0 6705 35380, 38459, 36961, [12239, 40736], 20711, 21109, 21452, 21474, 20489,
michael@0 6706 21930, 22766, 22863, 29245, 23435, 23652, 21277, 24803, 24819, 25436,
michael@0 6707 25475, 25407, 25531, 25805, 26089, 26361, 24035, 27085, 27133, 28437,
michael@0 6708 29157, 20105, 30185, 30456, 31379, 31967, 32207, 32156, 32865, 33609,
michael@0 6709 33624, 33900, 33980, 34299, 35013, [12187, 36208], 36865, 36973, 37783,
michael@0 6710 38684, 39442, 20687, 22679, 24974, 33235, 34101, 36104, 36896, 20419,
michael@0 6711 20596, 21063, 21363, 24687, 25417, 26463, 28204, [12188, 36275], 36895,
michael@0 6712 20439, 23646, 36042, 26063, 32154, 21330, 34966, 20854, 25539, 23384,
michael@0 6713 23403, 23562, 25613, 26449, 36956, 20182, 22810, 22826, 27760, 35409,
michael@0 6714 21822, 22549, 22949, 24816, 25171, 26561, 33333, 26965, 38464, 39364,
michael@0 6715 39464, 20307, 22534, 23550, 32784, 23729, 24111, 24453, 24608, 24907,
michael@0 6716 25140, 26367, 27888, 28382, 32974, 33151, 33492, 34955, 36024, 36864,
michael@0 6717 36910, 38538, 40667, 39899, 20195, 21488, [12068, 22823], 31532, 37261,
michael@0 6718 38988, 40441, 28381, 28711, 21331, 21828, 23429, 25176, 25246, 25299,
michael@0 6719 27810, 28655, 29730, 35351, 37944, 28609, 35582, 33592, 20967, 34552,
michael@0 6720 21482, 21481, 20294, 36948, [12192, 36784], 22890, 33073, 24061, 31466,
michael@0 6721 36799, 26842, [12181, 35895], 29432, 40008, 27197, 35504, 20025, 21336,
michael@0 6722 22022, 22374, 25285, 25506, 26086, 27470, 28129, 28251, 28845, 30701,
michael@0 6723 31471, 31658, 32187, 32829, 32966, 34507, 35477, 37723, 22243, 22727,
michael@0 6724 24382, 26029, 26262, 27264, 27573, 30007, 35527, 20516, 30693, 22320,
michael@0 6725 24347, 24677, 26234, 27744, 30196, 31258, 32622, 33268, 34584, 36933,
michael@0 6726 39347, 31689, 30044, [12149, 31481], 31569, 33988, 36880, 31209, 31378,
michael@0 6727 33590, 23265, 30528, 20013, 20210, 23449, 24544, 25277, 26172, 26609,
michael@0 6728 27880, [12173, 34411], 34935, 35387, 37198, 37619, 39376, 27159, 28710,
michael@0 6729 29482, 33511, 33879, 36015, 19969, 20806, 20939, 21899, 23541, 24086,
michael@0 6730 24115, 24193, 24340, 24373, 24427, 24500, 25074, 25361, 26274, 26397,
michael@0 6731 28526, 29266, 30010, 30522, 32884, 33081, 33144, 34678, 35519, 35548,
michael@0 6732 36229, 36339, 37530, [11985, 12199, 38263], 38914, [12227, 40165], 21189,
michael@0 6733 25431, 30452, 26389, 27784, 29645, 36035, 37806, 38515, 27941, 22684,
michael@0 6734 26894, 27084, 36861, 37786, 30171, 36890, 22618, 26626, 25524, 27131,
michael@0 6735 20291, 28460, 26584, 36795, 34086, 32180, 37716, 26943, 28528, 22378,
michael@0 6736 22775, 23340, 32044, [12118, 29226], 21514, 37347, 40372, 20141, 20302,
michael@0 6737 20572, 20597, 21059, 35998, 21576, 22564, 23450, 24093, 24213, 24237,
michael@0 6738 24311, 24351, 24716, 25269, 25402, 25552, 26799, 27712, 30855, 31118,
michael@0 6739 31243, 32224, 33351, 35330, 35558, 36420, 36883, 37048, 37165, 37336,
michael@0 6740 [12237, 40718], 27877, 25688, 25826, 25973, 28404, 30340, 31515, 36969,
michael@0 6741 37841, 28346, 21746, 24505, 25764, 36685, 36845, 37444, 20856, 22635,
michael@0 6742 22825, 23637, 24215, 28155, 32399, 29980, 36028, 36578, 39003, 28857,
michael@0 6743 20253, 27583, 28593, [12133, 30000], 38651, 20814, 21520, 22581, 22615,
michael@0 6744 22956, 23648, 24466, [12099, 26007], 26460, 28193, 30331, 33759, 36077,
michael@0 6745 36884, 37117, 37709, 30757, 30778, 21162, 24230, [12063, 22303], 22900,
michael@0 6746 24594, 20498, 20826, 20908, 20941, [12049, 20992], 21776, 22612, 22616,
michael@0 6747 22871, 23445, 23798, 23947, 24764, 25237, 25645, 26481, 26691, 26812,
michael@0 6748 26847, 30423, 28120, 28271, 28059, 28783, 29128, 24403, 30168, 31095,
michael@0 6749 31561, 31572, 31570, 31958, 32113, 21040, 33891, 34153, 34276, 35342,
michael@0 6750 35588, [12182, 35910], 36367, 36867, 36879, 37913, 38518, 38957, 39472,
michael@0 6751 38360, 20685, 21205, 21516, 22530, 23566, 24999, 25758, 27934, 30643,
michael@0 6752 31461, 33012, 33796, 36947, 37509, 23776, 40199, 21311, 24471, 24499,
michael@0 6753 28060, 29305, 30563, 31167, 31716, 27602, 29420, 35501, 26627, 27233,
michael@0 6754 20984, 31361, 26932, 23626, 40182, 33515, 23493, [12195, 37193], 28702,
michael@0 6755 22136, 23663, 24775, 25958, 27788, 35930, 36929, 38931, 21585, 26311,
michael@0 6756 37389, 22856, 37027, 20869, 20045, 20970, 34201, 35598, 28760, 25466,
michael@0 6757 37707, 26978, 39348, 32260, 30071, 21335, 26976, 36575, 38627, 27741,
michael@0 6758 [12038, 20108], 23612, 24336, 36841, 21250, 36049, [12161, 32905], 34425,
michael@0 6759 24319, [12103, 26085], 20083, [12042, 20837], 22914, 23615, 38894, 20219,
michael@0 6760 22922, 24525, 35469, 28641, 31152, 31074, 23527, 33905, 29483, 29105,
michael@0 6761 24180, 24565, 25467, 25754, 29123, 31896, 20035, 24316, 20043, 22492,
michael@0 6762 22178, 24745, 28611, 32013, 33021, 33075, 33215, 36786, 35223, 34468,
michael@0 6763 24052, 25226, 25773, 35207, 26487, 27874, 27966, 29750, 30772, 23110,
michael@0 6764 32629, 33453, [12218, 39340], 20467, 24259, 25309, 25490, 25943, 26479,
michael@0 6765 30403, 29260, 32972, 32954, 36649, 37197, 20493, 22521, 23186, 26757,
michael@0 6766 26995, 29028, 29437, 36023, 22770, 36064, 38506, 36889, 34687, 31204,
michael@0 6767 30695, 33833, 20271, 21093, 21338, 25293, 26575, 27850, [12137, 30333],
michael@0 6768 31636, 31893, 33334, 34180, 36843, 26333, 28448, 29190, 32283, 33707,
michael@0 6769 39361, [12008, 40614], 20989, 31665, 30834, 31672, 32903, 31560, 27368,
michael@0 6770 24161, 32908, 30033, 30048, [12043, 20843], 37474, 28300, 30330, 37271,
michael@0 6771 39658, 20240, 32624, 25244, 31567, 38309, 40169, 22138, 22617, 34532,
michael@0 6772 38588, 20276, 21028, 21322, 21453, 21467, 24070, 25644, 26001, 26495,
michael@0 6773 27710, 27726, 29256, 29359, 29677, 30036, 32321, 33324, 34281, 36009,
michael@0 6774 31684, [12196, 37318], 29033, 38930, 39151, 25405, 26217, 30058, 30436,
michael@0 6775 30928, 34115, 34542, 21290, 21329, 21542, 22915, 24199, 24444, 24754,
michael@0 6776 25161, 25209, 25259, 26000, [12112, 27604], 27852, 30130, [12138, 30382],
michael@0 6777 30865, 31192, 32203, 32631, 32933, 34987, 35513, 36027, 36991,
michael@0 6778 [12206, 38750], [12214, 39131], 27147, 31800, 20633, 23614, 24494, 26503,
michael@0 6779 27608, 29749, 30473, 32654, [12240, 40763], 26570, 31255, 21305,
michael@0 6780 [12134, 30091], 39661, 24422, 33181, 33777, 32920, 24380, 24517, 30050,
michael@0 6781 31558, 36924, 26727, 23019, 23195, 32016, 30334, 35628, 20469, 24426,
michael@0 6782 27161, 27703, 28418, 29922, 31080, 34920, 35413, 35961, 24287, 25551,
michael@0 6783 30149, 31186, 33495, 37672, 37618, 33948, 34541, 39981, 21697, 24428,
michael@0 6784 25996, 27996, 28693, 36007, 36051, 38971, 25935, 29942, 19981, 20184,
michael@0 6785 22496, 22827, 23142, 23500, 20904, 24067, 24220, 24598, 25206, 25975,
michael@0 6786 26023, 26222, 28014, [12119, 29238], 31526, 33104, 33178, 33433, 35676,
michael@0 6787 36000, 36070, 36212, [12201, 38428], 38468, 20398, 25771, 27494, 33310,
michael@0 6788 33889, 34154, 37096, 23553, 26963, [12213, 39080], 33914, 34135, 20239,
michael@0 6789 21103, 24489, 24133, 26381, 31119, 33145, 35079, 35206, 28149, 24343,
michael@0 6790 25173, 27832, 20175, 29289, 39826, 20998, 21563, 22132, 22707, 24996,
michael@0 6791 25198, 28954, 22894, 31881, 31966, 32027, 38640, [12098, 25991], 32862,
michael@0 6792 19993, 20341, 20853, 22592, 24163, 24179, 24330, 26564, 20006, 34109,
michael@0 6793 38281, 38491, [12150, 31859], [12212, 38913], 20731, 22721, 30294, 30887,
michael@0 6794 21029, 30629, 34065, 31622, 20559, 22793, [12122, 29255], 31687, 32232,
michael@0 6795 36794, 36820, 36941, 20415, 21193, 23081, 24321, 38829, 20445, 33303,
michael@0 6796 37610, 22275, 25429, 27497, 29995, 35036, 36628, 31298, 21215, 22675,
michael@0 6797 24917, 25098, 26286, [11935, 27597], 31807, 33769, 20515, 20472, 21253,
michael@0 6798 21574, 22577, 22857, 23453, 23792, 23791, 23849, 24214, 25265, 25447,
michael@0 6799 25918, [12101, 26041], 26379, 27861, 27873, 28921, 30770, 32299, 32990,
michael@0 6800 33459, 33804, 34028, 34562, 35090, 35370, 35914, 37030, 37586, 39165,
michael@0 6801 40179, 40300, 20047, 20129, 20621, 21078, 22346, 22952, 24125,
michael@0 6802 {f: 2, c: 24536}, 25151, 26292, 26395, 26576, 26834, 20882, 32033, 32938,
michael@0 6803 33192, 35584, 35980, 36031, 37502, 38450, 21536, 38956, 21271, 20693,
michael@0 6804 [12056, 21340], 22696, 25778, 26420, 29287, 30566, 31302, 37350, 21187,
michael@0 6805 27809, 27526, 22528, 24140, 22868, 26412, 32763, 20961, 30406, 25705,
michael@0 6806 30952, 39764, [12231, 40635], 22475, 22969, 26151, 26522, 27598, 21737,
michael@0 6807 27097, 24149, 33180, 26517, 39850, 26622, 40018, 26717, 20134, 20451,
michael@0 6808 [12060, 21448], 25273, 26411, 27819, 36804, 20397, 32365, 40639, 19975,
michael@0 6809 24930, 28288, 28459, 34067, 21619, 26410, 39749, [11922, 24051], 31637,
michael@0 6810 23724, 23494, 34588, 28234, 34001, 31252, 33032, 22937, 31885,
michael@0 6811 [11936, 27665], 30496, 21209, 22818, 28961, 29279, [12141, 30683], 38695,
michael@0 6812 40289, 26891, 23167, 23064, 20901, 21517, 21629, 26126, 30431, 36855,
michael@0 6813 37528, 40180, 23018, 29277, 28357, 20813, 26825, 32191, 32236,
michael@0 6814 [12207, 38754], 40634, 25720, 27169, 33538, 22916, 23391, [12113, 27611],
michael@0 6815 29467, 30450, 32178, 32791, 33945, 20786, [12106, 26408], 40665,
michael@0 6816 [12140, 30446], 26466, 21247, 39173, 23588, 25147, 31870, 36016, 21839,
michael@0 6817 24758, 32011, [12200, 38272], 21249, 20063, 20918, 22812, 29242, 32822,
michael@0 6818 37326, 24357, [12142, 30690], 21380, 24441, 32004, 34220, 35379, 36493,
michael@0 6819 38742, 26611, 34222, 37971, 24841, 24840, 27833, 30290, 35565, 36664,
michael@0 6820 21807, 20305, 20778, 21191, 21451, 23461, 24189, 24736, 24962, 25558,
michael@0 6821 26377, 26586, 28263, 28044, {f: 2, c: 29494}, 30001, 31056, 35029, 35480,
michael@0 6822 36938, [12194, 37009], 37109, 38596, 34701, [12067, 22805], 20104, 20313,
michael@0 6823 19982, 35465, 36671, 38928, 20653, 24188, 22934, 23481, 24248, 25562,
michael@0 6824 25594, 25793, 26332, 26954, 27096, 27915, 28342, 29076, [12132, 29992],
michael@0 6825 31407, [12154, 32650], 32768, 33865, 33993, 35201, 35617, 36362, 36965,
michael@0 6826 38525, 39178, 24958, 25233, 27442, 27779, 28020, 32716, 32764, 28096,
michael@0 6827 32645, 34746, 35064, 26469, 33713, 38972, 38647, 27931, 32097, 33853,
michael@0 6828 37226, 20081, 21365, 23888, 27396, 28651, 34253, 34349, 35239, 21033,
michael@0 6829 21519, 23653, 26446, 26792, 29702, 29827, 30178, 35023, 35041,
michael@0 6830 [12197, 37324], 38626, 38520, 24459, 29575, [12148, 31435], 33870, 25504,
michael@0 6831 30053, 21129, 27969, 28316, 29705, 30041, 30827, 31890, 38534,
michael@0 6832 [12015, 31452], [12243, 40845], 20406, 24942, 26053, 34396, 20102, 20142,
michael@0 6833 20698, 20001, 20940, 23534, 26009, 26753, 28092, 29471, 30274, 30637,
michael@0 6834 31260, 31975, 33391, 35538, 36988, 37327, 38517, 38936, [12050, 21147],
michael@0 6835 32209, 20523, 21400, 26519, 28107, 29136, 29747, 33256, 36650, 38563,
michael@0 6836 40023, 40607, 29792, 22593, 28057, 32047, 39006, 20196, 20278, 20363,
michael@0 6837 20919, 21169, 23994, 24604, 29618, 31036, 33491, 37428, 38583, 38646,
michael@0 6838 38666, 40599, 40802, 26278, 27508, 21015, 21155, 28872, 35010, 24265,
michael@0 6839 24651, 24976, 28451, 29001, 31806, 32244, 32879, 34030, 36899, 37676,
michael@0 6840 21570, 39791, 27347, 28809, 36034, 36335, 38706, 21172, 23105, 24266,
michael@0 6841 24324, 26391, 27004, 27028, 28010, 28431, 29282, 29436, 31725,
michael@0 6842 [12156, 32769], 32894, 34635, 37070, 20845, 40595, 31108, 32907, 37682,
michael@0 6843 35542, 20525, 21644, 35441, 27498, 36036, 33031, 24785, 26528, 40434,
michael@0 6844 20121, 20120, 39952, 35435, 34241, 34152, 26880, 28286, 30871, 33109,
michael@0 6845 24332, 19984, 19989, 20010, 20017, [12034, 20022], 20028, [12035, 20031],
michael@0 6846 20034, 20054, 20056, 20098, [12037, 20101], 35947, 20106, 33298, 24333,
michael@0 6847 20110, {f: 2, c: 20126}, [12039, 20128], 20130, 20144, 20147, 20150, 20174,
michael@0 6848 20173, 20164, 20166, 20162, 20183, 20190, 20205, 20191, 20215, 20233,
michael@0 6849 20314, 20272, 20315, 20317, 20311, 20295, 20342, 20360, 20367, 20376,
michael@0 6850 20347, 20329, 20336, 20369, 20335, 20358, 20374, 20760, 20436, 20447,
michael@0 6851 20430, 20440, 20443, 20433, 20442, 20432, {f: 2, c: 20452}, 20506, 20520,
michael@0 6852 20500, 20522, 20517, 20485, 20252, 20470, 20513, 20521, 20524, 20478,
michael@0 6853 20463, 20497, 20486, 20547, 20551, 26371, 20565, 20560, 20552, 20570,
michael@0 6854 20566, 20588, 20600, 20608, 20634, 20613, 20660, 20658, {f: 2, c: 20681},
michael@0 6855 20659, 20674, 20694, 20702, 20709, 20717, 20707, 20718, 20729, 20725,
michael@0 6856 20745, {f: 2, c: 20737}, 20758, 20757, 20756, 20762, 20769, 20794, 20791,
michael@0 6857 20796, 20795, [12041, 20799], [11918, 20800], 20818, 20812, 20820, 20834,
michael@0 6858 31480, {f: 2, c: 20841}, 20846, 20864, [12044, 20866], 22232, 20876, 20873,
michael@0 6859 20879, 20881, 20883, 20885, [12045, 20886], 20900, 20902, 20898,
michael@0 6860 {f: 2, c: 20905}, [12046, 20907], 20915, {f: 2, c: 20913}, 20912, 20917,
michael@0 6861 20925, 20933, 20937, 20955, [12047, 20960], 34389, 20969, 20973, 20976,
michael@0 6862 [12048, 20981], 20990, 20996, 21003, 21012, 21006, 21031, 21034, 21038,
michael@0 6863 21043, 21049, 21071, 21060, {f: 2, c: 21067}, 21086, 21076, 21098, 21108,
michael@0 6864 21097, 21107, 21119, 21117, 21133, 21140, 21138, 21105, 21128, 21137,
michael@0 6865 36776, 36775, {f: 2, c: 21164}, 21180, 21173, 21185, 21197, 21207, 21214,
michael@0 6866 21219, 21222, 39149, 21216, 21235, 21237, 21240, [12051, 21241], 21254,
michael@0 6867 21256, 30008, 21261, 21264, 21263, [12052, 21269], [12053, 21274], 21283,
michael@0 6868 21295, 21297, 21299, [12054, 21304], 21312, 21318, 21317, 19991, 21321,
michael@0 6869 21325, 20950, 21342, [12057, 21353], 21358, 22808, 21371, 21367,
michael@0 6870 [12058, 21378], 21398, 21408, 21414, 21413, 21422, 21424, [12059, 21430],
michael@0 6871 21443, 31762, 38617, 21471, 26364, 29166, 21486, 21480, 21485, 21498,
michael@0 6872 21505, 21565, 21568, {f: 2, c: 21548}, 21564, 21550, 21558, 21545, 21533,
michael@0 6873 21582, 21647, 21621, 21646, 21599, 21617, 21623, 21616, 21650, 21627,
michael@0 6874 21632, 21622, 21636, 21648, 21638, 21703, 21666, 21688, 21669, 21676,
michael@0 6875 21700, 21704, 21672, 21675, 21698, 21668, 21694, 21692, 21720,
michael@0 6876 {f: 2, c: 21733}, 21775, 21780, 21757, 21742, 21741, 21754, 21730, 21817,
michael@0 6877 21824, 21859, 21836, 21806, 21852, 21829, {f: 2, c: 21846}, 21816, 21811,
michael@0 6878 21853, 21913, 21888, 21679, 21898, 21919, 21883, 21886, 21912, 21918,
michael@0 6879 21934, 21884, 21891, 21929, 21895, 21928, 21978, 21957, 21983, 21956,
michael@0 6880 21980, 21988, 21972, 22036, 22007, 22038, 22014, 22013, 22043, 22009,
michael@0 6881 22094, 22096, 29151, 22068, 22070, 22066, 22072, 22123, 22116, 22063,
michael@0 6882 22124, 22122, 22150, 22144, 22154, 22176, 22164, 22159, 22181, 22190,
michael@0 6883 22198, 22196, 22210, 22204, 22209, 22211, 22208, 22216, 22222, 22225,
michael@0 6884 22227, [12062, 22231], 22254, 22265, 22272, 22271, 22276, 22281, 22280,
michael@0 6885 22283, 22285, 22291, 22296, 22294, 21959, 22300, 22310, {f: 2, c: 22327},
michael@0 6886 22350, 22331, 22336, 22351, 22377, 22464, 22408, 22369, 22399, 22409,
michael@0 6887 22419, 22432, 22451, 22436, 22442, 22448, 22467, 22470, 22484,
michael@0 6888 {f: 2, c: 22482}, 22538, 22486, 22499, 22539, 22553, 22557, 22642, 22561,
michael@0 6889 22626, 22603, 22640, 27584, 22610, 22589, 22649, 22661, 22713, 22687,
michael@0 6890 22699, 22714, 22750, 22715, 22712, 22702, 22725, 22739, 22737, 22743,
michael@0 6891 22745, 22744, 22757, 22748, 22756, 22751, 22767, 22778, 22777,
michael@0 6892 {f: 3, c: 22779}, [12065, 22786], [12066, 22794], 22800, 22811, 26790,
michael@0 6893 22821, {f: 2, c: 22828}, 22834, 22840, 22846, 31442, 22869, 22864, 22862,
michael@0 6894 22874, 22872, 22882, 22880, 22887, 22892, 22889, 22904, 22913, 22941,
michael@0 6895 20318, 20395, 22947, 22962, 22982, 23016, 23004, 22925, {f: 2, c: 23001},
michael@0 6896 23077, 23071, 23057, 23068, 23049, 23066, 23104, 23148, 23113,
michael@0 6897 {f: 2, c: 23093}, 23138, 23146, 23194, 23228, 23230, 23243, 23234, 23229,
michael@0 6898 23267, 23255, 23270, 23273, 23254, {f: 2, c: 23290}, 23308, 23307, 23318,
michael@0 6899 23346, 23248, 23338, 23350, 23358, 23363, 23365, 23360, 23377, 23381,
michael@0 6900 {f: 2, c: 23386}, 23397, 23401, 23408, 23411, 23413, 23416, 25992, 23418,
michael@0 6901 [12071, 23424], 23427, 23462, 23480, 23491, 23495, 23497, 23508, 23504,
michael@0 6902 23524, 23526, 23522, 23518, 23525, 23531, 23536, 23542, 23539, 23557,
michael@0 6903 {f: 2, c: 23559}, 23565, 23571, 23584, [11920, 12074, 23586], 23592,
michael@0 6904 [12075, 23608], 23609, 23617, 23622, 23630, 23635, 23632, 23631, 23409,
michael@0 6905 23660, [12076, 23662], 20066, 23670, 23673, 23692, 23697, 23700, 22939,
michael@0 6906 23723, 23739, 23734, 23740, 23735, 23749, 23742, 23751, 23769, 23785,
michael@0 6907 23805, 23802, 23789, 23948, 23786, 23819, 23829, 23831, 23900, 23839,
michael@0 6908 23835, 23825, 23828, 23842, 23834, 23833, 23832, 23884, 23890, 23886,
michael@0 6909 23883, 23916, 23923, 23926, 23943, 23940, 23938, 23970, 23965, 23980,
michael@0 6910 23982, 23997, 23952, 23991, 23996, 24009, 24013, 24019, 24018, 24022,
michael@0 6911 [12078, 24027], 24043, 24050, 24053, 24075, 24090, 24089, 24081, 24091,
michael@0 6912 {f: 2, c: 24118}, 24132, 24131, 24128, 24142, 24151, 24148, 24159, 24162,
michael@0 6913 24164, 24135, {f: 2, c: 24181}, [11923, 12083, 24186], 40636,
michael@0 6914 [12084, 24191], 24224, {f: 2, c: 24257}, 24264, 24272, 24271, 24278, 24291,
michael@0 6915 24285, {f: 2, c: 24282}, 24290, 24289, {f: 2, c: 24296}, 24300, 24305,
michael@0 6916 24307, 24304, [12085, 24308], 24312, [12086, 24318], 24323, 24329, 24413,
michael@0 6917 24412, [12087, 24331], 24337, 24342, 24361, 24365, 24376, 24385, 24392,
michael@0 6918 24396, 24398, 24367, [11924, 24401], {f: 2, c: 24406}, 24409,
michael@0 6919 [12090, 24417], 24429, [12091, 24435], 24439, 24451, 24450, 24447, 24458,
michael@0 6920 24456, 24465, 24455, 24478, 24473, 24472, 24480, 24488, 24493, 24508,
michael@0 6921 24534, 24571, 24548, 24568, 24561, 24541, 24755, 24575, 24609, 24672,
michael@0 6922 24601, 24592, 24617, 24590, 24625, 24603, 24597, 24619, 24614, 24591,
michael@0 6923 24634, 24666, 24641, 24682, 24695, 24671, 24650, 24646, 24653, 24675,
michael@0 6924 24643, 24676, 24642, 24684, 24683, 24665, 24705, 24717, 24807, 24707,
michael@0 6925 24730, 24708, 24731, {f: 2, c: 24726}, 24722, 24743, 24715, 24801, 24760,
michael@0 6926 24800, 24787, 24756, 24560, 24765, 24774, 24757, 24792, 24909, 24853,
michael@0 6927 24838, {f: 2, c: 24822}, 24832, 24820, 24826, 24835, 24865, 24827, 24817,
michael@0 6928 {f: 2, c: 24845}, 24903, 24894, 24872, 24871, 24906, 24895, 24892, 24876,
michael@0 6929 24884, 24893, 24898, 24900, 24947, 24951, {f: 3, c: 24920}, 24939, 24948,
michael@0 6930 24943, 24933, 24945, 24927, 24925, 24915, 24949, 24985, 24982, 24967,
michael@0 6931 25004, 24980, 24986, 24970, 24977, 25003, 25006, 25036, 25034, 25033,
michael@0 6932 25079, 25032, 25027, 25030, 25018, 25035, 32633, 25037, 25062, 25059,
michael@0 6933 25078, 25082, 25076, 25087, 25085, 25084, 25086, 25088, [12093, 25096],
michael@0 6934 25097, 25101, 25100, 25108, 25115, 25118, 25121, 25130, 25134, 25136,
michael@0 6935 {f: 2, c: 25138}, 25153, 25166, 25182, 25187, 25179, 25184, 25192, 25212,
michael@0 6936 25218, 25225, 25214, {f: 2, c: 25234}, 25238, 25300, 25219, 25236, 25303,
michael@0 6937 25297, 25275, 25295, 25343, 25286, 25812, 25288, 25308, 25292, 25290,
michael@0 6938 25282, 25287, 25243, 25289, 25356, 25326, 25329, 25383, 25346, 25352,
michael@0 6939 25327, 25333, 25424, 25406, 25421, 25628, 25423, 25494, 25486, 25472,
michael@0 6940 25515, 25462, 25507, 25487, 25481, 25503, 25525, 25451, 25449, 25534,
michael@0 6941 25577, 25536, 25542, 25571, 25545, 25554, 25590, 25540, 25622, 25652,
michael@0 6942 25606, 25619, 25638, 25654, 25885, 25623, 25640, 25615, 25703, 25711,
michael@0 6943 25718, 25678, 25898, 25749, 25747, 25765, 25769, 25736, 25788, 25818,
michael@0 6944 25810, 25797, 25799, 25787, 25816, 25794, 25841, 25831, 33289,
michael@0 6945 {f: 2, c: 25824}, 25260, 25827, 25839, 25900, 25846, 25844, 25842, 25850,
michael@0 6946 25856, 25853, 25880, 25884, 25861, 25892, 25891, 25899, [12097, 25908],
michael@0 6947 [11929, 25909], 25911, 25910, 25912, 30027, 25928, 25942, 25941, 25933,
michael@0 6948 25944, 25950, 25949, 25970, 25976, {f: 2, c: 25986}, 35722, 26011, 26015,
michael@0 6949 26027, 26039, 26051, 26054, 26049, 26052, 26060, 26066, 26075, 26073,
michael@0 6950 [12102, 26080], [11931, 26081], 26097, 26482, 26122, 26115, 26107, 26483,
michael@0 6951 {f: 2, c: 26165}, 26164, 26140, 26191, 26180, 26185, 26177, 26206, 26205,
michael@0 6952 26212, {f: 2, c: 26215}, 26207, 26210, 26224, 26243, 26248, 26254, 26249,
michael@0 6953 26244, 26264, 26269, 26305, 26297, 26313, 26302, 26300, 26308, 26296,
michael@0 6954 26326, 26330, 26336, 26175, 26342, 26345, [12104, 26352], 26357, 26359,
michael@0 6955 26383, 26390, 26398, {f: 2, c: 26406}, 38712, 26414, 26431, 26422, 26433,
michael@0 6956 26424, 26423, 26438, 26462, 26464, 26457, {f: 2, c: 26467}, 26505, 26480,
michael@0 6957 26537, 26492, 26474, 26508, 26507, 26534, 26529, 26501, 26551, 26607,
michael@0 6958 26548, 26604, 26547, 26601, 26552, 26596, 26590, 26589, 26594, 26606,
michael@0 6959 26553, 26574, 26566, 26599, 27292, 26654, 26694, 26665, 26688, 26701,
michael@0 6960 26674, 26702, 26803, 26667, 26713, 26723, 26743, 26751, 26783, 26767,
michael@0 6961 26797, 26772, 26781, 26779, 26755, 27310, 26809, 26740, 26805, 26784,
michael@0 6962 26810, 26895, 26765, 26750, 26881, 26826, 26888, 26840, 26914, 26918,
michael@0 6963 26849, 26892, 26829, 26836, 26855, 26837, 26934, 26898, 26884, 26839,
michael@0 6964 26851, 26917, 26873, 26848, 26863, 26920, 26922, 26906, 26915, 26913,
michael@0 6965 26822, 27001, 26999, 26972, 27000, 26987, 26964, 27006, 26990, 26937,
michael@0 6966 26996, 26941, 26969, 26928, 26977, 26974, 26973, 27009, 26986, 27058,
michael@0 6967 27054, 27088, 27071, 27073, 27091, 27070, 27086, 23528, 27082, 27101,
michael@0 6968 27067, 27075, 27047, 27182, 27025, 27040, 27036, 27029, 27060, 27102,
michael@0 6969 27112, 27138, 27163, 27135, 27402, 27129, 27122, 27111, 27141, 27057,
michael@0 6970 27166, 27117, 27156, 27115, 27146, 27154, 27329, 27171, 27155, 27204,
michael@0 6971 27148, 27250, 27190, 27256, 27207, 27234, 27225, 27238, 27208, 27192,
michael@0 6972 27170, 27280, 27277, 27296, 27268, {f: 2, c: 27298}, 27287, 34327, 27323,
michael@0 6973 27331, 27330, 27320, 27315, 27308, 27358, 27345, 27359, 27306, 27354,
michael@0 6974 27370, 27387, 27397, 34326, 27386, 27410, 27414, 39729, 27423, 27448,
michael@0 6975 27447, 30428, 27449, 39150, 27463, 27459, 27465, 27472, 27481, 27476,
michael@0 6976 27483, 27487, 27489, 27512, [12109, 27513], {f: 2, c: 27519}, 27524, 27523,
michael@0 6977 27533, 27544, 27541, 27550, 27556, {f: 2, c: 27562}, 27567, 27570, 27569,
michael@0 6978 [12110, 27571], 27575, 27580, 27590, [12111, 27595], 27603, 27615, 27628,
michael@0 6979 27627, 27635, 27631, 40638, 27656, 27667, [12115, 27668], 27675, 27684,
michael@0 6980 27683, 27742, 27733, 27746, 27754, 27778, 27789, 27802, 27777, 27803,
michael@0 6981 27774, 27752, 27763, 27794, 27792, 27844, 27889, 27859, 27837, 27863,
michael@0 6982 27845, 27869, 27822, 27825, 27838, 27834, 27867, 27887, 27865, 27882,
michael@0 6983 27935, 34893, 27958, 27947, 27965, 27960, 27929, 27957, 27955, 27922,
michael@0 6984 27916, 28003, 28051, 28004, 27994, 28025, 27993, 28046, 28053, 28644,
michael@0 6985 28037, 28153, 28181, 28170, 28085, 28103, 28134, 28088, 28102, 28140,
michael@0 6986 28126, 28108, 28136, 28114, 28101, 28154, 28121, 28132, 28117, 28138,
michael@0 6987 28142, 28205, 28270, 28206, 28185, 28274, 28255, 28222, 28195, 28267,
michael@0 6988 28203, 28278, 28237, 28191, 28227, 28218, 28238, 28196, 28415, 28189,
michael@0 6989 28216, 28290, 28330, 28312, 28361, 28343, 28371, 28349, 28335, 28356,
michael@0 6990 28338, {f: 2, c: 28372}, 28303, 28325, 28354, 28319, 28481, 28433, 28748,
michael@0 6991 28396, 28408, 28414, 28479, 28402, 28465, 28399, 28466, 28364, 28478,
michael@0 6992 28435, 28407, 28550, 28538, 28536, 28545, 28544, 28527, 28507, 28659,
michael@0 6993 28525, 28546, 28540, 28504, 28558, 28561, 28610, 28518, 28595, 28579,
michael@0 6994 28577, 28580, 28601, 28614, 28586, 28639, 28629, 28652, 28628, 28632,
michael@0 6995 28657, 28654, 28635, 28681, 28683, 28666, 28689, 28673, 28687, 28670,
michael@0 6996 28699, 28698, 28532, 28701, 28696, 28703, 28720, 28734, 28722, 28753,
michael@0 6997 28771, 28825, 28818, 28847, 28913, 28844, 28856, 28851, 28846, 28895,
michael@0 6998 28875, 28893, 28889, 28937, 28925, 28956, 28953, 29029, 29013, 29064,
michael@0 6999 29030, 29026, 29004, 29014, 29036, 29071, 29179, 29060, 29077, 29096,
michael@0 7000 29100, 29143, 29113, 29118, 29138, 29129, 29140, 29134, 29152, 29164,
michael@0 7001 29159, 29173, 29180, 29177, 29183, 29197, 29200, 29211, 29224, 29229,
michael@0 7002 29228, 29232, 29234, [12120, 29243], 29244, [12121, 29247], 29248, 29254,
michael@0 7003 29259, 29272, 29300, 29310, 29314, 29313, 29319, 29330, 29334, 29346,
michael@0 7004 29351, 29369, 29362, 29379, 29382, 29380, 29390, 29394, 29410,
michael@0 7005 {f: 2, c: 29408}, 29433, 29431, 20495, 29463, 29450, 29468, 29462, 29469,
michael@0 7006 29492, 29487, 29481, 29477, 29502, {f: 2, c: 29518}, 40664, 29527, 29546,
michael@0 7007 29544, 29552, 29560, 29557, 29563, 29562, 29640, 29619, 29646, 29627,
michael@0 7008 29632, 29669, 29678, 29662, 29858, 29701, 29807, 29733, 29688, 29746,
michael@0 7009 29754, 29781, 29759, 29791, 29785, 29761, 29788, 29801, 29808, 29795,
michael@0 7010 29802, 29814, 29822, 29835, 29854, 29863, 29898, 29903, 29908, 29681,
michael@0 7011 29920, 29923, 29927, 29929, 29934, 29938, {f: 2, c: 29936}, 29944, 29943,
michael@0 7012 29956, 29955, 29957, 29964, 29966, 29965, 29973, 29971, 29982, 29990,
michael@0 7013 29996, 30012, 30020, 30029, 30026, 30025, 30043, 30022, 30042, 30057,
michael@0 7014 30052, 30055, 30059, 30061, 30072, 30070, {f: 2, c: 30086}, 30068, 30090,
michael@0 7015 30089, 30082, 30100, 30106, 30109, 30117, 30115, 30146, 30131, 30147,
michael@0 7016 30133, 30141, 30136, 30140, 30129, 30157, 30154, 30162, 30169, 30179,
michael@0 7017 30174, {f: 2, c: 30206}, 30204, 30209, 30192, 30202, {f: 2, c: 30194},
michael@0 7018 30219, 30221, 30217, 30239, 30247, {f: 3, c: 30240}, 30244, 30260, 30256,
michael@0 7019 30267, {f: 2, c: 30279}, 30278, 30300, 30296, {f: 2, c: 30305},
michael@0 7020 {f: 3, c: 30312}, 30311, 30316, 30320, 30322, [12136, 30326], 30328, 30332,
michael@0 7021 30336, 30339, 30344, 30347, 30350, 30358, 30355, {f: 2, c: 30361}, 30384,
michael@0 7022 30388, {f: 3, c: 30392}, 30402, 30413, 30422, 30418, 30430, 30433, 30437,
michael@0 7023 30439, 30442, 34351, 30459, 30472, 30471, 30468, 30505, 30500, 30494,
michael@0 7024 {f: 2, c: 30501}, 30491, {f: 2, c: 30519}, 30535, 30554, 30568, 30571,
michael@0 7025 30555, 30565, 30591, 30590, 30585, 30606, 30603, 30609, 30624, 30622,
michael@0 7026 30640, 30646, 30649, 30655, {f: 2, c: 30652}, 30651, 30663, 30669, 30679,
michael@0 7027 30682, 30684, 30691, 30702, 30716, 30732, 30738, 31014, 30752, 31018,
michael@0 7028 30789, 30862, 30836, 30854, 30844, 30874, 30860, 30883, 30901, 30890,
michael@0 7029 30895, 30929, 30918, 30923, 30932, 30910, 30908, 30917, 30922, 30956,
michael@0 7030 30951, 30938, 30973, 30964, 30983, 30994, 30993, 31001, 31020, 31019,
michael@0 7031 31040, 31072, 31063, 31071, 31066, 31061, 31059, 31098, 31103, 31114,
michael@0 7032 31133, 31143, 40779, 31146, 31150, 31155, {f: 2, c: 31161}, 31177, 31189,
michael@0 7033 31207, 31212, 31201, 31203, 31240, 31245, {f: 2, c: 31256}, 31264, 31263,
michael@0 7034 31104, 31281, 31291, 31294, 31287, 31299, 31319, 31305, {f: 2, c: 31329},
michael@0 7035 31337, 40861, 31344, 31353, 31357, 31368, 31383, 31381, 31384, 31382,
michael@0 7036 31401, 31432, 31408, 31414, 31429, 31428, 31423, 36995, 31431, 31434,
michael@0 7037 31437, 31439, 31445, 31443, {f: 2, c: 31449}, 31453, {f: 2, c: 31457},
michael@0 7038 31462, 31469, 31472, 31490, 31503, 31498, 31494, 31539, {f: 2, c: 31512},
michael@0 7039 31518, 31541, 31528, 31542, 31568, 31610, 31492, 31565, 31499, 31564,
michael@0 7040 31557, 31605, 31589, 31604, 31591, {f: 2, c: 31600}, 31596, 31598, 31645,
michael@0 7041 31640, 31647, 31629, 31644, 31642, 31627, 31634, 31631, 31581, 31641,
michael@0 7042 31691, 31681, 31692, 31695, 31668, 31686, 31709, 31721, 31761, 31764,
michael@0 7043 31718, 31717, 31840, 31744, 31751, 31763, 31731, 31735, 31767, 31757,
michael@0 7044 31734, 31779, 31783, 31786, 31775, 31799, 31787, 31805, 31820, 31811,
michael@0 7045 31828, 31823, 31808, 31824, 31832, 31839, 31844, 31830, 31845, 31852,
michael@0 7046 31861, 31875, 31888, 31908, 31917, 31906, 31915, 31905, 31912, 31923,
michael@0 7047 31922, 31921, 31918, 31929, 31933, 31936, 31941, 31938, 31960, 31954,
michael@0 7048 31964, 31970, 39739, 31983, 31986, 31988, 31990, 31994, 32006, 32002,
michael@0 7049 32028, 32021, 32010, 32069, 32075, 32046, 32050, 32063, 32053, 32070,
michael@0 7050 32115, 32086, 32078, 32114, 32104, 32110, 32079, 32099, 32147, 32137,
michael@0 7051 32091, 32143, 32125, 32155, 32186, 32174, 32163, 32181, 32199, 32189,
michael@0 7052 32171, 32317, 32162, 32175, 32220, 32184, 32159, 32176, 32216, 32221,
michael@0 7053 32228, 32222, 32251, 32242, 32225, 32261, 32266, 32291, 32289, 32274,
michael@0 7054 32305, 32287, 32265, 32267, 32290, 32326, 32358, 32315, 32309, 32313,
michael@0 7055 32323, 32311, 32306, 32314, 32359, 32349, 32342, 32350, {f: 2, c: 32345},
michael@0 7056 32377, 32362, 32361, 32380, 32379, 32387, 32213, 32381, 36782, 32383,
michael@0 7057 {f: 2, c: 32392}, 32396, 32402, 32400, {f: 2, c: 32403}, 32406, 32398,
michael@0 7058 {f: 2, c: 32411}, 32568, 32570, 32581, {f: 3, c: 32588}, 32592,
michael@0 7059 [12153, 32593], 32597, 32596, 32600, {f: 2, c: 32607}, {f: 2, c: 32616},
michael@0 7060 32615, 32632, 32642, 32646, 32643, 32648, 32647, 32652, 32660, 32670,
michael@0 7061 32669, 32666, 32675, 32687, 32690, 32697, 32686, 32694, 32696, 35697,
michael@0 7062 {f: 2, c: 32709}, 32714, 32725, 32724, 32737, 32742, 32745, 32755, 32761,
michael@0 7063 39132, 32774, 32772, 32779, [12158, 32786], {f: 2, c: 32792}, 32796, 32801,
michael@0 7064 32808, 32831, 32827, 32842, 32838, 32850, 32856, 32858, 32863, 32866,
michael@0 7065 32872, 32883, 32882, 32880, 32886, 32889, 32893, [12160, 32895], 32900,
michael@0 7066 32902, 32901, 32923, 32915, 32922, 32941, 20880, 32940, 32987, 32997,
michael@0 7067 32985, 32989, 32964, 32986, 32982, 33033, 33007, 33009, 33051, 33065,
michael@0 7068 33059, 33071, 33099, 38539, 33094, 33086, 33107, 33105, 33020, 33137,
michael@0 7069 33134, {f: 2, c: 33125}, 33140, 33155, 33160, 33162, 33152, 33154, 33184,
michael@0 7070 33173, 33188, 33187, 33119, 33171, 33193, 33200, 33205, 33214, 33208,
michael@0 7071 33213, 33216, 33218, 33210, 33225, 33229, 33233, 33241, 33240, 33224,
michael@0 7072 33242, {f: 2, c: 33247}, 33255, {f: 2, c: 33274}, 33278, {f: 2, c: 33281},
michael@0 7073 33285, 33287, 33290, 33293, 33296, 33302, 33321, 33323, 33336, 33331,
michael@0 7074 33344, 33369, 33368, 33373, 33370, 33375, 33380, 33378, 33384,
michael@0 7075 {f: 2, c: 33386}, 33326, 33393, 33399, [12171, 33400], 33406, 33421, 33426,
michael@0 7076 33451, 33439, 33467, 33452, 33505, 33507, 33503, 33490, 33524, 33523,
michael@0 7077 33530, 33683, 33539, 33531, 33529, 33502, 33542, 33500, 33545, 33497,
michael@0 7078 33589, 33588, 33558, 33586, 33585, 33600, 33593, 33616, 33605, 33583,
michael@0 7079 33579, {f: 2, c: 33559}, 33669, 33690, 33706, 33695, 33698, 33686, 33571,
michael@0 7080 33678, 33671, 33674, 33660, 33717, 33651, 33653, 33696, 33673, 33704,
michael@0 7081 33780, 33811, 33771, 33742, 33789, 33795, 33752, 33803, 33729, 33783,
michael@0 7082 33799, 33760, 33778, 33805, 33826, 33824, 33725, 33848, 34054, 33787,
michael@0 7083 33901, 33834, 33852, 34138, 33924, 33911, 33899, 33965, 33902, 33922,
michael@0 7084 33897, 33862, 33836, 33903, 33913, 33845, 33994, 33890, 33977, 33983,
michael@0 7085 33951, 34009, 33997, 33979, 34010, 34000, 33985, 33990, 34006, 33953,
michael@0 7086 34081, 34047, 34036, {f: 2, c: 34071}, 34092, 34079, 34069, 34068, 34044,
michael@0 7087 34112, 34147, 34136, 34120, 34113, 34306, 34123, 34133, 34176, 34212,
michael@0 7088 34184, 34193, 34186, 34216, 34157, 34196, 34203, 34282, 34183, 34204,
michael@0 7089 34167, 34174, 34192, 34249, 34234, 34255, 34233, 34256, 34261, 34269,
michael@0 7090 34277, 34268, 34297, 34314, 34323, 34315, 34302, 34298, 34310, 34338,
michael@0 7091 34330, 34352, 34367, [12172, 34381], 20053, 34388, 34399, 34407, 34417,
michael@0 7092 34451, 34467, {f: 2, c: 34473}, {f: 2, c: 34443}, 34486, 34479, 34500,
michael@0 7093 34502, 34480, 34505, 34851, 34475, 34516, 34526, 34537, 34540, 34527,
michael@0 7094 34523, 34543, 34578, 34566, 34568, 34560, 34563, 34555, 34577, 34569,
michael@0 7095 34573, 34553, 34570, 34612, 34623, 34615, 34619, 34597, 34601, 34586,
michael@0 7096 34656, 34655, 34680, 34636, 34638, 34676, 34647, 34664, 34670, 34649,
michael@0 7097 34643, 34659, 34666, 34821, 34722, 34719, 34690, 34735, 34763, 34749,
michael@0 7098 34752, 34768, 38614, 34731, 34756, 34739, 34759, 34758, 34747, 34799,
michael@0 7099 34802, 34784, 34831, 34829, 34814, {f: 2, c: 34806}, 34830, 34770, 34833,
michael@0 7100 34838, 34837, 34850, 34849, 34865, 34870, 34873, 34855, 34875, 34884,
michael@0 7101 34882, 34898, 34905, 34910, 34914, 34923, 34945, 34942, 34974, 34933,
michael@0 7102 34941, 34997, 34930, 34946, 34967, 34962, 34990, 34969, 34978, 34957,
michael@0 7103 34980, 34992, 35007, 34993, {f: 2, c: 35011}, 35028, {f: 2, c: 35032},
michael@0 7104 35037, 35065, 35074, 35068, 35060, 35048, 35058, 35076, 35084, 35082,
michael@0 7105 35091, 35139, 35102, 35109, {f: 2, c: 35114}, 35137, 35140, 35131, 35126,
michael@0 7106 35128, 35148, 35101, 35168, 35166, 35174, 35172, 35181, 35178, 35183,
michael@0 7107 35188, 35191, [12177, 35198], 35203, 35208, 35210, 35219, 35224, 35233,
michael@0 7108 35241, 35238, 35244, 35247, 35250, 35258, 35261, {f: 2, c: 35263}, 35290,
michael@0 7109 {f: 2, c: 35292}, 35303, 35316, 35320, 35331, 35350, 35344, 35340, 35355,
michael@0 7110 35357, 35365, 35382, 35393, 35419, 35410, 35398, 35400, 35452, 35437,
michael@0 7111 35436, 35426, 35461, 35458, 35460, 35496, 35489, 35473, {f: 2, c: 35493},
michael@0 7112 35482, 35491, 35524, 35533, 35522, 35546, 35563, 35571, 35559, 35556,
michael@0 7113 35569, 35604, 35552, 35554, 35575, 35550, 35547, 35596, 35591, 35610,
michael@0 7114 35553, 35606, 35600, 35607, 35616, 35635, 38827, 35622, 35627, 35646,
michael@0 7115 35624, 35649, 35660, 35663, 35662, 35657, 35670, 35675, 35674, 35691,
michael@0 7116 35679, 35692, 35695, 35700, 35709, 35712, 35724, 35726, {f: 2, c: 35730},
michael@0 7117 35734, {f: 2, c: 35737}, 35898, 35905, 35903, 35912, 35916, 35918, 35920,
michael@0 7118 [12183, 35925], 35938, 35948, [12184, 35960], 35962, 35970, 35977, 35973,
michael@0 7119 35978, {f: 2, c: 35981}, 35988, 35964, 35992, 25117, 36013, 36010, 36029,
michael@0 7120 {f: 2, c: 36018}, 36014, 36022, 36040, 36033, 36068, 36067, 36058, 36093,
michael@0 7121 {f: 2, c: 36090}, {f: 2, c: 36100}, 36106, 36103, 36111, 36109, 36112,
michael@0 7122 40782, 36115, 36045, 36116, 36118, 36199, 36205, 36209, 36211, 36225,
michael@0 7123 36249, 36290, 36286, 36282, 36303, 36314, 36310, 36300, 36315, 36299,
michael@0 7124 {f: 2, c: 36330}, 36319, 36323, 36348, {f: 2, c: 36360}, 36351,
michael@0 7125 {f: 2, c: 36381}, 36368, 36383, 36418, 36405, 36400, 36404, 36426, 36423,
michael@0 7126 36425, 36428, 36432, 36424, 36441, 36452, 36448, 36394, 36451, 36437,
michael@0 7127 36470, 36466, 36476, 36481, 36487, 36485, 36484, 36491, 36490, 36499,
michael@0 7128 36497, 36500, 36505, 36522, 36513, 36524, 36528, 36550, 36529, 36542,
michael@0 7129 36549, 36552, 36555, 36571, 36579, 36604, 36603, 36587, 36606, 36618,
michael@0 7130 36613, 36629, 36626, 36633, 36627, 36636, 36639, 36635, 36620, 36646,
michael@0 7131 36659, 36667, 36665, 36677, 36674, 36670, 36684, 36681, 36678, 36686,
michael@0 7132 36695, 36700, {f: 3, c: 36706}, 36764, 36767, 36771, 36781, 36783, 36791,
michael@0 7133 36826, 36837, 36834, 36842, 36847, 36999, 36852, 36869, {f: 2, c: 36857},
michael@0 7134 36881, 36885, 36897, 36877, 36894, 36886, 36875, 36903, 36918, 36917,
michael@0 7135 36921, 36856, {f: 4, c: 36943}, 36878, 36937, 36926, 36950, 36952, 36958,
michael@0 7136 36968, 36975, 36982, 38568, 36978, 36994, 36989, 36993, 36992, 37002,
michael@0 7137 37001, 37007, 37032, 37039, 37041, 37045, 37090, 37092, 25160, 37083,
michael@0 7138 37122, 37138, 37145, 37170, 37168, 37194, 37206, 37208, 37219, 37221,
michael@0 7139 37225, 37235, 37234, 37259, 37257, 37250, 37282, 37291, 37295, 37290,
michael@0 7140 37301, 37300, 37306, {f: 2, c: 37312}, 37321, 37323, 37328, 37334, 37343,
michael@0 7141 37345, 37339, 37372, {f: 2, c: 37365}, 37406, 37375, 37396, 37420, 37397,
michael@0 7142 37393, 37470, 37463, 37445, 37449, 37476, 37448, 37525, 37439, 37451,
michael@0 7143 37456, 37532, 37526, 37523, 37531, 37466, 37583, 37561, 37559, 37609,
michael@0 7144 37647, 37626, 37700, 37678, 37657, 37666, 37658, 37667, 37690, 37685,
michael@0 7145 37691, 37724, 37728, 37756, 37742, 37718, 37808, {f: 2, c: 37804}, 37780,
michael@0 7146 37817, {f: 2, c: 37846}, 37864, 37861, 37848, 37827, 37853, 37840, 37832,
michael@0 7147 37860, 37914, 37908, 37907, 37891, 37895, 37904, 37942, 37931, 37941,
michael@0 7148 37921, 37946, 37953, 37970, 37956, 37979, 37984, 37986, 37982, 37994,
michael@0 7149 37417, 38000, 38005, 38007, 38013, 37978, 38012, 38014, 38017, 38015,
michael@0 7150 38274, 38279, 38282, 38292, 38294, {f: 2, c: 38296}, 38304, 38312, 38311,
michael@0 7151 38317, 38332, 38331, 38329, 38334, 38346, 28662, 38339, 38349, 38348,
michael@0 7152 38357, 38356, 38358, 38364, 38369, 38373, 38370, 38433, 38440,
michael@0 7153 {f: 2, c: 38446}, 38466, 38476, 38479, 38475, 38519, 38492, 38494, 38493,
michael@0 7154 38495, 38502, 38514, 38508, 38541, 38552, 38549, 38551, 38570, 38567,
michael@0 7155 {f: 2, c: 38577}, 38576, 38580, [12202, 38582], 38584, [12203, 38585],
michael@0 7156 38606, 38603, 38601, 38605, 35149, 38620, 38669, 38613, 38649, 38660,
michael@0 7157 38662, 38664, 38675, 38670, 38673, 38671, 38678, 38681, 38692, 38698,
michael@0 7158 38704, 38713, {f: 2, c: 38717}, 38724, 38726, 38728, 38722, 38729, 38748,
michael@0 7159 38752, 38756, 38758, 38760, 21202, 38763, 38769, 38777, 38789, 38780,
michael@0 7160 38785, 38778, 38790, 38795, {f: 2, c: 38799}, 38812, 38824, 38822, 38819,
michael@0 7161 {f: 2, c: 38835}, 38851, 38854, 38856, [12209, 38859], 38876,
michael@0 7162 [12210, 38893], 40783, 38898, 31455, 38902, 38901, 38927, 38924, 38968,
michael@0 7163 38948, 38945, 38967, 38973, 38982, 38991, 38987, 39019, {f: 3, c: 39023},
michael@0 7164 39028, 39027, 39082, 39087, 39089, 39094, 39108, 39107, 39110, 39145,
michael@0 7165 39147, 39171, 39177, 39186, 39188, 39192, 39201, {f: 2, c: 39197}, 39204,
michael@0 7166 39200, 39212, 39214, {f: 2, c: 39229}, 39234, 39241, 39237, 39248, 39243,
michael@0 7167 {f: 2, c: 39249}, 39244, 39253, {f: 2, c: 39319}, 39333, {f: 2, c: 39341},
michael@0 7168 39356, 39391, 39387, 39389, 39384, 39377, {f: 2, c: 39405},
michael@0 7169 {f: 2, c: 39409}, 39419, 39416, 39425, 39439, 39429, 39394, 39449, 39467,
michael@0 7170 39479, 39493, 39490, 39488, 39491, 39486, 39509, 39501, 39515, 39511,
michael@0 7171 39519, 39522, 39525, 39524, 39529, 39531, 39530, 39597, 39600, 39612,
michael@0 7172 39616, 39631, 39633, {f: 2, c: 39635}, 39646, [12221, 39647],
michael@0 7173 {f: 2, c: 39650}, 39654, 39663, 39659, 39662, 39668, 39665, 39671, 39675,
michael@0 7174 39686, 39704, 39706, 39711, {f: 2, c: 39714}, [12222, 39717],
michael@0 7175 {f: 4, c: 39719}, 39726, [12223, 39727], [12224, 39730], 39748, 39747,
michael@0 7176 39759, {f: 2, c: 39757}, 39761, 39768, 39796, 39827, 39811, 39825,
michael@0 7177 {f: 2, c: 39830}, {f: 2, c: 39839}, 39848, 39860, 39872, 39882, 39865,
michael@0 7178 39878, 39887, {f: 2, c: 39889}, 39907, 39906, 39908, 39892, 39905, 39994,
michael@0 7179 39922, 39921, 39920, 39957, 39956, 39945, 39955, 39948, 39942, 39944,
michael@0 7180 39954, 39946, 39940, 39982, 39963, 39973, 39972, 39969, 39984, 40007,
michael@0 7181 39986, 40006, 39998, 40026, 40032, 40039, 40054, 40056, 40167, 40172,
michael@0 7182 40176, 40201, 40200, 40171, 40195, 40198, 40234, 40230, 40367, 40227,
michael@0 7183 40223, 40260, 40213, 40210, 40257, 40255, 40254, 40262, 40264,
michael@0 7184 {f: 2, c: 40285}, 40292, 40273, 40272, 40281, 40306, 40329, 40327, 40363,
michael@0 7185 40303, 40314, 40346, 40356, 40361, 40370, 40388, 40385, 40379, 40376,
michael@0 7186 40378, 40390, 40399, 40386, 40409, 40403, 40440, 40422, 40429, 40431,
michael@0 7187 40445, {f: 2, c: 40474}, 40478, [12228, 40565], 40569, 40573, 40577, 40584,
michael@0 7188 {f: 2, c: 40587}, 40594, 40597, 40593, 40605, [12230, 40613], 40617, 40632,
michael@0 7189 40618, 40621, 38753, 40652, {f: 3, c: 40654}, 40660, 40668, 40670, 40669,
michael@0 7190 40672, 40677, 40680, 40687, 40692, {f: 2, c: 40694}, [12235, 40697],
michael@0 7191 {f: 2, c: 40699}, [12236, 40701], {f: 2, c: 40711}, 30391, 40725, 40737,
michael@0 7192 40748, 40766, [12241, 40778], [12242, 40786], 40788, 40803,
michael@0 7193 {f: 3, c: 40799}, {f: 2, c: 40806}, 40812, 40810, 40823, 40818, 40822,
michael@0 7194 40853, [12244, 40860], [12245, 40864], 22575, 27079, 36953, 29796, 0,
michael@0 7195 {f: 76, c: 9472}, {f: 20, c: 9312}, {f: 10, c: 8544}, 13129, 13076, 0,
michael@0 7196 13133, 0, 13095, 0, 13110, 13137, 0, 13069, 13094, 0, 13099, 13130, 0,
michael@0 7197 {f: 3, c: 13212}, {f: 2, c: 13198}, 13252, 13217, 12317, 12319, 8470,
michael@0 7198 13261, 0, {f: 5, c: 12964}, {f: 2, c: 12849}, 12857, 13182, 13181, 13180,
michael@0 7199 8750, 8721, {s: 3}, 8735, 8895, 0, 0, 21854, {s: 7}, 167133, 0, 0, 28976,
michael@0 7200 0, 40407, {s: 4}, 64054, 0, 0, 22169, 15694, {s: 4}, 20448, 0, 0, 36544, 0,
michael@0 7201 194797, {s: 4}, 153716, 32363, 33606, 167670, {s: 3}, 40572, 0, 0, 26171,
michael@0 7202 0, 40628, {s: 4}, 26629, {s: 5}, 23650, 0, 194780, 0, 32353, 0, 0, 64070,
michael@0 7203 {s: 5}, 34083, 37292, {s: 7}, 34796, {s: 8}, 25620, 0, 0, 39506, {s: 4},
michael@0 7204 64074, 0, 194692, {s: 4}, 31774, {s: 6}, 64016, 25681, 0, 0, 63980, 22625,
michael@0 7205 39002, 0, 194679, {s: 3}, 31153, 0, 28678, {s: 9}, 22218, {s: 3}, 21085, 0,
michael@0 7206 28497, 37297, {s: 10}, 64106, {s: 6}, 38960, 0, 40629, {s: 9}, 33802,
michael@0 7207 63939, {f: 2, c: 63890}, 63897, 0, 34847, 194575, 0, 194771, 194584,
michael@0 7208 {s: 7}, 137754, 23643, {s: 4}, 25890, 0, 0, 26618, 0, 26766, 0, 148432,
michael@0 7209 194848, {s: 21}, 34110, {s: 15}, 30562, {s: 12}, 65075, 0,
michael@0 7210 {f: 2, c: 65073}, {s: 4}, 65072, {f: 2, c: 65077}, {f: 2, c: 65081}, 0, 0,
michael@0 7211 {f: 2, c: 65079}, {f: 2, c: 65087}, {f: 2, c: 65085}, {f: 4, c: 65089},
michael@0 7212 {f: 2, c: 65083}, {s: 41}, {f: 3, c: 12436}, 0, 0, 22099, {s: 41}, 65508,
michael@0 7213 65287, 65282, 0, 9665, 9655, 8681, 8679, 8678, 8680, 9634, 9831, 9825,
michael@0 7214 9828, 9826, 13216, 13218, {f: 2, c: 13220}, 13207, 8467, 13208, 13235,
michael@0 7215 13234, 13233, 13232, {f: 3, c: 13189}, 13259, 13200, 13268, 13206, 13090,
michael@0 7216 13078, 13080, 13077, 13059, 13091, 13143, 13122, 13113, 13115, 13056,
michael@0 7217 13105, 13127, 13086, 13098, 0, 13183, 8481, 9742, 12342, 12320, {s: 3},
michael@0 7218 {f: 9, c: 9352}, {f: 20, c: 9332}, 12881, {f: 10, c: 8560},
michael@0 7219 {f: 10, c: 12882}, {f: 26, c: 9372}, 12867, 12861, 12863, 12852, 12856,
michael@0 7220 12851, 12860, 12866, 12862, 12854, 12853, 12859, 12864, 12858, 12976,
michael@0 7221 12973, 12969, 12975, 12948, 12970, 12952, 12971, 12946, 12945, 12947,
michael@0 7222 12972, 12974, 12950, {s: 8}, {f: 3, c: 9131}, 0, {f: 3, c: 9127}, 0, 13260,
michael@0 7223 13061, 0, 0, 13215, 13219, 13222, 0, 0, 12958, {f: 2, c: 13192}, 13256,
michael@0 7224 8749, 0, 12848, {f: 6, c: 12842}, 12855, 12865, 10145, {s: 3}, 9673, 9824,
michael@0 7225 9829, 9827, 9830, {f: 4, c: 9728}, 9758, {f: 2, c: 9756}, 9759, 12953,
michael@0 7226 9450, {f: 2, c: 8554}, {s: 3}, {f: 8, c: 9601}, 9615, 9614, 9613, 9612,
michael@0 7227 9611, 9610, 9609, {f: 2, c: 9620}, {f: 2, c: 9581}, 9584, 9583, 9552, 9566,
michael@0 7228 9578, 9569, {f: 2, c: 9698}, 9701, 9700, 0, 0, {f: 3, c: 9585}, {s: 20},
michael@0 7229 20956, 29081, {f: 9, c: 10102}, {s: 3}, {f: 2, c: 8570}, {s: 3}, 8575,
michael@0 7230 8458, 8457, 0, 0, 12292, 8646, {f: 2, c: 8644}, 0, {f: 4, c: 12535}, 0, 0,
michael@0 7231 12957, {s: 3}, 13179, {s: 3}, 13107, 13134, {s: 30}, 32394, 35100, 37704,
michael@0 7232 37512, 34012, 20425, 28859, 26161, 26824, 37625, 26363, 24389,
michael@0 7233 [12033, 20008], 20193, 20220, 20224, 20227, 20281, 20310, 20370, 20362,
michael@0 7234 20378, 20372, 20429, 20544, 20514, 20479, 20510, 20550, 20592, 20546,
michael@0 7235 20628, 20724, 20696, 20810, 20836, 20893, 20926, 20972, 21013, 21148,
michael@0 7236 21158, 21184, 21211, 21248, 0, 21284, 21362, 21395, 21426, 21469, 64014,
michael@0 7237 21660, 21642, 21673, 21759, 21894, 22361, 22373, 22444, 22472, 22471,
michael@0 7238 64015, 0, 22686, 22706, 22795, 22867, 22875, 22877, 22883, 22948, 22970,
michael@0 7239 23382, 23488, 29999, 23512, 0, 23582, 23718, 23738, 23797, 23847, 23891, 0,
michael@0 7240 23874, 23917, {f: 2, c: 23992}, 24016, 24353, 24372, 24423, 24503, 24542,
michael@0 7241 24669, 24709, 24714, 24798, 24789, 24864, 24818, 24849, 24887, 24880,
michael@0 7242 24984, 25107, 25254, 25589, 25696, 25757, 25806, 25934, 26112, 26133,
michael@0 7243 26121, 26158, 0, 26148, 26213, 26199, 26201, 64018, 26227, 26265, 26272,
michael@0 7244 26290, 26303, 26362, 26382, 0, 26470, 26555, 26706, 26560, 0, 26692, 26831,
michael@0 7245 64019, 26984, 64020, 27032, 27106, 27184, 27243, 27206, 27251, 27262,
michael@0 7246 27362, 27364, 27606, 27711, 27740, 27782, 27759, 27866, 27908, 28039,
michael@0 7247 28015, 28054, 28076, 28111, 28152, 28146, 28156, 28217, 28252, 28199,
michael@0 7248 28220, 28351, 28552, 28597, 28661, 28677, 28679, 28712, 28805, 28843,
michael@0 7249 28943, 28932, 29020, {f: 2, c: 28998}, 0, 29121, 29182, 29361, 29374,
michael@0 7250 29476, 64022, 29559, 29629, 29641, 29654, 29667, 29650, 29703, 29685,
michael@0 7251 29734, 29738, 29737, 29742, 0, 29833, 29855, 29953, 30063, 30338, 30364,
michael@0 7252 30366, 30363, 30374, 64023, 30534, 21167, 30753, 30798, 30820, 30842,
michael@0 7253 31024, {f: 3, c: 64024}, 31124, 64027, 31131, 31441, 31463, 64028, 31467,
michael@0 7254 31646, 64029, 32072, 0, 32183, 32160, 32214, 32338, 32583, 32673, 64030,
michael@0 7255 33537, 33634, 33663, 33735, 33782, 33864, 33972, 34131, 34137, 34155,
michael@0 7256 64031, 34224, {f: 2, c: 64032}, 34823, 35061, 35346, 35383, 35449, 35495,
michael@0 7257 35518, 35551, 64034, 35574, 35667, 35711, 36080, 36084, 36114, 36214,
michael@0 7258 64035, 36559, 0, 64037, 36967, 37086, 64038, 37141, 37159, 37338, 37335,
michael@0 7259 37342, {f: 2, c: 37357}, {f: 2, c: 37348}, 37382, 37392, 37386, 37434,
michael@0 7260 37440, 37436, 37454, 37465, 37457, 37433, 37479, 37543, {f: 2, c: 37495},
michael@0 7261 37607, 37591, 37593, 37584, 64039, 37589, 37600, 37587, 37669, 37665,
michael@0 7262 37627, 64040, 37662, 37631, 37661, 37634, 37744, 37719, 37796, 37830,
michael@0 7263 37854, 37880, 37937, 37957, 37960, 38290, 0, 64041, 38557, 38575, 38707,
michael@0 7264 38715, 38723, 38733, 38735, [12205, 38737], 0, 38999, 39013,
michael@0 7265 {f: 2, c: 64042}, 39207, 64044, 39326, 39502, 39641, 39644, 39797, 39794,
michael@0 7266 39823, 39857, 39867, 39936, 40304, 40299, 64045, 40473, 40657, 0, 92,
michael@0 7267 {s: 634}, 8364, 8486, 0, 0, 64256, {f: 2, c: 64259}, 257, 299, 363, 275,
michael@0 7268 333, 256, 298, 362, 274, 332, {f: 4, c: 8539}, {f: 2, c: 8531}, 8304,
michael@0 7269 {f: 6, c: 8308}, {f: 10, c: 8320}, 461, 282, 0, 7868, 463, 0, 296, 465, 0,
michael@0 7270 467, 366, 360, 462, 283, 0, 7869, 464, 0, 297, 466, 0, 468, 367, 361, 593,
michael@0 7271 8049, 8048, 509, 0, 596, 0, 0, 601, 0, 0, 602, 0, 0, 603, 8051, 8050, 0,
michael@0 7272 331, 629, 652, 0, 0, 658, 643, 720, {s: 682}, {f: 10, c: 12832}, {s: 108},
michael@0 7273 {f: 4, c: 12892}, {f: 15, c: 12977}, {s: 50}, {f: 26, c: 9424},
michael@0 7274 {f: 26, c: 9398}, {s: 48}, {f: 47, c: 13008}, 0, {f: 10, c: 12928}, 12944,
michael@0 7275 {f: 6, c: 12938}, 0, 12959, {s: 6}, {f: 2, c: 12960}, 12955, 12954, 12963,
michael@0 7276 12962, 12951, 0, 12956, 12949, {s: 6}, 9676, {s: 11}, 10111,
michael@0 7277 {f: 10, c: 9451}, {s: 510}, 8414, {s: 815}, 13274, {s: 3}, 8448, 13250, 0,
michael@0 7278 0, 8453, 0, 13169, 0, 0, 13197, 13211, {s: 3}, {f: 2, c: 13271}, {s: 3},
michael@0 7279 {f: 2, c: 13057}, 13060, 13062, 0, 13064, 0, 13063, 13066, 0, 13065, 0,
michael@0 7280 13067, 0, 13068, {f: 6, c: 13070}, 0, 13079, 0, 13081, 0, {f: 4, c: 13082},
michael@0 7281 {f: 3, c: 13087}, 13092, 0, 13093, 0, 0, {f: 2, c: 13096}, 0, 13101, 0, 0,
michael@0 7282 {f: 3, c: 13102}, 13106, 0, 0, {f: 2, c: 13108}, 13116, {s: 3}, 13111, 0,
michael@0 7283 13112, 13114, 13117, 13121, {f: 3, c: 13118}, {f: 4, c: 13123}, 13128,
michael@0 7284 {f: 2, c: 13131}, {f: 2, c: 13135}, 0, 0, 13138, 13140, 0, 0, 13139,
michael@0 7285 {f: 2, c: 13141}, {s: 132}, 8501, 976, 8714, 8463, 0, 981, 987, 977, 0,
michael@0 7286 {f: 2, c: 9832}, 9836, {s: 5}, 12347, 0, {f: 3, c: 12339}, 8252, 8265,
michael@0 7287 {s: 5}, 8723, 0, 8771, {f: 2, c: 8818}, {s: 6}, {f: 2, c: 12312},
michael@0 7288 {f: 2, c: 65375}, {s: 10}, 9115, {f: 2, c: 9117}, 9120, {s: 4}, 9121,
michael@0 7289 {f: 2, c: 9123}, 9126, {s: 12}, [9116, 9119, 9122, 9125, 9130], {s: 8},
michael@0 7290 9986, 0, 0, 12349, 0, 12447, 0, 0, 8709, 8864, 8854, 8856, 8853, 8855,
michael@0 7291 {s: 4}, 9664, 9654, {s: 4}, 8656, 8596, {f: 2, c: 8600}, {f: 2, c: 8598},
michael@0 7292 8652, 8651, {s: 10}, 12336, 8967, {s: 8}, 10048, 10047, {s: 7}, 9643, 0,
michael@0 7293 9642, 0, 10010, {s: 12}, 9702, {s: 4}, 10070, {s: 379}, {f: 2, c: 65093},
michael@0 7294 {s: 679}, 64103, 64098, 32227, [12232, 40643], 28331, 64082, 64061, 64069,
michael@0 7295 64062, 27114, 28212, 64096, 64071, 64056, 64066, 64078, 34395, 64105,
michael@0 7296 64052, 64099, 25581, 25802, 30799, 64084, 63856, 64077, 64097, 64072,
michael@0 7297 64076, {f: 2, c: 64091}, 64081, 64067, 64090, 28041, 29376, 0, 194885,
michael@0 7298 64086, 64080, 64049, 64059, 24034, 64063, 64101, 21373, 64055, 64095,
michael@0 7299 24501, 64064, 0, 64083, 0, 64085, 64104, 64068, 64089, 26202, 64053, 64075,
michael@0 7300 64100, 64065, 64048, 0, 64057, 64051, 27493, 64058, 27599, 64050, 25150,
michael@0 7301 64079, 63773, 63964, 63798, 28122, 63952, 26310, 27511, 64087, 37706, 0,
michael@0 7302 37636, {s: 120}, 133390, {s: 120}, 35999, 11991, [11965, 158033], {s: 5},
michael@0 7303 37555, 38321, 0, 0, 194812, {s: 13}, 194965, {s: 8}, 194794, 0, 26478,
michael@0 7304 11974, 0, 194594, {s: 13}, 13314, 0, 0, 26083, {s: 4}, 134071, {s: 10},
michael@0 7305 171339, 0, 194611, 24378, {s: 8}, 11945, 0, 20465, {s: 7}, 63753, {s: 7},
michael@0 7306 11964, 0, 0, 194732, 26435, {s: 3}, 133732, 35329, 25142, 0, 0, 21555,
michael@0 7307 23067, {s: 3}, 25221, 0, 0, 194819, {s: 6}, 21567, {s: 9}, 27506, {s: 4},
michael@0 7308 29986, 19256, 0, 0, 24063, {s: 6}, 194827, 29626, 134047, {s: 3}, 194600,
michael@0 7309 0, 194849, {s: 5}, 194623, {s: 16}, 194675, {f: 2, c: 11916}, 23577,
michael@0 7310 {s: 3}, 131083, 23426, 194642, {s: 5}, 11997, [11999, 39136],
michael@0 7311 [11998, 169599], 14221, 0, [11927, 14586], 0, 194887, 0, [11909, 20155],
michael@0 7312 131490, {s: 7}, 13599, 0, 194738, 0, 0, [11971, 35200], {s: 4}, 31237,
michael@0 7313 {s: 4}, 35498, 0, 32085, 0, 28568, {s: 7}, 25591, 30246, {s: 4},
michael@0 7314 [11978, 163767], {s: 5}, 146686, {s: 5}, 13351, 0, 0, 33067, 0, 0, 194842,
michael@0 7315 {s: 5}, 11950, {s: 5}, 194714, {s: 3}, 194831, {s: 19}, 22305, 135741,
michael@0 7316 194586, 0, 64003, {s: 7}, 21534, 15240, 20839, {s: 4}, 63839, {s: 9},
michael@0 7317 20023, {s: 13}, [11946, 150804], 24421, 23020, 194658, 0, 24217, {s: 46},
michael@0 7318 13416, {s: 8}, 21200, {s: 9}, 26625, 0, 195024, 195039, {s: 5}, 153215, 0,
michael@0 7319 0, 11959, {s: 4}, 36534, 63775, {s: 3}, 63875, {s: 5}, 31867, 63906, 0,
michael@0 7320 63898, 0, [11961, 32770], 157360, {s: 4}, [11911, 132648], 0, 0, 131210,
michael@0 7321 194604, [11915, 13630], {s: 4}, 21589, 0, 22841, 0, 0, 23414, 194669,
michael@0 7322 23572, 14306, 23782, 0, 20040, 0, 0, 194742, {s: 4}, 158105, 25371, 0, 0,
michael@0 7323 26211, 0, 194779, 0, 0, 27126, 27014, {s: 3}, 27596, 0, 28183, 0, 0, 27818,
michael@0 7324 {s: 3}, [11942, 20012], 0, 0, 29935, 30069, 30188, 30286, 16305, 30570,
michael@0 7325 30633, {s: 6}, 31571, 0, 0, 16996, {s: 3}, 194924, 0, 0, 32328, {s: 5},
michael@0 7326 11955, {s: 4}, 33089, 17491, 0, [11966, 33401], [11967, 64094],
michael@0 7327 [11968, 64093], 0, 20857, 33626, {s: 3}, 17701, 0, 34292, 131248, {s: 4},
michael@0 7328 34429, 0, 13358, 35014, {s: 6}, 18406, {s: 8}, 36808, {s: 19}, 166279, 0,
michael@0 7329 0, 167447, 0, 0, 38969, {s: 6}, 39432, {s: 4}, 39903, {s: 10}, 148206,
michael@0 7330 {s: 5}, 21385, 0, 64017, 194785, 0, 146622, 132625, 0, {f: 2, c: 19972},
michael@0 7331 19999, 20011, {f: 2, c: 20015}, {f: 2, c: 20032}, 20036, [11907, 20058],
michael@0 7332 20095, 20109, 20118, 20153, 20176, 20192, 20221, 20223, 20235, 20245,
michael@0 7333 20320, 20283, 20297, 20308, 20346, {f: 2, c: 20349}, 20375, 20414, 20431,
michael@0 7334 20477, {f: 2, c: 20480}, 20496, 20507, 20519, 20526, 20567, 20582, 20586,
michael@0 7335 20539, 20623, 20630, 20636, 20684, 20710, 20713, 20719, 20744, 20747,
michael@0 7336 20752, 20763, 20766, 20831, 20897, 20924, 0, 20974, 20980, 20993,
michael@0 7337 [11913, 20994], 21011, 21065, 21089, 21094, 21139, 21192, 21232,
michael@0 7338 {f: 2, c: 21258}, 21310, 21324, 21323, 21345, 21356, 21419, 21466, 21478,
michael@0 7339 21493, 21543, 21581, 21606, 21611, 21620, 21645, 21654, 21665, 21677,
michael@0 7340 21689, 21695, 21702, 21709, 21774, 21803, 21813, 21834, 21856, 0, 21896,
michael@0 7341 21902, 22024, {f: 2, c: 22030}, 22071, 22079, 22089, 22091, 22095, 22118,
michael@0 7342 22121, 22127, {f: 2, c: 22129}, 22165, 22170, {f: 2, c: 22188}, 22193,
michael@0 7343 22217, 22237, 22244, 22282, 22293, 22307, 22319, {f: 2, c: 22323}, 22348,
michael@0 7344 22384, 22412, 22428, 22456, 22502, 22509, {f: 2, c: 22517}, 22527, 22537,
michael@0 7345 22560, 22578, 22652, 22656, 22697, 22734, 22736, 22740, 22746, 22761,
michael@0 7346 22796, 22820, 22831, 22881, 22893, 22986, 22994, 23005, {f: 2, c: 23011},
michael@0 7347 23044, 23052, 23075, 23111, 23125, 23139, 23149, 23166, 23198, 23207,
michael@0 7348 23212, 23219, 23264, 23296, 23321, 23333, 23341, 23361, 23420,
michael@0 7349 {f: 2, c: 23422}, 23434, [11919, 23587], 23595, 23600, 23651, 23657, 23676,
michael@0 7350 23755, 23762, 23796, 23844, 23846, 23875, 23878, 23882, 23954, 23956,
michael@0 7351 23961, 23968, 24024, 24032, 24056, 24064, 24082, {f: 2, c: 24084}, 24088,
michael@0 7352 24110, 24152, {f: 2, c: 24171}, 24232, 24234, {f: 2, c: 24254}, 0, 24274,
michael@0 7353 24327, 24334, {f: 2, c: 24348}, 24354, 24360, 24374, 24379, 24384,
michael@0 7354 [12089, 24400], 24408, 24420, 24457, 24476, 24487, 24484, 24495, 24504,
michael@0 7355 [11926, 24516], 24521, 24545, 24553, 24557, 24572, 24599, 24602, 24627,
michael@0 7356 24673, 24703, 24734, 24740, 24752, 24779, 24795, 24824, {f: 3, c: 24850},
michael@0 7357 24860, 24956, 24973, 24991, 25000, 25026, 25055, 25109, 25129, 25155,
michael@0 7358 25158, [11928, 25164], 25169, 25174, 25284, 25340, 25354, 25357, 25368,
michael@0 7359 25401, {f: 2, c: 25410}, 25445, 25460, 25469, 25476, 25479, 25488, 25502,
michael@0 7360 25553, 25564, 25609, 25616, 25634, 25684, 25691, 25709, 25723,
michael@0 7361 {f: 2, c: 25790}, 25829, 25847, 25851, 25860, 25878, 25881, 25927, 25959,
michael@0 7362 25985, 25989, 26050, 26096, 26098, 26156, 26188, {f: 2, c: 26203}, 26209,
michael@0 7363 26219, 0, 26276, 26312, 26348, 26373, 26387, 26419, 26440, 26444, 26486,
michael@0 7364 26491, 26544, 26546, 26617, 26583, 26585, 26608, 26668, {f: 2, c: 26672},
michael@0 7365 26715, 26738, 26741, 26746, 26756, 26789, 26802, 26832, 26838, 26856,
michael@0 7366 26861, {f: 2, c: 26864}, 26876, 26897, 26899, 26933, 26939, 26967, 26979,
michael@0 7367 26994, {f: 2, c: 27007}, 27046, 27053, 27063, {f: 2, c: 27094}, 27137,
michael@0 7368 27151, 27157, 27176, 27188, 27198, 27205, {f: 2, c: 27216}, 27222, 27227,
michael@0 7369 27267, 27273, 27281, {f: 3, c: 27293}, 27356, 27367, 27372, 27422, 27428,
michael@0 7370 27445, 27462, 27478, 27488, 27522, 27582, 27617, 27633, 27664, 27699,
michael@0 7371 [11937, 27701], 11938, 27737, 27766, 27771, 27781, 27797, 27804, 27856,
michael@0 7372 27860, 27862, 27872, {f: 2, c: 27883}, 27886, 27914, 27918, 27921, 27950,
michael@0 7373 27991, 27998, 28005, 28034, 28095, 28100, 28106, 28118, 28137, 28194,
michael@0 7374 28241, 28359, 28362, 28366, 28413, 28442, 28458, 28463, 28467, 28506,
michael@0 7375 28510, 28514, 28541, 28555, 28557, 28562, 28564, 28570, {f: 2, c: 28583},
michael@0 7376 28598, 28634, 28638, 0, 28729, 28732, 0, 28756, {f: 2, c: 28765}, 28772,
michael@0 7377 [11939, 28780], 28798, 28801, 28821, 28855, {f: 2, c: 28883}, 28888, 28892,
michael@0 7378 28935, 28960, 28977, 29002, 29010, 29024, 29049, 29074, 0, 29131, 29139,
michael@0 7379 29142, 29184, 29213, 29227, 29240, 29249, 29267, {f: 2, c: 29269}, 29276,
michael@0 7380 29325, [11944, 29357], 29364, 29383, 29435, {f: 2, c: 29444}, 29480, 29489,
michael@0 7381 29507, 29548, 29564, 29571, {f: 2, c: 29573}, 29589, {f: 3, c: 29598},
michael@0 7382 29606, 29611, 29621, 29623, 29628, 29647, 29657, 29673, 29684, 29693,
michael@0 7383 29700, 29706, {f: 2, c: 29722}, 29732, 29736, 29740, {f: 3, c: 29743},
michael@0 7384 29753, 29764, 29767, 29771, 29773, 29777, 29783, 29798, 29803, 29809,
michael@0 7385 29824, {f: 3, c: 29829}, 29840, 29848, 29852, 29856, 29859, 29864, 29867,
michael@0 7386 29877, 29887, 29896, 29914, 29918, 30030, 30073, 30081, 30096,
michael@0 7387 [12135, 30098], 30099, 30132, 30180, 30201, 30208, 30218, {f: 2, c: 30229},
michael@0 7388 30233, 30238, 30253, 30261, 30275, 30283, 30309, 30317, 30319, 30321,
michael@0 7389 30324, {f: 2, c: 30372}, 30405, 30412, 30444, 30460, 30516, 30518, 30556,
michael@0 7390 {f: 2, c: 30559}, 30578, 30589, 30613, 30634, 30694, 30704, 30708, 30726,
michael@0 7391 30754, {f: 2, c: 30765}, 30768, 30773, 30824, 30878, 30920, 30924, 30926,
michael@0 7392 30948, {f: 2, c: 30944}, 30962, 30967, 30971, 31025, 0, [11949, 31035],
michael@0 7393 31037, 31045, {f: 2, c: 31067}, 31115, 31126, 31128, [12145, 31160], 31163,
michael@0 7394 31178, 31194, 31235, 31241, 31249, 31262, 31277, 31289, 31301, 31308,
michael@0 7395 31325, 0, 31341, 31352, 31392, 31395, 31411, {f: 2, c: 31419}, 31430,
michael@0 7396 31495, 31508, 31527, 31537, 31559, 31566, 31584, 31593, 31597, 31602,
michael@0 7397 31633, 31663, 31703, 31705, 31755, 31759, 31776, 31782, 31793, 31798,
michael@0 7398 31825, 31833, 31847, 31854, 31856, 31932, 31935, {f: 2, c: 31944}, 31959,
michael@0 7399 31961, 31965, 31979, {f: 3, c: 32007}, 32019, 32029, 32035, 32065, 32083,
michael@0 7400 32089, 32093, 32122, 32134, {f: 2, c: 32139}, 32204, 32235, 32241, 32249,
michael@0 7401 32264, 32273, 32277, 32288, 32327, 32354, 32366, 32371, 32397, 32401,
michael@0 7402 32408, 32580, 32591, [11947, 11954, 32594], [11953, 32595], 32609, 32657,
michael@0 7403 32703, 32718, 32735, 32741, 32748, {f: 2, c: 32750}, 32762, 32782, 32785,
michael@0 7404 32788, 32804, 32806, 32826, 32828, 32864, 32881, 32885, 32926, 32934,
michael@0 7405 32939, {f: 2, c: 32983}, 33046, 33048, 33082, 33098, 33100, 33153, 33156,
michael@0 7406 33204, 33231, 33273, 33283, 33313, 33330, 33332, 33350, 33355, 33359,
michael@0 7407 33422, 33454, 33463, 33470, 33478, 33534, 33603, 33617, 33621, 33670,
michael@0 7408 33677, 33682, 33688, 33705, {f: 2, c: 33727}, 33770, 33807, 33809, 33866,
michael@0 7409 33910, 33960, 33967, 33984, 33986, 34032, 34045, 34060, 34100, 34142,
michael@0 7410 34191, 34231, 34254, 34221, 34322, 34345, 34386, 34403, 34412, 34415,
michael@0 7411 34426, 34445, 34449, 34456, {f: 2, c: 34471}, 34554, 34557, 34571, 34579,
michael@0 7412 34585, 34590, 34600, 34622, 34673, 34696, 34713, {f: 2, c: 34732}, 34741,
michael@0 7413 34774, 34795, 34797, 34817, 0, 34822, 34827, 34836, 34844, 34902, 34911,
michael@0 7414 [11970, 34916], 34968, 34986, {f: 2, c: 35005}, 35018, 35026, 35035,
michael@0 7415 {f: 2, c: 35056}, 35078, {f: 3, c: 35096}, 35111, 35120, 35134, 35195,
michael@0 7416 35284, 35286, 35301, 35313, 35335, 35343, 35349, 35362, 35406, 35455,
michael@0 7417 35572, 35615, 35639, {f: 2, c: 35651}, 35668, 35740, 35742, 35911, 35924,
michael@0 7418 35955, 36004, 36057, 36065, 36088, 36094, 36123, 36201, 36204, 36228,
michael@0 7419 36237, 36245, 36262, 36294, 36302, 36324, 36332, 36384, 36427, 36460,
michael@0 7420 36464, 36474, 36498, 36526, 36531, 36561, 36564, 36601, 36631, 36662,
michael@0 7421 36774, [12193, 36789], [11981, 36790], 0, 36832, 36836, 36854, 36866,
michael@0 7422 36908, 36932, 37000, 37013, 37017, 37019, 37026, 37044, 37079, 37085,
michael@0 7423 37108, 37143, 37148, 37169, 37178, 37181, 37192, 37211, 37217, 37220,
michael@0 7424 37262, 37278, 37288, {f: 2, c: 37293}, 37298, 37308, 37360, 37367, 37371,
michael@0 7425 37383, 37416, 37427, 37432, 37443, 37447, 37455, 37472, 37570,
michael@0 7426 {f: 2, c: 37579}, 37599, 37645, 37653, 37663, 37671, 37703, 37714, 0,
michael@0 7427 37738, 37741, 37787, 37818, 37801, 37825, 37834, 37858, 37882, 37885,
michael@0 7428 37903, 37940, 37951, 37973, 37995, 38002, [11986, 38264], 38310, 38313, 0,
michael@0 7429 38324, 38333, 38362, [11983, 11990, 38429], 38465, 38488, 38532, 38564,
michael@0 7430 38569, 38610, 195060, 38622, 38633, 38641, 38658, 38665, 38746, 38755,
michael@0 7431 38766, 38771, 38810, 38818, {f: 2, c: 38837}, 38873, 38878, 38900, 38922,
michael@0 7432 38926, 38942, 38947, 38955, 38974, {f: 2, c: 38994}, 39001, 39020, 39096,
michael@0 7433 39098, 39103, 39112, 39141, {f: 2, c: 39218}, 39232, 39245, 39260, 39263,
michael@0 7434 39345, {f: 2, c: 39353}, 39369, 39426, 39446, 39460, 39463,
michael@0 7435 {f: 2, c: 39469}, 39478, 39480, 39498, 39510, {f: 2, c: 39605}, 39673,
michael@0 7436 39683, 39712, {f: 2, c: 39731}, 39795, 39801, 39847, 39873, 39879, 39895,
michael@0 7437 39911, 39915, 39927, 39930, 39933, 39947, 39975, 39978, 39990, 40001,
michael@0 7438 40019, 40035, 40048, 40055, 40194, 40258, 40263, 40291, 40297, 40316,
michael@0 7439 40318, 40333, 40369, 40387, 40391, 40406, 40415, 40427, 40436, 40469,
michael@0 7440 40477, 40612, 40616, 40620, 40679, 40686, 40720, 40722, 40727, 40729,
michael@0 7441 40751, 40759, 40761, 40769, 40773, 40791, 40808, 40817, 40821, 40848,
michael@0 7442 40852, 40866, 0, 13317, 194564, 22048, 24267, 11925, 0, 144954, 0, 28665,
michael@0 7443 28390, 29107, [11940, 64073], {s: 4}, [11980, 64102], 0, 23986, 0, 20435,
michael@0 7444 20697, 20720, 20931, 22134, 27220, 27905, 28112, 28226, 28377, 29668,
michael@0 7445 29729, 30060, 30801, 34805, 144382, 29608, 15091, 13531, 17420, 16010, 0,
michael@0 7446 0, 19432, 0, 16090, 15138, 0, 17786, 16531, 0, 18021, 16643, 17043, 18094,
michael@0 7447 13448, 140809, {f: 3, c: 63584}, 63610, 63615, {s: 23}, {f: 2, c: 8836},
michael@0 7448 {f: 2, c: 8842}, 8713, 0, {f: 2, c: 8965}, {s: 9}, {f: 2, c: 8741},
michael@0 7449 {s: 14}, 8802, 0, 8773, 8776, {f: 2, c: 8822}, {s: 4}, 8487, {s: 209},
michael@0 7450 {f: 2, c: 8922}, 8533, 8984, {f: 2, c: 7742}, {f: 2, c: 504}, 470, 472,
michael@0 7451 474, 476, 260, 728, 317, 346, 350, 356, 377, 379, 261, 731, 318, 347, 711,
michael@0 7452 351, 357, 378, 733, 380, 340, 258, 313, 262, 268, 280, 270, 323, 327, 336,
michael@0 7453 344, 368, 354, 341, 259, 314, 263, 269, 281, 271, 273, 324, 328, 337, 345,
michael@0 7454 369, 355, 729, 264, 284, 292, 308, 348, 364, 265, 285, 293, 309, 349, 365,
michael@0 7455 625, 651, 638, 620, 622, 633, 648, 598, 627, 637, 642, 656, 635, 621, 607,
michael@0 7456 626, 669, 654, 609, 624, 641, 295, 661, 660, 614, 664, 450, 595, 599, 644,
michael@0 7457 608, 403, 616, 649, 600, 604, 606, 592, 623, 650, 612, 594, 653, 613, 674,
michael@0 7458 673, 597, 657, 634, 615, 865, 712, 716, 721, 8255, 783, {f: 5, c: 741}, 0,
michael@0 7459 0, 805, 812, 825, 796, {f: 2, c: 799}, 829, 809, 815, 734, 804, 816, 828,
michael@0 7460 820, {f: 2, c: 797}, {f: 2, c: 792}, 810, {f: 2, c: 826}, 794, {s: 3},
michael@0 7461 {f: 2, c: 610}, 618, 628, 630, 632, 640, 655, 665, 668, 671, 688, 690, 695,
michael@0 7462 704, {f: 2, c: 736}, {s: 6}, 8862, {s: 287}, 12348, 12543, 0,
michael@0 7463 {f: 2, c: 12310}, 9838, 9835, {f: 2, c: 10548}, 10687, 0, 12448, 0,
michael@0 7464 {f: 2, c: 10746}, {s: 13}, 962, {f: 10, c: 9461}, {f: 2, c: 9750}, 9649,
michael@0 7465 {f: 10, c: 12784}, 0, {f: 6, c: 12794}, {f: 15, c: 9150}, 0, 0, 10003, 0,
michael@0 7466 9251, 9166, {f: 4, c: 9680}, {f: 2, c: 8263}, 0, 8273, 8258,
michael@0 7467 {f: 16, c: 12688}, {s: 13}, {f: 2, c: 9136}, {f: 12, c: 9842},
michael@0 7468 {f: 2, c: 12441}, 8413, {s: 450}, 20296, 20319, 20330, 20332, 20494, 20504,
michael@0 7469 20545, 20722, 20688, 20742, 20739, 20789, 20821, 20823, 13493, 20938,
michael@0 7470 20962, 21079, 21196, 21206, 21243, 21276, 21347, 21405, 21522, 21631,
michael@0 7471 21640, 21840, 21889, 21933, 21966, 22075, 22174, 22185, 22195, 22391,
michael@0 7472 22396, 135963, 22479, 22500, 22628, 22665, 136302, 22738, 22752, 34369,
michael@0 7473 22923, 22930, 22979, 23059, 23143, 23159, 23172, 23236, 137405, 23421,
michael@0 7474 23443, 23570, 64060, 136884, 23674, 23695, 23711, 23715, 23722, 23760,
michael@0 7475 138804, 23821, 23879, 23937, 23972, 23975, 24011, 24158, 24313, 24320,
michael@0 7476 24322, 24355, 24381, 24404, 24445, 24589, 24596, 24600, 24629, 24647,
michael@0 7477 24733, 24788, 24797, 24875, 25020, 25017, 25122, 25178, 25199, 25302,
michael@0 7478 25468, 25573, 25721, 25796, 25808, 25897, 26013, 26170, 26146, 26155,
michael@0 7479 26160, 26163, 26184, 143812, {f: 2, c: 26231}, 26253, 26299, 26331, 26344,
michael@0 7480 26439, 26497, 26515, 26520, 26523, 26620, 26653, 26787, 26890, 26953,
michael@0 7481 144836, 26946, 26980, 27045, 27087, 15286, 15299, 27113, 27125, 145215,
michael@0 7482 27195, 145251, 27284, 27301, 15375, 27419, 27436, 27495, 27561, 27565,
michael@0 7483 27607, 27647, 27653, 27764, 27800, 27899, 27846, 27953, 27961, 27967,
michael@0 7484 27992, 28052, 28074, 28123, 28125, 28228, 28254, 28337, 28353, 28432,
michael@0 7485 28505, 28513, 28542, 28556, 28576, 28604, 28615, 28618, 28656, 28750,
michael@0 7486 28789, 28836, 28900, 28971, 28958, 28974, 29009, 29032, 29061, 29063,
michael@0 7487 29114, 29124, 29205, 15935, 29339, 149489, 29479, 29520, 29542, 29602,
michael@0 7488 29739, 29766, 29794, 29805, 29862, 29865, 29897, 29951, 29975, 16242,
michael@0 7489 30158, 30210, 30216, 30308, 30337, 30365, 30378, 30390, 30414, 30420,
michael@0 7490 30438, 30449, 30474, 30489, {f: 2, c: 30541}, 30586, 30592, 30612, 30688,
michael@0 7491 152718, 30787, 30830, 30896, 152846, 30893, 30976, 31004, 31022, 31028,
michael@0 7492 31046, 31097, 31176, 153457, 31188, 31198, 31211, 31213, 31365, 154052,
michael@0 7493 31438, 31485, 31506, 31533, 31547, 31599, 31745, 31795, 155041, 31853,
michael@0 7494 31865, 31887, 31892, 31904, 31957, 32049, 32092, 32131, 32166, 32194,
michael@0 7495 32296, 32663, 32731, 32821, 32823, 32970, 32992, 33011, 33120,
michael@0 7496 {f: 2, c: 33127}, 33133, 33211, 33226, 33239, 17499, 33376, 33396, 158463,
michael@0 7497 33441, {f: 2, c: 33443}, 33449, 33471, 33493, 33533, 33536, 33570, 33581,
michael@0 7498 33594, 33607, 33661, 33703, 33743, 33745, 33761, 33793, 33798, 33887,
michael@0 7499 33904, 33907, 33925, 33950, 33978, 159296, 34098, 34078, 34095, 34148,
michael@0 7500 34170, 34188, 34210, 34251, 34285, 34303, {f: 2, c: 34308}, 34320, 159988,
michael@0 7501 34328, 34360, 34391, 34402, 17821, 34421, 34488, 34556, 34695, 17898,
michael@0 7502 34826, 34832, 35022, 161412, 35122, 35129, 35136, 35220, 35318, 35399,
michael@0 7503 35421, 35425, 35445, 35536, 35654, 35673, 35689, 35741, 35913, 35944,
michael@0 7504 36271, 36305, 36311, 36387, 36413, 36475, 164471, 18500, 36602, 36638,
michael@0 7505 36653, 36692, 164813, 36840, 36846, 36872, 36909, 37015, 37043, 37054,
michael@0 7506 {f: 2, c: 37060}, 37063, 37103, 37140, 37142, {f: 2, c: 37154}, 37167,
michael@0 7507 37172, 37251, 37361, 37705, {f: 2, c: 37732}, 37795, 37855, 37892, 37939,
michael@0 7508 37962, 37987, 38001, 38286, 38303, 38316, 38326, 38347, 38352, 38355,
michael@0 7509 18864, 38366, 38565, 38639, 38734, 38805, 38830, 38842, 38849, 38857,
michael@0 7510 38875, 38998, 39143, 39256, 39427, 39617, 39619, 39630, 39638, 39682,
michael@0 7511 39688, 19479, 39725, 39774, 39782, 39812, 39818, 39838, 39886, 39909,
michael@0 7512 39928, 39971, {f: 2, c: 40015}, 40037, {f: 2, c: 40221}, 40259, 40274,
michael@0 7513 40330, 40342, 40384, 40364, 40380, 172432, 40423, 40455, 40606, 40623,
michael@0 7514 40855, 131209, 19970, 19983, 19986, 20009, 20014, 20039, 131234, 20049,
michael@0 7515 13318, 131236, 20073, 20125, 13356, 20156, 20163, 20168, 20203, 20186,
michael@0 7516 20209, 20213, 20246, 20324, 20279, 20286, 20312, 131603, {f: 2, c: 20343},
michael@0 7517 20354, 20357, 20454, 20402, 20421, 20427, 20434, 13418, 20466, 20499,
michael@0 7518 20508, 20558, 20563, 20579, 20643, 20616, {f: 2, c: 20626}, 20629, 20650,
michael@0 7519 131883, 20657, {f: 2, c: 20666}, 20676, 20679, 20723, 131969, 20686,
michael@0 7520 131953, 20692, 20705, 13458, 132089, 20759, 132170, 20832, 132361, 20851,
michael@0 7521 20867, 20875, 13500, 20888, 20899, 20909, 13511, 132566, 20979, 21010,
michael@0 7522 21014, 132943, 21077, 21084, 21100, 21111, 21124, 21122, 133127, 21144,
michael@0 7523 133178, 21156, {f: 2, c: 21178}, 21194, 21201, 133305, 21239, 21301, 21314,
michael@0 7524 133500, 133533, 21351, 21370, 21412, 21428, 133843, 21431, 21440, 133917,
michael@0 7525 {f: 2, c: 13661}, 21461, 13667, 21492, 21540, 21544, 13678, 21571, 21602,
michael@0 7526 21612, 21653, 21664, 21670, 21678, 21687, 21690, 21699, 134469, 21740,
michael@0 7527 21743, 21745, 21747, {f: 2, c: 21760}, 21769, 21820, 21825, 13734, 21831,
michael@0 7528 13736, 21860, 134625, 21885, 21890, 21905, 13765, 21970, 134805, 134765,
michael@0 7529 21951, 21961, 21964, 21969, 21981, 13786, 21986, 134756, 21993, 22056,
michael@0 7530 135007, 22023, 22032, 22064, 13812, 22077, 22080, 22087, 22110, 22112,
michael@0 7531 22125, 13829, 22152, 22156, 22173, 22184, 22194, 22213, 22221, 22239,
michael@0 7532 22248, {f: 2, c: 22262}, 135681, 135765, 22313, 135803, {f: 2, c: 22341},
michael@0 7533 22349, 135796, 22376, 22383, {f: 3, c: 22387}, 22395, 135908, 135895,
michael@0 7534 22426, {f: 2, c: 22429}, 22440, 22487, 135933, 22476, 135990, 136004,
michael@0 7535 22494, 22512, 13898, 22520, 22523, 22525, 22532, 22558, 22567, 22585,
michael@0 7536 136132, 22601, 22604, 22631, {f: 2, c: 22666}, 22669, {f: 2, c: 22671},
michael@0 7537 22676, 22685, 22698, 22705, 136301, 22723, 22733, 22754, {f: 2, c: 22771},
michael@0 7538 {f: 2, c: 22789}, 22797, 22804, 136663, 13969, 22845, 13977, 22854, 13974,
michael@0 7539 158761, 22879, 136775, {f: 2, c: 22901}, 22908, 22943, 22958, 22972, 22984,
michael@0 7540 22989, 23006, 23015, 23022, 136966, 137026, 14031, 23053, 23063, 23079,
michael@0 7541 23085, 23141, 23162, 23179, 23196, {f: 2, c: 23199}, 23202, 23217, 23221,
michael@0 7542 23226, 23231, 23258, 23260, 23269, 23280, 23278, 23285, 23304, 23319,
michael@0 7543 23348, 23372, 23378, 23400, 23407, 23425, 23428, 137667, 23446, 23468,
michael@0 7544 {f: 2, c: 14177}, 23502, 23510, 14188, 14187, 23537, 23549, 14197, 23555,
michael@0 7545 23593, 138326, 23647, {f: 2, c: 23655}, 23664, 138541, 138565, 138616,
michael@0 7546 138594, 23688, 23690, 14273, 138657, 138652, 23712, 23714, 23719, 138642,
michael@0 7547 23725, 23733, 138679, 23753, 138720, 138803, 23814, 23824, 23851, 23837,
michael@0 7548 23840, 23857, 23865, 14312, 23905, 23914, 14324, 23920, 139038, 14333,
michael@0 7549 23944, 14336, 23959, 23984, 23988, 139126, 24017, 24023, 139258, 24036,
michael@0 7550 24041, 14383, 14390, 14400, 24095, 24126, 24137, 14428, 24150, 14433,
michael@0 7551 {f: 2, c: 24173}, 139643, 24229, 24236, 24249, 24262, 24281, 140062, 24317,
michael@0 7552 24328, 140205, 24350, 24391, 24419, 24434, 24446, 24463, 24482, 24519,
michael@0 7553 24523, {f: 3, c: 24530}, 24546, {f: 2, c: 24558}, 24563, 14615, 24610,
michael@0 7554 24612, 14618, 24652, 24725, 24744, 141043, 24753, 24766, 24776, 24793,
michael@0 7555 24814, 24821, 24848, 24857, 24862, 24890, 14703, 24897, 24902, 24928,
michael@0 7556 141403, {f: 2, c: 24978}, 24983, 24997, 25005, 141483, 25045, 25053, 25077,
michael@0 7557 141711, 25123, 25170, 25185, 25188, 25211, 25197, 25203, 25241, 25301,
michael@0 7558 142008, 25341, 25347, 25360, {f: 2, c: 142159}, 25394, 25397,
michael@0 7559 {f: 2, c: 25403}, 25409, 25412, 25422, 142150, 25433, 142365, 142246,
michael@0 7560 25452, 25497, 142372, 25492, 25533, {f: 2, c: 25556}, 25568,
michael@0 7561 {f: 2, c: 25579}, 25586, 25630, 25637, 25641, 25647, 25690, 25693, 25715,
michael@0 7562 25725, 25735, 25745, 25759, {f: 2, c: 25803}, 25813, 25815, 142817, 25828,
michael@0 7563 25855, 14958, 25871, 25876, 14963, 25886, 25906, 25924, 25940, 25963,
michael@0 7564 25978, 25988, 25994, 26034, 26037, 26040, 26047, 26057, 26068, 15062,
michael@0 7565 26105, 26108, 26116, 26120, 26145, 26154, 26181, 26193, 26190, 15082,
michael@0 7566 143811, 143861, 143798, 26218, {f: 2, c: 26220}, 26235, 26240, 26256,
michael@0 7567 26258, 15118, 26285, 26289, 26293, 15130, 15132, 15063, 26369, 26386,
michael@0 7568 144242, 26393, 144339, 144338, 26445, 26452, 26461, 144336, 144356, 144341,
michael@0 7569 26484, 144346, 26514, 144351, 33635, 26640, 26563, 26568, 26578, 26587,
michael@0 7570 26615, 144458, 144465, 144459, 26648, 26655, 26669, 144485, 26675, 26683,
michael@0 7571 26686, 26693, 26697, 26700, 26709, 26711, 15223, 26731, 26734, 26748,
michael@0 7572 26754, 26768, 26774, 15213, {f: 3, c: 26776}, 26780, {f: 2, c: 26794},
michael@0 7573 26804, 26811, 26875, 144612, 144730, 26819, 26821, 26828, 26841,
michael@0 7574 {f: 2, c: 26852}, 26860, 26871, 26883, 26887, 15239, 144788, 15245, 26950,
michael@0 7575 26985, 26988, 27002, 27026, 15268, 27030, 27056, 27066, 27068, 27072,
michael@0 7576 27089, 144953, 144967, 144952, 27107, {f: 2, c: 27118}, 27123, 15309,
michael@0 7577 27124, 27134, 27153, 27162, 27165, 145180, {f: 2, c: 27186}, 27199, 27209,
michael@0 7578 27258, 27214, 27218, 27236, 145164, 27275, 15344, 27297, 145252, 27307,
michael@0 7579 27325, 27334, 27348, 27344, 27357, 145407, 145383, {f: 3, c: 27377}, 27389,
michael@0 7580 145444, 27403, {f: 3, c: 27407}, 145469, 27415, 15398, 27439, 27466, 27480,
michael@0 7581 27500, 27509, [11934, 27514], 27521, 27547, 27566, 146072, 27581,
michael@0 7582 {f: 3, c: 27591}, 27610, {f: 2, c: 27622}, 27630, 27650, 27658, 27662,
michael@0 7583 27702, 146559, 27725, 27739, 27757, 27780, 27785, 15555, 27796, 27799,
michael@0 7584 27821, 27842, 15570, 27868, 27881, 27885, 146688, 27904, 27940,
michael@0 7585 {f: 2, c: 27942}, 27751, 27951, 27964, 27995, 28000, 28016,
michael@0 7586 {f: 2, c: 28032}, 28042, 28045, 28049, 28056, 146752, 146938, 146937,
michael@0 7587 146899, 28075, 28078, 28084, 28098, 27956, 28104, 28110, 28127, 28150,
michael@0 7588 28214, 28190, 15633, 28210, {f: 2, c: 28232}, {f: 2, c: 28235}, 28239,
michael@0 7589 {f: 2, c: 28243}, 28247, 28259, 15646, 28307, 28327, 28340, 28355, 28469,
michael@0 7590 28395, 28409, 28411, 28426, 28428, 28440, 28453, 28470, 28476, 147326,
michael@0 7591 28498, 28503, 28512, 28520, 28560, 28566, 28606, 28575, 28581, 28591,
michael@0 7592 15716, {f: 2, c: 28616}, 28649, 147606, 28668, 28672, 28682, 28707, 147715,
michael@0 7593 28730, 28739, 28743, 28747, 15770, 28773, 28777, 28782, 28790, 28806,
michael@0 7594 28823, 147910, 28831, 28849, 147966, 28908, 28874, 28881, 28931, 28934,
michael@0 7595 28936, 28940, 15808, 28975, 29008, 29011, 29022, 15828, 29078, 29056,
michael@0 7596 29083, 29088, 29090, {f: 2, c: 29102}, 148412, 29145, 29148, 29191, 15877,
michael@0 7597 29236, 29241, 29250, 29271, 29283, 149033, {f: 2, c: 29294}, 29304, 29311,
michael@0 7598 29326, 149157, 29358, 29360, 29377, 15968, 29388, 15974, 15976, 29427,
michael@0 7599 29434, 29447, 29458, {f: 2, c: 29464}, 16003, 29497, 29484, 29491, 29501,
michael@0 7600 29522, 16020, 29547, 149654, {f: 2, c: 29550}, 29553, 29569, 29578, 29588,
michael@0 7601 29592, 29596, 29605, 29625, 29631, 29637, 29643, 29665, 29671, 29689,
michael@0 7602 29715, 29690, 29697, 29779, 29760, 29763, 29778, 29789, 29825, 29832,
michael@0 7603 150093, 29842, 29847, 29849, 29857, 29861, 29866, 29881, 29883, 29882,
michael@0 7604 29910, 29912, 29931, 150358, 29946, 150383, 29984, 29988, 29994, 16215,
michael@0 7605 150550, {f: 2, c: 30013}, 30016, 30024, 30032, 30034, 30066, 30065, 30074,
michael@0 7606 {f: 2, c: 30077}, 30092, 16245, 30114, 16247, 30128, 30135,
michael@0 7607 {f: 2, c: 30143}, 30150, 30159, 30163, 30173, {f: 2, c: 30175}, 30183,
michael@0 7608 30190, 30193, 30211, 30232, 30215, 30223, 16302, 151054, 30227,
michael@0 7609 {f: 2, c: 30235}, 151095, 30245, 30248, 30268, 30259, 151146, 16329, 30273,
michael@0 7610 151179, 30281, 30293, 16343, 30318, 30357, 30369, 30368, {f: 2, c: 30375},
michael@0 7611 30383, 151626, 30409, 151637, 30440, 151842, 30487, 30490, 30509, 30517,
michael@0 7612 151977, 16441, 152037, 152013, 30552, 152094, 30588, 152140, 16472, 30618,
michael@0 7613 30623, 30626, 30628, {f: 2, c: 30686}, 30692, 30698, 30700, 30715, 152622,
michael@0 7614 30725, 30729, 30733, 30745, 30764, 30791, 30826, 152793, 30858, 30868,
michael@0 7615 30884, 30877, 30879, 30907, 30933, 30950, {f: 2, c: 30969}, 30974, 152999,
michael@0 7616 30992, 31003, 31013, 31050, 31064, 16645, 31079, 31090, 31125, 31137,
michael@0 7617 31145, 31156, 31170, 31175, {f: 2, c: 31180}, 31190, 16712, 153513, 153524,
michael@0 7618 16719, 31242, 31253, 31259, 16739, 31288, 31303, 31318, 31321, 31324,
michael@0 7619 31327, 31335, 31338, 31349, 31362, 31370, 31376, 31404, 154068, 16820,
michael@0 7620 31417, 31422, 16831, 31436, 31464, 31476, 154340, 154339, 154353, 31549,
michael@0 7621 31530, {f: 2, c: 31534}, 16870, 16883, 31615, 31553, 16878, 31573, 31609,
michael@0 7622 31588, 31590, 31603, 154546, 16903, 31632, 31643, 16910, 31669, 31676,
michael@0 7623 31685, 31690, 154699, 154724, 31700, 31702, 31706, 31722, 31728, 31747,
michael@0 7624 31758, 31813, 31818, 31831, 31838, 31841, 31849, 31855, 155182, 155222,
michael@0 7625 155237, 31910, 155234, {f: 2, c: 31926}, 155352, 31940, 155330, 31949,
michael@0 7626 155368, 155427, 31974, 155484, 31989, 32003, 17094, 32018, 32030, 155616,
michael@0 7627 155604, {f: 2, c: 32061}, 32064, 32071, 155660, 155643, 17110, 32090,
michael@0 7628 32106, 32112, 17117, 32127, 155671, 32136, 32151, 155744, 32157, 32167,
michael@0 7629 32170, 32182, 32192, 32215, 32217, 32230, 17154, 155885, 64088, 32272,
michael@0 7630 32279, 32285, 32295, 32300, 32325, 32373, 32382, {f: 2, c: 32390}, 17195,
michael@0 7631 32410, 17219, 32572, 32571, 32574, 32579, 13505, 156272, 156294,
michael@0 7632 {f: 2, c: 32611}, 32621, {f: 2, c: 32637}, 32656, 20859, 146702, 32662,
michael@0 7633 32668, 32685, 156674, 32707, 32719, 32739, 32754, 32778, 32776, 32790,
michael@0 7634 32812, 32816, 32835, 32870, 32891, 32921, 32924, 32932, 32935, 32952,
michael@0 7635 157310, 32965, 32981, 32998, 33037, 33013, 33019, 17390, 33077, 33054,
michael@0 7636 17392, 33060, 33063, 33068, 157469, 33085, 17416, 33129, 17431, 17436,
michael@0 7637 33157, 17442, 33176, 33202, 33217, 33219, 33238, 33243, 157917, 33252,
michael@0 7638 157930, 33260, 33277, 33279, 158063, 33284, 158173, 33305, 33314, 158238,
michael@0 7639 33340, 33353, 33349, 158296, 17526, 17530, 33367, 158348, 33372, 33379,
michael@0 7640 158391, 17553, 33405, 33407, 33411, 33418, 33427, {f: 2, c: 33447}, 33458,
michael@0 7641 33460, 33466, 33468, 33506, 33512, 33527, {f: 2, c: 33543}, 33548, 33620,
michael@0 7642 33563, 33565, 33584, 33596, 33604, 33623, 17598, 17620, 17587,
michael@0 7643 {f: 2, c: 33684}, 33691, 33693, 33737, 33744, 33748, 33757, 33765, 33785,
michael@0 7644 33813, 158835, 33815, 33849, 33871, {f: 2, c: 33873}, {f: 2, c: 33881},
michael@0 7645 33884, 158941, 33893, 33912, 33916, 33921, 17677, 33943, 33958, 33982,
michael@0 7646 17672, {f: 2, c: 33998}, 34003, 159333, 34023, 34026, 34031, 34033, 34042,
michael@0 7647 34075, {f: 2, c: 34084}, 34091, 34127, 34159, 17731, 34129,
michael@0 7648 {f: 2, c: 34145}, 159636, 34171, 34173, 34175, 34177, 34182, 34195, 34205,
michael@0 7649 34207, 159736, {f: 2, c: 159734}, 34236, 34247, 34250, {f: 2, c: 34264},
michael@0 7650 34271, 34273, 34278, 34294, 34304, 34321, 34334, 34337, 34340, 34343,
michael@0 7651 160013, 34361, 34364, 160057, 34368, 34387, 34390, 34423, 34439, 34441,
michael@0 7652 {f: 2, c: 34460}, 34481, 34483, 34497, 34499, 34513, 34517, 34519, 34531,
michael@0 7653 34534, 17848, 34565, 34567, 34574, 34576, 34591, 34593, 34595, 34609,
michael@0 7654 34618, 34624, 34627, 34641, 34648, {f: 2, c: 34660}, 34674, 34684, 160731,
michael@0 7655 160730, 34727, 34697, 34699, 34707, 34720, 160766, 17893, 34750, 160784,
michael@0 7656 34753, 34766, 34783, 160841, 34787, {f: 2, c: 34789}, 34794, 34835, 34856,
michael@0 7657 34862, 34866, 34876, 17935, 34890, 34904, 161301, 161300, 34921, 161329,
michael@0 7658 34927, 34976, 35004, 35008, 161427, 35025, 35027, 17985, 35073, 161550,
michael@0 7659 35127, 161571, 35138, 35141, 35145, 161618, 35170, 35209, 35216, 35231,
michael@0 7660 35248, 35255, 35288, 35307, 18081, 35315, 35325, 35327, 18095, 35345,
michael@0 7661 35348, 162181, 35361, 35381, 35390, 35397, 35405, 35416, 35502, 35472,
michael@0 7662 35511, 35543, 35580, 162436, 35594, 35589, 35597, 35612, 35629, 18188,
michael@0 7663 35665, 35678, 35702, 35713, 35723, {f: 2, c: 35732}, 35897, 162739, 35901,
michael@0 7664 162750, 162759, 35909, 35919, 35927, 35945, 35949, 163000, 35987, 35986,
michael@0 7665 35993, 18276, 35995, 36054, 36053, 163232, 36081, 163344, 36105, 36110,
michael@0 7666 36296, 36313, 36364, 18429, 36349, 36358, 163978, 36372, 36374,
michael@0 7667 {f: 2, c: 36385}, 36391, 164027, 18454, 36406, 36409, 36436, 36450, 36461,
michael@0 7668 36463, 36504, 36510, 36533, 36539, 164482, 18510, 164595, 36608, 36616,
michael@0 7669 36651, 36672, 36682, 36696, 164876, 36772, 36788, 164949, 36801, 36806,
michael@0 7670 64036, 36810, 36813, 36819, 36821, 36849, 36853, 36859, 36876, 36919,
michael@0 7671 165227, 36931, 36957, {f: 2, c: 165320}, 36997, 37004, 37008, 37025, 18613,
michael@0 7672 37040, 37046, 37059, 37064, 165591, 37084, 37087, 165626, 37110, 37106,
michael@0 7673 37120, 37099, {f: 2, c: 37118}, 37124, 37126, 37144, 37150, 37175, 37177,
michael@0 7674 {f: 2, c: 37190}, 37207, 37209, 37236, 37241, 37253, 37299, 37302,
michael@0 7675 {f: 2, c: 37315}, 166217, 166214, 37356, 37377, {f: 2, c: 37398}, 166251,
michael@0 7676 37442, 37450, 37462, 37473, 37477, 37480, 166280, {f: 2, c: 37500}, 37503,
michael@0 7677 37513, 37517, 37527, 37529, 37535, 37547, {f: 2, c: 166330}, 37554,
michael@0 7678 {f: 2, c: 37567}, 37574, 37582, 37605, 37649, 166430, 166441, 37623, 37673,
michael@0 7679 166513, 166467, 37713, 37722, 37739, 37745, 37747, 37793, 166553, 166605,
michael@0 7680 37768, 37771, 37775, 37790, 37877, 166628, 166621, 37873, 37831, 37852,
michael@0 7681 37863, 37897, {f: 2, c: 37910}, 37883, 37938, 37947, 166849, 166895, 37997,
michael@0 7682 37999, 38265, 38278, {f: 2, c: 38284}, 167184, 167281, 38344, 167419,
michael@0 7683 167455, 38444, {f: 2, c: 38451}, 167478, 38460, 38497, 167561, 38530,
michael@0 7684 167659, 38554, 167730, 18919, 38579, 38586, 38589, 18938, 167928, 38616,
michael@0 7685 38618, 38621, 18948, 38676, 38691, 18985, 38710, 38721, 38727, 38743,
michael@0 7686 38747, 38762, 168608, 168625, 38806, 38814, {f: 2, c: 38833}, 38846, 38860,
michael@0 7687 38865, 38868, 38872, 38881, 38897, 38916, 38925, 38932, 38934, 19132,
michael@0 7688 169104, {f: 2, c: 38962}, 38949, 38983, 39014, 39083, 39085, 39088, 169423,
michael@0 7689 39095, {f: 2, c: 39099}, 39106, 39111, 39115, 39137, 39139, 39146,
michael@0 7690 {f: 2, c: 39152}, 39155, 39176, 19259, 169712, {f: 2, c: 39190}, 169753,
michael@0 7691 {f: 3, c: 39194}, 169808, 39217, {f: 3, c: 39226}, 39233, 39238, 39246,
michael@0 7692 39264, 39331, 39334, 39357, 39359, 39363, 39380, 39385, 39390, 170182,
michael@0 7693 39408, 39417, 39420, 39434, 39441, 39450, 39456, 39473, 39492, 39500,
michael@0 7694 39512, 19394, 39599, 19402, 39607, 19410, 39609, 170610, 39622, 39632,
michael@0 7695 39634, 39637, 39648, 39653, 39657, 39692, 39696, 39698, 39702, 39708,
michael@0 7696 39723, 39741, 19488, 39755, 39779, 39781, {f: 2, c: 39787},
michael@0 7697 {f: 2, c: 39798}, 39846, 39852, 171483, 39858, 39864, 39870, 39923, 39896,
michael@0 7698 39901, 39914, 39919, 39918, 171541, 171658, 171593, 39958,
michael@0 7699 {f: 3, c: 39960}, 39965, 39970, 39977, 171716, 39985, 39991, 40005, 40028,
michael@0 7700 171753, {f: 2, c: 40009}, 171739, 40020, 40024, 40027, 40029, 40031,
michael@0 7701 {f: 3, c: 40041}, {f: 2, c: 40045}, 40050, 40053, 40058, 40166, 40178,
michael@0 7702 40203, [171982, 171991], 40209, {f: 2, c: 40215}, 172079, 19652, 172058,
michael@0 7703 40242, 19665, 40266, 40287, 40290, 172281, 172162, 40307, {f: 2, c: 40310},
michael@0 7704 40324, 40345, 40353, 40383, 40373, 40377, 40381, 40393, 40410, 40416,
michael@0 7705 40419, 19719, 40458, 40450, 40461, 40476, 40571, 139800, 40576, 40581,
michael@0 7706 40603, 172940, 40637, 173111, 40671, 40703, 40706, 19831, 40707, 40762,
michael@0 7707 40765, 40774, 40787, 40789, 40792, 173553, 40797, 173570, 40809, 40813,
michael@0 7708 40816, 173746, 11948, 13844, 14509, 15820, 16348, 17854, 17936, 19326,
michael@0 7709 19512, 19681, 19980, {f: 2, c: 20003}, 20089, 20211, 20236, 20249, 20267,
michael@0 7710 20270, 20273, 20356, 20382, 20407, 20484, 20492, 20556, 20575, 20578,
michael@0 7711 20599, 20622, 20638, 20642, 20675, 20712, 20721, 20734, 20743,
michael@0 7712 {f: 3, c: 20748}, 20787, 20792, 20852, 20868, 20920, 20922, 20936, 20943,
michael@0 7713 20945, {f: 2, c: 20947}, 20952, 20959, 20997, 21030, 21032, 21035,
michael@0 7714 {f: 2, c: 21041}, 21045, 21052, 21082, 21088, 21102, {f: 2, c: 21112},
michael@0 7715 21130, 21132, 21217, 21225, 21233, 21251, 21265, 21279, 21293, 21298,
michael@0 7716 21309, 21349, 21357, 21369, 21374, 21396, 21401, 21418, 21423, 21434,
michael@0 7717 21441, {f: 2, c: 21444}, 21472, 21523, 21546, 21553, {f: 2, c: 21556},
michael@0 7718 21580, 21671, 21674, 21681, 21691, 21710, 21738, 21756, 21765, 21768,
michael@0 7719 21781, 21799, 21802, 21814, 21841, 21862, 21903, 21906, 21908, 21924,
michael@0 7720 21938, 21955, 21958, 21971, 21979, 21996, 21998, 22001, 22006, 22008,
michael@0 7721 22021, 22029, {f: 2, c: 22033}, 22060, 22069, 22073, 22093, 22100, 22149,
michael@0 7722 22175, 22182, 22199, 22220, 22223, 22233, 22241, 22251, 22253, 22257,
michael@0 7723 22279, 22284, {f: 2, c: 22298}, 22301, 22316, 22318, {f: 2, c: 22333},
michael@0 7724 22367, 22379, 22381, 22394, 22403, 22423, 22446, 22485, 22503, 22541,
michael@0 7725 22566, 22605, 22607, 22623, 22637, 22655, 22657, 22680, 22716, 22815,
michael@0 7726 22819, 22873, 22905, 22935, 22959, 22963, 23007, 23025, 23032, 23218,
michael@0 7727 23224, 23274, 23286, 23323, 23325, 23329, 23352, 23479, 23511, 23520,
michael@0 7728 23583, 23594, 23596, 23606, 23641, 23644, 23661, 23773, 23809, 23860,
michael@0 7729 23869, 23897, 23934, 23939, 24007, 24057, 24104, 24114, 24117, 24155,
michael@0 7730 24168, 24170, 24183, 24192, 24203, 24243, 24253, 24273, {f: 2, c: 24276},
michael@0 7731 24397, 24492, 24554, 24583, 24649, 24660, 24679, 24763, 24772, 24829,
michael@0 7732 24842, 24854, 24874, 24886, 24926, 24932, 24955, 24957, 24959, 24989,
michael@0 7733 25016, 25052, 25058, 25061, 25064, 25092, 25095, 25137, 25145, 25149,
michael@0 7734 25210, 25232, 25256, 25306, 25332, 25366, 25386, 25398, 25414, 25419,
michael@0 7735 25427, 25457, 25461, 25471, 25474, 25482, {f: 2, c: 25518}, 25578,
michael@0 7736 {f: 2, c: 25592}, 25618, 25624, 25632, 25636, 25642, 25653, 25661, 25663,
michael@0 7737 25682, 25695, 25716, 25744, {f: 2, c: 25752}, 25772, 25779, 25837, 25840,
michael@0 7738 25883, 25887, 25902, 25929, 25952, 26002, 26005, 26036, 26046, 26056,
michael@0 7739 26062, 26064, 26079, 26238, {f: 2, c: 26251}, 26291, 26304, 26319, 26405,
michael@0 7740 26421, 26453, 26496, 26511, 26513, 26532, 26545, 26549, 26558, 26664,
michael@0 7741 26758, 26859, 26869, 26903, 26931, 26936, 26971, 26981, 27048, 27051,
michael@0 7742 27055, 27109, 27121, 27210, 27221, 27239, 27249, 27311, {f: 2, c: 27336},
michael@0 7743 27395, 27451, 27455, {f: 2, c: 27517}, 27568, 27639, 27641, 27652, 27657,
michael@0 7744 27661, 27692, 27722, 27730, 27732, 27769, 27820, 27828, 27858, 28001,
michael@0 7745 28028, 28089, 28144, 28229, 28275, 28283, 28285, 28297, 28348,
michael@0 7746 {f: 2, c: 28378}, 28454, 28457, 28464, 28551, 28573, 28590, 28599, 28685,
michael@0 7747 28704, 28745, 28824, 28848, {f: 2, c: 28885}, 28997, 29106, 29172, 29207,
michael@0 7748 29215, 29251, {f: 2, c: 29263}, 29274, 29280, 29288, 29303, 29316, 29385,
michael@0 7749 29413, 29428, 29442, 29451, 29470, 29474, {f: 2, c: 29498}, 29517, 29528,
michael@0 7750 29543, 29810, 29871, 29919, 29924, 29940, 29947, 29974, 29985, 30015,
michael@0 7751 30046, 30105, 30116, 30145, 30148, 30156, 30167, 30172, 30177, 30191,
michael@0 7752 30212, 30220, 30237, 30258, 30264, 30277, 30282, 30303, 30381, 30397,
michael@0 7753 30425, 30443, 30448, 30457, 30464, 30478, 30498, 30504, 30511, 30521,
michael@0 7754 30526, 30533, 30538, 30543, 30558, 30564, 30567, 30572, 30596,
michael@0 7755 {f: 2, c: 30604}, 30614, 30631, 30639, 30647, 30654, 30665, 30673, 30681,
michael@0 7756 30705, 30775, 30812, 30846, 30872, 30881, 30897, 30899, 30921, 30931,
michael@0 7757 30988, 31007, {f: 2, c: 31015}, 31039, 31042, 31060, 31083, 31100, 31147,
michael@0 7758 31172, 31210, 31234, 31244, 31280, 31290, 31300, 31360, 31366, 31380,
michael@0 7759 31413, 31421, 31486, 31531, 31607, 31648, 31660, 31664, 31720, 31730,
michael@0 7760 31736, 31740, 31742, 31753, 31784, 31791, 31810, {f: 2, c: 31826},
michael@0 7761 {f: 3, c: 31835}, 31858, 31869, 31879, 31902, 31930, 31943, 31955, 31962,
michael@0 7762 32060, 32077, 32130, 32133, 32141, 32145, 32158, 32179, 32185, 32208,
michael@0 7763 32229, {f: 2, c: 32245}, 32303, 32310, 32324, 32367, 32376, 32385, 32573,
michael@0 7764 32603, 32605, 32613, 32625, {f: 2, c: 32639}, 32651, 32674,
michael@0 7765 {f: 3, c: 32765}, 32775, 32781, 32798, 32825, 32904, 32910, 32975, 32980,
michael@0 7766 33005, 33008, 33015, 33018, 33022, 33027, 33047, 33072, 33111, 33135,
michael@0 7767 33139, 33163, 33168, 33179, 33182, 33227, 33237, {f: 2, c: 33245}, 33249,
michael@0 7768 33263, 33270, 33280, 33291, {f: 2, c: 33299}, 33306, 33338, 33348, 33389,
michael@0 7769 33412, 33417, 33425, 33450, 33456, 33488, 33514, 33519, 33526, 33622,
michael@0 7770 33656, 33784, 33788, 33880, 33939, 33969, 33981, 34043, 34118, 34134,
michael@0 7771 34141, 34181, 34200, 34370, 34374, 34496, 34580, 34594, 34606, 34617,
michael@0 7772 34653, 34683, 34700, 34702, {f: 2, c: 34711}, 34718, 34723, 34734, 34751,
michael@0 7773 34761, 34778, 34840, 34843, 34861, 34874, 34885, 34891, 34894, 34901,
michael@0 7774 34906, 34926, {f: 3, c: 34970}, 35021, 35040, 35055, {f: 2, c: 35086},
michael@0 7775 35110, 35125, 35162, 35164, 35179, 35184, 35196, 35237, 35253, 35260,
michael@0 7776 35285, 35401, 35415, 35431, 35454, 35462, 35478, 35510, 35529, 35537,
michael@0 7777 35549, 35564, 35573, 35590, 35599, 35601, 35653, 35666, 35693, 35704,
michael@0 7778 35708, 35710, 35717, 35743, 35915, 35923, 35963, 36026, 36037, 36041,
michael@0 7779 36050, 36076, 36085, 36087, 36097, 36099, 36119, 36124, 36206, 36241,
michael@0 7780 36255, 36267, 36274, 36309, 36327, {f: 2, c: 36337}, 36340, 36353, 36363,
michael@0 7781 36390, 36401, {f: 2, c: 36416}, 36429, 36431, 36444, 36449, 36457, 36465,
michael@0 7782 36469, 36471, 36489, 36496, 36501, 36506, 36519, 36521, 36525, 36584,
michael@0 7783 36592, 36615, 36632, 36645, 36647, 36652, 36661, 36666, 36675, 36679,
michael@0 7784 36689, 36693, {f: 3, c: 36768}, 36773, 36868, 36891, 36911, 36940, 36955,
michael@0 7785 36976, 36980, 36985, 37003, 37016, 37024, 37042, 37053, 37065, 37104,
michael@0 7786 37125, 37157, 37210, 37223, 37242, 37258, 37265, 37269, 37296, 37307,
michael@0 7787 37309, 37314, 37317, 37376, 37385, 37411, 37494, 37518, 37551,
michael@0 7788 {f: 2, c: 37563}, 37569, 37571, 37573, 37576, 37652, 37683, 37686, 37720,
michael@0 7789 37759, 37762, 37770, 37819, 37836, 37862, 37881, 37890, {f: 2, c: 37901},
michael@0 7790 37934, 37964, 38280, 38305, 38335, 38342, 38345, {f: 2, c: 38353}, 38368,
michael@0 7791 38372, 38374, 38436, 38449, 38456, 38461, 38484, 38516, 38523, 38527,
michael@0 7792 38529, 38531, 38537, 38550, 38574, 38659, 38683, {f: 2, c: 38689}, 38696,
michael@0 7793 38705, 38759, 38774, 38781, 38783, 38809, 38815, 38828, 38841, 38861,
michael@0 7794 38880, 38895, 38919, 38950, 38958, {f: 2, c: 39010}, 39092, 39109, 39170,
michael@0 7795 39185, 39189, 39221, 39240, 39252, 39262, 39393, 39436, 39440, 39459,
michael@0 7796 39489, 39505, {f: 2, c: 39613}, 39681, 39689, 39691, {f: 2, c: 39693},
michael@0 7797 39705, 39733, 39752, 39765, 39784, 39808, 39814, 39824, 39837, 39856,
michael@0 7798 39871, 39880, 39935, 39938, 39964, 39989, 40004, 40022, 40033, 40040,
michael@0 7799 40240, 40253, 40298, 40315, 40421, 40425, 40435, 40570, {f: 3, c: 40578},
michael@0 7800 40624, 40676, 40688, 40690, 40713, 40719, 40724, 40731, 40738, 40742,
michael@0 7801 {f: 2, c: 40746}, 40756, 40794, 40815, 40862, 40869, 131317, 151044,
michael@0 7802 151538, 163187, 194581, 194630, 194713, 194726, 194789, 195038, 13790,
michael@0 7803 {s: 4}, 172722, 0, 0, 131416, {s: 4}, 132529, 0, 0, 132844, {s: 6}, 134488,
michael@0 7804 {s: 21}, 154060, {s: 9}, 14756, 14776, 142914, 0, 0, 14940, 0, 0, 143339,
michael@0 7805 0, 0, 162228, 0, 15044, 15051, {s: 5}, 14981, {s: 8}, 15347, 27384, {s: 5},
michael@0 7806 15665, {s: 9}, 147531, 0, 15936, 14497, {s: 34}, 158878, {s: 12}, 18207,
michael@0 7807 162876, {s: 4}, 18462, {s: 71}, 39709, 39724, 20482, 20958, 21255, 23532,
michael@0 7808 63784, 26142, 63785, 28746, 64021, 21857, 27706, 31328, 156492, 34819,
michael@0 7809 38315, 38741, 171581, 173594],
michael@0 7810 'Adobe-Korea1': [{f: 95, c: 32}, 8361, 8208, 169, 0, 0, [12288, 12644],
michael@0 7811 {f: 2, c: 12289}, 12539, 8229, [8230, 8943], 168, 12291, {f: 2, c: 8211},
michael@0 7812 8214, 65340, 65374, {f: 2, c: 8216}, {f: 2, c: 8220}, {f: 2, c: 12308},
michael@0 7813 {f: 10, c: 12296}, 177, 215, 247, 8800, {f: 2, c: 8804}, 8734, 8756, 176,
michael@0 7814 {f: 2, c: 8242}, 8451, 8491, {f: 2, c: 65504}, 65509, 9794, 9792, 8736,
michael@0 7815 8869, 8978, 8706, 8711, 8801, 8786, 167, 8251, 9734, 9733, 9675, 9679,
michael@0 7816 9678, 9671, 9670, 9633, 9632, 9651, 9650, 9661, 9660, 8594,
michael@0 7817 {f: 2, c: 8592}, {f: 2, c: 8595}, 12307, 171, 187, 8730, 8765, 8733, 8757,
michael@0 7818 {f: 2, c: 8747}, 8712, 8715, {f: 2, c: 8838}, {f: 2, c: 8834}, 8746, 8745,
michael@0 7819 {f: 2, c: 8743}, 65506, 8658, 8660, 8704, 8707, 180, 732, 711, 728, 733,
michael@0 7820 730, 729, 184, 731, 161, 191, 8758, 8750, 8721, 8719, 164, 8457, 8240,
michael@0 7821 9665, 9664, 9655, 9654, 9828, {f: 2, c: 9824}, 9829, 9831, 9827, 9673,
michael@0 7822 9672, 9635, {f: 2, c: 9680}, 9618, {f: 2, c: 9636}, 9640, 9639, 9638, 9641,
michael@0 7823 9832, 9743, 9742, 9756, 9758, 182, {f: 2, c: 8224}, 8597, 8599, 8601, 8598,
michael@0 7824 8600, 9837, {f: 2, c: 9833}, 9836, 12927, 12828, 8470, 13255, 8482, 13250,
michael@0 7825 13272, 8481, {f: 59, c: 65281}, 65510, {f: 33, c: 65341}, 65507,
michael@0 7826 {f: 51, c: 12593}, {f: 42, c: 12645}, {f: 10, c: 8560}, {f: 10, c: 8544},
michael@0 7827 {f: 17, c: 913}, {f: 7, c: 931}, {f: 17, c: 945}, {f: 7, c: 963}, 9472,
michael@0 7828 9474, 9484, 9488, 9496, 9492, 9500, 9516, 9508, 9524, 9532, 9473, 9475,
michael@0 7829 9487, 9491, 9499, 9495, 9507, 9523, 9515, 9531, 9547, 9504, 9519, 9512,
michael@0 7830 9527, 9535, 9501, 9520, 9509, 9528, 9538, 9490, 9489, 9498, 9497, 9494,
michael@0 7831 9493, 9486, 9485, {f: 2, c: 9502}, {f: 2, c: 9505}, {f: 2, c: 9510},
michael@0 7832 {f: 2, c: 9513}, {f: 2, c: 9517}, {f: 2, c: 9521}, {f: 2, c: 9525},
michael@0 7833 {f: 2, c: 9529}, {f: 2, c: 9533}, {f: 2, c: 9536}, {f: 8, c: 9539},
michael@0 7834 {f: 3, c: 13205}, 8467, 13208, 13252, {f: 4, c: 13219}, {f: 10, c: 13209},
michael@0 7835 13258, {f: 3, c: 13197}, 13263, {f: 2, c: 13192}, 13256, {f: 2, c: 13223},
michael@0 7836 {f: 10, c: 13232}, {f: 5, c: 13184}, {f: 6, c: 13242}, {f: 5, c: 13200},
michael@0 7837 8486, {f: 2, c: 13248}, {f: 3, c: 13194}, 13270, 13253, {f: 3, c: 13229},
michael@0 7838 13275, {f: 4, c: 13225}, 13277, 13264, 13267, 13251, 13257, 13276, 13254,
michael@0 7839 198, 208, 170, 294, 306, 319, 321, 216, 338, 186, 222, 358, 330,
michael@0 7840 {f: 28, c: 12896}, {f: 26, c: 9424}, {f: 15, c: 9312}, 189,
michael@0 7841 {f: 2, c: 8531}, 188, 190, {f: 4, c: 8539}, 230, 273, 240, 295, 305, 307,
michael@0 7842 312, 320, 322, 248, 339, 223, 254, 359, 331, 329, {f: 28, c: 12800},
michael@0 7843 {f: 26, c: 9372}, {f: 15, c: 9332}, 185, {f: 2, c: 178}, 8308, 8319,
michael@0 7844 {f: 4, c: 8321}, {f: 83, c: 12353}, {f: 86, c: 12449}, {f: 6, c: 1040},
michael@0 7845 1025, {f: 32, c: 1046}, 1105, {f: 26, c: 1078}, {f: 2, c: 44032}, 44036,
michael@0 7846 {f: 4, c: 44039}, {f: 8, c: 44048}, {f: 5, c: 44057}, 44064, 44068,
michael@0 7847 {f: 2, c: 44076}, {f: 3, c: 44079}, {f: 2, c: 44088}, 44092, 44096, 44107,
michael@0 7848 44109, 44116, 44120, 44124, {f: 2, c: 44144}, 44148, {f: 2, c: 44151},
michael@0 7849 44154, {f: 2, c: 44160}, {f: 4, c: 44163}, {f: 4, c: 44169}, 44176, 44180,
michael@0 7850 {f: 2, c: 44188}, {f: 3, c: 44191}, {f: 3, c: 44200}, 44204,
michael@0 7851 {f: 2, c: 44207}, {f: 2, c: 44216}, {f: 3, c: 44219}, 44225, 44228, 44232,
michael@0 7852 44236, 44245, 44247, {f: 2, c: 44256}, 44260, {f: 2, c: 44263}, 44266,
michael@0 7853 44268, {f: 3, c: 44271}, 44275, {f: 2, c: 44277}, {f: 2, c: 44284}, 44288,
michael@0 7854 44292, 44294, {f: 2, c: 44300}, 44303, 44305, 44312, 44316, 44320, 44329,
michael@0 7855 {f: 2, c: 44332}, {f: 2, c: 44340}, 44344, 44348, {f: 2, c: 44356}, 44359,
michael@0 7856 44361, 44368, 44372, 44376, 44385, 44387, {f: 2, c: 44396}, 44400,
michael@0 7857 {f: 4, c: 44403}, {f: 3, c: 44411}, 44415, {f: 2, c: 44417},
michael@0 7858 {f: 2, c: 44424}, 44428, 44432, {f: 2, c: 44444}, 44452, 44471,
michael@0 7859 {f: 2, c: 44480}, 44484, 44488, {f: 2, c: 44496}, 44499, 44508, 44512,
michael@0 7860 44516, {f: 2, c: 44536}, 44540, {f: 3, c: 44543}, {f: 2, c: 44552}, 44555,
michael@0 7861 44557, 44564, {f: 2, c: 44592}, 44596, {f: 2, c: 44599}, 44602,
michael@0 7862 {f: 2, c: 44608}, 44611, {f: 2, c: 44613}, 44618, {f: 3, c: 44620}, 44624,
michael@0 7863 44628, 44630, {f: 2, c: 44636}, {f: 3, c: 44639}, 44645, {f: 2, c: 44648},
michael@0 7864 44652, 44656, {f: 2, c: 44664}, {f: 3, c: 44667}, {f: 2, c: 44676}, 44684,
michael@0 7865 {f: 3, c: 44732}, 44736, 44740, {f: 2, c: 44748}, {f: 3, c: 44751},
michael@0 7866 {f: 2, c: 44760}, 44764, 44776, 44779, 44781, 44788, 44792, 44796,
michael@0 7867 {f: 2, c: 44807}, 44813, 44816, {f: 2, c: 44844}, 44848, 44850, 44852,
michael@0 7868 {f: 2, c: 44860}, 44863, {f: 3, c: 44865}, {f: 2, c: 44872}, 44880,
michael@0 7869 {f: 2, c: 44892}, {f: 2, c: 44900}, 44921, 44928, 44932, 44936,
michael@0 7870 {f: 2, c: 44944}, 44949, 44956, {f: 2, c: 44984}, 44988, 44992,
michael@0 7871 {f: 3, c: 44999}, 45003, {f: 2, c: 45005}, 45012, 45020, {f: 2, c: 45032},
michael@0 7872 {f: 2, c: 45040}, 45044, 45048, {f: 2, c: 45056}, 45060, 45068, 45072,
michael@0 7873 45076, {f: 2, c: 45084}, 45096, {f: 2, c: 45124}, 45128, 45130, 45132,
michael@0 7874 45134, {f: 3, c: 45139}, 45143, 45145, 45149, {f: 2, c: 45180}, 45184,
michael@0 7875 45188, {f: 2, c: 45196}, 45199, 45201, {f: 3, c: 45208}, 45212,
michael@0 7876 {f: 4, c: 45215}, {f: 2, c: 45224}, {f: 5, c: 45227}, 45233,
michael@0 7877 {f: 3, c: 45235}, 45240, 45244, {f: 2, c: 45252}, {f: 3, c: 45255},
michael@0 7878 {f: 2, c: 45264}, 45268, 45272, 45280, 45285, {f: 2, c: 45320},
michael@0 7879 {f: 2, c: 45323}, 45328, {f: 2, c: 45330}, {f: 2, c: 45336},
michael@0 7880 {f: 3, c: 45339}, {f: 3, c: 45347}, 45352, 45356, {f: 2, c: 45364},
michael@0 7881 {f: 3, c: 45367}, {f: 2, c: 45376}, 45380, 45384, {f: 2, c: 45392},
michael@0 7882 {f: 2, c: 45396}, 45400, 45404, 45408, {f: 2, c: 45432}, 45436, 45440,
michael@0 7883 45442, {f: 2, c: 45448}, 45451, 45453, {f: 3, c: 45458}, 45464, 45468,
michael@0 7884 45480, 45516, 45520, 45524, {f: 2, c: 45532}, 45535, {f: 2, c: 45544},
michael@0 7885 45548, 45552, 45561, 45563, 45565, {f: 2, c: 45572}, 45576,
michael@0 7886 {f: 2, c: 45579}, {f: 2, c: 45588}, 45591, 45593, 45600, 45620, 45628,
michael@0 7887 45656, 45660, 45664, {f: 2, c: 45672}, {f: 2, c: 45684}, 45692,
michael@0 7888 {f: 2, c: 45700}, 45705, {f: 2, c: 45712}, 45716, {f: 3, c: 45720},
michael@0 7889 {f: 2, c: 45728}, 45731, {f: 2, c: 45733}, 45738, 45740, 45744, 45748,
michael@0 7890 {f: 2, c: 45768}, 45772, 45776, 45778, {f: 2, c: 45784}, 45787, 45789,
michael@0 7891 45794, {f: 3, c: 45796}, 45800, {f: 5, c: 45803}, {f: 3, c: 45811},
michael@0 7892 {f: 5, c: 45815}, {f: 3, c: 45823}, 45828, 45832, {f: 2, c: 45840},
michael@0 7893 {f: 3, c: 45843}, 45852, {f: 3, c: 45908}, 45912, {f: 2, c: 45915},
michael@0 7894 {f: 2, c: 45918}, {f: 2, c: 45924}, 45927, 45929, 45931, 45934,
michael@0 7895 {f: 2, c: 45936}, 45940, 45944, {f: 2, c: 45952}, {f: 3, c: 45955}, 45964,
michael@0 7896 45968, 45972, {f: 2, c: 45984}, 45992, 45996, {f: 2, c: 46020}, 46024,
michael@0 7897 {f: 2, c: 46027}, 46030, 46032, {f: 2, c: 46036}, 46039, 46041, 46043,
michael@0 7898 46045, 46048, 46052, 46056, 46076, 46096, 46104, 46108, 46112,
michael@0 7899 {f: 2, c: 46120}, 46123, 46132, {f: 2, c: 46160}, 46164, 46168,
michael@0 7900 {f: 2, c: 46176}, 46179, 46181, 46188, 46208, 46216, 46237, 46244, 46248,
michael@0 7901 46252, 46261, 46263, 46265, 46272, 46276, 46280, 46288, 46293,
michael@0 7902 {f: 2, c: 46300}, 46304, {f: 2, c: 46307}, 46310, {f: 2, c: 46316}, 46319,
michael@0 7903 46321, 46328, {f: 2, c: 46356}, 46360, {f: 2, c: 46363}, {f: 2, c: 46372},
michael@0 7904 {f: 4, c: 46375}, {f: 2, c: 46384}, 46388, 46392, {f: 2, c: 46400},
michael@0 7905 {f: 3, c: 46403}, {f: 3, c: 46411}, 46416, 46420, {f: 2, c: 46428},
michael@0 7906 {f: 3, c: 46431}, {f: 2, c: 46496}, 46500, 46504, {f: 2, c: 46506},
michael@0 7907 {f: 2, c: 46512}, {f: 3, c: 46515}, {f: 3, c: 46523}, 46528, 46532,
michael@0 7908 {f: 2, c: 46540}, {f: 3, c: 46543}, 46552, 46572, {f: 2, c: 46608}, 46612,
michael@0 7909 46616, 46629, 46636, 46644, 46664, 46692, 46696, {f: 2, c: 46748}, 46752,
michael@0 7910 46756, {f: 2, c: 46763}, 46769, 46804, 46832, 46836, 46840,
michael@0 7911 {f: 2, c: 46848}, 46853, {f: 2, c: 46888}, 46892, {f: 2, c: 46895},
michael@0 7912 {f: 2, c: 46904}, 46907, 46916, 46920, 46924, {f: 2, c: 46932}, 46944,
michael@0 7913 46948, 46952, {f: 2, c: 46960}, 46963, 46965, {f: 2, c: 46972}, 46976,
michael@0 7914 46980, {f: 2, c: 46988}, {f: 4, c: 46991}, {f: 4, c: 46998}, 47004, 47008,
michael@0 7915 {f: 2, c: 47016}, {f: 3, c: 47019}, {f: 2, c: 47028}, 47032, 47047, 47049,
michael@0 7916 {f: 2, c: 47084}, 47088, 47092, {f: 2, c: 47100}, {f: 3, c: 47103},
michael@0 7917 {f: 3, c: 47111}, 47116, 47120, {f: 2, c: 47128}, 47131, 47133,
michael@0 7918 {f: 2, c: 47140}, 47144, 47148, {f: 2, c: 47156}, {f: 3, c: 47159}, 47168,
michael@0 7919 47172, 47185, 47187, {f: 2, c: 47196}, 47200, 47204, {f: 2, c: 47212},
michael@0 7920 47215, 47217, 47224, 47228, 47245, 47272, 47280, 47284, 47288,
michael@0 7921 {f: 2, c: 47296}, 47299, 47301, 47308, 47312, 47316, 47325, 47327, 47329,
michael@0 7922 {f: 2, c: 47336}, 47340, 47344, {f: 2, c: 47352}, 47355, 47357, 47364,
michael@0 7923 47384, 47392, {f: 2, c: 47420}, 47424, 47428, 47436, 47439, 47441,
michael@0 7924 {f: 2, c: 47448}, 47452, 47456, {f: 2, c: 47464}, 47467, 47469,
michael@0 7925 {f: 2, c: 47476}, 47480, 47484, {f: 2, c: 47492}, 47495, {f: 2, c: 47497},
michael@0 7926 {f: 2, c: 47501}, {f: 2, c: 47532}, 47536, 47540, {f: 2, c: 47548}, 47551,
michael@0 7927 47553, {f: 2, c: 47560}, 47564, {f: 5, c: 47566}, {f: 2, c: 47576}, 47579,
michael@0 7928 {f: 2, c: 47581}, 47585, {f: 3, c: 47587}, 47592, 47596, {f: 2, c: 47604},
michael@0 7929 {f: 4, c: 47607}, {f: 2, c: 47616}, 47624, 47637, {f: 2, c: 47672}, 47676,
michael@0 7930 47680, 47682, {f: 2, c: 47688}, 47691, {f: 2, c: 47693}, {f: 3, c: 47699},
michael@0 7931 47704, 47708, {f: 2, c: 47716}, {f: 3, c: 47719}, {f: 2, c: 47728}, 47732,
michael@0 7932 47736, {f: 3, c: 47747}, 47751, 47756, {f: 2, c: 47784}, {f: 2, c: 47787},
michael@0 7933 47792, 47794, {f: 2, c: 47800}, 47803, 47805, 47812, 47816,
michael@0 7934 {f: 2, c: 47832}, 47868, 47872, 47876, 47885, 47887, 47889, 47896, 47900,
michael@0 7935 47904, 47913, 47915, {f: 3, c: 47924}, 47928, {f: 4, c: 47931},
michael@0 7936 {f: 2, c: 47940}, 47943, 47945, 47949, {f: 2, c: 47951}, 47956, 47960,
michael@0 7937 47969, 47971, 47980, 48008, 48012, 48016, 48036, 48040, 48044, 48052,
michael@0 7938 48055, 48064, 48068, 48072, 48080, 48083, {f: 2, c: 48120}, 48124,
michael@0 7939 {f: 2, c: 48127}, 48130, {f: 2, c: 48136}, {f: 3, c: 48139}, 48143, 48145,
michael@0 7940 {f: 5, c: 48148}, {f: 5, c: 48155}, {f: 2, c: 48164}, 48167, 48169, 48173,
michael@0 7941 {f: 2, c: 48176}, 48180, 48184, {f: 2, c: 48192}, {f: 3, c: 48195}, 48201,
michael@0 7942 {f: 2, c: 48204}, 48208, 48221, {f: 2, c: 48260}, 48264, {f: 2, c: 48267},
michael@0 7943 48270, {f: 2, c: 48276}, 48279, {f: 2, c: 48281}, {f: 2, c: 48288}, 48292,
michael@0 7944 {f: 2, c: 48295}, {f: 2, c: 48304}, {f: 3, c: 48307}, {f: 2, c: 48316},
michael@0 7945 48320, 48324, 48333, {f: 3, c: 48335}, 48341, 48344, 48348,
michael@0 7946 {f: 3, c: 48372}, 48376, 48380, {f: 2, c: 48388}, 48391, 48393, 48400,
michael@0 7947 48404, 48420, 48428, 48448, {f: 2, c: 48456}, 48460, 48464,
michael@0 7948 {f: 2, c: 48472}, 48484, 48488, {f: 2, c: 48512}, 48516, {f: 4, c: 48519},
michael@0 7949 {f: 2, c: 48528}, 48531, 48533, {f: 2, c: 48537}, 48540, 48548, 48560,
michael@0 7950 48568, {f: 2, c: 48596}, 48600, 48604, 48617, 48624, 48628, 48632, 48640,
michael@0 7951 48643, 48645, {f: 2, c: 48652}, 48656, 48660, {f: 2, c: 48668}, 48671,
michael@0 7952 {f: 2, c: 48708}, 48712, 48716, 48718, {f: 2, c: 48724}, 48727,
michael@0 7953 {f: 3, c: 48729}, {f: 2, c: 48736}, 48740, 48744, 48746, {f: 2, c: 48752},
michael@0 7954 {f: 3, c: 48755}, {f: 3, c: 48763}, 48768, 48772, {f: 2, c: 48780},
michael@0 7955 {f: 3, c: 48783}, {f: 2, c: 48792}, 48808, {f: 2, c: 48848}, 48852,
michael@0 7956 {f: 2, c: 48855}, 48864, {f: 3, c: 48867}, 48876, 48897, {f: 2, c: 48904},
michael@0 7957 {f: 2, c: 48920}, {f: 3, c: 48923}, {f: 2, c: 48960}, 48964, 48968,
michael@0 7958 {f: 2, c: 48976}, 48981, 49044, 49072, 49093, {f: 2, c: 49100}, 49104,
michael@0 7959 49108, 49116, 49119, 49121, 49212, 49233, 49240, 49244, 49248,
michael@0 7960 {f: 2, c: 49256}, {f: 2, c: 49296}, 49300, 49304, {f: 2, c: 49312}, 49315,
michael@0 7961 49317, {f: 2, c: 49324}, {f: 2, c: 49327}, {f: 4, c: 49331},
michael@0 7962 {f: 2, c: 49340}, {f: 3, c: 49343}, 49349, {f: 2, c: 49352}, 49356, 49360,
michael@0 7963 {f: 2, c: 49368}, {f: 3, c: 49371}, {f: 2, c: 49380}, 49384, 49388,
michael@0 7964 {f: 2, c: 49396}, 49399, 49401, 49408, 49412, 49416, 49424, 49429,
michael@0 7965 {f: 5, c: 49436}, {f: 2, c: 49443}, {f: 2, c: 49446}, {f: 2, c: 49452},
michael@0 7966 {f: 3, c: 49455}, 49462, {f: 2, c: 49464}, 49468, 49472, {f: 2, c: 49480},
michael@0 7967 {f: 3, c: 49483}, {f: 2, c: 49492}, 49496, 49500, {f: 2, c: 49508},
michael@0 7968 {f: 3, c: 49511}, 49520, 49524, 49528, 49541, {f: 3, c: 49548}, 49552,
michael@0 7969 49556, 49558, {f: 2, c: 49564}, 49567, 49569, 49573, {f: 2, c: 49576},
michael@0 7970 49580, 49584, 49597, 49604, 49608, 49612, 49620, {f: 2, c: 49623}, 49632,
michael@0 7971 49636, 49640, {f: 2, c: 49648}, 49651, {f: 2, c: 49660}, 49664, 49668,
michael@0 7972 {f: 2, c: 49676}, 49679, 49681, {f: 2, c: 49688}, 49692, {f: 2, c: 49695},
michael@0 7973 {f: 2, c: 49704}, 49707, 49709, 49711, {f: 2, c: 49713}, 49716, 49736,
michael@0 7974 {f: 2, c: 49744}, 49748, 49752, 49760, 49765, {f: 2, c: 49772}, 49776,
michael@0 7975 49780, {f: 2, c: 49788}, 49791, 49793, {f: 2, c: 49800}, 49808, 49816,
michael@0 7976 49819, 49821, {f: 2, c: 49828}, 49832, {f: 2, c: 49836}, {f: 2, c: 49844},
michael@0 7977 49847, 49849, {f: 2, c: 49884}, 49888, {f: 2, c: 49891}, {f: 3, c: 49899},
michael@0 7978 49903, 49905, 49910, {f: 2, c: 49912}, {f: 2, c: 49915}, 49920,
michael@0 7979 {f: 2, c: 49928}, {f: 2, c: 49932}, {f: 3, c: 49939}, 49944, 49948,
michael@0 7980 {f: 2, c: 49956}, {f: 2, c: 49960}, 49989, {f: 2, c: 50024}, 50028, 50032,
michael@0 7981 50034, {f: 2, c: 50040}, {f: 2, c: 50044}, 50052, 50056, 50060, 50112,
michael@0 7982 {f: 2, c: 50136}, 50140, {f: 2, c: 50143}, 50146, {f: 2, c: 50152}, 50157,
michael@0 7983 {f: 2, c: 50164}, 50168, 50184, 50192, 50212, 50220, 50224, 50228,
michael@0 7984 {f: 2, c: 50236}, 50248, {f: 2, c: 50276}, 50280, 50284, {f: 2, c: 50292},
michael@0 7985 50297, 50304, 50324, 50332, 50360, 50364, 50409, {f: 2, c: 50416}, 50420,
michael@0 7986 50424, 50426, {f: 3, c: 50431}, 50444, 50448, 50452, 50460,
michael@0 7987 {f: 2, c: 50472}, 50476, 50480, {f: 2, c: 50488}, 50491, 50493,
michael@0 7988 {f: 2, c: 50500}, {f: 3, c: 50504}, {f: 3, c: 50508}, {f: 3, c: 50515},
michael@0 7989 {f: 3, c: 50519}, {f: 2, c: 50525}, {f: 2, c: 50528}, 50532, 50536,
michael@0 7990 {f: 2, c: 50544}, {f: 3, c: 50547}, {f: 2, c: 50556}, 50560, 50564, 50567,
michael@0 7991 {f: 2, c: 50572}, 50575, 50577, 50581, {f: 2, c: 50583}, 50588, 50592,
michael@0 7992 50601, {f: 2, c: 50612}, {f: 2, c: 50616}, {f: 4, c: 50619},
michael@0 7993 {f: 7, c: 50628}, 50636, 50638, {f: 2, c: 50640}, 50644, 50648,
michael@0 7994 {f: 2, c: 50656}, 50659, 50661, {f: 3, c: 50668}, 50672, 50676,
michael@0 7995 {f: 2, c: 50678}, {f: 6, c: 50684}, {f: 4, c: 50693}, 50700, 50704,
michael@0 7996 {f: 2, c: 50712}, {f: 2, c: 50715}, {f: 2, c: 50724}, 50728,
michael@0 7997 {f: 3, c: 50732}, 50736, {f: 3, c: 50739}, 50743, 50745, 50747,
michael@0 7998 {f: 2, c: 50752}, 50756, 50760, {f: 2, c: 50768}, {f: 3, c: 50771},
michael@0 7999 {f: 2, c: 50780}, 50784, 50796, 50799, 50801, {f: 2, c: 50808}, 50812,
michael@0 8000 50816, {f: 2, c: 50824}, 50827, 50829, {f: 2, c: 50836}, 50840, 50844,
michael@0 8001 {f: 2, c: 50852}, 50855, 50857, {f: 2, c: 50864}, 50868, {f: 3, c: 50872},
michael@0 8002 {f: 2, c: 50880}, 50883, 50885, {f: 2, c: 50892}, 50896, 50900,
michael@0 8003 {f: 2, c: 50908}, {f: 2, c: 50912}, {f: 2, c: 50920}, 50924, 50928,
michael@0 8004 {f: 2, c: 50936}, 50941, {f: 2, c: 50948}, 50952, 50956, {f: 2, c: 50964},
michael@0 8005 50967, 50969, {f: 2, c: 50976}, 50980, 50984, {f: 2, c: 50992}, 50995,
michael@0 8006 50997, 50999, {f: 2, c: 51004}, 51008, 51012, 51018, {f: 2, c: 51020},
michael@0 8007 51023, {f: 8, c: 51025}, 51036, 51040, 51048, 51051, {f: 2, c: 51060},
michael@0 8008 51064, {f: 3, c: 51068}, {f: 3, c: 51075}, {f: 4, c: 51079}, 51086,
michael@0 8009 {f: 2, c: 51088}, 51092, {f: 3, c: 51094}, 51098, {f: 2, c: 51104},
michael@0 8010 {f: 4, c: 51107}, {f: 2, c: 51116}, 51120, 51124, {f: 2, c: 51132},
michael@0 8011 {f: 3, c: 51135}, {f: 2, c: 51144}, 51148, 51150, 51152, 51160, 51165,
michael@0 8012 51172, 51176, 51180, {f: 2, c: 51200}, 51204, 51208, 51210,
michael@0 8013 {f: 2, c: 51216}, 51219, {f: 2, c: 51221}, {f: 2, c: 51228}, 51232, 51236,
michael@0 8014 {f: 2, c: 51244}, 51247, 51249, 51256, 51260, 51264, {f: 2, c: 51272},
michael@0 8015 {f: 2, c: 51276}, 51284, {f: 2, c: 51312}, 51316, 51320, 51322,
michael@0 8016 {f: 2, c: 51328}, 51331, {f: 3, c: 51333}, {f: 3, c: 51339}, 51348, 51357,
michael@0 8017 51359, 51361, 51368, {f: 2, c: 51388}, 51396, 51400, 51404,
michael@0 8018 {f: 2, c: 51412}, 51415, 51417, {f: 2, c: 51424}, 51428, 51445,
michael@0 8019 {f: 2, c: 51452}, 51456, {f: 3, c: 51460}, {f: 2, c: 51468}, 51471, 51473,
michael@0 8020 51480, 51500, 51508, {f: 2, c: 51536}, 51540, 51544, {f: 2, c: 51552},
michael@0 8021 51555, 51564, 51568, 51572, 51580, {f: 2, c: 51592}, 51596, 51600,
michael@0 8022 {f: 2, c: 51608}, 51611, 51613, {f: 2, c: 51648}, 51652, {f: 2, c: 51655},
michael@0 8023 51658, {f: 2, c: 51664}, 51667, {f: 2, c: 51669}, {f: 2, c: 51673},
michael@0 8024 {f: 2, c: 51676}, 51680, 51682, 51684, 51687, {f: 2, c: 51692},
michael@0 8025 {f: 3, c: 51695}, {f: 2, c: 51704}, 51708, 51712, {f: 2, c: 51720},
michael@0 8026 {f: 3, c: 51723}, 51732, 51736, 51753, {f: 2, c: 51788}, 51792, 51796,
michael@0 8027 {f: 2, c: 51804}, {f: 3, c: 51807}, 51816, 51837, 51844, 51864,
michael@0 8028 {f: 2, c: 51900}, 51904, 51908, {f: 2, c: 51916}, 51919, 51921, 51923,
michael@0 8029 {f: 2, c: 51928}, 51936, 51948, 51956, 51976, 51984, 51988, 51992,
michael@0 8030 {f: 2, c: 52000}, 52033, {f: 2, c: 52040}, 52044, 52048, {f: 2, c: 52056},
michael@0 8031 52061, 52068, {f: 2, c: 52088}, 52124, 52152, 52180, 52196, 52199, 52201,
michael@0 8032 {f: 2, c: 52236}, 52240, 52244, {f: 2, c: 52252}, {f: 2, c: 52257},
michael@0 8033 {f: 3, c: 52263}, 52268, 52270, 52272, {f: 2, c: 52280}, {f: 4, c: 52283},
michael@0 8034 {f: 2, c: 52292}, 52296, 52300, {f: 2, c: 52308}, {f: 3, c: 52311}, 52320,
michael@0 8035 52324, 52326, 52328, 52336, 52341, {f: 2, c: 52376}, 52380, 52384,
michael@0 8036 {f: 2, c: 52392}, {f: 3, c: 52395}, {f: 2, c: 52404}, 52408, 52412,
michael@0 8037 {f: 2, c: 52420}, 52423, 52425, 52432, 52436, 52452, 52460, 52464, 52481,
michael@0 8038 {f: 2, c: 52488}, 52492, 52496, {f: 2, c: 52504}, 52507, 52509, 52516,
michael@0 8039 52520, 52524, 52537, 52572, 52576, 52580, {f: 2, c: 52588}, 52591, 52593,
michael@0 8040 52600, 52616, {f: 2, c: 52628}, 52632, 52636, {f: 2, c: 52644}, 52647,
michael@0 8041 52649, 52656, 52676, 52684, 52688, 52712, 52716, 52720, {f: 2, c: 52728},
michael@0 8042 52731, 52733, 52740, 52744, 52748, 52756, 52761, {f: 2, c: 52768}, 52772,
michael@0 8043 52776, {f: 2, c: 52784}, 52787, 52789, {f: 2, c: 52824}, 52828,
michael@0 8044 {f: 3, c: 52831}, {f: 2, c: 52840}, 52843, 52845, {f: 2, c: 52852}, 52856,
michael@0 8045 52860, {f: 2, c: 52868}, 52871, 52873, {f: 2, c: 52880}, 52884, 52888,
michael@0 8046 {f: 2, c: 52896}, {f: 3, c: 52899}, {f: 2, c: 52908}, 52929,
michael@0 8047 {f: 2, c: 52964}, 52968, {f: 2, c: 52971}, {f: 2, c: 52980},
michael@0 8048 {f: 3, c: 52983}, {f: 2, c: 52992}, 52996, 53000, {f: 2, c: 53008}, 53011,
michael@0 8049 53013, 53020, 53024, 53028, {f: 2, c: 53036}, {f: 3, c: 53039}, 53048,
michael@0 8050 {f: 2, c: 53076}, 53080, 53084, {f: 2, c: 53092}, 53095, 53097,
michael@0 8051 {f: 2, c: 53104}, 53108, 53112, 53120, 53125, 53132, 53153, 53160, 53168,
michael@0 8052 53188, {f: 2, c: 53216}, 53220, 53224, {f: 2, c: 53232}, 53235, 53237,
michael@0 8053 53244, 53248, 53252, 53265, 53272, 53293, {f: 2, c: 53300}, 53304, 53308,
michael@0 8054 {f: 2, c: 53316}, 53319, 53321, 53328, 53332, 53336, 53344,
michael@0 8055 {f: 2, c: 53356}, 53360, 53364, {f: 2, c: 53372}, 53377, {f: 2, c: 53412},
michael@0 8056 53416, 53420, {f: 2, c: 53428}, 53431, 53433, {f: 2, c: 53440}, 53444,
michael@0 8057 {f: 2, c: 53448}, {f: 2, c: 53456}, {f: 3, c: 53459}, {f: 2, c: 53468},
michael@0 8058 53472, 53476, {f: 2, c: 53484}, {f: 3, c: 53487}, 53496, 53517,
michael@0 8059 {f: 2, c: 53552}, 53556, 53560, 53562, {f: 2, c: 53568}, {f: 3, c: 53571},
michael@0 8060 {f: 2, c: 53580}, 53584, 53588, {f: 2, c: 53596}, 53599, 53601, 53608,
michael@0 8061 53612, 53628, 53636, 53640, {f: 2, c: 53664}, 53668, 53672,
michael@0 8062 {f: 2, c: 53680}, 53683, 53685, 53690, 53692, 53696, 53720, 53748, 53752,
michael@0 8063 53767, 53769, 53776, {f: 2, c: 53804}, 53808, 53812, {f: 2, c: 53820},
michael@0 8064 53823, 53825, 53832, 53852, 53860, {f: 2, c: 53888}, 53892, 53896,
michael@0 8065 {f: 2, c: 53904}, 53909, 53916, 53920, 53924, 53932, 53937,
michael@0 8066 {f: 2, c: 53944}, 53948, {f: 2, c: 53951}, 53954, {f: 2, c: 53960}, 53963,
michael@0 8067 53972, 53976, 53980, {f: 2, c: 53988}, {f: 2, c: 54000}, 54004, 54008,
michael@0 8068 {f: 2, c: 54016}, 54019, 54021, {f: 3, c: 54028}, 54032, 54036, 54038,
michael@0 8069 {f: 2, c: 54044}, {f: 3, c: 54047}, 54053, {f: 2, c: 54056}, 54060, 54064,
michael@0 8070 {f: 2, c: 54072}, {f: 3, c: 54075}, {f: 2, c: 54084}, {f: 2, c: 54140},
michael@0 8071 54144, 54148, {f: 2, c: 54156}, {f: 3, c: 54159}, {f: 2, c: 54168}, 54172,
michael@0 8072 54176, {f: 2, c: 54184}, 54187, 54189, 54196, 54200, 54204,
michael@0 8073 {f: 2, c: 54212}, {f: 2, c: 54216}, 54224, 54232, 54241, 54243,
michael@0 8074 {f: 2, c: 54252}, 54256, 54260, {f: 2, c: 54268}, 54271, 54273, 54280,
michael@0 8075 54301, 54336, 54340, 54364, 54368, 54372, 54381, 54383, {f: 2, c: 54392},
michael@0 8076 54396, {f: 2, c: 54399}, 54402, {f: 2, c: 54408}, 54411, 54413, 54420,
michael@0 8077 54441, 54476, 54480, 54484, 54492, 54495, 54504, 54508, 54512, 54520,
michael@0 8078 54523, 54525, 54532, 54536, 54540, {f: 2, c: 54548}, 54551,
michael@0 8079 {f: 2, c: 54588}, 54592, 54596, {f: 2, c: 54604}, 54607, 54609,
michael@0 8080 {f: 2, c: 54616}, 54620, 54624, 54629, {f: 2, c: 54632}, 54635, 54637,
michael@0 8081 {f: 2, c: 54644}, 54648, 54652, {f: 2, c: 54660}, {f: 3, c: 54663}, 54672,
michael@0 8082 54693, {f: 2, c: 54728}, 54732, 54736, 54738, {f: 2, c: 54744}, 54747,
michael@0 8083 54749, {f: 2, c: 54756}, 54760, 54764, {f: 2, c: 54772}, 54775, 54777,
michael@0 8084 {f: 2, c: 54784}, 54788, 54792, {f: 2, c: 54800}, {f: 3, c: 54803}, 54812,
michael@0 8085 54816, 54820, 54829, {f: 2, c: 54840}, 54844, 54848, 54853,
michael@0 8086 {f: 2, c: 54856}, 54859, 54861, 54865, {f: 2, c: 54868}, 54872, 54876,
michael@0 8087 54887, 54889, {f: 2, c: 54896}, 54900, 54915, 54917, {f: 2, c: 54924},
michael@0 8088 54928, 54932, 54941, 54943, 54945, 54952, 54956, 54960, 54969, 54971,
michael@0 8089 {f: 2, c: 54980}, 54984, 54988, 54993, 54996, 54999, 55001, 55008, 55012,
michael@0 8090 55016, 55024, 55029, {f: 2, c: 55036}, 55040, 55044, 55057,
michael@0 8091 {f: 2, c: 55064}, 55068, 55072, {f: 2, c: 55080}, 55083, 55085,
michael@0 8092 {f: 2, c: 55092}, 55096, 55100, 55108, 55111, 55113, {f: 2, c: 55120},
michael@0 8093 55124, {f: 4, c: 55126}, {f: 2, c: 55136}, 55139, 55141, 55145, 55148,
michael@0 8094 55152, 55156, {f: 2, c: 55164}, 55169, {f: 2, c: 55176}, 55180, 55184,
michael@0 8095 {f: 2, c: 55192}, 55195, 55197, 20285, 20339, 20551, 20729, 21152, 21487,
michael@0 8096 21621, 21733, 22025, 23233, 23478, 26247, {f: 2, c: 26550}, 26607, 27468,
michael@0 8097 29634, 30146, 31292, 33499, 33540, 34903, 34952, 35382, [36040, 63747],
michael@0 8098 36303, 36603, 36838, 39381, 21051, 21364, 21508, 24682, 24932, 27580,
michael@0 8099 29647, 33050, 35258, [12179, 35282], 38307, 20355, 21002, 22718, 22904,
michael@0 8100 23014, [12082, 24178], 24185, 25031, 25536, 26438, 26604, 26751, 28567,
michael@0 8101 30286, 30475, 30965, 31240, 31487, 31777, 32925, [12169, 33390], 33393,
michael@0 8102 35563, 38291, 20075, 21917, 26359, 28212, 30883, 31469, 33883, 35088,
michael@0 8103 34638, 38824, 21208, 22350, 22570, 23884, 24863, 25022, 25121, 25954,
michael@0 8104 26577, 27204, 28187, [12130, 29976], 30131, 30435, 30640, 32058, 37039,
michael@0 8105 {f: 2, c: 37969}, 40853, 21283, 23724, 30002, 32987, 37440, 38296, 21083,
michael@0 8106 22536, 23004, 23713, 23831, 24247, 24378, 24394, 24951, 27743, 30074,
michael@0 8107 30086, 31968, 32115, 32177, 32652, 33108, 33313, 34193, 35137, 35611,
michael@0 8108 37628, [38477, 64009], 40007, 20171, 20215, 20491, 20977, 22607, 24887,
michael@0 8109 24894, 24936, 25913, 27114, 28433, 30117, 30342, 30422, 31623, 33445,
michael@0 8110 33995, 37799, 38283, 21888, 23458, 22353, 31923, 32697, 37301, 20520,
michael@0 8111 21435, 23621, 24040, 25298, 25454, 25818, 25831, 28192, 28844, 31067,
michael@0 8112 36317, 36382, 36989, 37445, 37624, 20094, 20214, 20581, [12081, 24062],
michael@0 8113 24314, 24838, 26967, 33137, 34388, 36423, 37749, 39467, 20062, 20625,
michael@0 8114 26480, 26688, 20745, 21133, 21138, 27298, 30652, 37392, 40660, 21163,
michael@0 8115 24623, 36850, 20552, 25001, 25581, 25802, 26684, 27268, 28608, 33160,
michael@0 8116 35233, 38548, 22533, 29309, [12125, 29356], 29956, 32121, 32365, 32937,
michael@0 8117 [12178, 35211, 64010], 35700, 36963, 40273, 25225, 27770, 28500, 32080,
michael@0 8118 32570, 35363, 20860, 24906, 31645, 35609, 37463, 37772, 20140, 20435,
michael@0 8119 20510, 20670, 20742, 21185, 21197, 21375, 22384, 22659, 24218, 24465,
michael@0 8120 24950, 25004, 25806, 25964, 26223, 26299, [26356, 63745], 26775, 28039,
michael@0 8121 28805, 28913, 29855, 29861, 29898, 30169, 30828, 30956, 31455, 31478,
michael@0 8122 32069, 32147, 32789, 32831, 33051, 33686, 35686, 36629, 36885, 37857,
michael@0 8123 38915, 38968, 39514, 39912, 20418, 21843, 22586, [22865, 63753], 23395,
michael@0 8124 23622, 24760, 25106, 26690, 26800, 26856, 28330, 30028, 30328, 30926,
michael@0 8125 31293, 31995, 32363, 32380, 35336, 35489, 35903, 38542, 40388, 21476,
michael@0 8126 21481, 21578, 21617, 22266, 22993, 23396, 23611, 24235, 25335, 25911,
michael@0 8127 25925, 25970, 26272, 26543, 27073, 27837, 30204, 30352, 30590, 31295,
michael@0 8128 32660, 32771, 32929, 33167, 33510, 33533, 33776, 34241, 34865, 34996,
michael@0 8129 35493, 36764, 37678, 38599, 39015, [12220, 39640], [12238, 40723], 21741,
michael@0 8130 26011, 26354, 26767, 31296, [12181, 35895], 40288, 22256, 22372, 23825,
michael@0 8131 26118, 26801, 26829, 28414, 29736, 34974, 39908, 27752, [12219, 39592],
michael@0 8132 20379, 20844, 20849, 21151, 23380, [12079, 24037], 24656, 24685, 25329,
michael@0 8133 25511, 25915, 29657, 31354, 34467, 36002, 38799, [20018, 63749], 23521,
michael@0 8134 [12093, 25096], 26524, [12128, 29916], 31185, 33747, 35463, 35506, 36328,
michael@0 8135 36942, 37707, 38982, [24275, 64011], 27112, 34303, 37101, 20896, 23448,
michael@0 8136 23532, 24931, 26874, 27454, 28748, 29743, 29912, 31649, 32592, 33733,
michael@0 8137 35264, 36011, 38364, 39208, 21038, 24669, 25324, 36866, 20362, 20809,
michael@0 8138 21281, 22745, 24291, 26336, 27960, 28826, 29378, 29654, 31568, 33009,
michael@0 8139 37979, 21350, 25499, 32619, 20054, 20608, 22602, 22750, 24618, 24871,
michael@0 8140 25296, 27088, 39745, 23439, 32024, 32945, 36703, 20132, 20689, 21676,
michael@0 8141 21932, 23308, 23968, 24039, 25898, 25934, 26657, 27211, 29409, 30350,
michael@0 8142 30703, 32094, 32761, 33184, 34126, 34527, 36611, 36686, 37066, 39171,
michael@0 8143 39509, 39851, 19992, 20037, 20061, 20167, 20465, 20855, 21246, 21312,
michael@0 8144 [12061, 21475], [21477, 63750], 21646, 22036, 22389, 22434, 23495, 23943,
michael@0 8145 24272, 25084, 25304, 25937, 26552, 26601, 27083, 27472, 27590, 27628,
michael@0 8146 27714, 28317, 28792, 29399, 29590, 29699, 30655, 30697, 31350, 32127,
michael@0 8147 32777, [12165, 33276], 33285, 33290, 33503, 34914, 35635, 36092, 36544,
michael@0 8148 36881, 37041, 37476, 37558, 39378, 39493, 40169, 40407,
michael@0 8149 [12244, 40860, 63751, 63752], 22283, 23616, 33738, 38816, 38827, 40628,
michael@0 8150 21531, 31384, 32676, 35033, 36557, 37089, 22528, 23624, 25496, 31391,
michael@0 8151 23470, [12088, 24339], 31353, 31406, 33422, 36524, 20518, 21048, 21240,
michael@0 8152 21367, 22280, 25331, 25458, 27402, 28099, 30519, 21413, 29527, 34152,
michael@0 8153 36470, 38357, 26426, 27331, 28528, 35437, 36556, 39243, 26231, 27512,
michael@0 8154 36020, [12225, 39740], 21483, 22317, 22862, 25542, 27131, 29674, 30789,
michael@0 8155 31418, 31429, 31998, 33909, 35215, 36211, 36917, 38312, 21243, 22343,
michael@0 8156 30023, 31584, 33740, 37406, 27224, 20811, 21067, 21127, 25119, 26840,
michael@0 8157 26997, 38553, 20677, 21156, 21220, 25027, [12100, 26020], 26681, 27135,
michael@0 8158 29822, 31563, 33465, 33771, 35250, 35641, 36817, 39241, 20170, 22935,
michael@0 8159 25810, 26129, 27278, 29748, 31105, 31165, 33449, {f: 2, c: 34942}, 35167,
michael@0 8160 37670, 20235, 21450, 24613, 25201, 27762, 32026, 32102, 20120, 20834,
michael@0 8161 30684, 32943, 20225, 20238, 20854, 20864, 21980, 22120, 22331, 22522,
michael@0 8162 22524, 22804, 22855, 22931, 23492, 23696, 23822, [12080, 24049], 24190,
michael@0 8163 24524, 25216, 26071, 26083, {f: 2, c: 26398}, 26462, 26827, 26820, 27231,
michael@0 8164 27450, 27683, 27773, 27778, 28103, 29592, 29734, 29738, 29826, 29859,
michael@0 8165 30072, 30079, 30849, 30959, 31041, {f: 2, c: 31047}, 31098, 31637, 32000,
michael@0 8166 32186, 32648, 32774, 32813, 32908, 35352, 35663, [35912, 63744], 36215,
michael@0 8167 37665, 37668, 39138, 39249, {f: 2, c: 39438}, 39525, 40594, 32202, 20342,
michael@0 8168 21513, 25326, 26708, [12198, 37329, 63754], 21931, 20794, 23068, 25062,
michael@0 8169 [25295, 63835], 25343, 37027, [35582, 63837], 26262, 29014, 38627, 25423,
michael@0 8170 25466, 21335, 26511, 26976, 28275, 30007, 32013, 34930, 22218, 23064,
michael@0 8171 20035, 20839, [22856, 63756], 26608, 32784, [12069, 22899, 63873],
michael@0 8172 [24180, 63886], [25754, 63889], [31178, 63893], [24565, 63907], 24684,
michael@0 8173 25288, [25467, 63908], [23527, 63839, 63914], 23511, 21162, 22900, 24361,
michael@0 8174 [24594, 63840], 29785, 39377, 28611, 33215, 36786, 24817, 33126,
michael@0 8175 [23615, 63933], 23273, 35365, [26491, 63944], [32016, 63951], 33021, 23612,
michael@0 8176 [27877, 63971], [21311, 63979], [28346, 63980], 22810, [33590, 63998],
michael@0 8177 [20025, 63838], 20150, 20294, 21934, 22296, 22727, 24406, 26039, 26086,
michael@0 8178 27264, 27573, 28237, 30701, 31471, 31774, 32222, 34507, 34962, 37170,
michael@0 8179 37723, 25787, 28606, 29562, 30136, 36948, 21846, 22349, 25018, 25812,
michael@0 8180 26311, 28129, 28251, 28525, 28601, 30192, 32835, 33213, 34113, 35203,
michael@0 8181 35527, 35674, 37663, 27795, 30035, 31572, 36367, 36957, 21776, 22530,
michael@0 8182 22616, 24162, 25095, 25758, 26848, 30070, [31958, 64003], 34739, 40680,
michael@0 8183 20195, 22408, 22382, [12068, 22823], 23565, 23729, 24118, 24453, 25140,
michael@0 8184 25825, 29619, 33274, 34955, 36024, 38538, 40667, [23429, 64004], 24503,
michael@0 8185 24755, 20498, [12049, 20992], 21040, 22294, 22581, 22615, 23566, 23648,
michael@0 8186 23798, 23947, [24230, 64001], 24466, 24764, 25361, 25481, 25623, 26691,
michael@0 8187 26873, 27330, 28120, 28193, 28372, 28644, 29182, 30428, 30585, 31153,
michael@0 8188 31291, 33796, 35241, 36077, 36339, 36424, 36867, 36884, 36947, 37117,
michael@0 8189 37709, 38518, 38876, 27602, 28678, 29272, 29346, 29544, 30563, 31167,
michael@0 8190 31716, 32411, [35712, 63834], 22697, 24775, 25958, 26109, 26302, 27788,
michael@0 8191 28958, 29129, 35930, 38931, 20077, 31361, 20189, 20908, 20941, 21205,
michael@0 8192 21516, 24999, 26481, 26704, 26847, [27934, 64005], 28540, 30140, 30643,
michael@0 8193 31461, 33012, 33891, 37509, 20828, [12099, 26007], 26460, 26515, 30168,
michael@0 8194 31431, 33651, [12182, 35910], 36887, 38957, 23663, 33216, 33434, 36929,
michael@0 8195 36975, 37389, 24471, 23965, 27225, 29128, 30331, 31561, 34276, 35588,
michael@0 8196 37159, 39472, [21895, 63755], [25078, 63757], [30313, 63758],
michael@0 8197 [32645, 63759], [34367, 63760], [34746, 63761], [35064, 63762],
michael@0 8198 [37007, 63763], [27931, 63765], [28889, 63766], [29662, 63767], 32097,
michael@0 8199 [33853, 63768], [37226, 63769], [39409, 63770], [20098, 63771],
michael@0 8200 [21365, 63772], [27396, 63773], 27410, 28734, [29211, 63774],
michael@0 8201 [34349, 63775], [40478, 63776], 21068, 36771, [23888, 63777], 25829, 25900,
michael@0 8202 27414, [28651, 63778], 31811, 32412, [34253, 63779], [35172, 63780], 35261,
michael@0 8203 [25289, 63781], [33240, 63782], [34847, 63783], [24266, 63784],
michael@0 8204 [26391, 63785], [28010, 63786], [29436, 63787], 29701, 29807, 34690,
michael@0 8205 [37086, 63788], [20358, 63789], 23821, 24480, 33802, [20919, 63790],
michael@0 8206 [25504, 63861], [30053, 63862], [20142, 63863], 20486, [20841, 63864],
michael@0 8207 [20937, 63865], [26753, 63866], 27153, 31918, 31921, [31975, 63867],
michael@0 8208 [33391, 63868], [35538, 63869], 36635, [37327, 63870], 20406, 20791,
michael@0 8209 [21237, 63871], [21570, 63872], [24300, 63874], 24942, 25150,
michael@0 8210 [26053, 63875], 27354, [28670, 63876], [31018, 63877], 34268, 34851,
michael@0 8211 [38317, 63878], 39522, [39530, 63879], [40599, 63880], [40654, 63881],
michael@0 8212 [12050, 21147, 63882], [26310, 63883], [27511, 63884], 28701, 31019,
michael@0 8213 [36706, 63885], 38722, [24976, 63887], [25088, 63888], 25891,
michael@0 8214 [28451, 63890], [29001, 63891], [29833, 63892], [32244, 63894],
michael@0 8215 [32879, 63895], [34030, 63897], [36646, 63896], [36899, 63898],
michael@0 8216 [37706, 63899], 20925, [21015, 63900], [21155, 63901], 27916,
michael@0 8217 [28872, 63903], [35010, 63904], [24265, 63906], 25986, [27566, 63909],
michael@0 8218 28610, [31806, 63910], [29557, 63911], [20196, 63912], 20278,
michael@0 8219 [22265, 63913], 23738, [23994, 63915], [24604, 63916], [29618, 63917],
michael@0 8220 31533, [32666, 63919], 32718, [32838, 63920], 36894, [37428, 63921],
michael@0 8221 [38646, 63922], [38728, 63923], [38936, 63924], 40801, [20363, 63925],
michael@0 8222 28583, [31150, 63926], [37300, 63927], [38583, 63928], [21214, 63791],
michael@0 8223 25736, [25796, 63792], [27347, 63793], 28510, 28696, [29200, 63794],
michael@0 8224 [30439, 63795], [12156, 32769, 63796], [34310, 63797], [34396, 63798],
michael@0 8225 [36335, 63799], 36613, [38706, 63800], [39791, 63801], [40442, 63802],
michael@0 8226 [12228, 40565], [30860, 63803], [31103, 63804], [32160, 63805],
michael@0 8227 [33737, 63806], [37636, 63807], [12229, 40575, 63808], 40595,
michael@0 8228 [35542, 63809], [22751, 63810], [24324, 63811], 26407, 28711, 29903,
michael@0 8229 [31840, 63812], [32894, 63813], 20769, 28712, [29282, 63814],
michael@0 8230 [30922, 63815], [36034, 63816], 36058, 36084, [38647, 63817],
michael@0 8231 [20102, 63930], [20698, 63931], [23534, 63932], 24278, [26009, 63934],
michael@0 8232 [29134, 63936], [30274, 63937], 30637, 32842, [34044, 63938],
michael@0 8233 [36988, 63939], 39719, [12243, 40845, 63940], [22744, 63818], 23105,
michael@0 8234 [23650, 63819], [27155, 63820], [28122, 63821], [28431, 63822], 30267,
michael@0 8235 [32047, 63823], [32311, 63824], 34078, 35128, 37860, [38475, 63825],
michael@0 8236 [21129, 63943], 26066, [26611, 63945], 27060, [27969, 63946],
michael@0 8237 [28316, 63947], 28687, [29705, 63948], 29792, [30041, 63949], 30244,
michael@0 8238 [30827, 63950], 35628, [39006, 63952], [20845, 63953], [25134, 63954],
michael@0 8239 [38520, 63955], 20374, [20523, 63956], [23833, 63957], [28138, 63958],
michael@0 8240 32184, [36650, 63959], [24459, 63960], [24900, 63961], [26647, 63962],
michael@0 8241 [38534, 63964], [21202, 63826], [32907, 63827], [20956, 63828],
michael@0 8242 [20940, 63829], 26974, [31260, 63830], [32190, 63831], [33777, 63832],
michael@0 8243 [38517, 63833], 20442, [21033, 63965], 21400, [21519, 63966], 21774,
michael@0 8244 [23653, 63967], 24743, [26446, 63969], [26792, 63970], 28012, 29313, 29432,
michael@0 8245 [29702, 63972], 29827, [30178, 63973], 31852, [32633, 63974], 32696, 33673,
michael@0 8246 [35023, 63975], [35041, 63976], [12197, 37324, 63977], 37328,
michael@0 8247 [38626, 63978], 39881, [21533, 63981], 28542, [29136, 63982],
michael@0 8248 [29848, 63983], [34298, 63984], 36522, [38563, 63985], [40023, 63986],
michael@0 8249 [40607, 63987], [26519, 63988], [28107, 63989], 29747, [33256, 63990],
michael@0 8250 38678, 30764, [12148, 31435, 63991], [31520, 63992], [31890, 63993], 25705,
michael@0 8251 29802, 30194, 30908, 30952, [12218, 39340], 39764, [12231, 40635], 23518,
michael@0 8252 24149, 28448, 33180, 33707, 37000, 19975, 21325, 23081, 24018, 24398,
michael@0 8253 24930, 25405, 26217, 26364, 28415, 28459, 28771, 30622, 33836, 34067,
michael@0 8254 34875, 36627, 39237, 39995, 21788, 25273, 26411, 27819, 33545, 35178,
michael@0 8255 38778, 20129, 22916, {f: 2, c: 24536}, 26395, 32178, 32596, 33426, 33579,
michael@0 8256 33725, 36638, 37017, 22475, 22969, 23186, 23504, 26151, 26522, 26757,
michael@0 8257 27599, 29028, 32629, 36023, 36067, 36993, 39749, 33032, 35978, 38476,
michael@0 8258 39488, [12230, 40613], 23391, 27667, 29467, 30450, 30431, 33804, 20906,
michael@0 8259 35219, 20813, 20885, 21193, 26825, 27796, 30468, 30496, 32191, 32236,
michael@0 8260 [12207, 38754], 40629, 28357, 34065, 20901, 21517, 21629, 26126, 26269,
michael@0 8261 26919, 28319, [12139, 30399], 30609, 33559, 33986, 34719, 37225, 37528,
michael@0 8262 40180, 34946, 20398, 20882, 21215, 22982, 24125, 24917, {f: 2, c: 25720},
michael@0 8263 26286, 26576, 27169, 27597, [12113, 27611], 29279, 29281, 29761, 30520,
michael@0 8264 [12141, 30683], 32791, 33468, 33541, 35584, 35624, 35980, [12106, 26408],
michael@0 8265 27792, 29287, [12140, 30446], 30566, 31302, 40361, 27519, 27794, 22818,
michael@0 8266 26406, 33945, 21359, 22675, 22937, 24287, 25551, 26164, 26483, 28218,
michael@0 8267 29483, 31447, 33495, 37672, 21209, 24043, 25006, 25035, 25098, 25287,
michael@0 8268 25771, [12102, 26080], 26969, 27494, [12111, 27595], 28961, 29687, 30045,
michael@0 8269 32326, 33310, 33538, 34154, 35491, 36031, 38695, 40289, 22696, 40664,
michael@0 8270 20497, 21006, 21563, 21839, [12098, 25991], 27766, {f: 2, c: 32010}, 32862,
michael@0 8271 34442, [12200, 38272], 38639, 21247, 27797, 29289, 21619, 23194, 23614,
michael@0 8272 23883, 24396, 24494, 26410, 26806, 26979, 28220, 28228, 30473,
michael@0 8273 [12150, 31859], 32654, 34183, 35598, 36855, 38753, 40692, 23735, 24758,
michael@0 8274 24845, 25003, 25935, {f: 2, c: 26107}, 27665, 27887, 29599, 29641, 32225,
michael@0 8275 38292, 23494, 34588, 35600, 21085, 21338, 25293, 25615, 25778, 26420,
michael@0 8276 27192, 27850, 29632, 29854, 31636, 31893, 32283, 33162, 33334, 34180,
michael@0 8277 36843, 38649, 39361, 20276, 21322, 21453, 21467, 25292, 25644, 25856,
michael@0 8278 26001, 27075, 27886, 28504, 29677, 30036, 30242, 30436, 30460, 30928,
michael@0 8279 [30971, 63844], 31020, 32070, 33324, 34784, 36820, 38930, 39151, 21187,
michael@0 8280 25300, 25765, 28196, 28497, 30332, 36299, 37297, 37474, 39662, 39747,
michael@0 8281 20515, 20621, 22346, 22952, 23592, 24135, 24439, 25151, 25918,
michael@0 8282 [12101, 26041], 26049, 26121, 26507, 27036, 28354, 30917, 32033, 32938,
michael@0 8283 33152, 33323, 33459, 33953, 34444, 35370, 35607, 37030, 38450, 40848,
michael@0 8284 20493, 20467, 22521, 24472, 25308, 25490, 26479, 28227, 28953, 30403,
michael@0 8285 32972, 32986, {f: 2, c: 35060}, 35097, 36064, 36649, 37197, 38506, 20271,
michael@0 8286 20336, 24091, 26575, 26658, [12137, 30333], 30334, 39748, 24161, 27146,
michael@0 8287 29033, 29140, 30058, 32321, 34115, 34281, 39132, 20240, 31567, 32624,
michael@0 8288 38309, 20961, 24070, 26805, 27710, 27726, 27867, 29359, 31684, 33539,
michael@0 8289 27861, 29754, 20731, 21128, 22721, 25816, 27287, 29863, 30294, 30887,
michael@0 8290 34327, 38370, 38713, 21342, 24321, 35722, 36776, 36783, 37002, 21029,
michael@0 8291 30629, 40009, 40712, 19993, 20482, 20853, 23643, 24183, 26142, 26170,
michael@0 8292 26564, 26821, 28851, 29953, 30149, 31177, 31453, 36647, 39200, 39432,
michael@0 8293 20445, 22561, 22577, 23542, 26222, 27493, 27921, 28282, 28541, 29668,
michael@0 8294 29995, 33769, 35036, 35091, 35676, 36628, 20239, 20693, 21264,
michael@0 8295 [12056, 21340], 23443, [24489, 63846], 26381, 31119, 33145, 33583, 34068,
michael@0 8296 35079, 35206, 36665, [36667, 64007], 39333, 39954, 26412, 20086, 20472,
michael@0 8297 22857, 23553, {f: 2, c: 23791}, 25447, 26834, 28925, 29090, 29739, 32299,
michael@0 8298 34028, 34562, 36898, 37586, 40179, [19981, 63847], 20184, 20463, 20613,
michael@0 8299 21078, 21103, 21542, 21648, 22496, 22827, 23142, 23386, 23413, 23500,
michael@0 8300 24220, 25206, 25975, 26023, 28014, 28325, [12119, 29238], 31526, 31807,
michael@0 8301 [12152, 32566], {f: 2, c: 33104}, 33178, 33344, 33433, 33705, 35331, 36000,
michael@0 8302 36070, 36091, 36212, 36282, 37096, 37340, [12201, 38428], 38468, 39385,
michael@0 8303 40167, [21271, 63843], 20998, 21545, 22132, 22707, 22868, 22894, 24575,
michael@0 8304 24996, 25198, 26128, 27774, 28954, 30406, 31881, 31966, 32027, 33452,
michael@0 8305 36033, 38640, 20315, 24343, 24447, 25282, 23849, 26379, 26842, 30844,
michael@0 8306 32323, 40300, 19989, 20633, [12052, 21269], 21290, 21329, 22915, 23138,
michael@0 8307 24199, 24754, 24970, 25161, 25209, 26000, 26503, 27047, [12112, 27604],
michael@0 8308 {f: 3, c: 27606}, 27832, 29749, 30202, 30738, 30865, 31189, 31192, 31875,
michael@0 8309 32203, 32737, 32933, 33086, 33218, 33778, 34586, 35048, 35513, 35692,
michael@0 8310 36027, 37145, [12206, 38750], [12214, 39131], [12240, 40763], 22188, 23338,
michael@0 8311 24428, 25996, 27315, 27567, 27996, 28657, 28693, 29277, 29613, 36007,
michael@0 8312 36051, 38971, 24977, 27703, 32856, 39425, 20045, 20107, 20123, 20181,
michael@0 8313 20282, 20284, 20351, 20447, 20735, 21490, 21496, 21766, 21987, 22235,
michael@0 8314 [12064, 22763], 22882, 23057, 23531, 23546, 23556, 24051, 24107, 24473,
michael@0 8315 24605, 25448, 26012, 26031, 26614, 26619, 26797, 27515, 27801, 27863,
michael@0 8316 28195, 28681, 29509, 30722, 31038, 31040, 31072, 31169, 31721, 32023,
michael@0 8317 32114, 32902, 33293, 33678, 34001, 34503, 35039, 35408, 35422, 35613,
michael@0 8318 36060, 36198, 36781, 37034, 39164, 39391, 40605, 21066, 26388, 20632,
michael@0 8319 21034, [12077, 23665], 25955, 27733, 29642, 29987, 30109, 31639, 33948,
michael@0 8320 37240, 38704, 20087, 25746, [27578, 63856], 29022, 34217, 19977, 26441,
michael@0 8321 26862, 28183, 33439, 34072, 34923, 25591, 28545, 37394, 39087, 19978,
michael@0 8322 20663, 20687, 20767, 21830, 21930, 22039, 23360, 23577, 23776, 24120,
michael@0 8323 24202, 24224, 24258, 24819, 26705, 27233, 28248, 29245, 29248,
michael@0 8324 [29376, 63994], 30456, 31077, 31665, 32724, 35059, 35316, 35443, 35937,
michael@0 8325 36062, 38684, [22622, 63852], 29885, 36093, 21959, 31329, [32034, 63850],
michael@0 8326 [12170, 33394], 29298, [12131, 29983], 29989, 31513, 22661, 22779, 23996,
michael@0 8327 24207, 24246, 24464, 24661, 25234, 25471, 25933, 26257, 26329, 26360,
michael@0 8328 26646, 26866, 29312, 29790, 31598, 32110, 32214, 32626, 32997, 33298,
michael@0 8329 34223, 35199, 35475, 36893, 37604, [12233, 40653], [12239, 40736],
michael@0 8330 [12067, 22805], 22893, 24109, 24796, 26132, 26227, 26512, 27728, 28101,
michael@0 8331 28511, [12143, 30707], 30889, 33990, 37323, 37675, 20185, 20682, 20808,
michael@0 8332 21892, 23307, 23459, 25159, 25982, 26059, 28210, 29053, 29697, 29764,
michael@0 8333 29831, 29887, 30316, 31146, 32218, 32341, 32680, 33146, 33203, 33337,
michael@0 8334 34330, 34796, 35445, 36323, 36984, 37521, 37925, 39245, 39854, 21352,
michael@0 8335 23633, 26964, 27844, 27945, 28203, [12166, 33292], 34203, 35131, 35373,
michael@0 8336 [35498, 63855, 63905], 38634, 40807, 21089, 26297, 27570, 32406, 34814,
michael@0 8337 36109, 38275, 38493, 25885, 28041, 29166, 22478, 22995, 23468, 24615,
michael@0 8338 24826, 25104, 26143, 26207, 29481, 29689, 30427, [30465, 63853], 31596,
michael@0 8339 32854, 32882, 33125, 35488, 37266, 19990, 21218, 27506, 27927, 31237,
michael@0 8340 31545, 32048, 36016, 21484, 22063, 22609, 23477, [12073, 23567], 23569,
michael@0 8341 24034, 25152, 25475, 25620, 26157, 26803, 27836, 28040, 28335, 28703,
michael@0 8342 28836, 29138, 29990, 30095, 30094, 30233, 31505, 31712, 31787, 32032,
michael@0 8343 32057, 34092, 34157, 34311, 35380, 36877, 36961, 37045, 37559, 38902,
michael@0 8344 39479, 20439, 23660, 26463, 28049, 31903, 32396, 35606, 36118, 36895,
michael@0 8345 23403, 24061, 25613, 33984, 36956, 39137, [29575, 63841, 63963], 23435,
michael@0 8346 24730, 26494, 28126, 35359, 35494, 36865, 38924, 21047, 28753, 30862,
michael@0 8347 37782, 34928, 37335, 20462, 21463, 22013, 22234, 22402, 22781, 23234,
michael@0 8348 23432, 23723, 23744, 24101, 24833, 25101, [12095, 25163], 25480, 25628,
michael@0 8349 25910, [25976, 63849], 27193, 27530, [12116, 27700], 27929, 28465, 29159,
michael@0 8350 29417, 29560, 29703, 29874, 30246, 30561, 31168, 31319, 31466, 31929,
michael@0 8351 32143, 32172, 32353, 32670, 33065, 33585, 33936, 34010, 34282, 34966,
michael@0 8352 35504, 35728, 36664, 36930, 36995, 37228, 37526, 37561, 38539,
michael@0 8353 {f: 2, c: 38567}, 38614, 38656, 38920, [12216, 39318], 39635, 39706, 21460,
michael@0 8354 22654, 22809, 23408, 23487, 28113, 28506, 29087, 29729, 29881, 32901,
michael@0 8355 33789, 24033, 24455, 24490, 24642, 26092, 26642, 26991, 27219, 27529,
michael@0 8356 27957, 28147, 29667, 30462, 30636, 31565, 32020, 33059, 33308, 33600,
michael@0 8357 34036, 34147, 35426, 35524, 37255, 37662, 38918, 39348, 25100, 34899,
michael@0 8358 36848, 37477, 23815, 23847, 23913, 29791, 33181, 34664, 28629,
michael@0 8359 [25342, 63859], 32722, 35126, 35186, 19998, 20056, 20711, 21213, 21319,
michael@0 8360 25215, 26119, 32361, 34821, 38494, 20365, 21273, 22070, 22987, 23204,
michael@0 8361 [12075, 23608], 23630, 23629, 24066, 24337, 24643, 26045, 26159, 26178,
michael@0 8362 26558, 26612, 29468, [12142, 30690], [12144, 31034], 32709, 33940, 33997,
michael@0 8363 35222, 35430, 35433, 35553, [12183, 35925], 35962, 22516, 23508, 24335,
michael@0 8364 24687, 25325, 26893, 27542, 28252, 29060, 31698, 34645, [35672, 63996],
michael@0 8365 36606, [12215, 39135], 39166, 20280, 20353, 20449, 21627, 23072, 23480,
michael@0 8366 24892, 26032, 26216, 29180, 30003, 31070, 32051, 33102, [12162, 33251],
michael@0 8367 33688, 34218, 34254, 34563, 35338, [12189, 36523], [12191, 36763], 36805,
michael@0 8368 22833, 23460, 23526, 24713, 23529, 23563, [12092, 24515], 27777, 28145,
michael@0 8369 28683, 29978, 33455, 35574, [20160, 63997], [12055, 21313], 38617,
michael@0 8370 [12114, 27663], 20126, 20420, 20818, 21854, 23077, 23784, 25105,
michael@0 8371 [12123, 29273], 33469, 33706, 34558, 34905, 35357, 38463, 38597, 39187,
michael@0 8372 40201, 40285, 22538, 23731, 23997, 24132, [24801, 63929], 24853, 25569,
michael@0 8373 [27138, 63764, 63836, 63935], 28197, 37122, 37716, 38990, 39952, 40823,
michael@0 8374 23433, 23736, 25353, 26191, 26696, 30524, 38593, 38797, 38996, 39839,
michael@0 8375 26017, 35585, 36555, 38332, 21813, 23721, 24022, 24245, 26263, 30284,
michael@0 8376 33780, 38343, 22739, 25276, 29390, 40232, 20208, 22830, 24591, 26171,
michael@0 8377 27523, 31207, 40230, 21395, 21696, 22467, 23830, 24859, 26326, 28079,
michael@0 8378 30861, 33406, 38552, 38724, 21380, 25212, 25494, 28082, 32266, 33099,
michael@0 8379 38989, 27387, 32588, 40367, 40474, 20063, 20539, 20918, 22812, 24825,
michael@0 8380 25590, 26928, 29242, 32822, 37326, 24369, 32004, [33509, 63860], 33903,
michael@0 8381 33979, 34277, 36493, 20335, 22756, 23363, 24665, 25562, 25880, 25965,
michael@0 8382 26264, 26954, 27171, 27915, 28673, 29036, 30162, 30221, 31155, 31344,
michael@0 8383 [12154, 32650], 35140, 35731, 37312, 38525, 39178, 22276, 24481, 26044,
michael@0 8384 28417, 30208, 31142, 35486, 39341, [12226, 39770], 40812, 20740, 25014,
michael@0 8385 25233, 27277, 33222, 20547, 22576, 24422, 28937, [12180, 35328], 35578,
michael@0 8386 23420, 34326, 20474, 20796, 22196, 22852, 25513, 28153, 23978, 26989,
michael@0 8387 20870, 20104, 20313, 22914, 27487, 27741, 29877, 30998, 33287, 33349,
michael@0 8388 33593, 36671, 36701, 39192, 20134, 22495, 24441, [26131, 63968], 30123,
michael@0 8389 32377, 35695, 36870, 39515, 22181, 22567, 23032, 23071, 23476, 24310,
michael@0 8390 25424, 25403, 26941, 27783, 27839, 28046, 28051, 28149, 28436, 28895,
michael@0 8391 28982, 29017, 29123, 29141, 30799, 30831, 31605, 32227, 32303, 34893,
michael@0 8392 36575, 37467, 40182, 24709, 28037, 29105, 38321, 21421, 26579, 28814,
michael@0 8393 28976, 29744, 33398, 33490, 38331, 39653, 40573, 26308, 29121,
michael@0 8394 [33865, 63854], 22603, 23992, 24433, 26144, 26254, 27001, 27054, 27704,
michael@0 8395 27891, 28214, 28481, 28634, 28699, 28719, 29008, 29151, 29552, 29787,
michael@0 8396 29908, 30408, 31310, 32403, 33521, 35424, 36814, 37704, 38681, 20034,
michael@0 8397 20522, 21000, 21473, 26355, 27757, 28618, 29450, 30591, 31330, 33454,
michael@0 8398 34269, 34306, 35028, 35427, 35709, 35947, 37555, 38675, 38928, 20116,
michael@0 8399 20237, 20425, 20658, 21320, 21566, 21555, 21978, 22626, 22714, 22887,
michael@0 8400 23067, 23524, 24735, 25034, 25942, 26111, 26212, 26791, 27738, 28595,
michael@0 8401 28879, 29100, 29522, 31613, 34568, 35492, 39986, 40711, 23627, 27779,
michael@0 8402 29508, [12127, 29577], 37434, 28331, 29797, 30239, 31337, 32277, 34314,
michael@0 8403 20800, 22725, 25793, 29934, 29973, 30320, 32705, 37013, 38605, 39252,
michael@0 8404 28198, [12129, 29926], {f: 2, c: 31401}, 33253, 34521, 34680, 35355, 23113,
michael@0 8405 23436, 23451, 26785, 26880, 28003, 29609, 29715, 29740, 30871, 32233,
michael@0 8406 32747, 33048, 33109, 33694, 35916, [38446, 63942], 38929, [12104, 26352],
michael@0 8407 24448, 26106, 26505, 27754, 29579, 20525, 23043, 27498, 30702, 22806,
michael@0 8408 23916, 24013, 29477, 30031, 20709, 20985, 22575, 22829, 22934, 23002,
michael@0 8409 23525, 23970, 25303, 25622, 25747, 25854, 26332, 27208, 29183, 29796,
michael@0 8410 31368, 31407, 32327, 32350, 32768, 33136, 34799, 35201, 35616, 36953,
michael@0 8411 36992, 39250, 24958, 27442, 28020, 32287, 35109, 36785, 20433, 20653,
michael@0 8412 20887, 21191, 22471, 22665, 23481, 24248, 24898, 27029, 28044, 28263,
michael@0 8413 28342, 29076, 29794, [12132, 29992], 29996, 32883, 33592, 33993, 36362,
michael@0 8414 37780, 37854, 20110, 20305, 20598, 20778, [12060, 21448], 21451, 21491,
michael@0 8415 23431, 23507, 23588, 24858, 24962, 26100, [12124, 29275], 29591, 29760,
michael@0 8416 30402, 31056, 31121, 31161, 32006, [12155, 32701], 33419, 34261, 34398,
michael@0 8417 36802, 36935, 37109, 37354, 38533, [12204, 38632], 38633, 21206, 24423,
michael@0 8418 26093, 26161, 26671, 29020, 31286, 37057, 38922, 20113, 27218, 27550,
michael@0 8419 28560, 29065, 32792, 33464, 34131, 36939, 38549, 38642, 38907, 34074,
michael@0 8420 39729, 20112, 29066, 38596, 20803, 21407, 21729, 22291, 22290, 22435,
michael@0 8421 23195, 23236, 23491, 24616, 24895, 25588, 27781, 27961, 28274, 28304,
michael@0 8422 29232, 29503, 29783, 33489, 34945, 36677, 36960, 38498, 39000, 40219,
michael@0 8423 [12105, 26376], 36234, 37470, 20301, 20553, 20702, 21361, 22285, 22996,
michael@0 8424 23041, 23561, 24944, 26256, 28205, 29234, 29771, 32239, 32963, 33806,
michael@0 8425 33894, 34111, 34655, 34907, 35096, 35586, 36949, [12209, 38859], 39759,
michael@0 8426 20083, 20369, 20754, 20842, 21807, 21929, 23418, 23461, {f: 2, c: 24188},
michael@0 8427 24254, 24736, 24799, {f: 2, c: 24840}, 25540, 25912, 26377, 26580, 26586,
michael@0 8428 {f: 2, c: 26977}, 27833, 27943, 28216, 28641, {f: 2, c: 29494}, 29788,
michael@0 8429 30001, 30290, 32173, 33278, 33848, 35029, 35480, 35547, 35565, 36400,
michael@0 8430 36418, 36938, 36926, 36986, [12195, 37193], 37321, 37742, 22537, 27603,
michael@0 8431 [12161, 32905], 32946, 20801, 22891, 23609, 28516, 29607, 32996, 36103,
michael@0 8432 37399, 38287, [12160, 32895], 25102, 28700, 32104, 34701, 22432, 24681,
michael@0 8433 24903, 27575, 35518, 37504, 38577, [12036, 20057], 21535, 28139, 34093,
michael@0 8434 38512, [12211, 38899], 39150, 25558, 27875, [12194, 37009], 20957, 25033,
michael@0 8435 33210, 40441, 20381, 20506, 20736, 23452, 24847, 25087, 25836, 26885,
michael@0 8436 27589, 30097, 30691, 32681, 33380, 34191, 34811, [12176, 34915], 35516,
michael@0 8437 35696, 37291, [12038, 20108], 20197, 20234, 22839, 23016, 24050, 24347,
michael@0 8438 24411, 24609, 29246, 29669, [30064, 63842], 30157, 31227, [12157, 32780],
michael@0 8439 [12159, 32819], 32900, 33505, 33617, 36029, 36019, 36999, 39156, 39180,
michael@0 8440 28727, 30410, 32714, 32716, 32764, 35610, [12040, 20154], 20161, 20995,
michael@0 8441 21360, [21693, 63902], 22240, 23035, 23493, 24341, 24525, 28270, 32106,
michael@0 8442 33589, 34451, 35469, 38765, 38775, [12032, 19968], 20314, 20350, 22777,
michael@0 8443 [12103, 26085], 28322, 36920, 37808, 39353, 20219, 22764, 22922, 23001,
michael@0 8444 24641, 31252, 33615, 36035, [12042, 20837], 21316, 20173, 21097, 23381,
michael@0 8445 33471, 20180, [21050, 63999], 21672, 22985, 23039, [12070, 23376], 23383,
michael@0 8446 23388, 24675, 24904, 28363, [28825, 63995], 29038, 29574, 29943, 30133,
michael@0 8447 30913, 32043, 32773, [12163, 33258], 33576, 34071, 34249, 35566, 36039,
michael@0 8448 38604, 20316, 21242, 22204, 26027, 26152, 28796, 28856, 29237, 32189,
michael@0 8449 33421, 37196, 38592, 40306, 23409, 26855, 27544, 28538, 30430, 23697,
michael@0 8450 26283, 28507, 31668, 31786, 34870, 38620, 19976, 20183, 21280, 22580,
michael@0 8451 22715, 22767, 22892, 23559, 24115, 24196, 24373, 25484, 26290, 26454,
michael@0 8452 27167, 27299, 27404, 28479, 29254, 29520, 29835, 31456, 31911, 33144,
michael@0 8453 33247, 33255, 33674, 33900, 34083, 34196, 34255, 35037, 36115, 37292,
michael@0 8454 [12199, 38263], 38556, 20877, 21705, 22312, 23472, 25165, 26448, 26685,
michael@0 8455 26771, 28221, 28371, 28797, 32289, 35009, 36001, 36617, 40779, 40782,
michael@0 8456 29229, 31631, 35533, 37658, 20295, 20302, 20786, 21632, 22992, 24213,
michael@0 8457 25269, 26485, 26990, 27159, 27822, 28186, 29401, 29482, 30141, 31672,
michael@0 8458 32053, 33511, 33785, 33879, 34295, 35419, 36015, 36487, 36889, 37048,
michael@0 8459 38606, 40799, 21219, 21514, 23265, 23490, 25688, 25973, 28404, 29380,
michael@0 8460 30340, 31309, 31515, 31821, 32318, 32735, 33659, 35627, 36042,
michael@0 8461 [12186, 36196], 36321, 36447, 36842, 36857, 36969, 37841, 20291, 20346,
michael@0 8462 20659, 20840, 20856, 21069, 21098, 22625, 22652, 22880, 23560, 23637,
michael@0 8463 24283, 24731, 25136, 26643, 27583, 27656, 28593, 29006, 29728,
michael@0 8464 [12133, 30000], 30008, 30033, 30322, 31564, 31627, 31661, 31686, 32399,
michael@0 8465 35438, 36670, 36681, 37439, 37523, 37666, 37931, 38651, 39002, 39019,
michael@0 8466 39198, [20999, 64000], 25130, 25240, 27993, 30308, 31434, 31680, 32118,
michael@0 8467 21344, 23742, 24215, 28472, 28857, 31896, 38673, 39822, 40670, 25509,
michael@0 8468 25722, 34678, 19969, 20117, 20141, 20572, 20597, 21576, 22979, 23450,
michael@0 8469 24128, 24237, 24311, 24449, 24773, 25402, 25919, 25972, 26060, 26230,
michael@0 8470 26232, 26622, 26984, 27273, 27491, 27712, 28096, 28136, 28191, 28254,
michael@0 8471 28702, 28833, 29582, 29693, 30010, 30555, 30855, 31118, 31243, 31357,
michael@0 8472 31934, 32142, 33351, 35330, 35562, 35998, 37165, 37194, 37336, 37478,
michael@0 8473 37580, 37664, 38662, 38742, 38748, 38914, [12237, 40718], 21046, 21137,
michael@0 8474 21884, 22564, 24093, 24351, 24716, 25552, 26799, 28639, 31085, 31532,
michael@0 8475 33229, 34234, 35069, 35576, 36420, 37261, 38500, 38555, 38717, 38988,
michael@0 8476 [12241, 40778], 20430, 20806, 20939, 21161, 22066, 24340, 24427, 25514,
michael@0 8477 25805, 26089, 26177, 26362, 26361, 26397, 26781, 26839, 27133, 28437,
michael@0 8478 28526, 29031, 29157, [12118, 29226], 29866, 30522, 31062, 31066, 31199,
michael@0 8479 31264, 31381, 31895, 31967, 32068, 32368, 32903, 34299, 34468, 35412,
michael@0 8480 35519, 36249, 36481, 36896, 36973, 37347, 38459, 38613, [12227, 40165],
michael@0 8481 26063, 31751, [12188, 36275], 37827, 23384, 23562, 21330, 25305, 29469,
michael@0 8482 20519, 23447, 24478, 24752, 24939, 26837, 28121, 29742, 31278, 32066,
michael@0 8483 32156, 32305, 33131, 36394, 36405, 37758, 37912, 20304, 22352, 24038,
michael@0 8484 24231, 25387, 32618, 20027, 20303, 20367, 20570, 23005, 32964, 21610,
michael@0 8485 21608, 22014, 22863, 23449, 24030, 24282, 26205, 26417, 26609, 26666,
michael@0 8486 27880, 27954, 28234, 28557, 28855, 29664, 30087, 31820, 32002, 32044,
michael@0 8487 32162, [12168, 33311], 34523, 35387, 35461, [12187, 36208], 36490, 36659,
michael@0 8488 36913, 37198, 37202, 37956, 39376, [12149, 31481], 31909, 20426, 20737,
michael@0 8489 20934, 22472, 23535, 23803, 26201, 27197, 27994, 28310, 28652, 28940,
michael@0 8490 30063, 31459, 34850, 36897, 36981, 38603, 39423, 33537, 20013, 20210,
michael@0 8491 34886, 37325, 21373, 27355, 26987, 27713, 33914, 22686, 24974, 26366,
michael@0 8492 25327, 28893, 29969, 30151, 32338, 33976, 35657, 36104, 20043, 21482,
michael@0 8493 21675, 22320, 22336, 24535, 25345, 25351, 25711, [12096, 25903], 26088,
michael@0 8494 26234, 26525, 26547, [12108, 27490], 27744, 27802, 28460, 30693, 30757,
michael@0 8495 31049, 31063, 32025, 32930, 33026, [12164, 33267], 33437, 33463, 34584,
michael@0 8496 35468, 36100, 36286, 36978, 30452, 31257, 31287, 32340, 32887, 21767,
michael@0 8497 21972, 22645, 25391, 25634, 26185, 26187, 26733, 27035, 27524, 27941,
michael@0 8498 28337, 29645, 29800, 29857, 30043, 30137, 30433, 30494, 30603, 31206,
michael@0 8499 32265, 32285, 33275, 34095, 34967, 35386, 36049, 36587,
michael@0 8500 [12192, 36784, 63857], 36914, 37805, 38499, 38515, 38663, 20356, 21489,
michael@0 8501 23018, 23241, 24089, 26702, 29894, 30142, 31209, 31378, 33187, 34541,
michael@0 8502 36074, 36300, 36845, 26015, 26389, 22519, 28503, 32221, 36655, 37878,
michael@0 8503 38598, 24501, 25074, 28548, 19988, 20376, 20511, 21449, 21983, 23919,
michael@0 8504 24046, 27425, 27492, 30923, 31642, 36425, [12190, 36554, 63746], 36974,
michael@0 8505 25417, 25662, 30528, 31364, 37679, 38015, 40810, 25776, 28591, 29158,
michael@0 8506 29864, 29914, 31428, 31762, 32386, 31922, 32408, 35738, 36106, 38013,
michael@0 8507 39184, 39244, 21049, 23519, 25830, 26413, 32046, 20717, [21443, 63851],
michael@0 8508 22649, {f: 2, c: 24920}, 25082, 26028, 31449, 35730, 35734, 20489, 20513,
michael@0 8509 21109, 21809, 23100, 24288, 24432, 24884, 25950, 26124, 26166, 26274,
michael@0 8510 27085, 28356, 28466, 29462, 30241, 31379, 33081, 33369, 33750, 33980,
michael@0 8511 20661, 22512, 23488, 23528, 24425, 25505, 30758, 32181, 33756, 34081,
michael@0 8512 37319, 37365, 20874, 26613, 31574, 36012, 20932, 22971, 24765, 34389,
michael@0 8513 20508, 21076, 23610, 24957, 25114, [25299, 64002], 25842, 26021, 28364,
michael@0 8514 30240, 33034, 36448, 38495, 38587, 20191, 21315, 21912, 22825, 24029,
michael@0 8515 25797, 27849, 28154, 29588, 31359, [12167, 33307], 34214, 36068, 36368,
michael@0 8516 36983, 37351, 38369, 38433, 38854, 20984, 21746, 21894, 24505, 25764,
michael@0 8517 28552, 32180, 36639, 36685, 37941, 20681, 23574, 27838, 28155, 29979,
michael@0 8518 30651, 31805, 31844, 35449, 35522, 22558, 22974, 24086, 25463, 29266,
michael@0 8519 30090, 30571, 35548, 36028, 36626, 24307, 26228, 28152, 32893, 33729,
michael@0 8520 35531, [12205, 38737], 39894, 21059, 26367, 28053, 28399, 32224, 35558,
michael@0 8521 36910, 36958, 39636, 21021, 21119, 21736, 24980, 25220, 25307, 26786,
michael@0 8522 26898, 26970, 27189, 28818, 28966, 30813, 30977, 30990, 31186, 31245,
michael@0 8523 32918, [12171, 33400], 33493, 33609, 34121, 35970, 36229, 37218, 37259,
michael@0 8524 37294, 20419, 22225, 29165, 30679, 34560, 35320, [12072, 23544], 24534,
michael@0 8525 26449, 37032, 21474, 22618, 23541, 24740, 24961, 25696, 32317, 32880,
michael@0 8526 34085, 37507, 25774, 20652, 23828, 26368, 22684, 25277, 25512, 26894,
michael@0 8527 27000, 27166, 28267, 30394, 31179, 33467, 33833, 35535, 36264, 36861,
michael@0 8528 37138, 37195, 37276, 37648, 37656, 37786, 38619, 39478, 39949, 19985,
michael@0 8529 30044, 31069, 31482, 31569, 31689, 32302, 33988, 36441, 36468, 36600,
michael@0 8530 36880, 26149, 26943, 29763, 20986, 26414, 40668, 20805, 24544, 27798,
michael@0 8531 34802, 34909, 34935, 24756, 33205, 33795, 36101, 21462, 21561, 22068,
michael@0 8532 23094, 23601, 28810, 32736, 32858, 33030, 33261, 36259, 37257, 39519,
michael@0 8533 40434, 20596, 20164, 21408, 24827, 28204, 23652, 20360, 20516, 21988,
michael@0 8534 23769, 24159, 24677, 26772, 27835, 28100, 29118, 30164, 30196, 30305,
michael@0 8535 31258, 31305, 32199, 32251, 32622, 33268, 34473, 36636, 38601, 39347,
michael@0 8536 [12242, 40786], 21063, 21189, 39149, 35242, 19971, 26578, 28422, 20405,
michael@0 8537 23522, 26517, [27784, 63858], 28024, 29723, 30759, 37341, 37756, 34756,
michael@0 8538 31204, 31281, 24555, 20182, 21668, 21822, 22702, 22949, 24816, 25171,
michael@0 8539 25302, 26422, 26965, 33333, 38464, 39345, 39389, 20524, 21331, 21828,
michael@0 8540 22396, 25176, 25826, 26219, 26589, 28609, 28655, 29730, 29752, 35351,
michael@0 8541 37944, 21585, 22022, 22374, 24392, 24986, 27470, 28760, 28845, 32187,
michael@0 8542 35477, 22890, 33067, 25506, 30472, 32829, 36010, 22612, 25645, 27067,
michael@0 8543 23445, 24081, 28271, 34153, 20812, 21488, 22826, 24608, 24907, 27526,
michael@0 8544 27760, 27888, 31518, 32974, 33492, 36294, 37040, 39089, 25799, 28580,
michael@0 8545 25745, 25860, 20814, 21520, [12063, 22303], 35342, 24927, 26742, 30171,
michael@0 8546 31570, 32113, 36890, 22534, 27084, 33151, 35114, 36864, 38969, 20600,
michael@0 8547 22871, 22956, 25237, 36879, 39722, 24925, 29305, 38358, 22369, 23110,
michael@0 8548 24052, 25226, 25773, 25850, 26487, 27874, 27966, 29228, 29750, 30772,
michael@0 8549 32631, 33453, 36315, 38935, 21028, 22338, 26495, 29256, 29923, 36009,
michael@0 8550 36774, 37393, 38442, [12043, 20843], 21485, 25420, 20329, 21764, 24726,
michael@0 8551 25943, 27803, 28031, 29260, 29437, 31255, 35207, [12185, 35997], 24429,
michael@0 8552 28558, 28921, 33192, 24846, [20415, 63845], 20559, 25153, [12122, 29255],
michael@0 8553 31687, 32232, 32745, 36941, 38829, 39449, 36022, 22378, 24179, 26544,
michael@0 8554 33805, 35413, 21536, 23318, 24163, 24290, 24330, 25987, 32954, 34109,
michael@0 8555 38281, 38491, 20296, 21253, 21261, 21263, 21638, 21754, 22275, 24067,
michael@0 8556 24598, 25243, 25265, 25429, 27873, 28006, 30129, 30770, 32990, 33071,
michael@0 8557 33502, 33889, 33970, 34957, 35090, 36875, 37610, 39165, 39825, 24133,
michael@0 8558 [26292, 64006], 26333, 28689, 29190, 20469, 21117, 24426, 24915, 26451,
michael@0 8559 27161, 28418, 29922, 31080, 34920, 35961, 39111, 39108, 39491, 21697,
michael@0 8560 31263, 26963, 35575, 35914, [12213, 39080], 39342, 24444, 25259, 30130,
michael@0 8561 [12138, 30382], 34987, 36991, 38466, 21305, 24380, 24517, [27852, 63848],
michael@0 8562 29644, 30050, [12134, 30091], 31558, 33534, 39325, 20047, 36924, 19979,
michael@0 8563 20309, 21414, 22799, 24264, 26160, 27827, 29781, 33655, 34662, 36032,
michael@0 8564 36944, 38686, 39957, 22737, 23416, 34384, 35604, 40372, 23506, 24680,
michael@0 8565 24717, 26097, 27735, 28450, 28579, 28698, 32597, 32752, {f: 2, c: 38289},
michael@0 8566 38480, 38867, 21106, 36676, 20989, 21547, 21688, 21859, 21898, 27323,
michael@0 8567 28085, 32216, 33382, 37532, 38519, 40569, 21512, 21704, 30418, 34532,
michael@0 8568 38308, 38356, 38492, 20130, 20233, 23022, 23270, 24055, 24658, 25239,
michael@0 8569 26477, 26689, 27782, 28207, 32568, 32923, 33322, 38917, 20133, 20565,
michael@0 8570 21683, 22419, 22874, 23401, 23475, 25032, 26999, 28023, 28707, 34809,
michael@0 8571 35299, 35442, 35559, 36994, 39405, 39608, 21182, 26680, 20502, 24184,
michael@0 8572 26447, 33607, [12175, 34892, 64008], 20139, 21521, 22190, 29670, 37141,
michael@0 8573 38911, 39177, 39255, [12217, 39321], 22099, 22687, 34395, 35377, 25010,
michael@0 8574 27382, 29563, 36562, 27463, 38570, 39511, 22869, 29184, 36203,
michael@0 8575 [12208, 38761], 20436, 23796, 24358, 25080, 26203, 27883, 28843,
michael@0 8576 [12126, 29572], 29625, 29694, 30505, 30541, 32067, 32098, 32291, 33335,
michael@0 8577 34898, 36066, 37449, 39023, 23377, [12147, 31348], [12174, 34880],
michael@0 8578 [12212, 38913], 23244, 20448, 21332, 22846, 23805, 25406, 28025, 29433,
michael@0 8579 33029, 33031, 33698, 37583, 38960, 20136, 20804, 21009, 22411, 24418,
michael@0 8580 27842, 28366, 28677, 28752, 28847, 29074, 29673, [29801, 63918], 33610,
michael@0 8581 34722, 34913, 36872, 37026, 37795, 39336, 20846, 24407, 24800, 24935,
michael@0 8582 26291, 34137, 36426, 37295, 38795, 20046, 20114, 21628, 22741, 22778,
michael@0 8583 22909, 23733, 24359, [12094, 25142], 25160, 26122, 26215, 27627, 28009,
michael@0 8584 28111, 28246, 28408, 28564, 28640, 28649, 28765, 29392, 29733, 29786,
michael@0 8585 29920, 30355, 31068, 31946, 32286, 32993, 33446, 33899, 33983, 34382,
michael@0 8586 34399, 34676, 35703, 35946, 37804, 38912, 39013, 24785, 25110, 37239,
michael@0 8587 23130, 26127, 28151, 28222, 29759, 39746, 24573, 24794, 31503, 21700,
michael@0 8588 24344, 27742, 27859, 27946, 28888, 32005, 34425, 35340, 40251, 21270,
michael@0 8589 21644, 23301, 27194, [12117, 28779], 30069, 31117, [12146, 31166], 33457,
michael@0 8590 33775, 35441, 35649, 36008, 38772, 25844, 25899, {f: 2, c: 30906}, 31339,
michael@0 8591 20024, 21914, 22864, 23462, 24187, 24739, 25563, 27489, 26213, 26707,
michael@0 8592 28185, 29029, 29872, 32008, 36996, 39529, 39973, 27963, [28369, 63748],
michael@0 8593 29502, 35905, 38346, 20976, 24140, 24488, 24653, 24822, 24880, 24908,
michael@0 8594 {f: 2, c: 26179}, 27045, 27841, 28255, 28361, 28514, 29004, 29852, 30343,
michael@0 8595 31681, 31783, 33618, 34647, 36945, 38541, [12232, 40643], 21295, 22238,
michael@0 8596 24315, 24458, 24674, 24724, 25079, 26214, 26371, 27292, 28142, 28590,
michael@0 8597 28784, 29546, 32362, 33214, 33588, 34516, 35496, 36036, 21123, 29554,
michael@0 8598 23446, 27243, 37892, 21742, 22150, 23389, 25928, 25989, 26313, 26783,
michael@0 8599 28045, 28102, [12120, 29243], 32948, 37237, 39501, 20399, 20505, 21402,
michael@0 8600 21518, 21564, 21897, 21957, 24127, 24460, 26429, 29030, 29661, 36869,
michael@0 8601 21211, 21235, 22628, 22734, 28932, 29071, 29179, 34224, 35347,
michael@0 8602 [26248, 63941], 34216, 21927, 26244, 29002, 33841, 21321, 21913, 27585,
michael@0 8603 24409, 24509, 25582, 26249, 28999, 35569, 36637, 40638, 20241, 25658,
michael@0 8604 28875, 30054, 34407, 24676, 35662, 40440, 20807, 20982, 21256, 27958,
michael@0 8605 33016, [12234, 40657], 26133, 27427, 28824, 30165, 21507, 23673, 32007,
michael@0 8606 35350, [12107, 27424], 27453, 27462, 21560, 24688, 27965, 32725, 33288,
michael@0 8607 20694, 20958, 21916, 22123, 22221, 23020, 23305, 24076, 24985, 24984,
michael@0 8608 25137, 26206, 26342, 29081, {f: 2, c: 29113}, 29351, 31143, 31232, 32690,
michael@0 8609 35440, {s: 163}, {f: 4, c: 12310}, {s: 14}, 8223, 8219, {f: 2, c: 8314},
michael@0 8610 {s: 7}, 8316, 0, {f: 2, c: 8317}, {s: 23}, 700, {s: 44}, 8942, 8759,
michael@0 8611 {s: 20}, {f: 10, c: 10122}, {s: 36}, {f: 26, c: 9398}, {s: 61},
michael@0 8612 {f: 2, c: 8826}, {f: 2, c: 8910}, {f: 2, c: 8832}, {f: 4, c: 8816}, 0,
michael@0 8613 8842, 0, 8843, {f: 2, c: 8822}, 8825, {f: 2, c: 8922}, {s: 5}, 8773, 8771,
michael@0 8614 8776, 0, 8868, {s: 78}, 8244, {s: 11}, 9839, {s: 4}, 8258, {s: 4}, 10045,
michael@0 8615 0, 0, 8226, {s: 4}, {f: 2, c: 8249}, {s: 16}, 10010, 10006, 0, 9711,
michael@0 8616 {s: 3}, 10070, 0, 9676, {s: 24}, 9775, {s: 6}, 12320, 0, {f: 10, c: 10102},
michael@0 8617 {s: 17}, 12306, 12342, {s: 13}, 8710, 0, 8735, 0, {f: 2, c: 8741}, 0, 8787,
michael@0 8618 8785, {f: 2, c: 8806}, 8723, {f: 3, c: 8853}, 0, 8980, 0, 0, 8802, 0, 9649,
michael@0 8619 0, 8738, 8784, 0, 0, 8867, 0, 0, {f: 2, c: 8814}, 8837, 8836, 8713, 8716,
michael@0 8620 {f: 2, c: 8891}, 8794, 8966, {s: 6}, 12958, 0, 8252, {s: 11}, 9702, {s: 3},
michael@0 8621 9663, 9653, 9657, 9667, {s: 4}, 9674, 12849, 12857, 13259, {f: 5, c: 9327},
michael@0 8622 {s: 18}, 8656, 8655, 8653, {s: 37}, 8657, 8659, {s: 8}, 8626, 8625, 0,
michael@0 8623 8628, 8624, 8627, {s: 14}, 8636, 8640, {s: 10}, {f: 2, c: 8644}, {s: 144},
michael@0 8624 {f: 5, c: 9347}, {s: 33}, 12948, {s: 15}, 12965, {s: 93}, 8672, 8674, 8673,
michael@0 8625 8675, {s: 4}, 8678, 8680, 8679, 8681, {s: 20}, 9757, 9759, {s: 76}, 12944,
michael@0 8626 {f: 6, c: 12938}, {s: 15}, {f: 2, c: 12318}, 8246, 0, 8245, {s: 3}, 12540,
michael@0 8627 0, 0, {f: 2, c: 44034}, {f: 2, c: 44037}, {f: 5, c: 44043}, 44056,
michael@0 8628 {f: 2, c: 44062}, {f: 3, c: 44065}, {f: 7, c: 44069}, 44078,
michael@0 8629 {f: 6, c: 44082}, {f: 2, c: 44090}, {f: 3, c: 44093}, {f: 10, c: 44097},
michael@0 8630 44108, {f: 6, c: 44110}, {f: 3, c: 44117}, {f: 3, c: 44121},
michael@0 8631 {f: 19, c: 44125}, {f: 2, c: 44146}, {f: 2, c: 44149}, 44153,
michael@0 8632 {f: 5, c: 44155}, 44162, {f: 2, c: 44167}, {f: 3, c: 44173},
michael@0 8633 {f: 3, c: 44177}, {f: 7, c: 44181}, 44190, {f: 6, c: 44194}, 44203,
michael@0 8634 {f: 2, c: 44205}, {f: 7, c: 44209}, 44218, {f: 3, c: 44222},
michael@0 8635 {f: 2, c: 44226}, {f: 3, c: 44229}, {f: 3, c: 44233}, {f: 8, c: 44237},
michael@0 8636 44246, {f: 8, c: 44248}, {f: 2, c: 44258}, {f: 2, c: 44261}, 44265, 44267,
michael@0 8637 {f: 2, c: 44269}, 44274, 44276, {f: 5, c: 44279}, {f: 2, c: 44286},
michael@0 8638 {f: 3, c: 44289}, 44293, {f: 5, c: 44295}, 44302, 44304, {f: 6, c: 44306},
michael@0 8639 {f: 3, c: 44313}, {f: 3, c: 44317}, {f: 8, c: 44321}, {f: 2, c: 44330},
michael@0 8640 {f: 6, c: 44334}, {f: 2, c: 44342}, {f: 3, c: 44345}, {f: 7, c: 44349},
michael@0 8641 44358, 44360, {f: 6, c: 44362}, {f: 3, c: 44369}, {f: 3, c: 44373},
michael@0 8642 {f: 8, c: 44377}, 44386, {f: 8, c: 44388}, {f: 2, c: 44398},
michael@0 8643 {f: 2, c: 44401}, {f: 4, c: 44407}, 44414, 44416, {f: 5, c: 44419},
michael@0 8644 {f: 2, c: 44426}, {f: 3, c: 44429}, {f: 11, c: 44433}, {f: 6, c: 44446},
michael@0 8645 {f: 18, c: 44453}, {f: 8, c: 44472}, {f: 2, c: 44482}, {f: 3, c: 44485},
michael@0 8646 {f: 7, c: 44489}, 44498, {f: 8, c: 44500}, {f: 3, c: 44509},
michael@0 8647 {f: 3, c: 44513}, {f: 19, c: 44517}, {f: 2, c: 44538}, {f: 2, c: 44541},
michael@0 8648 {f: 6, c: 44546}, 44554, 44556, {f: 6, c: 44558}, {f: 27, c: 44565},
michael@0 8649 {f: 2, c: 44594}, {f: 2, c: 44597}, 44601, {f: 5, c: 44603}, 44610, 44612,
michael@0 8650 {f: 3, c: 44615}, 44619, 44623, {f: 3, c: 44625}, 44629, {f: 5, c: 44631},
michael@0 8651 44638, {f: 3, c: 44642}, {f: 2, c: 44646}, {f: 2, c: 44650},
michael@0 8652 {f: 3, c: 44653}, {f: 7, c: 44657}, 44666, {f: 6, c: 44670},
michael@0 8653 {f: 6, c: 44678}, {f: 47, c: 44685}, 44735, {f: 3, c: 44737},
michael@0 8654 {f: 7, c: 44741}, 44750, {f: 6, c: 44754}, {f: 2, c: 44762},
michael@0 8655 {f: 11, c: 44765}, {f: 2, c: 44777}, 44780, {f: 6, c: 44782},
michael@0 8656 {f: 3, c: 44789}, {f: 3, c: 44793}, {f: 10, c: 44797}, {f: 4, c: 44809},
michael@0 8657 {f: 2, c: 44814}, {f: 27, c: 44817}, {f: 2, c: 44846}, 44849, 44851,
michael@0 8658 {f: 7, c: 44853}, 44862, 44864, {f: 4, c: 44868}, {f: 6, c: 44874},
michael@0 8659 {f: 11, c: 44881}, {f: 6, c: 44894}, {f: 19, c: 44902}, {f: 6, c: 44922},
michael@0 8660 {f: 3, c: 44929}, {f: 3, c: 44933}, {f: 7, c: 44937}, {f: 3, c: 44946},
michael@0 8661 {f: 6, c: 44950}, {f: 27, c: 44957}, {f: 2, c: 44986}, {f: 3, c: 44989},
michael@0 8662 {f: 6, c: 44993}, 45002, 45004, {f: 5, c: 45007}, {f: 7, c: 45013},
michael@0 8663 {f: 11, c: 45021}, {f: 6, c: 45034}, {f: 2, c: 45042}, {f: 3, c: 45045},
michael@0 8664 {f: 7, c: 45049}, {f: 2, c: 45058}, {f: 7, c: 45061}, {f: 3, c: 45069},
michael@0 8665 {f: 3, c: 45073}, {f: 7, c: 45077}, {f: 10, c: 45086}, {f: 27, c: 45097},
michael@0 8666 {f: 2, c: 45126}, 45129, 45131, 45133, {f: 4, c: 45135}, 45142, 45144,
michael@0 8667 {f: 3, c: 45146}, {f: 30, c: 45150}, {f: 2, c: 45182}, {f: 3, c: 45185},
michael@0 8668 {f: 7, c: 45189}, 45198, 45200, {f: 6, c: 45202}, 45211, {f: 2, c: 45213},
michael@0 8669 {f: 5, c: 45219}, 45226, 45232, 45234, {f: 2, c: 45238}, {f: 3, c: 45241},
michael@0 8670 {f: 7, c: 45245}, 45254, {f: 6, c: 45258}, {f: 2, c: 45266},
michael@0 8671 {f: 3, c: 45269}, {f: 7, c: 45273}, {f: 4, c: 45281}, {f: 34, c: 45286},
michael@0 8672 45322, {f: 3, c: 45325}, 45329, {f: 4, c: 45332}, 45338, {f: 5, c: 45342},
michael@0 8673 {f: 2, c: 45350}, {f: 3, c: 45353}, {f: 7, c: 45357}, 45366,
michael@0 8674 {f: 6, c: 45370}, {f: 2, c: 45378}, {f: 3, c: 45381}, {f: 7, c: 45385},
michael@0 8675 {f: 2, c: 45394}, {f: 2, c: 45398}, {f: 3, c: 45401}, {f: 3, c: 45405},
michael@0 8676 {f: 23, c: 45409}, {f: 2, c: 45434}, {f: 3, c: 45437}, 45441,
michael@0 8677 {f: 5, c: 45443}, 45450, 45452, {f: 4, c: 45454}, {f: 3, c: 45461},
michael@0 8678 {f: 3, c: 45465}, {f: 11, c: 45469}, {f: 35, c: 45481}, {f: 3, c: 45517},
michael@0 8679 {f: 3, c: 45521}, {f: 7, c: 45525}, 45534, {f: 8, c: 45536},
michael@0 8680 {f: 2, c: 45546}, {f: 3, c: 45549}, {f: 8, c: 45553}, 45562, 45564,
michael@0 8681 {f: 6, c: 45566}, {f: 2, c: 45574}, {f: 2, c: 45577}, {f: 7, c: 45581},
michael@0 8682 45590, 45592, {f: 6, c: 45594}, {f: 19, c: 45601}, {f: 7, c: 45621},
michael@0 8683 {f: 27, c: 45629}, {f: 3, c: 45657}, {f: 3, c: 45661}, {f: 7, c: 45665},
michael@0 8684 {f: 10, c: 45674}, {f: 6, c: 45686}, {f: 7, c: 45693}, {f: 3, c: 45702},
michael@0 8685 {f: 6, c: 45706}, {f: 2, c: 45714}, {f: 3, c: 45717}, {f: 5, c: 45723},
michael@0 8686 45730, 45732, {f: 3, c: 45735}, 45739, {f: 3, c: 45741}, {f: 3, c: 45745},
michael@0 8687 {f: 19, c: 45749}, {f: 2, c: 45770}, {f: 3, c: 45773}, 45777,
michael@0 8688 {f: 5, c: 45779}, 45786, 45788, {f: 4, c: 45790}, 45795, 45799,
michael@0 8689 {f: 2, c: 45801}, {f: 3, c: 45808}, 45814, {f: 3, c: 45820},
michael@0 8690 {f: 2, c: 45826}, {f: 3, c: 45829}, {f: 7, c: 45833}, 45842,
michael@0 8691 {f: 6, c: 45846}, {f: 55, c: 45853}, 45911, {f: 2, c: 45913}, 45917,
michael@0 8692 {f: 4, c: 45920}, 45926, 45928, 45930, {f: 2, c: 45932}, 45935,
michael@0 8693 {f: 2, c: 45938}, {f: 3, c: 45941}, {f: 7, c: 45945}, 45954,
michael@0 8694 {f: 6, c: 45958}, {f: 3, c: 45965}, {f: 3, c: 45969}, {f: 11, c: 45973},
michael@0 8695 {f: 6, c: 45986}, {f: 3, c: 45993}, {f: 23, c: 45997}, {f: 2, c: 46022},
michael@0 8696 {f: 2, c: 46025}, 46029, 46031, {f: 3, c: 46033}, 46038, 46040, 46042,
michael@0 8697 46044, {f: 2, c: 46046}, {f: 3, c: 46049}, {f: 3, c: 46053},
michael@0 8698 {f: 19, c: 46057}, {f: 19, c: 46077}, {f: 7, c: 46097}, {f: 3, c: 46105},
michael@0 8699 {f: 3, c: 46109}, {f: 7, c: 46113}, 46122, {f: 8, c: 46124},
michael@0 8700 {f: 27, c: 46133}, {f: 2, c: 46162}, {f: 3, c: 46165}, {f: 7, c: 46169},
michael@0 8701 46178, 46180, {f: 6, c: 46182}, {f: 19, c: 46189}, {f: 7, c: 46209},
michael@0 8702 {f: 20, c: 46217}, {f: 6, c: 46238}, {f: 3, c: 46245}, {f: 3, c: 46249},
michael@0 8703 {f: 8, c: 46253}, 46262, 46264, {f: 6, c: 46266}, {f: 3, c: 46273},
michael@0 8704 {f: 3, c: 46277}, {f: 7, c: 46281}, {f: 4, c: 46289}, {f: 6, c: 46294},
michael@0 8705 {f: 2, c: 46302}, {f: 2, c: 46305}, 46309, {f: 5, c: 46311}, 46318, 46320,
michael@0 8706 {f: 6, c: 46322}, {f: 27, c: 46329}, {f: 2, c: 46358}, {f: 2, c: 46361},
michael@0 8707 {f: 7, c: 46365}, 46374, {f: 5, c: 46379}, {f: 2, c: 46386},
michael@0 8708 {f: 3, c: 46389}, {f: 7, c: 46393}, 46402, {f: 5, c: 46406},
michael@0 8709 {f: 2, c: 46414}, {f: 3, c: 46417}, {f: 7, c: 46421}, 46430,
michael@0 8710 {f: 62, c: 46434}, {f: 2, c: 46498}, {f: 3, c: 46501}, 46505,
michael@0 8711 {f: 4, c: 46508}, 46514, {f: 5, c: 46518}, {f: 2, c: 46526},
michael@0 8712 {f: 3, c: 46529}, {f: 7, c: 46533}, 46542, {f: 6, c: 46546},
michael@0 8713 {f: 19, c: 46553}, {f: 35, c: 46573}, {f: 2, c: 46610}, {f: 3, c: 46613},
michael@0 8714 {f: 12, c: 46617}, {f: 6, c: 46630}, {f: 7, c: 46637}, {f: 19, c: 46645},
michael@0 8715 {f: 27, c: 46665}, {f: 3, c: 46693}, {f: 51, c: 46697}, {f: 2, c: 46750},
michael@0 8716 {f: 3, c: 46753}, {f: 6, c: 46757}, {f: 4, c: 46765}, {f: 34, c: 46770},
michael@0 8717 {f: 27, c: 46805}, {f: 3, c: 46833}, {f: 3, c: 46837}, {f: 7, c: 46841},
michael@0 8718 {f: 3, c: 46850}, {f: 34, c: 46854}, {f: 2, c: 46890}, {f: 2, c: 46893},
michael@0 8719 {f: 7, c: 46897}, 46906, {f: 8, c: 46908}, {f: 3, c: 46917},
michael@0 8720 {f: 3, c: 46921}, {f: 7, c: 46925}, {f: 10, c: 46934}, {f: 3, c: 46945},
michael@0 8721 {f: 3, c: 46949}, {f: 7, c: 46953}, 46962, 46964, {f: 6, c: 46966},
michael@0 8722 {f: 2, c: 46974}, {f: 3, c: 46977}, {f: 7, c: 46981}, 46990,
michael@0 8723 {f: 3, c: 46995}, {f: 2, c: 47002}, {f: 3, c: 47005}, {f: 7, c: 47009},
michael@0 8724 47018, {f: 6, c: 47022}, {f: 2, c: 47030}, {f: 14, c: 47033}, 47048,
michael@0 8725 {f: 34, c: 47050}, {f: 2, c: 47086}, {f: 3, c: 47089}, {f: 7, c: 47093},
michael@0 8726 47102, {f: 5, c: 47106}, {f: 2, c: 47114}, {f: 3, c: 47117},
michael@0 8727 {f: 7, c: 47121}, 47130, 47132, {f: 6, c: 47134}, {f: 2, c: 47142},
michael@0 8728 {f: 3, c: 47145}, {f: 7, c: 47149}, 47158, {f: 6, c: 47162},
michael@0 8729 {f: 3, c: 47169}, {f: 12, c: 47173}, 47186, {f: 8, c: 47188},
michael@0 8730 {f: 2, c: 47198}, {f: 3, c: 47201}, {f: 7, c: 47205}, 47214, 47216,
michael@0 8731 {f: 6, c: 47218}, {f: 3, c: 47225}, {f: 16, c: 47229}, {f: 26, c: 47246},
michael@0 8732 {f: 7, c: 47273}, {f: 3, c: 47281}, {f: 3, c: 47285}, {f: 7, c: 47289},
michael@0 8733 47298, 47300, {f: 6, c: 47302}, {f: 3, c: 47309}, {f: 3, c: 47313},
michael@0 8734 {f: 8, c: 47317}, 47326, 47328, {f: 6, c: 47330}, {f: 2, c: 47338},
michael@0 8735 {f: 3, c: 47341}, {f: 7, c: 47345}, 47354, 47356, {f: 6, c: 47358},
michael@0 8736 {f: 19, c: 47365}, {f: 7, c: 47385}, {f: 27, c: 47393}, {f: 2, c: 47422},
michael@0 8737 {f: 3, c: 47425}, {f: 7, c: 47429}, {f: 2, c: 47437}, 47440,
michael@0 8738 {f: 6, c: 47442}, {f: 2, c: 47450}, {f: 3, c: 47453}, {f: 7, c: 47457},
michael@0 8739 47466, 47468, {f: 6, c: 47470}, {f: 2, c: 47478}, {f: 3, c: 47481},
michael@0 8740 {f: 7, c: 47485}, 47494, 47496, {f: 2, c: 47499}, {f: 29, c: 47503},
michael@0 8741 {f: 2, c: 47534}, {f: 3, c: 47537}, {f: 7, c: 47541}, 47550, 47552,
michael@0 8742 {f: 6, c: 47554}, {f: 2, c: 47562}, 47565, {f: 5, c: 47571}, 47578, 47580,
michael@0 8743 {f: 2, c: 47583}, 47586, {f: 2, c: 47590}, {f: 3, c: 47593},
michael@0 8744 {f: 7, c: 47597}, 47606, {f: 5, c: 47611}, {f: 6, c: 47618},
michael@0 8745 {f: 12, c: 47625}, {f: 34, c: 47638}, {f: 2, c: 47674}, {f: 3, c: 47677},
michael@0 8746 47681, {f: 5, c: 47683}, 47690, 47692, {f: 4, c: 47695}, {f: 2, c: 47702},
michael@0 8747 {f: 3, c: 47705}, {f: 7, c: 47709}, 47718, {f: 6, c: 47722},
michael@0 8748 {f: 2, c: 47730}, {f: 3, c: 47733}, {f: 10, c: 47737}, 47750,
michael@0 8749 {f: 4, c: 47752}, {f: 27, c: 47757}, 47786, {f: 3, c: 47789}, 47793,
michael@0 8750 {f: 5, c: 47795}, 47802, 47804, {f: 6, c: 47806}, {f: 3, c: 47813},
michael@0 8751 {f: 15, c: 47817}, {f: 34, c: 47834}, {f: 3, c: 47869}, {f: 3, c: 47873},
michael@0 8752 {f: 8, c: 47877}, 47886, 47888, {f: 6, c: 47890}, {f: 3, c: 47897},
michael@0 8753 {f: 3, c: 47901}, {f: 8, c: 47905}, 47914, {f: 8, c: 47916}, 47927,
michael@0 8754 {f: 2, c: 47929}, {f: 5, c: 47935}, 47942, 47944, {f: 3, c: 47946}, 47950,
michael@0 8755 {f: 3, c: 47953}, {f: 3, c: 47957}, {f: 8, c: 47961}, 47970,
michael@0 8756 {f: 8, c: 47972}, {f: 27, c: 47981}, {f: 3, c: 48009}, {f: 3, c: 48013},
michael@0 8757 {f: 19, c: 48017}, {f: 3, c: 48037}, {f: 3, c: 48041}, {f: 7, c: 48045},
michael@0 8758 {f: 2, c: 48053}, {f: 8, c: 48056}, {f: 3, c: 48065}, {f: 3, c: 48069},
michael@0 8759 {f: 7, c: 48073}, {f: 2, c: 48081}, {f: 36, c: 48084}, {f: 2, c: 48122},
michael@0 8760 {f: 2, c: 48125}, 48129, {f: 5, c: 48131}, 48138, 48142, 48144,
michael@0 8761 {f: 2, c: 48146}, {f: 2, c: 48153}, {f: 4, c: 48160}, 48166, 48168,
michael@0 8762 {f: 3, c: 48170}, {f: 2, c: 48174}, {f: 2, c: 48178}, {f: 3, c: 48181},
michael@0 8763 {f: 7, c: 48185}, 48194, {f: 3, c: 48198}, {f: 2, c: 48202},
michael@0 8764 {f: 2, c: 48206}, {f: 12, c: 48209}, {f: 38, c: 48222}, {f: 2, c: 48262},
michael@0 8765 {f: 2, c: 48265}, 48269, {f: 5, c: 48271}, 48278, 48280, {f: 5, c: 48283},
michael@0 8766 {f: 2, c: 48290}, {f: 2, c: 48293}, {f: 7, c: 48297}, 48306,
michael@0 8767 {f: 6, c: 48310}, {f: 2, c: 48318}, {f: 3, c: 48321}, {f: 8, c: 48325},
michael@0 8768 48334, {f: 3, c: 48338}, {f: 2, c: 48342}, {f: 3, c: 48345},
michael@0 8769 {f: 23, c: 48349}, 48375, {f: 3, c: 48377}, {f: 7, c: 48381}, 48390, 48392,
michael@0 8770 {f: 6, c: 48394}, {f: 3, c: 48401}, {f: 15, c: 48405}, {f: 7, c: 48421},
michael@0 8771 {f: 19, c: 48429}, {f: 7, c: 48449}, {f: 2, c: 48458}, {f: 3, c: 48461},
michael@0 8772 {f: 7, c: 48465}, {f: 10, c: 48474}, {f: 3, c: 48485}, {f: 23, c: 48489},
michael@0 8773 {f: 2, c: 48514}, {f: 2, c: 48517}, {f: 5, c: 48523}, 48530, 48532,
michael@0 8774 {f: 3, c: 48534}, 48539, {f: 7, c: 48541}, {f: 11, c: 48549},
michael@0 8775 {f: 7, c: 48561}, {f: 27, c: 48569}, {f: 2, c: 48598}, {f: 3, c: 48601},
michael@0 8776 {f: 12, c: 48605}, {f: 6, c: 48618}, {f: 3, c: 48625}, {f: 3, c: 48629},
michael@0 8777 {f: 7, c: 48633}, {f: 2, c: 48641}, 48644, {f: 6, c: 48646},
michael@0 8778 {f: 2, c: 48654}, {f: 3, c: 48657}, {f: 7, c: 48661}, 48670,
michael@0 8779 {f: 36, c: 48672}, {f: 2, c: 48710}, {f: 3, c: 48713}, 48717,
michael@0 8780 {f: 5, c: 48719}, 48726, 48728, {f: 4, c: 48732}, {f: 2, c: 48738},
michael@0 8781 {f: 3, c: 48741}, 48745, {f: 5, c: 48747}, 48754, {f: 5, c: 48758},
michael@0 8782 {f: 2, c: 48766}, {f: 3, c: 48769}, {f: 7, c: 48773}, 48782,
michael@0 8783 {f: 6, c: 48786}, {f: 14, c: 48794}, {f: 39, c: 48809}, {f: 2, c: 48850},
michael@0 8784 {f: 2, c: 48853}, {f: 7, c: 48857}, {f: 2, c: 48865}, {f: 6, c: 48870},
michael@0 8785 {f: 20, c: 48877}, {f: 6, c: 48898}, {f: 14, c: 48906}, 48922,
michael@0 8786 {f: 34, c: 48926}, {f: 2, c: 48962}, {f: 3, c: 48965}, {f: 7, c: 48969},
michael@0 8787 {f: 3, c: 48978}, {f: 62, c: 48982}, {f: 27, c: 49045}, {f: 20, c: 49073},
michael@0 8788 {f: 6, c: 49094}, {f: 2, c: 49102}, {f: 3, c: 49105}, {f: 7, c: 49109},
michael@0 8789 {f: 2, c: 49117}, 49120, {f: 90, c: 49122}, {f: 20, c: 49213},
michael@0 8790 {f: 6, c: 49234}, {f: 3, c: 49241}, {f: 3, c: 49245}, {f: 7, c: 49249},
michael@0 8791 {f: 38, c: 49258}, {f: 2, c: 49298}, {f: 3, c: 49301}, {f: 7, c: 49305},
michael@0 8792 49314, 49316, {f: 6, c: 49318}, 49326, {f: 2, c: 49329}, {f: 5, c: 49335},
michael@0 8793 49342, {f: 3, c: 49346}, {f: 2, c: 49350}, {f: 2, c: 49354},
michael@0 8794 {f: 3, c: 49357}, {f: 7, c: 49361}, 49370, {f: 6, c: 49374},
michael@0 8795 {f: 2, c: 49382}, {f: 3, c: 49385}, {f: 7, c: 49389}, 49398, 49400,
michael@0 8796 {f: 6, c: 49402}, {f: 3, c: 49409}, {f: 3, c: 49413}, {f: 7, c: 49417},
michael@0 8797 {f: 4, c: 49425}, {f: 6, c: 49430}, {f: 2, c: 49441}, 49445,
michael@0 8798 {f: 4, c: 49448}, 49454, {f: 4, c: 49458}, 49463, {f: 2, c: 49466},
michael@0 8799 {f: 3, c: 49469}, {f: 7, c: 49473}, 49482, {f: 6, c: 49486},
michael@0 8800 {f: 2, c: 49494}, {f: 3, c: 49497}, {f: 7, c: 49501}, 49510,
michael@0 8801 {f: 6, c: 49514}, {f: 3, c: 49521}, {f: 3, c: 49525}, {f: 12, c: 49529},
michael@0 8802 {f: 6, c: 49542}, 49551, {f: 3, c: 49553}, 49557, {f: 5, c: 49559}, 49566,
michael@0 8803 49568, {f: 3, c: 49570}, {f: 2, c: 49574}, {f: 2, c: 49578},
michael@0 8804 {f: 3, c: 49581}, {f: 12, c: 49585}, {f: 6, c: 49598}, {f: 3, c: 49605},
michael@0 8805 {f: 3, c: 49609}, {f: 7, c: 49613}, {f: 2, c: 49621}, {f: 7, c: 49625},
michael@0 8806 {f: 3, c: 49633}, {f: 3, c: 49637}, {f: 7, c: 49641}, 49650,
michael@0 8807 {f: 8, c: 49652}, {f: 2, c: 49662}, {f: 3, c: 49665}, {f: 7, c: 49669},
michael@0 8808 49678, 49680, {f: 6, c: 49682}, {f: 2, c: 49690}, {f: 2, c: 49693},
michael@0 8809 {f: 7, c: 49697}, 49706, 49708, 49710, 49712, 49715, {f: 19, c: 49717},
michael@0 8810 {f: 7, c: 49737}, {f: 2, c: 49746}, {f: 3, c: 49749}, {f: 7, c: 49753},
michael@0 8811 {f: 4, c: 49761}, {f: 6, c: 49766}, {f: 2, c: 49774}, {f: 3, c: 49777},
michael@0 8812 {f: 7, c: 49781}, 49790, 49792, {f: 6, c: 49794}, {f: 6, c: 49802},
michael@0 8813 {f: 7, c: 49809}, {f: 2, c: 49817}, 49820, {f: 6, c: 49822},
michael@0 8814 {f: 2, c: 49830}, {f: 3, c: 49833}, {f: 6, c: 49838}, 49846, 49848,
michael@0 8815 {f: 34, c: 49850}, {f: 2, c: 49886}, {f: 2, c: 49889}, {f: 6, c: 49893},
michael@0 8816 49902, 49904, {f: 4, c: 49906}, 49911, 49914, {f: 3, c: 49917},
michael@0 8817 {f: 7, c: 49921}, {f: 2, c: 49930}, {f: 5, c: 49934}, {f: 2, c: 49942},
michael@0 8818 {f: 3, c: 49945}, {f: 7, c: 49949}, {f: 2, c: 49958}, {f: 27, c: 49962},
michael@0 8819 {f: 34, c: 49990}, {f: 2, c: 50026}, {f: 3, c: 50029}, 50033,
michael@0 8820 {f: 5, c: 50035}, {f: 2, c: 50042}, {f: 6, c: 50046}, {f: 3, c: 50053},
michael@0 8821 {f: 3, c: 50057}, {f: 51, c: 50061}, {f: 23, c: 50113}, {f: 2, c: 50138},
michael@0 8822 {f: 2, c: 50141}, 50145, {f: 5, c: 50147}, {f: 3, c: 50154},
michael@0 8823 {f: 6, c: 50158}, {f: 2, c: 50166}, {f: 15, c: 50169}, {f: 7, c: 50185},
michael@0 8824 {f: 19, c: 50193}, {f: 7, c: 50213}, {f: 3, c: 50221}, {f: 3, c: 50225},
michael@0 8825 {f: 7, c: 50229}, {f: 10, c: 50238}, {f: 27, c: 50249}, {f: 2, c: 50278},
michael@0 8826 {f: 3, c: 50281}, {f: 7, c: 50285}, {f: 3, c: 50294}, {f: 6, c: 50298},
michael@0 8827 {f: 19, c: 50305}, {f: 7, c: 50325}, {f: 27, c: 50333}, {f: 3, c: 50361},
michael@0 8828 {f: 44, c: 50365}, {f: 6, c: 50410}, {f: 2, c: 50418}, {f: 3, c: 50421},
michael@0 8829 50425, {f: 4, c: 50427}, {f: 10, c: 50434}, {f: 3, c: 50445},
michael@0 8830 {f: 3, c: 50449}, {f: 7, c: 50453}, {f: 11, c: 50461}, {f: 2, c: 50474},
michael@0 8831 {f: 3, c: 50477}, {f: 7, c: 50481}, 50490, 50492, {f: 6, c: 50494},
michael@0 8832 {f: 2, c: 50502}, 50507, {f: 4, c: 50511}, 50518, {f: 3, c: 50522}, 50527,
michael@0 8833 {f: 2, c: 50530}, {f: 3, c: 50533}, {f: 7, c: 50537}, 50546,
michael@0 8834 {f: 6, c: 50550}, {f: 2, c: 50558}, {f: 3, c: 50561}, {f: 2, c: 50565},
michael@0 8835 {f: 4, c: 50568}, 50574, 50576, {f: 3, c: 50578}, 50582, {f: 3, c: 50585},
michael@0 8836 {f: 3, c: 50589}, {f: 8, c: 50593}, {f: 10, c: 50602}, {f: 2, c: 50614},
michael@0 8837 50618, {f: 5, c: 50623}, 50635, 50637, 50639, {f: 2, c: 50642},
michael@0 8838 {f: 3, c: 50645}, {f: 7, c: 50649}, 50658, 50660, {f: 6, c: 50662}, 50671,
michael@0 8839 {f: 3, c: 50673}, 50677, {f: 4, c: 50680}, {f: 3, c: 50690},
michael@0 8840 {f: 3, c: 50697}, {f: 3, c: 50701}, {f: 7, c: 50705}, 50714,
michael@0 8841 {f: 7, c: 50717}, {f: 2, c: 50726}, {f: 3, c: 50729}, 50735,
michael@0 8842 {f: 2, c: 50737}, 50742, 50744, 50746, {f: 4, c: 50748}, {f: 2, c: 50754},
michael@0 8843 {f: 3, c: 50757}, {f: 7, c: 50761}, 50770, {f: 6, c: 50774},
michael@0 8844 {f: 2, c: 50782}, {f: 11, c: 50785}, {f: 2, c: 50797}, 50800,
michael@0 8845 {f: 6, c: 50802}, {f: 2, c: 50810}, {f: 3, c: 50813}, {f: 7, c: 50817},
michael@0 8846 50826, 50828, {f: 6, c: 50830}, {f: 2, c: 50838}, {f: 3, c: 50841},
michael@0 8847 {f: 7, c: 50845}, 50854, 50856, {f: 6, c: 50858}, {f: 2, c: 50866},
michael@0 8848 {f: 3, c: 50869}, {f: 5, c: 50875}, 50882, 50884, {f: 6, c: 50886},
michael@0 8849 {f: 2, c: 50894}, {f: 3, c: 50897}, {f: 7, c: 50901}, {f: 2, c: 50910},
michael@0 8850 {f: 6, c: 50914}, {f: 2, c: 50922}, {f: 3, c: 50925}, {f: 7, c: 50929},
michael@0 8851 {f: 3, c: 50938}, {f: 6, c: 50942}, {f: 2, c: 50950}, {f: 3, c: 50953},
michael@0 8852 {f: 7, c: 50957}, 50966, 50968, {f: 6, c: 50970}, {f: 2, c: 50978},
michael@0 8853 {f: 3, c: 50981}, {f: 7, c: 50985}, 50994, 50996, 50998, {f: 4, c: 51000},
michael@0 8854 {f: 2, c: 51006}, {f: 3, c: 51009}, {f: 5, c: 51013}, 51019, 51022, 51024,
michael@0 8855 {f: 3, c: 51033}, {f: 3, c: 51037}, {f: 7, c: 51041}, {f: 2, c: 51049},
michael@0 8856 {f: 8, c: 51052}, {f: 2, c: 51062}, {f: 3, c: 51065}, {f: 4, c: 51071},
michael@0 8857 51078, {f: 3, c: 51083}, 51087, {f: 2, c: 51090}, 51093, 51097,
michael@0 8858 {f: 5, c: 51099}, 51106, {f: 5, c: 51111}, {f: 2, c: 51118},
michael@0 8859 {f: 3, c: 51121}, {f: 7, c: 51125}, 51134, {f: 6, c: 51138},
michael@0 8860 {f: 2, c: 51146}, 51149, 51151, {f: 7, c: 51153}, {f: 4, c: 51161},
michael@0 8861 {f: 6, c: 51166}, {f: 3, c: 51173}, {f: 3, c: 51177}, {f: 19, c: 51181},
michael@0 8862 {f: 2, c: 51202}, {f: 3, c: 51205}, 51209, {f: 5, c: 51211}, 51218, 51220,
michael@0 8863 {f: 5, c: 51223}, {f: 2, c: 51230}, {f: 3, c: 51233}, {f: 7, c: 51237},
michael@0 8864 51246, 51248, {f: 6, c: 51250}, {f: 3, c: 51257}, {f: 3, c: 51261},
michael@0 8865 {f: 7, c: 51265}, {f: 2, c: 51274}, {f: 6, c: 51278}, {f: 27, c: 51285},
michael@0 8866 {f: 2, c: 51314}, {f: 3, c: 51317}, 51321, {f: 5, c: 51323}, 51330, 51332,
michael@0 8867 {f: 3, c: 51336}, {f: 6, c: 51342}, {f: 8, c: 51349}, 51358, 51360,
michael@0 8868 {f: 6, c: 51362}, {f: 19, c: 51369}, {f: 6, c: 51390}, {f: 3, c: 51397},
michael@0 8869 {f: 3, c: 51401}, {f: 7, c: 51405}, 51414, 51416, {f: 6, c: 51418},
michael@0 8870 {f: 2, c: 51426}, {f: 16, c: 51429}, {f: 6, c: 51446}, {f: 2, c: 51454},
michael@0 8871 {f: 3, c: 51457}, {f: 5, c: 51463}, 51470, 51472, {f: 6, c: 51474},
michael@0 8872 {f: 19, c: 51481}, {f: 7, c: 51501}, {f: 27, c: 51509}, {f: 2, c: 51538},
michael@0 8873 {f: 3, c: 51541}, {f: 7, c: 51545}, 51554, {f: 8, c: 51556},
michael@0 8874 {f: 3, c: 51565}, {f: 3, c: 51569}, {f: 7, c: 51573}, {f: 11, c: 51581},
michael@0 8875 {f: 2, c: 51594}, {f: 3, c: 51597}, {f: 7, c: 51601}, 51610, 51612,
michael@0 8876 {f: 34, c: 51614}, {f: 2, c: 51650}, {f: 2, c: 51653}, 51657,
michael@0 8877 {f: 5, c: 51659}, 51666, 51668, {f: 2, c: 51671}, 51675, {f: 2, c: 51678},
michael@0 8878 51681, 51683, {f: 2, c: 51685}, {f: 4, c: 51688}, 51694, {f: 6, c: 51698},
michael@0 8879 {f: 2, c: 51706}, {f: 3, c: 51709}, {f: 7, c: 51713}, 51722,
michael@0 8880 {f: 6, c: 51726}, {f: 3, c: 51733}, {f: 16, c: 51737}, {f: 34, c: 51754},
michael@0 8881 {f: 2, c: 51790}, {f: 3, c: 51793}, {f: 7, c: 51797}, 51806,
michael@0 8882 {f: 6, c: 51810}, {f: 20, c: 51817}, {f: 6, c: 51838}, {f: 19, c: 51845},
michael@0 8883 {f: 35, c: 51865}, {f: 2, c: 51902}, {f: 3, c: 51905}, {f: 7, c: 51909},
michael@0 8884 51918, 51920, 51922, {f: 4, c: 51924}, {f: 6, c: 51930}, {f: 11, c: 51937},
michael@0 8885 {f: 7, c: 51949}, {f: 19, c: 51957}, {f: 7, c: 51977}, {f: 3, c: 51985},
michael@0 8886 {f: 3, c: 51989}, {f: 7, c: 51993}, {f: 31, c: 52002}, {f: 6, c: 52034},
michael@0 8887 {f: 2, c: 52042}, {f: 3, c: 52045}, {f: 7, c: 52049}, {f: 3, c: 52058},
michael@0 8888 {f: 6, c: 52062}, {f: 19, c: 52069}, {f: 34, c: 52090}, {f: 27, c: 52125},
michael@0 8889 {f: 27, c: 52153}, {f: 15, c: 52181}, {f: 2, c: 52197}, 52200,
michael@0 8890 {f: 34, c: 52202}, {f: 2, c: 52238}, {f: 3, c: 52241}, {f: 7, c: 52245},
michael@0 8891 {f: 3, c: 52254}, {f: 4, c: 52259}, {f: 2, c: 52266}, 52269, 52271,
michael@0 8892 {f: 7, c: 52273}, 52282, {f: 5, c: 52287}, {f: 2, c: 52294},
michael@0 8893 {f: 3, c: 52297}, {f: 7, c: 52301}, 52310, {f: 6, c: 52314},
michael@0 8894 {f: 3, c: 52321}, 52325, 52327, {f: 7, c: 52329}, {f: 4, c: 52337},
michael@0 8895 {f: 34, c: 52342}, {f: 2, c: 52378}, {f: 3, c: 52381}, {f: 7, c: 52385},
michael@0 8896 52394, {f: 6, c: 52398}, {f: 2, c: 52406}, {f: 3, c: 52409},
michael@0 8897 {f: 7, c: 52413}, 52422, 52424, {f: 6, c: 52426}, {f: 3, c: 52433},
michael@0 8898 {f: 15, c: 52437}, {f: 7, c: 52453}, {f: 3, c: 52461}, {f: 16, c: 52465},
michael@0 8899 {f: 6, c: 52482}, {f: 2, c: 52490}, {f: 3, c: 52493}, {f: 7, c: 52497},
michael@0 8900 52506, 52508, {f: 6, c: 52510}, {f: 3, c: 52517}, {f: 3, c: 52521},
michael@0 8901 {f: 12, c: 52525}, {f: 34, c: 52538}, {f: 3, c: 52573}, {f: 3, c: 52577},
michael@0 8902 {f: 7, c: 52581}, 52590, 52592, {f: 6, c: 52594}, {f: 15, c: 52601},
michael@0 8903 {f: 11, c: 52617}, {f: 2, c: 52630}, {f: 3, c: 52633}, {f: 7, c: 52637},
michael@0 8904 52646, 52648, {f: 6, c: 52650}, {f: 19, c: 52657}, {f: 7, c: 52677},
michael@0 8905 {f: 3, c: 52685}, {f: 23, c: 52689}, {f: 3, c: 52713}, {f: 3, c: 52717},
michael@0 8906 {f: 7, c: 52721}, 52730, 52732, {f: 6, c: 52734}, {f: 3, c: 52741},
michael@0 8907 {f: 3, c: 52745}, {f: 7, c: 52749}, {f: 4, c: 52757}, {f: 6, c: 52762},
michael@0 8908 {f: 2, c: 52770}, {f: 3, c: 52773}, {f: 7, c: 52777}, 52786, 52788,
michael@0 8909 {f: 34, c: 52790}, {f: 2, c: 52826}, {f: 2, c: 52829}, {f: 6, c: 52834},
michael@0 8910 52842, 52844, {f: 6, c: 52846}, {f: 2, c: 52854}, {f: 3, c: 52857},
michael@0 8911 {f: 7, c: 52861}, 52870, 52872, {f: 6, c: 52874}, {f: 2, c: 52882},
michael@0 8912 {f: 3, c: 52885}, {f: 7, c: 52889}, 52898, {f: 6, c: 52902},
michael@0 8913 {f: 19, c: 52910}, {f: 34, c: 52930}, {f: 2, c: 52966}, {f: 2, c: 52969},
michael@0 8914 {f: 7, c: 52973}, 52982, {f: 6, c: 52986}, {f: 2, c: 52994},
michael@0 8915 {f: 3, c: 52997}, {f: 7, c: 53001}, 53010, 53012, {f: 6, c: 53014},
michael@0 8916 {f: 3, c: 53021}, {f: 3, c: 53025}, {f: 7, c: 53029}, 53038,
michael@0 8917 {f: 6, c: 53042}, {f: 27, c: 53049}, {f: 2, c: 53078}, {f: 3, c: 53081},
michael@0 8918 {f: 7, c: 53085}, 53094, 53096, {f: 6, c: 53098}, {f: 2, c: 53106},
michael@0 8919 {f: 3, c: 53109}, {f: 7, c: 53113}, {f: 4, c: 53121}, {f: 6, c: 53126},
michael@0 8920 {f: 20, c: 53133}, {f: 6, c: 53154}, {f: 7, c: 53161}, {f: 19, c: 53169},
michael@0 8921 {f: 27, c: 53189}, {f: 2, c: 53218}, {f: 3, c: 53221}, {f: 7, c: 53225},
michael@0 8922 53234, 53236, {f: 6, c: 53238}, {f: 3, c: 53245}, {f: 3, c: 53249},
michael@0 8923 {f: 12, c: 53253}, {f: 6, c: 53266}, {f: 20, c: 53273}, {f: 6, c: 53294},
michael@0 8924 {f: 2, c: 53302}, {f: 3, c: 53305}, {f: 7, c: 53309}, 53318, 53320,
michael@0 8925 {f: 6, c: 53322}, {f: 3, c: 53329}, {f: 3, c: 53333}, {f: 7, c: 53337},
michael@0 8926 {f: 11, c: 53345}, {f: 2, c: 53358}, {f: 3, c: 53361}, {f: 7, c: 53365},
michael@0 8927 {f: 3, c: 53374}, {f: 34, c: 53378}, {f: 2, c: 53414}, {f: 3, c: 53417},
michael@0 8928 {f: 7, c: 53421}, 53430, 53432, {f: 6, c: 53434}, {f: 2, c: 53442},
michael@0 8929 {f: 3, c: 53445}, {f: 6, c: 53450}, 53458, {f: 6, c: 53462},
michael@0 8930 {f: 2, c: 53470}, {f: 3, c: 53473}, {f: 7, c: 53477}, 53486,
michael@0 8931 {f: 6, c: 53490}, {f: 20, c: 53497}, {f: 34, c: 53518}, {f: 2, c: 53554},
michael@0 8932 {f: 3, c: 53557}, 53561, {f: 5, c: 53563}, 53570, {f: 6, c: 53574},
michael@0 8933 {f: 2, c: 53582}, {f: 3, c: 53585}, {f: 7, c: 53589}, 53598, 53600,
michael@0 8934 {f: 6, c: 53602}, {f: 3, c: 53609}, {f: 15, c: 53613}, {f: 7, c: 53629},
michael@0 8935 {f: 3, c: 53637}, {f: 23, c: 53641}, {f: 2, c: 53666}, {f: 3, c: 53669},
michael@0 8936 {f: 7, c: 53673}, 53682, 53684, {f: 4, c: 53686}, 53691, {f: 3, c: 53693},
michael@0 8937 {f: 23, c: 53697}, {f: 27, c: 53721}, {f: 3, c: 53749}, {f: 14, c: 53753},
michael@0 8938 53768, {f: 6, c: 53770}, {f: 27, c: 53777}, {f: 2, c: 53806},
michael@0 8939 {f: 3, c: 53809}, {f: 7, c: 53813}, 53822, 53824, {f: 6, c: 53826},
michael@0 8940 {f: 19, c: 53833}, {f: 7, c: 53853}, {f: 27, c: 53861}, {f: 2, c: 53890},
michael@0 8941 {f: 3, c: 53893}, {f: 7, c: 53897}, {f: 3, c: 53906}, {f: 6, c: 53910},
michael@0 8942 {f: 3, c: 53917}, {f: 3, c: 53921}, {f: 7, c: 53925}, {f: 4, c: 53933},
michael@0 8943 {f: 6, c: 53938}, {f: 2, c: 53946}, {f: 2, c: 53949}, 53953,
michael@0 8944 {f: 5, c: 53955}, 53962, {f: 8, c: 53964}, {f: 3, c: 53973},
michael@0 8945 {f: 3, c: 53977}, {f: 7, c: 53981}, {f: 10, c: 53990}, {f: 2, c: 54002},
michael@0 8946 {f: 3, c: 54005}, {f: 7, c: 54009}, 54018, 54020, {f: 6, c: 54022}, 54031,
michael@0 8947 {f: 3, c: 54033}, 54037, {f: 5, c: 54039}, 54046, {f: 3, c: 54050},
michael@0 8948 {f: 2, c: 54054}, {f: 2, c: 54058}, {f: 3, c: 54061}, {f: 7, c: 54065},
michael@0 8949 54074, {f: 6, c: 54078}, {f: 54, c: 54086}, {f: 2, c: 54142},
michael@0 8950 {f: 3, c: 54145}, {f: 7, c: 54149}, 54158, {f: 6, c: 54162},
michael@0 8951 {f: 2, c: 54170}, {f: 3, c: 54173}, {f: 7, c: 54177}, 54186, 54188,
michael@0 8952 {f: 6, c: 54190}, {f: 3, c: 54197}, {f: 3, c: 54201}, {f: 7, c: 54205},
michael@0 8953 {f: 2, c: 54214}, {f: 6, c: 54218}, {f: 7, c: 54225}, {f: 8, c: 54233},
michael@0 8954 54242, {f: 8, c: 54244}, {f: 2, c: 54254}, {f: 3, c: 54257},
michael@0 8955 {f: 7, c: 54261}, 54270, 54272, {f: 6, c: 54274}, {f: 20, c: 54281},
michael@0 8956 {f: 34, c: 54302}, {f: 3, c: 54337}, {f: 23, c: 54341}, {f: 3, c: 54365},
michael@0 8957 {f: 3, c: 54369}, {f: 8, c: 54373}, 54382, {f: 8, c: 54384},
michael@0 8958 {f: 2, c: 54394}, {f: 2, c: 54397}, 54401, {f: 5, c: 54403}, 54410, 54412,
michael@0 8959 {f: 6, c: 54414}, {f: 20, c: 54421}, {f: 34, c: 54442}, {f: 3, c: 54477},
michael@0 8960 {f: 3, c: 54481}, {f: 7, c: 54485}, {f: 2, c: 54493}, {f: 8, c: 54496},
michael@0 8961 {f: 3, c: 54505}, {f: 3, c: 54509}, {f: 7, c: 54513}, {f: 2, c: 54521},
michael@0 8962 54524, {f: 6, c: 54526}, {f: 3, c: 54533}, {f: 3, c: 54537},
michael@0 8963 {f: 7, c: 54541}, 54550, {f: 36, c: 54552}, {f: 2, c: 54590},
michael@0 8964 {f: 3, c: 54593}, {f: 7, c: 54597}, 54606, 54608, {f: 6, c: 54610},
michael@0 8965 {f: 2, c: 54618}, {f: 3, c: 54621}, {f: 4, c: 54625}, {f: 2, c: 54630},
michael@0 8966 54634, 54636, {f: 6, c: 54638}, {f: 2, c: 54646}, {f: 3, c: 54649},
michael@0 8967 {f: 7, c: 54653}, 54662, {f: 6, c: 54666}, {f: 20, c: 54673},
michael@0 8968 {f: 34, c: 54694}, {f: 2, c: 54730}, {f: 3, c: 54733}, 54737,
michael@0 8969 {f: 5, c: 54739}, 54746, 54748, {f: 6, c: 54750}, {f: 2, c: 54758},
michael@0 8970 {f: 3, c: 54761}, {f: 7, c: 54765}, 54774, 54776, {f: 6, c: 54778},
michael@0 8971 {f: 2, c: 54786}, {f: 3, c: 54789}, {f: 7, c: 54793}, 54802,
michael@0 8972 {f: 6, c: 54806}, {f: 3, c: 54813}, {f: 3, c: 54817}, {f: 8, c: 54821},
michael@0 8973 {f: 10, c: 54830}, {f: 2, c: 54842}, {f: 3, c: 54845}, {f: 4, c: 54849},
michael@0 8974 {f: 2, c: 54854}, 54858, 54860, {f: 3, c: 54862}, {f: 2, c: 54866},
michael@0 8975 {f: 2, c: 54870}, {f: 3, c: 54873}, {f: 10, c: 54877}, 54888,
michael@0 8976 {f: 6, c: 54890}, {f: 2, c: 54898}, {f: 14, c: 54901}, 54916,
michael@0 8977 {f: 6, c: 54918}, {f: 2, c: 54926}, {f: 3, c: 54929}, {f: 8, c: 54933},
michael@0 8978 54942, 54944, {f: 6, c: 54946}, {f: 3, c: 54953}, {f: 3, c: 54957},
michael@0 8979 {f: 8, c: 54961}, 54970, {f: 8, c: 54972}, {f: 2, c: 54982},
michael@0 8980 {f: 3, c: 54985}, {f: 4, c: 54989}, {f: 2, c: 54994}, {f: 2, c: 54997},
michael@0 8981 55000, {f: 6, c: 55002}, {f: 3, c: 55009}, {f: 3, c: 55013},
michael@0 8982 {f: 7, c: 55017}, {f: 4, c: 55025}, {f: 6, c: 55030}, {f: 2, c: 55038},
michael@0 8983 {f: 3, c: 55041}, {f: 12, c: 55045}, {f: 6, c: 55058}, {f: 2, c: 55066},
michael@0 8984 {f: 3, c: 55069}, {f: 7, c: 55073}, 55082, 55084, {f: 6, c: 55086},
michael@0 8985 {f: 2, c: 55094}, {f: 3, c: 55097}, {f: 7, c: 55101}, {f: 2, c: 55109},
michael@0 8986 55112, {f: 6, c: 55114}, {f: 2, c: 55122}, 55125, {f: 6, c: 55130}, 55138,
michael@0 8987 55140, {f: 3, c: 55142}, {f: 2, c: 55146}, {f: 3, c: 55149},
michael@0 8988 {f: 3, c: 55153}, {f: 7, c: 55157}, {f: 3, c: 55166}, {f: 6, c: 55170},
michael@0 8989 {f: 2, c: 55178}, {f: 3, c: 55181}, {f: 7, c: 55185}, 55194, 55196,
michael@0 8990 {f: 6, c: 55198}],
michael@0 8991 'Adobe-CNS1': [{f: 95, c: 32}, {s: 3}, 12288, 65292, {f: 2, c: 12289}, 65294,
michael@0 8992 8226, 65307, 65306, 65311, 65281, 65072, 8230, 8229, 65104, 65380, 65106,
michael@0 8993 183, {f: 4, c: 65108}, 65372, 8211, 65073, 8212, {s: 4}, {f: 2, c: 65288},
michael@0 8994 {f: 2, c: 65077}, 65371, 65373, {f: 2, c: 65079}, {f: 2, c: 12308},
michael@0 8995 {f: 2, c: 65081}, {f: 2, c: 12304}, {f: 2, c: 65083}, {f: 2, c: 12298},
michael@0 8996 {f: 2, c: 65085}, {f: 2, c: 12296}, {f: 2, c: 65087}, {f: 2, c: 12300},
michael@0 8997 {f: 2, c: 65089}, {f: 2, c: 12302}, {f: 2, c: 65091}, {f: 6, c: 65113},
michael@0 8998 {f: 2, c: 8216}, {f: 2, c: 8220}, {f: 2, c: 12317}, 8245, 8242, 65283,
michael@0 8999 65286, 65290, 8251, 167, 12291, 9675, 9679, 9651, 9650, 9678, 9734, 9733,
michael@0 9000 9671, 9670, 9633, 9632, 9661, 9660, 12963, 8453, 8254, 0, 65343, 0,
michael@0 9001 {f: 2, c: 65097}, {f: 2, c: 65101}, {f: 2, c: 65099}, {f: 3, c: 65119},
michael@0 9002 65291, 65293, 215, 247, 177, 8730, 65308, 65310, 65309, {f: 2, c: 8806},
michael@0 9003 8800, 8734, 8786, 8801, {f: 5, c: 65122}, 8764, {f: 2, c: 8745}, 8869,
michael@0 9004 8736, 8735, 8895, 13266, 13265, 8747, 8750, 8757, 8756, 9792, 9794, 9793,
michael@0 9005 9737, 8593, 8595, 8594, 8592, {f: 2, c: 8598}, 8601, 8600, 8741, 8739, 0,
michael@0 9006 0, 65295, 65340, 65284, 165, 12306, {f: 2, c: 162}, 65285, 65312, 8451,
michael@0 9007 8457, {f: 3, c: 65129}, 13269, {f: 3, c: 13212}, 13262, 13217,
michael@0 9008 {f: 2, c: 13198}, 13252, 176, [20825, 58834], [20827, 58835],
michael@0 9009 [20830, 58837], [20829, 58836], 20833, 20835, 21991, [29929, 58044],
michael@0 9010 [31950, 58191], {f: 8, c: 9601}, 9615, 9614, 9613, 9612, 9611, 9610, 9609,
michael@0 9011 9532, 9524, 9516, 9508, 9500, 9620, 9472, 9474, 9621, 9484, 9488, 9492,
michael@0 9012 9496, {f: 2, c: 9581}, 9584, 9583, 9552, 9566, 9578, 9569, {f: 2, c: 9698},
michael@0 9013 9701, 9700, {f: 3, c: 9585}, {f: 10, c: 65296}, {f: 10, c: 8544},
michael@0 9014 {f: 9, c: 12321}, 0, [21316, 57443], 0, {f: 26, c: 65313},
michael@0 9015 {f: 26, c: 65345}, {f: 17, c: 913}, {f: 7, c: 931}, {f: 17, c: 945},
michael@0 9016 {f: 7, c: 963}, {f: 37, c: 12549}, 729, 714, 711, 715, [9312, 63153],
michael@0 9017 [9313, 63154], [9314, 63155], [9315, 63156], [9316, 63157], [9317, 63158],
michael@0 9018 [9318, 63159], [9319, 63160], [9320, 63161], [9321, 63162], [9332, 63163],
michael@0 9019 [9333, 63164], [9334, 63165], [9335, 63166], [9336, 63167], [9337, 63168],
michael@0 9020 [9338, 63169], [9339, 63170], [9340, 63171], [9341, 63172], [8560, 63173],
michael@0 9021 [8561, 63174], [8562, 63175], [8563, 63176], [8564, 63177], [8565, 63178],
michael@0 9022 [8566, 63179], [8567, 63180], [8568, 63181], [8569, 63182], [12033, 20008],
michael@0 9023 [12034, 20022, 63183], [12035, 20031, 63184], [12037, 20101, 63185],
michael@0 9024 [12039, 20128, 63186], [12044, 20866, 63187], [12045, 20886, 63188],
michael@0 9025 [12046, 20907, 63189], [12051, 21241, 63190], [12054, 21304, 63191],
michael@0 9026 [12057, 21353, 63192], [12059, 21430, 63193],
michael@0 9027 [12065, 12066, 22786, 22794, 63194], [12071, 23424, 63195],
michael@0 9028 [12078, 24027, 63196], [12083, 24186, 63197], [12084, 24191, 63198],
michael@0 9029 [12085, 24308], [12089, 24400, 63200], [12090, 24417, 63201],
michael@0 9030 [12097, 25908, 63202], [12102, 26080], [12135, 30098, 63204],
michael@0 9031 [12136, 30326], [12193, 36789, 63206], [12202, 38582], {f: 32, c: 9216},
michael@0 9032 9249, [12032, 19968], [12036, 20057], 19969, 19971, 20035, 20061, 20102,
michael@0 9033 [12038, 20108], [12040, 20154], [12041, 20799], [12042, 20837],
michael@0 9034 [12043, 20843], [12047, 20960], [12049, 20992], 20993, [12050, 21147],
michael@0 9035 [12052, 21269], [12055, 21313], [12056, 21340], [12060, 21448], 19977,
michael@0 9036 19979, 19976, 19978, 20011, 20024, 20961, 20037, 20040, 20063, 20062,
michael@0 9037 20110, 20129, [20800, 64012], 20995, 21242, 21315, 21449, [12061, 21475],
michael@0 9038 [12063, 22303], [12064, 22763], [12067, 22805], [12068, 22823],
michael@0 9039 [12069, 22899], [12070, 23376], 23377, 23379, [12072, 23544],
michael@0 9040 [12073, 23567], [12074, 23586], [12075, 23608], [12077, 23665], 24029,
michael@0 9041 [12079, 24037], [12080, 24049], {f: 2, c: 24050}, [12081, 24062],
michael@0 9042 [12082, 24178], [12086, 24318], [12087, 24331], [12088, 24339], 25165,
michael@0 9043 19985, 19984, 19981, 20013, 20016, 20025, 20043, 23609, 20104, 20113,
michael@0 9044 20117, 20114, 20116, 20130, 20161, 20160, 20163, {f: 2, c: 20166}, 20173,
michael@0 9045 {f: 2, c: 20170}, 20164, 20803, 20801, 20839, {f: 2, c: 20845}, 20844,
michael@0 9046 20887, 20982, {f: 3, c: 20998}, 21243, {f: 2, c: 21246}, 21270, 21305,
michael@0 9047 21320, 21319, 21317, 21342, 21380, 21451, 21450, 21453, 22764, 22825,
michael@0 9048 22827, 22826, 22829, 23380, 23569, 23588, 23610, 23663, 24052, 24187,
michael@0 9049 24319, {f: 2, c: 24340}, [12092, 24515], [12093, 25096], [12094, 25142],
michael@0 9050 [12095, 25163], 25166, [12096, 25903], [12098, 25991], [12099, 26007],
michael@0 9051 [12100, 26020], [12101, 26041], [12103, 26085], [12104, 26352],
michael@0 9052 [12105, 26376], [12106, 26408], [12107, 27424], [12108, 27490],
michael@0 9053 [12109, 27513], [12111, 27595], [12112, 27604], [12113, 27611],
michael@0 9054 [12114, 27663], [12116, 27700], [12117, 28779], [12118, 29226],
michael@0 9055 [12119, 29238], [12120, 29243], [12122, 29255], [12123, 29273],
michael@0 9056 [12124, 29275], [12125, 29356], 29579, 19993, 19990, 19989, 19988, 19992,
michael@0 9057 20027, 20045, 20047, 20046, 20197, 20184, {f: 4, c: 20180},
michael@0 9058 {f: 2, c: 20195}, 20185, 20190, 20805, 20804, {f: 2, c: 20873}, 20908,
michael@0 9059 {f: 2, c: 20985}, 20984, 21002, 21152, 21151, [21253, 57435], 21254, 21271,
michael@0 9060 21277, 20191, 21322, 21321, 21345, 21344, 21359, 21358, 21435, 21487,
michael@0 9061 21476, 21491, 21484, 21486, 21481, 21480, 21500, 21496, 21493, 21483,
michael@0 9062 21478, 21482, 21490, 21489, 21488, 21477, 21485, 21499, 22235, 22234,
michael@0 9063 22806, 22830, 22833, 22900, 22902, 23381, 23427, 23612, 24040, 24039,
michael@0 9064 24038, {f: 2, c: 24066}, 24179, 24188, 24321, 24344, 24343, 24517, 25098,
michael@0 9065 {f: 2, c: 25171}, 25170, 25169, 26021, 26086, 26414, 26412,
michael@0 9066 {f: 2, c: 26410}, 26413, 27491, 27597, 27665, 27664, 27704, 27713, 27712,
michael@0 9067 27710, 29359, [12126, 29572], [12127, 29577], [12128, 29916],
michael@0 9068 [12129, 29926], [12130, 29976], [12131, 29983], [12132, 29992], 29993,
michael@0 9069 [12133, 30000], {f: 3, c: 30001}, [12134, 30091], [12137, 30333],
michael@0 9070 [12138, 30382], [12139, 30399], [12140, 30446], [12141, 30683],
michael@0 9071 [12142, 30690], [12143, 30707], [12144, 31034], [12146, 31166],
michael@0 9072 [12147, 31348], [12148, 31435], {f: 2, c: 19998}, {f: 2, c: 20050}, 20073,
michael@0 9073 20121, 20132, 20134, 20133, 20223, 20233, 20249, 20234, 20245, 20237,
michael@0 9074 {f: 2, c: 20240}, 20239, 20210, 20214, 20219, 20208, 20211, 20221, 20225,
michael@0 9075 20235, 20809, 20807, 20806, 20808, 20840, 20849, 20877, 20912, 21015,
michael@0 9076 {f: 2, c: 21009}, 21006, 21014, 21155, 21256, 21281, 21280,
michael@0 9077 {f: 2, c: 21360}, 21513, 21519, 21516, 21514, 21520, 21505, 21515, 21508,
michael@0 9078 21521, 21517, 21512, 21507, 21518, 21510, 21522, 22240, 22238, 22237,
michael@0 9079 22323, 22320, 22312, 22317, 22316, 22319, 22313, {f: 2, c: 22809},
michael@0 9080 {f: 2, c: 22839}, 22916, 22904, 22915, 22909, 22905, 22914, 22913,
michael@0 9081 {f: 2, c: 23383}, {f: 2, c: 23431}, 23429, 23433, 23546, 23574, 23673,
michael@0 9082 24030, 24070, 24182, 24180, 24335, 24347, 24537, 24534, 25102,
michael@0 9083 {f: 2, c: 25100}, 25104, 25187, 25179, 25176, 25910, 26089, 26088,
michael@0 9084 {f: 2, c: 26092}, {f: 2, c: 26354}, 26377, 26429, 26420, 26417, 26421,
michael@0 9085 27425, 27492, 27515, 27670, 27741, 27735, 27737, {f: 2, c: 27743}, 27728,
michael@0 9086 27733, 27745, 27739, {f: 2, c: 27725}, 28784, 29279, 29277, 30334,
michael@0 9087 [12149, 31481], [12150, 31859], [12151, 31992], [12152, 32566],
michael@0 9088 [12154, 32650], [12155, 32701], [12156, 32769], 32771, [12157, 32780],
michael@0 9089 [12158, 32786], [12159, 32819], [12160, 32895], [12161, 32905],
michael@0 9090 {f: 2, c: 32907}, [12162, 33251], [12163, 33258], [12164, 33267],
michael@0 9091 [12165, 33276], [12166, 33292], [12167, 33307], [12168, 33311],
michael@0 9092 [12169, 33390], [12170, 33394], 33406, [12173, 34411], [12174, 34880],
michael@0 9093 [12175, 34892], [12176, 34915], 35199, 38433, 20018, 20136, 20301, 20303,
michael@0 9094 20295, 20311, 20318, 20276, 20315, 20309, 20272, {f: 2, c: 20304}, 20285,
michael@0 9095 20282, 20280, 20291, 20308, 20284, 20294, 20323, 20316, 20320, 20271,
michael@0 9096 20302, 20278, 20313, 20317, 20296, 20314, 20812, 20811, 20813, 20853,
michael@0 9097 {f: 2, c: 20918}, 21029, 21028, {f: 2, c: 21033}, 21032, 21163,
michael@0 9098 {f: 2, c: 21161}, 21164, 21283, 21363, 21365, 21533, 21549, 21534, 21566,
michael@0 9099 21542, 21582, 21543, 21574, 21571, 21555, 21576, 21570, 21531, 21545,
michael@0 9100 21578, 21561, 21563, 21560, 21550, {f: 2, c: 21557}, 21536, 21564, 21568,
michael@0 9101 21553, 21547, 21535, 21548, 22250, 22256, 22244, 22251, 22346, 22353,
michael@0 9102 22336, 22349, 22343, 22350, 22334, 22352, 22351, 22331, 22767, 22846,
michael@0 9103 22941, 22930, 22952, 22942, 22947, 22937, 22934, 22925, 22948, 22931,
michael@0 9104 22922, 22949, 23389, 23388, {f: 2, c: 23386}, 23436, 23435, 23439, 23596,
michael@0 9105 {f: 2, c: 23616}, 23615, 23614, {f: 2, c: 23696}, 23700, 23692, 24043,
michael@0 9106 24076, 24207, 24199, 24202, 24311, 24324, 24351, 24420, 24418, 24439,
michael@0 9107 24441, 24536, 24524, 24535, 24525, 24561, 24555, 24568, 24554, 25106,
michael@0 9108 25105, 25220, 25239, 25238, 25216, 25206, 25225, 25197, 25226, 25212,
michael@0 9109 25214, 25209, 25203, 25234, 25199, 25240, 25198, 25237, 25235, 25233,
michael@0 9110 25222, 25913, 25915, 25912, 26097, 26356, 26463, {f: 4, c: 26446}, 26460,
michael@0 9111 26454, [26462, 57801], 26441, 26438, 26464, 26451, 26455, 27493, 27599,
michael@0 9112 27714, 27742, 27801, 27777, {f: 2, c: 27784}, 27781, 27803, 27754, 27770,
michael@0 9113 27792, 27760, 27788, 27752, 27798, 27794, 27773, 27779, 27762, 27774,
michael@0 9114 27764, 27782, 27766, 27789, 27796, 27800, 27778, 28790, {f: 2, c: 28796},
michael@0 9115 28792, 29282, 29281, 29280, 29380, 29378, 29590, 29996, 29995,
michael@0 9116 {f: 2, c: 30007}, 30338, 30447, 30691, 31169, 31168, 31167, 31350, 31995,
michael@0 9117 32597, 32918, 32915, 32925, 32920, 32923, 32922, 32946, 33391, 33426,
michael@0 9118 33419, 33421, [12178, 35211], [12179, 35282], [12180, 35328],
michael@0 9119 [12181, 35895], [12182, 35910], [12183, 35925], [12185, 35997],
michael@0 9120 [12186, 36196], [12187, 36208], [12188, 36275], [12189, 36523],
michael@0 9121 [12190, 36554], [12191, 36763], [12192, 36784], 36802, 36806, 36805, 36804,
michael@0 9122 24033, [12194, 37009], 37026, 37034, 37030, 37027, [12195, 37193],
michael@0 9123 [12196, 37318], [12197, 37324], 38450, 38446, 38449, 38442, 38444, 20006,
michael@0 9124 20054, 20083, 20107, 20123, 20126, {f: 2, c: 20139}, 20335, 20381, 20365,
michael@0 9125 20339, 20351, 20332, 20379, 20363, 20358, 20355, 20336, 20341, 20360,
michael@0 9126 20329, 20347, 20374, 20350, 20367, 20369, 20346, 20820, 20818, 20821,
michael@0 9127 20841, 20855, 20854, 20856, 20925, 20989, 21051, 21048, 21047, 21050,
michael@0 9128 21040, 21038, 21046, 21057, 21182, 21179, 21330, 21332, 21331, 21329,
michael@0 9129 21350, {f: 3, c: 21367}, 21462, 21460, 21463, 21619, 21621, 21654, 21624,
michael@0 9130 21653, 21632, 21627, 21623, 21636, 21650, 21638, 21628, 21648, 21617,
michael@0 9131 21622, 21644, 21658, 21602, 21608, 21643, 21629, 21646, 22266, 22403,
michael@0 9132 22391, 22378, 22377, 22369, 22374, 22372, 22396, 22812, 22857,
michael@0 9133 {f: 2, c: 22855}, 22852, 22868, 22974, 22971, 22996, 22969, 22958, 22993,
michael@0 9134 22982, 22992, 22989, 22987, 22995, 22986, 22959, 22963, 22994, 22981,
michael@0 9135 23391, 23396, 23395, 23447, 23450, 23448, 23452, 23449, 23451, 23578,
michael@0 9136 23624, {f: 2, c: 23621}, 23735, 23713, 23736, 23721, 23723, 23729, 23731,
michael@0 9137 24088, 24090, 24086, 24085, 24091, 24081, 24184, 24218, 24215, 24220,
michael@0 9138 {f: 2, c: 24213}, 24310, {f: 2, c: 24358}, 24361, {f: 2, c: 24448}, 24447,
michael@0 9139 24444, 24541, 24544, 24573, 24565, 24575, 24591, 24596, 24623, 24629,
michael@0 9140 24598, 24618, 24597, 24609, 24615, 24617, 24619, 24603, 25110, 25109,
michael@0 9141 25151, 25150, 25152, 25215, 25289, 25292, 25284, 25279, 25282, 25273,
michael@0 9142 25298, 25307, 25259, {f: 2, c: 25299}, 25291, 25288, 25256, 25277, 25276,
michael@0 9143 [25296, 60582], 25305, 25287, 25293, 25269, 25306, 25265, 25304,
michael@0 9144 {f: 2, c: 25302}, 25286, 25260, [25294, 61010], 25918, 26023, 26044, 26106,
michael@0 9145 26132, 26131, 26124, 26118, 26114, 26126, 26112, 26127, 26133, 26122,
michael@0 9146 26119, 26381, 26379, 26477, 26507, 26517, 26481, 26524, 26483, 26487,
michael@0 9147 26503, 26525, 26519, {f: 2, c: 26479}, 26495, 26505, 26494, 26512, 26485,
michael@0 9148 26522, 26515, 26492, 26474, 26482, 27427, {f: 2, c: 27494}, 27519, 27667,
michael@0 9149 27675, 27875, 27880, 27891, 27825, 27852, 27877, 27827, {f: 2, c: 27837},
michael@0 9150 27836, 27874, 27819, 27861, 27859, 27832, 27844, 27833, 27841, 27822,
michael@0 9151 27863, 27845, 27889, 27839, 27835, 27873, 27867, 27850, 27820, 27887,
michael@0 9152 27868, 27862, 27872, 28821, 28814, 28818, 28810, 28825, {f: 2, c: 29228},
michael@0 9153 29240, 29256, 29287, 29289, 29376, 29390, 29401, 29399, 29392, 29609,
michael@0 9154 29608, 29599, 29611, 29605, 30013, 30109, {f: 2, c: 30105}, 30340, 30402,
michael@0 9155 30450, 30452, 30693, 30717, 31038, {f: 2, c: 31040}, 31177, 31176, 31354,
michael@0 9156 31353, 31482, 31998, 32596, 32652, 32651, [32773, 58236], 32954, 32933,
michael@0 9157 32930, 32945, 32929, 32939, 32937, 32948, 32938, 32943, 33253, 33278,
michael@0 9158 33293, 33459, 33437, 33433, 33453, 33469, 33439, 33465, 33457, 33452,
michael@0 9159 33445, 33455, 33464, 33443, 33456, 33470, 33463, 34382, 34417, 21021,
michael@0 9160 34920, 36555, 36814, 36820, 36817, 37045, 37048, 37041, 37046, 37319,
michael@0 9161 [12198, 37329], [12199, 38263], [12200, 38272], [12201, 38428], 38464,
michael@0 9162 38463, 38459, 38468, 38466, [12203, 38585], [12204, 38632], 38738,
michael@0 9163 [12206, 38750], 20127, {f: 2, c: 20141}, 20449, 20405, 20399, 20415, 20448,
michael@0 9164 20433, 20431, 20445, 20419, 20406, 20440, 20447, 20426, 20439, 20398,
michael@0 9165 20432, 20420, 20418, 20442, 20430, 20446, 20407, 20823, 20882, 20881,
michael@0 9166 20896, 21070, 21059, 21066, 21069, 21068, 21067, 21063, 21191, 21193,
michael@0 9167 21187, 21185, 21261, 21335, 21371, 21402, 21467, 21676, 21696, 21672,
michael@0 9168 21710, 21705, 21688, 21670, 21683, 21703, 21698, 21693, 21674, 21697,
michael@0 9169 21700, 21704, 21679, 21675, 21681, 21691, 21673, 21671, 21695, 22271,
michael@0 9170 22402, 22411, 22432, 22435, 22434, 22478, 22446, 22419, 22869, 22865,
michael@0 9171 22863, 22862, 22864, 23004, 23000, 23039, 23011, 23016, 23043, 23013,
michael@0 9172 23018, 23002, 23014, 23041, 23035, 23401, 23459, 23462, 23460, 23458,
michael@0 9173 23461, 23553, {f: 2, c: 23630}, 23629, 23627, 23769, 23762, 24055, 24093,
michael@0 9174 24101, 24095, 24189, 24224, 24230, 24314, 24328, 24365, 24421, 24456,
michael@0 9175 24453, {f: 2, c: 24458}, 24455, 24460, 24457, 24594, 24605, 24608, 24613,
michael@0 9176 24590, 24616, 24653, 24688, 24680, [24674, 60712], 24646, 24643, 24684,
michael@0 9177 24683, 24682, 24676, 25153, 25308, 25366, 25353, 25340, 25325, 25345,
michael@0 9178 25326, 25341, 25351, 25329, 25335, 25327, 25324, 25342, 25332, 25361,
michael@0 9179 25346, 25919, 25925, 26027, 26045, 26082, 26149, 26157, 26144, 26151,
michael@0 9180 26159, 26143, 26152, 26161, 26148, 26359, 26623, 26579, 26609, 26580,
michael@0 9181 26576, 26604, 26550, 26543, 26613, 26601, 26607, 26564, 26577, 26548,
michael@0 9182 26586, 26597, 26552, 26575, 26590, 26611, 26544, 26585, 26594, 26589,
michael@0 9183 26578, 27498, 27523, 27526, 27573, 27602, 27607, 27679, 27849, 27915,
michael@0 9184 27954, 27946, 27969, 27941, 27916, 27953, 27934, 27927, 27963,
michael@0 9185 {f: 2, c: 27965}, 27958, 27931, 27893, 27961, 27943, 27960, 27945, 27950,
michael@0 9186 27957, 27918, 27947, 28843, 28858, 28851, 28844, 28847, 28845, 28856,
michael@0 9187 28846, 28836, 29232, 29298, 29295, 29300, 29417, {f: 2, c: 29408}, 29623,
michael@0 9188 29642, 29627, 29618, 29645, 29632, 29619, 29978, 29997, 30031, 30028,
michael@0 9189 30030, 30027, 30123, {f: 2, c: 30116}, {f: 2, c: 30114}, 30328,
michael@0 9190 {f: 3, c: 30342}, 30408, 30406, 30403, 30405, 30465, 30457, 30456, 30473,
michael@0 9191 30475, 30462, 30460, 30471, 30684, 30722, 30740, {f: 2, c: 30732}, 31046,
michael@0 9192 31049, 31048, 31047, {f: 2, c: 31161}, {f: 2, c: 31185}, 31179, 31359,
michael@0 9193 31361, 31487, 31485, 31869, 32002, 32005, 32000, 32009, 32007, 32004,
michael@0 9194 32006, 32568, 32654, 32703, 32784, 32781, 32785, 32822, 32982, 32997,
michael@0 9195 32986, {f: 2, c: 32963}, 32972, 32993, 32987, 32974, 32990, 32996, 32989,
michael@0 9196 33268, 33314, 33511, 33539, 33541, 33507, 33499, 33510, 33540, 33509,
michael@0 9197 33538, 33545, 33490, 33495, 33521, 33537, 33500, 33492, 33489, 33502,
michael@0 9198 33491, 33503, 33519, 33542, 34384, 34425, 34427, 34426, 34893, 34923,
michael@0 9199 35201, 35284, 35336, {f: 2, c: 35330}, 35998, 36000, 36212, 36211, 36276,
michael@0 9200 36557, 36556, 36848, 36838, 36834, 36842, 36837, 36845, 36843, 36836,
michael@0 9201 36840, 37066, 37070, 37057, 37059, 37195, 37194, 37325, 38274, 38480,
michael@0 9202 {f: 3, c: 38475}, [12207, 38754], [12208, 38761], [12209, 38859],
michael@0 9203 [12210, 38893], [12211, 38899], [12212, 38913], [12213, 39080],
michael@0 9204 [12214, 39131], [12215, 39135], [12216, 39318], [12217, 39321], 20056,
michael@0 9205 20147, {f: 2, c: 20492}, 20515, 20463, 20518, 20517, 20472, [20521, 57375],
michael@0 9206 20502, 20486, 20540, 20511, 20506, 20498, 20497, 20474, 20480, 20500,
michael@0 9207 20520, 20465, 20513, 20491, 20505, 20504, 20467, 20462, 20525, 20522,
michael@0 9208 20478, 20523, 20489, 20860, {f: 2, c: 20900}, 20898, 20941, 20940, 20934,
michael@0 9209 20939, 21078, 21084, 21076, 21083, 21085, 21290, [21375, 57459], 21407,
michael@0 9210 21405, 21471, 21736, 21776, 21761, 21815, 21756, 21733, 21746, 21766,
michael@0 9211 21754, 21780, 21737, 21741, 21729, 21769, 21742, 21738, 21734, 21799,
michael@0 9212 21767, 21757, 21775, {f: 2, c: 22275}, 22466, 22484, 22475, 22467, 22537,
michael@0 9213 22799, {f: 2, c: 22871}, 22874, 23057, 23064, 23068, 23071, 23067, 23059,
michael@0 9214 23020, 23072, 23075, 23081, 23077, 23052, 23049, 23403, 23640, 23472,
michael@0 9215 23475, 23478, 23476, 23470, 23477, 23481, 23480, 23556, 23633, 23637,
michael@0 9216 23632, 23789, 23805, 23803, 23786, 23784, 23792, 23798, 23809, 23796,
michael@0 9217 24046, 24109, 24107, 24235, 24237, 24231, 24369, 24466, 24465, 24464,
michael@0 9218 24665, 24675, 24677, 24656, 24661, 24685, 24681, 24687, 24708, 24735,
michael@0 9219 24730, 24717, 24724, 24716, 24709, 24726, 25159, 25331, 25352, 25343,
michael@0 9220 25422, 25406, 25391, 25429, 25410, 25414, 25423, 25417, 25402, 25424,
michael@0 9221 25405, {f: 2, c: 25386}, 25384, 25421, 25420, {f: 2, c: 25928}, 26009,
michael@0 9222 26049, 26053, 26178, 26185, 26191, 26179, 26194, 26188, 26181, 26177,
michael@0 9223 26360, {f: 2, c: 26388}, 26391, 26657, 26680, 26696, 26694, 26707, 26681,
michael@0 9224 26690, 26708, 26665, 26803, 26647, 26700, 26705, 26685, 26612, 26704,
michael@0 9225 26688, 26684, 26691, 26666, 26693, 26643, 26648, 26689, 27530, 27529,
michael@0 9226 27575, 27683, {f: 2, c: 27687}, 27686, 27684, 27888, 28010, 28053, 28040,
michael@0 9227 28039, 28006, 28024, 28023, 27993, 28051, 28012, 28041, 28014, 27994,
michael@0 9228 28020, 28009, 28044, 28042, 28025, 28037, 28005, 28052, 28874, 28888,
michael@0 9229 28900, 28889, 28872, 28879, 29241, 29305, 29436, 29433, 29437, 29432,
michael@0 9230 29431, 29574, 29677, 29705, 29678, 29664, 29674, 29662, 30036, 30045,
michael@0 9231 30044, 30042, 30041, 30142, 30149, 30151, {f: 2, c: 30130}, 30141, 30140,
michael@0 9232 30137, 30146, 30136, 30347, 30384, 30410, {f: 2, c: 30413}, 30505,
michael@0 9233 {f: 2, c: 30495}, 30504, 30697, 30768, 30759, 30776, 30749, 30772, 30775,
michael@0 9234 30757, 30765, 30752, 30751, 30770, 31061, 31056, 31072, 31071, 31062,
michael@0 9235 31070, 31069, 31063, 31066, 31204, [31203, 60418], 31207, 31199, 31206,
michael@0 9236 31209, 31192, 31364, 31368, 31449, 31494, 31505, 31881, 32033, 32023,
michael@0 9237 32011, 32010, 32032, 32034, 32020, 32016, 32021, 32026, 32028, 32013,
michael@0 9238 32025, 32027, 32570, 32607, 32660, 32709, 32705, 32774, 32772, 32792,
michael@0 9239 32789, 32793, 32791, 32829, 32831, 33009, 33026, 33008, 33029, 33005,
michael@0 9240 33012, 33030, 33016, 33011, 33032, 33021, 33034, 33020, 33007, 33261,
michael@0 9241 33260, 33280, 33296, {f: 2, c: 33322}, 33320, 33324, 33467, 33579, 33618,
michael@0 9242 33620, 33610, 33592, 33616, 33609, 33589, 33588, 33615, 33586, 33593,
michael@0 9243 33590, 33559, 33600, 33585, 33576, 33603, 34388, 34442, 34474, 34451,
michael@0 9244 34468, 34473, 34444, 34467, 34460, 34928, 34935, {f: 2, c: 34945}, 34941,
michael@0 9245 34937, 35352, 35344, 35342, 35340, 35349, 35338, 35351, 35347, 35350,
michael@0 9246 35343, 35345, 35912, 35962, 35961, {f: 2, c: 36001}, [36215, 58442], 36524,
michael@0 9247 36562, 36564, 36559, 36785, 36865, 36870, 36855, 36864, 36858, 36852,
michael@0 9248 36867, 36861, 36869, 36856, 37013, 37089, 37085, 37090, 37202, 37197,
michael@0 9249 37196, 37336, 37341, 37335, 37340, 37337, 38275, {f: 2, c: 38498}, 38497,
michael@0 9250 38491, 38493, 38500, 38488, 38494, 38587, 39138, [12218, 39340],
michael@0 9251 [12219, 39592], [12220, 39640], [12222, 39717], [12224, 39730],
michael@0 9252 [12225, 39740], 20094, 20602, [20605, 57382], 20572, 20551, 20547, 20556,
michael@0 9253 20570, 20553, 20581, 20598, 20558, 20565, 20597, 20596, 20599, 20559,
michael@0 9254 20495, 20591, 20589, 20828, 20885, 20976, 21098, 21103, 21202, 21209,
michael@0 9255 21208, 21205, 21264, 21263, 21273, {f: 2, c: 21311}, 21310, 21443, 26364,
michael@0 9256 21830, 21866, 21862, 21828, 21854, 21857, 21827, 21834, 21809, 21846,
michael@0 9257 21839, 21845, 21807, 21860, 21816, 21806, 21852, 21804, 21859, 21811,
michael@0 9258 21825, 21847, 22280, 22283, 22281, 22495, 22533, 22538, 22534, 22496,
michael@0 9259 22500, 22522, 22530, 22581, 22519, 22521, 22816, 22882, 23094, 23105,
michael@0 9260 23113, 23142, 23146, 23104, 23100, 23138, 23130, 23110, 23114, 23408,
michael@0 9261 23495, 23493, 23492, 23490, 23487, 23494, 23561, 23560, 23559, 23648,
michael@0 9262 {f: 2, c: 23644}, 23815, 23814, 23822, 23835, 23830, 23842, 23825, 23849,
michael@0 9263 23828, 23833, 23844, 23847, 23831, 24034, 24120, 24118, 24115, 24119,
michael@0 9264 {f: 2, c: 24247}, 24246, 24245, 24254, 24373, 24375, 24407, 24428, 24425,
michael@0 9265 24427, 24471, 24473, 24478, 24472, 24481, 24480, 24476, 24703, 24739,
michael@0 9266 24713, 24736, 24744, 24779, 24756, 24806, 24765, 24773, 24763, 24757,
michael@0 9267 24796, 24764, 24792, 24789, 24774, 24799, 24760, 24794, 24775,
michael@0 9268 {f: 2, c: 25114}, 25160, 25504, 25511, 25458, 25494, 25506, 25509, 25463,
michael@0 9269 25447, 25496, 25514, 25457, 25513, 25481, 25475, 25499, 25451, 25512,
michael@0 9270 25476, 25480, 25497, 25505, 25516, 25490, 25487, 25472, 25467, 25449,
michael@0 9271 25448, 25466, 25949, 25942, 25937, 25945, 25943, 21855, 25935, 25944,
michael@0 9272 25941, 25940, 26012, 26011, 26028, 26063, {f: 2, c: 26059}, 26062, 26205,
michael@0 9273 26202, 26212, 26216, 26214, 26206, 26361, 21207, 26395, 26753, 26799,
michael@0 9274 26786, 26771, 26805, 26751, 26742, 26801, 26791, 26775, 26800, 26755,
michael@0 9275 26820, 26797, 26758, 26757, 26772, 26781, 26792, 26783, 26785, 26754,
michael@0 9276 27442, 27578, {f: 2, c: 27627}, 27691, 28046, 28092, 28147, 28121, 28082,
michael@0 9277 28129, 28108, 28132, 28155, 28154, 28165, 28103, 28107, 28079, 28113,
michael@0 9278 28078, 28126, 28153, 28088, 28151, 28149, 28101, 28114, 28186, 28085,
michael@0 9279 28122, 28139, 28120, 28138, 28145, 28142, 28136, 28102, 28100, 28074,
michael@0 9280 28140, 28095, 28134, 28921, {f: 2, c: 28937}, 28925, 28911, 29245, 29309,
michael@0 9281 29313, 29468, 29467, 29462, 29459, 29465, 29575, 29701, 29706, 29699,
michael@0 9282 29702, 29694, 29709, 29920, {f: 2, c: 29942}, 29980, 29986,
michael@0 9283 {f: 2, c: 30053}, 30050, 30064, 30095, {f: 2, c: 30164}, 30133, 30154,
michael@0 9284 30157, 30350, 30420, 30418, 30427, 30519, 30526, 30524, 30518, 30520,
michael@0 9285 30522, 30827, 30787, 30798, 31077, 31080, 31085, 31227, 31378, 31381,
michael@0 9286 31520, 31528, 31515, 31532, 31526, 31513, 31518, 31534, 31890, 31895,
michael@0 9287 31893, 32070, 32067, 32113, 32046, 32057, 32060, 32064, 32048, 32051,
michael@0 9288 32068, 32047, 32066, 32050, 32049, 32573, 32670, 32666, 32716, 32718,
michael@0 9289 32722, 32796, 32842, 32838, 33071, 33046, 33059, 33067, 33065, 33072,
michael@0 9290 33060, 33282, 33333, 33335, 33334, 33337, 33678, 33694, 33688, 33656,
michael@0 9291 33698, 33686, 33725, 33707, 33682, 33674, 33683, 33673, 33696, 33655,
michael@0 9292 {f: 2, c: 33659}, 33670, 33703, 34389, 24426, 34503, 34496, 34486, 34500,
michael@0 9293 34485, 34502, 34507, 34481, 34479, 34505, 34899, 34974, 34952, 34987,
michael@0 9294 34962, 34966, 34957, 34955, 35219, 35215, 35370, 35357, 35363, 35365,
michael@0 9295 35377, 35373, 35359, 35355, 35362, 35913, 35930, 36009, 36012, 36011,
michael@0 9296 36008, 36010, 36007, 36199, 36198, 36286, 36282, 36571, 36575, 36889,
michael@0 9297 36877, 36890, 36887, 36899, 36895, 36893, 36880, 36885, 36894, 36896,
michael@0 9298 36879, 36898, 36886, 36891, 36884, 37096, 37101, [37117, 58488], 37207,
michael@0 9299 37326, 37365, 37350, 37347, 37351, 37357, 37353, 38281, 38506, 38517,
michael@0 9300 38515, 38520, 38512, 38516, {f: 2, c: 38518}, 38508, 38592, 38634, 38633,
michael@0 9301 31456, 31455, {f: 2, c: 38914}, [12226, 39770], [12227, 40165],
michael@0 9302 [12228, 40565], [12229, 40575], [12230, 40613], [12231, 40635], 20642,
michael@0 9303 20621, 20613, 20633, 20625, 20608, 20630, 20632, 20634, 26368, 20977,
michael@0 9304 21106, {f: 2, c: 21108}, 21097, 21214, 21213, 21211, 21338, 21413, 21883,
michael@0 9305 21888, 21927, 21884, 21898, 21917, 21912, 21890, 21916, 21930, 21908,
michael@0 9306 21895, 21899, 21891, 21939, 21934, 21919, 21822, 21938, 21914, 21947,
michael@0 9307 21932, 21937, 21886, 21897, 21931, 21913, 22285, 22575, 22570, 22580,
michael@0 9308 22564, {f: 2, c: 22576}, 22561, 22557, 22560, {f: 2, c: 22777}, 22880,
michael@0 9309 [23159, 57587], 23194, 23167, 23186, 23195, 23207, 23411, 23409, 23506,
michael@0 9310 23500, 23507, 23504, {f: 2, c: 23562}, 23601, 23884, 23888, 23860, 23879,
michael@0 9311 24061, 24133, 24125, 24128, 24131, 24190, 24266, {f: 2, c: 24257}, 24260,
michael@0 9312 24380, 24429, {f: 2, c: 24489}, 24488, 24785, 24801, 24754, 24758, 24800,
michael@0 9313 24860, 24867, 24826, 24853, 24816, 24827, 24820, 24936, 24817, 24846,
michael@0 9314 24822, 24841, 24832, 24850, 25119, 25161, 25507, 25484, 25551, 25536,
michael@0 9315 25577, 25545, 25542, 25549, 25554, 25571, 25552, 25569, 25558,
michael@0 9316 {f: 2, c: 25581}, 25462, 25588, 25578, 25563, 25682, 25562, 25593, 25950,
michael@0 9317 25958, {f: 2, c: 25954}, 26001, 26000, 26031, 26222, 26224, [26228, 57786],
michael@0 9318 26230, 26223, 26257, 26234, 26238, 26231, {f: 2, c: 26366}, 26399, 26397,
michael@0 9319 26874, 26837, 26848, 26840, 26839, 26885, 26847, 26869, 26862, 26855,
michael@0 9320 26873, 26834, 26866, 26851, 26827, 26829, 26893, 26898, 26894, 26825,
michael@0 9321 26842, 26990, 26875, 27454, 27450, 27453, 27544, 27542, 27580, 27631,
michael@0 9322 {f: 2, c: 27694}, 27692, [28207, 57904], 28216, 28244, 28193, 28210, 28263,
michael@0 9323 28234, 28192, 28197, 28195, 28187, 28251, 28248, 28196, 28246, 28270,
michael@0 9324 28205, 28198, 28271, 28212, 28237, 28218, 28204, 28227, [28189, 57901],
michael@0 9325 28222, 28363, 28297, 28185, 28238, 28259, 28228, 28274, 28265, 28255,
michael@0 9326 {f: 2, c: 28953}, 28966, 28976, 28961, 28982, [29038, 57958], 28956, 29260,
michael@0 9327 29316, 29312, 29494, 29477, 29492, 29481, 29754, 29738, 29747, 29730,
michael@0 9328 29733, {f: 2, c: 29749}, 29748, 29743, 29723, 29734, 29736,
michael@0 9329 {f: 2, c: 29989}, 30059, 30058, 30178, 30171, 30179, 30169, 30168, 30174,
michael@0 9330 30176, {f: 2, c: 30331}, 30358, 30355, 30388, 30428, 30543, 30701, 30813,
michael@0 9331 30828, 30831, 31245, 31240, 31243, 31237, 31232, 31384, 31383, 31382,
michael@0 9332 31461, 31459, 31561, 31574, 31558, 31568, 31570, 31572, 31565, 31563,
michael@0 9333 31567, [31569, 60510], 31903, 31909, 32094, 32080, 32104, 32085, 32043,
michael@0 9334 32110, 32114, 32097, 32102, 32098, 32112, 32115, 21892, {f: 2, c: 32724},
michael@0 9335 32779, 32850, 32901, 33109, 33108, 33099, 33105, 33102, 33081, 33094,
michael@0 9336 33086, 33100, 33107, 33140, 33298, 33308, 33769, 33795, 33784, 33805,
michael@0 9337 33760, 33733, 33803, [33729, 58309], 33775, 33777, 33780, 33879, 33802,
michael@0 9338 33776, 33804, 33740, 33789, 33778, 33738, 33848, 33806, 33796, 33756,
michael@0 9339 33799, 33748, 33759, 34395, 34527, 34521, 34541, 34516, 34523, 34532,
michael@0 9340 34512, 34526, 34903, {f: 2, c: 35009}, 34993, 35203, 35222, 35387, 35424,
michael@0 9341 35413, 35422, 35388, 35393, 35412, 35419, 35408, 35398, 35380, 35386,
michael@0 9342 35382, 35414, 35937, 35970, 36015, 36028, 36019, 36029, 36033, 36027,
michael@0 9343 36032, 36020, 36023, 36022, 36031, 36024, 36234, 36229, 36225, 36302,
michael@0 9344 36317, 36299, 36314, 36305, 36300, 36315, 36294, 36603, 36600, 36604,
michael@0 9345 36764, 36910, 36917, 36913, 36920, 36914, 36918, 37122, 37109, 37129,
michael@0 9346 37118, 37219, 37221, 37327, {f: 2, c: 37396}, 37411, 37385, 37406, 37389,
michael@0 9347 37392, 37383, 37393, 38292, 38287, 38283, 38289, 38291, 38290, 38286,
michael@0 9348 38538, 38542, 38539, 38525, {f: 2, c: 38533}, 38541, 38514, 38532, 38593,
michael@0 9349 38597, 38596, {f: 2, c: 38598}, 38639, 38642, 38860, {f: 2, c: 38917},
michael@0 9350 38920, 39143, 39146, 39151, 39145, 39154, 39149, 39342, 39341,
michael@0 9351 [12232, 40643], [12233, 40653], [12234, 40657], 20098, 20653, 20661,
michael@0 9352 {f: 2, c: 20658}, 20677, 20670, 20652, 20663, 20667, 20655, 20679, 21119,
michael@0 9353 21111, 21117, 21215, 21222, 21220, {f: 2, c: 21218}, 21295, 21983, 21992,
michael@0 9354 21971, 21990, 21966, 21980, 21959, 21969, {f: 2, c: 21987}, 21999, 21978,
michael@0 9355 21985, {f: 2, c: 21957}, 21989, 21961, {f: 2, c: 22290}, 22622, 22609,
michael@0 9356 22616, 22615, 22618, 22612, 22635, 22604, 22637, 22602, 22626, 22610,
michael@0 9357 22603, 22887, 23233, 23241, 23244, 23230, 23229, 23228, 23219, 23234,
michael@0 9358 23218, 23913, 23919, 24140, 24185, 24265, 24264, 24338, 24409, 24492,
michael@0 9359 24494, 24858, 24847, 24904, 24863, 24819, 24859, 24825, 24833, 24840,
michael@0 9360 24910, 24908, 24900, 24909, 24894, 24884, 24871, 24845, 24838, 24887,
michael@0 9361 {f: 2, c: 25121}, 25619, 25662, 25630, 25642, 25645, 25661, 25644, 25615,
michael@0 9362 25628, 25620, 25613, 25654, {f: 2, c: 25622}, 25606, 25964, 26015, 26032,
michael@0 9363 26263, 26249, {f: 2, c: 26247}, 26262, 26244, 26264, 26253, 26371, 27028,
michael@0 9364 26989, 26970, 26999, 26976, 26964, 26997, 26928, 27010, 26954, 26984,
michael@0 9365 26987, 26974, 26963, 27001, 27014, 26973, 26979, 26971, 27463, 27506,
michael@0 9366 27584, 27583, 27603, 27645, 28322, 28335, 28371, 28342, 28354, 28304,
michael@0 9367 28317, 28359, 28357, 28325, 28312, 28348, 28346, 28331, 28369, 28310,
michael@0 9368 28316, 28356, 28372, 28330, 28327, 28340, 29006, 29017, 29033, 29028,
michael@0 9369 29001, 29031, 29020, 29036, 29030, 29004, 29029, 29022, 28998, 29032,
michael@0 9370 29014, 29242, 29266, 29495, 29509, 29503, 29502, 29807, 29786, 29781,
michael@0 9371 29791, 29790, 29761, 29759, 29785, 29787, [29788, 58019], 30070, 30072,
michael@0 9372 30208, 30192, 30209, 30194, 30193, 30202, 30207, 30196, 30195,
michael@0 9373 {f: 2, c: 30430}, 30555, 30571, 30566, 30558, 30563, 30585, 30570, 30572,
michael@0 9374 30556, 30565, 30568, 30562, 30702, 30862, 30896, {f: 2, c: 30871}, 30860,
michael@0 9375 30857, 30844, 30865, 30867, 30847, 31098, 31103, 31105, 33836, 31165,
michael@0 9376 31260, 31258, 31264, 31252, 31263, 31262, {f: 2, c: 31391}, 31607, 31680,
michael@0 9377 31584, 31598, 31591, 31921, 31923, 31925, 32147, 32121, 32145, 32129,
michael@0 9378 32143, 32091, 32622, {f: 2, c: 32617}, 32626, 32681, 32680, 32676, 32854,
michael@0 9379 32856, 32902, 32900, 33137, 33136, 33144, 33125, 33134, 33139, 33131,
michael@0 9380 {f: 2, c: 33145}, 33126, 33285, 33351, 33922, 33911, 33853, 33841, 33909,
michael@0 9381 33894, 33899, 33865, 33900, 33883, 33852, 33845, 33889, 33891, 33897,
michael@0 9382 33901, 33862, 34398, 34396, 34399, 34553, 34579, 34568, 34567, 34560,
michael@0 9383 34558, 34555, {f: 2, c: 34562}, 34566, 34570, 34905, 35039, 35028, 35033,
michael@0 9384 35036, 35032, 35037, 35041, 35018, 35029, 35026, 35228, 35299, 35435,
michael@0 9385 {f: 2, c: 35442}, 35430, 35433, 35440, 35463, 35452, 35427, 35488, 35441,
michael@0 9386 35461, 35437, 35426, 35438, 35436, 35449, 35451, 35390, 35432, 35938,
michael@0 9387 35978, 35977, 36042, {f: 2, c: 36039}, 36036, 36018, 36035, 36034, 36037,
michael@0 9388 36321, 36319, 36328, 36335, 36339, 36346, 36330, 36324, 36326, 36530,
michael@0 9389 36611, 36617, 36606, 36618, 36767, 36786, 36939, 36938, 36947, 36930,
michael@0 9390 36948, 36924, 36949, 36944, 36935, 36943, 36942, 36941, 36945, 36926,
michael@0 9391 36929, 37138, 37143, 37228, 37226, 37225, 37321, 37431, 37463, 37432,
michael@0 9392 37437, 37440, 37438, 37467, 37451, 37476, 37457, 37428, 37449, 37453,
michael@0 9393 37445, 37433, 37439, 37466, 38296, 38552, {f: 2, c: 38548}, 38605, 38603,
michael@0 9394 {f: 2, c: 38601}, 38647, 38651, 38649, 38646, 38742, 38772, 38774,
michael@0 9395 {f: 2, c: 38928}, 38931, 38922, 38930, 38924, 39164, 39156,
michael@0 9396 {f: 2, c: 39165}, 39347, 39345, 39348, 39649, 40169, 40578, [12237, 40718],
michael@0 9397 [12238, 40723], [12239, 40736], 20711, 20718, 20709, 20694, [20717, 60903],
michael@0 9398 20698, 20693, 20687, 20689, 20721, 20686, 20713, 20834, 20979, 21123,
michael@0 9399 21122, 21297, 21421, 22014, 22016, 22043, 22039, 22013, 22036, 22022,
michael@0 9400 22025, {f: 2, c: 22029}, 22007, 22038, 22047, 22024, 22032, 22006, 22296,
michael@0 9401 22294, 22645, 22654, 22659, 22675, 22666, 22649, 22661, 22653, 22781,
michael@0 9402 22821, 22818, 22820, 22890, 22889, 23265, 23270, 23273, 23255, 23254,
michael@0 9403 23256, 23267, 23413, 23518, 23527, 23521, {f: 2, c: 23525}, 23528, 23522,
michael@0 9404 23524, 23519, 23565, 23650, 23940, 23943, 24155, 24163, 24149, 24151,
michael@0 9405 24148, 24275, 24278, 24330, 24390, 24432, 24505, 24903, 24895, 24907,
michael@0 9406 24951, {f: 2, c: 24930}, 24927, 24922, 24920, 24949, 25130, 25735, 25688,
michael@0 9407 25684, 25764, 25720, 25695, 25722, 25681, 25703, 25652, 25709, 25723,
michael@0 9408 25970, 26017, 26071, 26070, 26274, 26280, 26269, 27036, 27048, 27029,
michael@0 9409 27073, 27054, 27091, 27083, 27035, 27063, 27067, 27051, 27060, 27088,
michael@0 9410 27085, 27053, 27084, 27046, 27075, 27043, 27465, 27468, 27699, 28467,
michael@0 9411 28436, 28414, 28435, 28404, 28457, 28478, 28448, 28460, 28431, 28418,
michael@0 9412 28450, 28415, 28399, 28422, 28465, 28472, 28466, 28451, 28437, 28459,
michael@0 9413 28463, 28552, 28458, 28396, 28417, 28402, 28364, 28407, 29076, 29081,
michael@0 9414 29053, 29066, 29060, 29074, 29246, 29330, 29334, 29508, 29520, 29796,
michael@0 9415 29795, 29802, 29808, 29805, 29956, 30097, 30247, 30221, 30219, 30217,
michael@0 9416 30227, 30433, 30435, 30596, 30589, 30591, 30561, 30913, 30879, 30887,
michael@0 9417 30899, 30889, 30883, {f: 2, c: 31118}, 31117, 31278, 31281, 31402, 31401,
michael@0 9418 31469, 31471, 31649, 31637, 31627, 31605, 31639, 31645, 31636, 31631,
michael@0 9419 [31672, 58170], 31623, 31620, 31929, {f: 2, c: 31933}, 32187, 32176, 32156,
michael@0 9420 {f: 2, c: 32189}, 32160, 32202, 32180, 32178, 32177, 32186, 32162, 32191,
michael@0 9421 32181, 32184, 32173, [32210, 58202], 32199, 32172, 32624, {f: 2, c: 32736},
michael@0 9422 32735, 32862, 32858, 32903, 33104, 33152, 33167, 33160, 33162, 33151,
michael@0 9423 33154, 33255, 33274, 33287, 33300, 33310, 33355, 33993, 33983, 33990,
michael@0 9424 33988, 33945, 33950, 33970, 33948, 33995, 33976, 33984, 34003, 33936,
michael@0 9425 33980, 34001, 33994, 34623, 34588, 34619, 34594, 34597, 34612, 34584,
michael@0 9426 34645, 34615, 34601, 35059, 35074, 35060, 35065, 35064, 35069, 35048,
michael@0 9427 35098, 35055, 35494, 35468, 35486, 35491, 35469, 35489, 35475, 35492,
michael@0 9428 35498, 35493, 35496, 35480, 35473, 35482, 35495, 35946, 35981, 35980,
michael@0 9429 36051, {f: 2, c: 36049}, 36203, 36249, 36245, 36348, 36628, 36626, 36629,
michael@0 9430 36627, 36771, 36960, 36952, 36956, 36963, 36953, 36958, 36962, 36957,
michael@0 9431 36955, 37145, 37144, 37150, 37237, 37240, 37239, 37236, 37496, 37548,
michael@0 9432 37504, 37509, 37528, 37526, 37499, 37523, 37532, 37544, 37500, 37521,
michael@0 9433 38305, {f: 2, c: 38312}, 38307, 38309, 38308, 38553, 38556, 38555, 38604,
michael@0 9434 38610, 38656, 38780, 38789, 38902, {f: 2, c: 38935}, 39087, 39089, 39171,
michael@0 9435 39173, 39180, 39177, 39361, {f: 2, c: 39599}, 39654, {f: 2, c: 39745},
michael@0 9436 40180, 40182, 40179, 40636, [12240, 40763], [12241, 40778], 20740, 20736,
michael@0 9437 20731, 20725, 20729, 20738, {f: 2, c: 20744}, 20741, 20956,
michael@0 9438 {f: 3, c: 21127}, 21133, 21130, 21232, 21426, 22062, 22075, 22073, 22066,
michael@0 9439 22079, 22068, 22057, 22099, 22094, 22103, 22132, 22070, {f: 2, c: 22063},
michael@0 9440 22656, 22687, 22686, 22707, 22684, 22702, 22697, 22694, 22893, 23305,
michael@0 9441 23291, 23307, 23285, 23308, 23304, 23534, 23532, 23529, 23531,
michael@0 9442 {f: 2, c: 23652}, 23965, 23956, 24162, 24159, 24161, 24290, 24282, 24287,
michael@0 9443 24285, 24291, 24288, 24392, 24433, 24503, 24501, 24950, 24935, 24942,
michael@0 9444 24925, 24917, 24962, 24956, 24944, 24939, 24958, 24999, 24976, 25003,
michael@0 9445 24974, 25004, 24986, 24996, 24980, 25006, 25134, 25705, 25711, 25721,
michael@0 9446 25758, 25778, 25736, [25744, 57745], 25776, 25765, 25747, 25749, 25769,
michael@0 9447 25746, 25774, 25773, 25771, 25754, 25772, 25753, 25762, 25779, 25973,
michael@0 9448 {f: 2, c: 25975}, 26286, 26283, 26292, 26289, 27171, 27167, 27112, 27137,
michael@0 9449 27166, 27161, 27133, 27169, 27155, 27146, 27123, 27138, 27141, 27117,
michael@0 9450 27153, 27472, 27470, 27556, {f: 2, c: 27589}, 28479, 28540, 28548, 28497,
michael@0 9451 28518, 28500, 28550, 28525, 28507, 28536, 28526, 28558, 28538, 28528,
michael@0 9452 28516, 28567, 28504, 28373, 28527, 28512, 28511, 29087, 29100, 29105,
michael@0 9453 29096, 29270, 29339, 29518, 29527, 29801, 29835, 29827, 29822, 29824,
michael@0 9454 30079, 30240, 30249, 30239, 30244, 30246, {f: 2, c: 30241}, 30362, 30394,
michael@0 9455 30436, 30606, 30599, 30604, 30609, 30603, 30923, 30917, 30906, 30922,
michael@0 9456 30910, 30933, 30908, 30928, 31295, 31292, 31296, 31293, 31287, 31291,
michael@0 9457 31407, 31406, 31661, 31665, 31684, 31668, {f: 2, c: 31686}, 31681, 31648,
michael@0 9458 31692, 31946, 32224, 32244, 32239, 32251, 32216, 32236, 32221, 32232,
michael@0 9459 32227, 32218, 32222, 32233, 32158, 32217, 32242, 32249, 32629, 32631,
michael@0 9460 32687, 32745, 32806, {f: 3, c: 33179}, 33184, 33178, 33176, 34071, 34109,
michael@0 9461 34074, 34030, {f: 2, c: 34092}, 34067, 34065, 34083, 34081, 34068, 34028,
michael@0 9462 34085, 34047, 34054, 34690, 34676, 34678, 34656, 34662, 34680, 34664,
michael@0 9463 34649, 34647, 34636, 34643, 34907, 34909, 35088, 35079, {f: 2, c: 35090},
michael@0 9464 35093, 35082, 35516, 35538, 35527, 35524, 35477, 35531, 35576, 35506,
michael@0 9465 35529, 35522, 35519, 35504, 35542, 35533, 35510, 35513, 35547, 35916,
michael@0 9466 35918, 35948, 36064, 36062, 36070, 36068, {f: 2, c: 36076},
michael@0 9467 {f: 2, c: 36066}, 36060, 36074, 36065, 36205, 36255, 36259, 36395, 36368,
michael@0 9468 36381, 36386, 36367, 36393, 36383, 36385, 36382, 36538, 36637, 36635,
michael@0 9469 36639, 36649, 36646, 36650, 36636, 36638, 36645, 36969, 36974, 36968,
michael@0 9470 36973, 36983, 37168, 37165, 37159, 37169, 37255, 37257, 37259, 37251,
michael@0 9471 37573, 37563, 37559, 37610, 37604, 37569, 37555, 37564, 37586, 37575,
michael@0 9472 37616, 37554, 38317, 38321, 38660, {f: 2, c: 38662}, 38665, 38752, 38797,
michael@0 9473 38795, 38799, 38945, 38955, 38940, 39091, 39178, 39187, 39186, 39192,
michael@0 9474 39389, 39376, 39391, 39387, 39377, 39381, 39378, 39385, 39607,
michael@0 9475 {f: 2, c: 39662}, 39719, 39749, 39748, 39799, 39791, 40198, 40201, 40195,
michael@0 9476 40617, 40638, 40654, 22696, [12242, 40786], 20754, 20760, 20756, 20752,
michael@0 9477 20757, 20864, 20906, 20957, 21137, 21139, 21235, 22105, 22123, 22137,
michael@0 9478 22121, 22116, 22136, 22122, 22120, 22117, 22129, 22127, 22124, 22114,
michael@0 9479 22134, 22721, 22718, 22727, 22725, 22894, 23325, 23348, 23416, 23536,
michael@0 9480 23566, 24394, 25010, 24977, 25001, 24970, 25037, 25014, 25022, 25034,
michael@0 9481 25032, 25136, 25797, 25793, 25803, {f: 2, c: 25787}, 25818, 25796, 25799,
michael@0 9482 25794, 25805, 25791, 25810, 25812, 25790, 25972, 26310, 26313, 26297,
michael@0 9483 26308, 26311, 26296, 27197, 27192, 27194, 27225, 27243, 27224, 27193,
michael@0 9484 27204, 27234, 27233, 27211, 27207, 27189, 27231, 27208, 27481, 27511,
michael@0 9485 27653, 28610, 28593, 28577, 28611, 28580, 28609, 28583, 28595, 28608,
michael@0 9486 28601, [28598, 60318], 28582, 28576, 28596, 29118, 29129, 29136, 29138,
michael@0 9487 29128, 29141, 29113, 29134, 29145, 29148, {f: 2, c: 29123}, 29544, 29852,
michael@0 9488 29859, 29848, 29855, 29854, 29922, {f: 2, c: 29964}, 30260, 30264, 30266,
michael@0 9489 30439, 30437, 30624, {f: 2, c: 30622}, 30629, 30952, 30938, 30956, 30951,
michael@0 9490 31142, {f: 2, c: 31309}, 31302, 31308, 31307, 31418, 31705, 31761, 31689,
michael@0 9491 31716, 31707, 31713, 31721, 31718, {f: 2, c: 31957}, 32266, 32273, 32264,
michael@0 9492 32283, 32291, 32286, [32285, 58211], 32265, 32272, 32633, 32690,
michael@0 9493 {f: 2, c: 32752}, 32750, [32808, 58239], 33203, 33193, 33192, 33275, 33288,
michael@0 9494 {f: 2, c: 33368}, 34122, 34137, 34120, {f: 2, c: 34152}, 34115, 34121,
michael@0 9495 34157, 34154, 34142, 34691, 34719, 34718, 34722, 34701, 34913, 35114,
michael@0 9496 35122, 35109, 35115, 35105, 35242, [35238, 58391], 35558, 35578, 35563,
michael@0 9497 35569, 35584, 35548, 35559, 35566, 35582, {f: 2, c: 35585}, 35575, 35565,
michael@0 9498 35571, 35574, 35580, 35947, 35949, 35987, 36084, 36420, 36401, 36404,
michael@0 9499 36418, 36409, 36405, 36667, 36655, 36664, 36659, 36776, 36774, 36981,
michael@0 9500 36980, 36984, 36978, 36988, 36986, 37172, 37266, 37664, 37686, 37624,
michael@0 9501 37683, 37679, 37666, 37628, 37675, 37636, 37658, 37648, 37670, 37665,
michael@0 9502 37653, 37678, 37657, 38331, {f: 2, c: 38567}, 38570, 38613, 38670, 38673,
michael@0 9503 38678, 38669, 38675, 38671, 38747, [38748, 58565], 38758, 38808, 38960,
michael@0 9504 38968, 38971, 38967, 38957, 38969, 38948, 39184, 39208, 39198, 39195,
michael@0 9505 39201, 39194, 39405, 39394, 39409, 39608, 39612, 39675, 39661, 39720,
michael@0 9506 39825, 40213, 40227, 40230, 40232, 40210, 40219, 40664, 40660,
michael@0 9507 [12243, 40845], [12244, 40860], 20778, 20767, 20769, 20786, 21237, 22158,
michael@0 9508 22144, 22160, 22149, 22151, 22159, 22741, 22739, 22737, 22734, 23344,
michael@0 9509 23338, 23332, 23418, 23607, 23656, 23996, 23994, 23997, 23992, 24171,
michael@0 9510 24396, 24509, 25033, 25026, 25031, 25062, 25035, 25138, 25140, 25806,
michael@0 9511 25802, 25816, 25824, 25840, 25830, 25836, 25841, 25826, 25837,
michael@0 9512 {f: 2, c: 25986}, 26329, 26326, 27264, 27284, 27268, 27298, 27292, 27355,
michael@0 9513 27299, 27262, 27287, 27280, 27296, 27484, 27566, 27610, 27656, 28632,
michael@0 9514 28657, {f: 2, c: 28639}, 28635, 28644, 28651, 28655, 28544, 28652, 28641,
michael@0 9515 28649, 28629, 28654, 28656, 29159, [29151, 60361], 29166, 29158, 29157,
michael@0 9516 29165, 29164, 29172, 29152, 29237, 29254, 29552, 29554, 29865, 29872,
michael@0 9517 29862, 29864, 30278, 30274, 30284, 30442, 30643, 30634, 30640, 30636,
michael@0 9518 30631, 30637, 30703, 30967, 30970, 30964, 30959, 30977, 31143, 31146,
michael@0 9519 31319, 31423, 31751, 31757, 31742, 31735, 31756, 31712, 31968, 31964,
michael@0 9520 31966, 31970, 31967, 31961, 31965, 32302, 32318, 32326, 32311, 32306,
michael@0 9521 32323, 32299, 32317, 32305, 32325, 32321, 32308, 32313, 32328, 32309,
michael@0 9522 32319, 32303, 32580, 32755, 32764, {f: 2, c: 32881}, 32880, 32879, 32883,
michael@0 9523 33222, 33219, 33210, 33218, 33216, 33215, 33213, 33225, 33214, 33256,
michael@0 9524 33289, 33393, 34218, 34180, 34174, 34204, 34193, 34196, 34223, 34203,
michael@0 9525 34183, 34216, 34186, 34214, 34407, 34752, 34769, 34739, 34770, 34758,
michael@0 9526 34731, 34747, 34746, 34760, 34763, 35131, 35126, 35140, 35128, 35133,
michael@0 9527 35244, 35598, 35607, 35609, 35611, 35594, 35616, 35613, 35588, 35600,
michael@0 9528 35905, 35903, 35955, 36090, 36093, 36092, 36088, 36091, 36264, 36425,
michael@0 9529 36427, 36424, 36426, 36676, 36670, 36674, 36677, 36671, 36991, 36989,
michael@0 9530 36996, {f: 2, c: 36993}, 36992, 37177, 37283, 37278, 37276, 37709, 37762,
michael@0 9531 37672, 37749, 37706, 37733, 37707, 37656, 37758, 37740, 37723, 37744,
michael@0 9532 37722, 37716, {f: 3, c: 38346}, 38344, 38342, 38577, 38584, 38614, 38684,
michael@0 9533 38686, 38816, 38867, 38982, 39094, 39221, 39425, 39423, 39854, 39851,
michael@0 9534 39850, 39853, 40251, 40255, 40587, 40655, 40670, {f: 2, c: 40668}, 40667,
michael@0 9535 40766, 40779, 21474, 22165, 22190, 22745, 22744, 23352, 24413, 25059,
michael@0 9536 25139, 25844, 25842, 25854, 25862, {f: 2, c: 25850}, 25847, 26039, 26332,
michael@0 9537 26406, 27315, 27308, 27331, 27323, 27320, 27330, {f: 2, c: 27310}, 27487,
michael@0 9538 27512, 27567, 28681, 28683, 28670, 28678, 28666, 28689, 28687,
michael@0 9539 {f: 2, c: 29179}, 29182, 29176, 29559, 29557, 29863, 29887, 29973, 30294,
michael@0 9540 30296, 30290, 30653, 30655, {f: 2, c: 30651}, 30990, 31150,
michael@0 9541 {f: 2, c: 31329}, 31328, {f: 2, c: 31428}, 31787, 31783, 31786, 31774,
michael@0 9542 31779, 31777, 31975, {f: 2, c: 32340}, 32350, 32346, 32353, 32338, 32345,
michael@0 9543 32584, 32761, 32763, 32887, 32886, 33229, 33231, 33290, 34255, 34217,
michael@0 9544 34253, 34256, 34249, 34224, 34234, 34233, 34799, 34796, 34802, 34784,
michael@0 9545 35206, 35250, 35316, 35624, 35641, 35628, 35627, 35920, 36101, 36441,
michael@0 9546 36451, 36454, 36452, 36447, 36437, 36544, 36681, 36685, 36999, 36995,
michael@0 9547 37000, {f: 2, c: 37291}, 37328, 37780, 37770, 37782, 37794, 37811, 37806,
michael@0 9548 37804, 37808, 37784, 37786, 37783, 38356, 38358, 38352, 38357, 38626,
michael@0 9549 38620, 38617, 38619, 38622, 38692, 38819, 38822, 38829, 38905, 38989,
michael@0 9550 38991, 38988, 38990, 38995, 39098, {f: 2, c: 39230}, 39229, 39214, 39333,
michael@0 9551 39438, 39617, 39683, 39686, 39759, 39758, 39757, 39882, 39881, 39933,
michael@0 9552 39880, 39872, 40273, 40285, 40288, 40672, 40725, 40748, 20787, 22181,
michael@0 9553 22184, {f: 2, c: 22750}, 22754, 23541, 40848, 24300, 25074, 25079, 25078,
michael@0 9554 25077, 25856, 25871, 26336, 26333, 27365, 27357, 27354, 27347, 28699,
michael@0 9555 28703, 28712, 28698, 28701, 28693, 28696, 29190, 29197, 29272, 29346,
michael@0 9556 29560, 29562, 29885, 29898, 29923, 30087, 30086, 30303, 30305, 30663,
michael@0 9557 31001, 31153, 31339, 31337, {f: 2, c: 31806}, 31800, 31805, 31799, 31808,
michael@0 9558 32363, 32365, 32377, {f: 2, c: 32361}, 32371, 32645, 32694, 32697, 32696,
michael@0 9559 33240, 34281, 34269, 34282, 34261, {f: 2, c: 34276}, 34295, 34811, 34821,
michael@0 9560 34829, 34809, 34814, 35168, 35167, 35158, 35166, 35649, 35676, 35672,
michael@0 9561 35657, 35674, {f: 2, c: 35662}, 35654, 35673, 36104, 36106, 36476, 36466,
michael@0 9562 36487, 36470, 36460, 36474, 36468, 36692, 36686, 36781, {f: 2, c: 37002},
michael@0 9563 37297, 37294, 37857, 37841, 37855, 37827, 37832, {f: 2, c: 37852}, 37846,
michael@0 9564 37858, 37837, 37848, 37860, 37847, 37864, 38364, 38580, 38627, 38698,
michael@0 9565 38695, 38753, 38876, 38907, 39006, 39000, 39003, 39100, 39237, 39241,
michael@0 9566 39446, 39449, 39693, 39912, 39911, 39894, 39899, 40329, 40289, 40306,
michael@0 9567 40298, 40300, 40594, 40599, 40595, 40628, 21240, 22199, 22198, 22196,
michael@0 9568 22204, 22756, 23360, 23363, 23421, 23542, 24009, 25080, 25082, 25880,
michael@0 9569 25876, 25881, 26342, 26407, 27372, 28734, 28720, 28722, 29200, 29563,
michael@0 9570 29903, 30306, 30309, 31014, 31018, 31020, 31019, 31431, 31478, 31820,
michael@0 9571 31811, 31821, {f: 2, c: 31983}, 36782, 32381, 32380, 32386, 32588, 32768,
michael@0 9572 33242, 33382, 34299, 34297, 34321, 34298, 34310, 34315, 34311, 34314,
michael@0 9573 {f: 2, c: 34836}, 35172, 35258, 35320, 35696, 35692, 35686, 35695, 35679,
michael@0 9574 35691, 36111, 36109, 36489, 36481, 36485, 36482, 37300, 37323, 37912,
michael@0 9575 37891, 37885, 38369, 38704, 39108, 39250, 39249, 39336, 39467, 39472,
michael@0 9576 39479, 39477, 39955, 39949, 40569, 40629, 40680, 40751, 40799, 40803,
michael@0 9577 40801, {f: 2, c: 20791}, 22209, 22208, 22210, 22804, 23660, 24013, 25084,
michael@0 9578 25086, 25885, 25884, 26005, 26345, 27387, 27396, 27386, 27570, 28748,
michael@0 9579 29211, 29351, 29910, 29908, 30313, 30675, 31824, 32399, 32396, 32700,
michael@0 9580 34327, 34349, 34330, 34851, 34850, 34849, 34847, 35178, 35180, 35261,
michael@0 9581 35700, 35703, 35709, 36115, 36490, 36493, 36491, 36703, 36783, 37306,
michael@0 9582 37934, 37939, 37941, 37946, 37944, 37938, 37931, 38370, {f: 2, c: 38712},
michael@0 9583 38706, [38911, 58586], 39015, 39013, 39255, 39493, 39491, 39488, 39486,
michael@0 9584 39631, 39764, 39761, 39981, 39973, 40367, 40372, 40386, 40376, 40605,
michael@0 9585 40687, 40729, 40796, {f: 2, c: 40806}, 20796, 20795, 22216, 22218, 22217,
michael@0 9586 23423, 24020, 24018, 24398, 25087, 25892, 27402, 27489, 28753, 28760,
michael@0 9587 29568, 29924, 30090, 30318, 30316, 31155, 31840, 31839, 32894, 32893,
michael@0 9588 33247, 35186, 35183, 35324, 35712, {f: 2, c: 36118}, 36497, 36499, 36705,
michael@0 9589 37192, 37956, {f: 2, c: 37969}, {f: 2, c: 38717}, 38851, 38849, 39019,
michael@0 9590 39253, 39509, 39501, 39634, 39706, 40009, 39985, 39998, 39995, 40403,
michael@0 9591 40407, 40756, 40812, 40810, 40852, 22220, 24022, 25088, 25891, 25899,
michael@0 9592 25898, 26348, 27408, 29914, 31434, 31844, 31843, 31845, 32403, 32406,
michael@0 9593 32404, 33250, 34360, 34367, 34865, 35722, 37008, 37007, 37987, 37984,
michael@0 9594 37988, 38760, 39023, 39260, {f: 2, c: 39514}, 39511, {f: 2, c: 39635},
michael@0 9595 39633, 40020, 40023, 40022, 40421, 40607, 40692, 22225, 22761, 25900,
michael@0 9596 28766, {f: 2, c: 30321}, [30679, 60226], 32592, 32648, 34870, 34873, 34914,
michael@0 9597 35731, 35730, 35734, 33399, 36123, 37312, 37994, 38722, 38728, 38724,
michael@0 9598 38854, 39024, 39519, 39714, 39768, 40031, {f: 2, c: 40441},
michael@0 9599 {f: 2, c: 40572}, 40711, 40823, 40818, 24307, 27414, 28771, 31852, 31854,
michael@0 9600 34875, 35264, 36513, 37313, 38002, 38000, 39025, 39262, 39638, 39715,
michael@0 9601 40652, 28772, 30682, 35738, 38007, 38857, 39522, 39525, 32412, 35740,
michael@0 9602 36522, 37317, {f: 2, c: 38013}, 38012, {f: 2, c: 40055}, 40695, 35924,
michael@0 9603 38015, 40474, 29224, 39530, 39729, 40475, 40478, 31858, 20034, 20060,
michael@0 9604 [12048, 20981], [12053, 21274], [12058, 21378], 19975, 19980, 20039, 20109,
michael@0 9605 [12062, 22231], [12076, 23662], [12091, 24435], 19983, 20871, 19982, 20014,
michael@0 9606 20115, 20162, 20169, 20168, 20888, 21244, 21356, 21433, 22304, 22787,
michael@0 9607 22828, [23568, 60417], 24063, 26081, [12110, 27571], 27596, [12115, 27668],
michael@0 9608 [12121, 29247], 20017, 20028, 20200, 20188, 20201, 20193, 20189, 20186,
michael@0 9609 21004, 21001, 21276, 21324, {f: 2, c: 22306}, 22807, 22831, 23425, 23428,
michael@0 9610 23570, 23611, 23668, 23667, 24068, 24192, 24194, 24521, 25097, 25168,
michael@0 9611 27669, 27702, 27715, 27711, 27707, 29358, 29360, 29578, [12145, 31160],
michael@0 9612 32906, 38430, 20238, 20248, 20268, 20213, 20244, 20209, 20224, 20215,
michael@0 9613 20232, 20253, 20226, 20229, 20258, 20243, 20228, 20212, 20242, 20913,
michael@0 9614 21011, 21008, 21158, 21282, 21279, 21325, 21386, 21511, 22241, 22239,
michael@0 9615 22318, 22314, 22324, 22844, 22912, 22908, 22917, 22907, 22910, 22903,
michael@0 9616 22911, 23382, 23573, 23589, 23676, {f: 2, c: 23674}, 23678, 24031,
michael@0 9617 [24181, 57646], 24196, 24322, 24346, 24436, 24533, 24532, 24527, 25180,
michael@0 9618 25182, 25188, 25185, 25190, 25186, 25177, 25184, 25178, 25189, 25911,
michael@0 9619 26095, 26094, 26430, 26425, 26424, 26427, 26426, 26431, 26428, 26419,
michael@0 9620 27672, 27718, 27730, 27740, 27727, [27722, 60796], 27732, {f: 2, c: 27723},
michael@0 9621 28785, 29278, {f: 2, c: 29364}, 29582, 29994, 30335, 31349, [12153, 32593],
michael@0 9622 [12171, 33400], 33404, 33408, 33405, 33407, [12172, 34381], [12177, 35198],
michael@0 9623 37017, [37015, 59347], 37016, 37019, 37012, 38434, 38436, 38432, 38435,
michael@0 9624 20310, 20283, 20322, 20297, 20307, 20324, 20286, 20327, 20306, 20319,
michael@0 9625 20289, 20312, 20269, 20275, 20287, 20321, 20879, 20921, 21020, 21022,
michael@0 9626 21025, {f: 2, c: 21165}, 21257, 21347, 21362, {f: 2, c: 21390}, 21552,
michael@0 9627 21559, 21546, 21588, 21573, 21529, 21532, 21541, 21528, 21565, 21583,
michael@0 9628 21569, 21544, 21540, 21575, 22254, 22247, 22245, 22337, 22341, 22348,
michael@0 9629 22345, 22347, 22354, 22790, 22848, 22950, 22936, 22944, 22935, 22926,
michael@0 9630 22946, 22928, 22927, 22951, 22945, 23438, 23442, 23592, 23594, 23693,
michael@0 9631 23695, 23688, 23691, 23689, 23698, 23690, 23686, 23699, 23701, 24032,
michael@0 9632 24074, 24078, 24203, 24201, 24204, 24200, 24205, 24325, 24349, 24440,
michael@0 9633 24438, 24530, 24529, 24528, 24557, 24552, 24558, 24563, 24545, 24548,
michael@0 9634 24547, 24570, 24559, 24567, 24571, 24576, 24564, 25146, 25219, 25228,
michael@0 9635 {f: 2, c: 25230}, 25236, 25223, 25201, 25211, 25210, 25200, 25217, 25224,
michael@0 9636 25207, 25213, 25202, 25204, 26096, 26100, 26099, 26098, 26101, 26437,
michael@0 9637 26439, 26457, 26453, 26444, 26440, 26461, 26445, 26458, 26443, 27600,
michael@0 9638 {f: 2, c: 27673}, 27768, 27751, 27755, 27780, 27787, 27791, 27761, 27759,
michael@0 9639 27753, 27802, 27757, 27783, 27797, [27804, 57900], 27750, 27763, 27749,
michael@0 9640 27771, 27790, 28788, 28794, 29283, 29375, 29373, 29379, 29382, 29377,
michael@0 9641 29370, 29381, 29589, 29591, {f: 2, c: 29587}, 29586, 30010, 30009,
michael@0 9642 {f: 2, c: 30100}, 30337, 31037, 32820, 32917, 32921, 32912, 32914, 32924,
michael@0 9643 33424, 33423, 33413, 33422, 33425, 33427, 33418, {f: 2, c: 33411},
michael@0 9644 [12184, 35960], 36809, 36799, 37023, 37025, 37029, 37022, 37031, 37024,
michael@0 9645 38448, 38440, 38447, 38445, 20019, 20376, 20348, 20357, 20349, 20352,
michael@0 9646 20359, 20342, 20340, 20361, 20356, 20343, 20300, 20375, 20330, 20378,
michael@0 9647 20345, 20353, 20344, 20368, 20380, 20372, 20382, 20370, 20354, 20373,
michael@0 9648 20331, 20334, 20894, 20924, 20926, 21045, {f: 2, c: 21042}, 21062, 21041,
michael@0 9649 21180, {f: 2, c: 21258}, 21308, 21394, 21396, 21639, 21631, 21633, 21649,
michael@0 9650 21634, 21640, 21611, 21626, 21630, 21605, 21612, 21620, 21606, 21645,
michael@0 9651 21615, 21601, 21600, 21656, 21603, 21607, 21604, 22263, 22265, 22383,
michael@0 9652 22386, 22381, 22379, 22385, 22384, 22390, 22400, 22389, 22395,
michael@0 9653 {f: 2, c: 22387}, 22370, 22376, 22397, 22796, 22853, 22965, 22970, 22991,
michael@0 9654 22990, 22962, 22988, 22977, 22966, 22972, 22979, 22998, 22961, 22973,
michael@0 9655 22976, 22984, 22964, 22983, 23394, 23397, 23443, 23445, 23620, 23623,
michael@0 9656 23726, 23716, 23712, 23733, 23727, 23720, 23724, 23711, 23715, 23725,
michael@0 9657 23714, 23722, 23719, 23709, 23717, 23734, 23728, 23718, 24087, 24084,
michael@0 9658 24089, 24360, {f: 3, c: 24354}, 24404, 24450, 24446, 24445, 24542, 24549,
michael@0 9659 24621, 24614, 24601, 24626, 24587, 24628, 24586, 24599, 24627, 24602,
michael@0 9660 24606, 24620, 24610, 24589, 24592, 24622, 24595, 24593, 24588, 24585,
michael@0 9661 24604, 25108, 25149, 25261, 25268, 25297, 25278, 25258, 25270, 25290,
michael@0 9662 25262, 25267, 25263, 25275, 25257, 25264, 25272, 25917, 26024, 26043,
michael@0 9663 26121, 26108, 26116, 26130, 26120, 26107, 26115, 26123, 26125, 26117,
michael@0 9664 26109, 26129, 26128, 26358, 26378, 26501, 26476, 26510, 26514, 26486,
michael@0 9665 26491, 26520, 26502, 26500, 26484, 26509, 26508, 26490, 26527, 26513,
michael@0 9666 26521, 26499, 26493, 26497, {f: 2, c: 26488}, 26516, 27429, 27520, 27518,
michael@0 9667 27614, 27677, 27795, 27884, 27883, 27886, 27865, 27830, 27860, 27821,
michael@0 9668 27879, 27831, 27856, 27842, 27834, 27843, 27846, 27885, 27890, 27858,
michael@0 9669 27869, 27828, 27786, 27805, 27776, 27870, 27840, 27952, 27853, 27847,
michael@0 9670 27824, 27897, 27855, 27881, 27857, 28820, 28824, 28805, 28819, 28806,
michael@0 9671 28804, 28817, 28822, 28802, 28826, 28803, 29290, 29398, 29387, 29400,
michael@0 9672 29385, 29404, 29394, 29396, 29402, 29388, 29393, 29604, 29601, 29613,
michael@0 9673 29606, 29602, 29600, 29612, 29597, 29917, 29928, {f: 2, c: 30015}, 30014,
michael@0 9674 30092, 30104, 30383, 30451, 30449, 30448, 30453, 30712, 30716, 30713,
michael@0 9675 30715, 30714, 30711, 31042, 31039, 31173, 31352, 31355, 31483, 31861,
michael@0 9676 31997, 32821, 32911, 32942, 32931, 32952, 32949, 32941, 33312, 33440,
michael@0 9677 33472, 33451, 33434, 33432, 33435, 33461, 33447, 33454, 33468, 33438,
michael@0 9678 33466, 33460, 33448, 33441, 33449, 33474, 33444, 33475, 33462, 33442,
michael@0 9679 34416, 34415, {f: 2, c: 34413}, 35926, 36818, 36811, 36819, 36813, 36822,
michael@0 9680 36821, 36823, 37042, 37044, 37039, 37043, 37040, 38457, 38461, 38460,
michael@0 9681 38458, 38467, 20429, 20421, 20435, 20402, 20425, 20427, 20417, 20436,
michael@0 9682 20444, 20441, [20411, 60346], 20403, 20443, 20423, 20438, 20410, 20416,
michael@0 9683 20409, 20460, 21060, 21065, 21184, 21186, 21309, 21372, 21399, 21398,
michael@0 9684 21401, 21400, 21690, 21665, 21677, 21669, 21711, 21699, 33549, 21687,
michael@0 9685 21678, 21718, 21686, {f: 2, c: 21701}, 21664, 21616, 21692, 21666, 21694,
michael@0 9686 21618, 21726, 21680, 22453, {f: 2, c: 22430}, 22436, 22412, 22423, 22429,
michael@0 9687 22427, 22420, 22424, 22415, 22425, 22437, 22426, 22421, 22772, 22797,
michael@0 9688 22867, 23009, 23006, 23022, 23040, 23025, 23005, 23034, 23037, 23036,
michael@0 9689 23030, 23012, 23026, 23031, 23003, 23017, 23027, 23029, 23008, 23038,
michael@0 9690 23028, 23021, 23464, 23628, 23760, 23768, 23756, 23767, 23755, 23771,
michael@0 9691 23774, 23770, 23753, 23751, 23754, 23766, {f: 2, c: 23763}, 23759, 23752,
michael@0 9692 23750, 23758, 23775, 23800, 24057, {f: 3, c: 24097}, 24096, 24100, 24240,
michael@0 9693 24228, 24226, 24219, 24227, 24229, 24327, 24366, 24406, 24454, 24631,
michael@0 9694 24633, 24660, 24690, 24670, 24645, 24659, 24647, 24649, 24667, 24652,
michael@0 9695 24640, 24642, 24671, 24612, 24644, 24664, 24678, 24686, {f: 2, c: 25154},
michael@0 9696 25295, 25357, 25355, 25333, 25358, 25347, 25323, 25337, 25359, 25356,
michael@0 9697 25336, 25334, 25344, {f: 2, c: 25363}, 25338, 25365, 25339, 25328, 25921,
michael@0 9698 25923, 26026, 26047, 26166, 26145, 26162, 26165, 26140, 26150, 26146,
michael@0 9699 26163, 26155, 26170, 26141, 26164, 26169, 26158, {f: 2, c: 26383}, 26561,
michael@0 9700 26610, 26568, 26554, 26588, 26555, 26616, 26584, 26560, 26551, 26565,
michael@0 9701 26603, 26596, 26591, 26549, 26573, 26547, 26615, 26614, 26606, 26595,
michael@0 9702 26562, 26553, 26574, 26599, 26608, 26546, 26620, 26566, 26605, 26572,
michael@0 9703 26542, 26598, 26587, 26618, {f: 2, c: 26569}, 26563, 26602, 26571, 27432,
michael@0 9704 27522, 27524, 27574, 27606, 27608, 27616, {f: 2, c: 27680}, 27944, 27956,
michael@0 9705 27949, 27935, 27964, 27967, 27922, 27914, 27866, 27955, 27908, 27929,
michael@0 9706 27962, 27930, 27921, 27904, 27933, 27970, 27905, 27928, 27959, 27907,
michael@0 9707 27919, 27968, 27911, 27936, 27948, 27912, 27938, 27913, 27920, 28855,
michael@0 9708 28831, 28862, 28849, 28848, 28833, {f: 2, c: 28852}, 28841, 29249,
michael@0 9709 {f: 2, c: 29257}, 29292, 29296, 29299, 29294, 29386, 29412, 29416, 29419,
michael@0 9710 29407, 29418, 29414, 29411, 29573, 29644, 29634, 29640, 29637, 29625,
michael@0 9711 29622, 29621, 29620, 29675, 29631, 29639, 29630, 29635, 29638, 29624,
michael@0 9712 29643, 29932, 29934, 29998, {f: 2, c: 30023}, 30119, 30122, 30329, 30404,
michael@0 9713 30472, {f: 3, c: 30467}, 30474, 30455, 30459, 30458, {f: 2, c: 30695},
michael@0 9714 30726, {f: 2, c: 30737}, 30725, 30736, 30735, 30734, [30729, 58095], 30723,
michael@0 9715 30739, 31050, 31052, 31051, 31045, 31044, 31189, 31181, 31183, 31190,
michael@0 9716 31182, 31360, 31358, 31441, {f: 2, c: 31488}, 31866, {f: 2, c: 31864},
michael@0 9717 {f: 3, c: 31871}, 32003, 32008, 32001, 32600, 32657, 32653, 32702, 32775,
michael@0 9718 {f: 2, c: 32782}, 32788, 32823, 32984, 32967, 32992, 32977, 32968, 32962,
michael@0 9719 32976, 32965, 32995, 32985, 32988, 32970, 32981, 32969, 32975, 32983,
michael@0 9720 32998, 32973, 33279, 33313, 33428, 33497, 33534, 33529, 33543, 33512,
michael@0 9721 33536, 33493, 33594, 33515, 33494, 33524, 33516, 33505, 33522, 33525,
michael@0 9722 33548, 33531, 33526, 33520, 33514, 33508, 33504, 33530, 33523, 33517,
michael@0 9723 34423, 34420, 34428, 34419, 34881, 34894, 34919, 34922, 34921, 35283,
michael@0 9724 35332, 35335, 36210, 36835, 36833, 36846, 36832, 37105, 37053, 37055,
michael@0 9725 37077, 37061, 37054, 37063, 37067, 37064, [37332, 60294], 37331, 38484,
michael@0 9726 38479, 38481, 38483, 38474, 38478, 20510, 20485, 20487, 20499, 20514,
michael@0 9727 20528, 20507, 20469, 20468, 20531, 20535, 20524, {f: 2, c: 20470}, 20503,
michael@0 9728 20508, 20512, 20519, 20533, 20527, 20529, 20494, 20826, 20884, 20883,
michael@0 9729 20938, {f: 2, c: 20932}, 20936, 20942, 21089, 21082, 21074,
michael@0 9730 {f: 2, c: 21086}, 21077, 21090, 21197, 21262, 21406, 21798, 21730, 21783,
michael@0 9731 21778, 21735, 21747, 21732, 21786, 21759, 21764, 21768, 21739, 21777,
michael@0 9732 21765, 21745, 21770, 21755, {f: 2, c: 21751}, 21728, 21774, 21763, 21771,
michael@0 9733 {f: 2, c: 22273}, 22476, 22578, 22485, 22482, 22458, 22470, 22461, 22460,
michael@0 9734 22456, 22454, 22463, 22471, 22480, 22457, 22465, 22798, 22858, 23065,
michael@0 9735 23062, {f: 2, c: 23085}, 23061, 23055, 23063, 23050, 23070, 23091, 23404,
michael@0 9736 23463, 23469, 23468, 23555, 23638, 23636, 23788, 23807, 23790, 23793,
michael@0 9737 23799, 23808, 23801, 24105, 24104, 24232, 24238, 24234, 24236, 24371,
michael@0 9738 24368, 24423, 24669, 24666, 24679, 24641, 24738, 24712, 24704, 24722,
michael@0 9739 24705, 24733, 24707, 24725, 24731, 24727, 24711, 24732, 24718, 25113,
michael@0 9740 25158, 25330, 25360, 25430, 25388, {f: 2, c: 25412}, 25398, 25411, 25572,
michael@0 9741 25401, 25419, 25418, 25404, 25385, 25409, 25396, 25432, 25428, 25433,
michael@0 9742 25389, 25415, 25395, 25434, 25425, 25400, 25431, 25408, 25416, 25930,
michael@0 9743 25926, 26054, {f: 2, c: 26051}, 26050, 26186, 26207, 26183, 26193,
michael@0 9744 {f: 2, c: 26386}, 26655, 26650, 26697, {f: 2, c: 26674}, 26683, 26699,
michael@0 9745 26703, 26646, 26673, 26652, 26677, 26667, 26669, 26671, 26702, 26692,
michael@0 9746 26676, 26653, 26642, 26644, 26662, 26664, 26670, 26701, 26682, 26661,
michael@0 9747 26656, 27436, 27439, 27437, 27441, 27444, 27501, 32898, 27528, 27622,
michael@0 9748 27620, 27624, 27619, 27618, 27623, 27685, 28026, {f: 2, c: 28003}, 28022,
michael@0 9749 27917, 28001, 28050, 27992, 28002, 28013, 28015, 28049, 28045, 28143,
michael@0 9750 28031, 28038, 27998, [28007, 59078], 28000, 28055, 28016, 28028, 27999,
michael@0 9751 28034, 28056, 27951, 28008, 28043, 28030, 28032, 28036, 27926, 28035,
michael@0 9752 28027, 28029, 28021, 28048, 28892, 28883, 28881, 28893, 28875, 32569,
michael@0 9753 28898, 28887, 28882, 28894, 28896, 28884, 28877, {f: 3, c: 28869}, 28890,
michael@0 9754 28878, 28897, 29250, 29304, 29303, 29302, 29440, 29434, 29428, 29438,
michael@0 9755 29430, 29427, 29435, 29441, 29651, 29657, 29669, 29654, 29628, 29671,
michael@0 9756 29667, 29673, 29660, 29650, 29659, 29652, 29661, 29658, {f: 2, c: 29655},
michael@0 9757 29672, {f: 2, c: 29918}, {f: 2, c: 29940}, 29985, 30043, 30047, 30128,
michael@0 9758 30145, 30139, 30148, 30144, 30143, 30134, 30138, 30346, 30409, 30493,
michael@0 9759 30491, 30480, 30483, 30482, 30499, 30481, 30485, {f: 2, c: 30489}, 30498,
michael@0 9760 30503, 30755, 30764, 30754, 30773, 30767, 30760, 30766, 30763, 30753,
michael@0 9761 30761, 30771, 30762, 30769, 31060, 31067, 31055, 31068, 31059, 31058,
michael@0 9762 31057, {f: 2, c: 31211}, 31200, 31214, 31213, 31210, 31196, 31198, 31197,
michael@0 9763 31366, 31369, 31365, {f: 2, c: 31371}, 31370, 31367, 31448, 31504, 31492,
michael@0 9764 31507, 31493, 31503, 31496, 31498, 31502, 31497, 31506, 31876, 31889,
michael@0 9765 31882, 31884, 31880, 31885, 31877, 32030, 32029, 32017, 32014, 32024,
michael@0 9766 32022, 32019, 32031, 32018, 32015, 32012, 32604, 32609, 32606, 32608,
michael@0 9767 32605, 32603, 32662, 32658, 32707, 32706, 32704, 32790, 32830, 32825,
michael@0 9768 33018, 33010, 33017, 33013, 33025, 33019, 33024, 33281, 33327, 33317,
michael@0 9769 33587, 33581, 33604, 33561, 33617, 33573, 33622, 33599, 33601, 33574,
michael@0 9770 33564, 33570, 33602, 33614, 33563, 33578, 33544, 33596, 33613, 33558,
michael@0 9771 33572, 33568, 33591, 33583, 33577, 33607, 33605, 33612, 33619, 33566,
michael@0 9772 33580, 33611, 33575, 33608, 34387, 34386, 34466, 34472, 34454, 34445,
michael@0 9773 34449, 34462, 34439, 34455, 34438, 34443, 34458, 34437, 34469, 34457,
michael@0 9774 34465, 34471, 34453, 34456, 34446, 34461, 34448, 34452, {f: 2, c: 34883},
michael@0 9775 34925, {f: 2, c: 34933}, 34930, 34944, 34929, 34943, 34927, 34947, 34942,
michael@0 9776 34932, 34940, 35346, 35911, 35927, 35963, 36004, 36003, 36214, 36216,
michael@0 9777 36277, 36279, 36278, 36561, 36563, 36862, 36853, 36866, 36863, 36859,
michael@0 9778 36868, 36860, 36854, 37078, 37088, {f: 2, c: 37081}, 37091, 37087, 37093,
michael@0 9779 37080, 37083, 37079, 37084, 37092, 37200, {f: 2, c: 37198}, 37333, 37346,
michael@0 9780 37338, 38492, 38495, 38588, 39139, [12221, 39647], [12223, 39727], 20095,
michael@0 9781 20592, 20586, 20577, 20574, 20576, 20563, 20555, 20573, 20594, 20552,
michael@0 9782 20557, 20545, 20571, 20554, 20578, 20501, 20549, 20575, 20585, 20587,
michael@0 9783 {f: 2, c: 20579}, 20550, 20544, 20590, 20595, 20567, 20561, 20944, 21099,
michael@0 9784 21101, 21100, 21102, 21206, 21203, 21293, 21404, {f: 2, c: 21877}, 21820,
michael@0 9785 21837, 21840, 21812, 21802, 21841, 21858, 21814, 21813, 21808, 21842,
michael@0 9786 21829, 21772, 21810, 21861, 21838, 21817, 21832, 21805, 21819, 21824,
michael@0 9787 21835, 22282, 22279, 22523, 22548, 22498, 22518, 22492, 22516, 22528,
michael@0 9788 22509, 22525, 22536, 22520, 22539, 22515, 22479, 22535, 22510, 22499,
michael@0 9789 22514, 22501, 22508, 22497, 22542, 22524, 22544, 22503, 22529, 22540,
michael@0 9790 22513, 22505, 22512, 22541, 22532, 22876, 23136, 23128, 23125,
michael@0 9791 [23143, 60437], 23134, 23096, 23093, 23149, 23120, 23135, 23141, 23148,
michael@0 9792 23123, 23140, 23127, 23107, 23133, 23122, 23108, 23131, 23112, 23182,
michael@0 9793 23102, 23117, 23097, 23116, 23152, 23145, 23111, 23121, 23126, 23106,
michael@0 9794 23132, 23410, 23406, 23489, 23488, 23641, 23838, 23819, 23837, 23834,
michael@0 9795 23840, 23820, 23848, 23821, 23846, 23845, 23823, 23856, 23826, 23843,
michael@0 9796 23839, 23854, 24126, 24116, 24241, 24244, 24249, {f: 2, c: 24242}, 24374,
michael@0 9797 24376, 24475, 24470, 24479, 24714, 24720, 24710, 24766, 24752, 24762,
michael@0 9798 {f: 2, c: 24787}, 24783, 24804, 24793, 24797, 24776, 24753, 24795, 24759,
michael@0 9799 24778, 24767, 24771, 24781, 24768, 25394, 25445, 25482, 25474, 25469,
michael@0 9800 25533, 25502, 25517, 25501, 25495, 25515, 25486, 25455, 25479, 25488,
michael@0 9801 25454, 25519, 25461, 25500, 25453, 25518, 25468, 25508, 25403, 25503,
michael@0 9802 25464, 25477, 25473, 25489, 25485, 25456, 25939, 26061, 26213, 26209,
michael@0 9803 26203, 26201, 26204, 26210, 26392, 26745, 26759, 26768, 26780,
michael@0 9804 {f: 2, c: 26733}, 26798, 26795, 26966, 26735, 26787, 26796, 26793, 26741,
michael@0 9805 26740, 26802, 26767, 26743, 26770, 26748, 26731, 26738, 26794, 26752,
michael@0 9806 26737, 26750, 26779, 26774, 26763, 26784, 26761, 26788, 26744, 26747,
michael@0 9807 26769, 26764, 26762, 26749, 27446, 27443, {f: 2, c: 27447}, 27537, 27535,
michael@0 9808 {f: 2, c: 27533}, 27532, 27690, 28096, 28075, 28084, 28083, 28276, 28076,
michael@0 9809 28137, 28130, 28087, 28150, 28116, 28160, 28104, 28128, 28127, 28118,
michael@0 9810 28094, 28133, {f: 2, c: 28124}, 28123, 28148, 28106, 28093, 28141, 28144,
michael@0 9811 28090, 28117, 28098, 28111, 28105, 28112, 28146, 28115, 28157, 28119,
michael@0 9812 28109, 28131, 28091, 28922, 28941, 28919, 28951, 28916, 28940, 28912,
michael@0 9813 28932, 28915, 28944, 28924, 28927, 28934, 28947, 28928, 28920, 28918,
michael@0 9814 28939, 28930, 28942, 29310, {f: 2, c: 29307}, 29311, 29469, 29463, 29447,
michael@0 9815 29457, 29464, 29450, 29448, 29439, 29455, 29470, 29576, 29686, 29688,
michael@0 9816 29685, 29700, 29697, 29693, 29703, 29696, 29690, 29692, 29695, 29708,
michael@0 9817 29707, 29684, 29704, 30052, 30051, 30158, 30162, 30159, {f: 2, c: 30155},
michael@0 9818 30161, 30160, 30351, 30345, 30419, 30521, 30511, 30509, {f: 2, c: 30513},
michael@0 9819 30516, 30515, 30525, 30501, 30523, 30517, 30792, 30802, 30793, 30797,
michael@0 9820 30794, 30796, 30758, 30789, 30800, 31076, 31079, {f: 2, c: 31081}, 31075,
michael@0 9821 31083, 31073, 31163, 31226, 31224, {f: 2, c: 31222}, 31375, 31380, 31376,
michael@0 9822 31541, 31547, 31540, 31525, 31536, 31522, 31524, 31539, 31512, 31530,
michael@0 9823 31517, 31537, 31531, 31533, 31535, 31538, 31544, 31514, 31523, 31892,
michael@0 9824 31896, 31894, 31907, 32053, 32061, 32056, 32054, 32058, 32069, 32044,
michael@0 9825 32041, 32065, 32071, {f: 2, c: 32062}, 32074, 32059, 32040, 32611, 32661,
michael@0 9826 {f: 2, c: 32668}, 32667, {f: 2, c: 32714}, 32717, {f: 2, c: 32720}, 32711,
michael@0 9827 32719, 32713, 32799, 32798, 32795, 32839, 32835, 32840, 33048, 33061,
michael@0 9828 33049, 33051, 33069, 33055, 33068, 33054, 33057, 33045, 33063, 33053,
michael@0 9829 33058, 33297, 33336, 33331, 33338, 33332, 33330, 33396, 33680, 33699,
michael@0 9830 33704, 33677, 33658, 33651, 33700, 33652, 33679, 33665, 33685, 33689,
michael@0 9831 33653, 33684, 33705, 33661, 33667, 33676, 33693, 33691, 33706, 33675,
michael@0 9832 33662, 33701, 33711, 33672, 33687, 33712, 33663, 33702, 33671, 33710,
michael@0 9833 33654, 34393, 34390, 34495, 34487, 34498, 34497, 34501, 34490, 34480,
michael@0 9834 34504, 34489, 34483, 34488, 34508, 34484, {f: 2, c: 34491}, 34499,
michael@0 9835 {f: 2, c: 34493}, 34898, 34953, 34965, 34984, 34978, 34986, 34970, 34961,
michael@0 9836 34977, 34975, 34968, 34983, 34969, 34971, 34967, 34980, 34988, 34956,
michael@0 9837 34963, 34958, 35202, 35286, 35289, 35285, 35376, 35367, 35372, 35358,
michael@0 9838 35897, 35899, {f: 2, c: 35932}, 35965, 36005, 36221, 36219, 36217, 36284,
michael@0 9839 36290, 36281, 36287, 36289, 36568, 36574, 36573, 36572, 36567,
michael@0 9840 {f: 2, c: 36576}, 36900, 36875, 36881, 36892, 36876, 36897, 37103, 37098,
michael@0 9841 37104, 37108, {f: 2, c: 37106}, 37076, {f: 2, c: 37099}, 37097, 37206,
michael@0 9842 37208, 37210, 37203, 37205, 37356, 37364, 37361, 37363, 37368, 37348,
michael@0 9843 37369, {f: 2, c: 37354}, 37367, 37352, 37358, 38266, 38278, 38280, 38524,
michael@0 9844 38509, 38507, 38513, 38511, 38591, 38762, 38916, 39141, 39319, 20635,
michael@0 9845 20629, 20628, 20638, 20619, 20643, 20611, 20620, 20622, 20637, 20584,
michael@0 9846 20636, 20626, 20610, 20615, 20831, 20948, 21266, 21265, 21412, 21415,
michael@0 9847 21905, 21928, 21925, 21933, 21879, 22085, 21922, 21907, 21896, 21903,
michael@0 9848 21941, 21889, 21923, 21906, 21924, 21885, 21900, 21926, 21887, 21909,
michael@0 9849 21921, 21902, 22284, 22569, 22583, 22553, 22558, 22567, 22563, 22568,
michael@0 9850 22517, 22600, 22565, 22556, 22555, 22579, 22591, 22582, 22574, 22585,
michael@0 9851 22584, 22573, 22572, 22587, 22881, 23215, 23188, 23199, 23162, 23202,
michael@0 9852 23198, 23160, 23206, 23164, 23205, 23212, 23189, 23214, 23095, 23172,
michael@0 9853 23178, 23191, 23171, 23179, 23209, 23163, 23165, 23180, 23196, 23183,
michael@0 9854 23187, 23197, 23530, 23501, 23499, 23508, 23505, 23498, 23502, 23564,
michael@0 9855 23600, 23863, 23875, 23915, 23873, 23883, 23871, 23861, 23889, 23886,
michael@0 9856 23893, 23859, 23866, 23890, 23869, 23857, 23897, 23874, 23865, 23881,
michael@0 9857 23864, 23868, 23858, 23862, 23872, 23877, 24132, 24129, [24408, 57673],
michael@0 9858 24486, 24485, 24491, 24777, 24761, 24780, 24802, 24782, 24772, 24852,
michael@0 9859 24818, 24842, 24854, 24837, 24821, 24851, 24824, 24828, 24830, 24769,
michael@0 9860 24835, 24856, 24861, 24848, 24831, 24836, 24843, 25162, 25492, 25521,
michael@0 9861 25520, 25550, 25573, 25576, 25583, 25539, 25757, 25587, 25546, 25568,
michael@0 9862 25590, 25557, 25586, 25589, 25697, 25567, 25534, 25565, 25564, 25540,
michael@0 9863 25560, 25555, 25538, 25543, 25548, 25547, 25544, 25584, 25559, 25561,
michael@0 9864 25906, 25959, 25962, 25956, 25948, 25960, 25957, 25996, {f: 2, c: 26013},
michael@0 9865 26030, 26064, 26066, 26236, 26220, 26235, 26240, 26225, 26233, 26218,
michael@0 9866 26226, 26369, 26892, 26835, 26884, 26844, 26922, 26860, 26858, 26865,
michael@0 9867 26895, 26838, 26871, 26859, 26852, 26870, 26899, 26896, 26867, 26849,
michael@0 9868 26887, 26828, 26888, 26992, 26804, 26897, 26863, 26822, 26900, 26872,
michael@0 9869 26832, 26877, 26876, 26856, 26891, 26890, 26903, 26830, 26824,
michael@0 9870 {f: 2, c: 26845}, 26854, 26868, 26833, 26886, 26836, 26857, 26901, 26917,
michael@0 9871 26823, 27449, 27451, 27455, 27452, 27540, 27543, 27545, 27541, 27581,
michael@0 9872 27632, {f: 2, c: 27634}, 27696, 28156, {f: 2, c: 28230}, 28191, 28233,
michael@0 9873 28296, {f: 2, c: 28220}, 28229, 28258, 28203, 28223, 28225, 28253, 28275,
michael@0 9874 28188, 28211, 28235, 28224, 28241, 28219, 28163, 28206, 28254, 28264,
michael@0 9875 28252, 28257, 28209, 28200, 28256, 28273, 28267, 28217, 28194, 28208,
michael@0 9876 28243, 28261, 28199, 28280, 28260, 28279, 28245, 28281, 28242, 28262,
michael@0 9877 {f: 2, c: 28213}, 28250, 28960, 28958, 28975, 28923, 28974, 28977, 28963,
michael@0 9878 28965, 28962, 28978, 28959, 28968, 28986, 28955, 29259, 29274,
michael@0 9879 {f: 2, c: 29320}, 29318, 29317, 29323, 29458, 29451, 29488, 29474, 29489,
michael@0 9880 29491, 29479, 29490, 29485, 29478, 29475, 29493, 29452, 29742, 29740,
michael@0 9881 29744, 29739, 29718, 29722, 29729, 29741, 29745, 29732, 29731, 29725,
michael@0 9882 29737, 29728, 29746, 29947, 29999, 30063, 30060, 30183, 30170, 30177,
michael@0 9883 30182, 30173, 30175, 30180, 30167, 30357, 30354, 30426, {f: 2, c: 30534},
michael@0 9884 30532, 30541, 30533, 30538, 30542, {f: 2, c: 30539}, 30686, 30700, 30816,
michael@0 9885 {f: 2, c: 30820}, 30812, 30829, 30833, 30826, 30830, 30832, 30825, 30824,
michael@0 9886 30814, 30818, 31092, 31091, 31090, 31088, 31234, 31242, 31235, 31244,
michael@0 9887 31236, 31385, 31462, 31460, 31562, 31559, 31556, 31560, 31564, 31566,
michael@0 9888 31552, 31576, 31557, 31906, 31902, 31912, 31905, 32088, 32111, 32099,
michael@0 9889 32083, 32086, 32103, 32106, 32079, 32109, 32092, 32107, 32082, 32084,
michael@0 9890 32105, 32081, 32095, 32078, {f: 2, c: 32574}, {f: 2, c: 32613}, 32674,
michael@0 9891 {f: 2, c: 32672}, 32727, 32849, {f: 2, c: 32847}, 33022, 32980, 33091,
michael@0 9892 33098, 33106, 33103, 33095, 33085, 33101, 33082, 33254, 33262,
michael@0 9893 {f: 3, c: 33271}, 33284, {f: 2, c: 33340}, 33343, 33397, 33595,
michael@0 9894 [33743, 60382], 33785, 33827, 33728, 33768, 33810, 33767, 33764, 33788,
michael@0 9895 33782, 33808, 33734, 33736, 33771, 33763, 33727, 33793, 33757, 33765,
michael@0 9896 33752, 33791, 33761, 33739, 33742, 33750, 33781, 33737, 33801,
michael@0 9897 [33807, 58332], 33758, 33809, 33798, 33730, 33779, 33749, 33786, 33735,
michael@0 9898 33745, 33770, 33811, 33690, 33731, 33772, 33774, 33732, 33787, 33751,
michael@0 9899 33762, 33819, 33755, 33790, 34520, 34530, 34534, 34515, 34531, 34522,
michael@0 9900 34538, 34525, 34539, 34524, 34540, 34537, 34519, 34536, 34513, 34888,
michael@0 9901 34902, 34901, 35002, 35031, 35001, 35000, 35008, 35006, 34998, 35004,
michael@0 9902 34999, 35005, 34994, 35073, 35017, 35221, 35224, 35223, 35293,
michael@0 9903 {f: 2, c: 35290}, 35406, 35405, 35385, 35417, 35392, {f: 2, c: 35415},
michael@0 9904 {f: 2, c: 35396}, 35410, 35400, 35409, 35402, 35404, 35407, 35935, 35969,
michael@0 9905 35968, 36026, 36030, 36016, 36025, 36021, 36228, 36224, 36233, 36312,
michael@0 9906 36307, 36301, 36295, 36310, 36316, 36303, 36309, 36313, 36296, 36311,
michael@0 9907 36293, 36591, 36599, 36602, 36601, 36582, 36590, 36581, 36597,
michael@0 9908 {f: 2, c: 36583}, 36598, 36587, 36593, 36588, 36596, 36585, 36909, 36916,
michael@0 9909 36911, 37126, 37164, [37124, 60367], 37119, 37116, 37128, 37113, 37115,
michael@0 9910 37121, 37120, 37127, 37125, 37123, 37217, 37220, 37215, 37218, 37216,
michael@0 9911 37377, 37386, 37413, 37379, 37402, 37414, 37391, 37388, 37376, 37394,
michael@0 9912 37375, 37373, 37382, 37380, 37415, 37378, 37404, 37412, 37401, 37399,
michael@0 9913 37381, 37398, 38267, 38285, 38284, 38288, 38535, 38526, {f: 2, c: 38536},
michael@0 9914 38531, 38528, 38594, 38600, 38595, 38641, 38640, 38764, 38768, 38766,
michael@0 9915 38919, 39081, 39147, 40166, [12235, 40697], {f: 2, c: 20099}, 20150, 20669,
michael@0 9916 20671, 20678, 20654, 20676, 20682, 20660, 20680, 20674, 20656, 20673,
michael@0 9917 20666, 20657, 20683, 20681, 20662, 20664, 20951, 21114, 21112,
michael@0 9918 {f: 2, c: 21115}, 21955, 21979, 21964, 21968, 21963, 21962, 21981,
michael@0 9919 [21952, 64013], 21972, 21956, 21993, 21951, 21970, 21901, 21967, 21973,
michael@0 9920 21986, 21974, 21960, 22002, 21965, 21977, 21954, 22292, 22611, 22632,
michael@0 9921 22628, 22607, 22605, 22601, 22639, 22613, 22606, 22621, 22617, 22629,
michael@0 9922 22619, 22589, 22627, 22641, 22780, 23239, 23236, 23243, 23226, 23224,
michael@0 9923 23217, 23221, 23216, 23231, 23240, 23227, 23238, 23223, 23232, 23242,
michael@0 9924 23220, 23222, 23245, 23225, 23184, 23510, {f: 2, c: 23512}, 23583, 23603,
michael@0 9925 23921, 23907, 23882, 23909, 23922, 23916, 23902, 23912, 23911, 23906,
michael@0 9926 24048, 24143, 24142, 24138, 24141, 24139, 24261, 24268, 24262, 24267,
michael@0 9927 24263, 24384, 24495, 24493, 24823, {f: 2, c: 24905}, 24875, 24901, 24886,
michael@0 9928 24882, 24878, 24902, 24879, 24911, 24873, 24896, 25120, 37224, 25123,
michael@0 9929 25125, 25124, 25541, 25585, 25579, 25616, 25618, 25609, 25632, 25636,
michael@0 9930 25651, 25667, 25631, 25621, 25624, 25657, 25655, {f: 2, c: 25634}, 25612,
michael@0 9931 25638, 25648, 25640, 25665, 25653, 25647, 25610, 25626, 25664, 25637,
michael@0 9932 25639, 25611, 25575, 25627, 25646, 25633, 25614, 25967, 26002, 26067,
michael@0 9933 26246, 26252, 26261, 26256, 26251, 26250, 26265, 26260, 26232, 26400,
michael@0 9934 26982, 26975, 26936, 26958, 26978, 26993, 26943, 26949, 26986, 26937,
michael@0 9935 26946, 26967, 26969, 27002, {f: 2, c: 26952}, 26933, 26988, 26931, 26941,
michael@0 9936 26981, 26864, 27000, 26932, 26985, 26944, 26991, 26948, 26998, 26968,
michael@0 9937 26945, 26996, 26956, 26939, 26955, 26935, 26972, 26959, 26961, 26930,
michael@0 9938 26962, 26927, 27003, 26940, 27462, 27461, 27459, 27458, 27464, 27457,
michael@0 9939 27547, {f: 2, c: 27643}, 27641, {f: 2, c: 27639}, 28315, 28374, 28360,
michael@0 9940 28303, 28352, 28319, {f: 2, c: 28307}, 28320, 28337, 28345, 28358, 28370,
michael@0 9941 28349, 28353, 28318, 28361, 28343, 28336, 28365, 28326, 28367, 28338,
michael@0 9942 28350, 28355, 28380, 28376, 28313, 28306, 28302, 28301, 28324, 28321,
michael@0 9943 28351, 28339, 28368, 28362, 28311, 28334, 28323, 28999, 29012, 29010,
michael@0 9944 29027, 29024, 28993, 29021, [29026, 61080], 29042, 29048, 29034, 29025,
michael@0 9945 28994, 29016, 28995, 29003, 29040, 29023, 29008, 29011, 28996, 29005,
michael@0 9946 29018, 29263, 29325, 29324, 29329, 29328, 29326, 29500, 29506, 29499,
michael@0 9947 29498, 29504, 29514, 29513, 29764, {f: 2, c: 29770}, 29778, 29777, 29783,
michael@0 9948 29760, {f: 2, c: 29775}, 29774, 29762, 29766, 29773, 29780, 29921, 29951,
michael@0 9949 29950, 29949, 29981, 30073, 30071, 27011, 30191, 30223, 30211, 30199,
michael@0 9950 30206, 30204, [30201, 60782], 30200, 30224, 30203, 30198, 30189, 30197,
michael@0 9951 30205, 30361, 30389, 30429, 30549, {f: 2, c: 30559}, 30546, 30550, 30554,
michael@0 9952 30569, 30567, 30548, 30553, 30573, 30688, 30855, 30874, 30868, 30863,
michael@0 9953 30852, 30869, {f: 2, c: 30853}, 30881, 30851, 30841, 30873, 30848, 30870,
michael@0 9954 30843, 31100, 31106, 31101, 31097, 31249, {f: 2, c: 31256}, 31250, 31255,
michael@0 9955 31253, 31266, 31251, 31259, 31248, 31395, 31394, 31390, 31467, 31590,
michael@0 9956 31588, 31597, 31604, 31593, 31602, 31589, 31603, 31601, 31600, 31585,
michael@0 9957 31608, 31606, 31587, 31922, 31924, 31919, 32136, 32134, 32128, 32141,
michael@0 9958 32127, 32133, 32122, 32142, 32123, 32131, 32124, 32140, 32148, 32132,
michael@0 9959 32125, 32146, 32621, 32619, {f: 2, c: 32615}, 32620, 32678, 32677, 32679,
michael@0 9960 {f: 2, c: 32731}, 32801, 33124, 33120, 33143, 33116, 33129, 33115, 33122,
michael@0 9961 33138, 26401, 33118, 33142, 33127, 33135, 33092, 33121, 33309, 33353,
michael@0 9962 33348, 33344, 33346, 33349, 34033, 33855, 33878, 33910, 33913, 33935,
michael@0 9963 33933, 33893, 33873, 33856, 33926, 33895, 33840, 33869, 33917, 33882,
michael@0 9964 33881, 33908, 33907, 33885, 34055, 33886, 33847, 33850, 33844, 33914,
michael@0 9965 33859, 33912, 33842, 33861, 33833, 33753, 33867, 33839, 33858, 33837,
michael@0 9966 33887, 33904, 33849, 33870, 33868, 33874, 33903, 33989, 33934, 33851,
michael@0 9967 33863, 33846, 33843, 33896, 33918, 33860, 33835, 33888, 33876, 33902,
michael@0 9968 33872, 34571, 34564, 34551, 34572, 34554, 34518, 34549, 34637, 34552,
michael@0 9969 34574, 34569, 34561, 34550, 34573, 34565, 35030, 35019, {f: 2, c: 35021},
michael@0 9970 35038, 35035, 35034, 35020, 35024, 35205, 35227, 35295, 35301, 35300,
michael@0 9971 35297, 35296, 35298, 35292, 35302, 35446, 35462, 35455, 35425, 35391,
michael@0 9972 35447, 35458, 35460, 35445, 35459, 35457, 35444, 35450, 35900, 35915,
michael@0 9973 35914, 35941, 35940, 35942, 35974, {f: 2, c: 35972}, 36044,
michael@0 9974 {f: 2, c: 36200}, 36241, 36236, {f: 2, c: 36238}, 36237, {f: 2, c: 36243},
michael@0 9975 36240, 36242, 36336, 36320, 36332, 36337, 36334, 36304, 36329, 36323,
michael@0 9976 36322, 36327, 36338, 36331, 36340, 36614, 36607, 36609, 36608, 36613,
michael@0 9977 {f: 2, c: 36615}, 36610, [36619, 60507], 36946, 36927, 36932, 36937, 36925,
michael@0 9978 37136, 37133, 37135, 37137, 37142, 37140, 37131, 37134, {f: 2, c: 37230},
michael@0 9979 37448, 37458, 37424, 37434, 37478, 37427, 37477, 37470, 37507, 37422,
michael@0 9980 37450, 37446, 37485, 37484, 37455, 37472, 37479, 37487, 37430, 37473,
michael@0 9981 37488, 37425, 37460, 37475, 37456, 37490, 37454, 37459, 37452, 37462,
michael@0 9982 37426, 38303, 38300, 38302, 38299, {f: 2, c: 38546}, 38545, 38551, 38606,
michael@0 9983 38650, 38653, 38648, 38645, 38771, {f: 2, c: 38775}, 38770, 38927,
michael@0 9984 {f: 2, c: 38925}, 39084, 39158, 39161, 39343, 39346, 39344, 39349, 39597,
michael@0 9985 39595, 39771, 40170, 40173, 40167, 40576, [12236, 40701], 20710, 20692,
michael@0 9986 20695, 20712, 20723, 20699, 20714, 20701, 20708, 20691, 20716, 20720,
michael@0 9987 20719, 20707, 20704, 20952, {f: 2, c: 21120}, 21225, 21227, 21296, 21420,
michael@0 9988 22055, 22037, 22028, 22034, 22012, 22031, 22044, 22017, 22035, 22018,
michael@0 9989 22010, 22045, 22020, 22015, 22009, 22665, 22652, 22672, 22680, 22662,
michael@0 9990 22657, 22655, 22644, 22667, 22650, 22663, 22673, 22670, 22646, 22658,
michael@0 9991 22664, 22651, 22676, 22671, 22782, 22891, 23260, 23278, 23269, 23253,
michael@0 9992 23274, 23258, 23277, 23275, 23283, 23266, 23264, 23259, 23276, 23262,
michael@0 9993 23261, 23257, 23272, 23263, 23415, 23520, 23523, 23651, 23938, 23936,
michael@0 9994 23933, 23942, 23930, 23937, 23927, 23946, 23945, 23944, 23934, 23932,
michael@0 9995 23949, 23929, 23935, {f: 2, c: 24152}, 24147, 24280, 24273, 24279, 24270,
michael@0 9996 24284, 24277, 24281, 24274, 24276, 24388, 24387, 24431, 24502, 24876,
michael@0 9997 24872, 24897, 24926, 24945, 24947, {f: 2, c: 24914}, 24946, 24940, 24960,
michael@0 9998 24948, 24916, 24954, 24923, 24933, 24891, 24938, 24929, 24918, 25129,
michael@0 9999 25127, 25131, 25643, 25677, 25691, 25693, 25716, 25718, {f: 2, c: 25714},
michael@0 10000 25725, 25717, 25702, 25766, 25678, 25730, 25694, 25692, 25675, 25683,
michael@0 10001 25696, 25680, 25727, 25663, 25708, 25707, 25689, 25701, 25719, 25971,
michael@0 10002 26016, 26273, 26272, 26271, 26373, 26372, 26402, 27057, 27062, 27081,
michael@0 10003 27040, 27086, 27030, 27056, 27052, 27068, 27025, 27033, 27022, 27047,
michael@0 10004 27021, 27049, 27070, 27055, 27071, 27076, 27069, 27044, 27092, 27065,
michael@0 10005 27082, 27034, 27087, 27059, 27027, 27050, 27041, 27038, 27097, 27031,
michael@0 10006 27024, 27074, 27061, 27045, 27078, 27466, 27469, 27467, {f: 3, c: 27550},
michael@0 10007 {f: 2, c: 27587}, 27646, 28366, 28405, 28401, 28419, 28453, 28408, 28471,
michael@0 10008 28411, 28462, 28425, 28494, {f: 2, c: 28441}, 28455, 28440, 28475, 28434,
michael@0 10009 28397, 28426, 28470, 28531, 28409, 28398, 28461, 28480, 28464, 28476,
michael@0 10010 28469, 28395, 28423, 28430, 28483, 28421, 28413, 28406, 28473, 28444,
michael@0 10011 28412, 28474, 28447, 28429, 28446, 28424, 28449, 29063, 29072, 29065,
michael@0 10012 29056, 29061, 29058, 29071, 29051, 29062, 29057, 29079, 29252, 29267,
michael@0 10013 29335, 29333, 29331, 29507, 29517, 29521, 29516, 29794, 29811, 29809,
michael@0 10014 29813, 29810, 29799, 29806, 29952, {f: 2, c: 29954}, 30077, 30096, 30230,
michael@0 10015 30216, 30220, 30229, 30225, 30218, 30228, 30392, 30593, 30588, 30597,
michael@0 10016 30594, 30574, 30592, 30575, 30590, 30595, 30898, 30890, 30900, 30893,
michael@0 10017 30888, 30846, 30891, 30878, 30885, 30880, 30892, 30882, 30884, 31128,
michael@0 10018 {f: 2, c: 31114}, 31126, 31125, 31124, 31123, 31127, 31112, 31122, 31120,
michael@0 10019 31275, 31306, 31280, 31279, 31272, 31270, 31400, {f: 2, c: 31403}, 31470,
michael@0 10020 31624, 31644, 31626, 31633, 31632, 31638, 31629, 31628, 31643, 31630,
michael@0 10021 31621, 31640, 21124, 31641, 31652, 31618, 31931, 31935, 31932, 31930,
michael@0 10022 32167, 32183, 32194, 32163, 32170, 32193, 32192, 32197, 32157, 32206,
michael@0 10023 32196, 32198, {f: 2, c: 32203}, 32175, 32185, 32150, 32188, 32159, 32166,
michael@0 10024 32174, 32169, 32161, 32201, 32627, {f: 2, c: 32738}, 32741, 32734, 32804,
michael@0 10025 32861, 32860, 33161, 33158, 33155, 33159, 33165, 33164, 33163, 33301,
michael@0 10026 33943, 33956, 33953, 33951, 33978, 33998, 33986, 33964, 33966, 33963,
michael@0 10027 33977, 33972, 33985, 33997, 33962, 33946, 33969, 34000, 33949, 33959,
michael@0 10028 33979, 33954, 33940, 33991, 33996, 33947, 33961, 33967, [33960, 58327],
michael@0 10029 34006, 33944, 33974, 33999, 33952, 34007, 34004, 34002, 34011, 33968,
michael@0 10030 33937, 34401, 34611, 34595, 34600, 34667, 34624, 34606, 34590, 34593,
michael@0 10031 34585, 34587, 34627, 34604, 34625, 34622, 34630, 34592, 34610, 34602,
michael@0 10032 34605, 34620, 34578, 34618, 34609, 34613, 34626, {f: 2, c: 34598}, 34616,
michael@0 10033 34596, 34586, 34608, 34577, 35063, 35047, {f: 2, c: 35057}, 35066, 35070,
michael@0 10034 35054, 35068, 35062, 35067, 35056, 35052, 35051, 35229, 35233, 35231,
michael@0 10035 35230, 35305, 35307, 35304, 35499, 35481, 35467, 35474, 35471, 35478,
michael@0 10036 35901, {f: 2, c: 35944}, 36053, 36047, 36055, 36246, 36361, 36354, 36351,
michael@0 10037 36365, 36349, 36362, 36355, 36359, 36358, 36357, 36350, 36352, 36356,
michael@0 10038 {f: 2, c: 36624}, 36622, 36621, 37155, 37148, 37152, 37154, 37151, 37149,
michael@0 10039 37146, 37156, 37153, 37147, 37242, 37234, 37241, 37235, 37541, 37540,
michael@0 10040 37494, 37531, 37498, 37536, 37524, 37546, 37517, 37542, 37530, 37547,
michael@0 10041 37497, 37527, 37503, 37539, 37614, 37518, 37506, 37525, 37538, 37501,
michael@0 10042 37512, 37537, 37514, 37510, 37516, 37529, 37543, 37502, 37511, 37545,
michael@0 10043 37533, 37515, 37421, 38558, 38561, 38655, 38744, 38781, 38778, 38782,
michael@0 10044 38787, 38784, 38786, 38779, 38788, 38785, 38783, 38862, 38861, 38934,
michael@0 10045 {f: 2, c: 39085}, 39170, 39168, 39175, 39325, 39324, 39363, 39353, 39355,
michael@0 10046 39354, 39362, 39357, 39367, 39601, 39651, 39655, {f: 2, c: 39742},
michael@0 10047 {f: 2, c: 39776}, 39775, {f: 2, c: 40177}, 40181, 40615, 20735, 20739,
michael@0 10048 20784, 20728, {f: 2, c: 20742}, 20726, 20734, {f: 2, c: 20747}, 20733,
michael@0 10049 20746, {f: 2, c: 21131}, 21233, 21231, 22088, 22082, 22092, 22069, 22081,
michael@0 10050 22090, 22089, 22086, 22104, 22106, 22080, 22067, 22077, 22060, 22078,
michael@0 10051 22072, 22058, 22074, 22298, 22699, 22685, 22705, 22688, 22691, 22703,
michael@0 10052 22700, 22693, 22689, 22783, 23295, 23284, 23293, 23287, 23286, 23299,
michael@0 10053 23288, 23298, 23289, 23297, 23303, 23301, 23311, 23655, 23961, 23959,
michael@0 10054 23967, 23954, 23970, 23955, 23957, 23968, 23964, 23969, 23962, 23966,
michael@0 10055 24169, 24157, 24160, 24156, 32243, 24283, 24286, 24289, 24393, 24498,
michael@0 10056 24971, 24963, 24953, 25009, 25008, 24994, 24969, 24987, 24979, 25007,
michael@0 10057 25005, 24991, 24978, 25002, 24993, 24973, 24934, 25011, 25133, 25710,
michael@0 10058 25712, 25750, 25760, 25733, 25751, 25756, 25743, 25739, 25738, 25740,
michael@0 10059 25763, 25759, 25704, 25777, 25752, 25974, 25978, 25977, 25979,
michael@0 10060 {f: 2, c: 26034}, 26293, 26288, 26281, 26290, 26295, 26282, 26287, 27136,
michael@0 10061 27142, 27159, 27109, 27128, 27157, 27121, 27108, 27168, 27135, 27116,
michael@0 10062 27106, 27163, 27165, 27134, 27175, 27122, 27118, 27156, 27127, 27111,
michael@0 10063 27200, 27144, 27110, 27131, 27149, 27132, 27115, 27145, 27140, 27160,
michael@0 10064 27173, 27151, 27126, 27174, 27143, 27124, 27158, 27473, 27557, 27555,
michael@0 10065 27554, 27558, 27649, 27648, 27647, 27650, 28481, 28454, 28542, 28551,
michael@0 10066 28614, 28562, 28557, 28553, 28556, 28514, 28495, 28549, 28506, 28566,
michael@0 10067 28534, 28524, 28546, 28501, 28530, 28498, 28496, 28503, 28564, 28563,
michael@0 10068 28509, 28416, 28513, 28523, 28541, 28519, 28560, 28499, 28555, 28521,
michael@0 10069 28543, 28565, 28515, 28535, 28522, 28539, 29106, 29103, 29083, 29104,
michael@0 10070 29088, 29082, 29097, 29109, 29085, 29093, 29086, 29092, 29089, 29098,
michael@0 10071 29084, 29095, 29107, 29336, 29338, 29528, 29522, {f: 3, c: 29534}, 29533,
michael@0 10072 29531, 29537, 29530, 29529, 29538, 29831, {f: 2, c: 29833}, 29830, 29825,
michael@0 10073 29821, 29829, 29832, 29820, [29817, 58868], 29960, 29959, 30078, 30245,
michael@0 10074 30238, 30233, 30237, 30236, 30243, 30234, 30248, 30235, {f: 3, c: 30364},
michael@0 10075 30363, 30605, 30607, 30601, 30600, 30925, 30907, 30927, 30924, 30929,
michael@0 10076 30926, 30932, 30920, {f: 2, c: 30915}, 30921, 31130, 31137, 31136, 31132,
michael@0 10077 31138, [31131, 59175], 27510, 31289, 31410, 31412, 31411, 31671, 31691,
michael@0 10078 31678, 31660, 31694, 31663, 31673, 31690, 31669, 31941, 31944, 31948,
michael@0 10079 31947, 32247, 32219, 32234, 32231, 32215, 32225, 32259, 32250, 32230,
michael@0 10080 32246, 32241, 32240, 32238, 32223, 32630, 32684, 32688, 32685, 32749,
michael@0 10081 32747, 32746, 32748, 32742, 32744, 32868, 32871, 33187, 33183, 33182,
michael@0 10082 33173, 33186, 33177, 33175, 33302, 33359, 33363, 33362, 33360, 33358,
michael@0 10083 33361, 34084, 34107, 34063, 34048, 34089, 34062, 34057, 34061, 34079,
michael@0 10084 34058, 34087, 34076, 34043, 34091, 34042, 34056, 34060, 34036, 34090,
michael@0 10085 34034, 34069, 34039, 34027, 34035, 34044, 34066, 34026, 34025, 34070,
michael@0 10086 34046, 34088, 34077, 34094, 34050, 34045, 34078, 34038, 34097, 34086,
michael@0 10087 {f: 2, c: 34023}, 34032, 34031, 34041, 34072, 34080, 34096, 34059, 34073,
michael@0 10088 34095, 34402, 34646, {f: 2, c: 34659}, 34679, 34785, 34675, 34648, 34644,
michael@0 10089 34651, 34642, 34657, 34650, 34641, 34654, 34669, 34666, 34640, 34638,
michael@0 10090 34655, 34653, 34671, 34668, 34682, 34670, 34652, 34661, 34639, 34683,
michael@0 10091 34677, 34658, 34663, 34665, 34906, 35077, 35084, 35092, 35083,
michael@0 10092 {f: 3, c: 35095}, 35078, 35094, 35089, 35086, 35081, 35234, 35236, 35235,
michael@0 10093 35309, 35312, 35308, 35535, 35526, 35512, 35539, 35537, {f: 2, c: 35540},
michael@0 10094 35515, 35543, 35518, 35520, 35525, 35544, 35523, 35514, 35517, 35545,
michael@0 10095 35902, 35917, 35983, 36069, 36063, 36057, 36072, 36058, 36061, 36071,
michael@0 10096 36256, 36252, 36257, 36251, 36384, 36387, 36389, 36388, 36398, 36373,
michael@0 10097 36379, 36374, 36369, 36377, {f: 2, c: 36390}, 36372, 36370, 36376, 36371,
michael@0 10098 36380, 36375, 36378, 36652, 36644, 36632, 36634, 36640, 36643,
michael@0 10099 {f: 2, c: 36630}, 36979, 36976, 36975, 36967, 36971, 37167, 37163,
michael@0 10100 {f: 2, c: 37161}, 37170, 37158, 37166, {f: 2, c: 37253}, 37258,
michael@0 10101 {f: 2, c: 37249}, 37252, 37248, 37584, {f: 2, c: 37571}, 37568, 37593,
michael@0 10102 37558, 37583, 37617, 37599, 37592, 37609, 37591, 37597, 37580, 37615,
michael@0 10103 37570, 37608, 37578, 37576, 37582, 37606, 37581, 37589, 37577, 37600,
michael@0 10104 37598, 37607, 37585, 37587, 37557, 37601, 37669, 37574, 37556, 38268,
michael@0 10105 38316, 38315, 38318, 38320, 38564, 38562, 38611, 38661, 38664, 38658,
michael@0 10106 38746, 38794, 38798, 38792, 38864, 38863, 38942, 38941, 38950, 38953,
michael@0 10107 38952, 38944, 38939, 38951, 39090, 39176, 39162, 39185, 39188,
michael@0 10108 {f: 2, c: 39190}, 39189, 39388, 39373, 39375, {f: 2, c: 39379}, 39374,
michael@0 10109 39369, [39382, 60270], 39384, 39371, 39383, 39372, 39603, 39660, 39659,
michael@0 10110 39667, 39666, 39665, 39750, 39747, 39783, 39796, 39793, 39782, 39798,
michael@0 10111 39797, 39792, 39784, 39780, 39788, 40188, 40186, 40189, 40191, 40183,
michael@0 10112 40199, 40192, 40185, 40187, 40200, 40197, 40196, 40579, 40659,
michael@0 10113 {f: 2, c: 40719}, 20764, 20755, 20759, 20762, 20753, 20958, 21300, 21473,
michael@0 10114 22128, 22112, 22126, 22131, 22118, 22115, 22125, 22130, 22110, 22135,
michael@0 10115 22300, 22299, 22728, 22717, 22729, 22719, 22714, 22722, 22716, 22726,
michael@0 10116 23319, 23321, 23323, 23329, 23316, 23315, 23312, 23318, [23336, 59539],
michael@0 10117 23322, 23328, 23326, 23535, 23980, 23985, 23977, 23975, 23989, 23984,
michael@0 10118 23982, 23978, 23976, 23986, 23981, 23983, 23988, {f: 2, c: 24167}, 24166,
michael@0 10119 24175, 24297, 24295, 24294, 24296, 24293, 24395, 24508, 24507, 24989,
michael@0 10120 25000, 24982, 25029, 25012, 25030, 25025, 25036, 25018, 25023, 25016,
michael@0 10121 24972, 25815, 25814, 25808, 25807, 25801, 25789, 25737, 25795, 25819,
michael@0 10122 25843, 25817, 25907, 25983, 25980, 26018, 26312, 26302, 26304,
michael@0 10123 {f: 2, c: 26314}, 26319, 26301, 26299, 26298, 26316, 26403, 27188, 27238,
michael@0 10124 27209, 27239, 27186, 27240, 27198, 27229, 27245, 27254, 27227, 27217,
michael@0 10125 27176, 27226, 27195, 27199, 27201, 27242, 27236, 27216, 27215, 27220,
michael@0 10126 27247, 27241, 27232, 27196, 27230, 27222, 27221, {f: 2, c: 27213}, 27206,
michael@0 10127 27477, 27476, 27478, 27559, {f: 2, c: 27562}, 27592, 27591, 27652, 27651,
michael@0 10128 27654, 28589, 28619, 28579, 28615, 28604, 28622, 28616, 28510, 28612,
michael@0 10129 28605, 28574, 28618, 28584, 28676, 28581, 28590, 28602, 28588, 28586,
michael@0 10130 28623, 28607, 28600, 28578, 28617, 28587, 28621, 28591, 28594, 28592,
michael@0 10131 29125, 29122, 29119, 29112, 29142, {f: 2, c: 29120}, 29131, 29140, 29130,
michael@0 10132 29127, 29135, 29117, 29144, 29116, 29126, {f: 2, c: 29146},
michael@0 10133 {f: 2, c: 29341}, 29545, {f: 2, c: 29542}, 29548, 29541, 29547, 29546,
michael@0 10134 29823, 29850, 29856, 29844, 29842, 29845, 29857, 29963, 30080, 30255,
michael@0 10135 30253, 30257, 30269, 30259, 30268, 30261, 30258, 30256, 30395, 30438,
michael@0 10136 30618, 30621, 30625, 30620, 30619, {f: 2, c: 30626}, 30613, 30617, 30615,
michael@0 10137 30941, 30953, 30949, 30954, 30942, 30947, 30939, {f: 2, c: 30945}, 30957,
michael@0 10138 {f: 2, c: 30943}, 31140, 31300, 31304, 31303, 31414, 31416, 31413, 31409,
michael@0 10139 31415, 31710, 31715, 31719, 31709, 31701, 31717, 31706, 31720, 31737,
michael@0 10140 31700, 31722, 31714, 31708, 31723, 31704, 31711, 31954, 31956, 31959,
michael@0 10141 {f: 2, c: 31952}, 32274, 32289, 32279, 32268, {f: 2, c: 32287}, 32275,
michael@0 10142 32270, 32284, 32277, 32282, 32290, 32267, 32271, 32278, 32269, 32276,
michael@0 10143 32293, 32292, 32579, {f: 2, c: 32635}, 32634, 32689, 32751, 32810, 32809,
michael@0 10144 32876, 33201, 33190, 33198, 33209, 33205, 33195, 33200, 33196, 33204,
michael@0 10145 33202, 33207, 33191, 33266, {f: 3, c: 33365}, 34134, 34117, 34155, 34125,
michael@0 10146 34131, 34145, 34136, 34112, 34118, 34148, 34113, 34146, 34116, 34129,
michael@0 10147 34119, 34147, 34110, 34139, 34161, 34126, 34158, 34165, 34133, 34151,
michael@0 10148 34144, 34188, 34150, 34141, 34132, 34149, 34156, 34403, 34405, 34404,
michael@0 10149 34724, 34715, 34703, 34711, 34707, 34706, 34696, 34689, 34710, 34712,
michael@0 10150 34681, 34695, 34723, 34693, {f: 2, c: 34704}, 34717, 34692, 34708, 34716,
michael@0 10151 34714, 34697, 35102, 35110, 35120, {f: 2, c: 35117}, 35111, 35121, 35106,
michael@0 10152 35113, 35107, 35119, 35116, 35103, 35313, 35552, 35554, 35570,
michael@0 10153 {f: 2, c: 35572}, 35549, 35604, 35556, 35551, 35568, 35528, 35550, 35553,
michael@0 10154 35560, 35583, 35567, 35579, {f: 2, c: 35985}, 35984, 36085, 36078, 36081,
michael@0 10155 36080, 36083, 36204, 36206, 36261, 36263, 36403, 36414, 36408, 36416,
michael@0 10156 36421, 36406, {f: 2, c: 36412}, 36417, 36400, 36415, 36541, [36662, 60329],
michael@0 10157 36654, 36661, 36658, 36665, 36663, 36660, 36982, 36985, 36987, 36998,
michael@0 10158 37114, 37171, {f: 2, c: 37173}, 37267, {f: 2, c: 37264}, 37261, 37263,
michael@0 10159 37671, 37662, 37640, 37663, 37638, 37647, 37754, 37688, 37692, 37659,
michael@0 10160 37667, 37650, 37633, 37702, 37677, 37646, 37645, 37579, 37661, 37626,
michael@0 10161 37651, 37625, 37623, 37684, 37634, 37668, 37631, 37673, 37689, 37685,
michael@0 10162 37674, 37652, 37644, 37643, 37630, 37641, 37632, 37627, 37654, 38332,
michael@0 10163 38349, 38334, {f: 2, c: 38329}, 38326, 38335, 38325, 38333, 38569, 38612,
michael@0 10164 38667, 38674, 38672, 38809, 38807, 38804, 38896, 38904, 38965, 38959,
michael@0 10165 38962, 39204, 39199, 39207, 39209, 39326, 39406, 39404, 39397, 39396,
michael@0 10166 39408, 39395, 39402, 39401, 39399, 39609, 39615, 39604, 39611, 39670,
michael@0 10167 39674, 39673, 39671, 39731, 39808, 39813, 39815, 39804, 39806, 39803,
michael@0 10168 39810, 39827, 39826, 39824, 39802, 39829, 39805, 39816, 40229, 40215,
michael@0 10169 40224, 40222, 40212, 40233, 40221, 40216, 40226, 40208, 40217, 40223,
michael@0 10170 40584, {f: 2, c: 40582}, 40622, 40621, {f: 2, c: 40661}, 40698, 40722,
michael@0 10171 40765, 20774, 20773, 20770, 20772, 20768, 20777, 21236, 22163,
michael@0 10172 {f: 2, c: 22156}, 22150, 22148, 22147, 22142, 22146, 22143, 22145, 22742,
michael@0 10173 22740, 22735, 22738, 23341, 23333, 23346, 23331, 23340, 23335, 23334,
michael@0 10174 23343, 23342, 23419, {f: 2, c: 23537}, 23991, 24172, 24170, 24510, 25027,
michael@0 10175 25013, 25020, 25063, 25056, 25061, 25060, 25064, 25054, 25839, 25833,
michael@0 10176 25827, 25835, 25828, 25832, 25985, 25984, 26038, 26074, 26322, 27277,
michael@0 10177 27286, 27265, 27301, 27273, 27295, 27291, 27297, 27294, 27271, 27283,
michael@0 10178 27278, 27285, 27267, 27304, 27300, 27281, 27263, 27302, 27290, 27269,
michael@0 10179 27276, 27282, 27483, 27565, 27657, 28620, 28585, 28660, 28628, 28643,
michael@0 10180 28636, 28653, 28647, 28646, 28638, 28658, 28637, 28642, 28648, 29153,
michael@0 10181 29169, 29160, 29170, 29156, 29168, 29154, 29555, {f: 2, c: 29550}, 29847,
michael@0 10182 29874, 29867, 29840, 29866, 29869, 29873, 29861, 29871, {f: 3, c: 29968},
michael@0 10183 29967, 30084, 30275, {f: 2, c: 30280}, 30279, 30372, 30441, 30645, 30635,
michael@0 10184 30642, 30647, 30646, 30644, 30641, 30632, 30704, 30963, 30973, 30978,
michael@0 10185 {f: 2, c: 30971}, 30975, 30962, 30981, 30969, 30974, 30980, 31147, 31144,
michael@0 10186 31324, 31323, 31318, 31320, 31316, 31322, 31422, {f: 2, c: 31424}, 31749,
michael@0 10187 31759, 31730, 31744, 31743, 31739, 31758, 31732, 31755, 31731, 31746,
michael@0 10188 31753, 31747, 31745, 31736, 31741, [31750, 58176], {f: 2, c: 31728}, 31760,
michael@0 10189 31754, 31976, 32301, 32316, 32322, 32307, 38984, 32312, 32298, 32329,
michael@0 10190 32320, 32327, 32297, 32332, 32304, 32315, 32310, 32324, 32314, 32581,
michael@0 10191 32639, 32638, 32637, 32756, 32754, 32812, 33211, 33220, 33228, 33226,
michael@0 10192 33221, 33223, 33212, 33257, 33371, 33370, 33372, 34179, 34176, 34191,
michael@0 10193 34215, 34197, 34208, 34187, 34211, 34171, 34212, 34202, 34206, 34167,
michael@0 10194 34172, 34185, 34209, 34170, 34168, 34135, 34190, 34198, 34182, 34189,
michael@0 10195 34201, 34205, 34177, 34210, 34178, 34184, 34181, 34169, 34166, 34200,
michael@0 10196 34192, 34207, 34408, 34750, 34730, 34733, 34757, 34736, 34732, 34745,
michael@0 10197 34741, 34748, 34734, 34761, 34755, 34754, 34764, 34743, 34735, 34756,
michael@0 10198 34762, 34740, 34742, 34751, 34744, 34749, 34782, 34738, 35125, 35123,
michael@0 10199 35132, 35134, 35137, 35154, 35127, 35138, 35245, 35247, 35246,
michael@0 10200 {f: 2, c: 35314}, 35614, 35608, 35606, 35601, 35589, 35595, 35618, 35599,
michael@0 10201 35602, 35605, 35591, 35597, 35592, 35590, 35612, 35603, 35610, 35919,
michael@0 10202 35952, 35954, 35953, 35951, 35989, 35988, 36089, 36207, 36430, 36429,
michael@0 10203 36435, 36432, 36428, 36423, 36675, 36672, 36997, 36990, 37176, 37274,
michael@0 10204 37282, 37275, 37273, 37279, 37281, 37277, 37280, 37793, 37763, 37807,
michael@0 10205 37732, 37718, 37703, 37756, 37720, 37724, 37750, 37705, {f: 2, c: 37712},
michael@0 10206 37728, 37741, 37775, 37708, 37738, 37753, 37719, 37717, 37714, 37711,
michael@0 10207 37745, 37751, 37755, 37729, 37726, 37731, 37735, 37710, 37721, 38343,
michael@0 10208 38336, 38345, 38339, 38341, 38327, 38574, 38576, 38572, 38688, 38687,
michael@0 10209 38680, 38685, 38681, 38810, 38817, 38812, 38814, 38813, 38869, 38868,
michael@0 10210 38897, 38977, 38980, 38986, 38985, 38981, 38979, 39205, {f: 2, c: 39211},
michael@0 10211 39210, 39219, 39218, 39215, 39213, 39217, 39216, 39320, 39331, 39329,
michael@0 10212 39426, 39418, 39412, 39415, 39417, 39416, 39414, 39419, {f: 2, c: 39421},
michael@0 10213 39420, 39427, 39614, 39678, 39677, 39681, 39676, 39752, 39834, 39848,
michael@0 10214 39838, 39835, 39846, 39841, 39845, 39844, 39814, 39842, 39840, 39855,
michael@0 10215 40243, 40257, 40295, 40246, {f: 2, c: 40238}, 40241, 40248, 40240, 40261,
michael@0 10216 {f: 2, c: 40258}, 40254, 40247, 40256, 40253, 32757, 40237, 40586, 40585,
michael@0 10217 40589, 40624, 40648, 40666, 40699, 40703, 40740, 40739, 40738, 40788,
michael@0 10218 [12245, 40864], 20785, {f: 2, c: 20781}, 22168, 22172, 22167, 22170, 22173,
michael@0 10219 22169, 22896, 23356, {f: 2, c: 23657}, 24000, {f: 2, c: 24173}, 25048,
michael@0 10220 25055, {f: 2, c: 25069}, 25073, 25066, 25072, 25067, 25046, 25065, 25855,
michael@0 10221 25860, 25853, 25848, 25857, 25859, 25852, 26004, 26075, {f: 2, c: 26330},
michael@0 10222 26328, 27333, 27321, 27325, 27361, 27334, 27322, {f: 2, c: 27318}, 27335,
michael@0 10223 27316, 27309, 27486, 27593, 27659, 28679, {f: 2, c: 28684}, 28673, 28677,
michael@0 10224 28692, 28686, {f: 2, c: 28671}, 28667, 28710, 28668, 28663, 28682,
michael@0 10225 [29185, 60224], 29183, 29177, 29187, 29181, 29558, 29880, 29888, 29877,
michael@0 10226 29889, 29886, 29878, 29883, 29890, 29972, 29971, 30300, 30308, 30297,
michael@0 10227 30288, 30291, 30295, 30298, 30374, 30397, 30444, 30658, 30650, 30988,
michael@0 10228 {f: 2, c: 30995}, 30985, 30992, 30994, 30993, 31149, 31148, 31327, 31772,
michael@0 10229 31785, 31769, 31776, 31775, 31789, 31773, 31782, 31784, 31778, 31781,
michael@0 10230 31792, 32348, 32336, 32342, 32355, 32344, 32354, 32351, 32337, 32352,
michael@0 10231 32343, 32339, 32693, 32691, {f: 2, c: 32759}, 32885, {f: 2, c: 33233},
michael@0 10232 33232, 33375, 33374, 34228, 34246, 34240, 34243, 34242, 34227, 34229,
michael@0 10233 34237, 34247, 34244, 34239, 34251, 34254, 34248, 34245, 34225, 34230,
michael@0 10234 34258, 34340, 34232, 34231, 34238, 34409, 34791, 34790, 34786, 34779,
michael@0 10235 34795, 34794, 34789, 34783, 34803, 34788, 34772, 34780, 34771, 34797,
michael@0 10236 34776, 34787, 34775, 34777, 34817, 34804, 34792, 34781, 35155, 35147,
michael@0 10237 35151, 35148, 35142, {f: 2, c: 35152}, 35145, 35626, 35623, 35619, 35635,
michael@0 10238 35632, 35637, 35655, 35631, 35644, 35646, 35633, 35621, 35639, 35622,
michael@0 10239 35638, 35630, 35620, 35643, 35645, 35642, 35906, 35957, 35993, 35992,
michael@0 10240 35991, 36094, 36100, 36098, 36096, 36444, 36450, 36448, 36439, 36438,
michael@0 10241 36446, 36453, 36455, 36443, 36442, 36449, 36445, 36457, 36436,
michael@0 10242 {f: 3, c: 36678}, 36683, 37160, {f: 2, c: 37178}, 37182, 37288, 37285,
michael@0 10243 37287, 37295, 37290, 37813, 37772, 37778, 37815, 37787, 37789, 37769,
michael@0 10244 37799, 37774, 37802, 37790, 37798, 37781, 37768, 37785, 37791, 37760,
michael@0 10245 37773, 37809, 37777, 37810, 37796, 37800, 37812, 37795, {f: 2, c: 38354},
michael@0 10246 38353, 38579, 38615, 38618, 24002, 38623, 38616, 38621, 38691, 38690,
michael@0 10247 38693, 38828, 38830, 38824, 38827, 38820, 38826, 38818, 38821, 38871,
michael@0 10248 38873, 38870, 38872, 38906, {f: 3, c: 38992}, 39096, 39233, 39228, 39226,
michael@0 10249 39439, 39435, 39433, 39437, 39428, 39441, 39434, 39429, 39431, 39430,
michael@0 10250 39616, 39644, 39688, {f: 2, c: 39684}, 39721, 39733, 39754, 39756, 39755,
michael@0 10251 39879, 39878, 39875, 39871, 39873, 39861, 39864, 39891, 39862, 39876,
michael@0 10252 39865, 39869, 40284, 40275, 40271, 40266, 40283, 40267, 40281, 40278,
michael@0 10253 40268, 40279, 40274, 40276, 40287, 40280, 40282, 40590, 40588, 40671,
michael@0 10254 40705, 40704, [40726, 58693], 40741, 40747, 40746, 40745, 40744, 40780,
michael@0 10255 40789, {f: 2, c: 20788}, 21142, 21239, 21428, 22187, 22189,
michael@0 10256 {f: 2, c: 22182}, 22186, 22188, 22746, 22749, 22747, 22802,
michael@0 10257 {f: 3, c: 23357}, 24003, 24176, 24511, 25083, 25863, 25872, 25869, 25865,
michael@0 10258 25868, 25870, 25988, 26078, 26077, 26334, 27367, 27360, 27340, 27345,
michael@0 10259 27353, 27339, 27359, 27356, 27344, 27371, 27343, 27341, 27358, 27488,
michael@0 10260 27568, 27660, 28697, 28711, 28704, 28694, 28715, {f: 3, c: 28705}, 28713,
michael@0 10261 28695, 28708, 28700, 29196, 29194, 29191, 29186, 29189, {f: 2, c: 29349},
michael@0 10262 29348, 29347, 29345, 29899, 29893, 29879, 29891, 29974, 30304,
michael@0 10263 {f: 2, c: 30665}, 30660, 30705, 31005, 31003, 31009, 31004, 30999, 31006,
michael@0 10264 31152, {f: 2, c: 31335}, 31795, 31804, 31801, 31788, 31803, 31980, 31978,
michael@0 10265 32374, 32373, 32376, 32368, 32375, 32367, 32378, 32370, 32372, 32360,
michael@0 10266 32587, 32586, 32643, 32646, 32695, {f: 2, c: 32765}, 32888, 33239, 33237,
michael@0 10267 33291, 33380, 33377, 33379, 34283, 34289, 34285, 34265, 34273, 34280,
michael@0 10268 34266, 34263, 34284, 34290, 34296, 34264, 34271, 34275, 34268, 34257,
michael@0 10269 34288, 34278, 34287, 34270, 34274, 34816, 34810, 34819, {f: 2, c: 34806},
michael@0 10270 34825, 34828, 34827, 34822, 34812, 34824, 34815, 34826, 34818, 35170,
michael@0 10271 {f: 2, c: 35162}, 35159, 35169, 35164, 35160, 35165, 35161, 35208, 35255,
michael@0 10272 35254, 35318, 35664, 35656, 35658, 35648, 35667, 35670, 35668, 35659,
michael@0 10273 35669, 35665, 35650, 35666, 35671, 35907, 35959, 35958, 35994,
michael@0 10274 {f: 2, c: 36102}, 36105, 36268, 36266, 36269, 36267, 36461, 36472, 36467,
michael@0 10275 36458, 36463, 36475, 36546, 36690, 36689, {f: 2, c: 36687}, 36691, 36788,
michael@0 10276 37184, 37183, 37296, 37293, 37854, 37831, 37839, 37826, 37850, 37840,
michael@0 10277 37881, 37868, 37836, 37849, 37801, 37862, 37834, 37844, 37870, 37859,
michael@0 10278 37845, 37828, 37838, 37824, 37842, 37797, 37863, 38269, {f: 2, c: 38362},
michael@0 10279 38625, 38697, {f: 2, c: 38699}, 38696, 38694, 38835, 38839, 38838,
michael@0 10280 {f: 3, c: 38877}, 39004, 39001, 39005, 38999, 39103, 39101, 39099, 39102,
michael@0 10281 39240, 39239, 39235, {f: 2, c: 39334}, 39450, 39445, 39461, 39453, 39460,
michael@0 10282 39451, 39458, 39456, 39463, 39459, 39454, 39452, 39444, 39618, 39691,
michael@0 10283 39690, 39694, 39692, 39735, {f: 2, c: 39914}, 39904, 39902, 39908, 39910,
michael@0 10284 39906, 39920, 39892, 39895, 39916, 39900, 39897, 39909, 39893, 39905,
michael@0 10285 39898, 40311, 40321, 40330, 40324, 40328, 40305, 40320, 40312, 40326,
michael@0 10286 {f: 2, c: 40331}, 40317, 40299, {f: 2, c: 40308}, 40304, 40297, 40325,
michael@0 10287 40307, 40315, 40322, 40303, 40313, 40319, 40327, 40296, 40596, 40593,
michael@0 10288 40640, 40700, 40749, {f: 2, c: 40768}, 40781, {f: 3, c: 40790}, 21303,
michael@0 10289 22194, 22197, 22195, 22755, 23365, {f: 2, c: 24006}, {f: 2, c: 24302},
michael@0 10290 {f: 2, c: 24512}, 25081, 25879, 25878, 25877, 25875, 26079, 26344,
michael@0 10291 {f: 2, c: 26339}, 27379, 27376, 27370, 27368, 27385, 27377,
michael@0 10292 {f: 2, c: 27374}, 28732, 28725, 28719, 28727, 28724, 28721, 28738, 28728,
michael@0 10293 28735, 28730, 28729, 28714, 28736, 28731, 28723, 28737, {f: 2, c: 29203},
michael@0 10294 29352, 29565, 29564, 29882, 30379, 30378, 30398, 30445, 30668,
michael@0 10295 {f: 2, c: 30670}, 30669, 30706, 31013, 31011, {f: 2, c: 31015}, 31012,
michael@0 10296 31017, 31154, 31342, {f: 2, c: 31340}, 31479, 31817, 31816, 31818, 31815,
michael@0 10297 31813, 31982, 32379, 32382, 32385, 32384, 32698, 32767, 32889, 33243,
michael@0 10298 33241, {f: 2, c: 33384}, 34338, 34303, 34305, 34302, 34331, 34304, 34294,
michael@0 10299 34308, 34313, 34309, 34316, 34301, 34841, {f: 2, c: 34832}, 34839, 34835,
michael@0 10300 34838, 35171, 35174, 35257, 35319, 35680, 35690, 35677, 35688, 35683,
michael@0 10301 35685, 35687, 35693, 36270, 36486, 36488, 36484, 36697, {f: 2, c: 36694},
michael@0 10302 36693, 36696, 36698, 37005, 37187, 37185, 37303, 37301, {f: 2, c: 37298},
michael@0 10303 37899, 37907, 37883, 37920, 37903, 37908, 37886, 37909, 37904, 37928,
michael@0 10304 37913, 37901, 37877, 37888, 37879, 37895, 37902, 37910, 37906, 37882,
michael@0 10305 37897, 37880, 37948, 37898, 37887, 37884, 37900, 37878, 37905, 37894,
michael@0 10306 38366, 38368, 38367, {f: 2, c: 38702}, 38841, 38843, {f: 2, c: 38909},
michael@0 10307 39008, {f: 2, c: 39010}, 39007, {f: 2, c: 39105}, 39248, 39246, 39257,
michael@0 10308 39244, 39243, 39251, 39474, 39476, 39473, 39468, 39466, 39478, 39465,
michael@0 10309 39470, 39480, 39469, 39623, 39626, 39622, 39696, 39698, 39697, 39947,
michael@0 10310 39944, 39927, 39941, 39954, 39928, 40000, 39943, 39950, 39942, 39959,
michael@0 10311 39956, 39945, 40351, 40345, 40356, 40349, 40338, 40344, 40336, 40347,
michael@0 10312 40352, 40340, 40348, 40362, 40343, 40353, 40346, 40354, 40360, 40350,
michael@0 10313 40355, 40383, 40361, 40342, {f: 2, c: 40358}, 40601, 40603, 40602, 40677,
michael@0 10314 40676, 40679, 40678, 40752, 40750, 40795, 40800, 40798, 40797, 40793,
michael@0 10315 40849, 20794, 20793, 21144, 21143, 22211, {f: 2, c: 22205}, 23368, 23367,
michael@0 10316 24011, 24015, 24305, 25085, 25883, 27394, 27388, 27395, 27384, 27392,
michael@0 10317 {f: 2, c: 28739}, 28746, {f: 2, c: 28744}, {f: 2, c: 28741}, 29213, 29210,
michael@0 10318 29209, 29566, 29975, 30314, 30672, 31021, 31025, 31023, 31828, 31827,
michael@0 10319 31986, 32394, [32391, 60229], 32392, 32395, 32390, 32397, 32589, 32699,
michael@0 10320 32816, 33245, 34328, 34346, 34342, 34335, 34339, 34332, 34329, 34343,
michael@0 10321 34350, 34337, 34336, 34345, 34334, 34341, 34857, 34845, 34843, 34848,
michael@0 10322 34852, 34844, 34859, 34890, 35181, 35177, 35182, 35179, 35322, 35705,
michael@0 10323 35704, 35653, {f: 2, c: 35706}, 36112, 36116, 36271, 36494, 36492, 36702,
michael@0 10324 36699, 36701, 37190, {f: 2, c: 37188}, 37305, 37951, 37947, 37942, 37929,
michael@0 10325 37949, 37936, 37945, 37930, 37943, 37932, 37952, 37937, 38373, 38372,
michael@0 10326 38371, 38709, 38714, 38847, 38881, 39012, 39113, 39110, 39104, 39256,
michael@0 10327 39254, 39481, 39485, 39494, 39492, 39490, 39489, 39482, 39487, 39629,
michael@0 10328 39701, {f: 2, c: 39703}, 39702, 39738, 39762, 39979, 39965, 39964, 39980,
michael@0 10329 39971, {f: 2, c: 39976}, 39972, 39969, 40375, 40374, 40380, 40385, 40391,
michael@0 10330 40394, 40399, 40382, 40389, 40387, 40379, 40373, 40398, {f: 2, c: 40377},
michael@0 10331 40364, 40392, 40369, 40365, 40396, 40371, 40397, 40370, 40570, 40604,
michael@0 10332 40683, 40686, 40685, 40731, 40728, 40730, 40753, 40782, 40805, 40804,
michael@0 10333 40850, 20153, 22214, 22213, 22219, 22897, {f: 2, c: 23371}, 24021, 24017,
michael@0 10334 24306, 25889, 25888, 25894, 25890, 27403, {f: 2, c: 27400}, 27661,
michael@0 10335 {f: 3, c: 28757}, 28754, {f: 2, c: 29214}, 29353, 29567, 29912, 29909,
michael@0 10336 29913, 29911, 30317, 30381, 31029, 31156, {f: 2, c: 31344}, 31831, 31836,
michael@0 10337 31833, 31835, 31834, 31988, 31985, 32401, 32591, 32647, 33246, 33387,
michael@0 10338 {f: 2, c: 34356}, 34355, 34348, 34354, 34358, 34860, 34856, 34854, 34858,
michael@0 10339 34853, 35185, 35263, 35262, 35323, 35710, 35716, 35714, 35718, 35717,
michael@0 10340 35711, 36117, 36501, 36500, 36506, 36498, 36496, {f: 2, c: 36502}, 36704,
michael@0 10341 36706, 37191, 37964, 37968, {f: 2, c: 37962}, 37967, 37959, 37957,
michael@0 10342 {f: 2, c: 37960}, 37958, 38719, 38883, 39018, 39017, 39115, 39252, 39259,
michael@0 10343 39502, {f: 2, c: 39507}, 39500, 39503, 39496, 39498, 39497, 39506, 39504,
michael@0 10344 39632, 39705, 39723, 39739, 39766, 39765, 40006, 40008, 39999, 40004,
michael@0 10345 39993, 39987, 40001, 39996, 39991, 39988, 39986, 39997, 39990, 40411,
michael@0 10346 40402, 40414, 40410, 40395, 40400, 40412, 40401, 40415, 40425, 40409,
michael@0 10347 40408, 40406, 40437, 40405, 40413, 40630, 40688, 40757, 40755, 40754,
michael@0 10348 40770, 40811, 40853, 40866, 20797, 21145, 22760, 22759, 22898, 23373,
michael@0 10349 24024, 34863, 24399, 25089, {f: 2, c: 25091}, 25897, 25893, 26006, 26347,
michael@0 10350 {f: 2, c: 27409}, 27407, 27594, 28763, 28762, 29218, 29570, 29569, 29571,
michael@0 10351 30320, 30676, 31847, 31846, 32405, 33388, 34362, 34368, 34361, 34364,
michael@0 10352 34353, 34363, 34366, 34864, 34866, 34862, 34867, 35190, 35188, 35187,
michael@0 10353 35326, 35724, 35726, 35723, 35720, 35909, 36121, 36504, 36708, 36707,
michael@0 10354 37308, 37986, 37973, 37981, 37975, 37982, {f: 2, c: 38852}, 38912, 39510,
michael@0 10355 39513, {f: 3, c: 39710}, 40018, 40024, 40016, 40010, 40013, 40011, 40021,
michael@0 10356 40025, 40012, 40014, 40443, 40439, 40431, 40419, 40427, 40440, 40420,
michael@0 10357 40438, 40417, 40430, 40422, 40434, [40432, 60370], 40418, 40428, 40436,
michael@0 10358 40435, 40424, 40429, 40642, 40656, {f: 2, c: 40690}, 40710, 40732, 40760,
michael@0 10359 40759, 40758, 40771, 40783, 40817, 40816, {f: 2, c: 40814}, 22227, 22221,
michael@0 10360 23374, 23661, 25901, {f: 2, c: 26349}, 27411, 28767, 28769, 28765, 28768,
michael@0 10361 29219, 29915, 29925, 30677, 31032, 31159, 31158, 31850, 32407, 32649,
michael@0 10362 33389, 34371, 34872, 34871, 34869, 34891, {f: 2, c: 35732},
michael@0 10363 {f: 3, c: 36510}, 36509, 37310, 37309, 37314, 37995, {f: 2, c: 37992},
michael@0 10364 38629, 38726, 38723, 38727, 38855, 38885, 39518, 39637, 39769, 40035,
michael@0 10365 40039, 40038, 40034, 40030, 40032, 40450, 40446, 40455, 40451, 40454,
michael@0 10366 40453, {f: 2, c: 40448}, 40457, 40447, 40445, 40452, 40608, 40734, 40774,
michael@0 10367 {f: 3, c: 40820}, 22228, 25902, 26040, {f: 2, c: 27416}, 27415, 27418,
michael@0 10368 28770, 29222, 29354, {f: 2, c: 30680}, 31033, 31849, 31851, 31990, 32410,
michael@0 10369 32408, 32411, 32409, {f: 2, c: 33248}, {f: 3, c: 34374}, {f: 2, c: 35193},
michael@0 10370 35196, 35195, 35327, {f: 2, c: 35736}, 36517, 36516, 36515, 37998, 37997,
michael@0 10371 37999, 38001, 38003, 38729, 39026, 39263, 40040, 40046, 40045, 40459,
michael@0 10372 40461, 40464, 40463, 40466, 40465, 40609, 40693, 40713, 40775, 40824,
michael@0 10373 40827, 40826, 40825, 22302, 28774, 31855, 34876, 36274, 36518, 37315,
michael@0 10374 38004, 38008, 38006, 38005, 39520, [39726, 60830], 40052, 40051, 40049,
michael@0 10375 40053, 40468, 40467, 40694, 40714, 40868, 28776, 28773, 31991, 34410,
michael@0 10376 34878, 34877, 34879, 35742, 35996, 36521, 36553, 38731, {f: 2, c: 39027},
michael@0 10377 39116, 39265, 39339, 39524, {f: 2, c: 39526}, 39716, 40469, 40471, 40776,
michael@0 10378 25095, 27422, 29223, 34380, 36520, 38018, {f: 2, c: 38016}, 39529, 39528,
michael@0 10379 40473, 34379, 35743, 38019, 40057, 40631, 30325, 39531, 40058, 40477,
michael@0 10380 {f: 2, c: 28777}, 29225, 40612, 40830, 40777, 40856, {s: 97}, 65075, 0,
michael@0 10381 65076, 65103, [168, 776, 63208], [710, 63209, 65342], [12541, 63210],
michael@0 10382 [12542, 63211], [12445, 63212], [12446, 63213], 0, [12293, 63216],
michael@0 10383 [12294, 63217], [12295, 63218], [12540, 63219], [63220, 65339],
michael@0 10384 [63221, 65341], [10045, 63222], [12353, 63223], [12354, 63224],
michael@0 10385 [12355, 63225], [12356, 63226], [12357, 63227], [12358, 63228],
michael@0 10386 [12359, 63229], [12360, 63230], [12361, 63231], [12362, 63232],
michael@0 10387 [12363, 63233], [12364, 63234], [12365, 63235], [12366, 63236],
michael@0 10388 [12367, 63237], [12368, 63238], [12369, 63239], [12370, 63240],
michael@0 10389 [12371, 63241], [12372, 63242], [12373, 63243], [12374, 63244],
michael@0 10390 [12375, 63245], [12376, 63246], [12377, 63247], [12378, 63248],
michael@0 10391 [12379, 63249], [12380, 63250], [12381, 63251], [12382, 63252],
michael@0 10392 [12383, 63253], [12384, 63254], [12385, 63255], [12386, 63256],
michael@0 10393 [12387, 63257], [12388, 63258], [12389, 63259], [12390, 63260],
michael@0 10394 [12391, 63261], [12392, 63262], [12393, 63263], [12394, 63264],
michael@0 10395 [12395, 63265], [12396, 63266], [12397, 63267], [12398, 63268],
michael@0 10396 [12399, 63269], [12400, 63270], [12401, 63271], [12402, 63272],
michael@0 10397 [12403, 63273], [12404, 63274], [12405, 63275], [12406, 63276],
michael@0 10398 [12407, 63277], [12408, 63278], [12409, 63279], [12410, 63280],
michael@0 10399 [12411, 63281], [12412, 63282], [12413, 63283], [12414, 63284],
michael@0 10400 [12415, 63285], [12416, 63286], [12417, 63287], [12418, 63288],
michael@0 10401 [12419, 63289], [12420, 63290], [12421, 63291], [12422, 63292],
michael@0 10402 [12423, 63293], [12424, 63294], [12425, 63295], [12426, 63296],
michael@0 10403 [12427, 63297], [12428, 63298], [12429, 63299], [12430, 63300],
michael@0 10404 [12431, 63301], [12432, 63302], [12433, 63303], [12434, 63304],
michael@0 10405 [12435, 63305], [12449, 63306], [12450, 63307], [12451, 63308],
michael@0 10406 [12452, 63309], [12453, 63310], [12454, 63311], [12455, 63312],
michael@0 10407 [12456, 63313], [12457, 63314], [12458, 63315], [12459, 63316],
michael@0 10408 [12460, 63317], [12461, 63318], [12462, 63319], [12463, 63320],
michael@0 10409 [12464, 63321], [12465, 63322], [12466, 63323], [12467, 63324],
michael@0 10410 [12468, 63325], [12469, 63326], [12470, 63327], [12471, 63328],
michael@0 10411 [12472, 63329], [12473, 63330], [12474, 63331], [12475, 63332],
michael@0 10412 [12476, 63333], [12477, 63334], [12478, 63335], [12479, 63336],
michael@0 10413 [12480, 63337], [12481, 63338], [12482, 63339], [12483, 63340],
michael@0 10414 [12484, 63341], [12485, 63342], [12486, 63343], [12487, 63344],
michael@0 10415 [12488, 63345], [12489, 63346], [12490, 63347], [12491, 63348],
michael@0 10416 [12492, 63349], [12493, 63350], [12494, 63351], [12495, 63352],
michael@0 10417 [12496, 63353], [12497, 63354], [12498, 63355], [12499, 63356],
michael@0 10418 [12500, 63357], [12501, 63358], [12502, 63359], [12503, 63360],
michael@0 10419 [12504, 63361], [12505, 63362], [12506, 63363], [12507, 63364],
michael@0 10420 [12508, 63365], [12509, 63366], [12510, 63367], [12511, 63368],
michael@0 10421 [12512, 63369], [12513, 63370], [12514, 63371], [12515, 63372],
michael@0 10422 [12516, 63373], [12517, 63374], [12518, 63375], [12519, 63376],
michael@0 10423 [12520, 63377], [12521, 63378], [12522, 63379], [12523, 63380],
michael@0 10424 [12524, 63381], [12525, 63382], [12526, 63383], [12527, 63384],
michael@0 10425 [12528, 63385], [12529, 63386], [12530, 63387], [12531, 63388],
michael@0 10426 [12532, 63389], [12533, 63390], [12534, 63391], [1040, 63392],
michael@0 10427 [1041, 63393], [1042, 63394], [1043, 63395], [1044, 63396], [1045, 63397],
michael@0 10428 [1025, 63398], [1046, 63399], [1047, 63400], [1048, 63401], [1049, 63402],
michael@0 10429 [1050, 63403], [1051, 63404], [1052, 63405], [1053, 63406], [1054, 63407],
michael@0 10430 [1055, 63408], [1056, 63409], [1057, 63410], [1058, 63411], [1059, 63412],
michael@0 10431 [1060, 63413], [1061, 63414], [1062, 63415], [1063, 63416], [1064, 63417],
michael@0 10432 [1065, 63418], [1066, 63419], [1067, 63420], [1068, 63421], [1069, 63422],
michael@0 10433 [1070, 63423], [1071, 63424], [1072, 63425], [1073, 63426], [1074, 63427],
michael@0 10434 [1075, 63428], [1076, 63429], [1077, 63430], [1105, 63431], [1078, 63432],
michael@0 10435 [1079, 63433], [1080, 63434], [1081, 63435], [1082, 63436], [1083, 63437],
michael@0 10436 [1084, 63438], [1085, 63439], [1086, 63440], [1087, 63441], [1088, 63442],
michael@0 10437 [1089, 63443], [1090, 63444], [1091, 63445], [1092, 63446], [1093, 63447],
michael@0 10438 [1094, 63448], [1095, 63449], [1096, 63450], [1097, 63451], [1098, 63452],
michael@0 10439 [1099, 63453], [1100, 63454], [1101, 63455], [1102, 63456], [1103, 63457],
michael@0 10440 [8679, 63458], [8632, 63459], [8633, 63460], [20033, 63461],
michael@0 10441 [63462, 131276], [20058, 63463], [63464, 131210], [20994, 63465],
michael@0 10442 [17553, 63466], 63467, [20872, 63468], [13853, 63469], [63470, 161287],
michael@0 10443 {s: 40}, [172, 63511, 65506], [63512, 65508], [63513, 65287],
michael@0 10444 [63514, 65282], [12849, 63515], [8470, 63516], [8481, 63517], 30849,
michael@0 10445 [37561, 58501], 35023, 22715, 24658, 31911, 23290, 9556, 9574, 9559, 9568,
michael@0 10446 9580, 9571, 9562, 9577, 9565, 9554, 9572, 9557, {s: 3}, 9560, 9575, 9563,
michael@0 10447 9555, 9573, 9558, 9567, 9579, 9570, 9561, 9576, 9564, 9553, {s: 5}, 9619,
michael@0 10448 {s: 26}, [58129, 147159], [22462, 58130], [58131, 159443], [28990, 58132],
michael@0 10449 [58133, 153568], [27042, 58135], [58136, 166889], [23412, 58137],
michael@0 10450 [31305, 58138], [58139, 153825], [58140, 169177], [31333, 58141],
michael@0 10451 [31357, 58142], [58143, 154028], [31419, 58144], [31408, 58145],
michael@0 10452 [31426, 58146], [31427, 58147], [29137, 58148], [58149, 156813],
michael@0 10453 [16842, 58150], [31450, 58151], [31453, 58152], [31466, 58153],
michael@0 10454 [16879, 58154], [21682, 58155], [58156, 154625], [31499, 58157],
michael@0 10455 [31573, 58158], [31529, 58159], [58160, 152334], [58161, 154878],
michael@0 10456 [31650, 58162], [31599, 58163], [33692, 58164], [58165, 154548],
michael@0 10457 [58166, 158847], [31696, 58167], [33825, 58168], [31634, 58169], 0,
michael@0 10458 [58171, 154912], 0, [33938, 58174], [31738, 58175], 0, [31797, 58177],
michael@0 10459 [58178, 154817], [31812, 58179], [31875, 58180], [58181, 149634],
michael@0 10460 [31910, 58182], [58184, 148856], [31945, 58185], [31943, 58186],
michael@0 10461 [31974, 58187], 0, [31987, 58189], [31989, 58190], [32359, 58192],
michael@0 10462 [17693, 58193], [58194, 159300], [32093, 58195], [58196, 159446],
michael@0 10463 [32137, 58198], [32171, 58199], [28981, 58200], [32179, 58201], 32214,
michael@0 10464 [58203, 147543], [58204, 155689], [32228, 58205], [15635, 58206],
michael@0 10465 [32245, 58207], [58208, 137209], [32229, 58209], [58210, 164717], 0,
michael@0 10466 [58212, 155937], [58213, 155994], [32366, 58214], 0, [17195, 58216],
michael@0 10467 [37996, 58217], [32295, 58218], [32576, 58219], [32577, 58220],
michael@0 10468 [32583, 58221], [31030, 58222], [58223, 156368], [39393, 58224],
michael@0 10469 [32663, 58225], [58226, 156497], [32675, 58227], [58228, 136801],
michael@0 10470 [58229, 131176], [17756, 58230], [58231, 145254], [58233, 164666],
michael@0 10471 [32762, 58234], [58235, 156809], 0, [32776, 58237], [32797, 58238], 0,
michael@0 10472 [32815, 58240], [58241, 172167], [58242, 158915], [32827, 58243],
michael@0 10473 [32828, 58244], [32865, 58245], [58246, 141076], [18825, 58247],
michael@0 10474 [58248, 157222], [58249, 146915], [58250, 157416], [26405, 58251],
michael@0 10475 [32935, 58252], [58253, 166472], [33031, 58254], [33050, 58255],
michael@0 10476 [22704, 58256], [58257, 141046], [27775, 58258], [58259, 156824],
michael@0 10477 [25831, 58261], [58262, 136330], [33304, 58263], [58264, 137310],
michael@0 10478 [27219, 58265], [58266, 150117], [58267, 150165], [17530, 58268],
michael@0 10479 [33321, 58269], [58271, 158290], [58272, 146814], [20473, 58273],
michael@0 10480 [58274, 136445], [34018, 58275], [33634, 58276], 0, [58278, 149927],
michael@0 10481 [58279, 144688], [58280, 137075], [58281, 146936], [33450, 58282],
michael@0 10482 [26907, 58283], [58284, 194964], [16859, 58285], [34123, 58286],
michael@0 10483 [33488, 58287], [33562, 58288], [58289, 134678], [58290, 137140],
michael@0 10484 [14017, 58291], [58292, 143741], [58293, 144730], [33403, 58294],
michael@0 10485 [33506, 58295], [33560, 58296], [58297, 147083], [58298, 159139],
michael@0 10486 [58299, 158469], [58300, 158615], [58301, 144846], [15807, 58302],
michael@0 10487 [33565, 58303], [21996, 58304], [33669, 58305], [17675, 58306],
michael@0 10488 [58307, 159141], [33708, 58308], 0, [33747, 58310], [58312, 159444],
michael@0 10489 [27223, 58313], [34138, 58314], [13462, 58315], [58316, 159298],
michael@0 10490 [33880, 58318], [58319, 154596], [33905, 58320], [15827, 58321],
michael@0 10491 [17636, 58322], [27303, 58323], [33866, 58324], [31064, 58326], 0,
michael@0 10492 [58328, 158614], [58329, 159351], [58330, 159299], [34014, 58331], 0,
michael@0 10493 [33681, 58333], [17568, 58334], [33939, 58335], [34020, 58336],
michael@0 10494 [58337, 154769], [16960, 58338], [58339, 154816], [17731, 58340],
michael@0 10495 [34100, 58341], [23282, 58342], 0, [17703, 58344], [34163, 58345],
michael@0 10496 [17686, 58346], [26559, 58347], [34326, 58348], [58349, 165413],
michael@0 10497 [58350, 165435], [34241, 58351], [58352, 159880], [34306, 58353],
michael@0 10498 [58354, 136578], [58355, 159949], [58356, 194994], [17770, 58357],
michael@0 10499 [34344, 58358], [13896, 58359], [58360, 137378], [21495, 58361],
michael@0 10500 [58362, 160666], [34430, 58363], 0, [58365, 172280], [34798, 58366],
michael@0 10501 [58367, 142375], [34737, 58368], [34778, 58369], [34831, 58370, 60990],
michael@0 10502 [22113, 58371], [34412, 58372], [26710, 58373], [17935, 58374],
michael@0 10503 [34885, 58375], [34886, 58376], [58377, 161248], [58378, 146873],
michael@0 10504 [58379, 161252], [34910, 58380], [34972, 58381], [18011, 58382],
michael@0 10505 [34996, 58383], [34997, 58384], [35013, 58386], [58388, 161551],
michael@0 10506 [35207, 58389], {s: 3}, [35239, 58393], [35260, 58394], [58395, 166437],
michael@0 10507 [35303, 58396], [58397, 162084], [58398, 162493], [35484, 58399],
michael@0 10508 [30611, 58400], [37374, 58401], [35472, 58402], [58403, 162393],
michael@0 10509 [31465, 58404], [58405, 162618], [18195, 58407], [58408, 162616],
michael@0 10510 [29052, 58409], [35596, 58410], [35615, 58411], [58412, 152624],
michael@0 10511 [58413, 152933], [35647, 58414], 0, [35661, 58416], [35497, 58417],
michael@0 10512 [58418, 150138], [35728, 58419], [35739, 58420], [35503, 58421],
michael@0 10513 [58422, 136927], [17941, 58423], [34895, 58424], [35995, 58425],
michael@0 10514 [58426, 163156], [58427, 163215], [58428, 195028], [14117, 58429],
michael@0 10515 [58430, 163155], [36054, 58431], [58432, 163224], [58433, 163261],
michael@0 10516 [36114, 58434], [36099, 58435], [58436, 137488], [36059, 58437],
michael@0 10517 [28764, 58438], [36113, 58439], [16080, 58441], 0, [36265, 58443],
michael@0 10518 [58444, 163842], [58445, 135188], [58446, 149898], [15228, 58447],
michael@0 10519 [58448, 164284], [58449, 160012], [31463, 58450], [36525, 58451],
michael@0 10520 [36534, 58452], [36547, 58453], [37588, 58454], [36633, 58455],
michael@0 10521 [36653, 58456], [58457, 164709], [58458, 164882], [36773, 58459],
michael@0 10522 [37635, 58460], [58461, 172703], [58462, 133712], [36787, 58463], 0,
michael@0 10523 [58465, 166366], [58466, 165181], [58467, 146875], [24312, 58468],
michael@0 10524 [58469, 143970], [36857, 58470], 0, [58474, 140069], [14720, 58475],
michael@0 10525 [58476, 159447], [36919, 58477], [58478, 165180], [58479, 162494],
michael@0 10526 [36961, 58480], [58481, 165228], [58482, 165387], [37032, 58483],
michael@0 10527 [58484, 165651], [37060, 58485], [58486, 165606], [37038, 58487], 0,
michael@0 10528 [37223, 58489], [37289, 58491], [37316, 58492], [31916, 58493],
michael@0 10529 [58494, 166195], [58495, 138889], [37390, 58496], [27807, 58497],
michael@0 10530 [37441, 58498], [37474, 58499], [58500, 153017], [58502, 166598],
michael@0 10531 [58503, 146587], [58504, 166668], [58505, 153051], [58506, 134449],
michael@0 10532 [37676, 58507], [37739, 58508], [58509, 166625], [58510, 166891],
michael@0 10533 [23235, 58512], [58513, 166626], [58514, 166629], [18789, 58515],
michael@0 10534 [37444, 58516], [58517, 166892], [58518, 166969], [58519, 166911],
michael@0 10535 [37747, 58520], [37979, 58521], [36540, 58522], [38277, 58523],
michael@0 10536 [38310, 58524], [37926, 58525], [38304, 58526], [28662, 58527],
michael@0 10537 [17081, 58528], [58530, 165592], [58531, 135804], [58532, 146990],
michael@0 10538 [18911, 58533], [27676, 58534], [38523, 58535], [38550, 58536],
michael@0 10539 [16748, 58537], [38563, 58538], [58539, 159445], [25050, 58540], 58541,
michael@0 10540 [30965, 58542], [58543, 166624], [38589, 58544], [21452, 58545],
michael@0 10541 [18849, 58546], [58547, 158904], [58548, 131700], [58549, 156688],
michael@0 10542 [58550, 168111], [58551, 168165], [58552, 150225], [58553, 137493],
michael@0 10543 [58554, 144138], [38705, 58555], [34370, 58556], [38710, 58557],
michael@0 10544 [18959, 58558], [17725, 58559], [17797, 58560], [58561, 150249],
michael@0 10545 [28789, 58562], [23361, 58563], [38683, 58564], 0, [58566, 168405],
michael@0 10546 [38743, 58567], [23370, 58568], [58569, 168427], [38751, 58570],
michael@0 10547 [37925, 58571], [20688, 58572], [58573, 143543], [58574, 143548],
michael@0 10548 [38793, 58575], [38815, 58576], [38833, 58577], [38846, 58578],
michael@0 10549 [38848, 58579], [38866, 58580], [38880, 58581], [58582, 152684],
michael@0 10550 [38894, 58583], [29724, 58584], [58585, 169011], 0, [38901, 58587],
michael@0 10551 [58588, 168989], [58589, 162170], [19153, 58590], [38964, 58591],
michael@0 10552 [38963, 58592], [38987, 58593], [39014, 58594], [15118, 58595],
michael@0 10553 [58596, 160117], [15697, 58597], [58598, 132656], [58599, 147804],
michael@0 10554 [58600, 153350], [39114, 58601], [39095, 58602], [39112, 58603],
michael@0 10555 [39111, 58604], [19199, 58605], [58606, 159015], [58607, 136915],
michael@0 10556 [21936, 58608], [39137, 58609], [39142, 58610], [39148, 58611],
michael@0 10557 [37752, 58612], [39225, 58613], [58614, 150057], [19314, 58615],
michael@0 10558 [58616, 170071], [58617, 170245], [39413, 58618], [39436, 58619],
michael@0 10559 [39483, 58620], [39440, 58621], [39512, 58622], [58623, 153381],
michael@0 10560 [14020, 58624], [58625, 168113], [58626, 170965], [39648, 58627],
michael@0 10561 [39650, 58628], [58629, 170757], [39668, 58630], [19470, 58631],
michael@0 10562 [39700, 58632], [39725, 58633], [58634, 165376], [20532, 58635],
michael@0 10563 [39732, 58636], [14531, 58638], [58639, 143485], [39760, 58640],
michael@0 10564 [39744, 58641], [58642, 171326], [23109, 58643], [58644, 137315],
michael@0 10565 [39822, 58645], [39938, 58647], [39935, 58648], [39948, 58649],
michael@0 10566 [58650, 171624], [40404, 58651], [58652, 171959], [58653, 172434],
michael@0 10567 [58654, 172459], [58655, 172257], [58656, 172323], [58657, 172511],
michael@0 10568 [40318, 58658], [40323, 58659], [58660, 172340], [40462, 58661],
michael@0 10569 [40388, 58663], [58665, 172435], [58666, 172576], [58667, 137531],
michael@0 10570 [58668, 172595], [40249, 58669], [58670, 172217], [58671, 172724],
michael@0 10571 [40592, 58672], [40597, 58673], [40606, 58674], [40610, 58675],
michael@0 10572 [19764, 58676], [40618, 58677], [40623, 58678], [58679, 148324],
michael@0 10573 [40641, 58680], [15200, 58681], [14821, 58682], [15645, 58683],
michael@0 10574 [20274, 58684], [14270, 58685], [58686, 166955], [40706, 58687],
michael@0 10575 [40712, 58688], [19350, 58689], [37924, 58690], [58691, 159138],
michael@0 10576 [40727, 58692, 60836], 0, [40761, 58694], [22175, 58695], [22154, 58696],
michael@0 10577 [40773, 58697], [39352, 58698], [58699, 168075], [38898, 58700],
michael@0 10578 [33919, 58701], 0, [40809, 58703], [31452, 58704], [40846, 58705],
michael@0 10579 [29206, 58706], [19390, 58707], [58708, 149877], [58709, 149947],
michael@0 10580 [29047, 58710], [58711, 150008], [58712, 148296], [58713, 150097],
michael@0 10581 [29598, 58714], [58715, 166874], [58716, 137466], [31135, 58717],
michael@0 10582 [58718, 166270], [58719, 167478], [37737, 58720], [37875, 58721],
michael@0 10583 [58722, 166468], [37612, 58723], [37761, 58724], [37835, 58725],
michael@0 10584 [58726, 166252], [58727, 148665], [29207, 58728], [16107, 58729],
michael@0 10585 [30578, 58730], [31299, 58731], [28880, 58732], [58733, 148595],
michael@0 10586 [58734, 148472], [29054, 58735], [58736, 137199], [28835, 58737],
michael@0 10587 [58738, 137406], [58739, 144793], [16071, 58740], [58741, 137349],
michael@0 10588 [58742, 152623], [58743, 137208], [14114, 58744], [58745, 136955],
michael@0 10589 [58746, 137273], [14049, 58747], [58748, 137076], [58749, 137425],
michael@0 10590 [58750, 155467], [14115, 58751], [58752, 136896], [22363, 58753],
michael@0 10591 [58754, 150053], [58755, 136190], [58756, 135848], [58757, 136134],
michael@0 10592 [58758, 136374], [34051, 58759, 58761], [58760, 145062], 0, [33877, 58762],
michael@0 10593 [58763, 149908], [58764, 160101], [58765, 146993], [58766, 152924],
michael@0 10594 [58767, 147195], [58768, 159826], [17652, 58769], [58770, 145134],
michael@0 10595 [58771, 170397], [58772, 159526], [26617, 58773], [14131, 58774],
michael@0 10596 [15381, 58775], [15847, 58776], [22636, 58777], [58778, 137506],
michael@0 10597 [26640, 58779], [16471, 58780], [58781, 145215], [58782, 147681],
michael@0 10598 [58783, 147595], [58784, 147727], [58785, 158753], [21707, 58786],
michael@0 10599 [22174, 58787], [58788, 157361], [22162, 58789], [58790, 135135],
michael@0 10600 [58791, 134056], [58792, 134669], 0, [58794, 166675], [37788, 58795],
michael@0 10601 [20216, 58796], [20779, 58797], [14361, 58798], [58799, 148534],
michael@0 10602 [20156, 58800], [58801, 132197], 0, [20299, 58803], [20362, 58804],
michael@0 10603 [58805, 153169], [23144, 58806], [58807, 131499], [58808, 132043],
michael@0 10604 [14745, 58809], [58810, 131850], [58811, 132116], [13365, 58812],
michael@0 10605 [20265, 58813], [58814, 131776], [58815, 167603], [58816, 131701],
michael@0 10606 [35546, 58817], [58818, 131596], [20120, 58819], [20685, 58820],
michael@0 10607 [20749, 58821], [20386, 58822], [20227, 58823], [58824, 150030],
michael@0 10608 [58825, 147082], [20290, 58826], [20526, 58827], [20588, 58828],
michael@0 10609 [20609, 58829], [20428, 58830], [20453, 58831], [20568, 58832],
michael@0 10610 [20732, 58833], [28278, 58838], [58839, 144789], [58840, 147001],
michael@0 10611 [58841, 147135], [28018, 58842], [58843, 137348], [58844, 147081],
michael@0 10612 [20904, 58845], [20931, 58846], [58847, 132576], [17629, 58848],
michael@0 10613 [58849, 132259], [58850, 132242], [58851, 132241], [36218, 58852],
michael@0 10614 [58853, 166556], [58854, 132878], [21081, 58855], [21156, 58856],
michael@0 10615 [58857, 133235], [21217, 58858], 0, [18042, 58860], [29068, 58861],
michael@0 10616 [58862, 148364], [58863, 134176], [58864, 149932], [58865, 135396],
michael@0 10617 [27089, 58866], [58867, 134685], 0, [16094, 58869], [29849, 58870],
michael@0 10618 [29716, 58871], [29782, 58872], [29592, 58873], [19342, 58874],
michael@0 10619 [58875, 150204], [58876, 147597], [21456, 58877], [13700, 58878],
michael@0 10620 [29199, 58879], [58880, 147657], [21940, 58881], [58882, 131909],
michael@0 10621 [21709, 58883], [58884, 134086], [22301, 58885], [37469, 58886],
michael@0 10622 [38644, 58887], [22493, 58889], [22413, 58890], [22399, 58891],
michael@0 10623 [13886, 58892], [22731, 58893], [23193, 58894], [58895, 166470],
michael@0 10624 [58896, 136954], [58897, 137071], [58898, 136976], [23084, 58899],
michael@0 10625 [22968, 58900], [23166, 58902], [23247, 58903], [23058, 58904],
michael@0 10626 [58905, 153926], [58906, 137715], [58907, 137313], [58908, 148117],
michael@0 10627 [14069, 58909], [27909, 58910], [29763, 58911], [23073, 58912],
michael@0 10628 [58913, 155267], [23169, 58914], [58915, 166871], [58916, 132115],
michael@0 10629 [37856, 58917], [29836, 58918], [58919, 135939], [28933, 58920],
michael@0 10630 [18802, 58921], [37896, 58922], [58923, 166395], [37821, 58924],
michael@0 10631 [14240, 58925], [23582, 58926], [23710, 58927], [24158, 58928],
michael@0 10632 [24136, 58929], [58930, 137622], [58931, 137596], [58932, 146158],
michael@0 10633 [24269, 58933], [23375, 58934], [58935, 137475], [58936, 137476],
michael@0 10634 [14081, 58937], [58938, 137376], [14045, 58939], [58940, 136958],
michael@0 10635 [14035, 58941], [33066, 58942], [58943, 166471], [58944, 138682],
michael@0 10636 [58945, 144498], [58946, 166312], [24332, 58947, 60916], [24334, 58948],
michael@0 10637 [58949, 137511], [58950, 137131], [23147, 58951], [58952, 137019],
michael@0 10638 [23364, 58953], [58955, 161277], [34912, 58956], [24702, 58957],
michael@0 10639 [58958, 141408], [58959, 140843], [24539, 58960], [16056, 58961],
michael@0 10640 [58962, 140719], [58963, 140734], [58964, 168072], [58965, 159603],
michael@0 10641 [25024, 58966], [58967, 131134], [58968, 131142], [58969, 140827],
michael@0 10642 [24985, 58970], [24984, 58971], [24693, 58972], [58973, 142491],
michael@0 10643 [58974, 142599], [58975, 149204], [58976, 168269], [25713, 58977],
michael@0 10644 [58978, 149093], [58979, 142186], [14889, 58980], [58981, 142114],
michael@0 10645 [58982, 144464], [58983, 170218], [58984, 142968], [25399, 58985],
michael@0 10646 [25782, 58987], [25393, 58988], [25553, 58989], [58990, 149987],
michael@0 10647 [58991, 142695], [25252, 58992], [58993, 142497], [25659, 58994],
michael@0 10648 [25963, 58995], [26994, 58996], [15348, 58997], [58998, 143502],
michael@0 10649 [58999, 144045], [59000, 149897], [59001, 144043], [21773, 59002],
michael@0 10650 [59003, 144096], [59004, 137433], [59005, 169023], [26318, 59006],
michael@0 10651 [59007, 144009], [59008, 143795], [15072, 59009], [59011, 152964],
michael@0 10652 [59012, 166690], [59013, 152975], [59014, 136956], [59015, 152923],
michael@0 10653 [59016, 152613], [30958, 59017], [59018, 143619], [59019, 137258],
michael@0 10654 [59020, 143924], [13412, 59021], [59022, 143887], [59023, 143746],
michael@0 10655 [59024, 148169], [26254, 59025], [59026, 159012], [26219, 59027],
michael@0 10656 [19347, 59028], [26160, 59029], [59030, 161904], [59031, 138731],
michael@0 10657 [26211, 59032], [59033, 144082], [59034, 144097], [26142, 59035],
michael@0 10658 [59036, 153714], [14545, 59037], [59038, 145466], [59039, 145340],
michael@0 10659 [15257, 59040], [59041, 145314], [59042, 144382], [29904, 59043],
michael@0 10660 [15254, 59044], [59046, 149034], [26806, 59047], 0, [15300, 59049],
michael@0 10661 [27326, 59050], [59052, 145365], [59053, 148615], [27187, 59054],
michael@0 10662 [27218, 59055], [27337, 59056], [27397, 59057], [59058, 137490],
michael@0 10663 [25873, 59059], [26776, 59060], [27212, 59061], [15319, 59062],
michael@0 10664 [27258, 59063], [27479, 59064], [59065, 147392], [59066, 146586],
michael@0 10665 [37792, 59067], [37618, 59068], [59069, 166890], [59070, 166603],
michael@0 10666 [37513, 59071], [59072, 163870], [59073, 166364], [37991, 59074],
michael@0 10667 [28069, 59075], [28427, 59076], 0, [59079, 147327], [15759, 59080],
michael@0 10668 [28164, 59081], [59082, 147516], [23101, 59083], [28170, 59084],
michael@0 10669 [22599, 59085], [27940, 59086], [30786, 59087], [28987, 59088],
michael@0 10670 [59089, 148250], [59090, 148086], [28913, 59091], [29264, 59092, 61085],
michael@0 10671 [29319, 59093], [29332, 59094], [59095, 149391], [59096, 149285],
michael@0 10672 [20857, 59097], [59098, 150180], [59099, 132587], [29818, 59100],
michael@0 10673 [59101, 147192], [59102, 144991], [59103, 150090], [59104, 149783],
michael@0 10674 [59105, 155617], [16134, 59106], [16049, 59107], [59108, 150239],
michael@0 10675 [59109, 166947], [59110, 147253], [24743, 59111], [16115, 59112],
michael@0 10676 [29900, 59113], [29756, 59114], [37767, 59115], [29751, 59116],
michael@0 10677 [17567, 59117], [59118, 159210], [17745, 59119], [30083, 59120],
michael@0 10678 [16227, 59121], [59122, 150745], [59123, 150790], [16216, 59124],
michael@0 10679 [30037, 59125], [30323, 59126], [59127, 173510], 0, [29800, 59129, 61070],
michael@0 10680 [59130, 166604], [59131, 149931], [59132, 149902], [15099, 59133],
michael@0 10681 [15821, 59134], [59135, 150094], [16127, 59136], [59137, 149957],
michael@0 10682 [59138, 149747], [37370, 59139], [22322, 59140], [37698, 59141],
michael@0 10683 [59142, 166627], [59143, 137316], [20703, 59144], [59145, 152097],
michael@0 10684 [59146, 152039], [30584, 59147], [59148, 143922], [30478, 59149],
michael@0 10685 [30479, 59150], [30587, 59151], [59152, 149143], [59153, 145281],
michael@0 10686 [14942, 59154], [59155, 149744], [29752, 59156], [29851, 59157],
michael@0 10687 [16063, 59158], [59159, 150202], [59160, 150215], [16584, 59161],
michael@0 10688 [59162, 150166], [59163, 156078], [37639, 59164], [59165, 152961],
michael@0 10689 [30750, 59166], [30861, 59167], [30856, 59168], [30930, 59169],
michael@0 10690 [29648, 59170], [31065, 59171], [59172, 161601], [59173, 153315],
michael@0 10691 [16654, 59174], 0, 0, [31141, 59177], [27181, 59178], [59179, 147194],
michael@0 10692 [31290, 59180], [31220, 59181], [16750, 59182], [59183, 136934],
michael@0 10693 [16690, 59184], [37429, 59185], [31217, 59186], [59187, 134476],
michael@0 10694 [59188, 149900], [59189, 131737], [59190, 146874], [59191, 137070],
michael@0 10695 [13719, 59192], [21867, 59193], [13680, 59194], [13994, 59195],
michael@0 10696 [59196, 131540], [59197, 134157], [31458, 59198], [23129, 59199],
michael@0 10697 [59200, 141045], [59201, 154287], [59202, 154268], [23053, 59203],
michael@0 10698 [59204, 131675], [30960, 59205], [23082, 59206], [59207, 154566],
michael@0 10699 [31486, 59208], [16889, 59209], [31837, 59210], [31853, 59211],
michael@0 10700 [16913, 59212], [59213, 154547], [59214, 155324], [59215, 155302],
michael@0 10701 [31949, 59216], [59217, 150009], [59218, 137136], [31886, 59219],
michael@0 10702 [31868, 59220], [31918, 59221], [27314, 59222], [32220, 59223],
michael@0 10703 [32263, 59224], [32211, 59225], [32590, 59226], [59227, 156257],
michael@0 10704 [59228, 155996], [59229, 162632], [32151, 59230], [59231, 155266],
michael@0 10705 [17002, 59232], [59233, 158581], [59234, 133398], [26582, 59235],
michael@0 10706 [59236, 131150], [59237, 144847], [22468, 59238], [59239, 156690],
michael@0 10707 [59240, 156664], [32733, 59242], [31527, 59243], [59244, 133164],
michael@0 10708 [59245, 154345], [59246, 154947], [31500, 59247], [59248, 155150],
michael@0 10709 [39398, 59249], [34373, 59250], [39523, 59251], [27164, 59252],
michael@0 10710 [59253, 144447], [59255, 150007], [59256, 157101], [39455, 59257],
michael@0 10711 [59258, 157088], 0, [59260, 160039], [59261, 158929], [17642, 59262],
michael@0 10712 [33079, 59263], [17410, 59264], [32966, 59265], [33033, 59266],
michael@0 10713 [33090, 59267], [59268, 157620], [39107, 59269], [59270, 158274],
michael@0 10714 [33378, 59271], [33381, 59272], [59273, 158289], [33875, 59274],
michael@0 10715 [59275, 159143], [34320, 59276], [59277, 160283], [23174, 59278],
michael@0 10716 [16767, 59279], [59280, 137280], [23339, 59281], [59282, 137377],
michael@0 10717 [23268, 59283], [59284, 137432], [34464, 59285], [59286, 195004],
michael@0 10718 [59287, 146831], [34861, 59288], [59289, 160802], [23042, 59290],
michael@0 10719 [34926, 59291], [20293, 59292], [34951, 59293], [35007, 59294],
michael@0 10720 [35046, 59295], [35173, 59296], [35149, 59297], [59298, 153219],
michael@0 10721 [35156, 59299], [59300, 161669], [59301, 161668], [59302, 166901],
michael@0 10722 [59303, 166873], [59304, 166812], [59305, 166393], [16045, 59306],
michael@0 10723 [33955, 59307], [18165, 59308], [18127, 59309], [14322, 59310],
michael@0 10724 [35389, 59311], [35356, 59312], [59313, 169032], [24397, 59314],
michael@0 10725 [37419, 59315], [59316, 148100], [26068, 59317], [28969, 59318],
michael@0 10726 [28868, 59319], [59320, 137285], [40301, 59321], [35999, 59322],
michael@0 10727 [36073, 59323], [59324, 163292], [22938, 59325], [30659, 59326],
michael@0 10728 [23024, 59327], [14036, 59329], [36394, 59330], [36519, 59331],
michael@0 10729 [59332, 150537], [36656, 59333], [36682, 59334], [17140, 59335],
michael@0 10730 [27736, 59336], [28603, 59337], [59338, 140065], [18587, 59339],
michael@0 10731 [28537, 59340], [28299, 59341], [59342, 137178], [39913, 59343],
michael@0 10732 [14005, 59344], [59345, 149807], [37051, 59346], 0, [21873, 59348],
michael@0 10733 [18694, 59349], [37307, 59350], [37892, 59351], [59352, 166475],
michael@0 10734 [16482, 59353], [59354, 166652], [37927, 59355], [59356, 166941],
michael@0 10735 [59357, 166971], [34021, 59358], [35371, 59359], [38297, 59360],
michael@0 10736 [38311, 59361], [38295, 59362], [38294, 59363], [59364, 167220],
michael@0 10737 [29765, 59365], [16066, 59366], [59367, 149759], [59368, 150082],
michael@0 10738 [59369, 148458], [16103, 59370], [59371, 143909], [38543, 59372],
michael@0 10739 [59373, 167655], [59374, 167526], [59375, 167525], [16076, 59376],
michael@0 10740 [59377, 149997], [59378, 150136], [59379, 147438], [29714, 59380],
michael@0 10741 [29803, 59381], [16124, 59382], [38721, 59383], [59384, 168112],
michael@0 10742 [26695, 59385], [18973, 59386], [59387, 168083], [59388, 153567], 0,
michael@0 10743 [37736, 59390], [59391, 166281], [59392, 166950], [59393, 166703],
michael@0 10744 [59394, 156606], [37562, 59395], [23313, 59396], [35689, 59397],
michael@0 10745 [18748, 59398], [29689, 59399], [59400, 147995], [38811, 59401], 0,
michael@0 10746 [39224, 59403], [59404, 134950], [24001, 59405], [59406, 166853],
michael@0 10747 [59407, 150194], [38943, 59408], [59409, 169178], [37622, 59410],
michael@0 10748 [59411, 169431], [37349, 59412], [17600, 59413], [59414, 166736],
michael@0 10749 [59415, 150119], [59416, 166756], [39132, 59417], [59418, 166469],
michael@0 10750 [16128, 59419], [37418, 59420], [18725, 59421], [33812, 59422],
michael@0 10751 [39227, 59423], [39245, 59424], [59425, 162566], [15869, 59426], 0,
michael@0 10752 [19311, 59428], [39338, 59429], [39516, 59430], [59431, 166757],
michael@0 10753 [59432, 153800], [27279, 59433], [39457, 59434], [23294, 59435],
michael@0 10754 [39471, 59436], [59437, 170225], [19344, 59438], [59439, 170312],
michael@0 10755 [39356, 59440], [19389, 59441], [19351, 59442], [37757, 59443],
michael@0 10756 [22642, 59444], [59445, 135938], [22562, 59446], [59447, 149944],
michael@0 10757 [59448, 136424], [30788, 59449], [59450, 141087], [59451, 146872],
michael@0 10758 [26821, 59452], [15741, 59453], [37976, 59454], [14631, 59455],
michael@0 10759 [24912, 59456], [59457, 141185], [59458, 141675], [24839, 59459],
michael@0 10760 [40015, 59460], [40019, 59461], [40059, 59462], [39989, 59463],
michael@0 10761 [39952, 59464], [39807, 59465], [39887, 59466], [59467, 171565],
michael@0 10762 [39839, 59468], [59469, 172533], [59470, 172286], [40225, 59471],
michael@0 10763 [19630, 59472], [59473, 147716], [40472, 59474], [19632, 59475],
michael@0 10764 [40204, 59476], [59477, 172468], [59478, 172269], [59479, 172275],
michael@0 10765 [59480, 170287], [40357, 59481], [33981, 59482], [59483, 159250],
michael@0 10766 [59484, 159711], [59485, 158594], [34300, 59486], [17715, 59487],
michael@0 10767 [59488, 159140], [59489, 159364], [59490, 159216], [33824, 59491],
michael@0 10768 [34286, 59492], [59493, 159232], [59494, 145367], [59495, 155748],
michael@0 10769 [31202, 59496], [59497, 144796], [59498, 144960], [59500, 149982],
michael@0 10770 [15714, 59501], [37851, 59502], [37566, 59503], [37704, 59504],
michael@0 10771 [59505, 131775], [30905, 59506], [37495, 59507], [37965, 59508],
michael@0 10772 [20452, 59509], [13376, 59510], [36964, 59511], [59512, 152925],
michael@0 10773 [30781, 59513], [30804, 59514], [30902, 59515], [30795, 59516],
michael@0 10774 [59517, 137047], [59518, 143817], [59519, 149825], [13978, 59520],
michael@0 10775 [20338, 59521], [28634, 59522], [28633, 59523], 0, [28702, 59524, 59525],
michael@0 10776 [21524, 59526], [59527, 147893], [22459, 59528], [22771, 59529],
michael@0 10777 [22410, 59530], [40214, 59531], [22487, 59532], [28980, 59533],
michael@0 10778 [13487, 59534], [59535, 147884], [29163, 59536], [59537, 158784],
michael@0 10779 [59538, 151447], 0, [59540, 137141], [59541, 166473], [24844, 59542],
michael@0 10780 [23246, 59543], [23051, 59544], [17084, 59545], [59546, 148616],
michael@0 10781 [14124, 59547], [19323, 59548], [59549, 166396], [37819, 59550],
michael@0 10782 [37816, 59551], [59552, 137430], [59553, 134941], [33906, 59554],
michael@0 10783 [59555, 158912], [59556, 136211], [59557, 148218], [59558, 142374],
michael@0 10784 [59559, 148417], [22932, 59560], [59561, 146871], [59562, 157505],
michael@0 10785 [32168, 59563], [59564, 155995], [59565, 155812], [59566, 149945],
michael@0 10786 [59567, 149899], [59568, 166394], [37605, 59569], [29666, 59570],
michael@0 10787 [16105, 59571], [29876, 59572], [59573, 166755], [59574, 137375],
michael@0 10788 [16097, 59575], [59576, 150195], [27352, 59577], [29683, 59578],
michael@0 10789 [29691, 59579], [16086, 59580], [59581, 150078], [59582, 150164],
michael@0 10790 [59583, 137177], [59584, 150118], [59585, 132007], [59586, 136228],
michael@0 10791 [59587, 149989], [29768, 59588], [59589, 149782], [28837, 59590],
michael@0 10792 [59591, 149878], [37508, 59592], [29670, 59593], [37727, 59594],
michael@0 10793 [59595, 132350], [37681, 59596], [59597, 166606], [59598, 166422],
michael@0 10794 [37766, 59599], [59600, 166887], [59601, 153045], [18741, 59602],
michael@0 10795 [59603, 166530], [29035, 59604], [59605, 149827], [59606, 134399],
michael@0 10796 [22180, 59607], [59608, 132634], [59609, 134123], [59610, 134328],
michael@0 10797 [21762, 59611], [31172, 59612], [59613, 137210], [32254, 59614],
michael@0 10798 [59615, 136898], [59616, 150096], [59617, 137298], [17710, 59618],
michael@0 10799 [37889, 59619], [14090, 59620], [59621, 166592], [59622, 149933],
michael@0 10800 [22960, 59623], [59624, 137407], [59625, 137347], [59626, 160900],
michael@0 10801 [23201, 59627], [14050, 59628], [59629, 146779], [14000, 59630],
michael@0 10802 [37471, 59631], [23161, 59632], [59633, 166529], [59634, 137314],
michael@0 10803 [37748, 59635], [15565, 59636], [59637, 133812], [19094, 59638],
michael@0 10804 [14730, 59639], [20724, 59640], [15721, 59641], [15692, 59642],
michael@0 10805 [59643, 136092], [29045, 59644], [17147, 59645], [59646, 164376],
michael@0 10806 [28175, 59647], [59648, 168164], [17643, 59649], [27991, 59650],
michael@0 10807 [59651, 163407], [28775, 59652], [27823, 59653], [15574, 59654],
michael@0 10808 [59655, 147437], [59656, 146989], [28162, 59657], [28428, 59658],
michael@0 10809 [15727, 59659], [59660, 132085], [30033, 59661], [14012, 59662],
michael@0 10810 [13512, 59663], [18048, 59664], [16090, 59665], [18545, 59666],
michael@0 10811 [22980, 59667], [37486, 59668], [18750, 59669], [36673, 59670],
michael@0 10812 [59671, 166940], [59672, 158656], [22546, 59673], [22472, 59674],
michael@0 10813 [14038, 59675], [59676, 136274], [28926, 59677], [59678, 148322],
michael@0 10814 [59679, 150129], [59680, 143331], [59681, 135856], [59682, 140221],
michael@0 10815 [26809, 59683], [26983, 59684], [59685, 136088], [59686, 144613],
michael@0 10816 [59687, 162804], [59688, 145119], [59689, 166531], [59690, 145366],
michael@0 10817 [59691, 144378], [59692, 150687], [27162, 59693], [59694, 145069],
michael@0 10818 [59695, 158903], [33854, 59696], [17631, 59697], [17614, 59698],
michael@0 10819 [59699, 159014], [59700, 159057], [59701, 158850], [59702, 159710], 0, 0,
michael@0 10820 [33597, 59705], [59706, 137018], [33773, 59707], [59708, 158848],
michael@0 10821 [59709, 159827], [59710, 137179], [22921, 59711], [23170, 59712],
michael@0 10822 [59713, 137139], [23137, 59714], [23153, 59715], [59716, 137477],
michael@0 10823 [59717, 147964], [14125, 59718], [23023, 59719], [59720, 137020],
michael@0 10824 [14023, 59721], [29070, 59722], [37776, 59723], [26266, 59724],
michael@0 10825 [59725, 148133], [23150, 59726], [23083, 59727], [59728, 148115],
michael@0 10826 [27179, 59729], [59730, 147193], [59731, 161590], [59732, 148571],
michael@0 10827 [59733, 148170], [28957, 59734], [59735, 148057], [59736, 166369],
michael@0 10828 [20400, 59737], [59738, 159016], [23746, 59739], [59740, 148686],
michael@0 10829 [59741, 163405], [59742, 148413], [27148, 59743], [59744, 148054],
michael@0 10830 [59745, 135940], 0, [28979, 59747], [59748, 148457], [15781, 59749],
michael@0 10831 [27871, 59750], [59751, 194597], [23019, 59754], [24412, 59757],
michael@0 10832 [59764, 144128], [31955, 59776], [59783, 162548], [59786, 153334],
michael@0 10833 [59790, 162584], [36972, 59791], [33270, 59795], [30476, 59797],
michael@0 10834 [27810, 59799], [22269, 59800], [22633, 59828], [26465, 59832],
michael@0 10835 [23646, 59838], [22770, 59841], [28857, 59843], [26627, 59853],
michael@0 10836 [36795, 59859], [36796, 59861], [20001, 59871], [31545, 59898],
michael@0 10837 [15820, 59902], [29482, 57990, 59909], [30048, 59912], [22586, 59920],
michael@0 10838 [33446, 59932], [27018, 59940], [24803, 59944], [20206, 59984],
michael@0 10839 [39364, 60002], [40639, 60023], [21249, 60025], [26528, 60038],
michael@0 10840 [24808, 60046], [20916, 60053], [31363, 60064], [39994, 60075],
michael@0 10841 [31432, 60093], [26906, 60098], [22956, 60100], [22592, 60102],
michael@0 10842 [21610, 60114], [24807, 60123], [22138, 60125], [26965, 60132],
michael@0 10843 [39983, 60133], [34725, 60134], [23584, 60141], [24075, 60143],
michael@0 10844 [26398, 60147], [33965, 60157], [35713, 60161], [20088, 60166],
michael@0 10845 [25283, 60176], [26709, 60180], 0, [33533, 60190], [35237, 60194],
michael@0 10846 [36768, 60196], [38840, 60198], [38983, 60200], [39613, 60201],
michael@0 10847 [24497, 60218], [26184, 60219], [26303, 60220], [60221, 162425], 0,
michael@0 10848 [60225, 149946], 0, 0, [60230, 131910], [26382, 60232], [26904, 60233],
michael@0 10849 [60235, 161367], [60236, 155618], [60239, 161278], [60240, 139418],
michael@0 10850 [18640, 60241], [19128, 60242], [60244, 166554], [60247, 147515],
michael@0 10851 [60250, 150085], [60251, 132554], [20946, 60252], [60253, 132625],
michael@0 10852 [22943, 60254], [60255, 138920], [15294, 60256], [60257, 146687],
michael@0 10853 [14747, 60262], [60264, 165352], [60265, 170441], [14178, 60266],
michael@0 10854 [60267, 139715], [35678, 60268], [60269, 166734], 0, [29193, 60274],
michael@0 10855 [60276, 134264], [60280, 132985], [36570, 60281], [21135, 60283],
michael@0 10856 [29041, 60285], [60288, 147274], [60289, 150183], [21948, 60290],
michael@0 10857 [60293, 158546], [13427, 60295], [60297, 161330], [18200, 60299],
michael@0 10858 [60303, 149823], [20582, 60305], [13563, 60306], [60307, 144332], 0,
michael@0 10859 [18300, 60310], [60311, 166216], [60315, 138640], 0, [60320, 162834],
michael@0 10860 [36950, 60321], [60323, 151450], [35682, 60324], [23899, 60327],
michael@0 10861 [60328, 158711], 0, [60331, 137500], [35562, 60332], [60333, 150006],
michael@0 10862 [60335, 147439], [19392, 60337], [60340, 141083], [37989, 60341],
michael@0 10863 [60342, 153569], [24981, 60343], [23079, 60344], [60345, 194765], 0,
michael@0 10864 [60348, 148769], [20074, 60350], [60351, 149812], [38486, 60352],
michael@0 10865 [28047, 60353], [60354, 158909], [35191, 60356], [60359, 156689], 0,
michael@0 10866 [31554, 60363], [60364, 168128], [60365, 133649], 0, [31301, 60369],
michael@0 10867 [39462, 60372], [13919, 60374], [60375, 156777], [60376, 131105],
michael@0 10868 [31107, 60377], [23852, 60380], [60381, 144665], 0, [18128, 60384],
michael@0 10869 [30011, 60386], [34917, 60387], [22710, 60389], [14108, 60390],
michael@0 10870 [60391, 140685], [15444, 60394], [37505, 60397], [60398, 139642],
michael@0 10871 [37680, 60400], [60402, 149968], [27705, 60403], [60406, 134904],
michael@0 10872 [34855, 60407], [35061, 60408], [60409, 141606], [60410, 164979],
michael@0 10873 [60411, 137137], [28344, 60412], [60413, 150058], [60414, 137248],
michael@0 10874 [14756, 60415], 0, 0, [17727, 60419], [26294, 60420], [60421, 171181],
michael@0 10875 [60422, 170148], [35139, 60423], [16607, 60427], [60428, 136714],
michael@0 10876 [14753, 60429], [60430, 145199], [60431, 164072], [60432, 136133],
michael@0 10877 [29101, 60433], [33638, 60434], [60436, 168360], 0, [19639, 60438],
michael@0 10878 [60439, 159919], [60440, 166315], [60445, 147834], [31555, 60446],
michael@0 10879 [31102, 60447], [28597, 60449], [60450, 172767], [27139, 60451],
michael@0 10880 [60452, 164632], [21410, 60453], [60454, 159239], [37823, 60455],
michael@0 10881 [26678, 60456], [38749, 59389, 60457], [60458, 164207], [60460, 158133],
michael@0 10882 [60461, 136173], [60462, 143919], [23941, 60464], [60465, 166960],
michael@0 10883 [22293, 60467], [38947, 60468], [60469, 166217], [23979, 60470],
michael@0 10884 [60471, 149896], [26046, 60472], [27093, 60473], [21458, 60474],
michael@0 10885 [60475, 150181], [60476, 147329], [15377, 60477], [26422, 60478],
michael@0 10886 [60482, 139169], [13770, 60490], [18682, 60493], 0, [30728, 60496],
michael@0 10887 [37461, 60497], [17394, 60499], [17375, 60501], [23032, 60505], 0,
michael@0 10888 [22155, 60518], [60520, 169449], [36882, 60541], [21953, 60546],
michael@0 10889 [17673, 60551], [32383, 60552], [28502, 60553], [27313, 60554],
michael@0 10890 [13540, 60556], [60558, 161949], [14138, 60559], 0, [60562, 163876],
michael@0 10891 [60565, 162366], [15851, 60567], [60569, 146615], [60574, 156248],
michael@0 10892 [22207, 60575], [36366, 60577], [23405, 60578], [25566, 60581], 0,
michael@0 10893 [25904, 60585], [22061, 60586], [21530, 60588], [60591, 171416],
michael@0 10894 [19581, 60592], [22050, 60593], [22046, 60594], [32585, 60595],
michael@0 10895 [22901, 60597], [60598, 146752], [34672, 60599], [33047, 60604],
michael@0 10896 [40286, 60605], [36120, 60606], [30267, 60607], [40005, 60608],
michael@0 10897 [30286, 60609], [30649, 60610], [37701, 60611], [21554, 60612],
michael@0 10898 [33096, 60613], [33527, 60614], [22053, 60615], [33074, 60616],
michael@0 10899 [33816, 60617], [32957, 60618], [21994, 60619], [31074, 60620],
michael@0 10900 [22083, 60621], [21526, 60622], [60623, 134813], [13774, 60624],
michael@0 10901 [22021, 57509, 60625], [22001, 60626], [26353, 60627], [60628, 164578],
michael@0 10902 [13869, 60629], [30004, 60630], [22000, 60631], [21946, 60632],
michael@0 10903 [21655, 60633], [21874, 60634], [60635, 134209], [60636, 134294],
michael@0 10904 [24272, 57652, 60637], [60639, 134774], [60640, 142434], [60641, 134818],
michael@0 10905 [40619, 60642], [32090, 60643], 0, [60645, 135285], [25245, 60646],
michael@0 10906 [38765, 60647], [21652, 60648], [36045, 60649], [29174, 60650],
michael@0 10907 [37238, 60651], [25596, 60652], [25529, 60653], [25598, 60654],
michael@0 10908 [21865, 60655], [60656, 142147], [40050, 60657], [60658, 143027],
michael@0 10909 [20890, 60659], [13535, 60660], [60661, 134567], [20903, 60662],
michael@0 10910 [21581, 60663], [21790, 60664], [21779, 60665], [30310, 60666],
michael@0 10911 [36397, 60667], [60668, 157834], [30129, 60669], [32950, 60670],
michael@0 10912 [34820, 60671], 0, [35015, 60673], [33206, 60674], [33820, 60675],
michael@0 10913 [17644, 60677], [29444, 60678], [33547, 60681], [22139, 60683],
michael@0 10914 [37232, 60690], [37384, 60692], [60696, 134905], [29286, 60697],
michael@0 10915 [18254, 60699], [60701, 163833], [16634, 60703], [40029, 60704],
michael@0 10916 [25887, 60705], [18675, 60707], [60708, 149472], [60709, 171388], 0,
michael@0 10917 [60713, 161187], 60715, [60716, 155720], [29091, 60718], [32398, 60719],
michael@0 10918 [40272, 60720], [13687, 60723], [27826, 60725], [21351, 60726],
michael@0 10919 [14812, 60728], [60731, 149016], [33325, 60734], [21579, 60735], 60739,
michael@0 10920 [14930, 60740], [29556, 60742], [60743, 171692], [19721, 60744],
michael@0 10921 [39917, 60745], 0, [19547, 60748], [60751, 171998], [33884, 60752],
michael@0 10922 [60754, 160434], [25390, 60757], [32037, 60758], [14890, 60761],
michael@0 10923 [36872, 60762], [21196, 60763], [15988, 60764], [13946, 60765],
michael@0 10924 [17897, 60766], [60767, 132238], [30272, 60768], [23280, 60769],
michael@0 10925 [60770, 134838], [30842, 60771], [18358, 60772], [22695, 60773],
michael@0 10926 [16575, 60774], [22140, 60775], [39819, 60776], [23924, 60777],
michael@0 10927 [30292, 60778], [60779, 173108], [40581, 60780], [19681, 60781], 0,
michael@0 10928 [14331, 60783], [24857, 60784], [60786, 148466], 60787, [22109, 60788],
michael@0 10929 [60792, 171526], [21044, 60793], [13741, 60795], 0, [40316, 60797],
michael@0 10930 [31830, 60798], [39737, 60799], [22494, 60800], [23635, 60802],
michael@0 10931 [25811, 60803], [60804, 169168], [60805, 156469], [34477, 60807],
michael@0 10932 [60808, 134440], [60811, 134513], 60812, [20990, 60813], [60814, 139023],
michael@0 10933 [23950, 60815], [38659, 60816], [60817, 138705], [40577, 60818],
michael@0 10934 [36940, 60819], [31519, 60820], [39682, 60821], [23761, 60822],
michael@0 10935 [31651, 60823], [25192, 60824], [25397, 60825], [39679, 60826],
michael@0 10936 [31695, 60827], [39722, 60828], [31870, 60829], 0, [31810, 60831],
michael@0 10937 [31878, 60832], [39957, 60833], [31740, 60834], [39689, 60835], 0, 39982,
michael@0 10938 [40794, 60839], [21875, 60840], [23491, 60841], [20477, 60842],
michael@0 10939 [40600, 60843], [20466, 60844], [21088, 60845], [21201, 60847],
michael@0 10940 [22375, 60848], [20566, 60849], [22967, 60850], [24082, 60851],
michael@0 10941 [38856, 60852], [40363, 60853], [36700, 60854], [21609, 60855],
michael@0 10942 [38836, 60856], [39232, 60857], [38842, 60858], [21292, 60859],
michael@0 10943 [24880, 60860], [26924, 60861], [21466, 60862], [39946, 60863],
michael@0 10944 [40194, 60864], [19515, 60865], [38465, 60866], [27008, 60867],
michael@0 10945 [20646, 60868], [30022, 60869], [60870, 137069], [39386, 60871],
michael@0 10946 [21107, 60872], 60873, [37209, 60874], [38529, 60875], [37212, 60876],
michael@0 10947 60877, [37201, 60878], [60879, 167575], [25471, 60880], [27338, 60882],
michael@0 10948 [22033, 60883], [37262, 60884], [30074, 60885], [25221, 60886],
michael@0 10949 [29519, 60888], [31856, 60889], [60890, 154657], 60892, [30422, 60894],
michael@0 10950 [39837, 60895], [20010, 60896], [60897, 134356], [33726, 60898],
michael@0 10951 [34882, 60899], 60900, [23626, 60901], [27072, 60902], 0, 0,
michael@0 10952 [21023, 60905], [24053, 60906], [20174, 60907], [27697, 60908],
michael@0 10953 [60909, 131570], [20281, 60910], [21660, 60911], 0, [21146, 60913],
michael@0 10954 [36226, 60914], [13822, 60915], 0, [13811, 60917], 60918, [27474, 60919],
michael@0 10955 [37244, 60920], [40869, 60921], [39831, 60922], [38958, 60923],
michael@0 10956 [39092, 60924], [39610, 60925], [40616, 60926], [40580, 60927],
michael@0 10957 [31508, 60929], 60930, [27642, 60931], [34840, 60932], [32632, 60933],
michael@0 10958 60934, [22048, 60935], [60936, 173642], [36471, 60937], [40787, 60938],
michael@0 10959 60939, [36308, 60940], [36431, 60941], [40476, 60942], [36353, 60943],
michael@0 10960 [25218, 60944], [60945, 164733], [36392, 60946], [36469, 60947],
michael@0 10961 [31443, 60948], [31294, 60950], [30936, 60951], [27882, 60952],
michael@0 10962 [35431, 60953], [30215, 60954], [40742, 60956], [27854, 60957],
michael@0 10963 [34774, 60958], [30147, 60959], [60960, 172722], [30803, 60961],
michael@0 10964 [36108, 60963], [29410, 60964], [29553, 60965], [35629, 60966],
michael@0 10965 [29442, 60967], [29937, 60968], [36075, 60969], [60970, 150203],
michael@0 10966 [34351, 60971], [24506, 60972], [34976, 60973], [17591, 60974], 60975,
michael@0 10967 [60977, 159237], 60978, [35454, 60979], [60980, 140571], 60981,
michael@0 10968 [24829, 60982], [30311, 60983], [39639, 60984], [40260, 60985],
michael@0 10969 [37742, 58859, 60986], [39823, 60987], [34805, 60988], 60989, 0,
michael@0 10970 [36087, 60991], [29484, 60992], [38689, 60993], [39856, 60994],
michael@0 10971 [13782, 60995], [29362, 60996], [19463, 60997], [31825, 60998],
michael@0 10972 [39242, 60999], [24921, 61001], [19460, 61002], [40598, 61003],
michael@0 10973 [24957, 61004], 61005, [22367, 61006], [24943, 61007], [25254, 61008],
michael@0 10974 [25145, 61009], 0, [14940, 61011], [25058, 61012], [21418, 61013],
michael@0 10975 [25444, 61015], [26626, 61016], [13778, 61017], [23895, 61018],
michael@0 10976 [36826, 61020], [61021, 167481], 61022, [20697, 61023], [30982, 61025],
michael@0 10977 [21298, 61026], [38456, 61027], [61028, 134971], [16485, 61029], 61030,
michael@0 10978 [30718, 61031], 61032, [31938, 61033], [61034, 155418], [31962, 61035],
michael@0 10979 [31277, 61036], [32870, 61037], [32867, 61038], [32077, 61039],
michael@0 10980 [29957, 61040], [29938, 61041], [35220, 61042], [33306, 61043],
michael@0 10981 [26380, 61044], [32866, 61045], [61046, 160902], [32859, 61047],
michael@0 10982 [29936, 61048], [33027, 61049], [30500, 61050], [35209, 61051],
michael@0 10983 [61052, 157644], [30035, 61053], [34729, 61055], [34766, 61056],
michael@0 10984 [33224, 61057], [34700, 61058], [35401, 61059], [36013, 61060],
michael@0 10985 [35651, 61061], [30507, 61062], [29944, 61063], [34010, 61064],
michael@0 10986 [27058, 61066], [36262, 61067], 61068, [35241, 58392, 61069], 0,
michael@0 10987 [28089, 61071], [34753, 61072], [61073, 147473], [29927, 61074],
michael@0 10988 [15835, 61075], [29046, 61076], [24740, 57702, 61077], [24988, 61078],
michael@0 10989 [15569, 61079], 0, [24695, 61081], 61082, [32625, 61083], 0,
michael@0 10990 [24809, 61086], [19326, 61087], [57344, 132423], [37595, 57345],
michael@0 10991 [57346, 132575], [57347, 147397], [34124, 57348], [17077, 57349],
michael@0 10992 [29679, 57350], [20917, 57351], [13897, 57352], [57353, 149826],
michael@0 10993 [57354, 166372], [37700, 57355], [57356, 137691], [33518, 57357],
michael@0 10994 [57358, 146632], [30780, 57359], [26436, 57360], [25311, 57361],
michael@0 10995 [57362, 149811], [57363, 166314], [57364, 131744], [57365, 158643],
michael@0 10996 [57366, 135941], [20395, 57367], [57368, 140525], [20488, 57369],
michael@0 10997 [57370, 159017], [57371, 162436], [57372, 144896], [57373, 150193],
michael@0 10998 [57374, 140563], 0, [57376, 131966], [24484, 57377], [57378, 131968],
michael@0 10999 [57379, 131911], [28379, 57380], [57381, 132127], 20702, [20737, 57383],
michael@0 11000 [13434, 57384], [20750, 57385], [39020, 57386], [14147, 57387],
michael@0 11001 [33814, 57388], [57389, 149924], [57390, 132231], [20832, 57391],
michael@0 11002 [57392, 144308], [20842, 57393], [57394, 134143], [57395, 139516],
michael@0 11003 [57396, 131813], [57397, 140592], [57398, 132494], [57399, 143923],
michael@0 11004 [57400, 137603], [23426, 57401], [34685, 57402], [57403, 132531],
michael@0 11005 [57404, 146585], [20914, 57405], [20920, 57406], [40244, 57407],
michael@0 11006 [20937, 57408], [20943, 57409], [20945, 57410], [15580, 57411],
michael@0 11007 [20947, 57412], [57413, 150182], [20915, 57414], 0, 0, [20973, 57417],
michael@0 11008 [33741, 57418], [26942, 57419], [57420, 145197], [24443, 57421],
michael@0 11009 [21003, 57422], [21030, 57423], [21052, 57424], [21173, 57425],
michael@0 11010 [21079, 57426], [21140, 57427], [21177, 57428], [21189, 57429],
michael@0 11011 [31765, 57430], [34114, 57431], [21216, 57432], [34317, 57433],
michael@0 11012 [57434, 158483], 0, [57436, 166622], [21833, 57437], [28377, 57438],
michael@0 11013 [57439, 147328], [57440, 133460], [57441, 147436], [21299, 57442], 0,
michael@0 11014 [57444, 134114], [27851, 57445], [57446, 136998], [26651, 57447],
michael@0 11015 [29653, 57448], [24650, 57449], [16042, 57450], [14540, 57451],
michael@0 11016 [57452, 136936], [29149, 57453], [17570, 57454], [21357, 57455],
michael@0 11017 [21364, 57456], [57457, 165547], [21374, 57458], 0, [57460, 136598],
michael@0 11018 [57461, 136723], [30694, 57462], [21395, 57463], [57464, 166555],
michael@0 11019 [21408, 57465], [21419, 57466], [21422, 57467], [29607, 57468],
michael@0 11020 [57469, 153458], [16217, 57470], [29596, 57471], [21441, 57472],
michael@0 11021 [21445, 57473], [27721, 57474], [20041, 57475], [22526, 57476],
michael@0 11022 [21465, 57477], [15019, 57478], [57479, 134031], [21472, 57480],
michael@0 11023 [57481, 147435], [57482, 142755], [21494, 57483], [57484, 134263],
michael@0 11024 [21523, 57485], [28793, 57486], [21803, 57487], [26199, 57488],
michael@0 11025 [27995, 57489], [21613, 57490], [57491, 158547], [57492, 134516],
michael@0 11026 [21853, 57493], [21647, 57494], [21668, 57495], [18342, 57496],
michael@0 11027 [57497, 136973], [57498, 134877], [15796, 57499], [57500, 134477],
michael@0 11028 [57501, 166332], [57502, 140952], [21831, 57503], [19693, 57504],
michael@0 11029 [21551, 57505], [29719, 57506], [21894, 57507], [21929, 57508], 0,
michael@0 11030 [57510, 137431], [57511, 147514], [17746, 57512], [57513, 148533],
michael@0 11031 [26291, 57514], [57515, 135348], [22071, 57516], [26317, 57517],
michael@0 11032 [57518, 144010], [26276, 57519], 0, [22093, 57521], [22095, 57522],
michael@0 11033 [30961, 57523], [22257, 57524], [38791, 57525], [21502, 57526],
michael@0 11034 [22272, 57527], [22255, 57528], [22253, 57529], [57530, 166758],
michael@0 11035 [13859, 57531], [57532, 135759], [22342, 57533], [57534, 147877],
michael@0 11036 [27758, 57535], [28811, 57536], [22338, 57537], [14001, 57538],
michael@0 11037 [57539, 158846], [22502, 57540], [57541, 136214], [22531, 57542],
michael@0 11038 [57543, 136276], [57544, 148323], [22566, 57545], [57546, 150517], 0,
michael@0 11039 [22698, 57548], [13665, 57549], [22752, 57550], [22748, 57551],
michael@0 11040 [57552, 135740], [22779, 57553], [23551, 57554], [22339, 57555],
michael@0 11041 [57556, 172368], [57557, 148088], [37843, 57558], [13729, 57559],
michael@0 11042 [22815, 57560], [26790, 57561], [14019, 57562], [28249, 57563],
michael@0 11043 [57564, 136766], [23076, 57565], 0, [57567, 136850], [34053, 57568],
michael@0 11044 [22985, 57569], [57570, 134478], [57571, 158849], [57572, 159018],
michael@0 11045 [57573, 137180], [23001, 57574], [57575, 137211], [57576, 137138],
michael@0 11046 [57577, 159142], [28017, 57578], [57579, 137256], [57580, 136917],
michael@0 11047 [23033, 57581], [57582, 159301], [23211, 57583], [23139, 57584],
michael@0 11048 [14054, 57585], [57586, 149929], 0, [14088, 57588], [23190, 57589],
michael@0 11049 [29797, 57590], [23251, 57591], [57592, 159649], [57593, 140628],
michael@0 11050 [57595, 137489], [14130, 57596], [57597, 136888], [24195, 57598],
michael@0 11051 [21200, 57599], [23414, 57600], [25992, 57601], [23420, 57602],
michael@0 11052 [57603, 162318], [16388, 57604], [18525, 57605], [57606, 131588],
michael@0 11053 [23509, 57607], [57609, 137780], [57610, 154060], [57611, 132517],
michael@0 11054 [23539, 57612], [23453, 57613], [19728, 57614], [23557, 57615],
michael@0 11055 [57616, 138052], [23571, 57617], [29646, 57618], [23572, 57619],
michael@0 11056 [57620, 138405], [57621, 158504], [23625, 57622], [18653, 57623],
michael@0 11057 [23685, 57624], [23785, 57625], [23791, 57626], [23947, 57627],
michael@0 11058 [57628, 138745], [57629, 138807], [23824, 57630], [23832, 57631],
michael@0 11059 [23878, 57632], [57633, 138916], [23738, 57634], [24023, 57635],
michael@0 11060 [33532, 57636], [14381, 57637], [57638, 149761], [57639, 139337],
michael@0 11061 [57640, 139635], [33415, 57641], [14390, 57642], [15298, 57643],
michael@0 11062 [24110, 57644], [27274, 57645], 0, 57647, [57648, 148668], [57649, 134355],
michael@0 11063 [21414, 57650], [20151, 57651], 0, [21416, 57653], [57654, 137073],
michael@0 11064 [24073, 57655], 57656, [57657, 164994], [24313, 57658], [24315, 57659],
michael@0 11065 [14496, 57660], [24316, 57661], [26686, 57662], [37915, 57663],
michael@0 11066 [24333, 57664], [57665, 131521], [57666, 194708], [15070, 57667],
michael@0 11067 [57669, 135994], [24378, 57670], [57671, 157832], [57672, 140240],
michael@0 11068 [57674, 140401], [24419, 57675], [57677, 159342], [24434, 57678],
michael@0 11069 [37696, 57679], [57680, 166454], [24487, 57681], [23990, 57682],
michael@0 11070 [15711, 57683], [57684, 152144], [57685, 139114], [57686, 159992],
michael@0 11071 [57687, 140904], [37334, 57688], [57689, 131742], [57690, 166441],
michael@0 11072 [24625, 57691], [26245, 57692], [14691, 57694], [15815, 57695],
michael@0 11073 [13881, 57696], [22416, 57697], [57698, 141236], [31089, 57699],
michael@0 11074 [15936, 57700], [24734, 57701], 0, 0, [57704, 149890], [57705, 149903],
michael@0 11075 [57706, 162387], [29860, 57707], [20705, 57708], [23200, 57709],
michael@0 11076 [24932, 57710], [24898, 57712], [57713, 194726], [57714, 159442],
michael@0 11077 [24961, 57715], [20980, 57716], [57717, 132694], [24967, 57718],
michael@0 11078 [23466, 57719], [57720, 147383], [57721, 141407], [25043, 57722],
michael@0 11079 [57723, 166813], [57724, 170333], [25040, 57725], [14642, 57726],
michael@0 11080 [57727, 141696], [57728, 141505], [24611, 57729], [24924, 57730],
michael@0 11081 [25886, 57731], [25483, 57732], [57733, 131352], [25285, 57734],
michael@0 11082 [57735, 137072], [25301, 57736], [57737, 142861], [25452, 57738],
michael@0 11083 [57739, 149983], [14871, 57740], [25656, 57741], [25592, 57742],
michael@0 11084 [57743, 136078], [57744, 137212], [28554, 57746], [57747, 142902], 0,
michael@0 11085 [57750, 153373], [25825, 57751], [25829, 57752], [38011, 57753],
michael@0 11086 [14950, 57754], [25658, 57755], [14935, 57756], [25933, 57757],
michael@0 11087 [28438, 57758], [57759, 150056], [57760, 150051], [25989, 57761],
michael@0 11088 [25965, 57762], [25951, 57763], 0, [26037, 57765], [57766, 149824],
michael@0 11089 [19255, 57767], [26065, 57768], [16600, 57769], [57770, 137257], 57771,
michael@0 11090 [26083, 57772], [24543, 57773], [57774, 144384], [26136, 57775],
michael@0 11091 [57776, 143863], [57777, 143864], [26180, 57778], [57779, 143780],
michael@0 11092 [57780, 143781], [26187, 57781], [57782, 134773], [26215, 57783],
michael@0 11093 [57784, 152038], [26227, 57785], 0, [57788, 143921], [57789, 165364],
michael@0 11094 [57790, 143816], [57791, 152339], [30661, 57792], [57793, 141559],
michael@0 11095 [39332, 57794], [26370, 57795], [57796, 148380], [57797, 150049],
michael@0 11096 [27130, 57799], [57800, 145346], 0, [26471, 57802], [26466, 57803],
michael@0 11097 [57804, 147917], [57805, 168173], [26583, 57806], [17641, 57807],
michael@0 11098 [26658, 57808], [28240, 57809], [37436, 57810], [26625, 57811],
michael@0 11099 [57812, 144358], [57813, 159136], [26717, 57814], [57815, 144495],
michael@0 11100 [27105, 57816], [27147, 57817], [57818, 166623], [26995, 57819],
michael@0 11101 [26819, 57820], [57821, 144845], [26881, 57822], [26880, 57823],
michael@0 11102 [14849, 57825], [57826, 144956], [15232, 57827], [26540, 57828],
michael@0 11103 [26977, 57829], [57830, 166474], [17148, 57831], [26934, 57832],
michael@0 11104 [27032, 57833], [15265, 57834], [57835, 132041], [33635, 57836],
michael@0 11105 [20624, 57837], [27129, 57838], [57839, 144985], [57840, 139562],
michael@0 11106 [27205, 57841], [57842, 145155], [27293, 57843], [15347, 57844],
michael@0 11107 [26545, 57845], [27336, 57846], [57847, 168348], [15373, 57848],
michael@0 11108 [27421, 57849], [57850, 133411], [24798, 57851, 60308], [27445, 57852],
michael@0 11109 [27508, 57853], [57854, 141261], [28341, 57855], [57856, 146139], 0,
michael@0 11110 [57858, 137560], [14144, 57859], [21537, 57860], [57861, 146266],
michael@0 11111 [27617, 57862], [57863, 147196], [27612, 57864], [27703, 57865],
michael@0 11112 [57866, 140427], [57867, 149745], [57868, 158545], [27738, 57869],
michael@0 11113 [33318, 57870], [27769, 57871], [57872, 146876], [17605, 57873],
michael@0 11114 [57874, 146877], [57875, 147876], [57876, 149772], [57877, 149760],
michael@0 11115 [57878, 146633], [14053, 57879], [15595, 57880], [57881, 134450],
michael@0 11116 [39811, 57882], [57883, 143865], [57884, 140433], [32655, 57885],
michael@0 11117 [26679, 57886], [57887, 159013], [57888, 159137], [57889, 159211],
michael@0 11118 [28054, 57890], [27996, 57891], [28284, 57892], [28420, 57893],
michael@0 11119 [57894, 149887], [57895, 147589], [57896, 159346], [34099, 57897],
michael@0 11120 [57898, 159604], [20935, 57899], 0, 0, [33838, 57902], [57903, 166689], 0,
michael@0 11121 [57905, 146991], [29779, 57906], [57907, 147330], [31180, 57908],
michael@0 11122 [28239, 57909], [23185, 57910], [57911, 143435], [28664, 57912],
michael@0 11123 [14093, 57913], [28573, 57914], [57915, 146992], [28410, 57916],
michael@0 11124 [57917, 136343], [57918, 147517], [17749, 57919], [37872, 57920],
michael@0 11125 [28484, 57921], [28508, 57922], [15694, 57923], [28532, 57924],
michael@0 11126 [57925, 168304], [15675, 57926], [28575, 57927], [57928, 147780],
michael@0 11127 [28627, 57929], [57930, 147601], [57931, 147797], [57932, 147513],
michael@0 11128 [57933, 147440], [57934, 147380], [57935, 147775], [20959, 57936],
michael@0 11129 [57937, 147798], [57938, 147799], [57939, 147776], [57940, 156125],
michael@0 11130 [28747, 57941], [28798, 57942], [28839, 57943], 0, [28876, 57945],
michael@0 11131 [28885, 57946], [28886, 57947], [28895, 57948], [16644, 57949],
michael@0 11132 [15848, 57950], [29108, 57951], [29078, 57952], [57953, 148087],
michael@0 11133 [28971, 57954], [28997, 57955], [23176, 57956], [29002, 57957], 0,
michael@0 11134 [57960, 148325], [29007, 57961], [37730, 57962], [57963, 148161],
michael@0 11135 [28972, 57964], [57965, 148570], [57966, 150055], [57967, 150050],
michael@0 11136 [29114, 57968], [57969, 166888], [28861, 57970], [29198, 57971],
michael@0 11137 [37954, 57972], [29205, 57973], [22801, 57974], [37955, 57975],
michael@0 11138 [29220, 57976], [37697, 57977], [57978, 153093], [29230, 57979],
michael@0 11139 [29248, 57980], [57981, 149876], [26813, 57982], [29269, 57983],
michael@0 11140 [29271, 57984], [15957, 57985], [57986, 143428], [26637, 57987],
michael@0 11141 [28477, 57988], [29314, 57989], 0, [29483, 57991], [57992, 149539],
michael@0 11142 [57993, 165931], [18669, 57994], [57995, 165892], [29480, 57996],
michael@0 11143 [29486, 57997], [29647, 57998], [29610, 57999], [58000, 134202],
michael@0 11144 [58001, 158254], [29641, 58002], [29769, 58003], [58004, 147938],
michael@0 11145 [58005, 136935], [58006, 150052], [26147, 58007], [14021, 58008],
michael@0 11146 [58009, 149943], [58010, 149901], [58011, 150011], [29687, 58012],
michael@0 11147 [29717, 58013], [26883, 58014], [58015, 150054], [29753, 58016],
michael@0 11148 [16087, 58018], 0, [58020, 141485], [29792, 58021], [58022, 167602],
michael@0 11149 [29767, 58023], [29668, 58024], [29814, 58025], [33721, 58026],
michael@0 11150 [29804, 58027], [29812, 58029], [37873, 58030], [27180, 58031],
michael@0 11151 [29826, 58032], [18771, 58033], [58034, 150156], [58035, 147807],
michael@0 11152 [58036, 150137], [58037, 166799], [23366, 58038], [58039, 166915],
michael@0 11153 [58040, 137374], [29896, 58041], [58042, 137608], [29966, 58043],
michael@0 11154 [29982, 58045], [58046, 167641], [58047, 137803], [23511, 58048],
michael@0 11155 [58049, 167596], [37765, 58050], [30029, 58051], [30026, 58052],
michael@0 11156 [30055, 58053], [30062, 58054], [58055, 151426], [16132, 58056],
michael@0 11157 [58057, 150803], [30094, 58058], [29789, 58059], [30110, 58060],
michael@0 11158 [30132, 58061], [30210, 58062], [30252, 58063], [30289, 58064],
michael@0 11159 [30287, 58065], [30319, 58066], 58067, [58068, 156661], [30352, 58069],
michael@0 11160 [33263, 58070], [14328, 58071], [58072, 157969], [58073, 157966],
michael@0 11161 [30369, 58074], [30373, 58075], [30391, 58076], [30412, 58077],
michael@0 11162 [58078, 159647], [33890, 58079], [58080, 151709], [58081, 151933],
michael@0 11163 [58082, 138780], [30494, 58083], [30502, 58084], [30528, 58085],
michael@0 11164 [25775, 58086], [58087, 152096], [30552, 58088], [58089, 144044],
michael@0 11165 [30639, 58090], [58091, 166244], [58092, 166248], [58093, 136897],
michael@0 11166 [30708, 58094], 0, [26826, 58098], [30895, 58099], [30919, 58100],
michael@0 11167 [30931, 58101], [38565, 58102], [31022, 58103], [58104, 153056],
michael@0 11168 [30935, 58105], [31028, 58106], [30897, 58107], [58108, 161292],
michael@0 11169 [36792, 58109], [34948, 58110], [58113, 140828], [31110, 58114],
michael@0 11170 [35072, 58115], [26882, 58116], [31104, 58117], [58118, 153687],
michael@0 11171 [31133, 58119], [58120, 162617], [31036, 58121], [31145, 58122],
michael@0 11172 [28202, 58123], [58124, 160038], [16040, 58125], [31174, 58126],
michael@0 11173 [58127, 168205], [31188, 58128], 0, [21797, 62526], 0, [62528, 134210],
michael@0 11174 [62529, 134421], [62530, 151851], [21904, 62531], [62532, 142534],
michael@0 11175 [14828, 62533], [62534, 131905], [36422, 62535], [62536, 150968],
michael@0 11176 [62537, 169189], 0, [62539, 164030], [30586, 62540], [62541, 142392],
michael@0 11177 [14900, 62542], [18389, 62543], [62544, 164189], [62545, 158194],
michael@0 11178 [62546, 151018], [25821, 62547], [62548, 134524], [62549, 135092],
michael@0 11179 [62550, 134357], 0, [25741, 62552], [36478, 62553], [62554, 134806], 0,
michael@0 11180 [62556, 135012], [62557, 142505], [62558, 164438], [62559, 148691], 0,
michael@0 11181 [62561, 134470], [62562, 170573], [62563, 164073], [18420, 62564],
michael@0 11182 [62565, 151207], [62566, 142530], [39602, 62567], [14951, 62568],
michael@0 11183 [62569, 169460], [16365, 62570], [13574, 62571], [62572, 152263],
michael@0 11184 [62573, 169940], 0, [62575, 142660], [40302, 62576], [38933, 62577], 0,
michael@0 11185 [17369, 62579], 0, [25780, 62581], [21731, 62582], 0, [62584, 142282], 0,
michael@0 11186 [14843, 62586], 0, [62588, 157402], [62589, 157462], [62590, 162208],
michael@0 11187 [25834, 62591], [62592, 151634], [62593, 134211], [36456, 62594], 0,
michael@0 11188 [62596, 166732], [62597, 132913], 0, [18443, 62599], [62600, 131497],
michael@0 11189 [16378, 62601], [22643, 62602], [62603, 142733], 0, [62605, 148936],
michael@0 11190 [62606, 132348], [62607, 155799], [62608, 134988], 0, [21881, 62610], 0,
michael@0 11191 [17338, 62612], 0, [19124, 62614], [62615, 141926], [62616, 135325],
michael@0 11192 [33194, 62617], [39157, 62618], [62619, 134556], [25465, 62620],
michael@0 11193 [14846, 62621], [62622, 141173], [36288, 62623], [22177, 62624],
michael@0 11194 [25724, 62625], [15939, 62626], 0, [62628, 173569], [62629, 134665],
michael@0 11195 [62630, 142031], 0, 0, [62633, 135368], [62634, 145858], [14738, 62635],
michael@0 11196 [14854, 62636], [62637, 164507], [13688, 62638], [62639, 155209],
michael@0 11197 [62640, 139463], 0, 0, [62643, 142514], [62644, 169760], [13500, 62645],
michael@0 11198 [27709, 62646], [62647, 151099], 0, 0, [62650, 161140], [62651, 142987],
michael@0 11199 [62652, 139784], [62653, 173659], [62654, 167117], [62655, 134778],
michael@0 11200 [62656, 134196], [62683, 161337], [62684, 142286], [62687, 142417],
michael@0 11201 [14872, 62689], [62691, 135367], [62693, 173618], [62695, 167122],
michael@0 11202 [62696, 167321], [62697, 167114], [38314, 62698], 0, [62706, 161630],
michael@0 11203 [28992, 62708], 0, [20822, 62385], 0, [20616, 62487], 0, [13459, 62489],
michael@0 11204 [20870, 62491], [24130, 63037], [20997, 62495], [21031, 62436],
michael@0 11205 [21113, 62497], 0, [13651, 62504], [21442, 62505], [21343, 62715], 0,
michael@0 11206 [21823, 62520], 0, [21976, 59986], [13789, 62722], [22049, 63067], 0,
michael@0 11207 [22100, 60044], [60148, 135291], 0, [60153, 135379], 0, [61095, 135934], 0,
michael@0 11208 0, [14265, 60104], [23745, 61099], [23829, 63066], [23894, 63030],
michael@0 11209 [14392, 63036], [20097, 62477], [24253, 63038], [14612, 63042],
michael@0 11210 [25017, 63050], [25232, 63054], [25368, 63056], [25690, 63063],
michael@0 11211 [25745, 62381], [33133, 62709], [33156, 59922], [33171, 59924],
michael@0 11212 [26624, 63080], [15292, 63093], [29327, 60517], [29389, 59781], 0,
michael@0 11213 [29497, 59785], [30018, 59811], [30172, 59817], [16320, 59818],
michael@0 11214 [60278, 151205], [16343, 59820], 0, 30336, [30348, 59824, 151388],
michael@0 11215 [16552, 59845], [30777, 59846], [16643, 59855], [31377, 59863],
michael@0 11216 [31771, 59876], [31981, 59884], [32659, 62658], [32686, 59892], 0,
michael@0 11217 [33535, 59936], [22623, 59981], [34482, 59960], 0, [34699, 59963],
michael@0 11218 [35143, 59969], 0, [35369, 59972], 0, [36465, 59988], [60484, 164233],
michael@0 11219 [36528, 59990], 0, [37214, 62443], [37260, 62441], [39182, 60051],
michael@0 11220 [39196, 60054], 0, 0, [39809, 60066], [40384, 60080], [40339, 60078],
michael@0 11221 [40620, 60085], [19857, 60540], 0, 37818, [40571, 60084], [28809, 63148],
michael@0 11222 [29512, 59788], 0, [31129, 59858], [36791, 59997], 0, [39234, 60056],
michael@0 11223 {s: 193}, 8364, {s: 4}, [12443, 63518], [12444, 63519], [11904, 63520],
michael@0 11224 {f: 5, c: 62211}, [62216, 131340], 62217, [62218, 131281], [62219, 131277],
michael@0 11225 {f: 2, c: 62220}, [62222, 131275], [62223, 139240], 62224, [62225, 131274],
michael@0 11226 {f: 4, c: 62226}, [62230, 131342], {f: 2, c: 62231}, {f: 2, c: 62776},
michael@0 11227 [62778, 138177], [62779, 194680], [12205, 38737, 62780], [62781, 131206],
michael@0 11228 [20059, 62782], [20155, 62783], [13630, 62784], [23587, 62785],
michael@0 11229 [24401, 62786], [24516, 62787], [14586, 62788], [25164, 62789],
michael@0 11230 [25909, 62790], [27514, 62791], [27701, 62792], [27706, 62793],
michael@0 11231 [28780, 62794], [29227, 62795], [20012, 62796], [29357, 62797],
michael@0 11232 [62798, 149737], [32594, 62799], [31035, 62800], [31993, 62801],
michael@0 11233 [32595, 62802], [62803, 156266], [13505, 62804], [62806, 156491],
michael@0 11234 [32770, 62807], [32896, 62808], [62809, 157202], [62810, 158033],
michael@0 11235 [21341, 62811], [34916, 62812], [35265, 62813], [62814, 161970],
michael@0 11236 [35744, 62815], [36125, 62816], [38021, 62817], [38264, 62818],
michael@0 11237 [38271, 62819], [38376, 62820], [62821, 167439], [38886, 62822],
michael@0 11238 [39029, 62823], [39118, 62824], [39134, 62825], [39267, 62826],
michael@0 11239 [62827, 170000], [40060, 62828], [40479, 62829], [40644, 62830],
michael@0 11240 [27503, 62831], [62832, 63751], [20023, 62833], [62834, 131207],
michael@0 11241 [38429, 62835], [25143, 62836], [38050, 62837], [11908, 63521],
michael@0 11242 [11910, 63522], [11911, 63523], [11912, 63524], [11914, 63525],
michael@0 11243 [11916, 63526], [11917, 63527], [11925, 63528], [11932, 63529],
michael@0 11244 [11941, 63531], [11943, 63532], [11946, 63533], [11948, 63534],
michael@0 11245 [11950, 63535], [11958, 63536], [11964, 63537], [11966, 63538],
michael@0 11246 [11978, 63540], [11980, 63541], [11981, 63542], [11983, 63543],
michael@0 11247 [11990, 63544], [11991, 63545], [11998, 63546], [62368, 172969],
michael@0 11248 [62369, 135493], [25866, 62371], [20029, 62374], [28381, 62375],
michael@0 11249 [40270, 62376], [37343, 62377], [62380, 161589], [20250, 62382],
michael@0 11250 [20264, 62383], [20392, 62384], [20852, 62386], [20892, 62387],
michael@0 11251 [20964, 62388], [21153, 62389], [21160, 62390], [21307, 62391],
michael@0 11252 [21326, 62392], [21457, 62393], [21464, 62394], [22242, 62395],
michael@0 11253 [22768, 62396], [22788, 62397], [22791, 62398], [22834, 62399],
michael@0 11254 [22836, 62400], [23398, 62401], [23454, 62402], [23455, 62403],
michael@0 11255 [23706, 62404], [24198, 62405], [24635, 62406], [25993, 62407],
michael@0 11256 [26622, 62408], [26628, 62409], [26725, 62410], [27982, 62411],
michael@0 11257 [28860, 62412], [30005, 62413], [32420, 62414], [32428, 62415],
michael@0 11258 [32442, 62416], [32455, 62417], [32463, 62418], [32479, 62419],
michael@0 11259 [32518, 62420], [32567, 62421], [33402, 62422], [33487, 62423],
michael@0 11260 [33647, 62424], [35270, 62425], [35774, 62426], [35810, 62427],
michael@0 11261 [36710, 62428], [36711, 62429], [36718, 62430], [29713, 62431],
michael@0 11262 [31996, 62432], [32205, 62433], [26950, 62434], [31433, 62435],
michael@0 11263 [30904, 62442], [32956, 62444], [36107, 62446], [33014, 62447],
michael@0 11264 [62448, 133607], [32927, 62451], [40647, 62452], [19661, 62453],
michael@0 11265 [40393, 62454], [40460, 62455], [19518, 62456], [62457, 171510],
michael@0 11266 [62458, 159758], [40458, 62459], [62460, 172339], [13761, 62461],
michael@0 11267 [28314, 62463], [33342, 62464], [29977, 62465], [18705, 62467],
michael@0 11268 [39532, 62468], [39567, 62469], [40857, 62470], [31111, 62471],
michael@0 11269 [62472, 164972], [62473, 138698], [62474, 132560], [62475, 142054],
michael@0 11270 [20004, 62476], [20096, 62478], [20103, 62479], [20159, 62480],
michael@0 11271 [20203, 62481], [20279, 62482], [13388, 62483], [20413, 62484],
michael@0 11272 [15944, 62485], [20483, 62486], [13437, 62488], [13477, 62490],
michael@0 11273 [22789, 62492], [20955, 62493], [20988, 62494], [20105, 62496],
michael@0 11274 [21136, 62498], [21287, 62499], [13767, 62500], [21417, 62501],
michael@0 11275 [13649, 62502], [21424, 62503], [21539, 62506], [13677, 62507],
michael@0 11276 [13682, 62508], [13953, 62509], [21651, 62510], [21667, 62511],
michael@0 11277 [21684, 62512], [21689, 62513], [21712, 62514], [21743, 62515],
michael@0 11278 [21784, 62516], [21795, 62517], [21800, 62518], [13720, 62519],
michael@0 11279 [13733, 62521], [13759, 62522], [21975, 62523], [13765, 62524],
michael@0 11280 [62525, 163204], [16467, 62538], [62551, 135412], [62555, 134155],
michael@0 11281 [62574, 161992], [62580, 155813], [62583, 142668], [62585, 135287],
michael@0 11282 [62587, 135279], [62595, 139681], [62609, 134550], [16571, 62611],
michael@0 11283 [62631, 142537], [22098, 62641], [62642, 134961], [62657, 157724],
michael@0 11284 [62659, 135375], [62660, 141315], [62661, 141625], [13819, 62662],
michael@0 11285 [62663, 152035], [62664, 134796], [62665, 135053], [62666, 134826],
michael@0 11286 [16275, 62667], [62668, 134960], [62669, 134471], [62670, 135503],
michael@0 11287 [62671, 134732], [62673, 134827], [62674, 134057], [62675, 134472],
michael@0 11288 [62676, 135360], [62677, 135485], [16377, 62678], [62679, 140950],
michael@0 11289 [25650, 62680], [62681, 135085], [62682, 144372], [62685, 134526],
michael@0 11290 [62686, 134527], [62688, 142421], [62690, 134808], [62692, 134958],
michael@0 11291 [62694, 158544], [21708, 62699], [33476, 62700], [21945, 62701],
michael@0 11292 [62703, 171715], [39974, 62704], [39606, 62705], [62707, 142830],
michael@0 11293 [33004, 62710], [23580, 62711], [62712, 157042], [33076, 62713],
michael@0 11294 [14231, 62714], [62716, 164029], [37302, 62717], [62718, 134906],
michael@0 11295 [62719, 134671], [62720, 134775], [62721, 134907], [62723, 151019],
michael@0 11296 [13833, 62724], [62725, 134358], [22191, 62726], [62727, 141237],
michael@0 11297 [62728, 135369], [62729, 134672], [62730, 134776], [62731, 135288],
michael@0 11298 [62732, 135496], [62733, 164359], [62734, 136277], [62735, 134777],
michael@0 11299 [62736, 151120], [62737, 142756], [23124, 62738], [62739, 135197],
michael@0 11300 [62740, 135198], [62741, 135413], [62742, 135414], [22428, 62743],
michael@0 11301 [62744, 134673], [62745, 161428], [62746, 164557], [62747, 135093],
michael@0 11302 [62748, 134779], [62749, 151934], [14083, 62750], [62751, 135094],
michael@0 11303 [62752, 135552], [62753, 152280], [62754, 172733], [62755, 149978],
michael@0 11304 [62756, 137274], [62757, 147831], [62758, 164476], [22681, 62759],
michael@0 11305 [21096, 62760], [13850, 62761], [62762, 153405], [31666, 62763],
michael@0 11306 [23400, 62764], [18432, 62765], [19244, 62766], [40743, 62767],
michael@0 11307 [18919, 62768], [39967, 62769], [39821, 62770], [62771, 154484],
michael@0 11308 [62772, 143677], [22011, 62773], [13810, 62774], [22153, 62775],
michael@0 11309 [23870, 63028], [23880, 63029], [15868, 63031], [14351, 63032],
michael@0 11310 [23972, 63033], [23993, 63034], [14368, 63035], [24357, 63039],
michael@0 11311 [24451, 63040], [14600, 63041], [14655, 63043], [14669, 63044],
michael@0 11312 [24791, 63045], [24893, 63046], [23781, 63047], [14729, 63048],
michael@0 11313 [25015, 63049], [25039, 63051], [14776, 63052], [25132, 63053],
michael@0 11314 [25317, 63055], [14840, 63057], [22193, 63058], [14851, 63059],
michael@0 11315 [25570, 63060], [25595, 63061], [25607, 63062], [14923, 63064],
michael@0 11316 [25792, 63065], [40863, 63068], [14999, 63069], [25990, 63070],
michael@0 11317 [15037, 63071], [26111, 63072], [26195, 63073], [15090, 63074],
michael@0 11318 [26258, 63075], [15138, 63076], [26390, 63077], [15170, 63078],
michael@0 11319 [26532, 63079], [15192, 63081], [26698, 63082], [26756, 63083],
michael@0 11320 [15218, 63084], [15217, 63085], [15227, 63086], [26889, 63087],
michael@0 11321 [26947, 63088], [29276, 63089], [26980, 63090], [27039, 63091],
michael@0 11322 [27013, 63092], [27094, 63094], [15325, 63095], [27237, 63096],
michael@0 11323 [27252, 63097], [27249, 63098], [27266, 63099], [15340, 63100],
michael@0 11324 [27289, 63101], [15346, 63102], [27307, 63103], [27317, 63104],
michael@0 11325 [27348, 63105], [27382, 63106], [27521, 63107], [27585, 63108],
michael@0 11326 [27626, 63109], [27765, 63110], [27818, 63111], [15563, 63112],
michael@0 11327 [27906, 63113], [27910, 63114], [27942, 63115], [28033, 63116],
michael@0 11328 [15599, 63117], [28068, 63118], [28081, 63119], [28181, 63120],
michael@0 11329 [28184, 63121], [28201, 63122], [28294, 63123], [63124, 166336],
michael@0 11330 [28347, 63125], [28386, 63126], [28378, 63127], [40831, 63128],
michael@0 11331 [28392, 63129], [28393, 63130], [28452, 63131], [28468, 63132],
michael@0 11332 [15686, 63133], [63134, 147265], [28545, 63135], [28606, 63136],
michael@0 11333 [15722, 63137], [15733, 63138], [29111, 63139], [23705, 63140],
michael@0 11334 [15754, 63141], [28716, 63142], [15761, 63143], [28752, 63144],
michael@0 11335 [28756, 63145], [28783, 63146], [28799, 63147], [63149, 131877],
michael@0 11336 [17345, 63150], [13809, 63151], [63152, 134872], [13902, 58134],
michael@0 11337 [15789, 58172], [58173, 154725], [26237, 58183], [31860, 58188],
michael@0 11338 [29837, 58197], [32402, 58215], [17667, 58232], [58260, 151480],
michael@0 11339 [58270, 133901], [58277, 158474], [13438, 58311], [58317, 143087],
michael@0 11340 [58325, 146613], [58343, 159385], [34673, 58364], [25537, 58385],
michael@0 11341 [30583, 58387], [35210, 58390], [58406, 147343], [35660, 58415],
michael@0 11342 [58440, 150729], [18730, 58464], [58471, 172052], [58472, 165564],
michael@0 11343 [58473, 165121], [15088, 58490], [28815, 58511], [58529, 140922],
michael@0 11344 [58637, 158120], [58646, 148043], [26760, 58662], [58664, 139611],
michael@0 11345 [40802, 58702], [37830, 58793], [58802, 131967], [37734, 58888],
michael@0 11346 [37519, 58901], [34324, 58954], [58986, 173147], [16784, 59010],
michael@0 11347 [26511, 59045], [26654, 59048], [14435, 59051], [59077, 149996],
michael@0 11348 [15129, 59128], [33942, 59176], [59241, 149858], [14818, 59254],
michael@0 11349 [33920, 59259], [17262, 59328], [38769, 59402], [39323, 59427],
michael@0 11350 [18733, 59499], [28439, 59703], [59704, 160009], [28838, 59746],
michael@0 11351 [59752, 150095], [32357, 59753], [23855, 59755], [15859, 59756],
michael@0 11352 [59758, 150109], [59759, 137183], [32164, 59760], [33830, 59761],
michael@0 11353 [21637, 59762], [59763, 146170], [59765, 131604], [22398, 59766],
michael@0 11354 [59767, 133333], [59768, 132633], [16357, 59769], [59770, 139166],
michael@0 11355 [59771, 172726], [28675, 59772], [59773, 168283], [23920, 59774],
michael@0 11356 [29583, 59775], [59777, 166489], [59778, 168992], [20424, 59779],
michael@0 11357 [32743, 59780], [29456, 59782], [29496, 59784], [29505, 59787],
michael@0 11358 [16041, 59789], [29173, 59792], [59793, 149746], [29665, 59794],
michael@0 11359 [16074, 59796], [16081, 59798], [29721, 59801], [29726, 59802],
michael@0 11360 [29727, 59803], [16098, 59804], [16112, 59805], [16116, 59806],
michael@0 11361 [16122, 59807], [29907, 59808], [16142, 59809], [16211, 59810],
michael@0 11362 [30061, 59812], [30066, 59813], [30093, 59814], [16252, 59815],
michael@0 11363 [30152, 59816], [30285, 59819], [30324, 59821], [16348, 59822],
michael@0 11364 [30330, 59823], [29064, 59825], [22051, 59826], [35200, 59827],
michael@0 11365 [16413, 59829], [30531, 59830], [16441, 59831], [16453, 59833],
michael@0 11366 [13787, 59834], [30616, 59835], [16490, 59836], [16495, 59837],
michael@0 11367 [30654, 59839], [30667, 59840], [30744, 59842], [30748, 59844],
michael@0 11368 [30791, 59847], [30801, 59848], [30822, 59849], [33864, 59850],
michael@0 11369 [59851, 152885], [31027, 59852], [31026, 59854], [16649, 59856],
michael@0 11370 [31121, 59857], [31238, 59860], [16743, 59862], [16818, 59864],
michael@0 11371 [31420, 59865], [33401, 59866], [16836, 59867], [31439, 59868],
michael@0 11372 [31451, 59869], [16847, 59870], [31586, 59872], [31596, 59873],
michael@0 11373 [31611, 59874], [31762, 59875], [16992, 59877], [17018, 59878],
michael@0 11374 [31867, 59879], [31900, 59880], [17036, 59881], [31928, 59882],
michael@0 11375 [17044, 59883], [36755, 59885], [28864, 59886], [59887, 134351],
michael@0 11376 [32207, 59888], [32212, 59889], [32208, 59890], [32253, 59891],
michael@0 11377 [32692, 59893], [29343, 59894], [17303, 59895], [32800, 59896],
michael@0 11378 [32805, 59897], [32814, 59899], [32817, 59900], [32852, 59901],
michael@0 11379 [22452, 59903], [28832, 59904], [32951, 59905], [33001, 59906],
michael@0 11380 [17389, 59907], [33036, 59908], [33038, 59910], [33042, 59911],
michael@0 11381 [33044, 59913], [17409, 59914], [15161, 59915], [33110, 59916],
michael@0 11382 [33113, 59917], [33114, 59918], [17427, 59919], [33148, 59921],
michael@0 11383 [17445, 59923], [17453, 59925], [33189, 59926], [22511, 59927],
michael@0 11384 [33217, 59928], [33252, 59929], [33364, 59930], [17551, 59931],
michael@0 11385 [33398, 59933], [33482, 59934], [33496, 59935], [17584, 59937],
michael@0 11386 [33623, 59938], [38505, 59939], [33797, 59941], [28917, 59942],
michael@0 11387 [33892, 59943], [33928, 59945], [17668, 59946], [33982, 59947],
michael@0 11388 [34017, 59948], [34040, 59949], [34064, 59950], [34104, 59951],
michael@0 11389 [34130, 59952], [17723, 59953], [34159, 59954], [34160, 59955],
michael@0 11390 [34272, 59956], [17783, 59957], [34418, 59958], [34450, 59959],
michael@0 11391 [34543, 59961], [38469, 59962], [17926, 59964], [17943, 59965],
michael@0 11392 [34990, 59966], [35071, 59967], [35108, 59968], [35217, 59970],
michael@0 11393 [59971, 162151], [35384, 59973], [35476, 59974], [35508, 59975],
michael@0 11394 [35921, 59976], [36052, 59977], [36082, 59978], [36124, 59979],
michael@0 11395 [18328, 59980], [36291, 59982], [18413, 59983], [36410, 59985],
michael@0 11396 [22356, 59987], [22005, 59989], [18487, 59991], [36558, 59992],
michael@0 11397 [36578, 59993], [36580, 59994], [36589, 59995], [36594, 59996],
michael@0 11398 [36801, 59998], [36810, 59999], [36812, 60000], [36915, 60001],
michael@0 11399 [18605, 60003], [39136, 60004], [37395, 60005], [18718, 60006],
michael@0 11400 [37416, 60007], [37464, 60008], [37483, 60009], [37553, 60010],
michael@0 11401 [37550, 60011], [37567, 60012], [37603, 60013], [37611, 60014],
michael@0 11402 [37619, 60015], [37620, 60016], [37629, 60017], [37699, 60018],
michael@0 11403 [37764, 60019], [37805, 60020], [18757, 60021], [18769, 60022],
michael@0 11404 [37911, 60024], [37917, 60026], [37933, 60027], [37950, 60028],
michael@0 11405 [18794, 60029], [37972, 60030], [38009, 60031], [38189, 60032],
michael@0 11406 [38306, 60033], [18855, 60034], [38388, 60035], [38451, 60036],
michael@0 11407 [18917, 60037], [18980, 60039], [38720, 60040], [18997, 60041],
michael@0 11408 [38834, 60042], [38850, 60043], [19172, 60045], [39097, 60047],
michael@0 11409 [19225, 60048], [39153, 60049], [22596, 60050], [39193, 60052],
michael@0 11410 [39223, 60055], [39261, 60057], [39266, 60058], [19312, 60059],
michael@0 11411 [39365, 60060], [19357, 60061], [39484, 60062], [39695, 60063],
michael@0 11412 [39785, 60065], [39901, 60067], [39921, 60068], [39924, 60069],
michael@0 11413 [19565, 60070], [39968, 60071], [14191, 60072], [60073, 138178],
michael@0 11414 [40265, 60074], [40702, 60076], [22096, 60077], [40381, 60079],
michael@0 11415 [40444, 60081], [38134, 60082], [36790, 60083], [40625, 60086],
michael@0 11416 [40637, 60087], [40646, 60088], [38108, 60089], [40674, 60090],
michael@0 11417 [40689, 60091], [40696, 60092], [40772, 60094], [60095, 131220],
michael@0 11418 [60096, 131767], [60097, 132000], [38083, 60099], [60101, 132311],
michael@0 11419 [38081, 60103], [60105, 132565], [60106, 132629], [60107, 132726],
michael@0 11420 [60108, 136890], [22359, 60109], [29043, 60110], [60111, 133826],
michael@0 11421 [60112, 133837], [60113, 134079], [60115, 194619], [60116, 134091],
michael@0 11422 [21662, 60117], [60118, 134139], [60119, 134203], [60120, 134227],
michael@0 11423 [60121, 134245], [60122, 134268], [60124, 134285], [60126, 134325],
michael@0 11424 [60127, 134365], [60128, 134381], [60129, 134511], [60130, 134578],
michael@0 11425 [60131, 134600], [60135, 134660], [60136, 134670], [60137, 134871],
michael@0 11426 [60138, 135056], [60139, 134957], [60140, 134771], [60142, 135100],
michael@0 11427 [60144, 135260], [60145, 135247], [60146, 135286], [60149, 135304],
michael@0 11428 [60150, 135318], [13895, 60151], [60152, 135359], [60154, 135471],
michael@0 11429 [60155, 135483], [21348, 60156], [60158, 135907], [60159, 136053],
michael@0 11430 [60160, 135990], [60162, 136567], [60163, 136729], [60164, 137155],
michael@0 11431 [60165, 137159], [28859, 60167], [60168, 137261], [60169, 137578],
michael@0 11432 [60170, 137773], [60171, 137797], [60172, 138282], [60173, 138352],
michael@0 11433 [60174, 138412], [60175, 138952], [60177, 138965], [60178, 139029],
michael@0 11434 [29080, 60179], [60181, 139333], [27113, 60182], [14024, 60183],
michael@0 11435 [60184, 139900], [60185, 140247], [60186, 140282], [60187, 141098],
michael@0 11436 [60188, 141425], [60189, 141647], [60191, 141671], [60192, 141715],
michael@0 11437 [60193, 142037], [60195, 142056], [60197, 142094], [60199, 142143],
michael@0 11438 [60202, 142412], [60204, 142472], [60205, 142519], [60206, 154600],
michael@0 11439 [60207, 142600], [60208, 142610], [60209, 142775], [60210, 142741],
michael@0 11440 [60211, 142914], [60212, 143220], [60213, 143308], [60214, 143411],
michael@0 11441 [60215, 143462], [60216, 144159], [60217, 144350], [60222, 144743],
michael@0 11442 [60223, 144883], [60227, 144922], [60228, 145174], [22709, 60231],
michael@0 11443 [60234, 146087], [60237, 146961], [60238, 147129], [60243, 147737],
michael@0 11444 [60245, 148206], [60246, 148237], [60248, 148276], [60249, 148374],
michael@0 11445 [60258, 148484], [60259, 148694], [22408, 60260], [60261, 149108],
michael@0 11446 [60263, 149295], [60271, 149522], [60272, 149755], [60273, 150037],
michael@0 11447 [60275, 150208], [22885, 60277], [60279, 151430], [60282, 151596],
michael@0 11448 [22335, 60284], [60286, 152217], [60287, 152601], [60291, 152646],
michael@0 11449 [60292, 152686], [60296, 152895], [60298, 152926], [60300, 152930],
michael@0 11450 [60301, 152934], [60302, 153543], [60304, 153693], [60309, 153859],
michael@0 11451 [60312, 154286], [60313, 154505], [60314, 154630], [22433, 60316],
michael@0 11452 [29009, 60317], [60319, 155906], [60322, 156082], [60325, 156674],
michael@0 11453 [60326, 156746], [60330, 156804], [60334, 156808], [60336, 156946],
michael@0 11454 [60338, 157119], [60339, 157365], [22201, 60347], [60349, 157436],
michael@0 11455 [13848, 60355], [60357, 157593], [60358, 157806], [60360, 157790],
michael@0 11456 [60362, 157895], [60366, 157990], [60368, 158009], [60371, 158202],
michael@0 11457 [60373, 158253], [60378, 158260], [60379, 158555], [60383, 158621],
michael@0 11458 [60385, 158884], [60388, 159150], [60392, 159819], [60393, 160205],
michael@0 11459 [60395, 160384], [60396, 160389], [60399, 160395], [60401, 160486],
michael@0 11460 [38047, 60404], [60405, 160848], [14009, 60416], [60424, 161740],
michael@0 11461 [60425, 161880], [22230, 60426], [60435, 162269], [60441, 162301],
michael@0 11462 [60442, 162314], [60443, 162571], [60444, 163174], [60448, 163849],
michael@0 11463 [60459, 163875], [60463, 163912], [60466, 163971], [60479, 163984],
michael@0 11464 [60480, 164084], [60481, 164142], [60483, 164175], [60485, 164271],
michael@0 11465 [60486, 164378], [60487, 164614], [60488, 164655], [60489, 164746],
michael@0 11466 [60491, 164968], [60492, 165546], [25574, 60494], [60495, 166230],
michael@0 11467 [60498, 166328], [60500, 166375], [60502, 166376], [60503, 166726],
michael@0 11468 [60504, 166868], [60506, 166921], [60508, 167877], [60509, 168172],
michael@0 11469 [60511, 168208], [60512, 168252], [15863, 60513], [60514, 168286],
michael@0 11470 [60515, 150218], [36816, 60516], [60519, 169191], [60521, 169392],
michael@0 11471 [60522, 169400], [60523, 169778], [60524, 170193], [60525, 170313],
michael@0 11472 [60526, 170346], [60527, 170435], [60528, 170536], [60529, 170766],
michael@0 11473 [60530, 171354], [60531, 171419], [32415, 60532], [60533, 171768],
michael@0 11474 [60534, 171811], [19620, 60535], [38215, 60536], [60537, 172691],
michael@0 11475 [29090, 60538], [60539, 172799], [60542, 173515], [19868, 60543],
michael@0 11476 [60544, 134300], [36798, 60545], [36794, 60547], [60548, 140464],
michael@0 11477 [36793, 60549], [60550, 150163], [20202, 60555], [60557, 166700],
michael@0 11478 [36480, 60560], [60561, 137205], [60563, 166764], [60564, 166809],
michael@0 11479 [60566, 157359], [60568, 161365], [60570, 153141], [60571, 153942],
michael@0 11480 [20122, 60572], [60573, 155265], [60576, 134765], [60579, 147080],
michael@0 11481 [60580, 150686], [60583, 137206], [60584, 137339], [60587, 154698],
michael@0 11482 [60589, 152337], [15814, 60590], [60596, 155352], [19996, 60600],
michael@0 11483 [60601, 135146], [60602, 134473], [60603, 145082], [60638, 151880],
michael@0 11484 [21982, 60644], [34694, 60672], [60676, 135361], [60679, 149254],
michael@0 11485 [23440, 60680], [60682, 157843], [60684, 141044], [60685, 163119],
michael@0 11486 [60686, 147875], [60687, 163187], [60688, 159440], [60689, 160438],
michael@0 11487 [60691, 135641], [60693, 146684], [60694, 173737], [60695, 134828],
michael@0 11488 [60698, 138402], [60700, 151490], [60702, 135147], [60706, 142752],
michael@0 11489 [60710, 135148], [60711, 134666], [60714, 135149], [60717, 135559],
michael@0 11490 [19994, 60721], [19972, 60722], [23309, 60724], [13996, 60727],
michael@0 11491 [21373, 60729], [13989, 60730], [22682, 60732], [60733, 150382],
michael@0 11492 [22442, 60736], [60737, 154261], [60738, 133497], [60741, 140389],
michael@0 11493 [60746, 146686], [60747, 171824], [60749, 151465], [60750, 169374],
michael@0 11494 [60753, 146870], [60755, 157619], [60756, 145184], [60759, 147191],
michael@0 11495 [60760, 146988], [60785, 143578], [60789, 135849], [22439, 60790],
michael@0 11496 [60791, 149859], [60794, 159918], [60801, 137068], [60806, 160100],
michael@0 11497 [60809, 159010], [60810, 150242], [39963, 60837], [60838, 149822],
michael@0 11498 [15878, 60846], [60881, 159011], [60887, 132092], [60891, 146685],
michael@0 11499 [60893, 149785], [22394, 60904], [21722, 60912], [29050, 60928],
michael@0 11500 [60949, 150135], [60955, 166490], [60962, 194624], [60976, 137275],
michael@0 11501 [61000, 155993], [61014, 144373], [61019, 166850], [61024, 138566],
michael@0 11502 [61054, 159441], [13877, 61065], [61084, 166701], [21024, 61088],
michael@0 11503 [15384, 61089], [61090, 146631], [61091, 155351], [61092, 161366],
michael@0 11504 [61093, 152881], [61094, 137540], [61096, 170243], [61097, 159196],
michael@0 11505 [61098, 159917], [61100, 156077], [61101, 166415], [61102, 145015],
michael@0 11506 [61103, 131310], [61104, 157766], [61105, 151310], [17762, 61106],
michael@0 11507 [23327, 61107], [61108, 156492], [40784, 61109], [40614, 61110],
michael@0 11508 [61111, 156267], [20962, 57415], [21314, 57416], [26285, 57520],
michael@0 11509 [22620, 57547], [21843, 57566], [15749, 57594], [24928, 57608],
michael@0 11510 [18606, 57668], [38845, 57676], [57693, 137335], [24755, 57703],
michael@0 11511 [33828, 57711], [38932, 57748], [57749, 147596], [57764, 143486],
michael@0 11512 [57787, 138813], [15147, 57798], [15666, 57824], [57857, 132021],
michael@0 11513 [28801, 57944], [23708, 57959], [58017, 132547], [14128, 58028],
michael@0 11514 [58096, 136054], [58097, 150034], [58111, 166699], [58112, 155779],
michael@0 11515 [256, 62233], [193, 62234], [461, 62235], [192, 62236], [274, 62237],
michael@0 11516 [201, 62238], [282, 62239], [200, 62240], [332, 62241], [211, 62242],
michael@0 11517 [465, 62243], [210, 62244], 62245, [7870, 62246], 62247, [7872, 62248],
michael@0 11518 [202, 62249], [257, 62250], [225, 62251], [462, 62252], [224, 62253],
michael@0 11519 [593, 62254], [275, 62255], [233, 62256], [283, 62257], [232, 62258],
michael@0 11520 [299, 62259], [237, 62260], [464, 62261], [236, 62262], [333, 62263],
michael@0 11521 [243, 62264], [466, 62265], [242, 62266], [363, 62267], [250, 62268],
michael@0 11522 [468, 62269], [249, 62270], [470, 62271], [472, 62272], [474, 62273],
michael@0 11523 [476, 62274], [252, 62275], 62276, [7871, 62277], 62278, [7873, 62279],
michael@0 11524 [234, 62280], [609, 62281], [643, 63551], [592, 63552], [603, 63553],
michael@0 11525 [596, 63554], [629, 63555], [339, 63556], [248, 63557], [331, 63558],
michael@0 11526 [650, 63559], [618, 63560], {f: 2, c: 62282}, [11933, 63530],
michael@0 11527 [11974, 63539], [12003, 63547], 20539, 28158, [62841, 171123], 62842,
michael@0 11528 [15817, 62843], 34959, [62845, 147790], 28791, 23797, [19232, 62848],
michael@0 11529 [62849, 152013], [13657, 62850], [62851, 154928], 24866, [62853, 166450],
michael@0 11530 36775, 37366, 29073, 26393, 29626, [62859, 144001], [62860, 172295],
michael@0 11531 [15499, 62861], [62862, 137600], [19216, 62863], 30948, 29698, 20910,
michael@0 11532 [62867, 165647], [16393, 62868], 27235, [62870, 172730], [16931, 62871],
michael@0 11533 34319, 31274, [62875, 170311], [62876, 166634], 38741, 28749, 21284,
michael@0 11534 [62880, 139390], 37876, 30425, [62883, 166371], 62884, 30685, 20131, 20464,
michael@0 11535 20668, 20015, 20247, 62891, 21556, 32139, 22674, 22736, [62896, 138678],
michael@0 11536 24210, 24217, 24514, [62900, 141074], 25995, [62902, 144377], 26905, 27203,
michael@0 11537 [62905, 146531], 27903, 29184, [62909, 148741], 29580, [16091, 62911],
michael@0 11538 [62912, 150035], 23317, 29881, 35715, [62916, 154788], [62917, 153237],
michael@0 11539 31379, 31724, 31939, 32364, 33528, 34199, 62924, 34960, 62926, 36537,
michael@0 11540 62928, 36815, 34143, 39392, 37409, 62933, [62934, 167353], [62935, 136255],
michael@0 11541 [16497, 62936], [17058, 62937], 23066, 39016, 26475, [17014, 62944], 22333,
michael@0 11542 34262, [62948, 149883], 33471, [62950, 160013], [19585, 62951],
michael@0 11543 [62952, 159092], 23931, [62954, 158485], [62955, 159678], {f: 2, c: 62956},
michael@0 11544 23446, 62959, 32347],
michael@0 11545 'Adobe-GB1': [{f: 95, c: 32}, {f: 3, c: 12288}, [183, 12539], 713, 711, 168,
michael@0 11546 12291, 12293, 8212, 65374, 8214, [8230, 8943], {f: 2, c: 8216},
michael@0 11547 {f: 2, c: 8220}, {f: 2, c: 12308}, {f: 8, c: 12296}, {f: 2, c: 12310},
michael@0 11548 {f: 2, c: 12304}, 177, 215, 247, 8758, {f: 2, c: 8743}, 8721, 8719, 8746,
michael@0 11549 8745, 8712, 8759, 8730, 8869, 8741, 8736, 8978, 8857, 8747, 8750, 8801,
michael@0 11550 8780, 8776, 8765, 8733, 8800, {f: 2, c: 8814}, {f: 2, c: 8804}, 8734, 8757,
michael@0 11551 8756, 9794, 9792, 176, {f: 2, c: 8242}, 8451, 65284, 164, {f: 2, c: 65504},
michael@0 11552 8240, 167, 8470, 9734, 9733, 9675, 9679, 9678, 9671, 9670, 9633, 9632,
michael@0 11553 9651, 9650, 8251, 8594, {f: 2, c: 8592}, 8595, 12307, {f: 20, c: 9352},
michael@0 11554 {f: 20, c: 9332}, {f: 10, c: 9312}, {f: 10, c: 12832}, {f: 12, c: 8544},
michael@0 11555 {f: 3, c: 65281}, 65509, {f: 89, c: 65285}, 65507, {f: 83, c: 12353},
michael@0 11556 {f: 86, c: 12449}, {f: 17, c: 913}, {f: 7, c: 931}, {f: 17, c: 945},
michael@0 11557 {f: 7, c: 963}, {f: 7, c: 59277}, {f: 2, c: 65077}, {f: 2, c: 65081},
michael@0 11558 {f: 2, c: 65087}, {f: 2, c: 65085}, {f: 4, c: 65089}, {f: 2, c: 59284},
michael@0 11559 {f: 2, c: 65083}, {f: 2, c: 65079}, 65073, 59286, {f: 2, c: 65075},
michael@0 11560 {f: 6, c: 1040}, 1025, {f: 32, c: 1046}, 1105, {f: 26, c: 1078}, 257, 225,
michael@0 11561 462, 224, 275, 233, 283, 232, 299, 237, 464, 236, 333, 243, 466, 242, 363,
michael@0 11562 250, 468, 249, 470, 472, 474, 476, 252, 234, 593, 7743, 324, 328, 505, 609,
michael@0 11563 {f: 37, c: 12549}, 0, {f: 76, c: 9472}, {s: 126}, 21834, 38463, 22467,
michael@0 11564 25384, 21710, 21769, 21696, 30353, 30284, 34108, 30702, 33406, 30861,
michael@0 11565 29233, 38552, 38797, 27688, 23433, 20474, 25353, 26263, 23736, 33018,
michael@0 11566 26696, 32942, 26114, 30414, 20985, 25942, 29100, 32753, 34948, 20658,
michael@0 11567 22885, 25034, 28595, 33453, 25420, 25170, 21485, 21543, 31494,
michael@0 11568 [12043, 20843], 30116, 24052, 25300, 36299, 38774, 25226, 32793, 22365,
michael@0 11569 38712, 32610, 29240, [12137, 30333], 26575, 30334, 25670, 20336, 36133,
michael@0 11570 25308, 31255, 26001, 29677, 25644, 25203, 33324, 39041, 26495, 29256,
michael@0 11571 25198, 25292, 20276, 29923, 21322, 21150, 32458, 37030, 24110, 26758,
michael@0 11572 27036, 33152, 32465, 26834, 30917, 34444, 38225, 20621, 35876, 33502,
michael@0 11573 32990, 21253, 35090, 21093, 34180, 38649, 20445, 22561, 39281, 23453,
michael@0 11574 25265, 25253, 26292, 35961, 40077, 29190, 26479, 30865, 24754, 21329,
michael@0 11575 21271, 36744, 32972, 36125, 38049, 20493, 29384, 22791, 24811, 28953,
michael@0 11576 34987, 22868, 33519, 26412, 31528, 23849, 32503, 29997, 27893, 36454,
michael@0 11577 36856, 36924, [12240, 40763], [12112, 27604], 37145, 31508, 24444, 30887,
michael@0 11578 34006, 34109, 27605, 27609, 27606, 24065, 24199, 30201, 38381, 25949,
michael@0 11579 24330, 24517, 36767, 22721, 33218, 36991, 38491, 38829, 36793, 32534,
michael@0 11580 36140, 25153, 20415, 21464, 21342, {f: 2, c: 36776}, 36779, 36941, 26631,
michael@0 11581 24426, 33176, 34920, 40150, 24971, 21035, 30250, 24428, 25996, 28626,
michael@0 11582 28392, 23486, 25672, 20853, 20912, 26564, 19993, 31177, 39292, 28851,
michael@0 11583 30149, 24182, 29627, 33760, 25773, 25320, 38069, 27874, 21338, 21187,
michael@0 11584 25615, 38082, 31636, 20271, 24091, 33334, 33046, 33162, 28196, 27850,
michael@0 11585 39539, 25429, [12056, 21340], 21754, 34917, 22496, 19981, 24067, 27493,
michael@0 11586 31807, 37096, 24598, 25830, 29468, 35009, 26448, 25165, 36130, 30572,
michael@0 11587 36393, 37319, 24425, 33756, 34081, 39184, 21442, 34453, 27531, 24813,
michael@0 11588 24808, 28799, 33485, 33329, 20179, 27815, 34255, 25805, 31961, 27133,
michael@0 11589 26361, 33609, 21397, 31574, 20391, 20876, 27979, 23618, 36461, 25554,
michael@0 11590 21449, 33580, 33590, 26597, 30900, 25661, 23519, 23700, 24046, 35815,
michael@0 11591 25286, 26612, 35962, 25600, 25530, 34633, 39307, 35863, 32544, 38130,
michael@0 11592 20135, 38416, 39076, 26124, 29462, 22330, 23581, 24120, 38271, 20607,
michael@0 11593 32928, [12058, 21378], 25950, 30021, 21809, 20513, 36229, 25220, 38046,
michael@0 11594 26397, 22066, 28526, 24034, 21557, 28818, 36710, 25199, 25764, 25507,
michael@0 11595 24443, 28552, 37108, [12162, 33251], [12192, 36784], 23576, 26216, 24561,
michael@0 11596 27785, 38472, 36225, 34924, 25745, 31216, 22478, 27225, 25104, 21576,
michael@0 11597 20056, 31243, 24809, 28548, 35802, 25215, 36894, 39563, 31204, 21507,
michael@0 11598 30196, 25345, 21273, 27744, 36831, 24347, 39536, 32827, 40831, 20360,
michael@0 11599 23610, [12186, 36196], 32709, 26021, 28861, 20805, 20914, [12173, 34411],
michael@0 11600 23815, 23456, 25277, 37228, 30068, 36364, 31264, 24833, 31609, 20167,
michael@0 11601 32504, 30597, 19985, 33261, 21021, 20986, 27249, 21416, 36487, 38148,
michael@0 11602 38607, 28353, 38500, 26970, 30784, 20648, 30679, 25616, 35302, 22788,
michael@0 11603 25571, 24029, 31359, 26941, 20256, 33337, 21912, 20018, 30126, 31383,
michael@0 11604 24162, 24202, 38383, 21019, 21561, 28810, 25462, 38180, 22402, 26149,
michael@0 11605 26943, 37255, 21767, 28147, 32431, 34850, 25139, 32496, 30133, 33576,
michael@0 11606 30913, 38604, 36766, 24904, 29943, 35789, 27492, 21050, 36176, 27425,
michael@0 11607 32874, 33905, 22257, 21254, 20174, 19995, 20945, 31895, 37259, 31751,
michael@0 11608 20419, 36479, 31713, 31388, 25703, 23828, 20652, 33030, 30209, 31929,
michael@0 11609 28140, 32736, 26449, 23384, [12072, 23544], 30923, 25774, 25619, 25514,
michael@0 11610 25387, 38169, 25645, 36798, 31572, 30249, 25171, [12068, 22823], 21574,
michael@0 11611 [12109, 27513], 20643, 25140, 24102, 27526, 20195, 36151, 34955, 24453,
michael@0 11612 36910, 24608, 32829, 25285, 20025, 21333, 37112, 25528, 32966, 26086,
michael@0 11613 27694, 20294, 24814, 28129, 35806, 24377, 34507, 24403, 25377, 20826,
michael@0 11614 33633, 26723, [12049, 20992], 25443, 36424, 20498, 23707, 31095, 23548,
michael@0 11615 21040, 31291, 24764, 36947, 30423, 24503, 24471, 30340, 36460, 28783,
michael@0 11616 30331, 31561, 30634, 20979, 37011, 22564, 20302, 28404, 36842, 25932,
michael@0 11617 31515, 29380, 28068, 32735, 23265, 25269, 24213, 22320, 33922, 31532,
michael@0 11618 24093, 24351, 36882, 32532, 39072, 25474, 28359, 30872, 28857, 20856,
michael@0 11619 38747, 22443, 30005, 20291, 30008, 24215, 24806, 22880, 28096, 27583,
michael@0 11620 30857, 21500, 38613, 20939, 20993, 25481, 21514, 38035, 35843, 36300,
michael@0 11621 29241, 30879, 34678, 36845, 35853, 21472, 19969, 30447, 21486, 38025,
michael@0 11622 39030, [12237, 40718], 38189, 23450, 35746, 20002, 19996, 20908, 33891,
michael@0 11623 25026, 21160, 26635, 20375, 24683, 20923, 27934, 20828, 25238,
michael@0 11624 [12099, 26007], 38497, [12182, 35910], 36887, 30168, 37117, 30563, 27602,
michael@0 11625 29322, 29420, 35835, 22581, 30585, 36172, 26460, 38208, 32922, 24230,
michael@0 11626 28193, 22930, 31471, 30701, 38203, 27573, 26029, 32526, 22534, 20817,
michael@0 11627 38431, 23545, 22697, 21544, 36466, 25958, 39039, 22244, 38045, 30462,
michael@0 11628 36929, 25479, 21702, 22810, 22842, 22427, 36530, 26421, 36346, 33333,
michael@0 11629 21057, 24816, 22549, 34558, 23784, 40517, 20420, 39069, 35769, 23077,
michael@0 11630 24694, 21380, 25212, 36943, 37122, 39295, 24681, [12157, 32780],
michael@0 11631 [12041, 20799], [12159, 32819], 23572, 39285, 27953, [12038, 20108], 36144,
michael@0 11632 21457, 32602, 31567, 20240, 20047, 38400, 27861, 29648, 34281, 24070,
michael@0 11633 30058, 32763, 27146, 30718, 38034, 32321, 20961, 28902, 21453, 36820,
michael@0 11634 33539, 36137, 29359, 39277, 27867, 22346, 33459, [12101, 26041], 32938,
michael@0 11635 25151, 38450, 22952, 20223, 35775, 32442, 25918, 33778, [12206, 38750],
michael@0 11636 21857, 39134, 32933, 21290, 35837, 21536, 32954, 24223, 27832, 36153,
michael@0 11637 33452, 37210, 21545, 27675, 20998, 32439, 22367, 28954, 27774, 31881,
michael@0 11638 22859, 20221, 24575, 24868, 31914, 20016, 23553, 26539, 34562, 23792,
michael@0 11639 38155, 39118, 30127, 28925, 36898, 20911, 32541, 35773, 22857, 20964,
michael@0 11640 20315, 21542, 22827, 25975, 32932, 23413, 25206, 25282, 36752, 24133,
michael@0 11641 27679, 31526, 20239, 20440, 26381, 28014, 28074, 31119, 34993, 24343,
michael@0 11642 29995, 25242, 36741, 20463, 37340, 26023, 33071, 33105, 24220, 33104,
michael@0 11643 36212, 21103, 35206, 36171, 22797, 20613, 20184, [12201, 38428],
michael@0 11644 [12119, 29238], 33145, 36127, 23500, 35747, 38468, 22919, 32538, 21648,
michael@0 11645 22134, 22030, 35813, 25913, 27010, 38041, 30422, 28297, [12082, 24178],
michael@0 11646 [12130, 29976], 26438, 26577, 31487, 32925, 36214, 24863, 31174, 25954,
michael@0 11647 36195, 20872, 21018, 38050, 32568, 32923, 32434, 23703, 28207, 26464,
michael@0 11648 31705, 30347, [12220, 39640], 33167, 32660, 31957, 25630, 38224, 31295,
michael@0 11649 21578, 21733, 27468, 25601, [12093, 25096], 40509, 33011, 30105, 21106,
michael@0 11650 [12208, 38761], 33883, 26684, 34532, 38401, 38548, 38124, 20010, 21508,
michael@0 11651 32473, 26681, 36319, 32789, 26356, 24218, 32697, 22466, 32831, 26775,
michael@0 11652 [12079, 24037], 25915, 21151, 24685, 40858, 20379, 36524, 20844, 23467,
michael@0 11653 [12088, 24339], 24041, 27742, 25329, 36129, 20849, 38057, 21246, 27807,
michael@0 11654 33503, 29399, 22434, 26500, 36141, 22815, 36764, 33735, 21653, 31629,
michael@0 11655 20272, 27837, 23396, 22993, [12238, 40723], 21476, 34506, [12219, 39592],
michael@0 11656 [12181, 35895], 32929, 25925, 39038, 22266, 38599, 21038, [12128, 29916],
michael@0 11657 21072, 23521, 25346, 35074, 20054, 25296, 24618, 26874, 20851, 23448,
michael@0 11658 20896, 35266, 31649, 39302, 32592, 24815, 28748, 36143, 20809,
michael@0 11659 [12084, 24191], 36891, 29808, 35268, 22317, 30789, 24402, 40863, 38394,
michael@0 11660 36712, [12225, 39740], 35809, 30328, 26690, 26588, 36330, 36149, 21053,
michael@0 11661 36746, 28378, 26829, 38149, 37101, 22269, 26524, 35065, 36807, 21704,
michael@0 11662 39608, 23401, 28023, 27686, 20133, 23475, 39559, 37219, 25000, 37039,
michael@0 11663 38889, 21547, 28085, 23506, 20989, 21898, 32597, 32752, 25788, 25421,
michael@0 11664 26097, 25022, 24717, 28938, 27735, 27721, 22831, 26477, 33322, 22741,
michael@0 11665 22158, 35946, 27627, 37085, 22909, 32791, 21495, 28009, 21621, 21917,
michael@0 11666 33655, 33743, 26680, [12146, 31166], 21644, 20309, 21512, 30418, 35977,
michael@0 11667 38402, 27827, 28088, 36203, 35088, 40548, 36154, 22079, [12234, 40657],
michael@0 11668 30165, 24456, 29408, 24680, 21756, 20136, 27178, 34913, 24658, 36720,
michael@0 11669 21700, 28888, 34425, 40511, 27946, 23439, 24344, 32418, 21897, 20399,
michael@0 11670 29492, 21564, 21402, 20505, 21518, 21628, 20046, 24573, 29786, 22774,
michael@0 11671 33899, 32993, 34676, 29392, 31946, 28246, 24359, 34382, 21804, 25252,
michael@0 11672 20114, 27818, 25143, 33457, 21719, 21326, 29502, 28369, 30011, 21010,
michael@0 11673 21270, 35805, 27088, 24458, 24576, 28142, 22351, 27426, 29615, 26707,
michael@0 11674 36824, 32531, 25442, 24739, 21796, 30186, 35938, 28949, 28067, 23462,
michael@0 11675 24187, 33618, 24908, 40644, 30970, 34647, 31783, 30343, 20976, 24822,
michael@0 11676 29004, 26179, 24140, 24653, 35854, 28784, 25381, 36745, 24509, 24674,
michael@0 11677 34516, 22238, 27585, 24724, 24935, 21321, 24800, 26214, 36159, 31229,
michael@0 11678 20250, 28905, 27719, 35763, 35826, 32472, 33636, 26127, 23130, 39746,
michael@0 11679 27985, 28151, 35905, 27963, 20249, [12117, 28779], 33719, 25110, 24785,
michael@0 11680 38669, 36135, 31096, 20987, 22334, 22522, 26426, 30072, 31293, 31215,
michael@0 11681 31637, 32908, 39269, 36857, 28608, 35749, 40481, 23020, 32489, 32521,
michael@0 11682 21513, 26497, 26840, 36753, 31821, 38598, 21450, 24613, 30142, 27762,
michael@0 11683 21363, 23241, 32423, 25380, [12047, 20960], 33034, [12080, 24049], 34015,
michael@0 11684 25216, 20864, 23395, 20238, 31085, 21058, 24760, 27982, 23492, 23490,
michael@0 11685 35745, 35760, 26082, 24524, 38469, 22931, 32487, 32426, 22025, 26551,
michael@0 11686 22841, 20339, 23478, 21152, 33626, 39050, 36158, 30002, 38078, 20551,
michael@0 11687 31292, 20215, 26550, 39550, 23233, 27516, 30417, 22362, 23574, 31546,
michael@0 11688 38388, 29006, 20860, 32937, 33392, 22904, 32516, 33575, 26816, 26604,
michael@0 11689 30897, 30839, 25315, 25441, 31616, 20461, 21098, 20943, 33616, 27099,
michael@0 11690 37492, 36341, 36145, 35265, 38190, 31661, 20214, 20581, 33328, 21073,
michael@0 11691 39279, 28176, 28293, 28071, 24314, 20725, 23004, 23558, 27974, 27743,
michael@0 11692 30086, 33931, 26728, 22870, 35762, 21280, 37233, 38477, 34121, 26898,
michael@0 11693 30977, 28966, 33014, 20132, 37066, 27975, 39556, 23047, 22204, 25605,
michael@0 11694 38128, 30699, 20389, 33050, 29409, [12179, 35282], 39290, 32564, 32478,
michael@0 11695 21119, 25945, 37237, 36735, 36739, 21483, 31382, 25581, 25509, 30342,
michael@0 11696 31224, 34903, 38454, 25130, 21163, 33410, 26708, 26480, 25463, 30571,
michael@0 11697 31469, 27905, 32467, 35299, 22992, 25106, 34249, 33445, 30028, 20511,
michael@0 11698 20171, 30117, 35819, 23626, [12081, 24062], 31563, [12100, 26020],
michael@0 11699 [12198, 37329], 20170, 27941, 35167, 32039, 38182, 20165, 35880, 36827,
michael@0 11700 38771, 26187, 31105, 36817, 28908, 28024, 23613, 21170, 33606, 20834,
michael@0 11701 33550, 30555, 26230, 40120, 20140, 24778, 31934, 31923, 32463, 20117,
michael@0 11702 35686, 26223, 39048, 38745, 22659, 25964, 38236, 24452, 30153, 38742,
michael@0 11703 31455, 31454, 20928, 28847, 31384, 25578, 31350, 32416, 29590,
michael@0 11704 [12210, 38893], 20037, 28792, 20061, 37202, 21417, 25937, 26087,
michael@0 11705 [12165, 33276], 33285, 21646, 23601, 30106, 38816, 25304, 29401, 30141,
michael@0 11706 23621, 39545, 33738, 23616, 21632, 30697, 20030, 27822, 32858, 25298,
michael@0 11707 25454, 24040, 20855, 36317, 36382, 38191, 20465, 21477, 24807, 28844,
michael@0 11708 21095, 25424, 40515, 23071, 20518, 30519, 21367, 32482, 25733, 25899,
michael@0 11709 25225, 25496, 20500, 29237, 35273, 20915, 35776, 32477, 22343, 33740,
michael@0 11710 38055, 20891, 21531, 23803, 20426, 31459, 27994, 37089, 39567, 21888,
michael@0 11711 21654, 21345, 21679, 24320, 25577, 26999, 20975, 24936, 21002, 22570,
michael@0 11712 21208, 22350, 30733, 30475, 24247, 24951, 31968, 25179, 25239, 20130,
michael@0 11713 28821, 32771, 25335, 28900, 38752, 22391, 33499, 26607, 26869, 30933,
michael@0 11714 39063, 31185, 22771, 21683, 21487, 28212, 20811, 21051, 23458, 35838,
michael@0 11715 32943, 21827, 22438, 24691, 22353, 21549, 31354, 24656, 23380, 25511,
michael@0 11716 25248, [12061, 21475], 25187, 23495, 26543, 21741, 31391, 33510, 37239,
michael@0 11717 24211, 35044, 22840, 22446, 25358, 36328, 33007, 22359, 31607, 20393,
michael@0 11718 24555, 23485, 27454, 21281, 31568, 29378, 26694, 30719, 30518, 26103,
michael@0 11719 20917, 20111, 30420, 23743, 31397, 33909, 22862, 39745, 20608, 39304,
michael@0 11720 24871, 28291, 22372, 26118, 25414, 22256, 25324, 25193, 24275, 38420,
michael@0 11721 22403, 25289, 21895, 34593, 33098, 36771, 21862, 33713, 26469, 36182,
michael@0 11722 34013, 23146, 26639, 25318, 31726, 38417, 20848, 28572, 35888, 25597,
michael@0 11723 35272, 25042, 32518, 28866, 28389, 29701, 27028, 29436, 24266, 37070,
michael@0 11724 26391, 28010, 25438, 21171, 29282, [12156, 32769], 20332, 23013, 37226,
michael@0 11725 28889, 28061, 21202, 20048, 38647, 38253, 34174, 30922, 32047, 20769,
michael@0 11726 22418, 25794, 32907, 31867, 27882, 26865, 26974, 20919, 21400, 26792,
michael@0 11727 29313, 40654, 31729, 29432, 31163, 28435, 29702, 26446, [12197, 37324],
michael@0 11728 40100, 31036, 33673, 33620, 21519, 26647, 20029, 21385, 21169, 30782,
michael@0 11729 21382, 21033, 20616, 20363, 20432, 30178, [12148, 31435], 31890, 27813,
michael@0 11730 [12202, 38582], [12050, 21147], 29827, 21737, 20457, 32852, 33714, 36830,
michael@0 11731 38256, 24265, 24604, 28063, 24088, 25947, 33080, 38142, 24651, 28860,
michael@0 11732 32451, 31918, 20937, 26753, 31921, 33391, 20004, 36742, 37327, 26238,
michael@0 11733 20142, 35845, 25769, 32842, 20698, 30103, 29134, 23525, 36797, 28518,
michael@0 11734 20102, 25730, 38243, 24278, 26009, 21015, 35010, 28872, 21155, 29454,
michael@0 11735 29747, 26519, 30967, 38678, 20020, 37051, 40158, 28107, 20955, 36161,
michael@0 11736 21533, 25294, 29618, 33777, 38646, 40836, 38083, 20278, 32666, 20940,
michael@0 11737 28789, 38517, 23725, 39046, 21478, 20196, 28316, 29705, 27060, 30827,
michael@0 11738 39311, 30041, 21016, 30244, 27969, 26611, 20845, 40857, 32843, 21657,
michael@0 11739 31548, 31423, 38534, 22404, 25314, 38471, 27004, 23044, 25602, 31699,
michael@0 11740 28431, 38475, 33446, 21346, 39045, 24208, 28809, 25523, 21348, 34383,
michael@0 11741 40065, 40595, 30860, 38706, 36335, 36162, [12229, 40575], 28510, 31108,
michael@0 11742 24405, 38470, 25134, 39540, 21525, 38109, 20387, 26053, 23653, 23649,
michael@0 11743 32533, 34385, 27695, 24459, 29575, 28388, 32511, 23782, 25371, 23402,
michael@0 11744 28390, 21365, 20081, 25504, 30053, 25249, 36718, 20262, 20177, 27814,
michael@0 11745 32438, 35770, 33821, 34746, 32599, 36923, 38179, 31657, 39585, 35064,
michael@0 11746 33853, 27931, 39558, 32476, 22920, [12231, 40635], 29595, 30721, 34434,
michael@0 11747 39532, 39554, 22043, 21527, 22475, 20080, 40614, 21334, 36808, 33033,
michael@0 11748 30610, 39314, 34542, 28385, 34067, 26364, 24930, 28459, 35881, 33426,
michael@0 11749 33579, 30450, 27667, 24537, 33725, 29483, 33541, 38170, [12113, 27611],
michael@0 11750 [12141, 30683], 38086, 21359, 33538, 20882, 24125, 35980, 36152, 20040,
michael@0 11751 29611, 26522, 26757, 37238, 38665, 29028, 27809, 30473, 23186, 38209,
michael@0 11752 27599, 32654, 26151, 23504, 22969, 23194, 38376, 38391, 20204, 33804,
michael@0 11753 33945, 27308, 30431, 38192, 29467, 26790, 23391, 30511, 37274, 38753,
michael@0 11754 31964, 36855, 35868, 24357, [12150, 31859], 31192, 35269, 27852, 34588,
michael@0 11755 23494, 24130, 26825, 30496, 32501, 20885, 20813, 21193, 23081, 32517,
michael@0 11756 [12207, 38754], 33495, 25551, 30596, 34256, 31186, 28218, 24217, 22937,
michael@0 11757 34065, 28781, 27665, 25279, [12139, 30399], 25935, 24751, 38397, 26126,
michael@0 11758 34719, 40483, 38125, 21517, 21629, 35884, {f: 2, c: 25720}, 34321, 27169,
michael@0 11759 33180, 30952, 25705, 39764, 25273, 26411, 33707, 22696, 40664, 27819,
michael@0 11760 28448, 23518, 38476, 35851, 29279, 26576, 25287, 29281, 20137, 22982,
michael@0 11761 27597, 22675, 26286, 24149, 21215, 24917, [12106, 26408], [12140, 30446],
michael@0 11762 30566, 29287, 31302, 25343, 21738, 21584, 38048, 37027, 23068, 32435,
michael@0 11763 27670, 20035, 22902, 32784, 22856, 21335, 30007, 38590, 22218, 25376,
michael@0 11764 33041, 24700, 38393, 28118, 21602, 39297, 20869, 23273, 33021, 22958,
michael@0 11765 38675, 20522, 27877, 23612, 25311, 20320, 21311, 33147, 36870, 28346,
michael@0 11766 34091, 25288, 24180, 30910, 25781, 25467, 24565, 23064, 37247, 40479,
michael@0 11767 23615, 25423, 32834, 23421, 21870, 38218, 38221, 28037, 24744, 26592,
michael@0 11768 29406, 20957, 23425, 25319, 27870, [12124, 29275], 25197, 38062, 32445,
michael@0 11769 33043, 27987, 20892, 24324, 22900, 21162, 24594, [12069, 22899], 26262,
michael@0 11770 34384, 30111, 25386, 25062, 31983, 35834, 21734, 27431, 40485, 27572,
michael@0 11771 34261, 21589, 20598, 27812, 21866, 36276, 29228, 24085, 24597, 29750,
michael@0 11772 25293, 25490, 29260, 24472, 28227, 27966, 25856, 28504, 30424, 30928,
michael@0 11773 30460, 30036, 21028, 21467, 20051, 24222, 26049, 32810, 32982, 25243,
michael@0 11774 21638, 21032, 28846, 34957, 36305, 27873, 21624, 32986, 22521, 35060,
michael@0 11775 36180, 38506, 37197, 20329, 27803, 21943, 30406, 30768, 25256, 28921,
michael@0 11776 28558, 24429, 34028, 26842, 30844, 31735, 33192, 26379, 40527, 25447,
michael@0 11777 30896, 22383, 30738, 38713, 25209, 25259, 21128, 29749, 27607, 21860,
michael@0 11778 33086, 30130, [12138, 30382], 21305, 30174, 20731, 23617, 35692, 31687,
michael@0 11779 20559, [12122, 29255], 39575, 39128, 28418, 29922, 31080, 25735, 30629,
michael@0 11780 25340, 39057, 36139, 21697, 32856, 20050, 22378, 33529, 33805, 24179,
michael@0 11781 20973, 29942, 35780, 23631, 22369, 27900, 39047, 23110, 30772, 39748,
michael@0 11782 36843, 31893, 21078, 25169, 38138, 20166, 33670, 33889, 33769, 33970,
michael@0 11783 22484, 26420, 22275, 26222, 28006, 35889, 26333, 28689, 26399, 27450,
michael@0 11784 26646, 25114, 22971, 19971, 20932, 28422, 26578, 27791, 20854, 26827,
michael@0 11785 22855, 27495, 30054, 23822, 33040, 40784, 26071, 31048, 31041, 39569,
michael@0 11786 36215, 23682, 20062, 20225, 21551, 22865, 30732, 22120, [12115, 27668],
michael@0 11787 36804, 24323, 27773, 27875, 35755, 25488, 24688, 27965, 29301, 25190,
michael@0 11788 38030, 38085, 21315, 36801, 31614, 20191, 35878, 20094, 40660, 38065,
michael@0 11789 38067, 21069, 28508, 36963, 27973, 35892, 22545, 23884, [12107, 27424],
michael@0 11790 27465, 26538, 21595, 33108, 32652, 22681, 34103, 24378, 25250, 27207,
michael@0 11791 38201, 25970, 24708, 26725, 30631, 20052, 20392, 24039, 38808, 25772,
michael@0 11792 32728, 23789, 20431, 31373, 20999, 33540, 19988, 24623, 31363, 38054,
michael@0 11793 20405, 20146, 31206, 29748, 21220, 33465, 25810, 31165, 23517, 27777,
michael@0 11794 38738, 36731, 27682, 20542, 21375, 28165, 25806, 26228, 27696, 24773,
michael@0 11795 39031, 35831, 24198, 29756, 31351, 31179, 19992, 37041, 29699, 27714,
michael@0 11796 22234, 37195, 27845, 36235, 21306, 34502, 26354, 36527, 23624, 39537,
michael@0 11797 28192, 21462, 23094, 40843, 36259, 21435, 22280, 39079, 26435, 37275,
michael@0 11798 27849, 20840, 30154, 25331, [12125, 29356], 21048, 21149, 32570, 28820,
michael@0 11799 30264, 21364, 40522, 27063, 30830, 38592, 35033, 32676, 28982, 29123,
michael@0 11800 20873, 26579, 29924, 22756, 25880, 22199, 35753, 39286, 25200, 32469,
michael@0 11801 24825, 28909, 22764, 20161, [12040, 20154], 24525, 38887, 20219, 35748,
michael@0 11802 20995, 22922, 32427, 25172, 20173, [12103, 26085], 25102, 33592, 33993,
michael@0 11803 33635, 34701, 29076, 28342, 23481, 32466, 20887, 25545, 26580,
michael@0 11804 [12161, 32905], 33593, 34837, 20754, 23418, 22914, 36785, 20083, 27741,
michael@0 11805 [12042, 20837], 35109, 36719, 38446, 34122, 29790, 38160, 38384, 28070,
michael@0 11806 33509, 24369, 25746, 27922, 33832, 33134, 40131, 22622, 36187, 19977,
michael@0 11807 21441, 20254, 25955, 26705, 21971, 20007, 25620, 39578, 25195, 23234,
michael@0 11808 29791, [12170, 33394], 28073, 26862, 20711, 33678, 30722, 26432, 21049,
michael@0 11809 27801, 32433, 20667, 21861, 29022, 31579, 26194, 29642, 33515, 26441,
michael@0 11810 [12077, 23665], 21024, 29053, 34923, 38378, 38485, 25797, 36193, 33203,
michael@0 11811 21892, 27733, 25159, 32558, 22674, 20260, 21830, 36175, 26188, 19978,
michael@0 11812 23578, 35059, 26786, 25422, 31245, 28903, 33421, 21242, 38902, 23569,
michael@0 11813 21736, 37045, 32461, 22882, 36170, 34503, [12166, 33292], 33293, 36198,
michael@0 11814 25668, 23556, 24913, 28041, 31038, 35774, 30775, 30003, 21627, 20280,
michael@0 11815 [12189, 36523], 28145, 23072, 32453, 31070, 27784, 23457, 23158, 29978,
michael@0 11816 32958, 24910, 28183, 22768, [12131, 29983], 29989, 29298, 21319, 32499,
michael@0 11817 30465, 30427, 21097, 32988, 22307, 24072, 22833, 29422, 26045, 28287,
michael@0 11818 35799, [12075, 23608], 34417, [12055, 21313], [12143, 30707], 25342, 26102,
michael@0 11819 20160, [12215, 39135], 34432, 23454, 35782, 21490, [12142, 30690], 20351,
michael@0 11820 23630, 39542, 22987, 24335, [12144, 31034], [12064, 22763], 19990, 26623,
michael@0 11821 20107, 25325, 35475, 36893, 21183, 26159, 21980, 22124, 36866, 20181,
michael@0 11822 20365, 37322, 39280, [12114, 27663], 24066, 24643, 23460, 35270, 35797,
michael@0 11823 25910, [12095, 25163], [12216, 39318], 23432, 23551, 25480, 21806, 21463,
michael@0 11824 30246, 20861, 34092, 26530, 26803, 27530, 25234, 36755, 21460, 33298,
michael@0 11825 28113, 30095, 20070, 36174, 23408, 29087, 34223, 26257, 26329, 32626,
michael@0 11826 34560, [12233, 40653], [12239, 40736], 23646, 26415, 36848, 26641, 26463,
michael@0 11827 25101, 31446, 22661, 24246, 25968, 28465, 24661, 21047, 32781, 25684,
michael@0 11828 34928, 29993, 24069, 26643, 25332, 38684, 21452, 29245, 35841,
michael@0 11829 [12116, 27700], 30561, 31246, 21550, 30636, 39034, 33308, 35828, 30805,
michael@0 11830 26388, 28865, 26031, 25749, 22070, 24605, 31169, 21496, 19997, 27515,
michael@0 11831 32902, 23546, 21987, 22235, 20282, 20284, 39282, 24051, 26494, 32824,
michael@0 11832 24578, 39042, 36865, 23435, 35772, 35829, 25628, 33368, 25822, 22013,
michael@0 11833 33487, 37221, 20439, 32032, 36895, 31903, 20723, 22609, 28335, 23487,
michael@0 11834 35785, 32899, 37240, 33948, 31639, 34429, 38539, 38543, 32485, 39635,
michael@0 11835 30862, 23681, 31319, 36930, 38567, 31071, 23385, 25439, 31499, 34001,
michael@0 11836 26797, 21766, 32553, 29712, 32034, 38145, 25152, 22604, 20182, 23427,
michael@0 11837 22905, 22612, 29549, 25374, 36427, 36367, 32974, 33492, 25260, 21488,
michael@0 11838 27888, 37214, 22826, 24577, 27760, 22349, 25674, 36138, 30251, 28393,
michael@0 11839 22363, 27264, 30192, 28525, 35885, 35848, 22374, 27631, 34962, 30899,
michael@0 11840 25506, 21497, 28845, 27748, 22616, 25642, 22530, 26848, 33179, 21776,
michael@0 11841 31958, 20504, 36538, 28108, 36255, 28907, 25487, 28059, 28372, 32486,
michael@0 11842 33796, 26691, 36867, 28120, 38518, 35752, 22871, 29305, 34276, 33150,
michael@0 11843 30140, 35466, 26799, 21076, 36386, 38161, 25552, 39064, 36420, 21884,
michael@0 11844 20307, 26367, 22159, 24789, 28053, 21059, 23625, 22825, 28155, 22635,
michael@0 11845 [12133, 30000], 29980, 24684, 33300, 33094, 25361, 26465, 36834, 30522,
michael@0 11846 36339, 36148, 38081, 24086, 21381, 21548, 28867, 27712, 24311, 20572,
michael@0 11847 20141, 24237, 25402, 33351, 36890, 26704, 37230, 30643, 21516, 38108,
michael@0 11848 24420, 31461, 26742, 25413, 31570, 32479, 30171, 20599, 25237, 22836,
michael@0 11849 36879, 20984, 31171, 31361, 22270, 24466, 36884, 28034, 23648,
michael@0 11850 [12063, 22303], 21520, 20820, 28237, 22242, 25512, 39059, 33151, 34581,
michael@0 11851 35114, 36864, 21534, 23663, 33216, 25302, 25176, 33073, 40501, 38464,
michael@0 11852 39534, 39548, 26925, 22949, 25299, 21822, 25366, 21703, 34521, 27964,
michael@0 11853 23043, [12129, 29926], 34972, 27498, 22806, 35916, 24367, 28286, 29609,
michael@0 11854 39037, 20024, 28919, 23436, 30871, 25405, 26202, 30358, 24779, 23451,
michael@0 11855 23113, 19975, 33109, 27754, 29579, 20129, 26505, [12153, 32593], 24448,
michael@0 11856 26106, 26395, 24536, 22916, 23041, 24013, 24494, 21361, 38886, 36829,
michael@0 11857 26693, 22260, 21807, 24799, 20026, 28493, 32500, 33479, 33806, 22996,
michael@0 11858 20255, 20266, 23614, 32428, 26410, 34074, 21619, 30031, 32963, 21890,
michael@0 11859 39759, 20301, 28205, 35859, 23561, 24944, 21355, 30239, 28201, 34442,
michael@0 11860 [12098, 25991], 38395, 32441, 21563, 31283, 32010, 38382, 21985, 32705,
michael@0 11861 29934, 25373, 34583, 28065, 31389, 25105, 26017, 21351, 25569, 27779,
michael@0 11862 24043, 21596, 38056, 20044, 27745, 35820, 23627, [12102, 26080], 33436,
michael@0 11863 26791, 21566, 21556, [12111, 27595], 27494, 20116, 25410, 21320, 33310,
michael@0 11864 20237, 20398, 22366, 25098, 38654, 26212, 29289, 21247, 21153, 24735,
michael@0 11865 35823, 26132, 29081, 26512, 35199, 30802, 30717, 26224, 22075, 21560,
michael@0 11866 38177, 29306, 31232, 24687, 24076, 24713, 33181, [12067, 22805], 24796,
michael@0 11867 29060, 28911, 28330, 27728, 29312, 27268, 34989, 24109, 20064, 23219,
michael@0 11868 21916, 38115, 27927, 31995, 38553, 25103, 32454, 30606, 34430, 21283,
michael@0 11869 38686, 36758, 26247, 23777, 20384, 29421, 19979, 21414, 22799, 21523,
michael@0 11870 25472, 38184, 20808, 20185, 40092, 32420, 21688, 36132, 34900, 33335,
michael@0 11871 38386, 28046, 24358, 23244, 26174, 38505, 29616, 29486, 21439, 33146,
michael@0 11872 39301, 32673, 23466, 38519, 38480, 32447, 30456, 21410, 38262,
michael@0 11873 [12217, 39321], 31665, 35140, 28248, 20065, 32724, 31077, 35814, 24819,
michael@0 11874 21709, 20139, 39033, 24055, 27233, 20687, 21521, 35937, 33831, 30813,
michael@0 11875 38660, 21066, 21742, 22179, 38144, 28040, 23477, 28102, 26195,
michael@0 11876 [12073, 23567], 23389, 26657, 32918, 21880, 31505, 25928, 26964, 20123,
michael@0 11877 27463, 34638, 38795, 21327, 25375, 25658, 37034, 26012, 32961, 35856,
michael@0 11878 20889, 26800, 21368, 34809, 25032, 27844, 27899, 35874, 23633, 34218,
michael@0 11879 33455, 38156, 27427, [12191, 36763], 26032, 24571, [12092, 24515], 20449,
michael@0 11880 34885, 26143, 33125, 29481, 24826, 20852, 21009, 22411, 24418, 37026,
michael@0 11881 [12175, 34892], 37266, 24184, 26447, 24615, 22995, 20804, 20982, 33016,
michael@0 11882 21256, 27769, 38596, 29066, 20241, 20462, 32670, 26429, 21957, 38152,
michael@0 11883 31168, 34966, 32483, 22687, 25100, 38656, 34394, 22040, 39035, 24464,
michael@0 11884 35768, 33988, 37207, 21465, 26093, 24207, 30044, 24676, 32110, 23167,
michael@0 11885 32490, 32493, 36713, 21927, 23459, 24748, 26059, [12126, 29572], 36873,
michael@0 11886 30307, 30505, 32474, 38772, 34203, 23398, [12147, 31348], 38634,
michael@0 11887 [12174, 34880], 21195, 29071, 24490, 26092, 35810, 23547, 39535, 24033,
michael@0 11888 27529, 27739, 35757, 35759, 36874, 36805, 21387, 25276, 40486, 40493,
michael@0 11889 21568, 20011, 33469, [12123, 29273], 34460, 23830, 34905, 28079, 38597,
michael@0 11890 21713, 20122, 35766, 28937, 21693, 38409, 28895, 28153, 30416, 20005,
michael@0 11891 30740, 34578, 23721, 24310, [12180, 35328], 39068, 38414, 28814, 27839,
michael@0 11892 22852, 25513, 30524, 34893, 28436, 33395, 22576, 29141, 21388, 30746,
michael@0 11893 38593, 21761, 24422, 28976, 23476, 35866, 39564, 27523, 22830, 40495,
michael@0 11894 31207, 26472, 25196, 20335, 30113, [12154, 32650], 27915, 38451, 27687,
michael@0 11895 20208, 30162, 20859, 26679, 28478, 36992, 33136, 22934, 29814, 25671,
michael@0 11896 23591, 36965, 31377, 35875, 23002, 21676, 33280, 33647, 35201, 32768,
michael@0 11897 26928, 22094, 32822, 29239, 37326, 20918, 20063, 39029, 25494, 19994,
michael@0 11898 21494, 26355, 33099, 22812, 28082, [12032, 19968], 22777, 21307, 25558,
michael@0 11899 38129, 20381, 20234, [12176, 34915], 39056, 22839, 36951, 31227, 20202,
michael@0 11900 33008, 30097, 27778, 23452, 23016, 24413, 26885, 34433, 20506, 24050,
michael@0 11901 [12036, 20057], 30691, 20197, 33402, 25233, 26131, [12194, 37009], 23673,
michael@0 11902 20159, 24441, 33222, 36920, 32900, 30123, 20134, 35028, 24847, 27589,
michael@0 11903 24518, 20041, 30410, 28322, 35811, 35758, 35850, 35793, 24322, 32764,
michael@0 11904 32716, 32462, 33589, 33643, 22240, 27575, [12211, 38899], 38452, 23035,
michael@0 11905 21535, 38134, 28139, 23493, 39278, 23609, 24341, 38544, 21360, 33521,
michael@0 11906 27185, 23156, 40560, 24212, 32552, 33721, {f: 2, c: 33828}, 33639, 34631,
michael@0 11907 36814, 36194, 30408, 24433, 39062, 30828, 26144, 21727, 25317, 20323,
michael@0 11908 33219, 30152, 24248, 38605, 36362, 34553, 21647, 27891, 28044, 27704,
michael@0 11909 24703, 21191, [12132, 29992], 24189, 20248, 24736, 24551, 23588, 30001,
michael@0 11910 37038, 38080, 29369, 27833, 28216, [12195, 37193], 26377, 21451, 21491,
michael@0 11911 20305, 37321, 35825, [12060, 21448], 24188, 36802, 28132, 20110, 30402,
michael@0 11912 27014, 34398, 24858, 33286, 20313, 20446, 36926, 40060, 24841, 28189,
michael@0 11913 28180, 38533, 20104, 23089, [12204, 38632], 19982, 23679, 31161, 23431,
michael@0 11914 35821, [12155, 32701], [12127, 29577], 22495, 33419, 37057, 21505, 36935,
michael@0 11915 21947, 23786, 24481, 24840, 27442, 29425, 32946, 35465, 28020, 23507,
michael@0 11916 35029, 39044, 35947, 39533, 40499, 28170, 20900, 20803, 22435, 34945,
michael@0 11917 21407, 25588, 36757, 22253, 21592, 22278, 29503, 28304, 32536, 36828,
michael@0 11918 33489, 24895, 24616, 38498, [12104, 26352], 32422, 36234, 36291, 38053,
michael@0 11919 23731, 31908, [12105, 26376], 24742, 38405, 32792, 20113, 37095, 21248,
michael@0 11920 38504, 20801, 36816, 34164, 37213, 26197, 38901, 23381, 21277, 30776,
michael@0 11921 26434, 26685, 21705, 28798, 23472, 36733, 20877, 22312, 21681, 25874,
michael@0 11922 26242, 36190, 36163, 33039, 33900, 36973, 31967, 20991, 34299, 26531,
michael@0 11923 26089, 28577, 34468, 36481, 22122, 36896, 30338, 28790, 29157, 36131,
michael@0 11924 25321, 21017, 27901, 36156, 24590, 22686, 24974, 26366, 36192, 25166,
michael@0 11925 21939, 28195, 26413, 36711, 38113, 38392, 30504, 26629, 27048, 21643,
michael@0 11926 20045, 28856, 35784, 25688, 25995, 23429, 31364, 20538, 23528, 30651,
michael@0 11927 27617, 35449, 31896, 27838, 30415, 26025, 36759, 23853, 23637, 34360,
michael@0 11928 26632, 21344, 25112, 31449, 28251, 32509, 27167, 31456, 24432, 28467,
michael@0 11929 24352, 25484, 28072, 26454, 19976, 24080, 36134, 20183, 32960, 30260,
michael@0 11930 38556, 25307, 26157, 25214, 27836, 36213, 29031, 32617, 20806, 32903,
michael@0 11931 21484, 36974, 25240, 21746, 34544, 36761, 32773, 38167, 34071, 36825,
michael@0 11932 27993, 29645, 26015, 30495, 29956, 30759, 33275, 36126, 38024, 20390,
michael@0 11933 26517, 30137, 35786, 38663, 25391, 38215, 38453, 33976, 25379, 30529,
michael@0 11934 24449, 29424, 20105, 24596, 25972, 25327, 27491, 25919, 24103, 30151,
michael@0 11935 37073, 35777, 33437, 26525, [12096, 25903], 21553, 34584, 30693, 32930,
michael@0 11936 33026, 27713, 20043, 32455, 32844, 30452, 26893, 27542, 25191, 20540,
michael@0 11937 20356, 22336, 25351, [12108, 27490], 36286, 21482, 26088, 32440, 24535,
michael@0 11938 25370, 25527, [12164, 33267], 33268, 32622, 24092, 23769, 21046, 26234,
michael@0 11939 31209, 31258, 36136, 28825, 30164, 28382, 27835, 31378, 20013, 30405,
michael@0 11940 24544, 38047, 34935, 32456, 31181, 32959, 37325, 20210, 20247,
michael@0 11941 [12168, 33311], 21608, 24030, 27954, 35788, 31909, 36724, 32920, 24090,
michael@0 11942 21650, 30385, 23449, 26172, 39588, 29664, 26666, 34523, 26417, 29482,
michael@0 11943 35832, 35803, 36880, [12149, 31481], 28891, 29038, 25284, 30633, 22065,
michael@0 11944 20027, 33879, 26609, 21161, 34496, 36142, 38136, 31569, 20303, 27880,
michael@0 11945 31069, 39547, 25235, [12118, 29226], 25341, 19987, 30742, 36716, 25776,
michael@0 11946 36186, 31686, 26729, 24196, 35013, 22918, 25758, 22766, 29366, 26894,
michael@0 11947 38181, 36861, 36184, 22368, 32512, 35846, 20934, 25417, 25305, 21331,
michael@0 11948 26700, 29730, 33537, 37196, 21828, 30528, 28796, 27978, 20857, 21672,
michael@0 11949 36164, 23039, 28363, 28100, 23388, 32043, 20180, 31869, 28371,
michael@0 11950 [12070, 23376], [12163, 33258], 28173, 23383, 39683, 26837, 36394, 23447,
michael@0 11951 32508, 24635, 32437, 37049, [12187, 36208], 22863, 25549, 31199,
michael@0 11952 [12188, 36275], 21330, 26063, 31062, 35781, 38459, 32452, 38075, 32386,
michael@0 11953 22068, 37257, 26368, 32618, 23562, 36981, 26152, 24038, 20304, 26590,
michael@0 11954 20570, 20316, 22352, 24231, 20109, 19980, 20800, 19984, 24319, 21317,
michael@0 11955 19989, 20120, 19998, [12224, 39730], 23404, 22121, [12033, 20008], 31162,
michael@0 11956 [12035, 20031], [12052, 21269], 20039, 22829, [12120, 29243], 21358, 27664,
michael@0 11957 22239, 32996, 39319, 27603, 30590, 40727, [12034, 20022], 20127, 40720,
michael@0 11958 20060, 20073, 20115, 33416, 23387, 21868, 22031, 20164, 21389, 21405,
michael@0 11959 21411, 21413, 21422, 38757, 36189, [12053, 21274], 21493, 21286, 21294,
michael@0 11960 21310, 36188, 21350, 21347, 20994, 21000, 21006, 21037, 21043,
michael@0 11961 {f: 2, c: 21055}, 21068, 21086, 21089, 21084, 33967, 21117, 21122, 21121,
michael@0 11962 21136, 21139, [12044, 20866], 32596, 20155, 20163, 20169, 20162, 20200,
michael@0 11963 20193, 20203, 20190, 20251, 20211, 20258, 20324, 20213, 20261, 20263,
michael@0 11964 20233, 20267, 20318, 20327, 25912, 20314, 20317, 20319, 20311, 20274,
michael@0 11965 20285, 20342, 20340, 20369, 20361, 20355, 20367, 20350, 20347, 20394,
michael@0 11966 20348, 20396, 20372, 20454, 20456, 20458, 20421, 20442, 20451, 20444,
michael@0 11967 20433, 20447, 20472, 20521, 20556, 20467, 20524, 20495, 20526, 20525,
michael@0 11968 20478, 20508, 20492, 20517, 20520, 20606, 20547, 20565, 20552, 20558,
michael@0 11969 20588, 20603, 20645, 20647, 20649, 20666, 20694, 20742, 20717, 20716,
michael@0 11970 20710, 20718, 20743, 20747, 20189, 27709, 20312, 20325, 20430,
michael@0 11971 [12245, 40864], 27718, 31860, 20846, 24061, 40649, 39320, 20865, 22804,
michael@0 11972 [12051, 21241], 21261, 35335, 21264, 20971, 22809, 20821, [12039, 20128],
michael@0 11973 20822, 20147, 34926, 34980, 20149, 33044, 35026, 31104, 23348, 34819,
michael@0 11974 32696, [12046, 20907], 20913, 20925, 20924, 20935, [12045, 20886], 20898,
michael@0 11975 20901, 35744, {f: 2, c: 35750}, 35754, {f: 2, c: 35764}, 35767,
michael@0 11976 {f: 2, c: 35778}, 35787, 35791, 35790, {f: 3, c: 35794}, 35798,
michael@0 11977 {f: 2, c: 35800}, 35804, {f: 2, c: 35807}, 35812, {f: 2, c: 35816}, 35822,
michael@0 11978 35824, 35827, 35830, 35833, 35836, {f: 2, c: 35839}, 35842, 35844, 35847,
michael@0 11979 35852, 35855, {f: 2, c: 35857}, {f: 3, c: 35860}, 35865, 35867, 35864,
michael@0 11980 35869, {f: 3, c: 35871}, 35877, 35879, {f: 2, c: 35882}, {f: 2, c: 35886},
michael@0 11981 {f: 2, c: 35890}, {f: 2, c: 35893}, [12057, 21353], 21370, 38429, 38434,
michael@0 11982 38433, 38449, 38442, 38461, 38460, 38466, 38473, 38484, 38495, 38503,
michael@0 11983 38508, 38514, 38516, 38536, 38541, 38551, 38576, 37015, 37019, 37021,
michael@0 11984 37017, 37036, 37025, 37044, 37043, 37046, 37050, 37048, 37040, 37071,
michael@0 11985 37061, 37054, 37072, 37060, 37063, 37075, 37094, 37090, 37084, 37079,
michael@0 11986 37083, 37099, 37103, 37118, 37124, 37154, 37150, 37155, 37169, 37167,
michael@0 11987 37177, 37187, 37190, 21005, 22850, 21154, {f: 2, c: 21164}, 21182, 21759,
michael@0 11988 21200, 21206, 21232, 21471, 29166, 30669, [12085, 24308], [12048, 20981],
michael@0 11989 20988, [12223, 39727], [12059, 21430], 24321, 30042, 24047, 22348, 22441,
michael@0 11990 22433, 22654, 22716, 22725, 22737, 22313, 22316, 22314, 22323, 22329,
michael@0 11991 {f: 2, c: 22318}, 22364, 22331, 22338, 22377, 22405, 22379, 22406, 22396,
michael@0 11992 22395, 22376, 22381, 22390, 22387, 22445, 22436, 22412, 22450, 22479,
michael@0 11993 22439, 22452, 22419, 22432, 22485, 22488, 22490, 22489, 22482, 22456,
michael@0 11994 22516, 22511, 22520, 22500, 22493, 22539, 22541, 22525, 22509, 22528,
michael@0 11995 22558, 22553, 22596, 22560, 22629, 22636, 22657, 22665, 22682, 22656,
michael@0 11996 39336, 40729, 25087, 33401, 33405, 33407, 33423, 33418, 33448, 33412,
michael@0 11997 33422, 33425, 33431, 33433, 33451, 33464, 33470, 33456, 33480, 33482,
michael@0 11998 33507, 33432, 33463, 33454, {f: 2, c: 33483}, 33473, 33449, 33460, 33441,
michael@0 11999 33450, 33439, 33476, 33486, 33444, 33505, 33545, 33527, 33508, 33551,
michael@0 12000 33543, 33500, 33524, 33490, 33496, 33548, 33531, 33491, 33553, 33562,
michael@0 12001 33542, {f: 2, c: 33556}, 33504, 33493, 33564, 33617, {f: 2, c: 33627},
michael@0 12002 33544, 33682, 33596, 33588, 33585, 33691, 33630, 33583, 33615, 33607,
michael@0 12003 33603, 33631, 33600, 33559, 33632, 33581, 33594, 33587, 33638, 33637,
michael@0 12004 33640, 33563, 33641, 33644, 33642, {f: 2, c: 33645}, 33712, 33656,
michael@0 12005 {f: 2, c: 33715}, 33696, 33706, 33683, 33692, 33669, 33660, 33718, 33705,
michael@0 12006 33661, 33720, 33659, 33688, 33694, 33704, 33722, 33724, 33729, 33793,
michael@0 12007 33765, 33752, 22535, 33816, 33803, 33757, 33789, 33750, 33820, 33848,
michael@0 12008 33809, 33798, 33748, 33759, 33807, 33795, {f: 2, c: 33784}, 33770, 33733,
michael@0 12009 33728, 33830, 33776, 33761, 33884, 33873, 33882, 33881, 33907,
michael@0 12010 {f: 2, c: 33927}, 33914, 33929, 33912, 33852, 33862, 33897, 33910, 33932,
michael@0 12011 33934, 33841, 33901, 33985, 33997, 34000, 34022, 33981, 34003, 33994,
michael@0 12012 33983, 33978, 34016, 33953, 33977, 33972, 33943, 34021, 34019, 34060,
michael@0 12013 29965, 34104, 34032, 34105, 34079, 34106, 34134, 34107, 34047, 34044,
michael@0 12014 34137, 34120, 34152, 34148, 34142, 34170, 30626, 34115, 34162, 34171,
michael@0 12015 34212, 34216, 34183, 34191, 34169, 34222, 34204, 34181, 34233, 34231,
michael@0 12016 34224, 34259, 34241, 34268, 34303, 34343, 34309, 34345, 34326, 34364,
michael@0 12017 [12086, 24318], 24328, 22844, 22849, 32823, 22869, 22874, 22872, 21263,
michael@0 12018 [12074, 23586], 23589, 23596, 23604, 25164, 25194, 25247, 25275, 25290,
michael@0 12019 25306, 25303, 25326, 25378, 25334, 25401, 25419, 25411, 25517, 25590,
michael@0 12020 25457, 25466, 25486, 25524, 25453, 25516, 25482, 25449, 25518, 25532,
michael@0 12021 25586, 25592, 25568, 25599, 25540, 25566, 25550, 25682, 25542, 25534,
michael@0 12022 25669, 25665, 25611, 25627, 25632, 25612, 25638, 25633, 25694, 25732,
michael@0 12023 25709, 25750, 25722, {f: 2, c: 25783}, 25753, 25786, 25792, 25808, 25815,
michael@0 12024 25828, 25826, 25865, 25893, 25902, [12087, 24331], 24530, 29977, 24337,
michael@0 12025 21343, 21489, 21501, 21481, 21480, 21499, 21522, 21526, 21510, 21579,
michael@0 12026 {f: 3, c: 21586}, 21590, 21571, 21537, 21591, 21593, 21539, 21554, 21634,
michael@0 12027 21652, 21623, 21617, 21604, {f: 2, c: 21658}, 21636, 21622, 21606, 21661,
michael@0 12028 21712, 21677, 21698, 21684, 21714, 21671, 21670, {f: 2, c: 21715}, 21618,
michael@0 12029 21667, 21717, 21691, 21695, 21708, {f: 2, c: 21721}, 21724,
michael@0 12030 {f: 2, c: 21673}, 21668, 21725, 21711, 21726, 21787, 21735, 21792, 21757,
michael@0 12031 21780, 21747, {f: 2, c: 21794}, 21775, 21777, 21799, 21802, 21863, 21903,
michael@0 12032 21941, 21833, 21869, 21825, 21845, 21823, 21840, 21820, 21815, 21846,
michael@0 12033 {f: 3, c: 21877}, 21811, 21808, 21852, 21899, 21970, 21891, 21937, 21945,
michael@0 12034 21896, 21889, 21919, 21886, 21974, 21905, 21883, 21983, {f: 2, c: 21949},
michael@0 12035 21908, 21913, 21994, 22007, 21961, 22047, 21969, {f: 2, c: 21995}, 21972,
michael@0 12036 21990, 21981, 21956, 21999, 21989, {f: 2, c: 22002}, {f: 2, c: 21964},
michael@0 12037 21992, 22005, 21988, 36756, 22046, 22024, 22028, 22017, 22052, 22051,
michael@0 12038 22014, 22016, 22055, 22061, 22104, 22073, 22103, 22060, 22093, 22114,
michael@0 12039 22105, 22108, 22092, 22100, 22150, 22116, 22129, 22123, {f: 2, c: 22139},
michael@0 12040 22149, 22163, 22191, 22228, [12062, 22231], 22237, 22241, 22261, 22251,
michael@0 12041 22265, 22271, 22276, 22282, 22281, 22300, 24079, 24089, 24084, 24081,
michael@0 12042 24113, {f: 2, c: 24123}, 24119, 24132, 24148, 24155, 24158, 24161, 23692,
michael@0 12043 23674, 23693, 23696, 23702, 23688, {f: 2, c: 23704}, 23697, 23706, 23708,
michael@0 12044 23733, 23714, 23741, 23724, 23723, 23729, 23715, 23745, 23735, 23748,
michael@0 12045 23762, 23780, 23755, 23781, {f: 2, c: 23810}, 23847, 23846, 23854, 23844,
michael@0 12046 23838, 23814, 23835, 23896, 23870, 23860, 23869, 23916, 23899, 23919,
michael@0 12047 23901, 23915, 23883, 23882, 23913, 23924, 23938, 23961, 23965, 35955,
michael@0 12048 23991, 24005, [12091, 24435], 24439, 24450, 24455, 24457, 24460, 24469,
michael@0 12049 24473, 24476, 24488, 24493, 24501, 24508, 34914, [12090, 24417], 29357,
michael@0 12050 29360, 29364, {f: 2, c: 29367}, 29379, 29377, 29390, 29389, 29394, 29416,
michael@0 12051 29423, 29417, 29426, 29428, 29431, 29441, 29427, 29443, {f: 2, c: 29434},
michael@0 12052 29463, 29459, 29473, 29450, 29470, 29469, 29461, 29474, 29497, 29477,
michael@0 12053 29484, 29496, 29489, 29520, 29517, 29527, 29536, 29548, 29551, 29566,
michael@0 12054 [12167, 33307], 22821, 39143, 22820, [12065, 22786], 39267,
michael@0 12055 {f: 6, c: 39271}, 39284, 39287, 39293, 39296, 39300, 39303, 39306, 39309,
michael@0 12056 {f: 2, c: 39312}, {f: 3, c: 39315}, 24192, 24209, 24203, 24214, 24229,
michael@0 12057 24224, 24249, 24245, 24254, 24243, 36179, 24274, 24273, 24283, 24296,
michael@0 12058 24298, 33210, 24516, 24521, 24534, 24527, 24579, 24558, 24580, 24545,
michael@0 12059 24548, 24574, {f: 2, c: 24581}, 24554, 24557, 24568, 24601, 24629, 24614,
michael@0 12060 24603, 24591, 24589, 24617, 24619, 24586, 24639, 24609, {f: 2, c: 24696},
michael@0 12061 24699, 24698, 24642, 24682, 24701, 24726, 24730, 24749, 24733, 24707,
michael@0 12062 24722, 24716, 24731, 24812, 24763, 24753, 24797, 24792, 24774, 24794,
michael@0 12063 24756, 24864, 24870, 24853, 24867, 24820, 24832, 24846, 24875, 24906,
michael@0 12064 24949, 25004, 24980, 24999, 25015, 25044, 25077, 24541, 38579, 38377,
michael@0 12065 38379, 38385, 38387, {f: 2, c: 38389}, 38396, 38398, {f: 2, c: 38403},
michael@0 12066 38406, 38408, {f: 4, c: 38410}, 38415, 38418, {f: 3, c: 38421},
michael@0 12067 {f: 2, c: 38425}, 20012, [12121, 29247], 25109, 27701, 27732, 27740, 27722,
michael@0 12068 27811, 27781, 27792, 27796, 27788, {f: 2, c: 27752}, 27764, 27766, 27782,
michael@0 12069 27817, 27856, 27860, 27821, {f: 2, c: 27895}, 27889, 27863, 27826, 27872,
michael@0 12070 27862, 27898, 27883, 27886, 27825, 27859, 27887, 27902, 27961, 27943,
michael@0 12071 27916, 27971, 27976, 27911, 27908, 27929, 27918, 27947, 27981, 27950,
michael@0 12072 27957, 27930, 27983, 27986, 27988, 27955, 28049, 28015, 28062, 28064,
michael@0 12073 27998, {f: 2, c: 28051}, 27996, 28000, 28028, 28003, 28186, 28103, 28101,
michael@0 12074 28126, 28174, 28095, 28128, 28177, 28134, 28125, 28121, 28182, 28075,
michael@0 12075 28172, 28078, 28203, 28270, 28238, 28267, 28338, 28255, 28294,
michael@0 12076 {f: 2, c: 28243}, 28210, 28197, 28228, 28383, 28337, 28312, 28384, 28461,
michael@0 12077 28386, 28325, 28327, 28349, 28347, 28343, 28375, 28340, 28367, 28303,
michael@0 12078 28354, 28319, 28514, {f: 2, c: 28486}, 28452, 28437, 28409, 28463, 28470,
michael@0 12079 28491, 28532, 28458, 28425, 28457, 28553, 28557, 28556, 28536, 28530,
michael@0 12080 28540, 28538, 28625, 28617, 28583, 28601, 28598, 28610, 28641, 28654,
michael@0 12081 28638, 28640, 28655, 28698, 28707, 28699, 28729, 28725, 28751, 28766,
michael@0 12082 [12071, 23424], 23428, 23445, 23443, 23461, 23480, 29999, 39582, 25652,
michael@0 12083 23524, 23534, 35120, 23536, 36423, 35591, 36790, 36819, 36821, 36837,
michael@0 12084 36846, 36836, 36841, 36838, 36851, 36840, 36869, 36868, 36875, 36902,
michael@0 12085 36881, 36877, 36886, 36897, {f: 2, c: 36917}, 36909, 36911, 36932,
michael@0 12086 {f: 2, c: 36945}, 36944, 36968, 36952, 36962, 36955, 26297, 36980, 36989,
michael@0 12087 36994, 37000, 36995, 37003, [12089, 24400], 24407, 24406, 24408, 23611,
michael@0 12088 21675, 23632, 23641, 23409, 23651, 23654, 32700, 24362, 24361, 24365,
michael@0 12089 33396, 24380, 39739, [12076, 23662], 22913, 22915, 22925, {f: 2, c: 22953},
michael@0 12090 22947, 22935, 22986, 22955, 22942, 22948, 22994, 22962, 22959, 22999,
michael@0 12091 22974, {f: 2, c: 23045}, 23005, 23048, 23011, 23000, 23033, 23052, 23049,
michael@0 12092 23090, 23092, 23057, 23075, 23059, 23104, 23143, 23114, 23125, 23100,
michael@0 12093 23138, 23157, 33004, 23210, 23195, 23159, 23162, 23230, 23275, 23218,
michael@0 12094 23250, 23252, 23224, 23264, 23267, 23281, 23254, 23270, 23256, 23260,
michael@0 12095 23305, 23319, 23318, 23346, 23351, 23360, 23573, 23580, 23386, 23397,
michael@0 12096 23411, 23377, 23379, 23394, 39541, {f: 2, c: 39543}, 39546, 39551, 39549,
michael@0 12097 {f: 2, c: 39552}, 39557, 39560, 39562, 39568, {f: 2, c: 39570}, 39574,
michael@0 12098 39576, {f: 3, c: 39579}, {f: 2, c: 39583}, {f: 2, c: 39586}, 39589, 39591,
michael@0 12099 32415, 32417, 32419, 32421, {f: 2, c: 32424}, 32429, 32432, 32446,
michael@0 12100 {f: 3, c: 32448}, 32457, {f: 2, c: 32459}, 32464, 32468, 32471, 32475,
michael@0 12101 {f: 2, c: 32480}, 32488, 32491, {f: 2, c: 32494}, {f: 2, c: 32497}, 32525,
michael@0 12102 32502, {f: 2, c: 32506}, 32510, {f: 3, c: 32513}, {f: 2, c: 32519},
michael@0 12103 {f: 2, c: 32523}, 32527, {f: 2, c: 32529}, 32535, 32537, 32540, 32539,
michael@0 12104 32543, {f: 7, c: 32545}, {f: 4, c: 32554}, {f: 5, c: 32559}, 32565,
michael@0 12105 [12083, 24186], 30079, [12078, 24027], 30014, 37013, 29582, 29585, 29614,
michael@0 12106 29602, 29599, 29647, 29634, 29649, 29623, 29619, 29632, 29641, 29640,
michael@0 12107 29669, 29657, 39036, 29706, 29673, 29671, 29662, 29626, 29682, 29711,
michael@0 12108 29738, 29787, 29734, 29733, 29736, 29744, 29742, 29740, 29723, 29722,
michael@0 12109 29761, 29788, 29783, 29781, 29785, 29815, 29805, 29822, 29852, 29838,
michael@0 12110 {f: 2, c: 29824}, 29831, 29835, 29854, {f: 2, c: 29864}, 29840, 29863,
michael@0 12111 29906, 29882, {f: 3, c: 38890}, 26444, 26451, 26462, 26440, 26473, 26533,
michael@0 12112 26503, 26474, 26483, 26520, 26535, 26485, 26536, 26526, 26541, 26507,
michael@0 12113 26487, 26492, 26608, 26633, 26584, 26634, 26601, 26544, 26636, 26585,
michael@0 12114 26549, 26586, 26547, 26589, 26624, 26563, 26552, 26594, 26638, 26561,
michael@0 12115 26621, {f: 2, c: 26674}, {f: 2, c: 26720}, 26702, 26722, 26692, 26724,
michael@0 12116 26755, 26653, 26709, 26726, 26689, 26727, 26688, 26686, 26698, 26697,
michael@0 12117 26665, 26805, 26767, 26740, 26743, 26771, 26731, 26818, 26990, 26876,
michael@0 12118 {f: 2, c: 26911}, 26873, 26916, 26864, 26891, 26881, 26967, 26851, 26896,
michael@0 12119 26993, 26937, 26976, 26946, 26973, 27012, 26987, 27008, 27032, 27000,
michael@0 12120 26932, 27084, {f: 2, c: 27015}, 27086, 27017, 26982, 26979, 27001, 27035,
michael@0 12121 27047, 27067, 27051, 27053, 27092, 27057, 27073, 27082, 27103, 27029,
michael@0 12122 27104, 27021, 27135, 27183, 27117, {f: 2, c: 27159}, 27237, 27122, 27204,
michael@0 12123 27198, 27296, 27216, 27227, 27189, 27278, 27257, 27197, 27176, 27224,
michael@0 12124 27260, 27281, 27280, 27305, 27287, 27307, 29495, 29522, {f: 2, c: 27521},
michael@0 12125 27527, 27524, {f: 2, c: 27538}, 27533, {f: 2, c: 27546}, 27553, 27562,
michael@0 12126 36715, 36717, {f: 3, c: 36721}, {f: 2, c: 36725}, 36728, 36727,
michael@0 12127 {f: 2, c: 36729}, 36732, 36734, {f: 2, c: 36737}, 36740, 36743, 36747,
michael@0 12128 {f: 3, c: 36749}, 36760, 36762, 36558, 25099, 25111, 25115, 25119, 25122,
michael@0 12129 25121, 25125, 25124, 25132, 33255, 29935, 29940, 29951, 29967, 29969,
michael@0 12130 29971, [12097, 25908], {f: 3, c: 26094}, 26122, 26137, 26482, 26115, 26133,
michael@0 12131 26112, 28805, 26359, 26141, 26164, 26161, 26166, 26165, 32774, 26207,
michael@0 12132 26196, 26177, 26191, 26198, 26209, 26199, 26231, 26244, 26252, 26279,
michael@0 12133 26269, 26302, {f: 2, c: 26331}, 26342, 26345, {f: 2, c: 36146}, 36150,
michael@0 12134 36155, 36157, 36160, {f: 2, c: 36165}, {f: 2, c: 36168}, 36167, 36173,
michael@0 12135 36181, 36185, 35271, {f: 3, c: 35274}, {f: 4, c: 35278}, 29294, 29343,
michael@0 12136 29277, 29286, 29295, {f: 2, c: 29310}, 29316, 29323, 29325, 29327, 29330,
michael@0 12137 25352, 25394, 25520, 25663, 25816, 32772, 27626, 27635, 27645, 27637,
michael@0 12138 27641, 27653, 27655, 27654, 27661, 27669, {f: 3, c: 27672}, 27681, 27689,
michael@0 12139 27684, 27690, 27698, 25909, 25941, 25963, 29261, 29266, 29270, 29232,
michael@0 12140 34402, 21014, 32927, 32924, 32915, 32956, 26378, 32957, 32945, 32939,
michael@0 12141 32941, 32948, 32951, {f: 4, c: 32999}, 32987, 32962, 32964, 32985, 32973,
michael@0 12142 32983, 26384, 32989, 33003, 33009, 33012, 33005, {f: 2, c: 33037}, 33010,
michael@0 12143 33020, 26389, 33042, 35930, 33078, 33054, 33068, 33048, 33074, 33096,
michael@0 12144 33100, 33107, 33140, {f: 2, c: 33113}, 33137, 33120, 33129,
michael@0 12145 {f: 2, c: 33148}, 33133, 33127, 22605, 23221, 33160, 33154, 33169, 28373,
michael@0 12146 33187, 33194, 33228, 26406, 33226, 33211, 33217, 33190, 27428, 27447,
michael@0 12147 27449, 27459, 27462, 27481, {f: 3, c: 39121}, 39125, {f: 2, c: 39129},
michael@0 12148 [12110, 27571], 24384, 27586, 35315, 26000, 40785, 26003, 26044, 26054,
michael@0 12149 26052, 26051, 26060, 26062, 26066, 26070, 28800, 28828, 28822, 28829,
michael@0 12150 28859, 28864, 28855, 28843, 28849, 28904, 28874, 28944, 28947, 28950,
michael@0 12151 28975, 28977, 29043, 29020, 29032, 28997, 29042, 29002, 29048, 29050,
michael@0 12152 29080, 29107, 29109, 29096, 29088, 29152, 29140, 29159, 29177, 29213,
michael@0 12153 29224, 28780, 28952, 29030, 29113, 25150, 25149, 25155, {f: 2, c: 25160},
michael@0 12154 31035, 31040, 31046, 31049, {f: 2, c: 31067}, 31059, 31066, 31074, 31063,
michael@0 12155 31072, 31087, 31079, 31098, 31109, 31114, 31130, 31143, 31155, 24529,
michael@0 12156 24528, 24636, 24669, 24666, 24679, 24641, 24665, 24675, 24747, 24838,
michael@0 12157 24845, 24925, 25001, 24989, 25035, 25041, 25094, 32896, [12160, 32895],
michael@0 12158 27795, 27894, 28156, 30710, 30712, 30720, 30729, {f: 2, c: 30743}, 30737,
michael@0 12159 26027, 30765, {f: 2, c: 30748}, {f: 3, c: 30777}, 30751, 30780, 30757,
michael@0 12160 30764, 30755, 30761, 30798, 30829, {f: 2, c: 30806}, 30758, 30800, 30791,
michael@0 12161 30796, 30826, 30875, 30867, 30874, 30855, 30876, 30881, 30883, 30898,
michael@0 12162 30905, 30885, 30932, 30937, 30921, 30956, 30962, 30981, 30964, 30995,
michael@0 12163 31012, 31006, 31028, 40859, [12235, 40697], {f: 2, c: 40699}, 30449, 30468,
michael@0 12164 30477, 30457, {f: 2, c: 30471}, 30490, 30498, 30489, 30509, 30502, 30517,
michael@0 12165 30520, {f: 2, c: 30544}, 30535, 30531, 30554, 30568, 30562, 30565, 30591,
michael@0 12166 30605, 30589, 30592, 30604, 30609, {f: 2, c: 30623}, 30640, 30645, 30653,
michael@0 12167 30010, 30016, 30030, 30027, 30024, 30043, 30066, 30073, 30083, 32600,
michael@0 12168 32609, 32607, 35400, 32616, 32628, 32625, 32633, 32641, 32638, 30413,
michael@0 12169 30437, 34866, {f: 3, c: 38021}, 38027, 38026, {f: 2, c: 38028},
michael@0 12170 {f: 2, c: 38031}, 38036, 38039, 38037, {f: 3, c: 38042}, {f: 2, c: 38051},
michael@0 12171 38059, 38058, 38061, 38060, {f: 2, c: 38063}, 38066, 38068,
michael@0 12172 {f: 5, c: 38070}, {f: 2, c: 38076}, 38079, 38084, {f: 7, c: 38088},
michael@0 12173 {f: 3, c: 38096}, {f: 3, c: 38101}, 38105, 38104, 38107, {f: 3, c: 38110},
michael@0 12174 38114, {f: 2, c: 38116}, {f: 2, c: 38119}, 38122, 38121, 38123,
michael@0 12175 {f: 2, c: 38126}, {f: 3, c: 38131}, 38135, 38137, {f: 2, c: 38140}, 38143,
michael@0 12176 38147, 38146, {f: 2, c: 38150}, {f: 2, c: 38153}, {f: 3, c: 38157},
michael@0 12177 {f: 5, c: 38162}, 38168, 38171, {f: 3, c: 38173}, 38178, {f: 2, c: 38186},
michael@0 12178 38185, 38188, {f: 2, c: 38193}, 38196, {f: 3, c: 38198}, 38204,
michael@0 12179 {f: 2, c: 38206}, 38210, 38197, {f: 3, c: 38212}, 38217, 38220,
michael@0 12180 {f: 2, c: 38222}, {f: 3, c: 38226}, {f: 4, c: 38230}, 38235,
michael@0 12181 {f: 2, c: 38238}, 38237, {f: 2, c: 38241}, {f: 9, c: 38244}, 38255,
michael@0 12182 {f: 3, c: 38257}, 38202, 30695, 30700, 38601, 31189, 31213, 31203, 31211,
michael@0 12183 31238, 23879, 31235, 31234, 31262, 31252, 31289, 31287, 31313, 40655,
michael@0 12184 39333, 31344, 30344, 30350, 30355, 30361, 30372, 29918, 29920, 29996,
michael@0 12185 40480, 40482, {f: 5, c: 40488}, 40498, 40497, 40502, 40504, 40503,
michael@0 12186 {f: 2, c: 40505}, 40510, {f: 2, c: 40513}, 40516, {f: 4, c: 40518},
michael@0 12187 {f: 2, c: 40523}, 40526, 40529, 40533, 40535, {f: 3, c: 40538}, 40542,
michael@0 12188 40547, {f: 7, c: 40550}, 40561, 40557, 40563, [12135, 30098], 30100, 30102,
michael@0 12189 30112, 30109, 30124, 30115, {f: 2, c: 30131}, 30136, 30148, 30129, 30128,
michael@0 12190 30147, 30146, 30166, 30157, 30179, 30184, 30182, 30180, 30187, 30183,
michael@0 12191 30211, 30193, 30204, 30207, 30224, 30208, 30213, 30220, 30231, 30218,
michael@0 12192 30245, 30232, 30229, 30233, 30235, 30268, 30242, 30240, 30272, 30253,
michael@0 12193 30256, 30271, 30261, 30275, 30270, 30259, 30285, 30302, 30292, 30300,
michael@0 12194 30294, 30315, 30319, 32714, 31462, {f: 2, c: 31352}, 31360, 31366, 31368,
michael@0 12195 31381, 31398, 31392, 31404, 31400, 31405, 31411, 34916, 34921, 34930,
michael@0 12196 34941, 34943, 34946, 34978, 35014, 34999, 35004, 35017, 35042, 35022,
michael@0 12197 35043, 35045, 35057, 35098, 35068, 35048, 35070, 35056, 35105, 35097,
michael@0 12198 35091, 35099, 35082, 35124, 35115, 35126, 35137, 35174, 35195,
michael@0 12199 [12134, 30091], 32997, 30386, 30388, 30684, [12158, 32786], 32788, 32790,
michael@0 12200 32796, 32800, 32802, {f: 3, c: 32805}, 32809, 32808, 32817, 32779, 32821,
michael@0 12201 32835, 32838, 32845, 32850, 32873, 32881, 35203, 39032, 39040, 39043,
michael@0 12202 39049, {f: 2, c: 39052}, 39055, 39060, {f: 2, c: 39066}, {f: 2, c: 39070},
michael@0 12203 {f: 2, c: 39073}, {f: 2, c: 39077}, [12172, 34381], 34388, 34412, 34414,
michael@0 12204 34431, 34426, 34428, 34427, 34472, 34445, 34443, 34476, 34461, 34471,
michael@0 12205 34467, 34474, 34451, 34473, 34486, 34500, 34485, 34510, 34480, 34490,
michael@0 12206 34481, 34479, 34505, 34511, 34484, 34537, {f: 2, c: 34545}, 34541, 34547,
michael@0 12207 34512, 34579, 34526, 34548, 34527, 34520, 34513, 34563, 34567, 34552,
michael@0 12208 34568, 34570, 34573, 34569, 34595, 34619, 34590, 34597, 34606, 34586,
michael@0 12209 34622, 34632, 34612, 34609, 34601, 34615, 34623, 34690, 34594,
michael@0 12210 {f: 2, c: 34685}, 34683, 34656, 34672, 34636, 34670, 34699, 34643, 34659,
michael@0 12211 34684, 34660, 34649, 34661, 34707, 34735, 34728, 34770, 34758, 34696,
michael@0 12212 34693, 34733, 34711, 34691, 34731, 34789, 34732, 34741, 34739, 34763,
michael@0 12213 34771, 34749, 34769, 34752, 34762, 34779, 34794, 34784, 34798, 34838,
michael@0 12214 34835, 34814, 34826, 34843, 34849, 34873, 34876, [12152, 32566], 32578,
michael@0 12215 {f: 2, c: 32580}, 33296, 31482, 31485, 31496, {f: 2, c: 31491}, 31509,
michael@0 12216 31498, 31531, 31503, 31559, 31544, 31530, 31513, 31534, 31537, 31520,
michael@0 12217 31525, 31524, 31539, 31550, 31518, 31576, 31578, 31557, 31605, 31564,
michael@0 12218 31581, 31584, 31598, 31611, 31586, 31602, 31601, 31632, {f: 2, c: 31654},
michael@0 12219 31672, 31660, 31645, 31656, 31621, 31658, 31644, 31650, 31659, 31668,
michael@0 12220 31697, 31681, 31692, 31709, 31706, {f: 2, c: 31717}, 31722, 31756, 31742,
michael@0 12221 31740, 31759, 31766, 31755, 31775, 31786, 31782, 31800, 31809, 31808,
michael@0 12222 33278, {f: 2, c: 33281}, 33284, 33260, 34884, {f: 3, c: 33313}, 33325,
michael@0 12223 33327, 33320, 33323, 33336, 33339, {f: 2, c: 33331}, 33342, 33348, 33353,
michael@0 12224 33355, 33359, 33370, 33375, 33384, 34942, 34949, 34952, 35032, 35039,
michael@0 12225 35166, 32669, 32671, 32679, {f: 2, c: 32687}, 32690, 31868, 25929, 31889,
michael@0 12226 31901, 31900, 31902, 31906, 31922, {f: 2, c: 31932}, 31937, 31943,
michael@0 12227 {f: 2, c: 31948}, 31944, 31941, 31959, 31976, [12169, 33390], 26280, 32703,
michael@0 12228 32718, 32725, 32741, 32737, 32742, 32745, 32750, 32755, [12151, 31992],
michael@0 12229 32119, 32166, 32174, 32327, 32411, 40632, 40628, 36211, 36228, 36244,
michael@0 12230 36241, 36273, 36199, 36205, 35911, 35913, 37194, 37200, {f: 2, c: 37198},
michael@0 12231 37220, 37218, 37217, 37232, 37225, 37231, {f: 2, c: 37245}, 37234, 37236,
michael@0 12232 37241, 37260, 37253, 37264, 37261, 37265, {f: 2, c: 37282}, 37290,
michael@0 12233 {f: 3, c: 37293}, 37301, 37300, 37306, [12183, 35925], 40574, 36280, 36331,
michael@0 12234 36357, 36441, 36457, 36277, 36287, 36284, 36282, 36292, {f: 2, c: 36310},
michael@0 12235 36314, 36318, {f: 2, c: 36302}, 36315, 36294, 36332, {f: 2, c: 36343},
michael@0 12236 36323, 36345, 36347, 36324, 36361, 36349, 36372, 36381, 36383, 36396,
michael@0 12237 36398, 36387, 36399, 36410, 36416, 36409, 36405, 36413, 36401, 36425,
michael@0 12238 {f: 2, c: 36417}, {f: 2, c: 36433}, 36426, 36464, 36470, 36476, 36463,
michael@0 12239 36468, 36485, 36495, 36500, 36496, 36508, 36510, [12184, 35960], 35970,
michael@0 12240 35978, 35973, 35992, 35988, 26011, 35286, 35294, 35290, 35292, 35301,
michael@0 12241 35307, 35311, 35390, 35622, 38739, 38633, 38643, 38639, 38662, 38657,
michael@0 12242 38664, 38671, 38670, 38698, 38701, 38704, 38718, 40832, 40835,
michael@0 12243 {f: 6, c: 40837}, 40844, 40702, 40715, 40717, [12203, 38585],
michael@0 12244 {f: 2, c: 38588}, 38606, 38610, 30655, 38624, 37518, 37550, 37576, 37694,
michael@0 12245 37738, 37834, 37775, 37950, 37995, 40063, 40066, {f: 4, c: 40069}, 31267,
michael@0 12246 40075, 40078, {f: 3, c: 40080}, {f: 2, c: 40084}, {f: 2, c: 40090},
michael@0 12247 {f: 6, c: 40094}, {f: 5, c: 40101}, 40107, {f: 2, c: 40109},
michael@0 12248 {f: 8, c: 40112}, {f: 4, c: 40122}, {f: 4, c: 40132}, {f: 7, c: 40138},
michael@0 12249 {f: 3, c: 40147}, {f: 3, c: 40151}, {f: 2, c: 40156}, 40159, 40162, 38780,
michael@0 12250 38789, {f: 2, c: 38801}, 38804, 38831, 38827, 38819, 38834, 38836, 39601,
michael@0 12251 39600, 39607, 40536, 39606, 39610, 39612, 39617, 39616, 39621, 39618,
michael@0 12252 {f: 2, c: 39627}, 39633, 39749, 39747, 39751, 39753, 39752, 39757, 39761,
michael@0 12253 39144, 39181, 39214, 39253, 39252, [12221, 39647], 39649, 39654, 39663,
michael@0 12254 39659, 39675, 39661, 39673, 39688, 39695, 39699, 39711, 39715,
michael@0 12255 {f: 2, c: 40637}, 32315, 40578, {f: 2, c: 40583}, 40587, 40594, 37846,
michael@0 12256 40605, 40607, {f: 3, c: 40667}, 40672, 40671, 40674, 40681, 40679, 40677,
michael@0 12257 40682, 40687, 40738, 40748, 40751, 40761, 40759, {f: 2, c: 40765}, 40772,
michael@0 12258 12295, {s: 13}, 30362, 34297, 31001, 24859, 39599, 35158, 22761, 32631,
michael@0 12259 25850, 25943, 38930, 36774, 32070, 24171, 32129, 37770, 35607, 39165,
michael@0 12260 23542, 22577, 39825, 36649, [12185, 35997], 37575, 29437, 20633, 24970,
michael@0 12261 32179, 31558, 30050, 25987, 24163, 38281, 37002, 32232, 36022, 35722,
michael@0 12262 36783, 36782, 27161, 40009, 30303, 28693, 28657, 36051, 25839, 39173,
michael@0 12263 25765, 37474, 37457, 39361, 35036, 36001, 21443, 34870, 27544, 24922,
michael@0 12264 24920, 29158, 33980, 33369, 20489, 28356, 21408, 20596, 28204, 23652,
michael@0 12265 35435, 25881, 25723, 34796, 39262, 35730, 32399, 37855, 29987, 38369,
michael@0 12266 39019, 22580, 22039, [12199, 38263], 20767, 33144, 24288, 26274, 37396,
michael@0 12267 [12190, 36554], 24505, 22645, 38515, 35183, 31281, 25074, 35488, 39425,
michael@0 12268 36978, 39347, [12242, 40786], 29118, 34909, 34802, 23541, 30087, 36490,
michael@0 12269 31820, 32162, 37276, 37604, 38619, 30990, 20786, 35320, 34389, 20659,
michael@0 12270 30241, 38358, 21109, 37656, 32020, 32189, 36781, 35422, 36060, 32880,
michael@0 12271 24478, 21474, 36517, 31428, 37679, 36948, 24118, 36024, 25812, 21934,
michael@0 12272 37170, 25763, 33213, 24986, 35477, 24392, 30070, 25803, 40680, 34153,
michael@0 12273 27284, 25623, 23798, 31153, 23566, 29128, 37159, 25973, 28364, 36958,
michael@0 12274 32224, 39003, 40670, 22666, 38651, 28593, 37347, 35519, 35548, 37336,
michael@0 12275 38914, 37664, 35330, 26481, 21205, 26847, 20941, [12222, 39717], 29346,
michael@0 12276 29544, 35712, 36077, 37709, 37723, 26039, 32222, 38538, 23565, 22136,
michael@0 12277 38931, 37389, 22890, 22702, 40285, 38989, 35355, 24801, 39187, 20818,
michael@0 12278 29246, 39180, 36019, 30332, 32624, 38309, 31020, 37353, 29033, 31684,
michael@0 12279 36009, 39151, 35370, 32033, [12214, 39131], 35513, 24290, 36027, 32027,
michael@0 12280 22707, 22894, 24996, 31966, 35920, 26963, 37586, [12213, 39080], 30219,
michael@0 12281 39342, 32299, 35575, 40179, 33178, 36667, 25771, 36628, 36070, 24489,
michael@0 12282 36000, 35331, 23142, 32283, 35442, 37411, 33995, 24185, 36245, 36123,
michael@0 12283 23713, 21083, 37628, 32177, 23831, 37804, 25841, 40255, 38307, 37499,
michael@0 12284 20491, 32102, 40852, 38799, 36002, 37390, 28317, 27083, 36092, 34865,
michael@0 12285 39015, 21102, 38364, 35264, 39208, 24931, 36011, 24291, 35215, 27512,
michael@0 12286 [12244, 40860], 38312, 36556, 35437, 27331, 36020, 21130, 36645, 37707,
michael@0 12287 22283, 36942, 39405, 38867, 28450, 34399, 38305, 40372, 36032, 36703,
michael@0 12288 40251, 32005, 22778, 35703, 28396, 22057, 33775, 30059, 21123, 35441,
michael@0 12289 25079, 22750, 27489, 29872, 36996, 32233, 35594, 25582, 36637, 36036,
michael@0 12290 31330, 26371, 29172, 21295, 35569, 35496, 32362, 33911, 28222, 29554,
michael@0 12291 36008, 31117, 25802, 27231, 31309, 39249, 35663, 40388, 32318, 32221,
michael@0 12292 26997, 36655, 32026, 25824, 24190, 34186, 21137, 28639, 35336, 35352,
michael@0 12293 38555, 32380, 32000, 22846, 33698, 38960, 36040, 37440, 20729, 39381,
michael@0 12294 27570, 30435, 22533, 31627, 38291, 33393, 32216, 32365, 27298, 40572,
michael@0 12295 25536, 25791, 31777, 20745, 34214, 27323, 37970, 36368, 36068,
michael@0 12296 [12178, 35211], 37749, 33382, 21133, 39198, 28472, 28666, 28567, 23559,
michael@0 12297 28479, 34083, 27123, 22892, 35611, 37292, 33184, 28550, 39509, 23308,
michael@0 12298 25898, 37496, 30703, 20709, 39171, 32371, 32094, 36686, 36611, 38542,
michael@0 12299 31680, 28500, 32080, 35489, 32202, 37670, 20677, 35641, 36914, 29180,
michael@0 12300 30433, 21185, 33686, 39912, 39514, 32147, 38968, 37857, 24465, 30169,
michael@0 12301 31478, 31998, 33290, 39378, 33289, 25818, 37624, 25084, 21127, 40273,
michael@0 12302 32121, 35258, 35363, 32118, 37406, 36557, 39423, 38283, 20977, 38982,
michael@0 12303 27579, 35506, 22718, 25031, 25715, 24235, 35122, 35463, 22602, 20744,
michael@0 12304 23532, 31014, 26336, 34407, 24011, 31418, 39243, 28528, 25844, 38346,
michael@0 12305 34847, 33240, 33802, 20358, 36084, 34253, 27396, 25876, 31811, 38348,
michael@0 12306 34349, 28734, 35733, 25900, 35261, 25078, 32412, 29211, 28651, 25736,
michael@0 12307 21214, 28551, 27138, 37939, 22744, 39006, 31852, 38626, 28757, 35023,
michael@0 12308 39881, 31150, 40599, 21426, 21237, 31019, 27511, 28701, 38584, 20486,
michael@0 12309 32879, 34030, 36899, 37934, 24976, 28451, 31806, 25986, 33225, 37832,
michael@0 12310 25088, 29001, 32244, 31975, 20841, 36635, 35538, 30274, 36988, 37904,
michael@0 12311 29557, 33256, 37168, 40023, 36035, 40801, 37428, 38728, 23994, 38936,
michael@0 12312 39230, 21129, [12243, 40845], 32894, 22184, 31840, 22751, 25871, 38580,
michael@0 12313 27155, 23105, 25695, 31757, 34310, 30439, 39025, 24300, 29200, 25796,
michael@0 12314 28407, 34396, 39791, 36034, 37682, 38520, 39522, 37569, 23650, 32311,
michael@0 12315 24942, 28670, 32209, 24018, 25891, 23423, 28772, 20098, 25476, 36650,
michael@0 12316 20523, 20374, 28138, 32184, 35542, 34367, 32645, 37007, 38012, 31854,
michael@0 12317 39486, 39409, 32097, 23229, 29802, 30908, 34718, [12218, 39340], 39393,
michael@0 12318 21966, 36023, [12230, 40613], 36067, 36993, 30622, 39237, 34875, 28415,
michael@0 12319 35646, 37672, 37466, 36031, 37762, [12200, 38272], 24758, 20497, 37683,
michael@0 12320 22818, 35598, 24396, 35219, 32191, 32236, 24287, 28357, 25003, 38313,
michael@0 12321 40180, 37528, 35628, 35584, 30045, 37385, 32013, 38627, 25747, 33126,
michael@0 12322 24817, 39719, 39186, 25836, 33193, 25862, 37312, [12227, 40165], 32886,
michael@0 12323 22169, 38007, 37811, 27320, 29552, 23527, 25840, 28632, 37397, 32016,
michael@0 12324 33215, 28611, 36786, 30247, 35582, 27472, 40407, 27590, 22036, 28442,
michael@0 12325 30436, 40848, 36064, 22132, 40300, 39449, 39108, 38971, 36007, 34315,
michael@0 12326 24977, 35413, 28497, 38935, 25778, 37610, 20693, 27192, 35676, 33229,
michael@0 12327 [12241, 40778], 39438, 35912, 21843, 27683, 35350, 29309, 37370, 37467,
michael@0 12328 36983, 31805, 35609, 37666, 37463, 28154, 35700, 22649, 27085, 21958,
michael@0 12329 22715, 34196, 25654, 37740, 27211, 21932, 20689, 32761, 31429, 31434,
michael@0 12330 27453, 35242, 23522, 36629, 27691, 20670, 38915, 35531, 24950, 29898,
michael@0 12331 31406, 36264, 21312, 36544, 39493, 40818, 39028, 27402, 21240, 40306,
michael@0 12332 30906, 35731, 39250, 25854, 32350, 29105, 38860, 35469, 32009, 27054,
michael@0 12333 32104, 36575, 37613, 38287, 28516, 28753, 34217, 39955, 36093, 20632,
michael@0 12334 21930, 39479, 25475, 28544, 27578, 32023, 31721, 26348, 38275, 38493,
michael@0 12335 36109, 32341, 20663, 36062, 29138, 32057, 36050, 25448, 25885, 25086,
michael@0 12336 35373, 32051, 23529, 23352, 33102, 28402, 32882, 32361, 21213, 32854,
michael@0 12337 24107, 29509, 28629, 35433, 26178, 34645, 23526, 35672, 39387, 21218,
michael@0 12338 36969, 37323, 39166, 35222, 35430, 22781, 29560, 27166, 36664, 26360,
michael@0 12339 36118, 23660, 34899, 27193, 31466, 25976, 24101, 38617, 35504, 38918,
michael@0 12340 35500, 30889, 29197, 32114, 39164, 39686, 32883, 24939, 38924, 35359,
michael@0 12341 35494, 25851, 34311, 35380, 32901, 38614, 38568, 32143, 27506, 23403,
michael@0 12342 25613, 32302, 29795, 37782, 29562, 25787, 33274, 24907, 25892, 36010,
michael@0 12343 30321, 28760, 22727, 35674, 35527, 22022, 28271, 29145, 28644, 32295,
michael@0 12344 35342, 39472, 35588, 37563, 38988, 39636, 26781, 36028, 37941, 24307,
michael@0 12345 32893, 28916, 37509, 32113, 38957, 22294, 22615, 22296, 38973, 40213,
michael@0 12346 39345, 39389, 27234, 31402, 35178, 24398, 28771, 38929, 33836, 32178,
michael@0 12347 [12209, 38859], 36949, 22285, 29234, 28656, 32173, 33894, 20553, 20702,
michael@0 12348 32239, 35586, 34907, 32862, 32011, 31337, 21839, 25790, 34680, 28198,
michael@0 12349 31401, 21978, 37794, 28879, 35491, 28961, 34154, 22626, 38695, 21209,
michael@0 12350 35492, 37675, 29351, 35186, 32722, 37521, 25138, 32048, 34662, 36676,
michael@0 12351 23805, 20448, 29433, 22151, 37697, 39854, 32406, 36066, 37532, 38289,
michael@0 12352 39023, 38570, 29694, 29563, 32291, 39201, 25010, 32171, 38002, 37129,
michael@0 12353 35443, 38911, 38917, 34157, 22210, 37559, 26313, 22063, 21332, 25406,
michael@0 12354 33029, 35559, 23531, 28681, 35613, 37573, 37313, 33288, 37561, 32137,
michael@0 12355 38920, 35377, 32210, 32396, 36562, 25080, 36984, 30316, 32098, 23416,
michael@0 12356 21211, 35426, 23563, 39348, 35347, 35338, 36956, 22739, 40201, 40232,
michael@0 12357 21854, 20126, 35357, 38329, 40573, 22196, 38996, 38331, 33399, 21421,
michael@0 12358 30831, 35578, 39511, 40230, 26954, 25562, 30221, 38525, 30306, 39178,
michael@0 12359 27171, 22575, 35617, 34277, 29242, [12212, 38913], 26989, 33865, 37291,
michael@0 12360 37541, 38948, 36986, 20736, 34811, 34269, 20740, 25014, 32681, 35427,
michael@0 12361 35696, 35516, 35695, 32377, 34093, 38512, 37504, 39154, 38577, 27387,
michael@0 12362 23344, 40441, 25033, 32403, 29801, 34722, 29151, 29074, 34821, 36111,
michael@0 12363 31310, 21938, 25793, 20653, 30320, 36404, 20778, 24962, 37109, 37438,
michael@0 12364 29494, 35480, 36671, 39192, [12226, 39770], 28417, 33287, 23996, 35486,
michael@0 12365 39729, 29508, 35709, 38928, 39341, 40219, 28149, 36677, 22290, 21729,
michael@0 12366 22291, 32227, 36960, 39000, 32004, 36493, 38000, 38322, 38642, 37142,
michael@0 12367 38549, 36939, 34292, 37270, 26248, 38620, 36617, 25890, 26283, 36106,
michael@0 12368 36124, 33247, 38015, 26839, 31432, 36012, 25799, 21063, 28580, 36042,
michael@0 12369 36104, 36555, 37720, 38296, 35408, 40779, 20661, 27656, 30430, 26028,
michael@0 12370 36670, 23940, 26855, 25136, 32187, 24373, 28466, 24115, 36076, 33081,
michael@0 12371 36249, 34756, 36685, 37754, 36889, 35998, 37341, 20597, 35386, 37806,
michael@0 12372 38499, 24128, 30309, 37165, 35657, 32340, 32887, 22519, 34937, 32025,
michael@0 12373 25711, 25842, 24159, 36074, 28399, 37912, 32066, 31278, 33131, 34886,
michael@0 12374 35589, 36600, 30394, 26205, 39519, 35576, 35461, 29165, 30682, 22225,
michael@0 12375 36015, 37956, 31689, 39376, 23560, 30938, 36681, 36090, 27137, 33674,
michael@0 12376 35037, 22941, 22767, 29376, 37648, 36101, 22684, 32180, 35524, 28310,
michael@0 12377 28609, 36039, 28460, 32156, 32317, 32305, 37138, 35419, 32068, 38013,
michael@0 12378 21959, 21401, 21428, 38760, 36107, 21293, 21297, 36094, 21060, 21132,
michael@0 12379 21108, 20660, 20480, 20630, 20757, 20738, 20756, 20796, 20791, 20712,
michael@0 12380 20674, 20795, 20752, 20794, 20681, 31988, 40652, 22213, 40172, 35131,
michael@0 12381 33248, 35329, 35344, 35340, 35349, 35635, 35406, 35365, 35393, 35382,
michael@0 12382 35398, 35412, 35416, 35410, 35462, 35460, 35455, 35440, 35452, 35445,
michael@0 12383 35436, 35438, 35533, 35554, 35425, 35482, 35493, {f: 2, c: 35473}, 35535,
michael@0 12384 35537, 35529, 35547, 35543, 35522, 35510, 35574, 35563, 35604, 35585,
michael@0 12385 35556, 35565, 35580, 35571, 35558, 35566, 35550, 35624, 35740, 35606,
michael@0 12386 35610, 35600, 35627, 35629, 35670, 35673, 35662, 35742, 35691, 35734,
michael@0 12387 38488, 37178, 37140, 37172, 37087, 37174, 37126, 37192, 33467, 21233,
michael@0 12388 24048, 22538, 22745, 22754, 22752, 22746, 22497, 22607, 22550, 22610,
michael@0 12389 22557, 22628, 34188, 34131, 34294, 33703, 33799, 34031, 33511, 34338,
michael@0 12390 34086, 22603, 29026, 34136, 34045, 34126, 34184, 34234, 29334, 28366,
michael@0 12391 34113, 34254, 34130, 33984, 33874, 33892, 33940, 33845, 34207, 34133,
michael@0 12392 40367, 33939, 32264, 34118, 34146, 34078, 39488, 34362, 37795, 34167,
michael@0 12393 34334, 34298, 34308, 34282, 34330, 22889, 23607, 25451, 25718, 25759,
michael@0 12394 25681, 25692, 25779, 25860, 25878, 25847, 25852, 25883, 22064, 22072,
michael@0 12395 22216, 22182, 21764, 21692, 22144, 22109, 22112, 22069, 22006, 22118,
michael@0 12396 22130, 22156, 22117, 22044, 22062, 21993, 22038, 22208, 22029, 22195,
michael@0 12397 22209, 22127, 36705, 22198, 22165, 22279, 24131, 24172, 24152, 24151,
michael@0 12398 23943, 23796, 23888, 23852, 23975, 23968, 23959, 23821, 23992, 23937,
michael@0 12399 24020, 24480, 29559, 29505, 29546, 29499, 29547, 29568, 29564, 39136,
michael@0 12400 39219, 39145, 39228, {f: 2, c: 39146}, 39149, 39156, 39177, 39185, 39195,
michael@0 12401 39223, 39231, 39235, {f: 3, c: 39240}, 39244, 39266, 24289, 36065, 25082,
michael@0 12402 25006, 24938, 24894, 24757, 24884, 25036, 24927, 25064, 24827, 24887,
michael@0 12403 24818, 24947, 24860, 24978, 38274, 38278, 38344, 38286, 38292, 38284,
michael@0 12404 38373, 38317, 38315, 39726, 38316, 38334, 38326, 39721, 38335, 38333,
michael@0 12405 38332, 38339, 38347, 38356, 38352, 38357, 38366, 28739, 28505, 28711,
michael@0 12406 28696, 28668, 28039, 28025, 28254, 28590, 28687, 28408, 28527, 28150,
michael@0 12407 28543, 28678, 28576, 28683, 28775, 28740, 28677, 28535, 28704, 28703,
michael@0 12408 28722, 28712, 28765, 39467, 36999, 36885, 37008, 23656, 24371, 23285,
michael@0 12409 23255, 23296, 23149, 23304, 23372, 23207, 23291, 23307, 23329, 23338,
michael@0 12410 23321, 39380, 39391, 39385, 39478, 39515, 39377, 39384, 39501, 39498,
michael@0 12411 39394, 39530, 39439, 39437, 39429, 39490, 39469, 39446, 39489, 39470,
michael@0 12412 39480, {f: 2, c: 39491}, 39503, 39525, 39524, 31993, 32006, 32002,
michael@0 12413 {f: 2, c: 32007}, 32394, 32028, 32021, 32019, 32058, 32050, 32049, 32272,
michael@0 12414 32060, 32064, 32063, 32093, 32078, 32115, 32134, 32131, 32136, 32190,
michael@0 12415 32186, 32203, 32212, 32196, 32158, 32172, 32185, 32163, 32176, 32199,
michael@0 12416 32217, 32215, 32249, 32242, 32354, 32230, 32246, 32241, 32267, 32225,
michael@0 12417 32265, 32285, 32287, 32286, 32301, 32266, 32273, 32381, 32313, 32309,
michael@0 12418 32306, 32326, 32325, 32392, 32346, 32338, 32366, 32382, 32368, 32367,
michael@0 12419 32408, 29859, 29771, 29903, 38922, 29885, 29759, 29833, 29862, 29908,
michael@0 12420 29914, 38873, 38878, 38876, 27050, 27370, 26776, 26838, 27141, 26783,
michael@0 12421 27355, 27379, 27368, 27359, 27273, 26895, 27208, 26984, 27071, 27194,
michael@0 12422 27292, 27410, 27422, 27357, 27111, 27407, 27414, 27372, 27354, 27384,
michael@0 12423 27315, 27367, 27299, 27347, 27358, 27556, 27550, 27566, 27563, 27567,
michael@0 12424 36564, 36571, 36594, 36603, 36708, 36601, 36604, 36587, 36580, 36706,
michael@0 12425 36602, 36606, 36618, 36615, 36613, 36626, 36646, {f: 2, c: 36638}, 36636,
michael@0 12426 36659, 36678, 36692, 25108, 25127, 29964, 26311, 26308, 26249, 26326,
michael@0 12427 36033, 36016, 36026, 36029, 36100, 36018, 36037, 36112, 36049, 36058,
michael@0 12428 36053, 36075, 36071, 36091, 35224, 35244, 35233, 35263, 35238, 35247,
michael@0 12429 35250, 35255, 27647, 27660, 27692, 29272, 26407, 33110, 33242, 33051,
michael@0 12430 33214, 33121, 33231, 27487, {f: 2, c: 39086}, 39094, 39100, 39110, 39112,
michael@0 12431 36674, 40783, 26005, 29036, 29010, 29079, 29121, 29148, 29182, 31152,
michael@0 12432 31118, 31146, 25055, 24932, 25059, 25095, 28585, 30959, 30893, 30824,
michael@0 12433 30904, 31018, 31025, 30820, 30973, 30951, 30947, 40853, 30616, 30558,
michael@0 12434 30652, 32646, 32648, {f: 3, c: 37330}, 37337, 37335, 37333, 37367, 37351,
michael@0 12435 37348, 37702, 37365, 37369, 37384, 37414, 37445, 37393, 37392, 37377,
michael@0 12436 37415, 37380, 37413, 37376, 37434, 37478, 37431, 37427, 37461, 37437,
michael@0 12437 37432, 37470, {f: 2, c: 37484}, 37439, 37984, 37424, 37449, 37448, 37453,
michael@0 12438 37422, 37433, 37944, 37548, 37536, 37498, 37546, 37614, 37583, 37891,
michael@0 12439 37603, 37946, 37553, 37542, 37799, 37526, 37580, 37545, 37877, 37523,
michael@0 12440 37503, 37801, 37530, 37658, 37547, 37507, 37899, 37544, 37539, 37906,
michael@0 12441 37688, 37617, 37847, 37605, 37616, 37615, 37608, 37564, 37597, 37622,
michael@0 12442 {f: 2, c: 37926}, 37571, 37599, 37606, 37650, 37638, 37737, 37659, 37696,
michael@0 12443 37633, 37653, 37678, 37699, {f: 2, c: 37639}, 37663, 37657, 37733, 37703,
michael@0 12444 37750, 37716, 37732, 37802, 37744, 37764, 37860, 37848, 37928, 37767,
michael@0 12445 37836, 37784, 37816, 37823, 37798, 37808, 37813, 37964, 37858,
michael@0 12446 {f: 2, c: 37852}, 37837, 37854, 37827, 37831, 37841, 37908, 37917, 37879,
michael@0 12447 37989, 37907, 37997, 37920, 38009, 37881, 37913, 37962, 37938, 37951,
michael@0 12448 37972, 37987, 37758, 31329, 40169, 40182, 40199, 40198, 40227, 40327,
michael@0 12449 40469, 40221, 40223, 40421, 40239, 40409, 40240, 40258, 40478, 40275,
michael@0 12450 40477, 40288, 40274, 40435, 40284, 40289, 40339, 40298, 40303, 40329,
michael@0 12451 40344, 40346, 40384, 40357, 40361, 40386, 40380, 40474, 40403, 40410,
michael@0 12452 40431, 40422, 40434, 40440, 40460, 40442, 40475, 30308, 30296, 30311,
michael@0 12453 30210, {f: 2, c: 30278}, 30281, 30238, 30267, {f: 2, c: 30317}, 30313,
michael@0 12454 30322, 31431, 31414, 35168, 35123, 35165, 35143, 35128, 35172, 30392,
michael@0 12455 32814, 32812, 32889, 32885, 38919, {f: 2, c: 38926}, 38945, 38940, 28481,
michael@0 12456 38950, 38967, 38990, 38995, 39027, 39010, 39001, 39013, 39020, 39024,
michael@0 12457 34787, 34822, 34566, 34851, 34806, 34554, 34799, 34692, 34832, 34760,
michael@0 12458 34833, 34747, 34766, 32588, 31716, 31591, 31849, 31731, 31744, 31691,
michael@0 12459 31836, 31774, 31787, 31779, 31850, 31839, 33380, 33387, 35018, 32677,
michael@0 12460 31986, 31990, 31965, 32310, 40617, 36274, 37317, 37315, 40570, 36489,
michael@0 12461 36428, 36498, 36474, 36437, 36506, 36491, 36499, 36497, 36513, 36451,
michael@0 12462 36522, 36518, 35316, 35318, 38746, 38722, 38717, 38724, 40788, 40799,
michael@0 12463 40793, 40800, 40796, 40806, 40812, 40810, 40823, [12236, 40701], 40703,
michael@0 12464 40713, 35726, 38014, 37864, 39799, 39796, 39809, 39811, 39822, 40056,
michael@0 12465 31308, 39826, 40031, 39824, 39853, 39834, 39850, 39838, 40045, 39851,
michael@0 12466 39837, 40024, 39873, 40058, 39985, 39993, 39971, 39991, 39872, 39882,
michael@0 12467 39879, 39933, 39894, {f: 2, c: 39914}, 39905, 39908, 39911, 39901, 39906,
michael@0 12468 39920, 39899, 39924, 39892, 40029, 39944, 39952, 39949, 39954, 39945,
michael@0 12469 39935, 39968, 39986, 39981, 39976, 39973, 39977, 39987, 39998, 40008,
michael@0 12470 39995, 39989, 40005, 40022, 40020, 40018, 40039, 38851, 38845, 38857,
michael@0 12471 40379, 39631, 39638, 39637, 39768, 39758, 39255, 39260, 39714, 40695,
michael@0 12472 40690, 35180, 38342, 37686, 24390, 34068, 32404, 40803, 22137, 40725,
michael@0 12473 22081, 39662, 35079, 31296, 39091, 38308, 39693, 36852, 24409, 31339,
michael@0 12474 39138, 20642, 34193, 20760, 25458, 21067, 30543, 32397, 26310, 30637,
michael@0 12475 [12228, 40565], 22217, 40692, 28635, 25054, 30663, 28720, 40629, 34890,
michael@0 12476 38370, 38854, 31844, 32308, 38822, 40623, 22220, 39089, 27311, 32590,
michael@0 12477 31984, 20418, 32363, 40569, 22190, 39706, 33903, 31142, 31858, 39634,
michael@0 12478 38587, 32251, 35069, 30787, {f: 10, c: 8560}, {f: 2, c: 714}, 729, 8211,
michael@0 12479 8213, 8229, 8245, 8453, 8457, {f: 4, c: 8598}, 8725, 8735, 8739, 8786,
michael@0 12480 {f: 2, c: 8806}, 8895, {f: 36, c: 9552}, {f: 15, c: 9601}, {f: 3, c: 9619},
michael@0 12481 {f: 2, c: 9660}, {f: 4, c: 9698}, 9737, 8853, 12306, {f: 2, c: 12317},
michael@0 12482 {f: 9, c: 12321}, 12963, {f: 2, c: 13198}, {f: 3, c: 13212}, 13217, 13252,
michael@0 12483 13262, {f: 2, c: 13265}, 13269, 65072, 65506, 65508, 8481, 12849, 8208,
michael@0 12484 12540, {f: 2, c: 12443}, {f: 2, c: 12541}, 12294, {f: 2, c: 12445},
michael@0 12485 {f: 10, c: 65097}, {f: 4, c: 65108}, {f: 14, c: 65113}, {f: 4, c: 65128},
michael@0 12486 12350, {f: 12, c: 12272}, 19970, {f: 3, c: 19972}, 19983, 19986, 19991,
michael@0 12487 {f: 3, c: 19999}, 20003, 20006, 20009, {f: 2, c: 20014}, 20017, 20019,
michael@0 12488 20021, 20023, 20028, {f: 3, c: 20032}, 20036, 20038, 20042, 20049, 20053,
michael@0 12489 20055, {f: 2, c: 20058}, {f: 4, c: 20066}, {f: 2, c: 20071},
michael@0 12490 {f: 6, c: 20074}, 20082, {f: 10, c: 20084}, {f: 3, c: 20095},
michael@0 12491 {f: 2, c: 20099}, [12037, 20101], 20103, 20106, 20112, {f: 2, c: 20118},
michael@0 12492 20121, {f: 2, c: 20124}, 20131, 20138, {f: 3, c: 20143}, 20148,
michael@0 12493 {f: 4, c: 20150}, {f: 3, c: 20156}, 20168, 20172, {f: 2, c: 20175}, 20178,
michael@0 12494 {f: 3, c: 20186}, 20192, 20194, {f: 2, c: 20198}, 20201, {f: 3, c: 20205},
michael@0 12495 20209, 20212, {f: 3, c: 20216}, 20220, 20222, 20224, {f: 7, c: 20226},
michael@0 12496 {f: 2, c: 20235}, {f: 5, c: 20242}, {f: 2, c: 20252}, 20257, 20259,
michael@0 12497 {f: 2, c: 20264}, {f: 3, c: 20268}, 20273, 20275, 20277, 20279, 20281,
michael@0 12498 20283, {f: 5, c: 20286}, {f: 2, c: 20292}, {f: 6, c: 20295}, 20306, 20308,
michael@0 12499 20310, {f: 2, c: 20321}, 20326, 20328, {f: 2, c: 20330}, {f: 2, c: 20333},
michael@0 12500 {f: 2, c: 20337}, 20341, {f: 4, c: 20343}, 20349, {f: 3, c: 20352}, 20357,
michael@0 12501 20359, 20362, 20364, 20366, 20368, {f: 2, c: 20370}, 20373,
michael@0 12502 {f: 3, c: 20376}, 20380, {f: 2, c: 20382}, {f: 2, c: 20385}, 20388, 20395,
michael@0 12503 20397, {f: 5, c: 20400}, {f: 9, c: 20406}, {f: 2, c: 20416},
michael@0 12504 {f: 4, c: 20422}, {f: 3, c: 20427}, {f: 5, c: 20434}, 20441, 20443, 20450,
michael@0 12505 {f: 2, c: 20452}, 20455, {f: 2, c: 20459}, 20464, 20466, {f: 4, c: 20468},
michael@0 12506 20473, {f: 3, c: 20475}, 20479, {f: 5, c: 20481}, {f: 2, c: 20487}, 20490,
michael@0 12507 20494, 20496, 20499, {f: 3, c: 20501}, 20507, {f: 2, c: 20509}, 20512,
michael@0 12508 {f: 3, c: 20514}, 20519, {f: 11, c: 20527}, 20539, 20541, {f: 4, c: 20543},
michael@0 12509 {f: 3, c: 20548}, {f: 2, c: 20554}, 20557, {f: 5, c: 20560},
michael@0 12510 {f: 4, c: 20566}, 20571, {f: 8, c: 20573}, {f: 6, c: 20582},
michael@0 12511 {f: 7, c: 20589}, {f: 3, c: 20600}, {f: 2, c: 20604}, {f: 4, c: 20609},
michael@0 12512 {f: 2, c: 20614}, {f: 4, c: 20617}, {f: 8, c: 20622}, 20631,
michael@0 12513 {f: 8, c: 20634}, 20644, 20646, {f: 2, c: 20650}, {f: 4, c: 20654}, 20662,
michael@0 12514 {f: 2, c: 20664}, {f: 2, c: 20668}, {f: 3, c: 20671}, {f: 2, c: 20675},
michael@0 12515 {f: 3, c: 20678}, {f: 5, c: 20682}, 20688, {f: 3, c: 20690},
michael@0 12516 {f: 3, c: 20695}, {f: 3, c: 20699}, {f: 6, c: 20703}, {f: 3, c: 20713},
michael@0 12517 {f: 4, c: 20719}, 20724, {f: 3, c: 20726}, 20730, {f: 4, c: 20732}, 20737,
michael@0 12518 20739, 20741, 20746, {f: 4, c: 20748}, 20753, 20755, {f: 2, c: 20758},
michael@0 12519 {f: 6, c: 20761}, 20768, {f: 8, c: 20770}, {f: 7, c: 20779},
michael@0 12520 {f: 4, c: 20787}, {f: 2, c: 20792}, {f: 2, c: 20797}, 20802, 20807, 20810,
michael@0 12521 20812, {f: 3, c: 20814}, 20819, {f: 3, c: 20823}, 20827, {f: 5, c: 20829},
michael@0 12522 {f: 2, c: 20835}, {f: 2, c: 20838}, 20842, 20847, 20850, 20858,
michael@0 12523 {f: 2, c: 20862}, {f: 2, c: 20867}, {f: 2, c: 20870}, {f: 2, c: 20874},
michael@0 12524 {f: 4, c: 20878}, {f: 2, c: 20883}, 20888, 20890, {f: 3, c: 20893}, 20897,
michael@0 12525 20899, {f: 5, c: 20902}, {f: 2, c: 20909}, 20916, {f: 3, c: 20920},
michael@0 12526 {f: 2, c: 20926}, {f: 3, c: 20929}, 20933, 20936, 20938, 20942, 20944,
michael@0 12527 {f: 9, c: 20946}, 20956, {f: 2, c: 20958}, {f: 2, c: 20962},
michael@0 12528 {f: 6, c: 20965}, 20972, 20974, 20978, 20980, 20983, 20990,
michael@0 12529 {f: 2, c: 20996}, 21001, {f: 2, c: 21003}, {f: 2, c: 21007},
michael@0 12530 {f: 3, c: 21011}, 21020, {f: 2, c: 21022}, {f: 3, c: 21025},
michael@0 12531 {f: 3, c: 21029}, 21034, 21036, 21039, {f: 2, c: 21041}, {f: 2, c: 21044},
michael@0 12532 21052, 21054, {f: 2, c: 21061}, {f: 2, c: 21064}, {f: 2, c: 21070},
michael@0 12533 {f: 2, c: 21074}, 21077, {f: 4, c: 21079}, 21085, {f: 2, c: 21087},
michael@0 12534 {f: 3, c: 21090}, 21094, 21096, {f: 3, c: 21099}, {f: 2, c: 21104}, 21107,
michael@0 12535 {f: 7, c: 21110}, 21118, 21120, {f: 3, c: 21124}, 21131, {f: 2, c: 21134},
michael@0 12536 21138, {f: 7, c: 21140}, 21148, {f: 4, c: 21156}, {f: 3, c: 21166},
michael@0 12537 {f: 10, c: 21172}, 21184, 21186, {f: 3, c: 21188}, 21192, 21194,
michael@0 12538 {f: 4, c: 21196}, 21201, {f: 2, c: 21203}, 21207, 21210, 21212,
michael@0 12539 {f: 2, c: 21216}, 21219, {f: 11, c: 21221}, {f: 3, c: 21234},
michael@0 12540 {f: 2, c: 21238}, {f: 3, c: 21243}, {f: 4, c: 21249}, 21255,
michael@0 12541 {f: 4, c: 21257}, 21262, {f: 4, c: 21265}, 21272, {f: 2, c: 21275},
michael@0 12542 {f: 2, c: 21278}, 21282, {f: 2, c: 21284}, {f: 3, c: 21287},
michael@0 12543 {f: 2, c: 21291}, 21296, {f: 6, c: 21298}, [12054, 21304],
michael@0 12544 {f: 2, c: 21308}, 21314, 21316, 21318, {f: 3, c: 21323}, 21328,
michael@0 12545 {f: 2, c: 21336}, 21339, 21341, 21349, 21352, 21354, {f: 2, c: 21356},
michael@0 12546 21362, 21366, 21369, {f: 4, c: 21371}, {f: 2, c: 21376}, 21379,
michael@0 12547 {f: 2, c: 21383}, 21386, {f: 7, c: 21390}, {f: 2, c: 21398},
michael@0 12548 {f: 2, c: 21403}, 21406, 21409, 21412, 21415, {f: 3, c: 21418},
michael@0 12549 {f: 3, c: 21423}, 21427, 21429, {f: 4, c: 21431}, {f: 3, c: 21436}, 21440,
michael@0 12550 {f: 4, c: 21444}, {f: 3, c: 21454}, {f: 2, c: 21458}, 21461, 21466,
michael@0 12551 {f: 3, c: 21468}, 21473, 21479, 21492, 21498, {f: 3, c: 21502}, 21506,
michael@0 12552 21509, 21511, 21515, 21524, {f: 3, c: 21528}, 21532, 21538,
michael@0 12553 {f: 2, c: 21540}, 21546, 21552, 21555, {f: 2, c: 21558}, 21562, 21565,
michael@0 12554 21567, {f: 2, c: 21569}, {f: 2, c: 21572}, 21575, 21577, {f: 4, c: 21580},
michael@0 12555 21585, 21594, {f: 5, c: 21597}, 21603, 21605, 21607, {f: 8, c: 21609},
michael@0 12556 21620, {f: 2, c: 21625}, {f: 2, c: 21630}, 21633, 21635, 21637,
michael@0 12557 {f: 4, c: 21639}, 21645, 21649, 21651, {f: 2, c: 21655}, 21660,
michael@0 12558 {f: 5, c: 21662}, 21669, 21678, 21680, 21682, {f: 3, c: 21685},
michael@0 12559 {f: 2, c: 21689}, 21694, 21699, 21701, {f: 2, c: 21706}, 21718, 21720,
michael@0 12560 21723, 21728, {f: 3, c: 21730}, {f: 2, c: 21739}, {f: 3, c: 21743},
michael@0 12561 {f: 6, c: 21748}, 21755, 21758, 21760, {f: 2, c: 21762}, 21765, 21768,
michael@0 12562 {f: 5, c: 21770}, {f: 2, c: 21778}, {f: 6, c: 21781}, {f: 4, c: 21788},
michael@0 12563 21793, {f: 2, c: 21797}, {f: 2, c: 21800}, 21803, 21805, 21810,
michael@0 12564 {f: 3, c: 21812}, {f: 4, c: 21816}, 21821, 21824, 21826, 21829,
michael@0 12565 {f: 2, c: 21831}, {f: 4, c: 21835}, {f: 2, c: 21841}, 21844,
michael@0 12566 {f: 5, c: 21847}, 21853, {f: 2, c: 21855}, {f: 2, c: 21858},
michael@0 12567 {f: 2, c: 21864}, 21867, {f: 6, c: 21871}, {f: 2, c: 21881}, 21885, 21887,
michael@0 12568 {f: 2, c: 21893}, {f: 3, c: 21900}, 21904, {f: 2, c: 21906},
michael@0 12569 {f: 3, c: 21909}, {f: 2, c: 21914}, 21918, {f: 7, c: 21920},
michael@0 12570 {f: 2, c: 21928}, 21931, 21933, {f: 2, c: 21935}, 21940, 21942, 21944,
michael@0 12571 21946, 21948, {f: 5, c: 21951}, 21960, {f: 2, c: 21962}, {f: 2, c: 21967},
michael@0 12572 21973, {f: 3, c: 21975}, 21979, 21982, 21984, 21986, 21991,
michael@0 12573 {f: 2, c: 21997}, {f: 2, c: 22000}, 22004, {f: 5, c: 22008}, 22015,
michael@0 12574 {f: 4, c: 22018}, 22023, {f: 2, c: 22026}, {f: 4, c: 22032}, 22037,
michael@0 12575 {f: 2, c: 22041}, 22045, {f: 3, c: 22048}, {f: 2, c: 22053}, 22056,
michael@0 12576 {f: 2, c: 22058}, 22067, 22071, 22074, {f: 3, c: 22076}, 22080,
michael@0 12577 {f: 10, c: 22082}, {f: 5, c: 22095}, {f: 2, c: 22101}, {f: 2, c: 22106},
michael@0 12578 {f: 2, c: 22110}, 22113, 22115, 22119, {f: 2, c: 22125}, 22128, 22131,
michael@0 12579 22133, 22135, 22138, {f: 3, c: 22141}, {f: 4, c: 22145}, {f: 4, c: 22152},
michael@0 12580 22157, {f: 3, c: 22160}, 22164, {f: 3, c: 22166}, {f: 9, c: 22170},
michael@0 12581 {f: 2, c: 22180}, 22183, {f: 5, c: 22185}, {f: 3, c: 22192}, 22197,
michael@0 12582 {f: 4, c: 22200}, {f: 3, c: 22205}, {f: 2, c: 22211}, {f: 2, c: 22214},
michael@0 12583 22219, {f: 4, c: 22221}, {f: 2, c: 22226}, {f: 2, c: 22229},
michael@0 12584 {f: 2, c: 22232}, 22236, 22243, {f: 6, c: 22245}, 22252, {f: 2, c: 22254},
michael@0 12585 {f: 2, c: 22258}, {f: 3, c: 22262}, {f: 2, c: 22267}, {f: 3, c: 22272},
michael@0 12586 22277, 22284, {f: 4, c: 22286}, {f: 2, c: 22292}, 22295, {f: 3, c: 22297},
michael@0 12587 {f: 2, c: 22301}, {f: 3, c: 22304}, {f: 4, c: 22308}, 22315,
michael@0 12588 {f: 2, c: 22321}, {f: 5, c: 22324}, {f: 2, c: 22332}, 22335, 22337,
michael@0 12589 {f: 4, c: 22339}, {f: 2, c: 22344}, 22347, {f: 5, c: 22354},
michael@0 12590 {f: 2, c: 22360}, {f: 2, c: 22370}, 22373, 22375, 22380, 22382,
michael@0 12591 {f: 3, c: 22384}, {f: 2, c: 22388}, {f: 3, c: 22392}, {f: 5, c: 22397},
michael@0 12592 {f: 4, c: 22407}, {f: 5, c: 22413}, {f: 7, c: 22420}, {f: 4, c: 22428},
michael@0 12593 22437, 22440, 22442, 22444, {f: 3, c: 22447}, 22451, {f: 3, c: 22453},
michael@0 12594 {f: 9, c: 22457}, {f: 7, c: 22468}, {f: 2, c: 22476}, {f: 2, c: 22480},
michael@0 12595 22483, {f: 2, c: 22486}, {f: 2, c: 22491}, 22494, {f: 2, c: 22498},
michael@0 12596 {f: 8, c: 22501}, 22510, {f: 4, c: 22512}, {f: 2, c: 22517},
michael@0 12597 {f: 2, c: 22523}, {f: 2, c: 22526}, 22529, {f: 2, c: 22531},
michael@0 12598 {f: 2, c: 22536}, 22540, {f: 3, c: 22542}, {f: 3, c: 22546},
michael@0 12599 {f: 2, c: 22551}, {f: 3, c: 22554}, 22559, {f: 2, c: 22562},
michael@0 12600 {f: 5, c: 22565}, {f: 4, c: 22571}, {f: 2, c: 22578}, {f: 14, c: 22582},
michael@0 12601 {f: 5, c: 22597}, 22606, 22608, 22611, {f: 2, c: 22613}, {f: 5, c: 22617},
michael@0 12602 {f: 3, c: 22623}, 22627, {f: 5, c: 22630}, {f: 8, c: 22637},
michael@0 12603 {f: 3, c: 22646}, {f: 4, c: 22650}, 22655, 22658, 22660, {f: 3, c: 22662},
michael@0 12604 {f: 7, c: 22667}, {f: 5, c: 22676}, 22683, 22685, {f: 8, c: 22688},
michael@0 12605 {f: 4, c: 22698}, {f: 4, c: 22703}, {f: 7, c: 22708}, 22717,
michael@0 12606 {f: 2, c: 22719}, {f: 3, c: 22722}, 22726, {f: 9, c: 22728}, 22738, 22740,
michael@0 12607 {f: 2, c: 22742}, {f: 3, c: 22747}, 22753, 22755, {f: 4, c: 22757}, 22762,
michael@0 12608 22765, {f: 2, c: 22769}, {f: 2, c: 22772}, {f: 2, c: 22775},
michael@0 12609 {f: 2, c: 22779}, {f: 4, c: 22782}, 22787, {f: 2, c: 22789},
michael@0 12610 {f: 2, c: 22792}, [12066, 22794], {f: 2, c: 22795}, 22798,
michael@0 12611 {f: 4, c: 22800}, {f: 2, c: 22807}, 22811, {f: 2, c: 22813},
michael@0 12612 {f: 2, c: 22816}, 22819, 22822, 22824, 22828, 22832, {f: 2, c: 22834},
michael@0 12613 {f: 2, c: 22837}, 22843, 22845, {f: 2, c: 22847}, 22851, {f: 2, c: 22853},
michael@0 12614 22858, {f: 2, c: 22860}, 22864, {f: 2, c: 22866}, 22873, {f: 5, c: 22875},
michael@0 12615 22881, {f: 2, c: 22883}, {f: 3, c: 22886}, 22891, 22893, {f: 4, c: 22895},
michael@0 12616 22901, 22903, {f: 3, c: 22906}, {f: 3, c: 22910}, 22917, 22921,
michael@0 12617 {f: 2, c: 22923}, {f: 4, c: 22926}, {f: 2, c: 22932}, 22936,
michael@0 12618 {f: 3, c: 22938}, {f: 4, c: 22943}, {f: 2, c: 22950}, {f: 2, c: 22956},
michael@0 12619 {f: 2, c: 22960}, {f: 6, c: 22963}, 22970, {f: 2, c: 22972},
michael@0 12620 {f: 7, c: 22975}, {f: 3, c: 22983}, {f: 4, c: 22988}, {f: 2, c: 22997},
michael@0 12621 23001, 23003, {f: 5, c: 23006}, 23012, {f: 2, c: 23014}, {f: 3, c: 23017},
michael@0 12622 {f: 12, c: 23021}, 23034, {f: 3, c: 23036}, 23040, 23042, {f: 2, c: 23050},
michael@0 12623 {f: 4, c: 23053}, 23058, {f: 4, c: 23060}, {f: 3, c: 23065},
michael@0 12624 {f: 2, c: 23069}, {f: 2, c: 23073}, 23076, {f: 3, c: 23078},
michael@0 12625 {f: 7, c: 23082}, 23091, 23093, {f: 5, c: 23095}, {f: 3, c: 23101},
michael@0 12626 {f: 4, c: 23106}, {f: 2, c: 23111}, {f: 10, c: 23115}, {f: 4, c: 23126},
michael@0 12627 {f: 7, c: 23131}, {f: 3, c: 23139}, {f: 2, c: 23144}, {f: 2, c: 23147},
michael@0 12628 {f: 6, c: 23150}, {f: 2, c: 23160}, {f: 4, c: 23163}, {f: 18, c: 23168},
michael@0 12629 {f: 7, c: 23187}, {f: 11, c: 23196}, {f: 2, c: 23208}, {f: 7, c: 23211},
michael@0 12630 23220, {f: 2, c: 23222}, {f: 4, c: 23225}, {f: 2, c: 23231},
michael@0 12631 {f: 6, c: 23235}, {f: 2, c: 23242}, {f: 5, c: 23245}, 23251, 23253,
michael@0 12632 {f: 3, c: 23257}, {f: 3, c: 23261}, 23266, {f: 2, c: 23268},
michael@0 12633 {f: 2, c: 23271}, 23274, {f: 5, c: 23276}, {f: 3, c: 23282},
michael@0 12634 {f: 5, c: 23286}, {f: 4, c: 23292}, {f: 7, c: 23297}, 23306,
michael@0 12635 {f: 9, c: 23309}, 23320, {f: 7, c: 23322}, {f: 8, c: 23330},
michael@0 12636 {f: 5, c: 23339}, 23345, 23347, {f: 2, c: 23349}, {f: 7, c: 23353},
michael@0 12637 {f: 11, c: 23361}, {f: 3, c: 23373}, 23378, 23382, 23390, {f: 2, c: 23392},
michael@0 12638 {f: 2, c: 23399}, {f: 3, c: 23405}, 23410, 23412, {f: 2, c: 23414}, 23417,
michael@0 12639 {f: 2, c: 23419}, 23422, 23426, 23430, 23434, {f: 2, c: 23437},
michael@0 12640 {f: 3, c: 23440}, 23444, 23446, 23455, {f: 3, c: 23463}, {f: 4, c: 23468},
michael@0 12641 {f: 2, c: 23473}, 23479, {f: 3, c: 23482}, {f: 2, c: 23488}, 23491,
michael@0 12642 {f: 4, c: 23496}, {f: 3, c: 23501}, 23505, {f: 9, c: 23508}, 23520, 23523,
michael@0 12643 23530, 23533, 23535, {f: 4, c: 23537}, 23543, {f: 2, c: 23549}, 23552,
michael@0 12644 {f: 2, c: 23554}, 23557, 23564, 23568, {f: 2, c: 23570}, 23575, 23577,
michael@0 12645 23579, {f: 4, c: 23582}, 23587, 23590, {f: 4, c: 23592}, {f: 4, c: 23597},
michael@0 12646 {f: 2, c: 23602}, {f: 2, c: 23605}, {f: 2, c: 23619}, {f: 2, c: 23622},
michael@0 12647 {f: 2, c: 23628}, {f: 3, c: 23634}, {f: 3, c: 23638}, {f: 4, c: 23642},
michael@0 12648 23647, 23655, {f: 3, c: 23657}, 23661, 23664, {f: 7, c: 23666},
michael@0 12649 {f: 4, c: 23675}, 23680, {f: 5, c: 23683}, {f: 3, c: 23689},
michael@0 12650 {f: 2, c: 23694}, {f: 2, c: 23698}, 23701, {f: 4, c: 23709},
michael@0 12651 {f: 5, c: 23716}, 23722, {f: 3, c: 23726}, 23730, 23732, 23734,
michael@0 12652 {f: 4, c: 23737}, 23742, 23744, {f: 2, c: 23746}, {f: 6, c: 23749},
michael@0 12653 {f: 6, c: 23756}, {f: 6, c: 23763}, {f: 7, c: 23770}, {f: 2, c: 23778},
michael@0 12654 23783, 23785, {f: 2, c: 23787}, {f: 2, c: 23790}, {f: 3, c: 23793}, 23797,
michael@0 12655 {f: 4, c: 23799}, 23804, {f: 4, c: 23806}, {f: 2, c: 23812},
michael@0 12656 {f: 5, c: 23816}, {f: 5, c: 23823}, 23829, {f: 3, c: 23832},
michael@0 12657 {f: 2, c: 23836}, {f: 5, c: 23839}, 23845, 23848, {f: 2, c: 23850},
michael@0 12658 {f: 5, c: 23855}, {f: 8, c: 23861}, {f: 8, c: 23871}, {f: 2, c: 23880},
michael@0 12659 {f: 3, c: 23885}, {f: 7, c: 23889}, {f: 2, c: 23897}, 23900,
michael@0 12660 {f: 11, c: 23902}, 23914, {f: 2, c: 23917}, {f: 4, c: 23920},
michael@0 12661 {f: 12, c: 23925}, 23939, {f: 2, c: 23941}, {f: 15, c: 23944}, 23960,
michael@0 12662 {f: 3, c: 23962}, {f: 2, c: 23966}, {f: 6, c: 23969}, {f: 15, c: 23976},
michael@0 12663 23993, 23995, {f: 8, c: 23997}, {f: 5, c: 24006}, 24012, {f: 4, c: 24014},
michael@0 12664 24019, {f: 6, c: 24021}, 24028, {f: 2, c: 24031}, {f: 2, c: 24035}, 24042,
michael@0 12665 {f: 2, c: 24044}, {f: 2, c: 24053}, {f: 5, c: 24056}, {f: 2, c: 24063},
michael@0 12666 24068, 24071, {f: 3, c: 24073}, {f: 2, c: 24077}, {f: 2, c: 24082}, 24087,
michael@0 12667 {f: 7, c: 24094}, {f: 3, c: 24104}, 24108, {f: 2, c: 24111}, 24114,
michael@0 12668 {f: 2, c: 24116}, {f: 2, c: 24121}, {f: 2, c: 24126}, 24129,
michael@0 12669 {f: 6, c: 24134}, {f: 7, c: 24141}, 24150, {f: 2, c: 24153},
michael@0 12670 {f: 2, c: 24156}, 24160, {f: 7, c: 24164}, {f: 5, c: 24173}, 24181, 24183,
michael@0 12671 {f: 3, c: 24193}, 24197, {f: 2, c: 24200}, {f: 3, c: 24204}, 24210, 24216,
michael@0 12672 24219, 24221, {f: 4, c: 24225}, {f: 3, c: 24232}, 24236, {f: 5, c: 24238},
michael@0 12673 24244, {f: 4, c: 24250}, {f: 10, c: 24255}, {f: 6, c: 24267},
michael@0 12674 {f: 2, c: 24276}, {f: 4, c: 24279}, {f: 3, c: 24284}, {f: 4, c: 24292},
michael@0 12675 24297, 24299, {f: 6, c: 24301}, 24309, {f: 2, c: 24312}, {f: 3, c: 24315},
michael@0 12676 {f: 3, c: 24325}, 24329, {f: 3, c: 24332}, 24336, 24338, 24340, 24342,
michael@0 12677 {f: 2, c: 24345}, {f: 3, c: 24348}, {f: 4, c: 24353}, 24360,
michael@0 12678 {f: 2, c: 24363}, 24366, 24368, 24370, 24372, {f: 3, c: 24374}, 24379,
michael@0 12679 {f: 3, c: 24381}, {f: 5, c: 24385}, 24391, {f: 3, c: 24393}, 24397, 24399,
michael@0 12680 24401, 24404, {f: 3, c: 24410}, {f: 3, c: 24414}, 24419, 24421,
michael@0 12681 {f: 2, c: 24423}, 24427, {f: 2, c: 24430}, 24434, {f: 3, c: 24436}, 24440,
michael@0 12682 24442, {f: 3, c: 24445}, 24451, 24454, {f: 3, c: 24461}, {f: 2, c: 24467},
michael@0 12683 24470, {f: 2, c: 24474}, 24477, 24479, {f: 6, c: 24482}, {f: 2, c: 24491},
michael@0 12684 {f: 6, c: 24495}, 24502, 24504, {f: 2, c: 24506}, {f: 5, c: 24510},
michael@0 12685 {f: 2, c: 24519}, {f: 2, c: 24522}, 24526, {f: 3, c: 24531},
michael@0 12686 {f: 3, c: 24538}, {f: 2, c: 24542}, {f: 2, c: 24546}, {f: 2, c: 24549},
michael@0 12687 {f: 2, c: 24552}, 24556, {f: 2, c: 24559}, {f: 3, c: 24562},
michael@0 12688 {f: 2, c: 24566}, {f: 2, c: 24569}, 24572, {f: 3, c: 24583},
michael@0 12689 {f: 2, c: 24587}, {f: 2, c: 24592}, 24595, {f: 2, c: 24599}, 24602,
michael@0 12690 {f: 2, c: 24606}, {f: 3, c: 24610}, {f: 3, c: 24620}, {f: 5, c: 24624},
michael@0 12691 {f: 5, c: 24630}, {f: 2, c: 24637}, 24640, {f: 7, c: 24644}, 24652,
michael@0 12692 {f: 2, c: 24654}, 24657, {f: 2, c: 24659}, {f: 3, c: 24662},
michael@0 12693 {f: 2, c: 24667}, {f: 4, c: 24670}, {f: 2, c: 24677}, 24686,
michael@0 12694 {f: 2, c: 24689}, {f: 2, c: 24692}, 24695, 24702, {f: 3, c: 24704},
michael@0 12695 {f: 4, c: 24709}, {f: 2, c: 24714}, {f: 4, c: 24718}, 24723, 24725,
michael@0 12696 {f: 3, c: 24727}, 24732, 24734, {f: 2, c: 24737}, {f: 2, c: 24740}, 24743,
michael@0 12697 {f: 2, c: 24745}, 24750, 24752, 24755, 24759, {f: 2, c: 24761},
michael@0 12698 {f: 8, c: 24765}, {f: 3, c: 24775}, {f: 5, c: 24780}, {f: 3, c: 24786},
michael@0 12699 {f: 2, c: 24790}, 24793, 24795, 24798, {f: 4, c: 24802}, 24810, 24821,
michael@0 12700 {f: 2, c: 24823}, {f: 4, c: 24828}, {f: 4, c: 24834}, 24839,
michael@0 12701 {f: 3, c: 24842}, {f: 5, c: 24848}, {f: 4, c: 24854}, {f: 2, c: 24861},
michael@0 12702 {f: 2, c: 24865}, 24869, {f: 3, c: 24872}, {f: 8, c: 24876},
michael@0 12703 {f: 2, c: 24885}, {f: 6, c: 24888}, {f: 8, c: 24896}, 24905, 24909,
michael@0 12704 {f: 2, c: 24911}, {f: 3, c: 24914}, {f: 2, c: 24918}, 24921,
michael@0 12705 {f: 2, c: 24923}, 24926, {f: 2, c: 24928}, {f: 2, c: 24933}, 24937,
michael@0 12706 {f: 2, c: 24940}, 24943, {f: 2, c: 24945}, 24948, {f: 10, c: 24952},
michael@0 12707 {f: 7, c: 24963}, {f: 2, c: 24972}, 24975, 24979, {f: 5, c: 24981},
michael@0 12708 {f: 2, c: 24987}, {f: 6, c: 24990}, {f: 2, c: 24997}, 25002, 25005,
michael@0 12709 {f: 3, c: 25007}, {f: 3, c: 25011}, {f: 6, c: 25016}, {f: 3, c: 25023},
michael@0 12710 {f: 4, c: 25027}, {f: 4, c: 25037}, 25043, {f: 9, c: 25045},
michael@0 12711 {f: 3, c: 25056}, {f: 2, c: 25060}, 25063, {f: 9, c: 25065},
michael@0 12712 {f: 2, c: 25075}, 25081, 25083, 25085, {f: 5, c: 25089}, 25097, 25107,
michael@0 12713 25113, {f: 3, c: 25116}, 25120, 25123, 25126, {f: 2, c: 25128}, 25131,
michael@0 12714 25133, 25135, 25137, 25141, [12094, 25142], {f: 5, c: 25144}, 25154,
michael@0 12715 {f: 3, c: 25156}, 25162, {f: 2, c: 25167}, {f: 3, c: 25173},
michael@0 12716 {f: 2, c: 25177}, {f: 7, c: 25180}, {f: 2, c: 25188}, 25192,
michael@0 12717 {f: 2, c: 25201}, {f: 2, c: 25204}, {f: 2, c: 25207}, {f: 2, c: 25210},
michael@0 12718 25213, {f: 3, c: 25217}, {f: 4, c: 25221}, {f: 6, c: 25227}, 25236, 25241,
michael@0 12719 {f: 3, c: 25244}, 25251, {f: 2, c: 25254}, {f: 2, c: 25257},
michael@0 12720 {f: 4, c: 25261}, {f: 3, c: 25266}, {f: 3, c: 25270}, 25274, 25278,
michael@0 12721 {f: 2, c: 25280}, 25283, 25291, 25295, 25297, 25301, {f: 2, c: 25309},
michael@0 12722 {f: 2, c: 25312}, 25316, {f: 2, c: 25322}, 25328, 25330, 25333,
michael@0 12723 {f: 4, c: 25336}, 25344, {f: 4, c: 25347}, {f: 4, c: 25354},
michael@0 12724 {f: 2, c: 25359}, {f: 4, c: 25362}, {f: 3, c: 25367}, 25372,
michael@0 12725 {f: 2, c: 25382}, 25385, {f: 3, c: 25388}, {f: 2, c: 25392},
michael@0 12726 {f: 6, c: 25395}, {f: 2, c: 25403}, {f: 3, c: 25407}, 25412,
michael@0 12727 {f: 2, c: 25415}, 25418, {f: 4, c: 25425}, {f: 8, c: 25430}, 25440,
michael@0 12728 {f: 3, c: 25444}, 25450, 25452, {f: 2, c: 25455}, {f: 3, c: 25459},
michael@0 12729 {f: 2, c: 25464}, {f: 4, c: 25468}, 25473, {f: 2, c: 25477}, 25483, 25485,
michael@0 12730 25489, {f: 3, c: 25491}, 25495, {f: 7, c: 25497}, 25505, 25508, 25510,
michael@0 12731 25515, 25519, {f: 2, c: 25521}, {f: 2, c: 25525}, 25529, 25531, 25533,
michael@0 12732 25535, {f: 3, c: 25537}, 25541, {f: 2, c: 25543}, {f: 3, c: 25546}, 25553,
michael@0 12733 {f: 3, c: 25555}, {f: 3, c: 25559}, {f: 3, c: 25563}, 25567, 25570,
michael@0 12734 {f: 5, c: 25572}, {f: 2, c: 25579}, {f: 3, c: 25583}, 25587, 25589, 25591,
michael@0 12735 {f: 4, c: 25593}, 25598, {f: 2, c: 25603}, {f: 5, c: 25606}, 25614,
michael@0 12736 {f: 2, c: 25617}, {f: 2, c: 25621}, {f: 3, c: 25624}, 25629, 25631,
michael@0 12737 {f: 4, c: 25634}, {f: 3, c: 25639}, 25643, {f: 6, c: 25646}, 25653,
michael@0 12738 {f: 3, c: 25655}, {f: 2, c: 25659}, 25662, 25664, {f: 2, c: 25666}, 25673,
michael@0 12739 {f: 6, c: 25675}, 25683, {f: 3, c: 25685}, {f: 3, c: 25689}, 25693,
michael@0 12740 {f: 7, c: 25696}, 25704, {f: 3, c: 25706}, 25710, {f: 3, c: 25712},
michael@0 12741 {f: 2, c: 25716}, 25719, {f: 6, c: 25724}, 25731, 25734, {f: 8, c: 25737},
michael@0 12742 25748, {f: 2, c: 25751}, {f: 4, c: 25754}, {f: 3, c: 25760},
michael@0 12743 {f: 3, c: 25766}, 25770, 25775, 25777, 25780, 25782, 25785, 25789, 25795,
michael@0 12744 25798, {f: 2, c: 25800}, 25804, 25807, 25809, 25811, {f: 2, c: 25813},
michael@0 12745 25817, {f: 3, c: 25819}, 25823, 25825, 25827, 25829, {f: 5, c: 25831},
michael@0 12746 {f: 2, c: 25837}, 25843, {f: 2, c: 25845}, {f: 2, c: 25848}, 25853, 25855,
michael@0 12747 {f: 3, c: 25857}, 25861, {f: 2, c: 25863}, {f: 5, c: 25866},
michael@0 12748 {f: 2, c: 25872}, 25875, 25877, 25879, 25882, 25884, {f: 4, c: 25886},
michael@0 12749 {f: 4, c: 25894}, 25901, {f: 4, c: 25904}, 25911, 25914, {f: 2, c: 25916},
michael@0 12750 {f: 5, c: 25920}, {f: 2, c: 25926}, {f: 2, c: 25930}, {f: 2, c: 25933},
michael@0 12751 25936, {f: 3, c: 25938}, 25944, 25946, 25948, {f: 3, c: 25951},
michael@0 12752 {f: 2, c: 25956}, {f: 4, c: 25959}, {f: 3, c: 25965}, 25969, 25971, 25974,
michael@0 12753 {f: 9, c: 25977}, {f: 3, c: 25988}, {f: 3, c: 25992}, {f: 3, c: 25997},
michael@0 12754 26002, 26004, 26006, 26008, 26010, {f: 2, c: 26013}, 26016,
michael@0 12755 {f: 2, c: 26018}, 26022, 26024, 26026, 26030, {f: 6, c: 26033}, 26040,
michael@0 12756 {f: 2, c: 26042}, {f: 3, c: 26046}, 26050, {f: 4, c: 26055}, 26061,
michael@0 12757 {f: 2, c: 26064}, {f: 3, c: 26067}, {f: 8, c: 26072}, 26081,
michael@0 12758 {f: 2, c: 26083}, {f: 2, c: 26090}, {f: 4, c: 26098}, {f: 2, c: 26104},
michael@0 12759 {f: 5, c: 26107}, 26113, {f: 2, c: 26116}, {f: 3, c: 26119}, 26123, 26125,
michael@0 12760 {f: 3, c: 26128}, {f: 3, c: 26134}, {f: 3, c: 26138}, 26142,
michael@0 12761 {f: 4, c: 26145}, 26150, {f: 4, c: 26153}, 26158, 26160, {f: 2, c: 26162},
michael@0 12762 {f: 5, c: 26167}, 26173, {f: 2, c: 26175}, {f: 7, c: 26180},
michael@0 12763 {f: 2, c: 26189}, {f: 2, c: 26192}, {f: 2, c: 26200}, {f: 2, c: 26203},
michael@0 12764 26206, 26208, {f: 2, c: 26210}, 26213, 26215, {f: 5, c: 26217},
michael@0 12765 {f: 3, c: 26225}, 26229, {f: 2, c: 26232}, {f: 3, c: 26235},
michael@0 12766 {f: 3, c: 26239}, 26243, {f: 2, c: 26245}, {f: 2, c: 26250},
michael@0 12767 {f: 4, c: 26253}, {f: 4, c: 26258}, {f: 5, c: 26264}, {f: 4, c: 26270},
michael@0 12768 {f: 4, c: 26275}, {f: 2, c: 26281}, {f: 2, c: 26284}, {f: 5, c: 26287},
michael@0 12769 {f: 4, c: 26293}, {f: 4, c: 26298}, {f: 5, c: 26303}, 26309, 26312,
michael@0 12770 {f: 12, c: 26314}, {f: 2, c: 26327}, 26330, {f: 2, c: 26334},
michael@0 12771 {f: 5, c: 26337}, {f: 2, c: 26343}, {f: 2, c: 26346}, {f: 3, c: 26349},
michael@0 12772 26353, {f: 2, c: 26357}, {f: 2, c: 26362}, 26365, {f: 2, c: 26369},
michael@0 12773 {f: 4, c: 26372}, 26380, {f: 2, c: 26382}, {f: 3, c: 26385}, 26390,
michael@0 12774 {f: 3, c: 26392}, 26396, 26398, {f: 6, c: 26400}, 26409, 26414, 26416,
michael@0 12775 {f: 2, c: 26418}, {f: 4, c: 26422}, {f: 2, c: 26427}, {f: 2, c: 26430},
michael@0 12776 26433, {f: 2, c: 26436}, 26439, {f: 2, c: 26442}, 26445, 26450,
michael@0 12777 {f: 2, c: 26452}, {f: 5, c: 26455}, 26461, {f: 3, c: 26466},
michael@0 12778 {f: 2, c: 26470}, {f: 2, c: 26475}, 26478, 26484, 26486, {f: 4, c: 26488},
michael@0 12779 26493, 26496, {f: 2, c: 26498}, {f: 2, c: 26501}, 26504, 26506,
michael@0 12780 {f: 4, c: 26508}, {f: 4, c: 26513}, 26518, 26521, 26523, {f: 3, c: 26527},
michael@0 12781 26532, 26534, 26537, 26540, 26542, {f: 2, c: 26545}, 26548,
michael@0 12782 {f: 8, c: 26553}, 26562, {f: 10, c: 26565}, {f: 3, c: 26581}, 26587, 26591,
michael@0 12783 26593, {f: 2, c: 26595}, {f: 3, c: 26598}, {f: 2, c: 26602},
michael@0 12784 {f: 2, c: 26605}, 26610, {f: 8, c: 26613}, 26622, {f: 4, c: 26625}, 26630,
michael@0 12785 26637, 26640, 26642, {f: 2, c: 26644}, {f: 5, c: 26648}, {f: 3, c: 26654},
michael@0 12786 {f: 7, c: 26658}, {f: 7, c: 26667}, {f: 3, c: 26676}, {f: 2, c: 26682},
michael@0 12787 26687, 26695, 26699, 26701, 26703, 26706, {f: 10, c: 26710}, 26730,
michael@0 12788 {f: 8, c: 26732}, 26741, {f: 9, c: 26744}, 26754, 26756, {f: 8, c: 26759},
michael@0 12789 {f: 3, c: 26768}, {f: 3, c: 26772}, {f: 4, c: 26777}, 26782,
michael@0 12790 {f: 2, c: 26784}, {f: 3, c: 26787}, {f: 4, c: 26793}, 26798,
michael@0 12791 {f: 2, c: 26801}, 26804, {f: 10, c: 26806}, 26817, {f: 6, c: 26819}, 26826,
michael@0 12792 26828, {f: 4, c: 26830}, {f: 2, c: 26835}, 26841, {f: 4, c: 26843},
michael@0 12793 {f: 2, c: 26849}, {f: 3, c: 26852}, {f: 6, c: 26856}, 26863,
michael@0 12794 {f: 3, c: 26866}, {f: 3, c: 26870}, 26875, {f: 4, c: 26877},
michael@0 12795 {f: 3, c: 26882}, {f: 5, c: 26886}, 26892, 26897, {f: 12, c: 26899},
michael@0 12796 {f: 3, c: 26913}, {f: 8, c: 26917}, {f: 2, c: 26926}, {f: 3, c: 26929},
michael@0 12797 {f: 4, c: 26933}, {f: 3, c: 26938}, 26942, {f: 2, c: 26944},
michael@0 12798 {f: 7, c: 26947}, {f: 8, c: 26955}, {f: 2, c: 26965}, {f: 2, c: 26968},
michael@0 12799 {f: 2, c: 26971}, 26975, {f: 2, c: 26977}, {f: 2, c: 26980}, 26983,
michael@0 12800 {f: 2, c: 26985}, 26988, {f: 2, c: 26991}, {f: 3, c: 26994}, 26998,
michael@0 12801 {f: 2, c: 27002}, {f: 3, c: 27005}, 27009, 27011, 27013, {f: 3, c: 27018},
michael@0 12802 {f: 6, c: 27022}, {f: 2, c: 27030}, {f: 2, c: 27033}, {f: 10, c: 27037},
michael@0 12803 27049, 27052, {f: 2, c: 27055}, {f: 2, c: 27058}, {f: 2, c: 27061},
michael@0 12804 {f: 3, c: 27064}, {f: 3, c: 27068}, 27072, {f: 8, c: 27074}, 27087,
michael@0 12805 {f: 3, c: 27089}, {f: 6, c: 27093}, {f: 3, c: 27100}, {f: 6, c: 27105},
michael@0 12806 {f: 5, c: 27112}, {f: 4, c: 27118}, {f: 9, c: 27124}, 27134, 27136,
michael@0 12807 {f: 2, c: 27139}, {f: 4, c: 27142}, {f: 8, c: 27147}, {f: 3, c: 27156},
michael@0 12808 {f: 4, c: 27162}, 27168, 27170, {f: 4, c: 27172}, 27177, {f: 4, c: 27179},
michael@0 12809 27184, {f: 3, c: 27186}, {f: 2, c: 27190}, {f: 2, c: 27195},
michael@0 12810 {f: 5, c: 27199}, {f: 2, c: 27205}, {f: 2, c: 27209}, {f: 4, c: 27212},
michael@0 12811 {f: 7, c: 27217}, 27226, {f: 3, c: 27228}, 27232, {f: 2, c: 27235},
michael@0 12812 {f: 11, c: 27238}, {f: 7, c: 27250}, {f: 2, c: 27258}, {f: 3, c: 27261},
michael@0 12813 {f: 3, c: 27265}, {f: 4, c: 27269}, {f: 4, c: 27274}, 27279,
michael@0 12814 {f: 2, c: 27282}, {f: 2, c: 27285}, {f: 4, c: 27288}, {f: 3, c: 27293},
michael@0 12815 27297, {f: 5, c: 27300}, 27306, {f: 2, c: 27309}, {f: 3, c: 27312},
michael@0 12816 {f: 4, c: 27316}, {f: 2, c: 27321}, {f: 7, c: 27324}, {f: 15, c: 27332},
michael@0 12817 {f: 6, c: 27348}, 27356, {f: 7, c: 27360}, 27369, 27371, {f: 6, c: 27373},
michael@0 12818 {f: 4, c: 27380}, {f: 2, c: 27385}, {f: 8, c: 27388}, {f: 5, c: 27397},
michael@0 12819 {f: 4, c: 27403}, {f: 2, c: 27408}, {f: 3, c: 27411}, {f: 7, c: 27415},
michael@0 12820 27423, {f: 2, c: 27429}, {f: 10, c: 27432}, {f: 4, c: 27443}, 27448,
michael@0 12821 {f: 2, c: 27451}, {f: 4, c: 27455}, {f: 2, c: 27460}, 27464,
michael@0 12822 {f: 2, c: 27466}, {f: 3, c: 27469}, {f: 8, c: 27473}, {f: 5, c: 27482},
michael@0 12823 27488, {f: 2, c: 27496}, {f: 7, c: 27499}, {f: 4, c: 27507}, 27514,
michael@0 12824 {f: 4, c: 27517}, 27525, 27528, 27532, {f: 4, c: 27534}, {f: 2, c: 27540},
michael@0 12825 27543, 27545, {f: 2, c: 27548}, {f: 2, c: 27551}, {f: 2, c: 27554},
michael@0 12826 {f: 5, c: 27557}, {f: 2, c: 27564}, {f: 2, c: 27568}, 27574,
michael@0 12827 {f: 2, c: 27576}, {f: 3, c: 27580}, 27584, {f: 2, c: 27587},
michael@0 12828 {f: 4, c: 27591}, 27596, 27598, {f: 2, c: 27600}, 27608, 27610,
michael@0 12829 {f: 5, c: 27612}, {f: 8, c: 27618}, {f: 3, c: 27628}, {f: 3, c: 27632},
michael@0 12830 27636, {f: 3, c: 27638}, {f: 3, c: 27642}, 27646, {f: 5, c: 27648},
michael@0 12831 {f: 3, c: 27657}, 27662, 27666, 27671, {f: 3, c: 27676}, 27680, 27685,
michael@0 12832 27693, 27697, 27699, {f: 2, c: 27702}, {f: 4, c: 27705}, {f: 2, c: 27710},
michael@0 12833 {f: 3, c: 27715}, 27720, {f: 5, c: 27723}, {f: 3, c: 27729}, 27734,
michael@0 12834 {f: 3, c: 27736}, {f: 2, c: 27746}, {f: 3, c: 27749}, {f: 5, c: 27755},
michael@0 12835 27761, 27763, 27765, {f: 2, c: 27767}, {f: 3, c: 27770}, {f: 2, c: 27775},
michael@0 12836 27780, 27783, {f: 2, c: 27786}, {f: 2, c: 27789}, {f: 2, c: 27793},
michael@0 12837 {f: 4, c: 27797}, 27802, {f: 3, c: 27804}, 27808, 27810, 27816, 27820,
michael@0 12838 {f: 2, c: 27823}, {f: 4, c: 27828}, 27834, {f: 4, c: 27840},
michael@0 12839 {f: 3, c: 27846}, 27851, {f: 3, c: 27853}, {f: 2, c: 27857},
michael@0 12840 {f: 3, c: 27864}, {f: 2, c: 27868}, 27871, 27876, {f: 2, c: 27878}, 27881,
michael@0 12841 {f: 2, c: 27884}, 27890, 27892, 27897, {f: 2, c: 27903}, {f: 2, c: 27906},
michael@0 12842 {f: 2, c: 27909}, {f: 3, c: 27912}, 27917, {f: 3, c: 27919},
michael@0 12843 {f: 4, c: 27923}, 27928, {f: 2, c: 27932}, {f: 6, c: 27935}, 27942,
michael@0 12844 {f: 2, c: 27944}, {f: 2, c: 27948}, {f: 2, c: 27951}, 27956,
michael@0 12845 {f: 3, c: 27958}, 27962, {f: 2, c: 27967}, 27970, 27972, 27977, 27980,
michael@0 12846 27984, {f: 4, c: 27989}, 27995, 27997, 27999, {f: 2, c: 28001},
michael@0 12847 {f: 2, c: 28004}, {f: 2, c: 28007}, {f: 3, c: 28011}, {f: 4, c: 28016},
michael@0 12848 {f: 2, c: 28021}, {f: 2, c: 28026}, {f: 5, c: 28029}, {f: 2, c: 28035},
michael@0 12849 28038, {f: 2, c: 28042}, 28045, {f: 2, c: 28047}, 28050, {f: 5, c: 28054},
michael@0 12850 28060, 28066, 28069, {f: 2, c: 28076}, {f: 2, c: 28080}, {f: 2, c: 28083},
michael@0 12851 {f: 2, c: 28086}, {f: 6, c: 28089}, {f: 3, c: 28097}, {f: 3, c: 28104},
michael@0 12852 {f: 4, c: 28109}, {f: 4, c: 28114}, 28119, {f: 3, c: 28122}, 28127,
michael@0 12853 {f: 2, c: 28130}, 28133, {f: 3, c: 28135}, 28141, {f: 2, c: 28143}, 28146,
michael@0 12854 28148, 28152, {f: 8, c: 28157}, {f: 4, c: 28166}, 28171, 28175,
michael@0 12855 {f: 2, c: 28178}, 28181, {f: 2, c: 28184}, {f: 2, c: 28187},
michael@0 12856 {f: 2, c: 28190}, 28194, {f: 2, c: 28199}, 28202, 28206, {f: 2, c: 28208},
michael@0 12857 28211, {f: 3, c: 28213}, 28217, {f: 3, c: 28219}, {f: 4, c: 28223},
michael@0 12858 {f: 8, c: 28229}, {f: 4, c: 28239}, 28245, 28247, {f: 2, c: 28249},
michael@0 12859 {f: 2, c: 28252}, {f: 11, c: 28256}, {f: 2, c: 28268}, {f: 14, c: 28272},
michael@0 12860 {f: 3, c: 28288}, 28292, {f: 2, c: 28295}, {f: 5, c: 28298},
michael@0 12861 {f: 5, c: 28305}, 28311, {f: 3, c: 28313}, 28318, {f: 2, c: 28320},
michael@0 12862 {f: 2, c: 28323}, 28326, {f: 2, c: 28328}, {f: 4, c: 28331}, 28336, 28339,
michael@0 12863 28341, {f: 2, c: 28344}, 28348, {f: 3, c: 28350}, 28355, 28358,
michael@0 12864 {f: 3, c: 28360}, 28365, 28368, 28370, 28374, {f: 2, c: 28376},
michael@0 12865 {f: 3, c: 28379}, 28387, 28391, {f: 2, c: 28394}, {f: 2, c: 28397},
michael@0 12866 {f: 2, c: 28400}, 28403, {f: 2, c: 28405}, {f: 5, c: 28410}, 28416,
michael@0 12867 {f: 3, c: 28419}, {f: 2, c: 28423}, {f: 5, c: 28426}, {f: 3, c: 28432},
michael@0 12868 {f: 4, c: 28438}, {f: 5, c: 28443}, 28449, {f: 4, c: 28453}, 28462, 28464,
michael@0 12869 {f: 2, c: 28468}, 28471, {f: 5, c: 28473}, 28480, {f: 4, c: 28482},
michael@0 12870 {f: 3, c: 28488}, 28492, {f: 3, c: 28494}, {f: 2, c: 28498},
michael@0 12871 {f: 3, c: 28501}, {f: 2, c: 28506}, 28509, {f: 3, c: 28511}, 28515, 28517,
michael@0 12872 {f: 6, c: 28519}, 28529, 28531, {f: 2, c: 28533}, 28537, 28539,
michael@0 12873 {f: 2, c: 28541}, {f: 3, c: 28545}, 28549, {f: 2, c: 28554},
michael@0 12874 {f: 8, c: 28559}, {f: 4, c: 28568}, {f: 3, c: 28573}, {f: 2, c: 28578},
michael@0 12875 {f: 2, c: 28581}, 28584, {f: 4, c: 28586}, {f: 2, c: 28591}, 28594,
michael@0 12876 {f: 2, c: 28596}, {f: 2, c: 28599}, {f: 6, c: 28602}, {f: 5, c: 28612},
michael@0 12877 {f: 7, c: 28618}, {f: 2, c: 28627}, {f: 2, c: 28630}, {f: 2, c: 28633},
michael@0 12878 {f: 2, c: 28636}, {f: 2, c: 28642}, {f: 6, c: 28645}, {f: 2, c: 28652},
michael@0 12879 {f: 8, c: 28658}, 28667, 28669, {f: 6, c: 28671}, {f: 2, c: 28679}, 28682,
michael@0 12880 {f: 3, c: 28684}, 28688, {f: 3, c: 28690}, {f: 2, c: 28694}, 28697, 28700,
michael@0 12881 28702, {f: 2, c: 28705}, {f: 3, c: 28708}, {f: 7, c: 28713}, 28721,
michael@0 12882 {f: 2, c: 28723}, {f: 3, c: 28726}, {f: 4, c: 28730}, {f: 4, c: 28735},
michael@0 12883 {f: 7, c: 28741}, {f: 2, c: 28749}, 28752, {f: 3, c: 28754},
michael@0 12884 {f: 2, c: 28758}, {f: 4, c: 28761}, {f: 4, c: 28767}, {f: 2, c: 28773},
michael@0 12885 {f: 3, c: 28776}, 28782, {f: 4, c: 28785}, 28791, {f: 3, c: 28793}, 28797,
michael@0 12886 {f: 4, c: 28801}, {f: 3, c: 28806}, {f: 3, c: 28811}, {f: 3, c: 28815},
michael@0 12887 28819, {f: 2, c: 28823}, {f: 2, c: 28826}, {f: 13, c: 28830}, 28848, 28850,
michael@0 12888 {f: 3, c: 28852}, 28858, {f: 2, c: 28862}, {f: 4, c: 28868}, 28873,
michael@0 12889 {f: 4, c: 28875}, {f: 8, c: 28880}, 28890, {f: 3, c: 28892},
michael@0 12890 {f: 4, c: 28896}, 28901, 28906, 28910, {f: 4, c: 28912}, {f: 2, c: 28917},
michael@0 12891 28920, {f: 3, c: 28922}, {f: 11, c: 28926}, {f: 5, c: 28939},
michael@0 12892 {f: 2, c: 28945}, 28948, 28951, {f: 6, c: 28955}, {f: 4, c: 28962},
michael@0 12893 {f: 8, c: 28967}, {f: 4, c: 28978}, {f: 14, c: 28983}, {f: 3, c: 28998},
michael@0 12894 29003, 29005, {f: 3, c: 29007}, {f: 9, c: 29011}, 29021, {f: 3, c: 29023},
michael@0 12895 29027, 29029, {f: 2, c: 29034}, 29037, {f: 3, c: 29039}, {f: 4, c: 29044},
michael@0 12896 29049, {f: 2, c: 29051}, {f: 6, c: 29054}, {f: 5, c: 29061},
michael@0 12897 {f: 4, c: 29067}, {f: 2, c: 29072}, 29075, {f: 2, c: 29077},
michael@0 12898 {f: 5, c: 29082}, {f: 7, c: 29089}, {f: 3, c: 29097}, {f: 4, c: 29101},
michael@0 12899 29106, 29108, {f: 3, c: 29110}, {f: 4, c: 29114}, {f: 2, c: 29119}, 29122,
michael@0 12900 {f: 4, c: 29124}, {f: 5, c: 29129}, {f: 3, c: 29135}, 29139,
michael@0 12901 {f: 3, c: 29142}, {f: 2, c: 29146}, {f: 2, c: 29149}, {f: 4, c: 29153},
michael@0 12902 {f: 5, c: 29160}, {f: 5, c: 29167}, {f: 4, c: 29173}, {f: 2, c: 29178},
michael@0 12903 29181, {f: 7, c: 29183}, {f: 6, c: 29191}, {f: 2, c: 29198},
michael@0 12904 {f: 10, c: 29201}, 29212, {f: 10, c: 29214}, 29225, 29227,
michael@0 12905 {f: 3, c: 29229}, {f: 2, c: 29235}, 29244, {f: 7, c: 29248},
michael@0 12906 {f: 3, c: 29257}, {f: 4, c: 29262}, {f: 3, c: 29267}, 29271, 29274, 29276,
michael@0 12907 29278, 29280, {f: 3, c: 29283}, 29288, {f: 4, c: 29290}, {f: 2, c: 29296},
michael@0 12908 {f: 2, c: 29299}, {f: 3, c: 29302}, {f: 2, c: 29307}, {f: 2, c: 29314},
michael@0 12909 {f: 5, c: 29317}, 29324, 29326, {f: 2, c: 29328}, {f: 3, c: 29331},
michael@0 12910 {f: 8, c: 29335}, {f: 2, c: 29344}, {f: 4, c: 29347}, {f: 4, c: 29352},
michael@0 12911 29358, {f: 3, c: 29361}, 29365, {f: 6, c: 29370}, {f: 3, c: 29381},
michael@0 12912 {f: 4, c: 29385}, 29391, 29393, {f: 4, c: 29395}, 29400, {f: 4, c: 29402},
michael@0 12913 29407, {f: 6, c: 29410}, {f: 2, c: 29418}, {f: 2, c: 29429},
michael@0 12914 {f: 3, c: 29438}, 29442, {f: 6, c: 29444}, {f: 3, c: 29451},
michael@0 12915 {f: 4, c: 29455}, 29460, {f: 3, c: 29464}, {f: 2, c: 29471},
michael@0 12916 {f: 2, c: 29475}, {f: 3, c: 29478}, 29485, {f: 2, c: 29487},
michael@0 12917 {f: 2, c: 29490}, 29493, 29498, {f: 2, c: 29500}, 29504, {f: 2, c: 29506},
michael@0 12918 {f: 7, c: 29510}, {f: 2, c: 29518}, 29521, {f: 4, c: 29523},
michael@0 12919 {f: 8, c: 29528}, {f: 7, c: 29537}, 29545, 29550, 29553, {f: 2, c: 29555},
michael@0 12920 29558, 29561, 29565, 29567, {f: 3, c: 29569}, {f: 2, c: 29573}, 29576,
michael@0 12921 29578, {f: 2, c: 29580}, {f: 2, c: 29583}, {f: 4, c: 29586},
michael@0 12922 {f: 4, c: 29591}, {f: 3, c: 29596}, {f: 2, c: 29600}, {f: 6, c: 29603},
michael@0 12923 29610, {f: 2, c: 29612}, 29617, {f: 3, c: 29620}, {f: 2, c: 29624},
michael@0 12924 {f: 4, c: 29628}, 29633, {f: 5, c: 29635}, {f: 2, c: 29643}, 29646,
michael@0 12925 {f: 7, c: 29650}, {f: 4, c: 29658}, 29663, {f: 4, c: 29665}, 29670, 29672,
michael@0 12926 {f: 3, c: 29674}, {f: 4, c: 29678}, {f: 11, c: 29683}, {f: 4, c: 29695},
michael@0 12927 29700, {f: 2, c: 29703}, {f: 4, c: 29707}, {f: 9, c: 29713},
michael@0 12928 {f: 6, c: 29724}, {f: 2, c: 29731}, 29735, 29737, 29739, 29741, 29743,
michael@0 12929 {f: 2, c: 29745}, {f: 5, c: 29751}, {f: 2, c: 29757}, 29760,
michael@0 12930 {f: 9, c: 29762}, {f: 9, c: 29772}, 29782, 29784, 29789, {f: 3, c: 29792},
michael@0 12931 {f: 5, c: 29796}, {f: 2, c: 29803}, {f: 2, c: 29806}, {f: 5, c: 29809},
michael@0 12932 {f: 6, c: 29816}, 29823, 29826, {f: 3, c: 29828}, 29832, 29834,
michael@0 12933 {f: 2, c: 29836}, 29839, {f: 11, c: 29841}, 29853, {f: 4, c: 29855},
michael@0 12934 {f: 2, c: 29860}, {f: 6, c: 29866}, {f: 9, c: 29873}, {f: 2, c: 29883},
michael@0 12935 {f: 12, c: 29886}, {f: 4, c: 29899}, {f: 2, c: 29904}, 29907,
michael@0 12936 {f: 5, c: 29909}, 29915, 29917, 29919, 29921, 29925, {f: 7, c: 29927},
michael@0 12937 {f: 4, c: 29936}, 29941, {f: 7, c: 29944}, {f: 4, c: 29952},
michael@0 12938 {f: 7, c: 29957}, 29966, 29968, 29970, {f: 4, c: 29972}, 29979,
michael@0 12939 {f: 2, c: 29981}, {f: 3, c: 29984}, 29988, {f: 2, c: 29990}, 29994, 29998,
michael@0 12940 30004, 30006, 30009, {f: 2, c: 30012}, 30015, {f: 4, c: 30017},
michael@0 12941 {f: 2, c: 30022}, {f: 2, c: 30025}, 30029, {f: 4, c: 30032},
michael@0 12942 {f: 4, c: 30037}, {f: 4, c: 30046}, {f: 2, c: 30051}, {f: 3, c: 30055},
michael@0 12943 {f: 6, c: 30060}, 30067, 30069, 30071, {f: 5, c: 30074}, {f: 3, c: 30080},
michael@0 12944 {f: 2, c: 30084}, {f: 3, c: 30088}, {f: 3, c: 30092}, 30096, 30099, 30101,
michael@0 12945 30104, {f: 2, c: 30107}, 30110, 30114, {f: 5, c: 30118}, 30125,
michael@0 12946 {f: 2, c: 30134}, {f: 2, c: 30138}, {f: 3, c: 30143}, 30150,
michael@0 12947 {f: 2, c: 30155}, {f: 4, c: 30158}, 30163, 30167, 30170, {f: 2, c: 30172},
michael@0 12948 {f: 3, c: 30175}, 30181, 30185, {f: 4, c: 30188}, {f: 2, c: 30194},
michael@0 12949 {f: 4, c: 30197}, {f: 2, c: 30202}, {f: 2, c: 30205}, 30212,
michael@0 12950 {f: 4, c: 30214}, {f: 2, c: 30222}, {f: 4, c: 30225}, 30230, 30234,
michael@0 12951 {f: 2, c: 30236}, 30243, 30248, 30252, {f: 2, c: 30254}, {f: 2, c: 30257},
michael@0 12952 {f: 2, c: 30262}, {f: 2, c: 30265}, 30269, 30273, {f: 2, c: 30276}, 30280,
michael@0 12953 {f: 2, c: 30282}, {f: 6, c: 30286}, 30293, 30295, {f: 3, c: 30297}, 30301,
michael@0 12954 {f: 2, c: 30304}, 30310, 30312, 30314, {f: 3, c: 30323}, [12136, 30326],
michael@0 12955 30327, {f: 2, c: 30329}, {f: 3, c: 30335}, 30339, 30341, {f: 2, c: 30345},
michael@0 12956 {f: 2, c: 30348}, {f: 2, c: 30351}, 30354, {f: 2, c: 30356},
michael@0 12957 {f: 2, c: 30359}, {f: 9, c: 30363}, {f: 9, c: 30373}, {f: 2, c: 30383},
michael@0 12958 30387, {f: 3, c: 30389}, 30393, {f: 4, c: 30395}, {f: 2, c: 30400},
michael@0 12959 {f: 2, c: 30403}, 30407, 30409, {f: 2, c: 30411}, 30419, 30421,
michael@0 12960 {f: 2, c: 30425}, {f: 2, c: 30428}, 30432, 30434, 30438, {f: 6, c: 30440},
michael@0 12961 30448, 30451, {f: 3, c: 30453}, {f: 2, c: 30458}, 30461, {f: 2, c: 30463},
michael@0 12962 {f: 2, c: 30466}, {f: 2, c: 30469}, 30474, 30476, {f: 11, c: 30478},
michael@0 12963 {f: 4, c: 30491}, 30497, {f: 3, c: 30499}, 30503, {f: 3, c: 30506}, 30510,
michael@0 12964 {f: 5, c: 30512}, 30521, 30523, {f: 3, c: 30525}, 30530, {f: 3, c: 30532},
michael@0 12965 {f: 7, c: 30536}, {f: 8, c: 30546}, {f: 2, c: 30556}, {f: 2, c: 30559},
michael@0 12966 30564, 30567, {f: 2, c: 30569}, {f: 12, c: 30573}, {f: 3, c: 30586},
michael@0 12967 {f: 3, c: 30593}, {f: 6, c: 30598}, {f: 2, c: 30607}, {f: 5, c: 30611},
michael@0 12968 {f: 5, c: 30617}, 30625, {f: 2, c: 30627}, 30630, 30632, 30635,
michael@0 12969 {f: 2, c: 30638}, {f: 2, c: 30641}, 30644, {f: 5, c: 30646}, 30654,
michael@0 12970 {f: 7, c: 30656}, {f: 5, c: 30664}, {f: 9, c: 30670}, {f: 2, c: 30680},
michael@0 12971 {f: 5, c: 30685}, 30692, 30694, 30696, 30698, {f: 3, c: 30704},
michael@0 12972 {f: 2, c: 30708}, 30711, {f: 4, c: 30713}, {f: 6, c: 30723},
michael@0 12973 {f: 2, c: 30730}, {f: 3, c: 30734}, 30739, 30741, 30745, 30747, 30750,
michael@0 12974 {f: 3, c: 30752}, 30756, 30760, {f: 2, c: 30762}, {f: 2, c: 30766},
michael@0 12975 {f: 3, c: 30769}, {f: 2, c: 30773}, 30781, 30783, {f: 2, c: 30785}, 30788,
michael@0 12976 30790, {f: 4, c: 30792}, 30797, 30799, 30801, {f: 2, c: 30803},
michael@0 12977 {f: 5, c: 30808}, {f: 6, c: 30814}, {f: 3, c: 30821}, 30825,
michael@0 12978 {f: 7, c: 30832}, {f: 4, c: 30840}, {f: 10, c: 30845}, 30856,
michael@0 12979 {f: 2, c: 30858}, {f: 2, c: 30863}, 30866, {f: 3, c: 30868}, 30873,
michael@0 12980 {f: 2, c: 30877}, 30880, 30882, 30884, 30886, 30888, {f: 3, c: 30890},
michael@0 12981 {f: 2, c: 30894}, {f: 3, c: 30901}, 30907, 30909, {f: 2, c: 30911},
michael@0 12982 {f: 3, c: 30914}, {f: 3, c: 30918}, {f: 4, c: 30924}, {f: 3, c: 30929},
michael@0 12983 {f: 3, c: 30934}, {f: 8, c: 30939}, {f: 3, c: 30948}, {f: 3, c: 30953},
michael@0 12984 {f: 2, c: 30957}, {f: 2, c: 30960}, 30963, {f: 2, c: 30965},
michael@0 12985 {f: 2, c: 30968}, {f: 2, c: 30971}, {f: 3, c: 30974}, {f: 3, c: 30978},
michael@0 12986 {f: 8, c: 30982}, {f: 4, c: 30991}, {f: 5, c: 30996}, {f: 4, c: 31002},
michael@0 12987 {f: 5, c: 31007}, 31013, {f: 3, c: 31015}, {f: 4, c: 31021},
michael@0 12988 {f: 2, c: 31026}, {f: 5, c: 31029}, 31037, 31039, {f: 4, c: 31042}, 31047,
michael@0 12989 {f: 9, c: 31050}, {f: 2, c: 31060}, {f: 2, c: 31064}, 31073,
michael@0 12990 {f: 2, c: 31075}, 31078, {f: 4, c: 31081}, 31086, {f: 7, c: 31088}, 31097,
michael@0 12991 {f: 5, c: 31099}, {f: 2, c: 31106}, {f: 4, c: 31110}, {f: 2, c: 31115},
michael@0 12992 {f: 10, c: 31120}, {f: 11, c: 31131}, {f: 2, c: 31144}, {f: 3, c: 31147},
michael@0 12993 31151, 31154, {f: 4, c: 31156}, [12145, 31160], 31164, 31167, 31170,
michael@0 12994 {f: 2, c: 31172}, {f: 2, c: 31175}, 31178, 31180, {f: 3, c: 31182},
michael@0 12995 {f: 2, c: 31187}, {f: 2, c: 31190}, {f: 6, c: 31193}, {f: 3, c: 31200},
michael@0 12996 31205, 31208, 31210, 31212, 31214, {f: 7, c: 31217}, {f: 2, c: 31225},
michael@0 12997 31228, {f: 2, c: 31230}, 31233, {f: 2, c: 31236}, {f: 4, c: 31239}, 31244,
michael@0 12998 {f: 5, c: 31247}, {f: 2, c: 31253}, {f: 2, c: 31256}, {f: 3, c: 31259},
michael@0 12999 31263, {f: 2, c: 31265}, {f: 10, c: 31268}, {f: 2, c: 31279}, 31282,
michael@0 13000 {f: 3, c: 31284}, 31288, 31290, 31294, {f: 5, c: 31297}, {f: 5, c: 31303},
michael@0 13001 {f: 2, c: 31311}, {f: 5, c: 31314}, {f: 9, c: 31320}, {f: 6, c: 31331},
michael@0 13002 31338, {f: 4, c: 31340}, {f: 3, c: 31345}, 31349, {f: 4, c: 31355}, 31362,
michael@0 13003 31365, 31367, {f: 4, c: 31369}, {f: 3, c: 31374}, {f: 2, c: 31379},
michael@0 13004 {f: 3, c: 31385}, 31390, {f: 4, c: 31393}, 31399, 31403, {f: 4, c: 31407},
michael@0 13005 {f: 2, c: 31412}, {f: 3, c: 31415}, {f: 4, c: 31419}, {f: 4, c: 31424},
michael@0 13006 31430, 31433, {f: 10, c: 31436}, {f: 2, c: 31447}, {f: 4, c: 31450},
michael@0 13007 {f: 2, c: 31457}, 31460, {f: 3, c: 31463}, {f: 2, c: 31467}, 31470,
michael@0 13008 {f: 6, c: 31472}, {f: 2, c: 31479}, {f: 2, c: 31483}, 31486,
michael@0 13009 {f: 3, c: 31488}, 31493, 31495, 31497, {f: 3, c: 31500}, 31504,
michael@0 13010 {f: 2, c: 31506}, {f: 3, c: 31510}, 31514, {f: 2, c: 31516}, 31519,
michael@0 13011 {f: 3, c: 31521}, 31527, 31529, 31533, {f: 2, c: 31535}, 31538,
michael@0 13012 {f: 4, c: 31540}, 31545, 31547, 31549, {f: 6, c: 31551}, 31560, 31562,
michael@0 13013 {f: 2, c: 31565}, 31571, 31573, 31575, 31577, 31580, {f: 2, c: 31582},
michael@0 13014 31585, {f: 4, c: 31587}, {f: 6, c: 31592}, {f: 2, c: 31599},
michael@0 13015 {f: 2, c: 31603}, 31606, 31608, 31610, {f: 2, c: 31612}, 31615,
michael@0 13016 {f: 4, c: 31617}, {f: 5, c: 31622}, 31628, {f: 2, c: 31630},
michael@0 13017 {f: 3, c: 31633}, 31638, {f: 4, c: 31640}, {f: 3, c: 31646},
michael@0 13018 {f: 3, c: 31651}, {f: 3, c: 31662}, {f: 2, c: 31666}, {f: 3, c: 31669},
michael@0 13019 {f: 7, c: 31673}, {f: 2, c: 31682}, 31685, 31688, 31690, {f: 4, c: 31693},
michael@0 13020 31698, {f: 5, c: 31700}, {f: 2, c: 31707}, {f: 3, c: 31710},
michael@0 13021 {f: 2, c: 31714}, {f: 2, c: 31719}, {f: 3, c: 31723}, {f: 2, c: 31727},
michael@0 13022 31730, {f: 3, c: 31732}, {f: 4, c: 31736}, 31741, 31743, {f: 6, c: 31745},
michael@0 13023 {f: 3, c: 31752}, 31758, {f: 6, c: 31760}, {f: 7, c: 31767}, 31776, 31778,
michael@0 13024 {f: 2, c: 31780}, {f: 2, c: 31784}, {f: 12, c: 31788}, {f: 4, c: 31801},
michael@0 13025 31810, {f: 8, c: 31812}, {f: 14, c: 31822}, {f: 2, c: 31837},
michael@0 13026 {f: 3, c: 31841}, {f: 4, c: 31845}, 31851, 31853, {f: 3, c: 31855},
michael@0 13027 {f: 6, c: 31861}, {f: 11, c: 31870}, {f: 7, c: 31882}, {f: 2, c: 31891},
michael@0 13028 31894, {f: 3, c: 31897}, {f: 2, c: 31904}, 31907, {f: 4, c: 31910},
michael@0 13029 {f: 3, c: 31915}, {f: 2, c: 31919}, {f: 5, c: 31924}, {f: 2, c: 31930},
michael@0 13030 {f: 2, c: 31935}, {f: 3, c: 31938}, 31942, 31945, 31947, {f: 7, c: 31950},
michael@0 13031 31960, {f: 2, c: 31962}, {f: 6, c: 31969}, {f: 6, c: 31977}, 31985, 31987,
michael@0 13032 31989, 31991, 31994, {f: 2, c: 31996}, 31999, 32001, 32003, 32012,
michael@0 13033 {f: 2, c: 32014}, {f: 2, c: 32017}, 32022, 32024, {f: 3, c: 32029},
michael@0 13034 {f: 4, c: 32035}, {f: 3, c: 32040}, {f: 3, c: 32044}, {f: 5, c: 32052},
michael@0 13035 32059, {f: 2, c: 32061}, 32065, 32067, 32069, {f: 7, c: 32071}, 32079,
michael@0 13036 {f: 12, c: 32081}, {f: 2, c: 32095}, {f: 3, c: 32099}, 32103,
michael@0 13037 {f: 5, c: 32105}, {f: 2, c: 32111}, {f: 2, c: 32116}, 32120,
michael@0 13038 {f: 7, c: 32122}, 32130, {f: 2, c: 32132}, 32135, {f: 5, c: 32138},
michael@0 13039 {f: 3, c: 32144}, {f: 8, c: 32148}, 32157, {f: 3, c: 32159},
michael@0 13040 {f: 2, c: 32164}, {f: 4, c: 32167}, 32175, {f: 3, c: 32181}, 32188,
michael@0 13041 {f: 4, c: 32192}, {f: 2, c: 32197}, {f: 2, c: 32200}, {f: 5, c: 32204},
michael@0 13042 32211, {f: 2, c: 32213}, {f: 3, c: 32218}, 32223, 32226, {f: 2, c: 32228},
michael@0 13043 32231, {f: 2, c: 32234}, {f: 2, c: 32237}, 32240, 32243, 32245,
michael@0 13044 {f: 2, c: 32247}, 32250, {f: 12, c: 32252}, {f: 4, c: 32268},
michael@0 13045 {f: 9, c: 32274}, 32284, {f: 3, c: 32288}, {f: 3, c: 32292},
michael@0 13046 {f: 3, c: 32296}, 32300, {f: 2, c: 32303}, 32307, 32312, 32314, 32316,
michael@0 13047 {f: 2, c: 32319}, {f: 3, c: 32322}, {f: 10, c: 32328}, 32339,
michael@0 13048 {f: 4, c: 32342}, {f: 3, c: 32347}, {f: 3, c: 32351}, {f: 6, c: 32355},
michael@0 13049 32364, {f: 2, c: 32369}, {f: 5, c: 32372}, {f: 2, c: 32378},
michael@0 13050 {f: 3, c: 32383}, {f: 5, c: 32387}, 32393, 32395, 32398, {f: 3, c: 32400},
michael@0 13051 32405, 32407, {f: 2, c: 32409}, {f: 2, c: 32413}, 32430, 32436,
michael@0 13052 {f: 2, c: 32443}, 32470, 32484, 32492, 32505, 32522, 32528, 32542, 32567,
michael@0 13053 32569, {f: 7, c: 32571}, 32579, {f: 6, c: 32582}, 32589, 32591,
michael@0 13054 {f: 2, c: 32594}, 32598, 32601, {f: 4, c: 32603}, 32608, {f: 5, c: 32611},
michael@0 13055 {f: 3, c: 32619}, 32623, 32627, {f: 2, c: 32629}, 32632, {f: 4, c: 32634},
michael@0 13056 {f: 2, c: 32639}, {f: 3, c: 32642}, 32647, 32649, 32651, 32653,
michael@0 13057 {f: 5, c: 32655}, {f: 5, c: 32661}, {f: 2, c: 32667}, 32672,
michael@0 13058 {f: 2, c: 32674}, 32678, 32680, {f: 5, c: 32682}, 32689, {f: 5, c: 32691},
michael@0 13059 {f: 2, c: 32698}, 32702, 32704, {f: 3, c: 32706}, {f: 4, c: 32710}, 32715,
michael@0 13060 32717, {f: 3, c: 32719}, 32723, {f: 2, c: 32726}, {f: 6, c: 32729},
michael@0 13061 {f: 3, c: 32738}, {f: 2, c: 32743}, {f: 4, c: 32746}, 32751, 32754,
michael@0 13062 {f: 5, c: 32756}, 32762, {f: 3, c: 32765}, 32770, {f: 4, c: 32775},
michael@0 13063 {f: 2, c: 32782}, 32785, 32787, {f: 2, c: 32794}, {f: 3, c: 32797}, 32801,
michael@0 13064 {f: 2, c: 32803}, 32811, 32813, {f: 2, c: 32815}, 32818, 32820,
michael@0 13065 {f: 2, c: 32825}, 32828, 32830, {f: 2, c: 32832}, {f: 2, c: 32836},
michael@0 13066 {f: 3, c: 32839}, {f: 4, c: 32846}, 32851, 32853, 32855, 32857,
michael@0 13067 {f: 3, c: 32859}, {f: 10, c: 32863}, {f: 4, c: 32875}, 32884, 32888,
michael@0 13068 {f: 3, c: 32890}, {f: 2, c: 32897}, 32904, 32906, {f: 6, c: 32909},
michael@0 13069 {f: 2, c: 32916}, 32919, 32921, 32926, 32931, {f: 3, c: 32934}, 32940,
michael@0 13070 32944, 32947, {f: 2, c: 32949}, {f: 2, c: 32952}, 32955, 32965,
michael@0 13071 {f: 5, c: 32967}, {f: 7, c: 32975}, 32984, {f: 2, c: 32991},
michael@0 13072 {f: 2, c: 32994}, 32998, 33006, 33013, 33015, 33017, 33019,
michael@0 13073 {f: 4, c: 33022}, {f: 2, c: 33027}, {f: 2, c: 33031}, {f: 2, c: 33035},
michael@0 13074 33045, 33047, 33049, {f: 2, c: 33052}, {f: 13, c: 33055}, {f: 2, c: 33069},
michael@0 13075 33072, {f: 3, c: 33075}, 33079, {f: 4, c: 33082}, {f: 7, c: 33087}, 33095,
michael@0 13076 33097, 33101, 33103, 33106, {f: 2, c: 33111}, {f: 5, c: 33115},
michael@0 13077 {f: 3, c: 33122}, 33128, 33130, 33132, 33135, {f: 2, c: 33138},
michael@0 13078 {f: 3, c: 33141}, 33153, {f: 5, c: 33155}, 33161, {f: 4, c: 33163}, 33168,
michael@0 13079 {f: 6, c: 33170}, 33177, {f: 2, c: 33182}, {f: 2, c: 33185},
michael@0 13080 {f: 2, c: 33188}, 33191, {f: 8, c: 33195}, {f: 6, c: 33204}, 33212,
michael@0 13081 {f: 2, c: 33220}, {f: 2, c: 33223}, 33227, 33230, {f: 8, c: 33232}, 33241,
michael@0 13082 {f: 4, c: 33243}, {f: 2, c: 33249}, {f: 3, c: 33252}, 33257, 33259,
michael@0 13083 {f: 5, c: 33262}, {f: 5, c: 33269}, 33277, 33279, 33283, 33291,
michael@0 13084 {f: 2, c: 33294}, 33297, 33299, {f: 6, c: 33301}, 33309, 33312,
michael@0 13085 {f: 4, c: 33316}, 33321, 33326, 33330, 33338, {f: 2, c: 33340},
michael@0 13086 {f: 5, c: 33343}, {f: 2, c: 33349}, 33352, 33354, {f: 3, c: 33356},
michael@0 13087 {f: 8, c: 33360}, {f: 4, c: 33371}, {f: 4, c: 33376}, 33381, 33383,
michael@0 13088 {f: 2, c: 33385}, {f: 2, c: 33388}, {f: 2, c: 33397}, [12171, 33400],
michael@0 13089 {f: 2, c: 33403}, {f: 2, c: 33408}, 33411, {f: 3, c: 33413}, 33417, 33420,
michael@0 13090 33424, {f: 4, c: 33427}, {f: 2, c: 33434}, 33438, 33440, {f: 2, c: 33442},
michael@0 13091 33447, 33458, {f: 2, c: 33461}, 33466, 33468, {f: 2, c: 33471},
michael@0 13092 {f: 2, c: 33474}, {f: 2, c: 33477}, 33481, 33488, 33494, {f: 2, c: 33497},
michael@0 13093 33501, 33506, {f: 3, c: 33512}, {f: 3, c: 33516}, 33520, {f: 2, c: 33522},
michael@0 13094 {f: 2, c: 33525}, 33528, 33530, {f: 5, c: 33532}, {f: 2, c: 33546}, 33549,
michael@0 13095 33552, {f: 2, c: 33554}, 33558, {f: 2, c: 33560}, {f: 10, c: 33565},
michael@0 13096 {f: 2, c: 33577}, 33582, 33584, 33586, 33591, 33595, {f: 3, c: 33597},
michael@0 13097 {f: 2, c: 33601}, {f: 2, c: 33604}, 33608, {f: 5, c: 33610}, 33619,
michael@0 13098 {f: 5, c: 33621}, 33629, 33634, {f: 7, c: 33648}, {f: 2, c: 33657},
michael@0 13099 {f: 7, c: 33662}, {f: 2, c: 33671}, {f: 3, c: 33675}, {f: 3, c: 33679},
michael@0 13100 {f: 2, c: 33684}, 33687, {f: 2, c: 33689}, 33693, 33695, 33697,
michael@0 13101 {f: 4, c: 33699}, {f: 4, c: 33708}, 33717, 33723, {f: 2, c: 33726},
michael@0 13102 {f: 3, c: 33730}, 33734, {f: 2, c: 33736}, 33739, {f: 2, c: 33741},
michael@0 13103 {f: 4, c: 33744}, 33749, 33751, {f: 3, c: 33753}, 33758, {f: 3, c: 33762},
michael@0 13104 {f: 3, c: 33766}, {f: 4, c: 33771}, {f: 5, c: 33779}, {f: 3, c: 33786},
michael@0 13105 {f: 3, c: 33790}, 33794, 33797, {f: 2, c: 33800}, 33808, {f: 6, c: 33810},
michael@0 13106 {f: 3, c: 33817}, {f: 6, c: 33822}, {f: 3, c: 33833}, {f: 4, c: 33837},
michael@0 13107 {f: 3, c: 33842}, {f: 2, c: 33846}, {f: 3, c: 33849}, {f: 8, c: 33854},
michael@0 13108 {f: 2, c: 33863}, {f: 7, c: 33866}, {f: 4, c: 33875}, 33880,
michael@0 13109 {f: 4, c: 33885}, 33890, 33893, {f: 2, c: 33895}, 33898, 33902, 33904,
michael@0 13110 33906, 33908, 33913, {f: 7, c: 33915}, {f: 4, c: 33923}, 33930, 33933,
michael@0 13111 {f: 4, c: 33935}, {f: 2, c: 33941}, 33944, {f: 2, c: 33946},
michael@0 13112 {f: 4, c: 33949}, {f: 13, c: 33954}, {f: 2, c: 33968}, 33971,
michael@0 13113 {f: 3, c: 33973}, 33979, 33982, {f: 2, c: 33986}, {f: 4, c: 33989}, 33996,
michael@0 13114 {f: 2, c: 33998}, 34002, {f: 2, c: 34004}, {f: 6, c: 34007}, 34014,
michael@0 13115 {f: 2, c: 34017}, 34020, {f: 5, c: 34023}, 34029, {f: 11, c: 34033}, 34046,
michael@0 13116 {f: 12, c: 34048}, {f: 4, c: 34061}, 34066, {f: 2, c: 34069},
michael@0 13117 {f: 2, c: 34072}, {f: 3, c: 34075}, 34080, 34082, {f: 2, c: 34084},
michael@0 13118 {f: 4, c: 34087}, {f: 9, c: 34094}, {f: 3, c: 34110}, 34114,
michael@0 13119 {f: 2, c: 34116}, 34119, {f: 3, c: 34123}, {f: 3, c: 34127}, 34132, 34135,
michael@0 13120 {f: 4, c: 34138}, {f: 3, c: 34143}, 34147, {f: 3, c: 34149},
michael@0 13121 {f: 2, c: 34155}, {f: 4, c: 34158}, 34163, {f: 2, c: 34165}, 34168,
michael@0 13122 {f: 2, c: 34172}, {f: 5, c: 34175}, 34182, 34185, 34187, {f: 2, c: 34189},
michael@0 13123 34192, {f: 2, c: 34194}, {f: 6, c: 34197}, {f: 2, c: 34205},
michael@0 13124 {f: 4, c: 34208}, 34213, 34215, {f: 3, c: 34219}, {f: 6, c: 34225}, 34232,
michael@0 13125 {f: 6, c: 34235}, {f: 7, c: 34242}, {f: 3, c: 34250}, {f: 2, c: 34257},
michael@0 13126 34260, {f: 6, c: 34262}, {f: 6, c: 34270}, {f: 3, c: 34278},
michael@0 13127 {f: 9, c: 34283}, 34293, {f: 2, c: 34295}, {f: 3, c: 34300},
michael@0 13128 {f: 4, c: 34304}, {f: 3, c: 34312}, {f: 5, c: 34316}, {f: 4, c: 34322},
michael@0 13129 {f: 3, c: 34327}, {f: 3, c: 34331}, {f: 3, c: 34335}, {f: 4, c: 34339},
michael@0 13130 34344, {f: 3, c: 34346}, {f: 10, c: 34350}, 34361, 34363, {f: 2, c: 34365},
michael@0 13131 {f: 13, c: 34368}, {f: 2, c: 34386}, {f: 4, c: 34390}, 34395, 34397,
michael@0 13132 {f: 2, c: 34400}, {f: 4, c: 34403}, {f: 3, c: 34408}, 34413,
michael@0 13133 {f: 2, c: 34415}, {f: 7, c: 34418}, {f: 7, c: 34435}, {f: 5, c: 34446},
michael@0 13134 34452, {f: 6, c: 34454}, {f: 5, c: 34462}, {f: 2, c: 34469}, 34475,
michael@0 13135 {f: 2, c: 34477}, {f: 2, c: 34482}, {f: 3, c: 34487}, {f: 5, c: 34491},
michael@0 13136 {f: 3, c: 34497}, 34501, 34504, {f: 2, c: 34508}, {f: 2, c: 34514},
michael@0 13137 {f: 3, c: 34517}, 34522, {f: 2, c: 34524}, {f: 4, c: 34528},
michael@0 13138 {f: 4, c: 34533}, {f: 3, c: 34538}, 34543, {f: 3, c: 34549},
michael@0 13139 {f: 3, c: 34555}, 34559, 34561, {f: 2, c: 34564}, {f: 2, c: 34571},
michael@0 13140 {f: 4, c: 34574}, 34580, 34582, 34585, 34587, 34589, {f: 2, c: 34591},
michael@0 13141 34596, {f: 3, c: 34598}, {f: 4, c: 34602}, {f: 2, c: 34607},
michael@0 13142 {f: 2, c: 34610}, {f: 2, c: 34613}, {f: 3, c: 34616}, {f: 2, c: 34620},
michael@0 13143 {f: 7, c: 34624}, {f: 2, c: 34634}, 34637, {f: 4, c: 34639}, 34644, 34646,
michael@0 13144 34648, {f: 6, c: 34650}, {f: 2, c: 34657}, {f: 7, c: 34663}, 34671,
michael@0 13145 {f: 3, c: 34673}, 34677, 34679, {f: 2, c: 34681}, {f: 3, c: 34687},
michael@0 13146 {f: 2, c: 34694}, {f: 2, c: 34697}, 34700, {f: 5, c: 34702},
michael@0 13147 {f: 3, c: 34708}, {f: 6, c: 34712}, {f: 2, c: 34720}, {f: 5, c: 34723},
michael@0 13148 {f: 2, c: 34729}, 34734, {f: 3, c: 34736}, 34740, {f: 4, c: 34742}, 34748,
michael@0 13149 {f: 2, c: 34750}, {f: 3, c: 34753}, 34757, 34759, 34761, {f: 2, c: 34764},
michael@0 13150 {f: 2, c: 34767}, {f: 7, c: 34772}, {f: 4, c: 34780}, {f: 2, c: 34785},
michael@0 13151 34788, {f: 4, c: 34790}, 34795, 34797, {f: 2, c: 34800}, {f: 3, c: 34803},
michael@0 13152 {f: 2, c: 34807}, 34810, {f: 2, c: 34812}, {f: 4, c: 34815}, 34820,
michael@0 13153 {f: 3, c: 34823}, {f: 5, c: 34827}, 34834, 34836, {f: 4, c: 34839},
michael@0 13154 {f: 3, c: 34844}, 34848, {f: 13, c: 34852}, {f: 3, c: 34867},
michael@0 13155 {f: 2, c: 34871}, 34874, {f: 3, c: 34877}, {f: 3, c: 34881},
michael@0 13156 {f: 3, c: 34887}, 34891, {f: 5, c: 34894}, {f: 2, c: 34901}, 34904, 34906,
michael@0 13157 34908, {f: 3, c: 34910}, {f: 2, c: 34918}, 34922, 34925, 34927, 34929,
michael@0 13158 {f: 4, c: 34931}, 34936, {f: 3, c: 34938}, 34944, 34947, {f: 2, c: 34950},
michael@0 13159 {f: 2, c: 34953}, 34956, {f: 4, c: 34958}, {f: 3, c: 34963},
michael@0 13160 {f: 5, c: 34967}, {f: 5, c: 34973}, 34979, {f: 6, c: 34981}, 34988,
michael@0 13161 {f: 3, c: 34990}, {f: 5, c: 34994}, {f: 4, c: 35000}, {f: 4, c: 35005},
michael@0 13162 {f: 2, c: 35011}, {f: 2, c: 35015}, {f: 3, c: 35019}, {f: 2, c: 35024},
michael@0 13163 35027, {f: 2, c: 35030}, {f: 2, c: 35034}, 35038, {f: 2, c: 35040},
michael@0 13164 {f: 2, c: 35046}, {f: 7, c: 35049}, 35058, {f: 3, c: 35061},
michael@0 13165 {f: 2, c: 35066}, {f: 3, c: 35071}, {f: 4, c: 35075}, {f: 2, c: 35080},
michael@0 13166 {f: 5, c: 35083}, 35089, {f: 5, c: 35092}, {f: 5, c: 35100},
michael@0 13167 {f: 3, c: 35106}, {f: 4, c: 35110}, {f: 4, c: 35116}, 35121, 35125, 35127,
michael@0 13168 {f: 2, c: 35129}, {f: 5, c: 35132}, {f: 2, c: 35138}, {f: 2, c: 35141},
michael@0 13169 {f: 14, c: 35144}, {f: 6, c: 35159}, {f: 3, c: 35169}, 35173,
michael@0 13170 {f: 3, c: 35175}, 35179, {f: 2, c: 35181}, {f: 2, c: 35184},
michael@0 13171 {f: 8, c: 35187}, {f: 2, c: 35196}, [12177, 35198], 35200, 35202,
michael@0 13172 {f: 2, c: 35204}, {f: 4, c: 35207}, {f: 3, c: 35212}, {f: 3, c: 35216},
michael@0 13173 {f: 2, c: 35220}, 35223, {f: 8, c: 35225}, {f: 4, c: 35234},
michael@0 13174 {f: 3, c: 35239}, 35243, {f: 2, c: 35245}, {f: 2, c: 35248},
michael@0 13175 {f: 4, c: 35251}, {f: 2, c: 35256}, {f: 2, c: 35259}, 35262, 35267, 35277,
michael@0 13176 {f: 3, c: 35283}, {f: 3, c: 35287}, 35291, 35293, {f: 4, c: 35295}, 35300,
michael@0 13177 {f: 4, c: 35303}, {f: 3, c: 35308}, {f: 3, c: 35312}, 35317, 35319,
michael@0 13178 {f: 7, c: 35321}, {f: 3, c: 35332}, 35337, 35339, 35341, 35343,
michael@0 13179 {f: 2, c: 35345}, 35348, 35351, {f: 2, c: 35353}, 35356, 35358,
michael@0 13180 {f: 3, c: 35360}, 35364, {f: 4, c: 35366}, {f: 2, c: 35371},
michael@0 13181 {f: 3, c: 35374}, {f: 2, c: 35378}, 35381, {f: 3, c: 35383},
michael@0 13182 {f: 3, c: 35387}, {f: 2, c: 35391}, {f: 4, c: 35394}, 35399,
michael@0 13183 {f: 5, c: 35401}, 35407, 35409, 35411, {f: 2, c: 35414}, {f: 2, c: 35417},
michael@0 13184 {f: 2, c: 35420}, {f: 2, c: 35423}, {f: 2, c: 35428}, {f: 2, c: 35431},
michael@0 13185 35434, 35439, 35444, {f: 3, c: 35446}, {f: 2, c: 35450}, {f: 2, c: 35453},
michael@0 13186 {f: 4, c: 35456}, 35464, {f: 2, c: 35467}, {f: 3, c: 35470}, 35476,
michael@0 13187 {f: 2, c: 35478}, 35481, {f: 3, c: 35483}, 35487, 35490, 35495,
michael@0 13188 {f: 3, c: 35497}, {f: 3, c: 35501}, 35505, {f: 3, c: 35507},
michael@0 13189 {f: 2, c: 35511}, {f: 2, c: 35514}, {f: 2, c: 35517}, {f: 2, c: 35520},
michael@0 13190 35523, {f: 2, c: 35525}, 35528, 35530, 35532, 35534, 35536,
michael@0 13191 {f: 3, c: 35539}, {f: 3, c: 35544}, 35549, {f: 3, c: 35551}, 35555, 35557,
michael@0 13192 {f: 3, c: 35560}, 35564, {f: 2, c: 35567}, 35570, {f: 2, c: 35572}, 35577,
michael@0 13193 35579, 35581, 35583, 35587, 35590, {f: 2, c: 35592}, {f: 3, c: 35595},
michael@0 13194 35599, {f: 3, c: 35601}, 35605, 35608, 35612, {f: 3, c: 35614},
michael@0 13195 {f: 4, c: 35618}, 35623, {f: 2, c: 35625}, {f: 5, c: 35630},
michael@0 13196 {f: 5, c: 35636}, {f: 4, c: 35642}, {f: 10, c: 35647}, {f: 4, c: 35658},
michael@0 13197 {f: 6, c: 35664}, 35671, 35675, {f: 9, c: 35677}, {f: 4, c: 35687},
michael@0 13198 {f: 2, c: 35693}, {f: 3, c: 35697}, {f: 2, c: 35701}, {f: 5, c: 35704},
michael@0 13199 {f: 2, c: 35710}, {f: 9, c: 35713}, {f: 3, c: 35723}, {f: 3, c: 35727},
michael@0 13200 35732, {f: 5, c: 35735}, 35741, 35743, 35756, 35761, 35771, 35783, 35792,
michael@0 13201 35818, 35849, 35870, {f: 9, c: 35896}, {f: 4, c: 35906}, {f: 2, c: 35914},
michael@0 13202 {f: 3, c: 35917}, {f: 4, c: 35921}, {f: 4, c: 35926}, {f: 6, c: 35931},
michael@0 13203 {f: 7, c: 35939}, {f: 7, c: 35948}, {f: 4, c: 35956}, {f: 7, c: 35963},
michael@0 13204 {f: 2, c: 35971}, {f: 3, c: 35974}, 35979, {f: 7, c: 35981},
michael@0 13205 {f: 3, c: 35989}, {f: 4, c: 35993}, 35999, {f: 4, c: 36003},
michael@0 13206 {f: 2, c: 36013}, 36017, 36021, 36025, 36030, 36038, 36041,
michael@0 13207 {f: 6, c: 36043}, 36052, {f: 4, c: 36054}, 36059, 36061, 36063, 36069,
michael@0 13208 {f: 2, c: 36072}, {f: 6, c: 36078}, {f: 5, c: 36085}, {f: 5, c: 36095},
michael@0 13209 {f: 2, c: 36102}, 36105, 36108, 36110, {f: 5, c: 36113}, {f: 4, c: 36119},
michael@0 13210 36128, {f: 2, c: 36177}, 36183, 36191, 36197, {f: 3, c: 36200}, 36204,
michael@0 13211 {f: 2, c: 36206}, {f: 2, c: 36209}, {f: 9, c: 36216}, {f: 2, c: 36226},
michael@0 13212 {f: 4, c: 36230}, {f: 5, c: 36236}, {f: 2, c: 36242}, {f: 3, c: 36246},
michael@0 13213 {f: 5, c: 36250}, {f: 3, c: 36256}, {f: 4, c: 36260}, {f: 8, c: 36265},
michael@0 13214 {f: 2, c: 36278}, 36281, 36283, 36285, {f: 3, c: 36288}, 36293,
michael@0 13215 {f: 4, c: 36295}, 36301, 36304, {f: 4, c: 36306}, {f: 2, c: 36312}, 36316,
michael@0 13216 {f: 3, c: 36320}, {f: 3, c: 36325}, 36329, {f: 2, c: 36333},
michael@0 13217 {f: 3, c: 36336}, 36340, 36342, 36348, {f: 7, c: 36350}, {f: 3, c: 36358},
michael@0 13218 36363, {f: 2, c: 36365}, {f: 3, c: 36369}, {f: 8, c: 36373},
michael@0 13219 {f: 2, c: 36384}, {f: 5, c: 36388}, 36395, 36397, 36400, {f: 2, c: 36402},
michael@0 13220 {f: 3, c: 36406}, {f: 2, c: 36411}, {f: 2, c: 36414}, 36419,
michael@0 13221 {f: 2, c: 36421}, {f: 4, c: 36429}, {f: 2, c: 36435}, {f: 3, c: 36438},
michael@0 13222 {f: 9, c: 36442}, {f: 2, c: 36452}, {f: 2, c: 36455}, {f: 2, c: 36458},
michael@0 13223 36462, 36465, 36467, 36469, {f: 3, c: 36471}, 36475, {f: 2, c: 36477},
michael@0 13224 36480, {f: 3, c: 36482}, 36486, 36488, 36492, 36494, {f: 5, c: 36501},
michael@0 13225 36507, 36509, {f: 2, c: 36511}, {f: 3, c: 36514}, {f: 3, c: 36519},
michael@0 13226 {f: 2, c: 36525}, {f: 2, c: 36528}, {f: 7, c: 36531}, {f: 5, c: 36539},
michael@0 13227 {f: 9, c: 36545}, {f: 3, c: 36559}, 36563, {f: 6, c: 36565},
michael@0 13228 {f: 3, c: 36572}, {f: 4, c: 36576}, {f: 6, c: 36581}, {f: 6, c: 36588},
michael@0 13229 {f: 5, c: 36595}, 36605, {f: 4, c: 36607}, 36612, 36614, 36616,
michael@0 13230 {f: 7, c: 36619}, 36627, {f: 5, c: 36630}, {f: 5, c: 36640},
michael@0 13231 {f: 2, c: 36647}, {f: 4, c: 36651}, {f: 3, c: 36656}, {f: 4, c: 36660},
michael@0 13232 {f: 2, c: 36665}, {f: 2, c: 36668}, {f: 2, c: 36672}, 36675,
michael@0 13233 {f: 2, c: 36679}, {f: 3, c: 36682}, {f: 5, c: 36687}, {f: 10, c: 36693},
michael@0 13234 36704, 36707, 36709, 36714, 36736, 36748, 36754, 36765, {f: 3, c: 36768},
michael@0 13235 {f: 2, c: 36772}, 36775, 36778, 36780, {f: 2, c: 36787}, [12193, 36789],
michael@0 13236 {f: 2, c: 36791}, {f: 3, c: 36794}, {f: 2, c: 36799}, 36803, 36806,
michael@0 13237 {f: 5, c: 36809}, 36815, 36818, {f: 2, c: 36822}, 36826, {f: 2, c: 36832},
michael@0 13238 36835, 36839, 36844, 36847, {f: 2, c: 36849}, {f: 2, c: 36853},
michael@0 13239 {f: 3, c: 36858}, {f: 2, c: 36862}, {f: 2, c: 36871}, 36876, 36878, 36883,
michael@0 13240 36888, 36892, {f: 2, c: 36900}, {f: 6, c: 36903}, {f: 2, c: 36912},
michael@0 13241 {f: 2, c: 36915}, 36919, {f: 2, c: 36921}, 36925, {f: 2, c: 36927}, 36931,
michael@0 13242 {f: 2, c: 36933}, {f: 3, c: 36936}, 36940, 36950, {f: 2, c: 36953}, 36957,
michael@0 13243 36959, 36961, 36964, {f: 2, c: 36966}, {f: 3, c: 36970}, {f: 3, c: 36975},
michael@0 13244 36979, 36982, 36985, 36987, 36990, {f: 2, c: 36997}, 37001,
michael@0 13245 {f: 3, c: 37004}, 37010, 37012, 37014, 37016, 37018, 37020,
michael@0 13246 {f: 3, c: 37022}, {f: 2, c: 37028}, {f: 3, c: 37031}, 37035, 37037, 37042,
michael@0 13247 37047, {f: 2, c: 37052}, {f: 2, c: 37055}, {f: 2, c: 37058}, 37062,
michael@0 13248 {f: 2, c: 37064}, {f: 3, c: 37067}, 37074, {f: 3, c: 37076},
michael@0 13249 {f: 3, c: 37080}, 37086, 37088, {f: 3, c: 37091}, {f: 2, c: 37097}, 37100,
michael@0 13250 37102, {f: 4, c: 37104}, {f: 2, c: 37110}, {f: 4, c: 37113},
michael@0 13251 {f: 3, c: 37119}, 37123, 37125, {f: 2, c: 37127}, {f: 8, c: 37130}, 37139,
michael@0 13252 37141, {f: 2, c: 37143}, {f: 4, c: 37146}, {f: 3, c: 37151},
michael@0 13253 {f: 3, c: 37156}, {f: 5, c: 37160}, 37166, 37171, 37173, {f: 2, c: 37175},
michael@0 13254 {f: 8, c: 37179}, {f: 2, c: 37188}, 37191, 37201, {f: 4, c: 37203},
michael@0 13255 {f: 2, c: 37208}, {f: 2, c: 37211}, {f: 2, c: 37215}, {f: 3, c: 37222},
michael@0 13256 37227, 37229, 37235, {f: 3, c: 37242}, {f: 5, c: 37248}, 37254, 37256,
michael@0 13257 37258, {f: 2, c: 37262}, {f: 3, c: 37267}, {f: 3, c: 37271},
michael@0 13258 {f: 5, c: 37277}, {f: 6, c: 37284}, {f: 4, c: 37296}, {f: 4, c: 37302},
michael@0 13259 {f: 5, c: 37307}, 37314, 37316, [12196, 37318], 37320, 37328, 37334,
michael@0 13260 {f: 2, c: 37338}, {f: 5, c: 37342}, {f: 2, c: 37349}, 37352,
michael@0 13261 {f: 11, c: 37354}, 37366, 37368, {f: 5, c: 37371}, {f: 2, c: 37378},
michael@0 13262 {f: 3, c: 37381}, {f: 3, c: 37386}, 37391, {f: 2, c: 37394},
michael@0 13263 {f: 8, c: 37398}, {f: 4, c: 37407}, 37412, {f: 6, c: 37416}, 37423,
michael@0 13264 {f: 2, c: 37425}, {f: 2, c: 37429}, {f: 2, c: 37435}, {f: 4, c: 37441},
michael@0 13265 {f: 2, c: 37446}, {f: 3, c: 37450}, {f: 3, c: 37454}, {f: 3, c: 37458},
michael@0 13266 37462, {f: 2, c: 37464}, {f: 2, c: 37468}, {f: 3, c: 37471},
michael@0 13267 {f: 3, c: 37475}, {f: 5, c: 37479}, {f: 6, c: 37486}, {f: 3, c: 37493},
michael@0 13268 37497, {f: 3, c: 37500}, {f: 2, c: 37505}, 37508, {f: 8, c: 37510},
michael@0 13269 {f: 2, c: 37519}, 37522, {f: 2, c: 37524}, 37527, 37529, 37531,
michael@0 13270 {f: 3, c: 37533}, {f: 2, c: 37537}, 37540, 37543, 37549, {f: 2, c: 37551},
michael@0 13271 {f: 5, c: 37554}, 37560, 37562, {f: 4, c: 37565}, 37570, 37572, 37574,
michael@0 13272 {f: 3, c: 37577}, {f: 2, c: 37581}, {f: 2, c: 37584}, {f: 10, c: 37587},
michael@0 13273 37598, {f: 3, c: 37600}, 37607, 37609, {f: 2, c: 37611}, {f: 4, c: 37618},
michael@0 13274 37623, {f: 3, c: 37625}, {f: 4, c: 37629}, {f: 4, c: 37634},
michael@0 13275 {f: 7, c: 37641}, 37649, {f: 2, c: 37651}, {f: 2, c: 37654},
michael@0 13276 {f: 3, c: 37660}, 37665, {f: 3, c: 37667}, 37671, {f: 2, c: 37673},
michael@0 13277 {f: 2, c: 37676}, {f: 2, c: 37680}, {f: 2, c: 37684}, 37687,
michael@0 13278 {f: 5, c: 37689}, 37695, 37698, {f: 2, c: 37700}, {f: 3, c: 37704}, 37708,
michael@0 13279 {f: 6, c: 37710}, {f: 3, c: 37717}, {f: 2, c: 37721}, {f: 8, c: 37724},
michael@0 13280 {f: 3, c: 37734}, 37739, {f: 3, c: 37741}, {f: 4, c: 37745},
michael@0 13281 {f: 3, c: 37751}, {f: 3, c: 37755}, {f: 3, c: 37759}, 37763,
michael@0 13282 {f: 2, c: 37765}, {f: 2, c: 37768}, {f: 4, c: 37771}, {f: 6, c: 37776},
michael@0 13283 37783, {f: 9, c: 37785}, {f: 2, c: 37796}, 37800, 37803, 37805, 37807,
michael@0 13284 {f: 2, c: 37809}, 37812, {f: 2, c: 37814}, {f: 6, c: 37817},
michael@0 13285 {f: 3, c: 37824}, {f: 3, c: 37828}, 37833, 37835, {f: 3, c: 37838},
michael@0 13286 {f: 4, c: 37842}, {f: 3, c: 37849}, 37856, 37859, {f: 3, c: 37861},
michael@0 13287 {f: 12, c: 37865}, 37878, 37880, {f: 9, c: 37882}, {f: 7, c: 37892},
michael@0 13288 {f: 4, c: 37900}, 37905, {f: 3, c: 37909}, {f: 3, c: 37914},
michael@0 13289 {f: 2, c: 37918}, {f: 5, c: 37921}, {f: 5, c: 37929}, {f: 3, c: 37935},
michael@0 13290 37940, {f: 2, c: 37942}, 37945, {f: 3, c: 37947}, {f: 4, c: 37952},
michael@0 13291 {f: 5, c: 37957}, 37963, {f: 5, c: 37965}, 37971, {f: 11, c: 37973},
michael@0 13292 {f: 2, c: 37985}, 37988, {f: 5, c: 37990}, 37996, {f: 2, c: 37998}, 38001,
michael@0 13293 {f: 4, c: 38003}, 38008, {f: 2, c: 38010}, {f: 5, c: 38016}, 38033, 38038,
michael@0 13294 38040, 38087, 38095, {f: 2, c: 38099}, 38106, 38118, 38139, 38172, 38176,
michael@0 13295 38183, 38195, 38205, 38211, 38216, 38219, 38229, 38234, 38240, 38254,
michael@0 13296 {f: 2, c: 38260}, {f: 7, c: 38264}, 38273, {f: 2, c: 38276},
michael@0 13297 {f: 2, c: 38279}, 38282, 38285, 38288, 38290, {f: 3, c: 38293},
michael@0 13298 {f: 8, c: 38297}, 38306, {f: 2, c: 38310}, 38314, {f: 4, c: 38318},
michael@0 13299 {f: 3, c: 38323}, {f: 2, c: 38327}, 38330, {f: 3, c: 38336},
michael@0 13300 {f: 2, c: 38340}, 38343, 38345, {f: 3, c: 38349}, {f: 3, c: 38353},
michael@0 13301 {f: 5, c: 38359}, 38365, {f: 2, c: 38367}, {f: 2, c: 38371},
michael@0 13302 {f: 2, c: 38374}, 38380, 38399, 38407, 38419, 38424, 38427, 38430, 38432,
michael@0 13303 {f: 7, c: 38435}, {f: 3, c: 38443}, {f: 2, c: 38447}, {f: 4, c: 38455},
michael@0 13304 38462, 38465, 38467, 38474, {f: 2, c: 38478}, {f: 3, c: 38481},
michael@0 13305 {f: 2, c: 38486}, {f: 2, c: 38489}, 38492, 38494, 38496, {f: 2, c: 38501},
michael@0 13306 38507, {f: 3, c: 38509}, 38513, {f: 4, c: 38521}, {f: 7, c: 38526}, 38535,
michael@0 13307 38537, 38540, {f: 3, c: 38545}, 38550, 38554, {f: 10, c: 38557}, 38569,
michael@0 13308 {f: 5, c: 38571}, 38578, 38581, 38583, 38586, 38591, {f: 2, c: 38594},
michael@0 13309 38600, {f: 2, c: 38602}, {f: 2, c: 38608}, {f: 2, c: 38611},
michael@0 13310 {f: 2, c: 38615}, 38618, {f: 3, c: 38621}, 38625, {f: 4, c: 38628},
michael@0 13311 {f: 4, c: 38635}, {f: 2, c: 38640}, {f: 2, c: 38644}, 38648, 38650,
michael@0 13312 {f: 2, c: 38652}, 38655, {f: 2, c: 38658}, 38661, {f: 3, c: 38666},
michael@0 13313 {f: 3, c: 38672}, {f: 2, c: 38676}, {f: 5, c: 38679}, 38685,
michael@0 13314 {f: 8, c: 38687}, {f: 2, c: 38696}, {f: 2, c: 38699}, {f: 2, c: 38702},
michael@0 13315 38705, {f: 5, c: 38707}, {f: 3, c: 38714}, {f: 3, c: 38719}, 38723,
michael@0 13316 {f: 3, c: 38725}, {f: 8, c: 38729}, [12205, 38737], {f: 2, c: 38740},
michael@0 13317 {f: 2, c: 38743}, {f: 2, c: 38748}, 38751, {f: 2, c: 38755},
michael@0 13318 {f: 2, c: 38758}, {f: 9, c: 38762}, 38773, {f: 5, c: 38775},
michael@0 13319 {f: 8, c: 38781}, {f: 5, c: 38790}, 38796, 38798, 38800, 38803,
michael@0 13320 {f: 3, c: 38805}, {f: 7, c: 38809}, {f: 2, c: 38817}, {f: 2, c: 38820},
michael@0 13321 {f: 4, c: 38823}, 38828, 38830, {f: 2, c: 38832}, 38835, {f: 8, c: 38837},
michael@0 13322 {f: 5, c: 38846}, {f: 2, c: 38852}, {f: 2, c: 38855}, 38858,
michael@0 13323 {f: 6, c: 38861}, {f: 5, c: 38868}, {f: 2, c: 38874}, 38877,
michael@0 13324 {f: 7, c: 38879}, 38888, {f: 5, c: 38894}, 38900, {f: 8, c: 38903}, 38912,
michael@0 13325 38916, 38921, 38923, 38925, {f: 3, c: 38932}, {f: 3, c: 38937},
michael@0 13326 {f: 4, c: 38941}, {f: 2, c: 38946}, 38949, {f: 6, c: 38951},
michael@0 13327 {f: 2, c: 38958}, {f: 6, c: 38961}, {f: 2, c: 38969}, 38972,
michael@0 13328 {f: 8, c: 38974}, {f: 5, c: 38983}, {f: 4, c: 38991}, {f: 3, c: 38997},
michael@0 13329 39002, {f: 2, c: 39004}, {f: 3, c: 39007}, {f: 2, c: 39011}, 39014,
michael@0 13330 {f: 3, c: 39016}, {f: 2, c: 39021}, 39026, 39051, 39054, 39058, 39061,
michael@0 13331 39065, 39075, {f: 5, c: 39081}, 39088, 39090, {f: 2, c: 39092},
michael@0 13332 {f: 5, c: 39095}, {f: 7, c: 39101}, 39109, 39111, {f: 5, c: 39113},
michael@0 13333 {f: 2, c: 39119}, 39124, {f: 2, c: 39126}, {f: 2, c: 39132}, 39137,
michael@0 13334 {f: 4, c: 39139}, 39148, 39150, {f: 2, c: 39152}, 39155, {f: 7, c: 39157},
michael@0 13335 {f: 4, c: 39167}, 39172, {f: 3, c: 39174}, 39179, {f: 2, c: 39182},
michael@0 13336 {f: 4, c: 39188}, {f: 2, c: 39193}, {f: 2, c: 39196}, {f: 2, c: 39199},
michael@0 13337 {f: 6, c: 39202}, {f: 5, c: 39209}, {f: 4, c: 39215}, {f: 3, c: 39220},
michael@0 13338 {f: 4, c: 39224}, 39229, {f: 3, c: 39232}, 39236, {f: 2, c: 39238},
michael@0 13339 {f: 4, c: 39245}, 39251, 39254, {f: 4, c: 39256}, 39261, {f: 3, c: 39263},
michael@0 13340 39268, 39270, 39283, {f: 2, c: 39288}, 39291, 39294, {f: 2, c: 39298},
michael@0 13341 39305, 39308, 39310, {f: 11, c: 39322}, {f: 2, c: 39334}, {f: 3, c: 39337},
michael@0 13342 {f: 2, c: 39343}, 39346, {f: 12, c: 39349}, {f: 14, c: 39362}, 39379,
michael@0 13343 {f: 2, c: 39382}, 39386, 39388, 39390, 39392, {f: 10, c: 39395},
michael@0 13344 {f: 3, c: 39406}, {f: 13, c: 39410}, 39424, {f: 3, c: 39426},
michael@0 13345 {f: 7, c: 39430}, {f: 6, c: 39440}, {f: 2, c: 39447}, {f: 17, c: 39450},
michael@0 13346 39468, 39471, {f: 5, c: 39473}, {f: 5, c: 39481}, 39487, {f: 4, c: 39494},
michael@0 13347 {f: 2, c: 39499}, 39502, {f: 5, c: 39504}, 39510, {f: 2, c: 39512},
michael@0 13348 {f: 3, c: 39516}, {f: 2, c: 39520}, 39523, {f: 4, c: 39526}, 39531, 39538,
michael@0 13349 39555, 39561, {f: 2, c: 39565}, {f: 2, c: 39572}, 39577, 39590,
michael@0 13350 {f: 6, c: 39593}, {f: 4, c: 39602}, 39609, 39611, {f: 3, c: 39613},
michael@0 13351 {f: 2, c: 39619}, {f: 5, c: 39622}, {f: 2, c: 39629}, 39632, 39639,
michael@0 13352 {f: 6, c: 39641}, 39648, {f: 4, c: 39650}, {f: 4, c: 39655}, 39660,
michael@0 13353 {f: 9, c: 39664}, 39674, {f: 7, c: 39676}, {f: 2, c: 39684}, 39687,
michael@0 13354 {f: 4, c: 39689}, 39694, {f: 3, c: 39696}, {f: 6, c: 39700},
michael@0 13355 {f: 4, c: 39707}, {f: 2, c: 39712}, 39716, 39718, 39720, {f: 4, c: 39722},
michael@0 13356 39728, {f: 8, c: 39731}, {f: 4, c: 39741}, 39750, {f: 3, c: 39754}, 39760,
michael@0 13357 {f: 2, c: 39762}, {f: 3, c: 39765}, 39769, {f: 20, c: 39771},
michael@0 13358 {f: 4, c: 39792}, {f: 2, c: 39797}, {f: 9, c: 39800}, 39810,
michael@0 13359 {f: 10, c: 39812}, 39823, {f: 7, c: 39827}, {f: 2, c: 39835},
michael@0 13360 {f: 11, c: 39839}, 39852, {f: 17, c: 39855}, {f: 5, c: 39874}, 39880,
michael@0 13361 {f: 9, c: 39883}, 39893, {f: 4, c: 39895}, 39900, {f: 3, c: 39902}, 39907,
michael@0 13362 {f: 2, c: 39909}, 39913, {f: 4, c: 39916}, {f: 3, c: 39921},
michael@0 13363 {f: 8, c: 39925}, 39934, {f: 8, c: 39936}, {f: 3, c: 39946},
michael@0 13364 {f: 2, c: 39950}, 39953, {f: 12, c: 39956}, {f: 2, c: 39969}, 39972,
michael@0 13365 {f: 2, c: 39974}, {f: 3, c: 39978}, {f: 3, c: 39982}, 39988, 39990, 39992,
michael@0 13366 39994, {f: 2, c: 39996}, {f: 6, c: 39999}, {f: 2, c: 40006},
michael@0 13367 {f: 8, c: 40010}, 40019, 40021, {f: 4, c: 40025}, 40030, {f: 7, c: 40032},
michael@0 13368 {f: 5, c: 40040}, {f: 10, c: 40046}, 40057, 40059, {f: 2, c: 40061}, 40064,
michael@0 13369 {f: 2, c: 40067}, {f: 2, c: 40073}, 40076, 40079, 40083, {f: 4, c: 40086},
michael@0 13370 40093, 40106, 40108, 40111, 40121, {f: 5, c: 40126}, {f: 2, c: 40136},
michael@0 13371 {f: 2, c: 40145}, {f: 2, c: 40154}, {f: 2, c: 40160}, {f: 2, c: 40163},
michael@0 13372 {f: 3, c: 40166}, {f: 2, c: 40170}, {f: 6, c: 40173}, 40181,
michael@0 13373 {f: 15, c: 40183}, 40200, {f: 11, c: 40202}, {f: 5, c: 40214}, 40220,
michael@0 13374 40222, {f: 3, c: 40224}, {f: 2, c: 40228}, 40231, {f: 6, c: 40233},
michael@0 13375 {f: 10, c: 40241}, {f: 3, c: 40252}, {f: 2, c: 40256}, {f: 14, c: 40259},
michael@0 13376 {f: 8, c: 40276}, {f: 2, c: 40286}, {f: 8, c: 40290}, 40299,
michael@0 13377 {f: 2, c: 40301}, {f: 2, c: 40304}, {f: 20, c: 40307}, 40328,
michael@0 13378 {f: 9, c: 40330}, {f: 4, c: 40340}, 40345, {f: 10, c: 40347},
michael@0 13379 {f: 3, c: 40358}, {f: 5, c: 40362}, {f: 4, c: 40368}, {f: 6, c: 40373},
michael@0 13380 {f: 3, c: 40381}, 40385, 40387, {f: 14, c: 40389}, {f: 3, c: 40404}, 40408,
michael@0 13381 {f: 10, c: 40411}, {f: 8, c: 40423}, {f: 2, c: 40432}, {f: 4, c: 40436},
michael@0 13382 {f: 17, c: 40443}, {f: 8, c: 40461}, {f: 4, c: 40470}, 40476, 40484, 40487,
michael@0 13383 40494, 40496, 40500, {f: 2, c: 40507}, 40512, 40525, 40528,
michael@0 13384 {f: 3, c: 40530}, 40534, 40537, 40541, {f: 4, c: 40543}, 40549,
michael@0 13385 {f: 2, c: 40558}, 40562, 40564, {f: 3, c: 40566}, 40571, {f: 2, c: 40576},
michael@0 13386 {f: 4, c: 40579}, {f: 2, c: 40585}, {f: 6, c: 40588}, {f: 3, c: 40596},
michael@0 13387 {f: 5, c: 40600}, 40606, {f: 5, c: 40608}, {f: 2, c: 40615},
michael@0 13388 {f: 5, c: 40618}, {f: 4, c: 40624}, {f: 2, c: 40630}, {f: 2, c: 40633},
michael@0 13389 40636, {f: 4, c: 40639}, [12232, 40643], {f: 4, c: 40645},
michael@0 13390 {f: 2, c: 40650}, 40656, {f: 2, c: 40658}, {f: 3, c: 40661},
michael@0 13391 {f: 2, c: 40665}, 40673, {f: 2, c: 40675}, 40678, {f: 4, c: 40683},
michael@0 13392 {f: 2, c: 40688}, 40691, {f: 2, c: 40693}, 40696, 40698, {f: 9, c: 40704},
michael@0 13393 40714, 40716, 40719, {f: 2, c: 40721}, 40724, 40726, 40728,
michael@0 13394 {f: 6, c: 40730}, 40737, {f: 9, c: 40739}, {f: 2, c: 40749},
michael@0 13395 {f: 7, c: 40752}, 40760, 40762, 40764, {f: 5, c: 40767}, {f: 5, c: 40773},
michael@0 13396 {f: 3, c: 40780}, 40787, {f: 4, c: 40789}, {f: 2, c: 40794},
michael@0 13397 {f: 2, c: 40797}, 40802, {f: 2, c: 40804}, {f: 3, c: 40807}, 40811,
michael@0 13398 {f: 5, c: 40813}, {f: 4, c: 40819}, {f: 7, c: 40824}, {f: 2, c: 40833},
michael@0 13399 {f: 2, c: 40846}, {f: 3, c: 40849}, {f: 3, c: 40854}, {f: 2, c: 40861},
michael@0 13400 {f: 5, c: 40865}, 63788, {f: 3, c: 64013}, 64017, {f: 2, c: 64019}, 64024,
michael@0 13401 {f: 3, c: 64031}, {f: 2, c: 64035}, {f: 3, c: 64039}, 11905,
michael@0 13402 [59414, 131207], [59415, 131209], [59416, 131276], 11908, 13427, 13383,
michael@0 13403 11912, 11915, 59422, 13726, 13850, 13838, 11916, 11927, 14702, 14616,
michael@0 13404 59430, 14799, 14815, 14963, 14800, {f: 2, c: 59435}, 15182, 15470, 15584,
michael@0 13405 11943, [59441, 136663], 59442, 11946, 16470, 16735, 11950, 17207, 11955,
michael@0 13406 {f: 2, c: 11958}, [59451, 141711], 17329, 17324, 11963, 17373, 17622,
michael@0 13407 18017, 17996, [59459, 132361], 18211, 18217, 18300, 18317, 11978, 18759,
michael@0 13408 18810, 18813, {f: 2, c: 18818}, {f: 2, c: 18821}, 18847, 18843, 18871,
michael@0 13409 18870, [59476, 133533], [59477, 147966], 19619, {f: 3, c: 19615}, 19575,
michael@0 13410 19618, {f: 7, c: 19731}, 19886, 59492, {s: 226}, 8364, 165, 0, 0, 12351,
michael@0 13411 {s: 17}, 12436, {s: 14}, 12535, 12537, 12536, 12538, 0, {f: 3, c: 12339},
michael@0 13412 {f: 3, c: 12344}, {f: 3, c: 12586}, {f: 24, c: 12704}, 11904,
michael@0 13413 {f: 2, c: 11906}, {f: 3, c: 11909}, {f: 2, c: 11913}, {f: 10, c: 11917},
michael@0 13414 {f: 2, c: 11928}, {f: 12, c: 11931}, {f: 2, c: 11944}, {f: 3, c: 11947},
michael@0 13415 {f: 4, c: 11951}, {f: 2, c: 11956}, {f: 3, c: 11960}, {f: 14, c: 11964},
michael@0 13416 {f: 41, c: 11979}, {f: 71, c: 13312}, {f: 43, c: 13384},
michael@0 13417 {f: 298, c: 13428}, {f: 111, c: 13727}, {f: 11, c: 13839},
michael@0 13418 {f: 765, c: 13851}, {f: 85, c: 14617}, {f: 96, c: 14703},
michael@0 13419 {f: 14, c: 14801}, {f: 147, c: 14816}, {f: 218, c: 14964},
michael@0 13420 {f: 287, c: 15183}, {f: 113, c: 15471}, {f: 885, c: 15585},
michael@0 13421 {f: 264, c: 16471}, {f: 471, c: 16736}, {f: 116, c: 17208},
michael@0 13422 {f: 4, c: 17325}, {f: 43, c: 17330}, {f: 248, c: 17374},
michael@0 13423 {f: 373, c: 17623}, {f: 20, c: 17997}, {f: 193, c: 18018},
michael@0 13424 {f: 5, c: 18212}, {f: 82, c: 18218}, {f: 16, c: 18301}, {f: 441, c: 18318},
michael@0 13425 {f: 50, c: 18760}, {f: 2, c: 18811}, {f: 4, c: 18814}, 18820,
michael@0 13426 {f: 20, c: 18823}, {f: 3, c: 18844}, {f: 22, c: 18848}, {f: 703, c: 18872},
michael@0 13427 {f: 39, c: 19576}, {f: 111, c: 19620}, {f: 148, c: 19738},
michael@0 13428 {f: 7, c: 19887}]
michael@0 13429 };
michael@0 13430
michael@0 13431
michael@0 13432
michael@0 13433 var ARCFourCipher = (function ARCFourCipherClosure() {
michael@0 13434 function ARCFourCipher(key) {
michael@0 13435 this.a = 0;
michael@0 13436 this.b = 0;
michael@0 13437 var s = new Uint8Array(256);
michael@0 13438 var i, j = 0, tmp, keyLength = key.length;
michael@0 13439 for (i = 0; i < 256; ++i) {
michael@0 13440 s[i] = i;
michael@0 13441 }
michael@0 13442 for (i = 0; i < 256; ++i) {
michael@0 13443 tmp = s[i];
michael@0 13444 j = (j + tmp + key[i % keyLength]) & 0xFF;
michael@0 13445 s[i] = s[j];
michael@0 13446 s[j] = tmp;
michael@0 13447 }
michael@0 13448 this.s = s;
michael@0 13449 }
michael@0 13450
michael@0 13451 ARCFourCipher.prototype = {
michael@0 13452 encryptBlock: function ARCFourCipher_encryptBlock(data) {
michael@0 13453 var i, n = data.length, tmp, tmp2;
michael@0 13454 var a = this.a, b = this.b, s = this.s;
michael@0 13455 var output = new Uint8Array(n);
michael@0 13456 for (i = 0; i < n; ++i) {
michael@0 13457 a = (a + 1) & 0xFF;
michael@0 13458 tmp = s[a];
michael@0 13459 b = (b + tmp) & 0xFF;
michael@0 13460 tmp2 = s[b];
michael@0 13461 s[a] = tmp2;
michael@0 13462 s[b] = tmp;
michael@0 13463 output[i] = data[i] ^ s[(tmp + tmp2) & 0xFF];
michael@0 13464 }
michael@0 13465 this.a = a;
michael@0 13466 this.b = b;
michael@0 13467 return output;
michael@0 13468 }
michael@0 13469 };
michael@0 13470 ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
michael@0 13471
michael@0 13472 return ARCFourCipher;
michael@0 13473 })();
michael@0 13474
michael@0 13475 var calculateMD5 = (function calculateMD5Closure() {
michael@0 13476 var r = new Uint8Array([
michael@0 13477 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
michael@0 13478 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
michael@0 13479 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
michael@0 13480 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]);
michael@0 13481
michael@0 13482 var k = new Int32Array([
michael@0 13483 -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426,
michael@0 13484 -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162,
michael@0 13485 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632,
michael@0 13486 643717713, -373897302, -701558691, 38016083, -660478335, -405537848,
michael@0 13487 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784,
michael@0 13488 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556,
michael@0 13489 -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222,
michael@0 13490 -722521979, 76029189, -640364487, -421815835, 530742520, -995338651,
michael@0 13491 -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606,
michael@0 13492 -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649,
michael@0 13493 -145523070, -1120210379, 718787259, -343485551]);
michael@0 13494
michael@0 13495 function hash(data, offset, length) {
michael@0 13496 var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878;
michael@0 13497 // pre-processing
michael@0 13498 var paddedLength = (length + 72) & ~63; // data + 9 extra bytes
michael@0 13499 var padded = new Uint8Array(paddedLength);
michael@0 13500 var i, j, n;
michael@0 13501 for (i = 0; i < length; ++i) {
michael@0 13502 padded[i] = data[offset++];
michael@0 13503 }
michael@0 13504 padded[i++] = 0x80;
michael@0 13505 n = paddedLength - 8;
michael@0 13506 while (i < n) {
michael@0 13507 padded[i++] = 0;
michael@0 13508 }
michael@0 13509 padded[i++] = (length << 3) & 0xFF;
michael@0 13510 padded[i++] = (length >> 5) & 0xFF;
michael@0 13511 padded[i++] = (length >> 13) & 0xFF;
michael@0 13512 padded[i++] = (length >> 21) & 0xFF;
michael@0 13513 padded[i++] = (length >>> 29) & 0xFF;
michael@0 13514 padded[i++] = 0;
michael@0 13515 padded[i++] = 0;
michael@0 13516 padded[i++] = 0;
michael@0 13517 // chunking
michael@0 13518 // TODO ArrayBuffer ?
michael@0 13519 var w = new Int32Array(16);
michael@0 13520 for (i = 0; i < paddedLength;) {
michael@0 13521 for (j = 0; j < 16; ++j, i += 4) {
michael@0 13522 w[j] = (padded[i] | (padded[i + 1] << 8) |
michael@0 13523 (padded[i + 2] << 16) | (padded[i + 3] << 24));
michael@0 13524 }
michael@0 13525 var a = h0, b = h1, c = h2, d = h3, f, g;
michael@0 13526 for (j = 0; j < 64; ++j) {
michael@0 13527 if (j < 16) {
michael@0 13528 f = (b & c) | ((~b) & d);
michael@0 13529 g = j;
michael@0 13530 } else if (j < 32) {
michael@0 13531 f = (d & b) | ((~d) & c);
michael@0 13532 g = (5 * j + 1) & 15;
michael@0 13533 } else if (j < 48) {
michael@0 13534 f = b ^ c ^ d;
michael@0 13535 g = (3 * j + 5) & 15;
michael@0 13536 } else {
michael@0 13537 f = c ^ (b | (~d));
michael@0 13538 g = (7 * j) & 15;
michael@0 13539 }
michael@0 13540 var tmp = d, rotateArg = (a + f + k[j] + w[g]) | 0, rotate = r[j];
michael@0 13541 d = c;
michael@0 13542 c = b;
michael@0 13543 b = (b + ((rotateArg << rotate) | (rotateArg >>> (32 - rotate)))) | 0;
michael@0 13544 a = tmp;
michael@0 13545 }
michael@0 13546 h0 = (h0 + a) | 0;
michael@0 13547 h1 = (h1 + b) | 0;
michael@0 13548 h2 = (h2 + c) | 0;
michael@0 13549 h3 = (h3 + d) | 0;
michael@0 13550 }
michael@0 13551 return new Uint8Array([
michael@0 13552 h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >>> 24) & 0xFF,
michael@0 13553 h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >>> 24) & 0xFF,
michael@0 13554 h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >>> 24) & 0xFF,
michael@0 13555 h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >>> 24) & 0xFF
michael@0 13556 ]);
michael@0 13557 }
michael@0 13558 return hash;
michael@0 13559 })();
michael@0 13560
michael@0 13561 var NullCipher = (function NullCipherClosure() {
michael@0 13562 function NullCipher() {}
michael@0 13563
michael@0 13564 NullCipher.prototype = {
michael@0 13565 decryptBlock: function NullCipher_decryptBlock(data) {
michael@0 13566 return data;
michael@0 13567 }
michael@0 13568 };
michael@0 13569
michael@0 13570 return NullCipher;
michael@0 13571 })();
michael@0 13572
michael@0 13573 var AES128Cipher = (function AES128CipherClosure() {
michael@0 13574 var rcon = new Uint8Array([
michael@0 13575 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
michael@0 13576 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
michael@0 13577 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
michael@0 13578 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
michael@0 13579 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
michael@0 13580 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,
michael@0 13581 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
michael@0 13582 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
michael@0 13583 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,
michael@0 13584 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e,
michael@0 13585 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
michael@0 13586 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
michael@0 13587 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02,
michael@0 13588 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
michael@0 13589 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
michael@0 13590 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
michael@0 13591 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb,
michael@0 13592 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
michael@0 13593 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
michael@0 13594 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
michael@0 13595 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
michael@0 13596 0x74, 0xe8, 0xcb, 0x8d]);
michael@0 13597
michael@0 13598 var s = new Uint8Array([
michael@0 13599 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
michael@0 13600 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
michael@0 13601 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
michael@0 13602 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
michael@0 13603 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
michael@0 13604 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
michael@0 13605 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
michael@0 13606 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
michael@0 13607 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
michael@0 13608 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
michael@0 13609 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
michael@0 13610 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
michael@0 13611 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
michael@0 13612 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
michael@0 13613 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
michael@0 13614 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
michael@0 13615 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
michael@0 13616 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
michael@0 13617 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
michael@0 13618 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
michael@0 13619 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
michael@0 13620 0xb0, 0x54, 0xbb, 0x16]);
michael@0 13621
michael@0 13622 var inv_s = new Uint8Array([
michael@0 13623 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
michael@0 13624 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
michael@0 13625 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
michael@0 13626 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
michael@0 13627 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
michael@0 13628 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
michael@0 13629 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
michael@0 13630 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
michael@0 13631 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
michael@0 13632 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
michael@0 13633 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
michael@0 13634 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
michael@0 13635 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
michael@0 13636 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
michael@0 13637 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
michael@0 13638 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
michael@0 13639 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
michael@0 13640 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
michael@0 13641 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
michael@0 13642 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
michael@0 13643 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
michael@0 13644 0x55, 0x21, 0x0c, 0x7d]);
michael@0 13645
michael@0 13646 var mix = new Uint32Array([
michael@0 13647 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927,
michael@0 13648 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45,
michael@0 13649 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb,
michael@0 13650 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381,
michael@0 13651 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf,
michael@0 13652 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66,
michael@0 13653 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28,
michael@0 13654 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012,
michael@0 13655 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
michael@0 13656 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e,
michael@0 13657 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd,
michael@0 13658 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7,
michael@0 13659 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89,
michael@0 13660 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b,
michael@0 13661 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815,
michael@0 13662 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f,
michael@0 13663 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa,
michael@0 13664 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8,
michael@0 13665 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36,
michael@0 13666 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
michael@0 13667 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742,
michael@0 13668 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea,
michael@0 13669 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4,
michael@0 13670 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e,
michael@0 13671 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360,
michael@0 13672 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502,
michael@0 13673 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87,
michael@0 13674 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd,
michael@0 13675 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3,
michael@0 13676 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621,
michael@0 13677 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
michael@0 13678 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55,
michael@0 13679 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26,
michael@0 13680 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844,
michael@0 13681 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba,
michael@0 13682 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480,
michael@0 13683 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce,
michael@0 13684 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67,
michael@0 13685 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929,
michael@0 13686 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713,
michael@0 13687 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed,
michael@0 13688 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
michael@0 13689 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
michael@0 13690
michael@0 13691 function expandKey128(cipherKey) {
michael@0 13692 var b = 176, result = new Uint8Array(b);
michael@0 13693 result.set(cipherKey);
michael@0 13694 for (var j = 16, i = 1; j < b; ++i) {
michael@0 13695 // RotWord
michael@0 13696 var t1 = result[j - 3], t2 = result[j - 2],
michael@0 13697 t3 = result[j - 1], t4 = result[j - 4];
michael@0 13698 // SubWord
michael@0 13699 t1 = s[t1]; t2 = s[t2]; t3 = s[t3]; t4 = s[t4];
michael@0 13700 // Rcon
michael@0 13701 t1 = t1 ^ rcon[i];
michael@0 13702 for (var n = 0; n < 4; ++n) {
michael@0 13703 result[j] = (t1 ^= result[j - 16]); j++;
michael@0 13704 result[j] = (t2 ^= result[j - 16]); j++;
michael@0 13705 result[j] = (t3 ^= result[j - 16]); j++;
michael@0 13706 result[j] = (t4 ^= result[j - 16]); j++;
michael@0 13707 }
michael@0 13708 }
michael@0 13709 return result;
michael@0 13710 }
michael@0 13711
michael@0 13712 function decrypt128(input, key) {
michael@0 13713 var state = new Uint8Array(16);
michael@0 13714 state.set(input);
michael@0 13715 var i, j, k;
michael@0 13716 var t, u, v;
michael@0 13717 // AddRoundKey
michael@0 13718 for (j = 0, k = 160; j < 16; ++j, ++k) {
michael@0 13719 state[j] ^= key[k];
michael@0 13720 }
michael@0 13721 for (i = 9; i >= 1; --i) {
michael@0 13722 // InvShiftRows
michael@0 13723 t = state[13]; state[13] = state[9]; state[9] = state[5];
michael@0 13724 state[5] = state[1]; state[1] = t;
michael@0 13725 t = state[14]; u = state[10]; state[14] = state[6];
michael@0 13726 state[10] = state[2]; state[6] = t; state[2] = u;
michael@0 13727 t = state[15]; u = state[11]; v = state[7]; state[15] = state[3];
michael@0 13728 state[11] = t; state[7] = u; state[3] = v;
michael@0 13729 // InvSubBytes
michael@0 13730 for (j = 0; j < 16; ++j) {
michael@0 13731 state[j] = inv_s[state[j]];
michael@0 13732 }
michael@0 13733 // AddRoundKey
michael@0 13734 for (j = 0, k = i * 16; j < 16; ++j, ++k) {
michael@0 13735 state[j] ^= key[k];
michael@0 13736 }
michael@0 13737 // InvMixColumns
michael@0 13738 for (j = 0; j < 16; j += 4) {
michael@0 13739 var s0 = mix[state[j]], s1 = mix[state[j + 1]],
michael@0 13740 s2 = mix[state[j + 2]], s3 = mix[state[j + 3]];
michael@0 13741 t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^
michael@0 13742 (s3 >>> 24) ^ (s3 << 8));
michael@0 13743 state[j] = (t >>> 24) & 0xFF;
michael@0 13744 state[j + 1] = (t >> 16) & 0xFF;
michael@0 13745 state[j + 2] = (t >> 8) & 0xFF;
michael@0 13746 state[j + 3] = t & 0xFF;
michael@0 13747 }
michael@0 13748 }
michael@0 13749 // InvShiftRows
michael@0 13750 t = state[13]; state[13] = state[9]; state[9] = state[5];
michael@0 13751 state[5] = state[1]; state[1] = t;
michael@0 13752 t = state[14]; u = state[10]; state[14] = state[6];
michael@0 13753 state[10] = state[2]; state[6] = t; state[2] = u;
michael@0 13754 t = state[15]; u = state[11]; v = state[7]; state[15] = state[3];
michael@0 13755 state[11] = t; state[7] = u; state[3] = v;
michael@0 13756 for (j = 0; j < 16; ++j) {
michael@0 13757 // InvSubBytes
michael@0 13758 state[j] = inv_s[state[j]];
michael@0 13759 // AddRoundKey
michael@0 13760 state[j] ^= key[j];
michael@0 13761 }
michael@0 13762 return state;
michael@0 13763 }
michael@0 13764
michael@0 13765 function AES128Cipher(key) {
michael@0 13766 this.key = expandKey128(key);
michael@0 13767 this.buffer = new Uint8Array(16);
michael@0 13768 this.bufferPosition = 0;
michael@0 13769 }
michael@0 13770
michael@0 13771 function decryptBlock2(data, finalize) {
michael@0 13772 var i, j, ii, sourceLength = data.length,
michael@0 13773 buffer = this.buffer, bufferLength = this.bufferPosition,
michael@0 13774 result = [], iv = this.iv;
michael@0 13775 for (i = 0; i < sourceLength; ++i) {
michael@0 13776 buffer[bufferLength] = data[i];
michael@0 13777 ++bufferLength;
michael@0 13778 if (bufferLength < 16) {
michael@0 13779 continue;
michael@0 13780 }
michael@0 13781 // buffer is full, decrypting
michael@0 13782 var plain = decrypt128(buffer, this.key);
michael@0 13783 // xor-ing the IV vector to get plain text
michael@0 13784 for (j = 0; j < 16; ++j) {
michael@0 13785 plain[j] ^= iv[j];
michael@0 13786 }
michael@0 13787 iv = buffer;
michael@0 13788 result.push(plain);
michael@0 13789 buffer = new Uint8Array(16);
michael@0 13790 bufferLength = 0;
michael@0 13791 }
michael@0 13792 // saving incomplete buffer
michael@0 13793 this.buffer = buffer;
michael@0 13794 this.bufferLength = bufferLength;
michael@0 13795 this.iv = iv;
michael@0 13796 if (result.length === 0) {
michael@0 13797 return new Uint8Array([]);
michael@0 13798 }
michael@0 13799 // combining plain text blocks into one
michael@0 13800 var outputLength = 16 * result.length;
michael@0 13801 if (finalize) {
michael@0 13802 // undo a padding that is described in RFC 2898
michael@0 13803 var lastBlock = result[result.length - 1];
michael@0 13804 outputLength -= lastBlock[15];
michael@0 13805 result[result.length - 1] = lastBlock.subarray(0, 16 - lastBlock[15]);
michael@0 13806 }
michael@0 13807 var output = new Uint8Array(outputLength);
michael@0 13808 for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
michael@0 13809 output.set(result[i], j);
michael@0 13810 }
michael@0 13811 return output;
michael@0 13812 }
michael@0 13813
michael@0 13814 AES128Cipher.prototype = {
michael@0 13815 decryptBlock: function AES128Cipher_decryptBlock(data, finalize) {
michael@0 13816 var i, sourceLength = data.length;
michael@0 13817 var buffer = this.buffer, bufferLength = this.bufferPosition;
michael@0 13818 // waiting for IV values -- they are at the start of the stream
michael@0 13819 for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {
michael@0 13820 buffer[bufferLength] = data[i];
michael@0 13821 }
michael@0 13822 if (bufferLength < 16) {
michael@0 13823 // need more data
michael@0 13824 this.bufferLength = bufferLength;
michael@0 13825 return new Uint8Array([]);
michael@0 13826 }
michael@0 13827 this.iv = buffer;
michael@0 13828 this.buffer = new Uint8Array(16);
michael@0 13829 this.bufferLength = 0;
michael@0 13830 // starting decryption
michael@0 13831 this.decryptBlock = decryptBlock2;
michael@0 13832 return this.decryptBlock(data.subarray(16), finalize);
michael@0 13833 }
michael@0 13834 };
michael@0 13835
michael@0 13836 return AES128Cipher;
michael@0 13837 })();
michael@0 13838
michael@0 13839 var CipherTransform = (function CipherTransformClosure() {
michael@0 13840 function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
michael@0 13841 this.stringCipherConstructor = stringCipherConstructor;
michael@0 13842 this.streamCipherConstructor = streamCipherConstructor;
michael@0 13843 }
michael@0 13844 CipherTransform.prototype = {
michael@0 13845 createStream: function CipherTransform_createStream(stream, length) {
michael@0 13846 var cipher = new this.streamCipherConstructor();
michael@0 13847 return new DecryptStream(stream, length,
michael@0 13848 function cipherTransformDecryptStream(data, finalize) {
michael@0 13849 return cipher.decryptBlock(data, finalize);
michael@0 13850 }
michael@0 13851 );
michael@0 13852 },
michael@0 13853 decryptString: function CipherTransform_decryptString(s) {
michael@0 13854 var cipher = new this.stringCipherConstructor();
michael@0 13855 var data = stringToBytes(s);
michael@0 13856 data = cipher.decryptBlock(data, true);
michael@0 13857 return bytesToString(data);
michael@0 13858 }
michael@0 13859 };
michael@0 13860 return CipherTransform;
michael@0 13861 })();
michael@0 13862
michael@0 13863 var CipherTransformFactory = (function CipherTransformFactoryClosure() {
michael@0 13864 var defaultPasswordBytes = new Uint8Array([
michael@0 13865 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
michael@0 13866 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
michael@0 13867 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
michael@0 13868 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
michael@0 13869
michael@0 13870 function prepareKeyData(fileId, password, ownerPassword, userPassword,
michael@0 13871 flags, revision, keyLength, encryptMetadata) {
michael@0 13872 var hashDataSize = 40 + ownerPassword.length + fileId.length;
michael@0 13873 var hashData = new Uint8Array(hashDataSize), i = 0, j, n;
michael@0 13874 if (password) {
michael@0 13875 n = Math.min(32, password.length);
michael@0 13876 for (; i < n; ++i) {
michael@0 13877 hashData[i] = password[i];
michael@0 13878 }
michael@0 13879 }
michael@0 13880 j = 0;
michael@0 13881 while (i < 32) {
michael@0 13882 hashData[i++] = defaultPasswordBytes[j++];
michael@0 13883 }
michael@0 13884 // as now the padded password in the hashData[0..i]
michael@0 13885 for (j = 0, n = ownerPassword.length; j < n; ++j) {
michael@0 13886 hashData[i++] = ownerPassword[j];
michael@0 13887 }
michael@0 13888 hashData[i++] = flags & 0xFF;
michael@0 13889 hashData[i++] = (flags >> 8) & 0xFF;
michael@0 13890 hashData[i++] = (flags >> 16) & 0xFF;
michael@0 13891 hashData[i++] = (flags >>> 24) & 0xFF;
michael@0 13892 for (j = 0, n = fileId.length; j < n; ++j) {
michael@0 13893 hashData[i++] = fileId[j];
michael@0 13894 }
michael@0 13895 if (revision >= 4 && !encryptMetadata) {
michael@0 13896 hashData[i++] = 0xFF;
michael@0 13897 hashData[i++] = 0xFF;
michael@0 13898 hashData[i++] = 0xFF;
michael@0 13899 hashData[i++] = 0xFF;
michael@0 13900 }
michael@0 13901 var hash = calculateMD5(hashData, 0, i);
michael@0 13902 var keyLengthInBytes = keyLength >> 3;
michael@0 13903 if (revision >= 3) {
michael@0 13904 for (j = 0; j < 50; ++j) {
michael@0 13905 hash = calculateMD5(hash, 0, keyLengthInBytes);
michael@0 13906 }
michael@0 13907 }
michael@0 13908 var encryptionKey = hash.subarray(0, keyLengthInBytes);
michael@0 13909 var cipher, checkData;
michael@0 13910
michael@0 13911 if (revision >= 3) {
michael@0 13912 for (i = 0; i < 32; ++i) {
michael@0 13913 hashData[i] = defaultPasswordBytes[i];
michael@0 13914 }
michael@0 13915 for (j = 0, n = fileId.length; j < n; ++j) {
michael@0 13916 hashData[i++] = fileId[j];
michael@0 13917 }
michael@0 13918 cipher = new ARCFourCipher(encryptionKey);
michael@0 13919 checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
michael@0 13920 n = encryptionKey.length;
michael@0 13921 var derivedKey = new Uint8Array(n), k;
michael@0 13922 for (j = 1; j <= 19; ++j) {
michael@0 13923 for (k = 0; k < n; ++k) {
michael@0 13924 derivedKey[k] = encryptionKey[k] ^ j;
michael@0 13925 }
michael@0 13926 cipher = new ARCFourCipher(derivedKey);
michael@0 13927 checkData = cipher.encryptBlock(checkData);
michael@0 13928 }
michael@0 13929 for (j = 0, n = checkData.length; j < n; ++j) {
michael@0 13930 if (userPassword[j] != checkData[j]) {
michael@0 13931 return null;
michael@0 13932 }
michael@0 13933 }
michael@0 13934 } else {
michael@0 13935 cipher = new ARCFourCipher(encryptionKey);
michael@0 13936 checkData = cipher.encryptBlock(defaultPasswordBytes);
michael@0 13937 for (j = 0, n = checkData.length; j < n; ++j) {
michael@0 13938 if (userPassword[j] != checkData[j]) {
michael@0 13939 return null;
michael@0 13940 }
michael@0 13941 }
michael@0 13942 }
michael@0 13943 return encryptionKey;
michael@0 13944 }
michael@0 13945
michael@0 13946 function decodeUserPassword(password, ownerPassword, revision, keyLength) {
michael@0 13947 var hashData = new Uint8Array(32), i = 0, j, n;
michael@0 13948 n = Math.min(32, password.length);
michael@0 13949 for (; i < n; ++i) {
michael@0 13950 hashData[i] = password[i];
michael@0 13951 }
michael@0 13952 j = 0;
michael@0 13953 while (i < 32) {
michael@0 13954 hashData[i++] = defaultPasswordBytes[j++];
michael@0 13955 }
michael@0 13956 var hash = calculateMD5(hashData, 0, i);
michael@0 13957 var keyLengthInBytes = keyLength >> 3;
michael@0 13958 if (revision >= 3) {
michael@0 13959 for (j = 0; j < 50; ++j) {
michael@0 13960 hash = calculateMD5(hash, 0, hash.length);
michael@0 13961 }
michael@0 13962 }
michael@0 13963
michael@0 13964 var cipher, userPassword;
michael@0 13965 if (revision >= 3) {
michael@0 13966 userPassword = ownerPassword;
michael@0 13967 var derivedKey = new Uint8Array(keyLengthInBytes), k;
michael@0 13968 for (j = 19; j >= 0; j--) {
michael@0 13969 for (k = 0; k < keyLengthInBytes; ++k) {
michael@0 13970 derivedKey[k] = hash[k] ^ j;
michael@0 13971 }
michael@0 13972 cipher = new ARCFourCipher(derivedKey);
michael@0 13973 userPassword = cipher.encryptBlock(userPassword);
michael@0 13974 }
michael@0 13975 } else {
michael@0 13976 cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes));
michael@0 13977 userPassword = cipher.encryptBlock(ownerPassword);
michael@0 13978 }
michael@0 13979 return userPassword;
michael@0 13980 }
michael@0 13981
michael@0 13982 var identityName = Name.get('Identity');
michael@0 13983
michael@0 13984 function CipherTransformFactory(dict, fileId, password) {
michael@0 13985 var filter = dict.get('Filter');
michael@0 13986 if (!isName(filter) || filter.name != 'Standard') {
michael@0 13987 error('unknown encryption method');
michael@0 13988 }
michael@0 13989 this.dict = dict;
michael@0 13990 var algorithm = dict.get('V');
michael@0 13991 if (!isInt(algorithm) ||
michael@0 13992 (algorithm != 1 && algorithm != 2 && algorithm != 4)) {
michael@0 13993 error('unsupported encryption algorithm');
michael@0 13994 }
michael@0 13995 this.algorithm = algorithm;
michael@0 13996 var keyLength = dict.get('Length') || 40;
michael@0 13997 if (!isInt(keyLength) ||
michael@0 13998 keyLength < 40 || (keyLength % 8) !== 0) {
michael@0 13999 error('invalid key length');
michael@0 14000 }
michael@0 14001
michael@0 14002 // prepare keys
michael@0 14003 var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32);
michael@0 14004 var userPassword = stringToBytes(dict.get('U')).subarray(0, 32);
michael@0 14005 var flags = dict.get('P');
michael@0 14006 var revision = dict.get('R');
michael@0 14007 var encryptMetadata = (algorithm == 4 && // meaningful when V is 4
michael@0 14008 dict.get('EncryptMetadata') !== false); // makes true as default value
michael@0 14009 this.encryptMetadata = encryptMetadata;
michael@0 14010
michael@0 14011 var fileIdBytes = stringToBytes(fileId);
michael@0 14012 var passwordBytes;
michael@0 14013 if (password) {
michael@0 14014 passwordBytes = stringToBytes(password);
michael@0 14015 }
michael@0 14016
michael@0 14017 var encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
michael@0 14018 ownerPassword, userPassword, flags,
michael@0 14019 revision, keyLength, encryptMetadata);
michael@0 14020 if (!encryptionKey && !password) {
michael@0 14021 throw new PasswordException('No password given',
michael@0 14022 PasswordResponses.NEED_PASSWORD);
michael@0 14023 } else if (!encryptionKey && password) {
michael@0 14024 // Attempting use the password as an owner password
michael@0 14025 var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword,
michael@0 14026 revision, keyLength);
michael@0 14027 encryptionKey = prepareKeyData(fileIdBytes, decodedPassword,
michael@0 14028 ownerPassword, userPassword, flags,
michael@0 14029 revision, keyLength, encryptMetadata);
michael@0 14030 }
michael@0 14031
michael@0 14032 if (!encryptionKey) {
michael@0 14033 throw new PasswordException('Incorrect Password',
michael@0 14034 PasswordResponses.INCORRECT_PASSWORD);
michael@0 14035 }
michael@0 14036
michael@0 14037 this.encryptionKey = encryptionKey;
michael@0 14038
michael@0 14039 if (algorithm == 4) {
michael@0 14040 this.cf = dict.get('CF');
michael@0 14041 this.stmf = dict.get('StmF') || identityName;
michael@0 14042 this.strf = dict.get('StrF') || identityName;
michael@0 14043 this.eff = dict.get('EFF') || this.strf;
michael@0 14044 }
michael@0 14045 }
michael@0 14046
michael@0 14047 function buildObjectKey(num, gen, encryptionKey, isAes) {
michael@0 14048 var key = new Uint8Array(encryptionKey.length + 9), i, n;
michael@0 14049 for (i = 0, n = encryptionKey.length; i < n; ++i) {
michael@0 14050 key[i] = encryptionKey[i];
michael@0 14051 }
michael@0 14052 key[i++] = num & 0xFF;
michael@0 14053 key[i++] = (num >> 8) & 0xFF;
michael@0 14054 key[i++] = (num >> 16) & 0xFF;
michael@0 14055 key[i++] = gen & 0xFF;
michael@0 14056 key[i++] = (gen >> 8) & 0xFF;
michael@0 14057 if (isAes) {
michael@0 14058 key[i++] = 0x73;
michael@0 14059 key[i++] = 0x41;
michael@0 14060 key[i++] = 0x6C;
michael@0 14061 key[i++] = 0x54;
michael@0 14062 }
michael@0 14063 var hash = calculateMD5(key, 0, i);
michael@0 14064 return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
michael@0 14065 }
michael@0 14066
michael@0 14067 function buildCipherConstructor(cf, name, num, gen, key) {
michael@0 14068 var cryptFilter = cf.get(name.name);
michael@0 14069 var cfm;
michael@0 14070 if (cryptFilter !== null && cryptFilter !== undefined) {
michael@0 14071 cfm = cryptFilter.get('CFM');
michael@0 14072 }
michael@0 14073 if (!cfm || cfm.name == 'None') {
michael@0 14074 return function cipherTransformFactoryBuildCipherConstructorNone() {
michael@0 14075 return new NullCipher();
michael@0 14076 };
michael@0 14077 }
michael@0 14078 if ('V2' == cfm.name) {
michael@0 14079 return function cipherTransformFactoryBuildCipherConstructorV2() {
michael@0 14080 return new ARCFourCipher(buildObjectKey(num, gen, key, false));
michael@0 14081 };
michael@0 14082 }
michael@0 14083 if ('AESV2' == cfm.name) {
michael@0 14084 return function cipherTransformFactoryBuildCipherConstructorAESV2() {
michael@0 14085 return new AES128Cipher(buildObjectKey(num, gen, key, true));
michael@0 14086 };
michael@0 14087 }
michael@0 14088 error('Unknown crypto method');
michael@0 14089 }
michael@0 14090
michael@0 14091 CipherTransformFactory.prototype = {
michael@0 14092 createCipherTransform:
michael@0 14093 function CipherTransformFactory_createCipherTransform(num, gen) {
michael@0 14094 if (this.algorithm == 4) {
michael@0 14095 return new CipherTransform(
michael@0 14096 buildCipherConstructor(this.cf, this.stmf,
michael@0 14097 num, gen, this.encryptionKey),
michael@0 14098 buildCipherConstructor(this.cf, this.strf,
michael@0 14099 num, gen, this.encryptionKey));
michael@0 14100 }
michael@0 14101 // algorithms 1 and 2
michael@0 14102 var key = buildObjectKey(num, gen, this.encryptionKey, false);
michael@0 14103 var cipherConstructor = function buildCipherCipherConstructor() {
michael@0 14104 return new ARCFourCipher(key);
michael@0 14105 };
michael@0 14106 return new CipherTransform(cipherConstructor, cipherConstructor);
michael@0 14107 }
michael@0 14108 };
michael@0 14109
michael@0 14110 return CipherTransformFactory;
michael@0 14111 })();
michael@0 14112
michael@0 14113
michael@0 14114
michael@0 14115 var PatternType = {
michael@0 14116 FUNCTION_BASED: 1,
michael@0 14117 AXIAL: 2,
michael@0 14118 RADIAL: 3,
michael@0 14119 FREE_FORM_MESH: 4,
michael@0 14120 LATTICE_FORM_MESH: 5,
michael@0 14121 COONS_PATCH_MESH: 6,
michael@0 14122 TENSOR_PATCH_MESH: 7
michael@0 14123 };
michael@0 14124
michael@0 14125 var Pattern = (function PatternClosure() {
michael@0 14126 // Constructor should define this.getPattern
michael@0 14127 function Pattern() {
michael@0 14128 error('should not call Pattern constructor');
michael@0 14129 }
michael@0 14130
michael@0 14131 Pattern.prototype = {
michael@0 14132 // Input: current Canvas context
michael@0 14133 // Output: the appropriate fillStyle or strokeStyle
michael@0 14134 getPattern: function Pattern_getPattern(ctx) {
michael@0 14135 error('Should not call Pattern.getStyle: ' + ctx);
michael@0 14136 }
michael@0 14137 };
michael@0 14138
michael@0 14139 Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
michael@0 14140 res) {
michael@0 14141
michael@0 14142 var dict = isStream(shading) ? shading.dict : shading;
michael@0 14143 var type = dict.get('ShadingType');
michael@0 14144
michael@0 14145 switch (type) {
michael@0 14146 case PatternType.AXIAL:
michael@0 14147 case PatternType.RADIAL:
michael@0 14148 // Both radial and axial shadings are handled by RadialAxial shading.
michael@0 14149 return new Shadings.RadialAxial(dict, matrix, xref, res);
michael@0 14150 case PatternType.FREE_FORM_MESH:
michael@0 14151 case PatternType.LATTICE_FORM_MESH:
michael@0 14152 case PatternType.COONS_PATCH_MESH:
michael@0 14153 case PatternType.TENSOR_PATCH_MESH:
michael@0 14154 return new Shadings.Mesh(shading, matrix, xref, res);
michael@0 14155 default:
michael@0 14156 UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
michael@0 14157 return new Shadings.Dummy();
michael@0 14158 }
michael@0 14159 };
michael@0 14160 return Pattern;
michael@0 14161 })();
michael@0 14162
michael@0 14163 var Shadings = {};
michael@0 14164
michael@0 14165 // A small number to offset the first/last color stops so we can insert ones to
michael@0 14166 // support extend. Number.MIN_VALUE appears to be too small and breaks the
michael@0 14167 // extend. 1e-7 works in FF but chrome seems to use an even smaller sized number
michael@0 14168 // internally so we have to go bigger.
michael@0 14169 Shadings.SMALL_NUMBER = 1e-2;
michael@0 14170
michael@0 14171 // Radial and axial shading have very similar implementations
michael@0 14172 // If needed, the implementations can be broken into two classes
michael@0 14173 Shadings.RadialAxial = (function RadialAxialClosure() {
michael@0 14174 function RadialAxial(dict, matrix, xref, res) {
michael@0 14175 this.matrix = matrix;
michael@0 14176 this.coordsArr = dict.get('Coords');
michael@0 14177 this.shadingType = dict.get('ShadingType');
michael@0 14178 this.type = 'Pattern';
michael@0 14179 var cs = dict.get('ColorSpace', 'CS');
michael@0 14180 cs = ColorSpace.parse(cs, xref, res);
michael@0 14181 this.cs = cs;
michael@0 14182
michael@0 14183 var t0 = 0.0, t1 = 1.0;
michael@0 14184 if (dict.has('Domain')) {
michael@0 14185 var domainArr = dict.get('Domain');
michael@0 14186 t0 = domainArr[0];
michael@0 14187 t1 = domainArr[1];
michael@0 14188 }
michael@0 14189
michael@0 14190 var extendStart = false, extendEnd = false;
michael@0 14191 if (dict.has('Extend')) {
michael@0 14192 var extendArr = dict.get('Extend');
michael@0 14193 extendStart = extendArr[0];
michael@0 14194 extendEnd = extendArr[1];
michael@0 14195 }
michael@0 14196
michael@0 14197 if (this.shadingType === PatternType.RADIAL &&
michael@0 14198 (!extendStart || !extendEnd)) {
michael@0 14199 // Radial gradient only currently works if either circle is fully within
michael@0 14200 // the other circle.
michael@0 14201 var x1 = this.coordsArr[0];
michael@0 14202 var y1 = this.coordsArr[1];
michael@0 14203 var r1 = this.coordsArr[2];
michael@0 14204 var x2 = this.coordsArr[3];
michael@0 14205 var y2 = this.coordsArr[4];
michael@0 14206 var r2 = this.coordsArr[5];
michael@0 14207 var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
michael@0 14208 if (r1 <= r2 + distance &&
michael@0 14209 r2 <= r1 + distance) {
michael@0 14210 warn('Unsupported radial gradient.');
michael@0 14211 }
michael@0 14212 }
michael@0 14213
michael@0 14214 this.extendStart = extendStart;
michael@0 14215 this.extendEnd = extendEnd;
michael@0 14216
michael@0 14217 var fnObj = dict.get('Function');
michael@0 14218 var fn;
michael@0 14219 if (isArray(fnObj)) {
michael@0 14220 var fnArray = [];
michael@0 14221 for (var j = 0, jj = fnObj.length; j < jj; j++) {
michael@0 14222 var obj = xref.fetchIfRef(fnObj[j]);
michael@0 14223 if (!isPDFFunction(obj)) {
michael@0 14224 error('Invalid function');
michael@0 14225 }
michael@0 14226 fnArray.push(PDFFunction.parse(xref, obj));
michael@0 14227 }
michael@0 14228 fn = function radialAxialColorFunction(arg) {
michael@0 14229 var out = [];
michael@0 14230 for (var i = 0, ii = fnArray.length; i < ii; i++) {
michael@0 14231 out.push(fnArray[i](arg)[0]);
michael@0 14232 }
michael@0 14233 return out;
michael@0 14234 };
michael@0 14235 } else {
michael@0 14236 if (!isPDFFunction(fnObj)) {
michael@0 14237 error('Invalid function');
michael@0 14238 }
michael@0 14239 fn = PDFFunction.parse(xref, fnObj);
michael@0 14240 }
michael@0 14241
michael@0 14242 // 10 samples seems good enough for now, but probably won't work
michael@0 14243 // if there are sharp color changes. Ideally, we would implement
michael@0 14244 // the spec faithfully and add lossless optimizations.
michael@0 14245 var diff = t1 - t0;
michael@0 14246 var step = diff / 10;
michael@0 14247
michael@0 14248 var colorStops = this.colorStops = [];
michael@0 14249
michael@0 14250 // Protect against bad domains so we don't end up in an infinte loop below.
michael@0 14251 if (t0 >= t1 || step <= 0) {
michael@0 14252 // Acrobat doesn't seem to handle these cases so we'll ignore for
michael@0 14253 // now.
michael@0 14254 info('Bad shading domain.');
michael@0 14255 return;
michael@0 14256 }
michael@0 14257
michael@0 14258 var rgbColor;
michael@0 14259 for (var i = t0; i <= t1; i += step) {
michael@0 14260 rgbColor = cs.getRgb(fn([i]), 0);
michael@0 14261 var cssColor = Util.makeCssRgb(rgbColor);
michael@0 14262 colorStops.push([(i - t0) / diff, cssColor]);
michael@0 14263 }
michael@0 14264
michael@0 14265 var background = 'transparent';
michael@0 14266 if (dict.has('Background')) {
michael@0 14267 rgbColor = cs.getRgb(dict.get('Background'), 0);
michael@0 14268 background = Util.makeCssRgb(rgbColor);
michael@0 14269 }
michael@0 14270
michael@0 14271 if (!extendStart) {
michael@0 14272 // Insert a color stop at the front and offset the first real color stop
michael@0 14273 // so it doesn't conflict with the one we insert.
michael@0 14274 colorStops.unshift([0, background]);
michael@0 14275 colorStops[1][0] += Shadings.SMALL_NUMBER;
michael@0 14276 }
michael@0 14277 if (!extendEnd) {
michael@0 14278 // Same idea as above in extendStart but for the end.
michael@0 14279 colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
michael@0 14280 colorStops.push([1, background]);
michael@0 14281 }
michael@0 14282
michael@0 14283 this.colorStops = colorStops;
michael@0 14284 }
michael@0 14285
michael@0 14286 RadialAxial.prototype = {
michael@0 14287 getIR: function RadialAxial_getIR() {
michael@0 14288 var coordsArr = this.coordsArr;
michael@0 14289 var shadingType = this.shadingType;
michael@0 14290 var type, p0, p1, r0, r1;
michael@0 14291 if (shadingType == PatternType.AXIAL) {
michael@0 14292 p0 = [coordsArr[0], coordsArr[1]];
michael@0 14293 p1 = [coordsArr[2], coordsArr[3]];
michael@0 14294 r0 = null;
michael@0 14295 r1 = null;
michael@0 14296 type = 'axial';
michael@0 14297 } else if (shadingType == PatternType.RADIAL) {
michael@0 14298 p0 = [coordsArr[0], coordsArr[1]];
michael@0 14299 p1 = [coordsArr[3], coordsArr[4]];
michael@0 14300 r0 = coordsArr[2];
michael@0 14301 r1 = coordsArr[5];
michael@0 14302 type = 'radial';
michael@0 14303 } else {
michael@0 14304 error('getPattern type unknown: ' + shadingType);
michael@0 14305 }
michael@0 14306
michael@0 14307 var matrix = this.matrix;
michael@0 14308 if (matrix) {
michael@0 14309 p0 = Util.applyTransform(p0, matrix);
michael@0 14310 p1 = Util.applyTransform(p1, matrix);
michael@0 14311 }
michael@0 14312
michael@0 14313 return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
michael@0 14314 }
michael@0 14315 };
michael@0 14316
michael@0 14317 return RadialAxial;
michael@0 14318 })();
michael@0 14319
michael@0 14320 // All mesh shading. For now, they will be presented as set of the triangles
michael@0 14321 // to be drawn on the canvas and rgb color for each vertex.
michael@0 14322 Shadings.Mesh = (function MeshClosure() {
michael@0 14323 function MeshStreamReader(stream, context) {
michael@0 14324 this.stream = stream;
michael@0 14325 this.context = context;
michael@0 14326 this.buffer = 0;
michael@0 14327 this.bufferLength = 0;
michael@0 14328 }
michael@0 14329 MeshStreamReader.prototype = {
michael@0 14330 get hasData() {
michael@0 14331 if (this.stream.end) {
michael@0 14332 return this.stream.pos < this.stream.end;
michael@0 14333 }
michael@0 14334 if (this.bufferLength > 0) {
michael@0 14335 return true;
michael@0 14336 }
michael@0 14337 var nextByte = this.stream.getByte();
michael@0 14338 if (nextByte < 0) {
michael@0 14339 return false;
michael@0 14340 }
michael@0 14341 this.buffer = nextByte;
michael@0 14342 this.bufferLength = 8;
michael@0 14343 return true;
michael@0 14344 },
michael@0 14345 readBits: function MeshStreamReader_readBits(n) {
michael@0 14346 var buffer = this.buffer;
michael@0 14347 var bufferLength = this.bufferLength;
michael@0 14348 if (n === 32) {
michael@0 14349 if (bufferLength === 0) {
michael@0 14350 return ((this.stream.getByte() << 24) |
michael@0 14351 (this.stream.getByte() << 16) | (this.stream.getByte() << 8) |
michael@0 14352 this.stream.getByte()) >>> 0;
michael@0 14353 }
michael@0 14354 buffer = (buffer << 24) | (this.stream.getByte() << 16) |
michael@0 14355 (this.stream.getByte() << 8) | this.stream.getByte();
michael@0 14356 var nextByte = this.stream.getByte();
michael@0 14357 this.buffer = nextByte & ((1 << bufferLength) - 1);
michael@0 14358 return ((buffer << (8 - bufferLength)) |
michael@0 14359 ((nextByte & 0xFF) >> bufferLength)) >>> 0;
michael@0 14360 }
michael@0 14361 if (n === 8 && bufferLength === 0) {
michael@0 14362 return this.stream.getByte();
michael@0 14363 }
michael@0 14364 while (bufferLength < n) {
michael@0 14365 buffer = (buffer << 8) | this.stream.getByte();
michael@0 14366 bufferLength += 8;
michael@0 14367 }
michael@0 14368 bufferLength -= n;
michael@0 14369 this.bufferLength = bufferLength;
michael@0 14370 this.buffer = buffer & ((1 << bufferLength) - 1);
michael@0 14371 return buffer >> bufferLength;
michael@0 14372 },
michael@0 14373 align: function MeshStreamReader_align() {
michael@0 14374 this.buffer = 0;
michael@0 14375 this.bufferLength = 0;
michael@0 14376 },
michael@0 14377 readFlag: function MeshStreamReader_readFlag() {
michael@0 14378 return this.readBits(this.context.bitsPerFlag);
michael@0 14379 },
michael@0 14380 readCoordinate: function MeshStreamReader_readCoordinate() {
michael@0 14381 var bitsPerCoordinate = this.context.bitsPerCoordinate;
michael@0 14382 var xi = this.readBits(bitsPerCoordinate);
michael@0 14383 var yi = this.readBits(bitsPerCoordinate);
michael@0 14384 var decode = this.context.decode;
michael@0 14385 var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) :
michael@0 14386 2.3283064365386963e-10; // 2 ^ -32
michael@0 14387 return [
michael@0 14388 xi * scale * (decode[1] - decode[0]) + decode[0],
michael@0 14389 yi * scale * (decode[3] - decode[2]) + decode[2]
michael@0 14390 ];
michael@0 14391 },
michael@0 14392 readComponents: function MeshStreamReader_readComponents() {
michael@0 14393 var numComps = this.context.numComps;
michael@0 14394 var bitsPerComponent = this.context.bitsPerComponent;
michael@0 14395 var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) :
michael@0 14396 2.3283064365386963e-10; // 2 ^ -32
michael@0 14397 var decode = this.context.decode;
michael@0 14398 var components = [];
michael@0 14399 for (var i = 0, j = 4; i < numComps; i++, j += 2) {
michael@0 14400 var ci = this.readBits(bitsPerComponent);
michael@0 14401 components.push(ci * scale * (decode[j + 1] - decode[j]) + decode[j]);
michael@0 14402 }
michael@0 14403 if (this.context.colorFn) {
michael@0 14404 components = this.context.colorFn(components);
michael@0 14405 }
michael@0 14406 return this.context.colorSpace.getRgb(components, 0);
michael@0 14407 }
michael@0 14408 };
michael@0 14409
michael@0 14410 function decodeType4Shading(mesh, reader) {
michael@0 14411 var coords = mesh.coords;
michael@0 14412 var colors = mesh.colors;
michael@0 14413 var operators = [];
michael@0 14414 var ps = []; // not maintaining cs since that will match ps
michael@0 14415 var verticesLeft = 0; // assuming we have all data to start a new triangle
michael@0 14416 while (reader.hasData) {
michael@0 14417 var f = reader.readFlag();
michael@0 14418 var coord = reader.readCoordinate();
michael@0 14419 var color = reader.readComponents();
michael@0 14420 if (verticesLeft === 0) { // ignoring flags if we started a triangle
michael@0 14421 assert(0 <= f && f <= 2, 'Unknown type4 flag');
michael@0 14422 switch (f) {
michael@0 14423 case 0:
michael@0 14424 verticesLeft = 3;
michael@0 14425 break;
michael@0 14426 case 1:
michael@0 14427 ps.push(ps[ps.length - 2], ps[ps.length - 1]);
michael@0 14428 verticesLeft = 1;
michael@0 14429 break;
michael@0 14430 case 2:
michael@0 14431 ps.push(ps[ps.length - 3], ps[ps.length - 1]);
michael@0 14432 verticesLeft = 1;
michael@0 14433 break;
michael@0 14434 }
michael@0 14435 operators.push(f);
michael@0 14436 }
michael@0 14437 ps.push(coords.length);
michael@0 14438 coords.push(coord);
michael@0 14439 colors.push(color);
michael@0 14440 verticesLeft--;
michael@0 14441
michael@0 14442 reader.align();
michael@0 14443 }
michael@0 14444
michael@0 14445 var psPacked = new Int32Array(ps);
michael@0 14446
michael@0 14447 mesh.figures.push({
michael@0 14448 type: 'triangles',
michael@0 14449 coords: psPacked,
michael@0 14450 colors: psPacked
michael@0 14451 });
michael@0 14452 }
michael@0 14453
michael@0 14454 function decodeType5Shading(mesh, reader, verticesPerRow) {
michael@0 14455 var coords = mesh.coords;
michael@0 14456 var colors = mesh.colors;
michael@0 14457 var ps = []; // not maintaining cs since that will match ps
michael@0 14458 while (reader.hasData) {
michael@0 14459 var coord = reader.readCoordinate();
michael@0 14460 var color = reader.readComponents();
michael@0 14461 ps.push(coords.length);
michael@0 14462 coords.push(coord);
michael@0 14463 colors.push(color);
michael@0 14464 }
michael@0 14465
michael@0 14466 var psPacked = new Int32Array(ps);
michael@0 14467
michael@0 14468 mesh.figures.push({
michael@0 14469 type: 'lattice',
michael@0 14470 coords: psPacked,
michael@0 14471 colors: psPacked,
michael@0 14472 verticesPerRow: verticesPerRow
michael@0 14473 });
michael@0 14474 }
michael@0 14475
michael@0 14476 var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
michael@0 14477 var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
michael@0 14478
michael@0 14479 var TRIANGLE_DENSITY = 20; // count of triangles per entire mesh bounds
michael@0 14480
michael@0 14481 var getB = (function getBClosure() {
michael@0 14482 function buildB(count) {
michael@0 14483 var lut = [];
michael@0 14484 for (var i = 0; i <= count; i++) {
michael@0 14485 var t = i / count, t_ = 1 - t;
michael@0 14486 lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_,
michael@0 14487 3 * t * t * t_, t * t * t]));
michael@0 14488 }
michael@0 14489 return lut;
michael@0 14490 }
michael@0 14491 var cache = [];
michael@0 14492 return function getB(count) {
michael@0 14493 if (!cache[count]) {
michael@0 14494 cache[count] = buildB(count);
michael@0 14495 }
michael@0 14496 return cache[count];
michael@0 14497 };
michael@0 14498 })();
michael@0 14499
michael@0 14500 function buildFigureFromPatch(mesh, index) {
michael@0 14501 var figure = mesh.figures[index];
michael@0 14502 assert(figure.type === 'patch', 'Unexpected patch mesh figure');
michael@0 14503
michael@0 14504 var coords = mesh.coords, colors = mesh.colors;
michael@0 14505 var pi = figure.coords;
michael@0 14506 var ci = figure.colors;
michael@0 14507
michael@0 14508 var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0],
michael@0 14509 coords[pi[12]][0], coords[pi[15]][0]);
michael@0 14510 var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1],
michael@0 14511 coords[pi[12]][1], coords[pi[15]][1]);
michael@0 14512 var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0],
michael@0 14513 coords[pi[12]][0], coords[pi[15]][0]);
michael@0 14514 var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1],
michael@0 14515 coords[pi[12]][1], coords[pi[15]][1]);
michael@0 14516 var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY /
michael@0 14517 (mesh.bounds[2] - mesh.bounds[0]));
michael@0 14518 splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
michael@0 14519 Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
michael@0 14520 var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY /
michael@0 14521 (mesh.bounds[3] - mesh.bounds[1]));
michael@0 14522 splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
michael@0 14523 Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
michael@0 14524
michael@0 14525 var verticesPerRow = splitXBy + 1;
michael@0 14526 var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
michael@0 14527 var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
michael@0 14528 var k = 0;
michael@0 14529 var cl = new Uint8Array(3), cr = new Uint8Array(3);
michael@0 14530 var c0 = colors[ci[0]], c1 = colors[ci[1]],
michael@0 14531 c2 = colors[ci[2]], c3 = colors[ci[3]];
michael@0 14532 var bRow = getB(splitYBy), bCol = getB(splitXBy);
michael@0 14533 for (var row = 0; row <= splitYBy; row++) {
michael@0 14534 cl[0] = ((c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy) | 0;
michael@0 14535 cl[1] = ((c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy) | 0;
michael@0 14536 cl[2] = ((c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy) | 0;
michael@0 14537
michael@0 14538 cr[0] = ((c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy) | 0;
michael@0 14539 cr[1] = ((c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy) | 0;
michael@0 14540 cr[2] = ((c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy) | 0;
michael@0 14541
michael@0 14542 for (var col = 0; col <= splitXBy; col++, k++) {
michael@0 14543 if ((row === 0 || row === splitYBy) &&
michael@0 14544 (col === 0 || col === splitXBy)) {
michael@0 14545 continue;
michael@0 14546 }
michael@0 14547 var x = 0, y = 0;
michael@0 14548 var q = 0;
michael@0 14549 for (var i = 0; i <= 3; i++) {
michael@0 14550 for (var j = 0; j <= 3; j++, q++) {
michael@0 14551 var m = bRow[row][i] * bCol[col][j];
michael@0 14552 x += coords[pi[q]][0] * m;
michael@0 14553 y += coords[pi[q]][1] * m;
michael@0 14554 }
michael@0 14555 }
michael@0 14556 figureCoords[k] = coords.length;
michael@0 14557 coords.push([x, y]);
michael@0 14558 figureColors[k] = colors.length;
michael@0 14559 var newColor = new Uint8Array(3);
michael@0 14560 newColor[0] = ((cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy) | 0;
michael@0 14561 newColor[1] = ((cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy) | 0;
michael@0 14562 newColor[2] = ((cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy) | 0;
michael@0 14563 colors.push(newColor);
michael@0 14564 }
michael@0 14565 }
michael@0 14566 figureCoords[0] = pi[0];
michael@0 14567 figureColors[0] = ci[0];
michael@0 14568 figureCoords[splitXBy] = pi[3];
michael@0 14569 figureColors[splitXBy] = ci[1];
michael@0 14570 figureCoords[verticesPerRow * splitYBy] = pi[12];
michael@0 14571 figureColors[verticesPerRow * splitYBy] = ci[2];
michael@0 14572 figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
michael@0 14573 figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
michael@0 14574
michael@0 14575 mesh.figures[index] = {
michael@0 14576 type: 'lattice',
michael@0 14577 coords: figureCoords,
michael@0 14578 colors: figureColors,
michael@0 14579 verticesPerRow: verticesPerRow
michael@0 14580 };
michael@0 14581 }
michael@0 14582
michael@0 14583 function decodeType6Shading(mesh, reader) {
michael@0 14584 // A special case of Type 7. The p11, p12, p21, p22 automatically filled
michael@0 14585 var coords = mesh.coords;
michael@0 14586 var colors = mesh.colors;
michael@0 14587 var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33
michael@0 14588 var cs = new Int32Array(4); // c00, c30, c03, c33
michael@0 14589 while (reader.hasData) {
michael@0 14590 var f = reader.readFlag();
michael@0 14591 assert(0 <= f && f <= 3, 'Unknown type6 flag');
michael@0 14592 var i, ii;
michael@0 14593 var pi = coords.length;
michael@0 14594 for (i = 0, ii = (f !== 0 ? 8 : 12); i < ii; i++) {
michael@0 14595 coords.push(reader.readCoordinate());
michael@0 14596 }
michael@0 14597 var ci = colors.length;
michael@0 14598 for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) {
michael@0 14599 colors.push(reader.readComponents());
michael@0 14600 }
michael@0 14601 var tmp1, tmp2, tmp3, tmp4;
michael@0 14602 switch (f) {
michael@0 14603 case 0:
michael@0 14604 ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6;
michael@0 14605 ps[ 8] = pi + 2; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7;
michael@0 14606 ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 8;
michael@0 14607 ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9;
michael@0 14608 cs[2] = ci + 1; cs[3] = ci + 2;
michael@0 14609 cs[0] = ci; cs[1] = ci + 3;
michael@0 14610 break;
michael@0 14611 case 1:
michael@0 14612 tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15];
michael@0 14613 ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2;
michael@0 14614 ps[ 8] = pi + 6; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 1;
michael@0 14615 ps[ 4] = pi + 7; /* calculated below */ ps[ 7] = pi;
michael@0 14616 ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4;
michael@0 14617 tmp1 = cs[2]; tmp2 = cs[3];
michael@0 14618 cs[2] = ci + 1; cs[3] = ci;
michael@0 14619 cs[0] = tmp1; cs[1] = tmp2;
michael@0 14620 break;
michael@0 14621 case 2:
michael@0 14622 ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5;
michael@0 14623 ps[ 8] = ps[11]; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 4;
michael@0 14624 ps[ 4] = ps[7]; /* calculated below */ ps[ 7] = pi + 3;
michael@0 14625 ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2;
michael@0 14626 cs[2] = cs[3]; cs[3] = ci + 1;
michael@0 14627 cs[0] = cs[1]; cs[1] = ci;
michael@0 14628 break;
michael@0 14629 case 3:
michael@0 14630 ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3];
michael@0 14631 ps[ 8] = pi; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7;
michael@0 14632 ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 6;
michael@0 14633 ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5;
michael@0 14634 cs[2] = cs[0]; cs[3] = cs[1];
michael@0 14635 cs[0] = ci; cs[1] = ci + 1;
michael@0 14636 break;
michael@0 14637 }
michael@0 14638 // set p11, p12, p21, p22
michael@0 14639 ps[5] = coords.length;
michael@0 14640 coords.push([
michael@0 14641 (-4 * coords[ps[0]][0] - coords[ps[15]][0] +
michael@0 14642 6 * (coords[ps[4]][0] + coords[ps[1]][0]) -
michael@0 14643 2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
michael@0 14644 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
michael@0 14645 (-4 * coords[ps[0]][1] - coords[ps[15]][1] +
michael@0 14646 6 * (coords[ps[4]][1] + coords[ps[1]][1]) -
michael@0 14647 2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
michael@0 14648 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
michael@0 14649 ]);
michael@0 14650 ps[6] = coords.length;
michael@0 14651 coords.push([
michael@0 14652 (-4 * coords[ps[3]][0] - coords[ps[12]][0] +
michael@0 14653 6 * (coords[ps[2]][0] + coords[ps[7]][0]) -
michael@0 14654 2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
michael@0 14655 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
michael@0 14656 (-4 * coords[ps[3]][1] - coords[ps[12]][1] +
michael@0 14657 6 * (coords[ps[2]][1] + coords[ps[7]][1]) -
michael@0 14658 2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
michael@0 14659 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
michael@0 14660 ]);
michael@0 14661 ps[9] = coords.length;
michael@0 14662 coords.push([
michael@0 14663 (-4 * coords[ps[12]][0] - coords[ps[3]][0] +
michael@0 14664 6 * (coords[ps[8]][0] + coords[ps[13]][0]) -
michael@0 14665 2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
michael@0 14666 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
michael@0 14667 (-4 * coords[ps[12]][1] - coords[ps[3]][1] +
michael@0 14668 6 * (coords[ps[8]][1] + coords[ps[13]][1]) -
michael@0 14669 2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
michael@0 14670 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
michael@0 14671 ]);
michael@0 14672 ps[10] = coords.length;
michael@0 14673 coords.push([
michael@0 14674 (-4 * coords[ps[15]][0] - coords[ps[0]][0] +
michael@0 14675 6 * (coords[ps[11]][0] + coords[ps[14]][0]) -
michael@0 14676 2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
michael@0 14677 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
michael@0 14678 (-4 * coords[ps[15]][1] - coords[ps[0]][1] +
michael@0 14679 6 * (coords[ps[11]][1] + coords[ps[14]][1]) -
michael@0 14680 2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
michael@0 14681 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
michael@0 14682 ]);
michael@0 14683 mesh.figures.push({
michael@0 14684 type: 'patch',
michael@0 14685 coords: new Int32Array(ps), // making copies of ps and cs
michael@0 14686 colors: new Int32Array(cs)
michael@0 14687 });
michael@0 14688 }
michael@0 14689 }
michael@0 14690
michael@0 14691 function decodeType7Shading(mesh, reader) {
michael@0 14692 var coords = mesh.coords;
michael@0 14693 var colors = mesh.colors;
michael@0 14694 var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33
michael@0 14695 var cs = new Int32Array(4); // c00, c30, c03, c33
michael@0 14696 while (reader.hasData) {
michael@0 14697 var f = reader.readFlag();
michael@0 14698 assert(0 <= f && f <= 3, 'Unknown type7 flag');
michael@0 14699 var i, ii;
michael@0 14700 var pi = coords.length;
michael@0 14701 for (i = 0, ii = (f !== 0 ? 12 : 16); i < ii; i++) {
michael@0 14702 coords.push(reader.readCoordinate());
michael@0 14703 }
michael@0 14704 var ci = colors.length;
michael@0 14705 for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) {
michael@0 14706 colors.push(reader.readComponents());
michael@0 14707 }
michael@0 14708 var tmp1, tmp2, tmp3, tmp4;
michael@0 14709 switch (f) {
michael@0 14710 case 0:
michael@0 14711 ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6;
michael@0 14712 ps[ 8] = pi + 2; ps[ 9] = pi + 13; ps[10] = pi + 14; ps[11] = pi + 7;
michael@0 14713 ps[ 4] = pi + 1; ps[ 5] = pi + 12; ps[ 6] = pi + 15; ps[ 7] = pi + 8;
michael@0 14714 ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9;
michael@0 14715 cs[2] = ci + 1; cs[3] = ci + 2;
michael@0 14716 cs[0] = ci; cs[1] = ci + 3;
michael@0 14717 break;
michael@0 14718 case 1:
michael@0 14719 tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15];
michael@0 14720 ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2;
michael@0 14721 ps[ 8] = pi + 6; ps[ 9] = pi + 11; ps[10] = pi + 10; ps[11] = pi + 1;
michael@0 14722 ps[ 4] = pi + 7; ps[ 5] = pi + 8; ps[ 6] = pi + 9; ps[ 7] = pi;
michael@0 14723 ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4;
michael@0 14724 tmp1 = cs[2]; tmp2 = cs[3];
michael@0 14725 cs[2] = ci + 1; cs[3] = ci;
michael@0 14726 cs[0] = tmp1; cs[1] = tmp2;
michael@0 14727 break;
michael@0 14728 case 2:
michael@0 14729 ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5;
michael@0 14730 ps[ 8] = ps[11]; ps[ 9] = pi + 8; ps[10] = pi + 11; ps[11] = pi + 4;
michael@0 14731 ps[ 4] = ps[7]; ps[ 5] = pi + 9; ps[ 6] = pi + 10; ps[ 7] = pi + 3;
michael@0 14732 ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2;
michael@0 14733 cs[2] = cs[3]; cs[3] = ci + 1;
michael@0 14734 cs[0] = cs[1]; cs[1] = ci;
michael@0 14735 break;
michael@0 14736 case 3:
michael@0 14737 ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3];
michael@0 14738 ps[ 8] = pi; ps[ 9] = pi + 9; ps[10] = pi + 8; ps[11] = pi + 7;
michael@0 14739 ps[ 4] = pi + 1; ps[ 5] = pi + 10; ps[ 6] = pi + 11; ps[ 7] = pi + 6;
michael@0 14740 ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5;
michael@0 14741 cs[2] = cs[0]; cs[3] = cs[1];
michael@0 14742 cs[0] = ci; cs[1] = ci + 1;
michael@0 14743 break;
michael@0 14744 }
michael@0 14745 mesh.figures.push({
michael@0 14746 type: 'patch',
michael@0 14747 coords: new Int32Array(ps), // making copies of ps and cs
michael@0 14748 colors: new Int32Array(cs)
michael@0 14749 });
michael@0 14750 }
michael@0 14751 }
michael@0 14752
michael@0 14753 function updateBounds(mesh) {
michael@0 14754 var minX = mesh.coords[0][0], minY = mesh.coords[0][1],
michael@0 14755 maxX = minX, maxY = minY;
michael@0 14756 for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
michael@0 14757 var x = mesh.coords[i][0], y = mesh.coords[i][1];
michael@0 14758 minX = minX > x ? x : minX;
michael@0 14759 minY = minY > y ? y : minY;
michael@0 14760 maxX = maxX < x ? x : maxX;
michael@0 14761 maxY = maxY < y ? y : maxY;
michael@0 14762 }
michael@0 14763 mesh.bounds = [minX, minY, maxX, maxY];
michael@0 14764 }
michael@0 14765
michael@0 14766 function packData(mesh) {
michael@0 14767 var i, ii, j, jj;
michael@0 14768
michael@0 14769 var coords = mesh.coords;
michael@0 14770 var coordsPacked = new Float32Array(coords.length * 2);
michael@0 14771 for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
michael@0 14772 var xy = coords[i];
michael@0 14773 coordsPacked[j++] = xy[0];
michael@0 14774 coordsPacked[j++] = xy[1];
michael@0 14775 }
michael@0 14776 mesh.coords = coordsPacked;
michael@0 14777
michael@0 14778 var colors = mesh.colors;
michael@0 14779 var colorsPacked = new Uint8Array(colors.length * 3);
michael@0 14780 for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
michael@0 14781 var c = colors[i];
michael@0 14782 colorsPacked[j++] = c[0];
michael@0 14783 colorsPacked[j++] = c[1];
michael@0 14784 colorsPacked[j++] = c[2];
michael@0 14785 }
michael@0 14786 mesh.colors = colorsPacked;
michael@0 14787
michael@0 14788 var figures = mesh.figures;
michael@0 14789 for (i = 0, ii = figures.length; i < ii; i++) {
michael@0 14790 var figure = figures[i], ps = figure.coords, cs = figure.colors;
michael@0 14791 for (j = 0, jj = ps.length; j < jj; j++) {
michael@0 14792 ps[j] *= 2;
michael@0 14793 cs[j] *= 3;
michael@0 14794 }
michael@0 14795 }
michael@0 14796 }
michael@0 14797
michael@0 14798 function Mesh(stream, matrix, xref, res) {
michael@0 14799 assert(isStream(stream), 'Mesh data is not a stream');
michael@0 14800 var dict = stream.dict;
michael@0 14801 this.matrix = matrix;
michael@0 14802 this.shadingType = dict.get('ShadingType');
michael@0 14803 this.type = 'Pattern';
michael@0 14804 this.bbox = dict.get('BBox');
michael@0 14805 var cs = dict.get('ColorSpace', 'CS');
michael@0 14806 cs = ColorSpace.parse(cs, xref, res);
michael@0 14807 this.cs = cs;
michael@0 14808 this.background = dict.has('Background') ?
michael@0 14809 cs.getRgb(dict.get('Background'), 0) : null;
michael@0 14810
michael@0 14811 var fnObj = dict.get('Function');
michael@0 14812 var fn;
michael@0 14813 if (!fnObj) {
michael@0 14814 fn = null;
michael@0 14815 } else if (isArray(fnObj)) {
michael@0 14816 var fnArray = [];
michael@0 14817 for (var j = 0, jj = fnObj.length; j < jj; j++) {
michael@0 14818 var obj = xref.fetchIfRef(fnObj[j]);
michael@0 14819 if (!isPDFFunction(obj)) {
michael@0 14820 error('Invalid function');
michael@0 14821 }
michael@0 14822 fnArray.push(PDFFunction.parse(xref, obj));
michael@0 14823 }
michael@0 14824 fn = function radialAxialColorFunction(arg) {
michael@0 14825 var out = [];
michael@0 14826 for (var i = 0, ii = fnArray.length; i < ii; i++) {
michael@0 14827 out.push(fnArray[i](arg)[0]);
michael@0 14828 }
michael@0 14829 return out;
michael@0 14830 };
michael@0 14831 } else {
michael@0 14832 if (!isPDFFunction(fnObj)) {
michael@0 14833 error('Invalid function');
michael@0 14834 }
michael@0 14835 fn = PDFFunction.parse(xref, fnObj);
michael@0 14836 }
michael@0 14837
michael@0 14838 this.coords = [];
michael@0 14839 this.colors = [];
michael@0 14840 this.figures = [];
michael@0 14841
michael@0 14842 var decodeContext = {
michael@0 14843 bitsPerCoordinate: dict.get('BitsPerCoordinate'),
michael@0 14844 bitsPerComponent: dict.get('BitsPerComponent'),
michael@0 14845 bitsPerFlag: dict.get('BitsPerFlag'),
michael@0 14846 decode: dict.get('Decode'),
michael@0 14847 colorFn: fn,
michael@0 14848 colorSpace: cs,
michael@0 14849 numComps: fn ? 1 : cs.numComps
michael@0 14850 };
michael@0 14851 var reader = new MeshStreamReader(stream, decodeContext);
michael@0 14852
michael@0 14853 var patchMesh = false;
michael@0 14854 switch (this.shadingType) {
michael@0 14855 case PatternType.FREE_FORM_MESH:
michael@0 14856 decodeType4Shading(this, reader);
michael@0 14857 break;
michael@0 14858 case PatternType.LATTICE_FORM_MESH:
michael@0 14859 var verticesPerRow = dict.get('VerticesPerRow') | 0;
michael@0 14860 assert(verticesPerRow >= 2, 'Invalid VerticesPerRow');
michael@0 14861 decodeType5Shading(this, reader, verticesPerRow);
michael@0 14862 break;
michael@0 14863 case PatternType.COONS_PATCH_MESH:
michael@0 14864 decodeType6Shading(this, reader);
michael@0 14865 patchMesh = true;
michael@0 14866 break;
michael@0 14867 case PatternType.TENSOR_PATCH_MESH:
michael@0 14868 decodeType7Shading(this, reader);
michael@0 14869 patchMesh = true;
michael@0 14870 break;
michael@0 14871 default:
michael@0 14872 error('Unsupported mesh type.');
michael@0 14873 break;
michael@0 14874 }
michael@0 14875
michael@0 14876 if (patchMesh) {
michael@0 14877 // dirty bounds calculation for determining, how dense shall be triangles
michael@0 14878 updateBounds(this);
michael@0 14879 for (var i = 0, ii = this.figures.length; i < ii; i++) {
michael@0 14880 buildFigureFromPatch(this, i);
michael@0 14881 }
michael@0 14882 }
michael@0 14883 // calculate bounds
michael@0 14884 updateBounds(this);
michael@0 14885
michael@0 14886 packData(this);
michael@0 14887 }
michael@0 14888
michael@0 14889 Mesh.prototype = {
michael@0 14890 getIR: function Mesh_getIR() {
michael@0 14891 return ['Mesh', this.shadingType, this.coords, this.colors, this.figures,
michael@0 14892 this.bounds, this.matrix, this.bbox, this.background];
michael@0 14893 }
michael@0 14894 };
michael@0 14895
michael@0 14896 return Mesh;
michael@0 14897 })();
michael@0 14898
michael@0 14899 Shadings.Dummy = (function DummyClosure() {
michael@0 14900 function Dummy() {
michael@0 14901 this.type = 'Pattern';
michael@0 14902 }
michael@0 14903
michael@0 14904 Dummy.prototype = {
michael@0 14905 getIR: function Dummy_getIR() {
michael@0 14906 return ['Dummy'];
michael@0 14907 }
michael@0 14908 };
michael@0 14909 return Dummy;
michael@0 14910 })();
michael@0 14911
michael@0 14912 function getTilingPatternIR(operatorList, dict, args) {
michael@0 14913 var matrix = dict.get('Matrix');
michael@0 14914 var bbox = dict.get('BBox');
michael@0 14915 var xstep = dict.get('XStep');
michael@0 14916 var ystep = dict.get('YStep');
michael@0 14917 var paintType = dict.get('PaintType');
michael@0 14918 var tilingType = dict.get('TilingType');
michael@0 14919
michael@0 14920 return [
michael@0 14921 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep,
michael@0 14922 paintType, tilingType
michael@0 14923 ];
michael@0 14924 }
michael@0 14925
michael@0 14926
michael@0 14927 var PartialEvaluator = (function PartialEvaluatorClosure() {
michael@0 14928 function PartialEvaluator(pdfManager, xref, handler, pageIndex,
michael@0 14929 uniquePrefix, idCounters, fontCache) {
michael@0 14930 this.pdfManager = pdfManager;
michael@0 14931 this.xref = xref;
michael@0 14932 this.handler = handler;
michael@0 14933 this.pageIndex = pageIndex;
michael@0 14934 this.uniquePrefix = uniquePrefix;
michael@0 14935 this.idCounters = idCounters;
michael@0 14936 this.fontCache = fontCache;
michael@0 14937 }
michael@0 14938
michael@0 14939 var TILING_PATTERN = 1, SHADING_PATTERN = 2;
michael@0 14940
michael@0 14941 PartialEvaluator.prototype = {
michael@0 14942 hasBlendModes: function PartialEvaluator_hasBlendModes(resources) {
michael@0 14943 if (!isDict(resources)) {
michael@0 14944 return false;
michael@0 14945 }
michael@0 14946
michael@0 14947 var processed = Object.create(null);
michael@0 14948 if (resources.objId) {
michael@0 14949 processed[resources.objId] = true;
michael@0 14950 }
michael@0 14951
michael@0 14952 var nodes = [resources];
michael@0 14953 while (nodes.length) {
michael@0 14954 var key;
michael@0 14955 var node = nodes.shift();
michael@0 14956 // First check the current resources for blend modes.
michael@0 14957 var graphicStates = node.get('ExtGState');
michael@0 14958 if (isDict(graphicStates)) {
michael@0 14959 graphicStates = graphicStates.getAll();
michael@0 14960 for (key in graphicStates) {
michael@0 14961 var graphicState = graphicStates[key];
michael@0 14962 var bm = graphicState['BM'];
michael@0 14963 if (isName(bm) && bm.name !== 'Normal') {
michael@0 14964 return true;
michael@0 14965 }
michael@0 14966 }
michael@0 14967 }
michael@0 14968 // Descend into the XObjects to look for more resources and blend modes.
michael@0 14969 var xObjects = node.get('XObject');
michael@0 14970 if (!isDict(xObjects)) {
michael@0 14971 continue;
michael@0 14972 }
michael@0 14973 xObjects = xObjects.getAll();
michael@0 14974 for (key in xObjects) {
michael@0 14975 var xObject = xObjects[key];
michael@0 14976 if (!isStream(xObject)) {
michael@0 14977 continue;
michael@0 14978 }
michael@0 14979 var xResources = xObject.dict.get('Resources');
michael@0 14980 // Checking objId to detect an infinite loop.
michael@0 14981 if (isDict(xResources) &&
michael@0 14982 (!xResources.objId || !processed[xResources.objId])) {
michael@0 14983 nodes.push(xResources);
michael@0 14984 if (xResources.objId) {
michael@0 14985 processed[xResources.objId] = true;
michael@0 14986 }
michael@0 14987 }
michael@0 14988 }
michael@0 14989 }
michael@0 14990 return false;
michael@0 14991 },
michael@0 14992
michael@0 14993 buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
michael@0 14994 xobj, smask,
michael@0 14995 operatorList,
michael@0 14996 initialState) {
michael@0 14997 var matrix = xobj.dict.get('Matrix');
michael@0 14998 var bbox = xobj.dict.get('BBox');
michael@0 14999 var group = xobj.dict.get('Group');
michael@0 15000 if (group) {
michael@0 15001 var groupOptions = {
michael@0 15002 matrix: matrix,
michael@0 15003 bbox: bbox,
michael@0 15004 smask: smask,
michael@0 15005 isolated: false,
michael@0 15006 knockout: false
michael@0 15007 };
michael@0 15008
michael@0 15009 var groupSubtype = group.get('S');
michael@0 15010 if (isName(groupSubtype) && groupSubtype.name === 'Transparency') {
michael@0 15011 groupOptions.isolated = (group.get('I') || false);
michael@0 15012 groupOptions.knockout = (group.get('K') || false);
michael@0 15013 var colorSpace = group.get('CS');
michael@0 15014 groupOptions.colorSpace = (colorSpace ?
michael@0 15015 ColorSpace.parseToIR(colorSpace, this.xref, resources) : null);
michael@0 15016 }
michael@0 15017 operatorList.addOp(OPS.beginGroup, [groupOptions]);
michael@0 15018 }
michael@0 15019
michael@0 15020 operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]);
michael@0 15021
michael@0 15022 this.getOperatorList(xobj, (xobj.dict.get('Resources') || resources),
michael@0 15023 operatorList, initialState);
michael@0 15024 operatorList.addOp(OPS.paintFormXObjectEnd, []);
michael@0 15025
michael@0 15026 if (group) {
michael@0 15027 operatorList.addOp(OPS.endGroup, [groupOptions]);
michael@0 15028 }
michael@0 15029 },
michael@0 15030
michael@0 15031 buildPaintImageXObject:
michael@0 15032 function PartialEvaluator_buildPaintImageXObject(resources, image,
michael@0 15033 inline, operatorList,
michael@0 15034 cacheKey, cache) {
michael@0 15035 var self = this;
michael@0 15036 var dict = image.dict;
michael@0 15037 var w = dict.get('Width', 'W');
michael@0 15038 var h = dict.get('Height', 'H');
michael@0 15039
michael@0 15040 if (!(w && isNum(w)) || !(h && isNum(h))) {
michael@0 15041 warn('Image dimensions are missing, or not numbers.');
michael@0 15042 return;
michael@0 15043 }
michael@0 15044 if (PDFJS.maxImageSize !== -1 && w * h > PDFJS.maxImageSize) {
michael@0 15045 warn('Image exceeded maximum allowed size and was removed.');
michael@0 15046 return;
michael@0 15047 }
michael@0 15048
michael@0 15049 var imageMask = (dict.get('ImageMask', 'IM') || false);
michael@0 15050 var imgData, args;
michael@0 15051 if (imageMask) {
michael@0 15052 // This depends on a tmpCanvas being filled with the
michael@0 15053 // current fillStyle, such that processing the pixel
michael@0 15054 // data can't be done here. Instead of creating a
michael@0 15055 // complete PDFImage, only read the information needed
michael@0 15056 // for later.
michael@0 15057
michael@0 15058 var width = dict.get('Width', 'W');
michael@0 15059 var height = dict.get('Height', 'H');
michael@0 15060 var bitStrideLength = (width + 7) >> 3;
michael@0 15061 var imgArray = image.getBytes(bitStrideLength * height);
michael@0 15062 var decode = dict.get('Decode', 'D');
michael@0 15063 var canTransfer = image instanceof DecodeStream;
michael@0 15064 var inverseDecode = (!!decode && decode[0] > 0);
michael@0 15065
michael@0 15066 imgData = PDFImage.createMask(imgArray, width, height,
michael@0 15067 canTransfer, inverseDecode);
michael@0 15068 imgData.cached = true;
michael@0 15069 args = [imgData];
michael@0 15070 operatorList.addOp(OPS.paintImageMaskXObject, args);
michael@0 15071 if (cacheKey) {
michael@0 15072 cache.key = cacheKey;
michael@0 15073 cache.fn = OPS.paintImageMaskXObject;
michael@0 15074 cache.args = args;
michael@0 15075 }
michael@0 15076 return;
michael@0 15077 }
michael@0 15078
michael@0 15079 var softMask = (dict.get('SMask', 'SM') || false);
michael@0 15080 var mask = (dict.get('Mask') || false);
michael@0 15081
michael@0 15082 var SMALL_IMAGE_DIMENSIONS = 200;
michael@0 15083 // Inlining small images into the queue as RGB data
michael@0 15084 if (inline && !softMask && !mask && !(image instanceof JpegStream) &&
michael@0 15085 (w + h) < SMALL_IMAGE_DIMENSIONS) {
michael@0 15086 var imageObj = new PDFImage(this.xref, resources, image,
michael@0 15087 inline, null, null);
michael@0 15088 // We force the use of RGBA_32BPP images here, because we can't handle
michael@0 15089 // any other kind.
michael@0 15090 imgData = imageObj.createImageData(/* forceRGBA = */ true);
michael@0 15091 operatorList.addOp(OPS.paintInlineImageXObject, [imgData]);
michael@0 15092 return;
michael@0 15093 }
michael@0 15094
michael@0 15095 // If there is no imageMask, create the PDFImage and a lot
michael@0 15096 // of image processing can be done here.
michael@0 15097 var uniquePrefix = (this.uniquePrefix || '');
michael@0 15098 var objId = 'img_' + uniquePrefix + (++this.idCounters.obj);
michael@0 15099 operatorList.addDependency(objId);
michael@0 15100 args = [objId, w, h];
michael@0 15101
michael@0 15102 if (!softMask && !mask && image instanceof JpegStream &&
michael@0 15103 image.isNativelySupported(this.xref, resources)) {
michael@0 15104 // These JPEGs don't need any more processing so we can just send it.
michael@0 15105 operatorList.addOp(OPS.paintJpegXObject, args);
michael@0 15106 this.handler.send('obj',
michael@0 15107 [objId, this.pageIndex, 'JpegStream', image.getIR()]);
michael@0 15108 return;
michael@0 15109 }
michael@0 15110
michael@0 15111 PDFImage.buildImage(self.handler, self.xref, resources, image, inline).
michael@0 15112 then(function(imageObj) {
michael@0 15113 var imgData = imageObj.createImageData(/* forceRGBA = */ false);
michael@0 15114 self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData],
michael@0 15115 null, [imgData.data.buffer]);
michael@0 15116 }).then(null, function (reason) {
michael@0 15117 warn('Unable to decode image: ' + reason);
michael@0 15118 self.handler.send('obj', [objId, self.pageIndex, 'Image', null]);
michael@0 15119 });
michael@0 15120
michael@0 15121 operatorList.addOp(OPS.paintImageXObject, args);
michael@0 15122 if (cacheKey) {
michael@0 15123 cache.key = cacheKey;
michael@0 15124 cache.fn = OPS.paintImageXObject;
michael@0 15125 cache.args = args;
michael@0 15126 }
michael@0 15127 },
michael@0 15128
michael@0 15129 handleSMask: function PartialEvaluator_handleSmask(smask, resources,
michael@0 15130 operatorList,
michael@0 15131 stateManager) {
michael@0 15132 var smaskContent = smask.get('G');
michael@0 15133 var smaskOptions = {
michael@0 15134 subtype: smask.get('S').name,
michael@0 15135 backdrop: smask.get('BC')
michael@0 15136 };
michael@0 15137 this.buildFormXObject(resources, smaskContent, smaskOptions,
michael@0 15138 operatorList, stateManager.state.clone());
michael@0 15139 },
michael@0 15140
michael@0 15141 handleTilingType:
michael@0 15142 function PartialEvaluator_handleTilingType(fn, args, resources,
michael@0 15143 pattern, patternDict,
michael@0 15144 operatorList) {
michael@0 15145 // Create an IR of the pattern code.
michael@0 15146 var tilingOpList = this.getOperatorList(pattern,
michael@0 15147 (patternDict.get('Resources') || resources));
michael@0 15148 // Add the dependencies to the parent operator list so they are resolved
michael@0 15149 // before sub operator list is executed synchronously.
michael@0 15150 operatorList.addDependencies(tilingOpList.dependencies);
michael@0 15151 operatorList.addOp(fn, getTilingPatternIR({
michael@0 15152 fnArray: tilingOpList.fnArray,
michael@0 15153 argsArray: tilingOpList.argsArray
michael@0 15154 }, patternDict, args));
michael@0 15155 },
michael@0 15156
michael@0 15157 handleSetFont:
michael@0 15158 function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef,
michael@0 15159 operatorList, state) {
michael@0 15160 // TODO(mack): Not needed?
michael@0 15161 var fontName;
michael@0 15162 if (fontArgs) {
michael@0 15163 fontArgs = fontArgs.slice();
michael@0 15164 fontName = fontArgs[0].name;
michael@0 15165 }
michael@0 15166 var self = this;
michael@0 15167 var font = this.loadFont(fontName, fontRef, this.xref, resources,
michael@0 15168 operatorList);
michael@0 15169 state.font = font;
michael@0 15170 var loadedName = font.loadedName;
michael@0 15171 if (!font.sent) {
michael@0 15172 var fontData = font.translated.exportData();
michael@0 15173
michael@0 15174 self.handler.send('commonobj', [
michael@0 15175 loadedName,
michael@0 15176 'Font',
michael@0 15177 fontData
michael@0 15178 ]);
michael@0 15179 font.sent = true;
michael@0 15180 }
michael@0 15181
michael@0 15182 return loadedName;
michael@0 15183 },
michael@0 15184
michael@0 15185 handleText: function PartialEvaluator_handleText(chars, state) {
michael@0 15186 var font = state.font.translated;
michael@0 15187 var glyphs = font.charsToGlyphs(chars);
michael@0 15188 var isAddToPathSet = !!(state.textRenderingMode &
michael@0 15189 TextRenderingMode.ADD_TO_PATH_FLAG);
michael@0 15190 if (font.data && (isAddToPathSet || PDFJS.disableFontFace)) {
michael@0 15191 for (var i = 0; i < glyphs.length; i++) {
michael@0 15192 if (glyphs[i] === null) {
michael@0 15193 continue;
michael@0 15194 }
michael@0 15195 var fontChar = glyphs[i].fontChar;
michael@0 15196 if (!font.renderer.hasBuiltPath(fontChar)) {
michael@0 15197 var path = font.renderer.getPathJs(fontChar);
michael@0 15198 this.handler.send('commonobj', [
michael@0 15199 font.loadedName + '_path_' + fontChar,
michael@0 15200 'FontPath',
michael@0 15201 path
michael@0 15202 ]);
michael@0 15203 }
michael@0 15204 }
michael@0 15205 }
michael@0 15206
michael@0 15207 return glyphs;
michael@0 15208 },
michael@0 15209
michael@0 15210 setGState: function PartialEvaluator_setGState(resources, gState,
michael@0 15211 operatorList, xref,
michael@0 15212 stateManager) {
michael@0 15213
michael@0 15214 var self = this;
michael@0 15215 // TODO(mack): This should be rewritten so that this function returns
michael@0 15216 // what should be added to the queue during each iteration
michael@0 15217 function setGStateForKey(gStateObj, key, value) {
michael@0 15218 switch (key) {
michael@0 15219 case 'Type':
michael@0 15220 break;
michael@0 15221 case 'LW':
michael@0 15222 case 'LC':
michael@0 15223 case 'LJ':
michael@0 15224 case 'ML':
michael@0 15225 case 'D':
michael@0 15226 case 'RI':
michael@0 15227 case 'FL':
michael@0 15228 case 'CA':
michael@0 15229 case 'ca':
michael@0 15230 gStateObj.push([key, value]);
michael@0 15231 break;
michael@0 15232 case 'Font':
michael@0 15233 var loadedName = self.handleSetFont(resources, null, value[0],
michael@0 15234 operatorList,
michael@0 15235 stateManager.state);
michael@0 15236 operatorList.addDependency(loadedName);
michael@0 15237 gStateObj.push([key, [loadedName, value[1]]]);
michael@0 15238 break;
michael@0 15239 case 'BM':
michael@0 15240 gStateObj.push([key, value]);
michael@0 15241 break;
michael@0 15242 case 'SMask':
michael@0 15243 if (isName(value) && value.name === 'None') {
michael@0 15244 gStateObj.push([key, false]);
michael@0 15245 break;
michael@0 15246 }
michael@0 15247 var dict = xref.fetchIfRef(value);
michael@0 15248 if (isDict(dict)) {
michael@0 15249 self.handleSMask(dict, resources, operatorList, stateManager);
michael@0 15250 gStateObj.push([key, true]);
michael@0 15251 } else {
michael@0 15252 warn('Unsupported SMask type');
michael@0 15253 }
michael@0 15254
michael@0 15255 break;
michael@0 15256 // Only generate info log messages for the following since
michael@0 15257 // they are unlikey to have a big impact on the rendering.
michael@0 15258 case 'OP':
michael@0 15259 case 'op':
michael@0 15260 case 'OPM':
michael@0 15261 case 'BG':
michael@0 15262 case 'BG2':
michael@0 15263 case 'UCR':
michael@0 15264 case 'UCR2':
michael@0 15265 case 'TR':
michael@0 15266 case 'TR2':
michael@0 15267 case 'HT':
michael@0 15268 case 'SM':
michael@0 15269 case 'SA':
michael@0 15270 case 'AIS':
michael@0 15271 case 'TK':
michael@0 15272 // TODO implement these operators.
michael@0 15273 info('graphic state operator ' + key);
michael@0 15274 break;
michael@0 15275 default:
michael@0 15276 info('Unknown graphic state operator ' + key);
michael@0 15277 break;
michael@0 15278 }
michael@0 15279 }
michael@0 15280
michael@0 15281 // This array holds the converted/processed state data.
michael@0 15282 var gStateObj = [];
michael@0 15283 var gStateMap = gState.map;
michael@0 15284 for (var key in gStateMap) {
michael@0 15285 var value = gStateMap[key];
michael@0 15286 setGStateForKey(gStateObj, key, value);
michael@0 15287 }
michael@0 15288
michael@0 15289 operatorList.addOp(OPS.setGState, [gStateObj]);
michael@0 15290 },
michael@0 15291
michael@0 15292 loadFont: function PartialEvaluator_loadFont(fontName, font, xref,
michael@0 15293 resources,
michael@0 15294 parentOperatorList) {
michael@0 15295
michael@0 15296 function errorFont() {
michael@0 15297 return {
michael@0 15298 translated: new ErrorFont('Font ' + fontName + ' is not available'),
michael@0 15299 loadedName: 'g_font_error'
michael@0 15300 };
michael@0 15301 }
michael@0 15302
michael@0 15303 var fontRef;
michael@0 15304 if (font) { // Loading by ref.
michael@0 15305 assert(isRef(font));
michael@0 15306 fontRef = font;
michael@0 15307 } else { // Loading by name.
michael@0 15308 var fontRes = resources.get('Font');
michael@0 15309 if (fontRes) {
michael@0 15310 fontRef = fontRes.getRaw(fontName);
michael@0 15311 } else {
michael@0 15312 warn('fontRes not available');
michael@0 15313 return errorFont();
michael@0 15314 }
michael@0 15315 }
michael@0 15316 if (this.fontCache.has(fontRef)) {
michael@0 15317 return this.fontCache.get(fontRef);
michael@0 15318 }
michael@0 15319
michael@0 15320 font = xref.fetchIfRef(fontRef);
michael@0 15321 if (!isDict(font)) {
michael@0 15322 return errorFont();
michael@0 15323 }
michael@0 15324
michael@0 15325 var preEvaluatedFont = this.preEvaluateFont(font, xref);
michael@0 15326 var descriptor = preEvaluatedFont.descriptor;
michael@0 15327 var fontID = fontRef.num + '_' + fontRef.gen;
michael@0 15328 if (isDict(descriptor)) {
michael@0 15329 if (!descriptor.fontAliases) {
michael@0 15330 descriptor.fontAliases = Object.create(null);
michael@0 15331 }
michael@0 15332
michael@0 15333 var fontAliases = descriptor.fontAliases;
michael@0 15334 var hash = preEvaluatedFont.hash;
michael@0 15335 if (fontAliases[hash]) {
michael@0 15336 var aliasFontRef = fontAliases[hash].aliasRef;
michael@0 15337 if (aliasFontRef && this.fontCache.has(aliasFontRef)) {
michael@0 15338 this.fontCache.putAlias(fontRef, aliasFontRef);
michael@0 15339 var cachedFont = this.fontCache.get(fontRef);
michael@0 15340 return cachedFont;
michael@0 15341 }
michael@0 15342 }
michael@0 15343
michael@0 15344 if (!fontAliases[hash]) {
michael@0 15345 fontAliases[hash] = {
michael@0 15346 fontID: Font.getFontID()
michael@0 15347 };
michael@0 15348 }
michael@0 15349
michael@0 15350 fontAliases[hash].aliasRef = fontRef;
michael@0 15351 fontID = fontAliases[hash].fontID;
michael@0 15352 }
michael@0 15353
michael@0 15354 // Workaround for bad PDF generators that don't reference fonts
michael@0 15355 // properly, i.e. by not using an object identifier.
michael@0 15356 // Check if the fontRef is a Dict (as opposed to a standard object),
michael@0 15357 // in which case we don't cache the font and instead reference it by
michael@0 15358 // fontName in font.loadedName below.
michael@0 15359 var fontRefIsDict = isDict(fontRef);
michael@0 15360 if (!fontRefIsDict) {
michael@0 15361 this.fontCache.put(fontRef, font);
michael@0 15362 }
michael@0 15363
michael@0 15364 // Keep track of each font we translated so the caller can
michael@0 15365 // load them asynchronously before calling display on a page.
michael@0 15366 font.loadedName = 'g_font_' + (fontRefIsDict ?
michael@0 15367 fontName.replace(/\W/g, '') : fontID);
michael@0 15368
michael@0 15369 if (!font.translated) {
michael@0 15370 var translated;
michael@0 15371 try {
michael@0 15372 translated = this.translateFont(preEvaluatedFont, xref);
michael@0 15373 } catch (e) {
michael@0 15374 UnsupportedManager.notify(UNSUPPORTED_FEATURES.font);
michael@0 15375 translated = new ErrorFont(e instanceof Error ? e.message : e);
michael@0 15376 }
michael@0 15377 font.translated = translated;
michael@0 15378 }
michael@0 15379
michael@0 15380 if (font.translated.loadCharProcs) {
michael@0 15381 var charProcs = font.get('CharProcs').getAll();
michael@0 15382 var fontResources = (font.get('Resources') || resources);
michael@0 15383 var charProcKeys = Object.keys(charProcs);
michael@0 15384 var charProcOperatorList = {};
michael@0 15385 for (var i = 0, n = charProcKeys.length; i < n; ++i) {
michael@0 15386 var key = charProcKeys[i];
michael@0 15387 var glyphStream = charProcs[key];
michael@0 15388 var operatorList = this.getOperatorList(glyphStream, fontResources);
michael@0 15389 charProcOperatorList[key] = operatorList.getIR();
michael@0 15390 if (!parentOperatorList) {
michael@0 15391 continue;
michael@0 15392 }
michael@0 15393 // Add the dependencies to the parent operator list so they are
michael@0 15394 // resolved before sub operator list is executed synchronously.
michael@0 15395 parentOperatorList.addDependencies(charProcOperatorList.dependencies);
michael@0 15396 }
michael@0 15397 font.translated.charProcOperatorList = charProcOperatorList;
michael@0 15398 }
michael@0 15399 font.loaded = true;
michael@0 15400 return font;
michael@0 15401 },
michael@0 15402
michael@0 15403 getOperatorList: function PartialEvaluator_getOperatorList(stream,
michael@0 15404 resources,
michael@0 15405 operatorList,
michael@0 15406 initialState) {
michael@0 15407
michael@0 15408 var self = this;
michael@0 15409 var xref = this.xref;
michael@0 15410 var imageCache = {};
michael@0 15411
michael@0 15412 operatorList = (operatorList || new OperatorList());
michael@0 15413
michael@0 15414 resources = (resources || Dict.empty);
michael@0 15415 var xobjs = (resources.get('XObject') || Dict.empty);
michael@0 15416 var patterns = (resources.get('Pattern') || Dict.empty);
michael@0 15417 var stateManager = new StateManager(initialState || new EvalState());
michael@0 15418 var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
michael@0 15419
michael@0 15420 var operation, i, ii;
michael@0 15421 while ((operation = preprocessor.read())) {
michael@0 15422 var args = operation.args;
michael@0 15423 var fn = operation.fn;
michael@0 15424 var shading;
michael@0 15425
michael@0 15426 switch (fn) {
michael@0 15427 case OPS.setStrokeColorN:
michael@0 15428 case OPS.setFillColorN:
michael@0 15429 if (args[args.length - 1].code) {
michael@0 15430 break;
michael@0 15431 }
michael@0 15432 // compile tiling patterns
michael@0 15433 var patternName = args[args.length - 1];
michael@0 15434 // SCN/scn applies patterns along with normal colors
michael@0 15435 var pattern;
michael@0 15436 if (isName(patternName) &&
michael@0 15437 (pattern = patterns.get(patternName.name))) {
michael@0 15438 var dict = (isStream(pattern) ? pattern.dict : pattern);
michael@0 15439 var typeNum = dict.get('PatternType');
michael@0 15440
michael@0 15441 if (typeNum == TILING_PATTERN) {
michael@0 15442 self.handleTilingType(fn, args, resources, pattern, dict,
michael@0 15443 operatorList);
michael@0 15444 args = [];
michael@0 15445 continue;
michael@0 15446 } else if (typeNum == SHADING_PATTERN) {
michael@0 15447 shading = dict.get('Shading');
michael@0 15448 var matrix = dict.get('Matrix');
michael@0 15449 pattern = Pattern.parseShading(shading, matrix, xref,
michael@0 15450 resources);
michael@0 15451 args = pattern.getIR();
michael@0 15452 } else {
michael@0 15453 error('Unkown PatternType ' + typeNum);
michael@0 15454 }
michael@0 15455 }
michael@0 15456 break;
michael@0 15457 case OPS.paintXObject:
michael@0 15458 if (args[0].code) {
michael@0 15459 break;
michael@0 15460 }
michael@0 15461 // eagerly compile XForm objects
michael@0 15462 var name = args[0].name;
michael@0 15463 if (imageCache.key === name) {
michael@0 15464 operatorList.addOp(imageCache.fn, imageCache.args);
michael@0 15465 args = [];
michael@0 15466 continue;
michael@0 15467 }
michael@0 15468
michael@0 15469 var xobj = xobjs.get(name);
michael@0 15470 if (xobj) {
michael@0 15471 assert(isStream(xobj), 'XObject should be a stream');
michael@0 15472
michael@0 15473 var type = xobj.dict.get('Subtype');
michael@0 15474 assert(isName(type),
michael@0 15475 'XObject should have a Name subtype');
michael@0 15476
michael@0 15477 if ('Form' == type.name) {
michael@0 15478 stateManager.save();
michael@0 15479 self.buildFormXObject(resources, xobj, null, operatorList,
michael@0 15480 stateManager.state.clone());
michael@0 15481 args = [];
michael@0 15482 stateManager.restore();
michael@0 15483 continue;
michael@0 15484 } else if ('Image' == type.name) {
michael@0 15485 self.buildPaintImageXObject(resources, xobj, false,
michael@0 15486 operatorList, name, imageCache);
michael@0 15487 args = [];
michael@0 15488 continue;
michael@0 15489 } else {
michael@0 15490 error('Unhandled XObject subtype ' + type.name);
michael@0 15491 }
michael@0 15492 }
michael@0 15493 break;
michael@0 15494 case OPS.setFont:
michael@0 15495 // eagerly collect all fonts
michael@0 15496 var loadedName = self.handleSetFont(resources, args, null,
michael@0 15497 operatorList,
michael@0 15498 stateManager.state);
michael@0 15499 operatorList.addDependency(loadedName);
michael@0 15500 args[0] = loadedName;
michael@0 15501 break;
michael@0 15502 case OPS.endInlineImage:
michael@0 15503 var cacheKey = args[0].cacheKey;
michael@0 15504 if (cacheKey && imageCache.key === cacheKey) {
michael@0 15505 operatorList.addOp(imageCache.fn, imageCache.args);
michael@0 15506 args = [];
michael@0 15507 continue;
michael@0 15508 }
michael@0 15509 self.buildPaintImageXObject(resources, args[0], true,
michael@0 15510 operatorList, cacheKey, imageCache);
michael@0 15511 args = [];
michael@0 15512 continue;
michael@0 15513 case OPS.showText:
michael@0 15514 args[0] = this.handleText(args[0], stateManager.state);
michael@0 15515 break;
michael@0 15516 case OPS.showSpacedText:
michael@0 15517 var arr = args[0];
michael@0 15518 var arrLength = arr.length;
michael@0 15519 for (i = 0; i < arrLength; ++i) {
michael@0 15520 if (isString(arr[i])) {
michael@0 15521 arr[i] = this.handleText(arr[i], stateManager.state);
michael@0 15522 }
michael@0 15523 }
michael@0 15524 break;
michael@0 15525 case OPS.nextLineShowText:
michael@0 15526 args[0] = this.handleText(args[0], stateManager.state);
michael@0 15527 break;
michael@0 15528 case OPS.nextLineSetSpacingShowText:
michael@0 15529 args[2] = this.handleText(args[2], stateManager.state);
michael@0 15530 break;
michael@0 15531 case OPS.setTextRenderingMode:
michael@0 15532 stateManager.state.textRenderingMode = args[0];
michael@0 15533 break;
michael@0 15534 // Parse the ColorSpace data to a raw format.
michael@0 15535 case OPS.setFillColorSpace:
michael@0 15536 case OPS.setStrokeColorSpace:
michael@0 15537 args = [ColorSpace.parseToIR(args[0], xref, resources)];
michael@0 15538 break;
michael@0 15539 case OPS.shadingFill:
michael@0 15540 var shadingRes = resources.get('Shading');
michael@0 15541 if (!shadingRes) {
michael@0 15542 error('No shading resource found');
michael@0 15543 }
michael@0 15544
michael@0 15545 shading = shadingRes.get(args[0].name);
michael@0 15546 if (!shading) {
michael@0 15547 error('No shading object found');
michael@0 15548 }
michael@0 15549
michael@0 15550 var shadingFill = Pattern.parseShading(shading, null, xref,
michael@0 15551 resources);
michael@0 15552 var patternIR = shadingFill.getIR();
michael@0 15553 args = [patternIR];
michael@0 15554 fn = OPS.shadingFill;
michael@0 15555 break;
michael@0 15556 case OPS.setGState:
michael@0 15557 var dictName = args[0];
michael@0 15558 var extGState = resources.get('ExtGState');
michael@0 15559
michael@0 15560 if (!isDict(extGState) || !extGState.has(dictName.name)) {
michael@0 15561 break;
michael@0 15562 }
michael@0 15563
michael@0 15564 var gState = extGState.get(dictName.name);
michael@0 15565 self.setGState(resources, gState, operatorList, xref,
michael@0 15566 stateManager);
michael@0 15567 args = [];
michael@0 15568 continue;
michael@0 15569 }
michael@0 15570 operatorList.addOp(fn, args);
michael@0 15571 }
michael@0 15572
michael@0 15573 // Some PDFs don't close all restores inside object/form.
michael@0 15574 // Closing those for them.
michael@0 15575 for (i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
michael@0 15576 operatorList.addOp(OPS.restore, []);
michael@0 15577 }
michael@0 15578
michael@0 15579 return operatorList;
michael@0 15580 },
michael@0 15581
michael@0 15582 getTextContent: function PartialEvaluator_getTextContent(stream, resources,
michael@0 15583 stateManager) {
michael@0 15584
michael@0 15585 stateManager = (stateManager || new StateManager(new TextState()));
michael@0 15586
michael@0 15587 var textContent = {
michael@0 15588 items: [],
michael@0 15589 styles: Object.create(null)
michael@0 15590 };
michael@0 15591 var bidiTexts = textContent.items;
michael@0 15592 var SPACE_FACTOR = 0.35;
michael@0 15593 var MULTI_SPACE_FACTOR = 1.5;
michael@0 15594
michael@0 15595 var self = this;
michael@0 15596 var xref = this.xref;
michael@0 15597
michael@0 15598 resources = (xref.fetchIfRef(resources) || Dict.empty);
michael@0 15599
michael@0 15600 // The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd.
michael@0 15601 var xobjs = null;
michael@0 15602 var xobjsCache = {};
michael@0 15603
michael@0 15604 var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
michael@0 15605
michael@0 15606 var operation;
michael@0 15607 var textState;
michael@0 15608
michael@0 15609 function newTextChunk() {
michael@0 15610 var font = textState.font;
michael@0 15611 if (!(font.loadedName in textContent.styles)) {
michael@0 15612 textContent.styles[font.loadedName] = {
michael@0 15613 fontFamily: font.fallbackName,
michael@0 15614 ascent: font.ascent,
michael@0 15615 descent: font.descent,
michael@0 15616 vertical: font.vertical
michael@0 15617 };
michael@0 15618 }
michael@0 15619 return {
michael@0 15620 str: '',
michael@0 15621 dir: null,
michael@0 15622 width: 0,
michael@0 15623 height: 0,
michael@0 15624 transform: null,
michael@0 15625 fontName: font.loadedName
michael@0 15626 };
michael@0 15627 }
michael@0 15628
michael@0 15629 function runBidi(textChunk) {
michael@0 15630 var bidiResult = PDFJS.bidi(textChunk.str, -1, textState.font.vertical);
michael@0 15631 textChunk.str = bidiResult.str;
michael@0 15632 textChunk.dir = bidiResult.dir;
michael@0 15633 return textChunk;
michael@0 15634 }
michael@0 15635
michael@0 15636 function handleSetFont(fontName, fontRef) {
michael@0 15637 var font = textState.font = self.loadFont(fontName, fontRef, xref,
michael@0 15638 resources, null).translated;
michael@0 15639 textState.fontMatrix = font.fontMatrix ? font.fontMatrix :
michael@0 15640 FONT_IDENTITY_MATRIX;
michael@0 15641 }
michael@0 15642
michael@0 15643 function buildTextGeometry(chars, textChunk) {
michael@0 15644 var font = textState.font;
michael@0 15645 textChunk = textChunk || newTextChunk();
michael@0 15646 if (!textChunk.transform) {
michael@0 15647 // 9.4.4 Text Space Details
michael@0 15648 var tsm = [textState.fontSize * textState.textHScale, 0,
michael@0 15649 0, textState.fontSize,
michael@0 15650 0, textState.textRise];
michael@0 15651 var trm = textChunk.transform = Util.transform(textState.ctm,
michael@0 15652 Util.transform(textState.textMatrix, tsm));
michael@0 15653 if (!font.vertical) {
michael@0 15654 textChunk.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]);
michael@0 15655 } else {
michael@0 15656 textChunk.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]);
michael@0 15657 }
michael@0 15658 }
michael@0 15659 var width = 0;
michael@0 15660 var height = 0;
michael@0 15661 var glyphs = font.charsToGlyphs(chars);
michael@0 15662 var defaultVMetrics = font.defaultVMetrics;
michael@0 15663 for (var i = 0; i < glyphs.length; i++) {
michael@0 15664 var glyph = glyphs[i];
michael@0 15665 if (!glyph) { // Previous glyph was a space.
michael@0 15666 width += textState.wordSpacing * textState.textHScale;
michael@0 15667 continue;
michael@0 15668 }
michael@0 15669 var vMetricX = null;
michael@0 15670 var vMetricY = null;
michael@0 15671 var glyphWidth = null;
michael@0 15672 if (font.vertical) {
michael@0 15673 if (glyph.vmetric) {
michael@0 15674 glyphWidth = glyph.vmetric[0];
michael@0 15675 vMetricX = glyph.vmetric[1];
michael@0 15676 vMetricY = glyph.vmetric[2];
michael@0 15677 } else {
michael@0 15678 glyphWidth = glyph.width;
michael@0 15679 vMetricX = glyph.width * 0.5;
michael@0 15680 vMetricY = defaultVMetrics[2];
michael@0 15681 }
michael@0 15682 } else {
michael@0 15683 glyphWidth = glyph.width;
michael@0 15684 }
michael@0 15685
michael@0 15686 var glyphUnicode = glyph.unicode;
michael@0 15687 if (glyphUnicode in NormalizedUnicodes) {
michael@0 15688 glyphUnicode = NormalizedUnicodes[glyphUnicode];
michael@0 15689 }
michael@0 15690 glyphUnicode = reverseIfRtl(glyphUnicode);
michael@0 15691
michael@0 15692 // The following will calculate the x and y of the individual glyphs.
michael@0 15693 // if (font.vertical) {
michael@0 15694 // tsm[4] -= vMetricX * Math.abs(textState.fontSize) *
michael@0 15695 // textState.fontMatrix[0];
michael@0 15696 // tsm[5] -= vMetricY * textState.fontSize *
michael@0 15697 // textState.fontMatrix[0];
michael@0 15698 // }
michael@0 15699 // var trm = Util.transform(textState.textMatrix, tsm);
michael@0 15700 // var pt = Util.applyTransform([trm[4], trm[5]], textState.ctm);
michael@0 15701 // var x = pt[0];
michael@0 15702 // var y = pt[1];
michael@0 15703
michael@0 15704 var tx = 0;
michael@0 15705 var ty = 0;
michael@0 15706 if (!font.vertical) {
michael@0 15707 var w0 = glyphWidth * textState.fontMatrix[0];
michael@0 15708 tx = (w0 * textState.fontSize + textState.charSpacing) *
michael@0 15709 textState.textHScale;
michael@0 15710 width += tx;
michael@0 15711 } else {
michael@0 15712 var w1 = glyphWidth * textState.fontMatrix[0];
michael@0 15713 ty = w1 * textState.fontSize + textState.charSpacing;
michael@0 15714 height += ty;
michael@0 15715 }
michael@0 15716 textState.translateTextMatrix(tx, ty);
michael@0 15717
michael@0 15718 textChunk.str += glyphUnicode;
michael@0 15719 }
michael@0 15720
michael@0 15721 var a = textState.textLineMatrix[0];
michael@0 15722 var b = textState.textLineMatrix[1];
michael@0 15723 var scaleLineX = Math.sqrt(a * a + b * b);
michael@0 15724 a = textState.ctm[0];
michael@0 15725 b = textState.ctm[1];
michael@0 15726 var scaleCtmX = Math.sqrt(a * a + b * b);
michael@0 15727 if (!font.vertical) {
michael@0 15728 textChunk.width += width * scaleCtmX * scaleLineX;
michael@0 15729 } else {
michael@0 15730 textChunk.height += Math.abs(height * scaleCtmX * scaleLineX);
michael@0 15731 }
michael@0 15732 return textChunk;
michael@0 15733 }
michael@0 15734
michael@0 15735 while ((operation = preprocessor.read())) {
michael@0 15736 textState = stateManager.state;
michael@0 15737 var fn = operation.fn;
michael@0 15738 var args = operation.args;
michael@0 15739 switch (fn) {
michael@0 15740 case OPS.setFont:
michael@0 15741 handleSetFont(args[0].name);
michael@0 15742 textState.fontSize = args[1];
michael@0 15743 break;
michael@0 15744 case OPS.setTextRise:
michael@0 15745 textState.textRise = args[0];
michael@0 15746 break;
michael@0 15747 case OPS.setHScale:
michael@0 15748 textState.textHScale = args[0] / 100;
michael@0 15749 break;
michael@0 15750 case OPS.setLeading:
michael@0 15751 textState.leading = args[0];
michael@0 15752 break;
michael@0 15753 case OPS.moveText:
michael@0 15754 textState.translateTextLineMatrix(args[0], args[1]);
michael@0 15755 textState.textMatrix = textState.textLineMatrix.slice();
michael@0 15756 break;
michael@0 15757 case OPS.setLeadingMoveText:
michael@0 15758 textState.leading = -args[1];
michael@0 15759 textState.translateTextLineMatrix(args[0], args[1]);
michael@0 15760 textState.textMatrix = textState.textLineMatrix.slice();
michael@0 15761 break;
michael@0 15762 case OPS.nextLine:
michael@0 15763 textState.carriageReturn();
michael@0 15764 break;
michael@0 15765 case OPS.setTextMatrix:
michael@0 15766 textState.setTextMatrix(args[0], args[1], args[2], args[3],
michael@0 15767 args[4], args[5]);
michael@0 15768 textState.setTextLineMatrix(args[0], args[1], args[2], args[3],
michael@0 15769 args[4], args[5]);
michael@0 15770 break;
michael@0 15771 case OPS.setCharSpacing:
michael@0 15772 textState.charSpacing = args[0];
michael@0 15773 break;
michael@0 15774 case OPS.setWordSpacing:
michael@0 15775 textState.wordSpacing = args[0];
michael@0 15776 break;
michael@0 15777 case OPS.beginText:
michael@0 15778 textState.textMatrix = IDENTITY_MATRIX.slice();
michael@0 15779 textState.textLineMatrix = IDENTITY_MATRIX.slice();
michael@0 15780 break;
michael@0 15781 case OPS.showSpacedText:
michael@0 15782 var items = args[0];
michael@0 15783 var textChunk = newTextChunk();
michael@0 15784 var offset;
michael@0 15785 for (var j = 0, jj = items.length; j < jj; j++) {
michael@0 15786 if (typeof items[j] === 'string') {
michael@0 15787 buildTextGeometry(items[j], textChunk);
michael@0 15788 } else {
michael@0 15789 var val = items[j] / 1000;
michael@0 15790 if (!textState.font.vertical) {
michael@0 15791 offset = -val * textState.fontSize * textState.textHScale *
michael@0 15792 textState.textMatrix[0];
michael@0 15793 textState.translateTextMatrix(offset, 0);
michael@0 15794 textChunk.width += offset;
michael@0 15795 } else {
michael@0 15796 offset = -val * textState.fontSize * textState.textMatrix[3];
michael@0 15797 textState.translateTextMatrix(0, offset);
michael@0 15798 textChunk.height += offset;
michael@0 15799 }
michael@0 15800 if (items[j] < 0 && textState.font.spaceWidth > 0) {
michael@0 15801 var fakeSpaces = -items[j] / textState.font.spaceWidth;
michael@0 15802 if (fakeSpaces > MULTI_SPACE_FACTOR) {
michael@0 15803 fakeSpaces = Math.round(fakeSpaces);
michael@0 15804 while (fakeSpaces--) {
michael@0 15805 textChunk.str += ' ';
michael@0 15806 }
michael@0 15807 } else if (fakeSpaces > SPACE_FACTOR) {
michael@0 15808 textChunk.str += ' ';
michael@0 15809 }
michael@0 15810 }
michael@0 15811 }
michael@0 15812 }
michael@0 15813 bidiTexts.push(runBidi(textChunk));
michael@0 15814 break;
michael@0 15815 case OPS.showText:
michael@0 15816 bidiTexts.push(runBidi(buildTextGeometry(args[0])));
michael@0 15817 break;
michael@0 15818 case OPS.nextLineShowText:
michael@0 15819 textState.carriageReturn();
michael@0 15820 bidiTexts.push(runBidi(buildTextGeometry(args[0])));
michael@0 15821 break;
michael@0 15822 case OPS.nextLineSetSpacingShowText:
michael@0 15823 textState.wordSpacing = args[0];
michael@0 15824 textState.charSpacing = args[1];
michael@0 15825 textState.carriageReturn();
michael@0 15826 bidiTexts.push(runBidi(buildTextGeometry(args[2])));
michael@0 15827 break;
michael@0 15828 case OPS.paintXObject:
michael@0 15829 if (args[0].code) {
michael@0 15830 break;
michael@0 15831 }
michael@0 15832
michael@0 15833 if (!xobjs) {
michael@0 15834 xobjs = (resources.get('XObject') || Dict.empty);
michael@0 15835 }
michael@0 15836
michael@0 15837 var name = args[0].name;
michael@0 15838 if (xobjsCache.key === name) {
michael@0 15839 if (xobjsCache.texts) {
michael@0 15840 Util.concatenateToArray(bidiTexts, xobjsCache.texts.items);
michael@0 15841 Util.extendObj(textContent.styles, xobjsCache.texts.styles);
michael@0 15842 }
michael@0 15843 break;
michael@0 15844 }
michael@0 15845
michael@0 15846 var xobj = xobjs.get(name);
michael@0 15847 if (!xobj) {
michael@0 15848 break;
michael@0 15849 }
michael@0 15850 assert(isStream(xobj), 'XObject should be a stream');
michael@0 15851
michael@0 15852 var type = xobj.dict.get('Subtype');
michael@0 15853 assert(isName(type),
michael@0 15854 'XObject should have a Name subtype');
michael@0 15855
michael@0 15856 if ('Form' !== type.name) {
michael@0 15857 xobjsCache.key = name;
michael@0 15858 xobjsCache.texts = null;
michael@0 15859 break;
michael@0 15860 }
michael@0 15861
michael@0 15862 stateManager.save();
michael@0 15863 var matrix = xobj.dict.get('Matrix');
michael@0 15864 if (isArray(matrix) && matrix.length === 6) {
michael@0 15865 stateManager.transform(matrix);
michael@0 15866 }
michael@0 15867
michael@0 15868 var formTextContent = this.getTextContent(
michael@0 15869 xobj,
michael@0 15870 xobj.dict.get('Resources') || resources,
michael@0 15871 stateManager
michael@0 15872 );
michael@0 15873 Util.concatenateToArray(bidiTexts, formTextContent.items);
michael@0 15874 Util.extendObj(textContent.styles, formTextContent.styles);
michael@0 15875 stateManager.restore();
michael@0 15876
michael@0 15877 xobjsCache.key = name;
michael@0 15878 xobjsCache.texts = formTextContent;
michael@0 15879 break;
michael@0 15880 case OPS.setGState:
michael@0 15881 var dictName = args[0];
michael@0 15882 var extGState = resources.get('ExtGState');
michael@0 15883
michael@0 15884 if (!isDict(extGState) || !extGState.has(dictName.name)) {
michael@0 15885 break;
michael@0 15886 }
michael@0 15887
michael@0 15888 var gsState = extGState.get(dictName.name);
michael@0 15889
michael@0 15890 for (var i = 0; i < gsState.length; i++) {
michael@0 15891 if (gsState[i] === 'Font') {
michael@0 15892 handleSetFont(args[0].name);
michael@0 15893 }
michael@0 15894 }
michael@0 15895 break;
michael@0 15896 } // switch
michael@0 15897 } // while
michael@0 15898
michael@0 15899 return textContent;
michael@0 15900 },
michael@0 15901
michael@0 15902 extractDataStructures: function
michael@0 15903 partialEvaluatorExtractDataStructures(dict, baseDict,
michael@0 15904 xref, properties) {
michael@0 15905 // 9.10.2
michael@0 15906 var toUnicode = (dict.get('ToUnicode') || baseDict.get('ToUnicode'));
michael@0 15907 if (toUnicode) {
michael@0 15908 properties.toUnicode = this.readToUnicode(toUnicode, xref, properties);
michael@0 15909 }
michael@0 15910 if (properties.composite) {
michael@0 15911 // CIDSystemInfo helps to match CID to glyphs
michael@0 15912 var cidSystemInfo = dict.get('CIDSystemInfo');
michael@0 15913 if (isDict(cidSystemInfo)) {
michael@0 15914 properties.cidSystemInfo = {
michael@0 15915 registry: cidSystemInfo.get('Registry'),
michael@0 15916 ordering: cidSystemInfo.get('Ordering'),
michael@0 15917 supplement: cidSystemInfo.get('Supplement')
michael@0 15918 };
michael@0 15919 }
michael@0 15920
michael@0 15921 var cidToGidMap = dict.get('CIDToGIDMap');
michael@0 15922 if (isStream(cidToGidMap)) {
michael@0 15923 properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
michael@0 15924 }
michael@0 15925 }
michael@0 15926
michael@0 15927 // Based on 9.6.6 of the spec the encoding can come from multiple places
michael@0 15928 // and depends on the font type. The base encoding and differences are
michael@0 15929 // read here, but the encoding that is actually used is chosen during
michael@0 15930 // glyph mapping in the font.
michael@0 15931 // TODO: Loading the built in encoding in the font would allow the
michael@0 15932 // differences to be merged in here not require us to hold on to it.
michael@0 15933 var differences = [];
michael@0 15934 var baseEncodingName = null;
michael@0 15935 var encoding;
michael@0 15936 if (dict.has('Encoding')) {
michael@0 15937 encoding = dict.get('Encoding');
michael@0 15938 if (isDict(encoding)) {
michael@0 15939 baseEncodingName = encoding.get('BaseEncoding');
michael@0 15940 baseEncodingName = (isName(baseEncodingName) ?
michael@0 15941 baseEncodingName.name : null);
michael@0 15942 // Load the differences between the base and original
michael@0 15943 if (encoding.has('Differences')) {
michael@0 15944 var diffEncoding = encoding.get('Differences');
michael@0 15945 var index = 0;
michael@0 15946 for (var j = 0, jj = diffEncoding.length; j < jj; j++) {
michael@0 15947 var data = diffEncoding[j];
michael@0 15948 if (isNum(data)) {
michael@0 15949 index = data;
michael@0 15950 } else {
michael@0 15951 differences[index++] = data.name;
michael@0 15952 }
michael@0 15953 }
michael@0 15954 }
michael@0 15955 } else if (isName(encoding)) {
michael@0 15956 baseEncodingName = encoding.name;
michael@0 15957 } else {
michael@0 15958 error('Encoding is not a Name nor a Dict');
michael@0 15959 }
michael@0 15960 // According to table 114 if the encoding is a named encoding it must be
michael@0 15961 // one of these predefined encodings.
michael@0 15962 if ((baseEncodingName !== 'MacRomanEncoding' &&
michael@0 15963 baseEncodingName !== 'MacExpertEncoding' &&
michael@0 15964 baseEncodingName !== 'WinAnsiEncoding')) {
michael@0 15965 baseEncodingName = null;
michael@0 15966 }
michael@0 15967 }
michael@0 15968
michael@0 15969 if (baseEncodingName) {
michael@0 15970 properties.defaultEncoding = Encodings[baseEncodingName].slice();
michael@0 15971 } else {
michael@0 15972 encoding = (properties.type === 'TrueType' ?
michael@0 15973 Encodings.WinAnsiEncoding : Encodings.StandardEncoding);
michael@0 15974 // The Symbolic attribute can be misused for regular fonts
michael@0 15975 // Heuristic: we have to check if the font is a standard one also
michael@0 15976 if (!!(properties.flags & FontFlags.Symbolic)) {
michael@0 15977 encoding = (!properties.file && /Symbol/i.test(properties.name) ?
michael@0 15978 Encodings.SymbolSetEncoding :
michael@0 15979 Encodings.MacRomanEncoding);
michael@0 15980 }
michael@0 15981 properties.defaultEncoding = encoding;
michael@0 15982 }
michael@0 15983
michael@0 15984 properties.differences = differences;
michael@0 15985 properties.baseEncodingName = baseEncodingName;
michael@0 15986 properties.dict = dict;
michael@0 15987 },
michael@0 15988
michael@0 15989 readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) {
michael@0 15990 var cmapObj = toUnicode;
michael@0 15991 if (isName(cmapObj)) {
michael@0 15992 return CMapFactory.create(cmapObj).map;
michael@0 15993 } else if (isStream(cmapObj)) {
michael@0 15994 var cmap = CMapFactory.create(cmapObj).map;
michael@0 15995 // Convert UTF-16BE
michael@0 15996 // NOTE: cmap can be a sparse array, so use forEach instead of for(;;)
michael@0 15997 // to iterate over all keys.
michael@0 15998 cmap.forEach(function(token, i) {
michael@0 15999 var str = [];
michael@0 16000 for (var k = 0; k < token.length; k += 2) {
michael@0 16001 var w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
michael@0 16002 if ((w1 & 0xF800) !== 0xD800) { // w1 < 0xD800 || w1 > 0xDFFF
michael@0 16003 str.push(w1);
michael@0 16004 continue;
michael@0 16005 }
michael@0 16006 k += 2;
michael@0 16007 var w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
michael@0 16008 str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
michael@0 16009 }
michael@0 16010 cmap[i] = String.fromCharCode.apply(String, str);
michael@0 16011 });
michael@0 16012 return cmap;
michael@0 16013 }
michael@0 16014 return null;
michael@0 16015 },
michael@0 16016
michael@0 16017 readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) {
michael@0 16018 // Extract the encoding from the CIDToGIDMap
michael@0 16019 var glyphsData = cidToGidStream.getBytes();
michael@0 16020
michael@0 16021 // Set encoding 0 to later verify the font has an encoding
michael@0 16022 var result = [];
michael@0 16023 for (var j = 0, jj = glyphsData.length; j < jj; j++) {
michael@0 16024 var glyphID = (glyphsData[j++] << 8) | glyphsData[j];
michael@0 16025 if (glyphID === 0) {
michael@0 16026 continue;
michael@0 16027 }
michael@0 16028 var code = j >> 1;
michael@0 16029 result[code] = glyphID;
michael@0 16030 }
michael@0 16031 return result;
michael@0 16032 },
michael@0 16033
michael@0 16034 extractWidths: function PartialEvaluator_extractWidths(dict, xref,
michael@0 16035 descriptor,
michael@0 16036 properties) {
michael@0 16037 var glyphsWidths = [];
michael@0 16038 var defaultWidth = 0;
michael@0 16039 var glyphsVMetrics = [];
michael@0 16040 var defaultVMetrics;
michael@0 16041 var i, ii, j, jj, start, code, widths;
michael@0 16042 if (properties.composite) {
michael@0 16043 defaultWidth = dict.get('DW') || 1000;
michael@0 16044
michael@0 16045 widths = dict.get('W');
michael@0 16046 if (widths) {
michael@0 16047 for (i = 0, ii = widths.length; i < ii; i++) {
michael@0 16048 start = widths[i++];
michael@0 16049 code = xref.fetchIfRef(widths[i]);
michael@0 16050 if (isArray(code)) {
michael@0 16051 for (j = 0, jj = code.length; j < jj; j++) {
michael@0 16052 glyphsWidths[start++] = code[j];
michael@0 16053 }
michael@0 16054 } else {
michael@0 16055 var width = widths[++i];
michael@0 16056 for (j = start; j <= code; j++) {
michael@0 16057 glyphsWidths[j] = width;
michael@0 16058 }
michael@0 16059 }
michael@0 16060 }
michael@0 16061 }
michael@0 16062
michael@0 16063 if (properties.vertical) {
michael@0 16064 var vmetrics = (dict.get('DW2') || [880, -1000]);
michael@0 16065 defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]];
michael@0 16066 vmetrics = dict.get('W2');
michael@0 16067 if (vmetrics) {
michael@0 16068 for (i = 0, ii = vmetrics.length; i < ii; i++) {
michael@0 16069 start = vmetrics[i++];
michael@0 16070 code = xref.fetchIfRef(vmetrics[i]);
michael@0 16071 if (isArray(code)) {
michael@0 16072 for (j = 0, jj = code.length; j < jj; j++) {
michael@0 16073 glyphsVMetrics[start++] = [code[j++], code[j++], code[j]];
michael@0 16074 }
michael@0 16075 } else {
michael@0 16076 var vmetric = [vmetrics[++i], vmetrics[++i], vmetrics[++i]];
michael@0 16077 for (j = start; j <= code; j++) {
michael@0 16078 glyphsVMetrics[j] = vmetric;
michael@0 16079 }
michael@0 16080 }
michael@0 16081 }
michael@0 16082 }
michael@0 16083 }
michael@0 16084 } else {
michael@0 16085 var firstChar = properties.firstChar;
michael@0 16086 widths = dict.get('Widths');
michael@0 16087 if (widths) {
michael@0 16088 j = firstChar;
michael@0 16089 for (i = 0, ii = widths.length; i < ii; i++) {
michael@0 16090 glyphsWidths[j++] = widths[i];
michael@0 16091 }
michael@0 16092 defaultWidth = (parseFloat(descriptor.get('MissingWidth')) || 0);
michael@0 16093 } else {
michael@0 16094 // Trying get the BaseFont metrics (see comment above).
michael@0 16095 var baseFontName = dict.get('BaseFont');
michael@0 16096 if (isName(baseFontName)) {
michael@0 16097 var metrics = this.getBaseFontMetrics(baseFontName.name);
michael@0 16098
michael@0 16099 glyphsWidths = this.buildCharCodeToWidth(metrics.widths,
michael@0 16100 properties);
michael@0 16101 defaultWidth = metrics.defaultWidth;
michael@0 16102 }
michael@0 16103 }
michael@0 16104 }
michael@0 16105
michael@0 16106 // Heuristic: detection of monospace font by checking all non-zero widths
michael@0 16107 var isMonospace = true;
michael@0 16108 var firstWidth = defaultWidth;
michael@0 16109 for (var glyph in glyphsWidths) {
michael@0 16110 var glyphWidth = glyphsWidths[glyph];
michael@0 16111 if (!glyphWidth) {
michael@0 16112 continue;
michael@0 16113 }
michael@0 16114 if (!firstWidth) {
michael@0 16115 firstWidth = glyphWidth;
michael@0 16116 continue;
michael@0 16117 }
michael@0 16118 if (firstWidth != glyphWidth) {
michael@0 16119 isMonospace = false;
michael@0 16120 break;
michael@0 16121 }
michael@0 16122 }
michael@0 16123 if (isMonospace) {
michael@0 16124 properties.flags |= FontFlags.FixedPitch;
michael@0 16125 }
michael@0 16126
michael@0 16127 properties.defaultWidth = defaultWidth;
michael@0 16128 properties.widths = glyphsWidths;
michael@0 16129 properties.defaultVMetrics = defaultVMetrics;
michael@0 16130 properties.vmetrics = glyphsVMetrics;
michael@0 16131 },
michael@0 16132
michael@0 16133 isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) {
michael@0 16134 // Simulating descriptor flags attribute
michael@0 16135 var fontNameWoStyle = baseFontName.split('-')[0];
michael@0 16136 return (fontNameWoStyle in serifFonts) ||
michael@0 16137 (fontNameWoStyle.search(/serif/gi) !== -1);
michael@0 16138 },
michael@0 16139
michael@0 16140 getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
michael@0 16141 var defaultWidth = 0;
michael@0 16142 var widths = [];
michael@0 16143 var monospace = false;
michael@0 16144 var lookupName = (stdFontMap[name] || name);
michael@0 16145
michael@0 16146 if (!(lookupName in Metrics)) {
michael@0 16147 // Use default fonts for looking up font metrics if the passed
michael@0 16148 // font is not a base font
michael@0 16149 if (this.isSerifFont(name)) {
michael@0 16150 lookupName = 'Times-Roman';
michael@0 16151 } else {
michael@0 16152 lookupName = 'Helvetica';
michael@0 16153 }
michael@0 16154 }
michael@0 16155 var glyphWidths = Metrics[lookupName];
michael@0 16156
michael@0 16157 if (isNum(glyphWidths)) {
michael@0 16158 defaultWidth = glyphWidths;
michael@0 16159 monospace = true;
michael@0 16160 } else {
michael@0 16161 widths = glyphWidths;
michael@0 16162 }
michael@0 16163
michael@0 16164 return {
michael@0 16165 defaultWidth: defaultWidth,
michael@0 16166 monospace: monospace,
michael@0 16167 widths: widths
michael@0 16168 };
michael@0 16169 },
michael@0 16170
michael@0 16171 buildCharCodeToWidth:
michael@0 16172 function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName,
michael@0 16173 properties) {
michael@0 16174 var widths = Object.create(null);
michael@0 16175 var differences = properties.differences;
michael@0 16176 var encoding = properties.defaultEncoding;
michael@0 16177 for (var charCode = 0; charCode < 256; charCode++) {
michael@0 16178 if (charCode in differences &&
michael@0 16179 widthsByGlyphName[differences[charCode]]) {
michael@0 16180 widths[charCode] = widthsByGlyphName[differences[charCode]];
michael@0 16181 continue;
michael@0 16182 }
michael@0 16183 if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {
michael@0 16184 widths[charCode] = widthsByGlyphName[encoding[charCode]];
michael@0 16185 continue;
michael@0 16186 }
michael@0 16187 }
michael@0 16188 return widths;
michael@0 16189 },
michael@0 16190
michael@0 16191 preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict, xref) {
michael@0 16192 var baseDict = dict;
michael@0 16193 var type = dict.get('Subtype');
michael@0 16194 assert(isName(type), 'invalid font Subtype');
michael@0 16195
michael@0 16196 var composite = false;
michael@0 16197 var uint8array;
michael@0 16198 if (type.name == 'Type0') {
michael@0 16199 // If font is a composite
michael@0 16200 // - get the descendant font
michael@0 16201 // - set the type according to the descendant font
michael@0 16202 // - get the FontDescriptor from the descendant font
michael@0 16203 var df = dict.get('DescendantFonts');
michael@0 16204 if (!df) {
michael@0 16205 error('Descendant fonts are not specified');
michael@0 16206 }
michael@0 16207 dict = (isArray(df) ? xref.fetchIfRef(df[0]) : df);
michael@0 16208
michael@0 16209 type = dict.get('Subtype');
michael@0 16210 assert(isName(type), 'invalid font Subtype');
michael@0 16211 composite = true;
michael@0 16212 }
michael@0 16213
michael@0 16214 var descriptor = dict.get('FontDescriptor');
michael@0 16215 if (descriptor) {
michael@0 16216 var hash = new MurmurHash3_64();
michael@0 16217 var encoding = baseDict.getRaw('Encoding');
michael@0 16218 if (isName(encoding)) {
michael@0 16219 hash.update(encoding.name);
michael@0 16220 } else if (isRef(encoding)) {
michael@0 16221 hash.update(encoding.num + '_' + encoding.gen);
michael@0 16222 }
michael@0 16223
michael@0 16224 var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode');
michael@0 16225 if (isStream(toUnicode)) {
michael@0 16226 var stream = toUnicode.str || toUnicode;
michael@0 16227 uint8array = stream.buffer ?
michael@0 16228 new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) :
michael@0 16229 new Uint8Array(stream.bytes.buffer,
michael@0 16230 stream.start, stream.end - stream.start);
michael@0 16231 hash.update(uint8array);
michael@0 16232
michael@0 16233 } else if (isName(toUnicode)) {
michael@0 16234 hash.update(toUnicode.name);
michael@0 16235 }
michael@0 16236
michael@0 16237 var widths = dict.get('Widths') || baseDict.get('Widths');
michael@0 16238 if (widths) {
michael@0 16239 uint8array = new Uint8Array(new Uint32Array(widths).buffer);
michael@0 16240 hash.update(uint8array);
michael@0 16241 }
michael@0 16242 }
michael@0 16243
michael@0 16244 return {
michael@0 16245 descriptor: descriptor,
michael@0 16246 dict: dict,
michael@0 16247 baseDict: baseDict,
michael@0 16248 composite: composite,
michael@0 16249 hash: hash ? hash.hexdigest() : ''
michael@0 16250 };
michael@0 16251 },
michael@0 16252
michael@0 16253 translateFont: function PartialEvaluator_translateFont(preEvaluatedFont,
michael@0 16254 xref) {
michael@0 16255 var baseDict = preEvaluatedFont.baseDict;
michael@0 16256 var dict = preEvaluatedFont.dict;
michael@0 16257 var composite = preEvaluatedFont.composite;
michael@0 16258 var descriptor = preEvaluatedFont.descriptor;
michael@0 16259 var type = dict.get('Subtype');
michael@0 16260 var maxCharIndex = (composite ? 0xFFFF : 0xFF);
michael@0 16261 var properties;
michael@0 16262
michael@0 16263 if (!descriptor) {
michael@0 16264 if (type.name == 'Type3') {
michael@0 16265 // FontDescriptor is only required for Type3 fonts when the document
michael@0 16266 // is a tagged pdf. Create a barbebones one to get by.
michael@0 16267 descriptor = new Dict(null);
michael@0 16268 descriptor.set('FontName', Name.get(type.name));
michael@0 16269 } else {
michael@0 16270 // Before PDF 1.5 if the font was one of the base 14 fonts, having a
michael@0 16271 // FontDescriptor was not required.
michael@0 16272 // This case is here for compatibility.
michael@0 16273 var baseFontName = dict.get('BaseFont');
michael@0 16274 if (!isName(baseFontName)) {
michael@0 16275 error('Base font is not specified');
michael@0 16276 }
michael@0 16277
michael@0 16278 // Using base font name as a font name.
michael@0 16279 baseFontName = baseFontName.name.replace(/[,_]/g, '-');
michael@0 16280 var metrics = this.getBaseFontMetrics(baseFontName);
michael@0 16281
michael@0 16282 // Simulating descriptor flags attribute
michael@0 16283 var fontNameWoStyle = baseFontName.split('-')[0];
michael@0 16284 var flags =
michael@0 16285 (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) |
michael@0 16286 (metrics.monospace ? FontFlags.FixedPitch : 0) |
michael@0 16287 (symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
michael@0 16288 FontFlags.Nonsymbolic);
michael@0 16289
michael@0 16290 properties = {
michael@0 16291 type: type.name,
michael@0 16292 name: baseFontName,
michael@0 16293 widths: metrics.widths,
michael@0 16294 defaultWidth: metrics.defaultWidth,
michael@0 16295 flags: flags,
michael@0 16296 firstChar: 0,
michael@0 16297 lastChar: maxCharIndex
michael@0 16298 };
michael@0 16299 this.extractDataStructures(dict, dict, xref, properties);
michael@0 16300 properties.widths = this.buildCharCodeToWidth(metrics.widths,
michael@0 16301 properties);
michael@0 16302 return new Font(baseFontName, null, properties);
michael@0 16303 }
michael@0 16304 }
michael@0 16305
michael@0 16306 // According to the spec if 'FontDescriptor' is declared, 'FirstChar',
michael@0 16307 // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem
michael@0 16308 // to ignore this rule when a variant of a standart font is used.
michael@0 16309 // TODO Fill the width array depending on which of the base font this is
michael@0 16310 // a variant.
michael@0 16311 var firstChar = (dict.get('FirstChar') || 0);
michael@0 16312 var lastChar = (dict.get('LastChar') || maxCharIndex);
michael@0 16313
michael@0 16314 var fontName = descriptor.get('FontName');
michael@0 16315 var baseFont = dict.get('BaseFont');
michael@0 16316 // Some bad PDFs have a string as the font name.
michael@0 16317 if (isString(fontName)) {
michael@0 16318 fontName = Name.get(fontName);
michael@0 16319 }
michael@0 16320 if (isString(baseFont)) {
michael@0 16321 baseFont = Name.get(baseFont);
michael@0 16322 }
michael@0 16323
michael@0 16324 if (type.name !== 'Type3') {
michael@0 16325 var fontNameStr = fontName && fontName.name;
michael@0 16326 var baseFontStr = baseFont && baseFont.name;
michael@0 16327 if (fontNameStr !== baseFontStr) {
michael@0 16328 info('The FontDescriptor\'s FontName is "' + fontNameStr +
michael@0 16329 '" but should be the same as the Font\'s BaseFont "' +
michael@0 16330 baseFontStr + '"');
michael@0 16331 // Workaround for cases where e.g. fontNameStr = 'Arial' and
michael@0 16332 // baseFontStr = 'Arial,Bold' (needed when no font file is embedded).
michael@0 16333 if (fontNameStr && baseFontStr &&
michael@0 16334 baseFontStr.search(fontNameStr) === 0) {
michael@0 16335 fontName = baseFont;
michael@0 16336 }
michael@0 16337 }
michael@0 16338 }
michael@0 16339 fontName = (fontName || baseFont);
michael@0 16340
michael@0 16341 assert(isName(fontName), 'invalid font name');
michael@0 16342
michael@0 16343 var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
michael@0 16344 if (fontFile) {
michael@0 16345 if (fontFile.dict) {
michael@0 16346 var subtype = fontFile.dict.get('Subtype');
michael@0 16347 if (subtype) {
michael@0 16348 subtype = subtype.name;
michael@0 16349 }
michael@0 16350 var length1 = fontFile.dict.get('Length1');
michael@0 16351 var length2 = fontFile.dict.get('Length2');
michael@0 16352 }
michael@0 16353 }
michael@0 16354
michael@0 16355 properties = {
michael@0 16356 type: type.name,
michael@0 16357 name: fontName.name,
michael@0 16358 subtype: subtype,
michael@0 16359 file: fontFile,
michael@0 16360 length1: length1,
michael@0 16361 length2: length2,
michael@0 16362 loadedName: baseDict.loadedName,
michael@0 16363 composite: composite,
michael@0 16364 wideChars: composite,
michael@0 16365 fixedPitch: false,
michael@0 16366 fontMatrix: (dict.get('FontMatrix') || FONT_IDENTITY_MATRIX),
michael@0 16367 firstChar: firstChar || 0,
michael@0 16368 lastChar: (lastChar || maxCharIndex),
michael@0 16369 bbox: descriptor.get('FontBBox'),
michael@0 16370 ascent: descriptor.get('Ascent'),
michael@0 16371 descent: descriptor.get('Descent'),
michael@0 16372 xHeight: descriptor.get('XHeight'),
michael@0 16373 capHeight: descriptor.get('CapHeight'),
michael@0 16374 flags: descriptor.get('Flags'),
michael@0 16375 italicAngle: descriptor.get('ItalicAngle'),
michael@0 16376 coded: false
michael@0 16377 };
michael@0 16378
michael@0 16379 if (composite) {
michael@0 16380 var cidEncoding = baseDict.get('Encoding');
michael@0 16381 if (isName(cidEncoding)) {
michael@0 16382 properties.cidEncoding = cidEncoding.name;
michael@0 16383 }
michael@0 16384 properties.cMap = CMapFactory.create(cidEncoding,
michael@0 16385 { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null);
michael@0 16386 properties.vertical = properties.cMap.vertical;
michael@0 16387 }
michael@0 16388 this.extractDataStructures(dict, baseDict, xref, properties);
michael@0 16389 this.extractWidths(dict, xref, descriptor, properties);
michael@0 16390
michael@0 16391 if (type.name === 'Type3') {
michael@0 16392 properties.coded = true;
michael@0 16393 }
michael@0 16394
michael@0 16395 return new Font(fontName.name, fontFile, properties);
michael@0 16396 }
michael@0 16397 };
michael@0 16398
michael@0 16399 return PartialEvaluator;
michael@0 16400 })();
michael@0 16401
michael@0 16402 var OperatorList = (function OperatorListClosure() {
michael@0 16403 var CHUNK_SIZE = 1000;
michael@0 16404 var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size
michael@0 16405
michael@0 16406 function getTransfers(queue) {
michael@0 16407 var transfers = [];
michael@0 16408 var fnArray = queue.fnArray, argsArray = queue.argsArray;
michael@0 16409 for (var i = 0, ii = queue.length; i < ii; i++) {
michael@0 16410 switch (fnArray[i]) {
michael@0 16411 case OPS.paintInlineImageXObject:
michael@0 16412 case OPS.paintInlineImageXObjectGroup:
michael@0 16413 case OPS.paintImageMaskXObject:
michael@0 16414 var arg = argsArray[i][0]; // first param in imgData
michael@0 16415 if (!arg.cached) {
michael@0 16416 transfers.push(arg.data.buffer);
michael@0 16417 }
michael@0 16418 break;
michael@0 16419 }
michael@0 16420 }
michael@0 16421 return transfers;
michael@0 16422 }
michael@0 16423
michael@0 16424 function OperatorList(intent, messageHandler, pageIndex) {
michael@0 16425 this.messageHandler = messageHandler;
michael@0 16426 this.fnArray = [];
michael@0 16427 this.argsArray = [];
michael@0 16428 this.dependencies = {};
michael@0 16429 this.pageIndex = pageIndex;
michael@0 16430 this.intent = intent;
michael@0 16431 }
michael@0 16432
michael@0 16433 OperatorList.prototype = {
michael@0 16434 get length() {
michael@0 16435 return this.argsArray.length;
michael@0 16436 },
michael@0 16437
michael@0 16438 addOp: function(fn, args) {
michael@0 16439 this.fnArray.push(fn);
michael@0 16440 this.argsArray.push(args);
michael@0 16441 if (this.messageHandler) {
michael@0 16442 if (this.fnArray.length >= CHUNK_SIZE) {
michael@0 16443 this.flush();
michael@0 16444 } else if (this.fnArray.length >= CHUNK_SIZE_ABOUT &&
michael@0 16445 (fn === OPS.restore || fn === OPS.endText)) {
michael@0 16446 // heuristic to flush on boundary of restore or endText
michael@0 16447 this.flush();
michael@0 16448 }
michael@0 16449 }
michael@0 16450 },
michael@0 16451
michael@0 16452 addDependency: function(dependency) {
michael@0 16453 if (dependency in this.dependencies) {
michael@0 16454 return;
michael@0 16455 }
michael@0 16456 this.dependencies[dependency] = true;
michael@0 16457 this.addOp(OPS.dependency, [dependency]);
michael@0 16458 },
michael@0 16459
michael@0 16460 addDependencies: function(dependencies) {
michael@0 16461 for (var key in dependencies) {
michael@0 16462 this.addDependency(key);
michael@0 16463 }
michael@0 16464 },
michael@0 16465
michael@0 16466 addOpList: function(opList) {
michael@0 16467 Util.extendObj(this.dependencies, opList.dependencies);
michael@0 16468 for (var i = 0, ii = opList.length; i < ii; i++) {
michael@0 16469 this.addOp(opList.fnArray[i], opList.argsArray[i]);
michael@0 16470 }
michael@0 16471 },
michael@0 16472
michael@0 16473 getIR: function() {
michael@0 16474 return {
michael@0 16475 fnArray: this.fnArray,
michael@0 16476 argsArray: this.argsArray,
michael@0 16477 length: this.length
michael@0 16478 };
michael@0 16479 },
michael@0 16480
michael@0 16481 flush: function(lastChunk) {
michael@0 16482 new QueueOptimizer().optimize(this);
michael@0 16483 var transfers = getTransfers(this);
michael@0 16484 this.messageHandler.send('RenderPageChunk', {
michael@0 16485 operatorList: {
michael@0 16486 fnArray: this.fnArray,
michael@0 16487 argsArray: this.argsArray,
michael@0 16488 lastChunk: lastChunk,
michael@0 16489 length: this.length
michael@0 16490 },
michael@0 16491 pageIndex: this.pageIndex,
michael@0 16492 intent: this.intent
michael@0 16493 }, null, transfers);
michael@0 16494 this.dependencies = {};
michael@0 16495 this.fnArray.length = 0;
michael@0 16496 this.argsArray.length = 0;
michael@0 16497 }
michael@0 16498 };
michael@0 16499
michael@0 16500 return OperatorList;
michael@0 16501 })();
michael@0 16502
michael@0 16503 var StateManager = (function StateManagerClosure() {
michael@0 16504 function StateManager(initialState) {
michael@0 16505 this.state = initialState;
michael@0 16506 this.stateStack = [];
michael@0 16507 }
michael@0 16508 StateManager.prototype = {
michael@0 16509 save: function () {
michael@0 16510 var old = this.state;
michael@0 16511 this.stateStack.push(this.state);
michael@0 16512 this.state = old.clone();
michael@0 16513 },
michael@0 16514 restore: function () {
michael@0 16515 var prev = this.stateStack.pop();
michael@0 16516 if (prev) {
michael@0 16517 this.state = prev;
michael@0 16518 }
michael@0 16519 },
michael@0 16520 transform: function (args) {
michael@0 16521 this.state.ctm = Util.transform(this.state.ctm, args);
michael@0 16522 }
michael@0 16523 };
michael@0 16524 return StateManager;
michael@0 16525 })();
michael@0 16526
michael@0 16527 var TextState = (function TextStateClosure() {
michael@0 16528 function TextState() {
michael@0 16529 this.ctm = new Float32Array(IDENTITY_MATRIX);
michael@0 16530 this.fontSize = 0;
michael@0 16531 this.font = null;
michael@0 16532 this.fontMatrix = FONT_IDENTITY_MATRIX;
michael@0 16533 this.textMatrix = IDENTITY_MATRIX.slice();
michael@0 16534 this.textLineMatrix = IDENTITY_MATRIX.slice();
michael@0 16535 this.charSpacing = 0;
michael@0 16536 this.wordSpacing = 0;
michael@0 16537 this.leading = 0;
michael@0 16538 this.textHScale = 1;
michael@0 16539 this.textRise = 0;
michael@0 16540 }
michael@0 16541
michael@0 16542 TextState.prototype = {
michael@0 16543 setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
michael@0 16544 var m = this.textMatrix;
michael@0 16545 m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f;
michael@0 16546 },
michael@0 16547 setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
michael@0 16548 var m = this.textLineMatrix;
michael@0 16549 m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f;
michael@0 16550 },
michael@0 16551 translateTextMatrix: function TextState_translateTextMatrix(x, y) {
michael@0 16552 var m = this.textMatrix;
michael@0 16553 m[4] = m[0] * x + m[2] * y + m[4];
michael@0 16554 m[5] = m[1] * x + m[3] * y + m[5];
michael@0 16555 },
michael@0 16556 translateTextLineMatrix: function TextState_translateTextMatrix(x, y) {
michael@0 16557 var m = this.textLineMatrix;
michael@0 16558 m[4] = m[0] * x + m[2] * y + m[4];
michael@0 16559 m[5] = m[1] * x + m[3] * y + m[5];
michael@0 16560 },
michael@0 16561 calcRenderMatrix: function TextState_calcRendeMatrix(ctm) {
michael@0 16562 // 9.4.4 Text Space Details
michael@0 16563 var tsm = [this.fontSize * this.textHScale, 0,
michael@0 16564 0, this.fontSize,
michael@0 16565 0, this.textRise];
michael@0 16566 return Util.transform(ctm, Util.transform(this.textMatrix, tsm));
michael@0 16567 },
michael@0 16568 carriageReturn: function TextState_carriageReturn() {
michael@0 16569 this.translateTextLineMatrix(0, -this.leading);
michael@0 16570 this.textMatrix = this.textLineMatrix.slice();
michael@0 16571 },
michael@0 16572 clone: function TextState_clone() {
michael@0 16573 var clone = Object.create(this);
michael@0 16574 clone.textMatrix = this.textMatrix.slice();
michael@0 16575 clone.textLineMatrix = this.textLineMatrix.slice();
michael@0 16576 clone.fontMatrix = this.fontMatrix.slice();
michael@0 16577 return clone;
michael@0 16578 }
michael@0 16579 };
michael@0 16580 return TextState;
michael@0 16581 })();
michael@0 16582
michael@0 16583 var EvalState = (function EvalStateClosure() {
michael@0 16584 function EvalState() {
michael@0 16585 this.ctm = new Float32Array(IDENTITY_MATRIX);
michael@0 16586 this.font = null;
michael@0 16587 this.textRenderingMode = TextRenderingMode.FILL;
michael@0 16588 }
michael@0 16589 EvalState.prototype = {
michael@0 16590 clone: function CanvasExtraState_clone() {
michael@0 16591 return Object.create(this);
michael@0 16592 },
michael@0 16593 };
michael@0 16594 return EvalState;
michael@0 16595 })();
michael@0 16596
michael@0 16597 var EvaluatorPreprocessor = (function EvaluatorPreprocessorClosure() {
michael@0 16598 // Specifies properties for each command
michael@0 16599 //
michael@0 16600 // If variableArgs === true: [0, `numArgs`] expected
michael@0 16601 // If variableArgs === false: exactly `numArgs` expected
michael@0 16602 var OP_MAP = {
michael@0 16603 // Graphic state
michael@0 16604 w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false },
michael@0 16605 J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false },
michael@0 16606 j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false },
michael@0 16607 M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false },
michael@0 16608 d: { id: OPS.setDash, numArgs: 2, variableArgs: false },
michael@0 16609 ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false },
michael@0 16610 i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false },
michael@0 16611 gs: { id: OPS.setGState, numArgs: 1, variableArgs: false },
michael@0 16612 q: { id: OPS.save, numArgs: 0, variableArgs: false },
michael@0 16613 Q: { id: OPS.restore, numArgs: 0, variableArgs: false },
michael@0 16614 cm: { id: OPS.transform, numArgs: 6, variableArgs: false },
michael@0 16615
michael@0 16616 // Path
michael@0 16617 m: { id: OPS.moveTo, numArgs: 2, variableArgs: false },
michael@0 16618 l: { id: OPS.lineTo, numArgs: 2, variableArgs: false },
michael@0 16619 c: { id: OPS.curveTo, numArgs: 6, variableArgs: false },
michael@0 16620 v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false },
michael@0 16621 y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false },
michael@0 16622 h: { id: OPS.closePath, numArgs: 0, variableArgs: false },
michael@0 16623 re: { id: OPS.rectangle, numArgs: 4, variableArgs: false },
michael@0 16624 S: { id: OPS.stroke, numArgs: 0, variableArgs: false },
michael@0 16625 s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false },
michael@0 16626 f: { id: OPS.fill, numArgs: 0, variableArgs: false },
michael@0 16627 F: { id: OPS.fill, numArgs: 0, variableArgs: false },
michael@0 16628 'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false },
michael@0 16629 B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false },
michael@0 16630 'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false },
michael@0 16631 b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false },
michael@0 16632 'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false },
michael@0 16633 n: { id: OPS.endPath, numArgs: 0, variableArgs: false },
michael@0 16634
michael@0 16635 // Clipping
michael@0 16636 W: { id: OPS.clip, numArgs: 0, variableArgs: false },
michael@0 16637 'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false },
michael@0 16638
michael@0 16639 // Text
michael@0 16640 BT: { id: OPS.beginText, numArgs: 0, variableArgs: false },
michael@0 16641 ET: { id: OPS.endText, numArgs: 0, variableArgs: false },
michael@0 16642 Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false },
michael@0 16643 Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false },
michael@0 16644 Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false },
michael@0 16645 TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false },
michael@0 16646 Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false },
michael@0 16647 Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false },
michael@0 16648 Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false },
michael@0 16649 Td: { id: OPS.moveText, numArgs: 2, variableArgs: false },
michael@0 16650 TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false },
michael@0 16651 Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false },
michael@0 16652 'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false },
michael@0 16653 Tj: { id: OPS.showText, numArgs: 1, variableArgs: false },
michael@0 16654 TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false },
michael@0 16655 '\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false },
michael@0 16656 '"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3,
michael@0 16657 variableArgs: false },
michael@0 16658
michael@0 16659 // Type3 fonts
michael@0 16660 d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false },
michael@0 16661 d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false },
michael@0 16662
michael@0 16663 // Color
michael@0 16664 CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false },
michael@0 16665 cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false },
michael@0 16666 SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true },
michael@0 16667 SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true },
michael@0 16668 sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true },
michael@0 16669 scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true },
michael@0 16670 G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false },
michael@0 16671 g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false },
michael@0 16672 RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false },
michael@0 16673 rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false },
michael@0 16674 K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false },
michael@0 16675 k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false },
michael@0 16676
michael@0 16677 // Shading
michael@0 16678 sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false },
michael@0 16679
michael@0 16680 // Images
michael@0 16681 BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false },
michael@0 16682 ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false },
michael@0 16683 EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false },
michael@0 16684
michael@0 16685 // XObjects
michael@0 16686 Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false },
michael@0 16687 MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false },
michael@0 16688 DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false },
michael@0 16689 BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false },
michael@0 16690 BDC: { id: OPS.beginMarkedContentProps, numArgs: 2,
michael@0 16691 variableArgs: false },
michael@0 16692 EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false },
michael@0 16693
michael@0 16694 // Compatibility
michael@0 16695 BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false },
michael@0 16696 EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false },
michael@0 16697
michael@0 16698 // (reserved partial commands for the lexer)
michael@0 16699 BM: null,
michael@0 16700 BD: null,
michael@0 16701 'true': null,
michael@0 16702 fa: null,
michael@0 16703 fal: null,
michael@0 16704 fals: null,
michael@0 16705 'false': null,
michael@0 16706 nu: null,
michael@0 16707 nul: null,
michael@0 16708 'null': null
michael@0 16709 };
michael@0 16710
michael@0 16711 function EvaluatorPreprocessor(stream, xref, stateManager) {
michael@0 16712 // TODO(mduan): pass array of knownCommands rather than OP_MAP
michael@0 16713 // dictionary
michael@0 16714 this.parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
michael@0 16715 this.stateManager = stateManager;
michael@0 16716 }
michael@0 16717
michael@0 16718 EvaluatorPreprocessor.prototype = {
michael@0 16719 get savedStatesDepth() {
michael@0 16720 return this.stateManager.stateStack.length;
michael@0 16721 },
michael@0 16722
michael@0 16723 read: function EvaluatorPreprocessor_read() {
michael@0 16724 var args = [];
michael@0 16725 while (true) {
michael@0 16726 var obj = this.parser.getObj();
michael@0 16727 if (isEOF(obj)) {
michael@0 16728 return null; // no more commands
michael@0 16729 }
michael@0 16730 if (!isCmd(obj)) {
michael@0 16731 // argument
michael@0 16732 if (obj !== null && obj !== undefined) {
michael@0 16733 args.push((obj instanceof Dict ? obj.getAll() : obj));
michael@0 16734 assert(args.length <= 33, 'Too many arguments');
michael@0 16735 }
michael@0 16736 continue;
michael@0 16737 }
michael@0 16738
michael@0 16739 var cmd = obj.cmd;
michael@0 16740 // Check that the command is valid
michael@0 16741 var opSpec = OP_MAP[cmd];
michael@0 16742 if (!opSpec) {
michael@0 16743 warn('Unknown command "' + cmd + '"');
michael@0 16744 continue;
michael@0 16745 }
michael@0 16746
michael@0 16747 var fn = opSpec.id;
michael@0 16748
michael@0 16749 // Validate the number of arguments for the command
michael@0 16750 if (opSpec.variableArgs) {
michael@0 16751 if (args.length > opSpec.numArgs) {
michael@0 16752 info('Command ' + fn + ': expected [0,' + opSpec.numArgs +
michael@0 16753 '] args, but received ' + args.length + ' args');
michael@0 16754 }
michael@0 16755 } else {
michael@0 16756 if (args.length < opSpec.numArgs) {
michael@0 16757 // If we receive too few args, it's not possible to possible
michael@0 16758 // to execute the command, so skip the command
michael@0 16759 info('Command ' + fn + ': because expected ' +
michael@0 16760 opSpec.numArgs + ' args, but received ' + args.length +
michael@0 16761 ' args; skipping');
michael@0 16762 args = [];
michael@0 16763 continue;
michael@0 16764 } else if (args.length > opSpec.numArgs) {
michael@0 16765 info('Command ' + fn + ': expected ' + opSpec.numArgs +
michael@0 16766 ' args, but received ' + args.length + ' args');
michael@0 16767 }
michael@0 16768 }
michael@0 16769
michael@0 16770 // TODO figure out how to type-check vararg functions
michael@0 16771 this.preprocessCommand(fn, args);
michael@0 16772
michael@0 16773 return { fn: fn, args: args };
michael@0 16774 }
michael@0 16775 },
michael@0 16776
michael@0 16777 preprocessCommand:
michael@0 16778 function EvaluatorPreprocessor_preprocessCommand(fn, args) {
michael@0 16779 switch (fn | 0) {
michael@0 16780 case OPS.save:
michael@0 16781 this.stateManager.save();
michael@0 16782 break;
michael@0 16783 case OPS.restore:
michael@0 16784 this.stateManager.restore();
michael@0 16785 break;
michael@0 16786 case OPS.transform:
michael@0 16787 this.stateManager.transform(args);
michael@0 16788 break;
michael@0 16789 }
michael@0 16790 }
michael@0 16791 };
michael@0 16792 return EvaluatorPreprocessor;
michael@0 16793 })();
michael@0 16794
michael@0 16795 var QueueOptimizer = (function QueueOptimizerClosure() {
michael@0 16796 function addState(parentState, pattern, fn) {
michael@0 16797 var state = parentState;
michael@0 16798 for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
michael@0 16799 var item = pattern[i];
michael@0 16800 state = (state[item] || (state[item] = []));
michael@0 16801 }
michael@0 16802 state[pattern[pattern.length - 1]] = fn;
michael@0 16803 }
michael@0 16804
michael@0 16805 function handlePaintSolidColorImageMask(index, count, fnArray, argsArray) {
michael@0 16806 // Handles special case of mainly LaTeX documents which
michael@0 16807 // use image masks to draw lines with the current fill style.
michael@0 16808 // 'count' groups of (save, transform, paintImageMaskXObject, restore)+
michael@0 16809 // have been found at index.
michael@0 16810 for (var i = 0; i < count; i++) {
michael@0 16811 var arg = argsArray[index + 4 * i + 2];
michael@0 16812 var imageMask = arg.length == 1 && arg[0];
michael@0 16813 if (imageMask && imageMask.width == 1 && imageMask.height == 1 &&
michael@0 16814 (!imageMask.data.length || (imageMask.data.length == 1 &&
michael@0 16815 imageMask.data[0] === 0))) {
michael@0 16816 fnArray[index + 4 * i + 2] = OPS.paintSolidColorImageMask;
michael@0 16817 continue;
michael@0 16818 }
michael@0 16819 break;
michael@0 16820 }
michael@0 16821 return count - i;
michael@0 16822 }
michael@0 16823
michael@0 16824 var InitialState = [];
michael@0 16825
michael@0 16826 addState(InitialState,
michael@0 16827 [OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore],
michael@0 16828 function foundInlineImageGroup(context) {
michael@0 16829 // grouping paintInlineImageXObject's into paintInlineImageXObjectGroup
michael@0 16830 // searching for (save, transform, paintInlineImageXObject, restore)+
michael@0 16831 var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
michael@0 16832 var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
michael@0 16833 var MAX_WIDTH = 1000;
michael@0 16834 var IMAGE_PADDING = 1;
michael@0 16835
michael@0 16836 var fnArray = context.fnArray, argsArray = context.argsArray;
michael@0 16837 var j = context.currentOperation - 3, i = j + 4;
michael@0 16838 var ii = fnArray.length;
michael@0 16839
michael@0 16840 for (; i < ii && fnArray[i - 4] === fnArray[i]; i++) {}
michael@0 16841 var count = Math.min((i - j) >> 2, MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
michael@0 16842 if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
michael@0 16843 context.currentOperation = i - 1;
michael@0 16844 return;
michael@0 16845 }
michael@0 16846 // assuming that heights of those image is too small (~1 pixel)
michael@0 16847 // packing as much as possible by lines
michael@0 16848 var maxX = 0;
michael@0 16849 var map = [], maxLineHeight = 0;
michael@0 16850 var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING;
michael@0 16851 var q;
michael@0 16852 for (q = 0; q < count; q++) {
michael@0 16853 var transform = argsArray[j + (q << 2) + 1];
michael@0 16854 var img = argsArray[j + (q << 2) + 2][0];
michael@0 16855 if (currentX + img.width > MAX_WIDTH) {
michael@0 16856 // starting new line
michael@0 16857 maxX = Math.max(maxX, currentX);
michael@0 16858 currentY += maxLineHeight + 2 * IMAGE_PADDING;
michael@0 16859 currentX = 0;
michael@0 16860 maxLineHeight = 0;
michael@0 16861 }
michael@0 16862 map.push({
michael@0 16863 transform: transform,
michael@0 16864 x: currentX, y: currentY,
michael@0 16865 w: img.width, h: img.height
michael@0 16866 });
michael@0 16867 currentX += img.width + 2 * IMAGE_PADDING;
michael@0 16868 maxLineHeight = Math.max(maxLineHeight, img.height);
michael@0 16869 }
michael@0 16870 var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
michael@0 16871 var imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
michael@0 16872 var imgData = new Uint8Array(imgWidth * imgHeight * 4);
michael@0 16873 var imgRowSize = imgWidth << 2;
michael@0 16874 for (q = 0; q < count; q++) {
michael@0 16875 var data = argsArray[j + (q << 2) + 2][0].data;
michael@0 16876 // copy image by lines and extends pixels into padding
michael@0 16877 var rowSize = map[q].w << 2;
michael@0 16878 var dataOffset = 0;
michael@0 16879 var offset = (map[q].x + map[q].y * imgWidth) << 2;
michael@0 16880 imgData.set(data.subarray(0, rowSize), offset - imgRowSize);
michael@0 16881 for (var k = 0, kk = map[q].h; k < kk; k++) {
michael@0 16882 imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);
michael@0 16883 dataOffset += rowSize;
michael@0 16884 offset += imgRowSize;
michael@0 16885 }
michael@0 16886 imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset);
michael@0 16887 while (offset >= 0) {
michael@0 16888 data[offset - 4] = data[offset];
michael@0 16889 data[offset - 3] = data[offset + 1];
michael@0 16890 data[offset - 2] = data[offset + 2];
michael@0 16891 data[offset - 1] = data[offset + 3];
michael@0 16892 data[offset + rowSize] = data[offset + rowSize - 4];
michael@0 16893 data[offset + rowSize + 1] = data[offset + rowSize - 3];
michael@0 16894 data[offset + rowSize + 2] = data[offset + rowSize - 2];
michael@0 16895 data[offset + rowSize + 3] = data[offset + rowSize - 1];
michael@0 16896 offset -= imgRowSize;
michael@0 16897 }
michael@0 16898 }
michael@0 16899 // replacing queue items
michael@0 16900 fnArray.splice(j, count * 4, OPS.paintInlineImageXObjectGroup);
michael@0 16901 argsArray.splice(j, count * 4,
michael@0 16902 [{ width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP,
michael@0 16903 data: imgData }, map]);
michael@0 16904 context.currentOperation = j;
michael@0 16905 });
michael@0 16906
michael@0 16907 addState(InitialState,
michael@0 16908 [OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore],
michael@0 16909 function foundImageMaskGroup(context) {
michael@0 16910 // grouping paintImageMaskXObject's into paintImageMaskXObjectGroup
michael@0 16911 // searching for (save, transform, paintImageMaskXObject, restore)+
michael@0 16912 var MIN_IMAGES_IN_MASKS_BLOCK = 10;
michael@0 16913 var MAX_IMAGES_IN_MASKS_BLOCK = 100;
michael@0 16914 var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
michael@0 16915
michael@0 16916 var fnArray = context.fnArray, argsArray = context.argsArray;
michael@0 16917 var j = context.currentOperation - 3, i = j + 4;
michael@0 16918 var ii = fnArray.length, q;
michael@0 16919
michael@0 16920 for (; i < ii && fnArray[i - 4] === fnArray[i]; i++) {}
michael@0 16921 var count = (i - j) >> 2;
michael@0 16922 count = handlePaintSolidColorImageMask(j, count, fnArray, argsArray);
michael@0 16923 if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
michael@0 16924 context.currentOperation = i - 1;
michael@0 16925 return;
michael@0 16926 }
michael@0 16927
michael@0 16928 var isSameImage = false;
michael@0 16929 var transformArgs;
michael@0 16930 if (argsArray[j + 1][1] === 0 && argsArray[j + 1][2] === 0) {
michael@0 16931 i = j + 4;
michael@0 16932 isSameImage = true;
michael@0 16933 for (q = 1; q < count; q++, i += 4) {
michael@0 16934 var prevTransformArgs = argsArray[i - 3];
michael@0 16935 transformArgs = argsArray[i + 1];
michael@0 16936 if (argsArray[i - 2][0] !== argsArray[i + 2][0] ||
michael@0 16937 prevTransformArgs[0] !== transformArgs[0] ||
michael@0 16938 prevTransformArgs[1] !== transformArgs[1] ||
michael@0 16939 prevTransformArgs[2] !== transformArgs[2] ||
michael@0 16940 prevTransformArgs[3] !== transformArgs[3]) {
michael@0 16941 if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
michael@0 16942 isSameImage = false;
michael@0 16943 } else {
michael@0 16944 count = q;
michael@0 16945 }
michael@0 16946 break; // different image or transform
michael@0 16947 }
michael@0 16948 }
michael@0 16949 }
michael@0 16950
michael@0 16951 if (isSameImage) {
michael@0 16952 count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);
michael@0 16953 var positions = new Float32Array(count * 2);
michael@0 16954 i = j + 1;
michael@0 16955 for (q = 0; q < count; q++) {
michael@0 16956 transformArgs = argsArray[i];
michael@0 16957 positions[(q << 1)] = transformArgs[4];
michael@0 16958 positions[(q << 1) + 1] = transformArgs[5];
michael@0 16959 i += 4;
michael@0 16960 }
michael@0 16961
michael@0 16962 // replacing queue items
michael@0 16963 fnArray.splice(j, count * 4, OPS.paintImageMaskXObjectRepeat);
michael@0 16964 argsArray.splice(j, count * 4, [argsArray[j + 2][0],
michael@0 16965 argsArray[j + 1][0], argsArray[j + 1][3], positions]);
michael@0 16966
michael@0 16967 context.currentOperation = j;
michael@0 16968 } else {
michael@0 16969 count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
michael@0 16970 var images = [];
michael@0 16971 for (q = 0; q < count; q++) {
michael@0 16972 transformArgs = argsArray[j + (q << 2) + 1];
michael@0 16973 var maskParams = argsArray[j + (q << 2) + 2][0];
michael@0 16974 images.push({ data: maskParams.data, width: maskParams.width,
michael@0 16975 height: maskParams.height,
michael@0 16976 transform: transformArgs });
michael@0 16977 }
michael@0 16978
michael@0 16979 // replacing queue items
michael@0 16980 fnArray.splice(j, count * 4, OPS.paintImageMaskXObjectGroup);
michael@0 16981 argsArray.splice(j, count * 4, [images]);
michael@0 16982
michael@0 16983 context.currentOperation = j;
michael@0 16984 }
michael@0 16985 });
michael@0 16986
michael@0 16987 addState(InitialState,
michael@0 16988 [OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore],
michael@0 16989 function (context) {
michael@0 16990 var MIN_IMAGES_IN_BLOCK = 3;
michael@0 16991 var MAX_IMAGES_IN_BLOCK = 1000;
michael@0 16992
michael@0 16993 var fnArray = context.fnArray, argsArray = context.argsArray;
michael@0 16994 var j = context.currentOperation - 3, i = j + 4;
michael@0 16995 if (argsArray[j + 1][1] !== 0 || argsArray[j + 1][2] !== 0) {
michael@0 16996 return;
michael@0 16997 }
michael@0 16998 var ii = fnArray.length;
michael@0 16999 var transformArgs;
michael@0 17000 for (; i + 3 < ii && fnArray[i - 4] === fnArray[i]; i += 4) {
michael@0 17001 if (fnArray[i - 3] !== fnArray[i + 1] ||
michael@0 17002 fnArray[i - 2] !== fnArray[i + 2] ||
michael@0 17003 fnArray[i - 1] !== fnArray[i + 3]) {
michael@0 17004 break;
michael@0 17005 }
michael@0 17006 if (argsArray[i - 2][0] !== argsArray[i + 2][0]) {
michael@0 17007 break; // different image
michael@0 17008 }
michael@0 17009 var prevTransformArgs = argsArray[i - 3];
michael@0 17010 transformArgs = argsArray[i + 1];
michael@0 17011 if (prevTransformArgs[0] !== transformArgs[0] ||
michael@0 17012 prevTransformArgs[1] !== transformArgs[1] ||
michael@0 17013 prevTransformArgs[2] !== transformArgs[2] ||
michael@0 17014 prevTransformArgs[3] !== transformArgs[3]) {
michael@0 17015 break; // different transform
michael@0 17016 }
michael@0 17017 }
michael@0 17018 var count = Math.min((i - j) >> 2, MAX_IMAGES_IN_BLOCK);
michael@0 17019 if (count < MIN_IMAGES_IN_BLOCK) {
michael@0 17020 context.currentOperation = i - 1;
michael@0 17021 return;
michael@0 17022 }
michael@0 17023
michael@0 17024 var positions = new Float32Array(count * 2);
michael@0 17025 i = j + 1;
michael@0 17026 for (var q = 0; q < count; q++) {
michael@0 17027 transformArgs = argsArray[i];
michael@0 17028 positions[(q << 1)] = transformArgs[4];
michael@0 17029 positions[(q << 1) + 1] = transformArgs[5];
michael@0 17030 i += 4;
michael@0 17031 }
michael@0 17032 var args = [argsArray[j + 2][0], argsArray[j + 1][0],
michael@0 17033 argsArray[j + 1][3], positions];
michael@0 17034 // replacing queue items
michael@0 17035 fnArray.splice(j, count * 4, OPS.paintImageXObjectRepeat);
michael@0 17036 argsArray.splice(j, count * 4, args);
michael@0 17037
michael@0 17038 context.currentOperation = j;
michael@0 17039 });
michael@0 17040
michael@0 17041 addState(InitialState,
michael@0 17042 [OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText],
michael@0 17043 function (context) {
michael@0 17044 // moving single chars with same font into beginText/endText groups
michael@0 17045 // searching for (beginText, setFont, setTextMatrix, showText, endText)+
michael@0 17046 var MIN_CHARS_IN_BLOCK = 3;
michael@0 17047 var MAX_CHARS_IN_BLOCK = 1000;
michael@0 17048
michael@0 17049 var fnArray = context.fnArray, argsArray = context.argsArray;
michael@0 17050 var j = context.currentOperation - 4, i = j + 5;
michael@0 17051 var ii = fnArray.length;
michael@0 17052
michael@0 17053 for (; i < ii && fnArray[i - 5] === fnArray[i]; i++) {
michael@0 17054 if (fnArray[i] === OPS.setFont) {
michael@0 17055 if (argsArray[i - 5][0] !== argsArray[i][0] ||
michael@0 17056 argsArray[i - 5][1] !== argsArray[i][1]) {
michael@0 17057 break;
michael@0 17058 }
michael@0 17059 }
michael@0 17060 }
michael@0 17061 var count = Math.min(((i - j) / 5) | 0, MAX_CHARS_IN_BLOCK);
michael@0 17062 if (count < MIN_CHARS_IN_BLOCK) {
michael@0 17063 context.currentOperation = i - 1;
michael@0 17064 return;
michael@0 17065 }
michael@0 17066 if (j >= 4 && fnArray[j - 4] === fnArray[j + 1] &&
michael@0 17067 fnArray[j - 3] === fnArray[j + 2] &&
michael@0 17068 fnArray[j - 2] === fnArray[j + 3] &&
michael@0 17069 fnArray[j - 1] === fnArray[j + 4] &&
michael@0 17070 argsArray[j - 4][0] === argsArray[j + 1][0] &&
michael@0 17071 argsArray[j - 4][1] === argsArray[j + 1][1]) {
michael@0 17072 // extending one block ahead (very first block might have 'dependency')
michael@0 17073 count++;
michael@0 17074 j -= 5;
michael@0 17075 }
michael@0 17076 var k = j + 7;
michael@0 17077 i = j + 4;
michael@0 17078 for (var q = 1; q < count; q++) {
michael@0 17079 fnArray[i] = fnArray[k];
michael@0 17080 argsArray[i] = argsArray[k];
michael@0 17081 fnArray[i + 1] = fnArray[k + 1];
michael@0 17082 argsArray[i + 1] = argsArray[k + 1];
michael@0 17083 i += 2;
michael@0 17084 k += 5;
michael@0 17085 }
michael@0 17086 var removed = (count - 1) * 3;
michael@0 17087 fnArray.splice(i, removed);
michael@0 17088 argsArray.splice(i, removed);
michael@0 17089
michael@0 17090 context.currentOperation = i;
michael@0 17091 });
michael@0 17092
michael@0 17093 function QueueOptimizer() {}
michael@0 17094
michael@0 17095 QueueOptimizer.prototype = {
michael@0 17096 optimize: function QueueOptimizer_optimize(queue) {
michael@0 17097 var fnArray = queue.fnArray, argsArray = queue.argsArray;
michael@0 17098 var context = {
michael@0 17099 currentOperation: 0,
michael@0 17100 fnArray: fnArray,
michael@0 17101 argsArray: argsArray
michael@0 17102 };
michael@0 17103 var i, ii = argsArray.length;
michael@0 17104 var state;
michael@0 17105 for (i = 0; i < ii; i++) {
michael@0 17106 state = (state || InitialState)[fnArray[i]];
michael@0 17107 if (typeof state === 'function') { // we found some handler
michael@0 17108 context.currentOperation = i;
michael@0 17109 state = state(context);
michael@0 17110 i = context.currentOperation;
michael@0 17111 ii = context.fnArray.length;
michael@0 17112 }
michael@0 17113 }
michael@0 17114 }
michael@0 17115 };
michael@0 17116 return QueueOptimizer;
michael@0 17117 })();
michael@0 17118
michael@0 17119
michael@0 17120 var BUILT_IN_CMAPS = [
michael@0 17121 // << Start unicode maps.
michael@0 17122 'Adobe-GB1-UCS2',
michael@0 17123 'Adobe-CNS1-UCS2',
michael@0 17124 'Adobe-Japan1-UCS2',
michael@0 17125 'Adobe-Korea1-UCS2',
michael@0 17126 // >> End unicode maps.
michael@0 17127 '78-EUC-H',
michael@0 17128 '78-EUC-V',
michael@0 17129 '78-H',
michael@0 17130 '78-RKSJ-H',
michael@0 17131 '78-RKSJ-V',
michael@0 17132 '78-V',
michael@0 17133 '78ms-RKSJ-H',
michael@0 17134 '78ms-RKSJ-V',
michael@0 17135 '83pv-RKSJ-H',
michael@0 17136 '90ms-RKSJ-H',
michael@0 17137 '90ms-RKSJ-V',
michael@0 17138 '90msp-RKSJ-H',
michael@0 17139 '90msp-RKSJ-V',
michael@0 17140 '90pv-RKSJ-H',
michael@0 17141 '90pv-RKSJ-V',
michael@0 17142 'Add-H',
michael@0 17143 'Add-RKSJ-H',
michael@0 17144 'Add-RKSJ-V',
michael@0 17145 'Add-V',
michael@0 17146 'Adobe-CNS1-0',
michael@0 17147 'Adobe-CNS1-1',
michael@0 17148 'Adobe-CNS1-2',
michael@0 17149 'Adobe-CNS1-3',
michael@0 17150 'Adobe-CNS1-4',
michael@0 17151 'Adobe-CNS1-5',
michael@0 17152 'Adobe-CNS1-6',
michael@0 17153 'Adobe-GB1-0',
michael@0 17154 'Adobe-GB1-1',
michael@0 17155 'Adobe-GB1-2',
michael@0 17156 'Adobe-GB1-3',
michael@0 17157 'Adobe-GB1-4',
michael@0 17158 'Adobe-GB1-5',
michael@0 17159 'Adobe-Japan1-0',
michael@0 17160 'Adobe-Japan1-1',
michael@0 17161 'Adobe-Japan1-2',
michael@0 17162 'Adobe-Japan1-3',
michael@0 17163 'Adobe-Japan1-4',
michael@0 17164 'Adobe-Japan1-5',
michael@0 17165 'Adobe-Japan1-6',
michael@0 17166 'Adobe-Korea1-0',
michael@0 17167 'Adobe-Korea1-1',
michael@0 17168 'Adobe-Korea1-2',
michael@0 17169 'B5-H',
michael@0 17170 'B5-V',
michael@0 17171 'B5pc-H',
michael@0 17172 'B5pc-V',
michael@0 17173 'CNS-EUC-H',
michael@0 17174 'CNS-EUC-V',
michael@0 17175 'CNS1-H',
michael@0 17176 'CNS1-V',
michael@0 17177 'CNS2-H',
michael@0 17178 'CNS2-V',
michael@0 17179 'ETHK-B5-H',
michael@0 17180 'ETHK-B5-V',
michael@0 17181 'ETen-B5-H',
michael@0 17182 'ETen-B5-V',
michael@0 17183 'ETenms-B5-H',
michael@0 17184 'ETenms-B5-V',
michael@0 17185 'EUC-H',
michael@0 17186 'EUC-V',
michael@0 17187 'Ext-H',
michael@0 17188 'Ext-RKSJ-H',
michael@0 17189 'Ext-RKSJ-V',
michael@0 17190 'Ext-V',
michael@0 17191 'GB-EUC-H',
michael@0 17192 'GB-EUC-V',
michael@0 17193 'GB-H',
michael@0 17194 'GB-V',
michael@0 17195 'GBK-EUC-H',
michael@0 17196 'GBK-EUC-V',
michael@0 17197 'GBK2K-H',
michael@0 17198 'GBK2K-V',
michael@0 17199 'GBKp-EUC-H',
michael@0 17200 'GBKp-EUC-V',
michael@0 17201 'GBT-EUC-H',
michael@0 17202 'GBT-EUC-V',
michael@0 17203 'GBT-H',
michael@0 17204 'GBT-V',
michael@0 17205 'GBTpc-EUC-H',
michael@0 17206 'GBTpc-EUC-V',
michael@0 17207 'GBpc-EUC-H',
michael@0 17208 'GBpc-EUC-V',
michael@0 17209 'H',
michael@0 17210 'HKdla-B5-H',
michael@0 17211 'HKdla-B5-V',
michael@0 17212 'HKdlb-B5-H',
michael@0 17213 'HKdlb-B5-V',
michael@0 17214 'HKgccs-B5-H',
michael@0 17215 'HKgccs-B5-V',
michael@0 17216 'HKm314-B5-H',
michael@0 17217 'HKm314-B5-V',
michael@0 17218 'HKm471-B5-H',
michael@0 17219 'HKm471-B5-V',
michael@0 17220 'HKscs-B5-H',
michael@0 17221 'HKscs-B5-V',
michael@0 17222 'Hankaku',
michael@0 17223 'Hiragana',
michael@0 17224 'KSC-EUC-H',
michael@0 17225 'KSC-EUC-V',
michael@0 17226 'KSC-H',
michael@0 17227 'KSC-Johab-H',
michael@0 17228 'KSC-Johab-V',
michael@0 17229 'KSC-V',
michael@0 17230 'KSCms-UHC-H',
michael@0 17231 'KSCms-UHC-HW-H',
michael@0 17232 'KSCms-UHC-HW-V',
michael@0 17233 'KSCms-UHC-V',
michael@0 17234 'KSCpc-EUC-H',
michael@0 17235 'KSCpc-EUC-V',
michael@0 17236 'Katakana',
michael@0 17237 'NWP-H',
michael@0 17238 'NWP-V',
michael@0 17239 'RKSJ-H',
michael@0 17240 'RKSJ-V',
michael@0 17241 'Roman',
michael@0 17242 'UniCNS-UCS2-H',
michael@0 17243 'UniCNS-UCS2-V',
michael@0 17244 'UniCNS-UTF16-H',
michael@0 17245 'UniCNS-UTF16-V',
michael@0 17246 'UniCNS-UTF32-H',
michael@0 17247 'UniCNS-UTF32-V',
michael@0 17248 'UniCNS-UTF8-H',
michael@0 17249 'UniCNS-UTF8-V',
michael@0 17250 'UniGB-UCS2-H',
michael@0 17251 'UniGB-UCS2-V',
michael@0 17252 'UniGB-UTF16-H',
michael@0 17253 'UniGB-UTF16-V',
michael@0 17254 'UniGB-UTF32-H',
michael@0 17255 'UniGB-UTF32-V',
michael@0 17256 'UniGB-UTF8-H',
michael@0 17257 'UniGB-UTF8-V',
michael@0 17258 'UniJIS-UCS2-H',
michael@0 17259 'UniJIS-UCS2-HW-H',
michael@0 17260 'UniJIS-UCS2-HW-V',
michael@0 17261 'UniJIS-UCS2-V',
michael@0 17262 'UniJIS-UTF16-H',
michael@0 17263 'UniJIS-UTF16-V',
michael@0 17264 'UniJIS-UTF32-H',
michael@0 17265 'UniJIS-UTF32-V',
michael@0 17266 'UniJIS-UTF8-H',
michael@0 17267 'UniJIS-UTF8-V',
michael@0 17268 'UniJIS2004-UTF16-H',
michael@0 17269 'UniJIS2004-UTF16-V',
michael@0 17270 'UniJIS2004-UTF32-H',
michael@0 17271 'UniJIS2004-UTF32-V',
michael@0 17272 'UniJIS2004-UTF8-H',
michael@0 17273 'UniJIS2004-UTF8-V',
michael@0 17274 'UniJISPro-UCS2-HW-V',
michael@0 17275 'UniJISPro-UCS2-V',
michael@0 17276 'UniJISPro-UTF8-V',
michael@0 17277 'UniJISX0213-UTF32-H',
michael@0 17278 'UniJISX0213-UTF32-V',
michael@0 17279 'UniJISX02132004-UTF32-H',
michael@0 17280 'UniJISX02132004-UTF32-V',
michael@0 17281 'UniKS-UCS2-H',
michael@0 17282 'UniKS-UCS2-V',
michael@0 17283 'UniKS-UTF16-H',
michael@0 17284 'UniKS-UTF16-V',
michael@0 17285 'UniKS-UTF32-H',
michael@0 17286 'UniKS-UTF32-V',
michael@0 17287 'UniKS-UTF8-H',
michael@0 17288 'UniKS-UTF8-V',
michael@0 17289 'V',
michael@0 17290 'WP-Symbol'];
michael@0 17291
michael@0 17292 // CMap, not to be confused with TrueType's cmap.
michael@0 17293 var CMap = (function CMapClosure() {
michael@0 17294 function CMap(builtInCMap) {
michael@0 17295 // Codespace ranges are stored as follows:
michael@0 17296 // [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]]
michael@0 17297 // where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...]
michael@0 17298 this.codespaceRanges = [[], [], [], []];
michael@0 17299 this.numCodespaceRanges = 0;
michael@0 17300 this.map = [];
michael@0 17301 this.vertical = false;
michael@0 17302 this.useCMap = null;
michael@0 17303 this.builtInCMap = builtInCMap;
michael@0 17304 }
michael@0 17305 CMap.prototype = {
michael@0 17306 addCodespaceRange: function(n, low, high) {
michael@0 17307 this.codespaceRanges[n - 1].push(low, high);
michael@0 17308 this.numCodespaceRanges++;
michael@0 17309 },
michael@0 17310
michael@0 17311 mapRange: function(low, high, dstLow) {
michael@0 17312 var lastByte = dstLow.length - 1;
michael@0 17313 while (low <= high) {
michael@0 17314 this.map[low] = dstLow;
michael@0 17315 // Only the last byte has to be incremented.
michael@0 17316 dstLow = dstLow.substr(0, lastByte) +
michael@0 17317 String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
michael@0 17318 ++low;
michael@0 17319 }
michael@0 17320 },
michael@0 17321
michael@0 17322 mapRangeToArray: function(low, high, array) {
michael@0 17323 var i = 0;
michael@0 17324 while (low <= high) {
michael@0 17325 this.map[low] = array[i++];
michael@0 17326 ++low;
michael@0 17327 }
michael@0 17328 },
michael@0 17329
michael@0 17330 mapOne: function(src, dst) {
michael@0 17331 this.map[src] = dst;
michael@0 17332 },
michael@0 17333
michael@0 17334 lookup: function(code) {
michael@0 17335 return this.map[code];
michael@0 17336 },
michael@0 17337
michael@0 17338 readCharCode: function(str, offset) {
michael@0 17339 var c = 0;
michael@0 17340 var codespaceRanges = this.codespaceRanges;
michael@0 17341 var codespaceRangesLen = this.codespaceRanges.length;
michael@0 17342 // 9.7.6.2 CMap Mapping
michael@0 17343 // The code length is at most 4.
michael@0 17344 for (var n = 0; n < codespaceRangesLen; n++) {
michael@0 17345 c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0;
michael@0 17346 // Check each codespace range to see if it falls within.
michael@0 17347 var codespaceRange = codespaceRanges[n];
michael@0 17348 for (var k = 0, kk = codespaceRange.length; k < kk;) {
michael@0 17349 var low = codespaceRange[k++];
michael@0 17350 var high = codespaceRange[k++];
michael@0 17351 if (c >= low && c <= high) {
michael@0 17352 return [c, n + 1];
michael@0 17353 }
michael@0 17354 }
michael@0 17355 }
michael@0 17356
michael@0 17357 return [0, 1];
michael@0 17358 }
michael@0 17359
michael@0 17360 };
michael@0 17361 return CMap;
michael@0 17362 })();
michael@0 17363
michael@0 17364 var IdentityCMap = (function IdentityCMapClosure() {
michael@0 17365 function IdentityCMap(vertical, n) {
michael@0 17366 CMap.call(this);
michael@0 17367 this.vertical = vertical;
michael@0 17368 this.addCodespaceRange(n, 0, 0xffff);
michael@0 17369 this.mapRange(0, 0xffff, '\u0000');
michael@0 17370 }
michael@0 17371 Util.inherit(IdentityCMap, CMap, {});
michael@0 17372
michael@0 17373 return IdentityCMap;
michael@0 17374 })();
michael@0 17375
michael@0 17376 var BinaryCMapReader = (function BinaryCMapReaderClosure() {
michael@0 17377 function fetchBinaryData(url) {
michael@0 17378 var nonBinaryRequest = PDFJS.disableWorker;
michael@0 17379 var request = new XMLHttpRequest();
michael@0 17380 request.open('GET', url, false);
michael@0 17381 if (!nonBinaryRequest) {
michael@0 17382 try {
michael@0 17383 request.responseType = 'arraybuffer';
michael@0 17384 nonBinaryRequest = request.responseType !== 'arraybuffer';
michael@0 17385 } catch (e) {
michael@0 17386 nonBinaryRequest = true;
michael@0 17387 }
michael@0 17388 }
michael@0 17389 if (nonBinaryRequest && request.overrideMimeType) {
michael@0 17390 request.overrideMimeType('text/plain; charset=x-user-defined');
michael@0 17391 }
michael@0 17392 request.send(null);
michael@0 17393 if (request.status === 0 && /^https?:/i.test(url)) {
michael@0 17394 error('Unable to get binary cMap at: ' + url);
michael@0 17395 }
michael@0 17396 if (nonBinaryRequest) {
michael@0 17397 var data = Array.prototype.map.call(request.responseText, function (ch) {
michael@0 17398 return ch.charCodeAt(0) & 255;
michael@0 17399 });
michael@0 17400 return new Uint8Array(data);
michael@0 17401 }
michael@0 17402 return new Uint8Array(request.response);
michael@0 17403 }
michael@0 17404
michael@0 17405 function hexToInt(a, size) {
michael@0 17406 var n = 0;
michael@0 17407 for (var i = 0; i <= size; i++) {
michael@0 17408 n = (n << 8) | a[i];
michael@0 17409 }
michael@0 17410 return n >>> 0;
michael@0 17411 }
michael@0 17412
michael@0 17413 function hexToStr(a, size) {
michael@0 17414 return String.fromCharCode.apply(null, a.subarray(0, size + 1));
michael@0 17415 }
michael@0 17416
michael@0 17417 function addHex(a, b, size) {
michael@0 17418 var c = 0;
michael@0 17419 for (var i = size; i >= 0; i--) {
michael@0 17420 c += a[i] + b[i];
michael@0 17421 a[i] = c & 255;
michael@0 17422 c >>= 8;
michael@0 17423 }
michael@0 17424 }
michael@0 17425
michael@0 17426 function incHex(a, size) {
michael@0 17427 var c = 1;
michael@0 17428 for (var i = size; i >= 0 && c > 0; i--) {
michael@0 17429 c += a[i];
michael@0 17430 a[i] = c & 255;
michael@0 17431 c >>= 8;
michael@0 17432 }
michael@0 17433 }
michael@0 17434
michael@0 17435 var MAX_NUM_SIZE = 16;
michael@0 17436 var MAX_ENCODED_NUM_SIZE = 19; // ceil(MAX_NUM_SIZE * 7 / 8)
michael@0 17437
michael@0 17438 function BinaryCMapStream(data) {
michael@0 17439 this.buffer = data;
michael@0 17440 this.pos = 0;
michael@0 17441 this.end = data.length;
michael@0 17442 this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
michael@0 17443 }
michael@0 17444
michael@0 17445 BinaryCMapStream.prototype = {
michael@0 17446 readByte: function () {
michael@0 17447 if (this.pos >= this.end) {
michael@0 17448 return -1;
michael@0 17449 }
michael@0 17450 return this.buffer[this.pos++];
michael@0 17451 },
michael@0 17452 readNumber: function () {
michael@0 17453 var n = 0;
michael@0 17454 var last;
michael@0 17455 do {
michael@0 17456 var b = this.readByte();
michael@0 17457 if (b < 0) {
michael@0 17458 error('unexpected EOF in bcmap');
michael@0 17459 }
michael@0 17460 last = !(b & 0x80);
michael@0 17461 n = (n << 7) | (b & 0x7F);
michael@0 17462 } while (!last);
michael@0 17463 return n;
michael@0 17464 },
michael@0 17465 readSigned: function () {
michael@0 17466 var n = this.readNumber();
michael@0 17467 return (n & 1) ? ~(n >>> 1) : n >>> 1;
michael@0 17468 },
michael@0 17469 readHex: function (num, size) {
michael@0 17470 num.set(this.buffer.subarray(this.pos,
michael@0 17471 this.pos + size + 1));
michael@0 17472 this.pos += size + 1;
michael@0 17473 },
michael@0 17474 readHexNumber: function (num, size) {
michael@0 17475 var last;
michael@0 17476 var stack = this.tmpBuf, sp = 0;
michael@0 17477 do {
michael@0 17478 var b = this.readByte();
michael@0 17479 if (b < 0) {
michael@0 17480 error('unexpected EOF in bcmap');
michael@0 17481 }
michael@0 17482 last = !(b & 0x80);
michael@0 17483 stack[sp++] = b & 0x7F;
michael@0 17484 } while (!last);
michael@0 17485 var i = size, buffer = 0, bufferSize = 0;
michael@0 17486 while (i >= 0) {
michael@0 17487 while (bufferSize < 8 && stack.length > 0) {
michael@0 17488 buffer = (stack[--sp] << bufferSize) | buffer;
michael@0 17489 bufferSize += 7;
michael@0 17490 }
michael@0 17491 num[i] = buffer & 255;
michael@0 17492 i--;
michael@0 17493 buffer >>= 8;
michael@0 17494 bufferSize -= 8;
michael@0 17495 }
michael@0 17496 },
michael@0 17497 readHexSigned: function (num, size) {
michael@0 17498 this.readHexNumber(num, size);
michael@0 17499 var sign = num[size] & 1 ? 255 : 0;
michael@0 17500 var c = 0;
michael@0 17501 for (var i = 0; i <= size; i++) {
michael@0 17502 c = ((c & 1) << 8) | num[i];
michael@0 17503 num[i] = (c >> 1) ^ sign;
michael@0 17504 }
michael@0 17505 },
michael@0 17506 readString: function () {
michael@0 17507 var len = this.readNumber();
michael@0 17508 var s = '';
michael@0 17509 for (var i = 0; i < len; i++) {
michael@0 17510 s += String.fromCharCode(this.readNumber());
michael@0 17511 }
michael@0 17512 return s;
michael@0 17513 }
michael@0 17514 };
michael@0 17515
michael@0 17516 function processBinaryCMap(url, cMap, extend) {
michael@0 17517 var data = fetchBinaryData(url);
michael@0 17518 var stream = new BinaryCMapStream(data);
michael@0 17519
michael@0 17520 var header = stream.readByte();
michael@0 17521 cMap.vertical = !!(header & 1);
michael@0 17522
michael@0 17523 var useCMap = null;
michael@0 17524 var start = new Uint8Array(MAX_NUM_SIZE);
michael@0 17525 var end = new Uint8Array(MAX_NUM_SIZE);
michael@0 17526 var char = new Uint8Array(MAX_NUM_SIZE);
michael@0 17527 var charCode = new Uint8Array(MAX_NUM_SIZE);
michael@0 17528 var tmp = new Uint8Array(MAX_NUM_SIZE);
michael@0 17529 var code;
michael@0 17530
michael@0 17531 var b;
michael@0 17532 while ((b = stream.readByte()) >= 0) {
michael@0 17533 var type = b >> 5;
michael@0 17534 if (type === 7) { // metadata, e.g. comment or usecmap
michael@0 17535 switch (b & 0x1F) {
michael@0 17536 case 0:
michael@0 17537 stream.readString(); // skipping comment
michael@0 17538 break;
michael@0 17539 case 1:
michael@0 17540 useCMap = stream.readString();
michael@0 17541 break;
michael@0 17542 }
michael@0 17543 continue;
michael@0 17544 }
michael@0 17545 var sequence = !!(b & 0x10);
michael@0 17546 var dataSize = b & 15;
michael@0 17547
michael@0 17548 assert(dataSize + 1 <= MAX_NUM_SIZE);
michael@0 17549
michael@0 17550 var ucs2DataSize = 1;
michael@0 17551 var subitemsCount = stream.readNumber();
michael@0 17552 var i;
michael@0 17553 switch (type) {
michael@0 17554 case 0: // codespacerange
michael@0 17555 stream.readHex(start, dataSize);
michael@0 17556 stream.readHexNumber(end, dataSize);
michael@0 17557 addHex(end, start, dataSize);
michael@0 17558 cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize),
michael@0 17559 hexToInt(end, dataSize));
michael@0 17560 for (i = 1; i < subitemsCount; i++) {
michael@0 17561 incHex(end, dataSize);
michael@0 17562 stream.readHexNumber(start, dataSize);
michael@0 17563 addHex(start, end, dataSize);
michael@0 17564 stream.readHexNumber(end, dataSize);
michael@0 17565 addHex(end, start, dataSize);
michael@0 17566 cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize),
michael@0 17567 hexToInt(end, dataSize));
michael@0 17568 }
michael@0 17569 break;
michael@0 17570 case 1: // notdefrange
michael@0 17571 stream.readHex(start, dataSize);
michael@0 17572 stream.readHexNumber(end, dataSize);
michael@0 17573 addHex(end, start, dataSize);
michael@0 17574 code = stream.readNumber();
michael@0 17575 // undefined range, skipping
michael@0 17576 for (i = 1; i < subitemsCount; i++) {
michael@0 17577 incHex(end, dataSize);
michael@0 17578 stream.readHexNumber(start, dataSize);
michael@0 17579 addHex(start, end, dataSize);
michael@0 17580 stream.readHexNumber(end, dataSize);
michael@0 17581 addHex(end, start, dataSize);
michael@0 17582 code = stream.readNumber();
michael@0 17583 // nop
michael@0 17584 }
michael@0 17585 break;
michael@0 17586 case 2: // cidchar
michael@0 17587 stream.readHex(char, dataSize);
michael@0 17588 code = stream.readNumber();
michael@0 17589 cMap.mapOne(hexToInt(char, dataSize), String.fromCharCode(code));
michael@0 17590 for (i = 1; i < subitemsCount; i++) {
michael@0 17591 incHex(char, dataSize);
michael@0 17592 if (!sequence) {
michael@0 17593 stream.readHexNumber(tmp, dataSize);
michael@0 17594 addHex(char, tmp, dataSize);
michael@0 17595 }
michael@0 17596 code = stream.readSigned() + (code + 1);
michael@0 17597 cMap.mapOne(hexToInt(char, dataSize), String.fromCharCode(code));
michael@0 17598 }
michael@0 17599 break;
michael@0 17600 case 3: // cidrange
michael@0 17601 stream.readHex(start, dataSize);
michael@0 17602 stream.readHexNumber(end, dataSize);
michael@0 17603 addHex(end, start, dataSize);
michael@0 17604 code = stream.readNumber();
michael@0 17605 cMap.mapRange(hexToInt(start, dataSize), hexToInt(end, dataSize),
michael@0 17606 String.fromCharCode(code));
michael@0 17607 for (i = 1; i < subitemsCount; i++) {
michael@0 17608 incHex(end, dataSize);
michael@0 17609 if (!sequence) {
michael@0 17610 stream.readHexNumber(start, dataSize);
michael@0 17611 addHex(start, end, dataSize);
michael@0 17612 } else {
michael@0 17613 start.set(end);
michael@0 17614 }
michael@0 17615 stream.readHexNumber(end, dataSize);
michael@0 17616 addHex(end, start, dataSize);
michael@0 17617 code = stream.readNumber();
michael@0 17618 cMap.mapRange(hexToInt(start, dataSize), hexToInt(end, dataSize),
michael@0 17619 String.fromCharCode(code));
michael@0 17620 }
michael@0 17621 break;
michael@0 17622 case 4: // bfchar
michael@0 17623 stream.readHex(char, ucs2DataSize);
michael@0 17624 stream.readHex(charCode, dataSize);
michael@0 17625 cMap.mapOne(hexToInt(char, ucs2DataSize),
michael@0 17626 hexToStr(charCode, dataSize));
michael@0 17627 for (i = 1; i < subitemsCount; i++) {
michael@0 17628 incHex(char, ucs2DataSize);
michael@0 17629 if (!sequence) {
michael@0 17630 stream.readHexNumber(tmp, ucs2DataSize);
michael@0 17631 addHex(char, tmp, ucs2DataSize);
michael@0 17632 }
michael@0 17633 incHex(charCode, dataSize);
michael@0 17634 stream.readHexSigned(tmp, dataSize);
michael@0 17635 addHex(charCode, tmp, dataSize);
michael@0 17636 cMap.mapOne(hexToInt(char, ucs2DataSize),
michael@0 17637 hexToStr(charCode, dataSize));
michael@0 17638 }
michael@0 17639 break;
michael@0 17640 case 5: // bfrange
michael@0 17641 stream.readHex(start, ucs2DataSize);
michael@0 17642 stream.readHexNumber(end, ucs2DataSize);
michael@0 17643 addHex(end, start, ucs2DataSize);
michael@0 17644 stream.readHex(charCode, dataSize);
michael@0 17645 cMap.mapRange(hexToInt(start, ucs2DataSize),
michael@0 17646 hexToInt(end, ucs2DataSize),
michael@0 17647 hexToStr(charCode, dataSize));
michael@0 17648 for (i = 1; i < subitemsCount; i++) {
michael@0 17649 incHex(end, ucs2DataSize);
michael@0 17650 if (!sequence) {
michael@0 17651 stream.readHexNumber(start, ucs2DataSize);
michael@0 17652 addHex(start, end, ucs2DataSize);
michael@0 17653 } else {
michael@0 17654 start.set(end);
michael@0 17655 }
michael@0 17656 stream.readHexNumber(end, ucs2DataSize);
michael@0 17657 addHex(end, start, ucs2DataSize);
michael@0 17658 stream.readHex(charCode, dataSize);
michael@0 17659 cMap.mapRange(hexToInt(start, ucs2DataSize),
michael@0 17660 hexToInt(end, ucs2DataSize),
michael@0 17661 hexToStr(charCode, dataSize));
michael@0 17662 }
michael@0 17663 break;
michael@0 17664 default:
michael@0 17665 error('Unknown type: ' + type);
michael@0 17666 break;
michael@0 17667 }
michael@0 17668 }
michael@0 17669
michael@0 17670 if (useCMap) {
michael@0 17671 extend(useCMap);
michael@0 17672 }
michael@0 17673 return cMap;
michael@0 17674 }
michael@0 17675
michael@0 17676 function BinaryCMapReader() {}
michael@0 17677
michael@0 17678 BinaryCMapReader.prototype = {
michael@0 17679 read: processBinaryCMap
michael@0 17680 };
michael@0 17681
michael@0 17682 return BinaryCMapReader;
michael@0 17683 })();
michael@0 17684
michael@0 17685 var CMapFactory = (function CMapFactoryClosure() {
michael@0 17686 function strToInt(str) {
michael@0 17687 var a = 0;
michael@0 17688 for (var i = 0; i < str.length; i++) {
michael@0 17689 a = (a << 8) | str.charCodeAt(i);
michael@0 17690 }
michael@0 17691 return a >>> 0;
michael@0 17692 }
michael@0 17693
michael@0 17694 function expectString(obj) {
michael@0 17695 if (!isString(obj)) {
michael@0 17696 error('Malformed CMap: expected string.');
michael@0 17697 }
michael@0 17698 }
michael@0 17699
michael@0 17700 function expectInt(obj) {
michael@0 17701 if (!isInt(obj)) {
michael@0 17702 error('Malformed CMap: expected int.');
michael@0 17703 }
michael@0 17704 }
michael@0 17705
michael@0 17706 function parseBfChar(cMap, lexer) {
michael@0 17707 while (true) {
michael@0 17708 var obj = lexer.getObj();
michael@0 17709 if (isEOF(obj)) {
michael@0 17710 break;
michael@0 17711 }
michael@0 17712 if (isCmd(obj, 'endbfchar')) {
michael@0 17713 return;
michael@0 17714 }
michael@0 17715 expectString(obj);
michael@0 17716 var src = strToInt(obj);
michael@0 17717 obj = lexer.getObj();
michael@0 17718 // TODO are /dstName used?
michael@0 17719 expectString(obj);
michael@0 17720 var dst = obj;
michael@0 17721 cMap.mapOne(src, dst);
michael@0 17722 }
michael@0 17723 }
michael@0 17724
michael@0 17725 function parseBfRange(cMap, lexer) {
michael@0 17726 while (true) {
michael@0 17727 var obj = lexer.getObj();
michael@0 17728 if (isEOF(obj)) {
michael@0 17729 break;
michael@0 17730 }
michael@0 17731 if (isCmd(obj, 'endbfrange')) {
michael@0 17732 return;
michael@0 17733 }
michael@0 17734 expectString(obj);
michael@0 17735 var low = strToInt(obj);
michael@0 17736 obj = lexer.getObj();
michael@0 17737 expectString(obj);
michael@0 17738 var high = strToInt(obj);
michael@0 17739 obj = lexer.getObj();
michael@0 17740 if (isInt(obj) || isString(obj)) {
michael@0 17741 var dstLow = isInt(obj) ? String.fromCharCode(obj) : obj;
michael@0 17742 cMap.mapRange(low, high, dstLow);
michael@0 17743 } else if (isCmd(obj, '[')) {
michael@0 17744 obj = lexer.getObj();
michael@0 17745 var array = [];
michael@0 17746 while (!isCmd(obj, ']') && !isEOF(obj)) {
michael@0 17747 array.push(obj);
michael@0 17748 obj = lexer.getObj();
michael@0 17749 }
michael@0 17750 cMap.mapRangeToArray(low, high, array);
michael@0 17751 } else {
michael@0 17752 break;
michael@0 17753 }
michael@0 17754 }
michael@0 17755 error('Invalid bf range.');
michael@0 17756 }
michael@0 17757
michael@0 17758 function parseCidChar(cMap, lexer) {
michael@0 17759 while (true) {
michael@0 17760 var obj = lexer.getObj();
michael@0 17761 if (isEOF(obj)) {
michael@0 17762 break;
michael@0 17763 }
michael@0 17764 if (isCmd(obj, 'endcidchar')) {
michael@0 17765 return;
michael@0 17766 }
michael@0 17767 expectString(obj);
michael@0 17768 var src = strToInt(obj);
michael@0 17769 obj = lexer.getObj();
michael@0 17770 expectInt(obj);
michael@0 17771 var dst = String.fromCharCode(obj);
michael@0 17772 cMap.mapOne(src, dst);
michael@0 17773 }
michael@0 17774 }
michael@0 17775
michael@0 17776 function parseCidRange(cMap, lexer) {
michael@0 17777 while (true) {
michael@0 17778 var obj = lexer.getObj();
michael@0 17779 if (isEOF(obj)) {
michael@0 17780 break;
michael@0 17781 }
michael@0 17782 if (isCmd(obj, 'endcidrange')) {
michael@0 17783 return;
michael@0 17784 }
michael@0 17785 expectString(obj);
michael@0 17786 var low = strToInt(obj);
michael@0 17787 obj = lexer.getObj();
michael@0 17788 expectString(obj);
michael@0 17789 var high = strToInt(obj);
michael@0 17790 obj = lexer.getObj();
michael@0 17791 expectInt(obj);
michael@0 17792 var dstLow = String.fromCharCode(obj);
michael@0 17793 cMap.mapRange(low, high, dstLow);
michael@0 17794 }
michael@0 17795 }
michael@0 17796
michael@0 17797 function parseCodespaceRange(cMap, lexer) {
michael@0 17798 while (true) {
michael@0 17799 var obj = lexer.getObj();
michael@0 17800 if (isEOF(obj)) {
michael@0 17801 break;
michael@0 17802 }
michael@0 17803 if (isCmd(obj, 'endcodespacerange')) {
michael@0 17804 return;
michael@0 17805 }
michael@0 17806 if (!isString(obj)) {
michael@0 17807 break;
michael@0 17808 }
michael@0 17809 var low = strToInt(obj);
michael@0 17810 obj = lexer.getObj();
michael@0 17811 if (!isString(obj)) {
michael@0 17812 break;
michael@0 17813 }
michael@0 17814 var high = strToInt(obj);
michael@0 17815 cMap.addCodespaceRange(obj.length, low, high);
michael@0 17816 }
michael@0 17817 error('Invalid codespace range.');
michael@0 17818 }
michael@0 17819
michael@0 17820 function parseWMode(cMap, lexer) {
michael@0 17821 var obj = lexer.getObj();
michael@0 17822 if (isInt(obj)) {
michael@0 17823 cMap.vertical = !!obj;
michael@0 17824 }
michael@0 17825 }
michael@0 17826
michael@0 17827 function parseCMap(cMap, lexer, builtInCMapParams, useCMap) {
michael@0 17828 var previous;
michael@0 17829 var embededUseCMap;
michael@0 17830 objLoop: while (true) {
michael@0 17831 var obj = lexer.getObj();
michael@0 17832 if (isEOF(obj)) {
michael@0 17833 break;
michael@0 17834 } else if (isName(obj)) {
michael@0 17835 if (obj.name === 'WMode') {
michael@0 17836 parseWMode(cMap, lexer);
michael@0 17837 }
michael@0 17838 previous = obj;
michael@0 17839 } else if (isCmd(obj)) {
michael@0 17840 switch (obj.cmd) {
michael@0 17841 case 'endcmap':
michael@0 17842 break objLoop;
michael@0 17843 case 'usecmap':
michael@0 17844 if (isName(previous)) {
michael@0 17845 embededUseCMap = previous.name;
michael@0 17846 }
michael@0 17847 break;
michael@0 17848 case 'begincodespacerange':
michael@0 17849 parseCodespaceRange(cMap, lexer);
michael@0 17850 break;
michael@0 17851 case 'beginbfchar':
michael@0 17852 parseBfChar(cMap, lexer);
michael@0 17853 break;
michael@0 17854 case 'begincidchar':
michael@0 17855 parseCidChar(cMap, lexer);
michael@0 17856 break;
michael@0 17857 case 'beginbfrange':
michael@0 17858 parseBfRange(cMap, lexer);
michael@0 17859 break;
michael@0 17860 case 'begincidrange':
michael@0 17861 parseCidRange(cMap, lexer);
michael@0 17862 break;
michael@0 17863 }
michael@0 17864 }
michael@0 17865 }
michael@0 17866
michael@0 17867 if (!useCMap && embededUseCMap) {
michael@0 17868 // Load the usecmap definition from the file only if there wasn't one
michael@0 17869 // specified.
michael@0 17870 useCMap = embededUseCMap;
michael@0 17871 }
michael@0 17872 if (useCMap) {
michael@0 17873 extendCMap(cMap, builtInCMapParams, useCMap);
michael@0 17874 }
michael@0 17875 }
michael@0 17876
michael@0 17877 function extendCMap(cMap, builtInCMapParams, useCMap) {
michael@0 17878 cMap.useCMap = createBuiltInCMap(useCMap, builtInCMapParams);
michael@0 17879 // If there aren't any code space ranges defined clone all the parent ones
michael@0 17880 // into this cMap.
michael@0 17881 if (cMap.numCodespaceRanges === 0) {
michael@0 17882 var useCodespaceRanges = cMap.useCMap.codespaceRanges;
michael@0 17883 for (var i = 0; i < useCodespaceRanges.length; i++) {
michael@0 17884 cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();
michael@0 17885 }
michael@0 17886 cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;
michael@0 17887 }
michael@0 17888 // Merge the map into the current one, making sure not to override
michael@0 17889 // any previously defined entries.
michael@0 17890 for (var key in cMap.useCMap.map) {
michael@0 17891 if (key in cMap.map) {
michael@0 17892 continue;
michael@0 17893 }
michael@0 17894 cMap.map[key] = cMap.useCMap.map[key];
michael@0 17895 }
michael@0 17896 }
michael@0 17897
michael@0 17898 function parseBinaryCMap(name, builtInCMapParams) {
michael@0 17899 var url = builtInCMapParams.url + name + '.bcmap';
michael@0 17900 var cMap = new CMap(true);
michael@0 17901 new BinaryCMapReader().read(url, cMap, function (useCMap) {
michael@0 17902 extendCMap(cMap, builtInCMapParams, useCMap);
michael@0 17903 });
michael@0 17904 return cMap;
michael@0 17905 }
michael@0 17906
michael@0 17907 function createBuiltInCMap(name, builtInCMapParams) {
michael@0 17908 if (name === 'Identity-H') {
michael@0 17909 return new IdentityCMap(false, 2);
michael@0 17910 } else if (name === 'Identity-V') {
michael@0 17911 return new IdentityCMap(true, 2);
michael@0 17912 }
michael@0 17913 if (BUILT_IN_CMAPS.indexOf(name) === -1) {
michael@0 17914 error('Unknown cMap name: ' + name);
michael@0 17915 }
michael@0 17916 assert (builtInCMapParams, 'buildin cmap parameters are not provided');
michael@0 17917
michael@0 17918 if (builtInCMapParams.packed) {
michael@0 17919 return parseBinaryCMap(name, builtInCMapParams);
michael@0 17920 }
michael@0 17921
michael@0 17922 var request = new XMLHttpRequest();
michael@0 17923 var url = builtInCMapParams.url + name;
michael@0 17924 request.open('GET', url, false);
michael@0 17925 request.send(null);
michael@0 17926 if (request.status === 0 && /^https?:/i.test(url)) {
michael@0 17927 error('Unable to get cMap at: ' + url);
michael@0 17928 }
michael@0 17929 var cMap = new CMap(true);
michael@0 17930 var lexer = new Lexer(new StringStream(request.responseText));
michael@0 17931 parseCMap(cMap, lexer, builtInCMapParams, null);
michael@0 17932 return cMap;
michael@0 17933 }
michael@0 17934
michael@0 17935 return {
michael@0 17936 create: function (encoding, builtInCMapParams, useCMap) {
michael@0 17937 if (isName(encoding)) {
michael@0 17938 return createBuiltInCMap(encoding.name, builtInCMapParams);
michael@0 17939 } else if (isStream(encoding)) {
michael@0 17940 var cMap = new CMap();
michael@0 17941 var lexer = new Lexer(encoding);
michael@0 17942 try {
michael@0 17943 parseCMap(cMap, lexer, builtInCMapParams, useCMap);
michael@0 17944 } catch (e) {
michael@0 17945 warn('Invalid CMap data. ' + e);
michael@0 17946 }
michael@0 17947 return cMap;
michael@0 17948 }
michael@0 17949 error('Encoding required.');
michael@0 17950 }
michael@0 17951 };
michael@0 17952 })();
michael@0 17953
michael@0 17954
michael@0 17955 // Unicode Private Use Area
michael@0 17956 var PRIVATE_USE_OFFSET_START = 0xE000;
michael@0 17957 var PRIVATE_USE_OFFSET_END = 0xF8FF;
michael@0 17958 var SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = false;
michael@0 17959
michael@0 17960 // PDF Glyph Space Units are one Thousandth of a TextSpace Unit
michael@0 17961 // except for Type 3 fonts
michael@0 17962 var PDF_GLYPH_SPACE_UNITS = 1000;
michael@0 17963
michael@0 17964 // Hinting is currently disabled due to unknown problems on windows
michael@0 17965 // in tracemonkey and various other pdfs with type1 fonts.
michael@0 17966 var HINTING_ENABLED = false;
michael@0 17967
michael@0 17968 // Accented charactars are not displayed properly on windows, using this flag
michael@0 17969 // to control analysis of seac charstrings.
michael@0 17970 var SEAC_ANALYSIS_ENABLED = false;
michael@0 17971
michael@0 17972 var FontFlags = {
michael@0 17973 FixedPitch: 1,
michael@0 17974 Serif: 2,
michael@0 17975 Symbolic: 4,
michael@0 17976 Script: 8,
michael@0 17977 Nonsymbolic: 32,
michael@0 17978 Italic: 64,
michael@0 17979 AllCap: 65536,
michael@0 17980 SmallCap: 131072,
michael@0 17981 ForceBold: 262144
michael@0 17982 };
michael@0 17983
michael@0 17984 var Encodings = {
michael@0 17985 ExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 17986 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 17987 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle',
michael@0 17988 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
michael@0 17989 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
michael@0 17990 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
michael@0 17991 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
michael@0 17992 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
michael@0 17993 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior',
michael@0 17994 'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior',
michael@0 17995 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
michael@0 17996 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior',
michael@0 17997 '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '',
michael@0 17998 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
michael@0 17999 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
michael@0 18000 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
michael@0 18001 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
michael@0 18002 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
michael@0 18003 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '',
michael@0 18004 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18005 '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
michael@0 18006 '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall',
michael@0 18007 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '',
michael@0 18008 'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall',
michael@0 18009 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
michael@0 18010 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
michael@0 18011 'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior',
michael@0 18012 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior',
michael@0 18013 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
michael@0 18014 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
michael@0 18015 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
michael@0 18016 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior',
michael@0 18017 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
michael@0 18018 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
michael@0 18019 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
michael@0 18020 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
michael@0 18021 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
michael@0 18022 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
michael@0 18023 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
michael@0 18024 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
michael@0 18025 'Ydieresissmall'],
michael@0 18026 MacExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18027 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18028 'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle',
michael@0 18029 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
michael@0 18030 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
michael@0 18031 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle',
michael@0 18032 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle',
michael@0 18033 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle',
michael@0 18034 'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '',
michael@0 18035 'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter',
michael@0 18036 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
michael@0 18037 'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff',
michael@0 18038 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior',
michael@0 18039 'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall',
michael@0 18040 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
michael@0 18041 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
michael@0 18042 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
michael@0 18043 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
michael@0 18044 'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '',
michael@0 18045 'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall',
michael@0 18046 'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall',
michael@0 18047 'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall',
michael@0 18048 'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall',
michael@0 18049 'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall',
michael@0 18050 'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '',
michael@0 18051 'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior',
michael@0 18052 'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior',
michael@0 18053 'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior',
michael@0 18054 'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '',
michael@0 18055 'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior',
michael@0 18056 'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall',
michael@0 18057 'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '',
michael@0 18058 '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '',
michael@0 18059 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior',
michael@0 18060 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
michael@0 18061 'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior',
michael@0 18062 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior',
michael@0 18063 '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall',
michael@0 18064 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior',
michael@0 18065 'periodsuperior', 'Dotaccentsmall', 'Ringsmall'],
michael@0 18066 MacRomanEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18067 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18068 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
michael@0 18069 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
michael@0 18070 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
michael@0 18071 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
michael@0 18072 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
michael@0 18073 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
michael@0 18074 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
michael@0 18075 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
michael@0 18076 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
michael@0 18077 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '',
michael@0 18078 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis',
michael@0 18079 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde',
michael@0 18080 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
michael@0 18081 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute',
michael@0 18082 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave',
michael@0 18083 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling',
michael@0 18084 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright',
michael@0 18085 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity',
michael@0 18086 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff',
michael@0 18087 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine',
michael@0 18088 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot',
michael@0 18089 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft',
michael@0 18090 'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE',
michael@0 18091 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft',
michael@0 18092 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
michael@0 18093 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl',
michael@0 18094 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand',
michael@0 18095 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
michael@0 18096 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple',
michael@0 18097 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex',
michael@0 18098 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
michael@0 18099 'ogonek', 'caron'],
michael@0 18100 StandardEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18101 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18102 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
michael@0 18103 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
michael@0 18104 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
michael@0 18105 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
michael@0 18106 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
michael@0 18107 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
michael@0 18108 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
michael@0 18109 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f',
michael@0 18110 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
michael@0 18111 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
michael@0 18112 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18113 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown',
michael@0 18114 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
michael@0 18115 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
michael@0 18116 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
michael@0 18117 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
michael@0 18118 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
michael@0 18119 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
michael@0 18120 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla',
michael@0 18121 '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '',
michael@0 18122 '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '',
michael@0 18123 '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae',
michael@0 18124 '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'],
michael@0 18125 WinAnsiEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18126 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18127 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
michael@0 18128 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
michael@0 18129 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
michael@0 18130 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
michael@0 18131 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
michael@0 18132 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
michael@0 18133 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
michael@0 18134 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
michael@0 18135 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
michael@0 18136 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
michael@0 18137 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase',
michael@0 18138 'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron',
michael@0 18139 'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft',
michael@0 18140 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash',
michael@0 18141 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet',
michael@0 18142 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling',
michael@0 18143 'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright',
michael@0 18144 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered',
michael@0 18145 'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute',
michael@0 18146 'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior',
michael@0 18147 'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters',
michael@0 18148 'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis',
michael@0 18149 'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
michael@0 18150 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve',
michael@0 18151 'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash',
michael@0 18152 'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn',
michael@0 18153 'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis',
michael@0 18154 'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis',
michael@0 18155 'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
michael@0 18156 'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
michael@0 18157 'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
michael@0 18158 'ydieresis'],
michael@0 18159 SymbolSetEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18160 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18161 'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
michael@0 18162 'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus',
michael@0 18163 'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
michael@0 18164 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
michael@0 18165 'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi',
michael@0 18166 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa',
michael@0 18167 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau',
michael@0 18168 'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft',
michael@0 18169 'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex',
michael@0 18170 'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota',
michael@0 18171 'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho',
michael@0 18172 'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta',
michael@0 18173 'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '',
michael@0 18174 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18175 '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal',
michael@0 18176 'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade',
michael@0 18177 'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree',
michael@0 18178 'plusminus', 'second', 'greaterequal', 'multiply', 'proportional',
michael@0 18179 'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence',
michael@0 18180 'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn',
michael@0 18181 'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply',
michael@0 18182 'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset',
michael@0 18183 'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element',
michael@0 18184 'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif',
michael@0 18185 'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot',
michael@0 18186 'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup',
michael@0 18187 'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans',
michael@0 18188 'copyrightsans', 'trademarksans', 'summation', 'parenlefttp',
michael@0 18189 'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex',
michael@0 18190 'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex',
michael@0 18191 '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt',
michael@0 18192 'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
michael@0 18193 'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
michael@0 18194 'bracerightbt'],
michael@0 18195 zapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18196 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18197 'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117',
michael@0 18198 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19',
michael@0 18199 'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7',
michael@0 18200 'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36',
michael@0 18201 'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46',
michael@0 18202 'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56',
michael@0 18203 'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66',
michael@0 18204 'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75',
michael@0 18205 'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97',
michael@0 18206 'a98', 'a99', 'a100', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18207 '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
michael@0 18208 '', '', 'a101', 'a102', 'a103', 'a104', 'a106', 'a107', 'a108', 'a112',
michael@0 18209 'a111', 'a110', 'a109', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125',
michael@0 18210 'a126', 'a127', 'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134',
michael@0 18211 'a135', 'a136', 'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143',
michael@0 18212 'a144', 'a145', 'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152',
michael@0 18213 'a153', 'a154', 'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161',
michael@0 18214 'a163', 'a164', 'a196', 'a165', 'a192', 'a166', 'a167', 'a168', 'a169',
michael@0 18215 'a170', 'a171', 'a172', 'a173', 'a162', 'a174', 'a175', 'a176', 'a177',
michael@0 18216 'a178', 'a179', 'a193', 'a180', 'a199', 'a181', 'a200', 'a182', '', 'a201',
michael@0 18217 'a183', 'a184', 'a197', 'a185', 'a194', 'a198', 'a186', 'a195', 'a187',
michael@0 18218 'a188', 'a189', 'a190', 'a191']
michael@0 18219 };
michael@0 18220
michael@0 18221 /**
michael@0 18222 * Hold a map of decoded fonts and of the standard fourteen Type1
michael@0 18223 * fonts and their acronyms.
michael@0 18224 */
michael@0 18225 var stdFontMap = {
michael@0 18226 'ArialNarrow': 'Helvetica',
michael@0 18227 'ArialNarrow-Bold': 'Helvetica-Bold',
michael@0 18228 'ArialNarrow-BoldItalic': 'Helvetica-BoldOblique',
michael@0 18229 'ArialNarrow-Italic': 'Helvetica-Oblique',
michael@0 18230 'ArialBlack': 'Helvetica',
michael@0 18231 'ArialBlack-Bold': 'Helvetica-Bold',
michael@0 18232 'ArialBlack-BoldItalic': 'Helvetica-BoldOblique',
michael@0 18233 'ArialBlack-Italic': 'Helvetica-Oblique',
michael@0 18234 'Arial': 'Helvetica',
michael@0 18235 'Arial-Bold': 'Helvetica-Bold',
michael@0 18236 'Arial-BoldItalic': 'Helvetica-BoldOblique',
michael@0 18237 'Arial-Italic': 'Helvetica-Oblique',
michael@0 18238 'Arial-BoldItalicMT': 'Helvetica-BoldOblique',
michael@0 18239 'Arial-BoldMT': 'Helvetica-Bold',
michael@0 18240 'Arial-ItalicMT': 'Helvetica-Oblique',
michael@0 18241 'ArialMT': 'Helvetica',
michael@0 18242 'Courier-Bold': 'Courier-Bold',
michael@0 18243 'Courier-BoldItalic': 'Courier-BoldOblique',
michael@0 18244 'Courier-Italic': 'Courier-Oblique',
michael@0 18245 'CourierNew': 'Courier',
michael@0 18246 'CourierNew-Bold': 'Courier-Bold',
michael@0 18247 'CourierNew-BoldItalic': 'Courier-BoldOblique',
michael@0 18248 'CourierNew-Italic': 'Courier-Oblique',
michael@0 18249 'CourierNewPS-BoldItalicMT': 'Courier-BoldOblique',
michael@0 18250 'CourierNewPS-BoldMT': 'Courier-Bold',
michael@0 18251 'CourierNewPS-ItalicMT': 'Courier-Oblique',
michael@0 18252 'CourierNewPSMT': 'Courier',
michael@0 18253 'Helvetica-Bold': 'Helvetica-Bold',
michael@0 18254 'Helvetica-BoldItalic': 'Helvetica-BoldOblique',
michael@0 18255 'Helvetica-Italic': 'Helvetica-Oblique',
michael@0 18256 'Symbol-Bold': 'Symbol',
michael@0 18257 'Symbol-BoldItalic': 'Symbol',
michael@0 18258 'Symbol-Italic': 'Symbol',
michael@0 18259 'TimesNewRoman': 'Times-Roman',
michael@0 18260 'TimesNewRoman-Bold': 'Times-Bold',
michael@0 18261 'TimesNewRoman-BoldItalic': 'Times-BoldItalic',
michael@0 18262 'TimesNewRoman-Italic': 'Times-Italic',
michael@0 18263 'TimesNewRomanPS': 'Times-Roman',
michael@0 18264 'TimesNewRomanPS-Bold': 'Times-Bold',
michael@0 18265 'TimesNewRomanPS-BoldItalic': 'Times-BoldItalic',
michael@0 18266 'TimesNewRomanPS-BoldItalicMT': 'Times-BoldItalic',
michael@0 18267 'TimesNewRomanPS-BoldMT': 'Times-Bold',
michael@0 18268 'TimesNewRomanPS-Italic': 'Times-Italic',
michael@0 18269 'TimesNewRomanPS-ItalicMT': 'Times-Italic',
michael@0 18270 'TimesNewRomanPSMT': 'Times-Roman',
michael@0 18271 'TimesNewRomanPSMT-Bold': 'Times-Bold',
michael@0 18272 'TimesNewRomanPSMT-BoldItalic': 'Times-BoldItalic',
michael@0 18273 'TimesNewRomanPSMT-Italic': 'Times-Italic'
michael@0 18274 };
michael@0 18275
michael@0 18276 /**
michael@0 18277 * Holds the map of the non-standard fonts that might be included as a standard
michael@0 18278 * fonts without glyph data.
michael@0 18279 */
michael@0 18280 var nonStdFontMap = {
michael@0 18281 'ComicSansMS': 'Comic Sans MS',
michael@0 18282 'ComicSansMS-Bold': 'Comic Sans MS-Bold',
michael@0 18283 'ComicSansMS-BoldItalic': 'Comic Sans MS-BoldItalic',
michael@0 18284 'ComicSansMS-Italic': 'Comic Sans MS-Italic',
michael@0 18285 'LucidaConsole': 'Courier',
michael@0 18286 'LucidaConsole-Bold': 'Courier-Bold',
michael@0 18287 'LucidaConsole-BoldItalic': 'Courier-BoldOblique',
michael@0 18288 'LucidaConsole-Italic': 'Courier-Oblique',
michael@0 18289 'MS-Gothic': 'MS Gothic',
michael@0 18290 'MS-Gothic-Bold': 'MS Gothic-Bold',
michael@0 18291 'MS-Gothic-BoldItalic': 'MS Gothic-BoldItalic',
michael@0 18292 'MS-Gothic-Italic': 'MS Gothic-Italic',
michael@0 18293 'MS-Mincho': 'MS Mincho',
michael@0 18294 'MS-Mincho-Bold': 'MS Mincho-Bold',
michael@0 18295 'MS-Mincho-BoldItalic': 'MS Mincho-BoldItalic',
michael@0 18296 'MS-Mincho-Italic': 'MS Mincho-Italic',
michael@0 18297 'MS-PGothic': 'MS PGothic',
michael@0 18298 'MS-PGothic-Bold': 'MS PGothic-Bold',
michael@0 18299 'MS-PGothic-BoldItalic': 'MS PGothic-BoldItalic',
michael@0 18300 'MS-PGothic-Italic': 'MS PGothic-Italic',
michael@0 18301 'MS-PMincho': 'MS PMincho',
michael@0 18302 'MS-PMincho-Bold': 'MS PMincho-Bold',
michael@0 18303 'MS-PMincho-BoldItalic': 'MS PMincho-BoldItalic',
michael@0 18304 'MS-PMincho-Italic': 'MS PMincho-Italic'
michael@0 18305 };
michael@0 18306
michael@0 18307 var serifFonts = {
michael@0 18308 'Adobe Jenson': true, 'Adobe Text': true, 'Albertus': true,
michael@0 18309 'Aldus': true, 'Alexandria': true, 'Algerian': true,
michael@0 18310 'American Typewriter': true, 'Antiqua': true, 'Apex': true,
michael@0 18311 'Arno': true, 'Aster': true, 'Aurora': true,
michael@0 18312 'Baskerville': true, 'Bell': true, 'Bembo': true,
michael@0 18313 'Bembo Schoolbook': true, 'Benguiat': true, 'Berkeley Old Style': true,
michael@0 18314 'Bernhard Modern': true, 'Berthold City': true, 'Bodoni': true,
michael@0 18315 'Bauer Bodoni': true, 'Book Antiqua': true, 'Bookman': true,
michael@0 18316 'Bordeaux Roman': true, 'Californian FB': true, 'Calisto': true,
michael@0 18317 'Calvert': true, 'Capitals': true, 'Cambria': true,
michael@0 18318 'Cartier': true, 'Caslon': true, 'Catull': true,
michael@0 18319 'Centaur': true, 'Century Old Style': true, 'Century Schoolbook': true,
michael@0 18320 'Chaparral': true, 'Charis SIL': true, 'Cheltenham': true,
michael@0 18321 'Cholla Slab': true, 'Clarendon': true, 'Clearface': true,
michael@0 18322 'Cochin': true, 'Colonna': true, 'Computer Modern': true,
michael@0 18323 'Concrete Roman': true, 'Constantia': true, 'Cooper Black': true,
michael@0 18324 'Corona': true, 'Ecotype': true, 'Egyptienne': true,
michael@0 18325 'Elephant': true, 'Excelsior': true, 'Fairfield': true,
michael@0 18326 'FF Scala': true, 'Folkard': true, 'Footlight': true,
michael@0 18327 'FreeSerif': true, 'Friz Quadrata': true, 'Garamond': true,
michael@0 18328 'Gentium': true, 'Georgia': true, 'Gloucester': true,
michael@0 18329 'Goudy Old Style': true, 'Goudy Schoolbook': true, 'Goudy Pro Font': true,
michael@0 18330 'Granjon': true, 'Guardian Egyptian': true, 'Heather': true,
michael@0 18331 'Hercules': true, 'High Tower Text': true, 'Hiroshige': true,
michael@0 18332 'Hoefler Text': true, 'Humana Serif': true, 'Imprint': true,
michael@0 18333 'Ionic No. 5': true, 'Janson': true, 'Joanna': true,
michael@0 18334 'Korinna': true, 'Lexicon': true, 'Liberation Serif': true,
michael@0 18335 'Linux Libertine': true, 'Literaturnaya': true, 'Lucida': true,
michael@0 18336 'Lucida Bright': true, 'Melior': true, 'Memphis': true,
michael@0 18337 'Miller': true, 'Minion': true, 'Modern': true,
michael@0 18338 'Mona Lisa': true, 'Mrs Eaves': true, 'MS Serif': true,
michael@0 18339 'Museo Slab': true, 'New York': true, 'Nimbus Roman': true,
michael@0 18340 'NPS Rawlinson Roadway': true, 'Palatino': true, 'Perpetua': true,
michael@0 18341 'Plantin': true, 'Plantin Schoolbook': true, 'Playbill': true,
michael@0 18342 'Poor Richard': true, 'Rawlinson Roadway': true, 'Renault': true,
michael@0 18343 'Requiem': true, 'Rockwell': true, 'Roman': true,
michael@0 18344 'Rotis Serif': true, 'Sabon': true, 'Scala': true,
michael@0 18345 'Seagull': true, 'Sistina': true, 'Souvenir': true,
michael@0 18346 'STIX': true, 'Stone Informal': true, 'Stone Serif': true,
michael@0 18347 'Sylfaen': true, 'Times': true, 'Trajan': true,
michael@0 18348 'Trinité': true, 'Trump Mediaeval': true, 'Utopia': true,
michael@0 18349 'Vale Type': true, 'Bitstream Vera': true, 'Vera Serif': true,
michael@0 18350 'Versailles': true, 'Wanted': true, 'Weiss': true,
michael@0 18351 'Wide Latin': true, 'Windsor': true, 'XITS': true
michael@0 18352 };
michael@0 18353
michael@0 18354 var symbolsFonts = {
michael@0 18355 'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true
michael@0 18356 };
michael@0 18357
michael@0 18358 // Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID fonts
michael@0 18359 // but does not embed the CID to GID mapping. The mapping is incomplete for all
michael@0 18360 // glyphs, but common for some set of the standard fonts.
michael@0 18361 var GlyphMapForStandardFonts = {
michael@0 18362 '2': 10, '3': 32, '4': 33, '5': 34, '6': 35, '7': 36, '8': 37, '9': 38,
michael@0 18363 '10': 39, '11': 40, '12': 41, '13': 42, '14': 43, '15': 44, '16': 173,
michael@0 18364 '17': 46, '18': 47, '19': 48, '20': 49, '21': 50, '22': 51, '23': 52,
michael@0 18365 '24': 53, '25': 54, '26': 55, '27': 56, '28': 57, '29': 58, '30': 894,
michael@0 18366 '31': 60, '32': 61, '33': 62, '34': 63, '35': 64, '36': 65, '37': 66,
michael@0 18367 '38': 67, '39': 68, '40': 69, '41': 70, '42': 71, '43': 72, '44': 73,
michael@0 18368 '45': 74, '46': 75, '47': 76, '48': 77, '49': 78, '50': 79, '51': 80,
michael@0 18369 '52': 81, '53': 82, '54': 83, '55': 84, '56': 85, '57': 86, '58': 87,
michael@0 18370 '59': 88, '60': 89, '61': 90, '62': 91, '63': 92, '64': 93, '65': 94,
michael@0 18371 '66': 95, '67': 96, '68': 97, '69': 98, '70': 99, '71': 100, '72': 101,
michael@0 18372 '73': 102, '74': 103, '75': 104, '76': 105, '77': 106, '78': 107, '79': 108,
michael@0 18373 '80': 109, '81': 110, '82': 111, '83': 112, '84': 113, '85': 114, '86': 115,
michael@0 18374 '87': 116, '88': 117, '89': 118, '90': 119, '91': 120, '92': 121, '93': 122,
michael@0 18375 '94': 123, '95': 124, '96': 125, '97': 126, '98': 196, '99': 197, '100': 199,
michael@0 18376 '101': 201, '102': 209, '103': 214, '104': 220, '105': 225, '106': 224,
michael@0 18377 '107': 226, '108': 228, '109': 227, '110': 229, '111': 231, '112': 233,
michael@0 18378 '113': 232, '114': 234, '115': 235, '116': 237, '117': 236, '118': 238,
michael@0 18379 '119': 239, '120': 241, '121': 243, '122': 242, '123': 244, '124': 246,
michael@0 18380 '125': 245, '126': 250, '127': 249, '128': 251, '129': 252, '130': 8224,
michael@0 18381 '131': 176, '132': 162, '133': 163, '134': 167, '135': 8226, '136': 182,
michael@0 18382 '137': 223, '138': 174, '139': 169, '140': 8482, '141': 180, '142': 168,
michael@0 18383 '143': 8800, '144': 198, '145': 216, '146': 8734, '147': 177, '148': 8804,
michael@0 18384 '149': 8805, '150': 165, '151': 181, '152': 8706, '153': 8721, '154': 8719,
michael@0 18385 '156': 8747, '157': 170, '158': 186, '159': 8486, '160': 230, '161': 248,
michael@0 18386 '162': 191, '163': 161, '164': 172, '165': 8730, '166': 402, '167': 8776,
michael@0 18387 '168': 8710, '169': 171, '170': 187, '171': 8230, '210': 218, '305': 963,
michael@0 18388 '306': 964, '307': 966, '308': 8215, '309': 8252, '310': 8319, '311': 8359,
michael@0 18389 '312': 8592, '313': 8593, '337': 9552, '493': 1039, '494': 1040, '705': 1524,
michael@0 18390 '706': 8362, '710': 64288, '711': 64298, '759': 1617, '761': 1776,
michael@0 18391 '763': 1778, '775': 1652, '777': 1764, '778': 1780, '779': 1781, '780': 1782,
michael@0 18392 '782': 771, '783': 64726, '786': 8363, '788': 8532, '790': 768, '791': 769,
michael@0 18393 '792': 768, '795': 803, '797': 64336, '798': 64337, '799': 64342,
michael@0 18394 '800': 64343, '801': 64344, '802': 64345, '803': 64362, '804': 64363,
michael@0 18395 '805': 64364, '2424': 7821, '2425': 7822, '2426': 7823, '2427': 7824,
michael@0 18396 '2428': 7825, '2429': 7826, '2430': 7827, '2433': 7682, '2678': 8045,
michael@0 18397 '2679': 8046, '2830': 1552, '2838': 686, '2840': 751, '2842': 753,
michael@0 18398 '2843': 754, '2844': 755, '2846': 757, '2856': 767, '2857': 848, '2858': 849,
michael@0 18399 '2862': 853, '2863': 854, '2864': 855, '2865': 861, '2866': 862, '2906': 7460,
michael@0 18400 '2908': 7462, '2909': 7463, '2910': 7464, '2912': 7466, '2913': 7467,
michael@0 18401 '2914': 7468, '2916': 7470, '2917': 7471, '2918': 7472, '2920': 7474,
michael@0 18402 '2921': 7475, '2922': 7476, '2924': 7478, '2925': 7479, '2926': 7480,
michael@0 18403 '2928': 7482, '2929': 7483, '2930': 7484, '2932': 7486, '2933': 7487,
michael@0 18404 '2934': 7488, '2936': 7490, '2937': 7491, '2938': 7492, '2940': 7494,
michael@0 18405 '2941': 7495, '2942': 7496, '2944': 7498, '2946': 7500, '2948': 7502,
michael@0 18406 '2950': 7504, '2951': 7505, '2952': 7506, '2954': 7508, '2955': 7509,
michael@0 18407 '2956': 7510, '2958': 7512, '2959': 7513, '2960': 7514, '2962': 7516,
michael@0 18408 '2963': 7517, '2964': 7518, '2966': 7520, '2967': 7521, '2968': 7522,
michael@0 18409 '2970': 7524, '2971': 7525, '2972': 7526, '2974': 7528, '2975': 7529,
michael@0 18410 '2976': 7530, '2978': 1537, '2979': 1538, '2980': 1539, '2982': 1549,
michael@0 18411 '2983': 1551, '2984': 1552, '2986': 1554, '2987': 1555, '2988': 1556,
michael@0 18412 '2990': 1623, '2991': 1624, '2995': 1775, '2999': 1791, '3002': 64290,
michael@0 18413 '3003': 64291, '3004': 64292, '3006': 64294, '3007': 64295, '3008': 64296,
michael@0 18414 '3011': 1900, '3014': 8223, '3015': 8244, '3017': 7532, '3018': 7533,
michael@0 18415 '3019': 7534, '3075': 7590, '3076': 7591, '3079': 7594, '3080': 7595,
michael@0 18416 '3083': 7598, '3084': 7599, '3087': 7602, '3088': 7603, '3091': 7606,
michael@0 18417 '3092': 7607, '3095': 7610, '3096': 7611, '3099': 7614, '3100': 7615,
michael@0 18418 '3103': 7618, '3104': 7619, '3107': 8337, '3108': 8338, '3116': 1884,
michael@0 18419 '3119': 1885, '3120': 1885, '3123': 1886, '3124': 1886, '3127': 1887,
michael@0 18420 '3128': 1887, '3131': 1888, '3132': 1888, '3135': 1889, '3136': 1889,
michael@0 18421 '3139': 1890, '3140': 1890, '3143': 1891, '3144': 1891, '3147': 1892,
michael@0 18422 '3148': 1892, '3153': 580, '3154': 581, '3157': 584, '3158': 585, '3161': 588,
michael@0 18423 '3162': 589, '3165': 891, '3166': 892, '3169': 1274, '3170': 1275,
michael@0 18424 '3173': 1278, '3174': 1279, '3181': 7622, '3182': 7623, '3282': 11799,
michael@0 18425 '3316': 578, '3379': 42785, '3393': 1159, '3416': 8377
michael@0 18426 };
michael@0 18427
michael@0 18428 // Some characters, e.g. copyrightserif, mapped to the private use area and
michael@0 18429 // might not be displayed using standard fonts. Mapping/hacking well-known chars
michael@0 18430 // to the similar equivalents in the normal characters range.
michael@0 18431 function mapSpecialUnicodeValues(code) {
michael@0 18432 if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials unicode block.
michael@0 18433 return 0;
michael@0 18434 }
michael@0 18435 switch (code) {
michael@0 18436 case 0xF8E9: // copyrightsans
michael@0 18437 case 0xF6D9: // copyrightserif
michael@0 18438 return 0x00A9; // copyright
michael@0 18439
michael@0 18440 case 0xF8E8: // registersans
michael@0 18441 case 0xF6DA: // registerserif
michael@0 18442 return 0x00AE; // registered
michael@0 18443
michael@0 18444 case 0xF8EA: // trademarksans
michael@0 18445 case 0xF6DB: // trademarkserif
michael@0 18446 return 0x2122; // trademark
michael@0 18447
michael@0 18448 default:
michael@0 18449 return code;
michael@0 18450 }
michael@0 18451 }
michael@0 18452
michael@0 18453 var UnicodeRanges = [
michael@0 18454 { 'begin': 0x0000, 'end': 0x007F }, // Basic Latin
michael@0 18455 { 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement
michael@0 18456 { 'begin': 0x0100, 'end': 0x017F }, // Latin Extended-A
michael@0 18457 { 'begin': 0x0180, 'end': 0x024F }, // Latin Extended-B
michael@0 18458 { 'begin': 0x0250, 'end': 0x02AF }, // IPA Extensions
michael@0 18459 { 'begin': 0x02B0, 'end': 0x02FF }, // Spacing Modifier Letters
michael@0 18460 { 'begin': 0x0300, 'end': 0x036F }, // Combining Diacritical Marks
michael@0 18461 { 'begin': 0x0370, 'end': 0x03FF }, // Greek and Coptic
michael@0 18462 { 'begin': 0x2C80, 'end': 0x2CFF }, // Coptic
michael@0 18463 { 'begin': 0x0400, 'end': 0x04FF }, // Cyrillic
michael@0 18464 { 'begin': 0x0530, 'end': 0x058F }, // Armenian
michael@0 18465 { 'begin': 0x0590, 'end': 0x05FF }, // Hebrew
michael@0 18466 { 'begin': 0xA500, 'end': 0xA63F }, // Vai
michael@0 18467 { 'begin': 0x0600, 'end': 0x06FF }, // Arabic
michael@0 18468 { 'begin': 0x07C0, 'end': 0x07FF }, // NKo
michael@0 18469 { 'begin': 0x0900, 'end': 0x097F }, // Devanagari
michael@0 18470 { 'begin': 0x0980, 'end': 0x09FF }, // Bengali
michael@0 18471 { 'begin': 0x0A00, 'end': 0x0A7F }, // Gurmukhi
michael@0 18472 { 'begin': 0x0A80, 'end': 0x0AFF }, // Gujarati
michael@0 18473 { 'begin': 0x0B00, 'end': 0x0B7F }, // Oriya
michael@0 18474 { 'begin': 0x0B80, 'end': 0x0BFF }, // Tamil
michael@0 18475 { 'begin': 0x0C00, 'end': 0x0C7F }, // Telugu
michael@0 18476 { 'begin': 0x0C80, 'end': 0x0CFF }, // Kannada
michael@0 18477 { 'begin': 0x0D00, 'end': 0x0D7F }, // Malayalam
michael@0 18478 { 'begin': 0x0E00, 'end': 0x0E7F }, // Thai
michael@0 18479 { 'begin': 0x0E80, 'end': 0x0EFF }, // Lao
michael@0 18480 { 'begin': 0x10A0, 'end': 0x10FF }, // Georgian
michael@0 18481 { 'begin': 0x1B00, 'end': 0x1B7F }, // Balinese
michael@0 18482 { 'begin': 0x1100, 'end': 0x11FF }, // Hangul Jamo
michael@0 18483 { 'begin': 0x1E00, 'end': 0x1EFF }, // Latin Extended Additional
michael@0 18484 { 'begin': 0x1F00, 'end': 0x1FFF }, // Greek Extended
michael@0 18485 { 'begin': 0x2000, 'end': 0x206F }, // General Punctuation
michael@0 18486 { 'begin': 0x2070, 'end': 0x209F }, // Superscripts And Subscripts
michael@0 18487 { 'begin': 0x20A0, 'end': 0x20CF }, // Currency Symbol
michael@0 18488 { 'begin': 0x20D0, 'end': 0x20FF }, // Combining Diacritical Marks For Symbols
michael@0 18489 { 'begin': 0x2100, 'end': 0x214F }, // Letterlike Symbols
michael@0 18490 { 'begin': 0x2150, 'end': 0x218F }, // Number Forms
michael@0 18491 { 'begin': 0x2190, 'end': 0x21FF }, // Arrows
michael@0 18492 { 'begin': 0x2200, 'end': 0x22FF }, // Mathematical Operators
michael@0 18493 { 'begin': 0x2300, 'end': 0x23FF }, // Miscellaneous Technical
michael@0 18494 { 'begin': 0x2400, 'end': 0x243F }, // Control Pictures
michael@0 18495 { 'begin': 0x2440, 'end': 0x245F }, // Optical Character Recognition
michael@0 18496 { 'begin': 0x2460, 'end': 0x24FF }, // Enclosed Alphanumerics
michael@0 18497 { 'begin': 0x2500, 'end': 0x257F }, // Box Drawing
michael@0 18498 { 'begin': 0x2580, 'end': 0x259F }, // Block Elements
michael@0 18499 { 'begin': 0x25A0, 'end': 0x25FF }, // Geometric Shapes
michael@0 18500 { 'begin': 0x2600, 'end': 0x26FF }, // Miscellaneous Symbols
michael@0 18501 { 'begin': 0x2700, 'end': 0x27BF }, // Dingbats
michael@0 18502 { 'begin': 0x3000, 'end': 0x303F }, // CJK Symbols And Punctuation
michael@0 18503 { 'begin': 0x3040, 'end': 0x309F }, // Hiragana
michael@0 18504 { 'begin': 0x30A0, 'end': 0x30FF }, // Katakana
michael@0 18505 { 'begin': 0x3100, 'end': 0x312F }, // Bopomofo
michael@0 18506 { 'begin': 0x3130, 'end': 0x318F }, // Hangul Compatibility Jamo
michael@0 18507 { 'begin': 0xA840, 'end': 0xA87F }, // Phags-pa
michael@0 18508 { 'begin': 0x3200, 'end': 0x32FF }, // Enclosed CJK Letters And Months
michael@0 18509 { 'begin': 0x3300, 'end': 0x33FF }, // CJK Compatibility
michael@0 18510 { 'begin': 0xAC00, 'end': 0xD7AF }, // Hangul Syllables
michael@0 18511 { 'begin': 0xD800, 'end': 0xDFFF }, // Non-Plane 0 *
michael@0 18512 { 'begin': 0x10900, 'end': 0x1091F }, // Phoenicia
michael@0 18513 { 'begin': 0x4E00, 'end': 0x9FFF }, // CJK Unified Ideographs
michael@0 18514 { 'begin': 0xE000, 'end': 0xF8FF }, // Private Use Area (plane 0)
michael@0 18515 { 'begin': 0x31C0, 'end': 0x31EF }, // CJK Strokes
michael@0 18516 { 'begin': 0xFB00, 'end': 0xFB4F }, // Alphabetic Presentation Forms
michael@0 18517 { 'begin': 0xFB50, 'end': 0xFDFF }, // Arabic Presentation Forms-A
michael@0 18518 { 'begin': 0xFE20, 'end': 0xFE2F }, // Combining Half Marks
michael@0 18519 { 'begin': 0xFE10, 'end': 0xFE1F }, // Vertical Forms
michael@0 18520 { 'begin': 0xFE50, 'end': 0xFE6F }, // Small Form Variants
michael@0 18521 { 'begin': 0xFE70, 'end': 0xFEFF }, // Arabic Presentation Forms-B
michael@0 18522 { 'begin': 0xFF00, 'end': 0xFFEF }, // Halfwidth And Fullwidth Forms
michael@0 18523 { 'begin': 0xFFF0, 'end': 0xFFFF }, // Specials
michael@0 18524 { 'begin': 0x0F00, 'end': 0x0FFF }, // Tibetan
michael@0 18525 { 'begin': 0x0700, 'end': 0x074F }, // Syriac
michael@0 18526 { 'begin': 0x0780, 'end': 0x07BF }, // Thaana
michael@0 18527 { 'begin': 0x0D80, 'end': 0x0DFF }, // Sinhala
michael@0 18528 { 'begin': 0x1000, 'end': 0x109F }, // Myanmar
michael@0 18529 { 'begin': 0x1200, 'end': 0x137F }, // Ethiopic
michael@0 18530 { 'begin': 0x13A0, 'end': 0x13FF }, // Cherokee
michael@0 18531 { 'begin': 0x1400, 'end': 0x167F }, // Unified Canadian Aboriginal Syllabics
michael@0 18532 { 'begin': 0x1680, 'end': 0x169F }, // Ogham
michael@0 18533 { 'begin': 0x16A0, 'end': 0x16FF }, // Runic
michael@0 18534 { 'begin': 0x1780, 'end': 0x17FF }, // Khmer
michael@0 18535 { 'begin': 0x1800, 'end': 0x18AF }, // Mongolian
michael@0 18536 { 'begin': 0x2800, 'end': 0x28FF }, // Braille Patterns
michael@0 18537 { 'begin': 0xA000, 'end': 0xA48F }, // Yi Syllables
michael@0 18538 { 'begin': 0x1700, 'end': 0x171F }, // Tagalog
michael@0 18539 { 'begin': 0x10300, 'end': 0x1032F }, // Old Italic
michael@0 18540 { 'begin': 0x10330, 'end': 0x1034F }, // Gothic
michael@0 18541 { 'begin': 0x10400, 'end': 0x1044F }, // Deseret
michael@0 18542 { 'begin': 0x1D000, 'end': 0x1D0FF }, // Byzantine Musical Symbols
michael@0 18543 { 'begin': 0x1D400, 'end': 0x1D7FF }, // Mathematical Alphanumeric Symbols
michael@0 18544 { 'begin': 0xFF000, 'end': 0xFFFFD }, // Private Use (plane 15)
michael@0 18545 { 'begin': 0xFE00, 'end': 0xFE0F }, // Variation Selectors
michael@0 18546 { 'begin': 0xE0000, 'end': 0xE007F }, // Tags
michael@0 18547 { 'begin': 0x1900, 'end': 0x194F }, // Limbu
michael@0 18548 { 'begin': 0x1950, 'end': 0x197F }, // Tai Le
michael@0 18549 { 'begin': 0x1980, 'end': 0x19DF }, // New Tai Lue
michael@0 18550 { 'begin': 0x1A00, 'end': 0x1A1F }, // Buginese
michael@0 18551 { 'begin': 0x2C00, 'end': 0x2C5F }, // Glagolitic
michael@0 18552 { 'begin': 0x2D30, 'end': 0x2D7F }, // Tifinagh
michael@0 18553 { 'begin': 0x4DC0, 'end': 0x4DFF }, // Yijing Hexagram Symbols
michael@0 18554 { 'begin': 0xA800, 'end': 0xA82F }, // Syloti Nagri
michael@0 18555 { 'begin': 0x10000, 'end': 0x1007F }, // Linear B Syllabary
michael@0 18556 { 'begin': 0x10140, 'end': 0x1018F }, // Ancient Greek Numbers
michael@0 18557 { 'begin': 0x10380, 'end': 0x1039F }, // Ugaritic
michael@0 18558 { 'begin': 0x103A0, 'end': 0x103DF }, // Old Persian
michael@0 18559 { 'begin': 0x10450, 'end': 0x1047F }, // Shavian
michael@0 18560 { 'begin': 0x10480, 'end': 0x104AF }, // Osmanya
michael@0 18561 { 'begin': 0x10800, 'end': 0x1083F }, // Cypriot Syllabary
michael@0 18562 { 'begin': 0x10A00, 'end': 0x10A5F }, // Kharoshthi
michael@0 18563 { 'begin': 0x1D300, 'end': 0x1D35F }, // Tai Xuan Jing Symbols
michael@0 18564 { 'begin': 0x12000, 'end': 0x123FF }, // Cuneiform
michael@0 18565 { 'begin': 0x1D360, 'end': 0x1D37F }, // Counting Rod Numerals
michael@0 18566 { 'begin': 0x1B80, 'end': 0x1BBF }, // Sundanese
michael@0 18567 { 'begin': 0x1C00, 'end': 0x1C4F }, // Lepcha
michael@0 18568 { 'begin': 0x1C50, 'end': 0x1C7F }, // Ol Chiki
michael@0 18569 { 'begin': 0xA880, 'end': 0xA8DF }, // Saurashtra
michael@0 18570 { 'begin': 0xA900, 'end': 0xA92F }, // Kayah Li
michael@0 18571 { 'begin': 0xA930, 'end': 0xA95F }, // Rejang
michael@0 18572 { 'begin': 0xAA00, 'end': 0xAA5F }, // Cham
michael@0 18573 { 'begin': 0x10190, 'end': 0x101CF }, // Ancient Symbols
michael@0 18574 { 'begin': 0x101D0, 'end': 0x101FF }, // Phaistos Disc
michael@0 18575 { 'begin': 0x102A0, 'end': 0x102DF }, // Carian
michael@0 18576 { 'begin': 0x1F030, 'end': 0x1F09F } // Domino Tiles
michael@0 18577 ];
michael@0 18578
michael@0 18579 var MacStandardGlyphOrdering = [
michael@0 18580 '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl',
michael@0 18581 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft',
michael@0 18582 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
michael@0 18583 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
michael@0 18584 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at',
michael@0 18585 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
michael@0 18586 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft',
michael@0 18587 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b',
michael@0 18588 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
michael@0 18589 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright',
michael@0 18590 'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde',
michael@0 18591 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis',
michael@0 18592 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
michael@0 18593 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve',
michael@0 18594 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex',
michael@0 18595 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet',
michael@0 18596 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute',
michael@0 18597 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal',
michael@0 18598 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi',
michael@0 18599 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash',
michael@0 18600 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin',
michael@0 18601 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis',
michael@0 18602 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash',
michael@0 18603 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright',
michael@0 18604 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency',
michael@0 18605 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered',
michael@0 18606 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex',
michael@0 18607 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex',
michael@0 18608 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute',
michael@0 18609 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron',
michael@0 18610 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron',
michael@0 18611 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar',
michael@0 18612 'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply',
michael@0 18613 'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter',
michael@0 18614 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla',
michael@0 18615 'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];
michael@0 18616
michael@0 18617 function getUnicodeRangeFor(value) {
michael@0 18618 for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) {
michael@0 18619 var range = UnicodeRanges[i];
michael@0 18620 if (value >= range.begin && value < range.end) {
michael@0 18621 return i;
michael@0 18622 }
michael@0 18623 }
michael@0 18624 return -1;
michael@0 18625 }
michael@0 18626
michael@0 18627 function isRTLRangeFor(value) {
michael@0 18628 var range = UnicodeRanges[13];
michael@0 18629 if (value >= range.begin && value < range.end) {
michael@0 18630 return true;
michael@0 18631 }
michael@0 18632 range = UnicodeRanges[11];
michael@0 18633 if (value >= range.begin && value < range.end) {
michael@0 18634 return true;
michael@0 18635 }
michael@0 18636 return false;
michael@0 18637 }
michael@0 18638
michael@0 18639 // The normalization table is obtained by filtering the Unicode characters
michael@0 18640 // database with <compat> entries.
michael@0 18641 var NormalizedUnicodes = {
michael@0 18642 '\u00A8': '\u0020\u0308',
michael@0 18643 '\u00AF': '\u0020\u0304',
michael@0 18644 '\u00B4': '\u0020\u0301',
michael@0 18645 '\u00B5': '\u03BC',
michael@0 18646 '\u00B8': '\u0020\u0327',
michael@0 18647 '\u0132': '\u0049\u004A',
michael@0 18648 '\u0133': '\u0069\u006A',
michael@0 18649 '\u013F': '\u004C\u00B7',
michael@0 18650 '\u0140': '\u006C\u00B7',
michael@0 18651 '\u0149': '\u02BC\u006E',
michael@0 18652 '\u017F': '\u0073',
michael@0 18653 '\u01C4': '\u0044\u017D',
michael@0 18654 '\u01C5': '\u0044\u017E',
michael@0 18655 '\u01C6': '\u0064\u017E',
michael@0 18656 '\u01C7': '\u004C\u004A',
michael@0 18657 '\u01C8': '\u004C\u006A',
michael@0 18658 '\u01C9': '\u006C\u006A',
michael@0 18659 '\u01CA': '\u004E\u004A',
michael@0 18660 '\u01CB': '\u004E\u006A',
michael@0 18661 '\u01CC': '\u006E\u006A',
michael@0 18662 '\u01F1': '\u0044\u005A',
michael@0 18663 '\u01F2': '\u0044\u007A',
michael@0 18664 '\u01F3': '\u0064\u007A',
michael@0 18665 '\u02D8': '\u0020\u0306',
michael@0 18666 '\u02D9': '\u0020\u0307',
michael@0 18667 '\u02DA': '\u0020\u030A',
michael@0 18668 '\u02DB': '\u0020\u0328',
michael@0 18669 '\u02DC': '\u0020\u0303',
michael@0 18670 '\u02DD': '\u0020\u030B',
michael@0 18671 '\u037A': '\u0020\u0345',
michael@0 18672 '\u0384': '\u0020\u0301',
michael@0 18673 '\u03D0': '\u03B2',
michael@0 18674 '\u03D1': '\u03B8',
michael@0 18675 '\u03D2': '\u03A5',
michael@0 18676 '\u03D5': '\u03C6',
michael@0 18677 '\u03D6': '\u03C0',
michael@0 18678 '\u03F0': '\u03BA',
michael@0 18679 '\u03F1': '\u03C1',
michael@0 18680 '\u03F2': '\u03C2',
michael@0 18681 '\u03F4': '\u0398',
michael@0 18682 '\u03F5': '\u03B5',
michael@0 18683 '\u03F9': '\u03A3',
michael@0 18684 '\u0587': '\u0565\u0582',
michael@0 18685 '\u0675': '\u0627\u0674',
michael@0 18686 '\u0676': '\u0648\u0674',
michael@0 18687 '\u0677': '\u06C7\u0674',
michael@0 18688 '\u0678': '\u064A\u0674',
michael@0 18689 '\u0E33': '\u0E4D\u0E32',
michael@0 18690 '\u0EB3': '\u0ECD\u0EB2',
michael@0 18691 '\u0EDC': '\u0EAB\u0E99',
michael@0 18692 '\u0EDD': '\u0EAB\u0EA1',
michael@0 18693 '\u0F77': '\u0FB2\u0F81',
michael@0 18694 '\u0F79': '\u0FB3\u0F81',
michael@0 18695 '\u1E9A': '\u0061\u02BE',
michael@0 18696 '\u1FBD': '\u0020\u0313',
michael@0 18697 '\u1FBF': '\u0020\u0313',
michael@0 18698 '\u1FC0': '\u0020\u0342',
michael@0 18699 '\u1FFE': '\u0020\u0314',
michael@0 18700 '\u2002': '\u0020',
michael@0 18701 '\u2003': '\u0020',
michael@0 18702 '\u2004': '\u0020',
michael@0 18703 '\u2005': '\u0020',
michael@0 18704 '\u2006': '\u0020',
michael@0 18705 '\u2008': '\u0020',
michael@0 18706 '\u2009': '\u0020',
michael@0 18707 '\u200A': '\u0020',
michael@0 18708 '\u2017': '\u0020\u0333',
michael@0 18709 '\u2024': '\u002E',
michael@0 18710 '\u2025': '\u002E\u002E',
michael@0 18711 '\u2026': '\u002E\u002E\u002E',
michael@0 18712 '\u2033': '\u2032\u2032',
michael@0 18713 '\u2034': '\u2032\u2032\u2032',
michael@0 18714 '\u2036': '\u2035\u2035',
michael@0 18715 '\u2037': '\u2035\u2035\u2035',
michael@0 18716 '\u203C': '\u0021\u0021',
michael@0 18717 '\u203E': '\u0020\u0305',
michael@0 18718 '\u2047': '\u003F\u003F',
michael@0 18719 '\u2048': '\u003F\u0021',
michael@0 18720 '\u2049': '\u0021\u003F',
michael@0 18721 '\u2057': '\u2032\u2032\u2032\u2032',
michael@0 18722 '\u205F': '\u0020',
michael@0 18723 '\u20A8': '\u0052\u0073',
michael@0 18724 '\u2100': '\u0061\u002F\u0063',
michael@0 18725 '\u2101': '\u0061\u002F\u0073',
michael@0 18726 '\u2103': '\u00B0\u0043',
michael@0 18727 '\u2105': '\u0063\u002F\u006F',
michael@0 18728 '\u2106': '\u0063\u002F\u0075',
michael@0 18729 '\u2107': '\u0190',
michael@0 18730 '\u2109': '\u00B0\u0046',
michael@0 18731 '\u2116': '\u004E\u006F',
michael@0 18732 '\u2121': '\u0054\u0045\u004C',
michael@0 18733 '\u2135': '\u05D0',
michael@0 18734 '\u2136': '\u05D1',
michael@0 18735 '\u2137': '\u05D2',
michael@0 18736 '\u2138': '\u05D3',
michael@0 18737 '\u213B': '\u0046\u0041\u0058',
michael@0 18738 '\u2160': '\u0049',
michael@0 18739 '\u2161': '\u0049\u0049',
michael@0 18740 '\u2162': '\u0049\u0049\u0049',
michael@0 18741 '\u2163': '\u0049\u0056',
michael@0 18742 '\u2164': '\u0056',
michael@0 18743 '\u2165': '\u0056\u0049',
michael@0 18744 '\u2166': '\u0056\u0049\u0049',
michael@0 18745 '\u2167': '\u0056\u0049\u0049\u0049',
michael@0 18746 '\u2168': '\u0049\u0058',
michael@0 18747 '\u2169': '\u0058',
michael@0 18748 '\u216A': '\u0058\u0049',
michael@0 18749 '\u216B': '\u0058\u0049\u0049',
michael@0 18750 '\u216C': '\u004C',
michael@0 18751 '\u216D': '\u0043',
michael@0 18752 '\u216E': '\u0044',
michael@0 18753 '\u216F': '\u004D',
michael@0 18754 '\u2170': '\u0069',
michael@0 18755 '\u2171': '\u0069\u0069',
michael@0 18756 '\u2172': '\u0069\u0069\u0069',
michael@0 18757 '\u2173': '\u0069\u0076',
michael@0 18758 '\u2174': '\u0076',
michael@0 18759 '\u2175': '\u0076\u0069',
michael@0 18760 '\u2176': '\u0076\u0069\u0069',
michael@0 18761 '\u2177': '\u0076\u0069\u0069\u0069',
michael@0 18762 '\u2178': '\u0069\u0078',
michael@0 18763 '\u2179': '\u0078',
michael@0 18764 '\u217A': '\u0078\u0069',
michael@0 18765 '\u217B': '\u0078\u0069\u0069',
michael@0 18766 '\u217C': '\u006C',
michael@0 18767 '\u217D': '\u0063',
michael@0 18768 '\u217E': '\u0064',
michael@0 18769 '\u217F': '\u006D',
michael@0 18770 '\u222C': '\u222B\u222B',
michael@0 18771 '\u222D': '\u222B\u222B\u222B',
michael@0 18772 '\u222F': '\u222E\u222E',
michael@0 18773 '\u2230': '\u222E\u222E\u222E',
michael@0 18774 '\u2474': '\u0028\u0031\u0029',
michael@0 18775 '\u2475': '\u0028\u0032\u0029',
michael@0 18776 '\u2476': '\u0028\u0033\u0029',
michael@0 18777 '\u2477': '\u0028\u0034\u0029',
michael@0 18778 '\u2478': '\u0028\u0035\u0029',
michael@0 18779 '\u2479': '\u0028\u0036\u0029',
michael@0 18780 '\u247A': '\u0028\u0037\u0029',
michael@0 18781 '\u247B': '\u0028\u0038\u0029',
michael@0 18782 '\u247C': '\u0028\u0039\u0029',
michael@0 18783 '\u247D': '\u0028\u0031\u0030\u0029',
michael@0 18784 '\u247E': '\u0028\u0031\u0031\u0029',
michael@0 18785 '\u247F': '\u0028\u0031\u0032\u0029',
michael@0 18786 '\u2480': '\u0028\u0031\u0033\u0029',
michael@0 18787 '\u2481': '\u0028\u0031\u0034\u0029',
michael@0 18788 '\u2482': '\u0028\u0031\u0035\u0029',
michael@0 18789 '\u2483': '\u0028\u0031\u0036\u0029',
michael@0 18790 '\u2484': '\u0028\u0031\u0037\u0029',
michael@0 18791 '\u2485': '\u0028\u0031\u0038\u0029',
michael@0 18792 '\u2486': '\u0028\u0031\u0039\u0029',
michael@0 18793 '\u2487': '\u0028\u0032\u0030\u0029',
michael@0 18794 '\u2488': '\u0031\u002E',
michael@0 18795 '\u2489': '\u0032\u002E',
michael@0 18796 '\u248A': '\u0033\u002E',
michael@0 18797 '\u248B': '\u0034\u002E',
michael@0 18798 '\u248C': '\u0035\u002E',
michael@0 18799 '\u248D': '\u0036\u002E',
michael@0 18800 '\u248E': '\u0037\u002E',
michael@0 18801 '\u248F': '\u0038\u002E',
michael@0 18802 '\u2490': '\u0039\u002E',
michael@0 18803 '\u2491': '\u0031\u0030\u002E',
michael@0 18804 '\u2492': '\u0031\u0031\u002E',
michael@0 18805 '\u2493': '\u0031\u0032\u002E',
michael@0 18806 '\u2494': '\u0031\u0033\u002E',
michael@0 18807 '\u2495': '\u0031\u0034\u002E',
michael@0 18808 '\u2496': '\u0031\u0035\u002E',
michael@0 18809 '\u2497': '\u0031\u0036\u002E',
michael@0 18810 '\u2498': '\u0031\u0037\u002E',
michael@0 18811 '\u2499': '\u0031\u0038\u002E',
michael@0 18812 '\u249A': '\u0031\u0039\u002E',
michael@0 18813 '\u249B': '\u0032\u0030\u002E',
michael@0 18814 '\u249C': '\u0028\u0061\u0029',
michael@0 18815 '\u249D': '\u0028\u0062\u0029',
michael@0 18816 '\u249E': '\u0028\u0063\u0029',
michael@0 18817 '\u249F': '\u0028\u0064\u0029',
michael@0 18818 '\u24A0': '\u0028\u0065\u0029',
michael@0 18819 '\u24A1': '\u0028\u0066\u0029',
michael@0 18820 '\u24A2': '\u0028\u0067\u0029',
michael@0 18821 '\u24A3': '\u0028\u0068\u0029',
michael@0 18822 '\u24A4': '\u0028\u0069\u0029',
michael@0 18823 '\u24A5': '\u0028\u006A\u0029',
michael@0 18824 '\u24A6': '\u0028\u006B\u0029',
michael@0 18825 '\u24A7': '\u0028\u006C\u0029',
michael@0 18826 '\u24A8': '\u0028\u006D\u0029',
michael@0 18827 '\u24A9': '\u0028\u006E\u0029',
michael@0 18828 '\u24AA': '\u0028\u006F\u0029',
michael@0 18829 '\u24AB': '\u0028\u0070\u0029',
michael@0 18830 '\u24AC': '\u0028\u0071\u0029',
michael@0 18831 '\u24AD': '\u0028\u0072\u0029',
michael@0 18832 '\u24AE': '\u0028\u0073\u0029',
michael@0 18833 '\u24AF': '\u0028\u0074\u0029',
michael@0 18834 '\u24B0': '\u0028\u0075\u0029',
michael@0 18835 '\u24B1': '\u0028\u0076\u0029',
michael@0 18836 '\u24B2': '\u0028\u0077\u0029',
michael@0 18837 '\u24B3': '\u0028\u0078\u0029',
michael@0 18838 '\u24B4': '\u0028\u0079\u0029',
michael@0 18839 '\u24B5': '\u0028\u007A\u0029',
michael@0 18840 '\u2A0C': '\u222B\u222B\u222B\u222B',
michael@0 18841 '\u2A74': '\u003A\u003A\u003D',
michael@0 18842 '\u2A75': '\u003D\u003D',
michael@0 18843 '\u2A76': '\u003D\u003D\u003D',
michael@0 18844 '\u2E9F': '\u6BCD',
michael@0 18845 '\u2EF3': '\u9F9F',
michael@0 18846 '\u2F00': '\u4E00',
michael@0 18847 '\u2F01': '\u4E28',
michael@0 18848 '\u2F02': '\u4E36',
michael@0 18849 '\u2F03': '\u4E3F',
michael@0 18850 '\u2F04': '\u4E59',
michael@0 18851 '\u2F05': '\u4E85',
michael@0 18852 '\u2F06': '\u4E8C',
michael@0 18853 '\u2F07': '\u4EA0',
michael@0 18854 '\u2F08': '\u4EBA',
michael@0 18855 '\u2F09': '\u513F',
michael@0 18856 '\u2F0A': '\u5165',
michael@0 18857 '\u2F0B': '\u516B',
michael@0 18858 '\u2F0C': '\u5182',
michael@0 18859 '\u2F0D': '\u5196',
michael@0 18860 '\u2F0E': '\u51AB',
michael@0 18861 '\u2F0F': '\u51E0',
michael@0 18862 '\u2F10': '\u51F5',
michael@0 18863 '\u2F11': '\u5200',
michael@0 18864 '\u2F12': '\u529B',
michael@0 18865 '\u2F13': '\u52F9',
michael@0 18866 '\u2F14': '\u5315',
michael@0 18867 '\u2F15': '\u531A',
michael@0 18868 '\u2F16': '\u5338',
michael@0 18869 '\u2F17': '\u5341',
michael@0 18870 '\u2F18': '\u535C',
michael@0 18871 '\u2F19': '\u5369',
michael@0 18872 '\u2F1A': '\u5382',
michael@0 18873 '\u2F1B': '\u53B6',
michael@0 18874 '\u2F1C': '\u53C8',
michael@0 18875 '\u2F1D': '\u53E3',
michael@0 18876 '\u2F1E': '\u56D7',
michael@0 18877 '\u2F1F': '\u571F',
michael@0 18878 '\u2F20': '\u58EB',
michael@0 18879 '\u2F21': '\u5902',
michael@0 18880 '\u2F22': '\u590A',
michael@0 18881 '\u2F23': '\u5915',
michael@0 18882 '\u2F24': '\u5927',
michael@0 18883 '\u2F25': '\u5973',
michael@0 18884 '\u2F26': '\u5B50',
michael@0 18885 '\u2F27': '\u5B80',
michael@0 18886 '\u2F28': '\u5BF8',
michael@0 18887 '\u2F29': '\u5C0F',
michael@0 18888 '\u2F2A': '\u5C22',
michael@0 18889 '\u2F2B': '\u5C38',
michael@0 18890 '\u2F2C': '\u5C6E',
michael@0 18891 '\u2F2D': '\u5C71',
michael@0 18892 '\u2F2E': '\u5DDB',
michael@0 18893 '\u2F2F': '\u5DE5',
michael@0 18894 '\u2F30': '\u5DF1',
michael@0 18895 '\u2F31': '\u5DFE',
michael@0 18896 '\u2F32': '\u5E72',
michael@0 18897 '\u2F33': '\u5E7A',
michael@0 18898 '\u2F34': '\u5E7F',
michael@0 18899 '\u2F35': '\u5EF4',
michael@0 18900 '\u2F36': '\u5EFE',
michael@0 18901 '\u2F37': '\u5F0B',
michael@0 18902 '\u2F38': '\u5F13',
michael@0 18903 '\u2F39': '\u5F50',
michael@0 18904 '\u2F3A': '\u5F61',
michael@0 18905 '\u2F3B': '\u5F73',
michael@0 18906 '\u2F3C': '\u5FC3',
michael@0 18907 '\u2F3D': '\u6208',
michael@0 18908 '\u2F3E': '\u6236',
michael@0 18909 '\u2F3F': '\u624B',
michael@0 18910 '\u2F40': '\u652F',
michael@0 18911 '\u2F41': '\u6534',
michael@0 18912 '\u2F42': '\u6587',
michael@0 18913 '\u2F43': '\u6597',
michael@0 18914 '\u2F44': '\u65A4',
michael@0 18915 '\u2F45': '\u65B9',
michael@0 18916 '\u2F46': '\u65E0',
michael@0 18917 '\u2F47': '\u65E5',
michael@0 18918 '\u2F48': '\u66F0',
michael@0 18919 '\u2F49': '\u6708',
michael@0 18920 '\u2F4A': '\u6728',
michael@0 18921 '\u2F4B': '\u6B20',
michael@0 18922 '\u2F4C': '\u6B62',
michael@0 18923 '\u2F4D': '\u6B79',
michael@0 18924 '\u2F4E': '\u6BB3',
michael@0 18925 '\u2F4F': '\u6BCB',
michael@0 18926 '\u2F50': '\u6BD4',
michael@0 18927 '\u2F51': '\u6BDB',
michael@0 18928 '\u2F52': '\u6C0F',
michael@0 18929 '\u2F53': '\u6C14',
michael@0 18930 '\u2F54': '\u6C34',
michael@0 18931 '\u2F55': '\u706B',
michael@0 18932 '\u2F56': '\u722A',
michael@0 18933 '\u2F57': '\u7236',
michael@0 18934 '\u2F58': '\u723B',
michael@0 18935 '\u2F59': '\u723F',
michael@0 18936 '\u2F5A': '\u7247',
michael@0 18937 '\u2F5B': '\u7259',
michael@0 18938 '\u2F5C': '\u725B',
michael@0 18939 '\u2F5D': '\u72AC',
michael@0 18940 '\u2F5E': '\u7384',
michael@0 18941 '\u2F5F': '\u7389',
michael@0 18942 '\u2F60': '\u74DC',
michael@0 18943 '\u2F61': '\u74E6',
michael@0 18944 '\u2F62': '\u7518',
michael@0 18945 '\u2F63': '\u751F',
michael@0 18946 '\u2F64': '\u7528',
michael@0 18947 '\u2F65': '\u7530',
michael@0 18948 '\u2F66': '\u758B',
michael@0 18949 '\u2F67': '\u7592',
michael@0 18950 '\u2F68': '\u7676',
michael@0 18951 '\u2F69': '\u767D',
michael@0 18952 '\u2F6A': '\u76AE',
michael@0 18953 '\u2F6B': '\u76BF',
michael@0 18954 '\u2F6C': '\u76EE',
michael@0 18955 '\u2F6D': '\u77DB',
michael@0 18956 '\u2F6E': '\u77E2',
michael@0 18957 '\u2F6F': '\u77F3',
michael@0 18958 '\u2F70': '\u793A',
michael@0 18959 '\u2F71': '\u79B8',
michael@0 18960 '\u2F72': '\u79BE',
michael@0 18961 '\u2F73': '\u7A74',
michael@0 18962 '\u2F74': '\u7ACB',
michael@0 18963 '\u2F75': '\u7AF9',
michael@0 18964 '\u2F76': '\u7C73',
michael@0 18965 '\u2F77': '\u7CF8',
michael@0 18966 '\u2F78': '\u7F36',
michael@0 18967 '\u2F79': '\u7F51',
michael@0 18968 '\u2F7A': '\u7F8A',
michael@0 18969 '\u2F7B': '\u7FBD',
michael@0 18970 '\u2F7C': '\u8001',
michael@0 18971 '\u2F7D': '\u800C',
michael@0 18972 '\u2F7E': '\u8012',
michael@0 18973 '\u2F7F': '\u8033',
michael@0 18974 '\u2F80': '\u807F',
michael@0 18975 '\u2F81': '\u8089',
michael@0 18976 '\u2F82': '\u81E3',
michael@0 18977 '\u2F83': '\u81EA',
michael@0 18978 '\u2F84': '\u81F3',
michael@0 18979 '\u2F85': '\u81FC',
michael@0 18980 '\u2F86': '\u820C',
michael@0 18981 '\u2F87': '\u821B',
michael@0 18982 '\u2F88': '\u821F',
michael@0 18983 '\u2F89': '\u826E',
michael@0 18984 '\u2F8A': '\u8272',
michael@0 18985 '\u2F8B': '\u8278',
michael@0 18986 '\u2F8C': '\u864D',
michael@0 18987 '\u2F8D': '\u866B',
michael@0 18988 '\u2F8E': '\u8840',
michael@0 18989 '\u2F8F': '\u884C',
michael@0 18990 '\u2F90': '\u8863',
michael@0 18991 '\u2F91': '\u897E',
michael@0 18992 '\u2F92': '\u898B',
michael@0 18993 '\u2F93': '\u89D2',
michael@0 18994 '\u2F94': '\u8A00',
michael@0 18995 '\u2F95': '\u8C37',
michael@0 18996 '\u2F96': '\u8C46',
michael@0 18997 '\u2F97': '\u8C55',
michael@0 18998 '\u2F98': '\u8C78',
michael@0 18999 '\u2F99': '\u8C9D',
michael@0 19000 '\u2F9A': '\u8D64',
michael@0 19001 '\u2F9B': '\u8D70',
michael@0 19002 '\u2F9C': '\u8DB3',
michael@0 19003 '\u2F9D': '\u8EAB',
michael@0 19004 '\u2F9E': '\u8ECA',
michael@0 19005 '\u2F9F': '\u8F9B',
michael@0 19006 '\u2FA0': '\u8FB0',
michael@0 19007 '\u2FA1': '\u8FB5',
michael@0 19008 '\u2FA2': '\u9091',
michael@0 19009 '\u2FA3': '\u9149',
michael@0 19010 '\u2FA4': '\u91C6',
michael@0 19011 '\u2FA5': '\u91CC',
michael@0 19012 '\u2FA6': '\u91D1',
michael@0 19013 '\u2FA7': '\u9577',
michael@0 19014 '\u2FA8': '\u9580',
michael@0 19015 '\u2FA9': '\u961C',
michael@0 19016 '\u2FAA': '\u96B6',
michael@0 19017 '\u2FAB': '\u96B9',
michael@0 19018 '\u2FAC': '\u96E8',
michael@0 19019 '\u2FAD': '\u9751',
michael@0 19020 '\u2FAE': '\u975E',
michael@0 19021 '\u2FAF': '\u9762',
michael@0 19022 '\u2FB0': '\u9769',
michael@0 19023 '\u2FB1': '\u97CB',
michael@0 19024 '\u2FB2': '\u97ED',
michael@0 19025 '\u2FB3': '\u97F3',
michael@0 19026 '\u2FB4': '\u9801',
michael@0 19027 '\u2FB5': '\u98A8',
michael@0 19028 '\u2FB6': '\u98DB',
michael@0 19029 '\u2FB7': '\u98DF',
michael@0 19030 '\u2FB8': '\u9996',
michael@0 19031 '\u2FB9': '\u9999',
michael@0 19032 '\u2FBA': '\u99AC',
michael@0 19033 '\u2FBB': '\u9AA8',
michael@0 19034 '\u2FBC': '\u9AD8',
michael@0 19035 '\u2FBD': '\u9ADF',
michael@0 19036 '\u2FBE': '\u9B25',
michael@0 19037 '\u2FBF': '\u9B2F',
michael@0 19038 '\u2FC0': '\u9B32',
michael@0 19039 '\u2FC1': '\u9B3C',
michael@0 19040 '\u2FC2': '\u9B5A',
michael@0 19041 '\u2FC3': '\u9CE5',
michael@0 19042 '\u2FC4': '\u9E75',
michael@0 19043 '\u2FC5': '\u9E7F',
michael@0 19044 '\u2FC6': '\u9EA5',
michael@0 19045 '\u2FC7': '\u9EBB',
michael@0 19046 '\u2FC8': '\u9EC3',
michael@0 19047 '\u2FC9': '\u9ECD',
michael@0 19048 '\u2FCA': '\u9ED1',
michael@0 19049 '\u2FCB': '\u9EF9',
michael@0 19050 '\u2FCC': '\u9EFD',
michael@0 19051 '\u2FCD': '\u9F0E',
michael@0 19052 '\u2FCE': '\u9F13',
michael@0 19053 '\u2FCF': '\u9F20',
michael@0 19054 '\u2FD0': '\u9F3B',
michael@0 19055 '\u2FD1': '\u9F4A',
michael@0 19056 '\u2FD2': '\u9F52',
michael@0 19057 '\u2FD3': '\u9F8D',
michael@0 19058 '\u2FD4': '\u9F9C',
michael@0 19059 '\u2FD5': '\u9FA0',
michael@0 19060 '\u3036': '\u3012',
michael@0 19061 '\u3038': '\u5341',
michael@0 19062 '\u3039': '\u5344',
michael@0 19063 '\u303A': '\u5345',
michael@0 19064 '\u309B': '\u0020\u3099',
michael@0 19065 '\u309C': '\u0020\u309A',
michael@0 19066 '\u3131': '\u1100',
michael@0 19067 '\u3132': '\u1101',
michael@0 19068 '\u3133': '\u11AA',
michael@0 19069 '\u3134': '\u1102',
michael@0 19070 '\u3135': '\u11AC',
michael@0 19071 '\u3136': '\u11AD',
michael@0 19072 '\u3137': '\u1103',
michael@0 19073 '\u3138': '\u1104',
michael@0 19074 '\u3139': '\u1105',
michael@0 19075 '\u313A': '\u11B0',
michael@0 19076 '\u313B': '\u11B1',
michael@0 19077 '\u313C': '\u11B2',
michael@0 19078 '\u313D': '\u11B3',
michael@0 19079 '\u313E': '\u11B4',
michael@0 19080 '\u313F': '\u11B5',
michael@0 19081 '\u3140': '\u111A',
michael@0 19082 '\u3141': '\u1106',
michael@0 19083 '\u3142': '\u1107',
michael@0 19084 '\u3143': '\u1108',
michael@0 19085 '\u3144': '\u1121',
michael@0 19086 '\u3145': '\u1109',
michael@0 19087 '\u3146': '\u110A',
michael@0 19088 '\u3147': '\u110B',
michael@0 19089 '\u3148': '\u110C',
michael@0 19090 '\u3149': '\u110D',
michael@0 19091 '\u314A': '\u110E',
michael@0 19092 '\u314B': '\u110F',
michael@0 19093 '\u314C': '\u1110',
michael@0 19094 '\u314D': '\u1111',
michael@0 19095 '\u314E': '\u1112',
michael@0 19096 '\u314F': '\u1161',
michael@0 19097 '\u3150': '\u1162',
michael@0 19098 '\u3151': '\u1163',
michael@0 19099 '\u3152': '\u1164',
michael@0 19100 '\u3153': '\u1165',
michael@0 19101 '\u3154': '\u1166',
michael@0 19102 '\u3155': '\u1167',
michael@0 19103 '\u3156': '\u1168',
michael@0 19104 '\u3157': '\u1169',
michael@0 19105 '\u3158': '\u116A',
michael@0 19106 '\u3159': '\u116B',
michael@0 19107 '\u315A': '\u116C',
michael@0 19108 '\u315B': '\u116D',
michael@0 19109 '\u315C': '\u116E',
michael@0 19110 '\u315D': '\u116F',
michael@0 19111 '\u315E': '\u1170',
michael@0 19112 '\u315F': '\u1171',
michael@0 19113 '\u3160': '\u1172',
michael@0 19114 '\u3161': '\u1173',
michael@0 19115 '\u3162': '\u1174',
michael@0 19116 '\u3163': '\u1175',
michael@0 19117 '\u3164': '\u1160',
michael@0 19118 '\u3165': '\u1114',
michael@0 19119 '\u3166': '\u1115',
michael@0 19120 '\u3167': '\u11C7',
michael@0 19121 '\u3168': '\u11C8',
michael@0 19122 '\u3169': '\u11CC',
michael@0 19123 '\u316A': '\u11CE',
michael@0 19124 '\u316B': '\u11D3',
michael@0 19125 '\u316C': '\u11D7',
michael@0 19126 '\u316D': '\u11D9',
michael@0 19127 '\u316E': '\u111C',
michael@0 19128 '\u316F': '\u11DD',
michael@0 19129 '\u3170': '\u11DF',
michael@0 19130 '\u3171': '\u111D',
michael@0 19131 '\u3172': '\u111E',
michael@0 19132 '\u3173': '\u1120',
michael@0 19133 '\u3174': '\u1122',
michael@0 19134 '\u3175': '\u1123',
michael@0 19135 '\u3176': '\u1127',
michael@0 19136 '\u3177': '\u1129',
michael@0 19137 '\u3178': '\u112B',
michael@0 19138 '\u3179': '\u112C',
michael@0 19139 '\u317A': '\u112D',
michael@0 19140 '\u317B': '\u112E',
michael@0 19141 '\u317C': '\u112F',
michael@0 19142 '\u317D': '\u1132',
michael@0 19143 '\u317E': '\u1136',
michael@0 19144 '\u317F': '\u1140',
michael@0 19145 '\u3180': '\u1147',
michael@0 19146 '\u3181': '\u114C',
michael@0 19147 '\u3182': '\u11F1',
michael@0 19148 '\u3183': '\u11F2',
michael@0 19149 '\u3184': '\u1157',
michael@0 19150 '\u3185': '\u1158',
michael@0 19151 '\u3186': '\u1159',
michael@0 19152 '\u3187': '\u1184',
michael@0 19153 '\u3188': '\u1185',
michael@0 19154 '\u3189': '\u1188',
michael@0 19155 '\u318A': '\u1191',
michael@0 19156 '\u318B': '\u1192',
michael@0 19157 '\u318C': '\u1194',
michael@0 19158 '\u318D': '\u119E',
michael@0 19159 '\u318E': '\u11A1',
michael@0 19160 '\u3200': '\u0028\u1100\u0029',
michael@0 19161 '\u3201': '\u0028\u1102\u0029',
michael@0 19162 '\u3202': '\u0028\u1103\u0029',
michael@0 19163 '\u3203': '\u0028\u1105\u0029',
michael@0 19164 '\u3204': '\u0028\u1106\u0029',
michael@0 19165 '\u3205': '\u0028\u1107\u0029',
michael@0 19166 '\u3206': '\u0028\u1109\u0029',
michael@0 19167 '\u3207': '\u0028\u110B\u0029',
michael@0 19168 '\u3208': '\u0028\u110C\u0029',
michael@0 19169 '\u3209': '\u0028\u110E\u0029',
michael@0 19170 '\u320A': '\u0028\u110F\u0029',
michael@0 19171 '\u320B': '\u0028\u1110\u0029',
michael@0 19172 '\u320C': '\u0028\u1111\u0029',
michael@0 19173 '\u320D': '\u0028\u1112\u0029',
michael@0 19174 '\u320E': '\u0028\u1100\u1161\u0029',
michael@0 19175 '\u320F': '\u0028\u1102\u1161\u0029',
michael@0 19176 '\u3210': '\u0028\u1103\u1161\u0029',
michael@0 19177 '\u3211': '\u0028\u1105\u1161\u0029',
michael@0 19178 '\u3212': '\u0028\u1106\u1161\u0029',
michael@0 19179 '\u3213': '\u0028\u1107\u1161\u0029',
michael@0 19180 '\u3214': '\u0028\u1109\u1161\u0029',
michael@0 19181 '\u3215': '\u0028\u110B\u1161\u0029',
michael@0 19182 '\u3216': '\u0028\u110C\u1161\u0029',
michael@0 19183 '\u3217': '\u0028\u110E\u1161\u0029',
michael@0 19184 '\u3218': '\u0028\u110F\u1161\u0029',
michael@0 19185 '\u3219': '\u0028\u1110\u1161\u0029',
michael@0 19186 '\u321A': '\u0028\u1111\u1161\u0029',
michael@0 19187 '\u321B': '\u0028\u1112\u1161\u0029',
michael@0 19188 '\u321C': '\u0028\u110C\u116E\u0029',
michael@0 19189 '\u321D': '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029',
michael@0 19190 '\u321E': '\u0028\u110B\u1169\u1112\u116E\u0029',
michael@0 19191 '\u3220': '\u0028\u4E00\u0029',
michael@0 19192 '\u3221': '\u0028\u4E8C\u0029',
michael@0 19193 '\u3222': '\u0028\u4E09\u0029',
michael@0 19194 '\u3223': '\u0028\u56DB\u0029',
michael@0 19195 '\u3224': '\u0028\u4E94\u0029',
michael@0 19196 '\u3225': '\u0028\u516D\u0029',
michael@0 19197 '\u3226': '\u0028\u4E03\u0029',
michael@0 19198 '\u3227': '\u0028\u516B\u0029',
michael@0 19199 '\u3228': '\u0028\u4E5D\u0029',
michael@0 19200 '\u3229': '\u0028\u5341\u0029',
michael@0 19201 '\u322A': '\u0028\u6708\u0029',
michael@0 19202 '\u322B': '\u0028\u706B\u0029',
michael@0 19203 '\u322C': '\u0028\u6C34\u0029',
michael@0 19204 '\u322D': '\u0028\u6728\u0029',
michael@0 19205 '\u322E': '\u0028\u91D1\u0029',
michael@0 19206 '\u322F': '\u0028\u571F\u0029',
michael@0 19207 '\u3230': '\u0028\u65E5\u0029',
michael@0 19208 '\u3231': '\u0028\u682A\u0029',
michael@0 19209 '\u3232': '\u0028\u6709\u0029',
michael@0 19210 '\u3233': '\u0028\u793E\u0029',
michael@0 19211 '\u3234': '\u0028\u540D\u0029',
michael@0 19212 '\u3235': '\u0028\u7279\u0029',
michael@0 19213 '\u3236': '\u0028\u8CA1\u0029',
michael@0 19214 '\u3237': '\u0028\u795D\u0029',
michael@0 19215 '\u3238': '\u0028\u52B4\u0029',
michael@0 19216 '\u3239': '\u0028\u4EE3\u0029',
michael@0 19217 '\u323A': '\u0028\u547C\u0029',
michael@0 19218 '\u323B': '\u0028\u5B66\u0029',
michael@0 19219 '\u323C': '\u0028\u76E3\u0029',
michael@0 19220 '\u323D': '\u0028\u4F01\u0029',
michael@0 19221 '\u323E': '\u0028\u8CC7\u0029',
michael@0 19222 '\u323F': '\u0028\u5354\u0029',
michael@0 19223 '\u3240': '\u0028\u796D\u0029',
michael@0 19224 '\u3241': '\u0028\u4F11\u0029',
michael@0 19225 '\u3242': '\u0028\u81EA\u0029',
michael@0 19226 '\u3243': '\u0028\u81F3\u0029',
michael@0 19227 '\u32C0': '\u0031\u6708',
michael@0 19228 '\u32C1': '\u0032\u6708',
michael@0 19229 '\u32C2': '\u0033\u6708',
michael@0 19230 '\u32C3': '\u0034\u6708',
michael@0 19231 '\u32C4': '\u0035\u6708',
michael@0 19232 '\u32C5': '\u0036\u6708',
michael@0 19233 '\u32C6': '\u0037\u6708',
michael@0 19234 '\u32C7': '\u0038\u6708',
michael@0 19235 '\u32C8': '\u0039\u6708',
michael@0 19236 '\u32C9': '\u0031\u0030\u6708',
michael@0 19237 '\u32CA': '\u0031\u0031\u6708',
michael@0 19238 '\u32CB': '\u0031\u0032\u6708',
michael@0 19239 '\u3358': '\u0030\u70B9',
michael@0 19240 '\u3359': '\u0031\u70B9',
michael@0 19241 '\u335A': '\u0032\u70B9',
michael@0 19242 '\u335B': '\u0033\u70B9',
michael@0 19243 '\u335C': '\u0034\u70B9',
michael@0 19244 '\u335D': '\u0035\u70B9',
michael@0 19245 '\u335E': '\u0036\u70B9',
michael@0 19246 '\u335F': '\u0037\u70B9',
michael@0 19247 '\u3360': '\u0038\u70B9',
michael@0 19248 '\u3361': '\u0039\u70B9',
michael@0 19249 '\u3362': '\u0031\u0030\u70B9',
michael@0 19250 '\u3363': '\u0031\u0031\u70B9',
michael@0 19251 '\u3364': '\u0031\u0032\u70B9',
michael@0 19252 '\u3365': '\u0031\u0033\u70B9',
michael@0 19253 '\u3366': '\u0031\u0034\u70B9',
michael@0 19254 '\u3367': '\u0031\u0035\u70B9',
michael@0 19255 '\u3368': '\u0031\u0036\u70B9',
michael@0 19256 '\u3369': '\u0031\u0037\u70B9',
michael@0 19257 '\u336A': '\u0031\u0038\u70B9',
michael@0 19258 '\u336B': '\u0031\u0039\u70B9',
michael@0 19259 '\u336C': '\u0032\u0030\u70B9',
michael@0 19260 '\u336D': '\u0032\u0031\u70B9',
michael@0 19261 '\u336E': '\u0032\u0032\u70B9',
michael@0 19262 '\u336F': '\u0032\u0033\u70B9',
michael@0 19263 '\u3370': '\u0032\u0034\u70B9',
michael@0 19264 '\u33E0': '\u0031\u65E5',
michael@0 19265 '\u33E1': '\u0032\u65E5',
michael@0 19266 '\u33E2': '\u0033\u65E5',
michael@0 19267 '\u33E3': '\u0034\u65E5',
michael@0 19268 '\u33E4': '\u0035\u65E5',
michael@0 19269 '\u33E5': '\u0036\u65E5',
michael@0 19270 '\u33E6': '\u0037\u65E5',
michael@0 19271 '\u33E7': '\u0038\u65E5',
michael@0 19272 '\u33E8': '\u0039\u65E5',
michael@0 19273 '\u33E9': '\u0031\u0030\u65E5',
michael@0 19274 '\u33EA': '\u0031\u0031\u65E5',
michael@0 19275 '\u33EB': '\u0031\u0032\u65E5',
michael@0 19276 '\u33EC': '\u0031\u0033\u65E5',
michael@0 19277 '\u33ED': '\u0031\u0034\u65E5',
michael@0 19278 '\u33EE': '\u0031\u0035\u65E5',
michael@0 19279 '\u33EF': '\u0031\u0036\u65E5',
michael@0 19280 '\u33F0': '\u0031\u0037\u65E5',
michael@0 19281 '\u33F1': '\u0031\u0038\u65E5',
michael@0 19282 '\u33F2': '\u0031\u0039\u65E5',
michael@0 19283 '\u33F3': '\u0032\u0030\u65E5',
michael@0 19284 '\u33F4': '\u0032\u0031\u65E5',
michael@0 19285 '\u33F5': '\u0032\u0032\u65E5',
michael@0 19286 '\u33F6': '\u0032\u0033\u65E5',
michael@0 19287 '\u33F7': '\u0032\u0034\u65E5',
michael@0 19288 '\u33F8': '\u0032\u0035\u65E5',
michael@0 19289 '\u33F9': '\u0032\u0036\u65E5',
michael@0 19290 '\u33FA': '\u0032\u0037\u65E5',
michael@0 19291 '\u33FB': '\u0032\u0038\u65E5',
michael@0 19292 '\u33FC': '\u0032\u0039\u65E5',
michael@0 19293 '\u33FD': '\u0033\u0030\u65E5',
michael@0 19294 '\u33FE': '\u0033\u0031\u65E5',
michael@0 19295 '\uFB00': '\u0066\u0066',
michael@0 19296 '\uFB01': '\u0066\u0069',
michael@0 19297 '\uFB02': '\u0066\u006C',
michael@0 19298 '\uFB03': '\u0066\u0066\u0069',
michael@0 19299 '\uFB04': '\u0066\u0066\u006C',
michael@0 19300 '\uFB05': '\u017F\u0074',
michael@0 19301 '\uFB06': '\u0073\u0074',
michael@0 19302 '\uFB13': '\u0574\u0576',
michael@0 19303 '\uFB14': '\u0574\u0565',
michael@0 19304 '\uFB15': '\u0574\u056B',
michael@0 19305 '\uFB16': '\u057E\u0576',
michael@0 19306 '\uFB17': '\u0574\u056D',
michael@0 19307 '\uFB4F': '\u05D0\u05DC',
michael@0 19308 '\uFB50': '\u0671',
michael@0 19309 '\uFB51': '\u0671',
michael@0 19310 '\uFB52': '\u067B',
michael@0 19311 '\uFB53': '\u067B',
michael@0 19312 '\uFB54': '\u067B',
michael@0 19313 '\uFB55': '\u067B',
michael@0 19314 '\uFB56': '\u067E',
michael@0 19315 '\uFB57': '\u067E',
michael@0 19316 '\uFB58': '\u067E',
michael@0 19317 '\uFB59': '\u067E',
michael@0 19318 '\uFB5A': '\u0680',
michael@0 19319 '\uFB5B': '\u0680',
michael@0 19320 '\uFB5C': '\u0680',
michael@0 19321 '\uFB5D': '\u0680',
michael@0 19322 '\uFB5E': '\u067A',
michael@0 19323 '\uFB5F': '\u067A',
michael@0 19324 '\uFB60': '\u067A',
michael@0 19325 '\uFB61': '\u067A',
michael@0 19326 '\uFB62': '\u067F',
michael@0 19327 '\uFB63': '\u067F',
michael@0 19328 '\uFB64': '\u067F',
michael@0 19329 '\uFB65': '\u067F',
michael@0 19330 '\uFB66': '\u0679',
michael@0 19331 '\uFB67': '\u0679',
michael@0 19332 '\uFB68': '\u0679',
michael@0 19333 '\uFB69': '\u0679',
michael@0 19334 '\uFB6A': '\u06A4',
michael@0 19335 '\uFB6B': '\u06A4',
michael@0 19336 '\uFB6C': '\u06A4',
michael@0 19337 '\uFB6D': '\u06A4',
michael@0 19338 '\uFB6E': '\u06A6',
michael@0 19339 '\uFB6F': '\u06A6',
michael@0 19340 '\uFB70': '\u06A6',
michael@0 19341 '\uFB71': '\u06A6',
michael@0 19342 '\uFB72': '\u0684',
michael@0 19343 '\uFB73': '\u0684',
michael@0 19344 '\uFB74': '\u0684',
michael@0 19345 '\uFB75': '\u0684',
michael@0 19346 '\uFB76': '\u0683',
michael@0 19347 '\uFB77': '\u0683',
michael@0 19348 '\uFB78': '\u0683',
michael@0 19349 '\uFB79': '\u0683',
michael@0 19350 '\uFB7A': '\u0686',
michael@0 19351 '\uFB7B': '\u0686',
michael@0 19352 '\uFB7C': '\u0686',
michael@0 19353 '\uFB7D': '\u0686',
michael@0 19354 '\uFB7E': '\u0687',
michael@0 19355 '\uFB7F': '\u0687',
michael@0 19356 '\uFB80': '\u0687',
michael@0 19357 '\uFB81': '\u0687',
michael@0 19358 '\uFB82': '\u068D',
michael@0 19359 '\uFB83': '\u068D',
michael@0 19360 '\uFB84': '\u068C',
michael@0 19361 '\uFB85': '\u068C',
michael@0 19362 '\uFB86': '\u068E',
michael@0 19363 '\uFB87': '\u068E',
michael@0 19364 '\uFB88': '\u0688',
michael@0 19365 '\uFB89': '\u0688',
michael@0 19366 '\uFB8A': '\u0698',
michael@0 19367 '\uFB8B': '\u0698',
michael@0 19368 '\uFB8C': '\u0691',
michael@0 19369 '\uFB8D': '\u0691',
michael@0 19370 '\uFB8E': '\u06A9',
michael@0 19371 '\uFB8F': '\u06A9',
michael@0 19372 '\uFB90': '\u06A9',
michael@0 19373 '\uFB91': '\u06A9',
michael@0 19374 '\uFB92': '\u06AF',
michael@0 19375 '\uFB93': '\u06AF',
michael@0 19376 '\uFB94': '\u06AF',
michael@0 19377 '\uFB95': '\u06AF',
michael@0 19378 '\uFB96': '\u06B3',
michael@0 19379 '\uFB97': '\u06B3',
michael@0 19380 '\uFB98': '\u06B3',
michael@0 19381 '\uFB99': '\u06B3',
michael@0 19382 '\uFB9A': '\u06B1',
michael@0 19383 '\uFB9B': '\u06B1',
michael@0 19384 '\uFB9C': '\u06B1',
michael@0 19385 '\uFB9D': '\u06B1',
michael@0 19386 '\uFB9E': '\u06BA',
michael@0 19387 '\uFB9F': '\u06BA',
michael@0 19388 '\uFBA0': '\u06BB',
michael@0 19389 '\uFBA1': '\u06BB',
michael@0 19390 '\uFBA2': '\u06BB',
michael@0 19391 '\uFBA3': '\u06BB',
michael@0 19392 '\uFBA4': '\u06C0',
michael@0 19393 '\uFBA5': '\u06C0',
michael@0 19394 '\uFBA6': '\u06C1',
michael@0 19395 '\uFBA7': '\u06C1',
michael@0 19396 '\uFBA8': '\u06C1',
michael@0 19397 '\uFBA9': '\u06C1',
michael@0 19398 '\uFBAA': '\u06BE',
michael@0 19399 '\uFBAB': '\u06BE',
michael@0 19400 '\uFBAC': '\u06BE',
michael@0 19401 '\uFBAD': '\u06BE',
michael@0 19402 '\uFBAE': '\u06D2',
michael@0 19403 '\uFBAF': '\u06D2',
michael@0 19404 '\uFBB0': '\u06D3',
michael@0 19405 '\uFBB1': '\u06D3',
michael@0 19406 '\uFBD3': '\u06AD',
michael@0 19407 '\uFBD4': '\u06AD',
michael@0 19408 '\uFBD5': '\u06AD',
michael@0 19409 '\uFBD6': '\u06AD',
michael@0 19410 '\uFBD7': '\u06C7',
michael@0 19411 '\uFBD8': '\u06C7',
michael@0 19412 '\uFBD9': '\u06C6',
michael@0 19413 '\uFBDA': '\u06C6',
michael@0 19414 '\uFBDB': '\u06C8',
michael@0 19415 '\uFBDC': '\u06C8',
michael@0 19416 '\uFBDD': '\u0677',
michael@0 19417 '\uFBDE': '\u06CB',
michael@0 19418 '\uFBDF': '\u06CB',
michael@0 19419 '\uFBE0': '\u06C5',
michael@0 19420 '\uFBE1': '\u06C5',
michael@0 19421 '\uFBE2': '\u06C9',
michael@0 19422 '\uFBE3': '\u06C9',
michael@0 19423 '\uFBE4': '\u06D0',
michael@0 19424 '\uFBE5': '\u06D0',
michael@0 19425 '\uFBE6': '\u06D0',
michael@0 19426 '\uFBE7': '\u06D0',
michael@0 19427 '\uFBE8': '\u0649',
michael@0 19428 '\uFBE9': '\u0649',
michael@0 19429 '\uFBEA': '\u0626\u0627',
michael@0 19430 '\uFBEB': '\u0626\u0627',
michael@0 19431 '\uFBEC': '\u0626\u06D5',
michael@0 19432 '\uFBED': '\u0626\u06D5',
michael@0 19433 '\uFBEE': '\u0626\u0648',
michael@0 19434 '\uFBEF': '\u0626\u0648',
michael@0 19435 '\uFBF0': '\u0626\u06C7',
michael@0 19436 '\uFBF1': '\u0626\u06C7',
michael@0 19437 '\uFBF2': '\u0626\u06C6',
michael@0 19438 '\uFBF3': '\u0626\u06C6',
michael@0 19439 '\uFBF4': '\u0626\u06C8',
michael@0 19440 '\uFBF5': '\u0626\u06C8',
michael@0 19441 '\uFBF6': '\u0626\u06D0',
michael@0 19442 '\uFBF7': '\u0626\u06D0',
michael@0 19443 '\uFBF8': '\u0626\u06D0',
michael@0 19444 '\uFBF9': '\u0626\u0649',
michael@0 19445 '\uFBFA': '\u0626\u0649',
michael@0 19446 '\uFBFB': '\u0626\u0649',
michael@0 19447 '\uFBFC': '\u06CC',
michael@0 19448 '\uFBFD': '\u06CC',
michael@0 19449 '\uFBFE': '\u06CC',
michael@0 19450 '\uFBFF': '\u06CC',
michael@0 19451 '\uFC00': '\u0626\u062C',
michael@0 19452 '\uFC01': '\u0626\u062D',
michael@0 19453 '\uFC02': '\u0626\u0645',
michael@0 19454 '\uFC03': '\u0626\u0649',
michael@0 19455 '\uFC04': '\u0626\u064A',
michael@0 19456 '\uFC05': '\u0628\u062C',
michael@0 19457 '\uFC06': '\u0628\u062D',
michael@0 19458 '\uFC07': '\u0628\u062E',
michael@0 19459 '\uFC08': '\u0628\u0645',
michael@0 19460 '\uFC09': '\u0628\u0649',
michael@0 19461 '\uFC0A': '\u0628\u064A',
michael@0 19462 '\uFC0B': '\u062A\u062C',
michael@0 19463 '\uFC0C': '\u062A\u062D',
michael@0 19464 '\uFC0D': '\u062A\u062E',
michael@0 19465 '\uFC0E': '\u062A\u0645',
michael@0 19466 '\uFC0F': '\u062A\u0649',
michael@0 19467 '\uFC10': '\u062A\u064A',
michael@0 19468 '\uFC11': '\u062B\u062C',
michael@0 19469 '\uFC12': '\u062B\u0645',
michael@0 19470 '\uFC13': '\u062B\u0649',
michael@0 19471 '\uFC14': '\u062B\u064A',
michael@0 19472 '\uFC15': '\u062C\u062D',
michael@0 19473 '\uFC16': '\u062C\u0645',
michael@0 19474 '\uFC17': '\u062D\u062C',
michael@0 19475 '\uFC18': '\u062D\u0645',
michael@0 19476 '\uFC19': '\u062E\u062C',
michael@0 19477 '\uFC1A': '\u062E\u062D',
michael@0 19478 '\uFC1B': '\u062E\u0645',
michael@0 19479 '\uFC1C': '\u0633\u062C',
michael@0 19480 '\uFC1D': '\u0633\u062D',
michael@0 19481 '\uFC1E': '\u0633\u062E',
michael@0 19482 '\uFC1F': '\u0633\u0645',
michael@0 19483 '\uFC20': '\u0635\u062D',
michael@0 19484 '\uFC21': '\u0635\u0645',
michael@0 19485 '\uFC22': '\u0636\u062C',
michael@0 19486 '\uFC23': '\u0636\u062D',
michael@0 19487 '\uFC24': '\u0636\u062E',
michael@0 19488 '\uFC25': '\u0636\u0645',
michael@0 19489 '\uFC26': '\u0637\u062D',
michael@0 19490 '\uFC27': '\u0637\u0645',
michael@0 19491 '\uFC28': '\u0638\u0645',
michael@0 19492 '\uFC29': '\u0639\u062C',
michael@0 19493 '\uFC2A': '\u0639\u0645',
michael@0 19494 '\uFC2B': '\u063A\u062C',
michael@0 19495 '\uFC2C': '\u063A\u0645',
michael@0 19496 '\uFC2D': '\u0641\u062C',
michael@0 19497 '\uFC2E': '\u0641\u062D',
michael@0 19498 '\uFC2F': '\u0641\u062E',
michael@0 19499 '\uFC30': '\u0641\u0645',
michael@0 19500 '\uFC31': '\u0641\u0649',
michael@0 19501 '\uFC32': '\u0641\u064A',
michael@0 19502 '\uFC33': '\u0642\u062D',
michael@0 19503 '\uFC34': '\u0642\u0645',
michael@0 19504 '\uFC35': '\u0642\u0649',
michael@0 19505 '\uFC36': '\u0642\u064A',
michael@0 19506 '\uFC37': '\u0643\u0627',
michael@0 19507 '\uFC38': '\u0643\u062C',
michael@0 19508 '\uFC39': '\u0643\u062D',
michael@0 19509 '\uFC3A': '\u0643\u062E',
michael@0 19510 '\uFC3B': '\u0643\u0644',
michael@0 19511 '\uFC3C': '\u0643\u0645',
michael@0 19512 '\uFC3D': '\u0643\u0649',
michael@0 19513 '\uFC3E': '\u0643\u064A',
michael@0 19514 '\uFC3F': '\u0644\u062C',
michael@0 19515 '\uFC40': '\u0644\u062D',
michael@0 19516 '\uFC41': '\u0644\u062E',
michael@0 19517 '\uFC42': '\u0644\u0645',
michael@0 19518 '\uFC43': '\u0644\u0649',
michael@0 19519 '\uFC44': '\u0644\u064A',
michael@0 19520 '\uFC45': '\u0645\u062C',
michael@0 19521 '\uFC46': '\u0645\u062D',
michael@0 19522 '\uFC47': '\u0645\u062E',
michael@0 19523 '\uFC48': '\u0645\u0645',
michael@0 19524 '\uFC49': '\u0645\u0649',
michael@0 19525 '\uFC4A': '\u0645\u064A',
michael@0 19526 '\uFC4B': '\u0646\u062C',
michael@0 19527 '\uFC4C': '\u0646\u062D',
michael@0 19528 '\uFC4D': '\u0646\u062E',
michael@0 19529 '\uFC4E': '\u0646\u0645',
michael@0 19530 '\uFC4F': '\u0646\u0649',
michael@0 19531 '\uFC50': '\u0646\u064A',
michael@0 19532 '\uFC51': '\u0647\u062C',
michael@0 19533 '\uFC52': '\u0647\u0645',
michael@0 19534 '\uFC53': '\u0647\u0649',
michael@0 19535 '\uFC54': '\u0647\u064A',
michael@0 19536 '\uFC55': '\u064A\u062C',
michael@0 19537 '\uFC56': '\u064A\u062D',
michael@0 19538 '\uFC57': '\u064A\u062E',
michael@0 19539 '\uFC58': '\u064A\u0645',
michael@0 19540 '\uFC59': '\u064A\u0649',
michael@0 19541 '\uFC5A': '\u064A\u064A',
michael@0 19542 '\uFC5B': '\u0630\u0670',
michael@0 19543 '\uFC5C': '\u0631\u0670',
michael@0 19544 '\uFC5D': '\u0649\u0670',
michael@0 19545 '\uFC5E': '\u0020\u064C\u0651',
michael@0 19546 '\uFC5F': '\u0020\u064D\u0651',
michael@0 19547 '\uFC60': '\u0020\u064E\u0651',
michael@0 19548 '\uFC61': '\u0020\u064F\u0651',
michael@0 19549 '\uFC62': '\u0020\u0650\u0651',
michael@0 19550 '\uFC63': '\u0020\u0651\u0670',
michael@0 19551 '\uFC64': '\u0626\u0631',
michael@0 19552 '\uFC65': '\u0626\u0632',
michael@0 19553 '\uFC66': '\u0626\u0645',
michael@0 19554 '\uFC67': '\u0626\u0646',
michael@0 19555 '\uFC68': '\u0626\u0649',
michael@0 19556 '\uFC69': '\u0626\u064A',
michael@0 19557 '\uFC6A': '\u0628\u0631',
michael@0 19558 '\uFC6B': '\u0628\u0632',
michael@0 19559 '\uFC6C': '\u0628\u0645',
michael@0 19560 '\uFC6D': '\u0628\u0646',
michael@0 19561 '\uFC6E': '\u0628\u0649',
michael@0 19562 '\uFC6F': '\u0628\u064A',
michael@0 19563 '\uFC70': '\u062A\u0631',
michael@0 19564 '\uFC71': '\u062A\u0632',
michael@0 19565 '\uFC72': '\u062A\u0645',
michael@0 19566 '\uFC73': '\u062A\u0646',
michael@0 19567 '\uFC74': '\u062A\u0649',
michael@0 19568 '\uFC75': '\u062A\u064A',
michael@0 19569 '\uFC76': '\u062B\u0631',
michael@0 19570 '\uFC77': '\u062B\u0632',
michael@0 19571 '\uFC78': '\u062B\u0645',
michael@0 19572 '\uFC79': '\u062B\u0646',
michael@0 19573 '\uFC7A': '\u062B\u0649',
michael@0 19574 '\uFC7B': '\u062B\u064A',
michael@0 19575 '\uFC7C': '\u0641\u0649',
michael@0 19576 '\uFC7D': '\u0641\u064A',
michael@0 19577 '\uFC7E': '\u0642\u0649',
michael@0 19578 '\uFC7F': '\u0642\u064A',
michael@0 19579 '\uFC80': '\u0643\u0627',
michael@0 19580 '\uFC81': '\u0643\u0644',
michael@0 19581 '\uFC82': '\u0643\u0645',
michael@0 19582 '\uFC83': '\u0643\u0649',
michael@0 19583 '\uFC84': '\u0643\u064A',
michael@0 19584 '\uFC85': '\u0644\u0645',
michael@0 19585 '\uFC86': '\u0644\u0649',
michael@0 19586 '\uFC87': '\u0644\u064A',
michael@0 19587 '\uFC88': '\u0645\u0627',
michael@0 19588 '\uFC89': '\u0645\u0645',
michael@0 19589 '\uFC8A': '\u0646\u0631',
michael@0 19590 '\uFC8B': '\u0646\u0632',
michael@0 19591 '\uFC8C': '\u0646\u0645',
michael@0 19592 '\uFC8D': '\u0646\u0646',
michael@0 19593 '\uFC8E': '\u0646\u0649',
michael@0 19594 '\uFC8F': '\u0646\u064A',
michael@0 19595 '\uFC90': '\u0649\u0670',
michael@0 19596 '\uFC91': '\u064A\u0631',
michael@0 19597 '\uFC92': '\u064A\u0632',
michael@0 19598 '\uFC93': '\u064A\u0645',
michael@0 19599 '\uFC94': '\u064A\u0646',
michael@0 19600 '\uFC95': '\u064A\u0649',
michael@0 19601 '\uFC96': '\u064A\u064A',
michael@0 19602 '\uFC97': '\u0626\u062C',
michael@0 19603 '\uFC98': '\u0626\u062D',
michael@0 19604 '\uFC99': '\u0626\u062E',
michael@0 19605 '\uFC9A': '\u0626\u0645',
michael@0 19606 '\uFC9B': '\u0626\u0647',
michael@0 19607 '\uFC9C': '\u0628\u062C',
michael@0 19608 '\uFC9D': '\u0628\u062D',
michael@0 19609 '\uFC9E': '\u0628\u062E',
michael@0 19610 '\uFC9F': '\u0628\u0645',
michael@0 19611 '\uFCA0': '\u0628\u0647',
michael@0 19612 '\uFCA1': '\u062A\u062C',
michael@0 19613 '\uFCA2': '\u062A\u062D',
michael@0 19614 '\uFCA3': '\u062A\u062E',
michael@0 19615 '\uFCA4': '\u062A\u0645',
michael@0 19616 '\uFCA5': '\u062A\u0647',
michael@0 19617 '\uFCA6': '\u062B\u0645',
michael@0 19618 '\uFCA7': '\u062C\u062D',
michael@0 19619 '\uFCA8': '\u062C\u0645',
michael@0 19620 '\uFCA9': '\u062D\u062C',
michael@0 19621 '\uFCAA': '\u062D\u0645',
michael@0 19622 '\uFCAB': '\u062E\u062C',
michael@0 19623 '\uFCAC': '\u062E\u0645',
michael@0 19624 '\uFCAD': '\u0633\u062C',
michael@0 19625 '\uFCAE': '\u0633\u062D',
michael@0 19626 '\uFCAF': '\u0633\u062E',
michael@0 19627 '\uFCB0': '\u0633\u0645',
michael@0 19628 '\uFCB1': '\u0635\u062D',
michael@0 19629 '\uFCB2': '\u0635\u062E',
michael@0 19630 '\uFCB3': '\u0635\u0645',
michael@0 19631 '\uFCB4': '\u0636\u062C',
michael@0 19632 '\uFCB5': '\u0636\u062D',
michael@0 19633 '\uFCB6': '\u0636\u062E',
michael@0 19634 '\uFCB7': '\u0636\u0645',
michael@0 19635 '\uFCB8': '\u0637\u062D',
michael@0 19636 '\uFCB9': '\u0638\u0645',
michael@0 19637 '\uFCBA': '\u0639\u062C',
michael@0 19638 '\uFCBB': '\u0639\u0645',
michael@0 19639 '\uFCBC': '\u063A\u062C',
michael@0 19640 '\uFCBD': '\u063A\u0645',
michael@0 19641 '\uFCBE': '\u0641\u062C',
michael@0 19642 '\uFCBF': '\u0641\u062D',
michael@0 19643 '\uFCC0': '\u0641\u062E',
michael@0 19644 '\uFCC1': '\u0641\u0645',
michael@0 19645 '\uFCC2': '\u0642\u062D',
michael@0 19646 '\uFCC3': '\u0642\u0645',
michael@0 19647 '\uFCC4': '\u0643\u062C',
michael@0 19648 '\uFCC5': '\u0643\u062D',
michael@0 19649 '\uFCC6': '\u0643\u062E',
michael@0 19650 '\uFCC7': '\u0643\u0644',
michael@0 19651 '\uFCC8': '\u0643\u0645',
michael@0 19652 '\uFCC9': '\u0644\u062C',
michael@0 19653 '\uFCCA': '\u0644\u062D',
michael@0 19654 '\uFCCB': '\u0644\u062E',
michael@0 19655 '\uFCCC': '\u0644\u0645',
michael@0 19656 '\uFCCD': '\u0644\u0647',
michael@0 19657 '\uFCCE': '\u0645\u062C',
michael@0 19658 '\uFCCF': '\u0645\u062D',
michael@0 19659 '\uFCD0': '\u0645\u062E',
michael@0 19660 '\uFCD1': '\u0645\u0645',
michael@0 19661 '\uFCD2': '\u0646\u062C',
michael@0 19662 '\uFCD3': '\u0646\u062D',
michael@0 19663 '\uFCD4': '\u0646\u062E',
michael@0 19664 '\uFCD5': '\u0646\u0645',
michael@0 19665 '\uFCD6': '\u0646\u0647',
michael@0 19666 '\uFCD7': '\u0647\u062C',
michael@0 19667 '\uFCD8': '\u0647\u0645',
michael@0 19668 '\uFCD9': '\u0647\u0670',
michael@0 19669 '\uFCDA': '\u064A\u062C',
michael@0 19670 '\uFCDB': '\u064A\u062D',
michael@0 19671 '\uFCDC': '\u064A\u062E',
michael@0 19672 '\uFCDD': '\u064A\u0645',
michael@0 19673 '\uFCDE': '\u064A\u0647',
michael@0 19674 '\uFCDF': '\u0626\u0645',
michael@0 19675 '\uFCE0': '\u0626\u0647',
michael@0 19676 '\uFCE1': '\u0628\u0645',
michael@0 19677 '\uFCE2': '\u0628\u0647',
michael@0 19678 '\uFCE3': '\u062A\u0645',
michael@0 19679 '\uFCE4': '\u062A\u0647',
michael@0 19680 '\uFCE5': '\u062B\u0645',
michael@0 19681 '\uFCE6': '\u062B\u0647',
michael@0 19682 '\uFCE7': '\u0633\u0645',
michael@0 19683 '\uFCE8': '\u0633\u0647',
michael@0 19684 '\uFCE9': '\u0634\u0645',
michael@0 19685 '\uFCEA': '\u0634\u0647',
michael@0 19686 '\uFCEB': '\u0643\u0644',
michael@0 19687 '\uFCEC': '\u0643\u0645',
michael@0 19688 '\uFCED': '\u0644\u0645',
michael@0 19689 '\uFCEE': '\u0646\u0645',
michael@0 19690 '\uFCEF': '\u0646\u0647',
michael@0 19691 '\uFCF0': '\u064A\u0645',
michael@0 19692 '\uFCF1': '\u064A\u0647',
michael@0 19693 '\uFCF2': '\u0640\u064E\u0651',
michael@0 19694 '\uFCF3': '\u0640\u064F\u0651',
michael@0 19695 '\uFCF4': '\u0640\u0650\u0651',
michael@0 19696 '\uFCF5': '\u0637\u0649',
michael@0 19697 '\uFCF6': '\u0637\u064A',
michael@0 19698 '\uFCF7': '\u0639\u0649',
michael@0 19699 '\uFCF8': '\u0639\u064A',
michael@0 19700 '\uFCF9': '\u063A\u0649',
michael@0 19701 '\uFCFA': '\u063A\u064A',
michael@0 19702 '\uFCFB': '\u0633\u0649',
michael@0 19703 '\uFCFC': '\u0633\u064A',
michael@0 19704 '\uFCFD': '\u0634\u0649',
michael@0 19705 '\uFCFE': '\u0634\u064A',
michael@0 19706 '\uFCFF': '\u062D\u0649',
michael@0 19707 '\uFD00': '\u062D\u064A',
michael@0 19708 '\uFD01': '\u062C\u0649',
michael@0 19709 '\uFD02': '\u062C\u064A',
michael@0 19710 '\uFD03': '\u062E\u0649',
michael@0 19711 '\uFD04': '\u062E\u064A',
michael@0 19712 '\uFD05': '\u0635\u0649',
michael@0 19713 '\uFD06': '\u0635\u064A',
michael@0 19714 '\uFD07': '\u0636\u0649',
michael@0 19715 '\uFD08': '\u0636\u064A',
michael@0 19716 '\uFD09': '\u0634\u062C',
michael@0 19717 '\uFD0A': '\u0634\u062D',
michael@0 19718 '\uFD0B': '\u0634\u062E',
michael@0 19719 '\uFD0C': '\u0634\u0645',
michael@0 19720 '\uFD0D': '\u0634\u0631',
michael@0 19721 '\uFD0E': '\u0633\u0631',
michael@0 19722 '\uFD0F': '\u0635\u0631',
michael@0 19723 '\uFD10': '\u0636\u0631',
michael@0 19724 '\uFD11': '\u0637\u0649',
michael@0 19725 '\uFD12': '\u0637\u064A',
michael@0 19726 '\uFD13': '\u0639\u0649',
michael@0 19727 '\uFD14': '\u0639\u064A',
michael@0 19728 '\uFD15': '\u063A\u0649',
michael@0 19729 '\uFD16': '\u063A\u064A',
michael@0 19730 '\uFD17': '\u0633\u0649',
michael@0 19731 '\uFD18': '\u0633\u064A',
michael@0 19732 '\uFD19': '\u0634\u0649',
michael@0 19733 '\uFD1A': '\u0634\u064A',
michael@0 19734 '\uFD1B': '\u062D\u0649',
michael@0 19735 '\uFD1C': '\u062D\u064A',
michael@0 19736 '\uFD1D': '\u062C\u0649',
michael@0 19737 '\uFD1E': '\u062C\u064A',
michael@0 19738 '\uFD1F': '\u062E\u0649',
michael@0 19739 '\uFD20': '\u062E\u064A',
michael@0 19740 '\uFD21': '\u0635\u0649',
michael@0 19741 '\uFD22': '\u0635\u064A',
michael@0 19742 '\uFD23': '\u0636\u0649',
michael@0 19743 '\uFD24': '\u0636\u064A',
michael@0 19744 '\uFD25': '\u0634\u062C',
michael@0 19745 '\uFD26': '\u0634\u062D',
michael@0 19746 '\uFD27': '\u0634\u062E',
michael@0 19747 '\uFD28': '\u0634\u0645',
michael@0 19748 '\uFD29': '\u0634\u0631',
michael@0 19749 '\uFD2A': '\u0633\u0631',
michael@0 19750 '\uFD2B': '\u0635\u0631',
michael@0 19751 '\uFD2C': '\u0636\u0631',
michael@0 19752 '\uFD2D': '\u0634\u062C',
michael@0 19753 '\uFD2E': '\u0634\u062D',
michael@0 19754 '\uFD2F': '\u0634\u062E',
michael@0 19755 '\uFD30': '\u0634\u0645',
michael@0 19756 '\uFD31': '\u0633\u0647',
michael@0 19757 '\uFD32': '\u0634\u0647',
michael@0 19758 '\uFD33': '\u0637\u0645',
michael@0 19759 '\uFD34': '\u0633\u062C',
michael@0 19760 '\uFD35': '\u0633\u062D',
michael@0 19761 '\uFD36': '\u0633\u062E',
michael@0 19762 '\uFD37': '\u0634\u062C',
michael@0 19763 '\uFD38': '\u0634\u062D',
michael@0 19764 '\uFD39': '\u0634\u062E',
michael@0 19765 '\uFD3A': '\u0637\u0645',
michael@0 19766 '\uFD3B': '\u0638\u0645',
michael@0 19767 '\uFD3C': '\u0627\u064B',
michael@0 19768 '\uFD3D': '\u0627\u064B',
michael@0 19769 '\uFD50': '\u062A\u062C\u0645',
michael@0 19770 '\uFD51': '\u062A\u062D\u062C',
michael@0 19771 '\uFD52': '\u062A\u062D\u062C',
michael@0 19772 '\uFD53': '\u062A\u062D\u0645',
michael@0 19773 '\uFD54': '\u062A\u062E\u0645',
michael@0 19774 '\uFD55': '\u062A\u0645\u062C',
michael@0 19775 '\uFD56': '\u062A\u0645\u062D',
michael@0 19776 '\uFD57': '\u062A\u0645\u062E',
michael@0 19777 '\uFD58': '\u062C\u0645\u062D',
michael@0 19778 '\uFD59': '\u062C\u0645\u062D',
michael@0 19779 '\uFD5A': '\u062D\u0645\u064A',
michael@0 19780 '\uFD5B': '\u062D\u0645\u0649',
michael@0 19781 '\uFD5C': '\u0633\u062D\u062C',
michael@0 19782 '\uFD5D': '\u0633\u062C\u062D',
michael@0 19783 '\uFD5E': '\u0633\u062C\u0649',
michael@0 19784 '\uFD5F': '\u0633\u0645\u062D',
michael@0 19785 '\uFD60': '\u0633\u0645\u062D',
michael@0 19786 '\uFD61': '\u0633\u0645\u062C',
michael@0 19787 '\uFD62': '\u0633\u0645\u0645',
michael@0 19788 '\uFD63': '\u0633\u0645\u0645',
michael@0 19789 '\uFD64': '\u0635\u062D\u062D',
michael@0 19790 '\uFD65': '\u0635\u062D\u062D',
michael@0 19791 '\uFD66': '\u0635\u0645\u0645',
michael@0 19792 '\uFD67': '\u0634\u062D\u0645',
michael@0 19793 '\uFD68': '\u0634\u062D\u0645',
michael@0 19794 '\uFD69': '\u0634\u062C\u064A',
michael@0 19795 '\uFD6A': '\u0634\u0645\u062E',
michael@0 19796 '\uFD6B': '\u0634\u0645\u062E',
michael@0 19797 '\uFD6C': '\u0634\u0645\u0645',
michael@0 19798 '\uFD6D': '\u0634\u0645\u0645',
michael@0 19799 '\uFD6E': '\u0636\u062D\u0649',
michael@0 19800 '\uFD6F': '\u0636\u062E\u0645',
michael@0 19801 '\uFD70': '\u0636\u062E\u0645',
michael@0 19802 '\uFD71': '\u0637\u0645\u062D',
michael@0 19803 '\uFD72': '\u0637\u0645\u062D',
michael@0 19804 '\uFD73': '\u0637\u0645\u0645',
michael@0 19805 '\uFD74': '\u0637\u0645\u064A',
michael@0 19806 '\uFD75': '\u0639\u062C\u0645',
michael@0 19807 '\uFD76': '\u0639\u0645\u0645',
michael@0 19808 '\uFD77': '\u0639\u0645\u0645',
michael@0 19809 '\uFD78': '\u0639\u0645\u0649',
michael@0 19810 '\uFD79': '\u063A\u0645\u0645',
michael@0 19811 '\uFD7A': '\u063A\u0645\u064A',
michael@0 19812 '\uFD7B': '\u063A\u0645\u0649',
michael@0 19813 '\uFD7C': '\u0641\u062E\u0645',
michael@0 19814 '\uFD7D': '\u0641\u062E\u0645',
michael@0 19815 '\uFD7E': '\u0642\u0645\u062D',
michael@0 19816 '\uFD7F': '\u0642\u0645\u0645',
michael@0 19817 '\uFD80': '\u0644\u062D\u0645',
michael@0 19818 '\uFD81': '\u0644\u062D\u064A',
michael@0 19819 '\uFD82': '\u0644\u062D\u0649',
michael@0 19820 '\uFD83': '\u0644\u062C\u062C',
michael@0 19821 '\uFD84': '\u0644\u062C\u062C',
michael@0 19822 '\uFD85': '\u0644\u062E\u0645',
michael@0 19823 '\uFD86': '\u0644\u062E\u0645',
michael@0 19824 '\uFD87': '\u0644\u0645\u062D',
michael@0 19825 '\uFD88': '\u0644\u0645\u062D',
michael@0 19826 '\uFD89': '\u0645\u062D\u062C',
michael@0 19827 '\uFD8A': '\u0645\u062D\u0645',
michael@0 19828 '\uFD8B': '\u0645\u062D\u064A',
michael@0 19829 '\uFD8C': '\u0645\u062C\u062D',
michael@0 19830 '\uFD8D': '\u0645\u062C\u0645',
michael@0 19831 '\uFD8E': '\u0645\u062E\u062C',
michael@0 19832 '\uFD8F': '\u0645\u062E\u0645',
michael@0 19833 '\uFD92': '\u0645\u062C\u062E',
michael@0 19834 '\uFD93': '\u0647\u0645\u062C',
michael@0 19835 '\uFD94': '\u0647\u0645\u0645',
michael@0 19836 '\uFD95': '\u0646\u062D\u0645',
michael@0 19837 '\uFD96': '\u0646\u062D\u0649',
michael@0 19838 '\uFD97': '\u0646\u062C\u0645',
michael@0 19839 '\uFD98': '\u0646\u062C\u0645',
michael@0 19840 '\uFD99': '\u0646\u062C\u0649',
michael@0 19841 '\uFD9A': '\u0646\u0645\u064A',
michael@0 19842 '\uFD9B': '\u0646\u0645\u0649',
michael@0 19843 '\uFD9C': '\u064A\u0645\u0645',
michael@0 19844 '\uFD9D': '\u064A\u0645\u0645',
michael@0 19845 '\uFD9E': '\u0628\u062E\u064A',
michael@0 19846 '\uFD9F': '\u062A\u062C\u064A',
michael@0 19847 '\uFDA0': '\u062A\u062C\u0649',
michael@0 19848 '\uFDA1': '\u062A\u062E\u064A',
michael@0 19849 '\uFDA2': '\u062A\u062E\u0649',
michael@0 19850 '\uFDA3': '\u062A\u0645\u064A',
michael@0 19851 '\uFDA4': '\u062A\u0645\u0649',
michael@0 19852 '\uFDA5': '\u062C\u0645\u064A',
michael@0 19853 '\uFDA6': '\u062C\u062D\u0649',
michael@0 19854 '\uFDA7': '\u062C\u0645\u0649',
michael@0 19855 '\uFDA8': '\u0633\u062E\u0649',
michael@0 19856 '\uFDA9': '\u0635\u062D\u064A',
michael@0 19857 '\uFDAA': '\u0634\u062D\u064A',
michael@0 19858 '\uFDAB': '\u0636\u062D\u064A',
michael@0 19859 '\uFDAC': '\u0644\u062C\u064A',
michael@0 19860 '\uFDAD': '\u0644\u0645\u064A',
michael@0 19861 '\uFDAE': '\u064A\u062D\u064A',
michael@0 19862 '\uFDAF': '\u064A\u062C\u064A',
michael@0 19863 '\uFDB0': '\u064A\u0645\u064A',
michael@0 19864 '\uFDB1': '\u0645\u0645\u064A',
michael@0 19865 '\uFDB2': '\u0642\u0645\u064A',
michael@0 19866 '\uFDB3': '\u0646\u062D\u064A',
michael@0 19867 '\uFDB4': '\u0642\u0645\u062D',
michael@0 19868 '\uFDB5': '\u0644\u062D\u0645',
michael@0 19869 '\uFDB6': '\u0639\u0645\u064A',
michael@0 19870 '\uFDB7': '\u0643\u0645\u064A',
michael@0 19871 '\uFDB8': '\u0646\u062C\u062D',
michael@0 19872 '\uFDB9': '\u0645\u062E\u064A',
michael@0 19873 '\uFDBA': '\u0644\u062C\u0645',
michael@0 19874 '\uFDBB': '\u0643\u0645\u0645',
michael@0 19875 '\uFDBC': '\u0644\u062C\u0645',
michael@0 19876 '\uFDBD': '\u0646\u062C\u062D',
michael@0 19877 '\uFDBE': '\u062C\u062D\u064A',
michael@0 19878 '\uFDBF': '\u062D\u062C\u064A',
michael@0 19879 '\uFDC0': '\u0645\u062C\u064A',
michael@0 19880 '\uFDC1': '\u0641\u0645\u064A',
michael@0 19881 '\uFDC2': '\u0628\u062D\u064A',
michael@0 19882 '\uFDC3': '\u0643\u0645\u0645',
michael@0 19883 '\uFDC4': '\u0639\u062C\u0645',
michael@0 19884 '\uFDC5': '\u0635\u0645\u0645',
michael@0 19885 '\uFDC6': '\u0633\u062E\u064A',
michael@0 19886 '\uFDC7': '\u0646\u062C\u064A',
michael@0 19887 '\uFE49': '\u203E',
michael@0 19888 '\uFE4A': '\u203E',
michael@0 19889 '\uFE4B': '\u203E',
michael@0 19890 '\uFE4C': '\u203E',
michael@0 19891 '\uFE4D': '\u005F',
michael@0 19892 '\uFE4E': '\u005F',
michael@0 19893 '\uFE4F': '\u005F',
michael@0 19894 '\uFE80': '\u0621',
michael@0 19895 '\uFE81': '\u0622',
michael@0 19896 '\uFE82': '\u0622',
michael@0 19897 '\uFE83': '\u0623',
michael@0 19898 '\uFE84': '\u0623',
michael@0 19899 '\uFE85': '\u0624',
michael@0 19900 '\uFE86': '\u0624',
michael@0 19901 '\uFE87': '\u0625',
michael@0 19902 '\uFE88': '\u0625',
michael@0 19903 '\uFE89': '\u0626',
michael@0 19904 '\uFE8A': '\u0626',
michael@0 19905 '\uFE8B': '\u0626',
michael@0 19906 '\uFE8C': '\u0626',
michael@0 19907 '\uFE8D': '\u0627',
michael@0 19908 '\uFE8E': '\u0627',
michael@0 19909 '\uFE8F': '\u0628',
michael@0 19910 '\uFE90': '\u0628',
michael@0 19911 '\uFE91': '\u0628',
michael@0 19912 '\uFE92': '\u0628',
michael@0 19913 '\uFE93': '\u0629',
michael@0 19914 '\uFE94': '\u0629',
michael@0 19915 '\uFE95': '\u062A',
michael@0 19916 '\uFE96': '\u062A',
michael@0 19917 '\uFE97': '\u062A',
michael@0 19918 '\uFE98': '\u062A',
michael@0 19919 '\uFE99': '\u062B',
michael@0 19920 '\uFE9A': '\u062B',
michael@0 19921 '\uFE9B': '\u062B',
michael@0 19922 '\uFE9C': '\u062B',
michael@0 19923 '\uFE9D': '\u062C',
michael@0 19924 '\uFE9E': '\u062C',
michael@0 19925 '\uFE9F': '\u062C',
michael@0 19926 '\uFEA0': '\u062C',
michael@0 19927 '\uFEA1': '\u062D',
michael@0 19928 '\uFEA2': '\u062D',
michael@0 19929 '\uFEA3': '\u062D',
michael@0 19930 '\uFEA4': '\u062D',
michael@0 19931 '\uFEA5': '\u062E',
michael@0 19932 '\uFEA6': '\u062E',
michael@0 19933 '\uFEA7': '\u062E',
michael@0 19934 '\uFEA8': '\u062E',
michael@0 19935 '\uFEA9': '\u062F',
michael@0 19936 '\uFEAA': '\u062F',
michael@0 19937 '\uFEAB': '\u0630',
michael@0 19938 '\uFEAC': '\u0630',
michael@0 19939 '\uFEAD': '\u0631',
michael@0 19940 '\uFEAE': '\u0631',
michael@0 19941 '\uFEAF': '\u0632',
michael@0 19942 '\uFEB0': '\u0632',
michael@0 19943 '\uFEB1': '\u0633',
michael@0 19944 '\uFEB2': '\u0633',
michael@0 19945 '\uFEB3': '\u0633',
michael@0 19946 '\uFEB4': '\u0633',
michael@0 19947 '\uFEB5': '\u0634',
michael@0 19948 '\uFEB6': '\u0634',
michael@0 19949 '\uFEB7': '\u0634',
michael@0 19950 '\uFEB8': '\u0634',
michael@0 19951 '\uFEB9': '\u0635',
michael@0 19952 '\uFEBA': '\u0635',
michael@0 19953 '\uFEBB': '\u0635',
michael@0 19954 '\uFEBC': '\u0635',
michael@0 19955 '\uFEBD': '\u0636',
michael@0 19956 '\uFEBE': '\u0636',
michael@0 19957 '\uFEBF': '\u0636',
michael@0 19958 '\uFEC0': '\u0636',
michael@0 19959 '\uFEC1': '\u0637',
michael@0 19960 '\uFEC2': '\u0637',
michael@0 19961 '\uFEC3': '\u0637',
michael@0 19962 '\uFEC4': '\u0637',
michael@0 19963 '\uFEC5': '\u0638',
michael@0 19964 '\uFEC6': '\u0638',
michael@0 19965 '\uFEC7': '\u0638',
michael@0 19966 '\uFEC8': '\u0638',
michael@0 19967 '\uFEC9': '\u0639',
michael@0 19968 '\uFECA': '\u0639',
michael@0 19969 '\uFECB': '\u0639',
michael@0 19970 '\uFECC': '\u0639',
michael@0 19971 '\uFECD': '\u063A',
michael@0 19972 '\uFECE': '\u063A',
michael@0 19973 '\uFECF': '\u063A',
michael@0 19974 '\uFED0': '\u063A',
michael@0 19975 '\uFED1': '\u0641',
michael@0 19976 '\uFED2': '\u0641',
michael@0 19977 '\uFED3': '\u0641',
michael@0 19978 '\uFED4': '\u0641',
michael@0 19979 '\uFED5': '\u0642',
michael@0 19980 '\uFED6': '\u0642',
michael@0 19981 '\uFED7': '\u0642',
michael@0 19982 '\uFED8': '\u0642',
michael@0 19983 '\uFED9': '\u0643',
michael@0 19984 '\uFEDA': '\u0643',
michael@0 19985 '\uFEDB': '\u0643',
michael@0 19986 '\uFEDC': '\u0643',
michael@0 19987 '\uFEDD': '\u0644',
michael@0 19988 '\uFEDE': '\u0644',
michael@0 19989 '\uFEDF': '\u0644',
michael@0 19990 '\uFEE0': '\u0644',
michael@0 19991 '\uFEE1': '\u0645',
michael@0 19992 '\uFEE2': '\u0645',
michael@0 19993 '\uFEE3': '\u0645',
michael@0 19994 '\uFEE4': '\u0645',
michael@0 19995 '\uFEE5': '\u0646',
michael@0 19996 '\uFEE6': '\u0646',
michael@0 19997 '\uFEE7': '\u0646',
michael@0 19998 '\uFEE8': '\u0646',
michael@0 19999 '\uFEE9': '\u0647',
michael@0 20000 '\uFEEA': '\u0647',
michael@0 20001 '\uFEEB': '\u0647',
michael@0 20002 '\uFEEC': '\u0647',
michael@0 20003 '\uFEED': '\u0648',
michael@0 20004 '\uFEEE': '\u0648',
michael@0 20005 '\uFEEF': '\u0649',
michael@0 20006 '\uFEF0': '\u0649',
michael@0 20007 '\uFEF1': '\u064A',
michael@0 20008 '\uFEF2': '\u064A',
michael@0 20009 '\uFEF3': '\u064A',
michael@0 20010 '\uFEF4': '\u064A',
michael@0 20011 '\uFEF5': '\u0644\u0622',
michael@0 20012 '\uFEF6': '\u0644\u0622',
michael@0 20013 '\uFEF7': '\u0644\u0623',
michael@0 20014 '\uFEF8': '\u0644\u0623',
michael@0 20015 '\uFEF9': '\u0644\u0625',
michael@0 20016 '\uFEFA': '\u0644\u0625',
michael@0 20017 '\uFEFB': '\u0644\u0627',
michael@0 20018 '\uFEFC': '\u0644\u0627'
michael@0 20019 };
michael@0 20020
michael@0 20021 function reverseIfRtl(chars) {
michael@0 20022 var charsLength = chars.length;
michael@0 20023 //reverse an arabic ligature
michael@0 20024 if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) {
michael@0 20025 return chars;
michael@0 20026 }
michael@0 20027 var s = '';
michael@0 20028 for (var ii = charsLength - 1; ii >= 0; ii--) {
michael@0 20029 s += chars[ii];
michael@0 20030 }
michael@0 20031 return s;
michael@0 20032 }
michael@0 20033
michael@0 20034 function adjustWidths(properties) {
michael@0 20035 if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) {
michael@0 20036 return;
michael@0 20037 }
michael@0 20038 // adjusting width to fontMatrix scale
michael@0 20039 var scale = 0.001 / properties.fontMatrix[0];
michael@0 20040 var glyphsWidths = properties.widths;
michael@0 20041 for (var glyph in glyphsWidths) {
michael@0 20042 glyphsWidths[glyph] *= scale;
michael@0 20043 }
michael@0 20044 properties.defaultWidth *= scale;
michael@0 20045 }
michael@0 20046
michael@0 20047 var Glyph = (function GlyphClosure() {
michael@0 20048 function Glyph(fontChar, unicode, accent, width, vmetric, operatorList) {
michael@0 20049 this.fontChar = fontChar;
michael@0 20050 this.unicode = unicode;
michael@0 20051 this.accent = accent;
michael@0 20052 this.width = width;
michael@0 20053 this.vmetric = vmetric;
michael@0 20054 this.operatorList = operatorList;
michael@0 20055 }
michael@0 20056
michael@0 20057 Glyph.prototype.matchesForCache =
michael@0 20058 function(fontChar, unicode, accent, width, vmetric, operatorList) {
michael@0 20059 return this.fontChar === fontChar &&
michael@0 20060 this.unicode === unicode &&
michael@0 20061 this.accent === accent &&
michael@0 20062 this.width === width &&
michael@0 20063 this.vmetric === vmetric &&
michael@0 20064 this.operatorList === operatorList;
michael@0 20065 };
michael@0 20066
michael@0 20067 return Glyph;
michael@0 20068 })();
michael@0 20069
michael@0 20070 /**
michael@0 20071 * 'Font' is the class the outside world should use, it encapsulate all the font
michael@0 20072 * decoding logics whatever type it is (assuming the font type is supported).
michael@0 20073 *
michael@0 20074 * For example to read a Type1 font and to attach it to the document:
michael@0 20075 * var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
michael@0 20076 * type1Font.bind();
michael@0 20077 */
michael@0 20078 var Font = (function FontClosure() {
michael@0 20079 function Font(name, file, properties) {
michael@0 20080 var charCode;
michael@0 20081
michael@0 20082 this.name = name;
michael@0 20083 this.loadedName = properties.loadedName;
michael@0 20084 this.coded = properties.coded;
michael@0 20085 this.loadCharProcs = properties.coded;
michael@0 20086 this.sizes = [];
michael@0 20087
michael@0 20088 this.glyphCache = {};
michael@0 20089
michael@0 20090 var names = name.split('+');
michael@0 20091 names = names.length > 1 ? names[1] : names[0];
michael@0 20092 names = names.split(/[-,_]/g)[0];
michael@0 20093 this.isSerifFont = !!(properties.flags & FontFlags.Serif);
michael@0 20094 this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
michael@0 20095 this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);
michael@0 20096
michael@0 20097 var type = properties.type;
michael@0 20098 this.type = type;
michael@0 20099
michael@0 20100 this.fallbackName = (this.isMonospace ? 'monospace' :
michael@0 20101 (this.isSerifFont ? 'serif' : 'sans-serif'));
michael@0 20102
michael@0 20103 this.differences = properties.differences;
michael@0 20104 this.widths = properties.widths;
michael@0 20105 this.defaultWidth = properties.defaultWidth;
michael@0 20106 this.composite = properties.composite;
michael@0 20107 this.wideChars = properties.wideChars;
michael@0 20108 this.cMap = properties.cMap;
michael@0 20109 this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;
michael@0 20110 this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;
michael@0 20111 this.fontMatrix = properties.fontMatrix;
michael@0 20112
michael@0 20113 var unicode = this.buildToUnicode(properties);
michael@0 20114 this.toUnicode = properties.toUnicode = unicode.toUnicode;
michael@0 20115 this.isIdentityUnicode = properties.isIdentityUnicode = unicode.isIdentity;
michael@0 20116
michael@0 20117 this.toFontChar = [];
michael@0 20118
michael@0 20119 if (properties.type == 'Type3') {
michael@0 20120 for (charCode = 0; charCode < 256; charCode++) {
michael@0 20121 this.toFontChar[charCode] = (this.differences[charCode] ||
michael@0 20122 properties.defaultEncoding[charCode]);
michael@0 20123 }
michael@0 20124 return;
michael@0 20125 }
michael@0 20126
michael@0 20127 this.cidEncoding = properties.cidEncoding;
michael@0 20128 this.vertical = properties.vertical;
michael@0 20129 if (this.vertical) {
michael@0 20130 this.vmetrics = properties.vmetrics;
michael@0 20131 this.defaultVMetrics = properties.defaultVMetrics;
michael@0 20132 }
michael@0 20133
michael@0 20134 if (!file) {
michael@0 20135 this.missingFile = true;
michael@0 20136 // The file data is not specified. Trying to fix the font name
michael@0 20137 // to be used with the canvas.font.
michael@0 20138 var fontName = name.replace(/[,_]/g, '-');
michael@0 20139 var isStandardFont = fontName in stdFontMap;
michael@0 20140 fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
michael@0 20141
michael@0 20142 this.bold = (fontName.search(/bold/gi) != -1);
michael@0 20143 this.italic = ((fontName.search(/oblique/gi) != -1) ||
michael@0 20144 (fontName.search(/italic/gi) != -1));
michael@0 20145
michael@0 20146 // Use 'name' instead of 'fontName' here because the original
michael@0 20147 // name ArialBlack for example will be replaced by Helvetica.
michael@0 20148 this.black = (name.search(/Black/g) != -1);
michael@0 20149
michael@0 20150 // if at least one width is present, remeasure all chars when exists
michael@0 20151 this.remeasure = Object.keys(this.widths).length > 0;
michael@0 20152 if (isStandardFont && type === 'CIDFontType2' &&
michael@0 20153 properties.cidEncoding.indexOf('Identity-') === 0) {
michael@0 20154 // Standard fonts might be embedded as CID font without glyph mapping.
michael@0 20155 // Building one based on GlyphMapForStandardFonts.
michael@0 20156 var map = [];
michael@0 20157 for (var code in GlyphMapForStandardFonts) {
michael@0 20158 map[+code] = GlyphMapForStandardFonts[code];
michael@0 20159 }
michael@0 20160 this.toFontChar = map;
michael@0 20161 this.toUnicode = map;
michael@0 20162 } else if (/Symbol/i.test(fontName)) {
michael@0 20163 var symbols = Encodings.SymbolSetEncoding;
michael@0 20164 for (charCode in symbols) {
michael@0 20165 var fontChar = GlyphsUnicode[symbols[charCode]];
michael@0 20166 if (!fontChar) {
michael@0 20167 continue;
michael@0 20168 }
michael@0 20169 this.toFontChar[charCode] = fontChar;
michael@0 20170 }
michael@0 20171 } else if (isStandardFont) {
michael@0 20172 this.toFontChar = [];
michael@0 20173 for (charCode in properties.defaultEncoding) {
michael@0 20174 var glyphName = properties.differences[charCode] ||
michael@0 20175 properties.defaultEncoding[charCode];
michael@0 20176 this.toFontChar[charCode] = GlyphsUnicode[glyphName];
michael@0 20177 }
michael@0 20178 } else {
michael@0 20179 for (charCode in this.toUnicode) {
michael@0 20180 this.toFontChar[charCode] = this.toUnicode[charCode].charCodeAt(0);
michael@0 20181 }
michael@0 20182 }
michael@0 20183 this.loadedName = fontName.split('-')[0];
michael@0 20184 this.loading = false;
michael@0 20185 return;
michael@0 20186 }
michael@0 20187
michael@0 20188 // Some fonts might use wrong font types for Type1C or CIDFontType0C
michael@0 20189 var subtype = properties.subtype;
michael@0 20190 if (subtype == 'Type1C' && (type != 'Type1' && type != 'MMType1')) {
michael@0 20191 type = 'Type1';
michael@0 20192 }
michael@0 20193 if (subtype == 'CIDFontType0C' && type != 'CIDFontType0') {
michael@0 20194 type = 'CIDFontType0';
michael@0 20195 }
michael@0 20196 // XXX: Temporarily change the type for open type so we trigger a warning.
michael@0 20197 // This should be removed when we add support for open type.
michael@0 20198 if (subtype === 'OpenType') {
michael@0 20199 type = 'OpenType';
michael@0 20200 }
michael@0 20201
michael@0 20202 var data;
michael@0 20203 switch (type) {
michael@0 20204 case 'Type1':
michael@0 20205 case 'CIDFontType0':
michael@0 20206 this.mimetype = 'font/opentype';
michael@0 20207
michael@0 20208 var cff = (subtype == 'Type1C' || subtype == 'CIDFontType0C') ?
michael@0 20209 new CFFFont(file, properties) : new Type1Font(name, file, properties);
michael@0 20210
michael@0 20211 adjustWidths(properties);
michael@0 20212
michael@0 20213 // Wrap the CFF data inside an OTF font file
michael@0 20214 data = this.convert(name, cff, properties);
michael@0 20215 break;
michael@0 20216
michael@0 20217 case 'OpenType':
michael@0 20218 case 'TrueType':
michael@0 20219 case 'CIDFontType2':
michael@0 20220 this.mimetype = 'font/opentype';
michael@0 20221
michael@0 20222 // Repair the TrueType file. It is can be damaged in the point of
michael@0 20223 // view of the sanitizer
michael@0 20224 data = this.checkAndRepair(name, file, properties);
michael@0 20225 break;
michael@0 20226
michael@0 20227 default:
michael@0 20228 error('Font ' + type + ' is not supported');
michael@0 20229 break;
michael@0 20230 }
michael@0 20231
michael@0 20232 this.data = data;
michael@0 20233
michael@0 20234 // Transfer some properties again that could change during font conversion
michael@0 20235 this.fontMatrix = properties.fontMatrix;
michael@0 20236 this.widths = properties.widths;
michael@0 20237 this.defaultWidth = properties.defaultWidth;
michael@0 20238 this.encoding = properties.baseEncoding;
michael@0 20239 this.seacMap = properties.seacMap;
michael@0 20240
michael@0 20241 this.loading = true;
michael@0 20242 }
michael@0 20243
michael@0 20244 Font.getFontID = (function () {
michael@0 20245 var ID = 1;
michael@0 20246 return function Font_getFontID() {
michael@0 20247 return String(ID++);
michael@0 20248 };
michael@0 20249 })();
michael@0 20250
michael@0 20251 function int16(b0, b1) {
michael@0 20252 return (b0 << 8) + b1;
michael@0 20253 }
michael@0 20254
michael@0 20255 function int32(b0, b1, b2, b3) {
michael@0 20256 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
michael@0 20257 }
michael@0 20258
michael@0 20259 function getMaxPower2(number) {
michael@0 20260 var maxPower = 0;
michael@0 20261 var value = number;
michael@0 20262 while (value >= 2) {
michael@0 20263 value /= 2;
michael@0 20264 maxPower++;
michael@0 20265 }
michael@0 20266
michael@0 20267 value = 2;
michael@0 20268 for (var i = 1; i < maxPower; i++) {
michael@0 20269 value *= 2;
michael@0 20270 }
michael@0 20271 return value;
michael@0 20272 }
michael@0 20273
michael@0 20274 function string16(value) {
michael@0 20275 return String.fromCharCode((value >> 8) & 0xff, value & 0xff);
michael@0 20276 }
michael@0 20277
michael@0 20278 function safeString16(value) {
michael@0 20279 // clamp value to the 16-bit int range
michael@0 20280 value = (value > 0x7FFF ? 0x7FFF : (value < -0x8000 ? -0x8000 : value));
michael@0 20281 return String.fromCharCode((value >> 8) & 0xff, value & 0xff);
michael@0 20282 }
michael@0 20283
michael@0 20284 function createOpenTypeHeader(sfnt, file, numTables) {
michael@0 20285 // Windows hates the Mac TrueType sfnt version number
michael@0 20286 if (sfnt == 'true') {
michael@0 20287 sfnt = string32(0x00010000);
michael@0 20288 }
michael@0 20289
michael@0 20290 // sfnt version (4 bytes)
michael@0 20291 var header = sfnt;
michael@0 20292
michael@0 20293 // numTables (2 bytes)
michael@0 20294 header += string16(numTables);
michael@0 20295
michael@0 20296 // searchRange (2 bytes)
michael@0 20297 var tablesMaxPower2 = getMaxPower2(numTables);
michael@0 20298 var searchRange = tablesMaxPower2 * 16;
michael@0 20299 header += string16(searchRange);
michael@0 20300
michael@0 20301 // entrySelector (2 bytes)
michael@0 20302 header += string16(Math.log(tablesMaxPower2) / Math.log(2));
michael@0 20303
michael@0 20304 // rangeShift (2 bytes)
michael@0 20305 header += string16(numTables * 16 - searchRange);
michael@0 20306
michael@0 20307 file.file += header;
michael@0 20308 file.virtualOffset += header.length;
michael@0 20309 }
michael@0 20310
michael@0 20311 function createTableEntry(file, tag, data) {
michael@0 20312 // offset
michael@0 20313 var offset = file.virtualOffset;
michael@0 20314
michael@0 20315 // length
michael@0 20316 var length = data.length;
michael@0 20317
michael@0 20318 // Per spec tables must be 4-bytes align so add padding as needed
michael@0 20319 while (data.length & 3) {
michael@0 20320 data.push(0x00);
michael@0 20321 }
michael@0 20322 while (file.virtualOffset & 3) {
michael@0 20323 file.virtualOffset++;
michael@0 20324 }
michael@0 20325
michael@0 20326 // checksum
michael@0 20327 var checksum = 0, n = data.length;
michael@0 20328 for (var i = 0; i < n; i += 4) {
michael@0 20329 checksum = (checksum + int32(data[i], data[i + 1], data[i + 2],
michael@0 20330 data[i + 3])) | 0;
michael@0 20331 }
michael@0 20332
michael@0 20333 var tableEntry = (tag + string32(checksum) +
michael@0 20334 string32(offset) + string32(length));
michael@0 20335 file.file += tableEntry;
michael@0 20336 file.virtualOffset += data.length;
michael@0 20337 }
michael@0 20338
michael@0 20339 /**
michael@0 20340 * Rebuilds the char code to glyph ID map by trying to replace the char codes
michael@0 20341 * with their unicode value. It also moves char codes that are in known
michael@0 20342 * problematic locations.
michael@0 20343 * @return {Object} Two properties:
michael@0 20344 * 'toFontChar' - maps original char codes(the value that will be read
michael@0 20345 * from commands such as show text) to the char codes that will be used in the
michael@0 20346 * font that we build
michael@0 20347 * 'charCodeToGlyphId' - maps the new font char codes to glyph ids
michael@0 20348 */
michael@0 20349 function adjustMapping(charCodeToGlyphId, properties) {
michael@0 20350 var toUnicode = properties.toUnicode;
michael@0 20351 var isSymbolic = !!(properties.flags & FontFlags.Symbolic);
michael@0 20352 var isIdentityUnicode = properties.isIdentityUnicode;
michael@0 20353 var newMap = Object.create(null);
michael@0 20354 var toFontChar = [];
michael@0 20355 var usedFontCharCodes = [];
michael@0 20356 var nextAvailableFontCharCode = PRIVATE_USE_OFFSET_START;
michael@0 20357 for (var originalCharCode in charCodeToGlyphId) {
michael@0 20358 originalCharCode |= 0;
michael@0 20359 var glyphId = charCodeToGlyphId[originalCharCode];
michael@0 20360 var fontCharCode = originalCharCode;
michael@0 20361 // First try to map the value to a unicode position if a non identity map
michael@0 20362 // was created.
michael@0 20363 if (!isIdentityUnicode && originalCharCode in toUnicode) {
michael@0 20364 var unicode = toUnicode[fontCharCode];
michael@0 20365 // TODO: Try to map ligatures to the correct spot.
michael@0 20366 if (unicode.length === 1) {
michael@0 20367 fontCharCode = unicode.charCodeAt(0);
michael@0 20368 }
michael@0 20369 }
michael@0 20370 // Try to move control characters, special characters and already mapped
michael@0 20371 // characters to the private use area since they will not be drawn by
michael@0 20372 // canvas if left in their current position. Also, move characters if the
michael@0 20373 // font was symbolic and there is only an identity unicode map since the
michael@0 20374 // characters probably aren't in the correct position (fixes an issue
michael@0 20375 // with firefox and thuluthfont).
michael@0 20376 if ((fontCharCode in usedFontCharCodes ||
michael@0 20377 fontCharCode <= 0x1f || // Control chars
michael@0 20378 fontCharCode === 0x7F || // Control char
michael@0 20379 fontCharCode === 0xAD || // Soft hyphen
michael@0 20380 (fontCharCode >= 0x80 && fontCharCode <= 0x9F) || // Control chars
michael@0 20381 (isSymbolic && isIdentityUnicode)) &&
michael@0 20382 nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) { // Room left.
michael@0 20383 // Loop to try and find a free spot in the private use area.
michael@0 20384 do {
michael@0 20385 fontCharCode = nextAvailableFontCharCode++;
michael@0 20386
michael@0 20387 if (SKIP_PRIVATE_USE_RANGE_F000_TO_F01F && fontCharCode === 0xF000) {
michael@0 20388 fontCharCode = 0xF020;
michael@0 20389 nextAvailableFontCharCode = fontCharCode + 1;
michael@0 20390 }
michael@0 20391
michael@0 20392 } while (fontCharCode in usedFontCharCodes &&
michael@0 20393 nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END);
michael@0 20394 }
michael@0 20395
michael@0 20396 newMap[fontCharCode] = glyphId;
michael@0 20397 toFontChar[originalCharCode] = fontCharCode;
michael@0 20398 usedFontCharCodes[fontCharCode] = true;
michael@0 20399 }
michael@0 20400 return {
michael@0 20401 toFontChar: toFontChar,
michael@0 20402 charCodeToGlyphId: newMap,
michael@0 20403 nextAvailableFontCharCode: nextAvailableFontCharCode
michael@0 20404 };
michael@0 20405 }
michael@0 20406
michael@0 20407 function getRanges(glyphs) {
michael@0 20408 // Array.sort() sorts by characters, not numerically, so convert to an
michael@0 20409 // array of characters.
michael@0 20410 var codes = [];
michael@0 20411 for (var charCode in glyphs) {
michael@0 20412 codes.push({ fontCharCode: charCode | 0, glyphId: glyphs[charCode] });
michael@0 20413 }
michael@0 20414 codes.sort(function fontGetRangesSort(a, b) {
michael@0 20415 return a.fontCharCode - b.fontCharCode;
michael@0 20416 });
michael@0 20417
michael@0 20418 // Split the sorted codes into ranges.
michael@0 20419 var ranges = [];
michael@0 20420 var length = codes.length;
michael@0 20421 for (var n = 0; n < length; ) {
michael@0 20422 var start = codes[n].fontCharCode;
michael@0 20423 var codeIndices = [codes[n].glyphId];
michael@0 20424 ++n;
michael@0 20425 var end = start;
michael@0 20426 while (n < length && end + 1 == codes[n].fontCharCode) {
michael@0 20427 codeIndices.push(codes[n].glyphId);
michael@0 20428 ++end;
michael@0 20429 ++n;
michael@0 20430 if (end === 0xFFFF) {
michael@0 20431 break;
michael@0 20432 }
michael@0 20433 }
michael@0 20434 ranges.push([start, end, codeIndices]);
michael@0 20435 }
michael@0 20436
michael@0 20437 return ranges;
michael@0 20438 }
michael@0 20439
michael@0 20440 function createCmapTable(glyphs) {
michael@0 20441 var ranges = getRanges(glyphs);
michael@0 20442 var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1;
michael@0 20443 var cmap = '\x00\x00' + // version
michael@0 20444 string16(numTables) + // numTables
michael@0 20445 '\x00\x03' + // platformID
michael@0 20446 '\x00\x01' + // encodingID
michael@0 20447 string32(4 + numTables * 8); // start of the table record
michael@0 20448
michael@0 20449 var i, ii, j, jj;
michael@0 20450 for (i = ranges.length - 1; i >= 0; --i) {
michael@0 20451 if (ranges[i][0] <= 0xFFFF) { break; }
michael@0 20452 }
michael@0 20453 var bmpLength = i + 1;
michael@0 20454
michael@0 20455 if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) {
michael@0 20456 ranges[i][1] = 0xFFFE;
michael@0 20457 }
michael@0 20458 var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0;
michael@0 20459 var segCount = bmpLength + trailingRangesCount;
michael@0 20460 var segCount2 = segCount * 2;
michael@0 20461 var searchRange = getMaxPower2(segCount) * 2;
michael@0 20462 var searchEntry = Math.log(segCount) / Math.log(2);
michael@0 20463 var rangeShift = 2 * segCount - searchRange;
michael@0 20464
michael@0 20465 // Fill up the 4 parallel arrays describing the segments.
michael@0 20466 var startCount = '';
michael@0 20467 var endCount = '';
michael@0 20468 var idDeltas = '';
michael@0 20469 var idRangeOffsets = '';
michael@0 20470 var glyphsIds = '';
michael@0 20471 var bias = 0;
michael@0 20472
michael@0 20473 var range, start, end, codes;
michael@0 20474 for (i = 0, ii = bmpLength; i < ii; i++) {
michael@0 20475 range = ranges[i];
michael@0 20476 start = range[0];
michael@0 20477 end = range[1];
michael@0 20478 startCount += string16(start);
michael@0 20479 endCount += string16(end);
michael@0 20480 codes = range[2];
michael@0 20481 var contiguous = true;
michael@0 20482 for (j = 1, jj = codes.length; j < jj; ++j) {
michael@0 20483 if (codes[j] !== codes[j - 1] + 1) {
michael@0 20484 contiguous = false;
michael@0 20485 break;
michael@0 20486 }
michael@0 20487 }
michael@0 20488 if (!contiguous) {
michael@0 20489 var offset = (segCount - i) * 2 + bias * 2;
michael@0 20490 bias += (end - start + 1);
michael@0 20491
michael@0 20492 idDeltas += string16(0);
michael@0 20493 idRangeOffsets += string16(offset);
michael@0 20494
michael@0 20495 for (j = 0, jj = codes.length; j < jj; ++j) {
michael@0 20496 glyphsIds += string16(codes[j]);
michael@0 20497 }
michael@0 20498 } else {
michael@0 20499 var startCode = codes[0];
michael@0 20500
michael@0 20501 idDeltas += string16((startCode - start) & 0xFFFF);
michael@0 20502 idRangeOffsets += string16(0);
michael@0 20503 }
michael@0 20504 }
michael@0 20505
michael@0 20506 if (trailingRangesCount > 0) {
michael@0 20507 endCount += '\xFF\xFF';
michael@0 20508 startCount += '\xFF\xFF';
michael@0 20509 idDeltas += '\x00\x01';
michael@0 20510 idRangeOffsets += '\x00\x00';
michael@0 20511 }
michael@0 20512
michael@0 20513 var format314 = '\x00\x00' + // language
michael@0 20514 string16(segCount2) +
michael@0 20515 string16(searchRange) +
michael@0 20516 string16(searchEntry) +
michael@0 20517 string16(rangeShift) +
michael@0 20518 endCount + '\x00\x00' + startCount +
michael@0 20519 idDeltas + idRangeOffsets + glyphsIds;
michael@0 20520
michael@0 20521 var format31012 = '';
michael@0 20522 var header31012 = '';
michael@0 20523 if (numTables > 1) {
michael@0 20524 cmap += '\x00\x03' + // platformID
michael@0 20525 '\x00\x0A' + // encodingID
michael@0 20526 string32(4 + numTables * 8 +
michael@0 20527 4 + format314.length); // start of the table record
michael@0 20528 format31012 = '';
michael@0 20529 for (i = 0, ii = ranges.length; i < ii; i++) {
michael@0 20530 range = ranges[i];
michael@0 20531 start = range[0];
michael@0 20532 codes = range[2];
michael@0 20533 var code = codes[0];
michael@0 20534 for (j = 1, jj = codes.length; j < jj; ++j) {
michael@0 20535 if (codes[j] !== codes[j - 1] + 1) {
michael@0 20536 end = range[0] + j - 1;
michael@0 20537 format31012 += string32(start) + // startCharCode
michael@0 20538 string32(end) + // endCharCode
michael@0 20539 string32(code); // startGlyphID
michael@0 20540 start = end + 1;
michael@0 20541 code = codes[j];
michael@0 20542 }
michael@0 20543 }
michael@0 20544 format31012 += string32(start) + // startCharCode
michael@0 20545 string32(range[1]) + // endCharCode
michael@0 20546 string32(code); // startGlyphID
michael@0 20547 }
michael@0 20548 header31012 = '\x00\x0C' + // format
michael@0 20549 '\x00\x00' + // reserved
michael@0 20550 string32(format31012.length + 16) + // length
michael@0 20551 '\x00\x00\x00\x00' + // language
michael@0 20552 string32(format31012.length / 12); // nGroups
michael@0 20553 }
michael@0 20554
michael@0 20555 return stringToArray(cmap +
michael@0 20556 '\x00\x04' + // format
michael@0 20557 string16(format314.length + 4) + // length
michael@0 20558 format314 + header31012 + format31012);
michael@0 20559 }
michael@0 20560
michael@0 20561 function validateOS2Table(os2) {
michael@0 20562 var stream = new Stream(os2.data);
michael@0 20563 var version = stream.getUint16();
michael@0 20564 // TODO verify all OS/2 tables fields, but currently we validate only those
michael@0 20565 // that give us issues
michael@0 20566 stream.getBytes(60); // skipping type, misc sizes, panose, unicode ranges
michael@0 20567 var selection = stream.getUint16();
michael@0 20568 if (version < 4 && (selection & 0x0300)) {
michael@0 20569 return false;
michael@0 20570 }
michael@0 20571 var firstChar = stream.getUint16();
michael@0 20572 var lastChar = stream.getUint16();
michael@0 20573 if (firstChar > lastChar) {
michael@0 20574 return false;
michael@0 20575 }
michael@0 20576 stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap
michael@0 20577 var usWinAscent = stream.getUint16();
michael@0 20578 if (usWinAscent === 0) { // makes font unreadable by windows
michael@0 20579 return false;
michael@0 20580 }
michael@0 20581
michael@0 20582 // OS/2 appears to be valid, resetting some fields
michael@0 20583 os2.data[8] = os2.data[9] = 0; // IE rejects fonts if fsType != 0
michael@0 20584 return true;
michael@0 20585 }
michael@0 20586
michael@0 20587 function createOS2Table(properties, charstrings, override) {
michael@0 20588 override = override || {
michael@0 20589 unitsPerEm: 0,
michael@0 20590 yMax: 0,
michael@0 20591 yMin: 0,
michael@0 20592 ascent: 0,
michael@0 20593 descent: 0
michael@0 20594 };
michael@0 20595
michael@0 20596 var ulUnicodeRange1 = 0;
michael@0 20597 var ulUnicodeRange2 = 0;
michael@0 20598 var ulUnicodeRange3 = 0;
michael@0 20599 var ulUnicodeRange4 = 0;
michael@0 20600
michael@0 20601 var firstCharIndex = null;
michael@0 20602 var lastCharIndex = 0;
michael@0 20603
michael@0 20604 if (charstrings) {
michael@0 20605 for (var code in charstrings) {
michael@0 20606 code |= 0;
michael@0 20607 if (firstCharIndex > code || !firstCharIndex) {
michael@0 20608 firstCharIndex = code;
michael@0 20609 }
michael@0 20610 if (lastCharIndex < code) {
michael@0 20611 lastCharIndex = code;
michael@0 20612 }
michael@0 20613
michael@0 20614 var position = getUnicodeRangeFor(code);
michael@0 20615 if (position < 32) {
michael@0 20616 ulUnicodeRange1 |= 1 << position;
michael@0 20617 } else if (position < 64) {
michael@0 20618 ulUnicodeRange2 |= 1 << position - 32;
michael@0 20619 } else if (position < 96) {
michael@0 20620 ulUnicodeRange3 |= 1 << position - 64;
michael@0 20621 } else if (position < 123) {
michael@0 20622 ulUnicodeRange4 |= 1 << position - 96;
michael@0 20623 } else {
michael@0 20624 error('Unicode ranges Bits > 123 are reserved for internal usage');
michael@0 20625 }
michael@0 20626 }
michael@0 20627 } else {
michael@0 20628 // TODO
michael@0 20629 firstCharIndex = 0;
michael@0 20630 lastCharIndex = 255;
michael@0 20631 }
michael@0 20632
michael@0 20633 var bbox = properties.bbox || [0, 0, 0, 0];
michael@0 20634 var unitsPerEm = (override.unitsPerEm ||
michael@0 20635 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]);
michael@0 20636
michael@0 20637 // if the font units differ to the PDF glyph space units
michael@0 20638 // then scale up the values
michael@0 20639 var scale = (properties.ascentScaled ? 1.0 :
michael@0 20640 unitsPerEm / PDF_GLYPH_SPACE_UNITS);
michael@0 20641
michael@0 20642 var typoAscent = (override.ascent ||
michael@0 20643 Math.round(scale * (properties.ascent || bbox[3])));
michael@0 20644 var typoDescent = (override.descent ||
michael@0 20645 Math.round(scale * (properties.descent || bbox[1])));
michael@0 20646 if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {
michael@0 20647 typoDescent = -typoDescent; // fixing incorrect descent
michael@0 20648 }
michael@0 20649 var winAscent = override.yMax || typoAscent;
michael@0 20650 var winDescent = -override.yMin || -typoDescent;
michael@0 20651
michael@0 20652 return '\x00\x03' + // version
michael@0 20653 '\x02\x24' + // xAvgCharWidth
michael@0 20654 '\x01\xF4' + // usWeightClass
michael@0 20655 '\x00\x05' + // usWidthClass
michael@0 20656 '\x00\x00' + // fstype (0 to let the font loads via font-face on IE)
michael@0 20657 '\x02\x8A' + // ySubscriptXSize
michael@0 20658 '\x02\xBB' + // ySubscriptYSize
michael@0 20659 '\x00\x00' + // ySubscriptXOffset
michael@0 20660 '\x00\x8C' + // ySubscriptYOffset
michael@0 20661 '\x02\x8A' + // ySuperScriptXSize
michael@0 20662 '\x02\xBB' + // ySuperScriptYSize
michael@0 20663 '\x00\x00' + // ySuperScriptXOffset
michael@0 20664 '\x01\xDF' + // ySuperScriptYOffset
michael@0 20665 '\x00\x31' + // yStrikeOutSize
michael@0 20666 '\x01\x02' + // yStrikeOutPosition
michael@0 20667 '\x00\x00' + // sFamilyClass
michael@0 20668 '\x00\x00\x06' +
michael@0 20669 String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) +
michael@0 20670 '\x00\x00\x00\x00\x00\x00' + // Panose
michael@0 20671 string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31)
michael@0 20672 string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63)
michael@0 20673 string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95)
michael@0 20674 string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127)
michael@0 20675 '\x2A\x32\x31\x2A' + // achVendID
michael@0 20676 string16(properties.italicAngle ? 1 : 0) + // fsSelection
michael@0 20677 string16(firstCharIndex ||
michael@0 20678 properties.firstChar) + // usFirstCharIndex
michael@0 20679 string16(lastCharIndex || properties.lastChar) + // usLastCharIndex
michael@0 20680 string16(typoAscent) + // sTypoAscender
michael@0 20681 string16(typoDescent) + // sTypoDescender
michael@0 20682 '\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value)
michael@0 20683 string16(winAscent) + // usWinAscent
michael@0 20684 string16(winDescent) + // usWinDescent
michael@0 20685 '\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31)
michael@0 20686 '\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63)
michael@0 20687 string16(properties.xHeight) + // sxHeight
michael@0 20688 string16(properties.capHeight) + // sCapHeight
michael@0 20689 string16(0) + // usDefaultChar
michael@0 20690 string16(firstCharIndex || properties.firstChar) + // usBreakChar
michael@0 20691 '\x00\x03'; // usMaxContext
michael@0 20692 }
michael@0 20693
michael@0 20694 function createPostTable(properties) {
michael@0 20695 var angle = Math.floor(properties.italicAngle * (Math.pow(2, 16)));
michael@0 20696 return ('\x00\x03\x00\x00' + // Version number
michael@0 20697 string32(angle) + // italicAngle
michael@0 20698 '\x00\x00' + // underlinePosition
michael@0 20699 '\x00\x00' + // underlineThickness
michael@0 20700 string32(properties.fixedPitch) + // isFixedPitch
michael@0 20701 '\x00\x00\x00\x00' + // minMemType42
michael@0 20702 '\x00\x00\x00\x00' + // maxMemType42
michael@0 20703 '\x00\x00\x00\x00' + // minMemType1
michael@0 20704 '\x00\x00\x00\x00'); // maxMemType1
michael@0 20705 }
michael@0 20706
michael@0 20707 function createNameTable(name, proto) {
michael@0 20708 if (!proto) {
michael@0 20709 proto = [[], []]; // no strings and unicode strings
michael@0 20710 }
michael@0 20711
michael@0 20712 var strings = [
michael@0 20713 proto[0][0] || 'Original licence', // 0.Copyright
michael@0 20714 proto[0][1] || name, // 1.Font family
michael@0 20715 proto[0][2] || 'Unknown', // 2.Font subfamily (font weight)
michael@0 20716 proto[0][3] || 'uniqueID', // 3.Unique ID
michael@0 20717 proto[0][4] || name, // 4.Full font name
michael@0 20718 proto[0][5] || 'Version 0.11', // 5.Version
michael@0 20719 proto[0][6] || '', // 6.Postscript name
michael@0 20720 proto[0][7] || 'Unknown', // 7.Trademark
michael@0 20721 proto[0][8] || 'Unknown', // 8.Manufacturer
michael@0 20722 proto[0][9] || 'Unknown' // 9.Designer
michael@0 20723 ];
michael@0 20724
michael@0 20725 // Mac want 1-byte per character strings while Windows want
michael@0 20726 // 2-bytes per character, so duplicate the names table
michael@0 20727 var stringsUnicode = [];
michael@0 20728 var i, ii, j, jj, str;
michael@0 20729 for (i = 0, ii = strings.length; i < ii; i++) {
michael@0 20730 str = proto[1][i] || strings[i];
michael@0 20731
michael@0 20732 var strBufUnicode = [];
michael@0 20733 for (j = 0, jj = str.length; j < jj; j++) {
michael@0 20734 strBufUnicode.push(string16(str.charCodeAt(j)));
michael@0 20735 }
michael@0 20736 stringsUnicode.push(strBufUnicode.join(''));
michael@0 20737 }
michael@0 20738
michael@0 20739 var names = [strings, stringsUnicode];
michael@0 20740 var platforms = ['\x00\x01', '\x00\x03'];
michael@0 20741 var encodings = ['\x00\x00', '\x00\x01'];
michael@0 20742 var languages = ['\x00\x00', '\x04\x09'];
michael@0 20743
michael@0 20744 var namesRecordCount = strings.length * platforms.length;
michael@0 20745 var nameTable =
michael@0 20746 '\x00\x00' + // format
michael@0 20747 string16(namesRecordCount) + // Number of names Record
michael@0 20748 string16(namesRecordCount * 12 + 6); // Storage
michael@0 20749
michael@0 20750 // Build the name records field
michael@0 20751 var strOffset = 0;
michael@0 20752 for (i = 0, ii = platforms.length; i < ii; i++) {
michael@0 20753 var strs = names[i];
michael@0 20754 for (j = 0, jj = strs.length; j < jj; j++) {
michael@0 20755 str = strs[j];
michael@0 20756 var nameRecord =
michael@0 20757 platforms[i] + // platform ID
michael@0 20758 encodings[i] + // encoding ID
michael@0 20759 languages[i] + // language ID
michael@0 20760 string16(j) + // name ID
michael@0 20761 string16(str.length) +
michael@0 20762 string16(strOffset);
michael@0 20763 nameTable += nameRecord;
michael@0 20764 strOffset += str.length;
michael@0 20765 }
michael@0 20766 }
michael@0 20767
michael@0 20768 nameTable += strings.join('') + stringsUnicode.join('');
michael@0 20769 return nameTable;
michael@0 20770 }
michael@0 20771
michael@0 20772 Font.prototype = {
michael@0 20773 name: null,
michael@0 20774 font: null,
michael@0 20775 mimetype: null,
michael@0 20776 encoding: null,
michael@0 20777 get renderer() {
michael@0 20778 var renderer = FontRendererFactory.create(this);
michael@0 20779 return shadow(this, 'renderer', renderer);
michael@0 20780 },
michael@0 20781
michael@0 20782 exportData: function Font_exportData() {
michael@0 20783 var data = {};
michael@0 20784 for (var i in this) {
michael@0 20785 if (this.hasOwnProperty(i)) {
michael@0 20786 data[i] = this[i];
michael@0 20787 }
michael@0 20788 }
michael@0 20789 return data;
michael@0 20790 },
michael@0 20791
michael@0 20792 checkAndRepair: function Font_checkAndRepair(name, font, properties) {
michael@0 20793 function readTableEntry(file) {
michael@0 20794 var tag = bytesToString(file.getBytes(4));
michael@0 20795
michael@0 20796 var checksum = file.getInt32();
michael@0 20797 var offset = file.getInt32() >>> 0;
michael@0 20798 var length = file.getInt32() >>> 0;
michael@0 20799
michael@0 20800 // Read the table associated data
michael@0 20801 var previousPosition = file.pos;
michael@0 20802 file.pos = file.start ? file.start : 0;
michael@0 20803 file.skip(offset);
michael@0 20804 var data = file.getBytes(length);
michael@0 20805 file.pos = previousPosition;
michael@0 20806
michael@0 20807 if (tag == 'head') {
michael@0 20808 // clearing checksum adjustment
michael@0 20809 data[8] = data[9] = data[10] = data[11] = 0;
michael@0 20810 data[17] |= 0x20; //Set font optimized for cleartype flag
michael@0 20811 }
michael@0 20812
michael@0 20813 return {
michael@0 20814 tag: tag,
michael@0 20815 checksum: checksum,
michael@0 20816 length: length,
michael@0 20817 offset: offset,
michael@0 20818 data: data
michael@0 20819 };
michael@0 20820 }
michael@0 20821
michael@0 20822 function readOpenTypeHeader(ttf) {
michael@0 20823 return {
michael@0 20824 version: bytesToString(ttf.getBytes(4)),
michael@0 20825 numTables: ttf.getUint16(),
michael@0 20826 searchRange: ttf.getUint16(),
michael@0 20827 entrySelector: ttf.getUint16(),
michael@0 20828 rangeShift: ttf.getUint16()
michael@0 20829 };
michael@0 20830 }
michael@0 20831
michael@0 20832 /**
michael@0 20833 * Read the appropriate subtable from the cmap according to 9.6.6.4 from
michael@0 20834 * PDF spec
michael@0 20835 */
michael@0 20836 function readCmapTable(cmap, font, isSymbolicFont) {
michael@0 20837 var segment;
michael@0 20838 var start = (font.start ? font.start : 0) + cmap.offset;
michael@0 20839 font.pos = start;
michael@0 20840
michael@0 20841 var version = font.getUint16();
michael@0 20842 var numTables = font.getUint16();
michael@0 20843
michael@0 20844 var potentialTable;
michael@0 20845 var canBreak = false;
michael@0 20846 // There's an order of preference in terms of which cmap subtable to
michael@0 20847 // use:
michael@0 20848 // - non-symbolic fonts the preference is a 3,1 table then a 1,0 table
michael@0 20849 // - symbolic fonts the preference is a 3,0 table then a 1,0 table
michael@0 20850 // The following takes advantage of the fact that the tables are sorted
michael@0 20851 // to work.
michael@0 20852 for (var i = 0; i < numTables; i++) {
michael@0 20853 var platformId = font.getUint16();
michael@0 20854 var encodingId = font.getUint16();
michael@0 20855 var offset = font.getInt32() >>> 0;
michael@0 20856 var useTable = false;
michael@0 20857
michael@0 20858 if (platformId == 1 && encodingId === 0) {
michael@0 20859 useTable = true;
michael@0 20860 // Continue the loop since there still may be a higher priority
michael@0 20861 // table.
michael@0 20862 } else if (!isSymbolicFont && platformId === 3 && encodingId === 1) {
michael@0 20863 useTable = true;
michael@0 20864 canBreak = true;
michael@0 20865 } else if (isSymbolicFont && platformId === 3 && encodingId === 0) {
michael@0 20866 useTable = true;
michael@0 20867 canBreak = true;
michael@0 20868 }
michael@0 20869
michael@0 20870 if (useTable) {
michael@0 20871 potentialTable = {
michael@0 20872 platformId: platformId,
michael@0 20873 encodingId: encodingId,
michael@0 20874 offset: offset
michael@0 20875 };
michael@0 20876 }
michael@0 20877 if (canBreak) {
michael@0 20878 break;
michael@0 20879 }
michael@0 20880 }
michael@0 20881
michael@0 20882 if (!potentialTable) {
michael@0 20883 warn('Could not find a preferred cmap table.');
michael@0 20884 return {
michael@0 20885 platformId: -1,
michael@0 20886 encodingId: -1,
michael@0 20887 mappings: [],
michael@0 20888 hasShortCmap: false
michael@0 20889 };
michael@0 20890 }
michael@0 20891
michael@0 20892 font.pos = start + potentialTable.offset;
michael@0 20893 var format = font.getUint16();
michael@0 20894 var length = font.getUint16();
michael@0 20895 var language = font.getUint16();
michael@0 20896
michael@0 20897 var hasShortCmap = false;
michael@0 20898 var mappings = [];
michael@0 20899 var j, glyphId;
michael@0 20900
michael@0 20901 // TODO(mack): refactor this cmap subtable reading logic out
michael@0 20902 if (format === 0) {
michael@0 20903 for (j = 0; j < 256; j++) {
michael@0 20904 var index = font.getByte();
michael@0 20905 if (!index) {
michael@0 20906 continue;
michael@0 20907 }
michael@0 20908 mappings.push({
michael@0 20909 charCode: j,
michael@0 20910 glyphId: index
michael@0 20911 });
michael@0 20912 }
michael@0 20913 hasShortCmap = true;
michael@0 20914 } else if (format === 4) {
michael@0 20915 // re-creating the table in format 4 since the encoding
michael@0 20916 // might be changed
michael@0 20917 var segCount = (font.getUint16() >> 1);
michael@0 20918 font.getBytes(6); // skipping range fields
michael@0 20919 var segIndex, segments = [];
michael@0 20920 for (segIndex = 0; segIndex < segCount; segIndex++) {
michael@0 20921 segments.push({ end: font.getUint16() });
michael@0 20922 }
michael@0 20923 font.getUint16();
michael@0 20924 for (segIndex = 0; segIndex < segCount; segIndex++) {
michael@0 20925 segments[segIndex].start = font.getUint16();
michael@0 20926 }
michael@0 20927
michael@0 20928 for (segIndex = 0; segIndex < segCount; segIndex++) {
michael@0 20929 segments[segIndex].delta = font.getUint16();
michael@0 20930 }
michael@0 20931
michael@0 20932 var offsetsCount = 0;
michael@0 20933 for (segIndex = 0; segIndex < segCount; segIndex++) {
michael@0 20934 segment = segments[segIndex];
michael@0 20935 var rangeOffset = font.getUint16();
michael@0 20936 if (!rangeOffset) {
michael@0 20937 segment.offsetIndex = -1;
michael@0 20938 continue;
michael@0 20939 }
michael@0 20940
michael@0 20941 var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex);
michael@0 20942 segment.offsetIndex = offsetIndex;
michael@0 20943 offsetsCount = Math.max(offsetsCount, offsetIndex +
michael@0 20944 segment.end - segment.start + 1);
michael@0 20945 }
michael@0 20946
michael@0 20947 var offsets = [];
michael@0 20948 for (j = 0; j < offsetsCount; j++) {
michael@0 20949 offsets.push(font.getUint16());
michael@0 20950 }
michael@0 20951
michael@0 20952 for (segIndex = 0; segIndex < segCount; segIndex++) {
michael@0 20953 segment = segments[segIndex];
michael@0 20954 start = segment.start;
michael@0 20955 var end = segment.end;
michael@0 20956 var delta = segment.delta;
michael@0 20957 offsetIndex = segment.offsetIndex;
michael@0 20958
michael@0 20959 for (j = start; j <= end; j++) {
michael@0 20960 if (j == 0xFFFF) {
michael@0 20961 continue;
michael@0 20962 }
michael@0 20963
michael@0 20964 glyphId = (offsetIndex < 0 ?
michael@0 20965 j : offsets[offsetIndex + j - start]);
michael@0 20966 glyphId = (glyphId + delta) & 0xFFFF;
michael@0 20967 if (glyphId === 0) {
michael@0 20968 continue;
michael@0 20969 }
michael@0 20970 mappings.push({
michael@0 20971 charCode: j,
michael@0 20972 glyphId: glyphId
michael@0 20973 });
michael@0 20974 }
michael@0 20975 }
michael@0 20976 } else if (format == 6) {
michael@0 20977 // Format 6 is a 2-bytes dense mapping, which means the font data
michael@0 20978 // lives glue together even if they are pretty far in the unicode
michael@0 20979 // table. (This looks weird, so I can have missed something), this
michael@0 20980 // works on Linux but seems to fails on Mac so let's rewrite the
michael@0 20981 // cmap table to a 3-1-4 style
michael@0 20982 var firstCode = font.getUint16();
michael@0 20983 var entryCount = font.getUint16();
michael@0 20984
michael@0 20985 for (j = 0; j < entryCount; j++) {
michael@0 20986 glyphId = font.getUint16();
michael@0 20987 var charCode = firstCode + j;
michael@0 20988
michael@0 20989 mappings.push({
michael@0 20990 charCode: charCode,
michael@0 20991 glyphId: glyphId
michael@0 20992 });
michael@0 20993 }
michael@0 20994 } else {
michael@0 20995 error('cmap table has unsupported format: ' + format);
michael@0 20996 }
michael@0 20997
michael@0 20998 // removing duplicate entries
michael@0 20999 mappings.sort(function (a, b) {
michael@0 21000 return a.charCode - b.charCode;
michael@0 21001 });
michael@0 21002 for (i = 1; i < mappings.length; i++) {
michael@0 21003 if (mappings[i - 1].charCode === mappings[i].charCode) {
michael@0 21004 mappings.splice(i, 1);
michael@0 21005 i--;
michael@0 21006 }
michael@0 21007 }
michael@0 21008
michael@0 21009 return {
michael@0 21010 platformId: potentialTable.platformId,
michael@0 21011 encodingId: potentialTable.encodingId,
michael@0 21012 mappings: mappings,
michael@0 21013 hasShortCmap: hasShortCmap
michael@0 21014 };
michael@0 21015 }
michael@0 21016
michael@0 21017 function sanitizeMetrics(font, header, metrics, numGlyphs) {
michael@0 21018 if (!header) {
michael@0 21019 if (metrics) {
michael@0 21020 metrics.data = null;
michael@0 21021 }
michael@0 21022 return;
michael@0 21023 }
michael@0 21024
michael@0 21025 font.pos = (font.start ? font.start : 0) + header.offset;
michael@0 21026 font.pos += header.length - 2;
michael@0 21027 var numOfMetrics = font.getUint16();
michael@0 21028
michael@0 21029 if (numOfMetrics > numGlyphs) {
michael@0 21030 info('The numOfMetrics (' + numOfMetrics + ') should not be ' +
michael@0 21031 'greater than the numGlyphs (' + numGlyphs + ')');
michael@0 21032 // Reduce numOfMetrics if it is greater than numGlyphs
michael@0 21033 numOfMetrics = numGlyphs;
michael@0 21034 header.data[34] = (numOfMetrics & 0xff00) >> 8;
michael@0 21035 header.data[35] = numOfMetrics & 0x00ff;
michael@0 21036 }
michael@0 21037
michael@0 21038 var numOfSidebearings = numGlyphs - numOfMetrics;
michael@0 21039 var numMissing = numOfSidebearings -
michael@0 21040 ((metrics.length - numOfMetrics * 4) >> 1);
michael@0 21041
michael@0 21042 var i, ii;
michael@0 21043 if (numMissing > 0) {
michael@0 21044 font.pos = (font.start ? font.start : 0) + metrics.offset;
michael@0 21045 var entries = '';
michael@0 21046 for (i = 0, ii = metrics.length; i < ii; i++) {
michael@0 21047 entries += String.fromCharCode(font.getByte());
michael@0 21048 }
michael@0 21049 for (i = 0; i < numMissing; i++) {
michael@0 21050 entries += '\x00\x00';
michael@0 21051 }
michael@0 21052 metrics.data = stringToArray(entries);
michael@0 21053 }
michael@0 21054 }
michael@0 21055
michael@0 21056 function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart,
michael@0 21057 hintsValid) {
michael@0 21058 if (sourceEnd - sourceStart <= 12) {
michael@0 21059 // glyph with data less than 12 is invalid one
michael@0 21060 return 0;
michael@0 21061 }
michael@0 21062 var glyf = source.subarray(sourceStart, sourceEnd);
michael@0 21063 var contoursCount = (glyf[0] << 8) | glyf[1];
michael@0 21064 if (contoursCount & 0x8000) {
michael@0 21065 // complex glyph, writing as is
michael@0 21066 dest.set(glyf, destStart);
michael@0 21067 return glyf.length;
michael@0 21068 }
michael@0 21069
michael@0 21070 var i, j = 10, flagsCount = 0;
michael@0 21071 for (i = 0; i < contoursCount; i++) {
michael@0 21072 var endPoint = (glyf[j] << 8) | glyf[j + 1];
michael@0 21073 flagsCount = endPoint + 1;
michael@0 21074 j += 2;
michael@0 21075 }
michael@0 21076 // skipping instructions
michael@0 21077 var instructionsStart = j;
michael@0 21078 var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
michael@0 21079 j += 2 + instructionsLength;
michael@0 21080 var instructionsEnd = j;
michael@0 21081 // validating flags
michael@0 21082 var coordinatesLength = 0;
michael@0 21083 for (i = 0; i < flagsCount; i++) {
michael@0 21084 var flag = glyf[j++];
michael@0 21085 if (flag & 0xC0) {
michael@0 21086 // reserved flags must be zero, cleaning up
michael@0 21087 glyf[j - 1] = flag & 0x3F;
michael@0 21088 }
michael@0 21089 var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) +
michael@0 21090 ((flag & 4) ? 1 : (flag & 32) ? 0 : 2);
michael@0 21091 coordinatesLength += xyLength;
michael@0 21092 if (flag & 8) {
michael@0 21093 var repeat = glyf[j++];
michael@0 21094 i += repeat;
michael@0 21095 coordinatesLength += repeat * xyLength;
michael@0 21096 }
michael@0 21097 }
michael@0 21098 // glyph without coordinates will be rejected
michael@0 21099 if (coordinatesLength === 0) {
michael@0 21100 return 0;
michael@0 21101 }
michael@0 21102 var glyphDataLength = j + coordinatesLength;
michael@0 21103 if (glyphDataLength > glyf.length) {
michael@0 21104 // not enough data for coordinates
michael@0 21105 return 0;
michael@0 21106 }
michael@0 21107 if (!hintsValid && instructionsLength > 0) {
michael@0 21108 dest.set(glyf.subarray(0, instructionsStart), destStart);
michael@0 21109 dest.set([0, 0], destStart + instructionsStart);
michael@0 21110 dest.set(glyf.subarray(instructionsEnd, glyphDataLength),
michael@0 21111 destStart + instructionsStart + 2);
michael@0 21112 glyphDataLength -= instructionsLength;
michael@0 21113 if (glyf.length - glyphDataLength > 3) {
michael@0 21114 glyphDataLength = (glyphDataLength + 3) & ~3;
michael@0 21115 }
michael@0 21116 return glyphDataLength;
michael@0 21117 }
michael@0 21118 if (glyf.length - glyphDataLength > 3) {
michael@0 21119 // truncating and aligning to 4 bytes the long glyph data
michael@0 21120 glyphDataLength = (glyphDataLength + 3) & ~3;
michael@0 21121 dest.set(glyf.subarray(0, glyphDataLength), destStart);
michael@0 21122 return glyphDataLength;
michael@0 21123 }
michael@0 21124 // glyph data is fine
michael@0 21125 dest.set(glyf, destStart);
michael@0 21126 return glyf.length;
michael@0 21127 }
michael@0 21128
michael@0 21129 function sanitizeHead(head, numGlyphs, locaLength) {
michael@0 21130 var data = head.data;
michael@0 21131
michael@0 21132 // Validate version:
michael@0 21133 // Should always be 0x00010000
michael@0 21134 var version = int32(data[0], data[1], data[2], data[3]);
michael@0 21135 if (version >> 16 !== 1) {
michael@0 21136 info('Attempting to fix invalid version in head table: ' + version);
michael@0 21137 data[0] = 0;
michael@0 21138 data[1] = 1;
michael@0 21139 data[2] = 0;
michael@0 21140 data[3] = 0;
michael@0 21141 }
michael@0 21142
michael@0 21143 var indexToLocFormat = int16(data[50], data[51]);
michael@0 21144 if (indexToLocFormat < 0 || indexToLocFormat > 1) {
michael@0 21145 info('Attempting to fix invalid indexToLocFormat in head table: ' +
michael@0 21146 indexToLocFormat);
michael@0 21147
michael@0 21148 // The value of indexToLocFormat should be 0 if the loca table
michael@0 21149 // consists of short offsets, and should be 1 if the loca table
michael@0 21150 // consists of long offsets.
michael@0 21151 //
michael@0 21152 // The number of entries in the loca table should be numGlyphs + 1.
michael@0 21153 //
michael@0 21154 // Using this information, we can work backwards to deduce if the
michael@0 21155 // size of each offset in the loca table, and thus figure out the
michael@0 21156 // appropriate value for indexToLocFormat.
michael@0 21157
michael@0 21158 var numGlyphsPlusOne = numGlyphs + 1;
michael@0 21159 if (locaLength === numGlyphsPlusOne << 1) {
michael@0 21160 // 0x0000 indicates the loca table consists of short offsets
michael@0 21161 data[50] = 0;
michael@0 21162 data[51] = 0;
michael@0 21163 } else if (locaLength === numGlyphsPlusOne << 2) {
michael@0 21164 // 0x0001 indicates the loca table consists of long offsets
michael@0 21165 data[50] = 0;
michael@0 21166 data[51] = 1;
michael@0 21167 } else {
michael@0 21168 warn('Could not fix indexToLocFormat: ' + indexToLocFormat);
michael@0 21169 }
michael@0 21170 }
michael@0 21171 }
michael@0 21172
michael@0 21173 function sanitizeGlyphLocations(loca, glyf, numGlyphs,
michael@0 21174 isGlyphLocationsLong, hintsValid,
michael@0 21175 dupFirstEntry) {
michael@0 21176 var itemSize, itemDecode, itemEncode;
michael@0 21177 if (isGlyphLocationsLong) {
michael@0 21178 itemSize = 4;
michael@0 21179 itemDecode = function fontItemDecodeLong(data, offset) {
michael@0 21180 return (data[offset] << 24) | (data[offset + 1] << 16) |
michael@0 21181 (data[offset + 2] << 8) | data[offset + 3];
michael@0 21182 };
michael@0 21183 itemEncode = function fontItemEncodeLong(data, offset, value) {
michael@0 21184 data[offset] = (value >>> 24) & 0xFF;
michael@0 21185 data[offset + 1] = (value >> 16) & 0xFF;
michael@0 21186 data[offset + 2] = (value >> 8) & 0xFF;
michael@0 21187 data[offset + 3] = value & 0xFF;
michael@0 21188 };
michael@0 21189 } else {
michael@0 21190 itemSize = 2;
michael@0 21191 itemDecode = function fontItemDecode(data, offset) {
michael@0 21192 return (data[offset] << 9) | (data[offset + 1] << 1);
michael@0 21193 };
michael@0 21194 itemEncode = function fontItemEncode(data, offset, value) {
michael@0 21195 data[offset] = (value >> 9) & 0xFF;
michael@0 21196 data[offset + 1] = (value >> 1) & 0xFF;
michael@0 21197 };
michael@0 21198 }
michael@0 21199 var locaData = loca.data;
michael@0 21200 var locaDataSize = itemSize * (1 + numGlyphs);
michael@0 21201 // is loca.data too short or long?
michael@0 21202 if (locaData.length !== locaDataSize) {
michael@0 21203 locaData = new Uint8Array(locaDataSize);
michael@0 21204 locaData.set(loca.data.subarray(0, locaDataSize));
michael@0 21205 loca.data = locaData;
michael@0 21206 }
michael@0 21207 // removing the invalid glyphs
michael@0 21208 var oldGlyfData = glyf.data;
michael@0 21209 var oldGlyfDataLength = oldGlyfData.length;
michael@0 21210 var newGlyfData = new Uint8Array(oldGlyfDataLength);
michael@0 21211 var startOffset = itemDecode(locaData, 0);
michael@0 21212 var writeOffset = 0;
michael@0 21213 itemEncode(locaData, 0, writeOffset);
michael@0 21214 var i, j;
michael@0 21215 for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
michael@0 21216 var endOffset = itemDecode(locaData, j);
michael@0 21217 if (endOffset > oldGlyfDataLength &&
michael@0 21218 ((oldGlyfDataLength + 3) & ~3) === endOffset) {
michael@0 21219 // Aspose breaks fonts by aligning the glyphs to the qword, but not
michael@0 21220 // the glyf table size, which makes last glyph out of range.
michael@0 21221 endOffset = oldGlyfDataLength;
michael@0 21222 }
michael@0 21223 if (endOffset > oldGlyfDataLength) {
michael@0 21224 // glyph end offset points outside glyf data, rejecting the glyph
michael@0 21225 itemEncode(locaData, j, writeOffset);
michael@0 21226 startOffset = endOffset;
michael@0 21227 continue;
michael@0 21228 }
michael@0 21229
michael@0 21230 var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
michael@0 21231 newGlyfData, writeOffset, hintsValid);
michael@0 21232 writeOffset += newLength;
michael@0 21233 itemEncode(locaData, j, writeOffset);
michael@0 21234 startOffset = endOffset;
michael@0 21235 }
michael@0 21236
michael@0 21237 if (writeOffset === 0) {
michael@0 21238 // glyf table cannot be empty -- redoing the glyf and loca tables
michael@0 21239 // to have single glyph with one point
michael@0 21240 var simpleGlyph = new Uint8Array(
michael@0 21241 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]);
michael@0 21242 for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
michael@0 21243 itemEncode(locaData, j, simpleGlyph.length);
michael@0 21244 }
michael@0 21245 glyf.data = simpleGlyph;
michael@0 21246 return;
michael@0 21247 }
michael@0 21248
michael@0 21249 if (dupFirstEntry) {
michael@0 21250 var firstEntryLength = itemDecode(locaData, itemSize);
michael@0 21251 if (newGlyfData.length > firstEntryLength + writeOffset) {
michael@0 21252 glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
michael@0 21253 } else {
michael@0 21254 glyf.data = new Uint8Array(firstEntryLength + writeOffset);
michael@0 21255 glyf.data.set(newGlyfData.subarray(0, writeOffset));
michael@0 21256 }
michael@0 21257 glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);
michael@0 21258 itemEncode(loca.data, locaData.length - itemSize,
michael@0 21259 writeOffset + firstEntryLength);
michael@0 21260 } else {
michael@0 21261 glyf.data = newGlyfData.subarray(0, writeOffset);
michael@0 21262 }
michael@0 21263 }
michael@0 21264
michael@0 21265 function readPostScriptTable(post, properties, maxpNumGlyphs) {
michael@0 21266 var start = (font.start ? font.start : 0) + post.offset;
michael@0 21267 font.pos = start;
michael@0 21268
michael@0 21269 var length = post.length, end = start + length;
michael@0 21270 var version = font.getInt32();
michael@0 21271 // skip rest to the tables
michael@0 21272 font.getBytes(28);
michael@0 21273
michael@0 21274 var glyphNames;
michael@0 21275 var valid = true;
michael@0 21276 var i;
michael@0 21277
michael@0 21278 switch (version) {
michael@0 21279 case 0x00010000:
michael@0 21280 glyphNames = MacStandardGlyphOrdering;
michael@0 21281 break;
michael@0 21282 case 0x00020000:
michael@0 21283 var numGlyphs = font.getUint16();
michael@0 21284 if (numGlyphs != maxpNumGlyphs) {
michael@0 21285 valid = false;
michael@0 21286 break;
michael@0 21287 }
michael@0 21288 var glyphNameIndexes = [];
michael@0 21289 for (i = 0; i < numGlyphs; ++i) {
michael@0 21290 var index = font.getUint16();
michael@0 21291 if (index >= 32768) {
michael@0 21292 valid = false;
michael@0 21293 break;
michael@0 21294 }
michael@0 21295 glyphNameIndexes.push(index);
michael@0 21296 }
michael@0 21297 if (!valid) {
michael@0 21298 break;
michael@0 21299 }
michael@0 21300 var customNames = [];
michael@0 21301 while (font.pos < end) {
michael@0 21302 var stringLength = font.getByte();
michael@0 21303 var string = '';
michael@0 21304 for (i = 0; i < stringLength; ++i) {
michael@0 21305 string += String.fromCharCode(font.getByte());
michael@0 21306 }
michael@0 21307 customNames.push(string);
michael@0 21308 }
michael@0 21309 glyphNames = [];
michael@0 21310 for (i = 0; i < numGlyphs; ++i) {
michael@0 21311 var j = glyphNameIndexes[i];
michael@0 21312 if (j < 258) {
michael@0 21313 glyphNames.push(MacStandardGlyphOrdering[j]);
michael@0 21314 continue;
michael@0 21315 }
michael@0 21316 glyphNames.push(customNames[j - 258]);
michael@0 21317 }
michael@0 21318 break;
michael@0 21319 case 0x00030000:
michael@0 21320 break;
michael@0 21321 default:
michael@0 21322 warn('Unknown/unsupported post table version ' + version);
michael@0 21323 valid = false;
michael@0 21324 break;
michael@0 21325 }
michael@0 21326 properties.glyphNames = glyphNames;
michael@0 21327 return valid;
michael@0 21328 }
michael@0 21329
michael@0 21330 function readNameTable(nameTable) {
michael@0 21331 var start = (font.start ? font.start : 0) + nameTable.offset;
michael@0 21332 font.pos = start;
michael@0 21333
michael@0 21334 var names = [[], []];
michael@0 21335 var length = nameTable.length, end = start + length;
michael@0 21336 var format = font.getUint16();
michael@0 21337 var FORMAT_0_HEADER_LENGTH = 6;
michael@0 21338 if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) {
michael@0 21339 // unsupported name table format or table "too" small
michael@0 21340 return names;
michael@0 21341 }
michael@0 21342 var numRecords = font.getUint16();
michael@0 21343 var stringsStart = font.getUint16();
michael@0 21344 var records = [];
michael@0 21345 var NAME_RECORD_LENGTH = 12;
michael@0 21346 var i, ii;
michael@0 21347
michael@0 21348 for (i = 0; i < numRecords &&
michael@0 21349 font.pos + NAME_RECORD_LENGTH <= end; i++) {
michael@0 21350 var r = {
michael@0 21351 platform: font.getUint16(),
michael@0 21352 encoding: font.getUint16(),
michael@0 21353 language: font.getUint16(),
michael@0 21354 name: font.getUint16(),
michael@0 21355 length: font.getUint16(),
michael@0 21356 offset: font.getUint16()
michael@0 21357 };
michael@0 21358 // using only Macintosh and Windows platform/encoding names
michael@0 21359 if ((r.platform == 1 && r.encoding === 0 && r.language === 0) ||
michael@0 21360 (r.platform == 3 && r.encoding == 1 && r.language == 0x409)) {
michael@0 21361 records.push(r);
michael@0 21362 }
michael@0 21363 }
michael@0 21364 for (i = 0, ii = records.length; i < ii; i++) {
michael@0 21365 var record = records[i];
michael@0 21366 var pos = start + stringsStart + record.offset;
michael@0 21367 if (pos + record.length > end) {
michael@0 21368 continue; // outside of name table, ignoring
michael@0 21369 }
michael@0 21370 font.pos = pos;
michael@0 21371 var nameIndex = record.name;
michael@0 21372 if (record.encoding) {
michael@0 21373 // unicode
michael@0 21374 var str = '';
michael@0 21375 for (var j = 0, jj = record.length; j < jj; j += 2) {
michael@0 21376 str += String.fromCharCode(font.getUint16());
michael@0 21377 }
michael@0 21378 names[1][nameIndex] = str;
michael@0 21379 } else {
michael@0 21380 names[0][nameIndex] = bytesToString(font.getBytes(record.length));
michael@0 21381 }
michael@0 21382 }
michael@0 21383 return names;
michael@0 21384 }
michael@0 21385
michael@0 21386 var TTOpsStackDeltas = [
michael@0 21387 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5,
michael@0 21388 -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1,
michael@0 21389 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1,
michael@0 21390 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2,
michael@0 21391 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1,
michael@0 21392 -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1,
michael@0 21393 -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
michael@0 21394 -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1,
michael@0 21395 -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2];
michael@0 21396 // 0xC0-DF == -1 and 0xE0-FF == -2
michael@0 21397
michael@0 21398 function sanitizeTTProgram(table, ttContext) {
michael@0 21399 var data = table.data;
michael@0 21400 var i = 0, j, n, b, funcId, pc, lastEndf = 0, lastDeff = 0;
michael@0 21401 var stack = [];
michael@0 21402 var callstack = [];
michael@0 21403 var functionsCalled = [];
michael@0 21404 var tooComplexToFollowFunctions =
michael@0 21405 ttContext.tooComplexToFollowFunctions;
michael@0 21406 var inFDEF = false, ifLevel = 0, inELSE = 0;
michael@0 21407 for (var ii = data.length; i < ii;) {
michael@0 21408 var op = data[i++];
michael@0 21409 // The TrueType instruction set docs can be found at
michael@0 21410 // https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html
michael@0 21411 if (op === 0x40) { // NPUSHB - pushes n bytes
michael@0 21412 n = data[i++];
michael@0 21413 if (inFDEF || inELSE) {
michael@0 21414 i += n;
michael@0 21415 } else {
michael@0 21416 for (j = 0; j < n; j++) {
michael@0 21417 stack.push(data[i++]);
michael@0 21418 }
michael@0 21419 }
michael@0 21420 } else if (op === 0x41) { // NPUSHW - pushes n words
michael@0 21421 n = data[i++];
michael@0 21422 if (inFDEF || inELSE) {
michael@0 21423 i += n * 2;
michael@0 21424 } else {
michael@0 21425 for (j = 0; j < n; j++) {
michael@0 21426 b = data[i++];
michael@0 21427 stack.push((b << 8) | data[i++]);
michael@0 21428 }
michael@0 21429 }
michael@0 21430 } else if ((op & 0xF8) === 0xB0) { // PUSHB - pushes bytes
michael@0 21431 n = op - 0xB0 + 1;
michael@0 21432 if (inFDEF || inELSE) {
michael@0 21433 i += n;
michael@0 21434 } else {
michael@0 21435 for (j = 0; j < n; j++) {
michael@0 21436 stack.push(data[i++]);
michael@0 21437 }
michael@0 21438 }
michael@0 21439 } else if ((op & 0xF8) === 0xB8) { // PUSHW - pushes words
michael@0 21440 n = op - 0xB8 + 1;
michael@0 21441 if (inFDEF || inELSE) {
michael@0 21442 i += n * 2;
michael@0 21443 } else {
michael@0 21444 for (j = 0; j < n; j++) {
michael@0 21445 b = data[i++];
michael@0 21446 stack.push((b << 8) | data[i++]);
michael@0 21447 }
michael@0 21448 }
michael@0 21449 } else if (op === 0x2B && !tooComplexToFollowFunctions) { // CALL
michael@0 21450 if (!inFDEF && !inELSE) {
michael@0 21451 // collecting inforamtion about which functions are used
michael@0 21452 funcId = stack[stack.length - 1];
michael@0 21453 ttContext.functionsUsed[funcId] = true;
michael@0 21454 if (funcId in ttContext.functionsStackDeltas) {
michael@0 21455 stack.length += ttContext.functionsStackDeltas[funcId];
michael@0 21456 } else if (funcId in ttContext.functionsDefined &&
michael@0 21457 functionsCalled.indexOf(funcId) < 0) {
michael@0 21458 callstack.push({data: data, i: i, stackTop: stack.length - 1});
michael@0 21459 functionsCalled.push(funcId);
michael@0 21460 pc = ttContext.functionsDefined[funcId];
michael@0 21461 if (!pc) {
michael@0 21462 warn('TT: CALL non-existent function');
michael@0 21463 ttContext.hintsValid = false;
michael@0 21464 return;
michael@0 21465 }
michael@0 21466 data = pc.data;
michael@0 21467 i = pc.i;
michael@0 21468 }
michael@0 21469 }
michael@0 21470 } else if (op === 0x2C && !tooComplexToFollowFunctions) { // FDEF
michael@0 21471 if (inFDEF || inELSE) {
michael@0 21472 warn('TT: nested FDEFs not allowed');
michael@0 21473 tooComplexToFollowFunctions = true;
michael@0 21474 }
michael@0 21475 inFDEF = true;
michael@0 21476 // collecting inforamtion about which functions are defined
michael@0 21477 lastDeff = i;
michael@0 21478 funcId = stack.pop();
michael@0 21479 ttContext.functionsDefined[funcId] = {data: data, i: i};
michael@0 21480 } else if (op === 0x2D) { // ENDF - end of function
michael@0 21481 if (inFDEF) {
michael@0 21482 inFDEF = false;
michael@0 21483 lastEndf = i;
michael@0 21484 } else {
michael@0 21485 pc = callstack.pop();
michael@0 21486 if (!pc) {
michael@0 21487 warn('TT: ENDF bad stack');
michael@0 21488 ttContext.hintsValid = false;
michael@0 21489 return;
michael@0 21490 }
michael@0 21491 funcId = functionsCalled.pop();
michael@0 21492 data = pc.data;
michael@0 21493 i = pc.i;
michael@0 21494 ttContext.functionsStackDeltas[funcId] =
michael@0 21495 stack.length - pc.stackTop;
michael@0 21496 }
michael@0 21497 } else if (op === 0x89) { // IDEF - instruction definition
michael@0 21498 if (inFDEF || inELSE) {
michael@0 21499 warn('TT: nested IDEFs not allowed');
michael@0 21500 tooComplexToFollowFunctions = true;
michael@0 21501 }
michael@0 21502 inFDEF = true;
michael@0 21503 // recording it as a function to track ENDF
michael@0 21504 lastDeff = i;
michael@0 21505 } else if (op === 0x58) { // IF
michael@0 21506 ++ifLevel;
michael@0 21507 } else if (op === 0x1B) { // ELSE
michael@0 21508 inELSE = ifLevel;
michael@0 21509 } else if (op === 0x59) { // EIF
michael@0 21510 if (inELSE === ifLevel) {
michael@0 21511 inELSE = 0;
michael@0 21512 }
michael@0 21513 --ifLevel;
michael@0 21514 } else if (op === 0x1C) { // JMPR
michael@0 21515 if (!inFDEF && !inELSE) {
michael@0 21516 var offset = stack[stack.length - 1];
michael@0 21517 // only jumping forward to prevent infinite loop
michael@0 21518 if (offset > 0) {
michael@0 21519 i += offset - 1;
michael@0 21520 }
michael@0 21521 }
michael@0 21522 }
michael@0 21523 // Adjusting stack not extactly, but just enough to get function id
michael@0 21524 if (!inFDEF && !inELSE) {
michael@0 21525 var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] :
michael@0 21526 op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0;
michael@0 21527 if (op >= 0x71 && op <= 0x75) {
michael@0 21528 n = stack.pop();
michael@0 21529 if (n === n) {
michael@0 21530 stackDelta = -n * 2;
michael@0 21531 }
michael@0 21532 }
michael@0 21533 while (stackDelta < 0 && stack.length > 0) {
michael@0 21534 stack.pop();
michael@0 21535 stackDelta++;
michael@0 21536 }
michael@0 21537 while (stackDelta > 0) {
michael@0 21538 stack.push(NaN); // pushing any number into stack
michael@0 21539 stackDelta--;
michael@0 21540 }
michael@0 21541 }
michael@0 21542 }
michael@0 21543 ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions;
michael@0 21544 var content = [data];
michael@0 21545 if (i > data.length) {
michael@0 21546 content.push(new Uint8Array(i - data.length));
michael@0 21547 }
michael@0 21548 if (lastDeff > lastEndf) {
michael@0 21549 warn('TT: complementing a missing function tail');
michael@0 21550 // new function definition started, but not finished
michael@0 21551 // complete function by [CLEAR, ENDF]
michael@0 21552 content.push(new Uint8Array([0x22, 0x2D]));
michael@0 21553 }
michael@0 21554 foldTTTable(table, content);
michael@0 21555 }
michael@0 21556
michael@0 21557 function checkInvalidFunctions(ttContext, maxFunctionDefs) {
michael@0 21558 if (ttContext.tooComplexToFollowFunctions) {
michael@0 21559 return;
michael@0 21560 }
michael@0 21561 if (ttContext.functionsDefined.length > maxFunctionDefs) {
michael@0 21562 warn('TT: more functions defined than expected');
michael@0 21563 ttContext.hintsValid = false;
michael@0 21564 return;
michael@0 21565 }
michael@0 21566 for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) {
michael@0 21567 if (j > maxFunctionDefs) {
michael@0 21568 warn('TT: invalid function id: ' + j);
michael@0 21569 ttContext.hintsValid = false;
michael@0 21570 return;
michael@0 21571 }
michael@0 21572 if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) {
michael@0 21573 warn('TT: undefined function: ' + j);
michael@0 21574 ttContext.hintsValid = false;
michael@0 21575 return;
michael@0 21576 }
michael@0 21577 }
michael@0 21578 }
michael@0 21579
michael@0 21580 function foldTTTable(table, content) {
michael@0 21581 if (content.length > 1) {
michael@0 21582 // concatenating the content items
michael@0 21583 var newLength = 0;
michael@0 21584 var j, jj;
michael@0 21585 for (j = 0, jj = content.length; j < jj; j++) {
michael@0 21586 newLength += content[j].length;
michael@0 21587 }
michael@0 21588 newLength = (newLength + 3) & ~3;
michael@0 21589 var result = new Uint8Array(newLength);
michael@0 21590 var pos = 0;
michael@0 21591 for (j = 0, jj = content.length; j < jj; j++) {
michael@0 21592 result.set(content[j], pos);
michael@0 21593 pos += content[j].length;
michael@0 21594 }
michael@0 21595 table.data = result;
michael@0 21596 table.length = newLength;
michael@0 21597 }
michael@0 21598 }
michael@0 21599
michael@0 21600 function sanitizeTTPrograms(fpgm, prep, cvt) {
michael@0 21601 var ttContext = {
michael@0 21602 functionsDefined: [],
michael@0 21603 functionsUsed: [],
michael@0 21604 functionsStackDeltas: [],
michael@0 21605 tooComplexToFollowFunctions: false,
michael@0 21606 hintsValid: true
michael@0 21607 };
michael@0 21608 if (fpgm) {
michael@0 21609 sanitizeTTProgram(fpgm, ttContext);
michael@0 21610 }
michael@0 21611 if (prep) {
michael@0 21612 sanitizeTTProgram(prep, ttContext);
michael@0 21613 }
michael@0 21614 if (fpgm) {
michael@0 21615 checkInvalidFunctions(ttContext, maxFunctionDefs);
michael@0 21616 }
michael@0 21617 if (cvt && (cvt.length & 1)) {
michael@0 21618 var cvtData = new Uint8Array(cvt.length + 1);
michael@0 21619 cvtData.set(cvt.data);
michael@0 21620 cvt.data = cvtData;
michael@0 21621 }
michael@0 21622 return ttContext.hintsValid;
michael@0 21623 }
michael@0 21624
michael@0 21625 // The following steps modify the original font data, making copy
michael@0 21626 font = new Stream(new Uint8Array(font.getBytes()));
michael@0 21627
michael@0 21628 var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp',
michael@0 21629 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF '];
michael@0 21630
michael@0 21631 var header = readOpenTypeHeader(font);
michael@0 21632 var numTables = header.numTables;
michael@0 21633 var cff, cffFile;
michael@0 21634
michael@0 21635 var tables = { 'OS/2': null, cmap: null, head: null, hhea: null,
michael@0 21636 hmtx: null, maxp: null, name: null, post: null };
michael@0 21637 var table, tableData;
michael@0 21638 for (var i = 0; i < numTables; i++) {
michael@0 21639 table = readTableEntry(font);
michael@0 21640 if (VALID_TABLES.indexOf(table.tag) < 0) {
michael@0 21641 continue; // skipping table if it's not a required or optional table
michael@0 21642 }
michael@0 21643 if (table.length === 0) {
michael@0 21644 continue; // skipping empty tables
michael@0 21645 }
michael@0 21646 tables[table.tag] = table;
michael@0 21647 }
michael@0 21648
michael@0 21649 var isTrueType = !tables['CFF '];
michael@0 21650 if (!isTrueType) {
michael@0 21651 // OpenType font
michael@0 21652 if (!tables.head || !tables.hhea || !tables.maxp || !tables.post) {
michael@0 21653 // no major tables: throwing everything at CFFFont
michael@0 21654 cffFile = new Stream(tables['CFF '].data);
michael@0 21655 cff = new CFFFont(cffFile, properties);
michael@0 21656
michael@0 21657 return this.convert(name, cff, properties);
michael@0 21658 }
michael@0 21659
michael@0 21660 delete tables.glyf;
michael@0 21661 delete tables.loca;
michael@0 21662 delete tables.fpgm;
michael@0 21663 delete tables.prep;
michael@0 21664 delete tables['cvt '];
michael@0 21665 } else {
michael@0 21666 if (!tables.glyf || !tables.loca) {
michael@0 21667 error('Required "glyf" or "loca" tables are not found');
michael@0 21668 }
michael@0 21669 }
michael@0 21670
michael@0 21671 if (!tables.maxp) {
michael@0 21672 error('Required "maxp" table is not found');
michael@0 21673 }
michael@0 21674
michael@0 21675 font.pos = (font.start || 0) + tables.maxp.offset;
michael@0 21676 var version = font.getInt32();
michael@0 21677 var numGlyphs = font.getUint16();
michael@0 21678 var maxFunctionDefs = 0;
michael@0 21679 if (version >= 0x00010000 && tables.maxp.length >= 22) {
michael@0 21680 // maxZones can be invalid
michael@0 21681 font.pos += 8;
michael@0 21682 var maxZones = font.getUint16();
michael@0 21683 if (maxZones > 2) { // reset to 2 if font has invalid maxZones
michael@0 21684 tables.maxp.data[14] = 0;
michael@0 21685 tables.maxp.data[15] = 2;
michael@0 21686 }
michael@0 21687 font.pos += 4;
michael@0 21688 maxFunctionDefs = font.getUint16();
michael@0 21689 }
michael@0 21690
michael@0 21691 var dupFirstEntry = false;
michael@0 21692 if (properties.type == 'CIDFontType2' && properties.toUnicode &&
michael@0 21693 properties.toUnicode[0] > '\u0000') {
michael@0 21694 // oracle's defect (see 3427), duplicating first entry
michael@0 21695 dupFirstEntry = true;
michael@0 21696 numGlyphs++;
michael@0 21697 tables.maxp.data[4] = numGlyphs >> 8;
michael@0 21698 tables.maxp.data[5] = numGlyphs & 255;
michael@0 21699 }
michael@0 21700
michael@0 21701 var hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep,
michael@0 21702 tables['cvt '], maxFunctionDefs);
michael@0 21703 if (!hintsValid) {
michael@0 21704 delete tables.fpgm;
michael@0 21705 delete tables.prep;
michael@0 21706 delete tables['cvt '];
michael@0 21707 }
michael@0 21708
michael@0 21709 // Tables needs to be written by ascendant alphabetic order
michael@0 21710 var tablesNames = Object.keys(tables);
michael@0 21711 tablesNames.sort();
michael@0 21712
michael@0 21713 numTables = tablesNames.length;
michael@0 21714
michael@0 21715 // header and new offsets. Table entry information is appended to the
michael@0 21716 // end of file. The virtualOffset represents where to put the actual
michael@0 21717 // data of a particular table;
michael@0 21718 var ttf = {
michael@0 21719 file: '',
michael@0 21720 virtualOffset: numTables * (4 * 4)
michael@0 21721 };
michael@0 21722
michael@0 21723 // The new numbers of tables will be the last one plus the num
michael@0 21724 // of missing tables
michael@0 21725 createOpenTypeHeader(header.version, ttf, numTables);
michael@0 21726
michael@0 21727 // Ensure the hmtx table contains the advance width and
michael@0 21728 // sidebearings information for numGlyphs in the maxp table
michael@0 21729 sanitizeMetrics(font, tables.hhea, tables.hmtx, numGlyphs);
michael@0 21730
michael@0 21731 if (!tables.head) {
michael@0 21732 error('Required "head" table is not found');
michael@0 21733 }
michael@0 21734
michael@0 21735 sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0);
michael@0 21736
michael@0 21737 if (isTrueType) {
michael@0 21738 var isGlyphLocationsLong = int16(tables.head.data[50],
michael@0 21739 tables.head.data[51]);
michael@0 21740 sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs,
michael@0 21741 isGlyphLocationsLong, hintsValid, dupFirstEntry);
michael@0 21742 }
michael@0 21743
michael@0 21744 if (!tables.hhea) {
michael@0 21745 error('Required "hhea" table is not found');
michael@0 21746 }
michael@0 21747
michael@0 21748 // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
michael@0 21749 // Sometimes it's 0. That needs to be fixed
michael@0 21750 if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) {
michael@0 21751 tables.hhea.data[10] = 0xFF;
michael@0 21752 tables.hhea.data[11] = 0xFF;
michael@0 21753 }
michael@0 21754
michael@0 21755 // The 'post' table has glyphs names.
michael@0 21756 if (tables.post) {
michael@0 21757 var valid = readPostScriptTable(tables.post, properties, numGlyphs);
michael@0 21758 if (!valid) {
michael@0 21759 tables.post = null;
michael@0 21760 }
michael@0 21761 }
michael@0 21762
michael@0 21763 var charCodeToGlyphId = [], charCode;
michael@0 21764 if (properties.type == 'CIDFontType2') {
michael@0 21765 var cidToGidMap = properties.cidToGidMap || [];
michael@0 21766 var cMap = properties.cMap.map;
michael@0 21767 for (charCode in cMap) {
michael@0 21768 charCode |= 0;
michael@0 21769 var cid = cMap[charCode];
michael@0 21770 assert(cid.length === 1, 'Max size of CID is 65,535');
michael@0 21771 cid = cid.charCodeAt(0);
michael@0 21772 var glyphId = -1;
michael@0 21773 if (cidToGidMap.length === 0) {
michael@0 21774 glyphId = charCode;
michael@0 21775 } else if (cid in cidToGidMap) {
michael@0 21776 glyphId = cidToGidMap[cid];
michael@0 21777 }
michael@0 21778 if (glyphId >= 0 && glyphId < numGlyphs) {
michael@0 21779 charCodeToGlyphId[charCode] = glyphId;
michael@0 21780 }
michael@0 21781 }
michael@0 21782 if (dupFirstEntry) {
michael@0 21783 charCodeToGlyphId[0] = numGlyphs - 1;
michael@0 21784 }
michael@0 21785 } else {
michael@0 21786 // Most of the following logic in this code branch is based on the
michael@0 21787 // 9.6.6.4 of the PDF spec.
michael@0 21788 var cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont);
michael@0 21789 var cmapPlatformId = cmapTable.platformId;
michael@0 21790 var cmapEncodingId = cmapTable.encodingId;
michael@0 21791 var cmapMappings = cmapTable.mappings;
michael@0 21792 var cmapMappingsLength = cmapMappings.length;
michael@0 21793 var hasEncoding = properties.differences.length ||
michael@0 21794 !!properties.baseEncodingName;
michael@0 21795
michael@0 21796 // The spec seems to imply that if the font is symbolic the encoding
michael@0 21797 // should be ignored, this doesn't appear to work for 'preistabelle.pdf'
michael@0 21798 // where the the font is symbolic and it has an encoding.
michael@0 21799 if (hasEncoding &&
michael@0 21800 (cmapPlatformId === 3 && cmapEncodingId === 1 ||
michael@0 21801 cmapPlatformId === 1 && cmapEncodingId === 0)) {
michael@0 21802 var baseEncoding = [];
michael@0 21803 if (properties.baseEncodingName === 'MacRomanEncoding' ||
michael@0 21804 properties.baseEncodingName === 'WinAnsiEncoding') {
michael@0 21805 baseEncoding = Encodings[properties.baseEncodingName];
michael@0 21806 }
michael@0 21807 for (charCode = 0; charCode < 256; charCode++) {
michael@0 21808 var glyphName;
michael@0 21809 if (this.differences && charCode in this.differences) {
michael@0 21810 glyphName = this.differences[charCode];
michael@0 21811 } else if (charCode in baseEncoding &&
michael@0 21812 baseEncoding[charCode] !== '') {
michael@0 21813 glyphName = baseEncoding[charCode];
michael@0 21814 } else {
michael@0 21815 glyphName = Encodings.StandardEncoding[charCode];
michael@0 21816 }
michael@0 21817 if (!glyphName) {
michael@0 21818 continue;
michael@0 21819 }
michael@0 21820 var unicodeOrCharCode;
michael@0 21821 if (cmapPlatformId === 3 && cmapEncodingId === 1) {
michael@0 21822 unicodeOrCharCode = GlyphsUnicode[glyphName];
michael@0 21823 } else if (cmapPlatformId === 1 && cmapEncodingId === 0) {
michael@0 21824 // TODO: the encoding needs to be updated with mac os table.
michael@0 21825 unicodeOrCharCode = Encodings.MacRomanEncoding.indexOf(glyphName);
michael@0 21826 }
michael@0 21827
michael@0 21828 var found = false;
michael@0 21829 for (i = 0; i < cmapMappingsLength; ++i) {
michael@0 21830 if (cmapMappings[i].charCode === unicodeOrCharCode) {
michael@0 21831 charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
michael@0 21832 found = true;
michael@0 21833 break;
michael@0 21834 }
michael@0 21835 }
michael@0 21836 if (!found && properties.glyphNames) {
michael@0 21837 // Try to map using the post table. There are currently no known
michael@0 21838 // pdfs that this fixes.
michael@0 21839 glyphId = properties.glyphNames.indexOf(glyphName);
michael@0 21840 if (glyphId > 0) {
michael@0 21841 charCodeToGlyphId[charCode] = glyphId;
michael@0 21842 }
michael@0 21843 }
michael@0 21844 }
michael@0 21845 } else {
michael@0 21846 // For (3, 0) cmap tables:
michael@0 21847 // The charcode key being stored in charCodeToGlyphId is the lower
michael@0 21848 // byte of the two-byte charcodes of the cmap table since according to
michael@0 21849 // the spec: 'each byte from the string shall be prepended with the
michael@0 21850 // high byte of the range [of charcodes in the cmap table], to form
michael@0 21851 // a two-byte character, which shall be used to select the
michael@0 21852 // associated glyph description from the subtable'.
michael@0 21853 //
michael@0 21854 // For (1, 0) cmap tables:
michael@0 21855 // 'single bytes from the string shall be used to look up the
michael@0 21856 // associated glyph descriptions from the subtable'. This means
michael@0 21857 // charcodes in the cmap will be single bytes, so no-op since
michael@0 21858 // glyph.charCode & 0xFF === glyph.charCode
michael@0 21859 for (i = 0; i < cmapMappingsLength; ++i) {
michael@0 21860 charCode = cmapMappings[i].charCode & 0xFF;
michael@0 21861 charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
michael@0 21862 }
michael@0 21863 }
michael@0 21864 }
michael@0 21865
michael@0 21866 if (charCodeToGlyphId.length === 0) {
michael@0 21867 // defines at least one glyph
michael@0 21868 charCodeToGlyphId[0] = 0;
michael@0 21869 }
michael@0 21870
michael@0 21871 // Converting glyphs and ids into font's cmap table
michael@0 21872 var newMapping = adjustMapping(charCodeToGlyphId, properties);
michael@0 21873 this.toFontChar = newMapping.toFontChar;
michael@0 21874 tables.cmap = {
michael@0 21875 tag: 'cmap',
michael@0 21876 data: createCmapTable(newMapping.charCodeToGlyphId)
michael@0 21877 };
michael@0 21878
michael@0 21879 if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) {
michael@0 21880 // extract some more font properties from the OpenType head and
michael@0 21881 // hhea tables; yMin and descent value are always negative
michael@0 21882 var override = {
michael@0 21883 unitsPerEm: int16(tables.head.data[18], tables.head.data[19]),
michael@0 21884 yMax: int16(tables.head.data[42], tables.head.data[43]),
michael@0 21885 yMin: int16(tables.head.data[38], tables.head.data[39]) - 0x10000,
michael@0 21886 ascent: int16(tables.hhea.data[4], tables.hhea.data[5]),
michael@0 21887 descent: int16(tables.hhea.data[6], tables.hhea.data[7]) - 0x10000
michael@0 21888 };
michael@0 21889
michael@0 21890 tables['OS/2'] = {
michael@0 21891 tag: 'OS/2',
michael@0 21892 data: stringToArray(createOS2Table(properties,
michael@0 21893 newMapping.charCodeToGlyphId,
michael@0 21894 override))
michael@0 21895 };
michael@0 21896 }
michael@0 21897
michael@0 21898 // Rewrite the 'post' table if needed
michael@0 21899 if (!tables.post) {
michael@0 21900 tables.post = {
michael@0 21901 tag: 'post',
michael@0 21902 data: stringToArray(createPostTable(properties))
michael@0 21903 };
michael@0 21904 }
michael@0 21905
michael@0 21906 if (!isTrueType) {
michael@0 21907 try {
michael@0 21908 // Trying to repair CFF file
michael@0 21909 cffFile = new Stream(tables['CFF '].data);
michael@0 21910 var parser = new CFFParser(cffFile, properties);
michael@0 21911 cff = parser.parse();
michael@0 21912 var compiler = new CFFCompiler(cff);
michael@0 21913 tables['CFF '].data = compiler.compile();
michael@0 21914 } catch (e) {
michael@0 21915 warn('Failed to compile font ' + properties.loadedName);
michael@0 21916 }
michael@0 21917 }
michael@0 21918
michael@0 21919 // Re-creating 'name' table
michael@0 21920 if (!tables.name) {
michael@0 21921 tables.name = {
michael@0 21922 tag: 'name',
michael@0 21923 data: stringToArray(createNameTable(this.name))
michael@0 21924 };
michael@0 21925 } else {
michael@0 21926 // ... using existing 'name' table as prototype
michael@0 21927 var namePrototype = readNameTable(tables.name);
michael@0 21928 tables.name.data = stringToArray(createNameTable(name, namePrototype));
michael@0 21929 }
michael@0 21930
michael@0 21931 // rewrite the tables but tweak offsets
michael@0 21932 for (i = 0; i < numTables; i++) {
michael@0 21933 table = tables[tablesNames[i]];
michael@0 21934 var data = [];
michael@0 21935
michael@0 21936 tableData = table.data;
michael@0 21937 for (var j = 0, jj = tableData.length; j < jj; j++) {
michael@0 21938 data.push(tableData[j]);
michael@0 21939 }
michael@0 21940 createTableEntry(ttf, table.tag, data);
michael@0 21941 }
michael@0 21942
michael@0 21943 // Add the table datas
michael@0 21944 for (i = 0; i < numTables; i++) {
michael@0 21945 table = tables[tablesNames[i]];
michael@0 21946 tableData = table.data;
michael@0 21947 ttf.file += bytesToString(new Uint8Array(tableData));
michael@0 21948
michael@0 21949 // 4-byte aligned data
michael@0 21950 while (ttf.file.length & 3) {
michael@0 21951 ttf.file += String.fromCharCode(0);
michael@0 21952 }
michael@0 21953 }
michael@0 21954
michael@0 21955 return stringToArray(ttf.file);
michael@0 21956 },
michael@0 21957
michael@0 21958 convert: function Font_convert(fontName, font, properties) {
michael@0 21959 // The offsets object holds at the same time a representation of where
michael@0 21960 // to write the table entry information about a table and another offset
michael@0 21961 // representing the offset where to draw the actual data of a particular
michael@0 21962 // table
michael@0 21963 var otf = {
michael@0 21964 file: '',
michael@0 21965 virtualOffset: 9 * (4 * 4)
michael@0 21966 };
michael@0 21967
michael@0 21968 createOpenTypeHeader('\x4F\x54\x54\x4F', otf, 9);
michael@0 21969
michael@0 21970 // TODO: Check the charstring widths to determine this.
michael@0 21971 properties.fixedPitch = false;
michael@0 21972
michael@0 21973 var mapping = font.getGlyphMapping(properties);
michael@0 21974 var newMapping = adjustMapping(mapping, properties);
michael@0 21975 this.toFontChar = newMapping.toFontChar;
michael@0 21976 var numGlyphs = font.numGlyphs;
michael@0 21977
michael@0 21978 function getCharCode(charCodeToGlyphId, glyphId, addMap) {
michael@0 21979 for (var charCode in charCodeToGlyphId) {
michael@0 21980 if (glyphId === charCodeToGlyphId[charCode]) {
michael@0 21981 return charCode | 0;
michael@0 21982 }
michael@0 21983 }
michael@0 21984 if (addMap) {
michael@0 21985 newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] =
michael@0 21986 glyphId;
michael@0 21987 return newMapping.nextAvailableFontCharCode++;
michael@0 21988 }
michael@0 21989 return null;
michael@0 21990 }
michael@0 21991
michael@0 21992 var seacs = font.seacs;
michael@0 21993 if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) {
michael@0 21994 var matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX;
michael@0 21995 var charset = font.getCharset();
michael@0 21996 var seacMap = Object.create(null);
michael@0 21997 for (var glyphId in seacs) {
michael@0 21998 glyphId |= 0;
michael@0 21999 var seac = seacs[glyphId];
michael@0 22000 var baseGlyphName = Encodings.StandardEncoding[seac[2]];
michael@0 22001 var accentGlyphName = Encodings.StandardEncoding[seac[3]];
michael@0 22002 var baseGlyphId = charset.indexOf(baseGlyphName);
michael@0 22003 var accentGlyphId = charset.indexOf(accentGlyphName);
michael@0 22004 if (baseGlyphId < 0 || accentGlyphId < 0) {
michael@0 22005 continue;
michael@0 22006 }
michael@0 22007 var accentOffset = {
michael@0 22008 x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4],
michael@0 22009 y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5]
michael@0 22010 };
michael@0 22011
michael@0 22012 var charCode = getCharCode(mapping, glyphId);
michael@0 22013 if (charCode === null) {
michael@0 22014 // There's no point in mapping it if the char code was never mapped
michael@0 22015 // to begin with.
michael@0 22016 continue;
michael@0 22017 }
michael@0 22018 // Find a fontCharCode that maps to the base and accent glyphs. If one
michael@0 22019 // doesn't exists, create it.
michael@0 22020 var charCodeToGlyphId = newMapping.charCodeToGlyphId;
michael@0 22021 var baseFontCharCode = getCharCode(charCodeToGlyphId, baseGlyphId,
michael@0 22022 true);
michael@0 22023 var accentFontCharCode = getCharCode(charCodeToGlyphId, accentGlyphId,
michael@0 22024 true);
michael@0 22025 seacMap[charCode] = {
michael@0 22026 baseFontCharCode: baseFontCharCode,
michael@0 22027 accentFontCharCode: accentFontCharCode,
michael@0 22028 accentOffset: accentOffset
michael@0 22029 };
michael@0 22030 }
michael@0 22031 properties.seacMap = seacMap;
michael@0 22032 }
michael@0 22033
michael@0 22034 var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
michael@0 22035
michael@0 22036 var fields = {
michael@0 22037 // PostScript Font Program
michael@0 22038 'CFF ': font.data,
michael@0 22039
michael@0 22040 // OS/2 and Windows Specific metrics
michael@0 22041 'OS/2': stringToArray(createOS2Table(properties,
michael@0 22042 newMapping.charCodeToGlyphId)),
michael@0 22043
michael@0 22044 // Character to glyphs mapping
michael@0 22045 'cmap': createCmapTable(newMapping.charCodeToGlyphId),
michael@0 22046
michael@0 22047 // Font header
michael@0 22048 'head': (function fontFieldsHead() {
michael@0 22049 return stringToArray(
michael@0 22050 '\x00\x01\x00\x00' + // Version number
michael@0 22051 '\x00\x00\x10\x00' + // fontRevision
michael@0 22052 '\x00\x00\x00\x00' + // checksumAdjustement
michael@0 22053 '\x5F\x0F\x3C\xF5' + // magicNumber
michael@0 22054 '\x00\x00' + // Flags
michael@0 22055 safeString16(unitsPerEm) + // unitsPerEM
michael@0 22056 '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date
michael@0 22057 '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date
michael@0 22058 '\x00\x00' + // xMin
michael@0 22059 safeString16(properties.descent) + // yMin
michael@0 22060 '\x0F\xFF' + // xMax
michael@0 22061 safeString16(properties.ascent) + // yMax
michael@0 22062 string16(properties.italicAngle ? 2 : 0) + // macStyle
michael@0 22063 '\x00\x11' + // lowestRecPPEM
michael@0 22064 '\x00\x00' + // fontDirectionHint
michael@0 22065 '\x00\x00' + // indexToLocFormat
michael@0 22066 '\x00\x00'); // glyphDataFormat
michael@0 22067 })(),
michael@0 22068
michael@0 22069 // Horizontal header
michael@0 22070 'hhea': (function fontFieldsHhea() {
michael@0 22071 return stringToArray(
michael@0 22072 '\x00\x01\x00\x00' + // Version number
michael@0 22073 safeString16(properties.ascent) + // Typographic Ascent
michael@0 22074 safeString16(properties.descent) + // Typographic Descent
michael@0 22075 '\x00\x00' + // Line Gap
michael@0 22076 '\xFF\xFF' + // advanceWidthMax
michael@0 22077 '\x00\x00' + // minLeftSidebearing
michael@0 22078 '\x00\x00' + // minRightSidebearing
michael@0 22079 '\x00\x00' + // xMaxExtent
michael@0 22080 safeString16(properties.capHeight) + // caretSlopeRise
michael@0 22081 safeString16(Math.tan(properties.italicAngle) *
michael@0 22082 properties.xHeight) + // caretSlopeRun
michael@0 22083 '\x00\x00' + // caretOffset
michael@0 22084 '\x00\x00' + // -reserved-
michael@0 22085 '\x00\x00' + // -reserved-
michael@0 22086 '\x00\x00' + // -reserved-
michael@0 22087 '\x00\x00' + // -reserved-
michael@0 22088 '\x00\x00' + // metricDataFormat
michael@0 22089 string16(numGlyphs)); // Number of HMetrics
michael@0 22090 })(),
michael@0 22091
michael@0 22092 // Horizontal metrics
michael@0 22093 'hmtx': (function fontFieldsHmtx() {
michael@0 22094 var charstrings = font.charstrings;
michael@0 22095 var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
michael@0 22096 for (var i = 1, ii = numGlyphs; i < ii; i++) {
michael@0 22097 // TODO: For CFF fonts the width should technically match th x in
michael@0 22098 // the glyph, but it doesn't seem to matter.
michael@0 22099 var charstring = charstrings ? charstrings[i - 1] : {};
michael@0 22100 var width = 'width' in charstring ? charstring.width : 0;
michael@0 22101 hmtx += string16(width) + string16(0);
michael@0 22102 }
michael@0 22103 return stringToArray(hmtx);
michael@0 22104 })(),
michael@0 22105
michael@0 22106 // Maximum profile
michael@0 22107 'maxp': (function fontFieldsMaxp() {
michael@0 22108 return stringToArray(
michael@0 22109 '\x00\x00\x50\x00' + // Version number
michael@0 22110 string16(numGlyphs)); // Num of glyphs
michael@0 22111 })(),
michael@0 22112
michael@0 22113 // Naming tables
michael@0 22114 'name': stringToArray(createNameTable(fontName)),
michael@0 22115
michael@0 22116 // PostScript informations
michael@0 22117 'post': stringToArray(createPostTable(properties))
michael@0 22118 };
michael@0 22119
michael@0 22120 var field;
michael@0 22121 for (field in fields) {
michael@0 22122 createTableEntry(otf, field, fields[field]);
michael@0 22123 }
michael@0 22124 for (field in fields) {
michael@0 22125 var table = fields[field];
michael@0 22126 otf.file += bytesToString(new Uint8Array(table));
michael@0 22127 }
michael@0 22128
michael@0 22129 return stringToArray(otf.file);
michael@0 22130 },
michael@0 22131
michael@0 22132 /**
michael@0 22133 * Builds a char code to unicode map based on section 9.10 of the spec.
michael@0 22134 * @param {Object} properties Font properties object.
michael@0 22135 * @return {Object} Has two properties: 'toUnicode' which maps char codes to
michael@0 22136 * unicode (string) values and 'isIdentity' which is true if an identity map
michael@0 22137 * is used.
michael@0 22138 */
michael@0 22139 buildToUnicode: function Font_buildToUnicode(properties) {
michael@0 22140 var map = {
michael@0 22141 isIdentity: false,
michael@0 22142 toUnicode: null
michael@0 22143 };
michael@0 22144 // Section 9.10.2 Mapping Character Codes to Unicode Values
michael@0 22145 if (properties.toUnicode && properties.toUnicode.length !== 0) {
michael@0 22146 map.toUnicode = properties.toUnicode;
michael@0 22147 return map;
michael@0 22148 }
michael@0 22149 // According to the spec if the font is a simple font we should only map
michael@0 22150 // to unicode if the base encoding is MacRoman, MacExpert, or WinAnsi or
michael@0 22151 // the differences array only contains adobe standard or symbol set names,
michael@0 22152 // in pratice it seems better to always try to create a toUnicode
michael@0 22153 // map based of the default encoding.
michael@0 22154 var toUnicode, charcode;
michael@0 22155 if (!properties.composite /* is simple font */) {
michael@0 22156 toUnicode = [];
michael@0 22157 var encoding = properties.defaultEncoding.slice();
michael@0 22158 // Merge in the differences array.
michael@0 22159 var differences = properties.differences;
michael@0 22160 for (charcode in differences) {
michael@0 22161 encoding[charcode] = differences[charcode];
michael@0 22162 }
michael@0 22163 for (charcode in encoding) {
michael@0 22164 // a) Map the character code to a character name.
michael@0 22165 var glyphName = encoding[charcode];
michael@0 22166 // b) Look up the character name in the Adobe Glyph List (see the
michael@0 22167 // Bibliography) to obtain the corresponding Unicode value.
michael@0 22168 if (glyphName === '' || !(glyphName in GlyphsUnicode)) {
michael@0 22169 // (undocumented) c) Few heuristics to recognize unknown glyphs
michael@0 22170 // NOTE: Adobe Reader does not do this step, but OSX Preview does
michael@0 22171 var code;
michael@0 22172 // Gxx glyph
michael@0 22173 if (glyphName.length === 3 &&
michael@0 22174 glyphName[0] === 'G' &&
michael@0 22175 (code = parseInt(glyphName.substr(1), 16))) {
michael@0 22176 toUnicode[charcode] = String.fromCharCode(code);
michael@0 22177 }
michael@0 22178 // Cddd glyph
michael@0 22179 if (glyphName.length >= 3 &&
michael@0 22180 glyphName[0] === 'C' &&
michael@0 22181 (code = +glyphName.substr(1))) {
michael@0 22182 toUnicode[charcode] = String.fromCharCode(code);
michael@0 22183 }
michael@0 22184 continue;
michael@0 22185 }
michael@0 22186 toUnicode[charcode] = String.fromCharCode(GlyphsUnicode[glyphName]);
michael@0 22187 }
michael@0 22188 map.toUnicode = toUnicode;
michael@0 22189 return map;
michael@0 22190 }
michael@0 22191 // If the font is a composite font that uses one of the predefined CMaps
michael@0 22192 // listed in Table 118 (except Identity–H and Identity–V) or whose
michael@0 22193 // descendant CIDFont uses the Adobe-GB1, Adobe-CNS1, Adobe-Japan1, or
michael@0 22194 // Adobe-Korea1 character collection:
michael@0 22195 if (properties.composite && (
michael@0 22196 (properties.cMap.builtInCMap &&
michael@0 22197 !(properties.cMap instanceof IdentityCMap)) ||
michael@0 22198 (properties.cidSystemInfo.registry === 'Adobe' &&
michael@0 22199 (properties.cidSystemInfo.ordering === 'GB1' ||
michael@0 22200 properties.cidSystemInfo.ordering === 'CNS1' ||
michael@0 22201 properties.cidSystemInfo.ordering === 'Japan1' ||
michael@0 22202 properties.cidSystemInfo.ordering === 'Korea1')))) {
michael@0 22203 // Then:
michael@0 22204 // a) Map the character code to a character identifier (CID) according
michael@0 22205 // to the font’s CMap.
michael@0 22206 // b) Obtain the registry and ordering of the character collection used
michael@0 22207 // by the font’s CMap (for example, Adobe and Japan1) from its
michael@0 22208 // CIDSystemInfo dictionary.
michael@0 22209 var registry = properties.cidSystemInfo.registry;
michael@0 22210 var ordering = properties.cidSystemInfo.ordering;
michael@0 22211 // c) Construct a second CMap name by concatenating the registry and
michael@0 22212 // ordering obtained in step (b) in the format registry–ordering–UCS2
michael@0 22213 // (for example, Adobe–Japan1–UCS2).
michael@0 22214 var ucs2CMapName = new Name(registry + '-' + ordering + '-UCS2');
michael@0 22215 // d) Obtain the CMap with the name constructed in step (c) (available
michael@0 22216 // from the ASN Web site; see the Bibliography).
michael@0 22217 var ucs2CMap = CMapFactory.create(ucs2CMapName,
michael@0 22218 { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null);
michael@0 22219 var cMap = properties.cMap;
michael@0 22220 toUnicode = [];
michael@0 22221 for (charcode in cMap.map) {
michael@0 22222 var cid = cMap.map[charcode];
michael@0 22223 assert(cid.length === 1, 'Max size of CID is 65,535');
michael@0 22224 // e) Map the CID obtained in step (a) according to the CMap obtained
michael@0 22225 // in step (d), producing a Unicode value.
michael@0 22226 var ucs2 = ucs2CMap.map[cid.charCodeAt(0)];
michael@0 22227 if (!ucs2) {
michael@0 22228 continue;
michael@0 22229 }
michael@0 22230 toUnicode[charcode] = String.fromCharCode((ucs2.charCodeAt(0) << 8) +
michael@0 22231 ucs2.charCodeAt(1));
michael@0 22232 }
michael@0 22233 map.toUnicode = toUnicode;
michael@0 22234 return map;
michael@0 22235 }
michael@0 22236
michael@0 22237 // The viewer's choice, just use an identity map.
michael@0 22238 toUnicode = [];
michael@0 22239 var firstChar = properties.firstChar, lastChar = properties.lastChar;
michael@0 22240 for (var i = firstChar; i <= lastChar; i++) {
michael@0 22241 toUnicode[i] = String.fromCharCode(i);
michael@0 22242 }
michael@0 22243 map.isIdentity = true;
michael@0 22244 map.toUnicode = toUnicode;
michael@0 22245 return map;
michael@0 22246 },
michael@0 22247
michael@0 22248 get spaceWidth() {
michael@0 22249 if ('_shadowWidth' in this) {
michael@0 22250 return this._shadowWidth;
michael@0 22251 }
michael@0 22252
michael@0 22253 // trying to estimate space character width
michael@0 22254 var possibleSpaceReplacements = ['space', 'minus', 'one', 'i'];
michael@0 22255 var width;
michael@0 22256 for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
michael@0 22257 var glyphName = possibleSpaceReplacements[i];
michael@0 22258 // if possible, getting width by glyph name
michael@0 22259 if (glyphName in this.widths) {
michael@0 22260 width = this.widths[glyphName];
michael@0 22261 break;
michael@0 22262 }
michael@0 22263 var glyphUnicode = GlyphsUnicode[glyphName];
michael@0 22264 // finding the charcode via unicodeToCID map
michael@0 22265 var charcode = 0;
michael@0 22266 if (this.composite) {
michael@0 22267 if (glyphUnicode in this.cMap.map) {
michael@0 22268 charcode = this.cMap.lookup(glyphUnicode).charCodeAt(0);
michael@0 22269 }
michael@0 22270 }
michael@0 22271 // ... via toUnicode map
michael@0 22272 if (!charcode && 'toUnicode' in this) {
michael@0 22273 charcode = this.toUnicode.indexOf(glyphUnicode);
michael@0 22274 }
michael@0 22275 // setting it to unicode if negative or undefined
michael@0 22276 if (charcode <= 0) {
michael@0 22277 charcode = glyphUnicode;
michael@0 22278 }
michael@0 22279 // trying to get width via charcode
michael@0 22280 width = this.widths[charcode];
michael@0 22281 if (width) {
michael@0 22282 break; // the non-zero width found
michael@0 22283 }
michael@0 22284 }
michael@0 22285 width = width || this.defaultWidth;
michael@0 22286 // Do not shadow the property here. See discussion:
michael@0 22287 // https://github.com/mozilla/pdf.js/pull/2127#discussion_r1662280
michael@0 22288 this._shadowWidth = width;
michael@0 22289 return width;
michael@0 22290 },
michael@0 22291
michael@0 22292 charToGlyph: function Font_charToGlyph(charcode) {
michael@0 22293 var fontCharCode, width, operatorList;
michael@0 22294
michael@0 22295 var widthCode = charcode;
michael@0 22296 if (this.cMap && charcode in this.cMap.map) {
michael@0 22297 widthCode = this.cMap.map[charcode].charCodeAt(0);
michael@0 22298 }
michael@0 22299 width = this.widths[widthCode];
michael@0 22300 width = isNum(width) ? width : this.defaultWidth;
michael@0 22301 var vmetric = this.vmetrics && this.vmetrics[widthCode];
michael@0 22302
michael@0 22303 var unicode = this.toUnicode[charcode] || charcode;
michael@0 22304 if (typeof unicode === 'number') {
michael@0 22305 unicode = String.fromCharCode(unicode);
michael@0 22306 }
michael@0 22307
michael@0 22308 // First try the toFontChar map, if it's not there then try falling
michael@0 22309 // back to the char code.
michael@0 22310 fontCharCode = this.toFontChar[charcode] || charcode;
michael@0 22311 if (this.missingFile) {
michael@0 22312 fontCharCode = mapSpecialUnicodeValues(fontCharCode);
michael@0 22313 }
michael@0 22314
michael@0 22315 if (this.type === 'Type3') {
michael@0 22316 // Font char code in this case is actually a glyph name.
michael@0 22317 operatorList = this.charProcOperatorList[fontCharCode];
michael@0 22318 }
michael@0 22319
michael@0 22320 var accent = null;
michael@0 22321 if (this.seacMap && this.seacMap[charcode]) {
michael@0 22322 var seac = this.seacMap[charcode];
michael@0 22323 fontCharCode = seac.baseFontCharCode;
michael@0 22324 accent = {
michael@0 22325 fontChar: String.fromCharCode(seac.accentFontCharCode),
michael@0 22326 offset: seac.accentOffset
michael@0 22327 };
michael@0 22328 }
michael@0 22329
michael@0 22330 var fontChar = String.fromCharCode(fontCharCode);
michael@0 22331
michael@0 22332 var glyph = this.glyphCache[charcode];
michael@0 22333 if (!glyph ||
michael@0 22334 !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric,
michael@0 22335 operatorList)) {
michael@0 22336 glyph = new Glyph(fontChar, unicode, accent, width, vmetric,
michael@0 22337 operatorList);
michael@0 22338 this.glyphCache[charcode] = glyph;
michael@0 22339 }
michael@0 22340 return glyph;
michael@0 22341 },
michael@0 22342
michael@0 22343 charsToGlyphs: function Font_charsToGlyphs(chars) {
michael@0 22344 var charsCache = this.charsCache;
michael@0 22345 var glyphs, glyph, charcode;
michael@0 22346
michael@0 22347 // if we translated this string before, just grab it from the cache
michael@0 22348 if (charsCache) {
michael@0 22349 glyphs = charsCache[chars];
michael@0 22350 if (glyphs) {
michael@0 22351 return glyphs;
michael@0 22352 }
michael@0 22353 }
michael@0 22354
michael@0 22355 // lazily create the translation cache
michael@0 22356 if (!charsCache) {
michael@0 22357 charsCache = this.charsCache = Object.create(null);
michael@0 22358 }
michael@0 22359
michael@0 22360 glyphs = [];
michael@0 22361 var charsCacheKey = chars;
michael@0 22362 var i = 0, ii;
michael@0 22363
michael@0 22364 if (this.cMap) {
michael@0 22365 // composite fonts have multi-byte strings convert the string from
michael@0 22366 // single-byte to multi-byte
michael@0 22367 while (i < chars.length) {
michael@0 22368 var c = this.cMap.readCharCode(chars, i);
michael@0 22369 charcode = c[0];
michael@0 22370 var length = c[1];
michael@0 22371 i += length;
michael@0 22372 glyph = this.charToGlyph(charcode);
michael@0 22373 glyphs.push(glyph);
michael@0 22374 // placing null after each word break charcode (ASCII SPACE)
michael@0 22375 // Ignore occurences of 0x20 in multiple-byte codes.
michael@0 22376 if (length === 1 && chars.charCodeAt(i - 1) === 0x20) {
michael@0 22377 glyphs.push(null);
michael@0 22378 }
michael@0 22379 }
michael@0 22380 } else {
michael@0 22381 for (i = 0, ii = chars.length; i < ii; ++i) {
michael@0 22382 charcode = chars.charCodeAt(i);
michael@0 22383 glyph = this.charToGlyph(charcode);
michael@0 22384 glyphs.push(glyph);
michael@0 22385 if (charcode == 0x20) {
michael@0 22386 glyphs.push(null);
michael@0 22387 }
michael@0 22388 }
michael@0 22389 }
michael@0 22390
michael@0 22391 // Enter the translated string into the cache
michael@0 22392 return (charsCache[charsCacheKey] = glyphs);
michael@0 22393 }
michael@0 22394 };
michael@0 22395
michael@0 22396 return Font;
michael@0 22397 })();
michael@0 22398
michael@0 22399 var ErrorFont = (function ErrorFontClosure() {
michael@0 22400 function ErrorFont(error) {
michael@0 22401 this.error = error;
michael@0 22402 }
michael@0 22403
michael@0 22404 ErrorFont.prototype = {
michael@0 22405 charsToGlyphs: function ErrorFont_charsToGlyphs() {
michael@0 22406 return [];
michael@0 22407 },
michael@0 22408 exportData: function ErrorFont_exportData() {
michael@0 22409 return {error: this.error};
michael@0 22410 }
michael@0 22411 };
michael@0 22412
michael@0 22413 return ErrorFont;
michael@0 22414 })();
michael@0 22415
michael@0 22416 /**
michael@0 22417 * Shared logic for building a char code to glyph id mapping for Type1 and
michael@0 22418 * simple CFF fonts. See section 9.6.6.2 of the spec.
michael@0 22419 * @param {Object} properties Font properties object.
michael@0 22420 * @param {Object} builtInEncoding The encoding contained within the actual font
michael@0 22421 * data.
michael@0 22422 * @param {Array} Array of glyph names where the index is the glyph ID.
michael@0 22423 * @returns {Object} A char code to glyph ID map.
michael@0 22424 */
michael@0 22425 function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {
michael@0 22426 var charCodeToGlyphId = Object.create(null);
michael@0 22427 var glyphId, charCode, baseEncoding;
michael@0 22428
michael@0 22429 if (properties.baseEncodingName) {
michael@0 22430 // If a valid base encoding name was used, the mapping is initialized with
michael@0 22431 // that.
michael@0 22432 baseEncoding = Encodings[properties.baseEncodingName];
michael@0 22433 for (charCode = 0; charCode < baseEncoding.length; charCode++) {
michael@0 22434 glyphId = glyphNames.indexOf(baseEncoding[charCode]);
michael@0 22435 if (glyphId >= 0) {
michael@0 22436 charCodeToGlyphId[charCode] = glyphId;
michael@0 22437 }
michael@0 22438 }
michael@0 22439 } else if (!!(properties.flags & FontFlags.Symbolic)) {
michael@0 22440 // For a symbolic font the encoding should be the fonts built-in
michael@0 22441 // encoding.
michael@0 22442 for (charCode in builtInEncoding) {
michael@0 22443 charCodeToGlyphId[charCode] = builtInEncoding[charCode];
michael@0 22444 }
michael@0 22445 } else {
michael@0 22446 // For non-symbolic fonts that don't have a base encoding the standard
michael@0 22447 // encoding should be used.
michael@0 22448 baseEncoding = Encodings.StandardEncoding;
michael@0 22449 for (charCode = 0; charCode < baseEncoding.length; charCode++) {
michael@0 22450 glyphId = glyphNames.indexOf(baseEncoding[charCode]);
michael@0 22451 if (glyphId >= 0) {
michael@0 22452 charCodeToGlyphId[charCode] = glyphId;
michael@0 22453 }
michael@0 22454 }
michael@0 22455 }
michael@0 22456
michael@0 22457 // Lastly, merge in the differences.
michael@0 22458 var differences = properties.differences;
michael@0 22459 if (differences) {
michael@0 22460 for (charCode in differences) {
michael@0 22461 var glyphName = differences[charCode];
michael@0 22462 glyphId = glyphNames.indexOf(glyphName);
michael@0 22463 if (glyphId >= 0) {
michael@0 22464 charCodeToGlyphId[charCode] = glyphId;
michael@0 22465 }
michael@0 22466 }
michael@0 22467 }
michael@0 22468 return charCodeToGlyphId;
michael@0 22469 }
michael@0 22470
michael@0 22471 /*
michael@0 22472 * CharStrings are encoded following the the CharString Encoding sequence
michael@0 22473 * describe in Chapter 6 of the "Adobe Type1 Font Format" specification.
michael@0 22474 * The value in a byte indicates a command, a number, or subsequent bytes
michael@0 22475 * that are to be interpreted in a special way.
michael@0 22476 *
michael@0 22477 * CharString Number Encoding:
michael@0 22478 * A CharString byte containing the values from 32 through 255 inclusive
michael@0 22479 * indicate an integer. These values are decoded in four ranges.
michael@0 22480 *
michael@0 22481 * 1. A CharString byte containing a value, v, between 32 and 246 inclusive,
michael@0 22482 * indicate the integer v - 139. Thus, the integer values from -107 through
michael@0 22483 * 107 inclusive may be encoded in single byte.
michael@0 22484 *
michael@0 22485 * 2. A CharString byte containing a value, v, between 247 and 250 inclusive,
michael@0 22486 * indicates an integer involving the next byte, w, according to the formula:
michael@0 22487 * [(v - 247) x 256] + w + 108
michael@0 22488 *
michael@0 22489 * 3. A CharString byte containing a value, v, between 251 and 254 inclusive,
michael@0 22490 * indicates an integer involving the next byte, w, according to the formula:
michael@0 22491 * -[(v - 251) * 256] - w - 108
michael@0 22492 *
michael@0 22493 * 4. A CharString containing the value 255 indicates that the next 4 bytes
michael@0 22494 * are a two complement signed integer. The first of these bytes contains the
michael@0 22495 * highest order bits, the second byte contains the next higher order bits
michael@0 22496 * and the fourth byte contain the lowest order bits.
michael@0 22497 *
michael@0 22498 *
michael@0 22499 * CharString Command Encoding:
michael@0 22500 * CharStrings commands are encoded in 1 or 2 bytes.
michael@0 22501 *
michael@0 22502 * Single byte commands are encoded in 1 byte that contains a value between
michael@0 22503 * 0 and 31 inclusive.
michael@0 22504 * If a command byte contains the value 12, then the value in the next byte
michael@0 22505 * indicates a command. This "escape" mechanism allows many extra commands
michael@0 22506 * to be encoded and this encoding technique helps to minimize the length of
michael@0 22507 * the charStrings.
michael@0 22508 */
michael@0 22509 var Type1CharString = (function Type1CharStringClosure() {
michael@0 22510 var COMMAND_MAP = {
michael@0 22511 'hstem': [1],
michael@0 22512 'vstem': [3],
michael@0 22513 'vmoveto': [4],
michael@0 22514 'rlineto': [5],
michael@0 22515 'hlineto': [6],
michael@0 22516 'vlineto': [7],
michael@0 22517 'rrcurveto': [8],
michael@0 22518 'callsubr': [10],
michael@0 22519 'flex': [12, 35],
michael@0 22520 'drop' : [12, 18],
michael@0 22521 'endchar': [14],
michael@0 22522 'rmoveto': [21],
michael@0 22523 'hmoveto': [22],
michael@0 22524 'vhcurveto': [30],
michael@0 22525 'hvcurveto': [31]
michael@0 22526 };
michael@0 22527
michael@0 22528 function Type1CharString() {
michael@0 22529 this.width = 0;
michael@0 22530 this.lsb = 0;
michael@0 22531 this.flexing = false;
michael@0 22532 this.output = [];
michael@0 22533 this.stack = [];
michael@0 22534 }
michael@0 22535
michael@0 22536 Type1CharString.prototype = {
michael@0 22537 convert: function Type1CharString_convert(encoded, subrs) {
michael@0 22538 var count = encoded.length;
michael@0 22539 var error = false;
michael@0 22540 var wx, sbx, subrNumber;
michael@0 22541 for (var i = 0; i < count; i++) {
michael@0 22542 var value = encoded[i];
michael@0 22543 if (value < 32) {
michael@0 22544 if (value === 12) {
michael@0 22545 value = (value << 8) + encoded[++i];
michael@0 22546 }
michael@0 22547 switch (value) {
michael@0 22548 case 1: // hstem
michael@0 22549 if (!HINTING_ENABLED) {
michael@0 22550 this.stack = [];
michael@0 22551 break;
michael@0 22552 }
michael@0 22553 error = this.executeCommand(2, COMMAND_MAP.hstem);
michael@0 22554 break;
michael@0 22555 case 3: // vstem
michael@0 22556 if (!HINTING_ENABLED) {
michael@0 22557 this.stack = [];
michael@0 22558 break;
michael@0 22559 }
michael@0 22560 error = this.executeCommand(2, COMMAND_MAP.vstem);
michael@0 22561 break;
michael@0 22562 case 4: // vmoveto
michael@0 22563 if (this.flexing) {
michael@0 22564 if (this.stack.length < 1) {
michael@0 22565 error = true;
michael@0 22566 break;
michael@0 22567 }
michael@0 22568 // Add the dx for flex and but also swap the values so they are
michael@0 22569 // the right order.
michael@0 22570 var dy = this.stack.pop();
michael@0 22571 this.stack.push(0, dy);
michael@0 22572 break;
michael@0 22573 }
michael@0 22574 error = this.executeCommand(1, COMMAND_MAP.vmoveto);
michael@0 22575 break;
michael@0 22576 case 5: // rlineto
michael@0 22577 error = this.executeCommand(2, COMMAND_MAP.rlineto);
michael@0 22578 break;
michael@0 22579 case 6: // hlineto
michael@0 22580 error = this.executeCommand(1, COMMAND_MAP.hlineto);
michael@0 22581 break;
michael@0 22582 case 7: // vlineto
michael@0 22583 error = this.executeCommand(1, COMMAND_MAP.vlineto);
michael@0 22584 break;
michael@0 22585 case 8: // rrcurveto
michael@0 22586 error = this.executeCommand(6, COMMAND_MAP.rrcurveto);
michael@0 22587 break;
michael@0 22588 case 9: // closepath
michael@0 22589 // closepath is a Type1 command that does not take argument and is
michael@0 22590 // useless in Type2 and it can simply be ignored.
michael@0 22591 this.stack = [];
michael@0 22592 break;
michael@0 22593 case 10: // callsubr
michael@0 22594 if (this.stack.length < 1) {
michael@0 22595 error = true;
michael@0 22596 break;
michael@0 22597 }
michael@0 22598 subrNumber = this.stack.pop();
michael@0 22599 error = this.convert(subrs[subrNumber], subrs);
michael@0 22600 break;
michael@0 22601 case 11: // return
michael@0 22602 return error;
michael@0 22603 case 13: // hsbw
michael@0 22604 if (this.stack.length < 2) {
michael@0 22605 error = true;
michael@0 22606 break;
michael@0 22607 }
michael@0 22608 // To convert to type2 we have to move the width value to the
michael@0 22609 // first part of the charstring and then use hmoveto with lsb.
michael@0 22610 wx = this.stack.pop();
michael@0 22611 sbx = this.stack.pop();
michael@0 22612 this.lsb = sbx;
michael@0 22613 this.width = wx;
michael@0 22614 this.stack.push(sbx);
michael@0 22615 error = this.executeCommand(1, COMMAND_MAP.hmoveto);
michael@0 22616 break;
michael@0 22617 case 14: // endchar
michael@0 22618 this.output.push(COMMAND_MAP.endchar[0]);
michael@0 22619 break;
michael@0 22620 case 21: // rmoveto
michael@0 22621 if (this.flexing) {
michael@0 22622 break;
michael@0 22623 }
michael@0 22624 error = this.executeCommand(2, COMMAND_MAP.rmoveto);
michael@0 22625 break;
michael@0 22626 case 22: // hmoveto
michael@0 22627 if (this.flexing) {
michael@0 22628 // Add the dy for flex.
michael@0 22629 this.stack.push(0);
michael@0 22630 break;
michael@0 22631 }
michael@0 22632 error = this.executeCommand(1, COMMAND_MAP.hmoveto);
michael@0 22633 break;
michael@0 22634 case 30: // vhcurveto
michael@0 22635 error = this.executeCommand(4, COMMAND_MAP.vhcurveto);
michael@0 22636 break;
michael@0 22637 case 31: // hvcurveto
michael@0 22638 error = this.executeCommand(4, COMMAND_MAP.hvcurveto);
michael@0 22639 break;
michael@0 22640 case (12 << 8) + 0: // dotsection
michael@0 22641 // dotsection is a Type1 command to specify some hinting feature
michael@0 22642 // for dots that do not take a parameter and it can safely be
michael@0 22643 // ignored for Type2.
michael@0 22644 this.stack = [];
michael@0 22645 break;
michael@0 22646 case (12 << 8) + 1: // vstem3
michael@0 22647 if (!HINTING_ENABLED) {
michael@0 22648 this.stack = [];
michael@0 22649 break;
michael@0 22650 }
michael@0 22651 // [vh]stem3 are Type1 only and Type2 supports [vh]stem with
michael@0 22652 // multiple parameters, so instead of returning [vh]stem3 take a
michael@0 22653 // shortcut and return [vhstem] instead.
michael@0 22654 error = this.executeCommand(2, COMMAND_MAP.vstem);
michael@0 22655 break;
michael@0 22656 case (12 << 8) + 2: // hstem3
michael@0 22657 if (!HINTING_ENABLED) {
michael@0 22658 this.stack = [];
michael@0 22659 break;
michael@0 22660 }
michael@0 22661 // See vstem3.
michael@0 22662 error = this.executeCommand(2, COMMAND_MAP.hstem);
michael@0 22663 break;
michael@0 22664 case (12 << 8) + 6: // seac
michael@0 22665 // seac is like type 2's special endchar but it doesn't use the
michael@0 22666 // first argument asb, so remove it.
michael@0 22667 if (SEAC_ANALYSIS_ENABLED) {
michael@0 22668 this.seac = this.stack.splice(-4, 4);
michael@0 22669 error = this.executeCommand(0, COMMAND_MAP.endchar);
michael@0 22670 } else {
michael@0 22671 error = this.executeCommand(4, COMMAND_MAP.endchar);
michael@0 22672 }
michael@0 22673 break;
michael@0 22674 case (12 << 8) + 7: // sbw
michael@0 22675 if (this.stack.length < 4) {
michael@0 22676 error = true;
michael@0 22677 break;
michael@0 22678 }
michael@0 22679 // To convert to type2 we have to move the width value to the
michael@0 22680 // first part of the charstring and then use rmoveto with
michael@0 22681 // (dx, dy). The height argument will not be used for vmtx and
michael@0 22682 // vhea tables reconstruction -- ignoring it.
michael@0 22683 var wy = this.stack.pop();
michael@0 22684 wx = this.stack.pop();
michael@0 22685 var sby = this.stack.pop();
michael@0 22686 sbx = this.stack.pop();
michael@0 22687 this.lsb = sbx;
michael@0 22688 this.width = wx;
michael@0 22689 this.stack.push(sbx, sby);
michael@0 22690 error = this.executeCommand(2, COMMAND_MAP.rmoveto);
michael@0 22691 break;
michael@0 22692 case (12 << 8) + 12: // div
michael@0 22693 if (this.stack.length < 2) {
michael@0 22694 error = true;
michael@0 22695 break;
michael@0 22696 }
michael@0 22697 var num2 = this.stack.pop();
michael@0 22698 var num1 = this.stack.pop();
michael@0 22699 this.stack.push(num1 / num2);
michael@0 22700 break;
michael@0 22701 case (12 << 8) + 16: // callothersubr
michael@0 22702 if (this.stack.length < 2) {
michael@0 22703 error = true;
michael@0 22704 break;
michael@0 22705 }
michael@0 22706 subrNumber = this.stack.pop();
michael@0 22707 var numArgs = this.stack.pop();
michael@0 22708 if (subrNumber === 0 && numArgs === 3) {
michael@0 22709 var flexArgs = this.stack.splice(this.stack.length - 17, 17);
michael@0 22710 this.stack.push(
michael@0 22711 flexArgs[2] + flexArgs[0], // bcp1x + rpx
michael@0 22712 flexArgs[3] + flexArgs[1], // bcp1y + rpy
michael@0 22713 flexArgs[4], // bcp2x
michael@0 22714 flexArgs[5], // bcp2y
michael@0 22715 flexArgs[6], // p2x
michael@0 22716 flexArgs[7], // p2y
michael@0 22717 flexArgs[8], // bcp3x
michael@0 22718 flexArgs[9], // bcp3y
michael@0 22719 flexArgs[10], // bcp4x
michael@0 22720 flexArgs[11], // bcp4y
michael@0 22721 flexArgs[12], // p3x
michael@0 22722 flexArgs[13], // p3y
michael@0 22723 flexArgs[14] // flexDepth
michael@0 22724 // 15 = finalx unused by flex
michael@0 22725 // 16 = finaly unused by flex
michael@0 22726 );
michael@0 22727 error = this.executeCommand(13, COMMAND_MAP.flex, true);
michael@0 22728 this.flexing = false;
michael@0 22729 this.stack.push(flexArgs[15], flexArgs[16]);
michael@0 22730 } else if (subrNumber === 1 && numArgs === 0) {
michael@0 22731 this.flexing = true;
michael@0 22732 }
michael@0 22733 break;
michael@0 22734 case (12 << 8) + 17: // pop
michael@0 22735 // Ignore this since it is only used with othersubr.
michael@0 22736 break;
michael@0 22737 case (12 << 8) + 33: // setcurrentpoint
michael@0 22738 // Ignore for now.
michael@0 22739 this.stack = [];
michael@0 22740 break;
michael@0 22741 default:
michael@0 22742 warn('Unknown type 1 charstring command of "' + value + '"');
michael@0 22743 break;
michael@0 22744 }
michael@0 22745 if (error) {
michael@0 22746 break;
michael@0 22747 }
michael@0 22748 continue;
michael@0 22749 } else if (value <= 246) {
michael@0 22750 value = value - 139;
michael@0 22751 } else if (value <= 250) {
michael@0 22752 value = ((value - 247) * 256) + encoded[++i] + 108;
michael@0 22753 } else if (value <= 254) {
michael@0 22754 value = -((value - 251) * 256) - encoded[++i] - 108;
michael@0 22755 } else {
michael@0 22756 value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 |
michael@0 22757 (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;
michael@0 22758 }
michael@0 22759 this.stack.push(value);
michael@0 22760 }
michael@0 22761 return error;
michael@0 22762 },
michael@0 22763
michael@0 22764 executeCommand: function(howManyArgs, command, keepStack) {
michael@0 22765 var stackLength = this.stack.length;
michael@0 22766 if (howManyArgs > stackLength) {
michael@0 22767 return true;
michael@0 22768 }
michael@0 22769 var start = stackLength - howManyArgs;
michael@0 22770 for (var i = start; i < stackLength; i++) {
michael@0 22771 var value = this.stack[i];
michael@0 22772 if (value === (value | 0)) { // int
michael@0 22773 this.output.push(28, (value >> 8) & 0xff, value & 0xff);
michael@0 22774 } else { // fixed point
michael@0 22775 value = (65536 * value) | 0;
michael@0 22776 this.output.push(255,
michael@0 22777 (value >> 24) & 0xFF,
michael@0 22778 (value >> 16) & 0xFF,
michael@0 22779 (value >> 8) & 0xFF,
michael@0 22780 value & 0xFF);
michael@0 22781 }
michael@0 22782 }
michael@0 22783 this.output.push.apply(this.output, command);
michael@0 22784 if (keepStack) {
michael@0 22785 this.stack.splice(start, howManyArgs);
michael@0 22786 } else {
michael@0 22787 this.stack.length = 0;
michael@0 22788 }
michael@0 22789 return false;
michael@0 22790 }
michael@0 22791 };
michael@0 22792
michael@0 22793 return Type1CharString;
michael@0 22794 })();
michael@0 22795
michael@0 22796 /*
michael@0 22797 * Type1Parser encapsulate the needed code for parsing a Type1 font
michael@0 22798 * program. Some of its logic depends on the Type2 charstrings
michael@0 22799 * structure.
michael@0 22800 * Note: this doesn't really parse the font since that would require evaluation
michael@0 22801 * of PostScript, but it is possible in most cases to extract what we need
michael@0 22802 * without a full parse.
michael@0 22803 */
michael@0 22804 var Type1Parser = (function Type1ParserClosure() {
michael@0 22805 /*
michael@0 22806 * Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence
michael@0 22807 * of Plaintext Bytes. The function took a key as a parameter which can be
michael@0 22808 * for decrypting the eexec block of for decoding charStrings.
michael@0 22809 */
michael@0 22810 var EEXEC_ENCRYPT_KEY = 55665;
michael@0 22811 var CHAR_STRS_ENCRYPT_KEY = 4330;
michael@0 22812
michael@0 22813 function isHexDigit(code) {
michael@0 22814 return code >= 48 && code <= 57 || // '0'-'9'
michael@0 22815 code >= 65 && code <= 70 || // 'A'-'F'
michael@0 22816 code >= 97 && code <= 102; // 'a'-'f'
michael@0 22817 }
michael@0 22818
michael@0 22819 function decrypt(data, key, discardNumber) {
michael@0 22820 var r = key | 0, c1 = 52845, c2 = 22719;
michael@0 22821 var count = data.length;
michael@0 22822 var decrypted = new Uint8Array(count);
michael@0 22823 for (var i = 0; i < count; i++) {
michael@0 22824 var value = data[i];
michael@0 22825 decrypted[i] = value ^ (r >> 8);
michael@0 22826 r = ((value + r) * c1 + c2) & ((1 << 16) - 1);
michael@0 22827 }
michael@0 22828 return Array.prototype.slice.call(decrypted, discardNumber);
michael@0 22829 }
michael@0 22830
michael@0 22831 function decryptAscii(data, key, discardNumber) {
michael@0 22832 var r = key | 0, c1 = 52845, c2 = 22719;
michael@0 22833 var count = data.length, maybeLength = count >>> 1;
michael@0 22834 var decrypted = new Uint8Array(maybeLength);
michael@0 22835 var i, j;
michael@0 22836 for (i = 0, j = 0; i < count; i++) {
michael@0 22837 var digit1 = data[i];
michael@0 22838 if (!isHexDigit(digit1)) {
michael@0 22839 continue;
michael@0 22840 }
michael@0 22841 i++;
michael@0 22842 var digit2;
michael@0 22843 while (i < count && !isHexDigit(digit2 = data[i])) {
michael@0 22844 i++;
michael@0 22845 }
michael@0 22846 if (i < count) {
michael@0 22847 var value = parseInt(String.fromCharCode(digit1, digit2), 16);
michael@0 22848 decrypted[j++] = value ^ (r >> 8);
michael@0 22849 r = ((value + r) * c1 + c2) & ((1 << 16) - 1);
michael@0 22850 }
michael@0 22851 }
michael@0 22852 return Array.prototype.slice.call(decrypted, discardNumber, j);
michael@0 22853 }
michael@0 22854
michael@0 22855 function isSpecial(c) {
michael@0 22856 return c === 0x2F || // '/'
michael@0 22857 c === 0x5B || c === 0x5D || // '[', ']'
michael@0 22858 c === 0x7B || c === 0x7D || // '{', '}'
michael@0 22859 c === 0x28 || c === 0x29; // '(', ')'
michael@0 22860 }
michael@0 22861
michael@0 22862 function Type1Parser(stream, encrypted) {
michael@0 22863 if (encrypted) {
michael@0 22864 var data = stream.getBytes();
michael@0 22865 var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) &&
michael@0 22866 isHexDigit(data[2]) && isHexDigit(data[3]));
michael@0 22867 stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) :
michael@0 22868 decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
michael@0 22869 }
michael@0 22870 this.stream = stream;
michael@0 22871 this.nextChar();
michael@0 22872 }
michael@0 22873
michael@0 22874 Type1Parser.prototype = {
michael@0 22875 readNumberArray: function Type1Parser_readNumberArray() {
michael@0 22876 this.getToken(); // read '[' or '{' (arrays can start with either)
michael@0 22877 var array = [];
michael@0 22878 while (true) {
michael@0 22879 var token = this.getToken();
michael@0 22880 if (token === null || token === ']' || token === '}') {
michael@0 22881 break;
michael@0 22882 }
michael@0 22883 array.push(parseFloat(token || 0));
michael@0 22884 }
michael@0 22885 return array;
michael@0 22886 },
michael@0 22887
michael@0 22888 readNumber: function Type1Parser_readNumber() {
michael@0 22889 var token = this.getToken();
michael@0 22890 return parseFloat(token || 0);
michael@0 22891 },
michael@0 22892
michael@0 22893 readInt: function Type1Parser_readInt() {
michael@0 22894 // Use '| 0' to prevent setting a double into length such as the double
michael@0 22895 // does not flow into the loop variable.
michael@0 22896 var token = this.getToken();
michael@0 22897 return parseInt(token || 0, 10) | 0;
michael@0 22898 },
michael@0 22899
michael@0 22900 readBoolean: function Type1Parser_readBoolean() {
michael@0 22901 var token = this.getToken();
michael@0 22902
michael@0 22903 // Use 1 and 0 since that's what type2 charstrings use.
michael@0 22904 return token === 'true' ? 1 : 0;
michael@0 22905 },
michael@0 22906
michael@0 22907 nextChar : function Type1_nextChar() {
michael@0 22908 return (this.currentChar = this.stream.getByte());
michael@0 22909 },
michael@0 22910
michael@0 22911 getToken: function Type1Parser_getToken() {
michael@0 22912 // Eat whitespace and comments.
michael@0 22913 var comment = false;
michael@0 22914 var ch = this.currentChar;
michael@0 22915 while (true) {
michael@0 22916 if (ch === -1) {
michael@0 22917 return null;
michael@0 22918 }
michael@0 22919
michael@0 22920 if (comment) {
michael@0 22921 if (ch === 0x0A || ch === 0x0D) {
michael@0 22922 comment = false;
michael@0 22923 }
michael@0 22924 } else if (ch === 0x25) { // '%'
michael@0 22925 comment = true;
michael@0 22926 } else if (!Lexer.isSpace(ch)) {
michael@0 22927 break;
michael@0 22928 }
michael@0 22929 ch = this.nextChar();
michael@0 22930 }
michael@0 22931 if (isSpecial(ch)) {
michael@0 22932 this.nextChar();
michael@0 22933 return String.fromCharCode(ch);
michael@0 22934 }
michael@0 22935 var token = '';
michael@0 22936 do {
michael@0 22937 token += String.fromCharCode(ch);
michael@0 22938 ch = this.nextChar();
michael@0 22939 } while (ch >= 0 && !Lexer.isSpace(ch) && !isSpecial(ch));
michael@0 22940 return token;
michael@0 22941 },
michael@0 22942
michael@0 22943 /*
michael@0 22944 * Returns an object containing a Subrs array and a CharStrings
michael@0 22945 * array extracted from and eexec encrypted block of data
michael@0 22946 */
michael@0 22947 extractFontProgram: function Type1Parser_extractFontProgram() {
michael@0 22948 var stream = this.stream;
michael@0 22949
michael@0 22950 var subrs = [], charstrings = [];
michael@0 22951 var program = {
michael@0 22952 subrs: [],
michael@0 22953 charstrings: [],
michael@0 22954 properties: {
michael@0 22955 'privateData': {
michael@0 22956 'lenIV': 4
michael@0 22957 }
michael@0 22958 }
michael@0 22959 };
michael@0 22960 var token, length, data, lenIV, encoded;
michael@0 22961 while ((token = this.getToken()) !== null) {
michael@0 22962 if (token !== '/') {
michael@0 22963 continue;
michael@0 22964 }
michael@0 22965 token = this.getToken();
michael@0 22966 switch (token) {
michael@0 22967 case 'CharStrings':
michael@0 22968 // The number immediately following CharStrings must be greater or
michael@0 22969 // equal to the number of CharStrings.
michael@0 22970 this.getToken();
michael@0 22971 this.getToken(); // read in 'dict'
michael@0 22972 this.getToken(); // read in 'dup'
michael@0 22973 this.getToken(); // read in 'begin'
michael@0 22974 while(true) {
michael@0 22975 token = this.getToken();
michael@0 22976 if (token === null || token === 'end') {
michael@0 22977 break;
michael@0 22978 }
michael@0 22979
michael@0 22980 if (token !== '/') {
michael@0 22981 continue;
michael@0 22982 }
michael@0 22983 var glyph = this.getToken();
michael@0 22984 length = this.readInt();
michael@0 22985 this.getToken(); // read in 'RD' or '-|'
michael@0 22986 data = stream.makeSubStream(stream.pos, length);
michael@0 22987 lenIV = program.properties.privateData['lenIV'];
michael@0 22988 encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV);
michael@0 22989 // Skip past the required space and binary data.
michael@0 22990 stream.skip(length);
michael@0 22991 this.nextChar();
michael@0 22992 token = this.getToken(); // read in 'ND' or '|-'
michael@0 22993 if (token === 'noaccess') {
michael@0 22994 this.getToken(); // read in 'def'
michael@0 22995 }
michael@0 22996 charstrings.push({
michael@0 22997 glyph: glyph,
michael@0 22998 encoded: encoded
michael@0 22999 });
michael@0 23000 }
michael@0 23001 break;
michael@0 23002 case 'Subrs':
michael@0 23003 var num = this.readInt();
michael@0 23004 this.getToken(); // read in 'array'
michael@0 23005 while ((token = this.getToken()) === 'dup') {
michael@0 23006 var index = this.readInt();
michael@0 23007 length = this.readInt();
michael@0 23008 this.getToken(); // read in 'RD' or '-|'
michael@0 23009 data = stream.makeSubStream(stream.pos, length);
michael@0 23010 lenIV = program.properties.privateData['lenIV'];
michael@0 23011 encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV);
michael@0 23012 // Skip past the required space and binary data.
michael@0 23013 stream.skip(length);
michael@0 23014 this.nextChar();
michael@0 23015 token = this.getToken(); // read in 'NP' or '|'
michael@0 23016 if (token === 'noaccess') {
michael@0 23017 this.getToken(); // read in 'put'
michael@0 23018 }
michael@0 23019 subrs[index] = encoded;
michael@0 23020 }
michael@0 23021 break;
michael@0 23022 case 'BlueValues':
michael@0 23023 case 'OtherBlues':
michael@0 23024 case 'FamilyBlues':
michael@0 23025 case 'FamilyOtherBlues':
michael@0 23026 var blueArray = this.readNumberArray();
michael@0 23027 // *Blue* values may contain invalid data: disables reading of
michael@0 23028 // those values when hinting is disabled.
michael@0 23029 if (blueArray.length > 0 && (blueArray.length % 2) === 0 &&
michael@0 23030 HINTING_ENABLED) {
michael@0 23031 program.properties.privateData[token] = blueArray;
michael@0 23032 }
michael@0 23033 break;
michael@0 23034 case 'StemSnapH':
michael@0 23035 case 'StemSnapV':
michael@0 23036 program.properties.privateData[token] = this.readNumberArray();
michael@0 23037 break;
michael@0 23038 case 'StdHW':
michael@0 23039 case 'StdVW':
michael@0 23040 program.properties.privateData[token] =
michael@0 23041 this.readNumberArray()[0];
michael@0 23042 break;
michael@0 23043 case 'BlueShift':
michael@0 23044 case 'lenIV':
michael@0 23045 case 'BlueFuzz':
michael@0 23046 case 'BlueScale':
michael@0 23047 case 'LanguageGroup':
michael@0 23048 case 'ExpansionFactor':
michael@0 23049 program.properties.privateData[token] = this.readNumber();
michael@0 23050 break;
michael@0 23051 case 'ForceBold':
michael@0 23052 program.properties.privateData[token] = this.readBoolean();
michael@0 23053 break;
michael@0 23054 }
michael@0 23055 }
michael@0 23056
michael@0 23057 for (var i = 0; i < charstrings.length; i++) {
michael@0 23058 glyph = charstrings[i].glyph;
michael@0 23059 encoded = charstrings[i].encoded;
michael@0 23060 var charString = new Type1CharString();
michael@0 23061 var error = charString.convert(encoded, subrs);
michael@0 23062 var output = charString.output;
michael@0 23063 if (error) {
michael@0 23064 // It seems when FreeType encounters an error while evaluating a glyph
michael@0 23065 // that it completely ignores the glyph so we'll mimic that behaviour
michael@0 23066 // here and put an endchar to make the validator happy.
michael@0 23067 output = [14];
michael@0 23068 }
michael@0 23069 program.charstrings.push({
michael@0 23070 glyphName: glyph,
michael@0 23071 charstring: output,
michael@0 23072 width: charString.width,
michael@0 23073 lsb: charString.lsb,
michael@0 23074 seac: charString.seac
michael@0 23075 });
michael@0 23076 }
michael@0 23077
michael@0 23078 return program;
michael@0 23079 },
michael@0 23080
michael@0 23081 extractFontHeader: function Type1Parser_extractFontHeader(properties) {
michael@0 23082 var token;
michael@0 23083 while ((token = this.getToken()) !== null) {
michael@0 23084 if (token !== '/') {
michael@0 23085 continue;
michael@0 23086 }
michael@0 23087 token = this.getToken();
michael@0 23088 switch (token) {
michael@0 23089 case 'FontMatrix':
michael@0 23090 var matrix = this.readNumberArray();
michael@0 23091 properties.fontMatrix = matrix;
michael@0 23092 break;
michael@0 23093 case 'Encoding':
michael@0 23094 var encodingArg = this.getToken();
michael@0 23095 var encoding;
michael@0 23096 if (!/^\d+$/.test(encodingArg)) {
michael@0 23097 // encoding name is specified
michael@0 23098 encoding = Encodings[encodingArg];
michael@0 23099 } else {
michael@0 23100 encoding = [];
michael@0 23101 var size = parseInt(encodingArg, 10) | 0;
michael@0 23102 this.getToken(); // read in 'array'
michael@0 23103
michael@0 23104 for (var j = 0; j < size; j++) {
michael@0 23105 token = this.getToken();
michael@0 23106 // skipping till first dup or def (e.g. ignoring for statement)
michael@0 23107 while (token !== 'dup' && token !== 'def') {
michael@0 23108 token = this.getToken();
michael@0 23109 if (token === null) {
michael@0 23110 return; // invalid header
michael@0 23111 }
michael@0 23112 }
michael@0 23113 if (token === 'def') {
michael@0 23114 break; // read all array data
michael@0 23115 }
michael@0 23116 var index = this.readInt();
michael@0 23117 this.getToken(); // read in '/'
michael@0 23118 var glyph = this.getToken();
michael@0 23119 encoding[index] = glyph;
michael@0 23120 this.getToken(); // read the in 'put'
michael@0 23121 }
michael@0 23122 }
michael@0 23123 properties.builtInEncoding = encoding;
michael@0 23124 break;
michael@0 23125 case 'FontBBox':
michael@0 23126 var fontBBox = this.readNumberArray();
michael@0 23127 // adjusting ascent/descent
michael@0 23128 properties.ascent = fontBBox[3];
michael@0 23129 properties.descent = fontBBox[1];
michael@0 23130 properties.ascentScaled = true;
michael@0 23131 break;
michael@0 23132 }
michael@0 23133 }
michael@0 23134 }
michael@0 23135 };
michael@0 23136
michael@0 23137 return Type1Parser;
michael@0 23138 })();
michael@0 23139
michael@0 23140 /**
michael@0 23141 * The CFF class takes a Type1 file and wrap it into a
michael@0 23142 * 'Compact Font Format' which itself embed Type2 charstrings.
michael@0 23143 */
michael@0 23144 var CFFStandardStrings = [
michael@0 23145 '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
michael@0 23146 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
michael@0 23147 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
michael@0 23148 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
michael@0 23149 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
michael@0 23150 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
michael@0 23151 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum',
michael@0 23152 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
michael@0 23153 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
michael@0 23154 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
michael@0 23155 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
michael@0 23156 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
michael@0 23157 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
michael@0 23158 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase',
michael@0 23159 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown',
michael@0 23160 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent',
michael@0 23161 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash',
michael@0 23162 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae',
michael@0 23163 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior',
michael@0 23164 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn',
michael@0 23165 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters',
michael@0 23166 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior',
michael@0 23167 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring',
michael@0 23168 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave',
michael@0 23169 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute',
michael@0 23170 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute',
michael@0 23171 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron',
michael@0 23172 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde',
michael@0 23173 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute',
michael@0 23174 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex',
michael@0 23175 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex',
michael@0 23176 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall',
michael@0 23177 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall',
michael@0 23178 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
michael@0 23179 'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle',
michael@0 23180 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
michael@0 23181 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior',
michael@0 23182 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior',
michael@0 23183 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior',
michael@0 23184 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
michael@0 23185 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior',
michael@0 23186 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall',
michael@0 23187 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
michael@0 23188 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
michael@0 23189 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
michael@0 23190 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
michael@0 23191 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
michael@0 23192 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall',
michael@0 23193 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior',
michael@0 23194 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth',
michael@0 23195 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds',
michael@0 23196 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
michael@0 23197 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior',
michael@0 23198 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior',
michael@0 23199 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',
michael@0 23200 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior',
michael@0 23201 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall',
michael@0 23202 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',
michael@0 23203 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall',
michael@0 23204 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall',
michael@0 23205 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall',
michael@0 23206 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',
michael@0 23207 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall',
michael@0 23208 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003',
michael@0 23209 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'
michael@0 23210 ];
michael@0 23211
michael@0 23212 // Type1Font is also a CIDFontType0.
michael@0 23213 var Type1Font = function Type1Font(name, file, properties) {
michael@0 23214 // Some bad generators embed pfb file as is, we have to strip 6-byte headers.
michael@0 23215 // Also, length1 and length2 might be off by 6 bytes as well.
michael@0 23216 // http://www.math.ubc.ca/~cass/piscript/type1.pdf
michael@0 23217 var PFB_HEADER_SIZE = 6;
michael@0 23218 var headerBlockLength = properties.length1;
michael@0 23219 var eexecBlockLength = properties.length2;
michael@0 23220 var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
michael@0 23221 var pfbHeaderPresent = pfbHeader[0] == 0x80 && pfbHeader[1] == 0x01;
michael@0 23222 if (pfbHeaderPresent) {
michael@0 23223 file.skip(PFB_HEADER_SIZE);
michael@0 23224 headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
michael@0 23225 (pfbHeader[3] << 8) | pfbHeader[2];
michael@0 23226 }
michael@0 23227
michael@0 23228 // Get the data block containing glyphs and subrs informations
michael@0 23229 var headerBlock = new Stream(file.getBytes(headerBlockLength));
michael@0 23230 var headerBlockParser = new Type1Parser(headerBlock);
michael@0 23231 headerBlockParser.extractFontHeader(properties);
michael@0 23232
michael@0 23233 if (pfbHeaderPresent) {
michael@0 23234 pfbHeader = file.getBytes(PFB_HEADER_SIZE);
michael@0 23235 eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
michael@0 23236 (pfbHeader[3] << 8) | pfbHeader[2];
michael@0 23237 }
michael@0 23238
michael@0 23239 // Decrypt the data blocks and retrieve it's content
michael@0 23240 var eexecBlock = new Stream(file.getBytes(eexecBlockLength));
michael@0 23241 var eexecBlockParser = new Type1Parser(eexecBlock, true);
michael@0 23242 var data = eexecBlockParser.extractFontProgram();
michael@0 23243 for (var info in data.properties) {
michael@0 23244 properties[info] = data.properties[info];
michael@0 23245 }
michael@0 23246
michael@0 23247 var charstrings = data.charstrings;
michael@0 23248 var type2Charstrings = this.getType2Charstrings(charstrings);
michael@0 23249 var subrs = this.getType2Subrs(data.subrs);
michael@0 23250
michael@0 23251 this.charstrings = charstrings;
michael@0 23252 this.data = this.wrap(name, type2Charstrings, this.charstrings,
michael@0 23253 subrs, properties);
michael@0 23254 this.seacs = this.getSeacs(data.charstrings);
michael@0 23255 };
michael@0 23256
michael@0 23257 Type1Font.prototype = {
michael@0 23258 get numGlyphs() {
michael@0 23259 return this.charstrings.length + 1;
michael@0 23260 },
michael@0 23261
michael@0 23262 getCharset: function Type1Font_getCharset() {
michael@0 23263 var charset = ['.notdef'];
michael@0 23264 var charstrings = this.charstrings;
michael@0 23265 for (var glyphId = 0; glyphId < charstrings.length; glyphId++) {
michael@0 23266 charset.push(charstrings[glyphId].glyphName);
michael@0 23267 }
michael@0 23268 return charset;
michael@0 23269 },
michael@0 23270
michael@0 23271 getGlyphMapping: function Type1Font_getGlyphMapping(properties) {
michael@0 23272 var charstrings = this.charstrings;
michael@0 23273 var glyphNames = ['.notdef'], glyphId;
michael@0 23274 for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
michael@0 23275 glyphNames.push(charstrings[glyphId].glyphName);
michael@0 23276 }
michael@0 23277 var encoding = properties.builtInEncoding;
michael@0 23278 if (encoding) {
michael@0 23279 var builtInEncoding = {};
michael@0 23280 for (var charCode in encoding) {
michael@0 23281 glyphId = glyphNames.indexOf(encoding[charCode]);
michael@0 23282 if (glyphId >= 0) {
michael@0 23283 builtInEncoding[charCode] = glyphId;
michael@0 23284 }
michael@0 23285 }
michael@0 23286 }
michael@0 23287
michael@0 23288 return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
michael@0 23289 },
michael@0 23290
michael@0 23291 getSeacs: function Type1Font_getSeacs(charstrings) {
michael@0 23292 var i, ii;
michael@0 23293 var seacMap = [];
michael@0 23294 for (i = 0, ii = charstrings.length; i < ii; i++) {
michael@0 23295 var charstring = charstrings[i];
michael@0 23296 if (charstring.seac) {
michael@0 23297 // Offset by 1 for .notdef
michael@0 23298 seacMap[i + 1] = charstring.seac;
michael@0 23299 }
michael@0 23300 }
michael@0 23301 return seacMap;
michael@0 23302 },
michael@0 23303
michael@0 23304 getType2Charstrings: function Type1Font_getType2Charstrings(
michael@0 23305 type1Charstrings) {
michael@0 23306 var type2Charstrings = [];
michael@0 23307 for (var i = 0, ii = type1Charstrings.length; i < ii; i++) {
michael@0 23308 type2Charstrings.push(type1Charstrings[i].charstring);
michael@0 23309 }
michael@0 23310 return type2Charstrings;
michael@0 23311 },
michael@0 23312
michael@0 23313 getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
michael@0 23314 var bias = 0;
michael@0 23315 var count = type1Subrs.length;
michael@0 23316 if (count < 1133) {
michael@0 23317 bias = 107;
michael@0 23318 } else if (count < 33769) {
michael@0 23319 bias = 1131;
michael@0 23320 } else {
michael@0 23321 bias = 32768;
michael@0 23322 }
michael@0 23323
michael@0 23324 // Add a bunch of empty subrs to deal with the Type2 bias
michael@0 23325 var type2Subrs = [];
michael@0 23326 var i;
michael@0 23327 for (i = 0; i < bias; i++) {
michael@0 23328 type2Subrs.push([0x0B]);
michael@0 23329 }
michael@0 23330
michael@0 23331 for (i = 0; i < count; i++) {
michael@0 23332 type2Subrs.push(type1Subrs[i]);
michael@0 23333 }
michael@0 23334
michael@0 23335 return type2Subrs;
michael@0 23336 },
michael@0 23337
michael@0 23338 wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
michael@0 23339 var cff = new CFF();
michael@0 23340 cff.header = new CFFHeader(1, 0, 4, 4);
michael@0 23341
michael@0 23342 cff.names = [name];
michael@0 23343
michael@0 23344 var topDict = new CFFTopDict();
michael@0 23345 // CFF strings IDs 0...390 are predefined names, so refering
michael@0 23346 // to entries in our own String INDEX starts at SID 391.
michael@0 23347 topDict.setByName('version', 391);
michael@0 23348 topDict.setByName('Notice', 392);
michael@0 23349 topDict.setByName('FullName', 393);
michael@0 23350 topDict.setByName('FamilyName', 394);
michael@0 23351 topDict.setByName('Weight', 395);
michael@0 23352 topDict.setByName('Encoding', null); // placeholder
michael@0 23353 topDict.setByName('FontMatrix', properties.fontMatrix);
michael@0 23354 topDict.setByName('FontBBox', properties.bbox);
michael@0 23355 topDict.setByName('charset', null); // placeholder
michael@0 23356 topDict.setByName('CharStrings', null); // placeholder
michael@0 23357 topDict.setByName('Private', null); // placeholder
michael@0 23358 cff.topDict = topDict;
michael@0 23359
michael@0 23360 var strings = new CFFStrings();
michael@0 23361 strings.add('Version 0.11'); // Version
michael@0 23362 strings.add('See original notice'); // Notice
michael@0 23363 strings.add(name); // FullName
michael@0 23364 strings.add(name); // FamilyName
michael@0 23365 strings.add('Medium'); // Weight
michael@0 23366 cff.strings = strings;
michael@0 23367
michael@0 23368 cff.globalSubrIndex = new CFFIndex();
michael@0 23369
michael@0 23370 var count = glyphs.length;
michael@0 23371 var charsetArray = [0];
michael@0 23372 var i, ii;
michael@0 23373 for (i = 0; i < count; i++) {
michael@0 23374 var index = CFFStandardStrings.indexOf(charstrings[i].glyphName);
michael@0 23375 // TODO: Insert the string and correctly map it. Previously it was
michael@0 23376 // thought mapping names that aren't in the standard strings to .notdef
michael@0 23377 // was fine, however in issue818 when mapping them all to .notdef the
michael@0 23378 // adieresis glyph no longer worked.
michael@0 23379 if (index == -1) {
michael@0 23380 index = 0;
michael@0 23381 }
michael@0 23382 charsetArray.push((index >> 8) & 0xff, index & 0xff);
michael@0 23383 }
michael@0 23384 cff.charset = new CFFCharset(false, 0, [], charsetArray);
michael@0 23385
michael@0 23386 var charStringsIndex = new CFFIndex();
michael@0 23387 charStringsIndex.add([0x8B, 0x0E]); // .notdef
michael@0 23388 for (i = 0; i < count; i++) {
michael@0 23389 charStringsIndex.add(glyphs[i]);
michael@0 23390 }
michael@0 23391 cff.charStrings = charStringsIndex;
michael@0 23392
michael@0 23393 var privateDict = new CFFPrivateDict();
michael@0 23394 privateDict.setByName('Subrs', null); // placeholder
michael@0 23395 var fields = [
michael@0 23396 'BlueValues',
michael@0 23397 'OtherBlues',
michael@0 23398 'FamilyBlues',
michael@0 23399 'FamilyOtherBlues',
michael@0 23400 'StemSnapH',
michael@0 23401 'StemSnapV',
michael@0 23402 'BlueShift',
michael@0 23403 'BlueFuzz',
michael@0 23404 'BlueScale',
michael@0 23405 'LanguageGroup',
michael@0 23406 'ExpansionFactor',
michael@0 23407 'ForceBold',
michael@0 23408 'StdHW',
michael@0 23409 'StdVW'
michael@0 23410 ];
michael@0 23411 for (i = 0, ii = fields.length; i < ii; i++) {
michael@0 23412 var field = fields[i];
michael@0 23413 if (!properties.privateData.hasOwnProperty(field)) {
michael@0 23414 continue;
michael@0 23415 }
michael@0 23416 var value = properties.privateData[field];
michael@0 23417 if (isArray(value)) {
michael@0 23418 // All of the private dictionary array data in CFF must be stored as
michael@0 23419 // "delta-encoded" numbers.
michael@0 23420 for (var j = value.length - 1; j > 0; j--) {
michael@0 23421 value[j] -= value[j - 1]; // ... difference from previous value
michael@0 23422 }
michael@0 23423 }
michael@0 23424 privateDict.setByName(field, value);
michael@0 23425 }
michael@0 23426 cff.topDict.privateDict = privateDict;
michael@0 23427
michael@0 23428 var subrIndex = new CFFIndex();
michael@0 23429 for (i = 0, ii = subrs.length; i < ii; i++) {
michael@0 23430 subrIndex.add(subrs[i]);
michael@0 23431 }
michael@0 23432 privateDict.subrsIndex = subrIndex;
michael@0 23433
michael@0 23434 var compiler = new CFFCompiler(cff);
michael@0 23435 return compiler.compile();
michael@0 23436 }
michael@0 23437 };
michael@0 23438
michael@0 23439 var CFFFont = (function CFFFontClosure() {
michael@0 23440 function CFFFont(file, properties) {
michael@0 23441 this.properties = properties;
michael@0 23442
michael@0 23443 var parser = new CFFParser(file, properties);
michael@0 23444 this.cff = parser.parse();
michael@0 23445 var compiler = new CFFCompiler(this.cff);
michael@0 23446 this.seacs = this.cff.seacs;
michael@0 23447 try {
michael@0 23448 this.data = compiler.compile();
michael@0 23449 } catch (e) {
michael@0 23450 warn('Failed to compile font ' + properties.loadedName);
michael@0 23451 // There may have just been an issue with the compiler, set the data
michael@0 23452 // anyway and hope the font loaded.
michael@0 23453 this.data = file;
michael@0 23454 }
michael@0 23455 }
michael@0 23456
michael@0 23457 CFFFont.prototype = {
michael@0 23458 get numGlyphs() {
michael@0 23459 return this.cff.charStrings.count;
michael@0 23460 },
michael@0 23461 getCharset: function CFFFont_getCharset() {
michael@0 23462 return this.cff.charset.charset;
michael@0 23463 },
michael@0 23464 getGlyphMapping: function CFFFont_getGlyphMapping() {
michael@0 23465 var cff = this.cff;
michael@0 23466 var properties = this.properties;
michael@0 23467 var charsets = cff.charset.charset;
michael@0 23468 var charCodeToGlyphId;
michael@0 23469 var glyphId;
michael@0 23470
michael@0 23471 if (properties.composite) {
michael@0 23472 charCodeToGlyphId = Object.create(null);
michael@0 23473 if (cff.isCIDFont) {
michael@0 23474 // If the font is actually a CID font then we should use the charset
michael@0 23475 // to map CIDs to GIDs.
michael@0 23476 for (glyphId = 0; glyphId < charsets.length; glyphId++) {
michael@0 23477 var cidString = String.fromCharCode(charsets[glyphId]);
michael@0 23478 var charCode = properties.cMap.map.indexOf(cidString);
michael@0 23479 charCodeToGlyphId[charCode] = glyphId;
michael@0 23480 }
michael@0 23481 } else {
michael@0 23482 // If it is NOT actually a CID font then CIDs should be mapped
michael@0 23483 // directly to GIDs.
michael@0 23484 for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) {
michael@0 23485 charCodeToGlyphId[glyphId] = glyphId;
michael@0 23486 }
michael@0 23487 }
michael@0 23488 return charCodeToGlyphId;
michael@0 23489 }
michael@0 23490
michael@0 23491 var encoding = cff.encoding ? cff.encoding.encoding : null;
michael@0 23492 charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets);
michael@0 23493 return charCodeToGlyphId;
michael@0 23494 }
michael@0 23495 };
michael@0 23496
michael@0 23497 return CFFFont;
michael@0 23498 })();
michael@0 23499
michael@0 23500 var CFFParser = (function CFFParserClosure() {
michael@0 23501 var CharstringValidationData = [
michael@0 23502 null,
michael@0 23503 { id: 'hstem', min: 2, resetStack: true, stem: true },
michael@0 23504 null,
michael@0 23505 { id: 'vstem', min: 2, resetStack: true, stem: true },
michael@0 23506 { id: 'vmoveto', min: 1, resetStack: true },
michael@0 23507 { id: 'rlineto', min: 2, resetStack: true },
michael@0 23508 { id: 'hlineto', min: 1, resetStack: true },
michael@0 23509 { id: 'vlineto', min: 1, resetStack: true },
michael@0 23510 { id: 'rrcurveto', min: 6, resetStack: true },
michael@0 23511 null,
michael@0 23512 { id: 'callsubr', min: 1, undefStack: true },
michael@0 23513 { id: 'return', min: 0, undefStack: true },
michael@0 23514 null, // 12
michael@0 23515 null,
michael@0 23516 null, // endchar
michael@0 23517 null,
michael@0 23518 null,
michael@0 23519 null,
michael@0 23520 { id: 'hstemhm', min: 2, resetStack: true, stem: true },
michael@0 23521 null, // hintmask
michael@0 23522 null, // cntrmask
michael@0 23523 { id: 'rmoveto', min: 2, resetStack: true },
michael@0 23524 { id: 'hmoveto', min: 1, resetStack: true },
michael@0 23525 { id: 'vstemhm', min: 2, resetStack: true, stem: true },
michael@0 23526 { id: 'rcurveline', min: 8, resetStack: true },
michael@0 23527 { id: 'rlinecurve', min: 8, resetStack: true },
michael@0 23528 { id: 'vvcurveto', min: 4, resetStack: true },
michael@0 23529 { id: 'hhcurveto', min: 4, resetStack: true },
michael@0 23530 null, // shortint
michael@0 23531 { id: 'callgsubr', min: 1, undefStack: true },
michael@0 23532 { id: 'vhcurveto', min: 4, resetStack: true },
michael@0 23533 { id: 'hvcurveto', min: 4, resetStack: true }
michael@0 23534 ];
michael@0 23535 var CharstringValidationData12 = [
michael@0 23536 null,
michael@0 23537 null,
michael@0 23538 null,
michael@0 23539 { id: 'and', min: 2, stackDelta: -1 },
michael@0 23540 { id: 'or', min: 2, stackDelta: -1 },
michael@0 23541 { id: 'not', min: 1, stackDelta: 0 },
michael@0 23542 null,
michael@0 23543 null,
michael@0 23544 null,
michael@0 23545 { id: 'abs', min: 1, stackDelta: 0 },
michael@0 23546 { id: 'add', min: 2, stackDelta: -1,
michael@0 23547 stackFn: function stack_div(stack, index) {
michael@0 23548 stack[index - 2] = stack[index - 2] + stack[index - 1];
michael@0 23549 }
michael@0 23550 },
michael@0 23551 { id: 'sub', min: 2, stackDelta: -1,
michael@0 23552 stackFn: function stack_div(stack, index) {
michael@0 23553 stack[index - 2] = stack[index - 2] - stack[index - 1];
michael@0 23554 }
michael@0 23555 },
michael@0 23556 { id: 'div', min: 2, stackDelta: -1,
michael@0 23557 stackFn: function stack_div(stack, index) {
michael@0 23558 stack[index - 2] = stack[index - 2] / stack[index - 1];
michael@0 23559 }
michael@0 23560 },
michael@0 23561 null,
michael@0 23562 { id: 'neg', min: 1, stackDelta: 0,
michael@0 23563 stackFn: function stack_div(stack, index) {
michael@0 23564 stack[index - 1] = -stack[index - 1];
michael@0 23565 }
michael@0 23566 },
michael@0 23567 { id: 'eq', min: 2, stackDelta: -1 },
michael@0 23568 null,
michael@0 23569 null,
michael@0 23570 { id: 'drop', min: 1, stackDelta: -1 },
michael@0 23571 null,
michael@0 23572 { id: 'put', min: 2, stackDelta: -2 },
michael@0 23573 { id: 'get', min: 1, stackDelta: 0 },
michael@0 23574 { id: 'ifelse', min: 4, stackDelta: -3 },
michael@0 23575 { id: 'random', min: 0, stackDelta: 1 },
michael@0 23576 { id: 'mul', min: 2, stackDelta: -1,
michael@0 23577 stackFn: function stack_div(stack, index) {
michael@0 23578 stack[index - 2] = stack[index - 2] * stack[index - 1];
michael@0 23579 }
michael@0 23580 },
michael@0 23581 null,
michael@0 23582 { id: 'sqrt', min: 1, stackDelta: 0 },
michael@0 23583 { id: 'dup', min: 1, stackDelta: 1 },
michael@0 23584 { id: 'exch', min: 2, stackDelta: 0 },
michael@0 23585 { id: 'index', min: 2, stackDelta: 0 },
michael@0 23586 { id: 'roll', min: 3, stackDelta: -2 },
michael@0 23587 null,
michael@0 23588 null,
michael@0 23589 null,
michael@0 23590 { id: 'hflex', min: 7, resetStack: true },
michael@0 23591 { id: 'flex', min: 13, resetStack: true },
michael@0 23592 { id: 'hflex1', min: 9, resetStack: true },
michael@0 23593 { id: 'flex1', min: 11, resetStack: true }
michael@0 23594 ];
michael@0 23595
michael@0 23596 function CFFParser(file, properties) {
michael@0 23597 this.bytes = file.getBytes();
michael@0 23598 this.properties = properties;
michael@0 23599 }
michael@0 23600 CFFParser.prototype = {
michael@0 23601 parse: function CFFParser_parse() {
michael@0 23602 var properties = this.properties;
michael@0 23603 var cff = new CFF();
michael@0 23604 this.cff = cff;
michael@0 23605
michael@0 23606 // The first five sections must be in order, all the others are reached
michael@0 23607 // via offsets contained in one of the below.
michael@0 23608 var header = this.parseHeader();
michael@0 23609 var nameIndex = this.parseIndex(header.endPos);
michael@0 23610 var topDictIndex = this.parseIndex(nameIndex.endPos);
michael@0 23611 var stringIndex = this.parseIndex(topDictIndex.endPos);
michael@0 23612 var globalSubrIndex = this.parseIndex(stringIndex.endPos);
michael@0 23613
michael@0 23614 var topDictParsed = this.parseDict(topDictIndex.obj.get(0));
michael@0 23615 var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
michael@0 23616
michael@0 23617 cff.header = header.obj;
michael@0 23618 cff.names = this.parseNameIndex(nameIndex.obj);
michael@0 23619 cff.strings = this.parseStringIndex(stringIndex.obj);
michael@0 23620 cff.topDict = topDict;
michael@0 23621 cff.globalSubrIndex = globalSubrIndex.obj;
michael@0 23622
michael@0 23623 this.parsePrivateDict(cff.topDict);
michael@0 23624
michael@0 23625 cff.isCIDFont = topDict.hasName('ROS');
michael@0 23626
michael@0 23627 var charStringOffset = topDict.getByName('CharStrings');
michael@0 23628 var charStringsAndSeacs = this.parseCharStrings(charStringOffset);
michael@0 23629 cff.charStrings = charStringsAndSeacs.charStrings;
michael@0 23630 cff.seacs = charStringsAndSeacs.seacs;
michael@0 23631
michael@0 23632 var fontMatrix = topDict.getByName('FontMatrix');
michael@0 23633 if (fontMatrix) {
michael@0 23634 properties.fontMatrix = fontMatrix;
michael@0 23635 }
michael@0 23636
michael@0 23637 var fontBBox = topDict.getByName('FontBBox');
michael@0 23638 if (fontBBox) {
michael@0 23639 // adjusting ascent/descent
michael@0 23640 properties.ascent = fontBBox[3];
michael@0 23641 properties.descent = fontBBox[1];
michael@0 23642 properties.ascentScaled = true;
michael@0 23643 }
michael@0 23644
michael@0 23645 var charset, encoding;
michael@0 23646 if (cff.isCIDFont) {
michael@0 23647 var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
michael@0 23648 for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
michael@0 23649 var dictRaw = fdArrayIndex.get(i);
michael@0 23650 var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw),
michael@0 23651 cff.strings);
michael@0 23652 this.parsePrivateDict(fontDict);
michael@0 23653 cff.fdArray.push(fontDict);
michael@0 23654 }
michael@0 23655 // cid fonts don't have an encoding
michael@0 23656 encoding = null;
michael@0 23657 charset = this.parseCharsets(topDict.getByName('charset'),
michael@0 23658 cff.charStrings.count, cff.strings, true);
michael@0 23659 cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'),
michael@0 23660 cff.charStrings.count);
michael@0 23661 } else {
michael@0 23662 charset = this.parseCharsets(topDict.getByName('charset'),
michael@0 23663 cff.charStrings.count, cff.strings, false);
michael@0 23664 encoding = this.parseEncoding(topDict.getByName('Encoding'),
michael@0 23665 properties,
michael@0 23666 cff.strings, charset.charset);
michael@0 23667 }
michael@0 23668 cff.charset = charset;
michael@0 23669 cff.encoding = encoding;
michael@0 23670
michael@0 23671 return cff;
michael@0 23672 },
michael@0 23673 parseHeader: function CFFParser_parseHeader() {
michael@0 23674 var bytes = this.bytes;
michael@0 23675 var bytesLength = bytes.length;
michael@0 23676 var offset = 0;
michael@0 23677
michael@0 23678 // Prevent an infinite loop, by checking that the offset is within the
michael@0 23679 // bounds of the bytes array. Necessary in empty, or invalid, font files.
michael@0 23680 while (offset < bytesLength && bytes[offset] !== 1) {
michael@0 23681 ++offset;
michael@0 23682 }
michael@0 23683 if (offset >= bytesLength) {
michael@0 23684 error('Invalid CFF header');
michael@0 23685 } else if (offset !== 0) {
michael@0 23686 info('cff data is shifted');
michael@0 23687 bytes = bytes.subarray(offset);
michael@0 23688 this.bytes = bytes;
michael@0 23689 }
michael@0 23690 var major = bytes[0];
michael@0 23691 var minor = bytes[1];
michael@0 23692 var hdrSize = bytes[2];
michael@0 23693 var offSize = bytes[3];
michael@0 23694 var header = new CFFHeader(major, minor, hdrSize, offSize);
michael@0 23695 return { obj: header, endPos: hdrSize };
michael@0 23696 },
michael@0 23697 parseDict: function CFFParser_parseDict(dict) {
michael@0 23698 var pos = 0;
michael@0 23699
michael@0 23700 function parseOperand() {
michael@0 23701 var value = dict[pos++];
michael@0 23702 if (value === 30) {
michael@0 23703 return parseFloatOperand(pos);
michael@0 23704 } else if (value === 28) {
michael@0 23705 value = dict[pos++];
michael@0 23706 value = ((value << 24) | (dict[pos++] << 16)) >> 16;
michael@0 23707 return value;
michael@0 23708 } else if (value === 29) {
michael@0 23709 value = dict[pos++];
michael@0 23710 value = (value << 8) | dict[pos++];
michael@0 23711 value = (value << 8) | dict[pos++];
michael@0 23712 value = (value << 8) | dict[pos++];
michael@0 23713 return value;
michael@0 23714 } else if (value >= 32 && value <= 246) {
michael@0 23715 return value - 139;
michael@0 23716 } else if (value >= 247 && value <= 250) {
michael@0 23717 return ((value - 247) * 256) + dict[pos++] + 108;
michael@0 23718 } else if (value >= 251 && value <= 254) {
michael@0 23719 return -((value - 251) * 256) - dict[pos++] - 108;
michael@0 23720 } else {
michael@0 23721 error('255 is not a valid DICT command');
michael@0 23722 }
michael@0 23723 return -1;
michael@0 23724 }
michael@0 23725
michael@0 23726 function parseFloatOperand() {
michael@0 23727 var str = '';
michael@0 23728 var eof = 15;
michael@0 23729 var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8',
michael@0 23730 '9', '.', 'E', 'E-', null, '-'];
michael@0 23731 var length = dict.length;
michael@0 23732 while (pos < length) {
michael@0 23733 var b = dict[pos++];
michael@0 23734 var b1 = b >> 4;
michael@0 23735 var b2 = b & 15;
michael@0 23736
michael@0 23737 if (b1 == eof) {
michael@0 23738 break;
michael@0 23739 }
michael@0 23740 str += lookup[b1];
michael@0 23741
michael@0 23742 if (b2 == eof) {
michael@0 23743 break;
michael@0 23744 }
michael@0 23745 str += lookup[b2];
michael@0 23746 }
michael@0 23747 return parseFloat(str);
michael@0 23748 }
michael@0 23749
michael@0 23750 var operands = [];
michael@0 23751 var entries = [];
michael@0 23752
michael@0 23753 pos = 0;
michael@0 23754 var end = dict.length;
michael@0 23755 while (pos < end) {
michael@0 23756 var b = dict[pos];
michael@0 23757 if (b <= 21) {
michael@0 23758 if (b === 12) {
michael@0 23759 b = (b << 8) | dict[++pos];
michael@0 23760 }
michael@0 23761 entries.push([b, operands]);
michael@0 23762 operands = [];
michael@0 23763 ++pos;
michael@0 23764 } else {
michael@0 23765 operands.push(parseOperand());
michael@0 23766 }
michael@0 23767 }
michael@0 23768 return entries;
michael@0 23769 },
michael@0 23770 parseIndex: function CFFParser_parseIndex(pos) {
michael@0 23771 var cffIndex = new CFFIndex();
michael@0 23772 var bytes = this.bytes;
michael@0 23773 var count = (bytes[pos++] << 8) | bytes[pos++];
michael@0 23774 var offsets = [];
michael@0 23775 var end = pos;
michael@0 23776 var i, ii;
michael@0 23777
michael@0 23778 if (count !== 0) {
michael@0 23779 var offsetSize = bytes[pos++];
michael@0 23780 // add 1 for offset to determine size of last object
michael@0 23781 var startPos = pos + ((count + 1) * offsetSize) - 1;
michael@0 23782
michael@0 23783 for (i = 0, ii = count + 1; i < ii; ++i) {
michael@0 23784 var offset = 0;
michael@0 23785 for (var j = 0; j < offsetSize; ++j) {
michael@0 23786 offset <<= 8;
michael@0 23787 offset += bytes[pos++];
michael@0 23788 }
michael@0 23789 offsets.push(startPos + offset);
michael@0 23790 }
michael@0 23791 end = offsets[count];
michael@0 23792 }
michael@0 23793 for (i = 0, ii = offsets.length - 1; i < ii; ++i) {
michael@0 23794 var offsetStart = offsets[i];
michael@0 23795 var offsetEnd = offsets[i + 1];
michael@0 23796 cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
michael@0 23797 }
michael@0 23798 return {obj: cffIndex, endPos: end};
michael@0 23799 },
michael@0 23800 parseNameIndex: function CFFParser_parseNameIndex(index) {
michael@0 23801 var names = [];
michael@0 23802 for (var i = 0, ii = index.count; i < ii; ++i) {
michael@0 23803 var name = index.get(i);
michael@0 23804 // OTS doesn't allow names to be over 127 characters.
michael@0 23805 var length = Math.min(name.length, 127);
michael@0 23806 var data = [];
michael@0 23807 // OTS also only permits certain characters in the name.
michael@0 23808 for (var j = 0; j < length; ++j) {
michael@0 23809 var c = name[j];
michael@0 23810 if (j === 0 && c === 0) {
michael@0 23811 data[j] = c;
michael@0 23812 continue;
michael@0 23813 }
michael@0 23814 if ((c < 33 || c > 126) || c === 91 /* [ */ || c === 93 /* ] */ ||
michael@0 23815 c === 40 /* ( */ || c === 41 /* ) */ || c === 123 /* { */ ||
michael@0 23816 c === 125 /* } */ || c === 60 /* < */ || c === 62 /* > */ ||
michael@0 23817 c === 47 /* / */ || c === 37 /* % */ || c === 35 /* # */) {
michael@0 23818 data[j] = 95;
michael@0 23819 continue;
michael@0 23820 }
michael@0 23821 data[j] = c;
michael@0 23822 }
michael@0 23823 names.push(bytesToString(data));
michael@0 23824 }
michael@0 23825 return names;
michael@0 23826 },
michael@0 23827 parseStringIndex: function CFFParser_parseStringIndex(index) {
michael@0 23828 var strings = new CFFStrings();
michael@0 23829 for (var i = 0, ii = index.count; i < ii; ++i) {
michael@0 23830 var data = index.get(i);
michael@0 23831 strings.add(bytesToString(data));
michael@0 23832 }
michael@0 23833 return strings;
michael@0 23834 },
michael@0 23835 createDict: function CFFParser_createDict(Type, dict, strings) {
michael@0 23836 var cffDict = new Type(strings);
michael@0 23837 for (var i = 0, ii = dict.length; i < ii; ++i) {
michael@0 23838 var pair = dict[i];
michael@0 23839 var key = pair[0];
michael@0 23840 var value = pair[1];
michael@0 23841 cffDict.setByKey(key, value);
michael@0 23842 }
michael@0 23843 return cffDict;
michael@0 23844 },
michael@0 23845 parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) {
michael@0 23846 var charStrings = this.parseIndex(charStringOffset).obj;
michael@0 23847 var seacs = [];
michael@0 23848 var count = charStrings.count;
michael@0 23849 for (var i = 0; i < count; i++) {
michael@0 23850 var charstring = charStrings.get(i);
michael@0 23851
michael@0 23852 var stackSize = 0;
michael@0 23853 var stack = [];
michael@0 23854 var undefStack = true;
michael@0 23855 var hints = 0;
michael@0 23856 var valid = true;
michael@0 23857 var data = charstring;
michael@0 23858 var length = data.length;
michael@0 23859 for (var j = 0; j < length;) {
michael@0 23860 var value = data[j++];
michael@0 23861 var validationCommand = null;
michael@0 23862 if (value == 12) {
michael@0 23863 var q = data[j++];
michael@0 23864 if (q === 0) {
michael@0 23865 // The CFF specification state that the 'dotsection' command
michael@0 23866 // (12, 0) is deprecated and treated as a no-op, but all Type2
michael@0 23867 // charstrings processors should support them. Unfortunately
michael@0 23868 // the font sanitizer don't. As a workaround the sequence (12, 0)
michael@0 23869 // is replaced by a useless (0, hmoveto).
michael@0 23870 data[j - 2] = 139;
michael@0 23871 data[j - 1] = 22;
michael@0 23872 stackSize = 0;
michael@0 23873 } else {
michael@0 23874 validationCommand = CharstringValidationData12[q];
michael@0 23875 }
michael@0 23876 } else if (value === 28) { // number (16 bit)
michael@0 23877 stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16;
michael@0 23878 j += 2;
michael@0 23879 stackSize++;
michael@0 23880 } else if (value == 14) {
michael@0 23881 if (stackSize >= 4) {
michael@0 23882 stackSize -= 4;
michael@0 23883 if (SEAC_ANALYSIS_ENABLED) {
michael@0 23884 seacs[i] = stack.slice(stackSize, stackSize + 4);
michael@0 23885 valid = false;
michael@0 23886 }
michael@0 23887 }
michael@0 23888 } else if (value >= 32 && value <= 246) { // number
michael@0 23889 stack[stackSize] = value - 139;
michael@0 23890 stackSize++;
michael@0 23891 } else if (value >= 247 && value <= 254) { // number (+1 bytes)
michael@0 23892 stack[stackSize] = (value < 251 ?
michael@0 23893 ((value - 247) << 8) + data[j] + 108 :
michael@0 23894 -((value - 251) << 8) - data[j] - 108);
michael@0 23895 j++;
michael@0 23896 stackSize++;
michael@0 23897 } else if (value == 255) { // number (32 bit)
michael@0 23898 stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) |
michael@0 23899 (data[j + 2] << 8) | data[j + 3]) / 65536;
michael@0 23900 j += 4;
michael@0 23901 stackSize++;
michael@0 23902 } else if (value == 19 || value == 20) {
michael@0 23903 hints += stackSize >> 1;
michael@0 23904 j += (hints + 7) >> 3; // skipping right amount of hints flag data
michael@0 23905 stackSize = 0;
michael@0 23906 } else {
michael@0 23907 validationCommand = CharstringValidationData[value];
michael@0 23908 }
michael@0 23909 if (validationCommand) {
michael@0 23910 if (validationCommand.stem) {
michael@0 23911 hints += stackSize >> 1;
michael@0 23912 }
michael@0 23913 if ('min' in validationCommand) {
michael@0 23914 if (!undefStack && stackSize < validationCommand.min) {
michael@0 23915 warn('Not enough parameters for ' + validationCommand.id +
michael@0 23916 '; actual: ' + stackSize +
michael@0 23917 ', expected: ' + validationCommand.min);
michael@0 23918 valid = false;
michael@0 23919 break;
michael@0 23920 }
michael@0 23921 }
michael@0 23922 if ('stackDelta' in validationCommand) {
michael@0 23923 if ('stackFn' in validationCommand) {
michael@0 23924 validationCommand.stackFn(stack, stackSize);
michael@0 23925 }
michael@0 23926 stackSize += validationCommand.stackDelta;
michael@0 23927 } else if (validationCommand.resetStack) {
michael@0 23928 stackSize = 0;
michael@0 23929 undefStack = false;
michael@0 23930 } else if (validationCommand.undefStack) {
michael@0 23931 stackSize = 0;
michael@0 23932 undefStack = true;
michael@0 23933 }
michael@0 23934 }
michael@0 23935 }
michael@0 23936 if (!valid) {
michael@0 23937 // resetting invalid charstring to single 'endchar'
michael@0 23938 charStrings.set(i, new Uint8Array([14]));
michael@0 23939 }
michael@0 23940 }
michael@0 23941 return { charStrings: charStrings, seacs: seacs };
michael@0 23942 },
michael@0 23943 emptyPrivateDictionary:
michael@0 23944 function CFFParser_emptyPrivateDictionary(parentDict) {
michael@0 23945 var privateDict = this.createDict(CFFPrivateDict, [],
michael@0 23946 parentDict.strings);
michael@0 23947 parentDict.setByKey(18, [0, 0]);
michael@0 23948 parentDict.privateDict = privateDict;
michael@0 23949 },
michael@0 23950 parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
michael@0 23951 // no private dict, do nothing
michael@0 23952 if (!parentDict.hasName('Private')) {
michael@0 23953 this.emptyPrivateDictionary(parentDict);
michael@0 23954 return;
michael@0 23955 }
michael@0 23956 var privateOffset = parentDict.getByName('Private');
michael@0 23957 // make sure the params are formatted correctly
michael@0 23958 if (!isArray(privateOffset) || privateOffset.length !== 2) {
michael@0 23959 parentDict.removeByName('Private');
michael@0 23960 return;
michael@0 23961 }
michael@0 23962 var size = privateOffset[0];
michael@0 23963 var offset = privateOffset[1];
michael@0 23964 // remove empty dicts or ones that refer to invalid location
michael@0 23965 if (size === 0 || offset >= this.bytes.length) {
michael@0 23966 this.emptyPrivateDictionary(parentDict);
michael@0 23967 return;
michael@0 23968 }
michael@0 23969
michael@0 23970 var privateDictEnd = offset + size;
michael@0 23971 var dictData = this.bytes.subarray(offset, privateDictEnd);
michael@0 23972 var dict = this.parseDict(dictData);
michael@0 23973 var privateDict = this.createDict(CFFPrivateDict, dict,
michael@0 23974 parentDict.strings);
michael@0 23975 parentDict.privateDict = privateDict;
michael@0 23976
michael@0 23977 // Parse the Subrs index also since it's relative to the private dict.
michael@0 23978 if (!privateDict.getByName('Subrs')) {
michael@0 23979 return;
michael@0 23980 }
michael@0 23981 var subrsOffset = privateDict.getByName('Subrs');
michael@0 23982 var relativeOffset = offset + subrsOffset;
michael@0 23983 // Validate the offset.
michael@0 23984 if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
michael@0 23985 this.emptyPrivateDictionary(parentDict);
michael@0 23986 return;
michael@0 23987 }
michael@0 23988 var subrsIndex = this.parseIndex(relativeOffset);
michael@0 23989 privateDict.subrsIndex = subrsIndex.obj;
michael@0 23990 },
michael@0 23991 parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) {
michael@0 23992 if (pos === 0) {
michael@0 23993 return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE,
michael@0 23994 ISOAdobeCharset);
michael@0 23995 } else if (pos == 1) {
michael@0 23996 return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT,
michael@0 23997 ExpertCharset);
michael@0 23998 } else if (pos == 2) {
michael@0 23999 return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET,
michael@0 24000 ExpertSubsetCharset);
michael@0 24001 }
michael@0 24002
michael@0 24003 var bytes = this.bytes;
michael@0 24004 var start = pos;
michael@0 24005 var format = bytes[pos++];
michael@0 24006 var charset = ['.notdef'];
michael@0 24007 var id, count, i;
michael@0 24008
michael@0 24009 // subtract 1 for the .notdef glyph
michael@0 24010 length -= 1;
michael@0 24011
michael@0 24012 switch (format) {
michael@0 24013 case 0:
michael@0 24014 for (i = 0; i < length; i++) {
michael@0 24015 id = (bytes[pos++] << 8) | bytes[pos++];
michael@0 24016 charset.push(cid ? id : strings.get(id));
michael@0 24017 }
michael@0 24018 break;
michael@0 24019 case 1:
michael@0 24020 while (charset.length <= length) {
michael@0 24021 id = (bytes[pos++] << 8) | bytes[pos++];
michael@0 24022 count = bytes[pos++];
michael@0 24023 for (i = 0; i <= count; i++) {
michael@0 24024 charset.push(cid ? id++ : strings.get(id++));
michael@0 24025 }
michael@0 24026 }
michael@0 24027 break;
michael@0 24028 case 2:
michael@0 24029 while (charset.length <= length) {
michael@0 24030 id = (bytes[pos++] << 8) | bytes[pos++];
michael@0 24031 count = (bytes[pos++] << 8) | bytes[pos++];
michael@0 24032 for (i = 0; i <= count; i++) {
michael@0 24033 charset.push(cid ? id++ : strings.get(id++));
michael@0 24034 }
michael@0 24035 }
michael@0 24036 break;
michael@0 24037 default:
michael@0 24038 error('Unknown charset format');
michael@0 24039 }
michael@0 24040 // Raw won't be needed if we actually compile the charset.
michael@0 24041 var end = pos;
michael@0 24042 var raw = bytes.subarray(start, end);
michael@0 24043
michael@0 24044 return new CFFCharset(false, format, charset, raw);
michael@0 24045 },
michael@0 24046 parseEncoding: function CFFParser_parseEncoding(pos,
michael@0 24047 properties,
michael@0 24048 strings,
michael@0 24049 charset) {
michael@0 24050 var encoding = {};
michael@0 24051 var bytes = this.bytes;
michael@0 24052 var predefined = false;
michael@0 24053 var hasSupplement = false;
michael@0 24054 var format, i, ii;
michael@0 24055 var raw = null;
michael@0 24056
michael@0 24057 function readSupplement() {
michael@0 24058 var supplementsCount = bytes[pos++];
michael@0 24059 for (i = 0; i < supplementsCount; i++) {
michael@0 24060 var code = bytes[pos++];
michael@0 24061 var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
michael@0 24062 encoding[code] = charset.indexOf(strings.get(sid));
michael@0 24063 }
michael@0 24064 }
michael@0 24065
michael@0 24066 if (pos === 0 || pos == 1) {
michael@0 24067 predefined = true;
michael@0 24068 format = pos;
michael@0 24069 var baseEncoding = pos ? Encodings.ExpertEncoding :
michael@0 24070 Encodings.StandardEncoding;
michael@0 24071 for (i = 0, ii = charset.length; i < ii; i++) {
michael@0 24072 var index = baseEncoding.indexOf(charset[i]);
michael@0 24073 if (index != -1) {
michael@0 24074 encoding[index] = i;
michael@0 24075 }
michael@0 24076 }
michael@0 24077 } else {
michael@0 24078 var dataStart = pos;
michael@0 24079 format = bytes[pos++];
michael@0 24080 switch (format & 0x7f) {
michael@0 24081 case 0:
michael@0 24082 var glyphsCount = bytes[pos++];
michael@0 24083 for (i = 1; i <= glyphsCount; i++) {
michael@0 24084 encoding[bytes[pos++]] = i;
michael@0 24085 }
michael@0 24086 break;
michael@0 24087
michael@0 24088 case 1:
michael@0 24089 var rangesCount = bytes[pos++];
michael@0 24090 var gid = 1;
michael@0 24091 for (i = 0; i < rangesCount; i++) {
michael@0 24092 var start = bytes[pos++];
michael@0 24093 var left = bytes[pos++];
michael@0 24094 for (var j = start; j <= start + left; j++) {
michael@0 24095 encoding[j] = gid++;
michael@0 24096 }
michael@0 24097 }
michael@0 24098 break;
michael@0 24099
michael@0 24100 default:
michael@0 24101 error('Unknow encoding format: ' + format + ' in CFF');
michael@0 24102 break;
michael@0 24103 }
michael@0 24104 var dataEnd = pos;
michael@0 24105 if (format & 0x80) {
michael@0 24106 // The font sanitizer does not support CFF encoding with a
michael@0 24107 // supplement, since the encoding is not really used to map
michael@0 24108 // between gid to glyph, let's overwrite what is declared in
michael@0 24109 // the top dictionary to let the sanitizer think the font use
michael@0 24110 // StandardEncoding, that's a lie but that's ok.
michael@0 24111 bytes[dataStart] &= 0x7f;
michael@0 24112 readSupplement();
michael@0 24113 hasSupplement = true;
michael@0 24114 }
michael@0 24115 raw = bytes.subarray(dataStart, dataEnd);
michael@0 24116 }
michael@0 24117 format = format & 0x7f;
michael@0 24118 return new CFFEncoding(predefined, format, encoding, raw);
michael@0 24119 },
michael@0 24120 parseFDSelect: function CFFParser_parseFDSelect(pos, length) {
michael@0 24121 var start = pos;
michael@0 24122 var bytes = this.bytes;
michael@0 24123 var format = bytes[pos++];
michael@0 24124 var fdSelect = [];
michael@0 24125 var i;
michael@0 24126
michael@0 24127 switch (format) {
michael@0 24128 case 0:
michael@0 24129 for (i = 0; i < length; ++i) {
michael@0 24130 var id = bytes[pos++];
michael@0 24131 fdSelect.push(id);
michael@0 24132 }
michael@0 24133 break;
michael@0 24134 case 3:
michael@0 24135 var rangesCount = (bytes[pos++] << 8) | bytes[pos++];
michael@0 24136 for (i = 0; i < rangesCount; ++i) {
michael@0 24137 var first = (bytes[pos++] << 8) | bytes[pos++];
michael@0 24138 var fdIndex = bytes[pos++];
michael@0 24139 var next = (bytes[pos] << 8) | bytes[pos + 1];
michael@0 24140 for (var j = first; j < next; ++j) {
michael@0 24141 fdSelect.push(fdIndex);
michael@0 24142 }
michael@0 24143 }
michael@0 24144 // Advance past the sentinel(next).
michael@0 24145 pos += 2;
michael@0 24146 break;
michael@0 24147 default:
michael@0 24148 error('Unknown fdselect format ' + format);
michael@0 24149 break;
michael@0 24150 }
michael@0 24151 var end = pos;
michael@0 24152 return new CFFFDSelect(fdSelect, bytes.subarray(start, end));
michael@0 24153 }
michael@0 24154 };
michael@0 24155 return CFFParser;
michael@0 24156 })();
michael@0 24157
michael@0 24158 // Compact Font Format
michael@0 24159 var CFF = (function CFFClosure() {
michael@0 24160 function CFF() {
michael@0 24161 this.header = null;
michael@0 24162 this.names = [];
michael@0 24163 this.topDict = null;
michael@0 24164 this.strings = new CFFStrings();
michael@0 24165 this.globalSubrIndex = null;
michael@0 24166
michael@0 24167 // The following could really be per font, but since we only have one font
michael@0 24168 // store them here.
michael@0 24169 this.encoding = null;
michael@0 24170 this.charset = null;
michael@0 24171 this.charStrings = null;
michael@0 24172 this.fdArray = [];
michael@0 24173 this.fdSelect = null;
michael@0 24174
michael@0 24175 this.isCIDFont = false;
michael@0 24176 }
michael@0 24177 return CFF;
michael@0 24178 })();
michael@0 24179
michael@0 24180 var CFFHeader = (function CFFHeaderClosure() {
michael@0 24181 function CFFHeader(major, minor, hdrSize, offSize) {
michael@0 24182 this.major = major;
michael@0 24183 this.minor = minor;
michael@0 24184 this.hdrSize = hdrSize;
michael@0 24185 this.offSize = offSize;
michael@0 24186 }
michael@0 24187 return CFFHeader;
michael@0 24188 })();
michael@0 24189
michael@0 24190 var CFFStrings = (function CFFStringsClosure() {
michael@0 24191 function CFFStrings() {
michael@0 24192 this.strings = [];
michael@0 24193 }
michael@0 24194 CFFStrings.prototype = {
michael@0 24195 get: function CFFStrings_get(index) {
michael@0 24196 if (index >= 0 && index <= 390) {
michael@0 24197 return CFFStandardStrings[index];
michael@0 24198 }
michael@0 24199 if (index - 391 <= this.strings.length) {
michael@0 24200 return this.strings[index - 391];
michael@0 24201 }
michael@0 24202 return CFFStandardStrings[0];
michael@0 24203 },
michael@0 24204 add: function CFFStrings_add(value) {
michael@0 24205 this.strings.push(value);
michael@0 24206 },
michael@0 24207 get count() {
michael@0 24208 return this.strings.length;
michael@0 24209 }
michael@0 24210 };
michael@0 24211 return CFFStrings;
michael@0 24212 })();
michael@0 24213
michael@0 24214 var CFFIndex = (function CFFIndexClosure() {
michael@0 24215 function CFFIndex() {
michael@0 24216 this.objects = [];
michael@0 24217 this.length = 0;
michael@0 24218 }
michael@0 24219 CFFIndex.prototype = {
michael@0 24220 add: function CFFIndex_add(data) {
michael@0 24221 this.length += data.length;
michael@0 24222 this.objects.push(data);
michael@0 24223 },
michael@0 24224 set: function CFFIndex_set(index, data) {
michael@0 24225 this.length += data.length - this.objects[index].length;
michael@0 24226 this.objects[index] = data;
michael@0 24227 },
michael@0 24228 get: function CFFIndex_get(index) {
michael@0 24229 return this.objects[index];
michael@0 24230 },
michael@0 24231 get count() {
michael@0 24232 return this.objects.length;
michael@0 24233 }
michael@0 24234 };
michael@0 24235 return CFFIndex;
michael@0 24236 })();
michael@0 24237
michael@0 24238 var CFFDict = (function CFFDictClosure() {
michael@0 24239 function CFFDict(tables, strings) {
michael@0 24240 this.keyToNameMap = tables.keyToNameMap;
michael@0 24241 this.nameToKeyMap = tables.nameToKeyMap;
michael@0 24242 this.defaults = tables.defaults;
michael@0 24243 this.types = tables.types;
michael@0 24244 this.opcodes = tables.opcodes;
michael@0 24245 this.order = tables.order;
michael@0 24246 this.strings = strings;
michael@0 24247 this.values = {};
michael@0 24248 }
michael@0 24249 CFFDict.prototype = {
michael@0 24250 // value should always be an array
michael@0 24251 setByKey: function CFFDict_setByKey(key, value) {
michael@0 24252 if (!(key in this.keyToNameMap)) {
michael@0 24253 return false;
michael@0 24254 }
michael@0 24255 // ignore empty values
michael@0 24256 if (value.length === 0) {
michael@0 24257 return true;
michael@0 24258 }
michael@0 24259 var type = this.types[key];
michael@0 24260 // remove the array wrapping these types of values
michael@0 24261 if (type === 'num' || type === 'sid' || type === 'offset') {
michael@0 24262 value = value[0];
michael@0 24263 }
michael@0 24264 this.values[key] = value;
michael@0 24265 return true;
michael@0 24266 },
michael@0 24267 setByName: function CFFDict_setByName(name, value) {
michael@0 24268 if (!(name in this.nameToKeyMap)) {
michael@0 24269 error('Invalid dictionary name "' + name + '"');
michael@0 24270 }
michael@0 24271 this.values[this.nameToKeyMap[name]] = value;
michael@0 24272 },
michael@0 24273 hasName: function CFFDict_hasName(name) {
michael@0 24274 return this.nameToKeyMap[name] in this.values;
michael@0 24275 },
michael@0 24276 getByName: function CFFDict_getByName(name) {
michael@0 24277 if (!(name in this.nameToKeyMap)) {
michael@0 24278 error('Invalid dictionary name "' + name + '"');
michael@0 24279 }
michael@0 24280 var key = this.nameToKeyMap[name];
michael@0 24281 if (!(key in this.values)) {
michael@0 24282 return this.defaults[key];
michael@0 24283 }
michael@0 24284 return this.values[key];
michael@0 24285 },
michael@0 24286 removeByName: function CFFDict_removeByName(name) {
michael@0 24287 delete this.values[this.nameToKeyMap[name]];
michael@0 24288 }
michael@0 24289 };
michael@0 24290 CFFDict.createTables = function CFFDict_createTables(layout) {
michael@0 24291 var tables = {
michael@0 24292 keyToNameMap: {},
michael@0 24293 nameToKeyMap: {},
michael@0 24294 defaults: {},
michael@0 24295 types: {},
michael@0 24296 opcodes: {},
michael@0 24297 order: []
michael@0 24298 };
michael@0 24299 for (var i = 0, ii = layout.length; i < ii; ++i) {
michael@0 24300 var entry = layout[i];
michael@0 24301 var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
michael@0 24302 tables.keyToNameMap[key] = entry[1];
michael@0 24303 tables.nameToKeyMap[entry[1]] = key;
michael@0 24304 tables.types[key] = entry[2];
michael@0 24305 tables.defaults[key] = entry[3];
michael@0 24306 tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]];
michael@0 24307 tables.order.push(key);
michael@0 24308 }
michael@0 24309 return tables;
michael@0 24310 };
michael@0 24311 return CFFDict;
michael@0 24312 })();
michael@0 24313
michael@0 24314 var CFFTopDict = (function CFFTopDictClosure() {
michael@0 24315 var layout = [
michael@0 24316 [[12, 30], 'ROS', ['sid', 'sid', 'num'], null],
michael@0 24317 [[12, 20], 'SyntheticBase', 'num', null],
michael@0 24318 [0, 'version', 'sid', null],
michael@0 24319 [1, 'Notice', 'sid', null],
michael@0 24320 [[12, 0], 'Copyright', 'sid', null],
michael@0 24321 [2, 'FullName', 'sid', null],
michael@0 24322 [3, 'FamilyName', 'sid', null],
michael@0 24323 [4, 'Weight', 'sid', null],
michael@0 24324 [[12, 1], 'isFixedPitch', 'num', 0],
michael@0 24325 [[12, 2], 'ItalicAngle', 'num', 0],
michael@0 24326 [[12, 3], 'UnderlinePosition', 'num', -100],
michael@0 24327 [[12, 4], 'UnderlineThickness', 'num', 50],
michael@0 24328 [[12, 5], 'PaintType', 'num', 0],
michael@0 24329 [[12, 6], 'CharstringType', 'num', 2],
michael@0 24330 [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'],
michael@0 24331 [0.001, 0, 0, 0.001, 0, 0]],
michael@0 24332 [13, 'UniqueID', 'num', null],
michael@0 24333 [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]],
michael@0 24334 [[12, 8], 'StrokeWidth', 'num', 0],
michael@0 24335 [14, 'XUID', 'array', null],
michael@0 24336 [15, 'charset', 'offset', 0],
michael@0 24337 [16, 'Encoding', 'offset', 0],
michael@0 24338 [17, 'CharStrings', 'offset', 0],
michael@0 24339 [18, 'Private', ['offset', 'offset'], null],
michael@0 24340 [[12, 21], 'PostScript', 'sid', null],
michael@0 24341 [[12, 22], 'BaseFontName', 'sid', null],
michael@0 24342 [[12, 23], 'BaseFontBlend', 'delta', null],
michael@0 24343 [[12, 31], 'CIDFontVersion', 'num', 0],
michael@0 24344 [[12, 32], 'CIDFontRevision', 'num', 0],
michael@0 24345 [[12, 33], 'CIDFontType', 'num', 0],
michael@0 24346 [[12, 34], 'CIDCount', 'num', 8720],
michael@0 24347 [[12, 35], 'UIDBase', 'num', null],
michael@0 24348 // XXX: CID Fonts on DirectWrite 6.1 only seem to work if FDSelect comes
michael@0 24349 // before FDArray.
michael@0 24350 [[12, 37], 'FDSelect', 'offset', null],
michael@0 24351 [[12, 36], 'FDArray', 'offset', null],
michael@0 24352 [[12, 38], 'FontName', 'sid', null]
michael@0 24353 ];
michael@0 24354 var tables = null;
michael@0 24355 function CFFTopDict(strings) {
michael@0 24356 if (tables === null) {
michael@0 24357 tables = CFFDict.createTables(layout);
michael@0 24358 }
michael@0 24359 CFFDict.call(this, tables, strings);
michael@0 24360 this.privateDict = null;
michael@0 24361 }
michael@0 24362 CFFTopDict.prototype = Object.create(CFFDict.prototype);
michael@0 24363 return CFFTopDict;
michael@0 24364 })();
michael@0 24365
michael@0 24366 var CFFPrivateDict = (function CFFPrivateDictClosure() {
michael@0 24367 var layout = [
michael@0 24368 [6, 'BlueValues', 'delta', null],
michael@0 24369 [7, 'OtherBlues', 'delta', null],
michael@0 24370 [8, 'FamilyBlues', 'delta', null],
michael@0 24371 [9, 'FamilyOtherBlues', 'delta', null],
michael@0 24372 [[12, 9], 'BlueScale', 'num', 0.039625],
michael@0 24373 [[12, 10], 'BlueShift', 'num', 7],
michael@0 24374 [[12, 11], 'BlueFuzz', 'num', 1],
michael@0 24375 [10, 'StdHW', 'num', null],
michael@0 24376 [11, 'StdVW', 'num', null],
michael@0 24377 [[12, 12], 'StemSnapH', 'delta', null],
michael@0 24378 [[12, 13], 'StemSnapV', 'delta', null],
michael@0 24379 [[12, 14], 'ForceBold', 'num', 0],
michael@0 24380 [[12, 17], 'LanguageGroup', 'num', 0],
michael@0 24381 [[12, 18], 'ExpansionFactor', 'num', 0.06],
michael@0 24382 [[12, 19], 'initialRandomSeed', 'num', 0],
michael@0 24383 [20, 'defaultWidthX', 'num', 0],
michael@0 24384 [21, 'nominalWidthX', 'num', 0],
michael@0 24385 [19, 'Subrs', 'offset', null]
michael@0 24386 ];
michael@0 24387 var tables = null;
michael@0 24388 function CFFPrivateDict(strings) {
michael@0 24389 if (tables === null) {
michael@0 24390 tables = CFFDict.createTables(layout);
michael@0 24391 }
michael@0 24392 CFFDict.call(this, tables, strings);
michael@0 24393 this.subrsIndex = null;
michael@0 24394 }
michael@0 24395 CFFPrivateDict.prototype = Object.create(CFFDict.prototype);
michael@0 24396 return CFFPrivateDict;
michael@0 24397 })();
michael@0 24398
michael@0 24399 var CFFCharsetPredefinedTypes = {
michael@0 24400 ISO_ADOBE: 0,
michael@0 24401 EXPERT: 1,
michael@0 24402 EXPERT_SUBSET: 2
michael@0 24403 };
michael@0 24404 var CFFCharset = (function CFFCharsetClosure() {
michael@0 24405 function CFFCharset(predefined, format, charset, raw) {
michael@0 24406 this.predefined = predefined;
michael@0 24407 this.format = format;
michael@0 24408 this.charset = charset;
michael@0 24409 this.raw = raw;
michael@0 24410 }
michael@0 24411 return CFFCharset;
michael@0 24412 })();
michael@0 24413
michael@0 24414 var CFFEncoding = (function CFFEncodingClosure() {
michael@0 24415 function CFFEncoding(predefined, format, encoding, raw) {
michael@0 24416 this.predefined = predefined;
michael@0 24417 this.format = format;
michael@0 24418 this.encoding = encoding;
michael@0 24419 this.raw = raw;
michael@0 24420 }
michael@0 24421 return CFFEncoding;
michael@0 24422 })();
michael@0 24423
michael@0 24424 var CFFFDSelect = (function CFFFDSelectClosure() {
michael@0 24425 function CFFFDSelect(fdSelect, raw) {
michael@0 24426 this.fdSelect = fdSelect;
michael@0 24427 this.raw = raw;
michael@0 24428 }
michael@0 24429 return CFFFDSelect;
michael@0 24430 })();
michael@0 24431
michael@0 24432 // Helper class to keep track of where an offset is within the data and helps
michael@0 24433 // filling in that offset once it's known.
michael@0 24434 var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
michael@0 24435 function CFFOffsetTracker() {
michael@0 24436 this.offsets = {};
michael@0 24437 }
michael@0 24438 CFFOffsetTracker.prototype = {
michael@0 24439 isTracking: function CFFOffsetTracker_isTracking(key) {
michael@0 24440 return key in this.offsets;
michael@0 24441 },
michael@0 24442 track: function CFFOffsetTracker_track(key, location) {
michael@0 24443 if (key in this.offsets) {
michael@0 24444 error('Already tracking location of ' + key);
michael@0 24445 }
michael@0 24446 this.offsets[key] = location;
michael@0 24447 },
michael@0 24448 offset: function CFFOffsetTracker_offset(value) {
michael@0 24449 for (var key in this.offsets) {
michael@0 24450 this.offsets[key] += value;
michael@0 24451 }
michael@0 24452 },
michael@0 24453 setEntryLocation: function CFFOffsetTracker_setEntryLocation(key,
michael@0 24454 values,
michael@0 24455 output) {
michael@0 24456 if (!(key in this.offsets)) {
michael@0 24457 error('Not tracking location of ' + key);
michael@0 24458 }
michael@0 24459 var data = output.data;
michael@0 24460 var dataOffset = this.offsets[key];
michael@0 24461 var size = 5;
michael@0 24462 for (var i = 0, ii = values.length; i < ii; ++i) {
michael@0 24463 var offset0 = i * size + dataOffset;
michael@0 24464 var offset1 = offset0 + 1;
michael@0 24465 var offset2 = offset0 + 2;
michael@0 24466 var offset3 = offset0 + 3;
michael@0 24467 var offset4 = offset0 + 4;
michael@0 24468 // It's easy to screw up offsets so perform this sanity check.
michael@0 24469 if (data[offset0] !== 0x1d || data[offset1] !== 0 ||
michael@0 24470 data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) {
michael@0 24471 error('writing to an offset that is not empty');
michael@0 24472 }
michael@0 24473 var value = values[i];
michael@0 24474 data[offset0] = 0x1d;
michael@0 24475 data[offset1] = (value >> 24) & 0xFF;
michael@0 24476 data[offset2] = (value >> 16) & 0xFF;
michael@0 24477 data[offset3] = (value >> 8) & 0xFF;
michael@0 24478 data[offset4] = value & 0xFF;
michael@0 24479 }
michael@0 24480 }
michael@0 24481 };
michael@0 24482 return CFFOffsetTracker;
michael@0 24483 })();
michael@0 24484
michael@0 24485 // Takes a CFF and converts it to the binary representation.
michael@0 24486 var CFFCompiler = (function CFFCompilerClosure() {
michael@0 24487 function CFFCompiler(cff) {
michael@0 24488 this.cff = cff;
michael@0 24489 }
michael@0 24490 CFFCompiler.prototype = {
michael@0 24491 compile: function CFFCompiler_compile() {
michael@0 24492 var cff = this.cff;
michael@0 24493 var output = {
michael@0 24494 data: [],
michael@0 24495 length: 0,
michael@0 24496 add: function CFFCompiler_add(data) {
michael@0 24497 this.data = this.data.concat(data);
michael@0 24498 this.length = this.data.length;
michael@0 24499 }
michael@0 24500 };
michael@0 24501
michael@0 24502 // Compile the five entries that must be in order.
michael@0 24503 var header = this.compileHeader(cff.header);
michael@0 24504 output.add(header);
michael@0 24505
michael@0 24506 var nameIndex = this.compileNameIndex(cff.names);
michael@0 24507 output.add(nameIndex);
michael@0 24508
michael@0 24509 if (cff.isCIDFont) {
michael@0 24510 // The spec is unclear on how font matrices should relate to each other
michael@0 24511 // when there is one in the main top dict and the sub top dicts.
michael@0 24512 // Windows handles this differently than linux and osx so we have to
michael@0 24513 // normalize to work on all.
michael@0 24514 // Rules based off of some mailing list discussions:
michael@0 24515 // - If main font has a matrix and subfont doesn't, use the main matrix.
michael@0 24516 // - If no main font matrix and there is a subfont matrix, use the
michael@0 24517 // subfont matrix.
michael@0 24518 // - If both have matrices, concat together.
michael@0 24519 // - If neither have matrices, use default.
michael@0 24520 // To make this work on all platforms we move the top matrix into each
michael@0 24521 // sub top dict and concat if necessary.
michael@0 24522 if (cff.topDict.hasName('FontMatrix')) {
michael@0 24523 var base = cff.topDict.getByName('FontMatrix');
michael@0 24524 cff.topDict.removeByName('FontMatrix');
michael@0 24525 for (var i = 0, ii = cff.fdArray.length; i < ii; i++) {
michael@0 24526 var subDict = cff.fdArray[i];
michael@0 24527 var matrix = base.slice(0);
michael@0 24528 if (subDict.hasName('FontMatrix')) {
michael@0 24529 matrix = Util.transform(matrix, subDict.getByName('FontMatrix'));
michael@0 24530 }
michael@0 24531 subDict.setByName('FontMatrix', matrix);
michael@0 24532 }
michael@0 24533 }
michael@0 24534 }
michael@0 24535
michael@0 24536 var compiled = this.compileTopDicts([cff.topDict],
michael@0 24537 output.length,
michael@0 24538 cff.isCIDFont);
michael@0 24539 output.add(compiled.output);
michael@0 24540 var topDictTracker = compiled.trackers[0];
michael@0 24541
michael@0 24542 var stringIndex = this.compileStringIndex(cff.strings.strings);
michael@0 24543 output.add(stringIndex);
michael@0 24544
michael@0 24545 var globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
michael@0 24546 output.add(globalSubrIndex);
michael@0 24547
michael@0 24548 // Now start on the other entries that have no specfic order.
michael@0 24549 if (cff.encoding && cff.topDict.hasName('Encoding')) {
michael@0 24550 if (cff.encoding.predefined) {
michael@0 24551 topDictTracker.setEntryLocation('Encoding', [cff.encoding.format],
michael@0 24552 output);
michael@0 24553 } else {
michael@0 24554 var encoding = this.compileEncoding(cff.encoding);
michael@0 24555 topDictTracker.setEntryLocation('Encoding', [output.length], output);
michael@0 24556 output.add(encoding);
michael@0 24557 }
michael@0 24558 }
michael@0 24559
michael@0 24560 if (cff.charset && cff.topDict.hasName('charset')) {
michael@0 24561 if (cff.charset.predefined) {
michael@0 24562 topDictTracker.setEntryLocation('charset', [cff.charset.format],
michael@0 24563 output);
michael@0 24564 } else {
michael@0 24565 var charset = this.compileCharset(cff.charset);
michael@0 24566 topDictTracker.setEntryLocation('charset', [output.length], output);
michael@0 24567 output.add(charset);
michael@0 24568 }
michael@0 24569 }
michael@0 24570
michael@0 24571 var charStrings = this.compileCharStrings(cff.charStrings);
michael@0 24572 topDictTracker.setEntryLocation('CharStrings', [output.length], output);
michael@0 24573 output.add(charStrings);
michael@0 24574
michael@0 24575 if (cff.isCIDFont) {
michael@0 24576 // For some reason FDSelect must be in front of FDArray on windows. OSX
michael@0 24577 // and linux don't seem to care.
michael@0 24578 topDictTracker.setEntryLocation('FDSelect', [output.length], output);
michael@0 24579 var fdSelect = this.compileFDSelect(cff.fdSelect.raw);
michael@0 24580 output.add(fdSelect);
michael@0 24581 // It is unclear if the sub font dictionary can have CID related
michael@0 24582 // dictionary keys, but the sanitizer doesn't like them so remove them.
michael@0 24583 compiled = this.compileTopDicts(cff.fdArray, output.length, true);
michael@0 24584 topDictTracker.setEntryLocation('FDArray', [output.length], output);
michael@0 24585 output.add(compiled.output);
michael@0 24586 var fontDictTrackers = compiled.trackers;
michael@0 24587
michael@0 24588 this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
michael@0 24589 }
michael@0 24590
michael@0 24591 this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
michael@0 24592
michael@0 24593 // If the font data ends with INDEX whose object data is zero-length,
michael@0 24594 // the sanitizer will bail out. Add a dummy byte to avoid that.
michael@0 24595 output.add([0]);
michael@0 24596
michael@0 24597 return output.data;
michael@0 24598 },
michael@0 24599 encodeNumber: function CFFCompiler_encodeNumber(value) {
michael@0 24600 if (parseFloat(value) == parseInt(value, 10) && !isNaN(value)) { // isInt
michael@0 24601 return this.encodeInteger(value);
michael@0 24602 } else {
michael@0 24603 return this.encodeFloat(value);
michael@0 24604 }
michael@0 24605 },
michael@0 24606 encodeFloat: function CFFCompiler_encodeFloat(num) {
michael@0 24607 var value = num.toString();
michael@0 24608
michael@0 24609 // rounding inaccurate doubles
michael@0 24610 var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
michael@0 24611 if (m) {
michael@0 24612 var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
michael@0 24613 value = (Math.round(num * epsilon) / epsilon).toString();
michael@0 24614 }
michael@0 24615
michael@0 24616 var nibbles = '';
michael@0 24617 var i, ii;
michael@0 24618 for (i = 0, ii = value.length; i < ii; ++i) {
michael@0 24619 var a = value[i];
michael@0 24620 if (a === 'e') {
michael@0 24621 nibbles += value[++i] === '-' ? 'c' : 'b';
michael@0 24622 } else if (a === '.') {
michael@0 24623 nibbles += 'a';
michael@0 24624 } else if (a === '-') {
michael@0 24625 nibbles += 'e';
michael@0 24626 } else {
michael@0 24627 nibbles += a;
michael@0 24628 }
michael@0 24629 }
michael@0 24630 nibbles += (nibbles.length & 1) ? 'f' : 'ff';
michael@0 24631 var out = [30];
michael@0 24632 for (i = 0, ii = nibbles.length; i < ii; i += 2) {
michael@0 24633 out.push(parseInt(nibbles.substr(i, 2), 16));
michael@0 24634 }
michael@0 24635 return out;
michael@0 24636 },
michael@0 24637 encodeInteger: function CFFCompiler_encodeInteger(value) {
michael@0 24638 var code;
michael@0 24639 if (value >= -107 && value <= 107) {
michael@0 24640 code = [value + 139];
michael@0 24641 } else if (value >= 108 && value <= 1131) {
michael@0 24642 value = [value - 108];
michael@0 24643 code = [(value >> 8) + 247, value & 0xFF];
michael@0 24644 } else if (value >= -1131 && value <= -108) {
michael@0 24645 value = -value - 108;
michael@0 24646 code = [(value >> 8) + 251, value & 0xFF];
michael@0 24647 } else if (value >= -32768 && value <= 32767) {
michael@0 24648 code = [0x1c, (value >> 8) & 0xFF, value & 0xFF];
michael@0 24649 } else {
michael@0 24650 code = [0x1d,
michael@0 24651 (value >> 24) & 0xFF,
michael@0 24652 (value >> 16) & 0xFF,
michael@0 24653 (value >> 8) & 0xFF,
michael@0 24654 value & 0xFF];
michael@0 24655 }
michael@0 24656 return code;
michael@0 24657 },
michael@0 24658 compileHeader: function CFFCompiler_compileHeader(header) {
michael@0 24659 return [
michael@0 24660 header.major,
michael@0 24661 header.minor,
michael@0 24662 header.hdrSize,
michael@0 24663 header.offSize
michael@0 24664 ];
michael@0 24665 },
michael@0 24666 compileNameIndex: function CFFCompiler_compileNameIndex(names) {
michael@0 24667 var nameIndex = new CFFIndex();
michael@0 24668 for (var i = 0, ii = names.length; i < ii; ++i) {
michael@0 24669 nameIndex.add(stringToArray(names[i]));
michael@0 24670 }
michael@0 24671 return this.compileIndex(nameIndex);
michael@0 24672 },
michael@0 24673 compileTopDicts: function CFFCompiler_compileTopDicts(dicts,
michael@0 24674 length,
michael@0 24675 removeCidKeys) {
michael@0 24676 var fontDictTrackers = [];
michael@0 24677 var fdArrayIndex = new CFFIndex();
michael@0 24678 for (var i = 0, ii = dicts.length; i < ii; ++i) {
michael@0 24679 var fontDict = dicts[i];
michael@0 24680 if (removeCidKeys) {
michael@0 24681 fontDict.removeByName('CIDFontVersion');
michael@0 24682 fontDict.removeByName('CIDFontRevision');
michael@0 24683 fontDict.removeByName('CIDFontType');
michael@0 24684 fontDict.removeByName('CIDCount');
michael@0 24685 fontDict.removeByName('UIDBase');
michael@0 24686 }
michael@0 24687 var fontDictTracker = new CFFOffsetTracker();
michael@0 24688 var fontDictData = this.compileDict(fontDict, fontDictTracker);
michael@0 24689 fontDictTrackers.push(fontDictTracker);
michael@0 24690 fdArrayIndex.add(fontDictData);
michael@0 24691 fontDictTracker.offset(length);
michael@0 24692 }
michael@0 24693 fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
michael@0 24694 return {
michael@0 24695 trackers: fontDictTrackers,
michael@0 24696 output: fdArrayIndex
michael@0 24697 };
michael@0 24698 },
michael@0 24699 compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts,
michael@0 24700 trackers,
michael@0 24701 output) {
michael@0 24702 for (var i = 0, ii = dicts.length; i < ii; ++i) {
michael@0 24703 var fontDict = dicts[i];
michael@0 24704 assert(fontDict.privateDict && fontDict.hasName('Private'),
michael@0 24705 'There must be an private dictionary.');
michael@0 24706 var privateDict = fontDict.privateDict;
michael@0 24707 var privateDictTracker = new CFFOffsetTracker();
michael@0 24708 var privateDictData = this.compileDict(privateDict, privateDictTracker);
michael@0 24709
michael@0 24710 var outputLength = output.length;
michael@0 24711 privateDictTracker.offset(outputLength);
michael@0 24712 if (!privateDictData.length) {
michael@0 24713 // The private dictionary was empty, set the output length to zero to
michael@0 24714 // ensure the offset length isn't out of bounds in the eyes of the
michael@0 24715 // sanitizer.
michael@0 24716 outputLength = 0;
michael@0 24717 }
michael@0 24718
michael@0 24719 trackers[i].setEntryLocation('Private',
michael@0 24720 [privateDictData.length, outputLength],
michael@0 24721 output);
michael@0 24722 output.add(privateDictData);
michael@0 24723
michael@0 24724 if (privateDict.subrsIndex && privateDict.hasName('Subrs')) {
michael@0 24725 var subrs = this.compileIndex(privateDict.subrsIndex);
michael@0 24726 privateDictTracker.setEntryLocation('Subrs', [privateDictData.length],
michael@0 24727 output);
michael@0 24728 output.add(subrs);
michael@0 24729 }
michael@0 24730 }
michael@0 24731 },
michael@0 24732 compileDict: function CFFCompiler_compileDict(dict, offsetTracker) {
michael@0 24733 var out = [];
michael@0 24734 // The dictionary keys must be in a certain order.
michael@0 24735 var order = dict.order;
michael@0 24736 for (var i = 0; i < order.length; ++i) {
michael@0 24737 var key = order[i];
michael@0 24738 if (!(key in dict.values)) {
michael@0 24739 continue;
michael@0 24740 }
michael@0 24741 var values = dict.values[key];
michael@0 24742 var types = dict.types[key];
michael@0 24743 if (!isArray(types)) {
michael@0 24744 types = [types];
michael@0 24745 }
michael@0 24746 if (!isArray(values)) {
michael@0 24747 values = [values];
michael@0 24748 }
michael@0 24749
michael@0 24750 // Remove any empty dict values.
michael@0 24751 if (values.length === 0) {
michael@0 24752 continue;
michael@0 24753 }
michael@0 24754
michael@0 24755 for (var j = 0, jj = types.length; j < jj; ++j) {
michael@0 24756 var type = types[j];
michael@0 24757 var value = values[j];
michael@0 24758 switch (type) {
michael@0 24759 case 'num':
michael@0 24760 case 'sid':
michael@0 24761 out = out.concat(this.encodeNumber(value));
michael@0 24762 break;
michael@0 24763 case 'offset':
michael@0 24764 // For offsets we just insert a 32bit integer so we don't have to
michael@0 24765 // deal with figuring out the length of the offset when it gets
michael@0 24766 // replaced later on by the compiler.
michael@0 24767 var name = dict.keyToNameMap[key];
michael@0 24768 // Some offsets have the offset and the length, so just record the
michael@0 24769 // position of the first one.
michael@0 24770 if (!offsetTracker.isTracking(name)) {
michael@0 24771 offsetTracker.track(name, out.length);
michael@0 24772 }
michael@0 24773 out = out.concat([0x1d, 0, 0, 0, 0]);
michael@0 24774 break;
michael@0 24775 case 'array':
michael@0 24776 case 'delta':
michael@0 24777 out = out.concat(this.encodeNumber(value));
michael@0 24778 for (var k = 1, kk = values.length; k < kk; ++k) {
michael@0 24779 out = out.concat(this.encodeNumber(values[k]));
michael@0 24780 }
michael@0 24781 break;
michael@0 24782 default:
michael@0 24783 error('Unknown data type of ' + type);
michael@0 24784 break;
michael@0 24785 }
michael@0 24786 }
michael@0 24787 out = out.concat(dict.opcodes[key]);
michael@0 24788 }
michael@0 24789 return out;
michael@0 24790 },
michael@0 24791 compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
michael@0 24792 var stringIndex = new CFFIndex();
michael@0 24793 for (var i = 0, ii = strings.length; i < ii; ++i) {
michael@0 24794 stringIndex.add(stringToArray(strings[i]));
michael@0 24795 }
michael@0 24796 return this.compileIndex(stringIndex);
michael@0 24797 },
michael@0 24798 compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
michael@0 24799 var globalSubrIndex = this.cff.globalSubrIndex;
michael@0 24800 this.out.writeByteArray(this.compileIndex(globalSubrIndex));
michael@0 24801 },
michael@0 24802 compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) {
michael@0 24803 return this.compileIndex(charStrings);
michael@0 24804 },
michael@0 24805 compileCharset: function CFFCompiler_compileCharset(charset) {
michael@0 24806 return this.compileTypedArray(charset.raw);
michael@0 24807 },
michael@0 24808 compileEncoding: function CFFCompiler_compileEncoding(encoding) {
michael@0 24809 return this.compileTypedArray(encoding.raw);
michael@0 24810 },
michael@0 24811 compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) {
michael@0 24812 return this.compileTypedArray(fdSelect);
michael@0 24813 },
michael@0 24814 compileTypedArray: function CFFCompiler_compileTypedArray(data) {
michael@0 24815 var out = [];
michael@0 24816 for (var i = 0, ii = data.length; i < ii; ++i) {
michael@0 24817 out[i] = data[i];
michael@0 24818 }
michael@0 24819 return out;
michael@0 24820 },
michael@0 24821 compileIndex: function CFFCompiler_compileIndex(index, trackers) {
michael@0 24822 trackers = trackers || [];
michael@0 24823 var objects = index.objects;
michael@0 24824 // First 2 bytes contains the number of objects contained into this index
michael@0 24825 var count = objects.length;
michael@0 24826
michael@0 24827 // If there is no object, just create an index. This technically
michael@0 24828 // should just be [0, 0] but OTS has an issue with that.
michael@0 24829 if (count === 0) {
michael@0 24830 return [0, 0, 0];
michael@0 24831 }
michael@0 24832
michael@0 24833 var data = [(count >> 8) & 0xFF, count & 0xff];
michael@0 24834
michael@0 24835 var lastOffset = 1, i;
michael@0 24836 for (i = 0; i < count; ++i) {
michael@0 24837 lastOffset += objects[i].length;
michael@0 24838 }
michael@0 24839
michael@0 24840 var offsetSize;
michael@0 24841 if (lastOffset < 0x100) {
michael@0 24842 offsetSize = 1;
michael@0 24843 } else if (lastOffset < 0x10000) {
michael@0 24844 offsetSize = 2;
michael@0 24845 } else if (lastOffset < 0x1000000) {
michael@0 24846 offsetSize = 3;
michael@0 24847 } else {
michael@0 24848 offsetSize = 4;
michael@0 24849 }
michael@0 24850
michael@0 24851 // Next byte contains the offset size use to reference object in the file
michael@0 24852 data.push(offsetSize);
michael@0 24853
michael@0 24854 // Add another offset after this one because we need a new offset
michael@0 24855 var relativeOffset = 1;
michael@0 24856 for (i = 0; i < count + 1; i++) {
michael@0 24857 if (offsetSize === 1) {
michael@0 24858 data.push(relativeOffset & 0xFF);
michael@0 24859 } else if (offsetSize === 2) {
michael@0 24860 data.push((relativeOffset >> 8) & 0xFF,
michael@0 24861 relativeOffset & 0xFF);
michael@0 24862 } else if (offsetSize === 3) {
michael@0 24863 data.push((relativeOffset >> 16) & 0xFF,
michael@0 24864 (relativeOffset >> 8) & 0xFF,
michael@0 24865 relativeOffset & 0xFF);
michael@0 24866 } else {
michael@0 24867 data.push((relativeOffset >>> 24) & 0xFF,
michael@0 24868 (relativeOffset >> 16) & 0xFF,
michael@0 24869 (relativeOffset >> 8) & 0xFF,
michael@0 24870 relativeOffset & 0xFF);
michael@0 24871 }
michael@0 24872
michael@0 24873 if (objects[i]) {
michael@0 24874 relativeOffset += objects[i].length;
michael@0 24875 }
michael@0 24876 }
michael@0 24877
michael@0 24878 for (i = 0; i < count; i++) {
michael@0 24879 // Notify the tracker where the object will be offset in the data.
michael@0 24880 if (trackers[i]) {
michael@0 24881 trackers[i].offset(data.length);
michael@0 24882 }
michael@0 24883 for (var j = 0, jj = objects[i].length; j < jj; j++) {
michael@0 24884 data.push(objects[i][j]);
michael@0 24885 }
michael@0 24886 }
michael@0 24887 return data;
michael@0 24888 }
michael@0 24889 };
michael@0 24890 return CFFCompiler;
michael@0 24891 })();
michael@0 24892
michael@0 24893 // Workaround for seac on Windows.
michael@0 24894 (function checkSeacSupport() {
michael@0 24895 if (/Windows/.test(navigator.userAgent)) {
michael@0 24896 SEAC_ANALYSIS_ENABLED = true;
michael@0 24897 }
michael@0 24898 })();
michael@0 24899
michael@0 24900 // Workaround for Private Use Area characters in Chrome on Windows
michael@0 24901 // http://code.google.com/p/chromium/issues/detail?id=122465
michael@0 24902 // https://github.com/mozilla/pdf.js/issues/1689
michael@0 24903 (function checkChromeWindows() {
michael@0 24904 if (/Windows.*Chrome/.test(navigator.userAgent)) {
michael@0 24905 SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = true;
michael@0 24906 }
michael@0 24907 })();
michael@0 24908
michael@0 24909
michael@0 24910 var FontRendererFactory = (function FontRendererFactoryClosure() {
michael@0 24911 function getLong(data, offset) {
michael@0 24912 return (data[offset] << 24) | (data[offset + 1] << 16) |
michael@0 24913 (data[offset + 2] << 8) | data[offset + 3];
michael@0 24914 }
michael@0 24915
michael@0 24916 function getUshort(data, offset) {
michael@0 24917 return (data[offset] << 8) | data[offset + 1];
michael@0 24918 }
michael@0 24919
michael@0 24920 function parseCmap(data, start, end) {
michael@0 24921 var offset = (getUshort(data, start + 2) === 1 ?
michael@0 24922 getLong(data, start + 8) : getLong(data, start + 16));
michael@0 24923 var format = getUshort(data, start + offset);
michael@0 24924 var length, ranges, p, i;
michael@0 24925 if (format === 4) {
michael@0 24926 length = getUshort(data, start + offset + 2);
michael@0 24927 var segCount = getUshort(data, start + offset + 6) >> 1;
michael@0 24928 p = start + offset + 14;
michael@0 24929 ranges = [];
michael@0 24930 for (i = 0; i < segCount; i++, p += 2) {
michael@0 24931 ranges[i] = {end: getUshort(data, p)};
michael@0 24932 }
michael@0 24933 p += 2;
michael@0 24934 for (i = 0; i < segCount; i++, p += 2) {
michael@0 24935 ranges[i].start = getUshort(data, p);
michael@0 24936 }
michael@0 24937 for (i = 0; i < segCount; i++, p += 2) {
michael@0 24938 ranges[i].idDelta = getUshort(data, p);
michael@0 24939 }
michael@0 24940 for (i = 0; i < segCount; i++, p += 2) {
michael@0 24941 var idOffset = getUshort(data, p);
michael@0 24942 if (idOffset === 0) {
michael@0 24943 continue;
michael@0 24944 }
michael@0 24945 ranges[i].ids = [];
michael@0 24946 for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
michael@0 24947 ranges[i].ids[j] = getUshort(data, p + idOffset);
michael@0 24948 idOffset += 2;
michael@0 24949 }
michael@0 24950 }
michael@0 24951 return ranges;
michael@0 24952 } else if (format === 12) {
michael@0 24953 length = getLong(data, start + offset + 4);
michael@0 24954 var groups = getLong(data, start + offset + 12);
michael@0 24955 p = start + offset + 16;
michael@0 24956 ranges = [];
michael@0 24957 for (i = 0; i < groups; i++) {
michael@0 24958 ranges.push({
michael@0 24959 start: getLong(data, p),
michael@0 24960 end: getLong(data, p + 4),
michael@0 24961 idDelta: getLong(data, p + 8) - getLong(data, p)
michael@0 24962 });
michael@0 24963 p += 12;
michael@0 24964 }
michael@0 24965 return ranges;
michael@0 24966 }
michael@0 24967 error('not supported cmap: ' + format);
michael@0 24968 }
michael@0 24969
michael@0 24970 function parseCff(data, start, end) {
michael@0 24971 var properties = {};
michael@0 24972 var parser = new CFFParser(new Stream(data, start, end - start),
michael@0 24973 properties);
michael@0 24974 var cff = parser.parse();
michael@0 24975 return {
michael@0 24976 glyphs: cff.charStrings.objects,
michael@0 24977 subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex &&
michael@0 24978 cff.topDict.privateDict.subrsIndex.objects),
michael@0 24979 gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects
michael@0 24980 };
michael@0 24981 }
michael@0 24982
michael@0 24983 function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
michael@0 24984 var itemSize, itemDecode;
michael@0 24985 if (isGlyphLocationsLong) {
michael@0 24986 itemSize = 4;
michael@0 24987 itemDecode = function fontItemDecodeLong(data, offset) {
michael@0 24988 return (data[offset] << 24) | (data[offset + 1] << 16) |
michael@0 24989 (data[offset + 2] << 8) | data[offset + 3];
michael@0 24990 };
michael@0 24991 } else {
michael@0 24992 itemSize = 2;
michael@0 24993 itemDecode = function fontItemDecode(data, offset) {
michael@0 24994 return (data[offset] << 9) | (data[offset + 1] << 1);
michael@0 24995 };
michael@0 24996 }
michael@0 24997 var glyphs = [];
michael@0 24998 var startOffset = itemDecode(loca, 0);
michael@0 24999 for (var j = itemSize; j < loca.length; j += itemSize) {
michael@0 25000 var endOffset = itemDecode(loca, j);
michael@0 25001 glyphs.push(glyf.subarray(startOffset, endOffset));
michael@0 25002 startOffset = endOffset;
michael@0 25003 }
michael@0 25004 return glyphs;
michael@0 25005 }
michael@0 25006
michael@0 25007 function lookupCmap(ranges, unicode) {
michael@0 25008 var code = unicode.charCodeAt(0);
michael@0 25009 var l = 0, r = ranges.length - 1;
michael@0 25010 while (l < r) {
michael@0 25011 var c = (l + r + 1) >> 1;
michael@0 25012 if (code < ranges[c].start) {
michael@0 25013 r = c - 1;
michael@0 25014 } else {
michael@0 25015 l = c;
michael@0 25016 }
michael@0 25017 }
michael@0 25018 if (ranges[l].start <= code && code <= ranges[l].end) {
michael@0 25019 return (ranges[l].idDelta + (ranges[l].ids ?
michael@0 25020 ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF;
michael@0 25021 }
michael@0 25022 return 0;
michael@0 25023 }
michael@0 25024
michael@0 25025 function compileGlyf(code, js, font) {
michael@0 25026 function moveTo(x, y) {
michael@0 25027 js.push('c.moveTo(' + x + ',' + y + ');');
michael@0 25028 }
michael@0 25029 function lineTo(x, y) {
michael@0 25030 js.push('c.lineTo(' + x + ',' + y + ');');
michael@0 25031 }
michael@0 25032 function quadraticCurveTo(xa, ya, x, y) {
michael@0 25033 js.push('c.quadraticCurveTo(' + xa + ',' + ya + ',' +
michael@0 25034 x + ',' + y + ');');
michael@0 25035 }
michael@0 25036
michael@0 25037 var i = 0;
michael@0 25038 var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
michael@0 25039 var flags;
michael@0 25040 var x = 0, y = 0;
michael@0 25041 i += 10;
michael@0 25042 if (numberOfContours < 0) {
michael@0 25043 // composite glyph
michael@0 25044 do {
michael@0 25045 flags = (code[i] << 8) | code[i + 1];
michael@0 25046 var glyphIndex = (code[i + 2] << 8) | code[i + 3];
michael@0 25047 i += 4;
michael@0 25048 var arg1, arg2;
michael@0 25049 if ((flags & 0x01)) {
michael@0 25050 arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
michael@0 25051 arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16;
michael@0 25052 i += 4;
michael@0 25053 } else {
michael@0 25054 arg1 = code[i++]; arg2 = code[i++];
michael@0 25055 }
michael@0 25056 if ((flags & 0x02)) {
michael@0 25057 x = arg1;
michael@0 25058 y = arg2;
michael@0 25059 } else {
michael@0 25060 x = 0; y = 0; // TODO "they are points" ?
michael@0 25061 }
michael@0 25062 var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0;
michael@0 25063 if ((flags & 0x08)) {
michael@0 25064 scaleX =
michael@0 25065 scaleY = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
michael@0 25066 i += 2;
michael@0 25067 } else if ((flags & 0x40)) {
michael@0 25068 scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
michael@0 25069 scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
michael@0 25070 i += 4;
michael@0 25071 } else if ((flags & 0x80)) {
michael@0 25072 scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
michael@0 25073 scale01 = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
michael@0 25074 scale10 = ((code[i + 4] << 24) | (code[i + 5] << 16)) / 1073741824;
michael@0 25075 scaleY = ((code[i + 6] << 24) | (code[i + 7] << 16)) / 1073741824;
michael@0 25076 i += 8;
michael@0 25077 }
michael@0 25078 var subglyph = font.glyphs[glyphIndex];
michael@0 25079 if (subglyph) {
michael@0 25080 js.push('c.save();');
michael@0 25081 js.push('c.transform(' + scaleX + ',' + scale01 + ',' +
michael@0 25082 scale10 + ',' + scaleY + ',' + x + ',' + y + ');');
michael@0 25083 compileGlyf(subglyph, js, font);
michael@0 25084 js.push('c.restore();');
michael@0 25085 }
michael@0 25086 } while ((flags & 0x20));
michael@0 25087 } else {
michael@0 25088 // simple glyph
michael@0 25089 var endPtsOfContours = [];
michael@0 25090 var j, jj;
michael@0 25091 for (j = 0; j < numberOfContours; j++) {
michael@0 25092 endPtsOfContours.push((code[i] << 8) | code[i + 1]);
michael@0 25093 i += 2;
michael@0 25094 }
michael@0 25095 var instructionLength = (code[i] << 8) | code[i + 1];
michael@0 25096 i += 2 + instructionLength; // skipping the instructions
michael@0 25097 var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1;
michael@0 25098 var points = [];
michael@0 25099 while (points.length < numberOfPoints) {
michael@0 25100 flags = code[i++];
michael@0 25101 var repeat = 1;
michael@0 25102 if ((flags & 0x08)) {
michael@0 25103 repeat += code[i++];
michael@0 25104 }
michael@0 25105 while (repeat-- > 0) {
michael@0 25106 points.push({flags: flags});
michael@0 25107 }
michael@0 25108 }
michael@0 25109 for (j = 0; j < numberOfPoints; j++) {
michael@0 25110 switch (points[j].flags & 0x12) {
michael@0 25111 case 0x00:
michael@0 25112 x += ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
michael@0 25113 i += 2;
michael@0 25114 break;
michael@0 25115 case 0x02:
michael@0 25116 x -= code[i++];
michael@0 25117 break;
michael@0 25118 case 0x12:
michael@0 25119 x += code[i++];
michael@0 25120 break;
michael@0 25121 }
michael@0 25122 points[j].x = x;
michael@0 25123 }
michael@0 25124 for (j = 0; j < numberOfPoints; j++) {
michael@0 25125 switch (points[j].flags & 0x24) {
michael@0 25126 case 0x00:
michael@0 25127 y += ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
michael@0 25128 i += 2;
michael@0 25129 break;
michael@0 25130 case 0x04:
michael@0 25131 y -= code[i++];
michael@0 25132 break;
michael@0 25133 case 0x24:
michael@0 25134 y += code[i++];
michael@0 25135 break;
michael@0 25136 }
michael@0 25137 points[j].y = y;
michael@0 25138 }
michael@0 25139
michael@0 25140 var startPoint = 0;
michael@0 25141 for (i = 0; i < numberOfContours; i++) {
michael@0 25142 var endPoint = endPtsOfContours[i];
michael@0 25143 // contours might have implicit points, which is located in the middle
michael@0 25144 // between two neighboring off-curve points
michael@0 25145 var contour = points.slice(startPoint, endPoint + 1);
michael@0 25146 if ((contour[0].flags & 1)) {
michael@0 25147 contour.push(contour[0]); // using start point at the contour end
michael@0 25148 } else if ((contour[contour.length - 1].flags & 1)) {
michael@0 25149 // first is off-curve point, trying to use one from the end
michael@0 25150 contour.unshift(contour[contour.length - 1]);
michael@0 25151 } else {
michael@0 25152 // start and end are off-curve points, creating implicit one
michael@0 25153 var p = {
michael@0 25154 flags: 1,
michael@0 25155 x: (contour[0].x + contour[contour.length - 1].x) / 2,
michael@0 25156 y: (contour[0].y + contour[contour.length - 1].y) / 2
michael@0 25157 };
michael@0 25158 contour.unshift(p);
michael@0 25159 contour.push(p);
michael@0 25160 }
michael@0 25161 moveTo(contour[0].x, contour[0].y);
michael@0 25162 for (j = 1, jj = contour.length; j < jj; j++) {
michael@0 25163 if ((contour[j].flags & 1)) {
michael@0 25164 lineTo(contour[j].x, contour[j].y);
michael@0 25165 } else if ((contour[j + 1].flags & 1)){
michael@0 25166 quadraticCurveTo(contour[j].x, contour[j].y,
michael@0 25167 contour[j + 1].x, contour[j + 1].y);
michael@0 25168 j++;
michael@0 25169 } else {
michael@0 25170 quadraticCurveTo(contour[j].x, contour[j].y,
michael@0 25171 (contour[j].x + contour[j + 1].x) / 2,
michael@0 25172 (contour[j].y + contour[j + 1].y) / 2);
michael@0 25173 }
michael@0 25174 }
michael@0 25175 startPoint = endPoint + 1;
michael@0 25176 }
michael@0 25177 }
michael@0 25178 }
michael@0 25179
michael@0 25180 function compileCharString(code, js, font) {
michael@0 25181 var stack = [];
michael@0 25182 var x = 0, y = 0;
michael@0 25183 var stems = 0;
michael@0 25184
michael@0 25185 function moveTo(x, y) {
michael@0 25186 js.push('c.moveTo(' + x + ',' + y + ');');
michael@0 25187 }
michael@0 25188 function lineTo(x, y) {
michael@0 25189 js.push('c.lineTo(' + x + ',' + y + ');');
michael@0 25190 }
michael@0 25191 function bezierCurveTo(x1, y1, x2, y2, x, y) {
michael@0 25192 js.push('c.bezierCurveTo(' + x1 + ',' + y1 + ',' + x2 + ',' + y2 + ',' +
michael@0 25193 x + ',' + y + ');');
michael@0 25194 }
michael@0 25195
michael@0 25196 function parse(code) {
michael@0 25197 var i = 0;
michael@0 25198 while (i < code.length) {
michael@0 25199 var stackClean = false;
michael@0 25200 var v = code[i++];
michael@0 25201 var xa, xb, ya, yb, y1, y2, y3, n, subrCode;
michael@0 25202 switch (v) {
michael@0 25203 case 1: // hstem
michael@0 25204 stems += stack.length >> 1;
michael@0 25205 stackClean = true;
michael@0 25206 break;
michael@0 25207 case 3: // vstem
michael@0 25208 stems += stack.length >> 1;
michael@0 25209 stackClean = true;
michael@0 25210 break;
michael@0 25211 case 4: // vmoveto
michael@0 25212 y += stack.pop();
michael@0 25213 moveTo(x, y);
michael@0 25214 stackClean = true;
michael@0 25215 break;
michael@0 25216 case 5: // rlineto
michael@0 25217 while (stack.length > 0) {
michael@0 25218 x += stack.shift();
michael@0 25219 y += stack.shift();
michael@0 25220 lineTo(x, y);
michael@0 25221 }
michael@0 25222 break;
michael@0 25223 case 6: // hlineto
michael@0 25224 while (stack.length > 0) {
michael@0 25225 x += stack.shift();
michael@0 25226 lineTo(x, y);
michael@0 25227 if (stack.length === 0) {
michael@0 25228 break;
michael@0 25229 }
michael@0 25230 y += stack.shift();
michael@0 25231 lineTo(x, y);
michael@0 25232 }
michael@0 25233 break;
michael@0 25234 case 7: // vlineto
michael@0 25235 while (stack.length > 0) {
michael@0 25236 y += stack.shift();
michael@0 25237 lineTo(x, y);
michael@0 25238 if (stack.length === 0) {
michael@0 25239 break;
michael@0 25240 }
michael@0 25241 x += stack.shift();
michael@0 25242 lineTo(x, y);
michael@0 25243 }
michael@0 25244 break;
michael@0 25245 case 8: // rrcurveto
michael@0 25246 while (stack.length > 0) {
michael@0 25247 xa = x + stack.shift(); ya = y + stack.shift();
michael@0 25248 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25249 x = xb + stack.shift(); y = yb + stack.shift();
michael@0 25250 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25251 }
michael@0 25252 break;
michael@0 25253 case 10: // callsubr
michael@0 25254 n = stack.pop() + font.subrsBias;
michael@0 25255 subrCode = font.subrs[n];
michael@0 25256 if (subrCode) {
michael@0 25257 parse(subrCode);
michael@0 25258 }
michael@0 25259 break;
michael@0 25260 case 11: // return
michael@0 25261 return;
michael@0 25262 case 12:
michael@0 25263 v = code[i++];
michael@0 25264 switch (v) {
michael@0 25265 case 34: // flex
michael@0 25266 xa = x + stack.shift();
michael@0 25267 xb = xa + stack.shift(); y1 = y + stack.shift();
michael@0 25268 x = xb + stack.shift();
michael@0 25269 bezierCurveTo(xa, y, xb, y1, x, y1);
michael@0 25270 xa = x + stack.shift();
michael@0 25271 xb = xa + stack.shift();
michael@0 25272 x = xb + stack.shift();
michael@0 25273 bezierCurveTo(xa, y1, xb, y, x, y);
michael@0 25274 break;
michael@0 25275 case 35: // flex
michael@0 25276 xa = x + stack.shift(); ya = y + stack.shift();
michael@0 25277 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25278 x = xb + stack.shift(); y = yb + stack.shift();
michael@0 25279 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25280 xa = x + stack.shift(); ya = y + stack.shift();
michael@0 25281 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25282 x = xb + stack.shift(); y = yb + stack.shift();
michael@0 25283 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25284 stack.pop(); // fd
michael@0 25285 break;
michael@0 25286 case 36: // hflex1
michael@0 25287 xa = x + stack.shift(); y1 = y + stack.shift();
michael@0 25288 xb = xa + stack.shift(); y2 = y1 + stack.shift();
michael@0 25289 x = xb + stack.shift();
michael@0 25290 bezierCurveTo(xa, y1, xb, y2, x, y2);
michael@0 25291 xa = x + stack.shift();
michael@0 25292 xb = xa + stack.shift(); y3 = y2 + stack.shift();
michael@0 25293 x = xb + stack.shift();
michael@0 25294 bezierCurveTo(xa, y2, xb, y3, x, y);
michael@0 25295 break;
michael@0 25296 case 37: // flex1
michael@0 25297 var x0 = x, y0 = y;
michael@0 25298 xa = x + stack.shift(); ya = y + stack.shift();
michael@0 25299 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25300 x = xb + stack.shift(); y = yb + stack.shift();
michael@0 25301 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25302 xa = x + stack.shift(); ya = y + stack.shift();
michael@0 25303 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25304 x = xb; y = yb;
michael@0 25305 if (Math.abs(x - x0) > Math.abs(y - y0)) {
michael@0 25306 x += stack.shift();
michael@0 25307 } else {
michael@0 25308 y += stack.shift();
michael@0 25309 }
michael@0 25310 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25311 break;
michael@0 25312 default:
michael@0 25313 error('unknown operator: 12 ' + v);
michael@0 25314 }
michael@0 25315 break;
michael@0 25316 case 14: // endchar
michael@0 25317 if (stack.length >= 4) {
michael@0 25318 var achar = stack.pop();
michael@0 25319 var bchar = stack.pop();
michael@0 25320 y = stack.pop();
michael@0 25321 x = stack.pop();
michael@0 25322 js.push('c.save();');
michael@0 25323 js.push('c.translate('+ x + ',' + y + ');');
michael@0 25324 var gid = lookupCmap(font.cmap, String.fromCharCode(
michael@0 25325 font.glyphNameMap[Encodings.StandardEncoding[achar]]));
michael@0 25326 compileCharString(font.glyphs[gid], js, font);
michael@0 25327 js.push('c.restore();');
michael@0 25328
michael@0 25329 gid = lookupCmap(font.cmap, String.fromCharCode(
michael@0 25330 font.glyphNameMap[Encodings.StandardEncoding[bchar]]));
michael@0 25331 compileCharString(font.glyphs[gid], js, font);
michael@0 25332 }
michael@0 25333 return;
michael@0 25334 case 18: // hstemhm
michael@0 25335 stems += stack.length >> 1;
michael@0 25336 stackClean = true;
michael@0 25337 break;
michael@0 25338 case 19: // hintmask
michael@0 25339 stems += stack.length >> 1;
michael@0 25340 i += (stems + 7) >> 3;
michael@0 25341 stackClean = true;
michael@0 25342 break;
michael@0 25343 case 20: // cntrmask
michael@0 25344 stems += stack.length >> 1;
michael@0 25345 i += (stems + 7) >> 3;
michael@0 25346 stackClean = true;
michael@0 25347 break;
michael@0 25348 case 21: // rmoveto
michael@0 25349 y += stack.pop();
michael@0 25350 x += stack.pop();
michael@0 25351 moveTo(x, y);
michael@0 25352 stackClean = true;
michael@0 25353 break;
michael@0 25354 case 22: // hmoveto
michael@0 25355 x += stack.pop();
michael@0 25356 moveTo(x, y);
michael@0 25357 stackClean = true;
michael@0 25358 break;
michael@0 25359 case 23: // vstemhm
michael@0 25360 stems += stack.length >> 1;
michael@0 25361 stackClean = true;
michael@0 25362 break;
michael@0 25363 case 24: // rcurveline
michael@0 25364 while (stack.length > 2) {
michael@0 25365 xa = x + stack.shift(); ya = y + stack.shift();
michael@0 25366 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25367 x = xb + stack.shift(); y = yb + stack.shift();
michael@0 25368 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25369 }
michael@0 25370 x += stack.shift();
michael@0 25371 y += stack.shift();
michael@0 25372 lineTo(x, y);
michael@0 25373 break;
michael@0 25374 case 25: // rlinecurve
michael@0 25375 while (stack.length > 6) {
michael@0 25376 x += stack.shift();
michael@0 25377 y += stack.shift();
michael@0 25378 lineTo(x, y);
michael@0 25379 }
michael@0 25380 xa = x + stack.shift(); ya = y + stack.shift();
michael@0 25381 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25382 x = xb + stack.shift(); y = yb + stack.shift();
michael@0 25383 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25384 break;
michael@0 25385 case 26: // vvcurveto
michael@0 25386 if (stack.length % 2) {
michael@0 25387 x += stack.shift();
michael@0 25388 }
michael@0 25389 while (stack.length > 0) {
michael@0 25390 xa = x; ya = y + stack.shift();
michael@0 25391 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25392 x = xb; y = yb + stack.shift();
michael@0 25393 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25394 }
michael@0 25395 break;
michael@0 25396 case 27: // hhcurveto
michael@0 25397 if (stack.length % 2) {
michael@0 25398 y += stack.shift();
michael@0 25399 }
michael@0 25400 while (stack.length > 0) {
michael@0 25401 xa = x + stack.shift(); ya = y;
michael@0 25402 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25403 x = xb + stack.shift(); y = yb;
michael@0 25404 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25405 }
michael@0 25406 break;
michael@0 25407 case 28:
michael@0 25408 stack.push(((code[i] << 24) | (code[i + 1] << 16)) >> 16);
michael@0 25409 i += 2;
michael@0 25410 break;
michael@0 25411 case 29: // callgsubr
michael@0 25412 n = stack.pop() + font.gsubrsBias;
michael@0 25413 subrCode = font.gsubrs[n];
michael@0 25414 if (subrCode) {
michael@0 25415 parse(subrCode);
michael@0 25416 }
michael@0 25417 break;
michael@0 25418 case 30: // vhcurveto
michael@0 25419 while (stack.length > 0) {
michael@0 25420 xa = x; ya = y + stack.shift();
michael@0 25421 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25422 x = xb + stack.shift();
michael@0 25423 y = yb + (stack.length === 1 ? stack.shift() : 0);
michael@0 25424 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25425 if (stack.length === 0) {
michael@0 25426 break;
michael@0 25427 }
michael@0 25428
michael@0 25429 xa = x + stack.shift(); ya = y;
michael@0 25430 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25431 y = yb + stack.shift();
michael@0 25432 x = xb + (stack.length === 1 ? stack.shift() : 0);
michael@0 25433 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25434 }
michael@0 25435 break;
michael@0 25436 case 31: // hvcurveto
michael@0 25437 while (stack.length > 0) {
michael@0 25438 xa = x + stack.shift(); ya = y;
michael@0 25439 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25440 y = yb + stack.shift();
michael@0 25441 x = xb + (stack.length === 1 ? stack.shift() : 0);
michael@0 25442 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25443 if (stack.length === 0) {
michael@0 25444 break;
michael@0 25445 }
michael@0 25446
michael@0 25447 xa = x; ya = y + stack.shift();
michael@0 25448 xb = xa + stack.shift(); yb = ya + stack.shift();
michael@0 25449 x = xb + stack.shift();
michael@0 25450 y = yb + (stack.length === 1 ? stack.shift() : 0);
michael@0 25451 bezierCurveTo(xa, ya, xb, yb, x, y);
michael@0 25452 }
michael@0 25453 break;
michael@0 25454 default:
michael@0 25455 if (v < 32) {
michael@0 25456 error('unknown operator: ' + v);
michael@0 25457 }
michael@0 25458 if (v < 247) {
michael@0 25459 stack.push(v - 139);
michael@0 25460 } else if (v < 251) {
michael@0 25461 stack.push((v - 247) * 256 + code[i++] + 108);
michael@0 25462 } else if (v < 255) {
michael@0 25463 stack.push(-(v - 251) * 256 - code[i++] - 108);
michael@0 25464 } else {
michael@0 25465 stack.push(((code[i] << 24) | (code[i + 1] << 16) |
michael@0 25466 (code[i + 2] << 8) | code[i + 3]) / 65536);
michael@0 25467 i += 4;
michael@0 25468 }
michael@0 25469 break;
michael@0 25470 }
michael@0 25471 if (stackClean) {
michael@0 25472 stack.length = 0;
michael@0 25473 }
michael@0 25474 }
michael@0 25475 }
michael@0 25476 parse(code);
michael@0 25477 }
michael@0 25478
michael@0 25479 var noop = '';
michael@0 25480
michael@0 25481 function CompiledFont(fontMatrix) {
michael@0 25482 this.compiledGlyphs = {};
michael@0 25483 this.fontMatrix = fontMatrix;
michael@0 25484 }
michael@0 25485 CompiledFont.prototype = {
michael@0 25486 getPathJs: function (unicode) {
michael@0 25487 var gid = lookupCmap(this.cmap, unicode);
michael@0 25488 var fn = this.compiledGlyphs[gid];
michael@0 25489 if (!fn) {
michael@0 25490 this.compiledGlyphs[gid] = fn = this.compileGlyph(this.glyphs[gid]);
michael@0 25491 }
michael@0 25492 return fn;
michael@0 25493 },
michael@0 25494
michael@0 25495 compileGlyph: function (code) {
michael@0 25496 if (!code || code.length === 0 || code[0] === 14) {
michael@0 25497 return noop;
michael@0 25498 }
michael@0 25499
michael@0 25500 var js = [];
michael@0 25501 js.push('c.save();');
michael@0 25502 js.push('c.transform(' + this.fontMatrix.join(',') + ');');
michael@0 25503 js.push('c.scale(size, -size);');
michael@0 25504
michael@0 25505 this.compileGlyphImpl(code, js);
michael@0 25506
michael@0 25507 js.push('c.restore();');
michael@0 25508
michael@0 25509 return js.join('\n');
michael@0 25510 },
michael@0 25511
michael@0 25512 compileGlyphImpl: function () {
michael@0 25513 error('Children classes should implement this.');
michael@0 25514 },
michael@0 25515
michael@0 25516 hasBuiltPath: function (unicode) {
michael@0 25517 var gid = lookupCmap(this.cmap, unicode);
michael@0 25518 return gid in this.compiledGlyphs;
michael@0 25519 }
michael@0 25520 };
michael@0 25521
michael@0 25522 function TrueTypeCompiled(glyphs, cmap, fontMatrix) {
michael@0 25523 fontMatrix = fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0];
michael@0 25524 CompiledFont.call(this, fontMatrix);
michael@0 25525
michael@0 25526 this.glyphs = glyphs;
michael@0 25527 this.cmap = cmap;
michael@0 25528
michael@0 25529 this.compiledGlyphs = [];
michael@0 25530 }
michael@0 25531
michael@0 25532 Util.inherit(TrueTypeCompiled, CompiledFont, {
michael@0 25533 compileGlyphImpl: function (code, js) {
michael@0 25534 compileGlyf(code, js, this);
michael@0 25535 }
michael@0 25536 });
michael@0 25537
michael@0 25538 function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) {
michael@0 25539 fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0];
michael@0 25540 CompiledFont.call(this, fontMatrix);
michael@0 25541 this.glyphs = cffInfo.glyphs;
michael@0 25542 this.gsubrs = cffInfo.gsubrs || [];
michael@0 25543 this.subrs = cffInfo.subrs || [];
michael@0 25544 this.cmap = cmap;
michael@0 25545 this.glyphNameMap = glyphNameMap || GlyphsUnicode;
michael@0 25546
michael@0 25547 this.compiledGlyphs = [];
michael@0 25548 this.gsubrsBias = (this.gsubrs.length < 1240 ?
michael@0 25549 107 : (this.gsubrs.length < 33900 ? 1131 : 32768));
michael@0 25550 this.subrsBias = (this.subrs.length < 1240 ?
michael@0 25551 107 : (this.subrs.length < 33900 ? 1131 : 32768));
michael@0 25552 }
michael@0 25553
michael@0 25554 Util.inherit(Type2Compiled, CompiledFont, {
michael@0 25555 compileGlyphImpl: function (code, js) {
michael@0 25556 compileCharString(code, js, this);
michael@0 25557 }
michael@0 25558 });
michael@0 25559
michael@0 25560
michael@0 25561 return {
michael@0 25562 create: function FontRendererFactory_create(font) {
michael@0 25563 var data = new Uint8Array(font.data);
michael@0 25564 var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
michael@0 25565 var numTables = getUshort(data, 4);
michael@0 25566 for (var i = 0, p = 12; i < numTables; i++, p += 16) {
michael@0 25567 var tag = bytesToString(data.subarray(p, p + 4));
michael@0 25568 var offset = getLong(data, p + 8);
michael@0 25569 var length = getLong(data, p + 12);
michael@0 25570 switch (tag) {
michael@0 25571 case 'cmap':
michael@0 25572 cmap = parseCmap(data, offset, offset + length);
michael@0 25573 break;
michael@0 25574 case 'glyf':
michael@0 25575 glyf = data.subarray(offset, offset + length);
michael@0 25576 break;
michael@0 25577 case 'loca':
michael@0 25578 loca = data.subarray(offset, offset + length);
michael@0 25579 break;
michael@0 25580 case 'head':
michael@0 25581 unitsPerEm = getUshort(data, offset + 18);
michael@0 25582 indexToLocFormat = getUshort(data, offset + 50);
michael@0 25583 break;
michael@0 25584 case 'CFF ':
michael@0 25585 cff = parseCff(data, offset, offset + length);
michael@0 25586 break;
michael@0 25587 }
michael@0 25588 }
michael@0 25589
michael@0 25590 if (glyf) {
michael@0 25591 var fontMatrix = (!unitsPerEm ? font.fontMatrix :
michael@0 25592 [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]);
michael@0 25593 return new TrueTypeCompiled(
michael@0 25594 parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
michael@0 25595 } else {
michael@0 25596 return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
michael@0 25597 }
michael@0 25598 }
michael@0 25599 };
michael@0 25600 })();
michael@0 25601
michael@0 25602
michael@0 25603
michael@0 25604 var GlyphsUnicode = {
michael@0 25605 A: 0x0041,
michael@0 25606 AE: 0x00C6,
michael@0 25607 AEacute: 0x01FC,
michael@0 25608 AEmacron: 0x01E2,
michael@0 25609 AEsmall: 0xF7E6,
michael@0 25610 Aacute: 0x00C1,
michael@0 25611 Aacutesmall: 0xF7E1,
michael@0 25612 Abreve: 0x0102,
michael@0 25613 Abreveacute: 0x1EAE,
michael@0 25614 Abrevecyrillic: 0x04D0,
michael@0 25615 Abrevedotbelow: 0x1EB6,
michael@0 25616 Abrevegrave: 0x1EB0,
michael@0 25617 Abrevehookabove: 0x1EB2,
michael@0 25618 Abrevetilde: 0x1EB4,
michael@0 25619 Acaron: 0x01CD,
michael@0 25620 Acircle: 0x24B6,
michael@0 25621 Acircumflex: 0x00C2,
michael@0 25622 Acircumflexacute: 0x1EA4,
michael@0 25623 Acircumflexdotbelow: 0x1EAC,
michael@0 25624 Acircumflexgrave: 0x1EA6,
michael@0 25625 Acircumflexhookabove: 0x1EA8,
michael@0 25626 Acircumflexsmall: 0xF7E2,
michael@0 25627 Acircumflextilde: 0x1EAA,
michael@0 25628 Acute: 0xF6C9,
michael@0 25629 Acutesmall: 0xF7B4,
michael@0 25630 Acyrillic: 0x0410,
michael@0 25631 Adblgrave: 0x0200,
michael@0 25632 Adieresis: 0x00C4,
michael@0 25633 Adieresiscyrillic: 0x04D2,
michael@0 25634 Adieresismacron: 0x01DE,
michael@0 25635 Adieresissmall: 0xF7E4,
michael@0 25636 Adotbelow: 0x1EA0,
michael@0 25637 Adotmacron: 0x01E0,
michael@0 25638 Agrave: 0x00C0,
michael@0 25639 Agravesmall: 0xF7E0,
michael@0 25640 Ahookabove: 0x1EA2,
michael@0 25641 Aiecyrillic: 0x04D4,
michael@0 25642 Ainvertedbreve: 0x0202,
michael@0 25643 Alpha: 0x0391,
michael@0 25644 Alphatonos: 0x0386,
michael@0 25645 Amacron: 0x0100,
michael@0 25646 Amonospace: 0xFF21,
michael@0 25647 Aogonek: 0x0104,
michael@0 25648 Aring: 0x00C5,
michael@0 25649 Aringacute: 0x01FA,
michael@0 25650 Aringbelow: 0x1E00,
michael@0 25651 Aringsmall: 0xF7E5,
michael@0 25652 Asmall: 0xF761,
michael@0 25653 Atilde: 0x00C3,
michael@0 25654 Atildesmall: 0xF7E3,
michael@0 25655 Aybarmenian: 0x0531,
michael@0 25656 B: 0x0042,
michael@0 25657 Bcircle: 0x24B7,
michael@0 25658 Bdotaccent: 0x1E02,
michael@0 25659 Bdotbelow: 0x1E04,
michael@0 25660 Becyrillic: 0x0411,
michael@0 25661 Benarmenian: 0x0532,
michael@0 25662 Beta: 0x0392,
michael@0 25663 Bhook: 0x0181,
michael@0 25664 Blinebelow: 0x1E06,
michael@0 25665 Bmonospace: 0xFF22,
michael@0 25666 Brevesmall: 0xF6F4,
michael@0 25667 Bsmall: 0xF762,
michael@0 25668 Btopbar: 0x0182,
michael@0 25669 C: 0x0043,
michael@0 25670 Caarmenian: 0x053E,
michael@0 25671 Cacute: 0x0106,
michael@0 25672 Caron: 0xF6CA,
michael@0 25673 Caronsmall: 0xF6F5,
michael@0 25674 Ccaron: 0x010C,
michael@0 25675 Ccedilla: 0x00C7,
michael@0 25676 Ccedillaacute: 0x1E08,
michael@0 25677 Ccedillasmall: 0xF7E7,
michael@0 25678 Ccircle: 0x24B8,
michael@0 25679 Ccircumflex: 0x0108,
michael@0 25680 Cdot: 0x010A,
michael@0 25681 Cdotaccent: 0x010A,
michael@0 25682 Cedillasmall: 0xF7B8,
michael@0 25683 Chaarmenian: 0x0549,
michael@0 25684 Cheabkhasiancyrillic: 0x04BC,
michael@0 25685 Checyrillic: 0x0427,
michael@0 25686 Chedescenderabkhasiancyrillic: 0x04BE,
michael@0 25687 Chedescendercyrillic: 0x04B6,
michael@0 25688 Chedieresiscyrillic: 0x04F4,
michael@0 25689 Cheharmenian: 0x0543,
michael@0 25690 Chekhakassiancyrillic: 0x04CB,
michael@0 25691 Cheverticalstrokecyrillic: 0x04B8,
michael@0 25692 Chi: 0x03A7,
michael@0 25693 Chook: 0x0187,
michael@0 25694 Circumflexsmall: 0xF6F6,
michael@0 25695 Cmonospace: 0xFF23,
michael@0 25696 Coarmenian: 0x0551,
michael@0 25697 Csmall: 0xF763,
michael@0 25698 D: 0x0044,
michael@0 25699 DZ: 0x01F1,
michael@0 25700 DZcaron: 0x01C4,
michael@0 25701 Daarmenian: 0x0534,
michael@0 25702 Dafrican: 0x0189,
michael@0 25703 Dcaron: 0x010E,
michael@0 25704 Dcedilla: 0x1E10,
michael@0 25705 Dcircle: 0x24B9,
michael@0 25706 Dcircumflexbelow: 0x1E12,
michael@0 25707 Dcroat: 0x0110,
michael@0 25708 Ddotaccent: 0x1E0A,
michael@0 25709 Ddotbelow: 0x1E0C,
michael@0 25710 Decyrillic: 0x0414,
michael@0 25711 Deicoptic: 0x03EE,
michael@0 25712 Delta: 0x2206,
michael@0 25713 Deltagreek: 0x0394,
michael@0 25714 Dhook: 0x018A,
michael@0 25715 Dieresis: 0xF6CB,
michael@0 25716 DieresisAcute: 0xF6CC,
michael@0 25717 DieresisGrave: 0xF6CD,
michael@0 25718 Dieresissmall: 0xF7A8,
michael@0 25719 Digammagreek: 0x03DC,
michael@0 25720 Djecyrillic: 0x0402,
michael@0 25721 Dlinebelow: 0x1E0E,
michael@0 25722 Dmonospace: 0xFF24,
michael@0 25723 Dotaccentsmall: 0xF6F7,
michael@0 25724 Dslash: 0x0110,
michael@0 25725 Dsmall: 0xF764,
michael@0 25726 Dtopbar: 0x018B,
michael@0 25727 Dz: 0x01F2,
michael@0 25728 Dzcaron: 0x01C5,
michael@0 25729 Dzeabkhasiancyrillic: 0x04E0,
michael@0 25730 Dzecyrillic: 0x0405,
michael@0 25731 Dzhecyrillic: 0x040F,
michael@0 25732 E: 0x0045,
michael@0 25733 Eacute: 0x00C9,
michael@0 25734 Eacutesmall: 0xF7E9,
michael@0 25735 Ebreve: 0x0114,
michael@0 25736 Ecaron: 0x011A,
michael@0 25737 Ecedillabreve: 0x1E1C,
michael@0 25738 Echarmenian: 0x0535,
michael@0 25739 Ecircle: 0x24BA,
michael@0 25740 Ecircumflex: 0x00CA,
michael@0 25741 Ecircumflexacute: 0x1EBE,
michael@0 25742 Ecircumflexbelow: 0x1E18,
michael@0 25743 Ecircumflexdotbelow: 0x1EC6,
michael@0 25744 Ecircumflexgrave: 0x1EC0,
michael@0 25745 Ecircumflexhookabove: 0x1EC2,
michael@0 25746 Ecircumflexsmall: 0xF7EA,
michael@0 25747 Ecircumflextilde: 0x1EC4,
michael@0 25748 Ecyrillic: 0x0404,
michael@0 25749 Edblgrave: 0x0204,
michael@0 25750 Edieresis: 0x00CB,
michael@0 25751 Edieresissmall: 0xF7EB,
michael@0 25752 Edot: 0x0116,
michael@0 25753 Edotaccent: 0x0116,
michael@0 25754 Edotbelow: 0x1EB8,
michael@0 25755 Efcyrillic: 0x0424,
michael@0 25756 Egrave: 0x00C8,
michael@0 25757 Egravesmall: 0xF7E8,
michael@0 25758 Eharmenian: 0x0537,
michael@0 25759 Ehookabove: 0x1EBA,
michael@0 25760 Eightroman: 0x2167,
michael@0 25761 Einvertedbreve: 0x0206,
michael@0 25762 Eiotifiedcyrillic: 0x0464,
michael@0 25763 Elcyrillic: 0x041B,
michael@0 25764 Elevenroman: 0x216A,
michael@0 25765 Emacron: 0x0112,
michael@0 25766 Emacronacute: 0x1E16,
michael@0 25767 Emacrongrave: 0x1E14,
michael@0 25768 Emcyrillic: 0x041C,
michael@0 25769 Emonospace: 0xFF25,
michael@0 25770 Encyrillic: 0x041D,
michael@0 25771 Endescendercyrillic: 0x04A2,
michael@0 25772 Eng: 0x014A,
michael@0 25773 Enghecyrillic: 0x04A4,
michael@0 25774 Enhookcyrillic: 0x04C7,
michael@0 25775 Eogonek: 0x0118,
michael@0 25776 Eopen: 0x0190,
michael@0 25777 Epsilon: 0x0395,
michael@0 25778 Epsilontonos: 0x0388,
michael@0 25779 Ercyrillic: 0x0420,
michael@0 25780 Ereversed: 0x018E,
michael@0 25781 Ereversedcyrillic: 0x042D,
michael@0 25782 Escyrillic: 0x0421,
michael@0 25783 Esdescendercyrillic: 0x04AA,
michael@0 25784 Esh: 0x01A9,
michael@0 25785 Esmall: 0xF765,
michael@0 25786 Eta: 0x0397,
michael@0 25787 Etarmenian: 0x0538,
michael@0 25788 Etatonos: 0x0389,
michael@0 25789 Eth: 0x00D0,
michael@0 25790 Ethsmall: 0xF7F0,
michael@0 25791 Etilde: 0x1EBC,
michael@0 25792 Etildebelow: 0x1E1A,
michael@0 25793 Euro: 0x20AC,
michael@0 25794 Ezh: 0x01B7,
michael@0 25795 Ezhcaron: 0x01EE,
michael@0 25796 Ezhreversed: 0x01B8,
michael@0 25797 F: 0x0046,
michael@0 25798 Fcircle: 0x24BB,
michael@0 25799 Fdotaccent: 0x1E1E,
michael@0 25800 Feharmenian: 0x0556,
michael@0 25801 Feicoptic: 0x03E4,
michael@0 25802 Fhook: 0x0191,
michael@0 25803 Fitacyrillic: 0x0472,
michael@0 25804 Fiveroman: 0x2164,
michael@0 25805 Fmonospace: 0xFF26,
michael@0 25806 Fourroman: 0x2163,
michael@0 25807 Fsmall: 0xF766,
michael@0 25808 G: 0x0047,
michael@0 25809 GBsquare: 0x3387,
michael@0 25810 Gacute: 0x01F4,
michael@0 25811 Gamma: 0x0393,
michael@0 25812 Gammaafrican: 0x0194,
michael@0 25813 Gangiacoptic: 0x03EA,
michael@0 25814 Gbreve: 0x011E,
michael@0 25815 Gcaron: 0x01E6,
michael@0 25816 Gcedilla: 0x0122,
michael@0 25817 Gcircle: 0x24BC,
michael@0 25818 Gcircumflex: 0x011C,
michael@0 25819 Gcommaaccent: 0x0122,
michael@0 25820 Gdot: 0x0120,
michael@0 25821 Gdotaccent: 0x0120,
michael@0 25822 Gecyrillic: 0x0413,
michael@0 25823 Ghadarmenian: 0x0542,
michael@0 25824 Ghemiddlehookcyrillic: 0x0494,
michael@0 25825 Ghestrokecyrillic: 0x0492,
michael@0 25826 Gheupturncyrillic: 0x0490,
michael@0 25827 Ghook: 0x0193,
michael@0 25828 Gimarmenian: 0x0533,
michael@0 25829 Gjecyrillic: 0x0403,
michael@0 25830 Gmacron: 0x1E20,
michael@0 25831 Gmonospace: 0xFF27,
michael@0 25832 Grave: 0xF6CE,
michael@0 25833 Gravesmall: 0xF760,
michael@0 25834 Gsmall: 0xF767,
michael@0 25835 Gsmallhook: 0x029B,
michael@0 25836 Gstroke: 0x01E4,
michael@0 25837 H: 0x0048,
michael@0 25838 H18533: 0x25CF,
michael@0 25839 H18543: 0x25AA,
michael@0 25840 H18551: 0x25AB,
michael@0 25841 H22073: 0x25A1,
michael@0 25842 HPsquare: 0x33CB,
michael@0 25843 Haabkhasiancyrillic: 0x04A8,
michael@0 25844 Hadescendercyrillic: 0x04B2,
michael@0 25845 Hardsigncyrillic: 0x042A,
michael@0 25846 Hbar: 0x0126,
michael@0 25847 Hbrevebelow: 0x1E2A,
michael@0 25848 Hcedilla: 0x1E28,
michael@0 25849 Hcircle: 0x24BD,
michael@0 25850 Hcircumflex: 0x0124,
michael@0 25851 Hdieresis: 0x1E26,
michael@0 25852 Hdotaccent: 0x1E22,
michael@0 25853 Hdotbelow: 0x1E24,
michael@0 25854 Hmonospace: 0xFF28,
michael@0 25855 Hoarmenian: 0x0540,
michael@0 25856 Horicoptic: 0x03E8,
michael@0 25857 Hsmall: 0xF768,
michael@0 25858 Hungarumlaut: 0xF6CF,
michael@0 25859 Hungarumlautsmall: 0xF6F8,
michael@0 25860 Hzsquare: 0x3390,
michael@0 25861 I: 0x0049,
michael@0 25862 IAcyrillic: 0x042F,
michael@0 25863 IJ: 0x0132,
michael@0 25864 IUcyrillic: 0x042E,
michael@0 25865 Iacute: 0x00CD,
michael@0 25866 Iacutesmall: 0xF7ED,
michael@0 25867 Ibreve: 0x012C,
michael@0 25868 Icaron: 0x01CF,
michael@0 25869 Icircle: 0x24BE,
michael@0 25870 Icircumflex: 0x00CE,
michael@0 25871 Icircumflexsmall: 0xF7EE,
michael@0 25872 Icyrillic: 0x0406,
michael@0 25873 Idblgrave: 0x0208,
michael@0 25874 Idieresis: 0x00CF,
michael@0 25875 Idieresisacute: 0x1E2E,
michael@0 25876 Idieresiscyrillic: 0x04E4,
michael@0 25877 Idieresissmall: 0xF7EF,
michael@0 25878 Idot: 0x0130,
michael@0 25879 Idotaccent: 0x0130,
michael@0 25880 Idotbelow: 0x1ECA,
michael@0 25881 Iebrevecyrillic: 0x04D6,
michael@0 25882 Iecyrillic: 0x0415,
michael@0 25883 Ifraktur: 0x2111,
michael@0 25884 Igrave: 0x00CC,
michael@0 25885 Igravesmall: 0xF7EC,
michael@0 25886 Ihookabove: 0x1EC8,
michael@0 25887 Iicyrillic: 0x0418,
michael@0 25888 Iinvertedbreve: 0x020A,
michael@0 25889 Iishortcyrillic: 0x0419,
michael@0 25890 Imacron: 0x012A,
michael@0 25891 Imacroncyrillic: 0x04E2,
michael@0 25892 Imonospace: 0xFF29,
michael@0 25893 Iniarmenian: 0x053B,
michael@0 25894 Iocyrillic: 0x0401,
michael@0 25895 Iogonek: 0x012E,
michael@0 25896 Iota: 0x0399,
michael@0 25897 Iotaafrican: 0x0196,
michael@0 25898 Iotadieresis: 0x03AA,
michael@0 25899 Iotatonos: 0x038A,
michael@0 25900 Ismall: 0xF769,
michael@0 25901 Istroke: 0x0197,
michael@0 25902 Itilde: 0x0128,
michael@0 25903 Itildebelow: 0x1E2C,
michael@0 25904 Izhitsacyrillic: 0x0474,
michael@0 25905 Izhitsadblgravecyrillic: 0x0476,
michael@0 25906 J: 0x004A,
michael@0 25907 Jaarmenian: 0x0541,
michael@0 25908 Jcircle: 0x24BF,
michael@0 25909 Jcircumflex: 0x0134,
michael@0 25910 Jecyrillic: 0x0408,
michael@0 25911 Jheharmenian: 0x054B,
michael@0 25912 Jmonospace: 0xFF2A,
michael@0 25913 Jsmall: 0xF76A,
michael@0 25914 K: 0x004B,
michael@0 25915 KBsquare: 0x3385,
michael@0 25916 KKsquare: 0x33CD,
michael@0 25917 Kabashkircyrillic: 0x04A0,
michael@0 25918 Kacute: 0x1E30,
michael@0 25919 Kacyrillic: 0x041A,
michael@0 25920 Kadescendercyrillic: 0x049A,
michael@0 25921 Kahookcyrillic: 0x04C3,
michael@0 25922 Kappa: 0x039A,
michael@0 25923 Kastrokecyrillic: 0x049E,
michael@0 25924 Kaverticalstrokecyrillic: 0x049C,
michael@0 25925 Kcaron: 0x01E8,
michael@0 25926 Kcedilla: 0x0136,
michael@0 25927 Kcircle: 0x24C0,
michael@0 25928 Kcommaaccent: 0x0136,
michael@0 25929 Kdotbelow: 0x1E32,
michael@0 25930 Keharmenian: 0x0554,
michael@0 25931 Kenarmenian: 0x053F,
michael@0 25932 Khacyrillic: 0x0425,
michael@0 25933 Kheicoptic: 0x03E6,
michael@0 25934 Khook: 0x0198,
michael@0 25935 Kjecyrillic: 0x040C,
michael@0 25936 Klinebelow: 0x1E34,
michael@0 25937 Kmonospace: 0xFF2B,
michael@0 25938 Koppacyrillic: 0x0480,
michael@0 25939 Koppagreek: 0x03DE,
michael@0 25940 Ksicyrillic: 0x046E,
michael@0 25941 Ksmall: 0xF76B,
michael@0 25942 L: 0x004C,
michael@0 25943 LJ: 0x01C7,
michael@0 25944 LL: 0xF6BF,
michael@0 25945 Lacute: 0x0139,
michael@0 25946 Lambda: 0x039B,
michael@0 25947 Lcaron: 0x013D,
michael@0 25948 Lcedilla: 0x013B,
michael@0 25949 Lcircle: 0x24C1,
michael@0 25950 Lcircumflexbelow: 0x1E3C,
michael@0 25951 Lcommaaccent: 0x013B,
michael@0 25952 Ldot: 0x013F,
michael@0 25953 Ldotaccent: 0x013F,
michael@0 25954 Ldotbelow: 0x1E36,
michael@0 25955 Ldotbelowmacron: 0x1E38,
michael@0 25956 Liwnarmenian: 0x053C,
michael@0 25957 Lj: 0x01C8,
michael@0 25958 Ljecyrillic: 0x0409,
michael@0 25959 Llinebelow: 0x1E3A,
michael@0 25960 Lmonospace: 0xFF2C,
michael@0 25961 Lslash: 0x0141,
michael@0 25962 Lslashsmall: 0xF6F9,
michael@0 25963 Lsmall: 0xF76C,
michael@0 25964 M: 0x004D,
michael@0 25965 MBsquare: 0x3386,
michael@0 25966 Macron: 0xF6D0,
michael@0 25967 Macronsmall: 0xF7AF,
michael@0 25968 Macute: 0x1E3E,
michael@0 25969 Mcircle: 0x24C2,
michael@0 25970 Mdotaccent: 0x1E40,
michael@0 25971 Mdotbelow: 0x1E42,
michael@0 25972 Menarmenian: 0x0544,
michael@0 25973 Mmonospace: 0xFF2D,
michael@0 25974 Msmall: 0xF76D,
michael@0 25975 Mturned: 0x019C,
michael@0 25976 Mu: 0x039C,
michael@0 25977 N: 0x004E,
michael@0 25978 NJ: 0x01CA,
michael@0 25979 Nacute: 0x0143,
michael@0 25980 Ncaron: 0x0147,
michael@0 25981 Ncedilla: 0x0145,
michael@0 25982 Ncircle: 0x24C3,
michael@0 25983 Ncircumflexbelow: 0x1E4A,
michael@0 25984 Ncommaaccent: 0x0145,
michael@0 25985 Ndotaccent: 0x1E44,
michael@0 25986 Ndotbelow: 0x1E46,
michael@0 25987 Nhookleft: 0x019D,
michael@0 25988 Nineroman: 0x2168,
michael@0 25989 Nj: 0x01CB,
michael@0 25990 Njecyrillic: 0x040A,
michael@0 25991 Nlinebelow: 0x1E48,
michael@0 25992 Nmonospace: 0xFF2E,
michael@0 25993 Nowarmenian: 0x0546,
michael@0 25994 Nsmall: 0xF76E,
michael@0 25995 Ntilde: 0x00D1,
michael@0 25996 Ntildesmall: 0xF7F1,
michael@0 25997 Nu: 0x039D,
michael@0 25998 O: 0x004F,
michael@0 25999 OE: 0x0152,
michael@0 26000 OEsmall: 0xF6FA,
michael@0 26001 Oacute: 0x00D3,
michael@0 26002 Oacutesmall: 0xF7F3,
michael@0 26003 Obarredcyrillic: 0x04E8,
michael@0 26004 Obarreddieresiscyrillic: 0x04EA,
michael@0 26005 Obreve: 0x014E,
michael@0 26006 Ocaron: 0x01D1,
michael@0 26007 Ocenteredtilde: 0x019F,
michael@0 26008 Ocircle: 0x24C4,
michael@0 26009 Ocircumflex: 0x00D4,
michael@0 26010 Ocircumflexacute: 0x1ED0,
michael@0 26011 Ocircumflexdotbelow: 0x1ED8,
michael@0 26012 Ocircumflexgrave: 0x1ED2,
michael@0 26013 Ocircumflexhookabove: 0x1ED4,
michael@0 26014 Ocircumflexsmall: 0xF7F4,
michael@0 26015 Ocircumflextilde: 0x1ED6,
michael@0 26016 Ocyrillic: 0x041E,
michael@0 26017 Odblacute: 0x0150,
michael@0 26018 Odblgrave: 0x020C,
michael@0 26019 Odieresis: 0x00D6,
michael@0 26020 Odieresiscyrillic: 0x04E6,
michael@0 26021 Odieresissmall: 0xF7F6,
michael@0 26022 Odotbelow: 0x1ECC,
michael@0 26023 Ogoneksmall: 0xF6FB,
michael@0 26024 Ograve: 0x00D2,
michael@0 26025 Ogravesmall: 0xF7F2,
michael@0 26026 Oharmenian: 0x0555,
michael@0 26027 Ohm: 0x2126,
michael@0 26028 Ohookabove: 0x1ECE,
michael@0 26029 Ohorn: 0x01A0,
michael@0 26030 Ohornacute: 0x1EDA,
michael@0 26031 Ohorndotbelow: 0x1EE2,
michael@0 26032 Ohorngrave: 0x1EDC,
michael@0 26033 Ohornhookabove: 0x1EDE,
michael@0 26034 Ohorntilde: 0x1EE0,
michael@0 26035 Ohungarumlaut: 0x0150,
michael@0 26036 Oi: 0x01A2,
michael@0 26037 Oinvertedbreve: 0x020E,
michael@0 26038 Omacron: 0x014C,
michael@0 26039 Omacronacute: 0x1E52,
michael@0 26040 Omacrongrave: 0x1E50,
michael@0 26041 Omega: 0x2126,
michael@0 26042 Omegacyrillic: 0x0460,
michael@0 26043 Omegagreek: 0x03A9,
michael@0 26044 Omegaroundcyrillic: 0x047A,
michael@0 26045 Omegatitlocyrillic: 0x047C,
michael@0 26046 Omegatonos: 0x038F,
michael@0 26047 Omicron: 0x039F,
michael@0 26048 Omicrontonos: 0x038C,
michael@0 26049 Omonospace: 0xFF2F,
michael@0 26050 Oneroman: 0x2160,
michael@0 26051 Oogonek: 0x01EA,
michael@0 26052 Oogonekmacron: 0x01EC,
michael@0 26053 Oopen: 0x0186,
michael@0 26054 Oslash: 0x00D8,
michael@0 26055 Oslashacute: 0x01FE,
michael@0 26056 Oslashsmall: 0xF7F8,
michael@0 26057 Osmall: 0xF76F,
michael@0 26058 Ostrokeacute: 0x01FE,
michael@0 26059 Otcyrillic: 0x047E,
michael@0 26060 Otilde: 0x00D5,
michael@0 26061 Otildeacute: 0x1E4C,
michael@0 26062 Otildedieresis: 0x1E4E,
michael@0 26063 Otildesmall: 0xF7F5,
michael@0 26064 P: 0x0050,
michael@0 26065 Pacute: 0x1E54,
michael@0 26066 Pcircle: 0x24C5,
michael@0 26067 Pdotaccent: 0x1E56,
michael@0 26068 Pecyrillic: 0x041F,
michael@0 26069 Peharmenian: 0x054A,
michael@0 26070 Pemiddlehookcyrillic: 0x04A6,
michael@0 26071 Phi: 0x03A6,
michael@0 26072 Phook: 0x01A4,
michael@0 26073 Pi: 0x03A0,
michael@0 26074 Piwrarmenian: 0x0553,
michael@0 26075 Pmonospace: 0xFF30,
michael@0 26076 Psi: 0x03A8,
michael@0 26077 Psicyrillic: 0x0470,
michael@0 26078 Psmall: 0xF770,
michael@0 26079 Q: 0x0051,
michael@0 26080 Qcircle: 0x24C6,
michael@0 26081 Qmonospace: 0xFF31,
michael@0 26082 Qsmall: 0xF771,
michael@0 26083 R: 0x0052,
michael@0 26084 Raarmenian: 0x054C,
michael@0 26085 Racute: 0x0154,
michael@0 26086 Rcaron: 0x0158,
michael@0 26087 Rcedilla: 0x0156,
michael@0 26088 Rcircle: 0x24C7,
michael@0 26089 Rcommaaccent: 0x0156,
michael@0 26090 Rdblgrave: 0x0210,
michael@0 26091 Rdotaccent: 0x1E58,
michael@0 26092 Rdotbelow: 0x1E5A,
michael@0 26093 Rdotbelowmacron: 0x1E5C,
michael@0 26094 Reharmenian: 0x0550,
michael@0 26095 Rfraktur: 0x211C,
michael@0 26096 Rho: 0x03A1,
michael@0 26097 Ringsmall: 0xF6FC,
michael@0 26098 Rinvertedbreve: 0x0212,
michael@0 26099 Rlinebelow: 0x1E5E,
michael@0 26100 Rmonospace: 0xFF32,
michael@0 26101 Rsmall: 0xF772,
michael@0 26102 Rsmallinverted: 0x0281,
michael@0 26103 Rsmallinvertedsuperior: 0x02B6,
michael@0 26104 S: 0x0053,
michael@0 26105 SF010000: 0x250C,
michael@0 26106 SF020000: 0x2514,
michael@0 26107 SF030000: 0x2510,
michael@0 26108 SF040000: 0x2518,
michael@0 26109 SF050000: 0x253C,
michael@0 26110 SF060000: 0x252C,
michael@0 26111 SF070000: 0x2534,
michael@0 26112 SF080000: 0x251C,
michael@0 26113 SF090000: 0x2524,
michael@0 26114 SF100000: 0x2500,
michael@0 26115 SF110000: 0x2502,
michael@0 26116 SF190000: 0x2561,
michael@0 26117 SF200000: 0x2562,
michael@0 26118 SF210000: 0x2556,
michael@0 26119 SF220000: 0x2555,
michael@0 26120 SF230000: 0x2563,
michael@0 26121 SF240000: 0x2551,
michael@0 26122 SF250000: 0x2557,
michael@0 26123 SF260000: 0x255D,
michael@0 26124 SF270000: 0x255C,
michael@0 26125 SF280000: 0x255B,
michael@0 26126 SF360000: 0x255E,
michael@0 26127 SF370000: 0x255F,
michael@0 26128 SF380000: 0x255A,
michael@0 26129 SF390000: 0x2554,
michael@0 26130 SF400000: 0x2569,
michael@0 26131 SF410000: 0x2566,
michael@0 26132 SF420000: 0x2560,
michael@0 26133 SF430000: 0x2550,
michael@0 26134 SF440000: 0x256C,
michael@0 26135 SF450000: 0x2567,
michael@0 26136 SF460000: 0x2568,
michael@0 26137 SF470000: 0x2564,
michael@0 26138 SF480000: 0x2565,
michael@0 26139 SF490000: 0x2559,
michael@0 26140 SF500000: 0x2558,
michael@0 26141 SF510000: 0x2552,
michael@0 26142 SF520000: 0x2553,
michael@0 26143 SF530000: 0x256B,
michael@0 26144 SF540000: 0x256A,
michael@0 26145 Sacute: 0x015A,
michael@0 26146 Sacutedotaccent: 0x1E64,
michael@0 26147 Sampigreek: 0x03E0,
michael@0 26148 Scaron: 0x0160,
michael@0 26149 Scarondotaccent: 0x1E66,
michael@0 26150 Scaronsmall: 0xF6FD,
michael@0 26151 Scedilla: 0x015E,
michael@0 26152 Schwa: 0x018F,
michael@0 26153 Schwacyrillic: 0x04D8,
michael@0 26154 Schwadieresiscyrillic: 0x04DA,
michael@0 26155 Scircle: 0x24C8,
michael@0 26156 Scircumflex: 0x015C,
michael@0 26157 Scommaaccent: 0x0218,
michael@0 26158 Sdotaccent: 0x1E60,
michael@0 26159 Sdotbelow: 0x1E62,
michael@0 26160 Sdotbelowdotaccent: 0x1E68,
michael@0 26161 Seharmenian: 0x054D,
michael@0 26162 Sevenroman: 0x2166,
michael@0 26163 Shaarmenian: 0x0547,
michael@0 26164 Shacyrillic: 0x0428,
michael@0 26165 Shchacyrillic: 0x0429,
michael@0 26166 Sheicoptic: 0x03E2,
michael@0 26167 Shhacyrillic: 0x04BA,
michael@0 26168 Shimacoptic: 0x03EC,
michael@0 26169 Sigma: 0x03A3,
michael@0 26170 Sixroman: 0x2165,
michael@0 26171 Smonospace: 0xFF33,
michael@0 26172 Softsigncyrillic: 0x042C,
michael@0 26173 Ssmall: 0xF773,
michael@0 26174 Stigmagreek: 0x03DA,
michael@0 26175 T: 0x0054,
michael@0 26176 Tau: 0x03A4,
michael@0 26177 Tbar: 0x0166,
michael@0 26178 Tcaron: 0x0164,
michael@0 26179 Tcedilla: 0x0162,
michael@0 26180 Tcircle: 0x24C9,
michael@0 26181 Tcircumflexbelow: 0x1E70,
michael@0 26182 Tcommaaccent: 0x0162,
michael@0 26183 Tdotaccent: 0x1E6A,
michael@0 26184 Tdotbelow: 0x1E6C,
michael@0 26185 Tecyrillic: 0x0422,
michael@0 26186 Tedescendercyrillic: 0x04AC,
michael@0 26187 Tenroman: 0x2169,
michael@0 26188 Tetsecyrillic: 0x04B4,
michael@0 26189 Theta: 0x0398,
michael@0 26190 Thook: 0x01AC,
michael@0 26191 Thorn: 0x00DE,
michael@0 26192 Thornsmall: 0xF7FE,
michael@0 26193 Threeroman: 0x2162,
michael@0 26194 Tildesmall: 0xF6FE,
michael@0 26195 Tiwnarmenian: 0x054F,
michael@0 26196 Tlinebelow: 0x1E6E,
michael@0 26197 Tmonospace: 0xFF34,
michael@0 26198 Toarmenian: 0x0539,
michael@0 26199 Tonefive: 0x01BC,
michael@0 26200 Tonesix: 0x0184,
michael@0 26201 Tonetwo: 0x01A7,
michael@0 26202 Tretroflexhook: 0x01AE,
michael@0 26203 Tsecyrillic: 0x0426,
michael@0 26204 Tshecyrillic: 0x040B,
michael@0 26205 Tsmall: 0xF774,
michael@0 26206 Twelveroman: 0x216B,
michael@0 26207 Tworoman: 0x2161,
michael@0 26208 U: 0x0055,
michael@0 26209 Uacute: 0x00DA,
michael@0 26210 Uacutesmall: 0xF7FA,
michael@0 26211 Ubreve: 0x016C,
michael@0 26212 Ucaron: 0x01D3,
michael@0 26213 Ucircle: 0x24CA,
michael@0 26214 Ucircumflex: 0x00DB,
michael@0 26215 Ucircumflexbelow: 0x1E76,
michael@0 26216 Ucircumflexsmall: 0xF7FB,
michael@0 26217 Ucyrillic: 0x0423,
michael@0 26218 Udblacute: 0x0170,
michael@0 26219 Udblgrave: 0x0214,
michael@0 26220 Udieresis: 0x00DC,
michael@0 26221 Udieresisacute: 0x01D7,
michael@0 26222 Udieresisbelow: 0x1E72,
michael@0 26223 Udieresiscaron: 0x01D9,
michael@0 26224 Udieresiscyrillic: 0x04F0,
michael@0 26225 Udieresisgrave: 0x01DB,
michael@0 26226 Udieresismacron: 0x01D5,
michael@0 26227 Udieresissmall: 0xF7FC,
michael@0 26228 Udotbelow: 0x1EE4,
michael@0 26229 Ugrave: 0x00D9,
michael@0 26230 Ugravesmall: 0xF7F9,
michael@0 26231 Uhookabove: 0x1EE6,
michael@0 26232 Uhorn: 0x01AF,
michael@0 26233 Uhornacute: 0x1EE8,
michael@0 26234 Uhorndotbelow: 0x1EF0,
michael@0 26235 Uhorngrave: 0x1EEA,
michael@0 26236 Uhornhookabove: 0x1EEC,
michael@0 26237 Uhorntilde: 0x1EEE,
michael@0 26238 Uhungarumlaut: 0x0170,
michael@0 26239 Uhungarumlautcyrillic: 0x04F2,
michael@0 26240 Uinvertedbreve: 0x0216,
michael@0 26241 Ukcyrillic: 0x0478,
michael@0 26242 Umacron: 0x016A,
michael@0 26243 Umacroncyrillic: 0x04EE,
michael@0 26244 Umacrondieresis: 0x1E7A,
michael@0 26245 Umonospace: 0xFF35,
michael@0 26246 Uogonek: 0x0172,
michael@0 26247 Upsilon: 0x03A5,
michael@0 26248 Upsilon1: 0x03D2,
michael@0 26249 Upsilonacutehooksymbolgreek: 0x03D3,
michael@0 26250 Upsilonafrican: 0x01B1,
michael@0 26251 Upsilondieresis: 0x03AB,
michael@0 26252 Upsilondieresishooksymbolgreek: 0x03D4,
michael@0 26253 Upsilonhooksymbol: 0x03D2,
michael@0 26254 Upsilontonos: 0x038E,
michael@0 26255 Uring: 0x016E,
michael@0 26256 Ushortcyrillic: 0x040E,
michael@0 26257 Usmall: 0xF775,
michael@0 26258 Ustraightcyrillic: 0x04AE,
michael@0 26259 Ustraightstrokecyrillic: 0x04B0,
michael@0 26260 Utilde: 0x0168,
michael@0 26261 Utildeacute: 0x1E78,
michael@0 26262 Utildebelow: 0x1E74,
michael@0 26263 V: 0x0056,
michael@0 26264 Vcircle: 0x24CB,
michael@0 26265 Vdotbelow: 0x1E7E,
michael@0 26266 Vecyrillic: 0x0412,
michael@0 26267 Vewarmenian: 0x054E,
michael@0 26268 Vhook: 0x01B2,
michael@0 26269 Vmonospace: 0xFF36,
michael@0 26270 Voarmenian: 0x0548,
michael@0 26271 Vsmall: 0xF776,
michael@0 26272 Vtilde: 0x1E7C,
michael@0 26273 W: 0x0057,
michael@0 26274 Wacute: 0x1E82,
michael@0 26275 Wcircle: 0x24CC,
michael@0 26276 Wcircumflex: 0x0174,
michael@0 26277 Wdieresis: 0x1E84,
michael@0 26278 Wdotaccent: 0x1E86,
michael@0 26279 Wdotbelow: 0x1E88,
michael@0 26280 Wgrave: 0x1E80,
michael@0 26281 Wmonospace: 0xFF37,
michael@0 26282 Wsmall: 0xF777,
michael@0 26283 X: 0x0058,
michael@0 26284 Xcircle: 0x24CD,
michael@0 26285 Xdieresis: 0x1E8C,
michael@0 26286 Xdotaccent: 0x1E8A,
michael@0 26287 Xeharmenian: 0x053D,
michael@0 26288 Xi: 0x039E,
michael@0 26289 Xmonospace: 0xFF38,
michael@0 26290 Xsmall: 0xF778,
michael@0 26291 Y: 0x0059,
michael@0 26292 Yacute: 0x00DD,
michael@0 26293 Yacutesmall: 0xF7FD,
michael@0 26294 Yatcyrillic: 0x0462,
michael@0 26295 Ycircle: 0x24CE,
michael@0 26296 Ycircumflex: 0x0176,
michael@0 26297 Ydieresis: 0x0178,
michael@0 26298 Ydieresissmall: 0xF7FF,
michael@0 26299 Ydotaccent: 0x1E8E,
michael@0 26300 Ydotbelow: 0x1EF4,
michael@0 26301 Yericyrillic: 0x042B,
michael@0 26302 Yerudieresiscyrillic: 0x04F8,
michael@0 26303 Ygrave: 0x1EF2,
michael@0 26304 Yhook: 0x01B3,
michael@0 26305 Yhookabove: 0x1EF6,
michael@0 26306 Yiarmenian: 0x0545,
michael@0 26307 Yicyrillic: 0x0407,
michael@0 26308 Yiwnarmenian: 0x0552,
michael@0 26309 Ymonospace: 0xFF39,
michael@0 26310 Ysmall: 0xF779,
michael@0 26311 Ytilde: 0x1EF8,
michael@0 26312 Yusbigcyrillic: 0x046A,
michael@0 26313 Yusbigiotifiedcyrillic: 0x046C,
michael@0 26314 Yuslittlecyrillic: 0x0466,
michael@0 26315 Yuslittleiotifiedcyrillic: 0x0468,
michael@0 26316 Z: 0x005A,
michael@0 26317 Zaarmenian: 0x0536,
michael@0 26318 Zacute: 0x0179,
michael@0 26319 Zcaron: 0x017D,
michael@0 26320 Zcaronsmall: 0xF6FF,
michael@0 26321 Zcircle: 0x24CF,
michael@0 26322 Zcircumflex: 0x1E90,
michael@0 26323 Zdot: 0x017B,
michael@0 26324 Zdotaccent: 0x017B,
michael@0 26325 Zdotbelow: 0x1E92,
michael@0 26326 Zecyrillic: 0x0417,
michael@0 26327 Zedescendercyrillic: 0x0498,
michael@0 26328 Zedieresiscyrillic: 0x04DE,
michael@0 26329 Zeta: 0x0396,
michael@0 26330 Zhearmenian: 0x053A,
michael@0 26331 Zhebrevecyrillic: 0x04C1,
michael@0 26332 Zhecyrillic: 0x0416,
michael@0 26333 Zhedescendercyrillic: 0x0496,
michael@0 26334 Zhedieresiscyrillic: 0x04DC,
michael@0 26335 Zlinebelow: 0x1E94,
michael@0 26336 Zmonospace: 0xFF3A,
michael@0 26337 Zsmall: 0xF77A,
michael@0 26338 Zstroke: 0x01B5,
michael@0 26339 a: 0x0061,
michael@0 26340 aabengali: 0x0986,
michael@0 26341 aacute: 0x00E1,
michael@0 26342 aadeva: 0x0906,
michael@0 26343 aagujarati: 0x0A86,
michael@0 26344 aagurmukhi: 0x0A06,
michael@0 26345 aamatragurmukhi: 0x0A3E,
michael@0 26346 aarusquare: 0x3303,
michael@0 26347 aavowelsignbengali: 0x09BE,
michael@0 26348 aavowelsigndeva: 0x093E,
michael@0 26349 aavowelsigngujarati: 0x0ABE,
michael@0 26350 abbreviationmarkarmenian: 0x055F,
michael@0 26351 abbreviationsigndeva: 0x0970,
michael@0 26352 abengali: 0x0985,
michael@0 26353 abopomofo: 0x311A,
michael@0 26354 abreve: 0x0103,
michael@0 26355 abreveacute: 0x1EAF,
michael@0 26356 abrevecyrillic: 0x04D1,
michael@0 26357 abrevedotbelow: 0x1EB7,
michael@0 26358 abrevegrave: 0x1EB1,
michael@0 26359 abrevehookabove: 0x1EB3,
michael@0 26360 abrevetilde: 0x1EB5,
michael@0 26361 acaron: 0x01CE,
michael@0 26362 acircle: 0x24D0,
michael@0 26363 acircumflex: 0x00E2,
michael@0 26364 acircumflexacute: 0x1EA5,
michael@0 26365 acircumflexdotbelow: 0x1EAD,
michael@0 26366 acircumflexgrave: 0x1EA7,
michael@0 26367 acircumflexhookabove: 0x1EA9,
michael@0 26368 acircumflextilde: 0x1EAB,
michael@0 26369 acute: 0x00B4,
michael@0 26370 acutebelowcmb: 0x0317,
michael@0 26371 acutecmb: 0x0301,
michael@0 26372 acutecomb: 0x0301,
michael@0 26373 acutedeva: 0x0954,
michael@0 26374 acutelowmod: 0x02CF,
michael@0 26375 acutetonecmb: 0x0341,
michael@0 26376 acyrillic: 0x0430,
michael@0 26377 adblgrave: 0x0201,
michael@0 26378 addakgurmukhi: 0x0A71,
michael@0 26379 adeva: 0x0905,
michael@0 26380 adieresis: 0x00E4,
michael@0 26381 adieresiscyrillic: 0x04D3,
michael@0 26382 adieresismacron: 0x01DF,
michael@0 26383 adotbelow: 0x1EA1,
michael@0 26384 adotmacron: 0x01E1,
michael@0 26385 ae: 0x00E6,
michael@0 26386 aeacute: 0x01FD,
michael@0 26387 aekorean: 0x3150,
michael@0 26388 aemacron: 0x01E3,
michael@0 26389 afii00208: 0x2015,
michael@0 26390 afii08941: 0x20A4,
michael@0 26391 afii10017: 0x0410,
michael@0 26392 afii10018: 0x0411,
michael@0 26393 afii10019: 0x0412,
michael@0 26394 afii10020: 0x0413,
michael@0 26395 afii10021: 0x0414,
michael@0 26396 afii10022: 0x0415,
michael@0 26397 afii10023: 0x0401,
michael@0 26398 afii10024: 0x0416,
michael@0 26399 afii10025: 0x0417,
michael@0 26400 afii10026: 0x0418,
michael@0 26401 afii10027: 0x0419,
michael@0 26402 afii10028: 0x041A,
michael@0 26403 afii10029: 0x041B,
michael@0 26404 afii10030: 0x041C,
michael@0 26405 afii10031: 0x041D,
michael@0 26406 afii10032: 0x041E,
michael@0 26407 afii10033: 0x041F,
michael@0 26408 afii10034: 0x0420,
michael@0 26409 afii10035: 0x0421,
michael@0 26410 afii10036: 0x0422,
michael@0 26411 afii10037: 0x0423,
michael@0 26412 afii10038: 0x0424,
michael@0 26413 afii10039: 0x0425,
michael@0 26414 afii10040: 0x0426,
michael@0 26415 afii10041: 0x0427,
michael@0 26416 afii10042: 0x0428,
michael@0 26417 afii10043: 0x0429,
michael@0 26418 afii10044: 0x042A,
michael@0 26419 afii10045: 0x042B,
michael@0 26420 afii10046: 0x042C,
michael@0 26421 afii10047: 0x042D,
michael@0 26422 afii10048: 0x042E,
michael@0 26423 afii10049: 0x042F,
michael@0 26424 afii10050: 0x0490,
michael@0 26425 afii10051: 0x0402,
michael@0 26426 afii10052: 0x0403,
michael@0 26427 afii10053: 0x0404,
michael@0 26428 afii10054: 0x0405,
michael@0 26429 afii10055: 0x0406,
michael@0 26430 afii10056: 0x0407,
michael@0 26431 afii10057: 0x0408,
michael@0 26432 afii10058: 0x0409,
michael@0 26433 afii10059: 0x040A,
michael@0 26434 afii10060: 0x040B,
michael@0 26435 afii10061: 0x040C,
michael@0 26436 afii10062: 0x040E,
michael@0 26437 afii10063: 0xF6C4,
michael@0 26438 afii10064: 0xF6C5,
michael@0 26439 afii10065: 0x0430,
michael@0 26440 afii10066: 0x0431,
michael@0 26441 afii10067: 0x0432,
michael@0 26442 afii10068: 0x0433,
michael@0 26443 afii10069: 0x0434,
michael@0 26444 afii10070: 0x0435,
michael@0 26445 afii10071: 0x0451,
michael@0 26446 afii10072: 0x0436,
michael@0 26447 afii10073: 0x0437,
michael@0 26448 afii10074: 0x0438,
michael@0 26449 afii10075: 0x0439,
michael@0 26450 afii10076: 0x043A,
michael@0 26451 afii10077: 0x043B,
michael@0 26452 afii10078: 0x043C,
michael@0 26453 afii10079: 0x043D,
michael@0 26454 afii10080: 0x043E,
michael@0 26455 afii10081: 0x043F,
michael@0 26456 afii10082: 0x0440,
michael@0 26457 afii10083: 0x0441,
michael@0 26458 afii10084: 0x0442,
michael@0 26459 afii10085: 0x0443,
michael@0 26460 afii10086: 0x0444,
michael@0 26461 afii10087: 0x0445,
michael@0 26462 afii10088: 0x0446,
michael@0 26463 afii10089: 0x0447,
michael@0 26464 afii10090: 0x0448,
michael@0 26465 afii10091: 0x0449,
michael@0 26466 afii10092: 0x044A,
michael@0 26467 afii10093: 0x044B,
michael@0 26468 afii10094: 0x044C,
michael@0 26469 afii10095: 0x044D,
michael@0 26470 afii10096: 0x044E,
michael@0 26471 afii10097: 0x044F,
michael@0 26472 afii10098: 0x0491,
michael@0 26473 afii10099: 0x0452,
michael@0 26474 afii10100: 0x0453,
michael@0 26475 afii10101: 0x0454,
michael@0 26476 afii10102: 0x0455,
michael@0 26477 afii10103: 0x0456,
michael@0 26478 afii10104: 0x0457,
michael@0 26479 afii10105: 0x0458,
michael@0 26480 afii10106: 0x0459,
michael@0 26481 afii10107: 0x045A,
michael@0 26482 afii10108: 0x045B,
michael@0 26483 afii10109: 0x045C,
michael@0 26484 afii10110: 0x045E,
michael@0 26485 afii10145: 0x040F,
michael@0 26486 afii10146: 0x0462,
michael@0 26487 afii10147: 0x0472,
michael@0 26488 afii10148: 0x0474,
michael@0 26489 afii10192: 0xF6C6,
michael@0 26490 afii10193: 0x045F,
michael@0 26491 afii10194: 0x0463,
michael@0 26492 afii10195: 0x0473,
michael@0 26493 afii10196: 0x0475,
michael@0 26494 afii10831: 0xF6C7,
michael@0 26495 afii10832: 0xF6C8,
michael@0 26496 afii10846: 0x04D9,
michael@0 26497 afii299: 0x200E,
michael@0 26498 afii300: 0x200F,
michael@0 26499 afii301: 0x200D,
michael@0 26500 afii57381: 0x066A,
michael@0 26501 afii57388: 0x060C,
michael@0 26502 afii57392: 0x0660,
michael@0 26503 afii57393: 0x0661,
michael@0 26504 afii57394: 0x0662,
michael@0 26505 afii57395: 0x0663,
michael@0 26506 afii57396: 0x0664,
michael@0 26507 afii57397: 0x0665,
michael@0 26508 afii57398: 0x0666,
michael@0 26509 afii57399: 0x0667,
michael@0 26510 afii57400: 0x0668,
michael@0 26511 afii57401: 0x0669,
michael@0 26512 afii57403: 0x061B,
michael@0 26513 afii57407: 0x061F,
michael@0 26514 afii57409: 0x0621,
michael@0 26515 afii57410: 0x0622,
michael@0 26516 afii57411: 0x0623,
michael@0 26517 afii57412: 0x0624,
michael@0 26518 afii57413: 0x0625,
michael@0 26519 afii57414: 0x0626,
michael@0 26520 afii57415: 0x0627,
michael@0 26521 afii57416: 0x0628,
michael@0 26522 afii57417: 0x0629,
michael@0 26523 afii57418: 0x062A,
michael@0 26524 afii57419: 0x062B,
michael@0 26525 afii57420: 0x062C,
michael@0 26526 afii57421: 0x062D,
michael@0 26527 afii57422: 0x062E,
michael@0 26528 afii57423: 0x062F,
michael@0 26529 afii57424: 0x0630,
michael@0 26530 afii57425: 0x0631,
michael@0 26531 afii57426: 0x0632,
michael@0 26532 afii57427: 0x0633,
michael@0 26533 afii57428: 0x0634,
michael@0 26534 afii57429: 0x0635,
michael@0 26535 afii57430: 0x0636,
michael@0 26536 afii57431: 0x0637,
michael@0 26537 afii57432: 0x0638,
michael@0 26538 afii57433: 0x0639,
michael@0 26539 afii57434: 0x063A,
michael@0 26540 afii57440: 0x0640,
michael@0 26541 afii57441: 0x0641,
michael@0 26542 afii57442: 0x0642,
michael@0 26543 afii57443: 0x0643,
michael@0 26544 afii57444: 0x0644,
michael@0 26545 afii57445: 0x0645,
michael@0 26546 afii57446: 0x0646,
michael@0 26547 afii57448: 0x0648,
michael@0 26548 afii57449: 0x0649,
michael@0 26549 afii57450: 0x064A,
michael@0 26550 afii57451: 0x064B,
michael@0 26551 afii57452: 0x064C,
michael@0 26552 afii57453: 0x064D,
michael@0 26553 afii57454: 0x064E,
michael@0 26554 afii57455: 0x064F,
michael@0 26555 afii57456: 0x0650,
michael@0 26556 afii57457: 0x0651,
michael@0 26557 afii57458: 0x0652,
michael@0 26558 afii57470: 0x0647,
michael@0 26559 afii57505: 0x06A4,
michael@0 26560 afii57506: 0x067E,
michael@0 26561 afii57507: 0x0686,
michael@0 26562 afii57508: 0x0698,
michael@0 26563 afii57509: 0x06AF,
michael@0 26564 afii57511: 0x0679,
michael@0 26565 afii57512: 0x0688,
michael@0 26566 afii57513: 0x0691,
michael@0 26567 afii57514: 0x06BA,
michael@0 26568 afii57519: 0x06D2,
michael@0 26569 afii57534: 0x06D5,
michael@0 26570 afii57636: 0x20AA,
michael@0 26571 afii57645: 0x05BE,
michael@0 26572 afii57658: 0x05C3,
michael@0 26573 afii57664: 0x05D0,
michael@0 26574 afii57665: 0x05D1,
michael@0 26575 afii57666: 0x05D2,
michael@0 26576 afii57667: 0x05D3,
michael@0 26577 afii57668: 0x05D4,
michael@0 26578 afii57669: 0x05D5,
michael@0 26579 afii57670: 0x05D6,
michael@0 26580 afii57671: 0x05D7,
michael@0 26581 afii57672: 0x05D8,
michael@0 26582 afii57673: 0x05D9,
michael@0 26583 afii57674: 0x05DA,
michael@0 26584 afii57675: 0x05DB,
michael@0 26585 afii57676: 0x05DC,
michael@0 26586 afii57677: 0x05DD,
michael@0 26587 afii57678: 0x05DE,
michael@0 26588 afii57679: 0x05DF,
michael@0 26589 afii57680: 0x05E0,
michael@0 26590 afii57681: 0x05E1,
michael@0 26591 afii57682: 0x05E2,
michael@0 26592 afii57683: 0x05E3,
michael@0 26593 afii57684: 0x05E4,
michael@0 26594 afii57685: 0x05E5,
michael@0 26595 afii57686: 0x05E6,
michael@0 26596 afii57687: 0x05E7,
michael@0 26597 afii57688: 0x05E8,
michael@0 26598 afii57689: 0x05E9,
michael@0 26599 afii57690: 0x05EA,
michael@0 26600 afii57694: 0xFB2A,
michael@0 26601 afii57695: 0xFB2B,
michael@0 26602 afii57700: 0xFB4B,
michael@0 26603 afii57705: 0xFB1F,
michael@0 26604 afii57716: 0x05F0,
michael@0 26605 afii57717: 0x05F1,
michael@0 26606 afii57718: 0x05F2,
michael@0 26607 afii57723: 0xFB35,
michael@0 26608 afii57793: 0x05B4,
michael@0 26609 afii57794: 0x05B5,
michael@0 26610 afii57795: 0x05B6,
michael@0 26611 afii57796: 0x05BB,
michael@0 26612 afii57797: 0x05B8,
michael@0 26613 afii57798: 0x05B7,
michael@0 26614 afii57799: 0x05B0,
michael@0 26615 afii57800: 0x05B2,
michael@0 26616 afii57801: 0x05B1,
michael@0 26617 afii57802: 0x05B3,
michael@0 26618 afii57803: 0x05C2,
michael@0 26619 afii57804: 0x05C1,
michael@0 26620 afii57806: 0x05B9,
michael@0 26621 afii57807: 0x05BC,
michael@0 26622 afii57839: 0x05BD,
michael@0 26623 afii57841: 0x05BF,
michael@0 26624 afii57842: 0x05C0,
michael@0 26625 afii57929: 0x02BC,
michael@0 26626 afii61248: 0x2105,
michael@0 26627 afii61289: 0x2113,
michael@0 26628 afii61352: 0x2116,
michael@0 26629 afii61573: 0x202C,
michael@0 26630 afii61574: 0x202D,
michael@0 26631 afii61575: 0x202E,
michael@0 26632 afii61664: 0x200C,
michael@0 26633 afii63167: 0x066D,
michael@0 26634 afii64937: 0x02BD,
michael@0 26635 agrave: 0x00E0,
michael@0 26636 agujarati: 0x0A85,
michael@0 26637 agurmukhi: 0x0A05,
michael@0 26638 ahiragana: 0x3042,
michael@0 26639 ahookabove: 0x1EA3,
michael@0 26640 aibengali: 0x0990,
michael@0 26641 aibopomofo: 0x311E,
michael@0 26642 aideva: 0x0910,
michael@0 26643 aiecyrillic: 0x04D5,
michael@0 26644 aigujarati: 0x0A90,
michael@0 26645 aigurmukhi: 0x0A10,
michael@0 26646 aimatragurmukhi: 0x0A48,
michael@0 26647 ainarabic: 0x0639,
michael@0 26648 ainfinalarabic: 0xFECA,
michael@0 26649 aininitialarabic: 0xFECB,
michael@0 26650 ainmedialarabic: 0xFECC,
michael@0 26651 ainvertedbreve: 0x0203,
michael@0 26652 aivowelsignbengali: 0x09C8,
michael@0 26653 aivowelsigndeva: 0x0948,
michael@0 26654 aivowelsigngujarati: 0x0AC8,
michael@0 26655 akatakana: 0x30A2,
michael@0 26656 akatakanahalfwidth: 0xFF71,
michael@0 26657 akorean: 0x314F,
michael@0 26658 alef: 0x05D0,
michael@0 26659 alefarabic: 0x0627,
michael@0 26660 alefdageshhebrew: 0xFB30,
michael@0 26661 aleffinalarabic: 0xFE8E,
michael@0 26662 alefhamzaabovearabic: 0x0623,
michael@0 26663 alefhamzaabovefinalarabic: 0xFE84,
michael@0 26664 alefhamzabelowarabic: 0x0625,
michael@0 26665 alefhamzabelowfinalarabic: 0xFE88,
michael@0 26666 alefhebrew: 0x05D0,
michael@0 26667 aleflamedhebrew: 0xFB4F,
michael@0 26668 alefmaddaabovearabic: 0x0622,
michael@0 26669 alefmaddaabovefinalarabic: 0xFE82,
michael@0 26670 alefmaksuraarabic: 0x0649,
michael@0 26671 alefmaksurafinalarabic: 0xFEF0,
michael@0 26672 alefmaksurainitialarabic: 0xFEF3,
michael@0 26673 alefmaksuramedialarabic: 0xFEF4,
michael@0 26674 alefpatahhebrew: 0xFB2E,
michael@0 26675 alefqamatshebrew: 0xFB2F,
michael@0 26676 aleph: 0x2135,
michael@0 26677 allequal: 0x224C,
michael@0 26678 alpha: 0x03B1,
michael@0 26679 alphatonos: 0x03AC,
michael@0 26680 amacron: 0x0101,
michael@0 26681 amonospace: 0xFF41,
michael@0 26682 ampersand: 0x0026,
michael@0 26683 ampersandmonospace: 0xFF06,
michael@0 26684 ampersandsmall: 0xF726,
michael@0 26685 amsquare: 0x33C2,
michael@0 26686 anbopomofo: 0x3122,
michael@0 26687 angbopomofo: 0x3124,
michael@0 26688 angbracketleft: 0x3008, // This glyph is missing from Adobe's original list.
michael@0 26689 angbracketright: 0x3009, // This glyph is missing from Adobe's original list.
michael@0 26690 angkhankhuthai: 0x0E5A,
michael@0 26691 angle: 0x2220,
michael@0 26692 anglebracketleft: 0x3008,
michael@0 26693 anglebracketleftvertical: 0xFE3F,
michael@0 26694 anglebracketright: 0x3009,
michael@0 26695 anglebracketrightvertical: 0xFE40,
michael@0 26696 angleleft: 0x2329,
michael@0 26697 angleright: 0x232A,
michael@0 26698 angstrom: 0x212B,
michael@0 26699 anoteleia: 0x0387,
michael@0 26700 anudattadeva: 0x0952,
michael@0 26701 anusvarabengali: 0x0982,
michael@0 26702 anusvaradeva: 0x0902,
michael@0 26703 anusvaragujarati: 0x0A82,
michael@0 26704 aogonek: 0x0105,
michael@0 26705 apaatosquare: 0x3300,
michael@0 26706 aparen: 0x249C,
michael@0 26707 apostrophearmenian: 0x055A,
michael@0 26708 apostrophemod: 0x02BC,
michael@0 26709 apple: 0xF8FF,
michael@0 26710 approaches: 0x2250,
michael@0 26711 approxequal: 0x2248,
michael@0 26712 approxequalorimage: 0x2252,
michael@0 26713 approximatelyequal: 0x2245,
michael@0 26714 araeaekorean: 0x318E,
michael@0 26715 araeakorean: 0x318D,
michael@0 26716 arc: 0x2312,
michael@0 26717 arighthalfring: 0x1E9A,
michael@0 26718 aring: 0x00E5,
michael@0 26719 aringacute: 0x01FB,
michael@0 26720 aringbelow: 0x1E01,
michael@0 26721 arrowboth: 0x2194,
michael@0 26722 arrowdashdown: 0x21E3,
michael@0 26723 arrowdashleft: 0x21E0,
michael@0 26724 arrowdashright: 0x21E2,
michael@0 26725 arrowdashup: 0x21E1,
michael@0 26726 arrowdblboth: 0x21D4,
michael@0 26727 arrowdbldown: 0x21D3,
michael@0 26728 arrowdblleft: 0x21D0,
michael@0 26729 arrowdblright: 0x21D2,
michael@0 26730 arrowdblup: 0x21D1,
michael@0 26731 arrowdown: 0x2193,
michael@0 26732 arrowdownleft: 0x2199,
michael@0 26733 arrowdownright: 0x2198,
michael@0 26734 arrowdownwhite: 0x21E9,
michael@0 26735 arrowheaddownmod: 0x02C5,
michael@0 26736 arrowheadleftmod: 0x02C2,
michael@0 26737 arrowheadrightmod: 0x02C3,
michael@0 26738 arrowheadupmod: 0x02C4,
michael@0 26739 arrowhorizex: 0xF8E7,
michael@0 26740 arrowleft: 0x2190,
michael@0 26741 arrowleftdbl: 0x21D0,
michael@0 26742 arrowleftdblstroke: 0x21CD,
michael@0 26743 arrowleftoverright: 0x21C6,
michael@0 26744 arrowleftwhite: 0x21E6,
michael@0 26745 arrowright: 0x2192,
michael@0 26746 arrowrightdblstroke: 0x21CF,
michael@0 26747 arrowrightheavy: 0x279E,
michael@0 26748 arrowrightoverleft: 0x21C4,
michael@0 26749 arrowrightwhite: 0x21E8,
michael@0 26750 arrowtableft: 0x21E4,
michael@0 26751 arrowtabright: 0x21E5,
michael@0 26752 arrowup: 0x2191,
michael@0 26753 arrowupdn: 0x2195,
michael@0 26754 arrowupdnbse: 0x21A8,
michael@0 26755 arrowupdownbase: 0x21A8,
michael@0 26756 arrowupleft: 0x2196,
michael@0 26757 arrowupleftofdown: 0x21C5,
michael@0 26758 arrowupright: 0x2197,
michael@0 26759 arrowupwhite: 0x21E7,
michael@0 26760 arrowvertex: 0xF8E6,
michael@0 26761 asciicircum: 0x005E,
michael@0 26762 asciicircummonospace: 0xFF3E,
michael@0 26763 asciitilde: 0x007E,
michael@0 26764 asciitildemonospace: 0xFF5E,
michael@0 26765 ascript: 0x0251,
michael@0 26766 ascriptturned: 0x0252,
michael@0 26767 asmallhiragana: 0x3041,
michael@0 26768 asmallkatakana: 0x30A1,
michael@0 26769 asmallkatakanahalfwidth: 0xFF67,
michael@0 26770 asterisk: 0x002A,
michael@0 26771 asteriskaltonearabic: 0x066D,
michael@0 26772 asteriskarabic: 0x066D,
michael@0 26773 asteriskmath: 0x2217,
michael@0 26774 asteriskmonospace: 0xFF0A,
michael@0 26775 asterisksmall: 0xFE61,
michael@0 26776 asterism: 0x2042,
michael@0 26777 asuperior: 0xF6E9,
michael@0 26778 asymptoticallyequal: 0x2243,
michael@0 26779 at: 0x0040,
michael@0 26780 atilde: 0x00E3,
michael@0 26781 atmonospace: 0xFF20,
michael@0 26782 atsmall: 0xFE6B,
michael@0 26783 aturned: 0x0250,
michael@0 26784 aubengali: 0x0994,
michael@0 26785 aubopomofo: 0x3120,
michael@0 26786 audeva: 0x0914,
michael@0 26787 augujarati: 0x0A94,
michael@0 26788 augurmukhi: 0x0A14,
michael@0 26789 aulengthmarkbengali: 0x09D7,
michael@0 26790 aumatragurmukhi: 0x0A4C,
michael@0 26791 auvowelsignbengali: 0x09CC,
michael@0 26792 auvowelsigndeva: 0x094C,
michael@0 26793 auvowelsigngujarati: 0x0ACC,
michael@0 26794 avagrahadeva: 0x093D,
michael@0 26795 aybarmenian: 0x0561,
michael@0 26796 ayin: 0x05E2,
michael@0 26797 ayinaltonehebrew: 0xFB20,
michael@0 26798 ayinhebrew: 0x05E2,
michael@0 26799 b: 0x0062,
michael@0 26800 babengali: 0x09AC,
michael@0 26801 backslash: 0x005C,
michael@0 26802 backslashmonospace: 0xFF3C,
michael@0 26803 badeva: 0x092C,
michael@0 26804 bagujarati: 0x0AAC,
michael@0 26805 bagurmukhi: 0x0A2C,
michael@0 26806 bahiragana: 0x3070,
michael@0 26807 bahtthai: 0x0E3F,
michael@0 26808 bakatakana: 0x30D0,
michael@0 26809 bar: 0x007C,
michael@0 26810 barmonospace: 0xFF5C,
michael@0 26811 bbopomofo: 0x3105,
michael@0 26812 bcircle: 0x24D1,
michael@0 26813 bdotaccent: 0x1E03,
michael@0 26814 bdotbelow: 0x1E05,
michael@0 26815 beamedsixteenthnotes: 0x266C,
michael@0 26816 because: 0x2235,
michael@0 26817 becyrillic: 0x0431,
michael@0 26818 beharabic: 0x0628,
michael@0 26819 behfinalarabic: 0xFE90,
michael@0 26820 behinitialarabic: 0xFE91,
michael@0 26821 behiragana: 0x3079,
michael@0 26822 behmedialarabic: 0xFE92,
michael@0 26823 behmeeminitialarabic: 0xFC9F,
michael@0 26824 behmeemisolatedarabic: 0xFC08,
michael@0 26825 behnoonfinalarabic: 0xFC6D,
michael@0 26826 bekatakana: 0x30D9,
michael@0 26827 benarmenian: 0x0562,
michael@0 26828 bet: 0x05D1,
michael@0 26829 beta: 0x03B2,
michael@0 26830 betasymbolgreek: 0x03D0,
michael@0 26831 betdagesh: 0xFB31,
michael@0 26832 betdageshhebrew: 0xFB31,
michael@0 26833 bethebrew: 0x05D1,
michael@0 26834 betrafehebrew: 0xFB4C,
michael@0 26835 bhabengali: 0x09AD,
michael@0 26836 bhadeva: 0x092D,
michael@0 26837 bhagujarati: 0x0AAD,
michael@0 26838 bhagurmukhi: 0x0A2D,
michael@0 26839 bhook: 0x0253,
michael@0 26840 bihiragana: 0x3073,
michael@0 26841 bikatakana: 0x30D3,
michael@0 26842 bilabialclick: 0x0298,
michael@0 26843 bindigurmukhi: 0x0A02,
michael@0 26844 birusquare: 0x3331,
michael@0 26845 blackcircle: 0x25CF,
michael@0 26846 blackdiamond: 0x25C6,
michael@0 26847 blackdownpointingtriangle: 0x25BC,
michael@0 26848 blackleftpointingpointer: 0x25C4,
michael@0 26849 blackleftpointingtriangle: 0x25C0,
michael@0 26850 blacklenticularbracketleft: 0x3010,
michael@0 26851 blacklenticularbracketleftvertical: 0xFE3B,
michael@0 26852 blacklenticularbracketright: 0x3011,
michael@0 26853 blacklenticularbracketrightvertical: 0xFE3C,
michael@0 26854 blacklowerlefttriangle: 0x25E3,
michael@0 26855 blacklowerrighttriangle: 0x25E2,
michael@0 26856 blackrectangle: 0x25AC,
michael@0 26857 blackrightpointingpointer: 0x25BA,
michael@0 26858 blackrightpointingtriangle: 0x25B6,
michael@0 26859 blacksmallsquare: 0x25AA,
michael@0 26860 blacksmilingface: 0x263B,
michael@0 26861 blacksquare: 0x25A0,
michael@0 26862 blackstar: 0x2605,
michael@0 26863 blackupperlefttriangle: 0x25E4,
michael@0 26864 blackupperrighttriangle: 0x25E5,
michael@0 26865 blackuppointingsmalltriangle: 0x25B4,
michael@0 26866 blackuppointingtriangle: 0x25B2,
michael@0 26867 blank: 0x2423,
michael@0 26868 blinebelow: 0x1E07,
michael@0 26869 block: 0x2588,
michael@0 26870 bmonospace: 0xFF42,
michael@0 26871 bobaimaithai: 0x0E1A,
michael@0 26872 bohiragana: 0x307C,
michael@0 26873 bokatakana: 0x30DC,
michael@0 26874 bparen: 0x249D,
michael@0 26875 bqsquare: 0x33C3,
michael@0 26876 braceex: 0xF8F4,
michael@0 26877 braceleft: 0x007B,
michael@0 26878 braceleftbt: 0xF8F3,
michael@0 26879 braceleftmid: 0xF8F2,
michael@0 26880 braceleftmonospace: 0xFF5B,
michael@0 26881 braceleftsmall: 0xFE5B,
michael@0 26882 bracelefttp: 0xF8F1,
michael@0 26883 braceleftvertical: 0xFE37,
michael@0 26884 braceright: 0x007D,
michael@0 26885 bracerightbt: 0xF8FE,
michael@0 26886 bracerightmid: 0xF8FD,
michael@0 26887 bracerightmonospace: 0xFF5D,
michael@0 26888 bracerightsmall: 0xFE5C,
michael@0 26889 bracerighttp: 0xF8FC,
michael@0 26890 bracerightvertical: 0xFE38,
michael@0 26891 bracketleft: 0x005B,
michael@0 26892 bracketleftbt: 0xF8F0,
michael@0 26893 bracketleftex: 0xF8EF,
michael@0 26894 bracketleftmonospace: 0xFF3B,
michael@0 26895 bracketlefttp: 0xF8EE,
michael@0 26896 bracketright: 0x005D,
michael@0 26897 bracketrightbt: 0xF8FB,
michael@0 26898 bracketrightex: 0xF8FA,
michael@0 26899 bracketrightmonospace: 0xFF3D,
michael@0 26900 bracketrighttp: 0xF8F9,
michael@0 26901 breve: 0x02D8,
michael@0 26902 brevebelowcmb: 0x032E,
michael@0 26903 brevecmb: 0x0306,
michael@0 26904 breveinvertedbelowcmb: 0x032F,
michael@0 26905 breveinvertedcmb: 0x0311,
michael@0 26906 breveinverteddoublecmb: 0x0361,
michael@0 26907 bridgebelowcmb: 0x032A,
michael@0 26908 bridgeinvertedbelowcmb: 0x033A,
michael@0 26909 brokenbar: 0x00A6,
michael@0 26910 bstroke: 0x0180,
michael@0 26911 bsuperior: 0xF6EA,
michael@0 26912 btopbar: 0x0183,
michael@0 26913 buhiragana: 0x3076,
michael@0 26914 bukatakana: 0x30D6,
michael@0 26915 bullet: 0x2022,
michael@0 26916 bulletinverse: 0x25D8,
michael@0 26917 bulletoperator: 0x2219,
michael@0 26918 bullseye: 0x25CE,
michael@0 26919 c: 0x0063,
michael@0 26920 caarmenian: 0x056E,
michael@0 26921 cabengali: 0x099A,
michael@0 26922 cacute: 0x0107,
michael@0 26923 cadeva: 0x091A,
michael@0 26924 cagujarati: 0x0A9A,
michael@0 26925 cagurmukhi: 0x0A1A,
michael@0 26926 calsquare: 0x3388,
michael@0 26927 candrabindubengali: 0x0981,
michael@0 26928 candrabinducmb: 0x0310,
michael@0 26929 candrabindudeva: 0x0901,
michael@0 26930 candrabindugujarati: 0x0A81,
michael@0 26931 capslock: 0x21EA,
michael@0 26932 careof: 0x2105,
michael@0 26933 caron: 0x02C7,
michael@0 26934 caronbelowcmb: 0x032C,
michael@0 26935 caroncmb: 0x030C,
michael@0 26936 carriagereturn: 0x21B5,
michael@0 26937 cbopomofo: 0x3118,
michael@0 26938 ccaron: 0x010D,
michael@0 26939 ccedilla: 0x00E7,
michael@0 26940 ccedillaacute: 0x1E09,
michael@0 26941 ccircle: 0x24D2,
michael@0 26942 ccircumflex: 0x0109,
michael@0 26943 ccurl: 0x0255,
michael@0 26944 cdot: 0x010B,
michael@0 26945 cdotaccent: 0x010B,
michael@0 26946 cdsquare: 0x33C5,
michael@0 26947 cedilla: 0x00B8,
michael@0 26948 cedillacmb: 0x0327,
michael@0 26949 cent: 0x00A2,
michael@0 26950 centigrade: 0x2103,
michael@0 26951 centinferior: 0xF6DF,
michael@0 26952 centmonospace: 0xFFE0,
michael@0 26953 centoldstyle: 0xF7A2,
michael@0 26954 centsuperior: 0xF6E0,
michael@0 26955 chaarmenian: 0x0579,
michael@0 26956 chabengali: 0x099B,
michael@0 26957 chadeva: 0x091B,
michael@0 26958 chagujarati: 0x0A9B,
michael@0 26959 chagurmukhi: 0x0A1B,
michael@0 26960 chbopomofo: 0x3114,
michael@0 26961 cheabkhasiancyrillic: 0x04BD,
michael@0 26962 checkmark: 0x2713,
michael@0 26963 checyrillic: 0x0447,
michael@0 26964 chedescenderabkhasiancyrillic: 0x04BF,
michael@0 26965 chedescendercyrillic: 0x04B7,
michael@0 26966 chedieresiscyrillic: 0x04F5,
michael@0 26967 cheharmenian: 0x0573,
michael@0 26968 chekhakassiancyrillic: 0x04CC,
michael@0 26969 cheverticalstrokecyrillic: 0x04B9,
michael@0 26970 chi: 0x03C7,
michael@0 26971 chieuchacirclekorean: 0x3277,
michael@0 26972 chieuchaparenkorean: 0x3217,
michael@0 26973 chieuchcirclekorean: 0x3269,
michael@0 26974 chieuchkorean: 0x314A,
michael@0 26975 chieuchparenkorean: 0x3209,
michael@0 26976 chochangthai: 0x0E0A,
michael@0 26977 chochanthai: 0x0E08,
michael@0 26978 chochingthai: 0x0E09,
michael@0 26979 chochoethai: 0x0E0C,
michael@0 26980 chook: 0x0188,
michael@0 26981 cieucacirclekorean: 0x3276,
michael@0 26982 cieucaparenkorean: 0x3216,
michael@0 26983 cieuccirclekorean: 0x3268,
michael@0 26984 cieuckorean: 0x3148,
michael@0 26985 cieucparenkorean: 0x3208,
michael@0 26986 cieucuparenkorean: 0x321C,
michael@0 26987 circle: 0x25CB,
michael@0 26988 circlecopyrt: 0x00A9, // This glyph is missing from Adobe's original list.
michael@0 26989 circlemultiply: 0x2297,
michael@0 26990 circleot: 0x2299,
michael@0 26991 circleplus: 0x2295,
michael@0 26992 circlepostalmark: 0x3036,
michael@0 26993 circlewithlefthalfblack: 0x25D0,
michael@0 26994 circlewithrighthalfblack: 0x25D1,
michael@0 26995 circumflex: 0x02C6,
michael@0 26996 circumflexbelowcmb: 0x032D,
michael@0 26997 circumflexcmb: 0x0302,
michael@0 26998 clear: 0x2327,
michael@0 26999 clickalveolar: 0x01C2,
michael@0 27000 clickdental: 0x01C0,
michael@0 27001 clicklateral: 0x01C1,
michael@0 27002 clickretroflex: 0x01C3,
michael@0 27003 club: 0x2663,
michael@0 27004 clubsuitblack: 0x2663,
michael@0 27005 clubsuitwhite: 0x2667,
michael@0 27006 cmcubedsquare: 0x33A4,
michael@0 27007 cmonospace: 0xFF43,
michael@0 27008 cmsquaredsquare: 0x33A0,
michael@0 27009 coarmenian: 0x0581,
michael@0 27010 colon: 0x003A,
michael@0 27011 colonmonetary: 0x20A1,
michael@0 27012 colonmonospace: 0xFF1A,
michael@0 27013 colonsign: 0x20A1,
michael@0 27014 colonsmall: 0xFE55,
michael@0 27015 colontriangularhalfmod: 0x02D1,
michael@0 27016 colontriangularmod: 0x02D0,
michael@0 27017 comma: 0x002C,
michael@0 27018 commaabovecmb: 0x0313,
michael@0 27019 commaaboverightcmb: 0x0315,
michael@0 27020 commaaccent: 0xF6C3,
michael@0 27021 commaarabic: 0x060C,
michael@0 27022 commaarmenian: 0x055D,
michael@0 27023 commainferior: 0xF6E1,
michael@0 27024 commamonospace: 0xFF0C,
michael@0 27025 commareversedabovecmb: 0x0314,
michael@0 27026 commareversedmod: 0x02BD,
michael@0 27027 commasmall: 0xFE50,
michael@0 27028 commasuperior: 0xF6E2,
michael@0 27029 commaturnedabovecmb: 0x0312,
michael@0 27030 commaturnedmod: 0x02BB,
michael@0 27031 compass: 0x263C,
michael@0 27032 congruent: 0x2245,
michael@0 27033 contourintegral: 0x222E,
michael@0 27034 control: 0x2303,
michael@0 27035 controlACK: 0x0006,
michael@0 27036 controlBEL: 0x0007,
michael@0 27037 controlBS: 0x0008,
michael@0 27038 controlCAN: 0x0018,
michael@0 27039 controlCR: 0x000D,
michael@0 27040 controlDC1: 0x0011,
michael@0 27041 controlDC2: 0x0012,
michael@0 27042 controlDC3: 0x0013,
michael@0 27043 controlDC4: 0x0014,
michael@0 27044 controlDEL: 0x007F,
michael@0 27045 controlDLE: 0x0010,
michael@0 27046 controlEM: 0x0019,
michael@0 27047 controlENQ: 0x0005,
michael@0 27048 controlEOT: 0x0004,
michael@0 27049 controlESC: 0x001B,
michael@0 27050 controlETB: 0x0017,
michael@0 27051 controlETX: 0x0003,
michael@0 27052 controlFF: 0x000C,
michael@0 27053 controlFS: 0x001C,
michael@0 27054 controlGS: 0x001D,
michael@0 27055 controlHT: 0x0009,
michael@0 27056 controlLF: 0x000A,
michael@0 27057 controlNAK: 0x0015,
michael@0 27058 controlRS: 0x001E,
michael@0 27059 controlSI: 0x000F,
michael@0 27060 controlSO: 0x000E,
michael@0 27061 controlSOT: 0x0002,
michael@0 27062 controlSTX: 0x0001,
michael@0 27063 controlSUB: 0x001A,
michael@0 27064 controlSYN: 0x0016,
michael@0 27065 controlUS: 0x001F,
michael@0 27066 controlVT: 0x000B,
michael@0 27067 copyright: 0x00A9,
michael@0 27068 copyrightsans: 0xF8E9,
michael@0 27069 copyrightserif: 0xF6D9,
michael@0 27070 cornerbracketleft: 0x300C,
michael@0 27071 cornerbracketlefthalfwidth: 0xFF62,
michael@0 27072 cornerbracketleftvertical: 0xFE41,
michael@0 27073 cornerbracketright: 0x300D,
michael@0 27074 cornerbracketrighthalfwidth: 0xFF63,
michael@0 27075 cornerbracketrightvertical: 0xFE42,
michael@0 27076 corporationsquare: 0x337F,
michael@0 27077 cosquare: 0x33C7,
michael@0 27078 coverkgsquare: 0x33C6,
michael@0 27079 cparen: 0x249E,
michael@0 27080 cruzeiro: 0x20A2,
michael@0 27081 cstretched: 0x0297,
michael@0 27082 curlyand: 0x22CF,
michael@0 27083 curlyor: 0x22CE,
michael@0 27084 currency: 0x00A4,
michael@0 27085 cyrBreve: 0xF6D1,
michael@0 27086 cyrFlex: 0xF6D2,
michael@0 27087 cyrbreve: 0xF6D4,
michael@0 27088 cyrflex: 0xF6D5,
michael@0 27089 d: 0x0064,
michael@0 27090 daarmenian: 0x0564,
michael@0 27091 dabengali: 0x09A6,
michael@0 27092 dadarabic: 0x0636,
michael@0 27093 dadeva: 0x0926,
michael@0 27094 dadfinalarabic: 0xFEBE,
michael@0 27095 dadinitialarabic: 0xFEBF,
michael@0 27096 dadmedialarabic: 0xFEC0,
michael@0 27097 dagesh: 0x05BC,
michael@0 27098 dageshhebrew: 0x05BC,
michael@0 27099 dagger: 0x2020,
michael@0 27100 daggerdbl: 0x2021,
michael@0 27101 dagujarati: 0x0AA6,
michael@0 27102 dagurmukhi: 0x0A26,
michael@0 27103 dahiragana: 0x3060,
michael@0 27104 dakatakana: 0x30C0,
michael@0 27105 dalarabic: 0x062F,
michael@0 27106 dalet: 0x05D3,
michael@0 27107 daletdagesh: 0xFB33,
michael@0 27108 daletdageshhebrew: 0xFB33,
michael@0 27109 dalethebrew: 0x05D3,
michael@0 27110 dalfinalarabic: 0xFEAA,
michael@0 27111 dammaarabic: 0x064F,
michael@0 27112 dammalowarabic: 0x064F,
michael@0 27113 dammatanaltonearabic: 0x064C,
michael@0 27114 dammatanarabic: 0x064C,
michael@0 27115 danda: 0x0964,
michael@0 27116 dargahebrew: 0x05A7,
michael@0 27117 dargalefthebrew: 0x05A7,
michael@0 27118 dasiapneumatacyrilliccmb: 0x0485,
michael@0 27119 dblGrave: 0xF6D3,
michael@0 27120 dblanglebracketleft: 0x300A,
michael@0 27121 dblanglebracketleftvertical: 0xFE3D,
michael@0 27122 dblanglebracketright: 0x300B,
michael@0 27123 dblanglebracketrightvertical: 0xFE3E,
michael@0 27124 dblarchinvertedbelowcmb: 0x032B,
michael@0 27125 dblarrowleft: 0x21D4,
michael@0 27126 dblarrowright: 0x21D2,
michael@0 27127 dbldanda: 0x0965,
michael@0 27128 dblgrave: 0xF6D6,
michael@0 27129 dblgravecmb: 0x030F,
michael@0 27130 dblintegral: 0x222C,
michael@0 27131 dbllowline: 0x2017,
michael@0 27132 dbllowlinecmb: 0x0333,
michael@0 27133 dbloverlinecmb: 0x033F,
michael@0 27134 dblprimemod: 0x02BA,
michael@0 27135 dblverticalbar: 0x2016,
michael@0 27136 dblverticallineabovecmb: 0x030E,
michael@0 27137 dbopomofo: 0x3109,
michael@0 27138 dbsquare: 0x33C8,
michael@0 27139 dcaron: 0x010F,
michael@0 27140 dcedilla: 0x1E11,
michael@0 27141 dcircle: 0x24D3,
michael@0 27142 dcircumflexbelow: 0x1E13,
michael@0 27143 dcroat: 0x0111,
michael@0 27144 ddabengali: 0x09A1,
michael@0 27145 ddadeva: 0x0921,
michael@0 27146 ddagujarati: 0x0AA1,
michael@0 27147 ddagurmukhi: 0x0A21,
michael@0 27148 ddalarabic: 0x0688,
michael@0 27149 ddalfinalarabic: 0xFB89,
michael@0 27150 dddhadeva: 0x095C,
michael@0 27151 ddhabengali: 0x09A2,
michael@0 27152 ddhadeva: 0x0922,
michael@0 27153 ddhagujarati: 0x0AA2,
michael@0 27154 ddhagurmukhi: 0x0A22,
michael@0 27155 ddotaccent: 0x1E0B,
michael@0 27156 ddotbelow: 0x1E0D,
michael@0 27157 decimalseparatorarabic: 0x066B,
michael@0 27158 decimalseparatorpersian: 0x066B,
michael@0 27159 decyrillic: 0x0434,
michael@0 27160 degree: 0x00B0,
michael@0 27161 dehihebrew: 0x05AD,
michael@0 27162 dehiragana: 0x3067,
michael@0 27163 deicoptic: 0x03EF,
michael@0 27164 dekatakana: 0x30C7,
michael@0 27165 deleteleft: 0x232B,
michael@0 27166 deleteright: 0x2326,
michael@0 27167 delta: 0x03B4,
michael@0 27168 deltaturned: 0x018D,
michael@0 27169 denominatorminusonenumeratorbengali: 0x09F8,
michael@0 27170 dezh: 0x02A4,
michael@0 27171 dhabengali: 0x09A7,
michael@0 27172 dhadeva: 0x0927,
michael@0 27173 dhagujarati: 0x0AA7,
michael@0 27174 dhagurmukhi: 0x0A27,
michael@0 27175 dhook: 0x0257,
michael@0 27176 dialytikatonos: 0x0385,
michael@0 27177 dialytikatonoscmb: 0x0344,
michael@0 27178 diamond: 0x2666,
michael@0 27179 diamondsuitwhite: 0x2662,
michael@0 27180 dieresis: 0x00A8,
michael@0 27181 dieresisacute: 0xF6D7,
michael@0 27182 dieresisbelowcmb: 0x0324,
michael@0 27183 dieresiscmb: 0x0308,
michael@0 27184 dieresisgrave: 0xF6D8,
michael@0 27185 dieresistonos: 0x0385,
michael@0 27186 dihiragana: 0x3062,
michael@0 27187 dikatakana: 0x30C2,
michael@0 27188 dittomark: 0x3003,
michael@0 27189 divide: 0x00F7,
michael@0 27190 divides: 0x2223,
michael@0 27191 divisionslash: 0x2215,
michael@0 27192 djecyrillic: 0x0452,
michael@0 27193 dkshade: 0x2593,
michael@0 27194 dlinebelow: 0x1E0F,
michael@0 27195 dlsquare: 0x3397,
michael@0 27196 dmacron: 0x0111,
michael@0 27197 dmonospace: 0xFF44,
michael@0 27198 dnblock: 0x2584,
michael@0 27199 dochadathai: 0x0E0E,
michael@0 27200 dodekthai: 0x0E14,
michael@0 27201 dohiragana: 0x3069,
michael@0 27202 dokatakana: 0x30C9,
michael@0 27203 dollar: 0x0024,
michael@0 27204 dollarinferior: 0xF6E3,
michael@0 27205 dollarmonospace: 0xFF04,
michael@0 27206 dollaroldstyle: 0xF724,
michael@0 27207 dollarsmall: 0xFE69,
michael@0 27208 dollarsuperior: 0xF6E4,
michael@0 27209 dong: 0x20AB,
michael@0 27210 dorusquare: 0x3326,
michael@0 27211 dotaccent: 0x02D9,
michael@0 27212 dotaccentcmb: 0x0307,
michael@0 27213 dotbelowcmb: 0x0323,
michael@0 27214 dotbelowcomb: 0x0323,
michael@0 27215 dotkatakana: 0x30FB,
michael@0 27216 dotlessi: 0x0131,
michael@0 27217 dotlessj: 0xF6BE,
michael@0 27218 dotlessjstrokehook: 0x0284,
michael@0 27219 dotmath: 0x22C5,
michael@0 27220 dottedcircle: 0x25CC,
michael@0 27221 doubleyodpatah: 0xFB1F,
michael@0 27222 doubleyodpatahhebrew: 0xFB1F,
michael@0 27223 downtackbelowcmb: 0x031E,
michael@0 27224 downtackmod: 0x02D5,
michael@0 27225 dparen: 0x249F,
michael@0 27226 dsuperior: 0xF6EB,
michael@0 27227 dtail: 0x0256,
michael@0 27228 dtopbar: 0x018C,
michael@0 27229 duhiragana: 0x3065,
michael@0 27230 dukatakana: 0x30C5,
michael@0 27231 dz: 0x01F3,
michael@0 27232 dzaltone: 0x02A3,
michael@0 27233 dzcaron: 0x01C6,
michael@0 27234 dzcurl: 0x02A5,
michael@0 27235 dzeabkhasiancyrillic: 0x04E1,
michael@0 27236 dzecyrillic: 0x0455,
michael@0 27237 dzhecyrillic: 0x045F,
michael@0 27238 e: 0x0065,
michael@0 27239 eacute: 0x00E9,
michael@0 27240 earth: 0x2641,
michael@0 27241 ebengali: 0x098F,
michael@0 27242 ebopomofo: 0x311C,
michael@0 27243 ebreve: 0x0115,
michael@0 27244 ecandradeva: 0x090D,
michael@0 27245 ecandragujarati: 0x0A8D,
michael@0 27246 ecandravowelsigndeva: 0x0945,
michael@0 27247 ecandravowelsigngujarati: 0x0AC5,
michael@0 27248 ecaron: 0x011B,
michael@0 27249 ecedillabreve: 0x1E1D,
michael@0 27250 echarmenian: 0x0565,
michael@0 27251 echyiwnarmenian: 0x0587,
michael@0 27252 ecircle: 0x24D4,
michael@0 27253 ecircumflex: 0x00EA,
michael@0 27254 ecircumflexacute: 0x1EBF,
michael@0 27255 ecircumflexbelow: 0x1E19,
michael@0 27256 ecircumflexdotbelow: 0x1EC7,
michael@0 27257 ecircumflexgrave: 0x1EC1,
michael@0 27258 ecircumflexhookabove: 0x1EC3,
michael@0 27259 ecircumflextilde: 0x1EC5,
michael@0 27260 ecyrillic: 0x0454,
michael@0 27261 edblgrave: 0x0205,
michael@0 27262 edeva: 0x090F,
michael@0 27263 edieresis: 0x00EB,
michael@0 27264 edot: 0x0117,
michael@0 27265 edotaccent: 0x0117,
michael@0 27266 edotbelow: 0x1EB9,
michael@0 27267 eegurmukhi: 0x0A0F,
michael@0 27268 eematragurmukhi: 0x0A47,
michael@0 27269 efcyrillic: 0x0444,
michael@0 27270 egrave: 0x00E8,
michael@0 27271 egujarati: 0x0A8F,
michael@0 27272 eharmenian: 0x0567,
michael@0 27273 ehbopomofo: 0x311D,
michael@0 27274 ehiragana: 0x3048,
michael@0 27275 ehookabove: 0x1EBB,
michael@0 27276 eibopomofo: 0x311F,
michael@0 27277 eight: 0x0038,
michael@0 27278 eightarabic: 0x0668,
michael@0 27279 eightbengali: 0x09EE,
michael@0 27280 eightcircle: 0x2467,
michael@0 27281 eightcircleinversesansserif: 0x2791,
michael@0 27282 eightdeva: 0x096E,
michael@0 27283 eighteencircle: 0x2471,
michael@0 27284 eighteenparen: 0x2485,
michael@0 27285 eighteenperiod: 0x2499,
michael@0 27286 eightgujarati: 0x0AEE,
michael@0 27287 eightgurmukhi: 0x0A6E,
michael@0 27288 eighthackarabic: 0x0668,
michael@0 27289 eighthangzhou: 0x3028,
michael@0 27290 eighthnotebeamed: 0x266B,
michael@0 27291 eightideographicparen: 0x3227,
michael@0 27292 eightinferior: 0x2088,
michael@0 27293 eightmonospace: 0xFF18,
michael@0 27294 eightoldstyle: 0xF738,
michael@0 27295 eightparen: 0x247B,
michael@0 27296 eightperiod: 0x248F,
michael@0 27297 eightpersian: 0x06F8,
michael@0 27298 eightroman: 0x2177,
michael@0 27299 eightsuperior: 0x2078,
michael@0 27300 eightthai: 0x0E58,
michael@0 27301 einvertedbreve: 0x0207,
michael@0 27302 eiotifiedcyrillic: 0x0465,
michael@0 27303 ekatakana: 0x30A8,
michael@0 27304 ekatakanahalfwidth: 0xFF74,
michael@0 27305 ekonkargurmukhi: 0x0A74,
michael@0 27306 ekorean: 0x3154,
michael@0 27307 elcyrillic: 0x043B,
michael@0 27308 element: 0x2208,
michael@0 27309 elevencircle: 0x246A,
michael@0 27310 elevenparen: 0x247E,
michael@0 27311 elevenperiod: 0x2492,
michael@0 27312 elevenroman: 0x217A,
michael@0 27313 ellipsis: 0x2026,
michael@0 27314 ellipsisvertical: 0x22EE,
michael@0 27315 emacron: 0x0113,
michael@0 27316 emacronacute: 0x1E17,
michael@0 27317 emacrongrave: 0x1E15,
michael@0 27318 emcyrillic: 0x043C,
michael@0 27319 emdash: 0x2014,
michael@0 27320 emdashvertical: 0xFE31,
michael@0 27321 emonospace: 0xFF45,
michael@0 27322 emphasismarkarmenian: 0x055B,
michael@0 27323 emptyset: 0x2205,
michael@0 27324 enbopomofo: 0x3123,
michael@0 27325 encyrillic: 0x043D,
michael@0 27326 endash: 0x2013,
michael@0 27327 endashvertical: 0xFE32,
michael@0 27328 endescendercyrillic: 0x04A3,
michael@0 27329 eng: 0x014B,
michael@0 27330 engbopomofo: 0x3125,
michael@0 27331 enghecyrillic: 0x04A5,
michael@0 27332 enhookcyrillic: 0x04C8,
michael@0 27333 enspace: 0x2002,
michael@0 27334 eogonek: 0x0119,
michael@0 27335 eokorean: 0x3153,
michael@0 27336 eopen: 0x025B,
michael@0 27337 eopenclosed: 0x029A,
michael@0 27338 eopenreversed: 0x025C,
michael@0 27339 eopenreversedclosed: 0x025E,
michael@0 27340 eopenreversedhook: 0x025D,
michael@0 27341 eparen: 0x24A0,
michael@0 27342 epsilon: 0x03B5,
michael@0 27343 epsilontonos: 0x03AD,
michael@0 27344 equal: 0x003D,
michael@0 27345 equalmonospace: 0xFF1D,
michael@0 27346 equalsmall: 0xFE66,
michael@0 27347 equalsuperior: 0x207C,
michael@0 27348 equivalence: 0x2261,
michael@0 27349 erbopomofo: 0x3126,
michael@0 27350 ercyrillic: 0x0440,
michael@0 27351 ereversed: 0x0258,
michael@0 27352 ereversedcyrillic: 0x044D,
michael@0 27353 escyrillic: 0x0441,
michael@0 27354 esdescendercyrillic: 0x04AB,
michael@0 27355 esh: 0x0283,
michael@0 27356 eshcurl: 0x0286,
michael@0 27357 eshortdeva: 0x090E,
michael@0 27358 eshortvowelsigndeva: 0x0946,
michael@0 27359 eshreversedloop: 0x01AA,
michael@0 27360 eshsquatreversed: 0x0285,
michael@0 27361 esmallhiragana: 0x3047,
michael@0 27362 esmallkatakana: 0x30A7,
michael@0 27363 esmallkatakanahalfwidth: 0xFF6A,
michael@0 27364 estimated: 0x212E,
michael@0 27365 esuperior: 0xF6EC,
michael@0 27366 eta: 0x03B7,
michael@0 27367 etarmenian: 0x0568,
michael@0 27368 etatonos: 0x03AE,
michael@0 27369 eth: 0x00F0,
michael@0 27370 etilde: 0x1EBD,
michael@0 27371 etildebelow: 0x1E1B,
michael@0 27372 etnahtafoukhhebrew: 0x0591,
michael@0 27373 etnahtafoukhlefthebrew: 0x0591,
michael@0 27374 etnahtahebrew: 0x0591,
michael@0 27375 etnahtalefthebrew: 0x0591,
michael@0 27376 eturned: 0x01DD,
michael@0 27377 eukorean: 0x3161,
michael@0 27378 euro: 0x20AC,
michael@0 27379 evowelsignbengali: 0x09C7,
michael@0 27380 evowelsigndeva: 0x0947,
michael@0 27381 evowelsigngujarati: 0x0AC7,
michael@0 27382 exclam: 0x0021,
michael@0 27383 exclamarmenian: 0x055C,
michael@0 27384 exclamdbl: 0x203C,
michael@0 27385 exclamdown: 0x00A1,
michael@0 27386 exclamdownsmall: 0xF7A1,
michael@0 27387 exclammonospace: 0xFF01,
michael@0 27388 exclamsmall: 0xF721,
michael@0 27389 existential: 0x2203,
michael@0 27390 ezh: 0x0292,
michael@0 27391 ezhcaron: 0x01EF,
michael@0 27392 ezhcurl: 0x0293,
michael@0 27393 ezhreversed: 0x01B9,
michael@0 27394 ezhtail: 0x01BA,
michael@0 27395 f: 0x0066,
michael@0 27396 fadeva: 0x095E,
michael@0 27397 fagurmukhi: 0x0A5E,
michael@0 27398 fahrenheit: 0x2109,
michael@0 27399 fathaarabic: 0x064E,
michael@0 27400 fathalowarabic: 0x064E,
michael@0 27401 fathatanarabic: 0x064B,
michael@0 27402 fbopomofo: 0x3108,
michael@0 27403 fcircle: 0x24D5,
michael@0 27404 fdotaccent: 0x1E1F,
michael@0 27405 feharabic: 0x0641,
michael@0 27406 feharmenian: 0x0586,
michael@0 27407 fehfinalarabic: 0xFED2,
michael@0 27408 fehinitialarabic: 0xFED3,
michael@0 27409 fehmedialarabic: 0xFED4,
michael@0 27410 feicoptic: 0x03E5,
michael@0 27411 female: 0x2640,
michael@0 27412 ff: 0xFB00,
michael@0 27413 ffi: 0xFB03,
michael@0 27414 ffl: 0xFB04,
michael@0 27415 fi: 0xFB01,
michael@0 27416 fifteencircle: 0x246E,
michael@0 27417 fifteenparen: 0x2482,
michael@0 27418 fifteenperiod: 0x2496,
michael@0 27419 figuredash: 0x2012,
michael@0 27420 filledbox: 0x25A0,
michael@0 27421 filledrect: 0x25AC,
michael@0 27422 finalkaf: 0x05DA,
michael@0 27423 finalkafdagesh: 0xFB3A,
michael@0 27424 finalkafdageshhebrew: 0xFB3A,
michael@0 27425 finalkafhebrew: 0x05DA,
michael@0 27426 finalmem: 0x05DD,
michael@0 27427 finalmemhebrew: 0x05DD,
michael@0 27428 finalnun: 0x05DF,
michael@0 27429 finalnunhebrew: 0x05DF,
michael@0 27430 finalpe: 0x05E3,
michael@0 27431 finalpehebrew: 0x05E3,
michael@0 27432 finaltsadi: 0x05E5,
michael@0 27433 finaltsadihebrew: 0x05E5,
michael@0 27434 firsttonechinese: 0x02C9,
michael@0 27435 fisheye: 0x25C9,
michael@0 27436 fitacyrillic: 0x0473,
michael@0 27437 five: 0x0035,
michael@0 27438 fivearabic: 0x0665,
michael@0 27439 fivebengali: 0x09EB,
michael@0 27440 fivecircle: 0x2464,
michael@0 27441 fivecircleinversesansserif: 0x278E,
michael@0 27442 fivedeva: 0x096B,
michael@0 27443 fiveeighths: 0x215D,
michael@0 27444 fivegujarati: 0x0AEB,
michael@0 27445 fivegurmukhi: 0x0A6B,
michael@0 27446 fivehackarabic: 0x0665,
michael@0 27447 fivehangzhou: 0x3025,
michael@0 27448 fiveideographicparen: 0x3224,
michael@0 27449 fiveinferior: 0x2085,
michael@0 27450 fivemonospace: 0xFF15,
michael@0 27451 fiveoldstyle: 0xF735,
michael@0 27452 fiveparen: 0x2478,
michael@0 27453 fiveperiod: 0x248C,
michael@0 27454 fivepersian: 0x06F5,
michael@0 27455 fiveroman: 0x2174,
michael@0 27456 fivesuperior: 0x2075,
michael@0 27457 fivethai: 0x0E55,
michael@0 27458 fl: 0xFB02,
michael@0 27459 florin: 0x0192,
michael@0 27460 fmonospace: 0xFF46,
michael@0 27461 fmsquare: 0x3399,
michael@0 27462 fofanthai: 0x0E1F,
michael@0 27463 fofathai: 0x0E1D,
michael@0 27464 fongmanthai: 0x0E4F,
michael@0 27465 forall: 0x2200,
michael@0 27466 four: 0x0034,
michael@0 27467 fourarabic: 0x0664,
michael@0 27468 fourbengali: 0x09EA,
michael@0 27469 fourcircle: 0x2463,
michael@0 27470 fourcircleinversesansserif: 0x278D,
michael@0 27471 fourdeva: 0x096A,
michael@0 27472 fourgujarati: 0x0AEA,
michael@0 27473 fourgurmukhi: 0x0A6A,
michael@0 27474 fourhackarabic: 0x0664,
michael@0 27475 fourhangzhou: 0x3024,
michael@0 27476 fourideographicparen: 0x3223,
michael@0 27477 fourinferior: 0x2084,
michael@0 27478 fourmonospace: 0xFF14,
michael@0 27479 fournumeratorbengali: 0x09F7,
michael@0 27480 fouroldstyle: 0xF734,
michael@0 27481 fourparen: 0x2477,
michael@0 27482 fourperiod: 0x248B,
michael@0 27483 fourpersian: 0x06F4,
michael@0 27484 fourroman: 0x2173,
michael@0 27485 foursuperior: 0x2074,
michael@0 27486 fourteencircle: 0x246D,
michael@0 27487 fourteenparen: 0x2481,
michael@0 27488 fourteenperiod: 0x2495,
michael@0 27489 fourthai: 0x0E54,
michael@0 27490 fourthtonechinese: 0x02CB,
michael@0 27491 fparen: 0x24A1,
michael@0 27492 fraction: 0x2044,
michael@0 27493 franc: 0x20A3,
michael@0 27494 g: 0x0067,
michael@0 27495 gabengali: 0x0997,
michael@0 27496 gacute: 0x01F5,
michael@0 27497 gadeva: 0x0917,
michael@0 27498 gafarabic: 0x06AF,
michael@0 27499 gaffinalarabic: 0xFB93,
michael@0 27500 gafinitialarabic: 0xFB94,
michael@0 27501 gafmedialarabic: 0xFB95,
michael@0 27502 gagujarati: 0x0A97,
michael@0 27503 gagurmukhi: 0x0A17,
michael@0 27504 gahiragana: 0x304C,
michael@0 27505 gakatakana: 0x30AC,
michael@0 27506 gamma: 0x03B3,
michael@0 27507 gammalatinsmall: 0x0263,
michael@0 27508 gammasuperior: 0x02E0,
michael@0 27509 gangiacoptic: 0x03EB,
michael@0 27510 gbopomofo: 0x310D,
michael@0 27511 gbreve: 0x011F,
michael@0 27512 gcaron: 0x01E7,
michael@0 27513 gcedilla: 0x0123,
michael@0 27514 gcircle: 0x24D6,
michael@0 27515 gcircumflex: 0x011D,
michael@0 27516 gcommaaccent: 0x0123,
michael@0 27517 gdot: 0x0121,
michael@0 27518 gdotaccent: 0x0121,
michael@0 27519 gecyrillic: 0x0433,
michael@0 27520 gehiragana: 0x3052,
michael@0 27521 gekatakana: 0x30B2,
michael@0 27522 geometricallyequal: 0x2251,
michael@0 27523 gereshaccenthebrew: 0x059C,
michael@0 27524 gereshhebrew: 0x05F3,
michael@0 27525 gereshmuqdamhebrew: 0x059D,
michael@0 27526 germandbls: 0x00DF,
michael@0 27527 gershayimaccenthebrew: 0x059E,
michael@0 27528 gershayimhebrew: 0x05F4,
michael@0 27529 getamark: 0x3013,
michael@0 27530 ghabengali: 0x0998,
michael@0 27531 ghadarmenian: 0x0572,
michael@0 27532 ghadeva: 0x0918,
michael@0 27533 ghagujarati: 0x0A98,
michael@0 27534 ghagurmukhi: 0x0A18,
michael@0 27535 ghainarabic: 0x063A,
michael@0 27536 ghainfinalarabic: 0xFECE,
michael@0 27537 ghaininitialarabic: 0xFECF,
michael@0 27538 ghainmedialarabic: 0xFED0,
michael@0 27539 ghemiddlehookcyrillic: 0x0495,
michael@0 27540 ghestrokecyrillic: 0x0493,
michael@0 27541 gheupturncyrillic: 0x0491,
michael@0 27542 ghhadeva: 0x095A,
michael@0 27543 ghhagurmukhi: 0x0A5A,
michael@0 27544 ghook: 0x0260,
michael@0 27545 ghzsquare: 0x3393,
michael@0 27546 gihiragana: 0x304E,
michael@0 27547 gikatakana: 0x30AE,
michael@0 27548 gimarmenian: 0x0563,
michael@0 27549 gimel: 0x05D2,
michael@0 27550 gimeldagesh: 0xFB32,
michael@0 27551 gimeldageshhebrew: 0xFB32,
michael@0 27552 gimelhebrew: 0x05D2,
michael@0 27553 gjecyrillic: 0x0453,
michael@0 27554 glottalinvertedstroke: 0x01BE,
michael@0 27555 glottalstop: 0x0294,
michael@0 27556 glottalstopinverted: 0x0296,
michael@0 27557 glottalstopmod: 0x02C0,
michael@0 27558 glottalstopreversed: 0x0295,
michael@0 27559 glottalstopreversedmod: 0x02C1,
michael@0 27560 glottalstopreversedsuperior: 0x02E4,
michael@0 27561 glottalstopstroke: 0x02A1,
michael@0 27562 glottalstopstrokereversed: 0x02A2,
michael@0 27563 gmacron: 0x1E21,
michael@0 27564 gmonospace: 0xFF47,
michael@0 27565 gohiragana: 0x3054,
michael@0 27566 gokatakana: 0x30B4,
michael@0 27567 gparen: 0x24A2,
michael@0 27568 gpasquare: 0x33AC,
michael@0 27569 gradient: 0x2207,
michael@0 27570 grave: 0x0060,
michael@0 27571 gravebelowcmb: 0x0316,
michael@0 27572 gravecmb: 0x0300,
michael@0 27573 gravecomb: 0x0300,
michael@0 27574 gravedeva: 0x0953,
michael@0 27575 gravelowmod: 0x02CE,
michael@0 27576 gravemonospace: 0xFF40,
michael@0 27577 gravetonecmb: 0x0340,
michael@0 27578 greater: 0x003E,
michael@0 27579 greaterequal: 0x2265,
michael@0 27580 greaterequalorless: 0x22DB,
michael@0 27581 greatermonospace: 0xFF1E,
michael@0 27582 greaterorequivalent: 0x2273,
michael@0 27583 greaterorless: 0x2277,
michael@0 27584 greateroverequal: 0x2267,
michael@0 27585 greatersmall: 0xFE65,
michael@0 27586 gscript: 0x0261,
michael@0 27587 gstroke: 0x01E5,
michael@0 27588 guhiragana: 0x3050,
michael@0 27589 guillemotleft: 0x00AB,
michael@0 27590 guillemotright: 0x00BB,
michael@0 27591 guilsinglleft: 0x2039,
michael@0 27592 guilsinglright: 0x203A,
michael@0 27593 gukatakana: 0x30B0,
michael@0 27594 guramusquare: 0x3318,
michael@0 27595 gysquare: 0x33C9,
michael@0 27596 h: 0x0068,
michael@0 27597 haabkhasiancyrillic: 0x04A9,
michael@0 27598 haaltonearabic: 0x06C1,
michael@0 27599 habengali: 0x09B9,
michael@0 27600 hadescendercyrillic: 0x04B3,
michael@0 27601 hadeva: 0x0939,
michael@0 27602 hagujarati: 0x0AB9,
michael@0 27603 hagurmukhi: 0x0A39,
michael@0 27604 haharabic: 0x062D,
michael@0 27605 hahfinalarabic: 0xFEA2,
michael@0 27606 hahinitialarabic: 0xFEA3,
michael@0 27607 hahiragana: 0x306F,
michael@0 27608 hahmedialarabic: 0xFEA4,
michael@0 27609 haitusquare: 0x332A,
michael@0 27610 hakatakana: 0x30CF,
michael@0 27611 hakatakanahalfwidth: 0xFF8A,
michael@0 27612 halantgurmukhi: 0x0A4D,
michael@0 27613 hamzaarabic: 0x0621,
michael@0 27614 hamzalowarabic: 0x0621,
michael@0 27615 hangulfiller: 0x3164,
michael@0 27616 hardsigncyrillic: 0x044A,
michael@0 27617 harpoonleftbarbup: 0x21BC,
michael@0 27618 harpoonrightbarbup: 0x21C0,
michael@0 27619 hasquare: 0x33CA,
michael@0 27620 hatafpatah: 0x05B2,
michael@0 27621 hatafpatah16: 0x05B2,
michael@0 27622 hatafpatah23: 0x05B2,
michael@0 27623 hatafpatah2f: 0x05B2,
michael@0 27624 hatafpatahhebrew: 0x05B2,
michael@0 27625 hatafpatahnarrowhebrew: 0x05B2,
michael@0 27626 hatafpatahquarterhebrew: 0x05B2,
michael@0 27627 hatafpatahwidehebrew: 0x05B2,
michael@0 27628 hatafqamats: 0x05B3,
michael@0 27629 hatafqamats1b: 0x05B3,
michael@0 27630 hatafqamats28: 0x05B3,
michael@0 27631 hatafqamats34: 0x05B3,
michael@0 27632 hatafqamatshebrew: 0x05B3,
michael@0 27633 hatafqamatsnarrowhebrew: 0x05B3,
michael@0 27634 hatafqamatsquarterhebrew: 0x05B3,
michael@0 27635 hatafqamatswidehebrew: 0x05B3,
michael@0 27636 hatafsegol: 0x05B1,
michael@0 27637 hatafsegol17: 0x05B1,
michael@0 27638 hatafsegol24: 0x05B1,
michael@0 27639 hatafsegol30: 0x05B1,
michael@0 27640 hatafsegolhebrew: 0x05B1,
michael@0 27641 hatafsegolnarrowhebrew: 0x05B1,
michael@0 27642 hatafsegolquarterhebrew: 0x05B1,
michael@0 27643 hatafsegolwidehebrew: 0x05B1,
michael@0 27644 hbar: 0x0127,
michael@0 27645 hbopomofo: 0x310F,
michael@0 27646 hbrevebelow: 0x1E2B,
michael@0 27647 hcedilla: 0x1E29,
michael@0 27648 hcircle: 0x24D7,
michael@0 27649 hcircumflex: 0x0125,
michael@0 27650 hdieresis: 0x1E27,
michael@0 27651 hdotaccent: 0x1E23,
michael@0 27652 hdotbelow: 0x1E25,
michael@0 27653 he: 0x05D4,
michael@0 27654 heart: 0x2665,
michael@0 27655 heartsuitblack: 0x2665,
michael@0 27656 heartsuitwhite: 0x2661,
michael@0 27657 hedagesh: 0xFB34,
michael@0 27658 hedageshhebrew: 0xFB34,
michael@0 27659 hehaltonearabic: 0x06C1,
michael@0 27660 heharabic: 0x0647,
michael@0 27661 hehebrew: 0x05D4,
michael@0 27662 hehfinalaltonearabic: 0xFBA7,
michael@0 27663 hehfinalalttwoarabic: 0xFEEA,
michael@0 27664 hehfinalarabic: 0xFEEA,
michael@0 27665 hehhamzaabovefinalarabic: 0xFBA5,
michael@0 27666 hehhamzaaboveisolatedarabic: 0xFBA4,
michael@0 27667 hehinitialaltonearabic: 0xFBA8,
michael@0 27668 hehinitialarabic: 0xFEEB,
michael@0 27669 hehiragana: 0x3078,
michael@0 27670 hehmedialaltonearabic: 0xFBA9,
michael@0 27671 hehmedialarabic: 0xFEEC,
michael@0 27672 heiseierasquare: 0x337B,
michael@0 27673 hekatakana: 0x30D8,
michael@0 27674 hekatakanahalfwidth: 0xFF8D,
michael@0 27675 hekutaarusquare: 0x3336,
michael@0 27676 henghook: 0x0267,
michael@0 27677 herutusquare: 0x3339,
michael@0 27678 het: 0x05D7,
michael@0 27679 hethebrew: 0x05D7,
michael@0 27680 hhook: 0x0266,
michael@0 27681 hhooksuperior: 0x02B1,
michael@0 27682 hieuhacirclekorean: 0x327B,
michael@0 27683 hieuhaparenkorean: 0x321B,
michael@0 27684 hieuhcirclekorean: 0x326D,
michael@0 27685 hieuhkorean: 0x314E,
michael@0 27686 hieuhparenkorean: 0x320D,
michael@0 27687 hihiragana: 0x3072,
michael@0 27688 hikatakana: 0x30D2,
michael@0 27689 hikatakanahalfwidth: 0xFF8B,
michael@0 27690 hiriq: 0x05B4,
michael@0 27691 hiriq14: 0x05B4,
michael@0 27692 hiriq21: 0x05B4,
michael@0 27693 hiriq2d: 0x05B4,
michael@0 27694 hiriqhebrew: 0x05B4,
michael@0 27695 hiriqnarrowhebrew: 0x05B4,
michael@0 27696 hiriqquarterhebrew: 0x05B4,
michael@0 27697 hiriqwidehebrew: 0x05B4,
michael@0 27698 hlinebelow: 0x1E96,
michael@0 27699 hmonospace: 0xFF48,
michael@0 27700 hoarmenian: 0x0570,
michael@0 27701 hohipthai: 0x0E2B,
michael@0 27702 hohiragana: 0x307B,
michael@0 27703 hokatakana: 0x30DB,
michael@0 27704 hokatakanahalfwidth: 0xFF8E,
michael@0 27705 holam: 0x05B9,
michael@0 27706 holam19: 0x05B9,
michael@0 27707 holam26: 0x05B9,
michael@0 27708 holam32: 0x05B9,
michael@0 27709 holamhebrew: 0x05B9,
michael@0 27710 holamnarrowhebrew: 0x05B9,
michael@0 27711 holamquarterhebrew: 0x05B9,
michael@0 27712 holamwidehebrew: 0x05B9,
michael@0 27713 honokhukthai: 0x0E2E,
michael@0 27714 hookabovecomb: 0x0309,
michael@0 27715 hookcmb: 0x0309,
michael@0 27716 hookpalatalizedbelowcmb: 0x0321,
michael@0 27717 hookretroflexbelowcmb: 0x0322,
michael@0 27718 hoonsquare: 0x3342,
michael@0 27719 horicoptic: 0x03E9,
michael@0 27720 horizontalbar: 0x2015,
michael@0 27721 horncmb: 0x031B,
michael@0 27722 hotsprings: 0x2668,
michael@0 27723 house: 0x2302,
michael@0 27724 hparen: 0x24A3,
michael@0 27725 hsuperior: 0x02B0,
michael@0 27726 hturned: 0x0265,
michael@0 27727 huhiragana: 0x3075,
michael@0 27728 huiitosquare: 0x3333,
michael@0 27729 hukatakana: 0x30D5,
michael@0 27730 hukatakanahalfwidth: 0xFF8C,
michael@0 27731 hungarumlaut: 0x02DD,
michael@0 27732 hungarumlautcmb: 0x030B,
michael@0 27733 hv: 0x0195,
michael@0 27734 hyphen: 0x002D,
michael@0 27735 hypheninferior: 0xF6E5,
michael@0 27736 hyphenmonospace: 0xFF0D,
michael@0 27737 hyphensmall: 0xFE63,
michael@0 27738 hyphensuperior: 0xF6E6,
michael@0 27739 hyphentwo: 0x2010,
michael@0 27740 i: 0x0069,
michael@0 27741 iacute: 0x00ED,
michael@0 27742 iacyrillic: 0x044F,
michael@0 27743 ibengali: 0x0987,
michael@0 27744 ibopomofo: 0x3127,
michael@0 27745 ibreve: 0x012D,
michael@0 27746 icaron: 0x01D0,
michael@0 27747 icircle: 0x24D8,
michael@0 27748 icircumflex: 0x00EE,
michael@0 27749 icyrillic: 0x0456,
michael@0 27750 idblgrave: 0x0209,
michael@0 27751 ideographearthcircle: 0x328F,
michael@0 27752 ideographfirecircle: 0x328B,
michael@0 27753 ideographicallianceparen: 0x323F,
michael@0 27754 ideographiccallparen: 0x323A,
michael@0 27755 ideographiccentrecircle: 0x32A5,
michael@0 27756 ideographicclose: 0x3006,
michael@0 27757 ideographiccomma: 0x3001,
michael@0 27758 ideographiccommaleft: 0xFF64,
michael@0 27759 ideographiccongratulationparen: 0x3237,
michael@0 27760 ideographiccorrectcircle: 0x32A3,
michael@0 27761 ideographicearthparen: 0x322F,
michael@0 27762 ideographicenterpriseparen: 0x323D,
michael@0 27763 ideographicexcellentcircle: 0x329D,
michael@0 27764 ideographicfestivalparen: 0x3240,
michael@0 27765 ideographicfinancialcircle: 0x3296,
michael@0 27766 ideographicfinancialparen: 0x3236,
michael@0 27767 ideographicfireparen: 0x322B,
michael@0 27768 ideographichaveparen: 0x3232,
michael@0 27769 ideographichighcircle: 0x32A4,
michael@0 27770 ideographiciterationmark: 0x3005,
michael@0 27771 ideographiclaborcircle: 0x3298,
michael@0 27772 ideographiclaborparen: 0x3238,
michael@0 27773 ideographicleftcircle: 0x32A7,
michael@0 27774 ideographiclowcircle: 0x32A6,
michael@0 27775 ideographicmedicinecircle: 0x32A9,
michael@0 27776 ideographicmetalparen: 0x322E,
michael@0 27777 ideographicmoonparen: 0x322A,
michael@0 27778 ideographicnameparen: 0x3234,
michael@0 27779 ideographicperiod: 0x3002,
michael@0 27780 ideographicprintcircle: 0x329E,
michael@0 27781 ideographicreachparen: 0x3243,
michael@0 27782 ideographicrepresentparen: 0x3239,
michael@0 27783 ideographicresourceparen: 0x323E,
michael@0 27784 ideographicrightcircle: 0x32A8,
michael@0 27785 ideographicsecretcircle: 0x3299,
michael@0 27786 ideographicselfparen: 0x3242,
michael@0 27787 ideographicsocietyparen: 0x3233,
michael@0 27788 ideographicspace: 0x3000,
michael@0 27789 ideographicspecialparen: 0x3235,
michael@0 27790 ideographicstockparen: 0x3231,
michael@0 27791 ideographicstudyparen: 0x323B,
michael@0 27792 ideographicsunparen: 0x3230,
michael@0 27793 ideographicsuperviseparen: 0x323C,
michael@0 27794 ideographicwaterparen: 0x322C,
michael@0 27795 ideographicwoodparen: 0x322D,
michael@0 27796 ideographiczero: 0x3007,
michael@0 27797 ideographmetalcircle: 0x328E,
michael@0 27798 ideographmooncircle: 0x328A,
michael@0 27799 ideographnamecircle: 0x3294,
michael@0 27800 ideographsuncircle: 0x3290,
michael@0 27801 ideographwatercircle: 0x328C,
michael@0 27802 ideographwoodcircle: 0x328D,
michael@0 27803 ideva: 0x0907,
michael@0 27804 idieresis: 0x00EF,
michael@0 27805 idieresisacute: 0x1E2F,
michael@0 27806 idieresiscyrillic: 0x04E5,
michael@0 27807 idotbelow: 0x1ECB,
michael@0 27808 iebrevecyrillic: 0x04D7,
michael@0 27809 iecyrillic: 0x0435,
michael@0 27810 ieungacirclekorean: 0x3275,
michael@0 27811 ieungaparenkorean: 0x3215,
michael@0 27812 ieungcirclekorean: 0x3267,
michael@0 27813 ieungkorean: 0x3147,
michael@0 27814 ieungparenkorean: 0x3207,
michael@0 27815 igrave: 0x00EC,
michael@0 27816 igujarati: 0x0A87,
michael@0 27817 igurmukhi: 0x0A07,
michael@0 27818 ihiragana: 0x3044,
michael@0 27819 ihookabove: 0x1EC9,
michael@0 27820 iibengali: 0x0988,
michael@0 27821 iicyrillic: 0x0438,
michael@0 27822 iideva: 0x0908,
michael@0 27823 iigujarati: 0x0A88,
michael@0 27824 iigurmukhi: 0x0A08,
michael@0 27825 iimatragurmukhi: 0x0A40,
michael@0 27826 iinvertedbreve: 0x020B,
michael@0 27827 iishortcyrillic: 0x0439,
michael@0 27828 iivowelsignbengali: 0x09C0,
michael@0 27829 iivowelsigndeva: 0x0940,
michael@0 27830 iivowelsigngujarati: 0x0AC0,
michael@0 27831 ij: 0x0133,
michael@0 27832 ikatakana: 0x30A4,
michael@0 27833 ikatakanahalfwidth: 0xFF72,
michael@0 27834 ikorean: 0x3163,
michael@0 27835 ilde: 0x02DC,
michael@0 27836 iluyhebrew: 0x05AC,
michael@0 27837 imacron: 0x012B,
michael@0 27838 imacroncyrillic: 0x04E3,
michael@0 27839 imageorapproximatelyequal: 0x2253,
michael@0 27840 imatragurmukhi: 0x0A3F,
michael@0 27841 imonospace: 0xFF49,
michael@0 27842 increment: 0x2206,
michael@0 27843 infinity: 0x221E,
michael@0 27844 iniarmenian: 0x056B,
michael@0 27845 integral: 0x222B,
michael@0 27846 integralbottom: 0x2321,
michael@0 27847 integralbt: 0x2321,
michael@0 27848 integralex: 0xF8F5,
michael@0 27849 integraltop: 0x2320,
michael@0 27850 integraltp: 0x2320,
michael@0 27851 intersection: 0x2229,
michael@0 27852 intisquare: 0x3305,
michael@0 27853 invbullet: 0x25D8,
michael@0 27854 invcircle: 0x25D9,
michael@0 27855 invsmileface: 0x263B,
michael@0 27856 iocyrillic: 0x0451,
michael@0 27857 iogonek: 0x012F,
michael@0 27858 iota: 0x03B9,
michael@0 27859 iotadieresis: 0x03CA,
michael@0 27860 iotadieresistonos: 0x0390,
michael@0 27861 iotalatin: 0x0269,
michael@0 27862 iotatonos: 0x03AF,
michael@0 27863 iparen: 0x24A4,
michael@0 27864 irigurmukhi: 0x0A72,
michael@0 27865 ismallhiragana: 0x3043,
michael@0 27866 ismallkatakana: 0x30A3,
michael@0 27867 ismallkatakanahalfwidth: 0xFF68,
michael@0 27868 issharbengali: 0x09FA,
michael@0 27869 istroke: 0x0268,
michael@0 27870 isuperior: 0xF6ED,
michael@0 27871 iterationhiragana: 0x309D,
michael@0 27872 iterationkatakana: 0x30FD,
michael@0 27873 itilde: 0x0129,
michael@0 27874 itildebelow: 0x1E2D,
michael@0 27875 iubopomofo: 0x3129,
michael@0 27876 iucyrillic: 0x044E,
michael@0 27877 ivowelsignbengali: 0x09BF,
michael@0 27878 ivowelsigndeva: 0x093F,
michael@0 27879 ivowelsigngujarati: 0x0ABF,
michael@0 27880 izhitsacyrillic: 0x0475,
michael@0 27881 izhitsadblgravecyrillic: 0x0477,
michael@0 27882 j: 0x006A,
michael@0 27883 jaarmenian: 0x0571,
michael@0 27884 jabengali: 0x099C,
michael@0 27885 jadeva: 0x091C,
michael@0 27886 jagujarati: 0x0A9C,
michael@0 27887 jagurmukhi: 0x0A1C,
michael@0 27888 jbopomofo: 0x3110,
michael@0 27889 jcaron: 0x01F0,
michael@0 27890 jcircle: 0x24D9,
michael@0 27891 jcircumflex: 0x0135,
michael@0 27892 jcrossedtail: 0x029D,
michael@0 27893 jdotlessstroke: 0x025F,
michael@0 27894 jecyrillic: 0x0458,
michael@0 27895 jeemarabic: 0x062C,
michael@0 27896 jeemfinalarabic: 0xFE9E,
michael@0 27897 jeeminitialarabic: 0xFE9F,
michael@0 27898 jeemmedialarabic: 0xFEA0,
michael@0 27899 jeharabic: 0x0698,
michael@0 27900 jehfinalarabic: 0xFB8B,
michael@0 27901 jhabengali: 0x099D,
michael@0 27902 jhadeva: 0x091D,
michael@0 27903 jhagujarati: 0x0A9D,
michael@0 27904 jhagurmukhi: 0x0A1D,
michael@0 27905 jheharmenian: 0x057B,
michael@0 27906 jis: 0x3004,
michael@0 27907 jmonospace: 0xFF4A,
michael@0 27908 jparen: 0x24A5,
michael@0 27909 jsuperior: 0x02B2,
michael@0 27910 k: 0x006B,
michael@0 27911 kabashkircyrillic: 0x04A1,
michael@0 27912 kabengali: 0x0995,
michael@0 27913 kacute: 0x1E31,
michael@0 27914 kacyrillic: 0x043A,
michael@0 27915 kadescendercyrillic: 0x049B,
michael@0 27916 kadeva: 0x0915,
michael@0 27917 kaf: 0x05DB,
michael@0 27918 kafarabic: 0x0643,
michael@0 27919 kafdagesh: 0xFB3B,
michael@0 27920 kafdageshhebrew: 0xFB3B,
michael@0 27921 kaffinalarabic: 0xFEDA,
michael@0 27922 kafhebrew: 0x05DB,
michael@0 27923 kafinitialarabic: 0xFEDB,
michael@0 27924 kafmedialarabic: 0xFEDC,
michael@0 27925 kafrafehebrew: 0xFB4D,
michael@0 27926 kagujarati: 0x0A95,
michael@0 27927 kagurmukhi: 0x0A15,
michael@0 27928 kahiragana: 0x304B,
michael@0 27929 kahookcyrillic: 0x04C4,
michael@0 27930 kakatakana: 0x30AB,
michael@0 27931 kakatakanahalfwidth: 0xFF76,
michael@0 27932 kappa: 0x03BA,
michael@0 27933 kappasymbolgreek: 0x03F0,
michael@0 27934 kapyeounmieumkorean: 0x3171,
michael@0 27935 kapyeounphieuphkorean: 0x3184,
michael@0 27936 kapyeounpieupkorean: 0x3178,
michael@0 27937 kapyeounssangpieupkorean: 0x3179,
michael@0 27938 karoriisquare: 0x330D,
michael@0 27939 kashidaautoarabic: 0x0640,
michael@0 27940 kashidaautonosidebearingarabic: 0x0640,
michael@0 27941 kasmallkatakana: 0x30F5,
michael@0 27942 kasquare: 0x3384,
michael@0 27943 kasraarabic: 0x0650,
michael@0 27944 kasratanarabic: 0x064D,
michael@0 27945 kastrokecyrillic: 0x049F,
michael@0 27946 katahiraprolongmarkhalfwidth: 0xFF70,
michael@0 27947 kaverticalstrokecyrillic: 0x049D,
michael@0 27948 kbopomofo: 0x310E,
michael@0 27949 kcalsquare: 0x3389,
michael@0 27950 kcaron: 0x01E9,
michael@0 27951 kcedilla: 0x0137,
michael@0 27952 kcircle: 0x24DA,
michael@0 27953 kcommaaccent: 0x0137,
michael@0 27954 kdotbelow: 0x1E33,
michael@0 27955 keharmenian: 0x0584,
michael@0 27956 kehiragana: 0x3051,
michael@0 27957 kekatakana: 0x30B1,
michael@0 27958 kekatakanahalfwidth: 0xFF79,
michael@0 27959 kenarmenian: 0x056F,
michael@0 27960 kesmallkatakana: 0x30F6,
michael@0 27961 kgreenlandic: 0x0138,
michael@0 27962 khabengali: 0x0996,
michael@0 27963 khacyrillic: 0x0445,
michael@0 27964 khadeva: 0x0916,
michael@0 27965 khagujarati: 0x0A96,
michael@0 27966 khagurmukhi: 0x0A16,
michael@0 27967 khaharabic: 0x062E,
michael@0 27968 khahfinalarabic: 0xFEA6,
michael@0 27969 khahinitialarabic: 0xFEA7,
michael@0 27970 khahmedialarabic: 0xFEA8,
michael@0 27971 kheicoptic: 0x03E7,
michael@0 27972 khhadeva: 0x0959,
michael@0 27973 khhagurmukhi: 0x0A59,
michael@0 27974 khieukhacirclekorean: 0x3278,
michael@0 27975 khieukhaparenkorean: 0x3218,
michael@0 27976 khieukhcirclekorean: 0x326A,
michael@0 27977 khieukhkorean: 0x314B,
michael@0 27978 khieukhparenkorean: 0x320A,
michael@0 27979 khokhaithai: 0x0E02,
michael@0 27980 khokhonthai: 0x0E05,
michael@0 27981 khokhuatthai: 0x0E03,
michael@0 27982 khokhwaithai: 0x0E04,
michael@0 27983 khomutthai: 0x0E5B,
michael@0 27984 khook: 0x0199,
michael@0 27985 khorakhangthai: 0x0E06,
michael@0 27986 khzsquare: 0x3391,
michael@0 27987 kihiragana: 0x304D,
michael@0 27988 kikatakana: 0x30AD,
michael@0 27989 kikatakanahalfwidth: 0xFF77,
michael@0 27990 kiroguramusquare: 0x3315,
michael@0 27991 kiromeetorusquare: 0x3316,
michael@0 27992 kirosquare: 0x3314,
michael@0 27993 kiyeokacirclekorean: 0x326E,
michael@0 27994 kiyeokaparenkorean: 0x320E,
michael@0 27995 kiyeokcirclekorean: 0x3260,
michael@0 27996 kiyeokkorean: 0x3131,
michael@0 27997 kiyeokparenkorean: 0x3200,
michael@0 27998 kiyeoksioskorean: 0x3133,
michael@0 27999 kjecyrillic: 0x045C,
michael@0 28000 klinebelow: 0x1E35,
michael@0 28001 klsquare: 0x3398,
michael@0 28002 kmcubedsquare: 0x33A6,
michael@0 28003 kmonospace: 0xFF4B,
michael@0 28004 kmsquaredsquare: 0x33A2,
michael@0 28005 kohiragana: 0x3053,
michael@0 28006 kohmsquare: 0x33C0,
michael@0 28007 kokaithai: 0x0E01,
michael@0 28008 kokatakana: 0x30B3,
michael@0 28009 kokatakanahalfwidth: 0xFF7A,
michael@0 28010 kooposquare: 0x331E,
michael@0 28011 koppacyrillic: 0x0481,
michael@0 28012 koreanstandardsymbol: 0x327F,
michael@0 28013 koroniscmb: 0x0343,
michael@0 28014 kparen: 0x24A6,
michael@0 28015 kpasquare: 0x33AA,
michael@0 28016 ksicyrillic: 0x046F,
michael@0 28017 ktsquare: 0x33CF,
michael@0 28018 kturned: 0x029E,
michael@0 28019 kuhiragana: 0x304F,
michael@0 28020 kukatakana: 0x30AF,
michael@0 28021 kukatakanahalfwidth: 0xFF78,
michael@0 28022 kvsquare: 0x33B8,
michael@0 28023 kwsquare: 0x33BE,
michael@0 28024 l: 0x006C,
michael@0 28025 labengali: 0x09B2,
michael@0 28026 lacute: 0x013A,
michael@0 28027 ladeva: 0x0932,
michael@0 28028 lagujarati: 0x0AB2,
michael@0 28029 lagurmukhi: 0x0A32,
michael@0 28030 lakkhangyaothai: 0x0E45,
michael@0 28031 lamaleffinalarabic: 0xFEFC,
michael@0 28032 lamalefhamzaabovefinalarabic: 0xFEF8,
michael@0 28033 lamalefhamzaaboveisolatedarabic: 0xFEF7,
michael@0 28034 lamalefhamzabelowfinalarabic: 0xFEFA,
michael@0 28035 lamalefhamzabelowisolatedarabic: 0xFEF9,
michael@0 28036 lamalefisolatedarabic: 0xFEFB,
michael@0 28037 lamalefmaddaabovefinalarabic: 0xFEF6,
michael@0 28038 lamalefmaddaaboveisolatedarabic: 0xFEF5,
michael@0 28039 lamarabic: 0x0644,
michael@0 28040 lambda: 0x03BB,
michael@0 28041 lambdastroke: 0x019B,
michael@0 28042 lamed: 0x05DC,
michael@0 28043 lameddagesh: 0xFB3C,
michael@0 28044 lameddageshhebrew: 0xFB3C,
michael@0 28045 lamedhebrew: 0x05DC,
michael@0 28046 lamfinalarabic: 0xFEDE,
michael@0 28047 lamhahinitialarabic: 0xFCCA,
michael@0 28048 laminitialarabic: 0xFEDF,
michael@0 28049 lamjeeminitialarabic: 0xFCC9,
michael@0 28050 lamkhahinitialarabic: 0xFCCB,
michael@0 28051 lamlamhehisolatedarabic: 0xFDF2,
michael@0 28052 lammedialarabic: 0xFEE0,
michael@0 28053 lammeemhahinitialarabic: 0xFD88,
michael@0 28054 lammeeminitialarabic: 0xFCCC,
michael@0 28055 largecircle: 0x25EF,
michael@0 28056 lbar: 0x019A,
michael@0 28057 lbelt: 0x026C,
michael@0 28058 lbopomofo: 0x310C,
michael@0 28059 lcaron: 0x013E,
michael@0 28060 lcedilla: 0x013C,
michael@0 28061 lcircle: 0x24DB,
michael@0 28062 lcircumflexbelow: 0x1E3D,
michael@0 28063 lcommaaccent: 0x013C,
michael@0 28064 ldot: 0x0140,
michael@0 28065 ldotaccent: 0x0140,
michael@0 28066 ldotbelow: 0x1E37,
michael@0 28067 ldotbelowmacron: 0x1E39,
michael@0 28068 leftangleabovecmb: 0x031A,
michael@0 28069 lefttackbelowcmb: 0x0318,
michael@0 28070 less: 0x003C,
michael@0 28071 lessequal: 0x2264,
michael@0 28072 lessequalorgreater: 0x22DA,
michael@0 28073 lessmonospace: 0xFF1C,
michael@0 28074 lessorequivalent: 0x2272,
michael@0 28075 lessorgreater: 0x2276,
michael@0 28076 lessoverequal: 0x2266,
michael@0 28077 lesssmall: 0xFE64,
michael@0 28078 lezh: 0x026E,
michael@0 28079 lfblock: 0x258C,
michael@0 28080 lhookretroflex: 0x026D,
michael@0 28081 lira: 0x20A4,
michael@0 28082 liwnarmenian: 0x056C,
michael@0 28083 lj: 0x01C9,
michael@0 28084 ljecyrillic: 0x0459,
michael@0 28085 ll: 0xF6C0,
michael@0 28086 lladeva: 0x0933,
michael@0 28087 llagujarati: 0x0AB3,
michael@0 28088 llinebelow: 0x1E3B,
michael@0 28089 llladeva: 0x0934,
michael@0 28090 llvocalicbengali: 0x09E1,
michael@0 28091 llvocalicdeva: 0x0961,
michael@0 28092 llvocalicvowelsignbengali: 0x09E3,
michael@0 28093 llvocalicvowelsigndeva: 0x0963,
michael@0 28094 lmiddletilde: 0x026B,
michael@0 28095 lmonospace: 0xFF4C,
michael@0 28096 lmsquare: 0x33D0,
michael@0 28097 lochulathai: 0x0E2C,
michael@0 28098 logicaland: 0x2227,
michael@0 28099 logicalnot: 0x00AC,
michael@0 28100 logicalnotreversed: 0x2310,
michael@0 28101 logicalor: 0x2228,
michael@0 28102 lolingthai: 0x0E25,
michael@0 28103 longs: 0x017F,
michael@0 28104 lowlinecenterline: 0xFE4E,
michael@0 28105 lowlinecmb: 0x0332,
michael@0 28106 lowlinedashed: 0xFE4D,
michael@0 28107 lozenge: 0x25CA,
michael@0 28108 lparen: 0x24A7,
michael@0 28109 lslash: 0x0142,
michael@0 28110 lsquare: 0x2113,
michael@0 28111 lsuperior: 0xF6EE,
michael@0 28112 ltshade: 0x2591,
michael@0 28113 luthai: 0x0E26,
michael@0 28114 lvocalicbengali: 0x098C,
michael@0 28115 lvocalicdeva: 0x090C,
michael@0 28116 lvocalicvowelsignbengali: 0x09E2,
michael@0 28117 lvocalicvowelsigndeva: 0x0962,
michael@0 28118 lxsquare: 0x33D3,
michael@0 28119 m: 0x006D,
michael@0 28120 mabengali: 0x09AE,
michael@0 28121 macron: 0x00AF,
michael@0 28122 macronbelowcmb: 0x0331,
michael@0 28123 macroncmb: 0x0304,
michael@0 28124 macronlowmod: 0x02CD,
michael@0 28125 macronmonospace: 0xFFE3,
michael@0 28126 macute: 0x1E3F,
michael@0 28127 madeva: 0x092E,
michael@0 28128 magujarati: 0x0AAE,
michael@0 28129 magurmukhi: 0x0A2E,
michael@0 28130 mahapakhhebrew: 0x05A4,
michael@0 28131 mahapakhlefthebrew: 0x05A4,
michael@0 28132 mahiragana: 0x307E,
michael@0 28133 maichattawalowleftthai: 0xF895,
michael@0 28134 maichattawalowrightthai: 0xF894,
michael@0 28135 maichattawathai: 0x0E4B,
michael@0 28136 maichattawaupperleftthai: 0xF893,
michael@0 28137 maieklowleftthai: 0xF88C,
michael@0 28138 maieklowrightthai: 0xF88B,
michael@0 28139 maiekthai: 0x0E48,
michael@0 28140 maiekupperleftthai: 0xF88A,
michael@0 28141 maihanakatleftthai: 0xF884,
michael@0 28142 maihanakatthai: 0x0E31,
michael@0 28143 maitaikhuleftthai: 0xF889,
michael@0 28144 maitaikhuthai: 0x0E47,
michael@0 28145 maitholowleftthai: 0xF88F,
michael@0 28146 maitholowrightthai: 0xF88E,
michael@0 28147 maithothai: 0x0E49,
michael@0 28148 maithoupperleftthai: 0xF88D,
michael@0 28149 maitrilowleftthai: 0xF892,
michael@0 28150 maitrilowrightthai: 0xF891,
michael@0 28151 maitrithai: 0x0E4A,
michael@0 28152 maitriupperleftthai: 0xF890,
michael@0 28153 maiyamokthai: 0x0E46,
michael@0 28154 makatakana: 0x30DE,
michael@0 28155 makatakanahalfwidth: 0xFF8F,
michael@0 28156 male: 0x2642,
michael@0 28157 mansyonsquare: 0x3347,
michael@0 28158 maqafhebrew: 0x05BE,
michael@0 28159 mars: 0x2642,
michael@0 28160 masoracirclehebrew: 0x05AF,
michael@0 28161 masquare: 0x3383,
michael@0 28162 mbopomofo: 0x3107,
michael@0 28163 mbsquare: 0x33D4,
michael@0 28164 mcircle: 0x24DC,
michael@0 28165 mcubedsquare: 0x33A5,
michael@0 28166 mdotaccent: 0x1E41,
michael@0 28167 mdotbelow: 0x1E43,
michael@0 28168 meemarabic: 0x0645,
michael@0 28169 meemfinalarabic: 0xFEE2,
michael@0 28170 meeminitialarabic: 0xFEE3,
michael@0 28171 meemmedialarabic: 0xFEE4,
michael@0 28172 meemmeeminitialarabic: 0xFCD1,
michael@0 28173 meemmeemisolatedarabic: 0xFC48,
michael@0 28174 meetorusquare: 0x334D,
michael@0 28175 mehiragana: 0x3081,
michael@0 28176 meizierasquare: 0x337E,
michael@0 28177 mekatakana: 0x30E1,
michael@0 28178 mekatakanahalfwidth: 0xFF92,
michael@0 28179 mem: 0x05DE,
michael@0 28180 memdagesh: 0xFB3E,
michael@0 28181 memdageshhebrew: 0xFB3E,
michael@0 28182 memhebrew: 0x05DE,
michael@0 28183 menarmenian: 0x0574,
michael@0 28184 merkhahebrew: 0x05A5,
michael@0 28185 merkhakefulahebrew: 0x05A6,
michael@0 28186 merkhakefulalefthebrew: 0x05A6,
michael@0 28187 merkhalefthebrew: 0x05A5,
michael@0 28188 mhook: 0x0271,
michael@0 28189 mhzsquare: 0x3392,
michael@0 28190 middledotkatakanahalfwidth: 0xFF65,
michael@0 28191 middot: 0x00B7,
michael@0 28192 mieumacirclekorean: 0x3272,
michael@0 28193 mieumaparenkorean: 0x3212,
michael@0 28194 mieumcirclekorean: 0x3264,
michael@0 28195 mieumkorean: 0x3141,
michael@0 28196 mieumpansioskorean: 0x3170,
michael@0 28197 mieumparenkorean: 0x3204,
michael@0 28198 mieumpieupkorean: 0x316E,
michael@0 28199 mieumsioskorean: 0x316F,
michael@0 28200 mihiragana: 0x307F,
michael@0 28201 mikatakana: 0x30DF,
michael@0 28202 mikatakanahalfwidth: 0xFF90,
michael@0 28203 minus: 0x2212,
michael@0 28204 minusbelowcmb: 0x0320,
michael@0 28205 minuscircle: 0x2296,
michael@0 28206 minusmod: 0x02D7,
michael@0 28207 minusplus: 0x2213,
michael@0 28208 minute: 0x2032,
michael@0 28209 miribaarusquare: 0x334A,
michael@0 28210 mirisquare: 0x3349,
michael@0 28211 mlonglegturned: 0x0270,
michael@0 28212 mlsquare: 0x3396,
michael@0 28213 mmcubedsquare: 0x33A3,
michael@0 28214 mmonospace: 0xFF4D,
michael@0 28215 mmsquaredsquare: 0x339F,
michael@0 28216 mohiragana: 0x3082,
michael@0 28217 mohmsquare: 0x33C1,
michael@0 28218 mokatakana: 0x30E2,
michael@0 28219 mokatakanahalfwidth: 0xFF93,
michael@0 28220 molsquare: 0x33D6,
michael@0 28221 momathai: 0x0E21,
michael@0 28222 moverssquare: 0x33A7,
michael@0 28223 moverssquaredsquare: 0x33A8,
michael@0 28224 mparen: 0x24A8,
michael@0 28225 mpasquare: 0x33AB,
michael@0 28226 mssquare: 0x33B3,
michael@0 28227 msuperior: 0xF6EF,
michael@0 28228 mturned: 0x026F,
michael@0 28229 mu: 0x00B5,
michael@0 28230 mu1: 0x00B5,
michael@0 28231 muasquare: 0x3382,
michael@0 28232 muchgreater: 0x226B,
michael@0 28233 muchless: 0x226A,
michael@0 28234 mufsquare: 0x338C,
michael@0 28235 mugreek: 0x03BC,
michael@0 28236 mugsquare: 0x338D,
michael@0 28237 muhiragana: 0x3080,
michael@0 28238 mukatakana: 0x30E0,
michael@0 28239 mukatakanahalfwidth: 0xFF91,
michael@0 28240 mulsquare: 0x3395,
michael@0 28241 multiply: 0x00D7,
michael@0 28242 mumsquare: 0x339B,
michael@0 28243 munahhebrew: 0x05A3,
michael@0 28244 munahlefthebrew: 0x05A3,
michael@0 28245 musicalnote: 0x266A,
michael@0 28246 musicalnotedbl: 0x266B,
michael@0 28247 musicflatsign: 0x266D,
michael@0 28248 musicsharpsign: 0x266F,
michael@0 28249 mussquare: 0x33B2,
michael@0 28250 muvsquare: 0x33B6,
michael@0 28251 muwsquare: 0x33BC,
michael@0 28252 mvmegasquare: 0x33B9,
michael@0 28253 mvsquare: 0x33B7,
michael@0 28254 mwmegasquare: 0x33BF,
michael@0 28255 mwsquare: 0x33BD,
michael@0 28256 n: 0x006E,
michael@0 28257 nabengali: 0x09A8,
michael@0 28258 nabla: 0x2207,
michael@0 28259 nacute: 0x0144,
michael@0 28260 nadeva: 0x0928,
michael@0 28261 nagujarati: 0x0AA8,
michael@0 28262 nagurmukhi: 0x0A28,
michael@0 28263 nahiragana: 0x306A,
michael@0 28264 nakatakana: 0x30CA,
michael@0 28265 nakatakanahalfwidth: 0xFF85,
michael@0 28266 napostrophe: 0x0149,
michael@0 28267 nasquare: 0x3381,
michael@0 28268 nbopomofo: 0x310B,
michael@0 28269 nbspace: 0x00A0,
michael@0 28270 ncaron: 0x0148,
michael@0 28271 ncedilla: 0x0146,
michael@0 28272 ncircle: 0x24DD,
michael@0 28273 ncircumflexbelow: 0x1E4B,
michael@0 28274 ncommaaccent: 0x0146,
michael@0 28275 ndotaccent: 0x1E45,
michael@0 28276 ndotbelow: 0x1E47,
michael@0 28277 nehiragana: 0x306D,
michael@0 28278 nekatakana: 0x30CD,
michael@0 28279 nekatakanahalfwidth: 0xFF88,
michael@0 28280 newsheqelsign: 0x20AA,
michael@0 28281 nfsquare: 0x338B,
michael@0 28282 ngabengali: 0x0999,
michael@0 28283 ngadeva: 0x0919,
michael@0 28284 ngagujarati: 0x0A99,
michael@0 28285 ngagurmukhi: 0x0A19,
michael@0 28286 ngonguthai: 0x0E07,
michael@0 28287 nhiragana: 0x3093,
michael@0 28288 nhookleft: 0x0272,
michael@0 28289 nhookretroflex: 0x0273,
michael@0 28290 nieunacirclekorean: 0x326F,
michael@0 28291 nieunaparenkorean: 0x320F,
michael@0 28292 nieuncieuckorean: 0x3135,
michael@0 28293 nieuncirclekorean: 0x3261,
michael@0 28294 nieunhieuhkorean: 0x3136,
michael@0 28295 nieunkorean: 0x3134,
michael@0 28296 nieunpansioskorean: 0x3168,
michael@0 28297 nieunparenkorean: 0x3201,
michael@0 28298 nieunsioskorean: 0x3167,
michael@0 28299 nieuntikeutkorean: 0x3166,
michael@0 28300 nihiragana: 0x306B,
michael@0 28301 nikatakana: 0x30CB,
michael@0 28302 nikatakanahalfwidth: 0xFF86,
michael@0 28303 nikhahitleftthai: 0xF899,
michael@0 28304 nikhahitthai: 0x0E4D,
michael@0 28305 nine: 0x0039,
michael@0 28306 ninearabic: 0x0669,
michael@0 28307 ninebengali: 0x09EF,
michael@0 28308 ninecircle: 0x2468,
michael@0 28309 ninecircleinversesansserif: 0x2792,
michael@0 28310 ninedeva: 0x096F,
michael@0 28311 ninegujarati: 0x0AEF,
michael@0 28312 ninegurmukhi: 0x0A6F,
michael@0 28313 ninehackarabic: 0x0669,
michael@0 28314 ninehangzhou: 0x3029,
michael@0 28315 nineideographicparen: 0x3228,
michael@0 28316 nineinferior: 0x2089,
michael@0 28317 ninemonospace: 0xFF19,
michael@0 28318 nineoldstyle: 0xF739,
michael@0 28319 nineparen: 0x247C,
michael@0 28320 nineperiod: 0x2490,
michael@0 28321 ninepersian: 0x06F9,
michael@0 28322 nineroman: 0x2178,
michael@0 28323 ninesuperior: 0x2079,
michael@0 28324 nineteencircle: 0x2472,
michael@0 28325 nineteenparen: 0x2486,
michael@0 28326 nineteenperiod: 0x249A,
michael@0 28327 ninethai: 0x0E59,
michael@0 28328 nj: 0x01CC,
michael@0 28329 njecyrillic: 0x045A,
michael@0 28330 nkatakana: 0x30F3,
michael@0 28331 nkatakanahalfwidth: 0xFF9D,
michael@0 28332 nlegrightlong: 0x019E,
michael@0 28333 nlinebelow: 0x1E49,
michael@0 28334 nmonospace: 0xFF4E,
michael@0 28335 nmsquare: 0x339A,
michael@0 28336 nnabengali: 0x09A3,
michael@0 28337 nnadeva: 0x0923,
michael@0 28338 nnagujarati: 0x0AA3,
michael@0 28339 nnagurmukhi: 0x0A23,
michael@0 28340 nnnadeva: 0x0929,
michael@0 28341 nohiragana: 0x306E,
michael@0 28342 nokatakana: 0x30CE,
michael@0 28343 nokatakanahalfwidth: 0xFF89,
michael@0 28344 nonbreakingspace: 0x00A0,
michael@0 28345 nonenthai: 0x0E13,
michael@0 28346 nonuthai: 0x0E19,
michael@0 28347 noonarabic: 0x0646,
michael@0 28348 noonfinalarabic: 0xFEE6,
michael@0 28349 noonghunnaarabic: 0x06BA,
michael@0 28350 noonghunnafinalarabic: 0xFB9F,
michael@0 28351 nooninitialarabic: 0xFEE7,
michael@0 28352 noonjeeminitialarabic: 0xFCD2,
michael@0 28353 noonjeemisolatedarabic: 0xFC4B,
michael@0 28354 noonmedialarabic: 0xFEE8,
michael@0 28355 noonmeeminitialarabic: 0xFCD5,
michael@0 28356 noonmeemisolatedarabic: 0xFC4E,
michael@0 28357 noonnoonfinalarabic: 0xFC8D,
michael@0 28358 notcontains: 0x220C,
michael@0 28359 notelement: 0x2209,
michael@0 28360 notelementof: 0x2209,
michael@0 28361 notequal: 0x2260,
michael@0 28362 notgreater: 0x226F,
michael@0 28363 notgreaternorequal: 0x2271,
michael@0 28364 notgreaternorless: 0x2279,
michael@0 28365 notidentical: 0x2262,
michael@0 28366 notless: 0x226E,
michael@0 28367 notlessnorequal: 0x2270,
michael@0 28368 notparallel: 0x2226,
michael@0 28369 notprecedes: 0x2280,
michael@0 28370 notsubset: 0x2284,
michael@0 28371 notsucceeds: 0x2281,
michael@0 28372 notsuperset: 0x2285,
michael@0 28373 nowarmenian: 0x0576,
michael@0 28374 nparen: 0x24A9,
michael@0 28375 nssquare: 0x33B1,
michael@0 28376 nsuperior: 0x207F,
michael@0 28377 ntilde: 0x00F1,
michael@0 28378 nu: 0x03BD,
michael@0 28379 nuhiragana: 0x306C,
michael@0 28380 nukatakana: 0x30CC,
michael@0 28381 nukatakanahalfwidth: 0xFF87,
michael@0 28382 nuktabengali: 0x09BC,
michael@0 28383 nuktadeva: 0x093C,
michael@0 28384 nuktagujarati: 0x0ABC,
michael@0 28385 nuktagurmukhi: 0x0A3C,
michael@0 28386 numbersign: 0x0023,
michael@0 28387 numbersignmonospace: 0xFF03,
michael@0 28388 numbersignsmall: 0xFE5F,
michael@0 28389 numeralsigngreek: 0x0374,
michael@0 28390 numeralsignlowergreek: 0x0375,
michael@0 28391 numero: 0x2116,
michael@0 28392 nun: 0x05E0,
michael@0 28393 nundagesh: 0xFB40,
michael@0 28394 nundageshhebrew: 0xFB40,
michael@0 28395 nunhebrew: 0x05E0,
michael@0 28396 nvsquare: 0x33B5,
michael@0 28397 nwsquare: 0x33BB,
michael@0 28398 nyabengali: 0x099E,
michael@0 28399 nyadeva: 0x091E,
michael@0 28400 nyagujarati: 0x0A9E,
michael@0 28401 nyagurmukhi: 0x0A1E,
michael@0 28402 o: 0x006F,
michael@0 28403 oacute: 0x00F3,
michael@0 28404 oangthai: 0x0E2D,
michael@0 28405 obarred: 0x0275,
michael@0 28406 obarredcyrillic: 0x04E9,
michael@0 28407 obarreddieresiscyrillic: 0x04EB,
michael@0 28408 obengali: 0x0993,
michael@0 28409 obopomofo: 0x311B,
michael@0 28410 obreve: 0x014F,
michael@0 28411 ocandradeva: 0x0911,
michael@0 28412 ocandragujarati: 0x0A91,
michael@0 28413 ocandravowelsigndeva: 0x0949,
michael@0 28414 ocandravowelsigngujarati: 0x0AC9,
michael@0 28415 ocaron: 0x01D2,
michael@0 28416 ocircle: 0x24DE,
michael@0 28417 ocircumflex: 0x00F4,
michael@0 28418 ocircumflexacute: 0x1ED1,
michael@0 28419 ocircumflexdotbelow: 0x1ED9,
michael@0 28420 ocircumflexgrave: 0x1ED3,
michael@0 28421 ocircumflexhookabove: 0x1ED5,
michael@0 28422 ocircumflextilde: 0x1ED7,
michael@0 28423 ocyrillic: 0x043E,
michael@0 28424 odblacute: 0x0151,
michael@0 28425 odblgrave: 0x020D,
michael@0 28426 odeva: 0x0913,
michael@0 28427 odieresis: 0x00F6,
michael@0 28428 odieresiscyrillic: 0x04E7,
michael@0 28429 odotbelow: 0x1ECD,
michael@0 28430 oe: 0x0153,
michael@0 28431 oekorean: 0x315A,
michael@0 28432 ogonek: 0x02DB,
michael@0 28433 ogonekcmb: 0x0328,
michael@0 28434 ograve: 0x00F2,
michael@0 28435 ogujarati: 0x0A93,
michael@0 28436 oharmenian: 0x0585,
michael@0 28437 ohiragana: 0x304A,
michael@0 28438 ohookabove: 0x1ECF,
michael@0 28439 ohorn: 0x01A1,
michael@0 28440 ohornacute: 0x1EDB,
michael@0 28441 ohorndotbelow: 0x1EE3,
michael@0 28442 ohorngrave: 0x1EDD,
michael@0 28443 ohornhookabove: 0x1EDF,
michael@0 28444 ohorntilde: 0x1EE1,
michael@0 28445 ohungarumlaut: 0x0151,
michael@0 28446 oi: 0x01A3,
michael@0 28447 oinvertedbreve: 0x020F,
michael@0 28448 okatakana: 0x30AA,
michael@0 28449 okatakanahalfwidth: 0xFF75,
michael@0 28450 okorean: 0x3157,
michael@0 28451 olehebrew: 0x05AB,
michael@0 28452 omacron: 0x014D,
michael@0 28453 omacronacute: 0x1E53,
michael@0 28454 omacrongrave: 0x1E51,
michael@0 28455 omdeva: 0x0950,
michael@0 28456 omega: 0x03C9,
michael@0 28457 omega1: 0x03D6,
michael@0 28458 omegacyrillic: 0x0461,
michael@0 28459 omegalatinclosed: 0x0277,
michael@0 28460 omegaroundcyrillic: 0x047B,
michael@0 28461 omegatitlocyrillic: 0x047D,
michael@0 28462 omegatonos: 0x03CE,
michael@0 28463 omgujarati: 0x0AD0,
michael@0 28464 omicron: 0x03BF,
michael@0 28465 omicrontonos: 0x03CC,
michael@0 28466 omonospace: 0xFF4F,
michael@0 28467 one: 0x0031,
michael@0 28468 onearabic: 0x0661,
michael@0 28469 onebengali: 0x09E7,
michael@0 28470 onecircle: 0x2460,
michael@0 28471 onecircleinversesansserif: 0x278A,
michael@0 28472 onedeva: 0x0967,
michael@0 28473 onedotenleader: 0x2024,
michael@0 28474 oneeighth: 0x215B,
michael@0 28475 onefitted: 0xF6DC,
michael@0 28476 onegujarati: 0x0AE7,
michael@0 28477 onegurmukhi: 0x0A67,
michael@0 28478 onehackarabic: 0x0661,
michael@0 28479 onehalf: 0x00BD,
michael@0 28480 onehangzhou: 0x3021,
michael@0 28481 oneideographicparen: 0x3220,
michael@0 28482 oneinferior: 0x2081,
michael@0 28483 onemonospace: 0xFF11,
michael@0 28484 onenumeratorbengali: 0x09F4,
michael@0 28485 oneoldstyle: 0xF731,
michael@0 28486 oneparen: 0x2474,
michael@0 28487 oneperiod: 0x2488,
michael@0 28488 onepersian: 0x06F1,
michael@0 28489 onequarter: 0x00BC,
michael@0 28490 oneroman: 0x2170,
michael@0 28491 onesuperior: 0x00B9,
michael@0 28492 onethai: 0x0E51,
michael@0 28493 onethird: 0x2153,
michael@0 28494 oogonek: 0x01EB,
michael@0 28495 oogonekmacron: 0x01ED,
michael@0 28496 oogurmukhi: 0x0A13,
michael@0 28497 oomatragurmukhi: 0x0A4B,
michael@0 28498 oopen: 0x0254,
michael@0 28499 oparen: 0x24AA,
michael@0 28500 openbullet: 0x25E6,
michael@0 28501 option: 0x2325,
michael@0 28502 ordfeminine: 0x00AA,
michael@0 28503 ordmasculine: 0x00BA,
michael@0 28504 orthogonal: 0x221F,
michael@0 28505 oshortdeva: 0x0912,
michael@0 28506 oshortvowelsigndeva: 0x094A,
michael@0 28507 oslash: 0x00F8,
michael@0 28508 oslashacute: 0x01FF,
michael@0 28509 osmallhiragana: 0x3049,
michael@0 28510 osmallkatakana: 0x30A9,
michael@0 28511 osmallkatakanahalfwidth: 0xFF6B,
michael@0 28512 ostrokeacute: 0x01FF,
michael@0 28513 osuperior: 0xF6F0,
michael@0 28514 otcyrillic: 0x047F,
michael@0 28515 otilde: 0x00F5,
michael@0 28516 otildeacute: 0x1E4D,
michael@0 28517 otildedieresis: 0x1E4F,
michael@0 28518 oubopomofo: 0x3121,
michael@0 28519 overline: 0x203E,
michael@0 28520 overlinecenterline: 0xFE4A,
michael@0 28521 overlinecmb: 0x0305,
michael@0 28522 overlinedashed: 0xFE49,
michael@0 28523 overlinedblwavy: 0xFE4C,
michael@0 28524 overlinewavy: 0xFE4B,
michael@0 28525 overscore: 0x00AF,
michael@0 28526 ovowelsignbengali: 0x09CB,
michael@0 28527 ovowelsigndeva: 0x094B,
michael@0 28528 ovowelsigngujarati: 0x0ACB,
michael@0 28529 p: 0x0070,
michael@0 28530 paampssquare: 0x3380,
michael@0 28531 paasentosquare: 0x332B,
michael@0 28532 pabengali: 0x09AA,
michael@0 28533 pacute: 0x1E55,
michael@0 28534 padeva: 0x092A,
michael@0 28535 pagedown: 0x21DF,
michael@0 28536 pageup: 0x21DE,
michael@0 28537 pagujarati: 0x0AAA,
michael@0 28538 pagurmukhi: 0x0A2A,
michael@0 28539 pahiragana: 0x3071,
michael@0 28540 paiyannoithai: 0x0E2F,
michael@0 28541 pakatakana: 0x30D1,
michael@0 28542 palatalizationcyrilliccmb: 0x0484,
michael@0 28543 palochkacyrillic: 0x04C0,
michael@0 28544 pansioskorean: 0x317F,
michael@0 28545 paragraph: 0x00B6,
michael@0 28546 parallel: 0x2225,
michael@0 28547 parenleft: 0x0028,
michael@0 28548 parenleftaltonearabic: 0xFD3E,
michael@0 28549 parenleftbt: 0xF8ED,
michael@0 28550 parenleftex: 0xF8EC,
michael@0 28551 parenleftinferior: 0x208D,
michael@0 28552 parenleftmonospace: 0xFF08,
michael@0 28553 parenleftsmall: 0xFE59,
michael@0 28554 parenleftsuperior: 0x207D,
michael@0 28555 parenlefttp: 0xF8EB,
michael@0 28556 parenleftvertical: 0xFE35,
michael@0 28557 parenright: 0x0029,
michael@0 28558 parenrightaltonearabic: 0xFD3F,
michael@0 28559 parenrightbt: 0xF8F8,
michael@0 28560 parenrightex: 0xF8F7,
michael@0 28561 parenrightinferior: 0x208E,
michael@0 28562 parenrightmonospace: 0xFF09,
michael@0 28563 parenrightsmall: 0xFE5A,
michael@0 28564 parenrightsuperior: 0x207E,
michael@0 28565 parenrighttp: 0xF8F6,
michael@0 28566 parenrightvertical: 0xFE36,
michael@0 28567 partialdiff: 0x2202,
michael@0 28568 paseqhebrew: 0x05C0,
michael@0 28569 pashtahebrew: 0x0599,
michael@0 28570 pasquare: 0x33A9,
michael@0 28571 patah: 0x05B7,
michael@0 28572 patah11: 0x05B7,
michael@0 28573 patah1d: 0x05B7,
michael@0 28574 patah2a: 0x05B7,
michael@0 28575 patahhebrew: 0x05B7,
michael@0 28576 patahnarrowhebrew: 0x05B7,
michael@0 28577 patahquarterhebrew: 0x05B7,
michael@0 28578 patahwidehebrew: 0x05B7,
michael@0 28579 pazerhebrew: 0x05A1,
michael@0 28580 pbopomofo: 0x3106,
michael@0 28581 pcircle: 0x24DF,
michael@0 28582 pdotaccent: 0x1E57,
michael@0 28583 pe: 0x05E4,
michael@0 28584 pecyrillic: 0x043F,
michael@0 28585 pedagesh: 0xFB44,
michael@0 28586 pedageshhebrew: 0xFB44,
michael@0 28587 peezisquare: 0x333B,
michael@0 28588 pefinaldageshhebrew: 0xFB43,
michael@0 28589 peharabic: 0x067E,
michael@0 28590 peharmenian: 0x057A,
michael@0 28591 pehebrew: 0x05E4,
michael@0 28592 pehfinalarabic: 0xFB57,
michael@0 28593 pehinitialarabic: 0xFB58,
michael@0 28594 pehiragana: 0x307A,
michael@0 28595 pehmedialarabic: 0xFB59,
michael@0 28596 pekatakana: 0x30DA,
michael@0 28597 pemiddlehookcyrillic: 0x04A7,
michael@0 28598 perafehebrew: 0xFB4E,
michael@0 28599 percent: 0x0025,
michael@0 28600 percentarabic: 0x066A,
michael@0 28601 percentmonospace: 0xFF05,
michael@0 28602 percentsmall: 0xFE6A,
michael@0 28603 period: 0x002E,
michael@0 28604 periodarmenian: 0x0589,
michael@0 28605 periodcentered: 0x00B7,
michael@0 28606 periodhalfwidth: 0xFF61,
michael@0 28607 periodinferior: 0xF6E7,
michael@0 28608 periodmonospace: 0xFF0E,
michael@0 28609 periodsmall: 0xFE52,
michael@0 28610 periodsuperior: 0xF6E8,
michael@0 28611 perispomenigreekcmb: 0x0342,
michael@0 28612 perpendicular: 0x22A5,
michael@0 28613 perthousand: 0x2030,
michael@0 28614 peseta: 0x20A7,
michael@0 28615 pfsquare: 0x338A,
michael@0 28616 phabengali: 0x09AB,
michael@0 28617 phadeva: 0x092B,
michael@0 28618 phagujarati: 0x0AAB,
michael@0 28619 phagurmukhi: 0x0A2B,
michael@0 28620 phi: 0x03C6,
michael@0 28621 phi1: 0x03D5,
michael@0 28622 phieuphacirclekorean: 0x327A,
michael@0 28623 phieuphaparenkorean: 0x321A,
michael@0 28624 phieuphcirclekorean: 0x326C,
michael@0 28625 phieuphkorean: 0x314D,
michael@0 28626 phieuphparenkorean: 0x320C,
michael@0 28627 philatin: 0x0278,
michael@0 28628 phinthuthai: 0x0E3A,
michael@0 28629 phisymbolgreek: 0x03D5,
michael@0 28630 phook: 0x01A5,
michael@0 28631 phophanthai: 0x0E1E,
michael@0 28632 phophungthai: 0x0E1C,
michael@0 28633 phosamphaothai: 0x0E20,
michael@0 28634 pi: 0x03C0,
michael@0 28635 pieupacirclekorean: 0x3273,
michael@0 28636 pieupaparenkorean: 0x3213,
michael@0 28637 pieupcieuckorean: 0x3176,
michael@0 28638 pieupcirclekorean: 0x3265,
michael@0 28639 pieupkiyeokkorean: 0x3172,
michael@0 28640 pieupkorean: 0x3142,
michael@0 28641 pieupparenkorean: 0x3205,
michael@0 28642 pieupsioskiyeokkorean: 0x3174,
michael@0 28643 pieupsioskorean: 0x3144,
michael@0 28644 pieupsiostikeutkorean: 0x3175,
michael@0 28645 pieupthieuthkorean: 0x3177,
michael@0 28646 pieuptikeutkorean: 0x3173,
michael@0 28647 pihiragana: 0x3074,
michael@0 28648 pikatakana: 0x30D4,
michael@0 28649 pisymbolgreek: 0x03D6,
michael@0 28650 piwrarmenian: 0x0583,
michael@0 28651 plus: 0x002B,
michael@0 28652 plusbelowcmb: 0x031F,
michael@0 28653 pluscircle: 0x2295,
michael@0 28654 plusminus: 0x00B1,
michael@0 28655 plusmod: 0x02D6,
michael@0 28656 plusmonospace: 0xFF0B,
michael@0 28657 plussmall: 0xFE62,
michael@0 28658 plussuperior: 0x207A,
michael@0 28659 pmonospace: 0xFF50,
michael@0 28660 pmsquare: 0x33D8,
michael@0 28661 pohiragana: 0x307D,
michael@0 28662 pointingindexdownwhite: 0x261F,
michael@0 28663 pointingindexleftwhite: 0x261C,
michael@0 28664 pointingindexrightwhite: 0x261E,
michael@0 28665 pointingindexupwhite: 0x261D,
michael@0 28666 pokatakana: 0x30DD,
michael@0 28667 poplathai: 0x0E1B,
michael@0 28668 postalmark: 0x3012,
michael@0 28669 postalmarkface: 0x3020,
michael@0 28670 pparen: 0x24AB,
michael@0 28671 precedes: 0x227A,
michael@0 28672 prescription: 0x211E,
michael@0 28673 primemod: 0x02B9,
michael@0 28674 primereversed: 0x2035,
michael@0 28675 product: 0x220F,
michael@0 28676 projective: 0x2305,
michael@0 28677 prolongedkana: 0x30FC,
michael@0 28678 propellor: 0x2318,
michael@0 28679 propersubset: 0x2282,
michael@0 28680 propersuperset: 0x2283,
michael@0 28681 proportion: 0x2237,
michael@0 28682 proportional: 0x221D,
michael@0 28683 psi: 0x03C8,
michael@0 28684 psicyrillic: 0x0471,
michael@0 28685 psilipneumatacyrilliccmb: 0x0486,
michael@0 28686 pssquare: 0x33B0,
michael@0 28687 puhiragana: 0x3077,
michael@0 28688 pukatakana: 0x30D7,
michael@0 28689 pvsquare: 0x33B4,
michael@0 28690 pwsquare: 0x33BA,
michael@0 28691 q: 0x0071,
michael@0 28692 qadeva: 0x0958,
michael@0 28693 qadmahebrew: 0x05A8,
michael@0 28694 qafarabic: 0x0642,
michael@0 28695 qaffinalarabic: 0xFED6,
michael@0 28696 qafinitialarabic: 0xFED7,
michael@0 28697 qafmedialarabic: 0xFED8,
michael@0 28698 qamats: 0x05B8,
michael@0 28699 qamats10: 0x05B8,
michael@0 28700 qamats1a: 0x05B8,
michael@0 28701 qamats1c: 0x05B8,
michael@0 28702 qamats27: 0x05B8,
michael@0 28703 qamats29: 0x05B8,
michael@0 28704 qamats33: 0x05B8,
michael@0 28705 qamatsde: 0x05B8,
michael@0 28706 qamatshebrew: 0x05B8,
michael@0 28707 qamatsnarrowhebrew: 0x05B8,
michael@0 28708 qamatsqatanhebrew: 0x05B8,
michael@0 28709 qamatsqatannarrowhebrew: 0x05B8,
michael@0 28710 qamatsqatanquarterhebrew: 0x05B8,
michael@0 28711 qamatsqatanwidehebrew: 0x05B8,
michael@0 28712 qamatsquarterhebrew: 0x05B8,
michael@0 28713 qamatswidehebrew: 0x05B8,
michael@0 28714 qarneyparahebrew: 0x059F,
michael@0 28715 qbopomofo: 0x3111,
michael@0 28716 qcircle: 0x24E0,
michael@0 28717 qhook: 0x02A0,
michael@0 28718 qmonospace: 0xFF51,
michael@0 28719 qof: 0x05E7,
michael@0 28720 qofdagesh: 0xFB47,
michael@0 28721 qofdageshhebrew: 0xFB47,
michael@0 28722 qofhebrew: 0x05E7,
michael@0 28723 qparen: 0x24AC,
michael@0 28724 quarternote: 0x2669,
michael@0 28725 qubuts: 0x05BB,
michael@0 28726 qubuts18: 0x05BB,
michael@0 28727 qubuts25: 0x05BB,
michael@0 28728 qubuts31: 0x05BB,
michael@0 28729 qubutshebrew: 0x05BB,
michael@0 28730 qubutsnarrowhebrew: 0x05BB,
michael@0 28731 qubutsquarterhebrew: 0x05BB,
michael@0 28732 qubutswidehebrew: 0x05BB,
michael@0 28733 question: 0x003F,
michael@0 28734 questionarabic: 0x061F,
michael@0 28735 questionarmenian: 0x055E,
michael@0 28736 questiondown: 0x00BF,
michael@0 28737 questiondownsmall: 0xF7BF,
michael@0 28738 questiongreek: 0x037E,
michael@0 28739 questionmonospace: 0xFF1F,
michael@0 28740 questionsmall: 0xF73F,
michael@0 28741 quotedbl: 0x0022,
michael@0 28742 quotedblbase: 0x201E,
michael@0 28743 quotedblleft: 0x201C,
michael@0 28744 quotedblmonospace: 0xFF02,
michael@0 28745 quotedblprime: 0x301E,
michael@0 28746 quotedblprimereversed: 0x301D,
michael@0 28747 quotedblright: 0x201D,
michael@0 28748 quoteleft: 0x2018,
michael@0 28749 quoteleftreversed: 0x201B,
michael@0 28750 quotereversed: 0x201B,
michael@0 28751 quoteright: 0x2019,
michael@0 28752 quoterightn: 0x0149,
michael@0 28753 quotesinglbase: 0x201A,
michael@0 28754 quotesingle: 0x0027,
michael@0 28755 quotesinglemonospace: 0xFF07,
michael@0 28756 r: 0x0072,
michael@0 28757 raarmenian: 0x057C,
michael@0 28758 rabengali: 0x09B0,
michael@0 28759 racute: 0x0155,
michael@0 28760 radeva: 0x0930,
michael@0 28761 radical: 0x221A,
michael@0 28762 radicalex: 0xF8E5,
michael@0 28763 radoverssquare: 0x33AE,
michael@0 28764 radoverssquaredsquare: 0x33AF,
michael@0 28765 radsquare: 0x33AD,
michael@0 28766 rafe: 0x05BF,
michael@0 28767 rafehebrew: 0x05BF,
michael@0 28768 ragujarati: 0x0AB0,
michael@0 28769 ragurmukhi: 0x0A30,
michael@0 28770 rahiragana: 0x3089,
michael@0 28771 rakatakana: 0x30E9,
michael@0 28772 rakatakanahalfwidth: 0xFF97,
michael@0 28773 ralowerdiagonalbengali: 0x09F1,
michael@0 28774 ramiddlediagonalbengali: 0x09F0,
michael@0 28775 ramshorn: 0x0264,
michael@0 28776 ratio: 0x2236,
michael@0 28777 rbopomofo: 0x3116,
michael@0 28778 rcaron: 0x0159,
michael@0 28779 rcedilla: 0x0157,
michael@0 28780 rcircle: 0x24E1,
michael@0 28781 rcommaaccent: 0x0157,
michael@0 28782 rdblgrave: 0x0211,
michael@0 28783 rdotaccent: 0x1E59,
michael@0 28784 rdotbelow: 0x1E5B,
michael@0 28785 rdotbelowmacron: 0x1E5D,
michael@0 28786 referencemark: 0x203B,
michael@0 28787 reflexsubset: 0x2286,
michael@0 28788 reflexsuperset: 0x2287,
michael@0 28789 registered: 0x00AE,
michael@0 28790 registersans: 0xF8E8,
michael@0 28791 registerserif: 0xF6DA,
michael@0 28792 reharabic: 0x0631,
michael@0 28793 reharmenian: 0x0580,
michael@0 28794 rehfinalarabic: 0xFEAE,
michael@0 28795 rehiragana: 0x308C,
michael@0 28796 rekatakana: 0x30EC,
michael@0 28797 rekatakanahalfwidth: 0xFF9A,
michael@0 28798 resh: 0x05E8,
michael@0 28799 reshdageshhebrew: 0xFB48,
michael@0 28800 reshhebrew: 0x05E8,
michael@0 28801 reversedtilde: 0x223D,
michael@0 28802 reviahebrew: 0x0597,
michael@0 28803 reviamugrashhebrew: 0x0597,
michael@0 28804 revlogicalnot: 0x2310,
michael@0 28805 rfishhook: 0x027E,
michael@0 28806 rfishhookreversed: 0x027F,
michael@0 28807 rhabengali: 0x09DD,
michael@0 28808 rhadeva: 0x095D,
michael@0 28809 rho: 0x03C1,
michael@0 28810 rhook: 0x027D,
michael@0 28811 rhookturned: 0x027B,
michael@0 28812 rhookturnedsuperior: 0x02B5,
michael@0 28813 rhosymbolgreek: 0x03F1,
michael@0 28814 rhotichookmod: 0x02DE,
michael@0 28815 rieulacirclekorean: 0x3271,
michael@0 28816 rieulaparenkorean: 0x3211,
michael@0 28817 rieulcirclekorean: 0x3263,
michael@0 28818 rieulhieuhkorean: 0x3140,
michael@0 28819 rieulkiyeokkorean: 0x313A,
michael@0 28820 rieulkiyeoksioskorean: 0x3169,
michael@0 28821 rieulkorean: 0x3139,
michael@0 28822 rieulmieumkorean: 0x313B,
michael@0 28823 rieulpansioskorean: 0x316C,
michael@0 28824 rieulparenkorean: 0x3203,
michael@0 28825 rieulphieuphkorean: 0x313F,
michael@0 28826 rieulpieupkorean: 0x313C,
michael@0 28827 rieulpieupsioskorean: 0x316B,
michael@0 28828 rieulsioskorean: 0x313D,
michael@0 28829 rieulthieuthkorean: 0x313E,
michael@0 28830 rieultikeutkorean: 0x316A,
michael@0 28831 rieulyeorinhieuhkorean: 0x316D,
michael@0 28832 rightangle: 0x221F,
michael@0 28833 righttackbelowcmb: 0x0319,
michael@0 28834 righttriangle: 0x22BF,
michael@0 28835 rihiragana: 0x308A,
michael@0 28836 rikatakana: 0x30EA,
michael@0 28837 rikatakanahalfwidth: 0xFF98,
michael@0 28838 ring: 0x02DA,
michael@0 28839 ringbelowcmb: 0x0325,
michael@0 28840 ringcmb: 0x030A,
michael@0 28841 ringhalfleft: 0x02BF,
michael@0 28842 ringhalfleftarmenian: 0x0559,
michael@0 28843 ringhalfleftbelowcmb: 0x031C,
michael@0 28844 ringhalfleftcentered: 0x02D3,
michael@0 28845 ringhalfright: 0x02BE,
michael@0 28846 ringhalfrightbelowcmb: 0x0339,
michael@0 28847 ringhalfrightcentered: 0x02D2,
michael@0 28848 rinvertedbreve: 0x0213,
michael@0 28849 rittorusquare: 0x3351,
michael@0 28850 rlinebelow: 0x1E5F,
michael@0 28851 rlongleg: 0x027C,
michael@0 28852 rlonglegturned: 0x027A,
michael@0 28853 rmonospace: 0xFF52,
michael@0 28854 rohiragana: 0x308D,
michael@0 28855 rokatakana: 0x30ED,
michael@0 28856 rokatakanahalfwidth: 0xFF9B,
michael@0 28857 roruathai: 0x0E23,
michael@0 28858 rparen: 0x24AD,
michael@0 28859 rrabengali: 0x09DC,
michael@0 28860 rradeva: 0x0931,
michael@0 28861 rragurmukhi: 0x0A5C,
michael@0 28862 rreharabic: 0x0691,
michael@0 28863 rrehfinalarabic: 0xFB8D,
michael@0 28864 rrvocalicbengali: 0x09E0,
michael@0 28865 rrvocalicdeva: 0x0960,
michael@0 28866 rrvocalicgujarati: 0x0AE0,
michael@0 28867 rrvocalicvowelsignbengali: 0x09C4,
michael@0 28868 rrvocalicvowelsigndeva: 0x0944,
michael@0 28869 rrvocalicvowelsigngujarati: 0x0AC4,
michael@0 28870 rsuperior: 0xF6F1,
michael@0 28871 rtblock: 0x2590,
michael@0 28872 rturned: 0x0279,
michael@0 28873 rturnedsuperior: 0x02B4,
michael@0 28874 ruhiragana: 0x308B,
michael@0 28875 rukatakana: 0x30EB,
michael@0 28876 rukatakanahalfwidth: 0xFF99,
michael@0 28877 rupeemarkbengali: 0x09F2,
michael@0 28878 rupeesignbengali: 0x09F3,
michael@0 28879 rupiah: 0xF6DD,
michael@0 28880 ruthai: 0x0E24,
michael@0 28881 rvocalicbengali: 0x098B,
michael@0 28882 rvocalicdeva: 0x090B,
michael@0 28883 rvocalicgujarati: 0x0A8B,
michael@0 28884 rvocalicvowelsignbengali: 0x09C3,
michael@0 28885 rvocalicvowelsigndeva: 0x0943,
michael@0 28886 rvocalicvowelsigngujarati: 0x0AC3,
michael@0 28887 s: 0x0073,
michael@0 28888 sabengali: 0x09B8,
michael@0 28889 sacute: 0x015B,
michael@0 28890 sacutedotaccent: 0x1E65,
michael@0 28891 sadarabic: 0x0635,
michael@0 28892 sadeva: 0x0938,
michael@0 28893 sadfinalarabic: 0xFEBA,
michael@0 28894 sadinitialarabic: 0xFEBB,
michael@0 28895 sadmedialarabic: 0xFEBC,
michael@0 28896 sagujarati: 0x0AB8,
michael@0 28897 sagurmukhi: 0x0A38,
michael@0 28898 sahiragana: 0x3055,
michael@0 28899 sakatakana: 0x30B5,
michael@0 28900 sakatakanahalfwidth: 0xFF7B,
michael@0 28901 sallallahoualayhewasallamarabic: 0xFDFA,
michael@0 28902 samekh: 0x05E1,
michael@0 28903 samekhdagesh: 0xFB41,
michael@0 28904 samekhdageshhebrew: 0xFB41,
michael@0 28905 samekhhebrew: 0x05E1,
michael@0 28906 saraaathai: 0x0E32,
michael@0 28907 saraaethai: 0x0E41,
michael@0 28908 saraaimaimalaithai: 0x0E44,
michael@0 28909 saraaimaimuanthai: 0x0E43,
michael@0 28910 saraamthai: 0x0E33,
michael@0 28911 saraathai: 0x0E30,
michael@0 28912 saraethai: 0x0E40,
michael@0 28913 saraiileftthai: 0xF886,
michael@0 28914 saraiithai: 0x0E35,
michael@0 28915 saraileftthai: 0xF885,
michael@0 28916 saraithai: 0x0E34,
michael@0 28917 saraothai: 0x0E42,
michael@0 28918 saraueeleftthai: 0xF888,
michael@0 28919 saraueethai: 0x0E37,
michael@0 28920 saraueleftthai: 0xF887,
michael@0 28921 sarauethai: 0x0E36,
michael@0 28922 sarauthai: 0x0E38,
michael@0 28923 sarauuthai: 0x0E39,
michael@0 28924 sbopomofo: 0x3119,
michael@0 28925 scaron: 0x0161,
michael@0 28926 scarondotaccent: 0x1E67,
michael@0 28927 scedilla: 0x015F,
michael@0 28928 schwa: 0x0259,
michael@0 28929 schwacyrillic: 0x04D9,
michael@0 28930 schwadieresiscyrillic: 0x04DB,
michael@0 28931 schwahook: 0x025A,
michael@0 28932 scircle: 0x24E2,
michael@0 28933 scircumflex: 0x015D,
michael@0 28934 scommaaccent: 0x0219,
michael@0 28935 sdotaccent: 0x1E61,
michael@0 28936 sdotbelow: 0x1E63,
michael@0 28937 sdotbelowdotaccent: 0x1E69,
michael@0 28938 seagullbelowcmb: 0x033C,
michael@0 28939 second: 0x2033,
michael@0 28940 secondtonechinese: 0x02CA,
michael@0 28941 section: 0x00A7,
michael@0 28942 seenarabic: 0x0633,
michael@0 28943 seenfinalarabic: 0xFEB2,
michael@0 28944 seeninitialarabic: 0xFEB3,
michael@0 28945 seenmedialarabic: 0xFEB4,
michael@0 28946 segol: 0x05B6,
michael@0 28947 segol13: 0x05B6,
michael@0 28948 segol1f: 0x05B6,
michael@0 28949 segol2c: 0x05B6,
michael@0 28950 segolhebrew: 0x05B6,
michael@0 28951 segolnarrowhebrew: 0x05B6,
michael@0 28952 segolquarterhebrew: 0x05B6,
michael@0 28953 segoltahebrew: 0x0592,
michael@0 28954 segolwidehebrew: 0x05B6,
michael@0 28955 seharmenian: 0x057D,
michael@0 28956 sehiragana: 0x305B,
michael@0 28957 sekatakana: 0x30BB,
michael@0 28958 sekatakanahalfwidth: 0xFF7E,
michael@0 28959 semicolon: 0x003B,
michael@0 28960 semicolonarabic: 0x061B,
michael@0 28961 semicolonmonospace: 0xFF1B,
michael@0 28962 semicolonsmall: 0xFE54,
michael@0 28963 semivoicedmarkkana: 0x309C,
michael@0 28964 semivoicedmarkkanahalfwidth: 0xFF9F,
michael@0 28965 sentisquare: 0x3322,
michael@0 28966 sentosquare: 0x3323,
michael@0 28967 seven: 0x0037,
michael@0 28968 sevenarabic: 0x0667,
michael@0 28969 sevenbengali: 0x09ED,
michael@0 28970 sevencircle: 0x2466,
michael@0 28971 sevencircleinversesansserif: 0x2790,
michael@0 28972 sevendeva: 0x096D,
michael@0 28973 seveneighths: 0x215E,
michael@0 28974 sevengujarati: 0x0AED,
michael@0 28975 sevengurmukhi: 0x0A6D,
michael@0 28976 sevenhackarabic: 0x0667,
michael@0 28977 sevenhangzhou: 0x3027,
michael@0 28978 sevenideographicparen: 0x3226,
michael@0 28979 seveninferior: 0x2087,
michael@0 28980 sevenmonospace: 0xFF17,
michael@0 28981 sevenoldstyle: 0xF737,
michael@0 28982 sevenparen: 0x247A,
michael@0 28983 sevenperiod: 0x248E,
michael@0 28984 sevenpersian: 0x06F7,
michael@0 28985 sevenroman: 0x2176,
michael@0 28986 sevensuperior: 0x2077,
michael@0 28987 seventeencircle: 0x2470,
michael@0 28988 seventeenparen: 0x2484,
michael@0 28989 seventeenperiod: 0x2498,
michael@0 28990 seventhai: 0x0E57,
michael@0 28991 sfthyphen: 0x00AD,
michael@0 28992 shaarmenian: 0x0577,
michael@0 28993 shabengali: 0x09B6,
michael@0 28994 shacyrillic: 0x0448,
michael@0 28995 shaddaarabic: 0x0651,
michael@0 28996 shaddadammaarabic: 0xFC61,
michael@0 28997 shaddadammatanarabic: 0xFC5E,
michael@0 28998 shaddafathaarabic: 0xFC60,
michael@0 28999 shaddakasraarabic: 0xFC62,
michael@0 29000 shaddakasratanarabic: 0xFC5F,
michael@0 29001 shade: 0x2592,
michael@0 29002 shadedark: 0x2593,
michael@0 29003 shadelight: 0x2591,
michael@0 29004 shademedium: 0x2592,
michael@0 29005 shadeva: 0x0936,
michael@0 29006 shagujarati: 0x0AB6,
michael@0 29007 shagurmukhi: 0x0A36,
michael@0 29008 shalshelethebrew: 0x0593,
michael@0 29009 shbopomofo: 0x3115,
michael@0 29010 shchacyrillic: 0x0449,
michael@0 29011 sheenarabic: 0x0634,
michael@0 29012 sheenfinalarabic: 0xFEB6,
michael@0 29013 sheeninitialarabic: 0xFEB7,
michael@0 29014 sheenmedialarabic: 0xFEB8,
michael@0 29015 sheicoptic: 0x03E3,
michael@0 29016 sheqel: 0x20AA,
michael@0 29017 sheqelhebrew: 0x20AA,
michael@0 29018 sheva: 0x05B0,
michael@0 29019 sheva115: 0x05B0,
michael@0 29020 sheva15: 0x05B0,
michael@0 29021 sheva22: 0x05B0,
michael@0 29022 sheva2e: 0x05B0,
michael@0 29023 shevahebrew: 0x05B0,
michael@0 29024 shevanarrowhebrew: 0x05B0,
michael@0 29025 shevaquarterhebrew: 0x05B0,
michael@0 29026 shevawidehebrew: 0x05B0,
michael@0 29027 shhacyrillic: 0x04BB,
michael@0 29028 shimacoptic: 0x03ED,
michael@0 29029 shin: 0x05E9,
michael@0 29030 shindagesh: 0xFB49,
michael@0 29031 shindageshhebrew: 0xFB49,
michael@0 29032 shindageshshindot: 0xFB2C,
michael@0 29033 shindageshshindothebrew: 0xFB2C,
michael@0 29034 shindageshsindot: 0xFB2D,
michael@0 29035 shindageshsindothebrew: 0xFB2D,
michael@0 29036 shindothebrew: 0x05C1,
michael@0 29037 shinhebrew: 0x05E9,
michael@0 29038 shinshindot: 0xFB2A,
michael@0 29039 shinshindothebrew: 0xFB2A,
michael@0 29040 shinsindot: 0xFB2B,
michael@0 29041 shinsindothebrew: 0xFB2B,
michael@0 29042 shook: 0x0282,
michael@0 29043 sigma: 0x03C3,
michael@0 29044 sigma1: 0x03C2,
michael@0 29045 sigmafinal: 0x03C2,
michael@0 29046 sigmalunatesymbolgreek: 0x03F2,
michael@0 29047 sihiragana: 0x3057,
michael@0 29048 sikatakana: 0x30B7,
michael@0 29049 sikatakanahalfwidth: 0xFF7C,
michael@0 29050 siluqhebrew: 0x05BD,
michael@0 29051 siluqlefthebrew: 0x05BD,
michael@0 29052 similar: 0x223C,
michael@0 29053 sindothebrew: 0x05C2,
michael@0 29054 siosacirclekorean: 0x3274,
michael@0 29055 siosaparenkorean: 0x3214,
michael@0 29056 sioscieuckorean: 0x317E,
michael@0 29057 sioscirclekorean: 0x3266,
michael@0 29058 sioskiyeokkorean: 0x317A,
michael@0 29059 sioskorean: 0x3145,
michael@0 29060 siosnieunkorean: 0x317B,
michael@0 29061 siosparenkorean: 0x3206,
michael@0 29062 siospieupkorean: 0x317D,
michael@0 29063 siostikeutkorean: 0x317C,
michael@0 29064 six: 0x0036,
michael@0 29065 sixarabic: 0x0666,
michael@0 29066 sixbengali: 0x09EC,
michael@0 29067 sixcircle: 0x2465,
michael@0 29068 sixcircleinversesansserif: 0x278F,
michael@0 29069 sixdeva: 0x096C,
michael@0 29070 sixgujarati: 0x0AEC,
michael@0 29071 sixgurmukhi: 0x0A6C,
michael@0 29072 sixhackarabic: 0x0666,
michael@0 29073 sixhangzhou: 0x3026,
michael@0 29074 sixideographicparen: 0x3225,
michael@0 29075 sixinferior: 0x2086,
michael@0 29076 sixmonospace: 0xFF16,
michael@0 29077 sixoldstyle: 0xF736,
michael@0 29078 sixparen: 0x2479,
michael@0 29079 sixperiod: 0x248D,
michael@0 29080 sixpersian: 0x06F6,
michael@0 29081 sixroman: 0x2175,
michael@0 29082 sixsuperior: 0x2076,
michael@0 29083 sixteencircle: 0x246F,
michael@0 29084 sixteencurrencydenominatorbengali: 0x09F9,
michael@0 29085 sixteenparen: 0x2483,
michael@0 29086 sixteenperiod: 0x2497,
michael@0 29087 sixthai: 0x0E56,
michael@0 29088 slash: 0x002F,
michael@0 29089 slashmonospace: 0xFF0F,
michael@0 29090 slong: 0x017F,
michael@0 29091 slongdotaccent: 0x1E9B,
michael@0 29092 smileface: 0x263A,
michael@0 29093 smonospace: 0xFF53,
michael@0 29094 sofpasuqhebrew: 0x05C3,
michael@0 29095 softhyphen: 0x00AD,
michael@0 29096 softsigncyrillic: 0x044C,
michael@0 29097 sohiragana: 0x305D,
michael@0 29098 sokatakana: 0x30BD,
michael@0 29099 sokatakanahalfwidth: 0xFF7F,
michael@0 29100 soliduslongoverlaycmb: 0x0338,
michael@0 29101 solidusshortoverlaycmb: 0x0337,
michael@0 29102 sorusithai: 0x0E29,
michael@0 29103 sosalathai: 0x0E28,
michael@0 29104 sosothai: 0x0E0B,
michael@0 29105 sosuathai: 0x0E2A,
michael@0 29106 space: 0x0020,
michael@0 29107 spacehackarabic: 0x0020,
michael@0 29108 spade: 0x2660,
michael@0 29109 spadesuitblack: 0x2660,
michael@0 29110 spadesuitwhite: 0x2664,
michael@0 29111 sparen: 0x24AE,
michael@0 29112 squarebelowcmb: 0x033B,
michael@0 29113 squarecc: 0x33C4,
michael@0 29114 squarecm: 0x339D,
michael@0 29115 squarediagonalcrosshatchfill: 0x25A9,
michael@0 29116 squarehorizontalfill: 0x25A4,
michael@0 29117 squarekg: 0x338F,
michael@0 29118 squarekm: 0x339E,
michael@0 29119 squarekmcapital: 0x33CE,
michael@0 29120 squareln: 0x33D1,
michael@0 29121 squarelog: 0x33D2,
michael@0 29122 squaremg: 0x338E,
michael@0 29123 squaremil: 0x33D5,
michael@0 29124 squaremm: 0x339C,
michael@0 29125 squaremsquared: 0x33A1,
michael@0 29126 squareorthogonalcrosshatchfill: 0x25A6,
michael@0 29127 squareupperlefttolowerrightfill: 0x25A7,
michael@0 29128 squareupperrighttolowerleftfill: 0x25A8,
michael@0 29129 squareverticalfill: 0x25A5,
michael@0 29130 squarewhitewithsmallblack: 0x25A3,
michael@0 29131 srsquare: 0x33DB,
michael@0 29132 ssabengali: 0x09B7,
michael@0 29133 ssadeva: 0x0937,
michael@0 29134 ssagujarati: 0x0AB7,
michael@0 29135 ssangcieuckorean: 0x3149,
michael@0 29136 ssanghieuhkorean: 0x3185,
michael@0 29137 ssangieungkorean: 0x3180,
michael@0 29138 ssangkiyeokkorean: 0x3132,
michael@0 29139 ssangnieunkorean: 0x3165,
michael@0 29140 ssangpieupkorean: 0x3143,
michael@0 29141 ssangsioskorean: 0x3146,
michael@0 29142 ssangtikeutkorean: 0x3138,
michael@0 29143 ssuperior: 0xF6F2,
michael@0 29144 sterling: 0x00A3,
michael@0 29145 sterlingmonospace: 0xFFE1,
michael@0 29146 strokelongoverlaycmb: 0x0336,
michael@0 29147 strokeshortoverlaycmb: 0x0335,
michael@0 29148 subset: 0x2282,
michael@0 29149 subsetnotequal: 0x228A,
michael@0 29150 subsetorequal: 0x2286,
michael@0 29151 succeeds: 0x227B,
michael@0 29152 suchthat: 0x220B,
michael@0 29153 suhiragana: 0x3059,
michael@0 29154 sukatakana: 0x30B9,
michael@0 29155 sukatakanahalfwidth: 0xFF7D,
michael@0 29156 sukunarabic: 0x0652,
michael@0 29157 summation: 0x2211,
michael@0 29158 sun: 0x263C,
michael@0 29159 superset: 0x2283,
michael@0 29160 supersetnotequal: 0x228B,
michael@0 29161 supersetorequal: 0x2287,
michael@0 29162 svsquare: 0x33DC,
michael@0 29163 syouwaerasquare: 0x337C,
michael@0 29164 t: 0x0074,
michael@0 29165 tabengali: 0x09A4,
michael@0 29166 tackdown: 0x22A4,
michael@0 29167 tackleft: 0x22A3,
michael@0 29168 tadeva: 0x0924,
michael@0 29169 tagujarati: 0x0AA4,
michael@0 29170 tagurmukhi: 0x0A24,
michael@0 29171 taharabic: 0x0637,
michael@0 29172 tahfinalarabic: 0xFEC2,
michael@0 29173 tahinitialarabic: 0xFEC3,
michael@0 29174 tahiragana: 0x305F,
michael@0 29175 tahmedialarabic: 0xFEC4,
michael@0 29176 taisyouerasquare: 0x337D,
michael@0 29177 takatakana: 0x30BF,
michael@0 29178 takatakanahalfwidth: 0xFF80,
michael@0 29179 tatweelarabic: 0x0640,
michael@0 29180 tau: 0x03C4,
michael@0 29181 tav: 0x05EA,
michael@0 29182 tavdages: 0xFB4A,
michael@0 29183 tavdagesh: 0xFB4A,
michael@0 29184 tavdageshhebrew: 0xFB4A,
michael@0 29185 tavhebrew: 0x05EA,
michael@0 29186 tbar: 0x0167,
michael@0 29187 tbopomofo: 0x310A,
michael@0 29188 tcaron: 0x0165,
michael@0 29189 tccurl: 0x02A8,
michael@0 29190 tcedilla: 0x0163,
michael@0 29191 tcheharabic: 0x0686,
michael@0 29192 tchehfinalarabic: 0xFB7B,
michael@0 29193 tchehinitialarabic: 0xFB7C,
michael@0 29194 tchehmedialarabic: 0xFB7D,
michael@0 29195 tcircle: 0x24E3,
michael@0 29196 tcircumflexbelow: 0x1E71,
michael@0 29197 tcommaaccent: 0x0163,
michael@0 29198 tdieresis: 0x1E97,
michael@0 29199 tdotaccent: 0x1E6B,
michael@0 29200 tdotbelow: 0x1E6D,
michael@0 29201 tecyrillic: 0x0442,
michael@0 29202 tedescendercyrillic: 0x04AD,
michael@0 29203 teharabic: 0x062A,
michael@0 29204 tehfinalarabic: 0xFE96,
michael@0 29205 tehhahinitialarabic: 0xFCA2,
michael@0 29206 tehhahisolatedarabic: 0xFC0C,
michael@0 29207 tehinitialarabic: 0xFE97,
michael@0 29208 tehiragana: 0x3066,
michael@0 29209 tehjeeminitialarabic: 0xFCA1,
michael@0 29210 tehjeemisolatedarabic: 0xFC0B,
michael@0 29211 tehmarbutaarabic: 0x0629,
michael@0 29212 tehmarbutafinalarabic: 0xFE94,
michael@0 29213 tehmedialarabic: 0xFE98,
michael@0 29214 tehmeeminitialarabic: 0xFCA4,
michael@0 29215 tehmeemisolatedarabic: 0xFC0E,
michael@0 29216 tehnoonfinalarabic: 0xFC73,
michael@0 29217 tekatakana: 0x30C6,
michael@0 29218 tekatakanahalfwidth: 0xFF83,
michael@0 29219 telephone: 0x2121,
michael@0 29220 telephoneblack: 0x260E,
michael@0 29221 telishagedolahebrew: 0x05A0,
michael@0 29222 telishaqetanahebrew: 0x05A9,
michael@0 29223 tencircle: 0x2469,
michael@0 29224 tenideographicparen: 0x3229,
michael@0 29225 tenparen: 0x247D,
michael@0 29226 tenperiod: 0x2491,
michael@0 29227 tenroman: 0x2179,
michael@0 29228 tesh: 0x02A7,
michael@0 29229 tet: 0x05D8,
michael@0 29230 tetdagesh: 0xFB38,
michael@0 29231 tetdageshhebrew: 0xFB38,
michael@0 29232 tethebrew: 0x05D8,
michael@0 29233 tetsecyrillic: 0x04B5,
michael@0 29234 tevirhebrew: 0x059B,
michael@0 29235 tevirlefthebrew: 0x059B,
michael@0 29236 thabengali: 0x09A5,
michael@0 29237 thadeva: 0x0925,
michael@0 29238 thagujarati: 0x0AA5,
michael@0 29239 thagurmukhi: 0x0A25,
michael@0 29240 thalarabic: 0x0630,
michael@0 29241 thalfinalarabic: 0xFEAC,
michael@0 29242 thanthakhatlowleftthai: 0xF898,
michael@0 29243 thanthakhatlowrightthai: 0xF897,
michael@0 29244 thanthakhatthai: 0x0E4C,
michael@0 29245 thanthakhatupperleftthai: 0xF896,
michael@0 29246 theharabic: 0x062B,
michael@0 29247 thehfinalarabic: 0xFE9A,
michael@0 29248 thehinitialarabic: 0xFE9B,
michael@0 29249 thehmedialarabic: 0xFE9C,
michael@0 29250 thereexists: 0x2203,
michael@0 29251 therefore: 0x2234,
michael@0 29252 theta: 0x03B8,
michael@0 29253 theta1: 0x03D1,
michael@0 29254 thetasymbolgreek: 0x03D1,
michael@0 29255 thieuthacirclekorean: 0x3279,
michael@0 29256 thieuthaparenkorean: 0x3219,
michael@0 29257 thieuthcirclekorean: 0x326B,
michael@0 29258 thieuthkorean: 0x314C,
michael@0 29259 thieuthparenkorean: 0x320B,
michael@0 29260 thirteencircle: 0x246C,
michael@0 29261 thirteenparen: 0x2480,
michael@0 29262 thirteenperiod: 0x2494,
michael@0 29263 thonangmonthothai: 0x0E11,
michael@0 29264 thook: 0x01AD,
michael@0 29265 thophuthaothai: 0x0E12,
michael@0 29266 thorn: 0x00FE,
michael@0 29267 thothahanthai: 0x0E17,
michael@0 29268 thothanthai: 0x0E10,
michael@0 29269 thothongthai: 0x0E18,
michael@0 29270 thothungthai: 0x0E16,
michael@0 29271 thousandcyrillic: 0x0482,
michael@0 29272 thousandsseparatorarabic: 0x066C,
michael@0 29273 thousandsseparatorpersian: 0x066C,
michael@0 29274 three: 0x0033,
michael@0 29275 threearabic: 0x0663,
michael@0 29276 threebengali: 0x09E9,
michael@0 29277 threecircle: 0x2462,
michael@0 29278 threecircleinversesansserif: 0x278C,
michael@0 29279 threedeva: 0x0969,
michael@0 29280 threeeighths: 0x215C,
michael@0 29281 threegujarati: 0x0AE9,
michael@0 29282 threegurmukhi: 0x0A69,
michael@0 29283 threehackarabic: 0x0663,
michael@0 29284 threehangzhou: 0x3023,
michael@0 29285 threeideographicparen: 0x3222,
michael@0 29286 threeinferior: 0x2083,
michael@0 29287 threemonospace: 0xFF13,
michael@0 29288 threenumeratorbengali: 0x09F6,
michael@0 29289 threeoldstyle: 0xF733,
michael@0 29290 threeparen: 0x2476,
michael@0 29291 threeperiod: 0x248A,
michael@0 29292 threepersian: 0x06F3,
michael@0 29293 threequarters: 0x00BE,
michael@0 29294 threequartersemdash: 0xF6DE,
michael@0 29295 threeroman: 0x2172,
michael@0 29296 threesuperior: 0x00B3,
michael@0 29297 threethai: 0x0E53,
michael@0 29298 thzsquare: 0x3394,
michael@0 29299 tihiragana: 0x3061,
michael@0 29300 tikatakana: 0x30C1,
michael@0 29301 tikatakanahalfwidth: 0xFF81,
michael@0 29302 tikeutacirclekorean: 0x3270,
michael@0 29303 tikeutaparenkorean: 0x3210,
michael@0 29304 tikeutcirclekorean: 0x3262,
michael@0 29305 tikeutkorean: 0x3137,
michael@0 29306 tikeutparenkorean: 0x3202,
michael@0 29307 tilde: 0x02DC,
michael@0 29308 tildebelowcmb: 0x0330,
michael@0 29309 tildecmb: 0x0303,
michael@0 29310 tildecomb: 0x0303,
michael@0 29311 tildedoublecmb: 0x0360,
michael@0 29312 tildeoperator: 0x223C,
michael@0 29313 tildeoverlaycmb: 0x0334,
michael@0 29314 tildeverticalcmb: 0x033E,
michael@0 29315 timescircle: 0x2297,
michael@0 29316 tipehahebrew: 0x0596,
michael@0 29317 tipehalefthebrew: 0x0596,
michael@0 29318 tippigurmukhi: 0x0A70,
michael@0 29319 titlocyrilliccmb: 0x0483,
michael@0 29320 tiwnarmenian: 0x057F,
michael@0 29321 tlinebelow: 0x1E6F,
michael@0 29322 tmonospace: 0xFF54,
michael@0 29323 toarmenian: 0x0569,
michael@0 29324 tohiragana: 0x3068,
michael@0 29325 tokatakana: 0x30C8,
michael@0 29326 tokatakanahalfwidth: 0xFF84,
michael@0 29327 tonebarextrahighmod: 0x02E5,
michael@0 29328 tonebarextralowmod: 0x02E9,
michael@0 29329 tonebarhighmod: 0x02E6,
michael@0 29330 tonebarlowmod: 0x02E8,
michael@0 29331 tonebarmidmod: 0x02E7,
michael@0 29332 tonefive: 0x01BD,
michael@0 29333 tonesix: 0x0185,
michael@0 29334 tonetwo: 0x01A8,
michael@0 29335 tonos: 0x0384,
michael@0 29336 tonsquare: 0x3327,
michael@0 29337 topatakthai: 0x0E0F,
michael@0 29338 tortoiseshellbracketleft: 0x3014,
michael@0 29339 tortoiseshellbracketleftsmall: 0xFE5D,
michael@0 29340 tortoiseshellbracketleftvertical: 0xFE39,
michael@0 29341 tortoiseshellbracketright: 0x3015,
michael@0 29342 tortoiseshellbracketrightsmall: 0xFE5E,
michael@0 29343 tortoiseshellbracketrightvertical: 0xFE3A,
michael@0 29344 totaothai: 0x0E15,
michael@0 29345 tpalatalhook: 0x01AB,
michael@0 29346 tparen: 0x24AF,
michael@0 29347 trademark: 0x2122,
michael@0 29348 trademarksans: 0xF8EA,
michael@0 29349 trademarkserif: 0xF6DB,
michael@0 29350 tretroflexhook: 0x0288,
michael@0 29351 triagdn: 0x25BC,
michael@0 29352 triaglf: 0x25C4,
michael@0 29353 triagrt: 0x25BA,
michael@0 29354 triagup: 0x25B2,
michael@0 29355 ts: 0x02A6,
michael@0 29356 tsadi: 0x05E6,
michael@0 29357 tsadidagesh: 0xFB46,
michael@0 29358 tsadidageshhebrew: 0xFB46,
michael@0 29359 tsadihebrew: 0x05E6,
michael@0 29360 tsecyrillic: 0x0446,
michael@0 29361 tsere: 0x05B5,
michael@0 29362 tsere12: 0x05B5,
michael@0 29363 tsere1e: 0x05B5,
michael@0 29364 tsere2b: 0x05B5,
michael@0 29365 tserehebrew: 0x05B5,
michael@0 29366 tserenarrowhebrew: 0x05B5,
michael@0 29367 tserequarterhebrew: 0x05B5,
michael@0 29368 tserewidehebrew: 0x05B5,
michael@0 29369 tshecyrillic: 0x045B,
michael@0 29370 tsuperior: 0xF6F3,
michael@0 29371 ttabengali: 0x099F,
michael@0 29372 ttadeva: 0x091F,
michael@0 29373 ttagujarati: 0x0A9F,
michael@0 29374 ttagurmukhi: 0x0A1F,
michael@0 29375 tteharabic: 0x0679,
michael@0 29376 ttehfinalarabic: 0xFB67,
michael@0 29377 ttehinitialarabic: 0xFB68,
michael@0 29378 ttehmedialarabic: 0xFB69,
michael@0 29379 tthabengali: 0x09A0,
michael@0 29380 tthadeva: 0x0920,
michael@0 29381 tthagujarati: 0x0AA0,
michael@0 29382 tthagurmukhi: 0x0A20,
michael@0 29383 tturned: 0x0287,
michael@0 29384 tuhiragana: 0x3064,
michael@0 29385 tukatakana: 0x30C4,
michael@0 29386 tukatakanahalfwidth: 0xFF82,
michael@0 29387 tusmallhiragana: 0x3063,
michael@0 29388 tusmallkatakana: 0x30C3,
michael@0 29389 tusmallkatakanahalfwidth: 0xFF6F,
michael@0 29390 twelvecircle: 0x246B,
michael@0 29391 twelveparen: 0x247F,
michael@0 29392 twelveperiod: 0x2493,
michael@0 29393 twelveroman: 0x217B,
michael@0 29394 twentycircle: 0x2473,
michael@0 29395 twentyhangzhou: 0x5344,
michael@0 29396 twentyparen: 0x2487,
michael@0 29397 twentyperiod: 0x249B,
michael@0 29398 two: 0x0032,
michael@0 29399 twoarabic: 0x0662,
michael@0 29400 twobengali: 0x09E8,
michael@0 29401 twocircle: 0x2461,
michael@0 29402 twocircleinversesansserif: 0x278B,
michael@0 29403 twodeva: 0x0968,
michael@0 29404 twodotenleader: 0x2025,
michael@0 29405 twodotleader: 0x2025,
michael@0 29406 twodotleadervertical: 0xFE30,
michael@0 29407 twogujarati: 0x0AE8,
michael@0 29408 twogurmukhi: 0x0A68,
michael@0 29409 twohackarabic: 0x0662,
michael@0 29410 twohangzhou: 0x3022,
michael@0 29411 twoideographicparen: 0x3221,
michael@0 29412 twoinferior: 0x2082,
michael@0 29413 twomonospace: 0xFF12,
michael@0 29414 twonumeratorbengali: 0x09F5,
michael@0 29415 twooldstyle: 0xF732,
michael@0 29416 twoparen: 0x2475,
michael@0 29417 twoperiod: 0x2489,
michael@0 29418 twopersian: 0x06F2,
michael@0 29419 tworoman: 0x2171,
michael@0 29420 twostroke: 0x01BB,
michael@0 29421 twosuperior: 0x00B2,
michael@0 29422 twothai: 0x0E52,
michael@0 29423 twothirds: 0x2154,
michael@0 29424 u: 0x0075,
michael@0 29425 uacute: 0x00FA,
michael@0 29426 ubar: 0x0289,
michael@0 29427 ubengali: 0x0989,
michael@0 29428 ubopomofo: 0x3128,
michael@0 29429 ubreve: 0x016D,
michael@0 29430 ucaron: 0x01D4,
michael@0 29431 ucircle: 0x24E4,
michael@0 29432 ucircumflex: 0x00FB,
michael@0 29433 ucircumflexbelow: 0x1E77,
michael@0 29434 ucyrillic: 0x0443,
michael@0 29435 udattadeva: 0x0951,
michael@0 29436 udblacute: 0x0171,
michael@0 29437 udblgrave: 0x0215,
michael@0 29438 udeva: 0x0909,
michael@0 29439 udieresis: 0x00FC,
michael@0 29440 udieresisacute: 0x01D8,
michael@0 29441 udieresisbelow: 0x1E73,
michael@0 29442 udieresiscaron: 0x01DA,
michael@0 29443 udieresiscyrillic: 0x04F1,
michael@0 29444 udieresisgrave: 0x01DC,
michael@0 29445 udieresismacron: 0x01D6,
michael@0 29446 udotbelow: 0x1EE5,
michael@0 29447 ugrave: 0x00F9,
michael@0 29448 ugujarati: 0x0A89,
michael@0 29449 ugurmukhi: 0x0A09,
michael@0 29450 uhiragana: 0x3046,
michael@0 29451 uhookabove: 0x1EE7,
michael@0 29452 uhorn: 0x01B0,
michael@0 29453 uhornacute: 0x1EE9,
michael@0 29454 uhorndotbelow: 0x1EF1,
michael@0 29455 uhorngrave: 0x1EEB,
michael@0 29456 uhornhookabove: 0x1EED,
michael@0 29457 uhorntilde: 0x1EEF,
michael@0 29458 uhungarumlaut: 0x0171,
michael@0 29459 uhungarumlautcyrillic: 0x04F3,
michael@0 29460 uinvertedbreve: 0x0217,
michael@0 29461 ukatakana: 0x30A6,
michael@0 29462 ukatakanahalfwidth: 0xFF73,
michael@0 29463 ukcyrillic: 0x0479,
michael@0 29464 ukorean: 0x315C,
michael@0 29465 umacron: 0x016B,
michael@0 29466 umacroncyrillic: 0x04EF,
michael@0 29467 umacrondieresis: 0x1E7B,
michael@0 29468 umatragurmukhi: 0x0A41,
michael@0 29469 umonospace: 0xFF55,
michael@0 29470 underscore: 0x005F,
michael@0 29471 underscoredbl: 0x2017,
michael@0 29472 underscoremonospace: 0xFF3F,
michael@0 29473 underscorevertical: 0xFE33,
michael@0 29474 underscorewavy: 0xFE4F,
michael@0 29475 union: 0x222A,
michael@0 29476 universal: 0x2200,
michael@0 29477 uogonek: 0x0173,
michael@0 29478 uparen: 0x24B0,
michael@0 29479 upblock: 0x2580,
michael@0 29480 upperdothebrew: 0x05C4,
michael@0 29481 upsilon: 0x03C5,
michael@0 29482 upsilondieresis: 0x03CB,
michael@0 29483 upsilondieresistonos: 0x03B0,
michael@0 29484 upsilonlatin: 0x028A,
michael@0 29485 upsilontonos: 0x03CD,
michael@0 29486 uptackbelowcmb: 0x031D,
michael@0 29487 uptackmod: 0x02D4,
michael@0 29488 uragurmukhi: 0x0A73,
michael@0 29489 uring: 0x016F,
michael@0 29490 ushortcyrillic: 0x045E,
michael@0 29491 usmallhiragana: 0x3045,
michael@0 29492 usmallkatakana: 0x30A5,
michael@0 29493 usmallkatakanahalfwidth: 0xFF69,
michael@0 29494 ustraightcyrillic: 0x04AF,
michael@0 29495 ustraightstrokecyrillic: 0x04B1,
michael@0 29496 utilde: 0x0169,
michael@0 29497 utildeacute: 0x1E79,
michael@0 29498 utildebelow: 0x1E75,
michael@0 29499 uubengali: 0x098A,
michael@0 29500 uudeva: 0x090A,
michael@0 29501 uugujarati: 0x0A8A,
michael@0 29502 uugurmukhi: 0x0A0A,
michael@0 29503 uumatragurmukhi: 0x0A42,
michael@0 29504 uuvowelsignbengali: 0x09C2,
michael@0 29505 uuvowelsigndeva: 0x0942,
michael@0 29506 uuvowelsigngujarati: 0x0AC2,
michael@0 29507 uvowelsignbengali: 0x09C1,
michael@0 29508 uvowelsigndeva: 0x0941,
michael@0 29509 uvowelsigngujarati: 0x0AC1,
michael@0 29510 v: 0x0076,
michael@0 29511 vadeva: 0x0935,
michael@0 29512 vagujarati: 0x0AB5,
michael@0 29513 vagurmukhi: 0x0A35,
michael@0 29514 vakatakana: 0x30F7,
michael@0 29515 vav: 0x05D5,
michael@0 29516 vavdagesh: 0xFB35,
michael@0 29517 vavdagesh65: 0xFB35,
michael@0 29518 vavdageshhebrew: 0xFB35,
michael@0 29519 vavhebrew: 0x05D5,
michael@0 29520 vavholam: 0xFB4B,
michael@0 29521 vavholamhebrew: 0xFB4B,
michael@0 29522 vavvavhebrew: 0x05F0,
michael@0 29523 vavyodhebrew: 0x05F1,
michael@0 29524 vcircle: 0x24E5,
michael@0 29525 vdotbelow: 0x1E7F,
michael@0 29526 vecyrillic: 0x0432,
michael@0 29527 veharabic: 0x06A4,
michael@0 29528 vehfinalarabic: 0xFB6B,
michael@0 29529 vehinitialarabic: 0xFB6C,
michael@0 29530 vehmedialarabic: 0xFB6D,
michael@0 29531 vekatakana: 0x30F9,
michael@0 29532 venus: 0x2640,
michael@0 29533 verticalbar: 0x007C,
michael@0 29534 verticallineabovecmb: 0x030D,
michael@0 29535 verticallinebelowcmb: 0x0329,
michael@0 29536 verticallinelowmod: 0x02CC,
michael@0 29537 verticallinemod: 0x02C8,
michael@0 29538 vewarmenian: 0x057E,
michael@0 29539 vhook: 0x028B,
michael@0 29540 vikatakana: 0x30F8,
michael@0 29541 viramabengali: 0x09CD,
michael@0 29542 viramadeva: 0x094D,
michael@0 29543 viramagujarati: 0x0ACD,
michael@0 29544 visargabengali: 0x0983,
michael@0 29545 visargadeva: 0x0903,
michael@0 29546 visargagujarati: 0x0A83,
michael@0 29547 vmonospace: 0xFF56,
michael@0 29548 voarmenian: 0x0578,
michael@0 29549 voicediterationhiragana: 0x309E,
michael@0 29550 voicediterationkatakana: 0x30FE,
michael@0 29551 voicedmarkkana: 0x309B,
michael@0 29552 voicedmarkkanahalfwidth: 0xFF9E,
michael@0 29553 vokatakana: 0x30FA,
michael@0 29554 vparen: 0x24B1,
michael@0 29555 vtilde: 0x1E7D,
michael@0 29556 vturned: 0x028C,
michael@0 29557 vuhiragana: 0x3094,
michael@0 29558 vukatakana: 0x30F4,
michael@0 29559 w: 0x0077,
michael@0 29560 wacute: 0x1E83,
michael@0 29561 waekorean: 0x3159,
michael@0 29562 wahiragana: 0x308F,
michael@0 29563 wakatakana: 0x30EF,
michael@0 29564 wakatakanahalfwidth: 0xFF9C,
michael@0 29565 wakorean: 0x3158,
michael@0 29566 wasmallhiragana: 0x308E,
michael@0 29567 wasmallkatakana: 0x30EE,
michael@0 29568 wattosquare: 0x3357,
michael@0 29569 wavedash: 0x301C,
michael@0 29570 wavyunderscorevertical: 0xFE34,
michael@0 29571 wawarabic: 0x0648,
michael@0 29572 wawfinalarabic: 0xFEEE,
michael@0 29573 wawhamzaabovearabic: 0x0624,
michael@0 29574 wawhamzaabovefinalarabic: 0xFE86,
michael@0 29575 wbsquare: 0x33DD,
michael@0 29576 wcircle: 0x24E6,
michael@0 29577 wcircumflex: 0x0175,
michael@0 29578 wdieresis: 0x1E85,
michael@0 29579 wdotaccent: 0x1E87,
michael@0 29580 wdotbelow: 0x1E89,
michael@0 29581 wehiragana: 0x3091,
michael@0 29582 weierstrass: 0x2118,
michael@0 29583 wekatakana: 0x30F1,
michael@0 29584 wekorean: 0x315E,
michael@0 29585 weokorean: 0x315D,
michael@0 29586 wgrave: 0x1E81,
michael@0 29587 whitebullet: 0x25E6,
michael@0 29588 whitecircle: 0x25CB,
michael@0 29589 whitecircleinverse: 0x25D9,
michael@0 29590 whitecornerbracketleft: 0x300E,
michael@0 29591 whitecornerbracketleftvertical: 0xFE43,
michael@0 29592 whitecornerbracketright: 0x300F,
michael@0 29593 whitecornerbracketrightvertical: 0xFE44,
michael@0 29594 whitediamond: 0x25C7,
michael@0 29595 whitediamondcontainingblacksmalldiamond: 0x25C8,
michael@0 29596 whitedownpointingsmalltriangle: 0x25BF,
michael@0 29597 whitedownpointingtriangle: 0x25BD,
michael@0 29598 whiteleftpointingsmalltriangle: 0x25C3,
michael@0 29599 whiteleftpointingtriangle: 0x25C1,
michael@0 29600 whitelenticularbracketleft: 0x3016,
michael@0 29601 whitelenticularbracketright: 0x3017,
michael@0 29602 whiterightpointingsmalltriangle: 0x25B9,
michael@0 29603 whiterightpointingtriangle: 0x25B7,
michael@0 29604 whitesmallsquare: 0x25AB,
michael@0 29605 whitesmilingface: 0x263A,
michael@0 29606 whitesquare: 0x25A1,
michael@0 29607 whitestar: 0x2606,
michael@0 29608 whitetelephone: 0x260F,
michael@0 29609 whitetortoiseshellbracketleft: 0x3018,
michael@0 29610 whitetortoiseshellbracketright: 0x3019,
michael@0 29611 whiteuppointingsmalltriangle: 0x25B5,
michael@0 29612 whiteuppointingtriangle: 0x25B3,
michael@0 29613 wihiragana: 0x3090,
michael@0 29614 wikatakana: 0x30F0,
michael@0 29615 wikorean: 0x315F,
michael@0 29616 wmonospace: 0xFF57,
michael@0 29617 wohiragana: 0x3092,
michael@0 29618 wokatakana: 0x30F2,
michael@0 29619 wokatakanahalfwidth: 0xFF66,
michael@0 29620 won: 0x20A9,
michael@0 29621 wonmonospace: 0xFFE6,
michael@0 29622 wowaenthai: 0x0E27,
michael@0 29623 wparen: 0x24B2,
michael@0 29624 wring: 0x1E98,
michael@0 29625 wsuperior: 0x02B7,
michael@0 29626 wturned: 0x028D,
michael@0 29627 wynn: 0x01BF,
michael@0 29628 x: 0x0078,
michael@0 29629 xabovecmb: 0x033D,
michael@0 29630 xbopomofo: 0x3112,
michael@0 29631 xcircle: 0x24E7,
michael@0 29632 xdieresis: 0x1E8D,
michael@0 29633 xdotaccent: 0x1E8B,
michael@0 29634 xeharmenian: 0x056D,
michael@0 29635 xi: 0x03BE,
michael@0 29636 xmonospace: 0xFF58,
michael@0 29637 xparen: 0x24B3,
michael@0 29638 xsuperior: 0x02E3,
michael@0 29639 y: 0x0079,
michael@0 29640 yaadosquare: 0x334E,
michael@0 29641 yabengali: 0x09AF,
michael@0 29642 yacute: 0x00FD,
michael@0 29643 yadeva: 0x092F,
michael@0 29644 yaekorean: 0x3152,
michael@0 29645 yagujarati: 0x0AAF,
michael@0 29646 yagurmukhi: 0x0A2F,
michael@0 29647 yahiragana: 0x3084,
michael@0 29648 yakatakana: 0x30E4,
michael@0 29649 yakatakanahalfwidth: 0xFF94,
michael@0 29650 yakorean: 0x3151,
michael@0 29651 yamakkanthai: 0x0E4E,
michael@0 29652 yasmallhiragana: 0x3083,
michael@0 29653 yasmallkatakana: 0x30E3,
michael@0 29654 yasmallkatakanahalfwidth: 0xFF6C,
michael@0 29655 yatcyrillic: 0x0463,
michael@0 29656 ycircle: 0x24E8,
michael@0 29657 ycircumflex: 0x0177,
michael@0 29658 ydieresis: 0x00FF,
michael@0 29659 ydotaccent: 0x1E8F,
michael@0 29660 ydotbelow: 0x1EF5,
michael@0 29661 yeharabic: 0x064A,
michael@0 29662 yehbarreearabic: 0x06D2,
michael@0 29663 yehbarreefinalarabic: 0xFBAF,
michael@0 29664 yehfinalarabic: 0xFEF2,
michael@0 29665 yehhamzaabovearabic: 0x0626,
michael@0 29666 yehhamzaabovefinalarabic: 0xFE8A,
michael@0 29667 yehhamzaaboveinitialarabic: 0xFE8B,
michael@0 29668 yehhamzaabovemedialarabic: 0xFE8C,
michael@0 29669 yehinitialarabic: 0xFEF3,
michael@0 29670 yehmedialarabic: 0xFEF4,
michael@0 29671 yehmeeminitialarabic: 0xFCDD,
michael@0 29672 yehmeemisolatedarabic: 0xFC58,
michael@0 29673 yehnoonfinalarabic: 0xFC94,
michael@0 29674 yehthreedotsbelowarabic: 0x06D1,
michael@0 29675 yekorean: 0x3156,
michael@0 29676 yen: 0x00A5,
michael@0 29677 yenmonospace: 0xFFE5,
michael@0 29678 yeokorean: 0x3155,
michael@0 29679 yeorinhieuhkorean: 0x3186,
michael@0 29680 yerahbenyomohebrew: 0x05AA,
michael@0 29681 yerahbenyomolefthebrew: 0x05AA,
michael@0 29682 yericyrillic: 0x044B,
michael@0 29683 yerudieresiscyrillic: 0x04F9,
michael@0 29684 yesieungkorean: 0x3181,
michael@0 29685 yesieungpansioskorean: 0x3183,
michael@0 29686 yesieungsioskorean: 0x3182,
michael@0 29687 yetivhebrew: 0x059A,
michael@0 29688 ygrave: 0x1EF3,
michael@0 29689 yhook: 0x01B4,
michael@0 29690 yhookabove: 0x1EF7,
michael@0 29691 yiarmenian: 0x0575,
michael@0 29692 yicyrillic: 0x0457,
michael@0 29693 yikorean: 0x3162,
michael@0 29694 yinyang: 0x262F,
michael@0 29695 yiwnarmenian: 0x0582,
michael@0 29696 ymonospace: 0xFF59,
michael@0 29697 yod: 0x05D9,
michael@0 29698 yoddagesh: 0xFB39,
michael@0 29699 yoddageshhebrew: 0xFB39,
michael@0 29700 yodhebrew: 0x05D9,
michael@0 29701 yodyodhebrew: 0x05F2,
michael@0 29702 yodyodpatahhebrew: 0xFB1F,
michael@0 29703 yohiragana: 0x3088,
michael@0 29704 yoikorean: 0x3189,
michael@0 29705 yokatakana: 0x30E8,
michael@0 29706 yokatakanahalfwidth: 0xFF96,
michael@0 29707 yokorean: 0x315B,
michael@0 29708 yosmallhiragana: 0x3087,
michael@0 29709 yosmallkatakana: 0x30E7,
michael@0 29710 yosmallkatakanahalfwidth: 0xFF6E,
michael@0 29711 yotgreek: 0x03F3,
michael@0 29712 yoyaekorean: 0x3188,
michael@0 29713 yoyakorean: 0x3187,
michael@0 29714 yoyakthai: 0x0E22,
michael@0 29715 yoyingthai: 0x0E0D,
michael@0 29716 yparen: 0x24B4,
michael@0 29717 ypogegrammeni: 0x037A,
michael@0 29718 ypogegrammenigreekcmb: 0x0345,
michael@0 29719 yr: 0x01A6,
michael@0 29720 yring: 0x1E99,
michael@0 29721 ysuperior: 0x02B8,
michael@0 29722 ytilde: 0x1EF9,
michael@0 29723 yturned: 0x028E,
michael@0 29724 yuhiragana: 0x3086,
michael@0 29725 yuikorean: 0x318C,
michael@0 29726 yukatakana: 0x30E6,
michael@0 29727 yukatakanahalfwidth: 0xFF95,
michael@0 29728 yukorean: 0x3160,
michael@0 29729 yusbigcyrillic: 0x046B,
michael@0 29730 yusbigiotifiedcyrillic: 0x046D,
michael@0 29731 yuslittlecyrillic: 0x0467,
michael@0 29732 yuslittleiotifiedcyrillic: 0x0469,
michael@0 29733 yusmallhiragana: 0x3085,
michael@0 29734 yusmallkatakana: 0x30E5,
michael@0 29735 yusmallkatakanahalfwidth: 0xFF6D,
michael@0 29736 yuyekorean: 0x318B,
michael@0 29737 yuyeokorean: 0x318A,
michael@0 29738 yyabengali: 0x09DF,
michael@0 29739 yyadeva: 0x095F,
michael@0 29740 z: 0x007A,
michael@0 29741 zaarmenian: 0x0566,
michael@0 29742 zacute: 0x017A,
michael@0 29743 zadeva: 0x095B,
michael@0 29744 zagurmukhi: 0x0A5B,
michael@0 29745 zaharabic: 0x0638,
michael@0 29746 zahfinalarabic: 0xFEC6,
michael@0 29747 zahinitialarabic: 0xFEC7,
michael@0 29748 zahiragana: 0x3056,
michael@0 29749 zahmedialarabic: 0xFEC8,
michael@0 29750 zainarabic: 0x0632,
michael@0 29751 zainfinalarabic: 0xFEB0,
michael@0 29752 zakatakana: 0x30B6,
michael@0 29753 zaqefgadolhebrew: 0x0595,
michael@0 29754 zaqefqatanhebrew: 0x0594,
michael@0 29755 zarqahebrew: 0x0598,
michael@0 29756 zayin: 0x05D6,
michael@0 29757 zayindagesh: 0xFB36,
michael@0 29758 zayindageshhebrew: 0xFB36,
michael@0 29759 zayinhebrew: 0x05D6,
michael@0 29760 zbopomofo: 0x3117,
michael@0 29761 zcaron: 0x017E,
michael@0 29762 zcircle: 0x24E9,
michael@0 29763 zcircumflex: 0x1E91,
michael@0 29764 zcurl: 0x0291,
michael@0 29765 zdot: 0x017C,
michael@0 29766 zdotaccent: 0x017C,
michael@0 29767 zdotbelow: 0x1E93,
michael@0 29768 zecyrillic: 0x0437,
michael@0 29769 zedescendercyrillic: 0x0499,
michael@0 29770 zedieresiscyrillic: 0x04DF,
michael@0 29771 zehiragana: 0x305C,
michael@0 29772 zekatakana: 0x30BC,
michael@0 29773 zero: 0x0030,
michael@0 29774 zeroarabic: 0x0660,
michael@0 29775 zerobengali: 0x09E6,
michael@0 29776 zerodeva: 0x0966,
michael@0 29777 zerogujarati: 0x0AE6,
michael@0 29778 zerogurmukhi: 0x0A66,
michael@0 29779 zerohackarabic: 0x0660,
michael@0 29780 zeroinferior: 0x2080,
michael@0 29781 zeromonospace: 0xFF10,
michael@0 29782 zerooldstyle: 0xF730,
michael@0 29783 zeropersian: 0x06F0,
michael@0 29784 zerosuperior: 0x2070,
michael@0 29785 zerothai: 0x0E50,
michael@0 29786 zerowidthjoiner: 0xFEFF,
michael@0 29787 zerowidthnonjoiner: 0x200C,
michael@0 29788 zerowidthspace: 0x200B,
michael@0 29789 zeta: 0x03B6,
michael@0 29790 zhbopomofo: 0x3113,
michael@0 29791 zhearmenian: 0x056A,
michael@0 29792 zhebrevecyrillic: 0x04C2,
michael@0 29793 zhecyrillic: 0x0436,
michael@0 29794 zhedescendercyrillic: 0x0497,
michael@0 29795 zhedieresiscyrillic: 0x04DD,
michael@0 29796 zihiragana: 0x3058,
michael@0 29797 zikatakana: 0x30B8,
michael@0 29798 zinorhebrew: 0x05AE,
michael@0 29799 zlinebelow: 0x1E95,
michael@0 29800 zmonospace: 0xFF5A,
michael@0 29801 zohiragana: 0x305E,
michael@0 29802 zokatakana: 0x30BE,
michael@0 29803 zparen: 0x24B5,
michael@0 29804 zretroflexhook: 0x0290,
michael@0 29805 zstroke: 0x01B6,
michael@0 29806 zuhiragana: 0x305A,
michael@0 29807 zukatakana: 0x30BA,
michael@0 29808 '.notdef': 0x0000
michael@0 29809 };
michael@0 29810
michael@0 29811
michael@0 29812
michael@0 29813 var PDFImage = (function PDFImageClosure() {
michael@0 29814 /**
michael@0 29815 * Decode the image in the main thread if it supported. Resovles the promise
michael@0 29816 * when the image data is ready.
michael@0 29817 */
michael@0 29818 function handleImageData(handler, xref, res, image) {
michael@0 29819 if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) {
michael@0 29820 // For natively supported jpegs send them to the main thread for decoding.
michael@0 29821 var dict = image.dict;
michael@0 29822 var colorSpace = dict.get('ColorSpace', 'CS');
michael@0 29823 colorSpace = ColorSpace.parse(colorSpace, xref, res);
michael@0 29824 var numComps = colorSpace.numComps;
michael@0 29825 var resolvePromise;
michael@0 29826 handler.send('JpegDecode', [image.getIR(), numComps], function(message) {
michael@0 29827 var data = message.data;
michael@0 29828 var stream = new Stream(data, 0, data.length, image.dict);
michael@0 29829 resolvePromise(stream);
michael@0 29830 });
michael@0 29831 return new Promise(function (resolve) {
michael@0 29832 resolvePromise = resolve;
michael@0 29833 });
michael@0 29834 } else {
michael@0 29835 return Promise.resolve(image);
michael@0 29836 }
michael@0 29837 }
michael@0 29838 /**
michael@0 29839 * Decode and clamp a value. The formula is different from the spec because we
michael@0 29840 * don't decode to float range [0,1], we decode it in the [0,max] range.
michael@0 29841 */
michael@0 29842 function decodeAndClamp(value, addend, coefficient, max) {
michael@0 29843 value = addend + value * coefficient;
michael@0 29844 // Clamp the value to the range
michael@0 29845 return (value < 0 ? 0 : (value > max ? max : value));
michael@0 29846 }
michael@0 29847 function PDFImage(xref, res, image, inline, smask, mask, isMask) {
michael@0 29848 this.image = image;
michael@0 29849 var dict = image.dict;
michael@0 29850 if (dict.has('Filter')) {
michael@0 29851 var filter = dict.get('Filter').name;
michael@0 29852 if (filter === 'JPXDecode') {
michael@0 29853 var jpxImage = new JpxImage();
michael@0 29854 jpxImage.parseImageProperties(image.stream);
michael@0 29855 image.stream.reset();
michael@0 29856 image.bitsPerComponent = jpxImage.bitsPerComponent;
michael@0 29857 image.numComps = jpxImage.componentsCount;
michael@0 29858 } else if (filter === 'JBIG2Decode') {
michael@0 29859 image.bitsPerComponent = 1;
michael@0 29860 image.numComps = 1;
michael@0 29861 }
michael@0 29862 }
michael@0 29863 // TODO cache rendered images?
michael@0 29864
michael@0 29865 this.width = dict.get('Width', 'W');
michael@0 29866 this.height = dict.get('Height', 'H');
michael@0 29867
michael@0 29868 if (this.width < 1 || this.height < 1) {
michael@0 29869 error('Invalid image width: ' + this.width + ' or height: ' +
michael@0 29870 this.height);
michael@0 29871 }
michael@0 29872
michael@0 29873 this.interpolate = dict.get('Interpolate', 'I') || false;
michael@0 29874 this.imageMask = dict.get('ImageMask', 'IM') || false;
michael@0 29875 this.matte = dict.get('Matte') || false;
michael@0 29876
michael@0 29877 var bitsPerComponent = image.bitsPerComponent;
michael@0 29878 if (!bitsPerComponent) {
michael@0 29879 bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
michael@0 29880 if (!bitsPerComponent) {
michael@0 29881 if (this.imageMask) {
michael@0 29882 bitsPerComponent = 1;
michael@0 29883 } else {
michael@0 29884 error('Bits per component missing in image: ' + this.imageMask);
michael@0 29885 }
michael@0 29886 }
michael@0 29887 }
michael@0 29888 this.bpc = bitsPerComponent;
michael@0 29889
michael@0 29890 if (!this.imageMask) {
michael@0 29891 var colorSpace = dict.get('ColorSpace', 'CS');
michael@0 29892 if (!colorSpace) {
michael@0 29893 info('JPX images (which do not require color spaces)');
michael@0 29894 switch (image.numComps) {
michael@0 29895 case 1:
michael@0 29896 colorSpace = Name.get('DeviceGray');
michael@0 29897 break;
michael@0 29898 case 3:
michael@0 29899 colorSpace = Name.get('DeviceRGB');
michael@0 29900 break;
michael@0 29901 case 4:
michael@0 29902 colorSpace = Name.get('DeviceCMYK');
michael@0 29903 break;
michael@0 29904 default:
michael@0 29905 error('JPX images with ' + this.numComps +
michael@0 29906 ' color components not supported.');
michael@0 29907 }
michael@0 29908 }
michael@0 29909 this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
michael@0 29910 this.numComps = this.colorSpace.numComps;
michael@0 29911 }
michael@0 29912
michael@0 29913 this.decode = dict.get('Decode', 'D');
michael@0 29914 this.needsDecode = false;
michael@0 29915 if (this.decode &&
michael@0 29916 ((this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode)) ||
michael@0 29917 (isMask && !ColorSpace.isDefaultDecode(this.decode, 1)))) {
michael@0 29918 this.needsDecode = true;
michael@0 29919 // Do some preprocessing to avoid more math.
michael@0 29920 var max = (1 << bitsPerComponent) - 1;
michael@0 29921 this.decodeCoefficients = [];
michael@0 29922 this.decodeAddends = [];
michael@0 29923 for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
michael@0 29924 var dmin = this.decode[i];
michael@0 29925 var dmax = this.decode[i + 1];
michael@0 29926 this.decodeCoefficients[j] = dmax - dmin;
michael@0 29927 this.decodeAddends[j] = max * dmin;
michael@0 29928 }
michael@0 29929 }
michael@0 29930
michael@0 29931 if (smask) {
michael@0 29932 this.smask = new PDFImage(xref, res, smask, false);
michael@0 29933 } else if (mask) {
michael@0 29934 if (isStream(mask)) {
michael@0 29935 this.mask = new PDFImage(xref, res, mask, false, null, null, true);
michael@0 29936 } else {
michael@0 29937 // Color key mask (just an array).
michael@0 29938 this.mask = mask;
michael@0 29939 }
michael@0 29940 }
michael@0 29941 }
michael@0 29942 /**
michael@0 29943 * Handles processing of image data and returns the Promise that is resolved
michael@0 29944 * with a PDFImage when the image is ready to be used.
michael@0 29945 */
michael@0 29946 PDFImage.buildImage = function PDFImage_buildImage(handler, xref,
michael@0 29947 res, image, inline) {
michael@0 29948 var imagePromise = handleImageData(handler, xref, res, image);
michael@0 29949 var smaskPromise;
michael@0 29950 var maskPromise;
michael@0 29951
michael@0 29952 var smask = image.dict.get('SMask');
michael@0 29953 var mask = image.dict.get('Mask');
michael@0 29954
michael@0 29955 if (smask) {
michael@0 29956 smaskPromise = handleImageData(handler, xref, res, smask);
michael@0 29957 maskPromise = Promise.resolve(null);
michael@0 29958 } else {
michael@0 29959 smaskPromise = Promise.resolve(null);
michael@0 29960 if (mask) {
michael@0 29961 if (isStream(mask)) {
michael@0 29962 maskPromise = handleImageData(handler, xref, res, mask);
michael@0 29963 } else if (isArray(mask)) {
michael@0 29964 maskPromise = Promise.resolve(mask);
michael@0 29965 } else {
michael@0 29966 warn('Unsupported mask format.');
michael@0 29967 maskPromise = Promise.resolve(null);
michael@0 29968 }
michael@0 29969 } else {
michael@0 29970 maskPromise = Promise.resolve(null);
michael@0 29971 }
michael@0 29972 }
michael@0 29973 return Promise.all([imagePromise, smaskPromise, maskPromise]).then(
michael@0 29974 function(results) {
michael@0 29975 var imageData = results[0];
michael@0 29976 var smaskData = results[1];
michael@0 29977 var maskData = results[2];
michael@0 29978 return new PDFImage(xref, res, imageData, inline, smaskData, maskData);
michael@0 29979 });
michael@0 29980 };
michael@0 29981
michael@0 29982 /**
michael@0 29983 * Resize an image using the nearest neighbor algorithm. Currently only
michael@0 29984 * supports one and three component images.
michael@0 29985 * @param {TypedArray} pixels The original image with one component.
michael@0 29986 * @param {Number} bpc Number of bits per component.
michael@0 29987 * @param {Number} components Number of color components, 1 or 3 is supported.
michael@0 29988 * @param {Number} w1 Original width.
michael@0 29989 * @param {Number} h1 Original height.
michael@0 29990 * @param {Number} w2 New width.
michael@0 29991 * @param {Number} h2 New height.
michael@0 29992 * @return {TypedArray} Resized image data.
michael@0 29993 */
michael@0 29994 PDFImage.resize = function PDFImage_resize(pixels, bpc, components,
michael@0 29995 w1, h1, w2, h2) {
michael@0 29996 var length = w2 * h2 * components;
michael@0 29997 var temp = (bpc <= 8 ? new Uint8Array(length) :
michael@0 29998 (bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length)));
michael@0 29999 var xRatio = w1 / w2;
michael@0 30000 var yRatio = h1 / h2;
michael@0 30001 var px, py, newIndex, oldIndex;
michael@0 30002 for (var i = 0; i < h2; i++) {
michael@0 30003 for (var j = 0; j < w2; j++) {
michael@0 30004 px = Math.floor(j * xRatio);
michael@0 30005 py = Math.floor(i * yRatio);
michael@0 30006 newIndex = (i * w2) + j;
michael@0 30007 oldIndex = ((py * w1) + px);
michael@0 30008 if (components === 1) {
michael@0 30009 temp[newIndex] = pixels[oldIndex];
michael@0 30010 } else if (components === 3) {
michael@0 30011 newIndex *= 3;
michael@0 30012 oldIndex *= 3;
michael@0 30013 temp[newIndex] = pixels[oldIndex];
michael@0 30014 temp[newIndex + 1] = pixels[oldIndex + 1];
michael@0 30015 temp[newIndex + 2] = pixels[oldIndex + 2];
michael@0 30016 }
michael@0 30017 }
michael@0 30018 }
michael@0 30019 return temp;
michael@0 30020 };
michael@0 30021
michael@0 30022 PDFImage.createMask =
michael@0 30023 function PDFImage_createMask(imgArray, width, height, canTransfer,
michael@0 30024 inverseDecode) {
michael@0 30025 // If imgArray came from a DecodeStream, we're safe to transfer it.
michael@0 30026 // Otherwise, copy it.
michael@0 30027 var actualLength = imgArray.byteLength;
michael@0 30028 var data;
michael@0 30029 if (canTransfer) {
michael@0 30030 data = imgArray;
michael@0 30031 } else {
michael@0 30032 data = new Uint8Array(actualLength);
michael@0 30033 data.set(imgArray);
michael@0 30034 }
michael@0 30035 // Invert if necessary. It's safe to modify the array -- whether it's the
michael@0 30036 // original or a copy, we're about to transfer it anyway, so nothing else
michael@0 30037 // in this thread can be relying on its contents.
michael@0 30038 if (inverseDecode) {
michael@0 30039 for (var i = 0; i < actualLength; i++) {
michael@0 30040 data[i] = ~data[i];
michael@0 30041 }
michael@0 30042 }
michael@0 30043
michael@0 30044 return {data: data, width: width, height: height};
michael@0 30045 };
michael@0 30046
michael@0 30047 PDFImage.prototype = {
michael@0 30048 get drawWidth() {
michael@0 30049 return Math.max(this.width,
michael@0 30050 this.smask && this.smask.width || 0,
michael@0 30051 this.mask && this.mask.width || 0);
michael@0 30052 },
michael@0 30053 get drawHeight() {
michael@0 30054 return Math.max(this.height,
michael@0 30055 this.smask && this.smask.height || 0,
michael@0 30056 this.mask && this.mask.height || 0);
michael@0 30057 },
michael@0 30058 decodeBuffer: function PDFImage_decodeBuffer(buffer) {
michael@0 30059 var bpc = this.bpc;
michael@0 30060 var numComps = this.numComps;
michael@0 30061
michael@0 30062 var decodeAddends = this.decodeAddends;
michael@0 30063 var decodeCoefficients = this.decodeCoefficients;
michael@0 30064 var max = (1 << bpc) - 1;
michael@0 30065 var i, ii;
michael@0 30066
michael@0 30067 if (bpc === 1) {
michael@0 30068 // If the buffer needed decode that means it just needs to be inverted.
michael@0 30069 for (i = 0, ii = buffer.length; i < ii; i++) {
michael@0 30070 buffer[i] = +!(buffer[i]);
michael@0 30071 }
michael@0 30072 return;
michael@0 30073 }
michael@0 30074 var index = 0;
michael@0 30075 for (i = 0, ii = this.width * this.height; i < ii; i++) {
michael@0 30076 for (var j = 0; j < numComps; j++) {
michael@0 30077 buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j],
michael@0 30078 decodeCoefficients[j], max);
michael@0 30079 index++;
michael@0 30080 }
michael@0 30081 }
michael@0 30082 },
michael@0 30083 getComponents: function PDFImage_getComponents(buffer) {
michael@0 30084 var bpc = this.bpc;
michael@0 30085
michael@0 30086 // This image doesn't require any extra work.
michael@0 30087 if (bpc === 8) {
michael@0 30088 return buffer;
michael@0 30089 }
michael@0 30090
michael@0 30091 var width = this.width;
michael@0 30092 var height = this.height;
michael@0 30093 var numComps = this.numComps;
michael@0 30094
michael@0 30095 var length = width * height * numComps;
michael@0 30096 var bufferPos = 0;
michael@0 30097 var output = (bpc <= 8 ? new Uint8Array(length) :
michael@0 30098 (bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length)));
michael@0 30099 var rowComps = width * numComps;
michael@0 30100
michael@0 30101 var max = (1 << bpc) - 1;
michael@0 30102 var i = 0, ii, buf;
michael@0 30103
michael@0 30104 if (bpc === 1) {
michael@0 30105 // Optimization for reading 1 bpc images.
michael@0 30106 var mask, loop1End, loop2End;
michael@0 30107 for (var j = 0; j < height; j++) {
michael@0 30108 loop1End = i + (rowComps & ~7);
michael@0 30109 loop2End = i + rowComps;
michael@0 30110
michael@0 30111 // unroll loop for all full bytes
michael@0 30112 while (i < loop1End) {
michael@0 30113 buf = buffer[bufferPos++];
michael@0 30114 output[i] = (buf >> 7) & 1;
michael@0 30115 output[i + 1] = (buf >> 6) & 1;
michael@0 30116 output[i + 2] = (buf >> 5) & 1;
michael@0 30117 output[i + 3] = (buf >> 4) & 1;
michael@0 30118 output[i + 4] = (buf >> 3) & 1;
michael@0 30119 output[i + 5] = (buf >> 2) & 1;
michael@0 30120 output[i + 6] = (buf >> 1) & 1;
michael@0 30121 output[i + 7] = buf & 1;
michael@0 30122 i += 8;
michael@0 30123 }
michael@0 30124
michael@0 30125 // handle remaing bits
michael@0 30126 if (i < loop2End) {
michael@0 30127 buf = buffer[bufferPos++];
michael@0 30128 mask = 128;
michael@0 30129 while (i < loop2End) {
michael@0 30130 output[i++] = +!!(buf & mask);
michael@0 30131 mask >>= 1;
michael@0 30132 }
michael@0 30133 }
michael@0 30134 }
michael@0 30135 } else {
michael@0 30136 // The general case that handles all other bpc values.
michael@0 30137 var bits = 0;
michael@0 30138 buf = 0;
michael@0 30139 for (i = 0, ii = length; i < ii; ++i) {
michael@0 30140 if (i % rowComps === 0) {
michael@0 30141 buf = 0;
michael@0 30142 bits = 0;
michael@0 30143 }
michael@0 30144
michael@0 30145 while (bits < bpc) {
michael@0 30146 buf = (buf << 8) | buffer[bufferPos++];
michael@0 30147 bits += 8;
michael@0 30148 }
michael@0 30149
michael@0 30150 var remainingBits = bits - bpc;
michael@0 30151 var value = buf >> remainingBits;
michael@0 30152 output[i] = (value < 0 ? 0 : (value > max ? max : value));
michael@0 30153 buf = buf & ((1 << remainingBits) - 1);
michael@0 30154 bits = remainingBits;
michael@0 30155 }
michael@0 30156 }
michael@0 30157 return output;
michael@0 30158 },
michael@0 30159 fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height,
michael@0 30160 actualHeight, image) {
michael@0 30161 var smask = this.smask;
michael@0 30162 var mask = this.mask;
michael@0 30163 var alphaBuf, sw, sh, i, ii, j;
michael@0 30164
michael@0 30165 if (smask) {
michael@0 30166 sw = smask.width;
michael@0 30167 sh = smask.height;
michael@0 30168 alphaBuf = new Uint8Array(sw * sh);
michael@0 30169 smask.fillGrayBuffer(alphaBuf);
michael@0 30170 if (sw != width || sh != height) {
michael@0 30171 alphaBuf = PDFImage.resize(alphaBuf, smask.bpc, 1, sw, sh, width,
michael@0 30172 height);
michael@0 30173 }
michael@0 30174 } else if (mask) {
michael@0 30175 if (mask instanceof PDFImage) {
michael@0 30176 sw = mask.width;
michael@0 30177 sh = mask.height;
michael@0 30178 alphaBuf = new Uint8Array(sw * sh);
michael@0 30179 mask.numComps = 1;
michael@0 30180 mask.fillGrayBuffer(alphaBuf);
michael@0 30181
michael@0 30182 // Need to invert values in rgbaBuf
michael@0 30183 for (i = 0, ii = sw * sh; i < ii; ++i) {
michael@0 30184 alphaBuf[i] = 255 - alphaBuf[i];
michael@0 30185 }
michael@0 30186
michael@0 30187 if (sw != width || sh != height) {
michael@0 30188 alphaBuf = PDFImage.resize(alphaBuf, mask.bpc, 1, sw, sh, width,
michael@0 30189 height);
michael@0 30190 }
michael@0 30191 } else if (isArray(mask)) {
michael@0 30192 // Color key mask: if any of the compontents are outside the range
michael@0 30193 // then they should be painted.
michael@0 30194 alphaBuf = new Uint8Array(width * height);
michael@0 30195 var numComps = this.numComps;
michael@0 30196 for (i = 0, ii = width * height; i < ii; ++i) {
michael@0 30197 var opacity = 0;
michael@0 30198 var imageOffset = i * numComps;
michael@0 30199 for (j = 0; j < numComps; ++j) {
michael@0 30200 var color = image[imageOffset + j];
michael@0 30201 var maskOffset = j * 2;
michael@0 30202 if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {
michael@0 30203 opacity = 255;
michael@0 30204 break;
michael@0 30205 }
michael@0 30206 }
michael@0 30207 alphaBuf[i] = opacity;
michael@0 30208 }
michael@0 30209 } else {
michael@0 30210 error('Unknown mask format.');
michael@0 30211 }
michael@0 30212 }
michael@0 30213
michael@0 30214 if (alphaBuf) {
michael@0 30215 for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
michael@0 30216 rgbaBuf[j] = alphaBuf[i];
michael@0 30217 }
michael@0 30218 } else {
michael@0 30219 // No mask.
michael@0 30220 for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
michael@0 30221 rgbaBuf[j] = 255;
michael@0 30222 }
michael@0 30223 }
michael@0 30224 },
michael@0 30225 undoPreblend: function PDFImage_undoPreblend(buffer, width, height) {
michael@0 30226 var matte = this.smask && this.smask.matte;
michael@0 30227 if (!matte) {
michael@0 30228 return;
michael@0 30229 }
michael@0 30230
michael@0 30231 function clamp(value) {
michael@0 30232 return (value < 0 ? 0 : (value > 255 ? 255 : value)) | 0;
michael@0 30233 }
michael@0 30234
michael@0 30235 var matteRgb = this.colorSpace.getRgb(matte, 0);
michael@0 30236 var length = width * height * 4;
michael@0 30237 for (var i = 0; i < length; i += 4) {
michael@0 30238 var alpha = buffer[i + 3];
michael@0 30239 if (alpha === 0) {
michael@0 30240 // according formula we have to get Infinity in all components
michael@0 30241 // making it as white (tipical paper color) should be okay
michael@0 30242 buffer[i] = 255;
michael@0 30243 buffer[i + 1] = 255;
michael@0 30244 buffer[i + 2] = 255;
michael@0 30245 continue;
michael@0 30246 }
michael@0 30247 var k = 255 / alpha;
michael@0 30248 buffer[i] = clamp((buffer[i] - matteRgb[0]) * k + matteRgb[0]);
michael@0 30249 buffer[i + 1] = clamp((buffer[i + 1] - matteRgb[1]) * k + matteRgb[1]);
michael@0 30250 buffer[i + 2] = clamp((buffer[i + 2] - matteRgb[2]) * k + matteRgb[2]);
michael@0 30251 }
michael@0 30252 },
michael@0 30253 createImageData: function PDFImage_createImageData(forceRGBA) {
michael@0 30254 var drawWidth = this.drawWidth;
michael@0 30255 var drawHeight = this.drawHeight;
michael@0 30256 var imgData = { // other fields are filled in below
michael@0 30257 width: drawWidth,
michael@0 30258 height: drawHeight
michael@0 30259 };
michael@0 30260
michael@0 30261 var numComps = this.numComps;
michael@0 30262 var originalWidth = this.width;
michael@0 30263 var originalHeight = this.height;
michael@0 30264 var bpc = this.bpc;
michael@0 30265
michael@0 30266 // Rows start at byte boundary.
michael@0 30267 var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
michael@0 30268 var imgArray = this.getImageBytes(originalHeight * rowBytes);
michael@0 30269
michael@0 30270 if (!forceRGBA) {
michael@0 30271 // If it is a 1-bit-per-pixel grayscale (i.e. black-and-white) image
michael@0 30272 // without any complications, we pass a same-sized copy to the main
michael@0 30273 // thread rather than expanding by 32x to RGBA form. This saves *lots*
michael@0 30274 // of memory for many scanned documents. It's also much faster.
michael@0 30275 //
michael@0 30276 // Similarly, if it is a 24-bit-per pixel RGB image without any
michael@0 30277 // complications, we avoid expanding by 1.333x to RGBA form.
michael@0 30278 var kind;
michael@0 30279 if (this.colorSpace.name === 'DeviceGray' && bpc === 1) {
michael@0 30280 kind = ImageKind.GRAYSCALE_1BPP;
michael@0 30281 } else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8) {
michael@0 30282 kind = ImageKind.RGB_24BPP;
michael@0 30283 }
michael@0 30284 if (kind && !this.smask && !this.mask && !this.needsDecode &&
michael@0 30285 drawWidth === originalWidth && drawHeight === originalHeight) {
michael@0 30286 imgData.kind = kind;
michael@0 30287
michael@0 30288 // If imgArray came from a DecodeStream, we're safe to transfer it
michael@0 30289 // (and thus neuter it) because it will constitute the entire
michael@0 30290 // DecodeStream's data. But if it came from a Stream, we need to
michael@0 30291 // copy it because it'll only be a portion of the Stream's data, and
michael@0 30292 // the rest will be read later on.
michael@0 30293 if (this.image instanceof DecodeStream) {
michael@0 30294 imgData.data = imgArray;
michael@0 30295 } else {
michael@0 30296 var newArray = new Uint8Array(imgArray.length);
michael@0 30297 newArray.set(imgArray);
michael@0 30298 imgData.data = newArray;
michael@0 30299 }
michael@0 30300 return imgData;
michael@0 30301 }
michael@0 30302 }
michael@0 30303
michael@0 30304 // imgArray can be incomplete (e.g. after CCITT fax encoding).
michael@0 30305 var actualHeight = 0 | (imgArray.length / rowBytes *
michael@0 30306 drawHeight / originalHeight);
michael@0 30307
michael@0 30308 var comps = this.getComponents(imgArray);
michael@0 30309
michael@0 30310 // If opacity data is present, use RGBA_32BPP form. Otherwise, use the
michael@0 30311 // more compact RGB_24BPP form if allowable.
michael@0 30312 var alpha01, maybeUndoPreblend;
michael@0 30313 if (!forceRGBA && !this.smask && !this.mask) {
michael@0 30314 imgData.kind = ImageKind.RGB_24BPP;
michael@0 30315 imgData.data = new Uint8Array(drawWidth * drawHeight * 3);
michael@0 30316 alpha01 = 0;
michael@0 30317 maybeUndoPreblend = false;
michael@0 30318 } else {
michael@0 30319 imgData.kind = ImageKind.RGBA_32BPP;
michael@0 30320 imgData.data = new Uint8Array(drawWidth * drawHeight * 4);
michael@0 30321 alpha01 = 1;
michael@0 30322 maybeUndoPreblend = true;
michael@0 30323
michael@0 30324 // Color key masking (opacity) must be performed before decoding.
michael@0 30325 this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight,
michael@0 30326 comps);
michael@0 30327 }
michael@0 30328
michael@0 30329 if (this.needsDecode) {
michael@0 30330 this.decodeBuffer(comps);
michael@0 30331 }
michael@0 30332 this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight,
michael@0 30333 drawWidth, drawHeight, actualHeight, bpc, comps,
michael@0 30334 alpha01);
michael@0 30335 if (maybeUndoPreblend) {
michael@0 30336 this.undoPreblend(imgData.data, drawWidth, actualHeight);
michael@0 30337 }
michael@0 30338
michael@0 30339 return imgData;
michael@0 30340 },
michael@0 30341 fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) {
michael@0 30342 var numComps = this.numComps;
michael@0 30343 if (numComps != 1) {
michael@0 30344 error('Reading gray scale from a color image: ' + numComps);
michael@0 30345 }
michael@0 30346
michael@0 30347 var width = this.width;
michael@0 30348 var height = this.height;
michael@0 30349 var bpc = this.bpc;
michael@0 30350
michael@0 30351 // rows start at byte boundary
michael@0 30352 var rowBytes = (width * numComps * bpc + 7) >> 3;
michael@0 30353 var imgArray = this.getImageBytes(height * rowBytes);
michael@0 30354
michael@0 30355 var comps = this.getComponents(imgArray);
michael@0 30356 var i, length;
michael@0 30357
michael@0 30358 if (bpc === 1) {
michael@0 30359 // inline decoding (= inversion) for 1 bpc images
michael@0 30360 length = width * height;
michael@0 30361 if (this.needsDecode) {
michael@0 30362 // invert and scale to {0, 255}
michael@0 30363 for (i = 0; i < length; ++i) {
michael@0 30364 buffer[i] = (comps[i] - 1) & 255;
michael@0 30365 }
michael@0 30366 } else {
michael@0 30367 // scale to {0, 255}
michael@0 30368 for (i = 0; i < length; ++i) {
michael@0 30369 buffer[i] = (-comps[i]) & 255;
michael@0 30370 }
michael@0 30371 }
michael@0 30372 return;
michael@0 30373 }
michael@0 30374
michael@0 30375 if (this.needsDecode) {
michael@0 30376 this.decodeBuffer(comps);
michael@0 30377 }
michael@0 30378 length = width * height;
michael@0 30379 // we aren't using a colorspace so we need to scale the value
michael@0 30380 var scale = 255 / ((1 << bpc) - 1);
michael@0 30381 for (i = 0; i < length; ++i) {
michael@0 30382 buffer[i] = (scale * comps[i]) | 0;
michael@0 30383 }
michael@0 30384 },
michael@0 30385 getImageBytes: function PDFImage_getImageBytes(length) {
michael@0 30386 this.image.reset();
michael@0 30387 return this.image.getBytes(length);
michael@0 30388 }
michael@0 30389 };
michael@0 30390 return PDFImage;
michael@0 30391 })();
michael@0 30392
michael@0 30393
michael@0 30394 // The Metrics object contains glyph widths (in glyph space units).
michael@0 30395 // As per PDF spec, for most fonts (Type 3 being an exception) a glyph
michael@0 30396 // space unit corresponds to 1/1000th of text space unit.
michael@0 30397 var Metrics = {
michael@0 30398 'Courier': 600,
michael@0 30399 'Courier-Bold': 600,
michael@0 30400 'Courier-BoldOblique': 600,
michael@0 30401 'Courier-Oblique': 600,
michael@0 30402 'Helvetica' : {
michael@0 30403 'space': 278,
michael@0 30404 'exclam': 278,
michael@0 30405 'quotedbl': 355,
michael@0 30406 'numbersign': 556,
michael@0 30407 'dollar': 556,
michael@0 30408 'percent': 889,
michael@0 30409 'ampersand': 667,
michael@0 30410 'quoteright': 222,
michael@0 30411 'parenleft': 333,
michael@0 30412 'parenright': 333,
michael@0 30413 'asterisk': 389,
michael@0 30414 'plus': 584,
michael@0 30415 'comma': 278,
michael@0 30416 'hyphen': 333,
michael@0 30417 'period': 278,
michael@0 30418 'slash': 278,
michael@0 30419 'zero': 556,
michael@0 30420 'one': 556,
michael@0 30421 'two': 556,
michael@0 30422 'three': 556,
michael@0 30423 'four': 556,
michael@0 30424 'five': 556,
michael@0 30425 'six': 556,
michael@0 30426 'seven': 556,
michael@0 30427 'eight': 556,
michael@0 30428 'nine': 556,
michael@0 30429 'colon': 278,
michael@0 30430 'semicolon': 278,
michael@0 30431 'less': 584,
michael@0 30432 'equal': 584,
michael@0 30433 'greater': 584,
michael@0 30434 'question': 556,
michael@0 30435 'at': 1015,
michael@0 30436 'A': 667,
michael@0 30437 'B': 667,
michael@0 30438 'C': 722,
michael@0 30439 'D': 722,
michael@0 30440 'E': 667,
michael@0 30441 'F': 611,
michael@0 30442 'G': 778,
michael@0 30443 'H': 722,
michael@0 30444 'I': 278,
michael@0 30445 'J': 500,
michael@0 30446 'K': 667,
michael@0 30447 'L': 556,
michael@0 30448 'M': 833,
michael@0 30449 'N': 722,
michael@0 30450 'O': 778,
michael@0 30451 'P': 667,
michael@0 30452 'Q': 778,
michael@0 30453 'R': 722,
michael@0 30454 'S': 667,
michael@0 30455 'T': 611,
michael@0 30456 'U': 722,
michael@0 30457 'V': 667,
michael@0 30458 'W': 944,
michael@0 30459 'X': 667,
michael@0 30460 'Y': 667,
michael@0 30461 'Z': 611,
michael@0 30462 'bracketleft': 278,
michael@0 30463 'backslash': 278,
michael@0 30464 'bracketright': 278,
michael@0 30465 'asciicircum': 469,
michael@0 30466 'underscore': 556,
michael@0 30467 'quoteleft': 222,
michael@0 30468 'a': 556,
michael@0 30469 'b': 556,
michael@0 30470 'c': 500,
michael@0 30471 'd': 556,
michael@0 30472 'e': 556,
michael@0 30473 'f': 278,
michael@0 30474 'g': 556,
michael@0 30475 'h': 556,
michael@0 30476 'i': 222,
michael@0 30477 'j': 222,
michael@0 30478 'k': 500,
michael@0 30479 'l': 222,
michael@0 30480 'm': 833,
michael@0 30481 'n': 556,
michael@0 30482 'o': 556,
michael@0 30483 'p': 556,
michael@0 30484 'q': 556,
michael@0 30485 'r': 333,
michael@0 30486 's': 500,
michael@0 30487 't': 278,
michael@0 30488 'u': 556,
michael@0 30489 'v': 500,
michael@0 30490 'w': 722,
michael@0 30491 'x': 500,
michael@0 30492 'y': 500,
michael@0 30493 'z': 500,
michael@0 30494 'braceleft': 334,
michael@0 30495 'bar': 260,
michael@0 30496 'braceright': 334,
michael@0 30497 'asciitilde': 584,
michael@0 30498 'exclamdown': 333,
michael@0 30499 'cent': 556,
michael@0 30500 'sterling': 556,
michael@0 30501 'fraction': 167,
michael@0 30502 'yen': 556,
michael@0 30503 'florin': 556,
michael@0 30504 'section': 556,
michael@0 30505 'currency': 556,
michael@0 30506 'quotesingle': 191,
michael@0 30507 'quotedblleft': 333,
michael@0 30508 'guillemotleft': 556,
michael@0 30509 'guilsinglleft': 333,
michael@0 30510 'guilsinglright': 333,
michael@0 30511 'fi': 500,
michael@0 30512 'fl': 500,
michael@0 30513 'endash': 556,
michael@0 30514 'dagger': 556,
michael@0 30515 'daggerdbl': 556,
michael@0 30516 'periodcentered': 278,
michael@0 30517 'paragraph': 537,
michael@0 30518 'bullet': 350,
michael@0 30519 'quotesinglbase': 222,
michael@0 30520 'quotedblbase': 333,
michael@0 30521 'quotedblright': 333,
michael@0 30522 'guillemotright': 556,
michael@0 30523 'ellipsis': 1000,
michael@0 30524 'perthousand': 1000,
michael@0 30525 'questiondown': 611,
michael@0 30526 'grave': 333,
michael@0 30527 'acute': 333,
michael@0 30528 'circumflex': 333,
michael@0 30529 'tilde': 333,
michael@0 30530 'macron': 333,
michael@0 30531 'breve': 333,
michael@0 30532 'dotaccent': 333,
michael@0 30533 'dieresis': 333,
michael@0 30534 'ring': 333,
michael@0 30535 'cedilla': 333,
michael@0 30536 'hungarumlaut': 333,
michael@0 30537 'ogonek': 333,
michael@0 30538 'caron': 333,
michael@0 30539 'emdash': 1000,
michael@0 30540 'AE': 1000,
michael@0 30541 'ordfeminine': 370,
michael@0 30542 'Lslash': 556,
michael@0 30543 'Oslash': 778,
michael@0 30544 'OE': 1000,
michael@0 30545 'ordmasculine': 365,
michael@0 30546 'ae': 889,
michael@0 30547 'dotlessi': 278,
michael@0 30548 'lslash': 222,
michael@0 30549 'oslash': 611,
michael@0 30550 'oe': 944,
michael@0 30551 'germandbls': 611,
michael@0 30552 'Idieresis': 278,
michael@0 30553 'eacute': 556,
michael@0 30554 'abreve': 556,
michael@0 30555 'uhungarumlaut': 556,
michael@0 30556 'ecaron': 556,
michael@0 30557 'Ydieresis': 667,
michael@0 30558 'divide': 584,
michael@0 30559 'Yacute': 667,
michael@0 30560 'Acircumflex': 667,
michael@0 30561 'aacute': 556,
michael@0 30562 'Ucircumflex': 722,
michael@0 30563 'yacute': 500,
michael@0 30564 'scommaaccent': 500,
michael@0 30565 'ecircumflex': 556,
michael@0 30566 'Uring': 722,
michael@0 30567 'Udieresis': 722,
michael@0 30568 'aogonek': 556,
michael@0 30569 'Uacute': 722,
michael@0 30570 'uogonek': 556,
michael@0 30571 'Edieresis': 667,
michael@0 30572 'Dcroat': 722,
michael@0 30573 'commaaccent': 250,
michael@0 30574 'copyright': 737,
michael@0 30575 'Emacron': 667,
michael@0 30576 'ccaron': 500,
michael@0 30577 'aring': 556,
michael@0 30578 'Ncommaaccent': 722,
michael@0 30579 'lacute': 222,
michael@0 30580 'agrave': 556,
michael@0 30581 'Tcommaaccent': 611,
michael@0 30582 'Cacute': 722,
michael@0 30583 'atilde': 556,
michael@0 30584 'Edotaccent': 667,
michael@0 30585 'scaron': 500,
michael@0 30586 'scedilla': 500,
michael@0 30587 'iacute': 278,
michael@0 30588 'lozenge': 471,
michael@0 30589 'Rcaron': 722,
michael@0 30590 'Gcommaaccent': 778,
michael@0 30591 'ucircumflex': 556,
michael@0 30592 'acircumflex': 556,
michael@0 30593 'Amacron': 667,
michael@0 30594 'rcaron': 333,
michael@0 30595 'ccedilla': 500,
michael@0 30596 'Zdotaccent': 611,
michael@0 30597 'Thorn': 667,
michael@0 30598 'Omacron': 778,
michael@0 30599 'Racute': 722,
michael@0 30600 'Sacute': 667,
michael@0 30601 'dcaron': 643,
michael@0 30602 'Umacron': 722,
michael@0 30603 'uring': 556,
michael@0 30604 'threesuperior': 333,
michael@0 30605 'Ograve': 778,
michael@0 30606 'Agrave': 667,
michael@0 30607 'Abreve': 667,
michael@0 30608 'multiply': 584,
michael@0 30609 'uacute': 556,
michael@0 30610 'Tcaron': 611,
michael@0 30611 'partialdiff': 476,
michael@0 30612 'ydieresis': 500,
michael@0 30613 'Nacute': 722,
michael@0 30614 'icircumflex': 278,
michael@0 30615 'Ecircumflex': 667,
michael@0 30616 'adieresis': 556,
michael@0 30617 'edieresis': 556,
michael@0 30618 'cacute': 500,
michael@0 30619 'nacute': 556,
michael@0 30620 'umacron': 556,
michael@0 30621 'Ncaron': 722,
michael@0 30622 'Iacute': 278,
michael@0 30623 'plusminus': 584,
michael@0 30624 'brokenbar': 260,
michael@0 30625 'registered': 737,
michael@0 30626 'Gbreve': 778,
michael@0 30627 'Idotaccent': 278,
michael@0 30628 'summation': 600,
michael@0 30629 'Egrave': 667,
michael@0 30630 'racute': 333,
michael@0 30631 'omacron': 556,
michael@0 30632 'Zacute': 611,
michael@0 30633 'Zcaron': 611,
michael@0 30634 'greaterequal': 549,
michael@0 30635 'Eth': 722,
michael@0 30636 'Ccedilla': 722,
michael@0 30637 'lcommaaccent': 222,
michael@0 30638 'tcaron': 317,
michael@0 30639 'eogonek': 556,
michael@0 30640 'Uogonek': 722,
michael@0 30641 'Aacute': 667,
michael@0 30642 'Adieresis': 667,
michael@0 30643 'egrave': 556,
michael@0 30644 'zacute': 500,
michael@0 30645 'iogonek': 222,
michael@0 30646 'Oacute': 778,
michael@0 30647 'oacute': 556,
michael@0 30648 'amacron': 556,
michael@0 30649 'sacute': 500,
michael@0 30650 'idieresis': 278,
michael@0 30651 'Ocircumflex': 778,
michael@0 30652 'Ugrave': 722,
michael@0 30653 'Delta': 612,
michael@0 30654 'thorn': 556,
michael@0 30655 'twosuperior': 333,
michael@0 30656 'Odieresis': 778,
michael@0 30657 'mu': 556,
michael@0 30658 'igrave': 278,
michael@0 30659 'ohungarumlaut': 556,
michael@0 30660 'Eogonek': 667,
michael@0 30661 'dcroat': 556,
michael@0 30662 'threequarters': 834,
michael@0 30663 'Scedilla': 667,
michael@0 30664 'lcaron': 299,
michael@0 30665 'Kcommaaccent': 667,
michael@0 30666 'Lacute': 556,
michael@0 30667 'trademark': 1000,
michael@0 30668 'edotaccent': 556,
michael@0 30669 'Igrave': 278,
michael@0 30670 'Imacron': 278,
michael@0 30671 'Lcaron': 556,
michael@0 30672 'onehalf': 834,
michael@0 30673 'lessequal': 549,
michael@0 30674 'ocircumflex': 556,
michael@0 30675 'ntilde': 556,
michael@0 30676 'Uhungarumlaut': 722,
michael@0 30677 'Eacute': 667,
michael@0 30678 'emacron': 556,
michael@0 30679 'gbreve': 556,
michael@0 30680 'onequarter': 834,
michael@0 30681 'Scaron': 667,
michael@0 30682 'Scommaaccent': 667,
michael@0 30683 'Ohungarumlaut': 778,
michael@0 30684 'degree': 400,
michael@0 30685 'ograve': 556,
michael@0 30686 'Ccaron': 722,
michael@0 30687 'ugrave': 556,
michael@0 30688 'radical': 453,
michael@0 30689 'Dcaron': 722,
michael@0 30690 'rcommaaccent': 333,
michael@0 30691 'Ntilde': 722,
michael@0 30692 'otilde': 556,
michael@0 30693 'Rcommaaccent': 722,
michael@0 30694 'Lcommaaccent': 556,
michael@0 30695 'Atilde': 667,
michael@0 30696 'Aogonek': 667,
michael@0 30697 'Aring': 667,
michael@0 30698 'Otilde': 778,
michael@0 30699 'zdotaccent': 500,
michael@0 30700 'Ecaron': 667,
michael@0 30701 'Iogonek': 278,
michael@0 30702 'kcommaaccent': 500,
michael@0 30703 'minus': 584,
michael@0 30704 'Icircumflex': 278,
michael@0 30705 'ncaron': 556,
michael@0 30706 'tcommaaccent': 278,
michael@0 30707 'logicalnot': 584,
michael@0 30708 'odieresis': 556,
michael@0 30709 'udieresis': 556,
michael@0 30710 'notequal': 549,
michael@0 30711 'gcommaaccent': 556,
michael@0 30712 'eth': 556,
michael@0 30713 'zcaron': 500,
michael@0 30714 'ncommaaccent': 556,
michael@0 30715 'onesuperior': 333,
michael@0 30716 'imacron': 278,
michael@0 30717 'Euro': 556
michael@0 30718 },
michael@0 30719 'Helvetica-Bold': {
michael@0 30720 'space': 278,
michael@0 30721 'exclam': 333,
michael@0 30722 'quotedbl': 474,
michael@0 30723 'numbersign': 556,
michael@0 30724 'dollar': 556,
michael@0 30725 'percent': 889,
michael@0 30726 'ampersand': 722,
michael@0 30727 'quoteright': 278,
michael@0 30728 'parenleft': 333,
michael@0 30729 'parenright': 333,
michael@0 30730 'asterisk': 389,
michael@0 30731 'plus': 584,
michael@0 30732 'comma': 278,
michael@0 30733 'hyphen': 333,
michael@0 30734 'period': 278,
michael@0 30735 'slash': 278,
michael@0 30736 'zero': 556,
michael@0 30737 'one': 556,
michael@0 30738 'two': 556,
michael@0 30739 'three': 556,
michael@0 30740 'four': 556,
michael@0 30741 'five': 556,
michael@0 30742 'six': 556,
michael@0 30743 'seven': 556,
michael@0 30744 'eight': 556,
michael@0 30745 'nine': 556,
michael@0 30746 'colon': 333,
michael@0 30747 'semicolon': 333,
michael@0 30748 'less': 584,
michael@0 30749 'equal': 584,
michael@0 30750 'greater': 584,
michael@0 30751 'question': 611,
michael@0 30752 'at': 975,
michael@0 30753 'A': 722,
michael@0 30754 'B': 722,
michael@0 30755 'C': 722,
michael@0 30756 'D': 722,
michael@0 30757 'E': 667,
michael@0 30758 'F': 611,
michael@0 30759 'G': 778,
michael@0 30760 'H': 722,
michael@0 30761 'I': 278,
michael@0 30762 'J': 556,
michael@0 30763 'K': 722,
michael@0 30764 'L': 611,
michael@0 30765 'M': 833,
michael@0 30766 'N': 722,
michael@0 30767 'O': 778,
michael@0 30768 'P': 667,
michael@0 30769 'Q': 778,
michael@0 30770 'R': 722,
michael@0 30771 'S': 667,
michael@0 30772 'T': 611,
michael@0 30773 'U': 722,
michael@0 30774 'V': 667,
michael@0 30775 'W': 944,
michael@0 30776 'X': 667,
michael@0 30777 'Y': 667,
michael@0 30778 'Z': 611,
michael@0 30779 'bracketleft': 333,
michael@0 30780 'backslash': 278,
michael@0 30781 'bracketright': 333,
michael@0 30782 'asciicircum': 584,
michael@0 30783 'underscore': 556,
michael@0 30784 'quoteleft': 278,
michael@0 30785 'a': 556,
michael@0 30786 'b': 611,
michael@0 30787 'c': 556,
michael@0 30788 'd': 611,
michael@0 30789 'e': 556,
michael@0 30790 'f': 333,
michael@0 30791 'g': 611,
michael@0 30792 'h': 611,
michael@0 30793 'i': 278,
michael@0 30794 'j': 278,
michael@0 30795 'k': 556,
michael@0 30796 'l': 278,
michael@0 30797 'm': 889,
michael@0 30798 'n': 611,
michael@0 30799 'o': 611,
michael@0 30800 'p': 611,
michael@0 30801 'q': 611,
michael@0 30802 'r': 389,
michael@0 30803 's': 556,
michael@0 30804 't': 333,
michael@0 30805 'u': 611,
michael@0 30806 'v': 556,
michael@0 30807 'w': 778,
michael@0 30808 'x': 556,
michael@0 30809 'y': 556,
michael@0 30810 'z': 500,
michael@0 30811 'braceleft': 389,
michael@0 30812 'bar': 280,
michael@0 30813 'braceright': 389,
michael@0 30814 'asciitilde': 584,
michael@0 30815 'exclamdown': 333,
michael@0 30816 'cent': 556,
michael@0 30817 'sterling': 556,
michael@0 30818 'fraction': 167,
michael@0 30819 'yen': 556,
michael@0 30820 'florin': 556,
michael@0 30821 'section': 556,
michael@0 30822 'currency': 556,
michael@0 30823 'quotesingle': 238,
michael@0 30824 'quotedblleft': 500,
michael@0 30825 'guillemotleft': 556,
michael@0 30826 'guilsinglleft': 333,
michael@0 30827 'guilsinglright': 333,
michael@0 30828 'fi': 611,
michael@0 30829 'fl': 611,
michael@0 30830 'endash': 556,
michael@0 30831 'dagger': 556,
michael@0 30832 'daggerdbl': 556,
michael@0 30833 'periodcentered': 278,
michael@0 30834 'paragraph': 556,
michael@0 30835 'bullet': 350,
michael@0 30836 'quotesinglbase': 278,
michael@0 30837 'quotedblbase': 500,
michael@0 30838 'quotedblright': 500,
michael@0 30839 'guillemotright': 556,
michael@0 30840 'ellipsis': 1000,
michael@0 30841 'perthousand': 1000,
michael@0 30842 'questiondown': 611,
michael@0 30843 'grave': 333,
michael@0 30844 'acute': 333,
michael@0 30845 'circumflex': 333,
michael@0 30846 'tilde': 333,
michael@0 30847 'macron': 333,
michael@0 30848 'breve': 333,
michael@0 30849 'dotaccent': 333,
michael@0 30850 'dieresis': 333,
michael@0 30851 'ring': 333,
michael@0 30852 'cedilla': 333,
michael@0 30853 'hungarumlaut': 333,
michael@0 30854 'ogonek': 333,
michael@0 30855 'caron': 333,
michael@0 30856 'emdash': 1000,
michael@0 30857 'AE': 1000,
michael@0 30858 'ordfeminine': 370,
michael@0 30859 'Lslash': 611,
michael@0 30860 'Oslash': 778,
michael@0 30861 'OE': 1000,
michael@0 30862 'ordmasculine': 365,
michael@0 30863 'ae': 889,
michael@0 30864 'dotlessi': 278,
michael@0 30865 'lslash': 278,
michael@0 30866 'oslash': 611,
michael@0 30867 'oe': 944,
michael@0 30868 'germandbls': 611,
michael@0 30869 'Idieresis': 278,
michael@0 30870 'eacute': 556,
michael@0 30871 'abreve': 556,
michael@0 30872 'uhungarumlaut': 611,
michael@0 30873 'ecaron': 556,
michael@0 30874 'Ydieresis': 667,
michael@0 30875 'divide': 584,
michael@0 30876 'Yacute': 667,
michael@0 30877 'Acircumflex': 722,
michael@0 30878 'aacute': 556,
michael@0 30879 'Ucircumflex': 722,
michael@0 30880 'yacute': 556,
michael@0 30881 'scommaaccent': 556,
michael@0 30882 'ecircumflex': 556,
michael@0 30883 'Uring': 722,
michael@0 30884 'Udieresis': 722,
michael@0 30885 'aogonek': 556,
michael@0 30886 'Uacute': 722,
michael@0 30887 'uogonek': 611,
michael@0 30888 'Edieresis': 667,
michael@0 30889 'Dcroat': 722,
michael@0 30890 'commaaccent': 250,
michael@0 30891 'copyright': 737,
michael@0 30892 'Emacron': 667,
michael@0 30893 'ccaron': 556,
michael@0 30894 'aring': 556,
michael@0 30895 'Ncommaaccent': 722,
michael@0 30896 'lacute': 278,
michael@0 30897 'agrave': 556,
michael@0 30898 'Tcommaaccent': 611,
michael@0 30899 'Cacute': 722,
michael@0 30900 'atilde': 556,
michael@0 30901 'Edotaccent': 667,
michael@0 30902 'scaron': 556,
michael@0 30903 'scedilla': 556,
michael@0 30904 'iacute': 278,
michael@0 30905 'lozenge': 494,
michael@0 30906 'Rcaron': 722,
michael@0 30907 'Gcommaaccent': 778,
michael@0 30908 'ucircumflex': 611,
michael@0 30909 'acircumflex': 556,
michael@0 30910 'Amacron': 722,
michael@0 30911 'rcaron': 389,
michael@0 30912 'ccedilla': 556,
michael@0 30913 'Zdotaccent': 611,
michael@0 30914 'Thorn': 667,
michael@0 30915 'Omacron': 778,
michael@0 30916 'Racute': 722,
michael@0 30917 'Sacute': 667,
michael@0 30918 'dcaron': 743,
michael@0 30919 'Umacron': 722,
michael@0 30920 'uring': 611,
michael@0 30921 'threesuperior': 333,
michael@0 30922 'Ograve': 778,
michael@0 30923 'Agrave': 722,
michael@0 30924 'Abreve': 722,
michael@0 30925 'multiply': 584,
michael@0 30926 'uacute': 611,
michael@0 30927 'Tcaron': 611,
michael@0 30928 'partialdiff': 494,
michael@0 30929 'ydieresis': 556,
michael@0 30930 'Nacute': 722,
michael@0 30931 'icircumflex': 278,
michael@0 30932 'Ecircumflex': 667,
michael@0 30933 'adieresis': 556,
michael@0 30934 'edieresis': 556,
michael@0 30935 'cacute': 556,
michael@0 30936 'nacute': 611,
michael@0 30937 'umacron': 611,
michael@0 30938 'Ncaron': 722,
michael@0 30939 'Iacute': 278,
michael@0 30940 'plusminus': 584,
michael@0 30941 'brokenbar': 280,
michael@0 30942 'registered': 737,
michael@0 30943 'Gbreve': 778,
michael@0 30944 'Idotaccent': 278,
michael@0 30945 'summation': 600,
michael@0 30946 'Egrave': 667,
michael@0 30947 'racute': 389,
michael@0 30948 'omacron': 611,
michael@0 30949 'Zacute': 611,
michael@0 30950 'Zcaron': 611,
michael@0 30951 'greaterequal': 549,
michael@0 30952 'Eth': 722,
michael@0 30953 'Ccedilla': 722,
michael@0 30954 'lcommaaccent': 278,
michael@0 30955 'tcaron': 389,
michael@0 30956 'eogonek': 556,
michael@0 30957 'Uogonek': 722,
michael@0 30958 'Aacute': 722,
michael@0 30959 'Adieresis': 722,
michael@0 30960 'egrave': 556,
michael@0 30961 'zacute': 500,
michael@0 30962 'iogonek': 278,
michael@0 30963 'Oacute': 778,
michael@0 30964 'oacute': 611,
michael@0 30965 'amacron': 556,
michael@0 30966 'sacute': 556,
michael@0 30967 'idieresis': 278,
michael@0 30968 'Ocircumflex': 778,
michael@0 30969 'Ugrave': 722,
michael@0 30970 'Delta': 612,
michael@0 30971 'thorn': 611,
michael@0 30972 'twosuperior': 333,
michael@0 30973 'Odieresis': 778,
michael@0 30974 'mu': 611,
michael@0 30975 'igrave': 278,
michael@0 30976 'ohungarumlaut': 611,
michael@0 30977 'Eogonek': 667,
michael@0 30978 'dcroat': 611,
michael@0 30979 'threequarters': 834,
michael@0 30980 'Scedilla': 667,
michael@0 30981 'lcaron': 400,
michael@0 30982 'Kcommaaccent': 722,
michael@0 30983 'Lacute': 611,
michael@0 30984 'trademark': 1000,
michael@0 30985 'edotaccent': 556,
michael@0 30986 'Igrave': 278,
michael@0 30987 'Imacron': 278,
michael@0 30988 'Lcaron': 611,
michael@0 30989 'onehalf': 834,
michael@0 30990 'lessequal': 549,
michael@0 30991 'ocircumflex': 611,
michael@0 30992 'ntilde': 611,
michael@0 30993 'Uhungarumlaut': 722,
michael@0 30994 'Eacute': 667,
michael@0 30995 'emacron': 556,
michael@0 30996 'gbreve': 611,
michael@0 30997 'onequarter': 834,
michael@0 30998 'Scaron': 667,
michael@0 30999 'Scommaaccent': 667,
michael@0 31000 'Ohungarumlaut': 778,
michael@0 31001 'degree': 400,
michael@0 31002 'ograve': 611,
michael@0 31003 'Ccaron': 722,
michael@0 31004 'ugrave': 611,
michael@0 31005 'radical': 549,
michael@0 31006 'Dcaron': 722,
michael@0 31007 'rcommaaccent': 389,
michael@0 31008 'Ntilde': 722,
michael@0 31009 'otilde': 611,
michael@0 31010 'Rcommaaccent': 722,
michael@0 31011 'Lcommaaccent': 611,
michael@0 31012 'Atilde': 722,
michael@0 31013 'Aogonek': 722,
michael@0 31014 'Aring': 722,
michael@0 31015 'Otilde': 778,
michael@0 31016 'zdotaccent': 500,
michael@0 31017 'Ecaron': 667,
michael@0 31018 'Iogonek': 278,
michael@0 31019 'kcommaaccent': 556,
michael@0 31020 'minus': 584,
michael@0 31021 'Icircumflex': 278,
michael@0 31022 'ncaron': 611,
michael@0 31023 'tcommaaccent': 333,
michael@0 31024 'logicalnot': 584,
michael@0 31025 'odieresis': 611,
michael@0 31026 'udieresis': 611,
michael@0 31027 'notequal': 549,
michael@0 31028 'gcommaaccent': 611,
michael@0 31029 'eth': 611,
michael@0 31030 'zcaron': 500,
michael@0 31031 'ncommaaccent': 611,
michael@0 31032 'onesuperior': 333,
michael@0 31033 'imacron': 278,
michael@0 31034 'Euro': 556
michael@0 31035 },
michael@0 31036 'Helvetica-BoldOblique': {
michael@0 31037 'space': 278,
michael@0 31038 'exclam': 333,
michael@0 31039 'quotedbl': 474,
michael@0 31040 'numbersign': 556,
michael@0 31041 'dollar': 556,
michael@0 31042 'percent': 889,
michael@0 31043 'ampersand': 722,
michael@0 31044 'quoteright': 278,
michael@0 31045 'parenleft': 333,
michael@0 31046 'parenright': 333,
michael@0 31047 'asterisk': 389,
michael@0 31048 'plus': 584,
michael@0 31049 'comma': 278,
michael@0 31050 'hyphen': 333,
michael@0 31051 'period': 278,
michael@0 31052 'slash': 278,
michael@0 31053 'zero': 556,
michael@0 31054 'one': 556,
michael@0 31055 'two': 556,
michael@0 31056 'three': 556,
michael@0 31057 'four': 556,
michael@0 31058 'five': 556,
michael@0 31059 'six': 556,
michael@0 31060 'seven': 556,
michael@0 31061 'eight': 556,
michael@0 31062 'nine': 556,
michael@0 31063 'colon': 333,
michael@0 31064 'semicolon': 333,
michael@0 31065 'less': 584,
michael@0 31066 'equal': 584,
michael@0 31067 'greater': 584,
michael@0 31068 'question': 611,
michael@0 31069 'at': 975,
michael@0 31070 'A': 722,
michael@0 31071 'B': 722,
michael@0 31072 'C': 722,
michael@0 31073 'D': 722,
michael@0 31074 'E': 667,
michael@0 31075 'F': 611,
michael@0 31076 'G': 778,
michael@0 31077 'H': 722,
michael@0 31078 'I': 278,
michael@0 31079 'J': 556,
michael@0 31080 'K': 722,
michael@0 31081 'L': 611,
michael@0 31082 'M': 833,
michael@0 31083 'N': 722,
michael@0 31084 'O': 778,
michael@0 31085 'P': 667,
michael@0 31086 'Q': 778,
michael@0 31087 'R': 722,
michael@0 31088 'S': 667,
michael@0 31089 'T': 611,
michael@0 31090 'U': 722,
michael@0 31091 'V': 667,
michael@0 31092 'W': 944,
michael@0 31093 'X': 667,
michael@0 31094 'Y': 667,
michael@0 31095 'Z': 611,
michael@0 31096 'bracketleft': 333,
michael@0 31097 'backslash': 278,
michael@0 31098 'bracketright': 333,
michael@0 31099 'asciicircum': 584,
michael@0 31100 'underscore': 556,
michael@0 31101 'quoteleft': 278,
michael@0 31102 'a': 556,
michael@0 31103 'b': 611,
michael@0 31104 'c': 556,
michael@0 31105 'd': 611,
michael@0 31106 'e': 556,
michael@0 31107 'f': 333,
michael@0 31108 'g': 611,
michael@0 31109 'h': 611,
michael@0 31110 'i': 278,
michael@0 31111 'j': 278,
michael@0 31112 'k': 556,
michael@0 31113 'l': 278,
michael@0 31114 'm': 889,
michael@0 31115 'n': 611,
michael@0 31116 'o': 611,
michael@0 31117 'p': 611,
michael@0 31118 'q': 611,
michael@0 31119 'r': 389,
michael@0 31120 's': 556,
michael@0 31121 't': 333,
michael@0 31122 'u': 611,
michael@0 31123 'v': 556,
michael@0 31124 'w': 778,
michael@0 31125 'x': 556,
michael@0 31126 'y': 556,
michael@0 31127 'z': 500,
michael@0 31128 'braceleft': 389,
michael@0 31129 'bar': 280,
michael@0 31130 'braceright': 389,
michael@0 31131 'asciitilde': 584,
michael@0 31132 'exclamdown': 333,
michael@0 31133 'cent': 556,
michael@0 31134 'sterling': 556,
michael@0 31135 'fraction': 167,
michael@0 31136 'yen': 556,
michael@0 31137 'florin': 556,
michael@0 31138 'section': 556,
michael@0 31139 'currency': 556,
michael@0 31140 'quotesingle': 238,
michael@0 31141 'quotedblleft': 500,
michael@0 31142 'guillemotleft': 556,
michael@0 31143 'guilsinglleft': 333,
michael@0 31144 'guilsinglright': 333,
michael@0 31145 'fi': 611,
michael@0 31146 'fl': 611,
michael@0 31147 'endash': 556,
michael@0 31148 'dagger': 556,
michael@0 31149 'daggerdbl': 556,
michael@0 31150 'periodcentered': 278,
michael@0 31151 'paragraph': 556,
michael@0 31152 'bullet': 350,
michael@0 31153 'quotesinglbase': 278,
michael@0 31154 'quotedblbase': 500,
michael@0 31155 'quotedblright': 500,
michael@0 31156 'guillemotright': 556,
michael@0 31157 'ellipsis': 1000,
michael@0 31158 'perthousand': 1000,
michael@0 31159 'questiondown': 611,
michael@0 31160 'grave': 333,
michael@0 31161 'acute': 333,
michael@0 31162 'circumflex': 333,
michael@0 31163 'tilde': 333,
michael@0 31164 'macron': 333,
michael@0 31165 'breve': 333,
michael@0 31166 'dotaccent': 333,
michael@0 31167 'dieresis': 333,
michael@0 31168 'ring': 333,
michael@0 31169 'cedilla': 333,
michael@0 31170 'hungarumlaut': 333,
michael@0 31171 'ogonek': 333,
michael@0 31172 'caron': 333,
michael@0 31173 'emdash': 1000,
michael@0 31174 'AE': 1000,
michael@0 31175 'ordfeminine': 370,
michael@0 31176 'Lslash': 611,
michael@0 31177 'Oslash': 778,
michael@0 31178 'OE': 1000,
michael@0 31179 'ordmasculine': 365,
michael@0 31180 'ae': 889,
michael@0 31181 'dotlessi': 278,
michael@0 31182 'lslash': 278,
michael@0 31183 'oslash': 611,
michael@0 31184 'oe': 944,
michael@0 31185 'germandbls': 611,
michael@0 31186 'Idieresis': 278,
michael@0 31187 'eacute': 556,
michael@0 31188 'abreve': 556,
michael@0 31189 'uhungarumlaut': 611,
michael@0 31190 'ecaron': 556,
michael@0 31191 'Ydieresis': 667,
michael@0 31192 'divide': 584,
michael@0 31193 'Yacute': 667,
michael@0 31194 'Acircumflex': 722,
michael@0 31195 'aacute': 556,
michael@0 31196 'Ucircumflex': 722,
michael@0 31197 'yacute': 556,
michael@0 31198 'scommaaccent': 556,
michael@0 31199 'ecircumflex': 556,
michael@0 31200 'Uring': 722,
michael@0 31201 'Udieresis': 722,
michael@0 31202 'aogonek': 556,
michael@0 31203 'Uacute': 722,
michael@0 31204 'uogonek': 611,
michael@0 31205 'Edieresis': 667,
michael@0 31206 'Dcroat': 722,
michael@0 31207 'commaaccent': 250,
michael@0 31208 'copyright': 737,
michael@0 31209 'Emacron': 667,
michael@0 31210 'ccaron': 556,
michael@0 31211 'aring': 556,
michael@0 31212 'Ncommaaccent': 722,
michael@0 31213 'lacute': 278,
michael@0 31214 'agrave': 556,
michael@0 31215 'Tcommaaccent': 611,
michael@0 31216 'Cacute': 722,
michael@0 31217 'atilde': 556,
michael@0 31218 'Edotaccent': 667,
michael@0 31219 'scaron': 556,
michael@0 31220 'scedilla': 556,
michael@0 31221 'iacute': 278,
michael@0 31222 'lozenge': 494,
michael@0 31223 'Rcaron': 722,
michael@0 31224 'Gcommaaccent': 778,
michael@0 31225 'ucircumflex': 611,
michael@0 31226 'acircumflex': 556,
michael@0 31227 'Amacron': 722,
michael@0 31228 'rcaron': 389,
michael@0 31229 'ccedilla': 556,
michael@0 31230 'Zdotaccent': 611,
michael@0 31231 'Thorn': 667,
michael@0 31232 'Omacron': 778,
michael@0 31233 'Racute': 722,
michael@0 31234 'Sacute': 667,
michael@0 31235 'dcaron': 743,
michael@0 31236 'Umacron': 722,
michael@0 31237 'uring': 611,
michael@0 31238 'threesuperior': 333,
michael@0 31239 'Ograve': 778,
michael@0 31240 'Agrave': 722,
michael@0 31241 'Abreve': 722,
michael@0 31242 'multiply': 584,
michael@0 31243 'uacute': 611,
michael@0 31244 'Tcaron': 611,
michael@0 31245 'partialdiff': 494,
michael@0 31246 'ydieresis': 556,
michael@0 31247 'Nacute': 722,
michael@0 31248 'icircumflex': 278,
michael@0 31249 'Ecircumflex': 667,
michael@0 31250 'adieresis': 556,
michael@0 31251 'edieresis': 556,
michael@0 31252 'cacute': 556,
michael@0 31253 'nacute': 611,
michael@0 31254 'umacron': 611,
michael@0 31255 'Ncaron': 722,
michael@0 31256 'Iacute': 278,
michael@0 31257 'plusminus': 584,
michael@0 31258 'brokenbar': 280,
michael@0 31259 'registered': 737,
michael@0 31260 'Gbreve': 778,
michael@0 31261 'Idotaccent': 278,
michael@0 31262 'summation': 600,
michael@0 31263 'Egrave': 667,
michael@0 31264 'racute': 389,
michael@0 31265 'omacron': 611,
michael@0 31266 'Zacute': 611,
michael@0 31267 'Zcaron': 611,
michael@0 31268 'greaterequal': 549,
michael@0 31269 'Eth': 722,
michael@0 31270 'Ccedilla': 722,
michael@0 31271 'lcommaaccent': 278,
michael@0 31272 'tcaron': 389,
michael@0 31273 'eogonek': 556,
michael@0 31274 'Uogonek': 722,
michael@0 31275 'Aacute': 722,
michael@0 31276 'Adieresis': 722,
michael@0 31277 'egrave': 556,
michael@0 31278 'zacute': 500,
michael@0 31279 'iogonek': 278,
michael@0 31280 'Oacute': 778,
michael@0 31281 'oacute': 611,
michael@0 31282 'amacron': 556,
michael@0 31283 'sacute': 556,
michael@0 31284 'idieresis': 278,
michael@0 31285 'Ocircumflex': 778,
michael@0 31286 'Ugrave': 722,
michael@0 31287 'Delta': 612,
michael@0 31288 'thorn': 611,
michael@0 31289 'twosuperior': 333,
michael@0 31290 'Odieresis': 778,
michael@0 31291 'mu': 611,
michael@0 31292 'igrave': 278,
michael@0 31293 'ohungarumlaut': 611,
michael@0 31294 'Eogonek': 667,
michael@0 31295 'dcroat': 611,
michael@0 31296 'threequarters': 834,
michael@0 31297 'Scedilla': 667,
michael@0 31298 'lcaron': 400,
michael@0 31299 'Kcommaaccent': 722,
michael@0 31300 'Lacute': 611,
michael@0 31301 'trademark': 1000,
michael@0 31302 'edotaccent': 556,
michael@0 31303 'Igrave': 278,
michael@0 31304 'Imacron': 278,
michael@0 31305 'Lcaron': 611,
michael@0 31306 'onehalf': 834,
michael@0 31307 'lessequal': 549,
michael@0 31308 'ocircumflex': 611,
michael@0 31309 'ntilde': 611,
michael@0 31310 'Uhungarumlaut': 722,
michael@0 31311 'Eacute': 667,
michael@0 31312 'emacron': 556,
michael@0 31313 'gbreve': 611,
michael@0 31314 'onequarter': 834,
michael@0 31315 'Scaron': 667,
michael@0 31316 'Scommaaccent': 667,
michael@0 31317 'Ohungarumlaut': 778,
michael@0 31318 'degree': 400,
michael@0 31319 'ograve': 611,
michael@0 31320 'Ccaron': 722,
michael@0 31321 'ugrave': 611,
michael@0 31322 'radical': 549,
michael@0 31323 'Dcaron': 722,
michael@0 31324 'rcommaaccent': 389,
michael@0 31325 'Ntilde': 722,
michael@0 31326 'otilde': 611,
michael@0 31327 'Rcommaaccent': 722,
michael@0 31328 'Lcommaaccent': 611,
michael@0 31329 'Atilde': 722,
michael@0 31330 'Aogonek': 722,
michael@0 31331 'Aring': 722,
michael@0 31332 'Otilde': 778,
michael@0 31333 'zdotaccent': 500,
michael@0 31334 'Ecaron': 667,
michael@0 31335 'Iogonek': 278,
michael@0 31336 'kcommaaccent': 556,
michael@0 31337 'minus': 584,
michael@0 31338 'Icircumflex': 278,
michael@0 31339 'ncaron': 611,
michael@0 31340 'tcommaaccent': 333,
michael@0 31341 'logicalnot': 584,
michael@0 31342 'odieresis': 611,
michael@0 31343 'udieresis': 611,
michael@0 31344 'notequal': 549,
michael@0 31345 'gcommaaccent': 611,
michael@0 31346 'eth': 611,
michael@0 31347 'zcaron': 500,
michael@0 31348 'ncommaaccent': 611,
michael@0 31349 'onesuperior': 333,
michael@0 31350 'imacron': 278,
michael@0 31351 'Euro': 556
michael@0 31352 },
michael@0 31353 'Helvetica-Oblique' : {
michael@0 31354 'space': 278,
michael@0 31355 'exclam': 278,
michael@0 31356 'quotedbl': 355,
michael@0 31357 'numbersign': 556,
michael@0 31358 'dollar': 556,
michael@0 31359 'percent': 889,
michael@0 31360 'ampersand': 667,
michael@0 31361 'quoteright': 222,
michael@0 31362 'parenleft': 333,
michael@0 31363 'parenright': 333,
michael@0 31364 'asterisk': 389,
michael@0 31365 'plus': 584,
michael@0 31366 'comma': 278,
michael@0 31367 'hyphen': 333,
michael@0 31368 'period': 278,
michael@0 31369 'slash': 278,
michael@0 31370 'zero': 556,
michael@0 31371 'one': 556,
michael@0 31372 'two': 556,
michael@0 31373 'three': 556,
michael@0 31374 'four': 556,
michael@0 31375 'five': 556,
michael@0 31376 'six': 556,
michael@0 31377 'seven': 556,
michael@0 31378 'eight': 556,
michael@0 31379 'nine': 556,
michael@0 31380 'colon': 278,
michael@0 31381 'semicolon': 278,
michael@0 31382 'less': 584,
michael@0 31383 'equal': 584,
michael@0 31384 'greater': 584,
michael@0 31385 'question': 556,
michael@0 31386 'at': 1015,
michael@0 31387 'A': 667,
michael@0 31388 'B': 667,
michael@0 31389 'C': 722,
michael@0 31390 'D': 722,
michael@0 31391 'E': 667,
michael@0 31392 'F': 611,
michael@0 31393 'G': 778,
michael@0 31394 'H': 722,
michael@0 31395 'I': 278,
michael@0 31396 'J': 500,
michael@0 31397 'K': 667,
michael@0 31398 'L': 556,
michael@0 31399 'M': 833,
michael@0 31400 'N': 722,
michael@0 31401 'O': 778,
michael@0 31402 'P': 667,
michael@0 31403 'Q': 778,
michael@0 31404 'R': 722,
michael@0 31405 'S': 667,
michael@0 31406 'T': 611,
michael@0 31407 'U': 722,
michael@0 31408 'V': 667,
michael@0 31409 'W': 944,
michael@0 31410 'X': 667,
michael@0 31411 'Y': 667,
michael@0 31412 'Z': 611,
michael@0 31413 'bracketleft': 278,
michael@0 31414 'backslash': 278,
michael@0 31415 'bracketright': 278,
michael@0 31416 'asciicircum': 469,
michael@0 31417 'underscore': 556,
michael@0 31418 'quoteleft': 222,
michael@0 31419 'a': 556,
michael@0 31420 'b': 556,
michael@0 31421 'c': 500,
michael@0 31422 'd': 556,
michael@0 31423 'e': 556,
michael@0 31424 'f': 278,
michael@0 31425 'g': 556,
michael@0 31426 'h': 556,
michael@0 31427 'i': 222,
michael@0 31428 'j': 222,
michael@0 31429 'k': 500,
michael@0 31430 'l': 222,
michael@0 31431 'm': 833,
michael@0 31432 'n': 556,
michael@0 31433 'o': 556,
michael@0 31434 'p': 556,
michael@0 31435 'q': 556,
michael@0 31436 'r': 333,
michael@0 31437 's': 500,
michael@0 31438 't': 278,
michael@0 31439 'u': 556,
michael@0 31440 'v': 500,
michael@0 31441 'w': 722,
michael@0 31442 'x': 500,
michael@0 31443 'y': 500,
michael@0 31444 'z': 500,
michael@0 31445 'braceleft': 334,
michael@0 31446 'bar': 260,
michael@0 31447 'braceright': 334,
michael@0 31448 'asciitilde': 584,
michael@0 31449 'exclamdown': 333,
michael@0 31450 'cent': 556,
michael@0 31451 'sterling': 556,
michael@0 31452 'fraction': 167,
michael@0 31453 'yen': 556,
michael@0 31454 'florin': 556,
michael@0 31455 'section': 556,
michael@0 31456 'currency': 556,
michael@0 31457 'quotesingle': 191,
michael@0 31458 'quotedblleft': 333,
michael@0 31459 'guillemotleft': 556,
michael@0 31460 'guilsinglleft': 333,
michael@0 31461 'guilsinglright': 333,
michael@0 31462 'fi': 500,
michael@0 31463 'fl': 500,
michael@0 31464 'endash': 556,
michael@0 31465 'dagger': 556,
michael@0 31466 'daggerdbl': 556,
michael@0 31467 'periodcentered': 278,
michael@0 31468 'paragraph': 537,
michael@0 31469 'bullet': 350,
michael@0 31470 'quotesinglbase': 222,
michael@0 31471 'quotedblbase': 333,
michael@0 31472 'quotedblright': 333,
michael@0 31473 'guillemotright': 556,
michael@0 31474 'ellipsis': 1000,
michael@0 31475 'perthousand': 1000,
michael@0 31476 'questiondown': 611,
michael@0 31477 'grave': 333,
michael@0 31478 'acute': 333,
michael@0 31479 'circumflex': 333,
michael@0 31480 'tilde': 333,
michael@0 31481 'macron': 333,
michael@0 31482 'breve': 333,
michael@0 31483 'dotaccent': 333,
michael@0 31484 'dieresis': 333,
michael@0 31485 'ring': 333,
michael@0 31486 'cedilla': 333,
michael@0 31487 'hungarumlaut': 333,
michael@0 31488 'ogonek': 333,
michael@0 31489 'caron': 333,
michael@0 31490 'emdash': 1000,
michael@0 31491 'AE': 1000,
michael@0 31492 'ordfeminine': 370,
michael@0 31493 'Lslash': 556,
michael@0 31494 'Oslash': 778,
michael@0 31495 'OE': 1000,
michael@0 31496 'ordmasculine': 365,
michael@0 31497 'ae': 889,
michael@0 31498 'dotlessi': 278,
michael@0 31499 'lslash': 222,
michael@0 31500 'oslash': 611,
michael@0 31501 'oe': 944,
michael@0 31502 'germandbls': 611,
michael@0 31503 'Idieresis': 278,
michael@0 31504 'eacute': 556,
michael@0 31505 'abreve': 556,
michael@0 31506 'uhungarumlaut': 556,
michael@0 31507 'ecaron': 556,
michael@0 31508 'Ydieresis': 667,
michael@0 31509 'divide': 584,
michael@0 31510 'Yacute': 667,
michael@0 31511 'Acircumflex': 667,
michael@0 31512 'aacute': 556,
michael@0 31513 'Ucircumflex': 722,
michael@0 31514 'yacute': 500,
michael@0 31515 'scommaaccent': 500,
michael@0 31516 'ecircumflex': 556,
michael@0 31517 'Uring': 722,
michael@0 31518 'Udieresis': 722,
michael@0 31519 'aogonek': 556,
michael@0 31520 'Uacute': 722,
michael@0 31521 'uogonek': 556,
michael@0 31522 'Edieresis': 667,
michael@0 31523 'Dcroat': 722,
michael@0 31524 'commaaccent': 250,
michael@0 31525 'copyright': 737,
michael@0 31526 'Emacron': 667,
michael@0 31527 'ccaron': 500,
michael@0 31528 'aring': 556,
michael@0 31529 'Ncommaaccent': 722,
michael@0 31530 'lacute': 222,
michael@0 31531 'agrave': 556,
michael@0 31532 'Tcommaaccent': 611,
michael@0 31533 'Cacute': 722,
michael@0 31534 'atilde': 556,
michael@0 31535 'Edotaccent': 667,
michael@0 31536 'scaron': 500,
michael@0 31537 'scedilla': 500,
michael@0 31538 'iacute': 278,
michael@0 31539 'lozenge': 471,
michael@0 31540 'Rcaron': 722,
michael@0 31541 'Gcommaaccent': 778,
michael@0 31542 'ucircumflex': 556,
michael@0 31543 'acircumflex': 556,
michael@0 31544 'Amacron': 667,
michael@0 31545 'rcaron': 333,
michael@0 31546 'ccedilla': 500,
michael@0 31547 'Zdotaccent': 611,
michael@0 31548 'Thorn': 667,
michael@0 31549 'Omacron': 778,
michael@0 31550 'Racute': 722,
michael@0 31551 'Sacute': 667,
michael@0 31552 'dcaron': 643,
michael@0 31553 'Umacron': 722,
michael@0 31554 'uring': 556,
michael@0 31555 'threesuperior': 333,
michael@0 31556 'Ograve': 778,
michael@0 31557 'Agrave': 667,
michael@0 31558 'Abreve': 667,
michael@0 31559 'multiply': 584,
michael@0 31560 'uacute': 556,
michael@0 31561 'Tcaron': 611,
michael@0 31562 'partialdiff': 476,
michael@0 31563 'ydieresis': 500,
michael@0 31564 'Nacute': 722,
michael@0 31565 'icircumflex': 278,
michael@0 31566 'Ecircumflex': 667,
michael@0 31567 'adieresis': 556,
michael@0 31568 'edieresis': 556,
michael@0 31569 'cacute': 500,
michael@0 31570 'nacute': 556,
michael@0 31571 'umacron': 556,
michael@0 31572 'Ncaron': 722,
michael@0 31573 'Iacute': 278,
michael@0 31574 'plusminus': 584,
michael@0 31575 'brokenbar': 260,
michael@0 31576 'registered': 737,
michael@0 31577 'Gbreve': 778,
michael@0 31578 'Idotaccent': 278,
michael@0 31579 'summation': 600,
michael@0 31580 'Egrave': 667,
michael@0 31581 'racute': 333,
michael@0 31582 'omacron': 556,
michael@0 31583 'Zacute': 611,
michael@0 31584 'Zcaron': 611,
michael@0 31585 'greaterequal': 549,
michael@0 31586 'Eth': 722,
michael@0 31587 'Ccedilla': 722,
michael@0 31588 'lcommaaccent': 222,
michael@0 31589 'tcaron': 317,
michael@0 31590 'eogonek': 556,
michael@0 31591 'Uogonek': 722,
michael@0 31592 'Aacute': 667,
michael@0 31593 'Adieresis': 667,
michael@0 31594 'egrave': 556,
michael@0 31595 'zacute': 500,
michael@0 31596 'iogonek': 222,
michael@0 31597 'Oacute': 778,
michael@0 31598 'oacute': 556,
michael@0 31599 'amacron': 556,
michael@0 31600 'sacute': 500,
michael@0 31601 'idieresis': 278,
michael@0 31602 'Ocircumflex': 778,
michael@0 31603 'Ugrave': 722,
michael@0 31604 'Delta': 612,
michael@0 31605 'thorn': 556,
michael@0 31606 'twosuperior': 333,
michael@0 31607 'Odieresis': 778,
michael@0 31608 'mu': 556,
michael@0 31609 'igrave': 278,
michael@0 31610 'ohungarumlaut': 556,
michael@0 31611 'Eogonek': 667,
michael@0 31612 'dcroat': 556,
michael@0 31613 'threequarters': 834,
michael@0 31614 'Scedilla': 667,
michael@0 31615 'lcaron': 299,
michael@0 31616 'Kcommaaccent': 667,
michael@0 31617 'Lacute': 556,
michael@0 31618 'trademark': 1000,
michael@0 31619 'edotaccent': 556,
michael@0 31620 'Igrave': 278,
michael@0 31621 'Imacron': 278,
michael@0 31622 'Lcaron': 556,
michael@0 31623 'onehalf': 834,
michael@0 31624 'lessequal': 549,
michael@0 31625 'ocircumflex': 556,
michael@0 31626 'ntilde': 556,
michael@0 31627 'Uhungarumlaut': 722,
michael@0 31628 'Eacute': 667,
michael@0 31629 'emacron': 556,
michael@0 31630 'gbreve': 556,
michael@0 31631 'onequarter': 834,
michael@0 31632 'Scaron': 667,
michael@0 31633 'Scommaaccent': 667,
michael@0 31634 'Ohungarumlaut': 778,
michael@0 31635 'degree': 400,
michael@0 31636 'ograve': 556,
michael@0 31637 'Ccaron': 722,
michael@0 31638 'ugrave': 556,
michael@0 31639 'radical': 453,
michael@0 31640 'Dcaron': 722,
michael@0 31641 'rcommaaccent': 333,
michael@0 31642 'Ntilde': 722,
michael@0 31643 'otilde': 556,
michael@0 31644 'Rcommaaccent': 722,
michael@0 31645 'Lcommaaccent': 556,
michael@0 31646 'Atilde': 667,
michael@0 31647 'Aogonek': 667,
michael@0 31648 'Aring': 667,
michael@0 31649 'Otilde': 778,
michael@0 31650 'zdotaccent': 500,
michael@0 31651 'Ecaron': 667,
michael@0 31652 'Iogonek': 278,
michael@0 31653 'kcommaaccent': 500,
michael@0 31654 'minus': 584,
michael@0 31655 'Icircumflex': 278,
michael@0 31656 'ncaron': 556,
michael@0 31657 'tcommaaccent': 278,
michael@0 31658 'logicalnot': 584,
michael@0 31659 'odieresis': 556,
michael@0 31660 'udieresis': 556,
michael@0 31661 'notequal': 549,
michael@0 31662 'gcommaaccent': 556,
michael@0 31663 'eth': 556,
michael@0 31664 'zcaron': 500,
michael@0 31665 'ncommaaccent': 556,
michael@0 31666 'onesuperior': 333,
michael@0 31667 'imacron': 278,
michael@0 31668 'Euro': 556
michael@0 31669 },
michael@0 31670 'Symbol': {
michael@0 31671 'space': 250,
michael@0 31672 'exclam': 333,
michael@0 31673 'universal': 713,
michael@0 31674 'numbersign': 500,
michael@0 31675 'existential': 549,
michael@0 31676 'percent': 833,
michael@0 31677 'ampersand': 778,
michael@0 31678 'suchthat': 439,
michael@0 31679 'parenleft': 333,
michael@0 31680 'parenright': 333,
michael@0 31681 'asteriskmath': 500,
michael@0 31682 'plus': 549,
michael@0 31683 'comma': 250,
michael@0 31684 'minus': 549,
michael@0 31685 'period': 250,
michael@0 31686 'slash': 278,
michael@0 31687 'zero': 500,
michael@0 31688 'one': 500,
michael@0 31689 'two': 500,
michael@0 31690 'three': 500,
michael@0 31691 'four': 500,
michael@0 31692 'five': 500,
michael@0 31693 'six': 500,
michael@0 31694 'seven': 500,
michael@0 31695 'eight': 500,
michael@0 31696 'nine': 500,
michael@0 31697 'colon': 278,
michael@0 31698 'semicolon': 278,
michael@0 31699 'less': 549,
michael@0 31700 'equal': 549,
michael@0 31701 'greater': 549,
michael@0 31702 'question': 444,
michael@0 31703 'congruent': 549,
michael@0 31704 'Alpha': 722,
michael@0 31705 'Beta': 667,
michael@0 31706 'Chi': 722,
michael@0 31707 'Delta': 612,
michael@0 31708 'Epsilon': 611,
michael@0 31709 'Phi': 763,
michael@0 31710 'Gamma': 603,
michael@0 31711 'Eta': 722,
michael@0 31712 'Iota': 333,
michael@0 31713 'theta1': 631,
michael@0 31714 'Kappa': 722,
michael@0 31715 'Lambda': 686,
michael@0 31716 'Mu': 889,
michael@0 31717 'Nu': 722,
michael@0 31718 'Omicron': 722,
michael@0 31719 'Pi': 768,
michael@0 31720 'Theta': 741,
michael@0 31721 'Rho': 556,
michael@0 31722 'Sigma': 592,
michael@0 31723 'Tau': 611,
michael@0 31724 'Upsilon': 690,
michael@0 31725 'sigma1': 439,
michael@0 31726 'Omega': 768,
michael@0 31727 'Xi': 645,
michael@0 31728 'Psi': 795,
michael@0 31729 'Zeta': 611,
michael@0 31730 'bracketleft': 333,
michael@0 31731 'therefore': 863,
michael@0 31732 'bracketright': 333,
michael@0 31733 'perpendicular': 658,
michael@0 31734 'underscore': 500,
michael@0 31735 'radicalex': 500,
michael@0 31736 'alpha': 631,
michael@0 31737 'beta': 549,
michael@0 31738 'chi': 549,
michael@0 31739 'delta': 494,
michael@0 31740 'epsilon': 439,
michael@0 31741 'phi': 521,
michael@0 31742 'gamma': 411,
michael@0 31743 'eta': 603,
michael@0 31744 'iota': 329,
michael@0 31745 'phi1': 603,
michael@0 31746 'kappa': 549,
michael@0 31747 'lambda': 549,
michael@0 31748 'mu': 576,
michael@0 31749 'nu': 521,
michael@0 31750 'omicron': 549,
michael@0 31751 'pi': 549,
michael@0 31752 'theta': 521,
michael@0 31753 'rho': 549,
michael@0 31754 'sigma': 603,
michael@0 31755 'tau': 439,
michael@0 31756 'upsilon': 576,
michael@0 31757 'omega1': 713,
michael@0 31758 'omega': 686,
michael@0 31759 'xi': 493,
michael@0 31760 'psi': 686,
michael@0 31761 'zeta': 494,
michael@0 31762 'braceleft': 480,
michael@0 31763 'bar': 200,
michael@0 31764 'braceright': 480,
michael@0 31765 'similar': 549,
michael@0 31766 'Euro': 750,
michael@0 31767 'Upsilon1': 620,
michael@0 31768 'minute': 247,
michael@0 31769 'lessequal': 549,
michael@0 31770 'fraction': 167,
michael@0 31771 'infinity': 713,
michael@0 31772 'florin': 500,
michael@0 31773 'club': 753,
michael@0 31774 'diamond': 753,
michael@0 31775 'heart': 753,
michael@0 31776 'spade': 753,
michael@0 31777 'arrowboth': 1042,
michael@0 31778 'arrowleft': 987,
michael@0 31779 'arrowup': 603,
michael@0 31780 'arrowright': 987,
michael@0 31781 'arrowdown': 603,
michael@0 31782 'degree': 400,
michael@0 31783 'plusminus': 549,
michael@0 31784 'second': 411,
michael@0 31785 'greaterequal': 549,
michael@0 31786 'multiply': 549,
michael@0 31787 'proportional': 713,
michael@0 31788 'partialdiff': 494,
michael@0 31789 'bullet': 460,
michael@0 31790 'divide': 549,
michael@0 31791 'notequal': 549,
michael@0 31792 'equivalence': 549,
michael@0 31793 'approxequal': 549,
michael@0 31794 'ellipsis': 1000,
michael@0 31795 'arrowvertex': 603,
michael@0 31796 'arrowhorizex': 1000,
michael@0 31797 'carriagereturn': 658,
michael@0 31798 'aleph': 823,
michael@0 31799 'Ifraktur': 686,
michael@0 31800 'Rfraktur': 795,
michael@0 31801 'weierstrass': 987,
michael@0 31802 'circlemultiply': 768,
michael@0 31803 'circleplus': 768,
michael@0 31804 'emptyset': 823,
michael@0 31805 'intersection': 768,
michael@0 31806 'union': 768,
michael@0 31807 'propersuperset': 713,
michael@0 31808 'reflexsuperset': 713,
michael@0 31809 'notsubset': 713,
michael@0 31810 'propersubset': 713,
michael@0 31811 'reflexsubset': 713,
michael@0 31812 'element': 713,
michael@0 31813 'notelement': 713,
michael@0 31814 'angle': 768,
michael@0 31815 'gradient': 713,
michael@0 31816 'registerserif': 790,
michael@0 31817 'copyrightserif': 790,
michael@0 31818 'trademarkserif': 890,
michael@0 31819 'product': 823,
michael@0 31820 'radical': 549,
michael@0 31821 'dotmath': 250,
michael@0 31822 'logicalnot': 713,
michael@0 31823 'logicaland': 603,
michael@0 31824 'logicalor': 603,
michael@0 31825 'arrowdblboth': 1042,
michael@0 31826 'arrowdblleft': 987,
michael@0 31827 'arrowdblup': 603,
michael@0 31828 'arrowdblright': 987,
michael@0 31829 'arrowdbldown': 603,
michael@0 31830 'lozenge': 494,
michael@0 31831 'angleleft': 329,
michael@0 31832 'registersans': 790,
michael@0 31833 'copyrightsans': 790,
michael@0 31834 'trademarksans': 786,
michael@0 31835 'summation': 713,
michael@0 31836 'parenlefttp': 384,
michael@0 31837 'parenleftex': 384,
michael@0 31838 'parenleftbt': 384,
michael@0 31839 'bracketlefttp': 384,
michael@0 31840 'bracketleftex': 384,
michael@0 31841 'bracketleftbt': 384,
michael@0 31842 'bracelefttp': 494,
michael@0 31843 'braceleftmid': 494,
michael@0 31844 'braceleftbt': 494,
michael@0 31845 'braceex': 494,
michael@0 31846 'angleright': 329,
michael@0 31847 'integral': 274,
michael@0 31848 'integraltp': 686,
michael@0 31849 'integralex': 686,
michael@0 31850 'integralbt': 686,
michael@0 31851 'parenrighttp': 384,
michael@0 31852 'parenrightex': 384,
michael@0 31853 'parenrightbt': 384,
michael@0 31854 'bracketrighttp': 384,
michael@0 31855 'bracketrightex': 384,
michael@0 31856 'bracketrightbt': 384,
michael@0 31857 'bracerighttp': 494,
michael@0 31858 'bracerightmid': 494,
michael@0 31859 'bracerightbt': 494,
michael@0 31860 'apple': 790
michael@0 31861 },
michael@0 31862 'Times-Roman': {
michael@0 31863 'space': 250,
michael@0 31864 'exclam': 333,
michael@0 31865 'quotedbl': 408,
michael@0 31866 'numbersign': 500,
michael@0 31867 'dollar': 500,
michael@0 31868 'percent': 833,
michael@0 31869 'ampersand': 778,
michael@0 31870 'quoteright': 333,
michael@0 31871 'parenleft': 333,
michael@0 31872 'parenright': 333,
michael@0 31873 'asterisk': 500,
michael@0 31874 'plus': 564,
michael@0 31875 'comma': 250,
michael@0 31876 'hyphen': 333,
michael@0 31877 'period': 250,
michael@0 31878 'slash': 278,
michael@0 31879 'zero': 500,
michael@0 31880 'one': 500,
michael@0 31881 'two': 500,
michael@0 31882 'three': 500,
michael@0 31883 'four': 500,
michael@0 31884 'five': 500,
michael@0 31885 'six': 500,
michael@0 31886 'seven': 500,
michael@0 31887 'eight': 500,
michael@0 31888 'nine': 500,
michael@0 31889 'colon': 278,
michael@0 31890 'semicolon': 278,
michael@0 31891 'less': 564,
michael@0 31892 'equal': 564,
michael@0 31893 'greater': 564,
michael@0 31894 'question': 444,
michael@0 31895 'at': 921,
michael@0 31896 'A': 722,
michael@0 31897 'B': 667,
michael@0 31898 'C': 667,
michael@0 31899 'D': 722,
michael@0 31900 'E': 611,
michael@0 31901 'F': 556,
michael@0 31902 'G': 722,
michael@0 31903 'H': 722,
michael@0 31904 'I': 333,
michael@0 31905 'J': 389,
michael@0 31906 'K': 722,
michael@0 31907 'L': 611,
michael@0 31908 'M': 889,
michael@0 31909 'N': 722,
michael@0 31910 'O': 722,
michael@0 31911 'P': 556,
michael@0 31912 'Q': 722,
michael@0 31913 'R': 667,
michael@0 31914 'S': 556,
michael@0 31915 'T': 611,
michael@0 31916 'U': 722,
michael@0 31917 'V': 722,
michael@0 31918 'W': 944,
michael@0 31919 'X': 722,
michael@0 31920 'Y': 722,
michael@0 31921 'Z': 611,
michael@0 31922 'bracketleft': 333,
michael@0 31923 'backslash': 278,
michael@0 31924 'bracketright': 333,
michael@0 31925 'asciicircum': 469,
michael@0 31926 'underscore': 500,
michael@0 31927 'quoteleft': 333,
michael@0 31928 'a': 444,
michael@0 31929 'b': 500,
michael@0 31930 'c': 444,
michael@0 31931 'd': 500,
michael@0 31932 'e': 444,
michael@0 31933 'f': 333,
michael@0 31934 'g': 500,
michael@0 31935 'h': 500,
michael@0 31936 'i': 278,
michael@0 31937 'j': 278,
michael@0 31938 'k': 500,
michael@0 31939 'l': 278,
michael@0 31940 'm': 778,
michael@0 31941 'n': 500,
michael@0 31942 'o': 500,
michael@0 31943 'p': 500,
michael@0 31944 'q': 500,
michael@0 31945 'r': 333,
michael@0 31946 's': 389,
michael@0 31947 't': 278,
michael@0 31948 'u': 500,
michael@0 31949 'v': 500,
michael@0 31950 'w': 722,
michael@0 31951 'x': 500,
michael@0 31952 'y': 500,
michael@0 31953 'z': 444,
michael@0 31954 'braceleft': 480,
michael@0 31955 'bar': 200,
michael@0 31956 'braceright': 480,
michael@0 31957 'asciitilde': 541,
michael@0 31958 'exclamdown': 333,
michael@0 31959 'cent': 500,
michael@0 31960 'sterling': 500,
michael@0 31961 'fraction': 167,
michael@0 31962 'yen': 500,
michael@0 31963 'florin': 500,
michael@0 31964 'section': 500,
michael@0 31965 'currency': 500,
michael@0 31966 'quotesingle': 180,
michael@0 31967 'quotedblleft': 444,
michael@0 31968 'guillemotleft': 500,
michael@0 31969 'guilsinglleft': 333,
michael@0 31970 'guilsinglright': 333,
michael@0 31971 'fi': 556,
michael@0 31972 'fl': 556,
michael@0 31973 'endash': 500,
michael@0 31974 'dagger': 500,
michael@0 31975 'daggerdbl': 500,
michael@0 31976 'periodcentered': 250,
michael@0 31977 'paragraph': 453,
michael@0 31978 'bullet': 350,
michael@0 31979 'quotesinglbase': 333,
michael@0 31980 'quotedblbase': 444,
michael@0 31981 'quotedblright': 444,
michael@0 31982 'guillemotright': 500,
michael@0 31983 'ellipsis': 1000,
michael@0 31984 'perthousand': 1000,
michael@0 31985 'questiondown': 444,
michael@0 31986 'grave': 333,
michael@0 31987 'acute': 333,
michael@0 31988 'circumflex': 333,
michael@0 31989 'tilde': 333,
michael@0 31990 'macron': 333,
michael@0 31991 'breve': 333,
michael@0 31992 'dotaccent': 333,
michael@0 31993 'dieresis': 333,
michael@0 31994 'ring': 333,
michael@0 31995 'cedilla': 333,
michael@0 31996 'hungarumlaut': 333,
michael@0 31997 'ogonek': 333,
michael@0 31998 'caron': 333,
michael@0 31999 'emdash': 1000,
michael@0 32000 'AE': 889,
michael@0 32001 'ordfeminine': 276,
michael@0 32002 'Lslash': 611,
michael@0 32003 'Oslash': 722,
michael@0 32004 'OE': 889,
michael@0 32005 'ordmasculine': 310,
michael@0 32006 'ae': 667,
michael@0 32007 'dotlessi': 278,
michael@0 32008 'lslash': 278,
michael@0 32009 'oslash': 500,
michael@0 32010 'oe': 722,
michael@0 32011 'germandbls': 500,
michael@0 32012 'Idieresis': 333,
michael@0 32013 'eacute': 444,
michael@0 32014 'abreve': 444,
michael@0 32015 'uhungarumlaut': 500,
michael@0 32016 'ecaron': 444,
michael@0 32017 'Ydieresis': 722,
michael@0 32018 'divide': 564,
michael@0 32019 'Yacute': 722,
michael@0 32020 'Acircumflex': 722,
michael@0 32021 'aacute': 444,
michael@0 32022 'Ucircumflex': 722,
michael@0 32023 'yacute': 500,
michael@0 32024 'scommaaccent': 389,
michael@0 32025 'ecircumflex': 444,
michael@0 32026 'Uring': 722,
michael@0 32027 'Udieresis': 722,
michael@0 32028 'aogonek': 444,
michael@0 32029 'Uacute': 722,
michael@0 32030 'uogonek': 500,
michael@0 32031 'Edieresis': 611,
michael@0 32032 'Dcroat': 722,
michael@0 32033 'commaaccent': 250,
michael@0 32034 'copyright': 760,
michael@0 32035 'Emacron': 611,
michael@0 32036 'ccaron': 444,
michael@0 32037 'aring': 444,
michael@0 32038 'Ncommaaccent': 722,
michael@0 32039 'lacute': 278,
michael@0 32040 'agrave': 444,
michael@0 32041 'Tcommaaccent': 611,
michael@0 32042 'Cacute': 667,
michael@0 32043 'atilde': 444,
michael@0 32044 'Edotaccent': 611,
michael@0 32045 'scaron': 389,
michael@0 32046 'scedilla': 389,
michael@0 32047 'iacute': 278,
michael@0 32048 'lozenge': 471,
michael@0 32049 'Rcaron': 667,
michael@0 32050 'Gcommaaccent': 722,
michael@0 32051 'ucircumflex': 500,
michael@0 32052 'acircumflex': 444,
michael@0 32053 'Amacron': 722,
michael@0 32054 'rcaron': 333,
michael@0 32055 'ccedilla': 444,
michael@0 32056 'Zdotaccent': 611,
michael@0 32057 'Thorn': 556,
michael@0 32058 'Omacron': 722,
michael@0 32059 'Racute': 667,
michael@0 32060 'Sacute': 556,
michael@0 32061 'dcaron': 588,
michael@0 32062 'Umacron': 722,
michael@0 32063 'uring': 500,
michael@0 32064 'threesuperior': 300,
michael@0 32065 'Ograve': 722,
michael@0 32066 'Agrave': 722,
michael@0 32067 'Abreve': 722,
michael@0 32068 'multiply': 564,
michael@0 32069 'uacute': 500,
michael@0 32070 'Tcaron': 611,
michael@0 32071 'partialdiff': 476,
michael@0 32072 'ydieresis': 500,
michael@0 32073 'Nacute': 722,
michael@0 32074 'icircumflex': 278,
michael@0 32075 'Ecircumflex': 611,
michael@0 32076 'adieresis': 444,
michael@0 32077 'edieresis': 444,
michael@0 32078 'cacute': 444,
michael@0 32079 'nacute': 500,
michael@0 32080 'umacron': 500,
michael@0 32081 'Ncaron': 722,
michael@0 32082 'Iacute': 333,
michael@0 32083 'plusminus': 564,
michael@0 32084 'brokenbar': 200,
michael@0 32085 'registered': 760,
michael@0 32086 'Gbreve': 722,
michael@0 32087 'Idotaccent': 333,
michael@0 32088 'summation': 600,
michael@0 32089 'Egrave': 611,
michael@0 32090 'racute': 333,
michael@0 32091 'omacron': 500,
michael@0 32092 'Zacute': 611,
michael@0 32093 'Zcaron': 611,
michael@0 32094 'greaterequal': 549,
michael@0 32095 'Eth': 722,
michael@0 32096 'Ccedilla': 667,
michael@0 32097 'lcommaaccent': 278,
michael@0 32098 'tcaron': 326,
michael@0 32099 'eogonek': 444,
michael@0 32100 'Uogonek': 722,
michael@0 32101 'Aacute': 722,
michael@0 32102 'Adieresis': 722,
michael@0 32103 'egrave': 444,
michael@0 32104 'zacute': 444,
michael@0 32105 'iogonek': 278,
michael@0 32106 'Oacute': 722,
michael@0 32107 'oacute': 500,
michael@0 32108 'amacron': 444,
michael@0 32109 'sacute': 389,
michael@0 32110 'idieresis': 278,
michael@0 32111 'Ocircumflex': 722,
michael@0 32112 'Ugrave': 722,
michael@0 32113 'Delta': 612,
michael@0 32114 'thorn': 500,
michael@0 32115 'twosuperior': 300,
michael@0 32116 'Odieresis': 722,
michael@0 32117 'mu': 500,
michael@0 32118 'igrave': 278,
michael@0 32119 'ohungarumlaut': 500,
michael@0 32120 'Eogonek': 611,
michael@0 32121 'dcroat': 500,
michael@0 32122 'threequarters': 750,
michael@0 32123 'Scedilla': 556,
michael@0 32124 'lcaron': 344,
michael@0 32125 'Kcommaaccent': 722,
michael@0 32126 'Lacute': 611,
michael@0 32127 'trademark': 980,
michael@0 32128 'edotaccent': 444,
michael@0 32129 'Igrave': 333,
michael@0 32130 'Imacron': 333,
michael@0 32131 'Lcaron': 611,
michael@0 32132 'onehalf': 750,
michael@0 32133 'lessequal': 549,
michael@0 32134 'ocircumflex': 500,
michael@0 32135 'ntilde': 500,
michael@0 32136 'Uhungarumlaut': 722,
michael@0 32137 'Eacute': 611,
michael@0 32138 'emacron': 444,
michael@0 32139 'gbreve': 500,
michael@0 32140 'onequarter': 750,
michael@0 32141 'Scaron': 556,
michael@0 32142 'Scommaaccent': 556,
michael@0 32143 'Ohungarumlaut': 722,
michael@0 32144 'degree': 400,
michael@0 32145 'ograve': 500,
michael@0 32146 'Ccaron': 667,
michael@0 32147 'ugrave': 500,
michael@0 32148 'radical': 453,
michael@0 32149 'Dcaron': 722,
michael@0 32150 'rcommaaccent': 333,
michael@0 32151 'Ntilde': 722,
michael@0 32152 'otilde': 500,
michael@0 32153 'Rcommaaccent': 667,
michael@0 32154 'Lcommaaccent': 611,
michael@0 32155 'Atilde': 722,
michael@0 32156 'Aogonek': 722,
michael@0 32157 'Aring': 722,
michael@0 32158 'Otilde': 722,
michael@0 32159 'zdotaccent': 444,
michael@0 32160 'Ecaron': 611,
michael@0 32161 'Iogonek': 333,
michael@0 32162 'kcommaaccent': 500,
michael@0 32163 'minus': 564,
michael@0 32164 'Icircumflex': 333,
michael@0 32165 'ncaron': 500,
michael@0 32166 'tcommaaccent': 278,
michael@0 32167 'logicalnot': 564,
michael@0 32168 'odieresis': 500,
michael@0 32169 'udieresis': 500,
michael@0 32170 'notequal': 549,
michael@0 32171 'gcommaaccent': 500,
michael@0 32172 'eth': 500,
michael@0 32173 'zcaron': 444,
michael@0 32174 'ncommaaccent': 500,
michael@0 32175 'onesuperior': 300,
michael@0 32176 'imacron': 278,
michael@0 32177 'Euro': 500
michael@0 32178 },
michael@0 32179 'Times-Bold': {
michael@0 32180 'space': 250,
michael@0 32181 'exclam': 333,
michael@0 32182 'quotedbl': 555,
michael@0 32183 'numbersign': 500,
michael@0 32184 'dollar': 500,
michael@0 32185 'percent': 1000,
michael@0 32186 'ampersand': 833,
michael@0 32187 'quoteright': 333,
michael@0 32188 'parenleft': 333,
michael@0 32189 'parenright': 333,
michael@0 32190 'asterisk': 500,
michael@0 32191 'plus': 570,
michael@0 32192 'comma': 250,
michael@0 32193 'hyphen': 333,
michael@0 32194 'period': 250,
michael@0 32195 'slash': 278,
michael@0 32196 'zero': 500,
michael@0 32197 'one': 500,
michael@0 32198 'two': 500,
michael@0 32199 'three': 500,
michael@0 32200 'four': 500,
michael@0 32201 'five': 500,
michael@0 32202 'six': 500,
michael@0 32203 'seven': 500,
michael@0 32204 'eight': 500,
michael@0 32205 'nine': 500,
michael@0 32206 'colon': 333,
michael@0 32207 'semicolon': 333,
michael@0 32208 'less': 570,
michael@0 32209 'equal': 570,
michael@0 32210 'greater': 570,
michael@0 32211 'question': 500,
michael@0 32212 'at': 930,
michael@0 32213 'A': 722,
michael@0 32214 'B': 667,
michael@0 32215 'C': 722,
michael@0 32216 'D': 722,
michael@0 32217 'E': 667,
michael@0 32218 'F': 611,
michael@0 32219 'G': 778,
michael@0 32220 'H': 778,
michael@0 32221 'I': 389,
michael@0 32222 'J': 500,
michael@0 32223 'K': 778,
michael@0 32224 'L': 667,
michael@0 32225 'M': 944,
michael@0 32226 'N': 722,
michael@0 32227 'O': 778,
michael@0 32228 'P': 611,
michael@0 32229 'Q': 778,
michael@0 32230 'R': 722,
michael@0 32231 'S': 556,
michael@0 32232 'T': 667,
michael@0 32233 'U': 722,
michael@0 32234 'V': 722,
michael@0 32235 'W': 1000,
michael@0 32236 'X': 722,
michael@0 32237 'Y': 722,
michael@0 32238 'Z': 667,
michael@0 32239 'bracketleft': 333,
michael@0 32240 'backslash': 278,
michael@0 32241 'bracketright': 333,
michael@0 32242 'asciicircum': 581,
michael@0 32243 'underscore': 500,
michael@0 32244 'quoteleft': 333,
michael@0 32245 'a': 500,
michael@0 32246 'b': 556,
michael@0 32247 'c': 444,
michael@0 32248 'd': 556,
michael@0 32249 'e': 444,
michael@0 32250 'f': 333,
michael@0 32251 'g': 500,
michael@0 32252 'h': 556,
michael@0 32253 'i': 278,
michael@0 32254 'j': 333,
michael@0 32255 'k': 556,
michael@0 32256 'l': 278,
michael@0 32257 'm': 833,
michael@0 32258 'n': 556,
michael@0 32259 'o': 500,
michael@0 32260 'p': 556,
michael@0 32261 'q': 556,
michael@0 32262 'r': 444,
michael@0 32263 's': 389,
michael@0 32264 't': 333,
michael@0 32265 'u': 556,
michael@0 32266 'v': 500,
michael@0 32267 'w': 722,
michael@0 32268 'x': 500,
michael@0 32269 'y': 500,
michael@0 32270 'z': 444,
michael@0 32271 'braceleft': 394,
michael@0 32272 'bar': 220,
michael@0 32273 'braceright': 394,
michael@0 32274 'asciitilde': 520,
michael@0 32275 'exclamdown': 333,
michael@0 32276 'cent': 500,
michael@0 32277 'sterling': 500,
michael@0 32278 'fraction': 167,
michael@0 32279 'yen': 500,
michael@0 32280 'florin': 500,
michael@0 32281 'section': 500,
michael@0 32282 'currency': 500,
michael@0 32283 'quotesingle': 278,
michael@0 32284 'quotedblleft': 500,
michael@0 32285 'guillemotleft': 500,
michael@0 32286 'guilsinglleft': 333,
michael@0 32287 'guilsinglright': 333,
michael@0 32288 'fi': 556,
michael@0 32289 'fl': 556,
michael@0 32290 'endash': 500,
michael@0 32291 'dagger': 500,
michael@0 32292 'daggerdbl': 500,
michael@0 32293 'periodcentered': 250,
michael@0 32294 'paragraph': 540,
michael@0 32295 'bullet': 350,
michael@0 32296 'quotesinglbase': 333,
michael@0 32297 'quotedblbase': 500,
michael@0 32298 'quotedblright': 500,
michael@0 32299 'guillemotright': 500,
michael@0 32300 'ellipsis': 1000,
michael@0 32301 'perthousand': 1000,
michael@0 32302 'questiondown': 500,
michael@0 32303 'grave': 333,
michael@0 32304 'acute': 333,
michael@0 32305 'circumflex': 333,
michael@0 32306 'tilde': 333,
michael@0 32307 'macron': 333,
michael@0 32308 'breve': 333,
michael@0 32309 'dotaccent': 333,
michael@0 32310 'dieresis': 333,
michael@0 32311 'ring': 333,
michael@0 32312 'cedilla': 333,
michael@0 32313 'hungarumlaut': 333,
michael@0 32314 'ogonek': 333,
michael@0 32315 'caron': 333,
michael@0 32316 'emdash': 1000,
michael@0 32317 'AE': 1000,
michael@0 32318 'ordfeminine': 300,
michael@0 32319 'Lslash': 667,
michael@0 32320 'Oslash': 778,
michael@0 32321 'OE': 1000,
michael@0 32322 'ordmasculine': 330,
michael@0 32323 'ae': 722,
michael@0 32324 'dotlessi': 278,
michael@0 32325 'lslash': 278,
michael@0 32326 'oslash': 500,
michael@0 32327 'oe': 722,
michael@0 32328 'germandbls': 556,
michael@0 32329 'Idieresis': 389,
michael@0 32330 'eacute': 444,
michael@0 32331 'abreve': 500,
michael@0 32332 'uhungarumlaut': 556,
michael@0 32333 'ecaron': 444,
michael@0 32334 'Ydieresis': 722,
michael@0 32335 'divide': 570,
michael@0 32336 'Yacute': 722,
michael@0 32337 'Acircumflex': 722,
michael@0 32338 'aacute': 500,
michael@0 32339 'Ucircumflex': 722,
michael@0 32340 'yacute': 500,
michael@0 32341 'scommaaccent': 389,
michael@0 32342 'ecircumflex': 444,
michael@0 32343 'Uring': 722,
michael@0 32344 'Udieresis': 722,
michael@0 32345 'aogonek': 500,
michael@0 32346 'Uacute': 722,
michael@0 32347 'uogonek': 556,
michael@0 32348 'Edieresis': 667,
michael@0 32349 'Dcroat': 722,
michael@0 32350 'commaaccent': 250,
michael@0 32351 'copyright': 747,
michael@0 32352 'Emacron': 667,
michael@0 32353 'ccaron': 444,
michael@0 32354 'aring': 500,
michael@0 32355 'Ncommaaccent': 722,
michael@0 32356 'lacute': 278,
michael@0 32357 'agrave': 500,
michael@0 32358 'Tcommaaccent': 667,
michael@0 32359 'Cacute': 722,
michael@0 32360 'atilde': 500,
michael@0 32361 'Edotaccent': 667,
michael@0 32362 'scaron': 389,
michael@0 32363 'scedilla': 389,
michael@0 32364 'iacute': 278,
michael@0 32365 'lozenge': 494,
michael@0 32366 'Rcaron': 722,
michael@0 32367 'Gcommaaccent': 778,
michael@0 32368 'ucircumflex': 556,
michael@0 32369 'acircumflex': 500,
michael@0 32370 'Amacron': 722,
michael@0 32371 'rcaron': 444,
michael@0 32372 'ccedilla': 444,
michael@0 32373 'Zdotaccent': 667,
michael@0 32374 'Thorn': 611,
michael@0 32375 'Omacron': 778,
michael@0 32376 'Racute': 722,
michael@0 32377 'Sacute': 556,
michael@0 32378 'dcaron': 672,
michael@0 32379 'Umacron': 722,
michael@0 32380 'uring': 556,
michael@0 32381 'threesuperior': 300,
michael@0 32382 'Ograve': 778,
michael@0 32383 'Agrave': 722,
michael@0 32384 'Abreve': 722,
michael@0 32385 'multiply': 570,
michael@0 32386 'uacute': 556,
michael@0 32387 'Tcaron': 667,
michael@0 32388 'partialdiff': 494,
michael@0 32389 'ydieresis': 500,
michael@0 32390 'Nacute': 722,
michael@0 32391 'icircumflex': 278,
michael@0 32392 'Ecircumflex': 667,
michael@0 32393 'adieresis': 500,
michael@0 32394 'edieresis': 444,
michael@0 32395 'cacute': 444,
michael@0 32396 'nacute': 556,
michael@0 32397 'umacron': 556,
michael@0 32398 'Ncaron': 722,
michael@0 32399 'Iacute': 389,
michael@0 32400 'plusminus': 570,
michael@0 32401 'brokenbar': 220,
michael@0 32402 'registered': 747,
michael@0 32403 'Gbreve': 778,
michael@0 32404 'Idotaccent': 389,
michael@0 32405 'summation': 600,
michael@0 32406 'Egrave': 667,
michael@0 32407 'racute': 444,
michael@0 32408 'omacron': 500,
michael@0 32409 'Zacute': 667,
michael@0 32410 'Zcaron': 667,
michael@0 32411 'greaterequal': 549,
michael@0 32412 'Eth': 722,
michael@0 32413 'Ccedilla': 722,
michael@0 32414 'lcommaaccent': 278,
michael@0 32415 'tcaron': 416,
michael@0 32416 'eogonek': 444,
michael@0 32417 'Uogonek': 722,
michael@0 32418 'Aacute': 722,
michael@0 32419 'Adieresis': 722,
michael@0 32420 'egrave': 444,
michael@0 32421 'zacute': 444,
michael@0 32422 'iogonek': 278,
michael@0 32423 'Oacute': 778,
michael@0 32424 'oacute': 500,
michael@0 32425 'amacron': 500,
michael@0 32426 'sacute': 389,
michael@0 32427 'idieresis': 278,
michael@0 32428 'Ocircumflex': 778,
michael@0 32429 'Ugrave': 722,
michael@0 32430 'Delta': 612,
michael@0 32431 'thorn': 556,
michael@0 32432 'twosuperior': 300,
michael@0 32433 'Odieresis': 778,
michael@0 32434 'mu': 556,
michael@0 32435 'igrave': 278,
michael@0 32436 'ohungarumlaut': 500,
michael@0 32437 'Eogonek': 667,
michael@0 32438 'dcroat': 556,
michael@0 32439 'threequarters': 750,
michael@0 32440 'Scedilla': 556,
michael@0 32441 'lcaron': 394,
michael@0 32442 'Kcommaaccent': 778,
michael@0 32443 'Lacute': 667,
michael@0 32444 'trademark': 1000,
michael@0 32445 'edotaccent': 444,
michael@0 32446 'Igrave': 389,
michael@0 32447 'Imacron': 389,
michael@0 32448 'Lcaron': 667,
michael@0 32449 'onehalf': 750,
michael@0 32450 'lessequal': 549,
michael@0 32451 'ocircumflex': 500,
michael@0 32452 'ntilde': 556,
michael@0 32453 'Uhungarumlaut': 722,
michael@0 32454 'Eacute': 667,
michael@0 32455 'emacron': 444,
michael@0 32456 'gbreve': 500,
michael@0 32457 'onequarter': 750,
michael@0 32458 'Scaron': 556,
michael@0 32459 'Scommaaccent': 556,
michael@0 32460 'Ohungarumlaut': 778,
michael@0 32461 'degree': 400,
michael@0 32462 'ograve': 500,
michael@0 32463 'Ccaron': 722,
michael@0 32464 'ugrave': 556,
michael@0 32465 'radical': 549,
michael@0 32466 'Dcaron': 722,
michael@0 32467 'rcommaaccent': 444,
michael@0 32468 'Ntilde': 722,
michael@0 32469 'otilde': 500,
michael@0 32470 'Rcommaaccent': 722,
michael@0 32471 'Lcommaaccent': 667,
michael@0 32472 'Atilde': 722,
michael@0 32473 'Aogonek': 722,
michael@0 32474 'Aring': 722,
michael@0 32475 'Otilde': 778,
michael@0 32476 'zdotaccent': 444,
michael@0 32477 'Ecaron': 667,
michael@0 32478 'Iogonek': 389,
michael@0 32479 'kcommaaccent': 556,
michael@0 32480 'minus': 570,
michael@0 32481 'Icircumflex': 389,
michael@0 32482 'ncaron': 556,
michael@0 32483 'tcommaaccent': 333,
michael@0 32484 'logicalnot': 570,
michael@0 32485 'odieresis': 500,
michael@0 32486 'udieresis': 556,
michael@0 32487 'notequal': 549,
michael@0 32488 'gcommaaccent': 500,
michael@0 32489 'eth': 500,
michael@0 32490 'zcaron': 444,
michael@0 32491 'ncommaaccent': 556,
michael@0 32492 'onesuperior': 300,
michael@0 32493 'imacron': 278,
michael@0 32494 'Euro': 500
michael@0 32495 },
michael@0 32496 'Times-BoldItalic': {
michael@0 32497 'space': 250,
michael@0 32498 'exclam': 389,
michael@0 32499 'quotedbl': 555,
michael@0 32500 'numbersign': 500,
michael@0 32501 'dollar': 500,
michael@0 32502 'percent': 833,
michael@0 32503 'ampersand': 778,
michael@0 32504 'quoteright': 333,
michael@0 32505 'parenleft': 333,
michael@0 32506 'parenright': 333,
michael@0 32507 'asterisk': 500,
michael@0 32508 'plus': 570,
michael@0 32509 'comma': 250,
michael@0 32510 'hyphen': 333,
michael@0 32511 'period': 250,
michael@0 32512 'slash': 278,
michael@0 32513 'zero': 500,
michael@0 32514 'one': 500,
michael@0 32515 'two': 500,
michael@0 32516 'three': 500,
michael@0 32517 'four': 500,
michael@0 32518 'five': 500,
michael@0 32519 'six': 500,
michael@0 32520 'seven': 500,
michael@0 32521 'eight': 500,
michael@0 32522 'nine': 500,
michael@0 32523 'colon': 333,
michael@0 32524 'semicolon': 333,
michael@0 32525 'less': 570,
michael@0 32526 'equal': 570,
michael@0 32527 'greater': 570,
michael@0 32528 'question': 500,
michael@0 32529 'at': 832,
michael@0 32530 'A': 667,
michael@0 32531 'B': 667,
michael@0 32532 'C': 667,
michael@0 32533 'D': 722,
michael@0 32534 'E': 667,
michael@0 32535 'F': 667,
michael@0 32536 'G': 722,
michael@0 32537 'H': 778,
michael@0 32538 'I': 389,
michael@0 32539 'J': 500,
michael@0 32540 'K': 667,
michael@0 32541 'L': 611,
michael@0 32542 'M': 889,
michael@0 32543 'N': 722,
michael@0 32544 'O': 722,
michael@0 32545 'P': 611,
michael@0 32546 'Q': 722,
michael@0 32547 'R': 667,
michael@0 32548 'S': 556,
michael@0 32549 'T': 611,
michael@0 32550 'U': 722,
michael@0 32551 'V': 667,
michael@0 32552 'W': 889,
michael@0 32553 'X': 667,
michael@0 32554 'Y': 611,
michael@0 32555 'Z': 611,
michael@0 32556 'bracketleft': 333,
michael@0 32557 'backslash': 278,
michael@0 32558 'bracketright': 333,
michael@0 32559 'asciicircum': 570,
michael@0 32560 'underscore': 500,
michael@0 32561 'quoteleft': 333,
michael@0 32562 'a': 500,
michael@0 32563 'b': 500,
michael@0 32564 'c': 444,
michael@0 32565 'd': 500,
michael@0 32566 'e': 444,
michael@0 32567 'f': 333,
michael@0 32568 'g': 500,
michael@0 32569 'h': 556,
michael@0 32570 'i': 278,
michael@0 32571 'j': 278,
michael@0 32572 'k': 500,
michael@0 32573 'l': 278,
michael@0 32574 'm': 778,
michael@0 32575 'n': 556,
michael@0 32576 'o': 500,
michael@0 32577 'p': 500,
michael@0 32578 'q': 500,
michael@0 32579 'r': 389,
michael@0 32580 's': 389,
michael@0 32581 't': 278,
michael@0 32582 'u': 556,
michael@0 32583 'v': 444,
michael@0 32584 'w': 667,
michael@0 32585 'x': 500,
michael@0 32586 'y': 444,
michael@0 32587 'z': 389,
michael@0 32588 'braceleft': 348,
michael@0 32589 'bar': 220,
michael@0 32590 'braceright': 348,
michael@0 32591 'asciitilde': 570,
michael@0 32592 'exclamdown': 389,
michael@0 32593 'cent': 500,
michael@0 32594 'sterling': 500,
michael@0 32595 'fraction': 167,
michael@0 32596 'yen': 500,
michael@0 32597 'florin': 500,
michael@0 32598 'section': 500,
michael@0 32599 'currency': 500,
michael@0 32600 'quotesingle': 278,
michael@0 32601 'quotedblleft': 500,
michael@0 32602 'guillemotleft': 500,
michael@0 32603 'guilsinglleft': 333,
michael@0 32604 'guilsinglright': 333,
michael@0 32605 'fi': 556,
michael@0 32606 'fl': 556,
michael@0 32607 'endash': 500,
michael@0 32608 'dagger': 500,
michael@0 32609 'daggerdbl': 500,
michael@0 32610 'periodcentered': 250,
michael@0 32611 'paragraph': 500,
michael@0 32612 'bullet': 350,
michael@0 32613 'quotesinglbase': 333,
michael@0 32614 'quotedblbase': 500,
michael@0 32615 'quotedblright': 500,
michael@0 32616 'guillemotright': 500,
michael@0 32617 'ellipsis': 1000,
michael@0 32618 'perthousand': 1000,
michael@0 32619 'questiondown': 500,
michael@0 32620 'grave': 333,
michael@0 32621 'acute': 333,
michael@0 32622 'circumflex': 333,
michael@0 32623 'tilde': 333,
michael@0 32624 'macron': 333,
michael@0 32625 'breve': 333,
michael@0 32626 'dotaccent': 333,
michael@0 32627 'dieresis': 333,
michael@0 32628 'ring': 333,
michael@0 32629 'cedilla': 333,
michael@0 32630 'hungarumlaut': 333,
michael@0 32631 'ogonek': 333,
michael@0 32632 'caron': 333,
michael@0 32633 'emdash': 1000,
michael@0 32634 'AE': 944,
michael@0 32635 'ordfeminine': 266,
michael@0 32636 'Lslash': 611,
michael@0 32637 'Oslash': 722,
michael@0 32638 'OE': 944,
michael@0 32639 'ordmasculine': 300,
michael@0 32640 'ae': 722,
michael@0 32641 'dotlessi': 278,
michael@0 32642 'lslash': 278,
michael@0 32643 'oslash': 500,
michael@0 32644 'oe': 722,
michael@0 32645 'germandbls': 500,
michael@0 32646 'Idieresis': 389,
michael@0 32647 'eacute': 444,
michael@0 32648 'abreve': 500,
michael@0 32649 'uhungarumlaut': 556,
michael@0 32650 'ecaron': 444,
michael@0 32651 'Ydieresis': 611,
michael@0 32652 'divide': 570,
michael@0 32653 'Yacute': 611,
michael@0 32654 'Acircumflex': 667,
michael@0 32655 'aacute': 500,
michael@0 32656 'Ucircumflex': 722,
michael@0 32657 'yacute': 444,
michael@0 32658 'scommaaccent': 389,
michael@0 32659 'ecircumflex': 444,
michael@0 32660 'Uring': 722,
michael@0 32661 'Udieresis': 722,
michael@0 32662 'aogonek': 500,
michael@0 32663 'Uacute': 722,
michael@0 32664 'uogonek': 556,
michael@0 32665 'Edieresis': 667,
michael@0 32666 'Dcroat': 722,
michael@0 32667 'commaaccent': 250,
michael@0 32668 'copyright': 747,
michael@0 32669 'Emacron': 667,
michael@0 32670 'ccaron': 444,
michael@0 32671 'aring': 500,
michael@0 32672 'Ncommaaccent': 722,
michael@0 32673 'lacute': 278,
michael@0 32674 'agrave': 500,
michael@0 32675 'Tcommaaccent': 611,
michael@0 32676 'Cacute': 667,
michael@0 32677 'atilde': 500,
michael@0 32678 'Edotaccent': 667,
michael@0 32679 'scaron': 389,
michael@0 32680 'scedilla': 389,
michael@0 32681 'iacute': 278,
michael@0 32682 'lozenge': 494,
michael@0 32683 'Rcaron': 667,
michael@0 32684 'Gcommaaccent': 722,
michael@0 32685 'ucircumflex': 556,
michael@0 32686 'acircumflex': 500,
michael@0 32687 'Amacron': 667,
michael@0 32688 'rcaron': 389,
michael@0 32689 'ccedilla': 444,
michael@0 32690 'Zdotaccent': 611,
michael@0 32691 'Thorn': 611,
michael@0 32692 'Omacron': 722,
michael@0 32693 'Racute': 667,
michael@0 32694 'Sacute': 556,
michael@0 32695 'dcaron': 608,
michael@0 32696 'Umacron': 722,
michael@0 32697 'uring': 556,
michael@0 32698 'threesuperior': 300,
michael@0 32699 'Ograve': 722,
michael@0 32700 'Agrave': 667,
michael@0 32701 'Abreve': 667,
michael@0 32702 'multiply': 570,
michael@0 32703 'uacute': 556,
michael@0 32704 'Tcaron': 611,
michael@0 32705 'partialdiff': 494,
michael@0 32706 'ydieresis': 444,
michael@0 32707 'Nacute': 722,
michael@0 32708 'icircumflex': 278,
michael@0 32709 'Ecircumflex': 667,
michael@0 32710 'adieresis': 500,
michael@0 32711 'edieresis': 444,
michael@0 32712 'cacute': 444,
michael@0 32713 'nacute': 556,
michael@0 32714 'umacron': 556,
michael@0 32715 'Ncaron': 722,
michael@0 32716 'Iacute': 389,
michael@0 32717 'plusminus': 570,
michael@0 32718 'brokenbar': 220,
michael@0 32719 'registered': 747,
michael@0 32720 'Gbreve': 722,
michael@0 32721 'Idotaccent': 389,
michael@0 32722 'summation': 600,
michael@0 32723 'Egrave': 667,
michael@0 32724 'racute': 389,
michael@0 32725 'omacron': 500,
michael@0 32726 'Zacute': 611,
michael@0 32727 'Zcaron': 611,
michael@0 32728 'greaterequal': 549,
michael@0 32729 'Eth': 722,
michael@0 32730 'Ccedilla': 667,
michael@0 32731 'lcommaaccent': 278,
michael@0 32732 'tcaron': 366,
michael@0 32733 'eogonek': 444,
michael@0 32734 'Uogonek': 722,
michael@0 32735 'Aacute': 667,
michael@0 32736 'Adieresis': 667,
michael@0 32737 'egrave': 444,
michael@0 32738 'zacute': 389,
michael@0 32739 'iogonek': 278,
michael@0 32740 'Oacute': 722,
michael@0 32741 'oacute': 500,
michael@0 32742 'amacron': 500,
michael@0 32743 'sacute': 389,
michael@0 32744 'idieresis': 278,
michael@0 32745 'Ocircumflex': 722,
michael@0 32746 'Ugrave': 722,
michael@0 32747 'Delta': 612,
michael@0 32748 'thorn': 500,
michael@0 32749 'twosuperior': 300,
michael@0 32750 'Odieresis': 722,
michael@0 32751 'mu': 576,
michael@0 32752 'igrave': 278,
michael@0 32753 'ohungarumlaut': 500,
michael@0 32754 'Eogonek': 667,
michael@0 32755 'dcroat': 500,
michael@0 32756 'threequarters': 750,
michael@0 32757 'Scedilla': 556,
michael@0 32758 'lcaron': 382,
michael@0 32759 'Kcommaaccent': 667,
michael@0 32760 'Lacute': 611,
michael@0 32761 'trademark': 1000,
michael@0 32762 'edotaccent': 444,
michael@0 32763 'Igrave': 389,
michael@0 32764 'Imacron': 389,
michael@0 32765 'Lcaron': 611,
michael@0 32766 'onehalf': 750,
michael@0 32767 'lessequal': 549,
michael@0 32768 'ocircumflex': 500,
michael@0 32769 'ntilde': 556,
michael@0 32770 'Uhungarumlaut': 722,
michael@0 32771 'Eacute': 667,
michael@0 32772 'emacron': 444,
michael@0 32773 'gbreve': 500,
michael@0 32774 'onequarter': 750,
michael@0 32775 'Scaron': 556,
michael@0 32776 'Scommaaccent': 556,
michael@0 32777 'Ohungarumlaut': 722,
michael@0 32778 'degree': 400,
michael@0 32779 'ograve': 500,
michael@0 32780 'Ccaron': 667,
michael@0 32781 'ugrave': 556,
michael@0 32782 'radical': 549,
michael@0 32783 'Dcaron': 722,
michael@0 32784 'rcommaaccent': 389,
michael@0 32785 'Ntilde': 722,
michael@0 32786 'otilde': 500,
michael@0 32787 'Rcommaaccent': 667,
michael@0 32788 'Lcommaaccent': 611,
michael@0 32789 'Atilde': 667,
michael@0 32790 'Aogonek': 667,
michael@0 32791 'Aring': 667,
michael@0 32792 'Otilde': 722,
michael@0 32793 'zdotaccent': 389,
michael@0 32794 'Ecaron': 667,
michael@0 32795 'Iogonek': 389,
michael@0 32796 'kcommaaccent': 500,
michael@0 32797 'minus': 606,
michael@0 32798 'Icircumflex': 389,
michael@0 32799 'ncaron': 556,
michael@0 32800 'tcommaaccent': 278,
michael@0 32801 'logicalnot': 606,
michael@0 32802 'odieresis': 500,
michael@0 32803 'udieresis': 556,
michael@0 32804 'notequal': 549,
michael@0 32805 'gcommaaccent': 500,
michael@0 32806 'eth': 500,
michael@0 32807 'zcaron': 389,
michael@0 32808 'ncommaaccent': 556,
michael@0 32809 'onesuperior': 300,
michael@0 32810 'imacron': 278,
michael@0 32811 'Euro': 500
michael@0 32812 },
michael@0 32813 'Times-Italic': {
michael@0 32814 'space': 250,
michael@0 32815 'exclam': 333,
michael@0 32816 'quotedbl': 420,
michael@0 32817 'numbersign': 500,
michael@0 32818 'dollar': 500,
michael@0 32819 'percent': 833,
michael@0 32820 'ampersand': 778,
michael@0 32821 'quoteright': 333,
michael@0 32822 'parenleft': 333,
michael@0 32823 'parenright': 333,
michael@0 32824 'asterisk': 500,
michael@0 32825 'plus': 675,
michael@0 32826 'comma': 250,
michael@0 32827 'hyphen': 333,
michael@0 32828 'period': 250,
michael@0 32829 'slash': 278,
michael@0 32830 'zero': 500,
michael@0 32831 'one': 500,
michael@0 32832 'two': 500,
michael@0 32833 'three': 500,
michael@0 32834 'four': 500,
michael@0 32835 'five': 500,
michael@0 32836 'six': 500,
michael@0 32837 'seven': 500,
michael@0 32838 'eight': 500,
michael@0 32839 'nine': 500,
michael@0 32840 'colon': 333,
michael@0 32841 'semicolon': 333,
michael@0 32842 'less': 675,
michael@0 32843 'equal': 675,
michael@0 32844 'greater': 675,
michael@0 32845 'question': 500,
michael@0 32846 'at': 920,
michael@0 32847 'A': 611,
michael@0 32848 'B': 611,
michael@0 32849 'C': 667,
michael@0 32850 'D': 722,
michael@0 32851 'E': 611,
michael@0 32852 'F': 611,
michael@0 32853 'G': 722,
michael@0 32854 'H': 722,
michael@0 32855 'I': 333,
michael@0 32856 'J': 444,
michael@0 32857 'K': 667,
michael@0 32858 'L': 556,
michael@0 32859 'M': 833,
michael@0 32860 'N': 667,
michael@0 32861 'O': 722,
michael@0 32862 'P': 611,
michael@0 32863 'Q': 722,
michael@0 32864 'R': 611,
michael@0 32865 'S': 500,
michael@0 32866 'T': 556,
michael@0 32867 'U': 722,
michael@0 32868 'V': 611,
michael@0 32869 'W': 833,
michael@0 32870 'X': 611,
michael@0 32871 'Y': 556,
michael@0 32872 'Z': 556,
michael@0 32873 'bracketleft': 389,
michael@0 32874 'backslash': 278,
michael@0 32875 'bracketright': 389,
michael@0 32876 'asciicircum': 422,
michael@0 32877 'underscore': 500,
michael@0 32878 'quoteleft': 333,
michael@0 32879 'a': 500,
michael@0 32880 'b': 500,
michael@0 32881 'c': 444,
michael@0 32882 'd': 500,
michael@0 32883 'e': 444,
michael@0 32884 'f': 278,
michael@0 32885 'g': 500,
michael@0 32886 'h': 500,
michael@0 32887 'i': 278,
michael@0 32888 'j': 278,
michael@0 32889 'k': 444,
michael@0 32890 'l': 278,
michael@0 32891 'm': 722,
michael@0 32892 'n': 500,
michael@0 32893 'o': 500,
michael@0 32894 'p': 500,
michael@0 32895 'q': 500,
michael@0 32896 'r': 389,
michael@0 32897 's': 389,
michael@0 32898 't': 278,
michael@0 32899 'u': 500,
michael@0 32900 'v': 444,
michael@0 32901 'w': 667,
michael@0 32902 'x': 444,
michael@0 32903 'y': 444,
michael@0 32904 'z': 389,
michael@0 32905 'braceleft': 400,
michael@0 32906 'bar': 275,
michael@0 32907 'braceright': 400,
michael@0 32908 'asciitilde': 541,
michael@0 32909 'exclamdown': 389,
michael@0 32910 'cent': 500,
michael@0 32911 'sterling': 500,
michael@0 32912 'fraction': 167,
michael@0 32913 'yen': 500,
michael@0 32914 'florin': 500,
michael@0 32915 'section': 500,
michael@0 32916 'currency': 500,
michael@0 32917 'quotesingle': 214,
michael@0 32918 'quotedblleft': 556,
michael@0 32919 'guillemotleft': 500,
michael@0 32920 'guilsinglleft': 333,
michael@0 32921 'guilsinglright': 333,
michael@0 32922 'fi': 500,
michael@0 32923 'fl': 500,
michael@0 32924 'endash': 500,
michael@0 32925 'dagger': 500,
michael@0 32926 'daggerdbl': 500,
michael@0 32927 'periodcentered': 250,
michael@0 32928 'paragraph': 523,
michael@0 32929 'bullet': 350,
michael@0 32930 'quotesinglbase': 333,
michael@0 32931 'quotedblbase': 556,
michael@0 32932 'quotedblright': 556,
michael@0 32933 'guillemotright': 500,
michael@0 32934 'ellipsis': 889,
michael@0 32935 'perthousand': 1000,
michael@0 32936 'questiondown': 500,
michael@0 32937 'grave': 333,
michael@0 32938 'acute': 333,
michael@0 32939 'circumflex': 333,
michael@0 32940 'tilde': 333,
michael@0 32941 'macron': 333,
michael@0 32942 'breve': 333,
michael@0 32943 'dotaccent': 333,
michael@0 32944 'dieresis': 333,
michael@0 32945 'ring': 333,
michael@0 32946 'cedilla': 333,
michael@0 32947 'hungarumlaut': 333,
michael@0 32948 'ogonek': 333,
michael@0 32949 'caron': 333,
michael@0 32950 'emdash': 889,
michael@0 32951 'AE': 889,
michael@0 32952 'ordfeminine': 276,
michael@0 32953 'Lslash': 556,
michael@0 32954 'Oslash': 722,
michael@0 32955 'OE': 944,
michael@0 32956 'ordmasculine': 310,
michael@0 32957 'ae': 667,
michael@0 32958 'dotlessi': 278,
michael@0 32959 'lslash': 278,
michael@0 32960 'oslash': 500,
michael@0 32961 'oe': 667,
michael@0 32962 'germandbls': 500,
michael@0 32963 'Idieresis': 333,
michael@0 32964 'eacute': 444,
michael@0 32965 'abreve': 500,
michael@0 32966 'uhungarumlaut': 500,
michael@0 32967 'ecaron': 444,
michael@0 32968 'Ydieresis': 556,
michael@0 32969 'divide': 675,
michael@0 32970 'Yacute': 556,
michael@0 32971 'Acircumflex': 611,
michael@0 32972 'aacute': 500,
michael@0 32973 'Ucircumflex': 722,
michael@0 32974 'yacute': 444,
michael@0 32975 'scommaaccent': 389,
michael@0 32976 'ecircumflex': 444,
michael@0 32977 'Uring': 722,
michael@0 32978 'Udieresis': 722,
michael@0 32979 'aogonek': 500,
michael@0 32980 'Uacute': 722,
michael@0 32981 'uogonek': 500,
michael@0 32982 'Edieresis': 611,
michael@0 32983 'Dcroat': 722,
michael@0 32984 'commaaccent': 250,
michael@0 32985 'copyright': 760,
michael@0 32986 'Emacron': 611,
michael@0 32987 'ccaron': 444,
michael@0 32988 'aring': 500,
michael@0 32989 'Ncommaaccent': 667,
michael@0 32990 'lacute': 278,
michael@0 32991 'agrave': 500,
michael@0 32992 'Tcommaaccent': 556,
michael@0 32993 'Cacute': 667,
michael@0 32994 'atilde': 500,
michael@0 32995 'Edotaccent': 611,
michael@0 32996 'scaron': 389,
michael@0 32997 'scedilla': 389,
michael@0 32998 'iacute': 278,
michael@0 32999 'lozenge': 471,
michael@0 33000 'Rcaron': 611,
michael@0 33001 'Gcommaaccent': 722,
michael@0 33002 'ucircumflex': 500,
michael@0 33003 'acircumflex': 500,
michael@0 33004 'Amacron': 611,
michael@0 33005 'rcaron': 389,
michael@0 33006 'ccedilla': 444,
michael@0 33007 'Zdotaccent': 556,
michael@0 33008 'Thorn': 611,
michael@0 33009 'Omacron': 722,
michael@0 33010 'Racute': 611,
michael@0 33011 'Sacute': 500,
michael@0 33012 'dcaron': 544,
michael@0 33013 'Umacron': 722,
michael@0 33014 'uring': 500,
michael@0 33015 'threesuperior': 300,
michael@0 33016 'Ograve': 722,
michael@0 33017 'Agrave': 611,
michael@0 33018 'Abreve': 611,
michael@0 33019 'multiply': 675,
michael@0 33020 'uacute': 500,
michael@0 33021 'Tcaron': 556,
michael@0 33022 'partialdiff': 476,
michael@0 33023 'ydieresis': 444,
michael@0 33024 'Nacute': 667,
michael@0 33025 'icircumflex': 278,
michael@0 33026 'Ecircumflex': 611,
michael@0 33027 'adieresis': 500,
michael@0 33028 'edieresis': 444,
michael@0 33029 'cacute': 444,
michael@0 33030 'nacute': 500,
michael@0 33031 'umacron': 500,
michael@0 33032 'Ncaron': 667,
michael@0 33033 'Iacute': 333,
michael@0 33034 'plusminus': 675,
michael@0 33035 'brokenbar': 275,
michael@0 33036 'registered': 760,
michael@0 33037 'Gbreve': 722,
michael@0 33038 'Idotaccent': 333,
michael@0 33039 'summation': 600,
michael@0 33040 'Egrave': 611,
michael@0 33041 'racute': 389,
michael@0 33042 'omacron': 500,
michael@0 33043 'Zacute': 556,
michael@0 33044 'Zcaron': 556,
michael@0 33045 'greaterequal': 549,
michael@0 33046 'Eth': 722,
michael@0 33047 'Ccedilla': 667,
michael@0 33048 'lcommaaccent': 278,
michael@0 33049 'tcaron': 300,
michael@0 33050 'eogonek': 444,
michael@0 33051 'Uogonek': 722,
michael@0 33052 'Aacute': 611,
michael@0 33053 'Adieresis': 611,
michael@0 33054 'egrave': 444,
michael@0 33055 'zacute': 389,
michael@0 33056 'iogonek': 278,
michael@0 33057 'Oacute': 722,
michael@0 33058 'oacute': 500,
michael@0 33059 'amacron': 500,
michael@0 33060 'sacute': 389,
michael@0 33061 'idieresis': 278,
michael@0 33062 'Ocircumflex': 722,
michael@0 33063 'Ugrave': 722,
michael@0 33064 'Delta': 612,
michael@0 33065 'thorn': 500,
michael@0 33066 'twosuperior': 300,
michael@0 33067 'Odieresis': 722,
michael@0 33068 'mu': 500,
michael@0 33069 'igrave': 278,
michael@0 33070 'ohungarumlaut': 500,
michael@0 33071 'Eogonek': 611,
michael@0 33072 'dcroat': 500,
michael@0 33073 'threequarters': 750,
michael@0 33074 'Scedilla': 500,
michael@0 33075 'lcaron': 300,
michael@0 33076 'Kcommaaccent': 667,
michael@0 33077 'Lacute': 556,
michael@0 33078 'trademark': 980,
michael@0 33079 'edotaccent': 444,
michael@0 33080 'Igrave': 333,
michael@0 33081 'Imacron': 333,
michael@0 33082 'Lcaron': 611,
michael@0 33083 'onehalf': 750,
michael@0 33084 'lessequal': 549,
michael@0 33085 'ocircumflex': 500,
michael@0 33086 'ntilde': 500,
michael@0 33087 'Uhungarumlaut': 722,
michael@0 33088 'Eacute': 611,
michael@0 33089 'emacron': 444,
michael@0 33090 'gbreve': 500,
michael@0 33091 'onequarter': 750,
michael@0 33092 'Scaron': 500,
michael@0 33093 'Scommaaccent': 500,
michael@0 33094 'Ohungarumlaut': 722,
michael@0 33095 'degree': 400,
michael@0 33096 'ograve': 500,
michael@0 33097 'Ccaron': 667,
michael@0 33098 'ugrave': 500,
michael@0 33099 'radical': 453,
michael@0 33100 'Dcaron': 722,
michael@0 33101 'rcommaaccent': 389,
michael@0 33102 'Ntilde': 667,
michael@0 33103 'otilde': 500,
michael@0 33104 'Rcommaaccent': 611,
michael@0 33105 'Lcommaaccent': 556,
michael@0 33106 'Atilde': 611,
michael@0 33107 'Aogonek': 611,
michael@0 33108 'Aring': 611,
michael@0 33109 'Otilde': 722,
michael@0 33110 'zdotaccent': 389,
michael@0 33111 'Ecaron': 611,
michael@0 33112 'Iogonek': 333,
michael@0 33113 'kcommaaccent': 444,
michael@0 33114 'minus': 675,
michael@0 33115 'Icircumflex': 333,
michael@0 33116 'ncaron': 500,
michael@0 33117 'tcommaaccent': 278,
michael@0 33118 'logicalnot': 675,
michael@0 33119 'odieresis': 500,
michael@0 33120 'udieresis': 500,
michael@0 33121 'notequal': 549,
michael@0 33122 'gcommaaccent': 500,
michael@0 33123 'eth': 500,
michael@0 33124 'zcaron': 389,
michael@0 33125 'ncommaaccent': 500,
michael@0 33126 'onesuperior': 300,
michael@0 33127 'imacron': 278,
michael@0 33128 'Euro': 500
michael@0 33129 },
michael@0 33130 'ZapfDingbats': {
michael@0 33131 'space': 278,
michael@0 33132 'a1': 974,
michael@0 33133 'a2': 961,
michael@0 33134 'a202': 974,
michael@0 33135 'a3': 980,
michael@0 33136 'a4': 719,
michael@0 33137 'a5': 789,
michael@0 33138 'a119': 790,
michael@0 33139 'a118': 791,
michael@0 33140 'a117': 690,
michael@0 33141 'a11': 960,
michael@0 33142 'a12': 939,
michael@0 33143 'a13': 549,
michael@0 33144 'a14': 855,
michael@0 33145 'a15': 911,
michael@0 33146 'a16': 933,
michael@0 33147 'a105': 911,
michael@0 33148 'a17': 945,
michael@0 33149 'a18': 974,
michael@0 33150 'a19': 755,
michael@0 33151 'a20': 846,
michael@0 33152 'a21': 762,
michael@0 33153 'a22': 761,
michael@0 33154 'a23': 571,
michael@0 33155 'a24': 677,
michael@0 33156 'a25': 763,
michael@0 33157 'a26': 760,
michael@0 33158 'a27': 759,
michael@0 33159 'a28': 754,
michael@0 33160 'a6': 494,
michael@0 33161 'a7': 552,
michael@0 33162 'a8': 537,
michael@0 33163 'a9': 577,
michael@0 33164 'a10': 692,
michael@0 33165 'a29': 786,
michael@0 33166 'a30': 788,
michael@0 33167 'a31': 788,
michael@0 33168 'a32': 790,
michael@0 33169 'a33': 793,
michael@0 33170 'a34': 794,
michael@0 33171 'a35': 816,
michael@0 33172 'a36': 823,
michael@0 33173 'a37': 789,
michael@0 33174 'a38': 841,
michael@0 33175 'a39': 823,
michael@0 33176 'a40': 833,
michael@0 33177 'a41': 816,
michael@0 33178 'a42': 831,
michael@0 33179 'a43': 923,
michael@0 33180 'a44': 744,
michael@0 33181 'a45': 723,
michael@0 33182 'a46': 749,
michael@0 33183 'a47': 790,
michael@0 33184 'a48': 792,
michael@0 33185 'a49': 695,
michael@0 33186 'a50': 776,
michael@0 33187 'a51': 768,
michael@0 33188 'a52': 792,
michael@0 33189 'a53': 759,
michael@0 33190 'a54': 707,
michael@0 33191 'a55': 708,
michael@0 33192 'a56': 682,
michael@0 33193 'a57': 701,
michael@0 33194 'a58': 826,
michael@0 33195 'a59': 815,
michael@0 33196 'a60': 789,
michael@0 33197 'a61': 789,
michael@0 33198 'a62': 707,
michael@0 33199 'a63': 687,
michael@0 33200 'a64': 696,
michael@0 33201 'a65': 689,
michael@0 33202 'a66': 786,
michael@0 33203 'a67': 787,
michael@0 33204 'a68': 713,
michael@0 33205 'a69': 791,
michael@0 33206 'a70': 785,
michael@0 33207 'a71': 791,
michael@0 33208 'a72': 873,
michael@0 33209 'a73': 761,
michael@0 33210 'a74': 762,
michael@0 33211 'a203': 762,
michael@0 33212 'a75': 759,
michael@0 33213 'a204': 759,
michael@0 33214 'a76': 892,
michael@0 33215 'a77': 892,
michael@0 33216 'a78': 788,
michael@0 33217 'a79': 784,
michael@0 33218 'a81': 438,
michael@0 33219 'a82': 138,
michael@0 33220 'a83': 277,
michael@0 33221 'a84': 415,
michael@0 33222 'a97': 392,
michael@0 33223 'a98': 392,
michael@0 33224 'a99': 668,
michael@0 33225 'a100': 668,
michael@0 33226 'a89': 390,
michael@0 33227 'a90': 390,
michael@0 33228 'a93': 317,
michael@0 33229 'a94': 317,
michael@0 33230 'a91': 276,
michael@0 33231 'a92': 276,
michael@0 33232 'a205': 509,
michael@0 33233 'a85': 509,
michael@0 33234 'a206': 410,
michael@0 33235 'a86': 410,
michael@0 33236 'a87': 234,
michael@0 33237 'a88': 234,
michael@0 33238 'a95': 334,
michael@0 33239 'a96': 334,
michael@0 33240 'a101': 732,
michael@0 33241 'a102': 544,
michael@0 33242 'a103': 544,
michael@0 33243 'a104': 910,
michael@0 33244 'a106': 667,
michael@0 33245 'a107': 760,
michael@0 33246 'a108': 760,
michael@0 33247 'a112': 776,
michael@0 33248 'a111': 595,
michael@0 33249 'a110': 694,
michael@0 33250 'a109': 626,
michael@0 33251 'a120': 788,
michael@0 33252 'a121': 788,
michael@0 33253 'a122': 788,
michael@0 33254 'a123': 788,
michael@0 33255 'a124': 788,
michael@0 33256 'a125': 788,
michael@0 33257 'a126': 788,
michael@0 33258 'a127': 788,
michael@0 33259 'a128': 788,
michael@0 33260 'a129': 788,
michael@0 33261 'a130': 788,
michael@0 33262 'a131': 788,
michael@0 33263 'a132': 788,
michael@0 33264 'a133': 788,
michael@0 33265 'a134': 788,
michael@0 33266 'a135': 788,
michael@0 33267 'a136': 788,
michael@0 33268 'a137': 788,
michael@0 33269 'a138': 788,
michael@0 33270 'a139': 788,
michael@0 33271 'a140': 788,
michael@0 33272 'a141': 788,
michael@0 33273 'a142': 788,
michael@0 33274 'a143': 788,
michael@0 33275 'a144': 788,
michael@0 33276 'a145': 788,
michael@0 33277 'a146': 788,
michael@0 33278 'a147': 788,
michael@0 33279 'a148': 788,
michael@0 33280 'a149': 788,
michael@0 33281 'a150': 788,
michael@0 33282 'a151': 788,
michael@0 33283 'a152': 788,
michael@0 33284 'a153': 788,
michael@0 33285 'a154': 788,
michael@0 33286 'a155': 788,
michael@0 33287 'a156': 788,
michael@0 33288 'a157': 788,
michael@0 33289 'a158': 788,
michael@0 33290 'a159': 788,
michael@0 33291 'a160': 894,
michael@0 33292 'a161': 838,
michael@0 33293 'a163': 1016,
michael@0 33294 'a164': 458,
michael@0 33295 'a196': 748,
michael@0 33296 'a165': 924,
michael@0 33297 'a192': 748,
michael@0 33298 'a166': 918,
michael@0 33299 'a167': 927,
michael@0 33300 'a168': 928,
michael@0 33301 'a169': 928,
michael@0 33302 'a170': 834,
michael@0 33303 'a171': 873,
michael@0 33304 'a172': 828,
michael@0 33305 'a173': 924,
michael@0 33306 'a162': 924,
michael@0 33307 'a174': 917,
michael@0 33308 'a175': 930,
michael@0 33309 'a176': 931,
michael@0 33310 'a177': 463,
michael@0 33311 'a178': 883,
michael@0 33312 'a179': 836,
michael@0 33313 'a193': 836,
michael@0 33314 'a180': 867,
michael@0 33315 'a199': 867,
michael@0 33316 'a181': 696,
michael@0 33317 'a200': 696,
michael@0 33318 'a182': 874,
michael@0 33319 'a201': 874,
michael@0 33320 'a183': 760,
michael@0 33321 'a184': 946,
michael@0 33322 'a197': 771,
michael@0 33323 'a185': 865,
michael@0 33324 'a194': 771,
michael@0 33325 'a198': 888,
michael@0 33326 'a186': 967,
michael@0 33327 'a195': 888,
michael@0 33328 'a187': 831,
michael@0 33329 'a188': 873,
michael@0 33330 'a189': 927,
michael@0 33331 'a190': 970,
michael@0 33332 'a191': 918
michael@0 33333 }
michael@0 33334 };
michael@0 33335
michael@0 33336
michael@0 33337
michael@0 33338 var EOF = {};
michael@0 33339
michael@0 33340 function isEOF(v) {
michael@0 33341 return (v == EOF);
michael@0 33342 }
michael@0 33343
michael@0 33344 var Parser = (function ParserClosure() {
michael@0 33345 function Parser(lexer, allowStreams, xref) {
michael@0 33346 this.lexer = lexer;
michael@0 33347 this.allowStreams = allowStreams;
michael@0 33348 this.xref = xref;
michael@0 33349 this.imageCache = {
michael@0 33350 length: 0,
michael@0 33351 adler32: 0,
michael@0 33352 stream: null
michael@0 33353 };
michael@0 33354 this.refill();
michael@0 33355 }
michael@0 33356
michael@0 33357 Parser.prototype = {
michael@0 33358 refill: function Parser_refill() {
michael@0 33359 this.buf1 = this.lexer.getObj();
michael@0 33360 this.buf2 = this.lexer.getObj();
michael@0 33361 },
michael@0 33362 shift: function Parser_shift() {
michael@0 33363 if (isCmd(this.buf2, 'ID')) {
michael@0 33364 this.buf1 = this.buf2;
michael@0 33365 this.buf2 = null;
michael@0 33366 } else {
michael@0 33367 this.buf1 = this.buf2;
michael@0 33368 this.buf2 = this.lexer.getObj();
michael@0 33369 }
michael@0 33370 },
michael@0 33371 getObj: function Parser_getObj(cipherTransform) {
michael@0 33372 if (isCmd(this.buf1, 'BI')) { // inline image
michael@0 33373 this.shift();
michael@0 33374 return this.makeInlineImage(cipherTransform);
michael@0 33375 }
michael@0 33376 if (isCmd(this.buf1, '[')) { // array
michael@0 33377 this.shift();
michael@0 33378 var array = [];
michael@0 33379 while (!isCmd(this.buf1, ']') && !isEOF(this.buf1)) {
michael@0 33380 array.push(this.getObj(cipherTransform));
michael@0 33381 }
michael@0 33382 if (isEOF(this.buf1)) {
michael@0 33383 error('End of file inside array');
michael@0 33384 }
michael@0 33385 this.shift();
michael@0 33386 return array;
michael@0 33387 }
michael@0 33388 if (isCmd(this.buf1, '<<')) { // dictionary or stream
michael@0 33389 this.shift();
michael@0 33390 var dict = new Dict(this.xref);
michael@0 33391 while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
michael@0 33392 if (!isName(this.buf1)) {
michael@0 33393 info('Malformed dictionary: key must be a name object');
michael@0 33394 this.shift();
michael@0 33395 continue;
michael@0 33396 }
michael@0 33397
michael@0 33398 var key = this.buf1.name;
michael@0 33399 this.shift();
michael@0 33400 if (isEOF(this.buf1)) {
michael@0 33401 break;
michael@0 33402 }
michael@0 33403 dict.set(key, this.getObj(cipherTransform));
michael@0 33404 }
michael@0 33405 if (isEOF(this.buf1)) {
michael@0 33406 error('End of file inside dictionary');
michael@0 33407 }
michael@0 33408
michael@0 33409 // Stream objects are not allowed inside content streams or
michael@0 33410 // object streams.
michael@0 33411 if (isCmd(this.buf2, 'stream')) {
michael@0 33412 return (this.allowStreams ?
michael@0 33413 this.makeStream(dict, cipherTransform) : dict);
michael@0 33414 }
michael@0 33415 this.shift();
michael@0 33416 return dict;
michael@0 33417 }
michael@0 33418 if (isInt(this.buf1)) { // indirect reference or integer
michael@0 33419 var num = this.buf1;
michael@0 33420 this.shift();
michael@0 33421 if (isInt(this.buf1) && isCmd(this.buf2, 'R')) {
michael@0 33422 var ref = new Ref(num, this.buf1);
michael@0 33423 this.shift();
michael@0 33424 this.shift();
michael@0 33425 return ref;
michael@0 33426 }
michael@0 33427 return num;
michael@0 33428 }
michael@0 33429 if (isString(this.buf1)) { // string
michael@0 33430 var str = this.buf1;
michael@0 33431 this.shift();
michael@0 33432 if (cipherTransform) {
michael@0 33433 str = cipherTransform.decryptString(str);
michael@0 33434 }
michael@0 33435 return str;
michael@0 33436 }
michael@0 33437
michael@0 33438 // simple object
michael@0 33439 var obj = this.buf1;
michael@0 33440 this.shift();
michael@0 33441 return obj;
michael@0 33442 },
michael@0 33443 makeInlineImage: function Parser_makeInlineImage(cipherTransform) {
michael@0 33444 var lexer = this.lexer;
michael@0 33445 var stream = lexer.stream;
michael@0 33446
michael@0 33447 // parse dictionary
michael@0 33448 var dict = new Dict(null);
michael@0 33449 while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
michael@0 33450 if (!isName(this.buf1)) {
michael@0 33451 error('Dictionary key must be a name object');
michael@0 33452 }
michael@0 33453
michael@0 33454 var key = this.buf1.name;
michael@0 33455 this.shift();
michael@0 33456 if (isEOF(this.buf1)) {
michael@0 33457 break;
michael@0 33458 }
michael@0 33459 dict.set(key, this.getObj(cipherTransform));
michael@0 33460 }
michael@0 33461
michael@0 33462 // parse image stream
michael@0 33463 var startPos = stream.pos;
michael@0 33464
michael@0 33465 // searching for the /EI\s/
michael@0 33466 var state = 0, ch, i, ii;
michael@0 33467 while (state != 4 && (ch = stream.getByte()) !== -1) {
michael@0 33468 switch (ch | 0) {
michael@0 33469 case 0x20:
michael@0 33470 case 0x0D:
michael@0 33471 case 0x0A:
michael@0 33472 // let's check next five bytes to be ASCII... just be sure
michael@0 33473 var followingBytes = stream.peekBytes(5);
michael@0 33474 for (i = 0, ii = followingBytes.length; i < ii; i++) {
michael@0 33475 ch = followingBytes[i];
michael@0 33476 if (ch !== 0x0A && ch !== 0x0D && (ch < 0x20 || ch > 0x7F)) {
michael@0 33477 // not a LF, CR, SPACE or any visible ASCII character
michael@0 33478 state = 0;
michael@0 33479 break; // some binary stuff found, resetting the state
michael@0 33480 }
michael@0 33481 }
michael@0 33482 state = (state === 3 ? 4 : 0);
michael@0 33483 break;
michael@0 33484 case 0x45:
michael@0 33485 state = 2;
michael@0 33486 break;
michael@0 33487 case 0x49:
michael@0 33488 state = (state === 2 ? 3 : 0);
michael@0 33489 break;
michael@0 33490 default:
michael@0 33491 state = 0;
michael@0 33492 break;
michael@0 33493 }
michael@0 33494 }
michael@0 33495
michael@0 33496 var length = (stream.pos - 4) - startPos;
michael@0 33497 var imageStream = stream.makeSubStream(startPos, length, dict);
michael@0 33498
michael@0 33499 // trying to cache repeat images, first we are trying to "warm up" caching
michael@0 33500 // using length, then comparing adler32
michael@0 33501 var MAX_LENGTH_TO_CACHE = 1000;
michael@0 33502 var cacheImage = false, adler32;
michael@0 33503 if (length < MAX_LENGTH_TO_CACHE && this.imageCache.length === length) {
michael@0 33504 var imageBytes = imageStream.getBytes();
michael@0 33505 imageStream.reset();
michael@0 33506
michael@0 33507 var a = 1;
michael@0 33508 var b = 0;
michael@0 33509 for (i = 0, ii = imageBytes.length; i < ii; ++i) {
michael@0 33510 a = (a + (imageBytes[i] & 0xff)) % 65521;
michael@0 33511 b = (b + a) % 65521;
michael@0 33512 }
michael@0 33513 adler32 = (b << 16) | a;
michael@0 33514
michael@0 33515 if (this.imageCache.stream && this.imageCache.adler32 === adler32) {
michael@0 33516 this.buf2 = Cmd.get('EI');
michael@0 33517 this.shift();
michael@0 33518
michael@0 33519 this.imageCache.stream.reset();
michael@0 33520 return this.imageCache.stream;
michael@0 33521 }
michael@0 33522 cacheImage = true;
michael@0 33523 }
michael@0 33524 if (!cacheImage && !this.imageCache.stream) {
michael@0 33525 this.imageCache.length = length;
michael@0 33526 this.imageCache.stream = null;
michael@0 33527 }
michael@0 33528
michael@0 33529 if (cipherTransform) {
michael@0 33530 imageStream = cipherTransform.createStream(imageStream, length);
michael@0 33531 }
michael@0 33532
michael@0 33533 imageStream = this.filter(imageStream, dict, length);
michael@0 33534 imageStream.dict = dict;
michael@0 33535 if (cacheImage) {
michael@0 33536 imageStream.cacheKey = 'inline_' + length + '_' + adler32;
michael@0 33537 this.imageCache.adler32 = adler32;
michael@0 33538 this.imageCache.stream = imageStream;
michael@0 33539 }
michael@0 33540
michael@0 33541 this.buf2 = Cmd.get('EI');
michael@0 33542 this.shift();
michael@0 33543
michael@0 33544 return imageStream;
michael@0 33545 },
michael@0 33546 fetchIfRef: function Parser_fetchIfRef(obj) {
michael@0 33547 // not relying on the xref.fetchIfRef -- xref might not be set
michael@0 33548 return (isRef(obj) ? this.xref.fetch(obj) : obj);
michael@0 33549 },
michael@0 33550 makeStream: function Parser_makeStream(dict, cipherTransform) {
michael@0 33551 var lexer = this.lexer;
michael@0 33552 var stream = lexer.stream;
michael@0 33553
michael@0 33554 // get stream start position
michael@0 33555 lexer.skipToNextLine();
michael@0 33556 var pos = stream.pos - 1;
michael@0 33557
michael@0 33558 // get length
michael@0 33559 var length = this.fetchIfRef(dict.get('Length'));
michael@0 33560 if (!isInt(length)) {
michael@0 33561 info('Bad ' + length + ' attribute in stream');
michael@0 33562 length = 0;
michael@0 33563 }
michael@0 33564
michael@0 33565 // skip over the stream data
michael@0 33566 stream.pos = pos + length;
michael@0 33567 lexer.nextChar();
michael@0 33568
michael@0 33569 this.shift(); // '>>'
michael@0 33570 this.shift(); // 'stream'
michael@0 33571 if (!isCmd(this.buf1, 'endstream')) {
michael@0 33572 // bad stream length, scanning for endstream
michael@0 33573 stream.pos = pos;
michael@0 33574 var SCAN_BLOCK_SIZE = 2048;
michael@0 33575 var ENDSTREAM_SIGNATURE_LENGTH = 9;
michael@0 33576 var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65,
michael@0 33577 0x61, 0x6D];
michael@0 33578 var skipped = 0, found = false, i, j;
michael@0 33579 while (stream.pos < stream.end) {
michael@0 33580 var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE);
michael@0 33581 var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH;
michael@0 33582 found = false;
michael@0 33583 for (i = 0, j = 0; i < scanLength; i++) {
michael@0 33584 var b = scanBytes[i];
michael@0 33585 if (b !== ENDSTREAM_SIGNATURE[j]) {
michael@0 33586 i -= j;
michael@0 33587 j = 0;
michael@0 33588 } else {
michael@0 33589 j++;
michael@0 33590 if (j >= ENDSTREAM_SIGNATURE_LENGTH) {
michael@0 33591 i++;
michael@0 33592 found = true;
michael@0 33593 break;
michael@0 33594 }
michael@0 33595 }
michael@0 33596 }
michael@0 33597 if (found) {
michael@0 33598 skipped += i - ENDSTREAM_SIGNATURE_LENGTH;
michael@0 33599 stream.pos += i - ENDSTREAM_SIGNATURE_LENGTH;
michael@0 33600 break;
michael@0 33601 }
michael@0 33602 skipped += scanLength;
michael@0 33603 stream.pos += scanLength;
michael@0 33604 }
michael@0 33605 if (!found) {
michael@0 33606 error('Missing endstream');
michael@0 33607 }
michael@0 33608 length = skipped;
michael@0 33609
michael@0 33610 lexer.nextChar();
michael@0 33611 this.shift();
michael@0 33612 this.shift();
michael@0 33613 }
michael@0 33614 this.shift(); // 'endstream'
michael@0 33615
michael@0 33616 stream = stream.makeSubStream(pos, length, dict);
michael@0 33617 if (cipherTransform) {
michael@0 33618 stream = cipherTransform.createStream(stream, length);
michael@0 33619 }
michael@0 33620 stream = this.filter(stream, dict, length);
michael@0 33621 stream.dict = dict;
michael@0 33622 return stream;
michael@0 33623 },
michael@0 33624 filter: function Parser_filter(stream, dict, length) {
michael@0 33625 var filter = this.fetchIfRef(dict.get('Filter', 'F'));
michael@0 33626 var params = this.fetchIfRef(dict.get('DecodeParms', 'DP'));
michael@0 33627 if (isName(filter)) {
michael@0 33628 return this.makeFilter(stream, filter.name, length, params);
michael@0 33629 }
michael@0 33630
michael@0 33631 var maybeLength = length;
michael@0 33632 if (isArray(filter)) {
michael@0 33633 var filterArray = filter;
michael@0 33634 var paramsArray = params;
michael@0 33635 for (var i = 0, ii = filterArray.length; i < ii; ++i) {
michael@0 33636 filter = filterArray[i];
michael@0 33637 if (!isName(filter)) {
michael@0 33638 error('Bad filter name: ' + filter);
michael@0 33639 }
michael@0 33640
michael@0 33641 params = null;
michael@0 33642 if (isArray(paramsArray) && (i in paramsArray)) {
michael@0 33643 params = paramsArray[i];
michael@0 33644 }
michael@0 33645 stream = this.makeFilter(stream, filter.name, maybeLength, params);
michael@0 33646 // after the first stream the length variable is invalid
michael@0 33647 maybeLength = null;
michael@0 33648 }
michael@0 33649 }
michael@0 33650 return stream;
michael@0 33651 },
michael@0 33652 makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) {
michael@0 33653 if (stream.dict.get('Length') === 0) {
michael@0 33654 return new NullStream(stream);
michael@0 33655 }
michael@0 33656 if (name == 'FlateDecode' || name == 'Fl') {
michael@0 33657 if (params) {
michael@0 33658 return new PredictorStream(new FlateStream(stream, maybeLength),
michael@0 33659 maybeLength, params);
michael@0 33660 }
michael@0 33661 return new FlateStream(stream, maybeLength);
michael@0 33662 }
michael@0 33663 if (name == 'LZWDecode' || name == 'LZW') {
michael@0 33664 var earlyChange = 1;
michael@0 33665 if (params) {
michael@0 33666 if (params.has('EarlyChange')) {
michael@0 33667 earlyChange = params.get('EarlyChange');
michael@0 33668 }
michael@0 33669 return new PredictorStream(
michael@0 33670 new LZWStream(stream, maybeLength, earlyChange),
michael@0 33671 maybeLength, params);
michael@0 33672 }
michael@0 33673 return new LZWStream(stream, maybeLength, earlyChange);
michael@0 33674 }
michael@0 33675 if (name == 'DCTDecode' || name == 'DCT') {
michael@0 33676 return new JpegStream(stream, maybeLength, stream.dict, this.xref);
michael@0 33677 }
michael@0 33678 if (name == 'JPXDecode' || name == 'JPX') {
michael@0 33679 return new JpxStream(stream, maybeLength, stream.dict);
michael@0 33680 }
michael@0 33681 if (name == 'ASCII85Decode' || name == 'A85') {
michael@0 33682 return new Ascii85Stream(stream, maybeLength);
michael@0 33683 }
michael@0 33684 if (name == 'ASCIIHexDecode' || name == 'AHx') {
michael@0 33685 return new AsciiHexStream(stream, maybeLength);
michael@0 33686 }
michael@0 33687 if (name == 'CCITTFaxDecode' || name == 'CCF') {
michael@0 33688 return new CCITTFaxStream(stream, maybeLength, params);
michael@0 33689 }
michael@0 33690 if (name == 'RunLengthDecode' || name == 'RL') {
michael@0 33691 return new RunLengthStream(stream, maybeLength);
michael@0 33692 }
michael@0 33693 if (name == 'JBIG2Decode') {
michael@0 33694 return new Jbig2Stream(stream, maybeLength, stream.dict);
michael@0 33695 }
michael@0 33696 warn('filter "' + name + '" not supported yet');
michael@0 33697 return stream;
michael@0 33698 }
michael@0 33699 };
michael@0 33700
michael@0 33701 return Parser;
michael@0 33702 })();
michael@0 33703
michael@0 33704 var Lexer = (function LexerClosure() {
michael@0 33705 function Lexer(stream, knownCommands) {
michael@0 33706 this.stream = stream;
michael@0 33707 this.nextChar();
michael@0 33708
michael@0 33709 // While lexing, we build up many strings one char at a time. Using += for
michael@0 33710 // this can result in lots of garbage strings. It's better to build an
michael@0 33711 // array of single-char strings and then join() them together at the end.
michael@0 33712 // And reusing a single array (i.e. |this.strBuf|) over and over for this
michael@0 33713 // purpose uses less memory than using a new array for each string.
michael@0 33714 this.strBuf = [];
michael@0 33715
michael@0 33716 // The PDFs might have "glued" commands with other commands, operands or
michael@0 33717 // literals, e.g. "q1". The knownCommands is a dictionary of the valid
michael@0 33718 // commands and their prefixes. The prefixes are built the following way:
michael@0 33719 // if there a command that is a prefix of the other valid command or
michael@0 33720 // literal (e.g. 'f' and 'false') the following prefixes must be included,
michael@0 33721 // 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no
michael@0 33722 // other commands or literals as a prefix. The knowCommands is optional.
michael@0 33723 this.knownCommands = knownCommands;
michael@0 33724 }
michael@0 33725
michael@0 33726 Lexer.isSpace = function Lexer_isSpace(ch) {
michael@0 33727 // Space is one of the following characters: SPACE, TAB, CR or LF.
michael@0 33728 return (ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A);
michael@0 33729 };
michael@0 33730
michael@0 33731 // A '1' in this array means the character is white space. A '1' or
michael@0 33732 // '2' means the character ends a name or command.
michael@0 33733 var specialChars = [
michael@0 33734 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
michael@0 33735 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
michael@0 33736 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
michael@0 33737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
michael@0 33738 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
michael@0 33739 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
michael@0 33740 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
michael@0 33741 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
michael@0 33742 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
michael@0 33743 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
michael@0 33744 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
michael@0 33745 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
michael@0 33746 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
michael@0 33747 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
michael@0 33748 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
michael@0 33749 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
michael@0 33750 ];
michael@0 33751
michael@0 33752 function toHexDigit(ch) {
michael@0 33753 if (ch >= 0x30 && ch <= 0x39) { // '0'-'9'
michael@0 33754 return ch & 0x0F;
michael@0 33755 }
michael@0 33756 if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) {
michael@0 33757 // 'A'-'F', 'a'-'f'
michael@0 33758 return (ch & 0x0F) + 9;
michael@0 33759 }
michael@0 33760 return -1;
michael@0 33761 }
michael@0 33762
michael@0 33763 Lexer.prototype = {
michael@0 33764 nextChar: function Lexer_nextChar() {
michael@0 33765 return (this.currentChar = this.stream.getByte());
michael@0 33766 },
michael@0 33767 peekChar: function Lexer_peekChar() {
michael@0 33768 return this.stream.peekBytes(1)[0];
michael@0 33769 },
michael@0 33770 getNumber: function Lexer_getNumber() {
michael@0 33771 var ch = this.currentChar;
michael@0 33772 var eNotation = false;
michael@0 33773 var divideBy = 0; // different from 0 if it's a floating point value
michael@0 33774 var sign = 1;
michael@0 33775
michael@0 33776 if (ch === 0x2D) { // '-'
michael@0 33777 sign = -1;
michael@0 33778 ch = this.nextChar();
michael@0 33779 } else if (ch === 0x2B) { // '+'
michael@0 33780 ch = this.nextChar();
michael@0 33781 }
michael@0 33782 if (ch === 0x2E) { // '.'
michael@0 33783 divideBy = 10;
michael@0 33784 ch = this.nextChar();
michael@0 33785 }
michael@0 33786 if (ch < 0x30 || ch > 0x39) { // '0' - '9'
michael@0 33787 error('Invalid number: ' + String.fromCharCode(ch));
michael@0 33788 return 0;
michael@0 33789 }
michael@0 33790
michael@0 33791 var baseValue = ch - 0x30; // '0'
michael@0 33792 var powerValue = 0;
michael@0 33793 var powerValueSign = 1;
michael@0 33794
michael@0 33795 while ((ch = this.nextChar()) >= 0) {
michael@0 33796 if (0x30 <= ch && ch <= 0x39) { // '0' - '9'
michael@0 33797 var currentDigit = ch - 0x30; // '0'
michael@0 33798 if (eNotation) { // We are after an 'e' or 'E'
michael@0 33799 powerValue = powerValue * 10 + currentDigit;
michael@0 33800 } else {
michael@0 33801 if (divideBy !== 0) { // We are after a point
michael@0 33802 divideBy *= 10;
michael@0 33803 }
michael@0 33804 baseValue = baseValue * 10 + currentDigit;
michael@0 33805 }
michael@0 33806 } else if (ch === 0x2E) { // '.'
michael@0 33807 if (divideBy === 0) {
michael@0 33808 divideBy = 1;
michael@0 33809 } else {
michael@0 33810 // A number can have only one '.'
michael@0 33811 break;
michael@0 33812 }
michael@0 33813 } else if (ch === 0x2D) { // '-'
michael@0 33814 // ignore minus signs in the middle of numbers to match
michael@0 33815 // Adobe's behavior
michael@0 33816 warn('Badly formated number');
michael@0 33817 } else if (ch === 0x45 || ch === 0x65) { // 'E', 'e'
michael@0 33818 // 'E' can be either a scientific notation or the beginning of a new
michael@0 33819 // operator
michael@0 33820 ch = this.peekChar();
michael@0 33821 if (ch === 0x2B || ch === 0x2D) { // '+', '-'
michael@0 33822 powerValueSign = (ch === 0x2D) ? -1 : 1;
michael@0 33823 this.nextChar(); // Consume the sign character
michael@0 33824 } else if (ch < 0x30 || ch > 0x39) { // '0' - '9'
michael@0 33825 // The 'E' must be the beginning of a new operator
michael@0 33826 break;
michael@0 33827 }
michael@0 33828 eNotation = true;
michael@0 33829 } else {
michael@0 33830 // the last character doesn't belong to us
michael@0 33831 break;
michael@0 33832 }
michael@0 33833 }
michael@0 33834
michael@0 33835 if (divideBy !== 0) {
michael@0 33836 baseValue /= divideBy;
michael@0 33837 }
michael@0 33838 if (eNotation) {
michael@0 33839 baseValue *= Math.pow(10, powerValueSign * powerValue);
michael@0 33840 }
michael@0 33841 return sign * baseValue;
michael@0 33842 },
michael@0 33843 getString: function Lexer_getString() {
michael@0 33844 var numParen = 1;
michael@0 33845 var done = false;
michael@0 33846 var strBuf = this.strBuf;
michael@0 33847 strBuf.length = 0;
michael@0 33848
michael@0 33849 var ch = this.nextChar();
michael@0 33850 while (true) {
michael@0 33851 var charBuffered = false;
michael@0 33852 switch (ch | 0) {
michael@0 33853 case -1:
michael@0 33854 warn('Unterminated string');
michael@0 33855 done = true;
michael@0 33856 break;
michael@0 33857 case 0x28: // '('
michael@0 33858 ++numParen;
michael@0 33859 strBuf.push('(');
michael@0 33860 break;
michael@0 33861 case 0x29: // ')'
michael@0 33862 if (--numParen === 0) {
michael@0 33863 this.nextChar(); // consume strings ')'
michael@0 33864 done = true;
michael@0 33865 } else {
michael@0 33866 strBuf.push(')');
michael@0 33867 }
michael@0 33868 break;
michael@0 33869 case 0x5C: // '\\'
michael@0 33870 ch = this.nextChar();
michael@0 33871 switch (ch) {
michael@0 33872 case -1:
michael@0 33873 warn('Unterminated string');
michael@0 33874 done = true;
michael@0 33875 break;
michael@0 33876 case 0x6E: // 'n'
michael@0 33877 strBuf.push('\n');
michael@0 33878 break;
michael@0 33879 case 0x72: // 'r'
michael@0 33880 strBuf.push('\r');
michael@0 33881 break;
michael@0 33882 case 0x74: // 't'
michael@0 33883 strBuf.push('\t');
michael@0 33884 break;
michael@0 33885 case 0x62: // 'b'
michael@0 33886 strBuf.push('\b');
michael@0 33887 break;
michael@0 33888 case 0x66: // 'f'
michael@0 33889 strBuf.push('\f');
michael@0 33890 break;
michael@0 33891 case 0x5C: // '\'
michael@0 33892 case 0x28: // '('
michael@0 33893 case 0x29: // ')'
michael@0 33894 strBuf.push(String.fromCharCode(ch));
michael@0 33895 break;
michael@0 33896 case 0x30: case 0x31: case 0x32: case 0x33: // '0'-'3'
michael@0 33897 case 0x34: case 0x35: case 0x36: case 0x37: // '4'-'7'
michael@0 33898 var x = ch & 0x0F;
michael@0 33899 ch = this.nextChar();
michael@0 33900 charBuffered = true;
michael@0 33901 if (ch >= 0x30 && ch <= 0x37) { // '0'-'7'
michael@0 33902 x = (x << 3) + (ch & 0x0F);
michael@0 33903 ch = this.nextChar();
michael@0 33904 if (ch >= 0x30 && ch <= 0x37) { // '0'-'7'
michael@0 33905 charBuffered = false;
michael@0 33906 x = (x << 3) + (ch & 0x0F);
michael@0 33907 }
michael@0 33908 }
michael@0 33909 strBuf.push(String.fromCharCode(x));
michael@0 33910 break;
michael@0 33911 case 0x0D: // CR
michael@0 33912 if (this.peekChar() === 0x0A) { // LF
michael@0 33913 this.nextChar();
michael@0 33914 }
michael@0 33915 break;
michael@0 33916 case 0x0A: // LF
michael@0 33917 break;
michael@0 33918 default:
michael@0 33919 strBuf.push(String.fromCharCode(ch));
michael@0 33920 break;
michael@0 33921 }
michael@0 33922 break;
michael@0 33923 default:
michael@0 33924 strBuf.push(String.fromCharCode(ch));
michael@0 33925 break;
michael@0 33926 }
michael@0 33927 if (done) {
michael@0 33928 break;
michael@0 33929 }
michael@0 33930 if (!charBuffered) {
michael@0 33931 ch = this.nextChar();
michael@0 33932 }
michael@0 33933 }
michael@0 33934 return strBuf.join('');
michael@0 33935 },
michael@0 33936 getName: function Lexer_getName() {
michael@0 33937 var ch;
michael@0 33938 var strBuf = this.strBuf;
michael@0 33939 strBuf.length = 0;
michael@0 33940 while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
michael@0 33941 if (ch === 0x23) { // '#'
michael@0 33942 ch = this.nextChar();
michael@0 33943 var x = toHexDigit(ch);
michael@0 33944 if (x != -1) {
michael@0 33945 var x2 = toHexDigit(this.nextChar());
michael@0 33946 if (x2 == -1) {
michael@0 33947 error('Illegal digit in hex char in name: ' + x2);
michael@0 33948 }
michael@0 33949 strBuf.push(String.fromCharCode((x << 4) | x2));
michael@0 33950 } else {
michael@0 33951 strBuf.push('#', String.fromCharCode(ch));
michael@0 33952 }
michael@0 33953 } else {
michael@0 33954 strBuf.push(String.fromCharCode(ch));
michael@0 33955 }
michael@0 33956 }
michael@0 33957 if (strBuf.length > 128) {
michael@0 33958 error('Warning: name token is longer than allowed by the spec: ' +
michael@0 33959 strBuf.length);
michael@0 33960 }
michael@0 33961 return Name.get(strBuf.join(''));
michael@0 33962 },
michael@0 33963 getHexString: function Lexer_getHexString() {
michael@0 33964 var strBuf = this.strBuf;
michael@0 33965 strBuf.length = 0;
michael@0 33966 var ch = this.currentChar;
michael@0 33967 var isFirstHex = true;
michael@0 33968 var firstDigit;
michael@0 33969 var secondDigit;
michael@0 33970 while (true) {
michael@0 33971 if (ch < 0) {
michael@0 33972 warn('Unterminated hex string');
michael@0 33973 break;
michael@0 33974 } else if (ch === 0x3E) { // '>'
michael@0 33975 this.nextChar();
michael@0 33976 break;
michael@0 33977 } else if (specialChars[ch] === 1) {
michael@0 33978 ch = this.nextChar();
michael@0 33979 continue;
michael@0 33980 } else {
michael@0 33981 if (isFirstHex) {
michael@0 33982 firstDigit = toHexDigit(ch);
michael@0 33983 if (firstDigit === -1) {
michael@0 33984 warn('Ignoring invalid character "' + ch + '" in hex string');
michael@0 33985 ch = this.nextChar();
michael@0 33986 continue;
michael@0 33987 }
michael@0 33988 } else {
michael@0 33989 secondDigit = toHexDigit(ch);
michael@0 33990 if (secondDigit === -1) {
michael@0 33991 warn('Ignoring invalid character "' + ch + '" in hex string');
michael@0 33992 ch = this.nextChar();
michael@0 33993 continue;
michael@0 33994 }
michael@0 33995 strBuf.push(String.fromCharCode((firstDigit << 4) | secondDigit));
michael@0 33996 }
michael@0 33997 isFirstHex = !isFirstHex;
michael@0 33998 ch = this.nextChar();
michael@0 33999 }
michael@0 34000 }
michael@0 34001 return strBuf.join('');
michael@0 34002 },
michael@0 34003 getObj: function Lexer_getObj() {
michael@0 34004 // skip whitespace and comments
michael@0 34005 var comment = false;
michael@0 34006 var ch = this.currentChar;
michael@0 34007 while (true) {
michael@0 34008 if (ch < 0) {
michael@0 34009 return EOF;
michael@0 34010 }
michael@0 34011 if (comment) {
michael@0 34012 if (ch === 0x0A || ch == 0x0D) { // LF, CR
michael@0 34013 comment = false;
michael@0 34014 }
michael@0 34015 } else if (ch === 0x25) { // '%'
michael@0 34016 comment = true;
michael@0 34017 } else if (specialChars[ch] !== 1) {
michael@0 34018 break;
michael@0 34019 }
michael@0 34020 ch = this.nextChar();
michael@0 34021 }
michael@0 34022
michael@0 34023 // start reading token
michael@0 34024 switch (ch | 0) {
michael@0 34025 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
michael@0 34026 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
michael@0 34027 case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
michael@0 34028 return this.getNumber();
michael@0 34029 case 0x28: // '('
michael@0 34030 return this.getString();
michael@0 34031 case 0x2F: // '/'
michael@0 34032 return this.getName();
michael@0 34033 // array punctuation
michael@0 34034 case 0x5B: // '['
michael@0 34035 this.nextChar();
michael@0 34036 return Cmd.get('[');
michael@0 34037 case 0x5D: // ']'
michael@0 34038 this.nextChar();
michael@0 34039 return Cmd.get(']');
michael@0 34040 // hex string or dict punctuation
michael@0 34041 case 0x3C: // '<'
michael@0 34042 ch = this.nextChar();
michael@0 34043 if (ch === 0x3C) {
michael@0 34044 // dict punctuation
michael@0 34045 this.nextChar();
michael@0 34046 return Cmd.get('<<');
michael@0 34047 }
michael@0 34048 return this.getHexString();
michael@0 34049 // dict punctuation
michael@0 34050 case 0x3E: // '>'
michael@0 34051 ch = this.nextChar();
michael@0 34052 if (ch === 0x3E) {
michael@0 34053 this.nextChar();
michael@0 34054 return Cmd.get('>>');
michael@0 34055 }
michael@0 34056 return Cmd.get('>');
michael@0 34057 case 0x7B: // '{'
michael@0 34058 this.nextChar();
michael@0 34059 return Cmd.get('{');
michael@0 34060 case 0x7D: // '}'
michael@0 34061 this.nextChar();
michael@0 34062 return Cmd.get('}');
michael@0 34063 case 0x29: // ')'
michael@0 34064 error('Illegal character: ' + ch);
michael@0 34065 break;
michael@0 34066 }
michael@0 34067
michael@0 34068 // command
michael@0 34069 var str = String.fromCharCode(ch);
michael@0 34070 var knownCommands = this.knownCommands;
michael@0 34071 var knownCommandFound = knownCommands && (str in knownCommands);
michael@0 34072 while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
michael@0 34073 // stop if known command is found and next character does not make
michael@0 34074 // the str a command
michael@0 34075 var possibleCommand = str + String.fromCharCode(ch);
michael@0 34076 if (knownCommandFound && !(possibleCommand in knownCommands)) {
michael@0 34077 break;
michael@0 34078 }
michael@0 34079 if (str.length == 128) {
michael@0 34080 error('Command token too long: ' + str.length);
michael@0 34081 }
michael@0 34082 str = possibleCommand;
michael@0 34083 knownCommandFound = knownCommands && (str in knownCommands);
michael@0 34084 }
michael@0 34085 if (str == 'true') {
michael@0 34086 return true;
michael@0 34087 }
michael@0 34088 if (str == 'false') {
michael@0 34089 return false;
michael@0 34090 }
michael@0 34091 if (str == 'null') {
michael@0 34092 return null;
michael@0 34093 }
michael@0 34094 return Cmd.get(str);
michael@0 34095 },
michael@0 34096 skipToNextLine: function Lexer_skipToNextLine() {
michael@0 34097 var ch = this.currentChar;
michael@0 34098 while (ch >= 0) {
michael@0 34099 if (ch === 0x0D) { // CR
michael@0 34100 ch = this.nextChar();
michael@0 34101 if (ch === 0x0A) { // LF
michael@0 34102 this.nextChar();
michael@0 34103 }
michael@0 34104 break;
michael@0 34105 } else if (ch === 0x0A) { // LF
michael@0 34106 this.nextChar();
michael@0 34107 break;
michael@0 34108 }
michael@0 34109 ch = this.nextChar();
michael@0 34110 }
michael@0 34111 }
michael@0 34112 };
michael@0 34113
michael@0 34114 return Lexer;
michael@0 34115 })();
michael@0 34116
michael@0 34117 var Linearization = (function LinearizationClosure() {
michael@0 34118 function Linearization(stream) {
michael@0 34119 this.parser = new Parser(new Lexer(stream), false, null);
michael@0 34120 var obj1 = this.parser.getObj();
michael@0 34121 var obj2 = this.parser.getObj();
michael@0 34122 var obj3 = this.parser.getObj();
michael@0 34123 this.linDict = this.parser.getObj();
michael@0 34124 if (isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') &&
michael@0 34125 isDict(this.linDict)) {
michael@0 34126 var obj = this.linDict.get('Linearized');
michael@0 34127 if (!(isNum(obj) && obj > 0)) {
michael@0 34128 this.linDict = null;
michael@0 34129 }
michael@0 34130 }
michael@0 34131 }
michael@0 34132
michael@0 34133 Linearization.prototype = {
michael@0 34134 getInt: function Linearization_getInt(name) {
michael@0 34135 var linDict = this.linDict;
michael@0 34136 var obj;
michael@0 34137 if (isDict(linDict) && isInt(obj = linDict.get(name)) && obj > 0) {
michael@0 34138 return obj;
michael@0 34139 }
michael@0 34140 error('"' + name + '" field in linearization table is invalid');
michael@0 34141 },
michael@0 34142 getHint: function Linearization_getHint(index) {
michael@0 34143 var linDict = this.linDict;
michael@0 34144 var obj1, obj2;
michael@0 34145 if (isDict(linDict) && isArray(obj1 = linDict.get('H')) &&
michael@0 34146 obj1.length >= 2 && isInt(obj2 = obj1[index]) && obj2 > 0) {
michael@0 34147 return obj2;
michael@0 34148 }
michael@0 34149 error('Hints table in linearization table is invalid: ' + index);
michael@0 34150 },
michael@0 34151 get length() {
michael@0 34152 if (!isDict(this.linDict)) {
michael@0 34153 return 0;
michael@0 34154 }
michael@0 34155 return this.getInt('L');
michael@0 34156 },
michael@0 34157 get hintsOffset() {
michael@0 34158 return this.getHint(0);
michael@0 34159 },
michael@0 34160 get hintsLength() {
michael@0 34161 return this.getHint(1);
michael@0 34162 },
michael@0 34163 get hintsOffset2() {
michael@0 34164 return this.getHint(2);
michael@0 34165 },
michael@0 34166 get hintsLenth2() {
michael@0 34167 return this.getHint(3);
michael@0 34168 },
michael@0 34169 get objectNumberFirst() {
michael@0 34170 return this.getInt('O');
michael@0 34171 },
michael@0 34172 get endFirst() {
michael@0 34173 return this.getInt('E');
michael@0 34174 },
michael@0 34175 get numPages() {
michael@0 34176 return this.getInt('N');
michael@0 34177 },
michael@0 34178 get mainXRefEntriesOffset() {
michael@0 34179 return this.getInt('T');
michael@0 34180 },
michael@0 34181 get pageFirst() {
michael@0 34182 return this.getInt('P');
michael@0 34183 }
michael@0 34184 };
michael@0 34185
michael@0 34186 return Linearization;
michael@0 34187 })();
michael@0 34188
michael@0 34189
michael@0 34190
michael@0 34191 var PostScriptParser = (function PostScriptParserClosure() {
michael@0 34192 function PostScriptParser(lexer) {
michael@0 34193 this.lexer = lexer;
michael@0 34194 this.operators = [];
michael@0 34195 this.token = null;
michael@0 34196 this.prev = null;
michael@0 34197 }
michael@0 34198 PostScriptParser.prototype = {
michael@0 34199 nextToken: function PostScriptParser_nextToken() {
michael@0 34200 this.prev = this.token;
michael@0 34201 this.token = this.lexer.getToken();
michael@0 34202 },
michael@0 34203 accept: function PostScriptParser_accept(type) {
michael@0 34204 if (this.token.type == type) {
michael@0 34205 this.nextToken();
michael@0 34206 return true;
michael@0 34207 }
michael@0 34208 return false;
michael@0 34209 },
michael@0 34210 expect: function PostScriptParser_expect(type) {
michael@0 34211 if (this.accept(type)) {
michael@0 34212 return true;
michael@0 34213 }
michael@0 34214 error('Unexpected symbol: found ' + this.token.type + ' expected ' +
michael@0 34215 type + '.');
michael@0 34216 },
michael@0 34217 parse: function PostScriptParser_parse() {
michael@0 34218 this.nextToken();
michael@0 34219 this.expect(PostScriptTokenTypes.LBRACE);
michael@0 34220 this.parseBlock();
michael@0 34221 this.expect(PostScriptTokenTypes.RBRACE);
michael@0 34222 return this.operators;
michael@0 34223 },
michael@0 34224 parseBlock: function PostScriptParser_parseBlock() {
michael@0 34225 while (true) {
michael@0 34226 if (this.accept(PostScriptTokenTypes.NUMBER)) {
michael@0 34227 this.operators.push(this.prev.value);
michael@0 34228 } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
michael@0 34229 this.operators.push(this.prev.value);
michael@0 34230 } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
michael@0 34231 this.parseCondition();
michael@0 34232 } else {
michael@0 34233 return;
michael@0 34234 }
michael@0 34235 }
michael@0 34236 },
michael@0 34237 parseCondition: function PostScriptParser_parseCondition() {
michael@0 34238 // Add two place holders that will be updated later
michael@0 34239 var conditionLocation = this.operators.length;
michael@0 34240 this.operators.push(null, null);
michael@0 34241
michael@0 34242 this.parseBlock();
michael@0 34243 this.expect(PostScriptTokenTypes.RBRACE);
michael@0 34244 if (this.accept(PostScriptTokenTypes.IF)) {
michael@0 34245 // The true block is right after the 'if' so it just falls through on
michael@0 34246 // true else it jumps and skips the true block.
michael@0 34247 this.operators[conditionLocation] = this.operators.length;
michael@0 34248 this.operators[conditionLocation + 1] = 'jz';
michael@0 34249 } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
michael@0 34250 var jumpLocation = this.operators.length;
michael@0 34251 this.operators.push(null, null);
michael@0 34252 var endOfTrue = this.operators.length;
michael@0 34253 this.parseBlock();
michael@0 34254 this.expect(PostScriptTokenTypes.RBRACE);
michael@0 34255 this.expect(PostScriptTokenTypes.IFELSE);
michael@0 34256 // The jump is added at the end of the true block to skip the false
michael@0 34257 // block.
michael@0 34258 this.operators[jumpLocation] = this.operators.length;
michael@0 34259 this.operators[jumpLocation + 1] = 'j';
michael@0 34260
michael@0 34261 this.operators[conditionLocation] = endOfTrue;
michael@0 34262 this.operators[conditionLocation + 1] = 'jz';
michael@0 34263 } else {
michael@0 34264 error('PS Function: error parsing conditional.');
michael@0 34265 }
michael@0 34266 }
michael@0 34267 };
michael@0 34268 return PostScriptParser;
michael@0 34269 })();
michael@0 34270
michael@0 34271 var PostScriptTokenTypes = {
michael@0 34272 LBRACE: 0,
michael@0 34273 RBRACE: 1,
michael@0 34274 NUMBER: 2,
michael@0 34275 OPERATOR: 3,
michael@0 34276 IF: 4,
michael@0 34277 IFELSE: 5
michael@0 34278 };
michael@0 34279
michael@0 34280 var PostScriptToken = (function PostScriptTokenClosure() {
michael@0 34281 function PostScriptToken(type, value) {
michael@0 34282 this.type = type;
michael@0 34283 this.value = value;
michael@0 34284 }
michael@0 34285
michael@0 34286 var opCache = {};
michael@0 34287
michael@0 34288 PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
michael@0 34289 var opValue = opCache[op];
michael@0 34290 if (opValue) {
michael@0 34291 return opValue;
michael@0 34292 }
michael@0 34293 return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
michael@0 34294 };
michael@0 34295
michael@0 34296 PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
michael@0 34297 '{');
michael@0 34298 PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
michael@0 34299 '}');
michael@0 34300 PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
michael@0 34301 PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
michael@0 34302 'IFELSE');
michael@0 34303 return PostScriptToken;
michael@0 34304 })();
michael@0 34305
michael@0 34306 var PostScriptLexer = (function PostScriptLexerClosure() {
michael@0 34307 function PostScriptLexer(stream) {
michael@0 34308 this.stream = stream;
michael@0 34309 this.nextChar();
michael@0 34310 }
michael@0 34311 PostScriptLexer.prototype = {
michael@0 34312 nextChar: function PostScriptLexer_nextChar() {
michael@0 34313 return (this.currentChar = this.stream.getByte());
michael@0 34314 },
michael@0 34315 getToken: function PostScriptLexer_getToken() {
michael@0 34316 var comment = false;
michael@0 34317 var ch = this.currentChar;
michael@0 34318
michael@0 34319 // skip comments
michael@0 34320 while (true) {
michael@0 34321 if (ch < 0) {
michael@0 34322 return EOF;
michael@0 34323 }
michael@0 34324
michael@0 34325 if (comment) {
michael@0 34326 if (ch === 0x0A || ch === 0x0D) {
michael@0 34327 comment = false;
michael@0 34328 }
michael@0 34329 } else if (ch == 0x25) { // '%'
michael@0 34330 comment = true;
michael@0 34331 } else if (!Lexer.isSpace(ch)) {
michael@0 34332 break;
michael@0 34333 }
michael@0 34334 ch = this.nextChar();
michael@0 34335 }
michael@0 34336 switch (ch | 0) {
michael@0 34337 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
michael@0 34338 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
michael@0 34339 case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
michael@0 34340 return new PostScriptToken(PostScriptTokenTypes.NUMBER,
michael@0 34341 this.getNumber());
michael@0 34342 case 0x7B: // '{'
michael@0 34343 this.nextChar();
michael@0 34344 return PostScriptToken.LBRACE;
michael@0 34345 case 0x7D: // '}'
michael@0 34346 this.nextChar();
michael@0 34347 return PostScriptToken.RBRACE;
michael@0 34348 }
michael@0 34349 // operator
michael@0 34350 var str = String.fromCharCode(ch);
michael@0 34351 while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
michael@0 34352 ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
michael@0 34353 str += String.fromCharCode(ch);
michael@0 34354 }
michael@0 34355 switch (str.toLowerCase()) {
michael@0 34356 case 'if':
michael@0 34357 return PostScriptToken.IF;
michael@0 34358 case 'ifelse':
michael@0 34359 return PostScriptToken.IFELSE;
michael@0 34360 default:
michael@0 34361 return PostScriptToken.getOperator(str);
michael@0 34362 }
michael@0 34363 },
michael@0 34364 getNumber: function PostScriptLexer_getNumber() {
michael@0 34365 var ch = this.currentChar;
michael@0 34366 var str = String.fromCharCode(ch);
michael@0 34367 while ((ch = this.nextChar()) >= 0) {
michael@0 34368 if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
michael@0 34369 ch === 0x2D || ch === 0x2E) { // '-', '.'
michael@0 34370 str += String.fromCharCode(ch);
michael@0 34371 } else {
michael@0 34372 break;
michael@0 34373 }
michael@0 34374 }
michael@0 34375 var value = parseFloat(str);
michael@0 34376 if (isNaN(value)) {
michael@0 34377 error('Invalid floating point number: ' + value);
michael@0 34378 }
michael@0 34379 return value;
michael@0 34380 }
michael@0 34381 };
michael@0 34382 return PostScriptLexer;
michael@0 34383 })();
michael@0 34384
michael@0 34385
michael@0 34386 var Stream = (function StreamClosure() {
michael@0 34387 function Stream(arrayBuffer, start, length, dict) {
michael@0 34388 this.bytes = (arrayBuffer instanceof Uint8Array ?
michael@0 34389 arrayBuffer : new Uint8Array(arrayBuffer));
michael@0 34390 this.start = start || 0;
michael@0 34391 this.pos = this.start;
michael@0 34392 this.end = (start + length) || this.bytes.length;
michael@0 34393 this.dict = dict;
michael@0 34394 }
michael@0 34395
michael@0 34396 // required methods for a stream. if a particular stream does not
michael@0 34397 // implement these, an error should be thrown
michael@0 34398 Stream.prototype = {
michael@0 34399 get length() {
michael@0 34400 return this.end - this.start;
michael@0 34401 },
michael@0 34402 getByte: function Stream_getByte() {
michael@0 34403 if (this.pos >= this.end) {
michael@0 34404 return -1;
michael@0 34405 }
michael@0 34406 return this.bytes[this.pos++];
michael@0 34407 },
michael@0 34408 getUint16: function Stream_getUint16() {
michael@0 34409 var b0 = this.getByte();
michael@0 34410 var b1 = this.getByte();
michael@0 34411 return (b0 << 8) + b1;
michael@0 34412 },
michael@0 34413 getInt32: function Stream_getInt32() {
michael@0 34414 var b0 = this.getByte();
michael@0 34415 var b1 = this.getByte();
michael@0 34416 var b2 = this.getByte();
michael@0 34417 var b3 = this.getByte();
michael@0 34418 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
michael@0 34419 },
michael@0 34420 // returns subarray of original buffer
michael@0 34421 // should only be read
michael@0 34422 getBytes: function Stream_getBytes(length) {
michael@0 34423 var bytes = this.bytes;
michael@0 34424 var pos = this.pos;
michael@0 34425 var strEnd = this.end;
michael@0 34426
michael@0 34427 if (!length) {
michael@0 34428 return bytes.subarray(pos, strEnd);
michael@0 34429 }
michael@0 34430 var end = pos + length;
michael@0 34431 if (end > strEnd) {
michael@0 34432 end = strEnd;
michael@0 34433 }
michael@0 34434 this.pos = end;
michael@0 34435 return bytes.subarray(pos, end);
michael@0 34436 },
michael@0 34437 peekBytes: function Stream_peekBytes(length) {
michael@0 34438 var bytes = this.getBytes(length);
michael@0 34439 this.pos -= bytes.length;
michael@0 34440 return bytes;
michael@0 34441 },
michael@0 34442 skip: function Stream_skip(n) {
michael@0 34443 if (!n) {
michael@0 34444 n = 1;
michael@0 34445 }
michael@0 34446 this.pos += n;
michael@0 34447 },
michael@0 34448 reset: function Stream_reset() {
michael@0 34449 this.pos = this.start;
michael@0 34450 },
michael@0 34451 moveStart: function Stream_moveStart() {
michael@0 34452 this.start = this.pos;
michael@0 34453 },
michael@0 34454 makeSubStream: function Stream_makeSubStream(start, length, dict) {
michael@0 34455 return new Stream(this.bytes.buffer, start, length, dict);
michael@0 34456 },
michael@0 34457 isStream: true
michael@0 34458 };
michael@0 34459
michael@0 34460 return Stream;
michael@0 34461 })();
michael@0 34462
michael@0 34463 var StringStream = (function StringStreamClosure() {
michael@0 34464 function StringStream(str) {
michael@0 34465 var length = str.length;
michael@0 34466 var bytes = new Uint8Array(length);
michael@0 34467 for (var n = 0; n < length; ++n) {
michael@0 34468 bytes[n] = str.charCodeAt(n);
michael@0 34469 }
michael@0 34470 Stream.call(this, bytes);
michael@0 34471 }
michael@0 34472
michael@0 34473 StringStream.prototype = Stream.prototype;
michael@0 34474
michael@0 34475 return StringStream;
michael@0 34476 })();
michael@0 34477
michael@0 34478 // super class for the decoding streams
michael@0 34479 var DecodeStream = (function DecodeStreamClosure() {
michael@0 34480 function DecodeStream(maybeMinBufferLength) {
michael@0 34481 this.pos = 0;
michael@0 34482 this.bufferLength = 0;
michael@0 34483 this.eof = false;
michael@0 34484 this.buffer = null;
michael@0 34485 this.minBufferLength = 512;
michael@0 34486 if (maybeMinBufferLength) {
michael@0 34487 // Compute the first power of two that is as big as maybeMinBufferLength.
michael@0 34488 while (this.minBufferLength < maybeMinBufferLength) {
michael@0 34489 this.minBufferLength *= 2;
michael@0 34490 }
michael@0 34491 }
michael@0 34492 }
michael@0 34493
michael@0 34494 DecodeStream.prototype = {
michael@0 34495 ensureBuffer: function DecodeStream_ensureBuffer(requested) {
michael@0 34496 var buffer = this.buffer;
michael@0 34497 var current;
michael@0 34498 if (buffer) {
michael@0 34499 current = buffer.byteLength;
michael@0 34500 if (requested <= current) {
michael@0 34501 return buffer;
michael@0 34502 }
michael@0 34503 } else {
michael@0 34504 current = 0;
michael@0 34505 }
michael@0 34506 var size = this.minBufferLength;
michael@0 34507 while (size < requested) {
michael@0 34508 size *= 2;
michael@0 34509 }
michael@0 34510 var buffer2 = new Uint8Array(size);
michael@0 34511 for (var i = 0; i < current; ++i) {
michael@0 34512 buffer2[i] = buffer[i];
michael@0 34513 }
michael@0 34514 return (this.buffer = buffer2);
michael@0 34515 },
michael@0 34516 getByte: function DecodeStream_getByte() {
michael@0 34517 var pos = this.pos;
michael@0 34518 while (this.bufferLength <= pos) {
michael@0 34519 if (this.eof) {
michael@0 34520 return -1;
michael@0 34521 }
michael@0 34522 this.readBlock();
michael@0 34523 }
michael@0 34524 return this.buffer[this.pos++];
michael@0 34525 },
michael@0 34526 getUint16: function DecodeStream_getUint16() {
michael@0 34527 var b0 = this.getByte();
michael@0 34528 var b1 = this.getByte();
michael@0 34529 return (b0 << 8) + b1;
michael@0 34530 },
michael@0 34531 getInt32: function DecodeStream_getInt32() {
michael@0 34532 var b0 = this.getByte();
michael@0 34533 var b1 = this.getByte();
michael@0 34534 var b2 = this.getByte();
michael@0 34535 var b3 = this.getByte();
michael@0 34536 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
michael@0 34537 },
michael@0 34538 getBytes: function DecodeStream_getBytes(length) {
michael@0 34539 var end, pos = this.pos;
michael@0 34540
michael@0 34541 if (length) {
michael@0 34542 this.ensureBuffer(pos + length);
michael@0 34543 end = pos + length;
michael@0 34544
michael@0 34545 while (!this.eof && this.bufferLength < end) {
michael@0 34546 this.readBlock();
michael@0 34547 }
michael@0 34548 var bufEnd = this.bufferLength;
michael@0 34549 if (end > bufEnd) {
michael@0 34550 end = bufEnd;
michael@0 34551 }
michael@0 34552 } else {
michael@0 34553 while (!this.eof) {
michael@0 34554 this.readBlock();
michael@0 34555 }
michael@0 34556 end = this.bufferLength;
michael@0 34557
michael@0 34558 // checking if bufferLength is still 0 then
michael@0 34559 // the buffer has to be initialized
michael@0 34560 if (!end) {
michael@0 34561 this.buffer = new Uint8Array(0);
michael@0 34562 }
michael@0 34563 }
michael@0 34564
michael@0 34565 this.pos = end;
michael@0 34566 return this.buffer.subarray(pos, end);
michael@0 34567 },
michael@0 34568 peekBytes: function DecodeStream_peekBytes(length) {
michael@0 34569 var bytes = this.getBytes(length);
michael@0 34570 this.pos -= bytes.length;
michael@0 34571 return bytes;
michael@0 34572 },
michael@0 34573 makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
michael@0 34574 var end = start + length;
michael@0 34575 while (this.bufferLength <= end && !this.eof) {
michael@0 34576 this.readBlock();
michael@0 34577 }
michael@0 34578 return new Stream(this.buffer, start, length, dict);
michael@0 34579 },
michael@0 34580 skip: function Stream_skip(n) {
michael@0 34581 if (!n) {
michael@0 34582 n = 1;
michael@0 34583 }
michael@0 34584 this.pos += n;
michael@0 34585 },
michael@0 34586 reset: function DecodeStream_reset() {
michael@0 34587 this.pos = 0;
michael@0 34588 },
michael@0 34589 getBaseStreams: function DecodeStream_getBaseStreams() {
michael@0 34590 if (this.str && this.str.getBaseStreams) {
michael@0 34591 return this.str.getBaseStreams();
michael@0 34592 }
michael@0 34593 return [];
michael@0 34594 }
michael@0 34595 };
michael@0 34596
michael@0 34597 return DecodeStream;
michael@0 34598 })();
michael@0 34599
michael@0 34600 var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
michael@0 34601 function StreamsSequenceStream(streams) {
michael@0 34602 this.streams = streams;
michael@0 34603 DecodeStream.call(this, /* maybeLength = */ null);
michael@0 34604 }
michael@0 34605
michael@0 34606 StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
michael@0 34607
michael@0 34608 StreamsSequenceStream.prototype.readBlock =
michael@0 34609 function streamSequenceStreamReadBlock() {
michael@0 34610
michael@0 34611 var streams = this.streams;
michael@0 34612 if (streams.length === 0) {
michael@0 34613 this.eof = true;
michael@0 34614 return;
michael@0 34615 }
michael@0 34616 var stream = streams.shift();
michael@0 34617 var chunk = stream.getBytes();
michael@0 34618 var bufferLength = this.bufferLength;
michael@0 34619 var newLength = bufferLength + chunk.length;
michael@0 34620 var buffer = this.ensureBuffer(newLength);
michael@0 34621 buffer.set(chunk, bufferLength);
michael@0 34622 this.bufferLength = newLength;
michael@0 34623 };
michael@0 34624
michael@0 34625 StreamsSequenceStream.prototype.getBaseStreams =
michael@0 34626 function StreamsSequenceStream_getBaseStreams() {
michael@0 34627
michael@0 34628 var baseStreams = [];
michael@0 34629 for (var i = 0, ii = this.streams.length; i < ii; i++) {
michael@0 34630 var stream = this.streams[i];
michael@0 34631 if (stream.getBaseStreams) {
michael@0 34632 Util.concatenateToArray(baseStreams, stream.getBaseStreams());
michael@0 34633 }
michael@0 34634 }
michael@0 34635 return baseStreams;
michael@0 34636 };
michael@0 34637
michael@0 34638 return StreamsSequenceStream;
michael@0 34639 })();
michael@0 34640
michael@0 34641 var FlateStream = (function FlateStreamClosure() {
michael@0 34642 var codeLenCodeMap = new Uint32Array([
michael@0 34643 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
michael@0 34644 ]);
michael@0 34645
michael@0 34646 var lengthDecode = new Uint32Array([
michael@0 34647 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a,
michael@0 34648 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f,
michael@0 34649 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073,
michael@0 34650 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102
michael@0 34651 ]);
michael@0 34652
michael@0 34653 var distDecode = new Uint32Array([
michael@0 34654 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d,
michael@0 34655 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1,
michael@0 34656 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01,
michael@0 34657 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001
michael@0 34658 ]);
michael@0 34659
michael@0 34660 var fixedLitCodeTab = [new Uint32Array([
michael@0 34661 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0,
michael@0 34662 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0,
michael@0 34663 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0,
michael@0 34664 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0,
michael@0 34665 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8,
michael@0 34666 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8,
michael@0 34667 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8,
michael@0 34668 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8,
michael@0 34669 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4,
michael@0 34670 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4,
michael@0 34671 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4,
michael@0 34672 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4,
michael@0 34673 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc,
michael@0 34674 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec,
michael@0 34675 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc,
michael@0 34676 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc,
michael@0 34677 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2,
michael@0 34678 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2,
michael@0 34679 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2,
michael@0 34680 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2,
michael@0 34681 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca,
michael@0 34682 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea,
michael@0 34683 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da,
michael@0 34684 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa,
michael@0 34685 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6,
michael@0 34686 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6,
michael@0 34687 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6,
michael@0 34688 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6,
michael@0 34689 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce,
michael@0 34690 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee,
michael@0 34691 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de,
michael@0 34692 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe,
michael@0 34693 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1,
michael@0 34694 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1,
michael@0 34695 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1,
michael@0 34696 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1,
michael@0 34697 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9,
michael@0 34698 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9,
michael@0 34699 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9,
michael@0 34700 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9,
michael@0 34701 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5,
michael@0 34702 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5,
michael@0 34703 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5,
michael@0 34704 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5,
michael@0 34705 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd,
michael@0 34706 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed,
michael@0 34707 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd,
michael@0 34708 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd,
michael@0 34709 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3,
michael@0 34710 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3,
michael@0 34711 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3,
michael@0 34712 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3,
michael@0 34713 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb,
michael@0 34714 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb,
michael@0 34715 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db,
michael@0 34716 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb,
michael@0 34717 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7,
michael@0 34718 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7,
michael@0 34719 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7,
michael@0 34720 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7,
michael@0 34721 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf,
michael@0 34722 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef,
michael@0 34723 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df,
michael@0 34724 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff
michael@0 34725 ]), 9];
michael@0 34726
michael@0 34727 var fixedDistCodeTab = [new Uint32Array([
michael@0 34728 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c,
michael@0 34729 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000,
michael@0 34730 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d,
michael@0 34731 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
michael@0 34732 ]), 5];
michael@0 34733
michael@0 34734 function FlateStream(str, maybeLength) {
michael@0 34735 this.str = str;
michael@0 34736 this.dict = str.dict;
michael@0 34737
michael@0 34738 var cmf = str.getByte();
michael@0 34739 var flg = str.getByte();
michael@0 34740 if (cmf == -1 || flg == -1) {
michael@0 34741 error('Invalid header in flate stream: ' + cmf + ', ' + flg);
michael@0 34742 }
michael@0 34743 if ((cmf & 0x0f) != 0x08) {
michael@0 34744 error('Unknown compression method in flate stream: ' + cmf + ', ' + flg);
michael@0 34745 }
michael@0 34746 if ((((cmf << 8) + flg) % 31) !== 0) {
michael@0 34747 error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg);
michael@0 34748 }
michael@0 34749 if (flg & 0x20) {
michael@0 34750 error('FDICT bit set in flate stream: ' + cmf + ', ' + flg);
michael@0 34751 }
michael@0 34752
michael@0 34753 this.codeSize = 0;
michael@0 34754 this.codeBuf = 0;
michael@0 34755
michael@0 34756 DecodeStream.call(this, maybeLength);
michael@0 34757 }
michael@0 34758
michael@0 34759 FlateStream.prototype = Object.create(DecodeStream.prototype);
michael@0 34760
michael@0 34761 FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
michael@0 34762 var str = this.str;
michael@0 34763 var codeSize = this.codeSize;
michael@0 34764 var codeBuf = this.codeBuf;
michael@0 34765
michael@0 34766 var b;
michael@0 34767 while (codeSize < bits) {
michael@0 34768 if ((b = str.getByte()) === -1) {
michael@0 34769 error('Bad encoding in flate stream');
michael@0 34770 }
michael@0 34771 codeBuf |= b << codeSize;
michael@0 34772 codeSize += 8;
michael@0 34773 }
michael@0 34774 b = codeBuf & ((1 << bits) - 1);
michael@0 34775 this.codeBuf = codeBuf >> bits;
michael@0 34776 this.codeSize = codeSize -= bits;
michael@0 34777
michael@0 34778 return b;
michael@0 34779 };
michael@0 34780
michael@0 34781 FlateStream.prototype.getCode = function FlateStream_getCode(table) {
michael@0 34782 var str = this.str;
michael@0 34783 var codes = table[0];
michael@0 34784 var maxLen = table[1];
michael@0 34785 var codeSize = this.codeSize;
michael@0 34786 var codeBuf = this.codeBuf;
michael@0 34787
michael@0 34788 while (codeSize < maxLen) {
michael@0 34789 var b;
michael@0 34790 if ((b = str.getByte()) === -1) {
michael@0 34791 error('Bad encoding in flate stream');
michael@0 34792 }
michael@0 34793 codeBuf |= (b << codeSize);
michael@0 34794 codeSize += 8;
michael@0 34795 }
michael@0 34796 var code = codes[codeBuf & ((1 << maxLen) - 1)];
michael@0 34797 var codeLen = code >> 16;
michael@0 34798 var codeVal = code & 0xffff;
michael@0 34799 if (codeSize === 0 || codeSize < codeLen || codeLen === 0) {
michael@0 34800 error('Bad encoding in flate stream');
michael@0 34801 }
michael@0 34802 this.codeBuf = (codeBuf >> codeLen);
michael@0 34803 this.codeSize = (codeSize - codeLen);
michael@0 34804 return codeVal;
michael@0 34805 };
michael@0 34806
michael@0 34807 FlateStream.prototype.generateHuffmanTable =
michael@0 34808 function flateStreamGenerateHuffmanTable(lengths) {
michael@0 34809 var n = lengths.length;
michael@0 34810
michael@0 34811 // find max code length
michael@0 34812 var maxLen = 0;
michael@0 34813 var i;
michael@0 34814 for (i = 0; i < n; ++i) {
michael@0 34815 if (lengths[i] > maxLen) {
michael@0 34816 maxLen = lengths[i];
michael@0 34817 }
michael@0 34818 }
michael@0 34819
michael@0 34820 // build the table
michael@0 34821 var size = 1 << maxLen;
michael@0 34822 var codes = new Uint32Array(size);
michael@0 34823 for (var len = 1, code = 0, skip = 2;
michael@0 34824 len <= maxLen;
michael@0 34825 ++len, code <<= 1, skip <<= 1) {
michael@0 34826 for (var val = 0; val < n; ++val) {
michael@0 34827 if (lengths[val] == len) {
michael@0 34828 // bit-reverse the code
michael@0 34829 var code2 = 0;
michael@0 34830 var t = code;
michael@0 34831 for (i = 0; i < len; ++i) {
michael@0 34832 code2 = (code2 << 1) | (t & 1);
michael@0 34833 t >>= 1;
michael@0 34834 }
michael@0 34835
michael@0 34836 // fill the table entries
michael@0 34837 for (i = code2; i < size; i += skip) {
michael@0 34838 codes[i] = (len << 16) | val;
michael@0 34839 }
michael@0 34840 ++code;
michael@0 34841 }
michael@0 34842 }
michael@0 34843 }
michael@0 34844
michael@0 34845 return [codes, maxLen];
michael@0 34846 };
michael@0 34847
michael@0 34848 FlateStream.prototype.readBlock = function FlateStream_readBlock() {
michael@0 34849 var buffer, len;
michael@0 34850 var str = this.str;
michael@0 34851 // read block header
michael@0 34852 var hdr = this.getBits(3);
michael@0 34853 if (hdr & 1) {
michael@0 34854 this.eof = true;
michael@0 34855 }
michael@0 34856 hdr >>= 1;
michael@0 34857
michael@0 34858 if (hdr === 0) { // uncompressed block
michael@0 34859 var b;
michael@0 34860
michael@0 34861 if ((b = str.getByte()) === -1) {
michael@0 34862 error('Bad block header in flate stream');
michael@0 34863 }
michael@0 34864 var blockLen = b;
michael@0 34865 if ((b = str.getByte()) === -1) {
michael@0 34866 error('Bad block header in flate stream');
michael@0 34867 }
michael@0 34868 blockLen |= (b << 8);
michael@0 34869 if ((b = str.getByte()) === -1) {
michael@0 34870 error('Bad block header in flate stream');
michael@0 34871 }
michael@0 34872 var check = b;
michael@0 34873 if ((b = str.getByte()) === -1) {
michael@0 34874 error('Bad block header in flate stream');
michael@0 34875 }
michael@0 34876 check |= (b << 8);
michael@0 34877 if (check != (~blockLen & 0xffff) &&
michael@0 34878 (blockLen !== 0 || check !== 0)) {
michael@0 34879 // Ignoring error for bad "empty" block (see issue 1277)
michael@0 34880 error('Bad uncompressed block length in flate stream');
michael@0 34881 }
michael@0 34882
michael@0 34883 this.codeBuf = 0;
michael@0 34884 this.codeSize = 0;
michael@0 34885
michael@0 34886 var bufferLength = this.bufferLength;
michael@0 34887 buffer = this.ensureBuffer(bufferLength + blockLen);
michael@0 34888 var end = bufferLength + blockLen;
michael@0 34889 this.bufferLength = end;
michael@0 34890 if (blockLen === 0) {
michael@0 34891 if (str.peekBytes(1).length === 0) {
michael@0 34892 this.eof = true;
michael@0 34893 }
michael@0 34894 } else {
michael@0 34895 for (var n = bufferLength; n < end; ++n) {
michael@0 34896 if ((b = str.getByte()) === -1) {
michael@0 34897 this.eof = true;
michael@0 34898 break;
michael@0 34899 }
michael@0 34900 buffer[n] = b;
michael@0 34901 }
michael@0 34902 }
michael@0 34903 return;
michael@0 34904 }
michael@0 34905
michael@0 34906 var litCodeTable;
michael@0 34907 var distCodeTable;
michael@0 34908 if (hdr == 1) { // compressed block, fixed codes
michael@0 34909 litCodeTable = fixedLitCodeTab;
michael@0 34910 distCodeTable = fixedDistCodeTab;
michael@0 34911 } else if (hdr == 2) { // compressed block, dynamic codes
michael@0 34912 var numLitCodes = this.getBits(5) + 257;
michael@0 34913 var numDistCodes = this.getBits(5) + 1;
michael@0 34914 var numCodeLenCodes = this.getBits(4) + 4;
michael@0 34915
michael@0 34916 // build the code lengths code table
michael@0 34917 var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);
michael@0 34918
michael@0 34919 var i;
michael@0 34920 for (i = 0; i < numCodeLenCodes; ++i) {
michael@0 34921 codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3);
michael@0 34922 }
michael@0 34923 var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
michael@0 34924
michael@0 34925 // build the literal and distance code tables
michael@0 34926 len = 0;
michael@0 34927 i = 0;
michael@0 34928 var codes = numLitCodes + numDistCodes;
michael@0 34929 var codeLengths = new Uint8Array(codes);
michael@0 34930 var bitsLength, bitsOffset, what;
michael@0 34931 while (i < codes) {
michael@0 34932 var code = this.getCode(codeLenCodeTab);
michael@0 34933 if (code == 16) {
michael@0 34934 bitsLength = 2; bitsOffset = 3; what = len;
michael@0 34935 } else if (code == 17) {
michael@0 34936 bitsLength = 3; bitsOffset = 3; what = (len = 0);
michael@0 34937 } else if (code == 18) {
michael@0 34938 bitsLength = 7; bitsOffset = 11; what = (len = 0);
michael@0 34939 } else {
michael@0 34940 codeLengths[i++] = len = code;
michael@0 34941 continue;
michael@0 34942 }
michael@0 34943
michael@0 34944 var repeatLength = this.getBits(bitsLength) + bitsOffset;
michael@0 34945 while (repeatLength-- > 0) {
michael@0 34946 codeLengths[i++] = what;
michael@0 34947 }
michael@0 34948 }
michael@0 34949
michael@0 34950 litCodeTable =
michael@0 34951 this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));
michael@0 34952 distCodeTable =
michael@0 34953 this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));
michael@0 34954 } else {
michael@0 34955 error('Unknown block type in flate stream');
michael@0 34956 }
michael@0 34957
michael@0 34958 buffer = this.buffer;
michael@0 34959 var limit = buffer ? buffer.length : 0;
michael@0 34960 var pos = this.bufferLength;
michael@0 34961 while (true) {
michael@0 34962 var code1 = this.getCode(litCodeTable);
michael@0 34963 if (code1 < 256) {
michael@0 34964 if (pos + 1 >= limit) {
michael@0 34965 buffer = this.ensureBuffer(pos + 1);
michael@0 34966 limit = buffer.length;
michael@0 34967 }
michael@0 34968 buffer[pos++] = code1;
michael@0 34969 continue;
michael@0 34970 }
michael@0 34971 if (code1 == 256) {
michael@0 34972 this.bufferLength = pos;
michael@0 34973 return;
michael@0 34974 }
michael@0 34975 code1 -= 257;
michael@0 34976 code1 = lengthDecode[code1];
michael@0 34977 var code2 = code1 >> 16;
michael@0 34978 if (code2 > 0) {
michael@0 34979 code2 = this.getBits(code2);
michael@0 34980 }
michael@0 34981 len = (code1 & 0xffff) + code2;
michael@0 34982 code1 = this.getCode(distCodeTable);
michael@0 34983 code1 = distDecode[code1];
michael@0 34984 code2 = code1 >> 16;
michael@0 34985 if (code2 > 0) {
michael@0 34986 code2 = this.getBits(code2);
michael@0 34987 }
michael@0 34988 var dist = (code1 & 0xffff) + code2;
michael@0 34989 if (pos + len >= limit) {
michael@0 34990 buffer = this.ensureBuffer(pos + len);
michael@0 34991 limit = buffer.length;
michael@0 34992 }
michael@0 34993 for (var k = 0; k < len; ++k, ++pos) {
michael@0 34994 buffer[pos] = buffer[pos - dist];
michael@0 34995 }
michael@0 34996 }
michael@0 34997 };
michael@0 34998
michael@0 34999 return FlateStream;
michael@0 35000 })();
michael@0 35001
michael@0 35002 var PredictorStream = (function PredictorStreamClosure() {
michael@0 35003 function PredictorStream(str, maybeLength, params) {
michael@0 35004 var predictor = this.predictor = params.get('Predictor') || 1;
michael@0 35005
michael@0 35006 if (predictor <= 1) {
michael@0 35007 return str; // no prediction
michael@0 35008 }
michael@0 35009 if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
michael@0 35010 error('Unsupported predictor: ' + predictor);
michael@0 35011 }
michael@0 35012
michael@0 35013 if (predictor === 2) {
michael@0 35014 this.readBlock = this.readBlockTiff;
michael@0 35015 } else {
michael@0 35016 this.readBlock = this.readBlockPng;
michael@0 35017 }
michael@0 35018
michael@0 35019 this.str = str;
michael@0 35020 this.dict = str.dict;
michael@0 35021
michael@0 35022 var colors = this.colors = params.get('Colors') || 1;
michael@0 35023 var bits = this.bits = params.get('BitsPerComponent') || 8;
michael@0 35024 var columns = this.columns = params.get('Columns') || 1;
michael@0 35025
michael@0 35026 this.pixBytes = (colors * bits + 7) >> 3;
michael@0 35027 this.rowBytes = (columns * colors * bits + 7) >> 3;
michael@0 35028
michael@0 35029 DecodeStream.call(this, maybeLength);
michael@0 35030 return this;
michael@0 35031 }
michael@0 35032
michael@0 35033 PredictorStream.prototype = Object.create(DecodeStream.prototype);
michael@0 35034
michael@0 35035 PredictorStream.prototype.readBlockTiff =
michael@0 35036 function predictorStreamReadBlockTiff() {
michael@0 35037 var rowBytes = this.rowBytes;
michael@0 35038
michael@0 35039 var bufferLength = this.bufferLength;
michael@0 35040 var buffer = this.ensureBuffer(bufferLength + rowBytes);
michael@0 35041
michael@0 35042 var bits = this.bits;
michael@0 35043 var colors = this.colors;
michael@0 35044
michael@0 35045 var rawBytes = this.str.getBytes(rowBytes);
michael@0 35046 this.eof = !rawBytes.length;
michael@0 35047 if (this.eof) {
michael@0 35048 return;
michael@0 35049 }
michael@0 35050
michael@0 35051 var inbuf = 0, outbuf = 0;
michael@0 35052 var inbits = 0, outbits = 0;
michael@0 35053 var pos = bufferLength;
michael@0 35054 var i;
michael@0 35055
michael@0 35056 if (bits === 1) {
michael@0 35057 for (i = 0; i < rowBytes; ++i) {
michael@0 35058 var c = rawBytes[i];
michael@0 35059 inbuf = (inbuf << 8) | c;
michael@0 35060 // bitwise addition is exclusive or
michael@0 35061 // first shift inbuf and then add
michael@0 35062 buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF;
michael@0 35063 // truncate inbuf (assumes colors < 16)
michael@0 35064 inbuf &= 0xFFFF;
michael@0 35065 }
michael@0 35066 } else if (bits === 8) {
michael@0 35067 for (i = 0; i < colors; ++i) {
michael@0 35068 buffer[pos++] = rawBytes[i];
michael@0 35069 }
michael@0 35070 for (; i < rowBytes; ++i) {
michael@0 35071 buffer[pos] = buffer[pos - colors] + rawBytes[i];
michael@0 35072 pos++;
michael@0 35073 }
michael@0 35074 } else {
michael@0 35075 var compArray = new Uint8Array(colors + 1);
michael@0 35076 var bitMask = (1 << bits) - 1;
michael@0 35077 var j = 0, k = bufferLength;
michael@0 35078 var columns = this.columns;
michael@0 35079 for (i = 0; i < columns; ++i) {
michael@0 35080 for (var kk = 0; kk < colors; ++kk) {
michael@0 35081 if (inbits < bits) {
michael@0 35082 inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF);
michael@0 35083 inbits += 8;
michael@0 35084 }
michael@0 35085 compArray[kk] = (compArray[kk] +
michael@0 35086 (inbuf >> (inbits - bits))) & bitMask;
michael@0 35087 inbits -= bits;
michael@0 35088 outbuf = (outbuf << bits) | compArray[kk];
michael@0 35089 outbits += bits;
michael@0 35090 if (outbits >= 8) {
michael@0 35091 buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF;
michael@0 35092 outbits -= 8;
michael@0 35093 }
michael@0 35094 }
michael@0 35095 }
michael@0 35096 if (outbits > 0) {
michael@0 35097 buffer[k++] = (outbuf << (8 - outbits)) +
michael@0 35098 (inbuf & ((1 << (8 - outbits)) - 1));
michael@0 35099 }
michael@0 35100 }
michael@0 35101 this.bufferLength += rowBytes;
michael@0 35102 };
michael@0 35103
michael@0 35104 PredictorStream.prototype.readBlockPng =
michael@0 35105 function predictorStreamReadBlockPng() {
michael@0 35106
michael@0 35107 var rowBytes = this.rowBytes;
michael@0 35108 var pixBytes = this.pixBytes;
michael@0 35109
michael@0 35110 var predictor = this.str.getByte();
michael@0 35111 var rawBytes = this.str.getBytes(rowBytes);
michael@0 35112 this.eof = !rawBytes.length;
michael@0 35113 if (this.eof) {
michael@0 35114 return;
michael@0 35115 }
michael@0 35116
michael@0 35117 var bufferLength = this.bufferLength;
michael@0 35118 var buffer = this.ensureBuffer(bufferLength + rowBytes);
michael@0 35119
michael@0 35120 var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
michael@0 35121 if (prevRow.length === 0) {
michael@0 35122 prevRow = new Uint8Array(rowBytes);
michael@0 35123 }
michael@0 35124
michael@0 35125 var i, j = bufferLength, up, c;
michael@0 35126 switch (predictor) {
michael@0 35127 case 0:
michael@0 35128 for (i = 0; i < rowBytes; ++i) {
michael@0 35129 buffer[j++] = rawBytes[i];
michael@0 35130 }
michael@0 35131 break;
michael@0 35132 case 1:
michael@0 35133 for (i = 0; i < pixBytes; ++i) {
michael@0 35134 buffer[j++] = rawBytes[i];
michael@0 35135 }
michael@0 35136 for (; i < rowBytes; ++i) {
michael@0 35137 buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF;
michael@0 35138 j++;
michael@0 35139 }
michael@0 35140 break;
michael@0 35141 case 2:
michael@0 35142 for (i = 0; i < rowBytes; ++i) {
michael@0 35143 buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
michael@0 35144 }
michael@0 35145 break;
michael@0 35146 case 3:
michael@0 35147 for (i = 0; i < pixBytes; ++i) {
michael@0 35148 buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
michael@0 35149 }
michael@0 35150 for (; i < rowBytes; ++i) {
michael@0 35151 buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) +
michael@0 35152 rawBytes[i]) & 0xFF;
michael@0 35153 j++;
michael@0 35154 }
michael@0 35155 break;
michael@0 35156 case 4:
michael@0 35157 // we need to save the up left pixels values. the simplest way
michael@0 35158 // is to create a new buffer
michael@0 35159 for (i = 0; i < pixBytes; ++i) {
michael@0 35160 up = prevRow[i];
michael@0 35161 c = rawBytes[i];
michael@0 35162 buffer[j++] = up + c;
michael@0 35163 }
michael@0 35164 for (; i < rowBytes; ++i) {
michael@0 35165 up = prevRow[i];
michael@0 35166 var upLeft = prevRow[i - pixBytes];
michael@0 35167 var left = buffer[j - pixBytes];
michael@0 35168 var p = left + up - upLeft;
michael@0 35169
michael@0 35170 var pa = p - left;
michael@0 35171 if (pa < 0) {
michael@0 35172 pa = -pa;
michael@0 35173 }
michael@0 35174 var pb = p - up;
michael@0 35175 if (pb < 0) {
michael@0 35176 pb = -pb;
michael@0 35177 }
michael@0 35178 var pc = p - upLeft;
michael@0 35179 if (pc < 0) {
michael@0 35180 pc = -pc;
michael@0 35181 }
michael@0 35182
michael@0 35183 c = rawBytes[i];
michael@0 35184 if (pa <= pb && pa <= pc) {
michael@0 35185 buffer[j++] = left + c;
michael@0 35186 } else if (pb <= pc) {
michael@0 35187 buffer[j++] = up + c;
michael@0 35188 } else {
michael@0 35189 buffer[j++] = upLeft + c;
michael@0 35190 }
michael@0 35191 }
michael@0 35192 break;
michael@0 35193 default:
michael@0 35194 error('Unsupported predictor: ' + predictor);
michael@0 35195 }
michael@0 35196 this.bufferLength += rowBytes;
michael@0 35197 };
michael@0 35198
michael@0 35199 return PredictorStream;
michael@0 35200 })();
michael@0 35201
michael@0 35202 /**
michael@0 35203 * Depending on the type of JPEG a JpegStream is handled in different ways. For
michael@0 35204 * JPEG's that are supported natively such as DeviceGray and DeviceRGB the image
michael@0 35205 * data is stored and then loaded by the browser. For unsupported JPEG's we use
michael@0 35206 * a library to decode these images and the stream behaves like all the other
michael@0 35207 * DecodeStreams.
michael@0 35208 */
michael@0 35209 var JpegStream = (function JpegStreamClosure() {
michael@0 35210 function JpegStream(stream, maybeLength, dict, xref) {
michael@0 35211 // TODO: per poppler, some images may have 'junk' before that
michael@0 35212 // need to be removed
michael@0 35213 this.stream = stream;
michael@0 35214 this.maybeLength = maybeLength;
michael@0 35215 this.dict = dict;
michael@0 35216
michael@0 35217 DecodeStream.call(this, maybeLength);
michael@0 35218 }
michael@0 35219
michael@0 35220 JpegStream.prototype = Object.create(DecodeStream.prototype);
michael@0 35221
michael@0 35222 Object.defineProperty(JpegStream.prototype, 'bytes', {
michael@0 35223 get: function JpegStream_bytes() {
michael@0 35224 // If this.maybeLength is null, we'll get the entire stream.
michael@0 35225 return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
michael@0 35226 },
michael@0 35227 configurable: true
michael@0 35228 });
michael@0 35229
michael@0 35230 JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) {
michael@0 35231 if (this.bufferLength) {
michael@0 35232 return;
michael@0 35233 }
michael@0 35234 try {
michael@0 35235 var jpegImage = new JpegImage();
michael@0 35236 if (this.colorTransform != -1) {
michael@0 35237 jpegImage.colorTransform = this.colorTransform;
michael@0 35238 }
michael@0 35239 jpegImage.parse(this.bytes);
michael@0 35240 var width = jpegImage.width;
michael@0 35241 var height = jpegImage.height;
michael@0 35242 var data = jpegImage.getData(width, height);
michael@0 35243 this.buffer = data;
michael@0 35244 this.bufferLength = data.length;
michael@0 35245 this.eof = true;
michael@0 35246 } catch (e) {
michael@0 35247 error('JPEG error: ' + e);
michael@0 35248 }
michael@0 35249 };
michael@0 35250 JpegStream.prototype.getIR = function JpegStream_getIR() {
michael@0 35251 return PDFJS.createObjectURL(this.bytes, 'image/jpeg');
michael@0 35252 };
michael@0 35253 /**
michael@0 35254 * Checks if the image can be decoded and displayed by the browser without any
michael@0 35255 * further processing such as color space conversions.
michael@0 35256 */
michael@0 35257 JpegStream.prototype.isNativelySupported =
michael@0 35258 function JpegStream_isNativelySupported(xref, res) {
michael@0 35259 var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res);
michael@0 35260 return cs.name === 'DeviceGray' || cs.name === 'DeviceRGB';
michael@0 35261 };
michael@0 35262 /**
michael@0 35263 * Checks if the image can be decoded by the browser.
michael@0 35264 */
michael@0 35265 JpegStream.prototype.isNativelyDecodable =
michael@0 35266 function JpegStream_isNativelyDecodable(xref, res) {
michael@0 35267 var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res);
michael@0 35268 var numComps = cs.numComps;
michael@0 35269 return numComps == 1 || numComps == 3;
michael@0 35270 };
michael@0 35271
michael@0 35272 return JpegStream;
michael@0 35273 })();
michael@0 35274
michael@0 35275 /**
michael@0 35276 * For JPEG 2000's we use a library to decode these images and
michael@0 35277 * the stream behaves like all the other DecodeStreams.
michael@0 35278 */
michael@0 35279 var JpxStream = (function JpxStreamClosure() {
michael@0 35280 function JpxStream(stream, maybeLength, dict) {
michael@0 35281 this.stream = stream;
michael@0 35282 this.maybeLength = maybeLength;
michael@0 35283 this.dict = dict;
michael@0 35284
michael@0 35285 DecodeStream.call(this, maybeLength);
michael@0 35286 }
michael@0 35287
michael@0 35288 JpxStream.prototype = Object.create(DecodeStream.prototype);
michael@0 35289
michael@0 35290 Object.defineProperty(JpxStream.prototype, 'bytes', {
michael@0 35291 get: function JpxStream_bytes() {
michael@0 35292 // If this.maybeLength is null, we'll get the entire stream.
michael@0 35293 return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
michael@0 35294 },
michael@0 35295 configurable: true
michael@0 35296 });
michael@0 35297
michael@0 35298 JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) {
michael@0 35299 if (this.bufferLength) {
michael@0 35300 return;
michael@0 35301 }
michael@0 35302
michael@0 35303 var jpxImage = new JpxImage();
michael@0 35304 jpxImage.parse(this.bytes);
michael@0 35305
michael@0 35306 var width = jpxImage.width;
michael@0 35307 var height = jpxImage.height;
michael@0 35308 var componentsCount = jpxImage.componentsCount;
michael@0 35309 var tileCount = jpxImage.tiles.length;
michael@0 35310 if (tileCount === 1) {
michael@0 35311 this.buffer = jpxImage.tiles[0].items;
michael@0 35312 } else {
michael@0 35313 var data = new Uint8Array(width * height * componentsCount);
michael@0 35314
michael@0 35315 for (var k = 0; k < tileCount; k++) {
michael@0 35316 var tileComponents = jpxImage.tiles[k];
michael@0 35317 var tileWidth = tileComponents.width;
michael@0 35318 var tileHeight = tileComponents.height;
michael@0 35319 var tileLeft = tileComponents.left;
michael@0 35320 var tileTop = tileComponents.top;
michael@0 35321
michael@0 35322 var src = tileComponents.items;
michael@0 35323 var srcPosition = 0;
michael@0 35324 var dataPosition = (width * tileTop + tileLeft) * componentsCount;
michael@0 35325 var imgRowSize = width * componentsCount;
michael@0 35326 var tileRowSize = tileWidth * componentsCount;
michael@0 35327
michael@0 35328 for (var j = 0; j < tileHeight; j++) {
michael@0 35329 var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize);
michael@0 35330 data.set(rowBytes, dataPosition);
michael@0 35331 srcPosition += tileRowSize;
michael@0 35332 dataPosition += imgRowSize;
michael@0 35333 }
michael@0 35334 }
michael@0 35335 this.buffer = data;
michael@0 35336 }
michael@0 35337 this.bufferLength = this.buffer.length;
michael@0 35338 this.eof = true;
michael@0 35339 };
michael@0 35340
michael@0 35341 return JpxStream;
michael@0 35342 })();
michael@0 35343
michael@0 35344 /**
michael@0 35345 * For JBIG2's we use a library to decode these images and
michael@0 35346 * the stream behaves like all the other DecodeStreams.
michael@0 35347 */
michael@0 35348 var Jbig2Stream = (function Jbig2StreamClosure() {
michael@0 35349 function Jbig2Stream(stream, maybeLength, dict) {
michael@0 35350 this.stream = stream;
michael@0 35351 this.maybeLength = maybeLength;
michael@0 35352 this.dict = dict;
michael@0 35353
michael@0 35354 DecodeStream.call(this, maybeLength);
michael@0 35355 }
michael@0 35356
michael@0 35357 Jbig2Stream.prototype = Object.create(DecodeStream.prototype);
michael@0 35358
michael@0 35359 Object.defineProperty(Jbig2Stream.prototype, 'bytes', {
michael@0 35360 get: function Jbig2Stream_bytes() {
michael@0 35361 // If this.maybeLength is null, we'll get the entire stream.
michael@0 35362 return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
michael@0 35363 },
michael@0 35364 configurable: true
michael@0 35365 });
michael@0 35366
michael@0 35367 Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) {
michael@0 35368 if (this.bufferLength) {
michael@0 35369 return;
michael@0 35370 }
michael@0 35371
michael@0 35372 var jbig2Image = new Jbig2Image();
michael@0 35373
michael@0 35374 var chunks = [], decodeParams = this.dict.get('DecodeParms');
michael@0 35375
michael@0 35376 // According to the PDF specification, DecodeParms can be either
michael@0 35377 // a dictionary, or an array whose elements are dictionaries.
michael@0 35378 if (isArray(decodeParams)) {
michael@0 35379 if (decodeParams.length > 1) {
michael@0 35380 warn('JBIG2 - \'DecodeParms\' array with multiple elements ' +
michael@0 35381 'not supported.');
michael@0 35382 }
michael@0 35383 decodeParams = decodeParams[0];
michael@0 35384 }
michael@0 35385 if (decodeParams && decodeParams.has('JBIG2Globals')) {
michael@0 35386 var globalsStream = decodeParams.get('JBIG2Globals');
michael@0 35387 var globals = globalsStream.getBytes();
michael@0 35388 chunks.push({data: globals, start: 0, end: globals.length});
michael@0 35389 }
michael@0 35390 chunks.push({data: this.bytes, start: 0, end: this.bytes.length});
michael@0 35391 var data = jbig2Image.parseChunks(chunks);
michael@0 35392 var dataLength = data.length;
michael@0 35393
michael@0 35394 // JBIG2 had black as 1 and white as 0, inverting the colors
michael@0 35395 for (var i = 0; i < dataLength; i++) {
michael@0 35396 data[i] ^= 0xFF;
michael@0 35397 }
michael@0 35398
michael@0 35399 this.buffer = data;
michael@0 35400 this.bufferLength = dataLength;
michael@0 35401 this.eof = true;
michael@0 35402 };
michael@0 35403
michael@0 35404 return Jbig2Stream;
michael@0 35405 })();
michael@0 35406
michael@0 35407 var DecryptStream = (function DecryptStreamClosure() {
michael@0 35408 function DecryptStream(str, maybeLength, decrypt) {
michael@0 35409 this.str = str;
michael@0 35410 this.dict = str.dict;
michael@0 35411 this.decrypt = decrypt;
michael@0 35412 this.nextChunk = null;
michael@0 35413 this.initialized = false;
michael@0 35414
michael@0 35415 DecodeStream.call(this, maybeLength);
michael@0 35416 }
michael@0 35417
michael@0 35418 var chunkSize = 512;
michael@0 35419
michael@0 35420 DecryptStream.prototype = Object.create(DecodeStream.prototype);
michael@0 35421
michael@0 35422 DecryptStream.prototype.readBlock = function DecryptStream_readBlock() {
michael@0 35423 var chunk;
michael@0 35424 if (this.initialized) {
michael@0 35425 chunk = this.nextChunk;
michael@0 35426 } else {
michael@0 35427 chunk = this.str.getBytes(chunkSize);
michael@0 35428 this.initialized = true;
michael@0 35429 }
michael@0 35430 if (!chunk || chunk.length === 0) {
michael@0 35431 this.eof = true;
michael@0 35432 return;
michael@0 35433 }
michael@0 35434 this.nextChunk = this.str.getBytes(chunkSize);
michael@0 35435 var hasMoreData = this.nextChunk && this.nextChunk.length > 0;
michael@0 35436
michael@0 35437 var decrypt = this.decrypt;
michael@0 35438 chunk = decrypt(chunk, !hasMoreData);
michael@0 35439
michael@0 35440 var bufferLength = this.bufferLength;
michael@0 35441 var i, n = chunk.length;
michael@0 35442 var buffer = this.ensureBuffer(bufferLength + n);
michael@0 35443 for (i = 0; i < n; i++) {
michael@0 35444 buffer[bufferLength++] = chunk[i];
michael@0 35445 }
michael@0 35446 this.bufferLength = bufferLength;
michael@0 35447 };
michael@0 35448
michael@0 35449 return DecryptStream;
michael@0 35450 })();
michael@0 35451
michael@0 35452 var Ascii85Stream = (function Ascii85StreamClosure() {
michael@0 35453 function Ascii85Stream(str, maybeLength) {
michael@0 35454 this.str = str;
michael@0 35455 this.dict = str.dict;
michael@0 35456 this.input = new Uint8Array(5);
michael@0 35457
michael@0 35458 // Most streams increase in size when decoded, but Ascii85 streams
michael@0 35459 // typically shrink by ~20%.
michael@0 35460 if (maybeLength) {
michael@0 35461 maybeLength = 0.8 * maybeLength;
michael@0 35462 }
michael@0 35463 DecodeStream.call(this, maybeLength);
michael@0 35464 }
michael@0 35465
michael@0 35466 Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
michael@0 35467
michael@0 35468 Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
michael@0 35469 var TILDA_CHAR = 0x7E; // '~'
michael@0 35470 var Z_LOWER_CHAR = 0x7A; // 'z'
michael@0 35471 var EOF = -1;
michael@0 35472
michael@0 35473 var str = this.str;
michael@0 35474
michael@0 35475 var c = str.getByte();
michael@0 35476 while (Lexer.isSpace(c)) {
michael@0 35477 c = str.getByte();
michael@0 35478 }
michael@0 35479
michael@0 35480 if (c === EOF || c === TILDA_CHAR) {
michael@0 35481 this.eof = true;
michael@0 35482 return;
michael@0 35483 }
michael@0 35484
michael@0 35485 var bufferLength = this.bufferLength, buffer;
michael@0 35486 var i;
michael@0 35487
michael@0 35488 // special code for z
michael@0 35489 if (c == Z_LOWER_CHAR) {
michael@0 35490 buffer = this.ensureBuffer(bufferLength + 4);
michael@0 35491 for (i = 0; i < 4; ++i) {
michael@0 35492 buffer[bufferLength + i] = 0;
michael@0 35493 }
michael@0 35494 this.bufferLength += 4;
michael@0 35495 } else {
michael@0 35496 var input = this.input;
michael@0 35497 input[0] = c;
michael@0 35498 for (i = 1; i < 5; ++i) {
michael@0 35499 c = str.getByte();
michael@0 35500 while (Lexer.isSpace(c)) {
michael@0 35501 c = str.getByte();
michael@0 35502 }
michael@0 35503
michael@0 35504 input[i] = c;
michael@0 35505
michael@0 35506 if (c === EOF || c == TILDA_CHAR) {
michael@0 35507 break;
michael@0 35508 }
michael@0 35509 }
michael@0 35510 buffer = this.ensureBuffer(bufferLength + i - 1);
michael@0 35511 this.bufferLength += i - 1;
michael@0 35512
michael@0 35513 // partial ending;
michael@0 35514 if (i < 5) {
michael@0 35515 for (; i < 5; ++i) {
michael@0 35516 input[i] = 0x21 + 84;
michael@0 35517 }
michael@0 35518 this.eof = true;
michael@0 35519 }
michael@0 35520 var t = 0;
michael@0 35521 for (i = 0; i < 5; ++i) {
michael@0 35522 t = t * 85 + (input[i] - 0x21);
michael@0 35523 }
michael@0 35524
michael@0 35525 for (i = 3; i >= 0; --i) {
michael@0 35526 buffer[bufferLength + i] = t & 0xFF;
michael@0 35527 t >>= 8;
michael@0 35528 }
michael@0 35529 }
michael@0 35530 };
michael@0 35531
michael@0 35532 return Ascii85Stream;
michael@0 35533 })();
michael@0 35534
michael@0 35535 var AsciiHexStream = (function AsciiHexStreamClosure() {
michael@0 35536 function AsciiHexStream(str, maybeLength) {
michael@0 35537 this.str = str;
michael@0 35538 this.dict = str.dict;
michael@0 35539
michael@0 35540 this.firstDigit = -1;
michael@0 35541
michael@0 35542 // Most streams increase in size when decoded, but AsciiHex streams shrink
michael@0 35543 // by 50%.
michael@0 35544 if (maybeLength) {
michael@0 35545 maybeLength = 0.5 * maybeLength;
michael@0 35546 }
michael@0 35547 DecodeStream.call(this, maybeLength);
michael@0 35548 }
michael@0 35549
michael@0 35550 AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
michael@0 35551
michael@0 35552 AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() {
michael@0 35553 var UPSTREAM_BLOCK_SIZE = 8000;
michael@0 35554 var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE);
michael@0 35555 if (!bytes.length) {
michael@0 35556 this.eof = true;
michael@0 35557 return;
michael@0 35558 }
michael@0 35559
michael@0 35560 var maxDecodeLength = (bytes.length + 1) >> 1;
michael@0 35561 var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength);
michael@0 35562 var bufferLength = this.bufferLength;
michael@0 35563
michael@0 35564 var firstDigit = this.firstDigit;
michael@0 35565 for (var i = 0, ii = bytes.length; i < ii; i++) {
michael@0 35566 var ch = bytes[i], digit;
michael@0 35567 if (ch >= 0x30 && ch <= 0x39) { // '0'-'9'
michael@0 35568 digit = ch & 0x0F;
michael@0 35569 } else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) {
michael@0 35570 // 'A'-'Z', 'a'-'z'
michael@0 35571 digit = (ch & 0x0F) + 9;
michael@0 35572 } else if (ch === 0x3E) { // '>'
michael@0 35573 this.eof = true;
michael@0 35574 break;
michael@0 35575 } else { // probably whitespace
michael@0 35576 continue; // ignoring
michael@0 35577 }
michael@0 35578 if (firstDigit < 0) {
michael@0 35579 firstDigit = digit;
michael@0 35580 } else {
michael@0 35581 buffer[bufferLength++] = (firstDigit << 4) | digit;
michael@0 35582 firstDigit = -1;
michael@0 35583 }
michael@0 35584 }
michael@0 35585 if (firstDigit >= 0 && this.eof) {
michael@0 35586 // incomplete byte
michael@0 35587 buffer[bufferLength++] = (firstDigit << 4);
michael@0 35588 firstDigit = -1;
michael@0 35589 }
michael@0 35590 this.firstDigit = firstDigit;
michael@0 35591 this.bufferLength = bufferLength;
michael@0 35592 };
michael@0 35593
michael@0 35594 return AsciiHexStream;
michael@0 35595 })();
michael@0 35596
michael@0 35597 var RunLengthStream = (function RunLengthStreamClosure() {
michael@0 35598 function RunLengthStream(str, maybeLength) {
michael@0 35599 this.str = str;
michael@0 35600 this.dict = str.dict;
michael@0 35601
michael@0 35602 DecodeStream.call(this, maybeLength);
michael@0 35603 }
michael@0 35604
michael@0 35605 RunLengthStream.prototype = Object.create(DecodeStream.prototype);
michael@0 35606
michael@0 35607 RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() {
michael@0 35608 // The repeatHeader has following format. The first byte defines type of run
michael@0 35609 // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes
michael@0 35610 // (in addition to the second byte from the header), n = 129 through 255 -
michael@0 35611 // duplicate the second byte from the header (257 - n) times, n = 128 - end.
michael@0 35612 var repeatHeader = this.str.getBytes(2);
michael@0 35613 if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] == 128) {
michael@0 35614 this.eof = true;
michael@0 35615 return;
michael@0 35616 }
michael@0 35617
michael@0 35618 var buffer;
michael@0 35619 var bufferLength = this.bufferLength;
michael@0 35620 var n = repeatHeader[0];
michael@0 35621 if (n < 128) {
michael@0 35622 // copy n bytes
michael@0 35623 buffer = this.ensureBuffer(bufferLength + n + 1);
michael@0 35624 buffer[bufferLength++] = repeatHeader[1];
michael@0 35625 if (n > 0) {
michael@0 35626 var source = this.str.getBytes(n);
michael@0 35627 buffer.set(source, bufferLength);
michael@0 35628 bufferLength += n;
michael@0 35629 }
michael@0 35630 } else {
michael@0 35631 n = 257 - n;
michael@0 35632 var b = repeatHeader[1];
michael@0 35633 buffer = this.ensureBuffer(bufferLength + n + 1);
michael@0 35634 for (var i = 0; i < n; i++) {
michael@0 35635 buffer[bufferLength++] = b;
michael@0 35636 }
michael@0 35637 }
michael@0 35638 this.bufferLength = bufferLength;
michael@0 35639 };
michael@0 35640
michael@0 35641 return RunLengthStream;
michael@0 35642 })();
michael@0 35643
michael@0 35644 var CCITTFaxStream = (function CCITTFaxStreamClosure() {
michael@0 35645
michael@0 35646 var ccittEOL = -2;
michael@0 35647 var twoDimPass = 0;
michael@0 35648 var twoDimHoriz = 1;
michael@0 35649 var twoDimVert0 = 2;
michael@0 35650 var twoDimVertR1 = 3;
michael@0 35651 var twoDimVertL1 = 4;
michael@0 35652 var twoDimVertR2 = 5;
michael@0 35653 var twoDimVertL2 = 6;
michael@0 35654 var twoDimVertR3 = 7;
michael@0 35655 var twoDimVertL3 = 8;
michael@0 35656
michael@0 35657 var twoDimTable = [
michael@0 35658 [-1, -1], [-1, -1], // 000000x
michael@0 35659 [7, twoDimVertL3], // 0000010
michael@0 35660 [7, twoDimVertR3], // 0000011
michael@0 35661 [6, twoDimVertL2], [6, twoDimVertL2], // 000010x
michael@0 35662 [6, twoDimVertR2], [6, twoDimVertR2], // 000011x
michael@0 35663 [4, twoDimPass], [4, twoDimPass], // 0001xxx
michael@0 35664 [4, twoDimPass], [4, twoDimPass],
michael@0 35665 [4, twoDimPass], [4, twoDimPass],
michael@0 35666 [4, twoDimPass], [4, twoDimPass],
michael@0 35667 [3, twoDimHoriz], [3, twoDimHoriz], // 001xxxx
michael@0 35668 [3, twoDimHoriz], [3, twoDimHoriz],
michael@0 35669 [3, twoDimHoriz], [3, twoDimHoriz],
michael@0 35670 [3, twoDimHoriz], [3, twoDimHoriz],
michael@0 35671 [3, twoDimHoriz], [3, twoDimHoriz],
michael@0 35672 [3, twoDimHoriz], [3, twoDimHoriz],
michael@0 35673 [3, twoDimHoriz], [3, twoDimHoriz],
michael@0 35674 [3, twoDimHoriz], [3, twoDimHoriz],
michael@0 35675 [3, twoDimVertL1], [3, twoDimVertL1], // 010xxxx
michael@0 35676 [3, twoDimVertL1], [3, twoDimVertL1],
michael@0 35677 [3, twoDimVertL1], [3, twoDimVertL1],
michael@0 35678 [3, twoDimVertL1], [3, twoDimVertL1],
michael@0 35679 [3, twoDimVertL1], [3, twoDimVertL1],
michael@0 35680 [3, twoDimVertL1], [3, twoDimVertL1],
michael@0 35681 [3, twoDimVertL1], [3, twoDimVertL1],
michael@0 35682 [3, twoDimVertL1], [3, twoDimVertL1],
michael@0 35683 [3, twoDimVertR1], [3, twoDimVertR1], // 011xxxx
michael@0 35684 [3, twoDimVertR1], [3, twoDimVertR1],
michael@0 35685 [3, twoDimVertR1], [3, twoDimVertR1],
michael@0 35686 [3, twoDimVertR1], [3, twoDimVertR1],
michael@0 35687 [3, twoDimVertR1], [3, twoDimVertR1],
michael@0 35688 [3, twoDimVertR1], [3, twoDimVertR1],
michael@0 35689 [3, twoDimVertR1], [3, twoDimVertR1],
michael@0 35690 [3, twoDimVertR1], [3, twoDimVertR1],
michael@0 35691 [1, twoDimVert0], [1, twoDimVert0], // 1xxxxxx
michael@0 35692 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35693 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35694 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35695 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35696 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35697 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35698 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35699 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35700 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35701 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35702 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35703 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35704 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35705 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35706 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35707 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35708 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35709 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35710 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35711 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35712 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35713 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35714 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35715 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35716 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35717 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35718 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35719 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35720 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35721 [1, twoDimVert0], [1, twoDimVert0],
michael@0 35722 [1, twoDimVert0], [1, twoDimVert0]
michael@0 35723 ];
michael@0 35724
michael@0 35725 var whiteTable1 = [
michael@0 35726 [-1, -1], // 00000
michael@0 35727 [12, ccittEOL], // 00001
michael@0 35728 [-1, -1], [-1, -1], // 0001x
michael@0 35729 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 001xx
michael@0 35730 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 010xx
michael@0 35731 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 011xx
michael@0 35732 [11, 1792], [11, 1792], // 1000x
michael@0 35733 [12, 1984], // 10010
michael@0 35734 [12, 2048], // 10011
michael@0 35735 [12, 2112], // 10100
michael@0 35736 [12, 2176], // 10101
michael@0 35737 [12, 2240], // 10110
michael@0 35738 [12, 2304], // 10111
michael@0 35739 [11, 1856], [11, 1856], // 1100x
michael@0 35740 [11, 1920], [11, 1920], // 1101x
michael@0 35741 [12, 2368], // 11100
michael@0 35742 [12, 2432], // 11101
michael@0 35743 [12, 2496], // 11110
michael@0 35744 [12, 2560] // 11111
michael@0 35745 ];
michael@0 35746
michael@0 35747 var whiteTable2 = [
michael@0 35748 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000000xx
michael@0 35749 [8, 29], [8, 29], // 00000010x
michael@0 35750 [8, 30], [8, 30], // 00000011x
michael@0 35751 [8, 45], [8, 45], // 00000100x
michael@0 35752 [8, 46], [8, 46], // 00000101x
michael@0 35753 [7, 22], [7, 22], [7, 22], [7, 22], // 0000011xx
michael@0 35754 [7, 23], [7, 23], [7, 23], [7, 23], // 0000100xx
michael@0 35755 [8, 47], [8, 47], // 00001010x
michael@0 35756 [8, 48], [8, 48], // 00001011x
michael@0 35757 [6, 13], [6, 13], [6, 13], [6, 13], // 000011xxx
michael@0 35758 [6, 13], [6, 13], [6, 13], [6, 13],
michael@0 35759 [7, 20], [7, 20], [7, 20], [7, 20], // 0001000xx
michael@0 35760 [8, 33], [8, 33], // 00010010x
michael@0 35761 [8, 34], [8, 34], // 00010011x
michael@0 35762 [8, 35], [8, 35], // 00010100x
michael@0 35763 [8, 36], [8, 36], // 00010101x
michael@0 35764 [8, 37], [8, 37], // 00010110x
michael@0 35765 [8, 38], [8, 38], // 00010111x
michael@0 35766 [7, 19], [7, 19], [7, 19], [7, 19], // 0001100xx
michael@0 35767 [8, 31], [8, 31], // 00011010x
michael@0 35768 [8, 32], [8, 32], // 00011011x
michael@0 35769 [6, 1], [6, 1], [6, 1], [6, 1], // 000111xxx
michael@0 35770 [6, 1], [6, 1], [6, 1], [6, 1],
michael@0 35771 [6, 12], [6, 12], [6, 12], [6, 12], // 001000xxx
michael@0 35772 [6, 12], [6, 12], [6, 12], [6, 12],
michael@0 35773 [8, 53], [8, 53], // 00100100x
michael@0 35774 [8, 54], [8, 54], // 00100101x
michael@0 35775 [7, 26], [7, 26], [7, 26], [7, 26], // 0010011xx
michael@0 35776 [8, 39], [8, 39], // 00101000x
michael@0 35777 [8, 40], [8, 40], // 00101001x
michael@0 35778 [8, 41], [8, 41], // 00101010x
michael@0 35779 [8, 42], [8, 42], // 00101011x
michael@0 35780 [8, 43], [8, 43], // 00101100x
michael@0 35781 [8, 44], [8, 44], // 00101101x
michael@0 35782 [7, 21], [7, 21], [7, 21], [7, 21], // 0010111xx
michael@0 35783 [7, 28], [7, 28], [7, 28], [7, 28], // 0011000xx
michael@0 35784 [8, 61], [8, 61], // 00110010x
michael@0 35785 [8, 62], [8, 62], // 00110011x
michael@0 35786 [8, 63], [8, 63], // 00110100x
michael@0 35787 [8, 0], [8, 0], // 00110101x
michael@0 35788 [8, 320], [8, 320], // 00110110x
michael@0 35789 [8, 384], [8, 384], // 00110111x
michael@0 35790 [5, 10], [5, 10], [5, 10], [5, 10], // 00111xxxx
michael@0 35791 [5, 10], [5, 10], [5, 10], [5, 10],
michael@0 35792 [5, 10], [5, 10], [5, 10], [5, 10],
michael@0 35793 [5, 10], [5, 10], [5, 10], [5, 10],
michael@0 35794 [5, 11], [5, 11], [5, 11], [5, 11], // 01000xxxx
michael@0 35795 [5, 11], [5, 11], [5, 11], [5, 11],
michael@0 35796 [5, 11], [5, 11], [5, 11], [5, 11],
michael@0 35797 [5, 11], [5, 11], [5, 11], [5, 11],
michael@0 35798 [7, 27], [7, 27], [7, 27], [7, 27], // 0100100xx
michael@0 35799 [8, 59], [8, 59], // 01001010x
michael@0 35800 [8, 60], [8, 60], // 01001011x
michael@0 35801 [9, 1472], // 010011000
michael@0 35802 [9, 1536], // 010011001
michael@0 35803 [9, 1600], // 010011010
michael@0 35804 [9, 1728], // 010011011
michael@0 35805 [7, 18], [7, 18], [7, 18], [7, 18], // 0100111xx
michael@0 35806 [7, 24], [7, 24], [7, 24], [7, 24], // 0101000xx
michael@0 35807 [8, 49], [8, 49], // 01010010x
michael@0 35808 [8, 50], [8, 50], // 01010011x
michael@0 35809 [8, 51], [8, 51], // 01010100x
michael@0 35810 [8, 52], [8, 52], // 01010101x
michael@0 35811 [7, 25], [7, 25], [7, 25], [7, 25], // 0101011xx
michael@0 35812 [8, 55], [8, 55], // 01011000x
michael@0 35813 [8, 56], [8, 56], // 01011001x
michael@0 35814 [8, 57], [8, 57], // 01011010x
michael@0 35815 [8, 58], [8, 58], // 01011011x
michael@0 35816 [6, 192], [6, 192], [6, 192], [6, 192], // 010111xxx
michael@0 35817 [6, 192], [6, 192], [6, 192], [6, 192],
michael@0 35818 [6, 1664], [6, 1664], [6, 1664], [6, 1664], // 011000xxx
michael@0 35819 [6, 1664], [6, 1664], [6, 1664], [6, 1664],
michael@0 35820 [8, 448], [8, 448], // 01100100x
michael@0 35821 [8, 512], [8, 512], // 01100101x
michael@0 35822 [9, 704], // 011001100
michael@0 35823 [9, 768], // 011001101
michael@0 35824 [8, 640], [8, 640], // 01100111x
michael@0 35825 [8, 576], [8, 576], // 01101000x
michael@0 35826 [9, 832], // 011010010
michael@0 35827 [9, 896], // 011010011
michael@0 35828 [9, 960], // 011010100
michael@0 35829 [9, 1024], // 011010101
michael@0 35830 [9, 1088], // 011010110
michael@0 35831 [9, 1152], // 011010111
michael@0 35832 [9, 1216], // 011011000
michael@0 35833 [9, 1280], // 011011001
michael@0 35834 [9, 1344], // 011011010
michael@0 35835 [9, 1408], // 011011011
michael@0 35836 [7, 256], [7, 256], [7, 256], [7, 256], // 0110111xx
michael@0 35837 [4, 2], [4, 2], [4, 2], [4, 2], // 0111xxxxx
michael@0 35838 [4, 2], [4, 2], [4, 2], [4, 2],
michael@0 35839 [4, 2], [4, 2], [4, 2], [4, 2],
michael@0 35840 [4, 2], [4, 2], [4, 2], [4, 2],
michael@0 35841 [4, 2], [4, 2], [4, 2], [4, 2],
michael@0 35842 [4, 2], [4, 2], [4, 2], [4, 2],
michael@0 35843 [4, 2], [4, 2], [4, 2], [4, 2],
michael@0 35844 [4, 2], [4, 2], [4, 2], [4, 2],
michael@0 35845 [4, 3], [4, 3], [4, 3], [4, 3], // 1000xxxxx
michael@0 35846 [4, 3], [4, 3], [4, 3], [4, 3],
michael@0 35847 [4, 3], [4, 3], [4, 3], [4, 3],
michael@0 35848 [4, 3], [4, 3], [4, 3], [4, 3],
michael@0 35849 [4, 3], [4, 3], [4, 3], [4, 3],
michael@0 35850 [4, 3], [4, 3], [4, 3], [4, 3],
michael@0 35851 [4, 3], [4, 3], [4, 3], [4, 3],
michael@0 35852 [4, 3], [4, 3], [4, 3], [4, 3],
michael@0 35853 [5, 128], [5, 128], [5, 128], [5, 128], // 10010xxxx
michael@0 35854 [5, 128], [5, 128], [5, 128], [5, 128],
michael@0 35855 [5, 128], [5, 128], [5, 128], [5, 128],
michael@0 35856 [5, 128], [5, 128], [5, 128], [5, 128],
michael@0 35857 [5, 8], [5, 8], [5, 8], [5, 8], // 10011xxxx
michael@0 35858 [5, 8], [5, 8], [5, 8], [5, 8],
michael@0 35859 [5, 8], [5, 8], [5, 8], [5, 8],
michael@0 35860 [5, 8], [5, 8], [5, 8], [5, 8],
michael@0 35861 [5, 9], [5, 9], [5, 9], [5, 9], // 10100xxxx
michael@0 35862 [5, 9], [5, 9], [5, 9], [5, 9],
michael@0 35863 [5, 9], [5, 9], [5, 9], [5, 9],
michael@0 35864 [5, 9], [5, 9], [5, 9], [5, 9],
michael@0 35865 [6, 16], [6, 16], [6, 16], [6, 16], // 101010xxx
michael@0 35866 [6, 16], [6, 16], [6, 16], [6, 16],
michael@0 35867 [6, 17], [6, 17], [6, 17], [6, 17], // 101011xxx
michael@0 35868 [6, 17], [6, 17], [6, 17], [6, 17],
michael@0 35869 [4, 4], [4, 4], [4, 4], [4, 4], // 1011xxxxx
michael@0 35870 [4, 4], [4, 4], [4, 4], [4, 4],
michael@0 35871 [4, 4], [4, 4], [4, 4], [4, 4],
michael@0 35872 [4, 4], [4, 4], [4, 4], [4, 4],
michael@0 35873 [4, 4], [4, 4], [4, 4], [4, 4],
michael@0 35874 [4, 4], [4, 4], [4, 4], [4, 4],
michael@0 35875 [4, 4], [4, 4], [4, 4], [4, 4],
michael@0 35876 [4, 4], [4, 4], [4, 4], [4, 4],
michael@0 35877 [4, 5], [4, 5], [4, 5], [4, 5], // 1100xxxxx
michael@0 35878 [4, 5], [4, 5], [4, 5], [4, 5],
michael@0 35879 [4, 5], [4, 5], [4, 5], [4, 5],
michael@0 35880 [4, 5], [4, 5], [4, 5], [4, 5],
michael@0 35881 [4, 5], [4, 5], [4, 5], [4, 5],
michael@0 35882 [4, 5], [4, 5], [4, 5], [4, 5],
michael@0 35883 [4, 5], [4, 5], [4, 5], [4, 5],
michael@0 35884 [4, 5], [4, 5], [4, 5], [4, 5],
michael@0 35885 [6, 14], [6, 14], [6, 14], [6, 14], // 110100xxx
michael@0 35886 [6, 14], [6, 14], [6, 14], [6, 14],
michael@0 35887 [6, 15], [6, 15], [6, 15], [6, 15], // 110101xxx
michael@0 35888 [6, 15], [6, 15], [6, 15], [6, 15],
michael@0 35889 [5, 64], [5, 64], [5, 64], [5, 64], // 11011xxxx
michael@0 35890 [5, 64], [5, 64], [5, 64], [5, 64],
michael@0 35891 [5, 64], [5, 64], [5, 64], [5, 64],
michael@0 35892 [5, 64], [5, 64], [5, 64], [5, 64],
michael@0 35893 [4, 6], [4, 6], [4, 6], [4, 6], // 1110xxxxx
michael@0 35894 [4, 6], [4, 6], [4, 6], [4, 6],
michael@0 35895 [4, 6], [4, 6], [4, 6], [4, 6],
michael@0 35896 [4, 6], [4, 6], [4, 6], [4, 6],
michael@0 35897 [4, 6], [4, 6], [4, 6], [4, 6],
michael@0 35898 [4, 6], [4, 6], [4, 6], [4, 6],
michael@0 35899 [4, 6], [4, 6], [4, 6], [4, 6],
michael@0 35900 [4, 6], [4, 6], [4, 6], [4, 6],
michael@0 35901 [4, 7], [4, 7], [4, 7], [4, 7], // 1111xxxxx
michael@0 35902 [4, 7], [4, 7], [4, 7], [4, 7],
michael@0 35903 [4, 7], [4, 7], [4, 7], [4, 7],
michael@0 35904 [4, 7], [4, 7], [4, 7], [4, 7],
michael@0 35905 [4, 7], [4, 7], [4, 7], [4, 7],
michael@0 35906 [4, 7], [4, 7], [4, 7], [4, 7],
michael@0 35907 [4, 7], [4, 7], [4, 7], [4, 7],
michael@0 35908 [4, 7], [4, 7], [4, 7], [4, 7]
michael@0 35909 ];
michael@0 35910
michael@0 35911 var blackTable1 = [
michael@0 35912 [-1, -1], [-1, -1], // 000000000000x
michael@0 35913 [12, ccittEOL], [12, ccittEOL], // 000000000001x
michael@0 35914 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000001xx
michael@0 35915 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000010xx
michael@0 35916 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000011xx
michael@0 35917 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000100xx
michael@0 35918 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000101xx
michael@0 35919 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000110xx
michael@0 35920 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000111xx
michael@0 35921 [11, 1792], [11, 1792], [11, 1792], [11, 1792], // 00000001000xx
michael@0 35922 [12, 1984], [12, 1984], // 000000010010x
michael@0 35923 [12, 2048], [12, 2048], // 000000010011x
michael@0 35924 [12, 2112], [12, 2112], // 000000010100x
michael@0 35925 [12, 2176], [12, 2176], // 000000010101x
michael@0 35926 [12, 2240], [12, 2240], // 000000010110x
michael@0 35927 [12, 2304], [12, 2304], // 000000010111x
michael@0 35928 [11, 1856], [11, 1856], [11, 1856], [11, 1856], // 00000001100xx
michael@0 35929 [11, 1920], [11, 1920], [11, 1920], [11, 1920], // 00000001101xx
michael@0 35930 [12, 2368], [12, 2368], // 000000011100x
michael@0 35931 [12, 2432], [12, 2432], // 000000011101x
michael@0 35932 [12, 2496], [12, 2496], // 000000011110x
michael@0 35933 [12, 2560], [12, 2560], // 000000011111x
michael@0 35934 [10, 18], [10, 18], [10, 18], [10, 18], // 0000001000xxx
michael@0 35935 [10, 18], [10, 18], [10, 18], [10, 18],
michael@0 35936 [12, 52], [12, 52], // 000000100100x
michael@0 35937 [13, 640], // 0000001001010
michael@0 35938 [13, 704], // 0000001001011
michael@0 35939 [13, 768], // 0000001001100
michael@0 35940 [13, 832], // 0000001001101
michael@0 35941 [12, 55], [12, 55], // 000000100111x
michael@0 35942 [12, 56], [12, 56], // 000000101000x
michael@0 35943 [13, 1280], // 0000001010010
michael@0 35944 [13, 1344], // 0000001010011
michael@0 35945 [13, 1408], // 0000001010100
michael@0 35946 [13, 1472], // 0000001010101
michael@0 35947 [12, 59], [12, 59], // 000000101011x
michael@0 35948 [12, 60], [12, 60], // 000000101100x
michael@0 35949 [13, 1536], // 0000001011010
michael@0 35950 [13, 1600], // 0000001011011
michael@0 35951 [11, 24], [11, 24], [11, 24], [11, 24], // 00000010111xx
michael@0 35952 [11, 25], [11, 25], [11, 25], [11, 25], // 00000011000xx
michael@0 35953 [13, 1664], // 0000001100100
michael@0 35954 [13, 1728], // 0000001100101
michael@0 35955 [12, 320], [12, 320], // 000000110011x
michael@0 35956 [12, 384], [12, 384], // 000000110100x
michael@0 35957 [12, 448], [12, 448], // 000000110101x
michael@0 35958 [13, 512], // 0000001101100
michael@0 35959 [13, 576], // 0000001101101
michael@0 35960 [12, 53], [12, 53], // 000000110111x
michael@0 35961 [12, 54], [12, 54], // 000000111000x
michael@0 35962 [13, 896], // 0000001110010
michael@0 35963 [13, 960], // 0000001110011
michael@0 35964 [13, 1024], // 0000001110100
michael@0 35965 [13, 1088], // 0000001110101
michael@0 35966 [13, 1152], // 0000001110110
michael@0 35967 [13, 1216], // 0000001110111
michael@0 35968 [10, 64], [10, 64], [10, 64], [10, 64], // 0000001111xxx
michael@0 35969 [10, 64], [10, 64], [10, 64], [10, 64]
michael@0 35970 ];
michael@0 35971
michael@0 35972 var blackTable2 = [
michael@0 35973 [8, 13], [8, 13], [8, 13], [8, 13], // 00000100xxxx
michael@0 35974 [8, 13], [8, 13], [8, 13], [8, 13],
michael@0 35975 [8, 13], [8, 13], [8, 13], [8, 13],
michael@0 35976 [8, 13], [8, 13], [8, 13], [8, 13],
michael@0 35977 [11, 23], [11, 23], // 00000101000x
michael@0 35978 [12, 50], // 000001010010
michael@0 35979 [12, 51], // 000001010011
michael@0 35980 [12, 44], // 000001010100
michael@0 35981 [12, 45], // 000001010101
michael@0 35982 [12, 46], // 000001010110
michael@0 35983 [12, 47], // 000001010111
michael@0 35984 [12, 57], // 000001011000
michael@0 35985 [12, 58], // 000001011001
michael@0 35986 [12, 61], // 000001011010
michael@0 35987 [12, 256], // 000001011011
michael@0 35988 [10, 16], [10, 16], [10, 16], [10, 16], // 0000010111xx
michael@0 35989 [10, 17], [10, 17], [10, 17], [10, 17], // 0000011000xx
michael@0 35990 [12, 48], // 000001100100
michael@0 35991 [12, 49], // 000001100101
michael@0 35992 [12, 62], // 000001100110
michael@0 35993 [12, 63], // 000001100111
michael@0 35994 [12, 30], // 000001101000
michael@0 35995 [12, 31], // 000001101001
michael@0 35996 [12, 32], // 000001101010
michael@0 35997 [12, 33], // 000001101011
michael@0 35998 [12, 40], // 000001101100
michael@0 35999 [12, 41], // 000001101101
michael@0 36000 [11, 22], [11, 22], // 00000110111x
michael@0 36001 [8, 14], [8, 14], [8, 14], [8, 14], // 00000111xxxx
michael@0 36002 [8, 14], [8, 14], [8, 14], [8, 14],
michael@0 36003 [8, 14], [8, 14], [8, 14], [8, 14],
michael@0 36004 [8, 14], [8, 14], [8, 14], [8, 14],
michael@0 36005 [7, 10], [7, 10], [7, 10], [7, 10], // 0000100xxxxx
michael@0 36006 [7, 10], [7, 10], [7, 10], [7, 10],
michael@0 36007 [7, 10], [7, 10], [7, 10], [7, 10],
michael@0 36008 [7, 10], [7, 10], [7, 10], [7, 10],
michael@0 36009 [7, 10], [7, 10], [7, 10], [7, 10],
michael@0 36010 [7, 10], [7, 10], [7, 10], [7, 10],
michael@0 36011 [7, 10], [7, 10], [7, 10], [7, 10],
michael@0 36012 [7, 10], [7, 10], [7, 10], [7, 10],
michael@0 36013 [7, 11], [7, 11], [7, 11], [7, 11], // 0000101xxxxx
michael@0 36014 [7, 11], [7, 11], [7, 11], [7, 11],
michael@0 36015 [7, 11], [7, 11], [7, 11], [7, 11],
michael@0 36016 [7, 11], [7, 11], [7, 11], [7, 11],
michael@0 36017 [7, 11], [7, 11], [7, 11], [7, 11],
michael@0 36018 [7, 11], [7, 11], [7, 11], [7, 11],
michael@0 36019 [7, 11], [7, 11], [7, 11], [7, 11],
michael@0 36020 [7, 11], [7, 11], [7, 11], [7, 11],
michael@0 36021 [9, 15], [9, 15], [9, 15], [9, 15], // 000011000xxx
michael@0 36022 [9, 15], [9, 15], [9, 15], [9, 15],
michael@0 36023 [12, 128], // 000011001000
michael@0 36024 [12, 192], // 000011001001
michael@0 36025 [12, 26], // 000011001010
michael@0 36026 [12, 27], // 000011001011
michael@0 36027 [12, 28], // 000011001100
michael@0 36028 [12, 29], // 000011001101
michael@0 36029 [11, 19], [11, 19], // 00001100111x
michael@0 36030 [11, 20], [11, 20], // 00001101000x
michael@0 36031 [12, 34], // 000011010010
michael@0 36032 [12, 35], // 000011010011
michael@0 36033 [12, 36], // 000011010100
michael@0 36034 [12, 37], // 000011010101
michael@0 36035 [12, 38], // 000011010110
michael@0 36036 [12, 39], // 000011010111
michael@0 36037 [11, 21], [11, 21], // 00001101100x
michael@0 36038 [12, 42], // 000011011010
michael@0 36039 [12, 43], // 000011011011
michael@0 36040 [10, 0], [10, 0], [10, 0], [10, 0], // 0000110111xx
michael@0 36041 [7, 12], [7, 12], [7, 12], [7, 12], // 0000111xxxxx
michael@0 36042 [7, 12], [7, 12], [7, 12], [7, 12],
michael@0 36043 [7, 12], [7, 12], [7, 12], [7, 12],
michael@0 36044 [7, 12], [7, 12], [7, 12], [7, 12],
michael@0 36045 [7, 12], [7, 12], [7, 12], [7, 12],
michael@0 36046 [7, 12], [7, 12], [7, 12], [7, 12],
michael@0 36047 [7, 12], [7, 12], [7, 12], [7, 12],
michael@0 36048 [7, 12], [7, 12], [7, 12], [7, 12]
michael@0 36049 ];
michael@0 36050
michael@0 36051 var blackTable3 = [
michael@0 36052 [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000xx
michael@0 36053 [6, 9], // 000100
michael@0 36054 [6, 8], // 000101
michael@0 36055 [5, 7], [5, 7], // 00011x
michael@0 36056 [4, 6], [4, 6], [4, 6], [4, 6], // 0010xx
michael@0 36057 [4, 5], [4, 5], [4, 5], [4, 5], // 0011xx
michael@0 36058 [3, 1], [3, 1], [3, 1], [3, 1], // 010xxx
michael@0 36059 [3, 1], [3, 1], [3, 1], [3, 1],
michael@0 36060 [3, 4], [3, 4], [3, 4], [3, 4], // 011xxx
michael@0 36061 [3, 4], [3, 4], [3, 4], [3, 4],
michael@0 36062 [2, 3], [2, 3], [2, 3], [2, 3], // 10xxxx
michael@0 36063 [2, 3], [2, 3], [2, 3], [2, 3],
michael@0 36064 [2, 3], [2, 3], [2, 3], [2, 3],
michael@0 36065 [2, 3], [2, 3], [2, 3], [2, 3],
michael@0 36066 [2, 2], [2, 2], [2, 2], [2, 2], // 11xxxx
michael@0 36067 [2, 2], [2, 2], [2, 2], [2, 2],
michael@0 36068 [2, 2], [2, 2], [2, 2], [2, 2],
michael@0 36069 [2, 2], [2, 2], [2, 2], [2, 2]
michael@0 36070 ];
michael@0 36071
michael@0 36072 function CCITTFaxStream(str, maybeLength, params) {
michael@0 36073 this.str = str;
michael@0 36074 this.dict = str.dict;
michael@0 36075
michael@0 36076 params = params || Dict.empty;
michael@0 36077
michael@0 36078 this.encoding = params.get('K') || 0;
michael@0 36079 this.eoline = params.get('EndOfLine') || false;
michael@0 36080 this.byteAlign = params.get('EncodedByteAlign') || false;
michael@0 36081 this.columns = params.get('Columns') || 1728;
michael@0 36082 this.rows = params.get('Rows') || 0;
michael@0 36083 var eoblock = params.get('EndOfBlock');
michael@0 36084 if (eoblock === null || eoblock === undefined) {
michael@0 36085 eoblock = true;
michael@0 36086 }
michael@0 36087 this.eoblock = eoblock;
michael@0 36088 this.black = params.get('BlackIs1') || false;
michael@0 36089
michael@0 36090 this.codingLine = new Uint32Array(this.columns + 1);
michael@0 36091 this.refLine = new Uint32Array(this.columns + 2);
michael@0 36092
michael@0 36093 this.codingLine[0] = this.columns;
michael@0 36094 this.codingPos = 0;
michael@0 36095
michael@0 36096 this.row = 0;
michael@0 36097 this.nextLine2D = this.encoding < 0;
michael@0 36098 this.inputBits = 0;
michael@0 36099 this.inputBuf = 0;
michael@0 36100 this.outputBits = 0;
michael@0 36101
michael@0 36102 var code1;
michael@0 36103 while ((code1 = this.lookBits(12)) === 0) {
michael@0 36104 this.eatBits(1);
michael@0 36105 }
michael@0 36106 if (code1 == 1) {
michael@0 36107 this.eatBits(12);
michael@0 36108 }
michael@0 36109 if (this.encoding > 0) {
michael@0 36110 this.nextLine2D = !this.lookBits(1);
michael@0 36111 this.eatBits(1);
michael@0 36112 }
michael@0 36113
michael@0 36114 DecodeStream.call(this, maybeLength);
michael@0 36115 }
michael@0 36116
michael@0 36117 CCITTFaxStream.prototype = Object.create(DecodeStream.prototype);
michael@0 36118
michael@0 36119 CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() {
michael@0 36120 while (!this.eof) {
michael@0 36121 var c = this.lookChar();
michael@0 36122 this.ensureBuffer(this.bufferLength + 1);
michael@0 36123 this.buffer[this.bufferLength++] = c;
michael@0 36124 }
michael@0 36125 };
michael@0 36126
michael@0 36127 CCITTFaxStream.prototype.addPixels =
michael@0 36128 function ccittFaxStreamAddPixels(a1, blackPixels) {
michael@0 36129 var codingLine = this.codingLine;
michael@0 36130 var codingPos = this.codingPos;
michael@0 36131
michael@0 36132 if (a1 > codingLine[codingPos]) {
michael@0 36133 if (a1 > this.columns) {
michael@0 36134 info('row is wrong length');
michael@0 36135 this.err = true;
michael@0 36136 a1 = this.columns;
michael@0 36137 }
michael@0 36138 if ((codingPos & 1) ^ blackPixels) {
michael@0 36139 ++codingPos;
michael@0 36140 }
michael@0 36141
michael@0 36142 codingLine[codingPos] = a1;
michael@0 36143 }
michael@0 36144 this.codingPos = codingPos;
michael@0 36145 };
michael@0 36146
michael@0 36147 CCITTFaxStream.prototype.addPixelsNeg =
michael@0 36148 function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
michael@0 36149 var codingLine = this.codingLine;
michael@0 36150 var codingPos = this.codingPos;
michael@0 36151
michael@0 36152 if (a1 > codingLine[codingPos]) {
michael@0 36153 if (a1 > this.columns) {
michael@0 36154 info('row is wrong length');
michael@0 36155 this.err = true;
michael@0 36156 a1 = this.columns;
michael@0 36157 }
michael@0 36158 if ((codingPos & 1) ^ blackPixels) {
michael@0 36159 ++codingPos;
michael@0 36160 }
michael@0 36161
michael@0 36162 codingLine[codingPos] = a1;
michael@0 36163 } else if (a1 < codingLine[codingPos]) {
michael@0 36164 if (a1 < 0) {
michael@0 36165 info('invalid code');
michael@0 36166 this.err = true;
michael@0 36167 a1 = 0;
michael@0 36168 }
michael@0 36169 while (codingPos > 0 && a1 < codingLine[codingPos - 1]) {
michael@0 36170 --codingPos;
michael@0 36171 }
michael@0 36172 codingLine[codingPos] = a1;
michael@0 36173 }
michael@0 36174
michael@0 36175 this.codingPos = codingPos;
michael@0 36176 };
michael@0 36177
michael@0 36178 CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() {
michael@0 36179 var refLine = this.refLine;
michael@0 36180 var codingLine = this.codingLine;
michael@0 36181 var columns = this.columns;
michael@0 36182
michael@0 36183 var refPos, blackPixels, bits, i;
michael@0 36184
michael@0 36185 if (this.outputBits === 0) {
michael@0 36186 if (this.eof) {
michael@0 36187 return null;
michael@0 36188 }
michael@0 36189 this.err = false;
michael@0 36190
michael@0 36191 var code1, code2, code3;
michael@0 36192 if (this.nextLine2D) {
michael@0 36193 for (i = 0; codingLine[i] < columns; ++i) {
michael@0 36194 refLine[i] = codingLine[i];
michael@0 36195 }
michael@0 36196 refLine[i++] = columns;
michael@0 36197 refLine[i] = columns;
michael@0 36198 codingLine[0] = 0;
michael@0 36199 this.codingPos = 0;
michael@0 36200 refPos = 0;
michael@0 36201 blackPixels = 0;
michael@0 36202
michael@0 36203 while (codingLine[this.codingPos] < columns) {
michael@0 36204 code1 = this.getTwoDimCode();
michael@0 36205 switch (code1) {
michael@0 36206 case twoDimPass:
michael@0 36207 this.addPixels(refLine[refPos + 1], blackPixels);
michael@0 36208 if (refLine[refPos + 1] < columns) {
michael@0 36209 refPos += 2;
michael@0 36210 }
michael@0 36211 break;
michael@0 36212 case twoDimHoriz:
michael@0 36213 code1 = code2 = 0;
michael@0 36214 if (blackPixels) {
michael@0 36215 do {
michael@0 36216 code1 += (code3 = this.getBlackCode());
michael@0 36217 } while (code3 >= 64);
michael@0 36218 do {
michael@0 36219 code2 += (code3 = this.getWhiteCode());
michael@0 36220 } while (code3 >= 64);
michael@0 36221 } else {
michael@0 36222 do {
michael@0 36223 code1 += (code3 = this.getWhiteCode());
michael@0 36224 } while (code3 >= 64);
michael@0 36225 do {
michael@0 36226 code2 += (code3 = this.getBlackCode());
michael@0 36227 } while (code3 >= 64);
michael@0 36228 }
michael@0 36229 this.addPixels(codingLine[this.codingPos] +
michael@0 36230 code1, blackPixels);
michael@0 36231 if (codingLine[this.codingPos] < columns) {
michael@0 36232 this.addPixels(codingLine[this.codingPos] + code2,
michael@0 36233 blackPixels ^ 1);
michael@0 36234 }
michael@0 36235 while (refLine[refPos] <= codingLine[this.codingPos] &&
michael@0 36236 refLine[refPos] < columns) {
michael@0 36237 refPos += 2;
michael@0 36238 }
michael@0 36239 break;
michael@0 36240 case twoDimVertR3:
michael@0 36241 this.addPixels(refLine[refPos] + 3, blackPixels);
michael@0 36242 blackPixels ^= 1;
michael@0 36243 if (codingLine[this.codingPos] < columns) {
michael@0 36244 ++refPos;
michael@0 36245 while (refLine[refPos] <= codingLine[this.codingPos] &&
michael@0 36246 refLine[refPos] < columns) {
michael@0 36247 refPos += 2;
michael@0 36248 }
michael@0 36249 }
michael@0 36250 break;
michael@0 36251 case twoDimVertR2:
michael@0 36252 this.addPixels(refLine[refPos] + 2, blackPixels);
michael@0 36253 blackPixels ^= 1;
michael@0 36254 if (codingLine[this.codingPos] < columns) {
michael@0 36255 ++refPos;
michael@0 36256 while (refLine[refPos] <= codingLine[this.codingPos] &&
michael@0 36257 refLine[refPos] < columns) {
michael@0 36258 refPos += 2;
michael@0 36259 }
michael@0 36260 }
michael@0 36261 break;
michael@0 36262 case twoDimVertR1:
michael@0 36263 this.addPixels(refLine[refPos] + 1, blackPixels);
michael@0 36264 blackPixels ^= 1;
michael@0 36265 if (codingLine[this.codingPos] < columns) {
michael@0 36266 ++refPos;
michael@0 36267 while (refLine[refPos] <= codingLine[this.codingPos] &&
michael@0 36268 refLine[refPos] < columns) {
michael@0 36269 refPos += 2;
michael@0 36270 }
michael@0 36271 }
michael@0 36272 break;
michael@0 36273 case twoDimVert0:
michael@0 36274 this.addPixels(refLine[refPos], blackPixels);
michael@0 36275 blackPixels ^= 1;
michael@0 36276 if (codingLine[this.codingPos] < columns) {
michael@0 36277 ++refPos;
michael@0 36278 while (refLine[refPos] <= codingLine[this.codingPos] &&
michael@0 36279 refLine[refPos] < columns) {
michael@0 36280 refPos += 2;
michael@0 36281 }
michael@0 36282 }
michael@0 36283 break;
michael@0 36284 case twoDimVertL3:
michael@0 36285 this.addPixelsNeg(refLine[refPos] - 3, blackPixels);
michael@0 36286 blackPixels ^= 1;
michael@0 36287 if (codingLine[this.codingPos] < columns) {
michael@0 36288 if (refPos > 0) {
michael@0 36289 --refPos;
michael@0 36290 } else {
michael@0 36291 ++refPos;
michael@0 36292 }
michael@0 36293 while (refLine[refPos] <= codingLine[this.codingPos] &&
michael@0 36294 refLine[refPos] < columns) {
michael@0 36295 refPos += 2;
michael@0 36296 }
michael@0 36297 }
michael@0 36298 break;
michael@0 36299 case twoDimVertL2:
michael@0 36300 this.addPixelsNeg(refLine[refPos] - 2, blackPixels);
michael@0 36301 blackPixels ^= 1;
michael@0 36302 if (codingLine[this.codingPos] < columns) {
michael@0 36303 if (refPos > 0) {
michael@0 36304 --refPos;
michael@0 36305 } else {
michael@0 36306 ++refPos;
michael@0 36307 }
michael@0 36308 while (refLine[refPos] <= codingLine[this.codingPos] &&
michael@0 36309 refLine[refPos] < columns) {
michael@0 36310 refPos += 2;
michael@0 36311 }
michael@0 36312 }
michael@0 36313 break;
michael@0 36314 case twoDimVertL1:
michael@0 36315 this.addPixelsNeg(refLine[refPos] - 1, blackPixels);
michael@0 36316 blackPixels ^= 1;
michael@0 36317 if (codingLine[this.codingPos] < columns) {
michael@0 36318 if (refPos > 0) {
michael@0 36319 --refPos;
michael@0 36320 } else {
michael@0 36321 ++refPos;
michael@0 36322 }
michael@0 36323 while (refLine[refPos] <= codingLine[this.codingPos] &&
michael@0 36324 refLine[refPos] < columns) {
michael@0 36325 refPos += 2;
michael@0 36326 }
michael@0 36327 }
michael@0 36328 break;
michael@0 36329 case EOF:
michael@0 36330 this.addPixels(columns, 0);
michael@0 36331 this.eof = true;
michael@0 36332 break;
michael@0 36333 default:
michael@0 36334 info('bad 2d code');
michael@0 36335 this.addPixels(columns, 0);
michael@0 36336 this.err = true;
michael@0 36337 }
michael@0 36338 }
michael@0 36339 } else {
michael@0 36340 codingLine[0] = 0;
michael@0 36341 this.codingPos = 0;
michael@0 36342 blackPixels = 0;
michael@0 36343 while (codingLine[this.codingPos] < columns) {
michael@0 36344 code1 = 0;
michael@0 36345 if (blackPixels) {
michael@0 36346 do {
michael@0 36347 code1 += (code3 = this.getBlackCode());
michael@0 36348 } while (code3 >= 64);
michael@0 36349 } else {
michael@0 36350 do {
michael@0 36351 code1 += (code3 = this.getWhiteCode());
michael@0 36352 } while (code3 >= 64);
michael@0 36353 }
michael@0 36354 this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
michael@0 36355 blackPixels ^= 1;
michael@0 36356 }
michael@0 36357 }
michael@0 36358
michael@0 36359 if (this.byteAlign) {
michael@0 36360 this.inputBits &= ~7;
michael@0 36361 }
michael@0 36362
michael@0 36363 var gotEOL = false;
michael@0 36364
michael@0 36365 if (!this.eoblock && this.row == this.rows - 1) {
michael@0 36366 this.eof = true;
michael@0 36367 } else {
michael@0 36368 code1 = this.lookBits(12);
michael@0 36369 while (code1 === 0) {
michael@0 36370 this.eatBits(1);
michael@0 36371 code1 = this.lookBits(12);
michael@0 36372 }
michael@0 36373 if (code1 == 1) {
michael@0 36374 this.eatBits(12);
michael@0 36375 gotEOL = true;
michael@0 36376 } else if (code1 == EOF) {
michael@0 36377 this.eof = true;
michael@0 36378 }
michael@0 36379 }
michael@0 36380
michael@0 36381 if (!this.eof && this.encoding > 0) {
michael@0 36382 this.nextLine2D = !this.lookBits(1);
michael@0 36383 this.eatBits(1);
michael@0 36384 }
michael@0 36385
michael@0 36386 if (this.eoblock && gotEOL) {
michael@0 36387 code1 = this.lookBits(12);
michael@0 36388 if (code1 == 1) {
michael@0 36389 this.eatBits(12);
michael@0 36390 if (this.encoding > 0) {
michael@0 36391 this.lookBits(1);
michael@0 36392 this.eatBits(1);
michael@0 36393 }
michael@0 36394 if (this.encoding >= 0) {
michael@0 36395 for (i = 0; i < 4; ++i) {
michael@0 36396 code1 = this.lookBits(12);
michael@0 36397 if (code1 != 1) {
michael@0 36398 info('bad rtc code: ' + code1);
michael@0 36399 }
michael@0 36400 this.eatBits(12);
michael@0 36401 if (this.encoding > 0) {
michael@0 36402 this.lookBits(1);
michael@0 36403 this.eatBits(1);
michael@0 36404 }
michael@0 36405 }
michael@0 36406 }
michael@0 36407 this.eof = true;
michael@0 36408 }
michael@0 36409 } else if (this.err && this.eoline) {
michael@0 36410 while (true) {
michael@0 36411 code1 = this.lookBits(13);
michael@0 36412 if (code1 == EOF) {
michael@0 36413 this.eof = true;
michael@0 36414 return null;
michael@0 36415 }
michael@0 36416 if ((code1 >> 1) == 1) {
michael@0 36417 break;
michael@0 36418 }
michael@0 36419 this.eatBits(1);
michael@0 36420 }
michael@0 36421 this.eatBits(12);
michael@0 36422 if (this.encoding > 0) {
michael@0 36423 this.eatBits(1);
michael@0 36424 this.nextLine2D = !(code1 & 1);
michael@0 36425 }
michael@0 36426 }
michael@0 36427
michael@0 36428 if (codingLine[0] > 0) {
michael@0 36429 this.outputBits = codingLine[this.codingPos = 0];
michael@0 36430 } else {
michael@0 36431 this.outputBits = codingLine[this.codingPos = 1];
michael@0 36432 }
michael@0 36433 this.row++;
michael@0 36434 }
michael@0 36435
michael@0 36436 var c;
michael@0 36437 if (this.outputBits >= 8) {
michael@0 36438 c = (this.codingPos & 1) ? 0 : 0xFF;
michael@0 36439 this.outputBits -= 8;
michael@0 36440 if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
michael@0 36441 this.codingPos++;
michael@0 36442 this.outputBits = (codingLine[this.codingPos] -
michael@0 36443 codingLine[this.codingPos - 1]);
michael@0 36444 }
michael@0 36445 } else {
michael@0 36446 bits = 8;
michael@0 36447 c = 0;
michael@0 36448 do {
michael@0 36449 if (this.outputBits > bits) {
michael@0 36450 c <<= bits;
michael@0 36451 if (!(this.codingPos & 1)) {
michael@0 36452 c |= 0xFF >> (8 - bits);
michael@0 36453 }
michael@0 36454 this.outputBits -= bits;
michael@0 36455 bits = 0;
michael@0 36456 } else {
michael@0 36457 c <<= this.outputBits;
michael@0 36458 if (!(this.codingPos & 1)) {
michael@0 36459 c |= 0xFF >> (8 - this.outputBits);
michael@0 36460 }
michael@0 36461 bits -= this.outputBits;
michael@0 36462 this.outputBits = 0;
michael@0 36463 if (codingLine[this.codingPos] < columns) {
michael@0 36464 this.codingPos++;
michael@0 36465 this.outputBits = (codingLine[this.codingPos] -
michael@0 36466 codingLine[this.codingPos - 1]);
michael@0 36467 } else if (bits > 0) {
michael@0 36468 c <<= bits;
michael@0 36469 bits = 0;
michael@0 36470 }
michael@0 36471 }
michael@0 36472 } while (bits);
michael@0 36473 }
michael@0 36474 if (this.black) {
michael@0 36475 c ^= 0xFF;
michael@0 36476 }
michael@0 36477 return c;
michael@0 36478 };
michael@0 36479
michael@0 36480 // This functions returns the code found from the table.
michael@0 36481 // The start and end parameters set the boundaries for searching the table.
michael@0 36482 // The limit parameter is optional. Function returns an array with three
michael@0 36483 // values. The first array element indicates whether a valid code is being
michael@0 36484 // returned. The second array element is the actual code. The third array
michael@0 36485 // element indicates whether EOF was reached.
michael@0 36486 CCITTFaxStream.prototype.findTableCode =
michael@0 36487 function ccittFaxStreamFindTableCode(start, end, table, limit) {
michael@0 36488
michael@0 36489 var limitValue = limit || 0;
michael@0 36490 for (var i = start; i <= end; ++i) {
michael@0 36491 var code = this.lookBits(i);
michael@0 36492 if (code == EOF) {
michael@0 36493 return [true, 1, false];
michael@0 36494 }
michael@0 36495 if (i < end) {
michael@0 36496 code <<= end - i;
michael@0 36497 }
michael@0 36498 if (!limitValue || code >= limitValue) {
michael@0 36499 var p = table[code - limitValue];
michael@0 36500 if (p[0] == i) {
michael@0 36501 this.eatBits(i);
michael@0 36502 return [true, p[1], true];
michael@0 36503 }
michael@0 36504 }
michael@0 36505 }
michael@0 36506 return [false, 0, false];
michael@0 36507 };
michael@0 36508
michael@0 36509 CCITTFaxStream.prototype.getTwoDimCode =
michael@0 36510 function ccittFaxStreamGetTwoDimCode() {
michael@0 36511
michael@0 36512 var code = 0;
michael@0 36513 var p;
michael@0 36514 if (this.eoblock) {
michael@0 36515 code = this.lookBits(7);
michael@0 36516 p = twoDimTable[code];
michael@0 36517 if (p && p[0] > 0) {
michael@0 36518 this.eatBits(p[0]);
michael@0 36519 return p[1];
michael@0 36520 }
michael@0 36521 } else {
michael@0 36522 var result = this.findTableCode(1, 7, twoDimTable);
michael@0 36523 if (result[0] && result[2]) {
michael@0 36524 return result[1];
michael@0 36525 }
michael@0 36526 }
michael@0 36527 info('Bad two dim code');
michael@0 36528 return EOF;
michael@0 36529 };
michael@0 36530
michael@0 36531 CCITTFaxStream.prototype.getWhiteCode =
michael@0 36532 function ccittFaxStreamGetWhiteCode() {
michael@0 36533
michael@0 36534 var code = 0;
michael@0 36535 var p;
michael@0 36536 if (this.eoblock) {
michael@0 36537 code = this.lookBits(12);
michael@0 36538 if (code == EOF) {
michael@0 36539 return 1;
michael@0 36540 }
michael@0 36541
michael@0 36542 if ((code >> 5) === 0) {
michael@0 36543 p = whiteTable1[code];
michael@0 36544 } else {
michael@0 36545 p = whiteTable2[code >> 3];
michael@0 36546 }
michael@0 36547
michael@0 36548 if (p[0] > 0) {
michael@0 36549 this.eatBits(p[0]);
michael@0 36550 return p[1];
michael@0 36551 }
michael@0 36552 } else {
michael@0 36553 var result = this.findTableCode(1, 9, whiteTable2);
michael@0 36554 if (result[0]) {
michael@0 36555 return result[1];
michael@0 36556 }
michael@0 36557
michael@0 36558 result = this.findTableCode(11, 12, whiteTable1);
michael@0 36559 if (result[0]) {
michael@0 36560 return result[1];
michael@0 36561 }
michael@0 36562 }
michael@0 36563 info('bad white code');
michael@0 36564 this.eatBits(1);
michael@0 36565 return 1;
michael@0 36566 };
michael@0 36567
michael@0 36568 CCITTFaxStream.prototype.getBlackCode =
michael@0 36569 function ccittFaxStreamGetBlackCode() {
michael@0 36570
michael@0 36571 var code, p;
michael@0 36572 if (this.eoblock) {
michael@0 36573 code = this.lookBits(13);
michael@0 36574 if (code == EOF) {
michael@0 36575 return 1;
michael@0 36576 }
michael@0 36577 if ((code >> 7) === 0) {
michael@0 36578 p = blackTable1[code];
michael@0 36579 } else if ((code >> 9) === 0 && (code >> 7) !== 0) {
michael@0 36580 p = blackTable2[(code >> 1) - 64];
michael@0 36581 } else {
michael@0 36582 p = blackTable3[code >> 7];
michael@0 36583 }
michael@0 36584
michael@0 36585 if (p[0] > 0) {
michael@0 36586 this.eatBits(p[0]);
michael@0 36587 return p[1];
michael@0 36588 }
michael@0 36589 } else {
michael@0 36590 var result = this.findTableCode(2, 6, blackTable3);
michael@0 36591 if (result[0]) {
michael@0 36592 return result[1];
michael@0 36593 }
michael@0 36594
michael@0 36595 result = this.findTableCode(7, 12, blackTable2, 64);
michael@0 36596 if (result[0]) {
michael@0 36597 return result[1];
michael@0 36598 }
michael@0 36599
michael@0 36600 result = this.findTableCode(10, 13, blackTable1);
michael@0 36601 if (result[0]) {
michael@0 36602 return result[1];
michael@0 36603 }
michael@0 36604 }
michael@0 36605 info('bad black code');
michael@0 36606 this.eatBits(1);
michael@0 36607 return 1;
michael@0 36608 };
michael@0 36609
michael@0 36610 CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) {
michael@0 36611 var c;
michael@0 36612 while (this.inputBits < n) {
michael@0 36613 if ((c = this.str.getByte()) === -1) {
michael@0 36614 if (this.inputBits === 0) {
michael@0 36615 return EOF;
michael@0 36616 }
michael@0 36617 return ((this.inputBuf << (n - this.inputBits)) &
michael@0 36618 (0xFFFF >> (16 - n)));
michael@0 36619 }
michael@0 36620 this.inputBuf = (this.inputBuf << 8) + c;
michael@0 36621 this.inputBits += 8;
michael@0 36622 }
michael@0 36623 return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
michael@0 36624 };
michael@0 36625
michael@0 36626 CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) {
michael@0 36627 if ((this.inputBits -= n) < 0) {
michael@0 36628 this.inputBits = 0;
michael@0 36629 }
michael@0 36630 };
michael@0 36631
michael@0 36632 return CCITTFaxStream;
michael@0 36633 })();
michael@0 36634
michael@0 36635 var LZWStream = (function LZWStreamClosure() {
michael@0 36636 function LZWStream(str, maybeLength, earlyChange) {
michael@0 36637 this.str = str;
michael@0 36638 this.dict = str.dict;
michael@0 36639 this.cachedData = 0;
michael@0 36640 this.bitsCached = 0;
michael@0 36641
michael@0 36642 var maxLzwDictionarySize = 4096;
michael@0 36643 var lzwState = {
michael@0 36644 earlyChange: earlyChange,
michael@0 36645 codeLength: 9,
michael@0 36646 nextCode: 258,
michael@0 36647 dictionaryValues: new Uint8Array(maxLzwDictionarySize),
michael@0 36648 dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
michael@0 36649 dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
michael@0 36650 currentSequence: new Uint8Array(maxLzwDictionarySize),
michael@0 36651 currentSequenceLength: 0
michael@0 36652 };
michael@0 36653 for (var i = 0; i < 256; ++i) {
michael@0 36654 lzwState.dictionaryValues[i] = i;
michael@0 36655 lzwState.dictionaryLengths[i] = 1;
michael@0 36656 }
michael@0 36657 this.lzwState = lzwState;
michael@0 36658
michael@0 36659 DecodeStream.call(this, maybeLength);
michael@0 36660 }
michael@0 36661
michael@0 36662 LZWStream.prototype = Object.create(DecodeStream.prototype);
michael@0 36663
michael@0 36664 LZWStream.prototype.readBits = function LZWStream_readBits(n) {
michael@0 36665 var bitsCached = this.bitsCached;
michael@0 36666 var cachedData = this.cachedData;
michael@0 36667 while (bitsCached < n) {
michael@0 36668 var c = this.str.getByte();
michael@0 36669 if (c === -1) {
michael@0 36670 this.eof = true;
michael@0 36671 return null;
michael@0 36672 }
michael@0 36673 cachedData = (cachedData << 8) | c;
michael@0 36674 bitsCached += 8;
michael@0 36675 }
michael@0 36676 this.bitsCached = (bitsCached -= n);
michael@0 36677 this.cachedData = cachedData;
michael@0 36678 this.lastCode = null;
michael@0 36679 return (cachedData >>> bitsCached) & ((1 << n) - 1);
michael@0 36680 };
michael@0 36681
michael@0 36682 LZWStream.prototype.readBlock = function LZWStream_readBlock() {
michael@0 36683 var blockSize = 512;
michael@0 36684 var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
michael@0 36685 var i, j, q;
michael@0 36686
michael@0 36687 var lzwState = this.lzwState;
michael@0 36688 if (!lzwState) {
michael@0 36689 return; // eof was found
michael@0 36690 }
michael@0 36691
michael@0 36692 var earlyChange = lzwState.earlyChange;
michael@0 36693 var nextCode = lzwState.nextCode;
michael@0 36694 var dictionaryValues = lzwState.dictionaryValues;
michael@0 36695 var dictionaryLengths = lzwState.dictionaryLengths;
michael@0 36696 var dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
michael@0 36697 var codeLength = lzwState.codeLength;
michael@0 36698 var prevCode = lzwState.prevCode;
michael@0 36699 var currentSequence = lzwState.currentSequence;
michael@0 36700 var currentSequenceLength = lzwState.currentSequenceLength;
michael@0 36701
michael@0 36702 var decodedLength = 0;
michael@0 36703 var currentBufferLength = this.bufferLength;
michael@0 36704 var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
michael@0 36705
michael@0 36706 for (i = 0; i < blockSize; i++) {
michael@0 36707 var code = this.readBits(codeLength);
michael@0 36708 var hasPrev = currentSequenceLength > 0;
michael@0 36709 if (code < 256) {
michael@0 36710 currentSequence[0] = code;
michael@0 36711 currentSequenceLength = 1;
michael@0 36712 } else if (code >= 258) {
michael@0 36713 if (code < nextCode) {
michael@0 36714 currentSequenceLength = dictionaryLengths[code];
michael@0 36715 for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
michael@0 36716 currentSequence[j] = dictionaryValues[q];
michael@0 36717 q = dictionaryPrevCodes[q];
michael@0 36718 }
michael@0 36719 } else {
michael@0 36720 currentSequence[currentSequenceLength++] = currentSequence[0];
michael@0 36721 }
michael@0 36722 } else if (code == 256) {
michael@0 36723 codeLength = 9;
michael@0 36724 nextCode = 258;
michael@0 36725 currentSequenceLength = 0;
michael@0 36726 continue;
michael@0 36727 } else {
michael@0 36728 this.eof = true;
michael@0 36729 delete this.lzwState;
michael@0 36730 break;
michael@0 36731 }
michael@0 36732
michael@0 36733 if (hasPrev) {
michael@0 36734 dictionaryPrevCodes[nextCode] = prevCode;
michael@0 36735 dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
michael@0 36736 dictionaryValues[nextCode] = currentSequence[0];
michael@0 36737 nextCode++;
michael@0 36738 codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ?
michael@0 36739 codeLength : Math.min(Math.log(nextCode + earlyChange) /
michael@0 36740 0.6931471805599453 + 1, 12) | 0;
michael@0 36741 }
michael@0 36742 prevCode = code;
michael@0 36743
michael@0 36744 decodedLength += currentSequenceLength;
michael@0 36745 if (estimatedDecodedSize < decodedLength) {
michael@0 36746 do {
michael@0 36747 estimatedDecodedSize += decodedSizeDelta;
michael@0 36748 } while (estimatedDecodedSize < decodedLength);
michael@0 36749 buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
michael@0 36750 }
michael@0 36751 for (j = 0; j < currentSequenceLength; j++) {
michael@0 36752 buffer[currentBufferLength++] = currentSequence[j];
michael@0 36753 }
michael@0 36754 }
michael@0 36755 lzwState.nextCode = nextCode;
michael@0 36756 lzwState.codeLength = codeLength;
michael@0 36757 lzwState.prevCode = prevCode;
michael@0 36758 lzwState.currentSequenceLength = currentSequenceLength;
michael@0 36759
michael@0 36760 this.bufferLength = currentBufferLength;
michael@0 36761 };
michael@0 36762
michael@0 36763 return LZWStream;
michael@0 36764 })();
michael@0 36765
michael@0 36766 var NullStream = (function NullStreamClosure() {
michael@0 36767 function NullStream() {
michael@0 36768 Stream.call(this, new Uint8Array(0));
michael@0 36769 }
michael@0 36770
michael@0 36771 NullStream.prototype = Stream.prototype;
michael@0 36772
michael@0 36773 return NullStream;
michael@0 36774 })();
michael@0 36775
michael@0 36776
michael@0 36777 var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
michael@0 36778 setup: function wphSetup(handler) {
michael@0 36779 var pdfManager;
michael@0 36780
michael@0 36781 function loadDocument(recoveryMode) {
michael@0 36782 var loadDocumentPromise = new LegacyPromise();
michael@0 36783
michael@0 36784 var parseSuccess = function parseSuccess() {
michael@0 36785 var numPagesPromise = pdfManager.ensureDoc('numPages');
michael@0 36786 var fingerprintPromise = pdfManager.ensureDoc('fingerprint');
michael@0 36787 var outlinePromise = pdfManager.ensureCatalog('documentOutline');
michael@0 36788 var infoPromise = pdfManager.ensureDoc('documentInfo');
michael@0 36789 var metadataPromise = pdfManager.ensureCatalog('metadata');
michael@0 36790 var encryptedPromise = pdfManager.ensureXRef('encrypt');
michael@0 36791 var javaScriptPromise = pdfManager.ensureCatalog('javaScript');
michael@0 36792 Promise.all([numPagesPromise, fingerprintPromise, outlinePromise,
michael@0 36793 infoPromise, metadataPromise, encryptedPromise,
michael@0 36794 javaScriptPromise]).then(function onDocReady(results) {
michael@0 36795
michael@0 36796 var doc = {
michael@0 36797 numPages: results[0],
michael@0 36798 fingerprint: results[1],
michael@0 36799 outline: results[2],
michael@0 36800 info: results[3],
michael@0 36801 metadata: results[4],
michael@0 36802 encrypted: !!results[5],
michael@0 36803 javaScript: results[6]
michael@0 36804 };
michael@0 36805 loadDocumentPromise.resolve(doc);
michael@0 36806 },
michael@0 36807 parseFailure);
michael@0 36808 };
michael@0 36809
michael@0 36810 var parseFailure = function parseFailure(e) {
michael@0 36811 loadDocumentPromise.reject(e);
michael@0 36812 };
michael@0 36813
michael@0 36814 pdfManager.ensureDoc('checkHeader', []).then(function() {
michael@0 36815 pdfManager.ensureDoc('parseStartXRef', []).then(function() {
michael@0 36816 pdfManager.ensureDoc('parse', [recoveryMode]).then(
michael@0 36817 parseSuccess, parseFailure);
michael@0 36818 }, parseFailure);
michael@0 36819 }, parseFailure);
michael@0 36820
michael@0 36821 return loadDocumentPromise;
michael@0 36822 }
michael@0 36823
michael@0 36824 function getPdfManager(data) {
michael@0 36825 var pdfManagerPromise = new LegacyPromise();
michael@0 36826
michael@0 36827 var source = data.source;
michael@0 36828 var disableRange = data.disableRange;
michael@0 36829 if (source.data) {
michael@0 36830 try {
michael@0 36831 pdfManager = new LocalPdfManager(source.data, source.password);
michael@0 36832 pdfManagerPromise.resolve();
michael@0 36833 } catch (ex) {
michael@0 36834 pdfManagerPromise.reject(ex);
michael@0 36835 }
michael@0 36836 return pdfManagerPromise;
michael@0 36837 } else if (source.chunkedViewerLoading) {
michael@0 36838 try {
michael@0 36839 pdfManager = new NetworkPdfManager(source, handler);
michael@0 36840 pdfManagerPromise.resolve();
michael@0 36841 } catch (ex) {
michael@0 36842 pdfManagerPromise.reject(ex);
michael@0 36843 }
michael@0 36844 return pdfManagerPromise;
michael@0 36845 }
michael@0 36846
michael@0 36847 var networkManager = new NetworkManager(source.url, {
michael@0 36848 httpHeaders: source.httpHeaders,
michael@0 36849 withCredentials: source.withCredentials
michael@0 36850 });
michael@0 36851 var fullRequestXhrId = networkManager.requestFull({
michael@0 36852 onHeadersReceived: function onHeadersReceived() {
michael@0 36853 if (disableRange) {
michael@0 36854 return;
michael@0 36855 }
michael@0 36856
michael@0 36857 var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId);
michael@0 36858 if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') {
michael@0 36859 return;
michael@0 36860 }
michael@0 36861
michael@0 36862 var contentEncoding =
michael@0 36863 fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity';
michael@0 36864 if (contentEncoding !== 'identity') {
michael@0 36865 return;
michael@0 36866 }
michael@0 36867
michael@0 36868 var length = fullRequestXhr.getResponseHeader('Content-Length');
michael@0 36869 length = parseInt(length, 10);
michael@0 36870 if (!isInt(length)) {
michael@0 36871 return;
michael@0 36872 }
michael@0 36873 source.length = length;
michael@0 36874 if (length <= 2 * RANGE_CHUNK_SIZE) {
michael@0 36875 // The file size is smaller than the size of two chunks, so it does
michael@0 36876 // not make any sense to abort the request and retry with a range
michael@0 36877 // request.
michael@0 36878 return;
michael@0 36879 }
michael@0 36880
michael@0 36881 // NOTE: by cancelling the full request, and then issuing range
michael@0 36882 // requests, there will be an issue for sites where you can only
michael@0 36883 // request the pdf once. However, if this is the case, then the
michael@0 36884 // server should not be returning that it can support range requests.
michael@0 36885 networkManager.abortRequest(fullRequestXhrId);
michael@0 36886
michael@0 36887 try {
michael@0 36888 pdfManager = new NetworkPdfManager(source, handler);
michael@0 36889 pdfManagerPromise.resolve(pdfManager);
michael@0 36890 } catch (ex) {
michael@0 36891 pdfManagerPromise.reject(ex);
michael@0 36892 }
michael@0 36893 },
michael@0 36894
michael@0 36895 onDone: function onDone(args) {
michael@0 36896 // the data is array, instantiating directly from it
michael@0 36897 try {
michael@0 36898 pdfManager = new LocalPdfManager(args.chunk, source.password);
michael@0 36899 pdfManagerPromise.resolve();
michael@0 36900 } catch (ex) {
michael@0 36901 pdfManagerPromise.reject(ex);
michael@0 36902 }
michael@0 36903 },
michael@0 36904
michael@0 36905 onError: function onError(status) {
michael@0 36906 if (status == 404) {
michael@0 36907 var exception = new MissingPDFException('Missing PDF "' +
michael@0 36908 source.url + '".');
michael@0 36909 handler.send('MissingPDF', { exception: exception });
michael@0 36910 } else {
michael@0 36911 handler.send('DocError', 'Unexpected server response (' +
michael@0 36912 status + ') while retrieving PDF "' +
michael@0 36913 source.url + '".');
michael@0 36914 }
michael@0 36915 },
michael@0 36916
michael@0 36917 onProgress: function onProgress(evt) {
michael@0 36918 handler.send('DocProgress', {
michael@0 36919 loaded: evt.loaded,
michael@0 36920 total: evt.lengthComputable ? evt.total : source.length
michael@0 36921 });
michael@0 36922 }
michael@0 36923 });
michael@0 36924
michael@0 36925 return pdfManagerPromise;
michael@0 36926 }
michael@0 36927
michael@0 36928 handler.on('test', function wphSetupTest(data) {
michael@0 36929 // check if Uint8Array can be sent to worker
michael@0 36930 if (!(data instanceof Uint8Array)) {
michael@0 36931 handler.send('test', false);
michael@0 36932 return;
michael@0 36933 }
michael@0 36934 // making sure postMessage transfers are working
michael@0 36935 var supportTransfers = data[0] === 255;
michael@0 36936 handler.postMessageTransfers = supportTransfers;
michael@0 36937 // check if the response property is supported by xhr
michael@0 36938 var xhr = new XMLHttpRequest();
michael@0 36939 var responseExists = 'response' in xhr;
michael@0 36940 // check if the property is actually implemented
michael@0 36941 try {
michael@0 36942 var dummy = xhr.responseType;
michael@0 36943 } catch (e) {
michael@0 36944 responseExists = false;
michael@0 36945 }
michael@0 36946 if (!responseExists) {
michael@0 36947 handler.send('test', false);
michael@0 36948 return;
michael@0 36949 }
michael@0 36950 handler.send('test', {
michael@0 36951 supportTypedArray: true,
michael@0 36952 supportTransfers: supportTransfers
michael@0 36953 });
michael@0 36954 });
michael@0 36955
michael@0 36956 handler.on('GetDocRequest', function wphSetupDoc(data) {
michael@0 36957
michael@0 36958 var onSuccess = function(doc) {
michael@0 36959 handler.send('GetDoc', { pdfInfo: doc });
michael@0 36960 };
michael@0 36961
michael@0 36962 var onFailure = function(e) {
michael@0 36963 if (e instanceof PasswordException) {
michael@0 36964 if (e.code === PasswordResponses.NEED_PASSWORD) {
michael@0 36965 handler.send('NeedPassword', {
michael@0 36966 exception: e
michael@0 36967 });
michael@0 36968 } else if (e.code === PasswordResponses.INCORRECT_PASSWORD) {
michael@0 36969 handler.send('IncorrectPassword', {
michael@0 36970 exception: e
michael@0 36971 });
michael@0 36972 }
michael@0 36973 } else if (e instanceof InvalidPDFException) {
michael@0 36974 handler.send('InvalidPDF', {
michael@0 36975 exception: e
michael@0 36976 });
michael@0 36977 } else if (e instanceof MissingPDFException) {
michael@0 36978 handler.send('MissingPDF', {
michael@0 36979 exception: e
michael@0 36980 });
michael@0 36981 } else {
michael@0 36982 handler.send('UnknownError', {
michael@0 36983 exception: new UnknownErrorException(e.message, e.toString())
michael@0 36984 });
michael@0 36985 }
michael@0 36986 };
michael@0 36987
michael@0 36988 PDFJS.maxImageSize = data.maxImageSize === undefined ?
michael@0 36989 -1 : data.maxImageSize;
michael@0 36990 PDFJS.disableFontFace = data.disableFontFace;
michael@0 36991 PDFJS.disableCreateObjectURL = data.disableCreateObjectURL;
michael@0 36992 PDFJS.verbosity = data.verbosity;
michael@0 36993 PDFJS.cMapUrl = data.cMapUrl === undefined ?
michael@0 36994 null : data.cMapUrl;
michael@0 36995 PDFJS.cMapPacked = data.cMapPacked === true;
michael@0 36996
michael@0 36997 getPdfManager(data).then(function () {
michael@0 36998 pdfManager.onLoadedStream().then(function(stream) {
michael@0 36999 handler.send('DataLoaded', { length: stream.bytes.byteLength });
michael@0 37000 });
michael@0 37001 }).then(function pdfManagerReady() {
michael@0 37002 loadDocument(false).then(onSuccess, function loadFailure(ex) {
michael@0 37003 // Try again with recoveryMode == true
michael@0 37004 if (!(ex instanceof XRefParseException)) {
michael@0 37005 if (ex instanceof PasswordException) {
michael@0 37006 // after password exception prepare to receive a new password
michael@0 37007 // to repeat loading
michael@0 37008 pdfManager.passwordChangedPromise = new LegacyPromise();
michael@0 37009 pdfManager.passwordChangedPromise.then(pdfManagerReady);
michael@0 37010 }
michael@0 37011
michael@0 37012 onFailure(ex);
michael@0 37013 return;
michael@0 37014 }
michael@0 37015
michael@0 37016 pdfManager.requestLoadedStream();
michael@0 37017 pdfManager.onLoadedStream().then(function() {
michael@0 37018 loadDocument(true).then(onSuccess, onFailure);
michael@0 37019 });
michael@0 37020 }, onFailure);
michael@0 37021 }, onFailure);
michael@0 37022 });
michael@0 37023
michael@0 37024 handler.on('GetPageRequest', function wphSetupGetPage(data) {
michael@0 37025 var pageIndex = data.pageIndex;
michael@0 37026 pdfManager.getPage(pageIndex).then(function(page) {
michael@0 37027 var rotatePromise = pdfManager.ensure(page, 'rotate');
michael@0 37028 var refPromise = pdfManager.ensure(page, 'ref');
michael@0 37029 var viewPromise = pdfManager.ensure(page, 'view');
michael@0 37030
michael@0 37031 Promise.all([rotatePromise, refPromise, viewPromise]).then(
michael@0 37032 function(results) {
michael@0 37033 var page = {
michael@0 37034 pageIndex: data.pageIndex,
michael@0 37035 rotate: results[0],
michael@0 37036 ref: results[1],
michael@0 37037 view: results[2]
michael@0 37038 };
michael@0 37039
michael@0 37040 handler.send('GetPage', { pageInfo: page });
michael@0 37041 });
michael@0 37042 });
michael@0 37043 });
michael@0 37044
michael@0 37045 handler.on('GetPageIndex', function wphSetupGetPageIndex(data, deferred) {
michael@0 37046 var ref = new Ref(data.ref.num, data.ref.gen);
michael@0 37047 var catalog = pdfManager.pdfDocument.catalog;
michael@0 37048 catalog.getPageIndex(ref).then(function (pageIndex) {
michael@0 37049 deferred.resolve(pageIndex);
michael@0 37050 }, deferred.reject);
michael@0 37051 });
michael@0 37052
michael@0 37053 handler.on('GetDestinations',
michael@0 37054 function wphSetupGetDestinations(data, deferred) {
michael@0 37055 pdfManager.ensureCatalog('destinations').then(function(destinations) {
michael@0 37056 deferred.resolve(destinations);
michael@0 37057 });
michael@0 37058 }
michael@0 37059 );
michael@0 37060
michael@0 37061 handler.on('GetAttachments',
michael@0 37062 function wphSetupGetAttachments(data, deferred) {
michael@0 37063 pdfManager.ensureCatalog('attachments').then(function(attachments) {
michael@0 37064 deferred.resolve(attachments);
michael@0 37065 }, deferred.reject);
michael@0 37066 }
michael@0 37067 );
michael@0 37068
michael@0 37069 handler.on('GetData', function wphSetupGetData(data, deferred) {
michael@0 37070 pdfManager.requestLoadedStream();
michael@0 37071 pdfManager.onLoadedStream().then(function(stream) {
michael@0 37072 deferred.resolve(stream.bytes);
michael@0 37073 });
michael@0 37074 });
michael@0 37075
michael@0 37076 handler.on('UpdatePassword', function wphSetupUpdatePassword(data) {
michael@0 37077 pdfManager.updatePassword(data);
michael@0 37078 });
michael@0 37079
michael@0 37080 handler.on('GetAnnotationsRequest', function wphSetupGetAnnotations(data) {
michael@0 37081 pdfManager.getPage(data.pageIndex).then(function(page) {
michael@0 37082 pdfManager.ensure(page, 'getAnnotationsData', []).then(
michael@0 37083 function(annotationsData) {
michael@0 37084 handler.send('GetAnnotations', {
michael@0 37085 pageIndex: data.pageIndex,
michael@0 37086 annotations: annotationsData
michael@0 37087 });
michael@0 37088 }
michael@0 37089 );
michael@0 37090 });
michael@0 37091 });
michael@0 37092
michael@0 37093 handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
michael@0 37094 pdfManager.getPage(data.pageIndex).then(function(page) {
michael@0 37095
michael@0 37096 var pageNum = data.pageIndex + 1;
michael@0 37097 var start = Date.now();
michael@0 37098 // Pre compile the pdf page and fetch the fonts/images.
michael@0 37099 page.getOperatorList(handler, data.intent).then(function(operatorList) {
michael@0 37100
michael@0 37101 info('page=' + pageNum + ' - getOperatorList: time=' +
michael@0 37102 (Date.now() - start) + 'ms, len=' + operatorList.fnArray.length);
michael@0 37103
michael@0 37104 }, function(e) {
michael@0 37105
michael@0 37106 var minimumStackMessage =
michael@0 37107 'worker.js: while trying to getPage() and getOperatorList()';
michael@0 37108
michael@0 37109 var wrappedException;
michael@0 37110
michael@0 37111 // Turn the error into an obj that can be serialized
michael@0 37112 if (typeof e === 'string') {
michael@0 37113 wrappedException = {
michael@0 37114 message: e,
michael@0 37115 stack: minimumStackMessage
michael@0 37116 };
michael@0 37117 } else if (typeof e === 'object') {
michael@0 37118 wrappedException = {
michael@0 37119 message: e.message || e.toString(),
michael@0 37120 stack: e.stack || minimumStackMessage
michael@0 37121 };
michael@0 37122 } else {
michael@0 37123 wrappedException = {
michael@0 37124 message: 'Unknown exception type: ' + (typeof e),
michael@0 37125 stack: minimumStackMessage
michael@0 37126 };
michael@0 37127 }
michael@0 37128
michael@0 37129 handler.send('PageError', {
michael@0 37130 pageNum: pageNum,
michael@0 37131 error: wrappedException,
michael@0 37132 intent: data.intent
michael@0 37133 });
michael@0 37134 });
michael@0 37135 });
michael@0 37136 }, this);
michael@0 37137
michael@0 37138 handler.on('GetTextContent', function wphExtractText(data, deferred) {
michael@0 37139 pdfManager.getPage(data.pageIndex).then(function(page) {
michael@0 37140 var pageNum = data.pageIndex + 1;
michael@0 37141 var start = Date.now();
michael@0 37142 page.extractTextContent().then(function(textContent) {
michael@0 37143 deferred.resolve(textContent);
michael@0 37144 info('text indexing: page=' + pageNum + ' - time=' +
michael@0 37145 (Date.now() - start) + 'ms');
michael@0 37146 }, function (e) {
michael@0 37147 // Skip errored pages
michael@0 37148 deferred.reject(e);
michael@0 37149 });
michael@0 37150 });
michael@0 37151 });
michael@0 37152
michael@0 37153 handler.on('Cleanup', function wphCleanup(data, deferred) {
michael@0 37154 pdfManager.cleanup();
michael@0 37155 deferred.resolve(true);
michael@0 37156 });
michael@0 37157
michael@0 37158 handler.on('Terminate', function wphTerminate(data, deferred) {
michael@0 37159 pdfManager.terminate();
michael@0 37160 deferred.resolve();
michael@0 37161 });
michael@0 37162 }
michael@0 37163 };
michael@0 37164
michael@0 37165 var consoleTimer = {};
michael@0 37166
michael@0 37167 var workerConsole = {
michael@0 37168 log: function log() {
michael@0 37169 var args = Array.prototype.slice.call(arguments);
michael@0 37170 globalScope.postMessage({
michael@0 37171 action: 'console_log',
michael@0 37172 data: args
michael@0 37173 });
michael@0 37174 },
michael@0 37175
michael@0 37176 error: function error() {
michael@0 37177 var args = Array.prototype.slice.call(arguments);
michael@0 37178 globalScope.postMessage({
michael@0 37179 action: 'console_error',
michael@0 37180 data: args
michael@0 37181 });
michael@0 37182 throw 'pdf.js execution error';
michael@0 37183 },
michael@0 37184
michael@0 37185 time: function time(name) {
michael@0 37186 consoleTimer[name] = Date.now();
michael@0 37187 },
michael@0 37188
michael@0 37189 timeEnd: function timeEnd(name) {
michael@0 37190 var time = consoleTimer[name];
michael@0 37191 if (!time) {
michael@0 37192 error('Unknown timer name ' + name);
michael@0 37193 }
michael@0 37194 this.log('Timer:', name, Date.now() - time);
michael@0 37195 }
michael@0 37196 };
michael@0 37197
michael@0 37198
michael@0 37199 // Worker thread?
michael@0 37200 if (typeof window === 'undefined') {
michael@0 37201 if (!('console' in globalScope)) {
michael@0 37202 globalScope.console = workerConsole;
michael@0 37203 }
michael@0 37204
michael@0 37205 // Listen for unsupported features so we can pass them on to the main thread.
michael@0 37206 PDFJS.UnsupportedManager.listen(function (msg) {
michael@0 37207 globalScope.postMessage({
michael@0 37208 action: '_unsupported_feature',
michael@0 37209 data: msg
michael@0 37210 });
michael@0 37211 });
michael@0 37212
michael@0 37213 var handler = new MessageHandler('worker_processor', this);
michael@0 37214 WorkerMessageHandler.setup(handler);
michael@0 37215 }
michael@0 37216
michael@0 37217
michael@0 37218 /* This class implements the QM Coder decoding as defined in
michael@0 37219 * JPEG 2000 Part I Final Committee Draft Version 1.0
michael@0 37220 * Annex C.3 Arithmetic decoding procedure
michael@0 37221 * available at http://www.jpeg.org/public/fcd15444-1.pdf
michael@0 37222 *
michael@0 37223 * The arithmetic decoder is used in conjunction with context models to decode
michael@0 37224 * JPEG2000 and JBIG2 streams.
michael@0 37225 */
michael@0 37226 var ArithmeticDecoder = (function ArithmeticDecoderClosure() {
michael@0 37227 // Table C-2
michael@0 37228 var QeTable = [
michael@0 37229 {qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1},
michael@0 37230 {qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0},
michael@0 37231 {qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0},
michael@0 37232 {qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0},
michael@0 37233 {qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0},
michael@0 37234 {qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0},
michael@0 37235 {qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1},
michael@0 37236 {qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0},
michael@0 37237 {qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0},
michael@0 37238 {qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0},
michael@0 37239 {qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0},
michael@0 37240 {qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0},
michael@0 37241 {qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0},
michael@0 37242 {qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0},
michael@0 37243 {qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1},
michael@0 37244 {qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0},
michael@0 37245 {qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0},
michael@0 37246 {qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0},
michael@0 37247 {qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0},
michael@0 37248 {qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0},
michael@0 37249 {qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0},
michael@0 37250 {qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0},
michael@0 37251 {qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0},
michael@0 37252 {qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0},
michael@0 37253 {qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0},
michael@0 37254 {qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0},
michael@0 37255 {qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0},
michael@0 37256 {qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0},
michael@0 37257 {qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0},
michael@0 37258 {qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0},
michael@0 37259 {qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0},
michael@0 37260 {qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0},
michael@0 37261 {qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0},
michael@0 37262 {qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0},
michael@0 37263 {qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0},
michael@0 37264 {qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0},
michael@0 37265 {qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0},
michael@0 37266 {qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0},
michael@0 37267 {qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0},
michael@0 37268 {qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0},
michael@0 37269 {qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0},
michael@0 37270 {qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0},
michael@0 37271 {qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0},
michael@0 37272 {qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0},
michael@0 37273 {qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0},
michael@0 37274 {qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0},
michael@0 37275 {qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0}
michael@0 37276 ];
michael@0 37277
michael@0 37278 // C.3.5 Initialisation of the decoder (INITDEC)
michael@0 37279 function ArithmeticDecoder(data, start, end) {
michael@0 37280 this.data = data;
michael@0 37281 this.bp = start;
michael@0 37282 this.dataEnd = end;
michael@0 37283
michael@0 37284 this.chigh = data[start];
michael@0 37285 this.clow = 0;
michael@0 37286
michael@0 37287 this.byteIn();
michael@0 37288
michael@0 37289 this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F);
michael@0 37290 this.clow = (this.clow << 7) & 0xFFFF;
michael@0 37291 this.ct -= 7;
michael@0 37292 this.a = 0x8000;
michael@0 37293 }
michael@0 37294
michael@0 37295 ArithmeticDecoder.prototype = {
michael@0 37296 // C.3.4 Compressed data input (BYTEIN)
michael@0 37297 byteIn: function ArithmeticDecoder_byteIn() {
michael@0 37298 var data = this.data;
michael@0 37299 var bp = this.bp;
michael@0 37300 if (data[bp] == 0xFF) {
michael@0 37301 var b1 = data[bp + 1];
michael@0 37302 if (b1 > 0x8F) {
michael@0 37303 this.clow += 0xFF00;
michael@0 37304 this.ct = 8;
michael@0 37305 } else {
michael@0 37306 bp++;
michael@0 37307 this.clow += (data[bp] << 9);
michael@0 37308 this.ct = 7;
michael@0 37309 this.bp = bp;
michael@0 37310 }
michael@0 37311 } else {
michael@0 37312 bp++;
michael@0 37313 this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00;
michael@0 37314 this.ct = 8;
michael@0 37315 this.bp = bp;
michael@0 37316 }
michael@0 37317 if (this.clow > 0xFFFF) {
michael@0 37318 this.chigh += (this.clow >> 16);
michael@0 37319 this.clow &= 0xFFFF;
michael@0 37320 }
michael@0 37321 },
michael@0 37322 // C.3.2 Decoding a decision (DECODE)
michael@0 37323 readBit: function ArithmeticDecoder_readBit(contexts, pos) {
michael@0 37324 // contexts are packed into 1 byte:
michael@0 37325 // highest 7 bits carry cx.index, lowest bit carries cx.mps
michael@0 37326 var cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1;
michael@0 37327 var qeTableIcx = QeTable[cx_index];
michael@0 37328 var qeIcx = qeTableIcx.qe;
michael@0 37329 var d;
michael@0 37330 var a = this.a - qeIcx;
michael@0 37331
michael@0 37332 if (this.chigh < qeIcx) {
michael@0 37333 // exchangeLps
michael@0 37334 if (a < qeIcx) {
michael@0 37335 a = qeIcx;
michael@0 37336 d = cx_mps;
michael@0 37337 cx_index = qeTableIcx.nmps;
michael@0 37338 } else {
michael@0 37339 a = qeIcx;
michael@0 37340 d = 1 ^ cx_mps;
michael@0 37341 if (qeTableIcx.switchFlag === 1) {
michael@0 37342 cx_mps = d;
michael@0 37343 }
michael@0 37344 cx_index = qeTableIcx.nlps;
michael@0 37345 }
michael@0 37346 } else {
michael@0 37347 this.chigh -= qeIcx;
michael@0 37348 if ((a & 0x8000) !== 0) {
michael@0 37349 this.a = a;
michael@0 37350 return cx_mps;
michael@0 37351 }
michael@0 37352 // exchangeMps
michael@0 37353 if (a < qeIcx) {
michael@0 37354 d = 1 ^ cx_mps;
michael@0 37355 if (qeTableIcx.switchFlag === 1) {
michael@0 37356 cx_mps = d;
michael@0 37357 }
michael@0 37358 cx_index = qeTableIcx.nlps;
michael@0 37359 } else {
michael@0 37360 d = cx_mps;
michael@0 37361 cx_index = qeTableIcx.nmps;
michael@0 37362 }
michael@0 37363 }
michael@0 37364 // C.3.3 renormD;
michael@0 37365 do {
michael@0 37366 if (this.ct === 0) {
michael@0 37367 this.byteIn();
michael@0 37368 }
michael@0 37369
michael@0 37370 a <<= 1;
michael@0 37371 this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1);
michael@0 37372 this.clow = (this.clow << 1) & 0xFFFF;
michael@0 37373 this.ct--;
michael@0 37374 } while ((a & 0x8000) === 0);
michael@0 37375 this.a = a;
michael@0 37376
michael@0 37377 contexts[pos] = cx_index << 1 | cx_mps;
michael@0 37378 return d;
michael@0 37379 }
michael@0 37380 };
michael@0 37381
michael@0 37382 return ArithmeticDecoder;
michael@0 37383 })();
michael@0 37384
michael@0 37385
michael@0 37386 var JpxImage = (function JpxImageClosure() {
michael@0 37387 // Table E.1
michael@0 37388 var SubbandsGainLog2 = {
michael@0 37389 'LL': 0,
michael@0 37390 'LH': 1,
michael@0 37391 'HL': 1,
michael@0 37392 'HH': 2
michael@0 37393 };
michael@0 37394 function JpxImage() {
michael@0 37395 this.failOnCorruptedImage = false;
michael@0 37396 }
michael@0 37397 JpxImage.prototype = {
michael@0 37398 load: function JpxImage_load(url) {
michael@0 37399 var xhr = new XMLHttpRequest();
michael@0 37400 xhr.open('GET', url, true);
michael@0 37401 xhr.responseType = 'arraybuffer';
michael@0 37402 xhr.onload = (function() {
michael@0 37403 // TODO catch parse error
michael@0 37404 var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
michael@0 37405 this.parse(data);
michael@0 37406 if (this.onload) {
michael@0 37407 this.onload();
michael@0 37408 }
michael@0 37409 }).bind(this);
michael@0 37410 xhr.send(null);
michael@0 37411 },
michael@0 37412 parse: function JpxImage_parse(data) {
michael@0 37413
michael@0 37414 var head = readUint16(data, 0);
michael@0 37415 // No box header, immediate start of codestream (SOC)
michael@0 37416 if (head === 0xFF4F) {
michael@0 37417 this.parseCodestream(data, 0, data.length);
michael@0 37418 return;
michael@0 37419 }
michael@0 37420
michael@0 37421 var position = 0, length = data.length;
michael@0 37422 while (position < length) {
michael@0 37423 var headerSize = 8;
michael@0 37424 var lbox = readUint32(data, position);
michael@0 37425 var tbox = readUint32(data, position + 4);
michael@0 37426 position += headerSize;
michael@0 37427 if (lbox === 1) {
michael@0 37428 // XLBox: read UInt64 according to spec.
michael@0 37429 // JavaScript's int precision of 53 bit should be sufficient here.
michael@0 37430 lbox = readUint32(data, position) * 4294967296 +
michael@0 37431 readUint32(data, position + 4);
michael@0 37432 position += 8;
michael@0 37433 headerSize += 8;
michael@0 37434 }
michael@0 37435 if (lbox === 0) {
michael@0 37436 lbox = length - position + headerSize;
michael@0 37437 }
michael@0 37438 if (lbox < headerSize) {
michael@0 37439 error('JPX error: Invalid box field size');
michael@0 37440 }
michael@0 37441 var dataLength = lbox - headerSize;
michael@0 37442 var jumpDataLength = true;
michael@0 37443 switch (tbox) {
michael@0 37444 case 0x6A501A1A: // 'jP\032\032'
michael@0 37445 // TODO
michael@0 37446 break;
michael@0 37447 case 0x6A703268: // 'jp2h'
michael@0 37448 jumpDataLength = false; // parsing child boxes
michael@0 37449 break;
michael@0 37450 case 0x636F6C72: // 'colr'
michael@0 37451 // TODO
michael@0 37452 break;
michael@0 37453 case 0x6A703263: // 'jp2c'
michael@0 37454 this.parseCodestream(data, position, position + dataLength);
michael@0 37455 break;
michael@0 37456 }
michael@0 37457 if (jumpDataLength) {
michael@0 37458 position += dataLength;
michael@0 37459 }
michael@0 37460 }
michael@0 37461 },
michael@0 37462 parseImageProperties: function JpxImage_parseImageProperties(stream) {
michael@0 37463 try {
michael@0 37464 var newByte = stream.getByte();
michael@0 37465 while (newByte >= 0) {
michael@0 37466 var oldByte = newByte;
michael@0 37467 newByte = stream.getByte();
michael@0 37468 var code = (oldByte << 8) | newByte;
michael@0 37469 // Image and tile size (SIZ)
michael@0 37470 if (code == 0xFF51) {
michael@0 37471 stream.skip(4);
michael@0 37472 var Xsiz = stream.getInt32() >>> 0; // Byte 4
michael@0 37473 var Ysiz = stream.getInt32() >>> 0; // Byte 8
michael@0 37474 var XOsiz = stream.getInt32() >>> 0; // Byte 12
michael@0 37475 var YOsiz = stream.getInt32() >>> 0; // Byte 16
michael@0 37476 stream.skip(16);
michael@0 37477 var Csiz = stream.getUint16(); // Byte 36
michael@0 37478 this.width = Xsiz - XOsiz;
michael@0 37479 this.height = Ysiz - YOsiz;
michael@0 37480 this.componentsCount = Csiz;
michael@0 37481 // Results are always returned as Uint8Arrays
michael@0 37482 this.bitsPerComponent = 8;
michael@0 37483 return;
michael@0 37484 }
michael@0 37485 }
michael@0 37486 throw 'No size marker found in JPX stream';
michael@0 37487 } catch (e) {
michael@0 37488 if (this.failOnCorruptedImage) {
michael@0 37489 error('JPX error: ' + e);
michael@0 37490 } else {
michael@0 37491 warn('JPX error: ' + e + '. Trying to recover');
michael@0 37492 }
michael@0 37493 }
michael@0 37494 },
michael@0 37495 parseCodestream: function JpxImage_parseCodestream(data, start, end) {
michael@0 37496 var context = {};
michael@0 37497 try {
michael@0 37498 var position = start;
michael@0 37499 while (position + 1 < end) {
michael@0 37500 var code = readUint16(data, position);
michael@0 37501 position += 2;
michael@0 37502
michael@0 37503 var length = 0, j, sqcd, spqcds, spqcdSize, scalarExpounded, tile;
michael@0 37504 switch (code) {
michael@0 37505 case 0xFF4F: // Start of codestream (SOC)
michael@0 37506 context.mainHeader = true;
michael@0 37507 break;
michael@0 37508 case 0xFFD9: // End of codestream (EOC)
michael@0 37509 break;
michael@0 37510 case 0xFF51: // Image and tile size (SIZ)
michael@0 37511 length = readUint16(data, position);
michael@0 37512 var siz = {};
michael@0 37513 siz.Xsiz = readUint32(data, position + 4);
michael@0 37514 siz.Ysiz = readUint32(data, position + 8);
michael@0 37515 siz.XOsiz = readUint32(data, position + 12);
michael@0 37516 siz.YOsiz = readUint32(data, position + 16);
michael@0 37517 siz.XTsiz = readUint32(data, position + 20);
michael@0 37518 siz.YTsiz = readUint32(data, position + 24);
michael@0 37519 siz.XTOsiz = readUint32(data, position + 28);
michael@0 37520 siz.YTOsiz = readUint32(data, position + 32);
michael@0 37521 var componentsCount = readUint16(data, position + 36);
michael@0 37522 siz.Csiz = componentsCount;
michael@0 37523 var components = [];
michael@0 37524 j = position + 38;
michael@0 37525 for (var i = 0; i < componentsCount; i++) {
michael@0 37526 var component = {
michael@0 37527 precision: (data[j] & 0x7F) + 1,
michael@0 37528 isSigned: !!(data[j] & 0x80),
michael@0 37529 XRsiz: data[j + 1],
michael@0 37530 YRsiz: data[j + 1]
michael@0 37531 };
michael@0 37532 calculateComponentDimensions(component, siz);
michael@0 37533 components.push(component);
michael@0 37534 }
michael@0 37535 context.SIZ = siz;
michael@0 37536 context.components = components;
michael@0 37537 calculateTileGrids(context, components);
michael@0 37538 context.QCC = [];
michael@0 37539 context.COC = [];
michael@0 37540 break;
michael@0 37541 case 0xFF5C: // Quantization default (QCD)
michael@0 37542 length = readUint16(data, position);
michael@0 37543 var qcd = {};
michael@0 37544 j = position + 2;
michael@0 37545 sqcd = data[j++];
michael@0 37546 switch (sqcd & 0x1F) {
michael@0 37547 case 0:
michael@0 37548 spqcdSize = 8;
michael@0 37549 scalarExpounded = true;
michael@0 37550 break;
michael@0 37551 case 1:
michael@0 37552 spqcdSize = 16;
michael@0 37553 scalarExpounded = false;
michael@0 37554 break;
michael@0 37555 case 2:
michael@0 37556 spqcdSize = 16;
michael@0 37557 scalarExpounded = true;
michael@0 37558 break;
michael@0 37559 default:
michael@0 37560 throw 'Invalid SQcd value ' + sqcd;
michael@0 37561 }
michael@0 37562 qcd.noQuantization = (spqcdSize == 8);
michael@0 37563 qcd.scalarExpounded = scalarExpounded;
michael@0 37564 qcd.guardBits = sqcd >> 5;
michael@0 37565 spqcds = [];
michael@0 37566 while (j < length + position) {
michael@0 37567 var spqcd = {};
michael@0 37568 if (spqcdSize == 8) {
michael@0 37569 spqcd.epsilon = data[j++] >> 3;
michael@0 37570 spqcd.mu = 0;
michael@0 37571 } else {
michael@0 37572 spqcd.epsilon = data[j] >> 3;
michael@0 37573 spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
michael@0 37574 j += 2;
michael@0 37575 }
michael@0 37576 spqcds.push(spqcd);
michael@0 37577 }
michael@0 37578 qcd.SPqcds = spqcds;
michael@0 37579 if (context.mainHeader) {
michael@0 37580 context.QCD = qcd;
michael@0 37581 } else {
michael@0 37582 context.currentTile.QCD = qcd;
michael@0 37583 context.currentTile.QCC = [];
michael@0 37584 }
michael@0 37585 break;
michael@0 37586 case 0xFF5D: // Quantization component (QCC)
michael@0 37587 length = readUint16(data, position);
michael@0 37588 var qcc = {};
michael@0 37589 j = position + 2;
michael@0 37590 var cqcc;
michael@0 37591 if (context.SIZ.Csiz < 257) {
michael@0 37592 cqcc = data[j++];
michael@0 37593 } else {
michael@0 37594 cqcc = readUint16(data, j);
michael@0 37595 j += 2;
michael@0 37596 }
michael@0 37597 sqcd = data[j++];
michael@0 37598 switch (sqcd & 0x1F) {
michael@0 37599 case 0:
michael@0 37600 spqcdSize = 8;
michael@0 37601 scalarExpounded = true;
michael@0 37602 break;
michael@0 37603 case 1:
michael@0 37604 spqcdSize = 16;
michael@0 37605 scalarExpounded = false;
michael@0 37606 break;
michael@0 37607 case 2:
michael@0 37608 spqcdSize = 16;
michael@0 37609 scalarExpounded = true;
michael@0 37610 break;
michael@0 37611 default:
michael@0 37612 throw 'Invalid SQcd value ' + sqcd;
michael@0 37613 }
michael@0 37614 qcc.noQuantization = (spqcdSize == 8);
michael@0 37615 qcc.scalarExpounded = scalarExpounded;
michael@0 37616 qcc.guardBits = sqcd >> 5;
michael@0 37617 spqcds = [];
michael@0 37618 while (j < (length + position)) {
michael@0 37619 spqcd = {};
michael@0 37620 if (spqcdSize == 8) {
michael@0 37621 spqcd.epsilon = data[j++] >> 3;
michael@0 37622 spqcd.mu = 0;
michael@0 37623 } else {
michael@0 37624 spqcd.epsilon = data[j] >> 3;
michael@0 37625 spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
michael@0 37626 j += 2;
michael@0 37627 }
michael@0 37628 spqcds.push(spqcd);
michael@0 37629 }
michael@0 37630 qcc.SPqcds = spqcds;
michael@0 37631 if (context.mainHeader) {
michael@0 37632 context.QCC[cqcc] = qcc;
michael@0 37633 } else {
michael@0 37634 context.currentTile.QCC[cqcc] = qcc;
michael@0 37635 }
michael@0 37636 break;
michael@0 37637 case 0xFF52: // Coding style default (COD)
michael@0 37638 length = readUint16(data, position);
michael@0 37639 var cod = {};
michael@0 37640 j = position + 2;
michael@0 37641 var scod = data[j++];
michael@0 37642 cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
michael@0 37643 cod.sopMarkerUsed = !!(scod & 2);
michael@0 37644 cod.ephMarkerUsed = !!(scod & 4);
michael@0 37645 cod.progressionOrder = data[j++];
michael@0 37646 cod.layersCount = readUint16(data, j);
michael@0 37647 j += 2;
michael@0 37648 cod.multipleComponentTransform = data[j++];
michael@0 37649
michael@0 37650 cod.decompositionLevelsCount = data[j++];
michael@0 37651 cod.xcb = (data[j++] & 0xF) + 2;
michael@0 37652 cod.ycb = (data[j++] & 0xF) + 2;
michael@0 37653 var blockStyle = data[j++];
michael@0 37654 cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
michael@0 37655 cod.resetContextProbabilities = !!(blockStyle & 2);
michael@0 37656 cod.terminationOnEachCodingPass = !!(blockStyle & 4);
michael@0 37657 cod.verticalyStripe = !!(blockStyle & 8);
michael@0 37658 cod.predictableTermination = !!(blockStyle & 16);
michael@0 37659 cod.segmentationSymbolUsed = !!(blockStyle & 32);
michael@0 37660 cod.reversibleTransformation = data[j++];
michael@0 37661 if (cod.entropyCoderWithCustomPrecincts) {
michael@0 37662 var precinctsSizes = [];
michael@0 37663 while (j < length + position) {
michael@0 37664 var precinctsSize = data[j++];
michael@0 37665 precinctsSizes.push({
michael@0 37666 PPx: precinctsSize & 0xF,
michael@0 37667 PPy: precinctsSize >> 4
michael@0 37668 });
michael@0 37669 }
michael@0 37670 cod.precinctsSizes = precinctsSizes;
michael@0 37671 }
michael@0 37672
michael@0 37673 if (cod.sopMarkerUsed || cod.ephMarkerUsed ||
michael@0 37674 cod.selectiveArithmeticCodingBypass ||
michael@0 37675 cod.resetContextProbabilities ||
michael@0 37676 cod.terminationOnEachCodingPass ||
michael@0 37677 cod.verticalyStripe || cod.predictableTermination) {
michael@0 37678 throw 'Unsupported COD options: ' +
michael@0 37679 globalScope.JSON.stringify(cod);
michael@0 37680 }
michael@0 37681
michael@0 37682 if (context.mainHeader) {
michael@0 37683 context.COD = cod;
michael@0 37684 } else {
michael@0 37685 context.currentTile.COD = cod;
michael@0 37686 context.currentTile.COC = [];
michael@0 37687 }
michael@0 37688 break;
michael@0 37689 case 0xFF90: // Start of tile-part (SOT)
michael@0 37690 length = readUint16(data, position);
michael@0 37691 tile = {};
michael@0 37692 tile.index = readUint16(data, position + 2);
michael@0 37693 tile.length = readUint32(data, position + 4);
michael@0 37694 tile.dataEnd = tile.length + position - 2;
michael@0 37695 tile.partIndex = data[position + 8];
michael@0 37696 tile.partsCount = data[position + 9];
michael@0 37697
michael@0 37698 context.mainHeader = false;
michael@0 37699 if (tile.partIndex === 0) {
michael@0 37700 // reset component specific settings
michael@0 37701 tile.COD = context.COD;
michael@0 37702 tile.COC = context.COC.slice(0); // clone of the global COC
michael@0 37703 tile.QCD = context.QCD;
michael@0 37704 tile.QCC = context.QCC.slice(0); // clone of the global COC
michael@0 37705 }
michael@0 37706 context.currentTile = tile;
michael@0 37707 break;
michael@0 37708 case 0xFF93: // Start of data (SOD)
michael@0 37709 tile = context.currentTile;
michael@0 37710 if (tile.partIndex === 0) {
michael@0 37711 initializeTile(context, tile.index);
michael@0 37712 buildPackets(context);
michael@0 37713 }
michael@0 37714
michael@0 37715 // moving to the end of the data
michael@0 37716 length = tile.dataEnd - position;
michael@0 37717 parseTilePackets(context, data, position, length);
michael@0 37718 break;
michael@0 37719 case 0xFF64: // Comment (COM)
michael@0 37720 length = readUint16(data, position);
michael@0 37721 // skipping content
michael@0 37722 break;
michael@0 37723 case 0xFF53: // Coding style component (COC)
michael@0 37724 throw 'Codestream code 0xFF53 (COC) is not implemented';
michael@0 37725 default:
michael@0 37726 throw 'Unknown codestream code: ' + code.toString(16);
michael@0 37727 }
michael@0 37728 position += length;
michael@0 37729 }
michael@0 37730 } catch (e) {
michael@0 37731 if (this.failOnCorruptedImage) {
michael@0 37732 error('JPX error: ' + e);
michael@0 37733 } else {
michael@0 37734 warn('JPX error: ' + e + '. Trying to recover');
michael@0 37735 }
michael@0 37736 }
michael@0 37737 this.tiles = transformComponents(context);
michael@0 37738 this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
michael@0 37739 this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
michael@0 37740 this.componentsCount = context.SIZ.Csiz;
michael@0 37741 }
michael@0 37742 };
michael@0 37743 function calculateComponentDimensions(component, siz) {
michael@0 37744 // Section B.2 Component mapping
michael@0 37745 component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
michael@0 37746 component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
michael@0 37747 component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
michael@0 37748 component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
michael@0 37749 component.width = component.x1 - component.x0;
michael@0 37750 component.height = component.y1 - component.y0;
michael@0 37751 }
michael@0 37752 function calculateTileGrids(context, components) {
michael@0 37753 var siz = context.SIZ;
michael@0 37754 // Section B.3 Division into tile and tile-components
michael@0 37755 var tile, tiles = [];
michael@0 37756 var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
michael@0 37757 var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
michael@0 37758 for (var q = 0; q < numYtiles; q++) {
michael@0 37759 for (var p = 0; p < numXtiles; p++) {
michael@0 37760 tile = {};
michael@0 37761 tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
michael@0 37762 tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
michael@0 37763 tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
michael@0 37764 tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
michael@0 37765 tile.width = tile.tx1 - tile.tx0;
michael@0 37766 tile.height = tile.ty1 - tile.ty0;
michael@0 37767 tile.components = [];
michael@0 37768 tiles.push(tile);
michael@0 37769 }
michael@0 37770 }
michael@0 37771 context.tiles = tiles;
michael@0 37772
michael@0 37773 var componentsCount = siz.Csiz;
michael@0 37774 for (var i = 0, ii = componentsCount; i < ii; i++) {
michael@0 37775 var component = components[i];
michael@0 37776 for (var j = 0, jj = tiles.length; j < jj; j++) {
michael@0 37777 var tileComponent = {};
michael@0 37778 tile = tiles[j];
michael@0 37779 tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
michael@0 37780 tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
michael@0 37781 tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
michael@0 37782 tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
michael@0 37783 tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
michael@0 37784 tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
michael@0 37785 tile.components[i] = tileComponent;
michael@0 37786 }
michael@0 37787 }
michael@0 37788 }
michael@0 37789 function getBlocksDimensions(context, component, r) {
michael@0 37790 var codOrCoc = component.codingStyleParameters;
michael@0 37791 var result = {};
michael@0 37792 if (!codOrCoc.entropyCoderWithCustomPrecincts) {
michael@0 37793 result.PPx = 15;
michael@0 37794 result.PPy = 15;
michael@0 37795 } else {
michael@0 37796 result.PPx = codOrCoc.precinctsSizes[r].PPx;
michael@0 37797 result.PPy = codOrCoc.precinctsSizes[r].PPy;
michael@0 37798 }
michael@0 37799 // calculate codeblock size as described in section B.7
michael@0 37800 result.xcb_ = (r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) :
michael@0 37801 Math.min(codOrCoc.xcb, result.PPx));
michael@0 37802 result.ycb_ = (r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) :
michael@0 37803 Math.min(codOrCoc.ycb, result.PPy));
michael@0 37804 return result;
michael@0 37805 }
michael@0 37806 function buildPrecincts(context, resolution, dimensions) {
michael@0 37807 // Section B.6 Division resolution to precincts
michael@0 37808 var precinctWidth = 1 << dimensions.PPx;
michael@0 37809 var precinctHeight = 1 << dimensions.PPy;
michael@0 37810 var numprecinctswide = (resolution.trx1 > resolution.trx0 ?
michael@0 37811 Math.ceil(resolution.trx1 / precinctWidth) -
michael@0 37812 Math.floor(resolution.trx0 / precinctWidth) : 0);
michael@0 37813 var numprecinctshigh = (resolution.try1 > resolution.try0 ?
michael@0 37814 Math.ceil(resolution.try1 / precinctHeight) -
michael@0 37815 Math.floor(resolution.try0 / precinctHeight) : 0);
michael@0 37816 var numprecincts = numprecinctswide * numprecinctshigh;
michael@0 37817 var precinctXOffset = Math.floor(resolution.trx0 / precinctWidth) *
michael@0 37818 precinctWidth;
michael@0 37819 var precinctYOffset = Math.floor(resolution.try0 / precinctHeight) *
michael@0 37820 precinctHeight;
michael@0 37821 resolution.precinctParameters = {
michael@0 37822 precinctXOffset: precinctXOffset,
michael@0 37823 precinctYOffset: precinctYOffset,
michael@0 37824 precinctWidth: precinctWidth,
michael@0 37825 precinctHeight: precinctHeight,
michael@0 37826 numprecinctswide: numprecinctswide,
michael@0 37827 numprecinctshigh: numprecinctshigh,
michael@0 37828 numprecincts: numprecincts
michael@0 37829 };
michael@0 37830 }
michael@0 37831 function buildCodeblocks(context, subband, dimensions) {
michael@0 37832 // Section B.7 Division sub-band into code-blocks
michael@0 37833 var xcb_ = dimensions.xcb_;
michael@0 37834 var ycb_ = dimensions.ycb_;
michael@0 37835 var codeblockWidth = 1 << xcb_;
michael@0 37836 var codeblockHeight = 1 << ycb_;
michael@0 37837 var cbx0 = subband.tbx0 >> xcb_;
michael@0 37838 var cby0 = subband.tby0 >> ycb_;
michael@0 37839 var cbx1 = (subband.tbx1 + codeblockWidth - 1) >> xcb_;
michael@0 37840 var cby1 = (subband.tby1 + codeblockHeight - 1) >> ycb_;
michael@0 37841 var precinctParameters = subband.resolution.precinctParameters;
michael@0 37842 var codeblocks = [];
michael@0 37843 var precincts = [];
michael@0 37844 var i, j, codeblock, precinctNumber;
michael@0 37845 for (j = cby0; j < cby1; j++) {
michael@0 37846 for (i = cbx0; i < cbx1; i++) {
michael@0 37847 codeblock = {
michael@0 37848 cbx: i,
michael@0 37849 cby: j,
michael@0 37850 tbx0: codeblockWidth * i,
michael@0 37851 tby0: codeblockHeight * j,
michael@0 37852 tbx1: codeblockWidth * (i + 1),
michael@0 37853 tby1: codeblockHeight * (j + 1)
michael@0 37854 };
michael@0 37855 // calculate precinct number
michael@0 37856 var pi = Math.floor((codeblock.tbx0 -
michael@0 37857 precinctParameters.precinctXOffset) /
michael@0 37858 precinctParameters.precinctWidth);
michael@0 37859 var pj = Math.floor((codeblock.tby0 -
michael@0 37860 precinctParameters.precinctYOffset) /
michael@0 37861 precinctParameters.precinctHeight);
michael@0 37862 precinctNumber = pj + pi * precinctParameters.numprecinctswide;
michael@0 37863 codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
michael@0 37864 codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
michael@0 37865 codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
michael@0 37866 codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
michael@0 37867 codeblock.precinctNumber = precinctNumber;
michael@0 37868 codeblock.subbandType = subband.type;
michael@0 37869 codeblock.Lblock = 3;
michael@0 37870 codeblocks.push(codeblock);
michael@0 37871 // building precinct for the sub-band
michael@0 37872 var precinct = precincts[precinctNumber];
michael@0 37873 if (precinct !== undefined) {
michael@0 37874 if (i < precinct.cbxMin) {
michael@0 37875 precinct.cbxMin = i;
michael@0 37876 } else if (i > precinct.cbxMax) {
michael@0 37877 precinct.cbxMax = i;
michael@0 37878 }
michael@0 37879 if (j < precinct.cbyMin) {
michael@0 37880 precinct.cbxMin = j;
michael@0 37881 } else if (j > precinct.cbyMax) {
michael@0 37882 precinct.cbyMax = j;
michael@0 37883 }
michael@0 37884 } else {
michael@0 37885 precincts[precinctNumber] = precinct = {
michael@0 37886 cbxMin: i,
michael@0 37887 cbyMin: j,
michael@0 37888 cbxMax: i,
michael@0 37889 cbyMax: j
michael@0 37890 };
michael@0 37891 }
michael@0 37892 codeblock.precinct = precinct;
michael@0 37893 }
michael@0 37894 }
michael@0 37895 subband.codeblockParameters = {
michael@0 37896 codeblockWidth: xcb_,
michael@0 37897 codeblockHeight: ycb_,
michael@0 37898 numcodeblockwide: cbx1 - cbx0 + 1,
michael@0 37899 numcodeblockhigh: cby1 - cby1 + 1
michael@0 37900 };
michael@0 37901 subband.codeblocks = codeblocks;
michael@0 37902 subband.precincts = precincts;
michael@0 37903 }
michael@0 37904 function createPacket(resolution, precinctNumber, layerNumber) {
michael@0 37905 var precinctCodeblocks = [];
michael@0 37906 // Section B.10.8 Order of info in packet
michael@0 37907 var subbands = resolution.subbands;
michael@0 37908 // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence
michael@0 37909 for (var i = 0, ii = subbands.length; i < ii; i++) {
michael@0 37910 var subband = subbands[i];
michael@0 37911 var codeblocks = subband.codeblocks;
michael@0 37912 for (var j = 0, jj = codeblocks.length; j < jj; j++) {
michael@0 37913 var codeblock = codeblocks[j];
michael@0 37914 if (codeblock.precinctNumber != precinctNumber) {
michael@0 37915 continue;
michael@0 37916 }
michael@0 37917 precinctCodeblocks.push(codeblock);
michael@0 37918 }
michael@0 37919 }
michael@0 37920 return {
michael@0 37921 layerNumber: layerNumber,
michael@0 37922 codeblocks: precinctCodeblocks
michael@0 37923 };
michael@0 37924 }
michael@0 37925 function LayerResolutionComponentPositionIterator(context) {
michael@0 37926 var siz = context.SIZ;
michael@0 37927 var tileIndex = context.currentTile.index;
michael@0 37928 var tile = context.tiles[tileIndex];
michael@0 37929 var layersCount = tile.codingStyleDefaultParameters.layersCount;
michael@0 37930 var componentsCount = siz.Csiz;
michael@0 37931 var maxDecompositionLevelsCount = 0;
michael@0 37932 for (var q = 0; q < componentsCount; q++) {
michael@0 37933 maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
michael@0 37934 tile.components[q].codingStyleParameters.decompositionLevelsCount);
michael@0 37935 }
michael@0 37936
michael@0 37937 var l = 0, r = 0, i = 0, k = 0;
michael@0 37938
michael@0 37939 this.nextPacket = function JpxImage_nextPacket() {
michael@0 37940 // Section B.12.1.1 Layer-resolution-component-position
michael@0 37941 for (; l < layersCount; l++) {
michael@0 37942 for (; r <= maxDecompositionLevelsCount; r++) {
michael@0 37943 for (; i < componentsCount; i++) {
michael@0 37944 var component = tile.components[i];
michael@0 37945 if (r > component.codingStyleParameters.decompositionLevelsCount) {
michael@0 37946 continue;
michael@0 37947 }
michael@0 37948
michael@0 37949 var resolution = component.resolutions[r];
michael@0 37950 var numprecincts = resolution.precinctParameters.numprecincts;
michael@0 37951 for (; k < numprecincts;) {
michael@0 37952 var packet = createPacket(resolution, k, l);
michael@0 37953 k++;
michael@0 37954 return packet;
michael@0 37955 }
michael@0 37956 k = 0;
michael@0 37957 }
michael@0 37958 i = 0;
michael@0 37959 }
michael@0 37960 r = 0;
michael@0 37961 }
michael@0 37962 throw 'Out of packets';
michael@0 37963 };
michael@0 37964 }
michael@0 37965 function ResolutionLayerComponentPositionIterator(context) {
michael@0 37966 var siz = context.SIZ;
michael@0 37967 var tileIndex = context.currentTile.index;
michael@0 37968 var tile = context.tiles[tileIndex];
michael@0 37969 var layersCount = tile.codingStyleDefaultParameters.layersCount;
michael@0 37970 var componentsCount = siz.Csiz;
michael@0 37971 var maxDecompositionLevelsCount = 0;
michael@0 37972 for (var q = 0; q < componentsCount; q++) {
michael@0 37973 maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
michael@0 37974 tile.components[q].codingStyleParameters.decompositionLevelsCount);
michael@0 37975 }
michael@0 37976
michael@0 37977 var r = 0, l = 0, i = 0, k = 0;
michael@0 37978
michael@0 37979 this.nextPacket = function JpxImage_nextPacket() {
michael@0 37980 // Section B.12.1.2 Resolution-layer-component-position
michael@0 37981 for (; r <= maxDecompositionLevelsCount; r++) {
michael@0 37982 for (; l < layersCount; l++) {
michael@0 37983 for (; i < componentsCount; i++) {
michael@0 37984 var component = tile.components[i];
michael@0 37985 if (r > component.codingStyleParameters.decompositionLevelsCount) {
michael@0 37986 continue;
michael@0 37987 }
michael@0 37988
michael@0 37989 var resolution = component.resolutions[r];
michael@0 37990 var numprecincts = resolution.precinctParameters.numprecincts;
michael@0 37991 for (; k < numprecincts;) {
michael@0 37992 var packet = createPacket(resolution, k, l);
michael@0 37993 k++;
michael@0 37994 return packet;
michael@0 37995 }
michael@0 37996 k = 0;
michael@0 37997 }
michael@0 37998 i = 0;
michael@0 37999 }
michael@0 38000 l = 0;
michael@0 38001 }
michael@0 38002 throw 'Out of packets';
michael@0 38003 };
michael@0 38004 }
michael@0 38005 function buildPackets(context) {
michael@0 38006 var siz = context.SIZ;
michael@0 38007 var tileIndex = context.currentTile.index;
michael@0 38008 var tile = context.tiles[tileIndex];
michael@0 38009 var componentsCount = siz.Csiz;
michael@0 38010 // Creating resolutions and sub-bands for each component
michael@0 38011 for (var c = 0; c < componentsCount; c++) {
michael@0 38012 var component = tile.components[c];
michael@0 38013 var decompositionLevelsCount =
michael@0 38014 component.codingStyleParameters.decompositionLevelsCount;
michael@0 38015 // Section B.5 Resolution levels and sub-bands
michael@0 38016 var resolutions = [];
michael@0 38017 var subbands = [];
michael@0 38018 for (var r = 0; r <= decompositionLevelsCount; r++) {
michael@0 38019 var blocksDimensions = getBlocksDimensions(context, component, r);
michael@0 38020 var resolution = {};
michael@0 38021 var scale = 1 << (decompositionLevelsCount - r);
michael@0 38022 resolution.trx0 = Math.ceil(component.tcx0 / scale);
michael@0 38023 resolution.try0 = Math.ceil(component.tcy0 / scale);
michael@0 38024 resolution.trx1 = Math.ceil(component.tcx1 / scale);
michael@0 38025 resolution.try1 = Math.ceil(component.tcy1 / scale);
michael@0 38026 buildPrecincts(context, resolution, blocksDimensions);
michael@0 38027 resolutions.push(resolution);
michael@0 38028
michael@0 38029 var subband;
michael@0 38030 if (r === 0) {
michael@0 38031 // one sub-band (LL) with last decomposition
michael@0 38032 subband = {};
michael@0 38033 subband.type = 'LL';
michael@0 38034 subband.tbx0 = Math.ceil(component.tcx0 / scale);
michael@0 38035 subband.tby0 = Math.ceil(component.tcy0 / scale);
michael@0 38036 subband.tbx1 = Math.ceil(component.tcx1 / scale);
michael@0 38037 subband.tby1 = Math.ceil(component.tcy1 / scale);
michael@0 38038 subband.resolution = resolution;
michael@0 38039 buildCodeblocks(context, subband, blocksDimensions);
michael@0 38040 subbands.push(subband);
michael@0 38041 resolution.subbands = [subband];
michael@0 38042 } else {
michael@0 38043 var bscale = 1 << (decompositionLevelsCount - r + 1);
michael@0 38044 var resolutionSubbands = [];
michael@0 38045 // three sub-bands (HL, LH and HH) with rest of decompositions
michael@0 38046 subband = {};
michael@0 38047 subband.type = 'HL';
michael@0 38048 subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
michael@0 38049 subband.tby0 = Math.ceil(component.tcy0 / bscale);
michael@0 38050 subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
michael@0 38051 subband.tby1 = Math.ceil(component.tcy1 / bscale);
michael@0 38052 subband.resolution = resolution;
michael@0 38053 buildCodeblocks(context, subband, blocksDimensions);
michael@0 38054 subbands.push(subband);
michael@0 38055 resolutionSubbands.push(subband);
michael@0 38056
michael@0 38057 subband = {};
michael@0 38058 subband.type = 'LH';
michael@0 38059 subband.tbx0 = Math.ceil(component.tcx0 / bscale);
michael@0 38060 subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
michael@0 38061 subband.tbx1 = Math.ceil(component.tcx1 / bscale);
michael@0 38062 subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
michael@0 38063 subband.resolution = resolution;
michael@0 38064 buildCodeblocks(context, subband, blocksDimensions);
michael@0 38065 subbands.push(subband);
michael@0 38066 resolutionSubbands.push(subband);
michael@0 38067
michael@0 38068 subband = {};
michael@0 38069 subband.type = 'HH';
michael@0 38070 subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
michael@0 38071 subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
michael@0 38072 subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
michael@0 38073 subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
michael@0 38074 subband.resolution = resolution;
michael@0 38075 buildCodeblocks(context, subband, blocksDimensions);
michael@0 38076 subbands.push(subband);
michael@0 38077 resolutionSubbands.push(subband);
michael@0 38078
michael@0 38079 resolution.subbands = resolutionSubbands;
michael@0 38080 }
michael@0 38081 }
michael@0 38082 component.resolutions = resolutions;
michael@0 38083 component.subbands = subbands;
michael@0 38084 }
michael@0 38085 // Generate the packets sequence
michael@0 38086 var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
michael@0 38087 switch (progressionOrder) {
michael@0 38088 case 0:
michael@0 38089 tile.packetsIterator =
michael@0 38090 new LayerResolutionComponentPositionIterator(context);
michael@0 38091 break;
michael@0 38092 case 1:
michael@0 38093 tile.packetsIterator =
michael@0 38094 new ResolutionLayerComponentPositionIterator(context);
michael@0 38095 break;
michael@0 38096 default:
michael@0 38097 throw 'Unsupported progression order ' + progressionOrder;
michael@0 38098 }
michael@0 38099 }
michael@0 38100 function parseTilePackets(context, data, offset, dataLength) {
michael@0 38101 var position = 0;
michael@0 38102 var buffer, bufferSize = 0, skipNextBit = false;
michael@0 38103 function readBits(count) {
michael@0 38104 while (bufferSize < count) {
michael@0 38105 var b = data[offset + position];
michael@0 38106 position++;
michael@0 38107 if (skipNextBit) {
michael@0 38108 buffer = (buffer << 7) | b;
michael@0 38109 bufferSize += 7;
michael@0 38110 skipNextBit = false;
michael@0 38111 } else {
michael@0 38112 buffer = (buffer << 8) | b;
michael@0 38113 bufferSize += 8;
michael@0 38114 }
michael@0 38115 if (b == 0xFF) {
michael@0 38116 skipNextBit = true;
michael@0 38117 }
michael@0 38118 }
michael@0 38119 bufferSize -= count;
michael@0 38120 return (buffer >>> bufferSize) & ((1 << count) - 1);
michael@0 38121 }
michael@0 38122 function alignToByte() {
michael@0 38123 bufferSize = 0;
michael@0 38124 if (skipNextBit) {
michael@0 38125 position++;
michael@0 38126 skipNextBit = false;
michael@0 38127 }
michael@0 38128 }
michael@0 38129 function readCodingpasses() {
michael@0 38130 if (readBits(1) === 0) {
michael@0 38131 return 1;
michael@0 38132 }
michael@0 38133 if (readBits(1) === 0) {
michael@0 38134 return 2;
michael@0 38135 }
michael@0 38136 var value = readBits(2);
michael@0 38137 if (value < 3) {
michael@0 38138 return value + 3;
michael@0 38139 }
michael@0 38140 value = readBits(5);
michael@0 38141 if (value < 31) {
michael@0 38142 return value + 6;
michael@0 38143 }
michael@0 38144 value = readBits(7);
michael@0 38145 return value + 37;
michael@0 38146 }
michael@0 38147 var tileIndex = context.currentTile.index;
michael@0 38148 var tile = context.tiles[tileIndex];
michael@0 38149 var packetsIterator = tile.packetsIterator;
michael@0 38150 while (position < dataLength) {
michael@0 38151 var packet = packetsIterator.nextPacket();
michael@0 38152 if (!readBits(1)) {
michael@0 38153 alignToByte();
michael@0 38154 continue;
michael@0 38155 }
michael@0 38156 var layerNumber = packet.layerNumber;
michael@0 38157 var queue = [], codeblock;
michael@0 38158 for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) {
michael@0 38159 codeblock = packet.codeblocks[i];
michael@0 38160 var precinct = codeblock.precinct;
michael@0 38161 var codeblockColumn = codeblock.cbx - precinct.cbxMin;
michael@0 38162 var codeblockRow = codeblock.cby - precinct.cbyMin;
michael@0 38163 var codeblockIncluded = false;
michael@0 38164 var firstTimeInclusion = false;
michael@0 38165 var valueReady;
michael@0 38166 if ('included' in codeblock) {
michael@0 38167 codeblockIncluded = !!readBits(1);
michael@0 38168 } else {
michael@0 38169 // reading inclusion tree
michael@0 38170 precinct = codeblock.precinct;
michael@0 38171 var inclusionTree, zeroBitPlanesTree;
michael@0 38172 if ('inclusionTree' in precinct) {
michael@0 38173 inclusionTree = precinct.inclusionTree;
michael@0 38174 } else {
michael@0 38175 // building inclusion and zero bit-planes trees
michael@0 38176 var width = precinct.cbxMax - precinct.cbxMin + 1;
michael@0 38177 var height = precinct.cbyMax - precinct.cbyMin + 1;
michael@0 38178 inclusionTree = new InclusionTree(width, height, layerNumber);
michael@0 38179 zeroBitPlanesTree = new TagTree(width, height);
michael@0 38180 precinct.inclusionTree = inclusionTree;
michael@0 38181 precinct.zeroBitPlanesTree = zeroBitPlanesTree;
michael@0 38182 }
michael@0 38183
michael@0 38184 if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
michael@0 38185 while (true) {
michael@0 38186 if (readBits(1)) {
michael@0 38187 valueReady = !inclusionTree.nextLevel();
michael@0 38188 if (valueReady) {
michael@0 38189 codeblock.included = true;
michael@0 38190 codeblockIncluded = firstTimeInclusion = true;
michael@0 38191 break;
michael@0 38192 }
michael@0 38193 } else {
michael@0 38194 inclusionTree.incrementValue(layerNumber);
michael@0 38195 break;
michael@0 38196 }
michael@0 38197 }
michael@0 38198 }
michael@0 38199 }
michael@0 38200 if (!codeblockIncluded) {
michael@0 38201 continue;
michael@0 38202 }
michael@0 38203 if (firstTimeInclusion) {
michael@0 38204 zeroBitPlanesTree = precinct.zeroBitPlanesTree;
michael@0 38205 zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
michael@0 38206 while (true) {
michael@0 38207 if (readBits(1)) {
michael@0 38208 valueReady = !zeroBitPlanesTree.nextLevel();
michael@0 38209 if (valueReady) {
michael@0 38210 break;
michael@0 38211 }
michael@0 38212 } else {
michael@0 38213 zeroBitPlanesTree.incrementValue();
michael@0 38214 }
michael@0 38215 }
michael@0 38216 codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
michael@0 38217 }
michael@0 38218 var codingpasses = readCodingpasses();
michael@0 38219 while (readBits(1)) {
michael@0 38220 codeblock.Lblock++;
michael@0 38221 }
michael@0 38222 var codingpassesLog2 = log2(codingpasses);
michael@0 38223 // rounding down log2
michael@0 38224 var bits = ((codingpasses < (1 << codingpassesLog2)) ?
michael@0 38225 codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock;
michael@0 38226 var codedDataLength = readBits(bits);
michael@0 38227 queue.push({
michael@0 38228 codeblock: codeblock,
michael@0 38229 codingpasses: codingpasses,
michael@0 38230 dataLength: codedDataLength
michael@0 38231 });
michael@0 38232 }
michael@0 38233 alignToByte();
michael@0 38234 while (queue.length > 0) {
michael@0 38235 var packetItem = queue.shift();
michael@0 38236 codeblock = packetItem.codeblock;
michael@0 38237 if (!('data' in codeblock)) {
michael@0 38238 codeblock.data = [];
michael@0 38239 }
michael@0 38240 codeblock.data.push({
michael@0 38241 data: data,
michael@0 38242 start: offset + position,
michael@0 38243 end: offset + position + packetItem.dataLength,
michael@0 38244 codingpasses: packetItem.codingpasses
michael@0 38245 });
michael@0 38246 position += packetItem.dataLength;
michael@0 38247 }
michael@0 38248 }
michael@0 38249 return position;
michael@0 38250 }
michael@0 38251 function copyCoefficients(coefficients, levelWidth, levelHeight, subband,
michael@0 38252 delta, mb, reversible, segmentationSymbolUsed) {
michael@0 38253 var x0 = subband.tbx0;
michael@0 38254 var y0 = subband.tby0;
michael@0 38255 var width = subband.tbx1 - subband.tbx0;
michael@0 38256 var codeblocks = subband.codeblocks;
michael@0 38257 var right = subband.type.charAt(0) === 'H' ? 1 : 0;
michael@0 38258 var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0;
michael@0 38259
michael@0 38260 for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
michael@0 38261 var codeblock = codeblocks[i];
michael@0 38262 var blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
michael@0 38263 var blockHeight = codeblock.tby1_ - codeblock.tby0_;
michael@0 38264 if (blockWidth === 0 || blockHeight === 0) {
michael@0 38265 continue;
michael@0 38266 }
michael@0 38267 if (!('data' in codeblock)) {
michael@0 38268 continue;
michael@0 38269 }
michael@0 38270
michael@0 38271 var bitModel, currentCodingpassType;
michael@0 38272 bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType,
michael@0 38273 codeblock.zeroBitPlanes, mb);
michael@0 38274 currentCodingpassType = 2; // first bit plane starts from cleanup
michael@0 38275
michael@0 38276 // collect data
michael@0 38277 var data = codeblock.data, totalLength = 0, codingpasses = 0;
michael@0 38278 var j, jj, dataItem;
michael@0 38279 for (j = 0, jj = data.length; j < jj; j++) {
michael@0 38280 dataItem = data[j];
michael@0 38281 totalLength += dataItem.end - dataItem.start;
michael@0 38282 codingpasses += dataItem.codingpasses;
michael@0 38283 }
michael@0 38284 var encodedData = new Uint8Array(totalLength);
michael@0 38285 var position = 0;
michael@0 38286 for (j = 0, jj = data.length; j < jj; j++) {
michael@0 38287 dataItem = data[j];
michael@0 38288 var chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
michael@0 38289 encodedData.set(chunk, position);
michael@0 38290 position += chunk.length;
michael@0 38291 }
michael@0 38292 // decoding the item
michael@0 38293 var decoder = new ArithmeticDecoder(encodedData, 0, totalLength);
michael@0 38294 bitModel.setDecoder(decoder);
michael@0 38295
michael@0 38296 for (j = 0; j < codingpasses; j++) {
michael@0 38297 switch (currentCodingpassType) {
michael@0 38298 case 0:
michael@0 38299 bitModel.runSignificancePropogationPass();
michael@0 38300 break;
michael@0 38301 case 1:
michael@0 38302 bitModel.runMagnitudeRefinementPass();
michael@0 38303 break;
michael@0 38304 case 2:
michael@0 38305 bitModel.runCleanupPass();
michael@0 38306 if (segmentationSymbolUsed) {
michael@0 38307 bitModel.checkSegmentationSymbol();
michael@0 38308 }
michael@0 38309 break;
michael@0 38310 }
michael@0 38311 currentCodingpassType = (currentCodingpassType + 1) % 3;
michael@0 38312 }
michael@0 38313
michael@0 38314 var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width;
michael@0 38315 var sign = bitModel.coefficentsSign;
michael@0 38316 var magnitude = bitModel.coefficentsMagnitude;
michael@0 38317 var bitsDecoded = bitModel.bitsDecoded;
michael@0 38318 var magnitudeCorrection = reversible ? 0 : 0.5;
michael@0 38319 var k, n, nb;
michael@0 38320 position = 0;
michael@0 38321 // Do the interleaving of Section F.3.3 here, so we do not need
michael@0 38322 // to copy later. LL level is not interleaved, just copied.
michael@0 38323 var interleave = (subband.type !== 'LL');
michael@0 38324 for (j = 0; j < blockHeight; j++) {
michael@0 38325 var row = (offset / width) | 0; // row in the non-interleaved subband
michael@0 38326 var levelOffset = 2 * row * (levelWidth - width) + right + bottom;
michael@0 38327 for (k = 0; k < blockWidth; k++) {
michael@0 38328 n = magnitude[position];
michael@0 38329 if (n !== 0) {
michael@0 38330 n = (n + magnitudeCorrection) * delta;
michael@0 38331 if (sign[position] !== 0) {
michael@0 38332 n = -n;
michael@0 38333 }
michael@0 38334 nb = bitsDecoded[position];
michael@0 38335 var pos = interleave ? (levelOffset + (offset << 1)) : offset;
michael@0 38336 if (reversible && (nb >= mb)) {
michael@0 38337 coefficients[pos] = n;
michael@0 38338 } else {
michael@0 38339 coefficients[pos] = n * (1 << (mb - nb));
michael@0 38340 }
michael@0 38341 }
michael@0 38342 offset++;
michael@0 38343 position++;
michael@0 38344 }
michael@0 38345 offset += width - blockWidth;
michael@0 38346 }
michael@0 38347 }
michael@0 38348 }
michael@0 38349 function transformTile(context, tile, c) {
michael@0 38350 var component = tile.components[c];
michael@0 38351 var codingStyleParameters = component.codingStyleParameters;
michael@0 38352 var quantizationParameters = component.quantizationParameters;
michael@0 38353 var decompositionLevelsCount =
michael@0 38354 codingStyleParameters.decompositionLevelsCount;
michael@0 38355 var spqcds = quantizationParameters.SPqcds;
michael@0 38356 var scalarExpounded = quantizationParameters.scalarExpounded;
michael@0 38357 var guardBits = quantizationParameters.guardBits;
michael@0 38358 var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
michael@0 38359 var precision = context.components[c].precision;
michael@0 38360
michael@0 38361 var reversible = codingStyleParameters.reversibleTransformation;
michael@0 38362 var transform = (reversible ? new ReversibleTransform() :
michael@0 38363 new IrreversibleTransform());
michael@0 38364
michael@0 38365 var subbandCoefficients = [];
michael@0 38366 var b = 0;
michael@0 38367 for (var i = 0; i <= decompositionLevelsCount; i++) {
michael@0 38368 var resolution = component.resolutions[i];
michael@0 38369
michael@0 38370 var width = resolution.trx1 - resolution.trx0;
michael@0 38371 var height = resolution.try1 - resolution.try0;
michael@0 38372 // Allocate space for the whole sublevel.
michael@0 38373 var coefficients = new Float32Array(width * height);
michael@0 38374
michael@0 38375 for (var j = 0, jj = resolution.subbands.length; j < jj; j++) {
michael@0 38376 var mu, epsilon;
michael@0 38377 if (!scalarExpounded) {
michael@0 38378 // formula E-5
michael@0 38379 mu = spqcds[0].mu;
michael@0 38380 epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
michael@0 38381 } else {
michael@0 38382 mu = spqcds[b].mu;
michael@0 38383 epsilon = spqcds[b].epsilon;
michael@0 38384 b++;
michael@0 38385 }
michael@0 38386
michael@0 38387 var subband = resolution.subbands[j];
michael@0 38388 var gainLog2 = SubbandsGainLog2[subband.type];
michael@0 38389
michael@0 38390 // calulate quantization coefficient (Section E.1.1.1)
michael@0 38391 var delta = (reversible ? 1 :
michael@0 38392 Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048));
michael@0 38393 var mb = (guardBits + epsilon - 1);
michael@0 38394
michael@0 38395 // In the first resolution level, copyCoefficients will fill the
michael@0 38396 // whole array with coefficients. In the succeding passes,
michael@0 38397 // copyCoefficients will consecutively fill in the values that belong
michael@0 38398 // to the interleaved positions of the HL, LH, and HH coefficients.
michael@0 38399 // The LL coefficients will then be interleaved in Transform.iterate().
michael@0 38400 copyCoefficients(coefficients, width, height, subband, delta, mb,
michael@0 38401 reversible, segmentationSymbolUsed);
michael@0 38402 }
michael@0 38403 subbandCoefficients.push({
michael@0 38404 width: width,
michael@0 38405 height: height,
michael@0 38406 items: coefficients
michael@0 38407 });
michael@0 38408 }
michael@0 38409
michael@0 38410 var result = transform.calculate(subbandCoefficients,
michael@0 38411 component.tcx0, component.tcy0);
michael@0 38412 return {
michael@0 38413 left: component.tcx0,
michael@0 38414 top: component.tcy0,
michael@0 38415 width: result.width,
michael@0 38416 height: result.height,
michael@0 38417 items: result.items
michael@0 38418 };
michael@0 38419 }
michael@0 38420 function transformComponents(context) {
michael@0 38421 var siz = context.SIZ;
michael@0 38422 var components = context.components;
michael@0 38423 var componentsCount = siz.Csiz;
michael@0 38424 var resultImages = [];
michael@0 38425 for (var i = 0, ii = context.tiles.length; i < ii; i++) {
michael@0 38426 var tile = context.tiles[i];
michael@0 38427 var transformedTiles = [];
michael@0 38428 var c;
michael@0 38429 for (c = 0; c < componentsCount; c++) {
michael@0 38430 transformedTiles[c] = transformTile(context, tile, c);
michael@0 38431 }
michael@0 38432 var tile0 = transformedTiles[0];
michael@0 38433 var out = new Uint8Array(tile0.items.length * componentsCount);
michael@0 38434 var result = {
michael@0 38435 left: tile0.left,
michael@0 38436 top: tile0.top,
michael@0 38437 width: tile0.width,
michael@0 38438 height: tile0.height,
michael@0 38439 items: out
michael@0 38440 };
michael@0 38441
michael@0 38442 // Section G.2.2 Inverse multi component transform
michael@0 38443 var shift, offset, max, min;
michael@0 38444 var pos = 0, j, jj, y0, y1, y2, r, g, b, k, val;
michael@0 38445 if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
michael@0 38446 var fourComponents = componentsCount === 4;
michael@0 38447 var y0items = transformedTiles[0].items;
michael@0 38448 var y1items = transformedTiles[1].items;
michael@0 38449 var y2items = transformedTiles[2].items;
michael@0 38450 var y3items = fourComponents ? transformedTiles[3].items : null;
michael@0 38451
michael@0 38452 // HACK: The multiple component transform formulas below assume that
michael@0 38453 // all components have the same precision. With this in mind, we
michael@0 38454 // compute shift and offset only once.
michael@0 38455 shift = components[0].precision - 8;
michael@0 38456 offset = (128 << shift) + 0.5;
michael@0 38457 max = (127.5 * (1 << shift));
michael@0 38458 min = -max;
michael@0 38459
michael@0 38460 var component0 = tile.components[0];
michael@0 38461 if (!component0.codingStyleParameters.reversibleTransformation) {
michael@0 38462 // inverse irreversible multiple component transform
michael@0 38463 for (j = 0, jj = y0items.length; j < jj; ++j) {
michael@0 38464 y0 = y0items[j];
michael@0 38465 y1 = y1items[j];
michael@0 38466 y2 = y2items[j];
michael@0 38467 r = y0 + 1.402 * y2;
michael@0 38468 g = y0 - 0.34413 * y1 - 0.71414 * y2;
michael@0 38469 b = y0 + 1.772 * y1;
michael@0 38470 out[pos++] = r <= min ? 0 : r >= max ? 255 : (r + offset) >> shift;
michael@0 38471 out[pos++] = g <= min ? 0 : g >= max ? 255 : (g + offset) >> shift;
michael@0 38472 out[pos++] = b <= min ? 0 : b >= max ? 255 : (b + offset) >> shift;
michael@0 38473 if (fourComponents) {
michael@0 38474 k = y3items[j];
michael@0 38475 out[pos++] =
michael@0 38476 k <= min ? 0 : k >= max ? 255 : (k + offset) >> shift;
michael@0 38477 }
michael@0 38478 }
michael@0 38479 } else {
michael@0 38480 // inverse reversible multiple component transform
michael@0 38481 for (j = 0, jj = y0items.length; j < jj; ++j) {
michael@0 38482 y0 = y0items[j];
michael@0 38483 y1 = y1items[j];
michael@0 38484 y2 = y2items[j];
michael@0 38485 g = y0 - ((y2 + y1) >> 2);
michael@0 38486 r = g + y2;
michael@0 38487 b = g + y1;
michael@0 38488 out[pos++] = r <= min ? 0 : r >= max ? 255 : (r + offset) >> shift;
michael@0 38489 out[pos++] = g <= min ? 0 : g >= max ? 255 : (g + offset) >> shift;
michael@0 38490 out[pos++] = b <= min ? 0 : b >= max ? 255 : (b + offset) >> shift;
michael@0 38491 if (fourComponents) {
michael@0 38492 k = y3items[j];
michael@0 38493 out[pos++] =
michael@0 38494 k <= min ? 0 : k >= max ? 255 : (k + offset) >> shift;
michael@0 38495 }
michael@0 38496 }
michael@0 38497 }
michael@0 38498 } else { // no multi-component transform
michael@0 38499 for (c = 0; c < componentsCount; c++) {
michael@0 38500 var items = transformedTiles[c].items;
michael@0 38501 shift = components[c].precision - 8;
michael@0 38502 offset = (128 << shift) + 0.5;
michael@0 38503 max = (127.5 * (1 << shift));
michael@0 38504 min = -max;
michael@0 38505 for (pos = c, j = 0, jj = items.length; j < jj; j++) {
michael@0 38506 val = items[j];
michael@0 38507 out[pos] = val <= min ? 0 :
michael@0 38508 val >= max ? 255 : (val + offset) >> shift;
michael@0 38509 pos += componentsCount;
michael@0 38510 }
michael@0 38511 }
michael@0 38512 }
michael@0 38513 resultImages.push(result);
michael@0 38514 }
michael@0 38515 return resultImages;
michael@0 38516 }
michael@0 38517 function initializeTile(context, tileIndex) {
michael@0 38518 var siz = context.SIZ;
michael@0 38519 var componentsCount = siz.Csiz;
michael@0 38520 var tile = context.tiles[tileIndex];
michael@0 38521 for (var c = 0; c < componentsCount; c++) {
michael@0 38522 var component = tile.components[c];
michael@0 38523 var qcdOrQcc = (c in context.currentTile.QCC ?
michael@0 38524 context.currentTile.QCC[c] : context.currentTile.QCD);
michael@0 38525 component.quantizationParameters = qcdOrQcc;
michael@0 38526 var codOrCoc = (c in context.currentTile.COC ?
michael@0 38527 context.currentTile.COC[c] : context.currentTile.COD);
michael@0 38528 component.codingStyleParameters = codOrCoc;
michael@0 38529 }
michael@0 38530 tile.codingStyleDefaultParameters = context.currentTile.COD;
michael@0 38531 }
michael@0 38532
michael@0 38533 // Section B.10.2 Tag trees
michael@0 38534 var TagTree = (function TagTreeClosure() {
michael@0 38535 function TagTree(width, height) {
michael@0 38536 var levelsLength = log2(Math.max(width, height)) + 1;
michael@0 38537 this.levels = [];
michael@0 38538 for (var i = 0; i < levelsLength; i++) {
michael@0 38539 var level = {
michael@0 38540 width: width,
michael@0 38541 height: height,
michael@0 38542 items: []
michael@0 38543 };
michael@0 38544 this.levels.push(level);
michael@0 38545 width = Math.ceil(width / 2);
michael@0 38546 height = Math.ceil(height / 2);
michael@0 38547 }
michael@0 38548 }
michael@0 38549 TagTree.prototype = {
michael@0 38550 reset: function TagTree_reset(i, j) {
michael@0 38551 var currentLevel = 0, value = 0, level;
michael@0 38552 while (currentLevel < this.levels.length) {
michael@0 38553 level = this.levels[currentLevel];
michael@0 38554 var index = i + j * level.width;
michael@0 38555 if (index in level.items) {
michael@0 38556 value = level.items[index];
michael@0 38557 break;
michael@0 38558 }
michael@0 38559 level.index = index;
michael@0 38560 i >>= 1;
michael@0 38561 j >>= 1;
michael@0 38562 currentLevel++;
michael@0 38563 }
michael@0 38564 currentLevel--;
michael@0 38565 level = this.levels[currentLevel];
michael@0 38566 level.items[level.index] = value;
michael@0 38567 this.currentLevel = currentLevel;
michael@0 38568 delete this.value;
michael@0 38569 },
michael@0 38570 incrementValue: function TagTree_incrementValue() {
michael@0 38571 var level = this.levels[this.currentLevel];
michael@0 38572 level.items[level.index]++;
michael@0 38573 },
michael@0 38574 nextLevel: function TagTree_nextLevel() {
michael@0 38575 var currentLevel = this.currentLevel;
michael@0 38576 var level = this.levels[currentLevel];
michael@0 38577 var value = level.items[level.index];
michael@0 38578 currentLevel--;
michael@0 38579 if (currentLevel < 0) {
michael@0 38580 this.value = value;
michael@0 38581 return false;
michael@0 38582 }
michael@0 38583
michael@0 38584 this.currentLevel = currentLevel;
michael@0 38585 level = this.levels[currentLevel];
michael@0 38586 level.items[level.index] = value;
michael@0 38587 return true;
michael@0 38588 }
michael@0 38589 };
michael@0 38590 return TagTree;
michael@0 38591 })();
michael@0 38592
michael@0 38593 var InclusionTree = (function InclusionTreeClosure() {
michael@0 38594 function InclusionTree(width, height, defaultValue) {
michael@0 38595 var levelsLength = log2(Math.max(width, height)) + 1;
michael@0 38596 this.levels = [];
michael@0 38597 for (var i = 0; i < levelsLength; i++) {
michael@0 38598 var items = new Uint8Array(width * height);
michael@0 38599 for (var j = 0, jj = items.length; j < jj; j++) {
michael@0 38600 items[j] = defaultValue;
michael@0 38601 }
michael@0 38602
michael@0 38603 var level = {
michael@0 38604 width: width,
michael@0 38605 height: height,
michael@0 38606 items: items
michael@0 38607 };
michael@0 38608 this.levels.push(level);
michael@0 38609
michael@0 38610 width = Math.ceil(width / 2);
michael@0 38611 height = Math.ceil(height / 2);
michael@0 38612 }
michael@0 38613 }
michael@0 38614 InclusionTree.prototype = {
michael@0 38615 reset: function InclusionTree_reset(i, j, stopValue) {
michael@0 38616 var currentLevel = 0;
michael@0 38617 while (currentLevel < this.levels.length) {
michael@0 38618 var level = this.levels[currentLevel];
michael@0 38619 var index = i + j * level.width;
michael@0 38620 level.index = index;
michael@0 38621 var value = level.items[index];
michael@0 38622
michael@0 38623 if (value == 0xFF) {
michael@0 38624 break;
michael@0 38625 }
michael@0 38626
michael@0 38627 if (value > stopValue) {
michael@0 38628 this.currentLevel = currentLevel;
michael@0 38629 // already know about this one, propagating the value to top levels
michael@0 38630 this.propagateValues();
michael@0 38631 return false;
michael@0 38632 }
michael@0 38633
michael@0 38634 i >>= 1;
michael@0 38635 j >>= 1;
michael@0 38636 currentLevel++;
michael@0 38637 }
michael@0 38638 this.currentLevel = currentLevel - 1;
michael@0 38639 return true;
michael@0 38640 },
michael@0 38641 incrementValue: function InclusionTree_incrementValue(stopValue) {
michael@0 38642 var level = this.levels[this.currentLevel];
michael@0 38643 level.items[level.index] = stopValue + 1;
michael@0 38644 this.propagateValues();
michael@0 38645 },
michael@0 38646 propagateValues: function InclusionTree_propagateValues() {
michael@0 38647 var levelIndex = this.currentLevel;
michael@0 38648 var level = this.levels[levelIndex];
michael@0 38649 var currentValue = level.items[level.index];
michael@0 38650 while (--levelIndex >= 0) {
michael@0 38651 level = this.levels[levelIndex];
michael@0 38652 level.items[level.index] = currentValue;
michael@0 38653 }
michael@0 38654 },
michael@0 38655 nextLevel: function InclusionTree_nextLevel() {
michael@0 38656 var currentLevel = this.currentLevel;
michael@0 38657 var level = this.levels[currentLevel];
michael@0 38658 var value = level.items[level.index];
michael@0 38659 level.items[level.index] = 0xFF;
michael@0 38660 currentLevel--;
michael@0 38661 if (currentLevel < 0) {
michael@0 38662 return false;
michael@0 38663 }
michael@0 38664
michael@0 38665 this.currentLevel = currentLevel;
michael@0 38666 level = this.levels[currentLevel];
michael@0 38667 level.items[level.index] = value;
michael@0 38668 return true;
michael@0 38669 }
michael@0 38670 };
michael@0 38671 return InclusionTree;
michael@0 38672 })();
michael@0 38673
michael@0 38674 // Section D. Coefficient bit modeling
michael@0 38675 var BitModel = (function BitModelClosure() {
michael@0 38676 var UNIFORM_CONTEXT = 17;
michael@0 38677 var RUNLENGTH_CONTEXT = 18;
michael@0 38678 // Table D-1
michael@0 38679 // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4),
michael@0 38680 // vv - sum of Vi (0..2), and hh - sum of Hi (0..2)
michael@0 38681 var LLAndLHContextsLabel = new Uint8Array([
michael@0 38682 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,
michael@0 38683 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,
michael@0 38684 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
michael@0 38685 ]);
michael@0 38686 var HLContextLabel = new Uint8Array([
michael@0 38687 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,
michael@0 38688 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,
michael@0 38689 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
michael@0 38690 ]);
michael@0 38691 var HHContextLabel = new Uint8Array([
michael@0 38692 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,
michael@0 38693 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,
michael@0 38694 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
michael@0 38695 ]);
michael@0 38696
michael@0 38697 function BitModel(width, height, subband, zeroBitPlanes, mb) {
michael@0 38698 this.width = width;
michael@0 38699 this.height = height;
michael@0 38700
michael@0 38701 this.contextLabelTable = (subband == 'HH' ? HHContextLabel :
michael@0 38702 (subband == 'HL' ? HLContextLabel : LLAndLHContextsLabel));
michael@0 38703
michael@0 38704 var coefficientCount = width * height;
michael@0 38705
michael@0 38706 // coefficients outside the encoding region treated as insignificant
michael@0 38707 // add border state cells for significanceState
michael@0 38708 this.neighborsSignificance = new Uint8Array(coefficientCount);
michael@0 38709 this.coefficentsSign = new Uint8Array(coefficientCount);
michael@0 38710 this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) :
michael@0 38711 mb > 6 ? new Uint16Array(coefficientCount) :
michael@0 38712 new Uint8Array(coefficientCount);
michael@0 38713 this.processingFlags = new Uint8Array(coefficientCount);
michael@0 38714
michael@0 38715 var bitsDecoded = new Uint8Array(coefficientCount);
michael@0 38716 if (zeroBitPlanes !== 0) {
michael@0 38717 for (var i = 0; i < coefficientCount; i++) {
michael@0 38718 bitsDecoded[i] = zeroBitPlanes;
michael@0 38719 }
michael@0 38720 }
michael@0 38721 this.bitsDecoded = bitsDecoded;
michael@0 38722
michael@0 38723 this.reset();
michael@0 38724 }
michael@0 38725
michael@0 38726 BitModel.prototype = {
michael@0 38727 setDecoder: function BitModel_setDecoder(decoder) {
michael@0 38728 this.decoder = decoder;
michael@0 38729 },
michael@0 38730 reset: function BitModel_reset() {
michael@0 38731 // We have 17 contexts that are accessed via context labels,
michael@0 38732 // plus the uniform and runlength context.
michael@0 38733 this.contexts = new Int8Array(19);
michael@0 38734
michael@0 38735 // Contexts are packed into 1 byte:
michael@0 38736 // highest 7 bits carry the index, lowest bit carries mps
michael@0 38737 this.contexts[0] = (4 << 1) | 0;
michael@0 38738 this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0;
michael@0 38739 this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0;
michael@0 38740 },
michael@0 38741 setNeighborsSignificance:
michael@0 38742 function BitModel_setNeighborsSignificance(row, column, index) {
michael@0 38743 var neighborsSignificance = this.neighborsSignificance;
michael@0 38744 var width = this.width, height = this.height;
michael@0 38745 var left = (column > 0);
michael@0 38746 var right = (column + 1 < width);
michael@0 38747 var i;
michael@0 38748
michael@0 38749 if (row > 0) {
michael@0 38750 i = index - width;
michael@0 38751 if (left) {
michael@0 38752 neighborsSignificance[i - 1] += 0x10;
michael@0 38753 }
michael@0 38754 if (right) {
michael@0 38755 neighborsSignificance[i + 1] += 0x10;
michael@0 38756 }
michael@0 38757 neighborsSignificance[i] += 0x04;
michael@0 38758 }
michael@0 38759
michael@0 38760 if (row + 1 < height) {
michael@0 38761 i = index + width;
michael@0 38762 if (left) {
michael@0 38763 neighborsSignificance[i - 1] += 0x10;
michael@0 38764 }
michael@0 38765 if (right) {
michael@0 38766 neighborsSignificance[i + 1] += 0x10;
michael@0 38767 }
michael@0 38768 neighborsSignificance[i] += 0x04;
michael@0 38769 }
michael@0 38770
michael@0 38771 if (left) {
michael@0 38772 neighborsSignificance[index - 1] += 0x01;
michael@0 38773 }
michael@0 38774 if (right) {
michael@0 38775 neighborsSignificance[index + 1] += 0x01;
michael@0 38776 }
michael@0 38777 neighborsSignificance[index] |= 0x80;
michael@0 38778 },
michael@0 38779 runSignificancePropogationPass:
michael@0 38780 function BitModel_runSignificancePropogationPass() {
michael@0 38781 var decoder = this.decoder;
michael@0 38782 var width = this.width, height = this.height;
michael@0 38783 var coefficentsMagnitude = this.coefficentsMagnitude;
michael@0 38784 var coefficentsSign = this.coefficentsSign;
michael@0 38785 var neighborsSignificance = this.neighborsSignificance;
michael@0 38786 var processingFlags = this.processingFlags;
michael@0 38787 var contexts = this.contexts;
michael@0 38788 var labels = this.contextLabelTable;
michael@0 38789 var bitsDecoded = this.bitsDecoded;
michael@0 38790 var processedInverseMask = ~1;
michael@0 38791 var processedMask = 1;
michael@0 38792 var firstMagnitudeBitMask = 2;
michael@0 38793
michael@0 38794 for (var i0 = 0; i0 < height; i0 += 4) {
michael@0 38795 for (var j = 0; j < width; j++) {
michael@0 38796 var index = i0 * width + j;
michael@0 38797 for (var i1 = 0; i1 < 4; i1++, index += width) {
michael@0 38798 var i = i0 + i1;
michael@0 38799 if (i >= height) {
michael@0 38800 break;
michael@0 38801 }
michael@0 38802 // clear processed flag first
michael@0 38803 processingFlags[index] &= processedInverseMask;
michael@0 38804
michael@0 38805 if (coefficentsMagnitude[index] ||
michael@0 38806 !neighborsSignificance[index]) {
michael@0 38807 continue;
michael@0 38808 }
michael@0 38809
michael@0 38810 var contextLabel = labels[neighborsSignificance[index]];
michael@0 38811 var decision = decoder.readBit(contexts, contextLabel);
michael@0 38812 if (decision) {
michael@0 38813 var sign = this.decodeSignBit(i, j, index);
michael@0 38814 coefficentsSign[index] = sign;
michael@0 38815 coefficentsMagnitude[index] = 1;
michael@0 38816 this.setNeighborsSignificance(i, j, index);
michael@0 38817 processingFlags[index] |= firstMagnitudeBitMask;
michael@0 38818 }
michael@0 38819 bitsDecoded[index]++;
michael@0 38820 processingFlags[index] |= processedMask;
michael@0 38821 }
michael@0 38822 }
michael@0 38823 }
michael@0 38824 },
michael@0 38825 decodeSignBit: function BitModel_decodeSignBit(row, column, index) {
michael@0 38826 var width = this.width, height = this.height;
michael@0 38827 var coefficentsMagnitude = this.coefficentsMagnitude;
michael@0 38828 var coefficentsSign = this.coefficentsSign;
michael@0 38829 var contribution, sign0, sign1, significance1;
michael@0 38830 var contextLabel, decoded;
michael@0 38831
michael@0 38832 // calculate horizontal contribution
michael@0 38833 significance1 = (column > 0 && coefficentsMagnitude[index - 1] !== 0);
michael@0 38834 if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
michael@0 38835 sign1 = coefficentsSign[index + 1];
michael@0 38836 if (significance1) {
michael@0 38837 sign0 = coefficentsSign[index - 1];
michael@0 38838 contribution = 1 - sign1 - sign0;
michael@0 38839 } else {
michael@0 38840 contribution = 1 - sign1 - sign1;
michael@0 38841 }
michael@0 38842 } else if (significance1) {
michael@0 38843 sign0 = coefficentsSign[index - 1];
michael@0 38844 contribution = 1 - sign0 - sign0;
michael@0 38845 } else {
michael@0 38846 contribution = 0;
michael@0 38847 }
michael@0 38848 var horizontalContribution = 3 * contribution;
michael@0 38849
michael@0 38850 // calculate vertical contribution and combine with the horizontal
michael@0 38851 significance1 = (row > 0 && coefficentsMagnitude[index - width] !== 0);
michael@0 38852 if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
michael@0 38853 sign1 = coefficentsSign[index + width];
michael@0 38854 if (significance1) {
michael@0 38855 sign0 = coefficentsSign[index - width];
michael@0 38856 contribution = 1 - sign1 - sign0 + horizontalContribution;
michael@0 38857 } else {
michael@0 38858 contribution = 1 - sign1 - sign1 + horizontalContribution;
michael@0 38859 }
michael@0 38860 } else if (significance1) {
michael@0 38861 sign0 = coefficentsSign[index - width];
michael@0 38862 contribution = 1 - sign0 - sign0 + horizontalContribution;
michael@0 38863 } else {
michael@0 38864 contribution = horizontalContribution;
michael@0 38865 }
michael@0 38866
michael@0 38867 if (contribution >= 0) {
michael@0 38868 contextLabel = 9 + contribution;
michael@0 38869 decoded = this.decoder.readBit(this.contexts, contextLabel);
michael@0 38870 } else {
michael@0 38871 contextLabel = 9 - contribution;
michael@0 38872 decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
michael@0 38873 }
michael@0 38874 return decoded;
michael@0 38875 },
michael@0 38876 runMagnitudeRefinementPass:
michael@0 38877 function BitModel_runMagnitudeRefinementPass() {
michael@0 38878 var decoder = this.decoder;
michael@0 38879 var width = this.width, height = this.height;
michael@0 38880 var coefficentsMagnitude = this.coefficentsMagnitude;
michael@0 38881 var neighborsSignificance = this.neighborsSignificance;
michael@0 38882 var contexts = this.contexts;
michael@0 38883 var bitsDecoded = this.bitsDecoded;
michael@0 38884 var processingFlags = this.processingFlags;
michael@0 38885 var processedMask = 1;
michael@0 38886 var firstMagnitudeBitMask = 2;
michael@0 38887 var length = width * height;
michael@0 38888 var width4 = width * 4;
michael@0 38889
michael@0 38890 for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) {
michael@0 38891 indexNext = Math.min(length, index0 + width4);
michael@0 38892 for (var j = 0; j < width; j++) {
michael@0 38893 for (var index = index0 + j; index < indexNext; index += width) {
michael@0 38894
michael@0 38895 // significant but not those that have just become
michael@0 38896 if (!coefficentsMagnitude[index] ||
michael@0 38897 (processingFlags[index] & processedMask) !== 0) {
michael@0 38898 continue;
michael@0 38899 }
michael@0 38900
michael@0 38901 var contextLabel = 16;
michael@0 38902 if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
michael@0 38903 processingFlags[index] ^= firstMagnitudeBitMask;
michael@0 38904 // first refinement
michael@0 38905 var significance = neighborsSignificance[index] & 127;
michael@0 38906 contextLabel = significance === 0 ? 15 : 14;
michael@0 38907 }
michael@0 38908
michael@0 38909 var bit = decoder.readBit(contexts, contextLabel);
michael@0 38910 coefficentsMagnitude[index] =
michael@0 38911 (coefficentsMagnitude[index] << 1) | bit;
michael@0 38912 bitsDecoded[index]++;
michael@0 38913 processingFlags[index] |= processedMask;
michael@0 38914 }
michael@0 38915 }
michael@0 38916 }
michael@0 38917 },
michael@0 38918 runCleanupPass: function BitModel_runCleanupPass() {
michael@0 38919 var decoder = this.decoder;
michael@0 38920 var width = this.width, height = this.height;
michael@0 38921 var neighborsSignificance = this.neighborsSignificance;
michael@0 38922 var coefficentsMagnitude = this.coefficentsMagnitude;
michael@0 38923 var coefficentsSign = this.coefficentsSign;
michael@0 38924 var contexts = this.contexts;
michael@0 38925 var labels = this.contextLabelTable;
michael@0 38926 var bitsDecoded = this.bitsDecoded;
michael@0 38927 var processingFlags = this.processingFlags;
michael@0 38928 var processedMask = 1;
michael@0 38929 var firstMagnitudeBitMask = 2;
michael@0 38930 var oneRowDown = width;
michael@0 38931 var twoRowsDown = width * 2;
michael@0 38932 var threeRowsDown = width * 3;
michael@0 38933 var iNext;
michael@0 38934 for (var i0 = 0; i0 < height; i0 = iNext) {
michael@0 38935 iNext = Math.min(i0 + 4, height);
michael@0 38936 var indexBase = i0 * width;
michael@0 38937 var checkAllEmpty = i0 + 3 < height;
michael@0 38938 for (var j = 0; j < width; j++) {
michael@0 38939 var index0 = indexBase + j;
michael@0 38940 // using the property: labels[neighborsSignificance[index]] == 0
michael@0 38941 // when neighborsSignificance[index] == 0
michael@0 38942 var allEmpty = (checkAllEmpty &&
michael@0 38943 processingFlags[index0] === 0 &&
michael@0 38944 processingFlags[index0 + oneRowDown] === 0 &&
michael@0 38945 processingFlags[index0 + twoRowsDown] === 0 &&
michael@0 38946 processingFlags[index0 + threeRowsDown] === 0 &&
michael@0 38947 neighborsSignificance[index0] === 0 &&
michael@0 38948 neighborsSignificance[index0 + oneRowDown] === 0 &&
michael@0 38949 neighborsSignificance[index0 + twoRowsDown] === 0 &&
michael@0 38950 neighborsSignificance[index0 + threeRowsDown] === 0);
michael@0 38951 var i1 = 0, index = index0;
michael@0 38952 var i = i0, sign;
michael@0 38953 if (allEmpty) {
michael@0 38954 var hasSignificantCoefficent =
michael@0 38955 decoder.readBit(contexts, RUNLENGTH_CONTEXT);
michael@0 38956 if (!hasSignificantCoefficent) {
michael@0 38957 bitsDecoded[index0]++;
michael@0 38958 bitsDecoded[index0 + oneRowDown]++;
michael@0 38959 bitsDecoded[index0 + twoRowsDown]++;
michael@0 38960 bitsDecoded[index0 + threeRowsDown]++;
michael@0 38961 continue; // next column
michael@0 38962 }
michael@0 38963 i1 = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
michael@0 38964 decoder.readBit(contexts, UNIFORM_CONTEXT);
michael@0 38965 if (i1 !== 0) {
michael@0 38966 i = i0 + i1;
michael@0 38967 index += i1 * width;
michael@0 38968 }
michael@0 38969
michael@0 38970 sign = this.decodeSignBit(i, j, index);
michael@0 38971 coefficentsSign[index] = sign;
michael@0 38972 coefficentsMagnitude[index] = 1;
michael@0 38973 this.setNeighborsSignificance(i, j, index);
michael@0 38974 processingFlags[index] |= firstMagnitudeBitMask;
michael@0 38975
michael@0 38976 index = index0;
michael@0 38977 for (var i2 = i0; i2 <= i; i2++, index += width) {
michael@0 38978 bitsDecoded[index]++;
michael@0 38979 }
michael@0 38980
michael@0 38981 i1++;
michael@0 38982 }
michael@0 38983 for (i = i0 + i1; i < iNext; i++, index += width) {
michael@0 38984 if (coefficentsMagnitude[index] ||
michael@0 38985 (processingFlags[index] & processedMask) !== 0) {
michael@0 38986 continue;
michael@0 38987 }
michael@0 38988
michael@0 38989 var contextLabel = labels[neighborsSignificance[index]];
michael@0 38990 var decision = decoder.readBit(contexts, contextLabel);
michael@0 38991 if (decision === 1) {
michael@0 38992 sign = this.decodeSignBit(i, j, index);
michael@0 38993 coefficentsSign[index] = sign;
michael@0 38994 coefficentsMagnitude[index] = 1;
michael@0 38995 this.setNeighborsSignificance(i, j, index);
michael@0 38996 processingFlags[index] |= firstMagnitudeBitMask;
michael@0 38997 }
michael@0 38998 bitsDecoded[index]++;
michael@0 38999 }
michael@0 39000 }
michael@0 39001 }
michael@0 39002 },
michael@0 39003 checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() {
michael@0 39004 var decoder = this.decoder;
michael@0 39005 var contexts = this.contexts;
michael@0 39006 var symbol = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 3) |
michael@0 39007 (decoder.readBit(contexts, UNIFORM_CONTEXT) << 2) |
michael@0 39008 (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
michael@0 39009 decoder.readBit(contexts, UNIFORM_CONTEXT);
michael@0 39010 if (symbol != 0xA) {
michael@0 39011 throw 'Invalid segmentation symbol';
michael@0 39012 }
michael@0 39013 }
michael@0 39014 };
michael@0 39015
michael@0 39016 return BitModel;
michael@0 39017 })();
michael@0 39018
michael@0 39019 // Section F, Discrete wavelet transformation
michael@0 39020 var Transform = (function TransformClosure() {
michael@0 39021 function Transform() {}
michael@0 39022
michael@0 39023 Transform.prototype.calculate =
michael@0 39024 function transformCalculate(subbands, u0, v0) {
michael@0 39025 var ll = subbands[0];
michael@0 39026 for (var i = 1, ii = subbands.length; i < ii; i++) {
michael@0 39027 ll = this.iterate(ll, subbands[i], u0, v0);
michael@0 39028 }
michael@0 39029 return ll;
michael@0 39030 };
michael@0 39031 Transform.prototype.extend = function extend(buffer, offset, size) {
michael@0 39032 // Section F.3.7 extending... using max extension of 4
michael@0 39033 var i1 = offset - 1, j1 = offset + 1;
michael@0 39034 var i2 = offset + size - 2, j2 = offset + size;
michael@0 39035 buffer[i1--] = buffer[j1++];
michael@0 39036 buffer[j2++] = buffer[i2--];
michael@0 39037 buffer[i1--] = buffer[j1++];
michael@0 39038 buffer[j2++] = buffer[i2--];
michael@0 39039 buffer[i1--] = buffer[j1++];
michael@0 39040 buffer[j2++] = buffer[i2--];
michael@0 39041 buffer[i1] = buffer[j1];
michael@0 39042 buffer[j2] = buffer[i2];
michael@0 39043 };
michael@0 39044 Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh,
michael@0 39045 u0, v0) {
michael@0 39046 var llWidth = ll.width, llHeight = ll.height, llItems = ll.items;
michael@0 39047 var width = hl_lh_hh.width;
michael@0 39048 var height = hl_lh_hh.height;
michael@0 39049 var items = hl_lh_hh.items;
michael@0 39050 var i, j, k, l, u, v;
michael@0 39051
michael@0 39052 // Interleave LL according to Section F.3.3
michael@0 39053 for (k = 0, i = 0; i < llHeight; i++) {
michael@0 39054 l = i * 2 * width;
michael@0 39055 for (j = 0; j < llWidth; j++, k++, l += 2) {
michael@0 39056 items[l] = llItems[k];
michael@0 39057 }
michael@0 39058 }
michael@0 39059 // The LL band is not needed anymore.
michael@0 39060 llItems = ll.items = null;
michael@0 39061
michael@0 39062 var bufferPadding = 4;
michael@0 39063 var rowBuffer = new Float32Array(width + 2 * bufferPadding);
michael@0 39064
michael@0 39065 // Section F.3.4 HOR_SR
michael@0 39066 if (width === 1) {
michael@0 39067 // if width = 1, when u0 even keep items as is, when odd divide by 2
michael@0 39068 if ((u0 & 1) !== 0) {
michael@0 39069 for (v = 0, k = 0; v < height; v++, k += width) {
michael@0 39070 items[k] *= 0.5;
michael@0 39071 }
michael@0 39072 }
michael@0 39073 } else {
michael@0 39074 for (v = 0, k = 0; v < height; v++, k += width) {
michael@0 39075 rowBuffer.set(items.subarray(k, k + width), bufferPadding);
michael@0 39076
michael@0 39077 this.extend(rowBuffer, bufferPadding, width);
michael@0 39078 this.filter(rowBuffer, bufferPadding, width);
michael@0 39079
michael@0 39080 items.set(
michael@0 39081 rowBuffer.subarray(bufferPadding, bufferPadding + width),
michael@0 39082 k);
michael@0 39083 }
michael@0 39084 }
michael@0 39085
michael@0 39086 // Accesses to the items array can take long, because it may not fit into
michael@0 39087 // CPU cache and has to be fetched from main memory. Since subsequent
michael@0 39088 // accesses to the items array are not local when reading columns, we
michael@0 39089 // have a cache miss every time. To reduce cache misses, get up to
michael@0 39090 // 'numBuffers' items at a time and store them into the individual
michael@0 39091 // buffers. The colBuffers should be small enough to fit into CPU cache.
michael@0 39092 var numBuffers = 16;
michael@0 39093 var colBuffers = [];
michael@0 39094 for (i = 0; i < numBuffers; i++) {
michael@0 39095 colBuffers.push(new Float32Array(height + 2 * bufferPadding));
michael@0 39096 }
michael@0 39097 var b, currentBuffer = 0;
michael@0 39098 ll = bufferPadding + height;
michael@0 39099
michael@0 39100 // Section F.3.5 VER_SR
michael@0 39101 if (height === 1) {
michael@0 39102 // if height = 1, when v0 even keep items as is, when odd divide by 2
michael@0 39103 if ((v0 & 1) !== 0) {
michael@0 39104 for (u = 0; u < width; u++) {
michael@0 39105 items[u] *= 0.5;
michael@0 39106 }
michael@0 39107 }
michael@0 39108 } else {
michael@0 39109 for (u = 0; u < width; u++) {
michael@0 39110 // if we ran out of buffers, copy several image columns at once
michael@0 39111 if (currentBuffer === 0) {
michael@0 39112 numBuffers = Math.min(width - u, numBuffers);
michael@0 39113 for (k = u, l = bufferPadding; l < ll; k += width, l++) {
michael@0 39114 for (b = 0; b < numBuffers; b++) {
michael@0 39115 colBuffers[b][l] = items[k + b];
michael@0 39116 }
michael@0 39117 }
michael@0 39118 currentBuffer = numBuffers;
michael@0 39119 }
michael@0 39120
michael@0 39121 currentBuffer--;
michael@0 39122 var buffer = colBuffers[currentBuffer];
michael@0 39123 this.extend(buffer, bufferPadding, height);
michael@0 39124 this.filter(buffer, bufferPadding, height);
michael@0 39125
michael@0 39126 // If this is last buffer in this group of buffers, flush all buffers.
michael@0 39127 if (currentBuffer === 0) {
michael@0 39128 k = u - numBuffers + 1;
michael@0 39129 for (l = bufferPadding; l < ll; k += width, l++) {
michael@0 39130 for (b = 0; b < numBuffers; b++) {
michael@0 39131 items[k + b] = colBuffers[b][l];
michael@0 39132 }
michael@0 39133 }
michael@0 39134 }
michael@0 39135 }
michael@0 39136 }
michael@0 39137
michael@0 39138 return {
michael@0 39139 width: width,
michael@0 39140 height: height,
michael@0 39141 items: items
michael@0 39142 };
michael@0 39143 };
michael@0 39144 return Transform;
michael@0 39145 })();
michael@0 39146
michael@0 39147 // Section 3.8.2 Irreversible 9-7 filter
michael@0 39148 var IrreversibleTransform = (function IrreversibleTransformClosure() {
michael@0 39149 function IrreversibleTransform() {
michael@0 39150 Transform.call(this);
michael@0 39151 }
michael@0 39152
michael@0 39153 IrreversibleTransform.prototype = Object.create(Transform.prototype);
michael@0 39154 IrreversibleTransform.prototype.filter =
michael@0 39155 function irreversibleTransformFilter(x, offset, length) {
michael@0 39156 var len = length >> 1;
michael@0 39157 offset = offset | 0;
michael@0 39158 var j, n, current, next;
michael@0 39159
michael@0 39160 var alpha = -1.586134342059924;
michael@0 39161 var beta = -0.052980118572961;
michael@0 39162 var gamma = 0.882911075530934;
michael@0 39163 var delta = 0.443506852043971;
michael@0 39164 var K = 1.230174104914001;
michael@0 39165 var K_ = 1 / K;
michael@0 39166
michael@0 39167 // step 1 is combined with step 3
michael@0 39168
michael@0 39169 // step 2
michael@0 39170 j = offset - 3;
michael@0 39171 for (n = len + 4; n--; j += 2) {
michael@0 39172 x[j] *= K_;
michael@0 39173 }
michael@0 39174
michael@0 39175 // step 1 & 3
michael@0 39176 j = offset - 2;
michael@0 39177 current = delta * x[j -1];
michael@0 39178 for (n = len + 3; n--; j += 2) {
michael@0 39179 next = delta * x[j + 1];
michael@0 39180 x[j] = K * x[j] - current - next;
michael@0 39181 if (n--) {
michael@0 39182 j += 2;
michael@0 39183 current = delta * x[j + 1];
michael@0 39184 x[j] = K * x[j] - current - next;
michael@0 39185 } else {
michael@0 39186 break;
michael@0 39187 }
michael@0 39188 }
michael@0 39189
michael@0 39190 // step 4
michael@0 39191 j = offset - 1;
michael@0 39192 current = gamma * x[j - 1];
michael@0 39193 for (n = len + 2; n--; j += 2) {
michael@0 39194 next = gamma * x[j + 1];
michael@0 39195 x[j] -= current + next;
michael@0 39196 if (n--) {
michael@0 39197 j += 2;
michael@0 39198 current = gamma * x[j + 1];
michael@0 39199 x[j] -= current + next;
michael@0 39200 } else {
michael@0 39201 break;
michael@0 39202 }
michael@0 39203 }
michael@0 39204
michael@0 39205 // step 5
michael@0 39206 j = offset;
michael@0 39207 current = beta * x[j - 1];
michael@0 39208 for (n = len + 1; n--; j += 2) {
michael@0 39209 next = beta * x[j + 1];
michael@0 39210 x[j] -= current + next;
michael@0 39211 if (n--) {
michael@0 39212 j += 2;
michael@0 39213 current = beta * x[j + 1];
michael@0 39214 x[j] -= current + next;
michael@0 39215 } else {
michael@0 39216 break;
michael@0 39217 }
michael@0 39218 }
michael@0 39219
michael@0 39220 // step 6
michael@0 39221 if (len !== 0) {
michael@0 39222 j = offset + 1;
michael@0 39223 current = alpha * x[j - 1];
michael@0 39224 for (n = len; n--; j += 2) {
michael@0 39225 next = alpha * x[j + 1];
michael@0 39226 x[j] -= current + next;
michael@0 39227 if (n--) {
michael@0 39228 j += 2;
michael@0 39229 current = alpha * x[j + 1];
michael@0 39230 x[j] -= current + next;
michael@0 39231 } else {
michael@0 39232 break;
michael@0 39233 }
michael@0 39234 }
michael@0 39235 }
michael@0 39236 };
michael@0 39237
michael@0 39238 return IrreversibleTransform;
michael@0 39239 })();
michael@0 39240
michael@0 39241 // Section 3.8.1 Reversible 5-3 filter
michael@0 39242 var ReversibleTransform = (function ReversibleTransformClosure() {
michael@0 39243 function ReversibleTransform() {
michael@0 39244 Transform.call(this);
michael@0 39245 }
michael@0 39246
michael@0 39247 ReversibleTransform.prototype = Object.create(Transform.prototype);
michael@0 39248 ReversibleTransform.prototype.filter =
michael@0 39249 function reversibleTransformFilter(x, offset, length) {
michael@0 39250 var len = length >> 1;
michael@0 39251 offset = offset | 0;
michael@0 39252 var j, n;
michael@0 39253
michael@0 39254 for (j = offset, n = len + 1; n--; j += 2) {
michael@0 39255 x[j] -= (x[j - 1] + x[j + 1] + 2) >> 2;
michael@0 39256 }
michael@0 39257
michael@0 39258 for (j = offset + 1, n = len; n--; j += 2) {
michael@0 39259 x[j] += (x[j - 1] + x[j + 1]) >> 1;
michael@0 39260 }
michael@0 39261 };
michael@0 39262
michael@0 39263 return ReversibleTransform;
michael@0 39264 })();
michael@0 39265
michael@0 39266 return JpxImage;
michael@0 39267 })();
michael@0 39268
michael@0 39269
michael@0 39270
michael@0 39271 var Jbig2Image = (function Jbig2ImageClosure() {
michael@0 39272 // Utility data structures
michael@0 39273 function ContextCache() {}
michael@0 39274
michael@0 39275 ContextCache.prototype = {
michael@0 39276 getContexts: function(id) {
michael@0 39277 if (id in this) {
michael@0 39278 return this[id];
michael@0 39279 }
michael@0 39280 return (this[id] = new Int8Array(1<<16));
michael@0 39281 }
michael@0 39282 };
michael@0 39283
michael@0 39284 function DecodingContext(data, start, end) {
michael@0 39285 this.data = data;
michael@0 39286 this.start = start;
michael@0 39287 this.end = end;
michael@0 39288 }
michael@0 39289
michael@0 39290 DecodingContext.prototype = {
michael@0 39291 get decoder() {
michael@0 39292 var decoder = new ArithmeticDecoder(this.data, this.start, this.end);
michael@0 39293 return shadow(this, 'decoder', decoder);
michael@0 39294 },
michael@0 39295 get contextCache() {
michael@0 39296 var cache = new ContextCache();
michael@0 39297 return shadow(this, 'contextCache', cache);
michael@0 39298 }
michael@0 39299 };
michael@0 39300
michael@0 39301 // Annex A. Arithmetic Integer Decoding Procedure
michael@0 39302 // A.2 Procedure for decoding values
michael@0 39303 function decodeInteger(contextCache, procedure, decoder) {
michael@0 39304 var contexts = contextCache.getContexts(procedure);
michael@0 39305
michael@0 39306 var prev = 1;
michael@0 39307 var state = 1, v = 0, s;
michael@0 39308 var toRead = 32, offset = 4436; // defaults for state 7
michael@0 39309 while (state) {
michael@0 39310 var bit = decoder.readBit(contexts, prev);
michael@0 39311 prev = (prev < 256 ? (prev << 1) | bit :
michael@0 39312 (((prev << 1) | bit) & 511) | 256);
michael@0 39313 switch (state) {
michael@0 39314 case 1:
michael@0 39315 s = !!bit;
michael@0 39316 break;
michael@0 39317 case 2:
michael@0 39318 if (bit) {
michael@0 39319 break;
michael@0 39320 }
michael@0 39321 state = 7;
michael@0 39322 toRead = 2;
michael@0 39323 offset = 0;
michael@0 39324 break;
michael@0 39325 case 3:
michael@0 39326 if (bit) {
michael@0 39327 break;
michael@0 39328 }
michael@0 39329 state = 7;
michael@0 39330 toRead = 4;
michael@0 39331 offset = 4;
michael@0 39332 break;
michael@0 39333 case 4:
michael@0 39334 if (bit) {
michael@0 39335 break;
michael@0 39336 }
michael@0 39337 state = 7;
michael@0 39338 toRead = 6;
michael@0 39339 offset = 20;
michael@0 39340 break;
michael@0 39341 case 5:
michael@0 39342 if (bit) {
michael@0 39343 break;
michael@0 39344 }
michael@0 39345 state = 7;
michael@0 39346 toRead = 8;
michael@0 39347 offset = 84;
michael@0 39348 break;
michael@0 39349 case 6:
michael@0 39350 if (bit) {
michael@0 39351 break;
michael@0 39352 }
michael@0 39353 state = 7;
michael@0 39354 toRead = 12;
michael@0 39355 offset = 340;
michael@0 39356 break;
michael@0 39357 default:
michael@0 39358 v = ((v << 1) | bit) >>> 0;
michael@0 39359 if (--toRead === 0) {
michael@0 39360 state = 0;
michael@0 39361 }
michael@0 39362 continue;
michael@0 39363 }
michael@0 39364 state++;
michael@0 39365 }
michael@0 39366 v += offset;
michael@0 39367 return (!s ? v : (v > 0 ? -v : null));
michael@0 39368 }
michael@0 39369
michael@0 39370 // A.3 The IAID decoding procedure
michael@0 39371 function decodeIAID(contextCache, decoder, codeLength) {
michael@0 39372 var contexts = contextCache.getContexts('IAID');
michael@0 39373
michael@0 39374 var prev = 1;
michael@0 39375 for (var i = 0; i < codeLength; i++) {
michael@0 39376 var bit = decoder.readBit(contexts, prev);
michael@0 39377 prev = (prev << 1) | bit;
michael@0 39378 }
michael@0 39379 if (codeLength < 31) {
michael@0 39380 return prev & ((1 << codeLength) - 1);
michael@0 39381 }
michael@0 39382 return prev & 0x7FFFFFFF;
michael@0 39383 }
michael@0 39384
michael@0 39385 // 7.3 Segment types
michael@0 39386 var SegmentTypes = [
michael@0 39387 'SymbolDictionary', null, null, null, 'IntermediateTextRegion', null,
michael@0 39388 'ImmediateTextRegion', 'ImmediateLosslessTextRegion', null, null, null,
michael@0 39389 null, null, null, null, null, 'patternDictionary', null, null, null,
michael@0 39390 'IntermediateHalftoneRegion', null, 'ImmediateHalftoneRegion',
michael@0 39391 'ImmediateLosslessHalftoneRegion', null, null, null, null, null, null, null,
michael@0 39392 null, null, null, null, null, 'IntermediateGenericRegion', null,
michael@0 39393 'ImmediateGenericRegion', 'ImmediateLosslessGenericRegion',
michael@0 39394 'IntermediateGenericRefinementRegion', null,
michael@0 39395 'ImmediateGenericRefinementRegion',
michael@0 39396 'ImmediateLosslessGenericRefinementRegion', null, null, null, null,
michael@0 39397 'PageInformation', 'EndOfPage', 'EndOfStripe', 'EndOfFile', 'Profiles',
michael@0 39398 'Tables', null, null, null, null, null, null, null, null,
michael@0 39399 'Extension'
michael@0 39400 ];
michael@0 39401
michael@0 39402 var CodingTemplates = [
michael@0 39403 [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1},
michael@0 39404 {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: 2, y: -1},
michael@0 39405 {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}],
michael@0 39406 [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: 2, y: -2},
michael@0 39407 {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1},
michael@0 39408 {x: 2, y: -1}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}],
michael@0 39409 [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1},
michael@0 39410 {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -2, y: 0},
michael@0 39411 {x: -1, y: 0}],
michael@0 39412 [{x: -3, y: -1}, {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1},
michael@0 39413 {x: 1, y: -1}, {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}]
michael@0 39414 ];
michael@0 39415
michael@0 39416 var RefinementTemplates = [
michael@0 39417 {
michael@0 39418 coding: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}],
michael@0 39419 reference: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}, {x: 0, y: 0},
michael@0 39420 {x: 1, y: 0}, {x: -1, y: 1}, {x: 0, y: 1}, {x: 1, y: 1}]
michael@0 39421 },
michael@0 39422 {
michael@0 39423 coding: [{x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}],
michael@0 39424 reference: [{x: 0, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, {x: 1, y: 0},
michael@0 39425 {x: 0, y: 1}, {x: 1, y: 1}]
michael@0 39426 }
michael@0 39427 ];
michael@0 39428
michael@0 39429 var ReusedContexts = [
michael@0 39430 0x1CD3, // '00111001101' (template) + '0011' (at),
michael@0 39431 0x079A, // '001111001101' + '0',
michael@0 39432 0x00E3, // '001110001' + '1',
michael@0 39433 0x018B // '011000101' + '1'
michael@0 39434 ];
michael@0 39435
michael@0 39436 var RefinementReusedContexts = [
michael@0 39437 0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference)
michael@0 39438 0x0008 // '0000' + '001000'
michael@0 39439 ];
michael@0 39440
michael@0 39441 // 6.2 Generic Region Decoding Procedure
michael@0 39442 function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at,
michael@0 39443 decodingContext) {
michael@0 39444 if (mmr) {
michael@0 39445 error('JBIG2 error: MMR encoding is not supported');
michael@0 39446 }
michael@0 39447
michael@0 39448 var useskip = !!skip;
michael@0 39449 var template = CodingTemplates[templateIndex].concat(at);
michael@0 39450
michael@0 39451 // Sorting is non-standard, and it is not required. But sorting increases
michael@0 39452 // the number of template bits that can be reused from the previous
michael@0 39453 // contextLabel in the main loop.
michael@0 39454 template.sort(function (a, b) {
michael@0 39455 return (a.y - b.y) || (a.x - b.x);
michael@0 39456 });
michael@0 39457
michael@0 39458 var templateLength = template.length;
michael@0 39459 var templateX = new Int8Array(templateLength);
michael@0 39460 var templateY = new Int8Array(templateLength);
michael@0 39461 var changingTemplateEntries = [];
michael@0 39462 var reuseMask = 0, minX = 0, maxX = 0, minY = 0;
michael@0 39463 var c, k;
michael@0 39464
michael@0 39465 for (k = 0; k < templateLength; k++) {
michael@0 39466 templateX[k] = template[k].x;
michael@0 39467 templateY[k] = template[k].y;
michael@0 39468 minX = Math.min(minX, template[k].x);
michael@0 39469 maxX = Math.max(maxX, template[k].x);
michael@0 39470 minY = Math.min(minY, template[k].y);
michael@0 39471 // Check if the template pixel appears in two consecutive context labels,
michael@0 39472 // so it can be reused. Otherwise, we add it to the list of changing
michael@0 39473 // template entries.
michael@0 39474 if (k < templateLength - 1 &&
michael@0 39475 template[k].y === template[k + 1].y &&
michael@0 39476 template[k].x === template[k + 1].x - 1) {
michael@0 39477 reuseMask |= 1 << (templateLength - 1 - k);
michael@0 39478 } else {
michael@0 39479 changingTemplateEntries.push(k);
michael@0 39480 }
michael@0 39481 }
michael@0 39482 var changingEntriesLength = changingTemplateEntries.length;
michael@0 39483
michael@0 39484 var changingTemplateX = new Int8Array(changingEntriesLength);
michael@0 39485 var changingTemplateY = new Int8Array(changingEntriesLength);
michael@0 39486 var changingTemplateBit = new Uint16Array(changingEntriesLength);
michael@0 39487 for (c = 0; c < changingEntriesLength; c++) {
michael@0 39488 k = changingTemplateEntries[c];
michael@0 39489 changingTemplateX[c] = template[k].x;
michael@0 39490 changingTemplateY[c] = template[k].y;
michael@0 39491 changingTemplateBit[c] = 1 << (templateLength - 1 - k);
michael@0 39492 }
michael@0 39493
michael@0 39494 // Get the safe bounding box edges from the width, height, minX, maxX, minY
michael@0 39495 var sbb_left = -minX;
michael@0 39496 var sbb_top = -minY;
michael@0 39497 var sbb_right = width - maxX;
michael@0 39498
michael@0 39499 var pseudoPixelContext = ReusedContexts[templateIndex];
michael@0 39500 var row = new Uint8Array(width);
michael@0 39501 var bitmap = [];
michael@0 39502
michael@0 39503 var decoder = decodingContext.decoder;
michael@0 39504 var contexts = decodingContext.contextCache.getContexts('GB');
michael@0 39505
michael@0 39506 var ltp = 0, j, i0, j0, contextLabel = 0, bit, shift;
michael@0 39507 for (var i = 0; i < height; i++) {
michael@0 39508 if (prediction) {
michael@0 39509 var sltp = decoder.readBit(contexts, pseudoPixelContext);
michael@0 39510 ltp ^= sltp;
michael@0 39511 if (ltp) {
michael@0 39512 bitmap.push(row); // duplicate previous row
michael@0 39513 continue;
michael@0 39514 }
michael@0 39515 }
michael@0 39516 row = new Uint8Array(row);
michael@0 39517 bitmap.push(row);
michael@0 39518 for (j = 0; j < width; j++) {
michael@0 39519 if (useskip && skip[i][j]) {
michael@0 39520 row[j] = 0;
michael@0 39521 continue;
michael@0 39522 }
michael@0 39523 // Are we in the middle of a scanline, so we can reuse contextLabel
michael@0 39524 // bits?
michael@0 39525 if (j >= sbb_left && j < sbb_right && i >= sbb_top) {
michael@0 39526 // If yes, we can just shift the bits that are reusable and only
michael@0 39527 // fetch the remaining ones.
michael@0 39528 contextLabel = (contextLabel << 1) & reuseMask;
michael@0 39529 for (k = 0; k < changingEntriesLength; k++) {
michael@0 39530 i0 = i + changingTemplateY[k];
michael@0 39531 j0 = j + changingTemplateX[k];
michael@0 39532 bit = bitmap[i0][j0];
michael@0 39533 if (bit) {
michael@0 39534 bit = changingTemplateBit[k];
michael@0 39535 contextLabel |= bit;
michael@0 39536 }
michael@0 39537 }
michael@0 39538 } else {
michael@0 39539 // compute the contextLabel from scratch
michael@0 39540 contextLabel = 0;
michael@0 39541 shift = templateLength - 1;
michael@0 39542 for (k = 0; k < templateLength; k++, shift--) {
michael@0 39543 j0 = j + templateX[k];
michael@0 39544 if (j0 >= 0 && j0 < width) {
michael@0 39545 i0 = i + templateY[k];
michael@0 39546 if (i0 >= 0) {
michael@0 39547 bit = bitmap[i0][j0];
michael@0 39548 if (bit) {
michael@0 39549 contextLabel |= bit << shift;
michael@0 39550 }
michael@0 39551 }
michael@0 39552 }
michael@0 39553 }
michael@0 39554 }
michael@0 39555 var pixel = decoder.readBit(contexts, contextLabel);
michael@0 39556 row[j] = pixel;
michael@0 39557 }
michael@0 39558 }
michael@0 39559 return bitmap;
michael@0 39560 }
michael@0 39561
michael@0 39562 // 6.3.2 Generic Refinement Region Decoding Procedure
michael@0 39563 function decodeRefinement(width, height, templateIndex, referenceBitmap,
michael@0 39564 offsetX, offsetY, prediction, at,
michael@0 39565 decodingContext) {
michael@0 39566 var codingTemplate = RefinementTemplates[templateIndex].coding;
michael@0 39567 if (templateIndex === 0) {
michael@0 39568 codingTemplate = codingTemplate.concat([at[0]]);
michael@0 39569 }
michael@0 39570 var codingTemplateLength = codingTemplate.length;
michael@0 39571 var codingTemplateX = new Int32Array(codingTemplateLength);
michael@0 39572 var codingTemplateY = new Int32Array(codingTemplateLength);
michael@0 39573 var k;
michael@0 39574 for (k = 0; k < codingTemplateLength; k++) {
michael@0 39575 codingTemplateX[k] = codingTemplate[k].x;
michael@0 39576 codingTemplateY[k] = codingTemplate[k].y;
michael@0 39577 }
michael@0 39578
michael@0 39579 var referenceTemplate = RefinementTemplates[templateIndex].reference;
michael@0 39580 if (templateIndex === 0) {
michael@0 39581 referenceTemplate = referenceTemplate.concat([at[1]]);
michael@0 39582 }
michael@0 39583 var referenceTemplateLength = referenceTemplate.length;
michael@0 39584 var referenceTemplateX = new Int32Array(referenceTemplateLength);
michael@0 39585 var referenceTemplateY = new Int32Array(referenceTemplateLength);
michael@0 39586 for (k = 0; k < referenceTemplateLength; k++) {
michael@0 39587 referenceTemplateX[k] = referenceTemplate[k].x;
michael@0 39588 referenceTemplateY[k] = referenceTemplate[k].y;
michael@0 39589 }
michael@0 39590 var referenceWidth = referenceBitmap[0].length;
michael@0 39591 var referenceHeight = referenceBitmap.length;
michael@0 39592
michael@0 39593 var pseudoPixelContext = RefinementReusedContexts[templateIndex];
michael@0 39594 var bitmap = [];
michael@0 39595
michael@0 39596 var decoder = decodingContext.decoder;
michael@0 39597 var contexts = decodingContext.contextCache.getContexts('GR');
michael@0 39598
michael@0 39599 var ltp = 0;
michael@0 39600 for (var i = 0; i < height; i++) {
michael@0 39601 if (prediction) {
michael@0 39602 var sltp = decoder.readBit(contexts, pseudoPixelContext);
michael@0 39603 ltp ^= sltp;
michael@0 39604 if (ltp) {
michael@0 39605 error('JBIG2 error: prediction is not supported');
michael@0 39606 }
michael@0 39607 }
michael@0 39608 var row = new Uint8Array(width);
michael@0 39609 bitmap.push(row);
michael@0 39610 for (var j = 0; j < width; j++) {
michael@0 39611 var i0, j0;
michael@0 39612 var contextLabel = 0;
michael@0 39613 for (k = 0; k < codingTemplateLength; k++) {
michael@0 39614 i0 = i + codingTemplateY[k];
michael@0 39615 j0 = j + codingTemplateX[k];
michael@0 39616 if (i0 < 0 || j0 < 0 || j0 >= width) {
michael@0 39617 contextLabel <<= 1; // out of bound pixel
michael@0 39618 } else {
michael@0 39619 contextLabel = (contextLabel << 1) | bitmap[i0][j0];
michael@0 39620 }
michael@0 39621 }
michael@0 39622 for (k = 0; k < referenceTemplateLength; k++) {
michael@0 39623 i0 = i + referenceTemplateY[k] + offsetY;
michael@0 39624 j0 = j + referenceTemplateX[k] + offsetX;
michael@0 39625 if (i0 < 0 || i0 >= referenceHeight || j0 < 0 ||
michael@0 39626 j0 >= referenceWidth) {
michael@0 39627 contextLabel <<= 1; // out of bound pixel
michael@0 39628 } else {
michael@0 39629 contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0];
michael@0 39630 }
michael@0 39631 }
michael@0 39632 var pixel = decoder.readBit(contexts, contextLabel);
michael@0 39633 row[j] = pixel;
michael@0 39634 }
michael@0 39635 }
michael@0 39636
michael@0 39637 return bitmap;
michael@0 39638 }
michael@0 39639
michael@0 39640 // 6.5.5 Decoding the symbol dictionary
michael@0 39641 function decodeSymbolDictionary(huffman, refinement, symbols,
michael@0 39642 numberOfNewSymbols, numberOfExportedSymbols,
michael@0 39643 huffmanTables, templateIndex, at,
michael@0 39644 refinementTemplateIndex, refinementAt,
michael@0 39645 decodingContext) {
michael@0 39646 if (huffman) {
michael@0 39647 error('JBIG2 error: huffman is not supported');
michael@0 39648 }
michael@0 39649
michael@0 39650 var newSymbols = [];
michael@0 39651 var currentHeight = 0;
michael@0 39652 var symbolCodeLength = log2(symbols.length + numberOfNewSymbols);
michael@0 39653
michael@0 39654 var decoder = decodingContext.decoder;
michael@0 39655 var contextCache = decodingContext.contextCache;
michael@0 39656
michael@0 39657 while (newSymbols.length < numberOfNewSymbols) {
michael@0 39658 var deltaHeight = decodeInteger(contextCache, 'IADH', decoder); // 6.5.6
michael@0 39659 currentHeight += deltaHeight;
michael@0 39660 var currentWidth = 0;
michael@0 39661 var totalWidth = 0;
michael@0 39662 while (true) {
michael@0 39663 var deltaWidth = decodeInteger(contextCache, 'IADW', decoder); // 6.5.7
michael@0 39664 if (deltaWidth === null) {
michael@0 39665 break; // OOB
michael@0 39666 }
michael@0 39667 currentWidth += deltaWidth;
michael@0 39668 totalWidth += currentWidth;
michael@0 39669 var bitmap;
michael@0 39670 if (refinement) {
michael@0 39671 // 6.5.8.2 Refinement/aggregate-coded symbol bitmap
michael@0 39672 var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder);
michael@0 39673 if (numberOfInstances > 1) {
michael@0 39674 bitmap = decodeTextRegion(huffman, refinement,
michael@0 39675 currentWidth, currentHeight, 0,
michael@0 39676 numberOfInstances, 1, //strip size
michael@0 39677 symbols.concat(newSymbols),
michael@0 39678 symbolCodeLength,
michael@0 39679 0, //transposed
michael@0 39680 0, //ds offset
michael@0 39681 1, //top left 7.4.3.1.1
michael@0 39682 0, //OR operator
michael@0 39683 huffmanTables,
michael@0 39684 refinementTemplateIndex, refinementAt,
michael@0 39685 decodingContext);
michael@0 39686 } else {
michael@0 39687 var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
michael@0 39688 var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3
michael@0 39689 var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4
michael@0 39690 var symbol = (symbolId < symbols.length ? symbols[symbolId] :
michael@0 39691 newSymbols[symbolId - symbols.length]);
michael@0 39692 bitmap = decodeRefinement(currentWidth, currentHeight,
michael@0 39693 refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt,
michael@0 39694 decodingContext);
michael@0 39695 }
michael@0 39696 } else {
michael@0 39697 // 6.5.8.1 Direct-coded symbol bitmap
michael@0 39698 bitmap = decodeBitmap(false, currentWidth, currentHeight,
michael@0 39699 templateIndex, false, null, at, decodingContext);
michael@0 39700 }
michael@0 39701 newSymbols.push(bitmap);
michael@0 39702 }
michael@0 39703 }
michael@0 39704 // 6.5.10 Exported symbols
michael@0 39705 var exportedSymbols = [];
michael@0 39706 var flags = [], currentFlag = false;
michael@0 39707 var totalSymbolsLength = symbols.length + numberOfNewSymbols;
michael@0 39708 while (flags.length < totalSymbolsLength) {
michael@0 39709 var runLength = decodeInteger(contextCache, 'IAEX', decoder);
michael@0 39710 while (runLength--) {
michael@0 39711 flags.push(currentFlag);
michael@0 39712 }
michael@0 39713 currentFlag = !currentFlag;
michael@0 39714 }
michael@0 39715 for (var i = 0, ii = symbols.length; i < ii; i++) {
michael@0 39716 if (flags[i]) {
michael@0 39717 exportedSymbols.push(symbols[i]);
michael@0 39718 }
michael@0 39719 }
michael@0 39720 for (var j = 0; j < numberOfNewSymbols; i++, j++) {
michael@0 39721 if (flags[i]) {
michael@0 39722 exportedSymbols.push(newSymbols[j]);
michael@0 39723 }
michael@0 39724 }
michael@0 39725 return exportedSymbols;
michael@0 39726 }
michael@0 39727
michael@0 39728 function decodeTextRegion(huffman, refinement, width, height,
michael@0 39729 defaultPixelValue, numberOfSymbolInstances,
michael@0 39730 stripSize, inputSymbols, symbolCodeLength,
michael@0 39731 transposed, dsOffset, referenceCorner,
michael@0 39732 combinationOperator, huffmanTables,
michael@0 39733 refinementTemplateIndex, refinementAt,
michael@0 39734 decodingContext) {
michael@0 39735 if (huffman) {
michael@0 39736 error('JBIG2 error: huffman is not supported');
michael@0 39737 }
michael@0 39738
michael@0 39739 // Prepare bitmap
michael@0 39740 var bitmap = [];
michael@0 39741 var i, row;
michael@0 39742 for (i = 0; i < height; i++) {
michael@0 39743 row = new Uint8Array(width);
michael@0 39744 if (defaultPixelValue) {
michael@0 39745 for (var j = 0; j < width; j++) {
michael@0 39746 row[j] = defaultPixelValue;
michael@0 39747 }
michael@0 39748 }
michael@0 39749 bitmap.push(row);
michael@0 39750 }
michael@0 39751
michael@0 39752 var decoder = decodingContext.decoder;
michael@0 39753 var contextCache = decodingContext.contextCache;
michael@0 39754 var stripT = -decodeInteger(contextCache, 'IADT', decoder); // 6.4.6
michael@0 39755 var firstS = 0;
michael@0 39756 i = 0;
michael@0 39757 while (i < numberOfSymbolInstances) {
michael@0 39758 var deltaT = decodeInteger(contextCache, 'IADT', decoder); // 6.4.6
michael@0 39759 stripT += deltaT;
michael@0 39760
michael@0 39761 var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder); // 6.4.7
michael@0 39762 firstS += deltaFirstS;
michael@0 39763 var currentS = firstS;
michael@0 39764 do {
michael@0 39765 var currentT = (stripSize == 1 ? 0 :
michael@0 39766 decodeInteger(contextCache, 'IAIT', decoder)); // 6.4.9
michael@0 39767 var t = stripSize * stripT + currentT;
michael@0 39768 var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
michael@0 39769 var applyRefinement = (refinement &&
michael@0 39770 decodeInteger(contextCache, 'IARI', decoder));
michael@0 39771 var symbolBitmap = inputSymbols[symbolId];
michael@0 39772 var symbolWidth = symbolBitmap[0].length;
michael@0 39773 var symbolHeight = symbolBitmap.length;
michael@0 39774 if (applyRefinement) {
michael@0 39775 var rdw = decodeInteger(contextCache, 'IARDW', decoder); // 6.4.11.1
michael@0 39776 var rdh = decodeInteger(contextCache, 'IARDH', decoder); // 6.4.11.2
michael@0 39777 var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3
michael@0 39778 var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4
michael@0 39779 symbolWidth += rdw;
michael@0 39780 symbolHeight += rdh;
michael@0 39781 symbolBitmap = decodeRefinement(symbolWidth, symbolHeight,
michael@0 39782 refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx,
michael@0 39783 (rdh >> 1) + rdy, false, refinementAt,
michael@0 39784 decodingContext);
michael@0 39785 }
michael@0 39786 var offsetT = t - ((referenceCorner & 1) ? 0 : symbolHeight);
michael@0 39787 var offsetS = currentS - ((referenceCorner & 2) ? symbolWidth : 0);
michael@0 39788 var s2, t2, symbolRow;
michael@0 39789 if (transposed) {
michael@0 39790 // Place Symbol Bitmap from T1,S1
michael@0 39791 for (s2 = 0; s2 < symbolHeight; s2++) {
michael@0 39792 row = bitmap[offsetS + s2];
michael@0 39793 if (!row) {
michael@0 39794 continue;
michael@0 39795 }
michael@0 39796 symbolRow = symbolBitmap[s2];
michael@0 39797 // To ignore Parts of Symbol bitmap which goes
michael@0 39798 // outside bitmap region
michael@0 39799 var maxWidth = Math.min(width - offsetT, symbolWidth);
michael@0 39800 switch (combinationOperator) {
michael@0 39801 case 0: // OR
michael@0 39802 for (t2 = 0; t2 < maxWidth; t2++) {
michael@0 39803 row[offsetT + t2] |= symbolRow[t2];
michael@0 39804 }
michael@0 39805 break;
michael@0 39806 case 2: // XOR
michael@0 39807 for (t2 = 0; t2 < maxWidth; t2++) {
michael@0 39808 row[offsetT + t2] ^= symbolRow[t2];
michael@0 39809 }
michael@0 39810 break;
michael@0 39811 default:
michael@0 39812 error('JBIG2 error: operator ' + combinationOperator +
michael@0 39813 ' is not supported');
michael@0 39814 }
michael@0 39815 }
michael@0 39816 currentS += symbolHeight - 1;
michael@0 39817 } else {
michael@0 39818 for (t2 = 0; t2 < symbolHeight; t2++) {
michael@0 39819 row = bitmap[offsetT + t2];
michael@0 39820 if (!row) {
michael@0 39821 continue;
michael@0 39822 }
michael@0 39823 symbolRow = symbolBitmap[t2];
michael@0 39824 switch (combinationOperator) {
michael@0 39825 case 0: // OR
michael@0 39826 for (s2 = 0; s2 < symbolWidth; s2++) {
michael@0 39827 row[offsetS + s2] |= symbolRow[s2];
michael@0 39828 }
michael@0 39829 break;
michael@0 39830 case 2: // XOR
michael@0 39831 for (s2 = 0; s2 < symbolWidth; s2++) {
michael@0 39832 row[offsetS + s2] ^= symbolRow[s2];
michael@0 39833 }
michael@0 39834 break;
michael@0 39835 default:
michael@0 39836 error('JBIG2 error: operator ' + combinationOperator +
michael@0 39837 ' is not supported');
michael@0 39838 }
michael@0 39839 }
michael@0 39840 currentS += symbolWidth - 1;
michael@0 39841 }
michael@0 39842 i++;
michael@0 39843 var deltaS = decodeInteger(contextCache, 'IADS', decoder); // 6.4.8
michael@0 39844 if (deltaS === null) {
michael@0 39845 break; // OOB
michael@0 39846 }
michael@0 39847 currentS += deltaS + dsOffset;
michael@0 39848 } while (true);
michael@0 39849 }
michael@0 39850 return bitmap;
michael@0 39851 }
michael@0 39852
michael@0 39853 function readSegmentHeader(data, start) {
michael@0 39854 var segmentHeader = {};
michael@0 39855 segmentHeader.number = readUint32(data, start);
michael@0 39856 var flags = data[start + 4];
michael@0 39857 var segmentType = flags & 0x3F;
michael@0 39858 if (!SegmentTypes[segmentType]) {
michael@0 39859 error('JBIG2 error: invalid segment type: ' + segmentType);
michael@0 39860 }
michael@0 39861 segmentHeader.type = segmentType;
michael@0 39862 segmentHeader.typeName = SegmentTypes[segmentType];
michael@0 39863 segmentHeader.deferredNonRetain = !!(flags & 0x80);
michael@0 39864
michael@0 39865 var pageAssociationFieldSize = !!(flags & 0x40);
michael@0 39866 var referredFlags = data[start + 5];
michael@0 39867 var referredToCount = (referredFlags >> 5) & 7;
michael@0 39868 var retainBits = [referredFlags & 31];
michael@0 39869 var position = start + 6;
michael@0 39870 if (referredFlags == 7) {
michael@0 39871 referredToCount = readUint32(data, position - 1) & 0x1FFFFFFF;
michael@0 39872 position += 3;
michael@0 39873 var bytes = (referredToCount + 7) >> 3;
michael@0 39874 retainBits[0] = data[position++];
michael@0 39875 while (--bytes > 0) {
michael@0 39876 retainBits.push(data[position++]);
michael@0 39877 }
michael@0 39878 } else if (referredFlags == 5 || referredFlags == 6) {
michael@0 39879 error('JBIG2 error: invalid referred-to flags');
michael@0 39880 }
michael@0 39881
michael@0 39882 segmentHeader.retainBits = retainBits;
michael@0 39883 var referredToSegmentNumberSize = (segmentHeader.number <= 256 ? 1 :
michael@0 39884 (segmentHeader.number <= 65536 ? 2 : 4));
michael@0 39885 var referredTo = [];
michael@0 39886 var i, ii;
michael@0 39887 for (i = 0; i < referredToCount; i++) {
michael@0 39888 var number = (referredToSegmentNumberSize == 1 ? data[position] :
michael@0 39889 (referredToSegmentNumberSize == 2 ? readUint16(data, position) :
michael@0 39890 readUint32(data, position)));
michael@0 39891 referredTo.push(number);
michael@0 39892 position += referredToSegmentNumberSize;
michael@0 39893 }
michael@0 39894 segmentHeader.referredTo = referredTo;
michael@0 39895 if (!pageAssociationFieldSize) {
michael@0 39896 segmentHeader.pageAssociation = data[position++];
michael@0 39897 } else {
michael@0 39898 segmentHeader.pageAssociation = readUint32(data, position);
michael@0 39899 position += 4;
michael@0 39900 }
michael@0 39901 segmentHeader.length = readUint32(data, position);
michael@0 39902 position += 4;
michael@0 39903
michael@0 39904 if (segmentHeader.length == 0xFFFFFFFF) {
michael@0 39905 // 7.2.7 Segment data length, unknown segment length
michael@0 39906 if (segmentType === 38) { // ImmediateGenericRegion
michael@0 39907 var genericRegionInfo = readRegionSegmentInformation(data, position);
michael@0 39908 var genericRegionSegmentFlags = data[position +
michael@0 39909 RegionSegmentInformationFieldLength];
michael@0 39910 var genericRegionMmr = !!(genericRegionSegmentFlags & 1);
michael@0 39911 // searching for the segment end
michael@0 39912 var searchPatternLength = 6;
michael@0 39913 var searchPattern = new Uint8Array(searchPatternLength);
michael@0 39914 if (!genericRegionMmr) {
michael@0 39915 searchPattern[0] = 0xFF;
michael@0 39916 searchPattern[1] = 0xAC;
michael@0 39917 }
michael@0 39918 searchPattern[2] = (genericRegionInfo.height >>> 24) & 0xFF;
michael@0 39919 searchPattern[3] = (genericRegionInfo.height >> 16) & 0xFF;
michael@0 39920 searchPattern[4] = (genericRegionInfo.height >> 8) & 0xFF;
michael@0 39921 searchPattern[5] = genericRegionInfo.height & 0xFF;
michael@0 39922 for (i = position, ii = data.length; i < ii; i++) {
michael@0 39923 var j = 0;
michael@0 39924 while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
michael@0 39925 j++;
michael@0 39926 }
michael@0 39927 if (j == searchPatternLength) {
michael@0 39928 segmentHeader.length = i + searchPatternLength;
michael@0 39929 break;
michael@0 39930 }
michael@0 39931 }
michael@0 39932 if (segmentHeader.length == 0xFFFFFFFF) {
michael@0 39933 error('JBIG2 error: segment end was not found');
michael@0 39934 }
michael@0 39935 } else {
michael@0 39936 error('JBIG2 error: invalid unknown segment length');
michael@0 39937 }
michael@0 39938 }
michael@0 39939 segmentHeader.headerEnd = position;
michael@0 39940 return segmentHeader;
michael@0 39941 }
michael@0 39942
michael@0 39943 function readSegments(header, data, start, end) {
michael@0 39944 var segments = [];
michael@0 39945 var position = start;
michael@0 39946 while (position < end) {
michael@0 39947 var segmentHeader = readSegmentHeader(data, position);
michael@0 39948 position = segmentHeader.headerEnd;
michael@0 39949 var segment = {
michael@0 39950 header: segmentHeader,
michael@0 39951 data: data
michael@0 39952 };
michael@0 39953 if (!header.randomAccess) {
michael@0 39954 segment.start = position;
michael@0 39955 position += segmentHeader.length;
michael@0 39956 segment.end = position;
michael@0 39957 }
michael@0 39958 segments.push(segment);
michael@0 39959 if (segmentHeader.type == 51) {
michael@0 39960 break; // end of file is found
michael@0 39961 }
michael@0 39962 }
michael@0 39963 if (header.randomAccess) {
michael@0 39964 for (var i = 0, ii = segments.length; i < ii; i++) {
michael@0 39965 segments[i].start = position;
michael@0 39966 position += segments[i].header.length;
michael@0 39967 segments[i].end = position;
michael@0 39968 }
michael@0 39969 }
michael@0 39970 return segments;
michael@0 39971 }
michael@0 39972
michael@0 39973 // 7.4.1 Region segment information field
michael@0 39974 function readRegionSegmentInformation(data, start) {
michael@0 39975 return {
michael@0 39976 width: readUint32(data, start),
michael@0 39977 height: readUint32(data, start + 4),
michael@0 39978 x: readUint32(data, start + 8),
michael@0 39979 y: readUint32(data, start + 12),
michael@0 39980 combinationOperator: data[start + 16] & 7
michael@0 39981 };
michael@0 39982 }
michael@0 39983 var RegionSegmentInformationFieldLength = 17;
michael@0 39984
michael@0 39985 function processSegment(segment, visitor) {
michael@0 39986 var header = segment.header;
michael@0 39987
michael@0 39988 var data = segment.data, position = segment.start, end = segment.end;
michael@0 39989 var args, at, i, atLength;
michael@0 39990 switch (header.type) {
michael@0 39991 case 0: // SymbolDictionary
michael@0 39992 // 7.4.2 Symbol dictionary segment syntax
michael@0 39993 var dictionary = {};
michael@0 39994 var dictionaryFlags = readUint16(data, position); // 7.4.2.1.1
michael@0 39995 dictionary.huffman = !!(dictionaryFlags & 1);
michael@0 39996 dictionary.refinement = !!(dictionaryFlags & 2);
michael@0 39997 dictionary.huffmanDHSelector = (dictionaryFlags >> 2) & 3;
michael@0 39998 dictionary.huffmanDWSelector = (dictionaryFlags >> 4) & 3;
michael@0 39999 dictionary.bitmapSizeSelector = (dictionaryFlags >> 6) & 1;
michael@0 40000 dictionary.aggregationInstancesSelector = (dictionaryFlags >> 7) & 1;
michael@0 40001 dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);
michael@0 40002 dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);
michael@0 40003 dictionary.template = (dictionaryFlags >> 10) & 3;
michael@0 40004 dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1;
michael@0 40005 position += 2;
michael@0 40006 if (!dictionary.huffman) {
michael@0 40007 atLength = dictionary.template === 0 ? 4 : 1;
michael@0 40008 at = [];
michael@0 40009 for (i = 0; i < atLength; i++) {
michael@0 40010 at.push({
michael@0 40011 x: readInt8(data, position),
michael@0 40012 y: readInt8(data, position + 1)
michael@0 40013 });
michael@0 40014 position += 2;
michael@0 40015 }
michael@0 40016 dictionary.at = at;
michael@0 40017 }
michael@0 40018 if (dictionary.refinement && !dictionary.refinementTemplate) {
michael@0 40019 at = [];
michael@0 40020 for (i = 0; i < 2; i++) {
michael@0 40021 at.push({
michael@0 40022 x: readInt8(data, position),
michael@0 40023 y: readInt8(data, position + 1)
michael@0 40024 });
michael@0 40025 position += 2;
michael@0 40026 }
michael@0 40027 dictionary.refinementAt = at;
michael@0 40028 }
michael@0 40029 dictionary.numberOfExportedSymbols = readUint32(data, position);
michael@0 40030 position += 4;
michael@0 40031 dictionary.numberOfNewSymbols = readUint32(data, position);
michael@0 40032 position += 4;
michael@0 40033 args = [dictionary, header.number, header.referredTo,
michael@0 40034 data, position, end];
michael@0 40035 break;
michael@0 40036 case 6: // ImmediateTextRegion
michael@0 40037 case 7: // ImmediateLosslessTextRegion
michael@0 40038 var textRegion = {};
michael@0 40039 textRegion.info = readRegionSegmentInformation(data, position);
michael@0 40040 position += RegionSegmentInformationFieldLength;
michael@0 40041 var textRegionSegmentFlags = readUint16(data, position);
michael@0 40042 position += 2;
michael@0 40043 textRegion.huffman = !!(textRegionSegmentFlags & 1);
michael@0 40044 textRegion.refinement = !!(textRegionSegmentFlags & 2);
michael@0 40045 textRegion.stripSize = 1 << ((textRegionSegmentFlags >> 2) & 3);
michael@0 40046 textRegion.referenceCorner = (textRegionSegmentFlags >> 4) & 3;
michael@0 40047 textRegion.transposed = !!(textRegionSegmentFlags & 64);
michael@0 40048 textRegion.combinationOperator = (textRegionSegmentFlags >> 7) & 3;
michael@0 40049 textRegion.defaultPixelValue = (textRegionSegmentFlags >> 9) & 1;
michael@0 40050 textRegion.dsOffset = (textRegionSegmentFlags << 17) >> 27;
michael@0 40051 textRegion.refinementTemplate = (textRegionSegmentFlags >> 15) & 1;
michael@0 40052 if (textRegion.huffman) {
michael@0 40053 var textRegionHuffmanFlags = readUint16(data, position);
michael@0 40054 position += 2;
michael@0 40055 textRegion.huffmanFS = (textRegionHuffmanFlags) & 3;
michael@0 40056 textRegion.huffmanDS = (textRegionHuffmanFlags >> 2) & 3;
michael@0 40057 textRegion.huffmanDT = (textRegionHuffmanFlags >> 4) & 3;
michael@0 40058 textRegion.huffmanRefinementDW = (textRegionHuffmanFlags >> 6) & 3;
michael@0 40059 textRegion.huffmanRefinementDH = (textRegionHuffmanFlags >> 8) & 3;
michael@0 40060 textRegion.huffmanRefinementDX = (textRegionHuffmanFlags >> 10) & 3;
michael@0 40061 textRegion.huffmanRefinementDY = (textRegionHuffmanFlags >> 12) & 3;
michael@0 40062 textRegion.huffmanRefinementSizeSelector =
michael@0 40063 !!(textRegionHuffmanFlags & 14);
michael@0 40064 }
michael@0 40065 if (textRegion.refinement && !textRegion.refinementTemplate) {
michael@0 40066 at = [];
michael@0 40067 for (i = 0; i < 2; i++) {
michael@0 40068 at.push({
michael@0 40069 x: readInt8(data, position),
michael@0 40070 y: readInt8(data, position + 1)
michael@0 40071 });
michael@0 40072 position += 2;
michael@0 40073 }
michael@0 40074 textRegion.refinementAt = at;
michael@0 40075 }
michael@0 40076 textRegion.numberOfSymbolInstances = readUint32(data, position);
michael@0 40077 position += 4;
michael@0 40078 // TODO 7.4.3.1.7 Symbol ID Huffman table decoding
michael@0 40079 if (textRegion.huffman) {
michael@0 40080 error('JBIG2 error: huffman is not supported');
michael@0 40081 }
michael@0 40082 args = [textRegion, header.referredTo, data, position, end];
michael@0 40083 break;
michael@0 40084 case 38: // ImmediateGenericRegion
michael@0 40085 case 39: // ImmediateLosslessGenericRegion
michael@0 40086 var genericRegion = {};
michael@0 40087 genericRegion.info = readRegionSegmentInformation(data, position);
michael@0 40088 position += RegionSegmentInformationFieldLength;
michael@0 40089 var genericRegionSegmentFlags = data[position++];
michael@0 40090 genericRegion.mmr = !!(genericRegionSegmentFlags & 1);
michael@0 40091 genericRegion.template = (genericRegionSegmentFlags >> 1) & 3;
michael@0 40092 genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
michael@0 40093 if (!genericRegion.mmr) {
michael@0 40094 atLength = genericRegion.template === 0 ? 4 : 1;
michael@0 40095 at = [];
michael@0 40096 for (i = 0; i < atLength; i++) {
michael@0 40097 at.push({
michael@0 40098 x: readInt8(data, position),
michael@0 40099 y: readInt8(data, position + 1)
michael@0 40100 });
michael@0 40101 position += 2;
michael@0 40102 }
michael@0 40103 genericRegion.at = at;
michael@0 40104 }
michael@0 40105 args = [genericRegion, data, position, end];
michael@0 40106 break;
michael@0 40107 case 48: // PageInformation
michael@0 40108 var pageInfo = {
michael@0 40109 width: readUint32(data, position),
michael@0 40110 height: readUint32(data, position + 4),
michael@0 40111 resolutionX: readUint32(data, position + 8),
michael@0 40112 resolutionY: readUint32(data, position + 12)
michael@0 40113 };
michael@0 40114 if (pageInfo.height == 0xFFFFFFFF) {
michael@0 40115 delete pageInfo.height;
michael@0 40116 }
michael@0 40117 var pageSegmentFlags = data[position + 16];
michael@0 40118 var pageStripingInformatiom = readUint16(data, position + 17);
michael@0 40119 pageInfo.lossless = !!(pageSegmentFlags & 1);
michael@0 40120 pageInfo.refinement = !!(pageSegmentFlags & 2);
michael@0 40121 pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1;
michael@0 40122 pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3;
michael@0 40123 pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
michael@0 40124 pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
michael@0 40125 args = [pageInfo];
michael@0 40126 break;
michael@0 40127 case 49: // EndOfPage
michael@0 40128 break;
michael@0 40129 case 50: // EndOfStripe
michael@0 40130 break;
michael@0 40131 case 51: // EndOfFile
michael@0 40132 break;
michael@0 40133 case 62: // 7.4.15 defines 2 extension types which
michael@0 40134 // are comments and can be ignored.
michael@0 40135 break;
michael@0 40136 default:
michael@0 40137 error('JBIG2 error: segment type ' + header.typeName + '(' +
michael@0 40138 header.type + ') is not implemented');
michael@0 40139 }
michael@0 40140 var callbackName = 'on' + header.typeName;
michael@0 40141 if (callbackName in visitor) {
michael@0 40142 visitor[callbackName].apply(visitor, args);
michael@0 40143 }
michael@0 40144 }
michael@0 40145
michael@0 40146 function processSegments(segments, visitor) {
michael@0 40147 for (var i = 0, ii = segments.length; i < ii; i++) {
michael@0 40148 processSegment(segments[i], visitor);
michael@0 40149 }
michael@0 40150 }
michael@0 40151
michael@0 40152 function parseJbig2(data, start, end) {
michael@0 40153 var position = start;
michael@0 40154 if (data[position] != 0x97 || data[position + 1] != 0x4A ||
michael@0 40155 data[position + 2] != 0x42 || data[position + 3] != 0x32 ||
michael@0 40156 data[position + 4] != 0x0D || data[position + 5] != 0x0A ||
michael@0 40157 data[position + 6] != 0x1A || data[position + 7] != 0x0A) {
michael@0 40158 error('JBIG2 error: invalid header');
michael@0 40159 }
michael@0 40160 var header = {};
michael@0 40161 position += 8;
michael@0 40162 var flags = data[position++];
michael@0 40163 header.randomAccess = !(flags & 1);
michael@0 40164 if (!(flags & 2)) {
michael@0 40165 header.numberOfPages = readUint32(data, position);
michael@0 40166 position += 4;
michael@0 40167 }
michael@0 40168 var segments = readSegments(header, data, position, end);
michael@0 40169 error('Not implemented');
michael@0 40170 // processSegments(segments, new SimpleSegmentVisitor());
michael@0 40171 }
michael@0 40172
michael@0 40173 function parseJbig2Chunks(chunks) {
michael@0 40174 var visitor = new SimpleSegmentVisitor();
michael@0 40175 for (var i = 0, ii = chunks.length; i < ii; i++) {
michael@0 40176 var chunk = chunks[i];
michael@0 40177 var segments = readSegments({}, chunk.data, chunk.start, chunk.end);
michael@0 40178 processSegments(segments, visitor);
michael@0 40179 }
michael@0 40180 return visitor.buffer;
michael@0 40181 }
michael@0 40182
michael@0 40183 function SimpleSegmentVisitor() {}
michael@0 40184
michael@0 40185 SimpleSegmentVisitor.prototype = {
michael@0 40186 onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) {
michael@0 40187 this.currentPageInfo = info;
michael@0 40188 var rowSize = (info.width + 7) >> 3;
michael@0 40189 var buffer = new Uint8Array(rowSize * info.height);
michael@0 40190 // The contents of ArrayBuffers are initialized to 0.
michael@0 40191 // Fill the buffer with 0xFF only if info.defaultPixelValue is set
michael@0 40192 if (info.defaultPixelValue) {
michael@0 40193 for (var i = 0, ii = buffer.length; i < ii; i++) {
michael@0 40194 buffer[i] = 0xFF;
michael@0 40195 }
michael@0 40196 }
michael@0 40197 this.buffer = buffer;
michael@0 40198 },
michael@0 40199 drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) {
michael@0 40200 var pageInfo = this.currentPageInfo;
michael@0 40201 var width = regionInfo.width, height = regionInfo.height;
michael@0 40202 var rowSize = (pageInfo.width + 7) >> 3;
michael@0 40203 var combinationOperator = pageInfo.combinationOperatorOverride ?
michael@0 40204 regionInfo.combinationOperator : pageInfo.combinationOperator;
michael@0 40205 var buffer = this.buffer;
michael@0 40206 var mask0 = 128 >> (regionInfo.x & 7);
michael@0 40207 var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
michael@0 40208 var i, j, mask, offset;
michael@0 40209 switch (combinationOperator) {
michael@0 40210 case 0: // OR
michael@0 40211 for (i = 0; i < height; i++) {
michael@0 40212 mask = mask0;
michael@0 40213 offset = offset0;
michael@0 40214 for (j = 0; j < width; j++) {
michael@0 40215 if (bitmap[i][j]) {
michael@0 40216 buffer[offset] |= mask;
michael@0 40217 }
michael@0 40218 mask >>= 1;
michael@0 40219 if (!mask) {
michael@0 40220 mask = 128;
michael@0 40221 offset++;
michael@0 40222 }
michael@0 40223 }
michael@0 40224 offset0 += rowSize;
michael@0 40225 }
michael@0 40226 break;
michael@0 40227 case 2: // XOR
michael@0 40228 for (i = 0; i < height; i++) {
michael@0 40229 mask = mask0;
michael@0 40230 offset = offset0;
michael@0 40231 for (j = 0; j < width; j++) {
michael@0 40232 if (bitmap[i][j]) {
michael@0 40233 buffer[offset] ^= mask;
michael@0 40234 }
michael@0 40235 mask >>= 1;
michael@0 40236 if (!mask) {
michael@0 40237 mask = 128;
michael@0 40238 offset++;
michael@0 40239 }
michael@0 40240 }
michael@0 40241 offset0 += rowSize;
michael@0 40242 }
michael@0 40243 break;
michael@0 40244 default:
michael@0 40245 error('JBIG2 error: operator ' + combinationOperator +
michael@0 40246 ' is not supported');
michael@0 40247 }
michael@0 40248 },
michael@0 40249 onImmediateGenericRegion:
michael@0 40250 function SimpleSegmentVisitor_onImmediateGenericRegion(region, data,
michael@0 40251 start, end) {
michael@0 40252 var regionInfo = region.info;
michael@0 40253 var decodingContext = new DecodingContext(data, start, end);
michael@0 40254 var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height,
michael@0 40255 region.template, region.prediction, null,
michael@0 40256 region.at, decodingContext);
michael@0 40257 this.drawBitmap(regionInfo, bitmap);
michael@0 40258 },
michael@0 40259 onImmediateLosslessGenericRegion:
michael@0 40260 function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() {
michael@0 40261 this.onImmediateGenericRegion.apply(this, arguments);
michael@0 40262 },
michael@0 40263 onSymbolDictionary:
michael@0 40264 function SimpleSegmentVisitor_onSymbolDictionary(dictionary,
michael@0 40265 currentSegment,
michael@0 40266 referredSegments,
michael@0 40267 data, start, end) {
michael@0 40268 var huffmanTables;
michael@0 40269 if (dictionary.huffman) {
michael@0 40270 error('JBIG2 error: huffman is not supported');
michael@0 40271 }
michael@0 40272
michael@0 40273 // Combines exported symbols from all referred segments
michael@0 40274 var symbols = this.symbols;
michael@0 40275 if (!symbols) {
michael@0 40276 this.symbols = symbols = {};
michael@0 40277 }
michael@0 40278
michael@0 40279 var inputSymbols = [];
michael@0 40280 for (var i = 0, ii = referredSegments.length; i < ii; i++) {
michael@0 40281 inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]);
michael@0 40282 }
michael@0 40283
michael@0 40284 var decodingContext = new DecodingContext(data, start, end);
michael@0 40285 symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman,
michael@0 40286 dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols,
michael@0 40287 dictionary.numberOfExportedSymbols, huffmanTables,
michael@0 40288 dictionary.template, dictionary.at,
michael@0 40289 dictionary.refinementTemplate, dictionary.refinementAt,
michael@0 40290 decodingContext);
michael@0 40291 },
michael@0 40292 onImmediateTextRegion:
michael@0 40293 function SimpleSegmentVisitor_onImmediateTextRegion(region,
michael@0 40294 referredSegments,
michael@0 40295 data, start, end) {
michael@0 40296 var regionInfo = region.info;
michael@0 40297 var huffmanTables;
michael@0 40298
michael@0 40299 // Combines exported symbols from all referred segments
michael@0 40300 var symbols = this.symbols;
michael@0 40301 var inputSymbols = [];
michael@0 40302 for (var i = 0, ii = referredSegments.length; i < ii; i++) {
michael@0 40303 inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]);
michael@0 40304 }
michael@0 40305 var symbolCodeLength = log2(inputSymbols.length);
michael@0 40306
michael@0 40307 var decodingContext = new DecodingContext(data, start, end);
michael@0 40308 var bitmap = decodeTextRegion(region.huffman, region.refinement,
michael@0 40309 regionInfo.width, regionInfo.height, region.defaultPixelValue,
michael@0 40310 region.numberOfSymbolInstances, region.stripSize, inputSymbols,
michael@0 40311 symbolCodeLength, region.transposed, region.dsOffset,
michael@0 40312 region.referenceCorner, region.combinationOperator, huffmanTables,
michael@0 40313 region.refinementTemplate, region.refinementAt, decodingContext);
michael@0 40314 this.drawBitmap(regionInfo, bitmap);
michael@0 40315 },
michael@0 40316 onImmediateLosslessTextRegion:
michael@0 40317 function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
michael@0 40318 this.onImmediateTextRegion.apply(this, arguments);
michael@0 40319 }
michael@0 40320 };
michael@0 40321
michael@0 40322 function Jbig2Image() {}
michael@0 40323
michael@0 40324 Jbig2Image.prototype = {
michael@0 40325 parseChunks: function Jbig2Image_parseChunks(chunks) {
michael@0 40326 return parseJbig2Chunks(chunks);
michael@0 40327 }
michael@0 40328 };
michael@0 40329
michael@0 40330 return Jbig2Image;
michael@0 40331 })();
michael@0 40332
michael@0 40333
michael@0 40334 var bidi = PDFJS.bidi = (function bidiClosure() {
michael@0 40335 // Character types for symbols from 0000 to 00FF.
michael@0 40336 var baseTypes = [
michael@0 40337 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS',
michael@0 40338 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
michael@0 40339 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON',
michael@0 40340 'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN',
michael@0 40341 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON',
michael@0 40342 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
michael@0 40343 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON',
michael@0 40344 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
michael@0 40345 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
michael@0 40346 'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN',
michael@0 40347 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
michael@0 40348 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
michael@0 40349 'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON',
michael@0 40350 'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON',
michael@0 40351 'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
michael@0 40352 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
michael@0 40353 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
michael@0 40354 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
michael@0 40355 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
michael@0 40356 ];
michael@0 40357
michael@0 40358 // Character types for symbols from 0600 to 06FF
michael@0 40359 var arabicTypes = [
michael@0 40360 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40361 'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL',
michael@0 40362 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40363 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40364 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40365 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40366 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
michael@0 40367 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL',
michael@0 40368 'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN',
michael@0 40369 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL',
michael@0 40370 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40371 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40372 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40373 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40374 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40375 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40376 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40377 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40378 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
michael@0 40379 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM',
michael@0 40380 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
michael@0 40381 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
michael@0 40382 ];
michael@0 40383
michael@0 40384 function isOdd(i) {
michael@0 40385 return (i & 1) !== 0;
michael@0 40386 }
michael@0 40387
michael@0 40388 function isEven(i) {
michael@0 40389 return (i & 1) === 0;
michael@0 40390 }
michael@0 40391
michael@0 40392 function findUnequal(arr, start, value) {
michael@0 40393 for (var j = start, jj = arr.length; j < jj; ++j) {
michael@0 40394 if (arr[j] != value) {
michael@0 40395 return j;
michael@0 40396 }
michael@0 40397 }
michael@0 40398 return j;
michael@0 40399 }
michael@0 40400
michael@0 40401 function setValues(arr, start, end, value) {
michael@0 40402 for (var j = start; j < end; ++j) {
michael@0 40403 arr[j] = value;
michael@0 40404 }
michael@0 40405 }
michael@0 40406
michael@0 40407 function reverseValues(arr, start, end) {
michael@0 40408 for (var i = start, j = end - 1; i < j; ++i, --j) {
michael@0 40409 var temp = arr[i];
michael@0 40410 arr[i] = arr[j];
michael@0 40411 arr[j] = temp;
michael@0 40412 }
michael@0 40413 }
michael@0 40414
michael@0 40415 function createBidiText(str, isLTR, vertical) {
michael@0 40416 return {
michael@0 40417 str: str,
michael@0 40418 dir: (vertical ? 'ttb' : (isLTR ? 'ltr' : 'rtl'))
michael@0 40419 };
michael@0 40420 }
michael@0 40421
michael@0 40422 // These are used in bidi(), which is called frequently. We re-use them on
michael@0 40423 // each call to avoid unnecessary allocations.
michael@0 40424 var chars = [];
michael@0 40425 var types = [];
michael@0 40426
michael@0 40427 function bidi(str, startLevel, vertical) {
michael@0 40428 var isLTR = true;
michael@0 40429 var strLength = str.length;
michael@0 40430 if (strLength === 0 || vertical) {
michael@0 40431 return createBidiText(str, isLTR, vertical);
michael@0 40432 }
michael@0 40433
michael@0 40434 // Get types and fill arrays
michael@0 40435 chars.length = 0;
michael@0 40436 types.length = 0;
michael@0 40437 var numBidi = 0;
michael@0 40438
michael@0 40439 var i, ii;
michael@0 40440 for (i = 0; i < strLength; ++i) {
michael@0 40441 chars[i] = str.charAt(i);
michael@0 40442
michael@0 40443 var charCode = str.charCodeAt(i);
michael@0 40444 var charType = 'L';
michael@0 40445 if (charCode <= 0x00ff) {
michael@0 40446 charType = baseTypes[charCode];
michael@0 40447 } else if (0x0590 <= charCode && charCode <= 0x05f4) {
michael@0 40448 charType = 'R';
michael@0 40449 } else if (0x0600 <= charCode && charCode <= 0x06ff) {
michael@0 40450 charType = arabicTypes[charCode & 0xff];
michael@0 40451 } else if (0x0700 <= charCode && charCode <= 0x08AC) {
michael@0 40452 charType = 'AL';
michael@0 40453 }
michael@0 40454 if (charType == 'R' || charType == 'AL' || charType == 'AN') {
michael@0 40455 numBidi++;
michael@0 40456 }
michael@0 40457 types[i] = charType;
michael@0 40458 }
michael@0 40459
michael@0 40460 // Detect the bidi method
michael@0 40461 // - If there are no rtl characters then no bidi needed
michael@0 40462 // - If less than 30% chars are rtl then string is primarily ltr
michael@0 40463 // - If more than 30% chars are rtl then string is primarily rtl
michael@0 40464 if (numBidi === 0) {
michael@0 40465 isLTR = true;
michael@0 40466 return createBidiText(str, isLTR);
michael@0 40467 }
michael@0 40468
michael@0 40469 if (startLevel == -1) {
michael@0 40470 if ((strLength / numBidi) < 0.3) {
michael@0 40471 isLTR = true;
michael@0 40472 startLevel = 0;
michael@0 40473 } else {
michael@0 40474 isLTR = false;
michael@0 40475 startLevel = 1;
michael@0 40476 }
michael@0 40477 }
michael@0 40478
michael@0 40479 var levels = [];
michael@0 40480 for (i = 0; i < strLength; ++i) {
michael@0 40481 levels[i] = startLevel;
michael@0 40482 }
michael@0 40483
michael@0 40484 /*
michael@0 40485 X1-X10: skip most of this, since we are NOT doing the embeddings.
michael@0 40486 */
michael@0 40487 var e = (isOdd(startLevel) ? 'R' : 'L');
michael@0 40488 var sor = e;
michael@0 40489 var eor = sor;
michael@0 40490
michael@0 40491 /*
michael@0 40492 W1. Examine each non-spacing mark (NSM) in the level run, and change the
michael@0 40493 type of the NSM to the type of the previous character. If the NSM is at the
michael@0 40494 start of the level run, it will get the type of sor.
michael@0 40495 */
michael@0 40496 var lastType = sor;
michael@0 40497 for (i = 0; i < strLength; ++i) {
michael@0 40498 if (types[i] == 'NSM') {
michael@0 40499 types[i] = lastType;
michael@0 40500 } else {
michael@0 40501 lastType = types[i];
michael@0 40502 }
michael@0 40503 }
michael@0 40504
michael@0 40505 /*
michael@0 40506 W2. Search backwards from each instance of a European number until the
michael@0 40507 first strong type (R, L, AL, or sor) is found. If an AL is found, change
michael@0 40508 the type of the European number to Arabic number.
michael@0 40509 */
michael@0 40510 lastType = sor;
michael@0 40511 var t;
michael@0 40512 for (i = 0; i < strLength; ++i) {
michael@0 40513 t = types[i];
michael@0 40514 if (t == 'EN') {
michael@0 40515 types[i] = (lastType == 'AL') ? 'AN' : 'EN';
michael@0 40516 } else if (t == 'R' || t == 'L' || t == 'AL') {
michael@0 40517 lastType = t;
michael@0 40518 }
michael@0 40519 }
michael@0 40520
michael@0 40521 /*
michael@0 40522 W3. Change all ALs to R.
michael@0 40523 */
michael@0 40524 for (i = 0; i < strLength; ++i) {
michael@0 40525 t = types[i];
michael@0 40526 if (t == 'AL') {
michael@0 40527 types[i] = 'R';
michael@0 40528 }
michael@0 40529 }
michael@0 40530
michael@0 40531 /*
michael@0 40532 W4. A single European separator between two European numbers changes to a
michael@0 40533 European number. A single common separator between two numbers of the same
michael@0 40534 type changes to that type:
michael@0 40535 */
michael@0 40536 for (i = 1; i < strLength - 1; ++i) {
michael@0 40537 if (types[i] == 'ES' && types[i - 1] == 'EN' && types[i + 1] == 'EN') {
michael@0 40538 types[i] = 'EN';
michael@0 40539 }
michael@0 40540 if (types[i] == 'CS' && (types[i - 1] == 'EN' || types[i - 1] == 'AN') &&
michael@0 40541 types[i + 1] == types[i - 1]) {
michael@0 40542 types[i] = types[i - 1];
michael@0 40543 }
michael@0 40544 }
michael@0 40545
michael@0 40546 /*
michael@0 40547 W5. A sequence of European terminators adjacent to European numbers changes
michael@0 40548 to all European numbers:
michael@0 40549 */
michael@0 40550 for (i = 0; i < strLength; ++i) {
michael@0 40551 if (types[i] == 'EN') {
michael@0 40552 // do before
michael@0 40553 var j;
michael@0 40554 for (j = i - 1; j >= 0; --j) {
michael@0 40555 if (types[j] != 'ET') {
michael@0 40556 break;
michael@0 40557 }
michael@0 40558 types[j] = 'EN';
michael@0 40559 }
michael@0 40560 // do after
michael@0 40561 for (j = i + 1; j < strLength; --j) {
michael@0 40562 if (types[j] != 'ET') {
michael@0 40563 break;
michael@0 40564 }
michael@0 40565 types[j] = 'EN';
michael@0 40566 }
michael@0 40567 }
michael@0 40568 }
michael@0 40569
michael@0 40570 /*
michael@0 40571 W6. Otherwise, separators and terminators change to Other Neutral:
michael@0 40572 */
michael@0 40573 for (i = 0; i < strLength; ++i) {
michael@0 40574 t = types[i];
michael@0 40575 if (t == 'WS' || t == 'ES' || t == 'ET' || t == 'CS') {
michael@0 40576 types[i] = 'ON';
michael@0 40577 }
michael@0 40578 }
michael@0 40579
michael@0 40580 /*
michael@0 40581 W7. Search backwards from each instance of a European number until the
michael@0 40582 first strong type (R, L, or sor) is found. If an L is found, then change
michael@0 40583 the type of the European number to L.
michael@0 40584 */
michael@0 40585 lastType = sor;
michael@0 40586 for (i = 0; i < strLength; ++i) {
michael@0 40587 t = types[i];
michael@0 40588 if (t == 'EN') {
michael@0 40589 types[i] = ((lastType == 'L') ? 'L' : 'EN');
michael@0 40590 } else if (t == 'R' || t == 'L') {
michael@0 40591 lastType = t;
michael@0 40592 }
michael@0 40593 }
michael@0 40594
michael@0 40595 /*
michael@0 40596 N1. A sequence of neutrals takes the direction of the surrounding strong
michael@0 40597 text if the text on both sides has the same direction. European and Arabic
michael@0 40598 numbers are treated as though they were R. Start-of-level-run (sor) and
michael@0 40599 end-of-level-run (eor) are used at level run boundaries.
michael@0 40600 */
michael@0 40601 for (i = 0; i < strLength; ++i) {
michael@0 40602 if (types[i] == 'ON') {
michael@0 40603 var end = findUnequal(types, i + 1, 'ON');
michael@0 40604 var before = sor;
michael@0 40605 if (i > 0) {
michael@0 40606 before = types[i - 1];
michael@0 40607 }
michael@0 40608
michael@0 40609 var after = eor;
michael@0 40610 if (end + 1 < strLength) {
michael@0 40611 after = types[end + 1];
michael@0 40612 }
michael@0 40613 if (before != 'L') {
michael@0 40614 before = 'R';
michael@0 40615 }
michael@0 40616 if (after != 'L') {
michael@0 40617 after = 'R';
michael@0 40618 }
michael@0 40619 if (before == after) {
michael@0 40620 setValues(types, i, end, before);
michael@0 40621 }
michael@0 40622 i = end - 1; // reset to end (-1 so next iteration is ok)
michael@0 40623 }
michael@0 40624 }
michael@0 40625
michael@0 40626 /*
michael@0 40627 N2. Any remaining neutrals take the embedding direction.
michael@0 40628 */
michael@0 40629 for (i = 0; i < strLength; ++i) {
michael@0 40630 if (types[i] == 'ON') {
michael@0 40631 types[i] = e;
michael@0 40632 }
michael@0 40633 }
michael@0 40634
michael@0 40635 /*
michael@0 40636 I1. For all characters with an even (left-to-right) embedding direction,
michael@0 40637 those of type R go up one level and those of type AN or EN go up two
michael@0 40638 levels.
michael@0 40639 I2. For all characters with an odd (right-to-left) embedding direction,
michael@0 40640 those of type L, EN or AN go up one level.
michael@0 40641 */
michael@0 40642 for (i = 0; i < strLength; ++i) {
michael@0 40643 t = types[i];
michael@0 40644 if (isEven(levels[i])) {
michael@0 40645 if (t == 'R') {
michael@0 40646 levels[i] += 1;
michael@0 40647 } else if (t == 'AN' || t == 'EN') {
michael@0 40648 levels[i] += 2;
michael@0 40649 }
michael@0 40650 } else { // isOdd
michael@0 40651 if (t == 'L' || t == 'AN' || t == 'EN') {
michael@0 40652 levels[i] += 1;
michael@0 40653 }
michael@0 40654 }
michael@0 40655 }
michael@0 40656
michael@0 40657 /*
michael@0 40658 L1. On each line, reset the embedding level of the following characters to
michael@0 40659 the paragraph embedding level:
michael@0 40660
michael@0 40661 segment separators,
michael@0 40662 paragraph separators,
michael@0 40663 any sequence of whitespace characters preceding a segment separator or
michael@0 40664 paragraph separator, and any sequence of white space characters at the end
michael@0 40665 of the line.
michael@0 40666 */
michael@0 40667
michael@0 40668 // don't bother as text is only single line
michael@0 40669
michael@0 40670 /*
michael@0 40671 L2. From the highest level found in the text to the lowest odd level on
michael@0 40672 each line, reverse any contiguous sequence of characters that are at that
michael@0 40673 level or higher.
michael@0 40674 */
michael@0 40675
michael@0 40676 // find highest level & lowest odd level
michael@0 40677 var highestLevel = -1;
michael@0 40678 var lowestOddLevel = 99;
michael@0 40679 var level;
michael@0 40680 for (i = 0, ii = levels.length; i < ii; ++i) {
michael@0 40681 level = levels[i];
michael@0 40682 if (highestLevel < level) {
michael@0 40683 highestLevel = level;
michael@0 40684 }
michael@0 40685 if (lowestOddLevel > level && isOdd(level)) {
michael@0 40686 lowestOddLevel = level;
michael@0 40687 }
michael@0 40688 }
michael@0 40689
michael@0 40690 // now reverse between those limits
michael@0 40691 for (level = highestLevel; level >= lowestOddLevel; --level) {
michael@0 40692 // find segments to reverse
michael@0 40693 var start = -1;
michael@0 40694 for (i = 0, ii = levels.length; i < ii; ++i) {
michael@0 40695 if (levels[i] < level) {
michael@0 40696 if (start >= 0) {
michael@0 40697 reverseValues(chars, start, i);
michael@0 40698 start = -1;
michael@0 40699 }
michael@0 40700 } else if (start < 0) {
michael@0 40701 start = i;
michael@0 40702 }
michael@0 40703 }
michael@0 40704 if (start >= 0) {
michael@0 40705 reverseValues(chars, start, levels.length);
michael@0 40706 }
michael@0 40707 }
michael@0 40708
michael@0 40709 /*
michael@0 40710 L3. Combining marks applied to a right-to-left base character will at this
michael@0 40711 point precede their base character. If the rendering engine expects them to
michael@0 40712 follow the base characters in the final display process, then the ordering
michael@0 40713 of the marks and the base character must be reversed.
michael@0 40714 */
michael@0 40715
michael@0 40716 // don't bother for now
michael@0 40717
michael@0 40718 /*
michael@0 40719 L4. A character that possesses the mirrored property as specified by
michael@0 40720 Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved
michael@0 40721 directionality of that character is R.
michael@0 40722 */
michael@0 40723
michael@0 40724 // don't mirror as characters are already mirrored in the pdf
michael@0 40725
michael@0 40726 // Finally, return string
michael@0 40727 var result = '';
michael@0 40728 for (i = 0, ii = chars.length; i < ii; ++i) {
michael@0 40729 var ch = chars[i];
michael@0 40730 if (ch != '<' && ch != '>') {
michael@0 40731 result += ch;
michael@0 40732 }
michael@0 40733 }
michael@0 40734 return createBidiText(result, isLTR);
michael@0 40735 }
michael@0 40736
michael@0 40737 return bidi;
michael@0 40738 })();
michael@0 40739
michael@0 40740
michael@0 40741 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 40742 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
michael@0 40743
michael@0 40744 /* Copyright 2014 Opera Software ASA
michael@0 40745 *
michael@0 40746 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 40747 * you may not use this file except in compliance with the License.
michael@0 40748 * You may obtain a copy of the License at
michael@0 40749 *
michael@0 40750 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 40751 *
michael@0 40752 * Unless required by applicable law or agreed to in writing, software
michael@0 40753 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 40754 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 40755 * See the License for the specific language governing permissions and
michael@0 40756 * limitations under the License.
michael@0 40757 *
michael@0 40758 *
michael@0 40759 * Based on https://code.google.com/p/smhasher/wiki/MurmurHash3.
michael@0 40760 * Hashes roughly 100 KB per millisecond on i7 3.4 GHz.
michael@0 40761 */
michael@0 40762 /* globals Uint32ArrayView */
michael@0 40763
michael@0 40764 'use strict';
michael@0 40765
michael@0 40766 var MurmurHash3_64 = (function MurmurHash3_64Closure (seed) {
michael@0 40767 // Workaround for missing math precison in JS.
michael@0 40768 var MASK_HIGH = 0xffff0000;
michael@0 40769 var MASK_LOW = 0xffff;
michael@0 40770
michael@0 40771 function MurmurHash3_64 (seed) {
michael@0 40772 var SEED = 0xc3d2e1f0;
michael@0 40773 this.h1 = seed ? seed & 0xffffffff : SEED;
michael@0 40774 this.h2 = seed ? seed & 0xffffffff : SEED;
michael@0 40775 }
michael@0 40776
michael@0 40777 MurmurHash3_64.prototype = {
michael@0 40778 update: function MurmurHash3_64_update(input) {
michael@0 40779 var useUint32ArrayView = false;
michael@0 40780 var i;
michael@0 40781 if (typeof input == 'string') {
michael@0 40782 var data = new Uint8Array(input.length * 2);
michael@0 40783 var length = 0;
michael@0 40784 for (i = 0; i < input.length; i++) {
michael@0 40785 var code = input.charCodeAt(i);
michael@0 40786 if (code <= 0xff) {
michael@0 40787 data[length++] = code;
michael@0 40788 }
michael@0 40789 else {
michael@0 40790 data[length++] = code >>> 8;
michael@0 40791 data[length++] = code & 0xff;
michael@0 40792 }
michael@0 40793 }
michael@0 40794 } else if (input instanceof Uint8Array) {
michael@0 40795 data = input;
michael@0 40796 length = data.length;
michael@0 40797 } else if (typeof input === 'object' && ('length' in input)) {
michael@0 40798 // processing regular arrays as well, e.g. for IE9
michael@0 40799 data = input;
michael@0 40800 length = data.length;
michael@0 40801 useUint32ArrayView = true;
michael@0 40802 } else {
michael@0 40803 throw new Error('Wrong data format in MurmurHash3_64_update. ' +
michael@0 40804 'Input must be a string or array.');
michael@0 40805 }
michael@0 40806
michael@0 40807 var blockCounts = length >> 2;
michael@0 40808 var tailLength = length - blockCounts * 4;
michael@0 40809 // we don't care about endianness here
michael@0 40810 var dataUint32 = useUint32ArrayView ?
michael@0 40811 new Uint32ArrayView(data, blockCounts) :
michael@0 40812 new Uint32Array(data.buffer, 0, blockCounts);
michael@0 40813 var k1 = 0;
michael@0 40814 var k2 = 0;
michael@0 40815 var h1 = this.h1;
michael@0 40816 var h2 = this.h2;
michael@0 40817 var C1 = 0xcc9e2d51;
michael@0 40818 var C2 = 0x1b873593;
michael@0 40819 var C1_LOW = C1 & MASK_LOW;
michael@0 40820 var C2_LOW = C2 & MASK_LOW;
michael@0 40821
michael@0 40822 for (i = 0; i < blockCounts; i++) {
michael@0 40823 if (i & 1) {
michael@0 40824 k1 = dataUint32[i];
michael@0 40825 k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW);
michael@0 40826 k1 = k1 << 15 | k1 >>> 17;
michael@0 40827 k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW);
michael@0 40828 h1 ^= k1;
michael@0 40829 h1 = h1 << 13 | h1 >>> 19;
michael@0 40830 h1 = h1 * 5 + 0xe6546b64;
michael@0 40831 } else {
michael@0 40832 k2 = dataUint32[i];
michael@0 40833 k2 = (k2 * C1 & MASK_HIGH) | (k2 * C1_LOW & MASK_LOW);
michael@0 40834 k2 = k2 << 15 | k2 >>> 17;
michael@0 40835 k2 = (k2 * C2 & MASK_HIGH) | (k2 * C2_LOW & MASK_LOW);
michael@0 40836 h2 ^= k2;
michael@0 40837 h2 = h2 << 13 | h2 >>> 19;
michael@0 40838 h2 = h2 * 5 + 0xe6546b64;
michael@0 40839 }
michael@0 40840 }
michael@0 40841
michael@0 40842 k1 = 0;
michael@0 40843
michael@0 40844 switch (tailLength) {
michael@0 40845 case 3:
michael@0 40846 k1 ^= data[blockCounts * 4 + 2] << 16;
michael@0 40847 /* falls through */
michael@0 40848 case 2:
michael@0 40849 k1 ^= data[blockCounts * 4 + 1] << 8;
michael@0 40850 /* falls through */
michael@0 40851 case 1:
michael@0 40852 k1 ^= data[blockCounts * 4];
michael@0 40853 /* falls through */
michael@0 40854 k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW);
michael@0 40855 k1 = k1 << 15 | k1 >>> 17;
michael@0 40856 k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW);
michael@0 40857 if (blockCounts & 1) {
michael@0 40858 h1 ^= k1;
michael@0 40859 } else {
michael@0 40860 h2 ^= k1;
michael@0 40861 }
michael@0 40862 }
michael@0 40863
michael@0 40864 this.h1 = h1;
michael@0 40865 this.h2 = h2;
michael@0 40866 return this;
michael@0 40867 },
michael@0 40868
michael@0 40869 hexdigest: function MurmurHash3_64_hexdigest () {
michael@0 40870 var h1 = this.h1;
michael@0 40871 var h2 = this.h2;
michael@0 40872
michael@0 40873 h1 ^= h2 >>> 1;
michael@0 40874 h1 = (h1 * 0xed558ccd & MASK_HIGH) | (h1 * 0x8ccd & MASK_LOW);
michael@0 40875 h2 = (h2 * 0xff51afd7 & MASK_HIGH) |
michael@0 40876 (((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16);
michael@0 40877 h1 ^= h2 >>> 1;
michael@0 40878 h1 = (h1 * 0x1a85ec53 & MASK_HIGH) | (h1 * 0xec53 & MASK_LOW);
michael@0 40879 h2 = (h2 * 0xc4ceb9fe & MASK_HIGH) |
michael@0 40880 (((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16);
michael@0 40881 h1 ^= h2 >>> 1;
michael@0 40882
michael@0 40883 for (var i = 0, arr = [h1, h2], str = ''; i < arr.length; i++) {
michael@0 40884 var hex = (arr[i] >>> 0).toString(16);
michael@0 40885 while (hex.length < 8) {
michael@0 40886 hex = '0' + hex;
michael@0 40887 }
michael@0 40888 str += hex;
michael@0 40889 }
michael@0 40890
michael@0 40891 return str;
michael@0 40892 }
michael@0 40893 };
michael@0 40894
michael@0 40895 return MurmurHash3_64;
michael@0 40896 })();
michael@0 40897 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
michael@0 40898 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
michael@0 40899 /*
michael@0 40900 Copyright 2011 notmasteryet
michael@0 40901
michael@0 40902 Licensed under the Apache License, Version 2.0 (the "License");
michael@0 40903 you may not use this file except in compliance with the License.
michael@0 40904 You may obtain a copy of the License at
michael@0 40905
michael@0 40906 http://www.apache.org/licenses/LICENSE-2.0
michael@0 40907
michael@0 40908 Unless required by applicable law or agreed to in writing, software
michael@0 40909 distributed under the License is distributed on an "AS IS" BASIS,
michael@0 40910 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 40911 See the License for the specific language governing permissions and
michael@0 40912 limitations under the License.
michael@0 40913 */
michael@0 40914
michael@0 40915 // - The JPEG specification can be found in the ITU CCITT Recommendation T.81
michael@0 40916 // (www.w3.org/Graphics/JPEG/itu-t81.pdf)
michael@0 40917 // - The JFIF specification can be found in the JPEG File Interchange Format
michael@0 40918 // (www.w3.org/Graphics/JPEG/jfif3.pdf)
michael@0 40919 // - The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters
michael@0 40920 // in PostScript Level 2, Technical Note #5116
michael@0 40921 // (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
michael@0 40922
michael@0 40923 var JpegImage = (function jpegImage() {
michael@0 40924 "use strict";
michael@0 40925 var dctZigZag = new Int32Array([
michael@0 40926 0,
michael@0 40927 1, 8,
michael@0 40928 16, 9, 2,
michael@0 40929 3, 10, 17, 24,
michael@0 40930 32, 25, 18, 11, 4,
michael@0 40931 5, 12, 19, 26, 33, 40,
michael@0 40932 48, 41, 34, 27, 20, 13, 6,
michael@0 40933 7, 14, 21, 28, 35, 42, 49, 56,
michael@0 40934 57, 50, 43, 36, 29, 22, 15,
michael@0 40935 23, 30, 37, 44, 51, 58,
michael@0 40936 59, 52, 45, 38, 31,
michael@0 40937 39, 46, 53, 60,
michael@0 40938 61, 54, 47,
michael@0 40939 55, 62,
michael@0 40940 63
michael@0 40941 ]);
michael@0 40942
michael@0 40943 var dctCos1 = 4017 // cos(pi/16)
michael@0 40944 var dctSin1 = 799 // sin(pi/16)
michael@0 40945 var dctCos3 = 3406 // cos(3*pi/16)
michael@0 40946 var dctSin3 = 2276 // sin(3*pi/16)
michael@0 40947 var dctCos6 = 1567 // cos(6*pi/16)
michael@0 40948 var dctSin6 = 3784 // sin(6*pi/16)
michael@0 40949 var dctSqrt2 = 5793 // sqrt(2)
michael@0 40950 var dctSqrt1d2 = 2896 // sqrt(2) / 2
michael@0 40951
michael@0 40952 function constructor() {
michael@0 40953 }
michael@0 40954
michael@0 40955 function buildHuffmanTable(codeLengths, values) {
michael@0 40956 var k = 0, code = [], i, j, length = 16;
michael@0 40957 while (length > 0 && !codeLengths[length - 1])
michael@0 40958 length--;
michael@0 40959 code.push({children: [], index: 0});
michael@0 40960 var p = code[0], q;
michael@0 40961 for (i = 0; i < length; i++) {
michael@0 40962 for (j = 0; j < codeLengths[i]; j++) {
michael@0 40963 p = code.pop();
michael@0 40964 p.children[p.index] = values[k];
michael@0 40965 while (p.index > 0) {
michael@0 40966 p = code.pop();
michael@0 40967 }
michael@0 40968 p.index++;
michael@0 40969 code.push(p);
michael@0 40970 while (code.length <= i) {
michael@0 40971 code.push(q = {children: [], index: 0});
michael@0 40972 p.children[p.index] = q.children;
michael@0 40973 p = q;
michael@0 40974 }
michael@0 40975 k++;
michael@0 40976 }
michael@0 40977 if (i + 1 < length) {
michael@0 40978 // p here points to last code
michael@0 40979 code.push(q = {children: [], index: 0});
michael@0 40980 p.children[p.index] = q.children;
michael@0 40981 p = q;
michael@0 40982 }
michael@0 40983 }
michael@0 40984 return code[0].children;
michael@0 40985 }
michael@0 40986
michael@0 40987 function getBlockBufferOffset(component, row, col) {
michael@0 40988 return 64 * ((component.blocksPerLine + 1) * row + col);
michael@0 40989 }
michael@0 40990
michael@0 40991 function decodeScan(data, offset,
michael@0 40992 frame, components, resetInterval,
michael@0 40993 spectralStart, spectralEnd,
michael@0 40994 successivePrev, successive) {
michael@0 40995 var precision = frame.precision;
michael@0 40996 var samplesPerLine = frame.samplesPerLine;
michael@0 40997 var scanLines = frame.scanLines;
michael@0 40998 var mcusPerLine = frame.mcusPerLine;
michael@0 40999 var progressive = frame.progressive;
michael@0 41000 var maxH = frame.maxH, maxV = frame.maxV;
michael@0 41001
michael@0 41002 var startOffset = offset, bitsData = 0, bitsCount = 0;
michael@0 41003
michael@0 41004 function readBit() {
michael@0 41005 if (bitsCount > 0) {
michael@0 41006 bitsCount--;
michael@0 41007 return (bitsData >> bitsCount) & 1;
michael@0 41008 }
michael@0 41009 bitsData = data[offset++];
michael@0 41010 if (bitsData == 0xFF) {
michael@0 41011 var nextByte = data[offset++];
michael@0 41012 if (nextByte) {
michael@0 41013 throw "unexpected marker: " + ((bitsData << 8) | nextByte).toString(16);
michael@0 41014 }
michael@0 41015 // unstuff 0
michael@0 41016 }
michael@0 41017 bitsCount = 7;
michael@0 41018 return bitsData >>> 7;
michael@0 41019 }
michael@0 41020
michael@0 41021 function decodeHuffman(tree) {
michael@0 41022 var node = tree;
michael@0 41023 var bit;
michael@0 41024 while ((bit = readBit()) !== null) {
michael@0 41025 node = node[bit];
michael@0 41026 if (typeof node === 'number')
michael@0 41027 return node;
michael@0 41028 if (typeof node !== 'object')
michael@0 41029 throw "invalid huffman sequence";
michael@0 41030 }
michael@0 41031 return null;
michael@0 41032 }
michael@0 41033
michael@0 41034 function receive(length) {
michael@0 41035 var n = 0;
michael@0 41036 while (length > 0) {
michael@0 41037 var bit = readBit();
michael@0 41038 if (bit === null) return;
michael@0 41039 n = (n << 1) | bit;
michael@0 41040 length--;
michael@0 41041 }
michael@0 41042 return n;
michael@0 41043 }
michael@0 41044
michael@0 41045 function receiveAndExtend(length) {
michael@0 41046 var n = receive(length);
michael@0 41047 if (n >= 1 << (length - 1))
michael@0 41048 return n;
michael@0 41049 return n + (-1 << length) + 1;
michael@0 41050 }
michael@0 41051
michael@0 41052 function decodeBaseline(component, offset) {
michael@0 41053 var t = decodeHuffman(component.huffmanTableDC);
michael@0 41054 var diff = t === 0 ? 0 : receiveAndExtend(t);
michael@0 41055 component.blockData[offset] = (component.pred += diff);
michael@0 41056 var k = 1;
michael@0 41057 while (k < 64) {
michael@0 41058 var rs = decodeHuffman(component.huffmanTableAC);
michael@0 41059 var s = rs & 15, r = rs >> 4;
michael@0 41060 if (s === 0) {
michael@0 41061 if (r < 15)
michael@0 41062 break;
michael@0 41063 k += 16;
michael@0 41064 continue;
michael@0 41065 }
michael@0 41066 k += r;
michael@0 41067 var z = dctZigZag[k];
michael@0 41068 component.blockData[offset + z] = receiveAndExtend(s);
michael@0 41069 k++;
michael@0 41070 }
michael@0 41071 }
michael@0 41072
michael@0 41073 function decodeDCFirst(component, offset) {
michael@0 41074 var t = decodeHuffman(component.huffmanTableDC);
michael@0 41075 var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
michael@0 41076 component.blockData[offset] = (component.pred += diff);
michael@0 41077 }
michael@0 41078
michael@0 41079 function decodeDCSuccessive(component, offset) {
michael@0 41080 component.blockData[offset] |= readBit() << successive;
michael@0 41081 }
michael@0 41082
michael@0 41083 var eobrun = 0;
michael@0 41084 function decodeACFirst(component, offset) {
michael@0 41085 if (eobrun > 0) {
michael@0 41086 eobrun--;
michael@0 41087 return;
michael@0 41088 }
michael@0 41089 var k = spectralStart, e = spectralEnd;
michael@0 41090 while (k <= e) {
michael@0 41091 var rs = decodeHuffman(component.huffmanTableAC);
michael@0 41092 var s = rs & 15, r = rs >> 4;
michael@0 41093 if (s === 0) {
michael@0 41094 if (r < 15) {
michael@0 41095 eobrun = receive(r) + (1 << r) - 1;
michael@0 41096 break;
michael@0 41097 }
michael@0 41098 k += 16;
michael@0 41099 continue;
michael@0 41100 }
michael@0 41101 k += r;
michael@0 41102 var z = dctZigZag[k];
michael@0 41103 component.blockData[offset + z] = receiveAndExtend(s) * (1 << successive);
michael@0 41104 k++;
michael@0 41105 }
michael@0 41106 }
michael@0 41107
michael@0 41108 var successiveACState = 0, successiveACNextValue;
michael@0 41109 function decodeACSuccessive(component, offset) {
michael@0 41110 var k = spectralStart, e = spectralEnd, r = 0;
michael@0 41111 while (k <= e) {
michael@0 41112 var z = dctZigZag[k];
michael@0 41113 switch (successiveACState) {
michael@0 41114 case 0: // initial state
michael@0 41115 var rs = decodeHuffman(component.huffmanTableAC);
michael@0 41116 var s = rs & 15, r = rs >> 4;
michael@0 41117 if (s === 0) {
michael@0 41118 if (r < 15) {
michael@0 41119 eobrun = receive(r) + (1 << r);
michael@0 41120 successiveACState = 4;
michael@0 41121 } else {
michael@0 41122 r = 16;
michael@0 41123 successiveACState = 1;
michael@0 41124 }
michael@0 41125 } else {
michael@0 41126 if (s !== 1)
michael@0 41127 throw "invalid ACn encoding";
michael@0 41128 successiveACNextValue = receiveAndExtend(s);
michael@0 41129 successiveACState = r ? 2 : 3;
michael@0 41130 }
michael@0 41131 continue;
michael@0 41132 case 1: // skipping r zero items
michael@0 41133 case 2:
michael@0 41134 if (component.blockData[offset + z]) {
michael@0 41135 component.blockData[offset + z] += (readBit() << successive);
michael@0 41136 } else {
michael@0 41137 r--;
michael@0 41138 if (r === 0)
michael@0 41139 successiveACState = successiveACState == 2 ? 3 : 0;
michael@0 41140 }
michael@0 41141 break;
michael@0 41142 case 3: // set value for a zero item
michael@0 41143 if (component.blockData[offset + z]) {
michael@0 41144 component.blockData[offset + z] += (readBit() << successive);
michael@0 41145 } else {
michael@0 41146 component.blockData[offset + z] = successiveACNextValue << successive;
michael@0 41147 successiveACState = 0;
michael@0 41148 }
michael@0 41149 break;
michael@0 41150 case 4: // eob
michael@0 41151 if (component.blockData[offset + z]) {
michael@0 41152 component.blockData[offset + z] += (readBit() << successive);
michael@0 41153 }
michael@0 41154 break;
michael@0 41155 }
michael@0 41156 k++;
michael@0 41157 }
michael@0 41158 if (successiveACState === 4) {
michael@0 41159 eobrun--;
michael@0 41160 if (eobrun === 0)
michael@0 41161 successiveACState = 0;
michael@0 41162 }
michael@0 41163 }
michael@0 41164
michael@0 41165 function decodeMcu(component, decode, mcu, row, col) {
michael@0 41166 var mcuRow = (mcu / mcusPerLine) | 0;
michael@0 41167 var mcuCol = mcu % mcusPerLine;
michael@0 41168 var blockRow = mcuRow * component.v + row;
michael@0 41169 var blockCol = mcuCol * component.h + col;
michael@0 41170 var offset = getBlockBufferOffset(component, blockRow, blockCol);
michael@0 41171 decode(component, offset);
michael@0 41172 }
michael@0 41173
michael@0 41174 function decodeBlock(component, decode, mcu) {
michael@0 41175 var blockRow = (mcu / component.blocksPerLine) | 0;
michael@0 41176 var blockCol = mcu % component.blocksPerLine;
michael@0 41177 var offset = getBlockBufferOffset(component, blockRow, blockCol);
michael@0 41178 decode(component, offset);
michael@0 41179 }
michael@0 41180
michael@0 41181 var componentsLength = components.length;
michael@0 41182 var component, i, j, k, n;
michael@0 41183 var decodeFn;
michael@0 41184 if (progressive) {
michael@0 41185 if (spectralStart === 0)
michael@0 41186 decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
michael@0 41187 else
michael@0 41188 decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
michael@0 41189 } else {
michael@0 41190 decodeFn = decodeBaseline;
michael@0 41191 }
michael@0 41192
michael@0 41193 var mcu = 0, marker;
michael@0 41194 var mcuExpected;
michael@0 41195 if (componentsLength == 1) {
michael@0 41196 mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
michael@0 41197 } else {
michael@0 41198 mcuExpected = mcusPerLine * frame.mcusPerColumn;
michael@0 41199 }
michael@0 41200 if (!resetInterval) {
michael@0 41201 resetInterval = mcuExpected;
michael@0 41202 }
michael@0 41203
michael@0 41204 var h, v;
michael@0 41205 while (mcu < mcuExpected) {
michael@0 41206 // reset interval stuff
michael@0 41207 for (i = 0; i < componentsLength; i++) {
michael@0 41208 components[i].pred = 0;
michael@0 41209 }
michael@0 41210 eobrun = 0;
michael@0 41211
michael@0 41212 if (componentsLength == 1) {
michael@0 41213 component = components[0];
michael@0 41214 for (n = 0; n < resetInterval; n++) {
michael@0 41215 decodeBlock(component, decodeFn, mcu);
michael@0 41216 mcu++;
michael@0 41217 }
michael@0 41218 } else {
michael@0 41219 for (n = 0; n < resetInterval; n++) {
michael@0 41220 for (i = 0; i < componentsLength; i++) {
michael@0 41221 component = components[i];
michael@0 41222 h = component.h;
michael@0 41223 v = component.v;
michael@0 41224 for (j = 0; j < v; j++) {
michael@0 41225 for (k = 0; k < h; k++) {
michael@0 41226 decodeMcu(component, decodeFn, mcu, j, k);
michael@0 41227 }
michael@0 41228 }
michael@0 41229 }
michael@0 41230 mcu++;
michael@0 41231 }
michael@0 41232 }
michael@0 41233
michael@0 41234 // find marker
michael@0 41235 bitsCount = 0;
michael@0 41236 marker = (data[offset] << 8) | data[offset + 1];
michael@0 41237 if (marker <= 0xFF00) {
michael@0 41238 throw "marker was not found";
michael@0 41239 }
michael@0 41240
michael@0 41241 if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx
michael@0 41242 offset += 2;
michael@0 41243 } else {
michael@0 41244 break;
michael@0 41245 }
michael@0 41246 }
michael@0 41247
michael@0 41248 return offset - startOffset;
michael@0 41249 }
michael@0 41250
michael@0 41251 // A port of poppler's IDCT method which in turn is taken from:
michael@0 41252 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
michael@0 41253 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
michael@0 41254 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
michael@0 41255 // 988-991.
michael@0 41256 function quantizeAndInverse(component, blockBufferOffset, p) {
michael@0 41257 var qt = component.quantizationTable;
michael@0 41258 var v0, v1, v2, v3, v4, v5, v6, v7, t;
michael@0 41259 var i;
michael@0 41260
michael@0 41261 // dequant
michael@0 41262 for (i = 0; i < 64; i++) {
michael@0 41263 p[i] = component.blockData[blockBufferOffset + i] * qt[i];
michael@0 41264 }
michael@0 41265
michael@0 41266 // inverse DCT on rows
michael@0 41267 for (i = 0; i < 8; ++i) {
michael@0 41268 var row = 8 * i;
michael@0 41269
michael@0 41270 // check for all-zero AC coefficients
michael@0 41271 if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&
michael@0 41272 p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&
michael@0 41273 p[7 + row] == 0) {
michael@0 41274 t = (dctSqrt2 * p[0 + row] + 512) >> 10;
michael@0 41275 p[0 + row] = t;
michael@0 41276 p[1 + row] = t;
michael@0 41277 p[2 + row] = t;
michael@0 41278 p[3 + row] = t;
michael@0 41279 p[4 + row] = t;
michael@0 41280 p[5 + row] = t;
michael@0 41281 p[6 + row] = t;
michael@0 41282 p[7 + row] = t;
michael@0 41283 continue;
michael@0 41284 }
michael@0 41285
michael@0 41286 // stage 4
michael@0 41287 v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;
michael@0 41288 v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;
michael@0 41289 v2 = p[2 + row];
michael@0 41290 v3 = p[6 + row];
michael@0 41291 v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
michael@0 41292 v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
michael@0 41293 v5 = p[3 + row] << 4;
michael@0 41294 v6 = p[5 + row] << 4;
michael@0 41295
michael@0 41296 // stage 3
michael@0 41297 t = (v0 - v1+ 1) >> 1;
michael@0 41298 v0 = (v0 + v1 + 1) >> 1;
michael@0 41299 v1 = t;
michael@0 41300 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
michael@0 41301 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
michael@0 41302 v3 = t;
michael@0 41303 t = (v4 - v6 + 1) >> 1;
michael@0 41304 v4 = (v4 + v6 + 1) >> 1;
michael@0 41305 v6 = t;
michael@0 41306 t = (v7 + v5 + 1) >> 1;
michael@0 41307 v5 = (v7 - v5 + 1) >> 1;
michael@0 41308 v7 = t;
michael@0 41309
michael@0 41310 // stage 2
michael@0 41311 t = (v0 - v3 + 1) >> 1;
michael@0 41312 v0 = (v0 + v3 + 1) >> 1;
michael@0 41313 v3 = t;
michael@0 41314 t = (v1 - v2 + 1) >> 1;
michael@0 41315 v1 = (v1 + v2 + 1) >> 1;
michael@0 41316 v2 = t;
michael@0 41317 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
michael@0 41318 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
michael@0 41319 v7 = t;
michael@0 41320 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
michael@0 41321 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
michael@0 41322 v6 = t;
michael@0 41323
michael@0 41324 // stage 1
michael@0 41325 p[0 + row] = v0 + v7;
michael@0 41326 p[7 + row] = v0 - v7;
michael@0 41327 p[1 + row] = v1 + v6;
michael@0 41328 p[6 + row] = v1 - v6;
michael@0 41329 p[2 + row] = v2 + v5;
michael@0 41330 p[5 + row] = v2 - v5;
michael@0 41331 p[3 + row] = v3 + v4;
michael@0 41332 p[4 + row] = v3 - v4;
michael@0 41333 }
michael@0 41334
michael@0 41335 // inverse DCT on columns
michael@0 41336 for (i = 0; i < 8; ++i) {
michael@0 41337 var col = i;
michael@0 41338
michael@0 41339 // check for all-zero AC coefficients
michael@0 41340 if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 &&
michael@0 41341 p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 &&
michael@0 41342 p[7*8 + col] == 0) {
michael@0 41343 t = (dctSqrt2 * p[i+0] + 8192) >> 14;
michael@0 41344 p[0*8 + col] = t;
michael@0 41345 p[1*8 + col] = t;
michael@0 41346 p[2*8 + col] = t;
michael@0 41347 p[3*8 + col] = t;
michael@0 41348 p[4*8 + col] = t;
michael@0 41349 p[5*8 + col] = t;
michael@0 41350 p[6*8 + col] = t;
michael@0 41351 p[7*8 + col] = t;
michael@0 41352 continue;
michael@0 41353 }
michael@0 41354
michael@0 41355 // stage 4
michael@0 41356 v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12;
michael@0 41357 v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12;
michael@0 41358 v2 = p[2*8 + col];
michael@0 41359 v3 = p[6*8 + col];
michael@0 41360 v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12;
michael@0 41361 v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12;
michael@0 41362 v5 = p[3*8 + col];
michael@0 41363 v6 = p[5*8 + col];
michael@0 41364
michael@0 41365 // stage 3
michael@0 41366 t = (v0 - v1 + 1) >> 1;
michael@0 41367 v0 = (v0 + v1 + 1) >> 1;
michael@0 41368 v1 = t;
michael@0 41369 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
michael@0 41370 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
michael@0 41371 v3 = t;
michael@0 41372 t = (v4 - v6 + 1) >> 1;
michael@0 41373 v4 = (v4 + v6 + 1) >> 1;
michael@0 41374 v6 = t;
michael@0 41375 t = (v7 + v5 + 1) >> 1;
michael@0 41376 v5 = (v7 - v5 + 1) >> 1;
michael@0 41377 v7 = t;
michael@0 41378
michael@0 41379 // stage 2
michael@0 41380 t = (v0 - v3 + 1) >> 1;
michael@0 41381 v0 = (v0 + v3 + 1) >> 1;
michael@0 41382 v3 = t;
michael@0 41383 t = (v1 - v2 + 1) >> 1;
michael@0 41384 v1 = (v1 + v2 + 1) >> 1;
michael@0 41385 v2 = t;
michael@0 41386 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
michael@0 41387 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
michael@0 41388 v7 = t;
michael@0 41389 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
michael@0 41390 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
michael@0 41391 v6 = t;
michael@0 41392
michael@0 41393 // stage 1
michael@0 41394 p[0*8 + col] = v0 + v7;
michael@0 41395 p[7*8 + col] = v0 - v7;
michael@0 41396 p[1*8 + col] = v1 + v6;
michael@0 41397 p[6*8 + col] = v1 - v6;
michael@0 41398 p[2*8 + col] = v2 + v5;
michael@0 41399 p[5*8 + col] = v2 - v5;
michael@0 41400 p[3*8 + col] = v3 + v4;
michael@0 41401 p[4*8 + col] = v3 - v4;
michael@0 41402 }
michael@0 41403
michael@0 41404 // convert to 8-bit integers
michael@0 41405 for (i = 0; i < 64; ++i) {
michael@0 41406 var index = blockBufferOffset + i;
michael@0 41407 component.blockData[index] = clampTo8bitInt((p[i] + 2056) >> 4);
michael@0 41408 }
michael@0 41409 }
michael@0 41410
michael@0 41411 function buildComponentData(frame, component) {
michael@0 41412 var lines = [];
michael@0 41413 var blocksPerLine = component.blocksPerLine;
michael@0 41414 var blocksPerColumn = component.blocksPerColumn;
michael@0 41415 var samplesPerLine = blocksPerLine << 3;
michael@0 41416 var computationBuffer = new Int32Array(64);
michael@0 41417
michael@0 41418 var i, j, ll = 0;
michael@0 41419 for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
michael@0 41420 for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
michael@0 41421 var offset = getBlockBufferOffset(component, blockRow, blockCol)
michael@0 41422 quantizeAndInverse(component, offset, computationBuffer);
michael@0 41423 }
michael@0 41424 }
michael@0 41425 return component.blockData;
michael@0 41426 }
michael@0 41427
michael@0 41428 function clampTo8bitInt(a) {
michael@0 41429 return a <= 0 ? 0 : a >= 255 ? 255 : a | 0;
michael@0 41430 }
michael@0 41431
michael@0 41432 function clamp0to255(a) {
michael@0 41433 return a <= 0 ? 0 : a >= 255 ? 255 : a;
michael@0 41434 }
michael@0 41435
michael@0 41436 constructor.prototype = {
michael@0 41437 load: function load(path) {
michael@0 41438 var xhr = new XMLHttpRequest();
michael@0 41439 xhr.open("GET", path, true);
michael@0 41440 xhr.responseType = "arraybuffer";
michael@0 41441 xhr.onload = (function() {
michael@0 41442 // TODO catch parse error
michael@0 41443 var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
michael@0 41444 this.parse(data);
michael@0 41445 if (this.onload)
michael@0 41446 this.onload();
michael@0 41447 }).bind(this);
michael@0 41448 xhr.send(null);
michael@0 41449 },
michael@0 41450
michael@0 41451 parse: function parse(data) {
michael@0 41452
michael@0 41453 function readUint16() {
michael@0 41454 var value = (data[offset] << 8) | data[offset + 1];
michael@0 41455 offset += 2;
michael@0 41456 return value;
michael@0 41457 }
michael@0 41458
michael@0 41459 function readDataBlock() {
michael@0 41460 var length = readUint16();
michael@0 41461 var array = data.subarray(offset, offset + length - 2);
michael@0 41462 offset += array.length;
michael@0 41463 return array;
michael@0 41464 }
michael@0 41465
michael@0 41466 function prepareComponents(frame) {
michael@0 41467 var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);
michael@0 41468 var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
michael@0 41469 for (var i = 0; i < frame.components.length; i++) {
michael@0 41470 component = frame.components[i];
michael@0 41471 var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH);
michael@0 41472 var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV);
michael@0 41473 var blocksPerLineForMcu = mcusPerLine * component.h;
michael@0 41474 var blocksPerColumnForMcu = mcusPerColumn * component.v;
michael@0 41475
michael@0 41476 var blocksBufferSize = 64 * blocksPerColumnForMcu
michael@0 41477 * (blocksPerLineForMcu + 1);
michael@0 41478 component.blockData = new Int16Array(blocksBufferSize);
michael@0 41479 component.blocksPerLine = blocksPerLine;
michael@0 41480 component.blocksPerColumn = blocksPerColumn;
michael@0 41481 }
michael@0 41482 frame.mcusPerLine = mcusPerLine;
michael@0 41483 frame.mcusPerColumn = mcusPerColumn;
michael@0 41484 }
michael@0 41485
michael@0 41486 var offset = 0, length = data.length;
michael@0 41487 var jfif = null;
michael@0 41488 var adobe = null;
michael@0 41489 var pixels = null;
michael@0 41490 var frame, resetInterval;
michael@0 41491 var quantizationTables = [];
michael@0 41492 var huffmanTablesAC = [], huffmanTablesDC = [];
michael@0 41493 var fileMarker = readUint16();
michael@0 41494 if (fileMarker != 0xFFD8) { // SOI (Start of Image)
michael@0 41495 throw "SOI not found";
michael@0 41496 }
michael@0 41497
michael@0 41498 fileMarker = readUint16();
michael@0 41499 while (fileMarker != 0xFFD9) { // EOI (End of image)
michael@0 41500 var i, j, l;
michael@0 41501 switch(fileMarker) {
michael@0 41502 case 0xFFE0: // APP0 (Application Specific)
michael@0 41503 case 0xFFE1: // APP1
michael@0 41504 case 0xFFE2: // APP2
michael@0 41505 case 0xFFE3: // APP3
michael@0 41506 case 0xFFE4: // APP4
michael@0 41507 case 0xFFE5: // APP5
michael@0 41508 case 0xFFE6: // APP6
michael@0 41509 case 0xFFE7: // APP7
michael@0 41510 case 0xFFE8: // APP8
michael@0 41511 case 0xFFE9: // APP9
michael@0 41512 case 0xFFEA: // APP10
michael@0 41513 case 0xFFEB: // APP11
michael@0 41514 case 0xFFEC: // APP12
michael@0 41515 case 0xFFED: // APP13
michael@0 41516 case 0xFFEE: // APP14
michael@0 41517 case 0xFFEF: // APP15
michael@0 41518 case 0xFFFE: // COM (Comment)
michael@0 41519 var appData = readDataBlock();
michael@0 41520
michael@0 41521 if (fileMarker === 0xFFE0) {
michael@0 41522 if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 &&
michael@0 41523 appData[3] === 0x46 && appData[4] === 0) { // 'JFIF\x00'
michael@0 41524 jfif = {
michael@0 41525 version: { major: appData[5], minor: appData[6] },
michael@0 41526 densityUnits: appData[7],
michael@0 41527 xDensity: (appData[8] << 8) | appData[9],
michael@0 41528 yDensity: (appData[10] << 8) | appData[11],
michael@0 41529 thumbWidth: appData[12],
michael@0 41530 thumbHeight: appData[13],
michael@0 41531 thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])
michael@0 41532 };
michael@0 41533 }
michael@0 41534 }
michael@0 41535 // TODO APP1 - Exif
michael@0 41536 if (fileMarker === 0xFFEE) {
michael@0 41537 if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F &&
michael@0 41538 appData[3] === 0x62 && appData[4] === 0x65 && appData[5] === 0) { // 'Adobe\x00'
michael@0 41539 adobe = {
michael@0 41540 version: appData[6],
michael@0 41541 flags0: (appData[7] << 8) | appData[8],
michael@0 41542 flags1: (appData[9] << 8) | appData[10],
michael@0 41543 transformCode: appData[11]
michael@0 41544 };
michael@0 41545 }
michael@0 41546 }
michael@0 41547 break;
michael@0 41548
michael@0 41549 case 0xFFDB: // DQT (Define Quantization Tables)
michael@0 41550 var quantizationTablesLength = readUint16();
michael@0 41551 var quantizationTablesEnd = quantizationTablesLength + offset - 2;
michael@0 41552 while (offset < quantizationTablesEnd) {
michael@0 41553 var quantizationTableSpec = data[offset++];
michael@0 41554 var tableData = new Int32Array(64);
michael@0 41555 if ((quantizationTableSpec >> 4) === 0) { // 8 bit values
michael@0 41556 for (j = 0; j < 64; j++) {
michael@0 41557 var z = dctZigZag[j];
michael@0 41558 tableData[z] = data[offset++];
michael@0 41559 }
michael@0 41560 } else if ((quantizationTableSpec >> 4) === 1) { //16 bit
michael@0 41561 for (j = 0; j < 64; j++) {
michael@0 41562 var z = dctZigZag[j];
michael@0 41563 tableData[z] = readUint16();
michael@0 41564 }
michael@0 41565 } else
michael@0 41566 throw "DQT: invalid table spec";
michael@0 41567 quantizationTables[quantizationTableSpec & 15] = tableData;
michael@0 41568 }
michael@0 41569 break;
michael@0 41570
michael@0 41571 case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT)
michael@0 41572 case 0xFFC1: // SOF1 (Start of Frame, Extended DCT)
michael@0 41573 case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT)
michael@0 41574 if (frame) {
michael@0 41575 throw "Only single frame JPEGs supported";
michael@0 41576 }
michael@0 41577 readUint16(); // skip data length
michael@0 41578 frame = {};
michael@0 41579 frame.extended = (fileMarker === 0xFFC1);
michael@0 41580 frame.progressive = (fileMarker === 0xFFC2);
michael@0 41581 frame.precision = data[offset++];
michael@0 41582 frame.scanLines = readUint16();
michael@0 41583 frame.samplesPerLine = readUint16();
michael@0 41584 frame.components = [];
michael@0 41585 frame.componentIds = {};
michael@0 41586 var componentsCount = data[offset++], componentId;
michael@0 41587 var maxH = 0, maxV = 0;
michael@0 41588 for (i = 0; i < componentsCount; i++) {
michael@0 41589 componentId = data[offset];
michael@0 41590 var h = data[offset + 1] >> 4;
michael@0 41591 var v = data[offset + 1] & 15;
michael@0 41592 if (maxH < h) maxH = h;
michael@0 41593 if (maxV < v) maxV = v;
michael@0 41594 var qId = data[offset + 2];
michael@0 41595 var l = frame.components.push({
michael@0 41596 h: h,
michael@0 41597 v: v,
michael@0 41598 quantizationTable: quantizationTables[qId]
michael@0 41599 });
michael@0 41600 frame.componentIds[componentId] = l - 1;
michael@0 41601 offset += 3;
michael@0 41602 }
michael@0 41603 frame.maxH = maxH;
michael@0 41604 frame.maxV = maxV;
michael@0 41605 prepareComponents(frame);
michael@0 41606 break;
michael@0 41607
michael@0 41608 case 0xFFC4: // DHT (Define Huffman Tables)
michael@0 41609 var huffmanLength = readUint16();
michael@0 41610 for (i = 2; i < huffmanLength;) {
michael@0 41611 var huffmanTableSpec = data[offset++];
michael@0 41612 var codeLengths = new Uint8Array(16);
michael@0 41613 var codeLengthSum = 0;
michael@0 41614 for (j = 0; j < 16; j++, offset++)
michael@0 41615 codeLengthSum += (codeLengths[j] = data[offset]);
michael@0 41616 var huffmanValues = new Uint8Array(codeLengthSum);
michael@0 41617 for (j = 0; j < codeLengthSum; j++, offset++)
michael@0 41618 huffmanValues[j] = data[offset];
michael@0 41619 i += 17 + codeLengthSum;
michael@0 41620
michael@0 41621 ((huffmanTableSpec >> 4) === 0 ?
michael@0 41622 huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] =
michael@0 41623 buildHuffmanTable(codeLengths, huffmanValues);
michael@0 41624 }
michael@0 41625 break;
michael@0 41626
michael@0 41627 case 0xFFDD: // DRI (Define Restart Interval)
michael@0 41628 readUint16(); // skip data length
michael@0 41629 resetInterval = readUint16();
michael@0 41630 break;
michael@0 41631
michael@0 41632 case 0xFFDA: // SOS (Start of Scan)
michael@0 41633 var scanLength = readUint16();
michael@0 41634 var selectorsCount = data[offset++];
michael@0 41635 var components = [], component;
michael@0 41636 for (i = 0; i < selectorsCount; i++) {
michael@0 41637 var componentIndex = frame.componentIds[data[offset++]];
michael@0 41638 component = frame.components[componentIndex];
michael@0 41639 var tableSpec = data[offset++];
michael@0 41640 component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
michael@0 41641 component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
michael@0 41642 components.push(component);
michael@0 41643 }
michael@0 41644 var spectralStart = data[offset++];
michael@0 41645 var spectralEnd = data[offset++];
michael@0 41646 var successiveApproximation = data[offset++];
michael@0 41647 var processed = decodeScan(data, offset,
michael@0 41648 frame, components, resetInterval,
michael@0 41649 spectralStart, spectralEnd,
michael@0 41650 successiveApproximation >> 4, successiveApproximation & 15);
michael@0 41651 offset += processed;
michael@0 41652 break;
michael@0 41653 default:
michael@0 41654 if (data[offset - 3] == 0xFF &&
michael@0 41655 data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
michael@0 41656 // could be incorrect encoding -- last 0xFF byte of the previous
michael@0 41657 // block was eaten by the encoder
michael@0 41658 offset -= 3;
michael@0 41659 break;
michael@0 41660 }
michael@0 41661 throw "unknown JPEG marker " + fileMarker.toString(16);
michael@0 41662 }
michael@0 41663 fileMarker = readUint16();
michael@0 41664 }
michael@0 41665
michael@0 41666 this.width = frame.samplesPerLine;
michael@0 41667 this.height = frame.scanLines;
michael@0 41668 this.jfif = jfif;
michael@0 41669 this.adobe = adobe;
michael@0 41670 this.components = [];
michael@0 41671 for (var i = 0; i < frame.components.length; i++) {
michael@0 41672 var component = frame.components[i];
michael@0 41673 this.components.push({
michael@0 41674 output: buildComponentData(frame, component),
michael@0 41675 scaleX: component.h / frame.maxH,
michael@0 41676 scaleY: component.v / frame.maxV,
michael@0 41677 blocksPerLine: component.blocksPerLine,
michael@0 41678 blocksPerColumn: component.blocksPerColumn
michael@0 41679 });
michael@0 41680 }
michael@0 41681 },
michael@0 41682
michael@0 41683 getData: function getData(width, height) {
michael@0 41684 var scaleX = this.width / width, scaleY = this.height / height;
michael@0 41685
michael@0 41686 var component, componentScaleX, componentScaleY;
michael@0 41687 var x, y, i;
michael@0 41688 var offset = 0;
michael@0 41689 var Y, Cb, Cr, K, C, M, Ye, R, G, B;
michael@0 41690 var colorTransform;
michael@0 41691 var numComponents = this.components.length;
michael@0 41692 var dataLength = width * height * numComponents;
michael@0 41693 var data = new Uint8Array(dataLength);
michael@0 41694 var componentLine;
michael@0 41695
michael@0 41696 // lineData is reused for all components. Assume first component is
michael@0 41697 // the biggest
michael@0 41698 var lineData = new Uint8Array((this.components[0].blocksPerLine << 3) *
michael@0 41699 this.components[0].blocksPerColumn * 8);
michael@0 41700
michael@0 41701 // First construct image data ...
michael@0 41702 for (i = 0; i < numComponents; i++) {
michael@0 41703 component = this.components[i];
michael@0 41704 var blocksPerLine = component.blocksPerLine;
michael@0 41705 var blocksPerColumn = component.blocksPerColumn;
michael@0 41706 var samplesPerLine = blocksPerLine << 3;
michael@0 41707
michael@0 41708 var j, k, ll = 0;
michael@0 41709 var lineOffset = 0;
michael@0 41710 for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
michael@0 41711 var scanLine = blockRow << 3;
michael@0 41712 for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
michael@0 41713 var bufferOffset = getBlockBufferOffset(component, blockRow, blockCol);
michael@0 41714 var offset = 0, sample = blockCol << 3;
michael@0 41715 for (j = 0; j < 8; j++) {
michael@0 41716 var lineOffset = (scanLine + j) * samplesPerLine;
michael@0 41717 for (k = 0; k < 8; k++) {
michael@0 41718 lineData[lineOffset + sample + k] =
michael@0 41719 component.output[bufferOffset + offset++];
michael@0 41720 }
michael@0 41721 }
michael@0 41722 }
michael@0 41723 }
michael@0 41724
michael@0 41725 componentScaleX = component.scaleX * scaleX;
michael@0 41726 componentScaleY = component.scaleY * scaleY;
michael@0 41727 offset = i;
michael@0 41728
michael@0 41729 var cx, cy;
michael@0 41730 var index;
michael@0 41731 for (y = 0; y < height; y++) {
michael@0 41732 for (x = 0; x < width; x++) {
michael@0 41733 cy = 0 | (y * componentScaleY);
michael@0 41734 cx = 0 | (x * componentScaleX);
michael@0 41735 index = cy * samplesPerLine + cx;
michael@0 41736 data[offset] = lineData[index];
michael@0 41737 offset += numComponents;
michael@0 41738 }
michael@0 41739 }
michael@0 41740 }
michael@0 41741
michael@0 41742 // ... then transform colors, if necessary
michael@0 41743 switch (numComponents) {
michael@0 41744 case 1: case 2: break;
michael@0 41745 // no color conversion for one or two compoenents
michael@0 41746
michael@0 41747 case 3:
michael@0 41748 // The default transform for three components is true
michael@0 41749 colorTransform = true;
michael@0 41750 // The adobe transform marker overrides any previous setting
michael@0 41751 if (this.adobe && this.adobe.transformCode)
michael@0 41752 colorTransform = true;
michael@0 41753 else if (typeof this.colorTransform !== 'undefined')
michael@0 41754 colorTransform = !!this.colorTransform;
michael@0 41755
michael@0 41756 if (colorTransform) {
michael@0 41757 for (i = 0; i < dataLength; i += numComponents) {
michael@0 41758 Y = data[i ];
michael@0 41759 Cb = data[i + 1];
michael@0 41760 Cr = data[i + 2];
michael@0 41761
michael@0 41762 R = clamp0to255(Y + 1.402 * (Cr - 128));
michael@0 41763 G = clamp0to255(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
michael@0 41764 B = clamp0to255(Y + 1.772 * (Cb - 128));
michael@0 41765
michael@0 41766 data[i ] = R;
michael@0 41767 data[i + 1] = G;
michael@0 41768 data[i + 2] = B;
michael@0 41769 }
michael@0 41770 }
michael@0 41771 break;
michael@0 41772 case 4:
michael@0 41773 // The default transform for four components is false
michael@0 41774 colorTransform = false;
michael@0 41775 // The adobe transform marker overrides any previous setting
michael@0 41776 if (this.adobe && this.adobe.transformCode)
michael@0 41777 colorTransform = true;
michael@0 41778 else if (typeof this.colorTransform !== 'undefined')
michael@0 41779 colorTransform = !!this.colorTransform;
michael@0 41780
michael@0 41781 if (colorTransform) {
michael@0 41782 for (i = 0; i < dataLength; i += numComponents) {
michael@0 41783 Y = data[i];
michael@0 41784 Cb = data[i + 1];
michael@0 41785 Cr = data[i + 2];
michael@0 41786
michael@0 41787 C = 255 - clamp0to255(Y + 1.402 * (Cr - 128));
michael@0 41788 M = 255 - clamp0to255(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
michael@0 41789 Ye = 255 - clamp0to255(Y + 1.772 * (Cb - 128));
michael@0 41790
michael@0 41791 data[i ] = C;
michael@0 41792 data[i + 1] = M;
michael@0 41793 data[i + 2] = Ye;
michael@0 41794 // K is unchanged
michael@0 41795 }
michael@0 41796 }
michael@0 41797 break;
michael@0 41798 default:
michael@0 41799 throw 'Unsupported color mode';
michael@0 41800 }
michael@0 41801 return data;
michael@0 41802 },
michael@0 41803 copyToImageData: function copyToImageData(imageData) {
michael@0 41804 var width = imageData.width, height = imageData.height;
michael@0 41805 var imageDataBytes = width * height * 4;
michael@0 41806 var imageDataArray = imageData.data;
michael@0 41807 var data = this.getData(width, height);
michael@0 41808 var i = 0, j = 0;
michael@0 41809 var Y, K, C, M, R, G, B;
michael@0 41810 switch (this.components.length) {
michael@0 41811 case 1:
michael@0 41812 while (j < imageDataBytes) {
michael@0 41813 Y = data[i++];
michael@0 41814
michael@0 41815 imageDataArray[j++] = Y;
michael@0 41816 imageDataArray[j++] = Y;
michael@0 41817 imageDataArray[j++] = Y;
michael@0 41818 imageDataArray[j++] = 255;
michael@0 41819 }
michael@0 41820 break;
michael@0 41821 case 3:
michael@0 41822 while (j < imageDataBytes) {
michael@0 41823 R = data[i++];
michael@0 41824 G = data[i++];
michael@0 41825 B = data[i++];
michael@0 41826
michael@0 41827 imageDataArray[j++] = R;
michael@0 41828 imageDataArray[j++] = G;
michael@0 41829 imageDataArray[j++] = B;
michael@0 41830 imageDataArray[j++] = 255;
michael@0 41831 }
michael@0 41832 break;
michael@0 41833 case 4:
michael@0 41834 while (j < imageDataBytes) {
michael@0 41835 C = data[i++];
michael@0 41836 M = data[i++];
michael@0 41837 Y = data[i++];
michael@0 41838 K = data[i++];
michael@0 41839
michael@0 41840 R = 255 - clamp0to255(C * (1 - K / 255) + K);
michael@0 41841 G = 255 - clamp0to255(M * (1 - K / 255) + K);
michael@0 41842 B = 255 - clamp0to255(Y * (1 - K / 255) + K);
michael@0 41843
michael@0 41844 imageDataArray[j++] = R;
michael@0 41845 imageDataArray[j++] = G;
michael@0 41846 imageDataArray[j++] = B;
michael@0 41847 imageDataArray[j++] = 255;
michael@0 41848 }
michael@0 41849 break;
michael@0 41850 default:
michael@0 41851 throw 'Unsupported color mode';
michael@0 41852 }
michael@0 41853 }
michael@0 41854 };
michael@0 41855
michael@0 41856 return constructor;
michael@0 41857 })();
michael@0 41858
michael@0 41859
michael@0 41860 }).call((typeof window === 'undefined') ? this : window);
michael@0 41861
michael@0 41862
michael@0 41863

mercurial