for (var i = 0; i < fonts.length; i++) {
var font = fonts[i];
+
+ // If there is already a fontObj on the font, then it was loaded/attached
+ // to the page already and we don't have to do anything for this font
+ // here future.
+ if (font.fontObj) {
+ console.log('got already', font.properties.loadedName);
+ continue;
+ }
var obj = new Font(font.name, font.file, font.properties);
+
+ // Store the fontObj on the font such that `setFont` in CanvasGraphics
+ // can reuse it later again.
+ font.fontObj = obj;
+
objs.push(obj);
var str = '';
return -1;
}
+/**
+ * FontShape is the minimal shape a FontObject can have to be useful during
+ * executing the IRQueue.
+ */
+var FontShape = (function FontShape() {
+ var constructor = function FontShape_constructor(obj) {
+ for (var name in obj) {
+ this[name] = obj[name];
+ }
+
+ var name = this.loadedName;
+ var bold = this.black ? (this.bold ? 'bolder' : 'bold') :
+ (this.bold ? 'bold' : 'normal');
+
+ var italic = this.italic ? 'italic' : 'normal';
+ this.fontFallback = this.serif ? 'serif' : 'sans-serif';
+
+ this.namePart1 = italic + ' ' + bold + ' ';
+ this.namePart2 = 'px "' + name + '", "';
+
+ this.supported = Object.keys(this.encoding).length != 0;
+
+ // Set the loading flag. Gets set to false in FontLoader.bind().
+ this.loading = true;
+ };
+
+ function int16(bytes) {
+ return (bytes[0] << 8) + (bytes[1] & 0xff);
+ };
+
+ constructor.prototype = {
+ getRule: function fonts_getRule(size, fallback) {
+ fallback = fallback || this.fontFallback;
+ return this.namePart1 + size + this.namePart2 + fallback + '"';
+ },
+
+ charsToUnicode: function fonts_chars2Unicode(chars) {
+ var charsCache = this.charsCache;
+ var str;
+
+ // if we translated this string before, just grab it from the cache
+ if (charsCache) {
+ str = charsCache[chars];
+ if (str)
+ return str;
+ }
+
+ // lazily create the translation cache
+ if (!charsCache)
+ charsCache = this.charsCache = Object.create(null);
+
+ // translate the string using the font's encoding
+ var encoding = this.encoding;
+ if (!encoding)
+ return chars;
+ str = '';
+
+ if (this.composite) {
+ // composite fonts have multi-byte strings convert the string from
+ // single-byte to multi-byte
+ // XXX assuming CIDFonts are two-byte - later need to extract the
+ // correct byte encoding according to the PDF spec
+ var length = chars.length - 1; // looping over two bytes at a time so
+ // loop should never end on the last byte
+ for (var i = 0; i < length; i++) {
+ var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]);
+ var unicode = encoding[charcode];
+ if ('undefined' == typeof(unicode)) {
+ warn('Unencoded charcode ' + charcode);
+ unicode = charcode;
+ } else {
+ unicode = unicode.unicode;
+ }
+ str += String.fromCharCode(unicode);
+ }
+ }
+ else {
+ for (var i = 0; i < chars.length; ++i) {
+ var charcode = chars.charCodeAt(i);
+ var unicode = encoding[charcode];
+ if ('undefined' == typeof(unicode)) {
+ warn('Unencoded charcode ' + charcode);
+ unicode = charcode;
+ } else {
+ unicode = unicode.unicode;
+ }
+
+ // Handle surrogate pairs
+ if (unicode > 0xFFFF) {
+ str += String.fromCharCode(unicode & 0xFFFF);
+ unicode >>= 16;
+ }
+ str += String.fromCharCode(unicode);
+ }
+ }
+
+ // Enter the translated string into the cache
+ return (charsCache[chars] = str);
+ }
+ }
+
+ return constructor;
+})();
+
+
/**
* '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).
ensureFonts: function(fonts, callback) {
console.log('--ensureFonts--', '' + fonts);
// Convert the font names to the corresponding font obj.
- // for (var i = 0; i < fonts.length; i++) {
- // // HACK FOR NOW. Access the data directly. This isn't allowed as the
- // // font object isn't resolved yet.
- // fonts[i] = this.objs.objs[fonts[i]].data;
- // }
+ for (var i = 0; i < fonts.length; i++) {
+ // HACK FOR NOW. Access the data directly. This isn't allowed as the
+ // font object isn't resolved yet.
+ fonts[i] = this.objs.objs[fonts[i]].data;
+ }
// Load all the fonts
var fontObjs = FontLoader.bind(
}.bind(this),
this.objs
);
-
- for (var i = 0, ii = fonts.length; i < ii; ++i)
- fonts[i].dict.fontObj = fontObjs[i];
},
display: function(gfx, callback) {
var i = 0;
- function checkFontData() {
- // Check if all fontObjs have been processed. If not, shedule a
- // callback that is called once the data arrives and that checks
- // the next fonts.
- for (i; i < depFonts.length; i++) {
- var fontName = depFonts[i];
- if (!objs.hasData(fontName)) {
- console.log('need to wait for fontData', fontName);
- objs.onData(fontName, checkFontData);
- return;
- } else if (!objs.isResolved(fontName)) {
- fontsToLoad.push(fontName);
- }
- }
-
- // There can be edge cases where two pages wait for one font and then
- // call startRenderingFromIRQueue twice with the same font. That makes
- // the font getting loaded twice and throw an error later as the font
- // promise gets resolved twice.
- // This prevents thats fonts are loaded really only once.
- for (var j = 0; j < fontsToLoad.length; j++) {
- var fontName = fontsToLoad[j];
- if (fontsLoading[fontName]) {
- fontsToLoad.splice(j, 1);
- j--;
- } else {
- fontsLoading[fontName] = true;
- }
- }
-
- // At this point, all font data ia loaded. Start the actuall rendering.
- page.startRenderingFromIRQueue(data.IRQueue, fontsToLoad);
- }
+ // function checkFontData() {
+ // // Check if all fontObjs have been processed. If not, shedule a
+ // // callback that is called once the data arrives and that checks
+ // // the next fonts.
+ // for (i; i < depFonts.length; i++) {
+ // var fontName = depFonts[i];
+ // if (!objs.hasData(fontName)) {
+ // console.log('need to wait for fontData', fontName);
+ // objs.onData(fontName, checkFontData);
+ // return;
+ // } else if (!objs.isResolved(fontName)) {
+ // fontsToLoad.push(fontName);
+ // }
+ // }
+ //
+ // // There can be edge cases where two pages wait for one font and then
+ // // call startRenderingFromIRQueue twice with the same font. That makes
+ // // the font getting loaded twice and throw an error later as the font
+ // // promise gets resolved twice.
+ // // This prevents thats fonts are loaded really only once.
+ // for (var j = 0; j < fontsToLoad.length; j++) {
+ // var fontName = fontsToLoad[j];
+ // if (fontsLoading[fontName]) {
+ // fontsToLoad.splice(j, 1);
+ // j--;
+ // } else {
+ // fontsLoading[fontName] = true;
+ // }
+ // }
+ //
+ // for (var i = 0; i < depFonts.lenght; i++) {
+ // // Get fonts from the objects.
+ // fontsToLoad.push(this.objs.get(depFonts[i]));
+ // }
+ //
+ // // At this point, all font data ia loaded. Start the actuall rendering.
+ // page.startRenderingFromIRQueue(data.IRQueue, fontsToLoad);
+ // }
+ //
+ // checkFontData();
-// checkFontData();
- page.startRenderingFromIRQueue(data.IRQueue, data.depFonts);
+ // Start rendering directly for now, as the fonts are
+ page.startRenderingFromIRQueue(data.IRQueue, Object.keys(data.depFonts));
}, this);
processorHandler.on("obj", function(data) {
var name = data[2];
var file = data[3];
var properties = data[4];
-
- // << CODE TAKEN FROM WORKER >>
- data = [objId, name, file, properties];
- var objId = data[0];
- var name = data[1];
- var file = data[2];
- var properties = data[3];
-
- var font = {
- name: name,
- file: file,
- properties: properties
- };
-
- // Some fonts don't have a file, e.g. the build in ones like Arial.
if (file) {
var fontFileDict = new Dict();
fontFileDict.map = file.dict.map;
-
+
var fontFile = new Stream(file.bytes, file.start,
file.end - file.start, fontFileDict);
// Stream one. This makes complex_ttf_font.pdf work.
var cmf = file.bytes[0];
if ((cmf & 0x0f) == 0x08) {
- font.file = new FlateStream(fontFile);
+ file = new FlateStream(fontFile);
} else {
- font.file = fontFile;
+ file = fontFile;
}
}
- var obj = new Font(font.name, font.file, font.properties);
-
- var str = '';
- var data = obj.data;
- if (data) {
- var length = data.length;
- for (var j = 0; j < length; j++)
- str += String.fromCharCode(data[j]);
- }
-
- obj.str = str;
-
- var fontObj = new FontShape(obj);
- for (var prop in obj) {
- fontObj[prop] = obj[prop];
- }
-
- if (!str) {
- this.objs.resolve(objId, fontObj);
- } else {
- this.objs.setData(objId, fontObj);
- }
+
+ // For now, resolve the font object here direclty. The real font object
+ // is then created in FontLoader.bind().
+ this.objs.resolve(objId, {
+ name: name,
+ file: file,
+ properties: properties
+ });
+
+ //
+ //
+ // // << CODE TAKEN FROM WORKER >>
+ // data = [objId, name, file, properties];
+ // var objId = data[0];
+ // var name = data[1];
+ // var file = data[2];
+ // var properties = data[3];
+ //
+ // var font = {
+ // name: name,
+ // file: file,
+ // properties: properties
+ // };
+ //
+ // // Some fonts don't have a file, e.g. the build in ones like Arial.
+ // if (file) {
+ // var fontFileDict = new Dict();
+ // fontFileDict.map = file.dict.map;
+ //
+ // var fontFile = new Stream(file.bytes, file.start,
+ // file.end - file.start, fontFileDict);
+ //
+ // // Check if this is a FlateStream. Otherwise just use the created
+ // // Stream one. This makes complex_ttf_font.pdf work.
+ // var cmf = file.bytes[0];
+ // if ((cmf & 0x0f) == 0x08) {
+ // font.file = new FlateStream(fontFile);
+ // } else {
+ // font.file = fontFile;
+ // }
+ // }
+ //
+ // var obj = new Font(font.name, font.file, font.properties);
+ //
+ // var str = '';
+ // var data = obj.data;
+ // if (data) {
+ // var length = data.length;
+ // for (var j = 0; j < length; j++)
+ // str += String.fromCharCode(data[j]);
+ // }
+ //
+ // obj.str = str;
+ //
+ // var fontObj = new FontShape(obj);
+ // for (var prop in obj) {
+ // fontObj[prop] = obj[prop];
+ // }
+ //
+ // if (!str) {
+ // this.objs.resolve(objId, fontObj);
+ // } else {
+ // this.objs.setData(objId, fontObj);
+ // }
// processorHandler.send("font", [objId, name, file, properties]);
break;
WorkerProcessorHandler.setup(processorHandler);
}
- processorHandler.send("doc", this.pdf);
+ processorHandler.send("doc", this.data);
}
constructor.prototype = {
}
}
} else if (cmd == 'Tf') { // eagerly collect all fonts
- var fontRes = resources.get('Font');
- if (fontRes) {
- fontRes = xref.fetchIfRef(fontRes);
- var font = xref.fetchIfRef(fontRes.get(args[0].name));
- assertWellFormed(isDict(font));
- if (!font.translated) {
- font.translated = this.translateFont(font, xref, resources);
- if (font.translated) {
- // keep track of each font we translated so the caller can
- // load them asynchronously before calling display on a page
- // fonts.push(font.translated);
- dependency.push(font.translated);
- }
- }
- }
-
+ args[0].name = handleSetFont(args[0].name);
+ // var fontRes = resources.get('Font');
+ // if (fontRes) {
+ // fontRes = xref.fetchIfRef(fontRes);
+ // var font = xref.fetchIfRef(fontRes.get(args[0].name));
+ // assertWellFormed(isDict(font));
+ // if (!font.translated) {
+ // font.translated = this.translateFont(font, xref, resources);
+ // if (font.translated) {
+ // // keep track of each font we translated so the caller can
+ // // load them asynchronously before calling display on a page
+ // // fonts.push(font.translated);
+ // dependency.push(font.translated);
+ // }
+ // }
+ // }
+ //
} else if (cmd == 'EI') {
buildPaintImageXObject(args[0], true);
}
this.current.leading = -leading;
},
setFont: function canvasGraphicsSetFont(fontRef, size) {
- var font;
- // the tf command uses a name, but graphics state uses a reference
- if (isName(fontRef)) {
- font = this.xref.fetchIfRef(this.res.get('Font'));
- if (!isDict(font))
- return;
-
- font = font.get(fontRef.name);
- } else if (isRef(fontRef)) {
- font = fontRef;
- }
- font = this.xref.fetchIfRef(font);
- if (!font)
- error('Referenced font is not found');
-
- var fontObj = font.fontObj;
+ // Lookup the fontObj using fontRef only.
+ var fontRefName = fontRef.name;
+ var fontObj = this.objs.get(fontRefName).fontObj;
+
+ if (!fontObj) {
+ throw "Can't find font for " + fontRefName;
+ }
+
+ var name = fontObj.loadedName || 'sans-serif';
+
+ // var font;
+ // // the tf command uses a name, but graphics state uses a reference
+ // if (isName(fontRef)) {
+ // font = this.xref.fetchIfRef(this.res.get('Font'));
+ // if (!isDict(font))
+ // return;
+ //
+ // font = font.get(fontRef.name);
+ // } else if (isRef(fontRef)) {
+ // font = fontRef;
+ // }
+ // font = this.xref.fetchIfRef(font);
+ // if (!font)
+ // error('Referenced font is not found');
+ //
+ // var fontObj = font.fontObj;
this.current.font = fontObj;
this.current.fontSize = size;
// return;
// }
- console.log("showText", text);
+ // console.log("showText", text);
var ctx = this.ctx;
var current = this.current;
// return;
// }
- console.log("showSpacedText", arr);
+ // console.log("showSpacedText", arr);
var ctx = this.ctx;
var current = this.current;