diff --git a/lib/cielab_color.dart b/lib/cielab_color.dart index 6b86ad6..04fe839 100644 --- a/lib/cielab_color.dart +++ b/lib/cielab_color.dart @@ -48,6 +48,8 @@ class CielabColor extends Color { return new XyzColor(xyz['x'], xyz['y'], xyz['z']); } + RgbaColor toRgbaColor() => this.toRgbColor().toRgbaColor(); + CielabColor toCielabColor() => this; String toString() => "l: $l, a: $a, b: $b"; diff --git a/lib/color.dart b/lib/color.dart index d940cc4..9f01697 100644 --- a/lib/color.dart +++ b/lib/color.dart @@ -10,6 +10,7 @@ library color; import 'dart:math'; part 'rgb_color.dart'; +part 'rgba_color.dart'; part 'hex_color.dart'; part 'hsl_color.dart'; part 'xyz_color.dart'; @@ -33,12 +34,14 @@ part 'color_filter.dart'; abstract class Color { Color() {} factory Color.rgb(int r, int g, int b) => new RgbColor(r, g, b); + factory Color.rgba(int r, int g, int b, num a) => new RgbaColor(r, g, b, a); factory Color.hex(String hexCode) => new HexColor(hexCode); factory Color.hsl(num h, num s, num l) => new HslColor(h, s, l); factory Color.xyz(num x, num y, num z) => new XyzColor(x, y, z); factory Color.cielab(num l, num a, num b) => new CielabColor(l, a, b); RgbColor toRgbColor(); + RgbaColor toRgbaColor(); HslColor toHslColor(); XyzColor toXyzColor(); CielabColor toCielabColor(); @@ -49,8 +52,11 @@ abstract class Color { Color clone(); get hashCode { - RgbColor rgb = this.toRgbColor(); - return 256 * 256 * rgb.r + 256 * rgb.g + rgb.b; + RgbaColor rgba = this.toRgbaColor(); + return (pow(2, 30) * rgba.a).round() + + 256 * 256 * rgba.r + + 256 * rgba.g + + rgba.b; } operator ==(Object other) { @@ -71,6 +77,8 @@ abstract class Color { return this.toXyzColor(); case CielabColor: return this.toCielabColor(); + case RgbaColor: + return this.toRgbaColor(); default: return this; } diff --git a/lib/hsl_color.dart b/lib/hsl_color.dart index c73f12a..d8caa17 100644 --- a/lib/hsl_color.dart +++ b/lib/hsl_color.dart @@ -77,6 +77,8 @@ class HslColor extends Color { return new RgbColor(rgb[0], rgb[1], rgb[2]); } + RgbaColor toRgbaColor() => this.toRgbColor().toRgbaColor(); + HslColor toHslColor() => this; XyzColor toXyzColor() => this.toRgbColor().toXyzColor(); diff --git a/lib/rgb_color.dart b/lib/rgb_color.dart index b381b0b..e8026c0 100644 --- a/lib/rgb_color.dart +++ b/lib/rgb_color.dart @@ -92,6 +92,8 @@ class RgbColor extends Color { HexColor toHexColor() => new HexColor.fromRgb(_r, _g, _b); + RgbaColor toRgbaColor() => new Color.rgba(r, g, b, 1); + String toString() => "r: $r, g: $g, b: $b"; String toCssString() => 'rgb($r, $g, $b)'; diff --git a/lib/rgba_color.dart b/lib/rgba_color.dart new file mode 100644 index 0000000..53a5e6b --- /dev/null +++ b/lib/rgba_color.dart @@ -0,0 +1,40 @@ +part of color; + +class RgbaColor extends RgbColor { + static const int aMin = 0; + static const int aMax = 1; + + num _a; + get a => _a; + + set a(num a) => _a = max(aMin, min(aMax, a)); + + /** + * Creates a [Color] using a vector describing its red, green, blue and alpha + * values. + * + * The value for [r], [g], and [b] should be in the range between 0 and + * 255 (inclusive). Values above this range will be assumed to be a value + * of 255, and values below this range will be assumed to be a value of 0. + * The value for [a] should be between 0 and 1 (1 means + * opaque). + * + * Note that when converting an [RgbaColor] to a different color model that + * doesn't provide alpha information, the alpha data [a] will be dropped. + */ + RgbaColor(num r, num g, num b, num a) : super(r, g, b) { + this.a = a; + } + + RgbaColor toRgbaColor() => this; + + String toString() => "r: $r, g: $g, b: $b, a: $a"; + + String toCssString() => 'rgba($r, $g, $b, $a)'; + + Map toMap() { + return {'r': r, 'g': g, 'b': b, 'a': a}; + } + + RgbaColor clone() => new RgbaColor(this.r, this.g, this.b, this.a); +} diff --git a/lib/xyz_color.dart b/lib/xyz_color.dart index 1aedd5e..d920610 100644 --- a/lib/xyz_color.dart +++ b/lib/xyz_color.dart @@ -48,6 +48,8 @@ class XyzColor extends Color { return new RgbColor(rgb['r'], rgb['g'], rgb['b']); } + RgbaColor toRgbaColor() => this.toRgbColor().toRgbaColor(); + HslColor toHslColor() => this.toRgbColor().toHslColor(); XyzColor toXyzColor() => this; diff --git a/test/color_test.dart b/test/color_test.dart index 8b869a6..7088946 100644 --- a/test/color_test.dart +++ b/test/color_test.dart @@ -10,6 +10,14 @@ void main() { expect(color.g, equals(255)); expect(color.b, equals(238)); }); + test("through the Color.rgba constructor", () { + RgbaColor color = new Color.rgba(192, 255, 238, 0.5); + expect(color is Color, isTrue); + expect(color.r, equals(192)); + expect(color.g, equals(255)); + expect(color.b, equals(238)); + expect(color.a, equals(0.5)); + }); test("through the Color.hex constructor", () { HexColor color = new Color.hex('c0ffee'); expect(color is Color, isTrue); @@ -45,6 +53,14 @@ void main() { expect(color.g, equals(255)); expect(color.b, equals(238)); }); + test("as an RgbaColor", () { + RgbaColor color = new RgbaColor(192, 255, 238, 0.5); + expect(color is Color, isTrue); + expect(color.r, equals(192)); + expect(color.g, equals(255)); + expect(color.b, equals(238)); + expect(color.a, equals(0.5)); + }); test("as a HexColor", () { HexColor color = new HexColor('c0ffee'); expect(color is Color, isTrue); @@ -87,6 +103,11 @@ void main() { String string = color.toString(); expect(string, equals('r: 192, g: 255, b: 238')); }); + test("from an RgbaColor", () { + Color color = new Color.rgba(192, 255, 238, 0.5); + String string = color.toString(); + expect(string, equals('r: 192, g: 255, b: 238, a: 0.5')); + }); test("from a HexColor", () { Color color = new Color.hex('c0ffee'); String string = color.toString(); @@ -120,6 +141,11 @@ void main() { String string = color.toCssString(); expect(string, equals('rgb(192, 255, 238)')); }); + test("from an RgbaColor", () { + RgbColor color = new Color.rgba(192, 255, 238, 0.5); + String string = color.toCssString(); + expect(string, equals('rgba(192, 255, 238, 0.5)')); + }); test("from a HexColor", () { HexColor color = new Color.hex('c0ffee'); String string = color.toCssString(); @@ -162,6 +188,12 @@ void main() { expect(rgb, equals(rgbClone)); expect(identical(rgb, rgbClone), isFalse); }); + test("as rgba", () { + RgbaColor rgba = new RgbaColor(192, 255, 238, 0.5); + RgbaColor rgbaClone = rgba.clone(); + expect(rgba, equals(rgbaClone)); + expect(identical(rgba, rgbaClone), isFalse); + }); test("as hex", () { HexColor hex = new HexColor('c0ffee'); HexColor hexClone = hex.clone(); @@ -189,18 +221,24 @@ void main() { }); group("Colors can be converted", () { RgbColor rgb; + RgbaColor rgba; HexColor hex; HslColor hsl; XyzColor xyz; CielabColor cielab; setUp(() { rgb = new RgbColor(192, 255, 238); + rgba = new RgbaColor(192, 255, 238, 1); hex = new HexColor('c0ffee'); hsl = new HslColor(163.8, 100, 87.6); xyz = new XyzColor(72.931, 88.9, 94.204); cielab = new CielabColor(95.538, -23.02, 1.732); }); + test("from rgb to rgba", () { + RgbaColor conversion = rgb.toRgbaColor(); + expect(conversion, equals(rgba)); + }); test("from rgb to hex", () { HexColor conversion = rgb.toHexColor(); expect(conversion, equals(hex)); @@ -218,10 +256,35 @@ void main() { expect(conversion, equals(cielab)); }); + test("from rgba to rgb", () { + RgbColor conversion = rgba.toRgbColor(); + expect(conversion, equals(rgb)); + }); + test("from rgba to hex", () { + HexColor conversion = rgba.toHexColor(); + expect(conversion, equals(hex)); + }); + test("from rgba to hsl", () { + HslColor conversion = rgba.toHslColor(); + expect(conversion, equals(hsl)); + }); + test("from rgba to xyz", () { + XyzColor conversion = rgba.toXyzColor(); + expect(conversion, equals(xyz)); + }); + test("from rgba to cielab", () { + CielabColor conversion = rgba.toCielabColor(); + expect(conversion, equals(cielab)); + }); + test("from hex to rgb", () { RgbColor conversion = hex.toRgbColor(); expect(conversion, equals(rgb)); }); + test("from hex to rgba", () { + RgbaColor conversion = hex.toRgbaColor(); + expect(conversion, equals(rgba)); + }); test("from hex to hsl", () { HslColor conversion = hex.toHslColor(); expect(conversion, equals(hsl)); @@ -239,6 +302,10 @@ void main() { RgbColor conversion = hsl.toRgbColor(); expect(conversion, equals(rgb)); }); + test("from hsl to rgba", () { + RgbaColor conversion = hsl.toRgbaColor(); + expect(conversion, equals(rgba)); + }); test("from hsl to xyz", () { XyzColor conversion = hsl.toXyzColor(); expect(conversion, equals(hsl)); @@ -252,6 +319,10 @@ void main() { RgbColor conversion = xyz.toRgbColor(); expect(conversion, equals(rgb)); }); + test("from xyz to rgba", () { + RgbaColor conversion = xyz.toRgbaColor(); + expect(conversion, equals(rgba)); + }); test("from xyz to hsl", () { HslColor conversion = xyz.toHslColor(); expect(conversion, equals(hsl)); @@ -265,6 +336,10 @@ void main() { RgbColor conversion = cielab.toRgbColor(); expect(conversion, equals(rgb)); }); + test("from cielab to rgba", () { + RgbaColor conversion = cielab.toRgbaColor(); + expect(conversion, equals(rgba)); + }); test("from cielab to hsl", () { HslColor conversion = cielab.toHslColor(); expect(conversion, equals(hsl));