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