[haiku-commits] r35905 - in haiku/trunk: headers/os/interface headers/private/interface src/kits/interface src/servers/app src/servers/app/drawing ...

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 18 Mar 2010 17:58:19 +0100 (CET)

Author: stippi
Date: 2010-03-18 17:58:19 +0100 (Thu, 18 Mar 2010)
New Revision: 35905
Changeset: http://dev.haiku-os.org/changeset/35905/haiku

Added:
   haiku/trunk/src/tests/servers/app/shape_test/
   haiku/trunk/src/tests/servers/app/shape_test/Jamfile
   haiku/trunk/src/tests/servers/app/shape_test/main.cpp
Modified:
   haiku/trunk/headers/os/interface/Shape.h
   haiku/trunk/headers/private/interface/ShapePrivate.h
   haiku/trunk/src/kits/interface/Shape.cpp
   haiku/trunk/src/servers/app/ServerPicture.cpp
   haiku/trunk/src/servers/app/ServerWindow.cpp
   haiku/trunk/src/servers/app/drawing/DrawingEngine.cpp
   haiku/trunk/src/servers/app/drawing/DrawingEngine.h
   haiku/trunk/src/servers/app/drawing/Painter/Painter.cpp
   haiku/trunk/src/servers/app/drawing/Painter/Painter.h
   haiku/trunk/src/servers/app/drawing/remote/RemoteDrawingEngine.cpp
   haiku/trunk/src/servers/app/drawing/remote/RemoteDrawingEngine.h
   haiku/trunk/src/servers/app/drawing/remote/RemoteMessage.h
   haiku/trunk/src/tests/servers/app/Jamfile
Log:
Basically, this changeset implements BShape::ArcTo(). In more detail:
 * Added BShape::ArcTo() and BShapeIterator::IterateArcTo(), using a previously
   unused virtual slot. (Added the symbols for binary compatibility for GCC2
   and GCC4.)
 * Added operator=(), operator==() and operator!=() to BShape.
 * Added BShape::BezierTo() version taking three points, which is sometimes
   more convenient.
 * Added the four new shape data ops OP_LARGE_ARC_TO_CW, OP_LARGE_ARC_TO_CCW,
   OP_SMALL_ARC_TO_CW and OP_SMALL_ARC_TO_CCW. For a single arc, provided the
   radius is large enough, there are four possibilities to draw the arc, these
   are controlled by the two boolean flags to ArcTo() and mapped to the new
   commands accordingly.
 * Some style cleanup in Shape.cpp (sorry for mixing it up, but it gets
   worse below...)
 * Added ShapeTest to src/tests/servers/app.
 * Changed the way BShapes are transformed from view to screen space in the
   app_server. For arcs, it would be nontrivial to apply a proper 
transformation,
   it's much easier to let AGG take care of it. This affects ServerPicture as
   well.
 * Wrapped iterating the BShape into try/catch blocks in ShapeIterator. But
   I really don't understand the purpose of the class in the first place.
   Maybe it can now be dropped, since coordinates don't have to be transformed
   in place anymore.
 * Refactored copy&paste shape iteration code in Painter. The transformation
   to screen space happens there.
 * Since RemoteDrawingEngine needed to be adopted anyway, I also updated
   it for the new DrawString() with offsets version. But the client still needs
   to be adapted.
 * Style cleanup in Painter.h


Modified: haiku/trunk/headers/os/interface/Shape.h
===================================================================
--- haiku/trunk/headers/os/interface/Shape.h    2010-03-18 16:19:13 UTC (rev 
35904)
+++ haiku/trunk/headers/os/interface/Shape.h    2010-03-18 16:58:19 UTC (rev 
35905)
@@ -30,10 +30,13 @@
                                                                        BPoint* 
bezierPts);
        virtual status_t                        IterateClose();
 
+       virtual status_t                        IterateArcTo(float& rx, float& 
ry,
+                                                                       float& 
angle, bool largeArc,
+                                                                       bool 
counterClockWise, BPoint& point);
+
                        status_t                        Iterate(BShape* shape);
 
 private:
-       virtual void                            _ReservedShapeIterator1();
        virtual void                            _ReservedShapeIterator2();
        virtual void                            _ReservedShapeIterator3();
        virtual void                            _ReservedShapeIterator4();
@@ -53,6 +56,11 @@
        virtual status_t                        Archive(BMessage* archive,
                                                                        bool 
deep = true) const;
 
+                       BShape&                         operator=(const BShape& 
other);
+
+                       bool                            operator==(const 
BShape& other) const;
+                       bool                            operator!=(const 
BShape& other) const;
+
                        void                            Clear();
                        BRect                           Bounds() const;
 
