app_server: add new BView layers API
* Add new methods BView::BeginLayer(uint8 opacity) BView::EndLayer() * All drawing between begin and end of a layer is redirected onto an intermediate bitmap. When ending the layer, this bitmap is composited onto the view with the opacity given when the layer was started. * Layers can be nested arbitrarily and will be blended onto each other in order. There can also be any arbitrary interleaving of layer begin/end and drawing operations. * Internally, drawing commands are redirected into a BPicture between BeginLayer and EndLayer (but client code need not know or care about this). Client code can also start/end other BPictures while inside a layer. * Uses the PictureBoundingBoxPlayer to determine the size of the layer bitmap before allocating and drawing into it, so it does not allocate more memory than necessary and -- more importantly -- it will not alpha-composite more pixels than necessary. * Drawing mode is always set to B_OP_ALPHA, blend mode to (B_PIXEL_ALPHA, B_ALPHA_COMPOSITE) while inside layers. This is necessary for (a) correct compositing output and (b) for redirection of drawing into the intermediate bitmap, which uses the renderer_region offset (in B_OP_COPY, the Painter does not use the AGG renderer methods, it directly accesses the pixel data. This would access out-of-bounds without the offset, so B_OP_COPY cannot be allowed.) To ensure these modes aren't changed, BView::SetDrawingMode() and BView::SetBlendingMode() are ignored while inside a layer. * The main motivation behind this new API is WebKit, which internally expects such a layers functionality to be present. A performant and reusable implementation of this functionality can only be done server-side in app_server.
This commit is contained in:
parent
d56beda4d8
commit
551438b9be
@ -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,
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
* Jérôme Duval, jerome.duval@free.fr
|
* Jérôme Duval, jerome.duval@free.fr
|
||||||
* Axel Dörfler, axeld@pinc-software.de
|
* Axel Dörfler, axeld@pinc-software.de
|
||||||
* Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
|
* Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
|
||||||
|
* Julian Harnath, <julian.harnath@rwth-aachen.de>
|
||||||
*/
|
*/
|
||||||
#ifndef APP_SERVER_PROTOCOL_H
|
#ifndef APP_SERVER_PROTOCOL_H
|
||||||
#define APP_SERVER_PROTOCOL_H
|
#define APP_SERVER_PROTOCOL_H
|
||||||
@ -319,6 +320,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, burton666@libero.it
|
* Stefano Ceccherini, burton666@libero.it
|
||||||
|
* Julian Harnath, <julian.harnath@rwth-achen.de>
|
||||||
*/
|
*/
|
||||||
#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;
|
||||||
|
|
||||||
@ -91,6 +93,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);
|
||||||
|
@ -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
|
||||||
|
@ -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, stefano.ceccherini@gmail.com
|
* Stefano Ceccherini, stefano.ceccherini@gmail.com
|
||||||
|
* Julian Harnath, <julian.harnath@rwth-achen.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <PictureDataWriter.h>
|
#include <PictureDataWriter.h>
|
||||||
@ -641,6 +642,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)
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2007, 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:
|
||||||
* 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)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** PicturePlayer is used to play picture data. */
|
/** PicturePlayer is used to play picture data. */
|
||||||
@ -23,6 +24,9 @@
|
|||||||
using BPrivate::PicturePlayer;
|
using BPrivate::PicturePlayer;
|
||||||
|
|
||||||
|
|
||||||
|
class Layer;
|
||||||
|
|
||||||
|
|
||||||
typedef void (*fnc)(void*);
|
typedef void (*fnc)(void*);
|
||||||
typedef void (*fnc_BPoint)(void*, BPoint);
|
typedef void (*fnc_BPoint)(void*, BPoint);
|
||||||
typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint);
|
typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint);
|
||||||
@ -47,6 +51,7 @@ typedef void (*fnc_DrawPixels)(void *, BRect, BRect, int32, int32, int32,
|
|||||||
typedef void (*fnc_DrawPicture)(void *, BPoint, int32);
|
typedef void (*fnc_DrawPicture)(void *, BPoint, int32);
|
||||||
typedef void (*fnc_BShape)(void*, BShape*);
|
typedef void (*fnc_BShape)(void*, BShape*);
|
||||||
typedef void (*fnc_BAffineTransform)(void*, BAffineTransform);
|
typedef void (*fnc_BAffineTransform)(void*, BAffineTransform);
|
||||||
|
typedef void (*fnc_Layer)(void*, const Layer*);
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -160,7 +165,7 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData)
|
|||||||
(void *)nop, (void *)nop, (void *)nop, (void *)nop,
|
(void *)nop, (void *)nop, (void *)nop, (void *)nop,
|
||||||
(void *)nop, (void *)nop, (void *)nop, (void *)nop,
|
(void *)nop, (void *)nop, (void *)nop, (void *)nop,
|
||||||
(void *)nop, (void *)nop, (void *)nop, (void *)nop,
|
(void *)nop, (void *)nop, (void *)nop, (void *)nop,
|
||||||
(void *)nop
|
(void *)nop, (void *)nop
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((uint32)tableEntries < kOpsTableSize) {
|
if ((uint32)tableEntries < kOpsTableSize) {
|
||||||
@ -546,6 +551,13 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case B_PIC_BLEND_LAYER:
|
||||||
|
{
|
||||||
|
((fnc_Layer)functionTable[49])(userData,
|
||||||
|
*reinterpret_cast<Layer* const*>(data));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
|
|
||||||
#include <Region.h>
|
#include <Region.h>
|
||||||
|
|
||||||
|
#include "AlphaMask.h"
|
||||||
#include "DrawingEngine.h"
|
#include "DrawingEngine.h"
|
||||||
#include "DrawState.h"
|
#include "DrawState.h"
|
||||||
|
#include "Layer.h"
|
||||||
|
|
||||||
|
|
||||||
#if __GNUC__ >= 3
|
#if __GNUC__ >= 3
|
||||||
@ -218,6 +220,46 @@ Canvas::ScreenToPenTransform() const GCC_2_NRV(transform)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Canvas::BlendLayer(Layer* layer)
|
||||||
|
{
|
||||||
|
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 AlphaMask(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
|
// #pragma mark - OffscreenCanvas
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ class DrawingEngine;
|
|||||||
class DrawState;
|
class DrawState;
|
||||||
class IntPoint;
|
class IntPoint;
|
||||||
class IntRect;
|
class IntRect;
|
||||||
|
class Layer;
|
||||||
class ServerPicture;
|
class ServerPicture;
|
||||||
|
|
||||||
|
|
||||||
@ -61,6 +62,8 @@ public:
|
|||||||
SimpleTransform PenToLocalTransform() const;
|
SimpleTransform PenToLocalTransform() const;
|
||||||
SimpleTransform ScreenToPenTransform() const;
|
SimpleTransform ScreenToPenTransform() const;
|
||||||
|
|
||||||
|
void BlendLayer(Layer* layer);
|
||||||
|
|
||||||
virtual DrawingEngine* GetDrawingEngine() const = 0;
|
virtual DrawingEngine* GetDrawingEngine() const = 0;
|
||||||
virtual ServerPicture* GetPicture(int32 token) const = 0;
|
virtual ServerPicture* GetPicture(int32 token) const = 0;
|
||||||
virtual void RebuildClipping(bool deep) = 0;
|
virtual void RebuildClipping(bool deep) = 0;
|
||||||
|
@ -67,6 +67,7 @@ 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
|
||||||
|
216
src/servers/app/Layer.cpp
Normal file
216
src/servers/app/Layer.cpp
Normal 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();
|
||||||
|
BPoint oldOffset;
|
||||||
|
if (mask != NULL) {
|
||||||
|
// Move alpha mask to bitmap origin
|
||||||
|
oldOffset = mask->Update(BPoint(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas->CurrentState()->SetDrawingMode(B_OP_ALPHA);
|
||||||
|
canvas->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
|
||||||
|
|
||||||
|
layerCanvas.ResyncDrawState();
|
||||||
|
// Apply state to the new drawing engine of the layer canvas
|
||||||
|
|
||||||
|
if (layerEngine->LockParallelAccess()) {
|
||||||
|
const BRegion region(boundingBox);
|
||||||
|
layerEngine->ConstrainClippingRegion(®ion);
|
||||||
|
|
||||||
|
// Draw recorded picture into bitmap
|
||||||
|
Play(&layerCanvas);
|
||||||
|
layerEngine->UnlockParallelAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask != NULL) {
|
||||||
|
// Move alpha mask back to its old position
|
||||||
|
// Note: this needs to be adapted if setting alpha masks is
|
||||||
|
// implemented as BPicture command (the mask now might be a different
|
||||||
|
// one than before).
|
||||||
|
mask->Update(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
src/servers/app/Layer.h
Normal file
42
src/servers/app/Layer.h
Normal 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
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#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"
|
||||||
@ -704,6 +705,18 @@ set_transform(BoundingBoxState* state, BAffineTransform transform)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
determine_bounds_nested_layer(BoundingBoxState* state, Layer* layer)
|
||||||
|
{
|
||||||
|
TRACE_BB("%p nested layer\n", state);
|
||||||
|
|
||||||
|
BRect boundingBox;
|
||||||
|
PictureBoundingBoxPlayer::Play(layer, state->GetDrawState(), &boundingBox);
|
||||||
|
if (boundingBox.IsValid())
|
||||||
|
state->IncludeRect(boundingBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const static void* kTableEntries[] = {
|
const static void* kTableEntries[] = {
|
||||||
(const void*)nop, // 0
|
(const void*)nop, // 0
|
||||||
(const void*)move_pen_by,
|
(const void*)move_pen_by,
|
||||||
@ -753,7 +766,8 @@ const static void* kTableEntries[] = {
|
|||||||
(const void*)nop, // 45
|
(const void*)nop, // 45
|
||||||
(const void*)set_font_face,
|
(const void*)set_font_face,
|
||||||
(const void*)set_blending_mode,
|
(const void*)set_blending_mode,
|
||||||
(const void*)set_transform // 48
|
(const void*)set_transform,
|
||||||
|
(const void*)determine_bounds_nested_layer // 49
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,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"
|
||||||
@ -784,6 +785,13 @@ set_transform(Canvas* canvas, BAffineTransform transform)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
blend_layer(Canvas* canvas, Layer* layer)
|
||||||
|
{
|
||||||
|
canvas->BlendLayer(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reserved()
|
reserved()
|
||||||
{
|
{
|
||||||
@ -839,7 +847,8 @@ const static void* kTableEntries[] = {
|
|||||||
(const void*)reserved, // 45
|
(const void*)reserved, // 45
|
||||||
(const void*)set_font_face,
|
(const void*)set_font_face,
|
||||||
(const void*)set_blending_mode,
|
(const void*)set_blending_mode,
|
||||||
(const void*)set_transform // 48
|
(const void*)set_transform,
|
||||||
|
(const void*)blend_layer // 49
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -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);
|
||||||
|
@ -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"
|
||||||
@ -2184,6 +2186,21 @@ 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;
|
||||||
|
fCurrentView->SetPicture(layer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_DispatchViewDrawingMessage(code, link);
|
_DispatchViewDrawingMessage(code, link);
|
||||||
break;
|
break;
|
||||||
@ -2922,6 +2939,15 @@ 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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BString codeString;
|
BString codeString;
|
||||||
string_for_message_code(code, codeString);
|
string_for_message_code(code, codeString);
|
||||||
@ -2983,6 +3009,11 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link)
|
|||||||
int8 drawingMode;
|
int8 drawingMode;
|
||||||
link.Read<int8>(&drawingMode);
|
link.Read<int8>(&drawingMode);
|
||||||
|
|
||||||
|
if (dynamic_cast<Layer*>(picture) != NULL) {
|
||||||
|
// drawing mode changes not allowed in layers
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
picture->WriteSetDrawingMode((drawing_mode)drawingMode);
|
picture->WriteSetDrawingMode((drawing_mode)drawingMode);
|
||||||
|
|
||||||
fCurrentView->CurrentState()->SetDrawingMode(
|
fCurrentView->CurrentState()->SetDrawingMode(
|
||||||
@ -3416,6 +3447,42 @@ 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;
|
||||||
|
|
||||||
|
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:
|
||||||
{
|
{
|
||||||
|
@ -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>
|
||||||
@ -972,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)
|
||||||
|
@ -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>
|
||||||
*/
|
*/
|
||||||
#ifndef VIEW_H
|
#ifndef VIEW_H
|
||||||
#define VIEW_H
|
#define VIEW_H
|
||||||
@ -156,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,
|
||||||
|
@ -154,6 +154,7 @@ SharedLibrary libtestappserver.so :
|
|||||||
BitmapHWInterface.cpp
|
BitmapHWInterface.cpp
|
||||||
Canvas.cpp
|
Canvas.cpp
|
||||||
DesktopSettings.cpp
|
DesktopSettings.cpp
|
||||||
|
Layer.cpp
|
||||||
OffscreenServerWindow.cpp
|
OffscreenServerWindow.cpp
|
||||||
OffscreenWindow.cpp
|
OffscreenWindow.cpp
|
||||||
PictureBoundingBoxPlayer.cpp
|
PictureBoundingBoxPlayer.cpp
|
||||||
|
Loading…
Reference in New Issue
Block a user