gfxMatrix nsSVGForeignObjectFrame::GetTransformMatrix(nsIFrame **aOutAncestor) { NS_PRECONDITION(aOutAncestor, "We need an ancestor to write to!"); /* Set the ancestor to be the outer frame. */ *aOutAncestor = nsSVGUtils::GetOuterSVGFrame(this); NS_ASSERTION(*aOutAncestor, "How did we end up without an outer frame?"); /* Return the matrix back to the root, factoring in the x and y offsets. */ return GetCanvasTMForChildren(); }
gfx3DMatrix nsSVGForeignObjectFrame::GetTransformMatrix(nsIFrame* aAncestor, nsIFrame **aOutAncestor) { NS_PRECONDITION(aOutAncestor, "We need an ancestor to write to!"); /* Set the ancestor to be the outer frame. */ *aOutAncestor = nsSVGUtils::GetOuterSVGFrame(this); NS_ASSERTION(*aOutAncestor, "How did we end up without an outer frame?"); if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) { return gfx3DMatrix::From2D(gfxMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); } /* Return the matrix back to the root, factoring in the x and y offsets. */ return gfx3DMatrix::From2D(GetCanvasTMForChildren()); }
NS_IMETHODIMP nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect) { if (IsDisabled()) return NS_OK; nsIFrame* kid = GetFirstPrincipalChild(); if (!kid) return NS_OK; gfxMatrix matrixForChildren = GetCanvasTMForChildren(); gfxMatrix matrix = GetCanvasTM(); if (matrixForChildren.IsSingular()) { NS_WARNING("Can't render foreignObject element!"); return NS_ERROR_FAILURE; } nsRect kidDirtyRect = kid->GetVisualOverflowRect(); /* Check if we need to draw anything. */ if (aDirtyRect) { // Transform the dirty rect into app units in our userspace. gfxMatrix invmatrix = matrix; invmatrix.Invert(); NS_ASSERTION(!invmatrix.IsSingular(), "inverse of non-singular matrix should be non-singular"); gfxRect transDirtyRect = gfxRect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height); transDirtyRect = invmatrix.TransformBounds(transDirtyRect); kidDirtyRect.IntersectRect(kidDirtyRect, nsLayoutUtils::RoundGfxRectToAppRect(transDirtyRect, PresContext()->AppUnitsPerCSSPixel())); // XXX after bug 614732 is fixed, we will compare mRect with aDirtyRect, // not with kidDirtyRect. I.e. // PRInt32 appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel(); // mRect.ToOutsidePixels(appUnitsPerDevPx).Intersects(*aDirtyRect) if (kidDirtyRect.IsEmpty()) return NS_OK; } gfxContext *gfx = aContext->ThebesContext(); gfx->Save(); if (GetStyleDisplay()->IsScrollableOverflow()) { float x, y, width, height; static_cast<nsSVGElement*>(mContent)-> GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height); nsSVGUtils::SetClipRect(gfx, matrix, clipRect); } gfx->Multiply(matrixForChildren); PRUint32 flags = nsLayoutUtils::PAINT_IN_TRANSFORM; if (SVGAutoRenderState::IsPaintingToWindow(aContext)) { flags |= nsLayoutUtils::PAINT_TO_WINDOW; } nsresult rv = nsLayoutUtils::PaintFrame(aContext, kid, nsRegion(kidDirtyRect), NS_RGBA(0,0,0,0), flags); gfx->Restore(); return rv; }
NS_IMETHODIMP nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext, const nsIntRect *aDirtyRect) { if (IsDisabled()) return NS_OK; nsIFrame* kid = GetFirstChild(nsnull); if (!kid) return NS_OK; gfxMatrix matrixForChildren = GetCanvasTMForChildren(); gfxMatrix matrix = GetCanvasTM(); nsRenderingContext *ctx = aContext->GetRenderingContext(this); if (!ctx || matrixForChildren.IsSingular()) { NS_WARNING("Can't render foreignObject element!"); return NS_ERROR_FAILURE; } /* Check if we need to draw anything. */ if (aDirtyRect) { PRInt32 appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel(); if (!mRect.ToOutsidePixels(appUnitsPerDevPx).Intersects(*aDirtyRect)) return NS_OK; } gfxContext *gfx = aContext->GetGfxContext(); gfx->Save(); if (GetStyleDisplay()->IsScrollableOverflow()) { float x, y, width, height; static_cast<nsSVGElement*>(mContent)-> GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height); nsSVGUtils::SetClipRect(gfx, matrix, clipRect); } gfx->Multiply(matrixForChildren); // Transform the dirty rect into the rectangle containing the // transformed dirty rect. gfxMatrix invmatrix = matrix.Invert(); NS_ASSERTION(!invmatrix.IsSingular(), "inverse of non-singular matrix should be non-singular"); gfxRect transDirtyRect = gfxRect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height); transDirtyRect = invmatrix.TransformBounds(transDirtyRect); transDirtyRect.Scale(nsPresContext::AppUnitsPerCSSPixel()); nsPoint tl(NSToCoordFloor(transDirtyRect.X()), NSToCoordFloor(transDirtyRect.Y())); nsPoint br(NSToCoordCeil(transDirtyRect.XMost()), NSToCoordCeil(transDirtyRect.YMost())); nsRect kidDirtyRect(tl.x, tl.y, br.x - tl.x, br.y - tl.y); kidDirtyRect.IntersectRect(kidDirtyRect, kid->GetRect()); PRUint32 flags = nsLayoutUtils::PAINT_IN_TRANSFORM; if (aContext->IsPaintingToWindow()) { flags |= nsLayoutUtils::PAINT_TO_WINDOW; } nsresult rv = nsLayoutUtils::PaintFrame(ctx, kid, nsRegion(kidDirtyRect), NS_RGBA(0,0,0,0), flags); gfx->Restore(); return rv; }