// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:sky'; enum FontWeight { w100, w200, w300, w400, w500, w600, w700, w800, w900 } const normal = FontWeight.w400; const bold = FontWeight.w700; enum FontStyle { normal, italic, oblique } enum TextAlign { left, right, center } enum TextBaseline { alphabetic, ideographic } enum TextDecoration { none, underline, overline, lineThrough } const underline = const <TextDecoration>[TextDecoration.underline]; const overline = const <TextDecoration>[TextDecoration.overline]; const lineThrough = const <TextDecoration>[TextDecoration.lineThrough]; enum TextDecorationStyle { solid, double, dotted, dashed, wavy } class TextStyle { const TextStyle({ this.color, this.fontFamily, this.fontSize, this.fontWeight, this.fontStyle, this.textAlign, this.textBaseline, this.height, this.decoration, this.decorationColor, this.decorationStyle }); final Color color; final String fontFamily; final double fontSize; // in pixels final FontWeight fontWeight; final FontStyle fontStyle; final TextAlign textAlign; final TextBaseline textBaseline; final double height; // multiple of fontSize final List<TextDecoration> decoration; // TODO(ianh): Switch this to a Set<> once Dart supports constant Sets final Color decorationColor; final TextDecorationStyle decorationStyle; TextStyle copyWith({ Color color, String fontFamily, double fontSize, FontWeight fontWeight, FontStyle fontStyle, TextAlign textAlign, TextBaseline textBaseline, double height, List<TextDecoration> decoration, Color decorationColor, TextDecorationStyle decorationStyle }) { return new TextStyle( color: color != null ? color : this.color, fontFamily: fontFamily != null ? fontFamily : this.fontFamily, fontSize: fontSize != null ? fontSize : this.fontSize, fontWeight: fontWeight != null ? fontWeight : this.fontWeight, fontStyle: fontStyle != null ? fontStyle : this.fontStyle, textAlign: textAlign != null ? textAlign : this.textAlign, textBaseline: textBaseline != null ? textBaseline : this.textBaseline, height: height != null ? height : this.height, decoration: decoration != null ? decoration : this.decoration, decorationColor: decorationColor != null ? decorationColor : this.decorationColor, decorationStyle: decorationStyle != null ? decorationStyle : this.decorationStyle ); } TextStyle merge(TextStyle other) { return copyWith( color: other.color, fontFamily: other.fontFamily, fontSize: other.fontSize, fontWeight: other.fontWeight, fontStyle: other.fontStyle, textAlign: other.textAlign, textBaseline: other.textBaseline, height: other.height, decoration: other.decoration, decorationColor: other.decorationColor, decorationStyle: other.decorationStyle ); } static String _colorToCSSString(Color color) { return 'rgba(${color.red}, ${color.green}, ${color.blue}, ${color.alpha / 255.0})'; } static String _fontFamilyToCSSString(String fontFamily) { // TODO(hansmuller): escape the fontFamily string. return fontFamily; } static String _decorationToCSSString(List<TextDecoration> decoration) { assert(decoration != null); const toCSS = const <TextDecoration, String>{ TextDecoration.none: 'none', TextDecoration.underline: 'underline', TextDecoration.overline: 'overline', TextDecoration.lineThrough: 'lineThrough' }; return decoration.map((d) => toCSS[d]).join(' '); } static String _decorationStyleToCSSString(TextDecorationStyle decorationStyle) { assert(decorationStyle != null); const toCSS = const <TextDecorationStyle, String>{ TextDecorationStyle.solid: 'solid', TextDecorationStyle.double: 'double', TextDecorationStyle.dotted: 'dotted', TextDecorationStyle.dashed: 'dashed', TextDecorationStyle.wavy: 'wavy' }; return toCSS[decorationStyle]; } void applyToCSSStyle(CSSStyleDeclaration cssStyle) { if (color != null) { cssStyle['color'] = _colorToCSSString(color); } if (fontFamily != null) { cssStyle['font-family'] = _fontFamilyToCSSString(fontFamily); } if (fontSize != null) { cssStyle['font-size'] = '${fontSize}px'; } if (fontWeight != null) { cssStyle['font-weight'] = const { FontWeight.w100: '100', FontWeight.w200: '200', FontWeight.w300: '300', FontWeight.w400: '400', FontWeight.w500: '500', FontWeight.w600: '600', FontWeight.w700: '700', FontWeight.w800: '800', FontWeight.w900: '900' }[fontWeight]; } if (fontStyle != null) { cssStyle['font-style'] = const { FontStyle.normal: 'normal', FontStyle.italic: 'italic', FontStyle.oblique: 'oblique', }[fontStyle]; } if (decoration != null) { cssStyle['text-decoration'] = _decorationToCSSString(decoration); if (decorationColor != null) cssStyle['text-decoration-color'] = _colorToCSSString(decorationColor); if (decorationStyle != null) cssStyle['text-decoration-style'] = _decorationStyleToCSSString(decorationStyle); } } void applyToContainerCSSStyle(CSSStyleDeclaration cssStyle) { if (textAlign != null) { cssStyle['text-align'] = const { TextAlign.left: 'left', TextAlign.right: 'right', TextAlign.center: 'center', }[textAlign]; } if (height != null) { cssStyle['line-height'] = '${height}'; } } bool operator ==(other) { if (identical(this, other)) return true; return other is TextStyle && color == other.color && fontFamily == other.fontFamily && fontSize == other.fontSize && fontWeight == other.fontWeight && fontStyle == other.fontStyle && textAlign == other.textAlign && textBaseline == other.textBaseline && decoration == other.decoration && decorationColor == other.decorationColor && decorationStyle == other.decorationStyle; } int get hashCode { // Use Quiver: https://github.com/domokit/mojo/issues/236 int value = 373; value = 37 * value + color.hashCode; value = 37 * value + fontFamily.hashCode; value = 37 * value + fontSize.hashCode; value = 37 * value + fontWeight.hashCode; value = 37 * value + fontStyle.hashCode; value = 37 * value + textAlign.hashCode; value = 37 * value + textBaseline.hashCode; value = 37 * value + decoration.hashCode; value = 37 * value + decorationColor.hashCode; value = 37 * value + decorationStyle.hashCode; return value; } String toString([String prefix = '']) { List<String> result = []; if (color != null) result.add('${prefix}color: $color'); // TODO(hansmuller): escape the fontFamily string. if (fontFamily != null) result.add('${prefix}fontFamily: "${fontFamily}"'); if (fontSize != null) result.add('${prefix}fontSize: $fontSize'); if (fontWeight != null) result.add('${prefix}fontWeight: $fontWeight'); if (fontStyle != null) result.add('${prefix}fontStyle: $fontStyle'); if (textAlign != null) result.add('${prefix}textAlign: $textAlign'); if (textBaseline != null) result.add('${prefix}textBaseline: $textBaseline'); if (decoration != null) result.add('${prefix}decoration: $decoration'); if (decorationColor != null) result.add('${prefix}decorationColor: $decorationColor'); if (decorationStyle != null) result.add('${prefix}decorationStyle: $decorationStyle'); if (result.isEmpty) return '${prefix}<no style specified>'; return result.join('\n'); } }