From da845ec5e6345bff293819a22d3f4edcf0a09034 Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Wed, 13 Jul 2011 11:41:04 -0700 Subject: [PATCH 01/12] git radial gradients working --- pdf.js | 194 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 137 insertions(+), 57 deletions(-) diff --git a/pdf.js b/pdf.js index a4c10fef7..452304d12 100644 --- a/pdf.js +++ b/pdf.js @@ -3793,7 +3793,7 @@ var PartialEvaluator = (function() { // <canvas> contexts store most of the state we need natively. // However, PDF needs a bit more state, which we store here. var CanvasExtraState = (function() { - function constructor() { + function constructor(old) { // Are soft masks and alpha values shapes or opacities? this.alphaIsShape = false; this.fontSize = 0; @@ -3810,10 +3810,70 @@ var CanvasExtraState = (function() { this.wordSpace = 0; this.textHScale = 100; // Color spaces - this.fillColorSpace = null; - this.strokeColorSpace = null; + this.fillColorSpaceObj = null; + this.strokeColorSpaceObj = null; + this.fillColorObj = null; + this.strokeColorObj = null; + + this.old = old; } constructor.prototype = { + get fillColorSpace() { + var cs = this.fillColorSpaceObj; + if (cs) + return cs; + + var old = this.old; + if (old) + return old.fillColorSpace; + + return null; + }, + set fillColorSpace(cs) { + this.fillColorSpaceObj = cs; + }, + get strokeColorSpace() { + var cs = this.strokeColorSpaceObj; + if (cs) + return cs; + + var old = this.old; + if (old) + return old.strokeColorSpace; + + return null; + }, + set strokeColorSpace(cs) { + this.strokeColorSpaceObj = cs; + }, + get fillColor() { + var color = this.fillColorObj; + if (color) + return color; + + var old = this.old; + if (old) + return old.fillColor; + + return null; + }, + set fillColor(color) { + this.fillColorObj = color; + }, + get strokeColor() { + var color = this.strokeColorObj; + if (color) + return color; + + var old = this.old; + if (old) + return old.strokeColor; + + return null; + }, + set strokeColor(color) { + this.strokeColorObj = color; + } }; return constructor; })(); @@ -3906,8 +3966,9 @@ var CanvasGraphics = (function() { if (this.ctx.$saveCurrentX) { this.ctx.$saveCurrentX(); } - this.stateStack.push(this.current); - this.current = new CanvasExtraState(); + var old = this.current; + this.stateStack.push(old); + this.current = new CanvasExtraState(old); }, restore: function() { var prev = this.stateStack.pop(); @@ -3954,7 +4015,16 @@ var CanvasGraphics = (function() { this.stroke(); }, fill: function() { - this.ctx.fill(); + var ctx = this.ctx; + var fillColor = this.current.fillColor; + + if (fillColor.type === "Pattern") { + this.ctx.fillStyle = fillColor.patternFn.apply(this, ctx); + ctx.fill(); + } else { + ctx.fill(); + } + this.consumePath(); }, eoFill: function() { @@ -3963,8 +4033,14 @@ var CanvasGraphics = (function() { this.restoreFillRule(savedFillRule); }, fillStroke: function() { - this.ctx.fill(); - this.ctx.stroke(); + var ctx = this.ctx; + var fillCS = this.current.fillColorSpace; + + if (fillCS && fillCS.name === "Pattern") + this.current.fillPattern(ctx); + + ctx.fill(); + ctx.stroke(); this.consumePath(); }, eoFillStroke: function() { @@ -4143,12 +4219,12 @@ var CanvasGraphics = (function() { ColorSpace.parse(space, this.xref, this.res); }, setStrokeColor: function(/*...*/) { - var cs = this.getStrokeColorSpace(); + var cs = this.current.strokeColorSpace; var color = cs.getRgb(arguments); this.setStrokeRGBColor.apply(this, color); }, setStrokeColorN: function(/*...*/) { - var cs = this.getStrokeColorSpace(); + var cs = this.current.strokeColorSpace; if (cs.name == 'Pattern') { this.ctx.strokeStyle = this.getPattern(cs, arguments); @@ -4157,15 +4233,19 @@ var CanvasGraphics = (function() { } }, setFillColor: function(/*...*/) { - var cs = this.getFillColorSpace(); + var cs = this.current.fillColorSpace; var color = cs.getRgb(arguments); this.setFillRGBColor.apply(this, color); }, setFillColorN: function(/*...*/) { - var cs = this.getFillColorSpace(); + var cs = this.current.fillColorSpace; if (cs.name == 'Pattern') { - this.ctx.fillStyle = this.getPattern(cs, arguments); + // return a set of functions which will set the pattern + // when fill is called + var pattern = this.getPattern(cs, arguments); + this.current.fillColor = pattern; + this.current.fillColor.type = "Pattern"; } else { this.setFillColor.apply(this, arguments); } @@ -4210,9 +4290,9 @@ var CanvasGraphics = (function() { this.transform.apply(this, matrix); var shading = this.getShading(pattern.get("Shading")); this.restore(); - - TODO('store transform so it can be applied before every fill'); return shading; + // TODO('store transform so it can be applied before every fill'); + // return shading; }, getTilingPattern: function(pattern, dict, color) { function multiply(m, tm) { @@ -4315,13 +4395,16 @@ var CanvasGraphics = (function() { this.ctx.strokeStyle = this.makeCssRgb(r, g, b); }, setFillRGBColor: function(r, g, b) { - this.ctx.fillStyle = this.makeCssRgb(r, g, b); + var color = this.makeCssRgb(r, g, b); + this.ctx.fillStyle = color; + this.current.fillColor = color; }, setStrokeCMYKColor: function(c, m, y, k) { this.ctx.strokeStyle = this.makeCssCmyk(c, m, y, k); }, setFillCMYKColor: function(c, m, y, k) { - this.ctx.fillStyle = this.makeCssCmyk(c, m, y, k); + var color = (new DeviceCmykCS()).getRgb([c, m, y, k]); + this.setFillRGBColor.apply(this, color); }, // Shading @@ -4341,7 +4424,7 @@ var CanvasGraphics = (function() { var shadingFill = this.getShading(shading); this.save(); - ctx.fillStyle = shadingFill; + ctx.fillStyle = shadingFill.patternFn.apply(this, ctx); var inv = ctx.mozCurrentTransformInverse; if (inv) { @@ -4455,8 +4538,6 @@ var CanvasGraphics = (function() { }, getRadialShading: function(sh, cs) { var coordsArr = sh.get('Coords'); - var x0 = coordsArr[0], y0 = coordsArr[1], r0 = coordsArr[2]; - var x1 = coordsArr[3], y1 = coordsArr[4], r1 = coordsArr[5]; var t0 = 0.0, t1 = 1.0; if (sh.has('Domain')) { @@ -4478,22 +4559,51 @@ var CanvasGraphics = (function() { error('Invalid function'); var fn = new PDFFunction(this.xref, fnObj); - var gradient = - this.ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); - // 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 diff = t1 - t0; + var colorStops = []; for (var i = t0; i <= t1; i += step) { var color = fn.func([i]); - var rgbColor = cs.getRgb(color); - gradient.addColorStop((i - t0) / diff, - this.makeCssRgb.apply(this, rgbColor)); + var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color)); + colorStops.push([(i - t0) / diff, rgbColor]); + } + + var patternMatrix = this.ctx.mozCurrentTransform; + + return { + patternFn : function() { + var x0 = coordsArr[0], y0 = coordsArr[1], r0 = coordsArr[2]; + var x1 = coordsArr[3], y1 = coordsArr[4], r1 = coordsArr[5]; + + // if the browser supports getting the tranform matrix, convert + // gradient coordinates from pattern space to current user space + if (patternMatrix) { + var userMatrix = this.ctx.mozCurrentTransformInverse; + + var p = this.applyTransform(x0, y0, patternMatrix); + p = this.applyTransform(p[0], p[1], userMatrix); + x0 = p[0]; + y0 = p[1]; + + var p = this.applyTransform(x1, y1, patternMatrix); + p = this.applyTransform(p[0], p[1], userMatrix); + x1 = p[0]; + y1 = p[1]; + } + + var gradient = + this.ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); + for (var i = 0, ii = colorStops.length; i < ii; ++i) { + var c = colorStops[i]; + gradient.addColorStop(c[0], c[1]); + } + return gradient; + } } - return gradient; }, // Images @@ -4645,36 +4755,6 @@ var CanvasGraphics = (function() { var bi = (255 * (1 - Math.min(1, y * (1 - k) + k))) | 0; return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; }, - getFillColorSpace: function() { - var cs = this.current.fillColorSpace; - if (cs) - return cs; - - var states = this.stateStack; - var i = states.length - 1; - while (i >= 0 && !(cs = states[i].fillColorSpace)) - --i; - - if (cs) - return cs; - else - return new DeviceRgbCS(); - }, - getStrokeColorSpace: function() { - var cs = this.current.strokeColorSpace; - if (cs) - return cs; - - var states = this.stateStack; - var i = states.length - 1; - while (i >= 0 && !(cs = states[i].strokeColorSpace)) - --i; - - if (cs) - return cs; - else - return new DeviceRgbCS(); - }, // We generally keep the canvas context set for // nonzero-winding, and just set evenodd for the operations // that need them. From 01d5e5579c0ff7fd6d8d277752478029555ca42c Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Wed, 13 Jul 2011 11:55:54 -0700 Subject: [PATCH 02/12] Changed linear gradients --- pdf.js | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/pdf.js b/pdf.js index 452304d12..6f2e0710f 100644 --- a/pdf.js +++ b/pdf.js @@ -4496,8 +4496,6 @@ var CanvasGraphics = (function() { }, getAxialShading: function(sh, cs) { var coordsArr = sh.get('Coords'); - var x0 = coordsArr[0], y0 = coordsArr[1], - x1 = coordsArr[2], y1 = coordsArr[3]; var t0 = 0.0, t1 = 1.0; if (sh.has('Domain')) { @@ -4519,22 +4517,51 @@ var CanvasGraphics = (function() { error('Invalid function'); var fn = new PDFFunction(this.xref, fnObj); - 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 diff = t1 - t0; + var colorStops = []; for (var i = t0; i <= t1; i += step) { var color = fn.func([i]); - var rgbColor = cs.getRgb(color); - gradient.addColorStop((i - t0) / diff, - this.makeCssRgb.apply(this, rgbColor)); + var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color)); + colorStops.push([(i - t0) / diff, rgbColor]); } + + var patternMatrix = this.ctx.mozCurrentTransform; - return gradient; + return { + patternFn : function() { + var x0 = coordsArr[0], y0 = coordsArr[1]; + var x1 = coordsArr[2], y1 = coordsArr[3]; + + // if the browser supports getting the tranform matrix, convert + // gradient coordinates from pattern space to current user space + if (patternMatrix) { + var userMatrix = this.ctx.mozCurrentTransformInverse; + + var p = this.applyTransform(x0, y0, patternMatrix); + p = this.applyTransform(p[0], p[1], userMatrix); + x0 = p[0]; + y0 = p[1]; + + var p = this.applyTransform(x1, y1, patternMatrix); + p = this.applyTransform(p[0], p[1], userMatrix); + x1 = p[0]; + y1 = p[1]; + } + + var gradient = + this.ctx.createLinearGradient(x0, y0, x1, y1); + for (var i = 0, ii = colorStops.length; i < ii; ++i) { + var c = colorStops[i]; + gradient.addColorStop(c[0], c[1]); + } + return gradient; + } + } }, getRadialShading: function(sh, cs) { var coordsArr = sh.get('Coords'); From 7986c35213d9cd1a657eeac43ec7ae76e54e9e9b Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Wed, 13 Jul 2011 15:43:09 -0700 Subject: [PATCH 03/12] fixed gradients, need to work on tiling --- pdf.js | 691 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 387 insertions(+), 304 deletions(-) diff --git a/pdf.js b/pdf.js index 6f2e0710f..2af03dce8 100644 --- a/pdf.js +++ b/pdf.js @@ -4019,7 +4019,7 @@ var CanvasGraphics = (function() { var fillColor = this.current.fillColor; if (fillColor.type === "Pattern") { - this.ctx.fillStyle = fillColor.patternFn.apply(this, ctx); + this.ctx.fillStyle = fillColor.getPattern(ctx); ctx.fill(); } else { ctx.fill(); @@ -4241,9 +4241,9 @@ var CanvasGraphics = (function() { var cs = this.current.fillColorSpace; if (cs.name == 'Pattern') { - // return a set of functions which will set the pattern - // when fill is called - var pattern = this.getPattern(cs, arguments); + // wait until fill to actually get the pattern + var pattern = Pattern.parse(cs, arguments, this.xref, this.res, + this.ctx); this.current.fillColor = pattern; this.current.fillColor.type = "Pattern"; } else { @@ -4251,139 +4251,12 @@ var CanvasGraphics = (function() { } }, getPattern: function(cs, args) { - var length = args.length; - var base = cs.base; - if (base) { - var baseComps = base.numComps; - - var color = []; - for (var i = 0; i < baseComps; ++i) - color.push(args[i]); - - color = base.getRgb(color); - } - - var patternName = args[length - 1]; - if (!IsName(patternName)) - error("Bad args to getPattern"); - - 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)); - var dict = IsStream(pattern) ? pattern.dict : pattern; - - var types = [null, this.getTilingPattern, this.getShadingPattern]; - - var typeNum = dict.get("PatternType"); - var patternFn = types[typeNum]; - if (!patternFn) - error("Unhandled pattern type"); - return patternFn.call(this, pattern, dict, color); }, getShadingPattern: function(pattern, dict) { - var matrix = dict.get("Matrix"); - - this.save(); - this.transform.apply(this, matrix); - var shading = this.getShading(pattern.get("Shading")); - this.restore(); - return shading; // TODO('store transform so it can be applied before every fill'); // return shading; }, getTilingPattern: function(pattern, dict, color) { - 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 ctx = this.ctx; - - - 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 = this.applyTransform(x0, y0, matrix); - // we want the canvas to be as large as the step size - var botRight = this.applyTransform(x0 + xstep, y0 + ystep, matrix); - - var width = botRight[0] - topLeft[0]; - var height = botRight[1] - topLeft[1]; - - // TODO: hack to avoid OOM, remove then pattern code is fixed - if (Math.abs(width) > 8192 || Math.abs(height) > 8192) { - this.restore(); - return 'hotpink'; - } - - var tmpCanvas = new this.ScratchCanvas(width, height); - - // set the new canvas element context as the graphics context - var tmpCtx = tmpCanvas.getContext('2d'); - var savedCtx = ctx; - this.ctx = tmpCtx; - - var paintType = dict.get('PaintType'); - switch (paintType) { - case PAINT_TYPE_COLORED: - tmpCtx.fillStyle = savedCtx.fillStyle; - tmpCtx.strokeStyle = savedCtx.strokeStyle; - break; - case PAINT_TYPE_UNCOLORED: - color = this.makeCssRgb.apply(this, color); - tmpCtx.fillStyle = color; - tmpCtx.strokeStyle = color; - break; - default: - error('Unsupported paint type'); - } - - // 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 = this.applyTransform(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(); - - return this.ctx.createPattern(tmpCanvas, 'repeat'); }, setStrokeGray: function(gray) { this.setStrokeRGBColor(gray, gray, gray); @@ -4421,10 +4294,10 @@ var CanvasGraphics = (function() { if (!shading) error('No shading object found'); - var shadingFill = this.getShading(shading); + var shadingFill = Pattern.parseShading(shading, null, xref, res, ctx); this.save(); - ctx.fillStyle = shadingFill.patternFn.apply(this, ctx); + ctx.fillStyle = shadingFill.getPattern(ctx); var inv = ctx.mozCurrentTransformInverse; if (inv) { @@ -4456,181 +4329,10 @@ var CanvasGraphics = (function() { this.restore(); }, getShading: function(shading) { - this.save(); - - shading = this.xref.fetchIfRef(shading); - var dict = IsStream(shading) ? shading.dict : shading; - - var bbox = dict.get('BBox'); - if (bbox && IsArray(bbox) && 4 == bbox.length) { - this.rectangle.apply(this, bbox); - this.clip(); - this.endPath(); - } - - var background = dict.get('Background'); - if (background) - TODO('handle background colors'); - - var cs = dict.get('ColorSpace', 'CS'); - cs = ColorSpace.parse(cs, this.xref, this.res); - - var types = [null, - null, - this.getAxialShading, - this.getRadialShading]; - - var typeNum = dict.get('ShadingType'); - var shadingFn = types[typeNum]; - - this.restore(); - - // Most likely we will not implement other types of shading - // unless the browser supports them - if (!shadingFn) { - warn("Unknown or NYI type of shading '"+ typeNum +"'"); - return 'hotpink'; - } - - return shadingFn.call(this, shading, cs); }, getAxialShading: function(sh, cs) { - var coordsArr = sh.get('Coords'); - - var t0 = 0.0, t1 = 1.0; - if (sh.has('Domain')) { - var domainArr = sh.get('Domain'); - t0 = domainArr[0], t1 = domainArr[1]; - } - - var extendStart = false, extendEnd = false; - if (sh.has('Extend')) { - var extendArr = sh.get('Extend'); - extendStart = extendArr[0], extendEnd = extendArr[1]; - TODO('Support extend'); - } - var fnObj = sh.get('Function'); - fnObj = this.xref.fetchIfRef(fnObj); - if (IsArray(fnObj)) - error('No support for array of functions'); - else if (!IsPDFFunction(fnObj)) - error('Invalid function'); - var fn = new PDFFunction(this.xref, fnObj); - - // 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 diff = t1 - t0; - - var colorStops = []; - for (var i = t0; i <= t1; i += step) { - var color = fn.func([i]); - var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color)); - colorStops.push([(i - t0) / diff, rgbColor]); - } - - var patternMatrix = this.ctx.mozCurrentTransform; - - return { - patternFn : function() { - var x0 = coordsArr[0], y0 = coordsArr[1]; - var x1 = coordsArr[2], y1 = coordsArr[3]; - - // if the browser supports getting the tranform matrix, convert - // gradient coordinates from pattern space to current user space - if (patternMatrix) { - var userMatrix = this.ctx.mozCurrentTransformInverse; - - var p = this.applyTransform(x0, y0, patternMatrix); - p = this.applyTransform(p[0], p[1], userMatrix); - x0 = p[0]; - y0 = p[1]; - - var p = this.applyTransform(x1, y1, patternMatrix); - p = this.applyTransform(p[0], p[1], userMatrix); - x1 = p[0]; - y1 = p[1]; - } - - var gradient = - this.ctx.createLinearGradient(x0, y0, x1, y1); - for (var i = 0, ii = colorStops.length; i < ii; ++i) { - var c = colorStops[i]; - gradient.addColorStop(c[0], c[1]); - } - return gradient; - } - } }, getRadialShading: function(sh, cs) { - var coordsArr = sh.get('Coords'); - - var t0 = 0.0, t1 = 1.0; - if (sh.has('Domain')) { - var domainArr = sh.get('Domain'); - t0 = domainArr[0], t1 = domainArr[1]; - } - - var extendStart = false, extendEnd = false; - if (sh.has('Extend')) { - var extendArr = sh.get('Extend'); - extendStart = extendArr[0], extendEnd = extendArr[1]; - TODO('Support extend'); - } - var fnObj = sh.get('Function'); - fnObj = this.xref.fetchIfRef(fnObj); - if (IsArray(fnObj)) - error('No support for array of functions'); - else if (!IsPDFFunction(fnObj)) - error('Invalid function'); - var fn = new PDFFunction(this.xref, fnObj); - - // 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 diff = t1 - t0; - - var colorStops = []; - for (var i = t0; i <= t1; i += step) { - var color = fn.func([i]); - var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color)); - colorStops.push([(i - t0) / diff, rgbColor]); - } - - var patternMatrix = this.ctx.mozCurrentTransform; - - return { - patternFn : function() { - var x0 = coordsArr[0], y0 = coordsArr[1], r0 = coordsArr[2]; - var x1 = coordsArr[3], y1 = coordsArr[4], r1 = coordsArr[5]; - - // if the browser supports getting the tranform matrix, convert - // gradient coordinates from pattern space to current user space - if (patternMatrix) { - var userMatrix = this.ctx.mozCurrentTransformInverse; - - var p = this.applyTransform(x0, y0, patternMatrix); - p = this.applyTransform(p[0], p[1], userMatrix); - x0 = p[0]; - y0 = p[1]; - - var p = this.applyTransform(x1, y1, patternMatrix); - p = this.applyTransform(p[0], p[1], userMatrix); - x1 = p[0]; - y1 = p[1]; - } - - var gradient = - this.ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); - for (var i = 0, ii = colorStops.length; i < ii; ++i) { - var c = colorStops[i]; - gradient.addColorStop(c[0], c[1]); - } - return gradient; - } - } }, // Images @@ -4832,6 +4534,8 @@ var ColorSpace = (function() { } } + if (!xref.fetchIfRef) + console.log("blah"); cs = xref.fetchIfRef(cs); if (IsName(cs)) { @@ -5154,6 +4858,385 @@ var DeviceCmykCS = (function() { return constructor; })(); +var Pattern = (function() { + // Constructor should define this.getPattern + function constructor() { + error('should not call Pattern constructor'); + }; + + constructor.prototype = { + // Input: current Canvas context + // Output: the appropriate fillStyle or strokeStyle + getPattern: function pattern_getStyle(ctx) { + error('Should not call Pattern.getStyle'); + }, + }; + + constructor.parse = function pattern_parse(cs, args, xref, res, ctx) { + var length = args.length; + + var patternName = args[length - 1]; + if (!IsName(patternName)) + error("Bad args to getPattern"); + + var patternRes = xref.fetchIfRef(res.get("Pattern")); + if (!patternRes) + error("Unable to find pattern resource"); + + var pattern = xref.fetchIfRef(patternRes.get(patternName.name)); + var dict = IsStream(pattern) ? pattern.dict : pattern; + + var typeNum = dict.get("PatternType"); + + var matrix = dict.get('Matrix'); + var patMatrix = ctx.mozCurrentTransform; + if (patMatrix) { + if (matrix) { + ctx.save(); + ctx.transform.apply(ctx, matrix); + patMatrix = ctx.mozCurrentTransform; + ctx.restore(); + } + } + + switch(typeNum) { + case 1: + var base = cs.base; + var color; + if (base) { + var baseComps = base.numComps; + + color = []; + for (var i = 0; i < baseComps; ++i) + color.push(args[i]); + + color = base.getRgb(color); + } + return new TilingPattern(pattern, dict, color); + break; + case 2: + var shading = xref.fetchIfRef(pattern.get('Shading')); + return Pattern.parseShading(shading, patMatrix, xref, res, ctx); + default: + error('Unknown type of pattern'); + } + }; + + constructor.parseShading = function pattern_shading(shading, patMatrix, + xref, res, ctx) { + + var dict = IsStream(shading) ? shading.dict : shading; + + var bbox = dict.get('BBox'); + var bg = dict.get('Background'); + + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + + var type = dict.get('ShadingType'); + + switch (type) { + case 2: + return new AxialShading(dict, patMatrix, bbox, cs, bg, xref); + break; + case 3: + return new RadialShading(dict, patMatrix, bbox, cs, bg, xref); + break; + default: + return new DummyShading(); + } + } + return constructor; +})(); + +var AxialShading = (function() { + function constructor(dict, patternMatrix, bbox, cs, background, xref) { + this.bbox = bbox; + this.cs = cs; + this.background = background; + this.patternMatrix = patternMatrix; + + this.coordsArr = dict.get('Coords'); + + var t0 = 0.0, t1 = 1.0; + if (dict.has('Domain')) { + var domainArr = dict.get('Domain'); + t0 = domainArr[0], t1 = domainArr[1]; + } + + var extendStart = false, extendEnd = false; + if (dict.has('Extend')) { + var extendArr = dict.get('Extend'); + extendStart = extendArr[0], extendEnd = extendArr[1]; + TODO('Support extend'); + } + + this.extendStart = extendStart; + this.extendEnd = extendEnd; + + var fnObj = dict.get('Function'); + fnObj = xref.fetchIfRef(fnObj); + if (IsArray(fnObj)) + error('No support for array of functions'); + else if (!IsPDFFunction(fnObj)) + error('Invalid function'); + var fn = new PDFFunction(xref, fnObj); + + // 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 diff = t1 - t0; + + var colorStops = []; + for (var i = t0; i <= t1; i += step) { + var color = fn.func([i]); + var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color)); + colorStops.push([(i - t0) / diff, rgbColor]); + } + + this.colorStops = colorStops; + }; + + constructor.prototype = { + getPattern: function(ctx) { + var coordsArr = this.coordsArr; + var x0 = coordsArr[0], y0 = coordsArr[1]; + var x1 = coordsArr[2], y1 = coordsArr[3]; + + // if the browser supports getting the tranform matrix, convert + // gradient coordinates from pattern space to current user space + var patternMatrix = this.patternMatrix; + if (patternMatrix) { + var userMatrix = ctx.mozCurrentTransformInverse; + + var p = this.applyTransform(x0, y0, patternMatrix); + p = this.applyTransform(p[0], p[1], userMatrix); + x0 = p[0]; + y0 = p[1]; + + var p = this.applyTransform(x1, y1, patternMatrix); + p = this.applyTransform(p[0], p[1], userMatrix); + x1 = p[0]; + y1 = p[1]; + } + + var colorStops = this.colorStops; + var gradient = + ctx.createLinearGradient(x0, y0, x1, y1); + for (var i = 0, ii = colorStops.length; i < ii; ++i) { + var c = colorStops[i]; + gradient.addColorStop(c[0], c[1]); + } + return gradient; + }, + applyTransform: function(x0, y0, m) { + var xt = x0 * m[0] + y0 * m[2] + m[4]; + var yt = x0 * m[1] + y0 * m[3] + m[5]; + return [xt, yt]; + }, + makeCssRgb: function(r, g, b) { + var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; + return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; + } + }; + return constructor; +})(); + +var RadialShading = (function() { + function constructor(dict, patternMatrix, bbox, cs, background, xref) { + this.bbox = bbox; + this.cs = cs; + this.background = background; + this.patternMatrix = patternMatrix; + + this.coordsArr = dict.get('Coords'); + + var t0 = 0.0, t1 = 1.0; + if (dict.has('Domain')) { + var domainArr = dict.get('Domain'); + t0 = domainArr[0], t1 = domainArr[1]; + } + + var extendStart = false, extendEnd = false; + if (dict.has('Extend')) { + var extendArr = dict.get('Extend'); + extendStart = extendArr[0], extendEnd = extendArr[1]; + TODO('Support extend'); + } + + this.extendStart = extendStart; + this.extendEnd = extendEnd; + + var fnObj = dict.get('Function'); + fnObj = xref.fetchIfRef(fnObj); + if (IsArray(fnObj)) + error('No support for array of functions'); + else if (!IsPDFFunction(fnObj)) + error('Invalid function'); + var fn = new PDFFunction(xref, fnObj); + + // 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 diff = t1 - t0; + + var colorStops = []; + for (var i = t0; i <= t1; i += step) { + var color = fn.func([i]); + var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color)); + colorStops.push([(i - t0) / diff, rgbColor]); + } + + this.colorStops = colorStops; + }; + + constructor.prototype = { + getPattern: function(ctx) { + var coordsArr = this.coordsArr; + var x0 = coordsArr[0], y0 = coordsArr[1], r0 = coordsArr[2]; + var x1 = coordsArr[3], y1 = coordsArr[4], r1 = coordsArr[5]; + + // if the browser supports getting the tranform matrix, convert + // gradient coordinates from pattern space to current user space + var patternMatrix = this.patternMatrix; + if (patternMatrix) { + var userMatrix = ctx.mozCurrentTransformInverse; + + var p = this.applyTransform(x0, y0, patternMatrix); + p = this.applyTransform(p[0], p[1], userMatrix); + x0 = p[0]; + y0 = p[1]; + + var p = this.applyTransform(x1, y1, patternMatrix); + p = this.applyTransform(p[0], p[1], userMatrix); + x1 = p[0]; + y1 = p[1]; + } + + var colorStops = this.colorStops; + var gradient = + ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); + for (var i = 0, ii = colorStops.length; i < ii; ++i) { + var c = colorStops[i]; + gradient.addColorStop(c[0], c[1]); + } + return gradient; + }, + applyTransform: function(x0, y0, m) { + var xt = x0 * m[0] + y0 * m[2] + m[4]; + var yt = x0 * m[1] + y0 * m[3] + m[5]; + return [xt, yt]; + }, + makeCssRgb: function(r, g, b) { + var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; + return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; + } + }; + + return constructor; +})(); + +var TilingPattern = (function() { + function constructor(tiling) { + 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 ctx = this.ctx; + + + 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 = this.applyTransform(x0, y0, matrix); + // we want the canvas to be as large as the step size + var botRight = this.applyTransform(x0 + xstep, y0 + ystep, matrix); + + var width = botRight[0] - topLeft[0]; + var height = botRight[1] - topLeft[1]; + + // TODO: hack to avoid OOM, remove then pattern code is fixed + if (Math.abs(width) > 8192 || Math.abs(height) > 8192) { + this.restore(); + return 'hotpink'; + } + + var tmpCanvas = new this.ScratchCanvas(width, height); + + // set the new canvas element context as the graphics context + var tmpCtx = tmpCanvas.getContext('2d'); + var savedCtx = ctx; + this.ctx = tmpCtx; + + var paintType = dict.get('PaintType'); + switch (paintType) { + case PAINT_TYPE_COLORED: + tmpCtx.fillStyle = savedCtx.fillStyle; + tmpCtx.strokeStyle = savedCtx.strokeStyle; + break; + case PAINT_TYPE_UNCOLORED: + color = this.makeCssRgb.apply(this, color); + tmpCtx.fillStyle = color; + tmpCtx.strokeStyle = color; + break; + default: + error('Unsupported paint type'); + } + + // 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 = this.applyTransform(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(); + + return this.ctx.createPattern(tmpCanvas, 'repeat'); + }; + + constructor.prototype = { + }; + return constructor; +})(); + + var PDFImage = (function() { function constructor(xref, res, image, inline) { this.image = image; From 9dcac17a3e5e264011da0495fab9bcbc40c2b5b0 Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Thu, 14 Jul 2011 10:59:12 -0700 Subject: [PATCH 04/12] patterns working --- pdf.js | 364 ++++++++++++++++++++++----------------------------------- 1 file changed, 141 insertions(+), 223 deletions(-) diff --git a/pdf.js b/pdf.js index 2af03dce8..5ce4c47bd 100644 --- a/pdf.js +++ b/pdf.js @@ -2969,6 +2969,7 @@ var Page = (function() { var fonts = [ ]; this.compile(gfx, fonts); + fonts = [] stats.compile = Date.now(); FontLoader.bind( @@ -3901,9 +3902,6 @@ var CanvasGraphics = (function() { var NORMAL_CLIP = {}; var EO_CLIP = {}; - // Used for tiling patterns - var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; - constructor.prototype = { beginDrawing: function(mediaBox) { var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height; @@ -4019,11 +4017,9 @@ var CanvasGraphics = (function() { var fillColor = this.current.fillColor; if (fillColor.type === "Pattern") { - this.ctx.fillStyle = fillColor.getPattern(ctx); - ctx.fill(); - } else { - ctx.fill(); + ctx.fillStyle = fillColor.getPattern(ctx); } + ctx.fill(); this.consumePath(); }, @@ -4227,7 +4223,7 @@ var CanvasGraphics = (function() { var cs = this.current.strokeColorSpace; if (cs.name == 'Pattern') { - this.ctx.strokeStyle = this.getPattern(cs, arguments); + // this.ctx.strokeStyle = this.getPattern(cs, arguments); } else { this.setStrokeColor.apply(this, arguments); } @@ -4242,7 +4238,7 @@ var CanvasGraphics = (function() { if (cs.name == 'Pattern') { // wait until fill to actually get the pattern - var pattern = Pattern.parse(cs, arguments, this.xref, this.res, + var pattern = Pattern.parse(arguments, cs, this.xref, this.res, this.ctx); this.current.fillColor = pattern; this.current.fillColor.type = "Pattern"; @@ -4250,8 +4246,6 @@ var CanvasGraphics = (function() { this.setFillColor.apply(this, arguments); } }, - getPattern: function(cs, args) { - }, getShadingPattern: function(pattern, dict) { // TODO('store transform so it can be applied before every fill'); // return shading; @@ -4297,7 +4291,7 @@ var CanvasGraphics = (function() { var shadingFill = Pattern.parseShading(shading, null, xref, res, ctx); this.save(); - ctx.fillStyle = shadingFill.getPattern(ctx); + ctx.fillStyle = shadingFill.getPattern(); var inv = ctx.mozCurrentTransformInverse; if (inv) { @@ -4328,12 +4322,6 @@ var CanvasGraphics = (function() { this.restore(); }, - getShading: function(shading) { - }, - getAxialShading: function(sh, cs) { - }, - getRadialShading: function(sh, cs) { - }, // Images beginInlineImage: function() { @@ -4534,8 +4522,6 @@ var ColorSpace = (function() { } } - if (!xref.fetchIfRef) - console.log("blah"); cs = xref.fetchIfRef(cs); if (IsName(cs)) { @@ -4872,7 +4858,7 @@ var Pattern = (function() { }, }; - constructor.parse = function pattern_parse(cs, args, xref, res, ctx) { + constructor.parse = function pattern_parse(args, cs, xref, res, ctx) { var length = args.length; var patternName = args[length - 1]; @@ -4885,19 +4871,7 @@ var Pattern = (function() { var pattern = xref.fetchIfRef(patternRes.get(patternName.name)); var dict = IsStream(pattern) ? pattern.dict : pattern; - var typeNum = dict.get("PatternType"); - - var matrix = dict.get('Matrix'); - var patMatrix = ctx.mozCurrentTransform; - if (patMatrix) { - if (matrix) { - ctx.save(); - ctx.transform.apply(ctx, matrix); - patMatrix = ctx.mozCurrentTransform; - ctx.restore(); - } - } switch(typeNum) { case 1: @@ -4912,51 +4886,53 @@ var Pattern = (function() { color = base.getRgb(color); } - return new TilingPattern(pattern, dict, color); + return new TilingPattern(pattern, dict, color, xref, ctx); break; case 2: - var shading = xref.fetchIfRef(pattern.get('Shading')); - return Pattern.parseShading(shading, patMatrix, xref, res, ctx); + var shading = xref.fetchIfRef(dict.get('Shading')); + var matrix = dict.get('Matrix'); + return Pattern.parseShading(shading, matrix, xref, res, ctx); + break; default: error('Unknown type of pattern'); } }; - constructor.parseShading = function pattern_shading(shading, patMatrix, + constructor.parseShading = function pattern_shading(shading, matrix, xref, res, ctx) { var dict = IsStream(shading) ? shading.dict : shading; - - var bbox = dict.get('BBox'); - var bg = dict.get('Background'); - - var cs = dict.get('ColorSpace', 'CS'); - cs = ColorSpace.parse(cs, xref, res); - var type = dict.get('ShadingType'); switch (type) { case 2: - return new AxialShading(dict, patMatrix, bbox, cs, bg, xref); + return new SimpleShading(dict, matrix, xref, res, ctx); break; case 3: - return new RadialShading(dict, patMatrix, bbox, cs, bg, xref); + return new SimpleShading(dict, matrix, xref, res, ctx); break; default: - return new DummyShading(); + error('Unsupported shading'); } } return constructor; })(); -var AxialShading = (function() { - function constructor(dict, patternMatrix, bbox, cs, background, xref) { - this.bbox = bbox; - this.cs = cs; - this.background = background; - this.patternMatrix = patternMatrix; - +var SimpleShading = (function() { + function constructor(dict, matrix, xref, res, ctx) { + this.matrix = matrix; + var bbox = dict.get('BBox'); + var background = dict.get('Background'); this.coordsArr = dict.get('Coords'); + this.shadingType = dict.get('ShadingType'); + + this.ctx = ctx; + this.curMatrix = ctx.mozCurrentTransform; + console.log(ctx.mozCurrentTransform); + + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + this.cs = cs; var t0 = 0.0, t1 = 1.0; if (dict.has('Domain')) { @@ -4999,40 +4975,60 @@ var AxialShading = (function() { }; constructor.prototype = { - getPattern: function(ctx) { + getPattern: function() { var coordsArr = this.coordsArr; - var x0 = coordsArr[0], y0 = coordsArr[1]; - var x1 = coordsArr[2], y1 = coordsArr[3]; + var type = this.shadingType; + if (type == 2) { + var p0 = [coordsArr[0], coordsArr[1]]; + var p1 = [coordsArr[2], coordsArr[3]]; + } else if (type == 3) { + var p0 = [coordsArr[0], coordsArr[1]]; + var p1 = [coordsArr[3], coordsArr[4]]; + var r0 = coordsArr[2], r1 = coordsArr[5] + } else { + error() + } + + var matrix = this.matrix; + if (matrix) { + p0 = this.applyTransform(p0, matrix); + p1 = this.applyTransform(p1, matrix); + } // if the browser supports getting the tranform matrix, convert // gradient coordinates from pattern space to current user space - var patternMatrix = this.patternMatrix; - if (patternMatrix) { + var curMatrix = this.curMatrix; + var ctx = this.ctx; + if (curMatrix) { var userMatrix = ctx.mozCurrentTransformInverse; + console.log(p0 + ',' + p1); + console.log(curMatrix); + console.log(userMatrix); - var p = this.applyTransform(x0, y0, patternMatrix); - p = this.applyTransform(p[0], p[1], userMatrix); - x0 = p[0]; - y0 = p[1]; + p0 = this.applyTransform(p0, curMatrix); + p0 = this.applyTransform(p0, userMatrix); + console.log(p0); - var p = this.applyTransform(x1, y1, patternMatrix); - p = this.applyTransform(p[0], p[1], userMatrix); - x1 = p[0]; - y1 = p[1]; + p1 = this.applyTransform(p1, curMatrix); + p1 = this.applyTransform(p1, userMatrix); + console.log(p0 + ',' + p1); } var colorStops = this.colorStops; - var gradient = - ctx.createLinearGradient(x0, y0, x1, y1); + if (type == 2) + var grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]); + else if (type == 3) + var grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1); + for (var i = 0, ii = colorStops.length; i < ii; ++i) { var c = colorStops[i]; - gradient.addColorStop(c[0], c[1]); + grad.addColorStop(c[0], c[1]); } - return gradient; + return grad; }, - applyTransform: function(x0, y0, m) { - var xt = x0 * m[0] + y0 * m[2] + m[4]; - var yt = x0 * m[1] + y0 * m[3] + m[5]; + applyTransform: function(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; return [xt, yt]; }, makeCssRgb: function(r, g, b) { @@ -5043,63 +5039,85 @@ var AxialShading = (function() { return constructor; })(); -var RadialShading = (function() { - function constructor(dict, patternMatrix, bbox, cs, background, xref) { - this.bbox = bbox; - this.cs = cs; - this.background = background; - this.patternMatrix = patternMatrix; +var TilingPattern = (function() { + var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; + + function constructor(pattern, dict, color, patMatrix, xref, ctx) { + 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.coordsArr = dict.get('Coords'); - var t0 = 0.0, t1 = 1.0; - if (dict.has('Domain')) { - var domainArr = dict.get('Domain'); - t0 = domainArr[0], t1 = domainArr[1]; - } + TODO('TilingType'); - var extendStart = false, extendEnd = false; - if (dict.has('Extend')) { - var extendArr = dict.get('Extend'); - extendStart = extendArr[0], extendEnd = extendArr[1]; - TODO('Support extend'); - } + this.patMatrix = patMatrix; - this.extendStart = extendStart; - this.extendEnd = extendEnd; + var bbox = dict.get('BBox'); + var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3]; - var fnObj = dict.get('Function'); - fnObj = xref.fetchIfRef(fnObj); - if (IsArray(fnObj)) - error('No support for array of functions'); - else if (!IsPDFFunction(fnObj)) - error('Invalid function'); - var fn = new PDFFunction(xref, fnObj); + var xstep = dict.get('XStep'); + var ystep = dict.get('YStep'); - // 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 diff = t1 - t0; + var topLeft = [x0, y0]; + // we want the canvas to be as large as the step size + var botRight = [x0 + xstep, y0 + ystep] - var colorStops = []; - for (var i = t0; i <= t1; i += step) { - var color = fn.func([i]); - var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color)); - colorStops.push([(i - t0) / diff, rgbColor]); - } + var width = botRight[0] - topLeft[0]; + var height = botRight[1] - topLeft[1]; - this.colorStops = colorStops; + // TODO: hack to avoid OOM, remove then pattern code is fixed + while (Math.abs(width) > 8192 || Math.abs(height) > 8192) { + width /= 2; + height /= 2; + } + + var tmpCanvas = new ScratchCanvas(width, height); + + // set the new canvas element context as the graphics context + var tmpCtx = tmpCanvas.getContext('2d'); + var graphics = new CanvasGraphics(tmpCtx); + + var paintType = dict.get('PaintType'); + switch (paintType) { + case PAINT_TYPE_COLORED: + tmpCtx.fillStyle = ctx.fillStyle; + tmpCtx.strokeStyle = ctx.strokeStyle; + break; + case PAINT_TYPE_UNCOLORED: + color = this.makeCssRgb.apply(this, color); + tmpCtx.fillStyle = color; + tmpCtx.strokeStyle = color; + break; + default: + error('Unsupported paint type'); + } + + // transform coordinates to pattern space + var tmpTransform = [width / xstep, 0, 0, height / ystep, -topLeft[0], -topLeft[1]]; + graphics.transform.apply(graphics, matrix); + + if (bbox && IsArray(bbox) && 4 == bbox.length) { + graphics.rectangle.apply(graphics, bbox); + graphics.clip(); + graphics.endPath(); + } + + var res = xref.fetchIfRef(dict.get('Resources')); + if (!pattern.code) + pattern.code = graphics.compile(pattern, xref, res, []); + graphics.execute(pattern.code, xref, res); + + this.canvas = tmpCanvas; }; constructor.prototype = { - getPattern: function(ctx) { - var coordsArr = this.coordsArr; - var x0 = coordsArr[0], y0 = coordsArr[1], r0 = coordsArr[2]; - var x1 = coordsArr[3], y1 = coordsArr[4], r1 = coordsArr[5]; - - // if the browser supports getting the tranform matrix, convert - // gradient coordinates from pattern space to current user space + getPattern: function tiling_getPattern(ctx) { var patternMatrix = this.patternMatrix; if (patternMatrix) { var userMatrix = ctx.mozCurrentTransformInverse; @@ -5118,11 +5136,10 @@ var RadialShading = (function() { var colorStops = this.colorStops; var gradient = ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); - for (var i = 0, ii = colorStops.length; i < ii; ++i) { + for (var i = 0, ii = colorStops.length; i < ii; ++i) var c = colorStops[i]; - gradient.addColorStop(c[0], c[1]); - } - return gradient; + ctx.transform.apply + return ctx.createPattern(this.canvas, 'repeat'); }, applyTransform: function(x0, y0, m) { var xt = x0 * m[0] + y0 * m[2] + m[4]; @@ -5134,105 +5151,6 @@ var RadialShading = (function() { return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; } }; - - return constructor; -})(); - -var TilingPattern = (function() { - function constructor(tiling) { - 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 ctx = this.ctx; - - - 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 = this.applyTransform(x0, y0, matrix); - // we want the canvas to be as large as the step size - var botRight = this.applyTransform(x0 + xstep, y0 + ystep, matrix); - - var width = botRight[0] - topLeft[0]; - var height = botRight[1] - topLeft[1]; - - // TODO: hack to avoid OOM, remove then pattern code is fixed - if (Math.abs(width) > 8192 || Math.abs(height) > 8192) { - this.restore(); - return 'hotpink'; - } - - var tmpCanvas = new this.ScratchCanvas(width, height); - - // set the new canvas element context as the graphics context - var tmpCtx = tmpCanvas.getContext('2d'); - var savedCtx = ctx; - this.ctx = tmpCtx; - - var paintType = dict.get('PaintType'); - switch (paintType) { - case PAINT_TYPE_COLORED: - tmpCtx.fillStyle = savedCtx.fillStyle; - tmpCtx.strokeStyle = savedCtx.strokeStyle; - break; - case PAINT_TYPE_UNCOLORED: - color = this.makeCssRgb.apply(this, color); - tmpCtx.fillStyle = color; - tmpCtx.strokeStyle = color; - break; - default: - error('Unsupported paint type'); - } - - // 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 = this.applyTransform(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(); - - return this.ctx.createPattern(tmpCanvas, 'repeat'); - }; - - constructor.prototype = { - }; return constructor; })(); From dc77e076c28e7abb776e9ddb6de101f95f167aeb Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Thu, 14 Jul 2011 11:50:27 -0700 Subject: [PATCH 05/12] Fixed tiling patterns --- pdf.js | 72 ++++++++++++++++++++++++---------------------------------- 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/pdf.js b/pdf.js index 5ce4c47bd..af0daeb41 100644 --- a/pdf.js +++ b/pdf.js @@ -2969,7 +2969,6 @@ var Page = (function() { var fonts = [ ]; this.compile(gfx, fonts); - fonts = [] stats.compile = Date.now(); FontLoader.bind( @@ -4017,9 +4016,13 @@ var CanvasGraphics = (function() { var fillColor = this.current.fillColor; if (fillColor.type === "Pattern") { + this.ctx.save(); ctx.fillStyle = fillColor.getPattern(ctx); + ctx.fill(); + this.ctx.restore(); + } else { + ctx.fill(); } - ctx.fill(); this.consumePath(); }, @@ -4246,12 +4249,6 @@ var CanvasGraphics = (function() { this.setFillColor.apply(this, arguments); } }, - getShadingPattern: function(pattern, dict) { - // TODO('store transform so it can be applied before every fill'); - // return shading; - }, - getTilingPattern: function(pattern, dict, color) { - }, setStrokeGray: function(gray) { this.setStrokeRGBColor(gray, gray, gray); }, @@ -4906,9 +4903,8 @@ var Pattern = (function() { switch (type) { case 2: - return new SimpleShading(dict, matrix, xref, res, ctx); - break; case 3: + // both radial and axial shadings are handled by simple shading return new SimpleShading(dict, matrix, xref, res, ctx); break; default: @@ -4928,7 +4924,6 @@ var SimpleShading = (function() { this.ctx = ctx; this.curMatrix = ctx.mozCurrentTransform; - console.log(ctx.mozCurrentTransform); var cs = dict.get('ColorSpace', 'CS'); cs = ColorSpace.parse(cs, xref, res); @@ -5001,17 +4996,12 @@ var SimpleShading = (function() { var ctx = this.ctx; if (curMatrix) { var userMatrix = ctx.mozCurrentTransformInverse; - console.log(p0 + ',' + p1); - console.log(curMatrix); - console.log(userMatrix); p0 = this.applyTransform(p0, curMatrix); p0 = this.applyTransform(p0, userMatrix); - console.log(p0); p1 = this.applyTransform(p1, curMatrix); p1 = this.applyTransform(p1, userMatrix); - console.log(p0 + ',' + p1); } var colorStops = this.colorStops; @@ -5042,7 +5032,7 @@ var SimpleShading = (function() { var TilingPattern = (function() { var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2; - function constructor(pattern, dict, color, patMatrix, xref, ctx) { + function constructor(pattern, dict, color, xref, ctx) { function multiply(m, tm) { var a = m[0] * tm[0] + m[1] * tm[2]; var b = m[0] * tm[1] + m[1] * tm[3]; @@ -5053,10 +5043,12 @@ var TilingPattern = (function() { return [a, b, c, d, e, f]; }; - TODO('TilingType'); - this.patMatrix = patMatrix; + this.matrix = dict.get("Matrix"); + this.curMatrix = ctx.mozCurrentTransform; + this.invMatrix = ctx.mozCurrentTransformInverse; + this.ctx = ctx; var bbox = dict.get('BBox'); var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3]; @@ -5072,9 +5064,9 @@ var TilingPattern = (function() { var height = botRight[1] - topLeft[1]; // TODO: hack to avoid OOM, remove then pattern code is fixed - while (Math.abs(width) > 8192 || Math.abs(height) > 8192) { - width /= 2; - height /= 2; + while (Math.abs(width) > 512 || Math.abs(height) > 512) { + width = 512; + height = 512; } var tmpCanvas = new ScratchCanvas(width, height); @@ -5098,9 +5090,14 @@ var TilingPattern = (function() { error('Unsupported paint type'); } + var scale = [width / xstep, height / ystep]; + this.scale = scale; + // transform coordinates to pattern space - var tmpTransform = [width / xstep, 0, 0, height / ystep, -topLeft[0], -topLeft[1]]; - graphics.transform.apply(graphics, matrix); + var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]]; + var tmpScale = [scale[0], 0, 0, scale[1], 0, 0]; + graphics.transform.apply(graphics, tmpScale); + graphics.transform.apply(graphics, tmpTranslate); if (bbox && IsArray(bbox) && 4 == bbox.length) { graphics.rectangle.apply(graphics, bbox); @@ -5118,27 +5115,18 @@ var TilingPattern = (function() { constructor.prototype = { getPattern: function tiling_getPattern(ctx) { - var patternMatrix = this.patternMatrix; - if (patternMatrix) { - var userMatrix = ctx.mozCurrentTransformInverse; + var matrix = this.matrix; + var curMatrix = this.curMatrix; - var p = this.applyTransform(x0, y0, patternMatrix); - p = this.applyTransform(p[0], p[1], userMatrix); - x0 = p[0]; - y0 = p[1]; + if (curMatrix) + ctx.setTransform.apply(ctx, curMatrix); - var p = this.applyTransform(x1, y1, patternMatrix); - p = this.applyTransform(p[0], p[1], userMatrix); - x1 = p[0]; - y1 = p[1]; - } + if (matrix) + ctx.transform.apply(ctx, matrix); + + var scale = this.scale; + ctx.scale(1 / scale[0], 1 / scale[1]); - var colorStops = this.colorStops; - var gradient = - ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); - for (var i = 0, ii = colorStops.length; i < ii; ++i) - var c = colorStops[i]; - ctx.transform.apply return ctx.createPattern(this.canvas, 'repeat'); }, applyTransform: function(x0, y0, m) { From faa6875b80b6d9513874960ce2e8a23869c46824 Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Fri, 15 Jul 2011 09:48:40 -0700 Subject: [PATCH 06/12] cleanup, add support for stroking --- pdf.js | 126 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/pdf.js b/pdf.js index af0daeb41..9a5944d5e 100644 --- a/pdf.js +++ b/pdf.js @@ -4226,7 +4226,10 @@ var CanvasGraphics = (function() { var cs = this.current.strokeColorSpace; if (cs.name == 'Pattern') { - // this.ctx.strokeStyle = this.getPattern(cs, arguments); + // wait until fill to actually get the pattern + var pattern = Pattern.parse(arguments, cs, this.xref, this.res, + this.ctx); + this.current.strokeColor = pattern; } else { this.setStrokeColor.apply(this, arguments); } @@ -4243,8 +4246,9 @@ var CanvasGraphics = (function() { // wait until fill to actually get the pattern var pattern = Pattern.parse(arguments, cs, this.xref, this.res, this.ctx); - this.current.fillColor = pattern; - this.current.fillColor.type = "Pattern"; +// this.current.fillColor = pattern; + this.ctx.fillStyle = pattern.getPattern(); + this.current.fillColor = "blah"; } else { this.setFillColor.apply(this, arguments); } @@ -4256,19 +4260,24 @@ var CanvasGraphics = (function() { this.setFillRGBColor(gray, gray, gray); }, setStrokeRGBColor: function(r, g, b) { - this.ctx.strokeStyle = this.makeCssRgb(r, g, b); + var color = Util.makeCssRgb(r, g, b); + this.ctx.strokeStyle = color; + this.current.fillColor = color; }, setFillRGBColor: function(r, g, b) { - var color = this.makeCssRgb(r, g, b); + var color = Util.makeCssRgb(r, g, b); this.ctx.fillStyle = color; this.current.fillColor = color; }, setStrokeCMYKColor: function(c, m, y, k) { - this.ctx.strokeStyle = this.makeCssCmyk(c, m, y, k); + var color = Util.makeCssCmyk(c, m, y, k); + this.ctx.strokeStyle = color; + this.current.fillColor = color; }, setFillCMYKColor: function(c, m, y, k) { - var color = (new DeviceCmykCS()).getRgb([c, m, y, k]); - this.setFillRGBColor.apply(this, color); + var color = Util.makeCssCmyk(c, m, y, k); + this.ctx.fillStyle = color; + this.current.fillColor = color; }, // Shading @@ -4296,10 +4305,10 @@ var CanvasGraphics = (function() { var width = canvas.width; var height = canvas.height; - var bl = this.applyTransform(0, 0, inv); - var br = this.applyTransform(0, width, inv); - var ul = this.applyTransform(height, 0, inv); - var ur = this.applyTransform(height, width, inv); + var bl = Util.applyTransform([0, 0], inv); + var br = Util.applyTransform([0, width], inv); + var ul = Util.applyTransform([height, 0], inv); + var ur = Util.applyTransform([height, width], inv); var x0 = Math.min(bl[0], br[0], ul[0], ur[0]); var y0 = Math.min(bl[1], br[1], ul[1], ur[1]); @@ -4457,18 +4466,6 @@ var CanvasGraphics = (function() { } this.ctx.beginPath(); }, - makeCssRgb: function(r, g, b) { - var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; - return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; - }, - makeCssCmyk: function(c, m, y, k) { - // while waiting on CSS's cmyk()... - // http://www.ilkeratalay.com/colorspacesfaq.php#rgb - var ri = (255 * (1 - Math.min(1, c * (1 - k) + k))) | 0; - var gi = (255 * (1 - Math.min(1, m * (1 - k) + k))) | 0; - var bi = (255 * (1 - Math.min(1, y * (1 - k) + k))) | 0; - return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; - }, // We generally keep the canvas context set for // nonzero-winding, and just set evenodd for the operations // that need them. @@ -4480,16 +4477,30 @@ var CanvasGraphics = (function() { restoreFillRule: function(rule) { this.ctx.mozFillRule = rule; }, - applyTransform: function(x0, y0, m) { - var xt = x0 * m[0] + y0 * m[2] + m[4]; - var yt = x0 * m[1] + y0 * m[3] + m[5]; - return [xt, yt]; - } }; return constructor; })(); +var Util = (function() { + function constructor() {}; + constructor.makeCssRgb = function makergb(r, g, b) { + var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; + return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; + }; + constructor.makeCssCmyk = function makecmyk(c, m, y, k) { + var c = (new DeviceCmykCS()).getRgb([c, m, y, k]); + return 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] + ')'; + }; + constructor.applyTransform = function apply(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + }; + + return constructor; +})(); + var ColorSpace = (function() { // Constructor should define this.numComps, this.defaultColor, this.name function constructor() { @@ -4884,12 +4895,10 @@ var Pattern = (function() { color = base.getRgb(color); } return new TilingPattern(pattern, dict, color, xref, ctx); - break; case 2: var shading = xref.fetchIfRef(dict.get('Shading')); var matrix = dict.get('Matrix'); return Pattern.parseShading(shading, matrix, xref, res, ctx); - break; default: error('Unknown type of pattern'); } @@ -4904,23 +4913,33 @@ var Pattern = (function() { switch (type) { case 2: case 3: - // both radial and axial shadings are handled by simple shading - return new SimpleShading(dict, matrix, xref, res, ctx); - break; + // both radial and axial shadings are handled by RadialAxial shading + return new RadialAxialShading(dict, matrix, xref, res, ctx); default: - error('Unsupported shading'); + return new DummyShading(); } } return constructor; })(); -var SimpleShading = (function() { +var DummyShading = (function() { + function constructor() {}; + constructor.prototype = { + getPattern: function dummy_getpattern() { + return 'hotpink'; + } + }; + return constructor; +})(); + +var RadialAxialShading = (function() { function constructor(dict, matrix, xref, res, ctx) { this.matrix = matrix; var bbox = dict.get('BBox'); var background = dict.get('Background'); this.coordsArr = dict.get('Coords'); this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; this.ctx = ctx; this.curMatrix = ctx.mozCurrentTransform; @@ -4962,7 +4981,7 @@ var SimpleShading = (function() { var colorStops = []; for (var i = t0; i <= t1; i += step) { var color = fn.func([i]); - var rgbColor = this.makeCssRgb.apply(this, cs.getRgb(color)); + var rgbColor = Util.makeCssRgb.apply(this, cs.getRgb(color)); colorStops.push([(i - t0) / diff, rgbColor]); } @@ -4986,8 +5005,8 @@ var SimpleShading = (function() { var matrix = this.matrix; if (matrix) { - p0 = this.applyTransform(p0, matrix); - p1 = this.applyTransform(p1, matrix); + p0 = Util.applyTransform(p0, matrix); + p1 = Util.applyTransform(p1, matrix); } // if the browser supports getting the tranform matrix, convert @@ -4997,11 +5016,11 @@ var SimpleShading = (function() { if (curMatrix) { var userMatrix = ctx.mozCurrentTransformInverse; - p0 = this.applyTransform(p0, curMatrix); - p0 = this.applyTransform(p0, userMatrix); + p0 = Util.applyTransform(p0, curMatrix); + p0 = Util.applyTransform(p0, userMatrix); - p1 = this.applyTransform(p1, curMatrix); - p1 = this.applyTransform(p1, userMatrix); + p1 = Util.applyTransform(p1, curMatrix); + p1 = Util.applyTransform(p1, userMatrix); } var colorStops = this.colorStops; @@ -5015,15 +5034,6 @@ var SimpleShading = (function() { grad.addColorStop(c[0], c[1]); } return grad; - }, - applyTransform: function(p, m) { - var xt = p[0] * m[0] + p[1] * m[2] + m[4]; - var yt = p[0] * m[1] + p[1] * m[3] + m[5]; - return [xt, yt]; - }, - makeCssRgb: function(r, g, b) { - var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; - return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; } }; return constructor; @@ -5049,6 +5059,7 @@ var TilingPattern = (function() { this.curMatrix = ctx.mozCurrentTransform; this.invMatrix = ctx.mozCurrentTransformInverse; this.ctx = ctx; + this.type = 'Pattern'; var bbox = dict.get('BBox'); var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3]; @@ -5082,7 +5093,7 @@ var TilingPattern = (function() { tmpCtx.strokeStyle = ctx.strokeStyle; break; case PAINT_TYPE_UNCOLORED: - color = this.makeCssRgb.apply(this, color); + color = Util.makeCssRgb.apply(this, color); tmpCtx.fillStyle = color; tmpCtx.strokeStyle = color; break; @@ -5128,15 +5139,6 @@ var TilingPattern = (function() { ctx.scale(1 / scale[0], 1 / scale[1]); return ctx.createPattern(this.canvas, 'repeat'); - }, - applyTransform: function(x0, y0, m) { - var xt = x0 * m[0] + y0 * m[2] + m[4]; - var yt = x0 * m[1] + y0 * m[3] + m[5]; - return [xt, yt]; - }, - makeCssRgb: function(r, g, b) { - var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; - return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; } }; return constructor; From dd1d90213bfb1f714124fe722c85b30a60f60ae4 Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Fri, 15 Jul 2011 11:18:37 -0700 Subject: [PATCH 07/12] cleanup --- pdf.js | 55 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/pdf.js b/pdf.js index 9a5944d5e..d371330ac 100644 --- a/pdf.js +++ b/pdf.js @@ -4004,7 +4004,17 @@ var CanvasGraphics = (function() { this.ctx.rect(x, y, width, height); }, stroke: function() { - this.ctx.stroke(); + var ctx = this.ctx; + var strokeColor = this.current.strokeColor; + if (strokeColor && strokeColor.type === "Pattern") { + ctx.save(); + ctx.strokeStyle = strokeColor.getPattern(ctx); + ctx.stroke(); + ctx.restore(); + } else { + ctx.stroke(); + } + this.consumePath(); }, closeStroke: function() { @@ -4015,11 +4025,11 @@ var CanvasGraphics = (function() { var ctx = this.ctx; var fillColor = this.current.fillColor; - if (fillColor.type === "Pattern") { - this.ctx.save(); + if (fillColor && fillColor.type === "Pattern") { + ctx.save(); ctx.fillStyle = fillColor.getPattern(ctx); ctx.fill(); - this.ctx.restore(); + ctx.restore(); } else { ctx.fill(); } @@ -4033,13 +4043,27 @@ var CanvasGraphics = (function() { }, fillStroke: function() { var ctx = this.ctx; - var fillCS = this.current.fillColorSpace; - if (fillCS && fillCS.name === "Pattern") - this.current.fillPattern(ctx); - - ctx.fill(); - ctx.stroke(); + var fillColor = this.current.fillColor; + if (fillColor && fillColor.type === "Pattern") { + ctx.save(); + ctx.fillStyle = fillColor.getPattern(ctx); + ctx.fill(); + ctx.restore(); + } else { + ctx.fill(); + } + + var strokeColor = this.current.strokeColor; + if (stokeColor && strokeColor.type === "Pattern") { + ctx.save(); + ctx.strokeStyle = strokeColor.getPattern(ctx); + ctx.stroke(); + ctx.restore(); + } else { + ctx.stroke(); + } + this.consumePath(); }, eoFillStroke: function() { @@ -4246,9 +4270,7 @@ var CanvasGraphics = (function() { // wait until fill to actually get the pattern var pattern = Pattern.parse(arguments, cs, this.xref, this.res, this.ctx); -// this.current.fillColor = pattern; - this.ctx.fillStyle = pattern.getPattern(); - this.current.fillColor = "blah"; + this.current.fillColor = pattern; } else { this.setFillColor.apply(this, arguments); } @@ -4262,7 +4284,7 @@ var CanvasGraphics = (function() { setStrokeRGBColor: function(r, g, b) { var color = Util.makeCssRgb(r, g, b); this.ctx.strokeStyle = color; - this.current.fillColor = color; + this.current.strokeColor = color; }, setFillRGBColor: function(r, g, b) { var color = Util.makeCssRgb(r, g, b); @@ -4272,7 +4294,7 @@ var CanvasGraphics = (function() { setStrokeCMYKColor: function(c, m, y, k) { var color = Util.makeCssCmyk(c, m, y, k); this.ctx.strokeStyle = color; - this.current.fillColor = color; + this.current.strokeColor = color; }, setFillCMYKColor: function(c, m, y, k) { var color = Util.makeCssCmyk(c, m, y, k); @@ -5125,9 +5147,10 @@ var TilingPattern = (function() { }; constructor.prototype = { - getPattern: function tiling_getPattern(ctx) { + getPattern: function tiling_getPattern() { var matrix = this.matrix; var curMatrix = this.curMatrix; + var ctx = this.ctx; if (curMatrix) ctx.setTransform.apply(ctx, curMatrix); From c438a8748a9ac46155d9844ea7ba19a70c4df231 Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Fri, 15 Jul 2011 11:41:39 -0700 Subject: [PATCH 08/12] fix type --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index d371330ac..fe2d38ac6 100644 --- a/pdf.js +++ b/pdf.js @@ -4055,7 +4055,7 @@ var CanvasGraphics = (function() { } var strokeColor = this.current.strokeColor; - if (stokeColor && strokeColor.type === "Pattern") { + if (strokeColor && strokeColor.type === "Pattern") { ctx.save(); ctx.strokeStyle = strokeColor.getPattern(ctx); ctx.stroke(); From 5f4b84146f2ab2bd95ff1a620e61d87f136236df Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Fri, 15 Jul 2011 12:05:14 -0700 Subject: [PATCH 09/12] fix to Util.getCssCmyk --- pdf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index fe2d38ac6..bf34d9398 100644 --- a/pdf.js +++ b/pdf.js @@ -4512,7 +4512,8 @@ var Util = (function() { }; constructor.makeCssCmyk = function makecmyk(c, m, y, k) { var c = (new DeviceCmykCS()).getRgb([c, m, y, k]); - return 'rgb(' + c[0] + ',' + c[1] + ',' + c[2] + ')'; + var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0; + return 'rgb(' + ri + ',' + gi + ',' + bi + ')'; }; constructor.applyTransform = function apply(p, m) { var xt = p[0] * m[0] + p[1] * m[2] + m[4]; From 2098d840dae1222f4e998b56d1eaa396fec67dad Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Fri, 15 Jul 2011 12:06:38 -0700 Subject: [PATCH 10/12] fix to dummyshading --- pdf.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index bf34d9398..bc726ccd2 100644 --- a/pdf.js +++ b/pdf.js @@ -4946,7 +4946,9 @@ var Pattern = (function() { })(); var DummyShading = (function() { - function constructor() {}; + function constructor() { + this.type = 'Pattern'; + }; constructor.prototype = { getPattern: function dummy_getpattern() { return 'hotpink'; From 636b1105b028a598fb61c7a825848a702f4f1d55 Mon Sep 17 00:00:00 2001 From: sbarman <sbarman@L3CWZ5T.(none)> Date: Mon, 18 Jul 2011 09:13:02 -0700 Subject: [PATCH 11/12] cleanup --- pdf.js | 73 ++++++++++++---------------------------------------------- 1 file changed, 15 insertions(+), 58 deletions(-) diff --git a/pdf.js b/pdf.js index bc726ccd2..bab032119 100644 --- a/pdf.js +++ b/pdf.js @@ -3817,62 +3817,10 @@ var CanvasExtraState = (function() { this.old = old; } + constructor.prototype = { - get fillColorSpace() { - var cs = this.fillColorSpaceObj; - if (cs) - return cs; - - var old = this.old; - if (old) - return old.fillColorSpace; - - return null; - }, - set fillColorSpace(cs) { - this.fillColorSpaceObj = cs; - }, - get strokeColorSpace() { - var cs = this.strokeColorSpaceObj; - if (cs) - return cs; - - var old = this.old; - if (old) - return old.strokeColorSpace; - - return null; - }, - set strokeColorSpace(cs) { - this.strokeColorSpaceObj = cs; - }, - get fillColor() { - var color = this.fillColorObj; - if (color) - return color; - - var old = this.old; - if (old) - return old.fillColor; - - return null; - }, - set fillColor(color) { - this.fillColorObj = color; - }, - get strokeColor() { - var color = this.strokeColorObj; - if (color) - return color; - - var old = this.old; - if (old) - return old.strokeColor; - - return null; - }, - set strokeColor(color) { - this.strokeColorObj = color; + clone: function canvasextra_clone() { + return Object.create(this); } }; return constructor; @@ -3965,7 +3913,7 @@ var CanvasGraphics = (function() { } var old = this.current; this.stateStack.push(old); - this.current = new CanvasExtraState(old); + this.current = old.clone(); }, restore: function() { var prev = this.stateStack.pop(); @@ -4007,6 +3955,8 @@ var CanvasGraphics = (function() { var ctx = this.ctx; var strokeColor = this.current.strokeColor; if (strokeColor && strokeColor.type === "Pattern") { + // for patterns, we transform to pattern space, calculate + // the pattern, call stroke, and restore to user space ctx.save(); ctx.strokeStyle = strokeColor.getPattern(ctx); ctx.stroke(); @@ -4250,7 +4200,9 @@ var CanvasGraphics = (function() { var cs = this.current.strokeColorSpace; if (cs.name == 'Pattern') { - // wait until fill to actually get the pattern + // wait until fill to actually get the pattern, since Canvas + // calcualtes the pattern according to the current coordinate space, + // not the space when the pattern is set. var pattern = Pattern.parse(arguments, cs, this.xref, this.res, this.ctx); this.current.strokeColor = pattern; @@ -4957,6 +4909,8 @@ var DummyShading = (function() { return constructor; })(); +// Radial and axial shading have very similar implementations +// If needed, the implementations can be broken into two classes var RadialAxialShading = (function() { function constructor(dict, matrix, xref, res, ctx) { this.matrix = matrix; @@ -5099,7 +5053,10 @@ var TilingPattern = (function() { var width = botRight[0] - topLeft[0]; var height = botRight[1] - topLeft[1]; - // TODO: hack to avoid OOM, remove then pattern code is fixed + // TODO: hack to avoid OOM, we would idealy compute the tiling + // pattern to be only as large as the acual size in device space + // This could be computed with .mozCurrentTransform, but still + // needs to be implemented while (Math.abs(width) > 512 || Math.abs(height) > 512) { width = 512; height = 512; From d4157c0c7cf01d13ea49c5fdc9a2036feb70985b Mon Sep 17 00:00:00 2001 From: notmasteryet <async.processingjs@yahoo.com> Date: Thu, 21 Jul 2011 18:47:48 -0500 Subject: [PATCH 12/12] Formatting hex number, making gjslint happy: reducing lines width --- crypto.js | 246 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 139 insertions(+), 107 deletions(-) diff --git a/crypto.js b/crypto.js index 98f7bb4a1..652f53b2c 100644 --- a/crypto.js +++ b/crypto.js @@ -144,110 +144,129 @@ var NullCipher = (function() { var AES128Cipher = (function() { var rcon = new Uint8Array([ - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, - 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, - 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, - 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, - 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, - 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, - 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, - 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, - 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, - 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, - 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, - 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, - 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, - 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, - 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, - 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]); + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, + 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, + 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d]); var s = new Uint8Array([ - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]); + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16]); var inv_s = new Uint8Array([ - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D]); + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d]); var mix = new Uint32Array([ - 0x0, 0xe090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, - 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, - 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, - 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, - 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, - 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, - 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, - 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, - 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x38f5fe7, 0xd8652ec, 0x1f9d45f1, - 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, - 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, - 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, - 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, - 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, - 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, - 0x2fb5c203, 0x58ae132, 0xb83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, - 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, - 0x5c72f5bc, 0x605bed5, 0x80cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, - 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, - 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, - 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, - 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, - 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, - 0x23bfa5b2, 0x9808683, 0x7898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, - 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, - 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, - 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, - 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, - 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, - 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, - 0x4c6a881b, 0x5e719f06, 0x5078920d, 0xa0fd964, 0x406d46f, 0x161dc372, - 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, - 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, - 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, - 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0xc0a67b1, 0x2036aba, 0x10187da7, - 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, - 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, - 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0xf853856, - 0x18c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, - 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, - 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, - 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, - 0x91548db5, 0x834f9aa8, 0x8d4697a3]); + 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, + 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, + 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, + 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, + 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, + 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, + 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, + 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, + 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, + 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, + 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, + 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, + 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, + 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, + 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, + 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, + 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, + 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, + 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, + 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, + 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, + 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, + 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, + 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, + 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, + 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, + 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, + 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, + 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, + 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, + 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, + 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, + 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, + 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, + 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, + 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, + 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, + 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, + 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, + 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, + 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, + 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, + 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); function expandKey128(cipherKey) { var b = 176, result = new Uint8Array(b); result.set(cipherKey); for (var j = 16, i = 1; j < b; ++i) { // RotWord - var t1 = result[j - 3], t2 = result[j - 2], t3 = result[j - 1], t4 = result[j - 4]; + var t1 = result[j - 3], t2 = result[j - 2], + t3 = result[j - 1], t4 = result[j - 4]; // SubWord t1 = s[t1]; t2 = s[t2]; t3 = s[t3]; t4 = s[t4]; // Rcon @@ -272,9 +291,12 @@ var AES128Cipher = (function() { state[j] ^= key[k]; for (i = 9; i >= 1; --i) { // InvShiftRows - t = state[13]; state[13] = state[9]; state[9] = state[5]; state[5] = state[1]; state[1] = t; - t = state[14]; u = state[10]; state[14] = state[6]; state[10] = state[2]; state[6] = t; state[2] = u; - t = state[15]; u = state[11]; v = state[7]; state[15] = state[3]; state[11] = t; state[7] = u; state[3] = v; + t = state[13]; state[13] = state[9]; state[9] = state[5]; + state[5] = state[1]; state[1] = t; + t = state[14]; u = state[10]; state[14] = state[6]; + state[10] = state[2]; state[6] = t; state[2] = u; + t = state[15]; u = state[11]; v = state[7]; state[15] = state[3]; + state[11] = t; state[7] = u; state[3] = v; // InvSubBytes for (j = 0; j < 16; ++j) state[j] = inv_s[state[j]]; @@ -283,8 +305,10 @@ var AES128Cipher = (function() { state[j] ^= key[k]; // InvMixColumns for (j = 0; j < 16; j += 4) { - var s0 = mix[state[j]], s1 = mix[state[j + 1]], s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; - t = s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ (s3 >>> 24) ^ (s3 << 8); + var s0 = mix[state[j]], s1 = mix[state[j + 1]], + s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; + t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ + (s3 >>> 24) ^ (s3 << 8)); state[j] = (t >>> 24) & 0xFF; state[j + 1] = (t >> 16) & 0xFF; state[j + 2] = (t >> 8) & 0xFF; @@ -292,9 +316,12 @@ var AES128Cipher = (function() { } } // InvShiftRows - t = state[13]; state[13] = state[9]; state[9] = state[5]; state[5] = state[1]; state[1] = t; - t = state[14]; u = state[10]; state[14] = state[6]; state[10] = state[2]; state[6] = t; state[2] = u; - t = state[15]; u = state[11]; v = state[7]; state[15] = state[3]; state[11] = t; state[7] = u; state[3] = v; + t = state[13]; state[13] = state[9]; state[9] = state[5]; + state[5] = state[1]; state[1] = t; + t = state[14]; u = state[10]; state[14] = state[6]; + state[10] = state[2]; state[6] = t; state[2] = u; + t = state[15]; u = state[11]; v = state[7]; state[15] = state[3]; + state[11] = t; state[7] = u; state[3] = v; // InvSubBytes for (j = 0; j < 16; ++j) state[j] = inv_s[state[j]]; @@ -311,9 +338,9 @@ var AES128Cipher = (function() { } function decryptBlock2(data) { - var i, j, sourceLength = data.length; - var buffer = this.buffer, bufferLength = this.bufferPosition, iv = this.iv; - var result = []; + var i, j, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = [], iv = this.iv; for (i = 0; i < sourceLength; ++i) { buffer[bufferLength] = data[i]; ++bufferLength; @@ -481,7 +508,8 @@ var CipherTransformFactory = (function() { var userPassword = stringToBytes(dict.get('U')); var flags = dict.get('P'); var revision = dict.get('R'); - var encryptMetadata = dict.get('EncryptMetadata') !== false; // makes true as default value + var encryptMetadata = + dict.get('EncryptMetadata') !== false; // makes true as default value var fileIdBytes = stringToBytes(fileId); var passwordBytes; if (password) @@ -489,7 +517,8 @@ var CipherTransformFactory = (function() { this.encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, - flags, revision, keyLength, encryptMetadata); + flags, revision, + keyLength, encryptMetadata); if (algorithm == 4) { this.cf = dict.get('CF'); this.stmf = dict.get('StmF') || identityName; @@ -539,14 +568,17 @@ var CipherTransformFactory = (function() { buildObjectKey(num, gen, key, true)); }; } + error('Unknown crypto method'); } constructor.prototype = { createCipherTransform: function(num, gen) { if (this.algorithm == 4) { return new CipherTransform( - buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey), - buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey)); + buildCipherConstructor(this.cf, this.stmf, + num, gen, this.encryptionKey), + buildCipherConstructor(this.cf, this.strf, + num, gen, this.encryptionKey)); } // algorithms 1 and 2 var key = buildObjectKey(num, gen, this.encryptionKey, false);