[haiku-commits] haiku: hrev49807 - in src: servers/app servers/app/drawing/Painter servers/app/drawing/Painter/bitmap_painter servers/app/drawing tests/servers/app/unit_tests

  • From: julian.harnath@xxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 11 Nov 2015 00:02:27 +0100 (CET)

hrev49807 adds 41 changesets to branch 'master'
old head: a29ff41ec711b4d124c4d3d5512baa82aded8dae
new head: 959355842feef458222e6b1648b29ccf9671de51
overview:
http://cgit.haiku-os.org/haiku/log/?qt=range&q=959355842fee+%5Ea29ff41ec711

----------------------------------------------------------------------------

ab1bd2fd07b5: app_server: rename DrawingContext to Canvas

* Better reflects the purpose of the class: an interface for things
in which we can draw (e.g. a View)

* Accordingly rename OffscreenContext to OffscreenCanvas

6f2a446e2eb8: app_server: extract coordinate conversion class

* Move coordinate conversion into a new class SimpleTransform. It
supports scaling and translation which is sufficient for conversion
between screen, local and pen (drawing) coordinates.

* Because all the overloaded methods for converting
BPoint/BRect/BRegion/etc are now within the single SimpleTransform
class, the interfaces of Canvas, View, DrawState, etc. are slimmed
down. These classes have too many responsibilities, so some will be
factored out into separate classes, this being the first.

ad53a0d99913: app_server: add unit test add-on, test for SimpleTransform

* app_server currently does not have any real unit tests, making
changes more difficult and riskier. A new directory unit_tests with
a test add-on is added in app_server's tetsts directory to hold
future unit tests.

* Add test for SimpleTransform class

ccaee9e818cc: app_server: add Squash method in DrawState

* New method DrawState::Squash() uses the combined scale, origin and
transform as the state's own scale, origin, transform.

This can be used when making copies of DrawStates which have
previous states below them in the state stack. The top of stack
DrawState can be copied, squashed and then used just like the
original one with the whole stack below it (except of course
when trying to pop off any earlier state).

1b4dba929dd3: app_server: add picture player for determining bounding box

* Add PictureBoundingBoxPlayer, a new player for BPictures. Instead
of drawing the picture, it determines an approximate bounding box
of its contained drawing operations.

* To increase performance, the resulting bounding box is an
approximation: it guarantees to always enclose all pixels of the
picture, however not necessarily tightly.

* PictureBoundingBoxPlayer::Play() gets a DrawState which is the
initial state used when playing the picture. The player does not
modify this state (it uses a copy internally), so the method is
idempotent.

8511f6ac9b4d: app_server: fix ServerPicture::SyncState pen size

* Should use the unscaled pen size here because we also write down
the current scale, and we don't want to scale the pen twice.

ae0468762f2f: app_server: add Canvas::PenToLocalTransform

c34cbf2878cb: app_server: fix PicturePlayer dummy function table

* With the support for BAffineTransform, it needs to have 49 entries

b5c7f936de1a: app_server: allow replacing the DrawState in a Canvas

* Needed for layers support. The previously set DrawState and its
stack predecessors are not freed, so take care to not leak memory
when using this.

65a54d2892d4: app_server: implement setting BAffineTransforms in BPicture

* Add a simple callback for the picture command

edc0b5e9db34: app_server: allow disabling affine transforms in DrawState

* New method DrawState::SetTransformEnabled allows to temporarily
disable all BAffineTransforms in the state stack (up to 'this').
Later, the same method can be used to reenable the transforms.

Needed for layers support: when drawing the finished layer bitmap
onto the view, the affine transforms must not be applied again --
they have already been applied while drawing the bitmap's contents.

6ac468ef24f6: app_server: add support for uniform opacity alpha masks

* Another constructor for AlphaMask allows creating a mask with no
picture, it will simply be a single uniform alpha value over the
whole mask.

* No need to even allocate a buffer in this case, we can just use
the feature of clipped_alpha_mask to define an opacity for outside
the mask, and set the buffer size to zero.

cd621b9585b4: app_server: add method to shift alpha masks

* Allow shifting the offset of alpha masks without changing the size.
Ideally, we only need to reattach the buffer in the shifted
position, saving the work of reallocating and redrawing the mask
picture. Needed for layers support.

d56beda4d8fa: app_server: optional coordinate shifting in renderer_region

* agg::renderer_region gets an extra feature which allows to
optionally shift the coordinates by a specified offset.

* This allows to shift coordinates at the lowest level, even below
the transformations done by BAffineTransform (which happen in the
painter, right before rasterization).

Needed for layers support: shifts the origin of the layer bitmaps
to their position in the view while keeping all transformations
(BView origin/scale transforms as well as BAffineTransforms)
intact. The offset for the layer bitmaps within their parent view
is determined by the bounding box and is then fixed, it must not
be altered while the layer's BPicture is played into the bitmap.

If this offset were added to the BView origin or as translation in
the BAffineTransform, it would be further transformed by the BView
scale or the other affine transform parameters. Thus, we need
another low-level offset mechanism which is even below
BAffineTransform's transformations.

551438b9be6b: 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.

d727d0743b2f: app_server: fix clearing user clipping from BPicture

* Clipping was set to an empty region instead of being cleared
when inside a BPicture

3d12d3a83246: app_server: special handling for opaque/invisible layers

* Opaque layers (opacity = 255) don't need to use an intermediate
bitmap (and everything that comes with it) for drawing at all,
they can just directly draw onto the underlying canvas or layer.
(WebKit likes to use plenty of opaque layers)

* Invisible layers (opacity = 0) can simply be ignored.

c77b945acdc5: app_server: allow drawing mode changes in opaque layers

* For better performance, we allow doing drawing mode changes
(and thus, B_OP_COPY) again when inside an opaque layer which
has only other opaque layers below it in the layer stack.

As soon as the first non-opaque layer turns up in the stack, the
drawing mode will be locked to alpha composite mode, until this
layer stack is ended entirely.

This allows using B_OP_COPY in many cases as used by WebKit.

* In the long term it would be nice to get rid of the drawing-mode
lock altogether, however that would need some larger refactoring
work in Painter (i.e. remove the offsetting from renderer_region
again and instead implement an "exit-level transform" (support
for offsets is enough) in Painter which is applied after all other
transforms).

e353fe396a36: app_server Painter: refactoring, extract bitmap drawing

* Extract bitmap drawing from Painter into separate class
Painter::BitmapPainter. This will allow to add new optimized
drawing modes without making Painter larger.

* BitmapPainter itself is further decomposed into separate
(method object) structs per drawing mode (currently, those are:
generic, no scale, nearest neighbor, bilinear). New optimized
implementations can be added by writing additional method objects
and calling them from BitmapPainter.

* DrawBitmapNoScale and DrawBitmapBilinear are implemented using
CRTP. This removes the function pointer in the 'no scale' version,
which was previously used to select the row copy type. In the
bilinear version it untangles the three variants (default,
low filter ratio, SIMD) into separate methods.

* While BitmapPainter is a nested class in Painter, the specialized
method objects are not. Instead, the AGG-specific data fields from
Painter are moved into a new struct PainterAggInterface. This
struct is passed to the method objects and allows them to access
the Painter's AGG renderer/rasterizer/scanline containers/etc.

Alternatives would be to make all the involved structs friends
of Painter, or nesting them all, or exposing all of Painter's
internals via getter methods -- all of these would be quite messy.

The details of the bitmap painting implementations are
intentionally hidden from Painter: there is no need for it to
know about their internals -- it does not even know their type
names. (Nesting or making them friend would expose their type
names to Painter.)

Furthermore, there is another level of information hiding between
BitmapPainter and the DrawBitmap[...] method objects.
BitmapPainter itself only needs to decide that it uses e.g. the
bilinear version. It has no knowledge that DrawBitmapBilinear is
internally made out of several structs implementing specially
optimized versions.

* Refactoring only, no functional change intended. Performance
should be unaffected.

2a58d5432d9a: Merge branch 'master' into app_server

f4f05935dbe4: app_server: give Painter direct access to alpha masks

* To use alpha masks in optimized drawing code outside of the AGG
renderer pipeline, we need to allow access to the alpha mask's
underlying buffer:

- AlphaMask gets another method which returns its
clipped_alpha_mask
- clipped_alpha_mask gets a get_hspan() method which returns a span
of alpha values without combining it with anything
- Painter/PainterAggInterface store a pointer to the
clipped_alpha_mask (in addition to the AlphaMask's scanline
container)

79a483ebbfdb: app_server: add alpha masked mode to DrawBitmapNoScale

* Add another mode to DrawBitmapNoScale for drawing bitmaps using
B_OP_COPY with alpha masks. It behaves like the definition for
ClipToPicture from the BeBook: pixels with alpha = 0 are ignored,
pixels with any alpha > 0 are copied.
Before, this fell back to the slower generic AGG-pipeline-based
version.

* Some light refactoring

64c6e038ebf3: app_server: bilinear bitmap painting: alpha overlay support

* Add support for pixel alpha overlay mode in the optimized bilinear-
scaled bitmap drawing code of BitmapPainter.
For now, only BilinearDefault supports this. DrawBitmapBilinear
gets the colour type and draw mode as template parameters to
minimize code duplication and allow simple extension with further
pixel formats and modes.
Avoids, for this mode, fallback to the slower generic
AGG-pipeline-based version.

01c730420420: app_server: fix comment header in pixel alpha overlay modes

ed7b139e0894: app_server: fix direct assignment in alpha pixel composite

* 'alpha' is 16 bit (alpha * cover) in blend_hline_alpha_pc(), so
compare with 255 * 255

801b5d211914: app_server: add pixel alpha composite solid mode

* Same concept as the previously exisiting drawing mode
implementations for e.g. pixel alpha overlay mode: when pattern
is solid, provide a separate mode implementation which does no
unnecessary pattern pixel lookups. This provides a considerable
speedup in composite mode when no stipple pattern is used.

e3d73948690d: app_server: fix test-app_server for launch_daemon changes

* Make test-app_server work again in a launch_daemon environment

* test_registrar gets a separate signature and port name again so the
host system can distinguish it from the system registrar

* AppServer is normally a BServer now, however, there can't be two
BApplications in one team. A class TestServerLoopAdapter is added,
which becomes the base class of AppServer instead of BServer when
compiling for libbe_test. It's an adapter class which looks towards
AppServer as it if was a BServer, but internally it is derived from
MessageLooper (like the old AppServer before the transition to
BServer).

This way, AppServer can stay a BServer in normal builds and it also
avoids having to use too many #ifdefs to distinguish the two
versions.

1cd452ea0362: app_server: Drawing mode fixups

* TODO: squash commit before merge into master

bafd2b461acb: app_server: PictureBoundingBoxPlayer fixups

* TODO: squash commit before merge into master

9b417f648625: app_server: rework AlphaMask, use bounds for mask pictures

* Refactor AlphaMask class to separate the mask from its source. This
allows use to not just a BPicture as source for a pixel alpha mask,
but also e.g. a BShape in the future (not yet implemented).

* For BPicture-based masks, use the PictureBoundingBoxPlayer to
determine the size of the resulting mask bitmap. The masks are now
drawn into bitmaps of this size (instead of the whole view size).

When alpha masks are stacked, their bounding rectangles intersect
(i.e. masks further up in the stack can never be larger than masks
lower in the stack). The bitmap of a mask always contains the state
of itself blended with all masks in the stack below it.

This also avoids frequent rerendering of the masks. They are now
independent of view size. When the view origin (in screen
coordinates) changes we only have to reattach the mask buffer,
without having to redraw it.

* The class UniformAlphaMask is used for simple masks with the same
alpha value in all pixels, it uses no mask bitmap at all.
Currently, it can only be used on its own and not be stacked
together with other mask types.

71cc4d49983c: Merge branch 'master' into app_server

Conflicts:
src/kits/app/Roster.cpp

6109a2086d11: 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

08135223ce63: Affine transforms: add method to test for dilation

* Add IsDilation() to BAffineTransform and Transformable which check
whether the transform is a dilation, i.e. consists of only
translation and/or scaling

ab12093685e7: BShape: move bounding box method to shape_data

* Makes it easier to get the bounding box from inside app_server

23af4ff6ac19: app_server: finish BShape-based alpha mask generation

4bd6f322bb1d: app_server/Interface Kit: add new clipping API

* Add new clipping API for rectangles (ClipToRect, ClipToInverseRect)
and shapes (ClipToShape, ClipToInverseShape)

* Works with affine transforms and automatically switches from fast
region-based clipping to alpha-mask based clipping as necessary.

* Always self-intersecting, i.e. no state push required to further
narrow down the clipping region. All of the 4 new methods can be
mixed in any order.

1cde68c5a29b: app_server: apply transform to CopyBits

* Apply affine transforms to source and target rects of
BView::CopyBits(). For now, only if transform is a dilation.

4721524cb5a9: BAffineTransform: add PreTranslate/PreScale/PreRotate

* The existing methods TranslateBy(), ScaleBy() and RotateBy()
transform the transformation. For a transform A, a point p,
and the temporary transform B (being applied by the methods),
this results in p' = B*(A*p) = (B*A)*p
This is not necessarily the desired result. Suppose A is a
translation and B a rotation, added by RotateBy(). Then B*A
means that the translation itself is rotated, so B moves the
coordinate origin itself, by rotating it around the original
origin of the coordinate system (top left view corner).

If we want to translate and then rotate around that *new* origin,
we need to multiply the transforms the other way around: A*B.

Three new methods PreTranslateBy(), PreScaleBy() and PreRotateBy()
implement this. They are later used as a base to add translatation/
scaling/rotation methods to BView which behave in the expected
ordering, similar to other graphic APIs.

