Fully support truetype composite fonts, clean up
This commit is contained in:
parent
926e4f1130
commit
36763e8e82
182
fonts.js
182
fonts.js
@ -411,7 +411,7 @@ var Font = (function() {
|
||||
break;
|
||||
}
|
||||
this.data = data;
|
||||
this.type = properties.type; //use the type to test if the string is single or multi-byte
|
||||
this.type = properties.type; // Use the type to test if the string is single or multi-byte
|
||||
this.id = Fonts.registerFont(name, data, properties);
|
||||
this.loadedName = 'pdfFont' + this.id;
|
||||
this.compositeFont = properties.compositeFont;
|
||||
@ -682,6 +682,65 @@ var Font = (function() {
|
||||
'\x00\x00\x00\x00'; // maxMemType1
|
||||
};
|
||||
|
||||
function createNameTable(name) {
|
||||
var strings = [
|
||||
'Original licence', // 0.Copyright
|
||||
name, // 1.Font family
|
||||
'Unknown', // 2.Font subfamily (font weight)
|
||||
'uniqueID', // 3.Unique ID
|
||||
name, // 4.Full font name
|
||||
'Version 0.11', // 5.Version
|
||||
'', // 6.Postscript name
|
||||
'Unknown', // 7.Trademark
|
||||
'Unknown', // 8.Manufacturer
|
||||
'Unknown' // 9.Designer
|
||||
];
|
||||
|
||||
// Mac want 1-byte per character strings while Windows want
|
||||
// 2-bytes per character, so duplicate the names table
|
||||
var stringsUnicode = [];
|
||||
for (var i = 0; i < strings.length; i++) {
|
||||
var str = strings[i];
|
||||
|
||||
var strUnicode = '';
|
||||
for (var j = 0; j < str.length; j++)
|
||||
strUnicode += string16(str.charCodeAt(j));
|
||||
stringsUnicode.push(strUnicode);
|
||||
}
|
||||
|
||||
var names = [strings, stringsUnicode];
|
||||
var platforms = ['\x00\x01', '\x00\x03'];
|
||||
var encodings = ['\x00\x00', '\x00\x01'];
|
||||
var languages = ['\x00\x00', '\x04\x09'];
|
||||
|
||||
var namesRecordCount = strings.length * platforms.length;
|
||||
var nameTable =
|
||||
'\x00\x00' + // format
|
||||
string16(namesRecordCount) + // Number of names Record
|
||||
string16(namesRecordCount * 12 + 6); // Storage
|
||||
|
||||
// Build the name records field
|
||||
var strOffset = 0;
|
||||
for (var i = 0; i < platforms.length; i++) {
|
||||
var strs = names[i];
|
||||
for (var j = 0; j < strs.length; j++) {
|
||||
var str = strs[j];
|
||||
var nameRecord =
|
||||
platforms[i] + // platform ID
|
||||
encodings[i] + // encoding ID
|
||||
languages[i] + // language ID
|
||||
string16(j) + // name ID
|
||||
string16(str.length) +
|
||||
string16(strOffset);
|
||||
nameTable += nameRecord;
|
||||
strOffset += str.length;
|
||||
}
|
||||
}
|
||||
|
||||
nameTable += strings.join('') + stringsUnicode.join('');
|
||||
return nameTable;
|
||||
}
|
||||
|
||||
constructor.prototype = {
|
||||
name: null,
|
||||
font: null,
|
||||
@ -814,7 +873,7 @@ var Font = (function() {
|
||||
|
||||
// This keep a reference to the CMap and the post tables since they can
|
||||
// be rewritted
|
||||
var cmap, post;
|
||||
var cmap, post, nameTable, maxp;
|
||||
|
||||
var tables = [];
|
||||
for (var i = 0; i < numTables; i++) {
|
||||
@ -825,6 +884,10 @@ var Font = (function() {
|
||||
cmap = table;
|
||||
else if (table.tag == 'post')
|
||||
post = table;
|
||||
else if (table.tag == 'name')
|
||||
nameTable = table;
|
||||
else if (table.tag == 'maxp')
|
||||
maxp = table;
|
||||
|
||||
requiredTables.splice(index, 1);
|
||||
}
|
||||
@ -859,24 +922,50 @@ var Font = (function() {
|
||||
data: stringToArray(createOS2Table(properties))
|
||||
});
|
||||
|
||||
if (!cmap) {
|
||||
// Replace the old CMAP table with a shiny new one
|
||||
if (properties.type == 'CIDFontType2') {
|
||||
// Type2 composite fonts map charcters directly to glyphs so the cmap
|
||||
// table must be replaced.
|
||||
|
||||
var glyphs = [];
|
||||
var charset = properties.charset;
|
||||
for (var i=1; i < charset.length; i++) {
|
||||
if (charset.indexOf(i) != -1) {
|
||||
if (charset.length == 0)
|
||||
{
|
||||
// PDF did not contain a GIDMap for the font so create an identity cmap
|
||||
|
||||
// First get the number of glyphs from the maxp table
|
||||
font.pos = (font.start ? font.start : 0) + maxp.length;
|
||||
var version = int16(font.getBytes(4));
|
||||
var numGlyphs = int16(font.getBytes(2));
|
||||
|
||||
// Now create an identity mapping
|
||||
for (var i=1; i < numGlyphs; i++) {
|
||||
glyphs.push({
|
||||
unicode: charset.indexOf(i)
|
||||
unicode: i
|
||||
});
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (var i=1; i < charset.length; i++) {
|
||||
if (charset.indexOf(i) != -1) {
|
||||
glyphs.push({
|
||||
unicode: charset.indexOf(i)
|
||||
});
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
tables.push({
|
||||
tag: 'cmap',
|
||||
data: createCMapTable(glyphs)
|
||||
})
|
||||
|
||||
if (!cmap) {
|
||||
// Font did not contain a cmap
|
||||
tables.push({
|
||||
tag: 'cmap',
|
||||
data: createCMapTable(glyphs)
|
||||
})
|
||||
} else {
|
||||
cmap.data = createCMapTable(glyphs);
|
||||
}
|
||||
} else {
|
||||
// Replace the old CMAP table with a shiny new one
|
||||
replaceCMapTable(cmap, font, properties);
|
||||
}
|
||||
|
||||
@ -888,6 +977,14 @@ var Font = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
// Rewrite the 'name' table if needed
|
||||
if (!nameTable) {
|
||||
tables.push({
|
||||
tag: 'name',
|
||||
data: stringToArray(createNameTable(this.name))
|
||||
});
|
||||
}
|
||||
|
||||
// Tables needs to be written by ascendant alphabetic order
|
||||
tables.sort(function tables_sort(a, b) {
|
||||
return (a.tag > b.tag) - (a.tag < b.tag);
|
||||
@ -930,65 +1027,6 @@ var Font = (function() {
|
||||
},
|
||||
|
||||
convert: function font_convert(fontName, font, properties) {
|
||||
function createNameTable(name) {
|
||||
var strings = [
|
||||
'Original licence', // 0.Copyright
|
||||
name, // 1.Font family
|
||||
'Unknown', // 2.Font subfamily (font weight)
|
||||
'uniqueID', // 3.Unique ID
|
||||
name, // 4.Full font name
|
||||
'Version 0.11', // 5.Version
|
||||
'', // 6.Postscript name
|
||||
'Unknown', // 7.Trademark
|
||||
'Unknown', // 8.Manufacturer
|
||||
'Unknown' // 9.Designer
|
||||
];
|
||||
|
||||
// Mac want 1-byte per character strings while Windows want
|
||||
// 2-bytes per character, so duplicate the names table
|
||||
var stringsUnicode = [];
|
||||
for (var i = 0; i < strings.length; i++) {
|
||||
var str = strings[i];
|
||||
|
||||
var strUnicode = '';
|
||||
for (var j = 0; j < str.length; j++)
|
||||
strUnicode += string16(str.charCodeAt(j));
|
||||
stringsUnicode.push(strUnicode);
|
||||
}
|
||||
|
||||
var names = [strings, stringsUnicode];
|
||||
var platforms = ['\x00\x01', '\x00\x03'];
|
||||
var encodings = ['\x00\x00', '\x00\x01'];
|
||||
var languages = ['\x00\x00', '\x04\x09'];
|
||||
|
||||
var namesRecordCount = strings.length * platforms.length;
|
||||
var nameTable =
|
||||
'\x00\x00' + // format
|
||||
string16(namesRecordCount) + // Number of names Record
|
||||
string16(namesRecordCount * 12 + 6); // Storage
|
||||
|
||||
// Build the name records field
|
||||
var strOffset = 0;
|
||||
for (var i = 0; i < platforms.length; i++) {
|
||||
var strs = names[i];
|
||||
for (var j = 0; j < strs.length; j++) {
|
||||
var str = strs[j];
|
||||
var nameRecord =
|
||||
platforms[i] + // platform ID
|
||||
encodings[i] + // encoding ID
|
||||
languages[i] + // language ID
|
||||
string16(j) + // name ID
|
||||
string16(str.length) +
|
||||
string16(strOffset);
|
||||
nameTable += nameRecord;
|
||||
strOffset += str.length;
|
||||
}
|
||||
}
|
||||
|
||||
nameTable += strings.join('') + stringsUnicode.join('');
|
||||
return nameTable;
|
||||
}
|
||||
|
||||
function isFixedPitch(glyphs) {
|
||||
for (var i = 0; i < glyphs.length - 1; i++) {
|
||||
if (glyphs[i] != glyphs[i + 1])
|
||||
|
50
pdf.js
50
pdf.js
@ -3630,7 +3630,7 @@ var PartialEvaluator = (function() {
|
||||
var compositeFont = false;
|
||||
assertWellFormed(IsName(subType), 'invalid font Subtype');
|
||||
|
||||
//If font is a composite
|
||||
// If font is a composite
|
||||
// - get the descendant font
|
||||
// - set the type according to the descendant font
|
||||
// - get the FontDescriptor from the descendant font
|
||||
@ -3664,31 +3664,35 @@ var PartialEvaluator = (function() {
|
||||
var encodingMap = {};
|
||||
var charset = [];
|
||||
if (compositeFont) {
|
||||
//Special CIDFont support
|
||||
//XXX only identity CID Encodings supported for now
|
||||
var encoding = xref.fetchIfRef(fontDict.get('Encoding'));
|
||||
if (IsName(encoding)) {
|
||||
//Encoding is a predefined CMap
|
||||
if (encoding.name == 'Identity-H') {
|
||||
if (subType.name == 'CIDFontType2') {
|
||||
var cidToGidMap = descendant.get('CIDToGIDMap');
|
||||
if (cidToGidMap) {
|
||||
//Extract the charset from the CIDToGIDMap
|
||||
var glyphsStream = xref.fetchIfRef(cidToGidMap);
|
||||
var glyphsData = glyphsStream.getBytes(0);
|
||||
var i = 0;
|
||||
//glyph ids are big-endian 2-byte values
|
||||
for (var j=0; j<glyphsData.length; j++) {
|
||||
var glyphID = (glyphsData[j++] << 8) | glyphsData[j];
|
||||
charset.push(glyphID);
|
||||
}
|
||||
}
|
||||
// Special CIDFont support
|
||||
// XXX only CIDFontType2 supported for now
|
||||
if (subType.name == 'CIDFontType2') {
|
||||
var cidToGidMap = descendant.get('CIDToGIDMap');
|
||||
if (cidToGidMap && IsRef(cidToGidMap)) {
|
||||
// Extract the charset from the CIDToGIDMap
|
||||
var glyphsStream = xref.fetchIfRef(cidToGidMap);
|
||||
var glyphsData = glyphsStream.getBytes(0);
|
||||
var i = 0;
|
||||
// Glyph ids are big-endian 2-byte values
|
||||
for (var j=0; j<glyphsData.length; j++) {
|
||||
var glyphID = (glyphsData[j++] << 8) | glyphsData[j];
|
||||
charset.push(glyphID);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// XXX This is a placeholder for handling of the encoding of CIDFontType0 fonts
|
||||
var encoding = xref.fetchIfRef(fontDict.get('Encoding'));
|
||||
if (IsName(encoding)) {
|
||||
// Encoding is a predefined CMap
|
||||
if (encoding.name == 'Identity-H') {
|
||||
TODO ('Need to create an identity cmap')
|
||||
} else {
|
||||
TODO ('Need to support predefined CMaps see PDF 32000-1:2008 9.7.5.2 Predefined CMaps')
|
||||
}
|
||||
} else {
|
||||
TODO ('Need to support predefined CMaps see PDF 32000-1:2008 9.7.5.2 Predefined CMaps')
|
||||
TODO ('Need to support encoding streams see PDF 32000-1:2008 9.7.5.3');
|
||||
}
|
||||
} else {
|
||||
TODO ('Need to support encoding streams see PDF 32000-1:2008 9.7.5.3');
|
||||
}
|
||||
} else if (fontDict.has('Encoding')) {
|
||||
var encoding = xref.fetchIfRef(fontDict.get('Encoding'));
|
||||
|
Loading…
Reference in New Issue
Block a user