KHtml

SVGCharacterLayoutInfo.h
1 /*
2  * This file is part of the WebKit project.
3  *
4  * Copyright (C) 2007 Nikolas Zimmermann <[email protected]>
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 <wtf/Assertions.h>
28 #include <wtf/HashMap.h>
29 #include <wtf/HashSet.h>
30 #include <wtf/Vector.h>
31 
32 #include "AffineTransform.h"
33 #include <wtf/RefCounted.h>
34 #include "SVGRenderStyle.h"
35 #include "SVGTextContentElement.h"
36 
37 // khtml
38 #include "rendering/render_line.h"
39 
40 namespace WebCore
41 {
42 
43 using namespace khtml;
44 //class InlineBox;
45 //class InlineFlowBox;
46 class SVGInlineTextBox;
47 class SVGLengthList;
48 class SVGNumberList;
49 class SVGTextPositioningElement;
50 
51 template<class Type>
52 class PositionedVector : public Vector<Type>
53 {
54 public:
55  PositionedVector<Type>()
56  : m_position(0)
57  {
58  }
59 
60  unsigned position() const
61  {
62  return m_position;
63  }
64 
65  void advance(unsigned position)
66  {
67  m_position += position;
68  ASSERT(m_position < Vector<Type>::size());
69  }
70 
71  Type valueAtCurrentPosition() const
72  {
73  ASSERT(m_position < Vector<Type>::size());
74  return Vector<Type>::at(m_position);
75  }
76 
77 private:
78  unsigned m_position;
79 };
80 
81 class PositionedFloatVector : public PositionedVector<float> { };
82 struct SVGChar;
83 
84 struct SVGCharacterLayoutInfo {
85  SVGCharacterLayoutInfo(Vector<SVGChar> &);
86 
87  enum StackType { XStack, YStack, DxStack, DyStack, AngleStack, BaselineShiftStack };
88 
89  bool xValueAvailable() const;
90  bool yValueAvailable() const;
91  bool dxValueAvailable() const;
92  bool dyValueAvailable() const;
93  bool angleValueAvailable() const;
94  bool baselineShiftValueAvailable() const;
95 
96  float xValueNext() const;
97  float yValueNext() const;
98  float dxValueNext() const;
99  float dyValueNext() const;
100  float angleValueNext() const;
101  float baselineShiftValueNext() const;
102 
103  void processedChunk(float savedShiftX, float savedShiftY);
104  void processedSingleCharacter();
105 
106  bool nextPathLayoutPointAndAngle(float glyphAdvance, float extraAdvance, float newOffset);
107 
108  // Used for text-on-path.
109  void addLayoutInformation(InlineFlowBox *, float textAnchorOffset = 0.0f);
110 
111  bool inPathLayout() const;
112  void setInPathLayout(bool value);
113 
114  // Used for anything else.
115  void addLayoutInformation(SVGTextPositioningElement *);
116 
117  // Global position
118  float curx;
119  float cury;
120 
121  // Global rotation
122  float angle;
123 
124  // Accumulated dx/dy values
125  float dx;
126  float dy;
127 
128  // Accumulated baseline-shift values
129  float shiftx;
130  float shifty;
131 
132  // Path specific advance values to handle lengthAdjust
133  float pathExtraAdvance;
134  float pathTextLength;
135  float pathChunkLength;
136 
137  // Result vector
138  Vector<SVGChar> &svgChars;
139  bool nextDrawnSeperated : 1;
140 
141 private:
142  // Used for baseline-shift.
143  void addStackContent(StackType, float);
144 
145  // Used for angle.
146  void addStackContent(StackType, SVGNumberList *);
147 
148  // Used for x/y/dx/dy.
149  void addStackContent(StackType, SVGLengthList *);
150 
151  void addStackContent(StackType, const PositionedFloatVector &);
152 
153  void xStackWalk();
154  void yStackWalk();
155  void dxStackWalk();
156  void dyStackWalk();
157  void angleStackWalk();
158  void baselineShiftStackWalk();
159 
160 private:
161  bool xStackChanged : 1;
162  bool yStackChanged : 1;
163  bool dxStackChanged : 1;
164  bool dyStackChanged : 1;
165  bool angleStackChanged : 1;
166  bool baselineShiftStackChanged : 1;
167 
168  // text on path layout
169  bool pathLayout : 1;
170  float currentOffset;
171  float startOffset;
172  float layoutPathLength;
173  Path layoutPath;
174 
175  Vector<PositionedFloatVector> xStack;
176  Vector<PositionedFloatVector> yStack;
177  Vector<PositionedFloatVector> dxStack;
178  Vector<PositionedFloatVector> dyStack;
179  Vector<PositionedFloatVector> angleStack;
180  Vector<float> baselineShiftStack;
181 };
182 
183 // Holds extra data, when the character is laid out on a path
184 struct SVGCharOnPath : RefCounted<SVGCharOnPath> {
185  static PassRefPtr<SVGCharOnPath> create()
186  {
187  return adoptRef(new SVGCharOnPath);
188  }
189 
190  float xScale;
191  float yScale;
192 
193  float xShift;
194  float yShift;
195 
196  float orientationAngle;
197 
198  bool hidden : 1;
199 
200 private:
201  SVGCharOnPath()
202  : xScale(1.0f)
203  , yScale(1.0f)
204  , xShift(0.0f)
205  , yShift(0.0f)
206  , orientationAngle(0.0f)
207  , hidden(false)
208  {
209  }
210 };
211 
212 struct SVGChar {
213  SVGChar()
214  : x(0.0f)
215  , y(0.0f)
216  , angle(0.0f)
217  , orientationShiftX(0.0f)
218  , orientationShiftY(0.0f)
219  , pathData()
220  , drawnSeperated(false)
221  , newTextChunk(false)
222  {
223  }
224 
225  ~SVGChar()
226  {
227  }
228 
229  float x;
230  float y;
231  float angle;
232 
233  float orientationShiftX;
234  float orientationShiftY;
235 
236  RefPtr<SVGCharOnPath> pathData;
237 
238  // Determines whether this char needs to be drawn separated
239  bool drawnSeperated : 1;
240 
241  // Determines whether this char starts a new chunk
242  bool newTextChunk : 1;
243 
244  // Helper methods
245  bool isHidden() const;
246  AffineTransform characterTransform() const;
247 };
248 
249 struct SVGInlineBoxCharacterRange {
250  SVGInlineBoxCharacterRange()
251  : startOffset(INT_MIN)
252  , endOffset(INT_MIN)
253  , box(nullptr)
254  {
255  }
256 
257  bool isOpen() const
258  {
259  return (startOffset == endOffset) && (endOffset == INT_MIN);
260  }
261  bool isClosed() const
262  {
263  return startOffset != INT_MIN && endOffset != INT_MIN;
264  }
265 
266  int startOffset;
267  int endOffset;
268 
269  InlineBox *box;
270 };
271 
272 // Convenience typedef
273 typedef SVGTextContentElement::SVGLengthAdjustType ELengthAdjust;
274 
275 struct SVGTextChunk {
276  SVGTextChunk()
277  : anchor(TA_START)
278  , textLength(0.0f)
279  , lengthAdjust(SVGTextContentElement::LENGTHADJUST_SPACING)
280  , ctm()
281  , isVerticalText(false)
282  , isTextPath(false)
283  , start(nullptr)
284  , end(nullptr)
285  { }
286 
287  // text-anchor support
288  ETextAnchor anchor;
289 
290  // textLength & lengthAdjust support
291  float textLength;
292  ELengthAdjust lengthAdjust;
293  AffineTransform ctm;
294 
295  // status flags
296  bool isVerticalText : 1;
297  bool isTextPath : 1;
298 
299  // main chunk data
300  Vector<SVGChar>::iterator start;
301  Vector<SVGChar>::iterator end;
302 
303  Vector<SVGInlineBoxCharacterRange> boxes;
304 };
305 
306 struct SVGTextChunkWalkerBase {
307  virtual ~SVGTextChunkWalkerBase() { }
308 
309  virtual void operator()(SVGInlineTextBox *textBox, int startOffset, const AffineTransform &chunkCtm,
310  const Vector<SVGChar>::iterator &start, const Vector<SVGChar>::iterator &end) = 0;
311 
312  // Followings methods are only used for painting text chunks
313  virtual void start(InlineBox *) = 0;
314  virtual void end(InlineBox *) = 0;
315 
316  virtual bool setupFill(InlineBox *) = 0;
317  virtual bool setupStroke(InlineBox *) = 0;
318 };
319 
320 template<typename CallbackClass>
321 struct SVGTextChunkWalker : public SVGTextChunkWalkerBase {
322 public:
323  typedef void (CallbackClass::*SVGTextChunkWalkerCallback)(SVGInlineTextBox *textBox,
324  int startOffset,
325  const AffineTransform &chunkCtm,
326  const Vector<SVGChar>::iterator &start,
327  const Vector<SVGChar>::iterator &end);
328 
329  // These callbacks are only used for painting!
330  typedef void (CallbackClass::*SVGTextChunkStartCallback)(InlineBox *box);
331  typedef void (CallbackClass::*SVGTextChunkEndCallback)(InlineBox *box);
332 
333  typedef bool (CallbackClass::*SVGTextChunkSetupFillCallback)(InlineBox *box);
334  typedef bool (CallbackClass::*SVGTextChunkSetupStrokeCallback)(InlineBox *box);
335 
336  SVGTextChunkWalker(CallbackClass *object,
337  SVGTextChunkWalkerCallback walker,
338  SVGTextChunkStartCallback start = nullptr,
339  SVGTextChunkEndCallback end = nullptr,
340  SVGTextChunkSetupFillCallback fill = nullptr,
341  SVGTextChunkSetupStrokeCallback stroke = nullptr)
342  : m_object(object)
343  , m_walkerCallback(walker)
344  , m_startCallback(start)
345  , m_endCallback(end)
346  , m_setupFillCallback(fill)
347  , m_setupStrokeCallback(stroke)
348  {
349  ASSERT(object);
350  ASSERT(walker);
351  }
352 
353  virtual void operator()(SVGInlineTextBox *textBox, int startOffset, const AffineTransform &chunkCtm,
354  const Vector<SVGChar>::iterator &start, const Vector<SVGChar>::iterator &end) override
355  {
356  (*m_object.*m_walkerCallback)(textBox, startOffset, chunkCtm, start, end);
357  }
358 
359  // Followings methods are only used for painting text chunks
360  void start(InlineBox *box) override
361  {
362  if (m_startCallback) {
363  (*m_object.*m_startCallback)(box);
364  } else {
365  ASSERT_NOT_REACHED();
366  }
367  }
368 
369  void end(InlineBox *box) override
370  {
371  if (m_endCallback) {
372  (*m_object.*m_endCallback)(box);
373  } else {
374  ASSERT_NOT_REACHED();
375  }
376  }
377 
378  bool setupFill(InlineBox *box) override
379  {
380  if (m_setupFillCallback) {
381  return (*m_object.*m_setupFillCallback)(box);
382  }
383 
384  ASSERT_NOT_REACHED();
385  return false;
386  }
387 
388  bool setupStroke(InlineBox *box) override
389  {
390  if (m_setupStrokeCallback) {
391  return (*m_object.*m_setupStrokeCallback)(box);
392  }
393 
394  ASSERT_NOT_REACHED();
395  return false;
396  }
397 
398 private:
399  CallbackClass *m_object;
400  SVGTextChunkWalkerCallback m_walkerCallback;
401  SVGTextChunkStartCallback m_startCallback;
402  SVGTextChunkEndCallback m_endCallback;
403  SVGTextChunkSetupFillCallback m_setupFillCallback;
404  SVGTextChunkSetupStrokeCallback m_setupStrokeCallback;
405 };
406 
407 struct SVGTextChunkLayoutInfo {
408  SVGTextChunkLayoutInfo(Vector<SVGTextChunk> &textChunks)
409  : assignChunkProperties(true)
410  , handlingTextPath(false)
411  , svgTextChunks(textChunks)
412  , it(nullptr)
413  {
414  }
415 
416  bool assignChunkProperties : 1;
417  bool handlingTextPath : 1;
418 
419  Vector<SVGTextChunk> &svgTextChunks;
420  Vector<SVGChar>::iterator it;
421 
422  SVGTextChunk chunk;
423 };
424 
425 struct SVGTextDecorationInfo {
426  // ETextDecoration is meant to be used here
427  HashMap<int, RenderObject *> fillServerMap;
428  HashMap<int, RenderObject *> strokeServerMap;
429 };
430 
431 } // namespace WebCore
432 
433 #endif // ENABLE(SVG)
434 #endif // SVGCharacterLayoutInfo_h
QAction * create(StandardAction id, const QObject *recvr, Func slot, QObject *parent)
This file is part of the HTML rendering engine for KDE.
const QList< QKeySequence > & end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:09 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.