#502 Adding basic Type3 font support.
This commit is contained in:
parent
65cad1caf8
commit
5f81017726
9
fonts.js
9
fonts.js
@ -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
171
pdf.js
@ -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);
|
||||
|
141
test/pdfs/simpletype3font.pdf
Normal file
141
test/pdfs/simpletype3font.pdf
Normal 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
|
@ -164,5 +164,11 @@
|
||||
"rounds": 1,
|
||||
"skipPages": [ 16 ],
|
||||
"type": "load"
|
||||
},
|
||||
{ "id": "simpletype3font",
|
||||
"file": "pdfs/simpletype3font.pdf",
|
||||
"link": false,
|
||||
"rounds": 1,
|
||||
"type": "load"
|
||||
}
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user