|
|
import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:sonnat/core/html/html_parser.dart'; import 'package:sonnat/core/html/src/css_parser.dart'; import 'package:sonnat/core/html/src/style/fontsize.dart'; import 'package:sonnat/core/html/src/style/length.dart'; import 'package:sonnat/core/html/src/style/lineheight.dart'; import 'package:sonnat/core/html/src/style/margin.dart'; import 'package:sonnat/core/html/src/style/marker.dart'; import 'package:sonnat/core/html/src/style/size.dart';
class Style { Color? backgroundColor; Color? color; Map<String, int?>? counterIncrement; Map<String, int?>? counterReset; TextDirection? direction; Display? display; String? fontFamily; List<String>? fontFamilyFallback; List<FontFeature>? fontFeatureSettings; FontSize? fontSize; FontStyle? fontStyle; FontWeight? fontWeight; Height? height; double? letterSpacing; ListStyleImage? listStyleImage; ListStyleType? listStyleType; ListStylePosition? listStylePosition; EdgeInsets? padding; Marker? marker; Margins? margin; TextAlign? textAlign; TextDecoration? textDecoration;
/// CSS attribute "`text-decoration-color`"
///
/// Inherited: no,
/// Default: Current color
Color? textDecorationColor;
/// CSS attribute "`text-decoration-style`"
///
/// Inherited: no,
/// Default: TextDecorationStyle.solid,
TextDecorationStyle? textDecorationStyle;
/// Loosely based on CSS attribute "`text-decoration-thickness`"
///
/// Uses a percent modifier based on the font size.
///
/// Inherited: no,
/// Default: 1.0 (specified by font size)
// TODO(Sub6Resources): Possibly base this more closely on the CSS attribute.
double? textDecorationThickness;
/// CSS attribute "`text-shadow`"
///
/// Inherited: yes,
/// Default: none,
List<Shadow>? textShadow;
/// CSS attribute "`vertical-align`"
///
/// Inherited: no,
/// Default: VerticalAlign.BASELINE,
VerticalAlign? verticalAlign;
/// CSS attribute "`white-space`"
///
/// Inherited: yes,
/// Default: WhiteSpace.NORMAL,
WhiteSpace? whiteSpace;
/// CSS attribute "`width`"
///
/// Inherited: no,
/// Default: Width.auto()
Width? width;
/// CSS attribute "`word-spacing`"
///
/// Inherited: yes,
/// Default: normal (0)
double? wordSpacing; LineHeight? lineHeight; String? before; String? after; Border? border; Alignment? alignment; Widget? markerContent;
/// MaxLine
///
///
///
///
int? maxLines;
/// TextOverflow
///
///
///
///
TextOverflow? textOverflow;
TextTransform? textTransform;
Style({ this.backgroundColor = Colors.transparent, this.color, this.counterIncrement, this.counterReset, this.direction, this.display, this.fontFamily, this.fontFamilyFallback, this.fontFeatureSettings, this.fontSize, this.fontStyle, this.fontWeight, this.height, this.lineHeight, this.letterSpacing, this.listStyleImage, this.listStyleType, this.listStylePosition, this.padding, this.marker, this.margin, this.textAlign, this.textDecoration, this.textDecorationColor, this.textDecorationStyle, this.textDecorationThickness, this.textShadow, this.verticalAlign, this.whiteSpace, this.width, this.wordSpacing, this.before, this.after, this.border, this.alignment, this.markerContent, this.maxLines, this.textOverflow, this.textTransform = TextTransform.none, }) { if (alignment == null && (display == Display.block || display == Display.listItem)) { alignment = Alignment.centerLeft; } }
static Map<String, Style> fromThemeData(ThemeData theme) => { 'h1': Style.fromTextStyle(theme.textTheme.displayLarge!), 'h2': Style.fromTextStyle(theme.textTheme.displayMedium!), 'h3': Style.fromTextStyle(theme.textTheme.displaySmall!), 'h4': Style.fromTextStyle(theme.textTheme.headlineMedium!), 'h5': Style.fromTextStyle(theme.textTheme.headlineSmall!), 'h6': Style.fromTextStyle(theme.textTheme.titleLarge!), 'body': Style.fromTextStyle(theme.textTheme.bodyMedium!), };
static Map<String, Style> fromCss(String css, OnCssParseError? onCssParseError) { final declarations = parseExternalCss(css, onCssParseError); Map<String, Style> styleMap = {}; declarations.forEach((key, value) { styleMap[key] = declarationsToStyle(value); }); return styleMap; }
TextStyle generateTextStyle() { return TextStyle( backgroundColor: backgroundColor, color: color, decoration: textDecoration, decorationColor: textDecorationColor, decorationStyle: textDecorationStyle, decorationThickness: textDecorationThickness, fontFamily: fontFamily, fontFamilyFallback: fontFamilyFallback, fontFeatures: fontFeatureSettings, fontSize: fontSize?.value, fontStyle: fontStyle, fontWeight: fontWeight, letterSpacing: letterSpacing, shadows: textShadow, wordSpacing: wordSpacing, height: lineHeight?.size ?? 1.0, ); }
@override String toString() { return 'Style'; }
Style merge(Style other) { return copyWith( backgroundColor: other.backgroundColor, color: other.color, counterIncrement: other.counterIncrement, counterReset: other.counterReset, direction: other.direction, display: other.display, fontFamily: other.fontFamily, fontFamilyFallback: other.fontFamilyFallback, fontFeatureSettings: other.fontFeatureSettings, fontSize: other.fontSize, fontStyle: other.fontStyle, fontWeight: other.fontWeight, height: other.height, lineHeight: other.lineHeight, letterSpacing: other.letterSpacing, listStyleImage: other.listStyleImage, listStyleType: other.listStyleType, listStylePosition: other.listStylePosition, padding: other.padding, margin: other.margin, marker: other.marker, textAlign: other.textAlign, textDecoration: other.textDecoration, textDecorationColor: other.textDecorationColor, textDecorationStyle: other.textDecorationStyle, textDecorationThickness: other.textDecorationThickness, textShadow: other.textShadow, verticalAlign: other.verticalAlign, whiteSpace: other.whiteSpace, width: other.width, wordSpacing: other.wordSpacing, before: other.before, after: other.after, border: other.border, alignment: other.alignment, markerContent: other.markerContent, maxLines: other.maxLines, textOverflow: other.textOverflow, textTransform: other.textTransform, ); }
Style copyOnlyInherited(Style child) { FontSize? finalFontSize = FontSize.inherit(fontSize, child.fontSize);
LineHeight? finalLineHeight = child.lineHeight != null ? child.lineHeight?.units == 'length' ? LineHeight(child.lineHeight!.size! / (finalFontSize == null ? 14 : finalFontSize.value) * 1.2) : child.lineHeight : lineHeight;
return child.copyWith( backgroundColor: child.backgroundColor != Colors.transparent ? child.backgroundColor : backgroundColor, color: child.color ?? color, direction: child.direction ?? direction, display: display == Display.none ? display : child.display, fontFamily: child.fontFamily ?? fontFamily, fontFamilyFallback: child.fontFamilyFallback ?? fontFamilyFallback, fontFeatureSettings: child.fontFeatureSettings ?? fontFeatureSettings, fontSize: finalFontSize, fontStyle: child.fontStyle ?? fontStyle, fontWeight: child.fontWeight ?? fontWeight, lineHeight: finalLineHeight, letterSpacing: child.letterSpacing ?? letterSpacing, listStyleImage: child.listStyleImage ?? listStyleImage, listStyleType: child.listStyleType ?? listStyleType, listStylePosition: child.listStylePosition ?? listStylePosition, textAlign: child.textAlign ?? textAlign, textDecoration: TextDecoration.combine([ child.textDecoration ?? TextDecoration.none, textDecoration ?? TextDecoration.none, ]), textShadow: child.textShadow ?? textShadow, whiteSpace: child.whiteSpace ?? whiteSpace, wordSpacing: child.wordSpacing ?? wordSpacing, maxLines: child.maxLines ?? maxLines, textOverflow: child.textOverflow ?? textOverflow, textTransform: child.textTransform ?? textTransform, ); }
Style copyWith({ Color? backgroundColor, Color? color, Map<String, int?>? counterIncrement, Map<String, int?>? counterReset, TextDirection? direction, Display? display, String? fontFamily, List<String>? fontFamilyFallback, List<FontFeature>? fontFeatureSettings, FontSize? fontSize, FontStyle? fontStyle, FontWeight? fontWeight, Height? height, LineHeight? lineHeight, double? letterSpacing, ListStyleImage? listStyleImage, ListStyleType? listStyleType, ListStylePosition? listStylePosition, EdgeInsets? padding, Margins? margin, Marker? marker, TextAlign? textAlign, TextDecoration? textDecoration, Color? textDecorationColor, TextDecorationStyle? textDecorationStyle, double? textDecorationThickness, List<Shadow>? textShadow, VerticalAlign? verticalAlign, WhiteSpace? whiteSpace, Width? width, double? wordSpacing, String? before, String? after, Border? border, Alignment? alignment, Widget? markerContent, int? maxLines, TextOverflow? textOverflow, TextTransform? textTransform, bool? beforeAfterNull, }) { return Style( backgroundColor: backgroundColor ?? this.backgroundColor, color: color ?? this.color, counterIncrement: counterIncrement ?? this.counterIncrement, counterReset: counterReset ?? this.counterReset, direction: direction ?? this.direction, display: display ?? this.display, fontFamily: fontFamily ?? this.fontFamily, fontFamilyFallback: fontFamilyFallback ?? this.fontFamilyFallback, fontFeatureSettings: fontFeatureSettings ?? this.fontFeatureSettings, fontSize: fontSize ?? this.fontSize, fontStyle: fontStyle ?? this.fontStyle, fontWeight: fontWeight ?? this.fontWeight, height: height ?? this.height, lineHeight: lineHeight ?? this.lineHeight, letterSpacing: letterSpacing ?? this.letterSpacing, listStyleImage: listStyleImage ?? this.listStyleImage, listStyleType: listStyleType ?? this.listStyleType, listStylePosition: listStylePosition ?? this.listStylePosition, padding: padding ?? this.padding, margin: margin ?? this.margin, marker: marker ?? this.marker, textAlign: textAlign ?? this.textAlign, textDecoration: textDecoration ?? this.textDecoration, textDecorationColor: textDecorationColor ?? this.textDecorationColor, textDecorationStyle: textDecorationStyle ?? this.textDecorationStyle, textDecorationThickness: textDecorationThickness ?? this.textDecorationThickness, textShadow: textShadow ?? this.textShadow, verticalAlign: verticalAlign ?? this.verticalAlign, whiteSpace: whiteSpace ?? this.whiteSpace, width: width ?? this.width, wordSpacing: wordSpacing ?? this.wordSpacing, before: beforeAfterNull == true ? null : before ?? this.before, after: beforeAfterNull == true ? null : after ?? this.after, border: border ?? this.border, alignment: alignment ?? this.alignment, markerContent: markerContent ?? this.markerContent, maxLines: maxLines ?? this.maxLines, textOverflow: textOverflow ?? this.textOverflow, textTransform: textTransform ?? this.textTransform, ); }
Style.fromTextStyle(TextStyle textStyle) { backgroundColor = textStyle.backgroundColor; color = textStyle.color; textDecoration = textStyle.decoration; textDecorationColor = textStyle.decorationColor; textDecorationStyle = textStyle.decorationStyle; textDecorationThickness = textStyle.decorationThickness; fontFamily = textStyle.fontFamily; fontFamilyFallback = textStyle.fontFamilyFallback; fontFeatureSettings = textStyle.fontFeatures; fontSize = textStyle.fontSize != null ? FontSize(textStyle.fontSize!) : null; fontStyle = textStyle.fontStyle; fontWeight = textStyle.fontWeight; letterSpacing = textStyle.letterSpacing; textShadow = textStyle.shadows; wordSpacing = textStyle.wordSpacing; lineHeight = LineHeight(textStyle.height ?? 1.2); textTransform = TextTransform.none; }
/// Sets any dimensions set to rem or em to the computed size
void setRelativeValues(double remValue, double emValue) { if (width?.unit == Unit.rem) { width = Width(width!.value * remValue); } else if (width?.unit == Unit.em) { width = Width(width!.value * emValue); }
if (height?.unit == Unit.rem) { height = Height(height!.value * remValue); } else if (height?.unit == Unit.em) { height = Height(height!.value * emValue); }
if (fontSize?.unit == Unit.rem) { fontSize = FontSize(fontSize!.value * remValue); } else if (fontSize?.unit == Unit.em) { fontSize = FontSize(fontSize!.value * emValue); }
Margin? marginLeft; Margin? marginTop; Margin? marginRight; Margin? marginBottom;
if (margin?.left?.unit == Unit.rem) { marginLeft = Margin(margin!.left!.value * remValue); } else if (margin?.left?.unit == Unit.em) { marginLeft = Margin(margin!.left!.value * emValue); }
if (margin?.top?.unit == Unit.rem) { marginTop = Margin(margin!.top!.value * remValue); } else if (margin?.top?.unit == Unit.em) { marginTop = Margin(margin!.top!.value * emValue); }
if (margin?.right?.unit == Unit.rem) { marginRight = Margin(margin!.right!.value * remValue); } else if (margin?.right?.unit == Unit.em) { marginRight = Margin(margin!.right!.value * emValue); }
if (margin?.bottom?.unit == Unit.rem) { marginBottom = Margin(margin!.bottom!.value * remValue); } else if (margin?.bottom?.unit == Unit.em) { marginBottom = Margin(margin!.bottom!.value * emValue); }
margin = margin?.copyWith( left: marginLeft, top: marginTop, right: marginRight, bottom: marginBottom, ); } }
enum Display { block, inline, inlineBlock, listItem, none, }
enum ListStyleType { arabicIndic('arabic-indic'), armenian('armenian'), lowerArmenian('lower-armenian'), upperArmenian('upper-armenian'), bengali('bengali'), cambodian('cambodian'), khmer('khmer'), circle('circle'), cjkDecimal('cjk-decimal'), cjkEarthlyBranch('cjk-earthly-branch'), cjkHeavenlyStem('cjk-heavenly-stem'), cjkIdeographic('cjk-ideographic'), decimal('decimal'), decimalLeadingZero('decimal-leading-zero'), devanagari('devanagari'), disc('disc'), disclosureClosed('disclosure-closed'), disclosureOpen('disclosure-open'), ethiopicNumeric('ethiopic-numeric'), georgian('georgian'), gujarati('gujarati'), gurmukhi('gurmukhi'), hebrew('hebrew'), hiragana('hiragana'), hiraganaIroha('hiragana-iroha'), japaneseFormal('japanese-formal'), japaneseInformal('japanese-informal'), kannada('kannada'), katakana('katakana'), katakanaIroha('katakana-iroha'), koreanHangulFormal('korean-hangul-formal'), koreanHanjaInformal('korean-hanja-informal'), koreanHanjaFormal('korean-hanja-formal'), lao('lao'), lowerAlpha('lower-alpha'), lowerGreek('lower-greek'), lowerLatin('lower-latin'), lowerRoman('lower-roman'), malayalam('malayalam'), mongolian('mongolian'), myanmar('myanmar'), none('none'), oriya('oriya'), persian('persian'), simpChineseFormal('simp-chinese-formal'), simpChineseInformal('simp-chinese-informal'), square('square'), tamil('tamil'), telugu('telugu'), thai('thai'), tibetan('tibetan'), tradChineseFormal('trad-chinese-formal'), tradChineseInformal('trad-chinese-informal'), upperAlpha('upper-alpha'), upperLatin('upper-latin'), upperRoman('upper-roman');
final String counterStyle;
const ListStyleType(this.counterStyle);
factory ListStyleType.fromName(String name) { return ListStyleType.values.firstWhere((value) { return name == value.counterStyle; }); } }
class ListStyleImage { final String uriText;
const ListStyleImage(this.uriText); }
enum ListStylePosition { outside, inside, }
enum TextTransform { uppercase, lowercase, capitalize, none, }
enum VerticalAlign { baseline, sub, sup, }
enum WhiteSpace { normal, pre, }
|