25dbf74b8e2a: BView: add methods for affine translation/scaling/rotation

* BView::TranslateBy(), BView::ScaleBy() and BView::RotateBy()
allow to conveniently modify the current affine transformation.
This makes it unnecessary to first read the current transform,
modify it, and then set it again.
Uses the new Pre...() methods of BAffineTransform.

* Also, remove setting the transform "through" to the BView even
while recording a BPicture, as this now results in transforms
being applied more than once.

0a6baa7e7410: app_server: gcc4 build fixes

959355842fee: Update haikuwebkit to 1.5.0-1

[ Julian Harnath <julian.harnath@xxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

78 files changed, 6235 insertions(+), 2379 deletions(-)
build/jam/repositories/HaikuPorts/x86_gcc2 | 4 +-
headers/os/interface/AffineTransform.h | 43 +
headers/os/interface/View.h | 14 +
headers/private/app/RegistrarDefs.h | 9 +-
headers/private/app/ServerProtocol.h | 15 +
headers/private/interface/PictureDataWriter.h | 14 +-
headers/private/interface/PicturePlayer.h | 8 +
headers/private/interface/PictureProtocol.h | 8 +-
headers/private/interface/ShapePrivate.h | 30 +
src/kits/app/AppMisc.cpp | 60 +
src/kits/app/Roster.cpp | 16 +-
src/kits/interface/AffineTransform.cpp | 8 +
src/kits/interface/PictureDataWriter.cpp | 101 +-
src/kits/interface/PicturePlayer.cpp | 79 ++
src/kits/interface/Shape.cpp | 27 +-
src/kits/interface/View.cpp | 138 ++-
src/servers/app/AppServer.cpp | 8 +-
src/servers/app/AppServer.h | 14 +-
src/servers/app/Canvas.cpp | 315 +++++
src/servers/app/Canvas.h | 111 ++
src/servers/app/DrawState.cpp | 222 ++--
src/servers/app/DrawState.h | 31 +-
src/servers/app/DrawingContext.cpp | 345 ------
src/servers/app/DrawingContext.h | 111 --
src/servers/app/Jamfile | 12 +-
src/servers/app/Layer.cpp | 233 ++++
src/servers/app/Layer.h | 42 +
src/servers/app/MessageLooper.cpp | 4 +-
src/servers/app/PictureBoundingBoxPlayer.cpp | 854 ++++++++++++++
src/servers/app/PictureBoundingBoxPlayer.h | 28 +
src/servers/app/ServerPicture.cpp | 445 +++++---
src/servers/app/ServerPicture.h | 11 +-
src/servers/app/ServerWindow.cpp | 366 +++++-
src/servers/app/SimpleTransform.h | 243 ++++
src/servers/app/TestServerLoopAdapter.cpp | 121 ++
src/servers/app/TestServerLoopAdapter.h | 51 +
src/servers/app/View.cpp | 256 +----
src/servers/app/View.h | 40 +-
src/servers/app/Window.cpp | 2 +-
src/servers/app/WorkspacesView.cpp | 6 +-
src/servers/app/drawing/AlphaMask.cpp | 410 ++++---
src/servers/app/drawing/AlphaMask.h | 122 +-
src/servers/app/drawing/DWindowHWInterface.cpp | 3 +-
src/servers/app/drawing/DrawingEngine.cpp | 19 +-
src/servers/app/drawing/DrawingEngine.h | 6 +-
src/servers/app/drawing/Painter/Jamfile | 4 +
src/servers/app/drawing/Painter/Painter.cpp | 1078 +-----------------
src/servers/app/drawing/Painter/Painter.h | 76 +-
.../app/drawing/Painter/PainterAggInterface.h | 69 ++
.../app/drawing/Painter/Transformable.cpp | 9 +
src/servers/app/drawing/Painter/Transformable.h | 1 +
.../app/drawing/Painter/agg_clipped_alpha_mask.h | 64 +-
.../app/drawing/Painter/agg_renderer_region.h | 138 ++-
.../Painter/bitmap_painter/BitmapPainter.cpp | 338 ++++++
.../Painter/bitmap_painter/BitmapPainter.h | 60 +
.../Painter/bitmap_painter/DrawBitmapBilinear.h | 648 +++++++++++
.../Painter/bitmap_painter/DrawBitmapGeneric.h | 112 ++
.../bitmap_painter/DrawBitmapNearestNeighbor.h | 143 +++
.../Painter/bitmap_painter/DrawBitmapNoScale.h | 197 ++++
.../painter_bilinear_scale.nasm | 0
.../Painter/drawing_modes/DrawingModeAlphaPC.h | 12 +-
.../drawing_modes/DrawingModeAlphaPCSolid.h | 155 +++
.../Painter/drawing_modes/DrawingModeAlphaPO.h | 12 +-
.../drawing_modes/DrawingModeAlphaPOSUBPIX.h | 2 +-
.../drawing_modes/DrawingModeAlphaPOSolid.h | 8 +-
.../DrawingModeAlphaPOSolidSUBPIX.h | 2 +-
.../Painter/drawing_modes/PixelFormat.cpp | 24 +-
src/servers/app/drawing/ViewHWInterface.cpp | 3 +-
src/servers/app/test_app_server.rdef | 2 +-
src/servers/registrar/Registrar.cpp | 2 +-
src/tests/servers/app/Jamfile | 10 +-
.../app/unit_tests/AppServerUnitTestAddOn.cpp | 20 +
src/tests/servers/app/unit_tests/Jamfile | 15 +
.../app/unit_tests/SimpleTransformTest.cpp | 269 +++++
.../servers/app/unit_tests/SimpleTransformTest.h | 36 +
src/tests/servers/registrar/Jamfile | 2 +-
.../servers/registrar/run_test_registrar.cpp | 2 +-
src/tests/servers/registrar/test_registrar.rdef | 96 ++

############################################################################

Commit: ab1bd2fd07b535209dd57ea00df4dc5794f9827f
URL: http://cgit.haiku-os.org/haiku/commit/?id=ab1bd2fd07b5
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sun Jan 4 15:33:25 2015 UTC

app_server: rename DrawingContext to Canvas

* Better reflects the purpose of the class: an interface for things
in which we can draw (e.g. a View)

* Accordingly rename OffscreenContext to OffscreenCanvas

----------------------------------------------------------------------------

diff --git a/src/servers/app/DrawingContext.cpp b/src/servers/app/Canvas.cpp
similarity index 80%
rename from src/servers/app/DrawingContext.cpp
rename to src/servers/app/Canvas.cpp
index 8a61f9b..715c6a1 100644
--- a/src/servers/app/DrawingContext.cpp
+++ b/src/servers/app/Canvas.cpp
@@ -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,10 +9,11 @@
* Stephan Aßmus <superstippi@xxxxxx>
* Marcus Overhagen <marcus@xxxxxxxxxxxx>
* Adrien Destugues <pulkomandy@xxxxxxxxxxxxx
+ * Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
*/


-#include "DrawingContext.h"
+#include "Canvas.h"

#include <new>

@@ -27,27 +28,27 @@
#include "DrawState.h"


-DrawingContext::DrawingContext()
+Canvas::Canvas()
:
fDrawState(new(std::nothrow) DrawState())
{
}


-DrawingContext::DrawingContext(const DrawState& state)
+Canvas::Canvas(const DrawState& state)
:
fDrawState(new(std::nothrow) DrawState(state))
{
}


-DrawingContext::~DrawingContext()
+Canvas::~Canvas()
{
}


status_t
-DrawingContext::InitCheck() const
+Canvas::InitCheck() const
{
if (fDrawState == NULL)
return B_NO_MEMORY;
@@ -57,7 +58,7 @@ DrawingContext::InitCheck() const


void
-DrawingContext::PushState()
+Canvas::PushState()
{
DrawState* newState = fDrawState->PushState();
if (newState)
@@ -66,7 +67,7 @@ DrawingContext::PushState()


void
-DrawingContext::PopState()
+Canvas::PopState()
{
if (fDrawState->PreviousState() == NULL)
return;
@@ -83,7 +84,7 @@ DrawingContext::PopState()


void
-DrawingContext::SetDrawingOrigin(BPoint origin)
+Canvas::SetDrawingOrigin(BPoint origin)
{
fDrawState->SetOrigin(origin);

@@ -94,7 +95,7 @@ DrawingContext::SetDrawingOrigin(BPoint origin)


BPoint
-DrawingContext::DrawingOrigin() const
+Canvas::DrawingOrigin() const
{
BPoint origin(fDrawState->Origin());
float scale = Scale();
@@ -107,7 +108,7 @@ DrawingContext::DrawingOrigin() const


void
-DrawingContext::SetScale(float scale)
+Canvas::SetScale(float scale)
{
fDrawState->SetScale(scale);

@@ -118,31 +119,31 @@ DrawingContext::SetScale(float scale)


float
-DrawingContext::Scale() const
+Canvas::Scale() const
{
return fDrawState->Scale();
}


void
-DrawingContext::SetUserClipping(const BRegion* region)
+Canvas::SetUserClipping(const BRegion* region)
{
fDrawState->SetClippingRegion(region);

- // rebuild clipping (for just this context)
+ // rebuild clipping (for just this canvas)
RebuildClipping(false);
}


void
-DrawingContext::SetAlphaMask(AlphaMask* mask)
+Canvas::SetAlphaMask(AlphaMask* mask)
{
fDrawState->SetAlphaMask(mask);
}


AlphaMask*
-DrawingContext::GetAlphaMask() const
+Canvas::GetAlphaMask() const
{
return fDrawState->GetAlphaMask();
}
@@ -150,7 +151,7 @@ DrawingContext::GetAlphaMask() const

//! converts a point from local *drawing* to screen coordinate system
void
-DrawingContext::ConvertToScreenForDrawing(BPoint* point) const
+Canvas::ConvertToScreenForDrawing(BPoint* point) const
{
fDrawState->Transform(point);
// NOTE: from here on, don't use the
@@ -161,7 +162,7 @@ DrawingContext::ConvertToScreenForDrawing(BPoint* point)
const

//! converts a rect from local *drawing* to screen coordinate system
void
-DrawingContext::ConvertToScreenForDrawing(BRect* rect) const
+Canvas::ConvertToScreenForDrawing(BRect* rect) const
{
fDrawState->Transform(rect);
// NOTE: from here on, don't use the
@@ -172,7 +173,7 @@ DrawingContext::ConvertToScreenForDrawing(BRect* rect) const

//! converts a region from local *drawing* to screen coordinate system
void
-DrawingContext::ConvertToScreenForDrawing(BRegion* region) const
+Canvas::ConvertToScreenForDrawing(BRegion* region) const
{
fDrawState->Transform(region);
// NOTE: from here on, don't use the
@@ -183,7 +184,7 @@ DrawingContext::ConvertToScreenForDrawing(BRegion* region)
const

//! converts a gradient from local *drawing* to screen coordinate system
void
-DrawingContext::ConvertToScreenForDrawing(BGradient* gradient) const
+Canvas::ConvertToScreenForDrawing(BGradient* gradient) const
{
switch (gradient->GetType()) {
case BGradient::TYPE_LINEAR:
@@ -266,7 +267,7 @@ DrawingContext::ConvertToScreenForDrawing(BGradient*
gradient) const

//! converts points from local *drawing* to screen coordinate system
void
-DrawingContext::ConvertToScreenForDrawing(BPoint* dst, const BPoint* src,
int32 num) const
+Canvas::ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num)
const
{
// TODO: optimize this, it should be smarter
while (num--) {
@@ -283,7 +284,7 @@ DrawingContext::ConvertToScreenForDrawing(BPoint* dst,
const BPoint* src, int32

//! converts rects from local *drawing* to screen coordinate system
void
-DrawingContext::ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32
num) const
+Canvas::ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num)
const
{
// TODO: optimize this, it should be smarter
while (num--) {
@@ -300,7 +301,7 @@ DrawingContext::ConvertToScreenForDrawing(BRect* dst, const
BRect* src, int32 nu

//! converts regions from local *drawing* to screen coordinate system
void
-DrawingContext::ConvertToScreenForDrawing(BRegion* dst, const BRegion* src,
int32 num) const
+Canvas::ConvertToScreenForDrawing(BRegion* dst, const BRegion* src, int32 num)
const
{
// TODO: optimize this, it should be smarter
while (num--) {
@@ -317,20 +318,20 @@ DrawingContext::ConvertToScreenForDrawing(BRegion* dst,
const BRegion* src, int3

//! converts a point from screen to local coordinate system
void
-DrawingContext::ConvertFromScreenForDrawing(BPoint* point) const
+Canvas::ConvertFromScreenForDrawing(BPoint* point) const
{
ConvertFromScreen(point);
fDrawState->InverseTransform(point);
}


-// #pragma mark - OffscreenContext
+// #pragma mark - OffscreenCanvas


-OffscreenContext::OffscreenContext(DrawingEngine* engine,
+OffscreenCanvas::OffscreenCanvas(DrawingEngine* engine,
const DrawState& state)
:
- DrawingContext(state),
+ Canvas(state),
fDrawingEngine(engine)
{
ResyncDrawState();
@@ -338,7 +339,7 @@ OffscreenContext::OffscreenContext(DrawingEngine* engine,


void
-OffscreenContext::ResyncDrawState()
+OffscreenCanvas::ResyncDrawState()
{
fDrawingEngine->SetDrawState(fDrawState);
}
diff --git a/src/servers/app/DrawingContext.h b/src/servers/app/Canvas.h
similarity index 90%
rename from src/servers/app/DrawingContext.h
rename to src/servers/app/Canvas.h
index 621ed0a..c8efc4c 100644
--- a/src/servers/app/DrawingContext.h
+++ b/src/servers/app/Canvas.h
@@ -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,9 +9,10 @@
* Stephan Aßmus <superstippi@xxxxxx>
* Marcus Overhagen <marcus@xxxxxxxxxxxx>
* Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
+ * Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
*/
-#ifndef DRAWING_CONTEXT_H
-#define DRAWING_CONTEXT_H
+#ifndef CANVAS_H
+#define CANVAS_H


#include <Point.h>
@@ -27,11 +28,11 @@ class IntRect;
class ServerPicture;


-class DrawingContext {
+class Canvas {
public:
- DrawingContext();
- DrawingContext(const
DrawState& state);
- virtual ~DrawingContext();
+ Canvas();
+ Canvas(const DrawState&
state);
+ virtual ~Canvas();

status_t InitCheck() const;

@@ -47,10 +48,10 @@ public:

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;
@@ -82,9 +83,9 @@ protected:
};


-class OffscreenContext: public DrawingContext {
+class OffscreenCanvas : public Canvas {
public:
-
OffscreenContext(DrawingEngine* engine,
+
OffscreenCanvas(DrawingEngine* engine,
const
DrawState& state);

// Screen and View
coordinates are the same for us.
@@ -108,4 +109,4 @@ private:
};


-#endif
+#endif // CANVAS_H
diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile
index 024088b..aebc6c8 100644
--- a/src/servers/app/Jamfile
+++ b/src/servers/app/Jamfile
@@ -32,10 +32,10 @@ local font_src =
;

UseBuildFeatureHeaders freetype ;
-Includes [ FGristFiles AppServer.cpp BitmapManager.cpp
+Includes [ FGristFiles AppServer.cpp BitmapManager.cpp Canvas.cpp
ClientMemoryAllocator.cpp Desktop.cpp DesktopSettings.cpp
- DrawState.cpp DrawingContext.cpp DrawingEngine.cpp ServerApp.cpp
- ServerBitmap.cpp ServerCursor.cpp ServerFont.cpp ServerPicture.cpp
+ DrawState.cpp DrawingEngine.cpp ServerApp.cpp
+ ServerBitmap.cpp ServerCursor.cpp ServerFont.cpp ServerPicture.cpp
ServerWindow.cpp View.cpp Window.cpp WorkspacesView.cpp
$(decorator_src) $(font_src) ]
: [ BuildFeatureAttribute freetype : headers ] ;
@@ -51,6 +51,7 @@ Server app_server :
AppServer.cpp
#BitfieldRegion.cpp
BitmapManager.cpp
+ Canvas.cpp
ClientMemoryAllocator.cpp
CursorData.cpp
CursorManager.cpp
@@ -59,7 +60,6 @@ Server app_server :
DesktopListener.cpp
DesktopSettings.cpp
DirectWindowInfo.cpp
- DrawingContext.cpp
DrawState.cpp
EventDispatcher.cpp
EventStream.cpp
@@ -97,7 +97,7 @@ Server app_server :
# libraries
:
libtranslation.so libbe.so libbnetapi.so
- libaslocal.a $(BROKEN_64)libasremote.a $(BROKEN_64)libashtml5.a
+ libaslocal.a $(BROKEN_64)libasremote.a $(BROKEN_64)libashtml5.a
libasdrawing.a libpainter.a libagg.a
[ BuildFeatureAttribute freetype : library ]
libstackandtile.a liblinprog.a libtextencoding.so libshared.a
diff --git a/src/servers/app/ServerPicture.cpp
b/src/servers/app/ServerPicture.cpp
index 1c115dc..6f09cb0 100644
--- a/src/servers/app/ServerPicture.cpp
+++ b/src/servers/app/ServerPicture.cpp
@@ -44,7 +44,7 @@ using std::stack;

class ShapePainter : public BShapeIterator {
public:
- ShapePainter(DrawingContext* context);
+ ShapePainter(Canvas* canvas);
virtual ~ShapePainter();

status_t Iterate(const BShape* shape);
@@ -59,15 +59,15 @@ public:
void Draw(BRect frame, bool filled);

private:
- DrawingContext* fContext;
+ Canvas* fCanvas;
stack<uint32> fOpStack;
stack<BPoint> fPtStack;
};


-ShapePainter::ShapePainter(DrawingContext* context)
+ShapePainter::ShapePainter(Canvas* canvas)
:
- fContext(context)
+ fCanvas(canvas)
{
}

@@ -203,10 +203,10 @@ ShapePainter::Draw(BRect frame, bool filled)
fPtStack.pop();
}

- BPoint offset(fContext->CurrentState()->PenLocation());
- fContext->ConvertToScreenForDrawing(&offset);
- fContext->GetDrawingEngine()->DrawShape(frame, opCount, opList,
- ptCount, ptList, filled, offset, fContext->Scale());
+ BPoint offset(fCanvas->CurrentState()->PenLocation());
+ fCanvas->ConvertToScreenForDrawing(&offset);
+ fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList,
+ ptCount, ptList, filled, offset, fCanvas->Scale());

delete[] opList;
delete[] ptList;
@@ -253,23 +253,23 @@ nop()


static void
-move_pen_by(DrawingContext* context, BPoint delta)
+move_pen_by(Canvas* canvas, BPoint delta)
{
- context->CurrentState()->SetPenLocation(
- context->CurrentState()->PenLocation() + delta);
+ canvas->CurrentState()->SetPenLocation(
+ canvas->CurrentState()->PenLocation() + delta);
}


static void
-stroke_line(DrawingContext* context, BPoint start, BPoint end)
+stroke_line(Canvas* canvas, BPoint start, BPoint end)
{
BPoint penPos = end;

- context->ConvertToScreenForDrawing(&start);
- context->ConvertToScreenForDrawing(&end);
- context->GetDrawingEngine()->StrokeLine(start, end);
+ canvas->ConvertToScreenForDrawing(&start);
+ canvas->ConvertToScreenForDrawing(&end);
+ canvas->GetDrawingEngine()->StrokeLine(start, end);

- context->CurrentState()->SetPenLocation(penPos);
+ canvas->CurrentState()->SetPenLocation(penPos);
// the DrawingEngine/Painter does not need to be updated, since this
// effects only the view->screen coord conversion, which is handled
// by the view only
@@ -277,109 +277,109 @@ stroke_line(DrawingContext* context, BPoint start,
BPoint end)


static void
-stroke_rect(DrawingContext* context, BRect rect)
+stroke_rect(Canvas* canvas, BRect rect)
{
- context->ConvertToScreenForDrawing(&rect);
- context->GetDrawingEngine()->StrokeRect(rect);
+ canvas->ConvertToScreenForDrawing(&rect);
+ canvas->GetDrawingEngine()->StrokeRect(rect);
}


static void
-fill_rect(DrawingContext* context, BRect rect)
+fill_rect(Canvas* canvas, BRect rect)
{
- context->ConvertToScreenForDrawing(&rect);
- context->GetDrawingEngine()->FillRect(rect);
+ canvas->ConvertToScreenForDrawing(&rect);
+ canvas->GetDrawingEngine()->FillRect(rect);
}


static void
-draw_round_rect(DrawingContext* context, BRect rect, BPoint radii, bool fill)
+draw_round_rect(Canvas* canvas, BRect rect, BPoint radii, bool fill)
{
- context->ConvertToScreenForDrawing(&rect);
- float scale = context->CurrentState()->CombinedScale();
- context->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
+ canvas->ConvertToScreenForDrawing(&rect);
+ float scale = canvas->CurrentState()->CombinedScale();
+ canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
radii.y * scale, fill);
}


static void
-stroke_round_rect(DrawingContext* context, BRect rect, BPoint radii)
+stroke_round_rect(Canvas* canvas, BRect rect, BPoint radii)
{
- draw_round_rect(context, rect, radii, false);
+ draw_round_rect(canvas, rect, radii, false);
}


static void
-fill_round_rect(DrawingContext* context, BRect rect, BPoint radii)
+fill_round_rect(Canvas* canvas, BRect rect, BPoint radii)
{
- draw_round_rect(context, rect, radii, true);
+ draw_round_rect(canvas, rect, radii, true);
}


static void
-stroke_bezier(DrawingContext* context, const BPoint* viewPoints)
+stroke_bezier(Canvas* canvas, const BPoint* viewPoints)
{
BPoint points[4];
- context->ConvertToScreenForDrawing(points, viewPoints, 4);
+ canvas->ConvertToScreenForDrawing(points, viewPoints, 4);

- context->GetDrawingEngine()->DrawBezier(points, false);
+ canvas->GetDrawingEngine()->DrawBezier(points, false);
}


static void
-fill_bezier(DrawingContext* context, const BPoint* viewPoints)
+fill_bezier(Canvas* canvas, const BPoint* viewPoints)
{
BPoint points[4];
- context->ConvertToScreenForDrawing(points, viewPoints, 4);
+ canvas->ConvertToScreenForDrawing(points, viewPoints, 4);

- context->GetDrawingEngine()->DrawBezier(points, true);
+ canvas->GetDrawingEngine()->DrawBezier(points, true);
}


static void
-stroke_arc(DrawingContext* context, BPoint center, BPoint radii,
+stroke_arc(Canvas* canvas, BPoint center, BPoint radii,
float startTheta, float arcTheta)
{
BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1);
- context->ConvertToScreenForDrawing(&rect);
- context->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, false);
+ canvas->ConvertToScreenForDrawing(&rect);
+ canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, false);
}


static void
-fill_arc(DrawingContext* context, BPoint center, BPoint radii,
+fill_arc(Canvas* canvas, BPoint center, BPoint radii,
float startTheta, float arcTheta)
{
BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1);
- context->ConvertToScreenForDrawing(&rect);
- context->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, true);
+ canvas->ConvertToScreenForDrawing(&rect);
+ canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, true);
}


static void
-stroke_ellipse(DrawingContext* context, BPoint center, BPoint radii)
+stroke_ellipse(Canvas* canvas, BPoint center, BPoint radii)
{
BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1);
- context->ConvertToScreenForDrawing(&rect);
- context->GetDrawingEngine()->DrawEllipse(rect, false);
+ canvas->ConvertToScreenForDrawing(&rect);
+ canvas->GetDrawingEngine()->DrawEllipse(rect, false);
}


static void
-fill_ellipse(DrawingContext* context, BPoint center, BPoint radii)
+fill_ellipse(Canvas* canvas, BPoint center, BPoint radii)
{
BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1);
- context->ConvertToScreenForDrawing(&rect);
- context->GetDrawingEngine()->DrawEllipse(rect, true);
+ canvas->ConvertToScreenForDrawing(&rect);
+ canvas->GetDrawingEngine()->DrawEllipse(rect, true);
}


static void
-stroke_polygon(DrawingContext* context, int32 numPoints,
+stroke_polygon(Canvas* canvas, int32 numPoints,
const BPoint* viewPoints, bool isClosed)
{
if (numPoints <= 0)
@@ -391,12 +391,12 @@ stroke_polygon(DrawingContext* context, int32 numPoints,
char data[200 * sizeof(BPoint)];
BPoint* points = (BPoint*)data;

- context->ConvertToScreenForDrawing(points, viewPoints,
numPoints);
+ canvas->ConvertToScreenForDrawing(points, viewPoints,
numPoints);

BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);

- context->GetDrawingEngine()->DrawPolygon(points, numPoints,
polyFrame,
+ canvas->GetDrawingEngine()->DrawPolygon(points, numPoints,
polyFrame,
false, isClosed && numPoints > 2);
} else {
// avoid constructor/destructor calls by
@@ -405,12 +405,12 @@ stroke_polygon(DrawingContext* context, int32 numPoints,
if (points == NULL)
return;

- context->ConvertToScreenForDrawing(points, viewPoints,
numPoints);
+ canvas->ConvertToScreenForDrawing(points, viewPoints,
numPoints);

BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);

- context->GetDrawingEngine()->DrawPolygon(points, numPoints,
polyFrame,
+ canvas->GetDrawingEngine()->DrawPolygon(points, numPoints,
polyFrame,
false, isClosed && numPoints > 2);
free(points);
}
@@ -418,7 +418,7 @@ stroke_polygon(DrawingContext* context, int32 numPoints,


static void
-fill_polygon(DrawingContext* context, int32 numPoints,
+fill_polygon(Canvas* canvas, int32 numPoints,
const BPoint* viewPoints)
{
if (numPoints <= 0)
@@ -430,12 +430,12 @@ fill_polygon(DrawingContext* context, int32 numPoints,
char data[200 * sizeof(BPoint)];
BPoint* points = (BPoint*)data;

- context->ConvertToScreenForDrawing(points, viewPoints,
numPoints);
+ canvas->ConvertToScreenForDrawing(points, viewPoints,
numPoints);

BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);

- context->GetDrawingEngine()->DrawPolygon(points, numPoints,
polyFrame,
+ canvas->GetDrawingEngine()->DrawPolygon(points, numPoints,
polyFrame,
true, true);
} else {
// avoid constructor/destructor calls by
@@ -444,12 +444,12 @@ fill_polygon(DrawingContext* context, int32 numPoints,
if (points == NULL)
return;

- context->ConvertToScreenForDrawing(points, viewPoints,
numPoints);
+ canvas->ConvertToScreenForDrawing(points, viewPoints,
numPoints);

BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);

- context->GetDrawingEngine()->DrawPolygon(points, numPoints,
polyFrame,
+ canvas->GetDrawingEngine()->DrawPolygon(points, numPoints,
polyFrame,
true, true);
free(points);
}
@@ -457,9 +457,9 @@ fill_polygon(DrawingContext* context, int32 numPoints,


static void
-stroke_shape(DrawingContext* context, const BShape* shape)
+stroke_shape(Canvas* canvas, const BShape* shape)
{
- ShapePainter drawShape(context);
+ ShapePainter drawShape(canvas);

drawShape.Iterate(shape);
drawShape.Draw(shape->Bounds(), false);
@@ -467,9 +467,9 @@ stroke_shape(DrawingContext* context, const BShape* shape)


static void
-fill_shape(DrawingContext* context, const BShape* shape)
+fill_shape(Canvas* canvas, const BShape* shape)
{
- ShapePainter drawShape(context);
+ ShapePainter drawShape(canvas);

drawShape.Iterate(shape);
drawShape.Draw(shape->Bounds(), true);
@@ -477,21 +477,21 @@ fill_shape(DrawingContext* context, const BShape* shape)


static void
-draw_string(DrawingContext* context, const char* string, float deltaSpace,
+draw_string(Canvas* canvas, const char* string, float deltaSpace,
float deltaNonSpace)
{
// NOTE: the picture data was recorded with a "set pen location"
// command inserted before the "draw string" command, so we can
// use PenLocation()
- BPoint location = context->CurrentState()->PenLocation();
+ BPoint location = canvas->CurrentState()->PenLocation();

escapement_delta delta = { deltaSpace, deltaNonSpace };
- context->ConvertToScreenForDrawing(&location);
- location = context->GetDrawingEngine()->DrawString(string,
strlen(string),
+ canvas->ConvertToScreenForDrawing(&location);
+ location = canvas->GetDrawingEngine()->DrawString(string,
strlen(string),
location, &delta);

- context->ConvertFromScreenForDrawing(&location);
- context->CurrentState()->SetPenLocation(location);
+ canvas->ConvertFromScreenForDrawing(&location);
+ canvas->CurrentState()->SetPenLocation(location);
// the DrawingEngine/Painter does not need to be updated, since this
// effects only the view->screen coord conversion, which is handled
// by the view only
@@ -499,7 +499,7 @@ draw_string(DrawingContext* context, const char* string,
float deltaSpace,


static void
-draw_pixels(DrawingContext* context, BRect src, BRect dest, int32 width,
+draw_pixels(Canvas* canvas, BRect src, BRect dest, int32 width,
int32 height, int32 bytesPerRow, int32 pixelFormat, int32 options,
const void* data)
{
@@ -511,31 +511,31 @@ draw_pixels(DrawingContext* context, BRect src, BRect
dest, int32 width,

memcpy(bitmap.Bits(), data, height * bytesPerRow);

- context->ConvertToScreenForDrawing(&dest);
- context->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
+ canvas->ConvertToScreenForDrawing(&dest);
+ canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
}


static void
-draw_picture(DrawingContext* context, BPoint where, int32 token)
+draw_picture(Canvas* canvas, BPoint where, int32 token)
{
- ServerPicture* picture = context->GetPicture(token);
+ ServerPicture* picture = canvas->GetPicture(token);
if (picture != NULL) {
- context->PushState();
- context->SetDrawingOrigin(where);
+ canvas->PushState();
+ canvas->SetDrawingOrigin(where);

- context->PushState();
- picture->Play(context);
- context->PopState();
+ canvas->PushState();
+ picture->Play(canvas);
+ canvas->PopState();

- context->PopState();
+ canvas->PopState();
picture->ReleaseReference();
}
}


static void
-set_clipping_rects(DrawingContext* context, const BRect* rects,
+set_clipping_rects(Canvas* canvas, const BRect* rects,
uint32 numRects)
{
// TODO: This might be too slow, we should copy the rects
@@ -543,13 +543,13 @@ set_clipping_rects(DrawingContext* context, const BRect*
rects,
BRegion region;
for (uint32 c = 0; c < numRects; c++)
region.Include(rects[c]);
- context->SetUserClipping(&region);
- context->UpdateCurrentDrawingRegion();
+ canvas->SetUserClipping(&region);
+ canvas->UpdateCurrentDrawingRegion();
}


static void
-clip_to_picture(DrawingContext* context, BPicture* picture, BPoint pt,
+clip_to_picture(Canvas* canvas, BPicture* picture, BPoint pt,
bool clipToInverse)
{
printf("ClipToPicture(picture, BPoint(%.2f, %.2f), %s)\n",
@@ -558,20 +558,20 @@ clip_to_picture(DrawingContext* context, BPicture*
picture, BPoint pt,


static void
-push_state(DrawingContext* context)
+push_state(Canvas* canvas)
{
- context->PushState();
+ canvas->PushState();
}


static void
-pop_state(DrawingContext* context)
+pop_state(Canvas* canvas)
{
- context->PopState();
+ canvas->PopState();

BPoint p(0, 0);
- context->ConvertToScreenForDrawing(&p);
- context->GetDrawingEngine()->SetDrawState(context->CurrentState(),
+ canvas->ConvertToScreenForDrawing(&p);
+ canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(),
(int32)p.x, (int32)p.y);
}

@@ -579,42 +579,42 @@ pop_state(DrawingContext* context)
// TODO: Be smart and actually take advantage of these methods:
// only apply state changes when they are called
static void
-enter_state_change(DrawingContext* context)
+enter_state_change(Canvas* canvas)
{
}


static void
-exit_state_change(DrawingContext* context)
+exit_state_change(Canvas* canvas)
{
- context->ResyncDrawState();
+ canvas->ResyncDrawState();
}


static void
-enter_font_state(DrawingContext* context)
+enter_font_state(Canvas* canvas)
{
}


static void
-exit_font_state(DrawingContext* context)
+exit_font_state(Canvas* canvas)
{
- context->GetDrawingEngine()->SetFont(context->CurrentState()->Font());
+ canvas->GetDrawingEngine()->SetFont(canvas->CurrentState()->Font());
}


static void
-set_origin(DrawingContext* context, BPoint pt)
+set_origin(Canvas* canvas, BPoint pt)
{
- context->CurrentState()->SetOrigin(pt);
+ canvas->CurrentState()->SetOrigin(pt);
}


static void
-set_pen_location(DrawingContext* context, BPoint pt)
+set_pen_location(Canvas* canvas, BPoint pt)
{
- context->CurrentState()->SetPenLocation(pt);
+ canvas->CurrentState()->SetPenLocation(pt);
// the DrawingEngine/Painter does not need to be updated, since this
// effects only the view->screen coord conversion, which is handled
// by the view only
@@ -622,65 +622,65 @@ set_pen_location(DrawingContext* context, BPoint pt)


static void
-set_drawing_mode(DrawingContext* context, drawing_mode mode)
+set_drawing_mode(Canvas* canvas, drawing_mode mode)
{
- context->CurrentState()->SetDrawingMode(mode);
- context->GetDrawingEngine()->SetDrawingMode(mode);
+ canvas->CurrentState()->SetDrawingMode(mode);
+ canvas->GetDrawingEngine()->SetDrawingMode(mode);
}


static void
-set_line_mode(DrawingContext* context, cap_mode capMode, join_mode joinMode,
+set_line_mode(Canvas* canvas, cap_mode capMode, join_mode joinMode,
float miterLimit)
{
- DrawState* state = context->CurrentState();
+ DrawState* state = canvas->CurrentState();
state->SetLineCapMode(capMode);
state->SetLineJoinMode(joinMode);
state->SetMiterLimit(miterLimit);
- context->GetDrawingEngine()->SetStrokeMode(capMode, joinMode,
miterLimit);
+ canvas->GetDrawingEngine()->SetStrokeMode(capMode, joinMode,
miterLimit);
}


static void
-set_pen_size(DrawingContext* context, float size)
+set_pen_size(Canvas* canvas, float size)
{
- context->CurrentState()->SetPenSize(size);
- context->GetDrawingEngine()->SetPenSize(
- context->CurrentState()->PenSize());
+ canvas->CurrentState()->SetPenSize(size);
+ canvas->GetDrawingEngine()->SetPenSize(
+ canvas->CurrentState()->PenSize());
// DrawState::PenSize() returns the scaled pen size, so we
// need to use that value to set the drawing engine pen size.
}


static void
-set_fore_color(DrawingContext* context, rgb_color color)
+set_fore_color(Canvas* canvas, rgb_color color)
{
- context->CurrentState()->SetHighColor(color);
- context->GetDrawingEngine()->SetHighColor(color);
+ canvas->CurrentState()->SetHighColor(color);
+ canvas->GetDrawingEngine()->SetHighColor(color);
}


static void
-set_back_color(DrawingContext* context, rgb_color color)
+set_back_color(Canvas* canvas, rgb_color color)
{
- context->CurrentState()->SetLowColor(color);
- context->GetDrawingEngine()->SetLowColor(color);
+ canvas->CurrentState()->SetLowColor(color);
+ canvas->GetDrawingEngine()->SetLowColor(color);
}


static void
-set_stipple_pattern(DrawingContext* context, pattern p)
+set_stipple_pattern(Canvas* canvas, pattern p)
{
- context->CurrentState()->SetPattern(Pattern(p));
- context->GetDrawingEngine()->SetPattern(p);
+ canvas->CurrentState()->SetPattern(Pattern(p));
+ canvas->GetDrawingEngine()->SetPattern(p);
}


static void
-set_scale(DrawingContext* context, float scale)
+set_scale(Canvas* canvas, float scale)
{
- context->CurrentState()->SetScale(scale);
- context->ResyncDrawState();
+ canvas->CurrentState()->SetScale(scale);
+ canvas->ResyncDrawState();

// Update the drawing engine draw state, since some stuff
// (for example the pen size) needs to be recalculated.
@@ -688,94 +688,94 @@ set_scale(DrawingContext* context, float scale)


static void
-set_font_family(DrawingContext* context, const char* family)
+set_font_family(Canvas* canvas, const char* family)
{
FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0);
ServerFont font;
font.SetStyle(fontStyle);
- context->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
+ canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
}


static void
-set_font_style(DrawingContext* context, const char* style)
+set_font_style(Canvas* canvas, const char* style)
{
- ServerFont font(context->CurrentState()->Font());
+ ServerFont font(canvas->CurrentState()->Font());

FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style);

font.SetStyle(fontStyle);
- context->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
+ canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
}


static void
-set_font_spacing(DrawingContext* context, int32 spacing)
+set_font_spacing(Canvas* canvas, int32 spacing)
{
ServerFont font;
font.SetSpacing(spacing);
- context->CurrentState()->SetFont(font, B_FONT_SPACING);
+ canvas->CurrentState()->SetFont(font, B_FONT_SPACING);
}


static void
-set_font_size(DrawingContext* context, float size)
+set_font_size(Canvas* canvas, float size)
{
ServerFont font;
font.SetSize(size);
- context->CurrentState()->SetFont(font, B_FONT_SIZE);
+ canvas->CurrentState()->SetFont(font, B_FONT_SIZE);
}


static void
-set_font_rotate(DrawingContext* context, float rotation)
+set_font_rotate(Canvas* canvas, float rotation)
{
ServerFont font;
font.SetRotation(rotation);
- context->CurrentState()->SetFont(font, B_FONT_ROTATION);
+ canvas->CurrentState()->SetFont(font, B_FONT_ROTATION);
}


static void
-set_font_encoding(DrawingContext* context, int32 encoding)
+set_font_encoding(Canvas* canvas, int32 encoding)
{
ServerFont font;
font.SetEncoding(encoding);
- context->CurrentState()->SetFont(font, B_FONT_ENCODING);
+ canvas->CurrentState()->SetFont(font, B_FONT_ENCODING);
}


static void
-set_font_flags(DrawingContext* context, int32 flags)
+set_font_flags(Canvas* canvas, int32 flags)
{
ServerFont font;
font.SetFlags(flags);
- context->CurrentState()->SetFont(font, B_FONT_FLAGS);
+ canvas->CurrentState()->SetFont(font, B_FONT_FLAGS);
}


static void
-set_font_shear(DrawingContext* context, float shear)
+set_font_shear(Canvas* canvas, float shear)
{
ServerFont font;
font.SetShear(shear);
- context->CurrentState()->SetFont(font, B_FONT_SHEAR);
+ canvas->CurrentState()->SetFont(font, B_FONT_SHEAR);
}


static void
-set_font_face(DrawingContext* context, int32 face)
+set_font_face(Canvas* canvas, int32 face)
{
ServerFont font;
font.SetFace(face);
- context->CurrentState()->SetFont(font, B_FONT_FACE);
+ canvas->CurrentState()->SetFont(font, B_FONT_FACE);
}


static void
-set_blending_mode(DrawingContext* context, int16 alphaSrcMode, int16
alphaFncMode)
+set_blending_mode(Canvas* canvas, int16 alphaSrcMode, int16 alphaFncMode)
{
- context->CurrentState()->SetBlendingMode((source_alpha)alphaSrcMode,
+ canvas->CurrentState()->SetBlendingMode((source_alpha)alphaSrcMode,
(alpha_function)alphaFncMode);
}

@@ -1068,7 +1068,7 @@ ServerPicture::SetFontFromLink(BPrivate::LinkReceiver&
link)


void
-ServerPicture::Play(DrawingContext* target)
+ServerPicture::Play(Canvas* target)
{
// TODO: for now: then change PicturePlayer
// to accept a BPositionIO object
diff --git a/src/servers/app/ServerPicture.h b/src/servers/app/ServerPicture.h
index 6f27d38..f559b45 100644
--- a/src/servers/app/ServerPicture.h
+++ b/src/servers/app/ServerPicture.h
@@ -18,7 +18,7 @@


class BFile;
-class DrawingContext;
+class Canvas;
class ServerApp;
class View;

@@ -49,7 +49,7 @@ public:
void SyncState(View* view);
void
SetFontFromLink(BPrivate::LinkReceiver& link);

- void Play(DrawingContext*
target);
+ void Play(Canvas* target);

void
PushPicture(ServerPicture* picture);
ServerPicture* PopPicture();
diff --git a/src/servers/app/View.h b/src/servers/app/View.h
index b2291af..7bdc31a 100644
--- a/src/servers/app/View.h
+++ b/src/servers/app/View.h
@@ -14,7 +14,7 @@
#define VIEW_H


-#include "DrawingContext.h"
+#include "Canvas.h"
#include "IntRect.h"

#include <GraphicsDefs.h>
@@ -37,7 +37,7 @@ class ServerCursor;
class ServerPicture;
class BGradient;

-class View: public DrawingContext {
+class View: public Canvas {
public:
View(IntRect frame,
IntPoint scrollingOffset,
const char*
name, int32 token,
diff --git a/src/servers/app/drawing/AlphaMask.cpp
b/src/servers/app/drawing/AlphaMask.cpp
index 2a595fc..2b744cd 100644
--- a/src/servers/app/drawing/AlphaMask.cpp
+++ b/src/servers/app/drawing/AlphaMask.cpp
@@ -12,7 +12,7 @@

#include "BitmapHWInterface.h"
#include "BitmapManager.h"
-#include "DrawingContext.h"
+#include "Canvas.h"
#include "DrawingEngine.h"
#include "ServerBitmap.h"
#include "ServerPicture.h"
@@ -56,7 +56,7 @@ AlphaMask::Update(BRect bounds, BPoint offset)
{
fViewBounds = bounds;
fViewOffset = offset;
-
+
if (fPreviousMask != NULL)
fPreviousMask->Update(bounds, offset);
}
@@ -98,7 +98,7 @@ AlphaMask::Generate()
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) {
@@ -140,7 +140,7 @@ AlphaMask::Generate()
transferBitmap = false;
}
}
-
+
if (transferBitmap) {
for (uint32 y = 0; y < height; y++) {
for (uint32 x = 0; x < width; x++) {
@@ -194,8 +194,8 @@ AlphaMask::_RenderPicture() const
return NULL;
}

- OffscreenContext context(engine, fDrawState);
- context.PushState();
+ OffscreenCanvas canvas(engine, fDrawState);
+ canvas.PushState();

if (engine->LockParallelAccess()) {
// FIXME ConstrainClippingRegion docs says passing NULL disables
@@ -203,11 +203,11 @@ AlphaMask::_RenderPicture() const
BRegion clipping;
clipping.Include(fViewBounds);
engine->ConstrainClippingRegion(&clipping);
- fPicture->Play(&context);
+ fPicture->Play(&canvas);
engine->UnlockParallelAccess();
}

- context.PopState();
+ canvas.PopState();
delete engine;

return bitmap;
diff --git a/src/tests/servers/app/Jamfile b/src/tests/servers/app/Jamfile
index 376d562..0a5daf0 100644
--- a/src/tests/servers/app/Jamfile
+++ b/src/tests/servers/app/Jamfile
@@ -152,8 +152,8 @@ SharedLibrary libtestappserver.so :

AlphaMask.cpp
BitmapHWInterface.cpp
+ Canvas.cpp
DesktopSettings.cpp
- DrawingContext.cpp
OffscreenServerWindow.cpp
OffscreenWindow.cpp
RegionPool.cpp
@@ -173,9 +173,9 @@ SharedLibrary libtestappserver.so :
[ BuildFeatureAttribute freetype : library ]
;

-Includes [ FGristFiles AppServer.cpp BitmapManager.cpp
+Includes [ FGristFiles AppServer.cpp BitmapManager.cpp Canvas.cpp
ClientMemoryAllocator.cpp Desktop.cpp DesktopSettings.cpp
- DrawState.cpp DrawingContext.cpp DrawingEngine.cpp ServerApp.cpp
+ DrawState.cpp DrawingEngine.cpp ServerApp.cpp
ServerBitmap.cpp ServerCursor.cpp ServerFont.cpp ServerPicture.cpp
ServerWindow.cpp View.cpp Window.cpp WorkspacesView.cpp
$(decorator_src) $(font_src) ]

############################################################################

Commit: 6f2a446e2eb8362b92dd6c12c8ed7274d110a9b1
URL: http://cgit.haiku-os.org/haiku/commit/?id=6f2a446e2eb8
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Apr 6 12:43:24 2015 UTC

app_server: extract coordinate conversion class

* Move coordinate conversion into a new class SimpleTransform. It
supports scaling and translation which is sufficient for conversion
between screen, local and pen (drawing) coordinates.

* Because all the overloaded methods for converting
BPoint/BRect/BRegion/etc are now within the single SimpleTransform
class, the interfaces of Canvas, View, DrawState, etc. are slimmed
down. These classes have too many responsibilities, so some will be
factored out into separate classes, this being the first.

----------------------------------------------------------------------------

diff --git a/src/servers/app/Canvas.cpp b/src/servers/app/Canvas.cpp
index 715c6a1..4fd87a0 100644
--- a/src/servers/app/Canvas.cpp
+++ b/src/servers/app/Canvas.cpp
@@ -17,17 +17,22 @@

#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"


+#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())
@@ -149,179 +154,49 @@ Canvas::GetAlphaMask() const
}


-//! converts a point from local *drawing* to screen coordinate system
-void
-Canvas::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
-Canvas::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
-Canvas::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
-Canvas::ConvertToScreenForDrawing(BGradient* gradient) const
+SimpleTransform
+Canvas::LocalToScreenTransform() const GCC_2_NRV(transform)
{
- 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();
+#if __GNUC__ >= 3
+ SimpleTransform transform;
+#endif
+ _LocalToScreenTransform(transform);
+ return transform;
}


-//! converts points from local *drawing* to screen coordinate system
-void
-Canvas::ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num)
const
+SimpleTransform
+Canvas::ScreenToLocalTransform() const GCC_2_NRV(transform)
{
- // 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++;
- }
+#if __GNUC__ >= 3
+ SimpleTransform transform;
+#endif
+ _ScreenToLocalTransform(transform);
+ return transform;
}


-//! converts rects from local *drawing* to screen coordinate system
-void
-Canvas::ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num)
const
+SimpleTransform
+Canvas::PenToScreenTransform() const GCC_2_NRV(transform)
{
- // 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++;
- }
+#if __GNUC__ >= 3
+ SimpleTransform transform;
+#endif
+ fDrawState->Transform(transform);
+ _LocalToScreenTransform(transform);
+ return transform;
}


-//! converts regions from local *drawing* to screen coordinate system
-void
-Canvas::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
-Canvas::ConvertFromScreenForDrawing(BPoint* point) const
+SimpleTransform
+Canvas::ScreenToPenTransform() const GCC_2_NRV(transform)
{
- ConvertFromScreen(point);
- fDrawState->InverseTransform(point);
+#if __GNUC__ >= 3
+ SimpleTransform transform;
+#endif
+ _ScreenToLocalTransform(transform);
+ fDrawState->InverseTransform(transform);
+ return transform;
}


diff --git a/src/servers/app/Canvas.h b/src/servers/app/Canvas.h
index c8efc4c..acb52d0 100644
--- a/src/servers/app/Canvas.h
+++ b/src/servers/app/Canvas.h
@@ -17,6 +17,8 @@

#include <Point.h>

+#include "SimpleTransform.h"
+

class AlphaMask;
class BGradient;
@@ -52,25 +54,10 @@ public:
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;
+ SimpleTransform LocalToScreenTransform() const;
+ SimpleTransform ScreenToLocalTransform() const;
+ SimpleTransform PenToScreenTransform() const;
+ SimpleTransform ScreenToPenTransform() const;

virtual DrawingEngine* GetDrawingEngine() const = 0;
virtual ServerPicture* GetPicture(int32 token) const = 0;
@@ -79,6 +66,12 @@ public:
virtual void UpdateCurrentDrawingRegion() {};

protected:
+ virtual void _LocalToScreenTransform(
+
SimpleTransform& transform) const = 0;
+ virtual void _ScreenToLocalTransform(
+
SimpleTransform& transform) const = 0;
+
+protected:
DrawState* fDrawState;
};

@@ -88,22 +81,17 @@ public:

OffscreenCanvas(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; }
+
+protected:
+ virtual void
_LocalToScreenTransform(SimpleTransform&) const {}
+ virtual void
_ScreenToLocalTransform(SimpleTransform&) const {}
+
private:
DrawingEngine* fDrawingEngine;
};
diff --git a/src/servers/app/DrawState.cpp b/src/servers/app/DrawState.cpp
index 23c358f..d7f88bc 100644
--- a/src/servers/app/DrawState.cpp
+++ b/src/servers/app/DrawState.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2008, Haiku.
+ * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -8,6 +8,7 @@
* Stephan Aßmus <superstippi@xxxxxx>
* Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
* Michael Pfeiffer <laplace@xxxxxxxxxxxxxxxxxxxxx>
+ * Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
*/

//! Data classes for working with BView states and draw parameters
@@ -211,7 +212,7 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link)
ViewSetStateInfo info;

link.Read<ViewSetStateInfo>(&info);
-
+
fPenLocation = info.penLocation;
fPenSize = info.penSize;
fHighColor = info.highColor;
@@ -407,8 +408,9 @@ DrawState::GetCombinedClippingRegion(BRegion* region) const
{
if (fClippingRegion != NULL) {
BRegion localTransformedClipping(*fClippingRegion);
- Transform(&localTransformedClipping);
-
+ SimpleTransform penTransform;
+ Transform(penTransform);
+ penTransform.Apply(&localTransformedClipping);
if (fPreviousState != NULL
&& fPreviousState->GetCombinedClippingRegion(region)) {
localTransformedClipping.IntersectWith(region);
@@ -438,7 +440,7 @@ DrawState::SetAlphaMask(AlphaMask* mask)
fAlphaMask = mask;
if (fAlphaMask != NULL && fPreviousState != NULL)
fAlphaMask->SetPrevious(fPreviousState->fAlphaMask);
-
+
}


@@ -453,83 +455,19 @@ DrawState::GetAlphaMask() const


void
-DrawState::Transform(float* x, float* y) const
-{
- // scale relative to origin, therefore
- // scale first then translate to
- // origin
- *x *= fCombinedScale;
- *y *= fCombinedScale;
- *x += fCombinedOrigin.x;
- *y += fCombinedOrigin.y;
-}
-
-
-void
-DrawState::InverseTransform(float* x, float* y) const
-{
- *x -= fCombinedOrigin.x;
- *y -= fCombinedOrigin.y;
- if (fCombinedScale != 0.0) {
- *x /= fCombinedScale;
- *y /= fCombinedScale;
- }
-}
-
-
-void
-DrawState::Transform(BPoint* point) const
+DrawState::Transform(SimpleTransform& transform) 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;
- }
+ transform.AddOffset(fCombinedOrigin.x, fCombinedOrigin.y);
+ transform.SetScale(fCombinedScale);
}


void
-DrawState::InverseTransform(BPoint* point) const
+DrawState::InverseTransform(SimpleTransform& transform) const
{
- InverseTransform(&(point->x), &(point->y));
+ transform.AddOffset(-fCombinedOrigin.x, -fCombinedOrigin.y);
+ if (fCombinedScale != 0.0)
+ transform.SetScale(1.0 / fCombinedScale);
}


diff --git a/src/servers/app/DrawState.h b/src/servers/app/DrawState.h
index 48508ed..3925497 100644
--- a/src/servers/app/DrawState.h
+++ b/src/servers/app/DrawState.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2008, Haiku.
+ * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -7,6 +7,7 @@
* Adi Oanca <adioanca@xxxxxxxxx>
* Stephan Aßmus <superstippi@xxxxxx>
* Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
+ * Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
*/
#ifndef _DRAW_STATE_H_
#define _DRAW_STATE_H_
@@ -20,6 +21,7 @@

#include "ServerFont.h"
#include "PatternHandler.h"
+#include "SimpleTransform.h"

class AlphaMask;
class BRegion;
@@ -78,14 +80,8 @@ public:
AlphaMask* GetAlphaMask() const;

// coordinate
transformations
- void Transform(float* x, float* y)
const;
- void InverseTransform(float* x,
float* y) const;
-
- void Transform(BPoint* point) const;
- void Transform(BRect* rect) const;
- void Transform(BRegion* region)
const;
-
- void InverseTransform(BPoint* point)
const;
+ void Transform(SimpleTransform&
transform) const;
+ void
InverseTransform(SimpleTransform& transform) const;

// color
void SetHighColor(rgb_color color);
diff --git a/src/servers/app/ServerPicture.cpp
b/src/servers/app/ServerPicture.cpp
index 6f09cb0..d03ddb2 100644
--- a/src/servers/app/ServerPicture.cpp
+++ b/src/servers/app/ServerPicture.cpp
@@ -204,7 +204,7 @@ ShapePainter::Draw(BRect frame, bool filled)
}

BPoint offset(fCanvas->CurrentState()->PenLocation());
- fCanvas->ConvertToScreenForDrawing(&offset);
+ fCanvas->PenToScreenTransform().Apply(&offset);
fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList,
ptCount, ptList, filled, offset, fCanvas->Scale());

@@ -265,8 +265,9 @@ stroke_line(Canvas* canvas, BPoint start, BPoint end)
{
BPoint penPos = end;

- canvas->ConvertToScreenForDrawing(&start);
- canvas->ConvertToScreenForDrawing(&end);
+ const SimpleTransform transform = canvas->PenToScreenTransform();
+ transform.Apply(&start);
+ transform.Apply(&end);
canvas->GetDrawingEngine()->StrokeLine(start, end);

canvas->CurrentState()->SetPenLocation(penPos);
@@ -279,7 +280,7 @@ stroke_line(Canvas* canvas, BPoint start, BPoint end)
static void
stroke_rect(Canvas* canvas, BRect rect)
{
- canvas->ConvertToScreenForDrawing(&rect);
+ canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->StrokeRect(rect);
}

@@ -287,7 +288,7 @@ stroke_rect(Canvas* canvas, BRect rect)
static void
fill_rect(Canvas* canvas, BRect rect)
{
- canvas->ConvertToScreenForDrawing(&rect);
+ canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->FillRect(rect);
}

@@ -295,7 +296,7 @@ fill_rect(Canvas* canvas, BRect rect)
static void
draw_round_rect(Canvas* canvas, BRect rect, BPoint radii, bool fill)
{
- canvas->ConvertToScreenForDrawing(&rect);
+ canvas->PenToScreenTransform().Apply(&rect);
float scale = canvas->CurrentState()->CombinedScale();
canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
radii.y * scale, fill);
@@ -320,8 +321,7 @@ static void
stroke_bezier(Canvas* canvas, const BPoint* viewPoints)
{
BPoint points[4];
- canvas->ConvertToScreenForDrawing(points, viewPoints, 4);
-
+ canvas->PenToScreenTransform().Apply(points, viewPoints, 4);
canvas->GetDrawingEngine()->DrawBezier(points, false);
}

@@ -330,8 +330,7 @@ static void
fill_bezier(Canvas* canvas, const BPoint* viewPoints)
{
BPoint points[4];
- canvas->ConvertToScreenForDrawing(points, viewPoints, 4);
-
+ canvas->PenToScreenTransform().Apply(points, viewPoints, 4);
canvas->GetDrawingEngine()->DrawBezier(points, true);
}

@@ -342,7 +341,7 @@ stroke_arc(Canvas* canvas, BPoint center, BPoint radii,
{
BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1);
- canvas->ConvertToScreenForDrawing(&rect);
+ canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, false);
}

@@ -353,7 +352,7 @@ fill_arc(Canvas* canvas, BPoint center, BPoint radii,
{
BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1);
- canvas->ConvertToScreenForDrawing(&rect);
+ canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, true);
}

@@ -363,7 +362,7 @@ stroke_ellipse(Canvas* canvas, BPoint center, BPoint radii)
{
BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1);
- canvas->ConvertToScreenForDrawing(&rect);
+ canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->DrawEllipse(rect, false);
}

@@ -373,7 +372,7 @@ fill_ellipse(Canvas* canvas, BPoint center, BPoint radii)
{
BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1);
- canvas->ConvertToScreenForDrawing(&rect);
+ canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->DrawEllipse(rect, true);
}

@@ -391,8 +390,7 @@ stroke_polygon(Canvas* canvas, int32 numPoints,
char data[200 * sizeof(BPoint)];
BPoint* points = (BPoint*)data;

- canvas->ConvertToScreenForDrawing(points, viewPoints,
numPoints);
-
+ canvas->PenToScreenTransform().Apply(points, viewPoints,
numPoints);
BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);

@@ -405,8 +403,7 @@ stroke_polygon(Canvas* canvas, int32 numPoints,
if (points == NULL)
return;

- canvas->ConvertToScreenForDrawing(points, viewPoints,
numPoints);
-
+ canvas->PenToScreenTransform().Apply(points, viewPoints,
numPoints);
BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);

@@ -430,8 +427,7 @@ fill_polygon(Canvas* canvas, int32 numPoints,
char data[200 * sizeof(BPoint)];
BPoint* points = (BPoint*)data;

- canvas->ConvertToScreenForDrawing(points, viewPoints,
numPoints);
-
+ canvas->PenToScreenTransform().Apply(points, viewPoints,
numPoints);
BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);

@@ -444,8 +440,7 @@ fill_polygon(Canvas* canvas, int32 numPoints,
if (points == NULL)
return;

- canvas->ConvertToScreenForDrawing(points, viewPoints,
numPoints);
-
+ canvas->PenToScreenTransform().Apply(points, viewPoints,
numPoints);
BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);

@@ -486,11 +481,11 @@ draw_string(Canvas* canvas, const char* string, float
deltaSpace,
BPoint location = canvas->CurrentState()->PenLocation();

escapement_delta delta = { deltaSpace, deltaNonSpace };
- canvas->ConvertToScreenForDrawing(&location);
+ canvas->PenToScreenTransform().Apply(&location);
location = canvas->GetDrawingEngine()->DrawString(string,
strlen(string),
location, &delta);

- canvas->ConvertFromScreenForDrawing(&location);
+ canvas->PenToScreenTransform().Apply(&location);
canvas->CurrentState()->SetPenLocation(location);
// the DrawingEngine/Painter does not need to be updated, since this
// effects only the view->screen coord conversion, which is handled
@@ -511,7 +506,7 @@ draw_pixels(Canvas* canvas, BRect src, BRect dest, int32
width,

memcpy(bitmap.Bits(), data, height * bytesPerRow);

- canvas->ConvertToScreenForDrawing(&dest);
+ canvas->PenToScreenTransform().Apply(&dest);
canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
}

@@ -570,7 +565,7 @@ pop_state(Canvas* canvas)
canvas->PopState();

BPoint p(0, 0);
- canvas->ConvertToScreenForDrawing(&p);
+ canvas->PenToScreenTransform().Apply(&p);
canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(),
(int32)p.x, (int32)p.y);
}
diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp
index 242438f..81892f9 100644
--- a/src/servers/app/ServerWindow.cpp
+++ b/src/servers/app/ServerWindow.cpp
@@ -351,7 +351,7 @@ ServerWindow::_Show()
fDesktop->ShowWindow(fWindow);
if (fDirectWindowInfo && fDirectWindowInfo->IsFullScreen())
_ResizeToFullScreen();
-
+
fDesktop->LockSingleWindow();
}

@@ -1964,7 +1964,7 @@ fDesktop->LockSingleWindow();
} else {
_UpdateCurrentDrawingRegion();
BRegion region(fCurrentDrawingRegion);
- fCurrentView->ConvertFromScreen(&region);
+
fCurrentView->ScreenToLocalTransform().Apply(&region);
fLink.AttachRegion(region);
}
fLink.Flush();
@@ -2254,8 +2254,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
info.endPoint.x, info.endPoint.y));

BPoint penPos = info.endPoint;
-
fCurrentView->ConvertToScreenForDrawing(&info.startPoint);
- fCurrentView->ConvertToScreenForDrawing(&info.endPoint);
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
+ transform.Apply(&info.startPoint);
+ transform.Apply(&info.endPoint);
drawingEngine->StrokeLine(info.startPoint,
info.endPoint);

// We update the pen here because many DrawingEngine
calls which
@@ -2279,7 +2281,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top,
rect.right,
rect.bottom));

- fCurrentView->ConvertToScreenForDrawing(&rect);
+ fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->InvertRect(rect);
break;
}
@@ -2294,7 +2296,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top,
rect.right,
rect.bottom));

- fCurrentView->ConvertToScreenForDrawing(&rect);
+ fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->StrokeRect(rect);
break;
}
@@ -2309,7 +2311,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top,
rect.right,
rect.bottom));

- fCurrentView->ConvertToScreenForDrawing(&rect);
+ fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->FillRect(rect);
break;
}
@@ -2326,8 +2328,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top,
rect.right,
rect.bottom));

- fCurrentView->ConvertToScreenForDrawing(&rect);
- fCurrentView->ConvertToScreenForDrawing(gradient);
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
+ transform.Apply(&rect);
+ transform.Apply(gradient);
drawingEngine->FillRect(rect, *gradient);
delete gradient;
break;
@@ -2356,7 +2360,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
info.viewRect.left, info.viewRect.top,
info.viewRect.right,
info.viewRect.bottom));

-
fCurrentView->ConvertToScreenForDrawing(&info.viewRect);
+
fCurrentView->PenToScreenTransform().Apply(&info.viewRect);

// TODO: Unbreak...
// if ((info.options & B_WAIT_FOR_RETRACE) != 0)
@@ -2382,7 +2386,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<float>(&span) != B_OK)
break;

- fCurrentView->ConvertToScreenForDrawing(&r);
+ fCurrentView->PenToScreenTransform().Apply(&r);
drawingEngine->DrawArc(r, angle, span, code ==
AS_FILL_ARC);
break;
}
@@ -2399,8 +2403,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
- fCurrentView->ConvertToScreenForDrawing(&r);
- fCurrentView->ConvertToScreenForDrawing(gradient);
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
+ transform.Apply(&r);
+ transform.Apply(gradient);
drawingEngine->FillArc(r, angle, span, *gradient);
delete gradient;
break;
@@ -2411,11 +2417,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message
AS_STROKE/FILL_BEZIER\n",
Title()));

+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
BPoint pts[4];
status_t status;
for (int32 i = 0; i < 4; i++) {
status = link.Read<BPoint>(&(pts[i]));
-
fCurrentView->ConvertToScreenForDrawing(&pts[i]);
+ transform.Apply(&pts[i]);
}
if (status != B_OK)
break;
@@ -2428,15 +2436,17 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
GTRACE(("ServerWindow %s: Message
AS_FILL_BEZIER_GRADIENT\n",
Title()));

+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
BPoint pts[4];
for (int32 i = 0; i < 4; i++) {
link.Read<BPoint>(&(pts[i]));
-
fCurrentView->ConvertToScreenForDrawing(&pts[i]);
+ transform.Apply(&pts[i]);
}
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
- fCurrentView->ConvertToScreenForDrawing(gradient);
+ transform.Apply(gradient);
drawingEngine->FillBezier(pts, *gradient);
delete gradient;
break;
@@ -2451,7 +2461,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<BRect>(&rect) != B_OK)
break;

- fCurrentView->ConvertToScreenForDrawing(&rect);
+ fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->DrawEllipse(rect, code ==
AS_FILL_ELLIPSE);
break;
}
@@ -2465,8 +2475,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
- fCurrentView->ConvertToScreenForDrawing(&rect);
- fCurrentView->ConvertToScreenForDrawing(gradient);
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
+ transform.Apply(&rect);
+ transform.Apply(gradient);
drawingEngine->FillEllipse(rect, *gradient);
delete gradient;
break;
@@ -2485,7 +2497,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<float>(&yRadius) != B_OK)
break;

- fCurrentView->ConvertToScreenForDrawing(&rect);
+ fCurrentView->PenToScreenTransform().Apply(&rect);
float scale =
fCurrentView->CurrentState()->CombinedScale();
drawingEngine->DrawRoundRect(rect, xRadius * scale,
yRadius * scale,
code == AS_FILL_ROUNDRECT);
@@ -2504,8 +2516,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
- fCurrentView->ConvertToScreenForDrawing(&rect);
- fCurrentView->ConvertToScreenForDrawing(gradient);
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
+ transform.Apply(&rect);
+ transform.Apply(gradient);
drawingEngine->FillRoundRect(rect, xrad, yrad,
*gradient);
delete gradient;
break;
@@ -2516,18 +2530,20 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message
AS_STROKE/FILL_TRIANGLE\n",
Title()));

+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
BPoint pts[3];
BRect rect;

for (int32 i = 0; i < 3; i++) {
link.Read<BPoint>(&(pts[i]));
-
fCurrentView->ConvertToScreenForDrawing(&pts[i]);
+ transform.Apply(&pts[i]);
}

if (link.Read<BRect>(&rect) != B_OK)
break;

- fCurrentView->ConvertToScreenForDrawing(&rect);
+ transform.Apply(&rect);
drawingEngine->DrawTriangle(pts, rect, code ==
AS_FILL_TRIANGLE);
break;
}
@@ -2536,18 +2552,20 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message
AS_FILL_TRIANGLE_GRADIENT\n",
Title()));

+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
BPoint pts[3];
BRect rect;
for (int32 i = 0; i < 3; i++) {
link.Read<BPoint>(&(pts[i]));
-
fCurrentView->ConvertToScreenForDrawing(&pts[i]);
+ transform.Apply(&pts[i]);
}
link.Read<BRect>(&rect);
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
- fCurrentView->ConvertToScreenForDrawing(&rect);
- fCurrentView->ConvertToScreenForDrawing(gradient);
+ transform.Apply(&rect);
+ transform.Apply(gradient);
drawingEngine->FillTriangle(pts, rect, *gradient);
delete gradient;
break;
@@ -2567,11 +2585,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
link.Read<bool>(&isClosed);
link.Read<int32>(&pointCount);

+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
BPoint* pointList = new(nothrow) BPoint[pointCount];
if (link.Read(pointList, pointCount * sizeof(BPoint))

= B_OK) {
for (int32 i = 0; i < pointCount; i++)
-
fCurrentView->ConvertToScreenForDrawing(&pointList[i]);
-
fCurrentView->ConvertToScreenForDrawing(&polyFrame);
+ transform.Apply(&pointList[i]);
+ transform.Apply(&polyFrame);

drawingEngine->DrawPolygon(pointList,
pointCount, polyFrame,
code == AS_FILL_POLYGON, isClosed &&
pointCount > 2);
@@ -2590,14 +2610,16 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
link.Read<BRect>(&polyFrame);
link.Read<int32>(&pointCount);

+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
BPoint* pointList = new(nothrow) BPoint[pointCount];
BGradient* gradient;
if (link.Read(pointList, pointCount * sizeof(BPoint))
== B_OK
&& link.ReadGradient(&gradient) == B_OK) {
for (int32 i = 0; i < pointCount; i++)
-
fCurrentView->ConvertToScreenForDrawing(&pointList[i]);
-
fCurrentView->ConvertToScreenForDrawing(&polyFrame);
-
fCurrentView->ConvertToScreenForDrawing(gradient);
+ transform.Apply(&pointList[i]);
+ transform.Apply(&polyFrame);
+ transform.Apply(gradient);

drawingEngine->FillPolygon(pointList,
pointCount,
polyFrame, *gradient, isClosed &&
pointCount > 2);
@@ -2631,8 +2653,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
=
fCurrentView->CurrentState()->PenLocation();
shapeFrame.OffsetBy(screenOffset);

-
fCurrentView->ConvertToScreenForDrawing(&screenOffset);
-
fCurrentView->ConvertToScreenForDrawing(&shapeFrame);
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
+ transform.Apply(&screenOffset);
+ transform.Apply(&shapeFrame);

drawingEngine->DrawShape(shapeFrame, opCount,
opList, ptCount,
ptList, code == AS_FILL_SHAPE,
screenOffset,
@@ -2669,9 +2693,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
=
fCurrentView->CurrentState()->PenLocation();
shapeFrame.OffsetBy(screenOffset);

-
fCurrentView->ConvertToScreenForDrawing(&screenOffset);
-
fCurrentView->ConvertToScreenForDrawing(&shapeFrame);
-
fCurrentView->ConvertToScreenForDrawing(gradient);
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
+ transform.Apply(&screenOffset);
+ transform.Apply(&shapeFrame);
+ transform.Apply(gradient);
drawingEngine->FillShape(shapeFrame, opCount,
opList,
ptCount, ptList, *gradient,
screenOffset,
fCurrentView->Scale());
@@ -2690,7 +2716,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.ReadRegion(&region) < B_OK)
break;

- fCurrentView->ConvertToScreenForDrawing(&region);
+ fCurrentView->PenToScreenTransform().Apply(&region);
drawingEngine->FillRegion(region);

break;
@@ -2707,8 +2733,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.ReadGradient(&gradient) != B_OK)
break;

- fCurrentView->ConvertToScreenForDrawing(&region);
- fCurrentView->ConvertToScreenForDrawing(gradient);
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
+ transform.Apply(&region);
+ transform.Apply(gradient);
drawingEngine->FillRegion(region, *gradient);
delete gradient;
break;
@@ -2747,11 +2775,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
}

// Convert to screen coords and draw
+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
for (int32 i = 0; i < lineCount; i++) {
- fCurrentView->ConvertToScreenForDrawing(
- &lineData[i].startPoint);
- fCurrentView->ConvertToScreenForDrawing(
- &lineData[i].endPoint);
+ transform.Apply(&lineData[i].startPoint);
+ transform.Apply(&lineData[i].endPoint);
}
drawingEngine->StrokeLineArray(lineCount, lineData);

@@ -2796,11 +2824,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View:
%s "
"-> %s\n", Title(), fCurrentView->Name(),
string));

- fCurrentView->ConvertToScreenForDrawing(&info.location);
+
fCurrentView->PenToScreenTransform().Apply(&info.location);
BPoint penLocation = drawingEngine->DrawString(string,
info.stringLength, info.location, delta);

- fCurrentView->ConvertFromScreenForDrawing(&penLocation);
+
fCurrentView->ScreenToPenTransform().Apply(&penLocation);

fCurrentView->CurrentState()->SetPenLocation(penLocation);

if (string != stackString)
@@ -2853,13 +2881,15 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message
AS_DRAW_STRING_WITH_OFFSETS, View: %s "
"-> %s\n", Title(), fCurrentView->Name(),
string));

