app_server: Some cleanup of the new clipping code.
* Fixed some coding style issues and use regular pointers like everywhere else in app_server code. * Moved _RenderPicture() from View to AlphaMask.
This commit is contained in:
@@ -1,16 +1,22 @@
|
||||
/*
|
||||
* Copyright 2014, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Adrien Destugues <[email protected]>
|
||||
*/
|
||||
|
||||
|
||||
#include "AlphaMask.h"
|
||||
|
||||
#include "BitmapHWInterface.h"
|
||||
#include "BitmapManager.h"
|
||||
#include "DrawingEngine.h"
|
||||
#include "ServerBitmap.h"
|
||||
#include "View.h"
|
||||
|
||||
|
||||
AlphaMask::AlphaMask(View& view, ServerPicture& picture, bool inverse,
|
||||
AlphaMask::AlphaMask(View* view, ServerPicture* picture, bool inverse,
|
||||
BPoint origin)
|
||||
:
|
||||
fPicture(picture),
|
||||
@@ -22,13 +28,13 @@ AlphaMask::AlphaMask(View& view, ServerPicture& picture, bool inverse,
|
||||
fCachedMask(),
|
||||
fScanline(fCachedMask)
|
||||
{
|
||||
fPicture.AcquireReference();
|
||||
fPicture->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
AlphaMask::~AlphaMask()
|
||||
{
|
||||
fPicture.ReleaseReference();
|
||||
fPicture->ReleaseReference();
|
||||
if (fCachedBitmap)
|
||||
fCachedBitmap->ReleaseReference();
|
||||
}
|
||||
@@ -37,23 +43,87 @@ AlphaMask::~AlphaMask()
|
||||
scanline_unpacked_masked_type*
|
||||
AlphaMask::Generate()
|
||||
{
|
||||
// If rendering the picture fails, we will draw without any clipping.
|
||||
ServerBitmap* bitmap = fView._RenderPicture(&fPicture, fInverse);
|
||||
if (!bitmap)
|
||||
return NULL;
|
||||
// if (fCachedBitmap != NULL) {
|
||||
// // TODO: See if cached bitmap can actually be used. Don't use it
|
||||
// // when view scrolling offset has changed, for example. Generate()
|
||||
// // could be passed a current offset
|
||||
// return &fScanline;
|
||||
// }
|
||||
|
||||
// FIXME actually use the cached bitmap whenever possible, instead of
|
||||
// rendering the BPicture again and again.
|
||||
if (fCachedBitmap)
|
||||
if (fCachedBitmap != NULL)
|
||||
fCachedBitmap->ReleaseReference();
|
||||
|
||||
// If rendering the picture fails, we will draw without any clipping.
|
||||
ServerBitmap* bitmap = _RenderPicture(fPicture, fInverse);
|
||||
if (bitmap == NULL) {
|
||||
fCachedBitmap = NULL;
|
||||
fBuffer.attach(NULL, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fCachedBitmap = bitmap;
|
||||
|
||||
fBuffer.attach(fCachedBitmap->Bits(), fCachedBitmap->Width(),
|
||||
fCachedBitmap->Height(), fCachedBitmap->BytesPerRow());
|
||||
|
||||
BPoint offset(B_ORIGIN);
|
||||
fView.ConvertToScreen(&offset);
|
||||
fView->ConvertToScreen(&offset);
|
||||
|
||||
fCachedMask.attach(fBuffer, offset.x + fOrigin.x, offset.y + fOrigin.y,
|
||||
fInverse ? 255 : 0);
|
||||
|
||||
return &fScanline;
|
||||
}
|
||||
|
||||
|
||||
ServerBitmap*
|
||||
AlphaMask::_RenderPicture(ServerPicture* picture, bool inverse) const
|
||||
{
|
||||
BRect bounds(fView->Bounds());
|
||||
|
||||
// TODO: Only the alpha channel is relevant, but there is no B_ALPHA8
|
||||
// color space, so we use 300% more memory than needed.
|
||||
UtilityBitmap* bitmap = new(std::nothrow) UtilityBitmap(bounds, B_RGBA32,
|
||||
0);
|
||||
if (bitmap == NULL)
|
||||
return NULL;
|
||||
|
||||
// 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();
|
||||
if (engine == NULL) {
|
||||
delete bitmap;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy the current state of the client view, so we draw with the right
|
||||
// font, color and everything
|
||||
engine->SetDrawState(fView->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();
|
||||
}
|
||||
delete engine;
|
||||
|
||||
if (!inverse)
|
||||
return bitmap;
|
||||
|
||||
// Compute the inverse of our bitmap. There probably is a better way.
|
||||
uint32 size = bitmap->BitsLength();
|
||||
uint8* bits = (uint8*)bitmap->Bits();
|
||||
|
||||
for(uint32 i = 0; i < size; i++)
|
||||
bits[i] = 255 - bits[i];
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
+22
-18
@@ -17,26 +17,30 @@
|
||||
class ServerBitmap;
|
||||
|
||||
|
||||
class AlphaMask
|
||||
{
|
||||
public:
|
||||
AlphaMask(View& view,
|
||||
ServerPicture& mask, bool inverse,
|
||||
BPoint origin);
|
||||
~AlphaMask();
|
||||
scanline_unpacked_masked_type* Generate();
|
||||
class AlphaMask {
|
||||
public:
|
||||
AlphaMask(View* view, ServerPicture* mask,
|
||||
bool inverse, BPoint origin);
|
||||
~AlphaMask();
|
||||
|
||||
private:
|
||||
ServerPicture& fPicture;
|
||||
const bool fInverse;
|
||||
const BPoint fOrigin;
|
||||
View& fView;
|
||||
scanline_unpacked_masked_type* Generate();
|
||||
|
||||
ServerBitmap* fCachedBitmap;
|
||||
agg::rendering_buffer fBuffer;
|
||||
agg::clipped_alpha_mask fCachedMask;
|
||||
scanline_unpacked_masked_type fScanline;
|
||||
private:
|
||||
ServerBitmap* _RenderPicture(ServerPicture* picture,
|
||||
bool inverse) const;
|
||||
|
||||
|
||||
private:
|
||||
ServerPicture* fPicture;
|
||||
const bool fInverse;
|
||||
BPoint fOrigin;
|
||||
View* fView;
|
||||
|
||||
ServerBitmap* fCachedBitmap;
|
||||
agg::rendering_buffer fBuffer;
|
||||
agg::clipped_alpha_mask fCachedMask;
|
||||
scanline_unpacked_masked_type fScanline;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif // ALPHA_MASK_H
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "AlphaMask.h"
|
||||
#include "BitmapHWInterface.h"
|
||||
#include "BitmapManager.h"
|
||||
#include "Desktop.h"
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
@@ -1596,79 +1594,13 @@ View::SetAlphaMask(ServerPicture* picture, bool inverse, BPoint origin)
|
||||
|
||||
delete fAlphaMask;
|
||||
if (picture != NULL) {
|
||||
fAlphaMask = new(std::nothrow) AlphaMask(*this, *picture, inverse,
|
||||
fAlphaMask = new(std::nothrow) AlphaMask(this, picture, inverse,
|
||||
origin);
|
||||
} else
|
||||
fAlphaMask = NULL;
|
||||
}
|
||||
|
||||
|
||||
ServerBitmap*
|
||||
View::_RenderPicture(ServerPicture* picture, bool inverse)
|
||||
{
|
||||
BRect bounds(Bounds());
|
||||
|
||||
// TODO: Only the alpha channel is relevant, but there is no B_ALPHA8
|
||||
// color space, so we use 300% more memory than needed.
|
||||
UtilityBitmap* bitmap = new(std::nothrow) UtilityBitmap(bounds, B_RGBA32,
|
||||
0);
|
||||
if (bitmap == NULL)
|
||||
return 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 abstraction
|
||||
* above View and OffscreenContext and allow for inlining more methods.
|
||||
*/
|
||||
OffscreenWindow window(bitmap, "ClipToPicture", 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();
|
||||
if (engine == NULL) {
|
||||
delete bitmap;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy the current state of the client view, so we draw with the right
|
||||
// font, color and everything
|
||||
engine->SetDrawState(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();
|
||||
}
|
||||
delete engine;
|
||||
|
||||
if (!inverse)
|
||||
return bitmap;
|
||||
|
||||
// Compute the inverse of our bitmap. There probably is a better way.
|
||||
uint32 size = bitmap->BitsLength();
|
||||
uint8* bits = (uint8*)bitmap->Bits();
|
||||
|
||||
for(uint32 i = 0; i < size; i++)
|
||||
bits[i] = 255 - bits[i];
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
BRegion&
|
||||
View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ class ServerPicture;
|
||||
class BGradient;
|
||||
|
||||
class View: public DrawingContext {
|
||||
public:
|
||||
public:
|
||||
View(IntRect frame, IntPoint scrollingOffset,
|
||||
const char* name, int32 token,
|
||||
uint32 resizeMode, uint32 flags);
|
||||
@@ -232,10 +232,7 @@ class View: public DrawingContext {
|
||||
int32 level = 0);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend class AlphaMask;
|
||||
ServerBitmap* _RenderPicture(ServerPicture* picture,
|
||||
bool inverse);
|
||||
protected:
|
||||
BRegion& _ScreenClipping(BRegion* windowContentClipping,
|
||||
bool force = false) const;
|
||||
void _MoveScreenClipping(int32 x, int32 y,
|
||||
|
||||
Reference in New Issue
Block a user