Chromium Code Reviews| Index: ui/gfx/render_text_linux.cc |
| =================================================================== |
| --- ui/gfx/render_text_linux.cc (revision 100777) |
| +++ ui/gfx/render_text_linux.cc (working copy) |
| @@ -8,6 +8,7 @@ |
| #include <algorithm> |
| +#include "base/i18n/break_iterator.h" |
| #include "base/logging.h" |
| #include "ui/gfx/canvas_skia.h" |
| #include "ui/gfx/pango_util.h" |
| @@ -184,8 +185,7 @@ |
| return LeftEndSelectionModel(); |
| if (break_type == CHARACTER_BREAK) |
| return LeftSelectionModel(current); |
| - // TODO(xji): not implemented yet. |
| - return RenderText::GetLeftSelectionModel(current, break_type); |
| + return LeftSelectionModelByWord(current); |
|
msw
2011/09/15 01:26:00
DCHECK(break_type == WORD_BREAK); before this to e
xji
2011/09/15 22:58:09
Done.
|
| } |
| SelectionModel RenderTextLinux::GetRightSelectionModel( |
| @@ -197,8 +197,7 @@ |
| return RightEndSelectionModel(); |
| if (break_type == CHARACTER_BREAK) |
| return RightSelectionModel(current); |
| - // TODO(xji): not implemented yet. |
| - return RenderText::GetRightSelectionModel(current, break_type); |
| + return RightSelectionModelByWord(current); |
| } |
| SelectionModel RenderTextLinux::LeftEndSelectionModel() { |
| @@ -428,6 +427,64 @@ |
| FirstSelectionModelInsideRun(item); |
| } |
| +SelectionModel RenderTextLinux::LeftSelectionModelByWord( |
| + const SelectionModel& selection) { |
| + base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
| + bool success = iter.Init(); |
| + DCHECK(success); |
| + if (!success) |
| + return selection; |
| + |
| + SelectionModel left_end = LeftEndSelectionModel(); |
| + SelectionModel left(selection); |
| + while (!left.Equals(left_end)) { |
| + left = LeftSelectionModel(left); |
| + size_t caret = left.caret_pos(); |
| + GSList* run = GetRunContainingPosition(caret); |
| + DCHECK(run); |
| + PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; |
| + size_t cursor = left.selection_end(); |
| + if (item->analysis.level % 2 == 0) { // LTR run. |
| + if (iter.IsStartOfWord(cursor)) |
| + return left; |
| + } else { // RTL run. |
| + if (iter.IsEndOfWord(cursor)) |
| + return left; |
| + } |
| + } |
| + |
| + return left_end; |
| +} |
| + |
| +SelectionModel RenderTextLinux::RightSelectionModelByWord( |
| + const SelectionModel& selection) { |
| + base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
| + bool success = iter.Init(); |
| + DCHECK(success); |
| + if (!success) |
| + return selection; |
| + |
| + SelectionModel right_end = RightEndSelectionModel(); |
| + SelectionModel right(selection); |
| + while (!right.Equals(right_end)) { |
| + right = RightSelectionModel(right); |
| + size_t caret = right.caret_pos(); |
| + GSList* run = GetRunContainingPosition(caret); |
| + DCHECK(run); |
| + PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; |
| + size_t cursor = right.selection_end(); |
| + if (item->analysis.level % 2 == 0) { // LTR run. |
| + if (iter.IsEndOfWord(cursor)) |
| + return right; |
| + } else { // RTL run. |
| + if (iter.IsStartOfWord(cursor)) |
| + return right; |
| + } |
| + } |
| + |
| + return right_end; |
| +} |
| + |
| PangoLayout* RenderTextLinux::EnsureLayout() { |
| if (layout_ == NULL) { |
| CanvasSkia canvas(display_rect().width(), display_rect().height(), false); |
| @@ -486,6 +543,15 @@ |
| void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) { |
| PangoAttrList* attrs = pango_attr_list_new(); |
| // Set selection background color. |
| + // TODO(xji): There's a bug in pango that it can't use two colors in one |
| + // glyph. Please refer to https://bugzilla.gnome.org/show_bug.cgi?id=648157 |
| + // for detail. So for example, if a font has "ffi" ligature, but you select |
| + // half of that glyph, you either get the entire "ffi" ligature |
| + // selection-colored, or none of it. |
| + // We could use clipping to render selection. |
| + // Use pango_glyph_item_get_logical_widths to find the exact boundaries of |
| + // selection, then cairo_clip that, paint background, set color to white and |
| + // redraw the layout. |
| SkColor selection_color = |
| focused() ? kFocusedSelectionColor : kUnfocusedSelectionColor; |
| size_t start = std::min(MinOfSelection(), text().length()); |
| @@ -502,6 +568,8 @@ |
| StyleRanges ranges_of_style(style_ranges()); |
| ApplyCompositionAndSelectionStyles(&ranges_of_style); |
| + PlatformFont* default_platform_font = default_style().font.platform_font(); |
| + |
| for (StyleRanges::const_iterator i = ranges_of_style.begin(); |
| i < ranges_of_style.end(); ++i) { |
| start = std::min(i->range.start(), text().length()); |
| @@ -509,13 +577,21 @@ |
| if (start >= end) |
| continue; |
| - const Font& font = !i->underline ? i->font : |
| - i->font.DeriveFont(0, i->font.GetStyle() | Font::UNDERLINED); |
| - PangoFontDescription* desc = font.GetNativeFont(); |
| - pango_attr = pango_attr_font_desc_new(desc); |
| - AppendPangoAttribute(start, end, pango_attr, attrs); |
| - pango_font_description_free(desc); |
| + const Font& font = i->font; |
| + if (font.platform_font() != default_platform_font) { |
|
msw
2011/09/15 01:26:00
I want to make sure this is correct. If you don't
xji
2011/09/15 22:58:09
Yes.
|
| + // In pango, different fonts means different runs, and it breaks Arabic |
|
msw
2011/09/15 01:26:00
Capitalize Pango?, also this comment probably belo
xji
2011/09/15 22:58:09
Done.
|
| + // shaping acorss run boundaries. So, set font to the largest range. |
| + PangoFontDescription* desc = font.GetNativeFont(); |
| + pango_attr = pango_attr_font_desc_new(desc); |
| + AppendPangoAttribute(start, end, pango_attr, attrs); |
| + pango_font_description_free(desc); |
| + } |
| + if (i->underline) { |
| + pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); |
| + AppendPangoAttribute(start, end, pango_attr, attrs); |
| + } |
| + |
| SkColor foreground = i->foreground; |
| pango_attr = pango_attr_foreground_new( |
| ConvertColorFrom8BitTo16Bit(SkColorGetR(foreground)), |
| @@ -542,6 +618,7 @@ |
| pango_attr_list_insert(attrs, pango_attr); |
| } |
| +// TODO(xji): keep a vector of runs to avoid use single-linked list. |
|
msw
2011/09/15 01:26:00
Nits: "*K*eep", "us*ing*", "singl*y*" and "list*s*
xji
2011/09/15 22:58:09
done except "lists", it is one list.
msw
2011/09/17 00:27:10
Technically that's grammatically incorrect, you'll
|
| PangoLayoutRun* RenderTextLinux::GetPreviousRun(PangoLayoutRun* run) const { |
| GSList* current = current_line_->runs; |
| GSList* prev = NULL; |