summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authorckocagil@chromium.org <ckocagil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-20 11:41:54 +0000
committerckocagil@chromium.org <ckocagil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-20 11:41:54 +0000
commit7c71dbfb0be07ce82670d9a10d340e87c95d9eff (patch)
treea51376a94d88e4f020d9c56d23d291bfe24eeef8 /ui/gfx
parent312593c8ee84950e079a298f3edeee2298389410 (diff)
downloadchromium_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.h9
-rw-r--r--ui/gfx/render_text_win.cc65
-rw-r--r--ui/gfx/render_text_win.h4
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;