Add support for ligatures, asterisks, etc.

This commit is contained in:
Vivien Nicolas 2011-06-14 11:08:08 +02:00
parent f802ad05b2
commit 4cae2df1e5
4 changed files with 61 additions and 33 deletions

View File

@ -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
View File

@ -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;

View File

@ -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
View File

@ -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;
} }