+ const SimpleTransform transform =
+ fCurrentView->PenToScreenTransform();
for (int32 i = 0; i < glyphCount; i++)
-
fCurrentView->ConvertToScreenForDrawing(&locations[i]);
+ transform.Apply(&locations[i]);

BPoint penLocation = drawingEngine->DrawString(string,
stringLength, locations);

- fCurrentView->ConvertFromScreenForDrawing(&penLocation);
+
fCurrentView->ScreenToPenTransform().Apply(&penLocation);

fCurrentView->CurrentState()->SetPenLocation(penLocation);

break;
@@ -3703,11 +3733,11 @@ ServerWindow::_UpdateDrawState(View* view)
if (view != NULL && drawingEngine != NULL) {
BPoint leftTop(0, 0);
if (view->GetAlphaMask() != NULL) {
- view->ConvertToScreen(&leftTop);
+ view->LocalToScreenTransform().Apply(&leftTop);
view->GetAlphaMask()->Update(view->Bounds(), leftTop);
leftTop = BPoint(0, 0);
}
- view->ConvertToScreenForDrawing(&leftTop);
+ view->PenToScreenTransform().Apply(&leftTop);
drawingEngine->SetDrawState(view->CurrentState(), leftTop.x,
leftTop.y);
}
}
diff --git a/src/servers/app/SimpleTransform.h
b/src/servers/app/SimpleTransform.h
new file mode 100644
index 0000000..00c8f45
--- /dev/null
+++ b/src/servers/app/SimpleTransform.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2001-2015, Haiku, Inc.
+ * Distributed under the terms of the MIT license.
+ *
+ * Authors:
+ * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
+ * Stephan Aßmus <superstippi@xxxxxx>
+ * Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
+ * Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
+ */
+
+#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

