nsresult nsSVGMarkerFrame::PaintMark(gfxContext& aContext, const gfxMatrix& aToMarkedFrameUserSpace, nsSVGPathGeometryFrame *aMarkedFrame, nsSVGMark *aMark, float aStrokeWidth) { // If the flag is set when we get here, it means this marker frame // has already been used painting the current mark, and the document // has a marker reference loop. if (mInUse) return NS_OK; AutoMarkerReferencer markerRef(this, aMarkedFrame); SVGMarkerElement *marker = static_cast<SVGMarkerElement*>(mContent); if (!marker->HasValidDimensions()) { return NS_OK; } const nsSVGViewBoxRect viewBox = marker->GetViewBoxRect(); if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) { // We must disable rendering if the viewBox width or height are zero. return NS_OK; } mStrokeWidth = aStrokeWidth; mX = aMark->x; mY = aMark->y; mAutoAngle = aMark->angle; mIsStart = aMark->type == nsSVGMark::eStart; Matrix viewBoxTM = marker->GetViewBoxTransform(); Matrix markerTM = marker->GetMarkerTransform(mStrokeWidth, mX, mY, mAutoAngle, mIsStart); gfxMatrix markTM = ThebesMatrix(viewBoxTM) * ThebesMatrix(markerTM) * aToMarkedFrameUserSpace; if (StyleDisplay()->IsScrollableOverflow()) { aContext.Save(); gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, viewBox.x, viewBox.y, viewBox.width, viewBox.height); nsSVGUtils::SetClipRect(&aContext, markTM, clipRect); } nsIFrame* kid = GetAnonymousChildFrame(this); nsISVGChildFrame* SVGFrame = do_QueryFrame(kid); // The CTM of each frame referencing us may be different. SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED); nsSVGUtils::PaintFrameWithEffects(kid, aContext, markTM); if (StyleDisplay()->IsScrollableOverflow()) aContext.Restore(); return NS_OK; }
SVGBBox nsSVGMarkerFrame::GetMarkBBoxContribution(const Matrix &aToBBoxUserspace, uint32_t aFlags, nsSVGPathGeometryFrame *aMarkedFrame, const nsSVGMark *aMark, float aStrokeWidth) { SVGBBox bbox; // If the flag is set when we get here, it means this marker frame // has already been used in calculating the current mark bbox, and // the document has a marker reference loop. if (mInUse) return bbox; AutoMarkerReferencer markerRef(this, aMarkedFrame); SVGMarkerElement *content = static_cast<SVGMarkerElement*>(mContent); if (!content->HasValidDimensions()) { return bbox; } const nsSVGViewBoxRect viewBox = content->GetViewBoxRect(); if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) { return bbox; } mStrokeWidth = aStrokeWidth; mX = aMark->x; mY = aMark->y; mAutoAngle = aMark->angle; mIsStart = aMark->type == nsSVGMark::eStart; Matrix markerTM = content->GetMarkerTransform(mStrokeWidth, mX, mY, mAutoAngle, mIsStart); Matrix viewBoxTM = content->GetViewBoxTransform(); Matrix tm = viewBoxTM * markerTM * aToBBoxUserspace; nsISVGChildFrame* child = do_QueryFrame(GetAnonymousChildFrame(this)); // When we're being called to obtain the invalidation area, we need to // pass down all the flags so that stroke is included. However, once DOM // getBBox() accepts flags, maybe we should strip some of those here? // We need to include zero width/height vertical/horizontal lines, so we have // to use UnionEdges. bbox.UnionEdges(child->GetBBoxContribution(tm, aFlags)); return bbox; }