1 /*
2 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #include "core/svg/SVGPathByteStreamBuilder.h"
23
24 #include "core/svg/SVGPathSeg.h"
25 #include "wtf/OwnPtr.h"
26
27 namespace WebCore {
28
29 // Helper class that coalesces writes to a SVGPathByteStream to a local buffer.
30 class CoalescingBuffer {
31 public:
CoalescingBuffer(SVGPathByteStream * byteStream)32 CoalescingBuffer(SVGPathByteStream* byteStream)
33 : m_currentOffset(0)
34 , m_byteStream(byteStream)
35 {
36 ASSERT(byteStream);
37 }
~CoalescingBuffer()38 ~CoalescingBuffer()
39 {
40 for (size_t i = 0; i < m_currentOffset; ++i)
41 m_byteStream->append(m_bytes[i]);
42 }
43
44 template<typename DataType>
writeType(DataType value)45 void writeType(DataType value)
46 {
47 ByteType<DataType> data;
48 data.value = value;
49 size_t typeSize = sizeof(ByteType<DataType>);
50 ASSERT(m_currentOffset + typeSize <= sizeof(m_bytes));
51 memcpy(m_bytes + m_currentOffset, data.bytes, typeSize);
52 m_currentOffset += typeSize;
53 }
54
writeFlag(bool value)55 void writeFlag(bool value) { writeType<bool>(value); }
writeFloat(float value)56 void writeFloat(float value) { writeType<float>(value); }
writeFloatPoint(const FloatPoint & point)57 void writeFloatPoint(const FloatPoint& point)
58 {
59 writeType<float>(point.x());
60 writeType<float>(point.y());
61 }
writeSegmentType(unsigned short value)62 void writeSegmentType(unsigned short value) { writeType<unsigned short>(value); }
63
64 private:
65 // Adjust size to fit the largest command (in serialized/byte-stream format).
66 // Currently a cubic segment.
67 size_t m_currentOffset;
68 unsigned char m_bytes[sizeof(unsigned short) + sizeof(FloatPoint) * 3];
69 SVGPathByteStream* m_byteStream;
70 };
71
SVGPathByteStreamBuilder()72 SVGPathByteStreamBuilder::SVGPathByteStreamBuilder()
73 : m_byteStream(0)
74 {
75 }
76
moveTo(const FloatPoint & targetPoint,bool,PathCoordinateMode mode)77 void SVGPathByteStreamBuilder::moveTo(const FloatPoint& targetPoint, bool, PathCoordinateMode mode)
78 {
79 CoalescingBuffer buffer(m_byteStream);
80 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegMoveToRel : PathSegMoveToAbs);
81 buffer.writeFloatPoint(targetPoint);
82 }
83
lineTo(const FloatPoint & targetPoint,PathCoordinateMode mode)84 void SVGPathByteStreamBuilder::lineTo(const FloatPoint& targetPoint, PathCoordinateMode mode)
85 {
86 CoalescingBuffer buffer(m_byteStream);
87 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegLineToRel : PathSegLineToAbs);
88 buffer.writeFloatPoint(targetPoint);
89 }
90
lineToHorizontal(float x,PathCoordinateMode mode)91 void SVGPathByteStreamBuilder::lineToHorizontal(float x, PathCoordinateMode mode)
92 {
93 CoalescingBuffer buffer(m_byteStream);
94 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegLineToHorizontalRel : PathSegLineToHorizontalAbs);
95 buffer.writeFloat(x);
96 }
97
lineToVertical(float y,PathCoordinateMode mode)98 void SVGPathByteStreamBuilder::lineToVertical(float y, PathCoordinateMode mode)
99 {
100 CoalescingBuffer buffer(m_byteStream);
101 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegLineToVerticalRel : PathSegLineToVerticalAbs);
102 buffer.writeFloat(y);
103 }
104
curveToCubic(const FloatPoint & point1,const FloatPoint & point2,const FloatPoint & targetPoint,PathCoordinateMode mode)105 void SVGPathByteStreamBuilder::curveToCubic(const FloatPoint& point1, const FloatPoint& point2, const FloatPoint& targetPoint, PathCoordinateMode mode)
106 {
107 CoalescingBuffer buffer(m_byteStream);
108 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegCurveToCubicRel : PathSegCurveToCubicAbs);
109 buffer.writeFloatPoint(point1);
110 buffer.writeFloatPoint(point2);
111 buffer.writeFloatPoint(targetPoint);
112 }
113
curveToCubicSmooth(const FloatPoint & point2,const FloatPoint & targetPoint,PathCoordinateMode mode)114 void SVGPathByteStreamBuilder::curveToCubicSmooth(const FloatPoint& point2, const FloatPoint& targetPoint, PathCoordinateMode mode)
115 {
116 CoalescingBuffer buffer(m_byteStream);
117 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegCurveToCubicSmoothRel : PathSegCurveToCubicSmoothAbs);
118 buffer.writeFloatPoint(point2);
119 buffer.writeFloatPoint(targetPoint);
120 }
121
curveToQuadratic(const FloatPoint & point1,const FloatPoint & targetPoint,PathCoordinateMode mode)122 void SVGPathByteStreamBuilder::curveToQuadratic(const FloatPoint& point1, const FloatPoint& targetPoint, PathCoordinateMode mode)
123 {
124 CoalescingBuffer buffer(m_byteStream);
125 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegCurveToQuadraticRel : PathSegCurveToQuadraticAbs);
126 buffer.writeFloatPoint(point1);
127 buffer.writeFloatPoint(targetPoint);
128 }
129
curveToQuadraticSmooth(const FloatPoint & targetPoint,PathCoordinateMode mode)130 void SVGPathByteStreamBuilder::curveToQuadraticSmooth(const FloatPoint& targetPoint, PathCoordinateMode mode)
131 {
132 CoalescingBuffer buffer(m_byteStream);
133 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegCurveToQuadraticSmoothRel : PathSegCurveToQuadraticSmoothAbs);
134 buffer.writeFloatPoint(targetPoint);
135 }
136
arcTo(float r1,float r2,float angle,bool largeArcFlag,bool sweepFlag,const FloatPoint & targetPoint,PathCoordinateMode mode)137 void SVGPathByteStreamBuilder::arcTo(float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag, const FloatPoint& targetPoint, PathCoordinateMode mode)
138 {
139 CoalescingBuffer buffer(m_byteStream);
140 buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegArcRel : PathSegArcAbs);
141 buffer.writeFloat(r1);
142 buffer.writeFloat(r2);
143 buffer.writeFloat(angle);
144 buffer.writeFlag(largeArcFlag);
145 buffer.writeFlag(sweepFlag);
146 buffer.writeFloatPoint(targetPoint);
147 }
148
closePath()149 void SVGPathByteStreamBuilder::closePath()
150 {
151 CoalescingBuffer buffer(m_byteStream);
152 buffer.writeSegmentType(PathSegClosePath);
153 }
154
155 } // namespace WebCore
156