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 git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35905 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fe0963a835
commit
76ab3f88df
@ -30,10 +30,13 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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:
|
||||
|
@ -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 {
|
||||
|
@ -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 @@ BShapeIterator::~BShapeIterator()
|
||||
|
||||
|
||||
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 @@ BShapeIterator::Iterate(BShape *shape)
|
||||
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,8 +84,21 @@ BShapeIterator::Iterate(BShape *shape)
|
||||
|
||||
|
||||
status_t
|
||||
BShapeIterator::IterateBezierTo(int32 bezierCount,
|
||||
BPoint *bezierPoints)
|
||||
BShapeIterator::IterateMoveTo(BPoint* point)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BShapeIterator::IterateLineTo(int32 lineCount, BPoint* linePoints)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BShapeIterator::IterateBezierTo(int32 bezierCount, BPoint* bezierPoints)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
@ -87,25 +112,21 @@ BShapeIterator::IterateClose()
|
||||
|
||||
|
||||
status_t
|
||||
BShapeIterator::IterateLineTo(int32 lineCount, BPoint *linePoints)
|
||||
BShapeIterator::IterateArcTo(float& rx, float& ry, float& angle, bool largeArc,
|
||||
bool counterClockWise, BPoint& point)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BShapeIterator::IterateMoveTo ( BPoint *point )
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void BShapeIterator::_ReservedShapeIterator1() {}
|
||||
void BShapeIterator::_ReservedShapeIterator2() {}
|
||||
void BShapeIterator::_ReservedShapeIterator3() {}
|
||||
void BShapeIterator::_ReservedShapeIterator4() {}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BShape::BShape()
|
||||
{
|
||||
InitData();
|
||||
@ -119,12 +140,12 @@ BShape::BShape(const BShape ©From)
|
||||
}
|
||||
|
||||
|
||||
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 @@ BShape::BShape(BMessage *archive)
|
||||
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 @@ BShape::BShape(BMessage *archive)
|
||||
}
|
||||
|
||||
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 @@ BShape::~BShape()
|
||||
|
||||
|
||||
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 @@ BShape::Archive(BMessage *archive, bool deep) const
|
||||
|
||||
|
||||
BArchivable*
|
||||
BShape::Instantiate(BMessage *archive)
|
||||
BShape::Instantiate(BMessage* archive)
|
||||
{
|
||||
if (validate_instantiation(archive, "BShape"))
|
||||
return new BShape(archive);
|
||||
@ -207,10 +228,50 @@ BShape::Instantiate(BMessage *archive)
|
||||
}
|
||||
|
||||
|
||||
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 @@ BShape::Clear()
|
||||
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 @@ BShape::Bounds() const
|
||||
|
||||
|
||||
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 @@ BShape::AddShape(const BShape *otherShape)
|
||||
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 @@ BShape::LineTo(BPoint point)
|
||||
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
|
||||
@ -341,11 +402,19 @@ BShape::LineTo(BPoint point)
|
||||
|
||||
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,9 +431,54 @@ BShape::BezierTo(BPoint controlPoints[3])
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
@ -380,7 +494,7 @@ BShape::Close()
|
||||
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 @@ BShape::Close()
|
||||
|
||||
|
||||
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::_ReservedShape4() {}
|
||||
|
||||
|
||||
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 @@ BShape::GetData(int32 *opCount, int32 *ptCount, uint32 **opList,
|
||||
|
||||
|
||||
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 @@ void
|
||||
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 @@ BShape::InitData()
|
||||
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 @@ BShape::AllocateOps(int32 count)
|
||||
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 @@ BShape::AllocatePts(int32 count)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - R4.5 compatibility
|
||||
// #pragma mark - binary compatibility
|
||||
|
||||
|
||||
#if __GNUC__ < 3
|
||||
|
||||
|
||||
extern "C" BShape*
|
||||
__6BShapeR6BShape(void* self, BShape& copyFrom)
|
||||
{
|
||||
@ -520,9 +635,25 @@ __6BShapeR6BShape(void* self, BShape& copyFrom)
|
||||
|
||||
|
||||
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
|
||||
|
@ -42,7 +42,7 @@ using std::stack;
|
||||
|
||||
class ShapePainter : public BShapeIterator {
|
||||
public:
|
||||
ShapePainter();
|
||||
ShapePainter(View* view);
|
||||
virtual ~ShapePainter();
|
||||
|
||||
status_t Iterate(const BShape* shape);
|
||||
@ -51,16 +51,21 @@ public:
|
||||
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 @@ ShapePainter::Iterate(const BShape* shape)
|
||||
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 @@ ShapePainter::IterateMoveTo(BPoint* point)
|
||||
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 @@ status_t
|
||||
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 @@ ShapePainter::Draw(View* view, BRect frame, bool filled)
|
||||
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 @@ fill_polygon(View* view, int32 numPoints, const BPoint* viewPoints)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2541,18 +2541,16 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
|
||||
// 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 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code,
|
||||
|
||||
// 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;
|
||||
|
@ -150,7 +150,7 @@ DrawingEngine::LockExclusiveAccess()
|
||||
|
||||
|
||||
bool
|
||||
DrawingEngine::IsExclusiveAccessLocked()
|
||||
DrawingEngine::IsExclusiveAccessLocked() const
|
||||
{
|
||||
return fGraphicsCard->IsExclusiveAccessLocked();
|
||||
}
|
||||
@ -1141,16 +1141,30 @@ DrawingEngine::FillRoundRect(BRect r, float xrad, float yrad,
|
||||
|
||||
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 @@ DrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
|
||||
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);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
void UnlockParallelAccess();
|
||||
|
||||
bool LockExclusiveAccess();
|
||||
virtual bool IsExclusiveAccessLocked();
|
||||
virtual bool IsExclusiveAccessLocked() const;
|
||||
void UnlockExclusiveAccess();
|
||||
|
||||
// for screen shots
|
||||
@ -138,11 +138,14 @@ public:
|
||||
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);
|
||||
|
@ -668,28 +668,31 @@ Painter::FillBezier(BPoint* p, const BGradient& gradient) const
|
||||
}
|
||||
|
||||
|
||||
// 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,16 +700,51 @@ Painter::DrawShape(const int32& opCount, const uint32* opList,
|
||||
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
|
||||
BRect
|
||||
Painter::DrawShape(const int32& opCount, const uint32* opList,
|
||||
const int32& ptCount, const BPoint* points, bool filled,
|
||||
const BPoint& viewToScreenOffset, float viewScale) const
|
||||
{
|
||||
CHECK_CLIPPING
|
||||
|
||||
iterate_shape_data(fPath, opCount, opList, ptCount, points,
|
||||
viewToScreenOffset, viewScale);
|
||||
|
||||
if (filled)
|
||||
return _FillPath(fCurve);
|
||||
@ -718,42 +756,13 @@ Painter::DrawShape(const int32& opCount, const uint32* opList,
|
||||
// FillShape
|
||||
BRect
|
||||
Painter::FillShape(const int32& opCount, const uint32* opList,
|
||||
const int32& ptCount, const BPoint* points, const BGradient& gradient) const
|
||||
const int32& ptCount, const BPoint* points, const BGradient& gradient,
|
||||
const BPoint& viewToScreenOffset, float viewScale) const
|
||||
{
|
||||
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();
|
||||
for (int32 i = 0; i < opCount; i++) {
|
||||
uint32 op = opList[i] & 0xFF000000;
|
||||
if (op & OP_MOVETO) {
|
||||
fPath.move_to(points->x, points->y);
|
||||
points++;
|
||||
}
|
||||
|
||||
if (op & OP_LINETO) {
|
||||
int32 count = opList[i] & 0x00FFFFFF;
|
||||
while (count--) {
|
||||
fPath.line_to(points->x, points->y);
|
||||
points++;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
points += 3;
|
||||
count -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (op & OP_CLOSE)
|
||||
fPath.close_polygon();
|
||||
}
|
||||
iterate_shape_data(fPath, opCount, opList, ptCount, points,
|
||||
viewToScreenOffset, viewScale);
|
||||
|
||||
return _FillPath(fCurve, gradient);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class Transformable;
|
||||
|
||||
|
||||
class Painter {
|
||||
public:
|
||||
public:
|
||||
Painter();
|
||||
virtual ~Painter();
|
||||
|
||||
@ -132,12 +132,15 @@ class Painter {
|
||||
// shapes
|
||||
BRect DrawShape(const int32& opCount,
|
||||
const uint32* opList, const int32& ptCount,
|
||||
const BPoint* ptList, bool filled) const;
|
||||
const BPoint* ptList, bool filled,
|
||||
const BPoint& viewToScreenOffset,
|
||||
float viewScale) const;
|
||||
BRect FillShape(const int32& opCount,
|
||||
const uint32* opList,
|
||||
const int32& ptCount,
|
||||
const uint32* opList, const int32& ptCount,
|
||||
const BPoint* ptList,
|
||||
const BGradient& gradient) const;
|
||||
const BGradient& gradient,
|
||||
const BPoint& viewToScreenOffset,
|
||||
float viewScale) const;
|
||||
|
||||
// rects
|
||||
BRect StrokeRect(const BRect& r) const;
|
||||
@ -237,7 +240,7 @@ class Painter {
|
||||
inline BRect AlignAndClipRect(BRect rect) const;
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
void _Transform(BPoint* point,
|
||||
bool centerOffset = true) const;
|
||||
BPoint _Transform(const BPoint& point,
|
||||
@ -330,46 +333,46 @@ class Painter {
|
||||
void _FillPathGradientConic(VertexSource& path,
|
||||
const BGradientConic& conic) const;
|
||||
|
||||
mutable agg::rendering_buffer fBuffer;
|
||||
mutable agg::rendering_buffer fBuffer;
|
||||
|
||||
// AGG rendering and rasterization classes
|
||||
pixfmt fPixelFormat;
|
||||
mutable renderer_base fBaseRenderer;
|
||||
pixfmt fPixelFormat;
|
||||
mutable renderer_base fBaseRenderer;
|
||||
|
||||
mutable scanline_unpacked_type fUnpackedScanline;
|
||||
mutable scanline_packed_type fPackedScanline;
|
||||
mutable scanline_packed_subpix_type fSubpixPackedScanline;
|
||||
mutable scanline_unpacked_subpix_type fSubpixUnpackedScanline;
|
||||
mutable rasterizer_subpix_type fSubpixRasterizer;
|
||||
mutable rasterizer_type fRasterizer;
|
||||
mutable renderer_subpix_type fSubpixRenderer;
|
||||
mutable renderer_type fRenderer;
|
||||
mutable renderer_bin_type fRendererBin;
|
||||
mutable scanline_unpacked_type fUnpackedScanline;
|
||||
mutable scanline_packed_type fPackedScanline;
|
||||
mutable scanline_packed_subpix_type fSubpixPackedScanline;
|
||||
mutable scanline_unpacked_subpix_type fSubpixUnpackedScanline;
|
||||
mutable rasterizer_subpix_type fSubpixRasterizer;
|
||||
mutable rasterizer_type fRasterizer;
|
||||
mutable renderer_subpix_type fSubpixRenderer;
|
||||
mutable renderer_type fRenderer;
|
||||
mutable renderer_bin_type fRendererBin;
|
||||
|
||||
mutable agg::path_storage fPath;
|
||||
mutable agg::conv_curve<agg::path_storage> fCurve;
|
||||
mutable agg::path_storage fPath;
|
||||
mutable agg::conv_curve<agg::path_storage> fCurve;
|
||||
|
||||
// for internal coordinate rounding/transformation
|
||||
bool fSubpixelPrecise : 1;
|
||||
bool fValidClipping : 1;
|
||||
bool fDrawingText : 1;
|
||||
bool fAttached : 1;
|
||||
bool fSubpixelPrecise : 1;
|
||||
bool fValidClipping : 1;
|
||||
bool fDrawingText : 1;
|
||||
bool fAttached : 1;
|
||||
|
||||
float fPenSize;
|
||||
const BRegion* fClippingRegion;
|
||||
drawing_mode fDrawingMode;
|
||||
source_alpha fAlphaSrcMode;
|
||||
alpha_function fAlphaFncMode;
|
||||
cap_mode fLineCapMode;
|
||||
join_mode fLineJoinMode;
|
||||
float fMiterLimit;
|
||||
float fPenSize;
|
||||
const BRegion* fClippingRegion;
|
||||
drawing_mode fDrawingMode;
|
||||
source_alpha fAlphaSrcMode;
|
||||
alpha_function fAlphaFncMode;
|
||||
cap_mode fLineCapMode;
|
||||
join_mode fLineJoinMode;
|
||||
float fMiterLimit;
|
||||
|
||||
PatternHandler fPatternHandler;
|
||||
PatternHandler fPatternHandler;
|
||||
|
||||
// a class handling rendering and caching of glyphs
|
||||
// it is setup to load from a specific Freetype supported
|
||||
// font file which it gets from ServerFont
|
||||
mutable AGGTextRenderer fTextRenderer;
|
||||
mutable AGGTextRenderer fTextRenderer;
|
||||
};
|
||||
|
||||
|
||||
@ -383,6 +386,7 @@ Painter::ClipRect(BRect rect) const
|
||||
return _Clipped(rect);
|
||||
}
|
||||
|
||||
|
||||
inline BRect
|
||||
Painter::AlignAndClipRect(BRect rect) const
|
||||
{
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "DrawState.h"
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <utf8_functions.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
@ -682,7 +683,7 @@ RemoteDrawingEngine::FillRoundRect(BRect rect, float xRadius, float yRadius,
|
||||
void
|
||||
RemoteDrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
|
||||
const uint32* opList, int32 pointCount, const BPoint* pointList,
|
||||
bool filled)
|
||||
bool filled, const BPoint& viewToScreenOffset, float viewScale)
|
||||
{
|
||||
BRect clipBounds = bounds;
|
||||
if (!filled)
|
||||
@ -699,13 +700,15 @@ RemoteDrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
|
||||
message.AddList(opList, opCount);
|
||||
message.Add(pointCount);
|
||||
message.AddList(pointList, pointCount);
|
||||
// TODO: viewToScreenOffset and viewScale
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RemoteDrawingEngine::FillShape(const BRect& bounds, int32 opCount,
|
||||
const uint32* opList, int32 pointCount, const BPoint* pointList,
|
||||
const BGradient& gradient)
|
||||
const BGradient& gradient, const BPoint& viewToScreenOffset,
|
||||
float viewScale)
|
||||
{
|
||||
if (!fClippingRegion.Intersects(bounds))
|
||||
return;
|
||||
@ -719,6 +722,7 @@ RemoteDrawingEngine::FillShape(const BRect& bounds, int32 opCount,
|
||||
message.Add(pointCount);
|
||||
message.AddList(pointList, pointCount);
|
||||
message.AddGradient(gradient);
|
||||
// TODO: viewToScreenOffset and viewScale
|
||||
}
|
||||
|
||||
|
||||
@ -824,6 +828,37 @@ RemoteDrawingEngine::DrawString(const char* string, int32 length,
|
||||
}
|
||||
|
||||
|
||||
BPoint
|
||||
RemoteDrawingEngine::DrawString(const char* string, int32 length,
|
||||
const BPoint* offsets)
|
||||
{
|
||||
// Guaranteed to have at least one point.
|
||||
RemoteMessage message(NULL, fHWInterface->SendBuffer());
|
||||
|
||||
message.Start(RP_DRAW_STRING_WITH_OFFSETS);
|
||||
message.Add(fToken);
|
||||
message.AddString(string, length);
|
||||
message.AddList(offsets, UTF8CountChars(string, length));
|
||||
|
||||
status_t result = _AddCallback();
|
||||
if (message.Flush() != B_OK)
|
||||
return offsets[0];
|
||||
|
||||
if (result != B_OK)
|
||||
return offsets[0];
|
||||
|
||||
do {
|
||||
result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT,
|
||||
1 * 1000 * 1000);
|
||||
} while (result == B_INTERRUPTED);
|
||||
|
||||
if (result != B_OK)
|
||||
return offsets[0];
|
||||
|
||||
return fDrawStringResult;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
RemoteDrawingEngine::StringWidth(const char* string, int32 length,
|
||||
escapement_delta* delta)
|
||||
|
@ -107,11 +107,15 @@ virtual void FillRoundRect(BRect rect, float xRadius,
|
||||
virtual void DrawShape(const BRect& bounds,
|
||||
int32 opCount, const uint32* opList,
|
||||
int32 pointCount, const BPoint* pointList,
|
||||
bool filled);
|
||||
bool filled,
|
||||
const BPoint& viewToScreenOffset,
|
||||
float viewScale);
|
||||
virtual void FillShape(const BRect& bounds,
|
||||
int32 opCount, const uint32* opList,
|
||||
int32 pointCount, const BPoint* pointList,
|
||||
const BGradient& gradient);
|
||||
const BGradient& gradient,
|
||||
const BPoint& viewToScreenOffset,
|
||||
float viewScale);
|
||||
|
||||
virtual void DrawTriangle(BPoint* points,
|
||||
const BRect& bounds, bool filled);
|
||||
@ -131,6 +135,8 @@ virtual void StrokeLineArray(int32 numlines,
|
||||
virtual BPoint DrawString(const char* string, int32 length,
|
||||
const BPoint& point,
|
||||
escapement_delta* delta = NULL);
|
||||
virtual BPoint DrawString(const char* string, int32 length,
|
||||
const BPoint* offsets);
|
||||
|
||||
virtual float StringWidth(const char* string, int32 length,
|
||||
escapement_delta* delta = NULL);
|
||||
|
@ -100,6 +100,7 @@ enum {
|
||||
RP_FILL_REGION_COLOR_NO_CLIPPING,
|
||||
|
||||
RP_DRAW_STRING = 180,
|
||||
RP_DRAW_STRING_WITH_OFFSETS,
|
||||
RP_DRAW_STRING_RESULT,
|
||||
RP_STRING_WIDTH,
|
||||
RP_STRING_WIDTH_RESULT,
|
||||
|
@ -192,6 +192,7 @@ SubInclude HAIKU_TOP src tests servers app regularapps ;
|
||||
SubInclude HAIKU_TOP src tests servers app resize_limits ;
|
||||
SubInclude HAIKU_TOP src tests servers app scrollbar ;
|
||||
SubInclude HAIKU_TOP src tests servers app scrolling ;
|
||||
SubInclude HAIKU_TOP src tests servers app shape_test ;
|
||||
SubInclude HAIKU_TOP src tests servers app statusbar ;
|
||||
SubInclude HAIKU_TOP src tests servers app stress_test ;
|
||||
SubInclude HAIKU_TOP src tests servers app textview ;
|
||||
|
17
src/tests/servers/app/shape_test/Jamfile
Normal file
17
src/tests/servers/app/shape_test/Jamfile
Normal file
@ -0,0 +1,17 @@
|
||||
SubDir HAIKU_TOP src tests servers app shape_test ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
AddSubDirSupportedPlatforms libbe_test ;
|
||||
|
||||
UseHeaders [ FDirName os app ] ;
|
||||
UseHeaders [ FDirName os interface ] ;
|
||||
|
||||
SimpleTest ShapeTest :
|
||||
main.cpp
|
||||
: be $(TARGET_LIBSUPC++)
|
||||
;
|
||||
|
||||
if ( $(TARGET_PLATFORM) = libbe_test ) {
|
||||
HaikuInstall install-test-apps : $(HAIKU_APP_TEST_DIR) : ShapeTest
|
||||
: tests!apps ;
|
||||
}
|
181
src/tests/servers/app/shape_test/main.cpp
Normal file
181
src/tests/servers/app/shape_test/main.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Message.h>
|
||||
#include <Shape.h>
|
||||
#include <View.h>
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
static const char* kAppSignature = "application/x.vnd-Haiku.ShapeTest";
|
||||
|
||||
|
||||
class TestView : public BView {
|
||||
public:
|
||||
TestView(BRect frame, const char* name,
|
||||
uint32 resizeFlags, uint32 flags);
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
};
|
||||
|
||||
|
||||
TestView::TestView(BRect frame, const char* name, uint32 resizeFlags,
|
||||
uint32 flags)
|
||||
:
|
||||
BView(frame, name, resizeFlags, flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TestView::Draw(BRect updateRect)
|
||||
{
|
||||
BRect r(Bounds());
|
||||
|
||||
SetDrawingMode(B_OP_ALPHA);
|
||||
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
||||
SetHighColor(0, 0, 0, 240);
|
||||
|
||||
class TranslateIterator : public BShapeIterator {
|
||||
public:
|
||||
TranslateIterator()
|
||||
:
|
||||
fOffsetX(0),
|
||||
fOffsetY(0)
|
||||
{
|
||||
}
|
||||
|
||||
TranslateIterator(float offsetX, float offsetY)
|
||||
:
|
||||
fOffsetX(offsetX),
|
||||
fOffsetY(offsetY)
|
||||
{
|
||||
}
|
||||
|
||||
void SetOffset(float offsetX, float offsetY)
|
||||
{
|
||||
fOffsetX = offsetX;
|
||||
fOffsetY = offsetY;
|
||||
}
|
||||
|
||||
virtual status_t IterateMoveTo(BPoint* point)
|
||||
{
|
||||
point->x += fOffsetX;
|
||||
point->y += fOffsetY;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
virtual status_t IterateLineTo(int32 lineCount, BPoint* linePts)
|
||||
{
|
||||
while (lineCount--) {
|
||||
linePts->x += fOffsetX;
|
||||
linePts->y += fOffsetY;
|
||||
linePts++;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
virtual status_t IterateBezierTo(int32 bezierCount, BPoint* bezierPts)
|
||||
{
|
||||
while (bezierCount--) {
|
||||
bezierPts[0].x += fOffsetX;
|
||||
bezierPts[0].y += fOffsetY;
|
||||
bezierPts[1].x += fOffsetX;
|
||||
bezierPts[1].y += fOffsetY;
|
||||
bezierPts[2].x += fOffsetX;
|
||||
bezierPts[2].y += fOffsetY;
|
||||
bezierPts += 3;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
virtual status_t IterateArcTo(float& rx, float& ry, float& angle,
|
||||
bool largeArc, bool counterClockWise, BPoint& point)
|
||||
{
|
||||
point.x += fOffsetX;
|
||||
point.y += fOffsetY;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
float fOffsetX;
|
||||
float fOffsetY;
|
||||
} translator;
|
||||
|
||||
MovePenTo(B_ORIGIN);
|
||||
|
||||
const float arcRX = 50;
|
||||
const float arcRY = 80;
|
||||
|
||||
BShape shape;
|
||||
shape.MoveTo(BPoint(20, 10));
|
||||
shape.LineTo(BPoint(10, 90));
|
||||
shape.LineTo(BPoint(90, 100));
|
||||
shape.ArcTo(arcRX, arcRY, 45, true, true, BPoint(100, 20));
|
||||
shape.Close();
|
||||
|
||||
StrokeShape(&shape);
|
||||
|
||||
shape.Clear();
|
||||
shape.MoveTo(BPoint(20, 10));
|
||||
shape.LineTo(BPoint(10, 90));
|
||||
shape.LineTo(BPoint(90, 100));
|
||||
shape.ArcTo(arcRX, arcRY, 45, false, true, BPoint(100, 20));
|
||||
shape.Close();
|
||||
|
||||
translator.SetOffset(10, 10);
|
||||
translator.Iterate(&shape);
|
||||
|
||||
SetHighColor(140, 30, 50, 255);
|
||||
StrokeShape(&shape);
|
||||
|
||||
shape.Clear();
|
||||
shape.MoveTo(BPoint(20, 10));
|
||||
shape.LineTo(BPoint(10, 90));
|
||||
shape.LineTo(BPoint(90, 100));
|
||||
shape.ArcTo(arcRX, arcRY, 45, true, false, BPoint(100, 20));
|
||||
shape.Close();
|
||||
|
||||
translator.SetOffset(20, 20);
|
||||
translator.Iterate(&shape);
|
||||
|
||||
SetHighColor(140, 130, 50, 255);
|
||||
StrokeShape(&shape);
|
||||
|
||||
shape.Clear();
|
||||
shape.MoveTo(BPoint(20, 10));
|
||||
shape.LineTo(BPoint(10, 90));
|
||||
shape.LineTo(BPoint(90, 100));
|
||||
shape.ArcTo(arcRX, arcRY, 45, false, false, BPoint(100, 20));
|
||||
shape.Close();
|
||||
|
||||
translator.SetOffset(30, 30);
|
||||
translator.Iterate(&shape);
|
||||
|
||||
SetHighColor(40, 130, 150, 255);
|
||||
StrokeShape(&shape);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
BApplication app(kAppSignature);
|
||||
|
||||
BWindow* window = new BWindow(BRect(50.0, 50.0, 300.0, 250.0),
|
||||
"BShape Test", B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE);
|
||||
|
||||
BView* view = new TestView(window->Bounds(), "test", B_FOLLOW_ALL,
|
||||
B_WILL_DRAW);
|
||||
window->AddChild(view);
|
||||
|
||||
window->Show();
|
||||
|
||||
app.Run();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user