From ed5de868df775fceddb5abedec7eab9bd5147d51 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 13 Aug 2007 07:20:43 +0000 Subject: [PATCH] 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 --- headers/private/interface/PictureDataWriter.h | 8 +- src/kits/interface/PictureDataWriter.cpp | 53 ++++++++- src/kits/interface/PicturePlayer.cpp | 4 + src/kits/interface/View.cpp | 3 +- src/servers/app/ServerPicture.cpp | 65 +++++++++-- src/servers/app/ServerPicture.h | 11 +- src/servers/app/ServerWindow.cpp | 106 +++++++++++++++++- 7 files changed, 234 insertions(+), 16 deletions(-) diff --git a/headers/private/interface/PictureDataWriter.h b/headers/private/interface/PictureDataWriter.h index 778ff60399..3e67796ce4 100644 --- a/headers/private/interface/PictureDataWriter.h +++ b/headers/private/interface/PictureDataWriter.h @@ -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); diff --git a/src/kits/interface/PictureDataWriter.cpp b/src/kits/interface/PictureDataWriter.cpp index f28f791723..0adb62cc20 100644 --- a/src/kits/interface/PictureDataWriter.cpp +++ b/src/kits/interface/PictureDataWriter.cpp @@ -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(numPoints); + for (int32 i = 0; i < numPoints; i++) + Write(points[i]); + if (!fill) + Write((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(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(where); + Write(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); } diff --git a/src/kits/interface/PicturePlayer.cpp b/src/kits/interface/PicturePlayer.cpp index 15addc9bdc..e59243a213 100644 --- a/src/kits/interface/PicturePlayer.cpp +++ b/src/kits/interface/PicturePlayer.cpp @@ -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(data), + *reinterpret_cast(data + sizeof(BPoint))); break; } diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index 26d2d42a1a..de14811ea2 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -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); diff --git a/src/servers/app/ServerPicture.cpp b/src/servers/app/ServerPicture.cpp index c3ae96c0a6..800f9e8524 100644 --- a/src/servers/app/ServerPicture.cpp +++ b/src/servers/app/ServerPicture.cpp @@ -10,6 +10,7 @@ #include "DrawingEngine.h" +#include "ServerApp.h" #include "ServerBitmap.h" #include "ServerPicture.h" #include "ServerTokenSpace.h" @@ -25,6 +26,7 @@ #include #include +#include #include #include @@ -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(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 { diff --git a/src/servers/app/ServerPicture.h b/src/servers/app/ServerPicture.h index ca986f4adb..02958fa648 100644 --- a/src/servers/app/ServerPicture.h +++ b/src/servers/app/ServerPicture.h @@ -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 diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index ea050601d7..71961effb8 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -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(&(pts[i])); fCurrentLayer->ConvertToScreenForDrawing(&pts[i]); - } + } link.Read(&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(&(points[i])); + } + + BRect rect; + link.Read(&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(&polyFrame); + if (code == AS_STROKE_POLYGON) + link.Read(&isClosed); + link.Read(&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(&(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(&token) == B_OK) { + BPoint where; + link.Read(&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(picture->Token()); + fLink.Flush(); + return true; + } /* case AS_LAYER_SET_BLENDING_MODE: {