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

Unified Diff: ui/gfx/render_text_linux.cc

Issue 8536047: Separate selection highlight from pango layout (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: address comments Created 9 years, 1 month 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
« no previous file with comments | « ui/gfx/render_text_linux.h ('k') | ui/gfx/render_text_win.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/render_text_linux.cc
===================================================================
--- ui/gfx/render_text_linux.cc (revision 112051)
+++ ui/gfx/render_text_linux.cc (working copy)
@@ -5,7 +5,6 @@
#include "ui/gfx/render_text_linux.h"
#include <pango/pangocairo.h>
-
#include <algorithm>
#include "base/i18n/break_iterator.h"
@@ -58,48 +57,14 @@
}
int RenderTextLinux::GetStringWidth() {
- PangoLayout* layout = EnsureLayout();
+ EnsureLayout();
int width;
- pango_layout_get_pixel_size(layout, &width, NULL);
+ pango_layout_get_pixel_size(layout_, &width, NULL);
return width;
}
-void RenderTextLinux::Draw(Canvas* canvas) {
- PangoLayout* layout = EnsureLayout();
- Rect bounds(display_rect());
-
- // Clip the canvas to the text display area.
- SkCanvas* canvas_skia = canvas->GetSkCanvas();
-
- skia::ScopedPlatformPaint scoped_platform_paint(canvas_skia);
- cairo_t* cr = scoped_platform_paint.GetPlatformSurface();
- cairo_save(cr);
- cairo_rectangle(cr, bounds.x(), bounds.y(), bounds.width(), bounds.height());
- cairo_clip(cr);
-
- int text_width, text_height;
- pango_layout_get_pixel_size(layout, &text_width, &text_height);
- Point offset(ToViewPoint(Point()));
- // Vertically centered.
- int text_y = offset.y() + ((bounds.height() - text_height) / 2);
- // TODO(xji): need to use SkCanvas->drawPosText() for gpu acceleration.
- cairo_move_to(cr, offset.x(), text_y);
- pango_cairo_show_layout(cr, layout);
-
- cairo_restore(cr);
-
- // Paint cursor.
- bounds = GetUpdatedCursorBounds();
- if (cursor_visible() && focused())
- canvas->DrawRectInt(kCursorColor,
- bounds.x(),
- bounds.y(),
- bounds.width(),
- bounds.height());
-}
-
SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) {
- PangoLayout* layout = EnsureLayout();
+ EnsureLayout();
if (text().empty())
return SelectionModel(0, 0, SelectionModel::LEADING);
@@ -113,7 +78,7 @@
return RightEndSelectionModel();
int caret_pos, trailing;
- pango_layout_xy_to_index(layout, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE,
+ pango_layout_xy_to_index(layout_, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE,
&caret_pos, &trailing);
size_t selection_end = caret_pos;
@@ -133,12 +98,12 @@
Rect RenderTextLinux::GetCursorBounds(const SelectionModel& selection,
bool insert_mode) {
- PangoLayout* layout = EnsureLayout();
+ EnsureLayout();
size_t caret_pos = insert_mode ? selection.caret_pos() :
selection.selection_end();
PangoRectangle pos;
- pango_layout_index_to_pos(layout, Utf16IndexToUtf8Index(caret_pos), &pos);
+ pango_layout_index_to_pos(layout_, Utf16IndexToUtf8Index(caret_pos), &pos);
SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
int x = pos.x;
@@ -220,6 +185,33 @@
return SelectionModel(0, 0, SelectionModel::LEADING);
}
+void RenderTextLinux::SetSelectionModel(const SelectionModel& model) {
+ if (GetSelectionStart() != model.selection_start() ||
+ GetCursorPosition() != model.selection_end()) {
+ selection_visual_bounds_.clear();
+ }
+
+ RenderText::SetSelectionModel(model);
+}
+
+void RenderTextLinux::GetSubstringBounds(size_t from,
+ size_t to,
+ std::vector<Rect>* bounds) {
+ DCHECK(from <= text().length());
+ DCHECK(to <= text().length());
+
+ bounds->clear();
+ if (from == to)
+ return;
+
+ EnsureLayout();
+
+ if (from == GetSelectionStart() && to == GetCursorPosition())
+ GetSelectionBounds(bounds);
+ else
+ CalculateSubstringBounds(from, to, bounds);
+}
+
bool RenderTextLinux::IsCursorablePosition(size_t position) {
if (position == 0 && text().empty())
return true;
@@ -233,6 +225,64 @@
ResetLayout();
}
+void RenderTextLinux::EnsureLayout() {
+ if (layout_ == NULL) {
+ CanvasSkia canvas(display_rect().width(), display_rect().height(), false);
+ skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
+ cairo_t* cr = scoped_platform_paint.GetPlatformSurface();
+
+ layout_ = pango_cairo_create_layout(cr);
+ SetupPangoLayout(
+ layout_,
+ text(),
+ default_style().font,
+ display_rect().width(),
+ base::i18n::GetFirstStrongCharacterDirection(text()),
+ CanvasSkia::DefaultCanvasTextAlignment());
+
+ // No width set so that the x-axis position is relative to the start of the
+ // text. ToViewPoint and ToTextPoint take care of the position conversion
+ // between text space and view spaces.
+ pango_layout_set_width(layout_, -1);
+ // TODO(xji): If RenderText will be used for displaying purpose, such as
+ // label, we will need to remove the single-line-mode setting.
+ pango_layout_set_single_paragraph_mode(layout_, true);
+ SetupPangoAttributes(layout_);
+
+ current_line_ = pango_layout_get_line_readonly(layout_, 0);
+ pango_layout_line_ref(current_line_);
+
+ pango_layout_get_log_attrs(layout_, &log_attrs_, &num_log_attrs_);
+
+ layout_text_ = pango_layout_get_text(layout_);
+ layout_text_len_ = strlen(layout_text_);
+ }
+}
+
+void RenderTextLinux::DrawVisualText(Canvas* canvas) {
+ Rect bounds(display_rect());
+
+ // Clip the canvas to the text display area.
+ SkCanvas* canvas_skia = canvas->GetSkCanvas();
+
+ skia::ScopedPlatformPaint scoped_platform_paint(canvas_skia);
+ cairo_t* cr = scoped_platform_paint.GetPlatformSurface();
+ cairo_save(cr);
+ cairo_rectangle(cr, bounds.x(), bounds.y(), bounds.width(), bounds.height());
+ cairo_clip(cr);
+
+ int text_width, text_height;
+ pango_layout_get_pixel_size(layout_, &text_width, &text_height);
+ Point offset(ToViewPoint(Point()));
+ // Vertically centered.
+ int text_y = offset.y() + ((bounds.height() - text_height) / 2);
+ // TODO(xji): need to use SkCanvas->drawPosText() for gpu acceleration.
+ cairo_move_to(cr, offset.x(), text_y);
+ pango_cairo_show_layout(cr, layout_);
+
+ cairo_restore(cr);
+}
+
size_t RenderTextLinux::IndexOfAdjacentGrapheme(size_t index, bool next) {
EnsureLayout();
return Utf16IndexOfAdjacentGrapheme(Utf16IndexToUtf8Index(index), next);
@@ -474,41 +524,6 @@
return right_end;
}
-PangoLayout* RenderTextLinux::EnsureLayout() {
- if (layout_ == NULL) {
- CanvasSkia canvas(display_rect().width(), display_rect().height(), false);
- skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
- cairo_t* cr = scoped_platform_paint.GetPlatformSurface();
-
- layout_ = pango_cairo_create_layout(cr);
- SetupPangoLayout(
- layout_,
- text(),
- default_style().font,
- display_rect().width(),
- base::i18n::GetFirstStrongCharacterDirection(text()),
- CanvasSkia::DefaultCanvasTextAlignment());
-
- // No width set so that the x-axis position is relative to the start of the
- // text. ToViewPoint and ToTextPoint take care of the position conversion
- // between text space and view spaces.
- pango_layout_set_width(layout_, -1);
- // TODO(xji): If RenderText will be used for displaying purpose, such as
- // label, we will need to remove the single-line-mode setting.
- pango_layout_set_single_paragraph_mode(layout_, true);
- SetupPangoAttributes(layout_);
-
- current_line_ = pango_layout_get_line_readonly(layout_, 0);
- pango_layout_line_ref(current_line_);
-
- pango_layout_get_log_attrs(layout_, &log_attrs_, &num_log_attrs_);
-
- layout_text_ = pango_layout_get_text(layout_);
- layout_text_len_ = strlen(layout_text_);
- }
- return layout_;
-}
-
void RenderTextLinux::ResetLayout() {
// set_cached_bounds_and_offset_valid(false) is done in RenderText for every
// operation that triggers ResetLayout().
@@ -525,44 +540,25 @@
log_attrs_ = NULL;
num_log_attrs_ = 0;
}
+ if (!selection_visual_bounds_.empty())
+ selection_visual_bounds_.clear();
layout_text_ = NULL;
layout_text_len_ = 0;
}
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());
- size_t end = std::min(MaxOfSelection(), text().length());
- PangoAttribute* pango_attr;
- if (end > start) {
- pango_attr = pango_attr_background_new(
- ConvertColorFrom8BitTo16Bit(SkColorGetR(selection_color)),
- ConvertColorFrom8BitTo16Bit(SkColorGetG(selection_color)),
- ConvertColorFrom8BitTo16Bit(SkColorGetB(selection_color)));
- AppendPangoAttribute(start, end, pango_attr, attrs);
- }
StyleRanges ranges_of_style(style_ranges());
ApplyCompositionAndSelectionStyles(&ranges_of_style);
PlatformFont* default_platform_font = default_style().font.platform_font();
+ PangoAttribute* pango_attr;
for (StyleRanges::const_iterator i = ranges_of_style.begin();
i < ranges_of_style.end(); ++i) {
- start = std::min(i->range.start(), text().length());
- end = std::min(i->range.end(), text().length());
+ size_t start = std::min(i->range.start(), text().length());
+ size_t end = std::min(i->range.end(), text().length());
if (start >= end)
continue;
@@ -657,4 +653,40 @@
return utf16_index;
}
+void RenderTextLinux::CalculateSubstringBounds(size_t from,
+ size_t to,
+ std::vector<Rect>* bounds) {
+ int* ranges;
+ int n_ranges;
+ size_t from_in_utf8 = Utf16IndexToUtf8Index(from);
+ size_t to_in_utf8 = Utf16IndexToUtf8Index(to);
+ pango_layout_line_get_x_ranges(
+ current_line_,
+ std::min(from_in_utf8, to_in_utf8),
+ std::max(from_in_utf8, to_in_utf8),
+ &ranges,
+ &n_ranges);
+
+ int height;
+ pango_layout_get_pixel_size(layout_, NULL, &height);
+
+ int y = (display_rect().height() - height) / 2;
+
+ for (int i = 0; i < n_ranges; ++i) {
+ int x = PANGO_PIXELS(ranges[2 * i]);
+ int width = PANGO_PIXELS(ranges[2 * i + 1]) - x;
+ Rect rect(x, y, width, height);
+ rect.set_origin(ToViewPoint(rect.origin()));
+ bounds->push_back(rect);
+ }
+ g_free(ranges);
+}
+
+void RenderTextLinux::GetSelectionBounds(std::vector<Rect>* bounds) {
+ if (selection_visual_bounds_.empty())
+ CalculateSubstringBounds(GetSelectionStart(), GetCursorPosition(),
+ &selection_visual_bounds_);
+ *bounds = selection_visual_bounds_;
+}
+
} // namespace gfx
« no previous file with comments | « ui/gfx/render_text_linux.h ('k') | ui/gfx/render_text_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698