Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Xavier Fung 2012-09-13 10:13:40 +08:00
commit 78d861b2cb
10 changed files with 174 additions and 82 deletions

49
make.js Executable file → Normal file
View File

@ -104,12 +104,19 @@ target.generic = function() {
target.web = function() { target.web = function() {
target.generic(); target.generic();
target.extension(); target.extension();
target.pagesrepo();
cd(ROOT_DIR);
echo(); echo();
echo('### Creating web site'); echo('### Creating web site');
if (test('-d', GH_PAGES_DIR))
rm('-rf', GH_PAGES_DIR);
mkdir('-p', GH_PAGES_DIR + '/web');
mkdir('-p', GH_PAGES_DIR + '/web/images');
mkdir('-p', GH_PAGES_DIR + BUILD_DIR);
mkdir('-p', GH_PAGES_DIR + EXTENSION_SRC_DIR + '/firefox');
mkdir('-p', GH_PAGES_DIR + EXTENSION_SRC_DIR + '/chrome');
cp('-R', GENERIC_DIR + '/*', GH_PAGES_DIR); cp('-R', GENERIC_DIR + '/*', GH_PAGES_DIR);
cp(FIREFOX_BUILD_DIR + '/*.xpi', FIREFOX_BUILD_DIR + '/*.rdf', cp(FIREFOX_BUILD_DIR + '/*.xpi', FIREFOX_BUILD_DIR + '/*.rdf',
GH_PAGES_DIR + EXTENSION_SRC_DIR + 'firefox/'); GH_PAGES_DIR + EXTENSION_SRC_DIR + 'firefox/');
@ -118,12 +125,14 @@ target.web = function() {
cp('web/index.html.template', GH_PAGES_DIR + '/index.html'); cp('web/index.html.template', GH_PAGES_DIR + '/index.html');
cd(GH_PAGES_DIR); cd(GH_PAGES_DIR);
exec('git init');
exec('git remote add origin ' + REPO);
exec('git add -A'); exec('git add -A');
exec('git commit -am "gh-pages site created via make.js script"');
exec('git branch -m gh-pages');
echo(); echo();
echo('Website built in ' + GH_PAGES_DIR); echo('Website built in ' + GH_PAGES_DIR);
echo('Don\'t forget to cd into ' + GH_PAGES_DIR +
' and issue \'git commit\' to push changes.');
}; };
// //
@ -245,38 +254,6 @@ target.bundle = function() {
}; };
//
// make pagesrepo
//
// This target clones the gh-pages repo into the build directory. It deletes
// the current contents of the repo, since we overwrite everything with data
// from the master repo. The 'make web' target then uses 'git add -A' to track
// additions, modifications, moves, and deletions.
target.pagesrepo = function() {
cd(ROOT_DIR);
echo();
echo('### Creating fresh clone of gh-pages');
if (!test('-d', BUILD_DIR))
mkdir(BUILD_DIR);
if (!test('-d', GH_PAGES_DIR)) {
echo();
echo('Cloning project repo...');
echo('(This operation can take a while, depending on network conditions)');
exec('git clone -b gh-pages --depth=1 ' + REPO + ' ' + GH_PAGES_DIR,
{silent: true});
echo('Done.');
}
rm('-rf', GH_PAGES_DIR + '/*');
mkdir('-p', GH_PAGES_DIR + '/web');
mkdir('-p', GH_PAGES_DIR + '/web/images');
mkdir('-p', GH_PAGES_DIR + BUILD_DIR);
mkdir('-p', GH_PAGES_DIR + EXTENSION_SRC_DIR + '/firefox');
mkdir('-p', GH_PAGES_DIR + EXTENSION_SRC_DIR + '/chrome');
};
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// //

View File

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

View File

@ -171,31 +171,30 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
++self.objIdCounter; ++self.objIdCounter;
if (!font.loadedName) { if (!font.loadedName) {
font.translated = self.translateFont(font, xref, resources, var translated = self.translateFont(font, xref, resources,
dependency); dependency);
if (font.translated) { if (translated) {
// keep track of each font we translated so the caller can // keep track of each font we translated so the caller can
// load them asynchronously before calling display on a page // load them asynchronously before calling display on a page
loadedName = 'font_' + uniquePrefix + self.objIdCounter; loadedName = 'font_' + uniquePrefix + self.objIdCounter;
font.translated.properties.loadedName = loadedName; translated.properties.loadedName = loadedName;
font.loadedName = loadedName; font.loadedName = loadedName;
font.translated = translated;
var translated = font.translated; var data;
// Convert the file to an ArrayBuffer which will be turned back into try {
// a Stream in the main thread. var fontObj = new Font(translated.name,
if (translated.file) translated.file,
translated.file = translated.file.getBytes(); translated.properties);
if (translated.properties.file) { data = fontObj.export();
translated.properties.file = } catch (e) {
translated.properties.file.getBytes(); data = { error: e };
} }
handler.send('obj', [ handler.send('obj', [
loadedName, loadedName,
'Font', 'Font',
translated.name, data
translated.file,
translated.properties
]); ]);
} }
} }

View File

