merge upstream

This commit is contained in:
Artur Adib 2012-09-18 16:57:09 -04:00
commit 863dd0d214
15 changed files with 409 additions and 306 deletions

View File

@ -32,6 +32,7 @@ const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
const MAX_DATABASE_LENGTH = 4096;
const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
const METRO_ID = '{99bceaaa-e3c6-48c1-b981-ef9b46b67d60}';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
@ -50,7 +51,8 @@ if (appInfo.ID === FIREFOX_ID) {
privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
.getService(Ci.nsIPrivateBrowsingService);
inPrivateBrowsing = privateBrowsing.privateBrowsingEnabled;
} else if (appInfo.ID === SEAMONKEY_ID) {
} else if (appInfo.ID === SEAMONKEY_ID ||
appInfo.ID === METRO_ID) {
privateBrowsing = null;
inPrivateBrowsing = false;
}

View File

@ -51,8 +51,8 @@ thumb_page_title=Page {{page}}
thumb_page_canvas=Thumbnail of Page {{page}}
# Context menu
page_rotate_cw=Rotate Clockwise
page_rotate_ccw=Rotate Counter-Clockwise
page_rotate_cw.label=Rotate Clockwise
page_rotate_ccw.label=Rotate Counter-Clockwise
# Search panel button title and messages
search=Find

View File

@ -50,6 +50,10 @@ thumb_page_title={{page}} ページ
# number.
thumb_page_canvas=ページの縮小版 {{page}}
# Context menu
page_rotate_cw.label=右回転
page_rotate_ccw.label=左回転
# Search panel button title and messages
search=検索
search_terms_not_found=(見つかりませんでした)

View File

@ -43,3 +43,7 @@ zoom.title=Масштаб
thumb_page_title=Страница {{page}}
thumb_page_canvas=Уменьшенное изображение страницы {{page}}
request_password=PDF защищён паролем:
fullscreen.title=Полный экран
fullscreen_label=Полный экран
page_rotate_cw.label=Повернуть по часовой стрелке
page_rotate_ccw.label=Повернуть против часовой стрелки

View File

@ -1,3 +1,4 @@
# Chrome 通知欄的訊息及按鍵
unsupported_feature=本 PDF 文件可能無法正常顯示。
open_with_different_viewer=使用其他檢視器打開文件
# Chrome 通知欄的訊息及按鍵
unsupported_feature=本 PDF 文件可能無法正常顯示。
open_with_different_viewer=使用其他檢視器打開文件
open_with_different_viewer.accessKey=o

View File

