app_server: Fix computing bounding boxes for transformed stuff.
* In DrawingEngine, clipping is computed before drawing happens. This did not take into account when drawing primitives can now be transformed. Fixes drawing glitches in the Transformation test when the round rect is scrolled into view and it was previously prevented to draw. * Fixed clipping rect computation for the sanitized StrokeRoundRect() implementation which centers the stroke on the rect.
This commit is contained in:
@@ -583,6 +583,7 @@ DrawingEngine::InvertRect(BRect r)
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
make_rect_valid(r);
|
||||
// NOTE: Currently ignores view transformation, so no TransformAndClipRect()
|
||||
r = fPainter->ClipRect(r);
|
||||
if (!r.IsValid())
|
||||
return;
|
||||
@@ -608,7 +609,7 @@ DrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& bitmapRect,
|
||||
{
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
BRect clipped = fPainter->ClipRect(viewRect);
|
||||
BRect clipped = fPainter->TransformAndClipRect(viewRect);
|
||||
if (clipped.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
|
||||
|
||||
@@ -632,7 +633,7 @@ DrawingEngine::DrawArc(BRect r, const float& angle, const float& span,
|
||||
if (!filled)
|
||||
extend_by_stroke_width(clipped, fPainter->PenSize());
|
||||
|
||||
clipped = fPainter->ClipRect(r);
|
||||
clipped = fPainter->TransformAndClipRect(r);
|
||||
|
||||
if (clipped.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
|
||||
@@ -662,7 +663,7 @@ DrawingEngine::FillArc(BRect r, const float& angle, const float& span,
|
||||
fPainter->AlignEllipseRect(&r, true);
|
||||
BRect clipped(r);
|
||||
|
||||
clipped = fPainter->ClipRect(r);
|
||||
clipped = fPainter->TransformAndClipRect(r);
|
||||
|
||||
if (clipped.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
|
||||
@@ -724,7 +725,7 @@ DrawingEngine::DrawEllipse(BRect r, bool filled)
|
||||
clipped.right = ceilf(clipped.right);
|
||||
clipped.bottom = ceilf(clipped.bottom);
|
||||
|
||||
clipped = fPainter->ClipRect(clipped);
|
||||
clipped = fPainter->TransformAndClipRect(clipped);
|
||||
|
||||
if (clipped.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
|
||||
@@ -750,7 +751,7 @@ DrawingEngine::FillEllipse(BRect r, const BGradient& gradient)
|
||||
clipped.right = ceilf(clipped.right);
|
||||
clipped.bottom = ceilf(clipped.bottom);
|
||||
|
||||
clipped = fPainter->ClipRect(clipped);
|
||||
clipped = fPainter->TransformAndClipRect(clipped);
|
||||
|
||||
if (clipped.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
|
||||
@@ -771,7 +772,7 @@ DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds,
|
||||
make_rect_valid(bounds);
|
||||
if (!filled)
|
||||
extend_by_stroke_width(bounds, fPainter->PenSize());
|
||||
bounds = fPainter->ClipRect(bounds);
|
||||
bounds = fPainter->TransformAndClipRect(bounds);
|
||||
if (bounds.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, bounds);
|
||||
|
||||
@@ -789,7 +790,7 @@ DrawingEngine::FillPolygon(BPoint* ptlist, int32 numpts, BRect bounds,
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
make_rect_valid(bounds);
|
||||
bounds = fPainter->ClipRect(bounds);
|
||||
bounds = fPainter->TransformAndClipRect(bounds);
|
||||
if (bounds.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, bounds);
|
||||
|
||||
@@ -938,7 +939,7 @@ DrawingEngine::StrokeRect(BRect r)
|
||||
make_rect_valid(r);
|
||||
BRect clipped(r);
|
||||
extend_by_stroke_width(clipped, fPainter->PenSize());
|
||||
clipped = fPainter->ClipRect(clipped);
|
||||
clipped = fPainter->TransformAndClipRect(clipped);
|
||||
if (clipped.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
|
||||
|
||||
@@ -955,7 +956,7 @@ DrawingEngine::FillRect(BRect r)
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
make_rect_valid(r);
|
||||
r = fPainter->AlignAndClipRect(r);
|
||||
r = fPainter->TransformAlignAndClipRect(r);
|
||||
if (!r.IsValid())
|
||||
return;
|
||||
|
||||
@@ -1007,7 +1008,7 @@ DrawingEngine::FillRect(BRect r, const BGradient& gradient)
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
make_rect_valid(r);
|
||||
r = fPainter->AlignAndClipRect(r);
|
||||
r = fPainter->TransformAlignAndClipRect(r);
|
||||
if (!r.IsValid())
|
||||
return;
|
||||
|
||||
@@ -1024,7 +1025,7 @@ DrawingEngine::FillRegion(BRegion& r)
|
||||
{
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
BRect clipped = fPainter->ClipRect(r.Frame());
|
||||
BRect clipped = fPainter->TransformAndClipRect(r.Frame());
|
||||
if (!clipped.IsValid())
|
||||
return;
|
||||
|
||||
@@ -1095,10 +1096,10 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, bool filled)
|
||||
{
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
// NOTE: the stroke does not extend past "r" in R5,
|
||||
// though I consider this unexpected behaviour.
|
||||
make_rect_valid(r);
|
||||
BRect clipped = fPainter->ClipRect(r);
|
||||
if (!filled)
|
||||
extend_by_stroke_width(r, fPainter->PenSize());
|
||||
BRect clipped = fPainter->TransformAndClipRect(r);
|
||||
|
||||
clipped.left = floorf(clipped.left);
|
||||
clipped.top = floorf(clipped.top);
|
||||
@@ -1122,10 +1123,8 @@ DrawingEngine::FillRoundRect(BRect r, float xrad, float yrad,
|
||||
{
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
// NOTE: the stroke does not extend past "r" in R5,
|
||||
// though I consider this unexpected behaviour.
|
||||
make_rect_valid(r);
|
||||
BRect clipped = fPainter->ClipRect(r);
|
||||
BRect clipped = fPainter->TransformAndClipRect(r);
|
||||
|
||||
clipped.left = floorf(clipped.left);
|
||||
clipped.top = floorf(clipped.top);
|
||||
@@ -1210,7 +1209,7 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, bool filled)
|
||||
BRect clipped(bounds);
|
||||
if (!filled)
|
||||
extend_by_stroke_width(clipped, fPainter->PenSize());
|
||||
clipped = fPainter->ClipRect(clipped);
|
||||
clipped = fPainter->TransformAndClipRect(clipped);
|
||||
if (clipped.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
|
||||
|
||||
@@ -1231,7 +1230,7 @@ DrawingEngine::FillTriangle(BPoint* pts, const BRect& bounds,
|
||||
ASSERT_PARALLEL_LOCKED();
|
||||
|
||||
BRect clipped(bounds);
|
||||
clipped = fPainter->ClipRect(clipped);
|
||||
clipped = fPainter->TransformAndClipRect(clipped);
|
||||
if (clipped.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
|
||||
|
||||
@@ -1250,7 +1249,7 @@ DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end)
|
||||
BRect touched(start, end);
|
||||
make_rect_valid(touched);
|
||||
extend_by_stroke_width(touched, fPainter->PenSize());
|
||||
touched = fPainter->ClipRect(touched);
|
||||
touched = fPainter->TransformAndClipRect(touched);
|
||||
if (touched.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, touched);
|
||||
|
||||
@@ -1286,7 +1285,7 @@ DrawingEngine::StrokeLineArray(int32 numLines,
|
||||
touched = touched | box;
|
||||
}
|
||||
extend_by_stroke_width(touched, fPainter->PenSize());
|
||||
touched = fPainter->ClipRect(touched);
|
||||
touched = fPainter->TransformAndClipRect(touched);
|
||||
if (touched.IsValid()) {
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, touched);
|
||||
|
||||
@@ -1328,7 +1327,8 @@ DrawingEngine::DrawString(const char* string, int32 length,
|
||||
BPoint penLocation = pt;
|
||||
|
||||
// try a fast clipping path
|
||||
if (fPainter->ClippingRegion() && fPainter->Font().Rotation() == 0.0f) {
|
||||
if (fPainter->ClippingRegion() && fPainter->Font().Rotation() == 0.0f
|
||||
&& fPainter->IsIdentityTransform()) {
|
||||
float fontSize = fPainter->Font().Size();
|
||||
BRect clippingFrame = fPainter->ClippingRegion()->Frame();
|
||||
if (pt.x - fontSize > clippingFrame.right
|
||||
@@ -1354,7 +1354,7 @@ DrawingEngine::DrawString(const char* string, int32 length,
|
||||
BRect b = fPainter->BoundingBox(string, length, pt, &penLocation, delta,
|
||||
&cacheReference);
|
||||
// stop here if we're supposed to render outside of the clipping
|
||||
b = fPainter->ClipRect(b);
|
||||
b = fPainter->TransformAndClipRect(b);
|
||||
if (b.IsValid()) {
|
||||
//printf("bounding box '%s': %lld µs\n", string, system_time() - now);
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, b);
|
||||
@@ -1385,7 +1385,7 @@ DrawingEngine::DrawString(const char* string, int32 length,
|
||||
BRect b = fPainter->BoundingBox(string, length, offsets, &penLocation,
|
||||
&cacheReference);
|
||||
// stop here if we're supposed to render outside of the clipping
|
||||
b = fPainter->ClipRect(b);
|
||||
b = fPainter->TransformAndClipRect(b);
|
||||
if (b.IsValid()) {
|
||||
//printf("bounding box '%s': %lld µs\n", string, system_time() - now);
|
||||
AutoFloatingOverlaysHider _(fGraphicsCard, b);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "FontManager.h"
|
||||
#include "PatternHandler.h"
|
||||
#include "ServerFont.h"
|
||||
#include "Transformable.h"
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
@@ -39,7 +40,6 @@ class FontCacheReference;
|
||||
class RenderingBuffer;
|
||||
class ServerBitmap;
|
||||
class ServerFont;
|
||||
class Transformable;
|
||||
|
||||
|
||||
class Painter {
|
||||
@@ -65,6 +65,9 @@ public:
|
||||
int32 xOffset = 0,
|
||||
int32 yOffset = 0);
|
||||
|
||||
inline bool IsIdentityTransform() const
|
||||
{ return fIdentityTransform; }
|
||||
|
||||
void SetHighColor(const rgb_color& color);
|
||||
inline rgb_color HighColor() const
|
||||
{ return fPatternHandler.HighColor(); }
|
||||
@@ -233,7 +236,9 @@ public:
|
||||
|
||||
BRect InvertRect(const BRect& r) const;
|
||||
|
||||
inline BRect TransformAndClipRect(BRect rect) const;
|
||||
inline BRect ClipRect(BRect rect) const;
|
||||
inline BRect TransformAlignAndClipRect(BRect rect) const;
|
||||
inline BRect AlignAndClipRect(BRect rect) const;
|
||||
|
||||
|
||||
@@ -367,7 +372,7 @@ private:
|
||||
bool fAttached : 1;
|
||||
bool fIdentityTransform : 1;
|
||||
|
||||
agg::trans_affine fTransform;
|
||||
Transformable fTransform;
|
||||
float fPenSize;
|
||||
const BRegion* fClippingRegion;
|
||||
drawing_mode fDrawingMode;
|
||||
@@ -386,6 +391,21 @@ private:
|
||||
};
|
||||
|
||||
|
||||
inline BRect
|
||||
Painter::TransformAndClipRect(BRect rect) const
|
||||
{
|
||||
rect.left = floorf(rect.left);
|
||||
rect.top = floorf(rect.top);
|
||||
rect.right = ceilf(rect.right);
|
||||
rect.bottom = ceilf(rect.bottom);
|
||||
|
||||
if (!fIdentityTransform)
|
||||
rect = fTransform.TransformBounds(rect);
|
||||
|
||||
return _Clipped(rect);
|
||||
}
|
||||
|
||||
|
||||
inline BRect
|
||||
Painter::ClipRect(BRect rect) const
|
||||
{
|
||||
@@ -413,4 +433,22 @@ Painter::AlignAndClipRect(BRect rect) const
|
||||
}
|
||||
|
||||
|
||||
inline BRect
|
||||
Painter::TransformAlignAndClipRect(BRect rect) const
|
||||
{
|
||||
rect.left = floorf(rect.left);
|
||||
rect.top = floorf(rect.top);
|
||||
if (fSubpixelPrecise) {
|
||||
rect.right = ceilf(rect.right);
|
||||
rect.bottom = ceilf(rect.bottom);
|
||||
} else {
|
||||
rect.right = floorf(rect.right);
|
||||
rect.bottom = floorf(rect.bottom);
|
||||
}
|
||||
if (!fIdentityTransform)
|
||||
rect = fTransform.TransformBounds(rect);
|
||||
return _Clipped(rect);
|
||||
}
|
||||
|
||||
|
||||
#endif // PAINTER_H
|
||||
|
||||
Reference in New Issue
Block a user