diff options
author | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-24 17:45:59 +0000 |
---|---|---|
committer | asvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-24 17:45:59 +0000 |
commit | f0ed8a2f0e95ab61f755f3f4c10b0cdd6007fe26 (patch) | |
tree | 2ef39f64782098f912dcb6221943aa1f9ec52d9a /ui | |
parent | b39c9b201b7a950c647cd9d79494b74692dfeb56 (diff) | |
download | chromium_src-f0ed8a2f0e95ab61f755f3f4c10b0cdd6007fe26.zip chromium_src-f0ed8a2f0e95ab61f755f3f4c10b0cdd6007fe26.tar.gz chromium_src-f0ed8a2f0e95ab61f755f3f4c10b0cdd6007fe26.tar.bz2 |
Add support for horizontal text alignment to RenderText.
Also adds a |cursor_enabled| setting to RenderText to control whether the cursor bounds should be added to the string width for the purposes of layout and gating the |display_offset_| behavior.
BUG=110595
TEST=Moving cursor outside of omnibox bounds under Aura in both LTR and RTL mode - view should pan and follow the cursor. Resizing the window when there is a pan offset, which should consume any new empty space. Also programmatically setting the new alignment modes via some unreleased code and inspecting the results.
Review URL: http://codereview.chromium.org/9252021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118856 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/gfx/render_text.cc | 98 | ||||
-rw-r--r-- | ui/gfx/render_text.h | 41 | ||||
-rw-r--r-- | ui/gfx/render_text_linux.cc | 3 | ||||
-rw-r--r-- | ui/gfx/render_text_win.cc | 3 |
4 files changed, 98 insertions, 47 deletions
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index bb35294..f61ddc9 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc @@ -319,6 +319,14 @@ void RenderText::SetText(const string16& text) { UpdateLayout(); } +void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) { + if (horizontal_alignment_ != alignment) { + horizontal_alignment_ = alignment; + display_offset_ = Point(); + cached_bounds_and_offset_valid_ = false; + } +} + void RenderText::SetFontList(const FontList& font_list) { font_list_ = font_list; cached_bounds_and_offset_valid_ = false; @@ -331,6 +339,11 @@ void RenderText::SetFontSize(int size) { UpdateLayout(); } +void RenderText::SetCursorEnabled(bool cursor_enabled) { + cursor_enabled_ = cursor_enabled; + cached_bounds_and_offset_valid_ = false; +} + const Font& RenderText::GetFont() const { return font_list_.GetFonts()[0]; } @@ -575,7 +588,9 @@ SelectionModel RenderText::GetSelectionModelForSelectionStart() { } RenderText::RenderText() - : cursor_visible_(false), + : horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT), + cursor_enabled_(true), + cursor_visible_(false), insert_mode_(true), focused_(false), composition_range_(ui::Range::InvalidRange()), @@ -656,24 +671,37 @@ void RenderText::ApplyCompositionAndSelectionStyles( } } +Point RenderText::GetTextOrigin() { + Point origin = display_rect().origin(); + origin = origin.Add(GetUpdatedDisplayOffset()); + origin = origin.Add(GetAlignmentOffset()); + return origin; +} + Point RenderText::ToTextPoint(const Point& point) { - Point p(point.Subtract(display_rect().origin())); - p = p.Subtract(GetUpdatedDisplayOffset()); - if (base::i18n::IsRTL()) - p.Offset(GetStringWidth() - display_rect().width() + 1, 0); - return p; + return point.Subtract(GetTextOrigin()); } Point RenderText::ToViewPoint(const Point& point) { - Point p(point.Add(display_rect().origin())); - p = p.Add(GetUpdatedDisplayOffset()); - if (base::i18n::IsRTL()) - p.Offset(display_rect().width() - GetStringWidth() - 1, 0); - return p; + return point.Add(GetTextOrigin()); +} + +int RenderText::GetContentWidth() { + return GetStringWidth() + (cursor_enabled_ ? 1 : 0); +} + +Point RenderText::GetAlignmentOffset() { + if (horizontal_alignment() != ALIGN_LEFT) { + int x_offset = display_rect().width() - GetContentWidth(); + if (horizontal_alignment() == ALIGN_CENTER) + x_offset /= 2; + return Point(x_offset, 0); + } + return Point(); } Point RenderText::GetOriginForSkiaDrawing() { - Point origin(ToViewPoint(Point())); + Point origin(GetTextOrigin()); // TODO(msw): Establish a vertical baseline for strings of mixed font heights. const Font& font = GetFont(); int height = font.GetHeight(); @@ -685,20 +713,20 @@ Point RenderText::GetOriginForSkiaDrawing() { return origin; } -int RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { +void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { if (!fade_head() && !fade_tail()) - return 0; + return; const int text_width = GetStringWidth(); const int display_width = display_rect().width(); // If the text fits as-is, no need to fade. if (text_width <= display_width) - return 0; + return; int gradient_width = CalculateFadeGradientWidth(GetFont(), display_width); if (gradient_width == 0) - return 0; + return; bool fade_left = fade_head(); bool fade_right = fade_tail(); @@ -720,14 +748,8 @@ int RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { solid_part.Inset(0, 0, gradient_width, 0); } - // Right-align the text when fading left. - int x_offset = 0; gfx::Rect text_rect = display_rect(); - if (fade_left && !fade_right) { - x_offset = display_width - text_width; - text_rect.Offset(x_offset, 0); - text_rect.set_width(text_width); - } + text_rect.Inset(GetAlignmentOffset().x(), 0, 0, 0); const SkColor color = default_style().foreground; SkAutoTUnref<SkShader> shader( @@ -736,8 +758,6 @@ int RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) { // |renderer| adds its own ref. So don't |release()| it from the ref ptr. renderer->SetShader(shader.get()); } - - return x_offset; } void RenderText::MoveCursorTo(size_t position, bool select) { @@ -755,17 +775,21 @@ void RenderText::MoveCursorTo(size_t position, bool select) { void RenderText::UpdateCachedBoundsAndOffset() { if (cached_bounds_and_offset_valid_) return; + // First, set the valid flag true to calculate the current cursor bounds using // the stale |display_offset_|. Applying |delta_offset| at the end of this // function will set |cursor_bounds_| and |display_offset_| to correct values. cached_bounds_and_offset_valid_ = true; cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_); + // Update |display_offset_| to ensure the current cursor is visible. - int display_width = display_rect_.width(); - int string_width = GetStringWidth(); + const int display_width = display_rect_.width(); + const int content_width = GetContentWidth(); + int delta_offset = 0; - if (string_width < display_width) { - // Show all text whenever it fits in the display width. + if (content_width <= display_width || !cursor_enabled()) { + // Don't pan if the text fits in the display width or when the cursor is + // disabled. delta_offset = -display_offset_.x(); } else if (cursor_bounds_.right() >= display_rect_.right()) { // TODO(xji): when the character overflow is a RTL character, currently, if @@ -780,13 +804,15 @@ void RenderText::UpdateCachedBoundsAndOffset() { // // Pan to show the cursor when it overflows to the left. delta_offset = display_rect_.x() - cursor_bounds_.x(); - } else { - // Pan to show additional overflow text when the display width increases. - int negate_rtl = base::i18n::IsRTL() ? -1 : 1; - int offset = negate_rtl * display_offset_.x(); - if (display_width > (string_width + offset)) - delta_offset = negate_rtl * (display_width - (string_width + offset) - 1); + } else if (display_offset_.x() != 0) { + // Reduce the pan offset to show additional overflow text when the display + // width increases. + const int negate_rtl = horizontal_alignment_ == ALIGN_RIGHT ? -1 : 1; + const int offset = negate_rtl * display_offset_.x(); + if (display_width > (content_width + offset)) + delta_offset = negate_rtl * (display_width - (content_width + offset)); } + display_offset_.Offset(delta_offset, 0); cursor_bounds_.Offset(delta_offset, 0); } @@ -805,7 +831,7 @@ void RenderText::DrawSelection(Canvas* canvas) { void RenderText::DrawCursor(Canvas* canvas) { // Paint cursor. Replace cursor is drawn as rectangle for now. // TODO(msw): Draw a better cursor with a better indication of association. - if (cursor_visible() && focused()) { + if (cursor_enabled() && cursor_visible() && focused()) { const Rect& bounds = GetUpdatedCursorBounds(); if (bounds.width() != 0) canvas->FillRect(kCursorColor, bounds); diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h index 47471d3..21fe484 100644 --- a/ui/gfx/render_text.h +++ b/ui/gfx/render_text.h @@ -81,6 +81,13 @@ enum BreakType { LINE_BREAK, }; +// Horizontal text alignment styles. +enum HorizontalAlignment { + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT, +}; + // VisualCursorDirection and LogicalCursorDirection represent directions of // motion of the cursor in BiDi text. The combinations that make sense are: // @@ -112,6 +119,11 @@ class UI_EXPORT RenderText { const string16& text() const { return text_; } void SetText(const string16& text); + HorizontalAlignment horizontal_alignment() const { + return horizontal_alignment_; + } + void SetHorizontalAlignment(HorizontalAlignment alignment); + const FontList& font_list() const { return font_list_; } void SetFontList(const FontList& font_list); @@ -123,6 +135,9 @@ class UI_EXPORT RenderText { const SelectionModel& selection_model() const { return selection_model_; } + bool cursor_enabled() const { return cursor_enabled_; } + void SetCursorEnabled(bool cursor_enabled); + bool cursor_visible() const { return cursor_visible_; } void set_cursor_visible(bool visible) { cursor_visible_ = visible; } @@ -312,21 +327,26 @@ class UI_EXPORT RenderText { // style (foreground) to selection range. void ApplyCompositionAndSelectionStyles(StyleRanges* style_ranges); + // Returns the text origin after applying text alignment and display offset. + Point GetTextOrigin(); + // Convert points from the text space to the view space and back. // Handles the display area, display offset, and the application LTR/RTL mode. Point ToTextPoint(const Point& point); Point ToViewPoint(const Point& point); + // Returns the width of content, which reserves room for the cursor if + // |cursor_enabled_| is true. + int GetContentWidth(); + + // Returns display offset based on current text alignment. + Point GetAlignmentOffset(); + // Returns the origin point for drawing text via Skia. Point GetOriginForSkiaDrawing(); - // Applies fade effects to |renderer| and returns a text drawing offset when - // fading the head would cause the text to change alignment. - // TODO(asvitkine): Applying right-alignment in this way doesn't work well - // with drawing the text selection and cursor. Instead, we - // should make RenderText support horizontal alignment - // explicitly. - int ApplyFadeEffects(internal::SkiaTextRenderer* renderer); + // Applies fade effects to |renderer|. + void ApplyFadeEffects(internal::SkiaTextRenderer* renderer); private: friend class RenderTextTest; @@ -357,6 +377,9 @@ class UI_EXPORT RenderText { // Logical UTF-16 string data to be drawn. string16 text_; + // Horizontal alignment of the text with respect to |display_rect_|. + HorizontalAlignment horizontal_alignment_; + // A list of fonts used to render |text_|. FontList font_list_; @@ -366,6 +389,10 @@ class UI_EXPORT RenderText { // The cached cursor bounds; get these bounds with GetUpdatedCursorBounds. Rect cursor_bounds_; + // Specifies whether the cursor is enabled. If disabled, no space is reserved + // for the cursor when positioning text. + bool cursor_enabled_; + // The cursor visibility and insert mode. bool cursor_visible_; bool insert_mode_; diff --git a/ui/gfx/render_text_linux.cc b/ui/gfx/render_text_linux.cc index 1043d88..14bf1f6 100644 --- a/ui/gfx/render_text_linux.cc +++ b/ui/gfx/render_text_linux.cc @@ -381,8 +381,7 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) { } internal::SkiaTextRenderer renderer(canvas); - // Fade effects may force right alignment, requiring an offset to |x|. - x += ApplyFadeEffects(&renderer); + ApplyFadeEffects(&renderer); for (GSList* it = current_line_->runs; it; it = it->next) { PangoLayoutRun* run = reinterpret_cast<PangoLayoutRun*>(it->data); diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc index 9896fb2..692d8e3 100644 --- a/ui/gfx/render_text_win.cc +++ b/ui/gfx/render_text_win.cc @@ -452,8 +452,7 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) { std::vector<SkPoint> pos; internal::SkiaTextRenderer renderer(canvas); - // Fade effects may force right alignment, requiring an offset to |x|. - x += ApplyFadeEffects(&renderer); + ApplyFadeEffects(&renderer); for (size_t i = 0; i < runs_.size(); ++i) { // Get the run specified by the visual-to-logical map. |