@ -1,83 +1,89 @@
# 主工具列按鍵 (工具提示和圖像的替代文字)
previous.title=上一頁
previous_label=上一頁
next.title=下一頁
next_label=下一頁
# 本地化提示 (page_label, page_of):
# 這些字符串會連接成 "Page: X of Y" 的表示方式。
# 不要翻譯 "{{pageCount}}" , 因為它用來表示總頁數。
page_label=
page_of=頁, 共 {{pageCount}} 頁
zoom_out.title=縮小
zoom_out_label=縮小
zoom_in.title=放大
zoom_in_label=放大
zoom.title=縮放
print.title=列印
print_label=列印
open_file.title=開啟檔案
open_file_label=開啟
download.title=下載
download_label=下載
bookmark.title=目前檢視(複製或在新視窗中開啟)
bookmark_label=目前檢視
# 側邊欄工具列按鍵 (工具提示和圖像的替代文字)
# (_label 字符串是按鍵的替代文字, .title 字符串是工具提示)
toggle_slider.title=切換側邊欄
toggle_slider_label=切換側邊欄
outline.title=顯示文件綱要
outline_label=文件綱要
thumbs.title=顯示縮圖
thumbs_label=縮圖
search_panel.title=搜索文件
search_panel_label=搜索
# 文件綱要相關訊息
no_outline=無可用的綱要
# 縮圖面板項目 (工具提示和圖像的替代文字)
# 本地化提示 (thumb_page_title): "{{page}}" 會被頁數取代。
thumb_page_title=第 {{page}} 頁
# 本地化提示 (thumb_page_canvas): "{{page}}" 會被頁數取代。
thumb_page_canvas=第 {{page}} 頁的縮圖
# 搜尋面板按鍵文字及訊息
search=搜索
search_terms_not_found=(沒有找到)
# 錯誤面板標籤
error_more_info=更多資訊
error_less_info=更少資訊
error_close=關閉
# 本地化提示 (error_build): "{{build}}" 會被PDF.JS版本號取代。
error_build=PDF.JS 版本號: {{build}}
# 本地化提示 (error_message): "{{message}}" 會被英文的錯誤描述取代。
error_message=錯誤信息: {{message}}
# 本地化提示 (error_stack): "{{stack}}" 會被錯誤堆疊取代。
error_stack=堆疊: {{stack}}
# 本地化提示 (error_file): "{{file}}" 會被檔案名稱取代。
error_file=檔案: {{file}}
# 本地化提示 (error_line): "{{line}}" 會被行數取代。
error_line=行數: {{line}}
rendering_error=渲染頁面時發生錯誤。
# 預設的縮放值
page_scale_width=符合頁寬
page_scale_fit=符合頁面
page_scale_auto=自動縮放
page_scale_actual=實際大小
# 載入指示訊息
# 本地化提示 (error_line): "{{percent}}" 會被百分比取代。
loading=正在載入... {{percent}}%
loading_error_indicator=錯誤
loading_error=載入PDF檔案時發生錯誤。
# 其他標籤和訊息
# "{{type}}" 用來表示PDF格式規範 (32000-1:2008 Table 169 Annotation types) 入面所定義的註解種類。
# 一些常見的類型有: "Check"、 "Text"、 "Comment"、 "Note"
text_annotation_type=[{{type}} 註解]
request_password=PDF檔案受密碼保護
# 主工具列按鍵 (工具提示和圖像的替代文字)
previous.title=上一頁
previous_label=上一頁
next.title=下一頁
next_label=下一頁
# 本地化提示 (page_label, page_of):
# 這些字符串會連接成 "Page: X of Y" 的表示方式。
# 不要翻譯 "{{pageCount}}" , 因為它用來表示總頁數。
page_label=
page_of=頁,共 {{pageCount}} 頁
zoom_out.title=縮小
zoom_out_label=縮小
zoom_in.title=放大
zoom_in_label=放大
zoom.title=縮放
print.title=列印
print_label=列印
fullscreen.title=全螢幕
fullscreen_label=全螢幕
open_file.title=開啟檔案
open_file_label=開啟
download.title=下載
download_label=下載
bookmark.title=目前檢視(複製或在新視窗中開啟)
bookmark_label=目前檢視
# 側邊欄工具列按鍵 (工具提示和圖像的替代文字)
# (_label 字符串是按鍵的替代文字, .title 字符串是工具提示)
toggle_slider.title=切換側邊欄
toggle_slider_label=切換側邊欄
outline.title=顯示文件綱要
outline_label=文件綱要
thumbs.title=顯示縮圖
thumbs_label=縮圖
search_panel.title=搜索文件
search_panel_label=搜索
# 文件綱要相關訊息
no_outline=無可用的綱要
# 縮圖面板項目 (工具提示和圖像的替代文字)
# 本地化提示 (thumb_page_title): "{{page}}" 會被頁數取代。
thumb_page_title=第 {{page}} 頁
# 本地化提示 (thumb_page_canvas): "{{page}}" 會被頁數取代。
thumb_page_canvas=第 {{page}} 頁的縮圖
# 右鍵菜單
page_rotate_cw.label=順時針旋轉
page_rotate_ccw.label=逆時針旋轉
# 搜尋面板按鍵文字及訊息
search=搜索
search_terms_not_found=(沒有找到)
# 錯誤面板標籤
error_more_info=更多資訊
error_less_info=更少資訊
error_close=關閉
# 本地化提示 (error_build): "{{build}}" 會被PDF.JS版本號取代。
error_build=PDF.JS 版本號: {{build}}
# 本地化提示 (error_message): "{{message}}" 會被英文的錯誤描述取代。
error_message=錯誤信息: {{message}}
# 本地化提示 (error_stack): "{{stack}}" 會被錯誤堆疊取代。
error_stack=堆疊: {{stack}}
# 本地化提示 (error_file): "{{file}}" 會被檔案名稱取代。
error_file=檔案: {{file}}
# 本地化提示 (error_line): "{{line}}" 會被行數取代。
error_line=行數: {{line}}
rendering_error=渲染頁面時發生錯誤。
# 預設的縮放值
page_scale_width=符合頁寬
page_scale_fit=符合頁面
page_scale_auto=自動縮放
page_scale_actual=實際大小
# 載入指示訊息
loading_error_indicator=錯誤
loading_error=載入PDF檔案時發生錯誤。
# 其他標籤和訊息
# "{{type}}" 用來表示PDF格式規範 (32000-1:2008 Table 169 Annotation types) 入面所定義的註解種類。
# 一些常見的類型有: "Check"、 "Text"、 "Comment"、 "Note"
text_annotation_type={{type}} 註解]
request_password=PDF檔案受密碼保護
printing_not_supported=警告:這個瀏覽器不完全支援列印。

