#502 Adding basic Type3 font support.

This commit is contained in:
= 2011-10-03 16:36:01 -07:00
parent 65cad1caf8
commit 5f81017726
4 changed files with 269 additions and 58 deletions

View File

@ -414,6 +414,8 @@ var Font = (function Font() {
var constructor = function font_constructor(name, file, properties) {
this.name = name;
this.encoding = properties.encoding;
this.coded = properties.coded;
this.resources = properties.resources;
this.sizes = [];
var names = name.split('+');
@ -428,6 +430,9 @@ var Font = (function Font() {
this.loading = false;
return;
}
this.fontMatrix = properties.fontMatrix;
if (properties.type == 'Type3')
return;
if (!file) {
// The file data is not specified. Trying to fix the font name
@ -478,7 +483,7 @@ var Font = (function Font() {
this.data = data;
this.type = type;
this.textMatrix = properties.textMatrix;
this.fontMatrix = properties.fontMatrix;
this.defaultWidth = properties.defaultWidth;
this.loadedName = getUniqueName();
this.composite = properties.composite;
@ -1929,7 +1934,7 @@ var Type1Parser = function type1Parser() {
// Make the angle into the right direction
matrix[2] *= -1;
properties.textMatrix = matrix;
properties.fontMatrix = matrix;
break;
case '/Encoding':
var size = parseInt(getToken(), 10);

171
pdf.js
View File

@ -4498,6 +4498,7 @@ var PartialEvaluator = (function partialEvaluator() {
baseEncoding = Encodings.WinAnsiEncoding.slice();
break;
case 'Type1':
case 'Type3':
baseEncoding = Encodings.StandardEncoding.slice();
break;
default:
@ -4684,35 +4685,43 @@ var PartialEvaluator = (function partialEvaluator() {
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);
// 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);
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',
@ -4771,7 +4780,7 @@ var PartialEvaluator = (function partialEvaluator() {
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'),
@ -4784,10 +4793,24 @@ var PartialEvaluator = (function partialEvaluator() {
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,
@ -5223,41 +5246,72 @@ var CanvasGraphics = (function canvasGraphics() {
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);
var unicode = glyph.unicode;
var char = (unicode >= 0x10000) ?
String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode);
ctx.scale(1 / textHScale, 1);
ctx.fillText(char, width, 0);
width += glyph.width * fontSize * 0.001 + charSpacing;
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);
ctx.fillText(char, width, 0);
width += glyph.width * fontSize * 0.001 + charSpacing;
}
current.x += width;
ctx.restore();
}
current.x += width;
this.ctx.restore();
},
showSpacedText: function canvasGraphicsShowSpacedText(arr) {
var ctx = this.ctx;
@ -5295,8 +5349,8 @@ var CanvasGraphics = (function canvasGraphics() {
// 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,
@ -5304,9 +5358,11 @@ var CanvasGraphics = (function canvasGraphics() {
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
@ -6413,6 +6469,7 @@ var PDFImage = (function pdfImage() {
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;
@ -6441,6 +6498,7 @@ var PDFImage = (function pdfImage() {
// 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(
@ -6468,6 +6526,7 @@ var PDFImage = (function pdfImage() {
// 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);

View File

@ -0,0 +1,141 @@
%PDF-1.4
%öäüß
1 0 obj
<<
/Type /Catalog
/Version /1.4
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/Kids [3 0 R]
/Count 1
>>
endobj
3 0 obj
<<
/Type /Page
/MediaBox [0 0 612 792]
/Parent 2 0 R
/Resources 4 0 R
/Contents 5 0 R
>>
endobj
4 0 obj
<<
/Font 6 0 R
/XObject <<
>>
>>
endobj
5 0 obj
<<
/Length 7 0 R
>>
stream
/F0 12 Tf
BT
100 700 Td
(ababab) Tj
ET
endstream
endobj
6 0 obj
<<
/F0 8 0 R
>>
endobj
7 0 obj
39
endobj
8 0 obj
<<
/Type /Font
/Subtype /Type3
/FontBBox [0 0 750 750]
/FontMatrix [0.001 0 0 0.001 0 0]
/CharProcs 9 0 R
/Encoding 10 0 R
/FirstChar 97
/LastChar 98
/Widths [1000 1000]
/FontDescriptor 11 0 R
>>
endobj
9 0 obj
<<
/square 12 0 R
/triangle 13 0 R
>>
endobj
10 0 obj
<<
/Type /Encoding
/Differences [97 /square /triangle]
>>
endobj
11 0 obj
<<
/Type /FontDescriptor
/FontName /SandT
/Flags 262178
/Ascent 0
/CapHeight 0
/Descent 0
/ItalicAngle 0
/StemV 0
/FontBBox [0 0 750 750]
>>
endobj
12 0 obj
<<
/Length 14 0 R
>>
stream
1000 0 0 0 750 750 d1 0 0 750 750 re f
endstream
endobj
13 0 obj
<<
/Length 15 0 R
>>
stream
1000 0 0 0 750 750 d1 0 0 m 375 750 l 750 0 l f
endstream
endobj
14 0 obj
38
endobj
15 0 obj
47
endobj
xref
0 16
0000000000 65535 f
0000000015 00000 n
0000000078 00000 n
0000000135 00000 n
0000000239 00000 n
0000000287 00000 n
0000000381 00000 n
0000000412 00000 n
0000000430 00000 n
0000000641 00000 n
0000000694 00000 n
0000000768 00000 n
0000000925 00000 n
0000001020 00000 n
0000001124 00000 n
0000001143 00000 n
trailer
<<
/Root 1 0 R
/ID [<DD02410A8B7AD4A0EE0D50E4180FABAC> <DD02410A8B7AD4A0EE0D50E4180FABAC>]
/Size 16
>>
startxref
1162
%%EOF

View File

@ -164,5 +164,11 @@
"rounds": 1,
"skipPages": [ 16 ],
"type": "load"
},
{ "id": "simpletype3font",
"file": "pdfs/simpletype3font.pdf",
"link": false,
"rounds": 1,
"type": "load"
}
]