From 5d8f463162c45c3109d7e32a4350e80dee9c730a Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 7 Jun 2012 16:00:07 -0700 Subject: [PATCH] Adds support for the extend option for linear and radial shadings. --- src/pattern.js | 33 +++++++++++++++++++++++++++++---- test/pdfs/.gitignore | 1 + test/pdfs/shading_extend.pdf | Bin 0 -> 9514 bytes 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 test/pdfs/shading_extend.pdf diff --git a/src/pattern.js b/src/pattern.js index 8d69d3a92..a0aa9a8b2 100644 --- a/src/pattern.js +++ b/src/pattern.js @@ -46,6 +46,11 @@ var Pattern = (function PatternClosure() { var Shadings = {}; +// A small number to offset the first/last color stops so we can insert ones to +// support extend. Number.MIN_VALUE appears to be too small and breaks the +// extend. +Shadings.SMALL_NUMBER = 1e-7; + // Radial and axial shading have very similar implementations // If needed, the implementations can be broken into two classes Shadings.RadialAxial = (function RadialAxialClosure() { @@ -54,7 +59,6 @@ Shadings.RadialAxial = (function RadialAxialClosure() { this.coordsArr = dict.get('Coords'); this.shadingType = dict.get('ShadingType'); this.type = 'Pattern'; - this.ctx = ctx; var cs = dict.get('ColorSpace', 'CS'); cs = ColorSpace.parse(cs, xref, res); @@ -72,7 +76,6 @@ Shadings.RadialAxial = (function RadialAxialClosure() { var extendArr = dict.get('Extend'); extendStart = extendArr[0]; extendEnd = extendArr[1]; - TODO('Support extend'); } this.extendStart = extendStart; @@ -88,16 +91,38 @@ Shadings.RadialAxial = (function RadialAxialClosure() { // 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 step = diff / 10; + + var colorStops = this.colorStops = []; + + // Protect against bad domains so we don't end up in an infinte loop below. + if (t0 >= t1 || step <= 0) { + // Acrobat doesn't seem to handle these cases so we'll ignore for + // now. + info('Bad shading domain.'); + return; + } - var colorStops = []; for (var i = t0; i <= t1; i += step) { var rgbColor = cs.getRgb(fn([i])); var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); colorStops.push([(i - t0) / diff, cssColor]); } + // XXX: Extend start and end does work in Chrome. Tested in v21. + if (!extendStart) { + // Insert a color stop at the front and offset the first real color stop + // so it doesn't conflict with the one we insert. + colorStops.unshift([0, 'rgba(255,255,255,0)']); + colorStops[1][0] += Shadings.SMALL_NUMBER; + } + if (!extendEnd) { + // Same idea as above in extendStart but for the end. + colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER; + colorStops.push([1, 'rgba(255,255,255,0)']); + } + this.colorStops = colorStops; } diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 7f2911983..60793fa31 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -34,3 +34,4 @@ !gradientfill.pdf !basicapi.pdf !mixedfonts.pdf +!shading_extend.pdf diff --git a/test/pdfs/shading_extend.pdf b/test/pdfs/shading_extend.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0c8c151da6170412f979805766010cee5531427e GIT binary patch literal 9514 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 Z&@Zl#r8S*eZ@?dHYM458c4u3|e*wJgEujDa literal 0 HcmV?d00001