Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/render_text.h" | 5 #include "ui/gfx/render_text.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <climits> | 10 #include <climits> |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 namespace gfx { | 47 namespace gfx { |
| 48 | 48 |
| 49 namespace { | 49 namespace { |
| 50 | 50 |
| 51 // Default color used for the text and cursor. | 51 // Default color used for the text and cursor. |
| 52 const SkColor kDefaultColor = SK_ColorBLACK; | 52 const SkColor kDefaultColor = SK_ColorBLACK; |
| 53 | 53 |
| 54 // Default color used for drawing selection background. | 54 // Default color used for drawing selection background. |
| 55 const SkColor kDefaultSelectionBackgroundColor = SK_ColorGRAY; | 55 const SkColor kDefaultSelectionBackgroundColor = SK_ColorGRAY; |
| 56 | 56 |
| 57 // Fraction of the text size to lower a strike through below the baseline. | 57 // Fraction of the text size to lower a strike through below the baseline. |
|
cjgrant
2017/06/30 19:04:25
Should this be "raise the strike through above the
msw
2017/06/30 20:51:23
That seems fine to me, just make sure you don't ac
cjgrant
2017/07/05 16:16:48
I did some underline and strike before/after tests
| |
| 58 const SkScalar kStrikeThroughOffset = (-SK_Scalar1 * 6 / 21); | 58 const SkScalar kStrikeThroughOffset = (-SK_Scalar1 * 29 / 126); |
|
cjgrant
2017/06/30 21:06:24
Forgot to say, this relatively nasty-looking const
msw
2017/06/30 23:01:32
Acknowledged.
cjgrant
2017/07/05 16:16:48
And, it's now actually correct. :|
| |
| 59 // Fraction of the text size to lower an underline below the baseline. | 59 // Fraction of the text size to lower an underline below the baseline. |
| 60 const SkScalar kUnderlineOffset = (SK_Scalar1 / 9); | 60 const SkScalar kUnderlineOffset = (SK_Scalar1 / 9); |
| 61 // Fraction of the text size to use for a strike through or under-line. | 61 // Default fraction of the text size to use for a strike through or under-line. |
|
msw
2017/06/30 20:51:23
optional nit: "underline" here to match most uses
cjgrant
2017/07/05 16:16:48
Done.
| |
| 62 const SkScalar kLineThickness = (SK_Scalar1 / 18); | 62 const SkScalar kLineThickness = (SK_Scalar1 / 18); |
|
msw
2017/06/30 20:51:23
optional nit: kLineThicknessFactor
cjgrant
2017/07/05 16:16:48
Done.
| |
| 63 | 63 |
| 64 // Invalid value of baseline. Assigning this value to |baseline_| causes | 64 // Invalid value of baseline. Assigning this value to |baseline_| causes |
| 65 // re-calculation of baseline. | 65 // re-calculation of baseline. |
| 66 const int kInvalidBaseline = INT_MAX; | 66 const int kInvalidBaseline = INT_MAX; |
| 67 | 67 |
| 68 int round(float value) { | 68 int round(float value) { |
| 69 return static_cast<int>(floor(value + 0.5f)); | 69 return static_cast<int>(floor(value + 0.5f)); |
| 70 } | 70 } |
| 71 | 71 |
| 72 // Given |font| and |display_width|, returns the width of the fade gradient. | 72 // Given |font| and |display_width|, returns the width of the fade gradient. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 render_text->IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD)); | 181 render_text->IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD)); |
| 182 break_list->ApplyValue(current_break->second, range); | 182 break_list->ApplyValue(current_break->second, range); |
| 183 } | 183 } |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 } // namespace | 187 } // namespace |
| 188 | 188 |
| 189 namespace internal { | 189 namespace internal { |
| 190 | 190 |
| 191 // Value of |underline_thickness_| that indicates that underline metrics have | |
| 192 // not been set explicitly. | |
| 193 const SkScalar kUnderlineMetricsNotSet = -1.0f; | |
|
cjgrant
2017/06/30 19:04:25
I don't see that underscore overrides are actually
msw
2017/06/30 20:51:23
Afaict, you're right; thanks for removing this unu
| |
| 194 | |
| 195 SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas) | 191 SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas) |
| 196 : canvas_(canvas), | 192 : canvas_(canvas), |
| 197 canvas_skia_(canvas->sk_canvas()), | 193 canvas_skia_(canvas->sk_canvas()), |
| 198 underline_thickness_(kUnderlineMetricsNotSet), | 194 strike_thickness_factor_(kLineThickness) { |
| 199 underline_position_(0.0f) { | |
| 200 DCHECK(canvas_skia_); | 195 DCHECK(canvas_skia_); |
| 201 flags_.setTextEncoding(cc::PaintFlags::kGlyphID_TextEncoding); | 196 flags_.setTextEncoding(cc::PaintFlags::kGlyphID_TextEncoding); |
| 202 flags_.setStyle(cc::PaintFlags::kFill_Style); | 197 flags_.setStyle(cc::PaintFlags::kFill_Style); |
| 203 flags_.setAntiAlias(true); | 198 flags_.setAntiAlias(true); |
| 204 flags_.setSubpixelText(true); | 199 flags_.setSubpixelText(true); |
| 205 flags_.setLCDRenderText(true); | 200 flags_.setLCDRenderText(true); |
| 206 flags_.setHinting(cc::PaintFlags::kNormal_Hinting); | 201 flags_.setHinting(cc::PaintFlags::kNormal_Hinting); |
| 207 } | 202 } |
| 208 | 203 |
| 209 SkiaTextRenderer::~SkiaTextRenderer() { | 204 SkiaTextRenderer::~SkiaTextRenderer() { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 227 } | 222 } |
| 228 | 223 |
| 229 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { | 224 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { |
| 230 flags_.setColor(foreground); | 225 flags_.setColor(foreground); |
| 231 } | 226 } |
| 232 | 227 |
| 233 void SkiaTextRenderer::SetShader(std::unique_ptr<cc::PaintShader> shader) { | 228 void SkiaTextRenderer::SetShader(std::unique_ptr<cc::PaintShader> shader) { |
| 234 flags_.setShader(std::move(shader)); | 229 flags_.setShader(std::move(shader)); |
| 235 } | 230 } |
| 236 | 231 |
| 237 void SkiaTextRenderer::SetUnderlineMetrics(SkScalar thickness, | 232 void SkiaTextRenderer::SetStrikeThicknessFactor(SkScalar factor) { |
| 238 SkScalar position) { | 233 strike_thickness_factor_ = factor; |
| 239 underline_thickness_ = thickness; | |
| 240 underline_position_ = position; | |
| 241 } | 234 } |
| 242 | 235 |
| 243 void SkiaTextRenderer::DrawPosText(const SkPoint* pos, | 236 void SkiaTextRenderer::DrawPosText(const SkPoint* pos, |
| 244 const uint16_t* glyphs, | 237 const uint16_t* glyphs, |
| 245 size_t glyph_count) { | 238 size_t glyph_count) { |
| 246 const size_t byte_length = glyph_count * sizeof(glyphs[0]); | 239 const size_t byte_length = glyph_count * sizeof(glyphs[0]); |
| 247 canvas_skia_->drawPosText(&glyphs[0], byte_length, &pos[0], flags_); | 240 canvas_skia_->drawPosText(&glyphs[0], byte_length, &pos[0], flags_); |
| 248 } | 241 } |
| 249 | 242 |
| 250 void SkiaTextRenderer::DrawDecorations(int x, | 243 void SkiaTextRenderer::DrawDecorations(int x, |
| 251 int y, | 244 int y, |
| 252 int width, | 245 int width, |
| 253 bool underline, | 246 bool underline, |
| 254 bool strike) { | 247 bool strike) { |
| 255 if (underline) | 248 if (underline) |
| 256 DrawUnderline(x, y, width); | 249 DrawUnderline(x, y, width); |
| 257 if (strike) | 250 if (strike) |
| 258 DrawStrike(x, y, width); | 251 DrawStrike(x, y, width); |
| 259 } | 252 } |
| 260 | 253 |
| 261 void SkiaTextRenderer::DrawUnderline(int x, int y, int width) { | 254 void SkiaTextRenderer::DrawUnderline(int x, int y, int width) { |
| 262 SkScalar x_scalar = SkIntToScalar(x); | 255 SkScalar x_scalar = SkIntToScalar(x); |
| 256 const SkScalar text_size = flags_.getTextSize(); | |
| 263 SkRect r = SkRect::MakeLTRB( | 257 SkRect r = SkRect::MakeLTRB( |
| 264 x_scalar, y + underline_position_, x_scalar + width, | 258 x_scalar, y + text_size * kUnderlineOffset, x_scalar + width, |
| 265 y + underline_position_ + underline_thickness_); | 259 y + (text_size * (kUnderlineOffset + kLineThickness))); |
| 266 if (underline_thickness_ == kUnderlineMetricsNotSet) { | |
| 267 const SkScalar text_size = flags_.getTextSize(); | |
| 268 r.fTop = text_size * kUnderlineOffset + y; | |
| 269 r.fBottom = r.fTop + text_size * kLineThickness; | |
| 270 } | |
| 271 canvas_skia_->drawRect(r, flags_); | 260 canvas_skia_->drawRect(r, flags_); |
| 272 } | 261 } |
| 273 | 262 |
| 274 void SkiaTextRenderer::DrawStrike(int x, int y, int width) const { | 263 void SkiaTextRenderer::DrawStrike(int x, int y, int width) const { |
| 275 const SkScalar text_size = flags_.getTextSize(); | 264 const SkScalar text_size = flags_.getTextSize(); |
| 276 const SkScalar height = text_size * kLineThickness; | 265 const SkScalar height = text_size * strike_thickness_factor_; |
| 277 const SkScalar offset = text_size * kStrikeThroughOffset + y; | 266 const SkScalar offset = text_size * kStrikeThroughOffset - height / 2 + y; |
| 278 SkScalar x_scalar = SkIntToScalar(x); | 267 SkScalar x_scalar = SkIntToScalar(x); |
| 279 const SkRect r = | 268 const SkRect r = |
| 280 SkRect::MakeLTRB(x_scalar, offset, x_scalar + width, offset + height); | 269 SkRect::MakeLTRB(x_scalar, offset, x_scalar + width, offset + height); |
| 281 canvas_skia_->drawRect(r, flags_); | 270 canvas_skia_->drawRect(r, flags_); |
| 282 } | 271 } |
| 283 | 272 |
| 284 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 273 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
| 285 const BreakList<BaselineStyle>& baselines, | 274 const BreakList<BaselineStyle>& baselines, |
| 286 const BreakList<Font::Weight>& weights, | 275 const BreakList<Font::Weight>& weights, |
| 287 const std::vector<BreakList<bool>>& styles) | 276 const std::vector<BreakList<bool>>& styles) |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 775 | 764 |
| 776 canvas->Save(); | 765 canvas->Save(); |
| 777 canvas->ClipRect(clip_rect); | 766 canvas->ClipRect(clip_rect); |
| 778 } | 767 } |
| 779 | 768 |
| 780 if (!text().empty() && focused()) | 769 if (!text().empty() && focused()) |
| 781 DrawSelection(canvas); | 770 DrawSelection(canvas); |
| 782 | 771 |
| 783 if (!text().empty()) { | 772 if (!text().empty()) { |
| 784 internal::SkiaTextRenderer renderer(canvas); | 773 internal::SkiaTextRenderer renderer(canvas); |
| 774 renderer.SetStrikeThicknessFactor(strike_thickness_factor_); | |
|
cjgrant
2017/06/30 19:04:25
I must be doing this wrong, but I don't see a bett
msw
2017/06/30 20:51:23
I would suggest removing SkiaTextRenderer::SetStri
cjgrant
2017/06/30 21:06:24
I'd thought about plumbing through the call path,
msw
2017/06/30 23:01:32
You could add a simple accessor |RenderText::strik
cjgrant
2017/07/05 16:16:48
I did your top-preference, and removed the DrawDec
| |
| 785 DrawVisualText(&renderer); | 775 DrawVisualText(&renderer); |
| 786 } | 776 } |
| 787 | 777 |
| 788 if (clip_to_display_rect()) | 778 if (clip_to_display_rect()) |
| 789 canvas->Restore(); | 779 canvas->Restore(); |
| 790 } | 780 } |
| 791 | 781 |
| 792 bool RenderText::IsValidLogicalIndex(size_t index) const { | 782 bool RenderText::IsValidLogicalIndex(size_t index) const { |
| 793 // Check that the index is at a valid code point (not mid-surrgate-pair) and | 783 // Check that the index is at a valid code point (not mid-surrgate-pair) and |
| 794 // that it's not truncated from the display text (its glyph may be shown). | 784 // that it's not truncated from the display text (its glyph may be shown). |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 972 left_rect->origin() + Vector2d(0, lines()[line_index].baseline); | 962 left_rect->origin() + Vector2d(0, lines()[line_index].baseline); |
| 973 return true; | 963 return true; |
| 974 } | 964 } |
| 975 | 965 |
| 976 base::string16 RenderText::GetTextFromRange(const Range& range) const { | 966 base::string16 RenderText::GetTextFromRange(const Range& range) const { |
| 977 if (range.IsValid() && range.GetMin() < text().length()) | 967 if (range.IsValid() && range.GetMin() < text().length()) |
| 978 return text().substr(range.GetMin(), range.length()); | 968 return text().substr(range.GetMin(), range.length()); |
| 979 return base::string16(); | 969 return base::string16(); |
| 980 } | 970 } |
| 981 | 971 |
| 972 void RenderText::SetStrikeThicknessFactor(SkScalar factor) { | |
|
msw
2017/06/30 20:51:23
nit: this could be a simple setter defined in the
cjgrant
2017/07/05 16:16:48
Done.
| |
| 973 strike_thickness_factor_ = factor; | |
| 974 } | |
| 975 | |
| 982 RenderText::RenderText() | 976 RenderText::RenderText() |
| 983 : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), | 977 : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), |
| 984 directionality_mode_(DIRECTIONALITY_FROM_TEXT), | 978 directionality_mode_(DIRECTIONALITY_FROM_TEXT), |
| 985 text_direction_(base::i18n::UNKNOWN_DIRECTION), | 979 text_direction_(base::i18n::UNKNOWN_DIRECTION), |
| 986 cursor_enabled_(true), | 980 cursor_enabled_(true), |
| 987 selection_color_(kDefaultColor), | 981 selection_color_(kDefaultColor), |
| 988 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 982 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
| 989 focused_(false), | 983 focused_(false), |
| 990 composition_range_(Range::InvalidRange()), | 984 composition_range_(Range::InvalidRange()), |
| 991 colors_(kDefaultColor), | 985 colors_(kDefaultColor), |
| 992 baselines_(NORMAL_BASELINE), | 986 baselines_(NORMAL_BASELINE), |
| 993 weights_(Font::Weight::NORMAL), | 987 weights_(Font::Weight::NORMAL), |
| 994 styles_(NUM_TEXT_STYLES), | 988 styles_(NUM_TEXT_STYLES), |
| 995 composition_and_selection_styles_applied_(false), | 989 composition_and_selection_styles_applied_(false), |
| 996 obscured_(false), | 990 obscured_(false), |
| 997 obscured_reveal_index_(-1), | 991 obscured_reveal_index_(-1), |
| 998 truncate_length_(0), | 992 truncate_length_(0), |
| 999 elide_behavior_(NO_ELIDE), | 993 elide_behavior_(NO_ELIDE), |
| 1000 text_elided_(false), | 994 text_elided_(false), |
| 1001 min_line_height_(0), | 995 min_line_height_(0), |
| 1002 multiline_(false), | 996 multiline_(false), |
| 1003 max_lines_(0), | 997 max_lines_(0), |
| 1004 word_wrap_behavior_(IGNORE_LONG_WORDS), | 998 word_wrap_behavior_(IGNORE_LONG_WORDS), |
| 1005 replace_newline_chars_with_symbols_(true), | 999 replace_newline_chars_with_symbols_(true), |
| 1006 subpixel_rendering_suppressed_(false), | 1000 subpixel_rendering_suppressed_(false), |
| 1007 clip_to_display_rect_(true), | 1001 clip_to_display_rect_(true), |
| 1008 baseline_(kInvalidBaseline), | 1002 baseline_(kInvalidBaseline), |
| 1009 cached_bounds_and_offset_valid_(false) {} | 1003 cached_bounds_and_offset_valid_(false), |
| 1004 strike_thickness_factor_(kLineThickness) {} | |
| 1010 | 1005 |
| 1011 SelectionModel RenderText::GetAdjacentSelectionModel( | 1006 SelectionModel RenderText::GetAdjacentSelectionModel( |
| 1012 const SelectionModel& current, | 1007 const SelectionModel& current, |
| 1013 BreakType break_type, | 1008 BreakType break_type, |
| 1014 VisualCursorDirection direction) { | 1009 VisualCursorDirection direction) { |
| 1015 EnsureLayout(); | 1010 EnsureLayout(); |
| 1016 | 1011 |
| 1017 if (break_type == LINE_BREAK || text().empty()) | 1012 if (break_type == LINE_BREAK || text().empty()) |
| 1018 return EdgeSelectionModel(direction); | 1013 return EdgeSelectionModel(direction); |
| 1019 if (break_type == CHARACTER_BREAK) | 1014 if (break_type == CHARACTER_BREAK) |
| (...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1639 | 1634 |
| 1640 for (; range_max < length; ++range_max) | 1635 for (; range_max < length; ++range_max) |
| 1641 if (iter.IsEndOfWord(range_max) || iter.IsStartOfWord(range_max)) | 1636 if (iter.IsEndOfWord(range_max) || iter.IsStartOfWord(range_max)) |
| 1642 break; | 1637 break; |
| 1643 | 1638 |
| 1644 return range.is_reversed() ? Range(range_max, range_min) | 1639 return range.is_reversed() ? Range(range_max, range_min) |
| 1645 : Range(range_min, range_max); | 1640 : Range(range_min, range_max); |
| 1646 } | 1641 } |
| 1647 | 1642 |
| 1648 } // namespace gfx | 1643 } // namespace gfx |
| OLD | NEW |