Skip to content

Commit

Permalink
Allow custom foreground paint to be used for drawing text (flutter#5395)
Browse files Browse the repository at this point in the history
* Allow specifying the foreground paint

* fix typo

* doc update

* call paint.reset
  • Loading branch information
dnfield authored Jun 10, 2018
1 parent d4f5ef6 commit 8f023c5
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 16 deletions.
32 changes: 24 additions & 8 deletions lib/ui/text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ Int32List _encodeTextStyle(
double height,
Locale locale,
Paint background,
Paint foreground,
) {
final Int32List result = new Int32List(8);
if (color != null) {
Expand Down Expand Up @@ -316,14 +317,18 @@ Int32List _encodeTextStyle(
result[0] |= 1 << 14;
// Passed separately to native.
}
if (foreground != null) {
result[0] |= 1 << 15;
// Passed separately to native.
}
return result;
}

/// An opaque object that determines the size, position, and rendering of text.
class TextStyle {
/// Creates a new TextStyle object.
///
/// * `color`: The color to use when painting the text.
/// * `color`: The color to use when painting the text. If this is specified, `foreground` must be null.
/// * `decoration`: The decorations to paint near the text (e.g., an underline).
/// * `decorationColor`: The color in which to paint the text decorations.
/// * `decorationStyle`: The style in which to paint the text decorations (e.g., dashed).
Expand All @@ -337,6 +342,7 @@ class TextStyle {
/// * `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.
/// * `foreground`: The paint used to draw the text. If this is specified, `color` must be null.
TextStyle({
Color color,
TextDecoration decoration,
Expand All @@ -352,7 +358,12 @@ class TextStyle {
double height,
Locale locale,
Paint background,
}) : _encoded = _encodeTextStyle(
Paint foreground,
}) : assert(color == null || foreground == null,
'Cannot provide both a color and a foreground\n'
'The color argument is just a shorthand for "foreground: new Paint()..color = color".'
),
_encoded = _encodeTextStyle(
color,
decoration,
decorationColor,
Expand All @@ -367,14 +378,16 @@ class TextStyle {
height,
locale,
background,
foreground,
),
_fontFamily = fontFamily ?? '',
_fontSize = fontSize,
_letterSpacing = letterSpacing,
_wordSpacing = wordSpacing,
_height = height,
_locale = locale,
_background = background;
_background = background,
_foreground = foreground;

final Int32List _encoded;
final String _fontFamily;
Expand All @@ -384,6 +397,7 @@ class TextStyle {
final double _height;
final Locale _locale;
final Paint _background;
final Paint _foreground;

@override
bool operator ==(dynamic other) {
Expand All @@ -398,7 +412,8 @@ class TextStyle {
_wordSpacing != typedOther._wordSpacing ||
_height != typedOther._height ||
_locale != typedOther._locale ||
_background != typedOther._background)
_background != typedOther._background ||
_foreground != typedOther._foreground)
return false;
for (int index = 0; index < _encoded.length; index += 1) {
if (_encoded[index] != typedOther._encoded[index])
Expand All @@ -408,7 +423,7 @@ class TextStyle {
}

@override
int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _letterSpacing, _wordSpacing, _height, _locale, _background);
int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _letterSpacing, _wordSpacing, _height, _locale, _background, _foreground);

@override
String toString() {
Expand All @@ -426,7 +441,8 @@ class TextStyle {
'wordSpacing: ${ _encoded[0] & 0x0800 == 0x0800 ? "${_wordSpacing}x" : "unspecified"}, '
'height: ${ _encoded[0] & 0x1000 == 0x1000 ? "${_height}x" : "unspecified"}, '
'locale: ${ _encoded[0] & 0x2000 == 0x2000 ? _locale : "unspecified"}, '
'background: ${ _encoded[0] & 0x4000 == 0x4000 ? _background : "unspecified"}'
'background: ${ _encoded[0] & 0x4000 == 0x4000 ? _background : "unspecified"}, '
'foreground: ${ _encoded[0] & 0x8000 == 0x8000 ? _foreground : "unspecified"}'
')';
}
}
Expand Down Expand Up @@ -1025,8 +1041,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), 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';
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, style._foreground?._objects, style._foreground?._data);
void _pushStyle(Int32List encoded, String fontFamily, double fontSize, double letterSpacing, double wordSpacing, double height, String locale, List<dynamic> backgroundObjects, ByteData backgroundData, List<dynamic> foregroundObjects, ByteData foregroundData) native 'ParagraphBuilder_pushStyle';

static String _encodeLocale(Locale locale) => locale?.toString() ?? '';

Expand Down
14 changes: 13 additions & 1 deletion lib/ui/text/paragraph_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const int tsWordSpacingIndex = 11;
const int tsHeightIndex = 12;
const int tsLocaleIndex = 13;
const int tsBackgroundIndex = 14;
const int tsForegroundIndex = 15;

const int tsColorMask = 1 << tsColorIndex;
const int tsTextDecorationMask = 1 << tsTextDecorationIndex;
Expand All @@ -54,6 +55,7 @@ const int tsWordSpacingMask = 1 << tsWordSpacingIndex;
const int tsHeightMask = 1 << tsHeightIndex;
const int tsLocaleMask = 1 << tsLocaleIndex;
const int tsBackgroundMask = 1 << tsBackgroundIndex;
const int tsForegroundMask = 1 << tsForegroundIndex;

// ParagraphStyle

Expand Down Expand Up @@ -167,7 +169,9 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded,
double height,
const std::string& locale,
Dart_Handle background_objects,
Dart_Handle background_data) {
Dart_Handle background_data,
Dart_Handle foreground_objects,
Dart_Handle foreground_data) {
FXL_DCHECK(encoded.num_elements() == 8);

int32_t mask = encoded[0];
Expand Down Expand Up @@ -235,6 +239,14 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded,
}
}

if (mask & tsForegroundMask) {
Paint foreground(foreground_objects, foreground_data);
if (foreground.paint()) {
style.has_foreground = true;
style.foreground = *foreground.paint();
}
}

m_paragraphBuilder->PushStyle(style);
}

