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

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: Update iteration and helpers; add tests; etc. Created 7 years, 10 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 // Temporarily apply composition underlines and selection colors.
539 // TODO(msw): Only break for font changes, not color etc. See TextRun comment. 530 ApplyCompositionAndSelectionStyles();
540 StyleRanges styles(style_ranges()); 531
541 ApplyCompositionAndSelectionStyles(&styles); 532 // Build the list of runs from the script items and ranged colors/styles.
542 StyleRanges::const_iterator style = styles.begin(); 533 // TODO(msw): Only break for bold/italic, not color etc. See TextRun comment.
534 internal::StyleIterator style(colors(), styles());
543 SCRIPT_ITEM* script_item = &script_items[0]; 535 SCRIPT_ITEM* script_item = &script_items[0];
544 for (int run_break = 0; run_break < text_length;) { 536 for (size_t run_break = 0; run_break < text_length;) {
545 internal::TextRun* run = new internal::TextRun(); 537 internal::TextRun* run = new internal::TextRun();
546 run->range.set_start(run_break); 538 run->range.set_start(run_break);
547 run->font = GetFont(); 539 run->font = GetFont();
548 run->font_style = style->font_style; 540 run->font_style = (style.style(BOLD) ? Font::BOLD : 0) |
541 (style.style(ITALIC) ? Font::ITALIC : 0);
549 DeriveFontIfNecessary(run->font.GetFontSize(), run->font.GetHeight(), 542 DeriveFontIfNecessary(run->font.GetFontSize(), run->font.GetHeight(),
550 run->font_style, &run->font); 543 run->font_style, &run->font);
551 run->foreground = style->foreground; 544 run->foreground = style.color();
552 run->strike = style->strike; 545 run->strike = style.style(STRIKE);
553 run->diagonal_strike = style->diagonal_strike; 546 run->diagonal_strike = style.style(DIAGONAL_STRIKE);
554 run->underline = style->underline; 547 run->underline = style.style(UNDERLINE);
555 run->script_analysis = script_item->a; 548 run->script_analysis = script_item->a;
556 549
557 // Find the range end and advance the structures as needed. 550 // Find the next break and advance the iterators as needed.
558 const int script_item_end = (script_item + 1)->iCharPos; 551 const size_t script_item_break = (script_item + 1)->iCharPos;
559 const int style_range_end = TextIndexToLayoutIndex(style->range.end()); 552 run_break = std::min(script_item_break,
560 run_break = std::min(script_item_end, style_range_end); 553 TextIndexToLayoutIndex(style.GetRange().end()));
Alexei Svitkine (slow) 2013/01/31 16:33:34 Is this really right? Reading the text/layout ind
msw 2013/01/31 20:27:39 The old/new code seems wrong as you say; I'll use
561 if (script_item_end <= style_range_end) 554 style.UpdatePosition(LayoutIndexToTextIndex(run_break));
555 if (script_item_break == run_break)
562 script_item++; 556 script_item++;
563 if (script_item_end >= style_range_end)
564 style++;
565 run->range.set_end(run_break); 557 run->range.set_end(run_break);
566 runs_.push_back(run); 558 runs_.push_back(run);
567 } 559 }
560
561 // Undo the temporarily applied composition underlines and selection colors.
562 UndoCompositionAndSelectionStyles();
568 } 563 }
569 564
570 void RenderTextWin::LayoutVisualText() { 565 void RenderTextWin::LayoutVisualText() {
571 DCHECK(!runs_.empty()); 566 DCHECK(!runs_.empty());
572 567
573 if (!cached_hdc_) 568 if (!cached_hdc_)
574 cached_hdc_ = CreateCompatibleDC(NULL); 569 cached_hdc_ = CreateCompatibleDC(NULL);
575 570
576 HRESULT hr = E_FAIL; 571 HRESULT hr = E_FAIL;
577 string_size_.set_height(0); 572 string_size_.set_height(0);
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 size_t position = LayoutIndexToTextIndex(run->range.end()); 839 size_t position = LayoutIndexToTextIndex(run->range.end());
845 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD); 840 position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD);
846 return SelectionModel(position, CURSOR_FORWARD); 841 return SelectionModel(position, CURSOR_FORWARD);
847 } 842 }
848 843
849 RenderText* RenderText::CreateInstance() { 844 RenderText* RenderText::CreateInstance() {
850 return new RenderTextWin; 845 return new RenderTextWin;
851 } 846 }
852 847
853 } // namespace gfx 848 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698