hrev46838 adds 2 changesets to branch 'master' old head: b8f01fee6077245ee530dce98dfc7babcdbe413d new head: 89f8b7a12d16a16388e45a4708c033cfb3993df7 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=89f8b7a+%5Eb8f01fe ---------------------------------------------------------------------------- 13e393d: app_server::Transforable: Cleanup * No need to implement operator== and != * Fix operator=() to be efficent, declare agg::trans_affine version, too. 89f8b7a: 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. [ Stephan Aßmus <superstippi@xxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 107 insertions(+), 83 deletions(-) src/servers/app/drawing/DrawingEngine.cpp | 48 +++++----- src/servers/app/drawing/Painter/Painter.h | 42 ++++++++- .../app/drawing/Painter/Transformable.cpp | 95 +++++++++----------- src/servers/app/drawing/Painter/Transformable.h | 5 +- ############################################################################ Commit: 13e393dfc18797b29ea7a07c3b94cadae4b330ee URL: http://cgit.haiku-os.org/haiku/commit/?id=13e393d Author: Stephan Aßmus <superstippi@xxxxxx> Date: Sat Feb 8 10:35:05 2014 UTC app_server::Transforable: Cleanup * No need to implement operator== and != * Fix operator=() to be efficent, declare agg::trans_affine version, too. ---------------------------------------------------------------------------- diff --git a/src/servers/app/drawing/Painter/Transformable.cpp b/src/servers/app/drawing/Painter/Transformable.cpp index 07769d9..ca7eb66 100644 --- a/src/servers/app/drawing/Painter/Transformable.cpp +++ b/src/servers/app/drawing/Painter/Transformable.cpp @@ -13,37 +13,37 @@ #include "Transformable.h" -// min4 + inline float min4(float a, float b, float c, float d) { return min_c(a, min_c(b, min_c(c, d))); } -// max4 + inline float max4(float a, float b, float c, float d) { return max_c(a, max_c(b, max_c(c, d))); } -// constructor + Transformable::Transformable() : agg::trans_affine() { } -// copy constructor + Transformable::Transformable(const Transformable& other) : agg::trans_affine(other) { } -// constructor + Transformable::Transformable(const BMessage* archive) : agg::trans_affine() { - if (archive) { + if (archive != NULL) { double storage[6]; status_t ret = B_OK; for (int32 i = 0; i < 6; i++) { @@ -56,17 +56,17 @@ Transformable::Transformable(const BMessage* archive) } } -// destructor + Transformable::~Transformable() { } -// Archive + status_t Transformable::Archive(BMessage* into, bool deep) const { status_t ret = BArchivable::Archive(into, deep); - if (ret >= B_OK) { + if (ret == B_OK) { double storage[6]; store_to(storage); for (int32 i = 0; i < 6; i++) { @@ -75,24 +75,24 @@ Transformable::Archive(BMessage* into, bool deep) const break; } // finish off - if (ret >= B_OK) + if (ret == B_OK) ret = into->AddString("class", "Transformable"); } return ret; } -// StoreTo + void Transformable::StoreTo(double matrix[6]) const { store_to(matrix); } -// LoadFrom + void Transformable::LoadFrom(double matrix[6]) { - // before calling the potentially heavy TransformationChanged() + // Before calling the potentially heavy TransformationChanged() // hook function, we make sure that it is actually true Transformable t; t.load_from(matrix); @@ -102,7 +102,7 @@ Transformable::LoadFrom(double matrix[6]) } } -// SetTransformable + void Transformable::SetTransformable(const Transformable& other) { @@ -112,19 +112,29 @@ Transformable::SetTransformable(const Transformable& other) } } -// operator= + Transformable& Transformable::operator=(const Transformable& other) { if (other != *this) { - reset(); - multiply(other); + agg::trans_affine::operator=(other); + TransformationChanged(); + } + return *this; +} + + +Transformable& +Transformable::operator=(const agg::trans_affine& other) +{ + if (other != *this) { + agg::trans_affine::operator=(other); TransformationChanged(); } return *this; } -// Multiply + Transformable& Transformable::Multiply(const Transformable& other) { @@ -135,14 +145,14 @@ Transformable::Multiply(const Transformable& other) return *this; } -// Reset + void Transformable::Reset() { reset(); } -// IsIdentity + bool Transformable::IsIdentity() const { @@ -158,39 +168,14 @@ Transformable::IsIdentity() const return false; } -// operator== -bool -Transformable::operator==(const Transformable& other) const -{ - double m1[6]; - other.store_to(m1); - double m2[6]; - store_to(m2); - if (m1[0] == m2[0] && - m1[1] == m2[1] && - m1[2] == m2[2] && - m1[3] == m2[3] && - m1[4] == m2[4] && - m1[5] == m2[5]) - return true; - return false; -} - -// operator!= -bool -Transformable::operator!=(const Transformable& other) const -{ - return !(*this == other); -} -// Transform void Transformable::Transform(double* x, double* y) const { transform(x, y); } -// Transform + void Transformable::Transform(BPoint* point) const { @@ -205,7 +190,7 @@ Transformable::Transform(BPoint* point) const } } -// Transform + BPoint Transformable::Transform(const BPoint& point) const { @@ -214,14 +199,14 @@ Transformable::Transform(const BPoint& point) const return p; } -// InverseTransform + void Transformable::InverseTransform(double* x, double* y) const { inverse_transform(x, y); } -// InverseTransform + void Transformable::InverseTransform(BPoint* point) const { @@ -236,7 +221,7 @@ Transformable::InverseTransform(BPoint* point) const } } -// InverseTransform + BPoint Transformable::InverseTransform(const BPoint& point) const { @@ -245,7 +230,7 @@ Transformable::InverseTransform(const BPoint& point) const return p; } -// TransformBounds + BRect Transformable::TransformBounds(const BRect& bounds) const { @@ -279,7 +264,7 @@ Transformable::IsTranslationOnly() const } -// TranslateBy + void Transformable::TranslateBy(BPoint offset) { @@ -289,7 +274,7 @@ Transformable::TranslateBy(BPoint offset) } } -// RotateBy + void Transformable::RotateBy(BPoint origin, double radians) { @@ -301,7 +286,7 @@ Transformable::RotateBy(BPoint origin, double radians) } } -// ScaleBy + void Transformable::ScaleBy(BPoint origin, double xScale, double yScale) { @@ -313,7 +298,7 @@ Transformable::ScaleBy(BPoint origin, double xScale, double yScale) } } -// ShearBy + void Transformable::ShearBy(BPoint origin, double xShear, double yShear) { diff --git a/src/servers/app/drawing/Painter/Transformable.h b/src/servers/app/drawing/Painter/Transformable.h index 9854020..ac8dc0b 100644 --- a/src/servers/app/drawing/Painter/Transformable.h +++ b/src/servers/app/drawing/Painter/Transformable.h @@ -32,13 +32,14 @@ class Transformable : public BArchivable, // set to or combine with other matrix void SetTransformable(const Transformable& other); + Transformable& operator=(const agg::trans_affine& other); Transformable& operator=(const Transformable& other); Transformable& Multiply(const Transformable& other); void Reset(); bool IsIdentity() const; - bool operator==(const Transformable& other) const; - bool operator!=(const Transformable& other) const; +// bool operator==(const Transformable& other) const; +// bool operator!=(const Transformable& other) const; // transforms coordiantes void Transform(double* x, double* y) const; ############################################################################ Revision: hrev46838 Commit: 89f8b7a12d16a16388e45a4708c033cfb3993df7 URL: http://cgit.haiku-os.org/haiku/commit/?id=89f8b7a Author: Stephan Aßmus <superstippi@xxxxxx> Date: Sat Feb 8 10:36:13 2014 UTC 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. ---------------------------------------------------------------------------- diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index 6ef0b85..3fdc48f 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -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); diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 6e5a09e..bb9f200 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -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; @@ -387,6 +392,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 { rect.left = floorf(rect.left); @@ -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