[ *** diff truncated: 424 lines dropped *** ]


############################################################################

Commit: ad53a0d999135776e664131cba0321bd1ce9e729
URL: http://cgit.haiku-os.org/haiku/commit/?id=ad53a0d99913
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Apr 6 12:44:11 2015 UTC

app_server: add unit test add-on, test for SimpleTransform

* app_server currently does not have any real unit tests, making
changes more difficult and riskier. A new directory unit_tests with
a test add-on is added in app_server's tetsts directory to hold
future unit tests.

* Add test for SimpleTransform class

----------------------------------------------------------------------------

############################################################################

Commit: ccaee9e818cc4ef94f313aa47a0b6c18ff580f57
URL: http://cgit.haiku-os.org/haiku/commit/?id=ccaee9e818cc
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 8 18:07:51 2015 UTC

app_server: add Squash method in DrawState

* New method DrawState::Squash() uses the combined scale, origin and
transform as the state's own scale, origin, transform.

This can be used when making copies of DrawStates which have
previous states below them in the state stack. The top of stack
DrawState can be copied, squashed and then used just like the
original one with the whole stack below it (except of course
when trying to pop off any earlier state).

----------------------------------------------------------------------------

############################################################################

Commit: 1b4dba929dd35c7aeaa92673efd63dbfc665c8e0
URL: http://cgit.haiku-os.org/haiku/commit/?id=1b4dba929dd3
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 8 18:17:04 2015 UTC

