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.
This commit is contained in:
Julian Harnath
2015-07-25 16:31:19 +02:00
parent ab1bd2fd07
commit 6f2a446e2e
11 changed files with 462 additions and 582 deletions
+40 -165
View File
@@ -17,17 +17,22 @@
#include <new> #include <new>
#include <GradientLinear.h>
#include <GradientRadial.h>
#include <GradientRadialFocus.h>
#include <GradientDiamond.h>
#include <GradientConic.h>
#include <Region.h> #include <Region.h>
#include "DrawingEngine.h" #include "DrawingEngine.h"
#include "DrawState.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() Canvas::Canvas()
: :
fDrawState(new(std::nothrow) DrawState()) fDrawState(new(std::nothrow) DrawState())
@@ -149,179 +154,49 @@ Canvas::GetAlphaMask() const
} }
//! converts a point from local *drawing* to screen coordinate system SimpleTransform
void Canvas::LocalToScreenTransform() const GCC_2_NRV(transform)
Canvas::ConvertToScreenForDrawing(BPoint* point) const
{ {
fDrawState->Transform(point); #if __GNUC__ >= 3
// NOTE: from here on, don't use the SimpleTransform transform;
// "*ForDrawing()" versions of the parent! #endif
ConvertToScreen(point); _LocalToScreenTransform(transform);
return transform;
} }
//! converts a rect from local *drawing* to screen coordinate system SimpleTransform
void Canvas::ScreenToLocalTransform() const GCC_2_NRV(transform)
Canvas::ConvertToScreenForDrawing(BRect* rect) const
{ {
fDrawState->Transform(rect); #if __GNUC__ >= 3
// NOTE: from here on, don't use the SimpleTransform transform;
// "*ForDrawing()" versions of the parent! #endif
ConvertToScreen(rect); _ScreenToLocalTransform(transform);
return transform;
} }
//! converts a region from local *drawing* to screen coordinate system SimpleTransform
void Canvas::PenToScreenTransform() const GCC_2_NRV(transform)
Canvas::ConvertToScreenForDrawing(BRegion* region) const
{ {
fDrawState->Transform(region); #if __GNUC__ >= 3
// NOTE: from here on, don't use the SimpleTransform transform;
// "*ForDrawing()" versions of the parent! #endif
ConvertToScreen(region); fDrawState->Transform(transform);
_LocalToScreenTransform(transform);
return transform;
} }
//! converts a gradient from local *drawing* to screen coordinate system SimpleTransform
void Canvas::ScreenToPenTransform() const GCC_2_NRV(transform)
Canvas::ConvertToScreenForDrawing(BGradient* gradient) const
{ {
switch (gradient->GetType()) { #if __GNUC__ >= 3
case BGradient::TYPE_LINEAR: SimpleTransform transform;
{ #endif
BGradientLinear* linear = (BGradientLinear*) gradient; _ScreenToLocalTransform(transform);
BPoint start = linear->Start(); fDrawState->InverseTransform(transform);
BPoint end = linear->End(); return transform;
fDrawState->Transform(&start);
ConvertToScreen(&start);
fDrawState->Transform(&end);
ConvertToScreen(&end);
linear->SetStart(start);
linear->SetEnd(end);
break;
}
case BGradient::TYPE_RADIAL:
{
BGradientRadial* radial = (BGradientRadial*) gradient;
BPoint center = radial->Center();
fDrawState->Transform(&center);
ConvertToScreen(&center);
radial->SetCenter(center);
break;
}
case BGradient::TYPE_RADIAL_FOCUS:
{
BGradientRadialFocus* radialFocus = (BGradientRadialFocus*) gradient;
BPoint center = radialFocus->Center();
BPoint focal = radialFocus->Focal();
fDrawState->Transform(&center);
ConvertToScreen(&center);
fDrawState->Transform(&focal);
ConvertToScreen(&focal);
radialFocus->SetCenter(center);
radialFocus->SetFocal(focal);
break;
}
case BGradient::TYPE_DIAMOND:
{
BGradientDiamond* diamond = (BGradientDiamond*) gradient;
BPoint center = diamond->Center();
fDrawState->Transform(&center);
ConvertToScreen(&center);
diamond->SetCenter(center);
break;
}
case BGradient::TYPE_CONIC:
{
BGradientConic* conic = (BGradientConic*) gradient;
BPoint center = conic->Center();
fDrawState->Transform(&center);
ConvertToScreen(&center);
conic->SetCenter(center);
break;
}
case BGradient::TYPE_NONE:
{
break;
}
}
// Make sure the gradient is fully padded so that out of bounds access
// get the correct colors
gradient->SortColorStopsByOffset();
BGradient::ColorStop* end = gradient->ColorStopAtFast(
gradient->CountColorStops() - 1);
if (end->offset != 255)
gradient->AddColor(end->color, 255);
BGradient::ColorStop* start = gradient->ColorStopAtFast(0);
if (start->offset != 0)
gradient->AddColor(start->color, 0);
gradient->SortColorStopsByOffset();
}
//! converts points from local *drawing* to screen coordinate system
void
Canvas::ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num) const
{
// TODO: optimize this, it should be smarter
while (num--) {
*dst = *src;
fDrawState->Transform(dst);
// NOTE: from here on, don't use the
// "*ForDrawing()" versions of the parent!
ConvertToScreen(dst);
src++;
dst++;
}
}
//! converts rects from local *drawing* to screen coordinate system
void
Canvas::ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num) const
{
// TODO: optimize this, it should be smarter
while (num--) {
*dst = *src;
fDrawState->Transform(dst);
// NOTE: from here on, don't use the
// "*ForDrawing()" versions of the parent!
ConvertToScreen(dst);
src++;
dst++;
}
}
//! converts regions from local *drawing* to screen coordinate system
void
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
{
ConvertFromScreen(point);
fDrawState->InverseTransform(point);
} }
+17 -29
View File
@@ -17,6 +17,8 @@
#include <Point.h> #include <Point.h>
#include "SimpleTransform.h"
class AlphaMask; class AlphaMask;
class BGradient; class BGradient;
@@ -52,25 +54,10 @@ public:
void SetAlphaMask(AlphaMask* mask); void SetAlphaMask(AlphaMask* mask);
AlphaMask* GetAlphaMask() const; AlphaMask* GetAlphaMask() const;
void ConvertToScreenForDrawing(BPoint* point) const; SimpleTransform LocalToScreenTransform() const;
void ConvertToScreenForDrawing(BRect* rect) const; SimpleTransform ScreenToLocalTransform() const;
void ConvertToScreenForDrawing(BRegion* region) const; SimpleTransform PenToScreenTransform() const;
void ConvertToScreenForDrawing(BGradient* gradient) const; SimpleTransform ScreenToPenTransform() const;
void ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num) const;
void ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num) const;
void ConvertToScreenForDrawing(BRegion* dst, const BRegion* src, int32 num) const;
void ConvertFromScreenForDrawing(BPoint* point) const;
// used when updating the pen position
virtual void ConvertToScreen(BPoint* point) const = 0;
virtual void ConvertToScreen(IntPoint* point) const = 0;
virtual void ConvertToScreen(BRect* rect) const = 0;
virtual void ConvertToScreen(IntRect* rect) const = 0;
virtual void ConvertToScreen(BRegion* region) const = 0;
virtual void ConvertFromScreen(BPoint* point) const = 0;
virtual DrawingEngine* GetDrawingEngine() const = 0; virtual DrawingEngine* GetDrawingEngine() const = 0;
virtual ServerPicture* GetPicture(int32 token) const = 0; virtual ServerPicture* GetPicture(int32 token) const = 0;
@@ -78,6 +65,12 @@ public:
virtual void ResyncDrawState() {}; virtual void ResyncDrawState() {};
virtual void UpdateCurrentDrawingRegion() {}; virtual void UpdateCurrentDrawingRegion() {};
protected:
virtual void _LocalToScreenTransform(
SimpleTransform& transform) const = 0;
virtual void _ScreenToLocalTransform(
SimpleTransform& transform) const = 0;
protected: protected:
DrawState* fDrawState; DrawState* fDrawState;
}; };
@@ -88,22 +81,17 @@ public:
OffscreenCanvas(DrawingEngine* engine, OffscreenCanvas(DrawingEngine* engine,
const DrawState& state); 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 DrawingEngine* GetDrawingEngine() const { return fDrawingEngine; }
virtual void RebuildClipping(bool deep) { /* TODO */ } virtual void RebuildClipping(bool deep) { /* TODO */ }
virtual void ResyncDrawState(); virtual void ResyncDrawState();
virtual ServerPicture* GetPicture(int32 token) const virtual ServerPicture* GetPicture(int32 token) const
{ /* TODO */ return NULL; } { /* TODO */ return NULL; }
protected:
virtual void _LocalToScreenTransform(SimpleTransform&) const {}
virtual void _ScreenToLocalTransform(SimpleTransform&) const {}
private: private:
DrawingEngine* fDrawingEngine; DrawingEngine* fDrawingEngine;
}; };
+12 -74
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2008, Haiku. * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -8,6 +8,7 @@
* Stephan Aßmus <[email protected]> * Stephan Aßmus <[email protected]>
* Axel Dörfler, [email protected] * Axel Dörfler, [email protected]
* Michael Pfeiffer <[email protected]> * Michael Pfeiffer <[email protected]>
* Julian Harnath <[email protected]>
*/ */
//! Data classes for working with BView states and draw parameters //! Data classes for working with BView states and draw parameters
@@ -407,8 +408,9 @@ DrawState::GetCombinedClippingRegion(BRegion* region) const
{ {
if (fClippingRegion != NULL) { if (fClippingRegion != NULL) {
BRegion localTransformedClipping(*fClippingRegion); BRegion localTransformedClipping(*fClippingRegion);
Transform(&localTransformedClipping); SimpleTransform penTransform;
Transform(penTransform);
penTransform.Apply(&localTransformedClipping);
if (fPreviousState != NULL if (fPreviousState != NULL
&& fPreviousState->GetCombinedClippingRegion(region)) { && fPreviousState->GetCombinedClippingRegion(region)) {
localTransformedClipping.IntersectWith(region); localTransformedClipping.IntersectWith(region);
@@ -453,83 +455,19 @@ DrawState::GetAlphaMask() const
void void
DrawState::Transform(float* x, float* y) const DrawState::Transform(SimpleTransform& transform) const
{ {
// scale relative to origin, therefore transform.AddOffset(fCombinedOrigin.x, fCombinedOrigin.y);
// scale first then translate to transform.SetScale(fCombinedScale);
// origin
*x *= fCombinedScale;
*y *= fCombinedScale;
*x += fCombinedOrigin.x;
*y += fCombinedOrigin.y;
} }
void void
DrawState::InverseTransform(float* x, float* y) const DrawState::InverseTransform(SimpleTransform& transform) const
{ {
*x -= fCombinedOrigin.x; transform.AddOffset(-fCombinedOrigin.x, -fCombinedOrigin.y);
*y -= fCombinedOrigin.y; if (fCombinedScale != 0.0)
if (fCombinedScale != 0.0) { transform.SetScale(1.0 / fCombinedScale);
*x /= fCombinedScale;
*y /= fCombinedScale;
}
}
void
DrawState::Transform(BPoint* point) const
{
Transform(&(point->x), &(point->y));
}
void
DrawState::Transform(BRect* rect) const
{
Transform(&(rect->left), &(rect->top));
Transform(&(rect->right), &(rect->bottom));
}
void
DrawState::Transform(BRegion* region) const
{
if (fCombinedScale == 1.0) {
region->OffsetBy(fCombinedOrigin.x, fCombinedOrigin.y);
} else {
// TODO: optimize some more
BRegion converted;
int32 count = region->CountRects();
for (int32 i = 0; i < count; i++) {
BRect r = region->RectAt(i);
BPoint lt(r.LeftTop());
BPoint rb(r.RightBottom());
// offset to bottom right corner of pixel before transformation
rb.x++;
rb.y++;
// apply transformation
Transform(&lt.x, &lt.y);
Transform(&rb.x, &rb.y);
// reset bottom right to pixel "index"
rb.x--;
rb.y--;
// add rect to converted region
// NOTE/TODO: the rect would not have to go
// through the whole intersection test process,
// it is guaranteed not to overlap with any rect
// already contained in the region
converted.Include(BRect(lt, rb));
}
*region = converted;
}
}
void
DrawState::InverseTransform(BPoint* point) const
{
InverseTransform(&(point->x), &(point->y));
} }
+5 -9
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2008, Haiku. * Copyright 2001-2015, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -7,6 +7,7 @@
* Adi Oanca <[email protected]> * Adi Oanca <[email protected]>
* Stephan Aßmus <[email protected]> * Stephan Aßmus <[email protected]>
* Axel Dörfler, [email protected] * Axel Dörfler, [email protected]
* Julian Harnath <[email protected]>
*/ */
#ifndef _DRAW_STATE_H_ #ifndef _DRAW_STATE_H_
#define _DRAW_STATE_H_ #define _DRAW_STATE_H_
@@ -20,6 +21,7 @@
#include "ServerFont.h" #include "ServerFont.h"
#include "PatternHandler.h" #include "PatternHandler.h"
#include "SimpleTransform.h"
class AlphaMask; class AlphaMask;
class BRegion; class BRegion;
@@ -78,14 +80,8 @@ public:
AlphaMask* GetAlphaMask() const; AlphaMask* GetAlphaMask() const;
// coordinate transformations // coordinate transformations
void Transform(float* x, float* y) const; void Transform(SimpleTransform& transform) const;
void InverseTransform(float* x, float* y) const; void InverseTransform(SimpleTransform& transform) const;
void Transform(BPoint* point) const;
void Transform(BRect* rect) const;
void Transform(BRegion* region) const;
void InverseTransform(BPoint* point) const;
// color // color
void SetHighColor(rgb_color color); void SetHighColor(rgb_color color);
+21 -26
View File
@@ -204,7 +204,7 @@ ShapePainter::Draw(BRect frame, bool filled)
} }
BPoint offset(fCanvas->CurrentState()->PenLocation()); BPoint offset(fCanvas->CurrentState()->PenLocation());
fCanvas->ConvertToScreenForDrawing(&offset); fCanvas->PenToScreenTransform().Apply(&offset);
fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList, fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList,
ptCount, ptList, filled, offset, fCanvas->Scale()); ptCount, ptList, filled, offset, fCanvas->Scale());
@@ -265,8 +265,9 @@ stroke_line(Canvas* canvas, BPoint start, BPoint end)
{ {
BPoint penPos = end; BPoint penPos = end;
canvas->ConvertToScreenForDrawing(&start); const SimpleTransform transform = canvas->PenToScreenTransform();
canvas->ConvertToScreenForDrawing(&end); transform.Apply(&start);
transform.Apply(&end);
canvas->GetDrawingEngine()->StrokeLine(start, end); canvas->GetDrawingEngine()->StrokeLine(start, end);
canvas->CurrentState()->SetPenLocation(penPos); canvas->CurrentState()->SetPenLocation(penPos);
@@ -279,7 +280,7 @@ stroke_line(Canvas* canvas, BPoint start, BPoint end)
static void static void
stroke_rect(Canvas* canvas, BRect rect) stroke_rect(Canvas* canvas, BRect rect)
{ {
canvas->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->StrokeRect(rect); canvas->GetDrawingEngine()->StrokeRect(rect);
} }
@@ -287,7 +288,7 @@ stroke_rect(Canvas* canvas, BRect rect)
static void static void
fill_rect(Canvas* canvas, BRect rect) fill_rect(Canvas* canvas, BRect rect)
{ {
canvas->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->FillRect(rect); canvas->GetDrawingEngine()->FillRect(rect);
} }
@@ -295,7 +296,7 @@ fill_rect(Canvas* canvas, BRect rect)
static void static void
draw_round_rect(Canvas* canvas, BRect rect, BPoint radii, bool fill) draw_round_rect(Canvas* canvas, BRect rect, BPoint radii, bool fill)
{ {
canvas->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
float scale = canvas->CurrentState()->CombinedScale(); float scale = canvas->CurrentState()->CombinedScale();
canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale, canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
radii.y * scale, fill); radii.y * scale, fill);
@@ -320,8 +321,7 @@ static void
stroke_bezier(Canvas* canvas, const BPoint* viewPoints) stroke_bezier(Canvas* canvas, const BPoint* viewPoints)
{ {
BPoint points[4]; BPoint points[4];
canvas->ConvertToScreenForDrawing(points, viewPoints, 4); canvas->PenToScreenTransform().Apply(points, viewPoints, 4);
canvas->GetDrawingEngine()->DrawBezier(points, false); canvas->GetDrawingEngine()->DrawBezier(points, false);
} }
@@ -330,8 +330,7 @@ static void
fill_bezier(Canvas* canvas, const BPoint* viewPoints) fill_bezier(Canvas* canvas, const BPoint* viewPoints)
{ {
BPoint points[4]; BPoint points[4];
canvas->ConvertToScreenForDrawing(points, viewPoints, 4); canvas->PenToScreenTransform().Apply(points, viewPoints, 4);
canvas->GetDrawingEngine()->DrawBezier(points, true); 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, BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1); center.x + radii.x - 1, center.y + radii.y - 1);
canvas->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, false); 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, BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1); center.x + radii.x - 1, center.y + radii.y - 1);
canvas->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, true); 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, BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1); center.x + radii.x - 1, center.y + radii.y - 1);
canvas->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->DrawEllipse(rect, false); 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, BRect rect(center.x - radii.x, center.y - radii.y,
center.x + radii.x - 1, center.y + radii.y - 1); center.x + radii.x - 1, center.y + radii.y - 1);
canvas->ConvertToScreenForDrawing(&rect); canvas->PenToScreenTransform().Apply(&rect);
canvas->GetDrawingEngine()->DrawEllipse(rect, true); canvas->GetDrawingEngine()->DrawEllipse(rect, true);
} }
@@ -391,8 +390,7 @@ stroke_polygon(Canvas* canvas, int32 numPoints,
char data[200 * sizeof(BPoint)]; char data[200 * sizeof(BPoint)];
BPoint* points = (BPoint*)data; BPoint* points = (BPoint*)data;
canvas->ConvertToScreenForDrawing(points, viewPoints, numPoints); canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);
BRect polyFrame; BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame); get_polygon_frame(points, numPoints, &polyFrame);
@@ -405,8 +403,7 @@ stroke_polygon(Canvas* canvas, int32 numPoints,
if (points == NULL) if (points == NULL)
return; return;
canvas->ConvertToScreenForDrawing(points, viewPoints, numPoints); canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);
BRect polyFrame; BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame); get_polygon_frame(points, numPoints, &polyFrame);
@@ -430,8 +427,7 @@ fill_polygon(Canvas* canvas, int32 numPoints,
char data[200 * sizeof(BPoint)]; char data[200 * sizeof(BPoint)];
BPoint* points = (BPoint*)data; BPoint* points = (BPoint*)data;
canvas->ConvertToScreenForDrawing(points, viewPoints, numPoints); canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);
BRect polyFrame; BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame); get_polygon_frame(points, numPoints, &polyFrame);
@@ -444,8 +440,7 @@ fill_polygon(Canvas* canvas, int32 numPoints,
if (points == NULL) if (points == NULL)
return; return;
canvas->ConvertToScreenForDrawing(points, viewPoints, numPoints); canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);
BRect polyFrame; BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame); get_polygon_frame(points, numPoints, &polyFrame);
@@ -486,11 +481,11 @@ draw_string(Canvas* canvas, const char* string, float deltaSpace,
BPoint location = canvas->CurrentState()->PenLocation(); BPoint location = canvas->CurrentState()->PenLocation();
escapement_delta delta = { deltaSpace, deltaNonSpace }; escapement_delta delta = { deltaSpace, deltaNonSpace };
canvas->ConvertToScreenForDrawing(&location); canvas->PenToScreenTransform().Apply(&location);
location = canvas->GetDrawingEngine()->DrawString(string, strlen(string), location = canvas->GetDrawingEngine()->DrawString(string, strlen(string),
location, &delta); location, &delta);
canvas->ConvertFromScreenForDrawing(&location); canvas->PenToScreenTransform().Apply(&location);
canvas->CurrentState()->SetPenLocation(location); canvas->CurrentState()->SetPenLocation(location);
// the DrawingEngine/Painter does not need to be updated, since this // the DrawingEngine/Painter does not need to be updated, since this
// effects only the view->screen coord conversion, which is handled // effects only the view->screen coord conversion, which is handled
@@ -511,7 +506,7 @@ draw_pixels(Canvas* canvas, BRect src, BRect dest, int32 width,
memcpy(bitmap.Bits(), data, height * bytesPerRow); memcpy(bitmap.Bits(), data, height * bytesPerRow);
canvas->ConvertToScreenForDrawing(&dest); canvas->PenToScreenTransform().Apply(&dest);
canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options); canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
} }
@@ -570,7 +565,7 @@ pop_state(Canvas* canvas)
canvas->PopState(); canvas->PopState();
BPoint p(0, 0); BPoint p(0, 0);
canvas->ConvertToScreenForDrawing(&p); canvas->PenToScreenTransform().Apply(&p);
canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(), canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(),
(int32)p.x, (int32)p.y); (int32)p.x, (int32)p.y);
} }
+79 -49
View File
@@ -1964,7 +1964,7 @@ fDesktop->LockSingleWindow();
} else { } else {
_UpdateCurrentDrawingRegion(); _UpdateCurrentDrawingRegion();
BRegion region(fCurrentDrawingRegion); BRegion region(fCurrentDrawingRegion);
fCurrentView->ConvertFromScreen(&region); fCurrentView->ScreenToLocalTransform().Apply(&region);
fLink.AttachRegion(region); fLink.AttachRegion(region);
} }
fLink.Flush(); fLink.Flush();
@@ -2254,8 +2254,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
info.endPoint.x, info.endPoint.y)); info.endPoint.x, info.endPoint.y));
BPoint penPos = info.endPoint; BPoint penPos = info.endPoint;
fCurrentView->ConvertToScreenForDrawing(&info.startPoint); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(&info.endPoint); fCurrentView->PenToScreenTransform();
transform.Apply(&info.startPoint);
transform.Apply(&info.endPoint);
drawingEngine->StrokeLine(info.startPoint, info.endPoint); drawingEngine->StrokeLine(info.startPoint, info.endPoint);
// We update the pen here because many DrawingEngine calls which // We update the pen here because many DrawingEngine calls which
@@ -2279,7 +2281,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top, rect.right, fCurrentView->Name(), rect.left, rect.top, rect.right,
rect.bottom)); rect.bottom));
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->InvertRect(rect); drawingEngine->InvertRect(rect);
break; break;
} }
@@ -2294,7 +2296,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top, rect.right, fCurrentView->Name(), rect.left, rect.top, rect.right,
rect.bottom)); rect.bottom));
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->StrokeRect(rect); drawingEngine->StrokeRect(rect);
break; break;
} }
@@ -2309,7 +2311,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top, rect.right, fCurrentView->Name(), rect.left, rect.top, rect.right,
rect.bottom)); rect.bottom));
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->FillRect(rect); drawingEngine->FillRect(rect);
break; break;
} }
@@ -2326,8 +2328,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
fCurrentView->Name(), rect.left, rect.top, rect.right, fCurrentView->Name(), rect.left, rect.top, rect.right,
rect.bottom)); rect.bottom));
fCurrentView->ConvertToScreenForDrawing(&rect); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&rect);
transform.Apply(gradient);
drawingEngine->FillRect(rect, *gradient); drawingEngine->FillRect(rect, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2356,7 +2360,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
info.viewRect.left, info.viewRect.top, info.viewRect.left, info.viewRect.top,
info.viewRect.right, info.viewRect.bottom)); info.viewRect.right, info.viewRect.bottom));
fCurrentView->ConvertToScreenForDrawing(&info.viewRect); fCurrentView->PenToScreenTransform().Apply(&info.viewRect);
// TODO: Unbreak... // TODO: Unbreak...
// if ((info.options & B_WAIT_FOR_RETRACE) != 0) // if ((info.options & B_WAIT_FOR_RETRACE) != 0)
@@ -2382,7 +2386,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<float>(&span) != B_OK) if (link.Read<float>(&span) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&r); fCurrentView->PenToScreenTransform().Apply(&r);
drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC); drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC);
break; break;
} }
@@ -2399,8 +2403,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&r); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&r);
transform.Apply(gradient);
drawingEngine->FillArc(r, angle, span, *gradient); drawingEngine->FillArc(r, angle, span, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2411,11 +2417,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n", DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n",
Title())); Title()));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint pts[4]; BPoint pts[4];
status_t status; status_t status;
for (int32 i = 0; i < 4; i++) { for (int32 i = 0; i < 4; i++) {
status = link.Read<BPoint>(&(pts[i])); status = link.Read<BPoint>(&(pts[i]));
fCurrentView->ConvertToScreenForDrawing(&pts[i]); transform.Apply(&pts[i]);
} }
if (status != B_OK) if (status != B_OK)
break; break;
@@ -2428,15 +2436,17 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n", GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n",
Title())); Title()));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint pts[4]; BPoint pts[4];
for (int32 i = 0; i < 4; i++) { for (int32 i = 0; i < 4; i++) {
link.Read<BPoint>(&(pts[i])); link.Read<BPoint>(&(pts[i]));
fCurrentView->ConvertToScreenForDrawing(&pts[i]); transform.Apply(&pts[i]);
} }
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(gradient); transform.Apply(gradient);
drawingEngine->FillBezier(pts, *gradient); drawingEngine->FillBezier(pts, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2451,7 +2461,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<BRect>(&rect) != B_OK) if (link.Read<BRect>(&rect) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE); drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE);
break; break;
} }
@@ -2465,8 +2475,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&rect);
transform.Apply(gradient);
drawingEngine->FillEllipse(rect, *gradient); drawingEngine->FillEllipse(rect, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2485,7 +2497,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.Read<float>(&yRadius) != B_OK) if (link.Read<float>(&yRadius) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); fCurrentView->PenToScreenTransform().Apply(&rect);
float scale = fCurrentView->CurrentState()->CombinedScale(); float scale = fCurrentView->CurrentState()->CombinedScale();
drawingEngine->DrawRoundRect(rect, xRadius * scale, yRadius * scale, drawingEngine->DrawRoundRect(rect, xRadius * scale, yRadius * scale,
code == AS_FILL_ROUNDRECT); code == AS_FILL_ROUNDRECT);
@@ -2504,8 +2516,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&rect);
transform.Apply(gradient);
drawingEngine->FillRoundRect(rect, xrad, yrad, *gradient); drawingEngine->FillRoundRect(rect, xrad, yrad, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2516,18 +2530,20 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n", DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n",
Title())); Title()));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint pts[3]; BPoint pts[3];
BRect rect; BRect rect;
for (int32 i = 0; i < 3; i++) { for (int32 i = 0; i < 3; i++) {
link.Read<BPoint>(&(pts[i])); link.Read<BPoint>(&(pts[i]));
fCurrentView->ConvertToScreenForDrawing(&pts[i]); transform.Apply(&pts[i]);
} }
if (link.Read<BRect>(&rect) != B_OK) if (link.Read<BRect>(&rect) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); transform.Apply(&rect);
drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE); drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE);
break; break;
} }
@@ -2536,18 +2552,20 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n", DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n",
Title())); Title()));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint pts[3]; BPoint pts[3];
BRect rect; BRect rect;
for (int32 i = 0; i < 3; i++) { for (int32 i = 0; i < 3; i++) {
link.Read<BPoint>(&(pts[i])); link.Read<BPoint>(&(pts[i]));
fCurrentView->ConvertToScreenForDrawing(&pts[i]); transform.Apply(&pts[i]);
} }
link.Read<BRect>(&rect); link.Read<BRect>(&rect);
BGradient* gradient; BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&rect); transform.Apply(&rect);
fCurrentView->ConvertToScreenForDrawing(gradient); transform.Apply(gradient);
drawingEngine->FillTriangle(pts, rect, *gradient); drawingEngine->FillTriangle(pts, rect, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2567,11 +2585,13 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
link.Read<bool>(&isClosed); link.Read<bool>(&isClosed);
link.Read<int32>(&pointCount); link.Read<int32>(&pointCount);
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint* pointList = new(nothrow) BPoint[pointCount]; BPoint* pointList = new(nothrow) BPoint[pointCount];
if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) { if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
for (int32 i = 0; i < pointCount; i++) for (int32 i = 0; i < pointCount; i++)
fCurrentView->ConvertToScreenForDrawing(&pointList[i]); transform.Apply(&pointList[i]);
fCurrentView->ConvertToScreenForDrawing(&polyFrame); transform.Apply(&polyFrame);
drawingEngine->DrawPolygon(pointList, pointCount, polyFrame, drawingEngine->DrawPolygon(pointList, pointCount, polyFrame,
code == AS_FILL_POLYGON, isClosed && pointCount > 2); code == AS_FILL_POLYGON, isClosed && pointCount > 2);
@@ -2590,14 +2610,16 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
link.Read<BRect>(&polyFrame); link.Read<BRect>(&polyFrame);
link.Read<int32>(&pointCount); link.Read<int32>(&pointCount);
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
BPoint* pointList = new(nothrow) BPoint[pointCount]; BPoint* pointList = new(nothrow) BPoint[pointCount];
BGradient* gradient; BGradient* gradient;
if (link.Read(pointList, pointCount * sizeof(BPoint)) == B_OK if (link.Read(pointList, pointCount * sizeof(BPoint)) == B_OK
&& link.ReadGradient(&gradient) == B_OK) { && link.ReadGradient(&gradient) == B_OK) {
for (int32 i = 0; i < pointCount; i++) for (int32 i = 0; i < pointCount; i++)
fCurrentView->ConvertToScreenForDrawing(&pointList[i]); transform.Apply(&pointList[i]);
fCurrentView->ConvertToScreenForDrawing(&polyFrame); transform.Apply(&polyFrame);
fCurrentView->ConvertToScreenForDrawing(gradient); transform.Apply(gradient);
drawingEngine->FillPolygon(pointList, pointCount, drawingEngine->FillPolygon(pointList, pointCount,
polyFrame, *gradient, isClosed && pointCount > 2); polyFrame, *gradient, isClosed && pointCount > 2);
@@ -2631,8 +2653,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
= fCurrentView->CurrentState()->PenLocation(); = fCurrentView->CurrentState()->PenLocation();
shapeFrame.OffsetBy(screenOffset); shapeFrame.OffsetBy(screenOffset);
fCurrentView->ConvertToScreenForDrawing(&screenOffset); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(&shapeFrame); fCurrentView->PenToScreenTransform();
transform.Apply(&screenOffset);
transform.Apply(&shapeFrame);
drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount, drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount,
ptList, code == AS_FILL_SHAPE, screenOffset, ptList, code == AS_FILL_SHAPE, screenOffset,
@@ -2669,9 +2693,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
= fCurrentView->CurrentState()->PenLocation(); = fCurrentView->CurrentState()->PenLocation();
shapeFrame.OffsetBy(screenOffset); shapeFrame.OffsetBy(screenOffset);
fCurrentView->ConvertToScreenForDrawing(&screenOffset); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(&shapeFrame); fCurrentView->PenToScreenTransform();
fCurrentView->ConvertToScreenForDrawing(gradient); transform.Apply(&screenOffset);
transform.Apply(&shapeFrame);
transform.Apply(gradient);
drawingEngine->FillShape(shapeFrame, opCount, opList, drawingEngine->FillShape(shapeFrame, opCount, opList,
ptCount, ptList, *gradient, screenOffset, ptCount, ptList, *gradient, screenOffset,
fCurrentView->Scale()); fCurrentView->Scale());
@@ -2690,7 +2716,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.ReadRegion(&region) < B_OK) if (link.ReadRegion(&region) < B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&region); fCurrentView->PenToScreenTransform().Apply(&region);
drawingEngine->FillRegion(region); drawingEngine->FillRegion(region);
break; break;
@@ -2707,8 +2733,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
if (link.ReadGradient(&gradient) != B_OK) if (link.ReadGradient(&gradient) != B_OK)
break; break;
fCurrentView->ConvertToScreenForDrawing(&region); const SimpleTransform transform =
fCurrentView->ConvertToScreenForDrawing(gradient); fCurrentView->PenToScreenTransform();
transform.Apply(&region);
transform.Apply(gradient);
drawingEngine->FillRegion(region, *gradient); drawingEngine->FillRegion(region, *gradient);
delete gradient; delete gradient;
break; break;
@@ -2747,11 +2775,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
} }
// Convert to screen coords and draw // Convert to screen coords and draw
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
for (int32 i = 0; i < lineCount; i++) { for (int32 i = 0; i < lineCount; i++) {
fCurrentView->ConvertToScreenForDrawing( transform.Apply(&lineData[i].startPoint);
&lineData[i].startPoint); transform.Apply(&lineData[i].endPoint);
fCurrentView->ConvertToScreenForDrawing(
&lineData[i].endPoint);
} }
drawingEngine->StrokeLineArray(lineCount, lineData); drawingEngine->StrokeLineArray(lineCount, lineData);
@@ -2796,11 +2824,11 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View: %s " DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View: %s "
"-> %s\n", Title(), fCurrentView->Name(), string)); "-> %s\n", Title(), fCurrentView->Name(), string));
fCurrentView->ConvertToScreenForDrawing(&info.location); fCurrentView->PenToScreenTransform().Apply(&info.location);
BPoint penLocation = drawingEngine->DrawString(string, BPoint penLocation = drawingEngine->DrawString(string,
info.stringLength, info.location, delta); info.stringLength, info.location, delta);
fCurrentView->ConvertFromScreenForDrawing(&penLocation); fCurrentView->ScreenToPenTransform().Apply(&penLocation);
fCurrentView->CurrentState()->SetPenLocation(penLocation); fCurrentView->CurrentState()->SetPenLocation(penLocation);
if (string != stackString) if (string != stackString)
@@ -2853,13 +2881,15 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING_WITH_OFFSETS, View: %s " DTRACE(("ServerWindow %s: Message AS_DRAW_STRING_WITH_OFFSETS, View: %s "
"-> %s\n", Title(), fCurrentView->Name(), string)); "-> %s\n", Title(), fCurrentView->Name(), string));
const SimpleTransform transform =
fCurrentView->PenToScreenTransform();
for (int32 i = 0; i < glyphCount; i++) for (int32 i = 0; i < glyphCount; i++)
fCurrentView->ConvertToScreenForDrawing(&locations[i]); transform.Apply(&locations[i]);
BPoint penLocation = drawingEngine->DrawString(string, BPoint penLocation = drawingEngine->DrawString(string,
stringLength, locations); stringLength, locations);
fCurrentView->ConvertFromScreenForDrawing(&penLocation); fCurrentView->ScreenToPenTransform().Apply(&penLocation);
fCurrentView->CurrentState()->SetPenLocation(penLocation); fCurrentView->CurrentState()->SetPenLocation(penLocation);
break; break;
@@ -3703,11 +3733,11 @@ ServerWindow::_UpdateDrawState(View* view)
if (view != NULL && drawingEngine != NULL) { if (view != NULL && drawingEngine != NULL) {
BPoint leftTop(0, 0); BPoint leftTop(0, 0);
if (view->GetAlphaMask() != NULL) { if (view->GetAlphaMask() != NULL) {
view->ConvertToScreen(&leftTop); view->LocalToScreenTransform().Apply(&leftTop);
view->GetAlphaMask()->Update(view->Bounds(), leftTop); view->GetAlphaMask()->Update(view->Bounds(), leftTop);
leftTop = BPoint(0, 0); leftTop = BPoint(0, 0);
} }
view->ConvertToScreenForDrawing(&leftTop); view->PenToScreenTransform().Apply(&leftTop);
drawingEngine->SetDrawState(view->CurrentState(), leftTop.x, leftTop.y); drawingEngine->SetDrawState(view->CurrentState(), leftTop.x, leftTop.y);
} }
} }
+243
View File
@@ -0,0 +1,243 @@
/*
* Copyright (c) 2001-2015, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* Stephan Aßmus <superstippi@gmx.de>
* Adrien Destugues <pulkomandy@pulkomandy.tk>
* Julian Harnath <julian.harnath@rwth-aachen.de>
*/
#ifndef SIMPLE_TRANSFORM_H
#define SIMPLE_TRANSFORM_H
#include <GradientLinear.h>
#include <GradientRadial.h>
#include <GradientRadialFocus.h>
#include <GradientDiamond.h>
#include <GradientConic.h>
#include <Point.h>
#include <Region.h>
#include "IntPoint.h"
#include "IntRect.h"
class SimpleTransform {
public:
SimpleTransform()
:
fScale(1.0)
{
}
void AddOffset(float x, float y)
{
fOffset.x += x;
fOffset.y += y;
}
void SetScale(float scale)
{
fScale = scale;
}
void Apply(BPoint* point) const
{
_Apply(point->x, point->y);
}
void Apply(IntPoint* point) const
{
_Apply(point->x, point->y);
}
void Apply(BRect* rect) const
{
if (fScale == 1.0) {
rect->OffsetBy(fOffset.x, fOffset.y);
} else {
_Apply(rect->left, rect->top);
_Apply(rect->right, rect->bottom);
}
}
void Apply(IntRect* rect) const
{
if (fScale == 1.0) {
rect->OffsetBy(fOffset.x, fOffset.y);
} else {
_Apply(rect->left, rect->top);
_Apply(rect->right, rect->bottom);
}
}
void Apply(BRegion* region) const
{
if (fScale == 1.0) {
region->OffsetBy(fOffset.x, fOffset.y);
} else {
// TODO: optimize some more
BRegion converted;
int32 count = region->CountRects();
for (int32 i = 0; i < count; i++) {
BRect r = region->RectAt(i);
BPoint lt(r.LeftTop());
BPoint rb(r.RightBottom());
// offset to bottom right corner of pixel before transformation
rb.x++;
rb.y++;
// apply transformation
_Apply(lt.x, lt.y);
_Apply(rb.x, rb.y);
// reset bottom right to pixel "index"
rb.x--;
rb.y--;
// add rect to converted region
// NOTE/TODO: the rect would not have to go
// through the whole intersection test process,
// it is guaranteed not to overlap with any rect
// already contained in the region
converted.Include(BRect(lt, rb));
}
*region = converted;
}
}
void Apply(BGradient* gradient) const
{
switch (gradient->GetType()) {
case BGradient::TYPE_LINEAR:
{
BGradientLinear* linear = (BGradientLinear*) gradient;
BPoint start = linear->Start();
BPoint end = linear->End();
Apply(&start);
Apply(&end);
linear->SetStart(start);
linear->SetEnd(end);
break;
}
case BGradient::TYPE_RADIAL:
{
BGradientRadial* radial = (BGradientRadial*) gradient;
BPoint center = radial->Center();
Apply(&center);
radial->SetCenter(center);
break;
}
case BGradient::TYPE_RADIAL_FOCUS:
{
BGradientRadialFocus* radialFocus =
(BGradientRadialFocus*)gradient;
BPoint center = radialFocus->Center();
BPoint focal = radialFocus->Focal();
Apply(&center);
Apply(&focal);
radialFocus->SetCenter(center);
radialFocus->SetFocal(focal);
break;
}
case BGradient::TYPE_DIAMOND:
{
BGradientDiamond* diamond = (BGradientDiamond*) gradient;
BPoint center = diamond->Center();
Apply(&center);
diamond->SetCenter(center);
break;
}
case BGradient::TYPE_CONIC:
{
BGradientConic* conic = (BGradientConic*) gradient;
BPoint center = conic->Center();
Apply(&center);
conic->SetCenter(center);
break;
}
case BGradient::TYPE_NONE:
{
break;
}
}
// Make sure the gradient is fully padded so that out of bounds access
// get the correct colors
gradient->SortColorStopsByOffset();
BGradient::ColorStop* end = gradient->ColorStopAtFast(
gradient->CountColorStops() - 1);
if (end->offset != 255)
gradient->AddColor(end->color, 255);
BGradient::ColorStop* start = gradient->ColorStopAtFast(0);
if (start->offset != 0)
gradient->AddColor(start->color, 0);
gradient->SortColorStopsByOffset();
}
void Apply(BPoint* destination, const BPoint* source, int32 count) const
{
// TODO: optimize this, it should be smarter
while (count--) {
*destination = *source;
Apply(destination);
source++;
destination++;
}
}
void Apply(BRect* destination, const BRect* source, int32 count) const
{
// TODO: optimize this, it should be smarter
while (count--) {
*destination = *source;
Apply(destination);
source++;
destination++;
}
}
void Apply(BRegion* destination, const BRegion* source, int32 count) const
{
// TODO: optimize this, it should be smarter
while (count--) {
*destination = *source;
Apply(destination);
source++;
destination++;
}
}
private:
void _Apply(int32& x, int32& y) const
{
x *= (int32)fScale;
y *= (int32)fScale;
x += (int32)fOffset.x;
y += (int32)fOffset.y;
}
void _Apply(float& x, float& y) const
{
x *= fScale;
y *= fScale;
x += fOffset.x;
y += fOffset.y;
}
private:
BPoint fOffset;
float fScale;
};
#endif // SIMPLE_TRANSFORM_H
+32 -198
View File
@@ -165,7 +165,8 @@ View::ConvertToVisibleInTopView(IntRect* bounds) const
{ {
*bounds = *bounds & Bounds(); *bounds = *bounds & Bounds();
// NOTE: this step is necessary even if we don't have a parent! // NOTE: this step is necessary even if we don't have a parent!
ConvertToParent(bounds); bounds->OffsetBy(fFrame.left - fScrollingOffset.x,
fFrame.top - fScrollingOffset.y);
if (fParent) if (fParent)
fParent->ConvertToVisibleInTopView(bounds); fParent->ConvertToVisibleInTopView(bounds);
@@ -440,7 +441,7 @@ View::ViewAt(const BPoint& where)
IntRect frame = Frame(); IntRect frame = Frame();
if (Parent() != NULL) if (Parent() != NULL)
Parent()->ConvertToScreen(&frame); Parent()->LocalToScreenTransform().Apply(&frame);
if (!frame.Contains(where)) if (!frame.Contains(where))
return NULL; return NULL;
@@ -524,7 +525,7 @@ View::_UpdateOverlayView() const
return; return;
IntRect destination = fBitmapDestination; IntRect destination = fBitmapDestination;
ConvertToScreen(&destination); LocalToScreenTransform().Apply(&destination);
overlay->Configure(fBitmapSource, destination); overlay->Configure(fBitmapSource, destination);
} }
@@ -556,201 +557,34 @@ View::UpdateOverlay()
void void
View::ConvertToParent(BPoint* point) const View::_LocalToScreenTransform(SimpleTransform& transform) const
{ {
// remove scrolling offset and convert to parent coordinate space const View* view = this;
point->x += fFrame.left - fScrollingOffset.x; int32 offsetX = 0;
point->y += fFrame.top - fScrollingOffset.y; int32 offsetY = 0;
do {
offsetX += view->fFrame.left - view->fScrollingOffset.x;
offsetY += view->fFrame.top - view->fScrollingOffset.y;
view = view->fParent;
} while (view != NULL);
transform.AddOffset(offsetX, offsetY);
} }
void void
View::ConvertToParent(IntPoint* point) const View::_ScreenToLocalTransform(SimpleTransform& transform) const
{ {
// remove scrolling offset and convert to parent coordinate space const View* view = this;
point->x += fFrame.left - fScrollingOffset.x; int32 offsetX = 0;
point->y += fFrame.top - fScrollingOffset.y; int32 offsetY = 0;
} do {
offsetX += view->fScrollingOffset.x - view->fFrame.left;
offsetY += view->fScrollingOffset.y - view->fFrame.top;
view = view->fParent;
} while (view != NULL);
transform.AddOffset(offsetX, offsetY);
void
View::ConvertToParent(BRect* rect) const
{
// remove scrolling offset and convert to parent coordinate space
rect->OffsetBy(fFrame.left - fScrollingOffset.x,
fFrame.top - fScrollingOffset.y);
}
void
View::ConvertToParent(IntRect* rect) const
{
// remove scrolling offset and convert to parent coordinate space
rect->OffsetBy(fFrame.left - fScrollingOffset.x,
fFrame.top - fScrollingOffset.y);
}
void
View::ConvertToParent(BRegion* region) const
{
// remove scrolling offset and convert to parent coordinate space
region->OffsetBy(fFrame.left - fScrollingOffset.x,
fFrame.top - fScrollingOffset.y);
}
void
View::ConvertFromParent(BPoint* point) const
{
// convert from parent coordinate space amd add scrolling offset
point->x += fScrollingOffset.x - fFrame.left;
point->y += fScrollingOffset.y - fFrame.top;
}
void
View::ConvertFromParent(IntPoint* point) const
{
// convert from parent coordinate space amd add scrolling offset
point->x += fScrollingOffset.x - fFrame.left;
point->y += fScrollingOffset.y - fFrame.top;
}
void
View::ConvertFromParent(BRect* rect) const
{
// convert from parent coordinate space amd add scrolling offset
rect->OffsetBy(fScrollingOffset.x - fFrame.left,
fScrollingOffset.y - fFrame.top);
}
void
View::ConvertFromParent(IntRect* rect) const
{
// convert from parent coordinate space amd add scrolling offset
rect->OffsetBy(fScrollingOffset.x - fFrame.left,
fScrollingOffset.y - fFrame.top);
}
void
View::ConvertFromParent(BRegion* region) const
{
// convert from parent coordinate space amd add scrolling offset
region->OffsetBy(fScrollingOffset.x - fFrame.left,
fScrollingOffset.y - fFrame.top);
}
//! converts a point from local to screen coordinate system
void
View::ConvertToScreen(BPoint* pt) const
{
ConvertToParent(pt);
if (fParent)
fParent->ConvertToScreen(pt);
}
//! converts a point from local to screen coordinate system
void
View::ConvertToScreen(IntPoint* pt) const
{
ConvertToParent(pt);
if (fParent)
fParent->ConvertToScreen(pt);
}
//! converts a rect from local to screen coordinate system
void
View::ConvertToScreen(BRect* rect) const
{
BPoint offset(0.0, 0.0);
ConvertToScreen(&offset);
rect->OffsetBy(offset);
}
//! converts a rect from local to screen coordinate system
void
View::ConvertToScreen(IntRect* rect) const
{
BPoint offset(0.0, 0.0);
ConvertToScreen(&offset);
rect->OffsetBy(offset);
}
//! converts a region from local to screen coordinate system
void
View::ConvertToScreen(BRegion* region) const
{
BPoint offset(0.0, 0.0);
ConvertToScreen(&offset);
region->OffsetBy((int)offset.x, (int)offset.y);
}
//! converts a point from screen to local coordinate system
void
View::ConvertFromScreen(BPoint* pt) const
{
ConvertFromParent(pt);
if (fParent)
fParent->ConvertFromScreen(pt);
}
//! converts a point from screen to local coordinate system
void
View::ConvertFromScreen(IntPoint* pt) const
{
ConvertFromParent(pt);
if (fParent)
fParent->ConvertFromScreen(pt);
}
//! converts a rect from screen to local coordinate system
void
View::ConvertFromScreen(BRect* rect) const
{
BPoint offset(0.0, 0.0);
ConvertFromScreen(&offset);
rect->OffsetBy(offset.x, offset.y);
}
//! converts a rect from screen to local coordinate system
void
View::ConvertFromScreen(IntRect* rect) const
{
BPoint offset(0.0, 0.0);
ConvertFromScreen(&offset);
rect->OffsetBy((int)offset.x, (int)offset.y);
}
//! converts a region from screen to local coordinate system
void
View::ConvertFromScreen(BRegion* region) const
{
BPoint offset(0.0, 0.0);
ConvertFromScreen(&offset);
region->OffsetBy((int)offset.x, (int)offset.y);
} }
@@ -775,7 +609,7 @@ View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
// local clipping to see which parts need invalidation // local clipping to see which parts need invalidation
IntRect oldVisibleBounds(newVisibleBounds); IntRect oldVisibleBounds(newVisibleBounds);
oldVisibleBounds.OffsetBy(-x, -y); oldVisibleBounds.OffsetBy(-x, -y);
ConvertToScreen(&oldVisibleBounds); LocalToScreenTransform().Apply(&oldVisibleBounds);
ConvertToVisibleInTopView(&newVisibleBounds); ConvertToVisibleInTopView(&newVisibleBounds);
@@ -788,7 +622,7 @@ View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
IntRect oldVisibleBounds(Bounds()); IntRect oldVisibleBounds(Bounds());
IntRect newVisibleBounds(oldVisibleBounds); IntRect newVisibleBounds(oldVisibleBounds);
oldVisibleBounds.OffsetBy(-x, -y); oldVisibleBounds.OffsetBy(-x, -y);
ConvertToScreen(&oldVisibleBounds); LocalToScreenTransform().Apply(&oldVisibleBounds);
// NOTE: using ConvertToVisibleInTopView() // NOTE: using ConvertToVisibleInTopView()
// instead of ConvertToScreen()! see below // instead of ConvertToScreen()! see below
@@ -875,7 +709,7 @@ View::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
} }
} }
ConvertToScreen(dirty); LocalToScreenTransform().Apply(dirty);
dirtyRegion->Include(dirty); dirtyRegion->Include(dirty);
} }
fWindow->RecycleRegion(dirty); fWindow->RecycleRegion(dirty);
@@ -1171,7 +1005,7 @@ View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
// draw view bitmap // draw view bitmap
// TODO: support other options! // TODO: support other options!
BRect rect = fBitmapDestination; BRect rect = fBitmapDestination;
ConvertToScreenForDrawing(&rect); PenToScreenTransform().Apply(&rect);
align_rect_to_pixels(&rect); align_rect_to_pixels(&rect);
@@ -1406,7 +1240,7 @@ View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region,
// This check will prevent descending the view hierarchy // This check will prevent descending the view hierarchy
// any further than necessary // any further than necessary
IntRect screenBounds(Bounds()); IntRect screenBounds(Bounds());
ConvertToScreen(&screenBounds); LocalToScreenTransform().Apply(&screenBounds);
if (!region.Intersects((clipping_rect)screenBounds)) if (!region.Intersects((clipping_rect)screenBounds))
return; return;
@@ -1537,7 +1371,7 @@ View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const
if (fScreenAndUserClipping == NULL) if (fScreenAndUserClipping == NULL)
return fScreenClipping; return fScreenClipping;
ConvertToScreen(fScreenAndUserClipping); LocalToScreenTransform().Apply(fScreenAndUserClipping);
fScreenAndUserClipping->IntersectWith( fScreenAndUserClipping->IntersectWith(
&_ScreenClipping(windowContentClipping, force)); &_ScreenClipping(windowContentClipping, force));
return *fScreenAndUserClipping; return *fScreenAndUserClipping;
@@ -1578,7 +1412,7 @@ View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
{ {
if (!fScreenClippingValid || force) { if (!fScreenClippingValid || force) {
fScreenClipping = fLocalClipping; fScreenClipping = fLocalClipping;
ConvertToScreen(&fScreenClipping); LocalToScreenTransform().Apply(&fScreenClipping);
// see if parts of our bounds are hidden underneath // see if parts of our bounds are hidden underneath
// the parent, the local clipping does not account for this // the parent, the local clipping does not account for this
+6 -25
View File
@@ -111,31 +111,7 @@ public:
View* ViewAt(const BPoint& where); View* ViewAt(const BPoint& where);
// coordinate conversion public:
void ConvertToParent(BPoint* point) const;
void ConvertToParent(IntPoint* point) const;
void ConvertToParent(BRect* rect) const;
void ConvertToParent(IntRect* rect) const;
void ConvertToParent(BRegion* region) const;
void ConvertFromParent(BPoint* point) const;
void ConvertFromParent(IntPoint* point) const;
void ConvertFromParent(BRect* rect) const;
void ConvertFromParent(IntRect* rect) const;
void ConvertFromParent(BRegion* region) const;
void ConvertToScreen(BPoint* point) const;
void ConvertToScreen(IntPoint* point) const;
void ConvertToScreen(BRect* rect) const;
void ConvertToScreen(IntRect* rect) const;
void ConvertToScreen(BRegion* region) const;
void ConvertFromScreen(BPoint* point) const;
void ConvertFromScreen(IntPoint* point) const;
void ConvertFromScreen(BRect* rect) const;
void ConvertFromScreen(IntRect* rect) const;
void ConvertFromScreen(BRegion* region) const;
void MoveBy(int32 dx, int32 dy, void MoveBy(int32 dx, int32 dy,
BRegion* dirtyRegion); BRegion* dirtyRegion);
@@ -235,6 +211,11 @@ public:
#endif #endif
protected: protected:
virtual void _LocalToScreenTransform(
SimpleTransform& transform) const;
virtual void _ScreenToLocalTransform(
SimpleTransform& transform) const;
BRegion& _ScreenClipping(BRegion* windowContentClipping, BRegion& _ScreenClipping(BRegion* windowContentClipping,
bool force = false) const; bool force = false) const;
void _MoveScreenClipping(int32 x, int32 y, void _MoveScreenClipping(int32 x, int32 y,
+1 -1
View File
@@ -817,7 +817,7 @@ Window::InvalidateView(View* view, BRegion& viewRegion)
if (!fContentRegionValid) if (!fContentRegionValid)
_UpdateContentRegion(); _UpdateContentRegion();
view->ConvertToScreen(&viewRegion); view->LocalToScreenTransform().Apply(&viewRegion);
viewRegion.IntersectWith(&VisibleContentRegion()); viewRegion.IntersectWith(&VisibleContentRegion());
if (viewRegion.CountRects() > 0) { if (viewRegion.CountRects() > 0) {
viewRegion.IntersectWith( viewRegion.IntersectWith(
+3 -3
View File
@@ -90,7 +90,7 @@ WorkspacesView::_WorkspaceAt(int32 i)
_GetGrid(columns, rows); _GetGrid(columns, rows);
BRect frame = Bounds(); BRect frame = Bounds();
ConvertToScreen(&frame); LocalToScreenTransform().Apply(&frame);
int32 width = frame.IntegerWidth() / columns; int32 width = frame.IntegerWidth() / columns;
int32 height = frame.IntegerHeight() / rows; int32 height = frame.IntegerHeight() / rows;
@@ -356,7 +356,7 @@ void
WorkspacesView::_Invalidate() const WorkspacesView::_Invalidate() const
{ {
BRect frame = Bounds(); BRect frame = Bounds();
ConvertToScreen(&frame); LocalToScreenTransform().Apply(&frame);
BRegion region(frame); BRegion region(frame);
Window()->MarkContentDirty(region); Window()->MarkContentDirty(region);
@@ -385,7 +385,7 @@ WorkspacesView::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
drawingEngine->ConstrainClippingRegion(&gridRegion); drawingEngine->ConstrainClippingRegion(&gridRegion);
BRect frame = Bounds(); BRect frame = Bounds();
ConvertToScreen(&frame); LocalToScreenTransform().Apply(&frame);
// horizontal lines // horizontal lines