Merge remote-tracking branch 'mozilla/master' into bidi

Conflicts:
	web/viewer.html
This commit is contained in:
notmasteryet 2012-02-20 12:41:19 -06:00
commit 28b4dac2d8
22 changed files with 1325 additions and 121 deletions

View File

@ -60,7 +60,7 @@ test: shell-test browser-test
production: | bundle
@echo "Preparing web/viewer-production.html"; \
cd web; \
sed '/PDFJSSCRIPT_REMOVE/d' viewer.html > viewer-1.tmp; \
sed '/PDFJSSCRIPT_REMOVE_CORE/d' viewer.html > viewer-1.tmp; \
sed '/PDFJSSCRIPT_INCLUDE_BUILD/ r viewer-snippet.html' viewer-1.tmp > viewer-production.html; \
rm -f *.tmp; \
cd ..
@ -216,6 +216,7 @@ EXTENSION_WEB_FILES = \
web/viewer.js \
web/viewer.html \
web/viewer-production.html \
web/debugger.js \
$(NULL)
FIREFOX_BUILD_DIR := $(BUILD_DIR)/firefox
@ -257,7 +258,7 @@ extension: | production
# Modify the viewer so it does all the extension only stuff.
@cd $(FIREFOX_BUILD_CONTENT)/web; \
sed -i.bak '/PDFJSSCRIPT_INCLUDE_BUNDLE/ r ../build/pdf.js' viewer-snippet-firefox-extension.html; \
sed -i.bak '/PDFJSSCRIPT_REMOVE/d' viewer.html; \
sed -i.bak '/PDFJSSCRIPT_REMOVE_CORE/d' viewer.html; \
sed -i.bak '/PDFJSSCRIPT_REMOVE_FIREFOX_EXTENSION/d' viewer.html; \
sed -i.bak '/PDFJSSCRIPT_INCLUDE_FIREFOX_EXTENSION/ r viewer-snippet-firefox-extension.html' viewer.html; \
rm -f *.bak;

View File

@ -37,8 +37,8 @@ auto-update extensions on a daily basis (you can change this through the
`extensions.update.interval` option in `about:config`).
For an experimental Chrome extension, get the code as explained below and issue `make extension`.
Then open Chrome with the flag `--enable-experimental-extension-apis`, go to `Tools > Extension`
and load the (unpackaged) extension from the directory `extensions/chrome`.
Then open Chrome, go to `Tools > Extension` and load the (unpackaged) extension
from the directory `build/chrome`.
### Getting the code

View File

@ -3,7 +3,7 @@
"version": "0.1",
"description": "Read PDF Document",
"permissions": [
"experimental",
"webRequest", "webRequestBlocking",
"http://*/*.pdf",
"file:///*/*.pdf"
],

View File

@ -1,6 +1,6 @@
<!doctype html>
<script>
chrome.experimental.webRequest.onBeforeRequest.addListener(
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
var viewerPage = 'content/web/viewer.html';
var url = chrome.extension.getURL(viewerPage) + '?file=' + details.url;

View File

@ -17,11 +17,15 @@ var TextRenderingMode = {
ADD_TO_PATH: 7
};
// Minimal font size that would be used during canvas fillText operations.
var MIN_FONT_SIZE = 1;
var CanvasExtraState = (function CanvasExtraStateClosure() {
function CanvasExtraState(old) {
// Are soft masks and alpha values shapes or opacities?
this.alphaIsShape = false;
this.fontSize = 0;
this.fontSizeScale = 1;
this.textMatrix = IDENTITY_MATRIX;
this.fontMatrix = IDENTITY_MATRIX;
this.leading = 0;
@ -265,7 +269,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
},
executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR,
executionStartIdx, continueCallback) {
executionStartIdx, continueCallback,
stepper) {
var argsArray = codeIR.argsArray;
var fnArray = codeIR.fnArray;
var i = executionStartIdx || 0;
@ -284,6 +289,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var slowCommands = this.slowCommands;
while (true) {
if (stepper && i === stepper.nextBreakPoint) {
stepper.breakIt(i, continueCallback);
return i;
}
fnName = fnArray[i];
if (fnName !== 'dependency') {
@ -577,6 +587,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.current.font = fontObj;
this.current.fontSize = size;
if (fontObj.coded)
return; // we don't need ctx.font for Type3 fonts
var name = fontObj.loadedName || 'sans-serif';
var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') :
(fontObj.bold ? 'bold' : 'normal');
@ -584,7 +597,16 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var italic = fontObj.italic ? 'italic' : 'normal';
var serif = fontObj.isSerifFont ? 'serif' : 'sans-serif';
var typeface = '"' + name + '", ' + serif;
var rule = italic + ' ' + bold + ' ' + size + 'px ' + typeface;
// Some font backends cannot handle fonts below certain size.
// Keeping the font at minimal size and using the fontSizeScale to change
// the current transformation matrix before the fillText/strokeText.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=726227
var browserFontSize = size >= MIN_FONT_SIZE ? size : MIN_FONT_SIZE;
this.current.fontSizeScale = browserFontSize != MIN_FONT_SIZE ? 1.0 :
size / MIN_FONT_SIZE;
var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
this.ctx.font = rule;
},
setTextRenderingMode: function canvasGraphicsSetTextRenderingMode(mode) {
@ -647,6 +669,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var font = current.font;
var glyphs = font.charsToGlyphs(str);
var fontSize = current.fontSize;
var fontSizeScale = current.fontSizeScale;
var charSpacing = current.charSpacing;
var wordSpacing = current.wordSpacing;
var textHScale = current.textHScale;
@ -710,11 +733,16 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
else
lineWidth /= scale;
ctx.lineWidth = lineWidth;
if (textSelection)
text.geom = this.getTextGeometry();
if (fontSizeScale != 1.0) {
ctx.scale(fontSizeScale, fontSizeScale);
lineWidth /= fontSizeScale;
}
ctx.lineWidth = lineWidth;
var x = 0;
for (var i = 0; i < glyphsLength; ++i) {
var glyph = glyphs[i];
@ -728,20 +756,21 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var charWidth = glyph.width * fontSize * 0.001 +
Util.sign(current.fontMatrix[0]) * charSpacing;
var scaledX = x / fontSizeScale;
switch (textRenderingMode) {
default: // other unsupported rendering modes
case TextRenderingMode.FILL:
case TextRenderingMode.FILL_ADD_TO_PATH:
ctx.fillText(char, x, 0);
ctx.fillText(char, scaledX, 0);
break;
case TextRenderingMode.STROKE:
case TextRenderingMode.STROKE_ADD_TO_PATH:
ctx.strokeText(char, x, 0);
ctx.strokeText(char, scaledX, 0);
break;
case TextRenderingMode.FILL_STROKE:
case TextRenderingMode.FILL_STROKE_ADD_TO_PATH:
ctx.fillText(char, x, 0);
ctx.strokeText(char, x, 0);
ctx.fillText(char, scaledX, 0);
ctx.strokeText(char, scaledX, 0);
break;
case TextRenderingMode.INVISIBLE:
break;

View File

@ -57,6 +57,7 @@ function getPdf(arg, callback) {
xhr.send(null);
}
globalScope.PDFJS.getPdf = getPdf;
globalScope.PDFJS.pdfBug = false;
var Page = (function PageClosure() {
function Page(xref, pageNumber, pageDict, ref) {
@ -104,25 +105,35 @@ var Page = (function PageClosure() {
return shadow(this, 'mediaBox', obj);
},
get view() {
var obj = this.inheritPageProp('CropBox');
var cropBox = this.inheritPageProp('CropBox');
var view = {
x: 0,
y: 0,
width: this.width,
height: this.height
};
if (!isArray(cropBox) || cropBox.length !== 4)
return shadow(this, 'view', view);
var mediaBox = this.mediaBox;
var offsetX = mediaBox[0], offsetY = mediaBox[1];
if (isArray(obj) && obj.length == 4) {
var tl = this.rotatePoint(obj[0] - offsetX, obj[1] - offsetY);
var br = this.rotatePoint(obj[2] - offsetX, obj[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, 'cropBox', view);
// 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() {
return shadow(this, 'annotations', this.inheritPageProp('Annots'));
@ -244,10 +255,16 @@ var Page = (function PageClosure() {
var startIdx = 0;
var length = this.IRQueue.fnArray.length;
var IRQueue = this.IRQueue;
var stepper = null;
if (PDFJS.pdfBug && StepperManager.enabled) {
stepper = StepperManager.create(this.pageNumber);
stepper.init(IRQueue);
stepper.nextBreakPoint = stepper.getNextBreakPoint();
}
var self = this;
function next() {
startIdx = gfx.executeIRQueue(IRQueue, startIdx, next);
startIdx = gfx.executeIRQueue(IRQueue, startIdx, next, stepper);
if (startIdx == length) {
self.stats.render = Date.now();
gfx.endDrawing();

View File

@ -1565,6 +1565,61 @@ var Font = (function FontClosure() {
}
};
function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart) {
if (sourceEnd - sourceStart <= 12) {
// glyph with data less than 12 is invalid one
return 0;
}
var glyf = source.subarray(sourceStart, sourceEnd);
var contoursCount = (glyf[0] << 8) | glyf[1];
if (contoursCount & 0x8000) {
// complex glyph, writing as is
dest.set(glyf, destStart);
return glyf.length;
}
var j = 10, flagsCount = 0;
for (var i = 0; i < contoursCount; i++) {
var endPoint = (glyf[j] << 8) | glyf[j + 1];
flagsCount = endPoint + 1;
j += 2;
}
// skipping instructions
var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
j += 2 + instructionsLength;
// validating flags
var coordinatesLength = 0;
for (var i = 0; i < flagsCount; i++) {
var flag = glyf[j++];
if (flag & 0xC0) {
// reserved flags must be zero, rejecting
return 0;
}
var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) +
((flag & 4) ? 1 : (flag & 32) ? 0 : 2);
coordinatesLength += xyLength;
if (flag & 8) {
var repeat = glyf[j++];
i += repeat;
coordinatesLength += repeat * xyLength;
}
}
var glyphDataLength = j + coordinatesLength;
if (glyphDataLength > glyf.length) {
// not enough data for coordinates
return 0;
}
if (glyf.length - glyphDataLength > 3) {
// truncating and aligning to 4 bytes the long glyph data
glyphDataLength = (glyphDataLength + 3) & ~3;
dest.set(glyf.subarray(0, glyphDataLength), destStart);
return glyphDataLength;
}
// glyph data is fine
dest.set(glyf, destStart);
return glyf.length;
}
function sanitizeGlyphLocations(loca, glyf, numGlyphs,
isGlyphLocationsLong) {
var itemSize, itemDecode, itemEncode;
@ -1591,21 +1646,21 @@ var Font = (function FontClosure() {
};
}
var locaData = loca.data;
// removing the invalid glyphs
var oldGlyfData = glyf.data;
var newGlyfData = new Uint8Array(oldGlyfData.length);
var startOffset = itemDecode(locaData, 0);
var firstOffset = itemDecode(locaData, itemSize);
if (firstOffset - startOffset < 12 || startOffset > 0) {
// removing first glyph
glyf.data = glyf.data.subarray(firstOffset);
glyf.length -= firstOffset;
itemEncode(locaData, 0, 0);
var i, pos = itemSize;
for (i = 1; i <= numGlyphs; ++i) {
itemEncode(locaData, pos,
itemDecode(locaData, pos) - firstOffset);
pos += itemSize;
}
var writeOffset = 0;
itemEncode(locaData, 0, writeOffset);
for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
var endOffset = itemDecode(locaData, j);
var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
newGlyfData, writeOffset);
writeOffset += newLength;
itemEncode(locaData, j, writeOffset);
startOffset = endOffset;
}
glyf.data = newGlyfData.subarray(0, writeOffset);
}
function readGlyphNameMap(post, properties) {
@ -2195,6 +2250,9 @@ var Font = (function FontClosure() {
var styleSheet = styleElement.sheet;
styleSheet.insertRule(rule, styleSheet.cssRules.length);
if (PDFJS.pdfBug && FontInspector.enabled)
FontInspector.fontAdded(this, url);
return rule;
},

View File

@ -162,6 +162,10 @@ var Parser = (function ParserClosure() {
return imageStream;
},
fetchIfRef: function parserFetchIfRef(obj) {
// not relying on the xref.fetchIfRef -- xref might not be set
return isRef(obj) ? this.xref.fetch(obj) : obj;
},
makeStream: function parserMakeStream(dict, cipherTransform) {
var lexer = this.lexer;
var stream = lexer.stream;
@ -171,10 +175,7 @@ var Parser = (function ParserClosure() {
var pos = stream.pos;
// get length
var length = dict.get('Length');
var xref = this.xref;
if (xref)
length = xref.fetchIfRef(length);
var length = this.fetchIfRef(dict.get('Length'));
if (!isInt(length)) {
error('Bad ' + length + ' attribute in stream');
length = 0;
@ -196,8 +197,8 @@ var Parser = (function ParserClosure() {
return stream;
},
filter: function parserFilter(stream, dict, length) {
var filter = dict.get('Filter', 'F');
var params = dict.get('DecodeParms', 'DP');
var filter = this.fetchIfRef(dict.get('Filter', 'F'));
var params = this.fetchIfRef(dict.get('DecodeParms', 'DP'));
if (isName(filter))
return this.makeFilter(stream, filter.name, length, params);
if (isArray(filter)) {

View File

@ -623,7 +623,6 @@ var PredictorStream = (function PredictorStreamClosure() {
var bufferLength = this.bufferLength;
var buffer = this.ensureBuffer(bufferLength + rowBytes);
var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
var bits = this.bits;
var colors = this.colors;
@ -632,6 +631,7 @@ var PredictorStream = (function PredictorStreamClosure() {
var inbuf = 0, outbuf = 0;
var inbits = 0, outbits = 0;
var pos = bufferLength;
if (bits === 1) {
for (var i = 0; i < rowBytes; ++i) {
@ -639,19 +639,21 @@ var PredictorStream = (function PredictorStreamClosure() {
inbuf = (inbuf << 8) | c;
// bitwise addition is exclusive or
// first shift inbuf and then add
currentRow[i] = (c ^ (inbuf >> colors)) & 0xFF;
buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF;
// truncate inbuf (assumes colors < 16)
inbuf &= 0xFFFF;
}
} else if (bits === 8) {
for (var i = 0; i < colors; ++i)
currentRow[i] = rawBytes[i];
for (; i < rowBytes; ++i)
currentRow[i] = currentRow[i - colors] + rawBytes[i];
buffer[pos++] = rawBytes[i];
for (; i < rowBytes; ++i) {
buffer[pos] = buffer[pos - colors] + rawBytes[i];
pos++;
}
} else {
var compArray = new Uint8Array(colors + 1);
var bitMask = (1 << bits) - 1;
var j = 0, k = 0;
var j = 0, k = bufferLength;
var columns = this.columns;
for (var i = 0; i < columns; ++i) {
for (var kk = 0; kk < colors; ++kk) {
@ -665,13 +667,13 @@ var PredictorStream = (function PredictorStreamClosure() {
outbuf = (outbuf << bits) | compArray[kk];
outbits += bits;
if (outbits >= 8) {
currentRow[k++] = (outbuf >> (outbits - 8)) & 0xFF;
buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF;
outbits -= 8;
}
}
}
if (outbits > 0) {
currentRow[k++] = (outbuf << (8 - outbits)) +
buffer[k++] = (outbuf << (8 - outbits)) +
(inbuf & ((1 << (8 - outbits)) - 1));
}
}
@ -690,32 +692,35 @@ var PredictorStream = (function PredictorStreamClosure() {
var bufferLength = this.bufferLength;
var buffer = this.ensureBuffer(bufferLength + rowBytes);
var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
if (prevRow.length == 0)
prevRow = new Uint8Array(rowBytes);
var j = bufferLength;
switch (predictor) {
case 0:
for (var i = 0; i < rowBytes; ++i)
currentRow[i] = rawBytes[i];
buffer[j++] = rawBytes[i];
break;
case 1:
for (var i = 0; i < pixBytes; ++i)
currentRow[i] = rawBytes[i];
for (; i < rowBytes; ++i)
currentRow[i] = (currentRow[i - pixBytes] + rawBytes[i]) & 0xFF;
buffer[j++] = rawBytes[i];
for (; i < rowBytes; ++i) {
buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF;
j++;
}
break;
case 2:
for (var i = 0; i < rowBytes; ++i)
currentRow[i] = (prevRow[i] + rawBytes[i]) & 0xFF;
buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
break;
case 3:
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) {
currentRow[i] = (((prevRow[i] + currentRow[i - pixBytes]) >> 1) +
buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) +
rawBytes[i]) & 0xFF;
j++;
}
break;
case 4:
@ -724,12 +729,12 @@ var PredictorStream = (function PredictorStreamClosure() {
for (var i = 0; i < pixBytes; ++i) {
var up = prevRow[i];
var c = rawBytes[i];
currentRow[i] = up + c;
buffer[j++] = up + c;
}
for (; i < rowBytes; ++i) {
var up = prevRow[i];
var upLeft = prevRow[i - pixBytes];
var left = currentRow[i - pixBytes];
var left = buffer[j - pixBytes];
var p = left + up - upLeft;
var pa = p - left;
@ -744,11 +749,11 @@ var PredictorStream = (function PredictorStreamClosure() {
var c = rawBytes[i];
if (pa <= pb && pa <= pc)
currentRow[i] = left + c;
buffer[j++] = left + c;
else if (pb <= pc)
currentRow[i] = up + c;
buffer[j++] = up + c;
else
currentRow[i] = upLeft + c;
buffer[j++] = upLeft + c;
}
break;
default:

View File

@ -111,6 +111,62 @@ var Util = (function UtilClosure() {
];
}
// 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 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 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 sign(num) {
return num < 0 ? -1 : 1;
};

View File

@ -0,0 +1 @@
http://hsivonen.iki.fi/thesis/html5-conformance-checker.pdf

View File

@ -0,0 +1 @@
http://www.madbad.altervista.org/_altervista_ht/2142.pdf

View File

@ -0,0 +1 @@
http://www.cs.txstate.edu/~mb92/papers/gpgpu11.pdf

View File

@ -14,7 +14,7 @@
<Description>
<em:id>toolkit@mozilla.org</em:id>
<em:minVersion>3.0</em:minVersion>
<em:maxVersion>7.0a1</em:maxVersion>
<em:maxVersion>13.0a1</em:maxVersion>
</Description>
</em:targetApplication>

View File

@ -64,7 +64,9 @@ MIMEs = {
'.svg': 'image/svg+xml',
'.pdf': 'application/pdf',
'.xhtml': 'application/xhtml+xml',
'.gif': 'image/gif',
'.ico': 'image/x-icon',
'.png': 'image/png',
'.log': 'text/plain'
}

View File

@ -438,6 +438,13 @@
"link": true,
"type": "eq"
},
{ "id": "issue1169",
"file": "pdfs/issue1169.pdf",
"md5": "3df3ed21fd43ac7fdb21e2015c8a7809",
"rounds": 1,
"link": true,
"type": "eq"
},
{ "id": "zerowidthline",
"file": "pdfs/zerowidthline.pdf",
"md5": "295d26e61a85635433f8e4b768953f60",
@ -445,6 +452,14 @@
"link": false,
"type": "eq"
},
{ "id": "html5checker",
"file": "pdfs/html5checker.pdf",
"md5": "74bbd80d1e7eb5f2951582233ef9ebab",
"rounds": 1,
"pageLimit": 7,
"link": true,
"type": "eq"
},
{ "id": "issue1133",
"file": "pdfs/issue1133.pdf",
"md5": "d1b61580cb100e3df93d33703af1773a",
@ -458,5 +473,12 @@
"rounds": 1,
"link": true,
"type": "eq"
},
{ "id": "issue1155",
"file": "pdfs/issue1155.pdf",
"md5": "b732ef25c16c9c20a77e40edef5aa6fe",
"rounds": 1,
"link": true,
"type": "eq"
}
]

396
web/debugger.js Normal file
View File

@ -0,0 +1,396 @@
/* -*- 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 FontInspector = (function FontInspectorClosure() {
var fonts;
var panelWidth = 300;
var active = false;
var fontAttribute = 'data-font-name';
function removeSelection() {
var divs = document.querySelectorAll('div[' + fontAttribute + ']');
for (var i = 0, ii = divs.length; i < ii; ++i) {
var div = divs[i];
div.className = '';
}
}
function resetSelection() {
var divs = document.querySelectorAll('div[' + fontAttribute + ']');
for (var i = 0, ii = divs.length; i < ii; ++i) {
var div = divs[i];
div.className = 'debuggerHideText';
}
}
function selectFont(fontName, show) {
var divs = document.querySelectorAll('div[' + fontAttribute + '=' +
fontName + ']');
for (var i = 0, ii = divs.length; i < ii; ++i) {
var div = divs[i];
div.className = show ? 'debuggerShowText' : 'debuggerHideText';
}
}
function textLayerClick(e) {
if (!e.target.dataset.fontName || e.target.tagName != 'DIV')
return;
var fontName = e.target.dataset.fontName;
var selects = document.getElementsByTagName('input');
for (var i = 0; i < selects.length; ++i) {
var select = selects[i];
if (select.dataset.fontName != fontName) continue;
select.checked = !select.checked;
selectFont(fontName, select.checked);
select.scrollIntoView();
}
}
return {
// Poperties/functions needed by PDFBug.
id: 'FontInspector',
name: 'Font Inspector',
panel: null,
manager: null,
init: function init() {
var panel = this.panel;
panel.setAttribute('style', 'padding: 5px;');
var tmp = document.createElement('button');
tmp.addEventListener('click', resetSelection);
tmp.textContent = 'Refresh';
panel.appendChild(tmp);
fonts = document.createElement('div');
panel.appendChild(fonts);
},
enabled: false,
get active() {
return active;
},
set active(value) {
active = value;
if (active) {
document.body.addEventListener('click', textLayerClick, true);
resetSelection();
} else {
document.body.removeEventListener('click', textLayerClick, true);
removeSelection();
}
},
// FontInspector specific functions.
fontAdded: function fontAdded(fontObj, url) {
function properties(obj, list) {
var moreInfo = document.createElement('table');
for (var i = 0; i < list.length; i++) {
var tr = document.createElement('tr');
var td1 = document.createElement('td');
td1.textContent = list[i];
tr.appendChild(td1);
var td2 = document.createElement('td');
td2.textContent = obj[list[i]].toString();
tr.appendChild(td2);
moreInfo.appendChild(tr);
}
return moreInfo;
}
var moreInfo = properties(fontObj, ['name', 'type']);
var m = /url\(['"]?([^\)"']+)/.exec(url);
var fontName = fontObj.loadedName;
var font = document.createElement('div');
var name = document.createElement('span');
name.textContent = fontName;
var download = document.createElement('a');
download.href = m[1];
download.textContent = 'Download';
var logIt = document.createElement('a');
logIt.href = '';
logIt.textContent = 'Log';
logIt.addEventListener('click', function(event) {
event.preventDefault();
console.log(fontObj);
});
var select = document.createElement('input');
select.setAttribute('type', 'checkbox');
select.dataset.fontName = fontName;
select.addEventListener('click', (function(select, fontName) {
return (function() {
selectFont(fontName, select.checked);
});
})(select, fontName));
font.appendChild(select);
font.appendChild(name);
font.appendChild(document.createTextNode(' '));
font.appendChild(download);
font.appendChild(document.createTextNode(' '));
font.appendChild(logIt);
font.appendChild(moreInfo);
fonts.appendChild(font);
// Somewhat of a hack, should probably add a hook for when the text layer
// is done rendering.
setTimeout(function() {
if (this.active)
resetSelection();
}.bind(this), 2000);
}
};
})();
// Manages all the page steppers.
var StepperManager = (function StepperManagerClosure() {
var steppers = [];
var stepperDiv = null;
var stepperControls = null;
var stepperChooser = null;
var breakPoints = {};
return {
// Poperties/functions needed by PDFBug.
id: 'Stepper',
name: 'Stepper',
panel: null,
manager: null,
init: function init() {
var self = this;
this.panel.setAttribute('style', 'padding: 5px;');
stepperControls = document.createElement('div');
stepperChooser = document.createElement('select');
stepperChooser.addEventListener('change', function(event) {
self.selectStepper(this.value);
});
stepperControls.appendChild(stepperChooser);
stepperDiv = document.createElement('div');
this.panel.appendChild(stepperControls);
this.panel.appendChild(stepperDiv);
if (sessionStorage.getItem('pdfjsBreakPoints'))
breakPoints = JSON.parse(sessionStorage.getItem('pdfjsBreakPoints'));
},
enabled: false,
active: false,
// Stepper specific functions.
create: function create(pageNumber) {
var debug = document.createElement('div');
debug.id = 'stepper' + pageNumber;
debug.setAttribute('hidden', true);
debug.className = 'stepper';
stepperDiv.appendChild(debug);
var b = document.createElement('option');
b.textContent = 'Page ' + (pageNumber + 1);
b.value = pageNumber;
stepperChooser.appendChild(b);
var initBreakPoints = breakPoints[pageNumber] || [];
var stepper = new Stepper(debug, pageNumber, initBreakPoints);
steppers.push(stepper);
if (steppers.length === 1)
this.selectStepper(pageNumber, false);
return stepper;
},
selectStepper: function selectStepper(pageNumber, selectPanel) {
if (selectPanel)
this.manager.selectPanel(1);
for (var i = 0; i < steppers.length; ++i) {
var stepper = steppers[i];
if (stepper.pageNumber == pageNumber)
stepper.panel.removeAttribute('hidden');
else
stepper.panel.setAttribute('hidden', true);
}
},
saveBreakPoints: function saveBreakPoints(pageNumber, bps) {
breakPoints[pageNumber] = bps;
sessionStorage.setItem('pdfjsBreakPoints', JSON.stringify(breakPoints));
}
};
})();
// The stepper for each page's IRQueue.
var Stepper = (function StepperClosure() {
function Stepper(panel, pageNumber, initialBreakPoints) {
this.panel = panel;
this.len;
this.breakPoint = 0;
this.nextBreakPoint = null;
this.pageNumber = pageNumber;
this.breakPoints = initialBreakPoints;
this.currentIdx = -1;
}
Stepper.prototype = {
init: function init(IRQueue) {
// Shorter way to create element and optionally set textContent.
function c(tag, textContent) {
var d = document.createElement(tag);
if (textContent)
d.textContent = textContent;
return d;
}
var panel = this.panel;
this.len = IRQueue.fnArray.length;
var content = c('div', 'c=continue, s=step');
var table = c('table');
content.appendChild(table);
table.cellSpacing = 0;
var headerRow = c('tr');
table.appendChild(headerRow);
headerRow.appendChild(c('th', 'Break'));
headerRow.appendChild(c('th', 'Idx'));
headerRow.appendChild(c('th', 'fn'));
headerRow.appendChild(c('th', 'args'));
for (var i = 0; i < IRQueue.fnArray.length; i++) {
var line = c('tr');
line.className = 'line';
line.id = 'idx' + i;
table.appendChild(line);
var checked = this.breakPoints.indexOf(i) != -1;
var args = IRQueue.argsArray[i] ? IRQueue.argsArray[i] : [];
var breakCell = c('td');
var cbox = c('input');
cbox.type = 'checkbox';
cbox.className = 'points';
cbox.checked = checked;
var self = this;
cbox.onclick = (function(x) {
return function() {
if (this.checked)
self.breakPoints.push(x);
else
self.breakPoints.splice(self.breakPoints.indexOf(x), 1);
StepperManager.saveBreakPoints(self.pageNumber, self.breakPoints);
}
})(i);
breakCell.appendChild(cbox);
line.appendChild(breakCell);
line.appendChild(c('td', i.toString()));
line.appendChild(c('td', IRQueue.fnArray[i]));
line.appendChild(c('td', args.join(', ')));
}
panel.appendChild(content);
var self = this;
},
getNextBreakPoint: function getNextBreakPoint() {
this.breakPoints.sort(function(a, b) { return a - b; });
for (var i = 0; i < this.breakPoints.length; i++) {
if (this.breakPoints[i] > this.currentIdx)
return this.breakPoints[i];
}
return null;
},
breakIt: function breakIt(idx, callback) {
StepperManager.selectStepper(this.pageNumber, true);
var self = this;
var dom = document;
self.currentIdx = idx;
var listener = function(e) {
switch (e.keyCode) {
case 83: // step
dom.removeEventListener('keydown', listener, false);
self.nextBreakPoint = self.currentIdx + 1;
self.goTo(-1);
callback();
break;
case 67: // continue
dom.removeEventListener('keydown', listener, false);
var breakPoint = self.getNextBreakPoint();
self.nextBreakPoint = breakPoint;
self.goTo(-1);
callback();
break;
}
}
dom.addEventListener('keydown', listener, false);
self.goTo(idx);
},
goTo: function goTo(idx) {
var allRows = this.panel.getElementsByClassName('line');
for (var x = 0; x < allRows.length; x++) {
allRows[x].style.backgroundColor = null;
}
var row = document.getElementById('idx' + idx);
if (row) {
row.style.backgroundColor = 'rgb(251,250,207)';
row.scrollIntoView();
}
}
};
return Stepper;
})();
// Manages all the debugging tools.
var PDFBug = (function PDFBugClosure() {
var panelWidth = 300;
var buttons = [];
var activePanel = null;
return {
tools: [
FontInspector,
StepperManager
],
init: function init() {
/*
* Basic Layout:
* PDFBug
* Controls
* Panels
* Panel
* Panel
* ...
*/
var ui = document.createElement('div');
ui.id = 'PDFBug';
var controls = document.createElement('div');
controls.setAttribute('class', 'controls');
ui.appendChild(controls);
var panels = document.createElement('div');
panels.setAttribute('class', 'panels');
ui.appendChild(panels);
document.body.appendChild(ui);
document.body.style.paddingRight = panelWidth + 'px';
// Initialize all the debugging tools.
var tools = this.tools;
for (var i = 0; i < tools.length; ++i) {
var tool = tools[i];
var panel = document.createElement('div');
var panelButton = document.createElement('button');
panelButton.textContent = tool.name;
var self = this;
panelButton.addEventListener('click', (function(selected) {
return function(event) {
event.preventDefault();
self.selectPanel(selected);
};
})(i));
controls.appendChild(panelButton);
panels.appendChild(panel);
tool.panel = panel;
tool.manager = this;
if (tool.enabled)
tool.init();
else
panel.textContent = tool.name + ' is disabled. To enable add ' +
' "' + tool.id + '" to the pdfBug parameter ' +
'and refresh (seperate multiple by commas).';
buttons.push(panelButton);
}
this.selectPanel(0);
},
selectPanel: function selectPanel(index) {
if (index === activePanel)
return;
activePanel = index;
var tools = this.tools;
for (var j = 0; j < tools.length; ++j) {
if (j == index) {
buttons[j].setAttribute('class', 'active');
tools[j].active = true;
tools[j].panel.removeAttribute('hidden');
} else {
buttons[j].setAttribute('class', '');
tools[j].active = false;
tools[j].panel.setAttribute('hidden', 'true');
}
}
}
};
})();

297
web/images/pin-down.svg Normal file
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

230
web/images/pin-up.svg Normal file
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

View File

@ -89,7 +89,8 @@ span#info {
z-index: 1;
}
#sidebar:hover {
#sidebar:hover,
#sidebar.pinned {
left: 0px;
transition: left 0.25s ease-in-out 0s;
-o-transition: left 0.25s ease-in-out 0s;
@ -97,6 +98,26 @@ span#info {
-webkit-transition: left 0.25s ease-in-out 0s;
}
#pinIcon {
position: absolute;
top: 4px;
right: 55px;
width: 15px;
height: 15px;
background: center no-repeat;
background-image: url('images/pin-up.svg');
background-size: 15px 15px;
}
#pinIcon:hover {
background-color: rgba(255,255,255,0.35);
}
#sidebar.pinned #pinIcon {
background-image: url('images/pin-down.svg');
background-size: 15px 15px;
}
#sidebarBox {
background-color: rgba(0, 0, 0, 0.7);
width: 300px;
@ -116,7 +137,7 @@ span#info {
position: absolute;
overflow: hidden;
overflow-y: auto;
top: 10px;
top: 20px;
bottom: 10px;
left: 10px;
width: 280px;
@ -147,7 +168,7 @@ span#info {
position: absolute;
background-color: #fff;
overflow: auto;
top: 10px;
top: 20px;
bottom: 10px;
left: 10px;
width: 280px;
@ -381,6 +402,43 @@ canvas {
}
#loading {
margin: 100px 0;
text-align: center;
margin: 100px 0;
text-align: center;
}
#PDFBug {
font-size: 10px;
position: fixed;
top: 35px;
bottom: 5px;
right: 2px;
width: 300px;
background: white;
border: 1px solid #666;
padding: 0;
}
#PDFBug .controls {
border-bottom: 1px solid #666;
padding: 3px;
background: -moz-linear-gradient(center bottom, #eee 0%, #fff 100%);
}
#PDFBug .panels {
overflow: auto;
position: absolute;
top: 27px;
left: 0;
right: 0;
bottom: 0;
}
#PDFBug button.active {
font-weight: bold;
}
.debuggerShowText {
background: yellow;
color: blue;
opacity: 0.3;
}
.debuggerHideText:hover {
background: yellow;
opacity: 0.3;
}

View File

@ -9,30 +9,32 @@
<script type="text/javascript" src="compatibility.js"></script> <!-- PDFJSSCRIPT_REMOVE_FIREFOX_EXTENSION -->
<!-- PDFJSSCRIPT_INCLUDE_BUILD -->
<script type="text/javascript" src="../src/core.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/util.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/canvas.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/obj.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/function.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/charsets.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/cidmaps.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/colorspace.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/crypto.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/evaluator.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/fonts.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/glyphlist.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/image.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/metrics.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/parser.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/pattern.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/stream.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/jpx.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/bidi.js"></script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE -->
<script type="text/javascript" src="../src/core.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/util.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/canvas.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/obj.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/function.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/charsets.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/cidmaps.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/colorspace.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/crypto.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/evaluator.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/fonts.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/glyphlist.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/image.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/metrics.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/parser.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/pattern.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/stream.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/worker.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../external/jpgjs/jpg.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/jpx.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="../src/bidi.js"></script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript">PDFJS.workerSrc = '../src/worker_loader.js';</script> <!-- PDFJSSCRIPT_REMOVE_CORE -->
<script type="text/javascript" src="debugger.js"></script>
<script type="text/javascript" src="viewer.js"></script>
</head>
<body>
@ -123,6 +125,7 @@
<div id="sidebar">
<div id="sidebarBox">
<div id="pinIcon" onClick="PDFView.pinSidebar()"></div>
<div id="sidebarScrollView">
<div id="sidebarView"></div>
</div>
@ -137,7 +140,7 @@
<img src="images/nav-outline.svg" align="top" height="16" alt="Document Outline" />
</button>
</div>
</div>
</div>
</div>
<div id="loading">Loading... 0%</div>

View File

@ -37,10 +37,6 @@ var RenderingQueue = (function RenderingQueueClosure() {
if (!item.drawingRequired())
return; // as no redraw required, no need for queueing.
if ('rendering' in item)
return; // is already in the queue
item.rendering = true;
this.items.push(item);
if (this.items.length > 1)
return; // not first item
@ -49,7 +45,6 @@ var RenderingQueue = (function RenderingQueueClosure() {
},
continueExecution: function RenderingQueueContinueExecution() {
var item = this.items.shift();
delete item.rendering;
if (this.items.length == 0)
return; // queue is empty
@ -325,7 +320,8 @@ var PDFView = {
if (pageNumber) {
var pdfOpenParams = PDFView.getAnchorUrl('#page=' + pageNumber);
var destKind = dest[1];
if ('name' in destKind && destKind.name == 'XYZ') {
if (typeof destKind === 'object' && 'name' in destKind &&
destKind.name == 'XYZ') {
var scale = (dest[4] || this.currentScale);
pdfOpenParams += '&zoom=' + (scale * 100);
if (dest[2] || dest[3]) {
@ -509,13 +505,7 @@ var PDFView = {
return;
if (hash.indexOf('=') >= 0) {
// parsing query string
var paramsPairs = hash.split('&');
var params = {};
for (var i = 0; i < paramsPairs.length; ++i) {
var paramPair = paramsPairs[i].split('=');
params[paramPair[0]] = paramPair[1];
}
var params = PDFView.parseQueryString(hash);
// borrowing syntax from "Parameters for Opening PDF Files"
if ('nameddest' in params) {
PDFView.navigateTo(params.nameddest);
@ -571,6 +561,10 @@ var PDFView = {
}
},
pinSidebar: function pdfViewPinSidebar() {
document.getElementById('sidebar').classList.toggle('pinned');
},
getVisiblePages: function pdfViewGetVisiblePages() {
var pages = this.pages;
var kBottomMargin = 10;
@ -623,6 +617,19 @@ var PDFView = {
}
return visibleThumbs;
},
// Helper function to parse query string (e.g. ?param1=value&parm2=...).
parseQueryString: function pdfViewParseQueryString(query) {
var parts = query.split('&');
var params = {};
for (var i = 0, ii = parts.length; i < parts.length; ++i) {
var param = parts[i].split('=');
var key = param[0];
var value = param.length > 1 ? param[1] : null;
params[unescape(key)] = unescape(value);
}
return params;
}
};
@ -865,7 +872,10 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
var self = this;
stats.begin = Date.now();
this.content.startRendering(ctx, function pageViewDrawCallback(error) {
div.removeChild(self.loadingIconDiv);
if (self.loadingIconDiv) {
div.removeChild(self.loadingIconDiv);
delete self.loadingIconDiv;
}
if (error)
PDFView.error('An error occurred while rendering the page.', error);
@ -965,7 +975,7 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) {
};
this.setImage = function thumbnailViewSetImage(img) {
if (this.hasImage)
if (this.hasImage || !img)
return;
var ctx = getPageDrawContext();
@ -1082,6 +1092,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
// vScale and hScale already contain the scaling to pixel units
var fontHeight = fontSize * text.geom.vScale;
textDiv.dataset.canvasWidth = text.canvasWidth * text.geom.hScale;
textDiv.dataset.fontName = fontName;
textDiv.style.fontSize = fontHeight + 'px';
textDiv.style.left = text.geom.x + 'px';
@ -1094,16 +1105,11 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
};
window.addEventListener('load', function webViewerLoad(evt) {
var params = document.location.search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
var param = params[i].split('=');
params[unescape(param[0])] = unescape(param[1]);
}
var params = PDFView.parseQueryString(document.location.search.substring(1));
var scale = ('scale' in params) ? params.scale : 0;
var file = PDFJS.isFirefoxExtension ?
window.location.toString() : params.file || kDefaultURL;
PDFView.open(file, parseFloat(scale));
PDFView.open(file, 0);
if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader ||
!window.FileList || !window.Blob) {
@ -1114,11 +1120,32 @@ window.addEventListener('load', function webViewerLoad(evt) {
document.getElementById('fileInput').value = null;
}
if ('disableWorker' in params)
PDFJS.disableWorker = (params['disableWorker'] === 'true');
// Special debugging flags in the hash section of the URL.
var hash = document.location.hash.substring(1);
var hashParams = PDFView.parseQueryString(hash);
if ('disableTextLayer' in params)
PDFJS.disableTextLayer = (params['disableTextLayer'] === 'true');
if ('disableWorker' in hashParams)
PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
if ('disableTextLayer' in hashParams)
PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
if ('pdfBug' in hashParams) {
PDFJS.pdfBug = true;
var pdfBug = hashParams['pdfBug'];
var all = false, enabled = [];
if (pdfBug === 'all')
all = true;
else
enabled = pdfBug.split(',');
var debugTools = PDFBug.tools;
for (var i = 0; i < debugTools.length; ++i) {
var tool = debugTools[i];
if (all || enabled.indexOf(tool.id) !== -1)
tool.enabled = true;
}
PDFBug.init();
}
var sidebarScrollView = document.getElementById('sidebarScrollView');
sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true);
@ -1205,7 +1232,6 @@ window.addEventListener('scroll', function webViewerScroll(evt) {
updateViewarea();
}, true);
var thumbnailTimer;
function updateThumbViewArea() {