12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375 |
- /* Copyright 2017 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 sharedUtil = require('../shared/util.js');
- var coreCharsets = require('./charsets.js');
- var coreEncodings = require('./encodings.js');
- var error = sharedUtil.error;
- var info = sharedUtil.info;
- var bytesToString = sharedUtil.bytesToString;
- var warn = sharedUtil.warn;
- var isArray = sharedUtil.isArray;
- var Util = sharedUtil.Util;
- var stringToBytes = sharedUtil.stringToBytes;
- var assert = sharedUtil.assert;
- var ISOAdobeCharset = coreCharsets.ISOAdobeCharset;
- var ExpertCharset = coreCharsets.ExpertCharset;
- var ExpertSubsetCharset = coreCharsets.ExpertSubsetCharset;
- var StandardEncoding = coreEncodings.StandardEncoding;
- var ExpertEncoding = coreEncodings.ExpertEncoding;
- var MAX_SUBR_NESTING = 10;
- var CFFStandardStrings = [
- '.notdef',
- 'space',
- 'exclam',
- 'quotedbl',
- 'numbersign',
- 'dollar',
- 'percent',
- 'ampersand',
- 'quoteright',
- 'parenleft',
- 'parenright',
- 'asterisk',
- 'plus',
- 'comma',
- 'hyphen',
- 'period',
- 'slash',
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'six',
- 'seven',
- 'eight',
- 'nine',
- 'colon',
- 'semicolon',
- 'less',
- 'equal',
- 'greater',
- 'question',
- 'at',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F',
- 'G',
- 'H',
- 'I',
- 'J',
- 'K',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
- 'Q',
- 'R',
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
- 'bracketleft',
- 'backslash',
- 'bracketright',
- 'asciicircum',
- 'underscore',
- 'quoteleft',
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'p',
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'z',
- 'braceleft',
- 'bar',
- 'braceright',
- 'asciitilde',
- 'exclamdown',
- 'cent',
- 'sterling',
- 'fraction',
- 'yen',
- 'florin',
- 'section',
- 'currency',
- 'quotesingle',
- 'quotedblleft',
- 'guillemotleft',
- 'guilsinglleft',
- 'guilsinglright',
- 'fi',
- 'fl',
- 'endash',
- 'dagger',
- 'daggerdbl',
- 'periodcentered',
- 'paragraph',
- 'bullet',
- 'quotesinglbase',
- 'quotedblbase',
- 'quotedblright',
- 'guillemotright',
- 'ellipsis',
- 'perthousand',
- 'questiondown',
- 'grave',
- 'acute',
- 'circumflex',
- 'tilde',
- 'macron',
- 'breve',
- 'dotaccent',
- 'dieresis',
- 'ring',
- 'cedilla',
- 'hungarumlaut',
- 'ogonek',
- 'caron',
- 'emdash',
- 'AE',
- 'ordfeminine',
- 'Lslash',
- 'Oslash',
- 'OE',
- 'ordmasculine',
- 'ae',
- 'dotlessi',
- 'lslash',
- 'oslash',
- 'oe',
- 'germandbls',
- 'onesuperior',
- 'logicalnot',
- 'mu',
- 'trademark',
- 'Eth',
- 'onehalf',
- 'plusminus',
- 'Thorn',
- 'onequarter',
- 'divide',
- 'brokenbar',
- 'degree',
- 'thorn',
- 'threequarters',
- 'twosuperior',
- 'registered',
- 'minus',
- 'eth',
- 'multiply',
- 'threesuperior',
- 'copyright',
- 'Aacute',
- 'Acircumflex',
- 'Adieresis',
- 'Agrave',
- 'Aring',
- 'Atilde',
- 'Ccedilla',
- 'Eacute',
- 'Ecircumflex',
- 'Edieresis',
- 'Egrave',
- 'Iacute',
- 'Icircumflex',
- 'Idieresis',
- 'Igrave',
- 'Ntilde',
- 'Oacute',
- 'Ocircumflex',
- 'Odieresis',
- 'Ograve',
- 'Otilde',
- 'Scaron',
- 'Uacute',
- 'Ucircumflex',
- 'Udieresis',
- 'Ugrave',
- 'Yacute',
- 'Ydieresis',
- 'Zcaron',
- 'aacute',
- 'acircumflex',
- 'adieresis',
- 'agrave',
- 'aring',
- 'atilde',
- 'ccedilla',
- 'eacute',
- 'ecircumflex',
- 'edieresis',
- 'egrave',
- 'iacute',
- 'icircumflex',
- 'idieresis',
- 'igrave',
- 'ntilde',
- 'oacute',
- 'ocircumflex',
- 'odieresis',
- 'ograve',
- 'otilde',
- 'scaron',
- 'uacute',
- 'ucircumflex',
- 'udieresis',
- 'ugrave',
- 'yacute',
- 'ydieresis',
- 'zcaron',
- 'exclamsmall',
- 'Hungarumlautsmall',
- 'dollaroldstyle',
- 'dollarsuperior',
- 'ampersandsmall',
- 'Acutesmall',
- 'parenleftsuperior',
- 'parenrightsuperior',
- 'twodotenleader',
- 'onedotenleader',
- 'zerooldstyle',
- 'oneoldstyle',
- 'twooldstyle',
- 'threeoldstyle',
- 'fouroldstyle',
- 'fiveoldstyle',
- 'sixoldstyle',
- 'sevenoldstyle',
- 'eightoldstyle',
- 'nineoldstyle',
- 'commasuperior',
- 'threequartersemdash',
- 'periodsuperior',
- 'questionsmall',
- 'asuperior',
- 'bsuperior',
- 'centsuperior',
- 'dsuperior',
- 'esuperior',
- 'isuperior',
- 'lsuperior',
- 'msuperior',
- 'nsuperior',
- 'osuperior',
- 'rsuperior',
- 'ssuperior',
- 'tsuperior',
- 'ff',
- 'ffi',
- 'ffl',
- 'parenleftinferior',
- 'parenrightinferior',
- 'Circumflexsmall',
- 'hyphensuperior',
- 'Gravesmall',
- 'Asmall',
- 'Bsmall',
- 'Csmall',
- 'Dsmall',
- 'Esmall',
- 'Fsmall',
- 'Gsmall',
- 'Hsmall',
- 'Ismall',
- 'Jsmall',
- 'Ksmall',
- 'Lsmall',
- 'Msmall',
- 'Nsmall',
- 'Osmall',
- 'Psmall',
- 'Qsmall',
- 'Rsmall',
- 'Ssmall',
- 'Tsmall',
- 'Usmall',
- 'Vsmall',
- 'Wsmall',
- 'Xsmall',
- 'Ysmall',
- 'Zsmall',
- 'colonmonetary',
- 'onefitted',
- 'rupiah',
- 'Tildesmall',
- 'exclamdownsmall',
- 'centoldstyle',
- 'Lslashsmall',
- 'Scaronsmall',
- 'Zcaronsmall',
- 'Dieresissmall',
- 'Brevesmall',
- 'Caronsmall',
- 'Dotaccentsmall',
- 'Macronsmall',
- 'figuredash',
- 'hypheninferior',
- 'Ogoneksmall',
- 'Ringsmall',
- 'Cedillasmall',
- 'questiondownsmall',
- 'oneeighth',
- 'threeeighths',
- 'fiveeighths',
- 'seveneighths',
- 'onethird',
- 'twothirds',
- 'zerosuperior',
- 'foursuperior',
- 'fivesuperior',
- 'sixsuperior',
- 'sevensuperior',
- 'eightsuperior',
- 'ninesuperior',
- 'zeroinferior',
- 'oneinferior',
- 'twoinferior',
- 'threeinferior',
- 'fourinferior',
- 'fiveinferior',
- 'sixinferior',
- 'seveninferior',
- 'eightinferior',
- 'nineinferior',
- 'centinferior',
- 'dollarinferior',
- 'periodinferior',
- 'commainferior',
- 'Agravesmall',
- 'Aacutesmall',
- 'Acircumflexsmall',
- 'Atildesmall',
- 'Adieresissmall',
- 'Aringsmall',
- 'AEsmall',
- 'Ccedillasmall',
- 'Egravesmall',
- 'Eacutesmall',
- 'Ecircumflexsmall',
- 'Edieresissmall',
- 'Igravesmall',
- 'Iacutesmall',
- 'Icircumflexsmall',
- 'Idieresissmall',
- 'Ethsmall',
- 'Ntildesmall',
- 'Ogravesmall',
- 'Oacutesmall',
- 'Ocircumflexsmall',
- 'Otildesmall',
- 'Odieresissmall',
- 'OEsmall',
- 'Oslashsmall',
- 'Ugravesmall',
- 'Uacutesmall',
- 'Ucircumflexsmall',
- 'Udieresissmall',
- 'Yacutesmall',
- 'Thornsmall',
- 'Ydieresissmall',
- '001.000',
- '001.001',
- '001.002',
- '001.003',
- 'Black',
- 'Bold',
- 'Book',
- 'Light',
- 'Medium',
- 'Regular',
- 'Roman',
- 'Semibold'
- ];
- var CFFParser = function CFFParserClosure() {
- var CharstringValidationData = [
- null,
- {
- id: 'hstem',
- min: 2,
- stackClearing: true,
- stem: true
- },
- null,
- {
- id: 'vstem',
- min: 2,
- stackClearing: true,
- stem: true
- },
- {
- id: 'vmoveto',
- min: 1,
- stackClearing: true
- },
- {
- id: 'rlineto',
- min: 2,
- resetStack: true
- },
- {
- id: 'hlineto',
- min: 1,
- resetStack: true
- },
- {
- id: 'vlineto',
- min: 1,
- resetStack: true
- },
- {
- id: 'rrcurveto',
- min: 6,
- resetStack: true
- },
- null,
- {
- id: 'callsubr',
- min: 1,
- undefStack: true
- },
- {
- id: 'return',
- min: 0,
- undefStack: true
- },
- null,
- null,
- {
- id: 'endchar',
- min: 0,
- stackClearing: true
- },
- null,
- null,
- null,
- {
- id: 'hstemhm',
- min: 2,
- stackClearing: true,
- stem: true
- },
- {
- id: 'hintmask',
- min: 0,
- stackClearing: true
- },
- {
- id: 'cntrmask',
- min: 0,
- stackClearing: true
- },
- {
- id: 'rmoveto',
- min: 2,
- stackClearing: true
- },
- {
- id: 'hmoveto',
- min: 1,
- stackClearing: true
- },
- {
- id: 'vstemhm',
- min: 2,
- stackClearing: true,
- stem: true
- },
- {
- id: 'rcurveline',
- min: 8,
- resetStack: true
- },
- {
- id: 'rlinecurve',
- min: 8,
- resetStack: true
- },
- {
- id: 'vvcurveto',
- min: 4,
- resetStack: true
- },
- {
- id: 'hhcurveto',
- min: 4,
- resetStack: true
- },
- null,
- {
- id: 'callgsubr',
- min: 1,
- undefStack: true
- },
- {
- id: 'vhcurveto',
- min: 4,
- resetStack: true
- },
- {
- id: 'hvcurveto',
- min: 4,
- resetStack: true
- }
- ];
- var CharstringValidationData12 = [
- null,
- null,
- null,
- {
- id: 'and',
- min: 2,
- stackDelta: -1
- },
- {
- id: 'or',
- min: 2,
- stackDelta: -1
- },
- {
- id: 'not',
- min: 1,
- stackDelta: 0
- },
- null,
- null,
- null,
- {
- id: 'abs',
- min: 1,
- stackDelta: 0
- },
- {
- id: 'add',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] + stack[index - 1];
- }
- },
- {
- id: 'sub',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] - stack[index - 1];
- }
- },
- {
- id: 'div',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] / stack[index - 1];
- }
- },
- null,
- {
- id: 'neg',
- min: 1,
- stackDelta: 0,
- stackFn: function stack_div(stack, index) {
- stack[index - 1] = -stack[index - 1];
- }
- },
- {
- id: 'eq',
- min: 2,
- stackDelta: -1
- },
- null,
- null,
- {
- id: 'drop',
- min: 1,
- stackDelta: -1
- },
- null,
- {
- id: 'put',
- min: 2,
- stackDelta: -2
- },
- {
- id: 'get',
- min: 1,
- stackDelta: 0
- },
- {
- id: 'ifelse',
- min: 4,
- stackDelta: -3
- },
- {
- id: 'random',
- min: 0,
- stackDelta: 1
- },
- {
- id: 'mul',
- min: 2,
- stackDelta: -1,
- stackFn: function stack_div(stack, index) {
- stack[index - 2] = stack[index - 2] * stack[index - 1];
- }
- },
- null,
- {
- id: 'sqrt',
- min: 1,
- stackDelta: 0
- },
- {
- id: 'dup',
- min: 1,
- stackDelta: 1
- },
- {
- id: 'exch',
- min: 2,
- stackDelta: 0
- },
- {
- id: 'index',
- min: 2,
- stackDelta: 0
- },
- {
- id: 'roll',
- min: 3,
- stackDelta: -2
- },
- null,
- null,
- null,
- {
- id: 'hflex',
- min: 7,
- resetStack: true
- },
- {
- id: 'flex',
- min: 13,
- resetStack: true
- },
- {
- id: 'hflex1',
- min: 9,
- resetStack: true
- },
- {
- id: 'flex1',
- min: 11,
- resetStack: true
- }
- ];
- function CFFParser(file, properties, seacAnalysisEnabled) {
- this.bytes = file.getBytes();
- this.properties = properties;
- this.seacAnalysisEnabled = !!seacAnalysisEnabled;
- }
- CFFParser.prototype = {
- parse: function CFFParser_parse() {
- var properties = this.properties;
- var cff = new CFF();
- this.cff = cff;
- var header = this.parseHeader();
- var nameIndex = this.parseIndex(header.endPos);
- var topDictIndex = this.parseIndex(nameIndex.endPos);
- var stringIndex = this.parseIndex(topDictIndex.endPos);
- var globalSubrIndex = this.parseIndex(stringIndex.endPos);
- var topDictParsed = this.parseDict(topDictIndex.obj.get(0));
- var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
- cff.header = header.obj;
- cff.names = this.parseNameIndex(nameIndex.obj);
- cff.strings = this.parseStringIndex(stringIndex.obj);
- cff.topDict = topDict;
- cff.globalSubrIndex = globalSubrIndex.obj;
- this.parsePrivateDict(cff.topDict);
- cff.isCIDFont = topDict.hasName('ROS');
- var charStringOffset = topDict.getByName('CharStrings');
- var charStringIndex = this.parseIndex(charStringOffset).obj;
- var fontMatrix = topDict.getByName('FontMatrix');
- if (fontMatrix) {
- properties.fontMatrix = fontMatrix;
- }
- var fontBBox = topDict.getByName('FontBBox');
- if (fontBBox) {
- properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
- properties.descent = Math.min(fontBBox[1], fontBBox[3]);
- properties.ascentScaled = true;
- }
- var charset, encoding;
- if (cff.isCIDFont) {
- var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
- for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
- var dictRaw = fdArrayIndex.get(i);
- var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings);
- this.parsePrivateDict(fontDict);
- cff.fdArray.push(fontDict);
- }
- encoding = null;
- charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, true);
- cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), charStringIndex.count);
- } else {
- charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, false);
- encoding = this.parseEncoding(topDict.getByName('Encoding'), properties, cff.strings, charset.charset);
- }
- cff.charset = charset;
- cff.encoding = encoding;
- var charStringsAndSeacs = this.parseCharStrings(charStringIndex, topDict.privateDict.subrsIndex, globalSubrIndex.obj, cff.fdSelect, cff.fdArray);
- cff.charStrings = charStringsAndSeacs.charStrings;
- cff.seacs = charStringsAndSeacs.seacs;
- cff.widths = charStringsAndSeacs.widths;
- return cff;
- },
- parseHeader: function CFFParser_parseHeader() {
- var bytes = this.bytes;
- var bytesLength = bytes.length;
- var offset = 0;
- while (offset < bytesLength && bytes[offset] !== 1) {
- ++offset;
- }
- if (offset >= bytesLength) {
- error('Invalid CFF header');
- } else if (offset !== 0) {
- info('cff data is shifted');
- bytes = bytes.subarray(offset);
- this.bytes = bytes;
- }
- var major = bytes[0];
- var minor = bytes[1];
- var hdrSize = bytes[2];
- var offSize = bytes[3];
- var header = new CFFHeader(major, minor, hdrSize, offSize);
- return {
- obj: header,
- endPos: hdrSize
- };
- },
- parseDict: function CFFParser_parseDict(dict) {
- var pos = 0;
- function parseOperand() {
- var value = dict[pos++];
- if (value === 30) {
- return parseFloatOperand();
- } else if (value === 28) {
- value = dict[pos++];
- value = (value << 24 | dict[pos++] << 16) >> 16;
- return value;
- } else if (value === 29) {
- value = dict[pos++];
- value = value << 8 | dict[pos++];
- value = value << 8 | dict[pos++];
- value = value << 8 | dict[pos++];
- return value;
- } else if (value >= 32 && value <= 246) {
- return value - 139;
- } else if (value >= 247 && value <= 250) {
- return (value - 247) * 256 + dict[pos++] + 108;
- } else if (value >= 251 && value <= 254) {
- return -((value - 251) * 256) - dict[pos++] - 108;
- }
- warn('CFFParser_parseDict: "' + value + '" is a reserved command.');
- return NaN;
- }
- function parseFloatOperand() {
- var str = '';
- var eof = 15;
- var lookup = [
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- '.',
- 'E',
- 'E-',
- null,
- '-'
- ];
- var length = dict.length;
- while (pos < length) {
- var b = dict[pos++];
- var b1 = b >> 4;
- var b2 = b & 15;
- if (b1 === eof) {
- break;
- }
- str += lookup[b1];
- if (b2 === eof) {
- break;
- }
- str += lookup[b2];
- }
- return parseFloat(str);
- }
- var operands = [];
- var entries = [];
- pos = 0;
- var end = dict.length;
- while (pos < end) {
- var b = dict[pos];
- if (b <= 21) {
- if (b === 12) {
- b = b << 8 | dict[++pos];
- }
- entries.push([
- b,
- operands
- ]);
- operands = [];
- ++pos;
- } else {
- operands.push(parseOperand());
- }
- }
- return entries;
- },
- parseIndex: function CFFParser_parseIndex(pos) {
- var cffIndex = new CFFIndex();
- var bytes = this.bytes;
- var count = bytes[pos++] << 8 | bytes[pos++];
- var offsets = [];
- var end = pos;
- var i, ii;
- if (count !== 0) {
- var offsetSize = bytes[pos++];
- var startPos = pos + (count + 1) * offsetSize - 1;
- for (i = 0, ii = count + 1; i < ii; ++i) {
- var offset = 0;
- for (var j = 0; j < offsetSize; ++j) {
- offset <<= 8;
- offset += bytes[pos++];
- }
- offsets.push(startPos + offset);
- }
- end = offsets[count];
- }
- for (i = 0, ii = offsets.length - 1; i < ii; ++i) {
- var offsetStart = offsets[i];
- var offsetEnd = offsets[i + 1];
- cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
- }
- return {
- obj: cffIndex,
- endPos: end
- };
- },
- parseNameIndex: function CFFParser_parseNameIndex(index) {
- var names = [];
- for (var i = 0, ii = index.count; i < ii; ++i) {
- var name = index.get(i);
- var length = Math.min(name.length, 127);
- var data = [];
- for (var j = 0; j < length; ++j) {
- var c = name[j];
- if (j === 0 && c === 0) {
- data[j] = c;
- continue;
- }
- if (c < 33 || c > 126 || c === 91 || c === 93 || c === 40 || c === 41 || c === 123 || c === 125 || c === 60 || c === 62 || c === 47 || c === 37 || c === 35) {
- data[j] = 95;
- continue;
- }
- data[j] = c;
- }
- names.push(bytesToString(data));
- }
- return names;
- },
- parseStringIndex: function CFFParser_parseStringIndex(index) {
- var strings = new CFFStrings();
- for (var i = 0, ii = index.count; i < ii; ++i) {
- var data = index.get(i);
- strings.add(bytesToString(data));
- }
- return strings;
- },
- createDict: function CFFParser_createDict(Type, dict, strings) {
- var cffDict = new Type(strings);
- for (var i = 0, ii = dict.length; i < ii; ++i) {
- var pair = dict[i];
- var key = pair[0];
- var value = pair[1];
- cffDict.setByKey(key, value);
- }
- return cffDict;
- },
- parseCharString: function CFFParser_parseCharString(state, data, localSubrIndex, globalSubrIndex) {
- if (!data || state.callDepth > MAX_SUBR_NESTING) {
- return false;
- }
- var stackSize = state.stackSize;
- var stack = state.stack;
- var length = data.length;
- for (var j = 0; j < length;) {
- var value = data[j++];
- var validationCommand = null;
- if (value === 12) {
- var q = data[j++];
- if (q === 0) {
- data[j - 2] = 139;
- data[j - 1] = 22;
- stackSize = 0;
- } else {
- validationCommand = CharstringValidationData12[q];
- }
- } else if (value === 28) {
- stack[stackSize] = (data[j] << 24 | data[j + 1] << 16) >> 16;
- j += 2;
- stackSize++;
- } else if (value === 14) {
- if (stackSize >= 4) {
- stackSize -= 4;
- if (this.seacAnalysisEnabled) {
- state.seac = stack.slice(stackSize, stackSize + 4);
- return false;
- }
- }
- validationCommand = CharstringValidationData[value];
- } else if (value >= 32 && value <= 246) {
- stack[stackSize] = value - 139;
- stackSize++;
- } else if (value >= 247 && value <= 254) {
- stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108;
- j++;
- stackSize++;
- } else if (value === 255) {
- stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536;
- j += 4;
- stackSize++;
- } else if (value === 19 || value === 20) {
- state.hints += stackSize >> 1;
- j += state.hints + 7 >> 3;
- stackSize %= 2;
- validationCommand = CharstringValidationData[value];
- } else if (value === 10 || value === 29) {
- var subrsIndex;
- if (value === 10) {
- subrsIndex = localSubrIndex;
- } else {
- subrsIndex = globalSubrIndex;
- }
- if (!subrsIndex) {
- validationCommand = CharstringValidationData[value];
- warn('Missing subrsIndex for ' + validationCommand.id);
- return false;
- }
- var bias = 32768;
- if (subrsIndex.count < 1240) {
- bias = 107;
- } else if (subrsIndex.count < 33900) {
- bias = 1131;
- }
- var subrNumber = stack[--stackSize] + bias;
- if (subrNumber < 0 || subrNumber >= subrsIndex.count || isNaN(subrNumber)) {
- validationCommand = CharstringValidationData[value];
- warn('Out of bounds subrIndex for ' + validationCommand.id);
- return false;
- }
- state.stackSize = stackSize;
- state.callDepth++;
- var valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex);
- if (!valid) {
- return false;
- }
- state.callDepth--;
- stackSize = state.stackSize;
- continue;
- } else if (value === 11) {
- state.stackSize = stackSize;
- return true;
- } else {
- validationCommand = CharstringValidationData[value];
- }
- if (validationCommand) {
- if (validationCommand.stem) {
- state.hints += stackSize >> 1;
- }
- if ('min' in validationCommand) {
- if (!state.undefStack && stackSize < validationCommand.min) {
- warn('Not enough parameters for ' + validationCommand.id + '; actual: ' + stackSize + ', expected: ' + validationCommand.min);
- return false;
- }
- }
- if (state.firstStackClearing && validationCommand.stackClearing) {
- state.firstStackClearing = false;
- stackSize -= validationCommand.min;
- if (stackSize >= 2 && validationCommand.stem) {
- stackSize %= 2;
- } else if (stackSize > 1) {
- warn('Found too many parameters for stack-clearing command');
- }
- if (stackSize > 0 && stack[stackSize - 1] >= 0) {
- state.width = stack[stackSize - 1];
- }
- }
- if ('stackDelta' in validationCommand) {
- if ('stackFn' in validationCommand) {
- validationCommand.stackFn(stack, stackSize);
- }
- stackSize += validationCommand.stackDelta;
- } else if (validationCommand.stackClearing) {
- stackSize = 0;
- } else if (validationCommand.resetStack) {
- stackSize = 0;
- state.undefStack = false;
- } else if (validationCommand.undefStack) {
- stackSize = 0;
- state.undefStack = true;
- state.firstStackClearing = false;
- }
- }
- }
- state.stackSize = stackSize;
- return true;
- },
- parseCharStrings: function CFFParser_parseCharStrings(charStrings, localSubrIndex, globalSubrIndex, fdSelect, fdArray) {
- var seacs = [];
- var widths = [];
- var count = charStrings.count;
- for (var i = 0; i < count; i++) {
- var charstring = charStrings.get(i);
- var state = {
- callDepth: 0,
- stackSize: 0,
- stack: [],
- undefStack: true,
- hints: 0,
- firstStackClearing: true,
- seac: null,
- width: null
- };
- var valid = true;
- var localSubrToUse = null;
- if (fdSelect && fdArray.length) {
- var fdIndex = fdSelect.getFDIndex(i);
- if (fdIndex === -1) {
- warn('Glyph index is not in fd select.');
- valid = false;
- }
- if (fdIndex >= fdArray.length) {
- warn('Invalid fd index for glyph index.');
- valid = false;
- }
- if (valid) {
- localSubrToUse = fdArray[fdIndex].privateDict.subrsIndex;
- }
- } else if (localSubrIndex) {
- localSubrToUse = localSubrIndex;
- }
- if (valid) {
- valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex);
- }
- if (state.width !== null) {
- widths[i] = state.width;
- }
- if (state.seac !== null) {
- seacs[i] = state.seac;
- }
- if (!valid) {
- charStrings.set(i, new Uint8Array([14]));
- }
- }
- return {
- charStrings: charStrings,
- seacs: seacs,
- widths: widths
- };
- },
- emptyPrivateDictionary: function CFFParser_emptyPrivateDictionary(parentDict) {
- var privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings);
- parentDict.setByKey(18, [
- 0,
- 0
- ]);
- parentDict.privateDict = privateDict;
- },
- parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
- if (!parentDict.hasName('Private')) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var privateOffset = parentDict.getByName('Private');
- if (!isArray(privateOffset) || privateOffset.length !== 2) {
- parentDict.removeByName('Private');
- return;
- }
- var size = privateOffset[0];
- var offset = privateOffset[1];
- if (size === 0 || offset >= this.bytes.length) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var privateDictEnd = offset + size;
- var dictData = this.bytes.subarray(offset, privateDictEnd);
- var dict = this.parseDict(dictData);
- var privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings);
- parentDict.privateDict = privateDict;
- if (!privateDict.getByName('Subrs')) {
- return;
- }
- var subrsOffset = privateDict.getByName('Subrs');
- var relativeOffset = offset + subrsOffset;
- if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
- this.emptyPrivateDictionary(parentDict);
- return;
- }
- var subrsIndex = this.parseIndex(relativeOffset);
- privateDict.subrsIndex = subrsIndex.obj;
- },
- parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) {
- if (pos === 0) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, ISOAdobeCharset);
- } else if (pos === 1) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, ExpertCharset);
- } else if (pos === 2) {
- return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, ExpertSubsetCharset);
- }
- var bytes = this.bytes;
- var start = pos;
- var format = bytes[pos++];
- var charset = ['.notdef'];
- var id, count, i;
- length -= 1;
- switch (format) {
- case 0:
- for (i = 0; i < length; i++) {
- id = bytes[pos++] << 8 | bytes[pos++];
- charset.push(cid ? id : strings.get(id));
- }
- break;
- case 1:
- while (charset.length <= length) {
- id = bytes[pos++] << 8 | bytes[pos++];
- count = bytes[pos++];
- for (i = 0; i <= count; i++) {
- charset.push(cid ? id++ : strings.get(id++));
- }
- }
- break;
- case 2:
- while (charset.length <= length) {
- id = bytes[pos++] << 8 | bytes[pos++];
- count = bytes[pos++] << 8 | bytes[pos++];
- for (i = 0; i <= count; i++) {
- charset.push(cid ? id++ : strings.get(id++));
- }
- }
- break;
- default:
- error('Unknown charset format');
- }
- var end = pos;
- var raw = bytes.subarray(start, end);
- return new CFFCharset(false, format, charset, raw);
- },
- parseEncoding: function CFFParser_parseEncoding(pos, properties, strings, charset) {
- var encoding = Object.create(null);
- var bytes = this.bytes;
- var predefined = false;
- var format, i, ii;
- var raw = null;
- function readSupplement() {
- var supplementsCount = bytes[pos++];
- for (i = 0; i < supplementsCount; i++) {
- var code = bytes[pos++];
- var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
- encoding[code] = charset.indexOf(strings.get(sid));
- }
- }
- if (pos === 0 || pos === 1) {
- predefined = true;
- format = pos;
- var baseEncoding = pos ? ExpertEncoding : StandardEncoding;
- for (i = 0, ii = charset.length; i < ii; i++) {
- var index = baseEncoding.indexOf(charset[i]);
- if (index !== -1) {
- encoding[index] = i;
- }
- }
- } else {
- var dataStart = pos;
- format = bytes[pos++];
- switch (format & 0x7f) {
- case 0:
- var glyphsCount = bytes[pos++];
- for (i = 1; i <= glyphsCount; i++) {
- encoding[bytes[pos++]] = i;
- }
- break;
- case 1:
- var rangesCount = bytes[pos++];
- var gid = 1;
- for (i = 0; i < rangesCount; i++) {
- var start = bytes[pos++];
- var left = bytes[pos++];
- for (var j = start; j <= start + left; j++) {
- encoding[j] = gid++;
- }
- }
- break;
- default:
- error('Unknown encoding format: ' + format + ' in CFF');
- break;
- }
- var dataEnd = pos;
- if (format & 0x80) {
- bytes[dataStart] &= 0x7f;
- readSupplement();
- }
- raw = bytes.subarray(dataStart, dataEnd);
- }
- format = format & 0x7f;
- return new CFFEncoding(predefined, format, encoding, raw);
- },
- parseFDSelect: function CFFParser_parseFDSelect(pos, length) {
- var start = pos;
- var bytes = this.bytes;
- var format = bytes[pos++];
- var fdSelect = [], rawBytes;
- var i, invalidFirstGID = false;
- switch (format) {
- case 0:
- for (i = 0; i < length; ++i) {
- var id = bytes[pos++];
- fdSelect.push(id);
- }
- rawBytes = bytes.subarray(start, pos);
- break;
- case 3:
- var rangesCount = bytes[pos++] << 8 | bytes[pos++];
- for (i = 0; i < rangesCount; ++i) {
- var first = bytes[pos++] << 8 | bytes[pos++];
- if (i === 0 && first !== 0) {
- warn('parseFDSelect: The first range must have a first GID of 0' + ' -- trying to recover.');
- invalidFirstGID = true;
- first = 0;
- }
- var fdIndex = bytes[pos++];
- var next = bytes[pos] << 8 | bytes[pos + 1];
- for (var j = first; j < next; ++j) {
- fdSelect.push(fdIndex);
- }
- }
- pos += 2;
- rawBytes = bytes.subarray(start, pos);
- if (invalidFirstGID) {
- rawBytes[3] = rawBytes[4] = 0;
- }
- break;
- default:
- error('parseFDSelect: Unknown format "' + format + '".');
- break;
- }
- assert(fdSelect.length === length, 'parseFDSelect: Invalid font data.');
- return new CFFFDSelect(fdSelect, rawBytes);
- }
- };
- return CFFParser;
- }();
- var CFF = function CFFClosure() {
- function CFF() {
- this.header = null;
- this.names = [];
- this.topDict = null;
- this.strings = new CFFStrings();
- this.globalSubrIndex = null;
- this.encoding = null;
- this.charset = null;
- this.charStrings = null;
- this.fdArray = [];
- this.fdSelect = null;
- this.isCIDFont = false;
- }
- return CFF;
- }();
- var CFFHeader = function CFFHeaderClosure() {
- function CFFHeader(major, minor, hdrSize, offSize) {
- this.major = major;
- this.minor = minor;
- this.hdrSize = hdrSize;
- this.offSize = offSize;
- }
- return CFFHeader;
- }();
- var CFFStrings = function CFFStringsClosure() {
- function CFFStrings() {
- this.strings = [];
- }
- CFFStrings.prototype = {
- get: function CFFStrings_get(index) {
- if (index >= 0 && index <= 390) {
- return CFFStandardStrings[index];
- }
- if (index - 391 <= this.strings.length) {
- return this.strings[index - 391];
- }
- return CFFStandardStrings[0];
- },
- add: function CFFStrings_add(value) {
- this.strings.push(value);
- },
- get count() {
- return this.strings.length;
- }
- };
- return CFFStrings;
- }();
- var CFFIndex = function CFFIndexClosure() {
- function CFFIndex() {
- this.objects = [];
- this.length = 0;
- }
- CFFIndex.prototype = {
- add: function CFFIndex_add(data) {
- this.length += data.length;
- this.objects.push(data);
- },
- set: function CFFIndex_set(index, data) {
- this.length += data.length - this.objects[index].length;
- this.objects[index] = data;
- },
- get: function CFFIndex_get(index) {
- return this.objects[index];
- },
- get count() {
- return this.objects.length;
- }
- };
- return CFFIndex;
- }();
- var CFFDict = function CFFDictClosure() {
- function CFFDict(tables, strings) {
- this.keyToNameMap = tables.keyToNameMap;
- this.nameToKeyMap = tables.nameToKeyMap;
- this.defaults = tables.defaults;
- this.types = tables.types;
- this.opcodes = tables.opcodes;
- this.order = tables.order;
- this.strings = strings;
- this.values = Object.create(null);
- }
- CFFDict.prototype = {
- setByKey: function CFFDict_setByKey(key, value) {
- if (!(key in this.keyToNameMap)) {
- return false;
- }
- var valueLength = value.length;
- if (valueLength === 0) {
- return true;
- }
- for (var i = 0; i < valueLength; i++) {
- if (isNaN(value[i])) {
- warn('Invalid CFFDict value: "' + value + '" for key "' + key + '".');
- return true;
- }
- }
- var type = this.types[key];
- if (type === 'num' || type === 'sid' || type === 'offset') {
- value = value[0];
- }
- this.values[key] = value;
- return true;
- },
- setByName: function CFFDict_setByName(name, value) {
- if (!(name in this.nameToKeyMap)) {
- error('Invalid dictionary name "' + name + '"');
- }
- this.values[this.nameToKeyMap[name]] = value;
- },
- hasName: function CFFDict_hasName(name) {
- return this.nameToKeyMap[name] in this.values;
- },
- getByName: function CFFDict_getByName(name) {
- if (!(name in this.nameToKeyMap)) {
- error('Invalid dictionary name "' + name + '"');
- }
- var key = this.nameToKeyMap[name];
- if (!(key in this.values)) {
- return this.defaults[key];
- }
- return this.values[key];
- },
- removeByName: function CFFDict_removeByName(name) {
- delete this.values[this.nameToKeyMap[name]];
- }
- };
- CFFDict.createTables = function CFFDict_createTables(layout) {
- var tables = {
- keyToNameMap: {},
- nameToKeyMap: {},
- defaults: {},
- types: {},
- opcodes: {},
- order: []
- };
- for (var i = 0, ii = layout.length; i < ii; ++i) {
- var entry = layout[i];
- var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
- tables.keyToNameMap[key] = entry[1];
- tables.nameToKeyMap[entry[1]] = key;
- tables.types[key] = entry[2];
- tables.defaults[key] = entry[3];
- tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]];
- tables.order.push(key);
- }
- return tables;
- };
- return CFFDict;
- }();
- var CFFTopDict = function CFFTopDictClosure() {
- var layout = [
- [
- [
- 12,
- 30
- ],
- 'ROS',
- [
- 'sid',
- 'sid',
- 'num'
- ],
- null
- ],
- [
- [
- 12,
- 20
- ],
- 'SyntheticBase',
- 'num',
- null
- ],
- [
- 0,
- 'version',
- 'sid',
- null
- ],
- [
- 1,
- 'Notice',
- 'sid',
- null
- ],
- [
- [
- 12,
- 0
- ],
- 'Copyright',
- 'sid',
- null
- ],
- [
- 2,
- 'FullName',
- 'sid',
- null
- ],
- [
- 3,
- 'FamilyName',
- 'sid',
- null
- ],
- [
- 4,
- 'Weight',
- 'sid',
- null
- ],
- [
- [
- 12,
- 1
- ],
- 'isFixedPitch',
- 'num',
- 0
- ],
- [
- [
- 12,
- 2
- ],
- 'ItalicAngle',
- 'num',
- 0
- ],
- [
- [
- 12,
- 3
- ],
- 'UnderlinePosition',
- 'num',
- -100
- ],
- [
- [
- 12,
- 4
- ],
- 'UnderlineThickness',
- 'num',
- 50
- ],
- [
- [
- 12,
- 5
- ],
- 'PaintType',
- 'num',
- 0
- ],
- [
- [
- 12,
- 6
- ],
- 'CharstringType',
- 'num',
- 2
- ],
- [
- [
- 12,
- 7
- ],
- 'FontMatrix',
- [
- 'num',
- 'num',
- 'num',
- 'num',
- 'num',
- 'num'
- ],
- [
- 0.001,
- 0,
- 0,
- 0.001,
- 0,
- 0
- ]
- ],
- [
- 13,
- 'UniqueID',
- 'num',
- null
- ],
- [
- 5,
- 'FontBBox',
- [
- 'num',
- 'num',
- 'num',
- 'num'
- ],
- [
- 0,
- 0,
- 0,
- 0
- ]
- ],
- [
- [
- 12,
- 8
- ],
- 'StrokeWidth',
- 'num',
- 0
- ],
- [
- 14,
- 'XUID',
- 'array',
- null
- ],
- [
- 15,
- 'charset',
- 'offset',
- 0
- ],
- [
- 16,
- 'Encoding',
- 'offset',
- 0
- ],
- [
- 17,
- 'CharStrings',
- 'offset',
- 0
- ],
- [
- 18,
- 'Private',
- [
- 'offset',
- 'offset'
- ],
- null
- ],
- [
- [
- 12,
- 21
- ],
- 'PostScript',
- 'sid',
- null
- ],
- [
- [
- 12,
- 22
- ],
- 'BaseFontName',
- 'sid',
- null
- ],
- [
- [
- 12,
- 23
- ],
- 'BaseFontBlend',
- 'delta',
- null
- ],
- [
- [
- 12,
- 31
- ],
- 'CIDFontVersion',
- 'num',
- 0
- ],
- [
- [
- 12,
- 32
- ],
- 'CIDFontRevision',
- 'num',
- 0
- ],
- [
- [
- 12,
- 33
- ],
- 'CIDFontType',
- 'num',
- 0
- ],
- [
- [
- 12,
- 34
- ],
- 'CIDCount',
- 'num',
- 8720
- ],
- [
- [
- 12,
- 35
- ],
- 'UIDBase',
- 'num',
- null
- ],
- [
- [
- 12,
- 37
- ],
- 'FDSelect',
- 'offset',
- null
- ],
- [
- [
- 12,
- 36
- ],
- 'FDArray',
- 'offset',
- null
- ],
- [
- [
- 12,
- 38
- ],
- 'FontName',
- 'sid',
- null
- ]
- ];
- var tables = null;
- function CFFTopDict(strings) {
- if (tables === null) {
- tables = CFFDict.createTables(layout);
- }
- CFFDict.call(this, tables, strings);
- this.privateDict = null;
- }
- CFFTopDict.prototype = Object.create(CFFDict.prototype);
- return CFFTopDict;
- }();
- var CFFPrivateDict = function CFFPrivateDictClosure() {
- var layout = [
- [
- 6,
- 'BlueValues',
- 'delta',
- null
- ],
- [
- 7,
- 'OtherBlues',
- 'delta',
- null
- ],
- [
- 8,
- 'FamilyBlues',
- 'delta',
- null
- ],
- [
- 9,
- 'FamilyOtherBlues',
- 'delta',
- null
- ],
- [
- [
- 12,
- 9
- ],
- 'BlueScale',
- 'num',
- 0.039625
- ],
- [
- [
- 12,
- 10
- ],
- 'BlueShift',
- 'num',
- 7
- ],
- [
- [
- 12,
- 11
- ],
- 'BlueFuzz',
- 'num',
- 1
- ],
- [
- 10,
- 'StdHW',
- 'num',
- null
- ],
- [
- 11,
- 'StdVW',
- 'num',
- null
- ],
- [
- [
- 12,
- 12
- ],
- 'StemSnapH',
- 'delta',
- null
- ],
- [
- [
- 12,
- 13
- ],
- 'StemSnapV',
- 'delta',
- null
- ],
- [
- [
- 12,
- 14
- ],
- 'ForceBold',
- 'num',
- 0
- ],
- [
- [
- 12,
- 17
- ],
- 'LanguageGroup',
- 'num',
- 0
- ],
- [
- [
- 12,
- 18
- ],
- 'ExpansionFactor',
- 'num',
- 0.06
- ],
- [
- [
- 12,
- 19
- ],
- 'initialRandomSeed',
- 'num',
- 0
- ],
- [
- 20,
- 'defaultWidthX',
- 'num',
- 0
- ],
- [
- 21,
- 'nominalWidthX',
- 'num',
- 0
- ],
- [
- 19,
- 'Subrs',
- 'offset',
- null
- ]
- ];
- var tables = null;
- function CFFPrivateDict(strings) {
- if (tables === null) {
- tables = CFFDict.createTables(layout);
- }
- CFFDict.call(this, tables, strings);
- this.subrsIndex = null;
- }
- CFFPrivateDict.prototype = Object.create(CFFDict.prototype);
- return CFFPrivateDict;
- }();
- var CFFCharsetPredefinedTypes = {
- ISO_ADOBE: 0,
- EXPERT: 1,
- EXPERT_SUBSET: 2
- };
- var CFFCharset = function CFFCharsetClosure() {
- function CFFCharset(predefined, format, charset, raw) {
- this.predefined = predefined;
- this.format = format;
- this.charset = charset;
- this.raw = raw;
- }
- return CFFCharset;
- }();
- var CFFEncoding = function CFFEncodingClosure() {
- function CFFEncoding(predefined, format, encoding, raw) {
- this.predefined = predefined;
- this.format = format;
- this.encoding = encoding;
- this.raw = raw;
- }
- return CFFEncoding;
- }();
- var CFFFDSelect = function CFFFDSelectClosure() {
- function CFFFDSelect(fdSelect, raw) {
- this.fdSelect = fdSelect;
- this.raw = raw;
- }
- CFFFDSelect.prototype = {
- getFDIndex: function CFFFDSelect_get(glyphIndex) {
- if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {
- return -1;
- }
- return this.fdSelect[glyphIndex];
- }
- };
- return CFFFDSelect;
- }();
- var CFFOffsetTracker = function CFFOffsetTrackerClosure() {
- function CFFOffsetTracker() {
- this.offsets = Object.create(null);
- }
- CFFOffsetTracker.prototype = {
- isTracking: function CFFOffsetTracker_isTracking(key) {
- return key in this.offsets;
- },
- track: function CFFOffsetTracker_track(key, location) {
- if (key in this.offsets) {
- error('Already tracking location of ' + key);
- }
- this.offsets[key] = location;
- },
- offset: function CFFOffsetTracker_offset(value) {
- for (var key in this.offsets) {
- this.offsets[key] += value;
- }
- },
- setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, values, output) {
- if (!(key in this.offsets)) {
- error('Not tracking location of ' + key);
- }
- var data = output.data;
- var dataOffset = this.offsets[key];
- var size = 5;
- for (var i = 0, ii = values.length; i < ii; ++i) {
- var offset0 = i * size + dataOffset;
- var offset1 = offset0 + 1;
- var offset2 = offset0 + 2;
- var offset3 = offset0 + 3;
- var offset4 = offset0 + 4;
- if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) {
- error('writing to an offset that is not empty');
- }
- var value = values[i];
- data[offset0] = 0x1d;
- data[offset1] = value >> 24 & 0xFF;
- data[offset2] = value >> 16 & 0xFF;
- data[offset3] = value >> 8 & 0xFF;
- data[offset4] = value & 0xFF;
- }
- }
- };
- return CFFOffsetTracker;
- }();
- var CFFCompiler = function CFFCompilerClosure() {
- function CFFCompiler(cff) {
- this.cff = cff;
- }
- CFFCompiler.prototype = {
- compile: function CFFCompiler_compile() {
- var cff = this.cff;
- var output = {
- data: [],
- length: 0,
- add: function CFFCompiler_add(data) {
- this.data = this.data.concat(data);
- this.length = this.data.length;
- }
- };
- var header = this.compileHeader(cff.header);
- output.add(header);
- var nameIndex = this.compileNameIndex(cff.names);
- output.add(nameIndex);
- if (cff.isCIDFont) {
- if (cff.topDict.hasName('FontMatrix')) {
- var base = cff.topDict.getByName('FontMatrix');
- cff.topDict.removeByName('FontMatrix');
- for (var i = 0, ii = cff.fdArray.length; i < ii; i++) {
- var subDict = cff.fdArray[i];
- var matrix = base.slice(0);
- if (subDict.hasName('FontMatrix')) {
- matrix = Util.transform(matrix, subDict.getByName('FontMatrix'));
- }
- subDict.setByName('FontMatrix', matrix);
- }
- }
- }
- var compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont);
- output.add(compiled.output);
- var topDictTracker = compiled.trackers[0];
- var stringIndex = this.compileStringIndex(cff.strings.strings);
- output.add(stringIndex);
- var globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
- output.add(globalSubrIndex);
- if (cff.encoding && cff.topDict.hasName('Encoding')) {
- if (cff.encoding.predefined) {
- topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], output);
- } else {
- var encoding = this.compileEncoding(cff.encoding);
- topDictTracker.setEntryLocation('Encoding', [output.length], output);
- output.add(encoding);
- }
- }
- if (cff.charset && cff.topDict.hasName('charset')) {
- if (cff.charset.predefined) {
- topDictTracker.setEntryLocation('charset', [cff.charset.format], output);
- } else {
- var charset = this.compileCharset(cff.charset);
- topDictTracker.setEntryLocation('charset', [output.length], output);
- output.add(charset);
- }
- }
- var charStrings = this.compileCharStrings(cff.charStrings);
- topDictTracker.setEntryLocation('CharStrings', [output.length], output);
- output.add(charStrings);
- if (cff.isCIDFont) {
- topDictTracker.setEntryLocation('FDSelect', [output.length], output);
- var fdSelect = this.compileFDSelect(cff.fdSelect.raw);
- output.add(fdSelect);
- compiled = this.compileTopDicts(cff.fdArray, output.length, true);
- topDictTracker.setEntryLocation('FDArray', [output.length], output);
- output.add(compiled.output);
- var fontDictTrackers = compiled.trackers;
- this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
- }
- this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
- output.add([0]);
- return output.data;
- },
- encodeNumber: function CFFCompiler_encodeNumber(value) {
- if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) {
- return this.encodeInteger(value);
- }
- return this.encodeFloat(value);
- },
- encodeFloat: function CFFCompiler_encodeFloat(num) {
- var value = num.toString();
- var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
- if (m) {
- var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
- value = (Math.round(num * epsilon) / epsilon).toString();
- }
- var nibbles = '';
- var i, ii;
- for (i = 0, ii = value.length; i < ii; ++i) {
- var a = value[i];
- if (a === 'e') {
- nibbles += value[++i] === '-' ? 'c' : 'b';
- } else if (a === '.') {
- nibbles += 'a';
- } else if (a === '-') {
- nibbles += 'e';
- } else {
- nibbles += a;
- }
- }
- nibbles += nibbles.length & 1 ? 'f' : 'ff';
- var out = [30];
- for (i = 0, ii = nibbles.length; i < ii; i += 2) {
- out.push(parseInt(nibbles.substr(i, 2), 16));
- }
- return out;
- },
- encodeInteger: function CFFCompiler_encodeInteger(value) {
- var code;
- if (value >= -107 && value <= 107) {
- code = [value + 139];
- } else if (value >= 108 && value <= 1131) {
- value = value - 108;
- code = [
- (value >> 8) + 247,
- value & 0xFF
- ];
- } else if (value >= -1131 && value <= -108) {
- value = -value - 108;
- code = [
- (value >> 8) + 251,
- value & 0xFF
- ];
- } else if (value >= -32768 && value <= 32767) {
- code = [
- 0x1c,
- value >> 8 & 0xFF,
- value & 0xFF
- ];
- } else {
- code = [
- 0x1d,
- value >> 24 & 0xFF,
- value >> 16 & 0xFF,
- value >> 8 & 0xFF,
- value & 0xFF
- ];
- }
- return code;
- },
- compileHeader: function CFFCompiler_compileHeader(header) {
- return [
- header.major,
- header.minor,
- header.hdrSize,
- header.offSize
- ];
- },
- compileNameIndex: function CFFCompiler_compileNameIndex(names) {
- var nameIndex = new CFFIndex();
- for (var i = 0, ii = names.length; i < ii; ++i) {
- nameIndex.add(stringToBytes(names[i]));
- }
- return this.compileIndex(nameIndex);
- },
- compileTopDicts: function CFFCompiler_compileTopDicts(dicts, length, removeCidKeys) {
- var fontDictTrackers = [];
- var fdArrayIndex = new CFFIndex();
- for (var i = 0, ii = dicts.length; i < ii; ++i) {
- var fontDict = dicts[i];
- if (removeCidKeys) {
- fontDict.removeByName('CIDFontVersion');
- fontDict.removeByName('CIDFontRevision');
- fontDict.removeByName('CIDFontType');
- fontDict.removeByName('CIDCount');
- fontDict.removeByName('UIDBase');
- }
- var fontDictTracker = new CFFOffsetTracker();
- var fontDictData = this.compileDict(fontDict, fontDictTracker);
- fontDictTrackers.push(fontDictTracker);
- fdArrayIndex.add(fontDictData);
- fontDictTracker.offset(length);
- }
- fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
- return {
- trackers: fontDictTrackers,
- output: fdArrayIndex
- };
- },
- compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, trackers, output) {
- for (var i = 0, ii = dicts.length; i < ii; ++i) {
- var fontDict = dicts[i];
- assert(fontDict.privateDict && fontDict.hasName('Private'), 'There must be an private dictionary.');
- var privateDict = fontDict.privateDict;
- var privateDictTracker = new CFFOffsetTracker();
- var privateDictData = this.compileDict(privateDict, privateDictTracker);
- var outputLength = output.length;
- privateDictTracker.offset(outputLength);
- if (!privateDictData.length) {
- outputLength = 0;
- }
- trackers[i].setEntryLocation('Private', [
- privateDictData.length,
- outputLength
- ], output);
- output.add(privateDictData);
- if (privateDict.subrsIndex && privateDict.hasName('Subrs')) {
- var subrs = this.compileIndex(privateDict.subrsIndex);
- privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], output);
- output.add(subrs);
- }
- }
- },
- compileDict: function CFFCompiler_compileDict(dict, offsetTracker) {
- var out = [];
- var order = dict.order;
- for (var i = 0; i < order.length; ++i) {
- var key = order[i];
- if (!(key in dict.values)) {
- continue;
- }
- var values = dict.values[key];
- var types = dict.types[key];
- if (!isArray(types)) {
- types = [types];
- }
- if (!isArray(values)) {
- values = [values];
- }
- if (values.length === 0) {
- continue;
- }
- for (var j = 0, jj = types.length; j < jj; ++j) {
- var type = types[j];
- var value = values[j];
- switch (type) {
- case 'num':
- case 'sid':
- out = out.concat(this.encodeNumber(value));
- break;
- case 'offset':
- var name = dict.keyToNameMap[key];
- if (!offsetTracker.isTracking(name)) {
- offsetTracker.track(name, out.length);
- }
- out = out.concat([
- 0x1d,
- 0,
- 0,
- 0,
- 0
- ]);
- break;
- case 'array':
- case 'delta':
- out = out.concat(this.encodeNumber(value));
- for (var k = 1, kk = values.length; k < kk; ++k) {
- out = out.concat(this.encodeNumber(values[k]));
- }
- break;
- default:
- error('Unknown data type of ' + type);
- break;
- }
- }
- out = out.concat(dict.opcodes[key]);
- }
- return out;
- },
- compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
- var stringIndex = new CFFIndex();
- for (var i = 0, ii = strings.length; i < ii; ++i) {
- stringIndex.add(stringToBytes(strings[i]));
- }
- return this.compileIndex(stringIndex);
- },
- compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
- var globalSubrIndex = this.cff.globalSubrIndex;
- this.out.writeByteArray(this.compileIndex(globalSubrIndex));
- },
- compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) {
- return this.compileIndex(charStrings);
- },
- compileCharset: function CFFCompiler_compileCharset(charset) {
- return this.compileTypedArray(charset.raw);
- },
- compileEncoding: function CFFCompiler_compileEncoding(encoding) {
- return this.compileTypedArray(encoding.raw);
- },
- compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) {
- return this.compileTypedArray(fdSelect);
- },
- compileTypedArray: function CFFCompiler_compileTypedArray(data) {
- var out = [];
- for (var i = 0, ii = data.length; i < ii; ++i) {
- out[i] = data[i];
- }
- return out;
- },
- compileIndex: function CFFCompiler_compileIndex(index, trackers) {
- trackers = trackers || [];
- var objects = index.objects;
- var count = objects.length;
- if (count === 0) {
- return [
- 0,
- 0,
- 0
- ];
- }
- var data = [
- count >> 8 & 0xFF,
- count & 0xff
- ];
- var lastOffset = 1, i;
- for (i = 0; i < count; ++i) {
- lastOffset += objects[i].length;
- }
- var offsetSize;
- if (lastOffset < 0x100) {
- offsetSize = 1;
- } else if (lastOffset < 0x10000) {
- offsetSize = 2;
- } else if (lastOffset < 0x1000000) {
- offsetSize = 3;
- } else {
- offsetSize = 4;
- }
- data.push(offsetSize);
- var relativeOffset = 1;
- for (i = 0; i < count + 1; i++) {
- if (offsetSize === 1) {
- data.push(relativeOffset & 0xFF);
- } else if (offsetSize === 2) {
- data.push(relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- } else if (offsetSize === 3) {
- data.push(relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- } else {
- data.push(relativeOffset >>> 24 & 0xFF, relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
- }
- if (objects[i]) {
- relativeOffset += objects[i].length;
- }
- }
- for (i = 0; i < count; i++) {
- if (trackers[i]) {
- trackers[i].offset(data.length);
- }
- for (var j = 0, jj = objects[i].length; j < jj; j++) {
- data.push(objects[i][j]);
- }
- }
- return data;
- }
- };
- return CFFCompiler;
- }();
- exports.CFFStandardStrings = CFFStandardStrings;
- exports.CFFParser = CFFParser;
- exports.CFF = CFF;
- exports.CFFHeader = CFFHeader;
- exports.CFFStrings = CFFStrings;
- exports.CFFIndex = CFFIndex;
- exports.CFFCharset = CFFCharset;
- exports.CFFTopDict = CFFTopDict;
- exports.CFFPrivateDict = CFFPrivateDict;
- exports.CFFCompiler = CFFCompiler;
|