View: optimize Fill/StrokePolygon with raw points array argument
Converting points array to `BPolygon` has significant cost, including heap allocation, when drawing a lot of polygons. Change-Id: I81e6b4031bac4beadcc79412c58eedddffc00a82 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10337 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
@@ -40,7 +40,7 @@ private:
|
||||
|
||||
bool _AddPoints(const BPoint* points, int32 count,
|
||||
bool computeBounds);
|
||||
void _ComputeBounds();
|
||||
static BRect _ComputeBounds(const BPoint* points, uint32 count);
|
||||
void _MapPoint(BPoint* point, const BRect& source,
|
||||
const BRect& destination);
|
||||
void _MapRectangle(BRect* rect, const BRect& source,
|
||||
|
||||
@@ -129,7 +129,7 @@ BPolygon::PrintToStream() const
|
||||
//BPolygon::TransformBy(const BAffineTransform& transform)
|
||||
//{
|
||||
// transform.Apply(fPoints, (int32)fCount);
|
||||
// _ComputeBounds();
|
||||
// fBounds = _ComputeBounds(fPoints, fCount);
|
||||
//}
|
||||
//
|
||||
//
|
||||
@@ -177,35 +177,35 @@ BPolygon::_AddPoints(const BPoint* points, int32 count, bool computeBounds)
|
||||
fCount += count;
|
||||
|
||||
if (computeBounds)
|
||||
_ComputeBounds();
|
||||
fBounds = _ComputeBounds(fPoints, fCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BPolygon::_ComputeBounds()
|
||||
BRect
|
||||
BPolygon::_ComputeBounds(const BPoint* points, uint32 count)
|
||||
{
|
||||
if (fCount == 0) {
|
||||
fBounds = BRect(0.0, 0.0, -1.0f, -1.0f);
|
||||
return;
|
||||
if (count == 0)
|
||||
return BRect(0.0, 0.0, -1.0f, -1.0f);
|
||||
|
||||
BRect bounds(points[0], points[0]);
|
||||
|
||||
for (uint32 i = 1; i < count; i++) {
|
||||
if (points[i].x < bounds.left)
|
||||
bounds.left = points[i].x;
|
||||
|
||||
if (points[i].y < bounds.top)
|
||||
bounds.top = points[i].y;
|
||||
|
||||
if (points[i].x > bounds.right)
|
||||
bounds.right = points[i].x;
|
||||
|
||||
if (points[i].y > bounds.bottom)
|
||||
bounds.bottom = points[i].y;
|
||||
}
|
||||
|
||||
fBounds = BRect(fPoints[0], fPoints[0]);
|
||||
|
||||
for (uint32 i = 1; i < fCount; i++) {
|
||||
if (fPoints[i].x < fBounds.left)
|
||||
fBounds.left = fPoints[i].x;
|
||||
|
||||
if (fPoints[i].y < fBounds.top)
|
||||
fBounds.top = fPoints[i].y;
|
||||
|
||||
if (fPoints[i].x > fBounds.right)
|
||||
fBounds.right = fPoints[i].x;
|
||||
|
||||
if (fPoints[i].y > fBounds.bottom)
|
||||
fBounds.bottom = fPoints[i].y;
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+80
-12
@@ -3611,10 +3611,28 @@ void
|
||||
BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed,
|
||||
::pattern pattern)
|
||||
{
|
||||
BPolygon polygon(pointArray, numPoints);
|
||||
if (pointArray == NULL
|
||||
|| numPoints <= 1
|
||||
|| fOwner == NULL)
|
||||
return;
|
||||
|
||||
StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed,
|
||||
pattern);
|
||||
BRect bounds = BPolygon::_ComputeBounds(pointArray, numPoints);
|
||||
|
||||
_CheckLockAndSwitchCurrent();
|
||||
_UpdatePattern(pattern);
|
||||
|
||||
if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON,
|
||||
numPoints * sizeof(BPoint) + sizeof(BRect) + sizeof(bool)
|
||||
+ sizeof(int32)) == B_OK) {
|
||||
fOwner->fLink->Attach<BRect>(bounds);
|
||||
fOwner->fLink->Attach<bool>(closed);
|
||||
fOwner->fLink->Attach<int32>(numPoints);
|
||||
fOwner->fLink->Attach(pointArray, numPoints * sizeof(BPoint));
|
||||
|
||||
_FlushIfNotInTransaction();
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3663,10 +3681,28 @@ void
|
||||
BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed,
|
||||
const BGradient& gradient)
|
||||
{
|
||||
BPolygon polygon(pointArray, numPoints);
|
||||
if (pointArray == NULL
|
||||
|| numPoints <= 1
|
||||
|| fOwner == NULL)
|
||||
return;
|
||||
|
||||
StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed,
|
||||
gradient);
|
||||
BRect bounds = BPolygon::_ComputeBounds(pointArray, numPoints);
|
||||
|
||||
_CheckLockAndSwitchCurrent();
|
||||
|
||||
if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON_GRADIENT,
|
||||
numPoints * sizeof(BPoint) + sizeof(BRect) + sizeof(bool)
|
||||
+ sizeof(int32)) == B_OK) {
|
||||
fOwner->fLink->Attach<BRect>(bounds);
|
||||
fOwner->fLink->Attach<bool>(closed);
|
||||
fOwner->fLink->Attach<int32>(numPoints);
|
||||
fOwner->fLink->Attach(pointArray, numPoints * sizeof(BPoint));
|
||||
fOwner->fLink->AttachGradient(gradient);
|
||||
|
||||
_FlushIfNotInTransaction();
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3755,11 +3791,27 @@ BView::FillPolygon(const BPolygon* polygon, const BGradient& gradient)
|
||||
void
|
||||
BView::FillPolygon(const BPoint* pointArray, int32 numPoints, ::pattern pattern)
|
||||
{
|
||||
if (pointArray == NULL)
|
||||
if (pointArray == NULL
|
||||
|| numPoints <= 2
|
||||
|| fOwner == NULL)
|
||||
return;
|
||||
|
||||
BPolygon polygon(pointArray, numPoints);
|
||||
FillPolygon(&polygon, pattern);
|
||||
BRect bounds = BPolygon::_ComputeBounds(pointArray, numPoints);
|
||||
|
||||
_CheckLockAndSwitchCurrent();
|
||||
_UpdatePattern(pattern);
|
||||
|
||||
if (fOwner->fLink->StartMessage(AS_FILL_POLYGON,
|
||||
numPoints * sizeof(BPoint) + sizeof(BRect) + sizeof(int32))
|
||||
== B_OK) {
|
||||
fOwner->fLink->Attach<BRect>(bounds);
|
||||
fOwner->fLink->Attach<int32>(numPoints);
|
||||
fOwner->fLink->Attach(pointArray, numPoints * sizeof(BPoint));
|
||||
|
||||
_FlushIfNotInTransaction();
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3767,11 +3819,27 @@ void
|
||||
BView::FillPolygon(const BPoint* pointArray, int32 numPoints,
|
||||
const BGradient& gradient)
|
||||
{
|
||||
if (pointArray == NULL)
|
||||
if (pointArray == NULL
|
||||
|| numPoints <= 2
|
||||
|| fOwner == NULL)
|
||||
return;
|
||||
|
||||
BPolygon polygon(pointArray, numPoints);
|
||||
FillPolygon(&polygon, gradient);
|
||||
BRect bounds = BPolygon::_ComputeBounds(pointArray, numPoints);
|
||||
|
||||
_CheckLockAndSwitchCurrent();
|
||||
|
||||
if (fOwner->fLink->StartMessage(AS_FILL_POLYGON_GRADIENT,
|
||||
numPoints * sizeof(BPoint) + sizeof(BRect) + sizeof(int32))
|
||||
== B_OK) {
|
||||
fOwner->fLink->Attach<BRect>(bounds);
|
||||
fOwner->fLink->Attach<int32>(numPoints);
|
||||
fOwner->fLink->Attach(pointArray, numPoints * sizeof(BPoint));
|
||||
fOwner->fLink->AttachGradient(gradient);
|
||||
|
||||
_FlushIfNotInTransaction();
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user