Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
      3  * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann (at) kde.org>
      4  * Copyright (C) 2004, 2005, 2008 Rob Buis <buis (at) kde.org>
      5  * Copyright (C) 2005, 2007 Eric Seidel <eric (at) webkit.org>
      6  * Copyright (C) 2009 Google, Inc.
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  */
     23 
     24 #include "config.h"
     25 
     26 #if ENABLE(SVG)
     27 #include "SVGMarkerLayoutInfo.h"
     28 
     29 #include "RenderSVGResourceMarker.h"
     30 
     31 namespace WebCore {
     32 
     33 SVGMarkerLayoutInfo::SVGMarkerLayoutInfo()
     34     : m_midMarker(0)
     35     , m_elementIndex(0)
     36     , m_strokeWidth(0)
     37 {
     38 }
     39 
     40 SVGMarkerLayoutInfo::~SVGMarkerLayoutInfo()
     41 {
     42 }
     43 
     44 static inline void processStartAndMidMarkers(void* infoPtr, const PathElement* element)
     45 {
     46     SVGMarkerLayoutInfo& info = *reinterpret_cast<SVGMarkerLayoutInfo*>(infoPtr);
     47     SVGMarkerData& markerData = info.markerData();
     48     int& elementIndex = info.elementIndex();
     49 
     50     // First update the outslope for the previous element
     51     markerData.updateOutslope(element->points[0]);
     52 
     53     // Draw the marker for the previous element
     54     RenderSVGResourceMarker* marker = markerData.marker();
     55     if (elementIndex > 0 && marker)
     56         info.addLayoutedMarker(marker, markerData.origin(), markerData.currentAngle());
     57 
     58     // Update our marker data for this element
     59     markerData.updateMarkerDataForPathElement(element);
     60 
     61     // After drawing the start marker, switch to drawing mid markers
     62     if (elementIndex == 1)
     63         markerData.updateTypeAndMarker(SVGMarkerData::Mid, info.midMarker());
     64 
     65     ++elementIndex;
     66 }
     67 
     68 FloatRect SVGMarkerLayoutInfo::calculateBoundaries(RenderSVGResourceMarker* startMarker, RenderSVGResourceMarker* midMarker, RenderSVGResourceMarker* endMarker, float strokeWidth, const Path& path)
     69 {
     70     m_layout.clear();
     71     m_midMarker = midMarker;
     72     m_strokeWidth = strokeWidth;
     73     m_elementIndex = 0;
     74     m_markerData = SVGMarkerData(SVGMarkerData::Start, startMarker);
     75     path.apply(this, processStartAndMidMarkers);
     76 
     77     if (endMarker) {
     78         m_markerData.updateTypeAndMarker(SVGMarkerData::End, endMarker);
     79         addLayoutedMarker(endMarker, m_markerData.origin(), m_markerData.currentAngle());
     80     }
     81 
     82     if (m_layout.isEmpty())
     83         return FloatRect();
     84 
     85     Vector<MarkerLayout>::iterator it = m_layout.begin();
     86     Vector<MarkerLayout>::iterator end = m_layout.end();
     87 
     88     FloatRect bounds;
     89     for (; it != end; ++it) {
     90         MarkerLayout& layout = *it;
     91 
     92         RenderSVGResourceMarker* markerContent = layout.marker;
     93         ASSERT(markerContent);
     94 
     95         bounds.unite(markerContent->markerBoundaries(layout.matrix));
     96     }
     97 
     98     return bounds;
     99 }
    100 
    101 void SVGMarkerLayoutInfo::clear()
    102 {
    103     m_midMarker = 0;
    104     m_elementIndex = 0;
    105     m_strokeWidth = 0;
    106     m_markerData.updateTypeAndMarker(SVGMarkerData::Unknown, 0);
    107     m_layout.clear();
    108 }
    109 
    110 void SVGMarkerLayoutInfo::drawMarkers(PaintInfo& paintInfo)
    111 {
    112     if (m_layout.isEmpty())
    113         return;
    114 
    115     Vector<MarkerLayout>::iterator it = m_layout.begin();
    116     Vector<MarkerLayout>::iterator end = m_layout.end();
    117 
    118     for (; it != end; ++it) {
    119         MarkerLayout& layout = *it;
    120         layout.marker->draw(paintInfo, layout.matrix);
    121     }
    122 }
    123 
    124 void SVGMarkerLayoutInfo::addLayoutedMarker(RenderSVGResourceMarker* marker, const FloatPoint& origin, float angle)
    125 {
    126     ASSERT(marker);
    127     m_layout.append(MarkerLayout(marker, marker->markerTransformation(origin, angle, m_strokeWidth)));
    128 }
    129 
    130 }
    131 
    132 #endif // ENABLE(SVG)
    133