Expand Down
4 changes: 3 additions & 1 deletion lib/ui/text/paragraph_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class ParagraphBuilder : public fxl::RefCountedThreadSafe<ParagraphBuilder>,
double height,
const std::string& locale,
Dart_Handle background_objects,
Dart_Handle background_data);
Dart_Handle background_data,
Dart_Handle foreground_objects,
Dart_Handle foreground_data);

void pop();

Expand Down
18 changes: 12 additions & 6 deletions third_party/txt/src/txt/paragraph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,12 @@ void Paragraph::Paint(SkCanvas* canvas, double x, double y) {
canvas->translate(x, y);
SkPaint paint;
for (const PaintRecord& record : records_) {
paint.setColor(record.style().color);
if (record.style().has_foreground) {
paint = record.style().foreground;
} else {
paint.reset();
paint.setColor(record.style().color);
}
SkPoint offset = record.offset();
PaintBackground(canvas, record);
canvas->drawTextBlob(record.text(), offset.x(), offset.y(), paint);
Expand Down Expand Up @@ -1049,8 +1054,8 @@ void Paragraph::PaintBackground(SkCanvas* canvas, const PaintRecord& record) {
return;

const SkPaint::FontMetrics& metrics = record.metrics();
SkRect rect(SkRect::MakeLTRB(0, metrics.fAscent,
record.GetRunWidth(), metrics.fDescent));
SkRect rect(SkRect::MakeLTRB(0, metrics.fAscent, record.GetRunWidth(),
metrics.fDescent));
rect.offset(record.offset());
canvas->drawRect(rect, record.style().background);
}
Expand Down Expand Up @@ -1090,15 +1095,16 @@ std::vector<Paragraph::TextBox> Paragraph::GetRectsForRange(size_t start,
}

// Add empty rectangles representing any newline characters within the range.
for (size_t line_number = 0; line_number < line_ranges_.size(); ++line_number) {
for (size_t line_number = 0; line_number < line_ranges_.size();
++line_number) {
const LineRange& line = line_ranges_[line_number];
if (line.start >= end)
break;
if (line.end_including_newline <= start)
continue;
if (line_boxes.find(line_number) == line_boxes.end()) {
if (line.end != line.end_including_newline &&
line.end >= start && line.end_including_newline <= end) {
if (line.end != line.end_including_newline && line.end >= start &&
line.end_including_newline <= end) {
SkScalar x = line_widths_[line_number];
SkScalar top = (line_number > 0) ? line_heights_[line_number - 1] : 0;
SkScalar bottom = line_heights_[line_number];
Expand Down
2 changes: 2 additions & 0 deletions third_party/txt/src/txt/text_style.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ bool TextStyle::equals(const TextStyle& other) const {
return false;
if (locale != other.locale)
return false;
if (foreground != other.foreground)
return false;

return true;
}
Expand Down
2 changes: 2 additions & 0 deletions third_party/txt/src/txt/text_style.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class TextStyle {
std::string locale;
bool has_background = false;
SkPaint background;
bool has_foreground = false;
SkPaint foreground;

TextStyle();

Expand Down

0 comments on commit 8f023c5

Please sign in to comment.