/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-var kMaxFontFileSize = 100000;
+/**
+ * Hold a map of decoded fonts and of the standard fourteen Type1 fonts and
+ * their acronyms.
+ * TODO Add the standard fourteen Type1 fonts list by default
+ * http://cgit.freedesktop.org/poppler/poppler/tree/poppler/GfxFont.cc#n65
+ */
+var Fonts = {};
+
/**
- * This dictionary holds decoded fonts data.
+ * '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).
+ *
+ * For example to read a Type1 font and to attach it to the document:
+ * var type1Font = new Font("MyFontName", binaryData, "Type1");
+ * type1Font.bind();
+ *
+ * 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.
*/
-var Fonts = new Dict();
+var Font = function(aFontName, aFontFile, aFontType) {
+ this.name = aFontName;
+
+ // If the font has already been decoded simply return
+ if (Fonts[aFontName]) {
+ this.font = Fonts[aFontName];
+ return;
+ }
+
+ switch (aFontType) {
+ case "Type1":
+ this.mimetype = "font/otf";
+ this.font = new Type1(aFontName, aFontFile);
+ break;
+ case "TrueType":
+ this.mimetype = "font/ttf";
+ this.font = new TrueType(aFontName, aFontFile);
+ break;
+ default:
+ error("Font " + aFontType + " is not supported");
+ break;
+ }
+
+ Fonts[aFontName] = this.font;
+ this.bind();
+};
+
+Font.prototype = {
+ name: null,
+ font: null,
+ mimetype: null,
+
+ bind: function() {
+ var data = this.font.data;
+
+ // Compute the binary data to base 64
+ var str = [];
+ var count = data.length;
+ for (var i = 0; i < count; i++)
+ str.push(data.getChar ? data.getChar()
+ : String.fromCharCode(data[i]));
+
+ var dataBase64 = window.btoa(str.join(""));
+
+ // Add the @font-face rule to the document
+ var url = "url(data:" + this.mimetype + ";base64," + dataBase64 + ");";
+ var rule = "@font-face { font-family:'" + this.name + "';src:" + url + "}";
+ var styleSheet = document.styleSheets[0];
+ styleSheet.insertRule(rule, styleSheet.length);
+ }
+};
+
+/** Implementation dirty logic starts here */
+
+var kMaxFontFileSize = 100000;
/**
- * This simple object keep a trace of the fonts that have already been decoded
- * by storing a map between the name given by the PDF and the name gather from
- * the font (aka the PostScript code of the font itself for Type1 font).
+ * This dictionary holds decoded fonts data.
*/
-var _Fonts = {};
+var PSFonts = new Dict();
var Stack = function() {
};
};
-var Base64Encoder = {
- encode: function(aFontName, aData) {
- var str = [];
- var count = aData.length;
- for (var i = 0; i < count; i++)
- str.push(aData.getChar ? aData.getChar() : String.fromCharCode(aData[i]));
-
- // Add the css rule to the document
- var fontData = window.btoa(str.join(""));
- var url = "url(data:font/otf;base64," + fontData + ");";
- document.styleSheets[0].insertRule("@font-face { font-family: '" + aFontName + "'; src: " + url + " }", 0);
-
- return fontData;
- }
-};
-
-var TrueTypeFont = function(aFontName, aFontFile) {
- if (_Fonts[aFontName])
- return;
- _Fonts[aFontName] = true;
-
+var TrueType = function(aFontName, aFontFile) {
var debug = true;
function dump(aMsg) {
if (debug)
}
dump("Loading a TrueType font: " + aFontName);
- var fontData = Base64Encoder.encode(aFontName, aFontFile);
- Fonts.set(aFontName, fontData);
+ this.data = aFontFile;
};
var Type1Parser = function(aAsciiStream, aBinaryStream) {
case "def":
var value = operandStack.pop();
var key = operandStack.pop();
-
- // XXX we don't want to do that here but for some reasons the names
- // are different between what is declared and the FontName directive
- if (key == "FontName" && Fonts.get(value)) {
- // The font has already be decoded, stop!
- return true;
- }
-
dump("def: " + key + " = " + value);
dictionaryStack.peek().set(key, value);
break;
// The key will be the identifier to recognize this font
fontName = key;
- Fonts.set(key, font);
+ PSFonts.set(key, font);
operandStack.push(font);
break;
var fontCount = 0;
-var Type1Font = function(aFontName, aFontFile) {
- if (_Fonts[aFontName])
- return;
- _Fonts[aFontName] = true;
-
+var Type1 = function(aFontName, aFontFile) {
// All Type1 font program should begin with the comment %!
if (aFontFile.getByte() != 0x25 || aFontFile.getByte() != 0x21)
error("Invalid file header");
this.parser = new Type1Parser(ASCIIStream, binaryStream);
var fontName = this.parser.parse();
- var font = Fonts.get(fontName);
- var fontData = this.convertToOTF(this.convertToCFF(font), font);
- fontData = Base64Encoder.encode(aFontName, fontData);
- Fonts.set(aFontName, fontData);
-
+ var font = PSFonts.get(fontName);
+ this.data = this.convertToOTF(this.convertToCFF(font), font);
var end = Date.now();
log("Time to parse font is:" + (end - start));
}
};
-Type1Font.prototype = {
+Type1.prototype = {
getDefaultWidth: function(aCharstrings) {
var defaultWidth = 0;
var defaultUsedCount = 0;
value = 2;
for (var i = 1; i < maxPower; i++)
value *= 2;
-
- if (fontCount == 5) {
- log ("mp2: " + aNumber + "::" + value);
- }
-
return value;
},
for (var i = 0; i < currentOffset; i++)
fontData.push(otf[i]);
- writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".otf");
+ //writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".otf");
return fontData;
}
};
var fontName = "";
var subtype = font.get("Subtype").name;
- switch (subtype) {
- case "Type1":
- var fontDescriptor = font.get("FontDescriptor");
- if (fontDescriptor.num) {
- // XXX fetchIfRef looks expensive
- var fontDescriptor = this.xref.fetchIfRef(fontDescriptor);
- var fontFile = this.xref.fetchIfRef(fontDescriptor.get("FontFile"));
- fontName = fontDescriptor.get("FontName").name;
- fontName = fontName.replace("+", ""); // no + are allowed in the font name
- font = new Type1Font(fontName, fontFile);
- }
- break;
-
- case "Type3":
- TODO("support Type3 font");
- break;
-
- case "TrueType":
- var fontDescriptor = font.get("FontDescriptor");
- if (fontDescriptor.num) {
- var fontDescriptor = this.xref.fetchIfRef(fontDescriptor);
- var fontFile = this.xref.fetchIfRef(fontDescriptor.get("FontFile2"));
- fontName = fontDescriptor.get("FontName").name;
- fontName = fontName.replace("+", ""); // no + are allowed in the font name
- font = new TrueTypeFont(fontName, fontFile);
- }
- break;
-
- default:
- error("Unsupported font type: " + subtype);
- break;
+ var fontDescriptor = font.get("FontDescriptor");
+ if (fontDescriptor.num) {
+ 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("+", " ");
+ new Font(fontName, fontFile, subtype);
}
this.current.fontSize = size;