Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: lib/src/property.dart

Issue 998843003: pkg/csslib: formatting (Closed) Base URL: https://github.com/dart-lang/csslib@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** Representations of CSS styles. */ 5 /** Representations of CSS styles. */
6 6
7 part of csslib.parser; 7 part of csslib.parser;
8 8
9 // TODO(terry): Prune down this file we do need some of the code in this file 9 // TODO(terry): Prune down this file we do need some of the code in this file
10 // for darker, lighter, how to represent a Font, etc but alot of 10 // for darker, lighter, how to represent a Font, etc but alot of
(...skipping 11 matching lines...) Expand all
22 * 22 *
23 * E.g., if property is color then expression could be rgba(255,255,0) the 23 * E.g., if property is color then expression could be rgba(255,255,0) the
24 * CSS declaration would be 'color:rgba(255,255,0);'. 24 * CSS declaration would be 'color:rgba(255,255,0);'.
25 * 25 *
26 * then _cssExpression would return 'rgba(255,255,0)'. See 26 * then _cssExpression would return 'rgba(255,255,0)'. See
27 * <http://www.w3.org/TR/CSS21/grammar.html> 27 * <http://www.w3.org/TR/CSS21/grammar.html>
28 */ 28 */
29 String get cssExpression; 29 String get cssExpression;
30 } 30 }
31 31
32
33 /** 32 /**
34 * Base interface for Color, HSL and RGB. 33 * Base interface for Color, HSL and RGB.
35 */ 34 */
36 abstract class ColorBase { 35 abstract class ColorBase {
37 /** 36 /**
38 * Canonical form for color #rrggbb with alpha blending (0.0 == full 37 * Canonical form for color #rrggbb with alpha blending (0.0 == full
39 * transparency and 1.0 == fully opaque). If _argb length is 6 it's an 38 * transparency and 1.0 == fully opaque). If _argb length is 6 it's an
40 * rrggbb otherwise it's aarrggbb. 39 * rrggbb otherwise it's aarrggbb.
41 */ 40 */
42 String toHexArgbString(); 41 String toHexArgbString();
43 42
44 /** 43 /**
45 * Return argb as a value (int). 44 * Return argb as a value (int).
46 */ 45 */
47 int get argbValue; 46 int get argbValue;
48 } 47 }
49 48
50
51 /** 49 /**
52 * General purpse Color class. Represent a color as an ARGB value that can be 50 * General purpse Color class. Represent a color as an ARGB value that can be
53 * converted to and from num, hex string, hsl, hsla, rgb, rgba and SVG pre- 51 * converted to and from num, hex string, hsl, hsla, rgb, rgba and SVG pre-
54 * defined color constant. 52 * defined color constant.
55 */ 53 */
56 class Color implements _StyleProperty, ColorBase { 54 class Color implements _StyleProperty, ColorBase {
57 // If _argb length is 6 it's an rrggbb otherwise it's aarrggbb. 55 // If _argb length is 6 it's an rrggbb otherwise it's aarrggbb.
58 final String _argb; 56 final String _argb;
59 57
60 // TODO(terry): Look at reducing Rgba and Hsla classes as factories for 58 // TODO(terry): Look at reducing Rgba and Hsla classes as factories for
61 // converting from Color to an Rgba or Hsla for reading only. 59 // converting from Color to an Rgba or Hsla for reading only.
62 // Usefulness of creating an Rgba or Hsla is limited. 60 // Usefulness of creating an Rgba or Hsla is limited.
63 61
64 /** 62 /**
65 * Create a color with an integer representing the rgb value of red, green, 63 * Create a color with an integer representing the rgb value of red, green,
66 * and blue. The value 0xffffff is the color white #ffffff (CSS style). 64 * and blue. The value 0xffffff is the color white #ffffff (CSS style).
67 * The [rgb] value of 0xffd700 would map to #ffd700 or the constant 65 * The [rgb] value of 0xffd700 would map to #ffd700 or the constant
68 * Color.gold, where ff is red intensity, d7 is green intensity, and 00 is 66 * Color.gold, where ff is red intensity, d7 is green intensity, and 00 is
69 * blue intensity. 67 * blue intensity.
70 */ 68 */
71 Color(int rgb, [num alpha]) : 69 Color(int rgb, [num alpha]) : this._argb = Color._rgbToArgbString(rgb, alpha);
72 this._argb = Color._rgbToArgbString(rgb, alpha);
73 70
74 /** 71 /**
75 * RGB takes three values. The [red], [green], and [blue] parameters are 72 * RGB takes three values. The [red], [green], and [blue] parameters are
76 * the intensity of those components where '0' is the least and '256' is the 73 * the intensity of those components where '0' is the least and '256' is the
77 * greatest. 74 * greatest.
78 * 75 *
79 * If [alpha] is provided, it is the level of translucency which ranges from 76 * If [alpha] is provided, it is the level of translucency which ranges from
80 * '0' (completely transparent) to '1.0' (completely opaque). It will 77 * '0' (completely transparent) to '1.0' (completely opaque). It will
81 * internally be mapped to an int between '0' and '255' like the other color 78 * internally be mapped to an int between '0' and '255' like the other color
82 * components. 79 * components.
83 */ 80 */
84 Color.createRgba(int red, int green, int blue, [num alpha]) : 81 Color.createRgba(int red, int green, int blue, [num alpha])
85 this._argb = Color.convertToHexString(Color._clamp(red, 0, 255), 82 : this._argb = Color.convertToHexString(Color._clamp(red, 0, 255),
86 Color._clamp(green, 0, 255), 83 Color._clamp(green, 0, 255), Color._clamp(blue, 0, 255),
87 Color._clamp(blue, 0, 255),
88 alpha != null ? Color._clamp(alpha, 0, 1) : alpha); 84 alpha != null ? Color._clamp(alpha, 0, 1) : alpha);
89 85
90 /** 86 /**
91 * Creates a new color from a CSS color string. For more information, see 87 * Creates a new color from a CSS color string. For more information, see
92 * <https://developer.mozilla.org/en/CSS/color>. 88 * <https://developer.mozilla.org/en/CSS/color>.
93 */ 89 */
94 Color.css(String color) : 90 Color.css(String color) : this._argb = Color._convertCssToArgb(color);
95 this._argb = Color._convertCssToArgb(color);
96 91
97 // TODO(jmesserly): I found the use of percents a bit suprising. 92 // TODO(jmesserly): I found the use of percents a bit suprising.
98 /** 93 /**
99 * HSL takes three values. The [hueDegree] degree on the color wheel; '0' is 94 * HSL takes three values. The [hueDegree] degree on the color wheel; '0' is
100 * the least and '100' is the greatest. The value '0' or '360' is red, '120' 95 * the least and '100' is the greatest. The value '0' or '360' is red, '120'
101 * is green, '240' is blue. Numbers in between reflect different shades. 96 * is green, '240' is blue. Numbers in between reflect different shades.
102 * The [saturationPercent] percentage; where'0' is the least and '100' is the 97 * The [saturationPercent] percentage; where'0' is the least and '100' is the
103 * greatest (100 represents full color). The [lightnessPercent] percentage; 98 * greatest (100 represents full color). The [lightnessPercent] percentage;
104 * where'0' is the least and '100' is the greatest. The value 0 is dark or 99 * where'0' is the least and '100' is the greatest. The value 0 is dark or
105 * black, 100 is light or white and 50 is a medium lightness. 100 * black, 100 is light or white and 50 is a medium lightness.
106 * 101 *
107 * If [alpha] is provided, it is the level of translucency which ranges from 102 * If [alpha] is provided, it is the level of translucency which ranges from
108 * '0' (completely transparent foreground) to '1.0' (completely opaque 103 * '0' (completely transparent foreground) to '1.0' (completely opaque
109 * foreground). 104 * foreground).
110 */ 105 */
111 Color.createHsla(num hueDegree, num saturationPercent, num lightnessPercent, 106 Color.createHsla(num hueDegree, num saturationPercent, num lightnessPercent,
112 [num alpha]) : 107 [num alpha])
113 this._argb = new Hsla(Color._clamp(hueDegree, 0, 360) / 360, 108 : this._argb = new Hsla(Color._clamp(hueDegree, 0, 360) / 360,
114 Color._clamp(saturationPercent, 0, 100) / 100, 109 Color._clamp(saturationPercent, 0, 100) / 100,
115 Color._clamp(lightnessPercent, 0, 100) / 100, 110 Color._clamp(lightnessPercent, 0, 100) / 100,
116 alpha != null ? Color._clamp(alpha, 0, 1) : alpha).toHexArgbString(); 111 alpha != null ? Color._clamp(alpha, 0, 1) : alpha).toHexArgbString();
117 112
118 /** 113 /**
119 * The hslaRaw takes three values. The [hue] degree on the color wheel; '0' 114 * The hslaRaw takes three values. The [hue] degree on the color wheel; '0'
120 * is the least and '1' is the greatest. The value '0' or '1' is red, the 115 * is the least and '1' is the greatest. The value '0' or '1' is red, the
121 * ratio of 120/360 is green, and the ratio of 240/360 is blue. Numbers in 116 * ratio of 120/360 is green, and the ratio of 240/360 is blue. Numbers in
122 * between reflect different shades. The [saturation] is a percentage; '0' 117 * between reflect different shades. The [saturation] is a percentage; '0'
123 * is the least and '1' is the greatest. The value of '1' is equivalent to 118 * is the least and '1' is the greatest. The value of '1' is equivalent to
124 * 100% (full colour). The [lightness] is a percentage; '0' is the least and 119 * 100% (full colour). The [lightness] is a percentage; '0' is the least and
125 * '1' is the greatest. The value of '0' is dark (black), the value of '1' 120 * '1' is the greatest. The value of '0' is dark (black), the value of '1'
126 * is light (white), and the value of '.50' is a medium lightness. 121 * is light (white), and the value of '.50' is a medium lightness.
127 * 122 *
128 * The fourth optional parameter is: 123 * The fourth optional parameter is:
129 * [alpha] level of translucency range of values is 0..1, zero is a 124 * [alpha] level of translucency range of values is 0..1, zero is a
130 * completely transparent foreground and 1 is a completely 125 * completely transparent foreground and 1 is a completely
131 * opaque foreground. 126 * opaque foreground.
132 */ 127 */
133 Color.hslaRaw(num hue, num saturation, num lightness, [num alpha]) : 128 Color.hslaRaw(num hue, num saturation, num lightness, [num alpha])
134 this._argb = new Hsla(Color._clamp(hue, 0, 1), 129 : this._argb = new Hsla(Color._clamp(hue, 0, 1),
135 Color._clamp(saturation, 0, 1), 130 Color._clamp(saturation, 0, 1), Color._clamp(lightness, 0, 1),
136 Color._clamp(lightness, 0, 1),
137 alpha != null ? Color._clamp(alpha, 0, 1) : alpha).toHexArgbString(); 131 alpha != null ? Color._clamp(alpha, 0, 1) : alpha).toHexArgbString();
138 132
139 /** 133 /**
140 * Generate a real constant for pre-defined colors (no leading #). 134 * Generate a real constant for pre-defined colors (no leading #).
141 */ 135 */
142 const Color.hex(this._argb); 136 const Color.hex(this._argb);
143 137
144 // TODO(jmesserly): this is needed by the example so leave it exposed for now. 138 // TODO(jmesserly): this is needed by the example so leave it exposed for now.
145 String toString() => cssExpression; 139 String toString() => cssExpression;
146 140
147 // TODO(terry): Regardless of how color is set (rgb, num, css or hsl) we'll 141 // TODO(terry): Regardless of how color is set (rgb, num, css or hsl) we'll
148 // always return a rgb or rgba loses fidelity when debugging in 142 // always return a rgb or rgba loses fidelity when debugging in
149 // CSS if user uses hsl and would like to edit as hsl, etc. If 143 // CSS if user uses hsl and would like to edit as hsl, etc. If
150 // this is an issue we should keep the original value and not re- 144 // this is an issue we should keep the original value and not re-
151 // create the CSS from the normalized value. 145 // create the CSS from the normalized value.
152 String get cssExpression { 146 String get cssExpression {
153 if (_argb.length == 6) { 147 if (_argb.length == 6) {
154 return "#$_argb"; // RGB only, no alpha blending. 148 return "#$_argb"; // RGB only, no alpha blending.
155 } else { 149 } else {
156 num alpha = Color.hexToInt(_argb.substring(0, 2)); 150 num alpha = Color.hexToInt(_argb.substring(0, 2));
157 String a = (alpha / 255).toStringAsPrecision(2); 151 String a = (alpha / 255).toStringAsPrecision(2);
158 int r = Color.hexToInt(_argb.substring(2, 4)); 152 int r = Color.hexToInt(_argb.substring(2, 4));
159 int g = Color.hexToInt(_argb.substring(4, 6)); 153 int g = Color.hexToInt(_argb.substring(4, 6));
160 int b = Color.hexToInt(_argb.substring(6, 8)); 154 int b = Color.hexToInt(_argb.substring(6, 8));
161 return "rgba($r,$g,$b,$a)"; 155 return "rgba($r,$g,$b,$a)";
162 } 156 }
163 } 157 }
164 158
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 /** 233 /**
240 * Parse CSS expressions of the from #rgb, rgb(r,g,b), rgba(r,g,b,a), 234 * Parse CSS expressions of the from #rgb, rgb(r,g,b), rgba(r,g,b,a),
241 * hsl(h,s,l), hsla(h,s,l,a) and SVG colors (e.g., darkSlateblue, etc.) and 235 * hsl(h,s,l), hsla(h,s,l,a) and SVG colors (e.g., darkSlateblue, etc.) and
242 * convert to argb. 236 * convert to argb.
243 */ 237 */
244 static String _convertCssToArgb(String value) { 238 static String _convertCssToArgb(String value) {
245 // TODO(terry): Better parser/regex for converting CSS properties. 239 // TODO(terry): Better parser/regex for converting CSS properties.
246 String color = value.trim().replaceAll("\\s", ""); 240 String color = value.trim().replaceAll("\\s", "");
247 if (color[0] == '#') { 241 if (color[0] == '#') {
248 String v = color.substring(1); 242 String v = color.substring(1);
249 Color.hexToInt(v); // Valid hexadecimal, throws if not. 243 Color.hexToInt(v); // Valid hexadecimal, throws if not.
250 return v; 244 return v;
251 } else if (color.length > 0 && color[color.length - 1] == ')') { 245 } else if (color.length > 0 && color[color.length - 1] == ')') {
252 int type; 246 int type;
253 if (color.indexOf("rgb(") == 0 || color.indexOf("RGB(") == 0) { 247 if (color.indexOf("rgb(") == 0 || color.indexOf("RGB(") == 0) {
254 color = color.substring(4); 248 color = color.substring(4);
255 type = _rgbCss; 249 type = _rgbCss;
256 } else if (color.indexOf("rgba(") == 0 || color.indexOf("RGBA(") == 0) { 250 } else if (color.indexOf("rgba(") == 0 || color.indexOf("RGBA(") == 0) {
257 type = _rgbaCss; 251 type = _rgbaCss;
258 color = color.substring(5); 252 color = color.substring(5);
259 } else if (color.indexOf("hsl(") == 0 || color.indexOf("HSL(") == 0) { 253 } else if (color.indexOf("hsl(") == 0 || color.indexOf("HSL(") == 0) {
260 type = _hslCss; 254 type = _hslCss;
261 color = color.substring(4); 255 color = color.substring(4);
262 } else if (color.indexOf("hsla(") == 0 || color.indexOf("HSLA(") == 0) { 256 } else if (color.indexOf("hsla(") == 0 || color.indexOf("HSLA(") == 0) {
263 type = _hslaCss; 257 type = _hslaCss;
264 color = color.substring(5); 258 color = color.substring(5);
265 } else { 259 } else {
266 throw new UnsupportedError('CSS property not implemented'); 260 throw new UnsupportedError('CSS property not implemented');
267 } 261 }
268 262
269 color = color.substring(0, color.length - 1); // Strip close paren. 263 color = color.substring(0, color.length - 1); // Strip close paren.
270 264
271 var args = <num>[]; 265 var args = <num>[];
272 List<String> params = color.split(","); 266 List<String> params = color.split(",");
273 for (String param in params) { 267 for (String param in params) {
274 args.add(double.parse(param)); 268 args.add(double.parse(param));
275 } 269 }
276 switch (type) { 270 switch (type) {
277 case _rgbCss: 271 case _rgbCss:
278 return Color.convertToHexString(args[0], args[1], args[2]); 272 return Color.convertToHexString(args[0], args[1], args[2]);
279 case _rgbaCss: 273 case _rgbaCss:
280 return Color.convertToHexString(args[0], args[1], args[2], args[3]); 274 return Color.convertToHexString(args[0], args[1], args[2], args[3]);
281 case _hslCss: 275 case _hslCss:
282 return new Hsla(args[0], args[1], args[2]).toHexArgbString(); 276 return new Hsla(args[0], args[1], args[2]).toHexArgbString();
283 case _hslaCss: 277 case _hslaCss:
284 return new Hsla(args[0], args[1], args[2], 278 return new Hsla(args[0], args[1], args[2], args[3]).toHexArgbString();
285 args[3]).toHexArgbString();
286 default: 279 default:
287 // Type not defined UnsupportedOperationException should have thrown. 280 // Type not defined UnsupportedOperationException should have thrown.
288 assert(true); 281 assert(true);
289 break; 282 break;
290 } 283 }
291 } 284 }
292 } 285 }
293 286
294 static int hexToInt(String hex) => int.parse(hex, radix: 16); 287 static int hexToInt(String hex) => int.parse(hex, radix: 16);
295 288
296 static String convertToHexString(int r, int g, int b, [num a]) { 289 static String convertToHexString(int r, int g, int b, [num a]) {
297 String rHex = Color._numAs2DigitHex(Color._clamp(r, 0, 255)); 290 String rHex = Color._numAs2DigitHex(Color._clamp(r, 0, 255));
298 String gHex = Color._numAs2DigitHex(Color._clamp(g, 0, 255)); 291 String gHex = Color._numAs2DigitHex(Color._clamp(g, 0, 255));
299 String bHex = Color._numAs2DigitHex(Color._clamp(b, 0, 255)); 292 String bHex = Color._numAs2DigitHex(Color._clamp(b, 0, 255));
300 String aHex = (a != null) ? 293 String aHex = (a != null)
301 Color._numAs2DigitHex((Color._clamp(a, 0, 1) * 255).round()) : ""; 294 ? Color._numAs2DigitHex((Color._clamp(a, 0, 1) * 255).round())
295 : "";
302 296
303 // TODO(terry) 15.toRadixString(16) return 'F' on Dartium not f as in JS. 297 // TODO(terry) 15.toRadixString(16) return 'F' on Dartium not f as in JS.
304 // bug: <http://code.google.com/p/dart/issues/detail?id=2670> 298 // bug: <http://code.google.com/p/dart/issues/detail?id=2670>
305 return "$aHex$rHex$gHex$bHex".toLowerCase(); 299 return "$aHex$rHex$gHex$bHex".toLowerCase();
306 } 300 }
307 301
308 static String _numAs2DigitHex(num v) { 302 static String _numAs2DigitHex(num v) {
309 // TODO(terry): v.toInt().toRadixString instead of v.toRadixString 303 // TODO(terry): v.toInt().toRadixString instead of v.toRadixString
310 // Bug <http://code.google.com/p/dart/issues/detail?id=2671>. 304 // Bug <http://code.google.com/p/dart/issues/detail?id=2671>.
311 String hex = v.toInt().toRadixString(16); 305 String hex = v.toInt().toRadixString(16);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 /** 348 /**
355 * The parameter [v] is the color to change (r, g, or b) in the range '0' to 349 * The parameter [v] is the color to change (r, g, or b) in the range '0' to
356 * '255'. The parameter [delta] is a number between '-1' and '1'. A value 350 * '255'. The parameter [delta] is a number between '-1' and '1'. A value
357 * between '-1' and '0' is darker and a value between '0' and '1' is lighter 351 * between '-1' and '0' is darker and a value between '0' and '1' is lighter
358 * ('0' imples no change). 352 * ('0' imples no change).
359 */ 353 */
360 static num _changeTintShadeColor(num v, num delta) => 354 static num _changeTintShadeColor(num v, num delta) =>
361 Color._clamp(((1 - delta) * v + (delta * 255)).round(), 0, 255); 355 Color._clamp(((1 - delta) * v + (delta * 255)).round(), 0, 255);
362 356
363 // Predefined CSS colors see <http://www.w3.org/TR/css3-color/> 357 // Predefined CSS colors see <http://www.w3.org/TR/css3-color/>
364 static final Color transparent = const Color.hex("00ffffff"); // Alpha 0.0 358 static final Color transparent = const Color.hex("00ffffff"); // Alpha 0.0
365 static final Color aliceBlue = const Color.hex("0f08ff"); 359 static final Color aliceBlue = const Color.hex("0f08ff");
366 static final Color antiqueWhite = const Color.hex("0faebd7"); 360 static final Color antiqueWhite = const Color.hex("0faebd7");
367 static final Color aqua = const Color.hex("00ffff"); 361 static final Color aqua = const Color.hex("00ffff");
368 static final Color aquaMarine = const Color.hex("7fffd4"); 362 static final Color aquaMarine = const Color.hex("7fffd4");
369 static final Color azure = const Color.hex("f0ffff"); 363 static final Color azure = const Color.hex("f0ffff");
370 static final Color beige = const Color.hex("f5f5dc"); 364 static final Color beige = const Color.hex("f5f5dc");
371 static final Color bisque = const Color.hex("ffe4c4"); 365 static final Color bisque = const Color.hex("ffe4c4");
372 static final Color black = const Color.hex("000000"); 366 static final Color black = const Color.hex("000000");
373 static final Color blanchedAlmond = const Color.hex("ffebcd"); 367 static final Color blanchedAlmond = const Color.hex("ffebcd");
374 static final Color blue = const Color.hex("0000ff"); 368 static final Color blue = const Color.hex("0000ff");
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 static final Color tomato = const Color.hex("ff6347"); 498 static final Color tomato = const Color.hex("ff6347");
505 static final Color turquoise = const Color.hex("40e0d0"); 499 static final Color turquoise = const Color.hex("40e0d0");
506 static final Color violet = const Color.hex("ee82ee"); 500 static final Color violet = const Color.hex("ee82ee");
507 static final Color wheat = const Color.hex("f5deb3"); 501 static final Color wheat = const Color.hex("f5deb3");
508 static final Color white = const Color.hex("ffffff"); 502 static final Color white = const Color.hex("ffffff");
509 static final Color whiteSmoke = const Color.hex("f5f5f5"); 503 static final Color whiteSmoke = const Color.hex("f5f5f5");
510 static final Color yellow = const Color.hex("ffff00"); 504 static final Color yellow = const Color.hex("ffff00");
511 static final Color yellowGreen = const Color.hex("9acd32"); 505 static final Color yellowGreen = const Color.hex("9acd32");
512 } 506 }
513 507
514
515 /** 508 /**
516 * Rgba class for users that want to interact with a color as a RGBA value. 509 * Rgba class for users that want to interact with a color as a RGBA value.
517 */ 510 */
518 class Rgba implements _StyleProperty, ColorBase { 511 class Rgba implements _StyleProperty, ColorBase {
519 // TODO(terry): Consider consolidating rgba to a single 32-bit int, make sure 512 // TODO(terry): Consider consolidating rgba to a single 32-bit int, make sure
520 // it works under JS and Dart VM. 513 // it works under JS and Dart VM.
521 final int r; 514 final int r;
522 final int g; 515 final int g;
523 final int b; 516 final int b;
524 final num a; 517 final num a;
525 518
526 Rgba(int red, int green, int blue, [num alpha]) : 519 Rgba(int red, int green, int blue, [num alpha])
527 this.r = Color._clamp(red, 0, 255), 520 : this.r = Color._clamp(red, 0, 255),
528 this.g = Color._clamp(green, 0, 255), 521 this.g = Color._clamp(green, 0, 255),
529 this.b = Color._clamp(blue, 0, 255), 522 this.b = Color._clamp(blue, 0, 255),
530 this.a = (alpha != null) ? Color._clamp(alpha, 0, 1) : alpha; 523 this.a = (alpha != null) ? Color._clamp(alpha, 0, 1) : alpha;
531 524
532 factory Rgba.fromString(String hexValue) => 525 factory Rgba.fromString(String hexValue) =>
533 new Color.css("#${Color._convertCssToArgb(hexValue)}").rgba; 526 new Color.css("#${Color._convertCssToArgb(hexValue)}").rgba;
534 527
535 factory Rgba.fromColor(Color color) => color.rgba; 528 factory Rgba.fromColor(Color color) => color.rgba;
536 529
537 factory Rgba.fromArgbValue(num value) { 530 factory Rgba.fromArgbValue(num value) {
538 return new Rgba(((value.toInt() & 0xff000000) >> 0x18), /* a */ 531 return new Rgba(((value.toInt() & 0xff000000) >> 0x18), /* a */
539 ((value.toInt() & 0xff0000) >> 0x10), /* r */ 532 ((value.toInt() & 0xff0000) >> 0x10), /* r */
540 ((value.toInt() & 0xff00) >> 8), /* g */ 533 ((value.toInt() & 0xff00) >> 8), /* g */
541 ((value.toInt() & 0xff))); /* b */ 534 ((value.toInt() & 0xff))); /* b */
542 } 535 }
543 536
544 factory Rgba.fromHsla(Hsla hsla) { 537 factory Rgba.fromHsla(Hsla hsla) {
545 // Convert to Rgba. 538 // Convert to Rgba.
546 // See site <http://easyrgb.com/index.php?X=MATH> for good documentation 539 // See site <http://easyrgb.com/index.php?X=MATH> for good documentation
547 // and color conversion routines. 540 // and color conversion routines.
548 541
549 num h = hsla.hue; 542 num h = hsla.hue;
550 num s = hsla.saturation; 543 num s = hsla.saturation;
551 num l = hsla.lightness; 544 num l = hsla.lightness;
(...skipping 10 matching lines...) Expand all
562 } else { 555 } else {
563 num var2; 556 num var2;
564 557
565 if (l < 0.5) { 558 if (l < 0.5) {
566 var2 = l * (1 + s); 559 var2 = l * (1 + s);
567 } else { 560 } else {
568 var2 = (l + s) - (s * l); 561 var2 = (l + s) - (s * l);
569 } 562 }
570 num var1 = 2 * l - var2; 563 num var1 = 2 * l - var2;
571 564
572 r = (255 * Rgba._hueToRGB(var1, var2, h + (1/3))).round().toInt(); 565 r = (255 * Rgba._hueToRGB(var1, var2, h + (1 / 3))).round().toInt();
573 g = (255 * Rgba._hueToRGB(var1, var2, h)).round().toInt(); 566 g = (255 * Rgba._hueToRGB(var1, var2, h)).round().toInt();
574 b = (255 * Rgba._hueToRGB(var1, var2, h - (1/3))).round().toInt(); 567 b = (255 * Rgba._hueToRGB(var1, var2, h - (1 / 3))).round().toInt();
575 } 568 }
576 569
577 return new Rgba(r, g, b, a); 570 return new Rgba(r, g, b, a);
578 } 571 }
579 572
580 static num _hueToRGB(num v1, num v2, num vH) { 573 static num _hueToRGB(num v1, num v2, num vH) {
581 if (vH < 0) { 574 if (vH < 0) {
582 vH += 1; 575 vH += 1;
583 } 576 }
584 577
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 618
626 Color get color => new Color.createRgba(r, g, b, a); 619 Color get color => new Color.createRgba(r, g, b, a);
627 Hsla get hsla => new Hsla.fromRgba(this); 620 Hsla get hsla => new Hsla.fromRgba(this);
628 621
629 Rgba darker(num amount) => Color._createNewTintShadeFromRgba(this, -amount); 622 Rgba darker(num amount) => Color._createNewTintShadeFromRgba(this, -amount);
630 Rgba lighter(num amount) => Color._createNewTintShadeFromRgba(this, amount); 623 Rgba lighter(num amount) => Color._createNewTintShadeFromRgba(this, amount);
631 624
632 int get hashCode => toHexArgbString().hashCode; 625 int get hashCode => toHexArgbString().hashCode;
633 } 626 }
634 627
635
636 /** 628 /**
637 * Hsl class support to interact with a color as a hsl with hue, saturation, and 629 * Hsl class support to interact with a color as a hsl with hue, saturation, and
638 * lightness with optional alpha blending. The hue is a ratio of 360 degrees 630 * lightness with optional alpha blending. The hue is a ratio of 360 degrees
639 * 360° = 1 or 0, (1° == (1/360)), saturation and lightness is a 0..1 fraction 631 * 360° = 1 or 0, (1° == (1/360)), saturation and lightness is a 0..1 fraction
640 * (1 == 100%) and alpha is a 0..1 fraction. 632 * (1 == 100%) and alpha is a 0..1 fraction.
641 */ 633 */
642 class Hsla implements _StyleProperty, ColorBase { 634 class Hsla implements _StyleProperty, ColorBase {
643 final num _h; // Value from 0..1 635 final num _h; // Value from 0..1
644 final num _s; // Value from 0..1 636 final num _s; // Value from 0..1
645 final num _l; // Value from 0..1 637 final num _l; // Value from 0..1
646 final num _a; // Value from 0..1 638 final num _a; // Value from 0..1
647 639
648 /** 640 /**
649 * [hue] is a 0..1 fraction of 360 degrees (360 == 0). 641 * [hue] is a 0..1 fraction of 360 degrees (360 == 0).
650 * [saturation] is a 0..1 fraction (100% == 1). 642 * [saturation] is a 0..1 fraction (100% == 1).
651 * [lightness] is a 0..1 fraction (100% == 1). 643 * [lightness] is a 0..1 fraction (100% == 1).
652 * [alpha] is a 0..1 fraction, alpha blending between 0..1, 1 == 100% opaque. 644 * [alpha] is a 0..1 fraction, alpha blending between 0..1, 1 == 100% opaque.
653 */ 645 */
654 Hsla(num hue, num saturation, num lightness, [num alpha]) : 646 Hsla(num hue, num saturation, num lightness, [num alpha])
655 this._h = (hue == 1) ? 0 : Color._clamp(hue, 0, 1), 647 : this._h = (hue == 1) ? 0 : Color._clamp(hue, 0, 1),
656 this._s = Color._clamp(saturation, 0, 1), 648 this._s = Color._clamp(saturation, 0, 1),
657 this._l = Color._clamp(lightness, 0, 1), 649 this._l = Color._clamp(lightness, 0, 1),
658 this._a = (alpha != null) ? Color._clamp(alpha, 0, 1) : alpha; 650 this._a = (alpha != null) ? Color._clamp(alpha, 0, 1) : alpha;
659 651
660 factory Hsla.fromString(String hexValue) { 652 factory Hsla.fromString(String hexValue) {
661 Rgba rgba = new Color.css("#${Color._convertCssToArgb(hexValue)}").rgba; 653 Rgba rgba = new Color.css("#${Color._convertCssToArgb(hexValue)}").rgba;
662 return _createFromRgba(rgba.r, rgba.g, rgba.b, rgba.a); 654 return _createFromRgba(rgba.r, rgba.g, rgba.b, rgba.a);
663 } 655 }
664 656
665 factory Hsla.fromColor(Color color) { 657 factory Hsla.fromColor(Color color) {
666 Rgba rgba = color.rgba; 658 Rgba rgba = color.rgba;
667 return _createFromRgba(rgba.r, rgba.g, rgba.b, rgba.a); 659 return _createFromRgba(rgba.r, rgba.g, rgba.b, rgba.a);
668 } 660 }
669 661
670 factory Hsla.fromArgbValue(num value) { 662 factory Hsla.fromArgbValue(num value) {
671 num a = (value.toInt() & 0xff000000) >> 0x18; 663 num a = (value.toInt() & 0xff000000) >> 0x18;
672 int r = (value.toInt() & 0xff0000) >> 0x10; 664 int r = (value.toInt() & 0xff0000) >> 0x10;
673 int g = (value.toInt() & 0xff00) >> 8; 665 int g = (value.toInt() & 0xff00) >> 8;
674 int b = value.toInt() & 0xff; 666 int b = value.toInt() & 0xff;
675 667
676 // Convert alpha to 0..1 from (0..255). 668 // Convert alpha to 0..1 from (0..255).
677 if (a != null) { 669 if (a != null) {
678 a = double.parse((a / 255).toStringAsPrecision(2)); 670 a = double.parse((a / 255).toStringAsPrecision(2));
679 } 671 }
680 672
681 return _createFromRgba(r, g, b, a); 673 return _createFromRgba(r, g, b, a);
682 } 674 }
683 675
684 factory Hsla.fromRgba(Rgba rgba) => 676 factory Hsla.fromRgba(Rgba rgba) =>
685 _createFromRgba(rgba.r, rgba.g, rgba.b, rgba.a); 677 _createFromRgba(rgba.r, rgba.g, rgba.b, rgba.a);
686 678
687 static Hsla _createFromRgba(num r, num g, num b, num a) { 679 static Hsla _createFromRgba(num r, num g, num b, num a) {
688 // Convert RGB to hsl. 680 // Convert RGB to hsl.
689 // See site <http://easyrgb.com/index.php?X=MATH> for good documentation 681 // See site <http://easyrgb.com/index.php?X=MATH> for good documentation
690 // and color conversion routines. 682 // and color conversion routines.
691 r /= 255; 683 r /= 255;
692 g /= 255; 684 g /= 255;
693 b /= 255; 685 b /= 255;
694 686
695 // Hue, saturation and lightness. 687 // Hue, saturation and lightness.
696 num h; 688 num h;
697 num s; 689 num s;
698 num l; 690 num l;
699 691
700 num minRgb = math.min(r, math.min(g, b)); 692 num minRgb = math.min(r, math.min(g, b));
701 num maxRgb = math.max(r, math.max(g, b)); 693 num maxRgb = math.max(r, math.max(g, b));
702 l = (maxRgb + minRgb) / 2; 694 l = (maxRgb + minRgb) / 2;
703 if (l <= 0) { 695 if (l <= 0) {
704 return new Hsla(0, 0, l); // Black; 696 return new Hsla(0, 0, l); // Black;
705 } 697 }
706 698
707 num vm = maxRgb - minRgb; 699 num vm = maxRgb - minRgb;
708 s = vm; 700 s = vm;
709 if (s > 0) { 701 if (s > 0) {
710 s /= (l < 0.5) ? (maxRgb + minRgb) : (2 - maxRgb - minRgb); 702 s /= (l < 0.5) ? (maxRgb + minRgb) : (2 - maxRgb - minRgb);
711 } else { 703 } else {
712 return new Hsla(0, 0, l); // White 704 return new Hsla(0, 0, l); // White
713 } 705 }
714 706
715 num r2, g2, b2; 707 num r2, g2, b2;
716 r2 = (maxRgb - r) / vm; 708 r2 = (maxRgb - r) / vm;
717 g2 = (maxRgb - g) / vm; 709 g2 = (maxRgb - g) / vm;
718 b2 = (maxRgb - b) / vm; 710 b2 = (maxRgb - b) / vm;
719 if (r == maxRgb) { 711 if (r == maxRgb) {
720 h = (g == minRgb) ? 5.0 + b2 : 1 - g2; 712 h = (g == minRgb) ? 5.0 + b2 : 1 - g2;
721 } else if (g == maxRgb) { 713 } else if (g == maxRgb) {
722 h = (b == minRgb) ? 1 + r2 : 3 - b2; 714 h = (b == minRgb) ? 1 + r2 : 3 - b2;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 */ 750 */
759 num get lightnessPercentage => (_l * 100).round(); 751 num get lightnessPercentage => (_l * 100).round();
760 752
761 /** 753 /**
762 * Returns number as 0..1 754 * Returns number as 0..1
763 */ 755 */
764 num get alpha => _a; 756 num get alpha => _a;
765 757
766 bool operator ==(other) => Color.equal(this, other); 758 bool operator ==(other) => Color.equal(this, other);
767 759
768 String get cssExpression => (_a == null) ? 760 String get cssExpression => (_a == null)
769 "hsl($hueDegrees,$saturationPercentage,$lightnessPercentage)" : 761 ? "hsl($hueDegrees,$saturationPercentage,$lightnessPercentage)"
770 "hsla($hueDegrees,$saturationPercentage,$lightnessPercentage,$_a)"; 762 : "hsla($hueDegrees,$saturationPercentage,$lightnessPercentage,$_a)";
771 763
772 String toHexArgbString() => new Rgba.fromHsla(this).toHexArgbString(); 764 String toHexArgbString() => new Rgba.fromHsla(this).toHexArgbString();
773 765
774 int get argbValue => Color.hexToInt(this.toHexArgbString()); 766 int get argbValue => Color.hexToInt(this.toHexArgbString());
775 767
776 Color get color => new Color.createHsla(_h, _s, _l, _a); 768 Color get color => new Color.createHsla(_h, _s, _l, _a);
777 Rgba get rgba => new Rgba.fromHsla(this); 769 Rgba get rgba => new Rgba.fromHsla(this);
778 770
779 Hsla darker(num amount) => 771 Hsla darker(num amount) =>
780 new Hsla.fromRgba(new Rgba.fromHsla(this).darker(amount)); 772 new Hsla.fromRgba(new Rgba.fromHsla(this).darker(amount));
781 773
782 Hsla lighter(num amount) => 774 Hsla lighter(num amount) =>
783 new Hsla.fromRgba(new Rgba.fromHsla(this).lighter(amount)); 775 new Hsla.fromRgba(new Rgba.fromHsla(this).lighter(amount));
784 776
785 int get hashCode => toHexArgbString().hashCode; 777 int get hashCode => toHexArgbString().hashCode;
786 } 778 }
787 779
788
789 /** X,Y position. */ 780 /** X,Y position. */
790 class PointXY implements _StyleProperty { 781 class PointXY implements _StyleProperty {
791 final num x, y; 782 final num x, y;
792 const PointXY(this.x, this.y); 783 const PointXY(this.x, this.y);
793 784
794 String get cssExpression { 785 String get cssExpression {
795 // TODO(terry): TBD 786 // TODO(terry): TBD
796 } 787 }
797 } 788 }
798 789
799
800 // TODO(terry): Implement style and color. 790 // TODO(terry): Implement style and color.
801 /** 791 /**
802 * Supports border for measuring with layout. 792 * Supports border for measuring with layout.
803 */ 793 */
804 class Border implements _StyleProperty { 794 class Border implements _StyleProperty {
805 final int top, left, bottom, right; 795 final int top, left, bottom, right;
806 796
807 // TODO(terry): Just like CSS, 1-arg -> set all properties, 2-args -> top and 797 // TODO(terry): Just like CSS, 1-arg -> set all properties, 2-args -> top and
808 // bottom are first arg, left and right are second, 3-args, and 798 // bottom are first arg, left and right are second, 3-args, and
809 // 4-args -> tlbr or trbl. 799 // 4-args -> tlbr or trbl.
810 const Border([this.top, this.left, this.bottom, this.right]); 800 const Border([this.top, this.left, this.bottom, this.right]);
811 801
812 // TODO(terry): Consider using Size or width and height. 802 // TODO(terry): Consider using Size or width and height.
813 Border.uniform(num amount) : 803 Border.uniform(num amount)
814 top = amount, left = amount, bottom = amount, right = amount; 804 : top = amount,
805 left = amount,
806 bottom = amount,
807 right = amount;
815 808
816 int get width => left + right; 809 int get width => left + right;
817 int get height => top + bottom; 810 int get height => top + bottom;
818 811
819 String get cssExpression { 812 String get cssExpression {
820 return (top == left && bottom == right && top == right) ? "${left}px" : 813 return (top == left && bottom == right && top == right)
821 "${top != null ? '$top' : '0'}px ${ 814 ? "${left}px"
815 : "${top != null ? '$top' : '0'}px ${
822 right != null ? '$right' : '0'}px ${ 816 right != null ? '$right' : '0'}px ${
823 bottom != null ? '$bottom' : '0'}px ${ 817 bottom != null ? '$bottom' : '0'}px ${
824 left != null ? '$left' : '0'}px"; 818 left != null ? '$left' : '0'}px";
825 } 819 }
826 } 820 }
827 821
828
829 /** Font style constants. */ 822 /** Font style constants. */
830 class FontStyle { 823 class FontStyle {
831 /** Font style [normal] default. */ 824 /** Font style [normal] default. */
832 static const String normal = "normal"; 825 static const String normal = "normal";
833 /** 826 /**
834 * Font style [italic] use explicity crafted italic font otherwise inclined 827 * Font style [italic] use explicity crafted italic font otherwise inclined
835 * on the fly like oblique. 828 * on the fly like oblique.
836 */ 829 */
837 static const String italic = "italic"; 830 static const String italic = "italic";
838 /** 831 /**
839 * Font style [oblique] is rarely used. The normal style of a font is inclined 832 * Font style [oblique] is rarely used. The normal style of a font is inclined
840 * on the fly to the right by 8-12 degrees. 833 * on the fly to the right by 8-12 degrees.
841 */ 834 */
842 static const String oblique = "oblique"; 835 static const String oblique = "oblique";
843 } 836 }
844 837
845
846 /** Font variant constants. */ 838 /** Font variant constants. */
847 class FontVariant { 839 class FontVariant {
848 /** Font style [normal] default. */ 840 /** Font style [normal] default. */
849 static const String normal = "normal"; 841 static const String normal = "normal";
850 /** Font variant [smallCaps]. */ 842 /** Font variant [smallCaps]. */
851 static const String smallCaps = "small-caps"; 843 static const String smallCaps = "small-caps";
852 } 844 }
853 845
854
855 /** Font weight constants values 100, 200, 300, 400, 500, 600, 700, 800, 900. */ 846 /** Font weight constants values 100, 200, 300, 400, 500, 600, 700, 800, 900. */
856 class FontWeight { 847 class FontWeight {
857 /** Font weight normal [default] */ 848 /** Font weight normal [default] */
858 static const int normal = 400; 849 static const int normal = 400;
859 /** Font weight bold */ 850 /** Font weight bold */
860 static const int bold = 700; 851 static const int bold = 700;
861 852
862 static const int wt100 = 100; 853 static const int wt100 = 100;
863 static const int wt200 = 200; 854 static const int wt200 = 200;
864 static const int wt300 = 300; 855 static const int wt300 = 300;
865 static const int wt400 = 400; 856 static const int wt400 = 400;
866 static const int wt500 = 500; 857 static const int wt500 = 500;
867 static const int wt600 = 600; 858 static const int wt600 = 600;
868 static const int wt700 = 700; 859 static const int wt700 = 700;
869 static const int wt800 = 800; 860 static const int wt800 = 800;
870 static const int wt900 = 900; 861 static const int wt900 = 900;
871 } 862 }
872 863
873
874 /** Generic font family names. */ 864 /** Generic font family names. */
875 class FontGeneric { 865 class FontGeneric {
876 /** Generic family sans-serif font (w/o serifs). */ 866 /** Generic family sans-serif font (w/o serifs). */
877 static const String sansSerif = "sans-serif"; 867 static const String sansSerif = "sans-serif";
878 /** Generic family serif font. */ 868 /** Generic family serif font. */
879 static const String serif = "serif"; 869 static const String serif = "serif";
880 /** Generic family fixed-width font. */ 870 /** Generic family fixed-width font. */
881 static const monospace = "monospace"; 871 static const monospace = "monospace";
882 /** Generic family emulate handwriting font. */ 872 /** Generic family emulate handwriting font. */
883 static const String cursive = "cursive"; 873 static const String cursive = "cursive";
884 /** Generic family decorative font. */ 874 /** Generic family decorative font. */
885 static const String fantasy = "fantasy"; 875 static const String fantasy = "fantasy";
886 } 876 }
887 877
888
889 /** 878 /**
890 * List of most common font families across different platforms. Use the 879 * List of most common font families across different platforms. Use the
891 * collection names in the Font class (e.g., Font.SANS_SERIF, Font.FONT_SERIF, 880 * collection names in the Font class (e.g., Font.SANS_SERIF, Font.FONT_SERIF,
892 * Font.MONOSPACE, Font.CURSIVE or Font.FANTASY). These work best on all 881 * Font.MONOSPACE, Font.CURSIVE or Font.FANTASY). These work best on all
893 * platforms using the fonts that best match availability on each platform. 882 * platforms using the fonts that best match availability on each platform.
894 * See <http://www.angelfire.com/al4/rcollins/style/fonts.html> for a good 883 * See <http://www.angelfire.com/al4/rcollins/style/fonts.html> for a good
895 * description of fonts available between platforms and browsers. 884 * description of fonts available between platforms and browsers.
896 */ 885 */
897 class FontFamily { 886 class FontFamily {
898 /** Sans-Serif font for Windows similar to Helvetica on Mac bold/italic. */ 887 /** Sans-Serif font for Windows similar to Helvetica on Mac bold/italic. */
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 927
939 /** Fantasy font on most Mac/Windows/Linux platforms. */ 928 /** Fantasy font on most Mac/Windows/Linux platforms. */
940 static const String impact = "impact"; 929 static const String impact = "impact";
941 /** Fantasy font for Windows. */ 930 /** Fantasy font for Windows. */
942 static const String webdings = "webdings"; 931 static const String webdings = "webdings";
943 } 932 }
944 933
945 class LineHeight { 934 class LineHeight {
946 final num height; 935 final num height;
947 final bool inPixels; 936 final bool inPixels;
948 const LineHeight(this.height, {this.inPixels : true}); 937 const LineHeight(this.height, {this.inPixels: true});
949 } 938 }
950 939
951 // TODO(terry): Support @font-face fule. 940 // TODO(terry): Support @font-face fule.
952 /** 941 /**
953 * Font style support for size, family, weight, style, variant, and lineheight. 942 * Font style support for size, family, weight, style, variant, and lineheight.
954 */ 943 */
955 class Font implements _StyleProperty { 944 class Font implements _StyleProperty {
956 /** Collection of most common sans-serif fonts in order. */ 945 /** Collection of most common sans-serif fonts in order. */
957 static const List<String> sansSerif = const [FontFamily.arial, 946 static const List<String> sansSerif = const [
958 FontFamily.verdana, 947 FontFamily.arial,
959 FontFamily.geneva, 948 FontFamily.verdana,
960 FontFamily.helvetica, 949 FontFamily.geneva,
961 FontGeneric.sansSerif]; 950 FontFamily.helvetica,
951 FontGeneric.sansSerif
952 ];
962 953
963 /** Collection of most common serif fonts in order. */ 954 /** Collection of most common serif fonts in order. */
964 static const List<String> serif = const [FontFamily.georgia, 955 static const List<String> serif = const [
965 FontFamily.timesNewRoman, 956 FontFamily.georgia,
966 FontFamily.times, 957 FontFamily.timesNewRoman,
967 FontGeneric.serif]; 958 FontFamily.times,
959 FontGeneric.serif
960 ];
968 /** Collection of most common monospace fonts in order. */ 961 /** Collection of most common monospace fonts in order. */
969 static const List<String> monospace = const [FontFamily.courierNew, 962 static const List<String> monospace = const [
970 FontFamily.courier, 963 FontFamily.courierNew,
971 FontGeneric.monospace]; 964 FontFamily.courier,
965 FontGeneric.monospace
966 ];
972 /** Collection of most common cursive fonts in order. */ 967 /** Collection of most common cursive fonts in order. */
973 static const List<String> cursive = const [FontFamily.textile, 968 static const List<String> cursive = const [
974 FontFamily.appleChancery, 969 FontFamily.textile,
975 FontFamily.zaphChancery, 970 FontFamily.appleChancery,
976 FontGeneric.fantasy]; 971 FontFamily.zaphChancery,
972 FontGeneric.fantasy
973 ];
977 /** Collection of most common fantasy fonts in order. */ 974 /** Collection of most common fantasy fonts in order. */
978 static const List<String> fantasy = const [FontFamily.comicSansMs, 975 static const List<String> fantasy = const [
979 FontFamily.impact, 976 FontFamily.comicSansMs,
980 FontFamily.webdings, 977 FontFamily.impact,
981 FontGeneric.fantasy]; 978 FontFamily.webdings,
979 FontGeneric.fantasy
980 ];
982 981
983 // TODO(terry): Should support the values xx-small, small, large, xx-large, 982 // TODO(terry): Should support the values xx-small, small, large, xx-large,
984 // etc. (mapped to a pixel sized font)? 983 // etc. (mapped to a pixel sized font)?
985 /** Font size in pixels. */ 984 /** Font size in pixels. */
986 final num size; 985 final num size;
987 986
988 // TODO(terry): _family should be an immutable list, wrapper class to do this 987 // TODO(terry): _family should be an immutable list, wrapper class to do this
989 // should exist in Dart. 988 // should exist in Dart.
990 /** 989 /**
991 * Family specifies a list of fonts, the browser will sequentially select the 990 * Family specifies a list of fonts, the browser will sequentially select the
(...skipping 29 matching lines...) Expand all
1021 // height. Classic typography suggest the ratio be 1.5. See 1020 // height. Classic typography suggest the ratio be 1.5. See
1022 // <http://www.pearsonified.com/2011/12/golden-ratio-typography.php> and 1021 // <http://www.pearsonified.com/2011/12/golden-ratio-typography.php> and
1023 // <http://meyerweb.com/eric/thoughts/2008/05/06/line-height-abnormal/>. 1022 // <http://meyerweb.com/eric/thoughts/2008/05/06/line-height-abnormal/>.
1024 /** 1023 /**
1025 * Create a font using [size] of font in pixels, [family] name of font(s) 1024 * Create a font using [size] of font in pixels, [family] name of font(s)
1026 * using [FontFamily], [style] of the font using [FontStyle], [variant] using 1025 * using [FontFamily], [style] of the font using [FontStyle], [variant] using
1027 * [FontVariant], and [lineHeight] extra space (leading) around the font in 1026 * [FontVariant], and [lineHeight] extra space (leading) around the font in
1028 * pixels, if not specified it's 1.2 the font size. 1027 * pixels, if not specified it's 1.2 the font size.
1029 */ 1028 */
1030 const Font({this.size, this.family, this.weight, this.style, this.variant, 1029 const Font({this.size, this.family, this.weight, this.style, this.variant,
1031 this.lineHeight}); 1030 this.lineHeight});
1032 1031
1033 /** 1032 /**
1034 * Merge the two fonts and return the result. See [Style.merge] for 1033 * Merge the two fonts and return the result. See [Style.merge] for
1035 * more information. 1034 * more information.
1036 */ 1035 */
1037 factory Font.merge(Font a, Font b) { 1036 factory Font.merge(Font a, Font b) {
1038 if (a == null) return b; 1037 if (a == null) return b;
1039 if (b == null) return a; 1038 if (b == null) return a;
1040 return new Font._merge(a, b); 1039 return new Font._merge(a, b);
1041 } 1040 }
1042 1041
1043 Font._merge(Font a, Font b) 1042 Font._merge(Font a, Font b)
1044 : size = _mergeVal(a.size, b.size), 1043 : size = _mergeVal(a.size, b.size),
1045 family = _mergeVal(a.family, b.family), 1044 family = _mergeVal(a.family, b.family),
1046 weight = _mergeVal(a.weight, b.weight), 1045 weight = _mergeVal(a.weight, b.weight),
1047 style = _mergeVal(a.style, b.style), 1046 style = _mergeVal(a.style, b.style),
1048 variant = _mergeVal(a.variant, b.variant), 1047 variant = _mergeVal(a.variant, b.variant),
1049 lineHeight = _mergeVal(a.lineHeight, b.lineHeight); 1048 lineHeight = _mergeVal(a.lineHeight, b.lineHeight);
1050 1049
1051 /** 1050 /**
1052 * Shorthand CSS format for font is: 1051 * Shorthand CSS format for font is:
1053 * 1052 *
1054 * font-style font-variant font-weight font-size/line-height font-family 1053 * font-style font-variant font-weight font-size/line-height font-family
1055 * 1054 *
1056 * The font-size and font-family values are required. If any of the other 1055 * The font-size and font-family values are required. If any of the other
1057 * values are missing the default value is used. 1056 * values are missing the default value is used.
1058 */ 1057 */
1059 String get cssExpression { 1058 String get cssExpression {
1060 // TODO(jimhug): include variant, style, other options 1059 // TODO(jimhug): include variant, style, other options
1061 if (weight != null) { 1060 if (weight != null) {
1062 // TODO(jacobr): is this really correct for lineHeight? 1061 // TODO(jacobr): is this really correct for lineHeight?
1063 if (lineHeight != null) { 1062 if (lineHeight != null) {
1064 return "$weight ${size}px/$lineHeightInPixels $_fontsAsString"; 1063 return "$weight ${size}px/$lineHeightInPixels $_fontsAsString";
1065 } 1064 }
1066 return '$weight ${size}px $_fontsAsString'; 1065 return '$weight ${size}px $_fontsAsString';
1067 } 1066 }
1068 1067
1069 return '${size}px $_fontsAsString'; 1068 return '${size}px $_fontsAsString';
1070 } 1069 }
1071 1070
1072 Font scale(num ratio) => 1071 Font scale(num ratio) => new Font(
1073 new Font(size: size * ratio, family: family, weight: weight, style: style, 1072 size: size * ratio,
1074 variant: variant); 1073 family: family,
1074 weight: weight,
1075 style: style,
1076 variant: variant);
1075 1077
1076 /** 1078 /**
1077 * The lineHeight, provides an indirect means to specify the leading. The 1079 * The lineHeight, provides an indirect means to specify the leading. The
1078 * leading is the difference between the font-size height and the (used) 1080 * leading is the difference between the font-size height and the (used)
1079 * value of line height in pixels. If lineHeight is not specified it's 1081 * value of line height in pixels. If lineHeight is not specified it's
1080 * automatically computed as 1.2 of the font size. Firefox is 1.2, Safari is 1082 * automatically computed as 1.2 of the font size. Firefox is 1.2, Safari is
1081 * ~1.2, and CSS suggest a ration from 1 to 1.2 of the font-size when 1083 * ~1.2, and CSS suggest a ration from 1 to 1.2 of the font-size when
1082 * computing line-height. The Font class constructor has the computation for 1084 * computing line-height. The Font class constructor has the computation for
1083 * _lineHeight. 1085 * _lineHeight.
1084 */ 1086 */
(...skipping 10 matching lines...) Expand all
1095 } 1097 }
1096 1098
1097 int get hashCode { 1099 int get hashCode {
1098 // TODO(jimhug): Lot's of potential collisions here. List of fonts, etc. 1100 // TODO(jimhug): Lot's of potential collisions here. List of fonts, etc.
1099 return size.toInt() % family[0].hashCode; 1101 return size.toInt() % family[0].hashCode;
1100 } 1102 }
1101 1103
1102 bool operator ==(other) { 1104 bool operator ==(other) {
1103 if (other is! Font) return false; 1105 if (other is! Font) return false;
1104 Font o = other; 1106 Font o = other;
1105 return o.size == size && o.family == family && o.weight == weight && 1107 return o.size == size &&
1106 o.lineHeight == lineHeight && o.style == style && o.variant == variant; 1108 o.family == family &&
1109 o.weight == weight &&
1110 o.lineHeight == lineHeight &&
1111 o.style == style &&
1112 o.variant == variant;
1107 } 1113 }
1108 1114
1109 // TODO(terry): This is fragile should probably just iterate through the list 1115 // TODO(terry): This is fragile should probably just iterate through the list
1110 // of fonts construction the font-family string. 1116 // of fonts construction the font-family string.
1111 /** Return fonts as a comma seperated list sans the square brackets. */ 1117 /** Return fonts as a comma seperated list sans the square brackets. */
1112 String get _fontsAsString { 1118 String get _fontsAsString {
1113 String fonts = family.toString(); 1119 String fonts = family.toString();
1114 return fonts.length > 2 ? fonts.substring(1, fonts.length - 1) : ""; 1120 return fonts.length > 2 ? fonts.substring(1, fonts.length - 1) : "";
1115 } 1121 }
1116 } 1122 }
(...skipping 28 matching lines...) Expand all
1145 */ 1151 */
1146 const BoxEdge([this.left, this.top, this.right, this.bottom]); 1152 const BoxEdge([this.left, this.top, this.right, this.bottom]);
1147 1153
1148 /** 1154 /**
1149 * Creates a box edge with the specified [top], [right], [bottom], and 1155 * Creates a box edge with the specified [top], [right], [bottom], and
1150 * [left] width. This matches the typical CSS order: 1156 * [left] width. This matches the typical CSS order:
1151 * <https://developer.mozilla.org/en/CSS/margin> 1157 * <https://developer.mozilla.org/en/CSS/margin>
1152 * <https://developer.mozilla.org/en/CSS/border-width> 1158 * <https://developer.mozilla.org/en/CSS/border-width>
1153 * <https://developer.mozilla.org/en/CSS/padding>. 1159 * <https://developer.mozilla.org/en/CSS/padding>.
1154 */ 1160 */
1155 const BoxEdge.clockwiseFromTop(this.top, this.right, this.bottom, this.left); 1161 const BoxEdge.clockwiseFromTop(this.top, this.right, this.bottom, this.left);
1156 1162
1157 /** 1163 /**
1158 * This is a helper to creates a box edge with the same [left], [top] 1164 * This is a helper to creates a box edge with the same [left], [top]
1159 * [right], and [bottom] widths. 1165 * [right], and [bottom] widths.
1160 */ 1166 */
1161 const BoxEdge.uniform(num size) 1167 const BoxEdge.uniform(num size)
1162 : top = size, left = size, bottom = size, right = size; 1168 : top = size,
1169 left = size,
1170 bottom = size,
1171 right = size;
1163 1172
1164 /** 1173 /**
1165 * Takes a possibly null box edge, with possibly null metrics, and fills 1174 * Takes a possibly null box edge, with possibly null metrics, and fills
1166 * them in with 0 instead. 1175 * them in with 0 instead.
1167 */ 1176 */
1168 factory BoxEdge.nonNull(BoxEdge other) { 1177 factory BoxEdge.nonNull(BoxEdge other) {
1169 if (other == null) return const BoxEdge(0, 0, 0, 0); 1178 if (other == null) return const BoxEdge(0, 0, 0, 0);
1170 num left = other.left; 1179 num left = other.left;
1171 num top = other.top; 1180 num top = other.top;
1172 num right = other.right; 1181 num right = other.right;
(...skipping 22 matching lines...) Expand all
1195 * Merge the two box edge sizes and return the result. See [Style.merge] for 1204 * Merge the two box edge sizes and return the result. See [Style.merge] for
1196 * more information. 1205 * more information.
1197 */ 1206 */
1198 factory BoxEdge.merge(BoxEdge x, BoxEdge y) { 1207 factory BoxEdge.merge(BoxEdge x, BoxEdge y) {
1199 if (x == null) return y; 1208 if (x == null) return y;
1200 if (y == null) return x; 1209 if (y == null) return x;
1201 return new BoxEdge._merge(x, y); 1210 return new BoxEdge._merge(x, y);
1202 } 1211 }
1203 1212
1204 BoxEdge._merge(BoxEdge x, BoxEdge y) 1213 BoxEdge._merge(BoxEdge x, BoxEdge y)
1205 : left = _mergeVal(x.left, y.left), 1214 : left = _mergeVal(x.left, y.left),
1206 top = _mergeVal(x.top, y.top), 1215 top = _mergeVal(x.top, y.top),
1207 right = _mergeVal(x.right, y.right), 1216 right = _mergeVal(x.right, y.right),
1208 bottom = _mergeVal(x.bottom, y.bottom); 1217 bottom = _mergeVal(x.bottom, y.bottom);
1209 1218
1210 /** 1219 /**
1211 * The total size of the horizontal edges. Equal to [left] + [right], where 1220 * The total size of the horizontal edges. Equal to [left] + [right], where
1212 * null is interpreted as 0px. 1221 * null is interpreted as 0px.
1213 */ 1222 */
1214 num get width => (left != null ? left : 0) + (right != null ? right : 0); 1223 num get width => (left != null ? left : 0) + (right != null ? right : 0);
1215 1224
1216 /** 1225 /**
1217 * The total size of the vertical edges. Equal to [top] + [bottom], where 1226 * The total size of the vertical edges. Equal to [top] + [bottom], where
1218 * null is interpreted as 0px. 1227 * null is interpreted as 0px.
1219 */ 1228 */
1220 num get height => (top != null ? top : 0) + (bottom != null ? bottom : 0); 1229 num get height => (top != null ? top : 0) + (bottom != null ? bottom : 0);
1221 } 1230 }
1222 1231
1223 _mergeVal(x, y) => y != null ? y : x; 1232 _mergeVal(x, y) => y != null ? y : x;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698