зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1295094 - Part 9. Implement nsDisplayMask. r=mstange
MozReview-Commit-ID: CBszApBehRE --HG-- extra : rebase_source : 94a1aee20a569e0e061d20cae81b1112275cd1a6
This commit is contained in:
Родитель
40076dcfa1
Коммит
40235c5c47
|
@ -3589,8 +3589,8 @@ PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
|
|||
basic->BeginTransaction();
|
||||
basic->SetTarget(context);
|
||||
|
||||
if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
|
||||
static_cast<nsDisplaySVGEffects*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic);
|
||||
if (aItem->GetType() == nsDisplayItem::TYPE_MASK) {
|
||||
static_cast<nsDisplayMask*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic);
|
||||
if (basic->InTransaction()) {
|
||||
basic->AbortTransaction();
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ DECLARE_DISPLAY_ITEM_TYPE(SCROLL_INFO_LAYER)
|
|||
DECLARE_DISPLAY_ITEM_TYPE(SELECTION_OVERLAY)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SUBDOCUMENT)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_EFFECTS)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(MASK)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_GLYPHS)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_PATH_GEOMETRY)
|
||||
|
|
|
@ -6677,92 +6677,6 @@ nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplaySVGEffects::PaintAsLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
|
||||
mFrame, mVisibleRect,
|
||||
borderArea, aBuilder,
|
||||
aManager, mOpacityItemCreated);
|
||||
|
||||
image::DrawResult result =
|
||||
nsSVGIntegrationUtils::PaintMaskAndClipPath(params);
|
||||
|
||||
nsDisplaySVGEffectsGeometry::UpdateDrawResult(this, result);
|
||||
}
|
||||
|
||||
LayerState
|
||||
nsDisplaySVGEffects::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aParameters)
|
||||
{
|
||||
return LAYER_SVG_EFFECTS;
|
||||
}
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplaySVGEffects::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aContainerParameters)
|
||||
{
|
||||
const nsIContent* content = mFrame->GetContent();
|
||||
bool hasSVGLayout = (mFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
|
||||
if (hasSVGLayout) {
|
||||
nsISVGChildFrame *svgChildFrame = do_QueryFrame(mFrame);
|
||||
if (!svgChildFrame || !mFrame->GetContent()->IsSVGElement()) {
|
||||
NS_ASSERTION(false, "why?");
|
||||
return nullptr;
|
||||
}
|
||||
if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
|
||||
return nullptr; // The SVG spec says not to draw filters for this
|
||||
}
|
||||
}
|
||||
|
||||
if (mFrame->StyleEffects()->mOpacity == 0.0f &&
|
||||
!mOpacityItemCreated)
|
||||
return nullptr;
|
||||
|
||||
nsIFrame* firstFrame =
|
||||
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
|
||||
nsSVGEffects::EffectProperties effectProperties =
|
||||
nsSVGEffects::GetEffectProperties(firstFrame);
|
||||
|
||||
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
|
||||
effectProperties.GetClipPathFrame(&isOK);
|
||||
|
||||
if (!isOK) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ContainerLayerParameters newContainerParameters = aContainerParameters;
|
||||
if (effectProperties.HasValidFilter()) {
|
||||
newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
|
||||
}
|
||||
|
||||
RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
newContainerParameters, nullptr);
|
||||
|
||||
return container.forget();
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplaySVGEffects::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
nsIFrame* firstFrame =
|
||||
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
|
||||
nsSVGEffects::EffectProperties effectProperties =
|
||||
nsSVGEffects::GetEffectProperties(firstFrame);
|
||||
|
||||
if (effectProperties.HasValidFilter()) {
|
||||
return nsRect();
|
||||
}
|
||||
|
||||
return nsDisplayWrapList::GetComponentAlphaBounds(aBuilder);
|
||||
}
|
||||
|
||||
bool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion) {
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
|
@ -6779,26 +6693,6 @@ bool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool nsDisplaySVGEffects::TryMerge(nsDisplayItem* aItem)
|
||||
{
|
||||
if (aItem->GetType() != TYPE_SVG_EFFECTS)
|
||||
return false;
|
||||
// items for the same content element should be merged into a single
|
||||
// compositing group
|
||||
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplaySVGEffects
|
||||
if (aItem->Frame()->GetContent() != mFrame->GetContent())
|
||||
return false;
|
||||
if (aItem->GetClip() != GetClip())
|
||||
return false;
|
||||
if (aItem->ScrollClip() != ScrollClip())
|
||||
return false;
|
||||
nsDisplaySVGEffects* other = static_cast<nsDisplaySVGEffects*>(aItem);
|
||||
MergeFromTrackingMergedFrames(other);
|
||||
mEffectsBounds.UnionRect(mEffectsBounds,
|
||||
other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
|
||||
return true;
|
||||
}
|
||||
|
||||
gfxRect
|
||||
nsDisplaySVGEffects::BBoxInUserSpace() const
|
||||
{
|
||||
|
@ -6838,9 +6732,120 @@ nsDisplaySVGEffects::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
}
|
||||
|
||||
bool nsDisplaySVGEffects::ValidateSVGFrame()
|
||||
{
|
||||
const nsIContent* content = mFrame->GetContent();
|
||||
bool hasSVGLayout = (mFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
|
||||
if (hasSVGLayout) {
|
||||
nsISVGChildFrame *svgChildFrame = do_QueryFrame(mFrame);
|
||||
if (!svgChildFrame || !mFrame->GetContent()->IsSVGElement()) {
|
||||
NS_ASSERTION(false, "why?");
|
||||
return false;
|
||||
}
|
||||
if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
|
||||
return false; // The SVG spec says not to draw filters for this
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsDisplayMask::nsDisplayMask(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
bool aOpacityItemCreated)
|
||||
: nsDisplaySVGEffects(aBuilder, aFrame, aList, aOpacityItemCreated)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayMask);
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsDisplayMask::~nsDisplayMask()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDisplayMask);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool nsDisplayMask::TryMerge(nsDisplayItem* aItem)
|
||||
{
|
||||
if (aItem->GetType() != TYPE_MASK)
|
||||
return false;
|
||||
|
||||
// items for the same content element should be merged into a single
|
||||
// compositing group
|
||||
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplaySVGEffects
|
||||
if (aItem->Frame()->GetContent() != mFrame->GetContent())
|
||||
return false;
|
||||
if (aItem->GetClip() != GetClip())
|
||||
return false;
|
||||
if (aItem->ScrollClip() != ScrollClip())
|
||||
return false;
|
||||
nsDisplayMask* other = static_cast<nsDisplayMask*>(aItem);
|
||||
MergeFromTrackingMergedFrames(other);
|
||||
mEffectsBounds.UnionRect(mEffectsBounds,
|
||||
other->mEffectsBounds + other->mFrame->GetOffsetTo(mFrame));
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplayMask::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aContainerParameters)
|
||||
{
|
||||
if (!ValidateSVGFrame()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mFrame->StyleEffects()->mOpacity == 0.0f &&
|
||||
!mOpacityItemCreated)
|
||||
return nullptr;
|
||||
|
||||
nsIFrame* firstFrame =
|
||||
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
|
||||
nsSVGEffects::EffectProperties effectProperties =
|
||||
nsSVGEffects::GetEffectProperties(firstFrame);
|
||||
|
||||
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
|
||||
effectProperties.GetClipPathFrame(&isOK);
|
||||
|
||||
if (!isOK) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
|
||||
aContainerParameters, nullptr);
|
||||
|
||||
return container.forget();
|
||||
}
|
||||
|
||||
LayerState
|
||||
nsDisplayMask::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aParameters)
|
||||
{
|
||||
return LAYER_SVG_EFFECTS;
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayMask::PaintAsLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
|
||||
nsSVGIntegrationUtils::PaintFramesParams params(*aCtx->ThebesContext(),
|
||||
mFrame, mVisibleRect,
|
||||
borderArea, aBuilder,
|
||||
aManager, mOpacityItemCreated);
|
||||
|
||||
image::DrawResult result =
|
||||
nsSVGIntegrationUtils::PaintMaskAndClipPath(params);
|
||||
|
||||
nsDisplaySVGEffectsGeometry::UpdateDrawResult(this, result);
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
nsDisplaySVGEffects::PrintEffects(nsACString& aTo)
|
||||
nsDisplayMask::PrintEffects(nsACString& aTo)
|
||||
{
|
||||
nsIFrame* firstFrame =
|
||||
nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
|
||||
|
@ -6869,13 +6874,7 @@ nsDisplaySVGEffects::PrintEffects(nsACString& aTo)
|
|||
aTo += "clip(basic-shape)";
|
||||
first = false;
|
||||
}
|
||||
if (effectProperties.HasValidFilter()) {
|
||||
if (!first) {
|
||||
aTo += ", ";
|
||||
}
|
||||
aTo += "filter";
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (effectProperties.GetFirstMaskFrame()) {
|
||||
if (!first) {
|
||||
aTo += ", ";
|
||||
|
|
|
@ -3782,18 +3782,14 @@ private:
|
|||
int32_t mAPD, mParentAPD;
|
||||
};
|
||||
|
||||
/**
|
||||
* A display item to paint a stacking context with effects
|
||||
* set by the stacking context root frame's style.
|
||||
*/
|
||||
class nsDisplaySVGEffects : public nsDisplayWrapList {
|
||||
class nsDisplaySVGEffects: public nsDisplayWrapList {
|
||||
public:
|
||||
nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList, bool aOpacityItemCreated);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplaySVGEffects();
|
||||
#endif
|
||||
|
||||
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) override;
|
||||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
|
@ -3804,22 +3800,12 @@ public:
|
|||
*aSnap = false;
|
||||
return mEffectsBounds + ToReferenceFrame();
|
||||
}
|
||||
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override;
|
||||
|
||||
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion) override;
|
||||
virtual bool TryMerge(nsDisplayItem* aItem) override;
|
||||
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
|
||||
return false;
|
||||
}
|
||||
NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
|
||||
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aParameters) override;
|
||||
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aContainerParameters) override;
|
||||
|
||||
gfxRect BBoxInUserSpace() const;
|
||||
gfxPoint UserSpaceOffset() const;
|
||||
|
@ -3832,15 +3818,9 @@ public:
|
|||
const nsDisplayItemGeometry* aGeometry,
|
||||
nsRegion* aInvalidRegion) override;
|
||||
|
||||
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx,
|
||||
LayerManager* aManager);
|
||||
protected:
|
||||
bool ValidateSVGFrame();
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void PrintEffects(nsACString& aTo);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// relative to mFrame
|
||||
nsRect mEffectsBounds;
|
||||
// True if the caller also created an nsDisplayOpacity item, and we should tell
|
||||
|
@ -3848,6 +3828,37 @@ private:
|
|||
bool mOpacityItemCreated;
|
||||
};
|
||||
|
||||
/**
|
||||
* A display item to paint a stacking context with mask and clip effects
|
||||
* set by the stacking context root frame's style.
|
||||
*/
|
||||
class nsDisplayMask : public nsDisplaySVGEffects {
|
||||
public:
|
||||
nsDisplayMask(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList, bool aOpacityItemCreated);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayMask();
|
||||
#endif
|
||||
|
||||
NS_DISPLAY_DECL_NAME("Mask", TYPE_MASK)
|
||||
|
||||
virtual bool TryMerge(nsDisplayItem* aItem) override;
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aContainerParameters) override;
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aParameters) override;
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void PrintEffects(nsACString& aTo);
|
||||
#endif
|
||||
|
||||
void PaintAsLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx,
|
||||
LayerManager* aManager);
|
||||
};
|
||||
|
||||
/* A display item that applies a transformation to all of its descendant
|
||||
* elements. This wrapper should only be used if there is a transform applied
|
||||
* to the root element.
|
||||
|
|
|
@ -196,9 +196,9 @@ PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
|
|||
}
|
||||
}
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
|
||||
if (aItem->GetType() == nsDisplayItem::TYPE_MASK) {
|
||||
nsCString str;
|
||||
(static_cast<nsDisplaySVGEffects*>(aItem))->PrintEffects(str);
|
||||
(static_cast<nsDisplayMask*>(aItem))->PrintEffects(str);
|
||||
aStream << str.get();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2448,9 +2448,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
buildingDisplayList.SetDirtyRect(dirtyRectOutsideSVGEffects);
|
||||
/* List now emptied, so add the new list to the top. */
|
||||
resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplaySVGEffects(aBuilder, this, &resultList, useOpacity));
|
||||
new (aBuilder) nsDisplayMask(aBuilder, this, &resultList, useOpacity));
|
||||
// Also add the hoisted scroll info items. We need those for APZ scrolling
|
||||
// because nsDisplaySVGEffects items can't build active layers.
|
||||
// because nsDisplayMask items can't build active layers.
|
||||
aBuilder->ExitSVGEffectsContents();
|
||||
resultList.AppendToTop(&hoistedScrollInfoItemsStorage);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче