|
|
@ -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); |
|
|
@ -2580,8 +2706,8 @@ var CanvasGraphics = (function() { |
|
|
|
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
|
|
|
|
// 10 samples seems good enough for now, but probably won't work
|
|
|
|
// if there are sharp color changes. Ideally, we could see the
|
|
|
|
// if there are sharp color changes. Ideally, we would implement
|
|
|
|
// current image size and base the # samples on that.
|
|
|
|
// 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) { |
|
|
@ -2594,8 +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
|
|
|
|
// Also, larger numbers seem to cause overflow which causes
|
|
|
|
// The following bug should allow us to remove this.
|
|
|
|
// nothing to be drawn.
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=664884
|
|
|
|
this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); |
|
|
|
this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|