View File

@ -575,24 +575,15 @@ var WorkerTransport = (function WorkerTransportClosure() {
this.objs.resolve(id, imageData);
break;
case 'Font':
var name = data[2];
var file = data[3];
var properties = data[4];
if (file) {
// Rewrap the ArrayBuffer in a stream.
var fontFileDict = new Dict();
file = new Stream(file, 0, file.length, fontFileDict);
}
var exportedData = data[2];
// At this point, only the font object is created but the font is
// not yet attached to the DOM. This is done in `FontLoader.bind`.
var font;
try {
font = new Font(name, file, properties);
} catch (e) {
font = new ErrorFont(e);
}
if ('error' in exportedData)
font = new ErrorFont(exportedData.error);
else
font = new Font(exportedData);
this.objs.resolve(id, font);
break;
default:

View File

@ -596,8 +596,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
(fontObj.bold ? 'bold' : 'normal');
var italic = fontObj.italic ? 'italic' : 'normal';
var serif = fontObj.isSerifFont ? 'serif' : 'sans-serif';
var typeface = '"' + name + '", ' + serif;
var typeface = '"' + name + '", ' + fontObj.fallbackName;
// Some font backends cannot handle fonts below certain size.
// Keeping the font at minimal size and using the fontSizeScale to change
@ -782,15 +781,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
x += charWidth;
var glyphUnicode = glyph.unicode === ' ' ? '\u00A0' : glyph.unicode;
var glyphUnicodeLength = glyphUnicode.length;
//reverse an arabic ligature
if (glyphUnicodeLength > 1 &&
isRTLRangeFor(glyphUnicode.charCodeAt(0))) {
for (var ii = glyphUnicodeLength - 1; ii >= 0; ii--)
text.str += glyphUnicode[ii];
} else
text.str += glyphUnicode;
text.length += glyphUnicodeLength;
if (glyphUnicode in NormalizedUnicodes)
glyphUnicode = NormalizedUnicodes[glyphUnicode];
text.str += reverseIfRtl(glyphUnicode);
text.canvasWidth += charWidth;
}
current.x += x * textHScale2;
@ -798,7 +791,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
if (textSelection)
this.textLayer.appendText(text, font.loadedName, fontSize);
this.textLayer.appendText(text, font.fallbackName, fontSize);
return text;
},
@ -842,7 +835,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var numFakeSpaces = Math.round(-e / text.geom.spaceWidth);
if (numFakeSpaces > 0) {
text.str += '\u00A0';
text.length++;
}
}
}
@ -856,7 +848,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
text.str += shownText.str;
}
text.canvasWidth += shownText.canvasWidth;
text.length += shownText.length;
}
} else {
error('TJ array element ' + e + ' is not string or num');
@ -864,7 +855,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
if (textSelection)
this.textLayer.appendText(text, font.loadedName, fontSize);
this.textLayer.appendText(text, font.fallbackName, fontSize);
},
nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
this.nextLine();

View File

