Home | History | Annotate | Download | only in gfx
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 // This file defines utility functions for eliding and formatting UI text.
      6 
      7 #ifndef UI_GFX_TEXT_ELIDER_H_
      8 #define UI_GFX_TEXT_ELIDER_H_
      9 
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/basictypes.h"
     14 #include "base/strings/string16.h"
     15 #include "ui/gfx/gfx_export.h"
     16 #include "ui/gfx/text_constants.h"
     17 
     18 class GURL;
     19 
     20 namespace base {
     21 class FilePath;
     22 }
     23 
     24 namespace gfx {
     25 class FontList;
     26 
     27 GFX_EXPORT extern const char kEllipsis[];
     28 GFX_EXPORT extern const base::char16 kEllipsisUTF16[];
     29 GFX_EXPORT extern const base::char16 kForwardSlash;
     30 
     31 // Helper class to split + elide text, while respecting UTF16 surrogate pairs.
     32 class StringSlicer {
     33  public:
     34   StringSlicer(const base::string16& text,
     35                const base::string16& ellipsis,
     36                bool elide_in_middle,
     37                bool elide_at_beginning);
     38 
     39   // Cuts |text_| to be |length| characters long. If |elide_in_middle_| is true,
     40   // the middle of the string is removed to leave equal-length pieces from the
     41   // beginning and end of the string; otherwise, the end of the string is
     42   // removed and only the beginning remains. If |insert_ellipsis| is true,
     43   // then an ellipsis character will be inserted at the cut point.
     44   base::string16 CutString(size_t length, bool insert_ellipsis);
     45 
     46  private:
     47   // Returns a valid cut boundary at or before/after |index|.
     48   size_t FindValidBoundaryBefore(size_t index) const;
     49   size_t FindValidBoundaryAfter(size_t index) const;
     50 
     51   // The text to be sliced.
     52   const base::string16& text_;
     53 
     54   // Ellipsis string to use.
     55   const base::string16& ellipsis_;
     56 
     57   // If true, the middle of the string will be elided.
     58   bool elide_in_middle_;
     59 
     60   // If true, the beginning of the string will be elided.
     61   bool elide_at_beginning_;
     62 
     63   DISALLOW_COPY_AND_ASSIGN(StringSlicer);
     64 };
     65 
     66 // Elides |text| to fit the |available_pixel_width| with the specified behavior.
     67 GFX_EXPORT base::string16 ElideText(const base::string16& text,
     68                                     const gfx::FontList& font_list,
     69                                     float available_pixel_width,
     70                                     ElideBehavior elide_behavior);
     71 
     72 // Elide a filename to fit a given pixel width, with an emphasis on not hiding
     73 // the extension unless we have to. If filename contains a path, the path will
     74 // be removed if filename doesn't fit into available_pixel_width. The elided
     75 // filename is forced to have LTR directionality, which means that in RTL UI
     76 // the elided filename is wrapped with LRE (Left-To-Right Embedding) mark and
     77 // PDF (Pop Directional Formatting) mark.
     78 GFX_EXPORT base::string16 ElideFilename(const base::FilePath& filename,
     79                                         const gfx::FontList& font_list,
     80                                         float available_pixel_width);
     81 
     82 // Functions to elide strings when the font information is unknown. As opposed
     83 // to the above functions, ElideString() and ElideRectangleString() operate in
     84 // terms of character units, not pixels.
     85 
     86 // If the size of |input| is more than |max_len|, this function returns
     87 // true and |input| is shortened into |output| by removing chars in the
     88 // middle (they are replaced with up to 3 dots, as size permits).
     89 // Ex: ElideString(ASCIIToUTF16("Hello"), 10, &str) puts Hello in str and
     90 // returns false.  ElideString(ASCIIToUTF16("Hello my name is Tom"), 10, &str)
     91 // puts "Hell...Tom" in str and returns true.
     92 // TODO(tsepez): Doesn't handle UTF-16 surrogate pairs properly.
     93 // TODO(tsepez): Doesn't handle bidi properly.
     94 GFX_EXPORT bool ElideString(const base::string16& input, int max_len,
     95                             base::string16* output);
     96 
     97 // Reformat |input| into |output| so that it fits into a |max_rows| by
     98 // |max_cols| rectangle of characters.  Input newlines are respected, but
     99 // lines that are too long are broken into pieces.  If |strict| is true,
    100 // we break first at naturally occuring whitespace boundaries, otherwise
    101 // we assume some other mechanism will do this in approximately the same
    102 // spot after the fact.  If the word itself is too long, we always break
    103 // intra-word (respecting UTF-16 surrogate pairs) as necssary. Truncation
    104 // (indicated by an added 3 dots) occurs if the result is still too long.
    105 //  Returns true if the input had to be truncated (and not just reformatted).
    106 GFX_EXPORT bool ElideRectangleString(const base::string16& input,
    107                                      size_t max_rows,
    108                                      size_t max_cols,
    109                                      bool strict,
    110                                      base::string16* output);
    111 
    112 // Specifies the word wrapping behavior of |ElideRectangleText()| when a word
    113 // would exceed the available width.
    114 enum WordWrapBehavior {
    115   // Words that are too wide will be put on a new line, but will not be
    116   // truncated or elided.
    117   IGNORE_LONG_WORDS,
    118 
    119   // Words that are too wide will be put on a new line and will be truncated to
    120   // the available width.
    121   TRUNCATE_LONG_WORDS,
    122 
    123   // Words that are too wide will be put on a new line and will be elided to the
    124   // available width.
    125   ELIDE_LONG_WORDS,
    126 
    127   // Words that are too wide will be put on a new line and will be wrapped over
    128   // multiple lines.
    129   WRAP_LONG_WORDS,
    130 };
    131 
    132 // Indicates whether the |available_pixel_width| by |available_pixel_height|
    133 // rectangle passed to |ElideRectangleText()| had insufficient space to
    134 // accommodate the given |text|, leading to elision or truncation.
    135 enum ReformattingResultFlags {
    136   INSUFFICIENT_SPACE_HORIZONTAL = 1 << 0,
    137   INSUFFICIENT_SPACE_VERTICAL = 1 << 1,
    138 };
    139 
    140 // Reformats |text| into output vector |lines| so that the resulting text fits
    141 // into an |available_pixel_width| by |available_pixel_height| rectangle with
    142 // the specified |font_list|. Input newlines are respected, but lines that are
    143 // too long are broken into pieces. For words that are too wide to fit on a
    144 // single line, the wrapping behavior can be specified with the |wrap_behavior|
    145 // param. Returns a combination of |ReformattingResultFlags| that indicate
    146 // whether the given rectangle had insufficient space to accommodate |text|,
    147 // leading to elision or truncation (and not just reformatting).
    148 GFX_EXPORT int ElideRectangleText(const base::string16& text,
    149                                   const gfx::FontList& font_list,
    150                                   float available_pixel_width,
    151                                   int available_pixel_height,
    152                                   WordWrapBehavior wrap_behavior,
    153                                   std::vector<base::string16>* lines);
    154 
    155 // Truncates |string| to |length| characters. This breaks the string according
    156 // to the specified |break_type|, which must be either WORD_BREAK or
    157 // CHARACTER_BREAK, and adds the horizontal ellipsis character (unicode
    158 // character 0x2026) to render "...". The supplied string is returned if the
    159 // string has |length| characters or less.
    160 GFX_EXPORT base::string16 TruncateString(const base::string16& string,
    161                                          size_t length,
    162                                          BreakType break_type);
    163 
    164 }  // namespace gfx
    165 
    166 #endif  // UI_GFX_TEXT_ELIDER_H_
    167