commit
695fe33601
1552
Encodings.js
Normal file
1552
Encodings.js
Normal file
File diff suppressed because it is too large
Load Diff
689
cffStandardStrings.js
Normal file
689
cffStandardStrings.js
Normal file
@ -0,0 +1,689 @@
|
|||||||
|
var CFFStrings = [
|
||||||
|
".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",
|
||||||
|
"266 ff",
|
||||||
|
"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 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"
|
||||||
|
},
|
||||||
|
"9": {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
391
fonts_utils.js
Normal file
391
fonts_utils.js
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
if (format == 0) {
|
||||||
|
charset[".notdef"] = readCharstringEncoding(aCharstrings[0]);
|
||||||
|
|
||||||
|
var count = aCharstrings.length - 1;
|
||||||
|
for (var i = 1; i < count + 1; i++) {
|
||||||
|
var sid = aStream.getByte() << 8 | aStream.getByte();
|
||||||
|
charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
|
||||||
|
//log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
|
||||||
|
}
|
||||||
|
} else if (format == 1) {
|
||||||
|
error("Charset Range are not supported");
|
||||||
|
} else {
|
||||||
|
error("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) {
|
||||||
|
var charstringTokens = [];
|
||||||
|
|
||||||
|
var count = aString.length;
|
||||||
|
for (var i = 0; i < count; ) {
|
||||||
|
var value = aString[i++];
|
||||||
|
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) {
|
||||||
|
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) - 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; i) {
|
||||||
|
var value = aString[i++];
|
||||||
|
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 byte = aString[i++];
|
||||||
|
|
||||||
|
var nibbles = [parseInt(byte / 16), parseInt(byte % 16)];
|
||||||
|
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) - 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) {
|
||||||
|
error("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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var offsets = [];
|
||||||
|
for (var i = 0; i < count + 1; i++)
|
||||||
|
offsets.push(getNextOffset());
|
||||||
|
|
||||||
|
log("Found " + count + " objects at offsets :" + offsets + " (offsize: " + offsize + ")");
|
||||||
|
|
||||||
|
// Now extract the objects
|
||||||
|
var relativeOffset = aStream.pos;
|
||||||
|
var objects = [];
|
||||||
|
for (var 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(aFilePath) {
|
||||||
|
var font = new Dict();
|
||||||
|
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", aFilePath, false);
|
||||||
|
xhr.mozResponseType = xhr.responseType = "arraybuffer";
|
||||||
|
xhr.expected = (document.URL.indexOf("file:") == 0) ? 0 : 200;
|
||||||
|
xhr.send(null);
|
||||||
|
this.data = new Stream(xhr.mozResponseArrayBuffer || xhr.mozResponse ||
|
||||||
|
xhr.responseArrayBuffer || xhr.response);
|
||||||
|
|
||||||
|
// Turn on this flag for additional debugging logs
|
||||||
|
var debug = false;
|
||||||
|
|
||||||
|
function dump(aStr) {
|
||||||
|
if (debug)
|
||||||
|
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 (IsNum(token)) {
|
||||||
|
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 && 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(aStream) {
|
||||||
|
font.set("major", aStream.getByte());
|
||||||
|
font.set("minor", aStream.getByte());
|
||||||
|
font.set("hdrSize", aStream.getByte());
|
||||||
|
font.set("offsize", aStream.getByte());
|
||||||
|
|
||||||
|
// Move the cursor after the header
|
||||||
|
aStream.skip(font.get("hdrSize") - aStream.pos);
|
||||||
|
|
||||||
|
// Read the NAME Index
|
||||||
|
dump("Reading Index: Names");
|
||||||
|
font.set("Names", readFontIndexData(aStream));
|
||||||
|
log("Names: " + font.get("Names"));
|
||||||
|
|
||||||
|
// Read the Top Dict Index
|
||||||
|
dump("Reading Index: TopDict");
|
||||||
|
var topDict = readFontIndexData(aStream, true);
|
||||||
|
log("TopDict: " + topDict);
|
||||||
|
|
||||||
|
// Read the String Index
|
||||||
|
dump("Reading Index: Strings");
|
||||||
|
var strings = readFontIndexData(aStream);
|
||||||
|
log("strings: " + strings);
|
||||||
|
|
||||||
|
// Fill up the Strings dictionary with the new unique strings
|
||||||
|
for (var i = 0; i < strings.length; i++)
|
||||||
|
CFFStrings.push(strings[i].join(""));
|
||||||
|
|
||||||
|
// Parse the TopDict operator
|
||||||
|
var objects = [];
|
||||||
|
var count = topDict.length;
|
||||||
|
for (var 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 private = font.get("Private");
|
||||||
|
log("Reading Private Dict (offset: " + private.offset + " size: " + private.size + ")");
|
||||||
|
aStream.pos = private.offset;
|
||||||
|
|
||||||
|
var privateDict = [];
|
||||||
|
for (var i = 0; i < private.size; i++)
|
||||||
|
privateDict.push(aStream.getByte());
|
||||||
|
dump("private:" + privateDict);
|
||||||
|
parseAsToken(privateDict, CFFDictPrivateDataMap);
|
||||||
|
|
||||||
|
for (var p in font.map)
|
||||||
|
dump(p + "::" + font.get(p));
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
error("Need to support CFFISOAdobeCharset");
|
||||||
|
} else if (charsetEntry == 1) {
|
||||||
|
error("Need to support CFFExpert");
|
||||||
|
} else if (charsetEntry == 2) {
|
||||||
|
error("Need to support CFFExpertSubsetCharset");
|
||||||
|
} else {
|
||||||
|
aStream.pos = charsetEntry;
|
||||||
|
var charset = 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) {
|
||||||
|
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, 0600, 0);
|
||||||
|
|
||||||
|
var bos = Cc["@mozilla.org/binaryoutputstream;1"]
|
||||||
|
.createInstance(Ci.nsIBinaryOutputStream);
|
||||||
|
bos.setOutputStream(stream);
|
||||||
|
bos.writeByteArray(aBytes, aBytes.length);
|
||||||
|
stream.close();
|
||||||
|
};
|
||||||
|
|
4289
glyphlist.js
Normal file
4289
glyphlist.js
Normal file
File diff suppressed because it is too large
Load Diff
101
pdf.js
101
pdf.js
@ -5,6 +5,7 @@ var ERRORS = 0, WARNINGS = 1, TODOS = 5;
|
|||||||
var verbosity = WARNINGS;
|
var verbosity = WARNINGS;
|
||||||
|
|
||||||
function log(msg) {
|
function log(msg) {
|
||||||
|
msg = msg.toString ? msg.toString() : msg;
|
||||||
if (console && console.log)
|
if (console && console.log)
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
else if (print)
|
else if (print)
|
||||||
@ -51,7 +52,7 @@ var Stream = (function() {
|
|||||||
this.bytes = new Uint8Array(arrayBuffer);
|
this.bytes = new Uint8Array(arrayBuffer);
|
||||||
this.start = start || 0;
|
this.start = start || 0;
|
||||||
this.pos = this.start;
|
this.pos = this.start;
|
||||||
this.end = (start + length) || arrayBuffer.byteLength;
|
this.end = (start + length) || this.bytes.byteLength;
|
||||||
this.dict = dict;
|
this.dict = dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +93,7 @@ var Stream = (function() {
|
|||||||
return ch;
|
return ch;
|
||||||
},
|
},
|
||||||
skip: function(n) {
|
skip: function(n) {
|
||||||
if (!n)
|
if (!n && !IsNum(n))
|
||||||
n = 1;
|
n = 1;
|
||||||
this.pos += n;
|
this.pos += n;
|
||||||
},
|
},
|
||||||
@ -522,6 +523,9 @@ var Name = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
|
toString: function() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return constructor;
|
return constructor;
|
||||||
@ -533,6 +537,9 @@ var Cmd = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
|
toString: function() {
|
||||||
|
return this.cmd;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return constructor;
|
return constructor;
|
||||||
@ -555,6 +562,16 @@ var Dict = (function() {
|
|||||||
},
|
},
|
||||||
set: function(key, value) {
|
set: function(key, value) {
|
||||||
this.map[key] = value;
|
this.map[key] = value;
|
||||||
|
},
|
||||||
|
forEach: function(aCallback) {
|
||||||
|
for (var key in this.map)
|
||||||
|
aCallback(key, this.map[key]);
|
||||||
|
},
|
||||||
|
toString: function() {
|
||||||
|
var keys = [];
|
||||||
|
for (var key in this.map)
|
||||||
|
keys.push(key);
|
||||||
|
return "Dict with " + keys.length + " keys: " + keys;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -777,6 +794,7 @@ var Lexer = (function() {
|
|||||||
x = (x << 3) + (ch - '0');
|
x = (x << 3) + (ch - '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
str += String.fromCharCode(x);
|
str += String.fromCharCode(x);
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
@ -898,10 +916,11 @@ var Lexer = (function() {
|
|||||||
stream.skip();
|
stream.skip();
|
||||||
return new Cmd(">>");
|
return new Cmd(">>");
|
||||||
}
|
}
|
||||||
|
case "{":
|
||||||
|
case "}":
|
||||||
|
return new Cmd(ch);
|
||||||
// fall through
|
// fall through
|
||||||
case ')':
|
case ')':
|
||||||
case '{':
|
|
||||||
case '}':
|
|
||||||
error("Illegal character");
|
error("Illegal character");
|
||||||
return Error;
|
return Error;
|
||||||
}
|
}
|
||||||
@ -1706,7 +1725,49 @@ var CanvasGraphics = (function() {
|
|||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
translateFont: function(fontDict, xref, resources) {
|
translateFont: function(fontDict, xref, resources) {
|
||||||
return "translated";
|
var descriptor = xref.fetch(fontDict.get("FontDescriptor"));
|
||||||
|
var fontName = descriptor.get("FontName").name;
|
||||||
|
fontName = fontName.replace("+", "_");
|
||||||
|
|
||||||
|
var font = Fonts[fontName];
|
||||||
|
if (!font) {
|
||||||
|
var fontFile = descriptor.get2("FontFile", "FontFile2");
|
||||||
|
fontFile = xref.fetchIfRef(fontFile);
|
||||||
|
|
||||||
|
// Generate the custom cmap of the font if needed
|
||||||
|
var encodingMap = {};
|
||||||
|
if (fontDict.has("Encoding")) {
|
||||||
|
var encoding = xref.fetchIfRef(fontDict.get("Encoding"));
|
||||||
|
if (IsDict(encoding)) {
|
||||||
|
// Build an map between codes and glyphs
|
||||||
|
var differences = encoding.get("Differences");
|
||||||
|
var index = 0;
|
||||||
|
for (var j = 0; j < differences.length; j++) {
|
||||||
|
var data = differences[j];
|
||||||
|
IsNum(data) ? index = data : encodingMap[index++] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the font charset
|
||||||
|
var charset = descriptor.get("CharSet").split("/");
|
||||||
|
} else if (IsName(encoding)) {
|
||||||
|
var encoding = Encodings[encoding];
|
||||||
|
var widths = xref.fetchIfRef(fontDict.get("Widths"));
|
||||||
|
var firstchar = xref.fetchIfRef(fontDict.get("FirstChar"));
|
||||||
|
|
||||||
|
var charset = [];
|
||||||
|
for (var j = 0; j < widths.length; j++) {
|
||||||
|
var index = widths[j];
|
||||||
|
if (index)
|
||||||
|
charset.push(encoding[j + firstchar]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fontBBox = descriptor.get("FontBBox");
|
||||||
|
var subtype = fontDict.get("Subtype").name;
|
||||||
|
new Font(fontName, fontFile, encodingMap, charset, fontBBox, subtype);
|
||||||
|
}
|
||||||
|
return Fonts[fontName];
|
||||||
},
|
},
|
||||||
|
|
||||||
beginDrawing: function(mediaBox) {
|
beginDrawing: function(mediaBox) {
|
||||||
@ -1943,16 +2004,25 @@ var CanvasGraphics = (function() {
|
|||||||
this.current.leading = leading;
|
this.current.leading = leading;
|
||||||
},
|
},
|
||||||
setFont: function(fontRef, size) {
|
setFont: function(fontRef, size) {
|
||||||
var fontRes = this.res.get("Font");
|
var font = this.res.get("Font");
|
||||||
if (!fontRes)
|
if (!IsDict(font))
|
||||||
return;
|
return;
|
||||||
fontRes = this.xref.fetchIfRef(fontRes);
|
|
||||||
var font = fontRes.get(fontRef.name);
|
font = font.get(fontRef.name);
|
||||||
|
font = this.xref.fetchIfRef(font);
|
||||||
if (!font)
|
if (!font)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var fontName = "";
|
||||||
|
var fontDescriptor = font.get("FontDescriptor");
|
||||||
|
if (fontDescriptor.num) {
|
||||||
|
var fontDescriptor = this.xref.fetchIfRef(fontDescriptor);
|
||||||
|
fontName = fontDescriptor.get("FontName").name.replace("+", "_");
|
||||||
|
Fonts.active = fontName;
|
||||||
|
}
|
||||||
|
|
||||||
this.current.fontSize = size;
|
this.current.fontSize = size;
|
||||||
TODO("using hard-coded font for testing");
|
this.ctx.font = this.current.fontSize +'px "' + fontName + '"';
|
||||||
this.ctx.font = this.current.fontSize +'px "Nimbus Roman No9 L"';
|
|
||||||
},
|
},
|
||||||
setTextRenderingMode: function(mode) {
|
setTextRenderingMode: function(mode) {
|
||||||
TODO("text rendering mode");
|
TODO("text rendering mode");
|
||||||
@ -1982,7 +2052,12 @@ var CanvasGraphics = (function() {
|
|||||||
this.ctx.scale(1, -1);
|
this.ctx.scale(1, -1);
|
||||||
this.ctx.transform.apply(this.ctx, this.current.textMatrix);
|
this.ctx.transform.apply(this.ctx, this.current.textMatrix);
|
||||||
|
|
||||||
this.ctx.fillText(text, this.current.x, this.current.y);
|
// Replace characters code by glyphs code
|
||||||
|
var glyphs = [];
|
||||||
|
for (var i = 0; i < text.length; i++)
|
||||||
|
glyphs[i] = String.fromCharCode(Fonts.unicodeFromCode(text[i].charCodeAt(0)));
|
||||||
|
|
||||||
|
this.ctx.fillText(glyphs.join(""), this.current.x, this.current.y);
|
||||||
this.current.x += this.ctx.measureText(text).width;
|
this.current.x += this.ctx.measureText(text).width;
|
||||||
|
|
||||||
this.ctx.restore();
|
this.ctx.restore();
|
||||||
|
35
test.css
Normal file
35
test.css
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
|
||||||
|
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 6px;
|
||||||
|
padding: 0px;
|
||||||
|
background-color: #c0bdb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls {
|
||||||
|
position:fixed;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 7px;
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
background-color: rgb(242, 240, 238);
|
||||||
|
}
|
||||||
|
|
||||||
|
span#info {
|
||||||
|
float: right;
|
||||||
|
font: 14px sans-serif;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#viewer {
|
||||||
|
margin: auto;
|
||||||
|
border: 1px solid black;
|
||||||
|
width: 8.5in;
|
||||||
|
height: 11in;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pageNumber {
|
||||||
|
text-align: right;
|
||||||
|
}
|
173
test.html
173
test.html
@ -1,155 +1,34 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Simple pdf.js page viewer</title>
|
<title>Simple pdf.js page viewer</title>
|
||||||
<script type="text/javascript"
|
<link rel="stylesheet" href="test.css"></link>
|
||||||
src="pdf.js"></script>
|
|
||||||
<style type"text/css">
|
|
||||||
body {
|
|
||||||
margin: 6px;
|
|
||||||
padding: 0px;
|
|
||||||
background-color: #c0bdb7;
|
|
||||||
}
|
|
||||||
#controls {
|
|
||||||
border-bottom: 1px solid black;
|
|
||||||
position:fixed;
|
|
||||||
left: 0px; top: 0px;
|
|
||||||
width: 100%;
|
|
||||||
padding: 7px;
|
|
||||||
background-color: rgb(242, 240, 238);
|
|
||||||
}
|
|
||||||
span#info {
|
|
||||||
float: right;
|
|
||||||
font: 14px sans-serif;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
#viewer {
|
|
||||||
margin: auto;
|
|
||||||
border: 1px solid black;
|
|
||||||
width: 8.5in;
|
|
||||||
height: 11in;
|
|
||||||
}
|
|
||||||
#pageNumber {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript" src="test.js"></script>
|
||||||
function queryParams() {
|
<script type="text/javascript" src="pdf.js"></script>
|
||||||
var qs = window.location.search.substring(1);
|
<script type="text/javascript" src="fonts.js"></script>
|
||||||
var kvs = qs.split("&");
|
<script type="text/javascript" src="cffStandardStrings.js"></script>
|
||||||
var params = { };
|
<script type="text/javascript" src="Encodings.js"></script>
|
||||||
for (var i = 0; i < kvs.length; ++i) {
|
<script type="text/javascript" src="glyphlist.js"></script>
|
||||||
var kv = kvs[i].split("=");
|
</head>
|
||||||
params[unescape(kv[0])] = unescape(kv[1]);
|
|
||||||
}
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
var canvas, numPages, pageDisplay, pageNum;
|
<body onload="load();">
|
||||||
function load(userInput) {
|
<div id="controls">
|
||||||
canvas = document.getElementById("canvas");
|
|
||||||
canvas.mozOpaque = true;
|
|
||||||
pageDisplay = document.getElementById("pageNumber");
|
|
||||||
infoDisplay = document.getElementById("info");
|
|
||||||
pageNum = parseInt(queryParams().page) || 1;
|
|
||||||
fileName = userInput;
|
|
||||||
if(!userInput){
|
|
||||||
fileName = queryParams().file || "compressed.tracemonkey-pldi-09.pdf";
|
|
||||||
}
|
|
||||||
open(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
function open(url) {
|
|
||||||
document.title = url;
|
|
||||||
req = new XMLHttpRequest();
|
|
||||||
req.open("GET", url);
|
|
||||||
req.mozResponseType = req.responseType = "arraybuffer";
|
|
||||||
req.expected = (document.URL.indexOf("file:") == 0) ? 0 : 200;
|
|
||||||
req.onreadystatechange = xhrstate;
|
|
||||||
req.send(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function xhrstate() {
|
|
||||||
if (req.readyState == 4 && req.status == req.expected) {
|
|
||||||
var data = req.mozResponseArrayBuffer ||
|
|
||||||
req.mozResponse ||
|
|
||||||
req.responseArrayBuffer ||
|
|
||||||
req.response;
|
|
||||||
pdf = new PDFDoc(new Stream(data));
|
|
||||||
numPages = pdf.numPages;
|
|
||||||
document.getElementById("numPages").innerHTML = numPages.toString();
|
|
||||||
gotoPage(pageNum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayPage(num) {
|
|
||||||
pageDisplay.value = num;
|
|
||||||
|
|
||||||
var t0 = Date.now();
|
|
||||||
|
|
||||||
var page = pdf.getPage(pageNum = num);
|
|
||||||
|
|
||||||
var t1 = Date.now();
|
|
||||||
|
|
||||||
var ctx = canvas.getContext("2d");
|
|
||||||
ctx.save();
|
|
||||||
ctx.fillStyle = "rgb(255, 255, 255)";
|
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
||||||
ctx.restore();
|
|
||||||
|
|
||||||
var gfx = new CanvasGraphics(ctx);
|
|
||||||
|
|
||||||
// page.compile will collect all fonts for us, once we have loaded them
|
|
||||||
// we can trigger the actual page rendering with page.display
|
|
||||||
var fonts = [];
|
|
||||||
page.compile(gfx, fonts);
|
|
||||||
|
|
||||||
var t2 = Date.now();
|
|
||||||
|
|
||||||
// This should be called when font loading is complete
|
|
||||||
page.display(gfx);
|
|
||||||
|
|
||||||
var t3 = Date.now();
|
|
||||||
|
|
||||||
infoDisplay.innerHTML = "Time to load/compile/render: "+ (t1 - t0) + "/" + (t2 - t1) + "/" + (t3 - t2) + " ms";
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextPage() {
|
|
||||||
if (pageNum < numPages)
|
|
||||||
++pageNum;
|
|
||||||
displayPage(pageNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
function prevPage() {
|
|
||||||
if (pageNum > 1)
|
|
||||||
--pageNum;
|
|
||||||
displayPage(pageNum);
|
|
||||||
}
|
|
||||||
function gotoPage(num) {
|
|
||||||
if (0 <= num && num <= numPages)
|
|
||||||
pageNum = num;
|
|
||||||
displayPage(pageNum);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body onload="load();">
|
|
||||||
<div id="controls">
|
|
||||||
<input type="file" style="float: right; margin: auto 32px;" onChange="load(this.value.toString());"></input>
|
<input type="file" style="float: right; margin: auto 32px;" onChange="load(this.value.toString());"></input>
|
||||||
<!-- This only opens supported PDFs from the source path...
|
<!-- This only opens supported PDFs from the source path...
|
||||||
-- Can we use JSONP to overcome the same-origin restrictions? -->
|
-- Can we use JSONP to overcome the same-origin restrictions? -->
|
||||||
<button onclick="prevPage();">Previous</button>
|
<button onclick="prevPage();">Previous</button>
|
||||||
<button onclick="nextPage();">Next</button>
|
<button onclick="nextPage();">Next</button>
|
||||||
<input type="text" id="pageNumber" onchange="gotoPage(this.value);"
|
<input type="text" id="pageNumber" onchange="gotoPage(this.value);"
|
||||||
value="1" size="4"></input>
|
value="1" size="4"></input>
|
||||||
/ <span id="numPages">--</span>
|
<span id="numPages">--</span>
|
||||||
<span id="info"></span>
|
<span id="info"></span>
|
||||||
</div>
|
</div>
|
||||||
<div id="viewer">
|
|
||||||
<!-- Canvas dimensions must be specified in CSS pixels. CSS pixels
|
|
||||||
-- are always 96 dpi. These dimensions are 8.5x11in at 96dpi. -->
|
|
||||||
<canvas id="canvas" width="816" height="1056"></canvas>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
<div id="viewer">
|
||||||
|
<!-- Canvas dimensions must be specified in CSS pixels. CSS pixels
|
||||||
|
are always 96 dpi. These dimensions are 8.5x11in at 96dpi. -->
|
||||||
|
<canvas id="canvas" width="816" height="1056"></canvas>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
117
test.js
Normal file
117
test.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
|
||||||
|
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
|
||||||
|
|
||||||
|
var pdfDocument, canvas, pageDisplay, pageNum, pageInterval;
|
||||||
|
function load(userInput) {
|
||||||
|
canvas = document.getElementById("canvas");
|
||||||
|
canvas.mozOpaque = true;
|
||||||
|
pageNum = parseInt(queryParams().page) || 1;
|
||||||
|
fileName = userInput;
|
||||||
|
if (!userInput) {
|
||||||
|
fileName = queryParams().file || "compressed.tracemonkey-pldi-09.pdf";
|
||||||
|
}
|
||||||
|
open(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function queryParams() {
|
||||||
|
var qs = window.location.search.substring(1);
|
||||||
|
var kvs = qs.split("&");
|
||||||
|
var params = { };
|
||||||
|
for (var i = 0; i < kvs.length; ++i) {
|
||||||
|
var kv = kvs[i].split("=");
|
||||||
|
params[unescape(kv[0])] = unescape(kv[1]);
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
function open(url) {
|
||||||
|
document.title = url;
|
||||||
|
req = new XMLHttpRequest();
|
||||||
|
req.open("GET", url);
|
||||||
|
req.mozResponseType = req.responseType = "arraybuffer";
|
||||||
|
req.expected = (document.URL.indexOf("file:") == 0) ? 0 : 200;
|
||||||
|
req.onreadystatechange = function() {
|
||||||
|
if (req.readyState == 4 && req.status == req.expected) {
|
||||||
|
var data = req.mozResponseArrayBuffer || req.mozResponse ||
|
||||||
|
req.responseArrayBuffer || req.response;
|
||||||
|
pdfDocument = new PDFDoc(new Stream(data));
|
||||||
|
numPages = pdfDocument.numPages;
|
||||||
|
document.getElementById("numPages").innerHTML = numPages.toString();
|
||||||
|
goToPage(pageNum);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotoPage(num) {
|
||||||
|
if (0 <= num && num <= numPages)
|
||||||
|
pageNum = num;
|
||||||
|
displayPage(pageNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayPage(num) {
|
||||||
|
if (pageNum != num)
|
||||||
|
window.clearTimeout(pageInterval);
|
||||||
|
|
||||||
|
document.getElementById("pageNumber").value = num;
|
||||||
|
|
||||||
|
var t0 = Date.now();
|
||||||
|
|
||||||
|
var page = pdfDocument.getPage(pageNum = num);
|
||||||
|
|
||||||
|
var t1 = Date.now();
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
ctx.save();
|
||||||
|
ctx.fillStyle = "rgb(255, 255, 255)";
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.restore();
|
||||||
|
|
||||||
|
var gfx = new CanvasGraphics(ctx);
|
||||||
|
|
||||||
|
// page.compile will collect all fonts for us, once we have loaded them
|
||||||
|
// we can trigger the actual page rendering with page.display
|
||||||
|
var fonts = [];
|
||||||
|
page.compile(gfx, fonts);
|
||||||
|
var t2 = Date.now();
|
||||||
|
|
||||||
|
var interval = 0;
|
||||||
|
for (var i = 0; i < fonts.length; i++) {
|
||||||
|
if (fonts[i].loading) {
|
||||||
|
interval = 10;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME This need to be replaced by an event
|
||||||
|
pageInterval = setInterval(function() {
|
||||||
|
for (var i = 0; i < fonts.length; i++) {
|
||||||
|
if (fonts[i].loading)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var t3 = Date.now();
|
||||||
|
|
||||||
|
clearInterval(pageInterval);
|
||||||
|
page.display(gfx);
|
||||||
|
|
||||||
|
var t4 = Date.now();
|
||||||
|
|
||||||
|
var infoDisplay = document.getElementById("info");
|
||||||
|
infoDisplay.innerHTML = "Time to load/compile/fonts/render: "+ (t1 - t0) + "/" + (t2 - t1) + "/" + (t3 - t2) + "/" + (t4 - t3) + " ms";
|
||||||
|
}, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextPage() {
|
||||||
|
if (pageNum < pdfDocument.numPages)
|
||||||
|
displayPage(++pageNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
function prevPage() {
|
||||||
|
if (pageNum > 1)
|
||||||
|
displayPage(--pageNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
function goToPage(num) {
|
||||||
|
if (0 <= num && num <= numPages)
|
||||||
|
displayPage(pageNum = num);
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user