@ -1526,6 +1526,15 @@ function fontCharsToUnicode(charCodes, fontProperties) {
*/ */
var Font = (function FontClosure() { var Font = (function FontClosure() {
function Font(name, file, properties) { function Font(name, file, properties) {
if (arguments.length === 1) {
// importing translated data
var data = arguments[0];
for (var i in data) {
this[i] = data[i];
}
return;
}
this.name = name; this.name = name;
this.coded = properties.coded; this.coded = properties.coded;
this.charProcOperatorList = properties.charProcOperatorList; this.charProcOperatorList = properties.charProcOperatorList;
@ -2036,6 +2045,15 @@ var Font = (function FontClosure() {
mimetype: null, mimetype: null,
encoding: null, encoding: null,
export: function Font_export() {
var data = {};
for (var i in this) {
if (this.hasOwnProperty(i))
data[i] = this[i];
}
return data;
},
checkAndRepair: function Font_checkAndRepair(name, font, properties) { checkAndRepair: function Font_checkAndRepair(name, font, properties) {
function readTableEntry(file) { function readTableEntry(file) {
var tag = file.getBytes(4); var tag = file.getBytes(4);

View File

@ -61,6 +61,12 @@ var Pattern = (function PatternClosure() {
var Shadings = {}; var Shadings = {};
// A small number to offset the first/last color stops so we can insert ones to
// support extend. Number.MIN_VALUE appears to be too small and breaks the
// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number
// internally so we have to go bigger.
Shadings.SMALL_NUMBER = 1e-2;
// 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 RadialAxialClosure() { Shadings.RadialAxial = (function RadialAxialClosure() {
@ -69,7 +75,6 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
this.coordsArr = dict.get('Coords'); this.coordsArr = dict.get('Coords');
this.shadingType = dict.get('ShadingType'); this.shadingType = dict.get('ShadingType');
this.type = 'Pattern'; this.type = 'Pattern';
this.ctx = ctx; this.ctx = ctx;
var cs = dict.get('ColorSpace', 'CS'); var cs = dict.get('ColorSpace', 'CS');
cs = ColorSpace.parse(cs, xref, res); cs = ColorSpace.parse(cs, xref, res);
@ -87,7 +92,23 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
var extendArr = dict.get('Extend'); var extendArr = dict.get('Extend');
extendStart = extendArr[0]; extendStart = extendArr[0];
extendEnd = extendArr[1]; extendEnd = extendArr[1];
TODO('Support extend'); }
if (this.shadingType === PatternType.RADIAL &&
(!extendStart || !extendEnd)) {
// Radial gradient only currently works if either circle is fully within
// the other circle.
var x1 = this.coordsArr[0];
var y1 = this.coordsArr[1];
var r1 = this.coordsArr[2];
var x2 = this.coordsArr[3];
var y2 = this.coordsArr[4];
var r2 = this.coordsArr[5];
var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
if (r1 <= r2 + distance &&
r2 <= r1 + distance) {
warn('Unsupported radial gradient.');
}
} }
this.extendStart = extendStart; this.extendStart = extendStart;
@ -103,16 +124,43 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
// 10 samples seems good enough for now, but probably won't work // 10 samples seems good enough for now, but probably won't work
// if there are sharp color changes. Ideally, we would implement // if there are sharp color changes. Ideally, we would implement
// the spec faithfully and add lossless optimizations. // the spec faithfully and add lossless optimizations.
var step = (t1 - t0) / 10;
var diff = t1 - t0; var diff = t1 - t0;
var step = diff / 10;
var colorStops = this.colorStops = [];
// Protect against bad domains so we don't end up in an infinte loop below.
if (t0 >= t1 || step <= 0) {
// Acrobat doesn't seem to handle these cases so we'll ignore for
// now.
info('Bad shading domain.');
return;
}
var colorStops = [];
for (var i = t0; i <= t1; i += step) { for (var i = t0; i <= t1; i += step) {
var rgbColor = cs.getRgb(fn([i])); var rgbColor = cs.getRgb(fn([i]));
var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
colorStops.push([(i - t0) / diff, cssColor]); colorStops.push([(i - t0) / diff, cssColor]);
} }
var background = 'transparent';
if (dict.has('Background')) {
var rgbColor = cs.getRgb(dict.get('Background'));
background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
}
if (!extendStart) {
// Insert a color stop at the front and offset the first real color stop
// so it doesn't conflict with the one we insert.
colorStops.unshift([0, background]);
colorStops[1][0] += Shadings.SMALL_NUMBER;
}
if (!extendEnd) {
// Same idea as above in extendStart but for the end.
colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
colorStops.push([1, background]);
}
this.colorStops = colorStops; this.colorStops = colorStops;
} }

View File

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

View File

@ -34,3 +34,4 @@
!gradientfill.pdf !gradientfill.pdf
!basicapi.pdf !basicapi.pdf
!mixedfonts.pdf !mixedfonts.pdf
!shading_extend.pdf

Binary file not shown.

View File

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

View File

@ -11,6 +11,12 @@
"rounds": 2, "rounds": 2,
"type": "fbf" "type": "fbf"
}, },
{ "id": "tracemonkey-text",
"file": "pdfs/tracemonkey.pdf",
"md5": "9a192d8b1a7dc652a19835f6f08098bd",
"rounds": 1,
"type": "text"
},
{ "id": "html5-canvas-cheat-sheet-load", { "id": "html5-canvas-cheat-sheet-load",
"file": "pdfs/canvas.pdf", "file": "pdfs/canvas.pdf",
"md5": "59510028561daf62e00bf9f6f066b033", "md5": "59510028561daf62e00bf9f6f066b033",
@ -89,6 +95,12 @@
"rounds": 1, "rounds": 1,
"type": "eq" "type": "eq"
}, },
{ "id": "thuluthfont-text",
"file": "pdfs/ThuluthFeatures.pdf",
"md5": "b7e18bf7a3d6a9c82aefa12d721072fc",
"rounds": 1,
"type": "text"
},
{ "id": "freeculture", { "id": "freeculture",
"file": "pdfs/freeculture.pdf", "file": "pdfs/freeculture.pdf",
"md5": "dcdf3a8268e6a18938a42d5149efcfca", "md5": "dcdf3a8268e6a18938a42d5149efcfca",