app_server: add picture player for determining bounding box

* Add PictureBoundingBoxPlayer, a new player for BPictures. Instead
of drawing the picture, it determines an approximate bounding box
of its contained drawing operations.

* To increase performance, the resulting bounding box is an
approximation: it guarantees to always enclose all pixels of the
picture, however not necessarily tightly.

* PictureBoundingBoxPlayer::Play() gets a DrawState which is the
initial state used when playing the picture. The player does not
modify this state (it uses a copy internally), so the method is
idempotent.

----------------------------------------------------------------------------

############################################################################

Commit: 8511f6ac9b4db63e490538fa7d0248ff0e0d5924
URL: http://cgit.haiku-os.org/haiku/commit/?id=8511f6ac9b4d
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 8 18:54:56 2015 UTC

app_server: fix ServerPicture::SyncState pen size

* Should use the unscaled pen size here because we also write down
the current scale, and we don't want to scale the pen twice.

----------------------------------------------------------------------------

############################################################################

Commit: ae0468762f2ff1f11bb575f40184fdb90d398dd9
URL: http://cgit.haiku-os.org/haiku/commit/?id=ae0468762f2f
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 8 19:16:30 2015 UTC

app_server: add Canvas::PenToLocalTransform

----------------------------------------------------------------------------

############################################################################

