Home | History | Annotate | Download | only in svg
      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 blink {
     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 blink
    156