Bug 1295094 - Part 9. Implement nsDisplayMask. r=mstange

MozReview-Commit-ID: CBszApBehRE

--HG--
extra : rebase_source : 94a1aee20a569e0e061d20cae81b1112275cd1a6
This commit is contained in:
cku 2016-08-10 03:02:45 +08:00
Родитель 40076dcfa1
Коммит 40235c5c47
6 изменённых файлов: 156 добавлений и 146 удалений

Просмотреть файл

@ -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);
}