diff --git a/src/canvas.js b/src/canvas.js index 70dd65e3d..3c7551404 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -28,6 +28,9 @@ var CanvasExtraState = (function canvasExtraState() { // Default fore and background colors this.fillColor = '#000000'; this.strokeColor = '#000000'; + // Note: fill alpha applies to all non-stroking operations + this.fillAlpha = 1; + this.strokeAlpha = 1; this.old = old; } @@ -206,6 +209,13 @@ var CanvasGraphics = (function canvasGraphics() { case 'Font': this.setFont(state[1], state[2]); break; + case 'CA': + this.current.strokeAlpha = state[1]; + break; + case 'ca': + this.current.fillAlpha = state[1]; + this.ctx.globalAlpha = state[1]; + break; } } }, @@ -254,9 +264,13 @@ var CanvasGraphics = (function canvasGraphics() { rectangle: function canvasGraphicsRectangle(x, y, width, height) { this.ctx.rect(x, y, width, height); }, - stroke: function canvasGraphicsStroke() { + stroke: function canvasGraphicsStroke(consumePath) { + consumePath = typeof consumePath !== 'undefined' ? consumePath : true; var ctx = this.ctx; var strokeColor = this.current.strokeColor; + // For stroke we want to temporarily change the global alpha to the + // stroking alpha. + ctx.globalAlpha = this.current.strokeAlpha; if (strokeColor && strokeColor.hasOwnProperty('type') && strokeColor.type === 'Pattern') { // for patterns, we transform to pattern space, calculate @@ -268,14 +282,17 @@ var CanvasGraphics = (function canvasGraphics() { } else { ctx.stroke(); } - - this.consumePath(); + if (consumePath) + this.consumePath(); + // Restore the global alpha to the fill alpha + ctx.globalAlpha = this.current.fillAlpha; }, closeStroke: function canvasGraphicsCloseStroke() { this.closePath(); this.stroke(); }, - fill: function canvasGraphicsFill() { + fill: function canvasGraphicsFill(consumePath) { + consumePath = typeof consumePath !== 'undefined' ? consumePath : true; var ctx = this.ctx; var fillColor = this.current.fillColor; @@ -288,8 +305,8 @@ var CanvasGraphics = (function canvasGraphics() { } else { ctx.fill(); } - - this.consumePath(); + if (consumePath) + this.consumePath(); }, eoFill: function canvasGraphicsEoFill() { var savedFillRule = this.setEOFillRule(); @@ -297,29 +314,8 @@ var CanvasGraphics = (function canvasGraphics() { this.restoreFillRule(savedFillRule); }, fillStroke: function canvasGraphicsFillStroke() { - var ctx = this.ctx; - - var fillColor = this.current.fillColor; - if (fillColor && fillColor.hasOwnProperty('type') && - fillColor.type === 'Pattern') { - ctx.save(); - ctx.fillStyle = fillColor.getPattern(ctx); - ctx.fill(); - ctx.restore(); - } else { - ctx.fill(); - } - - var strokeColor = this.current.strokeColor; - if (strokeColor && strokeColor.hasOwnProperty('type') && - strokeColor.type === 'Pattern') { - ctx.save(); - ctx.strokeStyle = strokeColor.getPattern(ctx); - ctx.stroke(); - ctx.restore(); - } else { - ctx.stroke(); - } + this.fill(false); + this.stroke(false); this.consumePath(); }, diff --git a/src/evaluator.js b/src/evaluator.js index 5007394b4..ea152717a 100644 --- a/src/evaluator.js +++ b/src/evaluator.js @@ -405,6 +405,8 @@ var PartialEvaluator = (function partialEvaluator() { case 'D': case 'RI': case 'FL': + case 'CA': + case 'ca': gsStateObj.push([key, value]); break; case 'Font': @@ -428,8 +430,6 @@ var PartialEvaluator = (function partialEvaluator() { case 'SA': case 'BM': case 'SMask': - case 'CA': - case 'ca': case 'AIS': case 'TK': TODO('graphic state operator ' + key); diff --git a/test/pdfs/alphatrans.pdf b/test/pdfs/alphatrans.pdf new file mode 100644 index 000000000..6274ce3ac Binary files /dev/null and b/test/pdfs/alphatrans.pdf differ