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

Unified Diff: ui/gfx/render_text_linux.cc

Issue 11535014: Replace StyleRange with BreakList; update RenderText, etc. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix RenderTextMac style iteration. Created 7 years, 11 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
« no previous file with comments | « ui/gfx/render_text.cc ('k') | ui/gfx/render_text_mac.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
diff --git a/ui/gfx/render_text_linux.cc b/ui/gfx/render_text_linux.cc
index 3d3cdefa62618e4a5441799c6830cccfa211e468..7afb9f54b40c8f7a01f670e50055acc7fc547d8f 100644
--- a/ui/gfx/render_text_linux.cc
+++ b/ui/gfx/render_text_linux.cc
@@ -325,26 +325,35 @@ void RenderTextLinux::EnsureLayout() {
void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) {
Alexei Svitkine (slow) 2013/01/29 22:07:25 Is it possible to add a test for this function? S
msw 2013/01/31 01:48:54 Done.
PangoAttrList* attrs = pango_attr_list_new();
- int default_font_style = font_list().GetFontStyle();
- for (StyleRanges::const_iterator i = style_ranges().begin();
- i < style_ranges().end(); ++i) {
- // In Pango, different fonts means different runs, and it breaks Arabic
- // shaping across run boundaries. So, set font only when it is different
- // from the default font.
- // 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 (i->font_style != default_font_style) {
- FontList derived_font_list = font_list().DeriveFontList(i->font_style);
+ // Splitting text runs to accommodate styling can break Arabic glyph shaping.
+ // Only split text runs as needed for bold and italic font styles changes.
+ BreakList<bool>::const_iterator bold = styles()[BOLD].breaks().begin();
+ BreakList<bool>::const_iterator italic = styles()[ITALIC].breaks().begin();
+ while (bold != styles()[BOLD].breaks().end() &&
+ italic != styles()[ITALIC].breaks().end()) {
+ const int style = (bold->second ? Font::BOLD : 0) |
+ (italic->second ? Font::ITALIC : 0);
+ const size_t bold_end = TextIndexToLayoutIndex(std::min(text().length(),
Alexei Svitkine (slow) 2013/01/29 22:07:25 Can you add the std::min() logic to style.GetNextB
msw 2013/01/31 01:48:54 I revised BreakList to support a max value. StyleI
+ styles()[BOLD].GetBreakEnd(bold)));
+ const size_t italic_end = TextIndexToLayoutIndex(std::min(text().length(),
+ styles()[ITALIC].GetBreakEnd(italic)));
+ const size_t end = std::min(bold_end, italic_end);
+ if (style != Font::NORMAL) {
Alexei Svitkine (slow) 2013/01/29 22:07:25 Shouldn't you compare it to the style of the font
msw 2013/01/31 01:48:54 Done.
+ FontList derived_font_list = font_list().DeriveFontList(style);
ScopedPangoFontDescription desc(pango_font_description_from_string(
derived_font_list.GetFontDescriptionString().c_str()));
PangoAttribute* pango_attr = pango_attr_font_desc_new(desc.get());
- pango_attr->start_index = TextIndexToLayoutIndex(i->range.start());
- pango_attr->end_index = TextIndexToLayoutIndex(i->range.end());
+ pango_attr->start_index =
+ TextIndexToLayoutIndex(std::max(bold->first, italic->first));
+ pango_attr->end_index = end;
pango_attr_list_insert(attrs, pango_attr);
}
+ bold += bold_end == end ? 1 : 0;
+ italic += italic_end == end ? 1 : 0;
}
+ DCHECK(bold == styles()[BOLD].breaks().end());
+ DCHECK(italic == styles()[ITALIC].breaks().end());
pango_layout_set_attributes(layout, attrs);
pango_attr_list_unref(attrs);
@@ -363,20 +372,6 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
std::vector<SkPoint> pos;
std::vector<uint16> glyphs;
- StyleRanges styles(style_ranges());
- ApplyCompositionAndSelectionStyles(&styles);
-
- // 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 = TextIndexToLayoutIndex(styles[i].range.end());
- style_ranges_utf8.push_back(ui::Range(start_index, end_index));
- start_index = end_index;
- }
-
internal::SkiaTextRenderer renderer(canvas);
ApplyFadeEffects(&renderer);
ApplyTextShadows(&renderer);
@@ -391,27 +386,16 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
render_params.antialiasing,
use_subpixel_rendering && !background_is_transparent());
+ // Temporarily apply composition underlines and selection colors.
+ ApplyCompositionAndSelectionStyles();
+
+ internal::StyleIterator style(colors(), styles());
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 = IsForwardMotion(CURSOR_RIGHT, 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)) {
- style = i;
- break;
- }
- }
- DCHECK_GE(style, 0);
-
ScopedPangoFontDescription desc(
pango_font_describe(run->item->analysis.font));
@@ -429,50 +413,57 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
for (int i = 0; i < glyph_count; ++i) {
const PangoGlyphInfo& glyph = run->glyphs->glyphs[i];
glyphs[i] = static_cast<uint16>(glyph.glyph);
- // Use pango_units_to_double() rather than PANGO_PIXELS() here so that
- // units won't get rounded to the pixel grid if we're using subpixel
- // positioning.
+ // Use pango_units_to_double() rather than PANGO_PIXELS() here so units
+ // are not rounded to the pixel grid if subpixel positioning is enabled.
pos[i].set(glyph_x + pango_units_to_double(glyph.geometry.x_offset),
y + pango_units_to_double(glyph.geometry.y_offset));
- // 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];
- DCHECK_GE(style, 0);
- DCHECK_LT(style, static_cast<int>(styles.size()));
- if (!IndexInRange(style_ranges_utf8[style], glyph_byte_index)) {
+ // Find the end of the current ranged style. If this glyph is beyond the
+ // current style, draw the glyphs so far and advance to the next style.
+ size_t glyph_index = run->item->offset + run->glyphs->log_clusters[i];
+ const size_t style_end_index = TextIndexToLayoutIndex(
+ std::min(text().length(), style.GetNextBreak()));
+ if (glyph_index >= style_end_index) {
// TODO(asvitkine): For cases like "fi", where "fi" is a single glyph
// but can span multiple styles, Pango splits the
// styles evenly over the glyph. We can do this too by
// clipping and drawing the glyph several times.
- renderer.SetForegroundColor(styles[style].foreground);
- renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style);
+ renderer.SetForegroundColor(style.color());
+ const int font_style = (style.style(BOLD) ? Font::BOLD : 0) |
+ (style.style(ITALIC) ? Font::ITALIC : 0);
+ renderer.SetFontFamilyWithStyle(family_name, font_style);
renderer.DrawPosText(&pos[start], &glyphs[start], i - start);
- if (styles[style].underline)
+ if (style.style(UNDERLINE))
SetPangoUnderlineMetrics(desc.get(), &renderer);
- renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]);
+ renderer.DrawDecorations(start_x, y, glyph_x - start_x,
+ style.style(UNDERLINE), style.style(STRIKE),
+ style.style(DIAGONAL_STRIKE));
start = i;
start_x = glyph_x;
- // Loop to find the next style, in case the glyph spans multiple styles.
- do {
- style += style_increment;
- } while (style >= 0 && style < static_cast<int>(styles.size()) &&
- !IndexInRange(style_ranges_utf8[style], glyph_byte_index));
+ style.UpdatePosition(LayoutIndexToTextIndex(style_end_index));
Alexei Svitkine (slow) 2013/01/29 22:07:25 Are you sure that |style_end_index| is correct for
msw 2013/01/31 01:48:54 You are right, my previous patch set was wrong; th
}
glyph_x += pango_units_to_double(glyph.geometry.width);
}
// Draw the remaining glyphs.
- renderer.SetForegroundColor(styles[style].foreground);
- renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style);
+ renderer.SetForegroundColor(style.color());
+ const int font_style = (style.style(BOLD) ? Font::BOLD : 0) |
+ (style.style(ITALIC) ? Font::ITALIC : 0);
+ renderer.SetFontFamilyWithStyle(family_name, font_style);
renderer.DrawPosText(&pos[start], &glyphs[start], glyph_count - start);
- if (styles[style].underline)
+ if (style.style(UNDERLINE))
SetPangoUnderlineMetrics(desc.get(), &renderer);
- renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]);
+ renderer.DrawDecorations(start_x, y, glyph_x - start_x,
+ style.style(UNDERLINE), style.style(STRIKE),
+ style.style(DIAGONAL_STRIKE));
+
x = glyph_x;
}
+
+ // Undo the temporarily applied composition underlines and selection colors.
+ UndoCompositionAndSelectionStyles();
}
GSList* RenderTextLinux::GetRunContainingCaret(
« no previous file with comments | « ui/gfx/render_text.cc ('k') | ui/gfx/render_text_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698