| Index: ui/gfx/render_text_harfbuzz.cc
|
| diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
|
| index 5628b9b5c8d0dbd4dc239ec6cca623299c3622eb..508655b61bf2c04b773b3ab34014bac55d5511b8 100644
|
| --- a/ui/gfx/render_text_harfbuzz.cc
|
| +++ b/ui/gfx/render_text_harfbuzz.cc
|
| @@ -25,6 +25,9 @@
|
| #include "ui/gfx/font_fallback_win.h"
|
| #endif
|
|
|
| +using gfx::internal::RangeF;
|
| +using gfx::internal::RoundRangeF;
|
| +
|
| namespace gfx {
|
|
|
| namespace {
|
| @@ -461,6 +464,11 @@ void GetClusterAtImpl(size_t pos,
|
|
|
| namespace internal {
|
|
|
| +Range RoundRangeF(const RangeF& range_f) {
|
| + return Range(std::floor(range_f.first + 0.5f),
|
| + std::floor(range_f.second + 0.5f));
|
| +}
|
| +
|
| TextRunHarfBuzz::TextRunHarfBuzz()
|
| : width(0.0f),
|
| preceding_run_widths(0.0f),
|
| @@ -522,21 +530,19 @@ size_t TextRunHarfBuzz::CountMissingGlyphs() const {
|
| return missing;
|
| }
|
|
|
| -Range TextRunHarfBuzz::GetGraphemeBounds(
|
| +RangeF TextRunHarfBuzz::GetGraphemeBounds(
|
| base::i18n::BreakIterator* grapheme_iterator,
|
| size_t text_index) {
|
| DCHECK_LT(text_index, range.end());
|
| - // TODO(msw): Support floating point grapheme bounds.
|
| - const int preceding_run_widths_int = SkScalarRoundToInt(preceding_run_widths);
|
| if (glyph_count == 0)
|
| - return Range(preceding_run_widths_int, preceding_run_widths_int + width);
|
| + return RangeF(preceding_run_widths, preceding_run_widths + width);
|
|
|
| Range chars;
|
| Range glyphs;
|
| GetClusterAt(text_index, &chars, &glyphs);
|
| - const int cluster_begin_x = SkScalarRoundToInt(positions[glyphs.start()].x());
|
| - const int cluster_end_x = glyphs.end() < glyph_count ?
|
| - SkScalarRoundToInt(positions[glyphs.end()].x()) : width;
|
| + const float cluster_begin_x = positions[glyphs.start()].x();
|
| + const float cluster_end_x = glyphs.end() < glyph_count ?
|
| + positions[glyphs.end()].x() : SkFloatToScalar(width);
|
|
|
| // A cluster consists of a number of code points and corresponds to a number
|
| // of glyphs that should be drawn together. A cluster can contain multiple
|
| @@ -563,13 +569,13 @@ Range TextRunHarfBuzz::GetGraphemeBounds(
|
| cluster_width * before / static_cast<float>(total));
|
| const int grapheme_end_x = cluster_begin_x + static_cast<int>(0.5f +
|
| cluster_width * (before + 1) / static_cast<float>(total));
|
| - return Range(preceding_run_widths_int + grapheme_begin_x,
|
| - preceding_run_widths_int + grapheme_end_x);
|
| + return RangeF(preceding_run_widths + grapheme_begin_x,
|
| + preceding_run_widths + grapheme_end_x);
|
| }
|
| }
|
|
|
| - return Range(preceding_run_widths_int + cluster_begin_x,
|
| - preceding_run_widths_int + cluster_end_x);
|
| + return RangeF(preceding_run_widths + cluster_begin_x,
|
| + preceding_run_widths + cluster_end_x);
|
| }
|
|
|
| } // namespace internal
|
| @@ -596,7 +602,7 @@ SelectionModel RenderTextHarfBuzz::FindCursorPosition(const Point& point) {
|
| EnsureLayout();
|
|
|
| int x = ToTextPoint(point).x();
|
| - int offset = 0;
|
| + float offset = 0;
|
| size_t run_index = GetRunContainingXCoord(x, &offset);
|
| if (run_index >= runs_.size())
|
| return EdgeSelectionModel((x < 0) ? CURSOR_LEFT : CURSOR_RIGHT);
|
| @@ -646,8 +652,15 @@ Range RenderTextHarfBuzz::GetGlyphBounds(size_t index) {
|
| return Range(GetStringSize().width());
|
| const size_t layout_index = TextIndexToLayoutIndex(index);
|
| internal::TextRunHarfBuzz* run = runs_[run_index];
|
| - Range bounds = run->GetGraphemeBounds(grapheme_iterator_.get(), layout_index);
|
| - return run->is_rtl ? Range(bounds.end(), bounds.start()) : bounds;
|
| + RangeF bounds =
|
| + run->GetGraphemeBounds(grapheme_iterator_.get(), layout_index);
|
| + // If cursor is enabled, extend the last glyph up to the rightmost cursor
|
| + // position since clients expect them to be contiguous.
|
| + if (cursor_enabled() && run_index == runs_.size() - 1 &&
|
| + index == (run->is_rtl ? run->range.start() : run->range.end() - 1))
|
| + bounds.second = std::ceil(bounds.second);
|
| + return RoundRangeF(run->is_rtl ?
|
| + RangeF(bounds.second, bounds.first) : bounds);
|
| }
|
|
|
| int RenderTextHarfBuzz::GetLayoutTextBaseline() {
|
| @@ -778,12 +791,12 @@ std::vector<Rect> RenderTextHarfBuzz::GetSubstringBounds(const Range& range) {
|
| if (!intersection.IsValid())
|
| continue;
|
| DCHECK(!intersection.is_reversed());
|
| - const Range leftmost_character_x = run->GetGraphemeBounds(
|
| + const Range leftmost_character_x = RoundRangeF(run->GetGraphemeBounds(
|
| grapheme_iterator_.get(),
|
| - run->is_rtl ? intersection.end() - 1 : intersection.start());
|
| - const Range rightmost_character_x = run->GetGraphemeBounds(
|
| + run->is_rtl ? intersection.end() - 1 : intersection.start()));
|
| + const Range rightmost_character_x = RoundRangeF(run->GetGraphemeBounds(
|
| grapheme_iterator_.get(),
|
| - run->is_rtl ? intersection.start() : intersection.end() - 1);
|
| + run->is_rtl ? intersection.start() : intersection.end() - 1));
|
| Range range_x(leftmost_character_x.start(), rightmost_character_x.end());
|
| DCHECK(!range_x.is_reversed());
|
| if (range_x.is_empty())
|
| @@ -911,7 +924,6 @@ void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) {
|
| ApplyTextShadows(&renderer);
|
| ApplyCompositionAndSelectionStyles();
|
|
|
| - int current_x = 0;
|
| const Vector2d line_offset = GetLineOffset(0);
|
| for (size_t i = 0; i < runs_.size(); ++i) {
|
| const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]];
|
| @@ -920,11 +932,12 @@ void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) {
|
| renderer.SetFontRenderParams(run.render_params,
|
| background_is_transparent());
|
|
|
| - Vector2d origin = line_offset + Vector2d(current_x, lines()[0].baseline);
|
| + Vector2d origin = line_offset + Vector2d(0, lines()[0].baseline);
|
| scoped_ptr<SkPoint[]> positions(new SkPoint[run.glyph_count]);
|
| for (size_t j = 0; j < run.glyph_count; ++j) {
|
| positions[j] = run.positions[j];
|
| - positions[j].offset(SkIntToScalar(origin.x()), SkIntToScalar(origin.y()));
|
| + positions[j].offset(SkIntToScalar(origin.x()) + run.preceding_run_widths,
|
| + SkIntToScalar(origin.y()));
|
| }
|
|
|
| for (BreakList<SkColor>::const_iterator it =
|
| @@ -946,13 +959,11 @@ void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) {
|
| colored_glyphs.length());
|
| int start_x = SkScalarRoundToInt(positions[colored_glyphs.start()].x());
|
| int end_x = SkScalarRoundToInt((colored_glyphs.end() == run.glyph_count) ?
|
| - (run.width + SkIntToScalar(origin.x())) :
|
| + (run.width + run.preceding_run_widths + SkIntToScalar(origin.x())) :
|
| positions[colored_glyphs.end()].x());
|
| renderer.DrawDecorations(start_x, origin.y(), end_x - start_x,
|
| run.underline, run.strike, run.diagonal_strike);
|
| }
|
| -
|
| - current_x += run.width;
|
| }
|
|
|
| renderer.EndDiagonalStrike();
|
| @@ -972,12 +983,13 @@ size_t RenderTextHarfBuzz::GetRunContainingCaret(
|
| return runs_.size();
|
| }
|
|
|
| -size_t RenderTextHarfBuzz::GetRunContainingXCoord(int x, int* offset) const {
|
| +size_t RenderTextHarfBuzz::GetRunContainingXCoord(float x,
|
| + float* offset) const {
|
| DCHECK(!needs_layout_);
|
| if (x < 0)
|
| return runs_.size();
|
| // Find the text run containing the argument point (assumed already offset).
|
| - int current_x = 0;
|
| + float current_x = 0;
|
| for (size_t i = 0; i < runs_.size(); ++i) {
|
| size_t run = visual_to_logical_[i];
|
| current_x += runs_[run]->width;
|
|
|