diff options
author | ckocagil@chromium.org <ckocagil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-20 11:41:54 +0000 |
---|---|---|
committer | ckocagil@chromium.org <ckocagil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-20 11:41:54 +0000 |
commit | 7c71dbfb0be07ce82670d9a10d340e87c95d9eff (patch) | |
tree | a51376a94d88e4f020d9c56d23d291bfe24eeef8 /ui/gfx | |
parent | 312593c8ee84950e079a298f3edeee2298389410 (diff) | |
download | chromium_src-7c71dbfb0be07ce82670d9a10d340e87c95d9eff.zip chromium_src-7c71dbfb0be07ce82670d9a10d340e87c95d9eff.tar.gz chromium_src-7c71dbfb0be07ce82670d9a10d340e87c95d9eff.tar.bz2 |
Colors shouldn't break runs and should be handled while drawing the text
BUG=262119,256908
TEST=In a views textfield, selecting half of a ligature shouldn't break the ligature. See http://www.catch22.net/tuts/uniscribe-mysteries in Firefox to see a example of how it used to look versus how it is supposed to look.
TBR=asvitkine@chromium.org
Review URL: https://chromiumcodereview.appspot.com/19672006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@212778 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r-- | ui/gfx/break_list.h | 9 | ||||
-rw-r--r-- | ui/gfx/render_text_win.cc | 65 | ||||
-rw-r--r-- | ui/gfx/render_text_win.h | 4 |
3 files changed, 56 insertions, 22 deletions
diff --git a/ui/gfx/break_list.h b/ui/gfx/break_list.h index c380222..770386e 100644 --- a/ui/gfx/break_list.h +++ b/ui/gfx/break_list.h @@ -47,6 +47,7 @@ class BreakList { // Get the break applicable to |position| (at or preceeding |position|). typename std::vector<Break>::iterator GetBreak(size_t position); + typename std::vector<Break>::const_iterator GetBreak(size_t position) const; // Get the range of the supplied break; returns the break's start position and // the next break's start position (or |max_| for the terminal break). @@ -126,6 +127,14 @@ typename std::vector<std::pair<size_t, T> >::iterator BreakList<T>::GetBreak( } template<class T> +typename std::vector<std::pair<size_t, T> >::const_iterator + BreakList<T>::GetBreak(size_t position) const { + typename std::vector<Break>::const_iterator i = breaks_.end() - 1; + for (; i != breaks_.begin() && i->first > position; --i); + return i; +} + +template<class T> ui::Range BreakList<T>::GetRange( const typename BreakList<T>::const_iterator& i) const { const typename BreakList<T>::const_iterator next = i + 1; diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc index 05be785..1047768 100644 --- a/ui/gfx/render_text_win.cc +++ b/ui/gfx/render_text_win.cc @@ -129,13 +129,30 @@ bool IsUnicodeBidiControlCharacter(char16 c) { c == base::i18n::kRightToLeftOverride; } +// Returns the corresponding glyph range of the given character range. +ui::Range CharRangeToGlyphRange(const internal::TextRun& run, + const ui::Range& range) { + DCHECK(run.range.Contains(ui::Range(range.start() + run.range.start(), + range.end() + run.range.start()))); + DCHECK(!range.is_reversed()); + DCHECK(!range.is_empty()); + if (run.script_analysis.fRTL) { + return ui::Range(run.logical_clusters[range.end() - 1], + range.start() > 0 ? run.logical_clusters[range.start() - 1] + : run.glyph_count); + } else { + return ui::Range(run.logical_clusters[range.start()], + range.end() < run.range.length() ? run.logical_clusters[range.end()] + : run.glyph_count); + } +} + } // namespace namespace internal { TextRun::TextRun() - : foreground(0), - font_style(0), + : font_style(0), strike(false), diagonal_strike(false), underline(false), @@ -340,14 +357,6 @@ SelectionModel RenderTextWin::AdjacentWordSelectionModel( return SelectionModel(pos, CURSOR_FORWARD); } -void RenderTextWin::SetSelectionModel(const SelectionModel& model) { - RenderText::SetSelectionModel(model); - // TODO(xji|msw): The text selection color is applied in ItemizeLogicalText(). - // So, the layout must be updated in order to draw the proper selection range. - // Colors should be applied in DrawVisualText(), as done by RenderTextLinux. - ResetLayout(); -} - ui::Range RenderTextWin::GetGlyphBounds(size_t index) { const size_t run_index = GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD)); @@ -459,6 +468,8 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) { renderer.SetFontSmoothingSettings( smoothing_enabled, cleartype_enabled && !background_is_transparent()); + ApplyCompositionAndSelectionStyles(); + for (size_t i = 0; i < runs_.size(); ++i) { // Get the run specified by the visual-to-logical map. internal::TextRun* run = runs_[visual_to_logical_[i]]; @@ -477,13 +488,30 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) { renderer.SetTextSize(run->font.GetFontSize()); renderer.SetFontFamilyWithStyle(run->font.GetFontName(), run->font_style); - renderer.SetForegroundColor(run->foreground); - renderer.DrawPosText(&pos[0], run->glyphs.get(), run->glyph_count); - renderer.DrawDecorations(x, y, run->width, run->underline, run->strike, - run->diagonal_strike); + + for (BreakList<SkColor>::const_iterator it = + colors().GetBreak(run->range.start()); + it != colors().breaks().end() && it->first < run->range.end(); + ++it) { + ui::Range intersection = colors().GetRange(it).Intersect(run->range); + ui::Range glyphs = CharRangeToGlyphRange(*run, + ui::Range(intersection.start() - run->range.start(), + intersection.end() - run->range.start())); + renderer.SetForegroundColor(it->second); + renderer.DrawPosText(&pos[glyphs.start()], &run->glyphs[glyphs.start()], + glyphs.length()); + SkScalar width = (static_cast<int>(glyphs.end()) < run->glyph_count ? + pos[glyphs.end()].x() : pos[0].x() + SkIntToScalar(run->width)) + - pos[glyphs.start()].x(); + renderer.DrawDecorations(pos[glyphs.start()].x(), y, + SkScalarCeilToInt(width), run->underline, + run->strike, run->diagonal_strike); + } x = glyph_x; } + + UndoCompositionAndSelectionStyles(); } void RenderTextWin::ItemizeLogicalText() { @@ -520,9 +548,11 @@ void RenderTextWin::ItemizeLogicalText() { // Temporarily apply composition underlines and selection colors. ApplyCompositionAndSelectionStyles(); - // Build the list of runs from the script items and ranged colors/styles. - // TODO(msw): Only break for bold/italic, not color etc. See TextRun comment. - internal::StyleIterator style(colors(), styles()); + // Build the list of runs from the script items and ranged styles. Use an + // empty color BreakList to avoid breaking runs at color boundaries. + BreakList<SkColor> empty_colors; + empty_colors.SetMax(text().length()); + internal::StyleIterator style(empty_colors, styles()); SCRIPT_ITEM* script_item = &script_items[0]; const size_t max_run_length = kMaxGlyphs / 2; for (size_t run_break = 0; run_break < layout_text_length;) { @@ -533,7 +563,6 @@ void RenderTextWin::ItemizeLogicalText() { (style.style(ITALIC) ? Font::ITALIC : 0); DeriveFontIfNecessary(run->font.GetFontSize(), run->font.GetHeight(), run->font_style, &run->font); - run->foreground = style.color(); run->strike = style.style(STRIKE); run->diagonal_strike = style.style(DIAGONAL_STRIKE); run->underline = style.style(UNDERLINE); diff --git a/ui/gfx/render_text_win.h b/ui/gfx/render_text_win.h index 704829d..07f7e75 100644 --- a/ui/gfx/render_text_win.h +++ b/ui/gfx/render_text_win.h @@ -30,9 +30,6 @@ struct TextRun { // |font.DeriveFont()|, which is expensive on Windows. int font_style; - // TODO(msw): Disambiguate color/style from TextRuns for proper glyph shaping. - // See an example: http://www.catch22.net/tuts/uniscribe-mysteries - SkColor foreground; bool strike; bool diagonal_strike; bool underline; @@ -79,7 +76,6 @@ class RenderTextWin : public RenderText { virtual SelectionModel AdjacentWordSelectionModel( const SelectionModel& selection, VisualCursorDirection direction) OVERRIDE; - virtual void SetSelectionModel(const SelectionModel& model) OVERRIDE; virtual ui::Range GetGlyphBounds(size_t index) OVERRIDE; virtual std::vector<Rect> GetSubstringBounds(const ui::Range& range) OVERRIDE; virtual size_t TextIndexToLayoutIndex(size_t index) const OVERRIDE; |