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