Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7e356ba
Support jianpu: up noteonly with duration line, octave dot and rest
songzhenke Aug 18, 2025
a341a9c
Hanle slur and note dot, enhance duration line, hide clef
songzhenke Sep 26, 2025
0af70ef
Fix duration line when load file by moving duration line to system la…
songzhenke Dec 21, 2025
3c17047
support jianpu in shadow node
songzhenke Dec 30, 2025
67379b9
fix default preset for staff found by unit test in engraving_test
songzhenke Jan 1, 2026
28188d6
Move octave dot from chord to note
songzhenke Jan 20, 2026
8aa7bab
Show chord in vertical jianpu. Support transposing instrument. Fix so…
songzhenke Feb 7, 2026
0a89c4a
Jianpu config and use beam (#2)
songzhenke Mar 13, 2026
1a8e8b0
Fix coderabbital code review comments (#4)
songzhenke Jun 2, 2026
670b7a8
Fix coderabbital code review comments 2 (#6)
songzhenke Jun 3, 2026
715c0fd
Merge branch 'musescore:main' into jianpu
songzhenke Jun 10, 2026
f395751
Merge branch 'main' into jianpu
songzhenke Jun 13, 2026
123bfea
Fix Jianpu grace note: magnitude scaling, octave dot offset, diminuti…
songzhenke Jun 13, 2026
9561cdb
add vtest jianpu-1 (#3)
songzhenke Jun 21, 2026
3ed8d86
Merge branch 'main' into jianpu
songzhenke Jun 21, 2026
ff0de9d
Support beam above/below for shdownote
songzhenke Jun 22, 2026
e49530c
Merge branch 'musescore:main' into jianpu
songzhenke Jun 29, 2026
f5a8a10
Merge branch 'main' into jianpu
songzhenke Jul 9, 2026
8d0b7b6
Merge branch 'musescore:main' into jianpu
songzhenke Jul 25, 2026
490c41c
wqMerge branch 'main' into jianpu
songzhenke Aug 17, 2026
ab40944
cleanup and add unit test
songzhenke Aug 26, 2026
f632f00
Merge branch 'main' into jianpu
songzhenke Aug 26, 2026
d4b75c8
Merge branch 'main' into jianpu
songzhenke Aug 27, 2026
c3a7e31
fix build error after merge from main
songzhenke Aug 27, 2026
a07a32d
Merge branch 'main' into jianpu
songzhenke Oct 20, 2026
0f082d9
Fix build issue after merge from main
songzhenke Oct 20, 2026
ccbf5f5
Add tonic setting for jianpu (#11)
songzhenke Oct 22, 2026
90006a8
jianpu tonic - suppor different number setting on linked staff
songzhenke Oct 23, 2026
a117f17
fix missing diminution duration line for single grace note
songzhenke Oct 24, 2026
75e7eba
fix missing diminution duration line for single note which has custom…
songzhenke Oct 25, 2026
d7cc196
Fixed an issue where the Jianpu font failed to load
songzhenke Oct 25, 2026
87b9146
Preserve Jianpu duration-line styling and default to horizontal beams
songzhenke Oct 28, 2026
af9e0b6
jianpu aligment - bypass mirroring and stem-side offsets
songzhenke Oct 29, 2026
536ca5b
duration lines contribute to the chord’s spacing shape
songzhenke Oct 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/engraving/dom/chord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,8 @@ bool Chord::shouldHaveStem() const
&& !(durationType().type() == DurationType::V_HALF && staffType && staffType->isTabStaff()
&& staffType->minimStyle() == TablatureMinimStyle::NONE)
&& !(measure() && measure()->stemless(staffIdx()))
&& !(staffType && staffType->isTabStaff() && staffType->stemless());
&& !(staffType && staffType->isTabStaff() && staffType->stemless())
&& !(staff && staff->isJianpuStaff(tick()));
}

bool Chord::shouldHaveHook() const
Expand Down
23 changes: 23 additions & 0 deletions src/engraving/dom/chordrest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "breath.h"
#include "chord.h"
#include "clef.h"
#include "durationline.h"
#include "factory.h"
#include "figuredbass.h"
#include "harmony.h"
Expand Down Expand Up @@ -134,6 +135,7 @@ ChordRest::~ChordRest()
{
muse::DeleteAll(m_lyrics);
muse::DeleteAll(m_el);
muse::DeleteAll(m_durationLines);
delete m_tabDur;

if (m_beam) {
Expand Down Expand Up @@ -876,6 +878,9 @@ void ChordRest::processSiblings(std::function<void(EngravingItem*)> func)
for (EngravingItem* e : m_el) {
func(e);
}
for (DurationLine* dl : m_durationLines) {
func(dl);
}
}

//---------------------------------------------------------
Expand Down Expand Up @@ -1099,6 +1104,9 @@ void ChordRest::scanElements(std::function<void(EngravingItem*)> func)
if (m_tabDur) {
func(m_tabDur);
}
for (DurationLine* dl : m_durationLines) {
func(dl);
}
}

//---------------------------------------------------------
Expand Down Expand Up @@ -1366,4 +1374,19 @@ bool ChordRest::hasPrecedingJumpItem() const

return !precedingRepeatMeasures.empty();
}

void ChordRest::resizeDurationLinesTo(size_t newSize)
{
while (m_durationLines.size() < newSize) {
DurationLine* dl = new DurationLine(this);
dl->setOwnershipParent(this);
dl->setTrack(track());
m_durationLines.push_back(dl);
}

while (m_durationLines.size() > newSize) {
delete m_durationLines.back();
m_durationLines.pop_back();
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
}
}
7 changes: 7 additions & 0 deletions src/engraving/dom/chordrest.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum class CrossMeasure : signed char {
class Articulation;
class BeamBase;
class BeamSegment;
class DurationLine;
class Lyrics;
class Measure;
class Score;
Expand Down Expand Up @@ -121,6 +122,10 @@ class ChordRest : public DurationElement

String durationUserName() const;

const std::vector<DurationLine*>& durationLines() const { return m_durationLines; }
std::vector<DurationLine*>& durationLines() { return m_durationLines; }
void resizeDurationLinesTo(size_t newSize);

void setTrack(track_idx_t val) override;

const std::vector<Lyrics*>& lyrics() const { return m_lyrics; }
Expand Down Expand Up @@ -228,5 +233,7 @@ class ChordRest : public DurationElement
TDuration m_durationType;
int m_staffMove = 0; // -1, 0, +1, used for crossbeaming
int m_storedStaffMove = 0; // used to remember and re-apply staff move if needed

std::vector<DurationLine*> m_durationLines;
};
}
4 changes: 4 additions & 0 deletions src/engraving/dom/dom.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ set(DOM_SRC
${CMAKE_CURRENT_LIST_DIR}/dummyparent.h
${CMAKE_CURRENT_LIST_DIR}/durationelement.cpp
${CMAKE_CURRENT_LIST_DIR}/durationelement.h
${CMAKE_CURRENT_LIST_DIR}/durationline.cpp
${CMAKE_CURRENT_LIST_DIR}/durationline.h
${CMAKE_CURRENT_LIST_DIR}/durationtype.cpp
${CMAKE_CURRENT_LIST_DIR}/durationtype.h
${CMAKE_CURRENT_LIST_DIR}/dynamic.cpp
Expand Down Expand Up @@ -209,6 +211,8 @@ set(DOM_SRC
${CMAKE_CURRENT_LIST_DIR}/noteline.cpp
${CMAKE_CURRENT_LIST_DIR}/noteline.h
${CMAKE_CURRENT_LIST_DIR}/notifier.h
${CMAKE_CURRENT_LIST_DIR}/octavedot.cpp
${CMAKE_CURRENT_LIST_DIR}/octavedot.h
${CMAKE_CURRENT_LIST_DIR}/ornament.cpp
${CMAKE_CURRENT_LIST_DIR}/ornament.h
${CMAKE_CURRENT_LIST_DIR}/ottava.cpp
Expand Down
109 changes: 109 additions & 0 deletions src/engraving/dom/durationline.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-Studio-CLA-applies
*
* MuseScore Studio
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include "durationline.h"

#include "chord.h"
#include "measure.h"
#include "rest.h"
#include "staff.h"
#include "system.h"

#include "log.h"

using namespace mu;

namespace mu::engraving {
//---------------------------------------------------------
// DurationLine
//---------------------------------------------------------

DurationLine::DurationLine(DummyParentOr<ChordRest> parent)
: EngravingItem(ElementType::DURATION_LINE, parent)
{
setSelectable(false);
}

//---------------------------------------------------------
// pagePos
//---------------------------------------------------------

PointF DurationLine::pagePos() const
{
if (ChordRest* chordRest = this->chordRest()) {
if (Measure* measure = chordRest->measure()) {
if (System* system = measure->system()) {
if (system->staves().size() > staffIdx()) {
if (SysStaff* staff = system->staff(staffIdx())) {
double yp = y() + staff->y() + system->y();
return PointF(pageX(), yp);
}
}
}
}
}

return EngravingItem::pagePos();
}

//---------------------------------------------------------
// spatiumChanged
//---------------------------------------------------------

void DurationLine::spatiumChanged(double oldValue, double newValue)
{
if (oldValue != 0.0) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this whole function, but for future reference use muse::RealIsNull to check doubles are 0.

m_len = (m_len / oldValue) * newValue;
}
}

//---------------------------------------------------------
// mag
//---------------------------------------------------------

double DurationLine::mag() const
{
auto* parent = ownershipParent();
if (parent && parent->isRest()) {
return toRest(parent)->mag();
}
if (parent && parent->isChord()) {
return toChord(parent)->mag();
}
const Staff* st = staff();
return st ? st->staffMag(this) : 1.0;
}

//---------------------------------------------------------
// chord
//---------------------------------------------------------

ChordRest* DurationLine::chordRest() const
{
auto* parent = ownershipParent();
if (parent && parent->isChordRest()) {
return toChordRest(parent);
} else {
return nullptr;
}
}
}
69 changes: 69 additions & 0 deletions src/engraving/dom/durationline.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-Studio-CLA-applies
*
* MuseScore Studio
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef MU_ENGRAVING_DURATIONLINE_H
#define MU_ENGRAVING_DURATIONLINE_H

#include "engravingitem.h"

namespace mu::engraving {
//---------------------------------------------------------
// @@ DurationLine
/// Graphic representation of a duration line.
//!
//! parent: ChordRest
//! x-origin: Chord
//! y-origin: SStaff
//---------------------------------------------------------

class DurationLine final : public EngravingItem
{
OBJECT_ALLOCATOR(engraving, DurationLine)
DECLARE_CLASSOF(ElementType::DURATION_LINE)

public:
DurationLine(DummyParentOr<ChordRest>);
~DurationLine() override = default;
DurationLine& operator=(const DurationLine&) = delete;

DurationLine* clone() const override { return new DurationLine(*this); }

PointF pagePos() const override; ///< position in page coordinates
ChordRest* chordRest() const;
double mag() const;

double len() const { return m_len; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be moved to LayoutData and spatiumChanged removed.

void setLen(double v) { m_len = v; }

void spatiumChanged(double /*oldValue*/, double /*newValue*/) override;

struct LayoutData : public EngravingItem::LayoutData {
double lineWidth = 0.0;
};
DECLARE_LAYOUTDATA_METHODS(DurationLine);

private:

double m_len = 0.0;
};
} // namespace mu::engraving
#endif
67 changes: 67 additions & 0 deletions src/engraving/dom/durationtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,4 +823,71 @@ bool TDuration::isValid(Fraction f)
t.truncateToFraction(f, 4);
return t.isValid() && (t.fraction() - f).numerator() == 0;
}

//---------------------------------------------------------
// augmentation lines - number of Line to lengthen duration
//
// The undotted duration uses base - 1 lines. Each dot adds half
// the line count represented by the preceding duration value.
//---------------------------------------------------------
int TDuration::augmentationLines() const
{
auto getLinesByDots = [this](int base){
int lines = base - 1;
int dots = this->dots();
while (dots > 0)
{
base /= 2;
lines += base;
dots--;
}
return lines;
};

switch (m_val) {
case DurationType::V_LONG:
return getLinesByDots(16);
case DurationType::V_BREVE:
return getLinesByDots(8);
case DurationType::V_WHOLE:
return getLinesByDots(4);
case DurationType::V_HALF:
return getLinesByDots(2);
default:
return 0;
}
}

//---------------------------------------------------------
// diminution lines - number of Line to halve duration
//---------------------------------------------------------
int TDuration::diminutionLines() const
{
switch (m_val) {
case DurationType::V_LONG:
case DurationType::V_BREVE:
case DurationType::V_WHOLE:
case DurationType::V_HALF:
case DurationType::V_QUARTER:
return 0;
case DurationType::V_EIGHTH:
return 1;
case DurationType::V_16TH:
return 2;
case DurationType::V_32ND:
return 3;
case DurationType::V_64TH:
return 4;
case DurationType::V_128TH:
return 5;
case DurationType::V_256TH:
return 6;
case DurationType::V_512TH:
return 7;
case DurationType::V_1024TH:
return 8;
default:
return 0;
}
}
}
3 changes: 3 additions & 0 deletions src/engraving/dom/durationtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class TDuration
Fraction fraction() const;
static bool isValid(Fraction f);

int augmentationLines() const;
int diminutionLines() const;

private:
void shiftType(int nSteps, bool stepDotted = false);
void truncateToFraction(const Fraction& l, int maxDots);
Expand Down
6 changes: 6 additions & 0 deletions src/engraving/dom/engravingitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,12 @@ bool EngravingItem::onTabStaff() const
return stt ? stt->isTabStaff() : false;
}

bool EngravingItem::isJianpuStaff() const
{
const Staff* st = staff();
return st ? st->isJianpuStaff(tick()) : false;
}

bool EngravingItem::hasGrips() const
{
return gripsCount() > 0;
Expand Down
1 change: 1 addition & 0 deletions src/engraving/dom/engravingitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ class EngravingItem : public EngravingObject
bool hasStaff() const;
const StaffType* staffType() const;
bool onTabStaff() const;
bool isJianpuStaff() const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool isJianpuStaff() const;
bool onJianpuStaff() const;

Part* part() const;
Part* originPart() const; // Delegates to an origin part for items in shared parts

Expand Down
Loading
Loading