Merge pull request #409 from vingtetun/master
Allow bypassing the sanitizer for Type1C font with encoding supplement
This commit is contained in:
commit
ca17f3e75b
@ -569,6 +569,7 @@ var CipherTransformFactory = (function() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
error('Unknown crypto method');
|
error('Unknown crypto method');
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
|
264
fonts.js
264
fonts.js
@ -57,7 +57,7 @@ var stdFontMap = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var FontMeasure = (function FontMeasure() {
|
var FontMeasure = (function FontMeasure() {
|
||||||
var kScalePrecision = 50;
|
var kScalePrecision = 30;
|
||||||
var ctx = document.createElement('canvas').getContext('2d');
|
var ctx = document.createElement('canvas').getContext('2d');
|
||||||
ctx.scale(1 / kScalePrecision, 1);
|
ctx.scale(1 / kScalePrecision, 1);
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ var FontMeasure = (function FontMeasure() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
setActive: function fonts_setActive(font, size) {
|
setActive: function fonts_setActive(font, size) {
|
||||||
if (current = font) {
|
if (current == font) {
|
||||||
var sizes = current.sizes;
|
var sizes = current.sizes;
|
||||||
if (!(measureCache = sizes[size]))
|
if (!(measureCache = sizes[size]))
|
||||||
measureCache = sizes[size] = Object.create(null);
|
measureCache = sizes[size] = Object.create(null);
|
||||||
@ -80,6 +80,7 @@ var FontMeasure = (function FontMeasure() {
|
|||||||
size *= kScalePrecision;
|
size *= kScalePrecision;
|
||||||
var rule = italic + ' ' + bold + ' ' + size + 'px "' + name + '"';
|
var rule = italic + ' ' + bold + ' ' + size + 'px "' + name + '"';
|
||||||
ctx.font = rule;
|
ctx.font = rule;
|
||||||
|
current = font;
|
||||||
},
|
},
|
||||||
measureText: function fonts_measureText(text) {
|
measureText: function fonts_measureText(text) {
|
||||||
var width;
|
var width;
|
||||||
@ -385,6 +386,7 @@ var Font = (function Font() {
|
|||||||
var constructor = function font_constructor(name, file, properties) {
|
var constructor = function font_constructor(name, file, properties) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.encoding = properties.encoding;
|
this.encoding = properties.encoding;
|
||||||
|
this.glyphs = properties.glyphs;
|
||||||
this.sizes = [];
|
this.sizes = [];
|
||||||
|
|
||||||
// If the font is to be ignored, register it like an already loaded font
|
// If the font is to be ignored, register it like an already loaded font
|
||||||
@ -414,11 +416,8 @@ var Font = (function Font() {
|
|||||||
this.mimetype = 'font/opentype';
|
this.mimetype = 'font/opentype';
|
||||||
|
|
||||||
var subtype = properties.subtype;
|
var subtype = properties.subtype;
|
||||||
if (subtype === 'Type1C') {
|
var cff = (subtype === 'Type1C') ? new Type2CFF(file, properties)
|
||||||
var cff = new Type2CFF(file, properties);
|
: new CFF(name, file, properties);
|
||||||
} else {
|
|
||||||
var cff = new CFF(name, file, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap the CFF data inside an OTF font file
|
// Wrap the CFF data inside an OTF font file
|
||||||
data = this.convert(name, cff, properties);
|
data = this.convert(name, cff, properties);
|
||||||
@ -638,30 +637,28 @@ var Font = (function Font() {
|
|||||||
var ulUnicodeRange3 = 0;
|
var ulUnicodeRange3 = 0;
|
||||||
var ulUnicodeRange4 = 0;
|
var ulUnicodeRange4 = 0;
|
||||||
|
|
||||||
var charset = properties.charset;
|
var firstCharIndex = null;
|
||||||
if (charset && charset.length) {
|
var lastCharIndex = 0;
|
||||||
var firstCharIndex = null;
|
|
||||||
var lastCharIndex = 0;
|
|
||||||
|
|
||||||
for (var i = 0; i < charset.length; i++) {
|
var encoding = properties.encoding;
|
||||||
var code = GlyphsUnicode[charset[i]];
|
for (var index in encoding) {
|
||||||
if (firstCharIndex > code || !firstCharIndex)
|
var code = encoding[index];
|
||||||
firstCharIndex = code;
|
if (firstCharIndex > code || !firstCharIndex)
|
||||||
if (lastCharIndex < code)
|
firstCharIndex = code;
|
||||||
lastCharIndex = code;
|
if (lastCharIndex < code)
|
||||||
|
lastCharIndex = code;
|
||||||
|
|
||||||
var position = getUnicodeRangeFor(code);
|
var position = getUnicodeRangeFor(code);
|
||||||
if (position < 32) {
|
if (position < 32) {
|
||||||
ulUnicodeRange1 |= 1 << position;
|
ulUnicodeRange1 |= 1 << position;
|
||||||
} else if (position < 64) {
|
} else if (position < 64) {
|
||||||
ulUnicodeRange2 |= 1 << position - 32;
|
ulUnicodeRange2 |= 1 << position - 32;
|
||||||
} else if (position < 96) {
|
} else if (position < 96) {
|
||||||
ulUnicodeRange3 |= 1 << position - 64;
|
ulUnicodeRange3 |= 1 << position - 64;
|
||||||
} else if (position < 123) {
|
} else if (position < 123) {
|
||||||
ulUnicodeRange4 |= 1 << position - 96;
|
ulUnicodeRange4 |= 1 << position - 96;
|
||||||
} else {
|
} else {
|
||||||
error('Unicode ranges Bits > 123 are reserved for internal usage');
|
error('Unicode ranges Bits > 123 are reserved for internal usage');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,7 +844,6 @@ var Font = (function Font() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var encoding = properties.encoding;
|
var encoding = properties.encoding;
|
||||||
var charset = properties.charset;
|
|
||||||
for (var i = 0; i < numRecords; i++) {
|
for (var i = 0; i < numRecords; i++) {
|
||||||
var table = records[i];
|
var table = records[i];
|
||||||
font.pos = start + table.offset;
|
font.pos = start + table.offset;
|
||||||
@ -856,7 +852,9 @@ var Font = (function Font() {
|
|||||||
var length = int16(font.getBytes(2));
|
var length = int16(font.getBytes(2));
|
||||||
var language = int16(font.getBytes(2));
|
var language = int16(font.getBytes(2));
|
||||||
|
|
||||||
if (format == 0) {
|
if (format == 4) {
|
||||||
|
return cmap.data;
|
||||||
|
} else if (format == 0) {
|
||||||
// Characters below 0x20 are controls characters that are hardcoded
|
// Characters below 0x20 are controls characters that are hardcoded
|
||||||
// into the platform so if some characters in the font are assigned
|
// into the platform so if some characters in the font are assigned
|
||||||
// under this limit they will not be displayed so let's rewrite the
|
// under this limit they will not be displayed so let's rewrite the
|
||||||
@ -871,35 +869,17 @@ var Font = (function Font() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rewrite = false;
|
if (properties.firstChar < 0x20) {
|
||||||
for (var code in encoding) {
|
var code = 0;
|
||||||
if (code < 0x20 && encoding[code])
|
|
||||||
rewrite = true;
|
|
||||||
|
|
||||||
if (rewrite)
|
|
||||||
encoding[code] = parseInt(code) + 0x1F;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rewrite) {
|
|
||||||
for (var j = 0; j < glyphs.length; j++) {
|
for (var j = 0; j < glyphs.length; j++) {
|
||||||
|
var glyph = glyphs[j];
|
||||||
glyphs[j].unicode += 0x1F;
|
glyphs[j].unicode += 0x1F;
|
||||||
|
properties.glyphs[glyph.glyph] = encoding[++code] = glyph.unicode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmap.data = createCMapTable(glyphs, deltas);
|
|
||||||
} else if (format == 6 && numRecords == 1 && !encoding.empty) {
|
return cmap.data = createCMapTable(glyphs, deltas);
|
||||||
// Format 0 alone is not allowed by the sanitizer so let's rewrite
|
} else if (format == 6) {
|
||||||
// that to a 3-1-4 Unicode BMP table
|
|
||||||
TODO('Use an other source of informations than ' +
|
|
||||||
'charset here, it is not reliable');
|
|
||||||
var glyphs = [];
|
|
||||||
for (var j = 0; j < charset.length; j++) {
|
|
||||||
glyphs.push({
|
|
||||||
unicode: GlyphsUnicode[charset[j]] || 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cmap.data = createCMapTable(glyphs);
|
|
||||||
} else if (format == 6 && numRecords == 1) {
|
|
||||||
// Format 6 is a 2-bytes dense mapping, which means the font data
|
// Format 6 is a 2-bytes dense mapping, which means the font data
|
||||||
// lives glue together even if they are pretty far in the unicode
|
// lives glue together even if they are pretty far in the unicode
|
||||||
// table. (This looks weird, so I can have missed something), this
|
// table. (This looks weird, so I can have missed something), this
|
||||||
@ -912,6 +892,8 @@ var Font = (function Font() {
|
|||||||
var min = 0xffff, max = 0;
|
var min = 0xffff, max = 0;
|
||||||
for (var j = 0; j < entryCount; j++) {
|
for (var j = 0; j < entryCount; j++) {
|
||||||
var charcode = int16(font.getBytes(2));
|
var charcode = int16(font.getBytes(2));
|
||||||
|
if (!charcode)
|
||||||
|
continue;
|
||||||
glyphs.push(charcode);
|
glyphs.push(charcode);
|
||||||
|
|
||||||
if (charcode < min)
|
if (charcode < min)
|
||||||
@ -939,9 +921,10 @@ var Font = (function Font() {
|
|||||||
var index = firstCode;
|
var index = firstCode;
|
||||||
for (var j = start; j <= end; j++)
|
for (var j = start; j <= end; j++)
|
||||||
encoding[index++] = glyphs[j - firstCode - 1].unicode;
|
encoding[index++] = glyphs[j - firstCode - 1].unicode;
|
||||||
cmap.data = createCMapTable(glyphs);
|
return cmap.data = createCMapTable(glyphs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return cmap.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check that required tables are present
|
// Check that required tables are present
|
||||||
@ -1035,9 +1018,8 @@ var Font = (function Font() {
|
|||||||
var glyphs = [];
|
var glyphs = [];
|
||||||
var encoding = properties.encoding;
|
var encoding = properties.encoding;
|
||||||
|
|
||||||
for (var i = 1; i < numGlyphs; i++) {
|
for (var i = 1; i < numGlyphs; i++)
|
||||||
glyphs.push({ unicode: i + kCmapGlyphOffset });
|
glyphs.push({ unicode: i + kCmapGlyphOffset });
|
||||||
}
|
|
||||||
|
|
||||||
if ('undefined' == typeof(encoding[0])) {
|
if ('undefined' == typeof(encoding[0])) {
|
||||||
// the font is directly characters to glyphs with no encoding
|
// the font is directly characters to glyphs with no encoding
|
||||||
@ -1290,7 +1272,7 @@ var Font = (function Font() {
|
|||||||
|
|
||||||
// Check if the glyph has already been converted
|
// Check if the glyph has already been converted
|
||||||
if (!IsNum(unicode))
|
if (!IsNum(unicode))
|
||||||
unicode = encoding[unicode] = GlyphsUnicode[unicode.name];
|
unicode = encoding[charcode] = this.glyphs[unicode];
|
||||||
|
|
||||||
// Handle surrogate pairs
|
// Handle surrogate pairs
|
||||||
if (unicode > 0xFFFF) {
|
if (unicode > 0xFFFF) {
|
||||||
@ -1715,9 +1697,6 @@ var Type1Parser = function() {
|
|||||||
properties.textMatrix = matrix;
|
properties.textMatrix = matrix;
|
||||||
break;
|
break;
|
||||||
case '/Encoding':
|
case '/Encoding':
|
||||||
if (!properties.builtInEncoding)
|
|
||||||
break;
|
|
||||||
|
|
||||||
var size = parseInt(getToken());
|
var size = parseInt(getToken());
|
||||||
getToken(); // read in 'array'
|
getToken(); // read in 'array'
|
||||||
|
|
||||||
@ -1726,9 +1705,12 @@ var Type1Parser = function() {
|
|||||||
if (token == 'dup') {
|
if (token == 'dup') {
|
||||||
var index = parseInt(getToken());
|
var index = parseInt(getToken());
|
||||||
var glyph = getToken();
|
var glyph = getToken();
|
||||||
properties.encoding[index] = GlyphsUnicode[glyph];
|
|
||||||
|
if ('undefined' == typeof(properties.differences[index])) {
|
||||||
|
properties.encoding[index] = glyph;
|
||||||
|
properties.glyphs[glyph] = GlyphsUnicode[glyph];
|
||||||
|
}
|
||||||
getToken(); // read the in 'put'
|
getToken(); // read the in 'put'
|
||||||
j = index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1904,7 +1886,7 @@ CFF.prototype = {
|
|||||||
missings.push(glyph.glyph);
|
missings.push(glyph.glyph);
|
||||||
} else {
|
} else {
|
||||||
charstrings.push({
|
charstrings.push({
|
||||||
glyph: glyph,
|
glyph: glyph.glyph,
|
||||||
unicode: unicode,
|
unicode: unicode,
|
||||||
charstring: glyph.data,
|
charstring: glyph.data,
|
||||||
width: glyph.width,
|
width: glyph.width,
|
||||||
@ -2080,7 +2062,7 @@ CFF.prototype = {
|
|||||||
|
|
||||||
var count = glyphs.length;
|
var count = glyphs.length;
|
||||||
for (var i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
var index = CFFStrings.indexOf(charstrings[i].glyph.glyph);
|
var index = CFFStrings.indexOf(charstrings[i].glyph);
|
||||||
// Some characters like asterikmath && circlecopyrt are
|
// Some characters like asterikmath && circlecopyrt are
|
||||||
// missing from the original strings, for the moment let's
|
// missing from the original strings, for the moment let's
|
||||||
// map them to .notdef and see later if it cause any
|
// map them to .notdef and see later if it cause any
|
||||||
@ -2149,35 +2131,28 @@ CFF.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var Type2CFF = (function() {
|
var Type2CFF = (function() {
|
||||||
|
|
||||||
// TODO: replace parsing code with the Type2Parser in font_utils.js
|
// TODO: replace parsing code with the Type2Parser in font_utils.js
|
||||||
function constructor(file, properties) {
|
function constructor(file, properties) {
|
||||||
var bytes = file.getBytes();
|
var bytes = file.getBytes();
|
||||||
this.bytes = bytes;
|
this.bytes = bytes;
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
|
|
||||||
// Other classes expect this.data to be a Javascript array
|
this.data = this.parse();
|
||||||
var data = [];
|
|
||||||
for (var i = 0, ii = bytes.length; i < ii; ++i)
|
|
||||||
data.push(bytes[i]);
|
|
||||||
this.data = data;
|
|
||||||
|
|
||||||
this.parse();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor.prototype = {
|
constructor.prototype = {
|
||||||
parse: function cff_parse() {
|
parse: function cff_parse() {
|
||||||
var header = this.parseHeader();
|
var header = this.parseHeader();
|
||||||
|
var properties = this.properties;
|
||||||
var nameIndex = this.parseIndex(header.endPos);
|
var nameIndex = this.parseIndex(header.endPos);
|
||||||
|
|
||||||
var dictIndex = this.parseIndex(nameIndex.endPos);
|
var dictIndex = this.parseIndex(nameIndex.endPos);
|
||||||
if (dictIndex.length != 1)
|
if (dictIndex.length != 1)
|
||||||
error('More than 1 font');
|
error('CFF contains more than 1 font');
|
||||||
|
|
||||||
var stringIndex = this.parseIndex(dictIndex.endPos);
|
var stringIndex = this.parseIndex(dictIndex.endPos);
|
||||||
var gsubrIndex = this.parseIndex(stringIndex.endPos);
|
var gsubrIndex = this.parseIndex(stringIndex.endPos);
|
||||||
|
|
||||||
|
|
||||||
var strings = this.getStrings(stringIndex);
|
var strings = this.getStrings(stringIndex);
|
||||||
|
|
||||||
var baseDict = this.parseDict(dictIndex.get(0));
|
var baseDict = this.parseDict(dictIndex.get(0));
|
||||||
@ -2185,31 +2160,45 @@ var Type2CFF = (function() {
|
|||||||
|
|
||||||
var bytes = this.bytes;
|
var bytes = this.bytes;
|
||||||
|
|
||||||
var privInfo = topDict['Private'];
|
var privateInfo = topDict.Private;
|
||||||
var privOffset = privInfo[1], privLength = privInfo[0];
|
var privOffset = privateInfo[1], privLength = privateInfo[0];
|
||||||
var privBytes = bytes.subarray(privOffset, privOffset + privLength);
|
var privBytes = bytes.subarray(privOffset, privOffset + privLength);
|
||||||
baseDict = this.parseDict(privBytes);
|
baseDict = this.parseDict(privBytes);
|
||||||
var privDict = this.getPrivDict(baseDict, strings);
|
var privDict = this.getPrivDict(baseDict, strings);
|
||||||
|
|
||||||
TODO('Parse encoding');
|
var charStrings = this.parseIndex(topDict.CharStrings);
|
||||||
var charStrings = this.parseIndex(topDict['CharStrings']);
|
var charset = this.parseCharsets(topDict.charset,
|
||||||
var charset = this.parseCharsets(topDict['charset'], charStrings.length,
|
charStrings.length, strings);
|
||||||
strings);
|
var hasSupplement = this.parseEncoding(topDict.Encoding, properties,
|
||||||
|
strings, charset);
|
||||||
|
|
||||||
|
// The font sanitizer does not support CFF encoding with a
|
||||||
|
// supplement, since the encoding is not really use to map
|
||||||
|
// between gid to glyph, let's overwrite what is declared in
|
||||||
|
// the top dictionary to let the sanitizer think the font use
|
||||||
|
// StandardEncoding, that's a lie but that's ok.
|
||||||
|
if (hasSupplement)
|
||||||
|
bytes[topDict.Encoding] = 0;
|
||||||
|
|
||||||
// charstrings contains info about glyphs (one element per glyph
|
// charstrings contains info about glyphs (one element per glyph
|
||||||
// containing mappings for {unicode, width})
|
// containing mappings for {unicode, width})
|
||||||
var charstrings = this.getCharStrings(charset, charStrings,
|
var charstrings = this.getCharStrings(charset, charStrings,
|
||||||
privDict, this.properties);
|
privDict, this.properties);
|
||||||
|
|
||||||
// create the mapping between charstring and glyph id
|
// create the mapping between charstring and glyph id
|
||||||
var glyphIds = [];
|
var glyphIds = [];
|
||||||
for (var i = 0, ii = charstrings.length; i < ii; ++i) {
|
for (var i = 0; i < charstrings.length; i++)
|
||||||
glyphIds.push(charstrings[i].gid);
|
glyphIds.push(charstrings[i].gid);
|
||||||
}
|
|
||||||
|
|
||||||
this.charstrings = charstrings;
|
this.charstrings = charstrings;
|
||||||
this.glyphIds = glyphIds;
|
this.glyphIds = glyphIds;
|
||||||
|
|
||||||
|
var data = [];
|
||||||
|
for (var i = 0, ii = bytes.length; i < ii; ++i)
|
||||||
|
data.push(bytes[i]);
|
||||||
|
return data;
|
||||||
},
|
},
|
||||||
|
|
||||||
getCharStrings: function cff_charstrings(charsets, charStrings,
|
getCharStrings: function cff_charstrings(charsets, charStrings,
|
||||||
privDict, properties) {
|
privDict, properties) {
|
||||||
var widths = properties.widths;
|
var widths = properties.widths;
|
||||||
@ -2218,31 +2207,93 @@ var Type2CFF = (function() {
|
|||||||
var nominalWidth = privDict['nominalWidthX'];
|
var nominalWidth = privDict['nominalWidthX'];
|
||||||
|
|
||||||
var charstrings = [];
|
var charstrings = [];
|
||||||
for (var i = 0, ii = charsets.length; i < ii; ++i) {
|
var differences = properties.differences;
|
||||||
var charName = charsets[i];
|
var index = 0;
|
||||||
var charCode = GlyphsUnicode[charName];
|
var kCmapGlyphOffset = 0xE000;
|
||||||
if (charCode) {
|
for (var i = 1; i < charsets.length; i++) {
|
||||||
var width = widths[charCode] || defaultWidth;
|
var glyph = charsets[i];
|
||||||
charstrings.push({unicode: charCode, width: width, gid: i});
|
for (var j = index; j < differences.length; j++) {
|
||||||
} else {
|
if (differences[j]) {
|
||||||
if (charName !== '.notdef')
|
index = j;
|
||||||
warn('Cannot find unicode for glyph ' + charName);
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var code = differences.indexOf(glyph);
|
||||||
|
if (code == -1)
|
||||||
|
code = properties.glyphs[glyph] || index;
|
||||||
|
|
||||||
|
var width = widths[code] || defaultWidth;
|
||||||
|
properties.encoding[index] = index + kCmapGlyphOffset;
|
||||||
|
charstrings.push({unicode: code + kCmapGlyphOffset, width: width, gid: i});
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort the arry by the unicode value
|
// sort the array by the unicode value
|
||||||
charstrings.sort(function(a, b) {return a.unicode - b.unicode});
|
charstrings.sort(function(a, b) {return a.unicode - b.unicode});
|
||||||
return charstrings;
|
return charstrings;
|
||||||
},
|
},
|
||||||
parseEncoding: function cff_parseencoding(pos) {
|
|
||||||
if (pos == 0) {
|
parseEncoding: function cff_parseencoding(pos, properties, strings, charset) {
|
||||||
return Encodings.StandardEncoding;
|
var encoding = {};
|
||||||
} else if (pos == 1) {
|
var bytes = this.bytes;
|
||||||
return Encodings.ExpertEncoding;
|
|
||||||
|
function readSupplement() {
|
||||||
|
var supplementsCount = bytes[pos++];
|
||||||
|
for (var i = 0; i < supplementsCount; i++) {
|
||||||
|
var code = bytes[pos++];
|
||||||
|
var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
|
||||||
|
encoding[code] = properties.differences.indexOf(strings[sid]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error('not implemented encodings');
|
if (pos == 0 || pos == 1) {
|
||||||
|
var gid = 1;
|
||||||
|
var baseEncoding = pos ? Encodings.ExpertEncoding
|
||||||
|
: Encodings.StandardEncoding;
|
||||||
|
for (var i = 0; i < charset.length; i++) {
|
||||||
|
var index = baseEncoding.indexOf(charset[i]);
|
||||||
|
if (index != -1)
|
||||||
|
encoding[index] = gid++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var format = bytes[pos++];
|
||||||
|
switch (format & 0x7f) {
|
||||||
|
case 0:
|
||||||
|
var glyphsCount = bytes[pos++];
|
||||||
|
for (var i = 1; i <= glyphsCount; i++)
|
||||||
|
encoding[bytes[pos++]] = i;
|
||||||
|
|
||||||
|
if (format & 0x80) {
|
||||||
|
readSupplement();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
var rangesCount = bytes[pos++];
|
||||||
|
var gid = 1;
|
||||||
|
for (var i = 0; i < rangesCount; i++) {
|
||||||
|
var start = bytes[pos++];
|
||||||
|
var count = bytes[pos++];
|
||||||
|
for (var j = start; j <= start + count; j++)
|
||||||
|
encoding[j] = gid++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format & 0x80) {
|
||||||
|
readSupplement();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error('Unknow encoding format: ' + format + " in CFF");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
parseCharsets: function cff_parsecharsets(pos, length, strings) {
|
parseCharsets: function cff_parsecharsets(pos, length, strings) {
|
||||||
var bytes = this.bytes;
|
var bytes = this.bytes;
|
||||||
var format = bytes[pos++];
|
var format = bytes[pos++];
|
||||||
@ -2257,7 +2308,7 @@ var Type2CFF = (function() {
|
|||||||
id = (id << 8) | bytes[pos++];
|
id = (id << 8) | bytes[pos++];
|
||||||
charset.push(strings[id]);
|
charset.push(strings[id]);
|
||||||
}
|
}
|
||||||
return charset;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
while (charset.length <= length) {
|
while (charset.length <= length) {
|
||||||
var first = bytes[pos++];
|
var first = bytes[pos++];
|
||||||
@ -2266,7 +2317,7 @@ var Type2CFF = (function() {
|
|||||||
for (var i = 0; i <= numLeft; ++i)
|
for (var i = 0; i <= numLeft; ++i)
|
||||||
charset.push(strings[first++]);
|
charset.push(strings[first++]);
|
||||||
}
|
}
|
||||||
return charset;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
while (charset.length <= length) {
|
while (charset.length <= length) {
|
||||||
var first = bytes[pos++];
|
var first = bytes[pos++];
|
||||||
@ -2276,11 +2327,11 @@ var Type2CFF = (function() {
|
|||||||
for (var i = 0; i <= numLeft; ++i)
|
for (var i = 0; i <= numLeft; ++i)
|
||||||
charset.push(strings[first++]);
|
charset.push(strings[first++]);
|
||||||
}
|
}
|
||||||
return charset;
|
break;
|
||||||
default:
|
default:
|
||||||
error('Unknown charset format');
|
error('Unknown charset format');
|
||||||
}
|
}
|
||||||
|
return charset;
|
||||||
},
|
},
|
||||||
getPrivDict: function cff_getprivdict(baseDict, strings) {
|
getPrivDict: function cff_getprivdict(baseDict, strings) {
|
||||||
var dict = {};
|
var dict = {};
|
||||||
@ -2410,6 +2461,7 @@ var Type2CFF = (function() {
|
|||||||
} else {
|
} else {
|
||||||
error('Incorrect byte');
|
error('Incorrect byte');
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseFloatOperand() {
|
function parseFloatOperand() {
|
||||||
|
97
pdf.js
97
pdf.js
@ -2093,7 +2093,7 @@ var LZWStream = (function() {
|
|||||||
var c = this.str.getByte();
|
var c = this.str.getByte();
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
this.eof = true;
|
this.eof = true;
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
cachedData = (cachedData << 8) | c;
|
cachedData = (cachedData << 8) | c;
|
||||||
bitsCached += 8;
|
bitsCached += 8;
|
||||||
@ -4204,8 +4204,6 @@ var PartialEvaluator = (function() {
|
|||||||
|
|
||||||
var builtInEncoding = false;
|
var builtInEncoding = false;
|
||||||
var encodingMap = {};
|
var encodingMap = {};
|
||||||
var glyphMap = {};
|
|
||||||
var charset = [];
|
|
||||||
if (compositeFont) {
|
if (compositeFont) {
|
||||||
// Special CIDFont support
|
// Special CIDFont support
|
||||||
// XXX only CIDFontType2 supported for now
|
// XXX only CIDFontType2 supported for now
|
||||||
@ -4247,69 +4245,64 @@ var PartialEvaluator = (function() {
|
|||||||
if (fontDict.has('Encoding')) {
|
if (fontDict.has('Encoding')) {
|
||||||
var encoding = xref.fetchIfRef(fontDict.get('Encoding'));
|
var encoding = xref.fetchIfRef(fontDict.get('Encoding'));
|
||||||
if (IsDict(encoding)) {
|
if (IsDict(encoding)) {
|
||||||
// Build a map of between codes and glyphs
|
|
||||||
// Load the base encoding
|
|
||||||
var baseName = encoding.get('BaseEncoding');
|
var baseName = encoding.get('BaseEncoding');
|
||||||
if (baseName) {
|
if (baseName)
|
||||||
baseEncoding = Encodings[baseName.name].slice();
|
baseEncoding = Encodings[baseName.name].slice();
|
||||||
}
|
|
||||||
|
|
||||||
// Load the differences between the base and original
|
// Load the differences between the base and original
|
||||||
var differences = encoding.get('Differences');
|
var differences = encoding.get('Differences');
|
||||||
var index = 0;
|
var index = 0;
|
||||||
for (var j = 0; j < differences.length; j++) {
|
for (var j = 0; j < differences.length; j++) {
|
||||||
var data = differences[j];
|
var data = differences[j];
|
||||||
if (IsNum(data)) {
|
if (IsNum(data))
|
||||||
index = data;
|
index = data;
|
||||||
} else {
|
else
|
||||||
diffEncoding[index++] = data.name;
|
diffEncoding[index++] = data.name;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (IsName(encoding)) {
|
} else if (IsName(encoding)) {
|
||||||
baseEncoding = Encodings[encoding.name].slice();
|
baseEncoding = Encodings[encoding.name].slice();
|
||||||
|
} else {
|
||||||
|
error("Encoding is not a Name nor a Dict");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fontType = subType.name;
|
||||||
if (!baseEncoding) {
|
if (!baseEncoding) {
|
||||||
var type = subType.name;
|
switch (fontType) {
|
||||||
if (type == 'TrueType') {
|
case 'TrueType':
|
||||||
baseEncoding = Encodings.WinAnsiEncoding.slice();
|
baseEncoding = Encodings.WinAnsiEncoding.slice();
|
||||||
} else if (type == 'Type1') {
|
break;
|
||||||
baseEncoding = Encodings.StandardEncoding.slice();
|
case 'Type1':
|
||||||
if (!diffEncoding.length)
|
baseEncoding = Encodings.StandardEncoding.slice();
|
||||||
builtInEncoding = true;
|
break;
|
||||||
} else {
|
default:
|
||||||
error('Unknown type of font');
|
warn('Unknown type of font: ' + fontType);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// firstChar and width are required
|
||||||
|
// (except for 14 standard fonts)
|
||||||
|
var firstChar = xref.fetchIfRef(fontDict.get('FirstChar')) || 0;
|
||||||
|
var widths = xref.fetchIfRef(fontDict.get('Widths')) || [];
|
||||||
|
|
||||||
|
var lastChar = xref.fetchIfRef(fontDict.get('LastChar'));
|
||||||
|
if (!lastChar)
|
||||||
|
lastChar = diffEncoding.length || baseEncoding.length;
|
||||||
|
|
||||||
// merge in the differences
|
// merge in the differences
|
||||||
var length = baseEncoding.length > diffEncoding.length ?
|
var glyphsMap = {};
|
||||||
baseEncoding.length : diffEncoding.length;
|
for (var i = firstChar; i <= lastChar; i++) {
|
||||||
for (var i = 0, ii = length; i < ii; ++i) {
|
var glyph = diffEncoding[i] || baseEncoding[i];
|
||||||
var diffGlyph = diffEncoding[i];
|
if (glyph)
|
||||||
var baseGlyph = baseEncoding[i];
|
glyphsMap[glyph] = encodingMap[i] = GlyphsUnicode[glyph] || i;
|
||||||
if (diffGlyph) {
|
|
||||||
glyphMap[i] = diffGlyph;
|
|
||||||
encodingMap[i] = GlyphsUnicode[diffGlyph];
|
|
||||||
} else if (baseGlyph) {
|
|
||||||
glyphMap[i] = baseGlyph;
|
|
||||||
encodingMap[i] = GlyphsUnicode[baseGlyph];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fontDict.has('ToUnicode')) {
|
if (fontType == 'TrueType' && fontDict.has('ToUnicode') && differences) {
|
||||||
encodingMap['empty'] = true;
|
|
||||||
var glyphsMap = {};
|
|
||||||
for (var p in glyphMap)
|
|
||||||
glyphsMap[glyphMap[p]] = encodingMap[p];
|
|
||||||
|
|
||||||
var cmapObj = xref.fetchIfRef(fontDict.get('ToUnicode'));
|
var cmapObj = xref.fetchIfRef(fontDict.get('ToUnicode'));
|
||||||
if (IsName(cmapObj)) {
|
if (IsName(cmapObj)) {
|
||||||
error('ToUnicode file cmap translation not implemented');
|
error('ToUnicode file cmap translation not implemented');
|
||||||
} else if (IsStream(cmapObj)) {
|
} else if (IsStream(cmapObj)) {
|
||||||
var firstChar = xref.fetchIfRef(fontDict.get('FirstChar'));
|
|
||||||
|
|
||||||
var tokens = [];
|
var tokens = [];
|
||||||
var token = '';
|
var token = '';
|
||||||
var beginArrayToken = {};
|
var beginArrayToken = {};
|
||||||
@ -4390,21 +4383,13 @@ var PartialEvaluator = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// firstChar and width are required
|
|
||||||
// (except for 14 standard fonts)
|
|
||||||
var firstChar = xref.fetchIfRef(fontDict.get('FirstChar'));
|
|
||||||
var widths = xref.fetchIfRef(fontDict.get('Widths')) || [];
|
|
||||||
for (var j = 0; j < widths.length; j++) {
|
|
||||||
if (widths[j])
|
|
||||||
charset.push(glyphMap[j + firstChar]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
var baseFontName = fontDict.get('BaseFont');
|
var baseFontName = fontDict.get('BaseFont');
|
||||||
if (!IsName(baseFontName))
|
if (!IsName(baseFontName))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Using base font name as a font name.
|
// Using base font name as a font name.
|
||||||
baseFontName = baseFontName.name.replace(/[\+,\-]/g, '_');
|
baseFontName = baseFontName.name.replace(/[\+,\-]/g, '_');
|
||||||
if (/^Symbol(_?(Bold|Italic))*$/.test(baseFontName)) {
|
if (/^Symbol(_?(Bold|Italic))*$/.test(baseFontName)) {
|
||||||
@ -4426,7 +4411,6 @@ var PartialEvaluator = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var descriptor = xref.fetch(fd);
|
var descriptor = xref.fetch(fd);
|
||||||
|
|
||||||
var fontName = fontDict.get('Name');
|
var fontName = fontDict.get('Name');
|
||||||
if (!fontName)
|
if (!fontName)
|
||||||
fontName = xref.fetchIfRef(descriptor.get('FontName'));
|
fontName = xref.fetchIfRef(descriptor.get('FontName'));
|
||||||
@ -4444,14 +4428,6 @@ var PartialEvaluator = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor.has('CharSet')) {
|
|
||||||
// Get the font charset if any (meaningful only in Type 1)
|
|
||||||
charset = descriptor.get('CharSet');
|
|
||||||
assertWellFormed(IsString(charset), 'invalid charset');
|
|
||||||
charset = charset.split('/');
|
|
||||||
charset.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
var widths = fontDict.get('Widths');
|
var widths = fontDict.get('Widths');
|
||||||
if (widths) {
|
if (widths) {
|
||||||
var glyphWidths = {};
|
var glyphWidths = {};
|
||||||
@ -4465,9 +4441,8 @@ var PartialEvaluator = (function() {
|
|||||||
subtype: fileType,
|
subtype: fileType,
|
||||||
widths: glyphWidths,
|
widths: glyphWidths,
|
||||||
encoding: encodingMap,
|
encoding: encodingMap,
|
||||||
|
differences: diffEncoding,
|
||||||
glyphs: glyphsMap || GlyphsUnicode,
|
glyphs: glyphsMap || GlyphsUnicode,
|
||||||
builtInEncoding: builtInEncoding,
|
|
||||||
charset: charset,
|
|
||||||
firstChar: fontDict.get('FirstChar'),
|
firstChar: fontDict.get('FirstChar'),
|
||||||
lastChar: fontDict.get('LastChar'),
|
lastChar: fontDict.get('LastChar'),
|
||||||
bbox: descriptor.get('FontBBox'),
|
bbox: descriptor.get('FontBBox'),
|
||||||
@ -5236,7 +5211,7 @@ var Util = (function() {
|
|||||||
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
||||||
};
|
};
|
||||||
constructor.makeCssCmyk = function makecmyk(c, m, y, k) {
|
constructor.makeCssCmyk = function makecmyk(c, m, y, k) {
|
||||||
var c = (new DeviceCmykCS()).getRgb([c, m, y, k]);
|
c = (new DeviceCmykCS()).getRgb([c, m, y, k]);
|
||||||
var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0;
|
var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0;
|
||||||
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
|
||||||
};
|
};
|
||||||
@ -5363,6 +5338,7 @@ var ColorSpace = (function() {
|
|||||||
} else {
|
} else {
|
||||||
error('unrecognized color space object: "' + cs + '"');
|
error('unrecognized color space object: "' + cs + '"');
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
return constructor;
|
return constructor;
|
||||||
@ -5661,6 +5637,7 @@ var Pattern = (function() {
|
|||||||
default:
|
default:
|
||||||
error('Unknown type of pattern: ' + typeNum);
|
error('Unknown type of pattern: ' + typeNum);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor.parseShading = function pattern_shading(shading, matrix,
|
constructor.parseShading = function pattern_shading(shading, matrix,
|
||||||
|
@ -218,11 +218,10 @@ var PageView = function(container, content, id, width, height,
|
|||||||
|
|
||||||
function setupLinks(canvas, content, scale) {
|
function setupLinks(canvas, content, scale) {
|
||||||
function bindLink(link, dest) {
|
function bindLink(link, dest) {
|
||||||
if (dest) {
|
link.onclick = function() {
|
||||||
link.onclick = function() {
|
if (dest)
|
||||||
PDFView.navigateTo(dest);
|
PDFView.navigateTo(dest);
|
||||||
return false;
|
return false;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var links = content.getLinks();
|
var links = content.getLinks();
|
||||||
@ -233,7 +232,7 @@ var PageView = function(container, content, id, width, height,
|
|||||||
link.style.width = Math.ceil(links[i].width * scale) + 'px';
|
link.style.width = Math.ceil(links[i].width * scale) + 'px';
|
||||||
link.style.height = Math.ceil(links[i].height * scale) + 'px';
|
link.style.height = Math.ceil(links[i].height * scale) + 'px';
|
||||||
link.href = links[i].url || '';
|
link.href = links[i].url || '';
|
||||||
bindLink(link, links[i].dest);
|
bindLink(link, ('dest' in links[i]) ? links[i].dest : null);
|
||||||
div.appendChild(link);
|
div.appendChild(link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,16 +422,18 @@ window.addEventListener('transitionend', function(evt) {
|
|||||||
var pagesCount = PDFView.pages.length;
|
var pagesCount = PDFView.pages.length;
|
||||||
|
|
||||||
var container = document.getElementById('sidebarView');
|
var container = document.getElementById('sidebarView');
|
||||||
container._interval = window.setInterval(function() {
|
container._interval = window.setInterval(function interval() {
|
||||||
if (pageIndex >= pagesCount)
|
if (pageIndex >= pagesCount) {
|
||||||
return window.clearInterval(container._interval);
|
window.clearInterval(container._interval);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PDFView.thumbnails[pageIndex++].draw();
|
PDFView.thumbnails[pageIndex++].draw();
|
||||||
}, 500);
|
}, 500);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
|
||||||
window.addEventListener('scalechange', function(evt) {
|
window.addEventListener('scalechange', function scalechange(evt) {
|
||||||
var options = document.getElementById('scaleSelect').options;
|
var options = document.getElementById('scaleSelect').options;
|
||||||
for (var i = 0; i < options.length; i++) {
|
for (var i = 0; i < options.length; i++) {
|
||||||
var option = options[i];
|
var option = options[i];
|
||||||
@ -440,7 +441,7 @@ window.addEventListener('scalechange', function(evt) {
|
|||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
window.addEventListener('pagechange', function(evt) {
|
window.addEventListener('pagechange', function pagechange(evt) {
|
||||||
var page = evt.detail;
|
var page = evt.detail;
|
||||||
document.location.hash = page;
|
document.location.hash = page;
|
||||||
document.getElementById('pageNumber').value = page;
|
document.getElementById('pageNumber').value = page;
|
||||||
|
Loading…
Reference in New Issue
Block a user