diff --git a/engine/src/flutter/lib/ui/painting/paint.cc b/engine/src/flutter/lib/ui/painting/paint.cc index b61a48c351..2bb02b18bf 100644 --- a/engine/src/flutter/lib/ui/painting/paint.cc +++ b/engine/src/flutter/lib/ui/painting/paint.cc @@ -12,9 +12,7 @@ #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/core/SkString.h" -using namespace blink; - -namespace tonic { +namespace blink { // Indices for 32bit values. constexpr int kIsAntiAliasIndex = 0; @@ -52,17 +50,10 @@ constexpr double kStrokeMiterLimitDefault = 4.0; // Must be kept in sync with the MaskFilter private constants in painting.dart. enum MaskFilterType { Null, Blur }; -Paint DartConverter::FromArguments(Dart_NativeArguments args, - int index, - Dart_Handle& exception) { - Dart_Handle paint_objects = Dart_GetNativeArgument(args, index); - FXL_DCHECK(!LogIfError(paint_objects)); - - Dart_Handle paint_data = Dart_GetNativeArgument(args, index + 1); - FXL_DCHECK(!LogIfError(paint_data)); - - Paint result; - SkPaint& paint = result.paint_; +Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data) { + is_null_ = Dart_IsNull(paint_data); + if (is_null_) + return; if (!Dart_IsNull(paint_objects)) { FXL_DCHECK(Dart_IsList(paint_objects)); @@ -72,12 +63,12 @@ Paint DartConverter::FromArguments(Dart_NativeArguments args, FXL_CHECK(length == kObjectCount); Dart_Handle values[kObjectCount]; if (Dart_IsError(Dart_ListGetRange(paint_objects, 0, kObjectCount, values))) - return result; + return; Dart_Handle shader = values[kShaderIndex]; if (!Dart_IsNull(shader)) { - Shader* decoded = DartConverter::FromDart(shader); - paint.setShader(decoded->shader()); + Shader* decoded = tonic::DartConverter::FromDart(shader); + paint_.setShader(decoded->shader()); } } @@ -87,49 +78,49 @@ Paint DartConverter::FromArguments(Dart_NativeArguments args, const uint32_t* uint_data = static_cast(byte_data.data()); const float* float_data = static_cast(byte_data.data()); - paint.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0); + paint_.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0); uint32_t encoded_color = uint_data[kColorIndex]; if (encoded_color) { SkColor color = encoded_color ^ kColorDefault; - paint.setColor(color); + paint_.setColor(color); } uint32_t encoded_blend_mode = uint_data[kBlendModeIndex]; if (encoded_blend_mode) { uint32_t blend_mode = encoded_blend_mode ^ kBlendModeDefault; - paint.setBlendMode(static_cast(blend_mode)); + paint_.setBlendMode(static_cast(blend_mode)); } uint32_t style = uint_data[kStyleIndex]; if (style) - paint.setStyle(static_cast(style)); + paint_.setStyle(static_cast(style)); float stroke_width = float_data[kStrokeWidthIndex]; if (stroke_width != 0.0) - paint.setStrokeWidth(stroke_width); + paint_.setStrokeWidth(stroke_width); uint32_t stroke_cap = uint_data[kStrokeCapIndex]; if (stroke_cap) - paint.setStrokeCap(static_cast(stroke_cap)); + paint_.setStrokeCap(static_cast(stroke_cap)); uint32_t stroke_join = uint_data[kStrokeJoinIndex]; if (stroke_join) - paint.setStrokeJoin(static_cast(stroke_join)); + paint_.setStrokeJoin(static_cast(stroke_join)); float stroke_miter_limit = float_data[kStrokeMiterLimitIndex]; if (stroke_miter_limit != 0.0) - paint.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault); + paint_.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault); uint32_t filter_quality = uint_data[kFilterQualityIndex]; if (filter_quality) - paint.setFilterQuality(static_cast(filter_quality)); + paint_.setFilterQuality(static_cast(filter_quality)); if (uint_data[kColorFilterIndex]) { SkColor color = uint_data[kColorFilterColorIndex]; SkBlendMode blend_mode = static_cast(uint_data[kColorFilterBlendModeIndex]); - paint.setColorFilter(SkColorFilter::MakeModeFilter(color, blend_mode)); + paint_.setColorFilter(SkColorFilter::MakeModeFilter(color, blend_mode)); } switch (uint_data[kMaskFilterIndex]) { @@ -139,18 +130,29 @@ Paint DartConverter::FromArguments(Dart_NativeArguments args, SkBlurStyle blur_style = static_cast(uint_data[kMaskFilterBlurStyleIndex]); double sigma = float_data[kMaskFilterSigmaIndex]; - paint.setMaskFilter(SkMaskFilter::MakeBlur(blur_style, sigma)); + paint_.setMaskFilter(SkMaskFilter::MakeBlur(blur_style, sigma)); break; } - - result.is_null_ = false; - return result; } -PaintData DartConverter::FromArguments(Dart_NativeArguments args, - int index, - Dart_Handle& exception) { - return PaintData(); +} // namespace blink + +namespace tonic { + +blink::Paint DartConverter::FromArguments( + Dart_NativeArguments args, int index, Dart_Handle& exception) { + Dart_Handle paint_objects = Dart_GetNativeArgument(args, index); + FXL_DCHECK(!LogIfError(paint_objects)); + + Dart_Handle paint_data = Dart_GetNativeArgument(args, index + 1); + FXL_DCHECK(!LogIfError(paint_data)); + + return blink::Paint(paint_objects, paint_data); +} + +blink::PaintData DartConverter::FromArguments( + Dart_NativeArguments args, int index, Dart_Handle& exception) { + return blink::PaintData(); } } // namespace tonic diff --git a/engine/src/flutter/lib/ui/painting/paint.h b/engine/src/flutter/lib/ui/painting/paint.h index f107dd206f..29a0d359d2 100644 --- a/engine/src/flutter/lib/ui/painting/paint.h +++ b/engine/src/flutter/lib/ui/painting/paint.h @@ -12,13 +12,16 @@ namespace blink { class Paint { public: + Paint() = default; + Paint(Dart_Handle paint_objects, Dart_Handle paint_data); + const SkPaint* paint() const { return is_null_ ? nullptr : &paint_; } private: friend struct tonic::DartConverter; SkPaint paint_; - bool is_null_; + bool is_null_ = true; }; // The PaintData argument is a placeholder to receive encoded data for Paint diff --git a/engine/src/flutter/lib/ui/text.dart b/engine/src/flutter/lib/ui/text.dart index 7c42c878a9..ff623068ac 100644 --- a/engine/src/flutter/lib/ui/text.dart +++ b/engine/src/flutter/lib/ui/text.dart @@ -257,6 +257,7 @@ Int32List _encodeTextStyle( double wordSpacing, double height, Locale locale, + Paint background, ) { final Int32List result = new Int32List(8); if (color != null) { @@ -311,6 +312,10 @@ Int32List _encodeTextStyle( result[0] |= 1 << 13; // Passed separately to native. } + if (background != null) { + result[0] |= 1 << 14; + // Passed separately to native. + } return result; } @@ -331,6 +336,7 @@ class TextStyle { /// * `textBaseline`: The common baseline that should be aligned between this text span and its parent text span, or, for the root text spans, with the line box. /// * `height`: The height of this text span, as a multiple of the font size. /// * `locale`: The locale used to select region-specific glyphs. + /// * `background`: The paint drawn as a background for the text. TextStyle({ Color color, TextDecoration decoration, @@ -345,6 +351,7 @@ class TextStyle { double wordSpacing, double height, Locale locale, + Paint background, }) : _encoded = _encodeTextStyle( color, decoration, @@ -359,13 +366,15 @@ class TextStyle { wordSpacing, height, locale, + background, ), _fontFamily = fontFamily ?? '', _fontSize = fontSize, _letterSpacing = letterSpacing, _wordSpacing = wordSpacing, _height = height, - _locale = locale; + _locale = locale, + _background = background; final Int32List _encoded; final String _fontFamily; @@ -374,6 +383,7 @@ class TextStyle { final double _wordSpacing; final double _height; final Locale _locale; + final Paint _background; @override bool operator ==(dynamic other) { @@ -387,7 +397,8 @@ class TextStyle { _letterSpacing != typedOther._letterSpacing || _wordSpacing != typedOther._wordSpacing || _height != typedOther._height || - _locale != typedOther._locale) + _locale != typedOther._locale || + _background != typedOther._background) return false; for (int index = 0; index < _encoded.length; index += 1) { if (_encoded[index] != typedOther._encoded[index]) @@ -397,7 +408,7 @@ class TextStyle { } @override - int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _letterSpacing, _wordSpacing, _height, _locale); + int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _letterSpacing, _wordSpacing, _height, _locale, _background); @override String toString() { @@ -414,7 +425,8 @@ class TextStyle { 'letterSpacing: ${ _encoded[0] & 0x0400 == 0x0400 ? "${_letterSpacing}x" : "unspecified"}, ' 'wordSpacing: ${ _encoded[0] & 0x0800 == 0x0800 ? "${_wordSpacing}x" : "unspecified"}, ' 'height: ${ _encoded[0] & 0x1000 == 0x1000 ? "${_height}x" : "unspecified"}, ' - 'locale: ${ _encoded[0] & 0x2000 == 0x2000 ? _locale : "unspecified"}' + 'locale: ${ _encoded[0] & 0x2000 == 0x2000 ? _locale : "unspecified"}, ' + 'background: ${ _encoded[0] & 0x4000 == 0x4000 ? _background : "unspecified"}' ')'; } } @@ -1013,8 +1025,8 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 { /// Applies the given style to the added text until [pop] is called. /// /// See [pop] for details. - void pushStyle(TextStyle style) => _pushStyle(style._encoded, style._fontFamily, style._fontSize, style._letterSpacing, style._wordSpacing, style._height, _encodeLocale(style._locale)); - void _pushStyle(Int32List encoded, String fontFamily, double fontSize, double letterSpacing, double wordSpacing, double height, String locale) native 'ParagraphBuilder_pushStyle'; + void pushStyle(TextStyle style) => _pushStyle(style._encoded, style._fontFamily, style._fontSize, style._letterSpacing, style._wordSpacing, style._height, _encodeLocale(style._locale), style._background?._objects, style._background?._data); + void _pushStyle(Int32List encoded, String fontFamily, double fontSize, double letterSpacing, double wordSpacing, double height, String locale, List backgroundObjects, ByteData backgroundData) native 'ParagraphBuilder_pushStyle'; static String _encodeLocale(Locale locale) => locale?.toString() ?? ''; diff --git a/engine/src/flutter/lib/ui/text/paragraph_builder.cc b/engine/src/flutter/lib/ui/text/paragraph_builder.cc index b987e3fde6..36cf84e027 100644 --- a/engine/src/flutter/lib/ui/text/paragraph_builder.cc +++ b/engine/src/flutter/lib/ui/text/paragraph_builder.cc @@ -42,6 +42,7 @@ const int tsLetterSpacingIndex = 10; const int tsWordSpacingIndex = 11; const int tsHeightIndex = 12; const int tsLocaleIndex = 13; +const int tsBackgroundIndex = 14; const int tsColorMask = 1 << tsColorIndex; const int tsTextDecorationMask = 1 << tsTextDecorationIndex; @@ -56,6 +57,7 @@ const int tsLetterSpacingMask = 1 << tsLetterSpacingIndex; const int tsWordSpacingMask = 1 << tsWordSpacingIndex; const int tsHeightMask = 1 << tsHeightIndex; const int tsLocaleMask = 1 << tsLocaleIndex; +const int tsBackgroundMask = 1 << tsBackgroundIndex; // ParagraphStyle @@ -290,7 +292,9 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded, double letterSpacing, double wordSpacing, double height, - const std::string& locale) { + const std::string& locale, + Dart_Handle background_objects, + Dart_Handle background_data) { FXL_DCHECK(encoded.num_elements() == 8); int32_t mask = encoded[0]; @@ -351,6 +355,14 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded, style.locale = locale; } + if (mask & tsBackgroundMask) { + Paint background(background_objects, background_data); + if (background.paint()) { + style.has_background = true; + style.background = *background.paint(); + } + } + m_paragraphBuilder->PushStyle(style); } else { // Blink Version. diff --git a/engine/src/flutter/lib/ui/text/paragraph_builder.h b/engine/src/flutter/lib/ui/text/paragraph_builder.h index 1c38d98696..9a600f064e 100644 --- a/engine/src/flutter/lib/ui/text/paragraph_builder.h +++ b/engine/src/flutter/lib/ui/text/paragraph_builder.h @@ -6,6 +6,7 @@ #define FLUTTER_LIB_UI_TEXT_PARAGRAPH_BUILDER_H_ #include +#include "flutter/lib/ui/painting/paint.h" #include "flutter/lib/ui/text/paragraph.h" #include "flutter/sky/engine/core/rendering/RenderObject.h" #include "flutter/sky/engine/wtf/OwnPtr.h" @@ -43,7 +44,9 @@ class ParagraphBuilder : public fxl::RefCountedThreadSafe, double letterSpacing, double wordSpacing, double height, - const std::string& locale); + const std::string& locale, + Dart_Handle background_objects, + Dart_Handle background_data); void pop(); diff --git a/engine/src/flutter/third_party/txt/src/txt/paragraph.cc b/engine/src/flutter/third_party/txt/src/txt/paragraph.cc index f75c4a0aea..743abdac1d 100644 --- a/engine/src/flutter/third_party/txt/src/txt/paragraph.cc +++ b/engine/src/flutter/third_party/txt/src/txt/paragraph.cc @@ -862,6 +862,7 @@ void Paragraph::Paint(SkCanvas* canvas, double x, double y) { for (const PaintRecord& record : records_) { paint.setColor(record.style().color); SkPoint offset = record.offset(); + PaintBackground(canvas, record); canvas->drawTextBlob(record.text(), offset.x(), offset.y(), paint); PaintDecorations(canvas, record); } @@ -1026,6 +1027,17 @@ void Paragraph::PaintDecorations(SkCanvas* canvas, const PaintRecord& record) { } } +void Paragraph::PaintBackground(SkCanvas* canvas, const PaintRecord& record) { + if (!record.style().has_background) + return; + + const SkPaint::FontMetrics& metrics = record.metrics(); + SkRect rect(SkRect::MakeLTRB(0, metrics.fAscent, + record.GetRunWidth(), metrics.fDescent)); + rect.offset(record.offset()); + canvas->drawRect(rect, record.style().background); +} + std::vector Paragraph::GetRectsForRange(size_t start, size_t end) const { std::map> line_boxes; diff --git a/engine/src/flutter/third_party/txt/src/txt/paragraph.h b/engine/src/flutter/third_party/txt/src/txt/paragraph.h index 454cdc9aca..894439abc5 100644 --- a/engine/src/flutter/third_party/txt/src/txt/paragraph.h +++ b/engine/src/flutter/third_party/txt/src/txt/paragraph.h @@ -310,6 +310,9 @@ class Paragraph { // Creates and draws the decorations onto the canvas. void PaintDecorations(SkCanvas* canvas, const PaintRecord& record); + // Draws the background onto the canvas. + void PaintBackground(SkCanvas* canvas, const PaintRecord& record); + FXL_DISALLOW_COPY_AND_ASSIGN(Paragraph); }; diff --git a/engine/src/flutter/third_party/txt/src/txt/text_style.h b/engine/src/flutter/third_party/txt/src/txt/text_style.h index 0a57cc7c68..2b995132a3 100644 --- a/engine/src/flutter/third_party/txt/src/txt/text_style.h +++ b/engine/src/flutter/third_party/txt/src/txt/text_style.h @@ -24,6 +24,7 @@ #include "text_baseline.h" #include "text_decoration.h" #include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkPaint.h" namespace txt { @@ -46,6 +47,8 @@ class TextStyle { double word_spacing = 0.0; double height = 1.0; std::string locale; + bool has_background = false; + SkPaint background; TextStyle();