blob: d0bca270f50a472b99ba54079161e6228beb75ae [file] [log] [blame]
// 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');
}
}