|
|
@ -61,6 +61,12 @@ var Pattern = (function PatternClosure() { |
|
|
|
|
|
|
|
|
|
|
|
var Shadings = {}; |
|
|
|
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. 1e-7 works in FF but chrome seems to use an even smaller sized number
|
|
|
|
|
|
|
|
// internally so we have to go bigger.
|
|
|
|
|
|
|
|
Shadings.SMALL_NUMBER = 1e-2; |
|
|
|
|
|
|
|
|
|
|
|
// Radial and axial shading have very similar implementations
|
|
|
|
// Radial and axial shading have very similar implementations
|
|
|
|
// If needed, the implementations can be broken into two classes
|
|
|
|
// If needed, the implementations can be broken into two classes
|
|
|
|
Shadings.RadialAxial = (function RadialAxialClosure() { |
|
|
|
Shadings.RadialAxial = (function RadialAxialClosure() { |
|
|
@ -69,7 +75,6 @@ Shadings.RadialAxial = (function RadialAxialClosure() { |
|
|
|
this.coordsArr = dict.get('Coords'); |
|
|
|
this.coordsArr = dict.get('Coords'); |
|
|
|
this.shadingType = dict.get('ShadingType'); |
|
|
|
this.shadingType = dict.get('ShadingType'); |
|
|
|
this.type = 'Pattern'; |
|
|
|
this.type = 'Pattern'; |
|
|
|
|
|
|
|
|
|
|
|
this.ctx = ctx; |
|
|
|
this.ctx = ctx; |
|
|
|
var cs = dict.get('ColorSpace', 'CS'); |
|
|
|
var cs = dict.get('ColorSpace', 'CS'); |
|
|
|
cs = ColorSpace.parse(cs, xref, res); |
|
|
|
cs = ColorSpace.parse(cs, xref, res); |
|
|
@ -87,7 +92,23 @@ Shadings.RadialAxial = (function RadialAxialClosure() { |
|
|
|
var extendArr = dict.get('Extend'); |
|
|
|
var extendArr = dict.get('Extend'); |
|
|
|
extendStart = extendArr[0]; |
|
|
|
extendStart = extendArr[0]; |
|
|
|
extendEnd = extendArr[1]; |
|
|
|
extendEnd = extendArr[1]; |
|
|
|
TODO('Support extend'); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.shadingType === PatternType.RADIAL && |
|
|
|
|
|
|
|
(!extendStart || !extendEnd)) { |
|
|
|
|
|
|
|
// Radial gradient only currently works if either circle is fully within
|
|
|
|
|
|
|
|
// the other circle.
|
|
|
|
|
|
|
|
var x1 = this.coordsArr[0]; |
|
|
|
|
|
|
|
var y1 = this.coordsArr[1]; |
|
|
|
|
|
|
|
var r1 = this.coordsArr[2]; |
|
|
|
|
|
|
|
var x2 = this.coordsArr[3]; |
|
|
|
|
|
|
|
var y2 = this.coordsArr[4]; |
|
|
|
|
|
|
|
var r2 = this.coordsArr[5]; |
|
|
|
|
|
|
|
var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); |
|
|
|
|
|
|
|
if (r1 <= r2 + distance && |
|
|
|
|
|
|
|
r2 <= r1 + distance) { |
|
|
|
|
|
|
|
warn('Unsupported radial gradient.'); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.extendStart = extendStart; |
|
|
|
this.extendStart = extendStart; |
|
|
@ -103,16 +124,43 @@ Shadings.RadialAxial = (function RadialAxialClosure() { |
|
|
|
// 10 samples seems good enough for now, but probably won't work
|
|
|
|
// 10 samples seems good enough for now, but probably won't work
|
|
|
|
// if there are sharp color changes. Ideally, we would implement
|
|
|
|
// if there are sharp color changes. Ideally, we would implement
|
|
|
|
// the spec faithfully and add lossless optimizations.
|
|
|
|
// the spec faithfully and add lossless optimizations.
|
|
|
|
var step = (t1 - t0) / 10; |
|
|
|
|
|
|
|
var diff = t1 - t0; |
|
|
|
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) { |
|
|
|
for (var i = t0; i <= t1; i += step) { |
|
|
|
var rgbColor = cs.getRgb(fn([i])); |
|
|
|
var rgbColor = cs.getRgb(fn([i])); |
|
|
|
var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); |
|
|
|
var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); |
|
|
|
colorStops.push([(i - t0) / diff, cssColor]); |
|
|
|
colorStops.push([(i - t0) / diff, cssColor]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var background = 'transparent'; |
|
|
|
|
|
|
|
if (dict.has('Background')) { |
|
|
|
|
|
|
|
var rgbColor = cs.getRgb(dict.get('Background')); |
|
|
|
|
|
|
|
background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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, background]); |
|
|
|
|
|
|
|
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, background]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.colorStops = colorStops; |
|
|
|
this.colorStops = colorStops; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|