summaryrefslogtreecommitdiffstats
path: root/ui/gfx/break_list.h
diff options
context:
space:
mode:
authormsw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-01 04:42:17 +0000
committermsw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-01 04:42:17 +0000
commitccfa43f042db868f6584f9cceef94ca7c4ddf239 (patch)
treef3f3980981147928cae30754448f88d45527d2d0 /ui/gfx/break_list.h
parent8c49a50da6675ed9329b01a1e960c78e42d4ba82 (diff)
downloadchromium_src-ccfa43f042db868f6584f9cceef94ca7c4ddf239.zip
chromium_src-ccfa43f042db868f6584f9cceef94ca7c4ddf239.tar.gz
chromium_src-ccfa43f042db868f6584f9cceef94ca7c4ddf239.tar.bz2
Replace StyleRange with BreakList; update RenderText, etc.
This is a functional rewrite with no observable behavior/appearance changes. (it helps by merging adjacent equivalent styles, reducing artificial run breaks) (it helps disambiguate font/adornment styles for application in layout/drawing) Remove gfx::StyleRange and its use within gfx::RenderText[Win|Linux|Mac]. Add new BreakList class for managing [ranged] colors and styles; add/update tests. Add gfx::TextStyle enum for bold, italic, underline, strike, and diagonal strike. Split ApplyStyleRange into [Set|Apply]Color and [Set|Apply]Style. Split ApplyDefaultStyle and |default_style_| into the first colors_ and styles_. Split up SkiaTextRenderer::DrawDecorations for Underline/Strike/DiagonalStrike. Update ApplyCompositionAndSelectionStyles, add UndoCompositionAndSelectionStyles. Add temporary StyleIterator convenience class for RenderText subclass style iteration. Update RenderText[Win|Linux|Mac], Textfield classes, and other users. Simplify OmniboxResultView (nix bold font, and ClassificationData). Rename gfx::Font::FontStyle::UNDERLINE (was UNDERLINED); TODO(followup): Only break runs for bold/italic, color/adorn while drawing. TODO(followup): Support more custom/ranged colors; merge TextStyle/FontStyle? BUG=90426,164047,131660 TEST=No observable appearance/performance/behavior changes. R=asvitkine@chromium.org,pkasting@chromium.org,sky@chromium.org Review URL: https://chromiumcodereview.appspot.com/11535014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@180067 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx/break_list.h')
-rw-r--r--ui/gfx/break_list.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/ui/gfx/break_list.h b/ui/gfx/break_list.h
new file mode 100644
index 0000000..c380222
--- /dev/null
+++ b/ui/gfx/break_list.h
@@ -0,0 +1,165 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_BREAK_LIST_H_
+#define UI_GFX_BREAK_LIST_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "ui/base/range/range.h"
+
+namespace gfx {
+
+// BreakLists manage ordered, non-overlapping, and non-repeating ranged values.
+// These may be used to apply ranged colors and styles to text, for an example.
+//
+// Each break stores the start position and value of its associated range.
+// A solitary break at position 0 applies to the entire space [0, max_).
+// |max_| is initially 0 and should be set to match the available ranged space.
+// The first break always has position 0, to ensure all positions have a value.
+// The value of the terminal break applies to the range [break.first, max_).
+// The value of other breaks apply to the range [break.first, (break+1).first).
+template <typename T>
+class BreakList {
+ public:
+ // The break type and const iterator, typedef'ed for convenience.
+ typedef std::pair<size_t, T> Break;
+ typedef typename std::vector<Break>::const_iterator const_iterator;
+
+ // Initialize a break at position 0 with the default or supplied |value|.
+ BreakList();
+ explicit BreakList(T value);
+
+ const std::vector<Break>& breaks() const { return breaks_; }
+
+ // Clear the breaks and set a break at position 0 with the supplied |value|.
+ void SetValue(T value);
+
+ // Adjust the breaks to apply |value| over the supplied |range|.
+ void ApplyValue(T value, const ui::Range& range);
+
+ // Set the max position and trim any breaks at or beyond that position.
+ void SetMax(size_t max);
+
+ // Get the break applicable to |position| (at or preceeding |position|).
+ typename std::vector<Break>::iterator GetBreak(size_t position);
+
+ // Get the range of the supplied break; returns the break's start position and
+ // the next break's start position (or |max_| for the terminal break).
+ ui::Range GetRange(const typename BreakList<T>::const_iterator& i) const;
+
+ // Comparison functions for testing purposes.
+ bool EqualsValueForTesting(T value) const;
+ bool EqualsForTesting(const std::vector<Break>& breaks) const;
+
+ private:
+#ifndef NDEBUG
+ // Check for ordered breaks [0, |max_|) with no adjacent equivalent values.
+ void CheckBreaks();
+#endif
+
+ std::vector<Break> breaks_;
+ size_t max_;
+};
+
+template<class T>
+BreakList<T>::BreakList() : breaks_(1, Break(0, T())), max_(0) {
+}
+
+template<class T>
+BreakList<T>::BreakList(T value) : breaks_(1, Break(0, value)), max_(0) {
+}
+
+template<class T>
+void BreakList<T>::SetValue(T value) {
+ breaks_.clear();
+ breaks_.push_back(Break(0, value));
+}
+
+template<class T>
+void BreakList<T>::ApplyValue(T value, const ui::Range& range) {
+ if (!range.IsValid() || range.is_empty())
+ return;
+ DCHECK(!breaks_.empty());
+ DCHECK(!range.is_reversed());
+ DCHECK(ui::Range(0, max_).Contains(range));
+
+ // Erase any breaks in |range|, then add start and end breaks as needed.
+ typename std::vector<Break>::iterator start = GetBreak(range.start());
+ start += start->first < range.start() ? 1 : 0;
+ typename std::vector<Break>::iterator end = GetBreak(range.end());
+ T trailing_value = end->second;
+ typename std::vector<Break>::iterator i =
+ start == breaks_.end() ? start : breaks_.erase(start, end + 1);
+ if (range.start() == 0 || (i - 1)->second != value)
+ i = breaks_.insert(i, Break(range.start(), value)) + 1;
+ if (trailing_value != value && range.end() != max_)
+ breaks_.insert(i, Break(range.end(), trailing_value));
+
+#ifndef NDEBUG
+ CheckBreaks();
+#endif
+}
+
+template<class T>
+void BreakList<T>::SetMax(size_t max) {
+ typename std::vector<Break>::iterator i = GetBreak(max);
+ i += (i == breaks_.begin() || i->first < max) ? 1 : 0;
+ breaks_.erase(i, breaks_.end());
+ max_ = max;
+
+#ifndef NDEBUG
+ CheckBreaks();
+#endif
+}
+
+template<class T>
+typename std::vector<std::pair<size_t, T> >::iterator BreakList<T>::GetBreak(
+ size_t position) {
+ typename std::vector<Break>::iterator i = breaks_.end() - 1;
+ for (; i != breaks_.begin() && i->first > position; --i);
+ return i;
+}
+
+template<class T>
+ui::Range BreakList<T>::GetRange(
+ const typename BreakList<T>::const_iterator& i) const {
+ const typename BreakList<T>::const_iterator next = i + 1;
+ return ui::Range(i->first, next == breaks_.end() ? max_ : next->first);
+}
+
+template<class T>
+bool BreakList<T>::EqualsValueForTesting(T value) const {
+ return breaks_.size() == 1 && breaks_[0] == Break(0, value);
+}
+
+template<class T>
+bool BreakList<T>::EqualsForTesting(const std::vector<Break>& breaks) const {
+ if (breaks_.size() != breaks.size())
+ return false;
+ for (size_t i = 0; i < breaks.size(); ++i)
+ if (breaks_[i] != breaks[i])
+ return false;
+ return true;
+}
+
+#ifndef NDEBUG
+template <class T>
+void BreakList<T>::CheckBreaks() {
+ DCHECK_EQ(breaks_[0].first, 0U) << "The first break must be at position 0.";
+ for (size_t i = 0; i < breaks_.size() - 1; ++i) {
+ DCHECK_LT(breaks_[i].first, breaks_[i + 1].first) << "Break out of order.";
+ DCHECK_NE(breaks_[i].second, breaks_[i + 1].second) << "Redundant break.";
+ }
+ if (max_ > 0)
+ DCHECK_LT(breaks_.back().first, max_) << "Break beyond max position.";
+}
+#endif
+
+} // namespace gfx
+
+#endif // UI_GFX_BREAK_LIST_H_