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: 32 CoalescingBuffer(SVGPathByteStream* byteStream) 33 : m_currentOffset(0) 34 , m_byteStream(byteStream) 35 { 36 ASSERT(byteStream); 37 } 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> 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 55 void writeFlag(bool value) { writeType<bool>(value); } 56 void writeFloat(float value) { writeType<float>(value); } 57 void writeFloatPoint(const FloatPoint& point) 58 { 59 writeType<float>(point.x()); 60 writeType<float>(point.y()); 61 } 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 72 SVGPathByteStreamBuilder::SVGPathByteStreamBuilder() 73 : m_byteStream(0) 74 { 75 } 76 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 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 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 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 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 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 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 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 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 149 void SVGPathByteStreamBuilder::closePath() 150 { 151 CoalescingBuffer buffer(m_byteStream); 152 buffer.writeSegmentType(PathSegClosePath); 153 } 154 155 } // namespace WebCore 156