未验证 提交 11d50441 编写于 作者: J Jason Simmons 提交者: GitHub

Provide an SkPaint that describes the background of a text style (#5153)

Fixes https://github.com/flutter/flutter/issues/11961
上级 2b9c280e
......@@ -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<Paint>::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<Paint>::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<Shader*>::FromDart(shader);
paint.setShader(decoded->shader());
Shader* decoded = tonic::DartConverter<Shader*>::FromDart(shader);
paint_.setShader(decoded->shader());
}
}
......@@ -87,49 +78,49 @@ Paint DartConverter<Paint>::FromArguments(Dart_NativeArguments args,
const uint32_t* uint_data = static_cast<const uint32_t*>(byte_data.data());
const float* float_data = static_cast<const float*>(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<SkBlendMode>(blend_mode));
paint_.setBlendMode(static_cast<SkBlendMode>(blend_mode));
}
uint32_t style = uint_data[kStyleIndex];
if (style)
paint.setStyle(static_cast<SkPaint::Style>(style));
paint_.setStyle(static_cast<SkPaint::Style>(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<SkPaint::Cap>(stroke_cap));
paint_.setStrokeCap(static_cast<SkPaint::Cap>(stroke_cap));
uint32_t stroke_join = uint_data[kStrokeJoinIndex];
if (stroke_join)
paint.setStrokeJoin(static_cast<SkPaint::Join>(stroke_join));
paint_.setStrokeJoin(static_cast<SkPaint::Join>(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<SkFilterQuality>(filter_quality));
paint_.setFilterQuality(static_cast<SkFilterQuality>(filter_quality));
if (uint_data[kColorFilterIndex]) {
SkColor color = uint_data[kColorFilterColorIndex];
SkBlendMode blend_mode =
static_cast<SkBlendMode>(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<Paint>::FromArguments(Dart_NativeArguments args,
SkBlurStyle blur_style =
static_cast<SkBlurStyle>(uint_data[kMaskFilterBlurStyleIndex]);
double sigma = float_data[kMaskFilterSigmaIndex];
paint.setMaskFilter(SkMaskFilter::MakeBlur(blur_style, sigma));
paint_.setMaskFilter(SkMaskFilter::MakeBlur(blur_style, sigma));
break;
}
}
} // namespace blink
namespace tonic {
blink::Paint DartConverter<blink::Paint>::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));
result.is_null_ = false;
return result;
return blink::Paint(paint_objects, paint_data);
}
PaintData DartConverter<PaintData>::FromArguments(Dart_NativeArguments args,
int index,
Dart_Handle& exception) {
return PaintData();
blink::PaintData DartConverter<blink::PaintData>::FromArguments(
Dart_NativeArguments args, int index, Dart_Handle& exception) {
return blink::PaintData();
}
} // namespace tonic
......@@ -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<Paint>;
SkPaint paint_;
bool is_null_;
bool is_null_ = true;
};
// The PaintData argument is a placeholder to receive encoded data for Paint
......
......@@ -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<dynamic> backgroundObjects, ByteData backgroundData) native 'ParagraphBuilder_pushStyle';
static String _encodeLocale(Locale locale) => locale?.toString() ?? '';
......
......@@ -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.
......
......@@ -6,6 +6,7 @@
#define FLUTTER_LIB_UI_TEXT_PARAGRAPH_BUILDER_H_
#include <memory>
#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<ParagraphBuilder>,
double letterSpacing,
double wordSpacing,
double height,
const std::string& locale);
const std::string& locale,
Dart_Handle background_objects,
Dart_Handle background_data);
void pop();
......
......@@ -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::TextBox> Paragraph::GetRectsForRange(size_t start,
size_t end) const {
std::map<size_t, std::vector<Paragraph::TextBox>> line_boxes;
......
......@@ -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);
};
......
......@@ -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();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册