зеркало из https://github.com/mozilla/gecko-dev.git
Bug 371460: Remove clipping functions from views. r+sr=roc.
This commit is contained in:
Родитель
52bb0dd7af
Коммит
88fb576ad6
|
@ -507,95 +507,6 @@ SyncFrameViewGeometryDependentProperties(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the frame has visible content that overflows the content area, then we
|
||||
// need the view marked as having transparent content
|
||||
|
||||
// There are two types of clipping:
|
||||
// - 'clip' which only applies to absolutely positioned elements, and is
|
||||
// relative to the element's border edge. 'clip' applies to the entire
|
||||
// element
|
||||
// - 'overflow:-moz-hidden-unscrollable' which only applies to
|
||||
// block-level elements and replaced elements. Note
|
||||
// that out-of-flow frames like floated or absolutely positioned
|
||||
// frames are block-level, but we can't rely on the 'display' value
|
||||
// being set correctly in the style context...
|
||||
PRBool hasClip = display->IsAbsolutelyPositioned() && (display->mClipFlags & NS_STYLE_CLIP_RECT);
|
||||
PRBool hasOverflowClip = isBlockLevel && (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP);
|
||||
if (hasClip || hasOverflowClip) {
|
||||
nsSize frameSize = aFrame->GetSize();
|
||||
nsRect clipRect;
|
||||
|
||||
if (hasClip) {
|
||||
// Start with the 'auto' values and then factor in user specified values
|
||||
clipRect.SetRect(0, 0, frameSize.width, frameSize.height);
|
||||
|
||||
if (display->mClipFlags & NS_STYLE_CLIP_RECT) {
|
||||
if (0 == (NS_STYLE_CLIP_TOP_AUTO & display->mClipFlags)) {
|
||||
clipRect.y = display->mClip.y;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_LEFT_AUTO & display->mClipFlags)) {
|
||||
clipRect.x = display->mClip.x;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & display->mClipFlags)) {
|
||||
clipRect.width = display->mClip.width;
|
||||
}
|
||||
if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & display->mClipFlags)) {
|
||||
clipRect.height = display->mClip.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOverflowClip) {
|
||||
// XXX We should be able to replace the next 14 lines with just
|
||||
// overflowClipRect.Deflate(aFrame->GetUsedBorderAndPadding());
|
||||
// but unfortunately this function gets called during frame
|
||||
// construction (why?), and GetUsedBorderAndPadding asserts when
|
||||
// called on a frame that hasn't been reflowed yet (for good
|
||||
// reason).
|
||||
const nsStyleBorder* borderStyle = aStyleContext->GetStyleBorder();
|
||||
const nsStylePadding* paddingStyle = aStyleContext->GetStylePadding();
|
||||
|
||||
nsMargin padding;
|
||||
nsRect overflowClipRect(0, 0, frameSize.width, frameSize.height);
|
||||
overflowClipRect.Deflate(borderStyle->GetBorder());
|
||||
// XXX We need to handle percentage padding
|
||||
if (paddingStyle->GetPadding(padding)) {
|
||||
overflowClipRect.Deflate(padding);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
NS_WARNING("Percentage padding and CLIP overflow don't mix");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (hasClip) {
|
||||
// If both 'clip' and 'overflow-clip' apply then use the intersection
|
||||
// of the two
|
||||
clipRect.IntersectRect(clipRect, overflowClipRect);
|
||||
} else {
|
||||
clipRect = overflowClipRect;
|
||||
}
|
||||
}
|
||||
|
||||
nsRect newSize = aView->GetBounds();
|
||||
newSize -= aView->GetPosition();
|
||||
|
||||
// If part of the view is being clipped out, then mark it transparent
|
||||
if (clipRect.y > newSize.y
|
||||
|| clipRect.x > newSize.x
|
||||
|| clipRect.XMost() < newSize.XMost()
|
||||
|| clipRect.YMost() < newSize.YMost()) {
|
||||
viewHasTransparentContent = PR_TRUE;
|
||||
}
|
||||
|
||||
// Set clipping of child views.
|
||||
nsRegion region(clipRect);
|
||||
vm->SetViewChildClipRegion(aView, ®ion);
|
||||
} else {
|
||||
// Remove clipping of child views.
|
||||
vm->SetViewChildClipRegion(aView, nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -553,8 +553,6 @@ nsSimplePageSequenceFrame::StartPrint(nsPresContext* aPresContext,
|
|||
// sure the child views don't get asked to print
|
||||
// but my guess is that there won't be any
|
||||
vm->SetViewVisibility(view, nsViewVisibility_kHide);
|
||||
nsRegion emptyRegion;
|
||||
vm->SetViewChildClipRegion(view, &emptyRegion);
|
||||
} else {
|
||||
nsRect rect = page->GetRect();
|
||||
rect.y = y;
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsPresContext.h"
|
||||
|
||||
|
|
|
@ -46,8 +46,6 @@
|
|||
#include "nsScrollbarButtonFrame.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIScrollbarMediator.h"
|
||||
|
||||
//
|
||||
|
|
|
@ -62,10 +62,10 @@ enum nsRectVisibility {
|
|||
nsRectVisibility_kZeroAreaRect
|
||||
};
|
||||
|
||||
// 88946f17-d4a7-410f-bb42-cc71dcd0a330
|
||||
// 38439490-51d4-416a-a12f-20535d9d8119
|
||||
#define NS_IVIEWMANAGER_IID \
|
||||
{ 0x88946f17, 0xd4a7, 0x410f, \
|
||||
{ 0xbb, 0x42, 0xcc, 0x71, 0xdc, 0xd0, 0xa3, 0x30 } }
|
||||
{ 0x38439490, 0x51d4, 0x416a, \
|
||||
{ 0xa1, 0x2f, 0x20, 0x53, 0x5d, 0x9d, 0x81, 0x19 } }
|
||||
|
||||
class nsIViewManager : public nsISupports
|
||||
{
|
||||
|
@ -264,28 +264,6 @@ public:
|
|||
NS_IMETHOD ResizeView(nsIView *aView, const nsRect &aRect,
|
||||
PRBool aRepaintExposedAreaOnly = PR_FALSE) = 0;
|
||||
|
||||
/**
|
||||
* Set the region to which a view's descendants are clipped. The view
|
||||
* itself is not clipped to this region; this allows for effects
|
||||
* where part of the view is drawn outside the clip region (e.g.,
|
||||
* its borders and background). The view manager generates the
|
||||
* appropriate dirty regions.
|
||||
*
|
||||
* @param aView view to set clipping for
|
||||
* @param aRegion
|
||||
* if null then no clipping is required. In this case all descendant
|
||||
* views (but not descendants through placeholder edges) must have their
|
||||
* bounds inside the bounds of this view
|
||||
* if non-null, then we will clip this view's descendant views
|
||||
* --- including descendants through placeholder edges ---
|
||||
* to the region. The region's bounds must be within the bounds of
|
||||
* this view. The descendant views' bounds need not be inside the bounds
|
||||
* of this view (because we're going to clip them anyway).
|
||||
*
|
||||
* XXX Currently we only support regions consisting of a single rectangle.
|
||||
*/
|
||||
NS_IMETHOD SetViewChildClipRegion(nsIView *aView, const nsRegion *aRegion) = 0;
|
||||
|
||||
/**
|
||||
* Set the visibility of a view.
|
||||
* The view manager generates the appropriate dirty regions.
|
||||
|
|
|
@ -88,8 +88,6 @@ nsScrollPortView::nsScrollPortView(nsViewManager* aViewManager)
|
|||
|
||||
mListeners = nsnull;
|
||||
mSmoothScroll = nsnull;
|
||||
|
||||
SetClipChildrenToBounds(PR_TRUE);
|
||||
}
|
||||
|
||||
nsScrollPortView::~nsScrollPortView()
|
||||
|
|
|
@ -868,101 +868,3 @@ PRBool nsIView::ExternalIsRoot() const
|
|||
{
|
||||
return nsIView::IsRoot();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aStopAtView clipping from ancestors of this view will not be applied
|
||||
* @return PR_TRUE iff we found a placeholder parent edge on the way up the view tree
|
||||
* from aView to aStopAtView
|
||||
*/
|
||||
static PRBool ApplyClipRect(const nsView* aView, nsRect* aRect, PRBool aFollowPlaceholders,
|
||||
nsIView* aStopAtView)
|
||||
{
|
||||
// this records the offset from the origin of the current aView
|
||||
// to the origin of the initial aView
|
||||
nsPoint offset(0, 0);
|
||||
PRBool lastViewIsFloating = aView->GetFloating();
|
||||
PRBool foundPlaceholders = PR_FALSE;
|
||||
while (NS_STATIC_CAST(const nsIView*, aView) != aStopAtView) {
|
||||
const nsView* parentView = aView->GetParent();
|
||||
nsPoint offsetFromParent = aView->GetPosition();
|
||||
|
||||
const nsView* zParent = aView->GetZParent();
|
||||
if (zParent) {
|
||||
foundPlaceholders = PR_TRUE;
|
||||
if (aFollowPlaceholders) {
|
||||
// correct offsetFromParent to account for the fact that we're
|
||||
// switching parentView to ZParent
|
||||
// Note that the common case is that parentView is an ancestor of
|
||||
// ZParent.
|
||||
const nsView* zParentChain;
|
||||
for (zParentChain = zParent;
|
||||
zParentChain != parentView && zParentChain;
|
||||
zParentChain = zParentChain->GetParent()) {
|
||||
offsetFromParent -= zParentChain->GetPosition();
|
||||
}
|
||||
if (!zParentChain) {
|
||||
// uh oh. As we walked up the tree, we missed zParent. This can
|
||||
// happen because of odd (but legal) containing block hierarchies.
|
||||
// Just compute the required offset from scratch; this is slow,
|
||||
// but hopefully rarely executed.
|
||||
offsetFromParent = nsViewManager::ComputeViewOffset(aView)
|
||||
- nsViewManager::ComputeViewOffset(zParent);
|
||||
}
|
||||
parentView = zParent;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parentView) {
|
||||
break;
|
||||
}
|
||||
|
||||
PRBool parentIsFloating = parentView->GetFloating();
|
||||
if (lastViewIsFloating && !parentIsFloating) {
|
||||
break;
|
||||
}
|
||||
|
||||
// now make offset be the offset from parentView's origin to the initial
|
||||
// aView's origin
|
||||
offset += offsetFromParent;
|
||||
if (parentView->GetClipChildrenToBounds(aFollowPlaceholders)) {
|
||||
// Get the parent's clip rect (which is just the dimensions in this
|
||||
// case) into the initial aView's coordinates
|
||||
nsRect clipRect = parentView->GetDimensions();
|
||||
clipRect -= offset;
|
||||
PRBool overlap = aRect->IntersectRect(clipRect, *aRect);
|
||||
if (!overlap) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The child-clipping rect is applied to all *content* children.
|
||||
// So we apply it if we're in the placeholder-following pass, or
|
||||
// if we're in the first pass and we haven't detected any
|
||||
// placeholders yet, in which case this geometric ancestor is also
|
||||
// a content ancestor.
|
||||
const nsRect* r = parentView->GetClipChildrenToRect();
|
||||
if (r && (!foundPlaceholders || aFollowPlaceholders)) {
|
||||
// Get the parent's clip rect into the initial aView's coordinates
|
||||
nsRect clipRect = *r;
|
||||
clipRect -= offset;
|
||||
PRBool overlap = aRect->IntersectRect(clipRect, *aRect);
|
||||
if (!overlap) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
aView = parentView;
|
||||
lastViewIsFloating = parentIsFloating;
|
||||
}
|
||||
|
||||
return foundPlaceholders;
|
||||
}
|
||||
|
||||
nsRect nsView::GetClippedRect(nsIView* aStopAtView)
|
||||
{
|
||||
nsRect clip = GetDimensions();
|
||||
PRBool foundPlaceholders = ApplyClipRect(this, &clip, PR_FALSE, aStopAtView);
|
||||
if (foundPlaceholders && !clip.IsEmpty()) {
|
||||
ApplyClipRect(this, &clip, PR_TRUE, aStopAtView);
|
||||
}
|
||||
return clip;
|
||||
}
|
||||
|
|
|
@ -110,41 +110,6 @@ public:
|
|||
*/
|
||||
virtual PRBool IsZPlaceholderView() const { return PR_FALSE; }
|
||||
|
||||
/**
|
||||
* Called to set the clip of the children of this view.
|
||||
* The clip is relative to the origin of the view.
|
||||
* All of the children of this view will be clipped using
|
||||
* the specified rectangle
|
||||
*/
|
||||
void SetClipChildrenToRect(const nsRect* aRect) {
|
||||
if (!aRect) {
|
||||
delete mClipRect;
|
||||
mClipRect = nsnull;
|
||||
} else {
|
||||
if (mClipRect) {
|
||||
*mClipRect = *aRect;
|
||||
} else {
|
||||
mClipRect = new nsRect(*aRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SetClipChildrenToBounds(PRBool aDoClip) {
|
||||
mVFlags = (mVFlags & ~NS_VIEW_FLAG_CLIP_CHILDREN_TO_BOUNDS)
|
||||
| (aDoClip ? NS_VIEW_FLAG_CLIP_CHILDREN_TO_BOUNDS : 0);
|
||||
}
|
||||
void SetClipPlaceholdersToBounds(PRBool aDoClip) {
|
||||
mVFlags = (mVFlags & ~NS_VIEW_FLAG_CLIP_PLACEHOLDERS_TO_BOUNDS)
|
||||
| (aDoClip ? NS_VIEW_FLAG_CLIP_PLACEHOLDERS_TO_BOUNDS : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to get the dimensions and position of the clip for the children of this view.
|
||||
*/
|
||||
const nsRect* GetClipChildrenToRect() const
|
||||
{ return mClipRect; }
|
||||
PRBool GetClipChildrenToBounds(PRBool aPlaceholders) const
|
||||
{ return (mVFlags & (aPlaceholders ? NS_VIEW_FLAG_CLIP_PLACEHOLDERS_TO_BOUNDS : NS_VIEW_FLAG_CLIP_CHILDREN_TO_BOUNDS)) != 0; }
|
||||
|
||||
/**
|
||||
* Called to indicate that the visibility of a view has been
|
||||
* changed.
|
||||
|
@ -183,14 +148,6 @@ public:
|
|||
*/
|
||||
NS_IMETHOD SetWidget(nsIWidget *aWidget);
|
||||
|
||||
/**
|
||||
* @return the view's dimensions after clipping by ancestors is applied
|
||||
* (the rect is relative to the view's origin)
|
||||
* @param aStopAtView do not consider clipping imposed by views above this view
|
||||
* on the ancestor chain
|
||||
*/
|
||||
nsRect GetClippedRect(nsIView* aStopAtView = nsnull);
|
||||
|
||||
// Helper function to get the view that's associated with a widget
|
||||
static nsView* GetViewFor(nsIWidget* aWidget) {
|
||||
return NS_STATIC_CAST(nsView*, nsIView::GetViewFor(aWidget));
|
||||
|
|
|
@ -1023,8 +1023,7 @@ AccumulateIntersectionsIntoDirtyRegion(nsView* aTargetView,
|
|||
// commonly we have dirty rects on the root view.
|
||||
nsPoint offset = aTargetView->GetOffsetTo(aSourceView);
|
||||
nsRegion intersection;
|
||||
intersection.And(*aSourceView->GetDirtyRegion(),
|
||||
aTargetView->GetClippedRect() + offset);
|
||||
intersection = *aSourceView->GetDirtyRegion();
|
||||
if (!intersection.IsEmpty()) {
|
||||
nsRegion* targetRegion = aTargetView->GetDirtyRegion();
|
||||
if (targetRegion) {
|
||||
|
@ -1073,22 +1072,7 @@ nsViewManager::UpdateViewAfterScroll(nsView *aView, const nsRegion& aUpdateRegio
|
|||
{
|
||||
NS_ASSERTION(RootViewManager()->mScrollCnt > 0,
|
||||
"Someone forgot to call WillBitBlit()");
|
||||
// Look at the view's clipped rect. It may be that part of the view is clipped out
|
||||
// in which case we don't need to worry about invalidating the clipped-out part.
|
||||
nsRect damageRect = aView->GetClippedRect();
|
||||
if (damageRect.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
nsPoint offset = ComputeViewOffset(aView);
|
||||
damageRect.MoveBy(offset);
|
||||
|
||||
// if this is a floating view, it isn't covered by any widgets other than
|
||||
// its children, which are handled by the widget scroller.
|
||||
if (aView->GetFloating()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateWidgetArea(RootViewManager()->GetRootView(), nsRegion(damageRect), aView);
|
||||
if (!aUpdateRegion.IsEmpty()) {
|
||||
// XXX We should update the region, not the bounds rect, but that requires
|
||||
// a little more work. Fix this when we reshuffle this code.
|
||||
|
@ -1209,14 +1193,7 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRU
|
|||
|
||||
nsView* view = NS_STATIC_CAST(nsView*, aView);
|
||||
|
||||
// Only Update the rectangle region of the rect that intersects the view's non clipped rectangle
|
||||
nsRect clippedRect = view->GetClippedRect();
|
||||
if (clippedRect.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRect damagedRect;
|
||||
damagedRect.IntersectRect(aRect, clippedRect);
|
||||
nsRect damagedRect(aRect);
|
||||
|
||||
// If the rectangle is not visible then abort
|
||||
// without invalidating. This is a performance
|
||||
|
@ -1968,47 +1945,6 @@ NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, const nsRect &aRect, PRB
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsViewManager::SetViewChildClipRegion(nsIView *aView, const nsRegion *aRegion)
|
||||
{
|
||||
nsView* view = NS_STATIC_CAST(nsView*, aView);
|
||||
|
||||
NS_ASSERTION(!(nsnull == view), "no view");
|
||||
|
||||
const nsRect* oldClipRect = view->GetClipChildrenToRect();
|
||||
|
||||
nsRect newClipRectStorage = view->GetDimensions();
|
||||
nsRect* newClipRect = nsnull;
|
||||
if (aRegion) {
|
||||
newClipRectStorage = aRegion->GetBounds();
|
||||
newClipRect = &newClipRectStorage;
|
||||
}
|
||||
|
||||
if ((oldClipRect != nsnull) == (newClipRect != nsnull)
|
||||
&& (!newClipRect || *newClipRect == *oldClipRect)) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsRect oldClipRectStorage =
|
||||
oldClipRect ? *oldClipRect : view->GetDimensions();
|
||||
|
||||
// Update the view properties
|
||||
view->SetClipChildrenToRect(newClipRect);
|
||||
|
||||
if (IsViewInserted(view)) {
|
||||
// Invalidate changed areas
|
||||
// Paint (new - old) in the current view
|
||||
InvalidateRectDifference(view, newClipRectStorage, oldClipRectStorage, NS_VMREFRESH_NO_SYNC);
|
||||
// Paint (old - new) in the parent view, since it'll be clipped out of the current view
|
||||
nsView* parent = view->GetParent();
|
||||
if (parent) {
|
||||
oldClipRectStorage += view->GetPosition();
|
||||
newClipRectStorage += view->GetPosition();
|
||||
InvalidateRectDifference(parent, oldClipRectStorage, newClipRectStorage, NS_VMREFRESH_NO_SYNC);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool nsViewManager::CanScrollWithBitBlt(nsView* aView, nsPoint aDelta,
|
||||
nsRegion* aUpdateRegion)
|
||||
{
|
||||
|
@ -2351,15 +2287,7 @@ NS_IMETHODIMP nsViewManager::EndUpdateViewBatch(PRUint32 aUpdateFlags)
|
|||
|
||||
NS_IMETHODIMP nsViewManager::SetRootScrollableView(nsIScrollableView *aScrollable)
|
||||
{
|
||||
if (mRootScrollable) {
|
||||
NS_STATIC_CAST(nsScrollPortView*, mRootScrollable)->
|
||||
SetClipPlaceholdersToBounds(PR_FALSE);
|
||||
}
|
||||
mRootScrollable = aScrollable;
|
||||
if (mRootScrollable) {
|
||||
NS_STATIC_CAST(nsScrollPortView*, mRootScrollable)->
|
||||
SetClipPlaceholdersToBounds(PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -200,8 +200,6 @@ public:
|
|||
|
||||
NS_IMETHOD ResizeView(nsIView *aView, const nsRect &aRect, PRBool aRepaintExposedAreaOnly = PR_FALSE);
|
||||
|
||||
NS_IMETHOD SetViewChildClipRegion(nsIView *aView, const nsRegion *aRegion);
|
||||
|
||||
NS_IMETHOD SetViewCheckChildEvents(nsIView *aView, PRBool aEnable);
|
||||
|
||||
NS_IMETHOD SetViewFloating(nsIView *aView, PRBool aFloating);
|
||||
|
|
Загрузка…
Ссылка в новой задаче