Merge branch 'master' of gitorious.org:owncloud/owncloud

This commit is contained in:
Tom Needham 2012-04-15 14:02:13 +00:00
commit fef3434bdf
41 changed files with 15914 additions and 4857 deletions

View File

@ -3,7 +3,7 @@ var bookmarks_loading = false;
var bookmarks_sorting = 'bookmarks_sorting_recent'; var bookmarks_sorting = 'bookmarks_sorting_recent';
$(document).ready(function() { $(document).ready(function() {
$('#bookmark_add_submit').click(addOrEditBookmark); $('#bookmark_add_submit').click(addOrEditBookmark);
$(window).resize(function () { $(window).resize(function () {
fillWindow($('.bookmarks_list')); fillWindow($('.bookmarks_list'));
@ -18,10 +18,10 @@ function getBookmarks() {
//have patience :) //have patience :)
return; return;
} }
$.ajax({ $.ajax({
url: 'ajax/updateList.php', url: 'ajax/updateList.php',
data: 'tag=' + encodeURI($('#bookmarkFilterTag').val()) + '&page=' + bookmarks_page + '&sort=' + bookmarks_sorting, data: 'tag=' + encodeURIComponent($('#bookmarkFilterTag').val()) + '&page=' + bookmarks_page + '&sort=' + bookmarks_sorting,
success: function(bookmarks){ success: function(bookmarks){
if (bookmarks.data.length) { if (bookmarks.data.length) {
bookmarks_page += 1; bookmarks_page += 1;
@ -29,7 +29,7 @@ function getBookmarks() {
$('.bookmark_link').unbind('click', recordClick); $('.bookmark_link').unbind('click', recordClick);
$('.bookmark_delete').unbind('click', delBookmark); $('.bookmark_delete').unbind('click', delBookmark);
$('.bookmark_edit').unbind('click', showBookmark); $('.bookmark_edit').unbind('click', showBookmark);
for(var i in bookmarks.data) { for(var i in bookmarks.data) {
updateBookmarksList(bookmarks.data[i]); updateBookmarksList(bookmarks.data[i]);
$("#firstrun").hide(); $("#firstrun").hide();
@ -41,13 +41,13 @@ function getBookmarks() {
$('.bookmark_link').click(recordClick); $('.bookmark_link').click(recordClick);
$('.bookmark_delete').click(delBookmark); $('.bookmark_delete').click(delBookmark);
$('.bookmark_edit').click(showBookmark); $('.bookmark_edit').click(showBookmark);
bookmarks_loading = false; bookmarks_loading = false;
if (bookmarks.data.length) { if (bookmarks.data.length) {
updateOnBottom() updateOnBottom()
} }
} }
}); });
} }
// function addBookmark() { // function addBookmark() {
@ -60,13 +60,13 @@ function addOrEditBookmark(event) {
var title = encodeEntities($('#bookmark_add_title').val()); var title = encodeEntities($('#bookmark_add_title').val());
var tags = encodeEntities($('#bookmark_add_tags').val()); var tags = encodeEntities($('#bookmark_add_tags').val());
$("#firstrun").hide(); $("#firstrun").hide();
if (id == 0) { if (id == 0) {
$.ajax({ $.ajax({
url: 'ajax/addBookmark.php', url: 'ajax/addBookmark.php',
data: 'url=' + encodeURI(url) + '&title=' + encodeURI(title) + '&tags=' + encodeURI(tags), data: 'url=' + encodeURIComponent(url) + '&title=' + encodeURIComponent(title) + '&tags=' + encodeURIComponent(tags),
success: function(response){ success: function(response){
$('.bookmarks_input').val(''); $('.bookmarks_input').val('');
$('.bookmarks_list').empty(); $('.bookmarks_list').empty();
bookmarks_page = 0; bookmarks_page = 0;
getBookmarks(); getBookmarks();
@ -76,8 +76,8 @@ function addOrEditBookmark(event) {
else { else {
$.ajax({ $.ajax({
url: 'ajax/editBookmark.php', url: 'ajax/editBookmark.php',
data: 'id=' + id + '&url=' + encodeURI(url) + '&title=' + encodeURI(title) + '&tags=' + encodeURI(tags), data: 'id=' + id + '&url=' + encodeURIComponent(url) + '&title=' + encodeURIComponent(title) + '&tags=' + encodeURIComponent(tags),
success: function(){ success: function(){
$('.bookmarks_input').val(''); $('.bookmarks_input').val('');
$('#bookmark_add_id').val('0'); $('#bookmark_add_id').val('0');
$('.bookmarks_list').empty(); $('.bookmarks_list').empty();
@ -86,14 +86,14 @@ function addOrEditBookmark(event) {
} }
}); });
} }
} }
function delBookmark(event) { function delBookmark(event) {
var record = $(this).parent().parent(); var record = $(this).parent().parent();
$.ajax({ $.ajax({
url: 'ajax/delBookmark.php', url: 'ajax/delBookmark.php',
data: 'url=' + encodeURI($(this).parent().parent().children('.bookmark_url:first').text()), data: 'url=' + encodeURIComponent($(this).parent().parent().children('.bookmark_url:first').text()),
success: function(data){ success: function(data){
record.remove(); record.remove();
if($('.bookmarks_list').is(':empty')) { if($('.bookmarks_list').is(':empty')) {
@ -109,7 +109,7 @@ function showBookmark(event) {
$('#bookmark_add_url').val(record.children('.bookmark_url:first').text()); $('#bookmark_add_url').val(record.children('.bookmark_url:first').text());
$('#bookmark_add_title').val(record.children('.bookmark_title:first').text()); $('#bookmark_add_title').val(record.children('.bookmark_title:first').text());
$('#bookmark_add_tags').val(record.children('.bookmark_tags:first').text()); $('#bookmark_add_tags').val(record.children('.bookmark_tags:first').text());
if ($('.bookmarks_add').css('display') == 'none') { if ($('.bookmarks_add').css('display') == 'none') {
$('.bookmarks_add').slideToggle(); $('.bookmarks_add').slideToggle();
} }
@ -124,7 +124,7 @@ function updateBookmarksList(bookmark) {
var taglist = ''; var taglist = '';
for ( var i=0, len=tags.length; i<len; ++i ){ for ( var i=0, len=tags.length; i<len; ++i ){
if(tags[i] != '') if(tags[i] != '')
taglist = taglist + '<a class="bookmark_tag" href="?tag=' + encodeURI(tags[i]) + '">' + tags[i] + '</a> '; taglist = taglist + '<a class="bookmark_tag" href="?tag=' + encodeURIComponent(tags[i]) + '">' + tags[i] + '</a> ';
} }
if(!hasProtocol(bookmark.url)) { if(!hasProtocol(bookmark.url)) {
bookmark.url = 'http://' + bookmark.url; bookmark.url = 'http://' + bookmark.url;
@ -165,8 +165,8 @@ function updateOnBottom() {
function recordClick(event) { function recordClick(event) {
$.ajax({ $.ajax({
url: 'ajax/recordClick.php', url: 'ajax/recordClick.php',
data: 'url=' + encodeURI($(this).attr('href')), data: 'url=' + encodeURIComponent($(this).attr('href')),
}); });
} }
function encodeEntities(s){ function encodeEntities(s){

10044
apps/files_pdfviewer/js/pdfjs/build/pdf.js Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,432 @@
/* -*- 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 bidi = PDFJS.bidi = (function bidiClosure() {
// Character types for symbols from 0000 to 00FF.
var baseTypes = [
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS',
'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON',
'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN',
'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON',
'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON',
'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN',
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON',
'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON',
'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
];
// Character types for symbols from 0600 to 06FF
var arabicTypes = [
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN',
'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM',
'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
];
function isOdd(i) {
return (i & 1) != 0;
}
function isEven(i) {
return (i & 1) == 0;
}
function findUnequal(arr, start, value) {
var j;
for (var j = start, jj = arr.length; j < jj; ++j) {
if (arr[j] != value)
return j;
}
return j;
}
function setValues(arr, start, end, value) {
for (var j = start; j < end; ++j) {
arr[j] = value;
}
}
function reverseValues(arr, start, end) {
for (var i = start, j = end - 1; i < j; ++i, --j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
function mirrorGlyphs(c) {
/*
# BidiMirroring-1.txt
0028; 0029 # LEFT PARENTHESIS
0029; 0028 # RIGHT PARENTHESIS
003C; 003E # LESS-THAN SIGN
003E; 003C # GREATER-THAN SIGN
005B; 005D # LEFT SQUARE BRACKET
005D; 005B # RIGHT SQUARE BRACKET
007B; 007D # LEFT CURLY BRACKET
007D; 007B # RIGHT CURLY BRACKET
00AB; 00BB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
00BB; 00AB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
*/
switch (c) {
case '(':
return ')';
case ')':
return '(';
case '<':
return '>';
case '>':
return '<';
case ']':
return '[';
case '[':
return ']';
case '}':
return '{';
case '{':
return '}';
case '\u00AB':
return '\u00BB';
case '\u00BB':
return '\u00AB';
default:
return c;
}
}
function bidi(text, startLevel) {
var str = text.str;
var strLength = str.length;
if (strLength == 0)
return str;
// get types, fill arrays
var chars = [];
var types = [];
var oldtypes = [];
var numBidi = 0;
for (var i = 0; i < strLength; ++i) {
chars[i] = str.charAt(i);
var charCode = str.charCodeAt(i);
var charType = 'L';
if (charCode <= 0x00ff)
charType = baseTypes[charCode];
else if (0x0590 <= charCode && charCode <= 0x05f4)
charType = 'R';
else if (0x0600 <= charCode && charCode <= 0x06ff)
charType = arabicTypes[charCode & 0xff];
else if (0x0700 <= charCode && charCode <= 0x08AC)
charType = 'AL';
if (charType == 'R' || charType == 'AL' || charType == 'AN')
numBidi++;
oldtypes[i] = types[i] = charType;
}
// detect the bidi method
// if there are no rtl characters then no bidi needed
// if less than 30% chars are rtl then string is primarily ltr
// if more than 30% chars are rtl then string is primarily rtl
if (numBidi == 0) {
text.direction = 'ltr';
return str;
}
if (startLevel == -1) {
if ((strLength / numBidi) < 0.3) {
text.direction = 'ltr';
startLevel = 0;
} else {
text.direction = 'rtl';
startLevel = 1;
}
}
var levels = [];
for (var i = 0; i < strLength; ++i) {
levels[i] = startLevel;
}
/*
X1-X10: skip most of this, since we are NOT doing the embeddings.
*/
var e = isOdd(startLevel) ? 'R' : 'L';
var sor = e;
var eor = sor;
/*
W1. Examine each non-spacing mark (NSM) in the level run, and change the
type of the NSM to the type of the previous character. If the NSM is at the
start of the level run, it will get the type of sor.
*/
var lastType = sor;
for (var i = 0; i < strLength; ++i) {
if (types[i] == 'NSM')
types[i] = lastType;
else
lastType = types[i];
}
/*
W2. Search backwards from each instance of a European number until the
first strong type (R, L, AL, or sor) is found. If an AL is found, change
the type of the European number to Arabic number.
*/
var lastType = sor;
for (var i = 0; i < strLength; ++i) {
var t = types[i];
if (t == 'EN')
types[i] = (lastType == 'AL') ? 'AN' : 'EN';
else if (t == 'R' || t == 'L' || t == 'AL')
lastType = t;
}
/*
W3. Change all ALs to R.
*/
for (var i = 0; i < strLength; ++i) {
var t = types[i];
if (t == 'AL')
types[i] = 'R';
}
/*
W4. A single European separator between two European numbers changes to a
European number. A single common separator between two numbers of the same
type changes to that type:
*/
for (var i = 1; i < strLength - 1; ++i) {
if (types[i] == 'ES' && types[i - 1] == 'EN' && types[i + 1] == 'EN')
types[i] = 'EN';
if (types[i] == 'CS' && (types[i - 1] == 'EN' || types[i - 1] == 'AN') &&
types[i + 1] == types[i - 1])
types[i] = types[i - 1];
}
/*
W5. A sequence of European terminators adjacent to European numbers changes
to all European numbers:
*/
for (var i = 0; i < strLength; ++i) {
if (types[i] == 'EN') {
// do before
for (var j = i - 1; j >= 0; --j) {
if (types[j] != 'ET')
break;
types[j] = 'EN';
}
// do after
for (var j = i + 1; j < strLength; --j) {
if (types[j] != 'ET')
break;
types[j] = 'EN';
}
}
}
/*
W6. Otherwise, separators and terminators change to Other Neutral:
*/
for (var i = 0; i < strLength; ++i) {
var t = types[i];
if (t == 'WS' || t == 'ES' || t == 'ET' || t == 'CS')
types[i] = 'ON';
}
/*
W7. Search backwards from each instance of a European number until the
first strong type (R, L, or sor) is found. If an L is found, then change
the type of the European number to L.
*/
var lastType = sor;
for (var i = 0; i < strLength; ++i) {
var t = types[i];
if (t == 'EN')
types[i] = (lastType == 'L') ? 'L' : 'EN';
else if (t == 'R' || t == 'L')
lastType = t;
}
/*
N1. A sequence of neutrals takes the direction of the surrounding strong
text if the text on both sides has the same direction. European and Arabic
numbers are treated as though they were R. Start-of-level-run (sor) and
end-of-level-run (eor) are used at level run boundaries.
*/
for (var i = 0; i < strLength; ++i) {
if (types[i] == 'ON') {
var end = findUnequal(types, i + 1, 'ON');
var before = sor;
if (i > 0)
before = types[i - 1];
var after = eor;
if (end + 1 < strLength)
after = types[end + 1];
if (before != 'L')
before = 'R';
if (after != 'L')
after = 'R';
if (before == after)
setValues(types, i, end, before);
i = end - 1; // reset to end (-1 so next iteration is ok)
}
}
/*
N2. Any remaining neutrals take the embedding direction.
*/
for (var i = 0; i < strLength; ++i) {
if (types[i] == 'ON')
types[i] = e;
}
/*
I1. For all characters with an even (left-to-right) embedding direction,
those of type R go up one level and those of type AN or EN go up two
levels.
I2. For all characters with an odd (right-to-left) embedding direction,
those of type L, EN or AN go up one level.
*/
for (var i = 0; i < strLength; ++i) {
var t = types[i];
if (isEven(levels[i])) {
if (t == 'R') {
levels[i] += 1;
} else if (t == 'AN' || t == 'EN') {
levels[i] += 2;
}
} else { // isOdd, so
if (t == 'L' || t == 'AN' || t == 'EN') {
levels[i] += 1;
}
}
}
/*
L1. On each line, reset the embedding level of the following characters to
the paragraph embedding level:
segment separators,
paragraph separators,
any sequence of whitespace characters preceding a segment separator or
paragraph separator, and any sequence of white space characters at the end
of the line.
*/
// don't bother as text is only single line
/*
L2. From the highest level found in the text to the lowest odd level on
each line, reverse any contiguous sequence of characters that are at that
level or higher.
*/
// find highest level & lowest odd level
var highestLevel = -1;
var lowestOddLevel = 99;
for (var i = 0, ii = levels.length; i < ii; ++i) {
var level = levels[i];
if (highestLevel < level)
highestLevel = level;
if (lowestOddLevel > level && isOdd(level))
lowestOddLevel = level;
}
// now reverse between those limits
for (var level = highestLevel; level >= lowestOddLevel; --level) {
// find segments to reverse
var start = -1;
for (var i = 0, ii = levels.length; i < ii; ++i) {
if (levels[i] < level) {
if (start >= 0) {
reverseValues(chars, start, i);
start = -1;
}
} else if (start < 0) {
start = i;
}
}
if (start >= 0) {
reverseValues(chars, start, levels.length);
}
}
/*
L3. Combining marks applied to a right-to-left base character will at this
point precede their base character. If the rendering engine expects them to
follow the base characters in the final display process, then the ordering
of the marks and the base character must be reversed.
*/
// don't bother for now
/*
L4. A character that possesses the mirrored property as specified by
Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved
directionality of that character is R.
*/
// don't mirror as characters are already mirrored in the pdf
// Finally, return string
var result = '';
for (var i = 0, ii = chars.length; i < ii; ++i) {
var ch = chars[i];
if (ch != '<' && ch != '>')
result += ch;
}
return result;
}
return bidi;
})();

784
apps/files_pdfviewer/js/pdfjs/src/canvas.js Executable file → Normal file

File diff suppressed because it is too large Load Diff

0
apps/files_pdfviewer/js/pdfjs/src/charsets.js Executable file → Normal file
View File

0
apps/files_pdfviewer/js/pdfjs/src/cidmaps.js Executable file → Normal file
View File

311
apps/files_pdfviewer/js/pdfjs/src/colorspace.js Executable file → Normal file
View File

@ -3,34 +3,34 @@
'use strict'; 'use strict';
var ColorSpace = (function colorSpaceColorSpace() { var ColorSpace = (function ColorSpaceClosure() {
// Constructor should define this.numComps, this.defaultColor, this.name // Constructor should define this.numComps, this.defaultColor, this.name
function constructor() { function ColorSpace() {
error('should not call ColorSpace constructor'); error('should not call ColorSpace constructor');
} }
constructor.prototype = { ColorSpace.prototype = {
// Input: array of size numComps representing color component values // Input: array of size numComps representing color component values
// Output: array of rgb values, each value ranging from [0.1] // Output: array of rgb values, each value ranging from [0.1]
getRgb: function colorSpaceGetRgb(color) { getRgb: function ColorSpace_getRgb(color) {
error('Should not call ColorSpace.getRgb: ' + color); error('Should not call ColorSpace.getRgb: ' + color);
}, },
// Input: Uint8Array of component values, each value scaled to [0,255] // Input: Uint8Array of component values, each value scaled to [0,255]
// Output: Uint8Array of rgb values, each value scaled to [0,255] // Output: Uint8Array of rgb values, each value scaled to [0,255]
getRgbBuffer: function colorSpaceGetRgbBuffer(input) { getRgbBuffer: function ColorSpace_getRgbBuffer(input) {
error('Should not call ColorSpace.getRgbBuffer: ' + input); error('Should not call ColorSpace.getRgbBuffer: ' + input);
} }
}; };
constructor.parse = function colorSpaceParse(cs, xref, res) { ColorSpace.parse = function ColorSpace_parse(cs, xref, res) {
var IR = constructor.parseToIR(cs, xref, res); var IR = ColorSpace.parseToIR(cs, xref, res);
if (IR instanceof AlternateCS) if (IR instanceof AlternateCS)
return IR; return IR;
return constructor.fromIR(IR); return ColorSpace.fromIR(IR);
}; };
constructor.fromIR = function colorSpaceFromIR(IR) { ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
var name = isArray(IR) ? IR[0] : IR; var name = isArray(IR) ? IR[0] : IR;
switch (name) { switch (name) {
@ -57,15 +57,20 @@ var ColorSpace = (function colorSpaceColorSpace() {
return new AlternateCS(numComps, ColorSpace.fromIR(alt), return new AlternateCS(numComps, ColorSpace.fromIR(alt),
PDFFunction.fromIR(tintFnIR)); PDFFunction.fromIR(tintFnIR));
case 'LabCS':
var whitePoint = IR[1].WhitePoint;
var blackPoint = IR[1].BlackPoint;
var range = IR[1].Range;
return new LabCS(whitePoint, blackPoint, range);
default: default:
error('Unkown name ' + name); error('Unkown name ' + name);
} }
return null; return null;
}; };
constructor.parseToIR = function colorSpaceParseToIR(cs, xref, res) { ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) {
if (isName(cs)) { if (isName(cs)) {
var colorSpaces = xref.fetchIfRef(res.get('ColorSpace')); var colorSpaces = res.get('ColorSpace');
if (isDict(colorSpaces)) { if (isDict(colorSpaces)) {
var refcs = colorSpaces.get(cs.name); var refcs = colorSpaces.get(cs.name);
if (refcs) if (refcs)
@ -130,6 +135,7 @@ var ColorSpace = (function colorSpaceColorSpace() {
basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res); basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
return ['PatternCS', basePatternCS]; return ['PatternCS', basePatternCS];
case 'Indexed': case 'Indexed':
case 'I':
var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res); var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
var hiVal = cs[2] + 1; var hiVal = cs[2] + 1;
var lookup = xref.fetchIfRef(cs[3]); var lookup = xref.fetchIfRef(cs[3]);
@ -146,6 +152,8 @@ var ColorSpace = (function colorSpaceColorSpace() {
var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3])); var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3]));
return ['AlternateCS', numComps, alt, tintFnIR]; return ['AlternateCS', numComps, alt, tintFnIR];
case 'Lab': case 'Lab':
var params = cs[1].getAll();
return ['LabCS', params];
default: default:
error('unimplemented color space object "' + mode + '"'); error('unimplemented color space object "' + mode + '"');
} }
@ -154,8 +162,31 @@ var ColorSpace = (function colorSpaceColorSpace() {
} }
return null; return null;
}; };
/**
* Checks if a decode map matches the default decode map for a color space.
* This handles the general decode maps where there are two values per
* component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
* This does not handle Lab, Indexed, or Pattern decode maps since they are
* slightly different.
* @param {Array} decode Decode map (usually from an image).
* @param {Number} n Number of components the color space has.
*/
ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) {
if (!decode)
return true;
return constructor; if (n * 2 !== decode.length) {
warning('The decode map is not the correct length');
return true;
}
for (var i = 0, ii = decode.length; i < ii; i += 2) {
if (decode[i] != 0 || decode[i + 1] != 1)
return false;
}
return true;
};
return ColorSpace;
})(); })();
/** /**
@ -164,8 +195,8 @@ var ColorSpace = (function colorSpaceColorSpace() {
* Both color spaces use a tinting function to convert colors to a base color * Both color spaces use a tinting function to convert colors to a base color
* space. * space.
*/ */
var AlternateCS = (function alternateCS() { var AlternateCS = (function AlternateCSClosure() {
function constructor(numComps, base, tintFn) { function AlternateCS(numComps, base, tintFn) {
this.name = 'Alternate'; this.name = 'Alternate';
this.numComps = numComps; this.numComps = numComps;
this.defaultColor = []; this.defaultColor = [];
@ -175,12 +206,12 @@ var AlternateCS = (function alternateCS() {
this.tintFn = tintFn; this.tintFn = tintFn;
} }
constructor.prototype = { AlternateCS.prototype = {
getRgb: function altcs_getRgb(color) { getRgb: function AlternateCS_getRgb(color) {
var tinted = this.tintFn(color); var tinted = this.tintFn(color);
return this.base.getRgb(tinted); return this.base.getRgb(tinted);
}, },
getRgbBuffer: function altcs_getRgbBuffer(input, bits) { getRgbBuffer: function AlternateCS_getRgbBuffer(input, bits) {
var tintFn = this.tintFn; var tintFn = this.tintFn;
var base = this.base; var base = this.base;
var scale = 1 / ((1 << bits) - 1); var scale = 1 / ((1 << bits) - 1);
@ -189,7 +220,7 @@ var AlternateCS = (function alternateCS() {
var baseNumComps = base.numComps; var baseNumComps = base.numComps;
var baseBuf = new Uint8Array(baseNumComps * length); var baseBuf = new Uint8Array(baseNumComps * length);
var numComps = this.numComps; var numComps = this.numComps;
var scaled = new Array(numComps); var scaled = [];
for (var i = 0; i < length; i += numComps) { for (var i = 0; i < length; i += numComps) {
for (var z = 0; z < numComps; ++z) for (var z = 0; z < numComps; ++z)
@ -200,24 +231,27 @@ var AlternateCS = (function alternateCS() {
baseBuf[pos++] = 255 * tinted[j]; baseBuf[pos++] = 255 * tinted[j];
} }
return base.getRgbBuffer(baseBuf, 8); return base.getRgbBuffer(baseBuf, 8);
},
isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
} }
}; };
return constructor; return AlternateCS;
})(); })();
var PatternCS = (function patternCS() { var PatternCS = (function PatternCSClosure() {
function constructor(baseCS) { function PatternCS(baseCS) {
this.name = 'Pattern'; this.name = 'Pattern';
this.base = baseCS; this.base = baseCS;
} }
constructor.prototype = {}; PatternCS.prototype = {};
return constructor; return PatternCS;
})(); })();
var IndexedCS = (function indexedCS() { var IndexedCS = (function IndexedCSClosure() {
function constructor(base, highVal, lookup) { function IndexedCS(base, highVal, lookup) {
this.name = 'Indexed'; this.name = 'Indexed';
this.numComps = 1; this.numComps = 1;
this.defaultColor = [0]; this.defaultColor = [0];
@ -240,8 +274,8 @@ var IndexedCS = (function indexedCS() {
this.lookup = lookupArray; this.lookup = lookupArray;
} }
constructor.prototype = { IndexedCS.prototype = {
getRgb: function indexcs_getRgb(color) { getRgb: function IndexedCS_getRgb(color) {
var numComps = this.base.numComps; var numComps = this.base.numComps;
var start = color[0] * numComps; var start = color[0] * numComps;
var c = []; var c = [];
@ -251,7 +285,7 @@ var IndexedCS = (function indexedCS() {
return this.base.getRgb(c); return this.base.getRgb(c);
}, },
getRgbBuffer: function indexcs_getRgbBuffer(input) { getRgbBuffer: function IndexedCS_getRgbBuffer(input) {
var base = this.base; var base = this.base;
var numComps = base.numComps; var numComps = base.numComps;
var lookup = this.lookup; var lookup = this.lookup;
@ -267,24 +301,28 @@ var IndexedCS = (function indexedCS() {
} }
return base.getRgbBuffer(baseBuf, 8); return base.getRgbBuffer(baseBuf, 8);
},
isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
// indexed color maps shouldn't be changed
return true;
} }
}; };
return constructor; return IndexedCS;
})(); })();
var DeviceGrayCS = (function deviceGrayCS() { var DeviceGrayCS = (function DeviceGrayCSClosure() {
function constructor() { function DeviceGrayCS() {
this.name = 'DeviceGray'; this.name = 'DeviceGray';
this.numComps = 1; this.numComps = 1;
this.defaultColor = [0]; this.defaultColor = [0];
} }
constructor.prototype = { DeviceGrayCS.prototype = {
getRgb: function graycs_getRgb(color) { getRgb: function DeviceGrayCS_getRgb(color) {
var c = color[0]; var c = color[0];
return [c, c, c]; return [c, c, c];
}, },
getRgbBuffer: function graycs_getRgbBuffer(input, bits) { getRgbBuffer: function DeviceGrayCS_getRgbBuffer(input, bits) {
var scale = 255 / ((1 << bits) - 1); var scale = 255 / ((1 << bits) - 1);
var length = input.length; var length = input.length;
var rgbBuf = new Uint8Array(length * 3); var rgbBuf = new Uint8Array(length * 3);
@ -295,22 +333,25 @@ var DeviceGrayCS = (function deviceGrayCS() {
rgbBuf[j++] = c; rgbBuf[j++] = c;
} }
return rgbBuf; return rgbBuf;
},
isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
} }
}; };
return constructor; return DeviceGrayCS;
})(); })();
var DeviceRgbCS = (function deviceRgbCS() { var DeviceRgbCS = (function DeviceRgbCSClosure() {
function constructor() { function DeviceRgbCS() {
this.name = 'DeviceRGB'; this.name = 'DeviceRGB';
this.numComps = 3; this.numComps = 3;
this.defaultColor = [0, 0, 0]; this.defaultColor = [0, 0, 0];
} }
constructor.prototype = { DeviceRgbCS.prototype = {
getRgb: function rgbcs_getRgb(color) { getRgb: function DeviceRgbCS_getRgb(color) {
return color; return color;
}, },
getRgbBuffer: function rgbcs_getRgbBuffer(input, bits) { getRgbBuffer: function DeviceRgbCS_getRgbBuffer(input, bits) {
if (bits == 8) if (bits == 8)
return input; return input;
var scale = 255 / ((1 << bits) - 1); var scale = 255 / ((1 << bits) - 1);
@ -319,73 +360,37 @@ var DeviceRgbCS = (function deviceRgbCS() {
for (i = 0; i < length; ++i) for (i = 0; i < length; ++i)
rgbBuf[i] = (scale * input[i]) | 0; rgbBuf[i] = (scale * input[i]) | 0;
return rgbBuf; return rgbBuf;
},
isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
} }
}; };
return constructor; return DeviceRgbCS;
})(); })();
var DeviceCmykCS = (function deviceCmykCS() { var DeviceCmykCS = (function DeviceCmykCSClosure() {
function constructor() { function DeviceCmykCS() {
this.name = 'DeviceCMYK'; this.name = 'DeviceCMYK';
this.numComps = 4; this.numComps = 4;
this.defaultColor = [0, 0, 0, 1]; this.defaultColor = [0, 0, 0, 1];
} }
constructor.prototype = { DeviceCmykCS.prototype = {
getRgb: function cmykcs_getRgb(color) { getRgb: function DeviceCmykCS_getRgb(color) {
var c = color[0], m = color[1], y = color[2], k = color[3]; var c = color[0], m = color[1], y = color[2], k = color[3];
var c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k;
var x, r, g, b; // CMYK -> CMY: http://www.easyrgb.com/index.php?X=MATH&H=14#text14
// this is a matrix multiplication, unrolled for performance c = (c * (1 - k) + k);
// code is taken from the poppler implementation m = (m * (1 - k) + k);
x = c1 * m1 * y1 * k1; // 0 0 0 0 y = (y * (1 - k) + k);
r = g = b = x;
x = c1 * m1 * y1 * k; // 0 0 0 1 // CMY -> RGB: http://www.easyrgb.com/index.php?X=MATH&H=12#text12
r += 0.1373 * x; var r = (1 - c);
g += 0.1216 * x; var g = (1 - m);
b += 0.1255 * x; var b = (1 - y);
x = c1 * m1 * y * k1; // 0 0 1 0
r += x;
g += 0.9490 * x;
x = c1 * m1 * y * k; // 0 0 1 1
r += 0.1098 * x;
g += 0.1020 * x;
x = c1 * m * y1 * k1; // 0 1 0 0
r += 0.9255 * x;
b += 0.5490 * x;
x = c1 * m * y1 * k; // 0 1 0 1
r += 0.1412 * x;
x = c1 * m * y * k1; // 0 1 1 0
r += 0.9294 * x;
g += 0.1098 * x;
b += 0.1412 * x;
x = c1 * m * y * k; // 0 1 1 1
r += 0.1333 * x;
x = c * m1 * y1 * k1; // 1 0 0 0
g += 0.6784 * x;
b += 0.9373 * x;
x = c * m1 * y1 * k; // 1 0 0 1
g += 0.0588 * x;
b += 0.1412 * x;
x = c * m1 * y * k1; // 1 0 1 0
g += 0.6510 * x;
b += 0.3137 * x;
x = c * m1 * y * k; // 1 0 1 1
g += 0.0745 * x;
x = c * m * y1 * k1; // 1 1 0 0
r += 0.1804 * x;
g += 0.1922 * x;
b += 0.5725 * x;
x = c * m * y1 * k; // 1 1 0 1
b += 0.0078 * x;
x = c * m * y * k1; // 1 1 1 0
r += 0.2118 * x;
g += 0.2119 * x;
b += 0.2235 * x;
return [r, g, b]; return [r, g, b];
}, },
getRgbBuffer: function cmykcs_getRgbBuffer(colorBuf, bits) { getRgbBuffer: function DeviceCmykCS_getRgbBuffer(colorBuf, bits) {
var scale = 1 / ((1 << bits) - 1); var scale = 1 / ((1 << bits) - 1);
var length = colorBuf.length / 4; var length = colorBuf.length / 4;
var rgbBuf = new Uint8Array(length * 3); var rgbBuf = new Uint8Array(length * 3);
@ -403,9 +408,125 @@ var DeviceCmykCS = (function deviceCmykCS() {
} }
return rgbBuf; return rgbBuf;
},
isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
} }
}; };
return constructor; return DeviceCmykCS;
})(); })();
//
// LabCS: Based on "PDF Reference, Sixth Ed", p.250
//
var LabCS = (function LabCSClosure() {
function LabCS(whitePoint, blackPoint, range) {
this.name = 'Lab';
this.numComps = 3;
this.defaultColor = [0, 0, 0];
if (!whitePoint)
error('WhitePoint missing - required for color space Lab');
blackPoint = blackPoint || [0, 0, 0];
range = range || [-100, 100, -100, 100];
// Translate args to spec variables
this.XW = whitePoint[0];
this.YW = whitePoint[1];
this.ZW = whitePoint[2];
this.amin = range[0];
this.amax = range[1];
this.bmin = range[2];
this.bmax = range[3];
// These are here just for completeness - the spec doesn't offer any
// formulas that use BlackPoint in Lab
this.XB = blackPoint[0];
this.YB = blackPoint[1];
this.ZB = blackPoint[2];
// Validate vars as per spec
if (this.XW < 0 || this.ZW < 0 || this.YW !== 1)
error('Invalid WhitePoint components, no fallback available');
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
warn('Invalid BlackPoint, falling back to default');
this.XB = this.YB = this.ZB = 0;
}
if (this.amin > this.amax || this.bmin > this.bmax) {
warn('Invalid Range, falling back to defaults');
this.amin = -100;
this.amax = 100;
this.bmin = -100;
this.bmax = 100;
}
};
// Function g(x) from spec
function g(x) {
if (x >= 6 / 29)
return x * x * x;
else
return (108 / 841) * (x - 4 / 29);
}
LabCS.prototype = {
getRgb: function LabCS_getRgb(color) {
// Ls,as,bs <---> L*,a*,b* in the spec
var Ls = color[0], as = color[1], bs = color[2];
// Adjust limits of 'as' and 'bs'
as = as > this.amax ? this.amax : as;
as = as < this.amin ? this.amin : as;
bs = bs > this.bmax ? this.bmax : bs;
bs = bs < this.bmin ? this.bmin : bs;
// Computes intermediate variables X,Y,Z as per spec
var M = (Ls + 16) / 116;
var L = M + (as / 500);
var N = M - (bs / 200);
var X = this.XW * g(L);
var Y = this.YW * g(M);
var Z = this.ZW * g(N);
// XYZ to RGB 3x3 matrix, from:
// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18
var XYZtoRGB = [3.240479, -1.537150, -0.498535,
-0.969256, 1.875992, 0.041556,
0.055648, -0.204043, 1.057311];
return Util.apply3dTransform(XYZtoRGB, [X, Y, Z]);
},
getRgbBuffer: function LabCS_getRgbBuffer(input, bits) {
if (bits == 8)
return input;
var scale = 255 / ((1 << bits) - 1);
var i, length = input.length / 3;
var rgbBuf = new Uint8Array(length);
var j = 0;
for (i = 0; i < length; ++i) {
// Convert L*, a*, s* into RGB
var rgb = this.getRgb([input[i], input[i + 1], input[i + 2]]);
rgbBuf[j++] = rgb[0];
rgbBuf[j++] = rgb[1];
rgbBuf[j++] = rgb[2];
}
return rgbBuf;
},
isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
// From Table 90 in Adobe's:
// "Document management - Portable document format", 1st ed, 2008
if (decodeMap[0] === 0 && decodeMap[1] === 100 &&
decodeMap[2] === this.amin && decodeMap[3] === this.amax &&
decodeMap[4] === this.bmin && decodeMap[5] === this.bmax)
return true;
else
return false;
}
};
return LabCS;
})();

616
apps/files_pdfviewer/js/pdfjs/src/core.js Executable file → Normal file
View File

@ -5,6 +5,8 @@
var globalScope = (typeof window === 'undefined') ? this : window; var globalScope = (typeof window === 'undefined') ? this : window;
var isWorker = (typeof window == 'undefined');
var ERRORS = 0, WARNINGS = 1, TODOS = 5; var ERRORS = 0, WARNINGS = 1, TODOS = 5;
var verbosity = WARNINGS; var verbosity = WARNINGS;
@ -31,7 +33,9 @@ function getPdf(arg, callback) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.open('GET', params.url); xhr.open('GET', params.url);
xhr.mozResponseType = xhr.responseType = 'arraybuffer'; xhr.mozResponseType = xhr.responseType = 'arraybuffer';
xhr.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200; var protocol = params.url.indexOf(':') < 0 ? window.location.protocol :
params.url.substring(0, params.url.indexOf(':') + 1);
xhr.expected = (protocol === 'http:' || protocol === 'https:') ? 200 : 0;
if ('progress' in params) if ('progress' in params)
xhr.onprogress = params.progress || undefined; xhr.onprogress = params.progress || undefined;
@ -39,41 +43,43 @@ function getPdf(arg, callback) {
if ('error' in params) if ('error' in params)
xhr.onerror = params.error || undefined; xhr.onerror = params.error || undefined;
xhr.onreadystatechange = function getPdfOnreadystatechange() { xhr.onreadystatechange = function getPdfOnreadystatechange(e) {
if (xhr.readyState === 4 && xhr.status === xhr.expected) { if (xhr.readyState === 4) {
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse || if (xhr.status === xhr.expected) {
xhr.responseArrayBuffer || xhr.response); var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
callback(data); xhr.responseArrayBuffer || xhr.response);
callback(data);
} else if (params.error) {
params.error(e);
}
} }
}; };
xhr.send(null); xhr.send(null);
} }
globalScope.PDFJS.getPdf = getPdf; globalScope.PDFJS.getPdf = getPdf;
globalScope.PDFJS.pdfBug = false;
var Page = (function pagePage() { var Page = (function PageClosure() {
function constructor(xref, pageNumber, pageDict, ref) { function Page(xref, pageNumber, pageDict, ref) {
this.pageNumber = pageNumber; this.pageNumber = pageNumber;
this.pageDict = pageDict; this.pageDict = pageDict;
this.stats = { this.stats = new StatTimer();
create: Date.now(), this.stats.enabled = !!globalScope.PDFJS.enableStats;
compile: 0.0,
fonts: 0.0,
images: 0.0,
render: 0.0
};
this.xref = xref; this.xref = xref;
this.ref = ref; this.ref = ref;
this.displayReadyPromise = null;
} }
constructor.prototype = { Page.prototype = {
getPageProp: function pageGetPageProp(key) { getPageProp: function Page_getPageProp(key) {
return this.xref.fetchIfRef(this.pageDict.get(key)); return this.pageDict.get(key);
}, },
inheritPageProp: function pageInheritPageProp(key) { inheritPageProp: function Page_inheritPageProp(key) {
var dict = this.pageDict; var dict = this.pageDict;
var obj = dict.get(key); var obj = dict.get(key);
while (obj === undefined) { while (obj === undefined) {
dict = this.xref.fetchIfRef(dict.get('Parent')); dict = dict.get('Parent');
if (!dict) if (!dict)
break; break;
obj = dict.get(key); obj = dict.get(key);
@ -94,23 +100,35 @@ var Page = (function pagePage() {
return shadow(this, 'mediaBox', obj); return shadow(this, 'mediaBox', obj);
}, },
get view() { get view() {
var obj = this.inheritPageProp('CropBox'); var cropBox = this.inheritPageProp('CropBox');
var view = { var view = {
x: 0, x: 0,
y: 0, y: 0,
width: this.width, width: this.width,
height: this.height height: this.height
}; };
if (isArray(obj) && obj.length == 4) { if (!isArray(cropBox) || cropBox.length !== 4)
var tl = this.rotatePoint(obj[0], obj[1]); return shadow(this, 'view', view);
var br = this.rotatePoint(obj[2], obj[3]);
view.x = Math.min(tl.x, br.x);
view.y = Math.min(tl.y, br.y);
view.width = Math.abs(tl.x - br.x);
view.height = Math.abs(tl.y - br.y);
}
return shadow(this, 'cropBox', view); var mediaBox = this.mediaBox;
var offsetX = mediaBox[0], offsetY = mediaBox[1];
// From the spec, 6th ed., p.963:
// "The crop, bleed, trim, and art boxes should not ordinarily
// extend beyond the boundaries of the media box. If they do, they are
// effectively reduced to their intersection with the media box."
cropBox = Util.intersect(cropBox, mediaBox);
if (!cropBox)
return shadow(this, 'view', view);
var tl = this.rotatePoint(cropBox[0] - offsetX, cropBox[1] - offsetY);
var br = this.rotatePoint(cropBox[2] - offsetX, cropBox[3] - offsetY);
view.x = Math.min(tl.x, br.x);
view.y = Math.min(tl.y, br.y);
view.width = Math.abs(tl.x - br.x);
view.height = Math.abs(tl.y - br.y);
return shadow(this, 'view', view);
}, },
get annotations() { get annotations() {
return shadow(this, 'annotations', this.inheritPageProp('Annots')); return shadow(this, 'annotations', this.inheritPageProp('Annots'));
@ -152,77 +170,80 @@ var Page = (function pagePage() {
return shadow(this, 'rotate', rotate); return shadow(this, 'rotate', rotate);
}, },
startRenderingFromIRQueue: function pageStartRenderingFromIRQueue( startRenderingFromOperatorList:
IRQueue, fonts) { function Page_startRenderingFromOperatorList(operatorList, fonts) {
var self = this; var self = this;
this.IRQueue = IRQueue; this.operatorList = operatorList;
var gfx = new CanvasGraphics(this.ctx, this.objs);
var displayContinuation = function pageDisplayContinuation() { var displayContinuation = function pageDisplayContinuation() {
// Always defer call to display() to work around bug in // Always defer call to display() to work around bug in
// Firefox error reporting from XHR callbacks. // Firefox error reporting from XHR callbacks.
setTimeout(function pageSetTimeout() { setTimeout(function pageSetTimeout() {
try { self.displayReadyPromise.resolve();
self.display(gfx, self.callback);
} catch (e) {
if (self.callback) self.callback(e.toString());
throw e;
}
}); });
}; };
this.ensureFonts(fonts, this.ensureFonts(fonts,
function pageStartRenderingFromIRQueueEnsureFonts() { function pageStartRenderingFromOperatorListEnsureFonts() {
displayContinuation(); displayContinuation();
}); }
);
}, },
getIRQueue: function pageGetIRQueue(handler, dependency) { getOperatorList: function Page_getOperatorList(handler, dependency) {
if (this.IRQueue) { if (this.operatorList) {
// content was compiled // content was compiled
return this.IRQueue; return this.operatorList;
} }
this.stats.time('Build IR Queue');
var xref = this.xref; var xref = this.xref;
var content = xref.fetchIfRef(this.content); var content = this.content;
var resources = xref.fetchIfRef(this.resources); var resources = this.resources;
if (isArray(content)) { if (isArray(content)) {
// fetching items // fetching items
var i, n = content.length; var i, n = content.length;
for (i = 0; i < n; ++i) for (i = 0; i < n; ++i)
content[i] = xref.fetchIfRef(content[i]); content[i] = xref.fetchIfRef(content[i]);
content = new StreamsSequenceStream(content); content = new StreamsSequenceStream(content);
} else if (!content) {
// replacing non-existent page content with empty one
content = new Stream(new Uint8Array(0));
} }
var pe = this.pe = new PartialEvaluator( var pe = this.pe = new PartialEvaluator(
xref, handler, 'p' + this.pageNumber + '_'); xref, handler, 'p' + this.pageNumber + '_');
var IRQueue = {};
return (this.IRQueue = pe.getIRQueue(content, resources, IRQueue, this.operatorList = pe.getOperatorList(content, resources, dependency);
dependency)); this.stats.timeEnd('Build IR Queue');
return this.operatorList;
}, },
ensureFonts: function pageEnsureFonts(fonts, callback) { ensureFonts: function Page_ensureFonts(fonts, callback) {
this.stats.time('Font Loading');
// Convert the font names to the corresponding font obj. // Convert the font names to the corresponding font obj.
for (var i = 0, ii = fonts.length; i < ii; i++) { for (var i = 0, ii = fonts.length; i < ii; i++) {
fonts[i] = this.objs.objs[fonts[i]].data; fonts[i] = this.objs.objs[fonts[i]].data;
} }
// Load all the fonts // Load all the fonts
var fontObjs = FontLoader.bind( FontLoader.bind(
fonts, fonts,
function pageEnsureFontsFontObjs(fontObjs) { function pageEnsureFontsFontObjs(fontObjs) {
this.stats.fonts = Date.now(); this.stats.timeEnd('Font Loading');
callback.call(this); callback.call(this);
}.bind(this), }.bind(this)
this.objs
); );
}, },
display: function pageDisplay(gfx, callback) { display: function Page_display(gfx, callback) {
var stats = this.stats;
stats.time('Rendering');
var xref = this.xref; var xref = this.xref;
var resources = xref.fetchIfRef(this.resources); var resources = this.resources;
var mediaBox = xref.fetchIfRef(this.mediaBox); var mediaBox = this.mediaBox;
assertWellFormed(isDict(resources), 'invalid page resources'); assertWellFormed(isDict(resources), 'invalid page resources');
gfx.xref = xref; gfx.xref = xref;
@ -233,20 +254,29 @@ var Page = (function pagePage() {
rotate: this.rotate }); rotate: this.rotate });
var startIdx = 0; var startIdx = 0;
var length = this.IRQueue.fnArray.length; var length = this.operatorList.fnArray.length;
var IRQueue = this.IRQueue; var operatorList = this.operatorList;
var stepper = null;
if (PDFJS.pdfBug && StepperManager.enabled) {
stepper = StepperManager.create(this.pageNumber);
stepper.init(operatorList);
stepper.nextBreakPoint = stepper.getNextBreakPoint();
}
var self = this; var self = this;
function next() { function next() {
startIdx = gfx.executeIRQueue(IRQueue, startIdx, next); startIdx =
gfx.executeOperatorList(operatorList, startIdx, next, stepper);
if (startIdx == length) { if (startIdx == length) {
self.stats.render = Date.now(); gfx.endDrawing();
stats.timeEnd('Rendering');
stats.timeEnd('Overall');
if (callback) callback(); if (callback) callback();
} }
} }
next(); next();
}, },
rotatePoint: function pageRotatePoint(x, y, reverse) { rotatePoint: function Page_rotatePoint(x, y, reverse) {
var rotate = reverse ? (360 - this.rotate) : this.rotate; var rotate = reverse ? (360 - this.rotate) : this.rotate;
switch (rotate) { switch (rotate) {
case 180: case 180:
@ -261,58 +291,183 @@ var Page = (function pagePage() {
return {x: x, y: this.height - y}; return {x: x, y: this.height - y};
} }
}, },
getLinks: function pageGetLinks() { getLinks: function Page_getLinks() {
var xref = this.xref;
var annotations = xref.fetchIfRef(this.annotations) || [];
var i, n = annotations.length;
var links = []; var links = [];
var annotations = pageGetAnnotations();
var i, n = annotations.length;
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
var annotation = xref.fetch(annotations[i]); if (annotations[i].type != 'Link')
continue;
links.push(annotations[i]);
}
return links;
},
getAnnotations: function Page_getAnnotations() {
var xref = this.xref;
function getInheritableProperty(annotation, name) {
var item = annotation;
while (item && !item.has(name)) {
item = item.get('Parent');
}
if (!item)
return null;
return item.get(name);
}
function isValidUrl(url) {
if (!url)
return false;
var colon = url.indexOf(':');
if (colon < 0)
return false;
var protocol = url.substr(0, colon);
switch (protocol) {
case 'http':
case 'https':
case 'ftp':
return true;
default:
return false;
}
}
var annotations = this.annotations || [];
var i, n = annotations.length;
var items = [];
for (i = 0; i < n; ++i) {
var annotationRef = annotations[i];
var annotation = xref.fetch(annotationRef);
if (!isDict(annotation)) if (!isDict(annotation))
continue; continue;
var subtype = annotation.get('Subtype'); var subtype = annotation.get('Subtype');
if (!isName(subtype) || subtype.name != 'Link') if (!isName(subtype))
continue; continue;
var rect = annotation.get('Rect'); var rect = annotation.get('Rect');
var topLeftCorner = this.rotatePoint(rect[0], rect[1]); var topLeftCorner = this.rotatePoint(rect[0], rect[1]);
var bottomRightCorner = this.rotatePoint(rect[2], rect[3]); var bottomRightCorner = this.rotatePoint(rect[2], rect[3]);
var link = {}; var item = {};
link.x = Math.min(topLeftCorner.x, bottomRightCorner.x); item.type = subtype.name;
link.y = Math.min(topLeftCorner.y, bottomRightCorner.y); item.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
link.width = Math.abs(topLeftCorner.x - bottomRightCorner.x); item.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y); item.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
var a = this.xref.fetchIfRef(annotation.get('A')); item.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
if (a) { switch (subtype.name) {
switch (a.get('S').name) { case 'Link':
case 'URI': var a = annotation.get('A');
link.url = a.get('URI'); if (a) {
switch (a.get('S').name) {
case 'URI':
var url = a.get('URI');
// TODO: pdf spec mentions urls can be relative to a Base
// entry in the dictionary.
if (!isValidUrl(url))
url = '';
item.url = url;
break;
case 'GoTo':
item.dest = a.get('D');
break;
default:
TODO('other link types');
}
} else if (annotation.has('Dest')) {
// simple destination link
var dest = annotation.get('Dest');
item.dest = isName(dest) ? dest.name : dest;
}
break;
case 'Widget':
var fieldType = getInheritableProperty(annotation, 'FT');
if (!isName(fieldType))
break; break;
case 'GoTo': item.fieldType = fieldType.name;
link.dest = a.get('D'); // Building the full field name by collecting the field and
break; // its ancestors 'T' properties and joining them using '.'.
default: var fieldName = [];
TODO('other link types'); var namedItem = annotation, ref = annotationRef;
} while (namedItem) {
} else if (annotation.has('Dest')) { var parent = namedItem.get('Parent');
// simple destination link var parentRef = namedItem.getRaw('Parent');
var dest = annotation.get('Dest'); var name = namedItem.get('T');
link.dest = isName(dest) ? dest.name : dest; if (name) {
fieldName.unshift(stringToPDFString(name));
} else {
// The field name is absent, that means more than one field
// with the same name may exist. Replacing the empty name
// with the '`' plus index in the parent's 'Kids' array.
// This is not in the PDF spec but necessary to id the
// the input controls.
var kids = parent.get('Kids');
var j, jj;
for (j = 0, jj = kids.length; j < jj; j++) {
var kidRef = kids[j];
if (kidRef.num == ref.num && kidRef.gen == ref.gen)
break;
}
fieldName.unshift('`' + j);
}
namedItem = parent;
ref = parentRef;
}
item.fullName = fieldName.join('.');
var alternativeText = stringToPDFString(annotation.get('TU') || '');
item.alternativeText = alternativeText;
var da = getInheritableProperty(annotation, 'DA') || '';
var m = /([\d\.]+)\sTf/.exec(da);
if (m)
item.fontSize = parseFloat(m[1]);
item.textAlignment = getInheritableProperty(annotation, 'Q');
item.flags = getInheritableProperty(annotation, 'Ff') || 0;
break;
case 'Text':
var content = annotation.get('Contents');
var title = annotation.get('T');
item.content = stringToPDFString(content || '');
item.title = stringToPDFString(title || '');
item.name = annotation.get('Name').name;
break;
default:
TODO('unimplemented annotation type: ' + subtype.name);
break;
} }
links.push(link); items.push(item);
} }
return links; return items;
}, },
startRendering: function pageStartRendering(ctx, callback) { startRendering: function Page_startRendering(ctx, callback, textLayer) {
this.ctx = ctx; var stats = this.stats;
this.callback = callback; stats.time('Overall');
// If there is no displayReadyPromise yet, then the operatorList was never
// requested before. Make the request and create the promise.
if (!this.displayReadyPromise) {
this.pdf.startRendering(this);
this.displayReadyPromise = new Promise();
}
this.startRenderingTime = Date.now(); // Once the operatorList and fonts are loaded, do the actual rendering.
this.pdf.startRendering(this); this.displayReadyPromise.then(
function pageDisplayReadyPromise() {
var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
try {
this.display(gfx, callback);
} catch (e) {
if (callback)
callback(e);
else
error(e);
}
}.bind(this),
function pageDisplayReadPromiseError(reason) {
if (callback)
callback(reason);
else
error(reason);
}
);
} }
}; };
return constructor; return Page;
})(); })();
/** /**
@ -321,12 +476,9 @@ var Page = (function pagePage() {
* Right now there exists one PDFDocModel on the main thread + one object * Right now there exists one PDFDocModel on the main thread + one object
* for each worker. If there is no worker support enabled, there are two * for each worker. If there is no worker support enabled, there are two
* `PDFDocModel` objects on the main thread created. * `PDFDocModel` objects on the main thread created.
* TODO: Refactor the internal object structure, such that there is no
* need for the `PDFDocModel` anymore and there is only one object on the
* main thread and not one entire copy on each worker instance.
*/ */
var PDFDocModel = (function pdfDoc() { var PDFDocModel = (function PDFDocModelClosure() {
function constructor(arg, callback) { function PDFDocModel(arg, callback) {
if (isStream(arg)) if (isStream(arg))
init.call(this, arg); init.call(this, arg);
else if (isArrayBuffer(arg)) else if (isArrayBuffer(arg))
@ -339,6 +491,7 @@ var PDFDocModel = (function pdfDoc() {
assertWellFormed(stream.length > 0, 'stream must have data'); assertWellFormed(stream.length > 0, 'stream must have data');
this.stream = stream; this.stream = stream;
this.setup(); this.setup();
this.acroForm = this.catalog.catDict.get('AcroForm');
} }
function find(stream, needle, limit, backwards) { function find(stream, needle, limit, backwards) {
@ -357,7 +510,7 @@ var PDFDocModel = (function pdfDoc() {
return true; /* found */ return true; /* found */
} }
constructor.prototype = { PDFDocModel.prototype = {
get linearization() { get linearization() {
var length = this.stream.length; var length = this.stream.length;
var linearization = false; var linearization = false;
@ -379,12 +532,17 @@ var PDFDocModel = (function pdfDoc() {
if (find(stream, 'endobj', 1024)) if (find(stream, 'endobj', 1024))
startXRef = stream.pos + 6; startXRef = stream.pos + 6;
} else { } else {
// Find startxref at the end of the file. // Find startxref by jumping backward from the end of the file.
var start = stream.end - 1024; var step = 1024;
if (start < 0) var found = false, pos = stream.end;
start = 0; while (!found && pos > 0) {
stream.pos = start; pos -= step - 'startxref'.length;
if (find(stream, 'startxref', 1024, true)) { if (pos < 0)
pos = 0;
stream.pos = pos;
found = find(stream, 'startxref', step, true);
}
if (found) {
stream.skip(9); stream.skip(9);
var ch; var ch;
do { do {
@ -413,7 +571,7 @@ var PDFDocModel = (function pdfDoc() {
}, },
// Find the header, remove leading garbage and setup the stream // Find the header, remove leading garbage and setup the stream
// starting from the header. // starting from the header.
checkHeader: function pdfDocCheckHeader() { checkHeader: function PDFDocModel_checkHeader() {
var stream = this.stream; var stream = this.stream;
stream.reset(); stream.reset();
if (find(stream, '%PDF-', 1024)) { if (find(stream, '%PDF-', 1024)) {
@ -423,12 +581,13 @@ var PDFDocModel = (function pdfDoc() {
} }
// May not be a PDF file, continue anyway. // May not be a PDF file, continue anyway.
}, },
setup: function pdfDocSetup(ownerPassword, userPassword) { setup: function PDFDocModel_setup(ownerPassword, userPassword) {
this.checkHeader(); this.checkHeader();
this.xref = new XRef(this.stream, var xref = new XRef(this.stream,
this.startXRef, this.startXRef,
this.mainXRefEntriesOffset); this.mainXRefEntriesOffset);
this.catalog = new Catalog(this.xref); this.xref = xref;
this.catalog = new Catalog(xref);
}, },
get numPages() { get numPages() {
var linearization = this.linearization; var linearization = this.linearization;
@ -436,16 +595,51 @@ var PDFDocModel = (function pdfDoc() {
// shadow the prototype getter // shadow the prototype getter
return shadow(this, 'numPages', num); return shadow(this, 'numPages', num);
}, },
getPage: function pdfDocGetPage(n) { getDocumentInfo: function PDFDocModel_getDocumentInfo() {
var info;
if (this.xref.trailer.has('Info')) {
var infoDict = this.xref.trailer.get('Info');
info = {};
infoDict.forEach(function(key, value) {
info[key] = typeof value !== 'string' ? value :
stringToPDFString(value);
});
}
return shadow(this, 'getDocumentInfo', info);
},
getFingerprint: function PDFDocModel_getFingerprint() {
var xref = this.xref, fileID;
if (xref.trailer.has('ID')) {
fileID = '';
var id = xref.trailer.get('ID')[0];
id.split('').forEach(function(el) {
fileID += Number(el.charCodeAt(0)).toString(16);
});
} else {
// If we got no fileID, then we generate one,
// from the first 100 bytes of PDF
var data = this.stream.bytes.subarray(0, 100);
var hash = calculateMD5(data, 0, data.length);
fileID = '';
for (var i = 0, length = hash.length; i < length; i++) {
fileID += Number(hash[i]).toString(16);
}
}
return shadow(this, 'getFingerprint', fileID);
},
getPage: function PDFDocModel_getPage(n) {
return this.catalog.getPage(n); return this.catalog.getPage(n);
} }
}; };
return constructor; return PDFDocModel;
})(); })();
var PDFDoc = (function pdfDoc() { var PDFDoc = (function PDFDocClosure() {
function constructor(arg, callback) { function PDFDoc(arg, callback) {
var stream = null; var stream = null;
var data = null; var data = null;
@ -461,9 +655,10 @@ var PDFDoc = (function pdfDoc() {
this.data = data; this.data = data;
this.stream = stream; this.stream = stream;
this.pdf = new PDFDocModel(stream); this.pdfModel = new PDFDocModel(stream);
this.fingerprint = this.pdfModel.getFingerprint();
this.catalog = this.pdf.catalog; this.info = this.pdfModel.getDocumentInfo();
this.catalog = this.pdfModel.catalog;
this.objs = new PDFObjects(); this.objs = new PDFObjects();
this.pageCache = []; this.pageCache = [];
@ -478,49 +673,59 @@ var PDFDoc = (function pdfDoc() {
if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') { if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
var workerSrc = PDFJS.workerSrc; var workerSrc = PDFJS.workerSrc;
if (typeof workerSrc === 'undefined') { if (typeof workerSrc === 'undefined') {
throw 'No PDFJS.workerSrc specified'; error('No PDFJS.workerSrc specified');
} }
var worker;
try { try {
worker = new Worker(workerSrc); var worker;
} catch (e) { if (PDFJS.isFirefoxExtension) {
// Some versions of FF can't create a worker on localhost, see: // The firefox extension can't load the worker from the resource://
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280 // url so we have to inline the script and then use the blob loader.
globalScope.PDFJS.disableWorker = true; var bb = new MozBlobBuilder();
this.setupFakeWorker(); bb.append(document.querySelector('#PDFJS_SCRIPT_TAG').textContent);
return; var blobUrl = window.URL.createObjectURL(bb.getBlob());
} worker = new Worker(blobUrl);
var messageHandler = new MessageHandler('main', worker);
// Tell the worker the file it was created from.
messageHandler.send('workerSrc', workerSrc);
messageHandler.on('test', function pdfDocTest(supportTypedArray) {
if (supportTypedArray) {
this.worker = worker;
this.setupMessageHandler(messageHandler);
} else { } else {
this.setupFakeWorker(); // Some versions of FF can't create a worker on localhost, see:
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
worker = new Worker(workerSrc);
} }
}.bind(this));
var testObj = new Uint8Array(1); var messageHandler = new MessageHandler('main', worker);
messageHandler.send('test', testObj);
} else { messageHandler.on('test', function pdfDocTest(supportTypedArray) {
this.setupFakeWorker(); if (supportTypedArray) {
this.worker = worker;
this.setupMessageHandler(messageHandler);
} else {
globalScope.PDFJS.disableWorker = true;
this.setupFakeWorker();
}
}.bind(this));
var testObj = new Uint8Array(1);
// Some versions of Opera throw a DATA_CLONE_ERR on
// serializing the typed array.
messageHandler.send('test', testObj);
return;
} catch (e) {
warn('The worker has been disabled.');
}
} }
// Either workers are disabled, not supported or have thrown an exception.
// Thus, we fallback to a faked worker.
globalScope.PDFJS.disableWorker = true;
this.setupFakeWorker();
} }
constructor.prototype = { PDFDoc.prototype = {
setupFakeWorker: function() { setupFakeWorker: function PDFDoc_setupFakeWorker() {
// If we don't use a worker, just post/sendMessage to the main thread. // If we don't use a worker, just post/sendMessage to the main thread.
var fakeWorker = { var fakeWorker = {
postMessage: function pdfDocPostMessage(obj) { postMessage: function PDFDoc_postMessage(obj) {
fakeWorker.onmessage({data: obj}); fakeWorker.onmessage({data: obj});
}, },
terminate: function pdfDocTerminate() {} terminate: function PDFDoc_terminate() {}
}; };
var messageHandler = new MessageHandler('main', fakeWorker); var messageHandler = new MessageHandler('main', fakeWorker);
@ -532,7 +737,7 @@ var PDFDoc = (function pdfDoc() {
}, },
setupMessageHandler: function(messageHandler) { setupMessageHandler: function PDFDoc_setupMessageHandler(messageHandler) {
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
messageHandler.on('page', function pdfDocPage(data) { messageHandler.on('page', function pdfDocPage(data) {
@ -540,7 +745,8 @@ var PDFDoc = (function pdfDoc() {
var page = this.pageCache[pageNum]; var page = this.pageCache[pageNum];
var depFonts = data.depFonts; var depFonts = data.depFonts;
page.startRenderingFromIRQueue(data.IRQueue, depFonts); page.stats.timeEnd('Page Request');
page.startRenderingFromOperatorList(data.operatorList, depFonts);
}, this); }, this);
messageHandler.on('obj', function pdfDocObj(data) { messageHandler.on('obj', function pdfDocObj(data) {
@ -549,8 +755,12 @@ var PDFDoc = (function pdfDoc() {
switch (type) { switch (type) {
case 'JpegStream': case 'JpegStream':
var IR = data[2]; var imageData = data[2];
new JpegImageLoader(id, IR, this.objs); loadJpegStream(id, imageData, this.objs);
break;
case 'Image':
var imageData = data[2];
this.objs.resolve(id, imageData);
break; break;
case 'Font': case 'Font':
var name = data[2]; var name = data[2];
@ -558,46 +768,63 @@ var PDFDoc = (function pdfDoc() {
var properties = data[4]; var properties = data[4];
if (file) { if (file) {
// Rewrap the ArrayBuffer in a stream.
var fontFileDict = new Dict(); var fontFileDict = new Dict();
fontFileDict.map = file.dict.map; file = new Stream(file, 0, file.length, fontFileDict);
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) {
file = new FlateStream(fontFile);
} else {
file = fontFile;
}
} }
// For now, resolve the font object here direclty. The real font // At this point, only the font object is created but the font is
// object is then created in FontLoader.bind(). // not yet attached to the DOM. This is done in `FontLoader.bind`.
this.objs.resolve(id, { var font = new Font(name, file, properties);
name: name, this.objs.resolve(id, font);
file: file,
properties: properties
});
break; break;
default: default:
throw 'Got unkown object type ' + type; error('Got unkown object type ' + type);
} }
}, this); }, this);
messageHandler.on('font_ready', function pdfDocFontReady(data) { messageHandler.on('page_error', function pdfDocError(data) {
var id = data[0]; var page = this.pageCache[data.pageNum];
var font = new FontShape(data[1]); if (page.displayReadyPromise)
page.displayReadyPromise.reject(data.error);
else
error(data.error);
}, this);
// If there is no string, then there is nothing to attach to the DOM. messageHandler.on('jpeg_decode', function(data, promise) {
if (!font.str) { var imageData = data[0];
this.objs.resolve(id, font); var components = data[1];
} else { if (components != 3 && components != 1)
this.objs.setData(id, font); error('Only 3 component or 1 component can be returned');
}
}.bind(this)); var img = new Image();
img.onload = (function messageHandler_onloadClosure() {
var width = img.width;
var height = img.height;
var size = width * height;
var rgbaLength = size * 4;
var buf = new Uint8Array(size * components);
var tmpCanvas = createScratchCanvas(width, height);
var tmpCtx = tmpCanvas.getContext('2d');
tmpCtx.drawImage(img, 0, 0);
var data = tmpCtx.getImageData(0, 0, width, height).data;
if (components == 3) {
for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
buf[j] = data[i];
buf[j + 1] = data[i + 1];
buf[j + 2] = data[i + 2];
}
} else if (components == 1) {
for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
buf[j] = data[i];
}
}
promise.resolve({ data: buf, width: width, height: height});
}).bind(this);
var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
img.src = src;
});
setTimeout(function pdfDocFontReadySetTimeout() { setTimeout(function pdfDocFontReadySetTimeout() {
messageHandler.send('doc', this.data); messageHandler.send('doc', this.data);
@ -606,21 +833,22 @@ var PDFDoc = (function pdfDoc() {
}, },
get numPages() { get numPages() {
return this.pdf.numPages; return this.pdfModel.numPages;
}, },
startRendering: function pdfDocStartRendering(page) { startRendering: function PDFDoc_startRendering(page) {
// The worker might not be ready to receive the page request yet. // The worker might not be ready to receive the page request yet.
this.workerReadyPromise.then(function pdfDocStartRenderingThen() { this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
page.stats.time('Page Request');
this.messageHandler.send('page_request', page.pageNumber + 1); this.messageHandler.send('page_request', page.pageNumber + 1);
}.bind(this)); }.bind(this));
}, },
getPage: function pdfDocGetPage(n) { getPage: function PDFDoc_getPage(n) {
if (this.pageCache[n]) if (this.pageCache[n])
return this.pageCache[n]; return this.pageCache[n];
var page = this.pdf.getPage(n); var page = this.pdfModel.getPage(n);
// Add a reference to the objects such that Page can forward the reference // Add a reference to the objects such that Page can forward the reference
// to the CanvasGraphics and so on. // to the CanvasGraphics and so on.
page.objs = this.objs; page.objs = this.objs;
@ -628,7 +856,7 @@ var PDFDoc = (function pdfDoc() {
return (this.pageCache[n] = page); return (this.pageCache[n] = page);
}, },
destroy: function pdfDocDestroy() { destroy: function PDFDoc_destroy() {
if (this.worker) if (this.worker)
this.worker.terminate(); this.worker.terminate();
@ -645,7 +873,7 @@ var PDFDoc = (function pdfDoc() {
} }
}; };
return constructor; return PDFDoc;
})(); })();
globalScope.PDFJS.PDFDoc = PDFDoc; globalScope.PDFJS.PDFDoc = PDFDoc;

59
apps/files_pdfviewer/js/pdfjs/src/crypto.js Executable file → Normal file
View File

@ -3,8 +3,8 @@
'use strict'; 'use strict';
var ARCFourCipher = (function arcFourCipher() { var ARCFourCipher = (function ARCFourCipherClosure() {
function constructor(key) { function ARCFourCipher(key) {
this.a = 0; this.a = 0;
this.b = 0; this.b = 0;
var s = new Uint8Array(256); var s = new Uint8Array(256);
@ -20,8 +20,8 @@ var ARCFourCipher = (function arcFourCipher() {
this.s = s; this.s = s;
} }
constructor.prototype = { ARCFourCipher.prototype = {
encryptBlock: function arcFourCipherEncryptBlock(data) { encryptBlock: function ARCFourCipher_encryptBlock(data) {
var i, n = data.length, tmp, tmp2; var i, n = data.length, tmp, tmp2;
var a = this.a, b = this.b, s = this.s; var a = this.a, b = this.b, s = this.s;
var output = new Uint8Array(n); var output = new Uint8Array(n);
@ -39,12 +39,12 @@ var ARCFourCipher = (function arcFourCipher() {
return output; return output;
} }
}; };
constructor.prototype.decryptBlock = constructor.prototype.encryptBlock; ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
return constructor; return ARCFourCipher;
})(); })();
var calculateMD5 = (function calculateMD5() { var calculateMD5 = (function calculateMD5Closure() {
var r = new Uint8Array([ var r = new Uint8Array([
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
@ -128,20 +128,20 @@ var calculateMD5 = (function calculateMD5() {
return hash; return hash;
})(); })();
var NullCipher = (function nullCipher() { var NullCipher = (function NullCipherClosure() {
function constructor() { function NullCipher() {
} }
constructor.prototype = { NullCipher.prototype = {
decryptBlock: function nullCipherDecryptBlock(data) { decryptBlock: function NullCipher_decryptBlock(data) {
return data; return data;
} }
}; };
return constructor; return NullCipher;
})(); })();
var AES128Cipher = (function aes128Cipher() { var AES128Cipher = (function AES128CipherClosure() {
var rcon = new Uint8Array([ var rcon = new Uint8Array([
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
@ -330,7 +330,7 @@ var AES128Cipher = (function aes128Cipher() {
return state; return state;
} }
function constructor(key) { function AES128Cipher(key) {
this.key = expandKey128(key); this.key = expandKey128(key);
this.buffer = new Uint8Array(16); this.buffer = new Uint8Array(16);
this.bufferPosition = 0; this.bufferPosition = 0;
@ -370,8 +370,8 @@ var AES128Cipher = (function aes128Cipher() {
return output; return output;
} }
constructor.prototype = { AES128Cipher.prototype = {
decryptBlock: function aes128CipherDecryptBlock(data) { decryptBlock: function AES128Cipher_decryptBlock(data) {
var i, sourceLength = data.length; var i, sourceLength = data.length;
var buffer = this.buffer, bufferLength = this.bufferPosition; var buffer = this.buffer, bufferLength = this.bufferPosition;
// waiting for IV values -- they are at the start of the stream // waiting for IV values -- they are at the start of the stream
@ -391,16 +391,16 @@ var AES128Cipher = (function aes128Cipher() {
} }
}; };
return constructor; return AES128Cipher;
})(); })();
var CipherTransform = (function cipherTransform() { var CipherTransform = (function CipherTransformClosure() {
function constructor(stringCipherConstructor, streamCipherConstructor) { function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
this.stringCipherConstructor = stringCipherConstructor; this.stringCipherConstructor = stringCipherConstructor;
this.streamCipherConstructor = streamCipherConstructor; this.streamCipherConstructor = streamCipherConstructor;
} }
constructor.prototype = { CipherTransform.prototype = {
createStream: function cipherTransformCreateStream(stream) { createStream: function CipherTransform_createStream(stream) {
var cipher = new this.streamCipherConstructor(); var cipher = new this.streamCipherConstructor();
return new DecryptStream(stream, return new DecryptStream(stream,
function cipherTransformDecryptStream(data) { function cipherTransformDecryptStream(data) {
@ -408,17 +408,17 @@ var CipherTransform = (function cipherTransform() {
} }
); );
}, },
decryptString: function cipherTransformDecryptString(s) { decryptString: function CipherTransform_decryptString(s) {
var cipher = new this.stringCipherConstructor(); var cipher = new this.stringCipherConstructor();
var data = stringToBytes(s); var data = stringToBytes(s);
data = cipher.decryptBlock(data); data = cipher.decryptBlock(data);
return bytesToString(data); return bytesToString(data);
} }
}; };
return constructor; return CipherTransform;
})(); })();
var CipherTransformFactory = (function cipherTransformFactory() { var CipherTransformFactory = (function CipherTransformFactoryClosure() {
function prepareKeyData(fileId, password, ownerPassword, userPassword, function prepareKeyData(fileId, password, ownerPassword, userPassword,
flags, revision, keyLength, encryptMetadata) { flags, revision, keyLength, encryptMetadata) {
var defaultPasswordBytes = new Uint8Array([ var defaultPasswordBytes = new Uint8Array([
@ -490,7 +490,7 @@ var CipherTransformFactory = (function cipherTransformFactory() {
var identityName = new Name('Identity'); var identityName = new Name('Identity');
function constructor(dict, fileId, password) { function CipherTransformFactory(dict, fileId, password) {
var filter = dict.get('Filter'); var filter = dict.get('Filter');
if (!isName(filter) || filter.name != 'Standard') if (!isName(filter) || filter.name != 'Standard')
error('unknown encryption method'); error('unknown encryption method');
@ -570,12 +570,11 @@ var CipherTransformFactory = (function cipherTransformFactory() {
}; };
} }
error('Unknown crypto method'); error('Unknown crypto method');
return null;
} }
constructor.prototype = { CipherTransformFactory.prototype = {
createCipherTransform: function buildCipherCreateCipherTransform(num, createCipherTransform:
gen) { function CipherTransformFactory_createCipherTransform(num, gen) {
if (this.algorithm == 4) { if (this.algorithm == 4) {
return new CipherTransform( return new CipherTransform(
buildCipherConstructor(this.cf, this.stmf, buildCipherConstructor(this.cf, this.stmf,
@ -592,6 +591,6 @@ var CipherTransformFactory = (function cipherTransformFactory() {
} }
}; };
return constructor; return CipherTransformFactory;
})(); })();

365
apps/files_pdfviewer/js/pdfjs/src/evaluator.js Executable file → Normal file
View File

@ -3,8 +3,8 @@
'use strict'; 'use strict';
var PartialEvaluator = (function partialEvaluator() { var PartialEvaluator = (function PartialEvaluatorClosure() {
function constructor(xref, handler, uniquePrefix) { function PartialEvaluator(xref, handler, uniquePrefix) {
this.state = new EvalState(); this.state = new EvalState();
this.stateStack = []; this.stateStack = [];
@ -111,14 +111,27 @@ var PartialEvaluator = (function partialEvaluator() {
EX: 'endCompat' EX: 'endCompat'
}; };
constructor.prototype = { function splitCombinedOperations(operations) {
getIRQueue: function partialEvaluatorGetIRQueue(stream, resources, // Two operations can be combined together, trying to find which two
queue, dependency) { // operations were concatenated.
for (var i = operations.length - 1; i > 0; i--) {
var op1 = operations.substring(0, i), op2 = operations.substring(i);
if (op1 in OP_MAP && op2 in OP_MAP)
return [op1, op2]; // operations found
}
return null;
}
PartialEvaluator.prototype = {
getOperatorList: function PartialEvaluator_getOperatorList(stream,
resources,
dependency,
queue) {
var self = this; var self = this;
var xref = this.xref; var xref = this.xref;
var handler = this.handler; var handler = this.handler;
var uniquePrefix = this.uniquePrefix; var uniquePrefix = this.uniquePrefix || '';
function insertDependency(depList) { function insertDependency(depList) {
fnArray.push('dependency'); fnArray.push('dependency');
@ -131,18 +144,14 @@ var PartialEvaluator = (function partialEvaluator() {
} }
} }
function handleSetFont(fontName, fontRef) { function handleSetFont(fontName, font) {
var loadedName = null; var loadedName = null;
var fontRes = resources.get('Font'); 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'); assert(fontRes, 'fontRes not available');
fontRes = xref.fetchIfRef(fontRes); font = xref.fetchIfRef(font) || fontRes.get(fontName);
fontRef = fontRef || fontRes.get(fontName);
var font = xref.fetchIfRef(fontRef);
assertWellFormed(isDict(font)); assertWellFormed(isDict(font));
if (!font.translated) { if (!font.translated) {
font.translated = self.translateFont(font, xref, resources, font.translated = self.translateFont(font, xref, resources,
@ -155,6 +164,15 @@ var PartialEvaluator = (function partialEvaluator() {
font.loadedName = loadedName; font.loadedName = loadedName;
var translated = font.translated; 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();
}
handler.send('obj', [ handler.send('obj', [
loadedName, loadedName,
'Font', 'Font',
@ -168,7 +186,7 @@ var PartialEvaluator = (function partialEvaluator() {
// Ensure the font is ready before the font is set // Ensure the font is ready before the font is set
// and later on used for drawing. // and later on used for drawing.
// TODO: This should get insert to the IRQueue only once per // OPTIMIZE: This should get insert to the operatorList only once per
// page. // page.
insertDependency([loadedName]); insertDependency([loadedName]);
return loadedName; return loadedName;
@ -179,65 +197,60 @@ var PartialEvaluator = (function partialEvaluator() {
var w = dict.get('Width', 'W'); var w = dict.get('Width', 'W');
var h = dict.get('Height', 'H'); var h = dict.get('Height', 'H');
if (image instanceof JpegStream && image.isNative) { var imageMask = dict.get('ImageMask', 'IM') || false;
var objId = 'img_' + uniquePrefix + (++self.objIdCounter); if (imageMask) {
handler.send('obj', [objId, 'JpegStream', image.getIR()]); // This depends on a tmpCanvas beeing filled with the
// current fillStyle, such that processing the pixel
// data can't be done here. Instead of creating a
// complete PDFImage, only read the information needed
// for later.
// Add the dependency on the image object. var width = dict.get('Width', 'W');
insertDependency([objId]); var height = dict.get('Height', 'H');
var bitStrideLength = (width + 7) >> 3;
// The normal fn. var imgArray = image.getBytes(bitStrideLength * height);
fn = 'paintJpegXObject'; var decode = dict.get('Decode', 'D');
args = [objId, w, h]; var inverseDecode = !!decode && decode[0] > 0;
fn = 'paintImageMaskXObject';
args = [imgArray, inverseDecode, width, height];
return; return;
} }
// Needs to be rendered ourself.
// Figure out if the image has an imageMask.
var imageMask = dict.get('ImageMask', 'IM') || false;
// If there is no imageMask, create the PDFImage and a lot // If there is no imageMask, create the PDFImage and a lot
// of image processing can be done here. // of image processing can be done here.
if (!imageMask) { var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
var imageObj = new PDFImage(xref, resources, image, inline); insertDependency([objId]);
args = [objId, w, h];
if (imageObj.imageMask) { var softMask = dict.get('SMask', 'IM') || false;
throw 'Can\'t handle this in the web worker :/'; if (!softMask && image instanceof JpegStream &&
} image.isNativelySupported(xref, resources)) {
// These JPEGs don't need any more processing so we can just send it.
var imgData = { fn = 'paintJpegXObject';
width: w, handler.send('obj', [objId, 'JpegStream', image.getIR()]);
height: h,
data: new Uint8Array(w * h * 4)
};
var pixels = imgData.data;
imageObj.fillRgbaBuffer(pixels, imageObj.decode);
fn = 'paintImageXObject';
args = [imgData];
return; return;
} }
// This depends on a tmpCanvas beeing filled with the fn = 'paintImageXObject';
// current fillStyle, such that processing the pixel
// data can't be done here. Instead of creating a
// complete PDFImage, only read the information needed
// for later.
fn = 'paintImageMaskXObject';
var width = dict.get('Width', 'W'); PDFImage.buildImage(function(imageObj) {
var height = dict.get('Height', 'H'); var drawWidth = imageObj.drawWidth;
var bitStrideLength = (width + 7) >> 3; var drawHeight = imageObj.drawHeight;
var imgArray = image.getBytes(bitStrideLength * height); var imgData = {
var decode = dict.get('Decode', 'D'); width: drawWidth,
var inverseDecode = !!decode && decode[0] > 0; height: drawHeight,
data: new Uint8Array(drawWidth * drawHeight * 4)
args = [imgArray, inverseDecode, width, height]; };
var pixels = imgData.data;
imageObj.fillRgbaBuffer(pixels, drawWidth, drawHeight);
handler.send('obj', [objId, 'Image', imgData]);
}, handler, xref, resources, image, inline);
} }
uniquePrefix = uniquePrefix || ''; if (!queue)
queue = {};
if (!queue.argsArray) { if (!queue.argsArray) {
queue.argsArray = []; queue.argsArray = [];
} }
@ -248,45 +261,48 @@ var PartialEvaluator = (function partialEvaluator() {
var fnArray = queue.fnArray, argsArray = queue.argsArray; var fnArray = queue.fnArray, argsArray = queue.argsArray;
var dependencyArray = dependency || []; var dependencyArray = dependency || [];
resources = xref.fetchIfRef(resources) || new Dict(); resources = resources || new Dict();
var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict(); var xobjs = resources.get('XObject') || new Dict();
var patterns = xref.fetchIfRef(resources.get('Pattern')) || new Dict(); var patterns = resources.get('Pattern') || new Dict();
var parser = new Parser(new Lexer(stream), false); var parser = new Parser(new Lexer(stream), false, xref);
var res = resources; var res = resources;
var hasNextObj = false, nextObj;
var args = [], obj; var args = [], obj;
var getObjBt = function getObjBt() {
parser = this.oldParser;
return { name: 'BT' };
};
var TILING_PATTERN = 1, SHADING_PATTERN = 2; var TILING_PATTERN = 1, SHADING_PATTERN = 2;
while (!isEOF(obj = parser.getObj())) { while (true) {
if (hasNextObj) {
obj = nextObj;
hasNextObj = false;
} else {
obj = parser.getObj();
if (isEOF(obj))
break;
}
if (isCmd(obj)) { if (isCmd(obj)) {
var cmd = obj.cmd; var cmd = obj.cmd;
var fn = OP_MAP[cmd]; var fn = OP_MAP[cmd];
if (!fn) { if (!fn) {
// invalid content command, trying to recover // invalid content command, trying to recover
if (cmd.substr(-2) == 'BT') { var cmds = splitCombinedOperations(cmd);
fn = OP_MAP[cmd.substr(0, cmd.length - 2)]; if (cmds) {
// feeding 'BT' on next interation cmd = cmds[0];
parser = { fn = OP_MAP[cmd];
getObj: getObjBt, // feeding other command on the next interation
oldParser: parser hasNextObj = true;
}; nextObj = Cmd.get(cmds[1]);
} }
} }
assertWellFormed(fn, 'Unknown command "' + cmd + '"'); assertWellFormed(fn, 'Unknown command "' + cmd + '"');
// TODO figure out how to type-check vararg functions // TODO figure out how to type-check vararg functions
if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) { if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
// Use the IR version for setStroke/FillColorN.
fn += '_IR';
// compile tiling patterns // compile tiling patterns
var patternName = args[args.length - 1]; var patternName = args[args.length - 1];
// SCN/scn applies patterns along with normal colors // SCN/scn applies patterns along with normal colors
if (isName(patternName)) { if (isName(patternName)) {
var pattern = xref.fetchIfRef(patterns.get(patternName.name)); var pattern = patterns.get(patternName.name);
if (pattern) { if (pattern) {
var dict = isStream(pattern) ? pattern.dict : pattern; var dict = isStream(pattern) ? pattern.dict : pattern;
var typeNum = dict.get('PatternType'); var typeNum = dict.get('PatternType');
@ -294,21 +310,20 @@ var PartialEvaluator = (function partialEvaluator() {
if (typeNum == TILING_PATTERN) { if (typeNum == TILING_PATTERN) {
// Create an IR of the pattern code. // Create an IR of the pattern code.
var depIdx = dependencyArray.length; var depIdx = dependencyArray.length;
var queueObj = {}; var operatorList = this.getOperatorList(pattern,
var codeIR = this.getIRQueue(pattern, dict.get('Resources'), dict.get('Resources') || resources, dependencyArray);
queueObj, dependencyArray);
// Add the dependencies that are required to execute the // Add the dependencies that are required to execute the
// codeIR. // operatorList.
insertDependency(dependencyArray.slice(depIdx)); insertDependency(dependencyArray.slice(depIdx));
args = TilingPattern.getIR(codeIR, dict, args); args = TilingPattern.getIR(operatorList, dict, args);
} }
else if (typeNum == SHADING_PATTERN) { else if (typeNum == SHADING_PATTERN) {
var shading = xref.fetchIfRef(dict.get('Shading')); var shading = dict.get('Shading');
var matrix = dict.get('Matrix'); var matrix = dict.get('Matrix');
var pattern = Pattern.parseShading(shading, matrix, xref, res, var pattern = Pattern.parseShading(shading, matrix, xref,
null /*ctx*/); res);
args = pattern.getIR(); args = pattern.getIR();
} else { } else {
error('Unkown PatternType ' + typeNum); error('Unkown PatternType ' + typeNum);
@ -320,7 +335,6 @@ var PartialEvaluator = (function partialEvaluator() {
var name = args[0].name; var name = args[0].name;
var xobj = xobjs.get(name); var xobj = xobjs.get(name);
if (xobj) { if (xobj) {
xobj = xref.fetchIfRef(xobj);
assertWellFormed(isStream(xobj), 'XObject should be a stream'); assertWellFormed(isStream(xobj), 'XObject should be a stream');
var type = xobj.dict.get('Subtype'); var type = xobj.dict.get('Subtype');
@ -336,14 +350,18 @@ var PartialEvaluator = (function partialEvaluator() {
fnArray.push('paintFormXObjectBegin'); fnArray.push('paintFormXObjectBegin');
argsArray.push([matrix, bbox]); argsArray.push([matrix, bbox]);
// This adds the IRQueue of the xObj to the current queue. // This adds the operatorList of the xObj to the current queue.
var depIdx = dependencyArray.length; var depIdx = dependencyArray.length;
this.getIRQueue(xobj, xobj.dict.get('Resources'), queue, // Pass in the current `queue` object. That means the `fnArray`
dependencyArray); // and the `argsArray` in this scope is reused and new commands
// are added to them.
this.getOperatorList(xobj,
xobj.dict.get('Resources') || resources,
dependencyArray, queue);
// Add the dependencies that are required to execute the // Add the dependencies that are required to execute the
// codeIR. // operatorList.
insertDependency(dependencyArray.slice(depIdx)); insertDependency(dependencyArray.slice(depIdx));
fn = 'paintFormXObjectEnd'; fn = 'paintFormXObjectEnd';
@ -367,28 +385,27 @@ var PartialEvaluator = (function partialEvaluator() {
args = [ColorSpace.parseToIR(args[0], xref, resources)]; args = [ColorSpace.parseToIR(args[0], xref, resources)];
break; break;
case 'shadingFill': case 'shadingFill':
var shadingRes = xref.fetchIfRef(res.get('Shading')); var shadingRes = res.get('Shading');
if (!shadingRes) if (!shadingRes)
error('No shading resource found'); error('No shading resource found');
var shading = xref.fetchIfRef(shadingRes.get(args[0].name)); var shading = shadingRes.get(args[0].name);
if (!shading) if (!shading)
error('No shading object found'); error('No shading object found');
var shadingFill = Pattern.parseShading(shading, null, xref, res, var shadingFill = Pattern.parseShading(shading, null, xref, res);
null);
var patternIR = shadingFill.getIR(); var patternIR = shadingFill.getIR();
args = [patternIR]; args = [patternIR];
fn = 'shadingFill'; fn = 'shadingFill';
break; break;
case 'setGState': case 'setGState':
var dictName = args[0]; var dictName = args[0];
var extGState = xref.fetchIfRef(resources.get('ExtGState')); var extGState = resources.get('ExtGState');
if (!isDict(extGState) || !extGState.has(dictName.name)) if (!isDict(extGState) || !extGState.has(dictName.name))
break; break;
var gsState = xref.fetchIfRef(extGState.get(dictName.name)); var gsState = extGState.get(dictName.name);
// This array holds the converted/processed state data. // This array holds the converted/processed state data.
var gsStateObj = []; var gsStateObj = [];
@ -453,10 +470,7 @@ var PartialEvaluator = (function partialEvaluator() {
} }
} }
return { return queue;
fnArray: fnArray,
argsArray: argsArray
};
}, },
extractDataStructures: function extractDataStructures: function
@ -470,7 +484,7 @@ var PartialEvaluator = (function partialEvaluator() {
if (properties.composite) { if (properties.composite) {
// CIDSystemInfo helps to match CID to glyphs // CIDSystemInfo helps to match CID to glyphs
var cidSystemInfo = xref.fetchIfRef(dict.get('CIDSystemInfo')); var cidSystemInfo = dict.get('CIDSystemInfo');
if (isDict(cidSystemInfo)) { if (isDict(cidSystemInfo)) {
properties.cidSystemInfo = { properties.cidSystemInfo = {
registry: cidSystemInfo.get('Registry'), registry: cidSystemInfo.get('Registry'),
@ -479,20 +493,24 @@ var PartialEvaluator = (function partialEvaluator() {
}; };
} }
var cidToGidMap = xref.fetchIfRef(dict.get('CIDToGIDMap')); var cidToGidMap = dict.get('CIDToGIDMap');
if (isStream(cidToGidMap)) if (isStream(cidToGidMap))
properties.cidToGidMap = this.readCidToGidMap(cidToGidMap); properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
} }
var flags = properties.flags;
var differences = []; var differences = [];
var baseEncoding = Encodings.StandardEncoding; var baseEncoding = !!(flags & FontFlags.Symbolic) ?
Encodings.symbolsEncoding : Encodings.StandardEncoding;
var hasEncoding = dict.has('Encoding'); var hasEncoding = dict.has('Encoding');
if (hasEncoding) { if (hasEncoding) {
var encoding = xref.fetchIfRef(dict.get('Encoding')); var encoding = dict.get('Encoding');
if (isDict(encoding)) { if (isDict(encoding)) {
var baseName = encoding.get('BaseEncoding'); var baseName = encoding.get('BaseEncoding');
if (baseName) if (baseName)
baseEncoding = Encodings[baseName.name]; baseEncoding = Encodings[baseName.name];
else
hasEncoding = false; // base encoding was not provided
// Load the differences between the base and original // Load the differences between the base and original
if (encoding.has('Differences')) { if (encoding.has('Differences')) {
@ -512,14 +530,14 @@ var PartialEvaluator = (function partialEvaluator() {
error('Encoding is not a Name nor a Dict'); error('Encoding is not a Name nor a Dict');
} }
} }
properties.differences = differences; properties.differences = differences;
properties.baseEncoding = baseEncoding; properties.baseEncoding = baseEncoding;
properties.hasEncoding = hasEncoding; properties.hasEncoding = hasEncoding;
}, },
readToUnicode: readToUnicode: function PartialEvaluator_readToUnicode(toUnicode, xref) {
function partialEvaluatorReadToUnicode(toUnicode, xref) { var cmapObj = toUnicode;
var cmapObj = xref.fetchIfRef(toUnicode);
var charToUnicode = []; var charToUnicode = [];
if (isName(cmapObj)) { if (isName(cmapObj)) {
var isIdentityMap = cmapObj.name.substr(0, 9) == 'Identity-'; var isIdentityMap = cmapObj.name.substr(0, 9) == 'Identity-';
@ -532,9 +550,9 @@ var PartialEvaluator = (function partialEvaluator() {
var cmap = cmapObj.getBytes(cmapObj.length); var cmap = cmapObj.getBytes(cmapObj.length);
for (var i = 0, ii = cmap.length; i < ii; i++) { for (var i = 0, ii = cmap.length; i < ii; i++) {
var byte = cmap[i]; var octet = cmap[i];
if (byte == 0x20 || byte == 0x0D || byte == 0x0A || if (octet == 0x20 || octet == 0x0D || octet == 0x0A ||
byte == 0x3C || byte == 0x5B || byte == 0x5D) { octet == 0x3C || octet == 0x5B || octet == 0x5D) {
switch (token) { switch (token) {
case 'usecmap': case 'usecmap':
error('usecmap is not implemented'); error('usecmap is not implemented');
@ -554,9 +572,21 @@ var PartialEvaluator = (function partialEvaluator() {
var startRange = tokens[j]; var startRange = tokens[j];
var endRange = tokens[j + 1]; var endRange = tokens[j + 1];
var code = tokens[j + 2]; var code = tokens[j + 2];
while (startRange <= endRange) { if (code == 0xFFFF) {
charToUnicode[startRange] = code++; // CMap is broken, assuming code == startRange
++startRange; code = startRange;
}
if (isArray(code)) {
var codeindex = 0;
while (startRange <= endRange) {
charToUnicode[startRange] = code[codeindex++];
++startRange;
}
} else {
while (startRange <= endRange) {
charToUnicode[startRange] = code++;
++startRange;
}
} }
} }
break; break;
@ -579,7 +609,7 @@ var PartialEvaluator = (function partialEvaluator() {
tokens.push(token); tokens.push(token);
token = ''; token = '';
} }
switch (byte) { switch (octet) {
case 0x5B: case 0x5B:
// begin list parsing // begin list parsing
tokens.push(beginArrayToken); tokens.push(beginArrayToken);
@ -593,21 +623,39 @@ var PartialEvaluator = (function partialEvaluator() {
tokens.push(items); tokens.push(items);
break; break;
} }
} else if (byte == 0x3E) { } else if (octet == 0x3E) {
if (token.length) { if (token.length) {
// parsing hex number if (token.length <= 4) {
tokens.push(parseInt(token, 16)); // parsing hex number
token = ''; tokens.push(parseInt(token, 16));
token = '';
} else {
// parsing hex UTF-16BE numbers
var str = [];
for (var k = 0, kk = token.length; k < kk; k += 4) {
var b = parseInt(token.substr(k, 4), 16);
if (b <= 0x10) {
k += 4;
b = (b << 16) | parseInt(token.substr(k, 4), 16);
b -= 0x10000;
str.push(0xD800 | (b >> 10));
str.push(0xDC00 | (b & 0x3FF));
break;
}
str.push(b);
}
tokens.push(String.fromCharCode.apply(String, str));
token = '';
}
} }
} else { } else {
token += String.fromCharCode(byte); token += String.fromCharCode(octet);
} }
} }
} }
return charToUnicode; return charToUnicode;
}, },
readCidToGidMap: readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) {
function partialEvaluatorReadCidToGidMap(cidToGidStream) {
// Extract the encoding from the CIDToGIDMap // Extract the encoding from the CIDToGIDMap
var glyphsData = cidToGidStream.getBytes(); var glyphsData = cidToGidStream.getBytes();
@ -624,16 +672,16 @@ var PartialEvaluator = (function partialEvaluator() {
return result; return result;
}, },
extractWidths: function partialEvaluatorWidths(dict, extractWidths: function PartialEvaluator_extractWidths(dict,
xref, xref,
descriptor, descriptor,
properties) { properties) {
var glyphsWidths = []; var glyphsWidths = [];
var defaultWidth = 0; var defaultWidth = 0;
if (properties.composite) { if (properties.composite) {
defaultWidth = xref.fetchIfRef(dict.get('DW')) || 1000; defaultWidth = dict.get('DW') || 1000;
var widths = xref.fetchIfRef(dict.get('W')); var widths = dict.get('W');
if (widths) { if (widths) {
var start = 0, end = 0; var start = 0, end = 0;
for (var i = 0, ii = widths.length; i < ii; i++) { for (var i = 0, ii = widths.length; i < ii; i++) {
@ -654,7 +702,7 @@ var PartialEvaluator = (function partialEvaluator() {
} }
} else { } else {
var firstChar = properties.firstChar; var firstChar = properties.firstChar;
var widths = xref.fetchIfRef(dict.get('Widths')); var widths = dict.get('Widths');
if (widths) { if (widths) {
var j = firstChar; var j = firstChar;
for (var i = 0, ii = widths.length; i < ii; i++) for (var i = 0, ii = widths.length; i < ii; i++)
@ -676,7 +724,7 @@ var PartialEvaluator = (function partialEvaluator() {
properties.widths = glyphsWidths; properties.widths = glyphsWidths;
}, },
getBaseFontMetrics: function getBaseFontMetrics(name) { getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
var defaultWidth = 0, widths = []; var defaultWidth = 0, widths = [];
var glyphWidths = Metrics[stdFontMap[name] || name]; var glyphWidths = Metrics[stdFontMap[name] || name];
if (isNum(glyphWidths)) { if (isNum(glyphWidths)) {
@ -691,8 +739,10 @@ var PartialEvaluator = (function partialEvaluator() {
}; };
}, },
translateFont: function partialEvaluatorTranslateFont(dict, xref, resources, translateFont: function PartialEvaluator_translateFont(dict,
dependency) { xref,
resources,
dependency) {
var baseDict = dict; var baseDict = dict;
var type = dict.get('Subtype'); var type = dict.get('Subtype');
assertWellFormed(isName(type), 'invalid font Subtype'); assertWellFormed(isName(type), 'invalid font Subtype');
@ -707,10 +757,7 @@ var PartialEvaluator = (function partialEvaluator() {
if (!df) if (!df)
return null; return null;
if (isRef(df)) dict = isArray(df) ? xref.fetchIfRef(df[0]) : df;
df = xref.fetch(df);
dict = xref.fetchIfRef(isRef(df) ? df : df[0]);
type = dict.get('Subtype'); type = dict.get('Subtype');
assertWellFormed(isName(type), 'invalid font Subtype'); assertWellFormed(isName(type), 'invalid font Subtype');
@ -718,7 +765,7 @@ var PartialEvaluator = (function partialEvaluator() {
} }
var maxCharIndex = composite ? 0xFFFF : 0xFF; var maxCharIndex = composite ? 0xFFFF : 0xFF;
var descriptor = xref.fetchIfRef(dict.get('FontDescriptor')); var descriptor = dict.get('FontDescriptor');
if (!descriptor) { if (!descriptor) {
if (type.name == 'Type3') { if (type.name == 'Type3') {
// FontDescriptor is only required for Type3 fonts when the document // FontDescriptor is only required for Type3 fonts when the document
@ -737,10 +784,18 @@ var PartialEvaluator = (function partialEvaluator() {
baseFontName = baseFontName.name.replace(/[,_]/g, '-'); baseFontName = baseFontName.name.replace(/[,_]/g, '-');
var metrics = this.getBaseFontMetrics(baseFontName); var metrics = this.getBaseFontMetrics(baseFontName);
// Simulating descriptor flags attribute
var fontNameWoStyle = baseFontName.split('-')[0];
var flags = (serifFonts[fontNameWoStyle] ||
(fontNameWoStyle.search(/serif/gi) != -1) ? FontFlags.Serif : 0) |
(symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
FontFlags.Nonsymbolic);
var properties = { var properties = {
type: type.name, type: type.name,
widths: metrics.widths, widths: metrics.widths,
defaultWidth: metrics.defaultWidth, defaultWidth: metrics.defaultWidth,
flags: flags,
firstChar: 0, firstChar: 0,
lastChar: maxCharIndex lastChar: maxCharIndex
}; };
@ -752,34 +807,31 @@ var PartialEvaluator = (function partialEvaluator() {
properties: properties properties: properties
}; };
} }
} }
// According to the spec if 'FontDescriptor' is declared, 'FirstChar', // According to the spec if 'FontDescriptor' is declared, 'FirstChar',
// 'LastChar' and 'Widths' should exists too, but some PDF encoders seems // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem
// to ignore this rule when a variant of a standart font is used. // to ignore this rule when a variant of a standart font is used.
// TODO Fill the width array depending on which of the base font this is // TODO Fill the width array depending on which of the base font this is
// a variant. // a variant.
var firstChar = xref.fetchIfRef(dict.get('FirstChar')) || 0; var firstChar = dict.get('FirstChar') || 0;
var lastChar = xref.fetchIfRef(dict.get('LastChar')) || maxCharIndex; var lastChar = dict.get('LastChar') || maxCharIndex;
var fontName = xref.fetchIfRef(descriptor.get('FontName')); var fontName = descriptor.get('FontName');
// Some bad pdf's have a string as the font name.
if (isString(fontName))
fontName = new Name(fontName);
assertWellFormed(isName(fontName), 'invalid font name'); assertWellFormed(isName(fontName), 'invalid font name');
var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3'); var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
if (fontFile) { if (fontFile) {
fontFile = xref.fetchIfRef(fontFile);
if (fontFile.dict) { if (fontFile.dict) {
var subtype = fontFile.dict.get('Subtype'); var subtype = fontFile.dict.get('Subtype');
if (subtype) if (subtype)
subtype = subtype.name; subtype = subtype.name;
var length1 = fontFile.dict.get('Length1'); var length1 = fontFile.dict.get('Length1');
if (!isInt(length1))
length1 = xref.fetchIfRef(length1);
var length2 = fontFile.dict.get('Length2'); var length2 = fontFile.dict.get('Length2');
if (!isInt(length2))
length2 = xref.fetchIfRef(length2);
} }
} }
@ -808,15 +860,14 @@ var PartialEvaluator = (function partialEvaluator() {
if (type.name === 'Type3') { if (type.name === 'Type3') {
properties.coded = true; properties.coded = true;
var charProcs = xref.fetchIfRef(dict.get('CharProcs')); var charProcs = dict.get('CharProcs').getAll();
var fontResources = xref.fetchIfRef(dict.get('Resources')) || resources; var fontResources = dict.get('Resources') || resources;
properties.resources = fontResources; properties.resources = fontResources;
properties.charProcIRQueues = {}; properties.charProcOperatorList = {};
for (var key in charProcs.map) { for (var key in charProcs) {
var glyphStream = xref.fetchIfRef(charProcs.map[key]); var glyphStream = charProcs[key];
var queueObj = {}; properties.charProcOperatorList[key] =
properties.charProcIRQueues[key] = this.getOperatorList(glyphStream, fontResources, dependency);
this.getIRQueue(glyphStream, fontResources, queueObj, dependency);
} }
} }
@ -829,11 +880,11 @@ var PartialEvaluator = (function partialEvaluator() {
} }
}; };
return constructor; return PartialEvaluator;
})(); })();
var EvalState = (function evalState() { var EvalState = (function EvalStateClosure() {
function constructor() { function EvalState() {
// Are soft masks and alpha values shapes or opacities? // Are soft masks and alpha values shapes or opacities?
this.alphaIsShape = false; this.alphaIsShape = false;
this.fontSize = 0; this.fontSize = 0;
@ -850,8 +901,8 @@ var EvalState = (function evalState() {
this.fillColorSpace = null; this.fillColorSpace = null;
this.strokeColorSpace = null; this.strokeColorSpace = null;
} }
constructor.prototype = { EvalState.prototype = {
}; };
return constructor; return EvalState;
})(); })();

2859
apps/files_pdfviewer/js/pdfjs/src/fonts.js Executable file → Normal file

File diff suppressed because it is too large Load Diff

729
apps/files_pdfviewer/js/pdfjs/src/function.js Executable file → Normal file
View File

@ -3,14 +3,14 @@
'use strict'; 'use strict';
var PDFFunction = (function pdfFunction() { var PDFFunction = (function PDFFunctionClosure() {
var CONSTRUCT_SAMPLED = 0; var CONSTRUCT_SAMPLED = 0;
var CONSTRUCT_INTERPOLATED = 2; var CONSTRUCT_INTERPOLATED = 2;
var CONSTRUCT_STICHED = 3; var CONSTRUCT_STICHED = 3;
var CONSTRUCT_POSTSCRIPT = 4; var CONSTRUCT_POSTSCRIPT = 4;
return { return {
getSampleArray: function pdfFunctionGetSampleArray(size, outputSize, bps, getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
str) { str) {
var length = 1; var length = 1;
for (var i = 0, ii = size.length; i < ii; i++) for (var i = 0, ii = size.length; i < ii; i++)
@ -38,7 +38,7 @@ var PDFFunction = (function pdfFunction() {
return array; return array;
}, },
getIR: function pdfFunctionGetIR(xref, fn) { getIR: function PDFFunction_getIR(xref, fn) {
var dict = fn.dict; var dict = fn.dict;
if (!dict) if (!dict)
dict = fn; dict = fn;
@ -57,7 +57,7 @@ var PDFFunction = (function pdfFunction() {
return typeFn.call(this, fn, dict, xref); return typeFn.call(this, fn, dict, xref);
}, },
fromIR: function pdfFunctionFromIR(IR) { fromIR: function PDFFunction_fromIR(IR) {
var type = IR[0]; var type = IR[0];
switch (type) { switch (type) {
case CONSTRUCT_SAMPLED: case CONSTRUCT_SAMPLED:
@ -72,16 +72,16 @@ var PDFFunction = (function pdfFunction() {
} }
}, },
parse: function pdfFunctionParse(xref, fn) { parse: function PDFFunction_parse(xref, fn) {
var IR = this.getIR(xref, fn); var IR = this.getIR(xref, fn);
return this.fromIR(IR); return this.fromIR(IR);
}, },
constructSampled: function pdfFunctionConstructSampled(str, dict) { constructSampled: function PDFFunction_constructSampled(str, dict) {
function toMultiArray(arr) { function toMultiArray(arr) {
var inputLength = arr.length; var inputLength = arr.length;
var outputLength = arr.length / 2; var outputLength = arr.length / 2;
var out = new Array(outputLength); var out = [];
var index = 0; var index = 0;
for (var i = 0; i < inputLength; i += 2) { for (var i = 0; i < inputLength; i += 2) {
out[index] = [arr[i], arr[i + 1]]; out[index] = [arr[i], arr[i + 1]];
@ -125,114 +125,104 @@ var PDFFunction = (function pdfFunction() {
else else
decode = toMultiArray(decode); decode = toMultiArray(decode);
// Precalc the multipliers
var inputMul = new Float64Array(inputSize);
for (var i = 0; i < inputSize; ++i) {
inputMul[i] = (encode[i][1] - encode[i][0]) /
(domain[i][1] - domain[i][0]);
}
var idxMul = new Int32Array(inputSize);
idxMul[0] = outputSize;
for (i = 1; i < inputSize; ++i) {
idxMul[i] = idxMul[i - 1] * size[i - 1];
}
var nSamples = outputSize;
for (i = 0; i < inputSize; ++i)
nSamples *= size[i];
var samples = this.getSampleArray(size, outputSize, bps, str); var samples = this.getSampleArray(size, outputSize, bps, str);
return [ return [
CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
outputSize, bps, range, inputMul, idxMul, nSamples outputSize, Math.pow(2, bps) - 1, range
]; ];
}, },
constructSampledFromIR: function pdfFunctionConstructSampledFromIR(IR) { constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
var inputSize = IR[1]; // See chapter 3, page 109 of the PDF reference
var domain = IR[2]; function interpolate(x, xmin, xmax, ymin, ymax) {
var encode = IR[3]; return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
var decode = IR[4]; }
var samples = IR[5];
var size = IR[6];
var outputSize = IR[7];
var bps = IR[8];
var range = IR[9];
var inputMul = IR[10];
var idxMul = IR[11];
var nSamples = IR[12];
return function constructSampledFromIRResult(args) { return function constructSampledFromIRResult(args) {
if (inputSize != args.length) // See chapter 3, page 110 of the PDF reference.
var m = IR[1];
var domain = IR[2];
var encode = IR[3];
var decode = IR[4];
var samples = IR[5];
var size = IR[6];
var n = IR[7];
var mask = IR[8];
var range = IR[9];
if (m != args.length)
error('Incorrect number of arguments: ' + inputSize + ' != ' + error('Incorrect number of arguments: ' + inputSize + ' != ' +
args.length); args.length);
// Most of the below is a port of Poppler's implementation.
// TODO: There's a few other ways to do multilinear interpolation such
// as piecewise, which is much faster but an approximation.
var out = new Float64Array(outputSize);
var x;
var e = new Array(inputSize);
var efrac0 = new Float64Array(inputSize);
var efrac1 = new Float64Array(inputSize);
var sBuf = new Float64Array(1 << inputSize);
var i, j, k, idx, t;
// map input values into sample array var x = args;
for (i = 0; i < inputSize; ++i) {
x = (args[i] - domain[i][0]) * inputMul[i] + encode[i][0];
if (x < 0) {
x = 0;
} else if (x > size[i] - 1) {
x = size[i] - 1;
}
e[i] = [Math.floor(x), 0];
if ((e[i][1] = e[i][0] + 1) >= size[i]) {
// this happens if in[i] = domain[i][1]
e[i][1] = e[i][0];
}
efrac1[i] = x - e[i][0];
efrac0[i] = 1 - efrac1[i];
}
// for each output, do m-linear interpolation // Building the cube vertices: its part and sample index
for (i = 0; i < outputSize; ++i) { // http://rjwagner49.com/Mathematics/Interpolation.pdf
var cubeVertices = 1 << m;
var cubeN = new Float64Array(cubeVertices);
var cubeVertex = new Uint32Array(cubeVertices);
for (var j = 0; j < cubeVertices; j++)
cubeN[j] = 1;
// pull 2^m values out of the sample array var k = n, pos = 1;
for (j = 0; j < (1 << inputSize); ++j) { // Map x_i to y_j for 0 <= i < m using the sampled function.
idx = i; for (var i = 0; i < m; ++i) {
for (k = 0, t = j; k < inputSize; ++k, t >>= 1) { // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
idx += idxMul[k] * (e[k][t & 1]); var domain_2i = domain[i][0];
} var domain_2i_1 = domain[i][1];
if (idx >= 0 && idx < nSamples) { var xi = Math.min(Math.max(x[i], domain_2i), domain_2i_1);
sBuf[j] = samples[idx];
// e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
// Encode_2i, Encode_2i+1)
var e = interpolate(xi, domain_2i, domain_2i_1,
encode[i][0], encode[i][1]);
// e_i' = min(max(e_i, 0), Size_i - 1)
var size_i = size[i];
e = Math.min(Math.max(e, 0), size_i - 1);
// Adjusting the cube: N and vertex sample index
var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
var n1 = e - e0; // (e - e0) / (e1 - e0);
var offset0 = e0 * k;
var offset1 = offset0 + k; // e1 * k
for (var j = 0; j < cubeVertices; j++) {
if (j & pos) {
cubeN[j] *= n1;
cubeVertex[j] += offset1;
} else { } else {
sBuf[j] = 0; // TODO Investigate if this is what Adobe does cubeN[j] *= n0;
cubeVertex[j] += offset0;
} }
} }
// do m sets of interpolations k *= size_i;
for (j = 0, t = (1 << inputSize); j < inputSize; ++j, t >>= 1) { pos <<= 1;
for (k = 0; k < t; k += 2) {
sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k + 1];
}
}
// map output value to range
out[i] = (sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0]);
if (out[i] < range[i][0]) {
out[i] = range[i][0];
} else if (out[i] > range[i][1]) {
out[i] = range[i][1];
}
} }
return out;
var y = new Float64Array(n);
for (var j = 0; j < n; ++j) {
// Sum all cube vertices' samples portions
var rj = 0;
for (var i = 0; i < cubeVertices; i++)
rj += samples[cubeVertex[i] + j] * cubeN[i];
// r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
// Decode_2j, Decode_2j+1)
rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
// y_j = min(max(r_j, range_2j), range_2j+1)
y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
}
return y;
} }
}, },
constructInterpolated: constructInterpolated: function PDFFunction_constructInterpolated(str,
function pdfFunctionConstructInterpolated(str, dict) { dict) {
var c0 = dict.get('C0') || [0]; var c0 = dict.get('C0') || [0];
var c1 = dict.get('C1') || [1]; var c1 = dict.get('C1') || [1];
var n = dict.get('N'); var n = dict.get('N');
@ -249,7 +239,7 @@ var PDFFunction = (function pdfFunction() {
}, },
constructInterpolatedFromIR: constructInterpolatedFromIR:
function pdfFunctionconstructInterpolatedFromIR(IR) { function PDFFunction_constructInterpolatedFromIR(IR) {
var c0 = IR[1]; var c0 = IR[1];
var diff = IR[2]; var diff = IR[2];
var n = IR[3]; var n = IR[3];
@ -268,9 +258,8 @@ var PDFFunction = (function pdfFunction() {
} }
}, },
constructStiched: function pdfFunctionConstructStiched(fn, dict, xref) { constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
var domain = dict.get('Domain'); var domain = dict.get('Domain');
var range = dict.get('Range');
if (!domain) if (!domain)
error('No domain'); error('No domain');
@ -290,7 +279,7 @@ var PDFFunction = (function pdfFunction() {
return [CONSTRUCT_STICHED, domain, bounds, encode, fns]; return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
}, },
constructStichedFromIR: function pdfFunctionConstructStichedFromIR(IR) { constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) {
var domain = IR[1]; var domain = IR[1];
var bounds = IR[2]; var bounds = IR[2];
var encode = IR[3]; var encode = IR[3];
@ -336,16 +325,550 @@ var PDFFunction = (function pdfFunction() {
}; };
}, },
constructPostScript: function pdfFunctionConstructPostScript() { constructPostScript: function PDFFunction_constructPostScript(fn, dict,
return [CONSTRUCT_POSTSCRIPT]; xref) {
var domain = dict.get('Domain');
var range = dict.get('Range');
if (!domain)
error('No domain.');
if (!range)
error('No range.');
var lexer = new PostScriptLexer(fn);
var parser = new PostScriptParser(lexer);
var code = parser.parse();
return [CONSTRUCT_POSTSCRIPT, domain, range, code];
}, },
constructPostScriptFromIR: function pdfFunctionConstructPostScriptFromIR() { constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(
TODO('unhandled type of function'); IR) {
return function constructPostScriptFromIRResult() { var domain = IR[1];
return [255, 105, 180]; var range = IR[2];
var code = IR[3];
var numOutputs = range.length / 2;
var evaluator = new PostScriptEvaluator(code);
// Cache the values for a big speed up, the cache size is limited though
// since the number of possible values can be huge from a PS function.
var cache = new FunctionCache();
return function constructPostScriptFromIRResult(args) {
var initialStack = [];
for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
initialStack.push(args[i]);
}
var key = initialStack.join('_');
if (cache.has(key))
return cache.get(key);
var stack = evaluator.execute(initialStack);
var transformed = [];
for (i = numOutputs - 1; i >= 0; --i) {
var out = stack.pop();
var rangeIndex = 2 * i;
if (out < range[rangeIndex])
out = range[rangeIndex];
else if (out > range[rangeIndex + 1])
out = range[rangeIndex + 1];
transformed[i] = out;
}
cache.set(key, transformed);
return transformed;
}; };
} }
}; };
})(); })();
var FunctionCache = (function FunctionCacheClosure() {
// Of 10 PDF's with type4 functions the maxium number of distinct values seen
// was 256. This still may need some tweaking in the future though.
var MAX_CACHE_SIZE = 1024;
function FunctionCache() {
this.cache = {};
this.total = 0;
}
FunctionCache.prototype = {
has: function FunctionCache_has(key) {
return key in this.cache;
},
get: function FunctionCache_get(key) {
return this.cache[key];
},
set: function FunctionCache_set(key, value) {
if (this.total < MAX_CACHE_SIZE) {
this.cache[key] = value;
this.total++;
}
}
};
return FunctionCache;
})();
var PostScriptStack = (function PostScriptStackClosure() {
var MAX_STACK_SIZE = 100;
function PostScriptStack(initialStack) {
this.stack = initialStack || [];
}
PostScriptStack.prototype = {
push: function PostScriptStack_push(value) {
if (this.stack.length >= MAX_STACK_SIZE)
error('PostScript function stack overflow.');
this.stack.push(value);
},
pop: function PostScriptStack_pop() {
if (this.stack.length <= 0)
error('PostScript function stack underflow.');
return this.stack.pop();
},
copy: function PostScriptStack_copy(n) {
if (this.stack.length + n >= MAX_STACK_SIZE)
error('PostScript function stack overflow.');
var stack = this.stack;
for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++)
stack.push(stack[i]);
},
index: function PostScriptStack_index(n) {
this.push(this.stack[this.stack.length - n - 1]);
},
// rotate the last n stack elements p times
roll: function PostScriptStack_roll(n, p) {
var stack = this.stack;
var l = stack.length - n;
var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
for (i = l, j = r; i < j; i++, j--) {
t = stack[i]; stack[i] = stack[j]; stack[j] = t;
}
for (i = l, j = c - 1; i < j; i++, j--) {
t = stack[i]; stack[i] = stack[j]; stack[j] = t;
}
for (i = c, j = r; i < j; i++, j--) {
t = stack[i]; stack[i] = stack[j]; stack[j] = t;
}
}
};
return PostScriptStack;
})();
var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
function PostScriptEvaluator(operators, operands) {
this.operators = operators;
this.operands = operands;
}
PostScriptEvaluator.prototype = {
execute: function PostScriptEvaluator_execute(initialStack) {
var stack = new PostScriptStack(initialStack);
var counter = 0;
var operators = this.operators;
var length = operators.length;
var operator, a, b;
while (counter < length) {
operator = operators[counter++];
if (typeof operator == 'number') {
// Operator is really an operand and should be pushed to the stack.
stack.push(operator);
continue;
}
switch (operator) {
// non standard ps operators
case 'jz': // jump if false
b = stack.pop();
a = stack.pop();
if (!a)
counter = b;
break;
case 'j': // jump
a = stack.pop();
counter = a;
break;
// all ps operators in alphabetical order (excluding if/ifelse)
case 'abs':
a = stack.pop();
stack.push(Math.abs(a));
break;
case 'add':
b = stack.pop();
a = stack.pop();
stack.push(a + b);
break;
case 'and':
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b))
stack.push(a && b);
else
stack.push(a & b);
break;
case 'atan':
a = stack.pop();
stack.push(Math.atan(a));
break;
case 'bitshift':
b = stack.pop();
a = stack.pop();
if (a > 0)
stack.push(a << b);
else
stack.push(a >> b);
break;
case 'ceiling':
a = stack.pop();
stack.push(Math.ceil(a));
break;
case 'copy':
a = stack.pop();
stack.copy(a);
break;
case 'cos':
a = stack.pop();
stack.push(Math.cos(a));
break;
case 'cvi':
a = stack.pop() | 0;
stack.push(a);
break;
case 'cvr':
// noop
break;
case 'div':
b = stack.pop();
a = stack.pop();
stack.push(a / b);
break;
case 'dup':
stack.copy(1);
break;
case 'eq':
b = stack.pop();
a = stack.pop();
stack.push(a == b);
break;
case 'exch':
stack.roll(2, 1);
break;
case 'exp':
b = stack.pop();
a = stack.pop();
stack.push(Math.pow(a, b));
break;
case 'false':
stack.push(false);
break;
case 'floor':
a = stack.pop();
stack.push(Math.floor(a));
break;
case 'ge':
b = stack.pop();
a = stack.pop();
stack.push(a >= b);
break;
case 'gt':
b = stack.pop();
a = stack.pop();
stack.push(a > b);
break;
case 'idiv':
b = stack.pop();
a = stack.pop();
stack.push((a / b) | 0);
break;
case 'index':
a = stack.pop();
stack.index(a);
break;
case 'le':
b = stack.pop();
a = stack.pop();
stack.push(a <= b);
break;
case 'ln':
a = stack.pop();
stack.push(Math.log(a));
break;
case 'log':
a = stack.pop();
stack.push(Math.log(a) / Math.LN10);
break;
case 'lt':
b = stack.pop();
a = stack.pop();
stack.push(a < b);
break;
case 'mod':
b = stack.pop();
a = stack.pop();
stack.push(a % b);
break;
case 'mul':
b = stack.pop();
a = stack.pop();
stack.push(a * b);
break;
case 'ne':
b = stack.pop();
a = stack.pop();
stack.push(a != b);
break;
case 'neg':
a = stack.pop();
stack.push(-b);
break;
case 'not':
a = stack.pop();
if (isBool(a) && isBool(b))
stack.push(a && b);
else
stack.push(a & b);
break;
case 'or':
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b))
stack.push(a || b);
else
stack.push(a | b);
break;
case 'pop':
stack.pop();
break;
case 'roll':
b = stack.pop();
a = stack.pop();
stack.roll(a, b);
break;
case 'round':
a = stack.pop();
stack.push(Math.round(a));
break;
case 'sin':
a = stack.pop();
stack.push(Math.sin(a));
break;
case 'sqrt':
a = stack.pop();
stack.push(Math.sqrt(a));
break;
case 'sub':
b = stack.pop();
a = stack.pop();
stack.push(a - b);
break;
case 'true':
stack.push(true);
break;
case 'truncate':
a = stack.pop();
a = a < 0 ? Math.ceil(a) : Math.floor(a);
stack.push(a);
break;
case 'xor':
b = stack.pop();
a = stack.pop();
if (isBool(a) && isBool(b))
stack.push(a != b);
else
stack.push(a ^ b);
break;
default:
error('Unknown operator ' + operator);
break;
}
}
return stack.stack;
}
};
return PostScriptEvaluator;
})();
var PostScriptParser = (function PostScriptParserClosure() {
function PostScriptParser(lexer) {
this.lexer = lexer;
this.operators = [];
this.token;
this.prev;
}
PostScriptParser.prototype = {
nextToken: function PostScriptParser_nextToken() {
this.prev = this.token;
this.token = this.lexer.getToken();
},
accept: function PostScriptParser_accept(type) {
if (this.token.type == type) {
this.nextToken();
return true;
}
return false;
},
expect: function PostScriptParser_expect(type) {
if (this.accept(type))
return true;
error('Unexpected symbol: found ' + this.token.type + ' expected ' +
type + '.');
},
parse: function PostScriptParser_parse() {
this.nextToken();
this.expect(PostScriptTokenTypes.LBRACE);
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
return this.operators;
},
parseBlock: function PostScriptParser_parseBlock() {
while (true) {
if (this.accept(PostScriptTokenTypes.NUMBER)) {
this.operators.push(this.prev.value);
} else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
this.operators.push(this.prev.value);
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
this.parseCondition();
} else {
return;
}
}
},
parseCondition: function PostScriptParser_parseCondition() {
// Add two place holders that will be updated later
var conditionLocation = this.operators.length;
this.operators.push(null, null);
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
if (this.accept(PostScriptTokenTypes.IF)) {
// The true block is right after the 'if' so it just falls through on
// true else it jumps and skips the true block.
this.operators[conditionLocation] = this.operators.length;
this.operators[conditionLocation + 1] = 'jz';
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
var jumpLocation = this.operators.length;
this.operators.push(null, null);
var endOfTrue = this.operators.length;
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
this.expect(PostScriptTokenTypes.IFELSE);
// The jump is added at the end of the true block to skip the false
// block.
this.operators[jumpLocation] = this.operators.length;
this.operators[jumpLocation + 1] = 'j';
this.operators[conditionLocation] = endOfTrue;
this.operators[conditionLocation + 1] = 'jz';
} else {
error('PS Function: error parsing conditional.');
}
}
};
return PostScriptParser;
})();
var PostScriptTokenTypes = {
LBRACE: 0,
RBRACE: 1,
NUMBER: 2,
OPERATOR: 3,
IF: 4,
IFELSE: 5
};
var PostScriptToken = (function PostScriptTokenClosure() {
function PostScriptToken(type, value) {
this.type = type;
this.value = value;
}
var opCache = {};
PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
var opValue = opCache[op];
if (opValue)
return opValue;
return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
};
PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
'{');
PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
'}');
PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
'IFELSE');
return PostScriptToken;
})();
var PostScriptLexer = (function PostScriptLexerClosure() {
function PostScriptLexer(stream) {
this.stream = stream;
}
PostScriptLexer.prototype = {
getToken: function PostScriptLexer_getToken() {
var s = '';
var ch;
var comment = false;
var stream = this.stream;
// skip comments
while (true) {
if (!(ch = stream.getChar()))
return EOF;
if (comment) {
if (ch == '\x0a' || ch == '\x0d')
comment = false;
} else if (ch == '%') {
comment = true;
} else if (!Lexer.isSpace(ch)) {
break;
}
}
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '+': case '-': case '.':
return new PostScriptToken(PostScriptTokenTypes.NUMBER,
this.getNumber(ch));
case '{':
return PostScriptToken.LBRACE;
case '}':
return PostScriptToken.RBRACE;
}
// operator
var str = ch.toLowerCase();
while (true) {
ch = stream.lookChar().toLowerCase();
if (ch >= 'a' && ch <= 'z')
str += ch;
else
break;
stream.skip();
}
switch (str) {
case 'if':
return PostScriptToken.IF;
case 'ifelse':
return PostScriptToken.IFELSE;
default:
return PostScriptToken.getOperator(str);
}
},
getNumber: function PostScriptLexer_getNumber(ch) {
var str = ch;
var stream = this.stream;
while (true) {
ch = stream.lookChar();
if ((ch >= '0' && ch <= '9') || ch == '-' || ch == '.')
str += ch;
else
break;
stream.skip();
}
var value = parseFloat(str);
if (isNaN(value))
error('Invalid floating point number: ' + value);
return value;
}
};
return PostScriptLexer;
})();

84
apps/files_pdfviewer/js/pdfjs/src/glyphlist.js Executable file → Normal file
View File

@ -1508,27 +1508,7 @@ var GlyphsUnicode = {
dalet: 0x05D3, dalet: 0x05D3,
daletdagesh: 0xFB33, daletdagesh: 0xFB33,
daletdageshhebrew: 0xFB33, daletdageshhebrew: 0xFB33,
dalethatafpatah: 0x05D305B2,
dalethatafpatahhebrew: 0x05D305B2,
dalethatafsegol: 0x05D305B1,
dalethatafsegolhebrew: 0x05D305B1,
dalethebrew: 0x05D3, dalethebrew: 0x05D3,
dalethiriq: 0x05D305B4,
dalethiriqhebrew: 0x05D305B4,
daletholam: 0x05D305B9,
daletholamhebrew: 0x05D305B9,
daletpatah: 0x05D305B7,
daletpatahhebrew: 0x05D305B7,
daletqamats: 0x05D305B8,
daletqamatshebrew: 0x05D305B8,
daletqubuts: 0x05D305BB,
daletqubutshebrew: 0x05D305BB,
daletsegol: 0x05D305B6,
daletsegolhebrew: 0x05D305B6,
daletsheva: 0x05D305B0,
daletshevahebrew: 0x05D305B0,
dalettsere: 0x05D305B5,
dalettserehebrew: 0x05D305B5,
dalfinalarabic: 0xFEAA, dalfinalarabic: 0xFEAA,
dammaarabic: 0x064F, dammaarabic: 0x064F,
dammalowarabic: 0x064F, dammalowarabic: 0x064F,
@ -1845,10 +1825,6 @@ var GlyphsUnicode = {
finalkafdagesh: 0xFB3A, finalkafdagesh: 0xFB3A,
finalkafdageshhebrew: 0xFB3A, finalkafdageshhebrew: 0xFB3A,
finalkafhebrew: 0x05DA, finalkafhebrew: 0x05DA,
finalkafqamats: 0x05DA05B8,
finalkafqamatshebrew: 0x05DA05B8,
finalkafsheva: 0x05DA05B0,
finalkafshevahebrew: 0x05DA05B0,
finalmem: 0x05DD, finalmem: 0x05DD,
finalmemhebrew: 0x05DD, finalmemhebrew: 0x05DD,
finalnun: 0x05DF, finalnun: 0x05DF,
@ -2037,14 +2013,7 @@ var GlyphsUnicode = {
hakatakanahalfwidth: 0xFF8A, hakatakanahalfwidth: 0xFF8A,
halantgurmukhi: 0x0A4D, halantgurmukhi: 0x0A4D,
hamzaarabic: 0x0621, hamzaarabic: 0x0621,
hamzadammaarabic: 0x0621064F,
hamzadammatanarabic: 0x0621064C,
hamzafathaarabic: 0x0621064E,
hamzafathatanarabic: 0x0621064B,
hamzalowarabic: 0x0621, hamzalowarabic: 0x0621,
hamzalowkasraarabic: 0x06210650,
hamzalowkasratanarabic: 0x0621064D,
hamzasukunarabic: 0x06210652,
hangulfiller: 0x3164, hangulfiller: 0x3164,
hardsigncyrillic: 0x044A, hardsigncyrillic: 0x044A,
harpoonleftbarbup: 0x21BC, harpoonleftbarbup: 0x21BC,
@ -2476,10 +2445,6 @@ var GlyphsUnicode = {
lameddagesh: 0xFB3C, lameddagesh: 0xFB3C,
lameddageshhebrew: 0xFB3C, lameddageshhebrew: 0xFB3C,
lamedhebrew: 0x05DC, lamedhebrew: 0x05DC,
lamedholam: 0x05DC05B9,
lamedholamdagesh: '05DC 05B9 05BC',
lamedholamdageshhebrew: '05DC 05B9 05BC',
lamedholamhebrew: 0x05DC05B9,
lamfinalarabic: 0xFEDE, lamfinalarabic: 0xFEDE,
lamhahinitialarabic: 0xFCCA, lamhahinitialarabic: 0xFCCA,
laminitialarabic: 0xFEDF, laminitialarabic: 0xFEDF,
@ -2489,8 +2454,6 @@ var GlyphsUnicode = {
lammedialarabic: 0xFEE0, lammedialarabic: 0xFEE0,
lammeemhahinitialarabic: 0xFD88, lammeemhahinitialarabic: 0xFD88,
lammeeminitialarabic: 0xFCCC, lammeeminitialarabic: 0xFCCC,
lammeemjeeminitialarabic: 'FEDF FEE4 FEA0',
lammeemkhahinitialarabic: 'FEDF FEE4 FEA8',
largecircle: 0x25EF, largecircle: 0x25EF,
lbar: 0x019A, lbar: 0x019A,
lbelt: 0x026C, lbelt: 0x026C,
@ -2787,7 +2750,6 @@ var GlyphsUnicode = {
noonfinalarabic: 0xFEE6, noonfinalarabic: 0xFEE6,
noonghunnaarabic: 0x06BA, noonghunnaarabic: 0x06BA,
noonghunnafinalarabic: 0xFB9F, noonghunnafinalarabic: 0xFB9F,
noonhehinitialarabic: 0xFEE7FEEC,
nooninitialarabic: 0xFEE7, nooninitialarabic: 0xFEE7,
noonjeeminitialarabic: 0xFCD2, noonjeeminitialarabic: 0xFCD2,
noonjeemisolatedarabic: 0xFC4B, noonjeemisolatedarabic: 0xFC4B,
@ -3159,27 +3121,7 @@ var GlyphsUnicode = {
qof: 0x05E7, qof: 0x05E7,
qofdagesh: 0xFB47, qofdagesh: 0xFB47,
qofdageshhebrew: 0xFB47, qofdageshhebrew: 0xFB47,
qofhatafpatah: 0x05E705B2,
qofhatafpatahhebrew: 0x05E705B2,
qofhatafsegol: 0x05E705B1,
qofhatafsegolhebrew: 0x05E705B1,
qofhebrew: 0x05E7, qofhebrew: 0x05E7,
qofhiriq: 0x05E705B4,
qofhiriqhebrew: 0x05E705B4,
qofholam: 0x05E705B9,
qofholamhebrew: 0x05E705B9,
qofpatah: 0x05E705B7,
qofpatahhebrew: 0x05E705B7,
qofqamats: 0x05E705B8,
qofqamatshebrew: 0x05E705B8,
qofqubuts: 0x05E705BB,
qofqubutshebrew: 0x05E705BB,
qofsegol: 0x05E705B6,
qofsegolhebrew: 0x05E705B6,
qofsheva: 0x05E705B0,
qofshevahebrew: 0x05E705B0,
qoftsere: 0x05E705B5,
qoftserehebrew: 0x05E705B5,
qparen: 0x24AC, qparen: 0x24AC,
quarternote: 0x2669, quarternote: 0x2669,
qubuts: 0x05BB, qubuts: 0x05BB,
@ -3253,32 +3195,11 @@ var GlyphsUnicode = {
reharmenian: 0x0580, reharmenian: 0x0580,
rehfinalarabic: 0xFEAE, rehfinalarabic: 0xFEAE,
rehiragana: 0x308C, rehiragana: 0x308C,
rehyehaleflamarabic: '0631 FEF3 FE8E 0644',
rekatakana: 0x30EC, rekatakana: 0x30EC,
rekatakanahalfwidth: 0xFF9A, rekatakanahalfwidth: 0xFF9A,
resh: 0x05E8, resh: 0x05E8,
reshdageshhebrew: 0xFB48, reshdageshhebrew: 0xFB48,
reshhatafpatah: 0x05E805B2,
reshhatafpatahhebrew: 0x05E805B2,
reshhatafsegol: 0x05E805B1,
reshhatafsegolhebrew: 0x05E805B1,
reshhebrew: 0x05E8, reshhebrew: 0x05E8,
reshhiriq: 0x05E805B4,
reshhiriqhebrew: 0x05E805B4,
reshholam: 0x05E805B9,
reshholamhebrew: 0x05E805B9,
reshpatah: 0x05E805B7,
reshpatahhebrew: 0x05E805B7,
reshqamats: 0x05E805B8,
reshqamatshebrew: 0x05E805B8,
reshqubuts: 0x05E805BB,
reshqubutshebrew: 0x05E805BB,
reshsegol: 0x05E805B6,
reshsegolhebrew: 0x05E805B6,
reshsheva: 0x05E805B0,
reshshevahebrew: 0x05E805B0,
reshtsere: 0x05E805B5,
reshtserehebrew: 0x05E805B5,
reversedtilde: 0x223D, reversedtilde: 0x223D,
reviahebrew: 0x0597, reviahebrew: 0x0597,
reviamugrashhebrew: 0x0597, reviamugrashhebrew: 0x0597,
@ -3477,7 +3398,6 @@ var GlyphsUnicode = {
shaddadammaarabic: 0xFC61, shaddadammaarabic: 0xFC61,
shaddadammatanarabic: 0xFC5E, shaddadammatanarabic: 0xFC5E,
shaddafathaarabic: 0xFC60, shaddafathaarabic: 0xFC60,
shaddafathatanarabic: 0x0651064B,
shaddakasraarabic: 0xFC62, shaddakasraarabic: 0xFC62,
shaddakasratanarabic: 0xFC5F, shaddakasratanarabic: 0xFC5F,
shade: 0x2592, shade: 0x2592,
@ -3674,7 +3594,6 @@ var GlyphsUnicode = {
tchehfinalarabic: 0xFB7B, tchehfinalarabic: 0xFB7B,
tchehinitialarabic: 0xFB7C, tchehinitialarabic: 0xFB7C,
tchehmedialarabic: 0xFB7D, tchehmedialarabic: 0xFB7D,
tchehmeeminitialarabic: 0xFB7CFEE4,
tcircle: 0x24E3, tcircle: 0x24E3,
tcircumflexbelow: 0x1E71, tcircumflexbelow: 0x1E71,
tcommaaccent: 0x0163, tcommaaccent: 0x0163,
@ -4287,6 +4206,7 @@ var GlyphsUnicode = {
zretroflexhook: 0x0290, zretroflexhook: 0x0290,
zstroke: 0x01B6, zstroke: 0x01B6,
zuhiragana: 0x305A, zuhiragana: 0x305A,
zukatakana: 0x30BA zukatakana: 0x30BA,
'.notdef': 0x0000
}; };

270
apps/files_pdfviewer/js/pdfjs/src/image.js Executable file → Normal file
View File

@ -3,8 +3,37 @@
'use strict'; 'use strict';
var PDFImage = (function pdfImage() { var PDFImage = (function PDFImageClosure() {
function constructor(xref, res, image, inline) { /**
* Decode the image in the main thread if it supported. Resovles the promise
* when the image data is ready.
*/
function handleImageData(handler, xref, res, image, promise) {
if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) {
// For natively supported jpegs send them to the main thread for decoding.
var dict = image.dict;
var colorSpace = dict.get('ColorSpace', 'CS');
colorSpace = ColorSpace.parse(colorSpace, xref, res);
var numComps = colorSpace.numComps;
handler.send('jpeg_decode', [image.getIR(), numComps], function(message) {
var data = message.data;
var stream = new Stream(data, 0, data.length, image.dict);
promise.resolve(stream);
});
} else {
promise.resolve(image);
}
}
/**
* Decode and clamp a value. The formula is different from the spec because we
* don't decode to float range [0,1], we decode it in the [0,max] range.
*/
function decodeAndClamp(value, addend, coefficient, max) {
value = addend + value * coefficient;
// Clamp the value to the range
return value < 0 ? 0 : value > max ? max : value;
}
function PDFImage(xref, res, image, inline, smask) {
this.image = image; this.image = image;
if (image.getParams) { if (image.getParams) {
// JPX/JPEG2000 streams directly contain bits per component // JPX/JPEG2000 streams directly contain bits per component
@ -49,34 +78,143 @@ var PDFImage = (function pdfImage() {
} }
this.decode = dict.get('Decode', 'D'); this.decode = dict.get('Decode', 'D');
this.needsDecode = false;
if (this.decode && this.colorSpace &&
!this.colorSpace.isDefaultDecode(this.decode)) {
this.needsDecode = true;
// Do some preprocessing to avoid more math.
var max = (1 << bitsPerComponent) - 1;
this.decodeCoefficients = [];
this.decodeAddends = [];
for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
var dmin = this.decode[i];
var dmax = this.decode[i + 1];
this.decodeCoefficients[j] = dmax - dmin;
this.decodeAddends[j] = max * dmin;
}
}
var mask = xref.fetchIfRef(dict.get('Mask')); var mask = dict.get('Mask');
var smask = xref.fetchIfRef(dict.get('SMask'));
if (mask) { if (mask) {
TODO('masked images'); TODO('masked images');
} else if (smask) { } else if (smask) {
this.smask = new PDFImage(xref, res, smask); this.smask = new PDFImage(xref, res, smask, false);
} }
} }
/**
* Handles processing of image data and calls the callback with an argument
* of a PDFImage when the image is ready to be used.
*/
PDFImage.buildImage = function PDFImage_buildImage(callback, handler, xref,
res, image, inline) {
var imageDataPromise = new Promise();
var smaskPromise = new Promise();
// The image data and smask data may not be ready yet, wait till both are
// resolved.
Promise.all([imageDataPromise, smaskPromise]).then(function(results) {
var imageData = results[0], smaskData = results[1];
var image = new PDFImage(xref, res, imageData, inline, smaskData);
callback(image);
});
constructor.prototype = { handleImageData(handler, xref, res, image, imageDataPromise);
getComponents: function getComponents(buffer, decodeMap) {
var smask = image.dict.get('SMask');
if (smask)
handleImageData(handler, xref, res, smask, smaskPromise);
else
smaskPromise.resolve(null);
};
/**
* Resize an image using the nearest neighbor algorithm. Currently only
* supports one and three component images.
* @param {TypedArray} pixels The original image with one component.
* @param {Number} bpc Number of bits per component.
* @param {Number} components Number of color components, 1 or 3 is supported.
* @param {Number} w1 Original width.
* @param {Number} h1 Original height.
* @param {Number} w2 New width.
* @param {Number} h2 New height.
* @return {TypedArray} Resized image data.
*/
PDFImage.resize = function PDFImage_resize(pixels, bpc, components,
w1, h1, w2, h2) {
var length = w2 * h2 * components;
var temp = bpc <= 8 ? new Uint8Array(length) :
bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
var xRatio = w1 / w2;
var yRatio = h1 / h2;
var px, py, newIndex, oldIndex;
for (var i = 0; i < h2; i++) {
for (var j = 0; j < w2; j++) {
px = Math.floor(j * xRatio);
py = Math.floor(i * yRatio);
newIndex = (i * w2) + j;
oldIndex = ((py * w1) + px);
if (components === 1) {
temp[newIndex] = pixels[oldIndex];
} else if (components === 3) {
newIndex *= 3;
oldIndex *= 3;
temp[newIndex] = pixels[oldIndex];
temp[newIndex + 1] = pixels[oldIndex + 1];
temp[newIndex + 2] = pixels[oldIndex + 2];
}
}
}
return temp;
};
PDFImage.prototype = {
get drawWidth() {
if (!this.smask)
return this.width;
return Math.max(this.width, this.smask.width);
},
get drawHeight() {
if (!this.smask)
return this.height;
return Math.max(this.height, this.smask.height);
},
getComponents: function PDFImage_getComponents(buffer) {
var bpc = this.bpc; var bpc = this.bpc;
if (bpc == 8) var needsDecode = this.needsDecode;
var decodeMap = this.decode;
// This image doesn't require any extra work.
if (bpc == 8 && !needsDecode)
return buffer; return buffer;
var bufferLength = buffer.length;
var width = this.width; var width = this.width;
var height = this.height; var height = this.height;
var numComps = this.numComps; var numComps = this.numComps;
var length = width * height; var length = width * height * numComps;
var bufferPos = 0; var bufferPos = 0;
var output = bpc <= 8 ? new Uint8Array(length) : var output = bpc <= 8 ? new Uint8Array(length) :
bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length); bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
var rowComps = width * numComps; var rowComps = width * numComps;
var decodeAddends, decodeCoefficients;
if (needsDecode) {
decodeAddends = this.decodeAddends;
decodeCoefficients = this.decodeCoefficients;
}
var max = (1 << bpc) - 1;
if (bpc == 1) { if (bpc == 8) {
// Optimization for reading 8 bpc images that have a decode.
for (var i = 0, ii = length; i < ii; ++i) {
var compIndex = i % numComps;
var value = buffer[i];
value = decodeAndClamp(value, decodeAddends[compIndex],
decodeCoefficients[compIndex], max);
output[i] = value;
}
} else if (bpc == 1) {
// Optimization for reading 1 bpc images.
var valueZero = 0, valueOne = 1; var valueZero = 0, valueOne = 1;
if (decodeMap) { if (decodeMap) {
valueZero = decodeMap[0] ? 1 : 0; valueZero = decodeMap[0] ? 1 : 0;
@ -101,8 +239,7 @@ var PDFImage = (function pdfImage() {
output[i] = !(buf & mask) ? valueZero : valueOne; output[i] = !(buf & mask) ? valueZero : valueOne;
} }
} else { } else {
if (decodeMap != null) // The general case that handles all other bpc values.
TODO('interpolate component values');
var bits = 0, buf = 0; var bits = 0, buf = 0;
for (var i = 0, ii = length; i < ii; ++i) { for (var i = 0, ii = length; i < ii; ++i) {
if (i % rowComps == 0) { if (i % rowComps == 0) {
@ -116,51 +253,44 @@ var PDFImage = (function pdfImage() {
} }
var remainingBits = bits - bpc; var remainingBits = bits - bpc;
output[i] = buf >> remainingBits; var value = buf >> remainingBits;
if (needsDecode) {
var compIndex = i % numComps;
value = decodeAndClamp(value, decodeAddends[compIndex],
decodeCoefficients[compIndex], max);
}
output[i] = value;
buf = buf & ((1 << remainingBits) - 1); buf = buf & ((1 << remainingBits) - 1);
bits = remainingBits; bits = remainingBits;
} }
} }
return output; return output;
}, },
getOpacity: function getOpacity() { getOpacity: function PDFImage_getOpacity(width, height) {
var smask = this.smask; var smask = this.smask;
var width = this.width; var originalWidth = this.width;
var height = this.height; var originalHeight = this.height;
var buf = new Uint8Array(width * height); var buf;
if (smask) { if (smask) {
if (smask.image.getImage) {
// smask is a DOM image
var tempCanvas = new ScratchCanvas(width, height);
var tempCtx = tempCanvas.getContext('2d');
var domImage = smask.image.getImage();
tempCtx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
0, 0, width, height);
var data = tempCtx.getImageData(0, 0, width, height).data;
for (var i = 0, j = 0, ii = width * height; i < ii; ++i, j += 4)
buf[i] = data[j]; // getting first component value
return buf;
}
var sw = smask.width; var sw = smask.width;
var sh = smask.height; var sh = smask.height;
if (sw != this.width || sh != this.height) buf = new Uint8Array(sw * sh);
error('smask dimensions do not match image dimensions: ' + sw +
' != ' + this.width + ', ' + sh + ' != ' + this.height);
smask.fillGrayBuffer(buf); smask.fillGrayBuffer(buf);
return buf; if (sw != width || sh != height)
buf = PDFImage.resize(buf, smask.bps, 1, sw, sh, width, height);
} else { } else {
buf = new Uint8Array(width * height);
for (var i = 0, ii = width * height; i < ii; ++i) for (var i = 0, ii = width * height; i < ii; ++i)
buf[i] = 255; buf[i] = 255;
} }
return buf; return buf;
}, },
applyStencilMask: function applyStencilMask(buffer, inverseDecode) { applyStencilMask: function PDFImage_applyStencilMask(buffer,
inverseDecode) {
var width = this.width, height = this.height; var width = this.width, height = this.height;
var bitStrideLength = (width + 7) >> 3; var bitStrideLength = (width + 7) >> 3;
this.image.reset(); var imgArray = this.getImageBytes(bitStrideLength * height);
var imgArray = this.image.getBytes(bitStrideLength * height);
var imgArrayPos = 0; var imgArrayPos = 0;
var i, j, mask, buf; var i, j, mask, buf;
// removing making non-masked pixels transparent // removing making non-masked pixels transparent
@ -180,21 +310,23 @@ var PDFImage = (function pdfImage() {
} }
} }
}, },
fillRgbaBuffer: function fillRgbaBuffer(buffer, decodeMap) { fillRgbaBuffer: function PDFImage_fillRgbaBuffer(buffer, width, height) {
var numComps = this.numComps; var numComps = this.numComps;
var width = this.width; var originalWidth = this.width;
var height = this.height; var originalHeight = this.height;
var bpc = this.bpc; var bpc = this.bpc;
// rows start at byte boundary; // rows start at byte boundary;
var rowBytes = (width * numComps * bpc + 7) >> 3; var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
this.image.reset(); var imgArray = this.getImageBytes(originalHeight * rowBytes);
var imgArray = this.image.getBytes(height * rowBytes);
var comps = this.colorSpace.getRgbBuffer( var comps = this.colorSpace.getRgbBuffer(
this.getComponents(imgArray, decodeMap), bpc); this.getComponents(imgArray), bpc);
if (originalWidth != width || originalHeight != height)
comps = PDFImage.resize(comps, this.bpc, 3, originalWidth,
originalHeight, width, height);
var compsPos = 0; var compsPos = 0;
var opacity = this.getOpacity(); var opacity = this.getOpacity(width, height);
var opacityPos = 0; var opacityPos = 0;
var length = width * height * 4; var length = width * height * 4;
@ -205,7 +337,7 @@ var PDFImage = (function pdfImage() {
buffer[i + 3] = opacity[opacityPos++]; buffer[i + 3] = opacity[opacityPos++];
} }
}, },
fillGrayBuffer: function fillGrayBuffer(buffer) { fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) {
var numComps = this.numComps; var numComps = this.numComps;
if (numComps != 1) if (numComps != 1)
error('Reading gray scale from a color image: ' + numComps); error('Reading gray scale from a color image: ' + numComps);
@ -216,42 +348,28 @@ var PDFImage = (function pdfImage() {
// rows start at byte boundary; // rows start at byte boundary;
var rowBytes = (width * numComps * bpc + 7) >> 3; var rowBytes = (width * numComps * bpc + 7) >> 3;
this.image.reset(); var imgArray = this.getImageBytes(height * rowBytes);
var imgArray = this.image.getBytes(height * rowBytes);
var comps = this.getComponents(imgArray); var comps = this.getComponents(imgArray);
var length = width * height; var length = width * height;
// we aren't using a colorspace so we need to scale the value
var scale = 255 / ((1 << bpc) - 1);
for (var i = 0; i < length; ++i) for (var i = 0; i < length; ++i)
buffer[i] = comps[i]; buffer[i] = (scale * comps[i]) | 0;
},
getImageBytes: function PDFImage_getImageBytes(length) {
this.image.reset();
return this.image.getBytes(length);
} }
}; };
return constructor; return PDFImage;
})(); })();
var JpegImageLoader = (function jpegImage() { function loadJpegStream(id, imageData, objs) {
function JpegImageLoader(objId, imageData, objs) { var img = new Image();
var src = 'data:image/jpeg;base64,' + window.btoa(imageData); img.onload = (function loadJpegStream_onloadClosure() {
objs.resolve(id, img);
var img = new Image(); });
img.onload = (function jpegImageLoaderOnload() { img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
this.loaded = true; }
objs.resolve(objId, this);
if (this.onLoad)
this.onLoad();
}).bind(this);
img.src = src;
this.domImage = img;
}
JpegImageLoader.prototype = {
getImage: function jpegImageLoaderGetImage() {
return this.domImage;
}
};
return JpegImageLoader;
})();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,66 @@
/* -*- 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 Metadata = PDFJS.Metadata = (function MetadataClosure() {
function Metadata(meta) {
if (typeof meta === 'string') {
var parser = new DOMParser();
meta = parser.parseFromString(meta, 'application/xml');
} else if (!(meta instanceof Document)) {
error('Metadata: Invalid metadata object');
}
this.metaDocument = meta;
this.metadata = {};
this.parse();
}
Metadata.prototype = {
parse: function Metadata_parse() {
var doc = this.metaDocument;
var rdf = doc.documentElement;
if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in <xmpmeta>
rdf = rdf.firstChild;
while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf')
rdf = rdf.nextSibling;
}
var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes())
return;
var childNodes = rdf.childNodes, desc, namespace, entries, entry;
for (var i = 0, length = childNodes.length; i < length; i++) {
desc = childNodes[i];
if (desc.nodeName.toLowerCase() !== 'rdf:description')
continue;
entries = [];
for (var ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text')
entries.push(desc.childNodes[ii]);
}
for (ii = 0, iLength = entries.length; ii < iLength; ii++) {
var entry = entries[ii];
var name = entry.nodeName.toLowerCase();
this.metadata[name] = entry.textContent.trim();
}
}
},
get: function Metadata_get(name) {
return this.metadata[name] || null;
},
has: function Metadata_has(name) {
return typeof this.metadata[name] !== 'undefined';
}
};
return Metadata;
})();

3
apps/files_pdfviewer/js/pdfjs/src/metrics.js Executable file → Normal file
View File

@ -3,6 +3,9 @@
'use strict'; 'use strict';
// The Metrics object contains glyph widths (in glyph space units).
// As per PDF spec, for most fonts (Type 3 being an exception) a glyph
// space unit corresponds to 1/1000th of text space unit.
var Metrics = { var Metrics = {
'Courier': 600, 'Courier': 600,
'Courier-Bold': 600, 'Courier-Bold': 600,

416
apps/files_pdfviewer/js/pdfjs/src/obj.js Executable file → Normal file
View File

@ -3,121 +3,157 @@
'use strict'; 'use strict';
var Name = (function nameName() { var Name = (function NameClosure() {
function constructor(name) { function Name(name) {
this.name = name; this.name = name;
} }
constructor.prototype = { Name.prototype = {};
};
return constructor; return Name;
})(); })();
var Cmd = (function cmdCmd() { var Cmd = (function CmdClosure() {
function constructor(cmd) { function Cmd(cmd) {
this.cmd = cmd; this.cmd = cmd;
} }
constructor.prototype = { Cmd.prototype = {};
var cmdCache = {};
Cmd.get = function Cmd_get(cmd) {
var cmdValue = cmdCache[cmd];
if (cmdValue)
return cmdValue;
return cmdCache[cmd] = new Cmd(cmd);
}; };
return constructor; return Cmd;
})(); })();
var Dict = (function dictDict() { var Dict = (function DictClosure() {
function constructor() { // xref is optional
function Dict(xref) {
// Map should only be used internally, use functions below to access.
this.map = Object.create(null); this.map = Object.create(null);
this.xref = xref;
} }
constructor.prototype = { Dict.prototype = {
get: function dictGet(key1, key2, key3) { // automatically dereferences Ref objects
get: function Dict_get(key1, key2, key3) {
var value; var value;
var xref = this.xref;
if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map || if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
typeof key2 == 'undefined') { typeof key2 == 'undefined') {
return value; return xref ? this.xref.fetchIfRef(value) : value;
} }
if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map || if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map ||
typeof key3 == 'undefined') { typeof key3 == 'undefined') {
return value; return xref ? this.xref.fetchIfRef(value) : value;
} }
value = this.map[key3] || null;
return this.map[key3] || null; return xref ? this.xref.fetchIfRef(value) : value;
},
// no dereferencing
getRaw: function Dict_getRaw(key) {
return this.map[key];
},
// creates new map and dereferences all Refs
getAll: function Dict_getAll() {
var all = {};
for (var key in this.map)
all[key] = this.get(key);
return all;
}, },
set: function dictSet(key, value) { set: function Dict_set(key, value) {
this.map[key] = value; this.map[key] = value;
}, },
has: function dictHas(key) { has: function Dict_has(key) {
return key in this.map; return key in this.map;
}, },
forEach: function dictForEach(callback) { forEach: function Dict_forEach(callback) {
for (var key in this.map) { for (var key in this.map) {
callback(key, this.map[key]); callback(key, this.get(key));
} }
} }
}; };
return constructor; return Dict;
})(); })();
var Ref = (function refRef() { var Ref = (function RefClosure() {
function constructor(num, gen) { function Ref(num, gen) {
this.num = num; this.num = num;
this.gen = gen; this.gen = gen;
} }
constructor.prototype = { Ref.prototype = {};
};
return constructor; return Ref;
})(); })();
// The reference is identified by number and generation, // The reference is identified by number and generation,
// this structure stores only one instance of the reference. // this structure stores only one instance of the reference.
var RefSet = (function refSet() { var RefSet = (function RefSetClosure() {
function constructor() { function RefSet() {
this.dict = {}; this.dict = {};
} }
constructor.prototype = { RefSet.prototype = {
has: function refSetHas(ref) { has: function RefSet_has(ref) {
return !!this.dict['R' + ref.num + '.' + ref.gen]; return !!this.dict['R' + ref.num + '.' + ref.gen];
}, },
put: function refSetPut(ref) { put: function RefSet_put(ref) {
this.dict['R' + ref.num + '.' + ref.gen] = ref; this.dict['R' + ref.num + '.' + ref.gen] = ref;
} }
}; };
return constructor; return RefSet;
})(); })();
var Catalog = (function catalogCatalog() { var Catalog = (function CatalogClosure() {
function constructor(xref) { function Catalog(xref) {
this.xref = xref; this.xref = xref;
var obj = xref.getCatalogObj(); var obj = xref.getCatalogObj();
assertWellFormed(isDict(obj), 'catalog object is not a dictionary'); assertWellFormed(isDict(obj), 'catalog object is not a dictionary');
this.catDict = obj; this.catDict = obj;
} }
constructor.prototype = { Catalog.prototype = {
get metadata() {
var stream = this.catDict.get('Metadata');
var metadata;
if (stream && isDict(stream.dict)) {
var type = stream.dict.get('Type');
var subtype = stream.dict.get('Subtype');
if (isName(type) && isName(subtype) &&
type.name === 'Metadata' && subtype.name === 'XML') {
metadata = stringToPDFString(bytesToString(stream.getBytes()));
}
}
return shadow(this, 'metadata', metadata);
},
get toplevelPagesDict() { get toplevelPagesDict() {
var pagesObj = this.catDict.get('Pages'); var pagesObj = this.catDict.get('Pages');
assertWellFormed(isRef(pagesObj), 'invalid top-level pages reference'); assertWellFormed(isDict(pagesObj), 'invalid top-level pages dictionary');
var xrefObj = this.xref.fetch(pagesObj);
assertWellFormed(isDict(xrefObj), 'invalid top-level pages dictionary');
// shadow the prototype getter // shadow the prototype getter
return shadow(this, 'toplevelPagesDict', xrefObj); return shadow(this, 'toplevelPagesDict', pagesObj);
}, },
get documentOutline() { get documentOutline() {
var obj = this.catDict.get('Outlines');
var xref = this.xref; var xref = this.xref;
var obj = this.catDict.get('Outlines');
var root = { items: [] }; var root = { items: [] };
if (isRef(obj)) { if (isDict(obj)) {
obj = xref.fetch(obj).get('First'); obj = obj.getRaw('First');
var processed = new RefSet(); var processed = new RefSet();
if (isRef(obj)) { if (isRef(obj)) {
var queue = [{obj: obj, parent: root}]; var queue = [{obj: obj, parent: root}];
@ -126,18 +162,20 @@ var Catalog = (function catalogCatalog() {
processed.put(obj); processed.put(obj);
while (queue.length > 0) { while (queue.length > 0) {
var i = queue.shift(); var i = queue.shift();
var outlineDict = xref.fetch(i.obj); var outlineDict = xref.fetchIfRef(i.obj);
if (outlineDict === null)
continue;
if (!outlineDict.has('Title')) if (!outlineDict.has('Title'))
error('Invalid outline item'); error('Invalid outline item');
var dest = outlineDict.get('A'); var dest = outlineDict.get('A');
if (dest) if (dest)
dest = xref.fetchIfRef(dest).get('D'); dest = dest.get('D');
else if (outlineDict.has('Dest')) { else if (outlineDict.has('Dest')) {
dest = outlineDict.get('Dest'); dest = outlineDict.getRaw('Dest');
if (isName(dest)) if (isName(dest))
dest = dest.name; dest = dest.name;
} }
var title = xref.fetchIfRef(outlineDict.get('Title')); var title = outlineDict.get('Title');
var outlineItem = { var outlineItem = {
dest: dest, dest: dest,
title: stringToPDFString(title), title: stringToPDFString(title),
@ -148,12 +186,12 @@ var Catalog = (function catalogCatalog() {
items: [] items: []
}; };
i.parent.items.push(outlineItem); i.parent.items.push(outlineItem);
obj = outlineDict.get('First'); obj = outlineDict.getRaw('First');
if (isRef(obj) && !processed.has(obj)) { if (isRef(obj) && !processed.has(obj)) {
queue.push({obj: obj, parent: outlineItem}); queue.push({obj: obj, parent: outlineItem});
processed.put(obj); processed.put(obj);
} }
obj = outlineDict.get('Next'); obj = outlineDict.getRaw('Next');
if (isRef(obj) && !processed.has(obj)) { if (isRef(obj) && !processed.has(obj)) {
queue.push({obj: obj, parent: i.parent}); queue.push({obj: obj, parent: i.parent});
processed.put(obj); processed.put(obj);
@ -173,7 +211,7 @@ var Catalog = (function catalogCatalog() {
// shadow the prototype getter // shadow the prototype getter
return shadow(this, 'num', obj); return shadow(this, 'num', obj);
}, },
traverseKids: function catalogTraverseKids(pagesDict) { traverseKids: function Catalog_traverseKids(pagesDict) {
var pageCache = this.pageCache; var pageCache = this.pageCache;
var kids = pagesDict.get('Kids'); var kids = pagesDict.get('Kids');
assertWellFormed(isArray(kids), assertWellFormed(isArray(kids),
@ -181,7 +219,7 @@ var Catalog = (function catalogCatalog() {
for (var i = 0, ii = kids.length; i < ii; ++i) { for (var i = 0, ii = kids.length; i < ii; ++i) {
var kid = kids[i]; var kid = kids[i];
assertWellFormed(isRef(kid), assertWellFormed(isRef(kid),
'page dictionary kid is not a reference'); 'page dictionary kid is not a reference');
var obj = this.xref.fetch(kid); var obj = this.xref.fetch(kid);
if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) { if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) {
pageCache.push(new Page(this.xref, pageCache.length, obj, kid)); pageCache.push(new Page(this.xref, pageCache.length, obj, kid));
@ -195,8 +233,7 @@ var Catalog = (function catalogCatalog() {
} }
}, },
get destinations() { get destinations() {
function fetchDestination(xref, ref) { function fetchDestination(dest) {
var dest = xref.fetchIfRef(ref);
return isDict(dest) ? dest.get('D') : dest; return isDict(dest) ? dest.get('D') : dest;
} }
@ -204,16 +241,16 @@ var Catalog = (function catalogCatalog() {
var dests = {}, nameTreeRef, nameDictionaryRef; var dests = {}, nameTreeRef, nameDictionaryRef;
var obj = this.catDict.get('Names'); var obj = this.catDict.get('Names');
if (obj) if (obj)
nameTreeRef = xref.fetchIfRef(obj).get('Dests'); nameTreeRef = obj.getRaw('Dests');
else if (this.catDict.has('Dests')) else if (this.catDict.has('Dests'))
nameDictionaryRef = this.catDict.get('Dests'); nameDictionaryRef = this.catDict.get('Dests');
if (nameDictionaryRef) { if (nameDictionaryRef) {
// reading simple destination dictionary // reading simple destination dictionary
obj = xref.fetchIfRef(nameDictionaryRef); obj = nameDictionaryRef;
obj.forEach(function catalogForEach(key, value) { obj.forEach(function catalogForEach(key, value) {
if (!value) return; if (!value) return;
dests[key] = fetchDestination(xref, value); dests[key] = fetchDestination(value);
}); });
} }
if (nameTreeRef) { if (nameTreeRef) {
@ -237,13 +274,13 @@ var Catalog = (function catalogCatalog() {
} }
var names = obj.get('Names'); var names = obj.get('Names');
for (i = 0, n = names.length; i < n; i += 2) { for (i = 0, n = names.length; i < n; i += 2) {
dests[names[i]] = fetchDestination(xref, names[i + 1]); dests[names[i]] = fetchDestination(xref.fetchIfRef(names[i + 1]));
} }
} }
} }
return shadow(this, 'destinations', dests); return shadow(this, 'destinations', dests);
}, },
getPage: function catalogGetPage(n) { getPage: function Catalog_getPage(n) {
var pageCache = this.pageCache; var pageCache = this.pageCache;
if (!pageCache) { if (!pageCache) {
pageCache = this.pageCache = []; pageCache = this.pageCache = [];
@ -253,105 +290,101 @@ var Catalog = (function catalogCatalog() {
} }
}; };
return constructor; return Catalog;
})(); })();
var XRef = (function xRefXRef() { var XRef = (function XRefClosure() {
function constructor(stream, startXRef, mainXRefEntriesOffset) { function XRef(stream, startXRef, mainXRefEntriesOffset) {
this.stream = stream; this.stream = stream;
this.entries = []; this.entries = [];
this.xrefstms = {}; this.xrefstms = {};
var trailerDict = this.readXRef(startXRef); var trailerDict = this.readXRef(startXRef);
trailerDict.xref = this;
this.trailer = trailerDict;
// prepare the XRef cache // prepare the XRef cache
this.cache = []; this.cache = [];
var encrypt = trailerDict.get('Encrypt'); var encrypt = trailerDict.get('Encrypt');
if (encrypt) { if (encrypt) {
var fileId = trailerDict.get('ID'); var fileId = trailerDict.get('ID');
this.encrypt = new CipherTransformFactory(this.fetch(encrypt), this.encrypt = new CipherTransformFactory(encrypt,
fileId[0] /*, password */); fileId[0] /*, password */);
} }
// get the root dictionary (catalog) object // get the root dictionary (catalog) object
if (!isRef(this.root = trailerDict.get('Root'))) if (!(this.root = trailerDict.get('Root')))
error('Invalid root reference'); error('Invalid root reference');
} }
constructor.prototype = { XRef.prototype = {
readXRefTable: function readXRefTable(parser) { readXRefTable: function XRef_readXRefTable(parser) {
// Example of cross-reference table:
// xref
// 0 1 <-- subsection header (first obj #, obj count)
// 0000000000 65535 f <-- actual object (offset, generation #, f/n)
// 23 2 <-- subsection header ... and so on ...
// 0000025518 00002 n
// 0000025635 00000 n
// trailer
// ...
// Outer loop is over subsection headers
var obj; var obj;
while (true) { while (!isCmd(obj = parser.getObj(), 'trailer')) {
if (isCmd(obj = parser.getObj(), 'trailer')) var first = obj,
break; count = parser.getObj();
if (!isInt(obj))
error('Invalid XRef table'); if (!isInt(first) || !isInt(count))
var first = obj; error('Invalid XRef table: wrong types in subsection header');
if (!isInt(obj = parser.getObj()))
error('Invalid XRef table'); // Inner loop is over objects themselves
var n = obj; for (var i = 0; i < count; i++) {
if (first < 0 || n < 0 || (first + n) != ((first + n) | 0))
error('Invalid XRef table: ' + first + ', ' + n);
for (var i = first; i < first + n; ++i) {
var entry = {}; var entry = {};
if (!isInt(obj = parser.getObj())) entry.offset = parser.getObj();
error('Invalid XRef table: ' + first + ', ' + n); entry.gen = parser.getObj();
entry.offset = obj; var type = parser.getObj();
if (!isInt(obj = parser.getObj()))
error('Invalid XRef table: ' + first + ', ' + n); if (isCmd(type, 'f'))
entry.gen = obj;
obj = parser.getObj();
if (isCmd(obj, 'n')) {
entry.uncompressed = true;
} else if (isCmd(obj, 'f')) {
entry.free = true; entry.free = true;
} else { else if (isCmd(type, 'n'))
error('Invalid XRef table: ' + first + ', ' + n); entry.uncompressed = true;
}
if (!this.entries[i]) { // Validate entry obj
// In some buggy PDF files the xref table claims to start at 1 if (!isInt(entry.offset) || !isInt(entry.gen) ||
// instead of 0. !(entry.free || entry.uncompressed)) {
if (i == 1 && first == 1 && error('Invalid entry in XRef subsection: ' + first + ', ' + count);
entry.offset == 0 && entry.gen == 65535 && entry.free) {
i = first = 0;
}
this.entries[i] = entry;
} }
if (!this.entries[i + first])
this.entries[i + first] = entry;
} }
} }
// read the trailer dictionary // Sanity check: as per spec, first object must have these properties
var dict; if (this.entries[0] &&
if (!isDict(dict = parser.getObj())) !(this.entries[0].gen === 65535 && this.entries[0].free))
error('Invalid XRef table'); error('Invalid XRef table: unexpected first object');
// get the 'Prev' pointer // Sanity check
var prev; if (!isCmd(obj, 'trailer'))
obj = dict.get('Prev'); error('Invalid XRef table: could not find trailer dictionary');
if (isInt(obj)) {
prev = obj;
} else if (isRef(obj)) {
// certain buggy PDF generators generate "/Prev NNN 0 R" instead
// of "/Prev NNN"
prev = obj.num;
}
if (prev) {
this.readXRef(prev);
}
// check for 'XRefStm' key // Read trailer dictionary, e.g.
if (isInt(obj = dict.get('XRefStm'))) { // trailer
var pos = obj; // << /Size 22
// ignore previously loaded xref streams (possible infinite recursion) // /Root 20R
if (!(pos in this.xrefstms)) { // /Info 10R
this.xrefstms[pos] = 1; // /ID [ <81b14aafa313db63dbd6f981e49f94f4> ]
this.readXRef(pos); // >>
} // The parser goes through the entire stream << ... >> and provides
} // a getter interface for the key-value table
var dict = parser.getObj();
if (!isDict(dict))
error('Invalid XRef table: could not parse trailer dictionary');
return dict; return dict;
}, },
readXRefStream: function readXRefStream(stream) { readXRefStream: function XRef_readXRefStream(stream) {
var streamParameters = stream.parameters; var streamParameters = stream.parameters;
var byteWidths = streamParameters.get('W'); var byteWidths = streamParameters.get('W');
var range = streamParameters.get('Index'); var range = streamParameters.get('Index');
@ -400,12 +433,9 @@ var XRef = (function xRefXRef() {
} }
range.splice(0, 2); range.splice(0, 2);
} }
var prev = streamParameters.get('Prev');
if (isInt(prev))
this.readXRef(prev);
return streamParameters; return streamParameters;
}, },
indexObjects: function indexObjects() { indexObjects: function XRef_indexObjects() {
// Simple scan through the PDF content to find objects, // Simple scan through the PDF content to find objects,
// trailers and XRef streams. // trailers and XRef streams.
function readToken(data, offset) { function readToken(data, offset) {
@ -497,7 +527,7 @@ var XRef = (function xRefXRef() {
var dict; var dict;
for (var i = 0, ii = trailers.length; i < ii; ++i) { for (var i = 0, ii = trailers.length; i < ii; ++i) {
stream.pos = trailers[i]; stream.pos = trailers[i];
var parser = new Parser(new Lexer(stream), true); var parser = new Parser(new Lexer(stream), true, null);
var obj = parser.getObj(); var obj = parser.getObj();
if (!isCmd(obj, 'trailer')) if (!isCmd(obj, 'trailer'))
continue; continue;
@ -513,50 +543,88 @@ var XRef = (function xRefXRef() {
return dict; return dict;
// nothing helps // nothing helps
error('Invalid PDF structure'); error('Invalid PDF structure');
return null;
}, },
readXRef: function readXref(startXRef) { readXRef: function XRef_readXRef(startXRef) {
var stream = this.stream; var stream = this.stream;
stream.pos = startXRef; stream.pos = startXRef;
var parser = new Parser(new Lexer(stream), true);
var obj = parser.getObj(); try {
// parse an old-style xref table var parser = new Parser(new Lexer(stream), true, null);
if (isCmd(obj, 'xref')) var obj = parser.getObj();
return this.readXRefTable(parser); var dict;
// parse an xref stream
if (isInt(obj)) { // Get dictionary
if (!isInt(parser.getObj()) || if (isCmd(obj, 'xref')) {
!isCmd(parser.getObj(), 'obj') || // Parse end-of-file XRef
!isStream(obj = parser.getObj())) { dict = this.readXRefTable(parser);
error('Invalid XRef stream');
// Recursively get other XRefs 'XRefStm', if any
obj = dict.get('XRefStm');
if (isInt(obj)) {
var pos = obj;
// ignore previously loaded xref streams
// (possible infinite recursion)
if (!(pos in this.xrefstms)) {
this.xrefstms[pos] = 1;
this.readXRef(pos);
}
}
} else if (isInt(obj)) {
// Parse in-stream XRef
if (!isInt(parser.getObj()) ||
!isCmd(parser.getObj(), 'obj') ||
!isStream(obj = parser.getObj())) {
error('Invalid XRef stream');
}
dict = this.readXRefStream(obj);
} }
return this.readXRefStream(obj);
// Recursively get previous dictionary, if any
obj = dict.get('Prev');
if (isInt(obj))
this.readXRef(obj);
else if (isRef(obj)) {
// The spec says Prev must not be a reference, i.e. "/Prev NNN"
// This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R"
this.readXRef(obj.num);
}
return dict;
} catch (e) {
log('(while reading XRef): ' + e);
} }
warn('Indexing all PDF objects');
return this.indexObjects(); return this.indexObjects();
}, },
getEntry: function xRefGetEntry(i) { getEntry: function XRef_getEntry(i) {
var e = this.entries[i]; var e = this.entries[i];
if (e.free) if (e === null)
error('reading an XRef stream not implemented yet'); return null;
return e; return e.free ? null : e; // returns null is the entry is free
}, },
fetchIfRef: function xRefFetchIfRef(obj) { fetchIfRef: function XRef_fetchIfRef(obj) {
if (!isRef(obj)) if (!isRef(obj))
return obj; return obj;
return this.fetch(obj); return this.fetch(obj);
}, },
fetch: function xRefFetch(ref, suppressEncryption) { fetch: function XRef_fetch(ref, suppressEncryption) {
assertWellFormed(isRef(ref), 'ref object is not a reference');
var num = ref.num; var num = ref.num;
var e = this.cache[num]; if (num in this.cache)
if (e) return this.cache[num];
return e;
var e = this.getEntry(num);
// the referenced entry can be free
if (e === null)
return (this.cache[num] = e);
e = this.getEntry(num);
var gen = ref.gen; var gen = ref.gen;
var stream, parser; var stream, parser;
if (e.uncompressed) { if (e.uncompressed) {
if (e.gen != gen) if (e.gen != gen)
throw ('inconsistent generation in XRef'); error('inconsistent generation in XRef');
stream = this.stream.makeSubStream(e.offset); stream = this.stream.makeSubStream(e.offset);
parser = new Parser(new Lexer(stream), true, this); parser = new Parser(new Lexer(stream), true, this);
var obj1 = parser.getObj(); var obj1 = parser.getObj();
@ -589,7 +657,7 @@ var XRef = (function xRefXRef() {
e = parser.getObj(); e = parser.getObj();
} }
// Don't cache streams since they are mutable (except images). // Don't cache streams since they are mutable (except images).
if (!isStream(e) || e.getImage) if (!isStream(e) || e instanceof JpegStream)
this.cache[num] = e; this.cache[num] = e;
return e; return e;
} }
@ -603,7 +671,7 @@ var XRef = (function xRefXRef() {
if (!isInt(first) || !isInt(n)) { if (!isInt(first) || !isInt(n)) {
error('invalid first and n parameters for ObjStm stream'); error('invalid first and n parameters for ObjStm stream');
} }
parser = new Parser(new Lexer(stream), false); parser = new Parser(new Lexer(stream), false, this);
var i, entries = [], nums = []; var i, entries = [], nums = [];
// read the object numbers to populate cache // read the object numbers to populate cache
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
@ -628,12 +696,12 @@ var XRef = (function xRefXRef() {
} }
return e; return e;
}, },
getCatalogObj: function xRefGetCatalogObj() { getCatalogObj: function XRef_getCatalogObj() {
return this.fetch(this.root); return this.root;
} }
}; };
return constructor; return XRef;
})(); })();
/** /**
@ -642,7 +710,7 @@ var XRef = (function xRefXRef() {
* inside of a worker. The `PDFObjects` implements some basic functions to * inside of a worker. The `PDFObjects` implements some basic functions to
* manage these objects. * manage these objects.
*/ */
var PDFObjects = (function pdfObjects() { var PDFObjects = (function PDFObjectsClosure() {
function PDFObjects() { function PDFObjects() {
this.objs = {}; this.objs = {};
} }
@ -655,7 +723,7 @@ var PDFObjects = (function pdfObjects() {
* Ensures there is an object defined for `objId`. Stores `data` on the * Ensures there is an object defined for `objId`. Stores `data` on the
* object *if* it is created. * object *if* it is created.
*/ */
ensureObj: function pdfObjectsEnsureObj(objId, data) { ensureObj: function PDFObjects_ensureObj(objId, data) {
if (this.objs[objId]) if (this.objs[objId])
return this.objs[objId]; return this.objs[objId];
return this.objs[objId] = new Promise(objId, data); return this.objs[objId] = new Promise(objId, data);
@ -670,7 +738,7 @@ var PDFObjects = (function pdfObjects() {
* function and the object is already resolved, the callback gets called * function and the object is already resolved, the callback gets called
* right away. * right away.
*/ */
get: function pdfObjectsGet(objId, callback) { get: function PDFObjects_get(objId, callback) {
// If there is a callback, then the get can be async and the object is // If there is a callback, then the get can be async and the object is
// not required to be resolved right now // not required to be resolved right now
if (callback) { if (callback) {
@ -684,18 +752,16 @@ var PDFObjects = (function pdfObjects() {
// If there isn't an object yet or the object isn't resolved, then the // If there isn't an object yet or the object isn't resolved, then the
// data isn't ready yet! // data isn't ready yet!
if (!obj || !obj.isResolved) { if (!obj || !obj.isResolved)
throw 'Requesting object that isn\'t resolved yet ' + objId; error('Requesting object that isn\'t resolved yet ' + objId);
return null;
} else { return obj.data;
return obj.data;
}
}, },
/** /**
* Resolves the object `objId` with optional `data`. * Resolves the object `objId` with optional `data`.
*/ */
resolve: function pdfObjectsResolve(objId, data) { resolve: function PDFObjects_resolve(objId, data) {
var objs = this.objs; var objs = this.objs;
// In case there is a promise already on this object, just resolve it. // In case there is a promise already on this object, just resolve it.
@ -706,11 +772,11 @@ var PDFObjects = (function pdfObjects() {
} }
}, },
onData: function pdfObjectsOnData(objId, callback) { onData: function PDFObjects_onData(objId, callback) {
this.ensureObj(objId).onData(callback); this.ensureObj(objId).onData(callback);
}, },
isResolved: function pdfObjectsIsResolved(objId) { isResolved: function PDFObjects_isResolved(objId) {
var objs = this.objs; var objs = this.objs;
if (!objs[objId]) { if (!objs[objId]) {
return false; return false;
@ -719,7 +785,7 @@ var PDFObjects = (function pdfObjects() {
} }
}, },
hasData: function pdfObjectsHasData(objId) { hasData: function PDFObjects_hasData(objId) {
var objs = this.objs; var objs = this.objs;
if (!objs[objId]) { if (!objs[objId]) {
return false; return false;
@ -731,7 +797,7 @@ var PDFObjects = (function pdfObjects() {
/** /**
* Sets the data of an object but *doesn't* resolve it. * Sets the data of an object but *doesn't* resolve it.
*/ */
setData: function pdfObjectsSetData(objId, data) { setData: function PDFObjects_setData(objId, data) {
// Watchout! If you call `this.ensureObj(objId, data)` you're going to // Watchout! If you call `this.ensureObj(objId, data)` you're going to
// create a *resolved* promise which shouldn't be the case! // create a *resolved* promise which shouldn't be the case!
this.ensureObj(objId).data = data; this.ensureObj(objId).data = data;

181
apps/files_pdfviewer/js/pdfjs/src/parser.js Executable file → Normal file
View File

@ -9,8 +9,8 @@ function isEOF(v) {
return v == EOF; return v == EOF;
} }
var Parser = (function parserParser() { var Parser = (function ParserClosure() {
function constructor(lexer, allowStreams, xref) { function Parser(lexer, allowStreams, xref) {
this.lexer = lexer; this.lexer = lexer;
this.allowStreams = allowStreams; this.allowStreams = allowStreams;
this.xref = xref; this.xref = xref;
@ -18,12 +18,12 @@ var Parser = (function parserParser() {
this.refill(); this.refill();
} }
constructor.prototype = { Parser.prototype = {
refill: function parserRefill() { refill: function Parser_refill() {
this.buf1 = this.lexer.getObj(); this.buf1 = this.lexer.getObj();
this.buf2 = this.lexer.getObj(); this.buf2 = this.lexer.getObj();
}, },
shift: function parserShift() { shift: function Parser_shift() {
if (isCmd(this.buf2, 'ID')) { if (isCmd(this.buf2, 'ID')) {
this.buf1 = this.buf2; this.buf1 = this.buf2;
this.buf2 = null; this.buf2 = null;
@ -34,7 +34,7 @@ var Parser = (function parserParser() {
this.buf2 = this.lexer.getObj(); this.buf2 = this.lexer.getObj();
} }
}, },
getObj: function parserGetObj(cipherTransform) { getObj: function Parser_getObj(cipherTransform) {
if (isCmd(this.buf1, 'BI')) { // inline image if (isCmd(this.buf1, 'BI')) { // inline image
this.shift(); this.shift();
return this.makeInlineImage(cipherTransform); return this.makeInlineImage(cipherTransform);
@ -51,17 +51,16 @@ var Parser = (function parserParser() {
} }
if (isCmd(this.buf1, '<<')) { // dictionary or stream if (isCmd(this.buf1, '<<')) { // dictionary or stream
this.shift(); this.shift();
var dict = new Dict(); var dict = new Dict(this.xref);
while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) { while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
if (!isName(this.buf1)) { if (!isName(this.buf1))
error('Dictionary key must be a name object'); error('Dictionary key must be a name object');
} else {
var key = this.buf1.name; var key = this.buf1.name;
this.shift(); this.shift();
if (isEOF(this.buf1)) if (isEOF(this.buf1))
break; break;
dict.set(key, this.getObj(cipherTransform)); dict.set(key, this.getObj(cipherTransform));
}
} }
if (isEOF(this.buf1)) if (isEOF(this.buf1))
error('End of file inside dictionary'); error('End of file inside dictionary');
@ -99,38 +98,37 @@ var Parser = (function parserParser() {
this.shift(); this.shift();
return obj; return obj;
}, },
makeInlineImage: function parserMakeInlineImage(cipherTransform) { makeInlineImage: function Parser_makeInlineImage(cipherTransform) {
var lexer = this.lexer; var lexer = this.lexer;
var stream = lexer.stream; var stream = lexer.stream;
// parse dictionary // parse dictionary
var dict = new Dict(); var dict = new Dict();
while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) { while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
if (!isName(this.buf1)) { if (!isName(this.buf1))
error('Dictionary key must be a name object'); error('Dictionary key must be a name object');
} else {
var key = this.buf1.name; var key = this.buf1.name;
this.shift(); this.shift();
if (isEOF(this.buf1)) if (isEOF(this.buf1))
break; break;
dict.set(key, this.getObj(cipherTransform)); dict.set(key, this.getObj(cipherTransform));
}
} }
// parse image stream // parse image stream
var startPos = stream.pos; var startPos = stream.pos;
// searching for the /\sEI\s/ // searching for the /EI\s/
var state = 0, ch; var state = 0, ch;
while (state != 4 && (ch = stream.getByte()) != null) { while (state != 4 && (ch = stream.getByte()) != null) {
switch (ch) { switch (ch) {
case 0x20: case 0x20:
case 0x0D: case 0x0D:
case 0x0A: case 0x0A:
state = state === 3 ? 4 : 1; state = state === 3 ? 4 : 0;
break; break;
case 0x45: case 0x45:
state = state === 1 ? 2 : 0; state = 2;
break; break;
case 0x49: case 0x49:
state = state === 2 ? 3 : 0; state = state === 2 ? 3 : 0;
@ -157,12 +155,16 @@ var Parser = (function parserParser() {
imageStream = this.filter(imageStream, dict, length); imageStream = this.filter(imageStream, dict, length);
imageStream.parameters = dict; imageStream.parameters = dict;
this.buf2 = new Cmd('EI'); this.buf2 = Cmd.get('EI');
this.shift(); this.shift();
return imageStream; return imageStream;
}, },
makeStream: function parserMakeStream(dict, cipherTransform) { fetchIfRef: function Parser_fetchIfRef(obj) {
// not relying on the xref.fetchIfRef -- xref might not be set
return isRef(obj) ? this.xref.fetch(obj) : obj;
},
makeStream: function Parser_makeStream(dict, cipherTransform) {
var lexer = this.lexer; var lexer = this.lexer;
var stream = lexer.stream; var stream = lexer.stream;
@ -171,14 +173,9 @@ var Parser = (function parserParser() {
var pos = stream.pos; var pos = stream.pos;
// get length // get length
var length = dict.get('Length'); var length = this.fetchIfRef(dict.get('Length'));
var xref = this.xref; if (!isInt(length))
if (xref)
length = xref.fetchIfRef(length);
if (!isInt(length)) {
error('Bad ' + length + ' attribute in stream'); error('Bad ' + length + ' attribute in stream');
length = 0;
}
// skip over the stream data // skip over the stream data
stream.pos = pos + length; stream.pos = pos + length;
@ -195,9 +192,9 @@ var Parser = (function parserParser() {
stream.parameters = dict; stream.parameters = dict;
return stream; return stream;
}, },
filter: function parserFilter(stream, dict, length) { filter: function Parser_filter(stream, dict, length) {
var filter = dict.get('Filter', 'F'); var filter = this.fetchIfRef(dict.get('Filter', 'F'));
var params = dict.get('DecodeParms', 'DP'); var params = this.fetchIfRef(dict.get('DecodeParms', 'DP'));
if (isName(filter)) if (isName(filter))
return this.makeFilter(stream, filter.name, length, params); return this.makeFilter(stream, filter.name, length, params);
if (isArray(filter)) { if (isArray(filter)) {
@ -207,25 +204,25 @@ var Parser = (function parserParser() {
filter = filterArray[i]; filter = filterArray[i];
if (!isName(filter)) if (!isName(filter))
error('Bad filter name: ' + filter); error('Bad filter name: ' + filter);
else {
params = null; params = null;
if (isArray(paramsArray) && (i in paramsArray)) if (isArray(paramsArray) && (i in paramsArray))
params = paramsArray[i]; params = paramsArray[i];
stream = this.makeFilter(stream, filter.name, length, params); stream = this.makeFilter(stream, filter.name, length, params);
// after the first stream the length variable is invalid // after the first stream the length variable is invalid
length = null; length = null;
}
} }
} }
return stream; return stream;
}, },
makeFilter: function parserMakeFilter(stream, name, length, params) { makeFilter: function Parser_makeFilter(stream, name, length, params) {
if (name == 'FlateDecode' || name == 'Fl') { if (name == 'FlateDecode' || name == 'Fl') {
if (params) { if (params) {
return new PredictorStream(new FlateStream(stream), params); return new PredictorStream(new FlateStream(stream), params);
} }
return new FlateStream(stream); return new FlateStream(stream);
} else if (name == 'LZWDecode' || name == 'LZW') { }
if (name == 'LZWDecode' || name == 'LZW') {
var earlyChange = 1; var earlyChange = 1;
if (params) { if (params) {
if (params.has('EarlyChange')) if (params.has('EarlyChange'))
@ -234,31 +231,41 @@ var Parser = (function parserParser() {
new LZWStream(stream, earlyChange), params); new LZWStream(stream, earlyChange), params);
} }
return new LZWStream(stream, earlyChange); return new LZWStream(stream, earlyChange);
} else if (name == 'DCTDecode' || name == 'DCT') { }
if (name == 'DCTDecode' || name == 'DCT') {
var bytes = stream.getBytes(length); var bytes = stream.getBytes(length);
return new JpegStream(bytes, stream.dict, this.xref); return new JpegStream(bytes, stream.dict, this.xref);
} else if (name == 'ASCII85Decode' || name == 'A85') {
return new Ascii85Stream(stream);
} else if (name == 'ASCIIHexDecode' || name == 'AHx') {
return new AsciiHexStream(stream);
} else if (name == 'CCITTFaxDecode' || name == 'CCF') {
return new CCITTFaxStream(stream, params);
} else {
TODO('filter "' + name + '" not supported yet');
} }
if (name == 'JPXDecode' || name == 'JPX') {
var bytes = stream.getBytes(length);
return new JpxStream(bytes, stream.dict);
}
if (name == 'ASCII85Decode' || name == 'A85') {
return new Ascii85Stream(stream);
}
if (name == 'ASCIIHexDecode' || name == 'AHx') {
return new AsciiHexStream(stream);
}
if (name == 'CCITTFaxDecode' || name == 'CCF') {
return new CCITTFaxStream(stream, params);
}
if (name == 'RunLengthDecode') {
return new RunLengthStream(stream);
}
warn('filter "' + name + '" not supported yet');
return stream; return stream;
} }
}; };
return constructor; return Parser;
})(); })();
var Lexer = (function lexer() { var Lexer = (function LexerClosure() {
function constructor(stream) { function Lexer(stream) {
this.stream = stream; this.stream = stream;
} }
constructor.isSpace = function lexerIsSpace(ch) { Lexer.isSpace = function Lexer_isSpace(ch) {
return ch == ' ' || ch == '\t' || ch == '\x0d' || ch == '\x0a'; return ch == ' ' || ch == '\t' || ch == '\x0d' || ch == '\x0a';
}; };
@ -292,8 +299,8 @@ var Lexer = (function lexer() {
return -1; return -1;
} }
constructor.prototype = { Lexer.prototype = {
getNumber: function lexerGetNumber(ch) { getNumber: function Lexer_getNumber(ch) {
var floating = false; var floating = false;
var str = ch; var str = ch;
var stream = this.stream; var stream = this.stream;
@ -321,7 +328,7 @@ var Lexer = (function lexer() {
error('Invalid floating point number: ' + value); error('Invalid floating point number: ' + value);
return value; return value;
}, },
getString: function lexerGetString() { getString: function Lexer_getString() {
var numParen = 1; var numParen = 1;
var done = false; var done = false;
var str = ''; var str = '';
@ -405,7 +412,7 @@ var Lexer = (function lexer() {
} while (!done); } while (!done);
return str; return str;
}, },
getName: function lexerGetName(ch) { getName: function Lexer_getName(ch) {
var str = ''; var str = '';
var stream = this.stream; var stream = this.stream;
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) { while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
@ -432,7 +439,7 @@ var Lexer = (function lexer() {
str.length); str.length);
return new Name(str); return new Name(str);
}, },
getHexString: function lexerGetHexString(ch) { getHexString: function Lexer_getHexString(ch) {
var str = ''; var str = '';
var stream = this.stream; var stream = this.stream;
for (;;) { for (;;) {
@ -461,7 +468,7 @@ var Lexer = (function lexer() {
} }
return str; return str;
}, },
getObj: function lexerGetObj() { getObj: function Lexer_getObj() {
// skip whitespace and comments // skip whitespace and comments
var comment = false; var comment = false;
var stream = this.stream; var stream = this.stream;
@ -492,14 +499,14 @@ var Lexer = (function lexer() {
// array punctuation // array punctuation
case '[': case '[':
case ']': case ']':
return new Cmd(ch); return Cmd.get(ch);
// hex string or dict punctuation // hex string or dict punctuation
case '<': case '<':
ch = stream.lookChar(); ch = stream.lookChar();
if (ch == '<') { if (ch == '<') {
// dict punctuation // dict punctuation
stream.skip(); stream.skip();
return new Cmd('<<'); return Cmd.get('<<');
} }
return this.getHexString(ch); return this.getHexString(ch);
// dict punctuation // dict punctuation
@ -507,25 +514,23 @@ var Lexer = (function lexer() {
ch = stream.lookChar(); ch = stream.lookChar();
if (ch == '>') { if (ch == '>') {
stream.skip(); stream.skip();
return new Cmd('>>'); return Cmd.get('>>');
} }
case '{': case '{':
case '}': case '}':
return new Cmd(ch); return Cmd.get(ch);
// fall through // fall through
case ')': case ')':
error('Illegal character: ' + ch); error('Illegal character: ' + ch);
return Error;
} }
// command // command
var str = ch; var str = ch;
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) { while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
stream.skip(); stream.skip();
if (str.length == 128) { if (str.length == 128)
error('Command token too long: ' + str.length); error('Command token too long: ' + str.length);
break;
}
str += ch; str += ch;
} }
if (str == 'true') if (str == 'true')
@ -534,9 +539,9 @@ var Lexer = (function lexer() {
return false; return false;
if (str == 'null') if (str == 'null')
return null; return null;
return new Cmd(str); return Cmd.get(str);
}, },
skipToNextLine: function lexerSkipToNextLine() { skipToNextLine: function Lexer_skipToNextLine() {
var stream = this.stream; var stream = this.stream;
while (true) { while (true) {
var ch = stream.getChar(); var ch = stream.getChar();
@ -549,17 +554,17 @@ var Lexer = (function lexer() {
} }
} }
}, },
skip: function lexerSkip() { skip: function Lexer_skip() {
this.stream.skip(); this.stream.skip();
} }
}; };
return constructor; return Lexer;
})(); })();
var Linearization = (function linearizationLinearization() { var Linearization = (function LinearizationClosure() {
function constructor(stream) { function Linearization(stream) {
this.parser = new Parser(new Lexer(stream), false); this.parser = new Parser(new Lexer(stream), false, null);
var obj1 = this.parser.getObj(); var obj1 = this.parser.getObj();
var obj2 = this.parser.getObj(); var obj2 = this.parser.getObj();
var obj3 = this.parser.getObj(); var obj3 = this.parser.getObj();
@ -572,8 +577,8 @@ var Linearization = (function linearizationLinearization() {
} }
} }
constructor.prototype = { Linearization.prototype = {
getInt: function linearizationGetInt(name) { getInt: function Linearization_getInt(name) {
var linDict = this.linDict; var linDict = this.linDict;
var obj; var obj;
if (isDict(linDict) && if (isDict(linDict) &&
@ -582,9 +587,8 @@ var Linearization = (function linearizationLinearization() {
return obj; return obj;
} }
error('"' + name + '" field in linearization table is invalid'); error('"' + name + '" field in linearization table is invalid');
return 0;
}, },
getHint: function linearizationGetHint(index) { getHint: function Linearization_getHint(index) {
var linDict = this.linDict; var linDict = this.linDict;
var obj1, obj2; var obj1, obj2;
if (isDict(linDict) && if (isDict(linDict) &&
@ -595,7 +599,6 @@ var Linearization = (function linearizationLinearization() {
return obj2; return obj2;
} }
error('Hints table in linearization table is invalid: ' + index); error('Hints table in linearization table is invalid: ' + index);
return 0;
}, },
get length() { get length() {
if (!isDict(this.linDict)) if (!isDict(this.linDict))
@ -631,6 +634,6 @@ var Linearization = (function linearizationLinearization() {
} }
}; };
return constructor; return Linearization;
})(); })();

148
apps/files_pdfviewer/js/pdfjs/src/pattern.js Executable file → Normal file
View File

@ -3,48 +3,53 @@
'use strict'; 'use strict';
var Pattern = (function patternPattern() { var PatternType = {
AXIAL: 2,
RADIAL: 3
};
var Pattern = (function PatternClosure() {
// Constructor should define this.getPattern // Constructor should define this.getPattern
function constructor() { function Pattern() {
error('should not call Pattern constructor'); error('should not call Pattern constructor');
} }
constructor.prototype = { Pattern.prototype = {
// Input: current Canvas context // Input: current Canvas context
// Output: the appropriate fillStyle or strokeStyle // Output: the appropriate fillStyle or strokeStyle
getPattern: function pattern_getStyle(ctx) { getPattern: function Pattern_getPattern(ctx) {
error('Should not call Pattern.getStyle: ' + ctx); error('Should not call Pattern.getStyle: ' + ctx);
} }
}; };
constructor.shadingFromIR = function pattern_shadingFromIR(ctx, raw) { Pattern.shadingFromIR = function Pattern_shadingFromIR(raw) {
return Shadings[raw[0]].fromIR(ctx, raw); return Shadings[raw[0]].fromIR(raw);
}; };
constructor.parseShading = function pattern_shading(shading, matrix, xref, Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
res, ctx) { res) {
var dict = isStream(shading) ? shading.dict : shading; var dict = isStream(shading) ? shading.dict : shading;
var type = dict.get('ShadingType'); var type = dict.get('ShadingType');
switch (type) { switch (type) {
case 2: case PatternType.AXIAL:
case 3: case PatternType.RADIAL:
// both radial and axial shadings are handled by RadialAxial shading // Both radial and axial shadings are handled by RadialAxial shading.
return new Shadings.RadialAxial(dict, matrix, xref, res, ctx); return new Shadings.RadialAxial(dict, matrix, xref, res);
default: default:
return new Shadings.Dummy(); return new Shadings.Dummy();
} }
}; };
return constructor; return Pattern;
})(); })();
var Shadings = {}; var Shadings = {};
// Radial and axial shading have very similar implementations // Radial and axial shading have very similar implementations
// If needed, the implementations can be broken into two classes // If needed, the implementations can be broken into two classes
Shadings.RadialAxial = (function radialAxialShading() { Shadings.RadialAxial = (function RadialAxialClosure() {
function constructor(dict, matrix, xref, res, ctx) { function RadialAxial(dict, matrix, xref, res, ctx) {
this.matrix = matrix; this.matrix = matrix;
this.coordsArr = dict.get('Coords'); this.coordsArr = dict.get('Coords');
this.shadingType = dict.get('ShadingType'); this.shadingType = dict.get('ShadingType');
@ -74,10 +79,9 @@ Shadings.RadialAxial = (function radialAxialShading() {
this.extendEnd = extendEnd; this.extendEnd = extendEnd;
var fnObj = dict.get('Function'); var fnObj = dict.get('Function');
fnObj = xref.fetchIfRef(fnObj);
if (isArray(fnObj)) if (isArray(fnObj))
error('No support for array of functions'); error('No support for array of functions');
else if (!isPDFFunction(fnObj)) if (!isPDFFunction(fnObj))
error('Invalid function'); error('Invalid function');
var fn = PDFFunction.parse(xref, fnObj); var fn = PDFFunction.parse(xref, fnObj);
@ -89,56 +93,60 @@ Shadings.RadialAxial = (function radialAxialShading() {
var colorStops = []; var colorStops = [];
for (var i = t0; i <= t1; i += step) { for (var i = t0; i <= t1; i += step) {
var color = fn([i]); var rgbColor = cs.getRgb(fn([i]));
var rgbColor = Util.makeCssRgb.apply(this, cs.getRgb(color)); var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
colorStops.push([(i - t0) / diff, rgbColor]); colorStops.push([(i - t0) / diff, cssColor]);
} }
this.colorStops = colorStops; this.colorStops = colorStops;
} }
constructor.fromIR = function radialAxialShadingGetIR(ctx, raw) { RadialAxial.fromIR = function RadialAxial_fromIR(raw) {
var type = raw[1]; var type = raw[1];
var colorStops = raw[2]; var colorStops = raw[2];
var p0 = raw[3]; var p0 = raw[3];
var p1 = raw[4]; var p1 = raw[4];
var r0 = raw[5]; var r0 = raw[5];
var r1 = raw[6]; var r1 = raw[6];
return {
type: 'Pattern',
getPattern: function(ctx) {
var curMatrix = ctx.mozCurrentTransform;
if (curMatrix) {
var userMatrix = ctx.mozCurrentTransformInverse;
var curMatrix = ctx.mozCurrentTransform; p0 = Util.applyTransform(p0, curMatrix);
if (curMatrix) { p0 = Util.applyTransform(p0, userMatrix);
var userMatrix = ctx.mozCurrentTransformInverse;
p0 = Util.applyTransform(p0, curMatrix); p1 = Util.applyTransform(p1, curMatrix);
p0 = Util.applyTransform(p0, userMatrix); p1 = Util.applyTransform(p1, userMatrix);
}
p1 = Util.applyTransform(p1, curMatrix); var grad;
p1 = Util.applyTransform(p1, userMatrix); if (type == PatternType.AXIAL)
} grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
else if (type == PatternType.RADIAL)
grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
var grad; for (var i = 0, ii = colorStops.length; i < ii; ++i) {
if (type == 2) var c = colorStops[i];
grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]); grad.addColorStop(c[0], c[1]);
else if (type == 3) }
grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1); return grad;
}
for (var i = 0, ii = colorStops.length; i < ii; ++i) { };
var c = colorStops[i];
grad.addColorStop(c[0], c[1]);
}
return grad;
}; };
constructor.prototype = { RadialAxial.prototype = {
getIR: function radialAxialShadingGetIR() { getIR: function RadialAxial_getIR() {
var coordsArr = this.coordsArr; var coordsArr = this.coordsArr;
var type = this.shadingType; var type = this.shadingType;
if (type == 2) { if (type == PatternType.AXIAL) {
var p0 = [coordsArr[0], coordsArr[1]]; var p0 = [coordsArr[0], coordsArr[1]];
var p1 = [coordsArr[2], coordsArr[3]]; var p1 = [coordsArr[2], coordsArr[3]];
var r0 = null; var r0 = null;
var r1 = null; var r1 = null;
} else if (type == 3) { } else if (type == PatternType.RADIAL) {
var p0 = [coordsArr[0], coordsArr[1]]; var p0 = [coordsArr[0], coordsArr[1]];
var p1 = [coordsArr[3], coordsArr[4]]; var p1 = [coordsArr[3], coordsArr[4]];
var r0 = coordsArr[2]; var r0 = coordsArr[2];
@ -157,31 +165,35 @@ Shadings.RadialAxial = (function radialAxialShading() {
} }
}; };
return constructor; return RadialAxial;
})(); })();
Shadings.Dummy = (function dummyShading() { Shadings.Dummy = (function DummyClosure() {
function constructor() { function Dummy() {
this.type = 'Pattern'; this.type = 'Pattern';
} }
constructor.fromIR = function dummyShadingFromIR() { Dummy.fromIR = function Dummy_fromIR() {
return 'hotpink'; return 'hotpink';
}; };
constructor.prototype = { Dummy.prototype = {
getIR: function dummyShadingGetIR() { getIR: function Dummy_getIR() {
return ['Dummy']; return ['Dummy'];
} }
}; };
return constructor; return Dummy;
})(); })();
var TilingPattern = (function tilingPattern() { var TilingPattern = (function TilingPatternClosure() {
var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; var PaintType = {
COLORED: 1,
UNCOLORED: 2
};
var MAX_PATTERN_SIZE = 512;
function TilingPattern(IR, color, ctx, objs) { function TilingPattern(IR, color, ctx, objs) {
var IRQueue = IR[2]; var operatorList = IR[2];
this.matrix = IR[3]; this.matrix = IR[3];
var bbox = IR[4]; var bbox = IR[4];
var xstep = IR[5]; var xstep = IR[5];
@ -204,30 +216,30 @@ var TilingPattern = (function tilingPattern() {
var width = botRight[0] - topLeft[0]; var width = botRight[0] - topLeft[0];
var height = botRight[1] - topLeft[1]; var height = botRight[1] - topLeft[1];
// TODO: hack to avoid OOM, we would idealy compute the tiling // TODO: hack to avoid OOM, we would ideally compute the tiling
// pattern to be only as large as the acual size in device space // pattern to be only as large as the acual size in device space
// This could be computed with .mozCurrentTransform, but still // This could be computed with .mozCurrentTransform, but still
// needs to be implemented // needs to be implemented
while (Math.abs(width) > 512 || Math.abs(height) > 512) { while (Math.abs(width) > MAX_PATTERN_SIZE ||
width = 512; Math.abs(height) > MAX_PATTERN_SIZE) {
height = 512; width = height = MAX_PATTERN_SIZE;
} }
var tmpCanvas = new ScratchCanvas(width, height); var tmpCanvas = createScratchCanvas(width, height);
// set the new canvas element context as the graphics context // set the new canvas element context as the graphics context
var tmpCtx = tmpCanvas.getContext('2d'); var tmpCtx = tmpCanvas.getContext('2d');
var graphics = new CanvasGraphics(tmpCtx, objs); var graphics = new CanvasGraphics(tmpCtx, objs);
switch (paintType) { switch (paintType) {
case PAINT_TYPE_COLORED: case PaintType.COLORED:
tmpCtx.fillStyle = ctx.fillStyle; tmpCtx.fillStyle = ctx.fillStyle;
tmpCtx.strokeStyle = ctx.strokeStyle; tmpCtx.strokeStyle = ctx.strokeStyle;
break; break;
case PAINT_TYPE_UNCOLORED: case PaintType.UNCOLORED:
color = Util.makeCssRgb.apply(this, color); var cssColor = Util.makeCssRgb(this, color[0], color[1], color[2]);
tmpCtx.fillStyle = color; tmpCtx.fillStyle = cssColor;
tmpCtx.strokeStyle = color; tmpCtx.strokeStyle = cssColor;
break; break;
default: default:
error('Unsupported paint type: ' + paintType); error('Unsupported paint type: ' + paintType);
@ -250,12 +262,12 @@ var TilingPattern = (function tilingPattern() {
graphics.endPath(); graphics.endPath();
} }
graphics.executeIRQueue(IRQueue); graphics.executeOperatorList(operatorList);
this.canvas = tmpCanvas; this.canvas = tmpCanvas;
} }
TilingPattern.getIR = function tiling_getIR(codeIR, dict, args) { TilingPattern.getIR = function TilingPattern_getIR(operatorList, dict, args) {
var matrix = dict.get('Matrix'); var matrix = dict.get('Matrix');
var bbox = dict.get('BBox'); var bbox = dict.get('BBox');
var xstep = dict.get('XStep'); var xstep = dict.get('XStep');
@ -263,12 +275,12 @@ var TilingPattern = (function tilingPattern() {
var paintType = dict.get('PaintType'); var paintType = dict.get('PaintType');
return [ return [
'TilingPattern', args, codeIR, matrix, bbox, xstep, ystep, paintType 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, paintType
]; ];
}; };
TilingPattern.prototype = { TilingPattern.prototype = {
getPattern: function tiling_getPattern() { getPattern: function TilingPattern_getPattern() {
var matrix = this.matrix; var matrix = this.matrix;
var curMatrix = this.curMatrix; var curMatrix = this.curMatrix;
var ctx = this.ctx; var ctx = this.ctx;

0
apps/files_pdfviewer/js/pdfjs/src/pdf.js Executable file → Normal file
View File

487
apps/files_pdfviewer/js/pdfjs/src/stream.js Executable file → Normal file
View File

@ -3,8 +3,8 @@
'use strict'; 'use strict';
var Stream = (function streamStream() { var Stream = (function StreamClosure() {
function constructor(arrayBuffer, start, length, dict) { function Stream(arrayBuffer, start, length, dict) {
this.bytes = new Uint8Array(arrayBuffer); this.bytes = new Uint8Array(arrayBuffer);
this.start = start || 0; this.start = start || 0;
this.pos = this.start; this.pos = this.start;
@ -14,18 +14,18 @@ var Stream = (function streamStream() {
// required methods for a stream. if a particular stream does not // required methods for a stream. if a particular stream does not
// implement these, an error should be thrown // implement these, an error should be thrown
constructor.prototype = { Stream.prototype = {
get length() { get length() {
return this.end - this.start; return this.end - this.start;
}, },
getByte: function stream_getByte() { getByte: function Stream_getByte() {
if (this.pos >= this.end) if (this.pos >= this.end)
return null; return null;
return this.bytes[this.pos++]; return this.bytes[this.pos++];
}, },
// returns subarray of original buffer // returns subarray of original buffer
// should only be read // should only be read
getBytes: function stream_getBytes(length) { getBytes: function Stream_getBytes(length) {
var bytes = this.bytes; var bytes = this.bytes;
var pos = this.pos; var pos = this.pos;
var strEnd = this.end; var strEnd = this.end;
@ -40,38 +40,38 @@ var Stream = (function streamStream() {
this.pos = end; this.pos = end;
return bytes.subarray(pos, end); return bytes.subarray(pos, end);
}, },
lookChar: function stream_lookChar() { lookChar: function Stream_lookChar() {
if (this.pos >= this.end) if (this.pos >= this.end)
return null; return null;
return String.fromCharCode(this.bytes[this.pos]); return String.fromCharCode(this.bytes[this.pos]);
}, },
getChar: function stream_getChar() { getChar: function Stream_getChar() {
if (this.pos >= this.end) if (this.pos >= this.end)
return null; return null;
return String.fromCharCode(this.bytes[this.pos++]); return String.fromCharCode(this.bytes[this.pos++]);
}, },
skip: function stream_skip(n) { skip: function Stream_skip(n) {
if (!n) if (!n)
n = 1; n = 1;
this.pos += n; this.pos += n;
}, },
reset: function stream_reset() { reset: function Stream_reset() {
this.pos = this.start; this.pos = this.start;
}, },
moveStart: function stream_moveStart() { moveStart: function Stream_moveStart() {
this.start = this.pos; this.start = this.pos;
}, },
makeSubStream: function stream_makeSubstream(start, length, dict) { makeSubStream: function Stream_makeSubStream(start, length, dict) {
return new Stream(this.bytes.buffer, start, length, dict); return new Stream(this.bytes.buffer, start, length, dict);
}, },
isStream: true isStream: true
}; };
return constructor; return Stream;
})(); })();
var StringStream = (function stringStream() { var StringStream = (function StringStreamClosure() {
function constructor(str) { function StringStream(str) {
var length = str.length; var length = str.length;
var bytes = new Uint8Array(length); var bytes = new Uint8Array(length);
for (var n = 0; n < length; ++n) for (var n = 0; n < length; ++n)
@ -79,22 +79,22 @@ var StringStream = (function stringStream() {
Stream.call(this, bytes); Stream.call(this, bytes);
} }
constructor.prototype = Stream.prototype; StringStream.prototype = Stream.prototype;
return constructor; return StringStream;
})(); })();
// super class for the decoding streams // super class for the decoding streams
var DecodeStream = (function decodeStream() { var DecodeStream = (function DecodeStreamClosure() {
function constructor() { function DecodeStream() {
this.pos = 0; this.pos = 0;
this.bufferLength = 0; this.bufferLength = 0;
this.eof = false; this.eof = false;
this.buffer = null; this.buffer = null;
} }
constructor.prototype = { DecodeStream.prototype = {
ensureBuffer: function decodestream_ensureBuffer(requested) { ensureBuffer: function DecodeStream_ensureBuffer(requested) {
var buffer = this.buffer; var buffer = this.buffer;
var current = buffer ? buffer.byteLength : 0; var current = buffer ? buffer.byteLength : 0;
if (requested < current) if (requested < current)
@ -107,7 +107,7 @@ var DecodeStream = (function decodeStream() {
buffer2[i] = buffer[i]; buffer2[i] = buffer[i];
return (this.buffer = buffer2); return (this.buffer = buffer2);
}, },
getByte: function decodestream_getByte() { getByte: function DecodeStream_getByte() {
var pos = this.pos; var pos = this.pos;
while (this.bufferLength <= pos) { while (this.bufferLength <= pos) {
if (this.eof) if (this.eof)
@ -116,7 +116,7 @@ var DecodeStream = (function decodeStream() {
} }
return this.buffer[this.pos++]; return this.buffer[this.pos++];
}, },
getBytes: function decodestream_getBytes(length) { getBytes: function DecodeStream_getBytes(length) {
var end, pos = this.pos; var end, pos = this.pos;
if (length) { if (length) {
@ -144,7 +144,7 @@ var DecodeStream = (function decodeStream() {
this.pos = end; this.pos = end;
return this.buffer.subarray(pos, end); return this.buffer.subarray(pos, end);
}, },
lookChar: function decodestream_lookChar() { lookChar: function DecodeStream_lookChar() {
var pos = this.pos; var pos = this.pos;
while (this.bufferLength <= pos) { while (this.bufferLength <= pos) {
if (this.eof) if (this.eof)
@ -153,7 +153,7 @@ var DecodeStream = (function decodeStream() {
} }
return String.fromCharCode(this.buffer[this.pos]); return String.fromCharCode(this.buffer[this.pos]);
}, },
getChar: function decodestream_getChar() { getChar: function DecodeStream_getChar() {
var pos = this.pos; var pos = this.pos;
while (this.bufferLength <= pos) { while (this.bufferLength <= pos) {
if (this.eof) if (this.eof)
@ -162,40 +162,40 @@ var DecodeStream = (function decodeStream() {
} }
return String.fromCharCode(this.buffer[this.pos++]); return String.fromCharCode(this.buffer[this.pos++]);
}, },
makeSubStream: function decodestream_makeSubstream(start, length, dict) { makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
var end = start + length; var end = start + length;
while (this.bufferLength <= end && !this.eof) while (this.bufferLength <= end && !this.eof)
this.readBlock(); this.readBlock();
return new Stream(this.buffer, start, length, dict); return new Stream(this.buffer, start, length, dict);
}, },
skip: function decodestream_skip(n) { skip: function DecodeStream_skip(n) {
if (!n) if (!n)
n = 1; n = 1;
this.pos += n; this.pos += n;
}, },
reset: function decodestream_reset() { reset: function DecodeStream_reset() {
this.pos = 0; this.pos = 0;
} }
}; };
return constructor; return DecodeStream;
})(); })();
var FakeStream = (function fakeStream() { var FakeStream = (function FakeStreamClosure() {
function constructor(stream) { function FakeStream(stream) {
this.dict = stream.dict; this.dict = stream.dict;
DecodeStream.call(this); DecodeStream.call(this);
} }
constructor.prototype = Object.create(DecodeStream.prototype); FakeStream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlock = function fakeStreamReadBlock() { FakeStream.prototype.readBlock = function FakeStream_readBlock() {
var bufferLength = this.bufferLength; var bufferLength = this.bufferLength;
bufferLength += 1024; bufferLength += 1024;
var buffer = this.ensureBuffer(bufferLength); var buffer = this.ensureBuffer(bufferLength);
this.bufferLength = bufferLength; this.bufferLength = bufferLength;
}; };
constructor.prototype.getBytes = function fakeStreamGetBytes(length) { FakeStream.prototype.getBytes = function FakeStream_getBytes(length) {
var end, pos = this.pos; var end, pos = this.pos;
if (length) { if (length) {
@ -217,18 +217,20 @@ var FakeStream = (function fakeStream() {
return this.buffer.subarray(pos, end); return this.buffer.subarray(pos, end);
}; };
return constructor; return FakeStream;
})(); })();
var StreamsSequenceStream = (function streamSequenceStream() { var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
function constructor(streams) { function StreamsSequenceStream(streams) {
this.streams = streams; this.streams = streams;
DecodeStream.call(this); DecodeStream.call(this);
} }
constructor.prototype = Object.create(DecodeStream.prototype); StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
StreamsSequenceStream.prototype.readBlock =
function streamSequenceStreamReadBlock() {
constructor.prototype.readBlock = function streamSequenceStreamReadBlock() {
var streams = this.streams; var streams = this.streams;
if (streams.length == 0) { if (streams.length == 0) {
this.eof = true; this.eof = true;
@ -243,10 +245,10 @@ var StreamsSequenceStream = (function streamSequenceStream() {
this.bufferLength = newLength; this.bufferLength = newLength;
}; };
return constructor; return StreamsSequenceStream;
})(); })();
var FlateStream = (function flateStream() { var FlateStream = (function FlateStreamClosure() {
var codeLenCodeMap = new Uint32Array([ var codeLenCodeMap = new Uint32Array([
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
]); ]);
@ -339,7 +341,7 @@ var FlateStream = (function flateStream() {
0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
]), 5]; ]), 5];
function constructor(stream) { function FlateStream(stream) {
var bytes = stream.getBytes(); var bytes = stream.getBytes();
var bytesPos = 0; var bytesPos = 0;
@ -364,9 +366,9 @@ var FlateStream = (function flateStream() {
DecodeStream.call(this); DecodeStream.call(this);
} }
constructor.prototype = Object.create(DecodeStream.prototype); FlateStream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.getBits = function flateStreamGetBits(bits) { FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
var codeSize = this.codeSize; var codeSize = this.codeSize;
var codeBuf = this.codeBuf; var codeBuf = this.codeBuf;
var bytes = this.bytes; var bytes = this.bytes;
@ -386,7 +388,7 @@ var FlateStream = (function flateStream() {
return b; return b;
}; };
constructor.prototype.getCode = function flateStreamGetCode(table) { FlateStream.prototype.getCode = function FlateStream_getCode(table) {
var codes = table[0]; var codes = table[0];
var maxLen = table[1]; var maxLen = table[1];
var codeSize = this.codeSize; var codeSize = this.codeSize;
@ -412,7 +414,7 @@ var FlateStream = (function flateStream() {
return codeVal; return codeVal;
}; };
constructor.prototype.generateHuffmanTable = FlateStream.prototype.generateHuffmanTable =
function flateStreamGenerateHuffmanTable(lengths) { function flateStreamGenerateHuffmanTable(lengths) {
var n = lengths.length; var n = lengths.length;
@ -451,7 +453,7 @@ var FlateStream = (function flateStream() {
return [codes, maxLen]; return [codes, maxLen];
}; };
constructor.prototype.readBlock = function flateStreamReadBlock() { FlateStream.prototype.readBlock = function FlateStream_readBlock() {
// read block header // read block header
var hdr = this.getBits(3); var hdr = this.getBits(3);
if (hdr & 1) if (hdr & 1)
@ -582,11 +584,11 @@ var FlateStream = (function flateStream() {
} }
}; };
return constructor; return FlateStream;
})(); })();
var PredictorStream = (function predictorStream() { var PredictorStream = (function PredictorStreamClosure() {
function constructor(stream, params) { function PredictorStream(stream, params) {
var predictor = this.predictor = params.get('Predictor') || 1; var predictor = this.predictor = params.get('Predictor') || 1;
if (predictor <= 1) if (predictor <= 1)
@ -613,15 +615,14 @@ var PredictorStream = (function predictorStream() {
return this; return this;
} }
constructor.prototype = Object.create(DecodeStream.prototype); PredictorStream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlockTiff = PredictorStream.prototype.readBlockTiff =
function predictorStreamReadBlockTiff() { function predictorStreamReadBlockTiff() {
var rowBytes = this.rowBytes; var rowBytes = this.rowBytes;
var bufferLength = this.bufferLength; var bufferLength = this.bufferLength;
var buffer = this.ensureBuffer(bufferLength + rowBytes); var buffer = this.ensureBuffer(bufferLength + rowBytes);
var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
var bits = this.bits; var bits = this.bits;
var colors = this.colors; var colors = this.colors;
@ -630,6 +631,7 @@ var PredictorStream = (function predictorStream() {
var inbuf = 0, outbuf = 0; var inbuf = 0, outbuf = 0;
var inbits = 0, outbits = 0; var inbits = 0, outbits = 0;
var pos = bufferLength;
if (bits === 1) { if (bits === 1) {
for (var i = 0; i < rowBytes; ++i) { for (var i = 0; i < rowBytes; ++i) {
@ -637,19 +639,21 @@ var PredictorStream = (function predictorStream() {
inbuf = (inbuf << 8) | c; inbuf = (inbuf << 8) | c;
// bitwise addition is exclusive or // bitwise addition is exclusive or
// first shift inbuf and then add // first shift inbuf and then add
currentRow[i] = (c ^ (inbuf >> colors)) & 0xFF; buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF;
// truncate inbuf (assumes colors < 16) // truncate inbuf (assumes colors < 16)
inbuf &= 0xFFFF; inbuf &= 0xFFFF;
} }
} else if (bits === 8) { } else if (bits === 8) {
for (var i = 0; i < colors; ++i) for (var i = 0; i < colors; ++i)
currentRow[i] = rawBytes[i]; buffer[pos++] = rawBytes[i];
for (; i < rowBytes; ++i) for (; i < rowBytes; ++i) {
currentRow[i] = currentRow[i - colors] + rawBytes[i]; buffer[pos] = buffer[pos - colors] + rawBytes[i];
pos++;
}
} else { } else {
var compArray = new Uint8Array(colors + 1); var compArray = new Uint8Array(colors + 1);
var bitMask = (1 << bits) - 1; var bitMask = (1 << bits) - 1;
var j = 0, k = 0; var j = 0, k = bufferLength;
var columns = this.columns; var columns = this.columns;
for (var i = 0; i < columns; ++i) { for (var i = 0; i < columns; ++i) {
for (var kk = 0; kk < colors; ++kk) { for (var kk = 0; kk < colors; ++kk) {
@ -663,20 +667,22 @@ var PredictorStream = (function predictorStream() {
outbuf = (outbuf << bits) | compArray[kk]; outbuf = (outbuf << bits) | compArray[kk];
outbits += bits; outbits += bits;
if (outbits >= 8) { if (outbits >= 8) {
currentRow[k++] = (outbuf >> (outbits - 8)) & 0xFF; buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF;
outbits -= 8; outbits -= 8;
} }
} }
} }
if (outbits > 0) { if (outbits > 0) {
currentRow[k++] = (outbuf << (8 - outbits)) + buffer[k++] = (outbuf << (8 - outbits)) +
(inbuf & ((1 << (8 - outbits)) - 1)); (inbuf & ((1 << (8 - outbits)) - 1));
} }
} }
this.bufferLength += rowBytes; this.bufferLength += rowBytes;
}; };
constructor.prototype.readBlockPng = function predictorStreamReadBlockPng() { PredictorStream.prototype.readBlockPng =
function predictorStreamReadBlockPng() {
var rowBytes = this.rowBytes; var rowBytes = this.rowBytes;
var pixBytes = this.pixBytes; var pixBytes = this.pixBytes;
@ -686,32 +692,35 @@ var PredictorStream = (function predictorStream() {
var bufferLength = this.bufferLength; var bufferLength = this.bufferLength;
var buffer = this.ensureBuffer(bufferLength + rowBytes); var buffer = this.ensureBuffer(bufferLength + rowBytes);
var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
if (prevRow.length == 0) if (prevRow.length == 0)
prevRow = new Uint8Array(rowBytes); prevRow = new Uint8Array(rowBytes);
var j = bufferLength;
switch (predictor) { switch (predictor) {
case 0: case 0:
for (var i = 0; i < rowBytes; ++i) for (var i = 0; i < rowBytes; ++i)
currentRow[i] = rawBytes[i]; buffer[j++] = rawBytes[i];
break; break;
case 1: case 1:
for (var i = 0; i < pixBytes; ++i) for (var i = 0; i < pixBytes; ++i)
currentRow[i] = rawBytes[i]; buffer[j++] = rawBytes[i];
for (; i < rowBytes; ++i) for (; i < rowBytes; ++i) {
currentRow[i] = (currentRow[i - pixBytes] + rawBytes[i]) & 0xFF; buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF;
j++;
}
break; break;
case 2: case 2:
for (var i = 0; i < rowBytes; ++i) for (var i = 0; i < rowBytes; ++i)
currentRow[i] = (prevRow[i] + rawBytes[i]) & 0xFF; buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
break; break;
case 3: case 3:
for (var i = 0; i < pixBytes; ++i) for (var i = 0; i < pixBytes; ++i)
currentRow[i] = (prevRow[i] >> 1) + rawBytes[i]; buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
for (; i < rowBytes; ++i) { for (; i < rowBytes; ++i) {
currentRow[i] = (((prevRow[i] + currentRow[i - pixBytes]) >> 1) + buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) +
rawBytes[i]) & 0xFF; rawBytes[i]) & 0xFF;
j++;
} }
break; break;
case 4: case 4:
@ -720,12 +729,12 @@ var PredictorStream = (function predictorStream() {
for (var i = 0; i < pixBytes; ++i) { for (var i = 0; i < pixBytes; ++i) {
var up = prevRow[i]; var up = prevRow[i];
var c = rawBytes[i]; var c = rawBytes[i];
currentRow[i] = up + c; buffer[j++] = up + c;
} }
for (; i < rowBytes; ++i) { for (; i < rowBytes; ++i) {
var up = prevRow[i]; var up = prevRow[i];
var upLeft = prevRow[i - pixBytes]; var upLeft = prevRow[i - pixBytes];
var left = currentRow[i - pixBytes]; var left = buffer[j - pixBytes];
var p = left + up - upLeft; var p = left + up - upLeft;
var pa = p - left; var pa = p - left;
@ -740,11 +749,11 @@ var PredictorStream = (function predictorStream() {
var c = rawBytes[i]; var c = rawBytes[i];
if (pa <= pb && pa <= pc) if (pa <= pb && pa <= pc)
currentRow[i] = left + c; buffer[j++] = left + c;
else if (pb <= pc) else if (pb <= pc)
currentRow[i] = up + c; buffer[j++] = up + c;
else else
currentRow[i] = upLeft + c; buffer[j++] = upLeft + c;
} }
break; break;
default: default:
@ -753,7 +762,7 @@ var PredictorStream = (function predictorStream() {
this.bufferLength += rowBytes; this.bufferLength += rowBytes;
}; };
return constructor; return PredictorStream;
})(); })();
/** /**
@ -763,7 +772,7 @@ var PredictorStream = (function predictorStream() {
* a library to decode these images and the stream behaves like all the other * a library to decode these images and the stream behaves like all the other
* DecodeStreams. * DecodeStreams.
*/ */
var JpegStream = (function jpegStream() { var JpegStream = (function JpegStreamClosure() {
function isAdobeImage(bytes) { function isAdobeImage(bytes) {
var maxBytesScanned = Math.max(bytes.length - 16, 1024); var maxBytesScanned = Math.max(bytes.length - 16, 1024);
// Looking for APP14, 'Adobe' // Looking for APP14, 'Adobe'
@ -794,63 +803,184 @@ var JpegStream = (function jpegStream() {
return newBytes; return newBytes;
} }
function constructor(bytes, dict, xref) { function JpegStream(bytes, dict, xref) {
// TODO: per poppler, some images may have 'junk' before that // TODO: per poppler, some images may have 'junk' before that
// need to be removed // need to be removed
this.dict = dict; this.dict = dict;
// Flag indicating wether the image can be natively loaded. this.isAdobeImage = false;
this.isNative = true; this.colorTransform = dict.get('ColorTransform') || -1;
this.colorTransform = -1;
if (isAdobeImage(bytes)) { if (isAdobeImage(bytes)) {
// when bug 674619 land, let's check if browser can do this.isAdobeImage = true;
// normal cmyk and then we won't have to the following bytes = fixAdobeImage(bytes);
var cs = xref.fetchIfRef(dict.get('ColorSpace'));
// DeviceRGB and DeviceGray are the only Adobe images that work natively
if (isName(cs) && (cs.name === 'DeviceRGB' || cs.name === 'DeviceGray')) {
bytes = fixAdobeImage(bytes);
this.src = bytesToString(bytes);
} else {
this.colorTransform = dict.get('ColorTransform');
this.isNative = false;
this.bytes = bytes;
}
} else {
this.src = bytesToString(bytes);
} }
this.bytes = bytes;
DecodeStream.call(this); DecodeStream.call(this);
} }
constructor.prototype = Object.create(DecodeStream.prototype); JpegStream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) { JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) {
if (this.bufferLength) if (this.bufferLength)
return; return;
var jpegImage = new JpegImage(); try {
jpegImage.colorTransform = this.colorTransform; var jpegImage = new JpegImage();
jpegImage.parse(this.bytes); if (this.colorTransform != -1)
var width = jpegImage.width; jpegImage.colorTransform = this.colorTransform;
var height = jpegImage.height; jpegImage.parse(this.bytes);
var data = jpegImage.getData(width, height); var width = jpegImage.width;
var height = jpegImage.height;
var data = jpegImage.getData(width, height);
this.buffer = data;
this.bufferLength = data.length;
} catch (e) {
error('JPEG error: ' + e);
}
};
JpegStream.prototype.getIR = function JpegStream_getIR() {
return bytesToString(this.bytes);
};
JpegStream.prototype.getChar = function JpegStream_getChar() {
error('internal error: getChar is not valid on JpegStream');
};
/**
* Checks if the image can be decoded and displayed by the browser without any
* further processing such as color space conversions.
*/
JpegStream.prototype.isNativelySupported =
function JpegStream_isNativelySupported(xref, res) {
var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
// when bug 674619 lands, let's check if browser can do
// normal cmyk and then we won't need to decode in JS
if (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB')
return true;
if (cs.name === 'DeviceCMYK' && !this.isAdobeImage &&
this.colorTransform < 1)
return true;
return false;
};
/**
* Checks if the image can be decoded by the browser.
*/
JpegStream.prototype.isNativelyDecodable =
function JpegStream_isNativelyDecodable(xref, res) {
var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
var numComps = cs.numComps;
if (numComps == 1 || numComps == 3)
return true;
return false;
};
return JpegStream;
})();
/**
* For JPEG 2000's we use a library to decode these images and
* the stream behaves like all the other DecodeStreams.
*/
var JpxStream = (function JpxStreamClosure() {
function JpxStream(bytes, dict) {
this.dict = dict;
this.bytes = bytes;
DecodeStream.call(this);
}
JpxStream.prototype = Object.create(DecodeStream.prototype);
JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) {
if (this.bufferLength)
return;
var jpxImage = new JpxImage();
jpxImage.parse(this.bytes);
var width = jpxImage.width;
var height = jpxImage.height;
var componentsCount = jpxImage.componentsCount;
if (componentsCount != 1 && componentsCount != 3 && componentsCount != 4)
error('JPX with ' + componentsCount + ' components is not supported');
var data = new Uint8Array(width * height * componentsCount);
for (var k = 0, kk = jpxImage.tiles.length; k < kk; k++) {
var tileCompoments = jpxImage.tiles[k];
var tileWidth = tileCompoments[0].width;
var tileHeight = tileCompoments[0].height;
var tileLeft = tileCompoments[0].left;
var tileTop = tileCompoments[0].top;
var dataPosition, sourcePosition, data0, data1, data2, data3, rowFeed;
switch (componentsCount) {
case 1:
data0 = tileCompoments[0].items;
dataPosition = width * tileTop + tileLeft;
rowFeed = width - tileWidth;
sourcePosition = 0;
for (var j = 0; j < tileHeight; j++) {
for (var i = 0; i < tileWidth; i++)
data[dataPosition++] = data0[sourcePosition++];
dataPosition += rowFeed;
}
break;
case 3:
data0 = tileCompoments[0].items;
data1 = tileCompoments[1].items;
data2 = tileCompoments[2].items;
dataPosition = (width * tileTop + tileLeft) * 3;
rowFeed = (width - tileWidth) * 3;
sourcePosition = 0;
for (var j = 0; j < tileHeight; j++) {
for (var i = 0; i < tileWidth; i++) {
data[dataPosition++] = data0[sourcePosition];
data[dataPosition++] = data1[sourcePosition];
data[dataPosition++] = data2[sourcePosition];
sourcePosition++;
}
dataPosition += rowFeed;
}
break;
case 4:
data0 = tileCompoments[0].items;
data1 = tileCompoments[1].items;
data2 = tileCompoments[2].items;
data3 = tileCompoments[3].items;
dataPosition = (width * tileTop + tileLeft) * 4;
rowFeed = (width - tileWidth) * 4;
sourcePosition = 0;
for (var j = 0; j < tileHeight; j++) {
for (var i = 0; i < tileWidth; i++) {
data[dataPosition++] = data0[sourcePosition];
data[dataPosition++] = data1[sourcePosition];
data[dataPosition++] = data2[sourcePosition];
data[dataPosition++] = data3[sourcePosition];
sourcePosition++;
}
dataPosition += rowFeed;
}
break;
}
}
this.buffer = data; this.buffer = data;
this.bufferLength = data.length; this.bufferLength = data.length;
}; };
constructor.prototype.getIR = function jpegStreamGetIR() { JpxStream.prototype.getChar = function JpxStream_getChar() {
return this.src; error('internal error: getChar is not valid on JpxStream');
};
constructor.prototype.getChar = function jpegStreamGetChar() {
error('internal error: getChar is not valid on JpegStream');
}; };
return constructor; return JpxStream;
})(); })();
var DecryptStream = (function decryptStream() { var DecryptStream = (function DecryptStreamClosure() {
function constructor(str, decrypt) { function DecryptStream(str, decrypt) {
this.str = str; this.str = str;
this.dict = str.dict; this.dict = str.dict;
this.decrypt = decrypt; this.decrypt = decrypt;
@ -860,9 +990,9 @@ var DecryptStream = (function decryptStream() {
var chunkSize = 512; var chunkSize = 512;
constructor.prototype = Object.create(DecodeStream.prototype); DecryptStream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlock = function decryptStreamReadBlock() { DecryptStream.prototype.readBlock = function DecryptStream_readBlock() {
var chunk = this.str.getBytes(chunkSize); var chunk = this.str.getBytes(chunkSize);
if (!chunk || chunk.length == 0) { if (!chunk || chunk.length == 0) {
this.eof = true; this.eof = true;
@ -879,11 +1009,11 @@ var DecryptStream = (function decryptStream() {
this.bufferLength = bufferLength; this.bufferLength = bufferLength;
}; };
return constructor; return DecryptStream;
})(); })();
var Ascii85Stream = (function ascii85Stream() { var Ascii85Stream = (function Ascii85StreamClosure() {
function constructor(str) { function Ascii85Stream(str) {
this.str = str; this.str = str;
this.dict = str.dict; this.dict = str.dict;
this.input = new Uint8Array(5); this.input = new Uint8Array(5);
@ -891,9 +1021,9 @@ var Ascii85Stream = (function ascii85Stream() {
DecodeStream.call(this); DecodeStream.call(this);
} }
constructor.prototype = Object.create(DecodeStream.prototype); Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlock = function ascii85StreamReadBlock() { Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
var tildaCode = '~'.charCodeAt(0); var tildaCode = '~'.charCodeAt(0);
var zCode = 'z'.charCodeAt(0); var zCode = 'z'.charCodeAt(0);
var str = this.str; var str = this.str;
@ -948,11 +1078,11 @@ var Ascii85Stream = (function ascii85Stream() {
} }
}; };
return constructor; return Ascii85Stream;
})(); })();
var AsciiHexStream = (function asciiHexStream() { var AsciiHexStream = (function AsciiHexStreamClosure() {
function constructor(str) { function AsciiHexStream(str) {
this.str = str; this.str = str;
this.dict = str.dict; this.dict = str.dict;
@ -986,9 +1116,9 @@ var AsciiHexStream = (function asciiHexStream() {
102: 15 102: 15
}; };
constructor.prototype = Object.create(DecodeStream.prototype); AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlock = function asciiHexStreamReadBlock() { AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() {
var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n,
decodeLength, buffer, bufferLength, i, length; decodeLength, buffer, bufferLength, i, length;
@ -1018,10 +1148,55 @@ var AsciiHexStream = (function asciiHexStream() {
this.eof = true; this.eof = true;
}; };
return constructor; return AsciiHexStream;
})(); })();
var CCITTFaxStream = (function ccittFaxStream() { var RunLengthStream = (function RunLengthStreamClosure() {
function RunLengthStream(str) {
this.str = str;
this.dict = str.dict;
DecodeStream.call(this);
}
RunLengthStream.prototype = Object.create(DecodeStream.prototype);
RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() {
// The repeatHeader has following format. The first byte defines type of run
// and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes
// (in addition to the second byte from the header), n = 129 through 255 -
// duplicate the second byte from the header (257 - n) times, n = 128 - end.
var repeatHeader = this.str.getBytes(2);
if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] == 128) {
this.eof = true;
return;
}
var bufferLength = this.bufferLength;
var n = repeatHeader[0];
if (n < 128) {
// copy n bytes
var buffer = this.ensureBuffer(bufferLength + n + 1);
buffer[bufferLength++] = repeatHeader[1];
if (n > 0) {
var source = this.str.getBytes(n);
buffer.set(source, bufferLength);
bufferLength += n;
}
} else {
n = 257 - n;
var b = repeatHeader[1];
var buffer = this.ensureBuffer(bufferLength + n + 1);
for (var i = 0; i < n; i++)
buffer[bufferLength++] = b;
}
this.bufferLength = bufferLength;
};
return RunLengthStream;
})();
var CCITTFaxStream = (function CCITTFaxStreamClosure() {
var ccittEOL = -2; var ccittEOL = -2;
var twoDimPass = 0; var twoDimPass = 0;
@ -1449,7 +1624,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
[2, 2], [2, 2], [2, 2], [2, 2] [2, 2], [2, 2], [2, 2], [2, 2]
]; ];
function constructor(str, params) { function CCITTFaxStream(str, params) {
this.str = str; this.str = str;
this.dict = str.dict; this.dict = str.dict;
@ -1494,9 +1669,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
DecodeStream.call(this); DecodeStream.call(this);
} }
constructor.prototype = Object.create(DecodeStream.prototype); CCITTFaxStream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlock = function ccittFaxStreamReadBlock() { CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() {
while (!this.eof) { while (!this.eof) {
var c = this.lookChar(); var c = this.lookChar();
this.buf = EOF; this.buf = EOF;
@ -1505,7 +1680,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
} }
}; };
constructor.prototype.addPixels = CCITTFaxStream.prototype.addPixels =
function ccittFaxStreamAddPixels(a1, blackPixels) { function ccittFaxStreamAddPixels(a1, blackPixels) {
var codingLine = this.codingLine; var codingLine = this.codingLine;
var codingPos = this.codingPos; var codingPos = this.codingPos;
@ -1525,7 +1700,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
this.codingPos = codingPos; this.codingPos = codingPos;
}; };
constructor.prototype.addPixelsNeg = CCITTFaxStream.prototype.addPixelsNeg =
function ccittFaxStreamAddPixelsNeg(a1, blackPixels) { function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
var codingLine = this.codingLine; var codingLine = this.codingLine;
var codingPos = this.codingPos; var codingPos = this.codingPos;
@ -1554,7 +1729,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
this.codingPos = codingPos; this.codingPos = codingPos;
}; };
constructor.prototype.lookChar = function ccittFaxStreamLookChar() { CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() {
if (this.buf != EOF) if (this.buf != EOF)
return this.buf; return this.buf;
@ -1852,10 +2027,10 @@ var CCITTFaxStream = (function ccittFaxStream() {
// values. The first array element indicates whether a valid code is being // values. The first array element indicates whether a valid code is being
// returned. The second array element is the actual code. The third array // returned. The second array element is the actual code. The third array
// element indicates whether EOF was reached. // element indicates whether EOF was reached.
var findTableCode = function ccittFaxStreamFindTableCode(start, end, table, CCITTFaxStream.prototype.findTableCode =
limit) { function ccittFaxStreamFindTableCode(start, end, table, limit) {
var limitValue = limit || 0;
var limitValue = limit || 0;
for (var i = start; i <= end; ++i) { for (var i = start; i <= end; ++i) {
var code = this.lookBits(i); var code = this.lookBits(i);
if (code == EOF) if (code == EOF)
@ -1873,18 +2048,20 @@ var CCITTFaxStream = (function ccittFaxStream() {
return [false, 0, false]; return [false, 0, false];
}; };
constructor.prototype.getTwoDimCode = function ccittFaxStreamGetTwoDimCode() { CCITTFaxStream.prototype.getTwoDimCode =
function ccittFaxStreamGetTwoDimCode() {
var code = 0; var code = 0;
var p; var p;
if (this.eoblock) { if (this.eoblock) {
code = this.lookBits(7); code = this.lookBits(7);
p = twoDimTable[code]; p = twoDimTable[code];
if (p[0] > 0) { if (p && p[0] > 0) {
this.eatBits(p[0]); this.eatBits(p[0]);
return p[1]; return p[1];
} }
} else { } else {
var result = findTableCode(1, 7, twoDimTable); var result = this.findTableCode(1, 7, twoDimTable);
if (result[0] && result[2]) if (result[0] && result[2])
return result[1]; return result[1];
} }
@ -1892,7 +2069,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
return EOF; return EOF;
}; };
constructor.prototype.getWhiteCode = function ccittFaxStreamGetWhiteCode() { CCITTFaxStream.prototype.getWhiteCode =
function ccittFaxStreamGetWhiteCode() {
var code = 0; var code = 0;
var p; var p;
var n; var n;
@ -1911,11 +2090,11 @@ var CCITTFaxStream = (function ccittFaxStream() {
return p[1]; return p[1];
} }
} else { } else {
var result = findTableCode(1, 9, whiteTable2); var result = this.findTableCode(1, 9, whiteTable2);
if (result[0]) if (result[0])
return result[1]; return result[1];
result = findTableCode(11, 12, whiteTable1); result = this.findTableCode(11, 12, whiteTable1);
if (result[0]) if (result[0])
return result[1]; return result[1];
} }
@ -1924,7 +2103,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
return 1; return 1;
}; };
constructor.prototype.getBlackCode = function ccittFaxStreamGetBlackCode() { CCITTFaxStream.prototype.getBlackCode =
function ccittFaxStreamGetBlackCode() {
var code, p; var code, p;
if (this.eoblock) { if (this.eoblock) {
code = this.lookBits(13); code = this.lookBits(13);
@ -1942,15 +2123,15 @@ var CCITTFaxStream = (function ccittFaxStream() {
return p[1]; return p[1];
} }
} else { } else {
var result = findTableCode(2, 6, blackTable3); var result = this.findTableCode(2, 6, blackTable3);
if (result[0]) if (result[0])
return result[1]; return result[1];
result = findTableCode(7, 12, blackTable2, 64); result = this.findTableCode(7, 12, blackTable2, 64);
if (result[0]) if (result[0])
return result[1]; return result[1];
result = findTableCode(10, 13, blackTable1); result = this.findTableCode(10, 13, blackTable1);
if (result[0]) if (result[0])
return result[1]; return result[1];
} }
@ -1959,7 +2140,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
return 1; return 1;
}; };
constructor.prototype.lookBits = function ccittFaxStreamLookBits(n) { CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) {
var c; var c;
while (this.inputBits < n) { while (this.inputBits < n) {
if ((c = this.str.getByte()) == null) { if ((c = this.str.getByte()) == null) {
@ -1974,16 +2155,16 @@ var CCITTFaxStream = (function ccittFaxStream() {
return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n)); return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
}; };
constructor.prototype.eatBits = function ccittFaxStreamEatBits(n) { CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) {
if ((this.inputBits -= n) < 0) if ((this.inputBits -= n) < 0)
this.inputBits = 0; this.inputBits = 0;
}; };
return constructor; return CCITTFaxStream;
})(); })();
var LZWStream = (function lzwStream() { var LZWStream = (function LZWStreamClosure() {
function constructor(str, earlyChange) { function LZWStream(str, earlyChange) {
this.str = str; this.str = str;
this.dict = str.dict; this.dict = str.dict;
this.cachedData = 0; this.cachedData = 0;
@ -2009,9 +2190,9 @@ var LZWStream = (function lzwStream() {
DecodeStream.call(this); DecodeStream.call(this);
} }
constructor.prototype = Object.create(DecodeStream.prototype); LZWStream.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBits = function lzwStreamReadBits(n) { LZWStream.prototype.readBits = function LZWStream_readBits(n) {
var bitsCached = this.bitsCached; var bitsCached = this.bitsCached;
var cachedData = this.cachedData; var cachedData = this.cachedData;
while (bitsCached < n) { while (bitsCached < n) {
@ -2029,7 +2210,7 @@ var LZWStream = (function lzwStream() {
return (cachedData >>> bitsCached) & ((1 << n) - 1); return (cachedData >>> bitsCached) & ((1 << n) - 1);
}; };
constructor.prototype.readBlock = function lzwStreamReadBlock() { LZWStream.prototype.readBlock = function LZWStream_readBlock() {
var blockSize = 512; var blockSize = 512;
var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize; var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
var i, j, q; var i, j, q;
@ -2108,6 +2289,6 @@ var LZWStream = (function lzwStream() {
this.bufferLength = currentBufferLength; this.bufferLength = currentBufferLength;
}; };
return constructor; return LZWStream;
})(); })();

218
apps/files_pdfviewer/js/pdfjs/src/util.js Executable file → Normal file
View File

@ -76,24 +76,102 @@ function stringToBytes(str) {
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
var Util = (function utilUtil() { var Util = (function UtilClosure() {
function constructor() {} function Util() {}
constructor.makeCssRgb = function makergb(r, g, b) {
Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
}; };
constructor.makeCssCmyk = function makecmyk(c, m, y, k) {
Util.makeCssCmyk = function Util_makeCssCmyk(c, m, y, k) {
c = (new DeviceCmykCS()).getRgb([c, m, y, k]); c = (new DeviceCmykCS()).getRgb([c, m, y, k]);
var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0; var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0;
return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
}; };
constructor.applyTransform = function apply(p, m) {
// For 2d affine transforms
Util.applyTransform = function Util_applyTransform(p, m) {
var xt = p[0] * m[0] + p[1] * m[2] + m[4]; var xt = p[0] * m[0] + p[1] * m[2] + m[4];
var yt = p[0] * m[1] + p[1] * m[3] + m[5]; var yt = p[0] * m[1] + p[1] * m[3] + m[5];
return [xt, yt]; return [xt, yt];
}; };
return constructor; // Apply a generic 3d matrix M on a 3-vector v:
// | a b c | | X |
// | d e f | x | Y |
// | g h i | | Z |
// M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
// with v as [X,Y,Z]
Util.apply3dTransform = function Util_apply3dTransform(m, v) {
return [
m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
];
}
// Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
// For coordinate systems whose origin lies in the bottom-left, this
// means normalization to (BL,TR) ordering. For systems with origin in the
// top-left, this means (TL,BR) ordering.
Util.normalizeRect = function Util_normalizeRect(rect) {
var r = rect.slice(0); // clone rect
if (rect[0] > rect[2]) {
r[0] = rect[2];
r[2] = rect[0];
}
if (rect[1] > rect[3]) {
r[1] = rect[3];
r[3] = rect[1];
}
return r;
}
// Returns a rectangle [x1, y1, x2, y2] corresponding to the
// intersection of rect1 and rect2. If no intersection, returns 'false'
// The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
Util.intersect = function Util_intersect(rect1, rect2) {
function compare(a, b) {
return a - b;
};
// Order points along the axes
var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
result = [];
rect1 = Util.normalizeRect(rect1);
rect2 = Util.normalizeRect(rect2);
// X: first and second points belong to different rectangles?
if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
(orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
// Intersection must be between second and third points
result[0] = orderedX[1];
result[2] = orderedX[2];
} else {
return false;
}
// Y: first and second points belong to different rectangles?
if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
(orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
// Intersection must be between second and third points
result[1] = orderedY[1];
result[3] = orderedY[2];
} else {
return false;
}
return result;
}
Util.sign = function Util_sign(num) {
return num < 0 ? -1 : 1;
};
return Util;
})(); })();
var PDFStringTranslateTable = [ var PDFStringTranslateTable = [
@ -197,7 +275,7 @@ function isPDFFunction(v) {
* can be set. If any of these happens twice or the data is required before * can be set. If any of these happens twice or the data is required before
* it was set, an exception is throw. * it was set, an exception is throw.
*/ */
var Promise = (function promise() { var Promise = (function PromiseClosure() {
var EMPTY_PROMISE = {}; var EMPTY_PROMISE = {};
/** /**
@ -206,6 +284,8 @@ var Promise = (function promise() {
*/ */
function Promise(name, data) { function Promise(name, data) {
this.name = name; this.name = name;
this.isRejected = false;
this.error = null;
// If you build a promise and pass in some data it's already resolved. // If you build a promise and pass in some data it's already resolved.
if (data != null) { if (data != null) {
this.isResolved = true; this.isResolved = true;
@ -216,8 +296,35 @@ var Promise = (function promise() {
this._data = EMPTY_PROMISE; this._data = EMPTY_PROMISE;
} }
this.callbacks = []; this.callbacks = [];
this.errbacks = [];
};
/**
* Builds a promise that is resolved when all the passed in promises are
* resolved.
* @param {Promise[]} promises Array of promises to wait for.
* @return {Promise} New dependant promise.
*/
Promise.all = function Promise_all(promises) {
var deferred = new Promise();
var unresolved = promises.length;
var results = [];
if (unresolved === 0) {
deferred.resolve(results);
return deferred;
}
for (var i = 0; i < unresolved; ++i) {
var promise = promises[i];
promise.then((function(i) {
return function(value) {
results[i] = value;
unresolved--;
if (unresolved === 0)
deferred.resolve(results);
};
})(i));
}
return deferred;
}; };
Promise.prototype = { Promise.prototype = {
hasData: false, hasData: false,
@ -226,8 +333,8 @@ var Promise = (function promise() {
return; return;
} }
if (this._data !== EMPTY_PROMISE) { if (this._data !== EMPTY_PROMISE) {
throw 'Promise ' + this.name + error('Promise ' + this.name +
': Cannot set the data of a promise twice'; ': Cannot set the data of a promise twice');
} }
this._data = value; this._data = value;
this.hasData = true; this.hasData = true;
@ -239,12 +346,12 @@ var Promise = (function promise() {
get data() { get data() {
if (this._data === EMPTY_PROMISE) { if (this._data === EMPTY_PROMISE) {
throw 'Promise ' + this.name + ': Cannot get data that isn\'t set'; error('Promise ' + this.name + ': Cannot get data that isn\'t set');
} }
return this._data; return this._data;
}, },
onData: function promiseOnData(callback) { onData: function Promise_onData(callback) {
if (this._data !== EMPTY_PROMISE) { if (this._data !== EMPTY_PROMISE) {
callback(this._data); callback(this._data);
} else { } else {
@ -252,13 +359,16 @@ var Promise = (function promise() {
} }
}, },
resolve: function promiseResolve(data) { resolve: function Promise_resolve(data) {
if (this.isResolved) { if (this.isResolved) {
throw 'A Promise can be resolved only once ' + this.name; error('A Promise can be resolved only once ' + this.name);
}
if (this.isRejected) {
error('The Promise was already rejected ' + this.name);
} }
this.isResolved = true; this.isResolved = true;
this.data = data; this.data = data || null;
var callbacks = this.callbacks; var callbacks = this.callbacks;
for (var i = 0, ii = callbacks.length; i < ii; i++) { for (var i = 0, ii = callbacks.length; i < ii; i++) {
@ -266,17 +376,39 @@ var Promise = (function promise() {
} }
}, },
then: function promiseThen(callback) { reject: function Promise_reject(reason) {
if (this.isRejected) {
error('A Promise can be rejected only once ' + this.name);
}
if (this.isResolved) {
error('The Promise was already resolved ' + this.name);
}
this.isRejected = true;
this.error = reason || null;
var errbacks = this.errbacks;
for (var i = 0, ii = errbacks.length; i < ii; i++) {
errbacks[i].call(null, reason);
}
},
then: function Promise_then(callback, errback) {
if (!callback) { if (!callback) {
throw 'Requiring callback' + this.name; error('Requiring callback' + this.name);
} }
// If the promise is already resolved, call the callback directly. // If the promise is already resolved, call the callback directly.
if (this.isResolved) { if (this.isResolved) {
var data = this.data; var data = this.data;
callback.call(null, data); callback.call(null, data);
} else if (this.isRejected && errback) {
var error = this.error;
errback.call(null, error);
} else { } else {
this.callbacks.push(callback); this.callbacks.push(callback);
if (errback)
this.errbacks.push(errback);
} }
} }
}; };
@ -284,3 +416,55 @@ var Promise = (function promise() {
return Promise; return Promise;
})(); })();
var StatTimer = (function StatTimerClosure() {
function rpad(str, pad, length) {
while (str.length < length)
str += pad;
return str;
}
function StatTimer() {
this.started = {};
this.times = [];
this.enabled = true;
}
StatTimer.prototype = {
time: function StatTimer_time(name) {
if (!this.enabled)
return;
if (name in this.started)
throw 'Timer is already running for ' + name;
this.started[name] = Date.now();
},
timeEnd: function StatTimer_timeEnd(name) {
if (!this.enabled)
return;
if (!(name in this.started))
throw 'Timer has not been started for ' + name;
this.times.push({
'name': name,
'start': this.started[name],
'end': Date.now()
});
// Remove timer from started so it can be called again.
delete this.started[name];
},
toString: function StatTimer_toString() {
var times = this.times;
var out = '';
// Find the longest name for padding purposes.
var longest = 0;
for (var i = 0, ii = times.length; i < ii; ++i) {
var name = times[i]['name'];
if (name.length > longest)
longest = name.length;
}
for (var i = 0, ii = times.length; i < ii; ++i) {
var span = times[i];
var duration = span.end - span.start;
out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
}
return out;
}
};
return StatTimer;
})();

View File

6
apps/files_pdfviewer/js/pdfjs/src/utils/fonts_utils.js Executable file → Normal file
View File

@ -122,9 +122,9 @@ function readFontDictData(aString, aMap) {
token = ''; token = '';
var parsed = false; var parsed = false;
while (!parsed) { while (!parsed) {
var byte = aString[i++]; var octet = aString[i++];
var nibbles = [parseInt(byte / 16, 10), parseInt(byte % 16, 10)]; var nibbles = [parseInt(octet / 16, 10), parseInt(octet % 16, 10)];
for (var j = 0; j < nibbles.length; j++) { for (var j = 0; j < nibbles.length; j++) {
var nibble = nibbles[j]; var nibble = nibbles[j];
switch (nibble) { switch (nibble) {
@ -336,7 +336,7 @@ var Type2Parser = function type2Parser(aFilePath) {
var privateDict = []; var privateDict = [];
for (var i = 0; i < priv.size; i++) for (var i = 0; i < priv.size; i++)
privateDict.push(aStream.getByte()); privateDict.push(aStream.getByte());
dump('private:' + privateDict); dump('privateData:' + privateDict);
parseAsToken(privateDict, CFFDictPrivateDataMap); parseAsToken(privateDict, CFFDictPrivateDataMap);
for (var p in font.map) for (var p in font.map)

154
apps/files_pdfviewer/js/pdfjs/src/worker.js Executable file → Normal file
View File

@ -6,6 +6,8 @@
function MessageHandler(name, comObj) { function MessageHandler(name, comObj) {
this.name = name; this.name = name;
this.comObj = comObj; this.comObj = comObj;
this.callbackIndex = 1;
var callbacks = this.callbacks = {};
var ah = this.actionHandler = {}; var ah = this.actionHandler = {};
ah['console_log'] = [function ahConsoleLog(data) { ah['console_log'] = [function ahConsoleLog(data) {
@ -17,11 +19,32 @@ function MessageHandler(name, comObj) {
comObj.onmessage = function messageHandlerComObjOnMessage(event) { comObj.onmessage = function messageHandlerComObjOnMessage(event) {
var data = event.data; var data = event.data;
if (data.action in ah) { if (data.isReply) {
var callbackId = data.callbackId;
if (data.callbackId in callbacks) {
var callback = callbacks[callbackId];
delete callbacks[callbackId];
callback(data.data);
} else {
error('Cannot resolve callback ' + callbackId);
}
} else if (data.action in ah) {
var action = ah[data.action]; var action = ah[data.action];
action[0].call(action[1], data.data); if (data.callbackId) {
var promise = new Promise();
promise.then(function(resolvedData) {
comObj.postMessage({
isReply: true,
callbackId: data.callbackId,
data: resolvedData
});
});
action[0].call(action[1], data.data, promise);
} else {
action[0].call(action[1], data.data);
}
} else { } else {
throw 'Unkown action from worker: ' + data.action; error('Unkown action from worker: ' + data.action);
} }
}; };
} }
@ -30,44 +53,47 @@ MessageHandler.prototype = {
on: function messageHandlerOn(actionName, handler, scope) { on: function messageHandlerOn(actionName, handler, scope) {
var ah = this.actionHandler; var ah = this.actionHandler;
if (ah[actionName]) { if (ah[actionName]) {
throw 'There is already an actionName called "' + actionName + '"'; error('There is already an actionName called "' + actionName + '"');
} }
ah[actionName] = [handler, scope]; ah[actionName] = [handler, scope];
}, },
/**
send: function messageHandlerSend(actionName, data) { * Sends a message to the comObj to invoke the action with the supplied data.
this.comObj.postMessage({ * @param {String} actionName Action to call.
* @param {JSON} data JSON data to send.
* @param {function} [callback] Optional callback that will handle a reply.
*/
send: function messageHandlerSend(actionName, data, callback) {
var message = {
action: actionName, action: actionName,
data: data data: data
}); };
if (callback) {
var callbackId = this.callbackIndex++;
this.callbacks[callbackId] = callback;
message.callbackId = callbackId;
}
this.comObj.postMessage(message);
} }
}; };
var WorkerMessageHandler = { var WorkerMessageHandler = {
setup: function wphSetup(handler) { setup: function wphSetup(handler) {
var pdfDoc = null; var pdfModel = null;
handler.on('test', function wphSetupTest(data) { handler.on('test', function wphSetupTest(data) {
handler.send('test', data instanceof Uint8Array); handler.send('test', data instanceof Uint8Array);
}); });
handler.on('workerSrc', function wphSetupWorkerSrc(data) {
// In development, the `workerSrc` message is handled in the
// `worker_loader.js` file. In production the workerProcessHandler is
// called for this. This servers as a dummy to prevent calling an
// undefined action `workerSrc`.
});
handler.on('doc', function wphSetupDoc(data) { handler.on('doc', function wphSetupDoc(data) {
// Create only the model of the PDFDoc, which is enough for // Create only the model of the PDFDoc, which is enough for
// processing the content of the pdf. // processing the content of the pdf.
pdfDoc = new PDFDocModel(new Stream(data)); pdfModel = new PDFDocModel(new Stream(data));
}); });
handler.on('page_request', function wphSetupPageRequest(pageNum) { handler.on('page_request', function wphSetupPageRequest(pageNum) {
pageNum = parseInt(pageNum); pageNum = parseInt(pageNum);
var page = pdfDoc.getPage(pageNum);
// The following code does quite the same as // The following code does quite the same as
// Page.prototype.startRendering, but stops at one point and sends the // Page.prototype.startRendering, but stops at one point and sends the
@ -77,12 +103,42 @@ var WorkerMessageHandler = {
var start = Date.now(); var start = Date.now();
var dependency = []; var dependency = [];
var operatorList = null;
try {
var page = pdfModel.getPage(pageNum);
// Pre compile the pdf page and fetch the fonts/images.
operatorList = page.getOperatorList(handler, dependency);
} catch (e) {
var minimumStackMessage =
'worker.js: while trying to getPage() and getOperatorList()';
// Pre compile the pdf page and fetch the fonts/images. // Turn the error into an obj that can be serialized
var IRQueue = page.getIRQueue(handler, dependency); if (typeof e === 'string') {
e = {
message: e,
stack: minimumStackMessage
};
} else if (typeof e === 'object') {
e = {
message: e.message || e.toString(),
stack: e.stack || minimumStackMessage
};
} else {
e = {
message: 'Unknown exception type: ' + (typeof e),
stack: minimumStackMessage
};
}
console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum, handler.send('page_error', {
Date.now() - start, IRQueue.fnArray.length); pageNum: pageNum,
error: e
});
return;
}
console.log('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
Date.now() - start, operatorList.fnArray.length);
// Filter the dependecies for fonts. // Filter the dependecies for fonts.
var fonts = {}; var fonts = {};
@ -95,59 +151,10 @@ var WorkerMessageHandler = {
handler.send('page', { handler.send('page', {
pageNum: pageNum, pageNum: pageNum,
IRQueue: IRQueue, operatorList: operatorList,
depFonts: Object.keys(fonts) depFonts: Object.keys(fonts)
}); });
}, this); }, this);
handler.on('font', function wphSetupFont(data) {
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 objData = obj.data;
if (objData) {
var length = objData.length;
for (var j = 0; j < length; ++j)
str += String.fromCharCode(objData[j]);
}
obj.str = str;
// Remove the data array form the font object, as it's not needed
// anymore as we sent over the ready str.
delete obj.data;
handler.send('font_ready', [objId, obj]);
});
} }
}; };
@ -168,6 +175,7 @@ var workerConsole = {
action: 'console_error', action: 'console_error',
data: args data: args
}); });
throw 'pdf.js execution error';
}, },
time: function time(name) { time: function time(name) {
@ -177,7 +185,7 @@ var workerConsole = {
timeEnd: function timeEnd(name) { timeEnd: function timeEnd(name) {
var time = consoleTimer[name]; var time = consoleTimer[name];
if (time == null) { if (time == null) {
throw 'Unkown timer name ' + name; error('Unkown timer name ' + name);
} }
this.log('Timer:', name, Date.now() - time); this.log('Timer:', name, Date.now() - time);
} }

73
apps/files_pdfviewer/js/pdfjs/src/worker_loader.js Executable file → Normal file
View File

@ -3,51 +3,32 @@
'use strict'; 'use strict';
function onMessageLoader(evt) { // List of files to include;
// Reset the `onmessage` function as it was only set to call var files = [
// this function the first time a message is passed to the worker 'core.js',
// but shouldn't get called anytime afterwards. 'util.js',
this.onmessage = null; 'canvas.js',
'obj.js',
'function.js',
'charsets.js',
'cidmaps.js',
'colorspace.js',
'crypto.js',
'evaluator.js',
'fonts.js',
'glyphlist.js',
'image.js',
'metrics.js',
'parser.js',
'pattern.js',
'stream.js',
'worker.js',
'../external/jpgjs/jpg.js',
'jpx.js',
'bidi.js'
];
if (evt.data.action !== 'workerSrc') { // Load all the files.
throw 'Worker expects first message to be `workerSrc`'; for (var i = 0; i < files.length; i++) {
} importScripts(files[i]);
// Content of `PDFJS.workerSrc` as defined on the main thread.
var workerSrc = evt.data.data;
// Extract the directory that contains the source files to load.
// Assuming the source files have the same relative possition as the
// `workerSrc` file.
var dir = workerSrc.substring(0, workerSrc.lastIndexOf('/') + 1);
// List of files to include;
var files = [
'core.js',
'util.js',
'canvas.js',
'obj.js',
'function.js',
'charsets.js',
'cidmaps.js',
'colorspace.js',
'crypto.js',
'evaluator.js',
'fonts.js',
'glyphlist.js',
'image.js',
'metrics.js',
'parser.js',
'pattern.js',
'stream.js',
'worker.js',
'../external/jpgjs/jpg.js'
];
// Load all the files.
for (var i = 0; i < files.length; i++) {
importScripts(dir + files[i]);
}
} }
this.onmessage = onMessageLoader;

3
apps/files_pdfviewer/js/pdfjs/web/images/bookmark.svg Executable file → Normal file
View File

@ -20,7 +20,8 @@
height="48.000000px" height="48.000000px"
width="48.000000px" width="48.000000px"
inkscape:output_extension="org.inkscape.output.svg.inkscape" inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1"> version="1.1"
viewbox="0 0 48 48">
<defs <defs
id="defs3"> id="defs3">
<inkscape:perspective <inkscape:perspective

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1,3 @@
<svg height="40" width="40" xmlns="http://www.w3.org/2000/svg">
<path d="M2.379,14.729 5.208,11.899 12.958,19.648 25.877,6.733 28.707,9.561 12.958,25.308z" fill="#333333"></path>
</svg>

After

Width:  |  Height:  |  Size: 188 B

View File

@ -0,0 +1,3 @@
<svg height="40" width="40" xmlns="http://www.w3.org/2000/svg">
<path d="M16,5.333c-7.732,0-14,4.701-14,10.5c0,1.982,0.741,3.833,2.016,5.414L2,25.667l5.613-1.441c2.339,1.317,5.237,2.107,8.387,2.107c7.732,0,14-4.701,14-10.5C30,10.034,23.732,5.333,16,5.333z" fill="#333333"></path>
</svg>

After

Width:  |  Height:  |  Size: 289 B

View File

@ -16,7 +16,8 @@
id="svg2994" id="svg2994"
height="48px" height="48px"
width="48px" width="48px"
inkscape:output_extension="org.inkscape.output.svg.inkscape"> inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs <defs
id="defs3"> id="defs3">
<inkscape:perspective <inkscape:perspective

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

3
apps/files_pdfviewer/js/pdfjs/web/images/download.svg Executable file → Normal file
View File

@ -16,7 +16,8 @@
id="svg2913" id="svg2913"
height="48px" height="48px"
width="48px" width="48px"
inkscape:output_extension="org.inkscape.output.svg.inkscape"> inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs <defs
id="defs3"> id="defs3">
<inkscape:perspective <inkscape:perspective

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

3
apps/files_pdfviewer/js/pdfjs/web/images/go-down.svg Executable file → Normal file
View File

@ -19,7 +19,8 @@
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png" inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
inkscape:export-xdpi="90.000000" inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000" inkscape:export-ydpi="90.000000"
inkscape:output_extension="org.inkscape.output.svg.inkscape"> inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs <defs
id="defs3"> id="defs3">
<inkscape:perspective <inkscape:perspective

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

3
apps/files_pdfviewer/js/pdfjs/web/images/go-up.svg Executable file → Normal file
View File

@ -19,7 +19,8 @@
inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png" inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
inkscape:export-xdpi="90.000000" inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000" inkscape:export-ydpi="90.000000"
inkscape:output_extension="org.inkscape.output.svg.inkscape"> inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs <defs
id="defs3"> id="defs3">
<inkscape:perspective <inkscape:perspective

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,297 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48"
height="48"
id="svg3075"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="pin-down.svg"
viewPort="0 0 48 48">
<defs
id="defs3077">
<linearGradient
inkscape:collect="always"
id="linearGradient3804">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop3806" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop3808" />
</linearGradient>
<linearGradient
id="linearGradient3965">
<stop
id="stop3967"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="1"
id="stop3969" />
</linearGradient>
<linearGradient
id="linearGradient3885">
<stop
style="stop-color:#a8b5e9;stop-opacity:1;"
offset="0"
id="stop3889" />
<stop
id="stop3891"
offset="1"
style="stop-color:#1d4488;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3865">
<stop
style="stop-color:#0e0ec3;stop-opacity:0"
offset="0"
id="stop3867" />
<stop
id="stop3883"
offset="0.5"
style="stop-color:#95b1e4;stop-opacity:1;" />
<stop
style="stop-color:#0d29c0;stop-opacity:1;"
offset="1"
id="stop3869" />
</linearGradient>
<linearGradient
id="linearGradient3853">
<stop
style="stop-color:#717171;stop-opacity:1;"
offset="0"
id="stop3855" />
<stop
id="stop3861"
offset="0.5"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#818181;stop-opacity:1;"
offset="1"
id="stop3857" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="radialGradient3792"
cx="13.508819"
cy="30.521608"
fx="13.508819"
fy="30.521608"
r="13.254341"
gradientTransform="matrix(1,0,0,1.045977,0,-1.4434017)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="linearGradient3802"
x1="15.306904"
y1="13.407407"
x2="29.35461"
y2="30.15519"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2304178,0,0,1.1235308,-2.1158755,998.83747)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3804"
id="radialGradient3812"
cx="20.111172"
cy="28.238274"
fx="20.111172"
fy="28.238274"
r="7.6291947"
gradientTransform="matrix(1.2304178,0,0,1.1452771,-2.1158755,998.22337)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="radialGradient3822"
cx="23.985939"
cy="24.847366"
fx="23.985939"
fy="24.847366"
r="10.593476"
gradientTransform="matrix(0.63682384,0.44303926,-1.1714282,1.6838088,35.523491,-26.055439)"
gradientUnits="userSpaceOnUse" />
<filter
inkscape:collect="always"
id="filter3856"
x="-0.30370581"
width="1.6074116"
y="-0.32771564"
height="1.6554313">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="4.7808869"
id="feGaussianBlur3858" />
</filter>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="radialGradient3865"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.045977,0,-1.4434017)"
cx="13.508819"
cy="30.521608"
fx="13.508819"
fy="30.521608"
r="13.254341" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="linearGradient3867"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2304178,0,0,1.1235308,-2.1158755,998.83747)"
x1="15.306904"
y1="13.407407"
x2="29.35461"
y2="30.15519" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3804"
id="radialGradient3869"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2304178,0,0,1.1452771,-2.1158755,998.22337)"
cx="20.111172"
cy="28.238274"
fx="20.111172"
fy="28.238274"
r="7.6291947" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="radialGradient3871"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.63682384,0.44303926,-1.1714282,1.6838088,35.523491,-26.055439)"
cx="23.985939"
cy="24.847366"
fx="23.985939"
fy="24.847366"
r="10.593476" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="linearGradient3875"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.98683814,0,0,0.9524914,3.4991888,1004.1467)"
x1="15.306904"
y1="13.407407"
x2="29.35461"
y2="30.15519" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3804"
id="radialGradient3877"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.195641,0.23932984,-0.18533175,0.95255553,4.5333676,999.33159)"
cx="20.111172"
cy="28.238274"
fx="20.111172"
fy="28.238274"
r="7.6291947" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="radialGradient3880"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5847553,0.52693722,-0.99805104,2.7064773,14.11088,-45.304477)"
cx="18.133854"
cy="19.778509"
fx="18.133854"
fy="19.778509"
r="10.593476" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="radialGradient3882"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.045977,0,-1.4434017)"
cx="13.508819"
cy="30.521608"
fx="13.508819"
fy="30.521608"
r="13.254341" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.9558805"
inkscape:cx="3.0237013"
inkscape:cy="17.287267"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1291"
inkscape:window-height="776"
inkscape:window-x="16"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3080">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1004.3622)">
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;filter:url(#filter3856)"
d="m 14.326415,1019.2702 c -8.3327876,4.0675 -9.8235436,10.8833 -8.8783416,15.1336 4.6840646,7.9754 8.3608166,13.8165 24.0118786,12.9139 9.657617,-3.7312 12.9762,-9.3269 13.519293,-15.7389 -0.547269,-4.3839 -1.957958,-9.3396 -5.649854,-14.9317 -3.965534,-2.471 -6.300859,-4.4246 -10.290805,-4.2374 -8.25193,0.5026 -8.752485,4.4502 -12.712171,6.8605 z"
id="path3826"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
transform="matrix(0.69099294,0,0,0.75978808,7.3427938,249.11025)" />
<path
sodipodi:type="arc"
style="fill:url(#radialGradient3882);fill-opacity:1;stroke:none"
id="path3011"
sodipodi:cx="21.176477"
sodipodi:cy="31.393986"
sodipodi:rx="13.254341"
sodipodi:ry="13.863736"
d="m 34.430819,31.393986 a 13.254341,13.863736 0 1 1 -26.5086827,0 13.254341,13.863736 0 1 1 26.5086827,0 z"
transform="matrix(0.98683814,0,0,0.83062636,2.696034,1005.3655)" />
<path
style="fill:url(#linearGradient3875);fill-opacity:1;stroke:url(#radialGradient3877);stroke-width:0.9695127;stroke-opacity:1"
d="m 17.246758,1026.7905 c -1.7156,4.5052 -2.482464,10.6205 8.726963,10.7476 4.849099,-1.8941 3.522783,-5.3561 6.021544,-11.8282 l -10.973104,-1.5977 z"
id="path3794"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:type="arc"
style="fill:url(#radialGradient3880);fill-opacity:1;stroke:none"
id="path3814"
sodipodi:cx="24.718111"
sodipodi:cy="23.38278"
sodipodi:rx="10.593476"
sodipodi:ry="9.6854639"
d="m 35.311587,23.38278 a 10.593476,9.6854639 0 1 1 -21.186952,0 10.593476,9.6854639 0 1 1 21.186952,0 z"
transform="matrix(0.85425691,0,0,0.84187503,3.9779774,1006.7561)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -0,0 +1,230 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48"
height="48"
id="svg3075"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="pin-up.svg"
viewPort="0 0 48 48">
<defs
id="defs3077">
<linearGradient
id="linearGradient3965">
<stop
id="stop3967"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="1"
id="stop3969" />
</linearGradient>
<linearGradient
id="linearGradient3885">
<stop
style="stop-color:#a8b5e9;stop-opacity:1;"
offset="0"
id="stop3889" />
<stop
id="stop3891"
offset="1"
style="stop-color:#1d4488;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3865">
<stop
style="stop-color:#0e0ec3;stop-opacity:1;"
offset="0"
id="stop3867" />
<stop
id="stop3883"
offset="0.5"
style="stop-color:#95b1e4;stop-opacity:1;" />
<stop
style="stop-color:#0d29c0;stop-opacity:1;"
offset="1"
id="stop3869" />
</linearGradient>
<linearGradient
id="linearGradient3853">
<stop
style="stop-color:#717171;stop-opacity:1;"
offset="0"
id="stop3855" />
<stop
id="stop3861"
offset="0.5"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#818181;stop-opacity:1;"
offset="1"
id="stop3857" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3853"
id="linearGradient3859"
x1="7.7696066"
y1="34.979828"
x2="11.854106"
y2="39.107044"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(4.8388015,1001.6582)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="radialGradient3871"
cx="14.801222"
cy="1030.6609"
fx="14.801222"
fy="1030.6609"
r="10.177785"
gradientTransform="matrix(1,0,0,1.0108042,4.8388015,-13.880529)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3865"
id="linearGradient3881"
x1="15.012629"
y1="11.922465"
x2="31.098303"
y2="28.858271"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.97315436,4.8388015,1002.4769)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3885"
id="radialGradient3909"
cx="16.437693"
cy="22.596292"
fx="16.437693"
fy="22.596292"
r="1.7789712"
gradientTransform="matrix(1,0,0,8.3599999,0,-166.30871)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3865"
id="linearGradient3927"
x1="26.47109"
y1="1010.7343"
x2="35.294788"
y2="1019.8425"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(4.5541661,-2.1347654)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3965"
id="radialGradient3995"
cx="23.189369"
cy="25.704245"
fx="23.189369"
fy="25.704245"
r="37.336674"
gradientTransform="matrix(1,0,0,1.0332422,0,-0.85446479)"
gradientUnits="userSpaceOnUse" />
<filter
inkscape:collect="always"
id="filter4009"
x="-0.19299152"
width="1.385983"
y="-0.18351803"
height="1.3670361">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="3.8667902"
id="feGaussianBlur4011" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.2819435"
inkscape:cx="18.697469"
inkscape:cy="17.287267"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="970"
inkscape:window-height="778"
inkscape:window-x="284"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3080">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1004.3622)">
<path
style="fill:url(#radialGradient3995);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1.0;filter:url(#filter4009)"
d="M -0.85390618,50.988672 14.231769,27.790888 C 12.21393,25.133052 9.5514307,24.605255 9.9622384,18.824874 13.947134,14.236899 17.362759,16.258973 21.347654,16.54779 l 8.966014,-8.6813789 c 1.467204,-2.4778468 -1.023584,-4.6422045 0.569271,-7.25820222 4.802307,-0.84764718 6.662499,1.15219542 11.527733,6.26197842 4.061691,4.1873637 5.648882,7.0611607 4.411848,9.5352857 -1.075122,2.776443 -4.518349,-0.692782 -5.835025,0.56927 l -9.108332,10.104556 c -0.418785,3.74872 2.078647,7.861968 -1.280859,11.243098 -4.132171,0.818036 -6.734336,-1.933944 -9.819921,-3.557942 z"
id="path3955"
inkscape:connector-curvature="0"
transform="translate(0,1004.3622)"
sodipodi:nodetypes="ccccccccccccc" />
<g
id="g3929">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path3083"
d="m 3.2884874,1051.0662 c 3.1862139,-6.2911 11.3693156,-15.19 15.4471616,-20.0327 l 2.86533,3.0086 c -3.476851,3.6575 -10.192375,10.8664 -18.3124916,17.0241 z"
style="fill:url(#linearGradient3859);fill-opacity:1;stroke:#a5a5a5;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3863"
d="m 11.10078,1023.3294 c 5.038264,10.1095 11.83652,14.8875 18.358981,18.2167 1.196291,-2.5422 1.454996,-5.6203 0,-9.6776 l -8.539061,-8.6814 c -3.704654,-1.8936 -6.871076,-1.3652 -9.81992,0.1423 z"
style="fill:url(#radialGradient3871);fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3873"
d="m 33.729292,1011.5171 -13.235545,11.4952 c 2.869602,4.2703 6.221839,7.4544 9.108332,9.1408 l 11.385416,-13.0187 z"
style="fill:url(#linearGradient3881);fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3893"
d="m 33.228885,1011.6148 c 1.843189,2.7806 3.431654,5.6597 7.19852,7.6953 l 5.398891,1.7423 c -7.6738,-4.7914 -10.989683,-9.5828 -13.947133,-14.3741 z"
style="fill:url(#linearGradient3927);fill-opacity:1;stroke:none" />
<path
transform="matrix(0.68275275,-0.5590416,0.45791123,0.47036287,17.42507,1012.2127)"
d="m 18.216664,22.596292 a 1.7789712,14.872199 0 1 1 -3.557943,0 1.7789712,14.872199 0 1 1 3.557943,0 z"
sodipodi:ry="14.872199"
sodipodi:rx="1.7789712"
sodipodi:cy="22.596292"
sodipodi:cx="16.437693"
id="path3901"
style="fill:url(#radialGradient3909);fill-opacity:1;stroke:none"
sodipodi:type="arc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

7
apps/files_pdfviewer/js/pdfjs/web/images/zoom-in.svg Executable file → Normal file
View File

@ -16,7 +16,8 @@
inkscape:version="0.46" inkscape:version="0.46"
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions" sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
sodipodi:docname="list-add.svg" sodipodi:docname="list-add.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"> inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs <defs
id="defs6433"> id="defs6433">
<inkscape:perspective <inkscape:perspective
@ -418,12 +419,12 @@
d="M 33.278212 34.94062 A 10.31934 2.320194 0 1 1 12.639532,34.94062 A 10.31934 2.320194 0 1 1 33.278212 34.94062 z" d="M 33.278212 34.94062 A 10.31934 2.320194 0 1 1 12.639532,34.94062 A 10.31934 2.320194 0 1 1 33.278212 34.94062 z"
transform="matrix(1.550487,0,0,1.978714,-12.4813,-32.49103)" /> transform="matrix(1.550487,0,0,1.978714,-12.4813,-32.49103)" />
<path <path
style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" style="fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
d="M 27.514356,37.542682 L 27.514356,28.515722 L 37.492820,28.475543 L 37.492820,21.480219 L 27.523285,21.480219 L 27.514356,11.520049 L 20.498082,11.531210 L 20.502546,21.462362 L 10.512920,21.536022 L 10.477206,28.504561 L 20.511475,28.475543 L 20.518171,37.515896 L 27.514356,37.542682 z " d="M 27.514356,37.542682 L 27.514356,28.515722 L 37.492820,28.475543 L 37.492820,21.480219 L 27.523285,21.480219 L 27.514356,11.520049 L 20.498082,11.531210 L 20.502546,21.462362 L 10.512920,21.536022 L 10.477206,28.504561 L 20.511475,28.475543 L 20.518171,37.515896 L 27.514356,37.542682 z "
id="text1314" id="text1314"
sodipodi:nodetypes="ccccccccccccc" /> sodipodi:nodetypes="ccccccccccccc" />
<path <path
style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" style="opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
d="M 26.498702,36.533920 L 26.498702,27.499738 L 36.501304,27.499738 L 36.494607,22.475309 L 26.507630,22.475309 L 26.507630,12.480335 L 21.512796,12.498193 L 21.521725,22.475309 L 11.495536,22.493166 L 11.468750,27.466256 L 21.533143,27.475185 L 21.519750,36.502670 L 26.498702,36.533920 z " d="M 26.498702,36.533920 L 26.498702,27.499738 L 36.501304,27.499738 L 36.494607,22.475309 L 26.507630,22.475309 L 26.507630,12.480335 L 21.512796,12.498193 L 21.521725,22.475309 L 11.495536,22.493166 L 11.468750,27.466256 L 21.533143,27.475185 L 21.519750,36.502670 L 26.498702,36.533920 z "
id="path7076" id="path7076"
sodipodi:nodetypes="ccccccccccccc" /> sodipodi:nodetypes="ccccccccccccc" />

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

7
apps/files_pdfviewer/js/pdfjs/web/images/zoom-out.svg Executable file → Normal file
View File

@ -16,7 +16,8 @@
inkscape:version="0.46" inkscape:version="0.46"
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions" sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
sodipodi:docname="list-remove.svg" sodipodi:docname="list-remove.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"> inkscape:output_extension="org.inkscape.output.svg.inkscape"
viewbox="0 0 48 48">
<defs <defs
id="defs6433"> id="defs6433">
<inkscape:perspective <inkscape:perspective
@ -406,12 +407,12 @@
inkscape:label="Layer 1" inkscape:label="Layer 1"
inkscape:groupmode="layer"> inkscape:groupmode="layer">
<path <path
style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" style="fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
d="M 27.514356,28.359472 L 39.633445,28.475543 L 39.633445,21.480219 L 27.523285,21.480219 L 20.502546,21.462362 L 8.5441705,21.489147 L 8.5084565,28.457686 L 20.511475,28.475543 L 27.514356,28.359472 z " d="M 27.514356,28.359472 L 39.633445,28.475543 L 39.633445,21.480219 L 27.523285,21.480219 L 20.502546,21.462362 L 8.5441705,21.489147 L 8.5084565,28.457686 L 20.511475,28.475543 L 27.514356,28.359472 z "
id="text1314" id="text1314"
sodipodi:nodetypes="ccccccccc" /> sodipodi:nodetypes="ccccccccc" />
<path <path
style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" style="opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
d="M 38.579429,27.484113 L 38.588357,22.475309 L 9.5267863,22.493166 L 9.5000003,27.466256 L 38.579429,27.484113 z " d="M 38.579429,27.484113 L 38.588357,22.475309 L 9.5267863,22.493166 L 9.5000003,27.466256 L 38.579429,27.484113 z "
id="path7076" id="path7076"
sodipodi:nodetypes="ccccc" /> sodipodi:nodetypes="ccccc" />

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,4 +1,5 @@
FileList={ FileList={
useUndo:true,
update:function(fileListHtml) { update:function(fileListHtml) {
$('#fileList').empty().html(fileListHtml); $('#fileList').empty().html(fileListHtml);
}, },
@ -163,7 +164,7 @@ FileList={
}); });
}, },
do_delete:function(files){ do_delete:function(files){
if(FileList.deleteFiles){//finish any ongoing deletes first if(FileList.deleteFiles || !FileList.useUndo){//finish any ongoing deletes first
FileList.finishDelete(function(){ FileList.finishDelete(function(){
FileList.do_delete(files); FileList.do_delete(files);
}); });
@ -196,7 +197,6 @@ FileList={
boolOperationFinished(data, function(){ boolOperationFinished(data, function(){
$('#notification').fadeOut(); $('#notification').fadeOut();
$.each(FileList.deleteFiles,function(index,file){ $.each(FileList.deleteFiles,function(index,file){
// alert(file);
FileList.remove(file); FileList.remove(file);
}); });
FileList.deleteCanceled=true; FileList.deleteCanceled=true;
@ -225,7 +225,7 @@ $(document).ready(function(){
} }
$('#notification').fadeOut(); $('#notification').fadeOut();
}); });
FileList.useUndo=('onbeforeunload' in window)
$(window).bind('beforeunload', function (){ $(window).bind('beforeunload', function (){
FileList.finishDelete(null,true); FileList.finishDelete(null,true);
}); });