Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Kalervo Kujala 2011-08-24 19:19:19 +03:00
commit 72acb26082
7 changed files with 897 additions and 173 deletions

@ -404,9 +404,6 @@ var Font = (function Font() {
(fontName.indexOf('Italic') != -1);
this.loadedName = fontName.split('-')[0];
this.loading = false;
this.charsToUnicode = function(s) {
return s;
};
return;
}

415
pdf.js

@ -289,6 +289,32 @@ var FakeStream = (function() {
return constructor;
})();
var StreamsSequenceStream = (function() {
function constructor(streams) {
this.streams = streams;
DecodeStream.call(this);
}
constructor.prototype = Object.create(DecodeStream.prototype);
constructor.prototype.readBlock = function() {
var streams = this.streams;
if (streams.length == 0) {
this.eof = true;
return;
}
var stream = streams.shift();
var chunk = stream.getBytes();
var bufferLength = this.bufferLength;
var newLength = bufferLength + chunk.length;
var buffer = this.ensureBuffer(newLength);
buffer.set(chunk, bufferLength);
this.bufferLength = newLength;
};
return constructor;
})();
var FlateStream = (function() {
var codeLenCodeMap = new Uint32Array([
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
@ -3312,28 +3338,16 @@ var Page = (function() {
}
var xref = this.xref;
var content;
var content = xref.fetchIfRef(this.content);
var resources = xref.fetchIfRef(this.resources);
if (!IsArray(this.content)) {
// content is not an array, shortcut
content = xref.fetchIfRef(this.content);
this.code = gfx.compile(content, xref, resources, fonts, images);
return;
if (IsArray(this.content)) {
// fetching items
var i, n = content.length;
for (i = 0; i < n; ++i)
content[i] = xref.fetchIfRef(this.content[i]);
content = new StreamsSequenceStream(content);
}
// the content is an array, compiling all items
var i, n = this.content.length, compiledItems = [];
for (i = 0; i < n; ++i) {
content = xref.fetchIfRef(this.content[i]);
compiledItems.push(gfx.compile(content, xref, resources, fonts,
images));
}
// creating the function that executes all compiled items
this.code = function(gfx) {
var i, n = compiledItems.length;
for (i = 0; i < n; ++i) {
compiledItems[i](gfx);
}
};
this.code = gfx.compile(content, xref, resources, fonts, images);
},
display: function(gfx) {
assert(this.code instanceof Function,
@ -3370,7 +3384,7 @@ var Page = (function() {
var links = [];
for (i = 0; i < n; ++i) {
var annotation = xref.fetch(annotations[i]);
if (!IsDict(annotation, 'Annot'))
if (!IsDict(annotation))
continue;
var subtype = annotation.get('Subtype');
if (!IsName(subtype) || subtype.name != 'Link')
@ -3397,6 +3411,9 @@ var Page = (function() {
TODO('other link types');
break;
}
} else if (annotation.has('Dest')) {
// simple destination link
link.dest = annotation.get('Dest').name;
}
links.push(link);
}
@ -3437,9 +3454,10 @@ var Catalog = (function() {
return str;
}
var obj = this.catDict.get('Outlines');
var xref = this.xref;
var root = { items: [] };
if (IsRef(obj)) {
obj = this.xref.fetch(obj).get('First');
obj = xref.fetch(obj).get('First');
var processed = new RefSet();
if (IsRef(obj)) {
var queue = [{obj: obj, parent: root}];
@ -3448,14 +3466,18 @@ var Catalog = (function() {
processed.put(obj);
while (queue.length > 0) {
var i = queue.shift();
var outlineDict = this.xref.fetch(i.obj);
var outlineDict = xref.fetch(i.obj);
if (!outlineDict.has('Title'))
error('Invalid outline item');
var dest = outlineDict.get('Dest');
if (!dest && outlineDict.get('A')) {
var a = this.xref.fetchIfRef(outlineDict.get('A'));
dest = a.get('D');
var dest = outlineDict.get('A');
if (dest)
dest = xref.fetchIfRef(dest).get('D');
else if (outlineDict.has('Dest')) {
dest = outlineDict.get('Dest');
if (IsName(dest))
dest = dest.name;
}
var outlineItem = {
dest: dest,
title: convertIfUnicode(outlineDict.get('Title')),
@ -3479,7 +3501,8 @@ var Catalog = (function() {
}
}
}
return shadow(this, 'documentOutline', root);
obj = root.items.length > 0 ? root.items : null;
return shadow(this, 'documentOutline', obj);
},
get numPages() {
var obj = this.toplevelPagesDict.get('Count');
@ -3513,15 +3536,26 @@ var Catalog = (function() {
},
get destinations() {
var xref = this.xref;
var dests = {}, nameTreeRef, nameDictionaryRef;
var obj = this.catDict.get('Names');
obj = obj ? xref.fetch(obj) : this.catDict;
obj = obj.get('Dests');
var dests = {};
if (obj) {
if (obj)
nameTreeRef = xref.fetchIfRef(obj).get('Dests');
else if(this.catDict.has('Dests'))
nameDictionaryRef = this.catDict.get('Dests');
if (nameDictionaryRef) {
// reading simple destination dictionary
obj = xref.fetch(nameDictionaryRef);
obj.forEach(function(key, value) {
if (!value) return;
dests[key] = xref.fetch(value).get('D');
});
}
if (nameTreeRef) {
// reading name tree
var processed = new RefSet();
processed.put(obj);
var queue = [obj];
processed.put(nameTreeRef);
var queue = [nameTreeRef];
while (queue.length > 0) {
var i, n;
obj = xref.fetch(queue.shift());
@ -3538,7 +3572,8 @@ var Catalog = (function() {
}
var names = obj.get('Names');
for (i = 0, n = names.length; i < n; i += 2) {
dests[names[i]] = xref.fetch(names[i + 1]).get('D');
var dest = xref.fetch(names[i + 1]);
dests[names[i]] = IsDict(dest) ? dest.get('D') : dest;
}
}
}
@ -3851,6 +3886,44 @@ var Encodings = {
'ucircumflex', 'udieresis', 'yacute', 'thorn', 'ydieresis'
]);
},
get symbolsEncoding() {
return shadow(this, 'symbolsEncoding',
[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath',
'plus', 'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two',
'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon',
'semicolon', 'less', 'equal', 'greater', 'question', 'congruent',
'Alpha', 'Beta', 'Chi', 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta',
'Iota', 'theta1', 'Kappa', 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi',
'Theta', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'sigma1', 'Omega', 'Xi',
'Psi', 'Zeta', 'bracketleft', 'therefore', 'bracketright',
'perpendicular', 'underscore', 'radicalex', 'alpha', 'beta', 'chi',
'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', 'phi1', 'kappa',
'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', 'sigma', 'tau',
'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', 'braceleft', 'bar',
'braceright', 'similar',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 'Euro',
'Upsilon1', 'minute', 'lessequal', 'fraction', 'infinity', 'florin',
'club', 'diamond', 'heart', 'spade', 'arrowboth', 'arrowleft', 'arrowup',
'arrowright', 'arrowdown', 'degree', 'plusminus', 'second',
'greaterequal', 'multiply', 'proportional', 'partialdiff', 'bullet',
'divide', 'notequal', 'equivalence', 'approxequal', 'ellipsis',
'arrowvertex', 'arrowhorizex', 'carriagereturn', 'aleph', 'Ifraktur',
'Rfraktur', 'weierstrass', 'circlemultiply', 'circleplus', 'emptyset',
'intersection', 'union', 'propersuperset', 'reflexsuperset', 'notsubset',
'propersubset', 'reflexsubset', 'element', 'notelement', 'angle',
'gradient', 'registerserif', 'copyrightserif', 'trademarkserif',
'product', 'radical', 'dotmath', 'logicalnot', 'logicaland', 'logicalor',
'arrowdblboth', 'arrowdblleft', 'arrowdblup', 'arrowdblright',
'arrowdbldown', 'lozenge', 'angleleft', 'registersans', 'copyrightsans',
'trademarksans', 'summation', 'parenlefttp', 'parenleftex',
'parenleftbt', 'bracketlefttp', 'bracketleftex', 'bracketleftbt',
'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', ,'angleright',
'integral', 'integraltp', 'integralex', 'integralbt', 'parenrighttp',
'parenrightex', 'parenrightbt', 'bracketrighttp', 'bracketrightex',
'bracketrightbt', 'bracerighttp', 'bracerightmid', 'bracerightbt'
]);
},
get zapfDingbatsEncoding() {
return shadow(this, 'zapfDingbatsEncoding',
[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
@ -4118,25 +4191,8 @@ var PartialEvaluator = (function() {
fd = fontDict.get('FontDescriptor');
}
if (!fd) {
var baseFontName = fontDict.get('BaseFont');
if (!IsName(baseFontName))
return null;
// Using base font name as a font name.
return {
name: baseFontName.name.replace(/[\+,\-]/g, '_'),
fontDict: fontDict,
properties: {}
};
}
var descriptor = xref.fetch(fd);
var fontName = xref.fetchIfRef(descriptor.get('FontName'));
assertWellFormed(IsName(fontName), 'invalid font name');
fontName = fontName.name.replace(/[\+,\-]/g, '_');
var encodingMap = {};
var glyphMap = {};
var charset = [];
if (compositeFont) {
// Special CIDFont support
@ -4174,128 +4230,163 @@ var PartialEvaluator = (function() {
'9.7.5.3');
}
}
} else if (fontDict.has('Encoding')) {
var encoding = xref.fetchIfRef(fontDict.get('Encoding'));
if (IsDict(encoding)) {
// Build a map of between codes and glyphs
// Load the base encoding
var baseName = encoding.get('BaseEncoding');
if (baseName) {
var base = Encodings[baseName.name];
for (var j = 0, end = base.length; j < end; j++)
encodingMap[j] = GlyphsUnicode[base[j]] || 0;
} else {
TODO('need to load default encoding');
}
// Load the differences between the base and original
var differences = encoding.get('Differences');
var index = 0;
for (var j = 0; j < differences.length; j++) {
var data = differences[j];
if (IsNum(data)) {
index = data;
} else {
encodingMap[index++] = (subType.name == 'TrueType') ? j :
GlyphsUnicode[data.name];
} else {
var baseEncoding = null, diffEncoding = [];
if (fontDict.has('Encoding')) {
var encoding = xref.fetchIfRef(fontDict.get('Encoding'));
if (IsDict(encoding)) {
// Build a map of between codes and glyphs
// Load the base encoding
var baseName = encoding.get('BaseEncoding');
if (baseName) {
baseEncoding = Encodings[baseName.name].slice();
}
}
// Get the font charset if any
var charset = descriptor.get('CharSet');
if (charset) {
assertWellFormed(IsString(charset), 'invalid charset');
charset = charset.split('/');
charset.shift();
}
} else if (IsName(encoding)) {
var encoding = Encodings[encoding.name];
if (!encoding)
error('Unknown font encoding');
var index = 0;
for (var j = 0; j < encoding.length; j++)
encodingMap[index++] = GlyphsUnicode[encoding[j]];
var firstChar = xref.fetchIfRef(fontDict.get('FirstChar'));
var widths = xref.fetchIfRef(fontDict.get('Widths'));
assertWellFormed(IsArray(widths) && IsInt(firstChar),
'invalid font Widths or FirstChar');
for (var j = 0; j < widths.length; j++) {
if (widths[j])
charset.push(encoding[j + firstChar]);
// Load the differences between the base and original
var differences = encoding.get('Differences');
var index = 0;
for (var j = 0; j < differences.length; j++) {
var data = differences[j];
if (IsNum(data)) {
index = data;
} else {
diffEncoding[index++] = data.name;
}
}
} else if (IsName(encoding)) {
baseEncoding = Encodings[encoding.name].slice();
}
}
} else if (fontDict.has('ToUnicode')) {
encodingMap = {empty: true};
var cmapObj = xref.fetchIfRef(fontDict.get('ToUnicode'));
if (IsName(cmapObj)) {
error('ToUnicode file cmap translation not implemented');
} else if (IsStream(cmapObj)) {
var encoding = Encodings['WinAnsiEncoding'];
var firstChar = xref.fetchIfRef(fontDict.get('FirstChar'));
var tokens = [];
var token = '';
if (!baseEncoding) {
var type = subType.name;
if (type == 'TrueType') {
baseEncoding = Encodings.WinAnsiEncoding.slice(0);
} else if (type == 'Type1') {
baseEncoding = Encodings.StandardEncoding.slice(0);
} else {
error('Unknown type of font');
}
}
var cmap = cmapObj.getBytes(cmapObj.length);
for (var i = 0; i < cmap.length; i++) {
var byte = cmap[i];
if (byte == 0x20 || byte == 0x0A || byte == 0x3C || byte == 0x3E) {
switch (token) {
case 'useCMap':
error('useCMap is not implemented');
break;
// merge in the differences
var length = baseEncoding.length > diffEncoding.length ?
baseEncoding.length : diffEncoding.length;
for (var i = 0, ii = length; i < ii; ++i) {
var diffGlyph = diffEncoding[i];
var baseGlyph = baseEncoding[i];
if (diffGlyph) {
glyphMap[i] = diffGlyph;
encodingMap[i] = GlyphsUnicode[diffGlyph];
} else if (baseGlyph) {
glyphMap[i] = baseGlyph;
encodingMap[i] = GlyphsUnicode[baseGlyph];
}
}
case 'beginbfchar':
case 'beginbfrange':
case 'begincodespacerange':
token = '';
tokens = [];
break;
if (fontDict.has('ToUnicode')) {
var cmapObj = xref.fetchIfRef(fontDict.get('ToUnicode'));
if (IsName(cmapObj)) {
error('ToUnicode file cmap translation not implemented');
} else if (IsStream(cmapObj)) {
var firstChar = xref.fetchIfRef(fontDict.get('FirstChar'));
case 'endcodespacerange':
TODO('Support CMap ranges');
break;
var tokens = [];
var token = '';
case 'endbfrange':
for (var j = 0; j < tokens.length; j += 3) {
var startRange = parseInt('0x' + tokens[j]);
var endRange = parseInt('0x' + tokens[j + 1]);
var code = parseInt('0x' + tokens[j + 2]);
var cmap = cmapObj.getBytes(cmapObj.length);
for (var i = 0; i < cmap.length; i++) {
var byte = cmap[i];
if (byte == 0x20 || byte == 0x0A || byte == 0x3C ||
byte == 0x3E) {
switch (token) {
case 'useCMap':
error('useCMap is not implemented');
break;
for (var k = startRange; k <= endRange; k++) {
charset.push(encoding[code++] || '.notdef');
}
case 'beginbfchar':
case 'beginbfrange':
case 'begincodespacerange':
token = '';
tokens = [];
break;
case 'endcodespacerange':
TODO('Support CMap ranges');
break;
case 'endbfrange':
for (var j = 0; j < tokens.length; j += 3) {
var startRange = parseInt('0x' + tokens[j]);
var endRange = parseInt('0x' + tokens[j + 1]);
var code = parseInt('0x' + tokens[j + 2]);
}
break;
case 'endbfchar':
for (var j = 0; j < tokens.length; j += 2) {
var index = parseInt('0x' + tokens[j]);
var code = parseInt('0x' + tokens[j + 1]);
encodingMap[index] = code;
}
break;
default:
if (token.length) {
tokens.push(token);
token = '';
}
break;
}
break;
case 'endbfchar':
for (var j = 0; j < tokens.length; j += 2) {
var index = parseInt('0x' + tokens[j]);
var code = parseInt('0x' + tokens[j + 1]);
encodingMap[index] = GlyphsUnicode[encoding[code]];
charset.push(encoding[code] || '.notdef');
}
break;
default:
if (token.length) {
tokens.push(token);
token = '';
}
break;
} else if (byte == 0x5B || byte == 0x5D) {
error('CMAP list parsing is not implemented');
} else {
token += String.fromCharCode(byte);
}
} else if (byte == 0x5B || byte == 0x5D) {
error('CMAP list parsing is not implemented');
} else {
token += String.fromCharCode(byte);
}
}
}
// firstChar and width are required
// (except for 14 standard fonts)
var firstChar = xref.fetchIfRef(fontDict.get('FirstChar'));
var widths = xref.fetchIfRef(fontDict.get('Widths')) || [];
for (var j = 0; j < widths.length; j++) {
if (widths[j])
charset.push(glyphMap[j + firstChar]);
}
}
if (!fd) {
var baseFontName = fontDict.get('BaseFont');
if (!IsName(baseFontName))
return null;
// Using base font name as a font name.
baseFontName = baseFontName.name.replace(/[\+,\-]/g, '_');
if (/^Symbol(_?(Bold|Italic))*$/.test(baseFontName)) {
// special case for symbols
var encoding = Encodings.symbolsEncoding;
for (var i = 0, n = encoding.length, j; i < n; i++) {
if (!(j = encoding[i]))
continue;
encodingMap[i] = GlyphsUnicode[j] || 0;
}
}
return {
name: baseFontName,
fontDict: fontDict,
properties: {
encoding: encodingMap
}
};
}
var descriptor = xref.fetch(fd);
var fontName = xref.fetchIfRef(descriptor.get('FontName'));
assertWellFormed(IsName(fontName), 'invalid font name');
fontName = fontName.name.replace(/[\+,\-]/g, '_');
var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
if (fontFile) {
fontFile = xref.fetchIfRef(fontFile);
@ -4307,6 +4398,14 @@ var PartialEvaluator = (function() {
}
}
if (descriptor.has('CharSet')) {
// Get the font charset if any (meaningful only in Type 1)
charset = descriptor.get('CharSet');
assertWellFormed(IsString(charset), 'invalid charset');
charset = charset.split('/');
charset.shift();
}
var widths = fontDict.get('Widths');
if (widths) {
var glyphWidths = {};

202
web/images/nav-outline.svg Normal file

@ -0,0 +1,202 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48px"
height="48px"
id="svg3007"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="nav-outline.svg">
<defs
id="defs3009">
<filter
inkscape:collect="always"
id="filter5333"
x="-0.16623206"
width="1.3324641"
y="-0.030014125"
height="1.0600282">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.47888561"
id="feGaussianBlur5335" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.945051"
inkscape:cx="20.614872"
inkscape:cy="23.423899"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1440"
inkscape:window-height="773"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3012">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#f0f0f0;fill-rule:evenodd;stroke:#808080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
id="rect3783"
width="46.16272"
height="45.59861"
x="1.0341953"
y="0.99112236" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect3787"
width="2.8205326"
height="2.7823999"
x="4.2307992"
y="4.093708" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5257"
width="24.68285"
height="1.4102663"
x="8.0855274"
y="4.657815" />
<rect
y="8.4185247"
x="8.4615984"
height="2.7823999"
width="2.8205326"
id="rect5259"
style="fill:#404040;fill-opacity:1;stroke:none" />
<rect
y="9.0766497"
x="12.410344"
height="1.4102663"
width="30.498053"
id="rect5261"
style="fill:#404040;fill-opacity:1;stroke:none" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5263"
width="2.8205326"
height="2.7823999"
x="8.4615984"
y="13.307448" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5265"
width="24.972752"
height="1.4102663"
x="12.410344"
y="13.965573" />
<rect
y="17.444229"
x="4.3248172"
height="2.7823999"
width="2.8205326"
id="rect5267"
style="fill:#404040;fill-opacity:1;stroke:none" />
<rect
y="18.008337"
x="8.1795454"
height="1.4102663"
width="25.101433"
id="rect5269"
style="fill:#404040;fill-opacity:1;stroke:none" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5271"
width="2.8205326"
height="2.7823999"
x="8.5556164"
y="21.769047" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5273"
width="28.782515"
height="1.4102663"
x="12.880433"
y="22.427172" />
<rect
y="26.65797"
x="13.475181"
height="2.7823999"
width="2.8205326"
id="rect5275"
style="fill:#404040;fill-opacity:1;stroke:none" />
<rect
y="27.316095"
x="17.479"
height="1.4102663"
width="23.681646"
id="rect5277"
style="fill:#404040;fill-opacity:1;stroke:none" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5279"
width="2.8205326"
height="2.7823999"
x="8.5130949"
y="31.006269" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5281"
width="24.557148"
height="1.4102663"
x="12.592034"
y="31.636858" />
<rect
y="35.464046"
x="13.475181"
height="2.7823999"
width="2.8205326"
id="rect5283"
style="fill:#404040;fill-opacity:1;stroke:none" />
<rect
y="36.055695"
x="17.744923"
height="1.4102663"
width="18.577394"
id="rect5285"
style="fill:#404040;fill-opacity:1;stroke:none" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5287"
width="2.8205326"
height="2.7823999"
x="13.54166"
y="40.35297" />
<rect
style="fill:#404040;fill-opacity:1;stroke:none"
id="rect5289"
width="23.080858"
height="1.4102663"
x="17.678442"
y="40.944618" />
</g>
</svg>

After

(image error) Size: 5.3 KiB

283
web/images/nav-thumbs.svg Normal file

@ -0,0 +1,283 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48px"
height="48px"
id="svg3007"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="nav-thumbs.svg">
<defs
id="defs3009">
<filter
inkscape:collect="always"
id="filter5333"
x="-0.16623206"
width="1.3324641"
y="-0.030014125"
height="1.0600282">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.47888561"
id="feGaussianBlur5335" />
</filter>
<filter
inkscape:collect="always"
id="filter5966">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.3570515"
id="feGaussianBlur5968" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.945051"
inkscape:cx="9.375932"
inkscape:cy="24.942259"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1440"
inkscape:window-height="773"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3012">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#484848;fill-rule:evenodd;stroke:#808080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
id="rect3783"
width="46.16272"
height="45.59861"
x="1.0341953"
y="0.99112236" />
<rect
y="4.7876148"
x="14.359808"
height="12.764274"
width="9.7061672"
id="rect5960"
style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter5966)"
transform="matrix(1.0465713,0,0,1.0642851,3.6426579,-2.1141417)" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect5958"
width="9.7061672"
height="12.764274"
x="18.897236"
y="3.1920807" />
<rect
transform="matrix(1.0465713,0,0,1.0642851,3.6426579,13.043433)"
style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter5966)"
id="rect5970"
width="9.7061672"
height="12.764274"
x="14.359808"
y="4.7876148" />
<rect
y="18.349655"
x="18.897236"
height="12.764274"
width="9.7061672"
id="rect5972"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<rect
y="4.7876148"
x="14.359808"
height="12.764274"
width="9.7061672"
id="rect5974"
style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter5966)"
transform="matrix(1.0465713,0,0,0.9368834,3.6426579,29.209842)" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect5976"
width="9.7061672"
height="11.833546"
x="18.897236"
y="33.906113" />
<rect
y="4.905829"
x="19.960924"
height="0.66480595"
width="7.7117486"
id="rect5995"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6177"
width="3.6219761"
height="0.66480595"
x="19.960924"
y="6.0340419" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6179"
width="7.7117486"
height="0.66480595"
x="19.960924"
y="7.2562728" />
<rect
y="8.3844862"
x="19.960924"
height="0.66480595"
width="5.6903667"
id="rect6181"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
y="9.7007341"
x="19.960924"
height="0.66480595"
width="7.7117486"
id="rect6183"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6185"
width="7.7117486"
height="0.66480595"
x="19.960924"
y="10.828948" />
<rect
y="12.051179"
x="19.960924"
height="0.66480595"
width="7.7117486"
id="rect6187"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
y="14.213587"
x="23.204536"
height="0.66480595"
width="1.2245234"
id="rect6189"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6209"
width="7.7117486"
height="0.66480595"
x="19.772888"
y="19.854652" />
<rect
y="39.08128"
x="19.913914"
height="0.66480595"
width="3.6219761"
id="rect6211"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
y="22.205095"
x="19.772888"
height="0.66480595"
width="6.6305442"
id="rect6213"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6215"
width="7.7587576"
height="0.66480595"
x="19.866905"
y="37.859051" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6217"
width="7.7117486"
height="0.66480595"
x="19.772888"
y="21.029873" />
<rect
y="25.777771"
x="19.772888"
height="0.66480595"
width="7.7117486"
id="rect6219"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6221"
width="7.7117486"
height="0.66480595"
x="19.772888"
y="27.000002" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6223"
width="1.2245234"
height="0.66480595"
x="23.204536"
y="28.974375" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6225"
width="3.6219761"
height="0.66480595"
x="19.960922"
y="42.983021" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6227"
width="7.7117486"
height="0.66480595"
x="19.913914"
y="36.777847" />
<rect
y="35.602627"
x="19.913914"
height="0.66480595"
width="7.7117486"
id="rect6231"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none"
id="rect6233"
width="7.7117486"
height="0.66480595"
x="19.913914"
y="40.350525" />
<rect
y="41.572754"
x="19.913914"
height="0.66480595"
width="7.7117486"
id="rect6235"
style="fill:#808080;fill-opacity:1;stroke:none" />
<rect
style="fill:#0000e6;fill-opacity:0.44444448;stroke:none"
id="rect6237"
width="3.5256658"
height="1.927364"
x="22.077036"
y="23.367346" />
</g>
</svg>

After

(image error) Size: 7.6 KiB

@ -60,10 +60,10 @@ span#info {
/* === Sidebar === */
#sidebar {
position: fixed;
width: 200px;
width: 350px;
top: 62px;
bottom: 18px;
left: -140px;
left: -290px;
transition: left 0.25s ease-in-out 1s;
-moz-transition: left 0.25s ease-in-out 1s;
-webkit-transition: left 0.25s ease-in-out 1s;
@ -78,7 +78,7 @@ span#info {
#sidebarBox {
background-color: rgba(0, 0, 0, 0.7);
width: 150px;
width: 300px;
height: 100%;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
@ -98,14 +98,73 @@ span#info {
top: 10px;
bottom: 10px;
left: 10px;
width: 130px;
width: 280px;
}
.thumbnail {
width: 104px;
height: 134px;
background-color: white;
margin: 5px;
margin-top: 5px;
margin-bottom: 5px;
margin-left:auto;
margin-right:auto;
}
#outlineScrollView {
position: absolute;
background-color: #fff;
overflow: auto;
top: 10px;
bottom: 10px;
left: 10px;
width: 280px;
}
#outlineView {
padding-top: 4px;
padding-bottom: 100px;
padding-left: 6px;
padding-right: 6px;
font-size: smaller;
}
.outlineItem > .outlineItems {
margin-left: 20px;
}
.outlineItem > a {
text-decoration: none;
color: black;
}
.outlineItem > a:hover {
background: #ff0;
box-shadow: 0px 2px 10px #ff0;
}
#sidebarControls {
position:absolute;
width: 120px;
height: 32px;
left: 15px;
bottom: 35px;
}
#sidebarControls > button {
box-shadow: 0px 4px 10px #000;
-moz-box-shadow: 0px 4px 10px #000;
-webkit-box-shadow: 0px 4px 10px #000;
}
#sidebarControls > button[disabled] > img {
opacity: 0.5;
}
#sidebarControls > button[data-selected] {
box-shadow: 0px 4px 10px #ff0;
-moz-box-shadow: 0px 4px 10px #ff0;
-webkit-box-shadow: 0px 4px 10px #ff0;
}
/* === Content view === */
@ -128,3 +187,10 @@ canvas {
padding: 8px 0px;
}
#sidebarView canvas:hover {
background: #ff0;
box-shadow: 0px 2px 10px #ff0;
-moz-box-shadow: 0px 2px 10px #ff0;
-webkit-box-shadow: 0px 2px 10px #ff0;
}

@ -2,7 +2,7 @@
<html>
<head>
<title>Simple pdf.js page viewer</title>
<link rel="stylesheet" href="viewer.css"></link>
<link rel="stylesheet" href="viewer.css"/>
<script type="text/javascript" src="compatibility.js"></script>
<script type="text/javascript" src="viewer.js"></script>
@ -26,7 +26,7 @@
<div class="separator"></div>
<input type="text" id="pageNumber" onchange="PDFView.page = this.value;" value="1" size="4"></input>
<input type="text" id="pageNumber" onchange="PDFView.page = this.value;" value="1" size="4"/>
<span>/</span>
<span id="numPages">--</span>
@ -38,7 +38,7 @@
<option value="75">75%</option>
<option value="100">100%</option>
<option value="125">125%</option>
<option value="150" selected="selected"><p>150%</p></option>
<option value="150" selected="selected">150%</option>
<option value="200">200%</option>
</select>
@ -51,7 +51,7 @@
<div class="separator"></div>
<input id="fileInput" type="file"></input>
<input id="fileInput" type="file"/>
<div class="separator"></div>
@ -63,6 +63,17 @@
<div id="sidebarScrollView">
<div id="sidebarView"></div>
</div>
<div id="outlineScrollView" style="display:none">
<div id="outlineView"></div>
</div>
<div id="sidebarControls">
<button id="thumbsSwitch" title="Show Thumbnails" onclick="PDFView.switchSidebarView('thumbs')" data-selected>
<img src="images/nav-thumbs.svg" align="top" height="32" alt="Thumbs" />
</button>
<button id="outlineSwitch" title="Show Document Outline" onclick="PDFView.switchSidebarView('outline')" disabled>
<img src="images/nav-outline.svg" align="top" height="32" alt="Document Outline" />
</button>
</div>
</div>
</div>

@ -27,9 +27,12 @@ var PDFView = {
var cssUnits = 96.0 / 72.0;
for (var i = 0; i < pages.length; i++)
pages[i].update(val / 100 * cssUnits);
// Jump the scroll position to the correct page.
document.location.hash = this.page;
if(document.location.hash == '#' + this.page)
this.pages[this.page-1].draw();
else
// Jump the scroll position to the correct page.
document.location.hash = this.page;
var event = document.createEvent("UIEvents");
event.initUIEvent("scalechange", false, false, window, val);
@ -126,6 +129,33 @@ var PDFView = {
this.page = parseInt(document.location.hash.substring(1)) || 1;
this.pagesRefMap = pagesRefMap;
this.destinations = pdf.catalog.destinations;
if (pdf.catalog.documentOutline) {
this.outline = new DocumentOutlineView(pdf.catalog.documentOutline);
var outlineSwitchButton = document.getElementById('outlineSwitch');
outlineSwitchButton.removeAttribute('disabled');
this.switchSidebarView('outline');
}
},
switchSidebarView: function(view) {
var thumbsScrollView = document.getElementById('sidebarScrollView');
var outlineScrollView = document.getElementById('outlineScrollView');
var thumbsSwitchButton = document.getElementById('thumbsSwitch');
var outlineSwitchButton = document.getElementById('outlineSwitch');
switch(view) {
case 'thumbs':
thumbsScrollView.style.display = 'block';
outlineScrollView.style.display = 'none';
thumbsSwitchButton.setAttribute('data-selected', true);
outlineSwitchButton.removeAttribute('data-selected');
break;
case 'outline':
thumbsScrollView.style.display = 'none';
outlineScrollView.style.display = 'block';
thumbsSwitchButton.removeAttribute('data-selected');
outlineSwitchButton.setAttribute('data-selected', true);
break;
}
},
getVisiblePages: function() {
@ -287,6 +317,42 @@ var ThumbnailView = function(container, page) {
};
};
var DocumentOutlineView = function(outline) {
var outlineView = document.getElementById('outlineView');
function bindItemLink(domObj, item) {
domObj.href = '';
domObj.onclick = function(e) {
PDFView.navigateTo(item.dest);
return false;
};
}
var queue = [{parent: outlineView, items: outline}];
while (queue.length > 0) {
var levelData = queue.shift();
var i, n = levelData.items.length;
for (i = 0; i < n; i++) {
var item = levelData.items[i];
var div = document.createElement('div');
div.className = 'outlineItem';
var a = document.createElement('a');
bindItemLink(a, item);
a.textContent = item.title;
div.appendChild(a);
if (item.items.length > 0) {
var itemsDiv = document.createElement('div');
itemsDiv.className = 'outlineItems';
div.appendChild(itemsDiv);
queue.push({parent: itemsDiv, items: item.items});
}
levelData.parent.appendChild(div);
}
}
};
window.addEventListener('load', function(evt) {
var params = document.location.search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {