* added SetUserClipping() and DrawingRegion(), which is used for

handling client defined clipping. The client clipping stays in local coords,
  which greatly simplyfies things. We ought to find a way to reduce the number
  of regions needed per Layer. I just added another one...
* renamed a few "lay"s to "child".
* used the new client added clipping in ServerWindow


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14847 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2005-11-11 00:19:32 +00:00
parent 41f78f7884
commit c5522d81d8
3 changed files with 86 additions and 60 deletions

View File

@ -50,6 +50,7 @@ Layer::Layer(BRect frame, const char* name, int32 token,
fVisible2(), fVisible2(),
fFullVisible2(), fFullVisible2(),
fDirtyForRebuild(), fDirtyForRebuild(),
fDrawingRegion(),
fDriver(driver), fDriver(driver),
fRootLayer(NULL), fRootLayer(NULL),
@ -421,6 +422,16 @@ Layer::SetName(const char* name)
fName.SetTo(name); fName.SetTo(name);
} }
// SetUserClipping
void
Layer::SetUserClipping(const BRegion& region)
{
fDrawState->SetClippingRegion(region);
// rebuild clipping
_RebuildDrawingRegion();
}
// SetFlags // SetFlags
void void
Layer::SetFlags(uint32 flags) Layer::SetFlags(uint32 flags)
@ -521,8 +532,6 @@ Layer::PushState()
{ {
fDrawState = fDrawState->PushState(); fDrawState = fDrawState->PushState();
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE); fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
// TODO: rebuild clipping and redraw
} }
@ -534,10 +543,15 @@ Layer::PopState()
return; return;
} }
bool rebuildClipping = fDrawState->ClippingRegion() != NULL;
fDrawState = fDrawState->PopState(); fDrawState = fDrawState->PopState();
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE); fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
// TODO: rebuild clipping and redraw // rebuild clipping
// (the clipping from the popped state is not effective anymore)
if (rebuildClipping)
_RebuildDrawingRegion();
} }
@ -880,21 +894,21 @@ void
Layer::PruneTree(void) Layer::PruneTree(void)
{ {
Layer* lay; Layer* child;
Layer* nextlay; Layer* nextChild;
lay = fFirstChild; child = fFirstChild;
fFirstChild = NULL; fFirstChild = NULL;
while (lay != NULL) { while (child != NULL) {
if (lay->fFirstChild != NULL) if (child->fFirstChild != NULL)
lay->PruneTree(); child->PruneTree();
nextlay = lay->fNextSibling; nextChild = child->fNextSibling;
lay->fNextSibling = NULL; child->fNextSibling = NULL;
delete lay; delete child;
lay = nextlay; child = nextChild;
} }
// Man, this thing is short. Elegant, ain't it? :P // Man, this thing is short. Elegant, ain't it? :P
} }
@ -1249,8 +1263,8 @@ Layer::_ResizeLayerFrameBy(float x, float y)
// call hook function // call hook function
ResizedByHook(dx, dy, true); // automatic ResizedByHook(dx, dy, true); // automatic
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) for (Layer* child = LastChild(); child; child = PreviousChild())
lay->resize_layer_frame_by(dx, dy); child->resize_layer_frame_by(dx, dy);
} }
} }
*/ */
@ -1281,39 +1295,39 @@ Layer::_RezizeLayerRedrawMore(BRegion &reg, float dx, float dy)
if (dx == 0 && dy == 0) if (dx == 0 && dy == 0)
return; return;
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) { for (Layer* child = LastChild(); child; child = PreviousChild()) {
uint16 rm = lay->fResizeMode & 0x0000FFFF; uint16 rm = child->fResizeMode & 0x0000FFFF;
if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) { if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
// NOTE: this is not exactly corect, but it works :-) // NOTE: this is not exactly corect, but it works :-)
// Normaly we shoud've used the lay's old, required region - the one returned // Normaly we shoud've used the child's old, required region - the one returned
// from get_user_region() with the old frame, and the current one. lay->Bounds() // from get_user_region() with the old frame, and the current one. child->Bounds()
// works for the moment so we leave it like this. // works for the moment so we leave it like this.
// calculate the old bounds. // calculate the old bounds.
BRect oldBounds(lay->Bounds()); BRect oldBounds(child->Bounds());
if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT) if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
oldBounds.right -=dx; oldBounds.right -=dx;
if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
oldBounds.bottom -=dy; oldBounds.bottom -=dy;
// compute the region that became visible because we got bigger OR smaller. // compute the region that became visible because we got bigger OR smaller.
BRegion regZ(lay->Bounds()); BRegion regZ(child->Bounds());
regZ.Include(oldBounds); regZ.Include(oldBounds);
regZ.Exclude(oldBounds&lay->Bounds()); regZ.Exclude(oldBounds & child->Bounds());
lay->ConvertToScreen(&regZ); child->ConvertToScreen(&regZ);
// intersect that with this'(not lay's) fullVisible region // intersect that with this'(not child's) fullVisible region
regZ.IntersectWith(&fFullVisible2); regZ.IntersectWith(&fFullVisible2);
reg.Include(&regZ); reg.Include(&regZ);
lay->_RezizeLayerRedrawMore(reg, child->_RezizeLayerRedrawMore(reg,
(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0, (rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0); (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
// above, OR this: // above, OR this:
// reg.Include(&lay->fFullVisible2); // reg.Include(&child->fFullVisible2);
} }
else else
if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) || if (((rm & 0x0F0F) == (uint16)B_FOLLOW_RIGHT && dx != 0) ||
@ -1321,7 +1335,7 @@ Layer::_RezizeLayerRedrawMore(BRegion &reg, float dx, float dy)
((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)|| ((rm & 0xF0F0) == (uint16)B_FOLLOW_BOTTOM && dy != 0)||
((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0)) ((rm & 0xF0F0) == (uint16)B_FOLLOW_V_CENTER && dy != 0))
{ {
reg.Include(&lay->fFullVisible2); reg.Include(&child->fFullVisible2);
} }
} }
} }
@ -1332,14 +1346,14 @@ Layer::_ResizeLayerFullUpdateOnResize(BRegion &reg, float dx, float dy)
if (dx == 0 && dy == 0) if (dx == 0 && dy == 0)
return; return;
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) { for (Layer* child = LastChild(); child; child = PreviousChild()) {
uint16 rm = lay->fResizeMode & 0x0000FFFF; uint16 rm = child->fResizeMode & 0x0000FFFF;
if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) { if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
if (lay->fFlags & B_FULL_UPDATE_ON_RESIZE && lay->fVisible2.CountRects() > 0) if (child->fFlags & B_FULL_UPDATE_ON_RESIZE && child->fVisible2.CountRects() > 0)
reg.Include(&lay->fVisible2); reg.Include(&child->fVisible2);
lay->_ResizeLayerFullUpdateOnResize(reg, child->_ResizeLayerFullUpdateOnResize(reg,
(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0, (rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0); (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
} }
@ -1409,15 +1423,15 @@ Layer::_RebuildVisibleRegions( const BRegion &invalid,
// allow this layer to hide some parts from its children // allow this layer to hide some parts from its children
_ReserveRegions(common); _ReserveRegions(common);
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) { for (Layer *child = LastChild(); child; child = PreviousChild()) {
if (lay == startFrom) if (child == startFrom)
fullRebuild = true; fullRebuild = true;
if (fullRebuild) if (fullRebuild)
lay->_RebuildVisibleRegions(invalid, common, lay->LastChild()); child->_RebuildVisibleRegions(invalid, common, child->LastChild());
// to let children know much they can take from parent's visible region // to let children know much they can take from parent's visible region
common.Exclude(&lay->fFullVisible2); common.Exclude(&child->fFullVisible2);
} }
// include what's left after all children took what they could. // include what's left after all children took what they could.
@ -1450,15 +1464,30 @@ Layer::_RebuildVisibleRegions( const BRegion &invalid,
// allow this layer to hide some parts from its children // allow this layer to hide some parts from its children
_ReserveRegions(common); _ReserveRegions(common);
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) { for (Layer *child = LastChild(); child; child = PreviousChild()) {
lay->_RebuildVisibleRegions(invalid, common, lay->LastChild()); child->_RebuildVisibleRegions(invalid, common, child->LastChild());
// to let children know much they can take from parent's visible region // to let children know much they can take from parent's visible region
common.Exclude(&lay->fFullVisible2); common.Exclude(&child->fFullVisible2);
} }
// include what's left after all children took what they could. // include what's left after all children took what they could.
fVisible2.Include(&common); fVisible2.Include(&common);
_RebuildDrawingRegion();
}
// _RebuildDrawingRegion
void
Layer::_RebuildDrawingRegion()
{
fDrawingRegion = fVisible2;
// apply user clipping which is in native coordinate system
if (const BRegion* userClipping = fDrawState->ClippingRegion()) {
BRegion screenUserClipping(*userClipping);
ConvertToScreen(&screenUserClipping);
fDrawingRegion.IntersectWith(&screenUserClipping);
}
} }
void void
@ -1539,13 +1568,13 @@ Layer::_AllRedraw(const BRegion &invalid)
} }
} }
for (Layer *lay = LastChild(); lay != NULL; lay = PreviousChild()) { for (Layer *child = LastChild(); child != NULL; child = PreviousChild()) {
if (!(lay->IsHidden())) { if (!(child->IsHidden())) {
BRegion common(lay->fFullVisible2); BRegion common(child->fFullVisible2);
common.IntersectWith(&invalid); common.IntersectWith(&invalid);
if (common.CountRects() > 0) if (common.CountRects() > 0)
lay->_AllRedraw(invalid); child->_AllRedraw(invalid);
} }
} }
} }

