зеркало из https://github.com/mozilla/pjs.git
Bug 602757. Part 3: Change IsOpaque to GetOpaqueRegion so we can get useful opaque regions for content that uses border-radius. r=tnikkel,sr=dbaron,a=blocking
This commit is contained in:
Родитель
360d34a263
Коммит
e7ff7b3a5f
|
@ -1486,8 +1486,10 @@ namespace {
|
|||
nsRect nsRegion::GetLargestRectangle () const {
|
||||
nsRect bestRect;
|
||||
|
||||
if (!mRectCount)
|
||||
if (mRectCount <= 1) {
|
||||
bestRect = mBoundRect;
|
||||
return bestRect;
|
||||
}
|
||||
|
||||
AxisPartition xaxis, yaxis;
|
||||
|
||||
|
|
|
@ -186,7 +186,8 @@ protected:
|
|||
void Accumulate(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect);
|
||||
const nsIntRect& aDrawRect,
|
||||
const FrameLayerBuilder::Clip& aClip);
|
||||
nsIFrame* GetActiveScrolledRoot() { return mActiveScrolledRoot; }
|
||||
|
||||
/**
|
||||
|
@ -307,6 +308,7 @@ protected:
|
|||
already_AddRefed<ThebesLayer> FindThebesLayerFor(nsDisplayItem* aItem,
|
||||
const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect,
|
||||
const FrameLayerBuilder::Clip& aClip,
|
||||
nsIFrame* aActiveScrolledRoot);
|
||||
ThebesLayerData* GetTopThebesLayerData()
|
||||
{
|
||||
|
@ -922,7 +924,8 @@ void
|
|||
ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect)
|
||||
const nsIntRect& aDrawRect,
|
||||
const FrameLayerBuilder::Clip& aClip)
|
||||
{
|
||||
nscolor uniformColor;
|
||||
if (aItem->IsUniform(aBuilder, &uniformColor)) {
|
||||
|
@ -947,18 +950,25 @@ ContainerState::ThebesLayerData::Accumulate(nsDisplayListBuilder* aBuilder,
|
|||
mDrawRegion.SimplifyOutward(4);
|
||||
|
||||
PRBool forceTransparentSurface = PR_FALSE;
|
||||
if (aItem->IsOpaque(aBuilder, &forceTransparentSurface)) {
|
||||
// We don't use SimplifyInward here since it's not defined exactly
|
||||
// what it will discard. For our purposes the most important case
|
||||
// is a large opaque background at the bottom of z-order (e.g.,
|
||||
// a canvas background), so we need to make sure that the first rect
|
||||
// we see doesn't get discarded.
|
||||
nsIntRegion tmp;
|
||||
tmp.Or(mOpaqueRegion, aDrawRect);
|
||||
if (tmp.GetNumRects() <= 4) {
|
||||
mOpaqueRegion = tmp;
|
||||
nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &forceTransparentSurface);
|
||||
if (!opaque.IsEmpty()) {
|
||||
nsRegionRectIterator iter(opaque);
|
||||
nscoord appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
|
||||
for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
|
||||
// We don't use SimplifyInward here since it's not defined exactly
|
||||
// what it will discard. For our purposes the most important case
|
||||
// is a large opaque background at the bottom of z-order (e.g.,
|
||||
// a canvas background), so we need to make sure that the first rect
|
||||
// we see doesn't get discarded.
|
||||
nsIntRect rect = aClip.ApproximateIntersect(*r).ToNearestPixels(appUnitsPerDevPixel);
|
||||
nsIntRegion tmp;
|
||||
tmp.Or(mOpaqueRegion, rect);
|
||||
if (tmp.GetNumRects() <= 4) {
|
||||
mOpaqueRegion = tmp;
|
||||
}
|
||||
}
|
||||
} else if (aItem->HasText()) {
|
||||
}
|
||||
if (aItem->HasText()) {
|
||||
if (!mOpaqueRegion.Contains(aVisibleRect)) {
|
||||
if (SuppressComponentAlpha(aBuilder, aItem)) {
|
||||
aItem->DisableComponentAlpha();
|
||||
|
@ -974,6 +984,7 @@ already_AddRefed<ThebesLayer>
|
|||
ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
|
||||
const nsIntRect& aVisibleRect,
|
||||
const nsIntRect& aDrawRect,
|
||||
const FrameLayerBuilder::Clip& aClip,
|
||||
nsIFrame* aActiveScrolledRoot)
|
||||
{
|
||||
PRInt32 i;
|
||||
|
@ -1028,7 +1039,7 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
|
|||
layer = thebesLayerData->mLayer;
|
||||
}
|
||||
|
||||
thebesLayerData->Accumulate(mBuilder, aItem, aVisibleRect, aDrawRect);
|
||||
thebesLayerData->Accumulate(mBuilder, aItem, aVisibleRect, aDrawRect, aClip);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
|
@ -1175,7 +1186,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
|||
}
|
||||
|
||||
nsRefPtr<ThebesLayer> thebesLayer =
|
||||
FindThebesLayerFor(item, itemVisibleRect, itemDrawRect,
|
||||
FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip,
|
||||
activeScrolledRoot);
|
||||
|
||||
InvalidateForLayerChange(item, thebesLayer);
|
||||
|
@ -1814,4 +1825,20 @@ FrameLayerBuilder::Clip::ApplyTo(gfxContext* aContext,
|
|||
}
|
||||
}
|
||||
|
||||
nsRect
|
||||
FrameLayerBuilder::Clip::ApproximateIntersect(const nsRect& aRect) const
|
||||
{
|
||||
nsRect r = aRect;
|
||||
if (mHaveClipRect) {
|
||||
r.IntersectRect(r, mClipRect);
|
||||
}
|
||||
for (PRUint32 i = 0, iEnd = mRoundedClipRects.Length();
|
||||
i < iEnd; ++i) {
|
||||
const Clip::RoundedRect &rr = mRoundedClipRects[i];
|
||||
nsRegion rgn = nsLayoutUtils::RoundedRectIntersectRect(rr.mRect, rr.mRadii, r);
|
||||
r = rgn.GetLargestRectangle();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -317,6 +317,11 @@ public:
|
|||
// or clearing of other clips must be done by the caller.
|
||||
void ApplyTo(gfxContext* aContext, nsPresContext* aPresContext);
|
||||
|
||||
// Return a rectangle contained in the intersection of aRect with this
|
||||
// clip region. Tries to return the largest possible rectangle, but may
|
||||
// not succeed.
|
||||
nsRect ApproximateIntersect(const nsRect& aRect) const;
|
||||
|
||||
bool operator==(const Clip& aOther) const {
|
||||
return mHaveClipRect == aOther.mHaveClipRect &&
|
||||
(!mHaveClipRect || mClipRect == aOther.mClipRect) &&
|
||||
|
|
|
@ -174,6 +174,9 @@ void
|
|||
nsDisplayListBuilder::SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
|
||||
const nsRegion& aRegion)
|
||||
{
|
||||
if (aRegion.IsEmpty())
|
||||
return;
|
||||
|
||||
nsRegion tmp;
|
||||
tmp.Sub(*aVisibleRegion, aRegion);
|
||||
// Don't let *aVisibleRegion get too complex, but don't let it fluff out
|
||||
|
@ -310,19 +313,19 @@ nsDisplayList::ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
|
|||
return ComputeVisibilityForSublist(aBuilder, aVisibleRegion, r.GetBounds());
|
||||
}
|
||||
|
||||
static PRBool
|
||||
static nsRegion
|
||||
TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aTransparentBackground)
|
||||
{
|
||||
if (aItem->IsOpaque(aBuilder, aTransparentBackground))
|
||||
return PR_TRUE;
|
||||
nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, aTransparentBackground);
|
||||
if (aBuilder->IsForPluginGeometry()) {
|
||||
// Treat all chrome items as opaque
|
||||
nsIFrame* f = aItem->GetUnderlyingFrame();
|
||||
if (f && f->PresContext()->IsChrome())
|
||||
return PR_TRUE;
|
||||
if (f && f->PresContext()->IsChrome()) {
|
||||
opaque = aItem->GetBounds(aBuilder);
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
return opaque;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -362,10 +365,9 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
|||
if (item->ComputeVisibility(aBuilder, aVisibleRegion)) {
|
||||
anyVisible = PR_TRUE;
|
||||
PRBool transparentBackground = PR_FALSE;
|
||||
if (TreatAsOpaque(item, aBuilder, &transparentBackground)) {
|
||||
// Subtract opaque item from the visible region
|
||||
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, nsRegion(bounds));
|
||||
}
|
||||
nsRegion opaque = TreatAsOpaque(item, aBuilder, &transparentBackground);
|
||||
// Subtract opaque item from the visible region
|
||||
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque);
|
||||
forceTransparentSurface = forceTransparentSurface || transparentBackground;
|
||||
}
|
||||
AppendToBottom(item);
|
||||
|
@ -686,9 +688,8 @@ PRBool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
return PR_FALSE;
|
||||
|
||||
PRBool forceTransparentBackground;
|
||||
if (TreatAsOpaque(this, aBuilder, &forceTransparentBackground)) {
|
||||
aVisibleRegion->Sub(*aVisibleRegion, bounds);
|
||||
}
|
||||
nsRegion opaque = TreatAsOpaque(this, aBuilder, &forceTransparentBackground);
|
||||
aVisibleRegion->Sub(*aVisibleRegion, opaque);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -834,25 +835,8 @@ RoundedBorderIntersectsRect(nsIFrame* aFrame,
|
|||
static PRBool RoundedRectContainsRect(const nsRect& aRoundedRect,
|
||||
const nscoord aRadii[8],
|
||||
const nsRect& aContainedRect) {
|
||||
// rectFullHeight and rectFullWidth together will approximately contain
|
||||
// the total area of the frame minus the rounded corners.
|
||||
nsRect rectFullHeight = aRoundedRect;
|
||||
nscoord xDiff = NS_MAX(aRadii[NS_CORNER_TOP_LEFT_X], aRadii[NS_CORNER_BOTTOM_LEFT_X]);
|
||||
rectFullHeight.x += xDiff;
|
||||
rectFullHeight.width -= NS_MAX(aRadii[NS_CORNER_TOP_RIGHT_X],
|
||||
aRadii[NS_CORNER_BOTTOM_RIGHT_X]) + xDiff;
|
||||
if (rectFullHeight.Contains(aContainedRect))
|
||||
return PR_TRUE;
|
||||
|
||||
nsRect rectFullWidth = aRoundedRect;
|
||||
nscoord yDiff = NS_MAX(aRadii[NS_CORNER_TOP_LEFT_Y], aRadii[NS_CORNER_TOP_RIGHT_Y]);
|
||||
rectFullWidth.y += yDiff;
|
||||
rectFullWidth.height -= NS_MAX(aRadii[NS_CORNER_BOTTOM_LEFT_Y],
|
||||
aRadii[NS_CORNER_BOTTOM_RIGHT_Y]) + yDiff;
|
||||
if (rectFullWidth.Contains(aContainedRect))
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
nsRegion rgn = nsLayoutUtils::RoundedRectIntersectRect(aRoundedRect, aRadii, aContainedRect);
|
||||
return rgn.Contains(aContainedRect);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -888,9 +872,10 @@ nsDisplayBackground::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface) {
|
||||
nsRegion
|
||||
nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface) {
|
||||
nsRegion result;
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
|
@ -901,27 +886,34 @@ nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder,
|
|||
*aForceTransparentSurface = disp->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
|
||||
disp->mAppearance == NS_THEME_WIN_GLASS;
|
||||
}
|
||||
return mThemeTransparency == nsITheme::eOpaque;
|
||||
if (mThemeTransparency == nsITheme::eOpaque) {
|
||||
result = GetBounds(aBuilder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsStyleContext* bgSC;
|
||||
if (!nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC))
|
||||
return PR_FALSE;
|
||||
return result;
|
||||
const nsStyleBackground* bg = bgSC->GetStyleBackground();
|
||||
|
||||
const nsStyleBackground::Layer& bottomLayer = bg->BottomLayer();
|
||||
|
||||
// bottom layer's clip is used for the color
|
||||
if (bottomLayer.mClip != NS_STYLE_BG_CLIP_BORDER ||
|
||||
nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius))
|
||||
return PR_FALSE;
|
||||
return result;
|
||||
|
||||
if (NS_GET_A(bg->mBackgroundColor) == 255 &&
|
||||
!nsCSSRendering::IsCanvasFrame(mFrame))
|
||||
return PR_TRUE;
|
||||
!nsCSSRendering::IsCanvasFrame(mFrame)) {
|
||||
result = GetBounds(aBuilder);
|
||||
return result;
|
||||
}
|
||||
|
||||
return bottomLayer.mRepeat == NS_STYLE_BG_REPEAT_XY &&
|
||||
bottomLayer.mImage.IsOpaque();
|
||||
if (bottomLayer.mRepeat == NS_STYLE_BG_REPEAT_XY &&
|
||||
bottomLayer.mImage.IsOpaque()) {
|
||||
result = GetBounds(aBuilder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -1283,13 +1275,17 @@ nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
mVisibleRect);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayWrapList::IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface) {
|
||||
nsRegion
|
||||
nsDisplayWrapList::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface) {
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
return mList.IsOpaque();
|
||||
nsRegion result;
|
||||
if (mList.IsOpaque()) {
|
||||
result = GetBounds(aBuilder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool nsDisplayWrapList::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
|
||||
|
@ -1427,14 +1423,14 @@ nsDisplayOpacity::~nsDisplayOpacity() {
|
|||
}
|
||||
#endif
|
||||
|
||||
PRBool nsDisplayOpacity::IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface) {
|
||||
nsRegion nsDisplayOpacity::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface) {
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
// We are never opaque, if our opacity was < 1 then we wouldn't have
|
||||
// been created.
|
||||
return PR_FALSE;
|
||||
return nsRegion();
|
||||
}
|
||||
|
||||
// nsDisplayOpacity uses layers for rendering
|
||||
|
@ -1601,13 +1597,14 @@ nsDisplayClipRoundedRect::~nsDisplayClipRoundedRect()
|
|||
}
|
||||
#endif
|
||||
|
||||
PRBool nsDisplayClipRoundedRect::IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion
|
||||
nsDisplayClipRoundedRect::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface)
|
||||
{
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
return nsRegion();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2021,8 +2018,8 @@ nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder)
|
|||
* mStoredList.GetVisibleRect().Contains(untransformedVisible), then it
|
||||
* certainly contains the actual (non-axis-aligned) untransformed rect.
|
||||
*/
|
||||
PRBool nsDisplayTransform::IsOpaque(nsDisplayListBuilder *aBuilder,
|
||||
PRBool* aForceTransparentSurface)
|
||||
nsRegion nsDisplayTransform::GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
|
||||
PRBool* aForceTransparentSurface)
|
||||
{
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
|
@ -2030,14 +2027,17 @@ PRBool nsDisplayTransform::IsOpaque(nsDisplayListBuilder *aBuilder,
|
|||
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
|
||||
nsRect untransformedVisible =
|
||||
UntransformRect(mVisibleRect, mFrame, ToReferenceFrame());
|
||||
return disp->mTransform.GetMainMatrixEntry(1) == 0.0f &&
|
||||
disp->mTransform.GetMainMatrixEntry(2) == 0.0f &&
|
||||
mStoredList.GetVisibleRect().Contains(untransformedVisible) &&
|
||||
mStoredList.IsOpaque(aBuilder);
|
||||
nsRegion result;
|
||||
if (disp->mTransform.GetMainMatrixEntry(1) == 0.0f &&
|
||||
disp->mTransform.GetMainMatrixEntry(2) == 0.0f &&
|
||||
mStoredList.GetOpaqueRegion(aBuilder).Contains(untransformedVisible)) {
|
||||
result = mVisibleRect;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The transform is uniform if it fills the entire bounding rect and the
|
||||
* wrapped list is uniform. See IsOpaque for discussion of why this
|
||||
* wrapped list is uniform. See GetOpaqueRegion for discussion of why this
|
||||
* works.
|
||||
*/
|
||||
PRBool nsDisplayTransform::IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor)
|
||||
|
@ -2161,13 +2161,13 @@ nsDisplaySVGEffects::~nsDisplaySVGEffects()
|
|||
}
|
||||
#endif
|
||||
|
||||
PRBool nsDisplaySVGEffects::IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface)
|
||||
nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface)
|
||||
{
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
return nsRegion();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -559,16 +559,16 @@ public:
|
|||
return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
|
||||
}
|
||||
/**
|
||||
* @return PR_TRUE if the item is definitely opaque --- i.e., paints
|
||||
* every pixel within its bounds opaquely
|
||||
* @return a region of the item that is opaque --- every pixel painted
|
||||
* with an opaque color.
|
||||
*/
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull)
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull)
|
||||
{
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
return nsRegion();
|
||||
}
|
||||
/**
|
||||
* If this returns true, then aColor is set to the uniform color
|
||||
|
@ -641,11 +641,10 @@ public:
|
|||
* On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
|
||||
* which may be visible. If the display item opaquely covers an area, it
|
||||
* can remove that area from aVisibleRegion before returning.
|
||||
* nsDisplayList::ComputeVisibility automatically subtracts the bounds
|
||||
* of items that return true from IsOpaque(), and automatically
|
||||
* removes items whose bounds do not intersect the visible area,
|
||||
* so implementations of nsDisplayItem::ComputeVisibility do not
|
||||
* need to do these things.
|
||||
* nsDisplayList::ComputeVisibility automatically subtracts the region
|
||||
* returned by GetOpaqueRegion, and automatically removes items whose bounds
|
||||
* do not intersect the visible area, so implementations of
|
||||
* nsDisplayItem::ComputeVisibility do not need to do these things.
|
||||
* nsDisplayList::ComputeVisibility will already have set mVisibleRect on
|
||||
* this item to the intersection of *aVisibleRegion and this item's bounds.
|
||||
* We rely on that, so this should only be called by
|
||||
|
@ -1360,12 +1359,16 @@ public:
|
|||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) { return mBounds; }
|
||||
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aOutTransparentBackground = nsnull) {
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aOutTransparentBackground = nsnull) {
|
||||
if (aOutTransparentBackground) {
|
||||
*aOutTransparentBackground = PR_FALSE;
|
||||
}
|
||||
return (NS_GET_A(mColor) == 255);
|
||||
nsRegion result;
|
||||
if (NS_GET_A(mColor) == 255) {
|
||||
result = GetBounds(aBuilder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
|
||||
|
@ -1400,8 +1403,8 @@ public:
|
|||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion);
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame);
|
||||
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
|
||||
|
@ -1536,8 +1539,8 @@ public:
|
|||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
|
||||
virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame);
|
||||
|
@ -1620,8 +1623,8 @@ public:
|
|||
virtual ~nsDisplayOpacity();
|
||||
#endif
|
||||
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager);
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
|
@ -1718,8 +1721,8 @@ public:
|
|||
virtual ~nsDisplayClipRoundedRect();
|
||||
#endif
|
||||
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
|
@ -1788,8 +1791,8 @@ public:
|
|||
virtual ~nsDisplaySVGEffects();
|
||||
#endif
|
||||
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
|
||||
|
@ -1847,8 +1850,8 @@ public:
|
|||
virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
|
||||
HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder);
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder *aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual PRBool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor);
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager);
|
||||
|
|
|
@ -178,11 +178,15 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
|
|||
nscolor color;
|
||||
nsRect vis = i->GetVisibleRect();
|
||||
nsDisplayList* list = i->GetList();
|
||||
nsRegion opaque;
|
||||
if (!list || list->DidComputeVisibility()) {
|
||||
opaque = i->GetOpaqueRegion(aBuilder);
|
||||
}
|
||||
fprintf(aOutput, "%s %p(%s) (%d,%d,%d,%d)(%d,%d,%d,%d)%s%s\n",
|
||||
i->Name(), (void*)f, NS_ConvertUTF16toUTF8(fName).get(),
|
||||
rect.x, rect.y, rect.width, rect.height,
|
||||
vis.x, vis.y, vis.width, vis.height,
|
||||
((!list || list->DidComputeVisibility()) && i->IsOpaque(aBuilder)) ? " opaque" : "",
|
||||
opaque.IsEmpty() ? "" : " opaque",
|
||||
i->IsUniform(aBuilder, &color) ? " uniform" : "");
|
||||
if (list) {
|
||||
PrintDisplayListTo(aBuilder, *list, aIndent + 4, aOutput);
|
||||
|
|
|
@ -923,6 +923,35 @@ nsLayoutUtils::RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor)
|
|||
nscoord(scaledRect.size.width), nscoord(scaledRect.size.height));
|
||||
}
|
||||
|
||||
|
||||
nsRegion
|
||||
nsLayoutUtils::RoundedRectIntersectRect(const nsRect& aRoundedRect,
|
||||
const nscoord aRadii[8],
|
||||
const nsRect& aContainedRect)
|
||||
{
|
||||
// rectFullHeight and rectFullWidth together will approximately contain
|
||||
// the total area of the frame minus the rounded corners.
|
||||
nsRect rectFullHeight = aRoundedRect;
|
||||
nscoord xDiff = NS_MAX(aRadii[NS_CORNER_TOP_LEFT_X], aRadii[NS_CORNER_BOTTOM_LEFT_X]);
|
||||
rectFullHeight.x += xDiff;
|
||||
rectFullHeight.width -= NS_MAX(aRadii[NS_CORNER_TOP_RIGHT_X],
|
||||
aRadii[NS_CORNER_BOTTOM_RIGHT_X]) + xDiff;
|
||||
nsRect r1;
|
||||
r1.IntersectRect(rectFullHeight, aContainedRect);
|
||||
|
||||
nsRect rectFullWidth = aRoundedRect;
|
||||
nscoord yDiff = NS_MAX(aRadii[NS_CORNER_TOP_LEFT_Y], aRadii[NS_CORNER_TOP_RIGHT_Y]);
|
||||
rectFullWidth.y += yDiff;
|
||||
rectFullWidth.height -= NS_MAX(aRadii[NS_CORNER_BOTTOM_LEFT_Y],
|
||||
aRadii[NS_CORNER_BOTTOM_RIGHT_Y]) + yDiff;
|
||||
nsRect r2;
|
||||
r2.IntersectRect(rectFullWidth, aContainedRect);
|
||||
|
||||
nsRegion result;
|
||||
result.Or(r1, r2);
|
||||
return result;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsLayoutUtils::MatrixTransformRect(const nsRect &aBounds,
|
||||
const gfxMatrix &aMatrix, float aFactor)
|
||||
|
|
|
@ -512,6 +512,15 @@ public:
|
|||
*/
|
||||
static nsRect RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor);
|
||||
|
||||
/**
|
||||
* Returns a subrectangle of aContainedRect that is entirely inside the rounded
|
||||
* rect. Complex cases are handled conservatively by returning a smaller
|
||||
* rect than necessary.
|
||||
*/
|
||||
static nsRegion RoundedRectIntersectRect(const nsRect& aRoundedRect,
|
||||
const nscoord aRadii[8],
|
||||
const nsRect& aContainedRect);
|
||||
|
||||
enum {
|
||||
PAINT_IN_TRANSFORM = 0x01,
|
||||
PAINT_SYNC_DECODE_IMAGES = 0x02,
|
||||
|
|
|
@ -177,14 +177,15 @@ public:
|
|||
return NS_GET_A(mExtraBackgroundColor) > 0 ||
|
||||
nsDisplayBackground::ComputeVisibility(aBuilder, aVisibleRegion);
|
||||
}
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull)
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull)
|
||||
{
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
return NS_GET_A(mExtraBackgroundColor) == 255 ||
|
||||
nsDisplayBackground::IsOpaque(aBuilder);
|
||||
if (NS_GET_A(mExtraBackgroundColor) == 255)
|
||||
return nsRegion(GetBounds(aBuilder));
|
||||
return nsDisplayBackground::GetOpaqueRegion(aBuilder);
|
||||
}
|
||||
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
|
||||
{
|
||||
|
|
|
@ -77,14 +77,18 @@ public:
|
|||
|
||||
NS_DISPLAY_DECL_NAME("nsDisplayCanvas", TYPE_CANVAS)
|
||||
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull) {
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull) {
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
nsIFrame* f = GetUnderlyingFrame();
|
||||
nsHTMLCanvasElement *canvas = CanvasElementFromContent(f->GetContent());
|
||||
return canvas->GetIsOpaque();
|
||||
nsRegion result;
|
||||
if (canvas->GetIsOpaque()) {
|
||||
result = GetBounds(aBuilder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
|
||||
|
|
|
@ -1290,13 +1290,14 @@ nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayPlugin::IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface)
|
||||
nsRegion
|
||||
nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface)
|
||||
{
|
||||
if (aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = PR_FALSE;
|
||||
}
|
||||
nsRegion result;
|
||||
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
||||
if (!aBuilder->IsForPluginGeometry()) {
|
||||
nsIWidget* widget = f->GetWidget();
|
||||
|
@ -1310,11 +1311,14 @@ nsDisplayPlugin::IsOpaque(nsDisplayListBuilder* aBuilder,
|
|||
// Something has clipped us unexpectedly. Perhaps there is a translucent
|
||||
// chrome element overlaying us that forced us to be clipped away. Treat
|
||||
// us as non-opaque since we may have holes.
|
||||
return PR_FALSE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return f->IsOpaque();
|
||||
if (f->IsOpaque()) {
|
||||
result = GetBounds(aBuilder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -316,8 +316,8 @@ public:
|
|||
#endif
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
|
||||
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext* aCtx);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -375,10 +375,10 @@ public:
|
|||
|
||||
NS_DISPLAY_DECL_NAME("Video", TYPE_VIDEO)
|
||||
|
||||
// It would be great if we could override IsOpaque to return false here,
|
||||
// It would be great if we could override GetOpaqueRegion to return nonempty here,
|
||||
// but it's probably not safe to do so in general. Video frames are
|
||||
// updated asynchronously from decoder threads, and it's possible that
|
||||
// we might have an opaque video frame when IsOpaque is called, but
|
||||
// we might have an opaque video frame when GetOpaqueRegion is called, but
|
||||
// when we come to paint, the video frame is transparent or has gone
|
||||
// away completely (e.g. because of a decoder error). The problem would
|
||||
// be especially acute if we have off-main-thread rendering.
|
||||
|
|
|
@ -280,7 +280,7 @@ struct nsStyleImage {
|
|||
// rect is non-trivial since each side value can be specified with
|
||||
// percentage unit, which can not be evaluated until the source image size
|
||||
// is available. Therefore, we currently postpone the evaluation of crop
|
||||
// rect until the actual rendering time --- alternatively until IsOpaque()
|
||||
// rect until the actual rendering time --- alternatively until GetOpaqueRegion()
|
||||
// is called.
|
||||
return mType == eStyleImageType_Null;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче