Fixed and cleaned up BShape and BShapeIterator. They should now work and behave like the R5 version.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16230 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2006-02-04 22:11:57 +00:00
parent 57a6c095d5
commit ec56c2c1dc
2 changed files with 137 additions and 201 deletions
+6 -9
View File
@@ -1,12 +1,7 @@
/******************************************************************************* /*
/ * Copyright 2006, Haiku, Inc. All Rights Reserved.
/ File: Shape.h * Distributed under the terms of the MIT License.
/ */
/ Description: BShape encapsulates a Postscript-style "path"
/
/ Copyright 1992-98, Be Incorporated, All Rights Reserved
/
*******************************************************************************/
#ifndef _SHAPE_H #ifndef _SHAPE_H
#define _SHAPE_H #define _SHAPE_H
@@ -88,6 +83,8 @@ virtual void _ReservedShape4();
void GetData(int32 *opCount, int32 *ptCount, uint32 **opList, BPoint **ptList); void GetData(int32 *opCount, int32 *ptCount, uint32 **opList, BPoint **ptList);
void SetData(int32 opCount, int32 ptCount, uint32 *opList, BPoint *ptList); void SetData(int32 opCount, int32 ptCount, uint32 *opList, BPoint *ptList);
void InitData(); void InitData();
void AllocatePts(int32 count);
void AllocateOps(int32 count);
uint32 fState; uint32 fState;
uint32 fBuildingOp; uint32 fBuildingOp;
+131 -192
View File
@@ -1,10 +1,11 @@
/* /*
* Copyright (c) 2001-2005, Haiku, Inc. * Copyright (c) 2001-2006, Haiku, Inc.
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
* *
* Authors: * Authors:
* Marc Flerackers ([email protected]) * Marc Flerackers ([email protected])
* Stephan Aßmus <[email protected]> * Stephan Aßmus <[email protected]>
* Michael Lotz <[email protected]>
* *
* Description: * Description:
* BShape encapsulates a Postscript-style "path" * BShape encapsulates a Postscript-style "path"
@@ -57,40 +58,27 @@ BShapeIterator::Iterate(BShape *shape)
BPoint *points = data->ptList; BPoint *points = data->ptList;
for (int32 i = 0; i < data->opCount; i++) { for (int32 i = 0; i < data->opCount; i++) {
switch (data->opList[i] & 0xFF000000) { int32 op = data->opList[i] & 0xFF000000;
case OP_LINETO: {
int32 count = data->opList[i] & 0x00FFFFFF; if (op & OP_MOVETO) {
IterateLineTo(count, points); IterateMoveTo(points);
points += count; points++;
break; }
}
case (OP_MOVETO | OP_LINETO): { if (op & OP_LINETO) {
int32 count = data->opList[i] & 0x00FFFFFF; int32 count = data->opList[i] & 0x00FFFFFF;
IterateMoveTo(points); IterateLineTo(count, points);
points++; points += count;
IterateLineTo(count, points); }
points += count;
break; if (op & OP_BEZIERTO) {
} int32 count = data->opList[i] & 0x00FFFFFF;
case OP_BEZIERTO: { IterateBezierTo(count / 3, points);
int32 count = data->opList[i] & 0x00FFFFFF; points += count;
IterateBezierTo(count, points); }
points += count;
break; if (op & OP_CLOSE) {
} IterateClose();
case (OP_MOVETO | OP_BEZIERTO): {
int32 count = data->opList[i] & 0x00FFFFFF;
IterateMoveTo(points);
points++;
IterateBezierTo(count, points);
points += count;
break;
}
case OP_CLOSE:
case OP_CLOSE | OP_LINETO | OP_BEZIERTO: {
IterateClose();
break;
}
} }
} }
@@ -152,35 +140,25 @@ BShape::BShape(BMessage *archive)
InitData(); InitData();
shape_data *data = (shape_data*)fPrivateData; shape_data *data = (shape_data*)fPrivateData;
ssize_t size;
ssize_t size = 0;
int32 count = 0;
type_code type = 0;
archive->GetInfo("ops", &type, &count);
AllocateOps(count);
int32 i = 0; int32 i = 0;
const uint32 *opPtr; const uint32 *opPtr;
while (archive->FindData("ops", B_INT32_TYPE, i++, (const void **)&opPtr, &size) == B_OK)
while (archive->FindData("ops", B_INT32_TYPE, i++, (const void**)&opPtr, &size) == B_OK) {
if (data->opSize < data->opCount + 1) {
int32 new_size = ((data->opCount + data->opBlockSize) /
data->opBlockSize) * data->opBlockSize;
data->opList = (uint32*)realloc(data->opList, new_size * sizeof(uint32));
data->opSize = new_size;
}
data->opList[data->opCount++] = *opPtr; data->opList[data->opCount++] = *opPtr;
}
archive->GetInfo("pts", &type, &count);
AllocatePts(count);
i = 0;
const BPoint *ptPtr; const BPoint *ptPtr;
while (archive->FindData("pts", B_POINT_TYPE, i++, (const void **)&ptPtr, &size) == B_OK)
while (archive->FindData("pts", B_POINT_TYPE, i++, (const void**)&ptPtr, &size) == B_OK) {
if (data->ptSize < data->ptCount + 1) {
int32 new_size = ((data->ptCount + data->ptBlockSize) /
data->ptBlockSize) * data->ptBlockSize;
data->ptList = (BPoint*)realloc(data->ptList,
new_size * sizeof(BPoint));
data->ptSize = new_size;
}
data->ptList[data->ptCount++] = *ptPtr; data->ptList[data->ptCount++] = *ptPtr;
}
} }
@@ -198,35 +176,32 @@ BShape::~BShape()
status_t status_t
BShape::Archive(BMessage *archive, bool deep) const BShape::Archive(BMessage *archive, bool deep) const
{ {
status_t err = BArchivable::Archive(archive, deep); status_t error = BArchivable::Archive(archive, deep);
int32 i;
if (err != B_OK) if (error != B_OK)
return err; return error;
shape_data *data = (shape_data*)fPrivateData; shape_data *data = (shape_data*)fPrivateData;
// If no valid shape data, return // If no valid shape data, return
if (data->opCount == 0 || data->ptCount == 0) if (data->opCount == 0 || data->ptCount == 0)
return err; return error;
// Avoids allocation for each point // Avoids allocation for each point
archive->AddData("pts", B_POINT_TYPE, data->ptList, sizeof(BPoint), true, archive->AddData("pts", B_POINT_TYPE, data->ptList, sizeof(BPoint), true,
data->ptCount); data->ptCount);
for (i = 1; i < data->ptCount; i++) for (int32 i = 1; i < data->ptCount; i++)
archive->AddPoint("pts", data->ptList[i]); archive->AddPoint("pts", data->ptList[i]);
// Avoids allocation for each op // Avoids allocation for each op
archive->AddData("ops", B_INT32_TYPE, data->opList, sizeof(int32), true, archive->AddData("ops", B_INT32_TYPE, data->opList, sizeof(int32), true,
data->opCount); data->opCount);
for (i = 1; i < data->opCount; i++) for (int32 i = 1; i < data->opCount; i++)
archive->AddInt32("ops", data->opList[i]); archive->AddInt32("ops", data->opList[i]);
archive->AddInt32("ops", fBuildingOp); return error;
return err;
} }
@@ -245,18 +220,18 @@ BShape::Clear()
{ {
shape_data *data = (shape_data*)fPrivateData; shape_data *data = (shape_data*)fPrivateData;
data->opCount = 0;
data->opSize = 0;
if (data->opList) { if (data->opList) {
free(data->opList); free(data->opList);
data->opList = NULL; data->opList = NULL;
data->opCount = 0;
data->opSize = 0;
} }
data->ptCount = 0;
data->ptSize = 0;
if (data->ptList) { if (data->ptList) {
free(data->ptList); free(data->ptList);
data->ptList = NULL; data->ptList = NULL;
data->ptCount = 0;
data->ptSize = 0;
} }
fState = 0; fState = 0;
@@ -280,14 +255,14 @@ BShape::Bounds() const
for (int32 i = 1; i < data->ptCount; i++) for (int32 i = 1; i < data->ptCount; i++)
{ {
if (bounds.left > data->ptList[0].x) if (bounds.left > data->ptList[i].x)
bounds.left = data->ptList[0].x; bounds.left = data->ptList[i].x;
if (bounds.top > data->ptList[0].y) if (bounds.top > data->ptList[i].y)
bounds.top = data->ptList[0].y; bounds.top = data->ptList[i].y;
if (bounds.right < data->ptList[0].x) if (bounds.right < data->ptList[i].x)
bounds.right = data->ptList[0].x; bounds.right = data->ptList[i].x;
if (bounds.bottom < data->ptList[0].y) if (bounds.bottom < data->ptList[i].y)
bounds.bottom = data->ptList[0].y; bounds.bottom = data->ptList[i].y;
} }
return bounds; return bounds;
@@ -300,26 +275,12 @@ BShape::AddShape(const BShape *otherShape)
shape_data *data = (shape_data*)fPrivateData; shape_data *data = (shape_data*)fPrivateData;
shape_data *otherData = (shape_data*)otherShape->fPrivateData; shape_data *otherData = (shape_data*)otherShape->fPrivateData;
if (data->opSize < data->opCount + otherData->opCount) AllocateOps(otherData->opCount);
{
int32 new_size = ((data->opCount + otherData->opBlockSize) /
data->opBlockSize) * data->opBlockSize;
data->opList = (uint32*)realloc(data->opList, new_size * sizeof(uint32));
data->opSize = new_size;
}
memcpy(data->opList + data->opCount * sizeof(uint32), otherData->opList, memcpy(data->opList + data->opCount * sizeof(uint32), otherData->opList,
otherData->opCount * sizeof(uint32)); otherData->opCount * sizeof(uint32));
data->opCount += otherData->opCount; data->opCount += otherData->opCount;
if (data->ptSize < data->ptCount + otherData->ptCount) AllocatePts(otherData->ptCount);
{
int32 new_size = ((data->ptCount + otherData->ptBlockSize) /
data->ptBlockSize) * data->ptBlockSize;
data->ptList = (BPoint*)realloc(data->ptList, new_size * sizeof(uint32));
data->ptSize = new_size;
}
memcpy(data->ptList + data->ptCount * sizeof(BPoint), otherData->ptList, memcpy(data->ptList + data->ptCount * sizeof(BPoint), otherData->ptList,
otherData->ptCount * sizeof(BPoint)); otherData->ptCount * sizeof(BPoint));
data->ptCount += otherData->ptCount; data->ptCount += otherData->ptCount;
@@ -336,24 +297,19 @@ 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 the last op is MoveTo, replace the point
// If there was a previous op, add the op
if (fBuildingOp == OP_MOVETO) { if (fBuildingOp == OP_MOVETO) {
data->ptList[data->ptCount - 1] = point; data->ptList[data->ptCount - 1] = point;
return B_OK; return B_OK;
} }
// BuildingOp is MoveTo
fBuildingOp = OP_MOVETO; fBuildingOp = OP_MOVETO;
// Add point // Add op
if (data->ptSize < data->ptCount + 1) { AllocateOps(1);
int32 new_size = ((data->ptCount + data->ptBlockSize) / data->opList[data->opCount++] = fBuildingOp;
data->ptBlockSize) * data->ptBlockSize;
data->ptList = (BPoint*)realloc(data->ptList, new_size * sizeof(BPoint));
data->ptSize = new_size;
}
// Add point
AllocatePts(1);
data->ptList[data->ptCount++] = point; data->ptList[data->ptCount++] = point;
return B_OK; return B_OK;
@@ -367,36 +323,19 @@ BShape::LineTo(BPoint point)
// If the last op is MoveTo, replace the op and set the count // If the last op is MoveTo, replace the op and set the count
// If the last op is LineTo increase the count // If the last op is LineTo increase the count
// If there was a previous op, add the op // Otherwise add the op
bool newOp = true; if (fBuildingOp & OP_LINETO || fBuildingOp == OP_MOVETO) {
if (fBuildingOp == OP_MOVETO) { fBuildingOp |= OP_LINETO;
fBuildingOp = OP_LINETO | OP_MOVETO; fBuildingOp += 1;
} else if (fBuildingOp & OP_LINETO) { data->opList[data->opCount - 1] = fBuildingOp;
newOp = false;
} else { } else {
fBuildingOp = OP_LINETO; fBuildingOp = OP_LINETO + 1;
AllocateOps(1);
data->opList[data->opCount++] = fBuildingOp;
} }
fBuildingOp++;
if (newOp) {
if (data->opSize < data->opCount + 1) {
int32 new_size = ((data->opCount + data->opBlockSize) /
data->opBlockSize) * data->opBlockSize;
data->opList = (uint32*)realloc(data->opList, new_size * sizeof(uint32));
data->opSize = new_size;
}
data->opCount++;
}
data->opList[data->opCount - 1] = fBuildingOp;
// Add point // Add point
if (data->ptSize < data->ptCount + 1) { AllocatePts(1);
int32 new_size = ((data->ptCount + data->ptBlockSize) /
data->ptBlockSize) * data->ptBlockSize;
data->ptList = (BPoint*)realloc(data->ptList, new_size * sizeof(BPoint));
data->ptSize = new_size;
}
data->ptList[data->ptCount++] = point; data->ptList[data->ptCount++] = point;
return B_OK; return B_OK;
@@ -410,38 +349,19 @@ BShape::BezierTo(BPoint controlPoints[3])
// If the last op is MoveTo, replace the op and set the count // If the last op is MoveTo, replace the op and set the count
// If the last op is BezierTo increase the count // If the last op is BezierTo increase the count
// If there was a previous op, add the op // Otherwise add the op
bool newOp = true; if (fBuildingOp & OP_BEZIERTO || fBuildingOp == OP_MOVETO) {
if (fBuildingOp == OP_MOVETO) { fBuildingOp |= OP_BEZIERTO;
fBuildingOp = OP_BEZIERTO | OP_MOVETO; fBuildingOp += 3;
} else if (fBuildingOp & OP_BEZIERTO) { data->opList[data->opCount - 1] = fBuildingOp;
newOp = false;
} else { } else {
fBuildingOp = OP_BEZIERTO; fBuildingOp = OP_BEZIERTO + 3;
AllocateOps(1);
data->opList[data->opCount++] = fBuildingOp;
} }
fBuildingOp += 3;
if (newOp) {
if (data->opSize < data->opCount + 1) {
int32 new_size = ((data->opCount + data->opBlockSize) /
data->opBlockSize) * data->opBlockSize;
data->opList = (uint32*)realloc(data->opList, new_size * sizeof(uint32));
data->opSize = new_size;
}
data->opCount++;
}
data->opList[data->opCount - 1] = fBuildingOp;
// Add points // Add points
if (data->ptSize < data->ptCount + 3) AllocatePts(3);
{
int32 new_size = ((data->ptCount + data->ptBlockSize) /
data->ptBlockSize) * data->ptBlockSize;
data->ptList = (BPoint*)realloc(data->ptList, new_size * sizeof(BPoint));
data->ptSize = new_size;
}
data->ptList[data->ptCount++] = controlPoints[0]; data->ptList[data->ptCount++] = controlPoints[0];
data->ptList[data->ptCount++] = controlPoints[1]; data->ptList[data->ptCount++] = controlPoints[1];
data->ptList[data->ptCount++] = controlPoints[2]; data->ptList[data->ptCount++] = controlPoints[2];
@@ -455,18 +375,22 @@ BShape::Close()
{ {
shape_data *data = (shape_data*)fPrivateData; shape_data *data = (shape_data*)fPrivateData;
// If there was a previous line/bezier op, add the op // If the last op is Close or MoveTo, ignore this
if (fBuildingOp & (OP_LINETO | OP_BEZIERTO)) { if (fBuildingOp == OP_CLOSE || fBuildingOp == OP_MOVETO)
if (data->opSize < data->opCount + 1) { return B_OK;
int32 new_size = ((data->opCount + data->opBlockSize) /
data->opBlockSize) * data->opBlockSize;
data->opList = (uint32*)realloc(data->opList, new_size * sizeof(uint32));
data->opSize = new_size;
}
data->opList[data->opCount++] = fBuildingOp;
fBuildingOp = OP_CLOSE; // ToDo: Decide about that, it's not BeOS compatible
} // If there was any op before we can attach the close to it
/*if (fBuildingOp) {
fBuildingOp |= OP_CLOSE;
data->opList[data->opCount - 1] = fBuildingOp;
return B_OK;
}*/
fBuildingOp = OP_CLOSE;
AllocateOps(1);
data->opList[data->opCount++] = fBuildingOp;
return B_OK; return B_OK;
} }
@@ -502,27 +426,16 @@ void
BShape::SetData(int32 opCount, int32 ptCount, uint32 *opList, BShape::SetData(int32 opCount, int32 ptCount, uint32 *opList,
BPoint *ptList) BPoint *ptList)
{ {
Clear();
shape_data *data = (shape_data*)fPrivateData; shape_data *data = (shape_data*)fPrivateData;
if (data->opSize < opCount) { AllocateOps(opCount);
int32 new_size = ((opCount + data->opBlockSize) /
data->opBlockSize) * data->opBlockSize;
data->opList = (uint32*)realloc(data->opList, new_size * sizeof(uint32));
data->opSize = new_size;
}
memcpy(data->opList, opList, opCount * sizeof(uint32)); memcpy(data->opList, opList, opCount * sizeof(uint32));
data->opCount = opCount; data->opCount = opCount;
fBuildingOp = data->opList[data->opCount - 1];
if (data->ptSize < ptCount) { AllocatePts(ptCount);
int32 new_size = ((ptCount + data->ptBlockSize) /
data->ptBlockSize) * data->ptBlockSize;
data->ptList = (BPoint*)realloc(data->ptList, new_size * sizeof(BPoint));
data->ptSize = new_size;
}
memcpy(data->ptList, ptList, ptCount * sizeof(BPoint)); memcpy(data->ptList, ptList, ptCount * sizeof(BPoint));
data->ptCount = ptCount; data->ptCount = ptCount;
} }
@@ -548,6 +461,36 @@ BShape::InitData()
} }
inline void
BShape::AllocateOps(int32 count)
{
shape_data *data = (shape_data*)fPrivateData;
while (data->opSize < data->opCount + count) {
int32 new_size = ((data->opCount + data->opBlockSize) /
data->opBlockSize) * data->opBlockSize;
data->opList = (uint32*)realloc(data->opList, new_size * sizeof(uint32));
data->opSize = new_size;
count -= data->opBlockSize;
}
}
inline void
BShape::AllocatePts(int32 count)
{
shape_data *data = (shape_data*)fPrivateData;
while (data->ptSize < data->ptCount + count) {
int32 new_size = ((data->ptCount + data->ptBlockSize) /
data->ptBlockSize) * data->ptBlockSize;
data->ptList = (BPoint*)realloc(data->ptList, new_size * sizeof(BPoint));
data->ptSize = new_size;
count -= data->ptBlockSize;
}
}
// #pragma mark - // #pragma mark -
// R4.5 compatibility // R4.5 compatibility
@@ -560,8 +503,4 @@ Bounds__6BShape(BShape *self)
return self->Bounds(); return self->Bounds();
} }
// ToDo: Add those:
// BShape(BShape &copyFrom);
// status_t AddShape(BShape *other);
#endif // __GNUC__ < 3 #endif // __GNUC__ < 3