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