From 81f56588dc406f822ce09001a45fb3ce04875c0c Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Wed, 30 Dec 2015 10:45:25 -0800 Subject: [PATCH] Implement wordSpacing and per-inline lineHeight. Change line-height to use percentages rather than pixels. --- sky/engine/core/dart/text.dart | 64 ++++++++++--- sky/engine/core/text/ParagraphBuilder.cpp | 105 ++++++++++++---------- sky/engine/core/text/ParagraphBuilder.h | 2 +- 3 files changed, 111 insertions(+), 60 deletions(-) diff --git a/sky/engine/core/dart/text.dart b/sky/engine/core/dart/text.dart index 21063cd88..795ef4eac 100644 --- a/sky/engine/core/dart/text.dart +++ b/sky/engine/core/dart/text.dart @@ -170,8 +170,9 @@ enum TextDecorationStyle { // The encoded array buffer has 7 elements. // // - Element 0: A bit field where the ith bit indicates wheter the ith element -// has a non-null value. Bits 7 and 8 indicate whether |fontFamily| and -// |fontSize| are non-null, respectively. Bit 0 is unused. +// has a non-null value. Bits 7 to 11 indicate whether |fontFamily|, +// |fontSize|, |letterSpacing|, |wordSpacing|, and |lineHeight| are non-null, +// respectively. Bit 0 is unused. // // - Element 1: The |color| in ARGB with 8 bits per channel. // @@ -195,7 +196,9 @@ Int32List _encodeTextStyle(Color color, FontStyle fontStyle, String fontFamily, double fontSize, - double letterSpacing) { + double letterSpacing, + double wordSpacing, + double lineHeight) { Int32List result = new Int32List(7); if (color != null) { result[0] |= 1 << 1; @@ -233,6 +236,14 @@ Int32List _encodeTextStyle(Color color, result[0] |= 1 << 9; // Passed separately to native. } + if (wordSpacing != null) { + result[0] |= 1 << 10; + // Passed separately to native. + } + if (lineHeight != null) { + result[0] |= 1 << 11; + // Passed separately to native. + } return result; } @@ -246,7 +257,9 @@ class TextStyle { FontStyle fontStyle, String fontFamily, double fontSize, - double letterSpacing + double letterSpacing, + double wordSpacing, + double lineHeight }) : _encoded = _encodeTextStyle(color, decoration, decorationColor, @@ -255,15 +268,37 @@ class TextStyle { fontStyle, fontFamily, fontSize, - letterSpacing), + letterSpacing, + wordSpacing, + lineHeight), _fontFamily = fontFamily ?? '', _fontSize = fontSize, - _letterSpacing = letterSpacing; + _letterSpacing = letterSpacing, + _wordSpacing = wordSpacing, + _lineHeight = lineHeight; final Int32List _encoded; final String _fontFamily; final double _fontSize; final double _letterSpacing; + final double _wordSpacing; + final double _lineHeight; + + String toString() { + return 'TextStyle(${_encoded[0]}|' + 'color: ${ _encoded[0] & 0x001 == 0x001 ? new Color(_encoded[1]) : "unspecified"}, ' + 'decoration: ${ _encoded[0] & 0x002 == 0x002 ? new TextDecoration._(_encoded[2]) : "unspecified"}, ' + 'decorationColor: ${_encoded[0] & 0x004 == 0x004 ? new Color(_encoded[3]) : "unspecified"}, ' + 'decorationStyle: ${_encoded[0] & 0x008 == 0x008 ? TextDecorationStyle.values[_encoded[4]] : "unspecified"}, ' + 'fontWeight: ${ _encoded[0] & 0x010 == 0x010 ? FontWeight.values[_encoded[5]] : "unspecified"}, ' + 'fontStyle: ${ _encoded[0] & 0x020 == 0x020 ? FontStyle.values[_encoded[6]] : "unspecified"}, ' + 'fontFamily: ${ _encoded[0] & 0x040 == 0x040 ? _fontFamily : "unspecified"}, ' + 'fontSize: ${ _encoded[0] & 0x080 == 0x080 ? _fontSize : "unspecified"}, ' + 'letterSpacing: ${ _encoded[0] & 0x100 == 0x100 ? "${_letterSpacing}x" : "unspecified"}, ' + 'wordSpacing: ${ _encoded[0] & 0x200 == 0x200 ? "${_wordSpacing}x" : "unspecified"}, ' + 'lineHeight: ${ _encoded[0] & 0x400 == 0x400 ? "${_lineHeight}x" : "unspecified"}' + ')'; + } } // This encoding must match the C++ version ParagraphBuilder::build. @@ -307,6 +342,14 @@ class ParagraphStyle { final Int32List _encoded; final double _lineHeight; + + String toString() { + return 'ParagraphStyle(' + 'textAlign: ${ _encoded[0] & 0x1 == 0x1 ? TextAlign.values[_encoded[1]] : "unspecified"}, ' + 'textBaseline: ${_encoded[0] & 0x2 == 0x2 ? TextBaseline.values[_encoded[2]] : "unspecified"}, ' + 'lineHeight: ${ _encoded[0] & 0x3 == 0x3 ? "${_lineHeight}x" : "unspecified"}' + ')'; + } } abstract class Paragraph extends NativeFieldWrapperClass2 { @@ -333,17 +376,14 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 { void _constructor() native "ParagraphBuilder_constructor"; ParagraphBuilder() { _constructor(); } - void _pushStyle(Int32List encoded, String fontFamily, double fontSize, double letterSpacing) native "ParagraphBuilder_pushStyle"; - - void pushStyle(TextStyle style) { - _pushStyle(style._encoded, style._fontFamily, style._fontSize, style._letterSpacing); - } + void _pushStyle(Int32List encoded, String fontFamily, double fontSize, double letterSpacing, double wordSpacing, double lineHeight) native "ParagraphBuilder_pushStyle"; + void pushStyle(TextStyle style) => _pushStyle(style._encoded, style._fontFamily, style._fontSize, style._letterSpacing, style._wordSpacing, style._lineHeight); void pop() native "ParagraphBuilder_pop"; + void addText(String text) native "ParagraphBuilder_addText"; Paragraph _build(Int32List encoded, double lineHeight) native "ParagraphBuilder_build"; - Paragraph build(ParagraphStyle style) => _build(style._encoded, style._lineHeight); } diff --git a/sky/engine/core/text/ParagraphBuilder.cpp b/sky/engine/core/text/ParagraphBuilder.cpp index 26cd12179..ecc3521bc 100644 --- a/sky/engine/core/text/ParagraphBuilder.cpp +++ b/sky/engine/core/text/ParagraphBuilder.cpp @@ -67,35 +67,39 @@ Color getColorFromARGB(int argb) { // TextStyle -const int kColorIndex = 1; -const int kTextDecorationIndex = 2; -const int kTextDecorationColorIndex = 3; -const int kTextDecorationStyleIndex = 4; -const int kFontWeightIndex = 5; -const int kFontStyleIndex = 6; -const int kFontFamilyIndex = 7; -const int kFontSizeIndex = 8; -const int kLetterSpacingIndex = 9; - -const int kColorMask = 1 << kColorIndex; -const int kTextDecorationMask = 1 << kTextDecorationIndex; -const int kTextDecorationColorMask = 1 << kTextDecorationColorIndex; -const int kTextDecorationStyleMask = 1 << kTextDecorationStyleIndex; -const int kFontWeightMask = 1 << kFontWeightIndex; -const int kFontStyleMask = 1 << kFontStyleIndex; -const int kFontFamilyMask = 1 << kFontFamilyIndex; -const int kFontSizeMask = 1 << kFontSizeIndex; -const int kLetterSpacingMask = 1 << kLetterSpacingIndex; +const int tsColorIndex = 1; +const int tsTextDecorationIndex = 2; +const int tsTextDecorationColorIndex = 3; +const int tsTextDecorationStyleIndex = 4; +const int tsFontWeightIndex = 5; +const int tsFontStyleIndex = 6; +const int tsFontFamilyIndex = 7; +const int tsFontSizeIndex = 8; +const int tsLetterSpacingIndex = 9; +const int tsWordSpacingIndex = 10; +const int tsLineHeightIndex = 11; + +const int tsColorMask = 1 << tsColorIndex; +const int tsTextDecorationMask = 1 << tsTextDecorationIndex; +const int tsTextDecorationColorMask = 1 << tsTextDecorationColorIndex; +const int tsTextDecorationStyleMask = 1 << tsTextDecorationStyleIndex; +const int tsFontWeightMask = 1 << tsFontWeightIndex; +const int tsFontStyleMask = 1 << tsFontStyleIndex; +const int tsFontFamilyMask = 1 << tsFontFamilyIndex; +const int tsFontSizeMask = 1 << tsFontSizeIndex; +const int tsLetterSpacingMask = 1 << tsLetterSpacingIndex; +const int tsWordSpacingMask = 1 << tsWordSpacingIndex; +const int tsLineHeightMask = 1 << tsLineHeightIndex; // ParagraphStyle -const int kTextAlignIndex = 1; -const int kTextBaselineIndex = 2; -const int kLineHeightIndex = 3; +const int psTextAlignIndex = 1; +const int psTextBaselineIndex = 2; +const int psLineHeightIndex = 3; -const int kTextAlignMask = 1 << kTextAlignIndex; -const int kTextBaselineMask = 1 << kTextBaselineIndex; -const int kLineHeightMask = 1 << kLineHeightIndex; +const int psTextAlignMask = 1 << psTextAlignIndex; +const int psTextBaselineMask = 1 << psTextBaselineIndex; +const int psLineHeightMask = 1 << psLineHeightIndex; } // namespace @@ -132,7 +136,7 @@ ParagraphBuilder::~ParagraphBuilder() { } -void ParagraphBuilder::pushStyle(Int32List& encoded, const String& fontFamily, double fontSize, double letterSpacing) +void ParagraphBuilder::pushStyle(Int32List& encoded, const String& fontFamily, double fontSize, double letterSpacing, double wordSpacing, double lineHeight) { DCHECK(encoded.num_elements() == 7); RefPtr style = RenderStyle::create(); @@ -140,48 +144,55 @@ void ParagraphBuilder::pushStyle(Int32List& encoded, const String& fontFamily, d int32_t mask = encoded[0]; - if (mask & kColorMask) - style->setColor(getColorFromARGB(encoded[kColorIndex])); + if (mask & tsColorMask) + style->setColor(getColorFromARGB(encoded[tsColorIndex])); - if (mask & kTextDecorationMask) { - style->setTextDecoration(static_cast(encoded[kTextDecorationIndex])); + if (mask & tsTextDecorationMask) { + style->setTextDecoration(static_cast(encoded[tsTextDecorationIndex])); style->applyTextDecorations(); } - if (mask & kTextDecorationColorMask) - style->setTextDecorationColor(StyleColor(getColorFromARGB(encoded[kTextDecorationColorIndex]))); + if (mask & tsTextDecorationColorMask) + style->setTextDecorationColor(StyleColor(getColorFromARGB(encoded[tsTextDecorationColorIndex]))); - if (mask & kTextDecorationStyleMask) - style->setTextDecorationStyle(static_cast(encoded[kTextDecorationStyleIndex])); + if (mask & tsTextDecorationStyleMask) + style->setTextDecorationStyle(static_cast(encoded[tsTextDecorationStyleIndex])); - if (mask & (kFontWeightMask | kFontStyleMask | kFontFamilyMask | kFontSizeMask | kLetterSpacingMask)) { + if (mask & (tsFontWeightMask | tsFontStyleMask | tsFontFamilyMask | tsFontSizeMask | tsLetterSpacingMask | tsWordSpacingMask)) { FontDescription fontDescription = style->fontDescription(); - if (mask & kFontWeightMask) - fontDescription.setWeight(static_cast(encoded[kFontWeightIndex])); + if (mask & tsFontWeightMask) + fontDescription.setWeight(static_cast(encoded[tsFontWeightIndex])); - if (mask & kFontStyleMask) - fontDescription.setStyle(static_cast(encoded[kFontStyleIndex])); + if (mask & tsFontStyleMask) + fontDescription.setStyle(static_cast(encoded[tsFontStyleIndex])); - if (mask & kFontFamilyMask) { + if (mask & tsFontFamilyMask) { FontFamily family; family.setFamily(fontFamily); fontDescription.setFamily(family); } - if (mask & kFontSizeMask) { + if (mask & tsFontSizeMask) { fontDescription.setSpecifiedSize(fontSize); fontDescription.setIsAbsoluteSize(true); fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontSize)); } - if (mask & kLetterSpacingMask) + if (mask & tsLetterSpacingMask) fontDescription.setLetterSpacing(letterSpacing); + if (mask & tsWordSpacingMask) + fontDescription.setWordSpacing(wordSpacing); + style->setFontDescription(fontDescription); style->font().update(nullptr); } + if (mask & tsLineHeightMask) { + style->setLineHeight(Length(lineHeight * 100.0, Percent)); + } + encoded.Release(); RenderObject* span = new RenderInline(); @@ -215,16 +226,16 @@ PassRefPtr ParagraphBuilder::build(Int32List& encoded, double lineHei if (mask) { RefPtr style = RenderStyle::clone(m_renderParagraph->style()); - if (mask & kTextAlignMask) - style->setTextAlign(static_cast(encoded[kTextAlignIndex])); + if (mask & psTextAlignMask) + style->setTextAlign(static_cast(encoded[psTextAlignIndex])); - if (mask & kTextBaselineMask) { + if (mask & psTextBaselineMask) { // TODO(abarth): Implement TextBaseline. The CSS version of this // property wasn't wired up either. } - if (mask & kLineHeightMask) - style->setLineHeight(Length(lineHeight, Fixed)); + if (mask & psLineHeightMask) + style->setLineHeight(Length(lineHeight * 100.0, Percent)); m_renderParagraph->setStyle(style.release()); } diff --git a/sky/engine/core/text/ParagraphBuilder.h b/sky/engine/core/text/ParagraphBuilder.h index d2ba228db..ba18816d2 100644 --- a/sky/engine/core/text/ParagraphBuilder.h +++ b/sky/engine/core/text/ParagraphBuilder.h @@ -23,7 +23,7 @@ public: ~ParagraphBuilder() override; - void pushStyle(Int32List& encoded, const String& fontFamily, double fontSize, double letterSpacing); + void pushStyle(Int32List& encoded, const String& fontFamily, double fontSize, double letterSpacing, double wordSpacing, double lineHeight); void pop(); void addText(const String& text); -- GitLab