Merge remote-tracking branch 'upstream/master' into test
This commit is contained in:
commit
94a64eece9
1
Makefile
1
Makefile
@ -63,6 +63,7 @@ bundle: | $(BUILD_DIR)
|
||||
@cd src; \
|
||||
cat $(PDF_JS_FILES) > all_files.tmp; \
|
||||
sed '/PDFJSSCRIPT_INCLUDE_ALL/ r all_files.tmp' pdf.js > ../$(BUILD_TARGET); \
|
||||
sed -i '' "s/PDFJSSCRIPT_BUNDLE_VER/`git log --format="%H" -n 1`/" ../$(BUILD_TARGET); \
|
||||
rm -f *.tmp; \
|
||||
cd ..
|
||||
|
||||
|
18
README.md
18
README.md
@ -95,9 +95,17 @@ workings of PDF and pdf.js:
|
||||
## Contributing
|
||||
|
||||
pdf.js is a community-driven project, so contributors are always welcome.
|
||||
Simply fork our repo and contribute away. A great place to start is our
|
||||
[open issues](https://github.com/mozilla/pdf.js/issues). For better consistency and
|
||||
long-term stability, please do look around the code and try to follow our conventions.
|
||||
Simply fork our repo and contribute away. Good starting places for picking
|
||||
a bug are the top error messages and TODOs in our corpus report:
|
||||
|
||||
+ http://people.mozilla.com/~bdahl/corpusreport/test/ref/
|
||||
|
||||
and of course our open Github issues:
|
||||
|
||||
+ https://github.com/mozilla/pdf.js/issues
|
||||
|
||||
For better consistency and long-term stability, please do look around the
|
||||
code and try to follow our conventions.
|
||||
More information about the contributor process can be found on the
|
||||
[contributor wiki page](https://github.com/mozilla/pdf.js/wiki/Contributing).
|
||||
|
||||
@ -152,9 +160,9 @@ See the bot repo for details:
|
||||
|
||||
## Additional resources
|
||||
|
||||
Our demo site is here:
|
||||
Gallery of user projects and modifications:
|
||||
|
||||
+ http://mozilla.github.com/pdf.js/web/viewer.html
|
||||
+ https://github.com/mozilla/pdf.js/wiki/Gallery-of-user-projects-and-modifications
|
||||
|
||||
You can read more about pdf.js here:
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>6.0</em:minVersion>
|
||||
<em:maxVersion>10.0.*</em:maxVersion>
|
||||
<em:maxVersion>11.0.*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
|
@ -445,7 +445,7 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
this.save();
|
||||
ctx.scale(fontSize, fontSize);
|
||||
ctx.transform.apply(ctx, fontMatrix);
|
||||
this.executeIRQueue(glyph.IRQueue);
|
||||
this.executeIRQueue(glyph.codeIRQueue);
|
||||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
@ -546,7 +546,9 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
setStrokeColor: function canvasGraphicsSetStrokeColor(/*...*/) {
|
||||
var cs = this.current.strokeColorSpace;
|
||||
var color = cs.getRgb(arguments);
|
||||
this.setStrokeRGBColor.apply(this, color);
|
||||
var color = Util.makeCssRgb.apply(null, cs.getRgb(arguments));
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
getColorN_IR_Pattern: function canvasGraphicsGetColorN_IR_Pattern(IR, cs) {
|
||||
if (IR[0] == 'TilingPattern') {
|
||||
@ -581,8 +583,9 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
},
|
||||
setFillColor: function canvasGraphicsSetFillColor(/*...*/) {
|
||||
var cs = this.current.fillColorSpace;
|
||||
var color = cs.getRgb(arguments);
|
||||
this.setFillRGBColor.apply(this, color);
|
||||
var color = Util.makeCssRgb.apply(null, cs.getRgb(arguments));
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
setFillColorN_IR: function canvasGraphicsSetFillColorN(/*...*/) {
|
||||
var cs = this.current.fillColorSpace;
|
||||
@ -594,27 +597,49 @@ var CanvasGraphics = (function canvasGraphics() {
|
||||
}
|
||||
},
|
||||
setStrokeGray: function canvasGraphicsSetStrokeGray(gray) {
|
||||
this.setStrokeRGBColor(gray, gray, gray);
|
||||
if (!(this.current.strokeColorSpace instanceof DeviceGrayCS))
|
||||
this.current.strokeColorSpace = new DeviceGrayCS();
|
||||
|
||||
var color = Util.makeCssRgb(gray, gray, gray);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
setFillGray: function canvasGraphicsSetFillGray(gray) {
|
||||
this.setFillRGBColor(gray, gray, gray);
|
||||
if (!(this.current.fillColorSpace instanceof DeviceGrayCS))
|
||||
this.current.fillColorSpace = new DeviceGrayCS();
|
||||
|
||||
var color = Util.makeCssRgb(gray, gray, gray);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
setStrokeRGBColor: function canvasGraphicsSetStrokeRGBColor(r, g, b) {
|
||||
if (!(this.current.strokeColorSpace instanceof DeviceRgbCS))
|
||||
this.current.strokeColorSpace = new DeviceRgbCS();
|
||||
|
||||
var color = Util.makeCssRgb(r, g, b);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
setFillRGBColor: function canvasGraphicsSetFillRGBColor(r, g, b) {
|
||||
if (!(this.current.fillColorSpace instanceof DeviceRgbCS))
|
||||
this.current.fillColorSpace = new DeviceRgbCS();
|
||||
|
||||
var color = Util.makeCssRgb(r, g, b);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
},
|
||||
setStrokeCMYKColor: function canvasGraphicsSetStrokeCMYKColor(c, m, y, k) {
|
||||
if (!(this.current.strokeColorSpace instanceof DeviceCmykCS))
|
||||
this.current.strokeColorSpace = new DeviceCmykCS();
|
||||
|
||||
var color = Util.makeCssCmyk(c, m, y, k);
|
||||
this.ctx.strokeStyle = color;
|
||||
this.current.strokeColor = color;
|
||||
},
|
||||
setFillCMYKColor: function canvasGraphicsSetFillCMYKColor(c, m, y, k) {
|
||||
if (!(this.current.fillColorSpace instanceof DeviceCmykCS))
|
||||
this.current.fillColorSpace = new DeviceCmykCS();
|
||||
|
||||
var color = Util.makeCssCmyk(c, m, y, k);
|
||||
this.ctx.fillStyle = color;
|
||||
this.current.fillColor = color;
|
||||
|
489
src/evaluator.js
489
src/evaluator.js
@ -459,18 +459,183 @@ 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);
|
||||
|
||||
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'),
|
||||
ordering: cidSystemInfo.get('Ordering'),
|
||||
supplement: cidSystemInfo.get('Supplement')
|
||||
};
|
||||
}
|
||||
|
||||
var cidToGidMap = xref.fetchIfRef(dict.get('CIDToGIDMap'));
|
||||
if (isStream(cidToGidMap))
|
||||
properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
// Load the differences between the base and original
|
||||
if (encoding.has('Differences')) {
|
||||
var diffEncoding = encoding.get('Differences');
|
||||
var index = 0;
|
||||
for (var j = 0, jj = diffEncoding.length; j < jj; j++) {
|
||||
var data = diffEncoding[j];
|
||||
if (isNum(data))
|
||||
index = data;
|
||||
else
|
||||
differences[index++] = data.name;
|
||||
}
|
||||
}
|
||||
} else if (isName(encoding)) {
|
||||
baseEncoding = Encodings[encoding.name];
|
||||
} else {
|
||||
error('Encoding is not a Name nor a Dict');
|
||||
}
|
||||
}
|
||||
properties.differences = differences;
|
||||
properties.baseEncoding = baseEncoding;
|
||||
properties.hasEncoding = hasEncoding;
|
||||
},
|
||||
|
||||
readToUnicode:
|
||||
function partialEvaluatorReadToUnicode(toUnicode, xref) {
|
||||
var cmapObj = xref.fetchIfRef(toUnicode);
|
||||
var charToUnicode = [];
|
||||
if (isName(cmapObj)) {
|
||||
var isIdentityMap = cmapObj.name.substr(0, 9) == 'Identity-';
|
||||
if (!isIdentityMap)
|
||||
error('ToUnicode file cmap translation not implemented');
|
||||
} else if (isStream(cmapObj)) {
|
||||
var tokens = [];
|
||||
var token = '';
|
||||
var beginArrayToken = {};
|
||||
|
||||
var cmap = cmapObj.getBytes(cmapObj.length);
|
||||
for (var i = 0, ii = cmap.length; i < ii; i++) {
|
||||
var byte = cmap[i];
|
||||
if (byte == 0x20 || byte == 0x0D || byte == 0x0A ||
|
||||
byte == 0x3C || byte == 0x5B || byte == 0x5D) {
|
||||
switch (token) {
|
||||
case 'usecmap':
|
||||
error('usecmap is not implemented');
|
||||
break;
|
||||
|
||||
case 'beginbfchar':
|
||||
case 'beginbfrange':
|
||||
case 'begincidchar':
|
||||
case 'begincidrange':
|
||||
token = '';
|
||||
tokens = [];
|
||||
break;
|
||||
|
||||
case 'endcidrange':
|
||||
case 'endbfrange':
|
||||
for (var j = 0, jj = tokens.length; j < jj; j += 3) {
|
||||
var startRange = tokens[j];
|
||||
var endRange = tokens[j + 1];
|
||||
var code = tokens[j + 2];
|
||||
while (startRange <= endRange) {
|
||||
charToUnicode[startRange] = code++;
|
||||
++startRange;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'endcidchar':
|
||||
case 'endbfchar':
|
||||
for (var j = 0, jj = tokens.length; j < jj; j += 2) {
|
||||
var index = tokens[j];
|
||||
var code = tokens[j + 1];
|
||||
charToUnicode[index] = code;
|
||||
}
|
||||
break;
|
||||
|
||||
case '':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (token[0] >= '0' && token[0] <= '9')
|
||||
token = parseInt(token, 10); // a number
|
||||
tokens.push(token);
|
||||
token = '';
|
||||
}
|
||||
switch (byte) {
|
||||
case 0x5B:
|
||||
// begin list parsing
|
||||
tokens.push(beginArrayToken);
|
||||
break;
|
||||
case 0x5D:
|
||||
// collect array items
|
||||
var items = [], item;
|
||||
while (tokens.length &&
|
||||
(item = tokens.pop()) != beginArrayToken)
|
||||
items.unshift(item);
|
||||
tokens.push(items);
|
||||
break;
|
||||
}
|
||||
} else if (byte == 0x3E) {
|
||||
if (token.length) {
|
||||
// parsing hex number
|
||||
tokens.push(parseInt(token, 16));
|
||||
token = '';
|
||||
}
|
||||
} else {
|
||||
token += String.fromCharCode(byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
return charToUnicode;
|
||||
},
|
||||
readCidToGidMap:
|
||||
function partialEvaluatorReadCidToGidMap(cidToGidStream) {
|
||||
// Extract the encoding from the CIDToGIDMap
|
||||
var glyphsData = cidToGidStream.getBytes();
|
||||
|
||||
// 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;
|
||||
|
||||
var code = j >> 1;
|
||||
result[code] = glyphID;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
extractWidths: function partialEvaluatorWidths(dict,
|
||||
xref,
|
||||
descriptor,
|
||||
properties) {
|
||||
var glyphsWidths = [];
|
||||
var defaultWidth = 0;
|
||||
if (properties.composite) {
|
||||
defaultWidth = xref.fetchIfRef(dict.get('DW')) || 1000;
|
||||
|
||||
var glyphsWidths = {};
|
||||
var widths = xref.fetchIfRef(dict.get('W'));
|
||||
if (widths) {
|
||||
var start = 0;
|
||||
var start = 0, end = 0;
|
||||
for (var i = 0, ii = widths.length; i < ii; i++) {
|
||||
var code = widths[i];
|
||||
if (isArray(code)) {
|
||||
@ -487,247 +652,42 @@ var PartialEvaluator = (function partialEvaluator() {
|
||||
}
|
||||
}
|
||||
}
|
||||
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 (isDict(cidSystemInfo)) {
|
||||
properties.cidSystemInfo = {
|
||||
registry: cidSystemInfo.get('Registry'),
|
||||
ordering: cidSystemInfo.get('Ordering'),
|
||||
supplement: cidSystemInfo.get('Supplement')
|
||||
};
|
||||
}
|
||||
|
||||
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 differences = properties.differences;
|
||||
var map = properties.encoding;
|
||||
var baseEncoding = null;
|
||||
if (dict.has('Encoding')) {
|
||||
encoding = xref.fetchIfRef(dict.get('Encoding'));
|
||||
if (isDict(encoding)) {
|
||||
var baseName = encoding.get('BaseEncoding');
|
||||
if (baseName)
|
||||
baseEncoding = Encodings[baseName.name].slice();
|
||||
|
||||
// Load the differences between the base and original
|
||||
if (encoding.has('Differences')) {
|
||||
var diffEncoding = encoding.get('Differences');
|
||||
var index = 0;
|
||||
for (var j = 0, jj = diffEncoding.length; j < jj; j++) {
|
||||
var data = diffEncoding[j];
|
||||
if (isNum(data))
|
||||
index = data;
|
||||
else
|
||||
differences[index++] = data.name;
|
||||
}
|
||||
}
|
||||
} else if (isName(encoding)) {
|
||||
baseEncoding = Encodings[encoding.name].slice();
|
||||
} 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 {
|
||||
error('Encoding is not a Name nor a Dict');
|
||||
}
|
||||
}
|
||||
// Trying get the BaseFont metrics (see comment above).
|
||||
var baseFontName = dict.get('BaseFont');
|
||||
if (isName(baseFontName)) {
|
||||
var metrics = this.getBaseFontMetrics(baseFontName.name);
|
||||
|
||||
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);
|
||||
}
|
||||
if (isName(cmapObj)) {
|
||||
error('ToUnicode file cmap translation not implemented');
|
||||
} else if (isStream(cmapObj)) {
|
||||
var tokens = [];
|
||||
var token = '';
|
||||
var beginArrayToken = {};
|
||||
|
||||
var cmap = cmapObj.getBytes(cmapObj.length);
|
||||
for (var i = 0, ii = cmap.length; i < ii; i++) {
|
||||
var byte = cmap[i];
|
||||
if (byte == 0x20 || byte == 0x0D || byte == 0x0A ||
|
||||
byte == 0x3C || byte == 0x5B || byte == 0x5D) {
|
||||
switch (token) {
|
||||
case 'usecmap':
|
||||
error('usecmap is not implemented');
|
||||
break;
|
||||
|
||||
case 'beginbfchar':
|
||||
case 'beginbfrange':
|
||||
case 'begincidchar':
|
||||
case 'begincidrange':
|
||||
token = '';
|
||||
tokens = [];
|
||||
break;
|
||||
|
||||
case 'endcidrange':
|
||||
case 'endbfrange':
|
||||
for (var j = 0, jj = tokens.length; j < jj; j += 3) {
|
||||
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;
|
||||
++startRange;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'endcidchar':
|
||||
case 'endbfchar':
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case '':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (token[0] >= '0' && token[0] <= '9')
|
||||
token = parseInt(token, 10); // a number
|
||||
tokens.push(token);
|
||||
token = '';
|
||||
}
|
||||
switch (byte) {
|
||||
case 0x5B:
|
||||
// begin list parsing
|
||||
tokens.push(beginArrayToken);
|
||||
break;
|
||||
case 0x5D:
|
||||
// collect array items
|
||||
var items = [], item;
|
||||
while (tokens.length &&
|
||||
(item = tokens.pop()) != beginArrayToken)
|
||||
items.unshift(item);
|
||||
tokens.push(items);
|
||||
break;
|
||||
}
|
||||
} else if (byte == 0x3E) {
|
||||
if (token.length) {
|
||||
// parsing hex number
|
||||
tokens.push(parseInt(token, 16));
|
||||
token = '';
|
||||
}
|
||||
} else {
|
||||
token += String.fromCharCode(byte);
|
||||
}
|
||||
glyphsWidths = metrics.widths;
|
||||
defaultWidth = metrics.defaultWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
return glyphs;
|
||||
|
||||
properties.defaultWidth = defaultWidth;
|
||||
properties.widths = glyphsWidths;
|
||||
},
|
||||
|
||||
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)
|
||||
continue;
|
||||
map[i] = GlyphsUnicode[j] || 0;
|
||||
}
|
||||
}
|
||||
|
||||
var defaultWidth = 0;
|
||||
var widths = Metrics[stdFontMap[name] || name];
|
||||
if (isNum(widths)) {
|
||||
defaultWidth = widths;
|
||||
widths = null;
|
||||
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 +716,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 +735,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 +761,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 +793,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
781
src/fonts.js
781
src/fonts.js
File diff suppressed because it is too large
Load Diff
@ -7,8 +7,9 @@ var PDFJS = {};
|
||||
// Use strict in our context only - users might not want it
|
||||
'use strict';
|
||||
|
||||
PDFJS.build = 'PDFJSSCRIPT_BUNDLE_VER';
|
||||
|
||||
// Files are inserted below - see Makefile
|
||||
/* PDFJSSCRIPT_INCLUDE_ALL */
|
||||
|
||||
}).call((typeof window === 'undefined') ? this : window);
|
||||
|
||||
|
@ -56,23 +56,29 @@ function load() {
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
var styleSheet = document.styleSheets[0];
|
||||
if (styleSheet) {
|
||||
// Clear out all the stylesheets since a new one is created for each font.
|
||||
while (document.styleSheets.length > 0) {
|
||||
var styleSheet = document.styleSheets[0];
|
||||
while (styleSheet.cssRules.length > 0)
|
||||
styleSheet.deleteRule(0);
|
||||
var ownerNode = styleSheet.ownerNode;
|
||||
ownerNode.parentNode.removeChild(ownerNode);
|
||||
}
|
||||
var guard = document.getElementById('content-end');
|
||||
var body = document.body;
|
||||
while (body.lastChild !== guard)
|
||||
body.removeChild(body.lastChild);
|
||||
|
||||
// Wipe out the link to the pdfdoc so it can be GC'ed.
|
||||
for (var i = 0; i < manifest.length; i++) {
|
||||
if (manifest[i].pdfDoc) {
|
||||
manifest[i].pdfDoc.destroy();
|
||||
delete manifest[i].pdfDoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nextTask() {
|
||||
// If there is a pdfDoc on the last task executed, destroy it to free memory.
|
||||
if (task && task.pdfDoc) {
|
||||
task.pdfDoc.destroy();
|
||||
delete task.pdfDoc;
|
||||
}
|
||||
cleanup();
|
||||
|
||||
if (currentTaskIdx == manifest.length) {
|
||||
|
@ -323,18 +323,18 @@ def verifyPDFs(manifestList):
|
||||
if os.access(f, os.R_OK):
|
||||
fileMd5 = hashlib.md5(open(f, 'rb').read()).hexdigest()
|
||||
if 'md5' not in item:
|
||||
print 'ERROR: Missing md5 for file "' + f + '".',
|
||||
print 'WARNING: Missing md5 for file "' + f + '".',
|
||||
print 'Hash for current file is "' + fileMd5 + '"'
|
||||
error = True
|
||||
continue
|
||||
md5 = item['md5']
|
||||
if fileMd5 != md5:
|
||||
print 'ERROR: MD5 of file "' + f + '" does not match file.',
|
||||
print 'WARNING: MD5 of file "' + f + '" does not match file.',
|
||||
print 'Expected "' + md5 + '" computed "' + fileMd5 + '"'
|
||||
error = True
|
||||
continue
|
||||
else:
|
||||
print 'ERROR: Unable to open file for reading "' + f + '".'
|
||||
print 'WARNING: Unable to open file for reading "' + f + '".'
|
||||
error = True
|
||||
return not error
|
||||
|
||||
@ -365,7 +365,8 @@ def setUp(options):
|
||||
downloadLinkedPDFs(manifestList)
|
||||
|
||||
if not verifyPDFs(manifestList):
|
||||
raise Exception('ERROR: failed to verify pdfs.')
|
||||
print 'Unable to verify the checksum for the files that are used for testing.'
|
||||
print 'Please re-download the files, or adjust the MD5 checksum in the manifest for the files listed above.\n'
|
||||
|
||||
for b in testBrowsers:
|
||||
State.taskResults[b.name] = { }
|
||||
|
@ -19,7 +19,7 @@
|
||||
},
|
||||
{ "id": "intelisa-load",
|
||||
"file": "pdfs/intelisa.pdf",
|
||||
"md5": "f3ed5487d1afa34d8b77c0c734a95c79",
|
||||
"md5": "f5712097d29287a97f1278839814f682",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
@ -194,7 +194,7 @@
|
||||
},
|
||||
{ "id": "f1040",
|
||||
"file": "pdfs/f1040.pdf",
|
||||
"md5": "7323b50c6d28d959b8b4b92c469b2469",
|
||||
"md5": "b59272ce19b4a0c5808c8861441b0741",
|
||||
"link": true,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
|
Loading…
Reference in New Issue
Block a user