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:
Julian Harnath
2015-11-10 23:09:54 +01:00
71 changed files with 5461 additions and 2390 deletions
+3
View File
@@ -505,6 +505,9 @@ public:
void DrawPictureAsync(const char* filename, void DrawPictureAsync(const char* filename,
long offset, BPoint where); long offset, BPoint where);
void BeginLayer(uint8 opacity);
void EndLayer();
status_t SetEventMask(uint32 mask, uint32 options = 0); status_t SetEventMask(uint32 mask, uint32 options = 0);
uint32 EventMask(); uint32 EventMask();
status_t SetMouseEventMask(uint32 mask, status_t SetMouseEventMask(uint32 mask,
+8 -1
View File
@@ -23,7 +23,14 @@ namespace BPrivate {
extern const char* kRAppLooperPortName; 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" #define B_REGISTRAR_AUTHENTICATION_PORT_NAME "auth"
+7
View File
@@ -7,6 +7,7 @@
* Jérôme Duval, [email protected] * Jérôme Duval, [email protected]
* Axel Dörfler, [email protected] * Axel Dörfler, [email protected]
* Andrej Spielmann, <[email protected]> * Andrej Spielmann, <[email protected]>
* Julian Harnath, <[email protected]>
*/ */
#ifndef APP_SERVER_PROTOCOL_H #ifndef APP_SERVER_PROTOCOL_H
#define APP_SERVER_PROTOCOL_H #define APP_SERVER_PROTOCOL_H
@@ -15,6 +16,10 @@
#include <SupportDefs.h> #include <SupportDefs.h>
#ifdef HAIKU_TARGET_PLATFORM_LIBBE_TEST
# define SERVER_PORT_NAME "haiku-test:app_server"
#endif
#if TEST_MODE #if TEST_MODE
# define SERVER_INPUT_PORT "haiku-test:input port" # define SERVER_INPUT_PORT "haiku-test:input port"
#endif #endif
@@ -319,6 +324,8 @@ enum {
AS_VIEW_SET_VIEW_BITMAP, AS_VIEW_SET_VIEW_BITMAP,
AS_VIEW_SET_PATTERN, AS_VIEW_SET_PATTERN,
AS_SET_CURRENT_VIEW, AS_SET_CURRENT_VIEW,
AS_VIEW_BEGIN_LAYER,
AS_VIEW_END_LAYER,
// BDirectWindow/BWindowScreen codes // BDirectWindow/BWindowScreen codes
AS_DIRECT_WINDOW_GET_SYNC_DATA, 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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Stefano Ceccherini, [email protected] * Stefano Ceccherini, [email protected]
* Julian Harnath, <[email protected]>
*/ */
#ifndef _PICTURE_DATA_WRITER_H #ifndef _PICTURE_DATA_WRITER_H
#define _PICTURE_DATA_WRITER_H #define _PICTURE_DATA_WRITER_H
@@ -17,6 +18,7 @@
#include <stack> #include <stack>
class Layer;
class BPositionIO; class BPositionIO;
class BRegion; class BRegion;
@@ -93,6 +95,8 @@ public:
status_t WriteDrawPicture(const BPoint& where, status_t WriteDrawPicture(const BPoint& where,
const int32& token); const int32& token);
status_t WriteBlendLayer(Layer* layer);
protected: protected:
// throw a status_t on error // throw a status_t on error
void BeginOp(const int16& op); void BeginOp(const int16& op);
@@ -23,6 +23,7 @@ class BAffineTransform;
class BList; class BList;
class BPicture; class BPicture;
class BShape; class BShape;
class Layer;
namespace BPrivate { namespace BPrivate {
@@ -83,6 +84,7 @@ struct picture_player_callbacks {
void (*set_blending_mode)(void* userData, source_alpha alphaSourceMode, void (*set_blending_mode)(void* userData, source_alpha alphaSourceMode,
alpha_function alphaFunctionMode); alpha_function alphaFunctionMode);
void (*set_transform)(void* userData, const BAffineTransform& transform); void (*set_transform)(void* userData, const BAffineTransform& transform);
void (*blend_layer)(void* userData, Layer* layer);
}; };
+2 -1
View File
@@ -52,10 +52,11 @@ enum {
B_PIC_SET_FONT_BPP = 0x0388, B_PIC_SET_FONT_BPP = 0x0388,
B_PIC_SET_FONT_FACE = 0x0389, B_PIC_SET_FONT_FACE = 0x0389,
B_PIC_SET_TRANSFORM = 0x0390, B_PIC_SET_TRANSFORM = 0x0390,
B_PIC_BLEND_LAYER = 0x0391
}; };
const static uint32 kOpsTableSize = 49; const static uint32 kOpsTableSize = 50;
#endif #endif
+60
View File
@@ -176,6 +176,9 @@ is_app_showing_modal_window(team_id team)
} }
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
/*! Creates a connection with the desktop. /*! Creates a connection with the desktop.
*/ */
status_t 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 } // namespace BPrivate
+13 -3
View File
@@ -2620,10 +2620,10 @@ BRoster::_InitMessenger()
DBG(OUT("BRoster::InitMessengers()\n")); DBG(OUT("BRoster::InitMessengers()\n"));
// find the registrar port // 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); port_id port = data.GetInt32("port", -1);
team_id team = data.GetInt32("team", -1); team_id team = data.GetInt32("team", -1);
@@ -2636,6 +2636,16 @@ BRoster::_InitMessenger()
B_PREFERRED_TOKEN); 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")); DBG(OUT("BRoster::InitMessengers() done\n"));
} }
+17 -1
View File
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Stefano Ceccherini, [email protected] * Stefano Ceccherini, [email protected]
* Julian Harnath, <[email protected]>
*/ */
#include <PictureDataWriter.h> #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 // private
void void
PictureDataWriter::BeginOp(const int16& op) PictureDataWriter::BeginOp(const int16& op)
+10
View File
@@ -1213,6 +1213,16 @@ PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData,
break; 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: default:
break; break;
} }
+24 -2
View File
@@ -7,6 +7,7 @@
* Axel Dörfler, axeld@pinc-software.de * Axel Dörfler, axeld@pinc-software.de
* Adrian Oanca, adioanca@cotty.iren.ro * Adrian Oanca, adioanca@cotty.iren.ro
* Ingo Weinhold. ingo_weinhold@gmx.de * 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 void
BView::Invalidate(BRect invalRect) BView::Invalidate(BRect invalRect)
{ {
@@ -5225,7 +5247,7 @@ BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
if (picture == NULL) { if (picture == NULL) {
fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE); fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
fOwner->fLink->Attach<int32>(-1); fOwner->fLink->Attach<int32>(-1);
// NOTE: No need to sync here, since the -1 token cannot // NOTE: No need to sync here, since the -1 token cannot
// become invalid on the server. // become invalid on the server.
} else { } 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 // the client creates BPictures on the stack, these BPictures may
// have issued a AS_DELETE_PICTURE command to the ServerApp when Draw() // have issued a AS_DELETE_PICTURE command to the ServerApp when Draw()
// goes out of scope, and the command is processed earlier in the // 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 // ServerWindow thread, which will then have the result that no
// ServerPicture is found of the token. // ServerPicture is found of the token.
if (sync) if (sync)
+6 -2
View File
@@ -48,7 +48,8 @@ uint32 gAppServerSIMDFlags = 0;
*/ */
AppServer::AppServer(status_t* status) 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") fDesktopLock("AppServerDesktopLock")
{ {
openlog("app_server", 0, LOG_DAEMON); openlog("app_server", 0, LOG_DAEMON);
@@ -153,7 +154,10 @@ AppServer::QuitRequested()
wait_for_thread(thread, &status); wait_for_thread(thread, &status);
} }
return BServer::QuitRequested(); delete this;
exit(0);
return SERVER_BASE::QuitRequested();
#else #else
return false; return false;
#endif #endif
+11 -3
View File
@@ -15,7 +15,6 @@
#include <Locker.h> #include <Locker.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <OS.h> #include <OS.h>
#include <Server.h>
#include <String.h> #include <String.h>
#include <Window.h> #include <Window.h>
@@ -23,12 +22,21 @@
#include "ServerConfig.h" #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 ServerApp;
class BitmapManager; class BitmapManager;
class Desktop; class Desktop;
class AppServer : public BServer { class AppServer : public SERVER_BASE {
public: public:
AppServer(status_t* status); AppServer(status_t* status);
virtual ~AppServer(); virtual ~AppServer();
@@ -39,7 +47,7 @@ public:
private: private:
Desktop* _CreateDesktop(uid_t userID, Desktop* _CreateDesktop(uid_t userID,
const char* targetScreen); const char* targetScreen);
Desktop* _FindDesktop(uid_t userID, virtual Desktop* _FindDesktop(uid_t userID,
const char* targetScreen); const char* targetScreen);
void _LaunchInputServer(); void _LaunchInputServer();
+289
View File
@@ -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);
}
+105
View File
@@ -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
+62 -94
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2008, Haiku. * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -8,6 +8,7 @@
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de * Axel Dörfler, axeld@pinc-software.de
* Michael Pfeiffer <laplace@users.sourceforge.net> * Michael Pfeiffer <laplace@users.sourceforge.net>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
//! Data classes for working with BView states and draw parameters //! Data classes for working with BView states and draw parameters
@@ -46,6 +47,7 @@ DrawState::DrawState()
fDrawingMode(B_OP_COPY), fDrawingMode(B_OP_COPY),
fAlphaSrcMode(B_PIXEL_ALPHA), fAlphaSrcMode(B_PIXEL_ALPHA),
fAlphaFncMode(B_ALPHA_OVERLAY), fAlphaFncMode(B_ALPHA_OVERLAY),
fDrawingModeLocked(false),
fPenLocation(0.0f, 0.0f), fPenLocation(0.0f, 0.0f),
fPenSize(1.0f), fPenSize(1.0f),
@@ -80,6 +82,7 @@ DrawState::DrawState(const DrawState& other)
fDrawingMode(other.fDrawingMode), fDrawingMode(other.fDrawingMode),
fAlphaSrcMode(other.fAlphaSrcMode), fAlphaSrcMode(other.fAlphaSrcMode),
fAlphaFncMode(other.fAlphaFncMode), fAlphaFncMode(other.fAlphaFncMode),
fDrawingModeLocked(other.fDrawingModeLocked),
fPenLocation(other.fPenLocation), fPenLocation(other.fPenLocation),
fPenSize(other.fPenSize), fPenSize(other.fPenSize),
@@ -107,8 +110,6 @@ DrawState::~DrawState()
{ {
delete fClippingRegion; delete fClippingRegion;
delete fPreviousState; delete fPreviousState;
if (fAlphaMask != NULL)
fAlphaMask->ReleaseReference();
} }
@@ -211,7 +212,7 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link)
ViewSetStateInfo info; ViewSetStateInfo info;
link.Read<ViewSetStateInfo>(&info); link.Read<ViewSetStateInfo>(&info);
fPenLocation = info.penLocation; fPenLocation = info.penLocation;
fPenSize = info.penSize; fPenSize = info.penSize;
fHighColor = info.highColor; 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 void
DrawState::SetClippingRegion(const BRegion* region) DrawState::SetClippingRegion(const BRegion* region)
{ {
@@ -407,8 +432,9 @@ DrawState::GetCombinedClippingRegion(BRegion* region) const
{ {
if (fClippingRegion != NULL) { if (fClippingRegion != NULL) {
BRegion localTransformedClipping(*fClippingRegion); BRegion localTransformedClipping(*fClippingRegion);
Transform(&localTransformedClipping); SimpleTransform penTransform;
Transform(penTransform);
penTransform.Apply(&localTransformedClipping);
if (fPreviousState != NULL if (fPreviousState != NULL
&& fPreviousState->GetCombinedClippingRegion(region)) { && fPreviousState->GetCombinedClippingRegion(region)) {
localTransformedClipping.IntersectWith(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 // NOTE: In BeOS, it wasn't possible to clip to a BPicture and keep
// regular custom clipping to a BRegion at the same time. // regular custom clipping to a BRegion at the same time.
if (fAlphaMask == mask) fAlphaMask.SetTo(mask);
return;
if (mask != NULL)
mask->AcquireReference();
if (fAlphaMask != NULL)
fAlphaMask->ReleaseReference();
fAlphaMask = mask;
if (fAlphaMask != NULL && fPreviousState != NULL)
fAlphaMask->SetPrevious(fPreviousState->fAlphaMask);
} }
AlphaMask* AlphaMask*
DrawState::GetAlphaMask() const DrawState::GetAlphaMask() const
{ {
return fAlphaMask; return fAlphaMask.Get();
} }
@@ -453,83 +469,19 @@ DrawState::GetAlphaMask() const
void void
DrawState::Transform(float* x, float* y) const DrawState::Transform(SimpleTransform& transform) const
{ {
// scale relative to origin, therefore transform.AddOffset(fCombinedOrigin.x, fCombinedOrigin.y);
// scale first then translate to transform.SetScale(fCombinedScale);
// origin
*x *= fCombinedScale;
*y *= fCombinedScale;
*x += fCombinedOrigin.x;
*y += fCombinedOrigin.y;
} }
void void
DrawState::InverseTransform(float* x, float* y) const DrawState::InverseTransform(SimpleTransform& transform) const
{ {
*x -= fCombinedOrigin.x; transform.AddOffset(-fCombinedOrigin.x, -fCombinedOrigin.y);
*y -= fCombinedOrigin.y; if (fCombinedScale != 0.0)
if (fCombinedScale != 0.0) { transform.SetScale(1.0 / fCombinedScale);
*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(&lt.x, &lt.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));
} }
@@ -557,21 +509,37 @@ DrawState::SetPattern(const Pattern& pattern)
} }
void bool
DrawState::SetDrawingMode(drawing_mode mode) 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 void
DrawState::SetBlendingMode(source_alpha srcMode, alpha_function fncMode) DrawState::SetDrawingModeLocked(bool locked)
{ {
fAlphaSrcMode = srcMode; fDrawingModeLocked = locked;
fAlphaFncMode = fncMode;
} }
void void
DrawState::SetPenLocation(BPoint location) DrawState::SetPenLocation(BPoint location)
{ {
+15 -12
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2008, Haiku. * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -7,6 +7,7 @@
* Adi Oanca <adioanca@mymail.ro> * Adi Oanca <adioanca@mymail.ro>
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de * Axel Dörfler, axeld@pinc-software.de
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
#ifndef _DRAW_STATE_H_ #ifndef _DRAW_STATE_H_
#define _DRAW_STATE_H_ #define _DRAW_STATE_H_
@@ -16,10 +17,12 @@
#include <GraphicsDefs.h> #include <GraphicsDefs.h>
#include <InterfaceDefs.h> #include <InterfaceDefs.h>
#include <Point.h> #include <Point.h>
#include <Referenceable.h>
#include <View.h> #include <View.h>
#include "ServerFont.h" #include "ServerFont.h"
#include "PatternHandler.h" #include "PatternHandler.h"
#include "SimpleTransform.h"
class AlphaMask; class AlphaMask;
class BRegion; class BRegion;
@@ -66,6 +69,9 @@ public:
{ return fTransform; } { return fTransform; }
BAffineTransform CombinedTransform() const BAffineTransform CombinedTransform() const
{ return fCombinedTransform; } { return fCombinedTransform; }
void SetTransformEnabled(bool enabled);
DrawState* Squash() const;
// additional clipping as requested by client // additional clipping as requested by client
void SetClippingRegion(const BRegion* region); void SetClippingRegion(const BRegion* region);
@@ -78,14 +84,8 @@ public:
AlphaMask* GetAlphaMask() const; AlphaMask* GetAlphaMask() const;
// coordinate transformations // coordinate transformations
void Transform(float* x, float* y) const; void Transform(SimpleTransform& transform) const;
void InverseTransform(float* x, float* y) const; void InverseTransform(SimpleTransform& transform) const;
void Transform(BPoint* point) const;
void Transform(BRect* rect) const;
void Transform(BRegion* region) const;
void InverseTransform(BPoint* point) const;
// color // color
void SetHighColor(rgb_color color); void SetHighColor(rgb_color color);
@@ -101,17 +101,19 @@ public:
{ return fPattern; } { return fPattern; }
// drawing/blending mode // drawing/blending mode
void SetDrawingMode(drawing_mode mode); bool SetDrawingMode(drawing_mode mode);
drawing_mode GetDrawingMode() const drawing_mode GetDrawingMode() const
{ return fDrawingMode; } { return fDrawingMode; }
void SetBlendingMode(source_alpha srcMode, bool SetBlendingMode(source_alpha srcMode,
alpha_function fncMode); alpha_function fncMode);
source_alpha AlphaSrcMode() const source_alpha AlphaSrcMode() const
{ return fAlphaSrcMode; } { return fAlphaSrcMode; }
alpha_function AlphaFncMode() const alpha_function AlphaFncMode() const
{ return fAlphaFncMode; } { return fAlphaFncMode; }
void SetDrawingModeLocked(bool locked);
// pen // pen
void SetPenLocation(BPoint location); void SetPenLocation(BPoint location);
BPoint PenLocation() const; BPoint PenLocation() const;
@@ -165,7 +167,7 @@ protected:
BRegion* fClippingRegion; BRegion* fClippingRegion;
AlphaMask* fAlphaMask; BReference<AlphaMask> fAlphaMask;
rgb_color fHighColor; rgb_color fHighColor;
rgb_color fLowColor; rgb_color fLowColor;
@@ -174,6 +176,7 @@ protected:
drawing_mode fDrawingMode; drawing_mode fDrawingMode;
source_alpha fAlphaSrcMode; source_alpha fAlphaSrcMode;
alpha_function fAlphaFncMode; alpha_function fAlphaFncMode;
bool fDrawingModeLocked;
BPoint fPenLocation; BPoint fPenLocation;
float fPenSize; float fPenSize;
-345
View File
@@ -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(&center);
ConvertToScreen(&center);
radial->SetCenter(center);
break;
}
case BGradient::TYPE_RADIAL_FOCUS:
{
BGradientRadialFocus* radialFocus = (BGradientRadialFocus*) gradient;
BPoint center = radialFocus->Center();
BPoint focal = radialFocus->Focal();
fDrawState->Transform(&center);
ConvertToScreen(&center);
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(&center);
ConvertToScreen(&center);
diamond->SetCenter(center);
break;
}
case BGradient::TYPE_CONIC:
{
BGradientConic* conic = (BGradientConic*) gradient;
BPoint center = conic->Center();
fDrawState->Transform(&center);
ConvertToScreen(&center);
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);
}
-111
View File
@@ -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
+7 -5
View File
@@ -32,10 +32,10 @@ local font_src =
; ;
UseBuildFeatureHeaders freetype ; UseBuildFeatureHeaders freetype ;
Includes [ FGristFiles AppServer.cpp BitmapManager.cpp Includes [ FGristFiles AppServer.cpp BitmapManager.cpp Canvas.cpp
ClientMemoryAllocator.cpp Desktop.cpp DesktopSettings.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 ServerBitmap.cpp ServerCursor.cpp ServerFont.cpp ServerPicture.cpp
ServerWindow.cpp View.cpp Window.cpp WorkspacesView.cpp ServerWindow.cpp View.cpp Window.cpp WorkspacesView.cpp
$(decorator_src) $(font_src) ] $(decorator_src) $(font_src) ]
: [ BuildFeatureAttribute freetype : headers ] ; : [ BuildFeatureAttribute freetype : headers ] ;
@@ -51,6 +51,7 @@ Server app_server :
AppServer.cpp AppServer.cpp
#BitfieldRegion.cpp #BitfieldRegion.cpp
BitmapManager.cpp BitmapManager.cpp
Canvas.cpp
ClientMemoryAllocator.cpp ClientMemoryAllocator.cpp
CursorData.cpp CursorData.cpp
CursorManager.cpp CursorManager.cpp
@@ -59,7 +60,6 @@ Server app_server :
DesktopListener.cpp DesktopListener.cpp
DesktopSettings.cpp DesktopSettings.cpp
DirectWindowInfo.cpp DirectWindowInfo.cpp
DrawingContext.cpp
DrawState.cpp DrawState.cpp
EventDispatcher.cpp EventDispatcher.cpp
EventStream.cpp EventStream.cpp
@@ -67,10 +67,12 @@ Server app_server :
InputManager.cpp InputManager.cpp
IntPoint.cpp IntPoint.cpp
IntRect.cpp IntRect.cpp
Layer.cpp
MessageLooper.cpp MessageLooper.cpp
MultiLocker.cpp MultiLocker.cpp
OffscreenServerWindow.cpp OffscreenServerWindow.cpp
OffscreenWindow.cpp OffscreenWindow.cpp
PictureBoundingBoxPlayer.cpp
ProfileMessageSupport.cpp ProfileMessageSupport.cpp
RGBColor.cpp RGBColor.cpp
RegionPool.cpp RegionPool.cpp
@@ -97,7 +99,7 @@ Server app_server :
# libraries # libraries
: :
libtranslation.so libbe.so libbnetapi.so 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 libasdrawing.a libpainter.a libagg.a
[ BuildFeatureAttribute freetype : library ] [ BuildFeatureAttribute freetype : library ]
libstackandtile.a liblinprog.a libtextencoding.so libshared.a libstackandtile.a liblinprog.a libtextencoding.so libshared.a
+216
View File
@@ -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(&region);
// 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;
}
+42
View File
@@ -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
+2 -2
View File
@@ -154,9 +154,9 @@ MessageLooper::_MessageLooper()
Lock(); Lock();
if (code == kMsgQuitLooper) { if (code == kMsgQuitLooper)
Quit(); Quit();
} else else
_DispatchMessage(code, receiver); _DispatchMessage(code, receiver);
Unlock(); 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
View File
@@ -1,11 +1,12 @@
/* /*
* Copyright 2001-2010, Haiku. * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Marc Flerackers (mflerackers@androme.be) * Marc Flerackers (mflerackers@androme.be)
* Stefano Ceccherini (stefano.ceccherini@gmail.com) * Stefano Ceccherini (stefano.ceccherini@gmail.com)
* Marcus Overhagen <marcus@overhagen.de> * Marcus Overhagen <marcus@overhagen.de>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
#include "ServerPicture.h" #include "ServerPicture.h"
@@ -18,6 +19,7 @@
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "DrawState.h" #include "DrawState.h"
#include "FontManager.h" #include "FontManager.h"
#include "Layer.h"
#include "ServerApp.h" #include "ServerApp.h"
#include "ServerBitmap.h" #include "ServerBitmap.h"
#include "ServerFont.h" #include "ServerFont.h"
@@ -45,7 +47,7 @@ using std::stack;
class ShapePainter : public BShapeIterator { class ShapePainter : public BShapeIterator {
public: public:
ShapePainter(DrawingContext* context); ShapePainter(Canvas* canvas);
virtual ~ShapePainter(); virtual ~ShapePainter();
status_t Iterate(const BShape* shape); status_t Iterate(const BShape* shape);
@@ -60,15 +62,15 @@ public:
void Draw(BRect frame, bool filled); void Draw(BRect frame, bool filled);
private: private:
DrawingContext* fContext; Canvas* fCanvas;
stack<uint32> fOpStack; stack<uint32> fOpStack;
stack<BPoint> fPtStack; 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(); fPtStack.pop();
} }
BPoint offset(fContext->CurrentState()->PenLocation()); BPoint offset(fCanvas->CurrentState()->PenLocation());
fContext->ConvertToScreenForDrawing(&offset); fCanvas->PenToScreenTransform().Apply(&offset);
fContext->GetDrawingEngine()->DrawShape(frame, opCount, opList, fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList,
ptCount, ptList, filled, offset, fContext->Scale()); ptCount, ptList, filled, offset, fCanvas->Scale());
delete[] opList; delete[] opList;
delete[] ptList; delete[] ptList;
@@ -248,26 +250,27 @@ get_polygon_frame(const BPoint* points, uint32 numPoints, BRect* _frame)
static void static void
move_pen_by(void* _context, const BPoint& delta) move_pen_by(void* _canvas, const BPoint& delta)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetPenLocation( canvas->CurrentState()->SetPenLocation(
context->CurrentState()->PenLocation() + delta); canvas->CurrentState()->PenLocation() + delta);
} }
static void 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 start = _start;
BPoint end = _end; BPoint end = _end;
context->ConvertToScreenForDrawing(&start); const SimpleTransform transform = canvas->PenToScreenTransform();
context->ConvertToScreenForDrawing(&end); transform.Apply(&start);
context->GetDrawingEngine()->StrokeLine(start, end); 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 // the DrawingEngine/Painter does not need to be updated, since this
// effects only the view->screen coord conversion, which is handled // effects only the view->screen coord conversion, which is handled
// by the view only // by the view only
@@ -275,79 +278,78 @@ stroke_line(void* _context, const BPoint& _start, const BPoint& _end)
static void 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; BRect rect = _rect;
context->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
if (fill) if (fill)
context->GetDrawingEngine()->FillRect(rect); canvas->GetDrawingEngine()->FillRect(rect);
else else
context->GetDrawingEngine()->StrokeRect(rect); canvas->GetDrawingEngine()->StrokeRect(rect);
} }
static void 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) bool fill)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
BRect rect = _rect; BRect rect = _rect;
context->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
float scale = context->CurrentState()->CombinedScale(); float scale = canvas->CurrentState()->CombinedScale();
context->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale, canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
radii.y * scale, fill); radii.y * scale, fill);
} }
static void static void
draw_bezier(void* _context, size_t numPoints, const BPoint viewPoints[], draw_bezier(void* _canvas, size_t numPoints, const BPoint viewPoints[],
bool fill) bool fill)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
const size_t kSupportedPoints = 4; const size_t kSupportedPoints = 4;
if (numPoints != kSupportedPoints) if (numPoints != kSupportedPoints)
return; return;
BPoint points[kSupportedPoints]; BPoint points[kSupportedPoints];
context->ConvertToScreenForDrawing(points, viewPoints, kSupportedPoints); canvas->PenToScreenTransform().Apply(points, viewPoints, kSupportedPoints);
canvas->GetDrawingEngine()->DrawBezier(points, fill);
context->GetDrawingEngine()->DrawBezier(points, fill);
} }
static void 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) 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, BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1); center.x + radii.x - 1, center.y + radii.y - 1);
context->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
context->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill); canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill);
} }
static void 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; BRect rect = _rect;
context->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
context->GetDrawingEngine()->DrawEllipse(rect, fill); canvas->GetDrawingEngine()->DrawEllipse(rect, fill);
} }
static void 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) bool isClosed, bool fill)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
if (numPoints == 0) if (numPoints == 0)
return; return;
@@ -361,12 +363,12 @@ draw_polygon(void* _context, size_t numPoints, const BPoint viewPoints[],
return; return;
} }
context->ConvertToScreenForDrawing(points, viewPoints, numPoints); canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);
BRect polyFrame; BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame); get_polygon_frame(points, numPoints, &polyFrame);
context->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, canvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
fill, isClosed && numPoints > 2); fill, isClosed && numPoints > 2);
if (numPoints > kMaxStackCount) if (numPoints > kMaxStackCount)
@@ -375,10 +377,10 @@ draw_polygon(void* _context, size_t numPoints, const BPoint viewPoints[],
static void 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); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
ShapePainter drawShape(context); ShapePainter drawShape(canvas);
drawShape.Iterate(&shape); drawShape.Iterate(&shape);
drawShape.Draw(shape.Bounds(), fill); drawShape.Draw(shape.Bounds(), fill);
@@ -386,23 +388,23 @@ draw_shape(void* _context, const BShape& shape, bool fill)
static void 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) 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" // NOTE: the picture data was recorded with a "set pen location"
// command inserted before the "draw string" command, so we can // command inserted before the "draw string" command, so we can
// use PenLocation() // use PenLocation()
BPoint location = context->CurrentState()->PenLocation(); BPoint location = canvas->CurrentState()->PenLocation();
escapement_delta delta = { deltaSpace, deltaNonSpace }; escapement_delta delta = { deltaSpace, deltaNonSpace };
context->ConvertToScreenForDrawing(&location); canvas->PenToScreenTransform().Apply(&location);
location = context->GetDrawingEngine()->DrawString(string, length, location = canvas->GetDrawingEngine()->DrawString(string, length,
location, &delta); location, &delta);
context->ConvertFromScreenForDrawing(&location); canvas->PenToScreenTransform().Apply(&location);
context->CurrentState()->SetPenLocation(location); canvas->CurrentState()->SetPenLocation(location);
// the DrawingEngine/Painter does not need to be updated, since this // the DrawingEngine/Painter does not need to be updated, since this
// effects only the view->screen coord conversion, which is handled // effects only the view->screen coord conversion, which is handled
// by the view only // by the view only
@@ -410,11 +412,11 @@ draw_string(void* _context, const char* string, size_t length, float deltaSpace,
static void 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, uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 options,
const void* data, size_t length) 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), UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1),
(color_space)pixelFormat, 0, bytesPerRow); (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)); memcpy(bitmap.Bits(), data, std::min(height * bytesPerRow, length));
BRect dest = _dest; BRect dest = _dest;
context->ConvertToScreenForDrawing(&dest); canvas->PenToScreenTransform().Apply(&dest);
context->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options); canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
} }
static void 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) { if (picture != NULL) {
context->PushState(); canvas->PushState();
context->SetDrawingOrigin(where); canvas->SetDrawingOrigin(where);
context->PushState(); canvas->PushState();
picture->Play(context); picture->Play(canvas);
context->PopState(); canvas->PopState();
context->PopState(); canvas->PopState();
picture->ReleaseReference(); picture->ReleaseReference();
} }
} }
static void 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 if (numRects == 0)
// directly to BRegion's internal data canvas->SetUserClipping(NULL);
BRegion region; else {
for (uint32 c = 0; c < numRects; c++) // TODO: This might be too slow, we should copy the rects
region.Include(rects[c]); // directly to BRegion's internal data
BRegion region;
context->SetUserClipping(&region); for (uint32 c = 0; c < numRects; c++)
context->UpdateCurrentDrawingRegion(); region.Include(rects[c]);
canvas->SetUserClipping(&region);
}
canvas->UpdateCurrentDrawingRegion();
} }
static void static void
clip_to_picture(void* _context, int32 pictureToken, const BPoint& where, clip_to_picture(void* _canvas, int32 pictureToken, const BPoint& where,
bool clipToInverse) 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) if (picture == NULL)
return; return;
AlphaMask* mask = new(std::nothrow) AlphaMask( AlphaMask* mask = new(std::nothrow) AlphaMask(
picture, clipToInverse, where, *context->CurrentState()); picture, clipToInverse, where, *canvas->CurrentState());
context->SetAlphaMask(mask); canvas->SetAlphaMask(mask);
context->UpdateCurrentDrawingRegion(); canvas->UpdateCurrentDrawingRegion();
if (mask != NULL) if (mask != NULL)
mask->ReleaseReference(); mask->ReleaseReference();
picture->ReleaseReference(); picture->ReleaseReference();
*/
} }
static void static void
push_state(void* _context) push_state(void* _canvas)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->PushState(); canvas->PushState();
} }
static void static void
pop_state(void* _context) pop_state(void* _canvas)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->PopState(); canvas->PopState();
BPoint p(0, 0); BPoint p(0, 0);
context->ConvertToScreenForDrawing(&p); canvas->PenToScreenTransform().Apply(&p);
context->GetDrawingEngine()->SetDrawState(context->CurrentState(), canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(),
(int32)p.x, (int32)p.y); (int32)p.x, (int32)p.y);
} }
@@ -511,46 +518,46 @@ pop_state(void* _context)
// TODO: Be smart and actually take advantage of these methods: // TODO: Be smart and actually take advantage of these methods:
// only apply state changes when they are called // only apply state changes when they are called
static void static void
enter_state_change(void* context) enter_state_change(void* _canvas)
{ {
} }
static void static void
exit_state_change(void* _context) exit_state_change(void* _canvas)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->ResyncDrawState(); canvas->ResyncDrawState();
} }
static void static void
enter_font_state(void* context) enter_font_state(void* _canvas)
{ {
} }
static void static void
exit_font_state(void* _context) exit_font_state(void* _canvas)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->GetDrawingEngine()->SetFont(context->CurrentState()->Font()); canvas->GetDrawingEngine()->SetFont(canvas->CurrentState()->Font());
} }
static void static void
set_origin(void* _context, const BPoint& pt) set_origin(void* _canvas, const BPoint& pt)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetOrigin(pt); canvas->CurrentState()->SetOrigin(pt);
} }
static void static void
set_pen_location(void* _context, const BPoint& pt) set_pen_location(void* _canvas, const BPoint& pt)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetPenLocation(pt); canvas->CurrentState()->SetPenLocation(pt);
// the DrawingEngine/Painter does not need to be updated, since this // the DrawingEngine/Painter does not need to be updated, since this
// effects only the view->screen coord conversion, which is handled // effects only the view->screen coord conversion, which is handled
// by the view only // by the view only
@@ -558,72 +565,72 @@ set_pen_location(void* _context, const BPoint& pt)
static void static void
set_drawing_mode(void* _context, drawing_mode mode) set_drawing_mode(void* _canvas, drawing_mode mode)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetDrawingMode(mode); if (canvas->CurrentState()->SetDrawingMode(mode))
context->GetDrawingEngine()->SetDrawingMode(mode); canvas->GetDrawingEngine()->SetDrawingMode(mode);
} }
static void 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) float miterLimit)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
DrawState* state = context->CurrentState(); DrawState* state = canvas->CurrentState();
state->SetLineCapMode(capMode); state->SetLineCapMode(capMode);
state->SetLineJoinMode(joinMode); state->SetLineJoinMode(joinMode);
state->SetMiterLimit(miterLimit); state->SetMiterLimit(miterLimit);
context->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit); canvas->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit);
} }
static void static void
set_pen_size(void* _context, float size) set_pen_size(void* _canvas, float size)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetPenSize(size); canvas->CurrentState()->SetPenSize(size);
context->GetDrawingEngine()->SetPenSize( canvas->GetDrawingEngine()->SetPenSize(
context->CurrentState()->PenSize()); canvas->CurrentState()->PenSize());
// DrawState::PenSize() returns the scaled pen size, so we // DrawState::PenSize() returns the scaled pen size, so we
// need to use that value to set the drawing engine pen size. // need to use that value to set the drawing engine pen size.
} }
static void 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); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetHighColor(color); canvas->CurrentState()->SetHighColor(color);
context->GetDrawingEngine()->SetHighColor(color); canvas->GetDrawingEngine()->SetHighColor(color);
} }
static void 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); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetLowColor(color); canvas->CurrentState()->SetLowColor(color);
context->GetDrawingEngine()->SetLowColor(color); canvas->GetDrawingEngine()->SetLowColor(color);
} }
static void static void
set_stipple_pattern(void* _context, const pattern& pattern) set_stipple_pattern(void* _canvas, const pattern& pattern)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetPattern(Pattern(pattern)); canvas->CurrentState()->SetPattern(Pattern(pattern));
context->GetDrawingEngine()->SetPattern(pattern); canvas->GetDrawingEngine()->SetPattern(pattern);
} }
static void static void
set_scale(void* _context, float scale) set_scale(void* _canvas, float scale)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetScale(scale); canvas->CurrentState()->SetScale(scale);
context->ResyncDrawState(); canvas->ResyncDrawState();
// Update the drawing engine draw state, since some stuff // Update the drawing engine draw state, since some stuff
// (for example the pen size) needs to be recalculated. // (for example the pen size) needs to be recalculated.
@@ -631,109 +638,125 @@ set_scale(void* _context, float scale)
static void 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); BString family(_family, length);
FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0); FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0);
ServerFont font; ServerFont font;
font.SetStyle(fontStyle); font.SetStyle(fontStyle);
context->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
} }
static void 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); BString style(_style, length);
ServerFont font(context->CurrentState()->Font()); ServerFont font(canvas->CurrentState()->Font());
FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style); FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style);
font.SetStyle(fontStyle); font.SetStyle(fontStyle);
context->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
} }
static void 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; ServerFont font;
font.SetSpacing(spacing); font.SetSpacing(spacing);
context->CurrentState()->SetFont(font, B_FONT_SPACING); canvas->CurrentState()->SetFont(font, B_FONT_SPACING);
} }
static void 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; ServerFont font;
font.SetSize(size); font.SetSize(size);
context->CurrentState()->SetFont(font, B_FONT_SIZE); canvas->CurrentState()->SetFont(font, B_FONT_SIZE);
} }
static void 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; ServerFont font;
font.SetRotation(rotation); font.SetRotation(rotation);
context->CurrentState()->SetFont(font, B_FONT_ROTATION); canvas->CurrentState()->SetFont(font, B_FONT_ROTATION);
} }
static void 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; ServerFont font;
font.SetEncoding(encoding); font.SetEncoding(encoding);
context->CurrentState()->SetFont(font, B_FONT_ENCODING); canvas->CurrentState()->SetFont(font, B_FONT_ENCODING);
} }
static void 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; ServerFont font;
font.SetFlags(flags); font.SetFlags(flags);
context->CurrentState()->SetFont(font, B_FONT_FLAGS); canvas->CurrentState()->SetFont(font, B_FONT_FLAGS);
} }
static void 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; ServerFont font;
font.SetShear(shear); font.SetShear(shear);
context->CurrentState()->SetFont(font, B_FONT_SHEAR); canvas->CurrentState()->SetFont(font, B_FONT_SHEAR);
} }
static void 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; ServerFont font;
font.SetFace(face); font.SetFace(face);
context->CurrentState()->SetFont(font, B_FONT_FACE); canvas->CurrentState()->SetFont(font, B_FONT_FACE);
} }
static void static void
set_blending_mode(void* _context, source_alpha alphaSrcMode, set_blending_mode(void* _canvas, source_alpha alphaSrcMode,
alpha_function alphaFncMode) alpha_function alphaFncMode)
{ {
DrawingContext* context = reinterpret_cast<DrawingContext *>(_context); Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
context->CurrentState()->SetBlendingMode(alphaSrcMode, alphaFncMode); 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_flags,
set_font_shear, set_font_shear,
set_font_face, 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()); WriteSetOrigin(view->CurrentState()->Origin());
WriteSetPenLocation(view->CurrentState()->PenLocation()); WriteSetPenLocation(view->CurrentState()->PenLocation());
WriteSetPenSize(view->CurrentState()->PenSize()); WriteSetPenSize(view->CurrentState()->UnscaledPenSize());
WriteSetScale(view->CurrentState()->Scale()); WriteSetScale(view->CurrentState()->Scale());
WriteSetLineMode(view->CurrentState()->LineCapMode(), WriteSetLineMode(view->CurrentState()->LineCapMode(),
view->CurrentState()->LineJoinMode(), view->CurrentState()->LineJoinMode(),
@@ -1010,7 +1035,7 @@ ServerPicture::SetFontFromLink(BPrivate::LinkReceiver& link)
void void
ServerPicture::Play(DrawingContext* target) ServerPicture::Play(Canvas* target)
{ {
// TODO: for now: then change PicturePlayer // TODO: for now: then change PicturePlayer
// to accept a BPositionIO object // to accept a BPositionIO object
+7 -4
View File
@@ -1,10 +1,11 @@
/* /*
* Copyright 2001-2010, Haiku. * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* DarkWyrm <bpmagic@columbus.rr.com> * DarkWyrm <bpmagic@columbus.rr.com>
* Stefano Ceccherini <stefano.ceccherini@gmail.com> * Stefano Ceccherini <stefano.ceccherini@gmail.com>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
#ifndef SERVER_PICTURE_H #ifndef SERVER_PICTURE_H
#define SERVER_PICTURE_H #define SERVER_PICTURE_H
@@ -18,7 +19,7 @@
class BFile; class BFile;
class DrawingContext; class Canvas;
class ServerApp; class ServerApp;
class View; class View;
@@ -35,7 +36,7 @@ public:
ServerPicture(const ServerPicture& other); ServerPicture(const ServerPicture& other);
ServerPicture(const char* fileName, ServerPicture(const char* fileName,
int32 offset); int32 offset);
~ServerPicture(); virtual ~ServerPicture();
int32 Token() { return fToken; } int32 Token() { return fToken; }
bool SetOwner(ServerApp* owner); bool SetOwner(ServerApp* owner);
@@ -49,7 +50,7 @@ public:
void SyncState(View* view); void SyncState(View* view);
void SetFontFromLink(BPrivate::LinkReceiver& link); void SetFontFromLink(BPrivate::LinkReceiver& link);
void Play(DrawingContext* target); void Play(Canvas* target);
void PushPicture(ServerPicture* picture); void PushPicture(ServerPicture* picture);
ServerPicture* PopPicture(); ServerPicture* PopPicture();
@@ -63,6 +64,8 @@ public:
status_t ExportData(BPrivate::PortLink& link); status_t ExportData(BPrivate::PortLink& link);
private: private:
friend class PictureBoundingBoxPlayer;
typedef BObjectList<ServerPicture> PictureList; typedef BObjectList<ServerPicture> PictureList;
int32 fToken; int32 fToken;
+164 -54
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2010, Haiku. * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -11,6 +11,7 @@
* Artur Wyszynski <harakash@gmail.com> * Artur Wyszynski <harakash@gmail.com>
* Philippe Saint-Pierre <stpere@gmail.com> * Philippe Saint-Pierre <stpere@gmail.com>
* Brecht Machiels <brecht@mos6581.org> * Brecht Machiels <brecht@mos6581.org>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
@@ -61,6 +62,7 @@
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "DrawState.h" #include "DrawState.h"
#include "HWInterface.h" #include "HWInterface.h"
#include "Layer.h"
#include "Overlay.h" #include "Overlay.h"
#include "ProfileMessageSupport.h" #include "ProfileMessageSupport.h"
#include "RenderingBuffer.h" #include "RenderingBuffer.h"
@@ -351,7 +353,7 @@ ServerWindow::_Show()
fDesktop->ShowWindow(fWindow); fDesktop->ShowWindow(fWindow);
if (fDirectWindowInfo && fDirectWindowInfo->IsFullScreen()) if (fDirectWindowInfo && fDirectWindowInfo->IsFullScreen())
_ResizeToFullScreen(); _ResizeToFullScreen();
fDesktop->LockSingleWindow(); fDesktop->LockSingleWindow();
} }
@@ -1940,11 +1942,13 @@ fDesktop->LockSingleWindow();
if (picture == NULL) if (picture == NULL)
break; break;
AlphaMask* mask = new(std::nothrow) AlphaMask( AlphaMask* const mask = new PictureAlphaMask(
picture, inverse, where, *fCurrentView->CurrentState()); fCurrentView->GetAlphaMask(), picture,
*fCurrentView->CurrentState(), where, inverse);
fCurrentView->SetAlphaMask(mask); fCurrentView->SetAlphaMask(mask);
if (mask != NULL) if (mask != NULL)
mask->ReleaseReference(); mask->ReleaseReference();
_UpdateDrawState(fCurrentView); _UpdateDrawState(fCurrentView);
picture->ReleaseReference(); picture->ReleaseReference();
@@ -1964,7 +1968,7 @@ fDesktop->LockSingleWindow();
} else { } else {
_UpdateCurrentDrawingRegion(); _UpdateCurrentDrawingRegion();
BRegion region(fCurrentDrawingRegion); BRegion region(fCurrentDrawingRegion);
fCurrentView->ConvertFromScreen(&region); fCurrentView->ScreenToLocalTransform().Apply(&region);
fLink.AttachRegion(region); fLink.AttachRegion(region);
} }
fLink.Flush(); fLink.Flush();
@@ -2185,6 +2189,29 @@ fDesktop->LockSingleWindow();
break; 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: default:
_DispatchViewDrawingMessage(code, link); _DispatchViewDrawingMessage(code, link);
break; break;
@@ -2255,8 +2282,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
info.endPoint.x, info.endPoint.y)); info.endPoint.x, info.endPoint.y));
BPoint penPos = info.endPoint; BPoint penPos = info.endPoint;
fCurrentView->ConvertToScreenForDrawing(&info.startPoint); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(&info.endPoint); fCurrentView->PenToScreenTransform();
transform.Apply(&info.startPoint);
transform.Apply(&info.endPoint);
drawingEngine->StrokeLine(info.startPoint, info.endPoint); drawingEngine->StrokeLine(info.startPoint, info.endPoint);
// We update the pen here because many DrawingEngine calls which // 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, fCurrentView->Name(), rect.left, rect.top, rect.right,
rect.bottom)); rect.bottom));
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->InvertRect(rect); drawingEngine->InvertRect(rect);
break; break;
} }
@@ -2295,7 +2324,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top, rect.right, fCurrentView->Name(), rect.left, rect.top, rect.right,
rect.bottom)); rect.bottom));
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->StrokeRect(rect); drawingEngine->StrokeRect(rect);
break; break;
} }
@@ -2310,7 +2339,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top, rect.right, fCurrentView->Name(), rect.left, rect.top, rect.right,
rect.bottom)); rect.bottom));
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->FillRect(rect); drawingEngine->FillRect(rect);
break; break;
} }
@@ -2327,8 +2356,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top, rect.right, fCurrentView->Name(), rect.left, rect.top, rect.right,
rect.bottom)); rect.bottom));
fCurrentView->ConvertToScreenForDrawing(&rect); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&rect);
transform.Apply(gradient);
drawingEngine->FillRect(rect, *gradient); drawingEngine->FillRect(rect, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2357,7 +2388,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
info.viewRect.left, info.viewRect.top, info.viewRect.left, info.viewRect.top,
info.viewRect.right, info.viewRect.bottom)); info.viewRect.right, info.viewRect.bottom));
fCurrentView->ConvertToScreenForDrawing(&info.viewRect); fCurrentView->PenToScreenTransform().Apply(&info.viewRect);
// TODO: Unbreak... // TODO: Unbreak...
// if ((info.options & B_WAIT_FOR_RETRACE) != 0) // if ((info.options & B_WAIT_FOR_RETRACE) != 0)
@@ -2383,7 +2414,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<float>(&span) != B_OK) if (link.Read<float>(&span) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&r); fCurrentView->PenToScreenTransform().Apply(&r);
drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC); drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC);
break; break;
} }
@@ -2400,8 +2431,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&r); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&r);
transform.Apply(gradient);
drawingEngine->FillArc(r, angle, span, *gradient); drawingEngine->FillArc(r, angle, span, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2412,11 +2445,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n", DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n",
Title())); Title()));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint pts[4]; BPoint pts[4];
status_t status; status_t status;
for (int32 i = 0; i < 4; i++) { for (int32 i = 0; i < 4; i++) {
status = link.Read<BPoint>(&(pts[i])); status = link.Read<BPoint>(&(pts[i]));
fCurrentView->ConvertToScreenForDrawing(&pts[i]); transform.Apply(&pts[i]);
} }
if (status != B_OK) if (status != B_OK)
break; break;
@@ -2429,15 +2464,17 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n", GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n",
Title())); Title()));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint pts[4]; BPoint pts[4];
for (int32 i = 0; i < 4; i++) { for (int32 i = 0; i < 4; i++) {
link.Read<BPoint>(&(pts[i])); link.Read<BPoint>(&(pts[i]));
fCurrentView->ConvertToScreenForDrawing(&pts[i]); transform.Apply(&pts[i]);
} }
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(gradient); transform.Apply(gradient);
drawingEngine->FillBezier(pts, *gradient); drawingEngine->FillBezier(pts, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2452,7 +2489,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<BRect>(&rect) != B_OK) if (link.Read<BRect>(&rect) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE); drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE);
break; break;
} }
@@ -2466,8 +2503,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&rect);
transform.Apply(gradient);
drawingEngine->FillEllipse(rect, *gradient); drawingEngine->FillEllipse(rect, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2486,7 +2525,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<float>(&yRadius) != B_OK) if (link.Read<float>(&yRadius) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
float scale = fCurrentView->CurrentState()->CombinedScale(); float scale = fCurrentView->CurrentState()->CombinedScale();
drawingEngine->DrawRoundRect(rect, xRadius * scale, yRadius * scale, drawingEngine->DrawRoundRect(rect, xRadius * scale, yRadius * scale,
code == AS_FILL_ROUNDRECT); code == AS_FILL_ROUNDRECT);
@@ -2505,8 +2544,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&rect);
transform.Apply(gradient);
drawingEngine->FillRoundRect(rect, xrad, yrad, *gradient); drawingEngine->FillRoundRect(rect, xrad, yrad, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2517,18 +2558,20 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n", DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n",
Title())); Title()));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint pts[3]; BPoint pts[3];
BRect rect; BRect rect;
for (int32 i = 0; i < 3; i++) { for (int32 i = 0; i < 3; i++) {
link.Read<BPoint>(&(pts[i])); link.Read<BPoint>(&(pts[i]));
fCurrentView->ConvertToScreenForDrawing(&pts[i]); transform.Apply(&pts[i]);
} }
if (link.Read<BRect>(&rect) != B_OK) if (link.Read<BRect>(&rect) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); transform.Apply(&rect);
drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE); drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE);
break; break;
} }
@@ -2537,18 +2580,20 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n", DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n",
Title())); Title()));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint pts[3]; BPoint pts[3];
BRect rect; BRect rect;
for (int32 i = 0; i < 3; i++) { for (int32 i = 0; i < 3; i++) {
link.Read<BPoint>(&(pts[i])); link.Read<BPoint>(&(pts[i]));
fCurrentView->ConvertToScreenForDrawing(&pts[i]); transform.Apply(&pts[i]);
} }
link.Read<BRect>(&rect); link.Read<BRect>(&rect);
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); transform.Apply(&rect);
fCurrentView->ConvertToScreenForDrawing(gradient); transform.Apply(gradient);
drawingEngine->FillTriangle(pts, rect, *gradient); drawingEngine->FillTriangle(pts, rect, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2568,11 +2613,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
link.Read<bool>(&isClosed); link.Read<bool>(&isClosed);
link.Read<int32>(&pointCount); link.Read<int32>(&pointCount);
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint* pointList = new(nothrow) BPoint[pointCount]; BPoint* pointList = new(nothrow) BPoint[pointCount];
if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) { if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
for (int32 i = 0; i < pointCount; i++) for (int32 i = 0; i < pointCount; i++)
fCurrentView->ConvertToScreenForDrawing(&pointList[i]); transform.Apply(&pointList[i]);
fCurrentView->ConvertToScreenForDrawing(&polyFrame); transform.Apply(&polyFrame);
drawingEngine->DrawPolygon(pointList, pointCount, polyFrame, drawingEngine->DrawPolygon(pointList, pointCount, polyFrame,
code == AS_FILL_POLYGON, isClosed && pointCount > 2); code == AS_FILL_POLYGON, isClosed && pointCount > 2);
@@ -2591,14 +2638,16 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
link.Read<BRect>(&polyFrame); link.Read<BRect>(&polyFrame);
link.Read<int32>(&pointCount); link.Read<int32>(&pointCount);
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint* pointList = new(nothrow) BPoint[pointCount]; BPoint* pointList = new(nothrow) BPoint[pointCount];
BGradient* gradient; BGradient* gradient;
if (link.Read(pointList, pointCount * sizeof(BPoint)) == B_OK if (link.Read(pointList, pointCount * sizeof(BPoint)) == B_OK
&& link.ReadGradient(&gradient) == B_OK) { && link.ReadGradient(&gradient) == B_OK) {
for (int32 i = 0; i < pointCount; i++) for (int32 i = 0; i < pointCount; i++)
fCurrentView->ConvertToScreenForDrawing(&pointList[i]); transform.Apply(&pointList[i]);
fCurrentView->ConvertToScreenForDrawing(&polyFrame); transform.Apply(&polyFrame);
fCurrentView->ConvertToScreenForDrawing(gradient); transform.Apply(gradient);
drawingEngine->FillPolygon(pointList, pointCount, drawingEngine->FillPolygon(pointList, pointCount,
polyFrame, *gradient, isClosed && pointCount > 2); polyFrame, *gradient, isClosed && pointCount > 2);
@@ -2632,8 +2681,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
= fCurrentView->CurrentState()->PenLocation(); = fCurrentView->CurrentState()->PenLocation();
shapeFrame.OffsetBy(screenOffset); shapeFrame.OffsetBy(screenOffset);
fCurrentView->ConvertToScreenForDrawing(&screenOffset); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(&shapeFrame); fCurrentView->PenToScreenTransform();
transform.Apply(&screenOffset);
transform.Apply(&shapeFrame);
drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount, drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount,
ptList, code == AS_FILL_SHAPE, screenOffset, ptList, code == AS_FILL_SHAPE, screenOffset,
@@ -2670,9 +2721,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
= fCurrentView->CurrentState()->PenLocation(); = fCurrentView->CurrentState()->PenLocation();
shapeFrame.OffsetBy(screenOffset); shapeFrame.OffsetBy(screenOffset);
fCurrentView->ConvertToScreenForDrawing(&screenOffset); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(&shapeFrame); fCurrentView->PenToScreenTransform();
fCurrentView->ConvertToScreenForDrawing(gradient); transform.Apply(&screenOffset);
transform.Apply(&shapeFrame);
transform.Apply(gradient);
drawingEngine->FillShape(shapeFrame, opCount, opList, drawingEngine->FillShape(shapeFrame, opCount, opList,
ptCount, ptList, *gradient, screenOffset, ptCount, ptList, *gradient, screenOffset,
fCurrentView->Scale()); fCurrentView->Scale());
@@ -2691,7 +2744,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.ReadRegion(&region) < B_OK) if (link.ReadRegion(&region) < B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&region); fCurrentView->PenToScreenTransform().Apply(&region);
drawingEngine->FillRegion(region); drawingEngine->FillRegion(region);
break; break;
@@ -2708,8 +2761,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&region); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&region);
transform.Apply(gradient);
drawingEngine->FillRegion(region, *gradient); drawingEngine->FillRegion(region, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2748,11 +2803,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
} }
// Convert to screen coords and draw // Convert to screen coords and draw
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
for (int32 i = 0; i < lineCount; i++) { for (int32 i = 0; i < lineCount; i++) {
fCurrentView->ConvertToScreenForDrawing( transform.Apply(&lineData[i].startPoint);
&lineData[i].startPoint); transform.Apply(&lineData[i].endPoint);
fCurrentView->ConvertToScreenForDrawing(
&lineData[i].endPoint);
} }
drawingEngine->StrokeLineArray(lineCount, lineData); drawingEngine->StrokeLineArray(lineCount, lineData);
@@ -2797,11 +2852,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View: %s " DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View: %s "
"-> %s\n", Title(), fCurrentView->Name(), string)); "-> %s\n", Title(), fCurrentView->Name(), string));
fCurrentView->ConvertToScreenForDrawing(&info.location); fCurrentView->PenToScreenTransform().Apply(&info.location);
BPoint penLocation = drawingEngine->DrawString(string, BPoint penLocation = drawingEngine->DrawString(string,
info.stringLength, info.location, delta); info.stringLength, info.location, delta);
fCurrentView->ConvertFromScreenForDrawing(&penLocation); fCurrentView->ScreenToPenTransform().Apply(&penLocation);
fCurrentView->CurrentState()->SetPenLocation(penLocation); fCurrentView->CurrentState()->SetPenLocation(penLocation);
if (string != stackString) if (string != stackString)
@@ -2854,13 +2909,15 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING_WITH_OFFSETS, View: %s " DTRACE(("ServerWindow %s: Message AS_DRAW_STRING_WITH_OFFSETS, View: %s "
"-> %s\n", Title(), fCurrentView->Name(), string)); "-> %s\n", Title(), fCurrentView->Name(), string));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
for (int32 i = 0; i < glyphCount; i++) for (int32 i = 0; i < glyphCount; i++)
fCurrentView->ConvertToScreenForDrawing(&locations[i]); transform.Apply(&locations[i]);
BPoint penLocation = drawingEngine->DrawString(string, BPoint penLocation = drawingEngine->DrawString(string,
stringLength, locations); stringLength, locations);
fCurrentView->ConvertFromScreenForDrawing(&penLocation); fCurrentView->ScreenToPenTransform().Apply(&penLocation);
fCurrentView->CurrentState()->SetPenLocation(penLocation); fCurrentView->CurrentState()->SetPenLocation(penLocation);
break; break;
@@ -2893,6 +2950,16 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
break; 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: default:
BString codeString; BString codeString;
string_for_message_code(code, codeString); string_for_message_code(code, codeString);
@@ -3411,6 +3478,49 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link)
fLink.Flush(); fLink.Flush();
return true; 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: case AS_VIEW_SET_BLENDING_MODE:
{ {
@@ -3728,11 +3838,11 @@ ServerWindow::_UpdateDrawState(View* view)
if (view != NULL && drawingEngine != NULL) { if (view != NULL && drawingEngine != NULL) {
BPoint leftTop(0, 0); BPoint leftTop(0, 0);
if (view->GetAlphaMask() != NULL) { if (view->GetAlphaMask() != NULL) {
view->ConvertToScreen(&leftTop); view->LocalToScreenTransform().Apply(&leftTop);
view->GetAlphaMask()->Update(view->Bounds(), leftTop); view->GetAlphaMask()->SetViewOrigin(leftTop);
leftTop = BPoint(0, 0); leftTop = BPoint(0, 0);
} }
view->ConvertToScreenForDrawing(&leftTop); view->PenToScreenTransform().Apply(&leftTop);
drawingEngine->SetDrawState(view->CurrentState(), leftTop.x, leftTop.y); drawingEngine->SetDrawState(view->CurrentState(), leftTop.x, leftTop.y);
} }
} }
+243
View File
@@ -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(&center);
radial->SetCenter(center);
break;
}
case BGradient::TYPE_RADIAL_FOCUS:
{
BGradientRadialFocus* radialFocus =
(BGradientRadialFocus*)gradient;
BPoint center = radialFocus->Center();
BPoint focal = radialFocus->Focal();
Apply(&center);
Apply(&focal);
radialFocus->SetCenter(center);
radialFocus->SetFocal(focal);
break;
}
case BGradient::TYPE_DIAMOND:
{
BGradientDiamond* diamond = (BGradientDiamond*) gradient;
BPoint center = diamond->Center();
Apply(&center);
diamond->SetCenter(center);
break;
}
case BGradient::TYPE_CONIC:
{
BGradientConic* conic = (BGradientConic*) gradient;
BPoint center = conic->Center();
Apply(&center);
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
+121
View File
@@ -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;
}
+51
View File
@@ -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
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2014, Haiku, Inc. * Copyright (c) 2001-2015, Haiku, Inc.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Authors: * Authors:
@@ -9,6 +9,7 @@
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Marcus Overhagen <marcus@overhagen.de> * Marcus Overhagen <marcus@overhagen.de>
* Adrien Destugues <pulkomandy@pulkomandy.tk * Adrien Destugues <pulkomandy@pulkomandy.tk
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
#include "View.h" #include "View.h"
@@ -19,6 +20,7 @@
#include "Desktop.h" #include "Desktop.h"
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "DrawState.h" #include "DrawState.h"
#include "Layer.h"
#include "Overlay.h" #include "Overlay.h"
#include "ServerApp.h" #include "ServerApp.h"
#include "ServerBitmap.h" #include "ServerBitmap.h"
@@ -27,6 +29,7 @@
#include "ServerWindow.h" #include "ServerWindow.h"
#include "Window.h" #include "Window.h"
#include "BitmapHWInterface.h"
#include "drawing_support.h" #include "drawing_support.h"
#include <List.h> #include <List.h>
@@ -165,7 +168,8 @@ View::ConvertToVisibleInTopView(IntRect* bounds) const
{ {
*bounds = *bounds & Bounds(); *bounds = *bounds & Bounds();
// NOTE: this step is necessary even if we don't have a parent! // 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) if (fParent)
fParent->ConvertToVisibleInTopView(bounds); fParent->ConvertToVisibleInTopView(bounds);
@@ -440,7 +444,7 @@ View::ViewAt(const BPoint& where)
IntRect frame = Frame(); IntRect frame = Frame();
if (Parent() != NULL) if (Parent() != NULL)
Parent()->ConvertToScreen(&frame); Parent()->LocalToScreenTransform().Apply(&frame);
if (!frame.Contains(where)) if (!frame.Contains(where))
return NULL; return NULL;
@@ -524,7 +528,7 @@ View::_UpdateOverlayView() const
return; return;
IntRect destination = fBitmapDestination; IntRect destination = fBitmapDestination;
ConvertToScreen(&destination); LocalToScreenTransform().Apply(&destination);
overlay->Configure(fBitmapSource, destination); overlay->Configure(fBitmapSource, destination);
} }
@@ -556,201 +560,34 @@ View::UpdateOverlay()
void void
View::ConvertToParent(BPoint* point) const View::_LocalToScreenTransform(SimpleTransform& transform) const
{ {
// remove scrolling offset and convert to parent coordinate space const View* view = this;
point->x += fFrame.left - fScrollingOffset.x; int32 offsetX = 0;
point->y += fFrame.top - fScrollingOffset.y; 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 void
View::ConvertToParent(IntPoint* point) const View::_ScreenToLocalTransform(SimpleTransform& transform) const
{ {
// remove scrolling offset and convert to parent coordinate space const View* view = this;
point->x += fFrame.left - fScrollingOffset.x; int32 offsetX = 0;
point->y += fFrame.top - fScrollingOffset.y; int32 offsetY = 0;
} do {
offsetX += view->fScrollingOffset.x - view->fFrame.left;
offsetY += view->fScrollingOffset.y - view->fFrame.top;
view = view->fParent;
} while (view != NULL);
transform.AddOffset(offsetX, offsetY);
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);
} }
@@ -775,7 +612,7 @@ View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
// local clipping to see which parts need invalidation // local clipping to see which parts need invalidation
IntRect oldVisibleBounds(newVisibleBounds); IntRect oldVisibleBounds(newVisibleBounds);
oldVisibleBounds.OffsetBy(-x, -y); oldVisibleBounds.OffsetBy(-x, -y);
ConvertToScreen(&oldVisibleBounds); LocalToScreenTransform().Apply(&oldVisibleBounds);
ConvertToVisibleInTopView(&newVisibleBounds); ConvertToVisibleInTopView(&newVisibleBounds);
@@ -788,7 +625,7 @@ View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
IntRect oldVisibleBounds(Bounds()); IntRect oldVisibleBounds(Bounds());
IntRect newVisibleBounds(oldVisibleBounds); IntRect newVisibleBounds(oldVisibleBounds);
oldVisibleBounds.OffsetBy(-x, -y); oldVisibleBounds.OffsetBy(-x, -y);
ConvertToScreen(&oldVisibleBounds); LocalToScreenTransform().Apply(&oldVisibleBounds);
// NOTE: using ConvertToVisibleInTopView() // NOTE: using ConvertToVisibleInTopView()
// instead of ConvertToScreen()! see below // 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); dirtyRegion->Include(dirty);
} }
fWindow->RecycleRegion(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 void
View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
BRegion* windowContentClipping, bool deep) BRegion* windowContentClipping, bool deep)
@@ -1171,7 +1020,7 @@ View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
// draw view bitmap // draw view bitmap
// TODO: support other options! // TODO: support other options!
BRect rect = fBitmapDestination; BRect rect = fBitmapDestination;
ConvertToScreenForDrawing(&rect); PenToScreenTransform().Apply(&rect);
align_rect_to_pixels(&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 // This check will prevent descending the view hierarchy
// any further than necessary // any further than necessary
IntRect screenBounds(Bounds()); IntRect screenBounds(Bounds());
ConvertToScreen(&screenBounds); LocalToScreenTransform().Apply(&screenBounds);
if (!region.Intersects((clipping_rect)screenBounds)) if (!region.Intersects((clipping_rect)screenBounds))
return; return;
@@ -1537,7 +1386,7 @@ View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const
if (fScreenAndUserClipping == NULL) if (fScreenAndUserClipping == NULL)
return fScreenClipping; return fScreenClipping;
ConvertToScreen(fScreenAndUserClipping); LocalToScreenTransform().Apply(fScreenAndUserClipping);
fScreenAndUserClipping->IntersectWith( fScreenAndUserClipping->IntersectWith(
&_ScreenClipping(windowContentClipping, force)); &_ScreenClipping(windowContentClipping, force));
return *fScreenAndUserClipping; return *fScreenAndUserClipping;
@@ -1578,7 +1427,7 @@ View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
{ {
if (!fScreenClippingValid || force) { if (!fScreenClippingValid || force) {
fScreenClipping = fLocalClipping; fScreenClipping = fLocalClipping;
ConvertToScreen(&fScreenClipping); LocalToScreenTransform().Apply(&fScreenClipping);
// see if parts of our bounds are hidden underneath // see if parts of our bounds are hidden underneath
// the parent, the local clipping does not account for this // the parent, the local clipping does not account for this
+12 -28
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2014, Haiku, Inc. * Copyright (c) 2001-2015, Haiku, Inc.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Authors: * Authors:
@@ -9,12 +9,13 @@
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Marcus Overhagen <marcus@overhagen.de> * Marcus Overhagen <marcus@overhagen.de>
* Adrien Destugues <pulkomandy@pulkomandy.tk> * Adrien Destugues <pulkomandy@pulkomandy.tk>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
#ifndef VIEW_H #ifndef VIEW_H
#define VIEW_H #define VIEW_H
#include "DrawingContext.h" #include "Canvas.h"
#include "IntRect.h" #include "IntRect.h"
#include <GraphicsDefs.h> #include <GraphicsDefs.h>
@@ -37,7 +38,7 @@ class ServerCursor;
class ServerPicture; class ServerPicture;
class BGradient; class BGradient;
class View: public DrawingContext { class View: public Canvas {
public: public:
View(IntRect frame, IntPoint scrollingOffset, View(IntRect frame, IntPoint scrollingOffset,
const char* name, int32 token, const char* name, int32 token,
@@ -111,31 +112,7 @@ public:
View* ViewAt(const BPoint& where); View* ViewAt(const BPoint& where);
// coordinate conversion public:
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;
void MoveBy(int32 dx, int32 dy, void MoveBy(int32 dx, int32 dy,
BRegion* dirtyRegion); BRegion* dirtyRegion);
@@ -180,6 +157,8 @@ public:
ServerPicture* Picture() const ServerPicture* Picture() const
{ return fPicture; } { return fPicture; }
void BlendAllLayers();
// for background clearing // for background clearing
virtual void Draw(DrawingEngine* drawingEngine, virtual void Draw(DrawingEngine* drawingEngine,
BRegion* effectiveClipping, BRegion* effectiveClipping,
@@ -235,6 +214,11 @@ public:
#endif #endif
protected: protected:
virtual void _LocalToScreenTransform(
SimpleTransform& transform) const;
virtual void _ScreenToLocalTransform(
SimpleTransform& transform) const;
BRegion& _ScreenClipping(BRegion* windowContentClipping, BRegion& _ScreenClipping(BRegion* windowContentClipping,
bool force = false) const; bool force = false) const;
void _MoveScreenClipping(int32 x, int32 y, void _MoveScreenClipping(int32 x, int32 y,
+1 -1
View File
@@ -817,7 +817,7 @@ Window::InvalidateView(View* view, BRegion& viewRegion)
if (!fContentRegionValid) if (!fContentRegionValid)
_UpdateContentRegion(); _UpdateContentRegion();
view->ConvertToScreen(&viewRegion); view->LocalToScreenTransform().Apply(&viewRegion);
viewRegion.IntersectWith(&VisibleContentRegion()); viewRegion.IntersectWith(&VisibleContentRegion());
if (viewRegion.CountRects() > 0) { if (viewRegion.CountRects() > 0) {
viewRegion.IntersectWith( viewRegion.IntersectWith(
+3 -3
View File
@@ -90,7 +90,7 @@ WorkspacesView::_WorkspaceAt(int32 i)
_GetGrid(columns, rows); _GetGrid(columns, rows);
BRect frame = Bounds(); BRect frame = Bounds();
ConvertToScreen(&frame); LocalToScreenTransform().Apply(&frame);
int32 width = frame.IntegerWidth() / columns; int32 width = frame.IntegerWidth() / columns;
int32 height = frame.IntegerHeight() / rows; int32 height = frame.IntegerHeight() / rows;
@@ -356,7 +356,7 @@ void
WorkspacesView::_Invalidate() const WorkspacesView::_Invalidate() const
{ {
BRect frame = Bounds(); BRect frame = Bounds();
ConvertToScreen(&frame); LocalToScreenTransform().Apply(&frame);
BRegion region(frame); BRegion region(frame);
Window()->MarkContentDirty(region); Window()->MarkContentDirty(region);
@@ -385,7 +385,7 @@ WorkspacesView::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
drawingEngine->ConstrainClippingRegion(&gridRegion); drawingEngine->ConstrainClippingRegion(&gridRegion);
BRect frame = Bounds(); BRect frame = Bounds();
ConvertToScreen(&frame); LocalToScreenTransform().Apply(&frame);
// horizontal lines // horizontal lines
+295 -148
View File
@@ -1,10 +1,11 @@
/* /*
* Copyright 2014, Haiku, Inc. * Copyright 2014-2015, Haiku, Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Adrien Destugues <pulkomandy@pulkomandy.tk> * Adrien Destugues <pulkomandy@pulkomandy.tk>
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
@@ -12,168 +13,75 @@
#include "BitmapHWInterface.h" #include "BitmapHWInterface.h"
#include "BitmapManager.h" #include "BitmapManager.h"
#include "DrawingContext.h" #include "Canvas.h"
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "PictureBoundingBoxPlayer.h"
#include "ServerBitmap.h" #include "ServerBitmap.h"
#include "ServerPicture.h" #include "ServerPicture.h"
#include "Shape.h"
AlphaMask::AlphaMask(ServerPicture* picture, bool inverse, BPoint origin, // #pragma mark - AlphaMask
const DrawState& drawState)
AlphaMask::AlphaMask(AlphaMask* previousMask, bool inverse)
: :
fPreviousMask(NULL), fPreviousMask(previousMask),
fBounds(),
fPicture(picture), fViewOrigin(),
fInverse(inverse), fInverse(inverse),
fOrigin(origin), fBackgroundOpacity(0),
fDrawState(drawState), fBits(NULL),
fViewBounds(),
fViewOffset(),
fCachedBitmap(NULL),
fCachedBounds(),
fCachedOffset(),
fBuffer(), fBuffer(),
fCachedMask(), fMask(),
fScanline(fCachedMask) fScanline(fMask)
{
}
AlphaMask::AlphaMask(uint8 backgroundOpacity)
:
fPreviousMask(),
fBounds(),
fViewOrigin(),
fInverse(false),
fBackgroundOpacity(backgroundOpacity),
fBits(NULL),
fBuffer(),
fMask(),
fScanline(fMask)
{ {
fPicture->AcquireReference();
} }
AlphaMask::~AlphaMask() AlphaMask::~AlphaMask()
{ {
fPicture->ReleaseReference(); delete[] fBits;
delete[] fCachedBitmap;
SetPrevious(NULL);
} }
void IntPoint
AlphaMask::Update(BRect bounds, BPoint offset) AlphaMask::SetViewOrigin(IntPoint viewOrigin)
{ {
fViewBounds = bounds; if (viewOrigin == fViewOrigin)
fViewOffset = offset; return fViewOrigin;
IntPoint oldOrigin = fViewOrigin;
fViewOrigin = viewOrigin;
_AttachMaskToBuffer();
if (fPreviousMask != NULL) if (fPreviousMask != NULL)
fPreviousMask->Update(bounds, offset); fPreviousMask->SetViewOrigin(viewOrigin);
}
return oldOrigin;
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;
} }
ServerBitmap* 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); B_RGBA32, 0);
if (bitmap == NULL) if (bitmap == NULL)
return NULL; return NULL;
@@ -183,33 +91,272 @@ AlphaMask::_RenderPicture() const
return NULL; return NULL;
} }
// Clear the bitmap with the transparent color memset(bitmap->Bits(), fBackgroundOpacity, bitmap->BitsLength());
memset(bitmap->Bits(), 0, 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 // Render the picture to the bitmap
BitmapHWInterface interface(bitmap); BitmapHWInterface interface(bitmap);
DrawingEngine* engine = interface.CreateDrawingEngine(); DrawingEngine* engine = interface.CreateDrawingEngine();
if (engine == NULL) { if (engine == NULL) {
delete bitmap; bitmap->ReleaseReference();
return NULL; return NULL;
} }
engine->SetRendererOffset(fBounds.left, fBounds.top);
OffscreenContext context(engine, fDrawState); OffscreenCanvas canvas(engine,
context.PushState(); 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()) { if (engine->LockParallelAccess()) {
// FIXME ConstrainClippingRegion docs says passing NULL disables
// all clipping. This doesn't work and will crash in Painter.
BRegion clipping; BRegion clipping;
clipping.Include(fViewBounds); clipping.Set((clipping_rect)fBounds);
engine->ConstrainClippingRegion(&clipping); engine->ConstrainClippingRegion(&clipping);
fPicture->Play(&context); static_cast<VectorMaskType*>(this)->DrawVectors(&canvas);
engine->UnlockParallelAccess(); engine->UnlockParallelAccess();
} }
context.PopState();
delete engine; delete engine;
return bitmap; 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;
}
+97 -21
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2014, Haiku, Inc. * Copyright 2014-2015, Haiku, Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -13,47 +13,123 @@
#include "DrawState.h" #include "DrawState.h"
#include "drawing/Painter/defines.h" #include "drawing/Painter/defines.h"
#include "IntRect.h"
class BShape;
class ServerBitmap; class ServerBitmap;
class ServerPicture; class ServerPicture;
// #pragma mark - AlphaMask
class AlphaMask : public BReferenceable { class AlphaMask : public BReferenceable {
public: public:
AlphaMask(ServerPicture* mask, bool inverse, AlphaMask(AlphaMask* previousMask,
BPoint origin, const DrawState& drawState); bool inverse);
~AlphaMask(); 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: private:
ServerBitmap* _RenderPicture() const; virtual ServerBitmap* _RenderSource() = 0;
virtual IntPoint _Offset() = 0;
void _AttachMaskToBuffer();
public:
BReference<AlphaMask> fPreviousMask;
IntRect fBounds;
private: private:
AlphaMask* fPreviousMask; IntPoint fViewOrigin;
ServerPicture* fPicture;
const bool fInverse; const bool fInverse;
BPoint fOrigin; uint8 fBackgroundOpacity;
DrawState fDrawState;
BRect fViewBounds;
BPoint fViewOffset;
uint8* fCachedBitmap;
BRect fCachedBounds;
BPoint fCachedOffset;
uint8* fBits;
agg::rendering_buffer fBuffer; agg::rendering_buffer fBuffer;
agg::clipped_alpha_mask fCachedMask; agg::clipped_alpha_mask fMask;
scanline_unpacked_masked_type fScanline; 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 #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 // has not been created either, but we need one to display
// a real BWindow in the test environment. // a real BWindow in the test environment.
// be_app->Run() needs to be called in another thread // 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(); app->Unlock();
thread_id appThread = spawn_thread(run_app_thread, "app thread", thread_id appThread = spawn_thread(run_app_thread, "app thread",
+10 -2
View File
@@ -1,9 +1,10 @@
/* /*
* Copyright 2001-2009, Haiku, Inc. * Copyright 2001-2015, Haiku, Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
@@ -1070,7 +1071,7 @@ DrawingEngine::FillRegion(BRegion& r)
doInSoftware = false; doInSoftware = false;
} }
} }
if (doInSoftware if (doInSoftware
&& (fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0 && (fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0
&& fPainter->Pattern() == B_SOLID_HIGH && 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 void
DrawingEngine::_CopyRect(uint8* src, uint32 width, uint32 height, DrawingEngine::_CopyRect(uint8* src, uint32 width, uint32 height,
uint32 bytesPerRow, int32 xOffset, int32 yOffset) const uint32 bytesPerRow, int32 xOffset, int32 yOffset) const
+4 -1
View File
@@ -1,11 +1,12 @@
/* /*
* Copyright 2001-2009, Haiku, Inc. * Copyright 2001-2015, Haiku, Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
* DarkWyrm <bpmagic@columbus.rr.com> * DarkWyrm <bpmagic@columbus.rr.com>
* Gabe Yoder <gyoder@stny.rr.com> * Gabe Yoder <gyoder@stny.rr.com>
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/ */
#ifndef DRAWING_ENGINE_H_ #ifndef DRAWING_ENGINE_H_
#define DRAWING_ENGINE_H_ #define DRAWING_ENGINE_H_
@@ -187,6 +188,8 @@ public:
virtual BRect CopyRect(BRect rect, int32 xOffset, virtual BRect CopyRect(BRect rect, int32 xOffset,
int32 yOffset) const; int32 yOffset) const;
void SetRendererOffset(int32 offsetX, int32 offsetY);
private: private:
void _CopyRect(uint8* bits, uint32 width, void _CopyRect(uint8* bits, uint32 width,
uint32 height, uint32 bytesPerRow, uint32 height, uint32 bytesPerRow,
+4
View File
@@ -12,6 +12,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes
UseBuildFeatureHeaders freetype ; UseBuildFeatureHeaders freetype ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) drawing_modes ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) drawing_modes ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) bitmap_painter ] ;
local PAINTER_ARCH_SOURCES ; local PAINTER_ARCH_SOURCES ;
if $(TARGET_ARCH) = x86 { if $(TARGET_ARCH) = x86 {
@@ -29,6 +30,9 @@ StaticLibrary libpainter.a :
# drawing_modes # drawing_modes
PixelFormat.cpp PixelFormat.cpp
# bitmap_painter
BitmapPainter.cpp
AGGTextRenderer.cpp AGGTextRenderer.cpp
$(PAINTER_ARCH_SOURCES) $(PAINTER_ARCH_SOURCES)
File diff suppressed because it is too large Load Diff
+15 -61
View File
@@ -1,6 +1,7 @@
/* /*
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>. * 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. * All rights reserved. Distributed under the terms of the MIT License.
* *
* API to the Anti-Grain Geometry based "Painter" drawing backend. Manages * API to the Anti-Grain Geometry based "Painter" drawing backend. Manages
@@ -13,6 +14,7 @@
#include "AGGTextRenderer.h" #include "AGGTextRenderer.h"
#include "FontManager.h" #include "FontManager.h"
#include "PainterAggInterface.h"
#include "PatternHandler.h" #include "PatternHandler.h"
#include "ServerFont.h" #include "ServerFont.h"
#include "Transformable.h" #include "Transformable.h"
@@ -20,7 +22,6 @@
#include "defines.h" #include "defines.h"
#include <agg_conv_curve.h> #include <agg_conv_curve.h>
#include <agg_path_storage.h>
#include <AffineTransform.h> #include <AffineTransform.h>
#include <Font.h> #include <Font.h>
@@ -42,6 +43,11 @@ class ServerBitmap;
class ServerFont; class ServerFont;
// Defines for SIMD support.
#define APPSERVER_SIMD_MMX (1 << 0)
#define APPSERVER_SIMD_SSE (1 << 1)
class Painter { class Painter {
public: public:
Painter(); Painter();
@@ -67,6 +73,8 @@ public:
inline bool IsIdentityTransform() const inline bool IsIdentityTransform() const
{ return fIdentityTransform; } { return fIdentityTransform; }
const Transformable& Transform() const
{ return fTransform; }
void SetHighColor(const rgb_color& color); void SetHighColor(const rgb_color& color);
inline rgb_color HighColor() const inline rgb_color HighColor() const
@@ -243,6 +251,8 @@ public:
inline BRect AlignAndClipRect(BRect rect) const; inline BRect AlignAndClipRect(BRect rect) const;
inline BRect AlignRect(BRect rect) const; inline BRect AlignRect(BRect rect) const;
void SetRendererOffset(int32 offsetX,
int32 offsetY);
private: private:
float _Align(float coord, bool round, float _Align(float coord, bool round,
@@ -270,41 +280,6 @@ private:
const BPoint& viewToScreenOffset, const BPoint& viewToScreenOffset,
float viewScale) const; 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 _InvertRect32(BRect r) const;
void _BlendRect32(const BRect& r, void _BlendRect32(const BRect& r,
const rgb_color& c) const; const rgb_color& c) const;
@@ -353,33 +328,12 @@ private:
int gradientStop = 100) const; int gradientStop = 100) const;
private: private:
mutable agg::rendering_buffer fBuffer; class BitmapPainter;
// AGG rendering and rasterization classes friend class BitmapPainter; // needed only for gcc2
pixfmt fPixelFormat;
mutable renderer_base fBaseRenderer;
// Regular drawing mode: pixel-aligned, no alpha masking private:
mutable scanline_unpacked_type fUnpackedScanline; mutable PainterAggInterface fInternal;
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;
// for internal coordinate rounding/transformation // for internal coordinate rounding/transformation
bool fSubpixelPrecise : 1; 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: public:
typedef int8u cover_type; typedef int8u cover_type;
enum cover_scale_e enum cover_scale_e
{ {
cover_shift = 8, cover_shift = 8,
cover_none = 0, cover_none = 0,
cover_full = 255 cover_full = 255
@@ -44,46 +44,13 @@ namespace agg
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const 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; int count = num_pix;
cover_type* covers = dst; cover_type* covers = dst;
if(y < 0 || y > ymax) bool has_inside = _set_outside(x, y, covers, count);
{ if (!has_inside)
memset(dst, m_outside, num_pix * sizeof(cover_type));
return; 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; const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do do
{ {
@@ -95,6 +62,67 @@ namespace agg
while(--count); 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: private:
int m_xOffset; int m_xOffset;
int m_yOffset; int m_yOffset;
@@ -1,6 +1,7 @@
/* /*
* Copyright 2005-2006, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2005-2006, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>. * 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. * All rights reserved. Distributed under the terms of the MIT License.
* *
* Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
@@ -36,7 +37,9 @@ namespace agg
m_ren(ren), m_ren(ren),
m_region(NULL), m_region(NULL),
m_curr_cb(0), 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(); } unsigned height() const { return m_ren.height(); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
const rect_i& clip_box() const { return m_ren.clip_box(); } const rect_i& clip_box() const { return m_bounds; }
int xmin() const { return m_ren.xmin(); } int xmin() const { return translate_from_base_ren_x(
int ymin() const { return m_ren.ymin(); } m_ren.xmin()); }
int xmax() const { return m_ren.xmax(); } int ymin() const { return translate_from_base_ren_y(
int ymax() const { return m_ren.ymax(); } 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; } const rect_i& bounding_clip_box() const { return m_bounds; }
@@ -69,7 +76,12 @@ namespace agg
if(m_region && m_region->CountRects() > 0) if(m_region && m_region->CountRects() > 0)
{ {
clipping_rect cb = m_region->RectAtInt(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 else
m_ren.clip_box_naked(0, 0, -1, -1); 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()) if(m_region && (int)(++m_curr_cb) < m_region->CountRects())
{ {
clipping_rect cb = m_region->RectAtInt(m_curr_cb); 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 true;
} }
return false; return false;
@@ -94,6 +111,7 @@ namespace agg
m_region = NULL; m_region = NULL;
m_curr_cb = 0; m_curr_cb = 0;
m_bounds = m_ren.clip_box(); 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) void clear(const color_type& c)
{ {
@@ -126,6 +206,8 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c) void copy_pixel(int x, int y, const color_type& c)
{ {
translate_to_base_ren(x, y);
first_clip_box(); first_clip_box();
do do
{ {
@@ -141,6 +223,8 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover) void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{ {
translate_to_base_ren(x, y);
first_clip_box(); first_clip_box();
do do
{ {
@@ -156,6 +240,8 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
color_type pixel(int x, int y) const color_type pixel(int x, int y) const
{ {
translate_to_base_ren(x, y);
first_clip_box(); first_clip_box();
do do
{ {
@@ -171,6 +257,9 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_hline(int x1, int y, int x2, const color_type& c) 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(); first_clip_box();
do do
{ {
@@ -182,6 +271,9 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_vline(int x, int y1, int y2, const color_type& c) 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(); first_clip_box();
do do
{ {
@@ -194,6 +286,9 @@ namespace agg
void blend_hline(int x1, int y, int x2, void blend_hline(int x1, int y, int x2,
const color_type& c, cover_type cover) const color_type& c, cover_type cover)
{ {
translate_to_base_ren(x1, y);
translate_to_base_ren_x(x2);
first_clip_box(); first_clip_box();
do do
{ {
@@ -201,11 +296,14 @@ namespace agg
} }
while(next_clip_box()); while(next_clip_box());
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_vline(int x, int y1, int y2, void blend_vline(int x, int y1, int y2,
const color_type& c, cover_type cover) const color_type& c, cover_type cover)
{ {
translate_to_base_ren(x, y1);
translate_to_base_ren_y(y2);
first_clip_box(); first_clip_box();
do do
{ {
@@ -217,6 +315,9 @@ namespace agg
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) 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(); first_clip_box();
do do
{ {
@@ -229,6 +330,9 @@ namespace agg
void blend_bar(int x1, int y1, int x2, int y2, void blend_bar(int x1, int y1, int x2, int y2,
const color_type& c, cover_type cover) const color_type& c, cover_type cover)
{ {
translate_to_base_ren(x1, y1);
translate_to_base_ren(x2, y2);
first_clip_box(); first_clip_box();
do do
{ {
@@ -242,6 +346,8 @@ namespace agg
void blend_solid_hspan(int x, int y, int len, void blend_solid_hspan(int x, int y, int len,
const color_type& c, const cover_type* covers) const color_type& c, const cover_type* covers)
{ {
translate_to_base_ren(x, y);
first_clip_box(); first_clip_box();
do do
{ {
@@ -254,6 +360,8 @@ namespace agg
void blend_solid_hspan_subpix(int x, int y, int len, void blend_solid_hspan_subpix(int x, int y, int len,
const color_type& c, const cover_type* covers) const color_type& c, const cover_type* covers)
{ {
translate_to_base_ren(x, y);
first_clip_box(); first_clip_box();
do do
{ {
@@ -266,6 +374,8 @@ namespace agg
void blend_solid_vspan(int x, int y, int len, void blend_solid_vspan(int x, int y, int len,
const color_type& c, const cover_type* covers) const color_type& c, const cover_type* covers)
{ {
translate_to_base_ren(x, y);
first_clip_box(); first_clip_box();
do do
{ {
@@ -280,6 +390,8 @@ namespace agg
const cover_type* covers, const cover_type* covers,
cover_type cover = cover_full) cover_type cover = cover_full)
{ {
translate_to_base_ren(x, y);
first_clip_box(); first_clip_box();
do do
{ {
@@ -294,6 +406,8 @@ namespace agg
const cover_type* covers, const cover_type* covers,
cover_type cover = cover_full) cover_type cover = cover_full)
{ {
translate_to_base_ren(x, y);
first_clip_box(); first_clip_box();
do do
{ {
@@ -308,6 +422,7 @@ namespace agg
const cover_type* covers, const cover_type* covers,
cover_type cover = cover_full) cover_type cover = cover_full)
{ {
translate_to_base_ren(x, y);
m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover); m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover);
} }
@@ -317,6 +432,7 @@ namespace agg
const cover_type* covers, const cover_type* covers,
cover_type cover = cover_full) cover_type cover = cover_full)
{ {
translate_to_base_ren(x, y);
m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover); m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover);
} }
@@ -326,6 +442,7 @@ namespace agg
int x_to=0, int x_to=0,
int y_to=0) int y_to=0)
{ {
translate_to_base_ren(x_to, y_to);
first_clip_box(); first_clip_box();
do do
{ {
@@ -343,6 +460,9 @@ namespace agg
BRegion* m_region; BRegion* m_region;
unsigned m_curr_cb; unsigned m_curr_cb;
rect_i m_bounds; 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 // blend_hline_alpha_pc
void 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, const color_type& c, uint8 cover,
agg_buffer* buffer, const PatternHandler* pattern) 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); rgb_color color = pattern->ColorAt(x, y);
uint16 alpha = color.alpha * cover; uint16 alpha = color.alpha * cover;
if (alpha) { if (alpha) {
if (alpha == 255) { if (alpha == 255 * 255) {
ASSIGN_ALPHA_PC(p, color.red, color.green, color.blue); ASSIGN_ALPHA_PC(p, color.red, color.green, color.blue);
} else { } else {
BLEND_ALPHA_PC(p, color.red, color.green, color.blue, alpha); 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 // blend_solid_hspan_alpha_pc
void 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, const color_type& c, const uint8* covers,
agg_buffer* buffer, const PatternHandler* pattern) 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 // blend_solid_vspan_alpha_pc
void 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, const color_type& c, const uint8* covers,
agg_buffer* buffer, const PatternHandler* pattern) 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 // blend_color_hspan_alpha_pc
void void
blend_color_hspan_alpha_pc(int x, int y, unsigned len, blend_color_hspan_alpha_pc(int x, int y, unsigned len,
const color_type* colors, const color_type* colors,
const uint8* covers, uint8 cover, const uint8* covers, uint8 cover,
agg_buffer* buffer, const PatternHandler* pattern) 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. * Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License. * 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 // blend_hline_alpha_po
void 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, const color_type& c, uint8 cover,
agg_buffer* buffer, const PatternHandler* pattern) 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 // blend_solid_hspan_alpha_po
void 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, const color_type& c, const uint8* covers,
agg_buffer* buffer, const PatternHandler* pattern) 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 // blend_solid_vspan_alpha_po
void 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, const color_type& c, const uint8* covers,
agg_buffer* buffer, const PatternHandler* pattern) 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 // blend_color_hspan_alpha_po
void void
blend_color_hspan_alpha_po(int x, int y, unsigned len, blend_color_hspan_alpha_po(int x, int y, unsigned len,
const color_type* colors, const color_type* colors,
const uint8* covers, uint8 cover, const uint8* covers, uint8 cover,
agg_buffer* buffer, const PatternHandler* pattern) agg_buffer* buffer, const PatternHandler* pattern)
{ {
@@ -3,7 +3,7 @@
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>. * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* All rights reserved. Distributed under the terms of the MIT License. * 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. * Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License. * 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 // blend_hline_alpha_po_solid
void 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, const color_type& c, uint8 cover,
agg_buffer* buffer, const PatternHandler* pattern) 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 // blend_solid_hspan_alpha_po_solid
void 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, const color_type& c, const uint8* covers,
agg_buffer* buffer, const PatternHandler* pattern) 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 // blend_solid_vspan_alpha_po_solid
void 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, const color_type& c, const uint8* covers,
agg_buffer* buffer, const PatternHandler* pattern) agg_buffer* buffer, const PatternHandler* pattern)
{ {
@@ -3,7 +3,7 @@
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>. * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* All rights reserved. Distributed under the terms of the MIT License. * 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 "DrawingModeAlphaCO.h"
#include "DrawingModeAlphaCOSolid.h" #include "DrawingModeAlphaCOSolid.h"
#include "DrawingModeAlphaPC.h" #include "DrawingModeAlphaPC.h"
#include "DrawingModeAlphaPCSolid.h"
#include "DrawingModeAlphaPO.h" #include "DrawingModeAlphaPO.h"
#include "DrawingModeAlphaPOSolid.h" #include "DrawingModeAlphaPOSolid.h"
#include "DrawingModeBlend.h" #include "DrawingModeBlend.h"
@@ -211,7 +212,7 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_COPY: case B_OP_COPY:
if (text) { if (text) {
fBlendPixel = blend_pixel_copy_text; fBlendPixel = blend_pixel_copy_text;
fBlendHLine = blend_hline_copy_text; fBlendHLine = blend_hline_copy_text;
fBlendSolidHSpanSubpix = blend_solid_hspan_copy_text_subpix; fBlendSolidHSpanSubpix = blend_solid_hspan_copy_text_subpix;
fBlendSolidHSpan = blend_solid_hspan_copy_text; fBlendSolidHSpan = blend_solid_hspan_copy_text;
fBlendSolidVSpan = blend_solid_vspan_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; fBlendColorHSpan = blend_color_hspan_alpha_po;
} else if (alphaFncMode == B_ALPHA_COMPOSITE) { } else if (alphaFncMode == B_ALPHA_COMPOSITE) {
fBlendPixel = blend_pixel_alpha_pc; if (fPatternHandler->IsSolid()) {
fBlendHLine = blend_hline_alpha_pc; fBlendPixel = blend_pixel_alpha_pc_solid;
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_pc_subpix; fBlendHLine = blend_hline_alpha_pc_solid;
fBlendSolidHSpan = blend_solid_hspan_alpha_pc; fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_pc_subpix;
fBlendSolidVSpan = blend_solid_vspan_alpha_pc; fBlendSolidHSpan = blend_solid_hspan_alpha_pc_solid;
fBlendColorHSpan = blend_color_hspan_alpha_pc; 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; break;
+2 -1
View File
@@ -483,7 +483,8 @@ ViewHWInterface::SetMode(const display_mode& mode)
// has not been created either, but we need one to display // has not been created either, but we need one to display
// a real BWindow in the test environment. // a real BWindow in the test environment.
// be_app->Run() needs to be called in another thread // 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(); app->Unlock();
thread_id appThread = spawn_thread(run_app_thread, "app thread", thread_id appThread = spawn_thread(run_app_thread, "app thread",
+1 -1
View File
@@ -2,7 +2,7 @@
* app_server.rdef * 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 ; resource app_flags B_EXCLUSIVE_LAUNCH ;
+1 -1
View File
@@ -57,7 +57,7 @@ static const bigtime_t kRosterSanityEventInterval = 1000000LL;
*/ */
Registrar::Registrar(status_t* _error) 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), fRoster(NULL),
fClipboardHandler(NULL), fClipboardHandler(NULL),
fMIMEManager(NULL), fMIMEManager(NULL),
+7 -3
View File
@@ -127,6 +127,7 @@ SharedLibrary libtestappserver.so :
ProfileMessageSupport.cpp ProfileMessageSupport.cpp
EventDispatcher.cpp EventDispatcher.cpp
EventStream.cpp EventStream.cpp
TestServerLoopAdapter.cpp
MessageLooper.cpp MessageLooper.cpp
# Decorator # Decorator
@@ -152,10 +153,12 @@ SharedLibrary libtestappserver.so :
AlphaMask.cpp AlphaMask.cpp
BitmapHWInterface.cpp BitmapHWInterface.cpp
Canvas.cpp
DesktopSettings.cpp DesktopSettings.cpp
DrawingContext.cpp Layer.cpp
OffscreenServerWindow.cpp OffscreenServerWindow.cpp
OffscreenWindow.cpp OffscreenWindow.cpp
PictureBoundingBoxPlayer.cpp
RegionPool.cpp RegionPool.cpp
Screen.cpp Screen.cpp
ScreenConfigurations.cpp ScreenConfigurations.cpp
@@ -173,9 +176,9 @@ SharedLibrary libtestappserver.so :
[ BuildFeatureAttribute freetype : library ] [ BuildFeatureAttribute freetype : library ]
; ;
Includes [ FGristFiles AppServer.cpp BitmapManager.cpp Includes [ FGristFiles AppServer.cpp BitmapManager.cpp Canvas.cpp
ClientMemoryAllocator.cpp Desktop.cpp DesktopSettings.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 ServerBitmap.cpp ServerCursor.cpp ServerFont.cpp ServerPicture.cpp
ServerWindow.cpp View.cpp Window.cpp WorkspacesView.cpp ServerWindow.cpp View.cpp Window.cpp WorkspacesView.cpp
$(decorator_src) $(font_src) ] $(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 stress_test ;
SubInclude HAIKU_TOP src tests servers app textview ; SubInclude HAIKU_TOP src tests servers app textview ;
SubInclude HAIKU_TOP src tests servers app transformation ; 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_state ;
SubInclude HAIKU_TOP src tests servers app view_transit ; SubInclude HAIKU_TOP src tests servers app view_transit ;
SubInclude HAIKU_TOP src tests servers app window_creation ; 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;
}
+15
View File
@@ -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(&region);
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(&region);
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], &regions[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
+1 -1
View File
@@ -110,7 +110,7 @@ Server test_registrar
libstorage_kit_mime.a libstorage_kit_mime.a
be localestub [ TargetLibstdc++ ] be localestub [ TargetLibstdc++ ]
: :
registrar.rdef test_registrar.rdef
; ;
if $(TARGET_PLATFORM) = libbe_test { if $(TARGET_PLATFORM) = libbe_test {
@@ -53,7 +53,7 @@ main(int argc, char* argv[])
while (get_next_thread_info(teamInfo.team, &threadCookie, &threadInfo) while (get_next_thread_info(teamInfo.team, &threadCookie, &threadInfo)
== B_OK) { == B_OK) {
// search for the roster thread // 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_id port = find_port("haiku-test:roster");
port_info portInfo; port_info portInfo;
if (get_port_info(port, &portInfo) == B_OK 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