File indexing completed on 2024-04-28 11:39:00
0001 /* 0002 * This file is part of the WebKit project. 0003 * 0004 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 * 0021 */ 0022 0023 #ifndef SVGCharacterLayoutInfo_h 0024 #define SVGCharacterLayoutInfo_h 0025 0026 #if ENABLE(SVG) 0027 #include <wtf/Assertions.h> 0028 #include <wtf/HashMap.h> 0029 #include <wtf/HashSet.h> 0030 #include <wtf/Vector.h> 0031 0032 #include "AffineTransform.h" 0033 #include <wtf/RefCounted.h> 0034 #include "SVGRenderStyle.h" 0035 #include "SVGTextContentElement.h" 0036 0037 // khtml 0038 #include "rendering/render_line.h" 0039 0040 namespace WebCore 0041 { 0042 0043 using namespace khtml; 0044 //class InlineBox; 0045 //class InlineFlowBox; 0046 class SVGInlineTextBox; 0047 class SVGLengthList; 0048 class SVGNumberList; 0049 class SVGTextPositioningElement; 0050 0051 template<class Type> 0052 class PositionedVector : public Vector<Type> 0053 { 0054 public: 0055 PositionedVector<Type>() 0056 : m_position(0) 0057 { 0058 } 0059 0060 unsigned position() const 0061 { 0062 return m_position; 0063 } 0064 0065 void advance(unsigned position) 0066 { 0067 m_position += position; 0068 ASSERT(m_position < Vector<Type>::size()); 0069 } 0070 0071 Type valueAtCurrentPosition() const 0072 { 0073 ASSERT(m_position < Vector<Type>::size()); 0074 return Vector<Type>::at(m_position); 0075 } 0076 0077 private: 0078 unsigned m_position; 0079 }; 0080 0081 class PositionedFloatVector : public PositionedVector<float> { }; 0082 struct SVGChar; 0083 0084 struct SVGCharacterLayoutInfo { 0085 SVGCharacterLayoutInfo(Vector<SVGChar> &); 0086 0087 enum StackType { XStack, YStack, DxStack, DyStack, AngleStack, BaselineShiftStack }; 0088 0089 bool xValueAvailable() const; 0090 bool yValueAvailable() const; 0091 bool dxValueAvailable() const; 0092 bool dyValueAvailable() const; 0093 bool angleValueAvailable() const; 0094 bool baselineShiftValueAvailable() const; 0095 0096 float xValueNext() const; 0097 float yValueNext() const; 0098 float dxValueNext() const; 0099 float dyValueNext() const; 0100 float angleValueNext() const; 0101 float baselineShiftValueNext() const; 0102 0103 void processedChunk(float savedShiftX, float savedShiftY); 0104 void processedSingleCharacter(); 0105 0106 bool nextPathLayoutPointAndAngle(float glyphAdvance, float extraAdvance, float newOffset); 0107 0108 // Used for text-on-path. 0109 void addLayoutInformation(InlineFlowBox *, float textAnchorOffset = 0.0f); 0110 0111 bool inPathLayout() const; 0112 void setInPathLayout(bool value); 0113 0114 // Used for anything else. 0115 void addLayoutInformation(SVGTextPositioningElement *); 0116 0117 // Global position 0118 float curx; 0119 float cury; 0120 0121 // Global rotation 0122 float angle; 0123 0124 // Accumulated dx/dy values 0125 float dx; 0126 float dy; 0127 0128 // Accumulated baseline-shift values 0129 float shiftx; 0130 float shifty; 0131 0132 // Path specific advance values to handle lengthAdjust 0133 float pathExtraAdvance; 0134 float pathTextLength; 0135 float pathChunkLength; 0136 0137 // Result vector 0138 Vector<SVGChar> &svgChars; 0139 bool nextDrawnSeperated : 1; 0140 0141 private: 0142 // Used for baseline-shift. 0143 void addStackContent(StackType, float); 0144 0145 // Used for angle. 0146 void addStackContent(StackType, SVGNumberList *); 0147 0148 // Used for x/y/dx/dy. 0149 void addStackContent(StackType, SVGLengthList *); 0150 0151 void addStackContent(StackType, const PositionedFloatVector &); 0152 0153 void xStackWalk(); 0154 void yStackWalk(); 0155 void dxStackWalk(); 0156 void dyStackWalk(); 0157 void angleStackWalk(); 0158 void baselineShiftStackWalk(); 0159 0160 private: 0161 bool xStackChanged : 1; 0162 bool yStackChanged : 1; 0163 bool dxStackChanged : 1; 0164 bool dyStackChanged : 1; 0165 bool angleStackChanged : 1; 0166 bool baselineShiftStackChanged : 1; 0167 0168 // text on path layout 0169 bool pathLayout : 1; 0170 float currentOffset; 0171 float startOffset; 0172 float layoutPathLength; 0173 Path layoutPath; 0174 0175 Vector<PositionedFloatVector> xStack; 0176 Vector<PositionedFloatVector> yStack; 0177 Vector<PositionedFloatVector> dxStack; 0178 Vector<PositionedFloatVector> dyStack; 0179 Vector<PositionedFloatVector> angleStack; 0180 Vector<float> baselineShiftStack; 0181 }; 0182 0183 // Holds extra data, when the character is laid out on a path 0184 struct SVGCharOnPath : RefCounted<SVGCharOnPath> { 0185 static PassRefPtr<SVGCharOnPath> create() 0186 { 0187 return adoptRef(new SVGCharOnPath); 0188 } 0189 0190 float xScale; 0191 float yScale; 0192 0193 float xShift; 0194 float yShift; 0195 0196 float orientationAngle; 0197 0198 bool hidden : 1; 0199 0200 private: 0201 SVGCharOnPath() 0202 : xScale(1.0f) 0203 , yScale(1.0f) 0204 , xShift(0.0f) 0205 , yShift(0.0f) 0206 , orientationAngle(0.0f) 0207 , hidden(false) 0208 { 0209 } 0210 }; 0211 0212 struct SVGChar { 0213 SVGChar() 0214 : x(0.0f) 0215 , y(0.0f) 0216 , angle(0.0f) 0217 , orientationShiftX(0.0f) 0218 , orientationShiftY(0.0f) 0219 , pathData() 0220 , drawnSeperated(false) 0221 , newTextChunk(false) 0222 { 0223 } 0224 0225 ~SVGChar() 0226 { 0227 } 0228 0229 float x; 0230 float y; 0231 float angle; 0232 0233 float orientationShiftX; 0234 float orientationShiftY; 0235 0236 RefPtr<SVGCharOnPath> pathData; 0237 0238 // Determines whether this char needs to be drawn separated 0239 bool drawnSeperated : 1; 0240 0241 // Determines whether this char starts a new chunk 0242 bool newTextChunk : 1; 0243 0244 // Helper methods 0245 bool isHidden() const; 0246 AffineTransform characterTransform() const; 0247 }; 0248 0249 struct SVGInlineBoxCharacterRange { 0250 SVGInlineBoxCharacterRange() 0251 : startOffset(INT_MIN) 0252 , endOffset(INT_MIN) 0253 , box(nullptr) 0254 { 0255 } 0256 0257 bool isOpen() const 0258 { 0259 return (startOffset == endOffset) && (endOffset == INT_MIN); 0260 } 0261 bool isClosed() const 0262 { 0263 return startOffset != INT_MIN && endOffset != INT_MIN; 0264 } 0265 0266 int startOffset; 0267 int endOffset; 0268 0269 InlineBox *box; 0270 }; 0271 0272 // Convenience typedef 0273 typedef SVGTextContentElement::SVGLengthAdjustType ELengthAdjust; 0274 0275 struct SVGTextChunk { 0276 SVGTextChunk() 0277 : anchor(TA_START) 0278 , textLength(0.0f) 0279 , lengthAdjust(SVGTextContentElement::LENGTHADJUST_SPACING) 0280 , ctm() 0281 , isVerticalText(false) 0282 , isTextPath(false) 0283 , start(nullptr) 0284 , end(nullptr) 0285 { } 0286 0287 // text-anchor support 0288 ETextAnchor anchor; 0289 0290 // textLength & lengthAdjust support 0291 float textLength; 0292 ELengthAdjust lengthAdjust; 0293 AffineTransform ctm; 0294 0295 // status flags 0296 bool isVerticalText : 1; 0297 bool isTextPath : 1; 0298 0299 // main chunk data 0300 Vector<SVGChar>::iterator start; 0301 Vector<SVGChar>::iterator end; 0302 0303 Vector<SVGInlineBoxCharacterRange> boxes; 0304 }; 0305 0306 struct SVGTextChunkWalkerBase { 0307 virtual ~SVGTextChunkWalkerBase() { } 0308 0309 virtual void operator()(SVGInlineTextBox *textBox, int startOffset, const AffineTransform &chunkCtm, 0310 const Vector<SVGChar>::iterator &start, const Vector<SVGChar>::iterator &end) = 0; 0311 0312 // Followings methods are only used for painting text chunks 0313 virtual void start(InlineBox *) = 0; 0314 virtual void end(InlineBox *) = 0; 0315 0316 virtual bool setupFill(InlineBox *) = 0; 0317 virtual bool setupStroke(InlineBox *) = 0; 0318 }; 0319 0320 template<typename CallbackClass> 0321 struct SVGTextChunkWalker : public SVGTextChunkWalkerBase { 0322 public: 0323 typedef void (CallbackClass::*SVGTextChunkWalkerCallback)(SVGInlineTextBox *textBox, 0324 int startOffset, 0325 const AffineTransform &chunkCtm, 0326 const Vector<SVGChar>::iterator &start, 0327 const Vector<SVGChar>::iterator &end); 0328 0329 // These callbacks are only used for painting! 0330 typedef void (CallbackClass::*SVGTextChunkStartCallback)(InlineBox *box); 0331 typedef void (CallbackClass::*SVGTextChunkEndCallback)(InlineBox *box); 0332 0333 typedef bool (CallbackClass::*SVGTextChunkSetupFillCallback)(InlineBox *box); 0334 typedef bool (CallbackClass::*SVGTextChunkSetupStrokeCallback)(InlineBox *box); 0335 0336 SVGTextChunkWalker(CallbackClass *object, 0337 SVGTextChunkWalkerCallback walker, 0338 SVGTextChunkStartCallback start = nullptr, 0339 SVGTextChunkEndCallback end = nullptr, 0340 SVGTextChunkSetupFillCallback fill = nullptr, 0341 SVGTextChunkSetupStrokeCallback stroke = nullptr) 0342 : m_object(object) 0343 , m_walkerCallback(walker) 0344 , m_startCallback(start) 0345 , m_endCallback(end) 0346 , m_setupFillCallback(fill) 0347 , m_setupStrokeCallback(stroke) 0348 { 0349 ASSERT(object); 0350 ASSERT(walker); 0351 } 0352 0353 virtual void operator()(SVGInlineTextBox *textBox, int startOffset, const AffineTransform &chunkCtm, 0354 const Vector<SVGChar>::iterator &start, const Vector<SVGChar>::iterator &end) override 0355 { 0356 (*m_object.*m_walkerCallback)(textBox, startOffset, chunkCtm, start, end); 0357 } 0358 0359 // Followings methods are only used for painting text chunks 0360 void start(InlineBox *box) override 0361 { 0362 if (m_startCallback) { 0363 (*m_object.*m_startCallback)(box); 0364 } else { 0365 ASSERT_NOT_REACHED(); 0366 } 0367 } 0368 0369 void end(InlineBox *box) override 0370 { 0371 if (m_endCallback) { 0372 (*m_object.*m_endCallback)(box); 0373 } else { 0374 ASSERT_NOT_REACHED(); 0375 } 0376 } 0377 0378 bool setupFill(InlineBox *box) override 0379 { 0380 if (m_setupFillCallback) { 0381 return (*m_object.*m_setupFillCallback)(box); 0382 } 0383 0384 ASSERT_NOT_REACHED(); 0385 return false; 0386 } 0387 0388 bool setupStroke(InlineBox *box) override 0389 { 0390 if (m_setupStrokeCallback) { 0391 return (*m_object.*m_setupStrokeCallback)(box); 0392 } 0393 0394 ASSERT_NOT_REACHED(); 0395 return false; 0396 } 0397 0398 private: 0399 CallbackClass *m_object; 0400 SVGTextChunkWalkerCallback m_walkerCallback; 0401 SVGTextChunkStartCallback m_startCallback; 0402 SVGTextChunkEndCallback m_endCallback; 0403 SVGTextChunkSetupFillCallback m_setupFillCallback; 0404 SVGTextChunkSetupStrokeCallback m_setupStrokeCallback; 0405 }; 0406 0407 struct SVGTextChunkLayoutInfo { 0408 SVGTextChunkLayoutInfo(Vector<SVGTextChunk> &textChunks) 0409 : assignChunkProperties(true) 0410 , handlingTextPath(false) 0411 , svgTextChunks(textChunks) 0412 , it(nullptr) 0413 { 0414 } 0415 0416 bool assignChunkProperties : 1; 0417 bool handlingTextPath : 1; 0418 0419 Vector<SVGTextChunk> &svgTextChunks; 0420 Vector<SVGChar>::iterator it; 0421 0422 SVGTextChunk chunk; 0423 }; 0424 0425 struct SVGTextDecorationInfo { 0426 // ETextDecoration is meant to be used here 0427 HashMap<int, RenderObject *> fillServerMap; 0428 HashMap<int, RenderObject *> strokeServerMap; 0429 }; 0430 0431 } // namespace WebCore 0432 0433 #endif // ENABLE(SVG) 0434 #endif // SVGCharacterLayoutInfo_h