1 /* 2 * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 #ifndef PARAGRAPH_LAYOUT_H 6 #define PARAGRAPH_LAYOUT_H 7 8 #include <Font.h> 9 #include <Referenceable.h> 10 #include <String.h> 11 12 #include "Paragraph.h" 13 #include "CharacterStyle.h" 14 15 16 class BView; 17 18 19 class GlyphInfo { 20 public: 21 GlyphInfo() 22 : 23 charCode(0), 24 x(0.0f), 25 width(0.0f), 26 lineIndex(0) 27 { 28 } 29 30 GlyphInfo(uint32 charCode, float x, float width, int32 lineIndex) 31 : 32 charCode(charCode), 33 x(x), 34 width(width), 35 lineIndex(lineIndex) 36 { 37 } 38 39 GlyphInfo(const GlyphInfo& other) 40 : 41 charCode(other.charCode), 42 x(other.x), 43 width(other.width), 44 lineIndex(other.lineIndex) 45 { 46 } 47 48 GlyphInfo& operator=(const GlyphInfo& other) 49 { 50 charCode = other.charCode; 51 x = other.x; 52 width = other.width; 53 lineIndex = other.lineIndex; 54 return *this; 55 } 56 57 bool operator==(const GlyphInfo& other) const 58 { 59 return charCode == other.charCode 60 && x == other.x 61 && width == other.width 62 && lineIndex == other.lineIndex; 63 } 64 65 bool operator!=(const GlyphInfo& other) const 66 { 67 return !(*this == other); 68 } 69 70 public: 71 uint32 charCode; 72 73 float x; 74 float width; 75 76 int32 lineIndex; 77 }; 78 79 80 typedef List<GlyphInfo, false> GlyphInfoList; 81 82 83 class LineInfo { 84 public: 85 LineInfo() 86 : 87 textOffset(0), 88 y(0.0f), 89 height(0.0f), 90 maxAscent(0.0f), 91 maxDescent(0.0f), 92 extraGlyphSpacing(0.0f), 93 extraWhiteSpacing(0.0f), 94 layoutedSpans() 95 { 96 } 97 98 LineInfo(int32 textOffset, float y, float height, float maxAscent, 99 float maxDescent) 100 : 101 textOffset(textOffset), 102 y(y), 103 height(height), 104 maxAscent(maxAscent), 105 maxDescent(maxDescent), 106 extraGlyphSpacing(0.0f), 107 extraWhiteSpacing(0.0f), 108 layoutedSpans() 109 { 110 } 111 112 LineInfo(const LineInfo& other) 113 : 114 textOffset(other.textOffset), 115 y(other.y), 116 height(other.height), 117 maxAscent(other.maxAscent), 118 maxDescent(other.maxDescent), 119 extraGlyphSpacing(other.extraGlyphSpacing), 120 extraWhiteSpacing(other.extraWhiteSpacing), 121 layoutedSpans(other.layoutedSpans) 122 { 123 } 124 125 LineInfo& operator=(const LineInfo& other) 126 { 127 textOffset = other.textOffset; 128 y = other.y; 129 height = other.height; 130 maxAscent = other.maxAscent; 131 maxDescent = other.maxDescent; 132 extraGlyphSpacing = other.extraGlyphSpacing; 133 extraWhiteSpacing = other.extraWhiteSpacing; 134 layoutedSpans = other.layoutedSpans; 135 return *this; 136 } 137 138 bool operator==(const LineInfo& other) const 139 { 140 return textOffset == other.textOffset 141 && y == other.y 142 && height == other.height 143 && maxAscent == other.maxAscent 144 && maxDescent == other.maxDescent 145 && extraGlyphSpacing == other.extraGlyphSpacing 146 && extraWhiteSpacing == other.extraWhiteSpacing 147 && layoutedSpans == other.layoutedSpans; 148 } 149 150 bool operator!=(const LineInfo& other) const 151 { 152 return !(*this == other); 153 } 154 155 public: 156 int32 textOffset; 157 158 float y; 159 float height; 160 161 float maxAscent; 162 float maxDescent; 163 164 float extraGlyphSpacing; 165 float extraWhiteSpacing; 166 167 TextSpanList layoutedSpans; 168 }; 169 170 171 typedef List<LineInfo, false> LineInfoList; 172 173 174 class ParagraphLayout : public BReferenceable { 175 public: 176 ParagraphLayout(); 177 ParagraphLayout(const Paragraph& paragraph); 178 ParagraphLayout(const ParagraphLayout& other); 179 virtual ~ParagraphLayout(); 180 181 void SetParagraph(const Paragraph& paragraph); 182 const ParagraphStyle& Style() const 183 { return fParagraphStyle; } 184 185 void SetWidth(float width); 186 float Width() const 187 { return fWidth; } 188 189 float Height(); 190 void Draw(BView* view, const BPoint& offset); 191 192 int32 CountGlyphs() const; 193 int32 CountLines(); 194 195 int32 LineIndexForOffset(int32 textOffset); 196 int32 FirstOffsetOnLine(int32 lineIndex); 197 int32 LastOffsetOnLine(int32 lineIndex); 198 199 void GetLineBounds(int32 lineIndex, 200 float& x1, float& y1, 201 float& x2, float& y2); 202 203 void GetTextBounds(int32 textOffset, 204 float& x1, float& y1, 205 float& x2, float& y2); 206 207 int32 TextOffsetAt(float x, float y, 208 bool& rightOfCenter); 209 210 private: 211 void _Init(); 212 213 void _ValidateLayout(); 214 void _Layout(); 215 void _ApplyAlignment(); 216 217 bool _AppendGlyphInfos(const TextSpan& span); 218 bool _AppendGlyphInfo(uint32 charCode, 219 float advanceX, 220 const CharacterStyle& style); 221 222 bool _FinalizeLine(int lineStart, int lineEnd, 223 int lineIndex, float y, float& lineHeight); 224 225 void _IncludeStyleInLine(LineInfo& line, 226 const CharacterStyle& style); 227 228 void _DrawLine(BView* view, const BPoint& offset, 229 const LineInfo& line) const; 230 void _DrawSpan(BView* view, BPoint offset, 231 const TextSpan& span, 232 int32 textOffset) const; 233 234 void _GetEmptyLayoutBounds(float& x1, float& y1, 235 float& x2, float& y2) const; 236 237 private: 238 TextSpanList fTextSpans; 239 ParagraphStyle fParagraphStyle; 240 241 float fWidth; 242 bool fLayoutValid; 243 244 GlyphInfoList fGlyphInfos; 245 LineInfoList fLineInfos; 246 }; 247 248 249 typedef BReference<ParagraphLayout> ParagraphLayoutRef; 250 251 252 #endif // PARAGRAPH_LAYOUT_H 253