Commit: c34cbf2878cb39d46bad3de00d17e60bf502d750
URL: http://cgit.haiku-os.org/haiku/commit/?id=c34cbf2878cb
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 8 19:22:25 2015 UTC

app_server: fix PicturePlayer dummy function table

* With the support for BAffineTransform, it needs to have 49 entries

----------------------------------------------------------------------------

############################################################################

Commit: b5c7f936de1af0ce11e8257c4bba56c4a4e12f11
URL: http://cgit.haiku-os.org/haiku/commit/?id=b5c7f936de1a
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 8 19:27:24 2015 UTC

app_server: allow replacing the DrawState in a Canvas

* Needed for layers support. The previously set DrawState and its
stack predecessors are not freed, so take care to not leak memory
when using this.

----------------------------------------------------------------------------

############################################################################

Commit: 65a54d2892d46ff6fb72d76390555de0d5d6dd96
URL: http://cgit.haiku-os.org/haiku/commit/?id=65a54d2892d4
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Tue Jul 21 20:46:43 2015 UTC

app_server: implement setting BAffineTransforms in BPicture

* Add a simple callback for the picture command

----------------------------------------------------------------------------

############################################################################

Commit: edc0b5e9db34f77086d510fa7159d2daf22488aa
URL: http://cgit.haiku-os.org/haiku/commit/?id=edc0b5e9db34
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 22 19:01:19 2015 UTC

