|  | @@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdfCombined = {}));
 | 
	
		
			
				|  |  |    // Use strict in our context only - users might not want it
 | 
	
		
			
				|  |  |    'use strict';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -var pdfjsVersion = '1.4.176';
 | 
	
		
			
				|  |  | -var pdfjsBuild = '447c48e';
 | 
	
		
			
				|  |  | +var pdfjsVersion = '1.4.179';
 | 
	
		
			
				|  |  | +var pdfjsBuild = '8910cea';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    var pdfjsFilePath =
 | 
	
		
			
				|  |  |      typeof document !== 'undefined' && document.currentScript ?
 | 
	
	
		
			
				|  | @@ -29398,6 +29398,7 @@ var shadow = sharedUtil.shadow;
 | 
	
		
			
				|  |  |  var stringToBytes = sharedUtil.stringToBytes;
 | 
	
		
			
				|  |  |  var string32 = sharedUtil.string32;
 | 
	
		
			
				|  |  |  var warn = sharedUtil.warn;
 | 
	
		
			
				|  |  | +var MissingDataException = sharedUtil.MissingDataException;
 | 
	
		
			
				|  |  |  var Stream = coreStream.Stream;
 | 
	
		
			
				|  |  |  var Lexer = coreParser.Lexer;
 | 
	
		
			
				|  |  |  var getGlyphsUnicode = coreGlyphList.getGlyphsUnicode;
 | 
	
	
		
			
				|  | @@ -32981,231 +32982,352 @@ var CFFStandardStrings = [
 | 
	
		
			
				|  |  |  ];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Type1Font is also a CIDFontType0.
 | 
	
		
			
				|  |  | -var Type1Font = function Type1Font(name, file, properties) {
 | 
	
		
			
				|  |  | -  // Some bad generators embed pfb file as is, we have to strip 6-byte headers.
 | 
	
		
			
				|  |  | -  // Also, length1 and length2 might be off by 6 bytes as well.
 | 
	
		
			
				|  |  | -  // http://www.math.ubc.ca/~cass/piscript/type1.pdf
 | 
	
		
			
				|  |  | -  var PFB_HEADER_SIZE = 6;
 | 
	
		
			
				|  |  | -  var headerBlockLength = properties.length1;
 | 
	
		
			
				|  |  | -  var eexecBlockLength = properties.length2;
 | 
	
		
			
				|  |  | -  var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
 | 
	
		
			
				|  |  | -  var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
 | 
	
		
			
				|  |  | -  if (pfbHeaderPresent) {
 | 
	
		
			
				|  |  | -    file.skip(PFB_HEADER_SIZE);
 | 
	
		
			
				|  |  | -    headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
 | 
	
		
			
				|  |  | -                        (pfbHeader[3] << 8) | pfbHeader[2];
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Get the data block containing glyphs and subrs informations
 | 
	
		
			
				|  |  | -  var headerBlock = new Stream(file.getBytes(headerBlockLength));
 | 
	
		
			
				|  |  | -  var headerBlockParser = new Type1Parser(headerBlock);
 | 
	
		
			
				|  |  | -  headerBlockParser.extractFontHeader(properties);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (pfbHeaderPresent) {
 | 
	
		
			
				|  |  | -    pfbHeader = file.getBytes(PFB_HEADER_SIZE);
 | 
	
		
			
				|  |  | -    eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
 | 
	
		
			
				|  |  | -                       (pfbHeader[3] << 8) | pfbHeader[2];
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Decrypt the data blocks and retrieve it's content
 | 
	
		
			
				|  |  | -  var eexecBlock = new Stream(file.getBytes(eexecBlockLength));
 | 
	
		
			
				|  |  | -  var eexecBlockParser = new Type1Parser(eexecBlock, true);
 | 
	
		
			
				|  |  | -  var data = eexecBlockParser.extractFontProgram();
 | 
	
		
			
				|  |  | -  for (var info in data.properties) {
 | 
	
		
			
				|  |  | -    properties[info] = data.properties[info];
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  var charstrings = data.charstrings;
 | 
	
		
			
				|  |  | -  var type2Charstrings = this.getType2Charstrings(charstrings);
 | 
	
		
			
				|  |  | -  var subrs = this.getType2Subrs(data.subrs);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  this.charstrings = charstrings;
 | 
	
		
			
				|  |  | -  this.data = this.wrap(name, type2Charstrings, this.charstrings,
 | 
	
		
			
				|  |  | -                        subrs, properties);
 | 
	
		
			
				|  |  | -  this.seacs = this.getSeacs(data.charstrings);
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | +var Type1Font = (function Type1FontClosure() {
 | 
	
		
			
				|  |  | +  function findBlock(streamBytes, signature, startIndex) {
 | 
	
		
			
				|  |  | +    var streamBytesLength = streamBytes.length;
 | 
	
		
			
				|  |  | +    var signatureLength = signature.length;
 | 
	
		
			
				|  |  | +    var scanLength = streamBytesLength - signatureLength;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    var i = startIndex, j, found = false;
 | 
	
		
			
				|  |  | +    while (i < scanLength) {
 | 
	
		
			
				|  |  | +      j = 0;
 | 
	
		
			
				|  |  | +      while (j < signatureLength && streamBytes[i + j] === signature[j]) {
 | 
	
		
			
				|  |  | +        j++;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (j >= signatureLength) { // `signature` found, skip over whitespace.
 | 
	
		
			
				|  |  | +        i += j;
 | 
	
		
			
				|  |  | +        while (i < streamBytesLength && Lexer.isSpace(streamBytes[i])) {
 | 
	
		
			
				|  |  | +          i++;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        found = true;
 | 
	
		
			
				|  |  | +        break;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      i++;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      found: found,
 | 
	
		
			
				|  |  | +      length: i,
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -Type1Font.prototype = {
 | 
	
		
			
				|  |  | -  get numGlyphs() {
 | 
	
		
			
				|  |  | -    return this.charstrings.length + 1;
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | +  function getHeaderBlock(stream, suggestedLength) {
 | 
	
		
			
				|  |  | +    var EEXEC_SIGNATURE = [0x65, 0x65, 0x78, 0x65, 0x63];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  getCharset: function Type1Font_getCharset() {
 | 
	
		
			
				|  |  | -    var charset = ['.notdef'];
 | 
	
		
			
				|  |  | -    var charstrings = this.charstrings;
 | 
	
		
			
				|  |  | -    for (var glyphId = 0; glyphId < charstrings.length; glyphId++) {
 | 
	
		
			
				|  |  | -      charset.push(charstrings[glyphId].glyphName);
 | 
	
		
			
				|  |  | +    var streamStartPos = stream.pos; // Save the initial stream position.
 | 
	
		
			
				|  |  | +    var headerBytes, headerBytesLength, block;
 | 
	
		
			
				|  |  | +    try {
 | 
	
		
			
				|  |  | +      headerBytes = stream.getBytes(suggestedLength);
 | 
	
		
			
				|  |  | +      headerBytesLength = headerBytes.length;
 | 
	
		
			
				|  |  | +    } catch (ex) {
 | 
	
		
			
				|  |  | +      if (ex instanceof MissingDataException) {
 | 
	
		
			
				|  |  | +        throw ex;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      // Ignore errors if the `suggestedLength` is huge enough that a Uint8Array
 | 
	
		
			
				|  |  | +      // cannot hold the result of `getBytes`, and fallback to simply checking
 | 
	
		
			
				|  |  | +      // the entire stream (fixes issue3928.pdf).
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return charset;
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  getGlyphMapping: function Type1Font_getGlyphMapping(properties) {
 | 
	
		
			
				|  |  | -    var charstrings = this.charstrings;
 | 
	
		
			
				|  |  | -    var glyphNames = ['.notdef'], glyphId;
 | 
	
		
			
				|  |  | -    for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
 | 
	
		
			
				|  |  | -      glyphNames.push(charstrings[glyphId].glyphName);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    var encoding = properties.builtInEncoding;
 | 
	
		
			
				|  |  | -    if (encoding) {
 | 
	
		
			
				|  |  | -      var builtInEncoding = Object.create(null);
 | 
	
		
			
				|  |  | -      for (var charCode in encoding) {
 | 
	
		
			
				|  |  | -        glyphId = glyphNames.indexOf(encoding[charCode]);
 | 
	
		
			
				|  |  | -        if (glyphId >= 0) {
 | 
	
		
			
				|  |  | -          builtInEncoding[charCode] = glyphId;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    if (headerBytesLength === suggestedLength) {
 | 
	
		
			
				|  |  | +      // Most of the time `suggestedLength` is correct, so to speed things up we
 | 
	
		
			
				|  |  | +      // initially only check the last few bytes to see if the header was found.
 | 
	
		
			
				|  |  | +      // Otherwise we (potentially) check the entire stream to prevent errors in
 | 
	
		
			
				|  |  | +      // `Type1Parser` (fixes issue5686.pdf).
 | 
	
		
			
				|  |  | +      block = findBlock(headerBytes, EEXEC_SIGNATURE,
 | 
	
		
			
				|  |  | +                        suggestedLength - 2 * EEXEC_SIGNATURE.length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (block.found && block.length === suggestedLength) {
 | 
	
		
			
				|  |  | +        return {
 | 
	
		
			
				|  |  | +          stream: new Stream(headerBytes),
 | 
	
		
			
				|  |  | +          length: suggestedLength,
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    warn('Invalid "Length1" property in Type1 font -- trying to recover.');
 | 
	
		
			
				|  |  | +    stream.pos = streamStartPos; // Reset the stream position.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | +    var SCAN_BLOCK_LENGTH = 2048;
 | 
	
		
			
				|  |  | +    var actualLength;
 | 
	
		
			
				|  |  | +    while (true) {
 | 
	
		
			
				|  |  | +      var scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
 | 
	
		
			
				|  |  | +      block = findBlock(scanBytes, EEXEC_SIGNATURE, 0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  getSeacs: function Type1Font_getSeacs(charstrings) {
 | 
	
		
			
				|  |  | -    var i, ii;
 | 
	
		
			
				|  |  | -    var seacMap = [];
 | 
	
		
			
				|  |  | -    for (i = 0, ii = charstrings.length; i < ii; i++) {
 | 
	
		
			
				|  |  | -      var charstring = charstrings[i];
 | 
	
		
			
				|  |  | -      if (charstring.seac) {
 | 
	
		
			
				|  |  | -        // Offset by 1 for .notdef
 | 
	
		
			
				|  |  | -        seacMap[i + 1] = charstring.seac;
 | 
	
		
			
				|  |  | +      if (block.length === 0) {
 | 
	
		
			
				|  |  | +        break;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      stream.pos += block.length; // Update the stream position.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (block.found) {
 | 
	
		
			
				|  |  | +        actualLength = stream.pos - streamStartPos;
 | 
	
		
			
				|  |  | +        break;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return seacMap;
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | +    stream.pos = streamStartPos; // Reset the stream position.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  getType2Charstrings: function Type1Font_getType2Charstrings(
 | 
	
		
			
				|  |  | -                                  type1Charstrings) {
 | 
	
		
			
				|  |  | -    var type2Charstrings = [];
 | 
	
		
			
				|  |  | -    for (var i = 0, ii = type1Charstrings.length; i < ii; i++) {
 | 
	
		
			
				|  |  | -      type2Charstrings.push(type1Charstrings[i].charstring);
 | 
	
		
			
				|  |  | +    if (actualLength) {
 | 
	
		
			
				|  |  | +      return {
 | 
	
		
			
				|  |  | +        stream: new Stream(stream.getBytes(actualLength)),
 | 
	
		
			
				|  |  | +        length: actualLength,
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    return type2Charstrings;
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | +    warn('Unable to recover "Length1" property in Type1 font -- using as is.');
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      stream: new Stream(stream.getBytes(suggestedLength)),
 | 
	
		
			
				|  |  | +      length: suggestedLength,
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
 | 
	
		
			
				|  |  | -    var bias = 0;
 | 
	
		
			
				|  |  | -    var count = type1Subrs.length;
 | 
	
		
			
				|  |  | -    if (count < 1133) {
 | 
	
		
			
				|  |  | -      bias = 107;
 | 
	
		
			
				|  |  | -    } else if (count < 33769) {
 | 
	
		
			
				|  |  | -      bias = 1131;
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      bias = 32768;
 | 
	
		
			
				|  |  | +  function getEexecBlock(stream, suggestedLength) {
 | 
	
		
			
				|  |  | +    // We should ideally parse the eexec block to ensure that `suggestedLength`
 | 
	
		
			
				|  |  | +    // is correct, so we don't truncate the block data if it's too small.
 | 
	
		
			
				|  |  | +    // However, this would also require checking if the fixed-content portion
 | 
	
		
			
				|  |  | +    // exists (using the 'Length3' property), and ensuring that it's valid.
 | 
	
		
			
				|  |  | +    //
 | 
	
		
			
				|  |  | +    // Given that `suggestedLength` almost always is correct, all the validation
 | 
	
		
			
				|  |  | +    // would require a great deal of unnecessary parsing for most fonts.
 | 
	
		
			
				|  |  | +    // To save time, we always fetch the entire stream instead, which also avoid
 | 
	
		
			
				|  |  | +    // issues if `suggestedLength` is huge (see comment in `getHeaderBlock`).
 | 
	
		
			
				|  |  | +    //
 | 
	
		
			
				|  |  | +    // NOTE: This means that the function can include the fixed-content portion
 | 
	
		
			
				|  |  | +    // in the returned eexec block. In practice this does *not* seem to matter,
 | 
	
		
			
				|  |  | +    // since `Type1Parser_extractFontProgram` will skip over any non-commands.
 | 
	
		
			
				|  |  | +    var eexecBytes = stream.getBytes();
 | 
	
		
			
				|  |  | +    return {
 | 
	
		
			
				|  |  | +      stream: new Stream(eexecBytes),
 | 
	
		
			
				|  |  | +      length: eexecBytes.length,
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  function Type1Font(name, file, properties) {
 | 
	
		
			
				|  |  | +    // Some bad generators embed pfb file as is, we have to strip 6-byte header.
 | 
	
		
			
				|  |  | +    // Also, length1 and length2 might be off by 6 bytes as well.
 | 
	
		
			
				|  |  | +    // http://www.math.ubc.ca/~cass/piscript/type1.pdf
 | 
	
		
			
				|  |  | +    var PFB_HEADER_SIZE = 6;
 | 
	
		
			
				|  |  | +    var headerBlockLength = properties.length1;
 | 
	
		
			
				|  |  | +    var eexecBlockLength = properties.length2;
 | 
	
		
			
				|  |  | +    var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
 | 
	
		
			
				|  |  | +    var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
 | 
	
		
			
				|  |  | +    if (pfbHeaderPresent) {
 | 
	
		
			
				|  |  | +      file.skip(PFB_HEADER_SIZE);
 | 
	
		
			
				|  |  | +      headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
 | 
	
		
			
				|  |  | +                          (pfbHeader[3] << 8) | pfbHeader[2];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // Add a bunch of empty subrs to deal with the Type2 bias
 | 
	
		
			
				|  |  | -    var type2Subrs = [];
 | 
	
		
			
				|  |  | -    var i;
 | 
	
		
			
				|  |  | -    for (i = 0; i < bias; i++) {
 | 
	
		
			
				|  |  | -      type2Subrs.push([0x0B]);
 | 
	
		
			
				|  |  | +    // Get the data block containing glyphs and subrs informations
 | 
	
		
			
				|  |  | +    var headerBlock = getHeaderBlock(file, headerBlockLength);
 | 
	
		
			
				|  |  | +    headerBlockLength = headerBlock.length;
 | 
	
		
			
				|  |  | +    var headerBlockParser = new Type1Parser(headerBlock.stream);
 | 
	
		
			
				|  |  | +    headerBlockParser.extractFontHeader(properties);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (pfbHeaderPresent) {
 | 
	
		
			
				|  |  | +      pfbHeader = file.getBytes(PFB_HEADER_SIZE);
 | 
	
		
			
				|  |  | +      eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
 | 
	
		
			
				|  |  | +                         (pfbHeader[3] << 8) | pfbHeader[2];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    for (i = 0; i < count; i++) {
 | 
	
		
			
				|  |  | -      type2Subrs.push(type1Subrs[i]);
 | 
	
		
			
				|  |  | +    // Decrypt the data blocks and retrieve it's content
 | 
	
		
			
				|  |  | +    var eexecBlock = getEexecBlock(file, eexecBlockLength);
 | 
	
		
			
				|  |  | +    eexecBlockLength = eexecBlock.length;
 | 
	
		
			
				|  |  | +    var eexecBlockParser = new Type1Parser(eexecBlock.stream, true);
 | 
	
		
			
				|  |  | +    var data = eexecBlockParser.extractFontProgram();
 | 
	
		
			
				|  |  | +    for (var info in data.properties) {
 | 
	
		
			
				|  |  | +      properties[info] = data.properties[info];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    return type2Subrs;
 | 
	
		
			
				|  |  | -  },
 | 
	
		
			
				|  |  | +    var charstrings = data.charstrings;
 | 
	
		
			
				|  |  | +    var type2Charstrings = this.getType2Charstrings(charstrings);
 | 
	
		
			
				|  |  | +    var subrs = this.getType2Subrs(data.subrs);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
 | 
	
		
			
				|  |  | -    var cff = new CFF();
 | 
	
		
			
				|  |  | -    cff.header = new CFFHeader(1, 0, 4, 4);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    cff.names = [name];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    var topDict = new CFFTopDict();
 | 
	
		
			
				|  |  | -    // CFF strings IDs 0...390 are predefined names, so refering
 | 
	
		
			
				|  |  | -    // to entries in our own String INDEX starts at SID 391.
 | 
	
		
			
				|  |  | -    topDict.setByName('version', 391);
 | 
	
		
			
				|  |  | -    topDict.setByName('Notice', 392);
 | 
	
		
			
				|  |  | -    topDict.setByName('FullName', 393);
 | 
	
		
			
				|  |  | -    topDict.setByName('FamilyName', 394);
 | 
	
		
			
				|  |  | -    topDict.setByName('Weight', 395);
 | 
	
		
			
				|  |  | -    topDict.setByName('Encoding', null); // placeholder
 | 
	
		
			
				|  |  | -    topDict.setByName('FontMatrix', properties.fontMatrix);
 | 
	
		
			
				|  |  | -    topDict.setByName('FontBBox', properties.bbox);
 | 
	
		
			
				|  |  | -    topDict.setByName('charset', null); // placeholder
 | 
	
		
			
				|  |  | -    topDict.setByName('CharStrings', null); // placeholder
 | 
	
		
			
				|  |  | -    topDict.setByName('Private', null); // placeholder
 | 
	
		
			
				|  |  | -    cff.topDict = topDict;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    var strings = new CFFStrings();
 | 
	
		
			
				|  |  | -    strings.add('Version 0.11'); // Version
 | 
	
		
			
				|  |  | -    strings.add('See original notice'); // Notice
 | 
	
		
			
				|  |  | -    strings.add(name); // FullName
 | 
	
		
			
				|  |  | -    strings.add(name); // FamilyName
 | 
	
		
			
				|  |  | -    strings.add('Medium'); // Weight
 | 
	
		
			
				|  |  | -    cff.strings = strings;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    cff.globalSubrIndex = new CFFIndex();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    var count = glyphs.length;
 | 
	
		
			
				|  |  | -    var charsetArray = [0];
 | 
	
		
			
				|  |  | -    var i, ii;
 | 
	
		
			
				|  |  | -    for (i = 0; i < count; i++) {
 | 
	
		
			
				|  |  | -      var index = CFFStandardStrings.indexOf(charstrings[i].glyphName);
 | 
	
		
			
				|  |  | -      // TODO: Insert the string and correctly map it.  Previously it was
 | 
	
		
			
				|  |  | -      // thought mapping names that aren't in the standard strings to .notdef
 | 
	
		
			
				|  |  | -      // was fine, however in issue818 when mapping them all to .notdef the
 | 
	
		
			
				|  |  | -      // adieresis glyph no longer worked.
 | 
	
		
			
				|  |  | -      if (index === -1) {
 | 
	
		
			
				|  |  | -        index = 0;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      charsetArray.push((index >> 8) & 0xff, index & 0xff);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    cff.charset = new CFFCharset(false, 0, [], charsetArray);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    var charStringsIndex = new CFFIndex();
 | 
	
		
			
				|  |  | -    charStringsIndex.add([0x8B, 0x0E]); // .notdef
 | 
	
		
			
				|  |  | -    for (i = 0; i < count; i++) {
 | 
	
		
			
				|  |  | -      charStringsIndex.add(glyphs[i]);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    cff.charStrings = charStringsIndex;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    var privateDict = new CFFPrivateDict();
 | 
	
		
			
				|  |  | -    privateDict.setByName('Subrs', null); // placeholder
 | 
	
		
			
				|  |  | -    var fields = [
 | 
	
		
			
				|  |  | -      'BlueValues',
 | 
	
		
			
				|  |  | -      'OtherBlues',
 | 
	
		
			
				|  |  | -      'FamilyBlues',
 | 
	
		
			
				|  |  | -      'FamilyOtherBlues',
 | 
	
		
			
				|  |  | -      'StemSnapH',
 | 
	
		
			
				|  |  | -      'StemSnapV',
 | 
	
		
			
				|  |  | -      'BlueShift',
 | 
	
		
			
				|  |  | -      'BlueFuzz',
 | 
	
		
			
				|  |  | -      'BlueScale',
 | 
	
		
			
				|  |  | -      'LanguageGroup',
 | 
	
		
			
				|  |  | -      'ExpansionFactor',
 | 
	
		
			
				|  |  | -      'ForceBold',
 | 
	
		
			
				|  |  | -      'StdHW',
 | 
	
		
			
				|  |  | -      'StdVW'
 | 
	
		
			
				|  |  | -    ];
 | 
	
		
			
				|  |  | -    for (i = 0, ii = fields.length; i < ii; i++) {
 | 
	
		
			
				|  |  | -      var field = fields[i];
 | 
	
		
			
				|  |  | -      if (!(field in properties.privateData)) {
 | 
	
		
			
				|  |  | -        continue;
 | 
	
		
			
				|  |  | +    this.charstrings = charstrings;
 | 
	
		
			
				|  |  | +    this.data = this.wrap(name, type2Charstrings, this.charstrings,
 | 
	
		
			
				|  |  | +                          subrs, properties);
 | 
	
		
			
				|  |  | +    this.seacs = this.getSeacs(data.charstrings);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  Type1Font.prototype = {
 | 
	
		
			
				|  |  | +    get numGlyphs() {
 | 
	
		
			
				|  |  | +      return this.charstrings.length + 1;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    getCharset: function Type1Font_getCharset() {
 | 
	
		
			
				|  |  | +      var charset = ['.notdef'];
 | 
	
		
			
				|  |  | +      var charstrings = this.charstrings;
 | 
	
		
			
				|  |  | +      for (var glyphId = 0; glyphId < charstrings.length; glyphId++) {
 | 
	
		
			
				|  |  | +        charset.push(charstrings[glyphId].glyphName);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return charset;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    getGlyphMapping: function Type1Font_getGlyphMapping(properties) {
 | 
	
		
			
				|  |  | +      var charstrings = this.charstrings;
 | 
	
		
			
				|  |  | +      var glyphNames = ['.notdef'], glyphId;
 | 
	
		
			
				|  |  | +      for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
 | 
	
		
			
				|  |  | +        glyphNames.push(charstrings[glyphId].glyphName);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      var value = properties.privateData[field];
 | 
	
		
			
				|  |  | -      if (isArray(value)) {
 | 
	
		
			
				|  |  | -        // All of the private dictionary array data in CFF must be stored as
 | 
	
		
			
				|  |  | -        // "delta-encoded" numbers.
 | 
	
		
			
				|  |  | -        for (var j = value.length - 1; j > 0; j--) {
 | 
	
		
			
				|  |  | -          value[j] -= value[j - 1]; // ... difference from previous value
 | 
	
		
			
				|  |  | +      var encoding = properties.builtInEncoding;
 | 
	
		
			
				|  |  | +      if (encoding) {
 | 
	
		
			
				|  |  | +        var builtInEncoding = Object.create(null);
 | 
	
		
			
				|  |  | +        for (var charCode in encoding) {
 | 
	
		
			
				|  |  | +          glyphId = glyphNames.indexOf(encoding[charCode]);
 | 
	
		
			
				|  |  | +          if (glyphId >= 0) {
 | 
	
		
			
				|  |  | +            builtInEncoding[charCode] = glyphId;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      privateDict.setByName(field, value);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    cff.topDict.privateDict = privateDict;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    var subrIndex = new CFFIndex();
 | 
	
		
			
				|  |  | -    for (i = 0, ii = subrs.length; i < ii; i++) {
 | 
	
		
			
				|  |  | -      subrIndex.add(subrs[i]);
 | 
	
		
			
				|  |  | +      return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    getSeacs: function Type1Font_getSeacs(charstrings) {
 | 
	
		
			
				|  |  | +      var i, ii;
 | 
	
		
			
				|  |  | +      var seacMap = [];
 | 
	
		
			
				|  |  | +      for (i = 0, ii = charstrings.length; i < ii; i++) {
 | 
	
		
			
				|  |  | +        var charstring = charstrings[i];
 | 
	
		
			
				|  |  | +        if (charstring.seac) {
 | 
	
		
			
				|  |  | +          // Offset by 1 for .notdef
 | 
	
		
			
				|  |  | +          seacMap[i + 1] = charstring.seac;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return seacMap;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    getType2Charstrings: function Type1Font_getType2Charstrings(
 | 
	
		
			
				|  |  | +                                    type1Charstrings) {
 | 
	
		
			
				|  |  | +      var type2Charstrings = [];
 | 
	
		
			
				|  |  | +      for (var i = 0, ii = type1Charstrings.length; i < ii; i++) {
 | 
	
		
			
				|  |  | +        type2Charstrings.push(type1Charstrings[i].charstring);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return type2Charstrings;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
 | 
	
		
			
				|  |  | +      var bias = 0;
 | 
	
		
			
				|  |  | +      var count = type1Subrs.length;
 | 
	
		
			
				|  |  | +      if (count < 1133) {
 | 
	
		
			
				|  |  | +        bias = 107;
 | 
	
		
			
				|  |  | +      } else if (count < 33769) {
 | 
	
		
			
				|  |  | +        bias = 1131;
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        bias = 32768;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Add a bunch of empty subrs to deal with the Type2 bias
 | 
	
		
			
				|  |  | +      var type2Subrs = [];
 | 
	
		
			
				|  |  | +      var i;
 | 
	
		
			
				|  |  | +      for (i = 0; i < bias; i++) {
 | 
	
		
			
				|  |  | +        type2Subrs.push([0x0B]);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      for (i = 0; i < count; i++) {
 | 
	
		
			
				|  |  | +        type2Subrs.push(type1Subrs[i]);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      return type2Subrs;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs,
 | 
	
		
			
				|  |  | +                                  properties) {
 | 
	
		
			
				|  |  | +      var cff = new CFF();
 | 
	
		
			
				|  |  | +      cff.header = new CFFHeader(1, 0, 4, 4);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      cff.names = [name];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var topDict = new CFFTopDict();
 | 
	
		
			
				|  |  | +      // CFF strings IDs 0...390 are predefined names, so refering
 | 
	
		
			
				|  |  | +      // to entries in our own String INDEX starts at SID 391.
 | 
	
		
			
				|  |  | +      topDict.setByName('version', 391);
 | 
	
		
			
				|  |  | +      topDict.setByName('Notice', 392);
 | 
	
		
			
				|  |  | +      topDict.setByName('FullName', 393);
 | 
	
		
			
				|  |  | +      topDict.setByName('FamilyName', 394);
 | 
	
		
			
				|  |  | +      topDict.setByName('Weight', 395);
 | 
	
		
			
				|  |  | +      topDict.setByName('Encoding', null); // placeholder
 | 
	
		
			
				|  |  | +      topDict.setByName('FontMatrix', properties.fontMatrix);
 | 
	
		
			
				|  |  | +      topDict.setByName('FontBBox', properties.bbox);
 | 
	
		
			
				|  |  | +      topDict.setByName('charset', null); // placeholder
 | 
	
		
			
				|  |  | +      topDict.setByName('CharStrings', null); // placeholder
 | 
	
		
			
				|  |  | +      topDict.setByName('Private', null); // placeholder
 | 
	
		
			
				|  |  | +      cff.topDict = topDict;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var strings = new CFFStrings();
 | 
	
		
			
				|  |  | +      strings.add('Version 0.11'); // Version
 | 
	
		
			
				|  |  | +      strings.add('See original notice'); // Notice
 | 
	
		
			
				|  |  | +      strings.add(name); // FullName
 | 
	
		
			
				|  |  | +      strings.add(name); // FamilyName
 | 
	
		
			
				|  |  | +      strings.add('Medium'); // Weight
 | 
	
		
			
				|  |  | +      cff.strings = strings;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      cff.globalSubrIndex = new CFFIndex();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var count = glyphs.length;
 | 
	
		
			
				|  |  | +      var charsetArray = [0];
 | 
	
		
			
				|  |  | +      var i, ii;
 | 
	
		
			
				|  |  | +      for (i = 0; i < count; i++) {
 | 
	
		
			
				|  |  | +        var index = CFFStandardStrings.indexOf(charstrings[i].glyphName);
 | 
	
		
			
				|  |  | +        // TODO: Insert the string and correctly map it.  Previously it was
 | 
	
		
			
				|  |  | +        // thought mapping names that aren't in the standard strings to .notdef
 | 
	
		
			
				|  |  | +        // was fine, however in issue818 when mapping them all to .notdef the
 | 
	
		
			
				|  |  | +        // adieresis glyph no longer worked.
 | 
	
		
			
				|  |  | +        if (index === -1) {
 | 
	
		
			
				|  |  | +          index = 0;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        charsetArray.push((index >> 8) & 0xff, index & 0xff);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      cff.charset = new CFFCharset(false, 0, [], charsetArray);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var charStringsIndex = new CFFIndex();
 | 
	
		
			
				|  |  | +      charStringsIndex.add([0x8B, 0x0E]); // .notdef
 | 
	
		
			
				|  |  | +      for (i = 0; i < count; i++) {
 | 
	
		
			
				|  |  | +        charStringsIndex.add(glyphs[i]);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      cff.charStrings = charStringsIndex;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var privateDict = new CFFPrivateDict();
 | 
	
		
			
				|  |  | +      privateDict.setByName('Subrs', null); // placeholder
 | 
	
		
			
				|  |  | +      var fields = [
 | 
	
		
			
				|  |  | +        'BlueValues',
 | 
	
		
			
				|  |  | +        'OtherBlues',
 | 
	
		
			
				|  |  | +        'FamilyBlues',
 | 
	
		
			
				|  |  | +        'FamilyOtherBlues',
 | 
	
		
			
				|  |  | +        'StemSnapH',
 | 
	
		
			
				|  |  | +        'StemSnapV',
 | 
	
		
			
				|  |  | +        'BlueShift',
 | 
	
		
			
				|  |  | +        'BlueFuzz',
 | 
	
		
			
				|  |  | +        'BlueScale',
 | 
	
		
			
				|  |  | +        'LanguageGroup',
 | 
	
		
			
				|  |  | +        'ExpansionFactor',
 | 
	
		
			
				|  |  | +        'ForceBold',
 | 
	
		
			
				|  |  | +        'StdHW',
 | 
	
		
			
				|  |  | +        'StdVW'
 | 
	
		
			
				|  |  | +      ];
 | 
	
		
			
				|  |  | +      for (i = 0, ii = fields.length; i < ii; i++) {
 | 
	
		
			
				|  |  | +        var field = fields[i];
 | 
	
		
			
				|  |  | +        if (!(field in properties.privateData)) {
 | 
	
		
			
				|  |  | +          continue;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        var value = properties.privateData[field];
 | 
	
		
			
				|  |  | +        if (isArray(value)) {
 | 
	
		
			
				|  |  | +          // All of the private dictionary array data in CFF must be stored as
 | 
	
		
			
				|  |  | +          // "delta-encoded" numbers.
 | 
	
		
			
				|  |  | +          for (var j = value.length - 1; j > 0; j--) {
 | 
	
		
			
				|  |  | +            value[j] -= value[j - 1]; // ... difference from previous value
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        privateDict.setByName(field, value);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      cff.topDict.privateDict = privateDict;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var subrIndex = new CFFIndex();
 | 
	
		
			
				|  |  | +      for (i = 0, ii = subrs.length; i < ii; i++) {
 | 
	
		
			
				|  |  | +        subrIndex.add(subrs[i]);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      privateDict.subrsIndex = subrIndex;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var compiler = new CFFCompiler(cff);
 | 
	
		
			
				|  |  | +      return compiler.compile();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    privateDict.subrsIndex = subrIndex;
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    var compiler = new CFFCompiler(cff);
 | 
	
		
			
				|  |  | -    return compiler.compile();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | +  return Type1Font;
 | 
	
		
			
				|  |  | +})();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  var CFFFont = (function CFFFontClosure() {
 | 
	
		
			
				|  |  |    function CFFFont(file, properties) {
 | 
	
	
		
			
				|  | @@ -46977,6 +47099,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  |            var length1 = fontFile.dict.get('Length1');
 | 
	
		
			
				|  |  |            var length2 = fontFile.dict.get('Length2');
 | 
	
		
			
				|  |  | +          var length3 = fontFile.dict.get('Length3');
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -46987,6 +47110,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 | 
	
		
			
				|  |  |          file: fontFile,
 | 
	
		
			
				|  |  |          length1: length1,
 | 
	
		
			
				|  |  |          length2: length2,
 | 
	
		
			
				|  |  | +        length3: length3,
 | 
	
		
			
				|  |  |          loadedName: baseDict.loadedName,
 | 
	
		
			
				|  |  |          composite: composite,
 | 
	
		
			
				|  |  |          wideChars: composite,
 |