diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index 6c51460e71..1ddb6c992e 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -5092,69 +5092,6 @@ BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync) if (!picture) return; -#if 1 - // TODO: Move the implementation to the server!!! - // This implementation is pretty slow, since just creating an offscreen - // bitmap takes a lot of time. That's the main reason why it should be moved - // to the server. - - // Here the idea is to get rid of the padding bytes in the bitmap, - // as padding complicates and slows down the iteration. - // TODO: Maybe it's not so nice as it assumes BBitmaps to be aligned - // to a 4 byte boundary. - BRect bounds(Bounds()); - if ((bounds.IntegerWidth() + 1) % 32) { - bounds.right = bounds.left + ((bounds.IntegerWidth() + 1) / 32 + 1) - * 32 - 1; - } - - // TODO: I used a RGBA32 bitmap because drawing on a GRAY8 doesn't work. - BBitmap* bitmap = new(std::nothrow) BBitmap(bounds, B_RGBA32, true); - if (bitmap != NULL && bitmap->InitCheck() == B_OK && bitmap->Lock()) { - BView* view = new(std::nothrow) BView(bounds, "drawing view", - B_FOLLOW_NONE, 0); - if (view != NULL) { - bitmap->AddChild(view); - view->DrawPicture(picture, where); - view->Sync(); - } - bitmap->Unlock(); - } - - BRegion region; - int32 width = bounds.IntegerWidth() + 1; - int32 height = bounds.IntegerHeight() + 1; - if (bitmap != NULL && bitmap->LockBits() == B_OK) { - uint32 bit = 0; - uint32* bits = (uint32*)bitmap->Bits(); - clipping_rect rect; - - // TODO: A possible optimization would be adding "spans" instead - // of 1x1 rects. That would probably help with very complex - // BPictures - for (int32 y = 0; y < height; y++) { - for (int32 x = 0; x < width; x++) { - bit = *bits++; - if (bit != 0xFFFFFFFF) { - rect.left = x; - rect.right = rect.left; - rect.top = rect.bottom = y; - region.Include(rect); - } - } - } - bitmap->UnlockBits(); - } - delete bitmap; - - if (invert) { - BRegion inverseRegion; - inverseRegion.Include(Bounds()); - inverseRegion.Exclude(®ion); - ConstrainClippingRegion(&inverseRegion); - } else - ConstrainClippingRegion(®ion); -#else if (_CheckOwnerLockAndSwitchCurrent()) { fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE); fOwner->fLink->Attach(picture->Token()); @@ -5170,7 +5107,6 @@ BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync) } fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT; -#endif } diff --git a/src/servers/app/DrawingContext.h b/src/servers/app/DrawingContext.h index da30566a6d..5a4674522a 100644 --- a/src/servers/app/DrawingContext.h +++ b/src/servers/app/DrawingContext.h @@ -75,4 +75,30 @@ class DrawingContext { }; +class OffscreenContext: public DrawingContext { + public: + OffscreenContext(DrawingEngine* engine) + : fDrawingEngine(engine) + {}; + + // Screen and View coordinates are the same for us. + // DrawState already takes care of World<>View + // conversions. + void ConvertToScreen(BPoint*) const {} + void ConvertToScreen(IntPoint*) const {} + void ConvertToScreen(BRect*) const {} + void ConvertToScreen(IntRect*) const {} + void ConvertToScreen(BRegion*) const {} + void ConvertFromScreen(BPoint*) const {} + + DrawingEngine* GetDrawingEngine() const { return fDrawingEngine; } + + void RebuildClipping(bool deep) { /* TODO */ } + ServerPicture* GetPicture(int32 token) const + { /* TODO */ return NULL; } + private: + DrawingEngine* fDrawingEngine; +}; + + #endif diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 34517a30a9..0d894b41be 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -53,6 +53,9 @@ #include "AppServer.h" #include "AutoDeleter.h" +#include "BBitmapBuffer.h" +#include "BitmapHWInterface.h" +#include "BitmapManager.h" #include "Desktop.h" #include "DirectWindowInfo.h" #include "DrawingEngine.h" @@ -3755,7 +3758,87 @@ status_t ServerWindow::PictureToRegion(ServerPicture* picture, BRegion& region, bool inverse, BPoint where) { - fprintf(stderr, "ServerWindow::PictureToRegion() not implemented\n"); + // Here the idea is to get rid of the padding bytes in the bitmap, + // as padding complicates and slows down the iteration. + // TODO: Maybe it's not so nice as it assumes BBitmaps to be aligned + // to a 4 byte boundary. + BRect bounds(fCurrentView->Bounds()); + if ((bounds.IntegerWidth() + 1) % 32) { + bounds.right = bounds.left + ((bounds.IntegerWidth() + 1) / 32 + 1) + * 32 - 1; + } + + // TODO: I used a RGBA32 bitmap because drawing on a GRAY8 doesn't work. + UtilityBitmap* bitmap = new UtilityBitmap(bounds, B_RGBA32, 0); + if (bitmap != NULL) { +#if 0 + /* + * TODO stippi says we could use OffscreenWindow to do this, but there + * doesn't seem to be a way to create a View without a BView on + * application side (the constructor wants a token). + * This would be better, as it would avoid the DrawingContext mess. + */ + OffscreenWindow window(bitmap, "ClipToPicture", fCurrentView->Window()); + View view(bounds, IntPoint(0, 0), "ClipToPicture"); + window->SetTopView(view); +#endif + + // Clear the bitmap with the transparent color + memset(bitmap->Bits(), 0, bitmap->BitsLength()); + + // Render the picture to the bitmap + BitmapHWInterface interface(bitmap); + DrawingEngine* engine = interface.CreateDrawingEngine(); + // Copy the current state of the client view, so we draw with the right + // font, color and everything + engine->SetDrawState(fCurrentView->CurrentState()); + OffscreenContext context(engine); + if (engine->LockParallelAccess()) + { + // FIXME ConstrainClippingRegion docs says passing NULL disables + // all clipping. This doesn't work and will crash in Painter. + BRegion clipping; + clipping.Include(bounds); + engine->ConstrainClippingRegion(&clipping); + picture->Play(&context); + engine->UnlockParallelAccess(); + } + } + + // TODO stop here: we want agg to clip using the bitmap (with alpha), not + // the region. + region.MakeEmpty(); - return B_ERROR; + int32 width = bounds.IntegerWidth() + 1; + int32 height = bounds.IntegerHeight() + 1; + if (bitmap != NULL) { + uint32 bit = 0; + uint32* bits = (uint32*)bitmap->Bits(); + clipping_rect rect; + + // TODO: A possible optimization would be adding "spans" instead + // of 1x1 rects. That would probably help with very complex + // BPictures + for (int32 y = 0; y < height; y++) { + for (int32 x = 0; x < width; x++) { + bit = *bits++; + if (bit != 0) { + rect.left = x; + rect.right = rect.left; + rect.top = rect.bottom = y; + region.Include(rect); + } + } + } + } + delete bitmap; + + if (inverse) { + BRegion inverseRegion; + inverseRegion.Include(BRect(fCurrentView->Bounds())); + inverseRegion.Exclude(®ion); + region = inverseRegion; + } + + return B_OK; }