app_server: allow disabling affine transforms in DrawState

* New method DrawState::SetTransformEnabled allows to temporarily
disable all BAffineTransforms in the state stack (up to 'this').
Later, the same method can be used to reenable the transforms.

Needed for layers support: when drawing the finished layer bitmap
onto the view, the affine transforms must not be applied again --
they have already been applied while drawing the bitmap's contents.

----------------------------------------------------------------------------

############################################################################

Commit: 6ac468ef24f664699f674e5dd9b27d41be906d95
URL: http://cgit.haiku-os.org/haiku/commit/?id=6ac468ef24f6
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 22 19:26:49 2015 UTC

app_server: add support for uniform opacity alpha masks

* Another constructor for AlphaMask allows creating a mask with no
picture, it will simply be a single uniform alpha value over the
whole mask.

* No need to even allocate a buffer in this case, we can just use
the feature of clipped_alpha_mask to define an opacity for outside
the mask, and set the buffer size to zero.

----------------------------------------------------------------------------

############################################################################

Commit: cd621b9585b4dd2dd629283976130c13afeb087e
URL: http://cgit.haiku-os.org/haiku/commit/?id=cd621b9585b4
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 22 19:31:42 2015 UTC

app_server: add method to shift alpha masks

* Allow shifting the offset of alpha masks without changing the size.
Ideally, we only need to reattach the buffer in the shifted
position, saving the work of reallocating and redrawing the mask
picture. Needed for layers support.

----------------------------------------------------------------------------

############################################################################

Commit: d56beda4d8fa72f264b64c8e649ae4d8a0430a43
URL: http://cgit.haiku-os.org/haiku/commit/?id=d56beda4d8fa
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Wed Jul 22 19:36:10 2015 UTC

app_server: optional coordinate shifting in renderer_region

* agg::renderer_region gets an extra feature which allows to
optionally shift the coordinates by a specified offset.

* This allows to shift coordinates at the lowest level, even below
the transformations done by BAffineTransform (which happen in the
painter, right before rasterization).

Needed for layers support: shifts the origin of the layer bitmaps
to their position in the view while keeping all transformations
(BView origin/scale transforms as well as BAffineTransforms)
intact. The offset for the layer bitmaps within their parent view
is determined by the bounding box and is then fixed, it must not
be altered while the layer's BPicture is played into the bitmap.

If this offset were added to the BView origin or as translation in
the BAffineTransform, it would be further transformed by the BView
scale or the other affine transform parameters. Thus, we need
another low-level offset mechanism which is even below
BAffineTransform's transformations.

----------------------------------------------------------------------------

############################################################################

Commit: 551438b9be6bb3c4c52b8276718d56eccf969dff
URL: http://cgit.haiku-os.org/haiku/commit/?id=551438b9be6b
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Jul 25 13:44:23 2015 UTC

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.

----------------------------------------------------------------------------

############################################################################

Commit: d727d0743b2f8bebaf895dc2a661a97fbf3f226a
URL: http://cgit.haiku-os.org/haiku/commit/?id=d727d0743b2f
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Fri Jul 31 19:01:12 2015 UTC

app_server: fix clearing user clipping from BPicture

* Clipping was set to an empty region instead of being cleared
when inside a BPicture

----------------------------------------------------------------------------

############################################################################

Commit: 3d12d3a832462309cca084b87a89d008ae50d5e9
URL: http://cgit.haiku-os.org/haiku/commit/?id=3d12d3a83246
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Aug 3 16:50:58 2015 UTC

app_server: special handling for opaque/invisible layers

* Opaque layers (opacity = 255) don't need to use an intermediate
bitmap (and everything that comes with it) for drawing at all,
they can just directly draw onto the underlying canvas or layer.
(WebKit likes to use plenty of opaque layers)

* Invisible layers (opacity = 0) can simply be ignored.

----------------------------------------------------------------------------

############################################################################

Commit: c77b945acdc5bdad234c2d5cd35ffb158e1ae9d8
URL: http://cgit.haiku-os.org/haiku/commit/?id=c77b945acdc5
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Aug 3 16:53:20 2015 UTC

app_server: allow drawing mode changes in opaque layers

* For better performance, we allow doing drawing mode changes
(and thus, B_OP_COPY) again when inside an opaque layer which
has only other opaque layers below it in the layer stack.

As soon as the first non-opaque layer turns up in the stack, the
drawing mode will be locked to alpha composite mode, until this
layer stack is ended entirely.

This allows using B_OP_COPY in many cases as used by WebKit.

* In the long term it would be nice to get rid of the drawing-mode
lock altogether, however that would need some larger refactoring
work in Painter (i.e. remove the offsetting from renderer_region
again and instead implement an "exit-level transform" (support
for offsets is enough) in Painter which is applied after all other
transforms).

----------------------------------------------------------------------------

############################################################################