@ -26,6 +26,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
this.handler = handler;
this.uniquePrefix = uniquePrefix;
this.objIdCounter = 0;
this.fontIdCounter = 0;
}
var OP_MAP = {
@ -138,6 +139,35 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
};
PartialEvaluator.prototype = {
loadFont: function PartialEvaluator_loadFont(fontName, font, xref,
resources, dependency) {
var fontRes = resources.get('Font');
assert(fontRes, 'fontRes not available');
font = xref.fetchIfRef(font) || fontRes.get(fontName);
assertWellFormed(isDict(font));
++this.fontIdCounter;
var loadedName = font.loadedName;
if (!loadedName) {
// keep track of each font we translated so the caller can
// load them asynchronously before calling display on a page
loadedName = 'font_' + this.uniquePrefix + this.fontIdCounter;
font.loadedName = loadedName;
var translated;
try {
translated = this.translateFont(font, xref, resources,
dependency);
} catch (e) {
translated = { error: e };
}
font.translated = translated;
}
return font;
},
getOperatorList: function PartialEvaluator_getOperatorList(stream,
resources,
dependency,
@ -160,46 +190,35 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
function handleSetFont(fontName, font) {
var loadedName = null;
font = self.loadFont(fontName, font, xref, resources, dependency);
var fontRes = resources.get('Font');
var loadedName = font.loadedName;
if (!font.sent) {
var data = font.translated;
if (data.loadCharProcs) {
delete data.loadCharProcs;
assert(fontRes, 'fontRes not available');
font = xref.fetchIfRef(font) || fontRes.get(fontName);
assertWellFormed(isDict(font));
++self.objIdCounter;
if (!font.loadedName) {
font.translated = self.translateFont(font, xref, resources,
dependency);
if (font.translated) {
// keep track of each font we translated so the caller can
// load them asynchronously before calling display on a page
loadedName = 'font_' + uniquePrefix + self.objIdCounter;
font.translated.properties.loadedName = loadedName;
font.loadedName = loadedName;
var translated = font.translated;
// Convert the file to an ArrayBuffer which will be turned back into
// a Stream in the main thread.
if (translated.file)
translated.file = translated.file.getBytes();
if (translated.properties.file) {
translated.properties.file =
translated.properties.file.getBytes();
var charProcs = font.get('CharProcs').getAll();
var fontResources = font.get('Resources') || resources;
var charProcOperatorList = {};
for (var key in charProcs) {
var glyphStream = charProcs[key];
charProcOperatorList[key] =
self.getOperatorList(glyphStream, fontResources, dependency);
}
handler.send('obj', [
loadedName,
'Font',
translated.name,
translated.file,
translated.properties
]);
data.charProcOperatorList = charProcOperatorList;
}
if (data instanceof Font)
data = data.export();
handler.send('obj', [
loadedName,
'Font',
data
]);
font.sent = true;
}
loadedName = loadedName || font.loadedName;
// Ensure the font is ready before the font is set
// and later on used for drawing.
@ -492,20 +511,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var xref = this.xref;
function handleSetFont(fontName, fontRef) {
var fontRes = resources.get('Font');
// TODO: TOASK: Is it possible to get here? If so, what does
// args[0].name should be like???
assert(fontRes, 'fontRes not available');
fontRes = xref.fetchIfRef(fontRes);
fontRef = fontRef || fontRes.get(fontName);
var font = xref.fetchIfRef(fontRef), tra;
assertWellFormed(isDict(font));
if (!font.translated) {
font.translated = self.translateFont(font, xref, resources);
}
return font;
return self.loadFont(fontName, fontRef, xref, resources, null);
}
resources = xref.fetchIfRef(resources) || new Dict();
@ -522,13 +528,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var cmd = obj.cmd;
switch (cmd) {
case 'Tf':
font = handleSetFont(args[0].name);
font = handleSetFont(args[0].name).translated;
break;
case 'TJ':
var items = args[0];
for (var j = 0, jj = items.length; j < jj; j++) {
if (typeof items[j] === 'string') {
chunk += items[j];
chunk += fontCharsToUnicode(items[j], font);
} else if (items[j] < 0) {
// making all negative offsets a space - better to have
// a space in incorrect place than not have them at all
@ -537,17 +543,17 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
break;
case 'Tj':
chunk += args[0];
chunk += fontCharsToUnicode(args[0], font);
break;
case "'":
chunk += args[0] + ' ';
chunk += fontCharsToUnicode(args[0], font) + ' ';
break;
case '"':
chunk += args[2] + ' ';
chunk += fontCharsToUnicode(args[2], font) + ' ';
break;
} // switch
if (chunk !== '') {
text += fontCharsToUnicode(chunk, font.translated.properties);
text += chunk;
chunk = '';
}
@ -819,21 +825,41 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
}
// Heuristic: detection of monospace font by checking all non-zero widths
var isMonospace = true, firstWidth = defaultWidth;
for (var glyph in glyphsWidths) {
var glyphWidth = glyphsWidths[glyph];
if (!glyphWidth)
continue;
if (!firstWidth) {
firstWidth = glyphWidth;
continue;
}
if (firstWidth != glyphWidth) {
isMonospace = false;
break;
}
}
if (isMonospace)
properties.flags |= FontFlags.FixedPitch;
properties.defaultWidth = defaultWidth;
properties.widths = glyphsWidths;
},
getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
var defaultWidth = 0, widths = [];
var defaultWidth = 0, widths = [], monospace = false;
var glyphWidths = Metrics[stdFontMap[name] || name];
if (isNum(glyphWidths)) {
defaultWidth = glyphWidths;
monospace = true;
} else {
widths = glyphWidths;
}
return {
defaultWidth: defaultWidth,
monospace: monospace,
widths: widths
};
},
@ -854,7 +880,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
// - get the FontDescriptor from the descendant font
var df = dict.get('DescendantFonts');
if (!df)
return null;
error('Descendant fonts are not specified');
dict = isArray(df) ? xref.fetchIfRef(df[0]) : df;
@ -877,7 +903,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
// This case is here for compatibility.
var baseFontName = dict.get('BaseFont');
if (!isName(baseFontName))
return null;
error('Base font is not specified');
// Using base font name as a font name.
baseFontName = baseFontName.name.replace(/[,_]/g, '-');
@ -887,6 +913,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var fontNameWoStyle = baseFontName.split('-')[0];
var flags = (serifFonts[fontNameWoStyle] ||
(fontNameWoStyle.search(/serif/gi) != -1) ? FontFlags.Serif : 0) |
(metrics.monospace ? FontFlags.FixedPitch : 0) |
(symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
FontFlags.Nonsymbolic);
@ -900,11 +927,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
};
this.extractDataStructures(dict, dict, xref, properties);
return {
name: baseFontName,
dict: baseDict,
properties: properties
};
return new Font(baseFontName, null, properties);
}
}
@ -940,6 +963,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
file: fontFile,
length1: length1,
length2: length2,
loadedName: baseDict.loadedName,
composite: composite,
wideChars: composite,
fixedPitch: false,
@ -960,22 +984,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
if (type.name === 'Type3') {
properties.coded = true;
var charProcs = dict.get('CharProcs').getAll();
var fontResources = dict.get('Resources') || resources;
properties.charProcOperatorList = {};
for (var key in charProcs) {
var glyphStream = charProcs[key];
properties.charProcOperatorList[key] =
this.getOperatorList(glyphStream, fontResources, dependency);
}
}
return {
name: fontName.name,
dict: baseDict,
file: fontFile,
properties: properties
};
return new Font(fontName.name, fontFile, properties);
}
};

