Merge pull request #19 from sbarman/tiling

Tiling
This commit is contained in:
Chris Jones 2011-06-20 14:51:33 -07:00
commit 3b876cecb5

134
pdf.js
View File

@ -1782,6 +1782,7 @@ var CanvasExtraState = (function() {
this.fontSize = 0.0; this.fontSize = 0.0;
this.textMatrix = IDENTITY_MATRIX; this.textMatrix = IDENTITY_MATRIX;
this.leading = 0.0; this.leading = 0.0;
this.colorSpace = null;
// Current point (in user coordinates) // Current point (in user coordinates)
this.x = 0.0; this.x = 0.0;
this.y = 0.0; this.y = 0.0;
@ -2076,6 +2077,9 @@ var CanvasGraphics = (function() {
const NORMAL_CLIP = {}; const NORMAL_CLIP = {};
const EO_CLIP = {}; const EO_CLIP = {};
// Used for tiling patterns
const PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
constructor.prototype = { constructor.prototype = {
translateFont: function(fontDict, xref, resources) { translateFont: function(fontDict, xref, resources) {
var descriptor = xref.fetch(fontDict.get("FontDescriptor")); var descriptor = xref.fetch(fontDict.get("FontDescriptor"));
@ -2467,6 +2471,10 @@ var CanvasGraphics = (function() {
}, },
setFillColorSpace: function(space) { setFillColorSpace: function(space) {
// TODO real impl // TODO real impl
if (space.name === "Pattern")
this.current.colorSpace = "Pattern";
else
this.current.colorSpace = "DeviceRGB";
}, },
setStrokeColor: function(/*...*/) { setStrokeColor: function(/*...*/) {
// TODO real impl // TODO real impl
@ -2490,7 +2498,125 @@ var CanvasGraphics = (function() {
}, },
setFillColorN: function(/*...*/) { setFillColorN: function(/*...*/) {
// TODO real impl // TODO real impl
this.setFillColor.apply(this, arguments); var colorSpace = this.current.colorSpace;
if (!colorSpace) {
var stateStack = this.stateStack;
var i = stateStack.length - 1;
while (!colorSpace && i >= 0) {
colorSpace = stateStack[i--].colorSpace;
}
}
if (this.current.colorSpace == "Pattern") {
var patternName = arguments[0];
if (IsName(patternName)) {
var xref = this.xref;
var patternRes = xref.fetchIfRef(this.res.get("Pattern"));
if (!patternRes)
error("Unable to find pattern resource");
var pattern = xref.fetchIfRef(patternRes.get(patternName.name));
const types = [null, this.tilingFill];
var typeNum = pattern.dict.get("PatternType");
var patternFn = types[typeNum];
if (!patternFn)
error("Unhandled pattern type");
patternFn.call(this, pattern);
}
} else {
// TODO real impl
this.setFillColor.apply(this, arguments);
}
},
tilingFill: function(pattern) {
function applyMatrix(point, m) {
var x = point[0] * m[0] + point[1] * m[2] + m[4];
var y = point[0] * m[1] + point[1] * m[3] + m[5];
return [x,y];
};
function multiply(m, tm) {
var a = m[0] * tm[0] + m[1] * tm[2];
var b = m[0] * tm[1] + m[1] * tm[3];
var c = m[2] * tm[0] + m[3] * tm[2];
var d = m[2] * tm[1] + m[3] * tm[3];
var e = m[4] * tm[0] + m[5] * tm[2] + tm[4];
var f = m[4] * tm[1] + m[5] * tm[3] + tm[5];
return [a, b, c, d, e, f]
};
this.save();
var dict = pattern.dict;
var ctx = this.ctx;
var paintType = dict.get("PaintType");
switch (paintType) {
case PAINT_TYPE_COLORED:
// should go to default for color space
ctx.fillStyle = this.makeCssRgb(1, 1, 1);
ctx.strokeStyle = this.makeCssRgb(0, 0, 0);
break;
case PAINT_TYPE_UNCOLORED:
default:
error("Unsupported paint type");
}
TODO("TilingType");
var matrix = dict.get("Matrix") || IDENTITY_MATRIX;
var bbox = dict.get("BBox");
var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
var xstep = dict.get("XStep");
var ystep = dict.get("YStep");
// top left corner should correspond to the top left of the bbox
var topLeft = applyMatrix([x0,y0], matrix);
// we want the canvas to be as large as the step size
var botRight = applyMatrix([x0 + xstep, y0 + ystep], matrix);
var tmpCanvas = document.createElement("canvas");
tmpCanvas.width = Math.ceil(botRight[0] - topLeft[0]);
tmpCanvas.height = Math.ceil(botRight[1] - topLeft[1]);
// set the new canvas element context as the graphics context
var tmpCtx = tmpCanvas.getContext("2d");
var savedCtx = ctx;
this.ctx = tmpCtx;
// normalize transform matrix so each step
// takes up the entire tmpCanvas (need to remove white borders)
if (matrix[1] === 0 && matrix[2] === 0) {
matrix[0] = tmpCanvas.width / xstep;
matrix[3] = tmpCanvas.height / ystep;
topLeft = applyMatrix([x0,y0], matrix);
}
// move the top left corner of bounding box to [0,0]
matrix = multiply(matrix, [1, 0, 0, 1, -topLeft[0], -topLeft[1]]);
this.transform.apply(this, matrix);
if (bbox && IsArray(bbox) && 4 == bbox.length) {
this.rectangle.apply(this, bbox);
this.clip();
this.endPath();
}
var xref = this.xref;
var res = xref.fetchIfRef(dict.get("Resources"));
if (!pattern.code)
pattern.code = this.compile(pattern, xref, res, []);
this.execute(pattern.code, xref, res);
this.ctx = savedCtx;
this.restore();
TODO("Inverse pattern is painted");
var pattern = this.ctx.createPattern(tmpCanvas, "repeat");
this.ctx.fillStyle = pattern;
}, },
setStrokeGray: function(gray) { setStrokeGray: function(gray) {
this.setStrokeRGBColor(gray, gray, gray); this.setStrokeRGBColor(gray, gray, gray);
@ -2578,6 +2704,10 @@ var CanvasGraphics = (function() {
var fn = new PDFFunction(this.xref, fnObj); var fn = new PDFFunction(this.xref, fnObj);
var gradient = this.ctx.createLinearGradient(x0, y0, x1, y1); var gradient = this.ctx.createLinearGradient(x0, y0, x1, y1);
// 10 samples seems good enough for now, but probably won't work
// if there are sharp color changes. Ideally, we would implement
// the spec faithfully and add lossless optimizations.
var step = (t1 - t0) / 10; var step = (t1 - t0) / 10;
for (var i = t0; i <= t1; i += step) { for (var i = t0; i <= t1; i += step) {
@ -2590,6 +2720,8 @@ var CanvasGraphics = (function() {
// HACK to draw the gradient onto an infinite rectangle. // HACK to draw the gradient onto an infinite rectangle.
// PDF gradients are drawn across the entire image while // PDF gradients are drawn across the entire image while
// Canvas only allows gradients to be drawn in a rectangle // Canvas only allows gradients to be drawn in a rectangle
// The following bug should allow us to remove this.
// https://bugzilla.mozilla.org/show_bug.cgi?id=664884
this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
}, },