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,
|
||||
long offset, BPoint where);
|
||||
|
||||
void BeginLayer(uint8 opacity);
|
||||
void EndLayer();
|
||||
|
||||
status_t SetEventMask(uint32 mask, uint32 options = 0);
|
||||
uint32 EventMask();
|
||||
status_t SetMouseEventMask(uint32 mask,
|
||||
|
@ -7,6 +7,7 @@
|
||||
* Jérôme Duval, jerome.duval@free.fr
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
|
||||
* Julian Harnath, <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef APP_SERVER_PROTOCOL_H
|
||||
#define APP_SERVER_PROTOCOL_H
|
||||
@ -319,6 +320,8 @@ enum {
|
||||
AS_VIEW_SET_VIEW_BITMAP,
|
||||
AS_VIEW_SET_PATTERN,
|
||||
AS_SET_CURRENT_VIEW,
|
||||
AS_VIEW_BEGIN_LAYER,
|
||||
AS_VIEW_END_LAYER,
|
||||
|
||||
// BDirectWindow/BWindowScreen codes
|
||||
AS_DIRECT_WINDOW_GET_SYNC_DATA,
|
||||
|
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Haiku, Inc. All rights reserved.
|
||||
* Copyright 2006-2015 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stefano Ceccherini, burton666@libero.it
|
||||
* Julian Harnath, <julian.harnath@rwth-achen.de>
|
||||
*/
|
||||
#ifndef _PICTURE_DATA_WRITER_H
|
||||
#define _PICTURE_DATA_WRITER_H
|
||||
@ -17,6 +18,7 @@
|
||||
#include <stack>
|
||||
|
||||
|
||||
class Layer;
|
||||
class BPositionIO;
|
||||
class BRegion;
|
||||
|
||||
@ -91,6 +93,8 @@ public:
|
||||
status_t WriteDrawPicture(const BPoint& where,
|
||||
const int32& token);
|
||||
|
||||
status_t WriteBlendLayer(Layer* layer);
|
||||
|
||||
protected:
|
||||
// throw a status_t on error
|
||||
void BeginOp(const int16& op);
|
||||
|
@ -52,10 +52,11 @@ enum {
|
||||
B_PIC_SET_FONT_BPP = 0x0388,
|
||||
B_PIC_SET_FONT_FACE = 0x0389,
|
||||
B_PIC_SET_TRANSFORM = 0x0390,
|
||||
B_PIC_BLEND_LAYER = 0x0391
|
||||
};
|
||||
|
||||
|
||||
const static uint32 kOpsTableSize = 49;
|
||||
const static uint32 kOpsTableSize = 50;
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2006-2009 Haiku, Inc. All rights reserved.
|
||||
* Copyright 2006-2015 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Stefano Ceccherini, stefano.ceccherini@gmail.com
|
||||
* Julian Harnath, <julian.harnath@rwth-achen.de>
|
||||
*/
|
||||
|
||||
#include <PictureDataWriter.h>
|
||||
@ -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
|
||||
void
|
||||
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.
|
||||
*
|
||||
* Authors:
|
||||
* Marc Flerackers (mflerackers@androme.be)
|
||||
* Stefano Ceccherini (stefano.ceccherini@gmail.com)
|
||||
* Marcus Overhagen (marcus@overhagen.de)
|
||||
* Julian Harnath (julian.harnath@rwth-aachen.de)
|
||||
*/
|
||||
|
||||
/** PicturePlayer is used to play picture data. */
|
||||
@ -23,6 +24,9 @@
|
||||
using BPrivate::PicturePlayer;
|
||||
|
||||
|
||||
class Layer;
|
||||
|
||||
|
||||
typedef void (*fnc)(void*);
|
||||
typedef void (*fnc_BPoint)(void*, 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_BShape)(void*, BShape*);
|
||||
typedef void (*fnc_BAffineTransform)(void*, BAffineTransform);
|
||||
typedef void (*fnc_Layer)(void*, const Layer*);
|
||||
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
if ((uint32)tableEntries < kOpsTableSize) {
|
||||
@ -546,6 +551,13 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData)
|
||||
break;
|
||||
}
|
||||
|
||||
case B_PIC_BLEND_LAYER:
|
||||
{
|
||||
((fnc_Layer)functionTable[49])(userData,
|
||||
*reinterpret_cast<Layer* const*>(data));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Adrian Oanca, adioanca@cotty.iren.ro
|
||||
* Ingo Weinhold. ingo_weinhold@gmx.de
|
||||
* Julian Harnath, julian.harnath@rwth-aachen.de
|
||||
*/
|
||||
|
||||
|
||||
@ -3933,6 +3934,27 @@ BView::DrawPictureAsync(const char* filename, long offset, BPoint where)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BView::BeginLayer(uint8 opacity)
|
||||
{
|
||||
if (_CheckOwnerLockAndSwitchCurrent()) {
|
||||
fOwner->fLink->StartMessage(AS_VIEW_BEGIN_LAYER);
|
||||
fOwner->fLink->Attach<uint8>(opacity);
|
||||
_FlushIfNotInTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BView::EndLayer()
|
||||
{
|
||||
if (_CheckOwnerLockAndSwitchCurrent()) {
|
||||
fOwner->fLink->StartMessage(AS_VIEW_END_LAYER);
|
||||
_FlushIfNotInTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BView::Invalidate(BRect invalRect)
|
||||
{
|
||||
@ -5225,7 +5247,7 @@ BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
|
||||
if (picture == NULL) {
|
||||
fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
|
||||
fOwner->fLink->Attach<int32>(-1);
|
||||
|
||||
|
||||
// NOTE: No need to sync here, since the -1 token cannot
|
||||
// become invalid on the server.
|
||||
} else {
|
||||
@ -5240,7 +5262,7 @@ BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
|
||||
// the client creates BPictures on the stack, these BPictures may
|
||||
// have issued a AS_DELETE_PICTURE command to the ServerApp when Draw()
|
||||
// goes out of scope, and the command is processed earlier in the
|
||||
// ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
|
||||
// ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
|
||||
// ServerWindow thread, which will then have the result that no
|
||||
// ServerPicture is found of the token.
|
||||
if (sync)
|
||||
|
@ -19,8 +19,10 @@
|
||||
|
||||
#include <Region.h>
|
||||
|
||||
#include "AlphaMask.h"
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "Layer.h"
|
||||
|
||||
|
||||
#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
|
||||
|
||||
|
||||
|
@ -27,6 +27,7 @@ class DrawingEngine;
|
||||
class DrawState;
|
||||
class IntPoint;
|
||||
class IntRect;
|
||||
class Layer;
|
||||
class ServerPicture;
|
||||
|
||||
|
||||
@ -61,6 +62,8 @@ public:
|
||||
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;
|
||||
|
@ -67,6 +67,7 @@ Server app_server :
|
||||
InputManager.cpp
|
||||
IntPoint.cpp
|
||||
IntRect.cpp
|
||||
Layer.cpp
|
||||
MessageLooper.cpp
|
||||
MultiLocker.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 "FontManager.h"
|
||||
#include "Layer.h"
|
||||
#include "ServerApp.h"
|
||||
#include "ServerBitmap.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 void*)nop, // 0
|
||||
(const void*)move_pen_by,
|
||||
@ -753,7 +766,8 @@ const static void* kTableEntries[] = {
|
||||
(const void*)nop, // 45
|
||||
(const void*)set_font_face,
|
||||
(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 "DrawState.h"
|
||||
#include "FontManager.h"
|
||||
#include "Layer.h"
|
||||
#include "ServerApp.h"
|
||||
#include "ServerBitmap.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
|
||||
reserved()
|
||||
{
|
||||
@ -839,7 +847,8 @@ const static void* kTableEntries[] = {
|
||||
(const void*)reserved, // 45
|
||||
(const void*)set_font_face,
|
||||
(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.
|
||||
*
|
||||
* Authors:
|
||||
* DarkWyrm <bpmagic@columbus.rr.com>
|
||||
* Stefano Ceccherini <stefano.ceccherini@gmail.com>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef SERVER_PICTURE_H
|
||||
#define SERVER_PICTURE_H
|
||||
@ -35,7 +36,7 @@ public:
|
||||
ServerPicture(const ServerPicture& other);
|
||||
ServerPicture(const char* fileName,
|
||||
int32 offset);
|
||||
~ServerPicture();
|
||||
virtual ~ServerPicture();
|
||||
|
||||
int32 Token() { return fToken; }
|
||||
bool SetOwner(ServerApp* owner);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2010, Haiku.
|
||||
* Copyright 2001-2015, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@ -11,6 +11,7 @@
|
||||
* Artur Wyszynski <harakash@gmail.com>
|
||||
* Philippe Saint-Pierre <stpere@gmail.com>
|
||||
* Brecht Machiels <brecht@mos6581.org>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
|
||||
|
||||
@ -61,6 +62,7 @@
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "HWInterface.h"
|
||||
#include "Layer.h"
|
||||
#include "Overlay.h"
|
||||
#include "ProfileMessageSupport.h"
|
||||
#include "RenderingBuffer.h"
|
||||
@ -2184,6 +2186,21 @@ fDesktop->LockSingleWindow();
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_VIEW_BEGIN_LAYER:
|
||||
{
|
||||
DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_LAYER\n",
|
||||
Title()));
|
||||
|
||||
uint8 opacity;
|
||||
link.Read<uint8>(&opacity);
|
||||
|
||||
Layer* layer = new(std::nothrow) Layer(opacity);
|
||||
if (layer == NULL)
|
||||
break;
|
||||
fCurrentView->SetPicture(layer);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
_DispatchViewDrawingMessage(code, link);
|
||||
break;
|
||||
@ -2922,6 +2939,15 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_VIEW_END_LAYER:
|
||||
{
|
||||
DTRACE(("ServerWindow %s: Message AS_VIEW_END_LAYER\n",
|
||||
Title()));
|
||||
fCurrentView->BlendAllLayers();
|
||||
fCurrentView->SetPicture(NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BString codeString;
|
||||
string_for_message_code(code, codeString);
|
||||
@ -2983,6 +3009,11 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
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);
|
||||
|
||||
fCurrentView->CurrentState()->SetDrawingMode(
|
||||
@ -3416,6 +3447,42 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link)
|
||||
fLink.Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
case AS_VIEW_BEGIN_LAYER:
|
||||
{
|
||||
uint8 opacity;
|
||||
link.Read<uint8>(&opacity);
|
||||
|
||||
Layer* layer = dynamic_cast<Layer*>(picture);
|
||||
if (layer == NULL)
|
||||
break;
|
||||
|
||||
Layer* nextLayer = new(std::nothrow) Layer(opacity);
|
||||
if (nextLayer == NULL)
|
||||
break;
|
||||
|
||||
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:
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014, Haiku, Inc.
|
||||
* Copyright (c) 2001-2015, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
@ -9,6 +9,7 @@
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#include "View.h"
|
||||
|
||||
@ -19,6 +20,7 @@
|
||||
#include "Desktop.h"
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "Layer.h"
|
||||
#include "Overlay.h"
|
||||
#include "ServerApp.h"
|
||||
#include "ServerBitmap.h"
|
||||
@ -27,6 +29,7 @@
|
||||
#include "ServerWindow.h"
|
||||
#include "Window.h"
|
||||
|
||||
#include "BitmapHWInterface.h"
|
||||
#include "drawing_support.h"
|
||||
|
||||
#include <List.h>
|
||||
@ -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
|
||||
View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
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.
|
||||
*
|
||||
* Authors:
|
||||
@ -9,6 +9,7 @@
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
* Marcus Overhagen <marcus@overhagen.de>
|
||||
* Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
* Julian Harnath <julian.harnath@rwth-aachen.de>
|
||||
*/
|
||||
#ifndef VIEW_H
|
||||
#define VIEW_H
|
||||
@ -156,6 +157,8 @@ public:
|
||||
ServerPicture* Picture() const
|
||||
{ return fPicture; }
|
||||
|
||||
void BlendAllLayers();
|
||||
|
||||
// for background clearing
|
||||
virtual void Draw(DrawingEngine* drawingEngine,
|
||||
BRegion* effectiveClipping,
|
||||
|
@ -154,6 +154,7 @@ SharedLibrary libtestappserver.so :
|
||||
BitmapHWInterface.cpp
|
||||
Canvas.cpp
|
||||
DesktopSettings.cpp
|
||||
Layer.cpp
|
||||
OffscreenServerWindow.cpp
|
||||
OffscreenWindow.cpp
|
||||
PictureBoundingBoxPlayer.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user