From 0a40b3a1ceaee196dbe76bd9b76ca2026bf3d437 Mon Sep 17 00:00:00 2001 From: X512 Date: Tue, 24 Mar 2026 21:57:52 +0900 Subject: [PATCH] BPicture: fix subpicture token storage Picture token written for `BView::DrawPicture` and `BView::ClipTo[Inverse]Picture` should be zero-based index in subpictures array, not global app_server BPicture token. Part of #1133. Change-Id: I2a544aefb343650e8bad58c5d297f7b9d5d1dbb5 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10575 Reviewed-by: waddlesplash --- src/kits/interface/Picture.cpp | 8 ++++---- src/servers/app/Canvas.h | 3 --- src/servers/app/ServerPicture.cpp | 26 ++++++++++++++++---------- src/servers/app/ServerPicture.h | 2 +- src/servers/app/ServerWindow.cpp | 10 ++++++---- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/kits/interface/Picture.cpp b/src/kits/interface/Picture.cpp index cf8317aad7..95779a33c3 100644 --- a/src/kits/interface/Picture.cpp +++ b/src/kits/interface/Picture.cpp @@ -33,13 +33,13 @@ static BObjectList sPictureList; -static mutex sPictureListLock = MUTEX_INITIALIZER("BPicture list"); +static recursive_lock sPictureListLock = RECURSIVE_LOCK_INITIALIZER("BPicture list"); void reconnect_pictures_to_app_server() { - MutexLocker _(sPictureListLock); + RecursiveLocker _(sPictureListLock); for (int32 i = 0; i < sPictureList.CountItems(); i++) { BPicture::Private picture(sPictureList.ItemAt(i)); picture.ReconnectToAppServer(); @@ -215,14 +215,14 @@ BPicture::_InitData() fExtent = new (std::nothrow) _BPictureExtent_; - MutexLocker _(sPictureListLock); + RecursiveLocker _(sPictureListLock); sPictureList.AddItem(this); } BPicture::~BPicture() { - MutexLocker _(sPictureListLock); + RecursiveLocker _(sPictureListLock); sPictureList.RemoveItem(this, false); _DisposeData(); } diff --git a/src/servers/app/Canvas.h b/src/servers/app/Canvas.h index 981a34d5af..c5a9b858c4 100644 --- a/src/servers/app/Canvas.h +++ b/src/servers/app/Canvas.h @@ -73,7 +73,6 @@ public: void BlendLayer(Layer* layer); virtual DrawingEngine* GetDrawingEngine() const = 0; - virtual ServerPicture* GetPicture(int32 token) const = 0; virtual void RebuildClipping(bool deep) = 0; virtual void ResyncDrawState() {}; virtual void UpdateCurrentDrawingRegion() {}; @@ -101,8 +100,6 @@ public: virtual void RebuildClipping(bool deep) { /* TODO */ } virtual void ResyncDrawState(); virtual void UpdateCurrentDrawingRegion(); - virtual ServerPicture* GetPicture(int32 token) const - { /* TODO */ return NULL; } virtual IntRect Bounds() const; protected: diff --git a/src/servers/app/ServerPicture.cpp b/src/servers/app/ServerPicture.cpp index ac5de3a915..3705fd8039 100644 --- a/src/servers/app/ServerPicture.cpp +++ b/src/servers/app/ServerPicture.cpp @@ -239,7 +239,7 @@ ShapePainter::Draw(BRect frame, bool filled) class CanvasCallbacks: public BPrivate::PicturePlayerCallbacks { public: - CanvasCallbacks(Canvas* const canvas); + CanvasCallbacks(Canvas* const canvas, BObjectList& pictures); virtual void MovePenBy(const BPoint& where); virtual void StrokeLine(const BPoint& start, const BPoint& end); @@ -309,12 +309,14 @@ public: private: Canvas* const fCanvas; + BObjectList& fPictures; }; -CanvasCallbacks::CanvasCallbacks(Canvas* const canvas) +CanvasCallbacks::CanvasCallbacks(Canvas* const canvas, BObjectList& pictures) : - fCanvas(canvas) + fCanvas(canvas), + fPictures(pictures) { } @@ -655,7 +657,7 @@ CanvasCallbacks::DrawPixels(const BRect& src, const BRect& _dest, uint32 width, void CanvasCallbacks::DrawPicture(const BPoint& where, int32 token) { - BReference picture(fCanvas->GetPicture(token), true); + BReference picture(fPictures.ItemAt(token), false); if (picture != NULL) { fCanvas->PushState(); fCanvas->SetDrawingOrigin(where); @@ -690,7 +692,7 @@ void CanvasCallbacks::ClipToPicture(int32 pictureToken, const BPoint& where, bool clipToInverse) { - BReference picture(fCanvas->GetPicture(pictureToken), true); + BReference picture(fPictures.ItemAt(pictureToken), false); if (picture == NULL) return; BReference mask(new(std::nothrow) PictureAlphaMask(fCanvas->GetAlphaMask(), @@ -1246,7 +1248,7 @@ ServerPicture::Play(Canvas* target) if (mallocIO == NULL) return; - CanvasCallbacks callbacks(target); + CanvasCallbacks callbacks(target, *fPictures.Get()); BPrivate::PicturePlayer player(mallocIO->Buffer(), mallocIO->BufferLength(), PictureList::Private(fPictures.Get()).AsBList()); @@ -1283,17 +1285,21 @@ ServerPicture::AppendPicture(ServerPicture* picture) } -bool +int32 ServerPicture::NestPicture(ServerPicture* picture) { if (!fPictures.IsSet()) fPictures.SetTo(new(std::nothrow) PictureList); - if (!fPictures.IsSet() || !fPictures->AddItem(picture)) - return false; + if (!fPictures.IsSet()) + return -1; + + int32 index = fPictures->CountItems(); + if (!fPictures->AddItem(picture)) + return -1; picture->AcquireReference(); - return true; + return index; } diff --git a/src/servers/app/ServerPicture.h b/src/servers/app/ServerPicture.h index e6fcbc0eb8..df91401b05 100644 --- a/src/servers/app/ServerPicture.h +++ b/src/servers/app/ServerPicture.h @@ -60,7 +60,7 @@ public: ServerPicture* PopPicture(); void AppendPicture(ServerPicture* picture); - bool NestPicture(ServerPicture* picture); + int32 NestPicture(ServerPicture* picture); off_t DataLength() const; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 2ab8f751c5..fd3f262b5a 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -4012,8 +4012,9 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) // We need to make a copy of the picture, since it can // change after it has been drawn BReference copy(App()->CreatePicture(pictureToDraw), true); - picture->NestPicture(copy); - picture->WriteDrawPicture(where, copy->Token()); + int32 subPictureIndex = picture->NestPicture(copy); + if (subPictureIndex >= 0) + picture->WriteDrawPicture(where, subPictureIndex); } } break; @@ -4063,8 +4064,9 @@ ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link) // We need to make a copy of the picture, since it can // change after it has been drawn BReference copy(App()->CreatePicture(pictureToClip), true); - picture->NestPicture(copy); - picture->WriteClipToPicture(copy->Token(), where, inverse); + int32 subPictureIndex = picture->NestPicture(copy); + if (subPictureIndex >= 0) + picture->WriteClipToPicture(subPictureIndex, where, inverse); } break; }