-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Implement page locks #33737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement page locks #33737
Changes from all commits
e2d15a5
c92e225
736258a
5cd2058
0cc86f2
7fe9c9f
4c7599f
3ac7e5a
d2d9db0
200b731
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -100,14 +100,13 @@ MeasureBase::~MeasureBase() | |
|
|
||
| System* MeasureBase::prevNonVBoxSystem() const | ||
| { | ||
| bool mmRests = score()->style().styleB(Sid::createMultiMeasureRests); | ||
| System* curSystem = system(); | ||
| IF_ASSERT_FAILED(curSystem) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| System* prevSystem = curSystem; | ||
| for (const MeasureBase* mb = this; mb && prevSystem == curSystem; mb = mmRests ? mb->prevMM() : mb->prev()) { | ||
| for (const MeasureBase* mb = this; mb && prevSystem == curSystem; mb = mb->prevMM()) { | ||
| if (mb->isMeasure() || mb->isHBox()) { | ||
| prevSystem = mb->system(); | ||
| } else { | ||
|
|
@@ -120,14 +119,13 @@ System* MeasureBase::prevNonVBoxSystem() const | |
|
|
||
| System* MeasureBase::nextNonVBoxSystem() const | ||
| { | ||
| bool mmRests = score()->style().styleB(Sid::createMultiMeasureRests); | ||
| System* curSystem = system(); | ||
| IF_ASSERT_FAILED(curSystem) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| System* nextSystem = curSystem; | ||
| for (const MeasureBase* mb = this; mb && nextSystem == curSystem; mb = mmRests ? mb->nextMM() : mb->next()) { | ||
| for (const MeasureBase* mb = this; mb && nextSystem == curSystem; mb = mb->nextMM()) { | ||
| if (mb->isMeasure() || mb->isHBox()) { | ||
| nextSystem = mb->system(); | ||
| } else { | ||
|
|
@@ -138,6 +136,41 @@ System* MeasureBase::nextNonVBoxSystem() const | |
| return nextSystem != curSystem ? nextSystem : nullptr; | ||
| } | ||
|
|
||
| Page* MeasureBase::page() const | ||
| { | ||
| return system() ? system()->page() : nullptr; | ||
| } | ||
|
|
||
| Page* MeasureBase::prevPage() const | ||
| { | ||
| Page* curPage = system() ? system()->page() : nullptr; | ||
| IF_ASSERT_FAILED(curPage) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| Page* prevPage = curPage; | ||
| for (const MeasureBase* mb = this; mb && prevPage == curPage; mb = mb->prevMM()) { | ||
| prevPage = mb->system()->page(); | ||
| } | ||
|
|
||
| return prevPage != curPage ? prevPage : nullptr; | ||
| } | ||
|
|
||
| Page* MeasureBase::nextPage() const | ||
| { | ||
| Page* curPage = system() ? system()->page() : nullptr; | ||
| IF_ASSERT_FAILED(curPage) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| Page* nextPage = curPage; | ||
| for (const MeasureBase* mb = this; mb && nextPage == curPage; mb = mb->nextMM()) { | ||
| nextPage = mb->system()->page(); | ||
| } | ||
|
|
||
| return nextPage != curPage ? nextPage : nullptr; | ||
| } | ||
|
|
||
| //--------------------------------------------------------- | ||
| // add | ||
| /// Add new EngravingItem \a el to MeasureBase | ||
|
|
@@ -638,20 +671,37 @@ bool MeasureBase::isBefore(const MeasureBase* other) const | |
| return false; | ||
| } | ||
|
|
||
| const SystemLock* MeasureBase::systemLock() const | ||
| const RangeLock* MeasureBase::systemLock() const | ||
| { | ||
| return score()->systemLocks()->lockContaining(this); | ||
| } | ||
|
|
||
| bool MeasureBase::isStartOfSystemLock() const | ||
| { | ||
| const SystemLock* lock = score()->systemLocks()->lockStartingAt(this); | ||
| const RangeLock* lock = score()->systemLocks()->lockStartingAt(this); | ||
| return lock != nullptr; | ||
| } | ||
|
|
||
| bool MeasureBase::isEndOfSystemLock() const | ||
| { | ||
| const SystemLock* lock = systemLock(); | ||
| const RangeLock* lock = systemLock(); | ||
| return lock && lock->endMB() == this; | ||
| } | ||
|
|
||
| const RangeLock* MeasureBase::pageLock() const | ||
| { | ||
| return score()->pageLocks()->lockContaining(this); | ||
| } | ||
|
|
||
| bool MeasureBase::isStartOfPageLock() const | ||
| { | ||
| const RangeLock* lock = score()->pageLocks()->lockStartingAt(this); | ||
| return lock != nullptr; | ||
| } | ||
|
|
||
| bool MeasureBase::isEndOfPageLock() const | ||
| { | ||
| const RangeLock* lock = pageLock(); | ||
| return lock && lock->endMB() == this; | ||
| } | ||
|
|
||
|
|
@@ -902,6 +952,39 @@ Measure* MeasureBaseList::measureByTick(int tick) const | |
| return nullptr; | ||
| } | ||
|
|
||
| MeasureBase* MeasureBaseList::measureBaseByTick(int tick) const | ||
| { | ||
| if (empty() || tick > m_last->endTick().ticks()) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| auto it = m_tickIndex.upper_bound(tick); | ||
|
|
||
| if (it == m_tickIndex.begin()) { | ||
| MeasureBase* mb = it->second; | ||
|
|
||
| return mb; | ||
| } | ||
|
|
||
| --it; | ||
| for (;; --it) { | ||
| if (it == m_tickIndex.begin()) { | ||
| MeasureBase* mb = it->second; | ||
|
|
||
| return mb; | ||
| } | ||
|
|
||
| MeasureBase* mb = it->second; | ||
| if (!mb) { | ||
| break; | ||
| } | ||
|
|
||
| return mb; | ||
| } | ||
|
|
||
| return nullptr; | ||
|
Comment on lines
+955
to
+985
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Persisting arbitrary lock boundaries by tick is ambiguous here.
🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| std::vector<MeasureBase*> MeasureBaseList::measureBasesAtTick(int tick) const | ||
| { | ||
| std::vector<MeasureBase*> result; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential null dereference in page navigation loops.
In both
prevPage()andnextPage(), the loop body accessesmb->system()->page()without checking ifmb->system()is null. While the initial check validatesthis->system(), subsequentMeasureBaseinstances encountered viaprevMM()/nextMM()may have null systems (e.g., unattached measures, frames outside systems).🛡️ Proposed fix to add null guard
Page* MeasureBase::prevPage() const { Page* curPage = system() ? system()->page() : nullptr; IF_ASSERT_FAILED(curPage) { return nullptr; } Page* prevPage = curPage; for (const MeasureBase* mb = this; mb && prevPage == curPage; mb = mb->prevMM()) { - prevPage = mb->system()->page(); + if (mb->system()) { + prevPage = mb->system()->page(); + } } return prevPage != curPage ? prevPage : nullptr; } Page* MeasureBase::nextPage() const { Page* curPage = system() ? system()->page() : nullptr; IF_ASSERT_FAILED(curPage) { return nullptr; } Page* nextPage = curPage; for (const MeasureBase* mb = this; mb && nextPage == curPage; mb = mb->nextMM()) { - nextPage = mb->system()->page(); + if (mb->system()) { + nextPage = mb->system()->page(); + } } return nextPage != curPage ? nextPage : nullptr; }📝 Committable suggestion
🤖 Prompt for AI Agents