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

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: fix lint error 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,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;

Powered by Google App Engine
This is Rietveld 408576698