summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/gfx/gradient.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo/dojox/gfx/gradient.js')
-rw-r--r--js/dojo/dojox/gfx/gradient.js161
1 files changed, 161 insertions, 0 deletions
diff --git a/js/dojo/dojox/gfx/gradient.js b/js/dojo/dojox/gfx/gradient.js
new file mode 100644
index 0000000..e167df8
--- /dev/null
+++ b/js/dojo/dojox/gfx/gradient.js
@@ -0,0 +1,161 @@
+//>>built
+define("dojox/gfx/gradient", ["dojo/_base/lang", "./matrix", "dojo/_base/Color"],
+ function(lang, m, Color){
+// Various utilities to deal with a linear gradient (mostly VML-specific)
+ var grad = lang.getObject("dojox.gfx.gradient", true);
+ var C = Color;
+ /*===== grad = dojox.gfx.gradient; =====*/
+
+ grad.rescale = function(stops, from, to){
+ // summary:
+ // Recalculates a gradient from 0-1 window to
+ // "from"-"to" window blending and replicating colors,
+ // if necessary.
+ // stops: Array
+ // input gradient as a list of colors with offsets
+ // (see dojox.gfx.defaultLinearGradient and dojox.gfx.defaultRadialGradient)
+ // from: Number
+ // the beginning of the window, should be less than "to"
+ // to: Number
+ // the end of the window, should be more than "from"
+
+ var len = stops.length, reverseFlag = (to < from), newStops;
+
+ // do we need to reverse the color table?
+ if(reverseFlag){
+ var tmp = from;
+ from = to;
+ to = tmp;
+ }
+
+ // various edge cases
+ if(!len){
+ // no colors
+ return [];
+ }
+ if(to <= stops[0].offset){
+ // all colors are before the color table
+ newStops = [
+ {offset: 0, color: stops[0].color},
+ {offset: 1, color: stops[0].color}
+ ];
+ }else if(from >= stops[len - 1].offset){
+ // all colors are after the color table
+ newStops = [
+ {offset: 0, color: stops[len - 1].color},
+ {offset: 1, color: stops[len - 1].color}
+ ];
+ }else{
+ // main scanning algorithm
+ var span = to - from, stop, prev, i;
+ newStops = [];
+ if(from < 0){
+ newStops.push({offset: 0, color: new C(stops[0].color)});
+ }
+ for(i = 0; i < len; ++i){
+ stop = stops[i];
+ if(stop.offset >= from){
+ break;
+ }
+ // skip this color
+ }
+ if(i){
+ prev = stops[i - 1];
+ newStops.push({
+ offset: 0,
+ color: Color.blendColors(new C(prev.color), new C(stop.color), (from - prev.offset) / (stop.offset - prev.offset))
+ });
+ }else{
+ newStops.push({offset: 0, color: new C(stop.color)});
+ }
+ for(; i < len; ++i){
+ stop = stops[i];
+ if(stop.offset >= to){
+ break;
+ }
+ newStops.push({offset: (stop.offset - from) / span, color: new C(stop.color)});
+ }
+ if(i < len){
+ prev = stops[i - 1];
+ newStops.push({
+ offset: 1,
+ color: Color.blendColors(new C(prev.color), new C(stop.color), (to - prev.offset) / (stop.offset - prev.offset))
+ });
+ }else{
+ newStops.push({offset: 1, color: new C(stops[len - 1].color)});
+ }
+ }
+
+ // reverse the color table, if needed
+ if(reverseFlag){
+ newStops.reverse();
+ for(i = 0, len = newStops.length; i < len; ++i){
+ stop = newStops[i];
+ stop.offset = 1 - stop.offset;
+ }
+ }
+
+ return newStops;
+ };
+
+ function getPoint(x, y, matrix, project, shiftAndRotate, scale){
+ var r = m.multiplyPoint(matrix, x, y),
+ p = m.multiplyPoint(project, r);
+ return {r: r, p: p, o: m.multiplyPoint(shiftAndRotate, p).x / scale};
+ }
+
+ function sortPoints(a, b){
+ return a.o - b.o;
+ }
+
+ grad.project = function(matrix, gradient, tl, rb, ttl, trb){
+ // summary:
+ // Returns a new gradient using the "VML algorithm" and suitable for VML.
+ // matrix: dojox.gfx.Matrix2D|Null:
+ // matrix to apply to a shape and its gradient
+ // gradient: Object:
+ // a linear gradient object to be transformed
+ // tl: dojox.gfx.Point:
+ // top-left corner of shape's bounding box
+ // rb: dojox.gfx.Point:
+ // right-bottom corner of shape's bounding box
+ // ttl: dojox.gfx.Point:
+ // top-left corner of shape's transformed bounding box
+ // trb: dojox.gfx.Point:
+ // right-bottom corner of shape's transformed bounding box
+
+ matrix = matrix || m.identity;
+
+ var f1 = m.multiplyPoint(matrix, gradient.x1, gradient.y1),
+ f2 = m.multiplyPoint(matrix, gradient.x2, gradient.y2),
+ angle = Math.atan2(f2.y - f1.y, f2.x - f1.x),
+ project = m.project(f2.x - f1.x, f2.y - f1.y),
+ pf1 = m.multiplyPoint(project, f1),
+ pf2 = m.multiplyPoint(project, f2),
+ shiftAndRotate = new m.Matrix2D([m.rotate(-angle), {dx: -pf1.x, dy: -pf1.y}]),
+ scale = m.multiplyPoint(shiftAndRotate, pf2).x,
+ //comboMatrix = new m.Matrix2D([shiftAndRotate, project, matrix]),
+ // bbox-specific calculations
+ points = [
+ getPoint(tl.x, tl.y, matrix, project, shiftAndRotate, scale),
+ getPoint(rb.x, rb.y, matrix, project, shiftAndRotate, scale),
+ getPoint(tl.x, rb.y, matrix, project, shiftAndRotate, scale),
+ getPoint(rb.x, tl.y, matrix, project, shiftAndRotate, scale)
+ ].sort(sortPoints),
+ from = points[0].o,
+ to = points[3].o,
+ stops = grad.rescale(gradient.colors, from, to),
+ //angle2 = Math.atan2(Math.abs(points[3].r.y - points[0].r.y) * (f2.y - f1.y), Math.abs(points[3].r.x - points[0].r.x) * (f2.x - f1.x));
+ angle2 = Math.atan2(points[3].r.y - points[0].r.y, points[3].r.x - points[0].r.x);
+
+ return {
+ type: "linear",
+ x1: points[0].p.x, y1: points[0].p.y, x2: points[3].p.x, y2: points[3].p.y,
+ colors: stops,
+ // additional helpers (for VML)
+ angle: angle
+ };
+ };
+
+ return grad;
+});