/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ 'use strict'; var isWorker = (typeof window == 'undefined'); /** * Maximum file size of the font. */ var kMaxFontFileSize = 200000; /** * Maximum time to wait for a font to be loaded by font-face rules. */ var kMaxWaitForFontFace = 1000; /** * 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 = (function Fonts() { var kScalePrecision = 40; var fonts = []; if (!isWorker) { var ctx = document.createElement('canvas').getContext('2d'); ctx.scale(1 / kScalePrecision, 1); } var fontCount = 0; function FontInfo(name, data, properties) { this.name = name; this.data = data; this.properties = properties; this.id = fontCount++; this.loading = true; this.sizes = []; } var current; var measureCache; return { registerFont: function fonts_registerFont(fontName, data, properties) { var font = new FontInfo(fontName, data, properties); fonts.push(font); return font.id; }, blacklistFont: function fonts_blacklistFont(fontName) { var id = registerFont(fontName, null, {}); markLoaded(fontName); return id; }, lookupById: function fonts_lookupById(id) { return fonts[id]; }, setActive: function fonts_setActive(fontName, fontObj, size) { // |current| can be null is fontName is a built-in font // (e.g. "sans-serif") if (fontObj && (current = fonts[fontObj.id])) { var sizes = current.sizes; if (!(measureCache = sizes[size])) measureCache = sizes[size] = Object.create(null); } else { measureCache = null } ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; }, measureText: function fonts_measureText(text) { var width; if (measureCache && (width = measureCache[text])) return width; width = ctx.measureText(text).width / kScalePrecision; if (measureCache) measureCache[text] = width; return width; } }; })(); var FontLoader = { listeningForFontLoad: false, bind: function(fonts, callback) { function checkFontsLoaded() { for (var i = 0; i < allIds.length; i++) { var id = allIds[i]; if (Fonts.lookupById(id).loading) { return false; } } document.documentElement.removeEventListener( 'pdfjsFontLoad', checkFontsLoaded, false); callback(); return true; } var allIds = []; var rules = [], names = [], ids = []; for (var i = 0; i < fonts.length; i++) { var font = fonts[i]; var obj = new Font(font.name, font.file, font.properties); font.fontDict.fontObj = obj; allIds.push(obj.id); var str = ''; var data = Fonts.lookupById(obj.id).data; var length = data.length; for (var j = 0; j < length; j++) str += String.fromCharCode(data[j]); var rule = isWorker ? obj.bindWorker(str) : obj.bindDOM(str); if (rule) { rules.push(rule); names.push(obj.loadedName); ids.push(obj.id); } } this.listeningForFontLoad = false; if (!isWorker && rules.length) { FontLoader.prepareFontLoadEvent(rules, names, ids); } if (!checkFontsLoaded()) { document.documentElement.addEventListener( 'pdfjsFontLoad', checkFontsLoaded, false); } return; }, // Set things up so that at least one pdfjsFontLoad event is // dispatched when all the @font-face |rules| for |names| have been // loaded in a subdocument. It's expected that the load of |rules| // has already started in this (outer) document, so that they should // be ordered before the load in the subdocument. prepareFontLoadEvent: function(rules, names, ids) { /** Hack begin */ // There's no event when a font has finished downloading so the // following code is a dirty hack to 'guess' when a font is // ready. This code will be obsoleted by Mozilla bug 471915. // // The only reliable way to know if a font is loaded in Gecko // (at the moment) is document.onload in a document with // a @font-face rule defined in a "static" stylesheet. We use a // subdocument in an