Skip to content

Commit

Permalink
Bug 1393791 - Move SVG Use anonymous content to the frame. r=emilio
Browse files Browse the repository at this point in the history
This brings it into alignment with what everything else does.

MozReview-Commit-ID: 2A9p8umHnKi
  • Loading branch information
bholley committed Aug 27, 2017
1 parent d3e80c0 commit 9631dd3
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 31 deletions.
41 changes: 23 additions & 18 deletions dom/svg/SVGUseElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "nsIURI.h"
#include "mozilla/URLExtraData.h"
#include "nsSVGEffects.h"
#include "nsSVGUseFrame.h"

NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Use)

Expand Down Expand Up @@ -55,13 +56,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGUseElement,
SVGUseElementBase)
nsAutoScriptBlocker scriptBlocker;
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginal)
tmp->DestroyAnonymousContent();
tmp->UnlinkSource();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGUseElement,
SVGUseElementBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mClone)
tmp->mSource.Traverse(&cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

Expand Down Expand Up @@ -213,11 +212,9 @@ SVGUseElement::NodeWillBeDestroyed(const nsINode *aNode)

//----------------------------------------------------------------------

nsIContent*
already_AddRefed<nsIContent>
SVGUseElement::CreateAnonymousContent()
{
mClone = nullptr;

if (mSource.get()) {
mSource.get()->RemoveMutationObserver(this);
}
Expand Down Expand Up @@ -293,18 +290,17 @@ SVGUseElement::CreateAnonymousContent()
do_AddRef(NodePrincipal()));

targetContent->AddMutationObserver(this);
mClone = newcontent;

#ifdef DEBUG
// Our anonymous clone can get restyled by various things
// (e.g. SMIL). Reconstructing its frame is OK, though, because
// it's going to be our _only_ child in the frame tree, so can't get
// mis-ordered with anything.
mClone->SetProperty(nsGkAtoms::restylableAnonymousNode,
reinterpret_cast<void*>(true));
newcontent->SetProperty(nsGkAtoms::restylableAnonymousNode,
reinterpret_cast<void*>(true));
#endif // DEBUG

return mClone;
return newcontent.forget();
}

nsIURI*
Expand All @@ -317,16 +313,14 @@ SVGUseElement::GetSourceDocURI()
return targetContent->OwnerDoc()->GetDocumentURI();
}

void
SVGUseElement::DestroyAnonymousContent()
{
nsContentUtils::DestroyAnonymousContent(&mClone);
}

bool
SVGUseElement::OurWidthAndHeightAreUsed() const
{
return mClone && mClone->IsAnyOfSVGElements(nsGkAtoms::svg, nsGkAtoms::symbol);
auto* frame = GetFrame();
if (!frame || !frame->GetContentClone()) {
return false;
}
return frame->GetContentClone()->IsAnyOfSVGElements(nsGkAtoms::svg, nsGkAtoms::symbol);
}

//----------------------------------------------------------------------
Expand All @@ -339,15 +333,18 @@ SVGUseElement::SyncWidthOrHeight(nsIAtom* aName)
"The clue is in the function name");
NS_ASSERTION(OurWidthAndHeightAreUsed(), "Don't call this");

auto* frame = GetFrame();
nsIContent* clone = frame ? frame->GetContentClone() : nullptr;

if (OurWidthAndHeightAreUsed()) {
nsSVGElement *target = static_cast<nsSVGElement*>(mClone.get());
auto* target = static_cast<nsSVGElement*>(clone);
uint32_t index = *sLengthInfo[ATTR_WIDTH].mName == aName ? ATTR_WIDTH : ATTR_HEIGHT;

if (mLengthAttributes[index].IsExplicitlySet()) {
target->SetLength(aName, mLengthAttributes[index]);
return;
}
if (mClone->IsSVGElement(nsGkAtoms::svg)) {
if (clone->IsSVGElement(nsGkAtoms::svg)) {
// Our width/height attribute is now no longer explicitly set, so we
// need to revert the clone's width/height to the width/height of the
// content that's being cloned.
Expand Down Expand Up @@ -474,6 +471,14 @@ SVGUseElement::GetStringInfo()
ArrayLength(sStringInfo));
}

nsSVGUseFrame*
SVGUseElement::GetFrame() const
{
nsIFrame* frame = GetPrimaryFrame();
MOZ_ASSERT_IF(frame, frame->IsSVGUseFrame());
return static_cast<nsSVGUseFrame*>(frame);
}

//----------------------------------------------------------------------
// nsIContent methods

Expand Down
6 changes: 3 additions & 3 deletions dom/svg/SVGUseElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ class SVGUseElement final : public SVGUseElementBase,
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED

// for nsSVGUseFrame's nsIAnonymousContentCreator implementation.
nsIContent* CreateAnonymousContent();
nsIContent* GetAnonymousContent() const { return mClone; }
void DestroyAnonymousContent();
already_AddRefed<nsIContent> CreateAnonymousContent();

// nsSVGElement specializations:
virtual gfxMatrix PrependLocalTransformsTo(
Expand Down Expand Up @@ -98,6 +96,8 @@ class SVGUseElement final : public SVGUseElementBase,
SVGUseElement* mContainer;
};

nsSVGUseFrame* GetFrame() const;

virtual LengthAttributesInfo GetLengthInfo() override;
virtual StringAttributesInfo GetStringInfo() override;

Expand Down
17 changes: 7 additions & 10 deletions layout/svg/nsSVGUseFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsSVGUseFrame.h"
#include "nsContentUtils.h"

#include "mozilla/dom/SVGUseElement.h"
#include "nsContentList.h"
Expand Down Expand Up @@ -101,9 +102,8 @@ nsSVGUseFrame::AttributeChanged(int32_t aNameSpaceID,
void
nsSVGUseFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
RefPtr<SVGUseElement> use = static_cast<SVGUseElement*>(GetContent());
nsContentUtils::DestroyAnonymousContent(&mContentClone);
nsSVGGFrame::DestroyFrom(aDestructRoot);
use->DestroyAnonymousContent();
}


Expand Down Expand Up @@ -168,23 +168,20 @@ nsSVGUseFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
{
SVGUseElement *use = static_cast<SVGUseElement*>(GetContent());

nsIContent* clone = use->CreateAnonymousContent();
mContentClone = use->CreateAnonymousContent();
nsLayoutUtils::PostRestyleEvent(
use, nsRestyleHint(0), nsChangeHint_InvalidateRenderingObservers);
if (!clone)
if (!mContentClone)
return NS_ERROR_FAILURE;
if (!aElements.AppendElement(clone))
return NS_ERROR_OUT_OF_MEMORY;
aElements.AppendElement(mContentClone);
return NS_OK;
}

void
nsSVGUseFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter)
{
SVGUseElement *use = static_cast<SVGUseElement*>(GetContent());
nsIContent* clone = use->GetAnonymousContent();
if (clone) {
aElements.AppendElement(clone);
if (mContentClone) {
aElements.AppendElement(mContentClone);
}
}
3 changes: 3 additions & 0 deletions layout/svg/nsSVGUseFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,11 @@ class nsSVGUseFrame final
void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;

nsIContent* GetContentClone() { return mContentClone.get(); }

private:
bool mHasValidDimensions;
nsCOMPtr<nsIContent> mContentClone;
};

#endif // __NS_SVGUSEFRAME_H__

0 comments on commit 9631dd3

Please sign in to comment.