#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) {
|
var constructor = function font_constructor(name, file, properties) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.encoding = properties.encoding;
|
this.encoding = properties.encoding;
|
||||||
|
this.coded = properties.coded;
|
||||||
|
this.resources = properties.resources;
|
||||||
this.sizes = [];
|
this.sizes = [];
|
||||||
|
|
||||||
var names = name.split('+');
|
var names = name.split('+');
|
||||||
@ -428,6 +430,9 @@ var Font = (function Font() {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.fontMatrix = properties.fontMatrix;
|
||||||
|
if (properties.type == 'Type3')
|
||||||
|
return;
|
||||||
|
|
||||||
if (!file) {
|
if (!file) {
|
||||||
// The file data is not specified. Trying to fix the font name
|
// The file data is not specified. Trying to fix the font name
|
||||||
@ -478,7 +483,7 @@ var Font = (function Font() {
|
|||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.textMatrix = properties.textMatrix;
|
this.fontMatrix = properties.fontMatrix;
|
||||||
this.defaultWidth = properties.defaultWidth;
|
this.defaultWidth = properties.defaultWidth;
|
||||||
this.loadedName = getUniqueName();
|
this.loadedName = getUniqueName();
|
||||||
this.composite = properties.composite;
|
this.composite = properties.composite;
|
||||||
@ -1929,7 +1934,7 @@ var Type1Parser = function type1Parser() {
|
|||||||
// Make the angle into the right direction
|
// Make the angle into the right direction
|
||||||
matrix[2] *= -1;
|
matrix[2] *= -1;
|
||||||
|
|
||||||
properties.textMatrix = matrix;
|
properties.fontMatrix = matrix;
|
||||||
break;
|
break;
|
||||||
case '/Encoding':
|
case '/Encoding':
|
||||||
var size = parseInt(getToken(), 10);
|
var size = parseInt(getToken(), 10);
|
||||||
|
171
pdf.js
171
pdf.js
@ -4498,6 +4498,7 @@ var PartialEvaluator = (function partialEvaluator() {
|
|||||||
baseEncoding = Encodings.WinAnsiEncoding.slice();
|
baseEncoding = Encodings.WinAnsiEncoding.slice();
|
||||||
break;
|
break;
|
||||||
case 'Type1':
|
case 'Type1':
|
||||||
|
case 'Type3':
|
||||||
baseEncoding = Encodings.StandardEncoding.slice();
|
baseEncoding = Encodings.StandardEncoding.slice();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -4684,35 +4685,43 @@ var PartialEvaluator = (function partialEvaluator() {
|
|||||||
composite = true;
|
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'));
|
var descriptor = xref.fetchIfRef(dict.get('FontDescriptor'));
|
||||||
if (!descriptor) {
|
if (!descriptor) {
|
||||||
var baseFontName = dict.get('BaseFont');
|
if (type.name == 'Type3') {
|
||||||
if (!IsName(baseFontName))
|
// FontDescriptor is only required for Type3 fonts when the document
|
||||||
return null;
|
// 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.
|
// Using base font name as a font name.
|
||||||
baseFontName = baseFontName.name.replace(/,/g, '_');
|
baseFontName = baseFontName.name.replace(/,/g, '_');
|
||||||
var metricsAndMap = this.getBaseFontMetricsAndMap(baseFontName);
|
var metricsAndMap = this.getBaseFontMetricsAndMap(baseFontName);
|
||||||
|
|
||||||
var properties = {
|
var properties = {
|
||||||
type: type.name,
|
type: type.name,
|
||||||
encoding: metricsAndMap.map,
|
encoding: metricsAndMap.map,
|
||||||
differences: [],
|
differences: [],
|
||||||
widths: metricsAndMap.widths,
|
widths: metricsAndMap.widths,
|
||||||
defaultWidth: metricsAndMap.defaultWidth,
|
defaultWidth: metricsAndMap.defaultWidth,
|
||||||
firstChar: 0,
|
firstChar: 0,
|
||||||
lastChar: 256
|
lastChar: 256
|
||||||
};
|
};
|
||||||
this.extractEncoding(dict, xref, properties);
|
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',
|
// According to the spec if 'FontDescriptor' is declared, 'FirstChar',
|
||||||
@ -4771,7 +4780,7 @@ var PartialEvaluator = (function partialEvaluator() {
|
|||||||
length2: length2,
|
length2: length2,
|
||||||
composite: composite,
|
composite: composite,
|
||||||
fixedPitch: false,
|
fixedPitch: false,
|
||||||
textMatrix: IDENTITY_MATRIX,
|
fontMatrix: dict.get('FontMatrix') || IDENTITY_MATRIX,
|
||||||
firstChar: firstChar || 0,
|
firstChar: firstChar || 0,
|
||||||
lastChar: lastChar || 256,
|
lastChar: lastChar || 256,
|
||||||
bbox: descriptor.get('FontBBox'),
|
bbox: descriptor.get('FontBBox'),
|
||||||
@ -4784,10 +4793,24 @@ var PartialEvaluator = (function partialEvaluator() {
|
|||||||
italicAngle: descriptor.get('ItalicAngle'),
|
italicAngle: descriptor.get('ItalicAngle'),
|
||||||
differences: [],
|
differences: [],
|
||||||
widths: glyphWidths,
|
widths: glyphWidths,
|
||||||
encoding: encoding
|
encoding: encoding,
|
||||||
|
coded: false
|
||||||
};
|
};
|
||||||
properties.glyphs = this.extractEncoding(dict, xref, properties);
|
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 {
|
return {
|
||||||
name: fontName.name,
|
name: fontName.name,
|
||||||
dict: baseDict,
|
dict: baseDict,
|
||||||
@ -5223,41 +5246,72 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
var ctx = this.ctx;
|
var ctx = this.ctx;
|
||||||
var current = this.current;
|
var current = this.current;
|
||||||
var font = current.font;
|
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 glyphs = font.charsToGlyphs(text);
|
||||||
var fontSize = current.fontSize;
|
var fontSize = current.fontSize;
|
||||||
var charSpacing = current.charSpacing;
|
var charSpacing = current.charSpacing;
|
||||||
var wordSpacing = current.wordSpacing;
|
var wordSpacing = current.wordSpacing;
|
||||||
var textHScale = current.textHScale;
|
var textHScale = current.textHScale;
|
||||||
ctx.scale(1 / textHScale, 1);
|
|
||||||
|
|
||||||
var width = 0;
|
|
||||||
var glyphsLength = glyphs.length;
|
var glyphsLength = glyphs.length;
|
||||||
for (var i = 0; i < glyphsLength; ++i) {
|
if (font.coded) {
|
||||||
var glyph = glyphs[i];
|
ctx.save();
|
||||||
if (glyph === null) {
|
ctx.transform.apply(ctx, current.textMatrix);
|
||||||
// word break
|
ctx.translate(current.x, current.y);
|
||||||
width += wordSpacing;
|
|
||||||
continue;
|
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;
|
ctx.scale(1 / textHScale, 1);
|
||||||
var char = (unicode >= 0x10000) ?
|
|
||||||
String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
|
|
||||||
0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode);
|
|
||||||
|
|
||||||
ctx.fillText(char, width, 0);
|
var width = 0;
|
||||||
width += glyph.width * fontSize * 0.001 + charSpacing;
|
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) {
|
showSpacedText: function canvasGraphicsShowSpacedText(arr) {
|
||||||
var ctx = this.ctx;
|
var ctx = this.ctx;
|
||||||
@ -5295,8 +5349,8 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
|
|
||||||
// Type3 fonts
|
// Type3 fonts
|
||||||
setCharWidth: function canvasGraphicsSetCharWidth(xWidth, yWidth) {
|
setCharWidth: function canvasGraphicsSetCharWidth(xWidth, yWidth) {
|
||||||
TODO('type 3 fonts ("d0" operator) xWidth: ' + xWidth + ' yWidth: ' +
|
// We can safely ignore this since the width should be the same
|
||||||
yWidth);
|
// as the width in the Widths array.
|
||||||
},
|
},
|
||||||
setCharWidthAndBounds: function canvasGraphicsSetCharWidthAndBounds(xWidth,
|
setCharWidthAndBounds: function canvasGraphicsSetCharWidthAndBounds(xWidth,
|
||||||
yWidth,
|
yWidth,
|
||||||
@ -5304,9 +5358,11 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
lly,
|
lly,
|
||||||
urx,
|
urx,
|
||||||
ury) {
|
ury) {
|
||||||
TODO('type 3 fonts ("d1" operator) xWidth: ' + xWidth + ' yWidth: ' +
|
// TODO? According the spec we're also suppose to ignore any operators
|
||||||
yWidth + ' llx: ' + llx + ' lly: ' + lly + ' urx: ' + urx +
|
// that set color or include images while processing this type3 font.
|
||||||
' ury ' + ury);
|
this.rectangle(llx, lly, urx - llx, ury - lly);
|
||||||
|
this.clip();
|
||||||
|
this.endPath();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
@ -6413,6 +6469,7 @@ var PDFImage = (function pdfImage() {
|
|||||||
applyStencilMask: function applyStencilMask(buffer, inverseDecode) {
|
applyStencilMask: function applyStencilMask(buffer, inverseDecode) {
|
||||||
var width = this.width, height = this.height;
|
var width = this.width, height = this.height;
|
||||||
var bitStrideLength = (width + 7) >> 3;
|
var bitStrideLength = (width + 7) >> 3;
|
||||||
|
this.image.reset();
|
||||||
var imgArray = this.image.getBytes(bitStrideLength * height);
|
var imgArray = this.image.getBytes(bitStrideLength * height);
|
||||||
var imgArrayPos = 0;
|
var imgArrayPos = 0;
|
||||||
var i, j, mask, buf;
|
var i, j, mask, buf;
|
||||||
@ -6441,6 +6498,7 @@ var PDFImage = (function pdfImage() {
|
|||||||
|
|
||||||
// rows start at byte boundary;
|
// rows start at byte boundary;
|
||||||
var rowBytes = (width * numComps * bpc + 7) >> 3;
|
var rowBytes = (width * numComps * bpc + 7) >> 3;
|
||||||
|
this.image.reset();
|
||||||
var imgArray = this.image.getBytes(height * rowBytes);
|
var imgArray = this.image.getBytes(height * rowBytes);
|
||||||
|
|
||||||
var comps = this.colorSpace.getRgbBuffer(
|
var comps = this.colorSpace.getRgbBuffer(
|
||||||
@ -6468,6 +6526,7 @@ var PDFImage = (function pdfImage() {
|
|||||||
|
|
||||||
// rows start at byte boundary;
|
// rows start at byte boundary;
|
||||||
var rowBytes = (width * numComps * bpc + 7) >> 3;
|
var rowBytes = (width * numComps * bpc + 7) >> 3;
|
||||||
|
this.image.reset();
|
||||||
var imgArray = this.image.getBytes(height * rowBytes);
|
var imgArray = this.image.getBytes(height * rowBytes);
|
||||||
|
|
||||||
var comps = this.getComponents(imgArray);
|
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,
|
"rounds": 1,
|
||||||
"skipPages": [ 16 ],
|
"skipPages": [ 16 ],
|
||||||
"type": "load"
|
"type": "load"
|
||||||
|
},
|
||||||
|
{ "id": "simpletype3font",
|
||||||
|
"file": "pdfs/simpletype3font.pdf",
|
||||||
|
"link": false,
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "load"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user