View File

@ -194,8 +194,12 @@ class Layer {
void SetFlags(uint32 flags); void SetFlags(uint32 flags);
// clipping stuff and redraw // clipping stuff and redraw
void SetUserClipping(const BRegion& region);
// region is expected in layer coordinates
inline const BRegion& VisibleRegion() const { return fVisible2; } inline const BRegion& VisibleRegion() const { return fVisible2; }
inline const BRegion& FullVisible() const { return fFullVisible2; } inline const BRegion& FullVisible() const { return fFullVisible2; }
inline const BRegion& DrawingRegion() const { return fDrawingRegion; }
virtual void GetWantedRegion(BRegion& reg); virtual void GetWantedRegion(BRegion& reg);
@ -224,6 +228,7 @@ class Layer {
void _RebuildVisibleRegions( const BRegion &invalid, void _RebuildVisibleRegions( const BRegion &invalid,
const BRegion &parentLocalVisible, const BRegion &parentLocalVisible,
const Layer *startFrom); const Layer *startFrom);
void _RebuildDrawingRegion();
void _ClearVisibleRegions(); void _ClearVisibleRegions();
void _ResizeLayerFrameBy(float x, float y); void _ResizeLayerFrameBy(float x, float y);
void _RezizeLayerRedrawMore(BRegion &reg, float dx, float dy); void _RezizeLayerRedrawMore(BRegion &reg, float dx, float dy);
@ -245,6 +250,7 @@ class Layer {
BRegion fVisible2; BRegion fVisible2;
BRegion fFullVisible2; BRegion fFullVisible2;
BRegion fDirtyForRebuild; BRegion fDirtyForRebuild;
BRegion fDrawingRegion;
DrawingEngine* fDriver; DrawingEngine* fDriver;
RootLayer* fRootLayer; RootLayer* fRootLayer;

View File

@ -1079,14 +1079,14 @@ if (myRootLayer)
fLink.Attach<int32>(0L); fLink.Attach<int32>(0L);
fLink.Flush(); fLink.Flush();
} else { } else {
// TODO: Watch out for the coordinate system in AS_LAYER_GET_CLIP_REGION BRegion drawingRegion = fCurrentLayer->DrawingRegion();
int32 rectCount = fCurrentLayer->fVisible2.CountRects(); int32 rectCount = drawingRegion.CountRects();
fLink.StartMessage(SERVER_TRUE); fLink.StartMessage(SERVER_TRUE);
fLink.Attach<int32>(rectCount); fLink.Attach<int32>(rectCount);
for (int32 i = 0; i < rectCount; i++) { for (int32 i = 0; i < rectCount; i++) {
BRect converted(fCurrentLayer->fVisible2.RectAt(i)); BRect converted(drawingRegion.RectAt(i));
fCurrentLayer->ConvertFromScreen(&converted); fCurrentLayer->ConvertFromScreen(&converted);
fLink.Attach<BRect>(converted); fLink.Attach<BRect>(converted);
} }
@ -1100,25 +1100,16 @@ if (myRootLayer)
{ {
DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: Layer: %s\n", Title(), fCurrentLayer->Name())); DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: Layer: %s\n", Title(), fCurrentLayer->Name()));
// TODO: Watch out for the coordinate system in AS_LAYER_SET_CLIP_REGION int32 rectCount;
int32 noOfRects; link.Read<int32>(&rectCount);
link.Read<int32>(&noOfRects);
BRegion region; BRegion region;
for (int i = 0; i < noOfRects; i++) { for (int32 i = 0; i < rectCount; i++) {
BRect r; BRect r;
link.Read<BRect>(&r); link.Read<BRect>(&r);
fCurrentLayer->ConvertToScreen(&r);
region.Include(r); region.Include(r);
} }
// TODO: Turned off user clipping for now (will probably not harm anything but performance right now) fCurrentLayer->SetUserClipping(region);
// We need to integrate user clipping more, in Layer::PopState, the clipping needs to be
// restored too. "AS_LAYER_SET_CLIP_REGION" is irritating, as I think it should be
// "AS_LAYER_CONSTRAIN_CLIP_REGION", since it means to "add" to the current clipping, not "set" it.
// fCurrentLayer->CurrentState()->SetClippingRegion(region);
// TODO: rebuild clipping and redraw
break; break;
} }
@ -1622,7 +1613,7 @@ ServerWindow::_DispatchGraphicsMessage(int32 code, BPrivate::LinkReceiver &link)
// NOTE: fCurrentLayer and fCurrentLayer->fLayerData cannot be NULL, // NOTE: fCurrentLayer and fCurrentLayer->fLayerData cannot be NULL,
// _DispatchGraphicsMessage() is called from _DispatchMessage() which // _DispatchGraphicsMessage() is called from _DispatchMessage() which
// checks both these conditions // checks both these conditions
BRegion rreg(fCurrentLayer->VisibleRegion()); BRegion rreg(fCurrentLayer->DrawingRegion());
if (fWinBorder->InUpdate()) if (fWinBorder->InUpdate())
rreg.IntersectWith(&fWinBorder->RegionToBeUpdated()); rreg.IntersectWith(&fWinBorder->RegionToBeUpdated());