Add new classes required for picture clipping

* agg_clipped_alpha_mask is a modified version of agg alpha mask class,
allowing us to offset the mask bitmap to follow the view position, and
also allows "inverse" clipping, where everything outside the bitmap is
considered inside the clipping region.
* AlphaMask is a container class keeping the ServerPicture, it's bitmap
rendering, and other relevant information. It will be used to save and
restore the clipping picture as part of the view state.
* Because these classes introduce more coupling within app_server, it's
not possible anymore to split out tst_app_server from
libtestappserver.so. Instead, move everything to libtestappserver.so,
except the things that actually need to not be there (to avoid
interferences with the host API). As a result, the previously introduced
stub cpp file to work around this problem isn't needed anymore.

The design for all this (and the previous commit) is Stippi's work.
Thanks for the advice and implementation hints!
This commit is contained in:
Adrien Destugues 2014-01-28 15:49:14 +01:00
parent f08d5477d8
commit 35d6e0fe81
7 changed files with 258 additions and 69 deletions

View File

@ -0,0 +1,59 @@
/*
* Copyright 2014, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#include "AlphaMask.h"
#include "ServerBitmap.h"
#include "View.h"
AlphaMask::AlphaMask(View& view, ServerPicture& picture, bool inverse,
BPoint origin)
:
fPicture(picture),
fInverse(inverse),
fOrigin(origin),
fView(view),
fCachedBitmap(NULL),
fBuffer(),
fCachedMask(),
fScanline(fCachedMask)
{
fPicture.AcquireReference();
}
AlphaMask::~AlphaMask()
{
fPicture.ReleaseReference();
if (fCachedBitmap)
fCachedBitmap->ReleaseReference();
}
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;
// FIXME actually use the cached bitmap whenever possible, instead of
// rendering the BPicture again and again.
if (fCachedBitmap)
fCachedBitmap->ReleaseReference();
fCachedBitmap = bitmap;
fBuffer.attach(fCachedBitmap->Bits(), fCachedBitmap->Width(),
fCachedBitmap->Height(), fCachedBitmap->BytesPerRow());
BPoint offset(B_ORIGIN);
fView.ConvertToScreen(&offset);
fCachedMask.attach(fBuffer, offset.x + fOrigin.x, offset.y + fOrigin.y,
fInverse ? 255 : 0);
return &fScanline;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2014, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef ALPHA_MASK_H
#define ALPHA_MASK_H
#include "agg_clipped_alpha_mask.h"
#include "ServerBitmap.h"
#include "ServerPicture.h"
#include "drawing/Painter/defines.h"
class ServerBitmap;
class AlphaMask
{
public:
AlphaMask(View& view,
ServerPicture& mask, bool inverse,
BPoint origin);
~AlphaMask();
scanline_unpacked_masked_type* Generate();
private:
ServerPicture& fPicture;
const bool fInverse;
const BPoint fOrigin;
View& fView;
ServerBitmap* fCachedBitmap;
agg::rendering_buffer fBuffer;
agg::clipped_alpha_mask fCachedMask;
scanline_unpacked_masked_type fScanline;
};
#endif

View File

@ -79,7 +79,6 @@ Server app_server :
ScreenConfigurations.cpp
ScreenManager.cpp
ServerApp.cpp
ServerAppStub.cpp
ServerBitmap.cpp
ServerCursor.cpp
ServerFont.cpp

View File

@ -472,6 +472,36 @@ ServerApp::RemovePicture(ServerPicture* picture)
}
/*! Called from the ClientMemoryAllocator whenever a server area could be
deleted.
A message is then sent to the client telling it that it can delete its
client area, too.
*/
void
ServerApp::NotifyDeleteClientArea(area_id serverArea)
{
BMessage notify(kMsgDeleteServerMemoryArea);
notify.AddInt32("server area", serverArea);
SendMessageToClient(&notify);
}
/*! \brief Send a message to the ServerApp's BApplication
\param message The message to send
*/
void
ServerApp::SendMessageToClient(BMessage* message) const
{
status_t status = fHandlerMessenger.SendMessage(message, (BHandler*)NULL,
100000);
if (status != B_OK) {
syslog(LOG_ERR, "app %s send to client failed: %s\n", Signature(),
strerror(status));
}
}
// #pragma mark - private methods

View File

