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

Unified Diff: ui/gfx/render_text_linux.cc

Issue 7892044: Implement move by word, fix rendering of Arabic shape joining (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: address comment Created 9 years, 3 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 side-by-side diff with in-line comments
Download patch
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,8 @@
return LeftEndSelectionModel();
if (break_type == CHARACTER_BREAK)
return LeftSelectionModel(current);
- // TODO(xji): not implemented yet.
- return RenderText::GetLeftSelectionModel(current, break_type);
+ DCHECK(break_type == WORD_BREAK);
+ return LeftSelectionModelByWord(current);
}
SelectionModel RenderTextLinux::GetRightSelectionModel(
@@ -197,8 +198,8 @@
return RightEndSelectionModel();
if (break_type == CHARACTER_BREAK)
return RightSelectionModel(current);
- // TODO(xji): not implemented yet.
- return RenderText::GetRightSelectionModel(current, break_type);
+ DCHECK(break_type == WORD_BREAK);
+ return RightSelectionModelByWord(current);
}
SelectionModel RenderTextLinux::LeftEndSelectionModel() {
@@ -428,6 +429,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 +545,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 +570,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,12 +579,19 @@
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;
+ // In Pango, different fonts means different runs, and it breaks Arabic
+ // shaping acorss run boundaries. So, set font only when it is different
+ // from the default faont.
+ // TODO(xji): we'll eventually need to split up StyleRange into components
+ // (ColorRange, FontRange, etc.) so that we can combine adjacent ranges
+ // with the same Fonts (to avoid unnecessarily splitting up runs)
+ if (font.platform_font() != default_platform_font) {
+ PangoFontDescription* desc = font.GetNativeFont();
+ pango_attr = pango_attr_font_desc_new(desc);
+ AppendPangoAttribute(start, end, pango_attr, attrs);
+ pango_font_description_free(desc);
+ }
SkColor foreground = i->foreground;
pango_attr = pango_attr_foreground_new(
@@ -523,6 +600,11 @@
ConvertColorFrom8BitTo16Bit(SkColorGetB(foreground)));
AppendPangoAttribute(start, end, pango_attr, attrs);
+ if (i->underline) {
+ pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
+ AppendPangoAttribute(start, end, pango_attr, attrs);
+ }
+
if (i->strike) {
pango_attr = pango_attr_strikethrough_new(true);
AppendPangoAttribute(start, end, pango_attr, attrs);
@@ -542,6 +624,7 @@
pango_attr_list_insert(attrs, pango_attr);
}
+// TODO(xji): Keep a vector of runs to avoid using singly-linked list.
PangoLayoutRun* RenderTextLinux::GetPreviousRun(PangoLayoutRun* run) const {
GSList* current = current_line_->runs;
GSList* prev = NULL;

Powered by Google App Engine
This is Rietveld 408576698