2 * Copyright 2003-2010 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT license.
6 * Stephan Aßmus, superstippi@gmx.de
7 * Marc Flerackers, mflerackers@androme.be
8 * Michael Lotz, mmlr@mlotz.ch
9 * Marcus Overhagen, marcus@overhagen.de
19 #include <ShapePrivate.h>
26 // #pragma mark - BShapeIterator
29 BShapeIterator::BShapeIterator()
34 BShapeIterator::~BShapeIterator()
40 BShapeIterator::Iterate(BShape
* shape
)
42 shape_data
* data
= (shape_data
*)shape
->fPrivateData
;
43 BPoint
* points
= data
->ptList
;
45 for (int32 i
= 0; i
< data
->opCount
; i
++) {
46 int32 op
= data
->opList
[i
] & 0xFF000000;
48 if ((op
& OP_MOVETO
) != 0) {
49 IterateMoveTo(points
);
53 if ((op
& OP_LINETO
) != 0) {
54 int32 count
= data
->opList
[i
] & 0x00FFFFFF;
55 IterateLineTo(count
, points
);
59 if ((op
& OP_BEZIERTO
) != 0) {
60 int32 count
= data
->opList
[i
] & 0x00FFFFFF;
61 IterateBezierTo(count
/ 3, points
);
65 if ((op
& OP_LARGE_ARC_TO_CW
) != 0 || (op
& OP_LARGE_ARC_TO_CCW
) != 0
66 || (op
& OP_SMALL_ARC_TO_CW
) != 0
67 || (op
& OP_SMALL_ARC_TO_CCW
) != 0) {
68 int32 count
= data
->opList
[i
] & 0x00FFFFFF;
69 for (int32 i
= 0; i
< count
/ 3; i
++) {
70 IterateArcTo(points
[0].x
, points
[0].y
, points
[1].x
,
71 op
& (OP_LARGE_ARC_TO_CW
| OP_LARGE_ARC_TO_CCW
),
72 op
& (OP_SMALL_ARC_TO_CCW
| OP_LARGE_ARC_TO_CCW
),
78 if ((op
& OP_CLOSE
) != 0)
87 BShapeIterator::IterateMoveTo(BPoint
* point
)
94 BShapeIterator::IterateLineTo(int32 lineCount
, BPoint
* linePoints
)
101 BShapeIterator::IterateBezierTo(int32 bezierCount
, BPoint
* bezierPoints
)
108 BShapeIterator::IterateClose()
115 BShapeIterator::IterateArcTo(float& rx
, float& ry
, float& angle
, bool largeArc
,
116 bool counterClockWise
, BPoint
& point
)
122 // #pragma mark - BShapeIterator FBC padding
125 void BShapeIterator::_ReservedShapeIterator2() {}
126 void BShapeIterator::_ReservedShapeIterator3() {}
127 void BShapeIterator::_ReservedShapeIterator4() {}
130 // #pragma mark - BShape
139 BShape::BShape(const BShape
& other
)
146 BShape::BShape(BMessage
* archive
)
152 shape_data
* data
= (shape_data
*)fPrivateData
;
157 archive
->GetInfo("ops", &type
, &count
);
158 if (!AllocateOps(count
))
163 while (archive
->FindData("ops", B_INT32_TYPE
, i
++,
164 (const void**)&opPtr
, &size
) == B_OK
) {
165 data
->opList
[data
->opCount
++] = *opPtr
;
168 archive
->GetInfo("pts", &type
, &count
);
169 if (!AllocatePts(count
)) {
176 while (archive
->FindData("pts", B_POINT_TYPE
, i
++,
177 (const void**)&ptPtr
, &size
) == B_OK
) {
178 data
->ptList
[data
->ptCount
++] = *ptPtr
;
185 shape_data
* data
= (shape_data
*)fPrivateData
;
186 if (!data
->fOwnsMemory
) {
191 data
->ReleaseReference();
196 BShape::Archive(BMessage
* archive
, bool deep
) const
198 status_t result
= BArchivable::Archive(archive
, deep
);
203 shape_data
* data
= (shape_data
*)fPrivateData
;
205 // If no valid shape data, return
206 if (data
->opCount
== 0 || data
->ptCount
== 0)
209 // Avoids allocation for each point
210 result
= archive
->AddData("pts", B_POINT_TYPE
, data
->ptList
,
211 sizeof(BPoint
), true, data
->ptCount
);
215 for (int32 i
= 1; i
< data
->ptCount
&& result
== B_OK
; i
++)
216 result
= archive
->AddPoint("pts", data
->ptList
[i
]);
218 // Avoids allocation for each op
219 if (result
== B_OK
) {
220 result
= archive
->AddData("ops", B_INT32_TYPE
, data
->opList
,
221 sizeof(int32
), true, data
->opCount
);
224 for (int32 i
= 1; i
< data
->opCount
&& result
== B_OK
; i
++)
225 result
= archive
->AddInt32("ops", data
->opList
[i
]);
232 BShape::Instantiate(BMessage
* archive
)
234 if (validate_instantiation(archive
, "BShape"))
235 return new BShape(archive
);
242 BShape::operator=(const BShape
& other
)
244 if (this != &other
) {
254 BShape::operator==(const BShape
& other
) const
259 shape_data
* data
= (shape_data
*)fPrivateData
;
260 shape_data
* otherData
= (shape_data
*)other
.fPrivateData
;
262 if (data
->opCount
!= otherData
->opCount
)
265 if (data
->ptCount
!= otherData
->ptCount
)
268 return memcmp(data
->opList
, otherData
->opList
,
269 data
->opCount
* sizeof(uint32
)) == 0
270 && memcmp(data
->ptList
, otherData
->ptList
,
271 data
->ptCount
* sizeof(BPoint
)) == 0;
276 BShape::operator!=(const BShape
& other
) const
278 return !(*this == other
);
285 shape_data
* data
= (shape_data
*)fPrivateData
;
307 BShape::Bounds() const
309 shape_data
* data
= (shape_data
*)fPrivateData
;
310 return data
->DetermineBoundingBox();
315 BShape::CurrentPosition() const
317 shape_data
* data
= (shape_data
*)fPrivateData
;
319 if (data
->ptCount
== 0)
322 return data
->ptList
[data
->ptCount
- 1];
327 BShape::AddShape(const BShape
* otherShape
)
329 shape_data
* data
= (shape_data
*)fPrivateData
;
330 shape_data
* otherData
= (shape_data
*)otherShape
->fPrivateData
;
332 if (!AllocateOps(otherData
->opCount
) || !AllocatePts(otherData
->ptCount
))
335 memcpy(data
->opList
+ data
->opCount
, otherData
->opList
,
336 otherData
->opCount
* sizeof(uint32
));
337 data
->opCount
+= otherData
->opCount
;
339 memcpy(data
->ptList
+ data
->ptCount
, otherData
->ptList
,
340 otherData
->ptCount
* sizeof(BPoint
));
341 data
->ptCount
+= otherData
->ptCount
;
343 fBuildingOp
= otherShape
->fBuildingOp
;
350 BShape::MoveTo(BPoint point
)
352 shape_data
* data
= (shape_data
*)fPrivateData
;
354 // If the last op is MoveTo, replace the point
355 if (fBuildingOp
== OP_MOVETO
) {
356 data
->ptList
[data
->ptCount
- 1] = point
;
360 if (!AllocateOps(1) || !AllocatePts(1))
363 fBuildingOp
= OP_MOVETO
;
366 data
->opList
[data
->opCount
++] = fBuildingOp
;
369 data
->ptList
[data
->ptCount
++] = point
;
376 BShape::LineTo(BPoint point
)
381 shape_data
* data
= (shape_data
*)fPrivateData
;
383 // If the last op is MoveTo, replace the op and set the count
384 // If the last op is LineTo increase the count
385 // Otherwise add the op
386 if (fBuildingOp
& OP_LINETO
|| fBuildingOp
== OP_MOVETO
) {
387 fBuildingOp
|= OP_LINETO
;
389 data
->opList
[data
->opCount
- 1] = fBuildingOp
;
394 fBuildingOp
= OP_LINETO
+ 1;
395 data
->opList
[data
->opCount
++] = fBuildingOp
;
399 data
->ptList
[data
->ptCount
++] = point
;
406 BShape::BezierTo(BPoint controlPoints
[3])
408 return BezierTo(controlPoints
[0], controlPoints
[1], controlPoints
[2]);
413 BShape::BezierTo(const BPoint
& control1
, const BPoint
& control2
,
414 const BPoint
& endPoint
)
419 shape_data
* data
= (shape_data
*)fPrivateData
;
421 // If the last op is MoveTo, replace the op and set the count
422 // If the last op is BezierTo increase the count
423 // Otherwise add the op
424 if (fBuildingOp
& OP_BEZIERTO
|| fBuildingOp
== OP_MOVETO
) {
425 fBuildingOp
|= OP_BEZIERTO
;
427 data
->opList
[data
->opCount
- 1] = fBuildingOp
;
431 fBuildingOp
= OP_BEZIERTO
+ 3;
432 data
->opList
[data
->opCount
++] = fBuildingOp
;
436 data
->ptList
[data
->ptCount
++] = control1
;
437 data
->ptList
[data
->ptCount
++] = control2
;
438 data
->ptList
[data
->ptCount
++] = endPoint
;
445 BShape::ArcTo(float rx
, float ry
, float angle
, bool largeArc
,
446 bool counterClockWise
, const BPoint
& point
)
451 shape_data
* data
= (shape_data
*)fPrivateData
;
455 if (counterClockWise
)
456 op
= OP_LARGE_ARC_TO_CCW
;
458 op
= OP_LARGE_ARC_TO_CW
;
460 if (counterClockWise
)
461 op
= OP_SMALL_ARC_TO_CCW
;
463 op
= OP_SMALL_ARC_TO_CW
;
466 // If the last op is MoveTo, replace the op and set the count
467 // If the last op is ArcTo increase the count
468 // Otherwise add the op
469 if (fBuildingOp
== op
|| fBuildingOp
== (op
| OP_MOVETO
)) {
472 data
->opList
[data
->opCount
- 1] = fBuildingOp
;
477 fBuildingOp
= op
+ 3;
478 data
->opList
[data
->opCount
++] = fBuildingOp
;
482 data
->ptList
[data
->ptCount
++] = BPoint(rx
, ry
);
483 data
->ptList
[data
->ptCount
++] = BPoint(angle
, 0);
484 data
->ptList
[data
->ptCount
++] = point
;
493 // If the last op is Close or MoveTo, ignore this
494 if (fBuildingOp
== OP_CLOSE
|| fBuildingOp
== OP_MOVETO
)
500 shape_data
* data
= (shape_data
*)fPrivateData
;
502 // ToDo: Decide about that, it's not BeOS compatible
503 // If there was any op before we can attach the close to it
505 fBuildingOp |= OP_CLOSE;
506 data->opList[data->opCount - 1] = fBuildingOp;
510 fBuildingOp
= OP_CLOSE
;
511 data
->opList
[data
->opCount
++] = fBuildingOp
;
517 // #pragma mark - BShape private methods
521 BShape::Perform(perform_code code
, void* data
)
523 return BArchivable::Perform(code
, data
);
527 // #pragma mark - BShape FBC methods
530 void BShape::_ReservedShape1() {}
531 void BShape::_ReservedShape2() {}
532 void BShape::_ReservedShape3() {}
533 void BShape::_ReservedShape4() {}
536 // #pragma mark - BShape private methods
540 BShape::GetData(int32
* opCount
, int32
* ptCount
, uint32
** opList
,
543 shape_data
* data
= (shape_data
*)fPrivateData
;
545 *opCount
= data
->opCount
;
546 *ptCount
= data
->ptCount
;
547 *opList
= data
->opList
;
548 *ptList
= data
->ptList
;
553 BShape::SetData(int32 opCount
, int32 ptCount
, const uint32
* opList
,
554 const BPoint
* ptList
)
561 shape_data
* data
= (shape_data
*)fPrivateData
;
563 if (!AllocateOps(opCount
) || !AllocatePts(ptCount
))
566 memcpy(data
->opList
, opList
, opCount
* sizeof(uint32
));
567 data
->opCount
= opCount
;
568 fBuildingOp
= data
->opList
[data
->opCount
- 1];
571 memcpy(data
->ptList
, ptList
, ptCount
* sizeof(BPoint
));
572 data
->ptCount
= ptCount
;
580 fPrivateData
= new shape_data
;
581 shape_data
* data
= (shape_data
*)fPrivateData
;
596 BShape::AllocateOps(int32 count
)
598 shape_data
* data
= (shape_data
*)fPrivateData
;
600 int32 newSize
= (data
->opCount
+ count
+ 255) / 256 * 256;
601 if (data
->opSize
>= newSize
)
604 uint32
* resizedArray
= (uint32
*)realloc(data
->opList
, newSize
* sizeof(uint32
));
606 data
->opList
= resizedArray
;
607 data
->opSize
= newSize
;
615 BShape::AllocatePts(int32 count
)
617 shape_data
* data
= (shape_data
*)fPrivateData
;
619 int32 newSize
= (data
->ptCount
+ count
+ 255) / 256 * 256;
620 if (data
->ptSize
>= newSize
)
623 BPoint
* resizedArray
= (BPoint
*)realloc(data
->ptList
, newSize
* sizeof(BPoint
));
625 data
->ptList
= resizedArray
;
626 data
->ptSize
= newSize
;
633 // #pragma mark - BShape binary compatibility methods
640 __6BShapeR6BShape(void* self
, BShape
& copyFrom
)
642 return new (self
) BShape(copyFrom
);
643 // we need to instantiate the object in the provided memory
648 Bounds__6BShape(BShape
* self
)
650 return self
->Bounds();
655 _ReservedShapeIterator1__14BShapeIterator(BShapeIterator
* self
)
660 #else // __GNUC__ < 3
664 _ZN14BShapeIterator23_ReservedShapeIterator1Ev(BShapeIterator
* self
)
669 #endif // __GNUC__ >= 3