/* -*- 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 = 40000; /** * Maximum time to wait for a font to be loaded by @font-face */ var kMaxWaitForFontFace = 1000; /** * Useful for debugging when you want to certains operations depending on how * many fonts are loaded. */ var fontCount = 0; var fontName = ""; /** * If for some reason one want to debug without fonts activated, it just need * to turn this pref to true/false. */ var kDisableFonts = false; /** * 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 = Object.create(null); if (!isWorker) { var ctx = document.createElement("canvas").getContext("2d"); ctx.scale(1 / kScalePrecision, 1); } function Font(name, data, properties) { this.name = name; this.data = data; this.properties = properties; this.loading = true; this.charsCache = Object.create(null); this.sizes = []; } var current; var charsCache; var measureCache; return { registerFont: function fonts_registerFont(fontName, data, properties) { fonts[fontName] = new Font(fontName, data, properties); }, blacklistFont: function fonts_blacklistFont(fontName) { registerFont(fontName, null, {}); markLoaded(fontName); }, lookup: function fonts_lookup(fontName) { return fonts[fontName]; }, setActive: function fonts_setActive(fontName, size) { // |current| can be null is fontName is a built-in font // (e.g. "sans-serif") if ((current = fonts[fontName])) { charsCache = current.charsCache; var sizes = current.sizes; if (!(measureCache = sizes[size])) measureCache = sizes[size] = Object.create(null); } ctx.font = (size * kScalePrecision) + 'px "' + fontName + '"'; }, charsToUnicode: function fonts_chars2Unicode(chars) { if (!charsCache) return chars; // if we translated this string before, just grab it from the cache var str = charsCache[chars]; if (str) return str; // translate the string using the font's encoding var encoding = current ? current.properties.encoding : null; if (!encoding) return chars; str = ""; for (var i = 0; i < chars.length; ++i) { var charcode = chars.charCodeAt(i); var unicode = encoding[charcode]; // Check if the glyph has already been converted if (!IsNum(unicode)) unicode = encoding[unicode] = GlyphsUnicode[unicode.name]; // 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; }, 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 < fonts.length; i++) { var font = fonts[i]; if (Fonts.lookup(font.name).loading) { return false; } } document.documentElement.removeEventListener( "pdfjsFontLoad", checkFontsLoaded, false); callback(); return true; } var rules = [ ], names = [ ]; for (var i = 0; i < fonts.length; i++) { var font = fonts[i]; if (!Fonts.lookup(font.name)) { var obj = new Font(font.name, font.file, font.properties); var str = ""; var data = Fonts.lookup(font.name).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(font.name); } } } if (!isWorker && rules.length) { FontLoader.prepareFontLoadEvent(rules, names); } 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) { /** 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