diff --git a/gulpfile.mjs b/gulpfile.mjs index 7da95fea12d6f..86d3b6bbafb9c 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -1585,7 +1585,6 @@ function buildLib(defines, dir) { gulp.src( [ "src/{core,display,shared}/**/*.js", - "!src/shared/{cffStandardStrings,fonts_utils}.js", "src/{pdf,pdf.image_decoders,pdf.worker}.js", ], { base: "src/" } diff --git a/src/shared/cffStandardStrings.js b/src/shared/cffStandardStrings.js deleted file mode 100644 index fbfc1378be5f9..0000000000000 --- a/src/shared/cffStandardStrings.js +++ /dev/null @@ -1,311 +0,0 @@ -/* Copyright 2012 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -var CFFEncodingMap = { - '0': '-reserved-', - '1': 'hstem', - '2': '-reserved-', - '3': 'vstem', - '4': 'vmoveto', - '5': 'rlineto', - '6': 'hlineto', - '7': 'vlineto', - '8': 'rrcurveto', - '9': '-reserved-', - '10': 'callsubr', - '11': 'return', - '12': { - '3': 'and', - '4': 'or', - '5': 'not', - '9': 'abs', - '10': 'add', - '11': 'div', - '12': 'sub', - '14': 'neg', - '15': 'eq', - '18': 'drop', - '20': 'put', - '21': 'get', - '22': 'ifelse', - '23': 'random', - '24': 'mul', - '26': 'sqrt', - '27': 'dup', - '28': 'exch', - '29': 'index', - '30': 'roll', - '34': 'hflex', - '35': 'flex', - '36': 'hflex1', - '37': 'flex1' - }, - '13': '-reserved-', - '14': 'endchar', - '15': '-reserved-', - '16': '-reserved-', - '17': '-reserved-', - '18': 'hstemhm', - '19': 'hintmask', - '20': 'cntrmask', - '21': 'rmoveto', - '22': 'hmoveto', - '23': 'vstemhm', - '24': 'rcurveline', - '25': 'rlivecurve', - '26': 'vvcurveto', - '27': 'hhcurveto', - '29': 'callgsubr', - '30': 'vhcurveto', - '31': 'hvcurveto' -}; - -var CFFDictDataMap = { - '0': { - name: 'version', - operand: 'SID' - }, - '1': { - name: 'Notice', - operand: 'SID' - }, - '2': { - name: 'FullName', - operand: 'SID' - }, - '3': { - name: 'FamilyName', - operand: 'SID' - }, - '4': { - name: 'Weight', - operand: 'SID' - }, - '5': { - name: 'FontBBox', - operand: [0, 0, 0, 0] - }, - '6': { - name: 'BlueValues' - }, - '7': { - name: 'OtherBlues' - }, - '8': { - name: 'FamilyBlues' - }, - '9': { - name: 'FamilyOtherBlues' - }, - '10': { - name: 'StdHW' - }, - '11': { - name: 'StdVW' - }, - '12': { - '0': { - name: 'Copyright', - operand: 'SID' - }, - '1': { - name: 'IsFixedPitch', - operand: false - }, - '2': { - name: 'ItalicAngle', - operand: 0 - }, - '3': { - name: 'UnderlinePosition', - operand: -100 - }, - '4': { - name: 'UnderlineThickness', - operand: 50 - }, - '5': { - name: 'PaintType', - operand: 0 - }, - '6': { - name: 'CharstringType', - operand: 2 - }, - '7': { - name: 'FontMatrix', - operand: [0.001, 0, 0, 0.001, 0, 0] - }, - '8': { - name: 'StrokeWidth', - operand: 0 - }, - '9': { - name: 'BlueScale' - }, - '10': { - name: 'BlueShift' - }, - '11': { - name: 'BlueFuzz' - }, - '12': { - name: 'StemSnapH' - }, - '13': { - name: 'StemSnapV' - }, - '14': { - name: 'ForceBold' - }, - '17': { - name: 'LanguageGroup' - }, - '18': { - name: 'ExpansionFactor' - }, - '19': { - name: 'initialRandomSeed' - }, - '20': { - name: 'SyntheticBase', - operand: null - }, - '21': { - name: 'PostScript', - operand: 'SID' - }, - '22': { - name: 'BaseFontName', - operand: 'SID' - }, - '23': { - name: 'BaseFontBlend', - operand: 'delta' - } - }, - '13': { - name: 'UniqueID', - operand: null - }, - '14': { - name: 'XUID', - operand: [] - }, - '15': { - name: 'charset', - operand: 0 - }, - '16': { - name: 'Encoding', - operand: 0 - }, - '17': { - name: 'CharStrings', - operand: null - }, - '18': { - name: 'Private', - operand: 'number number' - }, - '19': { - name: 'Subrs' - }, - '20': { - name: 'defaultWidthX' - }, - '21': { - name: 'nominalWidthX' - } -}; - -var CFFDictPrivateDataMap = { - '6': { - name: 'BluesValues', - operand: 'delta' - }, - '7': { - name: 'OtherBlues', - operand: 'delta' - }, - '8': { - name: 'FamilyBlues', - operand: 'delta' - }, - '9': { - name: 'FamilyOtherBlues', - operand: 'delta' - }, - '10': { - name: 'StdHW', - operand: null - }, - '11': { - name: 'StdVW', - operand: null - }, - '12': { - '9': { - name: 'BlueScale', - operand: 0.039625 - }, - '10': { - name: 'BlueShift', - operand: 7 - }, - '11': { - name: 'BlueFuzz', - operand: 1 - }, - '12': { - name: 'StemSnapH', - operand: 'delta' - }, - '13': { - name: 'StemSnapV', - operand: 'delta' - }, - '14': { - name: 'ForceBold', - operand: 'boolean' - }, - '17': { - name: 'LanguageGroup', - operand: 0 - }, - '18': { - name: 'ExpansionFactor', - operand: 0.06 - }, - '19': { - name: 'initialRandomSeed', - operand: 0 - } - }, - '19': { - name: 'Subrs', - operand: null - }, - '20': { - name: 'defaultWidthX', - operand: 0 - }, - '21': { - name: 'nominalWidthX', - operand: 0 - } -}; diff --git a/src/shared/fonts_utils.js b/src/shared/fonts_utils.js deleted file mode 100644 index d2a51698a368d..0000000000000 --- a/src/shared/fonts_utils.js +++ /dev/null @@ -1,429 +0,0 @@ -/* Copyright 2012 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* globals CFFDictDataMap, CFFDictPrivateDataMap, CFFEncodingMap, CFFStrings, - Components, Dict, dump, FormatError, netscape, Stream */ - -'use strict'; - -/* - * The Type2 reader code below is only used for debugging purpose since Type2 - * is only a CharString format and is never used directly as a Font file. - * - * So the code here is useful for dumping the data content of a .cff file in - * order to investigate the similarity between a Type1 CharString and a Type2 - * CharString or to understand the structure of the CFF format. - */ - -/* - * Build a charset by assigning the glyph name and the human readable form - * of the glyph data. - */ -function readCharset(aStream, aCharstrings) { - var charset = {}; - - var format = aStream.getByte(); - var count = aCharstrings.length - 1; - var i, sid; - if (format === 0) { - charset['.notdef'] = readCharstringEncoding(aCharstrings[0]); - - for (i = 1; i < count + 1; i++) { - sid = aStream.getByte() << 8 | aStream.getByte(); - charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]); - } - } else if (format === 1) { - for (i = 1; i < count + 1; i++) { - var first = aStream.getByte(); - first = (first << 8) | aStream.getByte(); - var numLeft = aStream.getByte(); - for (var j = 0; j <= numLeft; j++) { - sid = first++; - charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[j]); - } - } - } else { - throw new FormatError('Invalid charset format'); - } - - return charset; -} - -/* - * Take a Type2 binary charstring as input and transform it to a human - * readable representation as specified by the 'The Type 2 Charstring Format', - * chapter 3.1. - */ -function readCharstringEncoding(aString) { - if (!aString) { - return ''; - } - - var charstringTokens = []; - - var count = aString.length; - for (var i = 0; i < count; ) { - var value = aString[i++] | 0; - var token = null; - - if (value < 0) { - continue; - } else if (value <= 11) { - token = CFFEncodingMap[value]; - } else if (value === 12) { - token = CFFEncodingMap[value][aString[i++]]; - } else if (value <= 18) { - token = CFFEncodingMap[value]; - } else if (value <= 20) { - ++i; // var mask = aString[i++]; - token = CFFEncodingMap[value]; - } else if (value <= 27) { - token = CFFEncodingMap[value]; - } else if (value === 28) { - token = aString[i++] << 8 | aString[i++]; - } else if (value <= 31) { - token = CFFEncodingMap[value]; - } else if (value < 247) { - token = parseInt(value, 10) - 139; - } else if (value < 251) { - token = (value - 247) * 256 + aString[i++] + 108; - } else if (value < 255) { - token = -(value - 251) * 256 - aString[i++] - 108; - } else { // value === 255 - token = aString[i++] << 24 | aString[i++] << 16 | - aString[i++] << 8 | aString[i]; - } - - charstringTokens.push(token); - } - - return charstringTokens; -} - - -/* - * Take a binary DICT Data as input and transform it into a human readable - * form as specified by 'The Compact Font Format Specification', chapter 5. - */ -function readFontDictData(aString, aMap) { - var fontDictDataTokens = []; - - var count = aString.length; - for (var i = 0; i < count; ) { - var value = aString[i++] | 0; - var token = null; - - if (value === 12) { - token = aMap[value][aString[i++]]; - } else if (value === 28) { - token = aString[i++] << 8 | aString[i++]; - } else if (value === 29) { - token = aString[i++] << 24 | - aString[i++] << 16 | - aString[i++] << 8 | - aString[i++]; - } else if (value === 30) { - token = ''; - var parsed = false; - while (!parsed) { - var octet = aString[i++]; - - var nibbles = [parseInt(octet / 16, 10), parseInt(octet % 16, 10)]; - for (var j = 0; j < nibbles.length; j++) { - var nibble = nibbles[j]; - switch (nibble) { - case 0xA: - token += '.'; - break; - case 0xB: - token += 'E'; - break; - case 0xC: - token += 'E-'; - break; - case 0xD: - break; - case 0xE: - token += '-'; - break; - case 0xF: - parsed = true; - break; - default: - token += nibble; - break; - } - } - } - token = parseFloat(token); - } else if (value <= 31) { - token = aMap[value]; - } else if (value <= 246) { - token = parseInt(value, 10) - 139; - } else if (value <= 250) { - token = (value - 247) * 256 + aString[i++] + 108; - } else if (value <= 254) { - token = -(value - 251) * 256 - aString[i++] - 108; - } else if (value === 255) { - throw new FormatError('255 is not a valid DICT command'); - } - - fontDictDataTokens.push(token); - } - - return fontDictDataTokens; -} - -/* - * Take a stream as input and return an array of objects. - * In CFF an INDEX is a structure with the following format: - * { - * count: 2 bytes (Number of objects stored in INDEX), - * offsize: 1 byte (Offset array element size), - * offset: [count + 1] bytes (Offsets array), - * data: - (Objects data) - * } - * - * More explanation are given in the 'CFF Font Format Specification', - * chapter 5. - */ -function readFontIndexData(aStream, aIsByte) { - var count = aStream.getByte() << 8 | aStream.getByte(); - var offsize = aStream.getByte(); - - function getNextOffset() { - switch (offsize) { - case 0: - return 0; - case 1: - return aStream.getByte(); - case 2: - return aStream.getByte() << 8 | aStream.getByte(); - case 3: - return aStream.getByte() << 16 | aStream.getByte() << 8 | - aStream.getByte(); - case 4: - return aStream.getByte() << 24 | aStream.getByte() << 16 | - aStream.getByte() << 8 | aStream.getByte(); - } - throw new FormatError(offsize + ' is not a valid offset size'); - } - - var offsets = []; - var i; - for (i = 0; i < count + 1; i++) { - offsets.push(getNextOffset()); - } - - dump('Found ' + count + ' objects at offsets :' + - offsets + ' (offsize: ' + offsize + ')'); - - // Now extract the objects - var relativeOffset = aStream.pos; - var objects = []; - for (i = 0; i < count; i++) { - var offset = offsets[i]; - aStream.pos = relativeOffset + offset - 1; - - var data = []; - var length = offsets[i + 1] - 1; - for (var j = offset - 1; j < length; j++) { - data.push(aIsByte ? aStream.getByte() : aStream.getChar()); - } - objects.push(data); - } - - return objects; -} - -var Type2Parser = function type2Parser(aFilePath) { - var font = new Dict(null); - - var xhr = new XMLHttpRequest(); - xhr.open('GET', aFilePath, false); - xhr.responseType = 'arraybuffer'; - xhr.expected = document.URL.startsWith('file:') ? 0 : 200; - xhr.send(null); - this.data = new Stream(xhr.response); - - // Turn on this flag for additional debugging logs - var debug = false; - - function dump(aStr) { - if (debug) { - console.log(aStr); - } - } - - function parseAsToken(aString, aMap) { - var decoded = readFontDictData(aString, aMap); - - var stack = []; - var count = decoded.length; - for (var i = 0; i < count; i++) { - var token = decoded[i]; - if (typeof token === "number") { - stack.push(token); - } else { - switch (token.operand) { - case 'SID': - font.set(token.name, CFFStrings[stack.pop()]); - break; - case 'number number': - font.set(token.name, { - offset: stack.pop(), - size: stack.pop() - }); - break; - case 'boolean': - font.set(token.name, stack.pop()); - break; - case 'delta': - font.set(token.name, stack.pop()); - break; - default: - if (token.operand?.length) { - var array = []; - for (var j = 0; j < token.operand.length; j++) { - array.push(stack.pop()); - } - font.set(token.name, array); - } else { - font.set(token.name, stack.pop()); - } - break; - } - } - } - } - - this.parse = function type2ParserParse(aStream) { - font.set('major', aStream.getByte()); - font.set('minor', aStream.getByte()); - font.set('hdrSize', aStream.getByte()); - font.set('offsize', aStream.getByte()); - - // Read the NAME Index - dump('Reading Index: Names'); - font.set('Names', readFontIndexData(aStream)); - dump('Names: ' + font.get('Names')); - - // Read the Top Dict Index - dump('Reading Index: TopDict'); - var topDict = readFontIndexData(aStream, true); - dump('TopDict: ' + topDict); - - // Read the String Index - dump('Reading Index: Strings'); - var strings = readFontIndexData(aStream); - dump('strings: ' + strings); - - // Fill up the Strings dictionary with the new unique strings - var i; - for (i = 0; i < strings.length; i++) { - CFFStrings.push(strings[i].join('')); - } - - // Parse the TopDict operator - var count = topDict.length; - for (i = 0; i < count; i++) { - parseAsToken(topDict[i], CFFDictDataMap); - } - - // Read the Global Subr Index that comes just after the Strings Index - // (cf. "The Compact Font Format Specification" Chapter 16) - dump('Reading Global Subr Index'); - var subrs = readFontIndexData(aStream, true); - dump(subrs); - - // Reading Private Dict - var priv = font.get('Private'); - dump('Reading Private Dict (offset: ' + priv.offset + - ' size: ' + priv.size + ')'); - aStream.pos = priv.offset; - - var privateDict = []; - for (i = 0; i < priv.size; i++) { - privateDict.push(aStream.getByte()); - } - dump('privateData:' + privateDict); - parseAsToken(privateDict, CFFDictPrivateDataMap); - - font.forEach(function(key, value) { - dump(key + '::' + value); - }); - - // Read CharStrings Index - var charStringsOffset = font.get('CharStrings'); - dump('Read CharStrings Index (offset: ' + charStringsOffset + ')'); - aStream.pos = charStringsOffset; - var charStrings = readFontIndexData(aStream, true); - - // Read Charset - dump('Read Charset for ' + charStrings.length + ' glyphs'); - var charsetEntry = font.get('charset'); - if (charsetEntry === 0) { - throw new FormatError('Need to support CFFISOAdobeCharset'); - } else if (charsetEntry === 1) { - throw new FormatError('Need to support CFFExpert'); - } else if (charsetEntry === 2) { - throw new FormatError('Need to support CFFExpertSubsetCharset'); - } else { - aStream.pos = charsetEntry; - readCharset(aStream, charStrings); - } - }; -}; - -/* - * To try the Type2 decoder on a local file in the current directory: - * - * var cff = new Type2Parser("file.cff"); - * cff.parse(this.data); - * - * To try the Type2 decoder on a custom built CFF array: - * - * var file = new Uint8Array(cffFileArray, 0, cffFileSize); - * var parser = new Type2Parser(); - * parser.parse(new Stream(file)); - */ - -/* - * Write to a file to the disk (works only on Firefox in privilege mode) - * but this is useful for dumping a font file to the disk and check with - * fontforge or the ots program what's wrong with the file. - * - * writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".cff"); - */ -function writeToFile(aBytes, aFilePath) { - if (!('netscape' in window)) { - return; - } - - netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); - var Cc = Components.classes, - Ci = Components.interfaces; - var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile); - file.initWithPath(aFilePath); - - var stream = Cc['@mozilla.org/network/file-output-stream;1'] - .createInstance(Ci.nsIFileOutputStream); - stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0); - - var bos = Cc['@mozilla.org/binaryoutputstream;1'] - .createInstance(Ci.nsIBinaryOutputStream); - bos.setOutputStream(stream); - bos.writeByteArray(aBytes, aBytes.length); - stream.close(); -}