Merge branch 'app_server'
Conflicts: src/kits/interface/PicturePlayer.cpp src/servers/app/ServerPicture.cpp In addition, the following files were also adapted to master branch BPicture changes during the merge: src/kits/interface/PicturePlayer.h src/servers/app/PictureBoundingBoxPlayer.cpp
This commit is contained in:
@@ -505,6 +505,9 @@ public:
|
||||
void DrawPictureAsync(const char* filename,
|
||||
long offset, BPoint where);
|
||||
|
||||
void BeginLayer(uint8 opacity);
|
||||
void EndLayer();
|
||||
|
||||
status_t SetEventMask(uint32 mask, uint32 options = 0);
|
||||
uint32 EventMask();
|
||||
status_t SetMouseEventMask(uint32 mask,
|
||||
|
||||
@@ -23,7 +23,14 @@ namespace BPrivate {
|
||||
extern const char* kRAppLooperPortName;
|
||||
|
||||
|
||||
#define B_REGISTRAR_SIGNATURE "application/x-vnd.haiku-registrar"
|
||||
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
||||
# define B_REGISTRAR_SIGNATURE "application/x-vnd.haiku-registrar"
|
||||
# define B_REGISTRAR_PORT_NAME "system:roster"
|
||||
#else
|
||||
# define B_REGISTRAR_SIGNATURE "application/x-vnd.test-registrar"
|
||||
# define B_REGISTRAR_PORT_NAME "haiku-test:roster"
|
||||
#endif
|
||||
|
||||
#define B_REGISTRAR_AUTHENTICATION_PORT_NAME "auth"
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* Jérôme Duval, [email protected]
|
||||
* Axel Dörfler, [email protected]
|
||||
* Andrej Spielmann, <[email protected]>
|
||||
* Julian Harnath, <[email protected]>
|
||||
*/
|
||||
#ifndef APP_SERVER_PROTOCOL_H
|
||||
#define APP_SERVER_PROTOCOL_H
|
||||
@@ -15,6 +16,10 @@
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
#ifdef HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
||||
# define SERVER_PORT_NAME "haiku-test:app_server"
|
||||
#endif
|
||||
|
||||
#if TEST_MODE
|
||||
# define SERVER_INPUT_PORT "haiku-test:input port"
|
||||
#endif
|
||||
@@ -319,6 +324,8 @@ enum {
|
||||
AS_VIEW_SET_VIEW_BITMAP,
|
||||
AS_VIEW_SET_PATTERN,
|
||||
AS_SET_CURRENT_VIEW,
|
||||
AS_VIEW_BEGIN_LAYER,
|
||||
AS_VIEW_END_LAYER,
|
||||
|
||||
// BDirectWindow/BWindowScreen codes
|
||||
AS_DIRECT_WINDOW_GET_SYNC_DATA,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Haiku, Inc. All rights reserved.
|
||||
* Copyright 2006-2015 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stefano Ceccherini, [email protected]
|
||||
* Julian Harnath, <[email protected]>
|
||||
*/
|
||||
#ifndef _PICTURE_DATA_WRITER_H
|
||||
#define _PICTURE_DATA_WRITER_H
|
||||
@@ -17,6 +18,7 @@
|
||||
#include <stack>
|
||||
|
||||
|
||||
class Layer;
|
||||
class BPositionIO;
|
||||
class BRegion;
|
||||
|
||||
@@ -93,6 +95,8 @@ public:
|
||||
status_t WriteDrawPicture(const BPoint& where,
|
||||
const int32& token);
|
||||
|
||||
status_t WriteBlendLayer(Layer* layer);
|
||||
|
||||
protected:
|
||||
// throw a status_t on error
|
||||
void BeginOp(const int16& op);
|
||||
|
||||
@@ -23,6 +23,7 @@ class BAffineTransform;
|
||||
class BList;
|
||||
class BPicture;
|
||||
class BShape;
|
||||
class Layer;
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
@@ -83,6 +84,7 @@ struct picture_player_callbacks {
|
||||
void (*set_blending_mode)(void* userData, source_alpha alphaSourceMode,
|
||||
alpha_function alphaFunctionMode);
|
||||
void (*set_transform)(void* userData, const BAffineTransform& transform);
|
||||
void (*blend_layer)(void* userData, Layer* layer);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -52,10 +52,11 @@ enum {
|
||||
B_PIC_SET_FONT_BPP = 0x0388,
|
||||
B_PIC_SET_FONT_FACE = 0x0389,
|
||||
B_PIC_SET_TRANSFORM = 0x0390,
|
||||
B_PIC_BLEND_LAYER = 0x0391
|
||||
};
|
||||
|
||||
|
||||
const static uint32 kOpsTableSize = 49;
|
||||
const static uint32 kOpsTableSize = 50;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -176,6 +176,9 @@ is_app_showing_modal_window(team_id team)
|
||||
}
|
||||
|
||||
|
||||
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
||||
|
||||
|
||||
/*! Creates a connection with the desktop.
|
||||
*/
|
||||
status_t
|
||||
@@ -208,4 +211,61 @@ create_desktop_connection(ServerLink* link, const char* name, int32 capacity)
|
||||
}
|
||||
|
||||
|
||||
#else // HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
||||
|
||||
|
||||
static port_id sServerPort = -1;
|
||||
|
||||
|
||||
port_id
|
||||
get_app_server_port()
|
||||
{
|
||||
if (sServerPort < 0) {
|
||||
// No need for synchronization - in the worst case, we'll call
|
||||
// find_port() twice.
|
||||
sServerPort = find_port(SERVER_PORT_NAME);
|
||||
}
|
||||
|
||||
return sServerPort;
|
||||
}
|
||||
|
||||
|
||||
/*! Creates a connection with the desktop.
|
||||
*/
|
||||
status_t
|
||||
create_desktop_connection(ServerLink* link, const char* name, int32 capacity)
|
||||
{
|
||||
port_id serverPort = get_app_server_port();
|
||||
if (serverPort < 0)
|
||||
return serverPort;
|
||||
|
||||
// Create the port so that the app_server knows where to send messages
|
||||
port_id clientPort = create_port(capacity, name);
|
||||
if (clientPort < 0)
|
||||
return clientPort;
|
||||
|
||||
link->SetTo(serverPort, clientPort);
|
||||
|
||||
link->StartMessage(AS_GET_DESKTOP);
|
||||
link->Attach<port_id>(clientPort);
|
||||
link->Attach<int32>(getuid());
|
||||
link->AttachString(getenv("TARGET_SCREEN"));
|
||||
link->Attach<int32>(AS_PROTOCOL_VERSION);
|
||||
|
||||
int32 code;
|
||||
if (link->FlushWithReply(code) != B_OK || code != B_OK) {
|
||||
link->SetSenderPort(-1);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
link->Read<port_id>(&serverPort);
|
||||
link->SetSenderPort(serverPort);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
#endif // HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
+13
-3
@@ -2620,10 +2620,10 @@ BRoster::_InitMessenger()
|
||||
DBG(OUT("BRoster::InitMessengers()\n"));
|
||||
|
||||
// find the registrar port
|
||||
BMessage data;
|
||||
if (BLaunchRoster().GetData("application/x-vnd.Haiku-registrar", data)
|
||||
== B_OK) {
|
||||
|
||||
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
||||
BMessage data;
|
||||
if (BLaunchRoster().GetData(B_REGISTRAR_SIGNATURE, data) == B_OK) {
|
||||
port_id port = data.GetInt32("port", -1);
|
||||
team_id team = data.GetInt32("team", -1);
|
||||
|
||||
@@ -2636,6 +2636,16 @@ BRoster::_InitMessenger()
|
||||
B_PREFERRED_TOKEN);
|
||||
}
|
||||
}
|
||||
#else
|
||||
port_id rosterPort = find_port(B_REGISTRAR_PORT_NAME);
|
||||
port_info info;
|
||||
if (rosterPort >= 0 && get_port_info(rosterPort, &info) == B_OK) {
|
||||
DBG(OUT(" found roster port\n"));
|
||||
|
||||
BMessenger::Private(fMessenger).SetTo(info.team, rosterPort,
|
||||
B_PREFERRED_TOKEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
DBG(OUT("BRoster::InitMessengers() done\n"));
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2006-2009 Haiku, Inc. All rights reserved.
|
||||
* Copyright 2006-2015 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stefano Ceccherini, stefano.ceccherini@gmail.com
|
||||
* Julian Harnath, <julian.harnath@rwth-achen.de>
|
||||
*/
|
||||
|
||||
#include <PictureDataWriter.h>
|
||||
@@ -660,6 +661,21 @@ PictureDataWriter::WritePopState()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PictureDataWriter::WriteBlendLayer(Layer* layer)
|
||||
{
|
||||
try {
|
||||
BeginOp(B_PIC_BLEND_LAYER);
|
||||
Write<Layer*>(layer);
|
||||
EndOp();
|
||||
} catch (status_t& status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// private
|
||||
void
|
||||
PictureDataWriter::BeginOp(const int16& op)
|
||||
|
||||
@@ -1213,6 +1213,16 @@ PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData,
|
||||
break;
|
||||
}
|
||||
|
||||
case B_PIC_BLEND_LAYER:
|
||||
{
|
||||
Layer* const* layer;
|
||||
if (callbacks.blend_layer == NULL || !reader.Get<Layer*>(layer))
|
||||
break;
|
||||
|
||||
callbacks.blend_layer(userData, *layer);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Adrian Oanca, adioanca@cotty.iren.ro
|
||||
* Ingo Weinhold. ingo_weinhold@gmx.de
|
||||
* Julian Harnath, julian.harnath@rwth-aachen.de
|
||||
*/
|
||||
|
||||
|
||||
@@ -3933,6 +3934,27 @@ BView::DrawPictureAsync(const char* filename, long offset, BPoint where)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BView::BeginLayer(uint8 opacity)
|
||||
{
|
||||
if (_CheckOwnerLockAndSwitchCurrent()) {
|
||||
fOwner->fLink->StartMessage(AS_VIEW_BEGIN_LAYER);
|
||||
fOwner->fLink->Attach<uint8>(opacity);
|
||||
_FlushIfNotInTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BView::EndLayer()
|
||||
{
|
||||
if (_CheckOwnerLockAndSwitchCurrent()) {
|
||||
fOwner->fLink->StartMessage(AS_VIEW_END_LAYER);
|
||||
_FlushIfNotInTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BView::Invalidate(BRect invalRect)
|
||||
{
|
||||
@@ -5225,7 +5247,7 @@ BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
|
||||
if (picture == NULL) {
|
||||
fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
|
||||
fOwner->fLink->Attach<int32>(-1);
|
||||
|
||||
|
||||
// NOTE: No need to sync here, since the -1 token cannot
|
||||
// become invalid on the server.
|
||||
} else {
|
||||
@@ -5240,7 +5262,7 @@ BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
|
||||
// the client creates BPictures on the stack, these BPictures may
|
||||
// have issued a AS_DELETE_PICTURE command to the ServerApp when Draw()
|
||||
// goes out of scope, and the command is processed earlier in the
|
||||
// ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
|
||||
// ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
|
||||
// ServerWindow thread, which will then have the result that no
|
||||
// ServerPicture is found of the token.
|
||||
if (sync)
|
||||
|
||||
@@ -48,7 +48,8 @@ uint32 gAppServerSIMDFlags = 0;
|
||||
*/
|
||||
AppServer::AppServer(status_t* status)
|
||||
:
|
||||
BServer("application/x-vnd.Haiku-app_server", "picasso", -1, false, status),
|
||||
SERVER_BASE("application/x-vnd.Haiku-app_server", "picasso", -1, false,
|
||||
status),
|
||||
fDesktopLock("AppServerDesktopLock")
|
||||
{
|
||||
openlog("app_server", 0, LOG_DAEMON);
|
||||
@@ -153,7 +154,10 @@ AppServer::QuitRequested()
|
||||
wait_for_thread(thread, &status);
|
||||
}
|
||||
|
||||
return BServer::QuitRequested();
|
||||
delete this;
|
||||
exit(0);
|
||||
|
||||
return SERVER_BASE::QuitRequested();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <Locker.h>
|
||||
#include <ObjectList.h>
|
||||
#include <OS.h>
|
||||
#include <Server.h>
|
||||
#include <String.h>
|
||||
#include <Window.h>
|
||||
|
||||
@@ -23,12 +22,21 @@
|
||||
#include "ServerConfig.h"
|
||||
|
||||
|
||||
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
|
||||
# include <Server.h>
|
||||
# define SERVER_BASE BServer
|
||||
#else
|
||||
# include "TestServerLoopAdapter.h"
|
||||
# define SERVER_BASE TestServerLoopAdapter
|
||||
#endif
|
||||
|
||||
|
||||
class ServerApp;
|
||||
class BitmapManager;
|
||||
class Desktop;
|
||||
|
||||
|
||||
class AppServer : public BServer {
|
||||
class AppServer : public SERVER_BASE {
|
||||
public:
|
||||
AppServer(status_t* status);
|
||||
virtual ~AppServer();
|
||||
@@ -39,7 +47,7 @@ public:
|
||||
private:
|
||||
Desktop* _CreateDesktop(uid_t userID,
|
||||
const char* targetScreen);
|
||||
Desktop* _FindDesktop(uid_t userID,
|
||||
virtual Desktop* _FindDesktop(uid_t userID,
|
||||
const char* targetScreen);
|
||||
|
||||
void _LaunchInputServer();
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Adi Oanca <adioanca@gmail.com>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
|
||||
#include "Canvas.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <Region.h>
|
||||
|
||||
#include "AlphaMask.h"
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "Layer.h"
|
||||
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
# define GCC_2_NRV(x)
|
||||
// GCC >= 3.1 doesn't need it anymore
|
||||
#else
|
||||
# define GCC_2_NRV(x) return x;
|
||||
// GCC 2 named return value syntax
|
||||
// see http://gcc.gnu.org/onlinedocs/gcc-2.95.2/gcc_5.html#SEC106
|
||||
#endif
|
||||
|
||||
|
||||
Canvas::Canvas()
|
||||
:
|
||||
fDrawState(new(std::nothrow) DrawState())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Canvas::Canvas(const DrawState& state)
|
||||
:
|
||||
fDrawState(new(std::nothrow) DrawState(state))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Canvas::~Canvas()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Canvas::InitCheck() const
|
||||
{
|
||||
if (fDrawState == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Canvas::PushState()
|
||||
{
|
||||
DrawState* newState = fDrawState->PushState();
|
||||
if (newState)
|
||||
fDrawState = newState;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Canvas::PopState()
|
||||
{
|
||||
if (fDrawState->PreviousState() == NULL)
|
||||
return;
|
||||
|
||||
bool rebuildClipping = fDrawState->HasAdditionalClipping();
|
||||
|
||||
fDrawState = fDrawState->PopState();
|
||||
|
||||
// rebuild clipping
|
||||
// (the clipping from the popped state is not effective anymore)
|
||||
if (rebuildClipping)
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Canvas::SetDrawState(DrawState* newState)
|
||||
{
|
||||
fDrawState = newState;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Canvas::SetDrawingOrigin(BPoint origin)
|
||||
{
|
||||
fDrawState->SetOrigin(origin);
|
||||
|
||||
// rebuild clipping
|
||||
if (fDrawState->HasClipping())
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
|
||||
BPoint
|
||||
Canvas::DrawingOrigin() const
|
||||
{
|
||||
BPoint origin(fDrawState->Origin());
|
||||
float scale = Scale();
|
||||
|
||||
origin.x *= scale;
|
||||
origin.y *= scale;
|
||||
|
||||
return origin;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Canvas::SetScale(float scale)
|
||||
{
|
||||
fDrawState->SetScale(scale);
|
||||
|
||||
// rebuild clipping
|
||||
if (fDrawState->HasClipping())
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
Canvas::Scale() const
|
||||
{
|
||||
return fDrawState->Scale();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Canvas::SetUserClipping(const BRegion* region)
|
||||
{
|
||||
fDrawState->SetClippingRegion(region);
|
||||
|
||||
// rebuild clipping (for just this canvas)
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Canvas::SetAlphaMask(AlphaMask* mask)
|
||||
{
|
||||
fDrawState->SetAlphaMask(mask);
|
||||
}
|
||||
|
||||
|
||||
AlphaMask*
|
||||
Canvas::GetAlphaMask() const
|
||||
{
|
||||
return fDrawState->GetAlphaMask();
|
||||
}
|
||||
|
||||
|
||||
SimpleTransform
|
||||
Canvas::LocalToScreenTransform() const GCC_2_NRV(transform)
|
||||
{
|
||||
#if __GNUC__ >= 3
|
||||
SimpleTransform transform;
|
||||
#endif
|
||||
_LocalToScreenTransform(transform);
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
SimpleTransform
|
||||
Canvas::ScreenToLocalTransform() const GCC_2_NRV(transform)
|
||||
{
|
||||
#if __GNUC__ >= 3
|
||||
SimpleTransform transform;
|
||||
#endif
|
||||
_ScreenToLocalTransform(transform);
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
SimpleTransform
|
||||
Canvas::PenToScreenTransform() const GCC_2_NRV(transform)
|
||||
{
|
||||
#if __GNUC__ >= 3
|
||||
SimpleTransform transform;
|
||||
#endif
|
||||
fDrawState->Transform(transform);
|
||||
_LocalToScreenTransform(transform);
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
SimpleTransform
|
||||
Canvas::PenToLocalTransform() const GCC_2_NRV(transform)
|
||||
{
|
||||
#if __GNUC__ >= 3
|
||||
SimpleTransform transform;
|
||||
#endif
|
||||
fDrawState->Transform(transform);
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
SimpleTransform
|
||||
Canvas::ScreenToPenTransform() const GCC_2_NRV(transform)
|
||||
{
|
||||
#if __GNUC__ >= 3
|
||||
SimpleTransform transform;
|
||||
#endif
|
||||
_ScreenToLocalTransform(transform);
|
||||
fDrawState->InverseTransform(transform);
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Canvas::BlendLayer(Layer* layer)
|
||||
{
|
||||
if (layer->Opacity() == 255) {
|
||||
layer->Play(this);
|
||||
layer->ReleaseReference();
|
||||
return;
|
||||
} else if (layer->Opacity() == 0) {
|
||||
layer->ReleaseReference();
|
||||
return;
|
||||
}
|
||||
|
||||
UtilityBitmap* layerBitmap = layer->RenderToBitmap(this);
|
||||
if (layerBitmap == NULL)
|
||||
return;
|
||||
|
||||
BRect destination = layerBitmap->Bounds();
|
||||
destination.OffsetBy(layer->LeftTopOffset());
|
||||
LocalToScreenTransform().Apply(&destination);
|
||||
|
||||
PushState();
|
||||
|
||||
fDrawState->SetDrawingMode(B_OP_ALPHA);
|
||||
fDrawState->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
|
||||
fDrawState->SetTransformEnabled(false);
|
||||
|
||||
AlphaMask* mask = new UniformAlphaMask(layer->Opacity());
|
||||
if (mask == NULL) {
|
||||
layerBitmap->ReleaseReference();
|
||||
return;
|
||||
}
|
||||
|
||||
SetAlphaMask(mask);
|
||||
mask->ReleaseReference();
|
||||
ResyncDrawState();
|
||||
|
||||
GetDrawingEngine()->DrawBitmap(layerBitmap, layerBitmap->Bounds(),
|
||||
destination, 0);
|
||||
|
||||
fDrawState->SetTransformEnabled(true);
|
||||
|
||||
PopState();
|
||||
ResyncDrawState();
|
||||
|
||||
layerBitmap->ReleaseReference();
|
||||
layer->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - OffscreenCanvas
|
||||
|
||||
|
||||
OffscreenCanvas::OffscreenCanvas(DrawingEngine* engine,
|
||||
const DrawState& state)
|
||||
:
|
||||
Canvas(state),
|
||||
fDrawingEngine(engine)
|
||||
{
|
||||
ResyncDrawState();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OffscreenCanvas::ResyncDrawState()
|
||||
{
|
||||
fDrawingEngine->SetDrawState(fDrawState);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Adi Oanca <adioanca@gmail.com>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef CANVAS_H
|
||||
#define CANVAS_H
|
||||
|
||||
|
||||
#include <Point.h>
|
||||
|
||||
#include "SimpleTransform.h"
|
||||
|
||||
|
||||
class AlphaMask;
|
||||
class BGradient;
|
||||
class BRegion;
|
||||
class DrawingEngine;
|
||||
class DrawState;
|
||||
class IntPoint;
|
||||
class IntRect;
|
||||
class Layer;
|
||||
class ServerPicture;
|
||||
|
||||
|
||||
class Canvas {
|
||||
public:
|
||||
Canvas();
|
||||
Canvas(const DrawState& state);
|
||||
virtual ~Canvas();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
virtual void PushState();
|
||||
virtual void PopState();
|
||||
DrawState* CurrentState() const { return fDrawState; }
|
||||
void SetDrawState(DrawState* newState);
|
||||
|
||||
void SetDrawingOrigin(BPoint origin);
|
||||
BPoint DrawingOrigin() const;
|
||||
|
||||
void SetScale(float scale);
|
||||
float Scale() const;
|
||||
|
||||
void SetUserClipping(const BRegion* region);
|
||||
// region is expected in view coordinates
|
||||
|
||||
void SetAlphaMask(AlphaMask* mask);
|
||||
AlphaMask* GetAlphaMask() const;
|
||||
|
||||
SimpleTransform LocalToScreenTransform() const;
|
||||
SimpleTransform ScreenToLocalTransform() const;
|
||||
SimpleTransform PenToScreenTransform() const;
|
||||
SimpleTransform PenToLocalTransform() const;
|
||||
SimpleTransform ScreenToPenTransform() const;
|
||||
|
||||
void BlendLayer(Layer* layer);
|
||||
|
||||
virtual DrawingEngine* GetDrawingEngine() const = 0;
|
||||
virtual ServerPicture* GetPicture(int32 token) const = 0;
|
||||
virtual void RebuildClipping(bool deep) = 0;
|
||||
virtual void ResyncDrawState() {};
|
||||
virtual void UpdateCurrentDrawingRegion() {};
|
||||
|
||||
protected:
|
||||
virtual void _LocalToScreenTransform(
|
||||
SimpleTransform& transform) const = 0;
|
||||
virtual void _ScreenToLocalTransform(
|
||||
SimpleTransform& transform) const = 0;
|
||||
|
||||
protected:
|
||||
DrawState* fDrawState;
|
||||
};
|
||||
|
||||
|
||||
class OffscreenCanvas : public Canvas {
|
||||
public:
|
||||
OffscreenCanvas(DrawingEngine* engine,
|
||||
const DrawState& state);
|
||||
|
||||
virtual DrawingEngine* GetDrawingEngine() const { return fDrawingEngine; }
|
||||
|
||||
virtual void RebuildClipping(bool deep) { /* TODO */ }
|
||||
virtual void ResyncDrawState();
|
||||
virtual ServerPicture* GetPicture(int32 token) const
|
||||
{ /* TODO */ return NULL; }
|
||||
|
||||
protected:
|
||||
virtual void _LocalToScreenTransform(SimpleTransform&) const {}
|
||||
virtual void _ScreenToLocalTransform(SimpleTransform&) const {}
|
||||
|
||||
private:
|
||||
DrawingEngine* fDrawingEngine;
|
||||
};
|
||||
|
||||
|
||||
#endif // CANVAS_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2008, Haiku.
|
||||
* Copyright 2001-2015, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -8,6 +8,7 @@
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Michael Pfeiffer <laplace@users.sourceforge.net>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
//! Data classes for working with BView states and draw parameters
|
||||
@@ -46,6 +47,7 @@ DrawState::DrawState()
|
||||
fDrawingMode(B_OP_COPY),
|
||||
fAlphaSrcMode(B_PIXEL_ALPHA),
|
||||
fAlphaFncMode(B_ALPHA_OVERLAY),
|
||||
fDrawingModeLocked(false),
|
||||
|
||||
fPenLocation(0.0f, 0.0f),
|
||||
fPenSize(1.0f),
|
||||
@@ -80,6 +82,7 @@ DrawState::DrawState(const DrawState& other)
|
||||
fDrawingMode(other.fDrawingMode),
|
||||
fAlphaSrcMode(other.fAlphaSrcMode),
|
||||
fAlphaFncMode(other.fAlphaFncMode),
|
||||
fDrawingModeLocked(other.fDrawingModeLocked),
|
||||
|
||||
fPenLocation(other.fPenLocation),
|
||||
fPenSize(other.fPenSize),
|
||||
@@ -107,8 +110,6 @@ DrawState::~DrawState()
|
||||
{
|
||||
delete fClippingRegion;
|
||||
delete fPreviousState;
|
||||
if (fAlphaMask != NULL)
|
||||
fAlphaMask->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +212,7 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link)
|
||||
ViewSetStateInfo info;
|
||||
|
||||
link.Read<ViewSetStateInfo>(&info);
|
||||
|
||||
|
||||
fPenLocation = info.penLocation;
|
||||
fPenSize = info.penSize;
|
||||
fHighColor = info.highColor;
|
||||
@@ -369,6 +370,30 @@ DrawState::SetTransform(BAffineTransform transform)
|
||||
}
|
||||
|
||||
|
||||
/* Can be used to temporarily disable all BAffineTransforms in the state
|
||||
stack, and later reenable them.
|
||||
*/
|
||||
void
|
||||
DrawState::SetTransformEnabled(bool enabled)
|
||||
{
|
||||
if (enabled) {
|
||||
BAffineTransform temp = fTransform;
|
||||
SetTransform(BAffineTransform());
|
||||
SetTransform(temp);
|
||||
}
|
||||
else
|
||||
fCombinedTransform = BAffineTransform();
|
||||
}
|
||||
|
||||
|
||||
DrawState*
|
||||
DrawState::Squash() const
|
||||
{
|
||||
DrawState* const squashedState = new DrawState(*this);
|
||||
return squashedState->PushState();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawState::SetClippingRegion(const BRegion* region)
|
||||
{
|
||||
@@ -407,8 +432,9 @@ DrawState::GetCombinedClippingRegion(BRegion* region) const
|
||||
{
|
||||
if (fClippingRegion != NULL) {
|
||||
BRegion localTransformedClipping(*fClippingRegion);
|
||||
Transform(&localTransformedClipping);
|
||||
|
||||
SimpleTransform penTransform;
|
||||
Transform(penTransform);
|
||||
penTransform.Apply(&localTransformedClipping);
|
||||
if (fPreviousState != NULL
|
||||
&& fPreviousState->GetCombinedClippingRegion(region)) {
|
||||
localTransformedClipping.IntersectWith(region);
|
||||
@@ -428,24 +454,14 @@ DrawState::SetAlphaMask(AlphaMask* mask)
|
||||
{
|
||||
// NOTE: In BeOS, it wasn't possible to clip to a BPicture and keep
|
||||
// regular custom clipping to a BRegion at the same time.
|
||||
if (fAlphaMask == mask)
|
||||
return;
|
||||
|
||||
if (mask != NULL)
|
||||
mask->AcquireReference();
|
||||
if (fAlphaMask != NULL)
|
||||
fAlphaMask->ReleaseReference();
|
||||
fAlphaMask = mask;
|
||||
if (fAlphaMask != NULL && fPreviousState != NULL)
|
||||
fAlphaMask->SetPrevious(fPreviousState->fAlphaMask);
|
||||
|
||||
fAlphaMask.SetTo(mask);
|
||||
}
|
||||
|
||||
|
||||
AlphaMask*
|
||||
DrawState::GetAlphaMask() const
|
||||
{
|
||||
return fAlphaMask;
|
||||
return fAlphaMask.Get();
|
||||
}
|
||||
|
||||
|
||||
@@ -453,83 +469,19 @@ DrawState::GetAlphaMask() const
|
||||
|
||||
|
||||
void
|
||||
DrawState::Transform(float* x, float* y) const
|
||||
DrawState::Transform(SimpleTransform& transform) const
|
||||
{
|
||||
// scale relative to origin, therefore
|
||||
// scale first then translate to
|
||||
// origin
|
||||
*x *= fCombinedScale;
|
||||
*y *= fCombinedScale;
|
||||
*x += fCombinedOrigin.x;
|
||||
*y += fCombinedOrigin.y;
|
||||
transform.AddOffset(fCombinedOrigin.x, fCombinedOrigin.y);
|
||||
transform.SetScale(fCombinedScale);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawState::InverseTransform(float* x, float* y) const
|
||||
DrawState::InverseTransform(SimpleTransform& transform) const
|
||||
{
|
||||
*x -= fCombinedOrigin.x;
|
||||
*y -= fCombinedOrigin.y;
|
||||
if (fCombinedScale != 0.0) {
|
||||
*x /= fCombinedScale;
|
||||
*y /= fCombinedScale;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawState::Transform(BPoint* point) const
|
||||
{
|
||||
Transform(&(point->x), &(point->y));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawState::Transform(BRect* rect) const
|
||||
{
|
||||
Transform(&(rect->left), &(rect->top));
|
||||
Transform(&(rect->right), &(rect->bottom));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawState::Transform(BRegion* region) const
|
||||
{
|
||||
if (fCombinedScale == 1.0) {
|
||||
region->OffsetBy(fCombinedOrigin.x, fCombinedOrigin.y);
|
||||
} else {
|
||||
// TODO: optimize some more
|
||||
BRegion converted;
|
||||
int32 count = region->CountRects();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BRect r = region->RectAt(i);
|
||||
BPoint lt(r.LeftTop());
|
||||
BPoint rb(r.RightBottom());
|
||||
// offset to bottom right corner of pixel before transformation
|
||||
rb.x++;
|
||||
rb.y++;
|
||||
// apply transformation
|
||||
Transform(<.x, <.y);
|
||||
Transform(&rb.x, &rb.y);
|
||||
// reset bottom right to pixel "index"
|
||||
rb.x--;
|
||||
rb.y--;
|
||||
// add rect to converted region
|
||||
// NOTE/TODO: the rect would not have to go
|
||||
// through the whole intersection test process,
|
||||
// it is guaranteed not to overlap with any rect
|
||||
// already contained in the region
|
||||
converted.Include(BRect(lt, rb));
|
||||
}
|
||||
*region = converted;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawState::InverseTransform(BPoint* point) const
|
||||
{
|
||||
InverseTransform(&(point->x), &(point->y));
|
||||
transform.AddOffset(-fCombinedOrigin.x, -fCombinedOrigin.y);
|
||||
if (fCombinedScale != 0.0)
|
||||
transform.SetScale(1.0 / fCombinedScale);
|
||||
}
|
||||
|
||||
|
||||
@@ -557,21 +509,37 @@ DrawState::SetPattern(const Pattern& pattern)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
DrawState::SetDrawingMode(drawing_mode mode)
|
||||
{
|
||||
fDrawingMode = mode;
|
||||
if (!fDrawingModeLocked) {
|
||||
fDrawingMode = mode;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DrawState::SetBlendingMode(source_alpha srcMode, alpha_function fncMode)
|
||||
{
|
||||
if (!fDrawingModeLocked) {
|
||||
fAlphaSrcMode = srcMode;
|
||||
fAlphaFncMode = fncMode;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawState::SetBlendingMode(source_alpha srcMode, alpha_function fncMode)
|
||||
DrawState::SetDrawingModeLocked(bool locked)
|
||||
{
|
||||
fAlphaSrcMode = srcMode;
|
||||
fAlphaFncMode = fncMode;
|
||||
fDrawingModeLocked = locked;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DrawState::SetPenLocation(BPoint location)
|
||||
{
|
||||
|
||||
+15
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2008, Haiku.
|
||||
* Copyright 2001-2015, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -7,6 +7,7 @@
|
||||
* Adi Oanca <adioanca@mymail.ro>
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef _DRAW_STATE_H_
|
||||
#define _DRAW_STATE_H_
|
||||
@@ -16,10 +17,12 @@
|
||||
#include <GraphicsDefs.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <Point.h>
|
||||
#include <Referenceable.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "ServerFont.h"
|
||||
#include "PatternHandler.h"
|
||||
#include "SimpleTransform.h"
|
||||
|
||||
class AlphaMask;
|
||||
class BRegion;
|
||||
@@ -66,6 +69,9 @@ public:
|
||||
{ return fTransform; }
|
||||
BAffineTransform CombinedTransform() const
|
||||
{ return fCombinedTransform; }
|
||||
void SetTransformEnabled(bool enabled);
|
||||
|
||||
DrawState* Squash() const;
|
||||
|
||||
// additional clipping as requested by client
|
||||
void SetClippingRegion(const BRegion* region);
|
||||
@@ -78,14 +84,8 @@ public:
|
||||
AlphaMask* GetAlphaMask() const;
|
||||
|
||||
// coordinate transformations
|
||||
void Transform(float* x, float* y) const;
|
||||
void InverseTransform(float* x, float* y) const;
|
||||
|
||||
void Transform(BPoint* point) const;
|
||||
void Transform(BRect* rect) const;
|
||||
void Transform(BRegion* region) const;
|
||||
|
||||
void InverseTransform(BPoint* point) const;
|
||||
void Transform(SimpleTransform& transform) const;
|
||||
void InverseTransform(SimpleTransform& transform) const;
|
||||
|
||||
// color
|
||||
void SetHighColor(rgb_color color);
|
||||
@@ -101,17 +101,19 @@ public:
|
||||
{ return fPattern; }
|
||||
|
||||
// drawing/blending mode
|
||||
void SetDrawingMode(drawing_mode mode);
|
||||
bool SetDrawingMode(drawing_mode mode);
|
||||
drawing_mode GetDrawingMode() const
|
||||
{ return fDrawingMode; }
|
||||
|
||||
void SetBlendingMode(source_alpha srcMode,
|
||||
bool SetBlendingMode(source_alpha srcMode,
|
||||
alpha_function fncMode);
|
||||
source_alpha AlphaSrcMode() const
|
||||
{ return fAlphaSrcMode; }
|
||||
alpha_function AlphaFncMode() const
|
||||
{ return fAlphaFncMode; }
|
||||
|
||||
void SetDrawingModeLocked(bool locked);
|
||||
|
||||
// pen
|
||||
void SetPenLocation(BPoint location);
|
||||
BPoint PenLocation() const;
|
||||
@@ -165,7 +167,7 @@ protected:
|
||||
|
||||
BRegion* fClippingRegion;
|
||||
|
||||
AlphaMask* fAlphaMask;
|
||||
BReference<AlphaMask> fAlphaMask;
|
||||
|
||||
rgb_color fHighColor;
|
||||
rgb_color fLowColor;
|
||||
@@ -174,6 +176,7 @@ protected:
|
||||
drawing_mode fDrawingMode;
|
||||
source_alpha fAlphaSrcMode;
|
||||
alpha_function fAlphaFncMode;
|
||||
bool fDrawingModeLocked;
|
||||
|
||||
BPoint fPenLocation;
|
||||
float fPenSize;
|
||||
|
||||
@@ -1,345 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Adi Oanca <adioanca@gmail.com>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk
|
||||
*/
|
||||
|
||||
|
||||
#include "DrawingContext.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <GradientLinear.h>
|
||||
#include <GradientRadial.h>
|
||||
#include <GradientRadialFocus.h>
|
||||
#include <GradientDiamond.h>
|
||||
#include <GradientConic.h>
|
||||
#include <Region.h>
|
||||
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
|
||||
|
||||
DrawingContext::DrawingContext()
|
||||
:
|
||||
fDrawState(new(std::nothrow) DrawState())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DrawingContext::DrawingContext(const DrawState& state)
|
||||
:
|
||||
fDrawState(new(std::nothrow) DrawState(state))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DrawingContext::~DrawingContext()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DrawingContext::InitCheck() const
|
||||
{
|
||||
if (fDrawState == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawingContext::PushState()
|
||||
{
|
||||
DrawState* newState = fDrawState->PushState();
|
||||
if (newState)
|
||||
fDrawState = newState;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawingContext::PopState()
|
||||
{
|
||||
if (fDrawState->PreviousState() == NULL)
|
||||
return;
|
||||
|
||||
bool rebuildClipping = fDrawState->HasAdditionalClipping();
|
||||
|
||||
fDrawState = fDrawState->PopState();
|
||||
|
||||
// rebuild clipping
|
||||
// (the clipping from the popped state is not effective anymore)
|
||||
if (rebuildClipping)
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawingContext::SetDrawingOrigin(BPoint origin)
|
||||
{
|
||||
fDrawState->SetOrigin(origin);
|
||||
|
||||
// rebuild clipping
|
||||
if (fDrawState->HasClipping())
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
|
||||
BPoint
|
||||
DrawingContext::DrawingOrigin() const
|
||||
{
|
||||
BPoint origin(fDrawState->Origin());
|
||||
float scale = Scale();
|
||||
|
||||
origin.x *= scale;
|
||||
origin.y *= scale;
|
||||
|
||||
return origin;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawingContext::SetScale(float scale)
|
||||
{
|
||||
fDrawState->SetScale(scale);
|
||||
|
||||
// rebuild clipping
|
||||
if (fDrawState->HasClipping())
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
DrawingContext::Scale() const
|
||||
{
|
||||
return fDrawState->Scale();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawingContext::SetUserClipping(const BRegion* region)
|
||||
{
|
||||
fDrawState->SetClippingRegion(region);
|
||||
|
||||
// rebuild clipping (for just this context)
|
||||
RebuildClipping(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawingContext::SetAlphaMask(AlphaMask* mask)
|
||||
{
|
||||
fDrawState->SetAlphaMask(mask);
|
||||
}
|
||||
|
||||
|
||||
AlphaMask*
|
||||
DrawingContext::GetAlphaMask() const
|
||||
{
|
||||
return fDrawState->GetAlphaMask();
|
||||
}
|
||||
|
||||
|
||||
//! converts a point from local *drawing* to screen coordinate system
|
||||
void
|
||||
DrawingContext::ConvertToScreenForDrawing(BPoint* point) const
|
||||
{
|
||||
fDrawState->Transform(point);
|
||||
// NOTE: from here on, don't use the
|
||||
// "*ForDrawing()" versions of the parent!
|
||||
ConvertToScreen(point);
|
||||
}
|
||||
|
||||
|
||||
//! converts a rect from local *drawing* to screen coordinate system
|
||||
void
|
||||
DrawingContext::ConvertToScreenForDrawing(BRect* rect) const
|
||||
{
|
||||
fDrawState->Transform(rect);
|
||||
// NOTE: from here on, don't use the
|
||||
// "*ForDrawing()" versions of the parent!
|
||||
ConvertToScreen(rect);
|
||||
}
|
||||
|
||||
|
||||
//! converts a region from local *drawing* to screen coordinate system
|
||||
void
|
||||
DrawingContext::ConvertToScreenForDrawing(BRegion* region) const
|
||||
{
|
||||
fDrawState->Transform(region);
|
||||
// NOTE: from here on, don't use the
|
||||
// "*ForDrawing()" versions of the parent!
|
||||
ConvertToScreen(region);
|
||||
}
|
||||
|
||||
|
||||
//! converts a gradient from local *drawing* to screen coordinate system
|
||||
void
|
||||
DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const
|
||||
{
|
||||
switch (gradient->GetType()) {
|
||||
case BGradient::TYPE_LINEAR:
|
||||
{
|
||||
BGradientLinear* linear = (BGradientLinear*) gradient;
|
||||
BPoint start = linear->Start();
|
||||
BPoint end = linear->End();
|
||||
fDrawState->Transform(&start);
|
||||
ConvertToScreen(&start);
|
||||
fDrawState->Transform(&end);
|
||||
ConvertToScreen(&end);
|
||||
linear->SetStart(start);
|
||||
linear->SetEnd(end);
|
||||
break;
|
||||
}
|
||||
case BGradient::TYPE_RADIAL:
|
||||
{
|
||||
BGradientRadial* radial = (BGradientRadial*) gradient;
|
||||
BPoint center = radial->Center();
|
||||
fDrawState->Transform(¢er);
|
||||
ConvertToScreen(¢er);
|
||||
radial->SetCenter(center);
|
||||
break;
|
||||
}
|
||||
case BGradient::TYPE_RADIAL_FOCUS:
|
||||
{
|
||||
BGradientRadialFocus* radialFocus = (BGradientRadialFocus*) gradient;
|
||||
BPoint center = radialFocus->Center();
|
||||
BPoint focal = radialFocus->Focal();
|
||||
fDrawState->Transform(¢er);
|
||||
ConvertToScreen(¢er);
|
||||
fDrawState->Transform(&focal);
|
||||
ConvertToScreen(&focal);
|
||||
radialFocus->SetCenter(center);
|
||||
radialFocus->SetFocal(focal);
|
||||
break;
|
||||
}
|
||||
case BGradient::TYPE_DIAMOND:
|
||||
{
|
||||
BGradientDiamond* diamond = (BGradientDiamond*) gradient;
|
||||
BPoint center = diamond->Center();
|
||||
fDrawState->Transform(¢er);
|
||||
ConvertToScreen(¢er);
|
||||
diamond->SetCenter(center);
|
||||
break;
|
||||
}
|
||||
case BGradient::TYPE_CONIC:
|
||||
{
|
||||
BGradientConic* conic = (BGradientConic*) gradient;
|
||||
BPoint center = conic->Center();
|
||||
fDrawState->Transform(¢er);
|
||||
ConvertToScreen(¢er);
|
||||
conic->SetCenter(center);
|
||||
break;
|
||||
}
|
||||
case BGradient::TYPE_NONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the gradient is fully padded so that out of bounds access
|
||||
// get the correct colors
|
||||
gradient->SortColorStopsByOffset();
|
||||
|
||||
BGradient::ColorStop* end = gradient->ColorStopAtFast(
|
||||
gradient->CountColorStops() - 1);
|
||||
|
||||
if (end->offset != 255)
|
||||
gradient->AddColor(end->color, 255);
|
||||
|
||||
BGradient::ColorStop* start = gradient->ColorStopAtFast(0);
|
||||
|
||||
if (start->offset != 0)
|
||||
gradient->AddColor(start->color, 0);
|
||||
|
||||
gradient->SortColorStopsByOffset();
|
||||
}
|
||||
|
||||
|
||||
//! converts points from local *drawing* to screen coordinate system
|
||||
void
|
||||
DrawingContext::ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num) const
|
||||
{
|
||||
// TODO: optimize this, it should be smarter
|
||||
while (num--) {
|
||||
*dst = *src;
|
||||
fDrawState->Transform(dst);
|
||||
// NOTE: from here on, don't use the
|
||||
// "*ForDrawing()" versions of the parent!
|
||||
ConvertToScreen(dst);
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! converts rects from local *drawing* to screen coordinate system
|
||||
void
|
||||
DrawingContext::ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num) const
|
||||
{
|
||||
// TODO: optimize this, it should be smarter
|
||||
while (num--) {
|
||||
*dst = *src;
|
||||
fDrawState->Transform(dst);
|
||||
// NOTE: from here on, don't use the
|
||||
// "*ForDrawing()" versions of the parent!
|
||||
ConvertToScreen(dst);
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! converts regions from local *drawing* to screen coordinate system
|
||||
void
|
||||
DrawingContext::ConvertToScreenForDrawing(BRegion* dst, const BRegion* src, int32 num) const
|
||||
{
|
||||
// TODO: optimize this, it should be smarter
|
||||
while (num--) {
|
||||
*dst = *src;
|
||||
fDrawState->Transform(dst);
|
||||
// NOTE: from here on, don't use the
|
||||
// "*ForDrawing()" versions of the parent!
|
||||
ConvertToScreen(dst);
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! converts a point from screen to local coordinate system
|
||||
void
|
||||
DrawingContext::ConvertFromScreenForDrawing(BPoint* point) const
|
||||
{
|
||||
ConvertFromScreen(point);
|
||||
fDrawState->InverseTransform(point);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - OffscreenContext
|
||||
|
||||
|
||||
OffscreenContext::OffscreenContext(DrawingEngine* engine,
|
||||
const DrawState& state)
|
||||
:
|
||||
DrawingContext(state),
|
||||
fDrawingEngine(engine)
|
||||
{
|
||||
ResyncDrawState();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OffscreenContext::ResyncDrawState()
|
||||
{
|
||||
fDrawingEngine->SetDrawState(fDrawState);
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Adi Oanca <adioanca@gmail.com>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
*/
|
||||
#ifndef DRAWING_CONTEXT_H
|
||||
#define DRAWING_CONTEXT_H
|
||||
|
||||
|
||||
#include <Point.h>
|
||||
|
||||
|
||||
class AlphaMask;
|
||||
class BGradient;
|
||||
class BRegion;
|
||||
class DrawingEngine;
|
||||
class DrawState;
|
||||
class IntPoint;
|
||||
class IntRect;
|
||||
class ServerPicture;
|
||||
|
||||
|
||||
class DrawingContext {
|
||||
public:
|
||||
DrawingContext();
|
||||
DrawingContext(const DrawState& state);
|
||||
virtual ~DrawingContext();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
virtual void PushState();
|
||||
virtual void PopState();
|
||||
DrawState* CurrentState() const { return fDrawState; }
|
||||
|
||||
void SetDrawingOrigin(BPoint origin);
|
||||
BPoint DrawingOrigin() const;
|
||||
|
||||
void SetScale(float scale);
|
||||
float Scale() const;
|
||||
|
||||
void SetUserClipping(const BRegion* region);
|
||||
// region is expected in view coordinates
|
||||
|
||||
void SetAlphaMask(AlphaMask* mask);
|
||||
AlphaMask* GetAlphaMask() const;
|
||||
|
||||
void ConvertToScreenForDrawing(BPoint* point) const;
|
||||
void ConvertToScreenForDrawing(BRect* rect) const;
|
||||
void ConvertToScreenForDrawing(BRegion* region) const;
|
||||
void ConvertToScreenForDrawing(BGradient* gradient) const;
|
||||
|
||||
void ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num) const;
|
||||
void ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num) const;
|
||||
void ConvertToScreenForDrawing(BRegion* dst, const BRegion* src, int32 num) const;
|
||||
|
||||
void ConvertFromScreenForDrawing(BPoint* point) const;
|
||||
// used when updating the pen position
|
||||
|
||||
virtual void ConvertToScreen(BPoint* point) const = 0;
|
||||
virtual void ConvertToScreen(IntPoint* point) const = 0;
|
||||
virtual void ConvertToScreen(BRect* rect) const = 0;
|
||||
virtual void ConvertToScreen(IntRect* rect) const = 0;
|
||||
virtual void ConvertToScreen(BRegion* region) const = 0;
|
||||
|
||||
virtual void ConvertFromScreen(BPoint* point) const = 0;
|
||||
|
||||
virtual DrawingEngine* GetDrawingEngine() const = 0;
|
||||
virtual ServerPicture* GetPicture(int32 token) const = 0;
|
||||
virtual void RebuildClipping(bool deep) = 0;
|
||||
virtual void ResyncDrawState() {};
|
||||
virtual void UpdateCurrentDrawingRegion() {};
|
||||
|
||||
protected:
|
||||
DrawState* fDrawState;
|
||||
};
|
||||
|
||||
|
||||
class OffscreenContext: public DrawingContext {
|
||||
public:
|
||||
OffscreenContext(DrawingEngine* engine,
|
||||
const DrawState& state);
|
||||
|
||||
// Screen and View coordinates are the same for us.
|
||||
// DrawState already takes care of World<>View
|
||||
// conversions.
|
||||
virtual void ConvertToScreen(BPoint*) const {}
|
||||
virtual void ConvertToScreen(IntPoint*) const {}
|
||||
virtual void ConvertToScreen(BRect*) const {}
|
||||
virtual void ConvertToScreen(IntRect*) const {}
|
||||
virtual void ConvertToScreen(BRegion*) const {}
|
||||
virtual void ConvertFromScreen(BPoint*) const {}
|
||||
|
||||
virtual DrawingEngine* GetDrawingEngine() const { return fDrawingEngine; }
|
||||
|
||||
virtual void RebuildClipping(bool deep) { /* TODO */ }
|
||||
virtual void ResyncDrawState();
|
||||
virtual ServerPicture* GetPicture(int32 token) const
|
||||
{ /* TODO */ return NULL; }
|
||||
private:
|
||||
DrawingEngine* fDrawingEngine;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -32,10 +32,10 @@ local font_src =
|
||||
;
|
||||
|
||||
UseBuildFeatureHeaders freetype ;
|
||||
Includes [ FGristFiles AppServer.cpp BitmapManager.cpp
|
||||
Includes [ FGristFiles AppServer.cpp BitmapManager.cpp Canvas.cpp
|
||||
ClientMemoryAllocator.cpp Desktop.cpp DesktopSettings.cpp
|
||||
DrawState.cpp DrawingContext.cpp DrawingEngine.cpp ServerApp.cpp
|
||||
ServerBitmap.cpp ServerCursor.cpp ServerFont.cpp ServerPicture.cpp
|
||||
DrawState.cpp DrawingEngine.cpp ServerApp.cpp
|
||||
ServerBitmap.cpp ServerCursor.cpp ServerFont.cpp ServerPicture.cpp
|
||||
ServerWindow.cpp View.cpp Window.cpp WorkspacesView.cpp
|
||||
$(decorator_src) $(font_src) ]
|
||||
: [ BuildFeatureAttribute freetype : headers ] ;
|
||||
@@ -51,6 +51,7 @@ Server app_server :
|
||||
AppServer.cpp
|
||||
#BitfieldRegion.cpp
|
||||
BitmapManager.cpp
|
||||
Canvas.cpp
|
||||
ClientMemoryAllocator.cpp
|
||||
CursorData.cpp
|
||||
CursorManager.cpp
|
||||
@@ -59,7 +60,6 @@ Server app_server :
|
||||
DesktopListener.cpp
|
||||
DesktopSettings.cpp
|
||||
DirectWindowInfo.cpp
|
||||
DrawingContext.cpp
|
||||
DrawState.cpp
|
||||
EventDispatcher.cpp
|
||||
EventStream.cpp
|
||||
@@ -67,10 +67,12 @@ Server app_server :
|
||||
InputManager.cpp
|
||||
IntPoint.cpp
|
||||
IntRect.cpp
|
||||
Layer.cpp
|
||||
MessageLooper.cpp
|
||||
MultiLocker.cpp
|
||||
OffscreenServerWindow.cpp
|
||||
OffscreenWindow.cpp
|
||||
PictureBoundingBoxPlayer.cpp
|
||||
ProfileMessageSupport.cpp
|
||||
RGBColor.cpp
|
||||
RegionPool.cpp
|
||||
@@ -97,7 +99,7 @@ Server app_server :
|
||||
# libraries
|
||||
:
|
||||
libtranslation.so libbe.so libbnetapi.so
|
||||
libaslocal.a $(BROKEN_64)libasremote.a $(BROKEN_64)libashtml5.a
|
||||
libaslocal.a $(BROKEN_64)libasremote.a $(BROKEN_64)libashtml5.a
|
||||
libasdrawing.a libpainter.a libagg.a
|
||||
[ BuildFeatureAttribute freetype : library ]
|
||||
libstackandtile.a liblinprog.a libtextencoding.so libshared.a
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2015 Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#include "Layer.h"
|
||||
|
||||
#include "AlphaMask.h"
|
||||
#include "BitmapHWInterface.h"
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "IntRect.h"
|
||||
#include "PictureBoundingBoxPlayer.h"
|
||||
#include "ServerBitmap.h"
|
||||
#include "View.h"
|
||||
|
||||
|
||||
class LayerCanvas : public Canvas {
|
||||
public:
|
||||
LayerCanvas(DrawingEngine* drawingEngine, DrawState* drawState)
|
||||
:
|
||||
Canvas(),
|
||||
fDrawingEngine(drawingEngine)
|
||||
{
|
||||
delete fDrawState;
|
||||
fDrawState = drawState;
|
||||
}
|
||||
|
||||
virtual DrawingEngine* GetDrawingEngine() const
|
||||
{
|
||||
return fDrawingEngine;
|
||||
}
|
||||
|
||||
virtual ServerPicture* GetPicture(int32 token) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void RebuildClipping(bool)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ResyncDrawState()
|
||||
{
|
||||
fDrawingEngine->SetDrawState(fDrawState);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void _LocalToScreenTransform(SimpleTransform&) const
|
||||
{
|
||||
}
|
||||
|
||||
virtual void _ScreenToLocalTransform(SimpleTransform&) const
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
DrawingEngine* fDrawingEngine;
|
||||
};
|
||||
|
||||
|
||||
Layer::Layer(uint8 opacity)
|
||||
:
|
||||
fOpacity(opacity),
|
||||
fLeftTopOffset(0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Layer::~Layer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Layer::PushLayer(Layer* layer)
|
||||
{
|
||||
PushPicture(layer);
|
||||
}
|
||||
|
||||
|
||||
Layer*
|
||||
Layer::PopLayer()
|
||||
{
|
||||
Layer* const previousLayer = static_cast<Layer*>(PopPicture());
|
||||
if (previousLayer != NULL)
|
||||
previousLayer->ReleaseReference();
|
||||
return previousLayer;
|
||||
}
|
||||
|
||||
|
||||
UtilityBitmap*
|
||||
Layer::RenderToBitmap(Canvas* canvas)
|
||||
{
|
||||
BRect boundingBox = _DetermineBoundingBox(canvas);
|
||||
if (!boundingBox.IsValid())
|
||||
return NULL;
|
||||
|
||||
fLeftTopOffset = boundingBox.LeftTop();
|
||||
|
||||
UtilityBitmap* const layerBitmap = _AllocateBitmap(boundingBox);
|
||||
if (layerBitmap == NULL)
|
||||
return NULL;
|
||||
|
||||
BitmapHWInterface layerInterface(layerBitmap);
|
||||
DrawingEngine* const layerEngine = layerInterface.CreateDrawingEngine();
|
||||
if (layerEngine == NULL) {
|
||||
layerBitmap->ReleaseReference();
|
||||
return NULL;
|
||||
}
|
||||
layerEngine->SetRendererOffset(boundingBox.left, boundingBox.top);
|
||||
// Drawing commands of the layer's picture use coordinates in the
|
||||
// coordinate space of the underlying canvas. The coordinate origin
|
||||
// of the layer bitmap is at boundingBox.LeftTop(). So all the drawing
|
||||
// from the picture needs to be offset to be moved into the bitmap.
|
||||
// We use a low-level offsetting via the AGG renderer here because the
|
||||
// offset needs to be processed independently, after all other
|
||||
// transforms, even after the BAffineTransforms (which are processed in
|
||||
// Painter), to prevent this origin from being further transformed by
|
||||
// e.g. scaling.
|
||||
|
||||
LayerCanvas layerCanvas(layerEngine, canvas->CurrentState());
|
||||
|
||||
AlphaMask* const mask = layerCanvas.GetAlphaMask();
|
||||
IntPoint oldOffset;
|
||||
if (mask != NULL) {
|
||||
// Move alpha mask to bitmap origin
|
||||
oldOffset = mask->SetViewOrigin(IntPoint(0, 0));
|
||||
}
|
||||
|
||||
canvas->CurrentState()->SetDrawingMode(B_OP_ALPHA);
|
||||
canvas->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
|
||||
|
||||
layerCanvas.ResyncDrawState();
|
||||
// Apply state to the new drawing engine of the layer canvas
|
||||
|
||||
if (layerEngine->LockParallelAccess()) {
|
||||
const BRegion region(boundingBox);
|
||||
layerEngine->ConstrainClippingRegion(®ion);
|
||||
|
||||
// Draw recorded picture into bitmap
|
||||
Play(&layerCanvas);
|
||||
layerEngine->UnlockParallelAccess();
|
||||
}
|
||||
|
||||
if (mask != NULL) {
|
||||
// Move alpha mask back to its old position
|
||||
// Note: this needs to be adapted if setting alpha masks is
|
||||
// implemented as BPicture command (the mask now might be a different
|
||||
// one than before).
|
||||
mask->SetViewOrigin(oldOffset);
|
||||
layerCanvas.ResyncDrawState();
|
||||
}
|
||||
|
||||
canvas->SetDrawState(layerCanvas.CurrentState());
|
||||
// Update state in canvas (the top-of-stack state could be a different
|
||||
// state instance now, if the picture commands contained push/pop
|
||||
// commands)
|
||||
|
||||
delete layerEngine;
|
||||
|
||||
return layerBitmap;
|
||||
}
|
||||
|
||||
|
||||
IntPoint
|
||||
Layer::LeftTopOffset() const
|
||||
{
|
||||
return fLeftTopOffset;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
Layer::Opacity() const
|
||||
{
|
||||
return fOpacity;
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
Layer::_DetermineBoundingBox(Canvas* canvas)
|
||||
{
|
||||
BRect boundingBox;
|
||||
PictureBoundingBoxPlayer::Play(this, canvas->CurrentState(), &boundingBox);
|
||||
|
||||
if (!boundingBox.IsValid())
|
||||
return boundingBox;
|
||||
|
||||
// Round up and add an additional 2 pixels on the bottom/right to
|
||||
// compensate for the various types of rounding used in Painter.
|
||||
boundingBox.left = floorf(boundingBox.left);
|
||||
boundingBox.right = ceilf(boundingBox.right) + 2;
|
||||
boundingBox.top = floorf(boundingBox.top);
|
||||
boundingBox.bottom = ceilf(boundingBox.bottom) + 2;
|
||||
|
||||
// TODO: for optimization, crop the bounding box to the underlying
|
||||
// view bounds here
|
||||
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
|
||||
UtilityBitmap*
|
||||
Layer::_AllocateBitmap(const BRect& bounds)
|
||||
{
|
||||
UtilityBitmap* const layerBitmap = new(std::nothrow) UtilityBitmap(bounds,
|
||||
B_RGBA32, 0);
|
||||
if (layerBitmap == NULL)
|
||||
return NULL;
|
||||
if (!layerBitmap->IsValid()) {
|
||||
delete layerBitmap;
|
||||
return NULL;
|
||||
}
|
||||
memset(layerBitmap->Bits(), 0, layerBitmap->BitsLength());
|
||||
|
||||
return layerBitmap;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2015 Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef LAYER_H
|
||||
#define LAYER_H
|
||||
|
||||
|
||||
#include "ServerPicture.h"
|
||||
|
||||
#include "IntPoint.h"
|
||||
|
||||
|
||||
class AlphaMask;
|
||||
class Canvas;
|
||||
class UtilityBitmap;
|
||||
|
||||
|
||||
class Layer : public ServerPicture {
|
||||
public:
|
||||
Layer(uint8 opacity);
|
||||
virtual ~Layer();
|
||||
|
||||
void PushLayer(Layer* layer);
|
||||
Layer* PopLayer();
|
||||
|
||||
UtilityBitmap* RenderToBitmap(Canvas* canvas);
|
||||
|
||||
IntPoint LeftTopOffset() const;
|
||||
uint8 Opacity() const;
|
||||
|
||||
private:
|
||||
BRect _DetermineBoundingBox(Canvas* canvas);
|
||||
UtilityBitmap* _AllocateBitmap(const BRect& bounds);
|
||||
|
||||
private:
|
||||
uint8 fOpacity;
|
||||
IntPoint fLeftTopOffset;
|
||||
};
|
||||
|
||||
|
||||
#endif // LAYER_H
|
||||
@@ -154,9 +154,9 @@ MessageLooper::_MessageLooper()
|
||||
|
||||
Lock();
|
||||
|
||||
if (code == kMsgQuitLooper) {
|
||||
if (code == kMsgQuitLooper)
|
||||
Quit();
|
||||
} else
|
||||
else
|
||||
_DispatchMessage(code, receiver);
|
||||
|
||||
Unlock();
|
||||
|
||||
@@ -0,0 +1,816 @@
|
||||
/*
|
||||
* Copyright 2001-2015, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Marc Flerackers (mflerackers@androme.be)
|
||||
* Stefano Ceccherini (stefano.ceccherini@gmail.com)
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
#include "PictureBoundingBoxPlayer.h"
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "DrawState.h"
|
||||
#include "FontManager.h"
|
||||
#include "Layer.h"
|
||||
#include "ServerApp.h"
|
||||
#include "ServerBitmap.h"
|
||||
#include "ServerFont.h"
|
||||
#include "ServerPicture.h"
|
||||
#include "ServerTokenSpace.h"
|
||||
#include "View.h"
|
||||
#include "Window.h"
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Debug.h>
|
||||
#include <List.h>
|
||||
#include <ObjectListPrivate.h>
|
||||
#include <PicturePlayer.h>
|
||||
#include <PictureProtocol.h>
|
||||
#include <Shape.h>
|
||||
|
||||
|
||||
//#define DEBUG_TRACE_BB
|
||||
#ifdef DEBUG_TRACE_BB
|
||||
# define TRACE_BB(text, ...) debug_printf("PBBP: " text, ##__VA_ARGS__)
|
||||
#else
|
||||
# define TRACE_BB(text, ...)
|
||||
#endif
|
||||
|
||||
|
||||
typedef PictureBoundingBoxPlayer::State BoundingBoxState;
|
||||
|
||||
|
||||
// #pragma mark - PictureBoundingBoxPlayer::State
|
||||
|
||||
|
||||
class PictureBoundingBoxPlayer::State {
|
||||
public:
|
||||
State(const DrawState* drawState, BRect* boundingBox)
|
||||
:
|
||||
fDrawState(drawState->Squash()),
|
||||
fBoundingBox(boundingBox)
|
||||
{
|
||||
fBoundingBox->Set(INT_MAX, INT_MAX, INT_MIN, INT_MIN);
|
||||
}
|
||||
|
||||
~State()
|
||||
{
|
||||
delete fDrawState;
|
||||
}
|
||||
|
||||
DrawState* GetDrawState()
|
||||
{
|
||||
return fDrawState;
|
||||
}
|
||||
|
||||
void PushDrawState()
|
||||
{
|
||||
DrawState* nextState = fDrawState->PushState();
|
||||
if (nextState != NULL)
|
||||
fDrawState = nextState;
|
||||
}
|
||||
|
||||
void PopDrawState()
|
||||
{
|
||||
if (fDrawState->PreviousState() != NULL)
|
||||
fDrawState = fDrawState->PopState();
|
||||
}
|
||||
|
||||
SimpleTransform PenToLocalTransform() const
|
||||
{
|
||||
SimpleTransform transform;
|
||||
fDrawState->Transform(transform);
|
||||
return transform;
|
||||
}
|
||||
|
||||
void IncludeRect(BRect& rect)
|
||||
{
|
||||
_AffineTransformRect(rect);
|
||||
*fBoundingBox = (*fBoundingBox) | rect;
|
||||
}
|
||||
|
||||
private:
|
||||
void _AffineTransformRect(BRect& rect)
|
||||
{
|
||||
BAffineTransform transform = fDrawState->CombinedTransform();
|
||||
if (transform.IsIdentity())
|
||||
return;
|
||||
|
||||
BPoint transformedShape[4];
|
||||
transformedShape[0] = rect.LeftTop();
|
||||
transformedShape[1] = rect.LeftBottom();
|
||||
transformedShape[2] = rect.RightTop();
|
||||
transformedShape[3] = rect.RightBottom();
|
||||
|
||||
transform.Apply(&transformedShape[0], 4);
|
||||
|
||||
float minX = INT_MAX;
|
||||
float minY = INT_MAX;
|
||||
float maxX = INT_MIN;
|
||||
float maxY = INT_MIN;
|
||||
|
||||
for (uint32 i = 0; i < 4; i++) {
|
||||
if (transformedShape[i].x < minX)
|
||||
minX = transformedShape[i].x;
|
||||
else if (transformedShape[i].x > maxX)
|
||||
maxX = transformedShape[i].x;
|
||||
if (transformedShape[i].y < minY)
|
||||
minY = transformedShape[i].y;
|
||||
else if (transformedShape[i].y > maxY)
|
||||
maxY = transformedShape[i].y;
|
||||
}
|
||||
|
||||
rect.Set(minX, minY, maxX, maxY);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
DrawState* fDrawState;
|
||||
BRect* fBoundingBox;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - Picture playback hooks
|
||||
|
||||
|
||||
static void
|
||||
get_polygon_frame(const BPoint* points, int32 numPoints, BRect* frame)
|
||||
{
|
||||
ASSERT(numPoints > 0);
|
||||
|
||||
float left = points->x;
|
||||
float top = points->y;
|
||||
float right = left;
|
||||
float bottom = top;
|
||||
|
||||
points++;
|
||||
numPoints--;
|
||||
|
||||
while (numPoints--) {
|
||||
if (points->x < left)
|
||||
left = points->x;
|
||||
if (points->x > right)
|
||||
right = points->x;
|
||||
if (points->y < top)
|
||||
top = points->y;
|
||||
if (points->y > bottom)
|
||||
bottom = points->y;
|
||||
points++;
|
||||
}
|
||||
|
||||
frame->Set(left, top, right, bottom);
|
||||
}
|
||||
|
||||
|
||||
template<class RectType>
|
||||
static void
|
||||
expand_rect_for_pen_size(BoundingBoxState* state, RectType& rect)
|
||||
{
|
||||
float penInset = -((state->GetDrawState()->PenSize() / 2.0f) + 1.0f);
|
||||
rect.InsetBy(penInset, penInset);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
move_pen_by(void* _state, const BPoint& delta)
|
||||
{
|
||||
TRACE_BB("%p move pen by %.2f %.2f\n", _state, delta.x, delta.y);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->GetDrawState()->SetPenLocation(
|
||||
state->GetDrawState()->PenLocation() + delta);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_stroke_line(void* _state, const BPoint& _start,
|
||||
const BPoint& _end)
|
||||
{
|
||||
TRACE_BB("%p stroke line %.2f %.2f -> %.2f %.2f\n", _state,
|
||||
_start.x, _start.y, _end.x, _end.y);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
BPoint start = _start;
|
||||
BPoint end = _end;
|
||||
|
||||
const SimpleTransform transform = state->PenToLocalTransform();
|
||||
transform.Apply(&start);
|
||||
transform.Apply(&end);
|
||||
|
||||
BRect rect;
|
||||
if (start.x <= end.x) {
|
||||
rect.left = start.x;
|
||||
rect.right = end.x;
|
||||
} else {
|
||||
rect.left = end.x;
|
||||
rect.right = start.x;
|
||||
}
|
||||
if (start.y <= end.y) {
|
||||
rect.top = start.y;
|
||||
rect.bottom = end.y;
|
||||
} else {
|
||||
rect.top = end.y;
|
||||
rect.bottom = start.y;
|
||||
}
|
||||
|
||||
expand_rect_for_pen_size(state, rect);
|
||||
state->IncludeRect(rect);
|
||||
|
||||
state->GetDrawState()->SetPenLocation(_end);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_draw_rect(void* _state, const BRect& _rect, bool fill)
|
||||
{
|
||||
TRACE_BB("%p draw rect fill=%d %.2f %.2f %.2f %.2f\n", _state, fill,
|
||||
_rect.left, _rect.top, _rect.right, _rect.bottom);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
BRect rect = _rect;
|
||||
state->PenToLocalTransform().Apply(&rect);
|
||||
if (!fill)
|
||||
expand_rect_for_pen_size(state, rect);
|
||||
state->IncludeRect(rect);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_draw_round_rect(void* _state, const BRect& _rect,
|
||||
const BPoint&, bool fill)
|
||||
{
|
||||
determine_bounds_draw_rect(_state, _rect, fill);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_bezier(BoundingBoxState* state, const BPoint* viewPoints,
|
||||
BRect& outRect)
|
||||
{
|
||||
// Note: this is an approximation which results in a rectangle which
|
||||
// encloses all four control points. That will always enclose the curve,
|
||||
// although not necessarily tightly, but it's good enough for the purpose.
|
||||
// The exact bounding box of a bezier curve is not trivial to determine,
|
||||
// (need to calculate derivative of the curve) and we're going for
|
||||
// performance here.
|
||||
BPoint points[4];
|
||||
state->PenToLocalTransform().Apply(points, viewPoints, 4);
|
||||
BPoint topLeft = points[0];
|
||||
BPoint bottomRight = points[0];
|
||||
for (uint32 index = 1; index < 4; index++) {
|
||||
if (points[index].x < topLeft.x || points[index].y < topLeft.y)
|
||||
topLeft = points[index];
|
||||
if (points[index].x > topLeft.x || points[index].y > topLeft.y)
|
||||
bottomRight = points[index];
|
||||
}
|
||||
outRect.SetLeftTop(topLeft);
|
||||
outRect.SetRightBottom(bottomRight);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_draw_bezier(void* _state, size_t numPoints,
|
||||
const BPoint viewPoints[], bool fill)
|
||||
{
|
||||
TRACE_BB("%p draw bezier fill=%d (%.2f %.2f) (%.2f %.2f) "
|
||||
"(%.2f %.2f) (%.2f %.2f)\n",
|
||||
_state,
|
||||
fill,
|
||||
viewPoints[0].x, viewPoints[0].y,
|
||||
viewPoints[1].x, viewPoints[1].y,
|
||||
viewPoints[2].x, viewPoints[2].y,
|
||||
viewPoints[3].x, viewPoints[3].y);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
const size_t kSupportedPoints = 4;
|
||||
if (numPoints != kSupportedPoints)
|
||||
return;
|
||||
|
||||
BRect rect;
|
||||
determine_bounds_bezier(state, viewPoints, rect);
|
||||
if (!fill)
|
||||
expand_rect_for_pen_size(state, rect);
|
||||
state->IncludeRect(rect);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_draw_ellipse(void* _state, const BRect& _rect, bool fill)
|
||||
{
|
||||
TRACE_BB("%p draw ellipse fill=%d (%.2f %.2f) (%.2f %.2f)\n", _state, fill,
|
||||
_rect.left, _rect.top, _rect.right, _rect.bottom);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
BRect rect = _rect;
|
||||
state->PenToLocalTransform().Apply(&rect);
|
||||
if (!fill)
|
||||
expand_rect_for_pen_size(state, rect);
|
||||
state->IncludeRect(rect);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_draw_arc(void* _state, const BPoint& center,
|
||||
const BPoint& radii, float, float, bool fill)
|
||||
{
|
||||
BRect rect(center.x - radii.x, center.y - radii.y,
|
||||
center.x + radii.x - 1, center.y + radii.y - 1);
|
||||
determine_bounds_draw_ellipse(_state, rect, fill);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_polygon(BoundingBoxState* state, int32 numPoints,
|
||||
const BPoint* viewPoints, BRect& outRect)
|
||||
{
|
||||
if (numPoints <= 0)
|
||||
return;
|
||||
|
||||
if (numPoints <= 200) {
|
||||
// fast path: no malloc/free, also avoid
|
||||
// constructor/destructor calls
|
||||
char data[200 * sizeof(BPoint)];
|
||||
BPoint* points = (BPoint*)data;
|
||||
|
||||
state->PenToLocalTransform().Apply(points, viewPoints, numPoints);
|
||||
get_polygon_frame(points, numPoints, &outRect);
|
||||
|
||||
} else {
|
||||
// avoid constructor/destructor calls by
|
||||
// using malloc instead of new []
|
||||
BPoint* points = (BPoint*)malloc(numPoints * sizeof(BPoint));
|
||||
if (points == NULL)
|
||||
return;
|
||||
|
||||
state->PenToLocalTransform().Apply(points, viewPoints, numPoints);
|
||||
get_polygon_frame(points, numPoints, &outRect);
|
||||
|
||||
free(points);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
determine_bounds_draw_polygon(void* _state, size_t numPoints,
|
||||
const BPoint viewPoints[], bool, bool fill)
|
||||
{
|
||||
TRACE_BB("%p draw polygon fill=%d (%ld points)\n", _state, fill, numPoints);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
BRect rect;
|
||||
determine_bounds_polygon(state, numPoints, viewPoints, rect);
|
||||
if (!fill)
|
||||
expand_rect_for_pen_size(state, rect);
|
||||
state->IncludeRect(rect);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_draw_shape(void* _state, const BShape& shape, bool fill)
|
||||
{
|
||||
BRect rect = shape.Bounds();
|
||||
|
||||
TRACE_BB("%p stroke shape (bounds %.2f %.2f %.2f %.2f)\n", _state,
|
||||
rect.left, rect.top, rect.right, rect.bottom);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->PenToLocalTransform().Apply(&rect);
|
||||
if (!fill)
|
||||
expand_rect_for_pen_size(state, rect);
|
||||
state->IncludeRect(rect);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_draw_string(void* _state, const char* string, size_t _length,
|
||||
float deltaSpace, float deltaNonSpace)
|
||||
{
|
||||
TRACE_BB("%p string '%s'\n", _state, string);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
ServerFont font = state->GetDrawState()->Font();
|
||||
|
||||
escapement_delta delta = { deltaSpace, deltaNonSpace };
|
||||
BRect rect;
|
||||
int32 length = _length;
|
||||
font.GetBoundingBoxesForStrings((char**)&string, &length, 1, &rect,
|
||||
B_SCREEN_METRIC, &delta);
|
||||
|
||||
BPoint location = state->GetDrawState()->PenLocation();
|
||||
|
||||
state->PenToLocalTransform().Apply(&location);
|
||||
rect.OffsetBy(location);
|
||||
state->IncludeRect(rect);
|
||||
|
||||
state->PenToLocalTransform().Apply(&location);
|
||||
state->GetDrawState()->SetPenLocation(location);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_draw_pixels(void* _state, const BRect&, const BRect& _dest,
|
||||
uint32, uint32, size_t, color_space, uint32, const void*, size_t)
|
||||
{
|
||||
TRACE_BB("%p pixels (dest %.2f %.2f %.2f %.2f)\n", _state,
|
||||
_dest.left, _dest.top, _dest.right, _dest.bottom);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
BRect dest = _dest;
|
||||
state->PenToLocalTransform().Apply(&dest);
|
||||
state->IncludeRect(dest);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_picture(void* _state, const BPoint& where, int32 token)
|
||||
{
|
||||
TRACE_BB("%p picture (unimplemented)\n", _state);
|
||||
|
||||
// TODO
|
||||
(void)_state;
|
||||
(void)where;
|
||||
(void)token;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_clipping_rects(void* _state, size_t numRects, const BRect rects[])
|
||||
{
|
||||
TRACE_BB("%p cliping rects (%ld rects)\n", _state, numRects);
|
||||
|
||||
// TODO
|
||||
(void)_state;
|
||||
(void)rects;
|
||||
(void)numRects;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clip_to_picture(void* _state, int32 pictureToken, const BPoint& where,
|
||||
bool clipToInverse)
|
||||
{
|
||||
TRACE_BB("%p clip to picture (unimplemented)\n", _state);
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
push_state(void* _state)
|
||||
{
|
||||
TRACE_BB("%p push state\n", _state);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->PushDrawState();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pop_state(void* _state)
|
||||
{
|
||||
TRACE_BB("%p pop state\n", _state);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->PopDrawState();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
enter_state_change(void*)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exit_state_change(void*)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
enter_font_state(void*)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exit_font_state(void*)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_origin(void* _state, const BPoint& pt)
|
||||
{
|
||||
TRACE_BB("%p set origin %.2f %.2f\n", _state, pt.x, pt.y);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
state->GetDrawState()->SetOrigin(pt);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_pen_location(void* _state, const BPoint& pt)
|
||||
{
|
||||
TRACE_BB("%p set pen location %.2f %.2f\n", _state, pt.x, pt.y);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
state->GetDrawState()->SetPenLocation(pt);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_drawing_mode(void*, drawing_mode)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_line_mode(void* _state, cap_mode capMode, join_mode joinMode,
|
||||
float miterLimit)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
DrawState* drawState = state->GetDrawState();
|
||||
drawState->SetLineCapMode(capMode);
|
||||
drawState->SetLineJoinMode(joinMode);
|
||||
drawState->SetMiterLimit(miterLimit);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_pen_size(void* _state, float size)
|
||||
{
|
||||
TRACE_BB("%p set pen size %.2f\n", _state, size);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->GetDrawState()->SetPenSize(size);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_fore_color(void* _state, const rgb_color& color)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->GetDrawState()->SetHighColor(color);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_back_color(void* _state, const rgb_color& color)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->GetDrawState()->SetLowColor(color);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_stipple_pattern(void* _state, const pattern& _pattern)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->GetDrawState()->SetPattern(Pattern(_pattern));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_scale(void* _state, float scale)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->GetDrawState()->SetScale(scale);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_family(void* _state, const char* _family, size_t length)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
BString family(_family, length);
|
||||
FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0);
|
||||
ServerFont font;
|
||||
font.SetStyle(fontStyle);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_style(void* _state, const char* _style, size_t length)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
BString style(_style, length);
|
||||
ServerFont font(state->GetDrawState()->Font());
|
||||
FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style);
|
||||
font.SetStyle(fontStyle);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_spacing(void* _state, uint8 spacing)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
ServerFont font;
|
||||
font.SetSpacing(spacing);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_SPACING);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_size(void* _state, float size)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
ServerFont font;
|
||||
font.SetSize(size);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_SIZE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_rotate(void* _state, float rotation)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
ServerFont font;
|
||||
font.SetRotation(rotation);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_ROTATION);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_encoding(void* _state, uint8 encoding)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
ServerFont font;
|
||||
font.SetEncoding(encoding);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_ENCODING);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_flags(void* _state, uint32 flags)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
ServerFont font;
|
||||
font.SetFlags(flags);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_FLAGS);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_shear(void* _state, float shear)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
ServerFont font;
|
||||
font.SetShear(shear);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_SHEAR);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_face(void* _state, uint16 face)
|
||||
{
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
ServerFont font;
|
||||
font.SetFace(face);
|
||||
state->GetDrawState()->SetFont(font, B_FONT_FACE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_blending_mode(void*, source_alpha, alpha_function)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_transform(void* _state, const BAffineTransform& transform)
|
||||
{
|
||||
TRACE_BB("%p transform\n", _state);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
state->GetDrawState()->SetTransform(transform);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
determine_bounds_nested_layer(void* _state, Layer* layer)
|
||||
{
|
||||
TRACE_BB("%p nested layer\n", _state);
|
||||
BoundingBoxState* const state =
|
||||
reinterpret_cast<BoundingBoxState*>(_state);
|
||||
|
||||
BRect boundingBox;
|
||||
PictureBoundingBoxPlayer::Play(layer, state->GetDrawState(), &boundingBox);
|
||||
if (boundingBox.IsValid())
|
||||
state->IncludeRect(boundingBox);
|
||||
}
|
||||
|
||||
|
||||
static const BPrivate::picture_player_callbacks
|
||||
kPictureBoundingBoxPlayerCallbacks = {
|
||||
move_pen_by,
|
||||
determine_bounds_stroke_line,
|
||||
determine_bounds_draw_rect,
|
||||
determine_bounds_draw_round_rect,
|
||||
determine_bounds_draw_bezier,
|
||||
determine_bounds_draw_arc,
|
||||
determine_bounds_draw_ellipse,
|
||||
determine_bounds_draw_polygon,
|
||||
determine_bounds_draw_shape,
|
||||
determine_bounds_draw_string,
|
||||
determine_bounds_draw_pixels,
|
||||
draw_picture,
|
||||
set_clipping_rects,
|
||||
clip_to_picture,
|
||||
push_state,
|
||||
pop_state,
|
||||
enter_state_change,
|
||||
exit_state_change,
|
||||
enter_font_state,
|
||||
exit_font_state,
|
||||
set_origin,
|
||||
set_pen_location,
|
||||
set_drawing_mode,
|
||||
set_line_mode,
|
||||
set_pen_size,
|
||||
set_fore_color,
|
||||
set_back_color,
|
||||
set_stipple_pattern,
|
||||
set_scale,
|
||||
set_font_family,
|
||||
set_font_style,
|
||||
set_font_spacing,
|
||||
set_font_size,
|
||||
set_font_rotate,
|
||||
set_font_encoding,
|
||||
set_font_flags,
|
||||
set_font_shear,
|
||||
set_font_face,
|
||||
set_blending_mode,
|
||||
set_transform,
|
||||
determine_bounds_nested_layer
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - PictureBoundingBoxPlayer
|
||||
|
||||
|
||||
/* static */ void
|
||||
PictureBoundingBoxPlayer::Play(ServerPicture* picture,
|
||||
const DrawState* drawState, BRect* outBoundingBox)
|
||||
{
|
||||
State state(drawState, outBoundingBox);
|
||||
|
||||
BMallocIO* mallocIO = dynamic_cast<BMallocIO*>(picture->fData);
|
||||
if (mallocIO == NULL)
|
||||
return;
|
||||
|
||||
BPrivate::PicturePlayer player(mallocIO->Buffer(),
|
||||
mallocIO->BufferLength(), ServerPicture::PictureList::Private(
|
||||
picture->fPictures).AsBList());
|
||||
player.Play(kPictureBoundingBoxPlayerCallbacks,
|
||||
sizeof(kPictureBoundingBoxPlayerCallbacks), &state);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2015, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef PICTURE_BOUNDING_BOX_H
|
||||
#define PICTURE_BOUNDING_BOX_H
|
||||
|
||||
|
||||
class BRect;
|
||||
class DrawState;
|
||||
class ServerPicture;
|
||||
|
||||
|
||||
class PictureBoundingBoxPlayer {
|
||||
public:
|
||||
class State;
|
||||
|
||||
public:
|
||||
static void Play(ServerPicture* picture,
|
||||
const DrawState* drawState,
|
||||
BRect* outBoundingBox);
|
||||
};
|
||||
|
||||
|
||||
#endif // PICTURE_BOUNDING_BOX_H
|
||||
+195
-170
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* Copyright 2001-2010, Haiku.
|
||||
* Copyright 2001-2015, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Marc Flerackers (mflerackers@androme.be)
|
||||
* Stefano Ceccherini (stefano.ceccherini@gmail.com)
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
#include "ServerPicture.h"
|
||||
@@ -18,6 +19,7 @@
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "FontManager.h"
|
||||
#include "Layer.h"
|
||||
#include "ServerApp.h"
|
||||
#include "ServerBitmap.h"
|
||||
#include "ServerFont.h"
|
||||
@@ -45,7 +47,7 @@ using std::stack;
|
||||
|
||||
class ShapePainter : public BShapeIterator {
|
||||
public:
|
||||
ShapePainter(DrawingContext* context);
|
||||
ShapePainter(Canvas* canvas);
|
||||
virtual ~ShapePainter();
|
||||
|
||||
status_t Iterate(const BShape* shape);
|
||||
@@ -60,15 +62,15 @@ public:
|
||||
void Draw(BRect frame, bool filled);
|
||||
|
||||
private:
|
||||
DrawingContext* fContext;
|
||||
Canvas* fCanvas;
|
||||
stack<uint32> fOpStack;
|
||||
stack<BPoint> fPtStack;
|
||||
};
|
||||
|
||||
|
||||
ShapePainter::ShapePainter(DrawingContext* context)
|
||||
ShapePainter::ShapePainter(Canvas* canvas)
|
||||
:
|
||||
fContext(context)
|
||||
fCanvas(canvas)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -204,10 +206,10 @@ ShapePainter::Draw(BRect frame, bool filled)
|
||||
fPtStack.pop();
|
||||
}
|
||||
|
||||
BPoint offset(fContext->CurrentState()->PenLocation());
|
||||
fContext->ConvertToScreenForDrawing(&offset);
|
||||
fContext->GetDrawingEngine()->DrawShape(frame, opCount, opList,
|
||||
ptCount, ptList, filled, offset, fContext->Scale());
|
||||
BPoint offset(fCanvas->CurrentState()->PenLocation());
|
||||
fCanvas->PenToScreenTransform().Apply(&offset);
|
||||
fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList,
|
||||
ptCount, ptList, filled, offset, fCanvas->Scale());
|
||||
|
||||
delete[] opList;
|
||||
delete[] ptList;
|
||||
@@ -248,26 +250,27 @@ get_polygon_frame(const BPoint* points, uint32 numPoints, BRect* _frame)
|
||||
|
||||
|
||||
static void
|
||||
move_pen_by(void* _context, const BPoint& delta)
|
||||
move_pen_by(void* _canvas, const BPoint& delta)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetPenLocation(
|
||||
context->CurrentState()->PenLocation() + delta);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetPenLocation(
|
||||
canvas->CurrentState()->PenLocation() + delta);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
stroke_line(void* _context, const BPoint& _start, const BPoint& _end)
|
||||
stroke_line(void* _canvas, const BPoint& _start, const BPoint& _end)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
BPoint start = _start;
|
||||
BPoint end = _end;
|
||||
|
||||
context->ConvertToScreenForDrawing(&start);
|
||||
context->ConvertToScreenForDrawing(&end);
|
||||
context->GetDrawingEngine()->StrokeLine(start, end);
|
||||
const SimpleTransform transform = canvas->PenToScreenTransform();
|
||||
transform.Apply(&start);
|
||||
transform.Apply(&end);
|
||||
canvas->GetDrawingEngine()->StrokeLine(start, end);
|
||||
|
||||
context->CurrentState()->SetPenLocation(_end);
|
||||
canvas->CurrentState()->SetPenLocation(_end);
|
||||
// the DrawingEngine/Painter does not need to be updated, since this
|
||||
// effects only the view->screen coord conversion, which is handled
|
||||
// by the view only
|
||||
@@ -275,79 +278,78 @@ stroke_line(void* _context, const BPoint& _start, const BPoint& _end)
|
||||
|
||||
|
||||
static void
|
||||
draw_rect(void* _context, const BRect& _rect, bool fill)
|
||||
draw_rect(void* _canvas, const BRect& _rect, bool fill)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
BRect rect = _rect;
|
||||
|
||||
context->ConvertToScreenForDrawing(&rect);
|
||||
canvas->PenToScreenTransform().Apply(&rect);
|
||||
if (fill)
|
||||
context->GetDrawingEngine()->FillRect(rect);
|
||||
canvas->GetDrawingEngine()->FillRect(rect);
|
||||
else
|
||||
context->GetDrawingEngine()->StrokeRect(rect);
|
||||
canvas->GetDrawingEngine()->StrokeRect(rect);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_round_rect(void* _context, const BRect& _rect, const BPoint& radii,
|
||||
draw_round_rect(void* _canvas, const BRect& _rect, const BPoint& radii,
|
||||
bool fill)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
BRect rect = _rect;
|
||||
|
||||
context->ConvertToScreenForDrawing(&rect);
|
||||
float scale = context->CurrentState()->CombinedScale();
|
||||
context->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
|
||||
canvas->PenToScreenTransform().Apply(&rect);
|
||||
float scale = canvas->CurrentState()->CombinedScale();
|
||||
canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
|
||||
radii.y * scale, fill);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_bezier(void* _context, size_t numPoints, const BPoint viewPoints[],
|
||||
draw_bezier(void* _canvas, size_t numPoints, const BPoint viewPoints[],
|
||||
bool fill)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
const size_t kSupportedPoints = 4;
|
||||
if (numPoints != kSupportedPoints)
|
||||
return;
|
||||
|
||||
BPoint points[kSupportedPoints];
|
||||
context->ConvertToScreenForDrawing(points, viewPoints, kSupportedPoints);
|
||||
|
||||
context->GetDrawingEngine()->DrawBezier(points, fill);
|
||||
canvas->PenToScreenTransform().Apply(points, viewPoints, kSupportedPoints);
|
||||
canvas->GetDrawingEngine()->DrawBezier(points, fill);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_arc(void* _context, const BPoint& center, const BPoint& radii,
|
||||
draw_arc(void* _canvas, const BPoint& center, const BPoint& radii,
|
||||
float startTheta, float arcTheta, bool fill)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
BRect rect(center.x - radii.x, center.y - radii.y,
|
||||
center.x + radii.x - 1, center.y + radii.y - 1);
|
||||
context->ConvertToScreenForDrawing(&rect);
|
||||
context->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill);
|
||||
canvas->PenToScreenTransform().Apply(&rect);
|
||||
canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_ellipse(void* _context, const BRect& _rect, bool fill)
|
||||
draw_ellipse(void* _canvas, const BRect& _rect, bool fill)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
BRect rect = _rect;
|
||||
context->ConvertToScreenForDrawing(&rect);
|
||||
context->GetDrawingEngine()->DrawEllipse(rect, fill);
|
||||
canvas->PenToScreenTransform().Apply(&rect);
|
||||
canvas->GetDrawingEngine()->DrawEllipse(rect, fill);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_polygon(void* _context, size_t numPoints, const BPoint viewPoints[],
|
||||
draw_polygon(void* _canvas, size_t numPoints, const BPoint viewPoints[],
|
||||
bool isClosed, bool fill)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
if (numPoints == 0)
|
||||
return;
|
||||
@@ -361,12 +363,12 @@ draw_polygon(void* _context, size_t numPoints, const BPoint viewPoints[],
|
||||
return;
|
||||
}
|
||||
|
||||
context->ConvertToScreenForDrawing(points, viewPoints, numPoints);
|
||||
canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);
|
||||
|
||||
BRect polyFrame;
|
||||
get_polygon_frame(points, numPoints, &polyFrame);
|
||||
|
||||
context->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
|
||||
canvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
|
||||
fill, isClosed && numPoints > 2);
|
||||
|
||||
if (numPoints > kMaxStackCount)
|
||||
@@ -375,10 +377,10 @@ draw_polygon(void* _context, size_t numPoints, const BPoint viewPoints[],
|
||||
|
||||
|
||||
static void
|
||||
draw_shape(void* _context, const BShape& shape, bool fill)
|
||||
draw_shape(void* _canvas, const BShape& shape, bool fill)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
ShapePainter drawShape(context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
ShapePainter drawShape(canvas);
|
||||
|
||||
drawShape.Iterate(&shape);
|
||||
drawShape.Draw(shape.Bounds(), fill);
|
||||
@@ -386,23 +388,23 @@ draw_shape(void* _context, const BShape& shape, bool fill)
|
||||
|
||||
|
||||
static void
|
||||
draw_string(void* _context, const char* string, size_t length, float deltaSpace,
|
||||
draw_string(void* _canvas, const char* string, size_t length, float deltaSpace,
|
||||
float deltaNonSpace)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
// NOTE: the picture data was recorded with a "set pen location"
|
||||
// command inserted before the "draw string" command, so we can
|
||||
// use PenLocation()
|
||||
BPoint location = context->CurrentState()->PenLocation();
|
||||
BPoint location = canvas->CurrentState()->PenLocation();
|
||||
|
||||
escapement_delta delta = { deltaSpace, deltaNonSpace };
|
||||
context->ConvertToScreenForDrawing(&location);
|
||||
location = context->GetDrawingEngine()->DrawString(string, length,
|
||||
canvas->PenToScreenTransform().Apply(&location);
|
||||
location = canvas->GetDrawingEngine()->DrawString(string, length,
|
||||
location, &delta);
|
||||
|
||||
context->ConvertFromScreenForDrawing(&location);
|
||||
context->CurrentState()->SetPenLocation(location);
|
||||
canvas->PenToScreenTransform().Apply(&location);
|
||||
canvas->CurrentState()->SetPenLocation(location);
|
||||
// the DrawingEngine/Painter does not need to be updated, since this
|
||||
// effects only the view->screen coord conversion, which is handled
|
||||
// by the view only
|
||||
@@ -410,11 +412,11 @@ draw_string(void* _context, const char* string, size_t length, float deltaSpace,
|
||||
|
||||
|
||||
static void
|
||||
draw_pixels(void* _context, const BRect& src, const BRect& _dest, uint32 width,
|
||||
draw_pixels(void* _canvas, const BRect& src, const BRect& _dest, uint32 width,
|
||||
uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 options,
|
||||
const void* data, size_t length)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1),
|
||||
(color_space)pixelFormat, 0, bytesPerRow);
|
||||
@@ -425,85 +427,90 @@ draw_pixels(void* _context, const BRect& src, const BRect& _dest, uint32 width,
|
||||
memcpy(bitmap.Bits(), data, std::min(height * bytesPerRow, length));
|
||||
|
||||
BRect dest = _dest;
|
||||
context->ConvertToScreenForDrawing(&dest);
|
||||
context->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
|
||||
canvas->PenToScreenTransform().Apply(&dest);
|
||||
canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_picture(void* _context, const BPoint& where, int32 token)
|
||||
draw_picture(void* _canvas, const BPoint& where, int32 token)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
ServerPicture* picture = context->GetPicture(token);
|
||||
ServerPicture* picture = canvas->GetPicture(token);
|
||||
if (picture != NULL) {
|
||||
context->PushState();
|
||||
context->SetDrawingOrigin(where);
|
||||
canvas->PushState();
|
||||
canvas->SetDrawingOrigin(where);
|
||||
|
||||
context->PushState();
|
||||
picture->Play(context);
|
||||
context->PopState();
|
||||
canvas->PushState();
|
||||
picture->Play(canvas);
|
||||
canvas->PopState();
|
||||
|
||||
context->PopState();
|
||||
canvas->PopState();
|
||||
picture->ReleaseReference();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_clipping_rects(void* _context, size_t numRects, const BRect rects[])
|
||||
set_clipping_rects(void* _canvas, size_t numRects, const BRect rects[])
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
// TODO: This might be too slow, we should copy the rects
|
||||
// directly to BRegion's internal data
|
||||
BRegion region;
|
||||
for (uint32 c = 0; c < numRects; c++)
|
||||
region.Include(rects[c]);
|
||||
|
||||
context->SetUserClipping(®ion);
|
||||
context->UpdateCurrentDrawingRegion();
|
||||
if (numRects == 0)
|
||||
canvas->SetUserClipping(NULL);
|
||||
else {
|
||||
// TODO: This might be too slow, we should copy the rects
|
||||
// directly to BRegion's internal data
|
||||
BRegion region;
|
||||
for (uint32 c = 0; c < numRects; c++)
|
||||
region.Include(rects[c]);
|
||||
canvas->SetUserClipping(®ion);
|
||||
}
|
||||
canvas->UpdateCurrentDrawingRegion();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clip_to_picture(void* _context, int32 pictureToken, const BPoint& where,
|
||||
clip_to_picture(void* _canvas, int32 pictureToken, const BPoint& where,
|
||||
bool clipToInverse)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
/* TODO
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
|
||||
ServerPicture* picture = context->GetPicture(pictureToken);
|
||||
ServerPicture* picture = canvas->GetPicture(pictureToken);
|
||||
if (picture == NULL)
|
||||
return;
|
||||
|
||||
AlphaMask* mask = new(std::nothrow) AlphaMask(
|
||||
picture, clipToInverse, where, *context->CurrentState());
|
||||
context->SetAlphaMask(mask);
|
||||
context->UpdateCurrentDrawingRegion();
|
||||
picture, clipToInverse, where, *canvas->CurrentState());
|
||||
canvas->SetAlphaMask(mask);
|
||||
canvas->UpdateCurrentDrawingRegion();
|
||||
if (mask != NULL)
|
||||
mask->ReleaseReference();
|
||||
|
||||
picture->ReleaseReference();
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
push_state(void* _context)
|
||||
push_state(void* _canvas)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->PushState();
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->PushState();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pop_state(void* _context)
|
||||
pop_state(void* _canvas)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->PopState();
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->PopState();
|
||||
|
||||
BPoint p(0, 0);
|
||||
context->ConvertToScreenForDrawing(&p);
|
||||
context->GetDrawingEngine()->SetDrawState(context->CurrentState(),
|
||||
canvas->PenToScreenTransform().Apply(&p);
|
||||
canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(),
|
||||
(int32)p.x, (int32)p.y);
|
||||
}
|
||||
|
||||
@@ -511,46 +518,46 @@ pop_state(void* _context)
|
||||
// TODO: Be smart and actually take advantage of these methods:
|
||||
// only apply state changes when they are called
|
||||
static void
|
||||
enter_state_change(void* context)
|
||||
enter_state_change(void* _canvas)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exit_state_change(void* _context)
|
||||
exit_state_change(void* _canvas)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->ResyncDrawState();
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->ResyncDrawState();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
enter_font_state(void* context)
|
||||
enter_font_state(void* _canvas)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exit_font_state(void* _context)
|
||||
exit_font_state(void* _canvas)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->GetDrawingEngine()->SetFont(context->CurrentState()->Font());
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->GetDrawingEngine()->SetFont(canvas->CurrentState()->Font());
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_origin(void* _context, const BPoint& pt)
|
||||
set_origin(void* _canvas, const BPoint& pt)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetOrigin(pt);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetOrigin(pt);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_pen_location(void* _context, const BPoint& pt)
|
||||
set_pen_location(void* _canvas, const BPoint& pt)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetPenLocation(pt);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetPenLocation(pt);
|
||||
// the DrawingEngine/Painter does not need to be updated, since this
|
||||
// effects only the view->screen coord conversion, which is handled
|
||||
// by the view only
|
||||
@@ -558,72 +565,72 @@ set_pen_location(void* _context, const BPoint& pt)
|
||||
|
||||
|
||||
static void
|
||||
set_drawing_mode(void* _context, drawing_mode mode)
|
||||
set_drawing_mode(void* _canvas, drawing_mode mode)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetDrawingMode(mode);
|
||||
context->GetDrawingEngine()->SetDrawingMode(mode);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
if (canvas->CurrentState()->SetDrawingMode(mode))
|
||||
canvas->GetDrawingEngine()->SetDrawingMode(mode);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_line_mode(void* _context, cap_mode capMode, join_mode joinMode,
|
||||
set_line_mode(void* _canvas, cap_mode capMode, join_mode joinMode,
|
||||
float miterLimit)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
DrawState* state = context->CurrentState();
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
DrawState* state = canvas->CurrentState();
|
||||
state->SetLineCapMode(capMode);
|
||||
state->SetLineJoinMode(joinMode);
|
||||
state->SetMiterLimit(miterLimit);
|
||||
context->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit);
|
||||
canvas->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_pen_size(void* _context, float size)
|
||||
set_pen_size(void* _canvas, float size)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetPenSize(size);
|
||||
context->GetDrawingEngine()->SetPenSize(
|
||||
context->CurrentState()->PenSize());
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetPenSize(size);
|
||||
canvas->GetDrawingEngine()->SetPenSize(
|
||||
canvas->CurrentState()->PenSize());
|
||||
// DrawState::PenSize() returns the scaled pen size, so we
|
||||
// need to use that value to set the drawing engine pen size.
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_fore_color(void* _context, const rgb_color& color)
|
||||
set_fore_color(void* _canvas, const rgb_color& color)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetHighColor(color);
|
||||
context->GetDrawingEngine()->SetHighColor(color);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetHighColor(color);
|
||||
canvas->GetDrawingEngine()->SetHighColor(color);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_back_color(void* _context, const rgb_color& color)
|
||||
set_back_color(void* _canvas, const rgb_color& color)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetLowColor(color);
|
||||
context->GetDrawingEngine()->SetLowColor(color);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetLowColor(color);
|
||||
canvas->GetDrawingEngine()->SetLowColor(color);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_stipple_pattern(void* _context, const pattern& pattern)
|
||||
set_stipple_pattern(void* _canvas, const pattern& pattern)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetPattern(Pattern(pattern));
|
||||
context->GetDrawingEngine()->SetPattern(pattern);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetPattern(Pattern(pattern));
|
||||
canvas->GetDrawingEngine()->SetPattern(pattern);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_scale(void* _context, float scale)
|
||||
set_scale(void* _canvas, float scale)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetScale(scale);
|
||||
context->ResyncDrawState();
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetScale(scale);
|
||||
canvas->ResyncDrawState();
|
||||
|
||||
// Update the drawing engine draw state, since some stuff
|
||||
// (for example the pen size) needs to be recalculated.
|
||||
@@ -631,109 +638,125 @@ set_scale(void* _context, float scale)
|
||||
|
||||
|
||||
static void
|
||||
set_font_family(void* _context, const char* _family, size_t length)
|
||||
set_font_family(void* _canvas, const char* _family, size_t length)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
BString family(_family, length);
|
||||
|
||||
FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0);
|
||||
ServerFont font;
|
||||
font.SetStyle(fontStyle);
|
||||
context->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_style(void* _context, const char* _style, size_t length)
|
||||
set_font_style(void* _canvas, const char* _style, size_t length)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
BString style(_style, length);
|
||||
|
||||
ServerFont font(context->CurrentState()->Font());
|
||||
ServerFont font(canvas->CurrentState()->Font());
|
||||
|
||||
FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style);
|
||||
|
||||
font.SetStyle(fontStyle);
|
||||
context->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_spacing(void* _context, uint8 spacing)
|
||||
set_font_spacing(void* _canvas, uint8 spacing)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
ServerFont font;
|
||||
font.SetSpacing(spacing);
|
||||
context->CurrentState()->SetFont(font, B_FONT_SPACING);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_SPACING);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_size(void* _context, float size)
|
||||
set_font_size(void* _canvas, float size)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
ServerFont font;
|
||||
font.SetSize(size);
|
||||
context->CurrentState()->SetFont(font, B_FONT_SIZE);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_SIZE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_rotation(void* _context, float rotation)
|
||||
set_font_rotation(void* _canvas, float rotation)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
ServerFont font;
|
||||
font.SetRotation(rotation);
|
||||
context->CurrentState()->SetFont(font, B_FONT_ROTATION);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_ROTATION);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_encoding(void* _context, uint8 encoding)
|
||||
set_font_encoding(void* _canvas, uint8 encoding)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
ServerFont font;
|
||||
font.SetEncoding(encoding);
|
||||
context->CurrentState()->SetFont(font, B_FONT_ENCODING);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_ENCODING);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_flags(void* _context, uint32 flags)
|
||||
set_font_flags(void* _canvas, uint32 flags)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
ServerFont font;
|
||||
font.SetFlags(flags);
|
||||
context->CurrentState()->SetFont(font, B_FONT_FLAGS);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_FLAGS);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_shear(void* _context, float shear)
|
||||
set_font_shear(void* _canvas, float shear)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
ServerFont font;
|
||||
font.SetShear(shear);
|
||||
context->CurrentState()->SetFont(font, B_FONT_SHEAR);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_SHEAR);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_font_face(void* _context, uint16 face)
|
||||
set_font_face(void* _canvas, uint16 face)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
ServerFont font;
|
||||
font.SetFace(face);
|
||||
context->CurrentState()->SetFont(font, B_FONT_FACE);
|
||||
canvas->CurrentState()->SetFont(font, B_FONT_FACE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_blending_mode(void* _context, source_alpha alphaSrcMode,
|
||||
set_blending_mode(void* _canvas, source_alpha alphaSrcMode,
|
||||
alpha_function alphaFncMode)
|
||||
{
|
||||
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context);
|
||||
context->CurrentState()->SetBlendingMode(alphaSrcMode, alphaFncMode);
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetBlendingMode(alphaSrcMode, alphaFncMode);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_transform(void* _canvas, const BAffineTransform& transform)
|
||||
{
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->CurrentState()->SetTransform(transform);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
blend_layer(void* _canvas, Layer* layer)
|
||||
{
|
||||
Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
|
||||
canvas->BlendLayer(layer);
|
||||
}
|
||||
|
||||
|
||||
@@ -776,7 +799,9 @@ static const BPrivate::picture_player_callbacks kPicturePlayerCallbacks = {
|
||||
set_font_flags,
|
||||
set_font_shear,
|
||||
set_font_face,
|
||||
set_blending_mode
|
||||
set_blending_mode,
|
||||
set_transform,
|
||||
blend_layer
|
||||
};
|
||||
|
||||
|
||||
@@ -925,7 +950,7 @@ ServerPicture::SyncState(View* view)
|
||||
|
||||
WriteSetOrigin(view->CurrentState()->Origin());
|
||||
WriteSetPenLocation(view->CurrentState()->PenLocation());
|
||||
WriteSetPenSize(view->CurrentState()->PenSize());
|
||||
WriteSetPenSize(view->CurrentState()->UnscaledPenSize());
|
||||
WriteSetScale(view->CurrentState()->Scale());
|
||||
WriteSetLineMode(view->CurrentState()->LineCapMode(),
|
||||
view->CurrentState()->LineJoinMode(),
|
||||
@@ -1010,7 +1035,7 @@ ServerPicture::SetFontFromLink(BPrivate::LinkReceiver& link)
|
||||
|
||||
|
||||
void
|
||||
ServerPicture::Play(DrawingContext* target)
|
||||
ServerPicture::Play(Canvas* target)
|
||||
{
|
||||
// TODO: for now: then change PicturePlayer
|
||||
// to accept a BPositionIO object
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright 2001-2010, Haiku.
|
||||
* Copyright 2001-2015, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Stefano Ceccherini <stefano.ceccherini@gmail.com>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef SERVER_PICTURE_H
|
||||
#define SERVER_PICTURE_H
|
||||
@@ -18,7 +19,7 @@
|
||||
|
||||
|
||||
class BFile;
|
||||
class DrawingContext;
|
||||
class Canvas;
|
||||
class ServerApp;
|
||||
class View;
|
||||
|
||||
@@ -35,7 +36,7 @@ public:
|
||||
ServerPicture(const ServerPicture& other);
|
||||
ServerPicture(const char* fileName,
|
||||
int32 offset);
|
||||
~ServerPicture();
|
||||
virtual ~ServerPicture();
|
||||
|
||||
int32 Token() { return fToken; }
|
||||
bool SetOwner(ServerApp* owner);
|
||||
@@ -49,7 +50,7 @@ public:
|
||||
void SyncState(View* view);
|
||||
void SetFontFromLink(BPrivate::LinkReceiver& link);
|
||||
|
||||
void Play(DrawingContext* target);
|
||||
void Play(Canvas* target);
|
||||
|
||||
void PushPicture(ServerPicture* picture);
|
||||
ServerPicture* PopPicture();
|
||||
@@ -63,6 +64,8 @@ public:
|
||||
status_t ExportData(BPrivate::PortLink& link);
|
||||
|
||||
private:
|
||||
friend class PictureBoundingBoxPlayer;
|
||||
|
||||
typedef BObjectList<ServerPicture> PictureList;
|
||||
|
||||
int32 fToken;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2010, Haiku.
|
||||
* Copyright 2001-2015, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -11,6 +11,7 @@
|
||||
* Artur Wyszynski <harakash@gmail.com>
|
||||
* Philippe Saint-Pierre <stpere@gmail.com>
|
||||
* Brecht Machiels <brecht@mos6581.org>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
|
||||
@@ -61,6 +62,7 @@
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "HWInterface.h"
|
||||
#include "Layer.h"
|
||||
#include "Overlay.h"
|
||||
#include "ProfileMessageSupport.h"
|
||||
#include "RenderingBuffer.h"
|
||||
@@ -351,7 +353,7 @@ ServerWindow::_Show()
|
||||
fDesktop->ShowWindow(fWindow);
|
||||
if (fDirectWindowInfo && fDirectWindowInfo->IsFullScreen())
|
||||
_ResizeToFullScreen();
|
||||
|
||||
|
||||
fDesktop->LockSingleWindow();
|
||||
}
|
||||
|
||||
@@ -1940,11 +1942,13 @@ fDesktop->LockSingleWindow();
|
||||
if (picture == NULL)
|
||||
break;
|
||||
|
||||
AlphaMask* mask = new(std::nothrow) AlphaMask(
|
||||
picture, inverse, where, *fCurrentView->CurrentState());
|
||||
AlphaMask* const mask = new PictureAlphaMask(
|
||||
fCurrentView->GetAlphaMask(), picture,
|
||||
*fCurrentView->CurrentState(), where, inverse);
|
||||
fCurrentView->SetAlphaMask(mask);
|
||||
if (mask != NULL)
|
||||
mask->ReleaseReference();
|
||||
|
||||
_UpdateDrawState(fCurrentView);
|
||||
|
||||
picture->ReleaseReference();
|
||||
@@ -1964,7 +1968,7 @@ fDesktop->LockSingleWindow();
|
||||
} else {
|
||||
_UpdateCurrentDrawingRegion();
|
||||
BRegion region(fCurrentDrawingRegion);
|
||||
fCurrentView->ConvertFromScreen(®ion);
|
||||
fCurrentView->ScreenToLocalTransform().Apply(®ion);
|
||||
fLink.AttachRegion(region);
|
||||
}
|
||||
fLink.Flush();
|
||||
@@ -2185,6 +2189,29 @@ fDesktop->LockSingleWindow();
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_VIEW_BEGIN_LAYER:
|
||||
{
|
||||
DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_LAYER\n",
|
||||
Title()));
|
||||
|
||||
uint8 opacity;
|
||||
link.Read<uint8>(&opacity);
|
||||
|
||||
Layer* layer = new(std::nothrow) Layer(opacity);
|
||||
if (layer == NULL)
|
||||
break;
|
||||
|
||||
if (opacity != 255) {
|
||||
fCurrentView->CurrentState()->SetDrawingMode(B_OP_ALPHA);
|
||||
fCurrentView->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA,
|
||||
B_ALPHA_COMPOSITE);
|
||||
fCurrentView->CurrentState()->SetDrawingModeLocked(true);
|
||||
}
|
||||
|
||||
fCurrentView->SetPicture(layer);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
_DispatchViewDrawingMessage(code, link);
|
||||
break;
|
||||
@@ -2255,8 +2282,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
info.endPoint.x, info.endPoint.y));
|
||||
|
||||
BPoint penPos = info.endPoint;
|
||||
fCurrentView->ConvertToScreenForDrawing(&info.startPoint);
|
||||
fCurrentView->ConvertToScreenForDrawing(&info.endPoint);
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
transform.Apply(&info.startPoint);
|
||||
transform.Apply(&info.endPoint);
|
||||
drawingEngine->StrokeLine(info.startPoint, info.endPoint);
|
||||
|
||||
// We update the pen here because many DrawingEngine calls which
|
||||
@@ -2280,7 +2309,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
fCurrentView->Name(), rect.left, rect.top, rect.right,
|
||||
rect.bottom));
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->PenToScreenTransform().Apply(&rect);
|
||||
drawingEngine->InvertRect(rect);
|
||||
break;
|
||||
}
|
||||
@@ -2295,7 +2324,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
fCurrentView->Name(), rect.left, rect.top, rect.right,
|
||||
rect.bottom));
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->PenToScreenTransform().Apply(&rect);
|
||||
drawingEngine->StrokeRect(rect);
|
||||
break;
|
||||
}
|
||||
@@ -2310,7 +2339,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
fCurrentView->Name(), rect.left, rect.top, rect.right,
|
||||
rect.bottom));
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->PenToScreenTransform().Apply(&rect);
|
||||
drawingEngine->FillRect(rect);
|
||||
break;
|
||||
}
|
||||
@@ -2327,8 +2356,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
fCurrentView->Name(), rect.left, rect.top, rect.right,
|
||||
rect.bottom));
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
transform.Apply(&rect);
|
||||
transform.Apply(gradient);
|
||||
drawingEngine->FillRect(rect, *gradient);
|
||||
delete gradient;
|
||||
break;
|
||||
@@ -2357,7 +2388,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
info.viewRect.left, info.viewRect.top,
|
||||
info.viewRect.right, info.viewRect.bottom));
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&info.viewRect);
|
||||
fCurrentView->PenToScreenTransform().Apply(&info.viewRect);
|
||||
|
||||
// TODO: Unbreak...
|
||||
// if ((info.options & B_WAIT_FOR_RETRACE) != 0)
|
||||
@@ -2383,7 +2414,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
if (link.Read<float>(&span) != B_OK)
|
||||
break;
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&r);
|
||||
fCurrentView->PenToScreenTransform().Apply(&r);
|
||||
drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC);
|
||||
break;
|
||||
}
|
||||
@@ -2400,8 +2431,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
BGradient* gradient;
|
||||
if (link.ReadGradient(&gradient) != B_OK)
|
||||
break;
|
||||
fCurrentView->ConvertToScreenForDrawing(&r);
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
transform.Apply(&r);
|
||||
transform.Apply(gradient);
|
||||
drawingEngine->FillArc(r, angle, span, *gradient);
|
||||
delete gradient;
|
||||
break;
|
||||
@@ -2412,11 +2445,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n",
|
||||
Title()));
|
||||
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
BPoint pts[4];
|
||||
status_t status;
|
||||
for (int32 i = 0; i < 4; i++) {
|
||||
status = link.Read<BPoint>(&(pts[i]));
|
||||
fCurrentView->ConvertToScreenForDrawing(&pts[i]);
|
||||
transform.Apply(&pts[i]);
|
||||
}
|
||||
if (status != B_OK)
|
||||
break;
|
||||
@@ -2429,15 +2464,17 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n",
|
||||
Title()));
|
||||
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
BPoint pts[4];
|
||||
for (int32 i = 0; i < 4; i++) {
|
||||
link.Read<BPoint>(&(pts[i]));
|
||||
fCurrentView->ConvertToScreenForDrawing(&pts[i]);
|
||||
transform.Apply(&pts[i]);
|
||||
}
|
||||
BGradient* gradient;
|
||||
if (link.ReadGradient(&gradient) != B_OK)
|
||||
break;
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
transform.Apply(gradient);
|
||||
drawingEngine->FillBezier(pts, *gradient);
|
||||
delete gradient;
|
||||
break;
|
||||
@@ -2452,7 +2489,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
if (link.Read<BRect>(&rect) != B_OK)
|
||||
break;
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->PenToScreenTransform().Apply(&rect);
|
||||
drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE);
|
||||
break;
|
||||
}
|
||||
@@ -2466,8 +2503,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
BGradient* gradient;
|
||||
if (link.ReadGradient(&gradient) != B_OK)
|
||||
break;
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
transform.Apply(&rect);
|
||||
transform.Apply(gradient);
|
||||
drawingEngine->FillEllipse(rect, *gradient);
|
||||
delete gradient;
|
||||
break;
|
||||
@@ -2486,7 +2525,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
if (link.Read<float>(&yRadius) != B_OK)
|
||||
break;
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->PenToScreenTransform().Apply(&rect);
|
||||
float scale = fCurrentView->CurrentState()->CombinedScale();
|
||||
drawingEngine->DrawRoundRect(rect, xRadius * scale, yRadius * scale,
|
||||
code == AS_FILL_ROUNDRECT);
|
||||
@@ -2505,8 +2544,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
BGradient* gradient;
|
||||
if (link.ReadGradient(&gradient) != B_OK)
|
||||
break;
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
transform.Apply(&rect);
|
||||
transform.Apply(gradient);
|
||||
drawingEngine->FillRoundRect(rect, xrad, yrad, *gradient);
|
||||
delete gradient;
|
||||
break;
|
||||
@@ -2517,18 +2558,20 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n",
|
||||
Title()));
|
||||
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
BPoint pts[3];
|
||||
BRect rect;
|
||||
|
||||
for (int32 i = 0; i < 3; i++) {
|
||||
link.Read<BPoint>(&(pts[i]));
|
||||
fCurrentView->ConvertToScreenForDrawing(&pts[i]);
|
||||
transform.Apply(&pts[i]);
|
||||
}
|
||||
|
||||
if (link.Read<BRect>(&rect) != B_OK)
|
||||
break;
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
transform.Apply(&rect);
|
||||
drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE);
|
||||
break;
|
||||
}
|
||||
@@ -2537,18 +2580,20 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n",
|
||||
Title()));
|
||||
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
BPoint pts[3];
|
||||
BRect rect;
|
||||
for (int32 i = 0; i < 3; i++) {
|
||||
link.Read<BPoint>(&(pts[i]));
|
||||
fCurrentView->ConvertToScreenForDrawing(&pts[i]);
|
||||
transform.Apply(&pts[i]);
|
||||
}
|
||||
link.Read<BRect>(&rect);
|
||||
BGradient* gradient;
|
||||
if (link.ReadGradient(&gradient) != B_OK)
|
||||
break;
|
||||
fCurrentView->ConvertToScreenForDrawing(&rect);
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
transform.Apply(&rect);
|
||||
transform.Apply(gradient);
|
||||
drawingEngine->FillTriangle(pts, rect, *gradient);
|
||||
delete gradient;
|
||||
break;
|
||||
@@ -2568,11 +2613,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
link.Read<bool>(&isClosed);
|
||||
link.Read<int32>(&pointCount);
|
||||
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
BPoint* pointList = new(nothrow) BPoint[pointCount];
|
||||
if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
|
||||
for (int32 i = 0; i < pointCount; i++)
|
||||
fCurrentView->ConvertToScreenForDrawing(&pointList[i]);
|
||||
fCurrentView->ConvertToScreenForDrawing(&polyFrame);
|
||||
transform.Apply(&pointList[i]);
|
||||
transform.Apply(&polyFrame);
|
||||
|
||||
drawingEngine->DrawPolygon(pointList, pointCount, polyFrame,
|
||||
code == AS_FILL_POLYGON, isClosed && pointCount > 2);
|
||||
@@ -2591,14 +2638,16 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
link.Read<BRect>(&polyFrame);
|
||||
link.Read<int32>(&pointCount);
|
||||
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
BPoint* pointList = new(nothrow) BPoint[pointCount];
|
||||
BGradient* gradient;
|
||||
if (link.Read(pointList, pointCount * sizeof(BPoint)) == B_OK
|
||||
&& link.ReadGradient(&gradient) == B_OK) {
|
||||
for (int32 i = 0; i < pointCount; i++)
|
||||
fCurrentView->ConvertToScreenForDrawing(&pointList[i]);
|
||||
fCurrentView->ConvertToScreenForDrawing(&polyFrame);
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
transform.Apply(&pointList[i]);
|
||||
transform.Apply(&polyFrame);
|
||||
transform.Apply(gradient);
|
||||
|
||||
drawingEngine->FillPolygon(pointList, pointCount,
|
||||
polyFrame, *gradient, isClosed && pointCount > 2);
|
||||
@@ -2632,8 +2681,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
= fCurrentView->CurrentState()->PenLocation();
|
||||
shapeFrame.OffsetBy(screenOffset);
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&screenOffset);
|
||||
fCurrentView->ConvertToScreenForDrawing(&shapeFrame);
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
transform.Apply(&screenOffset);
|
||||
transform.Apply(&shapeFrame);
|
||||
|
||||
drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount,
|
||||
ptList, code == AS_FILL_SHAPE, screenOffset,
|
||||
@@ -2670,9 +2721,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
= fCurrentView->CurrentState()->PenLocation();
|
||||
shapeFrame.OffsetBy(screenOffset);
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&screenOffset);
|
||||
fCurrentView->ConvertToScreenForDrawing(&shapeFrame);
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
transform.Apply(&screenOffset);
|
||||
transform.Apply(&shapeFrame);
|
||||
transform.Apply(gradient);
|
||||
drawingEngine->FillShape(shapeFrame, opCount, opList,
|
||||
ptCount, ptList, *gradient, screenOffset,
|
||||
fCurrentView->Scale());
|
||||
@@ -2691,7 +2744,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
if (link.ReadRegion(®ion) < B_OK)
|
||||
break;
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(®ion);
|
||||
fCurrentView->PenToScreenTransform().Apply(®ion);
|
||||
drawingEngine->FillRegion(region);
|
||||
|
||||
break;
|
||||
@@ -2708,8 +2761,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
if (link.ReadGradient(&gradient) != B_OK)
|
||||
break;
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(®ion);
|
||||
fCurrentView->ConvertToScreenForDrawing(gradient);
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
transform.Apply(®ion);
|
||||
transform.Apply(gradient);
|
||||
drawingEngine->FillRegion(region, *gradient);
|
||||
delete gradient;
|
||||
break;
|
||||
@@ -2748,11 +2803,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
}
|
||||
|
||||
// Convert to screen coords and draw
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
for (int32 i = 0; i < lineCount; i++) {
|
||||
fCurrentView->ConvertToScreenForDrawing(
|
||||
&lineData[i].startPoint);
|
||||
fCurrentView->ConvertToScreenForDrawing(
|
||||
&lineData[i].endPoint);
|
||||
transform.Apply(&lineData[i].startPoint);
|
||||
transform.Apply(&lineData[i].endPoint);
|
||||
}
|
||||
drawingEngine->StrokeLineArray(lineCount, lineData);
|
||||
|
||||
@@ -2797,11 +2852,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View: %s "
|
||||
"-> %s\n", Title(), fCurrentView->Name(), string));
|
||||
|
||||
fCurrentView->ConvertToScreenForDrawing(&info.location);
|
||||
fCurrentView->PenToScreenTransform().Apply(&info.location);
|
||||
BPoint penLocation = drawingEngine->DrawString(string,
|
||||
info.stringLength, info.location, delta);
|
||||
|
||||
fCurrentView->ConvertFromScreenForDrawing(&penLocation);
|
||||
fCurrentView->ScreenToPenTransform().Apply(&penLocation);
|
||||
fCurrentView->CurrentState()->SetPenLocation(penLocation);
|
||||
|
||||
if (string != stackString)
|
||||
@@ -2854,13 +2909,15 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING_WITH_OFFSETS, View: %s "
|
||||
"-> %s\n", Title(), fCurrentView->Name(), string));
|
||||
|
||||
const SimpleTransform transform =
|
||||
fCurrentView->PenToScreenTransform();
|
||||
for (int32 i = 0; i < glyphCount; i++)
|
||||
fCurrentView->ConvertToScreenForDrawing(&locations[i]);
|
||||
transform.Apply(&locations[i]);
|
||||
|
||||
BPoint penLocation = drawingEngine->DrawString(string,
|
||||
stringLength, locations);
|
||||
|
||||
fCurrentView->ConvertFromScreenForDrawing(&penLocation);
|
||||
fCurrentView->ScreenToPenTransform().Apply(&penLocation);
|
||||
fCurrentView->CurrentState()->SetPenLocation(penLocation);
|
||||
|
||||
break;
|
||||
@@ -2893,6 +2950,16 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_VIEW_END_LAYER:
|
||||
{
|
||||
DTRACE(("ServerWindow %s: Message AS_VIEW_END_LAYER\n",
|
||||
Title()));
|
||||
fCurrentView->BlendAllLayers();
|
||||
fCurrentView->SetPicture(NULL);
|
||||
fCurrentView->CurrentState()->SetDrawingModeLocked(false);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BString codeString;
|
||||
string_for_message_code(code, codeString);
|
||||
@@ -3411,6 +3478,49 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
fLink.Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
case AS_VIEW_BEGIN_LAYER:
|
||||
{
|
||||
uint8 opacity;
|
||||
link.Read<uint8>(&opacity);
|
||||
|
||||
Layer* layer = dynamic_cast<Layer*>(picture);
|
||||
if (layer == NULL)
|
||||
break;
|
||||
|
||||
Layer* nextLayer = new(std::nothrow) Layer(opacity);
|
||||
if (nextLayer == NULL)
|
||||
break;
|
||||
|
||||
if (opacity != 255) {
|
||||
fCurrentView->CurrentState()->SetDrawingMode(B_OP_ALPHA);
|
||||
fCurrentView->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA,
|
||||
B_ALPHA_COMPOSITE);
|
||||
fCurrentView->CurrentState()->SetDrawingModeLocked(true);
|
||||
}
|
||||
|
||||
nextLayer->PushLayer(layer);
|
||||
fCurrentView->SetPicture(nextLayer);
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_VIEW_END_LAYER:
|
||||
{
|
||||
Layer* layer = dynamic_cast<Layer*>(picture);
|
||||
if (layer == NULL)
|
||||
break;
|
||||
|
||||
Layer* previousLayer = layer->PopLayer();
|
||||
if (previousLayer == NULL) {
|
||||
// End last layer
|
||||
return false;
|
||||
}
|
||||
fCurrentView->SetPicture(previousLayer);
|
||||
|
||||
previousLayer->WriteBlendLayer(layer);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case AS_VIEW_SET_BLENDING_MODE:
|
||||
{
|
||||
@@ -3728,11 +3838,11 @@ ServerWindow::_UpdateDrawState(View* view)
|
||||
if (view != NULL && drawingEngine != NULL) {
|
||||
BPoint leftTop(0, 0);
|
||||
if (view->GetAlphaMask() != NULL) {
|
||||
view->ConvertToScreen(&leftTop);
|
||||
view->GetAlphaMask()->Update(view->Bounds(), leftTop);
|
||||
view->LocalToScreenTransform().Apply(&leftTop);
|
||||
view->GetAlphaMask()->SetViewOrigin(leftTop);
|
||||
leftTop = BPoint(0, 0);
|
||||
}
|
||||
view->ConvertToScreenForDrawing(&leftTop);
|
||||
view->PenToScreenTransform().Apply(&leftTop);
|
||||
drawingEngine->SetDrawState(view->CurrentState(), leftTop.x, leftTop.y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
#ifndef SIMPLE_TRANSFORM_H
|
||||
#define SIMPLE_TRANSFORM_H
|
||||
|
||||
#include <GradientLinear.h>
|
||||
#include <GradientRadial.h>
|
||||
#include <GradientRadialFocus.h>
|
||||
#include <GradientDiamond.h>
|
||||
#include <GradientConic.h>
|
||||
#include <Point.h>
|
||||
#include <Region.h>
|
||||
|
||||
#include "IntPoint.h"
|
||||
#include "IntRect.h"
|
||||
|
||||
|
||||
class SimpleTransform {
|
||||
public:
|
||||
SimpleTransform()
|
||||
:
|
||||
fScale(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
void AddOffset(float x, float y)
|
||||
{
|
||||
fOffset.x += x;
|
||||
fOffset.y += y;
|
||||
}
|
||||
|
||||
void SetScale(float scale)
|
||||
{
|
||||
fScale = scale;
|
||||
}
|
||||
|
||||
void Apply(BPoint* point) const
|
||||
{
|
||||
_Apply(point->x, point->y);
|
||||
}
|
||||
|
||||
void Apply(IntPoint* point) const
|
||||
{
|
||||
_Apply(point->x, point->y);
|
||||
}
|
||||
|
||||
void Apply(BRect* rect) const
|
||||
{
|
||||
if (fScale == 1.0) {
|
||||
rect->OffsetBy(fOffset.x, fOffset.y);
|
||||
} else {
|
||||
_Apply(rect->left, rect->top);
|
||||
_Apply(rect->right, rect->bottom);
|
||||
}
|
||||
}
|
||||
|
||||
void Apply(IntRect* rect) const
|
||||
{
|
||||
if (fScale == 1.0) {
|
||||
rect->OffsetBy(fOffset.x, fOffset.y);
|
||||
} else {
|
||||
_Apply(rect->left, rect->top);
|
||||
_Apply(rect->right, rect->bottom);
|
||||
}
|
||||
}
|
||||
|
||||
void Apply(BRegion* region) const
|
||||
{
|
||||
if (fScale == 1.0) {
|
||||
region->OffsetBy(fOffset.x, fOffset.y);
|
||||
} else {
|
||||
// TODO: optimize some more
|
||||
BRegion converted;
|
||||
int32 count = region->CountRects();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BRect r = region->RectAt(i);
|
||||
BPoint lt(r.LeftTop());
|
||||
BPoint rb(r.RightBottom());
|
||||
// offset to bottom right corner of pixel before transformation
|
||||
rb.x++;
|
||||
rb.y++;
|
||||
// apply transformation
|
||||
_Apply(lt.x, lt.y);
|
||||
_Apply(rb.x, rb.y);
|
||||
// reset bottom right to pixel "index"
|
||||
rb.x--;
|
||||
rb.y--;
|
||||
// add rect to converted region
|
||||
// NOTE/TODO: the rect would not have to go
|
||||
// through the whole intersection test process,
|
||||
// it is guaranteed not to overlap with any rect
|
||||
// already contained in the region
|
||||
converted.Include(BRect(lt, rb));
|
||||
}
|
||||
*region = converted;
|
||||
}
|
||||
}
|
||||
|
||||
void Apply(BGradient* gradient) const
|
||||
{
|
||||
switch (gradient->GetType()) {
|
||||
case BGradient::TYPE_LINEAR:
|
||||
{
|
||||
BGradientLinear* linear = (BGradientLinear*) gradient;
|
||||
BPoint start = linear->Start();
|
||||
BPoint end = linear->End();
|
||||
Apply(&start);
|
||||
Apply(&end);
|
||||
linear->SetStart(start);
|
||||
linear->SetEnd(end);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_RADIAL:
|
||||
{
|
||||
BGradientRadial* radial = (BGradientRadial*) gradient;
|
||||
BPoint center = radial->Center();
|
||||
Apply(¢er);
|
||||
radial->SetCenter(center);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_RADIAL_FOCUS:
|
||||
{
|
||||
BGradientRadialFocus* radialFocus =
|
||||
(BGradientRadialFocus*)gradient;
|
||||
BPoint center = radialFocus->Center();
|
||||
BPoint focal = radialFocus->Focal();
|
||||
Apply(¢er);
|
||||
Apply(&focal);
|
||||
radialFocus->SetCenter(center);
|
||||
radialFocus->SetFocal(focal);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_DIAMOND:
|
||||
{
|
||||
BGradientDiamond* diamond = (BGradientDiamond*) gradient;
|
||||
BPoint center = diamond->Center();
|
||||
Apply(¢er);
|
||||
diamond->SetCenter(center);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_CONIC:
|
||||
{
|
||||
BGradientConic* conic = (BGradientConic*) gradient;
|
||||
BPoint center = conic->Center();
|
||||
Apply(¢er);
|
||||
conic->SetCenter(center);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_NONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the gradient is fully padded so that out of bounds access
|
||||
// get the correct colors
|
||||
gradient->SortColorStopsByOffset();
|
||||
|
||||
BGradient::ColorStop* end = gradient->ColorStopAtFast(
|
||||
gradient->CountColorStops() - 1);
|
||||
|
||||
if (end->offset != 255)
|
||||
gradient->AddColor(end->color, 255);
|
||||
|
||||
BGradient::ColorStop* start = gradient->ColorStopAtFast(0);
|
||||
|
||||
if (start->offset != 0)
|
||||
gradient->AddColor(start->color, 0);
|
||||
|
||||
gradient->SortColorStopsByOffset();
|
||||
}
|
||||
|
||||
void Apply(BPoint* destination, const BPoint* source, int32 count) const
|
||||
{
|
||||
// TODO: optimize this, it should be smarter
|
||||
while (count--) {
|
||||
*destination = *source;
|
||||
Apply(destination);
|
||||
source++;
|
||||
destination++;
|
||||
}
|
||||
}
|
||||
|
||||
void Apply(BRect* destination, const BRect* source, int32 count) const
|
||||
{
|
||||
// TODO: optimize this, it should be smarter
|
||||
while (count--) {
|
||||
*destination = *source;
|
||||
Apply(destination);
|
||||
source++;
|
||||
destination++;
|
||||
}
|
||||
}
|
||||
|
||||
void Apply(BRegion* destination, const BRegion* source, int32 count) const
|
||||
{
|
||||
// TODO: optimize this, it should be smarter
|
||||
while (count--) {
|
||||
*destination = *source;
|
||||
Apply(destination);
|
||||
source++;
|
||||
destination++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void _Apply(int32& x, int32& y) const
|
||||
{
|
||||
x *= (int32)fScale;
|
||||
y *= (int32)fScale;
|
||||
x += (int32)fOffset.x;
|
||||
y += (int32)fOffset.y;
|
||||
}
|
||||
|
||||
void _Apply(float& x, float& y) const
|
||||
{
|
||||
x *= fScale;
|
||||
y *= fScale;
|
||||
x += fOffset.x;
|
||||
y += fOffset.y;
|
||||
}
|
||||
|
||||
private:
|
||||
BPoint fOffset;
|
||||
float fScale;
|
||||
};
|
||||
|
||||
|
||||
#endif // SIMPLE_TRANSFORM_H
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Christian Packmann
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#include "TestServerLoopAdapter.h"
|
||||
|
||||
#include "Desktop.h"
|
||||
#include "ServerConfig.h"
|
||||
#include "ServerProtocol.h"
|
||||
|
||||
#include <PortLink.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//#define DEBUG_SERVER
|
||||
#ifdef DEBUG_SERVER
|
||||
# include <stdio.h>
|
||||
# define STRACE(x) printf x
|
||||
#else
|
||||
# define STRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
TestServerLoopAdapter::TestServerLoopAdapter(const char* signature,
|
||||
const char*, port_id, bool, status_t* outError)
|
||||
:
|
||||
MessageLooper("test-app_server"),
|
||||
fMessagePort(_CreatePort())
|
||||
{
|
||||
fLink.SetReceiverPort(fMessagePort);
|
||||
*outError = B_OK;
|
||||
}
|
||||
|
||||
|
||||
TestServerLoopAdapter::~TestServerLoopAdapter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TestServerLoopAdapter::Run()
|
||||
{
|
||||
rename_thread(find_thread(NULL), "picasso");
|
||||
_message_thread((void*)this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TestServerLoopAdapter::_DispatchMessage(int32 code,
|
||||
BPrivate::LinkReceiver& link)
|
||||
{
|
||||
switch (code) {
|
||||
case AS_GET_DESKTOP:
|
||||
{
|
||||
port_id replyPort = 0;
|
||||
link.Read<port_id>(&replyPort);
|
||||
|
||||
int32 userID = -1;
|
||||
link.Read<int32>(&userID);
|
||||
|
||||
char* targetScreen = NULL;
|
||||
link.ReadString(&targetScreen);
|
||||
|
||||
int32 version = -1;
|
||||
link.Read<int32>(&version);
|
||||
|
||||
BMessage message(AS_GET_DESKTOP);
|
||||
message.AddInt32("user", userID);
|
||||
message.AddInt32("version", version);
|
||||
message.AddString("target", targetScreen);
|
||||
MessageReceived(&message);
|
||||
|
||||
// AppServer will try to send a reply, we just let that fail
|
||||
// since we can find out the port by getting the desktop instance
|
||||
// ourselves
|
||||
|
||||
free(targetScreen);
|
||||
Desktop* desktop = _FindDesktop(userID, targetScreen);
|
||||
|
||||
BPrivate::LinkSender reply(replyPort);
|
||||
if (desktop != NULL) {
|
||||
reply.StartMessage(B_OK);
|
||||
reply.Attach<port_id>(desktop->MessagePort());
|
||||
} else
|
||||
reply.StartMessage(B_ERROR);
|
||||
|
||||
reply.Flush();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case B_QUIT_REQUESTED:
|
||||
{
|
||||
QuitRequested();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
STRACE(("Server::MainLoop received unexpected code %" B_PRId32 " "
|
||||
"(offset %" B_PRId32 ")\n", code, code - SERVER_TRUE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
port_id
|
||||
TestServerLoopAdapter::_CreatePort()
|
||||
{
|
||||
port_id port = create_port(DEFAULT_MONITOR_PORT_SIZE, SERVER_PORT_NAME);
|
||||
if (port < B_OK)
|
||||
debugger("test-app_server could not create message port");
|
||||
return port;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Julian Harnath, <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef TEST_SERVER_LOOP_ADAPTER_H
|
||||
#define TEST_SERVER_LOOP_ADAPTER_H
|
||||
|
||||
#include "MessageLooper.h"
|
||||
|
||||
|
||||
class BMessage;
|
||||
class Desktop;
|
||||
|
||||
|
||||
class TestServerLoopAdapter : public MessageLooper {
|
||||
public:
|
||||
TestServerLoopAdapter(const char* signature,
|
||||
const char* looperName, port_id port,
|
||||
bool initGui, status_t* outError);
|
||||
virtual ~TestServerLoopAdapter();
|
||||
|
||||
// MessageLooper interface
|
||||
virtual port_id MessagePort() const { return fMessagePort; }
|
||||
virtual bool Run();
|
||||
|
||||
// BApplication interface
|
||||
virtual void MessageReceived(BMessage* message) = 0;
|
||||
virtual bool QuitRequested() { return true; }
|
||||
|
||||
private:
|
||||
// MessageLooper interface
|
||||
virtual void _DispatchMessage(int32 code,
|
||||
BPrivate::LinkReceiver &link);
|
||||
|
||||
virtual Desktop* _FindDesktop(uid_t userID,
|
||||
const char* targetScreen) = 0;
|
||||
port_id _CreatePort();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
port_id fMessagePort;
|
||||
};
|
||||
|
||||
|
||||
#endif // TEST_SERVER_LOOP_ADAPTER_H
|
||||
+48
-199
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014, Haiku, Inc.
|
||||
* Copyright (c) 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
@@ -9,6 +9,7 @@
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#include "View.h"
|
||||
|
||||
@@ -19,6 +20,7 @@
|
||||
#include "Desktop.h"
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "Layer.h"
|
||||
#include "Overlay.h"
|
||||
#include "ServerApp.h"
|
||||
#include "ServerBitmap.h"
|
||||
@@ -27,6 +29,7 @@
|
||||
#include "ServerWindow.h"
|
||||
#include "Window.h"
|
||||
|
||||
#include "BitmapHWInterface.h"
|
||||
#include "drawing_support.h"
|
||||
|
||||
#include <List.h>
|
||||
@@ -165,7 +168,8 @@ View::ConvertToVisibleInTopView(IntRect* bounds) const
|
||||
{
|
||||
*bounds = *bounds & Bounds();
|
||||
// NOTE: this step is necessary even if we don't have a parent!
|
||||
ConvertToParent(bounds);
|
||||
bounds->OffsetBy(fFrame.left - fScrollingOffset.x,
|
||||
fFrame.top - fScrollingOffset.y);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertToVisibleInTopView(bounds);
|
||||
@@ -440,7 +444,7 @@ View::ViewAt(const BPoint& where)
|
||||
|
||||
IntRect frame = Frame();
|
||||
if (Parent() != NULL)
|
||||
Parent()->ConvertToScreen(&frame);
|
||||
Parent()->LocalToScreenTransform().Apply(&frame);
|
||||
|
||||
if (!frame.Contains(where))
|
||||
return NULL;
|
||||
@@ -524,7 +528,7 @@ View::_UpdateOverlayView() const
|
||||
return;
|
||||
|
||||
IntRect destination = fBitmapDestination;
|
||||
ConvertToScreen(&destination);
|
||||
LocalToScreenTransform().Apply(&destination);
|
||||
|
||||
overlay->Configure(fBitmapSource, destination);
|
||||
}
|
||||
@@ -556,201 +560,34 @@ View::UpdateOverlay()
|
||||
|
||||
|
||||
void
|
||||
View::ConvertToParent(BPoint* point) const
|
||||
View::_LocalToScreenTransform(SimpleTransform& transform) const
|
||||
{
|
||||
// remove scrolling offset and convert to parent coordinate space
|
||||
point->x += fFrame.left - fScrollingOffset.x;
|
||||
point->y += fFrame.top - fScrollingOffset.y;
|
||||
const View* view = this;
|
||||
int32 offsetX = 0;
|
||||
int32 offsetY = 0;
|
||||
do {
|
||||
offsetX += view->fFrame.left - view->fScrollingOffset.x;
|
||||
offsetY += view->fFrame.top - view->fScrollingOffset.y;
|
||||
view = view->fParent;
|
||||
} while (view != NULL);
|
||||
|
||||
transform.AddOffset(offsetX, offsetY);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::ConvertToParent(IntPoint* point) const
|
||||
View::_ScreenToLocalTransform(SimpleTransform& transform) const
|
||||
{
|
||||
// remove scrolling offset and convert to parent coordinate space
|
||||
point->x += fFrame.left - fScrollingOffset.x;
|
||||
point->y += fFrame.top - fScrollingOffset.y;
|
||||
}
|
||||
const View* view = this;
|
||||
int32 offsetX = 0;
|
||||
int32 offsetY = 0;
|
||||
do {
|
||||
offsetX += view->fScrollingOffset.x - view->fFrame.left;
|
||||
offsetY += view->fScrollingOffset.y - view->fFrame.top;
|
||||
view = view->fParent;
|
||||
} while (view != NULL);
|
||||
|
||||
|
||||
void
|
||||
View::ConvertToParent(BRect* rect) const
|
||||
{
|
||||
// remove scrolling offset and convert to parent coordinate space
|
||||
rect->OffsetBy(fFrame.left - fScrollingOffset.x,
|
||||
fFrame.top - fScrollingOffset.y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::ConvertToParent(IntRect* rect) const
|
||||
{
|
||||
// remove scrolling offset and convert to parent coordinate space
|
||||
rect->OffsetBy(fFrame.left - fScrollingOffset.x,
|
||||
fFrame.top - fScrollingOffset.y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::ConvertToParent(BRegion* region) const
|
||||
{
|
||||
// remove scrolling offset and convert to parent coordinate space
|
||||
region->OffsetBy(fFrame.left - fScrollingOffset.x,
|
||||
fFrame.top - fScrollingOffset.y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::ConvertFromParent(BPoint* point) const
|
||||
{
|
||||
// convert from parent coordinate space amd add scrolling offset
|
||||
point->x += fScrollingOffset.x - fFrame.left;
|
||||
point->y += fScrollingOffset.y - fFrame.top;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::ConvertFromParent(IntPoint* point) const
|
||||
{
|
||||
// convert from parent coordinate space amd add scrolling offset
|
||||
point->x += fScrollingOffset.x - fFrame.left;
|
||||
point->y += fScrollingOffset.y - fFrame.top;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::ConvertFromParent(BRect* rect) const
|
||||
{
|
||||
// convert from parent coordinate space amd add scrolling offset
|
||||
rect->OffsetBy(fScrollingOffset.x - fFrame.left,
|
||||
fScrollingOffset.y - fFrame.top);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::ConvertFromParent(IntRect* rect) const
|
||||
{
|
||||
// convert from parent coordinate space amd add scrolling offset
|
||||
rect->OffsetBy(fScrollingOffset.x - fFrame.left,
|
||||
fScrollingOffset.y - fFrame.top);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::ConvertFromParent(BRegion* region) const
|
||||
{
|
||||
// convert from parent coordinate space amd add scrolling offset
|
||||
region->OffsetBy(fScrollingOffset.x - fFrame.left,
|
||||
fScrollingOffset.y - fFrame.top);
|
||||
}
|
||||
|
||||
//! converts a point from local to screen coordinate system
|
||||
void
|
||||
View::ConvertToScreen(BPoint* pt) const
|
||||
{
|
||||
ConvertToParent(pt);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertToScreen(pt);
|
||||
}
|
||||
|
||||
|
||||
//! converts a point from local to screen coordinate system
|
||||
void
|
||||
View::ConvertToScreen(IntPoint* pt) const
|
||||
{
|
||||
ConvertToParent(pt);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertToScreen(pt);
|
||||
}
|
||||
|
||||
|
||||
//! converts a rect from local to screen coordinate system
|
||||
void
|
||||
View::ConvertToScreen(BRect* rect) const
|
||||
{
|
||||
BPoint offset(0.0, 0.0);
|
||||
ConvertToScreen(&offset);
|
||||
|
||||
rect->OffsetBy(offset);
|
||||
}
|
||||
|
||||
|
||||
//! converts a rect from local to screen coordinate system
|
||||
void
|
||||
View::ConvertToScreen(IntRect* rect) const
|
||||
{
|
||||
BPoint offset(0.0, 0.0);
|
||||
ConvertToScreen(&offset);
|
||||
|
||||
rect->OffsetBy(offset);
|
||||
}
|
||||
|
||||
|
||||
//! converts a region from local to screen coordinate system
|
||||
void
|
||||
View::ConvertToScreen(BRegion* region) const
|
||||
{
|
||||
BPoint offset(0.0, 0.0);
|
||||
ConvertToScreen(&offset);
|
||||
|
||||
region->OffsetBy((int)offset.x, (int)offset.y);
|
||||
}
|
||||
|
||||
|
||||
//! converts a point from screen to local coordinate system
|
||||
void
|
||||
View::ConvertFromScreen(BPoint* pt) const
|
||||
{
|
||||
ConvertFromParent(pt);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertFromScreen(pt);
|
||||
}
|
||||
|
||||
|
||||
//! converts a point from screen to local coordinate system
|
||||
void
|
||||
View::ConvertFromScreen(IntPoint* pt) const
|
||||
{
|
||||
ConvertFromParent(pt);
|
||||
|
||||
if (fParent)
|
||||
fParent->ConvertFromScreen(pt);
|
||||
}
|
||||
|
||||
|
||||
//! converts a rect from screen to local coordinate system
|
||||
void
|
||||
View::ConvertFromScreen(BRect* rect) const
|
||||
{
|
||||
BPoint offset(0.0, 0.0);
|
||||
ConvertFromScreen(&offset);
|
||||
|
||||
rect->OffsetBy(offset.x, offset.y);
|
||||
}
|
||||
|
||||
|
||||
//! converts a rect from screen to local coordinate system
|
||||
void
|
||||
View::ConvertFromScreen(IntRect* rect) const
|
||||
{
|
||||
BPoint offset(0.0, 0.0);
|
||||
ConvertFromScreen(&offset);
|
||||
|
||||
rect->OffsetBy((int)offset.x, (int)offset.y);
|
||||
}
|
||||
|
||||
|
||||
//! converts a region from screen to local coordinate system
|
||||
void
|
||||
View::ConvertFromScreen(BRegion* region) const
|
||||
{
|
||||
BPoint offset(0.0, 0.0);
|
||||
ConvertFromScreen(&offset);
|
||||
|
||||
region->OffsetBy((int)offset.x, (int)offset.y);
|
||||
transform.AddOffset(offsetX, offsetY);
|
||||
}
|
||||
|
||||
|
||||
@@ -775,7 +612,7 @@ View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
|
||||
// local clipping to see which parts need invalidation
|
||||
IntRect oldVisibleBounds(newVisibleBounds);
|
||||
oldVisibleBounds.OffsetBy(-x, -y);
|
||||
ConvertToScreen(&oldVisibleBounds);
|
||||
LocalToScreenTransform().Apply(&oldVisibleBounds);
|
||||
|
||||
ConvertToVisibleInTopView(&newVisibleBounds);
|
||||
|
||||
@@ -788,7 +625,7 @@ View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
|
||||
IntRect oldVisibleBounds(Bounds());
|
||||
IntRect newVisibleBounds(oldVisibleBounds);
|
||||
oldVisibleBounds.OffsetBy(-x, -y);
|
||||
ConvertToScreen(&oldVisibleBounds);
|
||||
LocalToScreenTransform().Apply(&oldVisibleBounds);
|
||||
|
||||
// NOTE: using ConvertToVisibleInTopView()
|
||||
// instead of ConvertToScreen()! see below
|
||||
@@ -875,7 +712,7 @@ View::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
|
||||
}
|
||||
}
|
||||
|
||||
ConvertToScreen(dirty);
|
||||
LocalToScreenTransform().Apply(dirty);
|
||||
dirtyRegion->Include(dirty);
|
||||
}
|
||||
fWindow->RecycleRegion(dirty);
|
||||
@@ -1138,6 +975,18 @@ View::SetPicture(ServerPicture* picture)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::BlendAllLayers()
|
||||
{
|
||||
if (fPicture == NULL)
|
||||
return;
|
||||
Layer* layer = dynamic_cast<Layer*>(fPicture);
|
||||
if (layer == NULL)
|
||||
return;
|
||||
BlendLayer(layer);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
BRegion* windowContentClipping, bool deep)
|
||||
@@ -1171,7 +1020,7 @@ View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
// draw view bitmap
|
||||
// TODO: support other options!
|
||||
BRect rect = fBitmapDestination;
|
||||
ConvertToScreenForDrawing(&rect);
|
||||
PenToScreenTransform().Apply(&rect);
|
||||
|
||||
align_rect_to_pixels(&rect);
|
||||
|
||||
@@ -1406,7 +1255,7 @@ View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region,
|
||||
// This check will prevent descending the view hierarchy
|
||||
// any further than necessary
|
||||
IntRect screenBounds(Bounds());
|
||||
ConvertToScreen(&screenBounds);
|
||||
LocalToScreenTransform().Apply(&screenBounds);
|
||||
if (!region.Intersects((clipping_rect)screenBounds))
|
||||
return;
|
||||
|
||||
@@ -1537,7 +1386,7 @@ View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const
|
||||
if (fScreenAndUserClipping == NULL)
|
||||
return fScreenClipping;
|
||||
|
||||
ConvertToScreen(fScreenAndUserClipping);
|
||||
LocalToScreenTransform().Apply(fScreenAndUserClipping);
|
||||
fScreenAndUserClipping->IntersectWith(
|
||||
&_ScreenClipping(windowContentClipping, force));
|
||||
return *fScreenAndUserClipping;
|
||||
@@ -1578,7 +1427,7 @@ View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
|
||||
{
|
||||
if (!fScreenClippingValid || force) {
|
||||
fScreenClipping = fLocalClipping;
|
||||
ConvertToScreen(&fScreenClipping);
|
||||
LocalToScreenTransform().Apply(&fScreenClipping);
|
||||
|
||||
// see if parts of our bounds are hidden underneath
|
||||
// the parent, the local clipping does not account for this
|
||||
|
||||
+12
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014, Haiku, Inc.
|
||||
* Copyright (c) 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
@@ -9,12 +9,13 @@
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef VIEW_H
|
||||
#define VIEW_H
|
||||
|
||||
|
||||
#include "DrawingContext.h"
|
||||
#include "Canvas.h"
|
||||
#include "IntRect.h"
|
||||
|
||||
#include <GraphicsDefs.h>
|
||||
@@ -37,7 +38,7 @@ class ServerCursor;
|
||||
class ServerPicture;
|
||||
class BGradient;
|
||||
|
||||
class View: public DrawingContext {
|
||||
class View: public Canvas {
|
||||
public:
|
||||
View(IntRect frame, IntPoint scrollingOffset,
|
||||
const char* name, int32 token,
|
||||
@@ -111,31 +112,7 @@ public:
|
||||
|
||||
View* ViewAt(const BPoint& where);
|
||||
|
||||
// coordinate conversion
|
||||
void ConvertToParent(BPoint* point) const;
|
||||
void ConvertToParent(IntPoint* point) const;
|
||||
void ConvertToParent(BRect* rect) const;
|
||||
void ConvertToParent(IntRect* rect) const;
|
||||
void ConvertToParent(BRegion* region) const;
|
||||
|
||||
void ConvertFromParent(BPoint* point) const;
|
||||
void ConvertFromParent(IntPoint* point) const;
|
||||
void ConvertFromParent(BRect* rect) const;
|
||||
void ConvertFromParent(IntRect* rect) const;
|
||||
void ConvertFromParent(BRegion* region) const;
|
||||
|
||||
void ConvertToScreen(BPoint* point) const;
|
||||
void ConvertToScreen(IntPoint* point) const;
|
||||
void ConvertToScreen(BRect* rect) const;
|
||||
void ConvertToScreen(IntRect* rect) const;
|
||||
void ConvertToScreen(BRegion* region) const;
|
||||
|
||||
void ConvertFromScreen(BPoint* point) const;
|
||||
void ConvertFromScreen(IntPoint* point) const;
|
||||
void ConvertFromScreen(BRect* rect) const;
|
||||
void ConvertFromScreen(IntRect* rect) const;
|
||||
void ConvertFromScreen(BRegion* region) const;
|
||||
|
||||
public:
|
||||
void MoveBy(int32 dx, int32 dy,
|
||||
BRegion* dirtyRegion);
|
||||
|
||||
@@ -180,6 +157,8 @@ public:
|
||||
ServerPicture* Picture() const
|
||||
{ return fPicture; }
|
||||
|
||||
void BlendAllLayers();
|
||||
|
||||
// for background clearing
|
||||
virtual void Draw(DrawingEngine* drawingEngine,
|
||||
BRegion* effectiveClipping,
|
||||
@@ -235,6 +214,11 @@ public:
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual void _LocalToScreenTransform(
|
||||
SimpleTransform& transform) const;
|
||||
virtual void _ScreenToLocalTransform(
|
||||
SimpleTransform& transform) const;
|
||||
|
||||
BRegion& _ScreenClipping(BRegion* windowContentClipping,
|
||||
bool force = false) const;
|
||||
void _MoveScreenClipping(int32 x, int32 y,
|
||||
|
||||
@@ -817,7 +817,7 @@ Window::InvalidateView(View* view, BRegion& viewRegion)
|
||||
if (!fContentRegionValid)
|
||||
_UpdateContentRegion();
|
||||
|
||||
view->ConvertToScreen(&viewRegion);
|
||||
view->LocalToScreenTransform().Apply(&viewRegion);
|
||||
viewRegion.IntersectWith(&VisibleContentRegion());
|
||||
if (viewRegion.CountRects() > 0) {
|
||||
viewRegion.IntersectWith(
|
||||
|
||||
@@ -90,7 +90,7 @@ WorkspacesView::_WorkspaceAt(int32 i)
|
||||
_GetGrid(columns, rows);
|
||||
|
||||
BRect frame = Bounds();
|
||||
ConvertToScreen(&frame);
|
||||
LocalToScreenTransform().Apply(&frame);
|
||||
|
||||
int32 width = frame.IntegerWidth() / columns;
|
||||
int32 height = frame.IntegerHeight() / rows;
|
||||
@@ -356,7 +356,7 @@ void
|
||||
WorkspacesView::_Invalidate() const
|
||||
{
|
||||
BRect frame = Bounds();
|
||||
ConvertToScreen(&frame);
|
||||
LocalToScreenTransform().Apply(&frame);
|
||||
|
||||
BRegion region(frame);
|
||||
Window()->MarkContentDirty(region);
|
||||
@@ -385,7 +385,7 @@ WorkspacesView::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
drawingEngine->ConstrainClippingRegion(&gridRegion);
|
||||
|
||||
BRect frame = Bounds();
|
||||
ConvertToScreen(&frame);
|
||||
LocalToScreenTransform().Apply(&frame);
|
||||
|
||||
// horizontal lines
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014, Haiku, Inc.
|
||||
* Copyright 2014-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
|
||||
@@ -12,168 +13,75 @@
|
||||
|
||||
#include "BitmapHWInterface.h"
|
||||
#include "BitmapManager.h"
|
||||
#include "DrawingContext.h"
|
||||
#include "Canvas.h"
|
||||
#include "DrawingEngine.h"
|
||||
#include "PictureBoundingBoxPlayer.h"
|
||||
#include "ServerBitmap.h"
|
||||
#include "ServerPicture.h"
|
||||
#include "Shape.h"
|
||||
|
||||
|
||||
AlphaMask::AlphaMask(ServerPicture* picture, bool inverse, BPoint origin,
|
||||
const DrawState& drawState)
|
||||
// #pragma mark - AlphaMask
|
||||
|
||||
|
||||
AlphaMask::AlphaMask(AlphaMask* previousMask, bool inverse)
|
||||
:
|
||||
fPreviousMask(NULL),
|
||||
|
||||
fPicture(picture),
|
||||
fPreviousMask(previousMask),
|
||||
fBounds(),
|
||||
fViewOrigin(),
|
||||
fInverse(inverse),
|
||||
fOrigin(origin),
|
||||
fDrawState(drawState),
|
||||
|
||||
fViewBounds(),
|
||||
fViewOffset(),
|
||||
|
||||
fCachedBitmap(NULL),
|
||||
fCachedBounds(),
|
||||
fCachedOffset(),
|
||||
|
||||
fBackgroundOpacity(0),
|
||||
fBits(NULL),
|
||||
fBuffer(),
|
||||
fCachedMask(),
|
||||
fScanline(fCachedMask)
|
||||
fMask(),
|
||||
fScanline(fMask)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AlphaMask::AlphaMask(uint8 backgroundOpacity)
|
||||
:
|
||||
fPreviousMask(),
|
||||
fBounds(),
|
||||
fViewOrigin(),
|
||||
fInverse(false),
|
||||
fBackgroundOpacity(backgroundOpacity),
|
||||
fBits(NULL),
|
||||
fBuffer(),
|
||||
fMask(),
|
||||
fScanline(fMask)
|
||||
{
|
||||
fPicture->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
AlphaMask::~AlphaMask()
|
||||
{
|
||||
fPicture->ReleaseReference();
|
||||
delete[] fCachedBitmap;
|
||||
SetPrevious(NULL);
|
||||
delete[] fBits;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaMask::Update(BRect bounds, BPoint offset)
|
||||
IntPoint
|
||||
AlphaMask::SetViewOrigin(IntPoint viewOrigin)
|
||||
{
|
||||
fViewBounds = bounds;
|
||||
fViewOffset = offset;
|
||||
|
||||
if (viewOrigin == fViewOrigin)
|
||||
return fViewOrigin;
|
||||
|
||||
IntPoint oldOrigin = fViewOrigin;
|
||||
fViewOrigin = viewOrigin;
|
||||
|
||||
_AttachMaskToBuffer();
|
||||
|
||||
if (fPreviousMask != NULL)
|
||||
fPreviousMask->Update(bounds, offset);
|
||||
}
|
||||
fPreviousMask->SetViewOrigin(viewOrigin);
|
||||
|
||||
|
||||
void
|
||||
AlphaMask::SetPrevious(AlphaMask* mask)
|
||||
{
|
||||
// Since multiple DrawStates can point to the same AlphaMask,
|
||||
// don't accept ourself as the "previous" mask on the state stack.
|
||||
if (mask == this || mask == fPreviousMask)
|
||||
return;
|
||||
|
||||
if (mask != NULL)
|
||||
mask->AcquireReference();
|
||||
if (fPreviousMask != NULL)
|
||||
fPreviousMask->ReleaseReference();
|
||||
fPreviousMask = mask;
|
||||
}
|
||||
|
||||
|
||||
scanline_unpacked_masked_type*
|
||||
AlphaMask::Generate()
|
||||
{
|
||||
if (fPicture == NULL || !fViewBounds.IsValid())
|
||||
return NULL;
|
||||
|
||||
// See if a cached bitmap can be used. Don't use it when the view offset
|
||||
// or bounds have changed.
|
||||
if (fCachedBitmap != NULL
|
||||
&& fViewBounds == fCachedBounds && fViewOffset == fCachedOffset) {
|
||||
return &fScanline;
|
||||
}
|
||||
|
||||
uint32 width = fViewBounds.IntegerWidth() + 1;
|
||||
uint32 height = fViewBounds.IntegerHeight() + 1;
|
||||
|
||||
if (fViewBounds != fCachedBounds || fCachedBitmap == NULL) {
|
||||
delete[] fCachedBitmap;
|
||||
fCachedBitmap = new(std::nothrow) uint8[width * height];
|
||||
}
|
||||
|
||||
// If rendering the picture fails, we will draw without any clipping.
|
||||
ServerBitmap* bitmap = _RenderPicture();
|
||||
if (bitmap == NULL || fCachedBitmap == NULL) {
|
||||
fBuffer.attach(NULL, 0, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8* bits = bitmap->Bits();
|
||||
uint32 bytesPerRow = bitmap->BytesPerRow();
|
||||
uint8* row = bits;
|
||||
uint8* pixel = fCachedBitmap;
|
||||
|
||||
// Let any previous masks also regenerate themselves. Updating the cached
|
||||
// mask bitmap is only necessary after the view size changed or the
|
||||
// scrolling offset, which definitely affects any masks of lower states
|
||||
// as well, so it works recursively until the bottom mask is regenerated.
|
||||
bool transferBitmap = true;
|
||||
if (fPreviousMask != NULL) {
|
||||
fPreviousMask->Generate();
|
||||
if (fPreviousMask->fCachedBitmap != NULL) {
|
||||
uint8* previousBits = fPreviousMask->fCachedBitmap;
|
||||
for (uint32 y = 0; y < height; y++) {
|
||||
for (uint32 x = 0; x < width; x++) {
|
||||
if (previousBits[0] != 0) {
|
||||
if (fInverse)
|
||||
pixel[0] = 255 - row[3];
|
||||
else
|
||||
pixel[0] = row[3];
|
||||
pixel[0] = pixel[0] * previousBits[0] / 255;
|
||||
} else
|
||||
pixel[0] = 0;
|
||||
previousBits++;
|
||||
pixel++;
|
||||
row += 4;
|
||||
}
|
||||
bits += bytesPerRow;
|
||||
row = bits;
|
||||
}
|
||||
transferBitmap = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (transferBitmap) {
|
||||
for (uint32 y = 0; y < height; y++) {
|
||||
for (uint32 x = 0; x < width; x++) {
|
||||
if (fInverse)
|
||||
pixel[0] = 255 - row[3];
|
||||
else
|
||||
pixel[0] = row[3];
|
||||
pixel++;
|
||||
row += 4;
|
||||
}
|
||||
bits += bytesPerRow;
|
||||
row = bits;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap->ReleaseReference();
|
||||
|
||||
fCachedBounds = fViewBounds;
|
||||
fCachedOffset = fViewOffset;
|
||||
|
||||
fBuffer.attach(fCachedBitmap, width, height, width);
|
||||
|
||||
fCachedMask.attach(fBuffer, fViewOffset.x + fOrigin.x,
|
||||
fViewOffset.y + fOrigin.y, fInverse ? 255 : 0);
|
||||
|
||||
return &fScanline;
|
||||
return oldOrigin;
|
||||
}
|
||||
|
||||
|
||||
ServerBitmap*
|
||||
AlphaMask::_RenderPicture() const
|
||||
AlphaMask::_CreateTemporaryBitmap(BRect bounds) const
|
||||
{
|
||||
UtilityBitmap* bitmap = new(std::nothrow) UtilityBitmap(fViewBounds,
|
||||
UtilityBitmap* bitmap = new(std::nothrow) UtilityBitmap(bounds,
|
||||
B_RGBA32, 0);
|
||||
if (bitmap == NULL)
|
||||
return NULL;
|
||||
@@ -183,33 +91,272 @@ AlphaMask::_RenderPicture() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Clear the bitmap with the transparent color
|
||||
memset(bitmap->Bits(), 0, bitmap->BitsLength());
|
||||
memset(bitmap->Bits(), fBackgroundOpacity, bitmap->BitsLength());
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaMask::_Generate()
|
||||
{
|
||||
ServerBitmap* const bitmap = _RenderSource();
|
||||
BReference<ServerBitmap> bitmapRef(bitmap, true);
|
||||
if (bitmap == NULL) {
|
||||
_SetNoClipping();
|
||||
return;
|
||||
}
|
||||
|
||||
const int32 width = fBounds.IntegerWidth() + 1;
|
||||
const int32 height = fBounds.IntegerHeight() + 1;
|
||||
|
||||
delete[] fBits;
|
||||
fBits = new(std::nothrow) uint8[width * height];
|
||||
|
||||
uint8* source = bitmap->Bits();
|
||||
uint8* destination = fBits;
|
||||
uint32 numPixels = width * height;
|
||||
|
||||
if (fPreviousMask != NULL) {
|
||||
int32 previousStartX = fBounds.left - fPreviousMask->fBounds.left;
|
||||
int32 previousStartY = fBounds.top - fPreviousMask->fBounds.top;
|
||||
if (previousStartX < 0)
|
||||
previousStartX = 0;
|
||||
if (previousStartY < 0)
|
||||
previousStartY = 0;
|
||||
|
||||
for (int32 y = previousStartY; y < previousStartY + height; y++) {
|
||||
uint8* previousRow = fPreviousMask->fBuffer.row_ptr(y);
|
||||
for (int32 x = previousStartX; x < previousStartX + width; x++) {
|
||||
uint8 sourceAlpha = fInverse ? 255 - source[3] : source[3];
|
||||
*destination = sourceAlpha * previousRow[x] / 255;
|
||||
destination++;
|
||||
source += 4;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (numPixels--) {
|
||||
*destination = fInverse ? 255 - source[3] : source[3];
|
||||
destination++;
|
||||
source += 4;
|
||||
}
|
||||
}
|
||||
|
||||
fBuffer.attach(fBits, width, height, width);
|
||||
_AttachMaskToBuffer();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaMask::_SetNoClipping()
|
||||
{
|
||||
fBuffer.attach(NULL, 0, 0, 0);
|
||||
_AttachMaskToBuffer();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlphaMask::_AttachMaskToBuffer()
|
||||
{
|
||||
uint8 outsideOpacity = fInverse ? 255 - fBackgroundOpacity
|
||||
: fBackgroundOpacity;
|
||||
|
||||
AlphaMask* previousMask = fPreviousMask;
|
||||
while (previousMask != NULL && outsideOpacity != 0) {
|
||||
uint8 previousOutsideOpacity = previousMask->fInverse
|
||||
? 255 - previousMask->fBackgroundOpacity
|
||||
: previousMask->fBackgroundOpacity;
|
||||
outsideOpacity = outsideOpacity * previousOutsideOpacity / 255;
|
||||
previousMask = previousMask->fPreviousMask;
|
||||
}
|
||||
|
||||
const IntPoint maskOffset = _Offset();
|
||||
const int32 offsetX = fBounds.left + maskOffset.x + fViewOrigin.x;
|
||||
const int32 offsetY = fBounds.top + maskOffset.y + fViewOrigin.y;
|
||||
|
||||
fMask.attach(fBuffer, offsetX, offsetY, outsideOpacity);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - UniformAlphaMask
|
||||
|
||||
|
||||
UniformAlphaMask::UniformAlphaMask(uint8 opacity)
|
||||
:
|
||||
AlphaMask(opacity)
|
||||
{
|
||||
fBounds.Set(0, 0, 0, 0);
|
||||
_SetNoClipping();
|
||||
}
|
||||
|
||||
|
||||
ServerBitmap*
|
||||
UniformAlphaMask::_RenderSource()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
IntPoint
|
||||
UniformAlphaMask::_Offset()
|
||||
{
|
||||
return IntPoint(0, 0);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - VectorAlphaMask
|
||||
|
||||
|
||||
template<class VectorMaskType>
|
||||
VectorAlphaMask<VectorMaskType>::VectorAlphaMask(AlphaMask* previousMask,
|
||||
BPoint where, bool inverse)
|
||||
:
|
||||
AlphaMask(previousMask, inverse),
|
||||
fWhere(where)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<class VectorMaskType>
|
||||
ServerBitmap*
|
||||
VectorAlphaMask<VectorMaskType>::_RenderSource()
|
||||
{
|
||||
fBounds = static_cast<VectorMaskType*>(this)->DetermineBoundingBox();
|
||||
if (fPreviousMask != NULL)
|
||||
fBounds = fBounds & fPreviousMask->fBounds;
|
||||
if (!fBounds.IsValid())
|
||||
return NULL;
|
||||
|
||||
ServerBitmap* bitmap = _CreateTemporaryBitmap(fBounds);
|
||||
if (bitmap == NULL)
|
||||
return NULL;
|
||||
|
||||
// Render the picture to the bitmap
|
||||
BitmapHWInterface interface(bitmap);
|
||||
DrawingEngine* engine = interface.CreateDrawingEngine();
|
||||
if (engine == NULL) {
|
||||
delete bitmap;
|
||||
bitmap->ReleaseReference();
|
||||
return NULL;
|
||||
}
|
||||
engine->SetRendererOffset(fBounds.left, fBounds.top);
|
||||
|
||||
OffscreenContext context(engine, fDrawState);
|
||||
context.PushState();
|
||||
OffscreenCanvas canvas(engine,
|
||||
static_cast<VectorMaskType*>(this)->GetDrawState());
|
||||
|
||||
DrawState* const drawState = canvas.CurrentState();
|
||||
drawState->SetDrawingMode(B_OP_ALPHA);
|
||||
drawState->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
|
||||
drawState->SetDrawingModeLocked(true);
|
||||
canvas.PushState();
|
||||
|
||||
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(fViewBounds);
|
||||
clipping.Set((clipping_rect)fBounds);
|
||||
engine->ConstrainClippingRegion(&clipping);
|
||||
fPicture->Play(&context);
|
||||
static_cast<VectorMaskType*>(this)->DrawVectors(&canvas);
|
||||
engine->UnlockParallelAccess();
|
||||
}
|
||||
|
||||
context.PopState();
|
||||
delete engine;
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
template<class VectorMaskType>
|
||||
IntPoint
|
||||
VectorAlphaMask<VectorMaskType>::_Offset()
|
||||
{
|
||||
return fWhere;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// #pragma mark - PictureAlphaMask
|
||||
|
||||
|
||||
PictureAlphaMask::PictureAlphaMask(AlphaMask* previousMask,
|
||||
ServerPicture* picture, const DrawState& drawState, BPoint where,
|
||||
bool inverse)
|
||||
:
|
||||
VectorAlphaMask<PictureAlphaMask>(previousMask, where, inverse),
|
||||
fPicture(picture),
|
||||
fDrawState(new DrawState(drawState))
|
||||
{
|
||||
_Generate();
|
||||
}
|
||||
|
||||
|
||||
PictureAlphaMask::~PictureAlphaMask()
|
||||
{
|
||||
delete fDrawState;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PictureAlphaMask::DrawVectors(Canvas* canvas)
|
||||
{
|
||||
fPicture->Play(canvas);
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
PictureAlphaMask::DetermineBoundingBox() const
|
||||
{
|
||||
BRect boundingBox;
|
||||
PictureBoundingBoxPlayer::Play(fPicture, fDrawState, &boundingBox);
|
||||
|
||||
if (!boundingBox.IsValid())
|
||||
return boundingBox;
|
||||
|
||||
// Round up and add an additional 2 pixels on the bottom/right to
|
||||
// compensate for the various types of rounding used in Painter.
|
||||
boundingBox.left = floorf(boundingBox.left);
|
||||
boundingBox.right = ceilf(boundingBox.right) + 2;
|
||||
boundingBox.top = floorf(boundingBox.top);
|
||||
boundingBox.bottom = ceilf(boundingBox.bottom) + 2;
|
||||
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
|
||||
const DrawState&
|
||||
PictureAlphaMask::GetDrawState() const
|
||||
{
|
||||
return *fDrawState;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ShapeAlphaMask
|
||||
|
||||
|
||||
ShapeAlphaMask::ShapeAlphaMask(AlphaMask* previousMask, BPoint where,
|
||||
bool inverse)
|
||||
:
|
||||
VectorAlphaMask<ShapeAlphaMask>(previousMask, where, inverse),
|
||||
fDrawState()
|
||||
{
|
||||
_Generate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ShapeAlphaMask::DrawVectors(Canvas* canvas)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
ShapeAlphaMask::DetermineBoundingBox() const
|
||||
{
|
||||
// TODO
|
||||
return BRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
const DrawState&
|
||||
ShapeAlphaMask::GetDrawState() const
|
||||
{
|
||||
return fDrawState;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014, Haiku, Inc.
|
||||
* Copyright 2014-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -13,47 +13,123 @@
|
||||
|
||||
#include "DrawState.h"
|
||||
#include "drawing/Painter/defines.h"
|
||||
#include "IntRect.h"
|
||||
|
||||
|
||||
class BShape;
|
||||
class ServerBitmap;
|
||||
class ServerPicture;
|
||||
|
||||
|
||||
// #pragma mark - AlphaMask
|
||||
|
||||
|
||||
class AlphaMask : public BReferenceable {
|
||||
public:
|
||||
AlphaMask(ServerPicture* mask, bool inverse,
|
||||
BPoint origin, const DrawState& drawState);
|
||||
~AlphaMask();
|
||||
AlphaMask(AlphaMask* previousMask,
|
||||
bool inverse);
|
||||
AlphaMask(uint8 backgroundOpacity);
|
||||
virtual ~AlphaMask();
|
||||
|
||||
void Update(BRect bounds, BPoint offset);
|
||||
IntPoint SetViewOrigin(IntPoint viewOrigin);
|
||||
|
||||
void SetPrevious(AlphaMask* mask);
|
||||
scanline_unpacked_masked_type* Scanline()
|
||||
{ return &fScanline; }
|
||||
|
||||
scanline_unpacked_masked_type* Generate();
|
||||
agg::clipped_alpha_mask* Mask()
|
||||
{ return &fMask; }
|
||||
|
||||
protected:
|
||||
ServerBitmap* _CreateTemporaryBitmap(BRect bounds) const;
|
||||
void _Generate();
|
||||
void _SetNoClipping();
|
||||
|
||||
private:
|
||||
ServerBitmap* _RenderPicture() const;
|
||||
virtual ServerBitmap* _RenderSource() = 0;
|
||||
virtual IntPoint _Offset() = 0;
|
||||
|
||||
void _AttachMaskToBuffer();
|
||||
|
||||
public:
|
||||
BReference<AlphaMask> fPreviousMask;
|
||||
IntRect fBounds;
|
||||
|
||||
private:
|
||||
AlphaMask* fPreviousMask;
|
||||
|
||||
ServerPicture* fPicture;
|
||||
IntPoint fViewOrigin;
|
||||
const bool fInverse;
|
||||
BPoint fOrigin;
|
||||
DrawState fDrawState;
|
||||
|
||||
BRect fViewBounds;
|
||||
BPoint fViewOffset;
|
||||
|
||||
uint8* fCachedBitmap;
|
||||
BRect fCachedBounds;
|
||||
BPoint fCachedOffset;
|
||||
uint8 fBackgroundOpacity;
|
||||
|
||||
uint8* fBits;
|
||||
agg::rendering_buffer fBuffer;
|
||||
agg::clipped_alpha_mask fCachedMask;
|
||||
agg::clipped_alpha_mask fMask;
|
||||
scanline_unpacked_masked_type fScanline;
|
||||
};
|
||||
|
||||
|
||||
class UniformAlphaMask : public AlphaMask {
|
||||
public:
|
||||
UniformAlphaMask(uint8 opacity);
|
||||
|
||||
private:
|
||||
virtual ServerBitmap* _RenderSource();
|
||||
virtual IntPoint _Offset();
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - VectorAlphaMask
|
||||
|
||||
|
||||
template<class VectorMaskType>
|
||||
class VectorAlphaMask : public AlphaMask {
|
||||
public:
|
||||
VectorAlphaMask(AlphaMask* previousMask,
|
||||
BPoint where, bool inverse);
|
||||
|
||||
private:
|
||||
virtual ServerBitmap* _RenderSource();
|
||||
virtual IntPoint _Offset();
|
||||
|
||||
protected:
|
||||
BPoint fWhere;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - PictureAlphaMask
|
||||
|
||||
|
||||
class PictureAlphaMask : public VectorAlphaMask<PictureAlphaMask> {
|
||||
public:
|
||||
PictureAlphaMask(AlphaMask* previousMask,
|
||||
ServerPicture* picture,
|
||||
const DrawState& drawState, BPoint where,
|
||||
bool inverse);
|
||||
virtual ~PictureAlphaMask();
|
||||
|
||||
void DrawVectors(Canvas* canvas);
|
||||
BRect DetermineBoundingBox() const;
|
||||
const DrawState& GetDrawState() const;
|
||||
|
||||
private:
|
||||
BReference<ServerPicture> fPicture;
|
||||
DrawState* fDrawState;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - ShapeAlphaMask
|
||||
|
||||
|
||||
class ShapeAlphaMask : public VectorAlphaMask<ShapeAlphaMask> {
|
||||
public:
|
||||
ShapeAlphaMask(AlphaMask* previousMask,
|
||||
BPoint where, bool inverse);
|
||||
|
||||
void DrawVectors(Canvas* canvas);
|
||||
BRect DetermineBoundingBox() const;
|
||||
const DrawState& GetDrawState() const;
|
||||
|
||||
private:
|
||||
DrawState fDrawState;
|
||||
};
|
||||
|
||||
|
||||
#endif // ALPHA_MASK_H
|
||||
|
||||
@@ -694,7 +694,8 @@ DWindowHWInterface::SetMode(const display_mode& mode)
|
||||
// has not been created either, but we need one to display
|
||||
// a real BWindow in the test environment.
|
||||
// be_app->Run() needs to be called in another thread
|
||||
BApplication* app = new BApplication("application/x-vnd.haiku-app-server");
|
||||
BApplication* app = new BApplication(
|
||||
"application/x-vnd.Haiku-test-app_server");
|
||||
app->Unlock();
|
||||
|
||||
thread_id appThread = spawn_thread(run_app_thread, "app thread",
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2001-2009, Haiku, Inc.
|
||||
* Copyright 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
|
||||
@@ -1070,7 +1071,7 @@ DrawingEngine::FillRegion(BRegion& r)
|
||||
doInSoftware = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (doInSoftware
|
||||
&& (fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0
|
||||
&& fPainter->Pattern() == B_SOLID_HIGH
|
||||
@@ -1555,6 +1556,13 @@ DrawingEngine::CopyRect(BRect src, int32 xOffset, int32 yOffset) const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawingEngine::SetRendererOffset(int32 offsetX, int32 offsetY)
|
||||
{
|
||||
fPainter->SetRendererOffset(offsetX, offsetY);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DrawingEngine::_CopyRect(uint8* src, uint32 width, uint32 height,
|
||||
uint32 bytesPerRow, int32 xOffset, int32 yOffset) const
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* Copyright 2001-2009, Haiku, Inc.
|
||||
* Copyright 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Gabe Yoder <gyoder@stny.rr.com>
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef DRAWING_ENGINE_H_
|
||||
#define DRAWING_ENGINE_H_
|
||||
@@ -187,6 +188,8 @@ public:
|
||||
virtual BRect CopyRect(BRect rect, int32 xOffset,
|
||||
int32 yOffset) const;
|
||||
|
||||
void SetRendererOffset(int32 offsetX, int32 offsetY);
|
||||
|
||||
private:
|
||||
void _CopyRect(uint8* bits, uint32 width,
|
||||
uint32 height, uint32 bytesPerRow,
|
||||
|
||||
@@ -12,6 +12,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes
|
||||
UseBuildFeatureHeaders freetype ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) drawing_modes ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) bitmap_painter ] ;
|
||||
|
||||
local PAINTER_ARCH_SOURCES ;
|
||||
if $(TARGET_ARCH) = x86 {
|
||||
@@ -29,6 +30,9 @@ StaticLibrary libpainter.a :
|
||||
# drawing_modes
|
||||
PixelFormat.cpp
|
||||
|
||||
# bitmap_painter
|
||||
BitmapPainter.cpp
|
||||
|
||||
AGGTextRenderer.cpp
|
||||
|
||||
$(PAINTER_ARCH_SOURCES)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
* API to the Anti-Grain Geometry based "Painter" drawing backend. Manages
|
||||
@@ -13,6 +14,7 @@
|
||||
|
||||
#include "AGGTextRenderer.h"
|
||||
#include "FontManager.h"
|
||||
#include "PainterAggInterface.h"
|
||||
#include "PatternHandler.h"
|
||||
#include "ServerFont.h"
|
||||
#include "Transformable.h"
|
||||
@@ -20,7 +22,6 @@
|
||||
#include "defines.h"
|
||||
|
||||
#include <agg_conv_curve.h>
|
||||
#include <agg_path_storage.h>
|
||||
|
||||
#include <AffineTransform.h>
|
||||
#include <Font.h>
|
||||
@@ -42,6 +43,11 @@ class ServerBitmap;
|
||||
class ServerFont;
|
||||
|
||||
|
||||
// Defines for SIMD support.
|
||||
#define APPSERVER_SIMD_MMX (1 << 0)
|
||||
#define APPSERVER_SIMD_SSE (1 << 1)
|
||||
|
||||
|
||||
class Painter {
|
||||
public:
|
||||
Painter();
|
||||
@@ -67,6 +73,8 @@ public:
|
||||
|
||||
inline bool IsIdentityTransform() const
|
||||
{ return fIdentityTransform; }
|
||||
const Transformable& Transform() const
|
||||
{ return fTransform; }
|
||||
|
||||
void SetHighColor(const rgb_color& color);
|
||||
inline rgb_color HighColor() const
|
||||
@@ -243,6 +251,8 @@ public:
|
||||
inline BRect AlignAndClipRect(BRect rect) const;
|
||||
inline BRect AlignRect(BRect rect) const;
|
||||
|
||||
void SetRendererOffset(int32 offsetX,
|
||||
int32 offsetY);
|
||||
|
||||
private:
|
||||
float _Align(float coord, bool round,
|
||||
@@ -270,41 +280,6 @@ private:
|
||||
const BPoint& viewToScreenOffset,
|
||||
float viewScale) const;
|
||||
|
||||
template<typename sourcePixel>
|
||||
void _TransparentMagicToAlpha(sourcePixel *buffer,
|
||||
uint32 width, uint32 height,
|
||||
uint32 sourceBytesPerRow,
|
||||
sourcePixel transparentMagic,
|
||||
BBitmap *output) const;
|
||||
|
||||
void _DrawBitmap(agg::rendering_buffer& srcBuffer,
|
||||
color_space format,
|
||||
BRect actualBitmapRect,
|
||||
BRect bitmapRect, BRect viewRect,
|
||||
uint32 bitmapFlags) const;
|
||||
template <class F>
|
||||
void _DrawBitmapNoScale32( F copyRowFunction,
|
||||
uint32 bytesPerSourcePixel,
|
||||
agg::rendering_buffer& srcBuffer,
|
||||
int32 xOffset, int32 yOffset,
|
||||
BRect viewRect) const;
|
||||
void _DrawBitmapNearestNeighborCopy32(
|
||||
agg::rendering_buffer& srcBuffer,
|
||||
double xOffset, double yOffset,
|
||||
double xScale, double yScale,
|
||||
BRect viewRect) const;
|
||||
void _DrawBitmapBilinearCopy32(
|
||||
agg::rendering_buffer& srcBuffer,
|
||||
double xOffset, double yOffset,
|
||||
double xScale, double yScale,
|
||||
BRect viewRect) const;
|
||||
void _DrawBitmapGeneric32(
|
||||
agg::rendering_buffer& srcBuffer,
|
||||
double xOffset, double yOffset,
|
||||
double xScale, double yScale,
|
||||
BRect viewRect,
|
||||
uint32 bitmapFlags) const;
|
||||
|
||||
void _InvertRect32(BRect r) const;
|
||||
void _BlendRect32(const BRect& r,
|
||||
const rgb_color& c) const;
|
||||
@@ -353,33 +328,12 @@ private:
|
||||
int gradientStop = 100) const;
|
||||
|
||||
private:
|
||||
mutable agg::rendering_buffer fBuffer;
|
||||
class BitmapPainter;
|
||||
|
||||
// AGG rendering and rasterization classes
|
||||
pixfmt fPixelFormat;
|
||||
mutable renderer_base fBaseRenderer;
|
||||
friend class BitmapPainter; // needed only for gcc2
|
||||
|
||||
// Regular drawing mode: pixel-aligned, no alpha masking
|
||||
mutable scanline_unpacked_type fUnpackedScanline;
|
||||
mutable scanline_packed_type fPackedScanline;
|
||||
mutable rasterizer_type fRasterizer;
|
||||
mutable renderer_type fRenderer;
|
||||
|
||||
// Fast mode: no antialiasing needed (horizontal/vertical lines, ...)
|
||||
mutable renderer_bin_type fRendererBin;
|
||||
|
||||
// Subpixel mode
|
||||
mutable scanline_packed_subpix_type fSubpixPackedScanline;
|
||||
mutable scanline_unpacked_subpix_type fSubpixUnpackedScanline;
|
||||
mutable rasterizer_subpix_type fSubpixRasterizer;
|
||||
mutable renderer_subpix_type fSubpixRenderer;
|
||||
|
||||
// Alpha-Masked mode: for ClipToPicture
|
||||
// (this uses the standard rasterizer and renderer)
|
||||
mutable scanline_unpacked_masked_type* fMaskedUnpackedScanline;
|
||||
|
||||
mutable agg::path_storage fPath;
|
||||
mutable agg::conv_curve<agg::path_storage> fCurve;
|
||||
private:
|
||||
mutable PainterAggInterface fInternal;
|
||||
|
||||
// for internal coordinate rounding/transformation
|
||||
bool fSubpixelPrecise : 1;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PAINTER_DATA_H
|
||||
#define PAINTER_DATA_H
|
||||
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#include <agg_path_storage.h>
|
||||
|
||||
|
||||
struct PainterAggInterface {
|
||||
PainterAggInterface(PatternHandler& patternHandler)
|
||||
:
|
||||
fBuffer(),
|
||||
fPixelFormat(fBuffer, &patternHandler),
|
||||
fBaseRenderer(fPixelFormat),
|
||||
fUnpackedScanline(),
|
||||
fPackedScanline(),
|
||||
fRasterizer(),
|
||||
fRenderer(fBaseRenderer),
|
||||
fRendererBin(fBaseRenderer),
|
||||
fSubpixPackedScanline(),
|
||||
fSubpixUnpackedScanline(),
|
||||
fSubpixRasterizer(),
|
||||
fSubpixRenderer(fBaseRenderer),
|
||||
fMaskedUnpackedScanline(NULL),
|
||||
fClippedAlphaMask(NULL),
|
||||
fPath(),
|
||||
fCurve(fPath)
|
||||
{
|
||||
}
|
||||
|
||||
agg::rendering_buffer fBuffer;
|
||||
|
||||
// AGG rendering and rasterization classes
|
||||
pixfmt fPixelFormat;
|
||||
renderer_base fBaseRenderer;
|
||||
|
||||
// Regular drawing mode: pixel-aligned, no alpha masking
|
||||
scanline_unpacked_type fUnpackedScanline;
|
||||
scanline_packed_type fPackedScanline;
|
||||
rasterizer_type fRasterizer;
|
||||
renderer_type fRenderer;
|
||||
|
||||
// Fast mode: no antialiasing needed (horizontal/vertical lines, ...)
|
||||
renderer_bin_type fRendererBin;
|
||||
|
||||
// Subpixel mode
|
||||
scanline_packed_subpix_type fSubpixPackedScanline;
|
||||
scanline_unpacked_subpix_type fSubpixUnpackedScanline;
|
||||
rasterizer_subpix_type fSubpixRasterizer;
|
||||
renderer_subpix_type fSubpixRenderer;
|
||||
|
||||
// Alpha-Masked mode: for ClipToPicture
|
||||
// (this uses the standard rasterizer and renderer)
|
||||
scanline_unpacked_masked_type* fMaskedUnpackedScanline;
|
||||
agg::clipped_alpha_mask* fClippedAlphaMask;
|
||||
|
||||
agg::path_storage fPath;
|
||||
agg::conv_curve<agg::path_storage> fCurve;
|
||||
};
|
||||
|
||||
|
||||
#endif // PAINTER_DATA_H
|
||||
@@ -23,7 +23,7 @@ namespace agg
|
||||
public:
|
||||
typedef int8u cover_type;
|
||||
enum cover_scale_e
|
||||
{
|
||||
{
|
||||
cover_shift = 8,
|
||||
cover_none = 0,
|
||||
cover_full = 255
|
||||
@@ -44,46 +44,13 @@ namespace agg
|
||||
|
||||
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));
|
||||
bool has_inside = _set_outside(x, y, covers, count);
|
||||
if (!has_inside)
|
||||
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
|
||||
{
|
||||
@@ -95,6 +62,67 @@ namespace agg
|
||||
while(--count);
|
||||
}
|
||||
|
||||
void get_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
bool has_inside = _set_outside(x, y, covers, count);
|
||||
if (!has_inside)
|
||||
return;
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
memcpy(covers, mask, count);
|
||||
}
|
||||
|
||||
private:
|
||||
bool _set_outside(int& x, int& y, cover_type*& covers,
|
||||
int& count) const
|
||||
{
|
||||
x -= m_xOffset;
|
||||
y -= m_yOffset;
|
||||
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int num_pix = count;
|
||||
cover_type* dst = covers;
|
||||
|
||||
if(y < 0 || y > ymax)
|
||||
{
|
||||
memset(dst, m_outside, num_pix * sizeof(cover_type));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
count += x;
|
||||
if(count <= 0)
|
||||
{
|
||||
memset(dst, m_outside, num_pix * sizeof(cover_type));
|
||||
return false;
|
||||
}
|
||||
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 false;
|
||||
}
|
||||
memset(covers + count, m_outside, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
int m_xOffset;
|
||||
int m_yOffset;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright 2005-2006, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||
@@ -36,7 +37,9 @@ namespace agg
|
||||
m_ren(ren),
|
||||
m_region(NULL),
|
||||
m_curr_cb(0),
|
||||
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
|
||||
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()),
|
||||
m_offset_x(0),
|
||||
m_offset_y(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,11 +52,15 @@ namespace agg
|
||||
unsigned height() const { return m_ren.height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& clip_box() const { return m_ren.clip_box(); }
|
||||
int xmin() const { return m_ren.xmin(); }
|
||||
int ymin() const { return m_ren.ymin(); }
|
||||
int xmax() const { return m_ren.xmax(); }
|
||||
int ymax() const { return m_ren.ymax(); }
|
||||
const rect_i& clip_box() const { return m_bounds; }
|
||||
int xmin() const { return translate_from_base_ren_x(
|
||||
m_ren.xmin()); }
|
||||
int ymin() const { return translate_from_base_ren_y(
|
||||
m_ren.ymin()); }
|
||||
int xmax() const { return translate_from_base_ren_x(
|
||||
m_ren.xmax()); }
|
||||
int ymax() const { return translate_from_base_ren_y(
|
||||
m_ren.ymax()); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const rect_i& bounding_clip_box() const { return m_bounds; }
|
||||
@@ -69,7 +76,12 @@ namespace agg
|
||||
if(m_region && m_region->CountRects() > 0)
|
||||
{
|
||||
clipping_rect cb = m_region->RectAtInt(0);
|
||||
m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom);
|
||||
translate_to_base_ren(cb);
|
||||
m_ren.clip_box_naked(
|
||||
cb.left,
|
||||
cb.top,
|
||||
cb.right,
|
||||
cb.bottom);
|
||||
}
|
||||
else
|
||||
m_ren.clip_box_naked(0, 0, -1, -1);
|
||||
@@ -81,7 +93,12 @@ namespace agg
|
||||
if(m_region && (int)(++m_curr_cb) < m_region->CountRects())
|
||||
{
|
||||
clipping_rect cb = m_region->RectAtInt(m_curr_cb);
|
||||
m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom);
|
||||
translate_to_base_ren(cb);
|
||||
m_ren.clip_box_naked(
|
||||
cb.left,
|
||||
cb.top,
|
||||
cb.right,
|
||||
cb.bottom);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -94,6 +111,7 @@ namespace agg
|
||||
m_region = NULL;
|
||||
m_curr_cb = 0;
|
||||
m_bounds = m_ren.clip_box();
|
||||
translate_from_base_ren(m_bounds);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@@ -117,6 +135,68 @@ namespace agg
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void set_offset(int offset_x, int offset_y)
|
||||
{
|
||||
m_offset_x = offset_x;
|
||||
m_offset_y = offset_y;
|
||||
|
||||
if (m_region == NULL) {
|
||||
m_bounds = m_ren.clip_box();
|
||||
translate_from_base_ren(m_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void translate_to_base_ren_x(int& x)
|
||||
{
|
||||
x -= m_offset_x;
|
||||
}
|
||||
|
||||
void translate_to_base_ren_y(int& y)
|
||||
{
|
||||
y -= m_offset_y;
|
||||
}
|
||||
|
||||
void translate_to_base_ren(int& x, int&y)
|
||||
{
|
||||
x -= m_offset_x;
|
||||
y -= m_offset_y;
|
||||
}
|
||||
|
||||
void translate_to_base_ren(clipping_rect& clip)
|
||||
{
|
||||
clip.left -= m_offset_x;
|
||||
clip.right -= m_offset_x;
|
||||
clip.top -= m_offset_y;
|
||||
clip.bottom -= m_offset_y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int translate_from_base_ren_x(int x) const
|
||||
{
|
||||
return x + m_offset_x;
|
||||
}
|
||||
|
||||
int translate_from_base_ren_y(int y) const
|
||||
{
|
||||
return y + m_offset_y;
|
||||
}
|
||||
|
||||
void translate_from_base_ren(int& x, int& y)
|
||||
{
|
||||
x += m_offset_x;
|
||||
y += m_offset_y;
|
||||
}
|
||||
|
||||
void translate_from_base_ren(rect_i& rect)
|
||||
{
|
||||
rect.x1 += m_offset_x;
|
||||
rect.x2 += m_offset_x;
|
||||
rect.y1 += m_offset_y;
|
||||
rect.y2 += m_offset_y;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(const color_type& c)
|
||||
{
|
||||
@@ -126,6 +206,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -141,6 +223,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -156,6 +240,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -171,6 +257,9 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x1, int y, int x2, const color_type& c)
|
||||
{
|
||||
translate_to_base_ren(x1, y);
|
||||
translate_to_base_ren_x(x2);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -182,6 +271,9 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y1, int y2, const color_type& c)
|
||||
{
|
||||
translate_to_base_ren(x, y1);
|
||||
translate_to_base_ren_y(y2);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -194,6 +286,9 @@ namespace agg
|
||||
void blend_hline(int x1, int y, int x2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
translate_to_base_ren(x1, y);
|
||||
translate_to_base_ren_x(x2);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -201,11 +296,14 @@ namespace agg
|
||||
}
|
||||
while(next_clip_box());
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y1, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
translate_to_base_ren(x, y1);
|
||||
translate_to_base_ren_y(y2);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -217,6 +315,9 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
|
||||
{
|
||||
translate_to_base_ren(x1, y1);
|
||||
translate_to_base_ren(x2, y2);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -229,6 +330,9 @@ namespace agg
|
||||
void blend_bar(int x1, int y1, int x2, int y2,
|
||||
const color_type& c, cover_type cover)
|
||||
{
|
||||
translate_to_base_ren(x1, y1);
|
||||
translate_to_base_ren(x2, y2);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -242,6 +346,8 @@ namespace agg
|
||||
void blend_solid_hspan(int x, int y, int len,
|
||||
const color_type& c, const cover_type* covers)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -254,6 +360,8 @@ namespace agg
|
||||
void blend_solid_hspan_subpix(int x, int y, int len,
|
||||
const color_type& c, const cover_type* covers)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -266,6 +374,8 @@ namespace agg
|
||||
void blend_solid_vspan(int x, int y, int len,
|
||||
const color_type& c, const cover_type* covers)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -280,6 +390,8 @@ namespace agg
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -294,6 +406,8 @@ namespace agg
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -308,6 +422,7 @@ namespace agg
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
@@ -317,6 +432,7 @@ namespace agg
|
||||
const cover_type* covers,
|
||||
cover_type cover = cover_full)
|
||||
{
|
||||
translate_to_base_ren(x, y);
|
||||
m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
@@ -326,6 +442,7 @@ namespace agg
|
||||
int x_to=0,
|
||||
int y_to=0)
|
||||
{
|
||||
translate_to_base_ren(x_to, y_to);
|
||||
first_clip_box();
|
||||
do
|
||||
{
|
||||
@@ -343,6 +460,9 @@ namespace agg
|
||||
BRegion* m_region;
|
||||
unsigned m_curr_cb;
|
||||
rect_i m_bounds;
|
||||
|
||||
int m_offset_x;
|
||||
int m_offset_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright 2009, Christian Packmann.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2005-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include "BitmapPainter.h"
|
||||
|
||||
#include <Bitmap.h>
|
||||
|
||||
#include <agg_image_accessors.h>
|
||||
#include <agg_pixfmt_rgba.h>
|
||||
#include <agg_span_image_filter_rgba.h>
|
||||
|
||||
#include "DrawBitmapBilinear.h"
|
||||
#include "DrawBitmapGeneric.h"
|
||||
#include "DrawBitmapNearestNeighbor.h"
|
||||
#include "DrawBitmapNoScale.h"
|
||||
#include "drawing_support.h"
|
||||
#include "ServerBitmap.h"
|
||||
#include "SystemPalette.h"
|
||||
|
||||
|
||||
// #define TRACE_BITMAP_PAINTER
|
||||
#ifdef TRACE_BITMAP_PAINTER
|
||||
# define TRACE(x...) printf(x)
|
||||
#else
|
||||
# define TRACE(x...)
|
||||
#endif
|
||||
|
||||
|
||||
Painter::BitmapPainter::BitmapPainter(const Painter* painter,
|
||||
const ServerBitmap* bitmap, uint32 options)
|
||||
:
|
||||
fPainter(painter),
|
||||
fStatus(B_NO_INIT),
|
||||
fOptions(options)
|
||||
{
|
||||
if (bitmap == NULL || !bitmap->IsValid())
|
||||
return;
|
||||
|
||||
fBitmapBounds = bitmap->Bounds();
|
||||
fBitmapBounds.OffsetBy(-fBitmapBounds.left, -fBitmapBounds.top);
|
||||
// Compensate for the lefttop offset the bitmap bounds might have
|
||||
// It has the right size, but put it at B_ORIGIN
|
||||
|
||||
fColorSpace = bitmap->ColorSpace();
|
||||
|
||||
fBitmap.attach(bitmap->Bits(), bitmap->Width(), bitmap->Height(),
|
||||
bitmap->BytesPerRow());
|
||||
|
||||
fStatus = B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Painter::BitmapPainter::Draw(const BRect& sourceRect,
|
||||
const BRect& destinationRect)
|
||||
{
|
||||
using namespace BitmapPainterPrivate;
|
||||
|
||||
if (fStatus != B_OK)
|
||||
return;
|
||||
|
||||
TRACE("BitmapPainter::Draw()\n");
|
||||
TRACE(" bitmapBounds = (%.1f, %.1f) - (%.1f, %.1f)\n",
|
||||
bitmapBounds.left, bitmapBounds.top,
|
||||
bitmapBounds.right, bitmapBounds.bottom);
|
||||
TRACE(" sourceRect = (%.1f, %.1f) - (%.1f, %.1f)\n",
|
||||
sourceRect.left, sourceRect.top,
|
||||
sourceRect.right, sourceRect.bottom);
|
||||
TRACE(" destinationRect = (%.1f, %.1f) - (%.1f, %.1f)\n",
|
||||
destinationRect.left, destinationRect.top,
|
||||
destinationRect.right, destinationRect.bottom);
|
||||
|
||||
bool success = _DetermineTransform(sourceRect, destinationRect);
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
// optimized version for no scale in CMAP8 or RGB32 OP_OVER
|
||||
if (!_HasScale() && !_HasAffineTransform() && !_HasAlphaMask()) {
|
||||
if (fColorSpace == B_CMAP8) {
|
||||
if (fPainter->fDrawingMode == B_OP_COPY) {
|
||||
DrawBitmapNoScale<CMap8Copy> drawNoScale;
|
||||
drawNoScale.Draw(fPainter->fInternal, fBitmap, 1, fOffset,
|
||||
fDestinationRect);
|
||||
return;
|
||||
}
|
||||
if (fPainter->fDrawingMode == B_OP_OVER) {
|
||||
DrawBitmapNoScale<CMap8Over> drawNoScale;
|
||||
drawNoScale.Draw(fPainter->fInternal, fBitmap, 1, fOffset,
|
||||
fDestinationRect);
|
||||
return;
|
||||
}
|
||||
} else if (fColorSpace == B_RGB32) {
|
||||
if (fPainter->fDrawingMode == B_OP_OVER) {
|
||||
DrawBitmapNoScale<Bgr32Over> drawNoScale;
|
||||
drawNoScale.Draw(fPainter->fInternal, fBitmap, 4, fOffset,
|
||||
fDestinationRect);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjectDeleter<BBitmap> convertedBitmapDeleter;
|
||||
_ConvertColorSpace(convertedBitmapDeleter);
|
||||
|
||||
// optimized version if there is no scale
|
||||
if (!_HasScale() && !_HasAffineTransform() && !_HasAlphaMask()) {
|
||||
if (fPainter->fDrawingMode == B_OP_COPY) {
|
||||
DrawBitmapNoScale<Bgr32Copy> drawNoScale;
|
||||
drawNoScale.Draw(fPainter->fInternal, fBitmap, 4, fOffset,
|
||||
fDestinationRect);
|
||||
return;
|
||||
}
|
||||
if (fPainter->fDrawingMode == B_OP_OVER
|
||||
|| (fPainter->fDrawingMode == B_OP_ALPHA
|
||||
&& fPainter->fAlphaSrcMode == B_PIXEL_ALPHA
|
||||
&& fPainter->fAlphaFncMode == B_ALPHA_OVERLAY)) {
|
||||
DrawBitmapNoScale<Bgr32Alpha> drawNoScale;
|
||||
drawNoScale.Draw(fPainter->fInternal, fBitmap, 4, fOffset,
|
||||
fDestinationRect);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_HasScale() && !_HasAffineTransform() && _HasAlphaMask()) {
|
||||
if (fPainter->fDrawingMode == B_OP_COPY) {
|
||||
DrawBitmapNoScale<Bgr32CopyMasked> drawNoScale;
|
||||
drawNoScale.Draw(fPainter->fInternal, fBitmap, 4, fOffset,
|
||||
fDestinationRect);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// bilinear and nearest-neighbor scaled, OP_COPY only
|
||||
if (fPainter->fDrawingMode == B_OP_COPY
|
||||
&& !_HasAffineTransform() && !_HasAlphaMask()) {
|
||||
if ((fOptions & B_FILTER_BITMAP_BILINEAR) != 0) {
|
||||
DrawBitmapBilinear<ColorTypeRgb, DrawModeCopy> drawBilinear;
|
||||
drawBilinear.Draw(fPainter, fPainter->fInternal,
|
||||
fBitmap, fOffset, fScaleX, fScaleY, fDestinationRect);
|
||||
} else {
|
||||
DrawBitmapNearestNeighborCopy::Draw(fPainter, fPainter->fInternal,
|
||||
fBitmap, fOffset, fScaleX, fScaleY, fDestinationRect);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fPainter->fDrawingMode == B_OP_ALPHA
|
||||
&& fPainter->fAlphaSrcMode == B_PIXEL_ALPHA
|
||||
&& fPainter->fAlphaFncMode == B_ALPHA_OVERLAY
|
||||
&& !_HasAffineTransform() && !_HasAlphaMask()
|
||||
&& (fOptions & B_FILTER_BITMAP_BILINEAR) != 0) {
|
||||
DrawBitmapBilinear<ColorTypeRgba, DrawModeAlphaOverlay> drawBilinear;
|
||||
drawBilinear.Draw(fPainter, fPainter->fInternal,
|
||||
fBitmap, fOffset, fScaleX, fScaleY, fDestinationRect);
|
||||
return;
|
||||
}
|
||||
|
||||
// for all other cases (non-optimized drawing mode or scaled drawing)
|
||||
DrawBitmapGeneric::Draw(fPainter, fPainter->fInternal, fBitmap, fOffset,
|
||||
fScaleX, fScaleY, fDestinationRect, fOptions);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Painter::BitmapPainter::_DetermineTransform(BRect sourceRect,
|
||||
const BRect& destinationRect)
|
||||
{
|
||||
if (!fPainter->fValidClipping
|
||||
|| !sourceRect.IsValid()
|
||||
|| !sourceRect.Intersects(fBitmapBounds)
|
||||
|| !destinationRect.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fDestinationRect = destinationRect;
|
||||
|
||||
if (!fPainter->fSubpixelPrecise) {
|
||||
align_rect_to_pixels(&sourceRect);
|
||||
align_rect_to_pixels(&fDestinationRect);
|
||||
}
|
||||
|
||||
fScaleX = (fDestinationRect.Width() + 1) / (sourceRect.Width() + 1);
|
||||
fScaleY = (fDestinationRect.Height() + 1) / (sourceRect.Height() + 1);
|
||||
|
||||
if (fScaleX == 0.0 || fScaleY == 0.0)
|
||||
return false;
|
||||
|
||||
// constrain source rect to bitmap bounds and transfer the changes to
|
||||
// the destination rect with the right scale
|
||||
if (sourceRect.left < fBitmapBounds.left) {
|
||||
float diff = fBitmapBounds.left - sourceRect.left;
|
||||
fDestinationRect.left += diff * fScaleX;
|
||||
sourceRect.left = fBitmapBounds.left;
|
||||
}
|
||||
if (sourceRect.top < fBitmapBounds.top) {
|
||||
float diff = fBitmapBounds.top - sourceRect.top;
|
||||
fDestinationRect.top += diff * fScaleY;
|
||||
sourceRect.top = fBitmapBounds.top;
|
||||
}
|
||||
if (sourceRect.right > fBitmapBounds.right) {
|
||||
float diff = sourceRect.right - fBitmapBounds.right;
|
||||
fDestinationRect.right -= diff * fScaleX;
|
||||
sourceRect.right = fBitmapBounds.right;
|
||||
}
|
||||
if (sourceRect.bottom > fBitmapBounds.bottom) {
|
||||
float diff = sourceRect.bottom - fBitmapBounds.bottom;
|
||||
fDestinationRect.bottom -= diff * fScaleY;
|
||||
sourceRect.bottom = fBitmapBounds.bottom;
|
||||
}
|
||||
|
||||
fOffset.x = fDestinationRect.left - sourceRect.left;
|
||||
fOffset.y = fDestinationRect.top - sourceRect.top;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Painter::BitmapPainter::_HasScale()
|
||||
{
|
||||
return fScaleX != 1.0 || fScaleY != 1.0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Painter::BitmapPainter::_HasAffineTransform()
|
||||
{
|
||||
return !fPainter->fIdentityTransform;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Painter::BitmapPainter::_HasAlphaMask()
|
||||
{
|
||||
return fPainter->fInternal.fMaskedUnpackedScanline != NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Painter::BitmapPainter::_ConvertColorSpace(
|
||||
ObjectDeleter<BBitmap>& convertedBitmapDeleter)
|
||||
{
|
||||
if (fColorSpace == B_RGBA32)
|
||||
return;
|
||||
|
||||
if (fColorSpace == B_RGB32
|
||||
&& (fPainter->fDrawingMode == B_OP_COPY
|
||||
#if 1
|
||||
// Enabling this would make the behavior compatible to BeOS, which
|
||||
// treats B_RGB32 bitmaps as B_RGB*A*32 bitmaps in B_OP_ALPHA - unlike in
|
||||
// all other drawing modes, where B_TRANSPARENT_MAGIC_RGBA32 is handled.
|
||||
// B_RGB32 bitmaps therefore don't draw correctly on BeOS if they actually
|
||||
// use this color, unless the alpha channel contains 255 for all other
|
||||
// pixels, which is inconsistent.
|
||||
|| fPainter->fDrawingMode == B_OP_ALPHA
|
||||
#endif
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BBitmap* conversionBitmap = new(nothrow) BBitmap(fBitmapBounds,
|
||||
B_BITMAP_NO_SERVER_LINK, B_RGBA32);
|
||||
if (conversionBitmap == NULL) {
|
||||
fprintf(stderr, "BitmapPainter::_ConvertColorSpace() - "
|
||||
"out of memory for creating temporary conversion bitmap\n");
|
||||
return;
|
||||
}
|
||||
convertedBitmapDeleter.SetTo(conversionBitmap);
|
||||
|
||||
status_t err = conversionBitmap->ImportBits(fBitmap.buf(),
|
||||
fBitmap.height() * fBitmap.stride(),
|
||||
fBitmap.stride(), 0, fColorSpace);
|
||||
if (err < B_OK) {
|
||||
fprintf(stderr, "BitmapPainter::_ConvertColorSpace() - "
|
||||
"colorspace conversion failed: %s\n", strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// the original bitmap might have had some of the
|
||||
// transaparent magic colors set that we now need to
|
||||
// make transparent in our RGBA32 bitmap again.
|
||||
switch (fColorSpace) {
|
||||
case B_RGB32:
|
||||
_TransparentMagicToAlpha((uint32 *)fBitmap.buf(),
|
||||
fBitmap.width(), fBitmap.height(),
|
||||
fBitmap.stride(), B_TRANSPARENT_MAGIC_RGBA32,
|
||||
conversionBitmap);
|
||||
break;
|
||||
|
||||
// TODO: not sure if this applies to B_RGBA15 too. It
|
||||
// should not because B_RGBA15 actually has an alpha
|
||||
// channel itself and it should have been preserved
|
||||
// when importing the bitmap. Maybe it applies to
|
||||
// B_RGB16 though?
|
||||
case B_RGB15:
|
||||
_TransparentMagicToAlpha((uint16 *)fBitmap.buf(),
|
||||
fBitmap.width(), fBitmap.height(),
|
||||
fBitmap.stride(), B_TRANSPARENT_MAGIC_RGBA15,
|
||||
conversionBitmap);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fBitmap.attach((uint8*)conversionBitmap->Bits(),
|
||||
(uint32)fBitmapBounds.IntegerWidth() + 1,
|
||||
(uint32)fBitmapBounds.IntegerHeight() + 1,
|
||||
conversionBitmap->BytesPerRow());
|
||||
}
|
||||
|
||||
|
||||
template<typename sourcePixel>
|
||||
void
|
||||
Painter::BitmapPainter::_TransparentMagicToAlpha(sourcePixel* buffer,
|
||||
uint32 width, uint32 height, uint32 sourceBytesPerRow,
|
||||
sourcePixel transparentMagic, BBitmap* output)
|
||||
{
|
||||
uint8* sourceRow = (uint8*)buffer;
|
||||
uint8* destRow = (uint8*)output->Bits();
|
||||
uint32 destBytesPerRow = output->BytesPerRow();
|
||||
|
||||
for (uint32 y = 0; y < height; y++) {
|
||||
sourcePixel* pixel = (sourcePixel*)sourceRow;
|
||||
uint32* destPixel = (uint32*)destRow;
|
||||
for (uint32 x = 0; x < width; x++, pixel++, destPixel++) {
|
||||
if (*pixel == transparentMagic)
|
||||
*destPixel &= 0x00ffffff;
|
||||
}
|
||||
|
||||
sourceRow += sourceBytesPerRow;
|
||||
destRow += destBytesPerRow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BITMAP_PAINTER_H
|
||||
#define BITMAP_PAINTER_H
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
|
||||
class Painter::BitmapPainter {
|
||||
public:
|
||||
|
||||
public:
|
||||
BitmapPainter(const Painter* painter,
|
||||
const ServerBitmap* bitmap,
|
||||
uint32 options);
|
||||
|
||||
void Draw(const BRect& sourceRect,
|
||||
const BRect& destinationRect);
|
||||
|
||||
private:
|
||||
bool _DetermineTransform(
|
||||
BRect sourceRect,
|
||||
const BRect& destinationRect);
|
||||
|
||||
bool _HasScale();
|
||||
bool _HasAffineTransform();
|
||||
bool _HasAlphaMask();
|
||||
|
||||
void _ConvertColorSpace(ObjectDeleter<BBitmap>&
|
||||
convertedBitmapDeleter);
|
||||
|
||||
template<typename sourcePixel>
|
||||
void _TransparentMagicToAlpha(sourcePixel *buffer,
|
||||
uint32 width, uint32 height,
|
||||
uint32 sourceBytesPerRow,
|
||||
sourcePixel transparentMagic,
|
||||
BBitmap *output);
|
||||
|
||||
private:
|
||||
const Painter* fPainter;
|
||||
status_t fStatus;
|
||||
agg::rendering_buffer fBitmap;
|
||||
BRect fBitmapBounds;
|
||||
color_space fColorSpace;
|
||||
uint32 fOptions;
|
||||
|
||||
BRect fDestinationRect;
|
||||
double fScaleX;
|
||||
double fScaleY;
|
||||
BPoint fOffset;
|
||||
};
|
||||
|
||||
|
||||
#endif // BITMAP_PAINTER_H
|
||||
@@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright 2009, Christian Packmann.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2005-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DRAW_BITMAP_BILINEAR_H
|
||||
#define DRAW_BITMAP_BILINEAR_H
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
|
||||
// Prototypes for assembler routines
|
||||
extern "C" {
|
||||
void bilinear_scale_xloop_mmxsse(const uint8* src, void* dst,
|
||||
void* xWeights, uint32 xmin, uint32 xmax, uint32 wTop, uint32 srcBPR);
|
||||
}
|
||||
|
||||
|
||||
extern uint32 gSIMDFlags;
|
||||
|
||||
|
||||
namespace BitmapPainterPrivate {
|
||||
|
||||
|
||||
struct FilterInfo {
|
||||
uint16 index; // index into source bitmap row/column
|
||||
uint16 weight; // weight of the pixel at index [0..255]
|
||||
};
|
||||
|
||||
|
||||
struct FilterData {
|
||||
FilterInfo* fWeightsX;
|
||||
FilterInfo* fWeightsY;
|
||||
uint32 fIndexOffsetX;
|
||||
uint32 fIndexOffsetY;
|
||||
};
|
||||
|
||||
|
||||
template<class OptimizedVersion>
|
||||
struct DrawBitmapBilinearOptimized {
|
||||
void Draw(PainterAggInterface& aggInterface, const BRect& destinationRect,
|
||||
agg::rendering_buffer* bitmap, const FilterData& filterData)
|
||||
{
|
||||
fSource = bitmap;
|
||||
fSourceBytesPerRow = bitmap->stride();
|
||||
fDestination = NULL;
|
||||
fDestinationBytesPerRow = aggInterface.fBuffer.stride();
|
||||
fWeightsX = filterData.fWeightsX;
|
||||
fWeightsY = filterData.fWeightsY;
|
||||
|
||||
const int32 left = (int32)destinationRect.left;
|
||||
const int32 top = (int32)destinationRect.top;
|
||||
const int32 right = (int32)destinationRect.right;
|
||||
const int32 bottom = (int32)destinationRect.bottom;
|
||||
|
||||
renderer_base& baseRenderer = aggInterface.fBaseRenderer;
|
||||
|
||||
// iterate over clipping boxes
|
||||
baseRenderer.first_clip_box();
|
||||
do {
|
||||
const int32 x1 = max_c(baseRenderer.xmin(), left);
|
||||
const int32 x2 = min_c(baseRenderer.xmax(), right);
|
||||
if (x1 > x2)
|
||||
continue;
|
||||
|
||||
int32 y1 = max_c(baseRenderer.ymin(), top);
|
||||
int32 y2 = min_c(baseRenderer.ymax(), bottom);
|
||||
if (y1 > y2)
|
||||
continue;
|
||||
|
||||
// buffer offset into destination
|
||||
fDestination = aggInterface.fBuffer.row_ptr(y1) + x1 * 4;
|
||||
|
||||
// x and y are needed as indices into the weight arrays, so the
|
||||
// offset into the target buffer needs to be compensated
|
||||
const int32 xIndexL = x1 - left - filterData.fIndexOffsetX;
|
||||
const int32 xIndexR = x2 - left - filterData.fIndexOffsetX;
|
||||
y1 -= top + filterData.fIndexOffsetY;
|
||||
y2 -= top + filterData.fIndexOffsetY;
|
||||
|
||||
//printf("x: %ld - %ld\n", xIndexL, xIndexR);
|
||||
//printf("y: %ld - %ld\n", y1, y2);
|
||||
|
||||
static_cast<OptimizedVersion*>(this)->DrawToClipRect(
|
||||
xIndexL, xIndexR, y1, y2);
|
||||
|
||||
} while (baseRenderer.next_clip_box());
|
||||
}
|
||||
|
||||
protected:
|
||||
agg::rendering_buffer* fSource;
|
||||
uint32 fSourceBytesPerRow;
|
||||
uint8* fDestination;
|
||||
uint32 fDestinationBytesPerRow;
|
||||
FilterInfo* fWeightsX;
|
||||
FilterInfo* fWeightsY;
|
||||
};
|
||||
|
||||
|
||||
struct ColorTypeRgb {
|
||||
static void
|
||||
Interpolate(uint32* t, const uint8* s, uint32 sourceBytesPerRow,
|
||||
uint16 wLeft, uint16 wTop, uint16 wRight, uint16 wBottom)
|
||||
{
|
||||
// left and right of top row
|
||||
t[0] = (s[0] * wLeft + s[4] * wRight) * wTop;
|
||||
t[1] = (s[1] * wLeft + s[5] * wRight) * wTop;
|
||||
t[2] = (s[2] * wLeft + s[6] * wRight) * wTop;
|
||||
|
||||
// left and right of bottom row
|
||||
s += sourceBytesPerRow;
|
||||
t[0] += (s[0] * wLeft + s[4] * wRight) * wBottom;
|
||||
t[1] += (s[1] * wLeft + s[5] * wRight) * wBottom;
|
||||
t[2] += (s[2] * wLeft + s[6] * wRight) * wBottom;
|
||||
|
||||
t[0] >>= 16;
|
||||
t[1] >>= 16;
|
||||
t[2] >>= 16;
|
||||
}
|
||||
|
||||
static void
|
||||
InterpolateLastColumn(uint32* t, const uint8* s, const uint8* sBottom,
|
||||
uint16 wTop, uint16 wBottom)
|
||||
{
|
||||
t[0] = (s[0] * wTop + sBottom[0] * wBottom) >> 8;
|
||||
t[1] = (s[1] * wTop + sBottom[1] * wBottom) >> 8;
|
||||
t[2] = (s[2] * wTop + sBottom[2] * wBottom) >> 8;
|
||||
}
|
||||
|
||||
static void
|
||||
InterpolateLastRow(uint32* t, const uint8* s, uint16 wLeft,
|
||||
uint16 wRight)
|
||||
{
|
||||
t[0] = (s[0] * wLeft + s[4] * wRight) >> 8;
|
||||
t[1] = (s[1] * wLeft + s[5] * wRight) >> 8;
|
||||
t[2] = (s[2] * wLeft + s[6] * wRight) >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct ColorTypeRgba {
|
||||
static void
|
||||
Interpolate(uint32* t, const uint8* s, uint32 sourceBytesPerRow,
|
||||
uint16 wLeft, uint16 wTop, uint16 wRight, uint16 wBottom)
|
||||
{
|
||||
// left and right of top row
|
||||
t[0] = (s[0] * wLeft + s[4] * wRight) * wTop;
|
||||
t[1] = (s[1] * wLeft + s[5] * wRight) * wTop;
|
||||
t[2] = (s[2] * wLeft + s[6] * wRight) * wTop;
|
||||
t[3] = (s[3] * wLeft + s[7] * wRight) * wTop;
|
||||
|
||||
// left and right of bottom row
|
||||
s += sourceBytesPerRow;
|
||||
|
||||
t[0] += (s[0] * wLeft + s[4] * wRight) * wBottom;
|
||||
t[1] += (s[1] * wLeft + s[5] * wRight) * wBottom;
|
||||
t[2] += (s[2] * wLeft + s[6] * wRight) * wBottom;
|
||||
t[3] += (s[3] * wLeft + s[7] * wRight) * wBottom;
|
||||
|
||||
t[0] >>= 16;
|
||||
t[1] >>= 16;
|
||||
t[2] >>= 16;
|
||||
t[3] >>= 16;
|
||||
}
|
||||
|
||||
static void
|
||||
InterpolateLastColumn(uint32* t, const uint8* s, const uint8* sBottom,
|
||||
uint16 wTop, uint16 wBottom)
|
||||
{
|
||||
t[0] = (s[0] * wTop + sBottom[0] * wBottom) >> 8;
|
||||
t[1] = (s[1] * wTop + sBottom[1] * wBottom) >> 8;
|
||||
t[2] = (s[2] * wTop + sBottom[2] * wBottom) >> 8;
|
||||
t[3] = (s[3] * wTop + sBottom[3] * wBottom) >> 8;
|
||||
}
|
||||
|
||||
static void
|
||||
InterpolateLastRow(uint32* t, const uint8* s, uint16 wLeft,
|
||||
uint16 wRight)
|
||||
{
|
||||
t[0] = (s[0] * wLeft + s[4] * wRight) >> 8;
|
||||
t[1] = (s[1] * wLeft + s[5] * wRight) >> 8;
|
||||
t[2] = (s[2] * wLeft + s[6] * wRight) >> 8;
|
||||
t[3] = (s[3] * wLeft + s[7] * wRight) >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct DrawModeCopy {
|
||||
static void
|
||||
Blend(uint8*& d, uint32* t)
|
||||
{
|
||||
d[0] = t[0];
|
||||
d[1] = t[1];
|
||||
d[2] = t[2];
|
||||
d += 4;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct DrawModeAlphaOverlay {
|
||||
static void
|
||||
Blend(uint8*& d, uint32* t)
|
||||
{
|
||||
uint8 t0 = t[0];
|
||||
uint8 t1 = t[1];
|
||||
uint8 t2 = t[2];
|
||||
uint8 t3 = t[3];
|
||||
|
||||
if (t3 == 255) {
|
||||
d[0] = t0;
|
||||
d[1] = t1;
|
||||
d[2] = t2;
|
||||
} else {
|
||||
d[0] = ((t0 - d[0]) * t3 + (d[0] << 8)) >> 8;
|
||||
d[1] = ((t1 - d[1]) * t3 + (d[1] << 8)) >> 8;
|
||||
d[2] = ((t2 - d[2]) * t3 + (d[2] << 8)) >> 8;
|
||||
}
|
||||
|
||||
d += 4;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class ColorType, class DrawMode>
|
||||
struct BilinearDefault :
|
||||
DrawBitmapBilinearOptimized<BilinearDefault<ColorType, DrawMode> > {
|
||||
|
||||
void DrawToClipRect(int32 xIndexL, int32 xIndexR, int32 y1, int32 y2)
|
||||
{
|
||||
// In this mode we anticipate many pixels wich need filtering,
|
||||
// there are no special cases for direct hit pixels except for
|
||||
// the last column/row and the right/bottom corner pixel.
|
||||
|
||||
// The last column/row handling does not need to be performed
|
||||
// for all clipping rects!
|
||||
int32 yMax = y2;
|
||||
if (fWeightsY[yMax].weight == 255)
|
||||
yMax--;
|
||||
int32 xIndexMax = xIndexR;
|
||||
if (fWeightsX[xIndexMax].weight == 255)
|
||||
xIndexMax--;
|
||||
|
||||
for (; y1 <= yMax; y1++) {
|
||||
// cache the weight of the top and bottom row
|
||||
const uint16 wTop = fWeightsY[y1].weight;
|
||||
const uint16 wBottom = 255 - fWeightsY[y1].weight;
|
||||
|
||||
// buffer offset into source (top row)
|
||||
register const uint8* src = fSource->row_ptr(fWeightsY[y1].index);
|
||||
|
||||
// buffer handle for destination to be incremented per
|
||||
// pixel
|
||||
register uint8* d = fDestination;
|
||||
|
||||
for (int32 x = xIndexL; x <= xIndexMax; x++) {
|
||||
const uint8* s = src + fWeightsX[x].index;
|
||||
|
||||
// calculate the weighted sum of all four
|
||||
// interpolated pixels
|
||||
const uint16 wLeft = fWeightsX[x].weight;
|
||||
const uint16 wRight = 255 - wLeft;
|
||||
|
||||
uint32 t[4];
|
||||
ColorType::Interpolate(&t[0], s, fSourceBytesPerRow,
|
||||
wLeft, wTop, wRight, wBottom);
|
||||
DrawMode::Blend(d, &t[0]);
|
||||
}
|
||||
// last column of pixels if necessary
|
||||
if (xIndexMax < xIndexR) {
|
||||
const uint8* s = src + fWeightsX[xIndexR].index;
|
||||
const uint8* sBottom = s + fSourceBytesPerRow;
|
||||
|
||||
uint32 t[4];
|
||||
ColorType::InterpolateLastColumn(&t[0], s, sBottom, wTop,
|
||||
wBottom);
|
||||
DrawMode::Blend(d, &t[0]);
|
||||
}
|
||||
|
||||
fDestination += fDestinationBytesPerRow;
|
||||
}
|
||||
|
||||
// last row of pixels if necessary
|
||||
// buffer offset into source (bottom row)
|
||||
register const uint8* src
|
||||
= fSource->row_ptr(fWeightsY[y2].index);
|
||||
// buffer handle for destination to be incremented per pixel
|
||||
register uint8* d = fDestination;
|
||||
|
||||
if (yMax < y2) {
|
||||
for (int32 x = xIndexL; x <= xIndexMax; x++) {
|
||||
const uint8* s = src + fWeightsX[x].index;
|
||||
const uint16 wLeft = fWeightsX[x].weight;
|
||||
const uint16 wRight = 255 - wLeft;
|
||||
uint32 t[4];
|
||||
ColorType::InterpolateLastRow(&t[0], s, wLeft, wRight);
|
||||
DrawMode::Blend(d, &t[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// pixel in bottom right corner if necessary
|
||||
if (yMax < y2 && xIndexMax < xIndexR) {
|
||||
const uint8* s = src + fWeightsX[xIndexR].index;
|
||||
*(uint32*)d = *(uint32*)s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct BilinearLowFilterRatio :
|
||||
DrawBitmapBilinearOptimized<BilinearLowFilterRatio> {
|
||||
void DrawToClipRect(int32 xIndexL, int32 xIndexR, int32 y1, int32 y2)
|
||||
{
|
||||
// In this mode, we anticipate to hit many destination pixels
|
||||
// that map directly to a source pixel, we have more branches
|
||||
// in the inner loop but save time because of the special
|
||||
// cases. If there are too few direct hit pixels, the branches
|
||||
// only waste time.
|
||||
|
||||
for (; y1 <= y2; y1++) {
|
||||
// cache the weight of the top and bottom row
|
||||
const uint16 wTop = fWeightsY[y1].weight;
|
||||
const uint16 wBottom = 255 - fWeightsY[y1].weight;
|
||||
|
||||
// buffer offset into source (top row)
|
||||
register const uint8* src = fSource->row_ptr(fWeightsY[y1].index);
|
||||
// buffer handle for destination to be incremented per
|
||||
// pixel
|
||||
register uint8* d = fDestination;
|
||||
|
||||
if (wTop == 255) {
|
||||
for (int32 x = xIndexL; x <= xIndexR; x++) {
|
||||
const uint8* s = src + fWeightsX[x].index;
|
||||
// This case is important to prevent out
|
||||
// of bounds access at bottom edge of the source
|
||||
// bitmap. If the scale is low and integer, it will
|
||||
// also help the speed.
|
||||
if (fWeightsX[x].weight == 255) {
|
||||
// As above, but to prevent out of bounds
|
||||
// on the right edge.
|
||||
*(uint32*)d = *(uint32*)s;
|
||||
} else {
|
||||
// Only the left and right pixels are
|
||||
// interpolated, since the top row has 100%
|
||||
// weight.
|
||||
const uint16 wLeft = fWeightsX[x].weight;
|
||||
const uint16 wRight = 255 - wLeft;
|
||||
d[0] = (s[0] * wLeft + s[4] * wRight) >> 8;
|
||||
d[1] = (s[1] * wLeft + s[5] * wRight) >> 8;
|
||||
d[2] = (s[2] * wLeft + s[6] * wRight) >> 8;
|
||||
}
|
||||
d += 4;
|
||||
}
|
||||
} else {
|
||||
for (int32 x = xIndexL; x <= xIndexR; x++) {
|
||||
const uint8* s = src + fWeightsX[x].index;
|
||||
if (fWeightsX[x].weight == 255) {
|
||||
// Prevent out of bounds access on the right
|
||||
// edge or simply speed up.
|
||||
const uint8* sBottom = s + fSourceBytesPerRow;
|
||||
d[0] = (s[0] * wTop + sBottom[0] * wBottom)
|
||||
>> 8;
|
||||
d[1] = (s[1] * wTop + sBottom[1] * wBottom)
|
||||
>> 8;
|
||||
d[2] = (s[2] * wTop + sBottom[2] * wBottom)
|
||||
>> 8;
|
||||
} else {
|
||||
// calculate the weighted sum of all four
|
||||
// interpolated pixels
|
||||
const uint16 wLeft = fWeightsX[x].weight;
|
||||
const uint16 wRight = 255 - wLeft;
|
||||
// left and right of top row
|
||||
uint32 t0 = (s[0] * wLeft + s[4] * wRight)
|
||||
* wTop;
|
||||
uint32 t1 = (s[1] * wLeft + s[5] * wRight)
|
||||
* wTop;
|
||||
uint32 t2 = (s[2] * wLeft + s[6] * wRight)
|
||||
* wTop;
|
||||
|
||||
// left and right of bottom row
|
||||
s += fSourceBytesPerRow;
|
||||
t0 += (s[0] * wLeft + s[4] * wRight) * wBottom;
|
||||
t1 += (s[1] * wLeft + s[5] * wRight) * wBottom;
|
||||
t2 += (s[2] * wLeft + s[6] * wRight) * wBottom;
|
||||
|
||||
d[0] = t0 >> 16;
|
||||
d[1] = t1 >> 16;
|
||||
d[2] = t2 >> 16;
|
||||
}
|
||||
d += 4;
|
||||
}
|
||||
}
|
||||
fDestination += fDestinationBytesPerRow;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef __INTEL__
|
||||
|
||||
struct BilinearSimd : DrawBitmapBilinearOptimized<BilinearSimd> {
|
||||
void DrawToClipRect(int32 xIndexL, int32 xIndexR, int32 y1, int32 y2)
|
||||
{
|
||||
// Basically the same as the "standard" mode, but we use SIMD
|
||||
// routines for the processing of the single display lines.
|
||||
|
||||
// The last column/row handling does not need to be performed
|
||||
// for all clipping rects!
|
||||
int32 yMax = y2;
|
||||
if (fWeightsY[yMax].weight == 255)
|
||||
yMax--;
|
||||
int32 xIndexMax = xIndexR;
|
||||
if (fWeightsX[xIndexMax].weight == 255)
|
||||
xIndexMax--;
|
||||
|
||||
for (; y1 <= yMax; y1++) {
|
||||
// cache the weight of the top and bottom row
|
||||
const uint16 wTop = fWeightsY[y1].weight;
|
||||
const uint16 wBottom = 255 - fWeightsY[y1].weight;
|
||||
|
||||
// buffer offset into source (top row)
|
||||
const uint8* src = fSource->row_ptr(fWeightsY[y1].index);
|
||||
// buffer handle for destination to be incremented per
|
||||
// pixel
|
||||
uint8* d = fDestination;
|
||||
bilinear_scale_xloop_mmxsse(src, fDestination, fWeightsX, xIndexL,
|
||||
xIndexMax, wTop, fSourceBytesPerRow);
|
||||
// increase pointer by processed pixels
|
||||
d += (xIndexMax - xIndexL + 1) * 4;
|
||||
|
||||
// last column of pixels if necessary
|
||||
if (xIndexMax < xIndexR) {
|
||||
const uint8* s = src + fWeightsX[xIndexR].index;
|
||||
const uint8* sBottom = s + fSourceBytesPerRow;
|
||||
d[0] = (s[0] * wTop + sBottom[0] * wBottom) >> 8;
|
||||
d[1] = (s[1] * wTop + sBottom[1] * wBottom) >> 8;
|
||||
d[2] = (s[2] * wTop + sBottom[2] * wBottom) >> 8;
|
||||
}
|
||||
|
||||
fDestination += fDestinationBytesPerRow;
|
||||
}
|
||||
|
||||
// last row of pixels if necessary
|
||||
// buffer offset into source (bottom row)
|
||||
register const uint8* src = fSource->row_ptr(fWeightsY[y2].index);
|
||||
// buffer handle for destination to be incremented per pixel
|
||||
register uint8* d = fDestination;
|
||||
|
||||
if (yMax < y2) {
|
||||
for (int32 x = xIndexL; x <= xIndexMax; x++) {
|
||||
const uint8* s = src + fWeightsX[x].index;
|
||||
const uint16 wLeft = fWeightsX[x].weight;
|
||||
const uint16 wRight = 255 - wLeft;
|
||||
d[0] = (s[0] * wLeft + s[4] * wRight) >> 8;
|
||||
d[1] = (s[1] * wLeft + s[5] * wRight) >> 8;
|
||||
d[2] = (s[2] * wLeft + s[6] * wRight) >> 8;
|
||||
d += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// pixel in bottom right corner if necessary
|
||||
if (yMax < y2 && xIndexMax < xIndexR) {
|
||||
const uint8* s = src + fWeightsX[xIndexR].index;
|
||||
*(uint32*)d = *(uint32*)s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __INTEL__
|
||||
|
||||
|
||||
template<class ColorType, class DrawMode>
|
||||
struct DrawBitmapBilinear {
|
||||
void
|
||||
Draw(const Painter* painter, PainterAggInterface& aggInterface,
|
||||
agg::rendering_buffer& bitmap, BPoint offset,
|
||||
double scaleX, double scaleY, BRect destinationRect)
|
||||
{
|
||||
//bigtime_t now = system_time();
|
||||
uint32 dstWidth = destinationRect.IntegerWidth() + 1;
|
||||
uint32 dstHeight = destinationRect.IntegerHeight() + 1;
|
||||
uint32 srcWidth = bitmap.width();
|
||||
uint32 srcHeight = bitmap.height();
|
||||
|
||||
// Do not calculate more filter weights than necessary and also
|
||||
// keep the stack based allocations reasonably sized
|
||||
const BRegion& clippingRegion = *painter->ClippingRegion();
|
||||
if (clippingRegion.Frame().IntegerWidth() + 1 < (int32)dstWidth)
|
||||
dstWidth = clippingRegion.Frame().IntegerWidth() + 1;
|
||||
if (clippingRegion.Frame().IntegerHeight() + 1 < (int32)dstHeight)
|
||||
dstHeight = clippingRegion.Frame().IntegerHeight() + 1;
|
||||
|
||||
// When calculating less filter weights than specified by
|
||||
// destinationRect, we need to compensate the offset.
|
||||
FilterData filterData;
|
||||
filterData.fIndexOffsetX = 0;
|
||||
filterData.fIndexOffsetY = 0;
|
||||
if (clippingRegion.Frame().left > destinationRect.left) {
|
||||
filterData.fIndexOffsetX = (int32)(clippingRegion.Frame().left
|
||||
- destinationRect.left);
|
||||
}
|
||||
if (clippingRegion.Frame().top > destinationRect.top) {
|
||||
filterData.fIndexOffsetY = (int32)(clippingRegion.Frame().top
|
||||
- destinationRect.top);
|
||||
}
|
||||
|
||||
//#define FILTER_INFOS_ON_HEAP
|
||||
#ifdef FILTER_INFOS_ON_HEAP
|
||||
filterData.fWeightsX = new (nothrow) FilterInfo[dstWidth];
|
||||
filterData.fWeightsY = new (nothrow) FilterInfo[dstHeight];
|
||||
if (filterData.fWeightsX == NULL || filterData.fWeightsY == NULL) {
|
||||
delete[] filterData.fWeightsX;
|
||||
delete[] filterData.fWeightsY;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
// stack based saves about 200µs on 1.85 GHz Core 2 Duo
|
||||
// should not pose a problem with stack overflows
|
||||
// (needs around 12Kb for 1920x1200)
|
||||
FilterInfo xWeights[dstWidth];
|
||||
FilterInfo yWeights[dstHeight];
|
||||
filterData.fWeightsX = &xWeights[0];
|
||||
filterData.fWeightsY = &yWeights[0];
|
||||
#endif
|
||||
|
||||
// Extract the cropping information for the source bitmap,
|
||||
// If only a part of the source bitmap is to be drawn with scale,
|
||||
// the offset will be different from the destinationRect left top
|
||||
// corner.
|
||||
const int32 xBitmapShift = (int32)(destinationRect.left - offset.x);
|
||||
const int32 yBitmapShift = (int32)(destinationRect.top - offset.y);
|
||||
|
||||
for (uint32 i = 0; i < dstWidth; i++) {
|
||||
// fractional index into source
|
||||
// NOTE: It is very important to calculate the fractional index
|
||||
// into the source pixel grid like this to prevent out of bounds
|
||||
// access! It will result in the rightmost pixel of the destination
|
||||
// to access the rightmost pixel of the source with a weighting
|
||||
// of 255. This in turn will trigger an optimization in the loop
|
||||
// that also prevents out of bounds access.
|
||||
float index = (i + filterData.fIndexOffsetX) * (srcWidth - 1)
|
||||
/ (srcWidth * scaleX - 1);
|
||||
// round down to get the left pixel
|
||||
filterData.fWeightsX[i].index = (uint16)index;
|
||||
filterData.fWeightsX[i].weight =
|
||||
255 - (uint16)((index - filterData.fWeightsX[i].index) * 255);
|
||||
// handle cropped source bitmap
|
||||
filterData.fWeightsX[i].index += xBitmapShift;
|
||||
// precompute index for 32 bit pixels
|
||||
filterData.fWeightsX[i].index *= 4;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < dstHeight; i++) {
|
||||
// fractional index into source
|
||||
// NOTE: It is very important to calculate the fractional index
|
||||
// into the source pixel grid like this to prevent out of bounds
|
||||
// access! It will result in the bottommost pixel of the
|
||||
// destination to access the bottommost pixel of the source with a
|
||||
// weighting of 255. This in turn will trigger an optimization in
|
||||
// the loop that also prevents out of bounds access.
|
||||
float index = (i + filterData.fIndexOffsetY) * (srcHeight - 1)
|
||||
/ (srcHeight * scaleY - 1);
|
||||
// round down to get the top pixel
|
||||
filterData.fWeightsY[i].index = (uint16)index;
|
||||
filterData.fWeightsY[i].weight =
|
||||
255 - (uint16)((index - filterData.fWeightsY[i].index) * 255);
|
||||
// handle cropped source bitmap
|
||||
filterData.fWeightsY[i].index += yBitmapShift;
|
||||
}
|
||||
//printf("X: %d/%d ... %d/%d, %d/%d (%ld)\n",
|
||||
// xWeights[0].index, xWeights[0].weight,
|
||||
// xWeights[dstWidth - 2].index, xWeights[dstWidth - 2].weight,
|
||||
// xWeights[dstWidth - 1].index, xWeights[dstWidth - 1].weight,
|
||||
// dstWidth);
|
||||
//printf("Y: %d/%d ... %d/%d, %d/%d (%ld)\n",
|
||||
// yWeights[0].index, yWeights[0].weight,
|
||||
// yWeights[dstHeight - 2].index, yWeights[dstHeight - 2].weight,
|
||||
// yWeights[dstHeight - 1].index, yWeights[dstHeight - 1].weight,
|
||||
// dstHeight);
|
||||
|
||||
// Figure out which version of the code we want to use...
|
||||
enum {
|
||||
kOptimizeForLowFilterRatio = 0,
|
||||
kUseDefaultVersion,
|
||||
kUseSIMDVersion
|
||||
};
|
||||
|
||||
int codeSelect = kUseDefaultVersion;
|
||||
|
||||
if (typeid(ColorType) == typeid(ColorTypeRgb)
|
||||
&& typeid(DrawMode) == typeid(DrawModeCopy)) {
|
||||
uint32 neededSIMDFlags = APPSERVER_SIMD_MMX | APPSERVER_SIMD_SSE;
|
||||
if ((gSIMDFlags & neededSIMDFlags) == neededSIMDFlags)
|
||||
codeSelect = kUseSIMDVersion;
|
||||
else {
|
||||
if (scaleX == scaleY && (scaleX == 1.5 || scaleX == 2.0
|
||||
|| scaleX == 2.5 || scaleX == 3.0)) {
|
||||
codeSelect = kOptimizeForLowFilterRatio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (codeSelect) {
|
||||
case kUseDefaultVersion:
|
||||
{
|
||||
BilinearDefault<ColorType, DrawMode> bilinearPainter;
|
||||
bilinearPainter.Draw(aggInterface, destinationRect, &bitmap,
|
||||
filterData);
|
||||
break;
|
||||
}
|
||||
|
||||
case kOptimizeForLowFilterRatio:
|
||||
{
|
||||
BilinearLowFilterRatio bilinearPainter;
|
||||
bilinearPainter.Draw(aggInterface, destinationRect,
|
||||
&bitmap, filterData);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __INTEL__
|
||||
case kUseSIMDVersion:
|
||||
{
|
||||
BilinearSimd bilinearPainter;
|
||||
bilinearPainter.Draw(aggInterface, destinationRect, &bitmap,
|
||||
filterData);
|
||||
break;
|
||||
}
|
||||
#endif // __INTEL__
|
||||
}
|
||||
|
||||
#ifdef FILTER_INFOS_ON_HEAP
|
||||
delete[] filterData.fWeightsX;
|
||||
delete[] filterData.fWeightsY;
|
||||
#endif
|
||||
//printf("draw bitmap %.5fx%.5f: %lld\n", scaleX, scaleY,
|
||||
// system_time() - now);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace BitmapPainterPrivate
|
||||
|
||||
|
||||
#endif // DRAW_BITMAP_BILINEAR_H
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2009, Christian Packmann.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2005-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DRAW_BITMAP_GENERIC_H
|
||||
#define DRAW_BITMAP_GENERIC_H
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
|
||||
struct DrawBitmapGeneric {
|
||||
static void
|
||||
Draw(const Painter* painter, PainterAggInterface& aggInterface,
|
||||
agg::rendering_buffer& bitmap, BPoint offset,
|
||||
double scaleX, double scaleY, BRect destinationRect, uint32 options)
|
||||
{
|
||||
// pixel format attached to bitmap
|
||||
typedef agg::pixfmt_bgra32 pixfmt_image;
|
||||
pixfmt_image pixf_img(bitmap);
|
||||
|
||||
agg::trans_affine srcMatrix;
|
||||
// NOTE: R5 seems to ignore this offset when drawing bitmaps
|
||||
// srcMatrix *= agg::trans_affine_translation(-actualBitmapRect.left,
|
||||
// -actualBitmapRect.top);
|
||||
srcMatrix *= painter->Transform();
|
||||
|
||||
agg::trans_affine imgMatrix;
|
||||
imgMatrix *= agg::trans_affine_translation(
|
||||
offset.x - destinationRect.left, offset.y - destinationRect.top);
|
||||
imgMatrix *= agg::trans_affine_scaling(scaleX, scaleY);
|
||||
imgMatrix *= agg::trans_affine_translation(destinationRect.left,
|
||||
destinationRect.top);
|
||||
imgMatrix *= painter->Transform();
|
||||
imgMatrix.invert();
|
||||
|
||||
// image interpolator
|
||||
typedef agg::span_interpolator_linear<> interpolator_type;
|
||||
interpolator_type interpolator(imgMatrix);
|
||||
|
||||
// scanline allocator
|
||||
agg::span_allocator<pixfmt_image::color_type> spanAllocator;
|
||||
|
||||
// image accessor attached to pixel format of bitmap
|
||||
typedef agg::image_accessor_clone<pixfmt_image> source_type;
|
||||
source_type source(pixf_img);
|
||||
|
||||
// clip to the current clipping region's frame
|
||||
if (painter->IsIdentityTransform()) {
|
||||
destinationRect = destinationRect
|
||||
& painter->ClippingRegion()->Frame();
|
||||
}
|
||||
// convert to pixel coords (versus pixel indices)
|
||||
destinationRect.right++;
|
||||
destinationRect.bottom++;
|
||||
|
||||
// path enclosing the bitmap
|
||||
agg::path_storage& path = aggInterface.fPath;
|
||||
rasterizer_type& rasterizer = aggInterface.fRasterizer;
|
||||
|
||||
path.remove_all();
|
||||
path.move_to(destinationRect.left, destinationRect.top);
|
||||
path.line_to(destinationRect.right, destinationRect.top);
|
||||
path.line_to(destinationRect.right, destinationRect.bottom);
|
||||
path.line_to(destinationRect.left, destinationRect.bottom);
|
||||
path.close_polygon();
|
||||
|
||||
agg::conv_transform<agg::path_storage> transformedPath(path,
|
||||
srcMatrix);
|
||||
rasterizer.reset();
|
||||
rasterizer.add_path(transformedPath);
|
||||
|
||||
if ((options & B_FILTER_BITMAP_BILINEAR) != 0) {
|
||||
// image filter (bilinear)
|
||||
typedef agg::span_image_filter_rgba_bilinear<
|
||||
source_type, interpolator_type> span_gen_type;
|
||||
span_gen_type spanGenerator(source, interpolator);
|
||||
|
||||
// render the path with the bitmap as scanline fill
|
||||
if (aggInterface.fMaskedUnpackedScanline != NULL) {
|
||||
agg::render_scanlines_aa(rasterizer,
|
||||
*aggInterface.fMaskedUnpackedScanline,
|
||||
aggInterface.fBaseRenderer, spanAllocator, spanGenerator);
|
||||
} else {
|
||||
agg::render_scanlines_aa(rasterizer,
|
||||
aggInterface.fUnpackedScanline,
|
||||
aggInterface.fBaseRenderer, spanAllocator, spanGenerator);
|
||||
}
|
||||
} else {
|
||||
// image filter (nearest neighbor)
|
||||
typedef agg::span_image_filter_rgba_nn<
|
||||
source_type, interpolator_type> span_gen_type;
|
||||
span_gen_type spanGenerator(source, interpolator);
|
||||
|
||||
// render the path with the bitmap as scanline fill
|
||||
if (aggInterface.fMaskedUnpackedScanline != NULL) {
|
||||
agg::render_scanlines_aa(rasterizer,
|
||||
*aggInterface.fMaskedUnpackedScanline,
|
||||
aggInterface.fBaseRenderer, spanAllocator, spanGenerator);
|
||||
} else {
|
||||
agg::render_scanlines_aa(rasterizer,
|
||||
aggInterface.fUnpackedScanline,
|
||||
aggInterface.fBaseRenderer, spanAllocator, spanGenerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // DRAW_BITMAP_GENERIC_H
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2009, Christian Packmann.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2005-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DRAW_BITMAP_NEAREST_NEIGHBOR_H
|
||||
#define DRAW_BITMAP_NEAREST_NEIGHBOR_H
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
|
||||
struct DrawBitmapNearestNeighborCopy {
|
||||
static void
|
||||
Draw(const Painter* painter, PainterAggInterface& aggInterface,
|
||||
agg::rendering_buffer& bitmap, BPoint offset,
|
||||
double scaleX, double scaleY, BRect destinationRect)
|
||||
{
|
||||
//bigtime_t now = system_time();
|
||||
uint32 dstWidth = destinationRect.IntegerWidth() + 1;
|
||||
uint32 dstHeight = destinationRect.IntegerHeight() + 1;
|
||||
uint32 srcWidth = bitmap.width();
|
||||
uint32 srcHeight = bitmap.height();
|
||||
|
||||
// Do not calculate more filter weights than necessary and also
|
||||
// keep the stack based allocations reasonably sized
|
||||
const BRegion& clippingRegion = *painter->ClippingRegion();
|
||||
if (clippingRegion.Frame().IntegerWidth() + 1 < (int32)dstWidth)
|
||||
dstWidth = clippingRegion.Frame().IntegerWidth() + 1;
|
||||
if (clippingRegion.Frame().IntegerHeight() + 1 < (int32)dstHeight)
|
||||
dstHeight = clippingRegion.Frame().IntegerHeight() + 1;
|
||||
|
||||
// When calculating less filter weights than specified by
|
||||
// destinationRect, we need to compensate the offset.
|
||||
uint32 filterWeightXIndexOffset = 0;
|
||||
uint32 filterWeightYIndexOffset = 0;
|
||||
if (clippingRegion.Frame().left > destinationRect.left) {
|
||||
filterWeightXIndexOffset = (int32)(clippingRegion.Frame().left
|
||||
- destinationRect.left);
|
||||
}
|
||||
if (clippingRegion.Frame().top > destinationRect.top) {
|
||||
filterWeightYIndexOffset = (int32)(clippingRegion.Frame().top
|
||||
- destinationRect.top);
|
||||
}
|
||||
|
||||
// should not pose a problem with stack overflows
|
||||
// (needs around 6Kb for 1920x1200)
|
||||
uint16 xIndices[dstWidth];
|
||||
uint16 yIndices[dstHeight];
|
||||
|
||||
// Extract the cropping information for the source bitmap,
|
||||
// If only a part of the source bitmap is to be drawn with scale,
|
||||
// the offset will be different from the destinationRect left top
|
||||
// corner.
|
||||
const int32 xBitmapShift = (int32)(destinationRect.left - offset.x);
|
||||
const int32 yBitmapShift = (int32)(destinationRect.top - offset.y);
|
||||
|
||||
for (uint32 i = 0; i < dstWidth; i++) {
|
||||
// index into source
|
||||
uint16 index = (uint16)((i + filterWeightXIndexOffset) * srcWidth
|
||||
/ (srcWidth * scaleX));
|
||||
// round down to get the left pixel
|
||||
xIndices[i] = index;
|
||||
// handle cropped source bitmap
|
||||
xIndices[i] += xBitmapShift;
|
||||
// precompute index for 32 bit pixels
|
||||
xIndices[i] *= 4;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < dstHeight; i++) {
|
||||
// index into source
|
||||
uint16 index = (uint16)((i + filterWeightYIndexOffset) * srcHeight
|
||||
/ (srcHeight * scaleY));
|
||||
// round down to get the top pixel
|
||||
yIndices[i] = index;
|
||||
// handle cropped source bitmap
|
||||
yIndices[i] += yBitmapShift;
|
||||
}
|
||||
//printf("X: %d ... %d, %d (%ld or %f)\n",
|
||||
// xIndices[0], xIndices[dstWidth - 2], xIndices[dstWidth - 1],
|
||||
// dstWidth, srcWidth * scaleX);
|
||||
//printf("Y: %d ... %d, %d (%ld or %f)\n",
|
||||
// yIndices[0], yIndices[dstHeight - 2], yIndices[dstHeight - 1],
|
||||
// dstHeight, srcHeight * scaleY);
|
||||
|
||||
const int32 left = (int32)destinationRect.left;
|
||||
const int32 top = (int32)destinationRect.top;
|
||||
const int32 right = (int32)destinationRect.right;
|
||||
const int32 bottom = (int32)destinationRect.bottom;
|
||||
|
||||
const uint32 dstBPR = aggInterface.fBuffer.stride();
|
||||
|
||||
renderer_base& baseRenderer = aggInterface.fBaseRenderer;
|
||||
|
||||
// iterate over clipping boxes
|
||||
baseRenderer.first_clip_box();
|
||||
do {
|
||||
const int32 x1 = max_c(baseRenderer.xmin(), left);
|
||||
const int32 x2 = min_c(baseRenderer.xmax(), right);
|
||||
if (x1 > x2)
|
||||
continue;
|
||||
|
||||
int32 y1 = max_c(baseRenderer.ymin(), top);
|
||||
int32 y2 = min_c(baseRenderer.ymax(), bottom);
|
||||
if (y1 > y2)
|
||||
continue;
|
||||
|
||||
// buffer offset into destination
|
||||
uint8* dst = aggInterface.fBuffer.row_ptr(y1) + x1 * 4;
|
||||
|
||||
// x and y are needed as indeces into the wheight arrays, so the
|
||||
// offset into the target buffer needs to be compensated
|
||||
const int32 xIndexL = x1 - left - filterWeightXIndexOffset;
|
||||
const int32 xIndexR = x2 - left - filterWeightXIndexOffset;
|
||||
y1 -= top + filterWeightYIndexOffset;
|
||||
y2 -= top + filterWeightYIndexOffset;
|
||||
|
||||
//printf("x: %ld - %ld\n", xIndexL, xIndexR);
|
||||
//printf("y: %ld - %ld\n", y1, y2);
|
||||
|
||||
for (; y1 <= y2; y1++) {
|
||||
// buffer offset into source (top row)
|
||||
register const uint8* src = bitmap.row_ptr(yIndices[y1]);
|
||||
// buffer handle for destination to be incremented per pixel
|
||||
register uint32* d = (uint32*)dst;
|
||||
|
||||
for (int32 x = xIndexL; x <= xIndexR; x++) {
|
||||
*d = *(uint32*)(src + xIndices[x]);
|
||||
d++;
|
||||
}
|
||||
dst += dstBPR;
|
||||
}
|
||||
} while (baseRenderer.next_clip_box());
|
||||
|
||||
//printf("draw bitmap %.5fx%.5f: %lld\n", xScale, yScale,
|
||||
// system_time() - now);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // DRAW_BITMAP_NEAREST_NEIGHBOR_H
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 2009, Christian Packmann.
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* Copyright 2005-2014, Stephan Aßmus <superstippi@gmx.de>.
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DRAW_BITMAP_NO_SCALE_H
|
||||
#define DRAW_BITMAP_NO_SCALE_H
|
||||
|
||||
#include "IntPoint.h"
|
||||
#include "IntRect.h"
|
||||
#include "Painter.h"
|
||||
|
||||
|
||||
template<class BlendType>
|
||||
struct DrawBitmapNoScale {
|
||||
public:
|
||||
void
|
||||
Draw(PainterAggInterface& aggInterface, agg::rendering_buffer& bitmap,
|
||||
uint32 bytesPerSourcePixel, IntPoint offset, BRect destinationRect)
|
||||
{
|
||||
// NOTE: this would crash if destinationRect was large enough to read
|
||||
// outside the bitmap, so make sure this is not the case before calling
|
||||
// this function!
|
||||
uint8* dst = aggInterface.fBuffer.row_ptr(0);
|
||||
const uint32 dstBPR = aggInterface.fBuffer.stride();
|
||||
|
||||
const uint8* src = bitmap.row_ptr(0);
|
||||
const uint32 srcBPR = bitmap.stride();
|
||||
|
||||
const int32 left = (int32)destinationRect.left;
|
||||
const int32 top = (int32)destinationRect.top;
|
||||
const int32 right = (int32)destinationRect.right;
|
||||
const int32 bottom = (int32)destinationRect.bottom;
|
||||
|
||||
#if DEBUG_DRAW_BITMAP
|
||||
if (left - offset.x < 0
|
||||
|| left - offset.x >= (int32)bitmap.width()
|
||||
|| right - offset.x >= (int32)srcBuffer.width()
|
||||
|| top - offset.y < 0
|
||||
|| top - offset.y >= (int32)bitmap.height()
|
||||
|| bottom - offset.y >= (int32)bitmap.height()) {
|
||||
char message[256];
|
||||
sprintf(message, "reading outside of bitmap (%ld, %ld, %ld, %ld) "
|
||||
"(%d, %d) (%ld, %ld)",
|
||||
left - offset.x, top - offset.y,
|
||||
right - offset.x, bottom - offset.y,
|
||||
bitmap.width(), bitmap.height(), offset.x, offset.y);
|
||||
debugger(message);
|
||||
}
|
||||
#endif
|
||||
|
||||
fColorMap = SystemPalette();
|
||||
fAlphaMask = aggInterface.fClippedAlphaMask;
|
||||
renderer_base& baseRenderer = aggInterface.fBaseRenderer;
|
||||
|
||||
// copy rects, iterate over clipping boxes
|
||||
baseRenderer.first_clip_box();
|
||||
do {
|
||||
fRect.left = max_c(baseRenderer.xmin(), left);
|
||||
fRect.right = min_c(baseRenderer.xmax(), right);
|
||||
if (fRect.left <= fRect.right) {
|
||||
fRect.top = max_c(baseRenderer.ymin(), top);
|
||||
fRect.bottom = min_c(baseRenderer.ymax(), bottom);
|
||||
if (fRect.top <= fRect.bottom) {
|
||||
uint8* dstHandle = dst + fRect.top * dstBPR
|
||||
+ fRect.left * 4;
|
||||
const uint8* srcHandle = src
|
||||
+ (fRect.top - offset.y) * srcBPR
|
||||
+ (fRect.left - offset.x) * bytesPerSourcePixel;
|
||||
|
||||
for (; fRect.top <= fRect.bottom; fRect.top++) {
|
||||
static_cast<BlendType*>(this)->BlendRow(dstHandle,
|
||||
srcHandle, fRect.right - fRect.left + 1);
|
||||
|
||||
dstHandle += dstBPR;
|
||||
srcHandle += srcBPR;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (baseRenderer.next_clip_box());
|
||||
}
|
||||
|
||||
protected:
|
||||
IntRect fRect;
|
||||
const rgb_color* fColorMap;
|
||||
const agg::clipped_alpha_mask* fAlphaMask;
|
||||
};
|
||||
|
||||
|
||||
struct CMap8Copy : public DrawBitmapNoScale<CMap8Copy>
|
||||
{
|
||||
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
|
||||
{
|
||||
uint32* d = (uint32*)dst;
|
||||
const uint8* s = src;
|
||||
while (numPixels--) {
|
||||
const rgb_color c = fColorMap[*s++];
|
||||
*d++ = (c.alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CMap8Over : public DrawBitmapNoScale<CMap8Over>
|
||||
{
|
||||
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
|
||||
{
|
||||
uint32* d = (uint32*)dst;
|
||||
const uint8* s = src;
|
||||
while (numPixels--) {
|
||||
const rgb_color c = fColorMap[*s++];
|
||||
if (c.alpha)
|
||||
*d = (c.alpha << 24) | (c.red << 16)
|
||||
| (c.green << 8) | (c.blue);
|
||||
d++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Bgr32Copy : public DrawBitmapNoScale<Bgr32Copy>
|
||||
{
|
||||
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
|
||||
{
|
||||
memcpy(dst, src, numPixels * 4);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Bgr32Over : public DrawBitmapNoScale<Bgr32Over>
|
||||
{
|
||||
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
|
||||
{
|
||||
uint32* d = (uint32*)dst;
|
||||
uint32* s = (uint32*)src;
|
||||
while (numPixels--) {
|
||||
if (*s != B_TRANSPARENT_MAGIC_RGBA32)
|
||||
*(uint32*)d = *(uint32*)s;
|
||||
d++;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Bgr32Alpha : public DrawBitmapNoScale<Bgr32Alpha>
|
||||
{
|
||||
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
|
||||
{
|
||||
uint32* d = (uint32*)dst;
|
||||
int32 bytes = numPixels * 4;
|
||||
uint8 buffer[bytes];
|
||||
uint8* b = buffer;
|
||||
while (numPixels--) {
|
||||
if (src[3] == 255) {
|
||||
*(uint32*)b = *(uint32*)src;
|
||||
} else {
|
||||
*(uint32*)b = *d;
|
||||
b[0] = ((src[0] - b[0]) * src[3] + (b[0] << 8)) >> 8;
|
||||
b[1] = ((src[1] - b[1]) * src[3] + (b[1] << 8)) >> 8;
|
||||
b[2] = ((src[2] - b[2]) * src[3] + (b[2] << 8)) >> 8;
|
||||
}
|
||||
d++;
|
||||
b += 4;
|
||||
src += 4;
|
||||
}
|
||||
memcpy(dst, buffer, bytes);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Bgr32CopyMasked : public DrawBitmapNoScale<Bgr32CopyMasked>
|
||||
{
|
||||
void BlendRow(uint8* dst, const uint8* src, int32 numPixels)
|
||||
{
|
||||
uint8 covers[numPixels];
|
||||
fAlphaMask->get_hspan(fRect.left, fRect.top, covers, numPixels);
|
||||
|
||||
uint32* destination = (uint32*)dst;
|
||||
uint32* source = (uint32*)src;
|
||||
uint8* mask = (uint8*)&covers[0];
|
||||
|
||||
while (numPixels--) {
|
||||
if (*mask != 0)
|
||||
*destination = *source;
|
||||
destination++;
|
||||
source++;
|
||||
mask++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // DRAW_BITMAP_NO_SCALE_H
|
||||
@@ -43,7 +43,7 @@ blend_pixel_alpha_pc(int x, int y, const color_type& c, uint8 cover,
|
||||
|
||||
// blend_hline_alpha_pc
|
||||
void
|
||||
blend_hline_alpha_pc(int x, int y, unsigned len,
|
||||
blend_hline_alpha_pc(int x, int y, unsigned len,
|
||||
const color_type& c, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
@@ -52,7 +52,7 @@ blend_hline_alpha_pc(int x, int y, unsigned len,
|
||||
rgb_color color = pattern->ColorAt(x, y);
|
||||
uint16 alpha = color.alpha * cover;
|
||||
if (alpha) {
|
||||
if (alpha == 255) {
|
||||
if (alpha == 255 * 255) {
|
||||
ASSIGN_ALPHA_PC(p, color.red, color.green, color.blue);
|
||||
} else {
|
||||
BLEND_ALPHA_PC(p, color.red, color.green, color.blue, alpha);
|
||||
@@ -65,7 +65,7 @@ blend_hline_alpha_pc(int x, int y, unsigned len,
|
||||
|
||||
// blend_solid_hspan_alpha_pc
|
||||
void
|
||||
blend_solid_hspan_alpha_pc(int x, int y, unsigned len,
|
||||
blend_solid_hspan_alpha_pc(int x, int y, unsigned len,
|
||||
const color_type& c, const uint8* covers,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
@@ -88,7 +88,7 @@ blend_solid_hspan_alpha_pc(int x, int y, unsigned len,
|
||||
|
||||
// blend_solid_vspan_alpha_pc
|
||||
void
|
||||
blend_solid_vspan_alpha_pc(int x, int y, unsigned len,
|
||||
blend_solid_vspan_alpha_pc(int x, int y, unsigned len,
|
||||
const color_type& c, const uint8* covers,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
@@ -112,8 +112,8 @@ blend_solid_vspan_alpha_pc(int x, int y, unsigned len,
|
||||
|
||||
// blend_color_hspan_alpha_pc
|
||||
void
|
||||
blend_color_hspan_alpha_pc(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
blend_color_hspan_alpha_pc(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const uint8* covers, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>
|
||||
* Copyright 2015, Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
* DrawingMode implementing B_OP_ALPHA in "Pixel Composite" mode on B_RGBA32.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DRAWING_MODE_ALPHA_PC_SOLID_H
|
||||
#define DRAWING_MODE_ALPHA_PC_SOLID_H
|
||||
|
||||
#include "DrawingMode.h"
|
||||
|
||||
|
||||
#define BLEND_ALPHA_PC(d, r, g, b, a) \
|
||||
{ \
|
||||
BLEND_COMPOSITE16(d, r, g, b, a); \
|
||||
}
|
||||
|
||||
|
||||
#define ASSIGN_ALPHA_PC(d, r, g, b) \
|
||||
{ \
|
||||
d[0] = (b); \
|
||||
d[1] = (g); \
|
||||
d[2] = (r); \
|
||||
d[3] = 255; \
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
blend_pixel_alpha_pc_solid(int x, int y, const color_type& color, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler*)
|
||||
{
|
||||
uint8* p = buffer->row_ptr(y) + (x << 2);
|
||||
uint16 alpha = color.a * cover;
|
||||
if (alpha == 255 * 255) {
|
||||
ASSIGN_ALPHA_PC(p, color.r, color.g, color.b);
|
||||
} else {
|
||||
BLEND_ALPHA_PC(p, color.r, color.g, color.b, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
blend_hline_alpha_pc_solid(int x, int y, unsigned len,
|
||||
const color_type& color, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler*)
|
||||
{
|
||||
uint8* p = buffer->row_ptr(y) + (x << 2);
|
||||
uint16 alpha = color.a * cover;
|
||||
if (alpha == 0)
|
||||
return;
|
||||
|
||||
if (alpha == 255 * 255) {
|
||||
do {
|
||||
ASSIGN_ALPHA_PC(p, color.r, color.g, color.b);
|
||||
p += 4;
|
||||
} while(--len);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
BLEND_ALPHA_PC(p, color.r, color.g, color.b, alpha);
|
||||
p += 4;
|
||||
} while(--len);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
blend_solid_hspan_alpha_pc_solid(int x, int y, unsigned len,
|
||||
const color_type& color, const uint8* covers,
|
||||
agg_buffer* buffer, const PatternHandler*)
|
||||
{
|
||||
uint8* p = buffer->row_ptr(y) + (x << 2);
|
||||
do {
|
||||
uint16 alpha = color.a * *covers;
|
||||
if (alpha) {
|
||||
if(alpha == 255 * 255) {
|
||||
ASSIGN_ALPHA_PC(p, color.r, color.g, color.b);
|
||||
} else {
|
||||
BLEND_ALPHA_PC(p, color.r, color.g, color.b, alpha);
|
||||
}
|
||||
}
|
||||
covers++;
|
||||
p += 4;
|
||||
} while(--len);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
blend_solid_vspan_alpha_pc_solid(int x, int y, unsigned len,
|
||||
const color_type& color, const uint8* covers,
|
||||
agg_buffer* buffer, const PatternHandler*)
|
||||
{
|
||||
uint8* p = buffer->row_ptr(y) + (x << 2);
|
||||
do {
|
||||
uint16 alpha = color.a * *covers;
|
||||
if (alpha) {
|
||||
if (alpha == 255 * 255) {
|
||||
ASSIGN_ALPHA_PC(p, color.r, color.g, color.b);
|
||||
} else {
|
||||
BLEND_ALPHA_PC(p, color.r, color.g, color.b, alpha);
|
||||
}
|
||||
}
|
||||
covers++;
|
||||
p += buffer->stride();
|
||||
} while(--len);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
blend_color_hspan_alpha_pc_solid(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const uint8* covers, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler*)
|
||||
{
|
||||
uint8* p = buffer->row_ptr(y) + (x << 2);
|
||||
if (covers) {
|
||||
// non-solid opacity
|
||||
do {
|
||||
uint16 alpha = colors->a * *covers;
|
||||
if (alpha) {
|
||||
if (alpha == 255 * 255) {
|
||||
ASSIGN_ALPHA_PC(p, colors->r, colors->g, colors->b);
|
||||
} else {
|
||||
BLEND_ALPHA_PC(p, colors->r, colors->g, colors->b, alpha);
|
||||
}
|
||||
}
|
||||
covers++;
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
} else {
|
||||
// solid full opcacity
|
||||
uint16 alpha = colors->a * cover;
|
||||
if (alpha == 255 * 255) {
|
||||
do {
|
||||
ASSIGN_ALPHA_PC(p, colors->r, colors->g, colors->b);
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
// solid partial opacity
|
||||
} else if (alpha) {
|
||||
do {
|
||||
BLEND_ALPHA_PC(p, colors->r, colors->g, colors->b, alpha);
|
||||
p += 4;
|
||||
++colors;
|
||||
} while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // DRAWING_MODE_ALPHA_PC_SOLID_H
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32.
|
||||
* DrawingMode implementing B_OP_ALPHA in "Pixel Overlay" mode on B_RGBA32.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -43,7 +43,7 @@ blend_pixel_alpha_po(int x, int y, const color_type& c, uint8 cover,
|
||||
|
||||
// blend_hline_alpha_po
|
||||
void
|
||||
blend_hline_alpha_po(int x, int y, unsigned len,
|
||||
blend_hline_alpha_po(int x, int y, unsigned len,
|
||||
const color_type& c, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
@@ -65,7 +65,7 @@ blend_hline_alpha_po(int x, int y, unsigned len,
|
||||
|
||||
// blend_solid_hspan_alpha_po
|
||||
void
|
||||
blend_solid_hspan_alpha_po(int x, int y, unsigned len,
|
||||
blend_solid_hspan_alpha_po(int x, int y, unsigned len,
|
||||
const color_type& c, const uint8* covers,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ blend_solid_hspan_alpha_po(int x, int y, unsigned len,
|
||||
|
||||
// blend_solid_vspan_alpha_po
|
||||
void
|
||||
blend_solid_vspan_alpha_po(int x, int y, unsigned len,
|
||||
blend_solid_vspan_alpha_po(int x, int y, unsigned len,
|
||||
const color_type& c, const uint8* covers,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
@@ -114,8 +114,8 @@ blend_solid_vspan_alpha_po(int x, int y, unsigned len,
|
||||
|
||||
// blend_color_hspan_alpha_po
|
||||
void
|
||||
blend_color_hspan_alpha_po(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
blend_color_hspan_alpha_po(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const uint8* covers, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
* DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32.
|
||||
* DrawingMode implementing B_OP_ALPHA in "Pixel Overlay" mode on B_RGBA32.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32.
|
||||
* DrawingMode implementing B_OP_ALPHA in "Pixel Overlay" mode on B_RGBA32.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -27,7 +27,7 @@ blend_pixel_alpha_po_solid(int x, int y, const color_type& c, uint8 cover,
|
||||
|
||||
// blend_hline_alpha_po_solid
|
||||
void
|
||||
blend_hline_alpha_po_solid(int x, int y, unsigned len,
|
||||
blend_hline_alpha_po_solid(int x, int y, unsigned len,
|
||||
const color_type& c, uint8 cover,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
@@ -64,7 +64,7 @@ blend_hline_alpha_po_solid(int x, int y, unsigned len,
|
||||
|
||||
// blend_solid_hspan_alpha_po_solid
|
||||
void
|
||||
blend_solid_hspan_alpha_po_solid(int x, int y, unsigned len,
|
||||
blend_solid_hspan_alpha_po_solid(int x, int y, unsigned len,
|
||||
const color_type& c, const uint8* covers,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
@@ -88,7 +88,7 @@ blend_solid_hspan_alpha_po_solid(int x, int y, unsigned len,
|
||||
|
||||
// blend_solid_vspan_alpha_po_solid
|
||||
void
|
||||
blend_solid_vspan_alpha_po_solid(int x, int y, unsigned len,
|
||||
blend_solid_vspan_alpha_po_solid(int x, int y, unsigned len,
|
||||
const color_type& c, const uint8* covers,
|
||||
agg_buffer* buffer, const PatternHandler* pattern)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
* DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32.
|
||||
* DrawingMode implementing B_OP_ALPHA in "Pixel Overlay" mode on B_RGBA32.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "DrawingModeAlphaCO.h"
|
||||
#include "DrawingModeAlphaCOSolid.h"
|
||||
#include "DrawingModeAlphaPC.h"
|
||||
#include "DrawingModeAlphaPCSolid.h"
|
||||
#include "DrawingModeAlphaPO.h"
|
||||
#include "DrawingModeAlphaPOSolid.h"
|
||||
#include "DrawingModeBlend.h"
|
||||
@@ -211,7 +212,7 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
|
||||
case B_OP_COPY:
|
||||
if (text) {
|
||||
fBlendPixel = blend_pixel_copy_text;
|
||||
fBlendHLine = blend_hline_copy_text;
|
||||
fBlendHLine = blend_hline_copy_text;
|
||||
fBlendSolidHSpanSubpix = blend_solid_hspan_copy_text_subpix;
|
||||
fBlendSolidHSpan = blend_solid_hspan_copy_text;
|
||||
fBlendSolidVSpan = blend_solid_vspan_copy_text;
|
||||
@@ -327,12 +328,21 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
|
||||
}
|
||||
fBlendColorHSpan = blend_color_hspan_alpha_po;
|
||||
} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
|
||||
fBlendPixel = blend_pixel_alpha_pc;
|
||||
fBlendHLine = blend_hline_alpha_pc;
|
||||
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_pc_subpix;
|
||||
fBlendSolidHSpan = blend_solid_hspan_alpha_pc;
|
||||
fBlendSolidVSpan = blend_solid_vspan_alpha_pc;
|
||||
fBlendColorHSpan = blend_color_hspan_alpha_pc;
|
||||
if (fPatternHandler->IsSolid()) {
|
||||
fBlendPixel = blend_pixel_alpha_pc_solid;
|
||||
fBlendHLine = blend_hline_alpha_pc_solid;
|
||||
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_pc_subpix;
|
||||
fBlendSolidHSpan = blend_solid_hspan_alpha_pc_solid;
|
||||
fBlendSolidVSpan = blend_solid_vspan_alpha_pc_solid;
|
||||
fBlendColorHSpan = blend_color_hspan_alpha_pc_solid;
|
||||
} else {
|
||||
fBlendPixel = blend_pixel_alpha_pc;
|
||||
fBlendHLine = blend_hline_alpha_pc;
|
||||
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_pc_subpix;
|
||||
fBlendSolidHSpan = blend_solid_hspan_alpha_pc;
|
||||
fBlendSolidVSpan = blend_solid_vspan_alpha_pc;
|
||||
fBlendColorHSpan = blend_color_hspan_alpha_pc;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -483,7 +483,8 @@ ViewHWInterface::SetMode(const display_mode& mode)
|
||||
// has not been created either, but we need one to display
|
||||
// a real BWindow in the test environment.
|
||||
// be_app->Run() needs to be called in another thread
|
||||
BApplication* app = new BApplication("application/x-vnd.haiku-app-server");
|
||||
BApplication* app = new BApplication(
|
||||
"application/x-vnd.Haiku-test-app_server");
|
||||
app->Unlock();
|
||||
|
||||
thread_id appThread = spawn_thread(run_app_thread, "app thread",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* app_server.rdef
|
||||
*/
|
||||
|
||||
resource app_signature "application/x-vnd.Haiku-app-server";
|
||||
resource app_signature "application/x-vnd.Haiku-test-app_server";
|
||||
|
||||
resource app_flags B_EXCLUSIVE_LAUNCH ;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ static const bigtime_t kRosterSanityEventInterval = 1000000LL;
|
||||
*/
|
||||
Registrar::Registrar(status_t* _error)
|
||||
:
|
||||
BServer(B_REGISTRAR_SIGNATURE, "system:roster", -1, false, _error),
|
||||
BServer(B_REGISTRAR_SIGNATURE, B_REGISTRAR_PORT_NAME, -1, false, _error),
|
||||
fRoster(NULL),
|
||||
fClipboardHandler(NULL),
|
||||
fMIMEManager(NULL),
|
||||
|
||||
@@ -127,6 +127,7 @@ SharedLibrary libtestappserver.so :
|
||||
ProfileMessageSupport.cpp
|
||||
EventDispatcher.cpp
|
||||
EventStream.cpp
|
||||
TestServerLoopAdapter.cpp
|
||||
MessageLooper.cpp
|
||||
|
||||
# Decorator
|
||||
@@ -152,10 +153,12 @@ SharedLibrary libtestappserver.so :
|
||||
|
||||
AlphaMask.cpp
|
||||
BitmapHWInterface.cpp
|
||||
Canvas.cpp
|
||||
DesktopSettings.cpp
|
||||
DrawingContext.cpp
|
||||
Layer.cpp
|
||||
OffscreenServerWindow.cpp
|
||||
OffscreenWindow.cpp
|
||||
PictureBoundingBoxPlayer.cpp
|
||||
RegionPool.cpp
|
||||
Screen.cpp
|
||||
ScreenConfigurations.cpp
|
||||
@@ -173,9 +176,9 @@ SharedLibrary libtestappserver.so :
|
||||
[ BuildFeatureAttribute freetype : library ]
|
||||
;
|
||||
|
||||
Includes [ FGristFiles AppServer.cpp BitmapManager.cpp
|
||||
Includes [ FGristFiles AppServer.cpp BitmapManager.cpp Canvas.cpp
|
||||
ClientMemoryAllocator.cpp Desktop.cpp DesktopSettings.cpp
|
||||
DrawState.cpp DrawingContext.cpp DrawingEngine.cpp ServerApp.cpp
|
||||
DrawState.cpp DrawingEngine.cpp ServerApp.cpp
|
||||
ServerBitmap.cpp ServerCursor.cpp ServerFont.cpp ServerPicture.cpp
|
||||
ServerWindow.cpp View.cpp Window.cpp WorkspacesView.cpp
|
||||
$(decorator_src) $(font_src) ]
|
||||
@@ -249,6 +252,7 @@ SubInclude HAIKU_TOP src tests servers app statusbar ;
|
||||
SubInclude HAIKU_TOP src tests servers app stress_test ;
|
||||
SubInclude HAIKU_TOP src tests servers app textview ;
|
||||
SubInclude HAIKU_TOP src tests servers app transformation ;
|
||||
SubInclude HAIKU_TOP src tests servers app unit_tests ;
|
||||
SubInclude HAIKU_TOP src tests servers app view_state ;
|
||||
SubInclude HAIKU_TOP src tests servers app view_transit ;
|
||||
SubInclude HAIKU_TOP src tests servers app window_creation ;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2015 Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include <TestSuite.h>
|
||||
#include <TestSuiteAddon.h>
|
||||
|
||||
#include "SimpleTransformTest.h"
|
||||
|
||||
|
||||
BTestSuite*
|
||||
getTestSuite()
|
||||
{
|
||||
BTestSuite* suite = new BTestSuite("AppServerUnitTests");
|
||||
|
||||
SimpleTransformTest::AddTests(*suite);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
SubDir HAIKU_TOP src tests servers app unit_tests ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app ] : true ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src servers app ] ;
|
||||
|
||||
UnitTestLib app_server_unit_tests.so :
|
||||
AppServerUnitTestAddOn.cpp
|
||||
|
||||
IntPoint.cpp
|
||||
IntRect.cpp
|
||||
SimpleTransformTest.cpp
|
||||
|
||||
: be [ TargetLibstdc++ ]
|
||||
;
|
||||
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright 2015 Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "SimpleTransformTest.h"
|
||||
|
||||
#include "IntPoint.h"
|
||||
#include "IntRect.h"
|
||||
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformPoint()
|
||||
{
|
||||
BPoint point(1.0, 1.0);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 10.0);
|
||||
specimen.Apply(&point);
|
||||
CPPUNIT_ASSERT(point == BPoint(11.0, 11.0));
|
||||
|
||||
specimen.AddOffset(10.0, 10.0);
|
||||
point.Set(0.0, 0.0);
|
||||
specimen.Apply(&point);
|
||||
CPPUNIT_ASSERT(point == BPoint(20.0, 20.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformIntPoint()
|
||||
{
|
||||
IntPoint point(1, 1);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 10.0);
|
||||
specimen.Apply(&point);
|
||||
CPPUNIT_ASSERT(point == BPoint(11.0, 11.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformRect()
|
||||
{
|
||||
BRect rect(5.0, 10.0, 15.0, 20.0);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 10.0);
|
||||
specimen.Apply(&rect);
|
||||
CPPUNIT_ASSERT(rect == BRect(15.0, 20.0, 25.0, 30.0));
|
||||
|
||||
specimen.SetScale(2.5);
|
||||
specimen.Apply(&rect);
|
||||
CPPUNIT_ASSERT(rect == BRect(47.5, 60.0, 72.5, 85.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformIntRect()
|
||||
{
|
||||
IntRect rect(5, 10, 15, 20);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 10.0);
|
||||
specimen.Apply(&rect);
|
||||
CPPUNIT_ASSERT(rect == IntRect(15, 20, 25, 30));
|
||||
|
||||
specimen.SetScale(2);
|
||||
specimen.Apply(&rect);
|
||||
CPPUNIT_ASSERT(rect == BRect(40, 50, 60, 70));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformRegion()
|
||||
{
|
||||
BRegion region;
|
||||
region.Include(BRect( 5.0, 5.0, 20.0, 20.0));
|
||||
region.Include(BRect(10.0, 10.0, 30.0, 30.0));
|
||||
region.Exclude(BRect(10.0, 20.0, 20.0, 25.0));
|
||||
|
||||
BRegion reference1 = region;
|
||||
reference1.OffsetBy(10, 20);
|
||||
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.Apply(®ion);
|
||||
CPPUNIT_ASSERT(region == reference1);
|
||||
|
||||
specimen.SetScale(2.5);
|
||||
|
||||
BRegion reference2;
|
||||
reference2.Include(BRect(47.0, 82.0, 87.0, 122.0));
|
||||
reference2.Include(BRect(60.0, 95.0, 112.0, 147.0));
|
||||
reference2.Exclude(BRect(60.0, 120.0, 86.0, 134.0));
|
||||
|
||||
specimen.Apply(®ion);
|
||||
CPPUNIT_ASSERT(region == reference2);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformGradientLinear()
|
||||
{
|
||||
BGradientLinear gradient(10.0, 20.0, 30.0, 40.0);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.SetScale(2.5);
|
||||
specimen.Apply(&gradient);
|
||||
CPPUNIT_ASSERT(gradient.Start() == BPoint(35.0, 70.0));
|
||||
CPPUNIT_ASSERT(gradient.End() == BPoint(85.0, 120.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformGradientRadial()
|
||||
{
|
||||
BGradientRadial gradient(10.0, 20.0, 10.0);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.SetScale(2.5);
|
||||
specimen.Apply(&gradient);
|
||||
CPPUNIT_ASSERT(gradient.Center() == BPoint(35.0, 70.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformGradientRadialFocus()
|
||||
{
|
||||
BGradientRadialFocus gradient(10.0, 20.0, 10.0, 30.0, 40.0);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.SetScale(2.5);
|
||||
specimen.Apply(&gradient);
|
||||
CPPUNIT_ASSERT(gradient.Center() == BPoint(35.0, 70.0));
|
||||
CPPUNIT_ASSERT(gradient.Focal() == BPoint(85.0, 120.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformGradientDiamond()
|
||||
{
|
||||
BGradientDiamond gradient(10.0, 20.0);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.SetScale(2.5);
|
||||
specimen.Apply(&gradient);
|
||||
CPPUNIT_ASSERT(gradient.Center() == BPoint(35.0, 70.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformGradientConic()
|
||||
{
|
||||
BGradientConic gradient(10.0, 20.0, 10.0);
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.SetScale(2.5);
|
||||
specimen.Apply(&gradient);
|
||||
CPPUNIT_ASSERT(gradient.Center() == BPoint(35.0, 70.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformPointArray()
|
||||
{
|
||||
BPoint points[3];
|
||||
points[0].Set(10.0, 20.0);
|
||||
points[1].Set(30.0, 40.0);
|
||||
points[2].Set(50.0, 60.0);
|
||||
BPoint transformedPoints[3];
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.Apply(&transformedPoints[0], &points[0], 3);
|
||||
CPPUNIT_ASSERT(transformedPoints[0] == BPoint(20.0, 40.0));
|
||||
CPPUNIT_ASSERT(transformedPoints[1] == BPoint(40.0, 60.0));
|
||||
CPPUNIT_ASSERT(transformedPoints[2] == BPoint(60.0, 80.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformRectArray()
|
||||
{
|
||||
BRect rects[3];
|
||||
rects[0].Set( 5.0, 10.0, 15.0, 20.0);
|
||||
rects[1].Set(15.0, 20.0, 25.0, 30.0);
|
||||
rects[2].Set(25.0, 30.0, 35.0, 40.0);
|
||||
BRect transformedRects[3];
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.SetScale(2.5);
|
||||
specimen.Apply(&transformedRects[0], &rects[0], 3);
|
||||
CPPUNIT_ASSERT(transformedRects[0] == BRect(22.5, 45.0, 47.5, 70.0));
|
||||
CPPUNIT_ASSERT(transformedRects[1] == BRect(47.5, 70.0, 72.5, 95.0));
|
||||
CPPUNIT_ASSERT(transformedRects[2] == BRect(72.5, 95.0, 97.5, 120.0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimpleTransformTest::TransformRegionArray()
|
||||
{
|
||||
BRegion regions[2];
|
||||
regions[0].Include(BRect( 5.0, 5.0, 20.0, 20.0));
|
||||
regions[0].Include(BRect(10.0, 10.0, 30.0, 30.0));
|
||||
regions[0].Exclude(BRect(10.0, 20.0, 20.0, 25.0));
|
||||
regions[1].Include(BRect( 5.0, 5.0, 20.0, 20.0));
|
||||
regions[1].Include(BRect(10.0, 10.0, 30.0, 30.0));
|
||||
regions[1].Exclude(BRect(10.0, 20.0, 20.0, 25.0));
|
||||
BRegion transformedRegions[3];
|
||||
SimpleTransform specimen;
|
||||
specimen.AddOffset(10.0, 20.0);
|
||||
specimen.SetScale(2.5);
|
||||
specimen.Apply(&transformedRegions[0], ®ions[0], 2);
|
||||
BRegion reference;
|
||||
reference.Include(BRect(22.0, 32.0, 62.0, 72.0));
|
||||
reference.Include(BRect(35.0, 45.0, 87.0, 97.0));
|
||||
reference.Exclude(BRect(35.0, 70.0, 61.0, 84.0));
|
||||
|
||||
CPPUNIT_ASSERT(transformedRegions[0] == reference);
|
||||
CPPUNIT_ASSERT(transformedRegions[1] == reference);
|
||||
}
|
||||
|
||||
|
||||
/* static */ void
|
||||
SimpleTransformTest::AddTests(BTestSuite& parent)
|
||||
{
|
||||
CppUnit::TestSuite* const suite = new CppUnit::TestSuite(
|
||||
"SimpleTransformTest");
|
||||
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformPoint",
|
||||
&SimpleTransformTest::TransformPoint));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformIntPoint",
|
||||
&SimpleTransformTest::TransformIntPoint));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformRect",
|
||||
&SimpleTransformTest::TransformRect));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformIntRect",
|
||||
&SimpleTransformTest::TransformIntRect));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformRegion",
|
||||
&SimpleTransformTest::TransformRegion));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformGradientLinear",
|
||||
&SimpleTransformTest::TransformGradientLinear));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformGradientRadial",
|
||||
&SimpleTransformTest::TransformGradientRadial));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformGradientRadialFocus",
|
||||
&SimpleTransformTest::TransformGradientRadialFocus));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformGradientDiamond",
|
||||
&SimpleTransformTest::TransformGradientDiamond));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformGradientConic",
|
||||
&SimpleTransformTest::TransformGradientConic));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformPointArray",
|
||||
&SimpleTransformTest::TransformPointArray));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformRectArray",
|
||||
&SimpleTransformTest::TransformRectArray));
|
||||
suite->addTest(new CppUnit::TestCaller<SimpleTransformTest>(
|
||||
"SimpleTransformTest::TransformRegionArray",
|
||||
&SimpleTransformTest::TransformRegionArray));
|
||||
|
||||
parent.addTest("SimpleTransformTest", suite);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2015 Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef SIMPLE_TRANSFORM_TEST_H
|
||||
#define SIMPLE_TRANSFORM_TEST_H
|
||||
|
||||
#include <TestCase.h>
|
||||
#include <TestSuite.h>
|
||||
|
||||
#include "SimpleTransform.h"
|
||||
|
||||
|
||||
class SimpleTransformTest : public BTestCase {
|
||||
public:
|
||||
static void AddTests(BTestSuite& parent);
|
||||
|
||||
void TransformPoint();
|
||||
void TransformIntPoint();
|
||||
void TransformRect();
|
||||
void TransformIntRect();
|
||||
void TransformRegion();
|
||||
|
||||
void TransformGradientLinear();
|
||||
void TransformGradientRadial();
|
||||
void TransformGradientRadialFocus();
|
||||
void TransformGradientDiamond();
|
||||
void TransformGradientConic();
|
||||
|
||||
void TransformPointArray();
|
||||
void TransformRectArray();
|
||||
void TransformRegionArray();
|
||||
};
|
||||
|
||||
|
||||
#endif // SIMPLE_TRANSFORM_TEST_H
|
||||
@@ -110,7 +110,7 @@ Server test_registrar
|
||||
libstorage_kit_mime.a
|
||||
be localestub [ TargetLibstdc++ ]
|
||||
:
|
||||
registrar.rdef
|
||||
test_registrar.rdef
|
||||
;
|
||||
|
||||
if $(TARGET_PLATFORM) = libbe_test {
|
||||
|
||||
@@ -53,7 +53,7 @@ main(int argc, char* argv[])
|
||||
while (get_next_thread_info(teamInfo.team, &threadCookie, &threadInfo)
|
||||
== B_OK) {
|
||||
// search for the roster thread
|
||||
if (!strcmp(threadInfo.name, "_roster_thread_")) {
|
||||
if (!strcmp(threadInfo.name, "roster")) {
|
||||
port_id port = find_port("haiku-test:roster");
|
||||
port_info portInfo;
|
||||
if (get_port_info(port, &portInfo) == B_OK
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* registrar.rdef
|
||||
*/
|
||||
|
||||
resource app_signature "application/x-vnd.test-registrar";
|
||||
|
||||
resource app_flags B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP;
|
||||
/* the registrar's application flags are actually
|
||||
* ignored.
|
||||
* The actually used flags are set in TRoster::Init().
|
||||
*/
|
||||
|
||||
resource app_version {
|
||||
major = 1,
|
||||
middle = 0,
|
||||
minor = 0,
|
||||
|
||||
variety = B_APPV_ALPHA,
|
||||
internal = 0,
|
||||
|
||||
short_info = "registrar",
|
||||
long_info = "registrar ©2005-2008 Haiku Inc."
|
||||
};
|
||||
|
||||
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||
|
||||
resource vector_icon array {
|
||||
$"6E6369660704006B0500020006023BB8A43D8642BF898E3DBC1F4BAE5447805C"
|
||||
$"00E3AD00FFBC8F05020106023D66A73B07B6B9BEF73C1A2B48379549C4DE3D76"
|
||||
$"9564FF536E4402000602B898C93319083A5C163FF4CC4AB5EA4451BB00B58A00"
|
||||
$"FF8565030200060236EEF83B80F5BF3E743AB74A4B669742DBD600FFEFC0FFFF"
|
||||
$"DE7C05FF0D0A044D5B585B59594D530A0626484C5B4E594E32282626270A0426"
|
||||
$"484C5B4C3426270A0448542A452A2C48370A042C442C2D2A2C2A450A044C5B4E"
|
||||
$"594E324C340A04282626274C344E320A042A45485448512C4408023133313C08"
|
||||
$"023534353E08023936394008023D373D4208022E344040090A00010010011584"
|
||||
$"00040A0101011001178400040A020102000A030103000A040104000A04010500"
|
||||
$"0A050106000A050107000A06050C0B0A0908100117820004"
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
resource large_icon array {
|
||||
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFF00D9D9D90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFF00D98383D9D90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFF00D900008383D9D90000FFFFFFFFFFFFFFFFFF00000000FFFFFFFFFF"
|
||||
$"FFFFFFFF00D9008F00008383D9D9000000000000FFFF003FD9D9D90000FFFFFF"
|
||||
$"FFFFFFFF00D9008F8F8F00008383D9D900003F3F00003FD9D9D9D9D9D90000FF"
|
||||
$"FFFFFFFF00D9008F3F8F8F8F00008383D9D900003F3FAAAAD9D9D9D9D9D98300"
|
||||
$"FFFFFFFF00D9003F3F8F3F8F8F8F00008383D9D900008383AAAAD9D9D983AA00"
|
||||
$"FFFFFFFF00D9008F3F3F3F8F3F8F8F8F00008383D9D900003F3FAAAA83AAAA00"
|
||||
$"FFFFFFFF00D9008F3F8F3F8F3F8F8F8F8F8F00008383D9D900D93F3FAAAAAA00"
|
||||
$"FFFFFFFF00D9008F3F8F3F3F3F8F8F8F8F8F8F8F000083AA00D9D9D983AA0111"
|
||||
$"FFFFFFFF00D9008F8F8F3F8F3F8F8F8F8F8F8F8F8F0083AA00D9D9D9D9AA0017"
|
||||
$"FFFFFFFF00D9008F8F8F8F8F3F3F8F8F8F8F8F8F8F0083AA00D9D9D9D9830011"
|
||||
$"FFFFFFFF00D9008F8F8F8F8F8F8F3F8F8F8F8F8F8F0083AA00D9D9D983AA0111"
|
||||
$"FFFFFFFF00D900008F8F8F8F8F8F8F8F8F8F8F8F8F0083AA00D9D983AA001111"
|
||||
$"FFFFFFFF0000838300008F8F8F8F8F8F8F8F8F8F8F0083AA00D983AA001111FF"
|
||||
$"FFFFFFFFFF000000838300008F8F8F8F8F8F8F8F8F0083AA0083AA001111FFFF"
|
||||
$"FFFFFFFF003FD9830000838300008F8F8F8F8F8F8F0083AA00AA001111FFFFFF"
|
||||
$"FFFFFF003FD98383001E0000838300008F8F8F8F8F0083AA00001111FFFFFFFF"
|
||||
$"FFFF003FD98383031ED9D9830000838300008F8F8F0083AA001111FFFFFFFFFF"
|
||||
$"FF003FD98383003FD9D98383003F0000838300008F0083AA0011FFFFFFFFFFFF"
|
||||
$"003FD98383003FD9D98383003FD9D9D900008383000083AA0011FFFFFFFFFFFF"
|
||||
$"00D98383003FD9D98383003FD9D98383003F0000838383AA0011FFFFFFFFFFFF"
|
||||
$"FF0000003FD9D98383003FD9D98383003FD98383000083001111FFFFFFFFFFFF"
|
||||
$"FFFF003FD9D98383003FD9D98383003FD98383001111001111FFFFFFFFFFFFFF"
|
||||
$"FFFF00D9838306003FD9D98383003FD98383001111FFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFF0000001000D9D98383003FD98383001111FFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFFFFFFFF000000003FD98300001111FFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFFFFFFFFFFFFFFFF000000111111FFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
};
|
||||
|
||||
resource mini_icon array {
|
||||
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFF000000FFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FF03D9D9D90000FFFFFFFF0000FFFFFF"
|
||||
$"FF03D9B6B6D9D900000000D9D90000FF"
|
||||
$"FF03D9B669B6B6D9D90000AAAAD98300"
|
||||
$"FF03D9B6116868B6B6D9D9003FAAAA00"
|
||||
$"FF03D9B68F681B8FB683AA00D9D9AA00"
|
||||
$"FF03D9B68F181B8FB683AA003FD9AA01"
|
||||
$"FF03D9B6B68F188FB683AA00D9830011"
|
||||
$"FF03038383B6B68FB683AA00830011FF"
|
||||
$"FF00D933048383B6B683AA000011FFFF"
|
||||
$"00D98300D90303838383AA0011FFFFFF"
|
||||
$"008300D98300D90303030011FFFFFFFF"
|
||||
$"FF00D98300D900D9830011FFFFFFFFFF"
|
||||
$"FFFF0000000000000011FFFFFFFFFFFF"
|
||||
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
};
|
||||
|
||||
#endif // HAIKU_TARGET_PLATFORM_HAIKU
|
||||
Reference in New Issue
Block a user