/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Main header first: #include"SVGForeignObjectFrame.h"
void SVGForeignObjectFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) {
NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::foreignObject), "Content is not an SVG foreignObject!");
nsresult SVGForeignObjectFrame::AttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute,
int32_t aModType) { if (aNameSpaceID == kNameSpaceID_None) { if (aAttribute == nsGkAtoms::transform) { // 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.
mCanvasTM = nullptr;
} elseif (aAttribute == nsGkAtoms::viewBox ||
aAttribute == nsGkAtoms::preserveAspectRatio) {
nsLayoutUtils::PostRestyleEvent(
mContent->AsElement(), RestyleHint{0},
nsChangeHint_InvalidateRenderingObservers);
}
}
void SVGForeignObjectFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
MOZ_ASSERT(!HasAnyStateBits(NS_FRAME_IS_NONDISPLAY), "Should not have been called");
// Only InvalidateAndScheduleBoundsUpdate marks us with NS_FRAME_IS_DIRTY, // so if that bit is still set we still have a resize pending. If we hit // this assertion, then we should get the presShell to skip reflow roots // that have a dirty parent since a reflow is going to come via the // reflow root's parent anyway.
NS_ASSERTION(!HasAnyStateBits(NS_FRAME_IS_DIRTY), "Reflowing while a resize is pending is wasteful");
// ReflowSVG makes sure mRect is up to date before we're called.
NS_ASSERTION(!aReflowInput.mParentReflowInput, "should only get reflow from being reflow root");
NS_ASSERTION(aReflowInput.ComputedSize() == GetLogicalSize(), "reflow roots should be reflowed at existing size and " "svg.css should ensure we have no padding/border/margin");
void SVGForeignObjectFrame::PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform,
imgDrawingParams& aImgParams) {
NS_ASSERTION(HasAnyStateBits(NS_FRAME_IS_NONDISPLAY), "Only painting of non-display SVG should take this code path");
if (IsDisabled()) { return;
}
nsIFrame* kid = PrincipalChildList().FirstChild(); if (!kid) { return;
}
if (aTransform.IsSingular()) {
NS_WARNING("Can't render foreignObject element!"); return;
}
gfxClipAutoSaveRestore autoSaveClip(&aContext);
if (StyleDisplay()->IsScrollableOverflow()) { float x, y, width, height;
SVGGeometryProperty::ResolveAll<SVGT::X, SVGT::Y, SVGT::Width,
SVGT::Height>( static_cast<SVGElement*>(GetContent()), &x, &y, &width, &height);
// SVG paints in CSS px, but normally frames paint in dev pixels. Here we // multiply a CSS-px-to-dev-pixel factor onto aTransform so our children // paint correctly. float cssPxPerDevPx = nsPresContext::AppUnitsToFloatCSSPixels(
PresContext()->AppUnitsPerDevPixel());
gfxMatrix canvasTMForChildren = aTransform;
canvasTMForChildren.PreScale(cssPxPerDevPx, cssPxPerDevPx);
// If mRect's width or height are negative, reflow blows up! We must clamp! if (w < 0.0f) {
w = 0.0f;
} if (h < 0.0f) {
h = 0.0f;
}
mRect = nsLayoutUtils::RoundGfxRectToAppRect(gfxRect(x, y, w, h),
AppUnitsPerCSSPixel());
// Fully mark our kid dirty so that it gets resized if necessary // (NS_FRAME_HAS_DIRTY_CHILDREN isn't enough in that case):
nsIFrame* kid = PrincipalChildList().FirstChild();
kid->MarkSubtreeDirty();
// Make sure to not allow interrupts if we're not being reflown as a root:
nsPresContext::InterruptPreventer noInterrupts(PresContext());
DoReflow();
if (HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) { // Make sure we have our filter property (if any) before calling // FinishAndStoreOverflow (subsequent filter changes are handled off // nsChangeHint_UpdateEffects):
SVGObserverUtils::UpdateEffects(this);
}
// If we have a filter, we need to invalidate ourselves because filter // output can change even if none of our descendants need repainting. if (StyleEffects()->HasFilters()) {
InvalidateFrame();
}
// Now unset the various reflow bits:
RemoveStateBits(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
NS_FRAME_HAS_DIRTY_CHILDREN);
}
void SVGForeignObjectFrame::NotifySVGChanged(uint32_t aFlags) {
MOZ_ASSERT(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), "Invalidation logic may need adjusting");
bool needNewBounds = false; // i.e. mRect or ink overflow rect bool needReflow = false; bool needNewCanvasTM = false;
if (aFlags & COORD_CONTEXT_CHANGED) { // Coordinate context changes affect mCanvasTM if we have a // percentage 'x' or 'y' if (StyleSVGReset()->mX.HasPercent() || StyleSVGReset()->mY.HasPercent()) {
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 (StylePosition()->GetWidth().HasPercent() ||
StylePosition()->GetHeight().HasPercent()) {
needNewBounds = true;
needReflow = true;
}
}
if (aFlags & TRANSFORM_CHANGED) { if (mCanvasTM && mCanvasTM->IsSingular()) {
needNewBounds = true; // old bounds are bogus
}
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) { // Ancestor changes can't affect how we render from the perspective of // any rendering observers that we may have, so we don't need to // invalidate them. We also don't need to invalidate ourself, since our // changed ancestor will have invalidated its entire area, which includes // our area.
SVGUtils::ScheduleReflowSVG(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 SVGOuterSVGFrame'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, SVGOuterSVGFrame::DidReflow will take care of reflowing us // synchronously, so there's no need. if (needReflow && !PresShell()->IsReflowLocked()) {
RequestReflow(IntrinsicDirty::None);
}
if (needNewCanvasTM) { // Do this after calling InvalidateAndScheduleBoundsUpdate in case we // change the code and it needs to use it.
mCanvasTM = nullptr;
}
}
void SVGForeignObjectFrame::RequestReflow(IntrinsicDirty aType) { if (HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) { // If we haven't had a ReflowSVG() yet, nothing to do. return;
}
nsIFrame* kid = PrincipalChildList().FirstChild(); if (!kid) { return;
}
void SVGForeignObjectFrame::DoReflow() {
MarkInReflow(); // Skip reflow if we're zero-sized, unless this is our first reflow. if (IsDisabled() && !HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) { return;
}
// We don't use mRect.height above because that tells the child to do // page/column breaking at that height.
NS_ASSERTION(
reflowInput.ComputedPhysicalBorderPadding() == nsMargin(0, 0, 0, 0) &&
reflowInput.ComputedPhysicalMargin() == nsMargin(0, 0, 0, 0), "style system should ensure that :-moz-svg-foreign-content " "does not get styled");
NS_ASSERTION(reflowInput.ComputedISize() == ISize(wm), "reflow input made child wrong size");
reflowInput.SetComputedBSize(BSize(wm));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.