Skip to content

Commit 19b7168

Browse files
committed
Copyright and page number text styles
1 parent a654c72 commit 19b7168

File tree

68 files changed

+343
-34
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+343
-34
lines changed

src/engraving/api/v1/apitypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,8 @@ enum class Tid {
558558
INSTRUMENT_CHANGE = int(mu::engraving::TextStyleType::INSTRUMENT_CHANGE),
559559
HEADER = int(mu::engraving::TextStyleType::HEADER),
560560
FOOTER = int(mu::engraving::TextStyleType::FOOTER),
561+
COPYRIGHT = int(mu::engraving::TextStyleType::COPYRIGHT),
562+
PAGE_NUMBER = int(mu::engraving::TextStyleType::PAGE_NUMBER)
561563
};
562564
Q_ENUM_NS(Tid);
563565

src/engraving/dom/page.cpp

Lines changed: 97 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,27 @@ void Page::appendSystem(System* s)
8484
m_systems.push_back(s);
8585
}
8686

87+
// Slight hack, see usage (header and footer styles will be getting more holistic rework in future)
88+
#define HEADERFOOTER_SID_FOR_SUFFIX(suffix) \
89+
(containsCopyright ? Sid::copyright##suffix : \
90+
(containsPageNumber ? Sid::pageNumber##suffix : \
91+
(isHeader ? Sid::header##suffix : Sid::footer##suffix))) \
92+
8793
//---------------------------------------------------------
8894
// layoutHeaderFooter
8995
//---------------------------------------------------------
9096

9197
Text* Page::layoutHeaderFooter(int area, const String& ss) const
9298
{
93-
String s = replaceTextMacros(ss);
94-
if (s.isEmpty()) {
99+
bool isHeader = area < MAX_HEADERS;
100+
101+
TextBlock tb = replaceTextMacros(isHeader, ss);
102+
if (tb.fragmentsWithoutEmpty().empty()) {
95103
return nullptr;
96104
}
97105

98106
Text* text;
99-
if (area < MAX_HEADERS) {
107+
if (isHeader) {
100108
text = score()->headerText(area);
101109
if (!text) {
102110
text = Factory::createText((Page*)this, TextStyleType::HEADER);
@@ -116,6 +124,7 @@ Text* Page::layoutHeaderFooter(int area, const String& ss) const
116124
}
117125
}
118126
text->setParent((Page*)this);
127+
119128
Align align = { AlignH::LEFT, AlignV::TOP };
120129
switch (area) {
121130
case 0: align = { AlignH::LEFT, AlignV::TOP };
@@ -131,9 +140,42 @@ Text* Page::layoutHeaderFooter(int area, const String& ss) const
131140
case 5: align = { AlignH::RIGHT, AlignV::BOTTOM };
132141
break;
133142
}
143+
144+
text->mutldata()->blocks = { tb };
145+
146+
//! NOTE: Keep in sync with replaceTextMacros
147+
std::wregex copyrightSearch(LR"(\$[cC])");
148+
std::wregex pageNumberSearch(LR"(\$[pPnN])");
149+
150+
bool containsCopyright = ss.contains(copyrightSearch);
151+
bool containsPageNumber = ss.contains(pageNumberSearch);
152+
153+
// TextBase properties (slight hack) - we'll use copyright/page number styling if the string contains
154+
//copyright/page number macros (hack because any non-copyright text will also adopt these style values)
134155
text->setAlign(align);
135-
text->setXmlText(s);
156+
text->setTextLineSpacing(style().styleD(HEADERFOOTER_SID_FOR_SUFFIX(LineSpacing)));
157+
text->setColor(style().styleV(HEADERFOOTER_SID_FOR_SUFFIX(Color)).value<Color>());
158+
159+
const bool spatiumDependent = style().styleB(HEADERFOOTER_SID_FOR_SUFFIX(FontSpatiumDependent));
160+
const double factor = spatiumDependent ? SPATIUM20 : DPMM;
161+
const PointF p = style().styleV(HEADERFOOTER_SID_FOR_SUFFIX(Offset)).value<PointF>();
162+
const PointF pointScaled = { p.x() * factor, p.y() * factor };
163+
text->setOffset(pointScaled);
164+
165+
// Frame properties...
166+
text->setFrameType(style().styleV(HEADERFOOTER_SID_FOR_SUFFIX(FrameType)).value<FrameType>());
167+
text->setFrameColor(style().styleV(HEADERFOOTER_SID_FOR_SUFFIX(FrameFgColor)).value<Color>());
168+
text->setBgColor(style().styleV(HEADERFOOTER_SID_FOR_SUFFIX(FrameBgColor)).value<Color>());
169+
text->setFrameWidth(style().styleV(HEADERFOOTER_SID_FOR_SUFFIX(FrameWidth)).value<Spatium>());
170+
text->setPaddingWidth(style().styleV(HEADERFOOTER_SID_FOR_SUFFIX(FramePadding)).value<Spatium>());
171+
text->setFrameRound(style().styleI(HEADERFOOTER_SID_FOR_SUFFIX(FrameRound)));
172+
173+
// Generates text from ldata, ensures newlines are formatted properly...
174+
text->genText();
175+
text->createBlocks();
176+
136177
renderer()->layoutItem(text);
178+
137179
return text;
138180
}
139181

@@ -326,10 +368,14 @@ void Page::doRebuildBspTree()
326368
// workTitle
327369
//---------------------------------------------------------
328370

329-
String Page::replaceTextMacros(const String& s) const
371+
TextBlock Page::replaceTextMacros(bool isHeader, const String& s) const
330372
{
331-
String d;
373+
std::list<TextFragment> fragments(1);
332374
for (size_t i = 0, n = s.size(); i < n; ++i) {
375+
// Header / footer style by default...
376+
fragments.back().format.setStyle(style().styleV(isHeader ? Sid::headerFontStyle : Sid::footerFontStyle).value<FontStyle>());
377+
fragments.back().format.setFontSize(style().styleD(isHeader ? Sid::headerFontSize : Sid::footerFontSize));
378+
fragments.back().format.setFontFamily(style().styleSt(isHeader ? Sid::headerFontFace : Sid::footerFontFace));
333379
Char c = s.at(i);
334380
if (c == '$' && (i < (n - 1))) {
335381
Char nc = s.at(i + 1);
@@ -348,52 +394,61 @@ String Page::replaceTextMacros(const String& s) const
348394
{
349395
int no = static_cast<int>(m_no) + 1 + score()->pageNumberOffset();
350396
if (no > 0) {
351-
d += String::number(no);
397+
TextFragment pageNumberFragment(String::number(no));
398+
pageNumberFragment.format.setStyle(style().styleV(Sid::pageNumberFontStyle).value<FontStyle>());
399+
pageNumberFragment.format.setFontSize(style().styleD(Sid::pageNumberFontSize));
400+
pageNumberFragment.format.setFontFamily(style().styleSt(Sid::pageNumberFontFace));
401+
fragments.emplace_back(pageNumberFragment);
402+
fragments.emplace_back(TextFragment()); // Start next fragment
352403
}
353404
}
354405
break;
355406
case 'n':
356-
d += String::number(score()->npages() + score()->pageNumberOffset());
407+
fragments.back().text += String::number(score()->npages() + score()->pageNumberOffset());
357408
break;
358409
case 'i': // not on first page
359410
if (!m_no) {
360411
break;
361412
}
362413
// FALLTHROUGH
363414
case 'I':
364-
d += score()->metaTag(u"partName").toXmlEscaped();
415+
fragments.back().text += score()->metaTag(u"partName").toXmlEscaped();
365416
break;
366417
case 'f':
367-
d += masterScore()->fileInfo()->fileName(false).toString().toXmlEscaped();
418+
fragments.back().text += masterScore()->fileInfo()->fileName(false).toString().toXmlEscaped();
368419
break;
369420
case 'F':
370-
d += masterScore()->fileInfo()->path().toString().toXmlEscaped();
421+
fragments.back().text += masterScore()->fileInfo()->path().toString().toXmlEscaped();
371422
break;
372423
case 'd':
373-
d += muse::Date::currentDate().toString(muse::DateFormat::ISODate);
424+
fragments.back().text += muse::Date::currentDate().toString(muse::DateFormat::ISODate);
374425
break;
375426
case 'D':
376427
{
377428
String creationDate = score()->metaTag(u"creationDate");
378429
if (creationDate.isEmpty()) {
379-
d += masterScore()->fileInfo()->birthTime().date().toString(muse::DateFormat::ISODate);
430+
fragments.back().text += masterScore()->fileInfo()->birthTime().date().toString(
431+
muse::DateFormat::ISODate);
380432
} else {
381-
d += muse::Date::fromStringISOFormat(creationDate).toString(muse::DateFormat::ISODate);
433+
fragments.back().text += muse::Date::fromStringISOFormat(creationDate).toString(
434+
muse::DateFormat::ISODate);
382435
}
383436
}
384437
break;
385438
case 'm':
386439
if (score()->dirty() || !masterScore()->saved()) {
387-
d += muse::Time::currentTime().toString(muse::DateFormat::ISODate);
440+
fragments.back().text += muse::Time::currentTime().toString(muse::DateFormat::ISODate);
388441
} else {
389-
d += masterScore()->fileInfo()->lastModified().time().toString(muse::DateFormat::ISODate);
442+
fragments.back().text += masterScore()->fileInfo()->lastModified().time().toString(
443+
muse::DateFormat::ISODate);
390444
}
391445
break;
392446
case 'M':
393447
if (score()->dirty() || !masterScore()->saved()) {
394-
d += muse::Date::currentDate().toString(muse::DateFormat::ISODate);
448+
fragments.back().text += muse::Date::currentDate().toString(muse::DateFormat::ISODate);
395449
} else {
396-
d += masterScore()->fileInfo()->lastModified().date().toString(muse::DateFormat::ISODate);
450+
fragments.back().text += masterScore()->fileInfo()->lastModified().date().toString(
451+
muse::DateFormat::ISODate);
397452
}
398453
break;
399454
case 'C': // only on first page
@@ -402,29 +457,36 @@ String Page::replaceTextMacros(const String& s) const
402457
}
403458
// FALLTHROUGH
404459
case 'c':
405-
d += score()->metaTag(u"copyright").toXmlEscaped();
406-
break;
460+
{
461+
TextFragment copyrightFragment(score()->metaTag(u"copyright").toXmlEscaped());
462+
copyrightFragment.format.setStyle(style().styleV(Sid::copyrightFontStyle).value<FontStyle>());
463+
copyrightFragment.format.setFontSize(style().styleD(Sid::copyrightFontSize));
464+
copyrightFragment.format.setFontFamily(style().styleSt(Sid::copyrightFontFace));
465+
fragments.emplace_back(copyrightFragment);
466+
fragments.emplace_back(TextFragment()); // Start next fragment
467+
}
468+
break;
407469
case 'v':
408470
if (score()->dirty()) {
409-
d += score()->appVersion();
471+
fragments.back().text += score()->appVersion();
410472
} else {
411-
d += score()->mscoreVersion();
473+
fragments.back().text += score()->mscoreVersion();
412474
}
413475
break;
414476
case 'r':
415477
if (score()->dirty()) {
416-
d += revision;
478+
fragments.back().text += revision;
417479
} else {
418480
int rev = score()->mscoreRevision();
419481
if (rev > 99999) { // MuseScore 1.3 is decimal 5702, 2.0 and later uses a 7-digit hex SHA
420-
d += String::number(rev, 16);
482+
fragments.back().text += String::number(rev, 16);
421483
} else {
422-
d += String::number(rev, 10);
484+
fragments.back().text += String::number(rev, 10);
423485
}
424486
}
425487
break;
426488
case '$':
427-
d += '$';
489+
fragments.back().text += '$';
428490
break;
429491
case ':':
430492
{
@@ -437,24 +499,27 @@ String Page::replaceTextMacros(const String& s) const
437499
tag += s.at(k);
438500
}
439501
if (k != n) { // found ':' ?
440-
d += score()->metaTag(tag).toXmlEscaped();
502+
fragments.back().text += score()->metaTag(tag).toXmlEscaped();
441503
i = k - 1;
442504
}
443505
}
444506
break;
445507
default:
446-
d += '$';
447-
d += nc;
508+
fragments.back().text += '$';
509+
fragments.back().text += nc;
448510
break;
449511
}
450512
++i;
451513
} else if (c == '&') {
452-
d += u"&amp;";
514+
fragments.back().text += u"&amp;";
453515
} else {
454-
d += c;
516+
fragments.back().text += c;
455517
}
456518
}
457-
return d;
519+
520+
TextBlock tb;
521+
tb.fragments() = fragments;
522+
return tb;
458523
}
459524

460525
//---------------------------------------------------------

src/engraving/dom/page.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "engravingitem.h"
2929
#include "bsp.h"
30+
#include "text.h"
3031

3132
namespace mu::engraving {
3233
class RootItem;
@@ -93,7 +94,7 @@ class Page final : public EngravingItem
9394
Page(RootItem* parent);
9495

9596
void doRebuildBspTree();
96-
String replaceTextMacros(const String&) const;
97+
TextBlock replaceTextMacros(bool isHeader, const String&) const;
9798

9899
std::vector<System*> m_systems;
99100
page_idx_t m_no = 0; // page number

src/engraving/dom/textbase.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ class TextBase : public EngravingItem
487487
DirectionV direction() const { return m_direction; }
488488
void setCenterBetweenStaves(AutoOnOff v) { m_centerBetweenStaves = v; }
489489
AutoOnOff centerBetweenStaves() const { return m_centerBetweenStaves; }
490+
void genText();
490491

491492
protected:
492493
TextBase(const ElementType& type, EngravingItem* parent = 0, TextStyleType tid = TextStyleType::DEFAULT,
@@ -507,7 +508,7 @@ class TextBase : public EngravingItem
507508
void drawSelection(muse::draw::Painter*, const RectF&) const;
508509
void insert(TextCursor*, char32_t code, LayoutData* ldata) const;
509510
String genText(const LayoutData* ldata) const;
510-
void genText();
511+
511512
virtual int getPropertyFlagsIdx(Pid id) const override;
512513
String stripText(bool, bool, bool) const;
513514
Sid offsetSid() const;

src/engraving/style/styledef.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,38 @@ const std::array<StyleDef::StyleValue, size_t(Sid::STYLES)> StyleDef::styleValue
13201320
{ Sid::footerFrameFgColor, "footerFrameFgColor", PropertyValue::fromValue(Color::BLACK) },
13211321
{ Sid::footerFrameBgColor, "footerFrameBgColor", PropertyValue::fromValue(Color::transparent) },
13221322

1323+
// New for 4.4 - defaults taken from footer
1324+
{ Sid::copyrightFontFace, "copyrightFontFace", "Edwin" },
1325+
{ Sid::copyrightFontSize, "copyrightFontSize", 9.0 },
1326+
{ Sid::copyrightLineSpacing, "copyrightLineSpacing", 1.0 },
1327+
{ Sid::copyrightFontSpatiumDependent, "copyrightFontSpatiumDependent", false },
1328+
{ Sid::copyrightFontStyle, "copyrightFontStyle", int(FontStyle::Normal) },
1329+
{ Sid::copyrightColor, "copyrightColor", PropertyValue::fromValue(Color::BLACK) },
1330+
{ Sid::copyrightAlign, "copyrightAlign", Align(AlignH::HCENTER, AlignV::BOTTOM) },
1331+
{ Sid::copyrightOffset, "copyrightOffset", PointF(0.0, 0.0) },
1332+
{ Sid::copyrightFrameType, "copyrightFrameType", int(FrameType::NO_FRAME) },
1333+
{ Sid::copyrightFramePadding, "copyrightFramePadding", 0.2 },
1334+
{ Sid::copyrightFrameWidth, "copyrightFrameWidth", 0.1 },
1335+
{ Sid::copyrightFrameRound, "copyrightFrameRound", 0 },
1336+
{ Sid::copyrightFrameFgColor, "copyrightFrameFgColor", PropertyValue::fromValue(Color::BLACK) },
1337+
{ Sid::copyrightFrameBgColor, "copyrightFrameBgColor", PropertyValue::fromValue(Color::transparent) },
1338+
1339+
// New for 4.4 - defaults taken from header
1340+
{ Sid::pageNumberFontFace, "pageNumberFontFace", "Edwin" },
1341+
{ Sid::pageNumberFontSize, "pageNumberFontSize", 11.0 },
1342+
{ Sid::pageNumberLineSpacing, "pageNumberLineSpacing", 1.0 },
1343+
{ Sid::pageNumberFontSpatiumDependent, "pageNumberFontSpatiumDependent", false },
1344+
{ Sid::pageNumberFontStyle, "pageNumberFontStyle", 1 },
1345+
{ Sid::pageNumberColor, "pageNumberColor", PropertyValue::fromValue(Color::BLACK) },
1346+
{ Sid::pageNumberAlign, "pageNumberAlign", Align(AlignH::HCENTER, AlignV::TOP) },
1347+
{ Sid::pageNumberOffset, "pageNumberOffset", PointF() },
1348+
{ Sid::pageNumberFrameType, "pageNumberFrameType", int(FrameType::NO_FRAME) },
1349+
{ Sid::pageNumberFramePadding, "pageNumberFramePadding", 0.2 },
1350+
{ Sid::pageNumberFrameWidth, "pageNumberFrameWidth", 0.1 },
1351+
{ Sid::pageNumberFrameRound, "pageNumberFrameRound", 0 },
1352+
{ Sid::pageNumberFrameFgColor, "pageNumberFrameFgColor", PropertyValue::fromValue(Color::BLACK) },
1353+
{ Sid::pageNumberFrameBgColor, "pageNumberFrameBgColor", PropertyValue::fromValue(Color::transparent) },
1354+
13231355
{ Sid::instrumentChangeFontFace, "instrumentChangeFontFace", "Edwin" },
13241356
{ Sid::instrumentChangeFontSize, "instrumentChangeFontSize", 10.0 },
13251357
{ Sid::instrumentChangeLineSpacing, "instrumentChangeLineSpacing", 1.0 },

src/engraving/style/styledef.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,36 @@ enum class Sid {
13271327
footerFrameFgColor,
13281328
footerFrameBgColor,
13291329

1330+
copyrightFontFace,
1331+
copyrightFontSize,
1332+
copyrightLineSpacing,
1333+
copyrightFontSpatiumDependent,
1334+
copyrightFontStyle,
1335+
copyrightColor,
1336+
copyrightAlign,
1337+
copyrightOffset,
1338+
copyrightFrameType,
1339+
copyrightFramePadding,
1340+
copyrightFrameWidth,
1341+
copyrightFrameRound,
1342+
copyrightFrameFgColor,
1343+
copyrightFrameBgColor,
1344+
1345+
pageNumberFontFace,
1346+
pageNumberFontSize,
1347+
pageNumberLineSpacing,
1348+
pageNumberFontSpatiumDependent,
1349+
pageNumberFontStyle,
1350+
pageNumberColor,
1351+
pageNumberAlign,
1352+
pageNumberOffset,
1353+
pageNumberFrameType,
1354+
pageNumberFramePadding,
1355+
pageNumberFrameWidth,
1356+
pageNumberFrameRound,
1357+
pageNumberFrameFgColor,
1358+
pageNumberFrameBgColor,
1359+
13301360
instrumentChangeFontFace,
13311361
instrumentChangeFontSize,
13321362
instrumentChangeLineSpacing,

0 commit comments

Comments
 (0)