View File

@ -418,11 +418,26 @@ function mapPrivateUseChars(code) {
}
var FontLoader = {
//#if !(MOZCENTRAL)
loadingContext: {
requests: [],
nextRequestId: 0
},
isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() {
if (isWorker)
return false;
// User agent string sniffing is bad, but there is no reliable way to tell
// if font is fully loaded and ready to be used with canvas.
var userAgent = window.navigator.userAgent;
var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent);
if (m && m[1] >= 14)
return true;
// TODO other browsers
return false;
})(),
bind: function fontLoaderBind(fonts, callback) {
assert(!isWorker, 'bind() shall be called from main thread');
@ -437,23 +452,15 @@ var FontLoader = {
}
font.attached = true;
var str = '';
var data = font.data;
if (data) {
var length = data.length;
for (var j = 0; j < length; j++)
str += String.fromCharCode(data[j]);
var rule = font.bindDOM(str);
if (rule) {
rules.push(rule);
fontsToLoad.push(font);
}
var rule = font.bindDOM();
if (rule) {
rules.push(rule);
fontsToLoad.push(font);
}
}
var request = FontLoader.queueLoadingCallback(callback);
if (rules.length > 0) {
if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request);
} else {
request.complete();
@ -595,6 +602,22 @@ var FontLoader = {
document.body.appendChild(frame);
/** Hack end */
}
//#else
//bind: function fontLoaderBind(fonts, callback) {
// assert(!isWorker, 'bind() shall be called from main thread');
//
// for (var i = 0, ii = fonts.length; i < ii; i++) {
// var font = fonts[i];
// if (font.attached)
// continue;
//
// font.attached = true;
// font.bindDOM()
// }
//
// setTimeout(callback);
//}
//#endif
};
var UnicodeRanges = [
@ -1464,54 +1487,30 @@ var NormalizedUnicodes = {
'\uFE4F': '\u005F'
};
function fontCharsToUnicode(charCodes, fontProperties) {
var toUnicode = fontProperties.toUnicode;
var composite = fontProperties.composite;
var encoding, differences, cidToUnicode;
var result = '';
if (composite) {
cidToUnicode = fontProperties.cidToUnicode;
for (var i = 0, ii = charCodes.length; i < ii; i += 2) {
var charCode = (charCodes.charCodeAt(i) << 8) |
charCodes.charCodeAt(i + 1);
if (toUnicode && charCode in toUnicode) {
var unicode = toUnicode[charCode];
result += typeof unicode !== 'number' ? unicode :
String.fromCharCode(unicode);
continue;
}
result += String.fromCharCode(!cidToUnicode ? charCode :
cidToUnicode[charCode] || charCode);
}
} else {
differences = fontProperties.differences;
encoding = fontProperties.baseEncoding;
for (var i = 0, ii = charCodes.length; i < ii; i++) {
var charCode = charCodes.charCodeAt(i);
var unicode;
if (toUnicode && charCode in toUnicode) {
var unicode = toUnicode[charCode];
result += typeof unicode !== 'number' ? unicode :
String.fromCharCode(unicode);
continue;
}
function reverseIfRtl(chars) {
var charsLength = chars.length;
//reverse an arabic ligature
if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0)))
return chars;
var glyphName = charCode in differences ? differences[charCode] :
encoding[charCode];
if (glyphName in GlyphsUnicode) {
result += String.fromCharCode(GlyphsUnicode[glyphName]);
continue;
}
result += String.fromCharCode(charCode);
}
}
// normalizing the unicode characters
for (var i = 0, ii = result.length; i < ii; i++) {
if (!(result[i] in NormalizedUnicodes))
var s = '';
for (var ii = charsLength - 1; ii >= 0; ii--)
s += chars[ii];
return s;
}
function fontCharsToUnicode(charCodes, font) {
var glyphs = font.charsToGlyphs(charCodes);
var result = '';
for (var i = 0, ii = glyphs.length; i < ii; i++) {
var glyph = glyphs[i];
if (!glyph)
continue;
result = result.substring(0, i) + NormalizedUnicodes[result[i]] +
result.substring(i + 1);
ii = result.length;
var glyphUnicode = glyph.unicode;
if (glyphUnicode in NormalizedUnicodes)
glyphUnicode = NormalizedUnicodes[glyphUnicode];
result += reverseIfRtl(glyphUnicode);
}
return result;
}
@ -1526,9 +1525,19 @@ function fontCharsToUnicode(charCodes, fontProperties) {
*/
var Font = (function FontClosure() {
function Font(name, file, properties) {
if (arguments.length === 1) {
// importing translated data
var data = arguments[0];
for (var i in data) {
this[i] = data[i];
}
return;
}
this.name = name;
this.loadedName = properties.loadedName;
this.coded = properties.coded;
this.charProcOperatorList = properties.charProcOperatorList;
this.loadCharProcs = properties.coded;
this.sizes = [];
var names = name.split('+');
@ -1536,17 +1545,13 @@ var Font = (function FontClosure() {
names = names.split(/[-,_]/g)[0];
this.isSerifFont = !!(properties.flags & FontFlags.Serif);
this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);
var type = properties.type;
this.type = type;
// If the font is to be ignored, register it like an already loaded font
// to avoid the cost of waiting for it be be loaded by the platform.
if (properties.ignore) {
this.loadedName = this.isSerifFont ? 'serif' : 'sans-serif';
this.loading = false;
return;
}
this.fallbackName = this.isMonospace ? 'monospace' :
this.isSerifFont ? 'serif' : 'sans-serif';
this.differences = properties.differences;
this.widths = properties.widths;
@ -1632,7 +1637,6 @@ var Font = (function FontClosure() {
this.widthMultiplier = !properties.fontMatrix ? 1.0 :
1.0 / properties.fontMatrix[0];
this.encoding = properties.baseEncoding;
this.loadedName = properties.loadedName;
this.loading = true;
};
@ -2036,6 +2040,15 @@ var Font = (function FontClosure() {
mimetype: null,
encoding: null,
export: function Font_export() {
var data = {};
for (var i in this) {
if (this.hasOwnProperty(i))
data[i] = this[i];
}
return data;
},
checkAndRepair: function Font_checkAndRepair(name, font, properties) {
function readTableEntry(file) {
var tag = file.getBytes(4);
@ -3138,7 +3151,11 @@ var Font = (function FontClosure() {
}
},
bindDOM: function Font_bindDOM(data) {
bindDOM: function Font_bindDOM() {
if (!this.data)
return null;
var data = bytesToString(this.data);
var fontName = this.loadedName;
// Add the font-face rule to the document

View File

@ -26,7 +26,7 @@
// "firefox-bin: Fatal IO error 12 (Cannot allocate memory) on X server :1."
// PDFJS.disableWorker = true;
var appPath, browser, canvas, currentTaskIdx, manifest, stdout;
var appPath, browser, canvas, dummyCanvas, currentTaskIdx, manifest, stdout;
var inFlightRequests = 0;
function queryParams() {
@ -148,6 +148,46 @@ function canvasToDataURL() {
return canvas.toDataURL('image/png');
}
function NullTextLayerBuilder() {
}
NullTextLayerBuilder.prototype = {
beginLayout: function NullTextLayerBuilder_BeginLayout() {},
endLayout: function NullTextLayerBuilder_EndLayout() {},
appendText: function NullTextLayerBuilder_AppendText() {}
};
function SimpleTextLayerBuilder(ctx, viewport) {
this.ctx = ctx;
this.viewport = viewport;
}
SimpleTextLayerBuilder.prototype = {
beginLayout: function SimpleTextLayerBuilder_BeginLayout() {
this.ctx.save();
},
endLayout: function SimpleTextLayerBuilder_EndLayout() {
this.ctx.restore();
},
appendText: function SimpleTextLayerBuilder_AppendText(text, fontName,
fontSize) {
var ctx = this.ctx, viewport = this.viewport;
// vScale and hScale already contain the scaling to pixel units
var fontHeight = fontSize * text.geom.vScale;
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.fillStyle = 'yellow';
ctx.rect(text.geom.x, text.geom.y - fontHeight,
text.canvasWidth * text.geom.hScale, fontHeight);
ctx.stroke();
ctx.fill();
var textContent = bidi(text, -1);
ctx.font = fontHeight + 'px ' + fontName;
ctx.fillStyle = 'black';
ctx.fillText(textContent, text.geom.x, text.geom.y);
}
};
function nextPage(task, loadError) {
var failure = loadError || '';
@ -196,16 +236,21 @@ function nextPage(task, loadError) {
canvas.height = viewport.height;
clear(ctx);
// using the text layer builder that does nothing to test
// text layer creation operations
var textLayerBuilder = {
beginLayout: function nullTextLayerBuilderBeginLayout() {},
endLayout: function nullTextLayerBuilderEndLayout() {},
appendText: function nullTextLayerBuilderAppendText(text, fontName,
fontSize) {}
};
var drawContext, textLayerBuilder;
if (task.type == 'text') {
// using dummy canvas for pdf context drawing operations
if (!dummyCanvas) {
dummyCanvas = document.createElement('canvas');
}
drawContext = dummyCanvas.getContext('2d');
// ... text builder will draw its content on the test canvas
textLayerBuilder = new SimpleTextLayerBuilder(ctx, viewport);
} else {
drawContext = ctx;
textLayerBuilder = new NullTextLayerBuilder();
}
var renderContext = {
canvasContext: ctx,
canvasContext: drawContext,
textLayer: textLayerBuilder,
viewport: viewport
};

View File

@ -514,7 +514,7 @@ def check(task, results, browser, masterMode):
return
kind = task['type']
if 'eq' == kind:
if 'eq' == kind or 'text' == kind:
checkEq(task, results, browser, masterMode)
elif 'fbf' == kind:
checkFBF(task, results, browser)
@ -528,6 +528,7 @@ def checkEq(task, results, browser, masterMode):
pfx = os.path.join(REFDIR, sys.platform, browser, task['id'])
results = results[0]
taskId = task['id']
taskType = task['type']
passed = True
for page in xrange(len(results)):
@ -547,7 +548,7 @@ def checkEq(task, results, browser, masterMode):
eq = (ref == snapshot)
if not eq:
print 'TEST-UNEXPECTED-FAIL | eq', taskId, '| in', browser, '| rendering of page', page + 1, '!= reference rendering'
print 'TEST-UNEXPECTED-FAIL | ', taskType, taskId, '| in', browser, '| rendering of page', page + 1, '!= reference rendering'
if not State.eqLog:
State.eqLog = open(EQLOG_FILE, 'w')
@ -576,7 +577,7 @@ def checkEq(task, results, browser, masterMode):
of.close()
if passed:
print 'TEST-PASS | eq test', task['id'], '| in', browser
print 'TEST-PASS | ', taskType, ' test', task['id'], '| in', browser
def checkFBF(task, results, browser):
round0, round1 = results[0], results[1]

View File

@ -11,6 +11,12 @@
"rounds": 2,
"type": "fbf"
},
{ "id": "tracemonkey-text",
"file": "pdfs/tracemonkey.pdf",
"md5": "9a192d8b1a7dc652a19835f6f08098bd",
"rounds": 1,
"type": "text"
},
{ "id": "html5-canvas-cheat-sheet-load",
"file": "pdfs/canvas.pdf",
"md5": "59510028561daf62e00bf9f6f066b033",
@ -77,6 +83,12 @@
"rounds": 1,
"type": "load"
},
{ "id": "arabiccidtruetype-text",
"file": "pdfs/ArabicCIDTrueType.pdf",
"md5": "d66dbd18bdb572d3ac8b88b32de2ece6",
"rounds": 1,
"type": "text"
},
{ "id": "complexttffont-pdf",
"file": "pdfs/complex_ttf_font.pdf",
"md5": "76de93f9116b01b693bf8583b3e76d91",
@ -89,6 +101,12 @@
"rounds": 1,
"type": "eq"
},
{ "id": "thuluthfont-text",
"file": "pdfs/ThuluthFeatures.pdf",
"md5": "b7e18bf7a3d6a9c82aefa12d721072fc",
"rounds": 1,
"type": "text"
},
{ "id": "freeculture",
"file": "pdfs/freeculture.pdf",
"md5": "dcdf3a8268e6a18938a42d5149efcfca",
@ -263,6 +281,13 @@
"rounds": 1,
"type": "eq"
},
{ "id": "simpletype3font-text",
"file": "pdfs/simpletype3font.pdf",
"md5": "b374c7543920840c61999e9e86939f99",
"link": false,
"rounds": 1,
"type": "text"
},
{ "id": "close-path-bug",
"file": "pdfs/close-path-bug.pdf",
"md5": "48dd17ef58393857d2d038d33699cac5",

View File

@ -8,7 +8,8 @@
<style type="text/css">
body {
margin-top: 1.0em;
background-color: #482a30;
background-color: rgb(64, 64, 64);
background-image: url(web/images/texture.png);
font-family: Helvetica, Arial, FreeSans, san-serif;
color: #ffffff;
}
@ -50,20 +51,28 @@
</div>
<h2>Try it out!</h2>
<p>Live <a href="web/viewer.html">demo</a> lives here.</p>
<p>Live <a href="web/viewer.html">demo</a> or firefox <a href="https://addons.mozilla.org/en-US/firefox/addon/pdfjs/">extension</a>.</p>
<h2>Authors</h2>
<p>Vivien Nicolas (21@vingtetun.org)
<br/>Andreas Gal (andreas.gal@gmail.com)
<br/>Soumya Deb (debloper@gmail.com)
<br/>Chris Jones (jones.chris.g@gmail.com)
<br/>Justin D'Arcangelo (justindarc@gmail.com)
<br/>sbarman (sbarman@eecs.berkeley.edu)
<br/>
<br/> </p>
<h2>Contact</h2>
<p> (andreas.gal@gmail.com)
<br/> </p>
Andreas Gal (gal@mozilla.com)<br/>
Chris G Jones (cjones@mozilla.com)<br/>
Shaon Barman (shaon.barman@gmail.com)<br/>
Vivien Nicolas (21@vingtetun.org)<br/>
Justin D'Arcangelo (justindarc@gmail.com)<br/>
Yury Delendik (ydelendik@mozilla.com)<br/>
Kalervo Kujala<br/>
Adil Allawi (@ironymark)<br/>
Jakob Miland (saebekassebil@gmail.com)<br/>
Artur Adib (aadib@mozilla.com)<br/>
Brendan Dahl (bdahl@mozilla.com)<br/>
David Quintana (gigaherz@gmail.com)<br/>
Julian Viereck<br/>
<a href="https://github.com/mozilla/pdf.js/graphs/contributors">...</a>
</p>
<h2>Contact</h2>
<p> (dev-pdf-js@lists.mozilla.org)
<br/> </p>
<h2>Download</h2>

View File

@ -1843,22 +1843,18 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
while (textDivs.length > 0) {
var textDiv = textDivs.shift();
if (textDiv.dataset.textLength > 0) {
textLayerFrag.appendChild(textDiv);
textLayerFrag.appendChild(textDiv);
if (textDiv.dataset.textLength > 1) { // avoid div by zero
// Adjust div width to match canvas text
ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
var width = ctx.measureText(textDiv.textContent).width;
ctx.font = textDiv.style.fontSize + ' sans-serif';
var width = ctx.measureText(textDiv.textContent).width;
if (width > 0) {
var textScale = textDiv.dataset.canvasWidth / width;
var textScale = textDiv.dataset.canvasWidth / width;
CustomStyle.setProp('transform' , textDiv,
'scale(' + textScale + ', 1)');
CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
}
} // textLength > 0
CustomStyle.setProp('transform' , textDiv,
'scale(' + textScale + ', 1)');
CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
}
}
textLayerDiv.appendChild(textLayerFrag);
@ -1889,14 +1885,13 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
// vScale and hScale already contain the scaling to pixel units
var fontHeight = fontSize * text.geom.vScale;
textDiv.dataset.canvasWidth = text.canvasWidth * text.geom.hScale;
textDiv.dataset.fontName = fontName;
textDiv.style.fontSize = fontHeight + 'px';
textDiv.style.fontFamily = fontName;
textDiv.style.left = text.geom.x + 'px';
textDiv.style.top = (text.geom.y - fontHeight) + 'px';
textDiv.textContent = PDFJS.bidi(text, -1);
textDiv.dir = text.direction;
textDiv.dataset.textLength = text.length;
this.textDivs.push(textDiv);
};
};
@ -2065,7 +2060,7 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
});
document.getElementById('searchTermsInput').addEventListener('keydown',
function() {
function(event) {
if (event.keyCode == 13) {
PDFView.search();
}
@ -2292,6 +2287,7 @@ window.addEventListener('keydown', function keydown(evt) {
PDFView.zoomIn();
handled = true;
break;
case 173: // FF/Mac '-'
case 109: // FF '-'
case 189: // Chrome '-'
PDFView.zoomOut();