* 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(),
fFullVisible2(),
fDirtyForRebuild(),
fDrawingRegion(),
fDriver(driver),
fRootLayer(NULL),
@ -421,6 +422,16 @@ Layer::SetName(const char* name)
fName.SetTo(name);
}
// SetUserClipping
void
Layer::SetUserClipping(const BRegion& region)
{
fDrawState->SetClippingRegion(region);
// rebuild clipping
_RebuildDrawingRegion();
}
// SetFlags
void
Layer::SetFlags(uint32 flags)
@ -521,8 +532,6 @@ Layer::PushState()
{
fDrawState = fDrawState->PushState();
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
// TODO: rebuild clipping and redraw
}
@ -534,10 +543,15 @@ Layer::PopState()
return;
}
bool rebuildClipping = fDrawState->ClippingRegion() != NULL;
fDrawState = fDrawState->PopState();
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* lay;
Layer* nextlay;
Layer* child;
Layer* nextChild;
lay = fFirstChild;
child = fFirstChild;
fFirstChild = NULL;
while (lay != NULL) {
if (lay->fFirstChild != NULL)
lay->PruneTree();
while (child != NULL) {
if (child->fFirstChild != NULL)
child->PruneTree();
nextlay = lay->fNextSibling;
lay->fNextSibling = NULL;
nextChild = child->fNextSibling;
child->fNextSibling = NULL;
delete lay;
lay = nextlay;
delete child;
child = nextChild;
}
// Man, this thing is short. Elegant, ain't it? :P
}
@ -1249,8 +1263,8 @@ Layer::_ResizeLayerFrameBy(float x, float y)
// call hook function
ResizedByHook(dx, dy, true); // automatic
for (Layer *lay = LastChild(); lay; lay = PreviousChild())
lay->resize_layer_frame_by(dx, dy);
for (Layer* child = LastChild(); child; child = PreviousChild())
child->resize_layer_frame_by(dx, dy);
}
}
*/
@ -1281,39 +1295,39 @@ Layer::_RezizeLayerRedrawMore(BRegion &reg, float dx, float dy)
if (dx == 0 && dy == 0)
return;
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
uint16 rm = lay->fResizeMode & 0x0000FFFF;
for (Layer* child = LastChild(); child; child = PreviousChild()) {
uint16 rm = child->fResizeMode & 0x0000FFFF;
if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT || (rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM) {
// NOTE: this is not exactly corect, but it works :-)
// Normaly we shoud've used the lay's old, required region - the one returned
// from get_user_region() with the old frame, and the current one. lay->Bounds()
// 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. child->Bounds()
// works for the moment so we leave it like this.
// calculate the old bounds.
BRect oldBounds(lay->Bounds());
BRect oldBounds(child->Bounds());
if ((rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT)
oldBounds.right -=dx;
if ((rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM)
oldBounds.bottom -=dy;
// compute the region that became visible because we got bigger OR smaller.
BRegion regZ(lay->Bounds());
BRegion regZ(child->Bounds());
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);
reg.Include(&regZ);
lay->_RezizeLayerRedrawMore(reg,
child->_RezizeLayerRedrawMore(reg,
(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 0,
(rm & 0xF0F0) == (uint16)B_FOLLOW_TOP_BOTTOM? dy: 0);
// above, OR this:
// reg.Include(&lay->fFullVisible2);
// reg.Include(&child->fFullVisible2);
}
else
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_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)
return;
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
uint16 rm = lay->fResizeMode & 0x0000FFFF;
for (Layer* child = LastChild(); child; child = PreviousChild()) {
uint16 rm = child->fResizeMode & 0x0000FFFF;
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)
reg.Include(&lay->fVisible2);
if (child->fFlags & B_FULL_UPDATE_ON_RESIZE && child->fVisible2.CountRects() > 0)
reg.Include(&child->fVisible2);
lay->_ResizeLayerFullUpdateOnResize(reg,
child->_ResizeLayerFullUpdateOnResize(reg,
(rm & 0x0F0F) == (uint16)B_FOLLOW_LEFT_RIGHT? dx: 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
_ReserveRegions(common);
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
if (lay == startFrom)
for (Layer *child = LastChild(); child; child = PreviousChild()) {
if (child == startFrom)
fullRebuild = true;
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
common.Exclude(&lay->fFullVisible2);
common.Exclude(&child->fFullVisible2);
}
// 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
_ReserveRegions(common);
for (Layer *lay = LastChild(); lay; lay = PreviousChild()) {
lay->_RebuildVisibleRegions(invalid, common, lay->LastChild());
for (Layer *child = LastChild(); child; child = PreviousChild()) {
child->_RebuildVisibleRegions(invalid, common, child->LastChild());
// 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.
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
@ -1539,13 +1568,13 @@ Layer::_AllRedraw(const BRegion &invalid)
}
}
for (Layer *lay = LastChild(); lay != NULL; lay = PreviousChild()) {
if (!(lay->IsHidden())) {
BRegion common(lay->fFullVisible2);
for (Layer *child = LastChild(); child != NULL; child = PreviousChild()) {
if (!(child->IsHidden())) {
BRegion common(child->fFullVisible2);
common.IntersectWith(&invalid);
if (common.CountRects() > 0)
lay->_AllRedraw(invalid);
child->_AllRedraw(invalid);
}
}
}

View File

@ -194,8 +194,12 @@ class Layer {
void SetFlags(uint32 flags);
// 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& FullVisible() const { return fFullVisible2; }
inline const BRegion& DrawingRegion() const { return fDrawingRegion; }
virtual void GetWantedRegion(BRegion& reg);
@ -224,6 +228,7 @@ class Layer {
void _RebuildVisibleRegions( const BRegion &invalid,
const BRegion &parentLocalVisible,
const Layer *startFrom);
void _RebuildDrawingRegion();
void _ClearVisibleRegions();
void _ResizeLayerFrameBy(float x, float y);
void _RezizeLayerRedrawMore(BRegion &reg, float dx, float dy);
@ -245,6 +250,7 @@ class Layer {
BRegion fVisible2;
BRegion fFullVisible2;
BRegion fDirtyForRebuild;
BRegion fDrawingRegion;
DrawingEngine* fDriver;
RootLayer* fRootLayer;

View File

@ -1079,14 +1079,14 @@ if (myRootLayer)
fLink.Attach<int32>(0L);
fLink.Flush();
} else {
// TODO: Watch out for the coordinate system in AS_LAYER_GET_CLIP_REGION
int32 rectCount = fCurrentLayer->fVisible2.CountRects();
BRegion drawingRegion = fCurrentLayer->DrawingRegion();
int32 rectCount = drawingRegion.CountRects();
fLink.StartMessage(SERVER_TRUE);
fLink.Attach<int32>(rectCount);
for (int32 i = 0; i < rectCount; i++) {
BRect converted(fCurrentLayer->fVisible2.RectAt(i));
BRect converted(drawingRegion.RectAt(i));
fCurrentLayer->ConvertFromScreen(&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()));
// TODO: Watch out for the coordinate system in AS_LAYER_SET_CLIP_REGION
int32 noOfRects;
link.Read<int32>(&noOfRects);
int32 rectCount;
link.Read<int32>(&rectCount);
BRegion region;
for (int i = 0; i < noOfRects; i++) {
for (int32 i = 0; i < rectCount; i++) {
BRect r;
link.Read<BRect>(&r);
fCurrentLayer->ConvertToScreen(&r);
region.Include(r);
}
// TODO: Turned off user clipping for now (will probably not harm anything but performance right now)
// 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
fCurrentLayer->SetUserClipping(region);
break;
}
@ -1622,7 +1613,7 @@ ServerWindow::_DispatchGraphicsMessage(int32 code, BPrivate::LinkReceiver &link)
// NOTE: fCurrentLayer and fCurrentLayer->fLayerData cannot be NULL,
// _DispatchGraphicsMessage() is called from _DispatchMessage() which
// checks both these conditions
BRegion rreg(fCurrentLayer->VisibleRegion());
BRegion rreg(fCurrentLayer->DrawingRegion());
if (fWinBorder->InUpdate())
rreg.IntersectWith(&fWinBorder->RegionToBeUpdated());