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:
Stephan Aßmus
2014-02-08 11:39:26 +01:00
parent 13e393dfc1
commit 89f8b7a12d
2 changed files with 64 additions and 26 deletions
+24 -24
View File
@@ -583,6 +583,7 @@ DrawingEngine::InvertRect(BRect r)
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
make_rect_valid(r); make_rect_valid(r);
// NOTE: Currently ignores view transformation, so no TransformAndClipRect()
r = fPainter->ClipRect(r); r = fPainter->ClipRect(r);
if (!r.IsValid()) if (!r.IsValid())
return; return;
@@ -608,7 +609,7 @@ DrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& bitmapRect,
{ {
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
BRect clipped = fPainter->ClipRect(viewRect); BRect clipped = fPainter->TransformAndClipRect(viewRect);
if (clipped.IsValid()) { if (clipped.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, clipped); AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -632,7 +633,7 @@ DrawingEngine::DrawArc(BRect r, const float& angle, const float& span,
if (!filled) if (!filled)
extend_by_stroke_width(clipped, fPainter->PenSize()); extend_by_stroke_width(clipped, fPainter->PenSize());
clipped = fPainter->ClipRect(r); clipped = fPainter->TransformAndClipRect(r);
if (clipped.IsValid()) { if (clipped.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, clipped); AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -662,7 +663,7 @@ DrawingEngine::FillArc(BRect r, const float& angle, const float& span,
fPainter->AlignEllipseRect(&r, true); fPainter->AlignEllipseRect(&r, true);
BRect clipped(r); BRect clipped(r);
clipped = fPainter->ClipRect(r); clipped = fPainter->TransformAndClipRect(r);
if (clipped.IsValid()) { if (clipped.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, clipped); AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -724,7 +725,7 @@ DrawingEngine::DrawEllipse(BRect r, bool filled)
clipped.right = ceilf(clipped.right); clipped.right = ceilf(clipped.right);
clipped.bottom = ceilf(clipped.bottom); clipped.bottom = ceilf(clipped.bottom);
clipped = fPainter->ClipRect(clipped); clipped = fPainter->TransformAndClipRect(clipped);
if (clipped.IsValid()) { if (clipped.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, clipped); AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -750,7 +751,7 @@ DrawingEngine::FillEllipse(BRect r, const BGradient& gradient)
clipped.right = ceilf(clipped.right); clipped.right = ceilf(clipped.right);
clipped.bottom = ceilf(clipped.bottom); clipped.bottom = ceilf(clipped.bottom);
clipped = fPainter->ClipRect(clipped); clipped = fPainter->TransformAndClipRect(clipped);
if (clipped.IsValid()) { if (clipped.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, clipped); AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -771,7 +772,7 @@ DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds,
make_rect_valid(bounds); make_rect_valid(bounds);
if (!filled) if (!filled)
extend_by_stroke_width(bounds, fPainter->PenSize()); extend_by_stroke_width(bounds, fPainter->PenSize());
bounds = fPainter->ClipRect(bounds); bounds = fPainter->TransformAndClipRect(bounds);
if (bounds.IsValid()) { if (bounds.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, bounds); AutoFloatingOverlaysHider _(fGraphicsCard, bounds);
@@ -789,7 +790,7 @@ DrawingEngine::FillPolygon(BPoint* ptlist, int32 numpts, BRect bounds,
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
make_rect_valid(bounds); make_rect_valid(bounds);
bounds = fPainter->ClipRect(bounds); bounds = fPainter->TransformAndClipRect(bounds);
if (bounds.IsValid()) { if (bounds.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, bounds); AutoFloatingOverlaysHider _(fGraphicsCard, bounds);
@@ -938,7 +939,7 @@ DrawingEngine::StrokeRect(BRect r)
make_rect_valid(r); make_rect_valid(r);
BRect clipped(r); BRect clipped(r);
extend_by_stroke_width(clipped, fPainter->PenSize()); extend_by_stroke_width(clipped, fPainter->PenSize());
clipped = fPainter->ClipRect(clipped); clipped = fPainter->TransformAndClipRect(clipped);
if (clipped.IsValid()) { if (clipped.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, clipped); AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -955,7 +956,7 @@ DrawingEngine::FillRect(BRect r)
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
make_rect_valid(r); make_rect_valid(r);
r = fPainter->AlignAndClipRect(r); r = fPainter->TransformAlignAndClipRect(r);
if (!r.IsValid()) if (!r.IsValid())
return; return;
@@ -1007,7 +1008,7 @@ DrawingEngine::FillRect(BRect r, const BGradient& gradient)
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
make_rect_valid(r); make_rect_valid(r);
r = fPainter->AlignAndClipRect(r); r = fPainter->TransformAlignAndClipRect(r);
if (!r.IsValid()) if (!r.IsValid())
return; return;
@@ -1024,7 +1025,7 @@ DrawingEngine::FillRegion(BRegion& r)
{ {
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
BRect clipped = fPainter->ClipRect(r.Frame()); BRect clipped = fPainter->TransformAndClipRect(r.Frame());
if (!clipped.IsValid()) if (!clipped.IsValid())
return; return;
@@ -1095,10 +1096,10 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, bool filled)
{ {
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
// NOTE: the stroke does not extend past "r" in R5,
// though I consider this unexpected behaviour.
make_rect_valid(r); 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.left = floorf(clipped.left);
clipped.top = floorf(clipped.top); clipped.top = floorf(clipped.top);
@@ -1122,10 +1123,8 @@ DrawingEngine::FillRoundRect(BRect r, float xrad, float yrad,
{ {
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
// NOTE: the stroke does not extend past "r" in R5,
// though I consider this unexpected behaviour.
make_rect_valid(r); make_rect_valid(r);
BRect clipped = fPainter->ClipRect(r); BRect clipped = fPainter->TransformAndClipRect(r);
clipped.left = floorf(clipped.left); clipped.left = floorf(clipped.left);
clipped.top = floorf(clipped.top); clipped.top = floorf(clipped.top);
@@ -1210,7 +1209,7 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, bool filled)
BRect clipped(bounds); BRect clipped(bounds);
if (!filled) if (!filled)
extend_by_stroke_width(clipped, fPainter->PenSize()); extend_by_stroke_width(clipped, fPainter->PenSize());
clipped = fPainter->ClipRect(clipped); clipped = fPainter->TransformAndClipRect(clipped);
if (clipped.IsValid()) { if (clipped.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, clipped); AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -1231,7 +1230,7 @@ DrawingEngine::FillTriangle(BPoint* pts, const BRect& bounds,
ASSERT_PARALLEL_LOCKED(); ASSERT_PARALLEL_LOCKED();
BRect clipped(bounds); BRect clipped(bounds);
clipped = fPainter->ClipRect(clipped); clipped = fPainter->TransformAndClipRect(clipped);
if (clipped.IsValid()) { if (clipped.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, clipped); AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
@@ -1250,7 +1249,7 @@ DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end)
BRect touched(start, end); BRect touched(start, end);
make_rect_valid(touched); make_rect_valid(touched);
extend_by_stroke_width(touched, fPainter->PenSize()); extend_by_stroke_width(touched, fPainter->PenSize());
touched = fPainter->ClipRect(touched); touched = fPainter->TransformAndClipRect(touched);
if (touched.IsValid()) { if (touched.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, touched); AutoFloatingOverlaysHider _(fGraphicsCard, touched);
@@ -1286,7 +1285,7 @@ DrawingEngine::StrokeLineArray(int32 numLines,
touched = touched | box; touched = touched | box;
} }
extend_by_stroke_width(touched, fPainter->PenSize()); extend_by_stroke_width(touched, fPainter->PenSize());
touched = fPainter->ClipRect(touched); touched = fPainter->TransformAndClipRect(touched);
if (touched.IsValid()) { if (touched.IsValid()) {
AutoFloatingOverlaysHider _(fGraphicsCard, touched); AutoFloatingOverlaysHider _(fGraphicsCard, touched);
@@ -1328,7 +1327,8 @@ DrawingEngine::DrawString(const char* string, int32 length,
BPoint penLocation = pt; BPoint penLocation = pt;
// try a fast clipping path // 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(); float fontSize = fPainter->Font().Size();
BRect clippingFrame = fPainter->ClippingRegion()->Frame(); BRect clippingFrame = fPainter->ClippingRegion()->Frame();
if (pt.x - fontSize > clippingFrame.right 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, BRect b = fPainter->BoundingBox(string, length, pt, &penLocation, delta,
&cacheReference); &cacheReference);
// stop here if we're supposed to render outside of the clipping // stop here if we're supposed to render outside of the clipping
b = fPainter->ClipRect(b); b = fPainter->TransformAndClipRect(b);
if (b.IsValid()) { if (b.IsValid()) {
//printf("bounding box '%s': %lld µs\n", string, system_time() - now); //printf("bounding box '%s': %lld µs\n", string, system_time() - now);
AutoFloatingOverlaysHider _(fGraphicsCard, b); AutoFloatingOverlaysHider _(fGraphicsCard, b);
@@ -1385,7 +1385,7 @@ DrawingEngine::DrawString(const char* string, int32 length,
BRect b = fPainter->BoundingBox(string, length, offsets, &penLocation, BRect b = fPainter->BoundingBox(string, length, offsets, &penLocation,
&cacheReference); &cacheReference);
// stop here if we're supposed to render outside of the clipping // stop here if we're supposed to render outside of the clipping
b = fPainter->ClipRect(b); b = fPainter->TransformAndClipRect(b);
if (b.IsValid()) { if (b.IsValid()) {
//printf("bounding box '%s': %lld µs\n", string, system_time() - now); //printf("bounding box '%s': %lld µs\n", string, system_time() - now);
AutoFloatingOverlaysHider _(fGraphicsCard, b); AutoFloatingOverlaysHider _(fGraphicsCard, b);
+40 -2
View File
@@ -15,6 +15,7 @@
#include "FontManager.h" #include "FontManager.h"
#include "PatternHandler.h" #include "PatternHandler.h"
#include "ServerFont.h" #include "ServerFont.h"
#include "Transformable.h"
#include "defines.h" #include "defines.h"
@@ -39,7 +40,6 @@ class FontCacheReference;
class RenderingBuffer; class RenderingBuffer;
class ServerBitmap; class ServerBitmap;
class ServerFont; class ServerFont;
class Transformable;
class Painter { class Painter {
@@ -65,6 +65,9 @@ public:
int32 xOffset = 0, int32 xOffset = 0,
int32 yOffset = 0); int32 yOffset = 0);
inline bool IsIdentityTransform() const
{ return fIdentityTransform; }
void SetHighColor(const rgb_color& color); void SetHighColor(const rgb_color& color);
inline rgb_color HighColor() const inline rgb_color HighColor() const
{ return fPatternHandler.HighColor(); } { return fPatternHandler.HighColor(); }
@@ -233,7 +236,9 @@ public:
BRect InvertRect(const BRect& r) const; BRect InvertRect(const BRect& r) const;
inline BRect TransformAndClipRect(BRect rect) const;
inline BRect ClipRect(BRect rect) const; inline BRect ClipRect(BRect rect) const;
inline BRect TransformAlignAndClipRect(BRect rect) const;
inline BRect AlignAndClipRect(BRect rect) const; inline BRect AlignAndClipRect(BRect rect) const;
@@ -367,7 +372,7 @@ private:
bool fAttached : 1; bool fAttached : 1;
bool fIdentityTransform : 1; bool fIdentityTransform : 1;
agg::trans_affine fTransform; Transformable fTransform;
float fPenSize; float fPenSize;
const BRegion* fClippingRegion; const BRegion* fClippingRegion;
drawing_mode fDrawingMode; 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 inline BRect
Painter::ClipRect(BRect rect) const 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 #endif // PAINTER_H