Skip to content

Commit

Permalink
Implements WebGL support
Browse files Browse the repository at this point in the history
  • Loading branch information
yurydelendik committed Apr 3, 2014
1 parent 944219a commit f57c693
Show file tree
Hide file tree
Showing 12 changed files with 516 additions and 33 deletions.
1 change: 1 addition & 0 deletions examples/acroforms/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<script type="text/javascript" src="../../src/display/api.js"></script>
<script type="text/javascript" src="../../src/display/metadata.js"></script>
<script type="text/javascript" src="../../src/display/canvas.js"></script>
<script type="text/javascript" src="../../src/display/webgl.js"></script>
<script type="text/javascript" src="../../src/display/pattern_helper.js"></script>
<script type="text/javascript" src="../../src/display/font_loader.js"></script>

Expand Down
1 change: 1 addition & 0 deletions examples/helloworld/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<script type="text/javascript" src="../../src/display/api.js"></script>
<script type="text/javascript" src="../../src/display/metadata.js"></script>
<script type="text/javascript" src="../../src/display/canvas.js"></script>
<script type="text/javascript" src="../../src/display/webgl.js"></script>
<script type="text/javascript" src="../../src/display/pattern_helper.js"></script>
<script type="text/javascript" src="../../src/display/font_loader.js"></script>

Expand Down
1 change: 1 addition & 0 deletions make.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ target.bundle = function(args) {
'display/api.js',
'display/metadata.js',
'display/canvas.js',
'display/webgl.js',
'display/pattern_helper.js',
'display/font_loader.js'
]);
Expand Down
7 changes: 7 additions & 0 deletions src/display/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ PDFJS.postMessageTransfers = (PDFJS.postMessageTransfers === undefined ?
PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ?
false : PDFJS.disableCreateObjectURL);

/**
* Disables WebGL usage.
* @var {boolean}
*/
PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ?
true : PDFJS.disableWebGL);

/**
* Controls the logging level.
* The constants from PDFJS.VERBOSITY_LEVELS should be used:
Expand Down
37 changes: 27 additions & 10 deletions src/display/canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
/* globals ColorSpace, DeviceCmykCS, DeviceGrayCS, DeviceRgbCS, error, PDFJS,
FONT_IDENTITY_MATRIX, Uint32ArrayView, IDENTITY_MATRIX, ImageData,
ImageKind, isArray, isNum, TilingPattern, OPS, Promise, Util, warn,
assert, info, shadow, TextRenderingMode, getShadingPatternFromIR */
assert, info, shadow, TextRenderingMode, getShadingPatternFromIR,
WebGLUtils */

'use strict';

Expand Down Expand Up @@ -601,15 +602,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
}