@@ -61,6 +69,13 @@
                        status_t                        MoveTo(BPoint point);
                        status_t                        LineTo(BPoint 
linePoint);
                        status_t                        BezierTo(BPoint 
controlPoints[3]);
+                       status_t                        BezierTo(const BPoint& 
control1,
+                                                                       const 
BPoint& control2,
+                                                                       const 
BPoint& endPoint);
+                       status_t                        ArcTo(float rx, float 
ry,
+                                                                       float 
angle, bool largeArc,
+                                                                       bool 
counterClockWise,
+                                                                       const 
BPoint& point);
                        status_t                        Close();
 
 private:

Modified: haiku/trunk/headers/private/interface/ShapePrivate.h
===================================================================
--- haiku/trunk/headers/private/interface/ShapePrivate.h        2010-03-18 
16:19:13 UTC (rev 35904)
+++ haiku/trunk/headers/private/interface/ShapePrivate.h        2010-03-18 
16:58:19 UTC (rev 35905)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2006, Haiku.
+ * Copyright 2003-2010, Haiku.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
@@ -9,10 +9,14 @@
 #ifndef SHAPE_PRIVATE_H
 #define SHAPE_PRIVATE_H
 
-#define OP_LINETO              0x10000000
-#define OP_BEZIERTO            0x20000000
-#define OP_CLOSE               0x40000000
-#define OP_MOVETO              0x80000000
+#define OP_LINETO                      0x10000000
+#define OP_BEZIERTO                    0x20000000
+#define OP_CLOSE                       0x40000000
+#define OP_MOVETO                      0x80000000
+#define OP_LARGE_ARC_TO_CW     0x01000000
+#define OP_LARGE_ARC_TO_CCW    0x02000000
+#define OP_SMALL_ARC_TO_CW     0x04000000
+#define OP_SMALL_ARC_TO_CCW    0x08000000
 
 
 struct shape_data {

Modified: haiku/trunk/src/kits/interface/Shape.cpp
===================================================================
--- haiku/trunk/src/kits/interface/Shape.cpp    2010-03-18 16:19:13 UTC (rev 
35904)
+++ haiku/trunk/src/kits/interface/Shape.cpp    2010-03-18 16:58:19 UTC (rev 
35905)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2007, Haiku, Inc.
+ * Copyright (c) 2001-2010, Haiku, Inc.
  * Distributed under the terms of the MIT license.
  *
  * Authors:
@@ -37,10 +37,10 @@
 
 
 status_t
-BShapeIterator::Iterate(BShape *shape)
+BShapeIterator::Iterate(BShape* shape)
 {
-       shape_data *data = (shape_data*)shape->fPrivateData;
-       BPoint *points = data->ptList;
+       shape_data* data = (shape_data*)shape->fPrivateData;
+       BPoint* points = data->ptList;
 
        for (int32 i = 0; i < data->opCount; i++) {
                int32 op = data->opList[i] & 0xFF000000;
@@ -62,6 +62,18 @@
                        points += count;
                }
 
+               if ((op & OP_LARGE_ARC_TO_CW) || (op & OP_LARGE_ARC_TO_CCW)
+                       || (op & OP_SMALL_ARC_TO_CW) || (op & 
OP_SMALL_ARC_TO_CCW)) {
+                       int32 count = data->opList[i] & 0x00FFFFFF;
+                       for (int32 i = 0; i < count / 3; i++) {
+                               IterateArcTo(points[0].x, points[0].y, 
points[1].x,
+                                       op & (OP_LARGE_ARC_TO_CW | 
OP_LARGE_ARC_TO_CCW),
+                                       op & (OP_SMALL_ARC_TO_CCW | 
OP_LARGE_ARC_TO_CCW),
+                                       points[2]);
+                               points += 3;
+                       }
+               }
+
                if (op & OP_CLOSE) {
                        IterateClose();
                }
@@ -72,40 +84,49 @@
 
 
 status_t
-BShapeIterator::IterateBezierTo(int32 bezierCount,
-                                                                               
 BPoint *bezierPoints)
+BShapeIterator::IterateMoveTo(BPoint* point)
 {
        return B_OK;
 }
 
 
 status_t
-BShapeIterator::IterateClose()
+BShapeIterator::IterateLineTo(int32 lineCount, BPoint* linePoints)
 {
        return B_OK;
 }
 
 
 status_t
-BShapeIterator::IterateLineTo(int32 lineCount, BPoint *linePoints)
+BShapeIterator::IterateBezierTo(int32 bezierCount, BPoint* bezierPoints)
 {
        return B_OK;
 }
 
 
 status_t
-BShapeIterator::IterateMoveTo ( BPoint *point )
+BShapeIterator::IterateClose()
 {
        return B_OK;
 }
 
 
-void BShapeIterator::_ReservedShapeIterator1() {}
+status_t
+BShapeIterator::IterateArcTo(float& rx, float& ry, float& angle, bool largeArc,
+       bool counterClockWise, BPoint& point)
+{
+       return B_OK;
+}
+
+
 void BShapeIterator::_ReservedShapeIterator2() {}
 void BShapeIterator::_ReservedShapeIterator3() {}
 void BShapeIterator::_ReservedShapeIterator4() {}
 
 
+// #pragma mark -
+
+
 BShape::BShape()
 {
        InitData();
@@ -119,12 +140,12 @@
 }
 
 
-BShape::BShape(BMessage *archive)
+BShape::BShape(BMessage* archive)
        :       BArchivable(archive)
 {
        InitData();
 
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        ssize_t size = 0;
        int32 count = 0;
@@ -134,8 +155,8 @@
                return;
 
        int32 i = 0;
-       const uint32 *opPtr;
-       while (archive->FindData("ops", B_INT32_TYPE, i++, (const void 
**)&opPtr, &size) == B_OK)
+       const uint32* opPtr;
+       while (archive->FindData("ops", B_INT32_TYPE, i++, (const 
void**)&opPtr, &size) == B_OK)
                data->opList[data->opCount++] = *opPtr;
 
        archive->GetInfo("pts", &type, &count);
@@ -145,15 +166,15 @@
        }
 
        i = 0;
-       const BPoint *ptPtr;
-       while (archive->FindData("pts", B_POINT_TYPE, i++, (const void 
**)&ptPtr, &size) == B_OK)
+       const BPoint* ptPtr;
+       while (archive->FindData("pts", B_POINT_TYPE, i++, (const 
void**)&ptPtr, &size) == B_OK)
                data->ptList[data->ptCount++] = *ptPtr;
 }
 
 
 BShape::~BShape()
 {
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        free(data->opList);
        free(data->ptList);
@@ -163,14 +184,14 @@
 
 
 status_t
-BShape::Archive(BMessage *archive, bool deep) const
+BShape::Archive(BMessage* archive, bool deep) const
 {
        status_t err = BArchivable::Archive(archive, deep);
 
        if (err != B_OK)
                return err;
 
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        // If no valid shape data, return
        if (data->opCount == 0 || data->ptCount == 0)
@@ -198,7 +219,7 @@
 
 
 BArchivable*
-BShape::Instantiate(BMessage *archive)
+BShape::Instantiate(BMessage* archive)
 {
        if (validate_instantiation(archive, "BShape"))
                return new BShape(archive);
@@ -207,10 +228,50 @@
 }
 
 
+BShape&
+BShape::operator=(const BShape& other)
+{
+       if (this != &other) {
+               Clear();
+               AddShape(&other);
+       }
+
+       return *this;
+}
+
+
+bool
+BShape::operator==(const BShape& other) const
+{
+       if (this == &other)
+               return true;
+
+       shape_data* data = (shape_data*)fPrivateData;
+       shape_data* otherData = (shape_data*)other.fPrivateData;
+
+       if (data->opCount != otherData->opCount)
+               return false;
+       if (data->ptCount != otherData->ptCount)
+               return false;
+
+       return memcmp(data->opList, otherData->opList,
+                       data->opCount * sizeof(uint32)) == 0
+               && memcmp(data->ptList, otherData->ptList,
+                       data->ptCount * sizeof(BPoint)) == 0;
+}
+
+
+bool
+BShape::operator!=(const BShape& other) const
+{
+       return !(*this == other);
+}
+
+
 void
 BShape::Clear()
 {
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        data->opCount = 0;
        data->opSize = 0;
@@ -234,7 +295,7 @@
 BRect
 BShape::Bounds() const
 {
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
        BRect bounds;
 
        if (data->ptCount == 0)
@@ -262,10 +323,10 @@
 
 
 status_t
-BShape::AddShape(const BShape *otherShape)
+BShape::AddShape(const BShape* otherShape)
 {
-       shape_data *data = (shape_data*)fPrivateData;
-       shape_data *otherData = (shape_data*)otherShape->fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
+       shape_data* otherData = (shape_data*)otherShape->fPrivateData;
 
        if (!AllocateOps(otherData->opCount) || 
!AllocatePts(otherData->ptCount))
                return B_NO_MEMORY;
@@ -287,7 +348,7 @@
 status_t
 BShape::MoveTo(BPoint point)
 {
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        // If the last op is MoveTo, replace the point
        if (fBuildingOp == OP_MOVETO) {
@@ -316,7 +377,7 @@
        if (!AllocatePts(1))
                return B_NO_MEMORY;
 
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        // If the last op is MoveTo, replace the op and set the count
        // If the last op is LineTo increase the count
@@ -342,10 +403,18 @@
 status_t
 BShape::BezierTo(BPoint controlPoints[3])
 {
+       return BezierTo(controlPoints[0], controlPoints[1], controlPoints[2]);
+}
+
+
+status_t
+BShape::BezierTo(const BPoint& control1, const BPoint& control2,
+       const BPoint& endPoint)
+{
        if (!AllocatePts(3))
                return B_NO_MEMORY;
 
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        // If the last op is MoveTo, replace the op and set the count
        // If the last op is BezierTo increase the count
@@ -362,15 +431,60 @@
        }
 
        // Add points
-       data->ptList[data->ptCount++] = controlPoints[0];
-       data->ptList[data->ptCount++] = controlPoints[1];
-       data->ptList[data->ptCount++] = controlPoints[2];
+       data->ptList[data->ptCount++] = control1;
+       data->ptList[data->ptCount++] = control2;
+       data->ptList[data->ptCount++] = endPoint;
 
        return B_OK;
 }
 
 
 status_t
+BShape::ArcTo(float rx, float ry, float angle, bool largeArc,
+       bool counterClockWise, const BPoint& point)
+{
+       if (!AllocatePts(3))
+               return B_NO_MEMORY;
+
+       shape_data* data = (shape_data*)fPrivateData;
+
+       uint32 op;
+       if (largeArc) {
+               if (counterClockWise)
+                       op = OP_LARGE_ARC_TO_CCW;
+               else
+                       op = OP_LARGE_ARC_TO_CW;
+       } else {
+               if (counterClockWise)
+                       op = OP_SMALL_ARC_TO_CCW;
+               else
+                       op = OP_SMALL_ARC_TO_CW;
+       }
+
+       // If the last op is MoveTo, replace the op and set the count
+       // If the last op is ArcTo increase the count
+       // Otherwise add the op
+       if (fBuildingOp == op || fBuildingOp == (op | OP_MOVETO)) {
+               fBuildingOp |= op;
+               fBuildingOp += 3;
+               data->opList[data->opCount - 1] = fBuildingOp;
+       } else {
+               if (!AllocateOps(1))
+                       return B_NO_MEMORY;
+               fBuildingOp = op + 3;
+               data->opList[data->opCount++] = fBuildingOp;
+       }
+
+       // Add points
+       data->ptList[data->ptCount++] = BPoint(rx, ry);
+       data->ptList[data->ptCount++] = BPoint(angle, 0);
+       data->ptList[data->ptCount++] = point;
+
+       return B_OK;
+}
+
+
+status_t
 BShape::Close()
 {
        // If the last op is Close or MoveTo, ignore this
@@ -380,7 +494,7 @@
        if (!AllocateOps(1))
                return B_NO_MEMORY;
 
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        // ToDo: Decide about that, it's not BeOS compatible
        // If there was any op before we can attach the close to it
@@ -398,7 +512,7 @@
 
 
 status_t
-BShape::Perform(perform_code d, void *arg)
+BShape::Perform(perform_code d, void* arg)
 {
        return BArchivable::Perform(d, arg);
 }
@@ -411,10 +525,10 @@
 
 
 void
-BShape::GetData(int32 *opCount, int32 *ptCount, uint32 **opList,
-                                        BPoint **ptList)
+BShape::GetData(int32* opCount, int32* ptCount, uint32** opList,
+       BPoint** ptList)
 {
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        *opCount = data->opCount;
        *ptCount = data->ptCount;
@@ -424,15 +538,15 @@
 
 
 void
-BShape::SetData(int32 opCount, int32 ptCount, const uint32 *opList,
-                               const BPoint *ptList)
+BShape::SetData(int32 opCount, int32 ptCount, const uint32* opList,
+                               const BPoint* ptList)
 {
        Clear();
 
        if (opCount == 0)
                return;
 
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        if (!AllocateOps(opCount) || !AllocatePts(ptCount))
                return;
@@ -454,7 +568,7 @@
 BShape::InitData()
 {
        fPrivateData = new shape_data;
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        fState = 0;
        fBuildingOp = 0;
@@ -471,7 +585,7 @@
 inline bool
 BShape::AllocateOps(int32 count)
 {
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        int32 newSize = (data->opCount + count + 255) / 256 * 256;
        if (data->opSize >= newSize)
@@ -490,7 +604,7 @@
 inline bool
 BShape::AllocatePts(int32 count)
 {
-       shape_data *data = (shape_data*)fPrivateData;
+       shape_data* data = (shape_data*)fPrivateData;
 
        int32 newSize = (data->ptCount + count + 255) / 256 * 256;
        if (data->ptSize >= newSize)
@@ -506,11 +620,12 @@
 }
 
 
-//     #pragma mark - R4.5 compatibility
+//     #pragma mark - binary compatibility
 
 
 #if __GNUC__ < 3
 
+
 extern "C" BShape*
 __6BShapeR6BShape(void* self, BShape& copyFrom)
 {
@@ -520,9 +635,25 @@
 
 
 extern "C" BRect
-Bounds__6BShape(BShape *self)
+Bounds__6BShape(BShape* self)
 {
        return self->Bounds();
 }
 
-#endif // __GNUC__ < 3
+
+extern "C" void
+_ReservedShapeIterator1__14BShapeIterator(BShapeIterator* self)
+{
+}
+
+
+#else // __GNUC__ < 3
+
+
+extern "C" void
+_ZN14BShapeIterator23_ReservedShapeIterator1Ev(BShapeIterator* self)
+{
+}
+
+
+#endif // __GNUC__ >= 3

Modified: haiku/trunk/src/servers/app/ServerPicture.cpp
===================================================================
--- haiku/trunk/src/servers/app/ServerPicture.cpp       2010-03-18 16:19:13 UTC 
(rev 35904)
+++ haiku/trunk/src/servers/app/ServerPicture.cpp       2010-03-18 16:58:19 UTC 
(rev 35905)
@@ -42,7 +42,7 @@
 
 class ShapePainter : public BShapeIterator {
 public:
-       ShapePainter();
+       ShapePainter(View* view);
        virtual ~ShapePainter();
 
        status_t Iterate(const BShape* shape);
@@ -51,16 +51,21 @@
        virtual status_t IterateLineTo(int32 lineCount, BPoint* linePts);
        virtual status_t IterateBezierTo(int32 bezierCount, BPoint* bezierPts);
        virtual status_t IterateClose();
+       virtual status_t IterateArcTo(float& rx, float& ry,
+               float& angle, bool largeArc, bool counterClockWise, BPoint& 
point);
 
-       void Draw(View* view, BRect frame, bool filled);
+       void Draw(BRect frame, bool filled);
 
 private:
-       stack<uint32> fOpStack;
-       stack<BPoint> fPtStack;
+       View*                   fView;
+       stack<uint32>   fOpStack;
+       stack<BPoint>   fPtStack;
 };
 
 
-ShapePainter::ShapePainter()
+ShapePainter::ShapePainter(View* view)
+       :
+       fView(view)
 {
 }
 
@@ -81,8 +86,14 @@
 status_t
 ShapePainter::IterateMoveTo(BPoint* point)
 {
-       fOpStack.push(OP_MOVETO);
-       fPtStack.push(*point);
+       try {
+               fOpStack.push(OP_MOVETO);
+               BPoint transformed(*point);
+               fView->ConvertToScreenForDrawing(&transformed);
+               fPtStack.push(transformed);
+       } catch (std::bad_alloc) {
+               return B_NO_MEMORY;
+       }
 
        return B_OK;
 }
@@ -91,9 +102,16 @@
 status_t
 ShapePainter::IterateLineTo(int32 lineCount, BPoint* linePts)
 {
-       fOpStack.push(OP_LINETO | lineCount);
-       for (int32 i = 0; i < lineCount; i++)
-               fPtStack.push(linePts[i]);
+       try {
+               fOpStack.push(OP_LINETO | lineCount);
+               for (int32 i = 0; i < lineCount; i++) {
+                       BPoint transformed(linePts[i]);
+                       fView->ConvertToScreenForDrawing(&transformed);
+                       fPtStack.push(transformed);
+               }
+       } catch (std::bad_alloc) {
+               return B_NO_MEMORY;
+       }
 
        return B_OK;
 }
@@ -103,27 +121,71 @@
 ShapePainter::IterateBezierTo(int32 bezierCount, BPoint* bezierPts)
 {
        bezierCount *= 3;
-       fOpStack.push(OP_BEZIERTO | bezierCount);
-       for (int32 i = 0; i < bezierCount; i++)
-               fPtStack.push(bezierPts[i]);
+       try {
+               fOpStack.push(OP_BEZIERTO | bezierCount);
+               for (int32 i = 0; i < bezierCount; i++) {
+                       BPoint transformed(bezierPts[i]);
+                       fView->ConvertToScreenForDrawing(&transformed);
+                       fPtStack.push(transformed);
+               }
+       } catch (std::bad_alloc) {
+               return B_NO_MEMORY;
+       }
 
        return B_OK;
 }
 
 
 status_t
-ShapePainter::IterateClose(void)
+ShapePainter::IterateArcTo(float& rx, float& ry,
+       float& angle, bool largeArc, bool counterClockWise, BPoint& point)
 {
-       fOpStack.push(OP_CLOSE);
+       uint32 op;
+       if (largeArc) {
+               if (counterClockWise)
+                       op = OP_LARGE_ARC_TO_CCW;
+               else
+                       op = OP_LARGE_ARC_TO_CW;
+       } else {
+               if (counterClockWise)
+                       op = OP_SMALL_ARC_TO_CCW;
+               else
+                       op = OP_SMALL_ARC_TO_CW;
+       }
 
+       try {
+               fOpStack.push(op | 3);
+               fPtStack.push(BPoint(rx * fView->Scale(), ry * fView->Scale()));
+               fPtStack.push(BPoint(angle, 0));
+               BPoint transformed(point);
+               fView->ConvertToScreenForDrawing(&transformed);
+               fPtStack.push(transformed);
+       } catch (std::bad_alloc) {
+               return B_NO_MEMORY;
+       }
+
        return B_OK;
 }
 
 
+status_t
+ShapePainter::IterateClose()
+{
+       try {
+               fOpStack.push(OP_CLOSE);
+       } catch (std::bad_alloc) {
+               return B_NO_MEMORY;
+       }
+
+       return B_OK;
+}
+
+
 void
-ShapePainter::Draw(View* view, BRect frame, bool filled)
+ShapePainter::Draw(BRect frame, bool filled)
 {
        // We're going to draw the currently iterated shape.
+       // TODO: This can be more efficient by skipping the conversion.
        int32 opCount = fOpStack.size();
        int32 ptCount = fPtStack.size();
 
@@ -144,14 +206,15 @@
                        fOpStack.pop();
                }
 
-               for (i = (ptCount - 1); i >= 0; i--) {
+               for (i = ptCount - 1; i >= 0; i--) {
                        ptList[i] = fPtStack.top();
                        fPtStack.pop();
-                       view->ConvertToScreenForDrawing(&ptList[i]);
                }
 
-               view->Window()->GetDrawingEngine()->DrawShape(frame, opCount,
-                       opList, ptCount, ptList, filled);
+               BPoint offset;
+               fView->ConvertToScreenForDrawing(&offset);
+               fView->Window()->GetDrawingEngine()->DrawShape(frame, opCount,
+                       opList, ptCount, ptList, filled, offset, 
fView->Scale());
 
                delete[] opList;
                delete[] ptList;
@@ -399,20 +462,20 @@
 static void
 stroke_shape(View* view, const BShape* shape)
 {
-       ShapePainter drawShape;
+       ShapePainter drawShape(view);
 
        drawShape.Iterate(shape);
-       drawShape.Draw(view, shape->Bounds(), false);
+       drawShape.Draw(shape->Bounds(), false);
 }
 
 
 static void
 fill_shape(View* view, const BShape* shape)
 {
-       ShapePainter drawShape;
+       ShapePainter drawShape(view);
 
        drawShape.Iterate(shape);
-       drawShape.Draw(view, shape->Bounds(), true);
+       drawShape.Draw(shape->Bounds(), true);
 }
 
 

Modified: haiku/trunk/src/servers/app/ServerWindow.cpp
===================================================================
--- haiku/trunk/src/servers/app/ServerWindow.cpp        2010-03-18 16:19:13 UTC 
(rev 35904)
+++ haiku/trunk/src/servers/app/ServerWindow.cpp        2010-03-18 16:58:19 UTC 
(rev 35905)
@@ -2541,18 +2541,16 @@
 
                                // this might seem a bit weird, but under R5, 
the shapes
                                // are always offset by the current pen location
-                               BPoint penLocation
+                               BPoint screenOffset
                                        = 
fCurrentView->CurrentState()->PenLocation();
-                               for (int32 i = 0; i < ptCount; i++) {
-                                       ptList[i] += penLocation;
-                                       
fCurrentView->ConvertToScreenForDrawing(&ptList[i]);
-                               }
+                               shapeFrame.OffsetBy(screenOffset);
 
-                               shapeFrame.OffsetBy(penLocation);
+                               
fCurrentView->ConvertToScreenForDrawing(&screenOffset);
                                
fCurrentView->ConvertToScreenForDrawing(&shapeFrame);
 
                                drawingEngine->DrawShape(shapeFrame, opCount, 
opList, ptCount,
-                                       ptList, code == AS_FILL_SHAPE);
+                                       ptList, code == AS_FILL_SHAPE, 
screenOffset,
+                                       fCurrentView->Scale());
                        }
 
                        delete[] opList;
@@ -2581,15 +2579,16 @@
 
                                // this might seem a bit weird, but under R5, 
the shapes
                                // are always offset by the current pen location
-                               BPoint penLocation
+                               BPoint screenOffset
                                        = 
fCurrentView->CurrentState()->PenLocation();
-                               for (int32 i = 0; i < ptCount; i++) {
-                                       ptList[i] += penLocation;
-                                       
fCurrentView->ConvertToScreenForDrawing(&ptList[i]);
-                               }
+                               shapeFrame.OffsetBy(screenOffset);
+
+                               
fCurrentView->ConvertToScreenForDrawing(&screenOffset);
+                               
fCurrentView->ConvertToScreenForDrawing(&shapeFrame);
                                
fCurrentView->ConvertToScreenForDrawing(gradient);
                                drawingEngine->FillShape(shapeFrame, opCount, 
opList,
-                                       ptCount, ptList, *gradient);
+                                       ptCount, ptList, *gradient, 
screenOffset,
+                                       fCurrentView->Scale());
                        }
 
                        delete[] opList;

Modified: haiku/trunk/src/servers/app/drawing/DrawingEngine.cpp
===================================================================
--- haiku/trunk/src/servers/app/drawing/DrawingEngine.cpp       2010-03-18 
16:19:13 UTC (rev 35904)
+++ haiku/trunk/src/servers/app/drawing/DrawingEngine.cpp       2010-03-18 
16:58:19 UTC (rev 35905)
@@ -150,7 +150,7 @@
 
 
 bool
-DrawingEngine::IsExclusiveAccessLocked()
+DrawingEngine::IsExclusiveAccessLocked() const
 {
        return fGraphicsCard->IsExclusiveAccessLocked();
 }
@@ -1141,16 +1141,30 @@
 
 void
 DrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
-       const uint32* opList, int32 ptCount, const BPoint* ptList, bool filled)
+       const uint32* opList, int32 ptCount, const BPoint* ptList, bool filled,
+       const BPoint& viewToScreenOffset, float viewScale)
 {
        ASSERT_PARALLEL_LOCKED();
 
-       // NOTE: hides cursor regardless of if and where
-       // shape is drawn on screen, TODO: optimize
+// TODO: bounds probably does not take curves and arcs into account...
+//     BRect clipped(bounds);
+//     if (!filled)
+//             extend_by_stroke_width(clipped, fPainter->PenSize());
+//     clipped = fPainter->ClipRect(bounds);
+//
+//     clipped.left = floorf(clipped.left);
+//     clipped.top = floorf(clipped.top);
+//     clipped.right = ceilf(clipped.right);
+//     clipped.bottom = ceilf(clipped.bottom);
+//
+//     if (!clipped.IsValid())
+//             return;
+//
+//     AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
        AutoFloatingOverlaysHider _(fGraphicsCard);
 
        BRect touched = fPainter->DrawShape(opCount, opList, ptCount, ptList,
-               filled);
+               filled, viewToScreenOffset, viewScale);
 
        _CopyToFront(touched);
 }
@@ -1159,16 +1173,27 @@
 void
 DrawingEngine::FillShape(const BRect& bounds, int32 opCount,
        const uint32* opList, int32 ptCount, const BPoint* ptList,
-       const BGradient& gradient)
+       const BGradient& gradient, const BPoint& viewToScreenOffset,
+       float viewScale)
 {
        ASSERT_PARALLEL_LOCKED();
 
-       // NOTE: hides cursor regardless of if and where
-       // shape is drawn on screen, TODO: optimize
+// TODO: bounds probably does not take curves and arcs into account...
+//     BRect clipped = fPainter->ClipRect(bounds);
+//
+//     clipped.left = floorf(clipped.left);
+//     clipped.top = floorf(clipped.top);
+//     clipped.right = ceilf(clipped.right);
+//     clipped.bottom = ceilf(clipped.bottom);
+//
+//     if (!clipped.IsValid())
+//             return;
+//
+//     AutoFloatingOverlaysHider _(fGraphicsCard, clipped);
        AutoFloatingOverlaysHider _(fGraphicsCard);
 
        BRect touched = fPainter->FillShape(opCount, opList, ptCount, ptList,
-               gradient);
+               gradient, viewToScreenOffset, viewScale);
 
        _CopyToFront(touched);
 }

Modified: haiku/trunk/src/servers/app/drawing/DrawingEngine.h
===================================================================
--- haiku/trunk/src/servers/app/drawing/DrawingEngine.h 2010-03-18 16:19:13 UTC 
(rev 35904)
+++ haiku/trunk/src/servers/app/drawing/DrawingEngine.h 2010-03-18 16:58:19 UTC 
(rev 35905)
@@ -56,7 +56,7 @@
                        void                    UnlockParallelAccess();
 
                        bool                    LockExclusiveAccess();
-       virtual bool                    IsExclusiveAccessLocked();
+       virtual bool                    IsExclusiveAccessLocked() const;
                        void                    UnlockExclusiveAccess();
 
        // for screen shots
@@ -138,11 +138,14 @@
        virtual void                    DrawShape(const BRect& bounds,
                                                                int32 opcount, 
const uint32* oplist,
                                                                int32 ptcount, 
const BPoint* ptlist,
-                                                               bool filled);
+                                                               bool filled, 
const BPoint& viewToScreenOffset,
+                                                               float 
viewScale);
        virtual void                    FillShape(const BRect& bounds,
-                                                         int32 opcount, const 
uint32* oplist,
-                                                         int32 ptcount, const 
BPoint* ptlist,
-                                                         const BGradient& 
gradient);
+                                                               int32 opcount, 
const uint32* oplist,
+                                                               int32 ptcount, 
const BPoint* ptlist,
+                                                               const 
BGradient& gradient,
+                                                               const BPoint& 
viewToScreenOffset,
+                                                               float 
viewScale);
 
        virtual void                    DrawTriangle(BPoint* points, const 
BRect& bounds,
                                                                bool filled);

Modified: haiku/trunk/src/servers/app/drawing/Painter/Painter.cpp
===================================================================
--- haiku/trunk/src/servers/app/drawing/Painter/Painter.cpp     2010-03-18 
16:19:13 UTC (rev 35904)
+++ haiku/trunk/src/servers/app/drawing/Painter/Painter.cpp     2010-03-18 
16:58:19 UTC (rev 35905)
@@ -668,28 +668,31 @@
 }
 
 
-// DrawShape
-BRect
-Painter::DrawShape(const int32& opCount, const uint32* opList,
-       const int32& ptCount, const BPoint* points, bool filled) const
+static void
+iterate_shape_data(agg::path_storage& path,
+       const int32& opCount, const uint32* opList,
+       const int32& ptCount, const BPoint* points,
+       const BPoint& viewToScreenOffset, float viewScale)
 {
-       CHECK_CLIPPING
-
        // TODO: if shapes are ever used more heavily in Haiku,
        // it would be nice to use BShape data directly (write
        // an AGG "VertexSource" adaptor)
-       fPath.remove_all();
+       path.remove_all();
        for (int32 i = 0; i < opCount; i++) {
                uint32 op = opList[i] & 0xFF000000;
                if (op & OP_MOVETO) {
-                       fPath.move_to(points->x, points->y);
+                       path.move_to(
+                               points->x * viewScale + viewToScreenOffset.x,
+                               points->y * viewScale + viewToScreenOffset.y);
                        points++;
                }
 
                if (op & OP_LINETO) {
                        int32 count = opList[i] & 0x00FFFFFF;
                        while (count--) {
-                               fPath.line_to(points->x, points->y);
+                               path.line_to(
+                                       points->x * viewScale + 
viewToScreenOffset.x,
+                                       points->y * viewScale + 
viewToScreenOffset.y);
                                points++;
                        }
                }
@@ -697,17 +700,52 @@
                if (op & OP_BEZIERTO) {
                        int32 count = opList[i] & 0x00FFFFFF;
                        while (count) {
-                               fPath.curve4(points[0].x, points[0].y, 
points[1].x, points[1].y,
-                                       points[2].x, points[2].y);
+                               path.curve4(
+                                       points[0].x * viewScale + 
viewToScreenOffset.x,
+                                       points[0].y * viewScale + 
viewToScreenOffset.y,
+                                       points[1].x * viewScale + 
viewToScreenOffset.x,
+                                       points[1].y * viewScale + 
viewToScreenOffset.y,
+                                       points[2].x * viewScale + 
viewToScreenOffset.x,
+                                       points[2].y * viewScale + 
viewToScreenOffset.y);
                                points += 3;
                                count -= 3;
                        }
                }
 
+               if ((op & OP_LARGE_ARC_TO_CW) || (op & OP_LARGE_ARC_TO_CCW)
+                       || (op & OP_SMALL_ARC_TO_CW) || (op & 
OP_SMALL_ARC_TO_CCW)) {
+                       int32 count = opList[i] & 0x00FFFFFF;
+                       while (count) {
+                               path.arc_to(
+                                       points[0].x * viewScale,
+                                       points[0].y * viewScale,
+                                       points[1].x,
+                                       op & (OP_LARGE_ARC_TO_CW | 
OP_LARGE_ARC_TO_CCW),
+                                       op & (OP_SMALL_ARC_TO_CW | 
OP_LARGE_ARC_TO_CW),
+                                       points[2].x * viewScale + 
viewToScreenOffset.x,
+                                       points[2].y * viewScale + 
viewToScreenOffset.y);
+                               points += 3;
+                               count -= 3;
+                       }
+               }
+
                if (op & OP_CLOSE)
-                       fPath.close_polygon();
+                       path.close_polygon();
        }
+}
 
+
+// DrawShape

[... truncated: 541 lines follow ...]

Other related posts: