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:
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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(®ion) < 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;
|
||||
|
||||
Reference in New Issue
Block a user