Skip to content

Commit

Permalink
Fix GH#9043: Music should automatically clear headers and footers
Browse files Browse the repository at this point in the history
Backport of musescore#9193, part 1 and 2
  • Loading branch information
Nick-Mazuk authored and Jojo-Schmitz committed Sep 22, 2021
1 parent b2f7a52 commit 237e9d6
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 9 deletions.
10 changes: 6 additions & 4 deletions libmscore/layout.cpp
Expand Up @@ -4742,7 +4742,9 @@ void LayoutContext::collectPage()
{
const qreal slb = score->styleP(Sid::staffLowerBorder);
bool breakPages = score->layoutMode() != LayoutMode::SYSTEM;
qreal ey = page->height() - page->bm();
qreal footerExtension = qMax(0.0, page->footerHeight() - score->styleV(Sid::footerOffset).value<QPointF>().y()); // how much the footer extends above the margin
qreal headerExtension = qMax(0.0, page->headerHeight() - score->styleV(Sid::headerOffset).value<QPointF>().y()); // how much the header extends below the margin
qreal endY = page->height() - page->bm() - footerExtension;
qreal y = 0.0;

System* nextSystem = 0;
Expand All @@ -4756,7 +4758,7 @@ void LayoutContext::collectPage()
y = page->system(0)->y() + page->system(0)->height();
}
else {
y = page->tm();
y = page->tm() + headerExtension;
}
for (int i = 1; i < pSystems; ++i) {
System* cs = page->system(i);
Expand Down Expand Up @@ -4886,12 +4888,12 @@ void LayoutContext::collectPage()
qreal margin = qMax(curSystem->minBottom(), curSystem->spacerDistance(false));
dist += qMax(margin, slb);
}
breakPage = (y + dist) >= ey && breakPages;
breakPage = (y + dist) >= endY && breakPages;
}
if (breakPage) {
qreal dist = qMax(prevSystem->minBottom(), prevSystem->spacerDistance(false));
dist = qMax(dist, slb);
layoutPage(page, ey - (y + dist));
layoutPage(page, endY - (y + dist));
// if we collected a system we cannot fit onto this page,
// we need to collect next page in order to correctly set system positions
if (collected)
Expand Down
103 changes: 98 additions & 5 deletions libmscore/page.cpp
Expand Up @@ -147,10 +147,25 @@ void Page::draw(QPainter* painter) const
//---------------------------------------------------------

void Page::drawHeaderFooter(QPainter* p, int area, const QString& ss) const
{
Text* text = layoutHeaderFooter(area, ss);
if (!text)
return;
p->translate(text->pos());
text->draw(p);
p->translate(-text->pos());
text->setParent(0);
}

//---------------------------------------------------------
// layoutHeaderFooter
//---------------------------------------------------------

Text* Page::layoutHeaderFooter(int area, const QString& ss) const
{
QString s = replaceTextMacros(ss);
if (s.isEmpty())
return;
return nullptr;

Text* text;
if (area < MAX_HEADERS) {
Expand Down Expand Up @@ -187,10 +202,88 @@ void Page::drawHeaderFooter(QPainter* p, int area, const QString& ss) const
text->setAlign(flags);
text->setXmlText(s);
text->layout();
p->translate(text->pos());
text->draw(p);
p->translate(-text->pos());
text->setParent(0);
return text;
}

//---------------------------------------------------------
// headerHeight
//---------------------------------------------------------

qreal Page::headerHeight() const
{
if (!score()->pageMode())
return 0.0;

int n = no() + 1 + score()->pageNumberOffset();

QString s1, s2, s3;

if (score()->styleB(Sid::showHeader) && (no() || score()->styleB(Sid::headerFirstPage))) {
bool odd = (n & 1) || !score()->styleB(Sid::headerOddEven);
if (odd) {
s1 = score()->styleSt(Sid::oddHeaderL);
s2 = score()->styleSt(Sid::oddHeaderC);
s3 = score()->styleSt(Sid::oddHeaderR);
}
else {
s1 = score()->styleSt(Sid::evenHeaderL);
s2 = score()->styleSt(Sid::evenHeaderC);
s3 = score()->styleSt(Sid::evenHeaderR);
}

Text* headerLeft = layoutHeaderFooter(0, s1);
Text* headerCenter = layoutHeaderFooter(1, s2);
Text* headerRight = layoutHeaderFooter(2, s3);

qreal headerLeftHeight = headerLeft ? headerLeft->visibleHeight() : 0.0;
qreal headerCenterHeight = headerCenter ? headerCenter->visibleHeight() : 0.0;
qreal headerRightHeight = headerRight ? headerRight->visibleHeight() : 0.0;
return qMax(headerLeftHeight, qMax(headerCenterHeight, headerRightHeight));
}

return 0.0;
}

//---------------------------------------------------------
// footerHeight
//---------------------------------------------------------

qreal Page::footerHeight() const
{
if (!score()->pageMode())
return 0.0;

int n = no() + 1 + score()->pageNumberOffset();

QString s1, s2, s3;

if (score()->styleB(Sid::showFooter) && (no() || score()->styleB(Sid::footerFirstPage))) {
bool odd = (n & 1) || !score()->styleB(Sid::footerOddEven);
if (odd) {
s1 = score()->styleSt(Sid::oddFooterL);
s2 = score()->styleSt(Sid::oddFooterC);
s3 = score()->styleSt(Sid::oddFooterR);
}
else {
s1 = score()->styleSt(Sid::evenFooterL);
s2 = score()->styleSt(Sid::evenFooterC);
s3 = score()->styleSt(Sid::evenFooterR);
}

Text* footerLeft = layoutHeaderFooter(3, s1);
Text* footerCenter = layoutHeaderFooter(4, s2);
Text* footerRight = layoutHeaderFooter(5, s3);

qreal footerLeftHeight = footerLeft ? footerLeft->visibleHeight() : 0.0;
qreal footerCenterHeight = footerCenter ? footerCenter->visibleHeight() : 0.0;
qreal footerRightHeight = footerRight ? footerRight->visibleHeight() : 0.0;

qreal footerHeight = qMax(footerLeftHeight, qMax(footerCenterHeight, footerRightHeight));

return footerHeight;
}

return 0.0;
}

#if 0
Expand Down
3 changes: 3 additions & 0 deletions libmscore/page.h
Expand Up @@ -42,6 +42,7 @@ class Page final : public Element {

QString replaceTextMacros(const QString&) const;
void drawHeaderFooter(QPainter*, int area, const QString&) const;
Text* layoutHeaderFooter(int area, const QString& ss) const;

public:
Page(Score*);
Expand All @@ -65,6 +66,8 @@ class Page final : public Element {
qreal bm() const;
qreal lm() const;
qreal rm() const;
qreal headerHeight() const;
qreal footerHeight() const;

void draw(QPainter*) const override;
void scanElements(void* data, void (*func)(void*, Element*), bool all=true) override;
Expand Down
28 changes: 28 additions & 0 deletions libmscore/textbase.cpp
Expand Up @@ -1798,6 +1798,8 @@ void TextBase::layout1()
_layout.append(TextBlock());
QRectF bb;
qreal y = 0;

// adjust the bounding box for the text item
for (int i = 0; i < rows(); ++i) {
TextBlock* t = &_layout[i];
t->layout(this);
Expand Down Expand Up @@ -1933,6 +1935,32 @@ qreal TextBase::lineHeight() const
return fontMetrics().height();
}

//---------------------------------------------------------
// visibleHeight
//---------------------------------------------------------

qreal TextBase::visibleHeight()
{
QRectF bb;
qreal y = 0;

// adjust the bounding box for the text item
for (int i = 0; i < rows(); ++i) {
TextBlock* t = &_layout[i];
if (t->columns() == 0 && i != rows() - 1)
continue;
t->layout(this);
const QRectF* r = &t->boundingRect();

if (r->height() == 0)
r = &_layout[i - i].boundingRect();
y += t->lineSpacing();
t->setY(y);
bb |= r->translated(0.0, y);
}
return bb.height();
}

//---------------------------------------------------------
// baseLine
//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions libmscore/textbase.h
Expand Up @@ -298,6 +298,7 @@ class TextBase : public Element {
qreal lineSpacing() const;
qreal lineHeight() const;
virtual qreal baseLine() const override;
qreal visibleHeight();

bool empty() const { return xmlText().isEmpty(); }
void clear() { setXmlText(QString()); }
Expand Down

0 comments on commit 237e9d6

Please sign in to comment.