[Pkg-javascript-commits] [pdf.js] 155/246: Adds image and mask features, fixes clippath
David Prévot
taffit at moszumanska.debian.org
Sun Sep 7 15:36:36 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository pdf.js.
commit 458b69b6497eaa02934ebf39286700e1263a2302
Author: pramodhkp <prmdh1 at gmail.com>
Date: Thu Aug 7 22:00:48 2014 +0530
Adds image and mask features, fixes clippath
---
src/core/evaluator.js | 4 +-
src/display/svg.js | 311 ++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 292 insertions(+), 23 deletions(-)
diff --git a/src/core/evaluator.js b/src/core/evaluator.js
index 41945e5..5de0ebd 100644
--- a/src/core/evaluator.js
+++ b/src/core/evaluator.js
@@ -1857,7 +1857,9 @@ var OperatorList = (function OperatorListClosure() {
},
flush: function(lastChunk) {
- new QueueOptimizer().optimize(this);
+ if (this.intent !== 'oplist') {
+ new QueueOptimizer().optimize(this);
+ }
var transfers = getTransfers(this);
this.messageHandler.send('RenderPageChunk', {
operatorList: {
diff --git a/src/display/svg.js b/src/display/svg.js
index 6431ebf..46048f5 100644
--- a/src/display/svg.js
+++ b/src/display/svg.js
@@ -15,7 +15,7 @@
* limitations under the License.
*/
/* globals PDFJS, FONT_IDENTITY_MATRIX, IDENTITY_MATRIX,
- isNum, OPS, Promise, Util, warn */
+ isNum, OPS, Promise, Util, warn, ImageKind, PDFJS */
'use strict';
@@ -29,6 +29,189 @@ function createScratchSVG(width, height) {
return svg;
}
+var convertImgDataToPng = (function convertImgDataToPngClosure() {
+ var crcTable = [];
+ for (var i = 0; i < 256; i++) {
+ var c = i;
+ for (var h = 0; h < 8; h++) {
+ if (c & 1) {
+ c = 0xedB88320 ^ ((c >> 1) & 0x7fffffff);
+ } else {
+ c = (c >> 1) & 0x7fffffff;
+ }
+ }
+ crcTable[i] = c;
+ }
+
+ function crc32(data, start, end) {
+ var crc = -1;
+ for (var i = start; i < end; i++) {
+ var a = (crc ^ data[i]) & 0xff;
+ var b = crcTable[a];
+ crc = (crc >>> 8) ^ b;
+ }
+ return crc ^ -1;
+ }
+
+ function createPngChunk(type, data) {
+ var chunk = new Uint8Array(12 + data.length);
+ var p = 0;
+
+ var len = data.length;
+ chunk[p] = len >> 24 & 0xff;
+ chunk[p + 1] = len >> 16 & 0xff;
+ chunk[p + 2] = len >> 8 & 0xff;
+ chunk[p + 3] = len & 0xff;
+
+ chunk[p + 4] = type.charCodeAt(0) & 0xff;
+ chunk[p + 5] = type.charCodeAt(1) & 0xff;
+ chunk[p + 6] = type.charCodeAt(2) & 0xff;
+ chunk[p + 7] = type.charCodeAt(3) & 0xff;
+
+ chunk.set(data, 8);
+
+ p = 8 + len;
+
+ var crc = crc32(chunk, 4, p);
+ chunk[p] = crc >> 24 & 0xff;
+ chunk[p + 1] = crc >> 16 & 0xff;
+ chunk[p + 2] = crc >> 8 & 0xff;
+ chunk[p + 3] = crc & 0xff;
+
+ return chunk;
+ }
+
+ function adler32(data, start, end) {
+ var a = 1;
+ var b = 0;
+ for (var i = start; i < end; ++i) {
+ a = (a + (data[i] & 0xff)) % 65521;
+ b = (b + a) % 65521;
+ }
+ return (b << 16) | a;
+ }
+
+ function encode(imgData, kind) {
+ var width = imgData.width;
+ var height = imgData.height;
+ var bitDepth;
+ var colorType;
+
+ var bytes = imgData.data;
+ var lineSize;
+ switch (kind) {
+ case ImageKind.GRAYSCALE_1BPP:
+ colorType = 0;
+ bitDepth = 1;
+ lineSize = (width + 7) >> 3;
+ break;
+ case ImageKind.RGB_24BPP:
+ colorType = 2;
+ bitDepth = 8;
+ lineSize = width * 3;
+ break;
+ case ImageKind.RGBA_32BPP:
+ colorType = 6;
+ bitDepth = 8;
+ lineSize = width * 4;
+ break;
+ default:
+ throw new Error('invalid format');
+ }
+
+ var literals = new Uint8Array((1 + lineSize) * height);
+ var offsetLiterals = 0, offsetBytes = 0;
+ for (var y = 0; y < height; ++y) {
+ literals[offsetLiterals++] = 0;
+ literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize),
+ offsetLiterals);
+ offsetBytes += lineSize;
+ offsetLiterals += lineSize;
+ }
+ if (kind === ImageKind.GRAYSCALE_1BPP) {
+ for (var i = 0, ii = bytes.length; i < ii; i++) {
+ bytes[i] ^= 0xFF;
+ }
+ }
+
+ var ihdr = new Uint8Array([
+ width >> 24 & 0xff,
+ width >> 16 & 0xff,
+ width >> 8 & 0xff,
+ width & 0xff,
+ height >> 24 & 0xff,
+ height >> 16 & 0xff,
+ height >> 8 & 0xff,
+ height & 0xff,
+ bitDepth, // bit depth
+ colorType, // color type
+ 0x00, // compression method
+ 0x00, // filter method
+ 0x00 // interlace method
+ ]);
+
+ var len = literals.length;
+ var maxBlockLength = 0xFFFF;
+
+ var idat = new Uint8Array(2 + len +
+ Math.ceil(len / maxBlockLength) * 5 + 4);
+ var pi = 0;
+ idat[pi++] = 0x78; // compression method and flags
+ idat[pi++] = 0x9c; // flags
+
+ var pos = 0;
+ while (len > maxBlockLength) {
+ idat[pi++] = 0x00;
+ idat[pi++] = 0xff;
+ idat[pi++] = 0xff;
+ idat[pi++] = 0x00;
+ idat[pi++] = 0x00;
+ idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
+ pi += maxBlockLength;
+ pos += maxBlockLength;
+ len -= maxBlockLength;
+ }
+
+ idat[pi++] = 0x01;
+ idat[pi++] = len & 0xff;
+ idat[pi++] = len >> 8 & 0xff;
+ idat[pi++] = (~len & 0xffff) & 0xff;
+ idat[pi++] = (~len & 0xffff) >> 8 & 0xff;
+
+ idat.set(literals.subarray(pos), pi);
+ pi += literals.length - pos;
+
+ var adler = adler32(literals, 0, literals.length); // checksum
+ idat[pi++] = adler >> 24 & 0xff;
+ idat[pi++] = adler >> 16 & 0xff;
+ idat[pi++] = adler >> 8 & 0xff;
+ idat[pi++] = adler & 0xff;
+
+ var chunks = [
+ new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
+ createPngChunk('IHDR', ihdr),
+ createPngChunk('IDAT', idat),
+ createPngChunk('IEND', new Uint8Array(0))
+ ];
+
+ var data = [];
+ for (var j = 0; j < 3; j++) {
+ data.push.apply(data, chunks[j]);
+ }
+ data = new Uint8Array(data);
+ return PDFJS.createObjectURL(data, 'image/png');
+ }
+
+ return function convertImgDataToPng(imgData) {
+ var kind = (imgData.kind === undefined ?
+ ImageKind.GRAYSCALE_1BPP : imgData.kind);
+ var url = encode(imgData, kind);
+ if (url) {
+ return url;
+ }
+ };
+})();
+
var SVGExtraState = (function SVGExtraStateClosure() {
function SVGExtraState(old) {
// Are soft masks and alpha values shapes or opacities?
@@ -70,6 +253,8 @@ var SVGExtraState = (function SVGExtraStateClosure() {
// Clipping
this.clipId = '';
this.pendingClip = false;
+
+ this.maskId = '';
}
SVGExtraState.prototype = {
@@ -109,7 +294,6 @@ function opListToTree(opList) {
return opTree;
}
-
var SVGGraphics = (function SVGGraphicsClosure(ctx) {
function SVGGraphics(commonObjs, objs) {
@@ -130,6 +314,7 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) {
var NORMAL_CLIP = {};
var EO_CLIP = {};
var clipCount = 0;
+ var maskCount = 0;
SVGGraphics.prototype = {
save: function SVGGraphics_save() {
@@ -211,7 +396,8 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) {
this.pgrp.appendChild(this.tgrp);
this.svg.appendChild(this.pgrp);
this.container.appendChild(this.svg);
- this.convertOpList(operatorList);
+ var opTree = this.convertOpList(operatorList);
+ this.executeOpTree(opTree);
},
convertOpList: function SVGGraphics_convertOpList(operatorList) {
@@ -233,8 +419,6 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) {
opList.push({'fnId' : fnId, 'fn': REVOPS[fnId], 'args': argsArray[x]});
}
opTree = opListToTree(opList);
-
- this.executeOpTree(opTree);
return opTree;
},
@@ -331,6 +515,15 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) {
case OPS.paintJpegXObject:
this.paintJpegXObject(args[0], args[1], args[2]);
break;
+ case OPS.paintImageXObject:
+ this.paintImageXObject(args[0]);
+ break;
+ case OPS.paintInlineImageXObject:
+ this.paintInlineImageXObject(args[0]);
+ break;
+ case OPS.paintImageMaskXObject:
+ this.paintImageMaskXObject(args[0]);
+ break;
case OPS.closePath:
this.closePath();
break;
@@ -635,6 +828,7 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) {
endPath: function SVGGraphics_endPath() {
var current = this.current;
if (current.pendingClip) {
+ this.cgrp.appendChild(this.tgrp);
this.pgrp.appendChild(this.cgrp);
} else {
this.pgrp.appendChild(this.tgrp);
@@ -657,6 +851,8 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) {
} else {
clipElement.setAttributeNS(null, 'clip-rule', 'nonzero');
}
+ this.clippath.setAttributeNS(null, 'transform',
+ 'matrix(' + this.transformMatrix + ')');
this.clippath.appendChild(clipElement);
this.defs.appendChild(this.clippath);
@@ -779,26 +975,97 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) {
this.tgrp.appendChild(rect);
},
- paintJpegXObject:
- function SVGGraphics_paintJpegXObject(objId, w, h) {
- var current = this.current;
- var imgObj = this.objs.get(objId);
- var imgEl = document.createElementNS(NS, 'svg:image');
- imgEl.setAttributeNS(XLINK_NS, 'href', imgObj.src);
- imgEl.setAttributeNS(null, 'width', imgObj.width + 'px');
- imgEl.setAttributeNS(null, 'height', imgObj.height + 'px');
- imgEl.setAttributeNS(null, 'x', 0);
- imgEl.setAttributeNS(null, 'y', -h);
- imgEl.setAttributeNS(null, 'transform', 'scale(' + 1 / w +
- ' ' + -1 / h + ')');
-
- this.tgrp.appendChild(imgEl);
- if (current.pendingClip) {
+ paintJpegXObject: function SVGGraphics_paintJpegXObject(objId, w, h) {
+ var current = this.current;
+ var imgObj = this.objs.get(objId);
+ var imgEl = document.createElementNS(NS, 'svg:image');
+ imgEl.setAttributeNS(XLINK_NS, 'href', imgObj.src);
+ imgEl.setAttributeNS(null, 'width', imgObj.width + 'px');
+ imgEl.setAttributeNS(null, 'height', imgObj.height + 'px');
+ imgEl.setAttributeNS(null, 'x', 0);
+ imgEl.setAttributeNS(null, 'y', -h);
+ imgEl.setAttributeNS(null, 'transform', 'scale(' + 1 / w +
+ ' ' + -1 / h + ')');
+
+ this.tgrp.appendChild(imgEl);
+ if (current.pendingClip) {
+ this.cgrp.appendChild(this.tgrp);
+ this.pgrp.appendChild(this.cgrp);
+ } else {
+ this.pgrp.appendChild(this.tgrp);
+ }
+ },
+
+ paintImageXObject: function SVGGraphics_paintImageXObject(objId) {
+ var imgData = this.objs.get(objId);
+ if (!imgData) {
+ warn('Dependent image isn\'t ready yet');
+ return;
+ }
+
+ this.paintInlineImageXObject(imgData);
+ },
+
+ paintInlineImageXObject:
+ function SVGGraphics_paintInlineImageXObject(imgData, mask) {
+ var current = this.current;
+ var width = imgData.width;
+ var height = imgData.height;
+
+ var imgSrc = convertImgDataToPng(imgData);
+ var cliprect = document.createElementNS(NS, 'svg:rect');
+ cliprect.setAttributeNS(null, 'x', 0);
+ cliprect.setAttributeNS(null, 'y', 0);
+ cliprect.setAttributeNS(null, 'width', width);
+ cliprect.setAttributeNS(null, 'height', height);
+ current.element = cliprect;
+ this.clip('nonzero');
+ var imgEl = document.createElementNS(NS, 'svg:image');
+ imgEl.setAttributeNS(XLINK_NS, 'href', imgSrc);
+ imgEl.setAttributeNS(null, 'x', 0);
+ imgEl.setAttributeNS(null, 'y', -height);
+ imgEl.setAttributeNS(null, 'width', width + 'px');
+ imgEl.setAttributeNS(null, 'height', height + 'px');
+ imgEl.setAttributeNS(null, 'transform', 'scale(' + (1 / width) +
+ ', ' + (-1 / height) + ')');
+ if (mask) {
+ mask.appendChild(imgEl);
+ } else {
+ this.tgrp.appendChild(imgEl);
+ }
+ if (current.pendingClip) {
this.cgrp.appendChild(this.tgrp);
this.pgrp.appendChild(this.cgrp);
- } else {
+ } else {
this.pgrp.appendChild(this.tgrp);
- }
+ }
+ },
+
+ paintImageMaskXObject:
+ function SVGGraphics_paintImageMaskXObject(imgData) {
+ var current = this.current;
+
+ var width = imgData.width;
+ var height = imgData.height;
+
+ var img = convertImgDataToPng(imgData);
+ var fillColor = current.fillColor;
+
+ current.maskId = 'mask' + maskCount++;
+ var mask = document.createElementNS(NS, 'svg:mask');
+ mask.setAttributeNS(null, 'id', current.maskId);
+
+ var rect = document.createElementNS(NS, 'svg:rect');
+ rect.setAttributeNS(null, 'x', 0);
+ rect.setAttributeNS(null, 'y', 0);
+ rect.setAttributeNS(null, 'width', width);
+ rect.setAttributeNS(null, 'height', height);
+ rect.setAttributeNS(null, 'fill', fillColor);
+ rect.setAttributeNS(null, 'mask', 'url(#' + current.maskId +')');
+ this.defs.appendChild(mask);
+ this.tgrp.appendChild(rect);
+
+ this.paintInlineImageXObject(imgData, mask);
},
};
return SVGGraphics;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git
More information about the Pkg-javascript-commits
mailing list