📄 renderpath.cpp
字号:
finishRenderSVGContent(this, paintInfo, boundingBox, filter, savedInfo.context); } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth()) paintOutline(paintInfo.context, static_cast<int>(boundingBox.x()), static_cast<int>(boundingBox.y()), static_cast<int>(boundingBox.width()), static_cast<int>(boundingBox.height()), style()); paintInfo.context->restore();}void RenderPath::addFocusRingRects(GraphicsContext* graphicsContext, int, int) { graphicsContext->addFocusRingRect(enclosingIntRect(relativeBBox(true)));}void RenderPath::absoluteRects(Vector<IntRect>& rects, int, int, bool){ rects.append(absoluteClippedOverflowRect());}void RenderPath::absoluteQuads(Vector<FloatQuad>& quads, bool){ quads.append(absoluteClippedOverflowRect());}bool RenderPath::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction){ // We only draw in the forground phase, so we only hit-test then. if (hitTestAction != HitTestForeground) return false; IntPoint absolutePoint(_x, _y); PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { FloatPoint hitPoint = mapAbsolutePointToLocal(absolutePoint); if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke) && strokeContains(hitPoint, hitRules.requireStroke)) || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill) && fillContains(hitPoint, hitRules.requireFill))) { updateHitTestResult(result, absolutePoint); return true; } } return false;}enum MarkerType { Start, Mid, End};struct MarkerData { FloatPoint origin; FloatPoint subpathStart; double strokeWidth; FloatPoint inslopePoints[2]; FloatPoint outslopePoints[2]; MarkerType type; SVGResourceMarker* marker;};struct DrawMarkersData { DrawMarkersData(GraphicsContext*, SVGResourceMarker* startMarker, SVGResourceMarker* midMarker, double strokeWidth); GraphicsContext* context; int elementIndex; MarkerData previousMarkerData; SVGResourceMarker* midMarker;};DrawMarkersData::DrawMarkersData(GraphicsContext* c, SVGResourceMarker *start, SVGResourceMarker *mid, double strokeWidth) : context(c) , elementIndex(0) , midMarker(mid){ previousMarkerData.origin = FloatPoint(); previousMarkerData.subpathStart = FloatPoint(); previousMarkerData.strokeWidth = strokeWidth; previousMarkerData.marker = start; previousMarkerData.type = Start;}static void drawMarkerWithData(GraphicsContext* context, MarkerData &data){ if (!data.marker) return; FloatPoint inslopeChange = data.inslopePoints[1] - FloatSize(data.inslopePoints[0].x(), data.inslopePoints[0].y()); FloatPoint outslopeChange = data.outslopePoints[1] - FloatSize(data.outslopePoints[0].x(), data.outslopePoints[0].y()); double inslope = rad2deg(atan2(inslopeChange.y(), inslopeChange.x())); double outslope = rad2deg(atan2(outslopeChange.y(), outslopeChange.x())); double angle = 0.0; switch (data.type) { case Start: angle = outslope; break; case Mid: angle = (inslope + outslope) / 2; break; case End: angle = inslope; } data.marker->draw(context, FloatRect(), data.origin.x(), data.origin.y(), data.strokeWidth, angle);}static inline void updateMarkerDataForElement(MarkerData& previousMarkerData, const PathElement* element){ FloatPoint* points = element->points; switch (element->type) { case PathElementAddQuadCurveToPoint: // TODO previousMarkerData.origin = points[1]; break; case PathElementAddCurveToPoint: previousMarkerData.inslopePoints[0] = points[1]; previousMarkerData.inslopePoints[1] = points[2]; previousMarkerData.origin = points[2]; break; case PathElementMoveToPoint: previousMarkerData.subpathStart = points[0]; case PathElementAddLineToPoint: previousMarkerData.inslopePoints[0] = previousMarkerData.origin; previousMarkerData.inslopePoints[1] = points[0]; previousMarkerData.origin = points[0]; break; case PathElementCloseSubpath: previousMarkerData.inslopePoints[0] = previousMarkerData.origin; previousMarkerData.inslopePoints[1] = points[0]; previousMarkerData.origin = previousMarkerData.subpathStart; previousMarkerData.subpathStart = FloatPoint(); }}static void drawStartAndMidMarkers(void* info, const PathElement* element){ DrawMarkersData& data = *reinterpret_cast<DrawMarkersData*>(info); int elementIndex = data.elementIndex; MarkerData& previousMarkerData = data.previousMarkerData; FloatPoint* points = element->points; // First update the outslope for the previous element previousMarkerData.outslopePoints[0] = previousMarkerData.origin; previousMarkerData.outslopePoints[1] = points[0]; // Draw the marker for the previous element if (elementIndex != 0) drawMarkerWithData(data.context, previousMarkerData); // Update our marker data for this element updateMarkerDataForElement(previousMarkerData, element); if (elementIndex == 1) { // After drawing the start marker, switch to drawing mid markers previousMarkerData.marker = data.midMarker; previousMarkerData.type = Mid; } data.elementIndex++;}FloatRect RenderPath::drawMarkersIfNeeded(GraphicsContext* context, const FloatRect&, const Path& path) const{ Document* doc = document(); SVGElement* svgElement = static_cast<SVGElement*>(node()); ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); const SVGRenderStyle* svgStyle = style()->svgStyle(); AtomicString startMarkerId(svgStyle->startMarker()); AtomicString midMarkerId(svgStyle->midMarker()); AtomicString endMarkerId(svgStyle->endMarker()); SVGResourceMarker* startMarker = getMarkerById(doc, startMarkerId); SVGResourceMarker* midMarker = getMarkerById(doc, midMarkerId); SVGResourceMarker* endMarker = getMarkerById(doc, endMarkerId); if (!startMarker && !startMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(startMarkerId, styledElement); else if (startMarker) startMarker->addClient(styledElement); if (!midMarker && !midMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(midMarkerId, styledElement); else if (midMarker) midMarker->addClient(styledElement); if (!endMarker && !endMarkerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(endMarkerId, styledElement); else if (endMarker) endMarker->addClient(styledElement); if (!startMarker && !midMarker && !endMarker) return FloatRect(); double strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, svgStyle->strokeWidth(), 1.0f); DrawMarkersData data(context, startMarker, midMarker, strokeWidth); path.apply(&data, drawStartAndMidMarkers); data.previousMarkerData.marker = endMarker; data.previousMarkerData.type = End; drawMarkerWithData(context, data.previousMarkerData); // We know the marker boundaries, only after they're drawn! // Otherwhise we'd need to do all the marker calculation twice // once here (through paint()) and once in absoluteClippedOverflowRect(). FloatRect bounds; if (startMarker) bounds.unite(startMarker->cachedBounds()); if (midMarker) bounds.unite(midMarker->cachedBounds()); if (endMarker) bounds.unite(endMarker->cachedBounds()); return bounds;}IntRect RenderPath::outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/) const{ // FIXME: handle non-root repaintContainer IntRect result = m_absoluteBounds; adjustRectForOutlineAndShadow(result); return result;}}#endif // ENABLE(SVG)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -