NS_IMETHODIMP nsSVGInnerSVGFrame::AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) { if (aNameSpaceID == kNameSpaceID_None && !(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { SVGSVGElement* content = static_cast<SVGSVGElement*>(mContent); if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) { nsSVGEffects::InvalidateRenderingObservers(this); nsSVGUtils::ScheduleReflowSVG(this); if (content->HasViewBoxOrSyntheticViewBox()) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nullptr; content->ChildrenOnlyTransformChanged(); nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED); } else { uint32_t flags = COORD_CONTEXT_CHANGED; if (mCanvasTM && mCanvasTM->IsSingular()) { mCanvasTM = nullptr; flags |= TRANSFORM_CHANGED; } nsSVGUtils::NotifyChildrenOfSVGChange(this, flags); } } else if (aAttribute == nsGkAtoms::transform || aAttribute == nsGkAtoms::preserveAspectRatio || aAttribute == nsGkAtoms::viewBox || aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nullptr; nsSVGUtils::NotifyChildrenOfSVGChange( this, aAttribute == nsGkAtoms::viewBox ? TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED : TRANSFORM_CHANGED); if (aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y) { nsSVGEffects::InvalidateRenderingObservers(this); nsSVGUtils::ScheduleReflowSVG(this); } else if (aAttribute == nsGkAtoms::transform) { nsSVGUtils::InvalidateBounds(this, false); nsSVGUtils::ScheduleReflowSVG(this); } else if (aAttribute == nsGkAtoms::viewBox || (aAttribute == nsGkAtoms::preserveAspectRatio && content->HasViewBoxOrSyntheticViewBox())) { nsSVGUtils::InvalidateBounds(this, false); nsSVGUtils::ScheduleReflowSVG(this); content->ChildrenOnlyTransformChanged(); } } } return NS_OK; }
void nsSVGOuterSVGFrame::NotifyViewportOrTransformChanged(uint32_t aFlags) { NS_ABORT_IF_FALSE(aFlags && !(aFlags & ~(COORD_CONTEXT_CHANGED | TRANSFORM_CHANGED | FULL_ZOOM_CHANGED)), "Unexpected aFlags value"); // No point in doing anything when were not init'ed yet: if (!mViewportInitialized) { return; } SVGSVGElement *content = static_cast<SVGSVGElement*>(mContent); if (aFlags & COORD_CONTEXT_CHANGED) { if (content->HasViewBoxRect()) { // Percentage lengths on children resolve against the viewBox rect so we // don't need to notify them of the viewport change, but the viewBox // transform will have changed, so we need to notify them of that instead. aFlags = TRANSFORM_CHANGED; } else if (content->ShouldSynthesizeViewBox()) { // In the case of a synthesized viewBox, the synthetic viewBox's rect // changes as the viewport changes. As a result we need to maintain the // COORD_CONTEXT_CHANGED flag. aFlags |= TRANSFORM_CHANGED; } else if (mCanvasTM && mCanvasTM->IsSingular()) { // A width/height of zero will result in us having a singular mCanvasTM // even when we don't have a viewBox. So we also want to recompute our // mCanvasTM for this width/height change even though we don't have a // viewBox. aFlags |= TRANSFORM_CHANGED; } } bool haveNonFulLZoomTransformChange = (aFlags & TRANSFORM_CHANGED); if (aFlags & FULL_ZOOM_CHANGED) { // Convert FULL_ZOOM_CHANGED to TRANSFORM_CHANGED: aFlags = (aFlags & ~FULL_ZOOM_CHANGED) | TRANSFORM_CHANGED; } if (aFlags & TRANSFORM_CHANGED) { // Make sure our canvas transform matrix gets (lazily) recalculated: mCanvasTM = nullptr; if (haveNonFulLZoomTransformChange && !(mState & NS_FRAME_IS_NONDISPLAY)) { uint32_t flags = (mState & NS_FRAME_IN_REFLOW) ? SVGSVGElement::eDuringReflow : 0; content->ChildrenOnlyTransformChanged(flags); } } nsSVGUtils::NotifyChildrenOfSVGChange(GetFirstPrincipalChild(), aFlags); }
nsresult nsSVGInnerSVGFrame::AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) { if (aNameSpaceID == kNameSpaceID_None && !(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) { SVGSVGElement* content = static_cast<SVGSVGElement*>(mContent); if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) { nsSVGEffects::InvalidateRenderingObservers(this); nsSVGUtils::ScheduleReflowSVG(this); if (content->HasViewBoxOrSyntheticViewBox()) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nullptr; content->ChildrenOnlyTransformChanged(); nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED); } else { uint32_t flags = COORD_CONTEXT_CHANGED; if (mCanvasTM && mCanvasTM->IsSingular()) { mCanvasTM = nullptr; flags |= TRANSFORM_CHANGED; } nsSVGUtils::NotifyChildrenOfSVGChange(this, flags); } } else if (aAttribute == nsGkAtoms::transform || aAttribute == nsGkAtoms::preserveAspectRatio || aAttribute == nsGkAtoms::viewBox || aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nullptr; nsSVGUtils::NotifyChildrenOfSVGChange( this, aAttribute == nsGkAtoms::viewBox ? TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED : TRANSFORM_CHANGED); // We don't invalidate for transform changes (the layers code does that). // Also note that SVGTransformableElement::GetAttributeChangeHint will // return nsChangeHint_UpdateOverflow for "transform" attribute changes // and cause DoApplyRenderingChangeToTree to make the SchedulePaint call. if (aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y) { nsSVGEffects::InvalidateRenderingObservers(this); nsSVGUtils::ScheduleReflowSVG(this); } else if (aAttribute == nsGkAtoms::viewBox || (aAttribute == nsGkAtoms::preserveAspectRatio && content->HasViewBoxOrSyntheticViewBox())) { content->ChildrenOnlyTransformChanged(); // SchedulePaint sets a global state flag so we only need to call it once // (on ourself is fine), not once on each child (despite bug 828240). SchedulePaint(); } } } return NS_OK; }