diff --git a/headers/private/interface/PictureDataWriter.h b/headers/private/interface/PictureDataWriter.h index af5f7e3c76..5d75abe7c5 100644 --- a/headers/private/interface/PictureDataWriter.h +++ b/headers/private/interface/PictureDataWriter.h @@ -20,6 +20,7 @@ class Layer; +class BGradient; class BPositionIO; class BRegion; @@ -91,6 +92,24 @@ public: status_t WriteDrawShape(const int32& opCount, const void* opList, const int32& ptCount, const void* ptList, const bool& fill); + status_t WriteDrawRectGradient(const BRect& rect, const BGradient& gradient, + const bool& fill); + status_t WriteDrawRoundRectGradient(const BRect& rect, + const BPoint& radius, const BGradient& gradient, const bool& fill); + status_t WriteDrawBezierGradient(const BPoint points[4], const BGradient& gradient, + const bool& fill); + status_t WriteDrawArcGradient(const BPoint& center, + const BPoint& radius, + const float& startTheta, + const float& arcTheta, const BGradient& gradient, const bool& fill); + status_t WriteDrawEllipseGradient(const BRect& rect, const BGradient& gradient, + const bool& fill); + status_t WriteDrawPolygonGradient(const int32& numPoints, + BPoint* points, const bool& isClosed, const BGradient& gradient, + const bool& fill); + status_t WriteDrawShapeGradient(const int32& opCount, + const void* opList, const int32& ptCount, + const void* ptList, const BGradient& gradient, const bool& fill); 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 72e4b50a78..308829e873 100644 --- a/headers/private/interface/PicturePlayer.h +++ b/headers/private/interface/PicturePlayer.h @@ -21,6 +21,7 @@ class BAffineTransform; +class BGradient; class BList; class BPicture; class BShape; @@ -94,6 +95,13 @@ struct picture_player_callbacks { int32 ptCount, const BPoint ptList[], bool inverse); void (*draw_string_locations)(void* userData, const char* string, size_t length, const BPoint locations[], size_t locationCount); + void (*draw_rect_gradient)(void* userData, const BRect& rect, BGradient& gradient, bool fill); + void (*draw_round_rect_gradient)(void* userData, const BRect& rect, const BPoint& radii, BGradient& gradient, bool fill); + void (*draw_bezier_gradient)(void* userData, size_t numControlPoints, const BPoint controlPoints[], BGradient& gradient, bool fill); + void (*draw_arc_gradient)(void* userData, const BPoint& center, const BPoint& radii, float startTheta, float arcTheta, BGradient& gradient, bool fill); + void (*draw_ellipse_gradient)(void* userData, const BRect& rect, BGradient& gradient, bool fill); + 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); }; diff --git a/headers/private/interface/PictureProtocol.h b/headers/private/interface/PictureProtocol.h index 8775ef1958..b83bb22701 100644 --- a/headers/private/interface/PictureProtocol.h +++ b/headers/private/interface/PictureProtocol.h @@ -23,6 +23,20 @@ enum { B_PIC_STROKE_ELLIPSE = 0x0115, B_PIC_FILL_ELLIPSE = 0x0116, B_PIC_DRAW_STRING_LOCATIONS = 0x0117, + B_PIC_STROKE_RECT_GRADIENT = 0x0118, + B_PIC_FILL_RECT_GRADIENT = 0x0119, + B_PIC_STROKE_ROUND_RECT_GRADIENT = 0x011A, + B_PIC_FILL_ROUND_RECT_GRADIENT = 0x011B, + B_PIC_STROKE_BEZIER_GRADIENT = 0x011C, + B_PIC_FILL_BEZIER_GRADIENT = 0x011D, + B_PIC_STROKE_POLYGON_GRADIENT = 0x011E, + B_PIC_FILL_POLYGON_GRADIENT = 0x011F, + B_PIC_STROKE_SHAPE_GRADIENT = 0x0120, + B_PIC_FILL_SHAPE_GRADIENT = 0x0121, + B_PIC_STROKE_ARC_GRADIENT = 0x0122, + B_PIC_FILL_ARC_GRADIENT = 0x0123, + B_PIC_STROKE_ELLIPSE_GRADIENT = 0x0124, + B_PIC_FILL_ELLIPSE_GRADIENT = 0x0125, B_PIC_ENTER_STATE_CHANGE = 0x0200, B_PIC_SET_CLIPPING_RECTS = 0x0201, @@ -62,7 +76,7 @@ enum { }; -const static uint32 kOpsTableSize = 51; +const static uint32 kOpsTableSize = 70; #endif diff --git a/src/kits/interface/PictureDataWriter.cpp b/src/kits/interface/PictureDataWriter.cpp index 0f66f5942f..7de6b56603 100644 --- a/src/kits/interface/PictureDataWriter.cpp +++ b/src/kits/interface/PictureDataWriter.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -519,6 +520,137 @@ PictureDataWriter::WriteDrawShape(const int32& opCount, const void* opList, } +status_t +PictureDataWriter::WriteDrawRectGradient(const BRect& rect, const BGradient& gradient, const bool& fill) +{ + try { + BeginOp(fill ? B_PIC_FILL_RECT_GRADIENT : B_PIC_STROKE_RECT_GRADIENT); + Write(rect); + gradient.Flatten(fData); + EndOp(); + } catch (status_t& status) { + return status; + } + + return B_OK; +} + + +status_t +PictureDataWriter::WriteDrawRoundRectGradient(const BRect& rect, const BPoint& radius, const BGradient& gradient, + const bool& fill) +{ + try { + BeginOp(fill ? B_PIC_FILL_ROUND_RECT_GRADIENT : B_PIC_STROKE_ROUND_RECT_GRADIENT); + Write(rect); + Write(radius); + gradient.Flatten(fData); + EndOp(); + } catch (status_t& status) { + return status; + } + + return B_OK; +} + + +status_t +PictureDataWriter::WriteDrawBezierGradient(const BPoint points[4], const BGradient& gradient, const bool& fill) +{ + try { + BeginOp(fill ? B_PIC_FILL_BEZIER_GRADIENT : B_PIC_STROKE_BEZIER_GRADIENT); + for (int32 i = 0; i < 4; i++) + Write(points[i]); + + gradient.Flatten(fData); + EndOp(); + } catch (status_t& status) { + return status; + } + + return B_OK; +} + + +status_t +PictureDataWriter::WriteDrawArcGradient(const BPoint& center, const BPoint& radius, + const float& startTheta, const float& arcTheta, const BGradient& gradient, const bool& fill) +{ + try { + BeginOp(fill ? B_PIC_FILL_ARC_GRADIENT : B_PIC_STROKE_ARC_GRADIENT); + Write(center); + Write(radius); + Write(startTheta); + Write(arcTheta); + gradient.Flatten(fData); + EndOp(); + } catch (status_t& status) { + return status; + } + + return B_OK; +} + + +status_t +PictureDataWriter::WriteDrawEllipseGradient(const BRect& rect, const BGradient& gradient, const bool& fill) +{ + try { + BeginOp(fill ? B_PIC_FILL_ELLIPSE_GRADIENT : B_PIC_STROKE_ELLIPSE_GRADIENT); + Write(rect); + gradient.Flatten(fData); + EndOp(); + } catch (status_t& status) { + return status; + } + + return B_OK; +} + + +status_t +PictureDataWriter::WriteDrawPolygonGradient(const int32& numPoints, BPoint* points, + const bool& isClosed, const BGradient& gradient, const bool& fill) +{ + try { + BeginOp(fill ? B_PIC_FILL_POLYGON_GRADIENT : B_PIC_STROKE_POLYGON_GRADIENT); + Write(numPoints); + for (int32 i = 0; i < numPoints; i++) + Write(points[i]); + + if (!fill) + Write((uint8)isClosed); + + gradient.Flatten(fData); + EndOp(); + } catch (status_t& status) { + return status; + } + + return B_OK; +} + + +status_t +PictureDataWriter::WriteDrawShapeGradient(const int32& opCount, const void* opList, + const int32& ptCount, const void* ptList, const BGradient& gradient, const bool& fill) +{ + try { + BeginOp(fill ? B_PIC_FILL_SHAPE_GRADIENT : B_PIC_STROKE_SHAPE_GRADIENT); + Write(opCount); + Write(ptCount); + WriteData(opList, opCount * sizeof(uint32)); + WriteData(ptList, ptCount * sizeof(BPoint)); + 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 0e893f89a7..ec2bdd94dd 100644 --- a/src/kits/interface/PicturePlayer.cpp +++ b/src/kits/interface/PicturePlayer.cpp @@ -18,9 +18,12 @@ #include #include +#include +#include #include #include +#include #include @@ -520,6 +523,88 @@ draw_string_locations(void* _context, const char* _string, size_t length, } +static void +draw_rect_gradient(void* _context, const BRect& rect, BGradient& gradient, bool fill) +{ + adapter_context* context = reinterpret_cast(_context); + ((void (*)(void*, BRect, BGradient&))context->function_table[fill ? 56 : 57])( + context->user_data, rect, gradient); +} + + +static void +draw_round_rect_gradient(void* _context, const BRect& rect, const BPoint& radii, BGradient& gradient, + bool fill) +{ + adapter_context* context = reinterpret_cast(_context); + ((void (*)(void*, BRect, BPoint, BGradient&))context->function_table[fill ? 58 : 59])( + context->user_data, rect, radii, gradient); +} + + +static void +draw_bezier_gradient(void* _context, size_t numPoints, const BPoint _points[], BGradient& gradient, bool fill) +{ + adapter_context* context = reinterpret_cast(_context); + if (numPoints != 4) + return; + + BPoint points[4] = { _points[0], _points[1], _points[2], _points[3] }; + ((void (*)(void*, BPoint*, BGradient&))context->function_table[fill ? 60 : 61])( + context->user_data, points, gradient); +} + + +static void +draw_arc_gradient(void* _context, const BPoint& center, const BPoint& radii, + float startTheta, float arcTheta, BGradient& gradient, bool fill) +{ + adapter_context* context = reinterpret_cast(_context); + ((void (*)(void*, BPoint, BPoint, float, float, BGradient&)) + context->function_table[fill ? 62 : 63])(context->user_data, center, + radii, startTheta, arcTheta, gradient); +} + + +static void +draw_ellipse_gradient(void* _context, const BRect& rect, BGradient& gradient, bool fill) +{ + adapter_context* context = reinterpret_cast(_context); + BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f); + BPoint center = rect.LeftTop() + radii; + ((void (*)(void*, BPoint, BPoint, BGradient&)) + context->function_table[fill ? 64 : 65])(context->user_data, center, + radii, gradient); +} + + +static void +draw_polygon_gradient(void* _context, size_t numPoints, const BPoint _points[], + bool isClosed, BGradient& gradient, bool fill) +{ + adapter_context* context = reinterpret_cast(_context); + + BStackOrHeapArray points(numPoints); + if (!points.IsValid()) + return; + + memcpy((void*)points, _points, numPoints * sizeof(BPoint)); + + ((void (*)(void*, int32, BPoint*, bool, BGradient&)) + context->function_table[fill ? 66 : 67])(context->user_data, numPoints, + points, isClosed, gradient); +} + + +static void +draw_shape_gradient(void* _context, const BShape& shape, BGradient& gradient, bool fill) +{ + adapter_context* context = reinterpret_cast(_context); + ((void (*)(void*, BShape, BGradient&))context->function_table[fill ? 68 : 69])( + context->user_data, shape, gradient); +} + + #if DEBUG > 1 static const char * @@ -655,7 +740,14 @@ PicturePlayer::Play(void** callBackTable, int32 tableEntries, void* userData) blend_layer, clip_to_rect, clip_to_shape, - draw_string_locations + draw_string_locations, + draw_rect_gradient, + draw_round_rect_gradient, + draw_bezier_gradient, + draw_arc_gradient, + draw_ellipse_gradient, + draw_polygon_gradient, + draw_shape_gradient }; // We don't check if the functions in the table are NULL, but we @@ -719,6 +811,20 @@ public: return true; } + bool GetGradient(BGradient*& gradient) + { + BMemoryIO stream(fBuffer, fRemaining); + printf("fRemaining: %ld\n", fRemaining); + if (BGradient::Unflatten(gradient, &stream) != B_OK) { + printf("BGradient::Unflatten(_gradient, &stream) != B_OK\n"); + return false; + } + + fRemaining -= stream.Position(); + fBuffer += stream.Position(); + return true; + } + template bool GetRemaining(const T*& buffer, size_t& size) @@ -936,6 +1042,141 @@ PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData, break; } + case B_PIC_STROKE_RECT_GRADIENT: + case B_PIC_FILL_RECT_GRADIENT: + { + const BRect* rect; + BGradient* gradient; + if (callbacks.draw_rect_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient)) + break; + ObjectDeleter gradientDeleter(gradient); + + callbacks.draw_rect_gradient(userData, *rect, *gradient, + header->op == B_PIC_FILL_RECT_GRADIENT); + break; + } + + case B_PIC_STROKE_ROUND_RECT_GRADIENT: + case B_PIC_FILL_ROUND_RECT_GRADIENT: + { + const BRect* rect; + const BPoint* radii; + BGradient* gradient; + if (callbacks.draw_round_rect_gradient == NULL || !reader.Get(rect) + || !reader.Get(radii) || !reader.GetGradient(gradient)) { + break; + } + ObjectDeleter gradientDeleter(gradient); + + callbacks.draw_round_rect_gradient(userData, *rect, *radii, *gradient, + header->op == B_PIC_FILL_ROUND_RECT_GRADIENT); + break; + } + + case B_PIC_STROKE_BEZIER_GRADIENT: + case B_PIC_FILL_BEZIER_GRADIENT: + { + const size_t kNumControlPoints = 4; + const BPoint* controlPoints; + BGradient* gradient; + if (callbacks.draw_bezier_gradient == NULL + || !reader.Get(controlPoints, kNumControlPoints) || !reader.GetGradient(gradient)) { + break; + } + ObjectDeleter gradientDeleter(gradient); + + callbacks.draw_bezier_gradient(userData, kNumControlPoints, + controlPoints, *gradient, header->op == B_PIC_FILL_BEZIER_GRADIENT); + break; + } + + case B_PIC_STROKE_POLYGON_GRADIENT: + case B_PIC_FILL_POLYGON_GRADIENT: + { + const uint32* numPoints; + const BPoint* points; + BGradient* gradient; + if (callbacks.draw_polygon_gradient == NULL || !reader.Get(numPoints) + || !reader.Get(points, *numPoints)) { + break; + } + + bool isClosed = true; + const bool* closedPointer; + if (header->op != B_PIC_FILL_POLYGON_GRADIENT) { + if (!reader.Get(closedPointer)) + break; + + isClosed = *closedPointer; + } + + if (!reader.GetGradient(gradient)) + break; + ObjectDeleter gradientDeleter(gradient); + + callbacks.draw_polygon_gradient(userData, *numPoints, points, isClosed, *gradient, + header->op == B_PIC_FILL_POLYGON_GRADIENT); + break; + } + + case B_PIC_STROKE_SHAPE_GRADIENT: + case B_PIC_FILL_SHAPE_GRADIENT: + { + const uint32* opCount; + const uint32* pointCount; + const uint32* opList; + const BPoint* pointList; + BGradient* gradient; + if (callbacks.draw_shape_gradient == NULL || !reader.Get(opCount) + || !reader.Get(pointCount) || !reader.Get(opList, *opCount) + || !reader.Get(pointList, *pointCount) || !reader.GetGradient(gradient)) { + break; + } + ObjectDeleter gradientDeleter(gradient); + + // TODO: remove BShape data copying + BShape shape; + shape.SetData(*opCount, *pointCount, opList, pointList); + + callbacks.draw_shape_gradient(userData, shape, *gradient, + header->op == B_PIC_FILL_SHAPE_GRADIENT); + break; + } + + case B_PIC_STROKE_ARC_GRADIENT: + case B_PIC_FILL_ARC_GRADIENT: + { + const BPoint* center; + const BPoint* radii; + const float* startTheta; + const float* arcTheta; + BGradient* gradient; + if (callbacks.draw_arc_gradient == NULL || !reader.Get(center) + || !reader.Get(radii) || !reader.Get(startTheta) + || !reader.Get(arcTheta) || !reader.GetGradient(gradient)) { + break; + } + ObjectDeleter gradientDeleter(gradient); + + callbacks.draw_arc_gradient(userData, *center, *radii, *startTheta, + *arcTheta, *gradient, header->op == B_PIC_FILL_ARC_GRADIENT); + break; + } + + case B_PIC_STROKE_ELLIPSE_GRADIENT: + case B_PIC_FILL_ELLIPSE_GRADIENT: + { + const BRect* rect; + BGradient* gradient; + if (callbacks.draw_ellipse_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient)) + break; + ObjectDeleter gradientDeleter(gradient); + + callbacks.draw_ellipse_gradient(userData, *rect, *gradient, + header->op == B_PIC_FILL_ELLIPSE_GRADIENT); + break; + } + case B_PIC_DRAW_STRING: { const float* escapementSpace; diff --git a/src/servers/app/ServerPicture.cpp b/src/servers/app/ServerPicture.cpp index 4daa9cef58..4159049d66 100644 --- a/src/servers/app/ServerPicture.cpp +++ b/src/servers/app/ServerPicture.cpp @@ -49,7 +49,7 @@ using std::stack; class ShapePainter : public BShapeIterator { public: - ShapePainter(Canvas* canvas); + ShapePainter(Canvas* canvas, BGradient* gradient); virtual ~ShapePainter(); status_t Iterate(const BShape* shape); @@ -65,14 +65,16 @@ public: private: Canvas* fCanvas; + BGradient* fGradient; stack fOpStack; stack fPtStack; }; -ShapePainter::ShapePainter(Canvas* canvas) +ShapePainter::ShapePainter(Canvas* canvas, BGradient* gradient) : - fCanvas(canvas) + fCanvas(canvas), + fGradient(gradient) { } @@ -217,8 +219,14 @@ ShapePainter::Draw(BRect frame, bool filled) transform.Apply(&screenOffset); transform.Apply(&frame); - fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList, - ptCount, ptList, filled, screenOffset, fCanvas->Scale()); + /* stroked gradients are not yet supported */ + if (fGradient != NULL && filled) { + fCanvas->GetDrawingEngine()->FillShape(frame, opCount, opList, + ptCount, ptList, *fGradient, screenOffset, fCanvas->Scale()); + } else { + fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList, + ptCount, ptList, filled, screenOffset, fCanvas->Scale()); + } delete[] opList; delete[] ptList; @@ -381,7 +389,125 @@ static void draw_shape(void* _canvas, const BShape& shape, bool fill) { Canvas* const canvas = reinterpret_cast(_canvas); - ShapePainter drawShape(canvas); + ShapePainter drawShape(canvas, NULL); + + drawShape.Iterate(&shape); + drawShape.Draw(shape.Bounds(), fill); +} + + +static void +draw_rect_gradient(void* _canvas, const BRect& _rect, BGradient& gradient, bool fill) +{ + Canvas* const canvas = reinterpret_cast(_canvas); + BRect rect = _rect; + + const SimpleTransform transform = + canvas->PenToScreenTransform(); + transform.Apply(&rect); + transform.Apply(&gradient); + + canvas->GetDrawingEngine()->FillRect(rect, gradient); +} + + +static void +draw_round_rect_gradient(void* _canvas, const BRect& _rect, const BPoint& radii, BGradient& gradient, + bool fill) +{ + Canvas* const canvas = reinterpret_cast(_canvas); + BRect rect = _rect; + + const SimpleTransform transform = + canvas->PenToScreenTransform(); + transform.Apply(&rect); + transform.Apply(&gradient); + float scale = canvas->CurrentState()->CombinedScale(); + canvas->GetDrawingEngine()->FillRoundRect(rect, radii.x * scale, + radii.y * scale, gradient); +} + + +static void +draw_bezier_gradient(void* _canvas, size_t numPoints, const BPoint viewPoints[], BGradient& gradient, + bool fill) +{ + Canvas* const canvas = reinterpret_cast(_canvas); + + const size_t kSupportedPoints = 4; + if (numPoints != kSupportedPoints) + return; + + BPoint points[kSupportedPoints]; + const SimpleTransform transform = + canvas->PenToScreenTransform(); + transform.Apply(points, viewPoints, kSupportedPoints); + transform.Apply(&gradient); + canvas->GetDrawingEngine()->FillBezier(points, gradient); +} + + +static void +draw_arc_gradient(void* _canvas, const BPoint& center, const BPoint& radii, + float startTheta, float arcTheta, BGradient& gradient, bool fill) +{ + Canvas* const canvas = reinterpret_cast(_canvas); + + BRect rect(center.x - radii.x, center.y - radii.y, + center.x + radii.x - 1, center.y + radii.y - 1); + const SimpleTransform transform = + canvas->PenToScreenTransform(); + transform.Apply(&rect); + transform.Apply(&gradient); + canvas->GetDrawingEngine()->FillArc(rect, startTheta, arcTheta, gradient); +} + + +static void +draw_ellipse_gradient(void* _canvas, const BRect& _rect, BGradient& gradient, bool fill) +{ + Canvas* const canvas = reinterpret_cast(_canvas); + BRect rect = _rect; + + const SimpleTransform transform = + canvas->PenToScreenTransform(); + transform.Apply(&rect); + transform.Apply(&gradient); + canvas->GetDrawingEngine()->FillEllipse(rect, gradient); +} + + +static void +draw_polygon_gradient(void* _canvas, size_t numPoints, const BPoint viewPoints[], + bool isClosed, BGradient& gradient, bool fill) +{ + Canvas* const canvas = reinterpret_cast(_canvas); + + if (numPoints == 0) + return; + + BStackOrHeapArray points(numPoints); + if (!points.IsValid()) + return; + + const SimpleTransform transform = + canvas->PenToScreenTransform(); + transform.Apply(points, viewPoints, numPoints); + transform.Apply(&gradient); + + BRect polyFrame; + get_polygon_frame(points, numPoints, &polyFrame); + + canvas->GetDrawingEngine()->FillPolygon(points, numPoints, polyFrame, + gradient, isClosed && numPoints > 2); +} + + +static void +draw_shape_gradient(void* _canvas, const BShape& shape, BGradient& gradient, bool fill) +{ + Canvas* const canvas = reinterpret_cast(_canvas); + ShapePainter drawShape(canvas, &gradient); drawShape.Iterate(&shape); drawShape.Draw(shape.Bounds(), fill); @@ -929,7 +1055,14 @@ static const BPrivate::picture_player_callbacks kPicturePlayerCallbacks = { blend_layer, clip_to_rect, clip_to_shape, - draw_string_locations + draw_string_locations, + draw_rect_gradient, + draw_round_rect_gradient, + draw_bezier_gradient, + draw_arc_gradient, + draw_ellipse_gradient, + draw_polygon_gradient, + draw_shape_gradient }; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index bd15e3326c..bc9dbf8526 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -3507,6 +3507,193 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) break; } + //case AS_STROKE_RECT_GRADIENT: + case AS_FILL_RECT_GRADIENT: + { + BRect rect; + link.Read(&rect); + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + picture->WriteDrawRectGradient(rect, *gradient, code == AS_FILL_RECT_GRADIENT); + break; + } + + //case AS_STROKE_ARC_GRADIENT: + case AS_FILL_ARC_GRADIENT: + { + BRect rect; + link.Read(&rect); + float startTheta, arcTheta; + link.Read(&startTheta); + link.Read(&arcTheta); + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + BPoint radii((rect.Width() + 1) / 2, (rect.Height() + 1) / 2); + BPoint center = rect.LeftTop() + radii; + + picture->WriteDrawArcGradient(center, radii, startTheta, arcTheta, *gradient, + code == AS_FILL_ARC_GRADIENT); + break; + } + + //case AS_STROKE_BEZIER_GRADIENT: + case AS_FILL_BEZIER_GRADIENT: + { + BPoint points[4]; + for (int32 i = 0; i < 4; i++) { + link.Read(&(points[i])); + } + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + picture->WriteDrawBezierGradient(points, *gradient, code == AS_FILL_BEZIER_GRADIENT); + break; + } + + //case AS_STROKE_ELLIPSE_GRADIENT: + case AS_FILL_ELLIPSE_GRADIENT: + { + BRect rect; + link.Read(&rect); + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + picture->WriteDrawEllipseGradient(rect, *gradient, code == AS_FILL_ELLIPSE_GRADIENT); + break; + } + + //case AS_STROKE_ROUNDRECT_GRADIENT: + case AS_FILL_ROUNDRECT_GRADIENT: + { + BRect rect; + link.Read(&rect); + + BPoint radii; + link.Read(&radii.x); + link.Read(&radii.y); + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + picture->WriteDrawRoundRectGradient(rect, radii, *gradient, code == AS_FILL_ROUNDRECT_GRADIENT); + break; + } + + //case AS_STROKE_TRIANGLE_GRADIENT: + case AS_FILL_TRIANGLE_GRADIENT: + { + // There is no B_PIC_FILL/STROKE_TRIANGLE op, + // we implement it using B_PIC_FILL/STROKE_POLYGON + BPoint points[3]; + + for (int32 i = 0; i < 3; i++) { + link.Read(&(points[i])); + } + + BRect rect; + link.Read(&rect); + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + picture->WriteDrawPolygonGradient(3, points, + true, *gradient, code == AS_FILL_TRIANGLE_GRADIENT); + break; + } + + //case AS_STROKE_POLYGON_GRADIENT: + case AS_FILL_POLYGON_GRADIENT: + { + BRect polyFrame; + bool isClosed = true; + int32 pointCount; + const bool fill = (code == AS_FILL_POLYGON_GRADIENT); + + link.Read(&polyFrame); + if (code == AS_STROKE_POLYGON) + link.Read(&isClosed); + link.Read(&pointCount); + + ArrayDeleter pointList(new(nothrow) BPoint[pointCount]); + if (link.Read(pointList.Get(), pointCount * sizeof(BPoint)) != B_OK) + break; + + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + picture->WriteDrawPolygonGradient(pointCount, pointList.Get(), + isClosed && pointCount > 2, *gradient, fill); + break; + } + + //case AS_STROKE_SHAPE_GRADIENT: + case AS_FILL_SHAPE_GRADIENT: + { + BRect shapeFrame; + int32 opCount; + int32 ptCount; + + link.Read(&shapeFrame); + link.Read(&opCount); + link.Read(&ptCount); + + ArrayDeleter opList(new(std::nothrow) uint32[opCount]); + ArrayDeleter ptList(new(std::nothrow) BPoint[ptCount]); + if (opList.Get() == NULL || ptList.Get() == NULL + || link.Read(opList.Get(), opCount * sizeof(uint32)) != B_OK + || link.Read(ptList.Get(), ptCount * sizeof(BPoint)) != B_OK) + break; + + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + // This might seem a bit weird, but under BeOS, the shapes + // are always offset by the current pen location + BPoint penLocation + = fCurrentView->CurrentState()->PenLocation(); + for (int32 i = 0; i < ptCount; i++) { + ptList.Get()[i] += penLocation; + } + const bool fill = (code == AS_FILL_SHAPE_GRADIENT); + picture->WriteDrawShapeGradient(opCount, opList.Get(), ptCount, ptList.Get(), *gradient, fill); + + break; + } + + case AS_FILL_REGION_GRADIENT: + { + // There is no B_PIC_FILL_REGION op, we have to + // implement it using B_PIC_FILL_RECT + BRegion region; + if (link.ReadRegion(®ion) < B_OK) + break; + + BGradient* gradient; + if (link.ReadGradient(&gradient) != B_OK) + break; + ObjectDeleter gradientDeleter(gradient); + + for (int32 i = 0; i < region.CountRects(); i++) + picture->WriteDrawRectGradient(region.RectAt(i), *gradient, true); + break; + } + case AS_STROKE_LINE: { ViewStrokeLineInfo info;