NS_IMETHODIMP nsSVGForeignObjectFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom *aAttribute, PRInt32 aModType) { if (aNameSpaceID == kNameSpaceID_None) { if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) { nsSVGUtils::InvalidateAndScheduleBoundsUpdate(this); // XXXjwatt: why mark intrinsic widths dirty? can't we just use eResize? RequestReflow(nsIPresShell::eStyleChange); } else if (aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y || aAttribute == nsGkAtoms::transform) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; nsSVGUtils::InvalidateAndScheduleBoundsUpdate(this); } else if (aAttribute == nsGkAtoms::viewBox || aAttribute == nsGkAtoms::preserveAspectRatio) { nsSVGUtils::InvalidateBounds(this); } } return NS_OK; }
void nsSVGForeignObjectFrame::NotifySVGChanged(PRUint32 aFlags) { PRBool reflow = PR_FALSE; if (aFlags & TRANSFORM_CHANGED) { // In an ideal world we would reflow when our CTM changes. This is because // glyph metrics do not necessarily scale uniformly with change in scale // and, as a result, CTM changes may require text to break at different // points. The problem would be how to keep performance acceptable when // e.g. the transform of an ancestor is animated. // We also seem to get some sort of infinite loop post bug 421584 if we // reflow. mCanvasTM = nsnull; if (!(aFlags & SUPPRESS_INVALIDATION)) { UpdateGraphic(); } } else if (aFlags & COORD_CONTEXT_CHANGED) { // Our coordinate context's width/height has changed. If we have a // percentage width/height our dimensions will change so we must reflow. nsSVGForeignObjectElement *fO = static_cast<nsSVGForeignObjectElement*>(mContent); if (fO->mLengthAttributes[nsSVGForeignObjectElement::WIDTH].IsPercentage() || fO->mLengthAttributes[nsSVGForeignObjectElement::HEIGHT].IsPercentage()) { reflow = PR_TRUE; } } if (reflow) { // If we're called while the PresShell is handling reflow events then we // must have been called as a result of the NotifyViewportChange() call in // our nsSVGOuterSVGFrame's Reflow() method. We must not call RequestReflow // at this point (i.e. during reflow) because it could confuse the // PresShell and prevent it from reflowing us properly in future. Besides // that, nsSVGOuterSVGFrame::DidReflow will take care of reflowing us // synchronously, so there's no need. if (!PresContext()->PresShell()->IsReflowLocked()) { UpdateGraphic(); // update mRect before requesting reflow RequestReflow(nsIPresShell::eResize); } } }
NS_IMETHODIMP nsSVGForeignObjectFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom *aAttribute, PRInt32 aModType) { if (aNameSpaceID == kNameSpaceID_None) { if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) { UpdateGraphic(); // update mRect before requesting reflow // XXXjwatt: why mark intrinsic widths dirty? can't we just use eResize? RequestReflow(nsIPresShell::eStyleChange); } else if (aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y || aAttribute == nsGkAtoms::transform) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; UpdateGraphic(); } } return NS_OK; }
void nsSVGForeignObjectFrame::NotifySVGChanged(PRUint32 aFlags) { NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), "Invalidation logic may need adjusting"); bool needNewBounds = false; // i.e. mRect or visual overflow rect bool needReflow = false; bool needNewCanvasTM = false; if (aFlags & COORD_CONTEXT_CHANGED) { nsSVGForeignObjectElement *fO = static_cast<nsSVGForeignObjectElement*>(mContent); // Coordinate context changes affect mCanvasTM if we have a // percentage 'x' or 'y' if (fO->mLengthAttributes[nsSVGForeignObjectElement::X].IsPercentage() || fO->mLengthAttributes[nsSVGForeignObjectElement::Y].IsPercentage()) { needNewBounds = true; needNewCanvasTM = true; } // Our coordinate context's width/height has changed. If we have a // percentage width/height our dimensions will change so we must reflow. if (fO->mLengthAttributes[nsSVGForeignObjectElement::WIDTH].IsPercentage() || fO->mLengthAttributes[nsSVGForeignObjectElement::HEIGHT].IsPercentage()) { needNewBounds = true; needReflow = true; } } if (aFlags & TRANSFORM_CHANGED) { needNewBounds = true; // needed if it was _our_ transform that changed needNewCanvasTM = true; // In an ideal world we would reflow when our CTM changes. This is because // glyph metrics do not necessarily scale uniformly with change in scale // and, as a result, CTM changes may require text to break at different // points. The problem would be how to keep performance acceptable when // e.g. the transform of an ancestor is animated. // We also seem to get some sort of infinite loop post bug 421584 if we // reflow. } if (needNewBounds && !(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS)) { nsSVGUtils::InvalidateAndScheduleBoundsUpdate(this); } // If we're called while the PresShell is handling reflow events then we // must have been called as a result of the NotifyViewportChange() call in // our nsSVGOuterSVGFrame's Reflow() method. We must not call RequestReflow // at this point (i.e. during reflow) because it could confuse the // PresShell and prevent it from reflowing us properly in future. Besides // that, nsSVGOuterSVGFrame::DidReflow will take care of reflowing us // synchronously, so there's no need. if (needReflow && !PresContext()->PresShell()->IsReflowLocked()) { RequestReflow(nsIPresShell::eResize); } if (needNewCanvasTM) { // Do this after calling InvalidateAndScheduleBoundsUpdate in case we // change the code and it needs to use it. mCanvasTM = nsnull; } }