baseEncoding = Encodings.WinAnsiEncoding.slice();
break;
case 'Type1':
+ case 'Type3':
baseEncoding = Encodings.StandardEncoding.slice();
break;
default:
composite = true;
}
- // Before PDF 1.5 if the font was one of the base 14 fonts, having a
- // FontDescriptor was not required.
- // This case is here for compatibility.
var descriptor = xref.fetchIfRef(dict.get('FontDescriptor'));
if (!descriptor) {
- var baseFontName = dict.get('BaseFont');
- if (!IsName(baseFontName))
- return null;
+ if (type.name == 'Type3') {
+ // FontDescriptor is only required for Type3 fonts when the document
+ // is a tagged pdf. Create a barbebones one to get by.
+ descriptor = new Dict();
+ descriptor.set('FontName', new Name(type.name));
+ } else {
+ // Before PDF 1.5 if the font was one of the base 14 fonts, having a
+ // FontDescriptor was not required.
+ // This case is here for compatibility.
+ var baseFontName = dict.get('BaseFont');
+ if (!IsName(baseFontName))
+ return null;
- // Using base font name as a font name.
- baseFontName = baseFontName.name.replace(/,/g, '_');
- var metricsAndMap = this.getBaseFontMetricsAndMap(baseFontName);
-
- var properties = {
- type: type.name,
- encoding: metricsAndMap.map,
- differences: [],
- widths: metricsAndMap.widths,
- defaultWidth: metricsAndMap.defaultWidth,
- firstChar: 0,
- lastChar: 256
- };
- this.extractEncoding(dict, xref, properties);
+ // Using base font name as a font name.
+ baseFontName = baseFontName.name.replace(/,/g, '_');
+ var metricsAndMap = this.getBaseFontMetricsAndMap(baseFontName);
+
+ var properties = {
+ type: type.name,
+ encoding: metricsAndMap.map,
+ differences: [],
+ widths: metricsAndMap.widths,
+ defaultWidth: metricsAndMap.defaultWidth,
+ firstChar: 0,
+ lastChar: 256
+ };
+ this.extractEncoding(dict, xref, properties);
+
+ return {
+ name: baseFontName,
+ dict: baseDict,
+ properties: properties
+ };
+ }
- return {
- name: baseFontName,
- dict: baseDict,
- properties: properties
- };
}
// According to the spec if 'FontDescriptor' is declared, 'FirstChar',
length2: length2,
composite: composite,
fixedPitch: false,
- textMatrix: IDENTITY_MATRIX,
+ fontMatrix: dict.get('FontMatrix') || IDENTITY_MATRIX,
firstChar: firstChar || 0,
lastChar: lastChar || 256,
bbox: descriptor.get('FontBBox'),
italicAngle: descriptor.get('ItalicAngle'),
differences: [],
widths: glyphWidths,
- encoding: encoding
+ encoding: encoding,
+ coded: false
};
properties.glyphs = this.extractEncoding(dict, 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;
+ for (var key in charProcs.map) {
+ var glyphStream = xref.fetchIfRef(charProcs.map[key]);
+ properties.glyphs[key].code = this.evaluate(glyphStream,
+ xref,
+ fontResources);
+ }
+ }
+
return {
name: fontName.name,
dict: baseDict,
var ctx = this.ctx;
var current = this.current;
var font = current.font;
-
- ctx.save();
- ctx.transform.apply(ctx, current.textMatrix);
- ctx.scale(1, -1);
- ctx.translate(current.x, -1 * current.y);
- ctx.transform.apply(ctx, font.textMatrix || IDENTITY_MATRIX);
-
var glyphs = font.charsToGlyphs(text);
var fontSize = current.fontSize;
var charSpacing = current.charSpacing;
var wordSpacing = current.wordSpacing;
var textHScale = current.textHScale;
- ctx.scale(1 / textHScale, 1);
-
- var width = 0;
var glyphsLength = glyphs.length;
- for (var i = 0; i < glyphsLength; ++i) {
- var glyph = glyphs[i];
- if (glyph === null) {
- // word break
- width += wordSpacing;
- continue;
+ if (font.coded) {
+ ctx.save();
+ ctx.transform.apply(ctx, current.textMatrix);
+ ctx.translate(current.x, current.y);
+
+ var fontMatrix = font.fontMatrix || IDENTITY_MATRIX;
+ ctx.scale(1 / textHScale, 1);
+ for (var i = 0; i < glyphsLength; ++i) {
+
+ var glyph = glyphs[i];
+ if (glyph === null) {
+ // word break
+ this.ctx.translate(wordSpacing, 0);
+ continue;
+ }
+
+ this.save();
+ ctx.scale(fontSize, fontSize);
+ ctx.transform.apply(ctx, fontMatrix);
+ this.execute(glyph.code, this.xref, font.resources);
+ this.restore();
+
+ var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
+ var width = transformed[0] * fontSize + charSpacing;
+
+ ctx.translate(width, 0);
+ current.x += width;
+
}
+ ctx.restore();
+ } else {
+ ctx.save();
+ ctx.transform.apply(ctx, current.textMatrix);
+ ctx.scale(1, -1);
+ ctx.translate(current.x, -1 * current.y);
+ ctx.transform.apply(ctx, font.fontMatrix || IDENTITY_MATRIX);
+
+ ctx.scale(1 / textHScale, 1);
+
+ var width = 0;
+ for (var i = 0; i < glyphsLength; ++i) {
+ var glyph = glyphs[i];
+ if (glyph === null) {
+ // word break
+ width += wordSpacing;
+ continue;
+ }
- var unicode = glyph.unicode;
- var char = (unicode >= 0x10000) ?
- String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
- 0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode);
+ var unicode = glyph.unicode;
+ var char = (unicode >= 0x10000) ?
+ String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
+ 0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode);
- ctx.fillText(char, width, 0);
- width += glyph.width * fontSize * 0.001 + charSpacing;
- }
- current.x += width;
+ ctx.fillText(char, width, 0);
+ width += glyph.width * fontSize * 0.001 + charSpacing;
+ }
+ current.x += width;
- this.ctx.restore();
+ ctx.restore();
+ }
},
showSpacedText: function canvasGraphicsShowSpacedText(arr) {
var ctx = this.ctx;
// Type3 fonts
setCharWidth: function canvasGraphicsSetCharWidth(xWidth, yWidth) {
- TODO('type 3 fonts ("d0" operator) xWidth: ' + xWidth + ' yWidth: ' +
- yWidth);
+ // We can safely ignore this since the width should be the same
+ // as the width in the Widths array.
},
setCharWidthAndBounds: function canvasGraphicsSetCharWidthAndBounds(xWidth,
yWidth,
lly,
urx,
ury) {
- TODO('type 3 fonts ("d1" operator) xWidth: ' + xWidth + ' yWidth: ' +
- yWidth + ' llx: ' + llx + ' lly: ' + lly + ' urx: ' + urx +
- ' ury ' + ury);
+ // TODO? According the spec we're also suppose to ignore any operators
+ // that set color or include images while processing this type3 font.
+ this.rectangle(llx, lly, urx - llx, ury - lly);
+ this.clip();
+ this.endPath();
},
// Color
applyStencilMask: function applyStencilMask(buffer, inverseDecode) {
var width = this.width, height = this.height;
var bitStrideLength = (width + 7) >> 3;
+ this.image.reset();
var imgArray = this.image.getBytes(bitStrideLength * height);
var imgArrayPos = 0;
var i, j, mask, buf;
// rows start at byte boundary;
var rowBytes = (width * numComps * bpc + 7) >> 3;
+ this.image.reset();
var imgArray = this.image.getBytes(height * rowBytes);
var comps = this.colorSpace.getRgbBuffer(
// rows start at byte boundary;
var rowBytes = (width * numComps * bpc + 7) >> 3;
+ this.image.reset();
var imgArray = this.image.getBytes(height * rowBytes);
var comps = this.getComponents(imgArray);