@ -1,57 +0,0 @@
/*
* Copyright 2001-2013, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Adrian Oanca <adioanca@cotty.iren.ro>
* Stephan Aßmus <superstippi@gmx.de>
* Stefano Ceccherini (burton666@libero.it)
* Axel Dörfler, axeld@pinc-software.de
* Jérôme Duval, jerome.duval@free.fr
* Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
* Philippe Saint-Pierre, stpere@gmail.com
* Wim van der Meer, <WPJvanderMeer@gmail.com>
*/
#include "ServerApp.h"
#include <syslog.h>
#include <ServerProtocol.h>
/* These methods are split to a separate compilation unit to allow splitting
* the test_app_server and libtestappserver.so on a convenient boundary.
*/
/*! Called from the ClientMemoryAllocator whenever a server area could be
deleted.
A message is then sent to the client telling it that it can delete its
client area, too.
*/
void
ServerApp::NotifyDeleteClientArea(area_id serverArea)
{
BMessage notify(kMsgDeleteServerMemoryArea);
notify.AddInt32("server area", serverArea);
SendMessageToClient(&notify);
}
/*! \brief Send a message to the ServerApp's BApplication
\param message The message to send
*/
void
ServerApp::SendMessageToClient(BMessage* message) const
{
status_t status = fHandlerMessenger.SendMessage(message, (BHandler*)NULL,
100000);
if (status != B_OK) {
syslog(LOG_ERR, "app %s send to client failed: %s\n", Signature(),
strerror(status));
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright 2014, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
*
* Class clipped_alpha_mask, a modified version of alpha_mask_u8 that can
* offset the mask, and has a controllable value for the area outside it.
*/
#ifndef AGG_CLIPED_ALPHA_MASK_INCLUDED
#define AGG_CLIPED_ALPHA_MASK_INCLUDED
#include <agg_alpha_mask_u8.h>
#include <agg_rendering_buffer.h>
namespace agg
{
class clipped_alpha_mask
{
public:
typedef int8u cover_type;
enum cover_scale_e
{
cover_shift = 8,
cover_none = 0,
cover_full = 255
};
clipped_alpha_mask()
: m_xOffset(0), m_yOffset(0), m_rbuf(0), m_outside(0) {}
clipped_alpha_mask(rendering_buffer& rbuf)
: m_xOffset(0), m_yOffset(0), m_rbuf(&rbuf), m_outside(0) {}
void attach(rendering_buffer& rbuf, int x, int y, int8u outside)
{
m_rbuf = &rbuf;
m_xOffset = x;
m_yOffset = y;
m_outside = outside;
}
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{
x -= m_xOffset;
y -= m_yOffset;
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(y < 0 || y > ymax)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
return;
}
if(x < 0)
{
count += x;
if(count <= 0)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
return;
}
memset(covers, m_outside, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
if(x + count > xmax)
{
int rest = x + count - xmax - 1;
count -= rest;
if(count <= 0)
{
memset(dst, m_outside, num_pix * sizeof(cover_type));
return;
}
memset(covers + count, m_outside, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
{
*covers = (cover_type)((cover_full + (*covers) * (*mask))
>> cover_shift);
++covers;
mask += Step;
}
while(--count);
}
private:
int m_xOffset;
int m_yOffset;
rendering_buffer* m_rbuf;
int8u m_outside;
// TODO this assumes an RGBA bitmap and only uses the alpha channel.
// We should keep the masking bitmap as an 8-bit bitmap with only the
// alpha channel, to save memory. (this would be Step=1, Offset=0)
static const int Step = 4;
static const int Offset = 3;
};
}
#endif

View File

@ -100,26 +100,16 @@ SharedLibrary libtestappserver.so :
MultiLocker.cpp
Overlay.cpp
RGBColor.cpp
ServerAppStub.cpp
ServerBitmap.cpp
ServerCursor.cpp
ServerFont.cpp
SystemPalette.cpp
# drawing
drawing_support.cpp
PatternHandler.cpp
# trace.c
# libraries
: be libpainter.a libagg.a libtextencoding.so libshared.a
[ BuildFeatureAttribute freetype : library ]
;
AddResources test_app_server : test_app_server.rdef ;
Server test_app_server :
# Misc. Sources
ProfileMessageSupport.cpp
EventDispatcher.cpp
@ -152,6 +142,7 @@ Server test_app_server :
drawing_support.cpp
MallocBuffer.cpp
AlphaMask.cpp
BitmapHWInterface.cpp
DesktopSettings.cpp
DrawingContext.cpp
@ -175,11 +166,22 @@ Server test_app_server :
StackAndTile.cpp
Stacking.cpp
Tiling.cpp
# libraries
: be libpainter.a libagg.a liblinprog.a libtextencoding.so libshared.a
[ BuildFeatureAttribute freetype : library ]
;
AddResources test_app_server : test_app_server.rdef ;
Server test_app_server :
# drawing
drawing_support.cpp
# libraries
:
[ BuildFeatureAttribute zlib : library ] libtestappserver.so be
libhwinterface.so libhwinterfaceimpl.so liblinprog.a libtextencoding.so
libhwinterface.so libhwinterfaceimpl.so libtextencoding.so
[ BuildFeatureAttribute freetype : library ]
$(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++)
;