15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGPathByteStreamBuilder.h" 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGPathSeg.h" 255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/OwnPtr.h" 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Helper class that coalesces writes to a SVGPathByteStream to a local buffer. 3009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class CoalescingBuffer { 3109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)public: 3209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer(SVGPathByteStream* byteStream) 3309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) : m_currentOffset(0) 3409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_byteStream(byteStream) 3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 3609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(byteStream); 3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ~CoalescingBuffer() 3909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 4009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (size_t i = 0; i < m_currentOffset; ++i) 4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_byteStream->append(m_bytes[i]); 4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 4309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 4409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) template<typename DataType> 4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void writeType(DataType value) 4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ByteType<DataType> data; 4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) data.value = value; 4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t typeSize = sizeof(ByteType<DataType>); 5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(m_currentOffset + typeSize <= sizeof(m_bytes)); 5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) memcpy(m_bytes + m_currentOffset, data.bytes, typeSize); 5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_currentOffset += typeSize; 5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void writeFlag(bool value) { writeType<bool>(value); } 5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void writeFloat(float value) { writeType<float>(value); } 5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void writeFloatPoint(const FloatPoint& point) 5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) { 5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) writeType<float>(point.x()); 6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) writeType<float>(point.y()); 6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void writeSegmentType(unsigned short value) { writeType<unsigned short>(value); } 6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)private: 6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Adjust size to fit the largest command (in serialized/byte-stream format). 6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Currently a cubic segment. 6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t m_currentOffset; 6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) unsigned char m_bytes[sizeof(unsigned short) + sizeof(FloatPoint) * 3]; 6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) SVGPathByteStream* m_byteStream; 7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}; 7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SVGPathByteStreamBuilder::SVGPathByteStreamBuilder() 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_byteStream(0) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::moveTo(const FloatPoint& targetPoint, bool, PathCoordinateMode mode) 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegMoveToRel : PathSegMoveToAbs); 8109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(targetPoint); 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::lineTo(const FloatPoint& targetPoint, PathCoordinateMode mode) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegLineToRel : PathSegLineToAbs); 8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(targetPoint); 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::lineToHorizontal(float x, PathCoordinateMode mode) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegLineToHorizontalRel : PathSegLineToHorizontalAbs); 9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloat(x); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::lineToVertical(float y, PathCoordinateMode mode) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 10009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegLineToVerticalRel : PathSegLineToVerticalAbs); 10209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloat(y); 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::curveToCubic(const FloatPoint& point1, const FloatPoint& point2, const FloatPoint& targetPoint, PathCoordinateMode mode) 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegCurveToCubicRel : PathSegCurveToCubicAbs); 10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(point1); 11009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(point2); 11109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(targetPoint); 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::curveToCubicSmooth(const FloatPoint& point2, const FloatPoint& targetPoint, PathCoordinateMode mode) 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 11609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 11709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegCurveToCubicSmoothRel : PathSegCurveToCubicSmoothAbs); 11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(point2); 11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(targetPoint); 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::curveToQuadratic(const FloatPoint& point1, const FloatPoint& targetPoint, PathCoordinateMode mode) 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 12409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegCurveToQuadraticRel : PathSegCurveToQuadraticAbs); 12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(point1); 12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(targetPoint); 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::curveToQuadraticSmooth(const FloatPoint& targetPoint, PathCoordinateMode mode) 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 13209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 13309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegCurveToQuadraticSmoothRel : PathSegCurveToQuadraticSmoothAbs); 13409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(targetPoint); 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::arcTo(float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag, const FloatPoint& targetPoint, PathCoordinateMode mode) 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 13909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(mode == RelativeCoordinates ? PathSegArcRel : PathSegArcAbs); 14109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloat(r1); 14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloat(r2); 14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloat(angle); 14409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFlag(largeArcFlag); 14509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFlag(sweepFlag); 14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeFloatPoint(targetPoint); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGPathByteStreamBuilder::closePath() 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoalescingBuffer buffer(m_byteStream); 15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) buffer.writeSegmentType(PathSegClosePath); 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 156