| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <climits> | 8 #include <climits> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/i18n/break_iterator.h" | 11 #include "base/i18n/break_iterator.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "third_party/icu/source/common/unicode/rbbi.h" | 16 #include "third_party/icu/source/common/unicode/rbbi.h" |
| 17 #include "third_party/icu/source/common/unicode/utf16.h" | 17 #include "third_party/icu/source/common/unicode/utf16.h" |
| 18 #include "third_party/skia/include/core/SkTypeface.h" | 18 #include "third_party/skia/include/core/SkTypeface.h" |
| 19 #include "third_party/skia/include/effects/SkGradientShader.h" | 19 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 20 #include "ui/gfx/canvas.h" | 20 #include "ui/gfx/canvas.h" |
| 21 #include "ui/gfx/geometry/safe_integer_conversions.h" |
| 21 #include "ui/gfx/insets.h" | 22 #include "ui/gfx/insets.h" |
| 22 #include "ui/gfx/render_text_harfbuzz.h" | 23 #include "ui/gfx/render_text_harfbuzz.h" |
| 23 #include "ui/gfx/scoped_canvas.h" | 24 #include "ui/gfx/scoped_canvas.h" |
| 24 #include "ui/gfx/skia_util.h" | 25 #include "ui/gfx/skia_util.h" |
| 25 #include "ui/gfx/switches.h" | 26 #include "ui/gfx/switches.h" |
| 26 #include "ui/gfx/text_elider.h" | 27 #include "ui/gfx/text_elider.h" |
| 27 #include "ui/gfx/text_utils.h" | 28 #include "ui/gfx/text_utils.h" |
| 28 #include "ui/gfx/utf16_indexing.h" | 29 #include "ui/gfx/utf16_indexing.h" |
| 29 | 30 |
| 30 namespace gfx { | 31 namespace gfx { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 } | 263 } |
| 263 | 264 |
| 264 void SkiaTextRenderer::EndDiagonalStrike() { | 265 void SkiaTextRenderer::EndDiagonalStrike() { |
| 265 if (diagonal_) { | 266 if (diagonal_) { |
| 266 diagonal_->Draw(); | 267 diagonal_->Draw(); |
| 267 diagonal_.reset(); | 268 diagonal_.reset(); |
| 268 } | 269 } |
| 269 } | 270 } |
| 270 | 271 |
| 271 void SkiaTextRenderer::DrawUnderline(int x, int y, int width) { | 272 void SkiaTextRenderer::DrawUnderline(int x, int y, int width) { |
| 272 SkRect r = SkRect::MakeLTRB(x, y + underline_position_, x + width, | 273 SkScalar x_scalar = SkIntToScalar(x); |
| 273 y + underline_position_ + underline_thickness_); | 274 SkRect r = SkRect::MakeLTRB( |
| 275 x_scalar, y + underline_position_, x_scalar + width, |
| 276 y + underline_position_ + underline_thickness_); |
| 274 if (underline_thickness_ == kUnderlineMetricsNotSet) { | 277 if (underline_thickness_ == kUnderlineMetricsNotSet) { |
| 275 const SkScalar text_size = paint_.getTextSize(); | 278 const SkScalar text_size = paint_.getTextSize(); |
| 276 r.fTop = SkScalarMulAdd(text_size, kUnderlineOffset, y); | 279 r.fTop = SkScalarMulAdd(text_size, kUnderlineOffset, y); |
| 277 r.fBottom = r.fTop + SkScalarMul(text_size, kLineThickness); | 280 r.fBottom = r.fTop + SkScalarMul(text_size, kLineThickness); |
| 278 } | 281 } |
| 279 canvas_skia_->drawRect(r, paint_); | 282 canvas_skia_->drawRect(r, paint_); |
| 280 } | 283 } |
| 281 | 284 |
| 282 void SkiaTextRenderer::DrawStrike(int x, int y, int width) const { | 285 void SkiaTextRenderer::DrawStrike(int x, int y, int width) const { |
| 283 const SkScalar text_size = paint_.getTextSize(); | 286 const SkScalar text_size = paint_.getTextSize(); |
| 284 const SkScalar height = SkScalarMul(text_size, kLineThickness); | 287 const SkScalar height = SkScalarMul(text_size, kLineThickness); |
| 285 const SkScalar offset = SkScalarMulAdd(text_size, kStrikeThroughOffset, y); | 288 const SkScalar offset = SkScalarMulAdd(text_size, kStrikeThroughOffset, y); |
| 286 const SkRect r = SkRect::MakeLTRB(x, offset, x + width, offset + height); | 289 SkScalar x_scalar = SkIntToScalar(x); |
| 290 const SkRect r = |
| 291 SkRect::MakeLTRB(x_scalar, offset, x_scalar + width, offset + height); |
| 287 canvas_skia_->drawRect(r, paint_); | 292 canvas_skia_->drawRect(r, paint_); |
| 288 } | 293 } |
| 289 | 294 |
| 290 SkiaTextRenderer::DiagonalStrike::DiagonalStrike(Canvas* canvas, | 295 SkiaTextRenderer::DiagonalStrike::DiagonalStrike(Canvas* canvas, |
| 291 Point start, | 296 Point start, |
| 292 const SkPaint& paint) | 297 const SkPaint& paint) |
| 293 : canvas_(canvas), | 298 : canvas_(canvas), |
| 294 start_(start), | 299 start_(start), |
| 295 paint_(paint), | 300 paint_(paint), |
| 296 total_length_(0) { | 301 total_length_(0) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 307 void SkiaTextRenderer::DiagonalStrike::Draw() { | 312 void SkiaTextRenderer::DiagonalStrike::Draw() { |
| 308 const SkScalar text_size = paint_.getTextSize(); | 313 const SkScalar text_size = paint_.getTextSize(); |
| 309 const SkScalar offset = SkScalarMul(text_size, kDiagonalStrikeMarginOffset); | 314 const SkScalar offset = SkScalarMul(text_size, kDiagonalStrikeMarginOffset); |
| 310 const int thickness = | 315 const int thickness = |
| 311 SkScalarCeilToInt(SkScalarMul(text_size, kLineThickness) * 2); | 316 SkScalarCeilToInt(SkScalarMul(text_size, kLineThickness) * 2); |
| 312 const int height = SkScalarCeilToInt(text_size - offset); | 317 const int height = SkScalarCeilToInt(text_size - offset); |
| 313 const Point end = start_ + Vector2d(total_length_, -height); | 318 const Point end = start_ + Vector2d(total_length_, -height); |
| 314 const int clip_height = height + 2 * thickness; | 319 const int clip_height = height + 2 * thickness; |
| 315 | 320 |
| 316 paint_.setAntiAlias(true); | 321 paint_.setAntiAlias(true); |
| 317 paint_.setStrokeWidth(thickness); | 322 paint_.setStrokeWidth(SkIntToScalar(thickness)); |
| 318 | 323 |
| 319 const bool clipped = pieces_.size() > 1; | 324 const bool clipped = pieces_.size() > 1; |
| 320 SkCanvas* sk_canvas = canvas_->sk_canvas(); | 325 SkCanvas* sk_canvas = canvas_->sk_canvas(); |
| 321 int x = start_.x(); | 326 int x = start_.x(); |
| 322 | 327 |
| 323 for (size_t i = 0; i < pieces_.size(); ++i) { | 328 for (size_t i = 0; i < pieces_.size(); ++i) { |
| 324 paint_.setColor(pieces_[i].second); | 329 paint_.setColor(pieces_[i].second); |
| 325 | 330 |
| 326 if (clipped) { | 331 if (clipped) { |
| 327 canvas_->Save(); | 332 canvas_->Save(); |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 | 718 |
| 714 return text_direction_; | 719 return text_direction_; |
| 715 } | 720 } |
| 716 | 721 |
| 717 VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() { | 722 VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() { |
| 718 return GetTextDirection() == base::i18n::LEFT_TO_RIGHT ? | 723 return GetTextDirection() == base::i18n::LEFT_TO_RIGHT ? |
| 719 CURSOR_RIGHT : CURSOR_LEFT; | 724 CURSOR_RIGHT : CURSOR_LEFT; |
| 720 } | 725 } |
| 721 | 726 |
| 722 SizeF RenderText::GetStringSizeF() { | 727 SizeF RenderText::GetStringSizeF() { |
| 723 const Size size = GetStringSize(); | 728 return GetStringSize(); |
| 724 return SizeF(size.width(), size.height()); | |
| 725 } | 729 } |
| 726 | 730 |
| 727 float RenderText::GetContentWidth() { | 731 float RenderText::GetContentWidth() { |
| 728 return GetStringSizeF().width() + (cursor_enabled_ ? 1 : 0); | 732 return GetStringSizeF().width() + (cursor_enabled_ ? 1 : 0); |
| 729 } | 733 } |
| 730 | 734 |
| 731 int RenderText::GetBaseline() { | 735 int RenderText::GetBaseline() { |
| 732 if (baseline_ == kInvalidBaseline) | 736 if (baseline_ == kInvalidBaseline) |
| 733 baseline_ = DetermineBaselineCenteringText(display_rect(), font_list()); | 737 baseline_ = DetermineBaselineCenteringText(display_rect(), font_list()); |
| 734 DCHECK_NE(kInvalidBaseline, baseline_); | 738 DCHECK_NE(kInvalidBaseline, baseline_); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 return SelectionModel(sel.start(), | 854 return SelectionModel(sel.start(), |
| 851 sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD); | 855 sel.is_reversed() ? CURSOR_BACKWARD : CURSOR_FORWARD); |
| 852 } | 856 } |
| 853 | 857 |
| 854 const Vector2d& RenderText::GetUpdatedDisplayOffset() { | 858 const Vector2d& RenderText::GetUpdatedDisplayOffset() { |
| 855 UpdateCachedBoundsAndOffset(); | 859 UpdateCachedBoundsAndOffset(); |
| 856 return display_offset_; | 860 return display_offset_; |
| 857 } | 861 } |
| 858 | 862 |
| 859 void RenderText::SetDisplayOffset(int horizontal_offset) { | 863 void RenderText::SetDisplayOffset(int horizontal_offset) { |
| 860 const int extra_content = GetContentWidth() - display_rect_.width(); | 864 const int extra_content = |
| 865 ToFlooredInt(GetContentWidth()) - display_rect_.width(); |
| 861 const int cursor_width = cursor_enabled_ ? 1 : 0; | 866 const int cursor_width = cursor_enabled_ ? 1 : 0; |
| 862 | 867 |
| 863 int min_offset = 0; | 868 int min_offset = 0; |
| 864 int max_offset = 0; | 869 int max_offset = 0; |
| 865 if (extra_content > 0) { | 870 if (extra_content > 0) { |
| 866 switch (GetCurrentHorizontalAlignment()) { | 871 switch (GetCurrentHorizontalAlignment()) { |
| 867 case ALIGN_LEFT: | 872 case ALIGN_LEFT: |
| 868 min_offset = -extra_content; | 873 min_offset = -extra_content; |
| 869 break; | 874 break; |
| 870 case ALIGN_RIGHT: | 875 case ALIGN_RIGHT: |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 layout_text_.assign(text.substr(0, iter.getIndex()) + kEllipsisUTF16); | 1208 layout_text_.assign(text.substr(0, iter.getIndex()) + kEllipsisUTF16); |
| 1204 } | 1209 } |
| 1205 } | 1210 } |
| 1206 | 1211 |
| 1207 if (elide_behavior_ != NO_ELIDE && | 1212 if (elide_behavior_ != NO_ELIDE && |
| 1208 elide_behavior_ != FADE_TAIL && | 1213 elide_behavior_ != FADE_TAIL && |
| 1209 !layout_text_.empty() && | 1214 !layout_text_.empty() && |
| 1210 static_cast<int>(GetContentWidth()) > display_rect_.width()) { | 1215 static_cast<int>(GetContentWidth()) > display_rect_.width()) { |
| 1211 // This doesn't trim styles so ellipsis may get rendered as a different | 1216 // This doesn't trim styles so ellipsis may get rendered as a different |
| 1212 // style than the preceding text. See crbug.com/327850. | 1217 // style than the preceding text. See crbug.com/327850. |
| 1213 layout_text_.assign( | 1218 layout_text_.assign(Elide(layout_text_, |
| 1214 Elide(layout_text_, display_rect_.width(), elide_behavior_)); | 1219 static_cast<float>(display_rect_.width()), |
| 1220 elide_behavior_)); |
| 1215 } | 1221 } |
| 1216 | 1222 |
| 1217 // Replace the newline character with a newline symbol in single line mode. | 1223 // Replace the newline character with a newline symbol in single line mode. |
| 1218 static const base::char16 kNewline[] = { '\n', 0 }; | 1224 static const base::char16 kNewline[] = { '\n', 0 }; |
| 1219 static const base::char16 kNewlineSymbol[] = { 0x2424, 0 }; | 1225 static const base::char16 kNewlineSymbol[] = { 0x2424, 0 }; |
| 1220 if (!multiline_ && replace_newline_chars_with_symbols_) | 1226 if (!multiline_ && replace_newline_chars_with_symbols_) |
| 1221 base::ReplaceChars(layout_text_, kNewline, kNewlineSymbol, &layout_text_); | 1227 base::ReplaceChars(layout_text_, kNewline, kNewlineSymbol, &layout_text_); |
| 1222 | 1228 |
| 1223 ResetLayout(); | 1229 ResetLayout(); |
| 1224 } | 1230 } |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1404 SetDisplayOffset(display_offset_.x() + delta_x); | 1410 SetDisplayOffset(display_offset_.x() + delta_x); |
| 1405 } | 1411 } |
| 1406 | 1412 |
| 1407 void RenderText::DrawSelection(Canvas* canvas) { | 1413 void RenderText::DrawSelection(Canvas* canvas) { |
| 1408 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 1414 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
| 1409 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) | 1415 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) |
| 1410 canvas->FillRect(*i, selection_background_focused_color_); | 1416 canvas->FillRect(*i, selection_background_focused_color_); |
| 1411 } | 1417 } |
| 1412 | 1418 |
| 1413 } // namespace gfx | 1419 } // namespace gfx |
| OLD | NEW |