Implemented the following BPicture ops: fill region, stroke/fill arc,
stroke/fill polygon, stroke/fill bezier. some work towards drawing of nested pictures. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21918 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -36,6 +36,10 @@ public:
|
||||
status_t WriteDrawEllipse(const BRect &rect, const bool &fill);
|
||||
status_t WriteDrawArc(const BPoint ¢er, const BPoint &radius,
|
||||
const float &startTheta, const float &arcTheta, const bool &fill);
|
||||
status_t WriteDrawPolygon(const int32 &numPoints, BPoint *points,
|
||||
const bool &isClosed, const bool &fill);
|
||||
status_t WriteDrawBezier(const BPoint points[4], const bool &fill);
|
||||
|
||||
status_t WriteStrokeLine(const BPoint &start, const BPoint &end);
|
||||
|
||||
status_t WriteSetHighColor(const rgb_color &color);
|
||||
@@ -48,7 +52,9 @@ public:
|
||||
status_t WriteDrawBitmap(const BRect &srcRect, const BRect &dstRect, const int32 &width, const int32 &height,
|
||||
const int32 &bytesPerRow, const int32 &colorSpace, const int32 &flags,
|
||||
const void *data, const int32 &length);
|
||||
|
||||
|
||||
status_t WriteDrawPicture(const BPoint &where, const int32 &token);
|
||||
|
||||
status_t WriteSetFontFamily(const font_family &family);
|
||||
status_t WriteSetFontStyle(const font_style &style);
|
||||
status_t WriteSetFontSpacing(const int32 &spacing);
|
||||
|
||||
@@ -221,6 +221,40 @@ PictureDataWriter::WriteDrawArc(const BPoint ¢er, const BPoint &radius,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PictureDataWriter::WriteDrawPolygon(const int32 &numPoints, BPoint *points,
|
||||
const bool &isClosed, const bool &fill)
|
||||
{
|
||||
try {
|
||||
BeginOp(fill ? B_PIC_FILL_POLYGON : B_PIC_STROKE_POLYGON);
|
||||
Write<int32>(numPoints);
|
||||
for (int32 i = 0; i < numPoints; i++)
|
||||
Write<BPoint>(points[i]);
|
||||
if (!fill)
|
||||
Write<uint8>((uint8)isClosed);
|
||||
EndOp();
|
||||
} catch (status_t &status) {
|
||||
return status;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PictureDataWriter::WriteDrawBezier(const BPoint points[4], const bool &fill)
|
||||
{
|
||||
try {
|
||||
BeginOp(fill ? B_PIC_FILL_BEZIER : B_PIC_STROKE_BEZIER);
|
||||
for (int32 i = 0; i < 4; i++)
|
||||
Write<BPoint>(points[i]);
|
||||
EndOp();
|
||||
} catch (status_t &status) {
|
||||
return status;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PictureDataWriter::WriteStrokeLine(const BPoint &start, const BPoint &end)
|
||||
{
|
||||
@@ -304,6 +338,23 @@ PictureDataWriter::WriteDrawBitmap(const BRect &srcRect, const BRect &dstRect, c
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PictureDataWriter::WriteDrawPicture(const BPoint &where, const int32 &token)
|
||||
{
|
||||
// TODO: I'm not sure about this function. I think we need to attach the picture
|
||||
// data too. The token won't be sufficient in many cases.
|
||||
try {
|
||||
BeginOp(B_PIC_DRAW_PICTURE);
|
||||
Write<BPoint>(where);
|
||||
Write<int32>(token);
|
||||
EndOp();
|
||||
} catch (status_t &status) {
|
||||
return status;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PictureDataWriter::WriteSetFontFamily(const font_family &family)
|
||||
{
|
||||
@@ -493,6 +544,6 @@ PictureDataWriter::WriteData(const void *data, size_t size)
|
||||
ssize_t result = fData->Write(data, size);
|
||||
if (result < 0)
|
||||
THROW_ERROR(result);
|
||||
if (result != size)
|
||||
if ((size_t)result != size)
|
||||
THROW_ERROR(B_IO_ERROR);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ typedef void (*fnc_ss)(void *, int16, int16);
|
||||
typedef void (*fnc_PBRecti)(void*, const BRect*, int32);
|
||||
typedef void (*fnc_DrawPixels)(void *, BRect, BRect, int32, int32, int32,
|
||||
int32, int32, const void *);
|
||||
typedef void (*fnc_DrawPicture)(void *, BPoint, int32);
|
||||
typedef void (*fnc_BShape)(void*, BShape*);
|
||||
|
||||
|
||||
@@ -230,6 +231,9 @@ PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData)
|
||||
|
||||
case B_PIC_DRAW_PICTURE:
|
||||
{
|
||||
((fnc_DrawPicture)callBackTable[19])(userData,
|
||||
*reinterpret_cast<const BPoint *>(data),
|
||||
*reinterpret_cast<const int32 *>(data + sizeof(BPoint)));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -3091,7 +3091,8 @@ BView::SetDiskMode(char* filename, long offset)
|
||||
}
|
||||
|
||||
|
||||
void BView::BeginPicture(BPicture *picture)
|
||||
void
|
||||
BView::BeginPicture(BPicture *picture)
|
||||
{
|
||||
if (do_owner_check() && picture && picture->usurped == NULL) {
|
||||
picture->usurp(cpicture);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
|
||||
#include "DrawingEngine.h"
|
||||
#include "ServerApp.h"
|
||||
#include "ServerBitmap.h"
|
||||
#include "ServerPicture.h"
|
||||
#include "ServerTokenSpace.h"
|
||||
@@ -25,6 +26,7 @@
|
||||
#include <ShapePrivate.h>
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <List.h>
|
||||
#include <Shape.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -108,7 +110,7 @@ ShapePainter::IterateClose(void)
|
||||
void
|
||||
ShapePainter::Draw(ViewLayer *view, BRect frame, bool filled)
|
||||
{
|
||||
// We're going to draw the currently iterated picture.
|
||||
// We're going to draw the currently iterated shape.
|
||||
int32 opCount, ptCount;
|
||||
opCount = fOpStack.size();
|
||||
ptCount = fPtStack.size();
|
||||
@@ -136,6 +138,8 @@ ShapePainter::Draw(ViewLayer *view, BRect frame, bool filled)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// drawing functions
|
||||
static void
|
||||
get_polygon_frame(const BPoint *points, int32 numPoints, BRect *_frame)
|
||||
{
|
||||
@@ -406,7 +410,6 @@ static void
|
||||
draw_pixels(ViewLayer *view, BRect src, BRect dest, int32 width, int32 height,
|
||||
int32 bytesPerRow, int32 pixelFormat, int32 flags, const void *data)
|
||||
{
|
||||
// TODO: Review this
|
||||
UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1), (color_space)pixelFormat, flags, bytesPerRow);
|
||||
|
||||
if (!bitmap.IsValid())
|
||||
@@ -420,6 +423,17 @@ draw_pixels(ViewLayer *view, BRect src, BRect dest, int32 width, int32 height,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_picture(ViewLayer *view, BPoint where, int32 token)
|
||||
{
|
||||
ServerPicture *picture = view->Window()->ServerWindow()->App()->FindPicture(token);
|
||||
if (picture != NULL) {
|
||||
view->CurrentState()->SetOrigin(where);
|
||||
picture->Play(view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_clipping_rects(ViewLayer *view, const BRect *rects, uint32 numRects)
|
||||
{
|
||||
@@ -667,7 +681,7 @@ const void *tableEntries[] = {
|
||||
(const void *)fill_shape,
|
||||
(const void *)draw_string,
|
||||
(const void *)draw_pixels,
|
||||
(const void *)reserved, // TODO: This is probably "draw_picture". Investigate
|
||||
(const void *)draw_picture,
|
||||
(const void *)set_clipping_rects,
|
||||
(const void *)clip_to_picture,
|
||||
(const void *)push_state,
|
||||
@@ -703,7 +717,9 @@ const void *tableEntries[] = {
|
||||
ServerPicture::ServerPicture()
|
||||
:
|
||||
PictureDataWriter(),
|
||||
fData(NULL)
|
||||
fData(NULL),
|
||||
fPictures(NULL),
|
||||
fUsurped(NULL)
|
||||
{
|
||||
fToken = gTokenSpace.NewToken(kPictureToken, this);
|
||||
fData = new (std::nothrow) BMallocIO();
|
||||
@@ -715,7 +731,9 @@ ServerPicture::ServerPicture()
|
||||
ServerPicture::ServerPicture(const ServerPicture &picture)
|
||||
:
|
||||
PictureDataWriter(),
|
||||
fData(NULL)
|
||||
fData(NULL),
|
||||
fPictures(NULL),
|
||||
fUsurped(NULL)
|
||||
{
|
||||
fToken = gTokenSpace.NewToken(kPictureToken, this);
|
||||
|
||||
@@ -738,7 +756,9 @@ ServerPicture::ServerPicture(const ServerPicture &picture)
|
||||
ServerPicture::ServerPicture(const char *fileName, const int32 &offset)
|
||||
:
|
||||
PictureDataWriter(),
|
||||
fData(NULL)
|
||||
fData(NULL),
|
||||
fPictures(NULL),
|
||||
fUsurped(NULL)
|
||||
{
|
||||
BPrivate::Storage::OffsetFile *file =
|
||||
new BPrivate::Storage::OffsetFile(new BFile(fileName, B_READ_WRITE), (off_t)offset);
|
||||
@@ -757,6 +777,7 @@ ServerPicture::~ServerPicture()
|
||||
{
|
||||
delete fData;
|
||||
gTokenSpace.RemoveToken(fToken);
|
||||
delete fPictures;
|
||||
}
|
||||
|
||||
|
||||
@@ -800,11 +821,41 @@ ServerPicture::Play(ViewLayer *view)
|
||||
if (mallocIO == NULL)
|
||||
return;
|
||||
|
||||
PicturePlayer player(mallocIO->Buffer(), mallocIO->BufferLength(), NULL);
|
||||
PicturePlayer player(mallocIO->Buffer(), mallocIO->BufferLength(), fPictures);
|
||||
player.Play(const_cast<void **>(tableEntries), sizeof(tableEntries) / sizeof(void *), view);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ServerPicture::Usurp(ServerPicture *picture)
|
||||
{
|
||||
fUsurped = picture;
|
||||
}
|
||||
|
||||
|
||||
ServerPicture *
|
||||
ServerPicture::StepDown()
|
||||
{
|
||||
ServerPicture *old = fUsurped;
|
||||
fUsurped = NULL;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ServerPicture::NestPicture(ServerPicture *picture)
|
||||
{
|
||||
if (fPictures == NULL)
|
||||
fPictures = new (std::nothrow) BList;
|
||||
|
||||
if (fPictures == NULL
|
||||
|| !fPictures->AddItem(picture))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
off_t
|
||||
ServerPicture::DataLength() const
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
class ServerApp;
|
||||
class ViewLayer;
|
||||
class BPrivate::LinkReceiver;
|
||||
class BList;
|
||||
class ServerPicture : public PictureDataWriter {
|
||||
public:
|
||||
int32 Token() { return fToken; }
|
||||
@@ -22,10 +23,14 @@ public:
|
||||
void EnterFontChange();
|
||||
void ExitFontChange();
|
||||
|
||||
void SyncState(ViewLayer *view);
|
||||
|
||||
void SyncState(ViewLayer *view);
|
||||
void Play(ViewLayer *view);
|
||||
|
||||
void Usurp(ServerPicture *newPicture);
|
||||
ServerPicture* StepDown();
|
||||
|
||||
bool NestPicture(ServerPicture *picture);
|
||||
|
||||
off_t DataLength() const;
|
||||
|
||||
status_t ImportData(BPrivate::LinkReceiver &link);
|
||||
@@ -42,6 +47,8 @@ friend class ServerApp;
|
||||
int32 fToken;
|
||||
BPositionIO *fData;
|
||||
// DrawState *fState;
|
||||
BList *fPictures;
|
||||
ServerPicture *fUsurped;
|
||||
};
|
||||
|
||||
#endif // __SERVER_PICTURE_H
|
||||
|
||||
@@ -2171,14 +2171,14 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
|
||||
case AS_FILL_TRIANGLE:
|
||||
{
|
||||
DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n", Title()));
|
||||
|
||||
BPoint pts[3];
|
||||
|
||||
BPoint pts[3];
|
||||
BRect rect;
|
||||
|
||||
for (int32 i = 0; i < 3; i++) {
|
||||
for (int32 i = 0; i < 3; i++) {
|
||||
link.Read<BPoint>(&(pts[i]));
|
||||
fCurrentLayer->ConvertToScreenForDrawing(&pts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
link.Read<BRect>(&rect);
|
||||
|
||||
@@ -2439,6 +2439,18 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_FILL_REGION:
|
||||
{
|
||||
// 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;
|
||||
for (int32 i = 0; i < region.CountRects(); i++)
|
||||
picture->WriteDrawRect(region.RectAt(i), true);
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_STROKE_ROUNDRECT:
|
||||
case AS_FILL_ROUNDRECT:
|
||||
{
|
||||
@@ -2478,6 +2490,57 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_STROKE_TRIANGLE:
|
||||
case AS_FILL_TRIANGLE:
|
||||
{
|
||||
// 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);
|
||||
|
||||
picture->WriteDrawPolygon(3, points,
|
||||
true, code == AS_FILL_TRIANGLE);
|
||||
break;
|
||||
}
|
||||
case AS_STROKE_POLYGON:
|
||||
case AS_FILL_POLYGON:
|
||||
{
|
||||
BRect polyFrame;
|
||||
bool isClosed = true;
|
||||
int32 pointCount;
|
||||
const bool fill = (code == AS_FILL_POLYGON);
|
||||
|
||||
link.Read<BRect>(&polyFrame);
|
||||
if (code == AS_STROKE_POLYGON)
|
||||
link.Read<bool>(&isClosed);
|
||||
link.Read<int32>(&pointCount);
|
||||
|
||||
BPoint* pointList = new(nothrow) BPoint[pointCount];
|
||||
if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
|
||||
picture->WriteDrawPolygon(pointCount, pointList,
|
||||
isClosed && pointCount > 2, fill);
|
||||
}
|
||||
delete[] pointList;
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_STROKE_BEZIER:
|
||||
case AS_FILL_BEZIER:
|
||||
{
|
||||
BPoint points[4];
|
||||
for (int32 i = 0; i < 4; i++) {
|
||||
link.Read<BPoint>(&(points[i]));
|
||||
}
|
||||
picture->WriteDrawBezier(points, code == AS_FILL_BEZIER);
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_STROKE_LINE:
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
@@ -2604,6 +2667,41 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver &link)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_LAYER_DRAW_PICTURE:
|
||||
{
|
||||
int32 token;
|
||||
if (link.Read<int32>(&token) == B_OK) {
|
||||
BPoint where;
|
||||
link.Read<BPoint>(&where);
|
||||
picture->WriteDrawPicture(where, token);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_LAYER_BEGIN_PICTURE:
|
||||
{
|
||||
ServerPicture *newPicture = App()->CreatePicture();
|
||||
newPicture->Usurp(picture);
|
||||
newPicture->SyncState(fCurrentLayer);
|
||||
fCurrentLayer->SetPicture(newPicture);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_LAYER_END_PICTURE:
|
||||
{
|
||||
ServerPicture *steppedDown = picture->StepDown();
|
||||
if (!steppedDown)
|
||||
return false;
|
||||
|
||||
steppedDown->NestPicture(picture);
|
||||
fCurrentLayer->SetPicture(steppedDown);
|
||||
fLink.StartMessage(B_OK);
|
||||
fLink.Attach<int32>(picture->Token());
|
||||
fLink.Flush();
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
case AS_LAYER_SET_BLENDING_MODE:
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user