Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[api-minor] Enables subpixel anti-aliasing for most of the content. #6551

Merged
merged 1 commit into from
Nov 18, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/display/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,8 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
* calling of PDFPage.getViewport method.
* @property {string} intent - Rendering intent, can be 'display' or 'print'
* (default value is 'display').
* @property {Array} transform - (optional) Additional transform, applied
* just before viewport transform.
* @property {Object} imageLayer - (optional) An object that has beginLayout,
* endLayout and appendImage functions.
* @property {function} continueCallback - (deprecated) A function that will be
Expand Down Expand Up @@ -1732,7 +1734,7 @@ var InternalRenderTask = (function InternalRenderTaskClosure() {
this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs,
this.objs, params.imageLayer);

this.gfx.beginDrawing(params.viewport, transparency);
this.gfx.beginDrawing(params.transform, params.viewport, transparency);
this.operatorListIdx = 0;
this.graphicsReady = true;
if (this.graphicsReadyCallback) {
Expand Down
85 changes: 56 additions & 29 deletions src/display/canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,15 @@ function addContextCurrentTransform(ctx) {
}

var CachedCanvases = (function CachedCanvasesClosure() {
var cache = {};
return {
function CachedCanvases() {
this.cache = Object.create(null);
}
CachedCanvases.prototype = {
getCanvas: function CachedCanvases_getCanvas(id, width, height,
trackTransform) {
var canvasEntry;
if (cache[id] !== undefined) {
canvasEntry = cache[id];
if (this.cache[id] !== undefined) {
canvasEntry = this.cache[id];
canvasEntry.canvas.width = width;
canvasEntry.canvas.height = height;
// reset canvas transform for emulated mozCurrentTransform, if needed
Expand All @@ -179,21 +181,22 @@ var CachedCanvases = (function CachedCanvasesClosure() {
if (trackTransform) {
addContextCurrentTransform(ctx);
}
cache[id] = canvasEntry = {canvas: canvas, context: ctx};
this.cache[id] = canvasEntry = {canvas: canvas, context: ctx};
}
return canvasEntry;
},
clear: function () {
for (var id in cache) {
var canvasEntry = cache[id];
for (var id in this.cache) {
var canvasEntry = this.cache[id];
// Zeroing the width and height causes Firefox to release graphics
// resources immediately, which can greatly reduce memory consumption.
canvasEntry.canvas.width = 0;
canvasEntry.canvas.height = 0;
delete cache[id];
delete this.cache[id];
}
}
};
return CachedCanvases;
})();

function compileType3Glyph(imgData) {
Expand Down Expand Up @@ -431,6 +434,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.smaskStack = [];
this.smaskCounter = 0;
this.tempSMask = null;
this.cachedCanvases = new CachedCanvases();
if (canvasCtx) {
// NOTE: if mozCurrentTransform is polyfilled, then the current state of
// the transformation must already be set in canvasCtx._transformMatrix.
Expand Down Expand Up @@ -707,28 +711,39 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {

CanvasGraphics.prototype = {

beginDrawing: function CanvasGraphics_beginDrawing(viewport, transparency) {
beginDrawing: function CanvasGraphics_beginDrawing(transform, viewport,
transparency) {
// For pdfs that use blend modes we have to clear the canvas else certain
// blend modes can look wrong since we'd be blending with a white
// backdrop. The problem with a transparent backdrop though is we then
// don't get sub pixel anti aliasing on text, so we fill with white if
// we can.
// don't get sub pixel anti aliasing on text, creating temporary
// transparent canvas when we have blend modes.
var width = this.ctx.canvas.width;
var height = this.ctx.canvas.height;

this.ctx.save();
this.ctx.fillStyle = 'rgb(255, 255, 255)';
this.ctx.fillRect(0, 0, width, height);
this.ctx.restore();

if (transparency) {
this.ctx.clearRect(0, 0, width, height);
} else {
this.ctx.mozOpaque = true;
var transparentCanvas = this.cachedCanvases.getCanvas(
'transparent', width, height, true);
this.compositeCtx = this.ctx;
this.transparentCanvas = transparentCanvas.canvas;
this.ctx = transparentCanvas.context;
this.ctx.save();
this.ctx.fillStyle = 'rgb(255, 255, 255)';
this.ctx.fillRect(0, 0, width, height);
this.ctx.restore();
// The transform can be applied before rendering, transferring it to
// the new canvas.
this.ctx.transform.apply(this.ctx,
this.compositeCtx.mozCurrentTransform);
}

var transform = viewport.transform;

this.ctx.save();
this.ctx.transform.apply(this.ctx, transform);
if (transform) {
this.ctx.transform.apply(this.ctx, transform);
}
this.ctx.transform.apply(this.ctx, viewport.transform);

this.baseTransform = this.ctx.mozCurrentTransform.slice();

Expand Down Expand Up @@ -810,7 +825,14 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {

endDrawing: function CanvasGraphics_endDrawing() {
this.ctx.restore();
CachedCanvases.clear();

if (this.transparentCanvas) {
this.ctx = this.compositeCtx;
this.ctx.drawImage(this.transparentCanvas, 0, 0);
this.transparentCanvas = null;
}

this.cachedCanvases.clear();
WebGLUtils.clear();

if (this.imageLayer) {
Expand Down Expand Up @@ -924,7 +946,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var drawnWidth = activeSMask.canvas.width;
var drawnHeight = activeSMask.canvas.height;
var cacheId = 'smaskGroupAt' + this.groupLevel;
var scratchCanvas = CachedCanvases.getCanvas(
var scratchCanvas = this.cachedCanvases.getCanvas(
cacheId, drawnWidth, drawnHeight, true);

var currentCtx = this.ctx;
Expand Down Expand Up @@ -1708,7 +1730,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// Using two cache entries is case if masks are used one after another.
cacheId += '_smask_' + ((this.smaskCounter++) % 2);
}
var scratchCanvas = CachedCanvases.getCanvas(
var scratchCanvas = this.cachedCanvases.getCanvas(
cacheId, drawnWidth, drawnHeight, true);
var groupCtx = scratchCanvas.context;

Expand Down Expand Up @@ -1849,7 +1871,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
return;
}

var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas',
width, height);
var maskCtx = maskCanvas.context;
maskCtx.save();

Expand All @@ -1874,7 +1897,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var fillColor = this.current.fillColor;
var isPatternFill = this.current.patternFill;

var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas',
width, height);
var maskCtx = maskCanvas.context;
maskCtx.save();

Expand Down Expand Up @@ -1909,7 +1933,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var image = images[i];
var width = image.width, height = image.height;

var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas',
width, height);
var maskCtx = maskCanvas.context;
maskCtx.save();

Expand Down Expand Up @@ -1982,7 +2007,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (imgData instanceof HTMLElement || !imgData.data) {
imgToPaint = imgData;
} else {
tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height);
tmpCanvas = this.cachedCanvases.getCanvas('inlineImage',
width, height);
var tmpCtx = tmpCanvas.context;
putBinaryImageData(tmpCtx, imgData);
imgToPaint = tmpCanvas.canvas;
Expand All @@ -2004,7 +2030,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
newHeight = Math.ceil(paintHeight / 2);
heightScale /= paintHeight / newHeight;
}
tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId,
newWidth, newHeight);
tmpCtx = tmpCanvas.context;
tmpCtx.clearRect(0, 0, newWidth, newHeight);
tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight,
Expand Down Expand Up @@ -2036,7 +2063,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var w = imgData.width;
var h = imgData.height;

var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h);
var tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', w, h);
var tmpCtx = tmpCanvas.context;
putBinaryImageData(tmpCtx, imgData);

Expand Down
12 changes: 7 additions & 5 deletions src/display/pattern_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
}

function createMeshCanvas(bounds, combinesScale, coords, colors, figures,
backgroundColor) {
backgroundColor, cachedCanvases) {
// we will increase scale on some weird factor to let antialiasing take
// care of "rough" edges
var EXPECTED_SCALE = 1.1;
Expand Down Expand Up @@ -183,11 +183,11 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
figures, context);

// https://bugzilla.mozilla.org/show_bug.cgi?id=972126
tmpCanvas = CachedCanvases.getCanvas('mesh', width, height, false);
tmpCanvas = cachedCanvases.getCanvas('mesh', width, height, false);
tmpCanvas.context.drawImage(canvas, 0, 0);
canvas = tmpCanvas.canvas;
} else {
tmpCanvas = CachedCanvases.getCanvas('mesh', width, height, false);
tmpCanvas = cachedCanvases.getCanvas('mesh', width, height, false);
var tmpCtx = tmpCanvas.context;

var data = tmpCtx.createImageData(width, height);
Expand Down Expand Up @@ -243,7 +243,8 @@ ShadingIRs.Mesh = {
// Rasterizing on the main thread since sending/queue large canvases
// might cause OOM.
var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords,
colors, figures, shadingFill ? null : background);
colors, figures, shadingFill ? null : background,
owner.cachedCanvases);

if (!shadingFill) {
ctx.setTransform.apply(ctx, owner.baseTransform);
Expand Down Expand Up @@ -346,7 +347,8 @@ var TilingPattern = (function TilingPatternClosure() {
height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])),
MAX_PATTERN_SIZE);

var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true);
var tmpCanvas = owner.cachedCanvases.getCanvas('pattern',
width, height, true);
var tmpCtx = tmpCanvas.context;
var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs);
graphics.groupLevel = owner.groupLevel;
Expand Down
18 changes: 15 additions & 3 deletions test/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ var SimpleTextLayerBuilder = (function SimpleTextLayerBuilderClosure() {
this.ctx = ctx;
this.viewport = viewport;
this.textCounter = 0;

// clear canvas
ctx.save();
ctx.fillStyle = 'rgb(255,255,255)';
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.restore();
}

SimpleTextLayerBuilder.prototype = {
Expand Down Expand Up @@ -271,6 +277,7 @@ var Driver = (function DriverClosure() {
_nextPage: function Driver_nextPage(task, loadError) {
var self = this;
var failure = loadError || '';
var ctx;

if (!task.pdfDoc) {
var dataUrl = this.canvas.toDataURL('image/png');
Expand Down Expand Up @@ -301,7 +308,11 @@ var Driver = (function DriverClosure() {
// Empty the canvas
this.canvas.width = 1;
this.canvas.height = 1;
this._clearCanvas();
ctx = this.canvas.getContext('2d', {alpha: false});
ctx.save();
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, 1, 1);
ctx.restore();

this._snapshot(task, '');
return;
Expand All @@ -311,7 +322,8 @@ var Driver = (function DriverClosure() {
try {
this._log(' Loading page ' + task.pageNum + '/' +
task.pdfDoc.numPages + '... ');
var ctx = this.canvas.getContext('2d');
this.canvas.mozOpaque = true;
ctx = this.canvas.getContext('2d', {alpha: false});
task.pdfDoc.getPage(task.pageNum).then(function(page) {
var viewport = page.getViewport(PDF_TO_CSS_UNITS);
self.canvas.width = viewport.width;
Expand Down Expand Up @@ -371,7 +383,7 @@ var Driver = (function DriverClosure() {
},

_clearCanvas: function Driver_clearCanvas() {
var ctx = this.canvas.getContext('2d');
var ctx = this.canvas.getContext('2d', {alpha: false});
ctx.beginPath();
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
Expand Down
26 changes: 15 additions & 11 deletions web/pdf_page_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ var PDFPageView = (function PDFPageViewClosure() {

var isScalingRestricted = false;
if (this.canvas && PDFJS.maxCanvasPixels > 0) {
var ctx = this.canvas.getContext('2d');
var outputScale = getOutputScale(ctx);
var outputScale = this.outputScale;
var pixelsInViewport = this.viewport.width * this.viewport.height;
var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport);
if (((Math.floor(this.viewport.width) * outputScale.sx) | 0) *
Expand Down Expand Up @@ -311,17 +310,23 @@ var PDFPageView = (function PDFPageViewClosure() {

var canvas = document.createElement('canvas');
canvas.id = 'page' + this.id;
canvas.setAttribute('hidden', 'hidden');
canvasWrapper.appendChild(canvas);
if (this.annotationLayer && this.annotationLayer.div) {
// annotationLayer needs to stay on top
div.insertBefore(canvasWrapper, this.annotationLayer.div);
} else {
div.appendChild(canvasWrapper);
}
var isCanvasHidden = true;
this.canvas = canvas;

var ctx = canvas.getContext('2d');
//#if MOZCENTRAL || FIREFOX || GENERIC
canvas.mozOpaque = true;
//#endif
var ctx = canvas.getContext('2d', {alpha: false});
var outputScale = getOutputScale(ctx);
this.outputScale = outputScale;

if (PDFJS.useOnlyCssZoom) {
var actualSizeViewport = viewport.clone({scale: CSS_UNITS});
Expand Down Expand Up @@ -374,14 +379,6 @@ var PDFPageView = (function PDFPageViewClosure() {
}
this.textLayer = textLayer;

if (outputScale.scaled) {
//#if !(MOZCENTRAL || FIREFOX)
// Used by the mozCurrentTransform polyfill in src/display/canvas.js.
ctx._transformMatrix = [outputScale.sx, 0, 0, outputScale.sy, 0, 0];
//#endif
ctx.scale(outputScale.sx, outputScale.sy);
}

var resolveRenderPromise, rejectRenderPromise;
var promise = new Promise(function (resolve, reject) {
resolveRenderPromise = resolve;
Expand Down Expand Up @@ -461,12 +458,19 @@ var PDFPageView = (function PDFPageViewClosure() {
};
return;
}
if (isCanvasHidden) {
self.canvas.removeAttribute('hidden');
isCanvasHidden = false;
}
cont();
};
}

var transform = !outputScale.scaled ? null :
[outputScale.sx, 0, 0, outputScale.sy, 0, 0];
var renderContext = {
canvasContext: ctx,
transform: transform,
viewport: this.viewport,
// intent: 'default', // === 'display'
};
Expand Down
Loading