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

Unified Diff: ui/gfx/render_text_linux.cc

Issue 8725002: Draw text via Skia in RenderTextLinux. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 9 years 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.cc ('k') | ui/gfx/render_text_win.cc » ('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 113213)
+++ ui/gfx/render_text_linux.cc (working copy)
@@ -6,10 +6,12 @@
#include <pango/pangocairo.h>
#include <algorithm>
+#include <vector>
#include "base/i18n/break_iterator.h"
#include "base/logging.h"
#include "ui/gfx/canvas_skia.h"
+#include "ui/gfx/font.h"
#include "ui/gfx/pango_util.h"
#include "unicode/uchar.h"
#include "unicode/ustring.h"
@@ -22,6 +24,18 @@
return (c << 8) + c;
}
+// Returns whether the given Pango item is Left to Right.
+bool IsRunLTR(const PangoItem* item) {
+ return (item->analysis.level & 1) == 0;
+}
+
+// Checks whether |range| contains |index|. This is not the same as calling
+// |range.Contains(ui::Range(index))| - as that would return true when
+// |index| == |range.end()|.
+bool IndexInRange(const ui::Range& range, size_t index) {
+ return index >= range.start() && index < range.end();
+}
+
} // namespace
// TODO(xji): index saved in upper layer is utf16 index. Pango uses utf8 index.
@@ -154,7 +168,7 @@
PangoLayoutRun* first_visual_run =
reinterpret_cast<PangoLayoutRun*>(current_line_->runs->data);
PangoItem* item = first_visual_run->item;
- if (item->analysis.level % 2 == 0) { // LTR.
+ if (IsRunLTR(item)) {
xji 2011/12/07 19:52:26 thanks for making those changes.
size_t caret = Utf8IndexToUtf16Index(item->offset);
return SelectionModel(text().length(), caret, SelectionModel::LEADING);
} else { // RTL.
@@ -172,7 +186,7 @@
PangoLayoutRun* last_visual_run = GetLastRun();
if (last_visual_run) {
PangoItem* item = last_visual_run->item;
- if (item->analysis.level % 2 == 0) { // LTR.
+ if (IsRunLTR(item)) {
size_t caret = Utf16IndexOfAdjacentGrapheme(item->offset + item->length,
false);
return SelectionModel(text().length(), caret, SelectionModel::TRAILING);
@@ -260,27 +274,99 @@
}
void RenderTextLinux::DrawVisualText(Canvas* canvas) {
- Rect bounds(display_rect());
+ DCHECK(layout_);
- // Clip the canvas to the text display area.
- SkCanvas* canvas_skia = canvas->GetSkCanvas();
+ Point offset(GetOriginForSkiaDrawing());
+ SkScalar x = SkIntToScalar(offset.x());
+ SkScalar y = SkIntToScalar(offset.y());
- 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);
+ std::vector<SkPoint> pos;
+ std::vector<uint16> glyphs;
- 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_);
+ StyleRanges styles(style_ranges());
+ ApplyCompositionAndSelectionStyles(&styles);
- cairo_restore(cr);
+ // Pre-calculate UTF8 indices from UTF16 indices.
+ // TODO(asvitkine): Can we cache these?
+ std::vector<ui::Range> style_ranges_utf8;
+ style_ranges_utf8.reserve(styles.size());
+ size_t start_index = 0;
+ for (size_t i = 0; i < styles.size(); ++i) {
+ size_t end_index = Utf16IndexToUtf8Index(styles[i].range.end());
+ style_ranges_utf8.push_back(ui::Range(start_index, end_index));
+ start_index = end_index;
+ }
+
+ internal::SkiaTextRenderer renderer(canvas);
+ for (GSList* it = current_line_->runs; it; it = it->next) {
+ PangoLayoutRun* run = reinterpret_cast<PangoLayoutRun*>(it->data);
+ int glyph_count = run->glyphs->num_glyphs;
+ if (glyph_count == 0)
+ continue;
+
+ size_t run_start = run->item->offset;
+ size_t first_glyph_byte_index = run_start + run->glyphs->log_clusters[0];
+ size_t style_increment = IsRunLTR(run->item) ? 1 : -1;
+
+ // Find the initial style for this run.
+ // TODO(asvitkine): Can we avoid looping here, e.g. by caching this per run?
+ int style = -1;
+ for (size_t i = 0; i < style_ranges_utf8.size(); ++i) {
+ if (IndexInRange(style_ranges_utf8[i], first_glyph_byte_index)) {
xji 2011/12/07 19:52:26 Ah, sorry that I just realized does this (using gl
Alexei Svitkine (slow) 2011/12/07 19:59:25 I am not sure how its possible to render a single
xji 2011/12/07 23:17:42 I am not sure about this part. I remember that you
behdad_google 2011/12/07 23:35:05 Yeah, this is broken. That's why I suggested that
xji 2011/12/08 00:27:56 Does pango handle using 2 different foregrounds (n
xji 2011/12/08 00:27:56 'fi' ligature is different. it is one glyph, but 2
behdad_google 2011/12/14 06:29:11 No. Pango doesn't by itself. But if you try sele
+ style = i;
+ break;
+ }
+ }
+ DCHECK_GE(style, 0);
xji 2011/12/07 19:52:26 nit: do you want to dcheck "style < style_ranges.u
Alexei Svitkine (slow) 2011/12/07 19:59:25 It's not possible given the above loop.
xji 2011/12/07 23:17:42 Ah, you right.
+
+ PangoFontDescription* native_font =
+ pango_font_describe(run->item->analysis.font);
+ renderer.SetFont(gfx::Font(native_font));
+ pango_font_description_free(native_font);
+
+ SkScalar glyph_x = x;
+ SkScalar start_x = x;
+ int start = 0;
+
+ glyphs.resize(glyph_count);
+ pos.resize(glyph_count);
+
+ for (int i = 0; i < glyph_count; ++i) {
+ const PangoGlyphInfo& glyph = run->glyphs->glyphs[i];
+ glyphs[i] = static_cast<uint16>(glyph.glyph);
+ pos[i].set(glyph_x + PANGO_PIXELS(glyph.geometry.x_offset),
+ y + PANGO_PIXELS(glyph.geometry.y_offset));
+ glyph_x += PANGO_PIXELS(glyph.geometry.width);
+
+ // If this glyph is beyond the current style, draw the glyphs so far and
+ // advance to the next style.
+ size_t glyph_byte_index = run_start + run->glyphs->log_clusters[i];
+ if (!IndexInRange(style_ranges_utf8[style], glyph_byte_index)) {
xji 2011/12/07 19:52:26 same question for whether glyph's style set works
+ renderer.SetForegroundColor(styles[style].foreground);
+ renderer.DrawPosText(&pos[start], &glyphs[start], i - start);
+ if (styles[style].underline || styles[style].strike) {
+ renderer.DrawDecorations(start_x, y, glyph_x - start_x,
+ styles[style].underline,
+ styles[style].strike);
+ }
+
+ style += style_increment;
+ start = i;
+ start_x = glyph_x;
+ }
+ }
+
+ // Draw the remaining glyphs.
+ renderer.SetForegroundColor(styles[style].foreground);
+ renderer.DrawPosText(&pos[start], &glyphs[start], glyph_count - start);
+ if (styles[style].underline || styles[style].strike) {
+ renderer.DrawDecorations(start_x, y, glyph_x - start_x,
+ styles[style].underline,
+ styles[style].strike);
+ }
+
+ x = glyph_x;
+ }
}
size_t RenderTextLinux::IndexOfAdjacentGrapheme(size_t index, bool next) {
@@ -380,7 +466,7 @@
size_t run_start = Utf8IndexToUtf16Index(item->offset);
size_t run_end = Utf8IndexToUtf16Index(item->offset + item->length);
- if (item->analysis.level % 2 == 0) { // LTR run.
+ if (IsRunLTR(item)) {
if (caret_placement == SelectionModel::TRAILING)
return SelectionModel(caret, caret, SelectionModel::LEADING);
else if (caret > run_start) {
@@ -405,8 +491,8 @@
return LeftEndSelectionModel();
item = prev_run->item;
- return (item->analysis.level % 2) ? FirstSelectionModelInsideRun(item) :
- LastSelectionModelInsideRun(item);
+ return IsRunLTR(item) ? LastSelectionModelInsideRun(item) :
+ FirstSelectionModelInsideRun(item);
}
// Assume caret_pos in |current| is n, 'l' represents leading in
@@ -438,7 +524,7 @@
size_t run_start = Utf8IndexToUtf16Index(item->offset);
size_t run_end = Utf8IndexToUtf16Index(item->offset + item->length);
- if (item->analysis.level % 2 == 0) { // LTR run.
+ if (IsRunLTR(item)) {
if (caret_placement == SelectionModel::LEADING) {
size_t cursor = GetIndexOfNextGrapheme(caret);
return SelectionModel(cursor, caret, SelectionModel::TRAILING);
@@ -462,8 +548,8 @@
return RightEndSelectionModel();
item = reinterpret_cast<PangoLayoutRun*>(next_run->data)->item;
- return (item->analysis.level % 2) ? LastSelectionModelInsideRun(item) :
- FirstSelectionModelInsideRun(item);
+ return IsRunLTR(item) ? FirstSelectionModelInsideRun(item) :
+ LastSelectionModelInsideRun(item);
}
SelectionModel RenderTextLinux::LeftSelectionModelByWord(
@@ -483,7 +569,7 @@
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 (IsRunLTR(item)) {
if (iter.IsStartOfWord(cursor))
return left;
} else { // RTL run.
@@ -512,7 +598,7 @@
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 (IsRunLTR(item)) {
if (iter.IsEndOfWord(cursor))
return right;
} else { // RTL run.
« no previous file with comments | « ui/gfx/render_text.cc ('k') | ui/gfx/render_text_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698