Chromium Code Reviews| Index: ui/gfx/render_text_linux.cc |
| =================================================================== |
| --- ui/gfx/render_text_linux.cc (revision 112983) |
| +++ 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" |
| @@ -260,27 +262,81 @@ |
| } |
| 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(ToViewPoint(Point())); |
| + // TODO(msw): Establish a vertical baseline for strings of mixed font heights. |
| + size_t height = default_style().font.GetHeight(); |
| - 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); |
| + SkScalar x = SkIntToScalar(offset.x()); |
| + SkScalar y = SkIntToScalar(offset.y()); |
| + // Center the text vertically in the display area. |
| + y += (display_rect().height() - height) / 2; |
| + // Offset by the font size to account for Skia expecting y to be the bottom. |
| + y += default_style().font.GetFontSize(); |
|
xji
2011/12/05 23:47:09
The x/y initialization is the same for Win and Lin
Alexei Svitkine (slow)
2011/12/06 22:05:36
I've added a helper function for this.
|
| - 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_); |
| + std::vector<SkPoint> pos; |
| + std::vector<uint16> glyphs; |
| - cairo_restore(cr); |
| + internal::SkiaTextRenderer renderer(canvas); |
| + renderer.Init(); |
| + |
|
xji
2011/12/05 23:47:09
you need to call ApplyCompositionAndSelectionStyle
Alexei Svitkine (slow)
2011/12/06 22:05:36
Done. On the Windows side, this needed to be done
|
| + for (GSList* it = current_line_->runs; it; it = it->next) { |
| + PangoLayoutRun* run = reinterpret_cast<PangoLayoutRun*>(it->data); |
| + size_t run_start = Utf8IndexToUtf16Index(run->item->offset); |
| + |
| + // Find the initial style for this run. |
| + StyleRanges::const_iterator style = style_ranges().begin(); |
| + StyleRanges::const_iterator next = style + 1; |
| + while (next < style_ranges().end() && next->range.start() <= run_start) |
|
msw
2011/12/06 18:40:56
This seems pretty inefficient, can we do better th
Alexei Svitkine (slow)
2011/12/06 19:10:12
I agree this is bad, I've added a TODO for now.
|
| + style = next++; |
| + |
| + int glyph_count = run->glyphs->num_glyphs; |
| + glyphs.resize(glyph_count); |
| + pos.resize(glyph_count); |
| + |
| + 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; |
| + for (int i = 0; i < glyph_count; ++i) { |
| + const PangoGlyphInfo& glyph = run->glyphs->glyphs[i]; |
| + glyphs[i] = static_cast<uint16>(glyph.glyph); |
|
xji
2011/12/05 23:47:09
will cast from uint32 to uint16 cause problem?
Alexei Svitkine (slow)
2011/12/06 19:10:12
See my other comment.
|
| + 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 the last for the current style, draw the glyphs so far |
|
xji
2011/12/05 23:47:09
this glyph is *beyond* the current style.
Alexei Svitkine (slow)
2011/12/06 19:10:12
You're right, I've fixed the comment.
|
| + // and advance the style iterator. |
| + size_t glyph_char_index = run->glyphs->log_clusters[i]; |
| + if (run_start + glyph_char_index >= style->range.end()) { |
|
xji
2011/12/05 23:47:09
glyph_char_index is *byte* index relative to run s
Alexei Svitkine (slow)
2011/12/06 19:10:12
Good catch! Rather than doing the conversion for e
|
| + renderer.SetForegroundColor(style->foreground); |
| + renderer.DrawPosText(&pos[start], &glyphs[start], i - start); |
| + if (style->strike || style->underline) { |
| + renderer.DrawDecorations(start_x, y, glyph_x - start_x, |
| + style->underline, style->strike); |
| + } |
| + |
| + ++style; |
| + start = i; |
| + start_x = glyph_x; |
| + } |
| + } |
| + |
| + // Draw the remaining glyphs. |
| + renderer.SetForegroundColor(style->foreground); |
| + renderer.DrawPosText(&pos[start], &glyphs[start], glyph_count - start); |
| + if (style->strike || style->underline) { |
| + renderer.DrawDecorations(start_x, y, glyph_x - start_x, |
| + style->underline, style->strike); |
| + } |
| + |
| + x = glyph_x; |
|
xji
2011/12/05 23:47:09
Nice mechanism on drawing with styles.
But seems t
Alexei Svitkine (slow)
2011/12/06 22:05:36
Good catch. I've updated the code to hopefully han
|
| + } |
| } |
| size_t RenderTextLinux::IndexOfAdjacentGrapheme(size_t index, bool next) { |