Home | History | Annotate | Download | only in rendering
      1 /*
      2     Copyright (C) Research In Motion Limited 2010. All rights reserved.
      3                   2004, 2005, 2007 Nikolas Zimmermann <zimmermann (at) kde.org>
      4                   2004, 2005, 2008 Rob Buis <buis (at) kde.org>
      5                   2005, 2007 Eric Seidel <eric (at) webkit.org>
      6                   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     aint 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 "RenderSVGViewportContainer.h"
     30 #include "SVGResourceMarker.h"
     31 
     32 namespace WebCore {
     33 
     34 SVGMarkerLayoutInfo::SVGMarkerLayoutInfo()
     35     : m_midMarker(0)
     36     , m_elementIndex(0)
     37     , m_strokeWidth(0)
     38 {
     39 }
     40 
     41 SVGMarkerLayoutInfo::~SVGMarkerLayoutInfo()
     42 {
     43 }
     44 
     45 static inline void processStartAndMidMarkers(void* infoPtr, const PathElement* element)
     46 {
     47     SVGMarkerLayoutInfo& info = *reinterpret_cast<SVGMarkerLayoutInfo*>(infoPtr);
     48     SVGMarkerData& markerData = info.markerData();
     49     int& elementIndex = info.elementIndex();
     50 
     51     // First update the outslope for the previous element
     52     markerData.updateOutslope(element->points[0]);
     53 
     54     // Draw the marker for the previous element
     55     SVGResourceMarker* marker = markerData.marker();
     56     if (elementIndex > 0 && marker)
     57         info.addLayoutedMarker(marker, markerData.origin(), markerData.currentAngle());
     58 
     59     // Update our marker data for this element
     60     markerData.updateMarkerDataForPathElement(element);
     61 
     62     // After drawing the start marker, switch to drawing mid markers
     63     if (elementIndex == 1)
     64         markerData.updateTypeAndMarker(SVGMarkerData::Mid, info.midMarker());
     65 
     66     ++elementIndex;
     67 }
     68 
     69 FloatRect SVGMarkerLayoutInfo::calculateBoundaries(SVGResourceMarker* startMarker, SVGResourceMarker* midMarker, SVGResourceMarker* endMarker, float strokeWidth, const Path& path)
     70 {
     71     m_layout.clear();
     72     m_midMarker = midMarker;
     73     m_strokeWidth = strokeWidth;
     74     m_elementIndex = 0;
     75     m_markerData = SVGMarkerData(SVGMarkerData::Start, startMarker);
     76     path.apply(this, processStartAndMidMarkers);
     77 
     78     if (endMarker) {
     79         m_markerData.updateTypeAndMarker(SVGMarkerData::End, endMarker);
     80         addLayoutedMarker(endMarker, m_markerData.origin(), m_markerData.currentAngle());
     81     }
     82 
     83     if (m_layout.isEmpty())
     84         return FloatRect();
     85 
     86     Vector<MarkerLayout>::iterator it = m_layout.begin();
     87     Vector<MarkerLayout>::iterator end = m_layout.end();
     88 
     89     FloatRect bounds;
     90     for (; it != end; ++it) {
     91         MarkerLayout& layout = *it;
     92 
     93         RenderSVGViewportContainer* markerContent = layout.marker->renderer();
     94         ASSERT(markerContent);
     95 
     96         bounds.unite(markerContent->markerBoundaries(layout.matrix));
     97     }
     98 
     99     return bounds;
    100 }
    101 
    102 void SVGMarkerLayoutInfo::drawMarkers(RenderObject::PaintInfo& paintInfo)
    103 {
    104     if (m_layout.isEmpty())
    105         return;
    106 
    107     Vector<MarkerLayout>::iterator it = m_layout.begin();
    108     Vector<MarkerLayout>::iterator end = m_layout.end();
    109 
    110     for (; it != end; ++it) {
    111         MarkerLayout& layout = *it;
    112         layout.marker->draw(paintInfo, layout.matrix);
    113     }
    114 }
    115 
    116 void SVGMarkerLayoutInfo::addLayoutedMarker(SVGResourceMarker* marker, const FloatPoint& origin, float angle)
    117 {
    118     ASSERT(marker);
    119     m_layout.append(MarkerLayout(marker, marker->markerTransformation(origin, angle, m_strokeWidth)));
    120 }
    121 
    122 }
    123 
    124 #endif // ENABLE(SVG)
    125