Skip to content

Commit 5209e97

Browse files
committed
Merge GradientColor into Color.
Work in progress.
1 parent 380fce3 commit 5209e97

15 files changed

Lines changed: 154 additions & 51 deletions

File tree

examples/JSON/Gradients.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
var gradient = new Gradient(['yellow', 'red', 'black'], true);
1111
var from = path.position;
1212
var to = path.bounds.rightCenter;
13-
var gradientColor = new GradientColor(gradient, from, to);
13+
var gradientColor = new Color(gradient, from, to);
1414
path.fillColor = gradientColor;
1515
path.strokeColor = 'black';
1616
window._json = project.exportJson();

examples/Paperjs.org/BouncingBalls.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
radius: radius / 3
3636
})
3737
],
38-
fillColor: new GradientColor(gradient, 0, radius, radius / 8),
38+
fillColor: new Color(gradient, 0, radius, radius / 8),
3939
position: this.point
4040
});
4141
}

examples/Paperjs.org/RadialRainbows.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
var path = new Path.Rectangle(view.bounds);
2525
var gradient = new Gradient(colors, true);
2626
var radius = Math.max(view.size.width, view.size.height) * 0.75;
27-
path.fillColor = new GradientColor(gradient, point, point + [radius, 0]);
27+
path.fillColor = new Color(gradient, point, point + [radius, 0]);
2828
var gradientColor = path.fillColor;
2929

3030
var mouseDown = false,

examples/SVG Export/Gradients.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
var circle = new Path.Circle({
1717
center: from,
1818
radius: radius,
19-
fillColor: new GradientColor(radial, from, to),
19+
fillColor: new Color(radial, from, to),
2020
strokeColor: 'black'
2121
});
2222

@@ -26,7 +26,7 @@
2626
var rect = new Path.Rectangle({
2727
from: from,
2828
to: to,
29-
fillColor: new GradientColor(linear, from, to),
29+
fillColor: new Color(linear, from, to),
3030
strokeColor: 'black'
3131
});
3232

examples/Scripts/HslColor.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
var gradient = new Gradient(colors, true);
4242
var from = center;
4343
var to = center + vector;
44-
var gradientColor = new GradientColor(gradient, from, to);
44+
var gradientColor = new Color(gradient, from, to);
4545
path.fillColor = path.strokeColor = gradientColor;
4646
}
4747
}

src/color/Color.js

