From 6f2a446e2eb8362b92dd6c12c8ed7274d110a9b1 Mon Sep 17 00:00:00 2001 From: Julian Harnath Date: Mon, 6 Apr 2015 14:43:24 +0200 Subject: [PATCH] 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. --- src/servers/app/Canvas.cpp | 205 +++++------------------- src/servers/app/Canvas.h | 46 ++---- src/servers/app/DrawState.cpp | 90 ++--------- src/servers/app/DrawState.h | 14 +- src/servers/app/ServerPicture.cpp | 47 +++--- src/servers/app/ServerWindow.cpp | 130 +++++++++------ src/servers/app/SimpleTransform.h | 243 +++++++++++++++++++++++++++++ src/servers/app/View.cpp | 230 ++++----------------------- src/servers/app/View.h | 31 +--- src/servers/app/Window.cpp | 2 +- src/servers/app/WorkspacesView.cpp | 6 +- 11 files changed, 462 insertions(+), 582 deletions(-) create mode 100644 src/servers/app/SimpleTransform.h diff --git a/src/servers/app/Canvas.cpp b/src/servers/app/Canvas.cpp index 715c6a1f05..4fd87a0322 100644 --- a/src/servers/app/Canvas.cpp +++ b/src/servers/app/Canvas.cpp @@ -17,17 +17,22 @@ #include -#include -#include -#include -#include -#include #include #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 +SimpleTransform +Canvas::LocalToScreenTransform() const GCC_2_NRV(transform) { - fDrawState->Transform(point); - // NOTE: from here on, don't use the - // "*ForDrawing()" versions of the parent! - ConvertToScreen(point); +#if __GNUC__ >= 3 + SimpleTransform transform; +#endif + _LocalToScreenTransform(transform); + return transform; } -//! converts a rect from local *drawing* to screen coordinate system -void -Canvas::ConvertToScreenForDrawing(BRect* rect) const +SimpleTransform +Canvas::ScreenToLocalTransform() const GCC_2_NRV(transform) { - fDrawState->Transform(rect); - // NOTE: from here on, don't use the - // "*ForDrawing()" versions of the parent! - ConvertToScreen(rect); +#if __GNUC__ >= 3 + SimpleTransform transform; +#endif + _ScreenToLocalTransform(transform); + return transform; } -//! converts a region from local *drawing* to screen coordinate system -void -Canvas::ConvertToScreenForDrawing(BRegion* region) const +SimpleTransform +Canvas::PenToScreenTransform() const GCC_2_NRV(transform) { - fDrawState->Transform(region); - // NOTE: from here on, don't use the - // "*ForDrawing()" versions of the parent! - ConvertToScreen(region); +#if __GNUC__ >= 3 + SimpleTransform transform; +#endif + fDrawState->Transform(transform); + _LocalToScreenTransform(transform); + return transform; } -//! converts a gradient from local *drawing* to screen coordinate system -void -Canvas::ConvertToScreenForDrawing(BGradient* gradient) const +SimpleTransform +Canvas::ScreenToPenTransform() 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(¢er); - ConvertToScreen(¢er); - radial->SetCenter(center); - break; - } - case BGradient::TYPE_RADIAL_FOCUS: - { - BGradientRadialFocus* radialFocus = (BGradientRadialFocus*) gradient; - BPoint center = radialFocus->Center(); - BPoint focal = radialFocus->Focal(); - fDrawState->Transform(¢er); - ConvertToScreen(¢er); - 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(¢er); - ConvertToScreen(¢er); - diamond->SetCenter(center); - break; - } - case BGradient::TYPE_CONIC: - { - BGradientConic* conic = (BGradientConic*) gradient; - BPoint center = conic->Center(); - fDrawState->Transform(¢er); - ConvertToScreen(¢er); - 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); +#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 c8efc4c612..acb52d09e5 100644 --- a/src/servers/app/Canvas.h +++ b/src/servers/app/Canvas.h @@ -17,6 +17,8 @@ #include +#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; @@ -78,6 +65,12 @@ public: virtual void ResyncDrawState() {}; 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 23c358fe6e..d7f88bc922 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 * Axel Dörfler, axeld@pinc-software.de * Michael Pfeiffer + * Julian Harnath */ //! Data classes for working with BView states and draw parameters @@ -211,7 +212,7 @@ DrawState::ReadFromLink(BPrivate::LinkReceiver& link) ViewSetStateInfo info; link.Read(&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 +DrawState::Transform(SimpleTransform& transform) const { - // scale relative to origin, therefore - // scale first then translate to - // origin - *x *= fCombinedScale; - *y *= fCombinedScale; - *x += fCombinedOrigin.x; - *y += fCombinedOrigin.y; + transform.AddOffset(fCombinedOrigin.x, fCombinedOrigin.y); + transform.SetScale(fCombinedScale); } void -DrawState::InverseTransform(float* x, float* y) const +DrawState::InverseTransform(SimpleTransform& transform) const { - *x -= fCombinedOrigin.x; - *y -= fCombinedOrigin.y; - if (fCombinedScale != 0.0) { - *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(<.x, <.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)); + 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 48508ed6cf..392549789f 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 * Stephan Aßmus * Axel Dörfler, axeld@pinc-software.de + * Julian Harnath */ #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 6f09cb0d70..d03ddb29e3 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 242438faf2..81892f939c 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(®ion); + fCurrentView->ScreenToLocalTransform().Apply(®ion); 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(&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(&(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(&(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(&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(&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(&(pts[i])); - fCurrentView->ConvertToScreenForDrawing(&pts[i]); + transform.Apply(&pts[i]); } if (link.Read(&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(&(pts[i])); - fCurrentView->ConvertToScreenForDrawing(&pts[i]); + transform.Apply(&pts[i]); } link.Read(&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(&isClosed); link.Read(&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(&polyFrame); link.Read(&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(®ion) < B_OK) break; - fCurrentView->ConvertToScreenForDrawing(®ion); + fCurrentView->PenToScreenTransform().Apply(®ion); drawingEngine->FillRegion(region); break; @@ -2707,8 +2733,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, if (link.ReadGradient(&gradient) != B_OK) break; - fCurrentView->ConvertToScreenForDrawing(®ion); - fCurrentView->ConvertToScreenForDrawing(gradient); + const SimpleTransform transform = + fCurrentView->PenToScreenTransform(); + transform.Apply(®ion); + 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 0000000000..00c8f458a5 --- /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@pinc-software.de + * Stephan Aßmus + * Adrien Destugues + * Julian Harnath + */ + +#ifndef SIMPLE_TRANSFORM_H +#define SIMPLE_TRANSFORM_H + +#include +#include +#include +#include +#include +#include +#include + +#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(¢er); + radial->SetCenter(center); + break; + } + + case BGradient::TYPE_RADIAL_FOCUS: + { + BGradientRadialFocus* radialFocus = + (BGradientRadialFocus*)gradient; + BPoint center = radialFocus->Center(); + BPoint focal = radialFocus->Focal(); + Apply(¢er); + Apply(&focal); + radialFocus->SetCenter(center); + radialFocus->SetFocal(focal); + break; + } + + case BGradient::TYPE_DIAMOND: + { + BGradientDiamond* diamond = (BGradientDiamond*) gradient; + BPoint center = diamond->Center(); + Apply(¢er); + diamond->SetCenter(center); + break; + } + + case BGradient::TYPE_CONIC: + { + BGradientConic* conic = (BGradientConic*) gradient; + BPoint center = conic->Center(); + Apply(¢er); + 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 diff --git a/src/servers/app/View.cpp b/src/servers/app/View.cpp index 7831b45cfb..b1375327a3 100644 --- a/src/servers/app/View.cpp +++ b/src/servers/app/View.cpp @@ -165,7 +165,8 @@ View::ConvertToVisibleInTopView(IntRect* bounds) const { *bounds = *bounds & Bounds(); // 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) fParent->ConvertToVisibleInTopView(bounds); @@ -440,7 +441,7 @@ View::ViewAt(const BPoint& where) IntRect frame = Frame(); if (Parent() != NULL) - Parent()->ConvertToScreen(&frame); + Parent()->LocalToScreenTransform().Apply(&frame); if (!frame.Contains(where)) return NULL; @@ -524,7 +525,7 @@ View::_UpdateOverlayView() const return; IntRect destination = fBitmapDestination; - ConvertToScreen(&destination); + LocalToScreenTransform().Apply(&destination); overlay->Configure(fBitmapSource, destination); } @@ -556,201 +557,34 @@ View::UpdateOverlay() void -View::ConvertToParent(BPoint* point) const +View::_LocalToScreenTransform(SimpleTransform& transform) const { - // remove scrolling offset and convert to parent coordinate space - point->x += fFrame.left - fScrollingOffset.x; - point->y += fFrame.top - fScrollingOffset.y; + const View* view = this; + int32 offsetX = 0; + 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 -View::ConvertToParent(IntPoint* point) const +View::_ScreenToLocalTransform(SimpleTransform& transform) const { - // remove scrolling offset and convert to parent coordinate space - point->x += fFrame.left - fScrollingOffset.x; - point->y += fFrame.top - fScrollingOffset.y; -} + const View* view = this; + int32 offsetX = 0; + int32 offsetY = 0; + do { + offsetX += view->fScrollingOffset.x - view->fFrame.left; + offsetY += view->fScrollingOffset.y - view->fFrame.top; + view = view->fParent; + } while (view != NULL); - -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); + transform.AddOffset(offsetX, offsetY); } @@ -775,7 +609,7 @@ View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion) // local clipping to see which parts need invalidation IntRect oldVisibleBounds(newVisibleBounds); oldVisibleBounds.OffsetBy(-x, -y); - ConvertToScreen(&oldVisibleBounds); + LocalToScreenTransform().Apply(&oldVisibleBounds); ConvertToVisibleInTopView(&newVisibleBounds); @@ -788,7 +622,7 @@ View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion) IntRect oldVisibleBounds(Bounds()); IntRect newVisibleBounds(oldVisibleBounds); oldVisibleBounds.OffsetBy(-x, -y); - ConvertToScreen(&oldVisibleBounds); + LocalToScreenTransform().Apply(&oldVisibleBounds); // NOTE: using ConvertToVisibleInTopView() // 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); } fWindow->RecycleRegion(dirty); @@ -1171,7 +1005,7 @@ View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, // draw view bitmap // TODO: support other options! BRect rect = fBitmapDestination; - ConvertToScreenForDrawing(&rect); + PenToScreenTransform().Apply(&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 // any further than necessary IntRect screenBounds(Bounds()); - ConvertToScreen(&screenBounds); + LocalToScreenTransform().Apply(&screenBounds); if (!region.Intersects((clipping_rect)screenBounds)) return; @@ -1537,7 +1371,7 @@ View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const if (fScreenAndUserClipping == NULL) return fScreenClipping; - ConvertToScreen(fScreenAndUserClipping); + LocalToScreenTransform().Apply(fScreenAndUserClipping); fScreenAndUserClipping->IntersectWith( &_ScreenClipping(windowContentClipping, force)); return *fScreenAndUserClipping; @@ -1578,7 +1412,7 @@ View::_ScreenClipping(BRegion* windowContentClipping, bool force) const { if (!fScreenClippingValid || force) { fScreenClipping = fLocalClipping; - ConvertToScreen(&fScreenClipping); + LocalToScreenTransform().Apply(&fScreenClipping); // see if parts of our bounds are hidden underneath // the parent, the local clipping does not account for this diff --git a/src/servers/app/View.h b/src/servers/app/View.h index 7bdc31a78d..5550fcb961 100644 --- a/src/servers/app/View.h +++ b/src/servers/app/View.h @@ -111,31 +111,7 @@ public: View* ViewAt(const BPoint& where); - // coordinate conversion - 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; - +public: void MoveBy(int32 dx, int32 dy, BRegion* dirtyRegion); @@ -235,6 +211,11 @@ public: #endif protected: + virtual void _LocalToScreenTransform( + SimpleTransform& transform) const; + virtual void _ScreenToLocalTransform( + SimpleTransform& transform) const; + BRegion& _ScreenClipping(BRegion* windowContentClipping, bool force = false) const; void _MoveScreenClipping(int32 x, int32 y, diff --git a/src/servers/app/Window.cpp b/src/servers/app/Window.cpp index 117e67a564..8af42bd2bd 100644 --- a/src/servers/app/Window.cpp +++ b/src/servers/app/Window.cpp @@ -817,7 +817,7 @@ Window::InvalidateView(View* view, BRegion& viewRegion) if (!fContentRegionValid) _UpdateContentRegion(); - view->ConvertToScreen(&viewRegion); + view->LocalToScreenTransform().Apply(&viewRegion); viewRegion.IntersectWith(&VisibleContentRegion()); if (viewRegion.CountRects() > 0) { viewRegion.IntersectWith( diff --git a/src/servers/app/WorkspacesView.cpp b/src/servers/app/WorkspacesView.cpp index be53497cec..2e4aabac75 100644 --- a/src/servers/app/WorkspacesView.cpp +++ b/src/servers/app/WorkspacesView.cpp @@ -90,7 +90,7 @@ WorkspacesView::_WorkspaceAt(int32 i) _GetGrid(columns, rows); BRect frame = Bounds(); - ConvertToScreen(&frame); + LocalToScreenTransform().Apply(&frame); int32 width = frame.IntegerWidth() / columns; int32 height = frame.IntegerHeight() / rows; @@ -356,7 +356,7 @@ void WorkspacesView::_Invalidate() const { BRect frame = Bounds(); - ConvertToScreen(&frame); + LocalToScreenTransform().Apply(&frame); BRegion region(frame); Window()->MarkContentDirty(region); @@ -385,7 +385,7 @@ WorkspacesView::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, drawingEngine->ConstrainClippingRegion(&gridRegion); BRect frame = Bounds(); - ConvertToScreen(&frame); + LocalToScreenTransform().Apply(&frame); // horizontal lines