Add support for ligatures, asterisks, etc.
This commit is contained in:
parent
f802ad05b2
commit
4cae2df1e5
69
PDFFont.js
69
PDFFont.js
@ -9,7 +9,7 @@ var kMaxFontFileSize = 40000;
|
|||||||
/**
|
/**
|
||||||
* Maximum number of glyphs per font.
|
* Maximum number of glyphs per font.
|
||||||
*/
|
*/
|
||||||
var kMaxGlyphsCount = 1024;
|
var kMaxGlyphsCount = 65526;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum time to wait for a font to be loaded by @font-face
|
* Maximum time to wait for a font to be loaded by @font-face
|
||||||
@ -28,33 +28,48 @@ var fontCount = 0;
|
|||||||
* TODO Add the standard fourteen Type1 fonts list by default
|
* TODO Add the standard fourteen Type1 fonts list by default
|
||||||
* http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65
|
* http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65
|
||||||
*/
|
*/
|
||||||
var Fonts = {};
|
var Fonts = {
|
||||||
|
_active: null,
|
||||||
|
get active() {
|
||||||
|
return this._active;
|
||||||
|
},
|
||||||
|
|
||||||
|
set active(aFontName) {
|
||||||
|
this._active = this[aFontName];
|
||||||
|
},
|
||||||
|
|
||||||
|
getUnicodeFor: function fonts_getUnicodeFor(aCode) {
|
||||||
|
var glyph = this._active.encoding[aCode];
|
||||||
|
var unicode = "0x" + GlyphsUnicode[glyph];
|
||||||
|
return unicode || aCode;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'Font' is the class the outside world should use, it encapsulate all the font
|
* 'Font' is the class the outside world should use, it encapsulate all the font
|
||||||
* decoding logics whatever type it is (assuming the font type is supported).
|
* decoding logics whatever type it is (assuming the font type is supported).
|
||||||
*
|
*
|
||||||
* For example to read a Type1 font and to attach it to the document:
|
* For example to read a Type1 font and to attach it to the document:
|
||||||
* var type1Font = new Font("MyFontName", binaryData, "Type1");
|
* var type1Font = new Font("MyFontName", binaryData, aFontEncoding, "Type1");
|
||||||
* type1Font.bind();
|
* type1Font.bind();
|
||||||
*
|
*
|
||||||
* As an improvment the last parameter can be replaced by an automatic guess
|
* As an improvment the last parameter can be replaced by an automatic guess
|
||||||
* of the font type based on the first byte of the file.
|
* of the font type based on the first byte of the file.
|
||||||
*/
|
*/
|
||||||
var Font = function(aFontName, aFontFile, aFontType) {
|
var Font = function(aName, aFile, aEncoding, aType) {
|
||||||
this.name = aFontName;
|
this.name = aName;
|
||||||
|
|
||||||
// If the font has already been decoded simply return
|
// If the font has already been decoded simply return
|
||||||
if (Fonts[aFontName]) {
|
if (Fonts[aName]) {
|
||||||
this.font = Fonts[aFontName].data;
|
this.font = Fonts[aName].data;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fontCount++;
|
fontCount++;
|
||||||
|
|
||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
switch (aFontType) {
|
switch (aType) {
|
||||||
case "Type1":
|
case "Type1":
|
||||||
var cff = new CFF(aFontName, aFontFile);
|
var cff = new CFF(aFile);
|
||||||
this.mimetype = "font/otf";
|
this.mimetype = "font/otf";
|
||||||
|
|
||||||
// Wrap the CFF data inside an OTF font file
|
// Wrap the CFF data inside an OTF font file
|
||||||
@ -63,18 +78,19 @@ var Font = function(aFontName, aFontFile, aFontType) {
|
|||||||
|
|
||||||
case "TrueType":
|
case "TrueType":
|
||||||
this.mimetype = "font/ttf";
|
this.mimetype = "font/ttf";
|
||||||
var ttf = new TrueType(aFontName, aFontFile);
|
var ttf = new TrueType(aFile);
|
||||||
this.font = ttf.data;
|
this.font = ttf.data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
warn("Font " + aFontType + " is not supported");
|
warn("Font " + aType + " is not supported");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var end = Date.now();
|
var end = Date.now();
|
||||||
|
|
||||||
Fonts[aFontName] = {
|
Fonts[aName] = {
|
||||||
data: this.font,
|
data: this.font,
|
||||||
|
encoding: aEncoding,
|
||||||
loading: true
|
loading: true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,11 +124,11 @@ Font.prototype = {
|
|||||||
var debug = false;
|
var debug = false;
|
||||||
|
|
||||||
var canvas = document.createElement("canvas");
|
var canvas = document.createElement("canvas");
|
||||||
var style = "position:absolute; left: " +
|
var style = "position:absolute; top: " +
|
||||||
(debug ? (100 * fontCount) : "-200") + "px; top: -200px;";
|
(debug ? (80 * fontCount) : "-200") + "px; left: 100px;";
|
||||||
canvas.setAttribute("style", style);
|
canvas.setAttribute("style", style);
|
||||||
canvas.setAttribute("width", 100);
|
canvas.setAttribute("width", 100);
|
||||||
canvas.setAttribute("heigth", 100);
|
canvas.setAttribute("heigth", 70);
|
||||||
document.body.appendChild(canvas);
|
document.body.appendChild(canvas);
|
||||||
|
|
||||||
// Get the first character of the font
|
// Get the first character of the font
|
||||||
@ -125,7 +141,7 @@ Font.prototype = {
|
|||||||
var res = xref.fetch(fontResource.get(id));
|
var res = xref.fetch(fontResource.get(id));
|
||||||
var descriptor = xref.fetch(res.get("FontDescriptor"));
|
var descriptor = xref.fetch(res.get("FontDescriptor"));
|
||||||
var name = descriptor.get("FontName").toString();
|
var name = descriptor.get("FontName").toString();
|
||||||
var font = Fonts[name.replace("+", "_")];
|
var font = Fonts[name.replace("+", "_")];
|
||||||
if (font && font.loading && name == fontName.replace("_", "+")) {
|
if (font && font.loading && name == fontName.replace("_", "+")) {
|
||||||
charset = descriptor.get("CharSet").split("/");
|
charset = descriptor.get("CharSet").split("/");
|
||||||
break;
|
break;
|
||||||
@ -174,7 +190,7 @@ Font.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
ctx.fillText(testString, 20, 60);
|
ctx.fillText(testString, 20, 50);
|
||||||
}, 150, this);
|
}, 150, this);
|
||||||
|
|
||||||
/** Hack end */
|
/** Hack end */
|
||||||
@ -246,8 +262,9 @@ Font.prototype = {
|
|||||||
|
|
||||||
_createCMAPTable: function font_createCMAPTable(aGlyphs) {
|
_createCMAPTable: function font_createCMAPTable(aGlyphs) {
|
||||||
var characters = new Array(kMaxGlyphsCount);
|
var characters = new Array(kMaxGlyphsCount);
|
||||||
for (var i = 0; i < aGlyphs.length; i++)
|
for (var i = 0; i < aGlyphs.length; i++) {
|
||||||
characters[aGlyphs[i].unicode] = i + 1;
|
characters[aGlyphs[i].unicode] = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Separate the glyphs into continuous range of codes, aka segment.
|
// Separate the glyphs into continuous range of codes, aka segment.
|
||||||
var ranges = [];
|
var ranges = [];
|
||||||
@ -377,10 +394,10 @@ Font.prototype = {
|
|||||||
0x01, 0x02, // yStrikeOutPosition
|
0x01, 0x02, // yStrikeOutPosition
|
||||||
0x00, 0x00, // sFamilyClass
|
0x00, 0x00, // sFamilyClass
|
||||||
0x02, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Panose
|
0x02, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Panose
|
||||||
0x00, 0x00, 0x00, 0x01, // ulUnicodeRange1 (Bits 0-31)
|
0xFF, 0xFF, 0xFF, 0xFF, // ulUnicodeRange1 (Bits 0-31)
|
||||||
0x00, 0x00, 0x00, 0x00, // ulUnicodeRange2 (Bits 32-63)
|
0xFF, 0xFF, 0xFF, 0xFF, // ulUnicodeRange1 (Bits 32-63)
|
||||||
0x00, 0x00, 0x00, 0x00, // ulUnicodeRange3 (Bits 64-95)
|
0xFF, 0xFF, 0xFF, 0xFF, // ulUnicodeRange1 (Bits 64-95)
|
||||||
0x00, 0x00, 0x00, 0x00, // ulUnicodeRange4 (Bits 96-127)
|
0xFF, 0xFF, 0xFF, 0xFF, // ulUnicodeRange1 (Bits 96-127)
|
||||||
0x2A, 0x32, 0x31, 0x2A, // achVendID
|
0x2A, 0x32, 0x31, 0x2A, // achVendID
|
||||||
0x00, 0x20, // fsSelection
|
0x00, 0x20, // fsSelection
|
||||||
0x00, 0x2D, // usFirstCharIndex
|
0x00, 0x2D, // usFirstCharIndex
|
||||||
@ -558,8 +575,8 @@ var FontsUtils = {
|
|||||||
* (near?) future this class will rewrite the font to ensure it is well formed
|
* (near?) future this class will rewrite the font to ensure it is well formed
|
||||||
* and valid in the point of view of the sanitizer.
|
* and valid in the point of view of the sanitizer.
|
||||||
*/
|
*/
|
||||||
var TrueType = function(aFontName, aFontFile) {
|
var TrueType = function(aFile) {
|
||||||
this.data = aFontFile;
|
this.data = aFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1229,7 +1246,7 @@ var Type1Parser = function(aAsciiStream, aBinaryStream) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var CFF = function(aFontName, aFontFile) {
|
var CFF = function(aFontFile) {
|
||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
|
|
||||||
var length1 = aFontFile.dict.get("Length1");
|
var length1 = aFontFile.dict.get("Length1");
|
||||||
@ -1405,7 +1422,7 @@ CFF.prototype = {
|
|||||||
var familyName = fontInfo.get("FamilyName");
|
var familyName = fontInfo.get("FamilyName");
|
||||||
var weight = fontInfo.get("Weight");
|
var weight = fontInfo.get("Weight");
|
||||||
var strings = [version, notice, fullName,
|
var strings = [version, notice, fullName,
|
||||||
familyName, weight, "asteriskmath"];
|
familyName, weight];
|
||||||
var stringsIndex = this.createCFFIndexHeader(strings);
|
var stringsIndex = this.createCFFIndexHeader(strings);
|
||||||
var stringsDataLength = stringsIndex.length;
|
var stringsDataLength = stringsIndex.length;
|
||||||
|
|
||||||
|
8
pdf.js
8
pdf.js
@ -798,6 +798,8 @@ var Lexer = (function() {
|
|||||||
x = (x << 3) + (ch - '0');
|
x = (x << 3) + (ch - '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x = Fonts.getUnicodeFor(x);
|
||||||
str += String.fromCharCode(x);
|
str += String.fromCharCode(x);
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
@ -1849,15 +1851,11 @@ var CanvasGraphics = (function() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var fontName = "";
|
var fontName = "";
|
||||||
var subtype = font.get("Subtype").name;
|
|
||||||
var fontDescriptor = font.get("FontDescriptor");
|
var fontDescriptor = font.get("FontDescriptor");
|
||||||
if (fontDescriptor.num) {
|
if (fontDescriptor.num) {
|
||||||
var fontDescriptor = this.xref.fetchIfRef(fontDescriptor);
|
var fontDescriptor = this.xref.fetchIfRef(fontDescriptor);
|
||||||
var fontFile = this.xref.fetchIfRef(fontDescriptor.get("FontFile"));
|
|
||||||
if (!fontFile)
|
|
||||||
fontFile = this.xref.fetchIfRef(fontDescriptor.get("FontFile2"));
|
|
||||||
fontName = fontDescriptor.get("FontName").name.replace("+", "_");
|
fontName = fontDescriptor.get("FontName").name.replace("+", "_");
|
||||||
new Font(fontName, fontFile, subtype);
|
Fonts.active = fontName;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.current.fontSize = size;
|
this.current.fontSize = size;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<html>
|
<html>
|
||||||
<<<<<<< HEAD
|
|
||||||
<head>
|
<head>
|
||||||
<title>Simple pdf.js page viewer</title>
|
<title>Simple pdf.js page viewer</title>
|
||||||
<link rel="stylesheet" href="test.css"></link>
|
<link rel="stylesheet" href="test.css"></link>
|
||||||
|
16
test.js
16
test.js
@ -93,7 +93,21 @@ function displayPage(num) {
|
|||||||
var fontFile = page.xref.fetchIfRef(descriptor.get("FontFile"));
|
var fontFile = page.xref.fetchIfRef(descriptor.get("FontFile"));
|
||||||
if (!fontFile)
|
if (!fontFile)
|
||||||
fontFile = page.xref.fetchIfRef(descriptor.get("FontFile2"));
|
fontFile = page.xref.fetchIfRef(descriptor.get("FontFile2"));
|
||||||
new Font(fontName, fontFile, subtype);
|
|
||||||
|
// Generate the custom cmap of the font
|
||||||
|
var encoding = xref.fetch(res.get("Encoding"));
|
||||||
|
var differences = encoding.get("Differences");
|
||||||
|
var encodingMap = {};
|
||||||
|
var index = 0;
|
||||||
|
for (var j = 0; j < differences.length; j++) {
|
||||||
|
var data = differences[j];
|
||||||
|
if (IsNum(data))
|
||||||
|
index = data;
|
||||||
|
else
|
||||||
|
encodingMap[index++] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
new Font(fontName, fontFile, encodingMap, subtype);
|
||||||
fontsReady = false;
|
fontsReady = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user