Home | History | Annotate | Download | only in text
      1 /*
      2  * Copyright (C) 2000 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 2000 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2000 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2003, 2006, 2007, 2011 Apple Inc. All rights reserved.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Library General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Library General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Library General Public License
     18  * along with this library; see the file COPYING.LIB.  If not, write to
     19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20  * Boston, MA 02110-1301, USA.
     21  *
     22  */
     23 
     24 #ifndef TextRun_h
     25 #define TextRun_h
     26 
     27 #include "platform/PlatformExport.h"
     28 #include "platform/fonts/Glyph.h"
     29 #include "platform/geometry/FloatRect.h"
     30 #include "platform/text/TextDirection.h"
     31 #include "platform/text/TextPath.h"
     32 #include "wtf/RefCounted.h"
     33 #include "wtf/text/WTFString.h"
     34 
     35 namespace blink {
     36 
     37 class FloatPoint;
     38 class Font;
     39 class GraphicsContext;
     40 class GlyphBuffer;
     41 class SimpleFontData;
     42 struct GlyphData;
     43 struct WidthIterator;
     44 
     45 class PLATFORM_EXPORT TextRun {
     46     WTF_MAKE_FAST_ALLOCATED;
     47 public:
     48     enum ExpansionBehaviorFlags {
     49         ForbidTrailingExpansion = 0 << 0,
     50         AllowTrailingExpansion = 1 << 0,
     51         ForbidLeadingExpansion = 0 << 1,
     52         AllowLeadingExpansion = 1 << 1,
     53     };
     54 
     55     typedef unsigned ExpansionBehavior;
     56 
     57     TextRun(const LChar* c, unsigned len, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true)
     58         : m_charactersLength(len)
     59         , m_len(len)
     60         , m_xpos(xpos)
     61         , m_horizontalGlyphStretch(1)
     62         , m_expansion(expansion)
     63         , m_expansionBehavior(expansionBehavior)
     64         , m_is8Bit(true)
     65         , m_allowTabs(false)
     66         , m_direction(direction)
     67         , m_directionalOverride(directionalOverride)
     68         , m_characterScanForCodePath(characterScanForCodePath)
     69         , m_useComplexCodePath(false)
     70         , m_disableSpacing(false)
     71         , m_tabSize(0)
     72         , m_normalizeSpace(false)
     73     {
     74         m_data.characters8 = c;
     75     }
     76 
     77     TextRun(const UChar* c, unsigned len, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true)
     78         : m_charactersLength(len)
     79         , m_len(len)
     80         , m_xpos(xpos)
     81         , m_horizontalGlyphStretch(1)
     82         , m_expansion(expansion)
     83         , m_expansionBehavior(expansionBehavior)
     84         , m_is8Bit(false)
     85         , m_allowTabs(false)
     86         , m_direction(direction)
     87         , m_directionalOverride(directionalOverride)
     88         , m_characterScanForCodePath(characterScanForCodePath)
     89         , m_useComplexCodePath(false)
     90         , m_disableSpacing(false)
     91         , m_tabSize(0)
     92         , m_normalizeSpace(false)
     93     {
     94         m_data.characters16 = c;
     95     }
     96 
     97     TextRun(const String& string, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, bool normalizeSpace = false)
     98         : m_charactersLength(string.length())
     99         , m_len(string.length())
    100         , m_xpos(xpos)
    101         , m_horizontalGlyphStretch(1)
    102         , m_expansion(expansion)
    103         , m_expansionBehavior(expansionBehavior)
    104         , m_allowTabs(false)
    105         , m_direction(direction)
    106         , m_directionalOverride(directionalOverride)
    107         , m_characterScanForCodePath(characterScanForCodePath)
    108         , m_useComplexCodePath(false)
    109         , m_disableSpacing(false)
    110         , m_tabSize(0)
    111         , m_normalizeSpace(normalizeSpace)
    112     {
    113         if (!m_charactersLength) {
    114             m_is8Bit = true;
    115             m_data.characters8 = 0;
    116         } else if (string.is8Bit()) {
    117             m_data.characters8 = string.characters8();
    118             m_is8Bit = true;
    119         } else {
    120             m_data.characters16 = string.characters16();
    121             m_is8Bit = false;
    122         }
    123     }
    124 
    125     TextRun(const StringView& string, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, bool normalizeSpace = false)
    126         : m_charactersLength(string.length())
    127         , m_len(string.length())
    128         , m_xpos(xpos)
    129         , m_horizontalGlyphStretch(1)
    130         , m_expansion(expansion)
    131         , m_expansionBehavior(expansionBehavior)
    132         , m_allowTabs(false)
    133         , m_direction(direction)
    134         , m_directionalOverride(directionalOverride)
    135         , m_characterScanForCodePath(characterScanForCodePath)
    136         , m_useComplexCodePath(false)
    137         , m_disableSpacing(false)
    138         , m_tabSize(0)
    139         , m_normalizeSpace(normalizeSpace)
    140     {
    141         if (!m_charactersLength) {
    142             m_is8Bit = true;
    143             m_data.characters8 = 0;
    144         } else if (string.is8Bit()) {
    145             m_data.characters8 = string.characters8();
    146             m_is8Bit = true;
    147         } else {
    148             m_data.characters16 = string.characters16();
    149             m_is8Bit = false;
    150         }
    151     }
    152 
    153     TextRun subRun(unsigned startOffset, unsigned length) const
    154     {
    155         ASSERT(startOffset < m_len);
    156 
    157         TextRun result = *this;
    158 
    159         if (is8Bit()) {
    160             result.setText(data8(startOffset), length);
    161             return result;
    162         }
    163         result.setText(data16(startOffset), length);
    164         return result;
    165     }
    166 
    167     UChar operator[](unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); return is8Bit() ? m_data.characters8[i] :m_data.characters16[i]; }
    168     const LChar* data8(unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); ASSERT(is8Bit()); return &m_data.characters8[i]; }
    169     const UChar* data16(unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); ASSERT(!is8Bit()); return &m_data.characters16[i]; }
    170 
    171     const LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; }
    172     const UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; }
    173 
    174     bool is8Bit() const { return m_is8Bit; }
    175     int length() const { return m_len; }
    176     int charactersLength() const { return m_charactersLength; }
    177 
    178     bool normalizeSpace() const { return m_normalizeSpace; }
    179     void setNormalizeSpace(bool normalizeSpace) { m_normalizeSpace = normalizeSpace; }
    180 
    181     void setText(const LChar* c, unsigned len) { m_data.characters8 = c; m_len = len; m_is8Bit = true;}
    182     void setText(const UChar* c, unsigned len) { m_data.characters16 = c; m_len = len; m_is8Bit = false;}
    183     void setText(const String&);
    184     void setCharactersLength(unsigned charactersLength) { m_charactersLength = charactersLength; }
    185 
    186     float horizontalGlyphStretch() const { return m_horizontalGlyphStretch; }
    187     void setHorizontalGlyphStretch(float scale) { m_horizontalGlyphStretch = scale; }
    188 
    189     bool allowTabs() const { return m_allowTabs; }
    190     unsigned tabSize() const { return m_tabSize; }
    191     void setTabSize(bool, unsigned);
    192 
    193     float xPos() const { return m_xpos; }
    194     void setXPos(float xPos) { m_xpos = xPos; }
    195     float expansion() const { return m_expansion; }
    196     bool allowsLeadingExpansion() const { return m_expansionBehavior & AllowLeadingExpansion; }
    197     bool allowsTrailingExpansion() const { return m_expansionBehavior & AllowTrailingExpansion; }
    198     TextDirection direction() const { return static_cast<TextDirection>(m_direction); }
    199     bool rtl() const { return m_direction == RTL; }
    200     bool ltr() const { return m_direction == LTR; }
    201     bool directionalOverride() const { return m_directionalOverride; }
    202     bool characterScanForCodePath() const { return m_characterScanForCodePath; }
    203     bool useComplexCodePath() const { return m_useComplexCodePath; }
    204     bool spacingDisabled() const { return m_disableSpacing; }
    205 
    206     void disableSpacing() { m_disableSpacing = true; }
    207     void setDirection(TextDirection direction) { m_direction = direction; }
    208     void setDirectionalOverride(bool override) { m_directionalOverride = override; }
    209     void setCharacterScanForCodePath(bool scan) { m_characterScanForCodePath = scan; }
    210     void setUseComplexCodePath(bool useComplex) { m_useComplexCodePath = useComplex; }
    211 
    212     class RenderingContext : public RefCounted<RenderingContext> {
    213     public:
    214         virtual ~RenderingContext() { }
    215 
    216         virtual GlyphData glyphDataForCharacter(const Font&, const TextRun&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength) = 0;
    217         virtual void drawSVGGlyphs(GraphicsContext*, const TextRun&, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const = 0;
    218         virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, Glyph& glyphId) const = 0;
    219     };
    220 
    221     RenderingContext* renderingContext() const { return m_renderingContext.get(); }
    222     void setRenderingContext(PassRefPtr<RenderingContext> context) { m_renderingContext = context; }
    223 
    224 private:
    225     union {
    226         const LChar* characters8;
    227         const UChar* characters16;
    228     } m_data;
    229     unsigned m_charactersLength; // Marks the end of the characters buffer. Default equals to m_len.
    230     unsigned m_len;
    231 
    232     // m_xpos is the x position relative to the left start of the text line, not relative to the left
    233     // start of the containing block. In the case of right alignment or center alignment, left start of
    234     // the text line is not the same as left start of the containing block.
    235     float m_xpos;
    236     float m_horizontalGlyphStretch;
    237 
    238     float m_expansion;
    239     ExpansionBehavior m_expansionBehavior : 2;
    240     unsigned m_is8Bit : 1;
    241     unsigned m_allowTabs : 1;
    242     unsigned m_direction : 1;
    243     unsigned m_directionalOverride : 1; // Was this direction set by an override character.
    244     unsigned m_characterScanForCodePath : 1;
    245     unsigned m_useComplexCodePath : 1;
    246     unsigned m_disableSpacing : 1;
    247     unsigned m_tabSize;
    248     bool m_normalizeSpace;
    249     RefPtr<RenderingContext> m_renderingContext;
    250 };
    251 
    252 inline void TextRun::setTabSize(bool allow, unsigned size)
    253 {
    254     m_allowTabs = allow;
    255     m_tabSize = size;
    256 }
    257 
    258 // Container for parameters needed to paint TextRun.
    259 struct TextRunPaintInfo {
    260     explicit TextRunPaintInfo(const TextRun& r)
    261         : run(r)
    262         , from(0)
    263         , to(r.length())
    264     {
    265     }
    266 
    267     const TextRun& run;
    268     int from;
    269     int to;
    270     FloatRect bounds;
    271 };
    272 
    273 }
    274 #endif
    275