Lines changed: 123 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ var Color = this.Color = Base.extend(new function() {
4747
gray: ['gray'],
4848
rgb: ['red', 'green', 'blue'],
4949
hsb: ['hue', 'saturation', 'brightness'],
50-
hsl: ['hue', 'saturation', 'lightness']
50+
hsl: ['hue', 'saturation', 'lightness'],
51+
gradient: ['gradient', 'origin', 'destination', 'hilite']
5152
};
5253

5354
var colorCache = {},
@@ -192,7 +193,18 @@ var Color = this.Color = Base.extend(new function() {
192193
'gray-hsl': function(g) {
193194
// TODO: Is lightness really the same as brightness for gray?
194195
return [0, 0, g];
196+
},
197+
198+
'gradient-rgb': function(gradient) {
199+
// TODO: Implement
200+
return [];
201+
},
202+
203+
'rgb-gradient': function(r, g, b) {
204+
// TODO: Implement
205+
return [];
195206
}
207+
196208
};
197209

198210
// Produce getters and setter methods for the various color components known
@@ -201,12 +213,15 @@ var Color = this.Color = Base.extend(new function() {
201213
// its component.
202214
return Base.each(types, function(properties, type) {
203215
Base.each(properties, function(name, index) {
204-
var isHue = name === 'hue',
216+
var part = Base.capitalize(name),
217+
isHue = name === 'hue',
218+
isGradient = name === 'gradient',
219+
isPoint = type === 'gradient' && !isGradient,
220+
isHilite = name === 'hilite',
205221
// Both hue and saturation have overlapping properties between
206222
// hsb and hsl. Handle this here separately, by testing for
207223
// overlaps and skipping conversion if the type is /hs[bl]/
208-
hasOverlap = /^(hue|saturation)$/.test(name),
209-
part = Base.capitalize(name);
224+
hasOverlap = /^(hue|saturation)$/.test(name);
210225

211226
this['get' + part] = function() {
212227
return this._type === type
@@ -222,11 +237,20 @@ var Color = this.Color = Base.extend(new function() {
222237
this._components = this._convert(type);
223238
this._type = type;
224239
}
225-
this._components[index] = isHue
240+
if (!isGradient)
241+
value = isHue
226242
// Keep negative values within modulo 360 too:
227243
? ((value % 360) + 360) % 360
228-
// All other values are 0..1
229-
: Math.min(Math.max(value, 0), 1);
244+
: isPoint
245+
? Point.read(arguments, 0, 0, true, isHilite) // clone, readNull
246+
// All other values are 0..1
247+
: Math.min(Math.max(value, 0), 1);
248+
if (value != null) {
249+
this._components[index] = value;
250+
if (isGradient)
251+
value._addOwner(this);
252+
this._changed();
253+
}
230254
};
231255
}, this);
232256
}, /** @lends Color# */{
@@ -242,6 +266,10 @@ var Color = this.Color = Base.extend(new function() {
242266
args = arguments,
243267
read = 0,
244268
type;
269+
if (Array.isArray(arg)) {
270+
args = arg;
271+
arg = args[0];
272+
}
245273
// Try type arg first
246274
if (typeof arg === 'string' && arg in types) {
247275
type = arg;
@@ -286,17 +314,19 @@ var Color = this.Color = Base.extend(new function() {
286314
components = arg._components.slice();
287315
alpha = arg._alpha;
288316
} else if (arg._class === 'Gradient') {
289-
// TODO: Construct gradient
290317
type = 'gradient';
318+
components = slice.call(args);
291319
} else {
292320
// Determine type by presence of object property names
293321
type = 'hue' in arg
294322
? 'lightness' in arg
295323
? 'hsl'
296324
: 'hsb'
297-
: 'gray' in arg
298-
? 'gray'
299-
: 'rgb';
325+
: 'gradient' in arg
326+
? 'gradient'
327+
: 'gray' in arg
328+
? 'gray'
329+
: 'rgb';
300330
var properties = types[type];
301331
components = [];
302332
for (var i = 0, l = properties.length; i < l; i++)
@@ -307,19 +337,31 @@ var Color = this.Color = Base.extend(new function() {
307337
if (this._read && type)
308338
read = 1;
309339
}
340+
// Define this GradientColor's unique id.
341+
if (type === 'gradient')
342+
this._id = ++Base._uid;
310343
// Default fallbacks: rgb, black
311344
this._type = type || 'rgb';
312345
this._components = components || (type === 'gray' ? [0] : [0, 0, 0]);
313346
this._alpha = alpha;
347+
// Trigger setters for each component by looping through properties
348+
// and resseting component value.
349+
// TODO: This is a hack and should implemented better, e.g. with
350+
// value handlers.
351+
var properties = types[this._type];
352+
for (var i = 0, l = properties.length; i < l; i++)
353+
this[properties[i]] = this._components[i];
314354
if (this._read)
315355
this._read = read;
316356
},
317357

318-
_serialize: function(options) {
319-
// We can ommit the type for gray and rgb:
320-
return /^(gray|rgb)$/.test(this._type)
321-
? this._components
322-
: [this._type].concat(this._components);
358+
_serialize: function(options, dictionary) {
359+
return Base.serialize(
360+
// We can ommit the type for gray and rgb:
361+
/^(gray|rgb)$/.test(this._type)
362+
? this._components
363+
: [this._type].concat(this._components),
364+
options, true, dictionary);
323365
},
324366

325367
/**
@@ -477,8 +519,53 @@ var Color = this.Color = Base.extend(new function() {
477519
return css;
478520
},
479521

480-
toCanvasStyle: function() {
481-
return this.toCss();
522+
toCanvasStyle: function(ctx) {
523+
if (this._type !== 'gradient')
524+
return this.toCss();
525+
// Gradient code form here onwards, incudling caching
526+
if (this._canvasGradient)
527+
return this._canvasGradient;
528+
var components = this._components,
529+
gradient = components[0],
530+
stops = gradient._stops,
531+
origin = components[1],
532+
destination = components[2],
533+
canvasGradient;
534+
if (gradient._radial) {
535+
var radius = destination.getDistance(origin),
536+
hilite = components[3];
537+
if (hilite) {
538+
var vector = hilite.subtract(origin);
539+
if (vector.getLength() > radius)
540+
hilite = origin.add(vector.normalize(radius - 0.1));
541+
}
542+
var start = hilite || origin;
543+
canvasGradient = ctx.createRadialGradient(start.x, start.y,
544+
0, origin.x, origin.y, radius);
545+
} else {
546+
canvasGradient = ctx.createLinearGradient(origin.x, origin.y,
547+
destination.x, destination.y);
548+
}
549+
for (var i = 0, l = stops.length; i < l; i++) {
550+
var stop = stops[i];
551+
canvasGradient.addColorStop(stop._rampPoint, stop._color.toCss());
552+
}
553+
return this._canvasGradient = canvasGradient;
554+
},
555+
556+
/**
557+
* Transform the gradient color by the specified matrix.
558+
*
559+
* @param {Matrix} matrix the matrix to transform the gradient color by
560+
*/
561+
transform: function(matrix) {
562+
if (this._type === 'gradient') {
563+
var components = this._components;
564+
for (var i = 1, l = components.length; i < l; i++) {
565+
var point = components[i];
566+
matrix._transformPoint(point, point, true);
567+
}
568+
}
482569
},
483570

484571
/**
@@ -613,6 +700,16 @@ var Color = this.Color = Base.extend(new function() {
613700
color._type = type;
614701
color._components = components;
615702
color._alpha = alpha;
703+
if (type === 'gradient') {
704+
// Make sure gradients always have an id
705+
color._id = ++Base._uid;
706+
// Clone all points:
707+
for (var i = 1, l = components.length; i < l; i++) {
708+
var point = components[i];
709+
if (point)
710+
components[i] = point.clone();
711+
}
712+
}
616713
return color;
617714
},
618715

@@ -626,16 +723,18 @@ var Color = this.Color = Base.extend(new function() {
626723

627724
// Expose RgbColor, RGBColor, etc. constructors for backward compatibility.
628725
Base.each(Color._types, function(properties, type) {
629-
this[Base.capitalize(type) + 'Color'] = this[type.toUpperCase() + 'Color'] =
726+
var ctor = this[Base.capitalize(type) + 'Color'] =
630727
function(arg) {
631728
var argType = arg != null && typeof arg,
632-
components = argType === 'number'
633-
? arguments
634-
: argType === 'object' && arg.length != null
635-
? arg
636-
: null;
729+
components = argType === 'object' && arg.length != null
730+
? arg
731+
: argType === 'string'
732+
? null
733+
: arguments;
637734
return components
638735
? new Color(type, components)
639736
: new Color(arg);
640737
};
738+
if (!/^(gray|gradient)$/.test(type))
739+
this[type.toUpperCase() + 'Color'] = ctor;
641740
}, this);

src/color/Gradient.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ var Gradient = this.Gradient = Base.extend(/** @lends Gradient# */{
2929

3030
_serialize: function(options, dictionary) {
3131
return dictionary.add(this, function() {
32-
return Base.serialize([this._type, this._stops],
32+
return Base.serialize([this._stops, this._radial],
3333
options, true, dictionary);
3434
});
3535
},

src/color/GradientColor.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
* @class The GradientColor object.
1717
*/
1818
var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor# */{
19-
_type: 'gradient',
2019

2120
/**
2221
* Creates a gradient color object.
@@ -45,7 +44,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
4544
*
4645
* // Have the gradient color run between the topLeft and
4746
* // bottomRight points we defined earlier:
48-
* var gradientColor = new GradientColor(gradient, topLeft, bottomRight);
47+
* var gradientColor = new Color(gradient, topLeft, bottomRight);
4948
*
5049
* // Set the fill color of the path to the gradient color:
5150
* path.fillColor = gradientColor;
@@ -77,7 +76,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
7776
* var to = path.position + [80, 0];
7877
*
7978
* // Create the gradient color:
80-
* var gradientColor = new GradientColor(gradient, from, to);
79+
* var gradientColor = new Color(gradient, from, to);
8180
*
8281
* // Set the fill color of the path to the gradient color:
8382
* path.fillColor = gradientColor;
@@ -145,7 +144,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
145144
* // to the bottom right point of the view:
146145
* var from = view.bounds.topLeft;
147146
* var to = view.bounds.bottomRight;
148-
* var gradientColor = new GradientColor(gradient, from, to);
147+
* var gradientColor = new Color(gradient, from, to);
149148
* path.fillColor = gradientColor;
150149
*
151150
* function onMouseMove(event) {
@@ -185,7 +184,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
185184
* var gradient = new Gradient(['yellow', 'red', 'black'], true);
186185
* var from = view.center;
187186
* var to = view.bounds.bottomRight;
188-
* var gradientColor = new GradientColor(gradient, from, to);
187+
* var gradientColor = new Color(gradient, from, to);
189188
* path.fillColor = gradientColor;
190189
*
191190
* function onMouseMove(event) {
@@ -221,7 +220,7 @@ var GradientColor = this.GradientColor = Color.extend(/** @lends GradientColor#
221220
* var gradient = new Gradient(['yellow', 'red', 'black'], true);
222221
* var from = path.position;
223222
* var to = path.bounds.rightCenter;
224-
* var gradientColor = new GradientColor(gradient, from, to);
223+
* var gradientColor = new Color(gradient, from, to);
225224
*
226225
* path.fillColor = gradientColor;
227226
*

src/color/GradientStop.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
5454
},
5555

5656
_serialize: function(options, dictionary) {
57-
return Base.serialize([this._color, this._rampPoint], options, false,
57+
return Base.serialize([this._color, this._rampPoint], options, true,
5858
dictionary);
5959
},
6060

@@ -92,7 +92,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
9292
* var gradient = new Gradient(colors, true);
9393
* var from = path.position;
9494
* var to = path.bounds.rightCenter;
95-
* var gradientColor = new GradientColor(gradient, from, to);
95+
* var gradientColor = new Color(gradient, from, to);
9696
*
9797
* path.fillColor = gradientColor;
9898
*
@@ -141,7 +141,7 @@ var GradientStop = this.GradientStop = Base.extend(/** @lends GradientStop# */{
141141
* // to the right center of its bounding rectangle:
142142
* var from = path.position;
143143
* var to = path.bounds.rightCenter;
144-
* var gradientColor = new GradientColor(gradient, from, to);
144+
* var gradientColor = new Color(gradient, from, to);
145145
* path.fillColor = gradientColor;
146146
*
147147
* // This function is called each frame of the animation:

0 commit comments

Comments
 (0)