1 /* 2 * This file is part of the WebKit project. 3 * 4 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef SVGCharacterLayoutInfo_h 24 #define SVGCharacterLayoutInfo_h 25 26 #if ENABLE(SVG) 27 #include "AffineTransform.h" 28 #include "SVGRenderStyle.h" 29 #include "SVGTextContentElement.h" 30 31 #include <wtf/Assertions.h> 32 #include <wtf/HashMap.h> 33 #include <wtf/HashSet.h> 34 #include <wtf/RefCounted.h> 35 #include <wtf/Vector.h> 36 37 namespace WebCore { 38 39 class InlineBox; 40 class InlineFlowBox; 41 class SVGInlineTextBox; 42 class SVGLengthList; 43 class SVGNumberList; 44 class SVGTextPositioningElement; 45 46 template<class Type> 47 class PositionedVector : public Vector<Type> { 48 public: 49 PositionedVector<Type>() 50 : m_position(0) 51 { 52 } 53 position()54 unsigned position() const 55 { 56 return m_position; 57 } 58 advance(unsigned position)59 void advance(unsigned position) 60 { 61 m_position += position; 62 ASSERT(m_position < Vector<Type>::size()); 63 } 64 valueAtCurrentPosition()65 Type valueAtCurrentPosition() const 66 { 67 ASSERT(m_position < Vector<Type>::size()); 68 return Vector<Type>::at(m_position); 69 } 70 71 private: 72 unsigned m_position; 73 }; 74 75 class PositionedFloatVector : public PositionedVector<float> { }; 76 struct SVGChar; 77 78 struct SVGCharacterLayoutInfo { 79 SVGCharacterLayoutInfo(Vector<SVGChar>&); 80 81 enum StackType { XStack, YStack, DxStack, DyStack, AngleStack, BaselineShiftStack }; 82 83 bool xValueAvailable() const; 84 bool yValueAvailable() const; 85 bool dxValueAvailable() const; 86 bool dyValueAvailable() const; 87 bool angleValueAvailable() const; 88 bool baselineShiftValueAvailable() const; 89 90 float xValueNext() const; 91 float yValueNext() const; 92 float dxValueNext() const; 93 float dyValueNext() const; 94 float angleValueNext() const; 95 float baselineShiftValueNext() const; 96 97 void processedChunk(float savedShiftX, float savedShiftY); 98 void processedSingleCharacter(); 99 100 bool nextPathLayoutPointAndAngle(float glyphAdvance, float extraAdvance, float newOffset); 101 102 // Used for text-on-path. 103 void addLayoutInformation(InlineFlowBox*, float textAnchorOffset = 0.0f); 104 105 bool inPathLayout() const; 106 void setInPathLayout(bool value); 107 108 // Used for anything else. 109 void addLayoutInformation(SVGTextPositioningElement*); 110 111 // Global position 112 float curx; 113 float cury; 114 115 // Global rotation 116 float angle; 117 118 // Accumulated dx/dy values 119 float dx; 120 float dy; 121 122 // Accumulated baseline-shift values 123 float shiftx; 124 float shifty; 125 126 // Path specific advance values to handle lengthAdjust 127 float pathExtraAdvance; 128 float pathTextLength; 129 float pathChunkLength; 130 131 // Result vector 132 Vector<SVGChar>& svgChars; 133 bool nextDrawnSeperated : 1; 134 135 private: 136 // Used for baseline-shift. 137 void addStackContent(StackType, float); 138 139 // Used for angle. 140 void addStackContent(StackType, SVGNumberList*); 141 142 // Used for x/y/dx/dy. 143 void addStackContent(StackType, SVGLengthList*, const SVGElement*); 144 145 void addStackContent(StackType, const PositionedFloatVector&); 146 147 void xStackWalk(); 148 void yStackWalk(); 149 void dxStackWalk(); 150 void dyStackWalk(); 151 void angleStackWalk(); 152 void baselineShiftStackWalk(); 153 154 private: 155 bool xStackChanged : 1; 156 bool yStackChanged : 1; 157 bool dxStackChanged : 1; 158 bool dyStackChanged : 1; 159 bool angleStackChanged : 1; 160 bool baselineShiftStackChanged : 1; 161 162 // text on path layout 163 bool pathLayout : 1; 164 float currentOffset; 165 float startOffset; 166 float layoutPathLength; 167 Path layoutPath; 168 169 Vector<PositionedFloatVector> xStack; 170 Vector<PositionedFloatVector> yStack; 171 Vector<PositionedFloatVector> dxStack; 172 Vector<PositionedFloatVector> dyStack; 173 Vector<PositionedFloatVector> angleStack; 174 Vector<float> baselineShiftStack; 175 }; 176 177 // Holds extra data, when the character is laid out on a path 178 struct SVGCharOnPath : RefCounted<SVGCharOnPath> { createSVGCharOnPath179 static PassRefPtr<SVGCharOnPath> create() { return adoptRef(new SVGCharOnPath); } 180 181 float xScale; 182 float yScale; 183 184 float xShift; 185 float yShift; 186 187 float orientationAngle; 188 189 bool hidden : 1; 190 191 private: SVGCharOnPathSVGCharOnPath192 SVGCharOnPath() 193 : xScale(1.0f) 194 , yScale(1.0f) 195 , xShift(0.0f) 196 , yShift(0.0f) 197 , orientationAngle(0.0f) 198 , hidden(false) 199 { 200 } 201 }; 202 203 struct SVGChar { SVGCharSVGChar204 SVGChar() 205 : x(0.0f) 206 , y(0.0f) 207 , angle(0.0f) 208 , orientationShiftX(0.0f) 209 , orientationShiftY(0.0f) 210 , pathData() 211 , drawnSeperated(false) 212 , newTextChunk(false) 213 { 214 } 215 ~SVGCharSVGChar216 ~SVGChar() 217 { 218 } 219 220 float x; 221 float y; 222 float angle; 223 224 float orientationShiftX; 225 float orientationShiftY; 226 227 RefPtr<SVGCharOnPath> pathData; 228 229 // Determines wheter this char needs to be drawn seperated 230 bool drawnSeperated : 1; 231 232 // Determines wheter this char starts a new chunk 233 bool newTextChunk : 1; 234 235 // Helper methods 236 bool isHidden() const; 237 AffineTransform characterTransform() const; 238 }; 239 240 struct SVGInlineBoxCharacterRange { SVGInlineBoxCharacterRangeSVGInlineBoxCharacterRange241 SVGInlineBoxCharacterRange() 242 : startOffset(INT_MIN) 243 , endOffset(INT_MIN) 244 , box(0) 245 { 246 } 247 isOpenSVGInlineBoxCharacterRange248 bool isOpen() const { return (startOffset == endOffset) && (endOffset == INT_MIN); } isClosedSVGInlineBoxCharacterRange249 bool isClosed() const { return startOffset != INT_MIN && endOffset != INT_MIN; } 250 251 int startOffset; 252 int endOffset; 253 254 InlineBox* box; 255 }; 256 257 // Convenience typedef 258 typedef SVGTextContentElement::SVGLengthAdjustType ELengthAdjust; 259 260 struct SVGTextChunk { SVGTextChunkSVGTextChunk261 SVGTextChunk() 262 : anchor(TA_START) 263 , textLength(0.0f) 264 , lengthAdjust(SVGTextContentElement::LENGTHADJUST_SPACING) 265 , ctm() 266 , isVerticalText(false) 267 , isTextPath(false) 268 , start(0) 269 , end(0) 270 { } 271 272 // text-anchor support 273 ETextAnchor anchor; 274 275 // textLength & lengthAdjust support 276 float textLength; 277 ELengthAdjust lengthAdjust; 278 AffineTransform ctm; 279 280 // status flags 281 bool isVerticalText : 1; 282 bool isTextPath : 1; 283 284 // main chunk data 285 Vector<SVGChar>::iterator start; 286 Vector<SVGChar>::iterator end; 287 288 Vector<SVGInlineBoxCharacterRange> boxes; 289 }; 290 291 struct SVGTextChunkWalkerBase { ~SVGTextChunkWalkerBaseSVGTextChunkWalkerBase292 virtual ~SVGTextChunkWalkerBase() { } 293 294 virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, 295 const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) = 0; 296 297 // Followings methods are only used for painting text chunks 298 virtual void start(InlineBox*) = 0; 299 virtual void end(InlineBox*) = 0; 300 301 virtual bool setupBackground(InlineBox*) = 0; 302 virtual bool setupFill(InlineBox*) = 0; 303 virtual bool setupFillSelection(InlineBox*) = 0; 304 virtual bool setupStroke(InlineBox*) = 0; 305 virtual bool setupStrokeSelection(InlineBox*) = 0; 306 virtual bool setupForeground(InlineBox*) = 0; 307 }; 308 309 template<typename CallbackClass> 310 struct SVGTextChunkWalker : public SVGTextChunkWalkerBase { 311 public: 312 typedef void (CallbackClass::*SVGTextChunkWalkerCallback)(SVGInlineTextBox* textBox, 313 int startOffset, 314 const AffineTransform& chunkCtm, 315 const Vector<SVGChar>::iterator& start, 316 const Vector<SVGChar>::iterator& end); 317 318 // These callbacks are only used for painting! 319 typedef void (CallbackClass::*SVGTextChunkStartCallback)(InlineBox* box); 320 typedef void (CallbackClass::*SVGTextChunkEndCallback)(InlineBox* box); 321 322 typedef bool (CallbackClass::*SVGTextChunkSetupBackgroundCallback)(InlineBox* box); 323 typedef bool (CallbackClass::*SVGTextChunkSetupFillCallback)(InlineBox* box); 324 typedef bool (CallbackClass::*SVGTextChunkSetupStrokeCallback)(InlineBox* box); 325 typedef bool (CallbackClass::*SVGTextChunkSetupForegroundCallback)(InlineBox* box); 326 327 SVGTextChunkWalker(CallbackClass* object, 328 SVGTextChunkWalkerCallback walker, 329 SVGTextChunkStartCallback start = 0, 330 SVGTextChunkEndCallback end = 0, 331 SVGTextChunkSetupBackgroundCallback background = 0, 332 SVGTextChunkSetupFillCallback fill = 0, 333 SVGTextChunkSetupFillCallback fillSelection = 0, 334 SVGTextChunkSetupStrokeCallback stroke = 0, 335 SVGTextChunkSetupStrokeCallback strokeSelection = 0, 336 SVGTextChunkSetupForegroundCallback foreground = 0) m_objectSVGTextChunkWalker337 : m_object(object) 338 , m_walkerCallback(walker) 339 , m_startCallback(start) 340 , m_endCallback(end) 341 , m_setupBackgroundCallback(background) 342 , m_setupFillCallback(fill) 343 , m_setupFillSelectionCallback(fillSelection) 344 , m_setupStrokeCallback(stroke) 345 , m_setupStrokeSelectionCallback(strokeSelection) 346 , m_setupForegroundCallback(foreground) 347 { 348 ASSERT(object); 349 ASSERT(walker); 350 } 351 operatorSVGTextChunkWalker352 virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, 353 const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) 354 { 355 (*m_object.*m_walkerCallback)(textBox, startOffset, chunkCtm, start, end); 356 } 357 358 // Followings methods are only used for painting text chunks startSVGTextChunkWalker359 virtual void start(InlineBox* box) 360 { 361 if (m_startCallback) 362 (*m_object.*m_startCallback)(box); 363 else 364 ASSERT_NOT_REACHED(); 365 } 366 endSVGTextChunkWalker367 virtual void end(InlineBox* box) 368 { 369 if (m_endCallback) 370 (*m_object.*m_endCallback)(box); 371 else 372 ASSERT_NOT_REACHED(); 373 } 374 setupBackgroundSVGTextChunkWalker375 virtual bool setupBackground(InlineBox* box) 376 { 377 if (m_setupBackgroundCallback) 378 return (*m_object.*m_setupBackgroundCallback)(box); 379 380 ASSERT_NOT_REACHED(); 381 return false; 382 } 383 setupFillSVGTextChunkWalker384 virtual bool setupFill(InlineBox* box) 385 { 386 if (m_setupFillCallback) 387 return (*m_object.*m_setupFillCallback)(box); 388 389 ASSERT_NOT_REACHED(); 390 return false; 391 } 392 setupFillSelectionSVGTextChunkWalker393 virtual bool setupFillSelection(InlineBox* box) 394 { 395 if (m_setupFillSelectionCallback) 396 return (*m_object.*m_setupFillSelectionCallback)(box); 397 398 ASSERT_NOT_REACHED(); 399 return false; 400 } 401 setupStrokeSVGTextChunkWalker402 virtual bool setupStroke(InlineBox* box) 403 { 404 if (m_setupStrokeCallback) 405 return (*m_object.*m_setupStrokeCallback)(box); 406 407 ASSERT_NOT_REACHED(); 408 return false; 409 } 410 setupStrokeSelectionSVGTextChunkWalker411 virtual bool setupStrokeSelection(InlineBox* box) 412 { 413 if (m_setupStrokeSelectionCallback) 414 return (*m_object.*m_setupStrokeSelectionCallback)(box); 415 416 ASSERT_NOT_REACHED(); 417 return false; 418 } 419 setupForegroundSVGTextChunkWalker420 virtual bool setupForeground(InlineBox* box) 421 { 422 if (m_setupForegroundCallback) 423 return (*m_object.*m_setupForegroundCallback)(box); 424 425 ASSERT_NOT_REACHED(); 426 return false; 427 } 428 429 private: 430 CallbackClass* m_object; 431 SVGTextChunkWalkerCallback m_walkerCallback; 432 SVGTextChunkStartCallback m_startCallback; 433 SVGTextChunkEndCallback m_endCallback; 434 SVGTextChunkSetupBackgroundCallback m_setupBackgroundCallback; 435 SVGTextChunkSetupFillCallback m_setupFillCallback; 436 SVGTextChunkSetupFillCallback m_setupFillSelectionCallback; 437 SVGTextChunkSetupStrokeCallback m_setupStrokeCallback; 438 SVGTextChunkSetupStrokeCallback m_setupStrokeSelectionCallback; 439 SVGTextChunkSetupForegroundCallback m_setupForegroundCallback; 440 }; 441 442 struct SVGTextChunkLayoutInfo { SVGTextChunkLayoutInfoSVGTextChunkLayoutInfo443 SVGTextChunkLayoutInfo(Vector<SVGTextChunk>& textChunks) 444 : assignChunkProperties(true) 445 , handlingTextPath(false) 446 , svgTextChunks(textChunks) 447 , it(0) 448 { 449 } 450 451 bool assignChunkProperties : 1; 452 bool handlingTextPath : 1; 453 454 Vector<SVGTextChunk>& svgTextChunks; 455 Vector<SVGChar>::iterator it; 456 457 SVGTextChunk chunk; 458 }; 459 460 struct SVGTextDecorationInfo { 461 // ETextDecoration is meant to be used here 462 HashMap<int, RenderObject*> fillServerMap; 463 HashMap<int, RenderObject*> strokeServerMap; 464 }; 465 466 } // namespace WebCore 467 468 #endif // ENABLE(SVG) 469 #endif // SVGCharacterLayoutInfo_h 470