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