function composeSMask(ctx, smask, layerCtx) {
var mask = smask.canvas;
var maskCtx = smask.context;
var width = mask.width, height = mask.height;

function genericComposeSMask(maskCtx, layerCtx, width, height,
subtype, backdrop) {
var addBackdropFn;
if (smask.backdrop) {
var cs = smask.colorSpace || ColorSpace.singletons.rgb;
var backdrop = cs.getRgb(smask.backdrop, 0);
if (backdrop) {
addBackdropFn = function (r0, g0, b0, bytes) {
var length = bytes.length;
for (var i = 3; i < length; i += 4) {
Expand All @@ -631,7 +627,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}

var composeFn;
if (smask.subtype === 'Luminosity') {
if (subtype === 'Luminosity') {
composeFn = function (maskDataBytes, layerDataBytes) {
var length = maskDataBytes.length;
for (var i = 3; i < length; i += 4) {
Expand Down Expand Up @@ -664,9 +660,29 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {

maskCtx.putImageData(layerData, 0, row);
}
}

function composeSMask(ctx, smask, layerCtx) {
var mask = smask.canvas;
var maskCtx = smask.context;

ctx.setTransform(smask.scaleX, 0, 0, smask.scaleY,
smask.offsetX, smask.offsetY);

var backdrop;
if (smask.backdrop) {
var cs = smask.colorSpace || ColorSpace.singletons.rgb;
backdrop = cs.getRgb(smask.backdrop, 0);
}
if (WebGLUtils.isEnabled) {
var composed = WebGLUtils.composeSMask(layerCtx.canvas, mask,
{subtype: smask.subtype, backdrop: backdrop});
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.drawImage(composed, smask.offsetX, smask.offsetY);
return;
}
genericComposeSMask(maskCtx, layerCtx, mask.width, mask.height,
smask.subtype, backdrop);
ctx.drawImage(mask, 0, 0);
}

Expand Down Expand Up @@ -784,6 +800,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
endDrawing: function CanvasGraphics_endDrawing() {
this.ctx.restore();
CachedCanvases.clear();
WebGLUtils.clear();

if (this.textLayer) {
this.textLayer.endLayout();
Expand Down
66 changes: 43 additions & 23 deletions src/display/pattern_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/
/* globals CanvasGraphics, CachedCanvases, ColorSpace, Util, error, info,
isArray, makeCssRgb */
isArray, makeCssRgb, WebGLUtils */

'use strict';

Expand Down Expand Up @@ -155,39 +155,59 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
// MAX_PATTERN_SIZE is used to avoid OOM situation.
var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough

var boundsWidth = bounds[2] - bounds[0];
var boundsHeight = bounds[3] - bounds[1];
var offsetX = Math.floor(bounds[0]);
var offsetY = Math.floor(bounds[1]);
var boundsWidth = Math.ceil(bounds[2]) - offsetX;
var boundsHeight = Math.ceil(bounds[3]) - offsetY;

var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] *
EXPECTED_SCALE)), MAX_PATTERN_SIZE);
var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] *
EXPECTED_SCALE)), MAX_PATTERN_SIZE);
var scaleX = width / boundsWidth;
var scaleY = height / boundsHeight;

var tmpCanvas = CachedCanvases.getCanvas('mesh', width, height, false);
var tmpCtx = tmpCanvas.context;
if (backgroundColor) {
tmpCtx.fillStyle = makeCssRgb(backgroundColor);
tmpCtx.fillRect(0, 0, width, height);
}
var scaleX = boundsWidth / width;
var scaleY = boundsHeight / height;

var context = {
coords: coords,
colors: colors,
offsetX: -bounds[0],
offsetY: -bounds[1],
scaleX: scaleX,
scaleY: scaleY
offsetX: -offsetX,
offsetY: -offsetY,
scaleX: 1 / scaleX,
scaleY: 1 / scaleY
};

var data = tmpCtx.getImageData(0, 0, width, height);
for (var i = 0; i < figures.length; i++) {
drawFigure(data, figures[i], context);
var canvas;
if (WebGLUtils.isEnabled) {
canvas = WebGLUtils.drawFigures(width, height, backgroundColor,
figures, context);

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

var data = tmpCtx.createImageData(width, height);
if (backgroundColor) {
var bytes = data.data;
for (var i = 0, ii = bytes.length; i < ii; i += 4) {
bytes[i] = backgroundColor[0];
bytes[i + 1] = backgroundColor[1];
bytes[i + 2] = backgroundColor[2];
bytes[i + 3] = 255;
}
}
for (var i = 0; i < figures.length; i++) {
drawFigure(data, figures[i], context);
}
tmpCtx.putImageData(data, 0, 0);
canvas = tmpCanvas.canvas;
}
tmpCtx.putImageData(data, 0, 0);

return {canvas: tmpCanvas.canvas, scaleX: 1 / scaleX, scaleY: 1 / scaleY};
return {canvas: canvas, offsetX: offsetX, offsetY: offsetY,
scaleX: scaleX, scaleY: scaleY};
}
return createMeshCanvas;
})();
Expand Down Expand Up @@ -221,7 +241,6 @@ ShadingIRs.Mesh = {

// Rasterizing on the main thread since sending/queue large canvases
// might cause OOM.
// TODO consider using WebGL or asm.js to perform rasterization
var temporaryPatternCanvas = createMeshCanvas(bounds, combinedScale,
coords, colors, figures, shadingFill ? null : background);

Expand All @@ -232,7 +251,8 @@ ShadingIRs.Mesh = {
}
}

ctx.translate(bounds[0], bounds[1]);
ctx.translate(temporaryPatternCanvas.offsetX,
temporaryPatternCanvas.offsetY);
ctx.scale(temporaryPatternCanvas.scaleX,
temporaryPatternCanvas.scaleY);

Expand Down
Loading

0 comments on commit f57c693

Please sign in to comment.