Commit: e353fe396a362ab9c10a7c058e76007939370f66
URL: http://cgit.haiku-os.org/haiku/commit/?id=e353fe396a36
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Aug 3 21:32:07 2015 UTC

app_server Painter: refactoring, extract bitmap drawing

* Extract bitmap drawing from Painter into separate class
Painter::BitmapPainter. This will allow to add new optimized
drawing modes without making Painter larger.

* BitmapPainter itself is further decomposed into separate
(method object) structs per drawing mode (currently, those are:
generic, no scale, nearest neighbor, bilinear). New optimized
implementations can be added by writing additional method objects
and calling them from BitmapPainter.

* DrawBitmapNoScale and DrawBitmapBilinear are implemented using
CRTP. This removes the function pointer in the 'no scale' version,
which was previously used to select the row copy type. In the
bilinear version it untangles the three variants (default,
low filter ratio, SIMD) into separate methods.

* While BitmapPainter is a nested class in Painter, the specialized
method objects are not. Instead, the AGG-specific data fields from
Painter are moved into a new struct PainterAggInterface. This
struct is passed to the method objects and allows them to access
the Painter's AGG renderer/rasterizer/scanline containers/etc.

Alternatives would be to make all the involved structs friends
of Painter, or nesting them all, or exposing all of Painter's
internals via getter methods -- all of these would be quite messy.

The details of the bitmap painting implementations are
intentionally hidden from Painter: there is no need for it to
know about their internals -- it does not even know their type
names. (Nesting or making them friend would expose their type
names to Painter.)

Furthermore, there is another level of information hiding between
BitmapPainter and the DrawBitmap[...] method objects.
BitmapPainter itself only needs to decide that it uses e.g. the
bilinear version. It has no knowledge that DrawBitmapBilinear is
internally made out of several structs implementing specially
optimized versions.

* Refactoring only, no functional change intended. Performance
should be unaffected.

----------------------------------------------------------------------------

############################################################################

Commit: 2a58d5432d9a428870d9c40fbc613d313a0a9df6
URL: http://cgit.haiku-os.org/haiku/commit/?id=2a58d5432d9a
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 15 09:12:35 2015 UTC

Merge branch 'master' into app_server

----------------------------------------------------------------------------

############################################################################

Commit: f4f05935dbe4fa5c5b1fda880e23d81a18b11da2
URL: http://cgit.haiku-os.org/haiku/commit/?id=f4f05935dbe4
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 15 09:14:42 2015 UTC

app_server: give Painter direct access to alpha masks

* To use alpha masks in optimized drawing code outside of the AGG
renderer pipeline, we need to allow access to the alpha mask's
underlying buffer:

- AlphaMask gets another method which returns its
clipped_alpha_mask
- clipped_alpha_mask gets a get_hspan() method which returns a span
of alpha values without combining it with anything
- Painter/PainterAggInterface store a pointer to the
clipped_alpha_mask (in addition to the AlphaMask's scanline
container)

----------------------------------------------------------------------------

############################################################################

Commit: 79a483ebbfdbf0bdf39c99b12c128a4fd088aa1d
URL: http://cgit.haiku-os.org/haiku/commit/?id=79a483ebbfdb
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 15 09:23:51 2015 UTC

app_server: add alpha masked mode to DrawBitmapNoScale

* Add another mode to DrawBitmapNoScale for drawing bitmaps using
B_OP_COPY with alpha masks. It behaves like the definition for
ClipToPicture from the BeBook: pixels with alpha = 0 are ignored,
pixels with any alpha > 0 are copied.
Before, this fell back to the slower generic AGG-pipeline-based
version.

* Some light refactoring

----------------------------------------------------------------------------

############################################################################

Commit: 64c6e038ebf396d2bc65fae21533458355fd6b90
URL: http://cgit.haiku-os.org/haiku/commit/?id=64c6e038ebf3
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 15 10:50:32 2015 UTC

app_server: bilinear bitmap painting: alpha overlay support

* Add support for pixel alpha overlay mode in the optimized bilinear-
scaled bitmap drawing code of BitmapPainter.
For now, only BilinearDefault supports this. DrawBitmapBilinear
gets the colour type and draw mode as template parameters to
minimize code duplication and allow simple extension with further
pixel formats and modes.
Avoids, for this mode, fallback to the slower generic
AGG-pipeline-based version.

----------------------------------------------------------------------------

############################################################################

Commit: 01c730420420627cf60877c5c018a8b180fa6ceb
URL: http://cgit.haiku-os.org/haiku/commit/?id=01c730420420
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 15 10:53:50 2015 UTC

app_server: fix comment header in pixel alpha overlay modes

----------------------------------------------------------------------------

############################################################################

Commit: ed7b139e08946d93fd3caf56dbc38e709b381094
URL: http://cgit.haiku-os.org/haiku/commit/?id=ed7b139e0894
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 15 10:54:36 2015 UTC

app_server: fix direct assignment in alpha pixel composite

* 'alpha' is 16 bit (alpha * cover) in blend_hline_alpha_pc(), so
compare with 255 * 255

----------------------------------------------------------------------------

############################################################################

Commit: 801b5d2119148b22e273b9c2639b41d979dc86fa
URL: http://cgit.haiku-os.org/haiku/commit/?id=801b5d211914
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 15 10:56:37 2015 UTC

app_server: add pixel alpha composite solid mode

* Same concept as the previously exisiting drawing mode
implementations for e.g. pixel alpha overlay mode: when pattern
is solid, provide a separate mode implementation which does no
unnecessary pattern pixel lookups. This provides a considerable
speedup in composite mode when no stipple pattern is used.

----------------------------------------------------------------------------

############################################################################

Commit: e3d73948690d37330da4349499d4974dcd328f70
URL: http://cgit.haiku-os.org/haiku/commit/?id=e3d73948690d
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 15 11:02:11 2015 UTC

app_server: fix test-app_server for launch_daemon changes

* Make test-app_server work again in a launch_daemon environment

* test_registrar gets a separate signature and port name again so the
host system can distinguish it from the system registrar

* AppServer is normally a BServer now, however, there can't be two
BApplications in one team. A class TestServerLoopAdapter is added,
which becomes the base class of AppServer instead of BServer when
compiling for libbe_test. It's an adapter class which looks towards
AppServer as it if was a BServer, but internally it is derived from
MessageLooper (like the old AppServer before the transition to
BServer).

This way, AppServer can stay a BServer in normal builds and it also
avoids having to use too many #ifdefs to distinguish the two
versions.

----------------------------------------------------------------------------

############################################################################

Commit: 1cd452ea0362086a2cdcaf93fbec292f23ff9d78
URL: http://cgit.haiku-os.org/haiku/commit/?id=1cd452ea0362
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 22 22:29:38 2015 UTC

app_server: Drawing mode fixups

* TODO: squash commit before merge into master

----------------------------------------------------------------------------

############################################################################

Commit: bafd2b461acb32cfb40755067d408e480b0d099e
URL: http://cgit.haiku-os.org/haiku/commit/?id=bafd2b461acb
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 22 22:31:10 2015 UTC

app_server: PictureBoundingBoxPlayer fixups

* TODO: squash commit before merge into master

----------------------------------------------------------------------------

############################################################################

Commit: 9b417f6486256a8166b79c1f92178503e39c4408
URL: http://cgit.haiku-os.org/haiku/commit/?id=9b417f648625
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Sat Aug 22 22:38:55 2015 UTC

app_server: rework AlphaMask, use bounds for mask pictures

* Refactor AlphaMask class to separate the mask from its source. This
allows use to not just a BPicture as source for a pixel alpha mask,
but also e.g. a BShape in the future (not yet implemented).

* For BPicture-based masks, use the PictureBoundingBoxPlayer to
determine the size of the resulting mask bitmap. The masks are now
drawn into bitmaps of this size (instead of the whole view size).

When alpha masks are stacked, their bounding rectangles intersect
(i.e. masks further up in the stack can never be larger than masks
lower in the stack). The bitmap of a mask always contains the state
of itself blended with all masks in the stack below it.

This also avoids frequent rerendering of the masks. They are now
independent of view size. When the view origin (in screen
coordinates) changes we only have to reattach the mask buffer,
without having to redraw it.

* The class UniformAlphaMask is used for simple masks with the same
alpha value in all pixels, it uses no mask bitmap at all.
Currently, it can only be used on its own and not be stacked
together with other mask types.

----------------------------------------------------------------------------

############################################################################

Commit: 71cc4d49983c5897e72bfd8b2eb1b6b6d704d0d7
URL: http://cgit.haiku-os.org/haiku/commit/?id=71cc4d49983c
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Tue Sep 1 18:07:21 2015 UTC

Merge branch 'master' into app_server

Conflicts:
src/kits/app/Roster.cpp

----------------------------------------------------------------------------

############################################################################

Commit: 6109a2086d1110934dc7ff48e381b41c9ea5120e
URL: http://cgit.haiku-os.org/haiku/commit/?id=6109a2086d11
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Tue Nov 10 22:09:54 2015 UTC

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

----------------------------------------------------------------------------

############################################################################

Commit: 08135223ce634855495feacae72c99a887da206d
URL: http://cgit.haiku-os.org/haiku/commit/?id=08135223ce63
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Nov 9 16:53:12 2015 UTC

Affine transforms: add method to test for dilation

* Add IsDilation() to BAffineTransform and Transformable which check
whether the transform is a dilation, i.e. consists of only
translation and/or scaling

----------------------------------------------------------------------------

############################################################################

Commit: ab12093685e7e4bfe65308914c8d945cd3917970
URL: http://cgit.haiku-os.org/haiku/commit/?id=ab12093685e7
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Nov 9 17:09:22 2015 UTC

BShape: move bounding box method to shape_data

* Makes it easier to get the bounding box from inside app_server

----------------------------------------------------------------------------

############################################################################

Commit: 23af4ff6ac19e4a02fe61fd17be1ed79b37f5b5a
URL: http://cgit.haiku-os.org/haiku/commit/?id=23af4ff6ac19
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Nov 9 17:15:08 2015 UTC

app_server: finish BShape-based alpha mask generation

----------------------------------------------------------------------------

############################################################################

Commit: 4bd6f322bb1d5b64c23e65c738cdda777d1759cd
URL: http://cgit.haiku-os.org/haiku/commit/?id=4bd6f322bb1d
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Nov 9 18:57:13 2015 UTC

app_server/Interface Kit: add new clipping API

* Add new clipping API for rectangles (ClipToRect, ClipToInverseRect)
and shapes (ClipToShape, ClipToInverseShape)

* Works with affine transforms and automatically switches from fast
region-based clipping to alpha-mask based clipping as necessary.

* Always self-intersecting, i.e. no state push required to further
narrow down the clipping region. All of the 4 new methods can be
mixed in any order.

----------------------------------------------------------------------------

############################################################################

Commit: 1cde68c5a29b7919a8ca57ce969edecfbe436685
URL: http://cgit.haiku-os.org/haiku/commit/?id=1cde68c5a29b
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Mon Nov 9 19:03:32 2015 UTC

app_server: apply transform to CopyBits

* Apply affine transforms to source and target rects of
BView::CopyBits(). For now, only if transform is a dilation.

----------------------------------------------------------------------------

############################################################################

Commit: 4721524cb5a91fd57032737c09d40d34f87f4c99
URL: http://cgit.haiku-os.org/haiku/commit/?id=4721524cb5a9
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Tue Nov 10 21:22:32 2015 UTC

BAffineTransform: add PreTranslate/PreScale/PreRotate

* The existing methods TranslateBy(), ScaleBy() and RotateBy()
transform the transformation. For a transform A, a point p,
and the temporary transform B (being applied by the methods),
this results in p' = B*(A*p) = (B*A)*p
This is not necessarily the desired result. Suppose A is a
translation and B a rotation, added by RotateBy(). Then B*A
means that the translation itself is rotated, so B moves the
coordinate origin itself, by rotating it around the original
origin of the coordinate system (top left view corner).

If we want to translate and then rotate around that *new* origin,
we need to multiply the transforms the other way around: A*B.

Three new methods PreTranslateBy(), PreScaleBy() and PreRotateBy()
implement this. They are later used as a base to add translatation/
scaling/rotation methods to BView which behave in the expected
ordering, similar to other graphic APIs.

----------------------------------------------------------------------------

############################################################################

Commit: 25dbf74b8e2aac1c64145408d19c933e7a3d3672
URL: http://cgit.haiku-os.org/haiku/commit/?id=25dbf74b8e2a
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Tue Nov 10 21:52:56 2015 UTC

BView: add methods for affine translation/scaling/rotation

* BView::TranslateBy(), BView::ScaleBy() and BView::RotateBy()
allow to conveniently modify the current affine transformation.
This makes it unnecessary to first read the current transform,
modify it, and then set it again.
Uses the new Pre...() methods of BAffineTransform.

* Also, remove setting the transform "through" to the BView even
while recording a BPicture, as this now results in transforms
being applied more than once.

----------------------------------------------------------------------------

############################################################################

Commit: 0a6baa7e7410e69784b4c09a142f7fb2501efa99
URL: http://cgit.haiku-os.org/haiku/commit/?id=0a6baa7e7410
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Tue Nov 10 22:42:43 2015 UTC

app_server: gcc4 build fixes

----------------------------------------------------------------------------

############################################################################

Revision: hrev49807
Commit: 959355842feef458222e6b1648b29ccf9671de51
URL: http://cgit.haiku-os.org/haiku/commit/?id=959355842fee
Author: Julian Harnath <julian.harnath@xxxxxxxxxxxxxx>
Date: Tue Nov 10 23:00:37 2015 UTC

Update haikuwebkit to 1.5.0-1

----------------------------------------------------------------------------


Other related posts: