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" |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 FontRenderParams::Hinting params_hinting) { | 167 FontRenderParams::Hinting params_hinting) { |
168 switch (params_hinting) { | 168 switch (params_hinting) { |
169 case FontRenderParams::HINTING_NONE: return SkPaint::kNo_Hinting; | 169 case FontRenderParams::HINTING_NONE: return SkPaint::kNo_Hinting; |
170 case FontRenderParams::HINTING_SLIGHT: return SkPaint::kSlight_Hinting; | 170 case FontRenderParams::HINTING_SLIGHT: return SkPaint::kSlight_Hinting; |
171 case FontRenderParams::HINTING_MEDIUM: return SkPaint::kNormal_Hinting; | 171 case FontRenderParams::HINTING_MEDIUM: return SkPaint::kNormal_Hinting; |
172 case FontRenderParams::HINTING_FULL: return SkPaint::kFull_Hinting; | 172 case FontRenderParams::HINTING_FULL: return SkPaint::kFull_Hinting; |
173 } | 173 } |
174 return SkPaint::kNo_Hinting; | 174 return SkPaint::kNo_Hinting; |
175 } | 175 } |
176 | 176 |
177 // Make sure ranges don't break text graphemes. If a range in |break_list| | |
178 // does break a grapheme in |render_text|, the range will be slightly | |
179 // extended to encompass the grapheme. | |
180 template <typename T> | |
181 void RestoreBreakList(RenderText* render_text, BreakList<T>& break_list) { | |
182 break_list.SetMax(render_text->text().length()); | |
183 Range range; | |
184 while (range.end() < break_list.max()) { | |
185 const auto& current_break = break_list.GetBreak(range.end()); | |
186 range = break_list.GetRange(current_break); | |
187 if (range.end() < break_list.max() && | |
188 !render_text->IsValidCursorIndex(range.end())) { | |
189 range.set_end( | |
190 render_text->IndexOfAdjacentGrapheme(range.end(), CURSOR_FORWARD)); | |
191 break_list.ApplyValue(current_break->second, range); | |
192 } | |
193 } | |
194 } | |
195 | |
196 } // namespace | 177 } // namespace |
197 | 178 |
198 namespace internal { | 179 namespace internal { |
199 | 180 |
200 // Value of |underline_thickness_| that indicates that underline metrics have | 181 // Value of |underline_thickness_| that indicates that underline metrics have |
201 // not been set explicitly. | 182 // not been set explicitly. |
202 const SkScalar kUnderlineMetricsNotSet = -1.0f; | 183 const SkScalar kUnderlineMetricsNotSet = -1.0f; |
203 | 184 |
204 SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas) | 185 SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas) |
205 : canvas_(canvas), | 186 : canvas_(canvas), |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 canvas_->DrawLine(start_, end, paint_); | 342 canvas_->DrawLine(start_, end, paint_); |
362 | 343 |
363 if (clipped) | 344 if (clipped) |
364 canvas_->Restore(); | 345 canvas_->Restore(); |
365 | 346 |
366 x += pieces_[i].first; | 347 x += pieces_[i].first; |
367 } | 348 } |
368 } | 349 } |
369 | 350 |
370 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 351 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
371 const BreakList<BaselineStyle>& baselines, | 352 const std::vector<BreakList<bool> >& styles) |
372 const std::vector<BreakList<bool>>& styles) | 353 : colors_(colors), |
373 : colors_(colors), baselines_(baselines), styles_(styles) { | 354 styles_(styles) { |
374 color_ = colors_.breaks().begin(); | 355 color_ = colors_.breaks().begin(); |
375 baseline_ = baselines_.breaks().begin(); | |
376 for (size_t i = 0; i < styles_.size(); ++i) | 356 for (size_t i = 0; i < styles_.size(); ++i) |
377 style_.push_back(styles_[i].breaks().begin()); | 357 style_.push_back(styles_[i].breaks().begin()); |
378 } | 358 } |
379 | 359 |
380 StyleIterator::~StyleIterator() {} | 360 StyleIterator::~StyleIterator() {} |
381 | 361 |
382 Range StyleIterator::GetRange() const { | 362 Range StyleIterator::GetRange() const { |
383 Range range(colors_.GetRange(color_)); | 363 Range range(colors_.GetRange(color_)); |
384 range = range.Intersect(baselines_.GetRange(baseline_)); | |
385 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 364 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
386 range = range.Intersect(styles_[i].GetRange(style_[i])); | 365 range = range.Intersect(styles_[i].GetRange(style_[i])); |
387 return range; | 366 return range; |
388 } | 367 } |
389 | 368 |
390 void StyleIterator::UpdatePosition(size_t position) { | 369 void StyleIterator::UpdatePosition(size_t position) { |
391 color_ = colors_.GetBreak(position); | 370 color_ = colors_.GetBreak(position); |
392 baseline_ = baselines_.GetBreak(position); | |
393 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | 371 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) |
394 style_[i] = styles_[i].GetBreak(position); | 372 style_[i] = styles_[i].GetBreak(position); |
395 } | 373 } |
396 | 374 |
397 LineSegment::LineSegment() : width(0), run(0) {} | 375 LineSegment::LineSegment() : width(0), run(0) {} |
398 | 376 |
399 LineSegment::~LineSegment() {} | 377 LineSegment::~LineSegment() {} |
400 | 378 |
401 Line::Line() : preceding_heights(0), baseline(0) {} | 379 Line::Line() : preceding_heights(0), baseline(0) {} |
402 | 380 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 RenderText* RenderText::CreateInstanceForEditing() { | 416 RenderText* RenderText::CreateInstanceForEditing() { |
439 return new RenderTextHarfBuzz; | 417 return new RenderTextHarfBuzz; |
440 } | 418 } |
441 | 419 |
442 void RenderText::SetText(const base::string16& text) { | 420 void RenderText::SetText(const base::string16& text) { |
443 DCHECK(!composition_range_.IsValid()); | 421 DCHECK(!composition_range_.IsValid()); |
444 if (text_ == text) | 422 if (text_ == text) |
445 return; | 423 return; |
446 text_ = text; | 424 text_ = text; |
447 | 425 |
448 // Adjust ranged styles, baselines, and colors to accommodate a new text | 426 // Adjust ranged styles and colors to accommodate a new text length. |
449 // length. Clear style ranges as they might break new text graphemes and apply | 427 // Clear style ranges as they might break new text graphemes and apply |
450 // the first style to the whole text instead. | 428 // the first style to the whole text instead. |
451 const size_t text_length = text_.length(); | 429 const size_t text_length = text_.length(); |
452 colors_.SetMax(text_length); | 430 colors_.SetMax(text_length); |
453 baselines_.SetValue(baselines_.breaks().begin()->second); | |
454 baselines_.SetMax(text_length); | |
455 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) { | 431 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) { |
456 BreakList<bool>& break_list = styles_[style]; | 432 BreakList<bool>& break_list = styles_[style]; |
457 break_list.SetValue(break_list.breaks().begin()->second); | 433 break_list.SetValue(break_list.breaks().begin()->second); |
458 break_list.SetMax(text_length); | 434 break_list.SetMax(text_length); |
459 } | 435 } |
460 cached_bounds_and_offset_valid_ = false; | 436 cached_bounds_and_offset_valid_ = false; |
461 | 437 |
462 // Reset selection model. SetText should always followed by SetSelectionModel | 438 // Reset selection model. SetText should always followed by SetSelectionModel |
463 // or SetCursorPosition in upper layer. | 439 // or SetCursorPosition in upper layer. |
464 SetSelectionModel(SelectionModel()); | 440 SetSelectionModel(SelectionModel()); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 } | 663 } |
688 | 664 |
689 void RenderText::SetColor(SkColor value) { | 665 void RenderText::SetColor(SkColor value) { |
690 colors_.SetValue(value); | 666 colors_.SetValue(value); |
691 } | 667 } |
692 | 668 |
693 void RenderText::ApplyColor(SkColor value, const Range& range) { | 669 void RenderText::ApplyColor(SkColor value, const Range& range) { |
694 colors_.ApplyValue(value, range); | 670 colors_.ApplyValue(value, range); |
695 } | 671 } |
696 | 672 |
697 void RenderText::SetBaselineStyle(BaselineStyle value) { | |
698 baselines_.SetValue(value); | |
699 } | |
700 | |
701 void RenderText::ApplyBaselineStyle(BaselineStyle value, const Range& range) { | |
702 baselines_.ApplyValue(value, range); | |
703 } | |
704 | |
705 void RenderText::SetStyle(TextStyle style, bool value) { | 673 void RenderText::SetStyle(TextStyle style, bool value) { |
706 styles_[style].SetValue(value); | 674 styles_[style].SetValue(value); |
707 | 675 |
708 cached_bounds_and_offset_valid_ = false; | 676 cached_bounds_and_offset_valid_ = false; |
709 // TODO(oshima|msw): Not all style change requires layout changes. | 677 // TODO(oshima|msw): Not all style change requires layout changes. |
710 // Consider optimizing based on the type of change. | 678 // Consider optimizing based on the type of change. |
711 OnLayoutTextAttributeChanged(false); | 679 OnLayoutTextAttributeChanged(false); |
712 } | 680 } |
713 | 681 |
714 void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) { | 682 void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) { |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 text_direction_(base::i18n::UNKNOWN_DIRECTION), | 903 text_direction_(base::i18n::UNKNOWN_DIRECTION), |
936 cursor_enabled_(true), | 904 cursor_enabled_(true), |
937 cursor_visible_(false), | 905 cursor_visible_(false), |
938 insert_mode_(true), | 906 insert_mode_(true), |
939 cursor_color_(kDefaultColor), | 907 cursor_color_(kDefaultColor), |
940 selection_color_(kDefaultColor), | 908 selection_color_(kDefaultColor), |
941 selection_background_focused_color_(kDefaultSelectionBackgroundColor), | 909 selection_background_focused_color_(kDefaultSelectionBackgroundColor), |
942 focused_(false), | 910 focused_(false), |
943 composition_range_(Range::InvalidRange()), | 911 composition_range_(Range::InvalidRange()), |
944 colors_(kDefaultColor), | 912 colors_(kDefaultColor), |
945 baselines_(NORMAL_BASELINE), | |
946 styles_(NUM_TEXT_STYLES), | 913 styles_(NUM_TEXT_STYLES), |
947 composition_and_selection_styles_applied_(false), | 914 composition_and_selection_styles_applied_(false), |
948 obscured_(false), | 915 obscured_(false), |
949 obscured_reveal_index_(-1), | 916 obscured_reveal_index_(-1), |
950 truncate_length_(0), | 917 truncate_length_(0), |
951 elide_behavior_(NO_ELIDE), | 918 elide_behavior_(NO_ELIDE), |
952 text_elided_(false), | 919 text_elided_(false), |
953 min_line_height_(0), | 920 min_line_height_(0), |
954 multiline_(false), | 921 multiline_(false), |
955 subpixel_rendering_suppressed_(false), | 922 subpixel_rendering_suppressed_(false), |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1309 | 1276 |
1310 TRACE_EVENT0("ui", "RenderText::Elide"); | 1277 TRACE_EVENT0("ui", "RenderText::Elide"); |
1311 | 1278 |
1312 // Create a RenderText copy with attributes that affect the rendering width. | 1279 // Create a RenderText copy with attributes that affect the rendering width. |
1313 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); | 1280 scoped_ptr<RenderText> render_text = CreateInstanceOfSameType(); |
1314 render_text->SetFontList(font_list_); | 1281 render_text->SetFontList(font_list_); |
1315 render_text->SetDirectionalityMode(directionality_mode_); | 1282 render_text->SetDirectionalityMode(directionality_mode_); |
1316 render_text->SetCursorEnabled(cursor_enabled_); | 1283 render_text->SetCursorEnabled(cursor_enabled_); |
1317 render_text->set_truncate_length(truncate_length_); | 1284 render_text->set_truncate_length(truncate_length_); |
1318 render_text->styles_ = styles_; | 1285 render_text->styles_ = styles_; |
1319 render_text->baselines_ = baselines_; | |
1320 render_text->colors_ = colors_; | 1286 render_text->colors_ = colors_; |
1321 if (text_width == 0) { | 1287 if (text_width == 0) { |
1322 render_text->SetText(text); | 1288 render_text->SetText(text); |
1323 text_width = render_text->GetContentWidthF(); | 1289 text_width = render_text->GetContentWidthF(); |
1324 } | 1290 } |
1325 if (text_width <= available_width) | 1291 if (text_width <= available_width) |
1326 return text; | 1292 return text; |
1327 | 1293 |
1328 const base::string16 ellipsis = base::string16(kEllipsisUTF16); | 1294 const base::string16 ellipsis = base::string16(kEllipsisUTF16); |
1329 const bool insert_ellipsis = (behavior != TRUNCATE); | 1295 const bool insert_ellipsis = (behavior != TRUNCATE); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 new_text.append(ellipsis); | 1329 new_text.append(ellipsis); |
1364 if (trailing_text_direction != text_direction) { | 1330 if (trailing_text_direction != text_direction) { |
1365 if (trailing_text_direction == base::i18n::LEFT_TO_RIGHT) | 1331 if (trailing_text_direction == base::i18n::LEFT_TO_RIGHT) |
1366 new_text += base::i18n::kLeftToRightMark; | 1332 new_text += base::i18n::kLeftToRightMark; |
1367 else | 1333 else |
1368 new_text += base::i18n::kRightToLeftMark; | 1334 new_text += base::i18n::kRightToLeftMark; |
1369 } | 1335 } |
1370 render_text->SetText(new_text); | 1336 render_text->SetText(new_text); |
1371 } | 1337 } |
1372 | 1338 |
1373 // Restore styles and baselines without breaking multi-character graphemes. | 1339 // Restore styles. Make sure style ranges don't break new text graphemes. |
1374 render_text->styles_ = styles_; | 1340 render_text->styles_ = styles_; |
1375 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 1341 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) { |
1376 RestoreBreakList(render_text.get(), render_text->styles_[style]); | 1342 BreakList<bool>& break_list = render_text->styles_[style]; |
1377 RestoreBreakList(render_text.get(), baselines_); | 1343 break_list.SetMax(render_text->text_.length()); |
| 1344 Range range; |
| 1345 while (range.end() < break_list.max()) { |
| 1346 BreakList<bool>::const_iterator current_break = |
| 1347 break_list.GetBreak(range.end()); |
| 1348 range = break_list.GetRange(current_break); |
| 1349 if (range.end() < break_list.max() && |
| 1350 !render_text->IsValidCursorIndex(range.end())) { |
| 1351 range.set_end(render_text->IndexOfAdjacentGrapheme(range.end(), |
| 1352 CURSOR_FORWARD)); |
| 1353 break_list.ApplyValue(current_break->second, range); |
| 1354 } |
| 1355 } |
| 1356 } |
1378 | 1357 |
1379 // We check the width of the whole desired string at once to ensure we | 1358 // We check the width of the whole desired string at once to ensure we |
1380 // handle kerning/ligatures/etc. correctly. | 1359 // handle kerning/ligatures/etc. correctly. |
1381 const float guess_width = render_text->GetContentWidthF(); | 1360 const float guess_width = render_text->GetContentWidthF(); |
1382 if (guess_width == available_width) | 1361 if (guess_width == available_width) |
1383 break; | 1362 break; |
1384 if (guess_width > available_width) { | 1363 if (guess_width > available_width) { |
1385 hi = guess - 1; | 1364 hi = guess - 1; |
1386 // Move back on the loop terminating condition when the guess is too wide. | 1365 // Move back on the loop terminating condition when the guess is too wide. |
1387 if (hi < lo) | 1366 if (hi < lo) |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1474 | 1453 |
1475 SetDisplayOffset(display_offset_.x() + delta_x); | 1454 SetDisplayOffset(display_offset_.x() + delta_x); |
1476 } | 1455 } |
1477 | 1456 |
1478 void RenderText::DrawSelection(Canvas* canvas) { | 1457 void RenderText::DrawSelection(Canvas* canvas) { |
1479 for (const Rect& s : GetSubstringBounds(selection())) | 1458 for (const Rect& s : GetSubstringBounds(selection())) |
1480 canvas->FillRect(s, selection_background_focused_color_); | 1459 canvas->FillRect(s, selection_background_focused_color_); |
1481 } | 1460 } |
1482 | 1461 |
1483 } // namespace gfx | 1462 } // namespace gfx |
OLD | NEW |