Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: ui/gfx/render_text_win.cc

Issue 11535014: Replace StyleRange with BreakList; update RenderText, etc. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Simplify OmniboxResultView; Rename StyleBreak; cleanup. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_win.h" 5 #include "ui/gfx/render_text_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/i18n/break_iterator.h" 9 #include "base/i18n/break_iterator.h"
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 if (base::win::GetVersion() < base::win::VERSION_VISTA) { 104 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
105 PlatformFontWin* platform_font = 105 PlatformFontWin* platform_font =
106 static_cast<PlatformFontWin*>(font->platform_font()); 106 static_cast<PlatformFontWin*>(font->platform_font());
107 *font = platform_font->DeriveFontWithHeight(font_height, target_style); 107 *font = platform_font->DeriveFontWithHeight(font_height, target_style);
108 return; 108 return;
109 } 109 }
110 110
111 const int current_style = (font->GetStyle() & kStyleMask); 111 const int current_style = (font->GetStyle() & kStyleMask);
112 const int current_size = font->GetFontSize(); 112 const int current_size = font->GetFontSize();
113 if (current_style != target_style || current_size != font_size) 113 if (current_style != target_style || current_size != font_size)
114 *font = font->DeriveFont(font_size - current_size, font_style); 114 *font = font->DeriveFont(font_size - current_size, target_style);
115 } 115 }
116 116
117 // Returns true if |c| is a Unicode BiDi control character. 117 // Returns true if |c| is a Unicode BiDi control character.
118 bool IsUnicodeBidiControlCharacter(char16 c) { 118 bool IsUnicodeBidiControlCharacter(char16 c) {
119 return c == base::i18n::kRightToLeftMark || 119 return c == base::i18n::kRightToLeftMark ||
120 c == base::i18n::kLeftToRightMark || 120 c == base::i18n::kLeftToRightMark ||
121 c == base::i18n::kLeftToRightEmbeddingMark || 121 c == base::i18n::kLeftToRightEmbeddingMark ||
122 c == base::i18n::kRightToLeftEmbeddingMark || 122 c == base::i18n::kRightToLeftEmbeddingMark ||
123 c == base::i18n::kPopDirectionalFormatting || 123 c == base::i18n::kPopDirectionalFormatting ||
124 c == base::i18n::kLeftToRightOverride || 124 c == base::i18n::kLeftToRightOverride ||
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 pos = iter.pos() - iter.GetString().length(); 327 pos = iter.pos() - iter.GetString().length();
328 } 328 }
329 } 329 }
330 } 330 }
331 } 331 }
332 return SelectionModel(pos, CURSOR_FORWARD); 332 return SelectionModel(pos, CURSOR_FORWARD);
333 } 333 }
334 334
335 void RenderTextWin::SetSelectionModel(const SelectionModel& model) { 335 void RenderTextWin::SetSelectionModel(const SelectionModel& model) {
336 RenderText::SetSelectionModel(model); 336 RenderText::SetSelectionModel(model);
337 // TODO(xji): The styles are applied to text inside ItemizeLogicalText(). So, 337 // TODO(xji|msw): The text selection color is applied in ItemizeLogicalText().
338 // we need to update layout here in order for the styles, such as selection 338 // So, the layout must be updated in order to draw the proper selection range.
339 // foreground, to be picked up. Eventually, we should separate styles from 339 // Colors should be applied in DrawVisualText(), as done by RenderTextLinux.
340 // layout by applying foreground, strike, and underline styles during
341 // DrawVisualText as what RenderTextLinux does.
342 ResetLayout(); 340 ResetLayout();
343 } 341 }
344 342
345 void RenderTextWin::GetGlyphBounds(size_t index, 343 void RenderTextWin::GetGlyphBounds(size_t index,
346 ui::Range* xspan, 344 ui::Range* xspan,
347 int* height) { 345 int* height) {
348 const size_t run_index = 346 const size_t run_index =
349 GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD)); 347 GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD));
350 DCHECK_LT(run_index, runs_.size()); 348 DCHECK_LT(run_index, runs_.size());
351 internal::TextRun* run = runs_[run_index]; 349 internal::TextRun* run = runs_[run_index];
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 for (int glyph = 0; glyph < run->glyph_count; glyph++) { 478 for (int glyph = 0; glyph < run->glyph_count; glyph++) {
481 pos[glyph].set(glyph_x + run->offsets[glyph].du, 479 pos[glyph].set(glyph_x + run->offsets[glyph].du,
482 y + run->offsets[glyph].dv); 480 y + run->offsets[glyph].dv);
483 glyph_x += SkIntToScalar(run->advance_widths[glyph]); 481 glyph_x += SkIntToScalar(run->advance_widths[glyph]);
484 } 482 }
485 483
486 renderer.SetTextSize(run->font.GetFontSize()); 484 renderer.SetTextSize(run->font.GetFontSize());
487 renderer.SetFontFamilyWithStyle(run->font.GetFontName(), run->font_style); 485 renderer.SetFontFamilyWithStyle(run->font.GetFontName(), run->font_style);
488 renderer.SetForegroundColor(run->foreground); 486 renderer.SetForegroundColor(run->foreground);
489 renderer.DrawPosText(&pos[0], run->glyphs.get(), run->glyph_count); 487 renderer.DrawPosText(&pos[0], run->glyphs.get(), run->glyph_count);
490 // TODO(oshima|msw): Consider refactoring StyleRange into Style 488 renderer.DrawDecorations(x, y, run->width, run->underline, run->strike,
491 // class and StyleRange containing Style, and use Style class in 489 run->diagonal_strike);
492 // TextRun class. This may conflict with msw's comment in
493 // TextRun, so please consult with msw when refactoring.
494 StyleRange style;
495 style.strike = run->strike;
496 style.diagonal_strike = run->diagonal_strike;
497 style.underline = run->underline;
498 renderer.DrawDecorations(x, y, run->width, style);
499 490
500 x = glyph_x; 491 x = glyph_x;
501 } 492 }
502 } 493 }
503 494
504 void RenderTextWin::ItemizeLogicalText() { 495 void RenderTextWin::ItemizeLogicalText() {
505 runs_.clear(); 496 runs_.clear();
506 string_size_ = Size(0, GetFont().GetHeight()); 497 string_size_ = Size(0, GetFont().GetHeight());
507 common_baseline_ = 0; 498 common_baseline_ = 0;
508 499
509 // Set Uniscribe's base text direction. 500 // Set Uniscribe's base text direction.
510 script_state_.uBidiLevel = 501 script_state_.uBidiLevel =
511 (GetTextDirection() == base::i18n::RIGHT_TO_LEFT) ? 1 : 0; 502 (GetTextDirection() == base::i18n::RIGHT_TO_LEFT) ? 1 : 0;
512 503
513 if (text().empty()) 504 if (text().empty())
514 return; 505 return;
515 506
516 HRESULT hr = E_OUTOFMEMORY; 507 HRESULT hr = E_OUTOFMEMORY;
517 int script_items_count = 0; 508 int script_items_count = 0;
518 std::vector<SCRIPT_ITEM> script_items; 509 std::vector<SCRIPT_ITEM> script_items;
519 const int text_length = GetLayoutText().length(); 510 const size_t text_length = GetLayoutText().length();
520 for (size_t n = kGuessItems; hr == E_OUTOFMEMORY && n < kMaxItems; n *= 2) { 511 for (size_t n = kGuessItems; hr == E_OUTOFMEMORY && n < kMaxItems; n *= 2) {
521 // Derive the array of Uniscribe script items from the logical text. 512 // Derive the array of Uniscribe script items from the logical text.
522 // ScriptItemize always adds a terminal array item so that the length of the 513 // ScriptItemize always adds a terminal array item so that the length of the
523 // last item can be derived from the terminal SCRIPT_ITEM::iCharPos. 514 // last item can be derived from the terminal SCRIPT_ITEM::iCharPos.
524 script_items.resize(n); 515 script_items.resize(n);
525 hr = ScriptItemize(GetLayoutText().c_str(), 516 hr = ScriptItemize(GetLayoutText().c_str(),
526 text_length, 517 text_length,
527 n - 1, 518 n - 1,
528 &script_control_, 519 &script_control_,
529 &script_state_, 520 &script_state_,
530 &script_items[0], 521 &script_items[0],
531 &script_items_count); 522 &script_items_count);
532 } 523 }
533 DCHECK(SUCCEEDED(hr)); 524 DCHECK(SUCCEEDED(hr));
534 525
535 if (script_items_count <= 0) 526 if (script_items_count <= 0)
536 return; 527 return;
537 528
538 // Build the list of runs, merge font/underline styles. 529 // Adjust the text colors to reflect the selection range.
539 // TODO(msw): Only break for font changes, not color etc. See TextRun comment. 530 ColorBreaks adjusted_colors(colors());
540 StyleRanges styles(style_ranges()); 531 ApplySelectionColor(&adjusted_colors);
541 ApplyCompositionAndSelectionStyles(&styles); 532
542 StyleRanges::const_iterator style = styles.begin(); 533 // Adjust the underline styling to reflect composition ranges.
534 const StyleBreaks* adjusted_styles[NUM_TEXT_STYLES];
Alexei Svitkine (slow) 2013/01/22 19:20:21 I don't get why you need this. Can you explain?
msw 2013/01/22 22:27:24 Similar to the previous code, where |styles| was a
535 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i)
536 adjusted_styles[i] = &styles(static_cast<TextStyle>(i));
537 StyleBreaks adjusted_underlines(styles(UNDERLINE));
538 ApplyCompositionStyle(&adjusted_underlines);
539 adjusted_styles[UNDERLINE] = &adjusted_underlines;
Alexei Svitkine (slow) 2013/01/22 19:20:21 The code in the diff doesn't seem to be special-ca
msw 2013/01/22 22:27:24 The prior code applied the transient composition u
540
541 // Track the current color and style with iterators.
542 ColorBreaks::const_iterator color = adjusted_colors.begin();
543 StyleBreaks::const_iterator style[NUM_TEXT_STYLES];
544 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i)
545 style[i] = adjusted_styles[i]->begin();
546 size_t style_end[NUM_TEXT_STYLES];
547
548 // Build the list of runs from the script items and ranged colors/styles.
549 // TODO(msw): Only break for bold/italic, not color etc. See TextRun comment.
543 SCRIPT_ITEM* script_item = &script_items[0]; 550 SCRIPT_ITEM* script_item = &script_items[0];
544 for (int run_break = 0; run_break < text_length;) { 551 for (size_t run_break = 0; run_break < text_length;) {
545 internal::TextRun* run = new internal::TextRun(); 552 internal::TextRun* run = new internal::TextRun();
546 run->range.set_start(run_break); 553 run->range.set_start(run_break);
547 run->font = GetFont(); 554 run->font = GetFont();
548 run->font_style = style->font_style; 555 run->font_style = (style[BOLD]->second ? Font::BOLD : 0) |
556 (style[ITALIC]->second ? Font::ITALIC : 0);
549 DeriveFontIfNecessary(run->font.GetFontSize(), run->font.GetHeight(), 557 DeriveFontIfNecessary(run->font.GetFontSize(), run->font.GetHeight(),
550 run->font_style, &run->font); 558 run->font_style, &run->font);
551 run->foreground = style->foreground; 559 run->foreground = color->second;
552 run->strike = style->strike; 560 run->strike = style[STRIKE]->second;
553 run->diagonal_strike = style->diagonal_strike; 561 run->diagonal_strike = style[DIAGONAL_STRIKE]->second;
554 run->underline = style->underline; 562 run->underline = style[UNDERLINE]->second;
555 run->script_analysis = script_item->a; 563 run->script_analysis = script_item->a;
556 564
557 // Find the range end and advance the structures as needed. 565 // Find the range end and advance the color and style iterators as needed.
558 const int script_item_end = (script_item + 1)->iCharPos; 566 const size_t script_item_end = (script_item + 1)->iCharPos;
559 const int style_range_end = TextIndexToLayoutIndex(style->range.end()); 567 const size_t color_end = TextIndexToLayoutIndex(
560 run_break = std::min(script_item_end, style_range_end); 568 GetBreakEnd(adjusted_colors, color));
561 if (script_item_end <= style_range_end) 569 run_break = std::min(script_item_end, color_end);
562 script_item++; 570 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) {
563 if (script_item_end >= style_range_end) 571 style_end[i] = TextIndexToLayoutIndex(
564 style++; 572 GetBreakEnd(*adjusted_styles[i], style[i]));
573 run_break = std::min(run_break, style_end[i]);
574 }
575
576 script_item += script_item_end == run_break ? 1 : 0;
577 color += color_end == run_break ? 1 : 0;
578 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i)
579 style[i] += style_end[i] == run_break ? 1 : 0;
580
565 run->range.set_end(run_break); 581 run->range.set_end(run_break);
566 runs_.push_back(run); 582 runs_.push_back(run);
567 } 583 }
568 } 584 }
569 585
570 void RenderTextWin::LayoutVisualText() { 586 void RenderTextWin::LayoutVisualText() {
571 DCHECK(!runs_.empty()); 587 DCHECK(!runs_.empty());
572 588
573 if (!cached_hdc_) 589 if (!cached_hdc_)
574 cached_hdc_ = CreateCompatibleDC(NULL); 590 cached_hdc_ = CreateCompatibleDC(NULL);
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 size_t position = LayoutIndexToTextIndex(run->range.end()); 860 size_t position = LayoutIndexToTextIndex(run->range.end());
845 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); 861 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD);
846 return SelectionModel(position, CURSOR_FORWARD); 862 return SelectionModel(position, CURSOR_FORWARD);
847 } 863 }
848 864
849 RenderText* RenderText::CreateInstance() { 865 RenderText* RenderText::CreateInstance() {
850 return new RenderTextWin; 866 return new RenderTextWin;
851 } 867 }
852 868
853 } // namespace gfx 869 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698