minor improvements and code cleanup for canvas.js

This commit is contained in:
Fabian Lange 2014-10-26 18:20:04 +01:00
parent d65db7c5ed
commit 5405b1c8e4

View File

@ -29,6 +29,9 @@ var MIN_FONT_SIZE = 16;
var MAX_GROUP_SIZE = 4096; var MAX_GROUP_SIZE = 4096;
var COMPILE_TYPE3_GLYPHS = true; var COMPILE_TYPE3_GLYPHS = true;
var MAX_SIZE_TO_COMPILE = 1000;
var FULL_CHUNK_HEIGHT = 16;
function createScratchCanvas(width, height) { function createScratchCanvas(width, height) {
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
@ -162,7 +165,7 @@ var CachedCanvases = (function CachedCanvasesClosure() {
getCanvas: function CachedCanvases_getCanvas(id, width, height, getCanvas: function CachedCanvases_getCanvas(id, width, height,
trackTransform) { trackTransform) {
var canvasEntry; var canvasEntry;
if (id in cache) { if (cache[id] !== undefined) {
canvasEntry = cache[id]; canvasEntry = cache[id];
canvasEntry.canvas.width = width; canvasEntry.canvas.width = width;
canvasEntry.canvas.height = height; canvasEntry.canvas.height = height;
@ -376,6 +379,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
// Default fore and background colors // Default fore and background colors
this.fillColor = '#000000'; this.fillColor = '#000000';
this.strokeColor = '#000000'; this.strokeColor = '#000000';
this.patternFill = false;
// Note: fill alpha applies to all non-stroking operations // Note: fill alpha applies to all non-stroking operations
this.fillAlpha = 1; this.fillAlpha = 1;
this.strokeAlpha = 1; this.strokeAlpha = 1;
@ -448,13 +452,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// that's ok; any such pixels are ignored. // that's ok; any such pixels are ignored.
var height = imgData.height, width = imgData.width; var height = imgData.height, width = imgData.width;
var fullChunkHeight = 16; var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
var fracChunks = height / fullChunkHeight; var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
var fullChunks = Math.floor(fracChunks); var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
var totalChunks = Math.ceil(fracChunks);
var partialChunkHeight = height - fullChunks * fullChunkHeight;
var chunkImgData = ctx.createImageData(width, fullChunkHeight); var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
var srcPos = 0, destPos; var srcPos = 0, destPos;
var src = imgData.data; var src = imgData.data;
var dest = chunkImgData.data; var dest = chunkImgData.data;
@ -474,7 +476,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
0xFF000000 : 0x000000FF; 0xFF000000 : 0x000000FF;
for (i = 0; i < totalChunks; i++) { for (i = 0; i < totalChunks; i++) {
thisChunkHeight = thisChunkHeight =
(i < fullChunks) ? fullChunkHeight : partialChunkHeight; (i < fullChunks) ? FULL_CHUNK_HEIGHT : partialChunkHeight;
destPos = 0; destPos = 0;
for (j = 0; j < thisChunkHeight; j++) { for (j = 0; j < thisChunkHeight; j++) {
var srcDiff = srcLength - srcPos; var srcDiff = srcLength - srcPos;
@ -509,19 +511,19 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
dest32[destPos++] = 0; dest32[destPos++] = 0;
} }
ctx.putImageData(chunkImgData, 0, i * fullChunkHeight); ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
} }
} else if (imgData.kind === ImageKind.RGBA_32BPP) { } else if (imgData.kind === ImageKind.RGBA_32BPP) {
// RGBA, 32-bits per pixel. // RGBA, 32-bits per pixel.
j = 0; j = 0;
elemsInThisChunk = width * fullChunkHeight * 4; elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
for (i = 0; i < fullChunks; i++) { for (i = 0; i < fullChunks; i++) {
dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
srcPos += elemsInThisChunk; srcPos += elemsInThisChunk;
ctx.putImageData(chunkImgData, 0, j); ctx.putImageData(chunkImgData, 0, j);
j += fullChunkHeight; j += FULL_CHUNK_HEIGHT;
} }
if (i < totalChunks) { if (i < totalChunks) {
elemsInThisChunk = width * partialChunkHeight * 4; elemsInThisChunk = width * partialChunkHeight * 4;
@ -531,11 +533,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
} else if (imgData.kind === ImageKind.RGB_24BPP) { } else if (imgData.kind === ImageKind.RGB_24BPP) {
// RGB, 24-bits per pixel. // RGB, 24-bits per pixel.
thisChunkHeight = fullChunkHeight; thisChunkHeight = FULL_CHUNK_HEIGHT;
elemsInThisChunk = width * thisChunkHeight; elemsInThisChunk = width * thisChunkHeight;
for (i = 0; i < totalChunks; i++) { for (i = 0; i < totalChunks; i++) {
if (i >= fullChunks) { if (i >= fullChunks) {
thisChunkHeight =partialChunkHeight; thisChunkHeight = partialChunkHeight;
elemsInThisChunk = width * thisChunkHeight; elemsInThisChunk = width * thisChunkHeight;
} }
@ -546,7 +548,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = 255; dest[destPos++] = 255;
} }
ctx.putImageData(chunkImgData, 0, i * fullChunkHeight); ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
} }
} else { } else {
error('bad image kind: ' + imgData.kind); error('bad image kind: ' + imgData.kind);
@ -555,20 +557,18 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
function putBinaryImageMask(ctx, imgData) { function putBinaryImageMask(ctx, imgData) {
var height = imgData.height, width = imgData.width; var height = imgData.height, width = imgData.width;
var fullChunkHeight = 16; var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
var fracChunks = height / fullChunkHeight; var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
var fullChunks = Math.floor(fracChunks); var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
var totalChunks = Math.ceil(fracChunks);
var partialChunkHeight = height - fullChunks * fullChunkHeight;
var chunkImgData = ctx.createImageData(width, fullChunkHeight); var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
var srcPos = 0; var srcPos = 0;
var src = imgData.data; var src = imgData.data;
var dest = chunkImgData.data; var dest = chunkImgData.data;
for (var i = 0; i < totalChunks; i++) { for (var i = 0; i < totalChunks; i++) {
var thisChunkHeight = var thisChunkHeight =
(i < fullChunks) ? fullChunkHeight : partialChunkHeight; (i < fullChunks) ? FULL_CHUNK_HEIGHT : partialChunkHeight;
// Expand the mask so it can be used by the canvas. Any required // Expand the mask so it can be used by the canvas. Any required
// inversion has already been handled. // inversion has already been handled.
@ -585,7 +585,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
mask >>= 1; mask >>= 1;
} }
} }
ctx.putImageData(chunkImgData, 0, i * fullChunkHeight); ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
} }
} }
@ -595,14 +595,14 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
'globalCompositeOperation', 'font']; 'globalCompositeOperation', 'font'];
for (var i = 0, ii = properties.length; i < ii; i++) { for (var i = 0, ii = properties.length; i < ii; i++) {
var property = properties[i]; var property = properties[i];
if (property in sourceCtx) { if (sourceCtx[property] !== undefined) {
destCtx[property] = sourceCtx[property]; destCtx[property] = sourceCtx[property];
} }
} }
if ('setLineDash' in sourceCtx) { if (sourceCtx.setLineDash !== undefined) {
destCtx.setLineDash(sourceCtx.getLineDash()); destCtx.setLineDash(sourceCtx.getLineDash());
destCtx.lineDashOffset = sourceCtx.lineDashOffset; destCtx.lineDashOffset = sourceCtx.lineDashOffset;
} else if ('mozDash' in sourceCtx) { } else if (sourceCtx.mozDashOffset !== undefined) {
destCtx.mozDash = sourceCtx.mozDash; destCtx.mozDash = sourceCtx.mozDash;
destCtx.mozDashOffset = sourceCtx.mozDashOffset; destCtx.mozDashOffset = sourceCtx.mozDashOffset;
} }
@ -829,7 +829,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}, },
setDash: function CanvasGraphics_setDash(dashArray, dashPhase) { setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
var ctx = this.ctx; var ctx = this.ctx;
if ('setLineDash' in ctx) { if (ctx.setLineDash !== undefined) {
ctx.setLineDash(dashArray); ctx.setLineDash(dashArray);
ctx.lineDashOffset = dashPhase; ctx.lineDashOffset = dashPhase;
} else { } else {
@ -1072,10 +1072,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
consumePath = typeof consumePath !== 'undefined' ? consumePath : true; consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
var ctx = this.ctx; var ctx = this.ctx;
var fillColor = this.current.fillColor; var fillColor = this.current.fillColor;
var isPatternFill = this.current.patternFill;
var needRestore = false; var needRestore = false;
if (fillColor && fillColor.hasOwnProperty('type') && if (isPatternFill) {
fillColor.type === 'Pattern') {
ctx.save(); ctx.save();
ctx.fillStyle = fillColor.getPattern(ctx, this); ctx.fillStyle = fillColor.getPattern(ctx, this);
needRestore = true; needRestore = true;
@ -1549,6 +1549,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}, },
setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) { setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) {
this.current.fillColor = this.getColorN_Pattern(arguments); this.current.fillColor = this.getColorN_Pattern(arguments);
this.current.patternFill = true;
}, },
setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) { setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
var color = Util.makeCssRgb(arguments); var color = Util.makeCssRgb(arguments);
@ -1559,6 +1560,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var color = Util.makeCssRgb(arguments); var color = Util.makeCssRgb(arguments);
this.ctx.fillStyle = color; this.ctx.fillStyle = color;
this.current.fillColor = color; this.current.fillColor = color;
this.current.patternFill = false;
}, },
shadingFill: function CanvasGraphics_shadingFill(patternIR) { shadingFill: function CanvasGraphics_shadingFill(patternIR) {
@ -1817,11 +1819,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) { paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) {
var ctx = this.ctx; var ctx = this.ctx;
var width = img.width, height = img.height; var width = img.width, height = img.height;
var fillColor = this.current.fillColor;
var isPatternFill = this.current.patternFill;
var glyph = this.processingType3; var glyph = this.processingType3;
if (COMPILE_TYPE3_GLYPHS && glyph && !('compiled' in glyph)) { if (COMPILE_TYPE3_GLYPHS && glyph && glyph.compiled === undefined) {
var MAX_SIZE_TO_COMPILE = 1000;
if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) { if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) {
glyph.compiled = glyph.compiled =
compileType3Glyph({data: img.data, width: width, height: height}); compileType3Glyph({data: img.data, width: width, height: height});
@ -1843,9 +1846,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
maskCtx.globalCompositeOperation = 'source-in'; maskCtx.globalCompositeOperation = 'source-in';
var fillColor = this.current.fillColor; maskCtx.fillStyle = isPatternFill ?
maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
fillColor.type === 'Pattern') ?
fillColor.getPattern(maskCtx, this) : fillColor; fillColor.getPattern(maskCtx, this) : fillColor;
maskCtx.fillRect(0, 0, width, height); maskCtx.fillRect(0, 0, width, height);
@ -1859,7 +1860,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
scaleY, positions) { scaleY, positions) {
var width = imgData.width; var width = imgData.width;
var height = imgData.height; var height = imgData.height;
var ctx = this.ctx; var fillColor = this.current.fillColor;
var isPatternFill = this.current.patternFill;
var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height);
var maskCtx = maskCanvas.context; var maskCtx = maskCanvas.context;
@ -1869,14 +1871,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
maskCtx.globalCompositeOperation = 'source-in'; maskCtx.globalCompositeOperation = 'source-in';
var fillColor = this.current.fillColor; maskCtx.fillStyle = isPatternFill ?
maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && fillColor.getPattern(maskCtx, this) : fillColor;
fillColor.type === 'Pattern') ?
fillColor.getPattern(maskCtx, this) : fillColor;
maskCtx.fillRect(0, 0, width, height); maskCtx.fillRect(0, 0, width, height);
maskCtx.restore(); maskCtx.restore();
var ctx = this.ctx;
for (var i = 0, ii = positions.length; i < ii; i += 2) { for (var i = 0, ii = positions.length; i < ii; i += 2) {
ctx.save(); ctx.save();
ctx.transform(scaleX, 0, 0, scaleY, positions[i], positions[i + 1]); ctx.transform(scaleX, 0, 0, scaleY, positions[i], positions[i + 1]);
@ -1891,6 +1892,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
function CanvasGraphics_paintImageMaskXObjectGroup(images) { function CanvasGraphics_paintImageMaskXObjectGroup(images) {
var ctx = this.ctx; var ctx = this.ctx;
var fillColor = this.current.fillColor;
var isPatternFill = this.current.patternFill;
for (var i = 0, ii = images.length; i < ii; i++) { for (var i = 0, ii = images.length; i < ii; i++) {
var image = images[i]; var image = images[i];
var width = image.width, height = image.height; var width = image.width, height = image.height;
@ -1903,9 +1906,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
maskCtx.globalCompositeOperation = 'source-in'; maskCtx.globalCompositeOperation = 'source-in';
var fillColor = this.current.fillColor; maskCtx.fillStyle = isPatternFill ?
maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
fillColor.type === 'Pattern') ?
fillColor.getPattern(maskCtx, this) : fillColor; fillColor.getPattern(maskCtx, this) : fillColor;
maskCtx.fillRect(0, 0, width, height); maskCtx.fillRect(0, 0, width, height);