BView: move ClipToPicture code to app_server
Now that DrawingContext makes it possible to draw on a ServerBitmap without the need for a BView, we can replay pictures on app_server side, avoiding the cost of creating a BBitmap, offscreen BWindow, and BView from the application side. The offscreen drawing context gets the same state as the view it's rendering the picture for, so font size, drawing mode, etc are used. The implementation is still the suboptimal one, converting the BBitmap to a BRegion, and using that for clipping. Changing that comes next.
This commit is contained in:
parent
70ebf47bab
commit
e0d1cc186a
@ -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<int32>(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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user