BPicture: add gradient support

Fixes #9680.

Change-Id: I0013326559cc40ff26cf7b44794c0b32aea832ba
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2829
Reviewed-by: Stephan Aßmus <[email protected]>
This commit is contained in:
X512
2020-07-12 19:44:43 +00:00
committed by waddlesplash
parent 10b294d85b
commit 90ab1a44ad
7 changed files with 743 additions and 9 deletions
@@ -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,
@@ -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);
};
+15 -1
View File
@@ -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
+132
View File
@@ -14,6 +14,7 @@
#include <string.h>
#include <DataIO.h>
#include <Gradient.h>
#include <Point.h>
#include <Rect.h>
#include <Region.h>
@@ -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<BRect>(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<BRect>(rect);
Write<BPoint>(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<BPoint>(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<BPoint>(center);
Write<BPoint>(radius);
Write<float>(startTheta);
Write<float>(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<BRect>(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<int32>(numPoints);
for (int32 i = 0; i < numPoints; i++)
Write<BPoint>(points[i]);
if (!fill)
Write<uint8>((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<int32>(opCount);
Write<int32>(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,
+242 -1
View File
@@ -18,9 +18,12 @@
#include <string.h>
#include <AffineTransform.h>
#include <DataIO.h>
#include <Gradient.h>
#include <PictureProtocol.h>
#include <Shape.h>
#include <AutoDeleter.h>
#include <StackOrHeapArray.h>
@@ -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<adapter_context*>(_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<adapter_context*>(_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<adapter_context*>(_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<adapter_context*>(_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<adapter_context*>(_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<adapter_context*>(_context);
BStackOrHeapArray<BPoint, 200> 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<adapter_context*>(_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<typename T>
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<BGradient> 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<BGradient> 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<BGradient> 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<BGradient> 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<BGradient> 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<BGradient> 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<BGradient> 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;
+140 -7
View File
@@ -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<uint32> fOpStack;
stack<BPoint> 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*>(_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*>(_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*>(_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*>(_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*>(_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*>(_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*>(_canvas);
if (numPoints == 0)
return;
BStackOrHeapArray<BPoint, 200> 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*>(_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
};
+187
View File
@@ -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<BRect>(&rect);
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
ObjectDeleter<BGradient> 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<BRect>(&rect);
float startTheta, arcTheta;
link.Read<float>(&startTheta);
link.Read<float>(&arcTheta);
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
ObjectDeleter<BGradient> 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<BPoint>(&(points[i]));
}
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
ObjectDeleter<BGradient> 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<BRect>(&rect);
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
ObjectDeleter<BGradient> 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<BRect>(&rect);
BPoint radii;
link.Read<float>(&radii.x);
link.Read<float>(&radii.y);
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
ObjectDeleter<BGradient> 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<BPoint>(&(points[i]));
}
BRect rect;
link.Read<BRect>(&rect);
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
ObjectDeleter<BGradient> 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<BRect>(&polyFrame);
if (code == AS_STROKE_POLYGON)
link.Read<bool>(&isClosed);
link.Read<int32>(&pointCount);
ArrayDeleter<BPoint> 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<BGradient> 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<BRect>(&shapeFrame);
link.Read<int32>(&opCount);
link.Read<int32>(&ptCount);
ArrayDeleter<uint32> opList(new(std::nothrow) uint32[opCount]);
ArrayDeleter<BPoint> 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<BGradient> 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(&region) < B_OK)
break;
BGradient* gradient;
if (link.ReadGradient(&gradient) != B_OK)
break;
ObjectDeleter<BGradient> gradientDeleter(gradient);
for (int32 i = 0; i < region.CountRects(); i++)
picture->WriteDrawRectGradient(region.RectAt(i), *gradient, true);
break;
}
case AS_STROKE_LINE:
{
ViewStrokeLineInfo info;