|
|
|
@ -459,41 +459,18 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -459,41 +459,18 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
}; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
extractEncoding: function partialEvaluatorExtractEncoding(dict, |
|
|
|
|
xref, |
|
|
|
|
properties) { |
|
|
|
|
var type = properties.type, encoding; |
|
|
|
|
if (properties.composite) { |
|
|
|
|
var defaultWidth = xref.fetchIfRef(dict.get('DW')) || 1000; |
|
|
|
|
properties.defaultWidth = defaultWidth; |
|
|
|
|
extractDataStructures: function |
|
|
|
|
partialEvaluatorExtractDataStructures(dict, baseDict, |
|
|
|
|
xref, properties) { |
|
|
|
|
// 9.10.2
|
|
|
|
|
var toUnicode = dict.get('ToUnicode') || |
|
|
|
|
baseDict.get('ToUnicode'); |
|
|
|
|
if (toUnicode) |
|
|
|
|
properties.toUnicode = this.readToUnicode(toUnicode, xref); |
|
|
|
|
|
|
|
|
|
var glyphsWidths = {}; |
|
|
|
|
var widths = xref.fetchIfRef(dict.get('W')); |
|
|
|
|
if (widths) { |
|
|
|
|
var start = 0; |
|
|
|
|
for (var i = 0, ii = widths.length; i < ii; i++) { |
|
|
|
|
var code = widths[i]; |
|
|
|
|
if (isArray(code)) { |
|
|
|
|
for (var j = 0, jj = code.length; j < jj; j++) |
|
|
|
|
glyphsWidths[start++] = code[j]; |
|
|
|
|
start = 0; |
|
|
|
|
} else if (start) { |
|
|
|
|
var width = widths[++i]; |
|
|
|
|
for (var j = start; j <= code; j++) |
|
|
|
|
glyphsWidths[j] = width; |
|
|
|
|
start = 0; |
|
|
|
|
} else { |
|
|
|
|
start = code; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
properties.widths = glyphsWidths; |
|
|
|
|
|
|
|
|
|
// Glyph ids are big-endian 2-byte values
|
|
|
|
|
encoding = properties.encoding; |
|
|
|
|
|
|
|
|
|
// CIDSystemInfo might help to match width and glyphs
|
|
|
|
|
var cidSystemInfo = dict.get('CIDSystemInfo'); |
|
|
|
|
if (properties.composite) { |
|
|
|
|
// CIDSystemInfo helps to match CID to glyphs
|
|
|
|
|
var cidSystemInfo = xref.fetchIfRef(dict.get('CIDSystemInfo')); |
|
|
|
|
if (isDict(cidSystemInfo)) { |
|
|
|
|
properties.cidSystemInfo = { |
|
|
|
|
registry: cidSystemInfo.get('Registry'), |
|
|
|
@ -502,44 +479,20 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -502,44 +479,20 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var cidToGidMap = dict.get('CIDToGIDMap'); |
|
|
|
|
if (!cidToGidMap || !isRef(cidToGidMap)) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Object.create(GlyphsUnicode); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Extract the encoding from the CIDToGIDMap
|
|
|
|
|
var glyphsStream = xref.fetchIfRef(cidToGidMap); |
|
|
|
|
var glyphsData = glyphsStream.getBytes(0); |
|
|
|
|
|
|
|
|
|
// Set encoding 0 to later verify the font has an encoding
|
|
|
|
|
encoding[0] = { unicode: 0, width: 0 }; |
|
|
|
|
for (var j = 0, jj = glyphsData.length; j < jj; j++) { |
|
|
|
|
var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; |
|
|
|
|
if (glyphID == 0) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
var code = j >> 1; |
|
|
|
|
var width = glyphsWidths[code]; |
|
|
|
|
encoding[code] = { |
|
|
|
|
unicode: glyphID, |
|
|
|
|
width: isNum(width) ? width : defaultWidth |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return Object.create(GlyphsUnicode); |
|
|
|
|
var cidToGidMap = xref.fetchIfRef(dict.get('CIDToGIDMap')); |
|
|
|
|
if (isStream(cidToGidMap)) |
|
|
|
|
properties.cidToGidMap = this.readCidToGidMap(cidToGidMap); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var differences = properties.differences; |
|
|
|
|
var map = properties.encoding; |
|
|
|
|
var baseEncoding = null; |
|
|
|
|
if (dict.has('Encoding')) { |
|
|
|
|
encoding = xref.fetchIfRef(dict.get('Encoding')); |
|
|
|
|
var differences = []; |
|
|
|
|
var baseEncoding = Encodings.StandardEncoding; |
|
|
|
|
var hasEncoding = dict.has('Encoding'); |
|
|
|
|
if (hasEncoding) { |
|
|
|
|
var encoding = xref.fetchIfRef(dict.get('Encoding')); |
|
|
|
|
if (isDict(encoding)) { |
|
|
|
|
var baseName = encoding.get('BaseEncoding'); |
|
|
|
|
if (baseName) |
|
|
|
|
baseEncoding = Encodings[baseName.name].slice(); |
|
|
|
|
baseEncoding = Encodings[baseName.name]; |
|
|
|
|
|
|
|
|
|
// Load the differences between the base and original
|
|
|
|
|
if (encoding.has('Differences')) { |
|
|
|
@ -554,67 +507,20 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -554,67 +507,20 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (isName(encoding)) { |
|
|
|
|
baseEncoding = Encodings[encoding.name].slice(); |
|
|
|
|
baseEncoding = Encodings[encoding.name]; |
|
|
|
|
} else { |
|
|
|
|
error('Encoding is not a Name nor a Dict'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
properties.differences = differences; |
|
|
|
|
properties.baseEncoding = baseEncoding; |
|
|
|
|
properties.hasEncoding = hasEncoding; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
if (!baseEncoding) { |
|
|
|
|
switch (type) { |
|
|
|
|
case 'TrueType': |
|
|
|
|
baseEncoding = Encodings.WinAnsiEncoding.slice(); |
|
|
|
|
break; |
|
|
|
|
case 'Type1': |
|
|
|
|
case 'Type3': |
|
|
|
|
baseEncoding = Encodings.StandardEncoding.slice(); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
warn('Unknown type of font: ' + type); |
|
|
|
|
baseEncoding = []; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// merge in the differences
|
|
|
|
|
var firstChar = properties.firstChar; |
|
|
|
|
var lastChar = properties.lastChar; |
|
|
|
|
var widths = properties.widths || []; |
|
|
|
|
var glyphs = {}; |
|
|
|
|
for (var i = firstChar; i <= lastChar; i++) { |
|
|
|
|
var glyph = differences[i]; |
|
|
|
|
var replaceGlyph = true; |
|
|
|
|
if (!glyph) { |
|
|
|
|
glyph = baseEncoding[i] || i; |
|
|
|
|
replaceGlyph = false; |
|
|
|
|
} |
|
|
|
|
var index = GlyphsUnicode[glyph] || i; |
|
|
|
|
var width = widths[i] || widths[glyph]; |
|
|
|
|
map[i] = { |
|
|
|
|
unicode: index, |
|
|
|
|
width: isNum(width) ? width : properties.defaultWidth |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if (replaceGlyph || !glyphs[glyph]) |
|
|
|
|
glyphs[glyph] = map[i]; |
|
|
|
|
if (replaceGlyph || !glyphs[index]) |
|
|
|
|
glyphs[index] = map[i]; |
|
|
|
|
|
|
|
|
|
// If there is no file, the character mapping can't be modified
|
|
|
|
|
// but this is unlikely that there is any standard encoding with
|
|
|
|
|
// chars below 0x1f, so that's fine.
|
|
|
|
|
if (!properties.file) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (index <= 0x1f || (index >= 127 && index <= 255)) |
|
|
|
|
map[i].unicode += kCmapGlyphOffset; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (type == 'TrueType' && dict.has('ToUnicode') && differences) { |
|
|
|
|
var cmapObj = dict.get('ToUnicode'); |
|
|
|
|
if (isRef(cmapObj)) { |
|
|
|
|
cmapObj = xref.fetch(cmapObj); |
|
|
|
|
} |
|
|
|
|
readToUnicode: |
|
|
|
|
function partialEvaluatorReadToUnicode(toUnicode, xref) { |
|
|
|
|
var cmapObj = xref.fetchIfRef(toUnicode); |
|
|
|
|
var charToUnicode = []; |
|
|
|
|
if (isName(cmapObj)) { |
|
|
|
|
error('ToUnicode file cmap translation not implemented'); |
|
|
|
|
} else if (isStream(cmapObj)) { |
|
|
|
@ -646,10 +552,8 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -646,10 +552,8 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
var startRange = tokens[j]; |
|
|
|
|
var endRange = tokens[j + 1]; |
|
|
|
|
var code = tokens[j + 2]; |
|
|
|
|
while (startRange < endRange) { |
|
|
|
|
var mapping = map[startRange] || {}; |
|
|
|
|
mapping.unicode = code++; |
|
|
|
|
map[startRange] = mapping; |
|
|
|
|
while (startRange <= endRange) { |
|
|
|
|
charToUnicode[startRange] = code++; |
|
|
|
|
++startRange; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -660,9 +564,7 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -660,9 +564,7 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
for (var j = 0, jj = tokens.length; j < jj; j += 2) { |
|
|
|
|
var index = tokens[j]; |
|
|
|
|
var code = tokens[j + 1]; |
|
|
|
|
var mapping = map[index] || {}; |
|
|
|
|
mapping.unicode = code; |
|
|
|
|
map[index] = mapping; |
|
|
|
|
charToUnicode[index] = code; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
@ -700,34 +602,90 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -700,34 +602,90 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return glyphs; |
|
|
|
|
return charToUnicode; |
|
|
|
|
}, |
|
|
|
|
readCidToGidMap: |
|
|
|
|
function partialEvaluatorReadCidToGidMap(cidToGidStream) { |
|
|
|
|
// Extract the encoding from the CIDToGIDMap
|
|
|
|
|
var glyphsData = cidToGidStream.getBytes(); |
|
|
|
|
|
|
|
|
|
getBaseFontMetricsAndMap: function getBaseFontMetricsAndMap(name) { |
|
|
|
|
var map = {}; |
|
|
|
|
if (/^Symbol(-?(Bold|Italic))*$/.test(name)) { |
|
|
|
|
// special case for symbols
|
|
|
|
|
var encoding = Encodings.symbolsEncoding.slice(); |
|
|
|
|
for (var i = 0, n = encoding.length, j; i < n; i++) { |
|
|
|
|
j = encoding[i]; |
|
|
|
|
if (!j) |
|
|
|
|
// Set encoding 0 to later verify the font has an encoding
|
|
|
|
|
var result = []; |
|
|
|
|
for (var j = 0, jj = glyphsData.length; j < jj; j++) { |
|
|
|
|
var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; |
|
|
|
|
if (glyphID == 0) |
|
|
|
|
continue; |
|
|
|
|
map[i] = GlyphsUnicode[j] || 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var code = j >> 1; |
|
|
|
|
result[code] = glyphID; |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
extractWidths: function partialEvaluatorWidths(dict, |
|
|
|
|
xref, |
|
|
|
|
descriptor, |
|
|
|
|
properties) { |
|
|
|
|
var glyphsWidths = []; |
|
|
|
|
var defaultWidth = 0; |
|
|
|
|
var widths = Metrics[stdFontMap[name] || name]; |
|
|
|
|
if (isNum(widths)) { |
|
|
|
|
defaultWidth = widths; |
|
|
|
|
widths = null; |
|
|
|
|
if (properties.composite) { |
|
|
|
|
defaultWidth = xref.fetchIfRef(dict.get('DW')) || 1000; |
|
|
|
|
|
|
|
|
|
var widths = xref.fetchIfRef(dict.get('W')); |
|
|
|
|
if (widths) { |
|
|
|
|
var start = 0, end = 0; |
|
|
|
|
for (var i = 0, ii = widths.length; i < ii; i++) { |
|
|
|
|
var code = widths[i]; |
|
|
|
|
if (isArray(code)) { |
|
|
|
|
for (var j = 0, jj = code.length; j < jj; j++) |
|
|
|
|
glyphsWidths[start++] = code[j]; |
|
|
|
|
start = 0; |
|
|
|
|
} else if (start) { |
|
|
|
|
var width = widths[++i]; |
|
|
|
|
for (var j = start; j <= code; j++) |
|
|
|
|
glyphsWidths[j] = width; |
|
|
|
|
start = 0; |
|
|
|
|
} else { |
|
|
|
|
start = code; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
var firstChar = properties.firstChar; |
|
|
|
|
var widths = xref.fetchIfRef(dict.get('Widths')); |
|
|
|
|
if (widths) { |
|
|
|
|
var j = firstChar; |
|
|
|
|
for (var i = 0, ii = widths.length; i < ii; i++) |
|
|
|
|
glyphsWidths[j++] = widths[i]; |
|
|
|
|
defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0; |
|
|
|
|
} else { |
|
|
|
|
// Trying get the BaseFont metrics (see comment above).
|
|
|
|
|
var baseFontName = dict.get('BaseFont'); |
|
|
|
|
if (isName(baseFontName)) { |
|
|
|
|
var metrics = this.getBaseFontMetrics(baseFontName.name); |
|
|
|
|
|
|
|
|
|
glyphsWidths = metrics.widths; |
|
|
|
|
defaultWidth = metrics.defaultWidth; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
properties.defaultWidth = defaultWidth; |
|
|
|
|
properties.widths = glyphsWidths; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
getBaseFontMetrics: function getBaseFontMetrics(name) { |
|
|
|
|
var defaultWidth = 0, widths = []; |
|
|
|
|
var glyphWidths = Metrics[stdFontMap[name] || name]; |
|
|
|
|
if (isNum(glyphWidths)) { |
|
|
|
|
defaultWidth = glyphWidths; |
|
|
|
|
} else { |
|
|
|
|
widths = glyphWidths; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
defaultWidth: defaultWidth, |
|
|
|
|
widths: widths || [], |
|
|
|
|
map: map |
|
|
|
|
widths: widths |
|
|
|
|
}; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
@ -756,6 +714,7 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -756,6 +714,7 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
assertWellFormed(isName(type), 'invalid font Subtype'); |
|
|
|
|
composite = true; |
|
|
|
|
} |
|
|
|
|
var maxCharIndex = composite ? 0xFFFF : 0xFF; |
|
|
|
|
|
|
|
|
|
var descriptor = xref.fetchIfRef(dict.get('FontDescriptor')); |
|
|
|
|
if (!descriptor) { |
|
|
|
@ -774,18 +733,16 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -774,18 +733,16 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
|
|
|
|
|
// Using base font name as a font name.
|
|
|
|
|
baseFontName = baseFontName.name.replace(/[,_]/g, '-'); |
|
|
|
|
var metricsAndMap = this.getBaseFontMetricsAndMap(baseFontName); |
|
|
|
|
var metrics = this.getBaseFontMetrics(baseFontName); |
|
|
|
|
|
|
|
|
|
var properties = { |
|
|
|
|
type: type.name, |
|
|
|
|
encoding: metricsAndMap.map, |
|
|
|
|
differences: [], |
|
|
|
|
widths: metricsAndMap.widths, |
|
|
|
|
defaultWidth: metricsAndMap.defaultWidth, |
|
|
|
|
widths: metrics.widths, |
|
|
|
|
defaultWidth: metrics.defaultWidth, |
|
|
|
|
firstChar: 0, |
|
|
|
|
lastChar: 256 |
|
|
|
|
lastChar: maxCharIndex |
|
|
|
|
}; |
|
|
|
|
this.extractEncoding(dict, xref, properties); |
|
|
|
|
this.extractDataStructures(dict, dict, xref, properties); |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
name: baseFontName, |
|
|
|
@ -802,27 +759,7 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -802,27 +759,7 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
// TODO Fill the width array depending on which of the base font this is
|
|
|
|
|
// a variant.
|
|
|
|
|
var firstChar = xref.fetchIfRef(dict.get('FirstChar')) || 0; |
|
|
|
|
var lastChar = xref.fetchIfRef(dict.get('LastChar')) || 256; |
|
|
|
|
var defaultWidth = 0; |
|
|
|
|
var glyphWidths = {}; |
|
|
|
|
var encoding = {}; |
|
|
|
|
var widths = xref.fetchIfRef(dict.get('Widths')); |
|
|
|
|
if (widths) { |
|
|
|
|
for (var i = 0, j = firstChar, ii = widths.length; i < ii; i++, j++) |
|
|
|
|
glyphWidths[j] = widths[i]; |
|
|
|
|
defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0; |
|
|
|
|
} else { |
|
|
|
|
// Trying get the BaseFont metrics (see comment above).
|
|
|
|
|
var baseFontName = dict.get('BaseFont'); |
|
|
|
|
if (isName(baseFontName)) { |
|
|
|
|
var metricsAndMap = this.getBaseFontMetricsAndMap(baseFontName.name); |
|
|
|
|
|
|
|
|
|
glyphWidths = metricsAndMap.widths; |
|
|
|
|
defaultWidth = metricsAndMap.defaultWidth; |
|
|
|
|
encoding = metricsAndMap.map; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var lastChar = xref.fetchIfRef(dict.get('LastChar')) || maxCharIndex; |
|
|
|
|
var fontName = xref.fetchIfRef(descriptor.get('FontName')); |
|
|
|
|
assertWellFormed(isName(fontName), 'invalid font name'); |
|
|
|
|
|
|
|
|
@ -854,34 +791,30 @@ var PartialEvaluator = (function partialEvaluator() {
@@ -854,34 +791,30 @@ var PartialEvaluator = (function partialEvaluator() {
|
|
|
|
|
fixedPitch: false, |
|
|
|
|
fontMatrix: dict.get('FontMatrix') || IDENTITY_MATRIX, |
|
|
|
|
firstChar: firstChar || 0, |
|
|
|
|
lastChar: lastChar || 256, |
|
|
|
|
lastChar: lastChar || maxCharIndex, |
|
|
|
|
bbox: descriptor.get('FontBBox'), |
|
|
|
|
ascent: descriptor.get('Ascent'), |
|
|
|
|
descent: descriptor.get('Descent'), |
|
|
|
|
xHeight: descriptor.get('XHeight'), |
|
|
|
|
capHeight: descriptor.get('CapHeight'), |
|
|
|
|
defaultWidth: defaultWidth, |
|
|
|
|
flags: descriptor.get('Flags'), |
|
|
|
|
italicAngle: descriptor.get('ItalicAngle'), |
|
|
|
|
differences: [], |
|
|
|
|
widths: glyphWidths, |
|
|
|
|
encoding: encoding, |
|
|
|
|
coded: false |
|
|
|
|
}; |
|
|
|
|
properties.glyphs = this.extractEncoding(dict, xref, properties); |
|
|
|
|
this.extractWidths(dict, xref, descriptor, properties); |
|
|
|
|
this.extractDataStructures(dict, baseDict, xref, properties); |
|
|
|
|
|
|
|
|
|
if (type.name === 'Type3') { |
|
|
|
|
properties.coded = true; |
|
|
|
|
var charProcs = xref.fetchIfRef(dict.get('CharProcs')); |
|
|
|
|
var fontResources = xref.fetchIfRef(dict.get('Resources')) || resources; |
|
|
|
|
properties.resources = fontResources; |
|
|
|
|
properties.charProcIRQueues = {}; |
|
|
|
|
for (var key in charProcs.map) { |
|
|
|
|
var glyphStream = xref.fetchIfRef(charProcs.map[key]); |
|
|
|
|
var queueObj = {}; |
|
|
|
|
properties.glyphs[key].IRQueue = this.getIRQueue(glyphStream, |
|
|
|
|
fontResources, |
|
|
|
|
queueObj, |
|
|
|
|
dependency); |
|
|
|
|
properties.charProcIRQueues[key] = |
|
|
|
|
this.getIRQueue(glyphStream, fontResources, queueObj, dependency); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|