📄 renderpath.cpp
字号:
/* Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005, 2008 Rob Buis <buis@kde.org> 2005, 2007 Eric Seidel <eric@webkit.org> This file is part of the KDE project This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License aint with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/#include "config.h"#if ENABLE(SVG)#include "RenderPath.h"#include "FloatPoint.h"#include "FloatQuad.h"#include "GraphicsContext.h"#include "PointerEventsHitRules.h"#include "RenderSVGContainer.h"#include "StrokeStyleApplier.h"#include "SVGPaintServer.h"#include "SVGRenderSupport.h"#include "SVGResourceFilter.h"#include "SVGResourceMarker.h"#include "SVGResourceMasker.h"#include "SVGStyledTransformableElement.h"#include "SVGTransformList.h"#include "SVGURIReference.h"#include <wtf/MathExtras.h>namespace WebCore {class BoundingRectStrokeStyleApplier : public StrokeStyleApplier {public: BoundingRectStrokeStyleApplier(const RenderObject* object, RenderStyle* style) : m_object(object) , m_style(style) { ASSERT(style); ASSERT(object); } void strokeStyle(GraphicsContext* gc) { applyStrokeStyleToContext(gc, m_style, m_object); }private: const RenderObject* m_object; RenderStyle* m_style;};// RenderPathRenderPath::RenderPath(SVGStyledTransformableElement* node) : RenderObject(node){}TransformationMatrix RenderPath::localTransform() const{ return m_localTransform;}FloatPoint RenderPath::mapAbsolutePointToLocal(const FloatPoint& point) const{ // FIXME: does it make sense to map incoming points with the inverse of the // absolute transform? double localX; double localY; absoluteTransform().inverse().map(point.x(), point.y(), localX, localY); return FloatPoint::narrowPrecision(localX, localY);}bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const{ if (m_path.isEmpty()) return false; if (requiresFill && !SVGPaintServer::fillPaintServer(style(), this)) return false; return m_path.contains(point, style()->svgStyle()->fillRule());}bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const{ if (m_path.isEmpty()) return false; if (requiresStroke && !SVGPaintServer::strokePaintServer(style(), this)) return false; BoundingRectStrokeStyleApplier strokeStyle(this, style()); return m_path.strokeContains(&strokeStyle, point);}FloatRect RenderPath::relativeBBox(bool includeStroke) const{ if (m_path.isEmpty()) return FloatRect(); if (includeStroke) { if (m_strokeBbox.isEmpty()) { if (style()->svgStyle()->hasStroke()) { BoundingRectStrokeStyleApplier strokeStyle(this, style()); m_strokeBbox = m_path.strokeBoundingRect(&strokeStyle); } else { if (m_fillBBox.isEmpty()) m_fillBBox = m_path.boundingRect(); m_strokeBbox = m_fillBBox; } } return m_strokeBbox; } if (m_fillBBox.isEmpty()) m_fillBBox = m_path.boundingRect(); return m_fillBBox;}void RenderPath::setPath(const Path& newPath){ m_path = newPath; m_strokeBbox = FloatRect(); m_fillBBox = FloatRect();}const Path& RenderPath::path() const{ return m_path;}bool RenderPath::calculateLocalTransform(){ TransformationMatrix oldTransform = m_localTransform; m_localTransform = static_cast<SVGStyledTransformableElement*>(node())->animatedLocalTransform(); return (m_localTransform != oldTransform);}void RenderPath::layout(){ // FIXME: using m_absoluteBounds breaks if containerForRepaint() is not the root LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout(), &m_absoluteBounds); calculateLocalTransform(); setPath(static_cast<SVGStyledTransformableElement*>(node())->toPathData()); m_absoluteBounds = absoluteClippedOverflowRect(); repainter.repaintAfterLayout(); setNeedsLayout(false);}IntRect RenderPath::clippedOverflowRectForRepaint(RenderBoxModelObject* /*repaintContainer*/){ // FIXME: handle non-root repaintContainer FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true)); // Markers can expand the bounding box repaintRect.unite(m_markerBounds);#if ENABLE(SVG_FILTERS) // Filters can expand the bounding box SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter()); if (filter) repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));#endif if (!repaintRect.isEmpty()) repaintRect.inflate(1); // inflate 1 pixel for antialiasing return enclosingIntRect(repaintRect);}int RenderPath::lineHeight(bool, bool) const{ return relativeBBox(true).height();}int RenderPath::baselinePosition(bool, bool) const{ return relativeBBox(true).height();}static inline void fillAndStrokePath(const Path& path, GraphicsContext* context, RenderStyle* style, RenderPath* object){ context->beginPath(); SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(style, object); if (fillPaintServer) { context->addPath(path); fillPaintServer->draw(context, object, ApplyToFillTargetType); } SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(style, object); if (strokePaintServer) { context->addPath(path); // path is cleared when filled. strokePaintServer->draw(context, object, ApplyToStrokeTargetType); }}void RenderPath::paint(PaintInfo& paintInfo, int, int){ if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || m_path.isEmpty()) return; paintInfo.context->save(); paintInfo.context->concatCTM(localTransform()); SVGResourceFilter* filter = 0; FloatRect boundingBox = relativeBBox(true); if (paintInfo.phase == PaintPhaseForeground) { PaintInfo savedInfo(paintInfo); prepareToRenderSVGContent(this, paintInfo, boundingBox, filter); if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES) paintInfo.context->setShouldAntialias(false); fillAndStrokePath(m_path, paintInfo.context, style(), this); if (static_cast<SVGStyledElement*>(node())->supportsMarkers()) m_markerBounds = drawMarkersIfNeeded(paintInfo.context, paintInfo.rect, m_path);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -