| Index: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
|
| ===================================================================
|
| --- chrome/browser/ui/views/omnibox/omnibox_result_view.cc (revision 147896)
|
| +++ chrome/browser/ui/views/omnibox/omnibox_result_view.cc (working copy)
|
| @@ -14,6 +14,7 @@
|
| #include <algorithm> // NOLINT
|
|
|
| #include "base/i18n/bidi_line_iterator.h"
|
| +#include "base/memory/scoped_vector.h"
|
| #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
|
| #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
|
| #include "chrome/browser/ui/views/omnibox/omnibox_result_view_model.h"
|
| @@ -25,6 +26,7 @@
|
| #include "ui/base/text/text_elider.h"
|
| #include "ui/gfx/canvas.h"
|
| #include "ui/gfx/color_utils.h"
|
| +#include "ui/gfx/render_text.h"
|
|
|
| namespace {
|
|
|
| @@ -47,6 +49,7 @@
|
| const gfx::Font* font;
|
| SkColor color;
|
| gfx::Size pixel_size;
|
| + gfx::RenderText* render_text; // Weak.
|
| };
|
|
|
| // Precalculated data used to draw a complete visual run within the match.
|
| @@ -339,6 +342,7 @@
|
| if (!bidi_line.Open(text, base::i18n::IsRTL(), is_url))
|
| return x;
|
| const int num_runs = bidi_line.CountRuns();
|
| + ScopedVector<gfx::RenderText> render_texts;
|
| Runs runs;
|
| for (int run = 0; run < num_runs; ++run) {
|
| int run_start_int = 0, run_length_int = 0;
|
| @@ -389,12 +393,21 @@
|
| current_data->color = GetColor(state, DIMMED_TEXT);
|
| else
|
| current_data->color = GetColor(state, force_dim ? DIMMED_TEXT : TEXT);
|
| - int width = 0;
|
| - int height = 0;
|
| - gfx::Canvas::SizeStringInt(current_data->text, *current_data->font,
|
| - &width, &height, gfx::Canvas::NO_ELLIPSIS);
|
| - current_data->pixel_size = gfx::Size(width, height);
|
| - current_run->pixel_width += width;
|
| +
|
| + render_texts.push_back(gfx::RenderText::CreateInstance());
|
| + current_data->render_text = render_texts.back();
|
| + current_data->render_text->SetFontList(
|
| + gfx::FontList(*current_data->font));
|
| + current_data->render_text->SetText(current_data->text);
|
| +
|
| + gfx::StyleRange style_range;
|
| + style_range.foreground = current_data->color;
|
| + style_range.font_style = current_data->font->GetStyle();
|
| + current_data->render_text->set_default_style(style_range);
|
| + current_data->render_text->ApplyDefaultStyle();
|
| +
|
| + current_data->pixel_size = current_data->render_text->GetStringSize();
|
| + current_run->pixel_width += current_data->pixel_size.width();
|
| }
|
| DCHECK(!current_run->classifications.empty());
|
| }
|
| @@ -440,37 +453,18 @@
|
| // Draw the runs.
|
| for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
|
| const bool reverse_visible_order = (i->is_rtl != base::i18n::IsRTL());
|
| - int flags = gfx::Canvas::NO_ELLIPSIS; // We've already elided.
|
| - if (reverse_visible_order) {
|
| + if (reverse_visible_order)
|
| std::reverse(i->classifications.begin(), i->classifications.end());
|
| - if (i->is_rtl)
|
| - flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
|
| - }
|
| for (Classifications::const_iterator j(i->classifications.begin());
|
| j != i->classifications.end(); ++j) {
|
| const int left =
|
| mirroring_context_->mirrored_left_coord(x, x + j->pixel_size.width());
|
| - // By passing the same y-coordinate for each run, we vertically align the
|
| - // tops of successive runs. This isn't actually what we want; we want to
|
| - // align the baselines, but Canvas doesn't currently expose text
|
| - // measurement APIs sufficient to make that happen. The problem here is
|
| - // font substitution: if no fonts are substituted, then all runs have the
|
| - // same font (in bold or normal styles), and thus the same height and same
|
| - // baseline. If fonts are substituted within a run, the characters are
|
| - // baseline-aligned within the run, but using the same top coordinate as
|
| - // for other runs is only correct if the overall ascent for this run is
|
| - // the same as for other runs -- that is, if the tallest ascent of all
|
| - // fonts in the run is equal to the ascent of the normal font. If this
|
| - // condition doesn't hold, the baseline for this run will be drawn too
|
| - // high or too low, depending on whether the run's tallest ascent is
|
| - // shorter or higher than the normal font's ascent, respectively.
|
| - //
|
| - // TODO(asvitkine): Fix this by replacing the SizeStringInt() calls
|
| - // elsewhere in this file with calls that can calculate actual baselines
|
| - // even in the face of font fallback. Tracked as: http://crbug.com/128027
|
| - canvas->DrawStringInt(j->text, *j->font, j->color, left, y,
|
| - j->pixel_size.width(), j->pixel_size.height(),
|
| - flags);
|
| + // Align the text runs to a common baseline.
|
| + const int top =
|
| + y + normal_font_.GetBaseline() - j->render_text->GetBaseline();
|
| + gfx::Rect rect(left, top, j->pixel_size.width(), j->pixel_size.height());
|
| + j->render_text->SetDisplayRect(rect);
|
| + j->render_text->Draw(canvas);
|
| x += j->pixel_size.width();
|
| }
|
| }
|
| @@ -499,6 +493,7 @@
|
| // an ellipsis, since there isn't enough room to draw it after this
|
| // classification.
|
| j->text += kEllipsis;
|
| + j->render_text->SetText(j->text);
|
|
|
| // We also add this classification's width (sans ellipsis) back to the
|
| // available width since we want to consider the available space we'll
|
| @@ -533,16 +528,15 @@
|
| // If we could only fit an ellipsis, then only make it bold if there was
|
| // an immediate prior classification in this run that was also bold, or
|
| // it will look orphaned.
|
| - if ((elided_text.length() == 1) &&
|
| + if ((j->font != &normal_font_) && (elided_text.length() == 1) &&
|
| (on_first_classification ||
|
| - (prior_classification->font == &normal_font_)))
|
| + (prior_classification->font == &normal_font_))) {
|
| j->font = &normal_font_;
|
| + j->render_text->SetFontList(gfx::FontList(*j->font));
|
| + }
|
|
|
| - int width = 0;
|
| - int height = 0;
|
| - gfx::Canvas::SizeStringInt(elided_text, *j->font, &width, &height,
|
| - gfx::Canvas::NO_ELLIPSIS);
|
| - j->pixel_size = gfx::Size(width, height);
|
| + j->render_text->SetText(elided_text);
|
| + j->pixel_size = j->render_text->GetStringSize();
|
|
|
| // Erase any other classifications that come after the elided one.
|
| i->classifications.erase(j.base(), i->classifications.end());
|
|
|