From ceaf2dd2d619abb4069b96f6f07bf1038862fd9e Mon Sep 17 00:00:00 2001 From: X512 Date: Wed, 3 Sep 2025 01:54:58 +0900 Subject: [PATCH] app_server: add gradient stroke support TODO: HTML5 remote desktop client. Change-Id: Ie2a32c4a498462578476d29a7000ea0b6f86810b Reviewed-on: https://review.haiku-os.org/c/haiku/+/9625 Reviewed-by: waddlesplash --- headers/os/interface/View.h | 40 +++ headers/private/app/ServerProtocol.h | 9 + headers/private/interface/PictureDataWriter.h | 2 + headers/private/interface/PicturePlayer.h | 1 + headers/private/interface/PictureProtocol.h | 3 +- src/apps/remotedesktop/RemoteView.cpp | 187 ++++++++---- src/kits/interface/PictureDataWriter.cpp | 18 ++ src/kits/interface/PicturePlayer.cpp | 26 +- src/kits/interface/View.cpp | 270 ++++++++++++++++++ src/servers/app/ServerPicture.cpp | 43 ++- src/servers/app/ServerWindow.cpp | 137 +++++++-- src/servers/app/drawing/DrawingEngine.cpp | 96 +++++-- src/servers/app/drawing/DrawingEngine.h | 33 ++- src/servers/app/drawing/Painter/Painter.cpp | 260 ++++++++++++++--- src/servers/app/drawing/Painter/Painter.h | 33 ++- .../interface/remote/RemoteDrawingEngine.cpp | 72 +++-- .../interface/remote/RemoteDrawingEngine.h | 33 ++- .../drawing/interface/remote/RemoteMessage.h | 12 +- 18 files changed, 1065 insertions(+), 210 deletions(-) diff --git a/headers/os/interface/View.h b/headers/os/interface/View.h index 690c9c8314..3a4eca0fd3 100644 --- a/headers/os/interface/View.h +++ b/headers/os/interface/View.h @@ -346,6 +346,10 @@ public: ::pattern pattern = B_SOLID_HIGH); void StrokeLine(BPoint start, BPoint end, ::pattern pattern = B_SOLID_HIGH); + void StrokeLine(BPoint toPoint, + const BGradient& gradient); + void StrokeLine(BPoint start, BPoint end, + const BGradient& gradient); void BeginLineArray(int32 count); void AddLine(BPoint start, BPoint end, rgb_color color); @@ -361,6 +365,16 @@ public: int32 numPoints, BRect bounds, bool closed = true, ::pattern pattern = B_SOLID_HIGH); + void StrokePolygon(const BPolygon* polygon, + bool closed, + const BGradient& gradient); + void StrokePolygon(const BPoint* pointArray, + int32 numPoints, bool closed, + const BGradient& gradient); + void StrokePolygon(const BPoint* pointArray, + int32 numPoints, BRect bounds, + bool closed, + const BGradient& gradient); void FillPolygon(const BPolygon* polygon, ::pattern pattern = B_SOLID_HIGH); void FillPolygon(const BPoint* pointArray, @@ -383,6 +397,11 @@ public: void StrokeTriangle(BPoint point1, BPoint point2, BPoint point3, ::pattern pattern = B_SOLID_HIGH); + void StrokeTriangle(BPoint point1, BPoint point2, + BPoint point3, BRect bounds, + const BGradient& gradient); + void StrokeTriangle(BPoint point1, BPoint point2, + BPoint point3, const BGradient& gradient); void FillTriangle(BPoint point1, BPoint point2, BPoint point3, ::pattern pattern = B_SOLID_HIGH); @@ -397,6 +416,8 @@ public: void StrokeRect(BRect rect, ::pattern pattern = B_SOLID_HIGH); + void StrokeRect(BRect rect, + const BGradient& gradient); void FillRect(BRect rect, ::pattern pattern = B_SOLID_HIGH); void FillRect(BRect rect, const BGradient& gradient); @@ -409,6 +430,9 @@ public: void StrokeRoundRect(BRect rect, float xRadius, float yRadius, ::pattern pattern = B_SOLID_HIGH); + void StrokeRoundRect(BRect rect, float xRadius, + float yRadius, + const BGradient& gradient); void FillRoundRect(BRect rect, float xRadius, float yRadius, ::pattern pattern = B_SOLID_HIGH); @@ -420,6 +444,11 @@ public: ::pattern pattern = B_SOLID_HIGH); void StrokeEllipse(BRect rect, ::pattern pattern = B_SOLID_HIGH); + void StrokeEllipse(BPoint center, float xRadius, + float yRadius, + const BGradient& gradient); + void StrokeEllipse(BRect rect, + const BGradient& gradient); void FillEllipse(BPoint center, float xRadius, float yRadius, ::pattern pattern = B_SOLID_HIGH); @@ -437,6 +466,13 @@ public: void StrokeArc(BRect rect, float startAngle, float arcAngle, ::pattern pattern = B_SOLID_HIGH); + void StrokeArc(BPoint center, float xRadius, + float yRadius, float startAngle, + float arcAngle, + const BGradient& gradient); + void StrokeArc(BRect rect, float startAngle, + float arcAngle, + const BGradient& gradient); void FillArc(BPoint center, float xRadius, float yRadius, float startAngle, float arcAngle, @@ -452,6 +488,8 @@ public: void StrokeBezier(BPoint* controlPoints, ::pattern pattern = B_SOLID_HIGH); + void StrokeBezier(BPoint* controlPoints, + const BGradient& gradient); void FillBezier(BPoint* controlPoints, ::pattern pattern = B_SOLID_HIGH); void FillBezier(BPoint* controlPoints, @@ -459,6 +497,8 @@ public: void StrokeShape(BShape* shape, ::pattern pattern = B_SOLID_HIGH); + void StrokeShape(BShape* shape, + const BGradient& gradient); void FillShape(BShape* shape, ::pattern pattern = B_SOLID_HIGH); void FillShape(BShape* shape, diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index f07f019b6f..848a68fbd7 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -224,15 +224,24 @@ enum { // Graphics calls AS_STROKE_ARC, + AS_STROKE_ARC_GRADIENT, AS_STROKE_BEZIER, + AS_STROKE_BEZIER_GRADIENT, AS_STROKE_ELLIPSE, + AS_STROKE_ELLIPSE_GRADIENT, AS_STROKE_LINE, + AS_STROKE_LINE_GRADIENT, AS_STROKE_LINEARRAY, AS_STROKE_POLYGON, + AS_STROKE_POLYGON_GRADIENT, AS_STROKE_RECT, + AS_STROKE_RECT_GRADIENT, AS_STROKE_ROUNDRECT, + AS_STROKE_ROUNDRECT_GRADIENT, AS_STROKE_SHAPE, + AS_STROKE_SHAPE_GRADIENT, AS_STROKE_TRIANGLE, + AS_STROKE_TRIANGLE_GRADIENT, AS_FILL_ARC, AS_FILL_ARC_GRADIENT, diff --git a/headers/private/interface/PictureDataWriter.h b/headers/private/interface/PictureDataWriter.h index 032a1d3ad3..06fb16356f 100644 --- a/headers/private/interface/PictureDataWriter.h +++ b/headers/private/interface/PictureDataWriter.h @@ -113,6 +113,8 @@ public: status_t WriteDrawShapeGradient(const int32& opCount, const void* opList, const int32& ptCount, const void* ptList, const BGradient& gradient, const bool& fill); + status_t WriteStrokeLineGradient(const BPoint& start, const BPoint& end, + const BGradient& gradient); status_t WriteDrawBitmap(const BRect& srcRect, const BRect& dstRect, const int32& width, const int32& height, diff --git a/headers/private/interface/PicturePlayer.h b/headers/private/interface/PicturePlayer.h index f5c3033c22..9cffa7b57a 100644 --- a/headers/private/interface/PicturePlayer.h +++ b/headers/private/interface/PicturePlayer.h @@ -103,6 +103,7 @@ struct picture_player_callbacks { void (*draw_polygon_gradient)(void* userData, size_t numPoints, const BPoint points[], bool isClosed, BGradient& gradient, bool fill); void (*draw_shape_gradient)(void* userData, const BShape& shape, BGradient& gradient, bool fill); void (*set_fill_rule)(void* userData, int32 fillRule); + void (*stroke_line_gradient)(void* userData, const BPoint& start, const BPoint& end, const BGradient& gradient); }; diff --git a/headers/private/interface/PictureProtocol.h b/headers/private/interface/PictureProtocol.h index 25e14cf568..0124abc6f6 100644 --- a/headers/private/interface/PictureProtocol.h +++ b/headers/private/interface/PictureProtocol.h @@ -37,6 +37,7 @@ enum { B_PIC_FILL_ARC_GRADIENT = 0x0123, B_PIC_STROKE_ELLIPSE_GRADIENT = 0x0124, B_PIC_FILL_ELLIPSE_GRADIENT = 0x0125, + B_PIC_STROKE_LINE_GRADIENT = 0x0126, B_PIC_ENTER_STATE_CHANGE = 0x0200, B_PIC_SET_CLIPPING_RECTS = 0x0201, @@ -77,7 +78,7 @@ enum { }; -const static uint32 kOpsTableSize = 71; +const static uint32 kOpsTableSize = 72; #endif diff --git a/src/apps/remotedesktop/RemoteView.cpp b/src/apps/remotedesktop/RemoteView.cpp index 86c0ffd6cf..a91fdfab00 100644 --- a/src/apps/remotedesktop/RemoteView.cpp +++ b/src/apps/remotedesktop/RemoteView.cpp @@ -805,29 +805,38 @@ RemoteView::_DrawThread() } case RP_STROKE_ARC: + case RP_STROKE_ARC_GRADIENT: case RP_FILL_ARC: case RP_FILL_ARC_GRADIENT: { BRect rect; float angle, span; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; message.Read(rect); message.Read(angle); if (message.Read(span) != B_OK) continue; + message.ReadGradient(&gradient); + if (code == RP_STROKE_ARC_GRADIENT || code == RP_FILL_ARC_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + if (code == RP_STROKE_ARC) { offscreen->StrokeArc(rect, angle, span, pattern); rect.InsetBy(-penSize, -penSize); + } else if (code == RP_STROKE_ARC_GRADIENT) { + offscreen->StrokeArc(rect, angle, span, *gradient); + rect.InsetBy(-penSize, -penSize); } else if (code == RP_FILL_ARC) offscreen->FillArc(rect, angle, span, pattern); else { - BGradient *gradient; - if (message.ReadGradient(&gradient) != B_OK) - continue; - offscreen->FillArc(rect, angle, span, *gradient); - delete gradient; } invalidRegion.Include(rect); @@ -835,26 +844,36 @@ RemoteView::_DrawThread() } case RP_STROKE_BEZIER: + case RP_STROKE_BEZIER_GRADIENT: case RP_FILL_BEZIER: case RP_FILL_BEZIER_GRADIENT: { BPoint points[4]; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; + if (message.ReadList(points, 4) != B_OK) continue; + message.ReadGradient(&gradient); + if (code == RP_STROKE_BEZIER_GRADIENT || code == RP_FILL_BEZIER_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + BRect bounds = _BuildInvalidateRect(points, 4); if (code == RP_STROKE_BEZIER) { offscreen->StrokeBezier(points, pattern); bounds.InsetBy(-penSize, -penSize); + } else if (code == RP_STROKE_BEZIER_GRADIENT) { + offscreen->StrokeBezier(points, *gradient); + bounds.InsetBy(-penSize, -penSize); } else if (code == RP_FILL_BEZIER) offscreen->FillBezier(points, pattern); else { - BGradient *gradient; - if (message.ReadGradient(&gradient) != B_OK) - continue; - offscreen->FillBezier(points, *gradient); - delete gradient; } invalidRegion.Include(bounds); @@ -862,25 +881,34 @@ RemoteView::_DrawThread() } case RP_STROKE_ELLIPSE: + case RP_STROKE_ELLIPSE_GRADIENT: case RP_FILL_ELLIPSE: case RP_FILL_ELLIPSE_GRADIENT: { BRect rect; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; if (message.Read(rect) != B_OK) continue; + message.ReadGradient(&gradient); + if (code == RP_STROKE_ELLIPSE_GRADIENT || code == RP_FILL_ELLIPSE_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + if (code == RP_STROKE_ELLIPSE) { offscreen->StrokeEllipse(rect, pattern); rect.InsetBy(-penSize, -penSize); + } else if (code == RP_STROKE_ELLIPSE_GRADIENT) { + offscreen->StrokeEllipse(rect, *gradient); + rect.InsetBy(-penSize, -penSize); } else if (code == RP_FILL_ELLIPSE) offscreen->FillEllipse(rect, pattern); else { - BGradient *gradient; - if (message.ReadGradient(&gradient) != B_OK) - continue; - offscreen->FillEllipse(rect, *gradient); - delete gradient; } invalidRegion.Include(rect); @@ -888,12 +916,15 @@ RemoteView::_DrawThread() } case RP_STROKE_POLYGON: + case RP_STROKE_POLYGON_GRADIENT: case RP_FILL_POLYGON: case RP_FILL_POLYGON_GRADIENT: { BRect bounds; bool closed; int32 numPoints; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; message.Read(bounds); message.Read(closed); @@ -904,20 +935,24 @@ RemoteView::_DrawThread() for (int32 i = 0; i < numPoints; i++) message.Read(points[i]); + message.ReadGradient(&gradient); + if (code == RP_STROKE_POLYGON_GRADIENT || code == RP_FILL_POLYGON_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + if (code == RP_STROKE_POLYGON) { - offscreen->StrokePolygon(points, numPoints, bounds, closed, - pattern); + offscreen->StrokePolygon(points, numPoints, bounds, closed, pattern); + bounds.InsetBy(-penSize, -penSize); + } else if (code == RP_STROKE_POLYGON_GRADIENT) { + offscreen->StrokePolygon(points, numPoints, bounds, closed, *gradient); bounds.InsetBy(-penSize, -penSize); } else if (code == RP_FILL_POLYGON) offscreen->FillPolygon(points, numPoints, bounds, pattern); else { - BGradient *gradient; - if (message.ReadGradient(&gradient) != B_OK) - continue; - - offscreen->FillPolygon(points, numPoints, bounds, - *gradient); - delete gradient; + offscreen->FillPolygon(points, numPoints, bounds, *gradient); } invalidRegion.Include(bounds); @@ -925,25 +960,35 @@ RemoteView::_DrawThread() } case RP_STROKE_RECT: + case RP_STROKE_RECT_GRADIENT: case RP_FILL_RECT: case RP_FILL_RECT_GRADIENT: { BRect rect; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; + if (message.Read(rect) != B_OK) continue; + message.ReadGradient(&gradient); + if (code == RP_STROKE_ARC_GRADIENT || code == RP_FILL_ARC_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + if (code == RP_STROKE_RECT) { offscreen->StrokeRect(rect, pattern); rect.InsetBy(-penSize, -penSize); + } else if (code == RP_STROKE_RECT_GRADIENT) { + offscreen->StrokeRect(rect, *gradient); + rect.InsetBy(-penSize, -penSize); } else if (code == RP_FILL_RECT) offscreen->FillRect(rect, pattern); else { - BGradient *gradient; - if (message.ReadGradient(&gradient) != B_OK) - continue; - offscreen->FillRect(rect, *gradient); - delete gradient; } invalidRegion.Include(rect); @@ -951,31 +996,38 @@ RemoteView::_DrawThread() } case RP_STROKE_ROUND_RECT: + case RP_STROKE_ROUND_RECT_GRADIENT: case RP_FILL_ROUND_RECT: case RP_FILL_ROUND_RECT_GRADIENT: { BRect rect; float xRadius, yRadius; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; message.Read(rect); message.Read(xRadius); if (message.Read(yRadius) != B_OK) continue; + message.ReadGradient(&gradient); + if (code == RP_STROKE_ARC_GRADIENT || code == RP_FILL_ARC_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + if (code == RP_STROKE_ROUND_RECT) { - offscreen->StrokeRoundRect(rect, xRadius, yRadius, - pattern); + offscreen->StrokeRoundRect(rect, xRadius, yRadius, pattern); + rect.InsetBy(-penSize, -penSize); + } else if (code == RP_STROKE_ROUND_RECT_GRADIENT) { + offscreen->StrokeRoundRect(rect, xRadius, yRadius, *gradient); rect.InsetBy(-penSize, -penSize); } else if (code == RP_FILL_ROUND_RECT) offscreen->FillRoundRect(rect, xRadius, yRadius, pattern); else { - BGradient *gradient; - if (message.ReadGradient(&gradient) != B_OK) - continue; - - offscreen->FillRoundRect(rect, xRadius, yRadius, - *gradient); - delete gradient; + offscreen->FillRoundRect(rect, xRadius, yRadius, *gradient); } invalidRegion.Include(rect); @@ -983,6 +1035,7 @@ RemoteView::_DrawThread() } case RP_STROKE_SHAPE: + case RP_STROKE_SHAPE_GRADIENT: case RP_FILL_SHAPE: case RP_FILL_SHAPE_GRADIENT: { @@ -1016,6 +1069,17 @@ RemoteView::_DrawThread() if (message.Read(scale) != B_OK) continue; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; + + message.ReadGradient(&gradient); + if (code == RP_STROKE_SHAPE_GRADIENT || code == RP_FILL_SHAPE_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + offscreen->PushState(); offscreen->MovePenTo(offset); offscreen->SetScale(scale); @@ -1024,17 +1088,13 @@ RemoteView::_DrawThread() if (code == RP_STROKE_SHAPE) { offscreen->StrokeShape(&shape, pattern); bounds.InsetBy(-penSize, -penSize); + } else if (code == RP_STROKE_SHAPE_GRADIENT) { + offscreen->StrokeShape(&shape, *gradient); + bounds.InsetBy(-penSize, -penSize); } else if (code == RP_FILL_SHAPE) offscreen->FillShape(&shape, pattern); else { - BGradient *gradient; - if (message.ReadGradient(&gradient) != B_OK) { - offscreen->PopState(); - continue; - } - offscreen->FillShape(&shape, *gradient); - delete gradient; } offscreen->PopState(); @@ -1043,31 +1103,41 @@ RemoteView::_DrawThread() } case RP_STROKE_TRIANGLE: + case RP_STROKE_TRIANGLE_GRADIENT: case RP_FILL_TRIANGLE: case RP_FILL_TRIANGLE_GRADIENT: { BRect bounds; BPoint points[3]; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; message.ReadList(points, 3); if (message.Read(bounds) != B_OK) continue; + message.ReadGradient(&gradient); + if (code == RP_STROKE_TRIANGLE_GRADIENT || code == RP_FILL_TRIANGLE_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + if (code == RP_STROKE_TRIANGLE) { offscreen->StrokeTriangle(points[0], points[1], points[2], bounds, pattern); bounds.InsetBy(-penSize, -penSize); + } else if (code == RP_STROKE_TRIANGLE_GRADIENT) { + offscreen->StrokeTriangle(points[0], points[1], points[2], + bounds, *gradient); + bounds.InsetBy(-penSize, -penSize); } else if (code == RP_FILL_TRIANGLE) { offscreen->FillTriangle(points[0], points[1], points[2], bounds, pattern); } else { - BGradient *gradient; - if (message.ReadGradient(&gradient) != B_OK) - continue; - offscreen->FillTriangle(points[0], points[1], points[2], bounds, *gradient); - delete gradient; } invalidRegion.Include(bounds); @@ -1075,12 +1145,27 @@ RemoteView::_DrawThread() } case RP_STROKE_LINE: + case RP_STROKE_LINE_GRADIENT: { BPoint points[2]; + BGradient *gradient = NULL; + ObjectDeleter gradientDeleter; + if (message.ReadList(points, 2) != B_OK) continue; - offscreen->StrokeLine(points[0], points[1], pattern); + message.ReadGradient(&gradient); + if (code == RP_STROKE_LINE_GRADIENT) { + if (message.ReadGradient(&gradient) != B_OK) + continue; + + gradientDeleter.SetTo(gradient); + } + + if (code == RP_STROKE_LINE) + offscreen->StrokeLine(points[0], points[1], pattern); + else + offscreen->StrokeLine(points[0], points[1], *gradient); BRect bounds = _BuildInvalidateRect(points, 2); invalidRegion.Include(bounds.InsetBySelf(-penSize, -penSize)); diff --git a/src/kits/interface/PictureDataWriter.cpp b/src/kits/interface/PictureDataWriter.cpp index 07109925d8..6e42f44100 100644 --- a/src/kits/interface/PictureDataWriter.cpp +++ b/src/kits/interface/PictureDataWriter.cpp @@ -676,6 +676,24 @@ PictureDataWriter::WriteDrawShapeGradient(const int32& opCount, const void* opLi } +status_t +PictureDataWriter::WriteStrokeLineGradient(const BPoint& start, const BPoint& end, + const BGradient& gradient) +{ + try { + BeginOp(B_PIC_STROKE_LINE_GRADIENT); + Write(start); + Write(end); + gradient.Flatten(fData); + EndOp(); + } catch (status_t& status) { + return status; + } + + return B_OK; +} + + status_t PictureDataWriter::WriteDrawBitmap(const BRect& srcRect, const BRect& dstRect, const int32& width, const int32& height, const int32& bytesPerRow, diff --git a/src/kits/interface/PicturePlayer.cpp b/src/kits/interface/PicturePlayer.cpp index d832d643de..80479db437 100644 --- a/src/kits/interface/PicturePlayer.cpp +++ b/src/kits/interface/PicturePlayer.cpp @@ -614,6 +614,14 @@ set_fill_rule(void* _context, int32 fillRule) } +static void +stroke_line_gradient(void* _context, const BPoint& start, const BPoint& end, const BGradient& gradient) +{ + adapter_context* context = reinterpret_cast(_context); + ((void (*)(void*, BPoint, BPoint, const BGradient&))context->function_table[71])( + context->user_data, start, end, gradient); +} + #if DEBUG > 1 static const char * @@ -656,6 +664,7 @@ PictureOpToString(int op) RETURN_STRING(B_PIC_FILL_ARC_GRADIENT); RETURN_STRING(B_PIC_STROKE_ELLIPSE_GRADIENT); RETURN_STRING(B_PIC_FILL_ELLIPSE_GRADIENT); + RETURN_STRING(B_PIC_STROKE_LINE_GRADIENT); RETURN_STRING(B_PIC_ENTER_STATE_CHANGE); RETURN_STRING(B_PIC_SET_CLIPPING_RECTS); @@ -774,7 +783,8 @@ PicturePlayer::Play(void** callBackTable, int32 tableEntries, void* userData) draw_ellipse_gradient, draw_polygon_gradient, draw_shape_gradient, - set_fill_rule + set_fill_rule, + stroke_line_gradient }; // We don't check if the functions in the table are NULL, but we @@ -1203,6 +1213,20 @@ PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData, break; } + case B_PIC_STROKE_LINE_GRADIENT: + { + const BPoint* start; + const BPoint* end; + BGradient* gradient; + if (callbacks.stroke_line_gradient == NULL || !reader.Get(start) + || !reader.Get(end) || !reader.GetGradient(gradient)) { + break; + } + + callbacks.stroke_line_gradient(userData, *start, *end, *gradient); + break; + } + case B_PIC_DRAW_STRING: { const int32* length; diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index 39f7af685d..2b4967bb5a 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -3333,6 +3333,31 @@ BView::StrokeEllipse(BRect rect, ::pattern pattern) } +void +BView::StrokeEllipse(BPoint center, float xRadius, float yRadius, + const BGradient& gradient) +{ + StrokeEllipse(BRect(center.x - xRadius, center.y - yRadius, + center.x + xRadius, center.y + yRadius), gradient); +} + + +void +BView::StrokeEllipse(BRect rect, const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_STROKE_ELLIPSE_GRADIENT); + fOwner->fLink->Attach(rect); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::FillEllipse(BPoint center, float xRadius, float yRadius, ::pattern pattern) @@ -3411,6 +3436,34 @@ BView::StrokeArc(BRect rect, float startAngle, float arcAngle, } +void +BView::StrokeArc(BPoint center, float xRadius, float yRadius, float startAngle, + float arcAngle, const BGradient& gradient) +{ + StrokeArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius, + center.y + yRadius), startAngle, arcAngle, gradient); +} + + +void +BView::StrokeArc(BRect rect, float startAngle, float arcAngle, + const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_STROKE_ARC_GRADIENT); + fOwner->fLink->Attach(rect); + fOwner->fLink->Attach(startAngle); + fOwner->fLink->Attach(arcAngle); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle, float arcAngle, ::pattern pattern) @@ -3486,6 +3539,25 @@ BView::StrokeBezier(BPoint* controlPoints, ::pattern pattern) } +void +BView::StrokeBezier(BPoint* controlPoints, const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_STROKE_BEZIER_GRADIENT); + fOwner->fLink->Attach(controlPoints[0]); + fOwner->fLink->Attach(controlPoints[1]); + fOwner->fLink->Attach(controlPoints[2]); + fOwner->fLink->Attach(controlPoints[3]); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::FillBezier(BPoint* controlPoints, ::pattern pattern) { @@ -3576,6 +3648,58 @@ BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, BRect bounds, } +void +BView::StrokePolygon(const BPolygon* polygon, bool closed, const BGradient& gradient) +{ + if (polygon == NULL) + return; + + StrokePolygon(polygon->fPoints, polygon->fCount, polygon->Frame(), closed, + gradient); +} + + +void +BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed, + const BGradient& gradient) +{ + BPolygon polygon(pointArray, numPoints); + + StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed, + gradient); +} + + +void +BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, BRect bounds, + bool closed, const BGradient& gradient) +{ + if (pointArray == NULL + || numPoints <= 1 + || fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + BPolygon polygon(pointArray, numPoints); + polygon.MapTo(polygon.Frame(), bounds); + + if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON_GRADIENT, + polygon.fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(bool) + + sizeof(int32)) == B_OK) { + fOwner->fLink->Attach(polygon.Frame()); + fOwner->fLink->Attach(closed); + fOwner->fLink->Attach(polygon.fCount); + fOwner->fLink->Attach(polygon.fPoints, polygon.fCount * sizeof(BPoint)); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); + } else { + fprintf(stderr, "ERROR: Can't send polygon to app_server!\n"); + } +} + + void BView::FillPolygon(const BPolygon* polygon, ::pattern pattern) { @@ -3695,6 +3819,22 @@ BView::StrokeRect(BRect rect, ::pattern pattern) } +void +BView::StrokeRect(BRect rect, const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_STROKE_RECT_GRADIENT); + fOwner->fLink->Attach(rect); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::FillRect(BRect rect, ::pattern pattern) { @@ -3756,6 +3896,25 @@ BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius, } +void +BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius, + const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_STROKE_ROUNDRECT_GRADIENT); + fOwner->fLink->Attach(rect); + fOwner->fLink->Attach(xRadius); + fOwner->fLink->Attach(yRadius); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::FillRoundRect(BRect rect, float xRadius, float yRadius, ::pattern pattern) @@ -3889,6 +4048,66 @@ BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3, } +void +BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3, BRect bounds, + const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_STROKE_TRIANGLE_GRADIENT); + fOwner->fLink->Attach(point1); + fOwner->fLink->Attach(point2); + fOwner->fLink->Attach(point3); + fOwner->fLink->Attach(bounds); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + +void +BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3, + const BGradient& gradient) +{ + if (fOwner) { + // we construct the smallest rectangle that contains the 3 points + // for the 1st point + BRect bounds(point1, point1); + + // for the 2nd point + if (point2.x < bounds.left) + bounds.left = point2.x; + + if (point2.y < bounds.top) + bounds.top = point2.y; + + if (point2.x > bounds.right) + bounds.right = point2.x; + + if (point2.y > bounds.bottom) + bounds.bottom = point2.y; + + // for the 3rd point + if (point3.x < bounds.left) + bounds.left = point3.x; + + if (point3.y < bounds.top) + bounds.top = point3.y; + + if (point3.x > bounds.right) + bounds.right = point3.x; + + if (point3.y > bounds.bottom) + bounds.bottom = point3.y; + + StrokeTriangle(point1, point2, point3, bounds, gradient); + } +} + + void BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3, ::pattern pattern) @@ -4038,6 +4257,36 @@ BView::StrokeLine(BPoint start, BPoint end, ::pattern pattern) } +void +BView::StrokeLine(BPoint toPoint, const BGradient& gradient) +{ + StrokeLine(PenLocation(), toPoint, gradient); +} + + +void +BView::StrokeLine(BPoint start, BPoint end, const BGradient& gradient) +{ + if (fOwner == NULL) + return; + + _CheckLockAndSwitchCurrent(); + + ViewStrokeLineInfo info; + info.startPoint = start; + info.endPoint = end; + + fOwner->fLink->StartMessage(AS_STROKE_LINE_GRADIENT); + fOwner->fLink->Attach(info); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); + + // this modifies our pen location, so we invalidate the flag. + fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT; +} + + void BView::StrokeShape(BShape* shape, ::pattern pattern) { @@ -4059,6 +4308,27 @@ BView::StrokeShape(BShape* shape, ::pattern pattern) } +void +BView::StrokeShape(BShape* shape, const BGradient& gradient) +{ + if (shape == NULL || fOwner == NULL) + return; + + shape_data* sd = BShape::Private(*shape).PrivateData(); + if (sd->opCount == 0 || sd->ptCount == 0) + return; + + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_STROKE_SHAPE_GRADIENT); + fOwner->fLink->Attach(shape->Bounds()); + fOwner->fLink->AttachShape(*shape); + fOwner->fLink->AttachGradient(gradient); + + _FlushIfNotInTransaction(); +} + + void BView::FillShape(BShape* shape, ::pattern pattern) { diff --git a/src/servers/app/ServerPicture.cpp b/src/servers/app/ServerPicture.cpp index b3813354b4..622fadd9b7 100644 --- a/src/servers/app/ServerPicture.cpp +++ b/src/servers/app/ServerPicture.cpp @@ -220,9 +220,9 @@ ShapePainter::Draw(BRect frame, bool filled) transform.Apply(&frame); /* stroked gradients are not yet supported */ - if (fGradient != NULL && filled) { - fCanvas->GetDrawingEngine()->FillShape(frame, opCount, opList, - ptCount, ptList, *fGradient, screenOffset, fCanvas->Scale()); + if (fGradient != NULL) { + fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList, + ptCount, ptList, filled, *fGradient, screenOffset, fCanvas->Scale()); } else { fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList, ptCount, ptList, filled, screenOffset, fCanvas->Scale()); @@ -420,8 +420,8 @@ draw_round_rect_gradient(void* _canvas, const BRect& _rect, const BPoint& radii, transform.Apply(&rect); transform.Apply(&gradient); float scale = canvas->CurrentState()->CombinedScale(); - canvas->GetDrawingEngine()->FillRoundRect(rect, radii.x * scale, - radii.y * scale, gradient); + canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale, + radii.y * scale, fill, gradient); } @@ -437,7 +437,7 @@ draw_bezier_gradient(void* _canvas, const BPoint viewPoints[4], BGradient& gradi canvas->PenToScreenTransform(); transform.Apply(points, viewPoints, kNumPoints); transform.Apply(&gradient); - canvas->GetDrawingEngine()->FillBezier(points, gradient); + canvas->GetDrawingEngine()->DrawBezier(points, fill, gradient); } @@ -453,7 +453,7 @@ draw_arc_gradient(void* _canvas, const BPoint& center, const BPoint& radii, canvas->PenToScreenTransform(); transform.Apply(&rect); transform.Apply(&gradient); - canvas->GetDrawingEngine()->FillArc(rect, startTheta, arcTheta, gradient); + canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill, gradient); } @@ -467,7 +467,7 @@ draw_ellipse_gradient(void* _canvas, const BRect& _rect, BGradient& gradient, bo canvas->PenToScreenTransform(); transform.Apply(&rect); transform.Apply(&gradient); - canvas->GetDrawingEngine()->FillEllipse(rect, gradient); + canvas->GetDrawingEngine()->DrawEllipse(rect, fill, gradient); } @@ -492,8 +492,8 @@ draw_polygon_gradient(void* _canvas, size_t numPoints, const BPoint viewPoints[] BRect polyFrame; get_polygon_frame(points, numPoints, &polyFrame); - canvas->GetDrawingEngine()->FillPolygon(points, numPoints, polyFrame, - gradient, isClosed && numPoints > 2); + canvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, + isClosed && numPoints > 2, fill, gradient); } @@ -508,6 +508,26 @@ draw_shape_gradient(void* _canvas, const BShape& shape, BGradient& gradient, boo } +static void +stroke_line_gradient(void* _canvas, const BPoint& _start, const BPoint& _end, + const BGradient& gradient) +{ + Canvas* const canvas = reinterpret_cast(_canvas); + BPoint start = _start; + BPoint end = _end; + + const SimpleTransform transform = canvas->PenToScreenTransform(); + transform.Apply(&start); + transform.Apply(&end); + canvas->GetDrawingEngine()->StrokeLine(start, end, gradient); + + canvas->CurrentState()->SetPenLocation(_end); + // the DrawingEngine/Painter does not need to be updated, since this + // effects only the view->screen coord conversion, which is handled + // by the view only +} + + static void draw_string(void* _canvas, const char* string, size_t length, float deltaSpace, float deltaNonSpace) @@ -1065,7 +1085,8 @@ static const BPrivate::picture_player_callbacks kPicturePlayerCallbacks = { draw_ellipse_gradient, draw_polygon_gradient, draw_shape_gradient, - set_fill_rule + set_fill_rule, + stroke_line_gradient }; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 3b73c480db..2ab8f751c5 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -2556,6 +2556,41 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, fCurrentView->CurrentState()->SetPenLocation(penPos); break; } + case AS_STROKE_LINE_GRADIENT: + { + ViewStrokeLineInfo info; + if (link.Read(&info) != B_OK) + break; + + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + + ObjectDeleter gradientDeleter(gradient); + + DTRACE(("ServerWindow %s: Message AS_STROKE_LINE: View: %s -> " + "BPoint(%.1f, %.1f) - BPoint(%.1f, %.1f)\n", Title(), + fCurrentView->Name(), + info.startPoint.x, info.startPoint.y, + info.endPoint.x, info.endPoint.y)); + + BPoint penPos = info.endPoint; + const SimpleTransform transform = + fCurrentView->PenToScreenTransform(); + transform.Apply(&info.startPoint); + transform.Apply(&info.endPoint); + drawingEngine->StrokeLine(info.startPoint, info.endPoint, *gradient); + + // We update the pen here because many DrawingEngine calls which + // do not update the pen position actually call StrokeLine + + // TODO: Decide where to put this, for example, it cannot be done + // for DrawString(), also there needs to be a decision, if the pen + // location is in View coordinates (I think it should be) or in + // screen coordinates. + fCurrentView->CurrentState()->SetPenLocation(penPos); + break; + } case AS_VIEW_INVERT_RECT: { BRect rect; @@ -2601,6 +2636,27 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, drawingEngine->FillRect(rect); break; } + case AS_STROKE_RECT_GRADIENT: + { + BRect rect; + link.Read(&rect); + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + + GTRACE(("ServerWindow %s: Message AS_STROKE_RECT_GRADIENT: View: %s " + "-> BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(), + fCurrentView->Name(), rect.left, rect.top, rect.right, + rect.bottom)); + + const SimpleTransform transform = + fCurrentView->PenToScreenTransform(); + transform.Apply(&rect); + transform.Apply(gradient); + drawingEngine->StrokeRect(rect, *gradient); + delete gradient; + break; + } case AS_FILL_RECT_GRADIENT: { BRect rect; @@ -2674,9 +2730,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC); break; } + case AS_STROKE_ARC_GRADIENT: case AS_FILL_ARC_GRADIENT: { - GTRACE(("ServerWindow %s: Message AS_FILL_ARC_GRADIENT\n", + GTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ARC_GRADIENT\n", Title())); float angle, span; @@ -2691,7 +2748,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, fCurrentView->PenToScreenTransform(); transform.Apply(&r); transform.Apply(gradient); - drawingEngine->FillArc(r, angle, span, *gradient); + drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC_GRADIENT, *gradient); delete gradient; break; } @@ -2715,9 +2772,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, drawingEngine->DrawBezier(pts, code == AS_FILL_BEZIER); break; } + case AS_STROKE_BEZIER_GRADIENT: case AS_FILL_BEZIER_GRADIENT: { - GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n", + GTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER_GRADIENT\n", Title())); const SimpleTransform transform = @@ -2731,7 +2789,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, if (link.ReadGradient(&gradient) != B_OK) break; transform.Apply(gradient); - drawingEngine->FillBezier(pts, *gradient); + drawingEngine->DrawBezier(pts, code == AS_FILL_BEZIER_GRADIENT, *gradient); delete gradient; break; } @@ -2749,9 +2807,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE); break; } + case AS_STROKE_ELLIPSE_GRADIENT: case AS_FILL_ELLIPSE_GRADIENT: { - GTRACE(("ServerWindow %s: Message AS_FILL_ELLIPSE_GRADIENT\n", + GTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ELLIPSE_GRADIENT\n", Title())); BRect rect; @@ -2763,7 +2822,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, fCurrentView->PenToScreenTransform(); transform.Apply(&rect); transform.Apply(gradient); - drawingEngine->FillEllipse(rect, *gradient); + drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE_GRADIENT, *gradient); delete gradient; break; } @@ -2787,9 +2846,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, code == AS_FILL_ROUNDRECT); break; } + case AS_STROKE_ROUNDRECT_GRADIENT: case AS_FILL_ROUNDRECT_GRADIENT: { - GTRACE(("ServerWindow %s: Message AS_FILL_ROUNDRECT_GRADIENT\n", + GTRACE(("ServerWindow %s: Message AS_FILL_STROKE/FILL_GRADIENT\n", Title())); BRect rect; @@ -2804,7 +2864,8 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, fCurrentView->PenToScreenTransform(); transform.Apply(&rect); transform.Apply(gradient); - drawingEngine->FillRoundRect(rect, xrad, yrad, *gradient); + drawingEngine->DrawRoundRect(rect, xrad, yrad, code == AS_FILL_ROUNDRECT_GRADIENT, + *gradient); delete gradient; break; } @@ -2831,9 +2892,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE); break; } + case AS_STROKE_TRIANGLE_GRADIENT: case AS_FILL_TRIANGLE_GRADIENT: { - DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n", + DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE_GRADIENT\n", Title())); const SimpleTransform transform = @@ -2850,7 +2912,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, break; transform.Apply(&rect); transform.Apply(gradient); - drawingEngine->FillTriangle(pts, rect, *gradient); + drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE_GRADIENT, *gradient); delete gradient; break; } @@ -2883,15 +2945,18 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, delete[] pointList; break; } + case AS_STROKE_POLYGON_GRADIENT: case AS_FILL_POLYGON_GRADIENT: { - DTRACE(("ServerWindow %s: Message AS_FILL_POLYGON_GRADIENT\n", + DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_POLYGON_GRADIENT\n", Title())); BRect polyFrame; bool isClosed = true; int32 pointCount; link.Read(&polyFrame); + if (code == AS_STROKE_POLYGON_GRADIENT) + link.Read(&isClosed); link.Read(&pointCount); const SimpleTransform transform = @@ -2905,8 +2970,9 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, transform.Apply(&polyFrame); transform.Apply(gradient); - drawingEngine->FillPolygon(pointList, pointCount, - polyFrame, *gradient, isClosed && pointCount > 2); + drawingEngine->DrawPolygon(pointList, pointCount, + polyFrame, code == AS_FILL_POLYGON_GRADIENT, isClosed && pointCount > 2, + *gradient); delete gradient; } delete[] pointList; @@ -2951,9 +3017,10 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, delete[] ptList; break; } + case AS_STROKE_SHAPE_GRADIENT: case AS_FILL_SHAPE_GRADIENT: { - DTRACE(("ServerWindow %s: Message AS_FILL_SHAPE_GRADIENT\n", + DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_SHAPE_GRADIENT\n", Title())); BRect shapeFrame; @@ -2982,8 +3049,8 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, transform.Apply(&screenOffset); transform.Apply(&shapeFrame); transform.Apply(gradient); - drawingEngine->FillShape(shapeFrame, opCount, opList, - ptCount, ptList, *gradient, screenOffset, + drawingEngine->DrawShape(shapeFrame, opCount, opList, + ptCount, ptList, code == AS_FILL_SHAPE_GRADIENT, *gradient, screenOffset, fCurrentView->Scale()); delete gradient; } @@ -3519,7 +3586,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } - //case AS_STROKE_RECT_GRADIENT: + case AS_STROKE_RECT_GRADIENT: case AS_FILL_RECT_GRADIENT: { BRect rect; @@ -3533,7 +3600,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } - //case AS_STROKE_ARC_GRADIENT: + case AS_STROKE_ARC_GRADIENT: case AS_FILL_ARC_GRADIENT: { BRect rect; @@ -3554,7 +3621,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } - //case AS_STROKE_BEZIER_GRADIENT: + case AS_STROKE_BEZIER_GRADIENT: case AS_FILL_BEZIER_GRADIENT: { BPoint points[4]; @@ -3570,7 +3637,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } - //case AS_STROKE_ELLIPSE_GRADIENT: + case AS_STROKE_ELLIPSE_GRADIENT: case AS_FILL_ELLIPSE_GRADIENT: { BRect rect; @@ -3584,7 +3651,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } - //case AS_STROKE_ROUNDRECT_GRADIENT: + case AS_STROKE_ROUNDRECT_GRADIENT: case AS_FILL_ROUNDRECT_GRADIENT: { BRect rect; @@ -3602,7 +3669,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } - //case AS_STROKE_TRIANGLE_GRADIENT: + case AS_STROKE_TRIANGLE_GRADIENT: case AS_FILL_TRIANGLE_GRADIENT: { // There is no B_PIC_FILL/STROKE_TRIANGLE op, @@ -3625,7 +3692,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } - //case AS_STROKE_POLYGON_GRADIENT: + case AS_STROKE_POLYGON_GRADIENT: case AS_FILL_POLYGON_GRADIENT: { BRect polyFrame; @@ -3634,7 +3701,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) const bool fill = (code == AS_FILL_POLYGON_GRADIENT); link.Read(&polyFrame); - if (code == AS_STROKE_POLYGON) + if (code == AS_STROKE_POLYGON_GRADIENT) link.Read(&isClosed); link.Read(&pointCount); @@ -3652,7 +3719,7 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } - //case AS_STROKE_SHAPE_GRADIENT: + case AS_STROKE_SHAPE_GRADIENT: case AS_FILL_SHAPE_GRADIENT: { BRect shapeFrame; @@ -3721,6 +3788,26 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } + case AS_STROKE_LINE_GRADIENT: + { + ViewStrokeLineInfo info; + link.Read(&info); + + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + picture->WriteStrokeLineGradient(info.startPoint, info.endPoint, *gradient); + + BPoint penPos = info.endPoint; + const SimpleTransform transform = + fCurrentView->PenToScreenTransform(); + transform.Apply(&info.endPoint); + fCurrentView->CurrentState()->SetPenLocation(penPos); + break; + } + case AS_STROKE_LINEARRAY: { int32 lineCount; diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index 9afffa4855..93847b2941 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -670,8 +670,8 @@ DrawingEngine::DrawArc(BRect r, const float& angle, const float& span, void -DrawingEngine::FillArc(BRect r, const float& angle, const float& span, - const BGradient& gradient) +DrawingEngine::DrawArc(BRect r, const float& angle, const float& span, + bool filled, const BGradient& gradient) { ASSERT_PARALLEL_LOCKED(); @@ -686,7 +686,10 @@ DrawingEngine::FillArc(BRect r, const float& angle, const float& span, BPoint center(r.left + xRadius, r.top + yRadius); - fPainter->FillArc(center, xRadius, yRadius, angle, span, gradient); + if (filled) + fPainter->FillArc(center, xRadius, yRadius, angle, span, gradient); + else + fPainter->StrokeArc(center, xRadius, yRadius, angle, span, gradient); } @@ -703,14 +706,14 @@ DrawingEngine::DrawBezier(BPoint* pts, bool filled) void -DrawingEngine::FillBezier(BPoint* pts, const BGradient& gradient) +DrawingEngine::DrawBezier(BPoint* pts, bool filled, const BGradient& gradient) { ASSERT_PARALLEL_LOCKED(); // TODO: figure out bounds and hide cursor depending on that DrawTransaction transaction(this); - transaction.SetDirty(fPainter->FillBezier(pts, gradient)); + transaction.SetDirty(fPainter->DrawBezier(pts, filled, gradient)); } @@ -740,13 +743,16 @@ DrawingEngine::DrawEllipse(BRect r, bool filled) void -DrawingEngine::FillEllipse(BRect r, const BGradient& gradient) +DrawingEngine::DrawEllipse(BRect r, bool filled, const BGradient& gradient) { ASSERT_PARALLEL_LOCKED(); make_rect_valid(r); BRect clipped = r; - fPainter->AlignEllipseRect(&clipped, true); + fPainter->AlignEllipseRect(&clipped, filled); + + if (!filled) + extend_by_stroke_width(clipped, fPainter->PenSize()); clipped.left = floorf(clipped.left); clipped.top = floorf(clipped.top); @@ -757,7 +763,7 @@ DrawingEngine::FillEllipse(BRect r, const BGradient& gradient) if (!transaction.IsDirty()) return; - fPainter->FillEllipse(r, gradient); + fPainter->DrawEllipse(r, filled, gradient); } @@ -779,17 +785,19 @@ DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds, void -DrawingEngine::FillPolygon(BPoint* ptlist, int32 numpts, BRect bounds, - const BGradient& gradient, bool closed) +DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds, + bool filled, bool closed, const BGradient& gradient) { ASSERT_PARALLEL_LOCKED(); make_rect_valid(bounds); + if (!filled) + extend_by_stroke_width(bounds, fPainter->PenSize()); DrawTransaction transaction(this, fPainter->TransformAndClipRect(bounds)); if (!transaction.IsDirty()) return; - fPainter->FillPolygon(ptlist, numpts, gradient, closed); + fPainter->DrawPolygon(ptlist, numpts, filled, closed, gradient); } @@ -928,6 +936,23 @@ DrawingEngine::FillRect(BRect r) } +void +DrawingEngine::StrokeRect(BRect r, const BGradient& gradient) +{ + ASSERT_PARALLEL_LOCKED(); + + // support invalid rects + make_rect_valid(r); + BRect clipped(r); + extend_by_stroke_width(clipped, fPainter->PenSize()); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(clipped)); + if (!transaction.IsDirty()) + return; + + fPainter->StrokeRect(r, gradient); +} + + void DrawingEngine::FillRect(BRect r, const BGradient& gradient) { @@ -1003,12 +1028,14 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, bool filled) void -DrawingEngine::FillRoundRect(BRect r, float xrad, float yrad, - const BGradient& gradient) +DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, + bool filled, const BGradient& gradient) { ASSERT_PARALLEL_LOCKED(); make_rect_valid(r); + if (!filled) + extend_by_stroke_width(r, fPainter->PenSize()); BRect clipped = fPainter->TransformAndClipRect(r); clipped.left = floorf(clipped.left); @@ -1020,7 +1047,10 @@ DrawingEngine::FillRoundRect(BRect r, float xrad, float yrad, if (!transaction.IsDirty()) return; - fPainter->FillRoundRect(r, xrad, yrad, gradient); + if (filled) + fPainter->FillRoundRect(r, xrad, yrad, gradient); + else + fPainter->StrokeRoundRect(r, xrad, yrad, gradient); } @@ -1053,9 +1083,9 @@ DrawingEngine::DrawShape(const BRect& bounds, int32 opCount, void -DrawingEngine::FillShape(const BRect& bounds, int32 opCount, +DrawingEngine::DrawShape(const BRect& bounds, int32 opCount, const uint32* opList, int32 ptCount, const BPoint* ptList, - const BGradient& gradient, const BPoint& viewToScreenOffset, + bool filled, const BGradient& gradient, const BPoint& viewToScreenOffset, float viewScale) { ASSERT_PARALLEL_LOCKED(); @@ -1073,8 +1103,8 @@ DrawingEngine::FillShape(const BRect& bounds, int32 opCount, // return; DrawTransaction transaction(this); - transaction.SetDirty(fPainter->FillShape(opCount, opList, ptCount, ptList, - gradient, viewToScreenOffset, viewScale)); + transaction.SetDirty(fPainter->DrawShape(opCount, opList, ptCount, ptList, + filled, gradient, viewToScreenOffset, viewScale)); } @@ -1098,16 +1128,22 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, bool filled) void -DrawingEngine::FillTriangle(BPoint* pts, const BRect& bounds, - const BGradient& gradient) +DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, + bool filled, const BGradient& gradient) { ASSERT_PARALLEL_LOCKED(); - DrawTransaction transaction(this, fPainter->TransformAndClipRect(bounds)); + BRect clipped(bounds); + if (!filled) + extend_by_stroke_width(clipped, fPainter->PenSize()); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(clipped)); if (!transaction.IsDirty()) return; - fPainter->FillTriangle(pts[0], pts[1], pts[2], gradient); + if (filled) + fPainter->FillTriangle(pts[0], pts[1], pts[2], gradient); + else + fPainter->StrokeTriangle(pts[0], pts[1], pts[2], gradient); } @@ -1127,6 +1163,22 @@ DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end) } +void +DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end, const BGradient& gradient) +{ + ASSERT_PARALLEL_LOCKED(); + + BRect touched(start, end); + make_rect_valid(touched); + extend_by_stroke_width(touched, fPainter->PenSize()); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(touched)); + if (!transaction.IsDirty()) + return; + + fPainter->StrokeLine(start, end, gradient); +} + + void DrawingEngine::StrokeLineArray(int32 numLines, const ViewLineArrayInfo *lineData) diff --git a/src/servers/app/drawing/DrawingEngine.h b/src/servers/app/drawing/DrawingEngine.h index e02b6d1abf..98e829b184 100644 --- a/src/servers/app/drawing/DrawingEngine.h +++ b/src/servers/app/drawing/DrawingEngine.h @@ -102,20 +102,20 @@ public: // drawing primitives virtual void DrawArc(BRect r, const float& angle, const float& span, bool filled); - virtual void FillArc(BRect r, const float& angle, - const float& span, const BGradient& gradient); + virtual void DrawArc(BRect r, const float& angle, + const float& span, bool filled, const BGradient& gradient); virtual void DrawBezier(BPoint* pts, bool filled); - virtual void FillBezier(BPoint* pts, const BGradient& gradient); + virtual void DrawBezier(BPoint* pts, bool filled, const BGradient& gradient); virtual void DrawEllipse(BRect r, bool filled); - virtual void FillEllipse(BRect r, const BGradient& gradient); + virtual void DrawEllipse(BRect r, bool filled, const BGradient& gradient); virtual void DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds, bool filled, bool closed); - virtual void FillPolygon(BPoint* ptlist, int32 numpts, - BRect bounds, const BGradient& gradient, - bool closed); + virtual void DrawPolygon(BPoint* ptlist, int32 numpts, + BRect bounds, bool filled, bool closed, + const BGradient& gradient); // these rgb_color versions are used internally by the server virtual void StrokePoint(const BPoint& point, @@ -125,6 +125,7 @@ public: virtual void FillRegion(BRegion& region, const rgb_color& color); virtual void StrokeRect(BRect rect); + virtual void StrokeRect(BRect rect, const BGradient& gradient); virtual void FillRect(BRect rect); virtual void FillRect(BRect rect, const BGradient& gradient); @@ -134,25 +135,25 @@ public: virtual void DrawRoundRect(BRect rect, float xrad, float yrad, bool filled); - virtual void FillRoundRect(BRect rect, float xrad, - float yrad, const BGradient& gradient); + virtual void DrawRoundRect(BRect rect, float xrad, + float yrad, bool filled, const BGradient& gradient); virtual void DrawShape(const BRect& bounds, int32 opcount, const uint32* oplist, int32 ptcount, const BPoint* ptlist, bool filled, const BPoint& viewToScreenOffset, float viewScale); - virtual void FillShape(const BRect& bounds, + virtual void DrawShape(const BRect& bounds, int32 opcount, const uint32* oplist, - int32 ptcount, const BPoint* ptlist, - const BGradient& gradient, - const BPoint& viewToScreenOffset, + int32 ptcount, const BPoint* ptlist, + bool filled, const BGradient& gradient, + const BPoint& viewToScreenOffset, float viewScale); virtual void DrawTriangle(BPoint* points, const BRect& bounds, bool filled); - virtual void FillTriangle(BPoint* points, const BRect& bounds, - const BGradient& gradient); + virtual void DrawTriangle(BPoint* points, const BRect& bounds, + bool filled, const BGradient& gradient); // these versions are used by the Decorator virtual void StrokeLine(const BPoint& start, @@ -160,6 +161,8 @@ public: virtual void StrokeLine(const BPoint& start, const BPoint& end); + virtual void StrokeLine(const BPoint& start, + const BPoint& end, const BGradient& gradient); virtual void StrokeLineArray(int32 numlines, const ViewLineArrayInfo* data); diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index a903e8561d..3010d30305 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -566,6 +566,48 @@ Painter::StrokeLine(BPoint a, BPoint b) } +// StrokeLine +void +Painter::StrokeLine(BPoint a, BPoint b, const BGradient& gradient) +{ + CHECK_CLIPPING_NO_RETURN + + // "false" means not to do the pixel center offset, + // because it would mess up our optimized versions + _Align(&a, false); + _Align(&b, false); + + fPath.remove_all(); + + if (a == b) { + // special case dots + fPath.move_to(a.x, a.y); + fPath.line_to(a.x + 1, a.y); + fPath.line_to(a.x + 1, a.y + 1); + fPath.line_to(a.x, a.y + 1); + + _FillPath(fPath, gradient); + } else { + // Do the pixel center offset here + if (!fSubpixelPrecise && fmodf(fPenSize, 2.0) != 0.0) { + _Align(&a, true); + _Align(&b, true); + } + + fPath.move_to(a.x, a.y); + fPath.line_to(b.x, b.y); + + if (!fSubpixelPrecise && fPenSize == 1.0f) { + // Tweak ends to "include" the pixel at the index, + // we need to do this in order to produce results like R5, + // where coordinates were inclusive + _StrokePath(fPath, B_SQUARE_CAP, gradient); + } else + _StrokePath(fPath, gradient); + } +} + + // StraightLine bool Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const @@ -649,6 +691,14 @@ Painter::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3) const } +// StrokeTriangle +BRect +Painter::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, const BGradient& gradient) +{ + return _DrawTriangle(pt1, pt2, pt3, false, gradient); +} + + // FillTriangle BRect Painter::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3) const @@ -662,21 +712,7 @@ BRect Painter::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, const BGradient& gradient) { - CHECK_CLIPPING - - _Align(&pt1); - _Align(&pt2); - _Align(&pt3); - - fPath.remove_all(); - - fPath.move_to(pt1.x, pt1.y); - fPath.line_to(pt2.x, pt2.y); - fPath.line_to(pt3.x, pt3.y); - - fPath.close_polygon(); - - return _FillPath(fPath, gradient); + return _DrawTriangle(pt1, pt2, pt3, true, gradient); } @@ -715,29 +751,34 @@ Painter::DrawPolygon(BPoint* p, int32 numPts, bool filled, bool closed) const // FillPolygon BRect -Painter::FillPolygon(BPoint* p, int32 numPts, const BGradient& gradient, - bool closed) +Painter::DrawPolygon(BPoint* p, int32 numPts, bool filled, bool closed, const BGradient& gradient) { CHECK_CLIPPING - if (numPts > 0) { - fPath.remove_all(); + if (numPts == 0) + return BRect(0.0, 0.0, -1.0, -1.0); - _Align(p); - fPath.move_to(p->x, p->y); + bool centerOffset = !filled && fIdentityTransform + && fmodf(fPenSize, 2.0) != 0.0; - for (int32 i = 1; i < numPts; i++) { - p++; - _Align(p); - fPath.line_to(p->x, p->y); - } + fPath.remove_all(); - if (closed) - fPath.close_polygon(); + _Align(p, centerOffset); + fPath.move_to(p->x, p->y); - return _FillPath(fPath, gradient); + for (int32 i = 1; i < numPts; i++) { + p++; + _Align(p, centerOffset); + fPath.line_to(p->x, p->y); } - return BRect(0.0, 0.0, -1.0, -1.0); + + if (closed) + fPath.close_polygon(); + + if (filled) + return _FillPath(fPath, gradient); + + return _StrokePath(fPath, gradient); } @@ -768,7 +809,7 @@ Painter::DrawBezier(BPoint* p, bool filled) const // FillBezier BRect -Painter::FillBezier(BPoint* p, const BGradient& gradient) +Painter::DrawBezier(BPoint* p, bool filled, const BGradient& gradient) { CHECK_CLIPPING @@ -782,8 +823,12 @@ Painter::FillBezier(BPoint* p, const BGradient& gradient) fPath.move_to(p[0].x, p[0].y); fPath.curve4(p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y); - fPath.close_polygon(); - return _FillPath(fCurve, gradient); + if (filled) { + fPath.close_polygon(); + return _FillPath(fCurve, gradient); + } + + return _StrokePath(fCurve, gradient); } @@ -807,8 +852,8 @@ 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, +Painter::DrawShape(const int32& opCount, const uint32* opList, + const int32& ptCount, const BPoint* points, bool filled, const BGradient& gradient, const BPoint& viewToScreenOffset, float viewScale) { CHECK_CLIPPING @@ -816,7 +861,10 @@ Painter::FillShape(const int32& opCount, const uint32* opList, _IterateShapeData(opCount, opList, ptCount, points, viewToScreenOffset, viewScale); - return _FillPath(fCurve, gradient); + if (filled) + return _FillPath(fCurve, gradient); + + return _StrokePath(fCurve, gradient); } @@ -871,6 +919,41 @@ Painter::StrokeRect(const BRect& r) const } +// StrokeRect +BRect +Painter::StrokeRect(const BRect& r, const BGradient& gradient) +{ + CHECK_CLIPPING + + BPoint a(r.left, r.top); + BPoint b(r.right, r.bottom); + _Align(&a, false); + _Align(&b, false); + + if (fIdentityTransform && fmodf(fPenSize, 2.0) != 0.0) { + // shift coords to center of pixels + a.x += 0.5; + a.y += 0.5; + b.x += 0.5; + b.y += 0.5; + } + + fPath.remove_all(); + fPath.move_to(a.x, a.y); + if (a.x == b.x || a.y == b.y) { + // special case rects with one pixel height or width + fPath.line_to(b.x, b.y); + } else { + fPath.line_to(b.x, a.y); + fPath.line_to(b.x, b.y); + fPath.line_to(a.x, b.y); + } + fPath.close_polygon(); + + return _StrokePath(fPath, gradient); +} + + // StrokeRect void Painter::StrokeRect(const BRect& r, const rgb_color& c) const @@ -1129,6 +1212,27 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const } +// StrokeRoundRect +BRect +Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius, + const BGradient& gradient) +{ + CHECK_CLIPPING + + BPoint lt(r.left, r.top); + BPoint rb(r.right, r.bottom); + bool centerOffset = fmodf(fPenSize, 2.0) != 0.0; + _Align(<, centerOffset); + _Align(&rb, centerOffset); + + agg::rounded_rect rect; + rect.rect(lt.x, lt.y, rb.x, rb.y); + rect.radius(xRadius, yRadius); + + return _StrokePath(rect, gradient); +} + + // FillRoundRect BRect Painter::FillRoundRect(const BRect& r, float xRadius, float yRadius) const @@ -1227,11 +1331,11 @@ Painter::DrawEllipse(BRect r, bool fill) const // FillEllipse BRect -Painter::FillEllipse(BRect r, const BGradient& gradient) +Painter::DrawEllipse(BRect r, bool fill, const BGradient& gradient) { CHECK_CLIPPING - AlignEllipseRect(&r, true); + AlignEllipseRect(&r, fill); float xRadius = r.Width() / 2.0; float yRadius = r.Height() / 2.0; @@ -1245,7 +1349,10 @@ Painter::FillEllipse(BRect r, const BGradient& gradient) agg::ellipse path(center.x, center.y, xRadius, yRadius, divisions); - return _FillPath(path, gradient); + if (fill) + return _FillPath(path, gradient); + else + return _StrokePath(path, gradient); } @@ -1270,6 +1377,27 @@ Painter::StrokeArc(BPoint center, float xRadius, float yRadius, float angle, } +// StrokeArc +BRect +Painter::StrokeArc(BPoint center, float xRadius, float yRadius, float angle, + float span, const BGradient& gradient) +{ + CHECK_CLIPPING + + _Align(¢er); + + double angleRad = (angle * M_PI) / 180.0; + double spanRad = (span * M_PI) / 180.0; + agg::bezier_arc arc(center.x, center.y, xRadius, yRadius, -angleRad, + -spanRad); + + agg::conv_curve path(arc); + path.approximation_scale(2.0); + + return _StrokePath(path, gradient); +} + + // FillArc BRect Painter::FillArc(BPoint center, float xRadius, float yRadius, float angle, @@ -1630,6 +1758,30 @@ Painter::_DrawTriangle(BPoint pt1, BPoint pt2, BPoint pt3, bool fill) const } +inline BRect +Painter::_DrawTriangle(BPoint pt1, BPoint pt2, BPoint pt3, bool fill, const BGradient& gradient) +{ + CHECK_CLIPPING + + _Align(&pt1); + _Align(&pt2); + _Align(&pt3); + + fPath.remove_all(); + + fPath.move_to(pt1.x, pt1.y); + fPath.line_to(pt2.x, pt2.y); + fPath.line_to(pt3.x, pt3.y); + + fPath.close_polygon(); + + if (fill) + return _FillPath(fPath, gradient); + + return _StrokePath(fPath, gradient); +} + + void Painter::_IterateShapeData(const int32& opCount, const uint32* opList, const int32& ptCount, const BPoint* points, @@ -1832,6 +1984,36 @@ Painter::_StrokePath(VertexSource& path, cap_mode capMode) const } +template +BRect +Painter::_StrokePath(VertexSource& path, const BGradient& gradient) +{ + return _StrokePath(path, fLineCapMode, gradient); +} + + +template +BRect +Painter::_StrokePath(VertexSource& path, cap_mode capMode, const BGradient& gradient) +{ + agg::conv_stroke stroke(path); + stroke.width(fPenSize); + + stroke.line_cap(agg_line_cap_mode_for(capMode)); + stroke.line_join(agg_line_join_mode_for(fLineJoinMode)); + stroke.miter_limit(fMiterLimit); + + if (fIdentityTransform) + return _RasterizePath(stroke, gradient); + + stroke.approximation_scale(fTransform.scale()); + + agg::conv_transform > transformedStroke( + stroke, fTransform); + return _RasterizePath(transformedStroke, gradient); +} + + // _FillPath template BRect diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index ee6eba4d19..28801cadbf 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -107,6 +107,7 @@ public: // lines void StrokeLine(BPoint a, BPoint b); + void StrokeLine(BPoint a, BPoint b, const BGradient& gradient); // returns true if the line was either vertical or horizontal // draws a solid one pixel wide line of color c, no blending @@ -116,6 +117,8 @@ public: // triangles BRect StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3) const; + BRect StrokeTriangle(BPoint pt1, BPoint pt2, + BPoint pt3, const BGradient& gradient); BRect FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3) const; @@ -126,15 +129,14 @@ public: // polygons BRect DrawPolygon(BPoint* ptArray, int32 numPts, bool filled, bool closed) const; - BRect FillPolygon(BPoint* ptArray, int32 numPts, - const BGradient& gradient, - bool closed); + BRect DrawPolygon(BPoint* ptArray, int32 numPts, + bool filled, bool closed, const BGradient& gradient); // bezier curves BRect DrawBezier(BPoint* controlPoints, bool filled) const; - BRect FillBezier(BPoint* controlPoints, - const BGradient& gradient); + BRect DrawBezier(BPoint* controlPoints, + bool filled, const BGradient& gradient); // shapes BRect DrawShape(const int32& opCount, @@ -142,15 +144,17 @@ public: const BPoint* ptList, bool filled, const BPoint& viewToScreenOffset, float viewScale) const; - BRect FillShape(const int32& opCount, + BRect DrawShape(const int32& opCount, const uint32* opList, const int32& ptCount, - const BPoint* ptList, + const BPoint* ptList, bool filled, const BGradient& gradient, const BPoint& viewToScreenOffset, float viewScale); // rects BRect StrokeRect(const BRect& r) const; + BRect StrokeRect(const BRect& r, + const BGradient& gradient); // strokes a one pixel wide solid rect, no blending void StrokeRect(const BRect& r, @@ -178,6 +182,9 @@ public: // round rects BRect StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const; + BRect StrokeRoundRect(const BRect& r, float xRadius, + float yRadius, + const BGradient& gradient); BRect FillRoundRect(const BRect& r, float xRadius, float yRadius) const; @@ -190,13 +197,16 @@ public: bool filled) const; BRect DrawEllipse(BRect r, bool filled) const; - BRect FillEllipse(BRect r, + BRect DrawEllipse(BRect r, bool filled, const BGradient& gradient); // arcs BRect StrokeArc(BPoint center, float xRadius, float yRadius, float angle, float span) const; + BRect StrokeArc(BPoint center, float xRadius, + float yRadius, float angle, + float span, const BGradient& gradient); BRect FillArc(BPoint center, float xRadius, float yRadius, float angle, @@ -271,6 +281,8 @@ private: // drawing functions stroke/fill BRect _DrawTriangle(BPoint pt1, BPoint pt2, BPoint pt3, bool fill) const; + BRect _DrawTriangle(BPoint pt1, BPoint pt2, + BPoint pt3, bool fill, const BGradient& gradient); void _IterateShapeData(const int32& opCount, const uint32* opList, const int32& ptCount, @@ -292,6 +304,11 @@ private: BRect _StrokePath(VertexSource& path, cap_mode capMode) const; template + BRect _StrokePath(VertexSource& path, const BGradient& gradient); + template + BRect _StrokePath(VertexSource& path, + cap_mode capMode, const BGradient& gradient); + template BRect _FillPath(VertexSource& path) const; template BRect _RasterizePath(VertexSource& path) const; diff --git a/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.cpp b/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.cpp index dc0b701bae..7d44ba236b 100644 --- a/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.cpp +++ b/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.cpp @@ -411,14 +411,14 @@ RemoteDrawingEngine::DrawArc(BRect rect, const float& angle, const float& span, } void -RemoteDrawingEngine::FillArc(BRect rect, const float& angle, const float& span, - const BGradient& gradient) +RemoteDrawingEngine::DrawArc(BRect rect, const float& angle, const float& span, + bool filled, const BGradient& gradient) { if (!fClippingRegion.Intersects(rect)) return; RemoteMessage message(NULL, fHWInterface->SendBuffer()); - message.Start(RP_FILL_ARC_GRADIENT); + message.Start(filled ? RP_FILL_ARC_GRADIENT : RP_STROKE_ARC_GRADIENT); message.Add(fToken); message.Add(rect); message.Add(angle); @@ -445,14 +445,14 @@ RemoteDrawingEngine::DrawBezier(BPoint* points, bool filled) void -RemoteDrawingEngine::FillBezier(BPoint* points, const BGradient& gradient) +RemoteDrawingEngine::DrawBezier(BPoint* points, bool filled, const BGradient& gradient) { BRect bounds = _BuildBounds(points, 4); if (!fClippingRegion.Intersects(bounds)) return; RemoteMessage message(NULL, fHWInterface->SendBuffer()); - message.Start(RP_FILL_BEZIER_GRADIENT); + message.Start(filled ? RP_FILL_BEZIER_GRADIENT : RP_STROKE_BEZIER_GRADIENT); message.Add(fToken); message.AddList(points, 4); message.AddGradient(gradient); @@ -477,13 +477,13 @@ RemoteDrawingEngine::DrawEllipse(BRect rect, bool filled) void -RemoteDrawingEngine::FillEllipse(BRect rect, const BGradient& gradient) +RemoteDrawingEngine::DrawEllipse(BRect rect, bool filled, const BGradient& gradient) { if (!fClippingRegion.Intersects(rect)) return; RemoteMessage message(NULL, fHWInterface->SendBuffer()); - message.Start(RP_FILL_ELLIPSE_GRADIENT); + message.Start(filled ? RP_FILL_ELLIPSE_GRADIENT : RP_STROKE_ELLIPSE_GRADIENT); message.Add(fToken); message.Add(rect); message.AddGradient(gradient); @@ -513,14 +513,14 @@ RemoteDrawingEngine::DrawPolygon(BPoint* pointList, int32 numPoints, void -RemoteDrawingEngine::FillPolygon(BPoint* pointList, int32 numPoints, - BRect bounds, const BGradient& gradient, bool closed) +RemoteDrawingEngine::DrawPolygon(BPoint* pointList, int32 numPoints, + BRect bounds, bool filled, bool closed, const BGradient& gradient) { if (!fClippingRegion.Intersects(bounds)) return; RemoteMessage message(NULL, fHWInterface->SendBuffer()); - message.Start(RP_FILL_POLYGON_GRADIENT); + message.Start(filled ? RP_FILL_POLYGON_GRADIENT : RP_STROKE_POLYGON_GRADIENT); message.Add(fToken); message.Add(bounds); message.Add(closed); @@ -629,6 +629,23 @@ RemoteDrawingEngine::StrokeRect(BRect rect) } +void +RemoteDrawingEngine::StrokeRect(BRect rect, const BGradient& gradient) +{ + BRect bounds = rect; + bounds.InsetBy(fExtendWidth, fExtendWidth); + + if (!fClippingRegion.Intersects(bounds)) + return; + + RemoteMessage message(NULL, fHWInterface->SendBuffer()); + message.Start(RP_STROKE_RECT_GRADIENT); + message.Add(fToken); + message.Add(rect); + message.AddGradient(gradient); +} + + void RemoteDrawingEngine::FillRect(BRect rect) { @@ -710,14 +727,14 @@ RemoteDrawingEngine::DrawRoundRect(BRect rect, float xRadius, float yRadius, void -RemoteDrawingEngine::FillRoundRect(BRect rect, float xRadius, float yRadius, - const BGradient& gradient) +RemoteDrawingEngine::DrawRoundRect(BRect rect, float xRadius, float yRadius, + bool filled, const BGradient& gradient) { if (!fClippingRegion.Intersects(rect)) return; RemoteMessage message(NULL, fHWInterface->SendBuffer()); - message.Start(RP_FILL_ROUND_RECT_GRADIENT); + message.Start(filled ? RP_FILL_ROUND_RECT_GRADIENT : RP_STROKE_ROUND_RECT_GRADIENT); message.Add(fToken); message.Add(rect); message.Add(xRadius); @@ -752,16 +769,16 @@ RemoteDrawingEngine::DrawShape(const BRect& bounds, int32 opCount, void -RemoteDrawingEngine::FillShape(const BRect& bounds, int32 opCount, +RemoteDrawingEngine::DrawShape(const BRect& bounds, int32 opCount, const uint32* opList, int32 pointCount, const BPoint* pointList, - const BGradient& gradient, const BPoint& viewToScreenOffset, + bool filled, const BGradient& gradient, const BPoint& viewToScreenOffset, float viewScale) { if (!fClippingRegion.Intersects(bounds)) return; RemoteMessage message(NULL, fHWInterface->SendBuffer()); - message.Start(RP_FILL_SHAPE_GRADIENT); + message.Start(filled ? RP_FILL_SHAPE_GRADIENT : RP_STROKE_SHAPE_GRADIENT); message.Add(fToken); message.Add(bounds); message.Add(opCount); @@ -794,14 +811,14 @@ RemoteDrawingEngine::DrawTriangle(BPoint* points, const BRect& bounds, void -RemoteDrawingEngine::FillTriangle(BPoint* points, const BRect& bounds, - const BGradient& gradient) +RemoteDrawingEngine::DrawTriangle(BPoint* points, const BRect& bounds, + bool filled, const BGradient& gradient) { if (!fClippingRegion.Intersects(bounds)) return; RemoteMessage message(NULL, fHWInterface->SendBuffer()); - message.Start(RP_FILL_TRIANGLE_GRADIENT); + message.Start(filled ? RP_FILL_TRIANGLE_GRADIENT : RP_STROKE_TRIANGLE_GRADIENT); message.Add(fToken); message.AddList(points, 3); message.Add(bounds); @@ -825,6 +842,23 @@ RemoteDrawingEngine::StrokeLine(const BPoint &start, const BPoint &end) } +void +RemoteDrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, const BGradient& gradient) +{ + BPoint points[2] = { start, end }; + BRect bounds = _BuildBounds(points, 2); + + if (!fClippingRegion.Intersects(bounds)) + return; + + RemoteMessage message(NULL, fHWInterface->SendBuffer()); + message.Start(RP_STROKE_LINE_GRADIENT); + message.Add(fToken); + message.AddList(points, 2); + message.AddGradient(gradient); +} + + void RemoteDrawingEngine::StrokeLineArray(int32 numLines, const ViewLineArrayInfo *lineData) diff --git a/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.h b/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.h index 51ba142d54..acfa60ddba 100644 --- a/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.h +++ b/src/servers/app/drawing/interface/remote/RemoteDrawingEngine.h @@ -70,23 +70,20 @@ public: // drawing primitives virtual void DrawArc(BRect rect, const float& angle, const float& span, bool filled); - virtual void FillArc(BRect rect, const float& angle, - const float& span, - const BGradient& gradient); + virtual void DrawArc(BRect rect, const float& angle, + const float& span, bool filled, const BGradient& gradient); virtual void DrawBezier(BPoint* points, bool filled); - virtual void FillBezier(BPoint* points, - const BGradient& gradient); + virtual void DrawBezier(BPoint* points, bool filled, const BGradient& gradient); virtual void DrawEllipse(BRect rect, bool filled); - virtual void FillEllipse(BRect rect, - const BGradient& gradient); + virtual void DrawEllipse(BRect rect, bool filled, const BGradient& gradient); virtual void DrawPolygon(BPoint* pointList, int32 numPoints, BRect bounds, bool filled, bool closed); - virtual void FillPolygon(BPoint* pointList, int32 numPoints, - BRect bounds, const BGradient& gradient, - bool closed); + virtual void DrawPolygon(BPoint* pointList, int32 numPoints, + BRect bounds, bool filled, bool closed, + const BGradient& gradient); // these rgb_color versions are used internally by the server virtual void StrokePoint(const BPoint& point, @@ -97,6 +94,7 @@ public: const rgb_color& color); virtual void StrokeRect(BRect rect); + virtual void StrokeRect(BRect rect, const BGradient& gradient); virtual void FillRect(BRect rect); virtual void FillRect(BRect rect, const BGradient& gradient); @@ -106,8 +104,8 @@ public: virtual void DrawRoundRect(BRect rect, float xRadius, float yRadius, bool filled); - virtual void FillRoundRect(BRect rect, float xRadius, - float yRadius, const BGradient& gradient); + virtual void DrawRoundRect(BRect rect, float xRadius, + float yRadius, bool filled, const BGradient& gradient); virtual void DrawShape(const BRect& bounds, int32 opCount, const uint32* opList, @@ -115,24 +113,25 @@ public: bool filled, const BPoint& viewToScreenOffset, float viewScale); - virtual void FillShape(const BRect& bounds, + virtual void DrawShape(const BRect& bounds, int32 opCount, const uint32* opList, int32 pointCount, const BPoint* pointList, - const BGradient& gradient, + bool filled, const BGradient& gradient, const BPoint& viewToScreenOffset, float viewScale); virtual void DrawTriangle(BPoint* points, const BRect& bounds, bool filled); - virtual void FillTriangle(BPoint* points, - const BRect& bounds, - const BGradient& gradient); + virtual void DrawTriangle(BPoint* points, const BRect& bounds, + bool filled, const BGradient& gradient); // these versions are used by the Decorator virtual void StrokeLine(const BPoint& start, const BPoint& end, const rgb_color& color); virtual void StrokeLine(const BPoint& start, const BPoint& end); + virtual void StrokeLine(const BPoint& start, + const BPoint& end, const BGradient& gradient); virtual void StrokeLineArray(int32 numlines, const ViewLineArrayInfo* data); diff --git a/src/servers/app/drawing/interface/remote/RemoteMessage.h b/src/servers/app/drawing/interface/remote/RemoteMessage.h index ffe35bf207..7cb3b9ba8a 100644 --- a/src/servers/app/drawing/interface/remote/RemoteMessage.h +++ b/src/servers/app/drawing/interface/remote/RemoteMessage.h @@ -125,7 +125,17 @@ enum { RP_KEY_UP, RP_UNMAPPED_KEY_DOWN, RP_UNMAPPED_KEY_UP, - RP_MODIFIERS_CHANGED + RP_MODIFIERS_CHANGED, + + RP_STROKE_ARC_GRADIENT = 260, + RP_STROKE_BEZIER_GRADIENT, + RP_STROKE_ELLIPSE_GRADIENT, + RP_STROKE_POLYGON_GRADIENT, + RP_STROKE_RECT_GRADIENT, + RP_STROKE_ROUND_RECT_GRADIENT, + RP_STROKE_SHAPE_GRADIENT, + RP_STROKE_TRIANGLE_GRADIENT, + RP_STROKE_LINE_GRADIENT, };