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
;
190 delete (shape_data
*)fPrivateData
;
195 BShape::Archive(BMessage
* archive
, bool deep
) const
197 status_t result
= BArchivable::Archive(archive
, deep
);
202 shape_data
* data
= (shape_data
*)fPrivateData
;
204 // If no valid shape data, return
205 if (data
->opCount
== 0 || data
->ptCount
== 0)
208 // Avoids allocation for each point
209 result
= archive
->AddData("pts", B_POINT_TYPE
, data
->ptList
,
210 sizeof(BPoint
), true, data
->ptCount
);
214 for (int32 i
= 1; i
< data
->ptCount
&& result
== B_OK
; i
++)
215 result
= archive
->AddPoint("pts", data
->ptList
[i
]);
217 // Avoids allocation for each op
218 if (result
== B_OK
) {
219 result
= archive
->AddData("ops", B_INT32_TYPE
, data
->opList
,
220 sizeof(int32
), true, data
->opCount
);
223 for (int32 i
= 1; i
< data
->opCount
&& result
== B_OK
; i
++)
224 result
= archive
->AddInt32("ops", data
->opList
[i
]);
231 BShape::Instantiate(BMessage
* archive
)
233 if (validate_instantiation(archive
, "BShape"))
234 return new BShape(archive
);
241 BShape::operator=(const BShape
& other
)
243 if (this != &other
) {
253 BShape::operator==(const BShape
& other
) const
258 shape_data
* data
= (shape_data
*)fPrivateData
;
259 shape_data
* otherData
= (shape_data
*)other
.fPrivateData
;
261 if (data
->opCount
!= otherData
->opCount
)
264 if (data
->ptCount
!= otherData
->ptCount
)
267 return memcmp(data
->opList
, otherData
->opList
,
268 data
->opCount
* sizeof(uint32
)) == 0
269 && memcmp(data
->ptList
, otherData
->ptList
,
270 data
->ptCount
* sizeof(BPoint
)) == 0;
275 BShape::operator!=(const BShape
& other
) const
277 return !(*this == other
);
284 shape_data
* data
= (shape_data
*)fPrivateData
;
306 BShape::Bounds() const
308 shape_data
* data
= (shape_data
*)fPrivateData
;
311 if (data
->ptCount
== 0)
314 // TODO: This implementation doesn't take into account curves at all.
315 bounds
.left
= data
->ptList
[0].x
;
316 bounds
.top
= data
->ptList
[0].y
;
317 bounds
.right
= data
->ptList
[0].x
;
318 bounds
.bottom
= data
->ptList
[0].y
;
320 for (int32 i
= 1; i
< data
->ptCount
; i
++) {
321 if (bounds
.left
> data
->ptList
[i
].x
)
322 bounds
.left
= data
->ptList
[i
].x
;
324 if (bounds
.top
> data
->ptList
[i
].y
)
325 bounds
.top
= data
->ptList
[i
].y
;
327 if (bounds
.right
< data
->ptList
[i
].x
)
328 bounds
.right
= data
->ptList
[i
].x
;
330 if (bounds
.bottom
< data
->ptList
[i
].y
)
331 bounds
.bottom
= data
->ptList
[i
].y
;
339 BShape::CurrentPosition() const
341 shape_data
* data
= (shape_data
*)fPrivateData
;
343 if (data
->ptCount
== 0)
346 return data
->ptList
[data
->ptCount
- 1];
351 BShape::AddShape(const BShape
* otherShape
)
353 shape_data
* data
= (shape_data
*)fPrivateData
;
354 shape_data
* otherData
= (shape_data
*)otherShape
->fPrivateData
;
356 if (!AllocateOps(otherData
->opCount
) || !AllocatePts(otherData
->ptCount
))
359 memcpy(data
->opList
+ data
->opCount
, otherData
->opList
,
360 otherData
->opCount
* sizeof(uint32
));
361 data
->opCount
+= otherData
->opCount
;
363 memcpy(data
->ptList
+ data
->ptCount
, otherData
->ptList
,
364 otherData
->ptCount
* sizeof(BPoint
));
365 data
->ptCount
+= otherData
->ptCount
;
367 fBuildingOp
= otherShape
->fBuildingOp
;
374 BShape::MoveTo(BPoint point
)
376 shape_data
* data
= (shape_data
*)fPrivateData
;
378 // If the last op is MoveTo, replace the point
379 if (fBuildingOp
== OP_MOVETO
) {
380 data
->ptList
[data
->ptCount
- 1] = point
;
384 if (!AllocateOps(1) || !AllocatePts(1))
387 fBuildingOp
= OP_MOVETO
;
390 data
->opList
[data
->opCount
++] = fBuildingOp
;
393 data
->ptList
[data
->ptCount
++] = point
;
400 BShape::LineTo(BPoint point
)
405 shape_data
* data
= (shape_data
*)fPrivateData
;
407 // If the last op is MoveTo, replace the op and set the count
408 // If the last op is LineTo increase the count
409 // Otherwise add the op
410 if (fBuildingOp
& OP_LINETO
|| fBuildingOp
== OP_MOVETO
) {
411 fBuildingOp
|= OP_LINETO
;
413 data
->opList
[data
->opCount
- 1] = fBuildingOp
;
418 fBuildingOp
= OP_LINETO
+ 1;
419 data
->opList
[data
->opCount
++] = fBuildingOp
;
423 data
->ptList
[data
->ptCount
++] = point
;
430 BShape::BezierTo(BPoint controlPoints
[3])
432 return BezierTo(controlPoints
[0], controlPoints
[1], controlPoints
[2]);
437 BShape::BezierTo(const BPoint
& control1
, const BPoint
& control2
,
438 const BPoint
& endPoint
)
443 shape_data
* data
= (shape_data
*)fPrivateData
;
445 // If the last op is MoveTo, replace the op and set the count
446 // If the last op is BezierTo increase the count
447 // Otherwise add the op
448 if (fBuildingOp
& OP_BEZIERTO
|| fBuildingOp
== OP_MOVETO
) {
449 fBuildingOp
|= OP_BEZIERTO
;
451 data
->opList
[data
->opCount
- 1] = fBuildingOp
;
455 fBuildingOp
= OP_BEZIERTO
+ 3;
456 data
->opList
[data
->opCount
++] = fBuildingOp
;
460 data
->ptList
[data
->ptCount
++] = control1
;
461 data
->ptList
[data
->ptCount
++] = control2
;
462 data
->ptList
[data
->ptCount
++] = endPoint
;
469 BShape::ArcTo(float rx
, float ry
, float angle
, bool largeArc
,
470 bool counterClockWise
, const BPoint
& point
)
475 shape_data
* data
= (shape_data
*)fPrivateData
;
479 if (counterClockWise
)
480 op
= OP_LARGE_ARC_TO_CCW
;
482 op
= OP_LARGE_ARC_TO_CW
;
484 if (counterClockWise
)
485 op
= OP_SMALL_ARC_TO_CCW
;
487 op
= OP_SMALL_ARC_TO_CW
;
490 // If the last op is MoveTo, replace the op and set the count
491 // If the last op is ArcTo increase the count
492 // Otherwise add the op
493 if (fBuildingOp
== op
|| fBuildingOp
== (op
| OP_MOVETO
)) {
496 data
->opList
[data
->opCount
- 1] = fBuildingOp
;
501 fBuildingOp
= op
+ 3;
502 data
->opList
[data
->opCount
++] = fBuildingOp
;
506 data
->ptList
[data
->ptCount
++] = BPoint(rx
, ry
);
507 data
->ptList
[data
->ptCount
++] = BPoint(angle
, 0);
508 data
->ptList
[data
->ptCount
++] = point
;
517 // If the last op is Close or MoveTo, ignore this
518 if (fBuildingOp
== OP_CLOSE
|| fBuildingOp
== OP_MOVETO
)
524 shape_data
* data
= (shape_data
*)fPrivateData
;
526 // ToDo: Decide about that, it's not BeOS compatible
527 // If there was any op before we can attach the close to it
529 fBuildingOp |= OP_CLOSE;
530 data->opList[data->opCount - 1] = fBuildingOp;
534 fBuildingOp
= OP_CLOSE
;
535 data
->opList
[data
->opCount
++] = fBuildingOp
;
541 // #pragma mark - BShape private methods
545 BShape::Perform(perform_code code
, void* data
)
547 return BArchivable::Perform(code
, data
);
551 // #pragma mark - BShape FBC methods
554 void BShape::_ReservedShape1() {}
555 void BShape::_ReservedShape2() {}
556 void BShape::_ReservedShape3() {}
557 void BShape::_ReservedShape4() {}
560 // #pragma mark - BShape private methods
564 BShape::GetData(int32
* opCount
, int32
* ptCount
, uint32
** opList
,
567 shape_data
* data
= (shape_data
*)fPrivateData
;
569 *opCount
= data
->opCount
;
570 *ptCount
= data
->ptCount
;
571 *opList
= data
->opList
;
572 *ptList
= data
->ptList
;
577 BShape::SetData(int32 opCount
, int32 ptCount
, const uint32
* opList
,
578 const BPoint
* ptList
)
585 shape_data
* data
= (shape_data
*)fPrivateData
;
587 if (!AllocateOps(opCount
) || !AllocatePts(ptCount
))
590 memcpy(data
->opList
, opList
, opCount
* sizeof(uint32
));
591 data
->opCount
= opCount
;
592 fBuildingOp
= data
->opList
[data
->opCount
- 1];
595 memcpy(data
->ptList
, ptList
, ptCount
* sizeof(BPoint
));
596 data
->ptCount
= ptCount
;
604 fPrivateData
= new shape_data
;
605 shape_data
* data
= (shape_data
*)fPrivateData
;
620 BShape::AllocateOps(int32 count
)
622 shape_data
* data
= (shape_data
*)fPrivateData
;
624 int32 newSize
= (data
->opCount
+ count
+ 255) / 256 * 256;
625 if (data
->opSize
>= newSize
)
628 uint32
* resizedArray
= (uint32
*)realloc(data
->opList
, newSize
* sizeof(uint32
));
630 data
->opList
= resizedArray
;
631 data
->opSize
= newSize
;
639 BShape::AllocatePts(int32 count
)
641 shape_data
* data
= (shape_data
*)fPrivateData
;
643 int32 newSize
= (data
->ptCount
+ count
+ 255) / 256 * 256;
644 if (data
->ptSize
>= newSize
)
647 BPoint
* resizedArray
= (BPoint
*)realloc(data
->ptList
, newSize
* sizeof(BPoint
));
649 data
->ptList
= resizedArray
;
650 data
->ptSize
= newSize
;
657 // #pragma mark - BShape binary compatibility methods
664 __6BShapeR6BShape(void* self
, BShape
& copyFrom
)
666 return new (self
) BShape(copyFrom
);
667 // we need to instantiate the object in the provided memory
672 Bounds__6BShape(BShape
* self
)
674 return self
->Bounds();
679 _ReservedShapeIterator1__14BShapeIterator(BShapeIterator
* self
)
684 #else // __GNUC__ < 3
688 _ZN14BShapeIterator23_ReservedShapeIterator1Ev(BShapeIterator
* self
)
693 #endif // __GNUC__ >= 3