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:
X512
2026-03-05 02:42:51 +00:00
committed by waddlesplash
parent 7ef695df5c
commit 02683a08de
3 changed files with 103 additions and 35 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ private:
bool _AddPoints(const BPoint* points, int32 count, bool _AddPoints(const BPoint* points, int32 count,
bool computeBounds); bool computeBounds);
void _ComputeBounds(); static BRect _ComputeBounds(const BPoint* points, uint32 count);
void _MapPoint(BPoint* point, const BRect& source, void _MapPoint(BPoint* point, const BRect& source,
const BRect& destination); const BRect& destination);
void _MapRectangle(BRect* rect, const BRect& source, void _MapRectangle(BRect* rect, const BRect& source,
+22 -22
View File
@@ -129,7 +129,7 @@ BPolygon::PrintToStream() const
//BPolygon::TransformBy(const BAffineTransform& transform) //BPolygon::TransformBy(const BAffineTransform& transform)
//{ //{
// transform.Apply(fPoints, (int32)fCount); // 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; fCount += count;
if (computeBounds) if (computeBounds)
_ComputeBounds(); fBounds = _ComputeBounds(fPoints, fCount);
return true; return true;
} }
void BRect
BPolygon::_ComputeBounds() BPolygon::_ComputeBounds(const BPoint* points, uint32 count)
{ {
if (fCount == 0) { if (count == 0)
fBounds = BRect(0.0, 0.0, -1.0f, -1.0f); return BRect(0.0, 0.0, -1.0f, -1.0f);
return;
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]); return bounds;
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;
}
} }
+80 -12
View File
@@ -3611,10 +3611,28 @@ void
BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed, BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed,
::pattern pattern) ::pattern pattern)
{ {
BPolygon polygon(pointArray, numPoints); if (pointArray == NULL
|| numPoints <= 1
|| fOwner == NULL)
return;
StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed, BRect bounds = BPolygon::_ComputeBounds(pointArray, numPoints);
pattern);
_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, BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed,
const BGradient& gradient) const BGradient& gradient)
{ {
BPolygon polygon(pointArray, numPoints); if (pointArray == NULL
|| numPoints <= 1
|| fOwner == NULL)
return;
StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed, BRect bounds = BPolygon::_ComputeBounds(pointArray, numPoints);
gradient);
_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 void
BView::FillPolygon(const BPoint* pointArray, int32 numPoints, ::pattern pattern) BView::FillPolygon(const BPoint* pointArray, int32 numPoints, ::pattern pattern)
{ {
if (pointArray == NULL) if (pointArray == NULL
|| numPoints <= 2
|| fOwner == NULL)
return; return;
BPolygon polygon(pointArray, numPoints); BRect bounds = BPolygon::_ComputeBounds(pointArray, numPoints);
FillPolygon(&polygon, pattern);
_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, BView::FillPolygon(const BPoint* pointArray, int32 numPoints,
const BGradient& gradient) const BGradient& gradient)
{ {
if (pointArray == NULL) if (pointArray == NULL
|| numPoints <= 2
|| fOwner == NULL)
return; return;
BPolygon polygon(pointArray, numPoints); BRect bounds = BPolygon::_ComputeBounds(pointArray, numPoints);
FillPolygon(&polygon, gradient);
_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");
}
} }