summaryrefslogtreecommitdiff
path: root/muse2
diff options
context:
space:
mode:
Diffstat (limited to 'muse2')
-rw-r--r--muse2/muse/app.cpp134
-rw-r--r--muse2/muse/app.h19
-rw-r--r--muse2/muse/arranger/pcanvas.cpp3
-rw-r--r--muse2/muse/cobject.h2
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp4499
-rw-r--r--muse2/muse/midiedit/scoreedit.h811
-rw-r--r--muse2/share/CMakeLists.txt1
-rw-r--r--muse2/share/scoreglyphs/0.pngbin0 -> 379 bytes
-rw-r--r--muse2/share/scoreglyphs/1.pngbin0 -> 353 bytes
-rw-r--r--muse2/share/scoreglyphs/2.pngbin0 -> 435 bytes
-rw-r--r--muse2/share/scoreglyphs/3.pngbin0 -> 446 bytes
-rw-r--r--muse2/share/scoreglyphs/4.pngbin0 -> 416 bytes
-rw-r--r--muse2/share/scoreglyphs/5.pngbin0 -> 431 bytes
-rw-r--r--muse2/share/scoreglyphs/6.pngbin0 -> 412 bytes
-rw-r--r--muse2/share/scoreglyphs/7.pngbin0 -> 412 bytes
-rw-r--r--muse2/share/scoreglyphs/8.pngbin0 -> 453 bytes
-rw-r--r--muse2/share/scoreglyphs/9.pngbin0 -> 453 bytes
-rw-r--r--muse2/share/scoreglyphs/CMakeLists.txt29
-rw-r--r--muse2/share/scoreglyphs/LICENSE364
-rw-r--r--muse2/share/scoreglyphs/acc_b.pngbin0 -> 347 bytes
-rw-r--r--muse2/share/scoreglyphs/acc_none.pngbin0 -> 359 bytes
-rw-r--r--muse2/share/scoreglyphs/acc_sharp.pngbin0 -> 403 bytes
-rw-r--r--muse2/share/scoreglyphs/clef_bass_big.pngbin0 -> 621 bytes
-rw-r--r--muse2/share/scoreglyphs/clef_violin_big.pngbin0 -> 1140 bytes
-rw-r--r--muse2/share/scoreglyphs/dot.pngbin0 -> 218 bytes
-rw-r--r--muse2/share/scoreglyphs/feta-original/CMakeLists.txt27
-rw-r--r--muse2/share/scoreglyphs/feta-original/COPYING-lilypond359
-rw-r--r--muse2/share/scoreglyphs/feta-original/GNUmakefile198
-rw-r--r--muse2/share/scoreglyphs/feta-original/README125
-rw-r--r--muse2/share/scoreglyphs/feta-original/aybabtu.pe.in84
-rw-r--r--muse2/share/scoreglyphs/feta-original/bigcheese.pe.in44
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-accordion.mf445
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet.mf19
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet11.mf6
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet13.mf6
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet14.mf6
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet16.mf6
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet18.mf6
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet20.mf7
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet23.mf7
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-alphabet26.mf6
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-arrow.mf169
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-autometric.mf255
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-banier.mf550
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-beugel.mf147
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-bolletjes.mf1497
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-a.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-b.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-c.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-d.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-e.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-f.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-g.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-h.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-braces-i.mf11
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-din-code.mf791
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-eindelijk.mf593
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-generic.mf57
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-haak.mf92
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-klef.mf698
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-macros.mf497
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-nummer-code.mf899
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-params.mf213
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-pendaal.mf348
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-puntje.mf26
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-schrift.mf1560
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-slag.mf315
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-test-generic.mf20
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-test11.mf15
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-test13.mf16
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-test16.mf16
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-test20.mf16
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-test23.mf16
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-test26.mf15
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-timesig.mf108
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta-toevallig.mf1308
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta11.mf13
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta13.mf13
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta14.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta16.mf13
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta18.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta20.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta23.mf15
-rw-r--r--muse2/share/scoreglyphs/feta-original/feta26.mf15
-rw-r--r--muse2/share/scoreglyphs/feta-original/mf2pt1.mp495
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-accidentals.mf385
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-clefs.mf1693
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-custodes.mf500
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-dots.mf27
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-flags.mf326
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-generic.mf42
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-heads.mf1492
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-macros.mf215
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-rests.mf418
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-scripts.mf231
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan-timesig.mf395
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan11.mf13
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan13.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan14.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan16.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan18.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan20.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan23.mf14
-rw-r--r--muse2/share/scoreglyphs/feta-original/parmesan26.mf14
-rw-r--r--muse2/share/scoreglyphs/flags16d.pngbin0 -> 450 bytes
-rw-r--r--muse2/share/scoreglyphs/flags16u.pngbin0 -> 429 bytes
-rw-r--r--muse2/share/scoreglyphs/flags32d.pngbin0 -> 522 bytes
-rw-r--r--muse2/share/scoreglyphs/flags32u.pngbin0 -> 489 bytes
-rw-r--r--muse2/share/scoreglyphs/flags64d.pngbin0 -> 584 bytes
-rw-r--r--muse2/share/scoreglyphs/flags64u.pngbin0 -> 583 bytes
-rw-r--r--muse2/share/scoreglyphs/flags8d.pngbin0 -> 384 bytes
-rw-r--r--muse2/share/scoreglyphs/flags8u.pngbin0 -> 356 bytes
-rw-r--r--muse2/share/scoreglyphs/half.pngbin0 -> 343 bytes
-rw-r--r--muse2/share/scoreglyphs/quarter.pngbin0 -> 317 bytes
-rw-r--r--muse2/share/scoreglyphs/rest1.pngbin0 -> 198 bytes
-rw-r--r--muse2/share/scoreglyphs/rest16.pngbin0 -> 409 bytes
-rw-r--r--muse2/share/scoreglyphs/rest2.pngbin0 -> 198 bytes
-rw-r--r--muse2/share/scoreglyphs/rest4.pngbin0 -> 431 bytes
-rw-r--r--muse2/share/scoreglyphs/rest8.pngbin0 -> 347 bytes
-rw-r--r--muse2/share/scoreglyphs/whole.pngbin0 -> 400 bytes
120 files changed, 22524 insertions, 1466 deletions
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp
index 8143bb0c..efa6b86d 100644
--- a/muse2/muse/app.cpp
+++ b/muse2/muse/app.cpp
@@ -114,6 +114,20 @@ pthread_t splashThread;
// // pyscript->runPythonScript(script);
// }
+
+void MusE::clearScoreMenuMappers()
+{
+ delete scoreOneStaffPerTrackMapper;
+ delete scoreAllInOneMapper;
+
+ scoreOneStaffPerTrackMapper = new QSignalMapper(this);
+ scoreAllInOneMapper = new QSignalMapper(this);
+
+ connect(scoreOneStaffPerTrackMapper, SIGNAL(mapped(QWidget*)), this, SLOT(openInScoreEdit_oneStaffPerTrack(QWidget*)));
+ connect(scoreAllInOneMapper, SIGNAL(mapped(QWidget*)), this, SLOT(openInScoreEdit_allInOne(QWidget*)));
+}
+
+
//---------------------------------------------------------
// sleep function
//---------------------------------------------------------
@@ -803,6 +817,8 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
editSignalMapper = new QSignalMapper(this);
midiPluginSignalMapper = new QSignalMapper(this);
followSignalMapper = new QSignalMapper(this);
+ scoreOneStaffPerTrackMapper = new QSignalMapper(this);
+ scoreAllInOneMapper = new QSignalMapper(this);
song = new Song("song");
song->blockSignals(true);
@@ -977,7 +993,15 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
editOutsideLoopAction = new QAction(QIcon(*select_outside_loopIcon), tr("&Outside Loop"), this);
editAllPartsAction = new QAction( QIcon(*select_all_parts_on_trackIcon), tr("All &Parts on Track"), this);
- startScoreEditAction = new QAction(*scoreIconSet, tr("Score"), this);
+
+ scoreSubmenu = new QMenu(tr("Score"), this);
+ scoreSubmenu->setIcon(QIcon(*scoreIconSet));
+
+ scoreAllInOneSubsubmenu = new QMenu(tr("all parts in one staff"), this);
+ scoreOneStaffPerTrackSubsubmenu = new QMenu(tr("one staff per part"), this);
+
+ updateScoreMenus();
+
startPianoEditAction = new QAction(*pianoIconSet, tr("Pianoroll"), this);
startDrumEditAction = new QAction(QIcon(*edit_drummsIcon), tr("Drums"), this);
startListEditAction = new QAction(QIcon(*edit_listIcon), tr("List"), this);
@@ -1127,10 +1151,12 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
connect(editSignalMapper, SIGNAL(mapped(int)), this, SLOT(cmd(int)));
connect(startPianoEditAction, SIGNAL(activated()), SLOT(startPianoroll()));
- connect(startScoreEditAction, SIGNAL(activated()), SLOT(startScoreEdit()));
connect(startDrumEditAction, SIGNAL(activated()), SLOT(startDrumEditor()));
connect(startListEditAction, SIGNAL(activated()), SLOT(startListEditor()));
connect(startWaveEditAction, SIGNAL(activated()), SLOT(startWaveEditor()));
+ connect(scoreOneStaffPerTrackMapper, SIGNAL(mapped(QWidget*)), this, SLOT(openInScoreEdit_oneStaffPerTrack(QWidget*)));
+ connect(scoreAllInOneMapper, SIGNAL(mapped(QWidget*)), this, SLOT(openInScoreEdit_allInOne(QWidget*)));
+
connect(masterGraphicAction, SIGNAL(activated()), SLOT(startMasterEditor()));
connect(masterListAction, SIGNAL(activated()), SLOT(startLMasterEditor()));
@@ -1346,7 +1372,9 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
menuEdit->addSeparator();
menuEdit->addAction(startPianoEditAction);
- menuEdit->addAction(startScoreEditAction);
+ menuEdit->addMenu(scoreSubmenu);
+ scoreSubmenu->addMenu(scoreAllInOneSubsubmenu);
+ scoreSubmenu->addMenu(scoreOneStaffPerTrackSubsubmenu);
menuEdit->addAction(startDrumEditAction);
menuEdit->addAction(startListEditAction);
menuEdit->addAction(startWaveEditAction);
@@ -3424,29 +3452,89 @@ PartList* MusE::getMidiPartsToEdit()
return pl;
}
+void MusE::scoreNamingChanged()
+{
+ updateScoreMenus();
+}
+
+void MusE::updateScoreMenus()
+{
+ QAction* action;
+
+
+ scoreOneStaffPerTrackSubsubmenu->clear();
+ scoreAllInOneSubsubmenu->clear();
+
+
+ action=new QAction(tr("New"), this);
+ connect(action, SIGNAL(activated()), scoreOneStaffPerTrackMapper, SLOT(map()));
+ scoreOneStaffPerTrackMapper->setMapping(action, (QWidget*)NULL);
+ scoreOneStaffPerTrackSubsubmenu->addAction(action);
+
+
+ action=new QAction(tr("New"), this); //the above action may NOT be reused!
+ connect(action, SIGNAL(activated()), scoreAllInOneMapper, SLOT(map()));
+ scoreAllInOneMapper->setMapping(action, (QWidget*)NULL);
+ scoreAllInOneSubsubmenu->addAction(action);
+
+ for (ToplevelList::iterator it=toplevels.begin(); it!=toplevels.end(); it++)
+ if (it->type()==Toplevel::SCORE)
+ {
+ ScoreEdit* score = (ScoreEdit*) it->cobject();
+
+ action=new QAction(score->get_name(), this);
+ connect(action, SIGNAL(activated()), scoreOneStaffPerTrackMapper, SLOT(map()));
+ scoreOneStaffPerTrackMapper->setMapping(action, (QWidget*)score);
+ scoreOneStaffPerTrackSubsubmenu->addAction(action);
+
+
+ action=new QAction(score->get_name(), this); //the above action may NOT be reused!
+ connect(action, SIGNAL(activated()), scoreAllInOneMapper, SLOT(map()));
+ scoreAllInOneMapper->setMapping(action, (QWidget*)score);
+ scoreAllInOneSubsubmenu->addAction(action);
+ }
+}
+
//---------------------------------------------------------
// startScoreEdit
//---------------------------------------------------------
-void MusE::startScoreEdit()
- {
- PartList* pl = getMidiPartsToEdit();
- if (pl == 0)
- return;
- startScoreEdit(pl, true);
- }
+void MusE::openInScoreEdit_oneStaffPerTrack(QWidget* dest)
+{
+ openInScoreEdit((ScoreEdit*)dest, false);
+}
-void MusE::startScoreEdit(PartList* pl, bool showDefaultCtrls)
- {
+void MusE::openInScoreEdit_allInOne(QWidget* dest)
+{
+ openInScoreEdit((ScoreEdit*)dest, true);
+}
- ScoreEdit* scoreedit = new ScoreEdit(pl, this, 0, arranger->cursorValue());
- if(showDefaultCtrls) // p4.0.12
- scoreedit->addCtrl();
- scoreedit->show();
- toplevels.push_back(Toplevel(Toplevel::PIANO_ROLL, (unsigned long)(scoreedit), scoreedit));
- connect(scoreedit, SIGNAL(deleted(unsigned long)), SLOT(toplevelDeleted(unsigned long)));
- connect(muse, SIGNAL(configChanged()), scoreedit, SLOT(configChanged()));
- }
+void MusE::openInScoreEdit(ScoreEdit* destination, bool allInOne)
+{
+ PartList* pl = getMidiPartsToEdit();
+ if (pl == 0)
+ return;
+ openInScoreEdit(destination, pl, allInOne);
+}
+
+void MusE::openInScoreEdit(ScoreEdit* destination, PartList* pl, bool allInOne)
+{
+ if (destination==NULL) // if no destination given, create a new one
+ {
+ destination = new ScoreEdit(pl, this, 0, arranger->cursorValue());
+ destination->show();
+ toplevels.push_back(Toplevel(Toplevel::SCORE, (unsigned long)(destination), destination));
+ connect(destination, SIGNAL(deleted(unsigned long)), SLOT(toplevelDeleted(unsigned long)));
+ connect(destination, SIGNAL(name_changed()), SLOT(scoreNamingChanged()));
+ //connect(muse, SIGNAL(configChanged()), destination, SLOT(config_changed()));
+ //commented out by flo, because the ScoreEditor connects to all
+ //relevant signals on his own
+
+ updateScoreMenus();
+ }
+
+ destination->add_parts(pl, allInOne);
+}
//---------------------------------------------------------
// startPianoroll
@@ -3667,6 +3755,7 @@ void MusE::toplevelDeleted(unsigned long tl)
{
for (iToplevel i = toplevels.begin(); i != toplevels.end(); ++i) {
if (i->object() == tl) {
+ bool mustUpdateScoreMenus=false;
switch(i->type()) {
case Toplevel::MARKER:
break;
@@ -3685,8 +3774,12 @@ void MusE::toplevelDeleted(unsigned long tl)
case Toplevel::WAVE:
case Toplevel::LMASTER:
break;
+ case Toplevel::SCORE:
+ mustUpdateScoreMenus=true;
}
toplevels.erase(i);
+ if (mustUpdateScoreMenus)
+ updateScoreMenus();
return;
}
}
@@ -4839,6 +4932,7 @@ again:
case Toplevel::MARKER:
break;
case Toplevel::PIANO_ROLL:
+ case Toplevel::SCORE:
case Toplevel::LISTE:
case Toplevel::DRUM:
case Toplevel::MASTER:
diff --git a/muse2/muse/app.h b/muse2/muse/app.h
index 168602d3..8a9fdac0 100644
--- a/muse2/muse/app.h
+++ b/muse2/muse/app.h
@@ -65,6 +65,7 @@ class Appearance;
class WaveTrack;
class AudioOutput;
class EditInstrument;
+class ScoreEdit;
#define MENU_ADD_SYNTH_ID_BASE 0x1000
@@ -109,7 +110,7 @@ class MusE : public QMainWindow
QAction *editInvertSelectionAction, *editInsideLoopAction, *editOutsideLoopAction, *editAllPartsAction;
QAction *trackMidiAction, *trackDrumAction, *trackWaveAction, *trackAOutputAction, *trackAGroupAction;
QAction *trackAInputAction, *trackAAuxAction;
- QAction *startPianoEditAction, *startDrumEditAction, *startListEditAction, *startWaveEditAction, *startScoreEditAction;
+ QAction *startPianoEditAction, *startDrumEditAction, *startListEditAction, *startWaveEditAction;
QAction *masterGraphicAction, *masterListAction;
QAction *midiTransposeAction;
QAction *midiTransformerAction;
@@ -158,6 +159,7 @@ class MusE : public QMainWindow
QMenu* menu_audio, *menuAutomation;
QMenu* menu_functions, *menuScriptPlugins;
QMenu* select, *master, *midiEdit, *addTrack;
+ QMenu *scoreSubmenu, *scoreOneStaffPerTrackSubsubmenu, *scoreAllInOneSubsubmenu;
// Special 'stay-open' menu for routes.
PopupMenu* routingPopupMenu;
@@ -220,6 +222,8 @@ class MusE : public QMainWindow
QSignalMapper *editSignalMapper;
QSignalMapper *midiPluginSignalMapper;
QSignalMapper *followSignalMapper;
+ QSignalMapper *scoreOneStaffPerTrackMapper;
+ QSignalMapper *scoreAllInOneMapper;
signals:
void configChanged();
@@ -261,8 +265,15 @@ class MusE : public QMainWindow
void startDrumEditor();
void startDrumEditor(PartList* /*pl*/, bool /*showDefaultCtrls*/ = false);
void startEditor(Track*);
- void startScoreEdit();
- void startScoreEdit(PartList* /*pl*/, bool /*showDefaultCtrls*/ = false);
+
+ void openInScoreEdit(ScoreEdit* destination, PartList* pl, bool allInOne=false);
+ void openInScoreEdit(ScoreEdit* destination, bool allInOne=false);
+ void openInScoreEdit_allInOne(QWidget* destination);
+ void openInScoreEdit_oneStaffPerTrack(QWidget* destination);
+ void clearScoreMenuMappers();
+ void updateScoreMenus();
+ void scoreNamingChanged();
+
void startPianoroll();
void startPianoroll(PartList* /*pl*/, bool /*showDefaultCtrls*/ = false);
void startWaveEditor();
@@ -320,7 +331,7 @@ class MusE : public QMainWindow
void execDeliveredScript(int);
void execUserScript(int);
-
+
public slots:
bool saveAs();
void bounceToFile(AudioOutput* ao = 0);
diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp
index e2c2b32d..6068c743 100644
--- a/muse2/muse/arranger/pcanvas.cpp
+++ b/muse2/muse/arranger/pcanvas.cpp
@@ -994,7 +994,8 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt)
// If no items selected, use the one clicked on.
if(!selfound)
item->part()->setColorIndex(curColorIndex);
-
+
+ song->update(SC_PART_MODIFIED);
redraw();
break;
}
diff --git a/muse2/muse/cobject.h b/muse2/muse/cobject.h
index 8e21eaf0..9a80b2b1 100644
--- a/muse2/muse/cobject.h
+++ b/muse2/muse/cobject.h
@@ -38,7 +38,7 @@ class TopWin : public QMainWindow
class Toplevel {
public:
enum ToplevelType { PIANO_ROLL, LISTE, DRUM, MASTER, WAVE,
- LMASTER, CLIPLIST, MARKER
+ LMASTER, CLIPLIST, MARKER, SCORE
#ifdef PATCHBAY
, M_PATCHBAY
#endif /* PATCHBAY */
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index f236a0d5..e904ce46 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -1,13 +1,15 @@
//=========================================================
// MusE
// Linux Music Editor
-// $Id: ScoreEdit.cpp,v 1.25.2.15 2009/11/16 11:29:33 lunar_shuttle Exp $
-// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+// scoreedit.cpp
+// (C) Copyright 2011 Florian Jung (florian.a.jung@web.de)
//=========================================================
+
#include <QLayout>
#include <QSizeGrip>
#include <QLabel>
+#include <QScrollBar>
#include <QPushButton>
#include <QToolButton>
#include <QToolTip>
@@ -18,6 +20,7 @@
#include <QClipboard>
#include <QDir>
#include <QAction>
+#include <QActionGroup>
#include <QKeySequence>
#include <QKeyEvent>
#include <QGridLayout>
@@ -26,9 +29,18 @@
#include <QMimeData>
#include <QScrollArea>
#include <QSettings>
+#include <QImage>
+#include <QInputDialog>
+#include <QMessageBox>
#include <stdio.h>
+#include <math.h>
+
+#include <iostream>
+#include <sstream>
+using namespace std;
+#include "app.h"
#include "xml.h"
#include "mtscale.h"
#include "prcanvas.h"
@@ -51,1361 +63,3314 @@
#include "mtrackinfo.h"
-int ScoreEdit::_quantInit = 96;
-int ScoreEdit::_rasterInit = 96;
-int ScoreEdit::_widthInit = 600;
-int ScoreEdit::_heightInit = 400;
-int ScoreEdit::_quantStrengthInit = 80; // 1 - 100%
-int ScoreEdit::_quantLimitInit = 50; // tick value
-bool ScoreEdit::_quantLenInit = false;
-int ScoreEdit::_toInit = 0;
-int ScoreEdit::colorModeInit = 0;
+#include "sig.h"
+
+
+string IntToStr(int i);
+QString IntToQStr(int i);
+
+
+#define SPLIT_NOTE 60
+//TODO: let the user specify that somehow?
+
+
+
+
+
+//PIXELS_PER_NOTEPOS must be greater or equal to 3*NOTE_XLEN + 2*NOTE_SHIFT
+//because if tick 0 is at x=0: the notes can be shifted by NOTE_SHIFT.
+//additionally, they can be moved by NOTE_XLEN (collision avoiding)
+//then, they have their own width, which is NOTE_XLEN/2 into the x>0-area
+//the same thing applies to the x<0-area
+
+// OOO
+// |
+// ^actual calculated x, without shifting or moving
+// ^ and
+// ^ : moved note (by XLEN)
+// additionally, a shift is possible
+// total_width = shift + move + note_xlen + move + shift, where move==note_xlen
+// total_width = 2*shift + 3*note_xlen
+// if total_width is greater than px_per_notepos, there will be collisions!
+
+
+
+
+
+//do NOT put parentheses around this!
+#define PAGESTEP 3/4
+
+
+#define SCROLL_MARGIN 10
+#define SCROLL_SPEED 5
+//SCROLL_SPEED is in (scroll_pixels per second) per mouse-move-pixel
+#define SCROLL_SPEED_MAX 500
+//SCROLL_SPEED_MAX is in scroll_pixels_per_second
+
+
+
+#define STAFF_DISTANCE (10*YLEN)
+#define GRANDSTAFF_DISTANCE (8*YLEN)
+
+QString create_random_string(int len=8)
+{
+ string result;
+
+ for (int i=0;i<len;i++)
+ result+=char((rand() % 26) + 'A');
+
+ return QString(result.c_str());
+}
+
+
+
+
+
-static const int xscale = -10;
-static const int yscale = 1;
-static const int pianoWidth = 40;
-static int ScoreEditTools = PointerTool | PencilTool | RubberTool | DrawTool;
+QPixmap *pix_whole, *pix_half, *pix_quarter; // arrays [NUM_PARTCOLORS+2]
+QPixmap *pix_dot, *pix_b, *pix_sharp, *pix_noacc; // arrays [NUM_PARTCOLORS+2]
+QPixmap *pix_r1, *pix_r2, *pix_r4, *pix_r8, *pix_r16; // pointers
+QPixmap *pix_flag_up, *pix_flag_down; // arrays [4]
+QPixmap *pix_num; // array [10]
+QPixmap *pix_clef_violin, *pix_clef_bass; //pointers
+bool pixmaps_loaded=false;
+
+
+
+
+int ScoreEdit::serial=1;
+set<QString> ScoreEdit::names;
+
//---------------------------------------------------------
// ScoreEdit
//---------------------------------------------------------
ScoreEdit::ScoreEdit(PartList* pl, QWidget* parent, const char* name, unsigned initPos)
- : MidiEditor(_quantInit, _rasterInit, pl, parent, name)
- {
- deltaMode = false;
- resize(_widthInit, _heightInit);
- selPart = 0;
- quantConfig = 0;
- _playEvents = false;
- _quantStrength = _quantStrengthInit;
- _quantLimit = _quantLimitInit;
- _quantLen = _quantLenInit;
- _to = _toInit;
- colorMode = colorModeInit;
-
- QSignalMapper* mapper = new QSignalMapper(this);
- QSignalMapper* colorMapper = new QSignalMapper(this);
-
- //---------Menu----------------------------------
-
- menuEdit = menuBar()->addMenu(tr("&Edit"));
-
- menuEdit->addActions(undoRedo->actions());
-
- menuEdit->addSeparator();
-
- editCutAction = menuEdit->addAction(QIcon(*editcutIconSet), tr("C&ut"));
- mapper->setMapping(editCutAction, PianoCanvas::CMD_CUT);
- connect(editCutAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- editCopyAction = menuEdit->addAction(QIcon(*editcopyIconSet), tr("&Copy"));
- mapper->setMapping(editCopyAction, PianoCanvas::CMD_COPY);
- connect(editCopyAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- editPasteAction = menuEdit->addAction(QIcon(*editpasteIconSet), tr("&Paste"));
- mapper->setMapping(editPasteAction, PianoCanvas::CMD_PASTE);
- connect(editPasteAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- menuEdit->addSeparator();
-
- editDelEventsAction = menuEdit->addAction(tr("Delete &Events"));
- mapper->setMapping(editDelEventsAction, PianoCanvas::CMD_DEL);
- connect(editDelEventsAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- menuEdit->addSeparator();
-
- menuSelect = menuEdit->addMenu(QIcon(*selectIcon), tr("&Select"));
-
- selectAllAction = menuSelect->addAction(QIcon(*select_allIcon), tr("Select &All"));
- mapper->setMapping(selectAllAction, PianoCanvas::CMD_SELECT_ALL);
- connect(selectAllAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- selectNoneAction = menuSelect->addAction(QIcon(*select_deselect_allIcon), tr("&Deselect All"));
- mapper->setMapping(selectNoneAction, PianoCanvas::CMD_SELECT_NONE);
- connect(selectNoneAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- selectInvertAction = menuSelect->addAction(QIcon(*select_invert_selectionIcon), tr("Invert &Selection"));
- mapper->setMapping(selectInvertAction, PianoCanvas::CMD_SELECT_INVERT);
- connect(selectInvertAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- menuSelect->addSeparator();
-
- selectInsideLoopAction = menuSelect->addAction(QIcon(*select_inside_loopIcon), tr("&Inside Loop"));
- mapper->setMapping(selectInsideLoopAction, PianoCanvas::CMD_SELECT_ILOOP);
- connect(selectInsideLoopAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- selectOutsideLoopAction = menuSelect->addAction(QIcon(*select_outside_loopIcon), tr("&Outside Loop"));
- mapper->setMapping(selectOutsideLoopAction, PianoCanvas::CMD_SELECT_OLOOP);
- connect(selectOutsideLoopAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- menuSelect->addSeparator();
-
- //selectPrevPartAction = select->addAction(tr("&Previous Part"));
- selectPrevPartAction = menuSelect->addAction(QIcon(*select_all_parts_on_trackIcon), tr("&Previous Part"));
- mapper->setMapping(selectPrevPartAction, PianoCanvas::CMD_SELECT_PREV_PART);
- connect(selectPrevPartAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- //selNextPartAction = select->addAction(tr("&Next Part"));
- selectNextPartAction = menuSelect->addAction(QIcon(*select_all_parts_on_trackIcon), tr("&Next Part"));
- mapper->setMapping(selectNextPartAction, PianoCanvas::CMD_SELECT_NEXT_PART);
- connect(selectNextPartAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- menuConfig = menuBar()->addMenu(tr("&Config"));
-
- eventColor = menuConfig->addMenu(tr("&Event Color"));
-
- QActionGroup* actgrp = new QActionGroup(this);
- actgrp->setExclusive(true);
-
- //evColorBlueAction = eventColor->addAction(tr("&Blue"));
- evColorBlueAction = actgrp->addAction(tr("&Blue"));
- evColorBlueAction->setCheckable(true);
- colorMapper->setMapping(evColorBlueAction, 0);
-
- //evColorPitchAction = eventColor->addAction(tr("&Pitch colors"));
- evColorPitchAction = actgrp->addAction(tr("&Pitch colors"));
- evColorPitchAction->setCheckable(true);
- colorMapper->setMapping(evColorPitchAction, 1);
-
- //evColorVelAction = eventColor->addAction(tr("&Velocity colors"));
- evColorVelAction = actgrp->addAction(tr("&Velocity colors"));
- evColorVelAction->setCheckable(true);
- colorMapper->setMapping(evColorVelAction, 2);
-
- connect(evColorBlueAction, SIGNAL(triggered()), colorMapper, SLOT(map()));
- connect(evColorPitchAction, SIGNAL(triggered()), colorMapper, SLOT(map()));
- connect(evColorVelAction, SIGNAL(triggered()), colorMapper, SLOT(map()));
-
- eventColor->addActions(actgrp->actions());
-
- connect(colorMapper, SIGNAL(mapped(int)), this, SLOT(eventColorModeChanged(int)));
-
- menuFunctions = menuBar()->addMenu(tr("&Functions"));
-
- menuFunctions->setTearOffEnabled(true);
-
- funcOverQuantAction = menuFunctions->addAction(tr("Over Quantize"));
- mapper->setMapping(funcOverQuantAction, PianoCanvas::CMD_OVER_QUANTIZE);
- connect(funcOverQuantAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcNoteOnQuantAction = menuFunctions->addAction(tr("Note On Quantize"));
- mapper->setMapping(funcNoteOnQuantAction, PianoCanvas::CMD_ON_QUANTIZE);
- connect(funcNoteOnQuantAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcNoteOnOffQuantAction = menuFunctions->addAction(tr("Note On/Off Quantize"));
- mapper->setMapping(funcNoteOnOffQuantAction, PianoCanvas::CMD_ONOFF_QUANTIZE);
- connect(funcNoteOnOffQuantAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcIterQuantAction = menuFunctions->addAction(tr("Iterative Quantize"));
- mapper->setMapping(funcIterQuantAction, PianoCanvas::CMD_ITERATIVE_QUANTIZE);
- connect(funcIterQuantAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- menuFunctions->addSeparator();
-
- funcConfigQuantAction = menuFunctions->addAction(tr("Config Quant..."));
- connect(funcConfigQuantAction, SIGNAL(triggered()), this, SLOT(configQuant()));
-
- menuFunctions->addSeparator();
-
- funcGateTimeAction = menuFunctions->addAction(tr("Modify Gate Time"));
- mapper->setMapping(funcGateTimeAction, PianoCanvas::CMD_MODIFY_GATE_TIME);
- connect(funcGateTimeAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcModVelAction = menuFunctions->addAction(tr("Modify Velocity"));
- mapper->setMapping(funcModVelAction, PianoCanvas::CMD_MODIFY_VELOCITY);
- connect(funcModVelAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcCrescendoAction = menuFunctions->addAction(tr("Crescendo"));
- mapper->setMapping(funcCrescendoAction, PianoCanvas::CMD_CRESCENDO);
- funcCrescendoAction->setEnabled(false);
- connect(funcCrescendoAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcTransposeAction = menuFunctions->addAction(tr("Transpose"));
- mapper->setMapping(funcTransposeAction, PianoCanvas::CMD_TRANSPOSE);
- funcTransposeAction->setEnabled(false);
- connect(funcTransposeAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcThinOutAction = menuFunctions->addAction(tr("Thin Out"));
- mapper->setMapping(funcThinOutAction, PianoCanvas::CMD_THIN_OUT);
- funcThinOutAction->setEnabled(false);
- connect(funcThinOutAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcEraseEventAction = menuFunctions->addAction(tr("Erase Event"));
- mapper->setMapping(funcEraseEventAction, PianoCanvas::CMD_ERASE_EVENT);
- funcEraseEventAction->setEnabled(false);
- connect(funcEraseEventAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcNoteShiftAction = menuFunctions->addAction(tr("Note Shift"));
- mapper->setMapping(funcNoteShiftAction, PianoCanvas::CMD_NOTE_SHIFT);
- funcNoteShiftAction->setEnabled(false);
- connect(funcNoteShiftAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcMoveClockAction = menuFunctions->addAction(tr("Move Clock"));
- mapper->setMapping(funcMoveClockAction, PianoCanvas::CMD_MOVE_CLOCK);
- funcMoveClockAction->setEnabled(false);
- connect(funcMoveClockAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcCopyMeasureAction = menuFunctions->addAction(tr("Copy Measure"));
- mapper->setMapping(funcCopyMeasureAction, PianoCanvas::CMD_COPY_MEASURE);
- funcCopyMeasureAction->setEnabled(false);
- connect(funcCopyMeasureAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcEraseMeasureAction = menuFunctions->addAction(tr("Erase Measure"));
- mapper->setMapping(funcEraseMeasureAction, PianoCanvas::CMD_ERASE_MEASURE);
- funcEraseMeasureAction->setEnabled(false);
- connect(funcEraseMeasureAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcDelMeasureAction = menuFunctions->addAction(tr("Delete Measure"));
- mapper->setMapping(funcDelMeasureAction, PianoCanvas::CMD_DELETE_MEASURE);
- funcDelMeasureAction->setEnabled(false);
- connect(funcDelMeasureAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcCreateMeasureAction = menuFunctions->addAction(tr("Create Measure"));
- mapper->setMapping(funcCreateMeasureAction, PianoCanvas::CMD_CREATE_MEASURE);
- funcCreateMeasureAction->setEnabled(false);
- connect(funcCreateMeasureAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcSetFixedLenAction = menuFunctions->addAction(tr("Set Fixed Length"));
- mapper->setMapping(funcSetFixedLenAction, PianoCanvas::CMD_FIXED_LEN);
- connect(funcSetFixedLenAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- funcDelOverlapsAction = menuFunctions->addAction(tr("Delete Overlaps"));
- mapper->setMapping(funcDelOverlapsAction, PianoCanvas::CMD_DELETE_OVERLAPS);
- connect(funcDelOverlapsAction, SIGNAL(triggered()), mapper, SLOT(map()));
-
- menuPlugins = menuBar()->addMenu(tr("&Plugins"));
- song->populateScriptMenu(menuPlugins, this);
-
- connect(mapper, SIGNAL(mapped(int)), this, SLOT(cmd(int)));
-
- //---------ToolBar----------------------------------
- tools = addToolBar(tr("ScoreEdit tools"));
- tools->setObjectName("ScoreEdit tools");
- tools->addActions(undoRedo->actions());
- tools->addSeparator();
-
- srec = new QToolButton();
- srec->setToolTip(tr("Step Record"));
- srec->setIcon(*steprecIcon);
- srec->setCheckable(true);
- tools->addWidget(srec);
-
- midiin = new QToolButton();
- midiin->setToolTip(tr("Midi Input"));
- midiin->setIcon(*midiinIcon);
- midiin->setCheckable(true);
- tools->addWidget(midiin);
-
- speaker = new QToolButton();
- speaker->setToolTip(tr("Play Events"));
- speaker->setIcon(*speakerIcon);
- speaker->setCheckable(true);
- tools->addWidget(speaker);
-
- tools2 = new EditToolBar(this, ScoreEditTools);
- addToolBar(tools2);
-
- QToolBar* panicToolbar = addToolBar(tr("panic"));
- panicToolbar->setObjectName("panic");
- panicToolbar->addAction(panicAction);
-
- //-------------------------------------------------------------
- // Transport Bar
- QToolBar* transport = addToolBar(tr("transport"));
- transport->setObjectName("transport");
- transport->addActions(transportAction->actions());
-
- addToolBarBreak();
- toolbar = new Toolbar1(this, _rasterInit, _quantInit);
- addToolBar(toolbar);
-
- addToolBarBreak();
- info = new NoteInfo(this);
- addToolBar(info);
-
- //---------------------------------------------------
- // split
- //---------------------------------------------------
-
- splitter = new Splitter(Qt::Vertical, mainw, "splitter");
- splitter->setHandleWidth(2);
-
- hsplitter = new Splitter(Qt::Horizontal, mainw, "hsplitter");
- hsplitter->setChildrenCollapsible(true);
- hsplitter->setHandleWidth(2);
-
- QPushButton* ctrl = new QPushButton(tr("ctrl"), mainw);
- //QPushButton* ctrl = new QPushButton(tr("C"), mainw); // Tim.
- ctrl->setObjectName("Ctrl");
- ctrl->setFont(config.fonts[3]);
- ctrl->setToolTip(tr("Add Controller View"));
- hscroll = new ScrollScale(-25, -2, xscale, 20000, Qt::Horizontal, mainw);
- ctrl->setFixedSize(pianoWidth, hscroll->sizeHint().height());
- //ctrl->setFixedSize(pianoWidth / 2, hscroll->sizeHint().height()); // Tim.
-
- // Tim.
- /*
- QPushButton* trackInfoButton = new QPushButton(tr("T"), mainw);
- trackInfoButton->setObjectName("TrackInfo");
- trackInfoButton->setFont(config.fonts[3]);
- trackInfoButton->setToolTip(tr("Show track info"));
- trackInfoButton->setFixedSize(pianoWidth / 2, hscroll->sizeHint().height());
- */
-
- QSizeGrip* corner = new QSizeGrip(mainw);
-
- midiTrackInfo = new MidiTrackInfo(mainw);
- int mtiw = midiTrackInfo->width(); // Save this.
- midiTrackInfo->setMinimumWidth(100);
- //midiTrackInfo->setMaximumWidth(150);
-
- midiTrackInfo->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding));
- infoScroll = new QScrollArea;
- infoScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- infoScroll->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- infoScroll->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding));
- infoScroll->setWidget(midiTrackInfo);
- infoScroll->setWidgetResizable(true);
- //infoScroll->setVisible(false);
- //infoScroll->setEnabled(false);
-
- //hsplitter->addWidget(midiTrackInfo);
- hsplitter->addWidget(infoScroll); // Tim.
- hsplitter->addWidget(splitter);
-
- mainGrid->setRowStretch(0, 100);
- mainGrid->setColumnStretch(1, 100);
- mainGrid->addWidget(hsplitter, 0, 1, 1, 3);
-
- // Original.
- /*
- mainGrid->setColumnStretch(1, 100);
- mainGrid->addWidget(splitter, 0, 0, 1, 3);
- mainGrid->addWidget(ctrl, 1, 0);
- mainGrid->addWidget(hscroll, 1, 1);
- mainGrid->addWidget(corner, 1, 2, Qt::AlignBottom|Qt::AlignRight);
- */
-
-
- // Tim.
- /*
- mainGrid->setColumnStretch(2, 100);
- mainGrid->addWidget(splitter, 0, 0, 1, 4);
- mainGrid->addWidget(trackInfoButton, 1, 0);
- mainGrid->addWidget(ctrl, 1, 1);
- mainGrid->addWidget(hscroll, 1, 2);
- mainGrid->addWidget(corner, 1, 3, Qt::AlignBottom|Qt::AlignRight);
- */
-
- //mainGrid->addRowSpacing(1, hscroll->sizeHint().height());
- //mainGrid->addItem(new QSpacerItem(0, hscroll->sizeHint().height()), 1, 0); // Orig + Tim.
-
- QWidget* split1 = new QWidget(splitter);
- split1->setObjectName("split1");
- QGridLayout* gridS1 = new QGridLayout(split1);
- gridS1->setContentsMargins(0, 0, 0, 0);
- gridS1->setSpacing(0);
- //Defined and configure your program change bar here.
- //This may well be a copy of MTScale extended for our needs
- time = new MTScale(&_raster, split1, xscale);
- Piano* piano = new Piano(split1, yscale);
- canvas = new PianoCanvas(this, split1, xscale, yscale);
- vscroll = new ScrollScale(-3, 7, yscale, KH * 75, Qt::Vertical, split1);
-
- //setFocusProxy(canvas); // Tim.
-
- int offset = -(config.division/4);
- canvas->setOrigin(offset, 0);
- canvas->setCanvasTools(ScoreEditTools);
- canvas->setFocus();
- connect(canvas, SIGNAL(toolChanged(int)), tools2, SLOT(set(int)));
- time->setOrigin(offset, 0);
-
- gridS1->setRowStretch(2, 100);
- gridS1->setColumnStretch(1, 100);
- //gridS1->setColumnStretch(2, 100); // Tim.
-
- gridS1->addWidget(time, 0, 1, 1, 2);
- gridS1->addWidget(hLine(split1), 1, 0, 1, 3);
- gridS1->addWidget(piano, 2, 0);
- gridS1->addWidget(canvas, 2, 1);
- gridS1->addWidget(vscroll, 2, 2);
-
- // Tim.
- /*
- gridS1->addWidget(time, 0, 2, 1, 3);
- gridS1->addWidget(hLine(split1), 1, 1, 1, 4);
- //gridS1->addWidget(infoScroll, 2, 0);
- gridS1->addWidget(infoScroll, 0, 0, 3, 1);
- gridS1->addWidget(piano, 2, 1);
- gridS1->addWidget(canvas, 2, 2);
- gridS1->addWidget(vscroll, 2, 3);
- */
-
- ctrlLane = new Splitter(Qt::Vertical, splitter, "ctrllane");
- QWidget* split2 = new QWidget(splitter);
- split2->setMaximumHeight(hscroll->sizeHint().height());
- split2->setMinimumHeight(hscroll->sizeHint().height());
- QGridLayout* gridS2 = new QGridLayout(split2);
- gridS2->setContentsMargins(0, 0, 0, 0);
- gridS2->setSpacing(0);
- gridS2->setRowStretch(0, 100);
- gridS2->setColumnStretch(1, 100);
- gridS2->addWidget(ctrl, 0, 0);
- gridS2->addWidget(hscroll, 0, 1);
- gridS2->addWidget(corner, 0, 2, Qt::AlignBottom|Qt::AlignRight);
- //splitter->setCollapsible(0, true);
-
- piano->setFixedWidth(pianoWidth);
-
- // Tim.
- QList<int> mops;
- mops.append(mtiw + 30); // 30 for possible scrollbar
- mops.append(width() - mtiw - 30);
- hsplitter->setSizes(mops);
-
- connect(tools2, SIGNAL(toolChanged(int)), canvas, SLOT(setTool(int)));
-
- connect(ctrl, SIGNAL(clicked()), SLOT(addCtrl()));
- //connect(trackInfoButton, SIGNAL(clicked()), SLOT(toggleTrackInfo())); Tim.
- connect(info, SIGNAL(valueChanged(NoteInfo::ValType, int)), SLOT(noteinfoChanged(NoteInfo::ValType, int)));
- connect(vscroll, SIGNAL(scrollChanged(int)), piano, SLOT(setYPos(int)));
- connect(vscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setYPos(int)));
- connect(vscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setYMag(int)));
- connect(vscroll, SIGNAL(scaleChanged(int)), piano, SLOT(setYMag(int)));
-
- connect(hscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setXPos(int)));
- connect(hscroll, SIGNAL(scrollChanged(int)), time, SLOT(setXPos(int)));
-
- connect(hscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setXMag(int)));
- connect(hscroll, SIGNAL(scaleChanged(int)), time, SLOT(setXMag(int)));
-
- connect(canvas, SIGNAL(newWidth(int)), SLOT(newCanvasWidth(int)));
- connect(canvas, SIGNAL(pitchChanged(int)), piano, SLOT(setPitch(int)));
- connect(canvas, SIGNAL(verticalScroll(unsigned)), vscroll, SLOT(setPos(unsigned)));
- connect(canvas, SIGNAL(horizontalScroll(unsigned)),hscroll, SLOT(setPos(unsigned)));
- connect(canvas, SIGNAL(horizontalScrollNoLimit(unsigned)),hscroll, SLOT(setPosNoLimit(unsigned)));
- connect(canvas, SIGNAL(selectionChanged(int, Event&, Part*)), this,
- SLOT(setSelection(int, Event&, Part*)));
-
- connect(piano, SIGNAL(keyPressed(int, int, bool)), canvas, SLOT(pianoPressed(int, int, bool)));
- connect(piano, SIGNAL(keyReleased(int, bool)), canvas, SLOT(pianoReleased(int, bool)));
- connect(srec, SIGNAL(toggled(bool)), SLOT(setSteprec(bool)));
- connect(midiin, SIGNAL(toggled(bool)), canvas, SLOT(setMidiin(bool)));
- connect(speaker, SIGNAL(toggled(bool)), SLOT(setSpeaker(bool)));
- connect(canvas, SIGNAL(followEvent(int)), SLOT(follow(int)));
-
- connect(hscroll, SIGNAL(scaleChanged(int)), SLOT(updateHScrollRange()));
- piano->setYPos(KH * 30);
- canvas->setYPos(KH * 30);
- vscroll->setPos(KH * 30);
- //setSelection(0, 0, 0); //Really necessary? Causes segfault when only 1 item selected, replaced by the following:
- info->setEnabled(false);
-
- connect(song, SIGNAL(songChanged(int)), SLOT(songChanged1(int)));
-
- setWindowTitle(canvas->getCaption());
-
- updateHScrollRange();
- // connect to toolbar
- connect(canvas, SIGNAL(pitchChanged(int)), toolbar, SLOT(setPitch(int)));
- connect(canvas, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
- connect(piano, SIGNAL(pitchChanged(int)), toolbar, SLOT(setPitch(int)));
- connect(time, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
- connect(toolbar, SIGNAL(quantChanged(int)), SLOT(setQuant(int)));
- connect(toolbar, SIGNAL(rasterChanged(int)),SLOT(setRaster(int)));
- connect(toolbar, SIGNAL(toChanged(int)), SLOT(setTo(int)));
- connect(toolbar, SIGNAL(soloChanged(bool)), SLOT(soloChanged(bool)));
-
- setFocusPolicy(Qt::StrongFocus);
- setEventColorMode(colorMode);
-
- QClipboard* cb = QApplication::clipboard();
- connect(cb, SIGNAL(dataChanged()), SLOT(clipboardChanged()));
-
- clipboardChanged(); // enable/disable "Paste"
- selectionChanged(); // enable/disable "Copy" & "Paste"
- initShortcuts(); // initialize shortcuts
-
- const Pos cpos=song->cPos();
- canvas->setPos(0, cpos.tick(), true);
- canvas->selectAtTick(cpos.tick());
- //canvas->selectFirst();//
-
- unsigned pos=0;
- if(initPos >= MAXINT)
- pos = song->cpos();
- if(pos > MAXINT)
- pos = MAXINT;
- if (pos)
- hscroll->setOffset((int)pos);
-
- if(canvas->track())
- {
- updateTrackInfo();
- toolbar->setSolo(canvas->track()->solo());
- }
-
- QSettings settings("MusE", "MusE-qt");
- //restoreGeometry(settings.value("ScoreEdit/geometry").toByteArray());
- restoreState(settings.value("ScoreEdit/windowState").toByteArray());
-
- }
+ : MidiEditor(0, 0, pl, parent, name)
+{
+ score_canvas=new ScoreCanvas(this, mainw, 1, 1);
+ xscroll = new QScrollBar(Qt::Horizontal, mainw);
+ yscroll = new QScrollBar(Qt::Vertical, mainw);
+
+ connect(xscroll, SIGNAL(valueChanged(int)), score_canvas, SLOT(x_scroll_event(int)));
+ connect(score_canvas, SIGNAL(xscroll_changed(int)), xscroll, SLOT(setValue(int)));
+
+ connect(yscroll, SIGNAL(valueChanged(int)), score_canvas, SLOT(y_scroll_event(int)));
+ connect(score_canvas, SIGNAL(yscroll_changed(int)), yscroll, SLOT(setValue(int)));
+
+ connect(score_canvas, SIGNAL(canvas_width_changed(int)), SLOT(canvas_width_changed(int)));
+ connect(score_canvas, SIGNAL(viewport_width_changed(int)), SLOT(viewport_width_changed(int)));
+ connect(score_canvas, SIGNAL(canvas_height_changed(int)), SLOT(canvas_height_changed(int)));
+ connect(score_canvas, SIGNAL(viewport_height_changed(int)), SLOT(viewport_height_changed(int)));
+
+ connect(song, SIGNAL(songChanged(int)), score_canvas, SLOT(song_changed(int)));
+
+ mainGrid->addWidget(score_canvas, 0, 0);
+ mainGrid->addWidget(xscroll,1,0);
+ mainGrid->addWidget(yscroll,0,1);
+
+ xscroll->setMinimum(0);
+ yscroll->setMinimum(0);
+
+ menu_mapper=new QSignalMapper(this);
+ connect(menu_mapper, SIGNAL(mapped(int)), SLOT(menu_command(int)));
+
+
+
+ // Toolbars ---------------------------------------------------------
+ QToolBar* undo_tools=addToolBar(tr("Undo/Redo tools"));
+ undo_tools->setObjectName("Undo/Redo tools");
+ undo_tools->addActions(undoRedo->actions());
+ addToolBar(undo_tools);
+
+ EditToolBar* edit_tools = new EditToolBar(this, PointerTool | PencilTool | RubberTool);
+ addToolBar(edit_tools);
+ edit_tools->set(PointerTool);
+ score_canvas->set_tool(PointerTool);
+ connect(edit_tools, SIGNAL(toolChanged(int)), score_canvas, SLOT(set_tool(int)));
+
+ QToolBar* panic_toolbar = addToolBar(tr("panic"));
+ panic_toolbar->setObjectName("panic");
+ panic_toolbar->addAction(panicAction);
+
+ QToolBar* transport_toolbar = addToolBar(tr("transport"));
+ transport_toolbar->setObjectName("transport");
+ transport_toolbar->addActions(transportAction->actions());
+
+ QToolBar* quant_len_toolbar = addToolBar(tr("Quant'n'length"));
+ quant_len_toolbar->setObjectName("Quant'n'length");
+ quant_len_toolbar->addWidget(new QLabel(tr("Note length:"), quant_len_toolbar));
+ QActionGroup* len_actions=new QActionGroup(this);
+ QAction* n1_action = quant_len_toolbar->addAction("1", menu_mapper, SLOT(map()));
+ QAction* n2_action = quant_len_toolbar->addAction("2", menu_mapper, SLOT(map()));
+ QAction* n4_action = quant_len_toolbar->addAction("4", menu_mapper, SLOT(map()));
+ QAction* n8_action = quant_len_toolbar->addAction("8", menu_mapper, SLOT(map()));
+ QAction* n16_action = quant_len_toolbar->addAction("16", menu_mapper, SLOT(map()));
+ QAction* n32_action = quant_len_toolbar->addAction("32", menu_mapper, SLOT(map()));
+ QAction* nlast_action = quant_len_toolbar->addAction(tr("last"), menu_mapper, SLOT(map()));
+ menu_mapper->setMapping(n1_action, CMD_NOTELEN_1);
+ menu_mapper->setMapping(n2_action, CMD_NOTELEN_2);
+ menu_mapper->setMapping(n4_action, CMD_NOTELEN_4);
+ menu_mapper->setMapping(n8_action, CMD_NOTELEN_8);
+ menu_mapper->setMapping(n16_action, CMD_NOTELEN_16);
+ menu_mapper->setMapping(n32_action, CMD_NOTELEN_32);
+ menu_mapper->setMapping(nlast_action, CMD_NOTELEN_LAST);
+ n1_action->setCheckable(true);
+ n2_action->setCheckable(true);
+ n4_action->setCheckable(true);
+ n8_action->setCheckable(true);
+ n16_action->setCheckable(true);
+ n32_action->setCheckable(true);
+ nlast_action->setCheckable(true);
+ len_actions->addAction(n1_action);
+ len_actions->addAction(n2_action);
+ len_actions->addAction(n4_action);
+ len_actions->addAction(n8_action);
+ len_actions->addAction(n16_action);
+ len_actions->addAction(n32_action);
+ len_actions->addAction(nlast_action);
+
+ nlast_action->setChecked(true);
+ menu_command(CMD_NOTELEN_LAST);
+
+ quant_len_toolbar->addSeparator();
+ quant_len_toolbar->addWidget(new QLabel(tr("Quantisation:"), quant_len_toolbar));
+ QComboBox* quant_combobox = new QComboBox(this);
+ quant_combobox->addItem("2"); // if you add or remove items from
+ quant_combobox->addItem("4"); // here, also change quant_mapper[]
+ quant_combobox->addItem("8"); // in ScoreCanvas::set_quant()!
+ quant_combobox->addItem("16");
+ quant_combobox->addItem("32");
+ connect(quant_combobox, SIGNAL(currentIndexChanged(int)), score_canvas, SLOT(set_quant(int)));
+ quant_len_toolbar->addWidget(quant_combobox);
+ quant_combobox->setCurrentIndex(2);
+
+
+ QMenu* settings_menu = menuBar()->addMenu(tr("&Settings"));
+
+ QMenu* color_menu = settings_menu->addMenu(tr("Note head &colors"));
+ QActionGroup* color_actions = new QActionGroup(this);
+ QAction* color_black_action = color_menu->addAction(tr("&Black"), menu_mapper, SLOT(map()));
+ QAction* color_velo_action = color_menu->addAction(tr("&Velocity"), menu_mapper, SLOT(map()));
+ QAction* color_part_action = color_menu->addAction(tr("&Part"), menu_mapper, SLOT(map()));
+ color_black_action->setCheckable(true);
+ color_velo_action->setCheckable(true);
+ color_part_action->setCheckable(true);
+ color_actions->addAction(color_black_action);
+ color_actions->addAction(color_velo_action);
+ color_actions->addAction(color_part_action);
+ menu_mapper->setMapping(color_black_action, CMD_COLOR_BLACK);
+ menu_mapper->setMapping(color_velo_action, CMD_COLOR_VELO);
+ menu_mapper->setMapping(color_part_action, CMD_COLOR_PART);
+
+ color_black_action->setChecked(true);
+ menu_command(CMD_COLOR_BLACK);
+
+ QMenu* preamble_menu = settings_menu->addMenu(tr("Set up &preamble"));
+ QAction* preamble_keysig_action = preamble_menu->addAction(tr("Display &key signature"));
+ QAction* preamble_timesig_action = preamble_menu->addAction(tr("Display &time signature"));
+ connect(preamble_keysig_action, SIGNAL(toggled(bool)), score_canvas, SLOT(preamble_keysig_slot(bool)));
+ connect(preamble_timesig_action, SIGNAL(toggled(bool)), score_canvas, SLOT(preamble_timesig_slot(bool)));
+
+ preamble_keysig_action->setCheckable(true);
+ preamble_timesig_action->setCheckable(true);
+
+ preamble_keysig_action->setChecked(true);
+ preamble_timesig_action->setChecked(true);
+
+ QAction* set_name_action = settings_menu->addAction(tr("Set Score &name"), menu_mapper, SLOT(map()));
+ menu_mapper->setMapping(set_name_action, CMD_SET_NAME);
+
+
+
+
+/* FINDMICHJETZT
+ addToolBarBreak();
+ info = new NoteInfo(this);
+ addToolBar(info);
+*/
-//---------------------------------------------------------
-// songChanged1
-//---------------------------------------------------------
-void ScoreEdit::songChanged1(int bits)
- {
-
- if (bits & SC_SOLO)
- {
- toolbar->setSolo(canvas->track()->solo());
- return;
- }
- songChanged(bits);
- //trackInfo->songChanged(bits);
- // We'll receive SC_SELECTION if a different part is selected.
- if (bits & SC_SELECTION)
- updateTrackInfo();
- }
-//---------------------------------------------------------
-// configChanged
-//---------------------------------------------------------
-void ScoreEdit::configChanged()
- {
- initShortcuts();
- //trackInfo->updateTrackInfo();
- }
+ score_canvas->song_changed(SC_EVENT_INSERTED);
+ score_canvas->goto_tick(initPos,true);
+
+ if (name!=NULL)
+ set_name(name, false, true);
+ else
+ set_name("Score "+IntToQStr(serial++), false, true);
+}
-//---------------------------------------------------------
-// updateHScrollRange
-//---------------------------------------------------------
-void ScoreEdit::updateHScrollRange()
+void ScoreEdit::add_parts(PartList* pl, bool all_in_one)
{
- int s, e;
- canvas->range(&s, &e);
- // Show one more measure.
- e += AL::sigmap.ticksMeasure(e);
- // Show another quarter measure due to imprecise drawing at canvas end point.
- e += AL::sigmap.ticksMeasure(e) / 4;
- // Compensate for the fixed piano and vscroll widths.
- e += canvas->rmapxDev(pianoWidth - vscroll->width());
- int s1, e1;
- hscroll->range(&s1, &e1);
- if(s != s1 || e != e1)
- hscroll->setRange(s, e);
+ score_canvas->add_staves(pl, all_in_one);
}
-void ScoreEdit::updateTrackInfo()
+bool ScoreEdit::set_name(QString newname, bool emit_signal, bool emergency_name)
{
- selected = curCanvasPart()->track();
- if (selected->isMidiTrack()) {
- midiTrackInfo->setTrack(selected);
- ///midiTrackInfo->updateTrackInfo(-1);
- }
+ if (names.find(newname)==names.end())
+ {
+ names.erase(name);
+ names.insert(newname);
+
+ name=newname;
+
+ if (emit_signal)
+ emit name_changed();
+
+ return true;
+ }
+ else
+ {
+ if (emergency_name)
+ {
+ while (set_name(create_random_string(), emit_signal, false) == false);
+ return true;
+ }
+ else
+ return false;
+ }
}
//---------------------------------------------------------
-// follow
+// ~ScoreEdit
//---------------------------------------------------------
-void ScoreEdit::follow(int pos)
- {
- int s, e;
- canvas->range(&s, &e);
+ScoreEdit::~ScoreEdit()
+{
+
+}
+
- if (pos < e && pos >= s)
- hscroll->setOffset(pos);
- if (pos < s)
- hscroll->setOffset(s);
- }
+void ScoreEdit::canvas_width_changed(int width)
+{
+ xscroll->setMaximum(width);
+}
+void ScoreEdit::viewport_width_changed(int width)
+{
+ xscroll->setPageStep(width * PAGESTEP);
+}
-//---------------------------------------------------------
-// setTime
-//---------------------------------------------------------
+void ScoreEdit::canvas_height_changed(int height)
+{
+ int val=height - score_canvas->viewport_height();
+ if (val<=0) val=0;
+
+ yscroll->setMaximum(val);
+
+ if (val==0)
+ yscroll->hide();
+ else
+ yscroll->show();
+}
+void ScoreEdit::viewport_height_changed(int height)
+{
+ int val=score_canvas->canvas_height() - height;
+ if (val<0) val=0;
+ yscroll->setPageStep(height * PAGESTEP);
+ yscroll->setMaximum(val);
+
+ if (val==0)
+ yscroll->hide();
+ else
+ yscroll->show();
+}
-void ScoreEdit::setTime(unsigned tick)
- {
- toolbar->setTime(tick);
- time->setPos(3, tick, false);
- }
+void ScoreEdit::closeEvent(QCloseEvent* e)
+{
+ QSettings settings("MusE", "MusE-qt");
+ //settings.setValue("ScoreEdit/geometry", saveGeometry());
+ settings.setValue("ScoreEdit/windowState", saveState());
-//---------------------------------------------------------
-// ~ScoreEdit
-//---------------------------------------------------------
+ emit deleted((unsigned long)this);
+ e->accept();
+}
-ScoreEdit::~ScoreEdit()
- {
- // undoRedo->removeFrom(tools); // p4.0.6 Removed
- }
+void ScoreEdit::menu_command(int cmd)
+{
+ switch (cmd)
+ {
+ case CMD_SET_NAME:
+ {
+ bool ok;
+ QString newname = QInputDialog::getText(this, tr("Enter the new score title"),
+ tr("Enter the new score title"), QLineEdit::Normal,
+ name, &ok);
+ if (ok)
+ {
+ if (!set_name(newname))
+ QMessageBox::warning(this, tr("Error"), tr("Changing score title failed:\nthe selected title is not unique"));
+ }
+ }
+
+ default:
+ score_canvas->menu_command(cmd);
+ }
+}
-//---------------------------------------------------------
-// cmd
-// pulldown menu commands
-//---------------------------------------------------------
-void ScoreEdit::cmd(int cmd)
- {
- ((PianoCanvas*)canvas)->cmd(cmd, _quantStrength, _quantLimit, _quantLen, _to);
- }
-//---------------------------------------------------------
-// setSelection
-// update Info Line
-//---------------------------------------------------------
+void ScoreCanvas::add_staves(PartList* pl, bool all_in_one)
+{
+ staff_t staff(this);
+
+ if (all_in_one)
+ {
+ staff.parts.clear();
+ for (ciPart part_it=pl->begin(); part_it!=pl->end(); part_it++)
+ staff.parts.insert(part_it->second);
+
+ staff.split_note=SPLIT_NOTE;
+
+ staff.type=GRAND_TOP; //FINDMICH
+ staff.clef=VIOLIN;
+ staves.push_back(staff);
+
+ staff.type=GRAND_BOTTOM;
+ staff.clef=BASS;
+ staves.push_back(staff);
+ }
+ else
+ {
+ set<Track*> tracks;
+
+ for (ciPart it=pl->begin(); it!=pl->end(); it++)
+ tracks.insert(it->second->track());
+
+ for (set<Track*>::iterator it=tracks.begin(); it!=tracks.end(); it++)
+ {
+ staff.parts.clear();
+ for (ciPart part_it=pl->begin(); part_it!=pl->end(); part_it++)
+ if (part_it->second->track() == *it)
+ staff.parts.insert(part_it->second);
+
+ staff.split_note=SPLIT_NOTE;
+
+ staff.type=GRAND_TOP; //FINDMICH
+ staff.clef=VIOLIN;
+ staves.push_back(staff);
+
+ staff.type=GRAND_BOTTOM;
+ staff.clef=BASS;
+ staves.push_back(staff);
+ }
+ }
+
+ recalc_staff_pos();
+ song_changed(SC_EVENT_INSERTED);
+}
-void ScoreEdit::setSelection(int tick, Event& e, Part* p)
- {
- int selections = canvas->selectionSize();
-
- selEvent = e;
- selPart = (MidiPart*)p;
- selTick = tick;
-
- if (selections > 1) {
- info->setEnabled(true);
- info->setDeltaMode(true);
- if (!deltaMode) {
- deltaMode = true;
- info->setValues(0, 0, 0, 0, 0);
- tickOffset = 0;
- lenOffset = 0;
- pitchOffset = 0;
- veloOnOffset = 0;
- veloOffOffset = 0;
- }
- }
- else if (selections == 1) {
- deltaMode = false;
- info->setEnabled(true);
- info->setDeltaMode(false);
- info->setValues(tick,
- selEvent.lenTick(),
- selEvent.pitch(),
- selEvent.velo(),
- selEvent.veloOff());
- }
- else {
- deltaMode = false;
- info->setEnabled(false);
- }
- selectionChanged();
- }
-//---------------------------------------------------------
-// edit currently selected Event
-//---------------------------------------------------------
+ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent,
+ int sx, int sy) : View(parent, sx, sy)
+{
+ editor = pr;
+ setFocusPolicy(Qt::StrongFocus);
+ setBg(Qt::white);
+
+ setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
+
+ load_pixmaps();
+
+ x_pos=0;
+ x_left=0;
+ y_pos=0;
+ dragging=false;
+ mouse_erases_notes=false;
+ mouse_inserts_notes=true;
+
+ curr_part=editor->parts()->begin()->second; //TODO FINDMICHJETZT
+
+ last_len=384;
+ new_len=-1;
+
+ set_quant(2); //this is actually unneccessary, as while
+ //initalizing the quant_combobox, this gets
+ //called again. but for safety...
+
+ dragging_staff=false;
+
+
+ coloring_mode=COLOR_MODE_BLACK;
+ preamble_contains_keysig=true;
+ preamble_contains_timesig=true;
+
+
+ x_scroll_speed=0;
+ x_scroll_pos=0;
+ y_scroll_speed=0;
+ y_scroll_pos=0;
+ connect (heartBeatTimer, SIGNAL(timeout()), SLOT(heartbeat_timer_event()));
+
+ connect(song, SIGNAL(posChanged(int, unsigned, bool)), SLOT(pos_changed(int,unsigned,bool)));
+ connect(song, SIGNAL(playChanged(bool)), SLOT(play_changed(bool)));
+ connect(muse, SIGNAL(configChanged()), SLOT(config_changed()));
+
+
+ staff_menu=new QMenu(this);
+
+ staffmode_treble_action = staff_menu->addAction(tr("Treble"));
+ connect(staffmode_treble_action, SIGNAL(triggered()), SLOT(staffmode_treble_slot()));
+
+ staffmode_bass_action = staff_menu->addAction(tr("Bass"));
+ connect(staffmode_bass_action, SIGNAL(triggered()), SLOT(staffmode_bass_slot()));
+
+ staffmode_both_action = staff_menu->addAction(tr("Grand Staff"));
+ connect(staffmode_both_action, SIGNAL(triggered()), SLOT(staffmode_both_slot()));
+
+ remove_staff_action = staff_menu->addAction(tr("Remove staff"));
+ connect(remove_staff_action, SIGNAL(triggered()), SLOT(remove_staff_slot()));
-void ScoreEdit::noteinfoChanged(NoteInfo::ValType type, int val)
- {
- int selections = canvas->selectionSize();
-
- if (selections == 0) {
- printf("noteinfoChanged while nothing selected\n");
- }
- else if (selections == 1) {
- Event event = selEvent.clone();
- switch(type) {
- case NoteInfo::VAL_TIME:
- event.setTick(val - selPart->tick());
- break;
- case NoteInfo::VAL_LEN:
- event.setLenTick(val);
- break;
- case NoteInfo::VAL_VELON:
- event.setVelo(val);
- break;
- case NoteInfo::VAL_VELOFF:
- event.setVeloOff(val);
- break;
- case NoteInfo::VAL_PITCH:
- event.setPitch(val);
- break;
- }
- // Indicate do undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(selEvent, event, selPart);
- audio->msgChangeEvent(selEvent, event, selPart, true, false, false);
- }
- else {
- // multiple events are selected; treat noteinfo values
- // as offsets to event values
-
- int delta = 0;
- switch (type) {
- case NoteInfo::VAL_TIME:
- delta = val - tickOffset;
- tickOffset = val;
- break;
- case NoteInfo::VAL_LEN:
- delta = val - lenOffset;
- lenOffset = val;
- break;
- case NoteInfo::VAL_VELON:
- delta = val - veloOnOffset;
- veloOnOffset = val;
- break;
- case NoteInfo::VAL_VELOFF:
- delta = val - veloOffOffset;
- veloOffOffset = val;
- break;
- case NoteInfo::VAL_PITCH:
- delta = val - pitchOffset;
- pitchOffset = val;
- break;
- }
- if (delta)
- canvas->modifySelected(type, delta);
- }
- }
+}
-//---------------------------------------------------------
-// addCtrl
-//---------------------------------------------------------
+void ScoreCanvas::staffmode_treble_slot()
+{
+ set_staffmode(current_staff, MODE_TREBLE);
+}
-CtrlEdit* ScoreEdit::addCtrl()
- {
- ///CtrlEdit* ctrlEdit = new CtrlEdit(splitter, this, xscale, false, "pianoCtrlEdit");
- CtrlEdit* ctrlEdit = new CtrlEdit(ctrlLane/*splitter*/, this, xscale, false, "pianoCtrlEdit"); // ccharrett
- connect(tools2, SIGNAL(toolChanged(int)), ctrlEdit, SLOT(setTool(int)));
- connect(hscroll, SIGNAL(scrollChanged(int)), ctrlEdit, SLOT(setXPos(int)));
- connect(hscroll, SIGNAL(scaleChanged(int)), ctrlEdit, SLOT(setXMag(int)));
- connect(ctrlEdit, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
- connect(ctrlEdit, SIGNAL(destroyedCtrl(CtrlEdit*)), SLOT(removeCtrl(CtrlEdit*)));
- connect(ctrlEdit, SIGNAL(yposChanged(int)), toolbar, SLOT(setInt(int)));
-
- ctrlEdit->setTool(tools2->curTool());
- ctrlEdit->setXPos(hscroll->pos());
- ctrlEdit->setXMag(hscroll->getScaleValue());
-
- ctrlEdit->show();
- ctrlEditList.push_back(ctrlEdit);
- return ctrlEdit;
- }
+void ScoreCanvas::staffmode_bass_slot()
+{
+ set_staffmode(current_staff, MODE_BASS);
+}
-//---------------------------------------------------------
-// removeCtrl
-//---------------------------------------------------------
+void ScoreCanvas::staffmode_both_slot()
+{
+ set_staffmode(current_staff, MODE_BOTH);
+}
-void ScoreEdit::removeCtrl(CtrlEdit* ctrl)
- {
- for (std::list<CtrlEdit*>::iterator i = ctrlEditList.begin();
- i != ctrlEditList.end(); ++i) {
- if (*i == ctrl) {
- ctrlEditList.erase(i);
- break;
- }
- }
- }
+void ScoreCanvas::remove_staff_slot()
+{
+ remove_staff(current_staff);
+}
-//---------------------------------------------------------
-// closeEvent
-//---------------------------------------------------------
+void ScoreCanvas::set_staffmode(list<staff_t>::iterator it, staff_mode_t mode)
+{
+ if (it->type == GRAND_BOTTOM)
+ {
+ it--;
+ if (it->type!=GRAND_TOP)
+ cout << "THIS SHOULD NEVER HAPPEN: grand_bottom without top!"<<endl;
+ }
+
+ if (it->type==GRAND_TOP)
+ {
+ list<staff_t>::iterator tmp=it;
+ tmp++;
+ if (tmp->type!=GRAND_BOTTOM)
+ cout << "THIS SHOULD NEVER HAPPEN: grand_top without bottom!"<<endl;
+ staves.erase(tmp);
+ }
+
+ switch (mode)
+ {
+ case MODE_TREBLE:
+ it->type=NORMAL;
+ it->clef=VIOLIN;
+ break;
+
+ case MODE_BASS:
+ it->type=NORMAL;
+ it->clef=BASS;
+ break;
+
+ case MODE_BOTH:
+ it->type=GRAND_BOTTOM;
+ it->clef=BASS;
+ it->split_note=SPLIT_NOTE;
+
+ staves.insert(it, staff_t(this, GRAND_TOP, VIOLIN, it->parts, it->split_note));
+ break;
+
+ default:
+ cout << "ILLEGAL FUNCTION CALL: invalid mode in set_staffmode" << endl;
+ }
+
+ recalc_staff_pos();
+ song_changed(SC_EVENT_INSERTED);
+}
-void ScoreEdit::closeEvent(QCloseEvent* e)
- {
- QSettings settings("MusE", "MusE-qt");
- //settings.setValue("ScoreEdit/geometry", saveGeometry());
- settings.setValue("ScoreEdit/windowState", saveState());
+void ScoreCanvas::remove_staff(list<staff_t>::iterator it)
+{
+ if (it->type == GRAND_BOTTOM)
+ {
+ it--;
+ if (it->type!=GRAND_TOP)
+ cout << "THIS SHOULD NEVER HAPPEN: grand_bottom without top!"<<endl;
+ }
+
+ if (it->type == NORMAL)
+ {
+ staves.erase(it);
+ }
+ else if (it->type == GRAND_TOP)
+ {
+ staves.erase(it++);
+ if (it->type!=GRAND_BOTTOM)
+ cout << "THIS SHOULD NEVER HAPPEN: grand_top without bottom!"<<endl;
+ staves.erase(it);
+ }
+
+ recalc_staff_pos();
+ song_changed(SC_EVENT_INSERTED);
+}
+
+void ScoreCanvas::merge_staves(list<staff_t>::iterator dest, list<staff_t>::iterator src)
+{
+ if (dest->type == GRAND_BOTTOM)
+ {
+ dest--;
+ if (dest->type!=GRAND_TOP)
+ cout << "THIS SHOULD NEVER HAPPEN: grand_bottom without top!"<<endl;
+ }
+
+ if (src->type == GRAND_BOTTOM)
+ {
+ src--;
+ if (src->type!=GRAND_TOP)
+ cout << "THIS SHOULD NEVER HAPPEN: grand_bottom without top!"<<endl;
+ }
+
+ if (dest==src) //dragged to itself?
+ return;
+
+
+ dest->parts.insert(src->parts.begin(), src->parts.end());
+
+ if (dest->type == GRAND_TOP)
+ {
+ dest++;
+ if (dest->type != GRAND_BOTTOM)
+ cout << "THIS SHOULD NEVER HAPPEN: grand_top without bottom!"<<endl;
+ dest->parts.insert(src->parts.begin(), src->parts.end());
+ }
+
+ remove_staff(src);
+
+ recalc_staff_pos();
+ song_changed(SC_EVENT_INSERTED);
+}
- emit deleted((unsigned long)this);
- e->accept();
- }
-//---------------------------------------------------------
-// readConfiguration
-//---------------------------------------------------------
+void ScoreCanvas::song_changed(int flags)
+{
+ if (flags & (SC_PART_INSERTED | SC_PART_MODIFIED | SC_PART_REMOVED |
+ SC_EVENT_INSERTED | SC_EVENT_MODIFIED | SC_EVENT_REMOVED |
+ SC_SIG | SC_KEY) )
+ {
+ cout << "song changed!" << endl;
+
+ calc_pos_add_list();
+
+ for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++)
+ {
+ it->create_appropriate_eventlist(it->parts);
+ it->create_itemlist();
+ it->process_itemlist(); // do note- and rest-grouping and collision avoiding
+ it->calc_item_pos();
+ }
+
+ redraw();
+ cout << "song had changed, recalculation complete" << endl;
+
+ emit canvas_width_changed(canvas_width());
+ }
+}
-void ScoreEdit::readConfiguration(Xml& xml)
- {
- for (;;) {
- Xml::Token token = xml.parse();
- if (token == Xml::Error || token == Xml::End)
- break;
- const QString& tag = xml.s1();
- switch (token) {
- case Xml::TagStart:
- if (tag == "quant")
- _quantInit = xml.parseInt();
- else if (tag == "raster")
- _rasterInit = xml.parseInt();
- else if (tag == "quantStrength")
- _quantStrengthInit = xml.parseInt();
- else if (tag == "quantLimit")
- _quantLimitInit = xml.parseInt();
- else if (tag == "quantLen")
- _quantLenInit = xml.parseInt();
- else if (tag == "to")
- _toInit = xml.parseInt();
- else if (tag == "colormode")
- colorModeInit = xml.parseInt();
- else if (tag == "width")
- _widthInit = xml.parseInt();
- else if (tag == "height")
- _heightInit = xml.parseInt();
- else
- xml.unknown("ScoreEdit");
- break;
- case Xml::TagEnd:
- if (tag == "ScoreEdit")
- return;
- default:
- break;
- }
- }
- }
+int ScoreCanvas::canvas_width()
+{
+ //return tick_to_x(staves.begin()->itemlist.rbegin()->first);
+ return tick_to_x(SONG_LENGTH);
+}
-//---------------------------------------------------------
-// writeConfiguration
-//---------------------------------------------------------
+int ScoreCanvas::canvas_height()
+{
+ return staves.rbegin()->y_bottom;
+}
-void ScoreEdit::writeConfiguration(int level, Xml& xml)
- {
- xml.tag(level++, "ScoreEdit");
- xml.intTag(level, "quant", _quantInit);
- xml.intTag(level, "raster", _rasterInit);
- xml.intTag(level, "quantStrength", _quantStrengthInit);
- xml.intTag(level, "quantLimit", _quantLimitInit);
- xml.intTag(level, "quantLen", _quantLenInit);
- xml.intTag(level, "to", _toInit);
- xml.intTag(level, "width", _widthInit);
- xml.intTag(level, "height", _heightInit);
- xml.intTag(level, "colormode", colorModeInit);
- xml.etag(level, "ScoreEdit");
- }
+int ScoreCanvas::viewport_width()
+{
+ return (width() - x_left);
+}
-//---------------------------------------------------------
-// soloChanged
-// signal from solo button
-//---------------------------------------------------------
+int ScoreCanvas::viewport_height()
+{
+ return height();
+}
-void ScoreEdit::soloChanged(bool flag)
- {
- audio->msgSetSolo(canvas->track(), flag);
- song->update(SC_SOLO);
- }
+string IntToStr(int i)
+{
+ ostringstream s;
+ s<<i;
+ return s.str();
+}
-//---------------------------------------------------------
-// setRaster
-//---------------------------------------------------------
+QString IntToQStr(int i)
+{
+ return QString(IntToStr(i).c_str());
+}
-void ScoreEdit::setRaster(int val)
- {
- _rasterInit = val;
- MidiEditor::setRaster(val);
- canvas->redrawGrid();
- canvas->setFocus(); // give back focus after kb input
- }
+void color_image(QImage& img, const QColor& color)
+{
+ uchar* ptr=img.bits();
+ int bytes=img.byteCount();
+ int r,g,b;
+ color.getRgb(&r,&g,&b);
+
+ for (int i=0; i<bytes/4; i++)
+ {
+ QRgb* rgb=((QRgb*)ptr);
+ (*rgb) = qRgba(r,g,b,qAlpha(*rgb));
+
+ ptr+=4;
+ }
+}
-//---------------------------------------------------------
-// setQuant
-//---------------------------------------------------------
+void load_colored_pixmaps(QString file, QPixmap* array)
+{
+ QImage img(file);
+
+ color_image(img, Qt::black);
+ array[BLACK_PIXMAP]=QPixmap::fromImage(img);
+
+ color_image(img, Qt::red);
+ array[HIGHLIGHTED_PIXMAP]=QPixmap::fromImage(img);
+
+
+ for (int color_index=0;color_index<NUM_PARTCOLORS; color_index++)
+ {
+ color_image(img, config.partColors[color_index]);
+ array[color_index]=QPixmap::fromImage(img);
+ }
+}
-void ScoreEdit::setQuant(int val)
- {
- _quantInit = val;
- MidiEditor::setQuant(val);
- canvas->setFocus();
- }
-//---------------------------------------------------------
-// writeStatus
-//---------------------------------------------------------
-void ScoreEdit::writeStatus(int level, Xml& xml) const
- {
- writePartList(level, xml);
- xml.tag(level++, "ScoreEdit");
- MidiEditor::writeStatus(level, xml);
- splitter->writeStatus(level, xml);
- hsplitter->writeStatus(level, xml);
-
- for (std::list<CtrlEdit*>::const_iterator i = ctrlEditList.begin();
- i != ctrlEditList.end(); ++i) {
- (*i)->writeStatus(level, xml);
- }
-
- xml.intTag(level, "steprec", canvas->steprec());
- xml.intTag(level, "midiin", canvas->midiin());
- xml.intTag(level, "tool", int(canvas->tool()));
- xml.intTag(level, "quantStrength", _quantStrength);
- xml.intTag(level, "quantLimit", _quantLimit);
- xml.intTag(level, "quantLen", _quantLen);
- xml.intTag(level, "playEvents", _playEvents);
- xml.intTag(level, "xpos", hscroll->pos());
- xml.intTag(level, "xmag", hscroll->mag());
- xml.intTag(level, "ypos", vscroll->pos());
- xml.intTag(level, "ymag", vscroll->mag());
- xml.tag(level, "/ScoreEdit");
- }
+void ScoreCanvas::load_pixmaps()
+{
+ if (!pixmaps_loaded)
+ {
+ cout << "loading pixmaps..." << endl;
+
+ pix_whole=new QPixmap[NUM_PARTCOLORS+2];
+ pix_half=new QPixmap[NUM_PARTCOLORS+2];
+ pix_quarter=new QPixmap[NUM_PARTCOLORS+2];
+ pix_dot=new QPixmap[NUM_PARTCOLORS+2];
+ pix_b=new QPixmap[NUM_PARTCOLORS+2];
+ pix_sharp=new QPixmap[NUM_PARTCOLORS+2];
+ pix_noacc=new QPixmap[NUM_PARTCOLORS+2];
+ pix_num=new QPixmap[10];
+
+ pix_r1=new QPixmap;
+ pix_r2=new QPixmap;
+ pix_r4=new QPixmap;
+ pix_r8=new QPixmap;
+ pix_r16=new QPixmap;
+
+ pix_clef_violin=new QPixmap;
+ pix_clef_bass=new QPixmap;
+
+ pix_flag_up=new QPixmap[4];
+ pix_flag_down=new QPixmap[4];
+
+
+
+
+ load_colored_pixmaps(museGlobalShare + "/scoreglyphs/whole.png", pix_whole);
+ load_colored_pixmaps(museGlobalShare + "/scoreglyphs/half.png", pix_half);
+ load_colored_pixmaps(museGlobalShare + "/scoreglyphs/quarter.png", pix_quarter);
+ load_colored_pixmaps(museGlobalShare + "/scoreglyphs/dot.png", pix_dot);
+ load_colored_pixmaps(museGlobalShare + "/scoreglyphs/acc_none.png", pix_noacc);
+ load_colored_pixmaps(museGlobalShare + "/scoreglyphs/acc_sharp.png", pix_sharp);
+ load_colored_pixmaps(museGlobalShare + "/scoreglyphs/acc_b.png", pix_b);
+
+ pix_r1->load(museGlobalShare + "/scoreglyphs/rest1.png");
+ pix_r2->load(museGlobalShare + "/scoreglyphs/rest2.png");
+ pix_r4->load(museGlobalShare + "/scoreglyphs/rest4.png");
+ pix_r8->load(museGlobalShare + "/scoreglyphs/rest8.png");
+ pix_r16->load(museGlobalShare + "/scoreglyphs/rest16.png");
+ pix_flag_up[0].load(museGlobalShare + "/scoreglyphs/flags8u.png");
+ pix_flag_up[1].load(museGlobalShare + "/scoreglyphs/flags16u.png");
+ pix_flag_up[2].load(museGlobalShare + "/scoreglyphs/flags32u.png");
+ pix_flag_up[3].load(museGlobalShare + "/scoreglyphs/flags64u.png");
+ pix_flag_down[0].load(museGlobalShare + "/scoreglyphs/flags8d.png");
+ pix_flag_down[1].load(museGlobalShare + "/scoreglyphs/flags16d.png");
+ pix_flag_down[2].load(museGlobalShare + "/scoreglyphs/flags32d.png");
+ pix_flag_down[3].load(museGlobalShare + "/scoreglyphs/flags64d.png");
+
+ pix_clef_violin->load(museGlobalShare + "/scoreglyphs/clef_violin_big.png");
+ pix_clef_bass->load(museGlobalShare + "/scoreglyphs/clef_bass_big.png");
+
+ for (int i=0;i<10;i++)
+ pix_num[i].load(museGlobalShare + "/scoreglyphs/"+IntToQStr(i)+".png");
+
+ pixmaps_loaded=true;
+ }
+}
-//---------------------------------------------------------
-// readStatus
-//---------------------------------------------------------
-void ScoreEdit::readStatus(Xml& xml)
- {
- for (;;) {
- Xml::Token token = xml.parse();
- if (token == Xml::Error || token == Xml::End)
- break;
- const QString& tag = xml.s1();
- switch (token) {
- case Xml::TagStart:
- if (tag == "steprec") {
- int val = xml.parseInt();
- canvas->setSteprec(val);
- srec->setChecked(val);
- }
- else if (tag == "midiin") {
- int val = xml.parseInt();
- canvas->setMidiin(val);
- midiin->setChecked(val);
- }
- else if (tag == "tool") {
- int tool = xml.parseInt();
- canvas->setTool(tool);
- tools2->set(tool);
- }
- else if (tag == "midieditor")
- MidiEditor::readStatus(xml);
- else if (tag == "ctrledit") {
- CtrlEdit* ctrl = addCtrl();
- ctrl->readStatus(xml);
- }
- else if (tag == splitter->objectName())
- splitter->readStatus(xml);
- else if (tag == hsplitter->objectName())
- hsplitter->readStatus(xml);
- else if (tag == "quantStrength")
- _quantStrength = xml.parseInt();
- else if (tag == "quantLimit")
- _quantLimit = xml.parseInt();
- else if (tag == "quantLen")
- _quantLen = xml.parseInt();
- else if (tag == "playEvents") {
- _playEvents = xml.parseInt();
- canvas->playEvents(_playEvents);
- speaker->setChecked(_playEvents);
- }
- else if (tag == "xmag")
- hscroll->setMag(xml.parseInt());
- else if (tag == "xpos")
- hscroll->setPos(xml.parseInt());
- else if (tag == "ymag")
- vscroll->setMag(xml.parseInt());
- else if (tag == "ypos")
- vscroll->setPos(xml.parseInt());
- else
- xml.unknown("ScoreEdit");
- break;
- case Xml::TagEnd:
- if (tag == "ScoreEdit") {
- _quantInit = _quant;
- _rasterInit = _raster;
- toolbar->setRaster(_raster);
- toolbar->setQuant(_quant);
- canvas->redrawGrid();
- return;
- }
- default:
- break;
- }
- }
- }
-
-static int rasterTable[] = {
- //-9----8- 7 6 5 4 3(1/4) 2 1
- 4, 8, 16, 32, 64, 128, 256, 512, 1024, // triple
- 6, 12, 24, 48, 96, 192, 384, 768, 1536,
- 9, 18, 36, 72, 144, 288, 576, 1152, 2304 // dot
- };
-//---------------------------------------------------------
-// viewKeyPressEvent
-//---------------------------------------------------------
+int modulo(int a, int b) // similar to a % b
+{
+ return (((a%b)+b)%b);
+}
-void ScoreEdit::keyPressEvent(QKeyEvent* event)
- {
- if (info->hasFocus()) {
- event->ignore();
- return;
- }
-
- int index;
- int n = sizeof(rasterTable)/sizeof(*rasterTable);
- for (index = 0; index < n; ++index)
- if (rasterTable[index] == raster())
- break;
- if (index == n) {
- index = 0;
- // raster 1 is not in table
- }
- int off = (index / 9) * 9;
- index = index % 9;
-
- int val = 0;
-
- PianoCanvas* pc = (PianoCanvas*)canvas;
- int key = event->key();
-
- //if (event->state() & Qt::ShiftButton)
- if (((QInputEvent*)event)->modifiers() & Qt::ShiftModifier)
- key += Qt::SHIFT;
- //if (event->state() & Qt::AltButton)
- if (((QInputEvent*)event)->modifiers() & Qt::AltModifier)
- key += Qt::ALT;
- //if (event->state() & Qt::ControlButton)
- if (((QInputEvent*)event)->modifiers() & Qt::ControlModifier)
- key+= Qt::CTRL;
-
- if (key == Qt::Key_Escape) {
- close();
- return;
- }
- else if (key == shortcuts[SHRT_TOOL_POINTER].key) {
- tools2->set(PointerTool);
- return;
- }
- else if (key == shortcuts[SHRT_TOOL_PENCIL].key) {
- tools2->set(PencilTool);
- return;
- }
- else if (key == shortcuts[SHRT_TOOL_RUBBER].key) {
- tools2->set(RubberTool);
- return;
- }
- else if (key == shortcuts[SHRT_TOOL_LINEDRAW].key) {
- tools2->set(DrawTool);
- return;
- }
- else if (key == shortcuts[SHRT_POS_INC].key) {
- pc->pianoCmd(CMD_RIGHT);
- return;
- }
- else if (key == shortcuts[SHRT_POS_DEC].key) {
- pc->pianoCmd(CMD_LEFT);
- return;
- }
- else if (key == shortcuts[SHRT_POS_INC_NOSNAP].key) {
- pc->pianoCmd(CMD_RIGHT_NOSNAP);
- return;
- }
- else if (key == shortcuts[SHRT_POS_DEC_NOSNAP].key) {
- pc->pianoCmd(CMD_LEFT_NOSNAP);
- return;
- }
- else if (key == shortcuts[SHRT_INSERT_AT_LOCATION].key) {
- pc->pianoCmd(CMD_INSERT);
- return;
- }
- else if (key == Qt::Key_Delete) {
- pc->pianoCmd(CMD_DELETE);
- return;
- }
- else if (key == shortcuts[SHRT_ZOOM_IN].key) {
- int mag = hscroll->mag();
- int zoomlvl = ScrollScale::getQuickZoomLevel(mag);
- if (zoomlvl < 23)
- zoomlvl++;
-
- int newmag = ScrollScale::convertQuickZoomLevelToMag(zoomlvl);
- hscroll->setMag(newmag);
- //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag);
- return;
- }
- else if (key == shortcuts[SHRT_ZOOM_OUT].key) {
- int mag = hscroll->mag();
- int zoomlvl = ScrollScale::getQuickZoomLevel(mag);
- if (zoomlvl > 1)
- zoomlvl--;
-
- int newmag = ScrollScale::convertQuickZoomLevelToMag(zoomlvl);
- hscroll->setMag(newmag);
- //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag);
- return;
- }
- else if (key == shortcuts[SHRT_GOTO_CPOS].key) {
- PartList* p = this->parts();
- Part* first = p->begin()->second;
- hscroll->setPos(song->cpos() - first->tick() );
- return;
- }
- else if (key == shortcuts[SHRT_SCROLL_LEFT].key) {
- int pos = hscroll->pos() - config.division;
- if (pos < 0)
- pos = 0;
- hscroll->setPos(pos);
- return;
- }
- else if (key == shortcuts[SHRT_SCROLL_RIGHT].key) {
- int pos = hscroll->pos() + config.division;
- hscroll->setPos(pos);
- return;
- }
- else if (key == shortcuts[SHRT_SET_QUANT_1].key)
- val = rasterTable[8 + off];
- else if (key == shortcuts[SHRT_SET_QUANT_2].key)
- val = rasterTable[7 + off];
- else if (key == shortcuts[SHRT_SET_QUANT_3].key)
- val = rasterTable[6 + off];
- else if (key == shortcuts[SHRT_SET_QUANT_4].key)
- val = rasterTable[5 + off];
- else if (key == shortcuts[SHRT_SET_QUANT_5].key)
- val = rasterTable[4 + off];
- else if (key == shortcuts[SHRT_SET_QUANT_6].key)
- val = rasterTable[3 + off];
- else if (key == shortcuts[SHRT_SET_QUANT_7].key)
- val = rasterTable[2 + off];
- else if (key == shortcuts[SHRT_TOGGLE_TRIOL].key)
- val = rasterTable[index + ((off == 0) ? 9 : 0)];
- else if (key == shortcuts[SHRT_EVENT_COLOR].key) {
- if (colorMode == 0)
- colorMode = 1;
- else if (colorMode == 1)
- colorMode = 2;
- else
- colorMode = 0;
- setEventColorMode(colorMode);
- return;
- }
- else if (key == shortcuts[SHRT_TOGGLE_PUNCT].key)
- val = rasterTable[index + ((off == 18) ? 9 : 18)];
-
- else if (key == shortcuts[SHRT_TOGGLE_PUNCT2].key) {//CDW
- if ((off == 18) && (index > 2)) {
- val = rasterTable[index + 9 - 1];
- }
- else if ((off == 9) && (index < 8)) {
- val = rasterTable[index + 18 + 1];
- }
- else
- return;
- }
- else { //Default:
- event->ignore();
- return;
- }
- setQuant(val);
- setRaster(val);
- toolbar->setQuant(_quant);
- toolbar->setRaster(_raster);
- }
+int divide_floor(int a, int b) // similar to a / b
+{ //TODO can be done better :/
+ return int(floor(float(a)/float(b)));
+}
-//---------------------------------------------------------
-// configQuant
-//---------------------------------------------------------
+#define DEFAULT_REST_HEIGHT 6 // TODO
-void ScoreEdit::configQuant()
- {
- if (!quantConfig) {
- quantConfig = new QuantConfig(_quantStrength, _quantLimit, _quantLen);
- connect(quantConfig, SIGNAL(setQuantStrength(int)), SLOT(setQuantStrength(int)));
- connect(quantConfig, SIGNAL(setQuantLimit(int)), SLOT(setQuantLimit(int)));
- connect(quantConfig, SIGNAL(setQuantLen(bool)), SLOT(setQuantLen(bool)));
- }
- quantConfig->show();
- }
-//---------------------------------------------------------
-// setSteprec
-//---------------------------------------------------------
+bool operator< (const note_pos_t& a, const note_pos_t& b)
+{
+ if (a.height<b.height) return true;
+ if (a.height>b.height) return false;
+ return a.vorzeichen<b.vorzeichen;
+}
-void ScoreEdit::setSteprec(bool flag)
- {
- canvas->setSteprec(flag);
- if (flag == false)
- midiin->setChecked(flag);
- }
-//---------------------------------------------------------
-// eventColorModeChanged
-//---------------------------------------------------------
+
+int flo_quantize(int tick, int quant_ticks)
+{
+ //TODO quantizing must be done with the proper functions!
+ return int(nearbyint((float)tick / quant_ticks))*quant_ticks;
+}
+
+int flo_quantize_floor(int tick, int quant_ticks)
+{
+ //TODO quantizing must be done with the proper functions, see above
+ return int(tick / quant_ticks) * quant_ticks;
+}
-void ScoreEdit::eventColorModeChanged(int mode)
- {
- colorMode = mode;
- colorModeInit = colorMode;
-
- ((PianoCanvas*)(canvas))->setColorMode(colorMode);
- }
+
+/* builds the event list used by the score editor.
+ * that list contains only note-on and -off, time-sig- and
+ * key-change events.
+ * it stores them sorted by their time (quantized); if more
+ * events with the same time occur, the NOTE-OFFs are
+ * put before the NOTE-ONs
+ * it only operates on parts which were selected in the
+ * arranger when the score viewer was started
+ *
+ * this abstracts the rest of the renderer from muse's internal
+ * data structures, making this easy to port to another application
+ */
+void staff_t::create_appropriate_eventlist(const set<Part*>& parts)
+{
+ using AL::sigmap;
+ using AL::iSigEvent;
+
+ eventlist.clear();
+
+ // phase one: fill the list -----------------------------------------
+
+ //insert note on events
+ for (set<Part*>::const_iterator part_it=parts.begin(); part_it!=parts.end(); part_it++)
+ {
+ Part* part=*part_it;
+ EventList* el=part->events();
+
+ for (iEvent it=el->begin(); it!=el->end(); it++)
+ {
+ Event& event=it->second;
+
+ if ( (event.isNote() && !event.isNoteOff()) &&
+ ( ((type==GRAND_TOP) && (event.pitch() >= split_note)) ||
+ ((type==GRAND_BOTTOM) && (event.pitch() < split_note)) ||
+ (type==NORMAL) ) )
+ {
+ unsigned begin, end;
+ begin=flo_quantize(event.tick()+part->tick(), parent->quant_ticks());
+ end=flo_quantize(event.endTick()+part->tick(), parent->quant_ticks());
+ cout <<"inserting note on at "<<begin<<" with pitch="<<event.pitch()<<" and len="<<end-begin<<endl;
+ eventlist.insert(pair<unsigned, FloEvent>(begin, FloEvent(begin,event.pitch(), event.velo(),end-begin,FloEvent::NOTE_ON,part,&it->second)));
+ }
+ //else ignore it
+ }
+ }
+
+ //insert bars and time signatures
+ for (iSigEvent it=sigmap.begin(); it!=sigmap.end(); it++)
+ {
+ unsigned from=it->second->tick;
+ unsigned to=it->first;
+ unsigned ticks_per_measure=sigmap.ticksMeasure(it->second->tick);
+
+ if (to > unsigned(SONG_LENGTH))
+ {
+ cout << "time signature's end-of-validness is outside of our song, limiting it." << endl;
+ to=SONG_LENGTH;
+ }
+
+ cout << "new signature from tick "<<from<<" to " << to << ": "<<it->second->sig.z<<"/"<<it->second->sig.n<<"; ticks per measure = "<<ticks_per_measure<<endl;
+ eventlist.insert(pair<unsigned, FloEvent>(from, FloEvent(from, FloEvent::TIME_SIG, it->second->sig.z, it->second->sig.n) ) );
+ for (unsigned t=from; t<to; t+=ticks_per_measure)
+ eventlist.insert(pair<unsigned, FloEvent>(t, FloEvent(t,0,0,ticks_per_measure,FloEvent::BAR) ) );
+ }
+
+ //insert key changes
+ for (iKeyEvent it=keymap.begin(); it!=keymap.end(); it++)
+ eventlist.insert(pair<unsigned, FloEvent>(it->second.tick, FloEvent(it->second.tick,FloEvent::KEY_CHANGE, it->second.key ) ) );
+
+
+ // phase two: deal with overlapping notes ---------------------------
+ ScoreEventList::iterator it, it2;
+
+ //iterate through all note_on - events
+ for (it=eventlist.begin(); it!=eventlist.end(); it++)
+ if (it->second.type==FloEvent::NOTE_ON)
+ {
+ unsigned end_tick=it->first + it->second.len;
+
+ //iterate though all (relevant) later note_ons which are
+ //at the same pitch. if there's a collision, shorten it's len
+ for (it2=it, it2++; it2!=eventlist.end() && it2->first < end_tick; it2++)
+ if ((it2->second.type==FloEvent::NOTE_ON) && (it2->second.pitch == it->second.pitch))
+ it->second.len=it2->first - it->first;
+ }
+
+
+ // phase three: eliminate zero-length-notes -------------------------
+ for (it=eventlist.begin(); it!=eventlist.end();)
+ if ((it->second.type==FloEvent::NOTE_ON) && (it->second.len<=0))
+ eventlist.erase(it++);
+ else
+ it++;
+}
-//---------------------------------------------------------
-// setEventColorMode
-//---------------------------------------------------------
-void ScoreEdit::setEventColorMode(int mode)
- {
- colorMode = mode;
- colorModeInit = colorMode;
-
- ///eventColor->setItemChecked(0, mode == 0);
- ///eventColor->setItemChecked(1, mode == 1);
- ///eventColor->setItemChecked(2, mode == 2);
- evColorBlueAction->setChecked(mode == 0);
- evColorPitchAction->setChecked(mode == 1);
- evColorVelAction->setChecked(mode == 2);
-
- ((PianoCanvas*)(canvas))->setColorMode(colorMode);
- }
+bool is_sharp_key(key_enum t)
+{
+ return ((t>=KEY_SHARP_BEGIN) && (t<=KEY_SHARP_END));
+}
+bool is_b_key(key_enum t)
+{
+ return ((t>=KEY_B_BEGIN) && (t<=KEY_B_END));
+}
-//---------------------------------------------------------
-// clipboardChanged
-//---------------------------------------------------------
+int n_accidentials(key_enum t)
+{
+ if (is_sharp_key(t))
+ return t-KEY_SHARP_BEGIN-1;
+ else
+ return t-KEY_B_BEGIN-1;
+}
-void ScoreEdit::clipboardChanged()
- {
- editPasteAction->setEnabled(QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-eventlist")));
- }
-//---------------------------------------------------------
-// selectionChanged
-//---------------------------------------------------------
+//note needs to be 0..11
+//always assumes violin clef
+//only for internal use
+note_pos_t note_pos_(int note, key_enum key)
+{
+ note_pos_t result;
+ //C CIS D DIS E F FIS G GIS A AIS H
+ int foo[12]={0,-1, 1,-1, 2,3,-1, 4,-1, 5, -1,6};
+
+ if ((note<0) || (note>=12))
+ cout << "WARNING: ILLEGAL FUNCTION CALL (note_pos, note out of range)" << endl;
+
+ if (foo[note]!=-1)
+ {
+ result.height=foo[note];
+ result.vorzeichen=NONE;
+ }
+ else
+ {
+ if (is_sharp_key(key))
+ {
+ result.height=foo[note-1];
+ result.vorzeichen=SHARP;
+ }
+ else // if is_b_key
+ {
+ result.height=foo[note+1];
+ result.vorzeichen=B;
+ }
+ }
+
+ // Special cases for GES / FIS keys
+ if (key==KEY_GES)
+ {
+ // convert a H to a Ces
+ if (note==11)
+ {
+ result.height=12;
+ result.vorzeichen=B;
+ }
+ }
+ else if (key==KEY_FIS)
+ {
+ // convert a F to an Eis
+ if (note==5)
+ {
+ result.height=2;
+ result.vorzeichen=SHARP;
+ }
+ }
+
+ return result;
+}
-void ScoreEdit::selectionChanged()
- {
- bool flag = canvas->selectionSize() > 0;
- editCutAction->setEnabled(flag);
- editCopyAction->setEnabled(flag);
- editDelEventsAction->setEnabled(flag);
- }
-//---------------------------------------------------------
-// setSpeaker
-//---------------------------------------------------------
+// V -------------------------- <-- height=10
+// I C -------------------------- <-- height=8
+// O L -------------------------- <-- height=6
+// L E -------------------------- <-- height=4
+// I F -------------------------- <-- height=2
+// N --o-- <-- this is C4. height=0
+
+// the "spaces" in between the lines have odd numbers.
+// that is, the space between line 2 and 4 is numbered 3.
+
+// these numbers do not change when clef changes. line 2
+// is always the "bottom line" of the system.
+// in violin clef, line 2 is E4
+// in bass clef, line 2 is G2
+
+note_pos_t note_pos (unsigned note, key_enum key, clef_t clef)
+{
+ int octave=(note/12)-1; //integer division. note is unsigned
+ note=note%12;
+
+ //now octave contains the octave the note is in
+ //(A4 is the 440Hz tone. C4 is the "low C" in the violin clef
+ //and the "high C" in the bass clef.
+ //note contains 0 for C, 1 for Cis, ..., 11 for H (or B if you're not german)
+
+ note_pos_t pos=note_pos_(note,key);
+
+ switch (clef) //CLEF_MARKER
+ {
+ case VIOLIN:
+ pos.height=pos.height + (octave-4)*7;
+ break;
+
+ case BASS:
+ pos.height=pos.height + (octave-3)*7 + 5;
+ break;
+ }
+
+ return pos;
+}
+
+
+int calc_len(int l, int d)
+{
+ // l=0,1,2 -> whole, half, quarter (think of 2^0, 2^1, 2^2)
+ // d=number of dots
+
+ int tmp=0;
+ for (int i=0;i<=d;i++)
+ tmp+=TICKS_PER_WHOLE / (1 << (l+i));
+
+ return tmp;
+}
+
+bool operator< (const note_len_t& a,const note_len_t& b) //TODO sane sorting order
+{
+ if (a.len<b.len) return true;
+ else if (a.dots<b.dots) return true;
+ else return false;
+}
+
+
+
+int calc_measure_len(const list<int>& nums, int denom)
+{
+ int sum=0;
+
+ for (list<int>::const_iterator it=nums.begin(); it!=nums.end(); it++)
+ sum+=*it;
+
+ return 64* sum/denom;
+}
-void ScoreEdit::setSpeaker(bool val)
- {
- _playEvents = val;
- canvas->playEvents(_playEvents);
- }
+vector<int> create_emphasize_list(const list<int>& nums, int denom)
+{
+ cout << "creating emphasize list for ";
+ for (list<int>::const_iterator it=nums.begin(); it!=nums.end(); it++)
+ cout << *it << " ";
+ cout << "/ "<<denom;
+
+ // |----- 8th -----|
+ int foo[]={4,7,6,7,5,7,6,7}; //if 64 changes, this also must change
+ int pos=0;
+ int len=calc_measure_len(nums, denom);
+
+ vector<int> result(len);
+
+ for (int i=0;i<len;i++)
+ result[i]=foo[i%8];
+
+ for (list<int>::const_iterator it=nums.begin(); it!=nums.end(); it++)
+ {
+ result[pos]=1;
+ for (int i=1;i<*it;i++)
+ result[pos + i*64/denom]=2;
+ pos+= *it * 64 / denom;
+ }
+
+ result[0]=0;
+
+ for (int i=0;i<len;i++)
+ {
+ if (i%8==0)
+ cout << endl<<i<<":\t";
+ cout << result[i]<<" ";
+ }
+ cout << endl;
+
+ return result;
+}
+
+vector<int> create_emphasize_list(int num, int denom)
+{
+ list<int> nums;
+
+ if (num%3 ==0)
+ {
+ for (int i=0;i<num/3;i++)
+ nums.push_back(3);
+ }
+ else if (num%2 ==0)
+ {
+ for (int i=0;i<num/2;i++)
+ nums.push_back(2);
+ }
+ else // num is odd
+ {
+ for (int i=0;i<(num-3)/2;i++)
+ nums.push_back(2);
+
+ nums.push_back(3);
+ }
+
+ return create_emphasize_list(nums, denom);
+}
+
+//quant_power2 must be in log(len), that is
+//whole, half, quarter, eighth = 0,1,2,3
+//NOT: 1,2,4,8! (think of 2^foo)
+//len is in ticks
+list<note_len_t> parse_note_len(int len_ticks, int begin_tick, vector<int>& foo, int quant_power2, bool allow_dots, bool allow_normal)
+{
+ list<note_len_t> retval;
+
+ if (len_ticks<0)
+ cout << "WARNING: ILLEGAL FUNCTION CALL in parse_note_len: len_ticks < 0" << endl;
+ if (begin_tick<0)
+ cout << "WARNING: ILLEGAL FUNCTION CALL in parse_note_len: begin_tick < 0" << endl;
+
+ if (allow_normal)
+ {
+ int dot_max = allow_dots ? quant_power2 : 0;
+
+ for (int i=0;i<=quant_power2;i++)
+ for (int j=0;j<=dot_max-i;j++)
+ if (calc_len(i,j) == len_ticks)
+ {
+ retval.push_back(note_len_t (i,j));
+ return retval;
+ }
+ }
+
+ //if !allow_normal or if the above failed
+
+ int begin=begin_tick * 64 / TICKS_PER_WHOLE;
+ int len=len_ticks * 64 / TICKS_PER_WHOLE;
+
+ unsigned pos=begin;
+ int len_done=0;
+
+ while (len_done<len)
+ {
+ int len_now=0;
+ int last_number=foo[pos];
+
+ do {pos++;len_done++;len_now++;} while (! ((foo[pos]<=last_number) || (len_done==len) || (pos==foo.size())) );
+
+ len_now=len_now*TICKS_PER_WHOLE/64;
+
+ cout << "add " << len_now << " ticks" << endl;
+ if (allow_dots)
+ {
+ for (int i=0;i<=quant_power2;i++)
+ for (int j=0;j<=quant_power2-i;j++)
+ if (calc_len(i,j) == len_now)
+ {
+ retval.push_back(note_len_t (i,j));
+ len_now=0;
+ }
+ }
+
+ if (len_now) //the above failed or allow_dots=false
+ {
+ for (int i=0; i<=quant_power2; i++)
+ {
+ int tmp=calc_len(i,0);
+ if (tmp <= len_now)
+ {
+ retval.push_back(note_len_t(i));
+ len_now-=tmp;
+ if (len_now==0) break;
+ }
+ }
+ }
+
+ if (len_now!=0)
+ cout << "WARNING: THIS SHOULD NEVER HAPPEN. wasn't able to split note len properly; len_now="<<len_now << endl;
+
+ if (pos==foo.size()) //we cross measure boundaries?
+ pos=0;
+ }
+
+
+ return retval;
+}
+
+
+#define YLEN 10
+#define NOTE_SHIFT 3
+
+#define REST_AUSWEICH_X 10
+#define DOT_XDIST 6
+#define DOT_XBEGIN 10
+#define DOT_XBEGIN_REST 10
+
+#define NUMBER_HEIGHT (pix_num[0].height())
+
+//kann 0 oder 1 sein:
+//bei notenkollisionen mit ungerader anzahl von kollidierenden
+//wird immer so ausgewichen, dass möglichst wenige ausweichen müssen
+//wenn die anzahl aber gerade ist, gibt es keine "bessere" lösung
+//in dem fall werden immer die geraden (0) bzw. ungeraden (1)
+//ausweichen.
+#define AUSWEICHEN_BEVORZUGT 0
+
+#define STEM_LEN 30
+
+#define DOTTED_RESTS true
+#define UNSPLIT_RESTS false
+
+#define AUX_LINE_LEN 1.5
+
+#define ACCIDENTIAL_DIST 11
+#define KEYCHANGE_ACC_DIST 9
+#define KEYCHANGE_ACC_LEFTDIST 9
+#define KEYCHANGE_ACC_RIGHTDIST 0
+
+
+#define no_notepos note_pos_t()
+
+#define TIE_DIST 5
+#define TIE_HEIGHT 6
+#define TIE_THICKNESS 3
+
+void ScoreCanvas::draw_tie (QPainter& p, int x1, int x4, int yo, bool up, QColor color)
+{
+ QPainterPath path;
+
+ int y1, y2, y3;
+
+ if (up)
+ {
+ y1 = yo - TIE_DIST;
+ y2 = y1 - TIE_HEIGHT;
+ y3=y2-TIE_THICKNESS;
+ }
+ else
+ {
+ y1 = yo + TIE_DIST;
+ y2 = y1 + TIE_HEIGHT;
+ y3=y2+TIE_THICKNESS;
+ }
+
+ int x2 = x1 + (x4-x1)/4;
+ int x3 = x4 - (x4-x1)/4;
+
+ path.moveTo(x1,y1);
+ path.cubicTo( x2,y2 , x3,y2 , x4,y1 );
+ path.cubicTo( x3,y3 , x2,y3 , x1,y1 );
+
+ p.setPen(color);
+ p.setBrush(color);
+
+ p.drawPath(path);
+}
+
+void ScoreCanvas::draw_accidentials(QPainter& p, int x, int y_offset, const list<int>& acc_list, const QPixmap& pix)
+{
+ int n_acc_drawn=0;
+
+ for (list<int>::const_iterator acc_it=acc_list.begin(); acc_it!=acc_list.end(); acc_it++)
+ {
+ int y_coord=2*YLEN - ( *acc_it -2)*YLEN/2;
+ draw_pixmap(p,x + n_acc_drawn*KEYCHANGE_ACC_DIST,y_offset + y_coord,pix);
+ n_acc_drawn++;
+ }
+}
+
+void staff_t::create_itemlist()
+{
+ key_enum tmp_key=KEY_C;
+ int lastevent=0;
+ int next_measure=-1;
+ int last_measure=-1;
+ vector<int> emphasize_list=create_emphasize_list(4,4); //actually unneccessary, for safety
+
+ itemlist.clear();
+
+ for (ScoreEventList::iterator it=eventlist.begin(); it!=eventlist.end(); it++)
+ {
+ int t, pitch, len, velo, actual_tick;
+ FloEvent::typeEnum type;
+ t=it->first;
+ pitch=it->second.pitch;
+ velo=it->second.vel;
+ len=it->second.len;
+ type=it->second.type;
+ actual_tick=it->second.tick;
+ if (actual_tick==-1) actual_tick=t;
+
+ note_pos_t notepos=note_pos(pitch,tmp_key,clef);
+
+ printf("FLO: t=%i\ttype=%i\tpitch=%i\tvel=%i\tlen=%i\n",it->first, it->second.type, it->second.pitch, it->second.vel, it->second.len);
+ cout << "\tline="<<notepos.height<<"\tvorzeichen="<<notepos.vorzeichen << endl;
+
+
+ if (type==FloEvent::BAR)
+ {
+ if (last_measure!=-1) //i.e.: "this is NOT the first bar"
+ {
+ if (lastevent==last_measure) //there was no note?
+ {
+ unsigned tmppos=(last_measure+t-parent->quant_ticks())/2;
+ cout << "\tend-of-measure: this was an empty measure. inserting rest in between at t="<<tmppos << endl;
+ itemlist[tmppos].insert( FloItem(FloItem::REST,notepos,0,0) );
+ itemlist[t].insert( FloItem(FloItem::REST_END,notepos,0,0) );
+ }
+ else
+ {
+ // if neccessary, insert rest at between last note and end-of-measure
+ int rest=t-lastevent;
+ if (rest)
+ {
+ printf("\tend-of-measure: set rest at %i with len %i\n",lastevent,rest);
+
+ list<note_len_t> lens=parse_note_len(rest,lastevent-last_measure,emphasize_list,parent->quant_power2(),DOTTED_RESTS,UNSPLIT_RESTS);
+ unsigned tmppos=lastevent;
+ for (list<note_len_t>::iterator x=lens.begin(); x!=lens.end(); x++)
+ {
+ cout << "\t\tpartial rest with len="<<x->len<<", dots="<<x->dots<<endl;
+ itemlist[tmppos].insert( FloItem(FloItem::REST,notepos,x->len,x->dots) );
+ tmppos+=calc_len(x->len,x->dots);
+ itemlist[tmppos].insert( FloItem(FloItem::REST_END,notepos,0,0) );
+ }
+ }
+ }
+ }
+
+ lastevent=t;
+ last_measure=t;
+ next_measure=t+len;
+
+ itemlist[t].insert( FloItem(FloItem::BAR,no_notepos,0,0) );
+ }
+ else if (type==FloEvent::NOTE_ON)
+ {
+ int rest=t-lastevent;
+ if (rest)
+ {
+ printf("\tset rest at %i with len %i\n",lastevent,rest);
+ // no need to check if the rest crosses measure boundaries;
+ // it can't.
+
+ list<note_len_t> lens=parse_note_len(rest,lastevent-last_measure,emphasize_list,parent->quant_power2(),DOTTED_RESTS,UNSPLIT_RESTS);
+ unsigned tmppos=lastevent;
+ for (list<note_len_t>::iterator x=lens.begin(); x!=lens.end(); x++)
+ {
+ cout << "\t\tpartial rest with len="<<x->len<<", dots="<<x->dots<<endl;
+ itemlist[tmppos].insert( FloItem(FloItem::REST,notepos,x->len,x->dots) );
+ tmppos+=calc_len(x->len,x->dots);
+ itemlist[tmppos].insert( FloItem(FloItem::REST_END,notepos,0,0) );
+ }
+ }
+
+
+
+ printf("\tset note at %i with len=%i\n", t, len);
+
+ int tmplen;
+ bool tied_note;
+
+ // if the note exceeds the current measure, split it.
+ if (t+len>next_measure)
+ {
+ tmplen=next_measure-t;
+ tied_note=true;
+
+ //append the "remainder" of the note to our EventList, so that
+ //it gets processed again when entering the new measure
+ int newlen=len-tmplen;
+ eventlist.insert(pair<unsigned, FloEvent>(next_measure, FloEvent(actual_tick,pitch, velo,0,FloEvent::NOTE_OFF, it->second.source_part, it->second.source_event)));
+ eventlist.insert(pair<unsigned, FloEvent>(next_measure, FloEvent(actual_tick,pitch, velo,newlen,FloEvent::NOTE_ON, it->second.source_part, it->second.source_event)));
+
+ cout << "\t\tnote was split to length "<<tmplen<<" + " << newlen<<endl;
+ }
+ else
+ {
+ tmplen=len;
+ tied_note=false;
+
+ cout << "\t\tinserting NOTE OFF at "<<t+len<<endl;
+ eventlist.insert(pair<unsigned, FloEvent>(t+len, FloEvent(t+len,pitch, velo,0,FloEvent::NOTE_OFF,it->second.source_part, it->second.source_event)));
+ }
+
+ list<note_len_t> lens=parse_note_len(tmplen,t-last_measure,emphasize_list,parent->quant_power2(),true,true);
+ unsigned tmppos=t;
+ int n_lens=lens.size();
+ int count=0;
+ for (list<note_len_t>::iterator x=lens.begin(); x!=lens.end(); x++)
+ {
+ cout << "\t\tpartial note with len="<<x->len<<", dots="<<x->dots<<endl;
+ count++;
+
+ bool tie;
+
+ if (count<n_lens)
+ tie=true; // all notes except the last are always tied
+ else
+ tie=tied_note; // only the last respects tied_note
+
+ itemlist[tmppos].insert( FloItem(FloItem::NOTE,notepos,x->len,x->dots, tie, actual_tick, it->second.source_part, it->second.source_event) );
+ tmppos+=calc_len(x->len,x->dots);
+ itemlist[tmppos].insert( FloItem(FloItem::NOTE_END,notepos,0,0) );
+ }
+ }
+ else if (type==FloEvent::NOTE_OFF)
+ {
+ lastevent=t;
+ }
+ else if (type==FloEvent::TIME_SIG)
+ {
+ cout << "inserting TIME SIGNATURE "<<it->second.num<<"/"<<it->second.denom<<" at "<<t<<endl;
+ itemlist[t].insert( FloItem(FloItem::TIME_SIG, it->second.num, it->second.denom) );
+
+ emphasize_list=create_emphasize_list(it->second.num, it->second.denom);
+ }
+ else if (type==FloEvent::KEY_CHANGE)
+ {
+ cout << "inserting KEY CHANGE ("<<it->second.key<<") at "<<t<<endl;
+ itemlist[t].insert( FloItem(FloItem::KEY_CHANGE, it->second.key) );
+ tmp_key=it->second.key;
+ }
+ }
+}
+
+void staff_t::process_itemlist()
+{
+ map<int,int> occupied;
+ int last_measure=0;
+ vector<int> emphasize_list=create_emphasize_list(4,4); //unneccessary, only for safety
+
+ //iterate through all times with items
+ for (ScoreItemList::iterator it2=itemlist.begin(); it2!=itemlist.end(); it2++)
+ {
+ set<FloItem, floComp>& curr_items=it2->second;
+
+ cout << "at t="<<it2->first<<endl;
+
+ // phase 0: keep track of active notes, rests -------------------
+ // (and occupied lines) and the last measure
+ // and the current time signature
+ for (set<FloItem, floComp>::iterator it=curr_items.begin(); it!=curr_items.end(); it++)
+ {
+ if ((it->type==FloItem::NOTE) || (it->type==FloItem::REST))
+ occupied[it->pos.height]++;
+ else if ((it->type==FloItem::NOTE_END) || (it->type==FloItem::REST_END))
+ occupied[it->pos.height]--;
+ else if (it->type==FloItem::BAR)
+ last_measure=it2->first;
+ else if (it->type==FloItem::TIME_SIG)
+ emphasize_list=create_emphasize_list(it->num, it->denom);
+ }
+
+ cout << "occupied: ";
+ for (map<int,int>::iterator i=occupied.begin(); i!=occupied.end(); i++)
+ if (i->second) cout << i->first << "("<<i->second<<") ";
+ cout << endl;
+
+
+
+
+
+ // phase 1: group rests together -----------------------------------
+ int n_groups=0;
+ bool dont_group=false;
+
+ //iterate through all rests R at that time
+ // iterate through all rests X at that time below R
+ // if something is between X and R ("barrier"), stop
+ // else: group them together
+ for (set<FloItem, floComp>::iterator it=curr_items.begin(); it!=curr_items.end();)
+ {
+ //only operate on rests; ignore rests which are created by this code
+ //(can be seen on already_grouped)
+ if ((it->type==FloItem::REST) && (it->already_grouped==false))
+ {
+ cout << "trying to group" << endl;
+
+ int lastheight;
+ int height_cumulative=0;
+ int counter=0;
+
+ lastheight=it->pos.height;
+
+ set<FloItem, floComp>::iterator tmp;
+ for (tmp=it; tmp!=curr_items.end();)
+ {
+ cout << "checking if we can proceed with an item at height="<<tmp->pos.height<<endl;
+
+ for (int i=lastheight+1; i<=tmp->pos.height-1; i++)
+ if (occupied[i]!=0)
+ {
+ cout << "we can NOT, because occ["<<i<<"] != 0" << endl;
+ //stop grouping that rest
+ goto get_out_here;
+ }
+
+ lastheight=tmp->pos.height;
+
+ // the current item is a rest with equal len? cool!
+ if (tmp->type==FloItem::REST && tmp->len==it->len && tmp->dots==it->dots)
+ {
+ // füge diese pause zur gruppe dazu und entferne sie von diesem set hier
+ // entfernen aber nur, wenn sie nicht it, also die erste pause ist, die brauchen wir noch!
+ cout << "\tgrouping rest at height="<<tmp->pos.height<<endl;
+ height_cumulative+=tmp->pos.height;
+ counter++;
+ if (tmp!=it)
+ curr_items.erase(tmp++);
+ else
+ tmp++;
+ }
+ else //it's something else? well, we can stop grouping that rest then
+ {
+ cout << "we can NOT, because that item is not a rest" << endl;
+ //stop grouping that rest
+ goto get_out_here;
+ }
+ }
+ cout << "no items to proceed on left, continuing" << endl;
+ get_out_here:
+
+ n_groups++;
+
+ // entferne it vom set und
+ // füge eine pause mit dem "mittelwert" ein.
+ // occupied und die "_END"-events bleiben unberührt
+
+ FloItem temp=*it;
+ temp.already_grouped=true;
+
+ // have we grouped all available rests into one single?
+ if ( (n_groups==1) && (tmp==curr_items.end()) && !dont_group)
+ {
+ cout << "wow, we were able to group all rests into one single" << endl;
+ if (temp.len==0) //the whole rest is shifted one line (one space and one line)
+ temp.pos.height=DEFAULT_REST_HEIGHT+2;
+ else
+ temp.pos.height=DEFAULT_REST_HEIGHT;
+ }
+ else
+ {
+ cout << "creating group #"<<n_groups<<endl;
+ temp.pos.height=nearbyint((float)height_cumulative/counter);
+ }
+
+ // do NOT first insert, then erase, because if temp.height ==
+ // it->height, the set considers temp and it equal (it doesn't
+ // take already_grouped into account)
+ // the result of this: insert does nothing, and erase erases
+ // the item. effect: you don't have the rest at all
+ curr_items.erase(it++);
+
+ cout << "replacing all grouped rests with a rest at height="<<temp.pos.height<<endl;
+
+ curr_items.insert(temp);
+ }
+ else
+ {
+ if (it->type==FloItem::NOTE)
+ dont_group=true;
+
+ it++;
+ }
+ }
+
+
+
+
+
+ // phase 2: avoid collisions of items ------------------------------
+ set<FloItem, floComp>::iterator lastit, groupbegin, invalid;
+ invalid=curr_items.end();
+ lastit=invalid;
+ groupbegin=invalid;
+ int count;
+
+ //TODO FINDMICH MARKER: is "grouping" notes and rests together okay?
+ // or is it better to ignore rests when grouping?
+ for (set<FloItem, floComp>::iterator it=curr_items.begin(); it!=curr_items.end(); it++)
+ if ( (it->type==FloItem::NOTE) || (it->type==FloItem::REST) )
+ {
+ if (lastit != invalid)
+ {
+ if (it->pos.height == lastit->pos.height+1) // they would collide?
+ {
+ if (groupbegin==invalid) // we have no group atm?
+ {
+ groupbegin=lastit; // start a new group
+ count=1; // because lastit has to be taken into account.
+ // for "it", there's a count++ later
+ }
+
+ // the following will work even on start-new-group,
+ // because lastit will be "untouched", and that's why
+ // still be initalized to "false"
+ it->ausweich=!lastit->ausweich;
+
+ count++;
+ }
+ else
+ {
+ if (groupbegin!=invalid) //this is the first item which
+ { //doesn't belong to the previous group any more
+ if (count%2 == 0) //count is even?
+ if (modulo(groupbegin->pos.height, 2) == AUSWEICHEN_BEVORZUGT)
+ for (set<FloItem, floComp>::iterator tmp=groupbegin; tmp!=it; tmp++)
+ tmp->ausweich=!tmp->ausweich;
+
+ groupbegin=invalid;
+ }
+ // else: everything is ok :)
+ }
+ }
+
+ lastit=it;
+ }
+
+ // this could be the case if the last processed item before end()
+ // still belonged to a group. finalize this last group as well:
+ if (groupbegin!=invalid)
+ {
+ if (count%2 == 0) //count is even?
+ if (modulo(groupbegin->pos.height, 2) == AUSWEICHEN_BEVORZUGT)
+ for (set<FloItem, floComp>::iterator tmp=groupbegin; tmp!=curr_items.end(); tmp++)
+ tmp->ausweich=!tmp->ausweich;
+ }
+ // else: everything is ok :)
+
+
+
+
+
+ // phase 3: group notes by their length and ------------------------
+ // find out appropriate stem directions
+group_them_again:
+ map<int, cumulative_t> lengths;
+ bool has_whole=false;
+
+ // find out which note lengths are present at that time
+ for (set<FloItem, floComp>::iterator it=curr_items.begin(); it!=curr_items.end(); it++)
+ if (it->type==FloItem::NOTE)
+ lengths[it->len].add(it->pos.height);
+
+ cout << "note lengths at that time are:";
+ for (map<int, cumulative_t>::iterator it=lengths.begin(); it!=lengths.end(); it++)
+ cout << it->first << "("<< it->second.mean() <<") ";
+ cout << endl;
+
+ if (lengths.erase(0)) // in case "0" is in the set, erase it
+ has_whole=true; // but remember there were whole notes
+
+ if (lengths.size()==0)
+ {
+ cout << "no notes other than wholes, or no notes at all. we can relax" << endl;
+ }
+ else if (lengths.size()==1)
+ {
+ pair<const int, cumulative_t>& group=*(lengths.begin());
+ stem_t stem;
+ int shift=0;
+ cout << "only one non-whole note group (len="<<group.first<<") at height="<<group.second.mean()<< endl;
+
+ if (group.second.mean()>=6)
+ {
+ stem=DOWNWARDS;
+ if (has_whole)
+ shift=-1;
+ }
+ else
+ {
+ stem=UPWARDS;
+ if (has_whole)
+ shift=1;
+ }
+
+ // for each note in that group
+ for (set<FloItem, floComp>::iterator it=curr_items.begin(); it!=curr_items.end(); it++)
+ if ( (it->type==FloItem::NOTE) && (it->len==group.first) )
+ {
+ it->stem=stem;
+ it->shift=shift;
+ }
+ }
+ else if (lengths.size()==2)
+ {
+ map<int, cumulative_t>::iterator it=lengths.begin();
+ pair<const int, cumulative_t>& group1=*it;
+ it++;
+ pair<const int, cumulative_t>& group2=*it;
+ stem_t stem1, stem2;
+ int shift1=0, shift2=0;
+ cout << "two non-whole note group: len="<<group1.first<<" at height="<<group1.second.mean()<<" and len="<<group2.first<<" at height="<<group2.second.mean()<< endl;
+
+ if (group1.second.mean()<group2.second.mean())
+ {
+ stem1=DOWNWARDS;
+ stem2=UPWARDS;
+ shift1=-1;
+ if (has_whole)
+ shift2=1;
+ }
+ else
+ {
+ stem1=UPWARDS;
+ stem2=DOWNWARDS;
+ shift2=-1;
+ if (has_whole)
+ shift1=1;
+ }
+
+ // for each note in group1
+ for (set<FloItem, floComp>::iterator it=curr_items.begin(); it!=curr_items.end(); it++)
+ if ( (it->type==FloItem::NOTE) && (it->len==group1.first) )
+ {
+ it->stem=stem1;
+ it->shift=shift1;
+ }
+
+ // for each note in group2
+ for (set<FloItem, floComp>::iterator it=curr_items.begin(); it!=curr_items.end(); it++)
+ if ( (it->type==FloItem::NOTE) && (it->len==group2.first) )
+ {
+ it->stem=stem2;
+ it->shift=shift2;
+ }
+ }
+ else //more than 2 groups
+ {
+ //at this time, there are no iterators pointing to curr_items.
+ //this means, we can erase and insert safely into curr_items here.
+
+ //group1 contains the longer notes, group2 the shorter
+
+ int group1_n=lengths.size()/2; //round down
+ int group2_n=lengths.size()-group1_n;
+
+ int group1_len, group2_len;
+ int group1_len_ticks, group2_len_ticks;
+
+
+ map<int, cumulative_t>::iterator lit=lengths.begin();
+ for (int i=0;i<group1_n-1;i++) lit++; //go to the group1_n-th entry
+ group1_len=lit->first;
+ for (int i=0;i<group2_n;i++) lit++; //go to the (group1_n+group2_n)-th entry (i.e., the last before end() )
+ group2_len=lit->first;
+
+ group1_len_ticks=calc_len(group1_len,0);
+ group2_len_ticks=calc_len(group2_len,0);
+
+ cout << "we have "<<lengths.size()<<" groups. putting the "<<group1_n<<" longest and the "<<group2_n<<"shortest groups together"<<endl;
+ cout << "\tgroup1 will have len="<<group1_len<<" ("<<group1_len_ticks<<" ticks), group2 will have len="<<group2_len<<" ("<<group2_len_ticks<<" ticks)"<<endl;
+
+ for (set<FloItem, floComp>::iterator it=curr_items.begin(); it!=curr_items.end();)
+ if (it->type==FloItem::NOTE)
+ {
+ //if *it belongs to group1 and has not already its destination length
+ cout << "\tprocessing note-item with len="<<it->len<<endl;
+ if (it->len<group1_len)
+ {
+ cout << "\t\thas to be changed to fit into group 1" << endl;
+ FloItem tmp=*it;
+ curr_items.erase(it++);
+
+ int len_ticks_remaining=calc_len(tmp.len, tmp.dots)-group1_len_ticks;
+ bool tied_note=tmp.tied;
+
+
+ //shorten the current item to it's group's length
+ tmp.len=group1_len;
+ tmp.dots=0;
+ tmp.tied=true;
+ curr_items.insert(tmp);
+
+ //create items for the remaining lengths (and a note_END for the just created shortened note)
+ int t=it2->first+group1_len_ticks;
+
+ itemlist[t].insert( FloItem(FloItem::NOTE_END,tmp.pos,0,0) );
+
+ list<note_len_t> lens=parse_note_len(len_ticks_remaining,t-last_measure,emphasize_list,parent->quant_power2(),true,true);
+ unsigned tmppos=t;
+ int n_lens=lens.size();
+ int count=0;
+ for (list<note_len_t>::iterator x=lens.begin(); x!=lens.end(); x++)
+ {
+ cout << "\t\twhile regrouping: partial note with len="<<x->len<<", dots="<<x->dots<<endl;
+ count++;
+
+ bool tie;
+
+ if (count<n_lens)
+ tie=true; // all notes except the last are always tied
+ else
+ tie=tied_note; // only the last respects tied_note
+
+ itemlist[tmppos].insert( FloItem(FloItem::NOTE, tmp.pos,x->len,x->dots, tie, tmp.begin_tick, tmp.source_part, tmp.source_event) );
+ tmppos+=calc_len(x->len,x->dots);
+ itemlist[tmppos].insert( FloItem(FloItem::NOTE_END, tmp.pos,0,0) );
+ }
+
+ }
+ //else if *it belongs to group2 and has not already its destination length
+ else if ((it->len<group2_len) && (it->len>group1_len))
+ {
+ cout << "\t\thas to be changed to fit into group 2" << endl;
+
+ FloItem tmp=*it;
+ curr_items.erase(it++);
+
+ int len_ticks_remaining=calc_len(tmp.len, tmp.dots)-group2_len_ticks;
+ bool tied_note=tmp.tied;
+
+
+ //shorten the current item to it's group's length
+ tmp.len=group2_len;
+ tmp.dots=0;
+ tmp.tied=true;
+ curr_items.insert(tmp);
+
+ //create items for the remaining lengths (and a note_END for the just created shortened note)
+ int t=it2->first+group2_len_ticks;
+
+ itemlist[t].insert( FloItem(FloItem::NOTE_END,tmp.pos,0,0) );
+
+ list<note_len_t> lens=parse_note_len(len_ticks_remaining,t-last_measure,emphasize_list,parent->quant_power2(),true,true);
+ unsigned tmppos=t;
+ int n_lens=lens.size();
+ int count=0;
+ for (list<note_len_t>::iterator x=lens.begin(); x!=lens.end(); x++)
+ {
+ cout << "\t\twhile regrouping: partial note with len="<<x->len<<", dots="<<x->dots<<endl;
+ count++;
+
+ bool tie;
+
+ if (count<n_lens)
+ tie=true; // all notes except the last are always tied
+ else
+ tie=tied_note; // only the last respects tied_note
+
+ itemlist[tmppos].insert( FloItem(FloItem::NOTE,tmp.pos,x->len,x->dots, tie, tmp.begin_tick, tmp.source_part, tmp.source_event) );
+ tmppos+=calc_len(x->len,x->dots);
+ itemlist[tmppos].insert( FloItem(FloItem::NOTE_END,tmp.pos,0,0) );
+ }
+
+ }
+ else //nothing to do?
+ {
+ cout << "\t\tnothing to do" << endl;
+ it++;
+ }
+ }
+ else
+ it++;
+
+ goto group_them_again; //do it again
+ }
+
+ }
+}
+
+//draw a pixmap centered
+void ScoreCanvas::draw_pixmap(QPainter& p, int x, int y, const QPixmap& pm)
+{
+ cout << "drawing pixmap width size="<<pm.width()<<"/"<<pm.height()<<" at "<<x<<"/"<<y<<endl;
+ p.drawPixmap(x-pm.width()/2,y-pm.height()/2,pm);
+}
+
+QRect bbox_center(int x, int y, const QSize& size)
+{
+ //why x-foo/2+foo? because due to integer divisions,
+ // x-foo/2+foo can be smaller than x+foo/2!
+ return QRect(x-size.width()/2,y-size.height()/2,size.width(),size.height());
+}
+
+QRect FloItem::bbox() const
+{
+ return bbox_center(x,y,pix->size());
+}
+
+void ScoreCanvas::draw_note_lines(QPainter& p, int y)
+{
+ int xend=width();
+
+ p.setPen(Qt::black);
+
+ for (int i=0;i<5;i++)
+ p.drawLine(0,y + i*YLEN - 2*YLEN,xend,y + i*YLEN - 2*YLEN);
+}
+
+
+void staff_t::calc_item_pos()
+{
+ key_enum curr_key=KEY_C; //this has to be KEY_C or KEY_C_B and nothing else,
+ //because only with these two keys the next (initial)
+ //key signature is properly drawn.
+ int pos_add=0;
+
+ for (ScoreItemList::iterator it2=itemlist.begin(); it2!=itemlist.end(); it2++)
+ {
+ for (set<FloItem, floComp>::iterator it=it2->second.begin(); it!=it2->second.end();it++)
+ {
+ it->x=it2->first * parent->pixels_per_whole()/TICKS_PER_WHOLE +pos_add;
+ //if this changes, also change the line(s) with YLEN (but not all). don't change it.
+ it->y=2*YLEN - (it->pos.height-2)*YLEN/2;
+
+ if (it->type==FloItem::NOTE)
+ {
+ it->x+=parent->note_x_indent() + it->shift*NOTE_SHIFT;
+
+ switch (it->len)
+ {
+ case 0: it->pix=pix_whole; break;
+ case 1: it->pix=pix_half; break;
+ default: it->pix=pix_quarter; break;
+ }
+
+ it->stem_x=it->x;
+
+ if (it->ausweich)
+ {
+ if ((it->stem==UPWARDS) || (it->len==0))
+ it->x += it->pix->width()-1; //AUSWEICH_X
+ else
+ it->x -= it->pix->width()-1; //AUSWEICH_X
+ }
+
+ //if there's a tie, try to find the tie's destination and set is_tie_dest
+ if (it->tied)
+ {
+ set<FloItem, floComp>::iterator dest;
+ set<FloItem, floComp>& desttime = itemlist[it2->first+calc_len(it->len,it->dots)];
+ for (dest=desttime.begin(); dest!=desttime.end();dest++)
+ if ((dest->type==FloItem::NOTE) && (dest->pos==it->pos))
+ {
+ dest->is_tie_dest=true;
+ dest->tie_from_x=it->x;
+ break;
+ }
+
+ if (dest==desttime.end())
+ cout << "THIS SHOULD NEVER HAPPEN: did not find destination note for tie!" << endl;
+ }
+ }
+ else if (it->type==FloItem::REST)
+ {
+ switch (it->len)
+ {
+ case 0: it->pix=pix_r1; break;
+ case 1: it->pix=pix_r2; break;
+ case 2: it->pix=pix_r4; break;
+ case 3: it->pix=pix_r8; break;
+ case 4: it->pix=pix_r16; break;
+ }
+
+ it->x+=parent->note_x_indent() + (it->ausweich ? REST_AUSWEICH_X : 0); //AUSWEICH_X
+ }
+ else if (it->type==FloItem::BAR)
+ {
+ //nothing to do :)
+ }
+ else if (it->type==FloItem::TIME_SIG)
+ {
+ int add=calc_timesig_width(it->num, it->denom);
+ pos_add+=add;
+ }
+ else if (it->type==FloItem::KEY_CHANGE)
+ {
+ key_enum new_key=it->key;
+
+ list<int> aufloes_list=calc_accidentials(curr_key, clef, new_key);
+ list<int> new_acc_list=calc_accidentials(new_key, clef);
+
+ int n_acc_drawn=aufloes_list.size() + new_acc_list.size();
+ pos_add+=n_acc_drawn*KEYCHANGE_ACC_DIST+ KEYCHANGE_ACC_LEFTDIST+ KEYCHANGE_ACC_RIGHTDIST;
+
+ curr_key=new_key;
+ }
+ }
+ }
+}
+
+void ScoreCanvas::calc_pos_add_list()
+{
+ using AL::sigmap;
+ using AL::iSigEvent;
+
+
+ pos_add_list.clear();
+
+ //process time signatures
+ for (iSigEvent it=sigmap.begin(); it!=sigmap.end(); it++)
+ pos_add_list[it->second->tick]+=calc_timesig_width(it->second->sig.z, it->second->sig.n);
+
+
+ //process key changes
+ key_enum curr_key=KEY_C; //this has to be KEY_C or KEY_C_B and nothing else,
+ //because only with these two keys the next (initial)
+ //key signature is properly calculated.
+ for (iKeyEvent it=keymap.begin(); it!=keymap.end(); it++)
+ {
+ key_enum new_key=it->second.key;
+ list<int> aufloes_list=calc_accidentials(curr_key, VIOLIN, new_key); //clef argument is unneccessary
+ list<int> new_acc_list=calc_accidentials(new_key, VIOLIN); //in this case
+ int n_acc_drawn=aufloes_list.size() + new_acc_list.size();
+ pos_add_list[it->second.tick]+=n_acc_drawn*KEYCHANGE_ACC_DIST+ KEYCHANGE_ACC_LEFTDIST+ KEYCHANGE_ACC_RIGHTDIST;
+
+ curr_key=new_key;
+ }
+}
+
+void ScoreCanvas::draw_items(QPainter& p, int y, staff_t& staff, int x1, int x2)
+{
+ int from_tick, to_tick;
+ ScoreItemList::iterator from_it, to_it;
+
+ //drawing too much isn't bad. drawing too few is.
+
+ from_tick=x_to_tick(x1);
+ from_it=staff.itemlist.lower_bound(from_tick);
+ //from_it now contains the first time which is fully drawn
+ //however, the previous beat could still be relevant, when it's
+ //partly drawn. so we decrement from_it
+ if (from_it!=staff.itemlist.begin()) from_it--;
+
+ //decrement until we're at a time with a bar
+ //otherwise, drawing accidentials will be broken
+ while (from_it!=staff.itemlist.begin() && from_it->second.find(FloItem(FloItem::BAR))==from_it->second.end())
+ from_it--;
+
+
+ to_tick=x_to_tick(x2);
+ to_it=staff.itemlist.upper_bound(to_tick);
+ //to_it now contains the first time which is not drawn at all any more
+ //however, a tie from 1:04 to 2:01 is stored in 2:01, not in 1:04,
+ //so for drawing ties, we need to increment to_it, so that the
+ //"first time not drawn at all any more" is the last which gets
+ //actually drawn.
+ if (to_it!=staff.itemlist.end()) to_it++; //do one tick more than neccessary. this will draw ties
+
+ draw_items(p,y, staff, from_it, to_it);
+}
+
+void ScoreCanvas::draw_items(QPainter& p, int y, staff_t& staff)
+{
+ draw_items(p,y, staff,x_pos,x_pos+width()-x_left);
+}
+
+void ScoreCanvas::draw_items(QPainter& p, int y_offset, staff_t& staff, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it)
+{
+ // init accidentials properly
+ vorzeichen_t curr_accidential[7];
+ vorzeichen_t default_accidential[7];
+ key_enum curr_key;
+
+ curr_key=key_at_tick(from_it->first);
+ list<int> new_acc_list=calc_accidentials(curr_key, staff.clef);
+ vorzeichen_t new_accidential = is_sharp_key(curr_key) ? SHARP : B;
+
+ for (int i=0;i<7;i++)
+ curr_accidential[i]=default_accidential[i]=NONE;
+
+ for (list<int>::iterator acc_it=new_acc_list.begin(); acc_it!=new_acc_list.end(); acc_it++)
+ default_accidential[*acc_it % 7]=curr_accidential[*acc_it % 7]=new_accidential;
+
+
+
+ for (ScoreItemList::iterator it2=from_it; it2!=to_it; it2++)
+ {
+ cout << "at t="<<it2->first << endl;
+
+ int upstem_y1 = -1, upstem_y2=-1, upstem_x=-1, upflag=-1;
+ int downstem_y1 = -1, downstem_y2=-1, downstem_x=-1, downflag=-1;
+
+ for (set<FloItem, floComp>::iterator it=it2->second.begin(); it!=it2->second.end();it++)
+ {
+ if (it->type==FloItem::NOTE)
+ {
+ cout << "\tNOTE at line"<<it->pos.height<<" with acc.="<<it->pos.vorzeichen<<", len="<<pow(2,it->len);
+ for (int i=0;i<it->dots;i++) cout << ".";
+ cout << " , stem=";
+ if (it->stem==UPWARDS)
+ cout << "UPWARDS";
+ else
+ cout << "DOWNWARDS";
+
+ cout << " , shift="<<it->shift<<", ausweich="<<it->ausweich<<", ";
+ if (!it->tied) cout << "un";
+ cout << "tied, is_tie_dest="<<it->is_tie_dest<<endl;
+
+ if (it->len!=0) //only for non-whole notes the stems are relevant!
+ {
+ if (it->stem==UPWARDS)
+ {
+ if (upstem_y1 == -1)
+ upstem_y1=it->y;
+
+ upstem_y2=it->y;
+
+
+ if ((upflag!=-1) && (upflag!=it->len))
+ cout << "WARNING: THIS SHOULD NEVER HAPPEN: upflag != this->flag" << endl;
+ upflag=it->len;
+
+ if ((upstem_x!=-1) && (upstem_x!=it->stem_x ))
+ cout << "WARNING: THIS SHOULD NEVER HAPPEN: upstem_x != x_result" << endl;
+ upstem_x=it->stem_x;
+ }
+ else
+ {
+ if (downstem_y1 == -1)
+ downstem_y1=it->y;
+
+ downstem_y2=it->y;
+
+
+ if ((downflag!=-1) && (downflag!=it->len))
+ cout << "WARNING: THIS SHOULD NEVER HAPPEN: downflag != this->flag" << endl;
+ downflag=it->len;
+
+ if ((downstem_x!=-1) && (downstem_x!=it->stem_x))
+ cout << "WARNING: THIS SHOULD NEVER HAPPEN: downstem_x != x_result" << endl;
+ downstem_x=it->stem_x; //important: before the below calculation!
+ }
+ }
+
+
+ if (it->pos.height <= 0) //we need auxiliary lines on the bottom?
+ {
+ p.setPen(Qt::black);
+ for (int i=0; i>=it->pos.height; i-=2)
+ p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,y_offset + 2*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,y_offset + 2*YLEN - (i-2)*YLEN/2);
+ }
+ else if (it->pos.height >= 12) //we need auxiliary lines on the top?
+ {
+ p.setPen(Qt::black);
+ for (int i=12; i<=it->pos.height; i+=2)
+ p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,y_offset + 2*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,y_offset + 2*YLEN - (i-2)*YLEN/2);
+ }
+
+ it->is_active= ( (song->cpos() >= it->source_event->tick() + it->source_part->tick()) &&
+ (song->cpos() < it->source_event->endTick() + it->source_part->tick()) );
+
+
+ int color_index;
+ switch (coloring_mode)
+ {
+ case COLOR_MODE_BLACK:
+ color_index=BLACK_PIXMAP;
+ break;
+
+ case COLOR_MODE_PART:
+ color_index=it->source_part->colorIndex();
+ break;
+
+ case COLOR_MODE_PITCH: //TODO
+ break;
+ }
+ if (audio->isPlaying() && it->is_active)
+ color_index=HIGHLIGHTED_PIXMAP;
+
+
+ draw_pixmap(p,it->x -x_pos+x_left,y_offset + it->y,it->pix[color_index]);
+ //TODO FINDMICH maybe draw a margin around bright colors?
+ //maybe draw the default color in black?
+
+ //draw dots
+
+ int x_dot=DOT_XBEGIN;
+ int y_dot;
+ if (modulo(it->pos.height, 2) == 0) //note is on a line?
+ y_dot=YLEN * 0.33; // actually 0.5, but that would be _exactly_ in the space
+ else //note is between two lines?
+ y_dot=YLEN * 0.1;
+
+ if (it->stem==DOWNWARDS)
+ y_dot=-y_dot;
+ //else y_dot=y_dot;
+
+ for (int i=0;i<it->dots;i++)
+ {
+ draw_pixmap(p,it->x+x_dot -x_pos+x_left,y_offset + it->y+y_dot,pix_dot[color_index]);
+ x_dot+=DOT_XDIST;
+ }
+
+
+
+ //draw accidentials
+ if (it->pos.vorzeichen != curr_accidential[modulo(it->pos.height,7)])
+ {
+ QPixmap* acc_pix;
+ switch (it->pos.vorzeichen)
+ {
+ case NONE: acc_pix=pix_noacc; break;
+ case SHARP: acc_pix=pix_sharp; break;
+ case B: acc_pix=pix_b; break;
+ }
+ draw_pixmap(p,it->x-ACCIDENTIAL_DIST -x_pos+x_left,y_offset + it->y, acc_pix[color_index]);
+
+ curr_accidential[modulo(it->pos.height,7)]=it->pos.vorzeichen;
+ }
+
+
+ //if needed, draw tie
+ if (it->is_tie_dest)
+ {
+ cout << "drawing tie" << endl;
+ draw_tie(p,it->tie_from_x-x_pos+x_left,it->x -x_pos+x_left,y_offset + it->y, (it->len==0) ? true : (it->stem==DOWNWARDS) , config.partColors[color_index]);
+ // in english: "if it's a whole note, tie is upwards (true). if not, tie is upwards if
+ // stem is downwards and vice versa"
+ }
+ }
+ else if (it->type==FloItem::REST)
+ {
+ cout << "\tREST at line"<<it->pos.height<<" with len="<<pow(2,it->len);
+ for (int i=0;i<it->dots;i++) cout << ".";
+ cout << " , ausweich="<<it->ausweich<<endl;
+
+ draw_pixmap(p,it->x -x_pos+x_left,y_offset + it->y,*it->pix);
+
+
+ //draw dots
+
+ int x_dot=DOT_XBEGIN_REST;
+ int y_dot;
+ if (modulo(it->pos.height, 2) == 0) //rest is on a line?
+ y_dot=YLEN * 0.33; // actually 0.5, but that would be _exactly_ in the space
+ else //note is between two lines?
+ y_dot=YLEN * 0.1;
+
+ if (it->len!=0) // all rests except the whole are treated as
+ y_dot=-y_dot; // if they had a downwards stem
+
+ for (int i=0;i<it->dots;i++)
+ {
+ draw_pixmap(p,it->x+x_dot -x_pos+x_left,y_offset + it->y+y_dot,pix_dot[BLACK_PIXMAP]);
+ x_dot+=DOT_XDIST;
+ }
+ }
+ else if (it->type==FloItem::BAR)
+ {
+ cout << "\tBAR" << endl;
+
+ p.setPen(Qt::black);
+ p.drawLine(it->x -x_pos+x_left,y_offset -2*YLEN,it->x -x_pos+x_left,y_offset +2*YLEN);
+
+ for (int i=0;i<7;i++)
+ curr_accidential[i]=default_accidential[i];
+ }
+ else if (it->type==FloItem::TIME_SIG)
+ {
+ cout << "\tTIME SIGNATURE: "<<it->num<<"/"<<it->denom<<endl;
+
+ draw_timesig(p, it->x - x_pos+x_left, y_offset, it->num, it->denom);
+ }
+ else if (it->type==FloItem::KEY_CHANGE)
+ {
+ key_enum new_key=it->key;
+ cout << "\tKEY CHANGE: from "<<curr_key<<" to "<<new_key<<endl;
+
+ list<int> aufloes_list=calc_accidentials(curr_key, staff.clef, new_key);
+ list<int> new_acc_list=calc_accidentials(new_key, staff.clef);
+
+ // vorzeichen aus curr_key auflösen
+ draw_accidentials(p, it->x + KEYCHANGE_ACC_LEFTDIST - x_pos+x_left, y_offset, aufloes_list, pix_noacc[BLACK_PIXMAP]);
+
+ // alle vorzeichen aus new_key zeichnen
+ QPixmap* pix = is_sharp_key(new_key) ? &pix_sharp[BLACK_PIXMAP] : &pix_b[BLACK_PIXMAP];
+ vorzeichen_t new_accidential = is_sharp_key(new_key) ? SHARP : B;
+
+ draw_accidentials(p, it->x + aufloes_list.size()*KEYCHANGE_ACC_DIST + KEYCHANGE_ACC_LEFTDIST - x_pos+x_left, y_offset, new_acc_list, *pix);
+
+ for (int i=0;i<7;i++)
+ curr_accidential[i]=default_accidential[i]=NONE;
+
+ for (list<int>::iterator acc_it=new_acc_list.begin(); acc_it!=new_acc_list.end(); acc_it++)
+ default_accidential[*acc_it % 7]=curr_accidential[*acc_it % 7]=new_accidential;
+
+ curr_key=new_key;
+ }
+ }
+
+ p.setPen(Qt::black);
+ //note: y1 is bottom, y2 is top!
+ if (upstem_x!=-1)
+ {
+ upstem_x=upstem_x-pix_quarter[0].width()/2 +pix_quarter[0].width() -1;
+ p.drawLine(upstem_x -x_pos+x_left, y_offset + upstem_y1, upstem_x -x_pos+x_left, y_offset + upstem_y2-STEM_LEN);
+
+ if (upflag>=3) //if the note needs a flag
+ p.drawPixmap(upstem_x -x_pos+x_left,y_offset + upstem_y2-STEM_LEN,pix_flag_up[upflag-3]);
+ }
+ if (downstem_x!=-1)
+ {
+ downstem_x=downstem_x-pix_quarter[0].width()/2;
+ p.drawLine(downstem_x -x_pos+x_left, y_offset + downstem_y1+STEM_LEN, downstem_x -x_pos+x_left, y_offset + downstem_y2);
+
+ if (downflag>=3) //if the note needs a flag
+ p.drawPixmap(downstem_x -x_pos+x_left,y_offset + downstem_y1+STEM_LEN-pix_flag_down[downflag-3].height(),pix_flag_down[downflag-3]);
+ }
+ }
+}
+
+bool ScoreCanvas::need_redraw_for_hilighting()
+{
+ for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++)
+ if (need_redraw_for_hilighting(it->itemlist)) return true;
+
+ return false;
+}
+
+bool ScoreCanvas::need_redraw_for_hilighting(ScoreItemList& itemlist)
+{
+ return need_redraw_for_hilighting(itemlist, x_pos,x_pos+width()-x_left);
+}
+
+bool ScoreCanvas::need_redraw_for_hilighting(ScoreItemList& itemlist, int x1, int x2)
+{
+ int from_tick, to_tick;
+ ScoreItemList::iterator from_it, to_it;
+
+ from_tick=x_to_tick(x1);
+ from_it=itemlist.lower_bound(from_tick);
+ //from_it now contains the first time which is fully drawn
+ //however, the previous beat could still be relevant, when it's
+ //partly drawn. so we decrement from_it
+ if (from_it!=itemlist.begin()) from_it--;
+
+ to_tick=x_to_tick(x2);
+ to_it=itemlist.upper_bound(to_tick);
+ //to_it now contains the first time which is not drawn at all any more
+
+ return need_redraw_for_hilighting(from_it, to_it);
+}
+
+bool ScoreCanvas::need_redraw_for_hilighting(ScoreItemList::iterator from_it, ScoreItemList::iterator to_it)
+{
+ //if we aren't playing, there will never be a need for redrawing due to highlighting things
+ if (audio->isPlaying()==false)
+ return false;
+
+ for (ScoreItemList::iterator it2=from_it; it2!=to_it; it2++)
+ for (set<FloItem, floComp>::iterator it=it2->second.begin(); it!=it2->second.end();it++)
+ if (it->type==FloItem::NOTE)
+ {
+ bool is_active= ( (song->cpos() >= it->source_event->tick() + it->source_part->tick()) &&
+ (song->cpos() < it->source_event->endTick() + it->source_part->tick()) );
+ if (it->is_active != is_active)
+ return true;
+ }
+
+ return false;
+}
+
+int clef_height(clef_t clef)
+{
+ switch (clef) //CLEF_MARKER
+ {
+ case VIOLIN: return 4;
+ case BASS: return 8;
+ default:
+ cout << "WARNING: ILLEGAL FUNCTION CALL in clef_height()" << endl;
+ return 6;
+ }
+}
+
+#define TIMESIG_LEFTMARGIN 5
+#define TIMESIG_RIGHTMARGIN 5
+#define DIGIT_YDIST 9
+#define DIGIT_WIDTH 12
+
+#define CLEF_LEFTMARGIN 5
+#define CLEF_RIGHTMARGIN 5
+
+void ScoreCanvas::draw_preamble(QPainter& p, int y_offset, clef_t clef)
+{
+ int x_left_old=x_left;
+ int tick=x_to_tick(x_pos);
+
+ // draw clef --------------------------------------------------------
+ QPixmap* pix_clef= (clef==BASS) ? pix_clef_bass : pix_clef_violin;
+ int y_coord=2*YLEN - ( clef_height(clef) -2)*YLEN/2;
+
+ draw_pixmap(p,CLEF_LEFTMARGIN + pix_clef->width()/2,y_offset + y_coord,*pix_clef);
+
+ x_left= CLEF_LEFTMARGIN + pix_clef->width() + CLEF_RIGHTMARGIN;
+
+
+ // draw accidentials ------------------------------------------------
+ if (preamble_contains_keysig)
+ {
+ x_left+=KEYCHANGE_ACC_LEFTDIST;
+
+ key_enum key=key_at_tick(tick);
+ QPixmap* pix_acc=is_sharp_key(key) ? &pix_sharp[BLACK_PIXMAP] : &pix_b[BLACK_PIXMAP];
+ list<int> acclist=calc_accidentials(key,clef);
+
+ draw_accidentials(p,x_left, y_offset, acclist ,*pix_acc);
+
+ x_left+=acclist.size()*KEYCHANGE_ACC_DIST + KEYCHANGE_ACC_RIGHTDIST;
+ }
+
+
+ // draw time signature ----------------------------------------------
+ if (preamble_contains_timesig)
+ {
+ x_left+=TIMESIG_LEFTMARGIN;
+
+ timesig_t timesig=timesig_at_tick(tick);
+
+ draw_timesig(p, x_left, y_offset, timesig.num, timesig.denom);
+
+ x_left+=calc_timesig_width(timesig.num, timesig.denom)+TIMESIG_RIGHTMARGIN;
+ }
+
+ // draw bar ---------------------------------------------------------
+ p.setPen(Qt::black);
+ p.drawLine(x_left,y_offset -2*YLEN,x_left,y_offset +2*YLEN);
+
+
+ if (x_left_old!=x_left)
+ emit viewport_width_changed(viewport_width());
+}
+
+
+void ScoreCanvas::draw_timesig(QPainter& p, int x, int y_offset, int num, int denom)
+{
+ int num_width=calc_number_width(num);
+ int denom_width=calc_number_width(denom);
+ int width=((num_width > denom_width) ? num_width : denom_width);
+ int num_indent=(width-num_width)/2 + TIMESIG_LEFTMARGIN;
+ int denom_indent=(width-denom_width)/2 + TIMESIG_LEFTMARGIN;
+
+ draw_number(p, x+num_indent, y_offset -DIGIT_YDIST, num);
+ draw_number(p, x+denom_indent, y_offset +DIGIT_YDIST, denom);
+}
+
+int calc_timesig_width(int num, int denom)
+{
+ int num_width=calc_number_width(num);
+ int denom_width=calc_number_width(denom);
+ int width=((num_width > denom_width) ? num_width : denom_width);
+ return width+TIMESIG_LEFTMARGIN+TIMESIG_RIGHTMARGIN;
+}
+
+int calc_number_width(int n)
+{
+ string str=IntToStr(n);
+ return (str.length()*DIGIT_WIDTH);
+}
+
+void ScoreCanvas::draw_number(QPainter& p, int x, int y, int n)
+{
+ string str=IntToStr(n);
+ int curr_x=x+DIGIT_WIDTH/2;
+
+ for (size_t i=0;i<str.length(); i++)
+ {
+ draw_pixmap(p, curr_x, y, pix_num[str[i]-'0']);
+ curr_x+=DIGIT_WIDTH;
+ }
+}
+
+
+void ScoreCanvas::draw(QPainter& p, const QRect&)
+{
+ cout <<"now in ScoreCanvas::draw"<<endl;
+
+
+
+ p.setPen(Qt::black);
+
+ for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++)
+ {
+ //TODO: maybe only draw visible staves?
+ draw_note_lines(p,it->y_draw - y_pos);
+ draw_preamble(p,it->y_draw - y_pos, it->clef);
+ p.setClipRect(x_left+1,0,p.device()->width(),p.device()->height());
+ draw_items(p,it->y_draw - y_pos, *it);
+ p.setClipping(false);
+ }
+}
+
+
+list<int> calc_accidentials(key_enum key, clef_t clef, key_enum next_key)
+{
+ list<int> result;
+
+ int violin_sharp_pos[]={10,7,11,8,5,9,6}; //CLEF_MARKER
+ int violin_b_pos[]={6,9,5,8,4,7,3};
+ int bass_sharp_pos[]={8,5,9,6,3,7,4};
+ int bass_b_pos[]={4,7,3,6,2,5,1};
+
+ int* accidential_pos;
+
+ switch (clef)
+ {
+ case VIOLIN: accidential_pos = is_sharp_key(key) ? violin_sharp_pos : violin_b_pos; break;
+ case BASS: accidential_pos = is_sharp_key(key) ? bass_sharp_pos : bass_b_pos; break;
+ }
+
+ int begin=0;
+
+ if (is_sharp_key(key)==is_sharp_key(next_key)) //same kind of key (both b or both #)?
+ begin=n_accidentials(next_key);
+ else
+ begin=0;
+
+
+ int end=n_accidentials(key);
+
+ for (int i=begin; i<end; i++)
+ result.push_back(accidential_pos[i]);
+
+ return result;
+}
+
+
+
+
+int ScoreCanvas::tick_to_x(int t)
+{
+ int x=t*pixels_per_whole()/TICKS_PER_WHOLE;
+
+ for (std::map<int,int>::iterator it=pos_add_list.begin(); it!=pos_add_list.end() && it->first<=t; it++)
+ x+=it->second;
+
+ return x;
+}
+
+int ScoreCanvas::calc_posadd(int t)
+{
+ int result=0;
+
+ for (std::map<int,int>::iterator it=pos_add_list.begin(); it!=pos_add_list.end() && it->first<t; it++)
+ result+=it->second;
+
+ return result;
+}
+
+//doesn't round mathematically correct, but i don't think this
+//will be a problem, because a tick is pretty small
+int ScoreCanvas::x_to_tick(int x)
+{
+ int t=TICKS_PER_WHOLE * x/pixels_per_whole();
+ int min_t=0;
+
+ cout << "t="<<t<<endl;
+
+ for (std::map<int,int>::iterator it=pos_add_list.begin(); it!=pos_add_list.end() && it->first<t; it++)
+ {
+ cout << "at pos_add event at t="<<it->first<<", add="<<it->second<<endl;
+ min_t=it->first;
+ x-=it->second;
+ t=TICKS_PER_WHOLE * x/pixels_per_whole();
+ }
+
+ return t > min_t ? t : min_t;
+}
+
+key_enum ScoreCanvas::key_at_tick(int t_)
+{
+ unsigned int t= (t_>=0) ? t_ : 0;
+
+ return keymap.keyAtTick(t);
+}
+
+timesig_t ScoreCanvas::timesig_at_tick(int t_)
+{
+ timesig_t tmp;
+ unsigned int t= (t_>=0) ? t_ : 0;
+
+ AL::sigmap.timesig(t, tmp.num, tmp.denom);
+
+ return tmp;
+}
+
+int ScoreCanvas::height_to_pitch(int h, clef_t clef)
+{
+ int foo[]={0,2,4,5,7,9,11};
+
+ switch(clef) //CLEF_MARKER
+ {
+ case VIOLIN: return foo[modulo(h,7)] + ( divide_floor(h,7)*12 ) + 60;
+ case BASS: return foo[modulo((h-5),7)] + ( divide_floor(h-5,7)*12 ) + 48;
+ default:
+ cout << "WARNING: THIS SHOULD NEVER HAPPEN: unknown clef in height_to_pitch" << endl;
+ return 60;
+ }
+}
+
+int ScoreCanvas::height_to_pitch(int h, clef_t clef, key_enum key)
+{
+ int add=0;
+
+ list<int> accs=calc_accidentials(key,clef);
+
+ for (list<int>::iterator it=accs.begin(); it!=accs.end(); it++)
+ {
+ if (modulo(*it,7) == modulo(h,7))
+ {
+ add=is_sharp_key(key) ? 1 : -1;
+ break;
+ }
+ }
+
+ return height_to_pitch(h,clef)+add;
+}
+
+int ScoreCanvas::y_to_height(int y)
+{
+ return int(nearbyint(float(2*YLEN - y)*2.0/YLEN))+2 ;
+}
+
+int ScoreCanvas::y_to_pitch(int y, int t, clef_t clef)
+{
+ return height_to_pitch(y_to_height(y), clef, key_at_tick(t));
+}
+
+
+#define DRAG_INIT_DISTANCE 5
+
+void ScoreCanvas::mousePressEvent (QMouseEvent* event)
+{
+ // den errechneten tick immer ABrunden!
+ // denn der "bereich" eines schlags geht von schlag_begin bis nächsterschlag_begin-1
+ // noten werden aber genau in die mitte dieses bereiches gezeichnet
+
+ list<staff_t>::iterator staff_it=staff_at_y(event->y() + y_pos);
+
+ int y=event->y() + y_pos - staff_it->y_draw;
+ int x=event->x()+x_pos-x_left;
+ int tick=flo_quantize_floor(x_to_tick(x), quant_ticks());
+ //TODO quantizing must (maybe?) be done with the proper functions
+
+ if (staff_it!=staves.end())
+ {
+ if (event->x() <= x_left) //clicked in the preamble?
+ {
+ if (event->button() == Qt::RightButton) //right-click?
+ {
+ current_staff=staff_it;
+ staff_menu->popup(event->globalPos());
+ }
+ else if (event->button() == Qt::MidButton) //middle click?
+ {
+ remove_staff(staff_it);
+ }
+ else if (event->button() == Qt::LeftButton) //left click?
+ {
+ current_staff=staff_it;
+ dragging_staff=true;
+ }
+ }
+ else
+ {
+ ScoreItemList& itemlist=staff_it->itemlist;
+
+ cout << "mousePressEvent at "<<x<<"/"<<y<<"; tick="<<tick<<endl;
+ set<FloItem, floComp>::iterator set_it;
+ for (set_it=itemlist[tick].begin(); set_it!=itemlist[tick].end(); set_it++)
+ if (set_it->type==FloItem::NOTE)
+ if (set_it->bbox().contains(x,y))
+ break;
+
+ if (set_it!=itemlist[tick].end()) //we found something?
+ {
+ mouse_down_pos=event->pos();
+ mouse_operation=NO_OP;
+
+ int t=tick;
+ set<FloItem, floComp>::iterator found;
+
+ do
+ {
+ found=itemlist[t].find(FloItem(FloItem::NOTE, set_it->pos));
+ if (found == itemlist[t].end())
+ {
+ cout << "FATAL: THIS SHOULD NEVER HAPPEN: could not find the note's tie-destination" << endl;
+ break;
+ }
+ else
+ {
+ t+=calc_len(found->len, found->dots);
+ }
+ } while (found->tied);
+
+ int total_begin=set_it->begin_tick;
+ int total_end=t;
+
+ int this_begin=tick;
+ int this_end=this_begin+calc_len(set_it->len, set_it->dots);
+
+ //that's the only note corresponding to the event?
+ if (this_begin==total_begin && this_end==total_end)
+ {
+ if (x < set_it->x)
+ mouse_x_drag_operation=BEGIN;
+ else
+ mouse_x_drag_operation=LENGTH;
+ }
+ //that's NOT the only note?
+ else
+ {
+ if (this_begin==total_begin)
+ mouse_x_drag_operation=BEGIN;
+ else if (this_end==total_end)
+ mouse_x_drag_operation=LENGTH;
+ else
+ mouse_x_drag_operation=NO_OP;
+ }
+
+ cout << "you clicked at a note with begin at "<<set_it->begin_tick<<" and end at "<<t<<endl;
+ cout << "x-drag-operation will be "<<mouse_x_drag_operation<<endl;
+ cout << "pointer to part is "<<set_it->source_part;
+ if (!set_it->source_part) cout << " (WARNING! THIS SHOULD NEVER HAPPEN!)";
+ cout << endl;
+
+ dragged_event=*set_it->source_event;
+ dragged_event_part=set_it->source_part;
+ dragged_event_original_pitch=dragged_event.pitch();
+
+ if ((mouse_erases_notes) || (event->button()==Qt::MidButton)) //erase?
+ {
+ audio->msgDeleteEvent(dragged_event, dragged_event_part, true, false, false);
+ }
+ else if (event->button()==Qt::LeftButton) //edit?
+ {
+ setMouseTracking(true);
+ dragging=true;
+ song->startUndo();
+ }
+ }
+ else //we found nothing?
+ {
+ if ((event->button()==Qt::LeftButton) && (mouse_inserts_notes))
+ {
+ signed int relative_tick=(signed) tick - curr_part->tick();
+ if (relative_tick>=0) //TODO FINDMICH do that better
+ {
+ song->startUndo();
+ //stopping undo at the end of this function is unneccessary
+ //because we'll begin a drag right after it. finishing
+ //this drag will stop undo as well (in mouseReleaseEvent)
+
+ Event newevent(Note);
+ newevent.setPitch(y_to_pitch(y,tick, staff_it->clef));
+ newevent.setVelo(64); //TODO
+ newevent.setVeloOff(64); //TODO
+ newevent.setTick(relative_tick);
+ newevent.setLenTick((new_len>0)?new_len:last_len);
+
+ audio->msgAddEvent(newevent, curr_part, false, false, false);
+
+ dragged_event_part=curr_part;
+ dragged_event=newevent;
+ dragged_event_original_pitch=newevent.pitch();
+
+ mouse_down_pos=event->pos();
+ mouse_operation=NO_OP;
+ mouse_x_drag_operation=LENGTH;
+
+ song_changed(SC_EVENT_INSERTED);
+
+ setMouseTracking(true);
+ dragging=true;
+ //song->startUndo(); unneccessary because we have started it already above
+ }
+ }
+ }
+ }
+ }
+}
+
+void ScoreCanvas::mouseReleaseEvent (QMouseEvent* event)
+{
+ if (dragging)
+ {
+ if (event->button()==Qt::LeftButton)
+ {
+ if (mouse_operation==LENGTH)
+ {
+ if (flo_quantize(dragged_event.lenTick(), quant_ticks()) <= 0)
+ {
+ cout << "new length <= 0, erasing item" << endl;
+ audio->msgDeleteEvent(dragged_event, dragged_event_part, false, false, false);
+ }
+ else
+ {
+ last_len=flo_quantize(dragged_event.lenTick(), quant_ticks());
+ }
+ }
+
+ song->endUndo(SC_EVENT_MODIFIED);
+ setMouseTracking(false);
+ dragging=false;
+
+ x_scroll_speed=0; x_scroll_pos=0;
+ }
+ }
+
+ if (dragging_staff)
+ {
+ merge_staves(staff_at_y(event->y()+y_pos), current_staff);
+ dragging_staff=false;
+
+ y_scroll_speed=0; y_scroll_pos=0;
+ }
+}
+
+#define PITCH_DELTA 5
+
+
+void ScoreCanvas::mouseMoveEvent (QMouseEvent* event)
+{
+ if (dragging)
+ {
+ int dx=event->x()-mouse_down_pos.x();
+ int dy=event->y()-mouse_down_pos.y();
+
+ int x=event->x()+x_pos-x_left;
+
+ int tick=flo_quantize_floor(x_to_tick(x), quant_ticks());
+
+ if (mouse_operation==NO_OP)
+ {
+ if ((abs(dx)>DRAG_INIT_DISTANCE) && (mouse_x_drag_operation!=NO_OP))
+ {
+ cout << "mouse-operation is now "<<mouse_x_drag_operation<<endl;
+ mouse_operation=mouse_x_drag_operation;
+ }
+ else if (abs(dy)>DRAG_INIT_DISTANCE)
+ {
+ cout << "mouse-operation is now PITCH" << endl;
+ mouse_operation=PITCH;
+ }
+ }
+
+ int new_pitch;
+
+ switch (mouse_operation)
+ {
+ case NONE:
+ break;
+
+ case PITCH:
+ cout << "changing pitch, delta="<<nearbyint((float)dy/PITCH_DELTA)<<endl;
+ new_pitch=dragged_event_original_pitch - nearbyint((float)dy/PITCH_DELTA);
+
+ if (dragged_event.pitch()!=new_pitch)
+ {
+ Event tmp=dragged_event.clone();
+ tmp.setPitch(new_pitch);
+
+ audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false);
+ dragged_event=tmp;
+
+ song_changed(SC_EVENT_INSERTED);
+ }
+
+ break;
+
+ case BEGIN:
+ if (dragged_event.tick()+dragged_event_part->tick() != unsigned(tick)) //TODO FINDMICHJETZT tick kann unsigned werden
+ {
+ Event tmp=dragged_event.clone();
+
+ if (tick-signed(dragged_event_part->tick()) >= 0) //TODO FINDMICH do that better
+ tmp.setTick(tick-dragged_event_part->tick());
+
+ audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false);
+ dragged_event=tmp;
+
+ song_changed(SC_EVENT_INSERTED);
+ }
+
+ break;
+
+ case LENGTH:
+ tick+=quant_ticks();
+ if (dragged_event.tick()+dragged_event.lenTick() + dragged_event_part->tick() != unsigned(tick))
+ {
+ Event tmp=dragged_event.clone();
+
+ if (tick-signed(dragged_event.tick() -dragged_event_part->tick()) >= 0) //TODO FINDMICH do that better
+ tmp.setLenTick(tick-dragged_event.tick() -dragged_event_part->tick());
+
+ audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false);
+ dragged_event=tmp;
+
+ song_changed(SC_EVENT_INSERTED);
+ }
+
+ break;
+ }
+
+
+ if ((mouse_operation==LENGTH) || (mouse_operation==BEGIN)) //x-scrolling enabled?
+ {
+ int win_x=event->x();
+
+ if (win_x < x_left + SCROLL_MARGIN)
+ {
+ x_scroll_speed=(win_x - (x_left + SCROLL_MARGIN)) * SCROLL_SPEED;
+ if (x_scroll_speed < -SCROLL_SPEED_MAX) x_scroll_speed=-SCROLL_SPEED_MAX;
+ }
+ else if (win_x > width() - SCROLL_MARGIN)
+ {
+ x_scroll_speed=(win_x - (width() - SCROLL_MARGIN)) * SCROLL_SPEED;
+ if (x_scroll_speed > SCROLL_SPEED_MAX) x_scroll_speed=SCROLL_SPEED_MAX;
+ }
+ else
+ x_scroll_speed=0;
+ }
+ else
+ {
+ x_scroll_speed=0;
+ }
+ }
+
+ if (dragging_staff) //y-scrolling enabled?
+ {
+ int win_y=event->y();
+
+ if (win_y < SCROLL_MARGIN)
+ {
+ y_scroll_speed=(win_y - SCROLL_MARGIN) * SCROLL_SPEED;
+ if (y_scroll_speed < -SCROLL_SPEED_MAX) y_scroll_speed=-SCROLL_SPEED_MAX;
+ }
+ else if (win_y > height() - SCROLL_MARGIN)
+ {
+ y_scroll_speed=(win_y - (height() - SCROLL_MARGIN)) * SCROLL_SPEED;
+ if (y_scroll_speed > SCROLL_SPEED_MAX) y_scroll_speed=SCROLL_SPEED_MAX;
+ }
+ else
+ y_scroll_speed=0;
+ }
+ else
+ {
+ y_scroll_speed=0;
+ }
+}
+
+void ScoreCanvas::heartbeat_timer_event()
+{
+ if (x_scroll_speed)
+ {
+ int old_xpos=x_pos;
+
+ x_scroll_pos+=x_scroll_speed*heartBeatTimer->interval()/1000.0;
+ int tmp=int(x_scroll_pos);
+ if (tmp!=0)
+ x_pos+=tmp;
+ x_scroll_pos-=tmp;
+
+ if (x_pos<0) x_pos=0;
+ if (x_pos>canvas_width()) x_pos=canvas_width();
+
+ if (old_xpos!=x_pos) emit xscroll_changed(x_pos);
+ }
+
+ if (y_scroll_speed)
+ {
+ int old_ypos=y_pos;
+
+ y_scroll_pos+=y_scroll_speed*heartBeatTimer->interval()/1000.0;
+ int tmp=int(y_scroll_pos);
+ if (tmp!=0)
+ y_pos+=tmp;
+ y_scroll_pos-=tmp;
+
+ if (y_pos<0) y_pos=0;
+ if (y_pos>canvas_height()) y_pos=canvas_height();
+
+ if (old_ypos!=y_pos) emit yscroll_changed(y_pos);
+ }
+}
+
+void ScoreCanvas::x_scroll_event(int x)
+{
+ cout << "SCROLL EVENT: x="<<x<<endl;
+ x_pos=x;
+ redraw();
+}
+
+void ScoreCanvas::y_scroll_event(int y)
+{
+ cout << "SCROLL EVENT: y="<<y<<endl;
+ y_pos=y;
+ redraw();
+}
+
+
+//if force is true, it will always happen something
+//if force is false, it will only happen something, if
+//tick isn't visible at all. if it's visible, but not at
+//the position goto would set it to, nothing happens
+void ScoreCanvas::goto_tick(int tick, bool force)
+{
+ if (!force)
+ {
+ if (tick < x_to_tick(x_pos))
+ {
+ x_pos=tick_to_x(tick) - x_left;
+ if (x_pos<0) x_pos=0;
+ if (x_pos>canvas_width()) x_pos=canvas_width();
+
+ emit xscroll_changed(x_pos);
+ }
+ else if (tick > x_to_tick(x_pos+viewport_width()*PAGESTEP))
+ {
+ x_pos=tick_to_x(tick);
+ if (x_pos<0) x_pos=0;
+ if (x_pos>canvas_width()) x_pos=canvas_width();
+
+ emit xscroll_changed(x_pos);
+ }
+ }
+ else
+ {
+ x_pos=tick_to_x(tick)-viewport_width()/2;
+ if (x_pos<0) x_pos=0;
+ if (x_pos>canvas_width()) x_pos=canvas_width();
+
+ emit xscroll_changed(x_pos);
+ }
+}
//---------------------------------------------------------
// resizeEvent
//---------------------------------------------------------
-void ScoreEdit::resizeEvent(QResizeEvent* ev)
- {
- QWidget::resizeEvent(ev);
- _widthInit = ev->size().width();
- _heightInit = ev->size().height();
- }
+void ScoreCanvas::resizeEvent(QResizeEvent* ev)
+{
+ QWidget::resizeEvent(ev); //TODO is this really neccessary?
+ emit viewport_width_changed( viewport_width() );
+ emit viewport_height_changed( viewport_height() );
+}
-/*
-//---------------------------------------------------------
-// trackInfoScroll
-//---------------------------------------------------------
+void ScoreCanvas::pos_changed(int index, unsigned tick, bool scroll)
+{
+ if (index==0)
+ {
+ if (scroll) //potential need to scroll?
+ {
+ switch (song->follow())
+ {
+ case Song::NO: break;
+ case Song::JUMP: goto_tick(tick,false); break;
+ case Song::CONTINUOUS: goto_tick(tick,true); break;
+ }
+ }
+
+ if (need_redraw_for_hilighting())
+ redraw();
+ }
+}
-void ScoreEdit::trackInfoScroll(int y)
- {
- if (trackInfo->visibleWidget())
- trackInfo->visibleWidget()->move(0, -y);
- }
-*/
-//---------------------------------------------------------
-// initShortcuts
-//---------------------------------------------------------
+void ScoreCanvas::recalc_staff_pos()
+{
+ int y=0;
+
+ for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++)
+ {
+ it->y_top=y;
+ switch (it->type)
+ {
+ case NORMAL:
+ it->y_draw = it->y_top + STAFF_DISTANCE/2;
+ it->y_bottom = it->y_draw + STAFF_DISTANCE/2;
+ break;
+ case GRAND_TOP:
+ it->y_draw = it->y_top + STAFF_DISTANCE/2;
+ it->y_bottom = it->y_draw + GRANDSTAFF_DISTANCE/2;
+ break;
+ case GRAND_BOTTOM:
+ it->y_draw = it->y_top + GRANDSTAFF_DISTANCE/2;
+ it->y_bottom = it->y_draw + STAFF_DISTANCE/2;
+ break;
+ default:
+ cout << "THIS SHOULD NEVER HAPPEN: invalid staff type!" << endl;
+ }
+ y=it->y_bottom;
+ }
+
+ emit canvas_height_changed( canvas_height() );
+}
-void ScoreEdit::initShortcuts()
- {
- editCutAction->setShortcut(shortcuts[SHRT_CUT].key);
- editCopyAction->setShortcut(shortcuts[SHRT_COPY].key);
- editPasteAction->setShortcut(shortcuts[SHRT_PASTE].key);
- editDelEventsAction->setShortcut(shortcuts[SHRT_DELETE].key);
-
- selectAllAction->setShortcut(shortcuts[SHRT_SELECT_ALL].key);
- selectNoneAction->setShortcut(shortcuts[SHRT_SELECT_NONE].key);
- selectInvertAction->setShortcut(shortcuts[SHRT_SELECT_INVERT].key);
- selectInsideLoopAction->setShortcut(shortcuts[SHRT_SELECT_ILOOP].key);
- selectOutsideLoopAction->setShortcut(shortcuts[SHRT_SELECT_OLOOP].key);
- selectPrevPartAction->setShortcut(shortcuts[SHRT_SELECT_PREV_PART].key);
- selectNextPartAction->setShortcut(shortcuts[SHRT_SELECT_NEXT_PART].key);
-
- eventColor->menuAction()->setShortcut(shortcuts[SHRT_EVENT_COLOR].key);
- //evColorBlueAction->setShortcut(shortcuts[ ].key);
- //evColorPitchAction->setShortcut(shortcuts[ ].key);
- //evColorVelAction->setShortcut(shortcuts[ ].key);
-
- funcOverQuantAction->setShortcut(shortcuts[SHRT_OVER_QUANTIZE].key);
- funcNoteOnQuantAction->setShortcut(shortcuts[SHRT_ON_QUANTIZE].key);
- funcNoteOnOffQuantAction->setShortcut(shortcuts[SHRT_ONOFF_QUANTIZE].key);
- funcIterQuantAction->setShortcut(shortcuts[SHRT_ITERATIVE_QUANTIZE].key);
-
- funcConfigQuantAction->setShortcut(shortcuts[SHRT_CONFIG_QUANT].key);
-
- funcGateTimeAction->setShortcut(shortcuts[SHRT_MODIFY_GATE_TIME].key);
- funcModVelAction->setShortcut(shortcuts[SHRT_MODIFY_VELOCITY].key);
- funcCrescendoAction->setShortcut(shortcuts[SHRT_CRESCENDO].key);
- funcTransposeAction->setShortcut(shortcuts[SHRT_TRANSPOSE].key);
- funcThinOutAction->setShortcut(shortcuts[SHRT_THIN_OUT].key);
- funcEraseEventAction->setShortcut(shortcuts[SHRT_ERASE_EVENT].key);
- funcNoteShiftAction->setShortcut(shortcuts[SHRT_NOTE_SHIFT].key);
- funcMoveClockAction->setShortcut(shortcuts[SHRT_MOVE_CLOCK].key);
- funcCopyMeasureAction->setShortcut(shortcuts[SHRT_COPY_MEASURE].key);
- funcEraseMeasureAction->setShortcut(shortcuts[SHRT_ERASE_MEASURE].key);
- funcDelMeasureAction->setShortcut(shortcuts[SHRT_DELETE_MEASURE].key);
- funcCreateMeasureAction->setShortcut(shortcuts[SHRT_CREATE_MEASURE].key);
- funcSetFixedLenAction->setShortcut(shortcuts[SHRT_FIXED_LEN].key);
- funcDelOverlapsAction->setShortcut(shortcuts[SHRT_DELETE_OVERLAPS].key);
-
- }
+list<staff_t>::iterator ScoreCanvas::staff_at_y(int y)
+{
+ for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++)
+ if ((y >= it->y_top) && (y < it->y_bottom))
+ return it;
-//---------------------------------------------------------
-// execDeliveredScript
-//---------------------------------------------------------
-void ScoreEdit::execDeliveredScript(int id)
+ return staves.end();
+}
+
+void ScoreCanvas::play_changed(bool)
{
- //QString scriptfile = QString(INSTPREFIX) + SCRIPTSSUFFIX + deliveredScriptNames[id];
- QString scriptfile = song->getScriptPath(id, true);
- song->executeScript(scriptfile.toAscii().data(), parts(), quant(), true);
+ redraw();
}
-//---------------------------------------------------------
-// execUserScript
-//---------------------------------------------------------
-void ScoreEdit::execUserScript(int id)
+void ScoreCanvas::config_changed()
{
- QString scriptfile = song->getScriptPath(id, false);
- song->executeScript(scriptfile.toAscii().data(), parts(), quant(), true);
+ redraw();
}
-//---------------------------------------------------------
-// newCanvasWidth
-//---------------------------------------------------------
+void ScoreCanvas::set_tool(int tool)
+{
+ switch (tool)
+ {
+ case PointerTool: mouse_erases_notes=false; mouse_inserts_notes=false; break;
+ case RubberTool: mouse_erases_notes=true; mouse_inserts_notes=false; break;
+ case PencilTool: mouse_erases_notes=false; mouse_inserts_notes=true; break;
+ default:
+ cout << "THIS SHOULD NEVER HAPPEN: set_tool called with unknown tool ("<<tool<<")"<<endl;
+ }
+}
-void ScoreEdit::newCanvasWidth(int /*w*/)
- {
-/*
- int nw = w + (vscroll->width() - 18); // 18 is the fixed width of the CtlEdit VScale widget.
- if(nw < 1)
- nw = 1;
-
- for (std::list<CtrlEdit*>::iterator i = ctrlEditList.begin();
- i != ctrlEditList.end(); ++i) {
- // Changed by Tim. p3.3.7
- //(*i)->setCanvasWidth(w);
- (*i)->setCanvasWidth(nw);
- }
-
- updateHScrollRange();
-*/
- }
+void ScoreCanvas::menu_command(int cmd)
+{
+ switch (cmd)
+ {
+ case CMD_COLOR_BLACK: coloring_mode=COLOR_MODE_BLACK; redraw(); break;
+ case CMD_COLOR_PART: coloring_mode=COLOR_MODE_PART; redraw(); break;
+ case CMD_NOTELEN_1: new_len=TICKS_PER_WHOLE/ 1; break;
+ case CMD_NOTELEN_2: new_len=TICKS_PER_WHOLE/ 2; break;
+ case CMD_NOTELEN_4: new_len=TICKS_PER_WHOLE/ 4; break;
+ case CMD_NOTELEN_8: new_len=TICKS_PER_WHOLE/ 8; break;
+ case CMD_NOTELEN_16: new_len=TICKS_PER_WHOLE/16; break;
+ case CMD_NOTELEN_32: new_len=TICKS_PER_WHOLE/32; break;
+ case CMD_NOTELEN_LAST: new_len=-1; break;
+ default:
+ cout << "ILLEGAL FUNCTION CALL: ScoreCanvas::menu_command called with unknown command ("<<cmd<<")"<<endl;
+ }
+}
-//---------------------------------------------------------
-// toggleTrackInfo
-//---------------------------------------------------------
+void ScoreCanvas::preamble_keysig_slot(bool state)
+{
+ preamble_contains_keysig=state;
+ redraw();
+}
+void ScoreCanvas::preamble_timesig_slot(bool state)
+{
+ preamble_contains_timesig=state;
+ redraw();
+}
-void ScoreEdit::toggleTrackInfo()
+void ScoreCanvas::set_quant(int val)
{
- bool vis = midiTrackInfo->isVisible();
- infoScroll->setVisible(!vis);
- infoScroll->setEnabled(!vis);
+ int quant_mapper[]={1,2,3,4,5};
+
+ if ((val>=0) && (val<signed(sizeof(quant_mapper)/sizeof(*quant_mapper))))
+ {
+ _quant_power2=quant_mapper[val];
+
+ song_changed(SC_EVENT_INSERTED);
+ }
+ else
+ {
+ cout << "ILLEGAL FUNCTION CALL: set_quant called with invalid value of "<<val<<endl;
+ }
}
+
+
+//the following assertions are made:
+// pix_quarter.width() == pix_half.width()
+
+
+// pix->width()-1 + 1/2*pix->width() + SHIFT + ADD_SPACE
+// 10-1+5+3+3=20 <- um so viel wird der taktstrich verschoben
+// um das doppelte (20*2=40) werden die kleinsten schläge gegeneinander versetzt
+
+
+
+
+
+//hint: recalculating event- and itemlists "from zero"
+// could happen in realtime, as it is pretty fast.
+// however, this adds unneccessary cpu usage.
+// it is NO problem to recalc the stuff "from zero"
+// every time something changes.
+
+
+/* BUGS and potential bugs
+ * o when color=black, then the tie has a wrong color, because
+ * partColors[BLACK_INDEX] is out of bounds
+ * o when the keymap is not used, this will probably lead to a bug
+ * o when adding a note, it's added to the first stave
+ * the problem is: there's always the first part selected
+ *
+ * CURRENT TODO
+ * o automatically set x-raster (by quant. strength)
+ *
+ * IMPORTANT TODO
+ * o removing the part the score's working on isn't handled
+ * o let the user select the currently edited part
+ * o support selections
+ * o emit a "song-changed" signal instead of calling our
+ * internal song_changed() function
+ * o check if "moving away" works for whole notes [seems to NOT work properly]
+ * o more fine-grained redrawing in song_changed: sometimes,
+ * only a redraw and not a recalc is needed
+ * o do all the song_changed(SC_EVENT_INSERTED) properly
+ *
+ * less important stuff
+ * o must add_parts() update the part-list?
+ * o support different keys in different tracks at the same time
+ * calc_pos_add_list and calc_item_pos will be affected by this
+ * calc_pos_add_list must be called before calc_item_pos then,
+ * and calc_item_pos must respect the pos_add_list instead of
+ * keeping its own pos_add variable (which is only an optimisation)
+ * o use nearest part instead of curr_part, maybe expand
+ * o draw measure numbers
+ * o when moving or resizing a note, so that its end is out-of-part,
+ * there's strange behaviour
+ * o ties aren't always drawn correctly when the destination note
+ * is out of view
+ * o tied notes don't work properly when there's a key-change in
+ * between, for example, when a cis is tied to a des
+ * o let the user select whether the preamble should have
+ * a fixed length (?)
+ * o let the user select what the preamble has to contain
+ * > o use timesig_t in all timesig-stuff
+ * o draw a margin around notes which are in a bright color
+ * o maybe override color 0 with "black"?
+ * o use bars instead of flags over groups of 8ths / 16ths etc
+ * o (change ItemList into map< pos_t , mutable_stuff_t >) [no]
+ * o deal with expanding parts or clip (expanding is better)
+ * o refuse to resize so that width gets smaller or equal than x_left
+ * o add tracks in correct order to score
+ *
+ * stuff for the other muse developers
+ * o process accurate timesignatures from muse's list (has to be implemented first in muse)
+ * ( (2+2+3)/4 or (3+2+2)/4 instead of 7/4 )
+ * o maybe do expanding parts inside the msgChangeEvent or
+ * msgNewEvent functions (see my e-mail)
+ *
+ * GUI stuff
+ * o invalidate len-buttons for lens which are outside of the quantisation setting
+ * o velocity/release-velo for newly inserted notes [->toolbar]
+ * o velocity/release-velo for already existing notes
+ * - do this by right-click -> some dialog shows up?
+ * - or by selecting the note and changing the values in the same widget which also is used for new notes?
+ * o initiate "select current part"
+*/
+
+
+/* how to use the score editor with multiple tracks
+ * ================================================
+ *
+ * select parts, right-click, "display in new score window" or "display per-track in new score window"
+ * or "display in existing window -> 1,2,3,4" or "display per-track in existing..."
+ *
+ * ScoreCanvas has a list of note systems, consisting of the following:
+ * * all parts included in that view
+ * * eventlist, itemlist
+ * * used clef, transposing/octave settings
+ * * enum { NOT_GROUPED, I_AM_TOP, I_AM_BOTTOM } group_state
+ * NOT_GROUPED means "single note system"
+ * I_AM_TOP and I_AM_BOTTOM mean that the two systems belong
+ * together
+ *
+ * when redrawing, we iterate through all systems.
+ * we add a distance according to group_state
+ * then we draw the system. if group_state is I_AM_BOTTOM, we
+ * draw our beams longer/higher, and we draw a bracket
+ *
+ * when clicking around, we first determine which system has been clicked in
+ * (the systems have enough space in between, so there won't be notes
+ * from sys1 in sys2. if there are, they're ignored for simplicity)
+ * then we proceed as usual (adding, removing, changing notes)
+ *
+ *
+ * pos_add_list stays the same for each staff, so we only need one
+ */
+
+/* R O A D M A P
+ * =============
+ *
+ * 1. finish the score editor, without transposing instruments and
+ * with only a global keymap
+ *
+ * REASON: a score editor with few functions is better than
+ * no score editor at all
+ *
+ *
+ * 2. support transposing by octave-steps
+ *
+ * REASON: the main problem with transposing is, that the
+ * editor needs different key signatures and needs
+ * to align them against each other. this problem
+ * doesn't exist when only transposing by octaves
+ *
+ *
+ * 3. support transposing instruments, but only one
+ * transposing-setting per score window. that is, you won't be
+ * able to display your (C-)strings in the same window as your
+ * B-trumpet. this will be very easy to implement
+ *
+ * REASON: the above problem still exists, but is circumvented
+ * by simply not having to align them against each other
+ * (because they're in different windows)
+ *
+ *
+ * 4. support different transposing instruments in the same score
+ * window. this will be some hassle, because we need to align
+ * the scores properly. for example, when the C-violin has
+ * C-major (no accidentials), then the B-trumpet need some
+ * accidentials. we now must align the staves so that the
+ * "note-after-keychange"s of both staves are again at the
+ * same x-position
+ *
+ * REASON: some solution for that problem must be written.
+ * this is a large step, which atm isn't very important
+ *
+ *
+ * 5. support different keys per track. this wouldn't be that
+ * hard, when 4) is already done; because we then already have
+ * the "align it properly" functionality, and can use it
+ *
+ * REASON: this is only a nice-to-have, which can however be
+ * easily implemented when 4) is done
+ */
+
diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h
index 767dc463..c3ba246c 100644
--- a/muse2/muse/midiedit/scoreedit.h
+++ b/muse2/muse/midiedit/scoreedit.h
@@ -1,8 +1,8 @@
//=========================================================
// MusE
// Linux Music Editor
-// $Id: pianoroll.h,v 1.5.2.4 2009/11/16 11:29:33 lunar_shuttle Exp $
-// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+// scoreedit.h
+// (C) Copyright 2011 Florian Jung (florian.a.jung@web.de)
//=========================================================
#ifndef __SCOREEDIT_H__
@@ -12,6 +12,11 @@
#include <QResizeEvent>
#include <QLabel>
#include <QKeyEvent>
+#include <QPainter>
+#include <QPixmap>
+#include <QTimer>
+#include <QScrollBar>
+#include <QSignalMapper>
#include <values.h>
#include "noteinfo.h"
@@ -19,183 +24,643 @@
#include "midieditor.h"
#include "tools.h"
#include "event.h"
+#include "view.h"
+#include "gconfig.h"
+#include "part.h"
+#include "keyevent.h"
-class MidiPart;
-class TimeLabel;
-class PitchLabel;
-class QLabel;
-class PianoCanvas;
-class MTScale;
-class Track;
-class QToolButton;
-class QToolBar;
-class QPushButton;
-class CtrlEdit;
-class Splitter;
-class PartList;
-class Toolbar1;
-class Xml;
-class QuantConfig;
-class ScrollScale;
-class Part;
-class SNode;
-class QMenu;
-class QAction;
-class QWidget;
-class QScrollBar;
-class MidiTrackInfo;
-class QScrollArea;
+#include <set>
+#include <map>
+#include <list>
+#include <vector>
+#include <string>
+
+using std::set;
+using std::pair;
+using std::map;
+using std::list;
+using std::vector;
+using std::string;
+
+
+
+#define TICKS_PER_WHOLE (config.division*4)
+#define SONG_LENGTH (song->len())
+
+
+
+enum {CMD_COLOR_BLACK, CMD_COLOR_VELO, CMD_COLOR_PART,
+ CMD_SET_NAME,
+ CMD_NOTELEN_1, CMD_NOTELEN_2, CMD_NOTELEN_4, CMD_NOTELEN_8,
+ CMD_NOTELEN_16, CMD_NOTELEN_32, CMD_NOTELEN_LAST };
+
+class ScoreCanvas;
//---------------------------------------------------------
-// PianoRoll
+// ScoreEdit
//---------------------------------------------------------
-class ScoreEdit : public MidiEditor {
- Event selEvent;
- MidiPart* selPart;
- int selTick;
-
- //enum { CMD_EVENT_COLOR, CMD_CONFIG_QUANT, CMD_LAST };
- //int menu_ids[CMD_LAST];
- //Q3PopupMenu *menuEdit, *menuFunctions, *menuSelect, *menuConfig, *menuPlugins;
-
-
- QMenu *menuEdit, *menuFunctions, *menuSelect, *menuConfig, *eventColor, *menuPlugins;
- MidiTrackInfo *midiTrackInfo;
- Track* selected;
-
- QAction* editCutAction;
- QAction* editCopyAction;
- QAction* editPasteAction;
- QAction* editDelEventsAction;
-
- QAction* selectAllAction;
- QAction* selectNoneAction;
- QAction* selectInvertAction;
- QAction* selectInsideLoopAction;
- QAction* selectOutsideLoopAction;
- QAction* selectPrevPartAction;
- QAction* selectNextPartAction;
-
- QAction* evColorBlueAction;
- QAction* evColorPitchAction;
- QAction* evColorVelAction;
-
- QAction* funcOverQuantAction;
- QAction* funcNoteOnQuantAction;
- QAction* funcNoteOnOffQuantAction;
- QAction* funcIterQuantAction;
- QAction* funcConfigQuantAction;
- QAction* funcGateTimeAction;
- QAction* funcModVelAction;
- QAction* funcCrescendoAction;
- QAction* funcTransposeAction;
- QAction* funcThinOutAction;
- QAction* funcEraseEventAction;
- QAction* funcNoteShiftAction;
- QAction* funcMoveClockAction;
- QAction* funcCopyMeasureAction;
- QAction* funcEraseMeasureAction;
- QAction* funcDelMeasureAction;
- QAction* funcCreateMeasureAction;
- QAction* funcSetFixedLenAction;
- QAction* funcDelOverlapsAction;
-
-
- int tickOffset;
- int lenOffset;
- int pitchOffset;
- int veloOnOffset;
- int veloOffOffset;
- bool deltaMode;
-
- NoteInfo* info;
- QToolButton* srec;
- QToolButton* midiin;
-
- Toolbar1* toolbar;
- Splitter* splitter;
- Splitter* hsplitter;
- Splitter* ctrlLane;
-
- QToolButton* speaker;
- QToolBar* tools;
- EditToolBar* tools2;
-
- int colorMode;
-
- static int _quantInit, _rasterInit;
- static int _widthInit, _heightInit;
-
- static int _quantStrengthInit;
- static int _quantLimitInit;
- static bool _quantLenInit;
- static int _toInit;
- static int colorModeInit;
-
- int _quantStrength;
- int _quantLimit;
- int _to;
- bool _quantLen;
- QuantConfig* quantConfig;
- bool _playEvents;
-
- //QScrollBar* infoScroll;
- QScrollArea* infoScroll;
-
- Q_OBJECT
- void initShortcuts();
- void setEventColorMode(int);
- QWidget* genToolbar(QWidget* parent);
- virtual void closeEvent(QCloseEvent*);
- virtual void keyPressEvent(QKeyEvent*);
- virtual void resizeEvent(QResizeEvent*);
-
- private slots:
- void setSelection(int, Event&, Part*);
- void noteinfoChanged(NoteInfo::ValType, int);
- //CtrlEdit* addCtrl();
- void removeCtrl(CtrlEdit* ctrl);
- void soloChanged(bool flag);
- //void trackInfoScroll(int);
- void setRaster(int);
- void setQuant(int);
- void configQuant();
- void setQuantStrength(int val) { _quantStrength = val; }
- void setQuantLimit(int val) { _quantLimit = val; }
- void setQuantLen(bool val) { _quantLen = val; }
- void cmd(int);
- void setSteprec(bool);
- void setTo(int val) { _to = val; }
- void eventColorModeChanged(int);
- void clipboardChanged(); // enable/disable "Paste"
- void selectionChanged(); // enable/disable "Copy" & "Paste"
- void setSpeaker(bool);
- void setTime(unsigned);
- void follow(int pos);
- void songChanged1(int);
- void configChanged();
- void newCanvasWidth(int);
- void toggleTrackInfo();
- void updateTrackInfo();
-
- signals:
- void deleted(unsigned long);
-
+class ScoreEdit : public MidiEditor
+{
+ Q_OBJECT
+
+ private:
+ virtual void closeEvent(QCloseEvent*);
+
+ QScrollBar* xscroll;
+ QScrollBar* yscroll;
+ ScoreCanvas* score_canvas;
+
+ static int serial;
+ static set<QString> names;
+
+ QString name;
+
+ QSignalMapper* menu_mapper;
+
+ bool set_name(QString newname, bool emit_signal=true, bool emergency_name=false);
+
+ private slots:
+ void menu_command(int);
+
+ signals:
+ void deleted(unsigned long);
+ void name_changed();
+
+ public slots:
+ void canvas_width_changed(int);
+ void viewport_width_changed(int);
+ void canvas_height_changed(int);
+ void viewport_height_changed(int);
+
+ public:
+ ScoreEdit(PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT);
+ ~ScoreEdit();
+ static void readConfiguration(Xml&){}; //TODO does nothing
+ static void writeConfiguration(int, Xml&){}; //TODO does nothing
+
+ void add_parts(PartList* pl, bool all_in_one=false);
+ QString get_name() { return name; }
+ };
+
+
+
+
+
+
+enum stem_t
+{
+ UPWARDS,
+ DOWNWARDS
+};
+
+enum vorzeichen_t
+{
+ B=-1,
+ NONE=0,
+ SHARP=1
+};
+
+struct note_pos_t
+{
+ int height; // 0 means "C-line", 1 "D-line" and so on
+ vorzeichen_t vorzeichen;
+
+ bool operator== (const note_pos_t& that) const
+ {
+ return (this->height==that.height) && (this->vorzeichen == that.vorzeichen);
+ }
+};
+
+bool operator< (const note_pos_t& a, const note_pos_t& b);
+
+
+
+
+
+
+
+class FloEvent
+{
+ public:
+ enum typeEnum { NOTE_ON = 30, NOTE_OFF = 10, BAR = 20, KEY_CHANGE=23, TIME_SIG=26 }; //the order matters!
+ typeEnum type;
+ unsigned tick;
+ Part* source_part;
+ Event* source_event;
+
+ int pitch;
+ mutable int vel;
+ mutable int len;
+
+ int num;
+ int denom;
+
+ key_enum key;
+
+
+ FloEvent(unsigned ti, int p,int v,int l,typeEnum t, Part* part=NULL, Event* event=NULL)
+ {
+ pitch=p;
+ vel=v;
+ len=l;
+ type= t;
+ tick=ti;
+ source_event=event;
+ source_part=part;
+ }
+ FloEvent(unsigned ti, typeEnum t, int num_, int denom_)
+ {
+ type=t;
+ num=num_;
+ denom=denom_;
+ tick=ti;
+ source_event=NULL;
+ source_part=NULL;
+ }
+ FloEvent(unsigned ti, typeEnum t, key_enum k)
+ {
+ type=t;
+ key=k;
+ tick=ti;
+ source_event=NULL;
+ source_part=NULL;
+ }
+};
+class FloItem
+{
+ public:
+ enum typeEnum { NOTE=21, REST=22, NOTE_END=01, REST_END=02, BAR =10, KEY_CHANGE=13, TIME_SIG=16}; //the order matters!
+ typeEnum type;
+ unsigned begin_tick;
+ Event* source_event;
+ Part* source_part;
+
+ note_pos_t pos;
+ int len;
+ int dots;
+ bool tied;
+ bool already_grouped;
+
+ int num;
+ int denom;
+
+ key_enum key;
+
+ mutable stem_t stem;
+ mutable int shift;
+ mutable bool ausweich;
+ mutable bool is_tie_dest;
+ mutable int tie_from_x;
+
+ mutable int x;
+ mutable int y;
+ mutable int stem_x;
+ mutable QPixmap* pix;
+
+ mutable bool is_active;
+
+ QRect bbox() const;
+
+
+
+ FloItem(typeEnum t, note_pos_t p, int l=0,int d=0, bool ti=false, unsigned beg=0, Part* part=NULL, Event* event=NULL)
+ {
+ pos=p;
+ dots=d;
+ len=l;
+ type=t;
+ already_grouped=false;
+ tied=ti;
+ shift=0;
+ ausweich=false;
+ is_tie_dest=false;
+ begin_tick=beg;
+ source_event=event;
+ source_part=part;
+ }
+
+ FloItem(typeEnum t, int num_, int denom_)
+ {
+ type=t;
+ num=num_;
+ denom=denom_;
+ begin_tick=-1;
+ source_event=NULL;
+ source_part=NULL;
+ }
+
+ FloItem(typeEnum t, key_enum k)
+ {
+ type=t;
+ key=k;
+ begin_tick=-1;
+ source_event=NULL;
+ source_part=NULL;
+ }
+
+ FloItem(typeEnum t)
+ {
+ type=t;
+
+ already_grouped=false;
+ tied=false;
+ shift=0;
+ ausweich=false;
+ is_tie_dest=false;
+ begin_tick=-1;
+ source_event=NULL;
+ source_part=NULL;
+ }
+
+ FloItem()
+ {
+ already_grouped=false;
+ tied=false;
+ shift=0;
+ ausweich=false;
+ is_tie_dest=false;
+ begin_tick=-1;
+ source_event=NULL;
+ source_part=NULL;
+ }
+
+ bool operator==(const FloItem& that)
+ {
+ if (this->type != that.type) return false;
+
+ switch(type)
+ {
+ case NOTE:
+ case REST:
+ case NOTE_END:
+ case REST_END:
+ return (this->pos == that.pos);
+
+ //the following may only occurr once in a set
+ //so we don't search for "the time signature with 4/4
+ //at t=0", but only for "some time signature at t=0"
+ //that's why true is returned, and not some conditional
+ //expression
+ case BAR:
+ case KEY_CHANGE:
+ case TIME_SIG:
+ return true;
+ }
+ }
+};
+struct floComp
+{
+ bool operator() (const pair<unsigned, FloEvent>& a, const pair<unsigned, FloEvent>& b )
+ {
+ if (a.first < b.first) return true;
+ if (a.first > b.first) return false;
+
+ if (a.second.type<b.second.type) return true;
+ if (a.second.type>b.second.type) return false;
+
+ return (a.second.pitch<b.second.pitch);
+ }
+ bool operator() (const FloItem& a, const FloItem& b )
+ {
+ if (a.type < b.type) return true;
+ if (a.type > b.type) return false;
+
+ switch(a.type)
+ {
+ case FloItem::NOTE:
+ case FloItem::REST:
+ case FloItem::NOTE_END:
+ case FloItem::REST_END:
+ return (a.pos < b.pos);
+
+ //the following may only occurr once in a set
+ //so we don't search for "the time signature with 4/4
+ //at t=0", but only for "some time signature at t=0"
+ //that's why true is returned, and not some conditional
+ //expression
+ case FloItem::BAR:
+ case FloItem::KEY_CHANGE:
+ case FloItem::TIME_SIG:
+ return false;
+ }
+ return (a.pos < b.pos);
+ }
+};
+
+typedef set< pair<unsigned, FloEvent>, floComp > ScoreEventList;
+typedef map< unsigned, set<FloItem, floComp> > ScoreItemList;
+
+enum clef_t
+{
+ VIOLIN,
+ BASS
+};
+
+
+struct note_len_t
+{
+ int len;
+ int dots;
+
+ note_len_t(int l, int d)
+ {
+ len=l; dots=d;
+ }
+
+ note_len_t(int l)
+ {
+ len=l; dots=0;
+ }
+};
+
+bool operator< (const note_len_t& a,const note_len_t& b);
+
+struct cumulative_t
+{
+ int count;
+ int cumul;
+
+ cumulative_t()
+ {
+ count=0;
+ cumul=0;
+ }
+
+ void add(int v)
+ {
+ count++;
+ cumul+=v;
+ }
+
+ float mean()
+ {
+ return (float)cumul/count;
+ }
+};
+
+#define BLACK_PIXMAP (NUM_PARTCOLORS)
+#define HIGHLIGHTED_PIXMAP (NUM_PARTCOLORS+1)
+
+struct timesig_t
+{
+ int num;
+ int denom;
+};
+
+enum staff_type_t
+{
+ NORMAL,
+ GRAND_TOP,
+ GRAND_BOTTOM
+};
+
+enum staff_mode_t
+{
+ MODE_TREBLE,
+ MODE_BASS,
+ MODE_BOTH
+};
+
+struct staff_t
+{
+ set<Part*> parts;
+ ScoreEventList eventlist;
+ ScoreItemList itemlist;
+
+ int y_top;
+ int y_draw;
+ int y_bottom;
+
+ staff_type_t type;
+ clef_t clef;
+ int split_note;
+
+ ScoreCanvas* parent;
+
+ void create_appropriate_eventlist(const set<Part*>& parts);
+ void create_itemlist();
+ void process_itemlist();
+ void calc_item_pos();
+
+ staff_t(ScoreCanvas* parent_)
+ {
+ type=NORMAL;
+ clef=VIOLIN;
+ parent=parent_;
+ }
+
+ staff_t (ScoreCanvas* parent_, staff_type_t type_, clef_t clef_, set<Part*> parts_, int split_note_=0)
+ {
+ type=type_;
+ clef=clef_;
+ split_note=split_note_;
+ parts=parts_;
+ parent=parent_;
+ }
+};
+
+list<int> calc_accidentials(key_enum key, clef_t clef, key_enum next_key=KEY_C);
+note_pos_t note_pos_(int note, key_enum key);
+note_pos_t note_pos (unsigned note, key_enum key, clef_t clef);
+
+int calc_len(int l, int d);
+list<note_len_t> parse_note_len(int len_ticks, int begin_tick, vector<int>& foo, int quant_power2, bool allow_dots=true, bool allow_normal=true);
+
+int clef_height(clef_t clef);
+
+
+int calc_timesig_width(int num, int denom);
+int calc_number_width(int n);
+
+
+class ScoreCanvas : public View
+{
+ Q_OBJECT
+ private:
+ static void load_pixmaps();
+ static void draw_pixmap(QPainter& p, int x, int y, const QPixmap& pm);
+ static void draw_tie (QPainter& p, int x1, int x4, int yo, bool up=true, QColor color=Qt::black);
+
+ static void draw_accidentials(QPainter& p, int x, int y_offset, const list<int>& acc_list, const QPixmap& pix);
+
+ static void draw_timesig(QPainter& p, int x, int y_offset, int num, int denom);
+
+ static void draw_number(QPainter& p, int x, int y, int n);
+
+
+
+
+
+ static int height_to_pitch(int h, clef_t clef, key_enum key);
+ static int height_to_pitch(int h, clef_t clef);
+ static int y_to_height(int y);
+ int y_to_pitch(int y, int t, clef_t clef);
+
+
+
+
+ void draw_note_lines(QPainter& p, int y);
+ void draw_preamble(QPainter& p, int y, clef_t clef);
+ void draw_items(QPainter& p, int y, staff_t& staff, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it);
+ void draw_items(QPainter& p, int y, staff_t& staff, int x1, int x2);
+ void draw_items(QPainter& p, int y, staff_t& staff);
+ void calc_pos_add_list();
+
+
+ void recalc_staff_pos();
+ list<staff_t>::iterator staff_at_y(int y);
+
+
+ timesig_t timesig_at_tick(int t);
+ key_enum key_at_tick(int t);
+ int tick_to_x(int t);
+ int x_to_tick(int x);
+ int calc_posadd(int t);
+
+
+
+ bool need_redraw_for_hilighting(ScoreItemList::iterator from_it, ScoreItemList::iterator to_it);
+ bool need_redraw_for_hilighting(ScoreItemList& itemlist, int x1, int x2);
+ bool need_redraw_for_hilighting(ScoreItemList& itemlist);
+ bool need_redraw_for_hilighting();
+
+
+ void set_staffmode(list<staff_t>::iterator it, staff_mode_t mode);
+ void remove_staff(list<staff_t>::iterator it);
+ void merge_staves(list<staff_t>::iterator dest, list<staff_t>::iterator src);
+
+
+// member variables ---------------------------------------------------
+ int _quant_power2;
+
+ std::map<int,int> pos_add_list;
+
+ list<staff_t> staves;
+
+ // the drawing area is split into a "preamble" containing clef,
+ // key and time signature, and the "item's area" containing the
+ // actual items (notes, bars, rests, etc.)
+ // x_pos is responsible for scrolling. an item with item->x==x_pos
+ // will be drawn exactly at the left beginning of the item's area
+ // x_left could also be called "preamble's width". it defines
+ // where the item's area begins
+ // when multiple note systems are drawn into one window, the
+ // preamble's length is the same for each system
+ int x_pos;
+ int x_left;
+
+ int y_pos;
+
+ //for mouse-scrolling
+ float x_scroll_speed;
+ float x_scroll_pos;
+ float y_scroll_speed;
+ float y_scroll_pos;
+
+ Part* curr_part;
+ int last_len;
+ int new_len; //when zero or negative, last_len is used
+
+ QPoint mouse_down_pos;
+ bool mouse_down;
+ enum operation_t
+ {
+ NO_OP=0,
+ BEGIN=1,
+ LENGTH=2,
+ PITCH=3
+ };
+ operation_t mouse_operation;
+ operation_t mouse_x_drag_operation;
+ bool mouse_erases_notes;
+ bool mouse_inserts_notes;
+
+ bool dragging;
+ Part* dragged_event_part;
+ Event dragged_event;
+ int dragged_event_original_pitch;
+
+
+
+ enum {COLOR_MODE_BLACK, COLOR_MODE_PART, COLOR_MODE_PITCH} coloring_mode;
+ bool preamble_contains_keysig;
+ bool preamble_contains_timesig;
+
+
+ //menu stuff
+ QAction* staffmode_treble_action;
+ QAction* staffmode_bass_action;
+ QAction* staffmode_both_action;
+ QAction* remove_staff_action;
+
+ QMenu* staff_menu;
+ list<staff_t>::iterator current_staff;
+ bool dragging_staff;
+
+
+ private slots:
+ void staffmode_treble_slot();
+ void staffmode_bass_slot();
+ void staffmode_both_slot();
+ void remove_staff_slot();
+
+ void play_changed(bool);
+ void config_changed();
+
public slots:
- virtual void updateHScrollRange();
- void execDeliveredScript(int id);
- void execUserScript(int id);
- CtrlEdit* addCtrl();
-
- public:
- ScoreEdit(PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT);
- ~ScoreEdit();
- virtual void readStatus(Xml&);
- virtual void writeStatus(int, Xml&) const;
- static void readConfiguration(Xml&);
- static void writeConfiguration(int, Xml&);
- };
+ void x_scroll_event(int);
+ void y_scroll_event(int);
+ void song_changed(int);
+ void goto_tick(int,bool);
+ void pos_changed(int i, unsigned u, bool b);
+ void heartbeat_timer_event();
+
+ void set_tool(int);
+ void set_quant(int);
+ void menu_command(int);
+ void preamble_keysig_slot(bool);
+ void preamble_timesig_slot(bool);
+
+ signals:
+ void xscroll_changed(int);
+ void yscroll_changed(int);
+ void viewport_width_changed(int);
+ void canvas_width_changed(int);
+ void viewport_height_changed(int);
+ void canvas_height_changed(int);
+
+ protected:
+ virtual void draw(QPainter& p, const QRect& rect);
+ MidiEditor* editor;
+
+ virtual void mousePressEvent (QMouseEvent* event);
+ virtual void mouseMoveEvent (QMouseEvent* event);
+ virtual void mouseReleaseEvent (QMouseEvent* event);
+ virtual void resizeEvent(QResizeEvent*);
+
+ public:
+ ScoreCanvas(MidiEditor*, QWidget*, int, int);
+ ~ScoreCanvas(){};
+
+ void add_staves(PartList* pl, bool all_in_one);
+
+ int canvas_width();
+ int canvas_height();
+ int viewport_width();
+ int viewport_height();
+
+ int quant_power2() { return _quant_power2; }
+ int quant_len() { return (1<<_quant_power2); }
+ int quant_ticks() { return TICKS_PER_WHOLE / (1<<_quant_power2); }
+ int pixels_per_whole() { return 320; } //TODO FINDMICHJETZT
+ int note_x_indent() { return pixels_per_whole()/quant_len()/2; }
+};
+
+int calc_measure_len(const list<int>& nums, int denom);
+vector<int> create_emphasize_list(const list<int>& nums, int denom);
+vector<int> create_emphasize_list(int num, int denom);
+
#endif
diff --git a/muse2/share/CMakeLists.txt b/muse2/share/CMakeLists.txt
index aeb7e4a1..44b02269 100644
--- a/muse2/share/CMakeLists.txt
+++ b/muse2/share/CMakeLists.txt
@@ -29,6 +29,7 @@ subdirs(
scripts
templates
wallpapers
+ scoreglyphs
locale
)
diff --git a/muse2/share/scoreglyphs/0.png b/muse2/share/scoreglyphs/0.png
new file mode 100644
index 00000000..55e80896
--- /dev/null
+++ b/muse2/share/scoreglyphs/0.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/1.png b/muse2/share/scoreglyphs/1.png
new file mode 100644
index 00000000..37cc2f4a
--- /dev/null
+++ b/muse2/share/scoreglyphs/1.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/2.png b/muse2/share/scoreglyphs/2.png
new file mode 100644
index 00000000..6fbf0b77
--- /dev/null
+++ b/muse2/share/scoreglyphs/2.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/3.png b/muse2/share/scoreglyphs/3.png
new file mode 100644
index 00000000..5b896cfe
--- /dev/null
+++ b/muse2/share/scoreglyphs/3.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/4.png b/muse2/share/scoreglyphs/4.png
new file mode 100644
index 00000000..895fc9dd
--- /dev/null
+++ b/muse2/share/scoreglyphs/4.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/5.png b/muse2/share/scoreglyphs/5.png
new file mode 100644
index 00000000..1214777c
--- /dev/null
+++ b/muse2/share/scoreglyphs/5.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/6.png b/muse2/share/scoreglyphs/6.png
new file mode 100644
index 00000000..1113e5b8
--- /dev/null
+++ b/muse2/share/scoreglyphs/6.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/7.png b/muse2/share/scoreglyphs/7.png
new file mode 100644
index 00000000..05e01f4f
--- /dev/null
+++ b/muse2/share/scoreglyphs/7.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/8.png b/muse2/share/scoreglyphs/8.png
new file mode 100644
index 00000000..a9967b92
--- /dev/null
+++ b/muse2/share/scoreglyphs/8.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/9.png b/muse2/share/scoreglyphs/9.png
new file mode 100644
index 00000000..d4a23a88
--- /dev/null
+++ b/muse2/share/scoreglyphs/9.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/CMakeLists.txt b/muse2/share/scoreglyphs/CMakeLists.txt
new file mode 100644
index 00000000..16617660
--- /dev/null
+++ b/muse2/share/scoreglyphs/CMakeLists.txt
@@ -0,0 +1,29 @@
+#=============================================================================
+# MusE
+# Linux Music Editor
+# $Id:$
+#
+# Copyright (C) 2002-2006 by Werner Schweer and others
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#=============================================================================
+
+file (GLOB scoreglyph_files *.png LICENSE)
+
+subdirs( feta-original
+ )
+
+install( FILES ${scoreglyph_files}
+ DESTINATION ${MusE_SHARE_DIR}/scoreglyphs
+ )
+
diff --git a/muse2/share/scoreglyphs/LICENSE b/muse2/share/scoreglyphs/LICENSE
new file mode 100644
index 00000000..7ff14294
--- /dev/null
+++ b/muse2/share/scoreglyphs/LICENSE
@@ -0,0 +1,364 @@
+These images can be redistributed and/or modified under the terms
+of the GNU General Public License Version 2 as published by the
+Free Software Foundation.
+
+These images 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 <http://www.gnu.org/licenses/>.
+
+
+
+CREDITS:
+these images were taken from lilypond's feta font on 28. March 2011.
+they're licensed under the GPL2, as is the feta font (and the whole
+lilypond project they belong to), see ./feta-original/COPYING-lilypond
+
+the relevant original files from the feta font can be found in ./feta-original/
+
+a copy of the GPL2, which applies to these images, is attached below:
+
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/muse2/share/scoreglyphs/acc_b.png b/muse2/share/scoreglyphs/acc_b.png
new file mode 100644
index 00000000..1aa3f9e6
--- /dev/null
+++ b/muse2/share/scoreglyphs/acc_b.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/acc_none.png b/muse2/share/scoreglyphs/acc_none.png
new file mode 100644
index 00000000..a297eaf2
--- /dev/null
+++ b/muse2/share/scoreglyphs/acc_none.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/acc_sharp.png b/muse2/share/scoreglyphs/acc_sharp.png
new file mode 100644
index 00000000..0c8e9eb4
--- /dev/null
+++ b/muse2/share/scoreglyphs/acc_sharp.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/clef_bass_big.png b/muse2/share/scoreglyphs/clef_bass_big.png
new file mode 100644
index 00000000..e971a803
--- /dev/null
+++ b/muse2/share/scoreglyphs/clef_bass_big.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/clef_violin_big.png b/muse2/share/scoreglyphs/clef_violin_big.png
new file mode 100644
index 00000000..cb170746
--- /dev/null
+++ b/muse2/share/scoreglyphs/clef_violin_big.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/dot.png b/muse2/share/scoreglyphs/dot.png
new file mode 100644
index 00000000..e6f3a8f9
--- /dev/null
+++ b/muse2/share/scoreglyphs/dot.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/feta-original/CMakeLists.txt b/muse2/share/scoreglyphs/feta-original/CMakeLists.txt
new file mode 100644
index 00000000..04e44107
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/CMakeLists.txt
@@ -0,0 +1,27 @@
+#=============================================================================
+# MusE
+# Linux Music Editor
+# $Id:$
+#
+# Copyright (C) 2002-2006 by Werner Schweer and others
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#=============================================================================
+
+file (GLOB fetaorig_files COPYING-lilypond GNUmakefile README *.pe.in *.mf *.mp)
+
+
+install( FILES ${fetaorig_files}
+ DESTINATION ${MusE_SHARE_DIR}/scoreglyphs/feta-original
+ )
+
diff --git a/muse2/share/scoreglyphs/feta-original/COPYING-lilypond b/muse2/share/scoreglyphs/feta-original/COPYING-lilypond
new file mode 100644
index 00000000..32f7714f
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/COPYING-lilypond
@@ -0,0 +1,359 @@
+If you want to redistribute LilyPond, you must comply with the GNU
+General Public License (reproduced below). This license applies to
+LilyPond with the following exceptions:
+
+- It does not apply to example input files (which are in
+the subdirectory input/) that explicitly specify another license.
+
+- If you create a document which uses fonts included in LilyPond, and
+embed this font or unaltered portions of this font into the document,
+then this font does not by itself cause the resulting document to be
+covered by the GNU General Public License. This exception does not
+however invalidate any other reasons why the document might be covered
+by the GNU General Public License. If you modify this font, you may
+extend this exception to your version of the font, but you are not
+obligated to do so. If you do not wish to do so, delete this exception
+statement from your version.
+
+
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/muse2/share/scoreglyphs/feta-original/GNUmakefile b/muse2/share/scoreglyphs/feta-original/GNUmakefile
new file mode 100644
index 00000000..389f7b9b
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/GNUmakefile
@@ -0,0 +1,198 @@
+# mf/GNUmakefile
+
+depth = ..
+
+STEPMAKE_TEMPLATES = metafont \
+ install \
+ install-out
+LOCALSTEPMAKE_TEMPLATES = lilypond
+
+include $(depth)/make/stepmake.make
+
+
+EXTRA_DIST_FILES += README mf2pt1.mp
+
+# We don't use $(MF_FILES), because there's more .mf cruft here
+FETA_MF_FILES = $(call src-wildcard,feta[0-9]*.mf) \
+ $(call src-wildcard,feta-braces-[a-z].mf) \
+ $(call src-wildcard,feta-alphabet*[0-9].mf) \
+ $(call src-wildcard,parmesan[0-9]*.mf)
+
+STAFF_SIZES = 11 13 14 16 18 20 23 26
+BRACES = a b c d e f g h i
+
+OTF_FILES = $(STAFF_SIZES:%=$(outdir)/emmentaler-%.otf) \
+ $(outdir)/aybabtu.otf
+PE_SCRIPTS = $(STAFF_SIZES:%=$(outdir)/emmentaler-%.pe)
+OTF_TABLES = $(STAFF_SIZES:%=$(outdir)/feta%.otf-table) \
+ $(BRACES:%=$(outdir)/feta-braces-%.otf-table)
+FETA_FONTS = $(FETA_MF_FILES:.mf=)
+SVG_FILES = $(OTF_FILES:%.otf=%.svg)
+
+FC_FIND = $(shell $(FCMATCH) --verbose 'Century Schoolbook L:style=$(1)' \
+ | grep 'file:' \
+ | sed 's/.*"\([^"]*\)".*/\1/g')
+
+NCSB_OTFS = $(addprefix $(outdir)/,CenturySchL-Ital.otf \
+ CenturySchL-BoldItal.otf \
+ CenturySchL-Roma.otf \
+ CenturySchL-Bold.otf)
+NCSB_INSTALL_DIR = $(local_lilypond_datadir)/fonts/otf
+
+LOG_FILES = $(FETA_MF_FILES:%.mf=$(outdir)/%.log)
+LISP_FILES = $(FETA_MF_FILES:%.mf=$(outdir)/%.lisp)
+ENC_FILES = $(FETA_MF_FILES:%.mf=$(outdir)/%.enc)
+TFM_FILES = $(FETA_MF_FILES:%.mf=$(outdir)/%.tfm)
+
+$(outdir)/aybabtu.otf-table: $(BRACES:%=$(outdir)/feta-braces-%.otf-table)
+ cat $^ > $@
+
+$(outdir)/aybabtu.otf-gtable: $(BRACES:%=$(outdir)/feta-braces-%.otf-gtable)
+ echo '(design_size . 20)' > $@
+
+
+# only for fonts which
+#
+# 1. are mentioned in font.scm
+#
+# 2. are not included with teTeX
+#
+
+$(outdir)/emmentaler-%.otf \
+$(outdir)/emmentaler-%.svg: $(outdir)/emmentaler-%.pe \
+ $(outdir)/feta%.pfb \
+ $(outdir)/feta-alphabet%.pfb \
+ $(outdir)/parmesan%.pfb \
+ $(outdir)/feta%.otf-table \
+ $(outdir)/feta%.otf-gtable
+ cd $(outdir) && $(FONTFORGE) -script $(notdir $(basename ,$@).pe)
+
+$(outdir)/aybabtu.otf \
+$(outdir)/aybabtu.svg: $(outdir)/aybabtu.pe \
+ $(foreach s,$(BRACES),$(outdir)/feta-braces-$(s).pfb) \
+ $(outdir)/aybabtu.otf-table $(outdir)/aybabtu.otf-gtable
+ cd $(outdir) && $(FONTFORGE) -script aybabtu.pe
+
+$(outdir)/%.pfb: $(outdir)/%.log
+
+$(outdir)/%.otf-table: $(outdir)/%.lisp
+ cat $< $(if $(findstring brace,$<),,$(subst feta,parmesan,$<)) \
+ $(if $(findstring brace,$<),,$(subst feta,feta-alphabet,$<)) > $@
+
+
+## ugh -- we want this to prevent failing -j2 compiles.
+$(outdir)/feta26.otf-table: $(outdir)/feta26.lisp \
+ $(outdir)/parmesan26.lisp \
+ $(outdir)/feta-alphabet26.lisp
+$(outdir)/feta23.otf-table: $(outdir)/feta23.lisp \
+ $(outdir)/parmesan23.lisp \
+ $(outdir)/feta-alphabet23.lisp
+$(outdir)/feta20.otf-table: $(outdir)/feta20.lisp \
+ $(outdir)/parmesan20.lisp \
+ $(outdir)/feta-alphabet20.lisp
+$(outdir)/feta18.otf-table: $(outdir)/feta18.lisp \
+ $(outdir)/parmesan18.lisp \
+ $(outdir)/feta-alphabet18.lisp
+$(outdir)/feta16.otf-table: $(outdir)/feta16.lisp \
+ $(outdir)/parmesan16.lisp \
+ $(outdir)/feta-alphabet16.lisp
+$(outdir)/feta14.otf-table: $(outdir)/feta14.lisp \
+ $(outdir)/parmesan14.lisp \
+ $(outdir)/feta-alphabet14.lisp
+$(outdir)/feta13.otf-table: $(outdir)/feta13.lisp \
+ $(outdir)/parmesan13.lisp \
+ $(outdir)/feta-alphabet13.lisp
+$(outdir)/feta11.otf-table: $(outdir)/feta11.lisp \
+ $(outdir)/parmesan11.lisp \
+ $(outdir)/feta-alphabet11.lisp
+
+$(outdir)/aybabtu.otf: $(outdir)/aybabtu.subfonts \
+ $(outdir)/aybabtu.fontname \
+ $(outdir)/aybabtu.otf-table \
+ $(outdir)/aybabtu.otf-gtable \
+ $(outdir)/aybabtu.pe
+
+$(outdir)/aybabtu.otf \
+$(outdir)/aybabtu.svg: $(BRACES:%=$(outdir)/feta-braces-%.pfb)
+
+$(outdir)/aybabtu.fontname:
+ echo -n 'aybabtu' > $@
+$(outdir)/aybabtu.subfonts:
+ echo $(subst .mf,,$(call src-wildcard,feta-braces-[a-z].mf)) > $@
+
+$(PE_SCRIPTS): $(buildscript-dir)/gen-emmentaler-scripts
+ $< --dir=$(outdir)
+
+ALL_FONTS = $(FETA_FONTS)
+PFB_FILES = $(ALL_FONTS:%=$(outdir)/%.pfb)
+
+# Make tfm files first, log files last,
+# so that normally log files aren't made twice
+ALL_GEN_FILES = $(LOG_FILES) \
+ $(ENC_FILES) \
+ $(LISP_FILES) \
+ $(OTF_TABLES) \
+ $(NCSB_OTFS) \
+ $(PFB_FILES) \
+ $(OTF_FILES) \
+ $(SVG_FILES)
+
+# PRE_INSTALL=$(MAKE) "$(ALL_GEN_FILES)"
+
+INSTALLATION_DIR = $(local_lilypond_datadir)/fonts/source
+INSTALLATION_FILES = $(MF_FILES)
+
+INSTALLATION_OUT_SUFFIXES = 1 2 3
+
+INSTALLATION_OUT_DIR1 = $(local_lilypond_datadir)/fonts/otf
+INSTALLATION_OUT_FILES1 = $(OTF_FILES) \
+ $(NCSB_OTFS)
+
+INSTALLATION_OUT_DIR2 = $(local_lilypond_datadir)/fonts/svg
+INSTALLATION_OUT_FILES2 = $(SVG_FILES)
+
+INSTALLATION_OUT_DIR3 = $(local_lilypond_datadir)/fonts/type1
+INSTALLATION_OUT_FILES3 = $(PFB_FILES)
+
+export MFINPUTS := .:$(MFINPUTS)
+
+
+default: $(ALL_GEN_FILES) \
+ $(outdir)/emmentaler-20.otf \
+ tree-regen \
+ $(outdir)/fonts.conf
+
+.PHONY: tree-regen
+
+# FIXME: temporary hack: must regenerate after building fonts
+tree-regen: $(ALL_GEN_FILES)
+ ${MAKE} -C $(top-build-dir) link-mf-tree
+
+##
+## todo: this also depends on .tfm, FIXME.
+$(outdir)/%.lisp \
+$(outdir)/%.otf-gtable \
+$(outdir)/%.enc \
+$(outdir)/%.pe: $(outdir)/%.log
+ $(buildscript-dir)/mf-to-table \
+ --global-lisp=$(outdir)/$(<F:.log=.otf-gtable) \
+ --lisp=$(outdir)/$(<F:.log=.lisp) \
+ --outdir=$(outdir) \
+ --enc $(outdir)/$(<F:.log=.enc) \
+ $<
+
+local-clean:
+ rm -f mfplain.mem mfplain.log
+ rm -f *.tfm *.log
+
+
+$(outdir)/fonts.conf:
+ echo '<fontconfig><dir>'$(shell cd $(outdir); pwd)'</dir></fontconfig>' > $@
+
+$(NCSB_OTFS): $(NCSB_SOURCE_FILES) \
+ $(auxscript-dir)/pfx2ttf.fontforge
+ $(foreach i, $(basename $(NCSB_SOURCE_FILES)), \
+ $(FONTFORGE) -script $(auxscript-dir)/pfx2ttf.fontforge \
+ $(i).pfb $(i).afm $(outdir)/ && ) true
+
+# eof
diff --git a/muse2/share/scoreglyphs/feta-original/README b/muse2/share/scoreglyphs/feta-original/README
new file mode 100644
index 00000000..9d52194b
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/README
@@ -0,0 +1,125 @@
+
+This is a font of music symbols. All MF sources are original. Most of the
+documentation is in comments in the MF code.
+
+Non-square pixels are not supported; with other words, the horizontal and
+vertical resolution of the output device must be the same.
+
+Currently, outline fonts are created by using `autotrace', but we are
+already in the process of converting the MF code directly to PostScript code
+with a tool called `mf2pt1', which in turn calls `FontForge' to postprocess
+the output (mainly to remove outline overlaps and to add hints).
+
+The recommended calling sequence of mf2pt1 is
+
+ mf2pt1 --rounding=0.0001 <other options> <font>
+
+You need mf2pt1 version 2.1 or newer.
+
+
+Here some guidelines to assure a clean conversion.
+
+. Never use `---'. Replace it with `--' together with explicit path
+ directions (if necessary).
+
+. Don't use self-intersecting outlines in general since they can confuse
+ mf2pt1's algorithm to get the orientation of a closed path. Note that
+ MetaPost's implementation of the `turningnumber' primitive (which would
+ immediately give the orientation of a path) is severely broken before
+ version 1.0 of MetaPost, thus some hand-made code in mf2pt1.mp is used
+ to work around this bug.
+
+. If outlines intersect, avoid grazing intersections. In case two outlines
+ intersect in an explicitly defined point, include this point in both
+ intersecting paths to avoid problems due to rounding errors.
+
+. Don't use `draw' with a polygonal pen but for straight lines (consisting
+ of exactly two points). In most cases it is quite easy to emulate `draw'
+ with an explicit definition of the outline or with `penstroke'.
+
+. Don't apply transformations after calling `fill' -- for example, don't
+ mirror `currentpicture'. Instead, transform the path and call `fill'
+ afterwards. This ensures that mf2pt1 gets the correct outline directions
+ which is a necessary prerequisite for FontForge's algorithm to remove
+ overlaps.
+
+
+Some glyph name rules:
+
+. Most glyph names have the form <group>.<name>, where <group> is defined
+ with the `fet_begingroup' command, and <name> is given with
+ `fet_beginchar' (within a `fet_begingroup' block). Example:
+ `clefs.vaticana.fa'.
+
+. Sometimes it would be sensible to use negative numbers in glyph names.
+ However, the `-' character shouldn't be used in a glyph name. Replace it
+ with `M'. For example, write `rests.M3mensural' instead of
+ `rests.-3mensural'.
+
+. Glyphs which exist in both an `up' and `down' version should start the
+ <name> part with either `u' or `d', respectively. Example: `flags.d3',
+ `flags.u3'. Glyphs which are neutral w.r.t. the direction, and where
+ members of the glyph group exist which have `up' and `down' versions,
+ should start with an `s'. Example: `noteheads.s0re'.
+
+
+Some design rules:
+
+. Always use smooth curve transitions. Since this is difficult to see in
+ MetaFont proof sheets (which don't show the tangents) I recommend to call
+ mf2pt1 like this
+
+ FONTFORGE=foo mf2pt1 ...
+
+ (`foo' should be a non-existent program; this avoids the default
+ postprocessing). Then call FontForge to inspect the outlines.
+
+. Use rounded corners.
+
+
+Hints for stem attachment:
+
+. Stem attachment of glyphs is controlled by two special variables called
+ `charwx' and `charwy'. Stems can be regarded as (very oblonged)
+ rectangles with slightly rounded corners. For stems pointing upwards the
+ lower right corner of this rectangle is attached to the glyph at position
+ (charwx, charwy). For stems pointing downwards it works analogously but
+ with the upper left corner, where the position of the attachment point is
+ additionally reflected horizontally about the center of the glyph -- this
+ ensures that in most cases charwx and charwy can be set to the same values
+ for up and down stems even though these are attached at the right/left end
+ of the note, respectively. To make this more precise, the upper left
+ corner of a down stem is attached at position (charwd/2 - charwx, charwy),
+ where `charwd' is an internal metafont variable representing the glyph
+ width as specified by the `set_char_box' command.
+
+. In case different stem attachments for upward and downward pointing stems
+ are needed, two separate glyphs must be defined in the Metafont file; of
+ course, this also applies if two entirely different shapes are needed.
+ These have the same name but are prefixed by `u' and `d', respectively
+ (for `up' and `down', obviously). In each of these glyphs the variables
+ charwx and charwy must be set accordingly. If, on the other hand, the
+ attachment point is the `same' for both directions (with the
+ abovementioned horizontal reflection taken into account), then the prefix
+ `s' (for `symmetric') should be used. See the existing files for
+ examples. The numbers in the glyph names refer to the duration of the
+ note; e.g., `s0cross' in feta-bolletjes.mf defines the notehead for a
+ whole cross-shaped note (similarly, `s1cross' and `s2cross' are for half
+ and quarter notes, respectively).
+
+
+Finally, some rules to assure that rasterization at low resolutions gives
+good results. Today, this is a minor issue, but in some cases it might show
+design flaws.
+
+. Use `define_whole_pixels' and friends where appropriate.
+
+. Use `hround' and `vround' consistently. A lot of auxiliary macros are
+ defined in feta-macros.mf.
+
+. If a path element is duplicated or shifted, use an integer value for the
+ offset.
+
+. Add `eps' for mirrored paths to assure correct MetaFont rasterization.
+ See the comment and the variables at the end of `feta-params.mf' for
+ details how vertical symmetry should be achieved.
diff --git a/muse2/share/scoreglyphs/feta-original/aybabtu.pe.in b/muse2/share/scoreglyphs/feta-original/aybabtu.pe.in
new file mode 100644
index 00000000..0130cff2
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/aybabtu.pe.in
@@ -0,0 +1,84 @@
+#!@FONTFORGE@
+# all your brace are belong to us
+
+Open("feta-braces-b.pfb");
+SelectAll();
+Scale(200, 0, 0);
+Generate("feta-braces-b.scale.pfb");
+
+Open("feta-braces-c.pfb");
+SelectAll();
+Scale(300, 0, 0);
+Generate("feta-braces-c.scale.pfb");
+
+Open("feta-braces-d.pfb");
+SelectAll();
+Scale(400, 0, 0);
+Generate("feta-braces-d.scale.pfb");
+
+Open("feta-braces-e.pfb");
+SelectAll();
+Scale(500, 0, 0);
+Generate("feta-braces-e.scale.pfb");
+
+Open("feta-braces-f.pfb");
+SelectAll();
+Scale(600, 0, 0);
+Generate("feta-braces-f.scale.pfb");
+
+Open("feta-braces-g.pfb");
+SelectAll();
+Scale(700, 0, 0);
+Generate("feta-braces-g.scale.pfb");
+
+Open("feta-braces-h.pfb");
+SelectAll();
+Scale(800, 0, 0);
+Generate("feta-braces-h.scale.pfb");
+
+Open("feta-braces-i.pfb");
+SelectAll();
+Scale(900, 0, 0);
+Generate("feta-braces-i.scale.pfb");
+
+
+New()
+
+MergeFonts("feta-braces-a.pfb");
+MergeFonts("feta-braces-b.scale.pfb");
+MergeFonts("feta-braces-c.scale.pfb");
+MergeFonts("feta-braces-d.scale.pfb");
+MergeFonts("feta-braces-e.scale.pfb");
+MergeFonts("feta-braces-f.scale.pfb");
+MergeFonts("feta-braces-g.scale.pfb");
+MergeFonts("feta-braces-h.scale.pfb");
+MergeFonts("feta-braces-i.scale.pfb");
+
+SetFontNames("Aybabtu-Regular", "Aybabtu", "Aybabtu Regular", "Regular", "GNU GPL", "@TOPLEVEL_VERSION@");
+
+i = 0;
+while (i < CharCnt())
+ Select(i);
+# crashes fontforge, use PUA for now -- jcn
+# SetUnicodeValue(i + 0xF0000, 0);
+/*
+PRIVATE AREA
+ In the BMP, the range 0xe000 to 0xf8ff will never be assigned to any
+ characters by the standard and is reserved for private usage. For the
+ Linux community, this private area has been subdivided further into the
+ range 0xe000 to 0xefff which can be used individually by any end-user
+ and the Linux zone in the range 0xf000 to 0xf8ff where extensions are
+ coordinated among all Linux users. The registry of the characters
+ assigned to the Linux zone is currently maintained by H. Peter Anvin
+ <Peter.Anvin@linux.org>.
+*/
+ SetUnicodeValue(i + 0xE000, 0);
+ ++i;
+endloop
+
+LoadTableFromFile("LILF", "aybabtu.subfonts")
+LoadTableFromFile("LILC", "aybabtu.otf-table")
+LoadTableFromFile("LILY", "aybabtu.otf-gtable")
+
+Generate("aybabtu.otf");
+Generate("aybabtu.svg");
diff --git a/muse2/share/scoreglyphs/feta-original/bigcheese.pe.in b/muse2/share/scoreglyphs/feta-original/bigcheese.pe.in
new file mode 100644
index 00000000..46b74f0a
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/bigcheese.pe.in
@@ -0,0 +1,44 @@
+#!@FONTFORGE@
+
+
+
+New();
+
+# Separate Feta versioning?
+# Naming: * expose LilyPond20/LilyPond rather than bigcheese
+# * using 20 as Weight works for gnome-font-select widget: gfs
+SetFontNames("bigcheese20", "LilyPond", "LilyPond BigCheese 20", "20", "GNU GPL", "@TOPLEVEL_VERSION@");
+
+MergeFonts("feta20.pfa");
+MergeFonts("parmesan20.pfa");
+
+# load nummer/din after setting PUA.
+i = 0;
+while (i < CharCnt())
+ Select(i);
+# crashes fontforge, use PUA for now -- jcn
+# SetUnicodeValue(i + 0xF0000, 0);
+/*
+PRIVATE AREA
+ In the BMP, the range 0xe000 to 0xf8ff will never be assigned to any
+ characters by the standard and is reserved for private usage. For the
+ Linux community, this private area has been subdivided further into the
+ range 0xe000 to 0xefff which can be used individually by any end-user
+ and the Linux zone in the range 0xf000 to 0xf8ff where extensions are
+ coordinated among all Linux users. The registry of the characters
+ assigned to the Linux zone is currently maintained by H. Peter Anvin
+ <Peter.Anvin@linux.org>.
+*/
+ SetUnicodeValue(i + 0xE000, 0);
+ ++i;
+endloop
+
+
+MergeFonts("feta-nummer10.pfa");
+MergeFonts("feta-din14.pfa");
+MergeKern("feta-din14.tfm");
+
+LoadTableFromFile("LILC", "feta20.otf-table")
+
+Generate("bigcheese20.otf");
+Generate("bigcheese20.cff");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-accordion.mf b/muse2/share/scoreglyphs/feta-original/feta-accordion.mf
new file mode 100644
index 00000000..f1058000
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-accordion.mf
@@ -0,0 +1,445 @@
+%
+% feta-accordion.mf -- draw accordion symbols
+%
+% source file of the GNU LilyPond music typesetter
+%
+% (c) 1998--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+fet_begingroup ("accordion");
+
+%
+% These dimensions are the same for all register symbols.
+% The different symbols should calculate their other dimensions from them.
+%
+
+accreg_dot_size# := .5 staff_space#;
+accreg_linethickness# := 1.3 stafflinethickness#;
+accreg_lh# := 1.0 staff_space#;
+
+define_pixels (accreg_dot_size, accreg_linethickness, accreg_lh);
+
+
+fet_beginchar ("accDiscant", "accDiscant")
+ save r, pat, lh, lt;
+ path pat;
+
+ r# = 3/2 accreg_lh#;
+ define_pixels (r);
+
+ set_char_box (r# + accreg_linethickness# / 2,
+ r# + accreg_linethickness# / 2,
+ 0, 2 r# + 0.7 accreg_linethickness#);
+
+ lh = vround (2/3 r);
+ lt = vround (0.7 accreg_linethickness);
+
+ h := 3 lh + lt;
+ b := w := (3 lh + hround accreg_linethickness) / 2;
+
+ penpos1 (hround accreg_linethickness, 0);
+ penpos2 (lt, 90);
+ penpos3 (hround accreg_linethickness, 180);
+ penpos4 (lt, 270);
+
+ z1r = (w, h / 2);
+ z2r = (0, h);
+ z3r = (-b, h / 2);
+ z4r = (0, 0);
+
+ penlabels (1, 2, 3, 4);
+
+ % mf doesn't handle pixel dropouts in outline objects, so we use
+ % `draw' if not called by mpost
+ if known miterlimit:
+ fill z1r
+ .. z2r
+ .. z3r
+ .. z4r
+ .. cycle;
+ unfill z1l
+ .. z2l
+ .. z3l
+ .. z4l
+ .. cycle;
+ else:
+ pickup pencircle xscaled accreg_linethickness yscaled lt;
+ draw z1
+ .. z2
+ .. z3
+ .. z4
+ .. cycle;
+ fi;
+
+ pat := z4{right}
+ .. z1{up}
+ .. {left}z2;
+
+ pickup penrazor scaled lt rotated 90;
+
+ top z5 = pat intersectionpoint ((0, lh + lt) -- (w, lh + lt));
+ z6 = z5 xscaled -1;
+ bot z7 = pat intersectionpoint ((0, 2 lh) -- (w, 2 lh));
+ z8 = z7 xscaled -1;
+
+ labels (5, 6, 7, 8);
+
+ draw z5
+ -- z6;
+ draw z7
+ -- z8;
+fet_endchar;
+
+
+fet_beginchar ("accDot", "accDot")
+ set_char_box (accreg_dot_size# / 2, accreg_dot_size# / 2,
+ accreg_dot_size# / 2, accreg_dot_size# / 2);
+
+ pickup pencircle scaled accreg_dot_size;
+
+ rt x0 = hround (accreg_dot_size / 2);
+ top y0 = vround (accreg_dot_size / 2);
+
+ drawdot z0;
+fet_endchar;
+
+
+fet_beginchar ("accFreebase", "accFreebase")
+ save r, lh, lt;
+
+ r# = accreg_lh#;
+ define_pixels (r);
+
+ set_char_box (r# + accreg_linethickness# / 2,
+ r# + accreg_linethickness# / 2,
+ 0, 2 r# + 0.7 accreg_linethickness#);
+
+ lh = vround r;
+ lt = vround (0.7 accreg_linethickness);
+
+ h := 2 lh + lt;
+ b := w := (2 lh + hround accreg_linethickness) / 2;
+
+ penpos1 (hround accreg_linethickness, 0);
+ penpos2 (lt, 90);
+ penpos3 (accreg_linethickness, 180);
+ penpos4 (lt, 270);
+
+ z1r = (w, h / 2);
+ z2r = (0, h);
+ z3r = (-b, h / 2);
+ z4r = (0, 0);
+
+ penlabels (1, 2, 3, 4);
+
+ % mf doesn't handle pixel dropouts in outline objects, so we use
+ % `draw' if not called by mpost
+ if known miterlimit:
+ fill z1r
+ .. z2r
+ .. z3r
+ .. z4r
+ .. cycle;
+ unfill z1l
+ .. z2l
+ .. z3l
+ .. z4l
+ .. cycle;
+ else:
+ pickup pencircle xscaled accreg_linethickness yscaled lt;
+ draw z1
+ .. z2
+ .. z3
+ .. z4
+ .. cycle;
+ fi;
+
+ pickup penrazor scaled lt rotated 90;
+
+ draw z1
+ -- z3;
+fet_endchar;
+
+
+fet_beginchar ("accStdbase", "accStdbase")
+ save r, p, lh, lt;
+ path pat;
+
+ r# = 2 accreg_lh#;
+ define_pixels (r);
+
+ set_char_box (r# + accreg_linethickness# / 2,
+ r# + accreg_linethickness# / 2,
+ 0, 2 r# + 0.7 accreg_linethickness#);
+
+ lh = vround (1/2 r);
+ lt = vround (0.7 accreg_linethickness);
+
+ h := 4 lh + lt;
+ b := w := (4 lh + hround accreg_linethickness) / 2;
+
+ penpos1 (hround accreg_linethickness, 0);
+ penpos2 (lt, 90);
+ penpos3 (hround accreg_linethickness, 180);
+ penpos4 (lt, 270);
+
+ z1r = (w, h / 2);
+ z2r = (0, h);
+ z3r = (-b, h / 2);
+ z4r = (0, 0);
+
+ penlabels (1, 2, 3, 4);
+
+ % mf doesn't handle pixel dropouts in outline objects, so we use
+ % `draw' if not called by mpost
+ if known miterlimit:
+ fill z1r
+ .. z2r
+ .. z3r
+ .. z4r
+ .. cycle;
+ unfill z1l
+ .. z2l
+ .. z3l
+ .. z4l
+ .. cycle;
+ else:
+ pickup pencircle xscaled accreg_linethickness yscaled lt;
+ draw z1
+ .. z2
+ .. z3
+ .. z4
+ .. cycle;
+ fi;
+
+ pat := z4{right}
+ .. z1{up}
+ .. {left}z2;
+
+ pickup penrazor scaled lt rotated 90;
+
+ top z5 = pat intersectionpoint ((0, lh + lt) -- (w, lh + lt));
+ z6 = z5 xscaled -1;
+ bot z7 = pat intersectionpoint ((0, 3 lh) -- (w, 3 lh));
+ z8 = z7 xscaled -1;
+
+ labels (5, 6, 7, 8);
+
+ draw z1
+ -- z3;
+ draw z5
+ -- z6;
+ draw z7
+ -- z8;
+fet_endchar;
+
+
+fet_beginchar ("accBayanbase", "accBayanbase")
+ save lh, lt;
+
+ lh = vround accreg_lh;
+ lt = vround accreg_linethickness;
+
+ set_char_box (accreg_lh# + accreg_linethickness# / 2,
+ accreg_lh# + accreg_linethickness# / 2,
+ 0, 3 accreg_lh# + accreg_linethickness#);
+
+ h := 3 lh + lt;
+
+ draw_rounded_block ((-w, 0), (-w + lt, h), lt);
+ draw_rounded_block ((w - lt, 0), (w, h), lt);
+
+ pickup penrazor scaled lt rotated 90;
+
+ bot z1 = (-w + lt / 2, 0);
+ bot z2 = (-w + lt / 2, lh);
+ bot z3 = (-w + lt / 2, 2 lh);
+ bot z4 = (-w + lt / 2, 3 lh);
+
+ bot z5 = (w - lt / 2, 0);
+ bot z6 = (w - lt / 2, lh);
+ bot z7 = (w - lt / 2, 2 lh);
+ bot z8 = (w - lt / 2, 3 lh);
+
+ draw z1
+ -- z5;
+ draw z2
+ -- z6;
+ draw z3
+ -- z7;
+ draw z4
+ -- z8;
+fet_endchar;
+
+
+def def_B (expr w, h) =
+ pickup pencircle scaled 0.15 linethickness;
+
+ penpos10 (thin, -90);
+ penpos11 (thin, -90);
+ penpos12 (thick, 0);
+ penpos13 (thin, 90);
+ penpos14 (thin, 90);
+
+ penpos15 (thick, 180);
+ penpos16 (thin, -90);
+ penpos17 (thin, -90);
+ penpos18 (thick, 0);
+ penpos19 (thick, 0);
+
+ z10 = (0, 0);
+ z11 = (cOne * w, 0);
+ z12 = (w, .5 mb * h);
+ z13 = (cTwo * w, mb * h);
+ z14 = (2 thick, mb * h);
+ z15 = (.94 w, h - .5 mt * h);
+ z16 = z13 + (0, mt * h);
+ z17 = (0, h);
+ z18 = (1.5 thick, 0);
+ z19 = (1.5 thick, h);
+enddef;
+
+
+def def_S (expr w, h) =
+ pickup pencircle scaled 0.03 linethickness;
+
+ penpos1 (thin, 180);
+ penpos2 (thin, -90);
+ penpos3 (thick, 0);
+ penpos4 (.5 thick, 90);
+ penpos5 (thick, 0);
+ penpos6 (thin, -90);
+ penpos7 (thin, 180);
+ penpos8 (thin, 180);
+ penpos9 (thin, 0);
+
+ z1 = (0, hs);
+ z2 = (w / 2, 0);
+ z3 = (w - .5 thick, .5 mb * h);
+ z4 = (w / 2, mb * h);
+ z5 = (.5 thick, h - .5 mt * h);
+ z6 = (w / 2, h);
+ z7 = (w, h - hs);
+ z8 = (0, y2r);
+ z9 = (w, y6l);
+
+ path bue, bueoverst;
+
+ bue := z2{left}
+ .. z1{up};
+
+ t := xpart (bue intersectiontimes (z8l -- z7l));
+
+ bueoverst := z6{right}
+ .. z7{down};
+enddef;
+
+
+def def_some_vars =
+ save hs, mb, mt, thin, thick, height, width, cOne, cTwo;
+ save bx, hx;
+
+ width = .8 (4 staff_space);
+ height = 2.4 staff_space;
+ % URG. smaller sizes should be wider and fatter
+ % thin = 0.05 staff_space;
+ % thick = 0.2 staff_space;
+
+ 4 hx + bx = 1.15;
+ 10 hx + bx = 1;
+ fatten := designsize * hx + bx * 1.2;
+ thick := 0.2 staff_space * fatten;
+
+ % urg: mustn't ever go thinner than blot!
+ thin# := blot_diameter#;
+ define_pixels (thin);
+
+ hs = 0.4 staff_space;
+ mb = .53;
+ mt = .47;
+ cOne = 0.65;
+ cTwo = 0.60;
+enddef;
+
+
+fet_beginchar ("accOldEE", "accOldEE")
+ save r, pp, ir, lh, lt, stroke_width;
+
+ r# = staff_space#;
+ define_pixels (r);
+
+ lr = .4 staff_space - linethickness;
+ ir = .6 staff_space;
+ stroke_width = .05 staff_space + .5 linethickness;
+
+ set_char_box (r# + accreg_linethickness# / 2,
+ r# + accreg_linethickness# / 2,
+ 0, 2 r# + 0.7 accreg_linethickness#);
+
+ z1 = (0, 0);
+ z2 = (0, ir);
+ z3 = (0, -ir);
+
+ penpos1 (blot_diameter, 0);
+ penpos2 (stroke_width + blot_diameter, 0);
+ penpos3 (stroke_width + blot_diameter, 0);
+
+ pickup pencircle scaled (lr + blot_diameter);
+
+ for pp := 0 step 45 until 135:
+ drawdot z2 rotated pp;
+ drawdot z3 rotated pp;
+
+ penstroke (z2e
+ -- z1e
+ -- z3e) rotated pp;
+ endfor;
+
+ pickup pencircle scaled lr;
+
+ drawdot (0, 0);
+
+ currentpicture := currentpicture shifted (0, h / 2);
+
+ lh = vround (2 r);
+ lt = vround (0.7 accreg_linethickness);
+
+ h := lh + lt;
+ b := w := (lh + hround accreg_linethickness) / 2;
+
+ penpos10 (hround accreg_linethickness, 0);
+ penpos11 (lt, 90);
+ penpos12 (hround accreg_linethickness, 180);
+ penpos13 (lt, 270);
+
+ z10r = (w, h / 2);
+ z11r = (0, h);
+ z12r = (-b, h / 2);
+ z13r = (0, 0);
+
+ % penlabels (1, 2, 10, 11, 12, 13);
+
+ % mf doesn't handle pixel dropouts in outline objects, so we use
+ % `draw' if not called by mpost
+ if known miterlimit:
+ fill z10r
+ .. z11r
+ .. z12r
+ .. z13r
+ .. cycle;
+ unfill z10l
+ .. z11l
+ .. z12l
+ .. z13l
+ .. cycle;
+ else:
+ pickup pencircle xscaled accreg_linethickness yscaled lt;
+ draw z10
+ .. z11
+ .. z12
+ .. z13
+ .. cycle;
+ fi;
+fet_endchar;
+
+
+fet_endgroup ("accordion");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet.mf
new file mode 100644
index 00000000..c3d1f09f
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet.mf
@@ -0,0 +1,19 @@
+test := 0;
+
+staffsize# := design_size * pt#;
+
+input feta-autometric;
+input feta-macros;
+input feta-params;
+
+fet_beginfont ("feta-alphabet", design_size, "fetaNumber");
+
+mode_setup;
+
+number_design_size := design_size / 2;
+dynamic_design_size := 14 design_size / 20;
+
+input feta-nummer-code;
+input feta-din-code;
+
+fet_endfont ("feta-nummer");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet11.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet11.mf
new file mode 100644
index 00000000..04ba4e38
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet11.mf
@@ -0,0 +1,6 @@
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 11.22;
+input feta-alphabet;
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet13.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet13.mf
new file mode 100644
index 00000000..d314f40d
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet13.mf
@@ -0,0 +1,6 @@
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 12.60;
+input feta-alphabet;
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet14.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet14.mf
new file mode 100644
index 00000000..9a1bd2ee
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet14.mf
@@ -0,0 +1,6 @@
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 14.14;
+input feta-alphabet;
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet16.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet16.mf
new file mode 100644
index 00000000..86eb9c8c
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet16.mf
@@ -0,0 +1,6 @@
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 15.87;
+input feta-alphabet;
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet18.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet18.mf
new file mode 100644
index 00000000..db216c15
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet18.mf
@@ -0,0 +1,6 @@
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 17.82;
+input feta-alphabet;
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet20.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet20.mf
new file mode 100644
index 00000000..0affe390
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet20.mf
@@ -0,0 +1,7 @@
+% feta-alphabet20.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 20;
+input feta-alphabet;
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet23.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet23.mf
new file mode 100644
index 00000000..c8a725e5
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet23.mf
@@ -0,0 +1,7 @@
+% feta-alphabet23.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 22.45;
+input feta-alphabet;
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-alphabet26.mf b/muse2/share/scoreglyphs/feta-original/feta-alphabet26.mf
new file mode 100644
index 00000000..71af0403
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-alphabet26.mf
@@ -0,0 +1,6 @@
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 25.20;
+input feta-alphabet;
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-arrow.mf b/muse2/share/scoreglyphs/feta-original/feta-arrow.mf
new file mode 100644
index 00000000..f0c39c78
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-arrow.mf
@@ -0,0 +1,169 @@
+%
+% feta-arrow.mf -- draw arrow heads
+%
+% source file of the GNU LilyPond music typesetter
+%
+% (c) 2005--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+fet_begingroup ("arrowheads");
+
+%
+% To consider: we could put arrow heads at their real Unicode locations.
+%
+
+%
+% Set up paths for upper half of arrow head pointing right.
+% CLOSE_PATH is for a closed arrow, OPEN_PATH is for the open arrow.
+% OPEN_TENSION sets the tension for the part which forms the path in
+% OPEN_PATH.
+%
+
+def set_arrow_paths (expr width, height, open_tension, arrowlinethickness) =
+ save pat, finalpath;
+ save tip_angle_o, tip_angle_c, tip_dir_c, tip_dir_o;
+ save indent;
+ path pat, open_path, close_path;
+ pair tip_dir_o, tip_dir_c;
+
+ pickup pencircle scaled arrowlinethickness;
+
+ indent = linethickness / 2;
+
+ lft x1 = -width;
+ x2 = 0;
+ top y1 = height;
+ y2 = 0;
+
+ z4 = z3;
+ y5 = 0;
+ x5 = x4 + indent;
+
+ pat := z1
+ ..tension open_tension.. z2{right};
+ penpos2 (arrowlinethickness, 90);
+ tip_dir_o := direction 0.0 of pat;
+ tip_angle_o := angle (tip_dir_o);
+ penpos1 (arrowlinethickness, 90 + tip_angle_o);
+ z3 = z1;
+ penpos3 (arrowlinethickness, tip_angle_o);
+
+ open_path := z1r{tip_dir_o}
+ .. z2r{right}
+ .. z2l{left}
+ .. z1l{-tip_dir_o}
+ .. z3l
+ .. cycle;
+
+ pat := z4
+ .. z5{down};
+ tip_dir_c := direction 0.0 of pat;
+ tip_angle_c := angle (tip_dir_c);
+ penpos4 (arrowlinethickness, 90+ tip_angle_c);
+ penpos5 (arrowlinethickness, 0);
+ z6 = z5;
+ penpos6 (arrowlinethickness, 90);
+
+ close_path := z4l{tip_dir_c}
+ .. z5l{down}
+ .. z6l{right}
+ .. z2l{right}
+ .. z2r{left}
+ ..tension open_tension.. z1r{-tip_dir_o}
+ .. z3l
+ .. cycle;
+enddef;
+
+
+fet_beginchar ("open", "open.01");
+ set_char_box (staff_space#, 1.6 linethickness# / 2,
+ 0.5 staff_space#, 0.5 staff_space#);
+ set_arrow_paths (staff_space, 0.5 staff_space,
+ 1.0, 1.6 linethickness);
+ fill open_path;
+ open_path := open_path yscaled -1;
+ fill open_path;
+
+ penlabels (1, 2, 3);
+ penlabels (4, 5, 6);
+fet_endchar;
+
+
+fet_beginchar ("open", "open.0M1");
+ set_char_box (1.6 linethickness# / 2, staff_space#,
+ 0.5 staff_space#, 0.5 staff_space#);
+ set_arrow_paths (staff_space, 0.5 staff_space,
+ 1.0, 1.6 linethickness);
+ fill open_path;
+ open_path := open_path yscaled -1;
+ fill open_path;
+ currentpicture := currentpicture xscaled -1;
+fet_endchar;
+
+
+fet_beginchar ("open", "open.11");
+ set_char_box (.5 staff_space#, .5 staff_space#,
+ 1.0 staff_space#, 1.6 linethickness# / 2);
+ set_arrow_paths (staff_space, 0.5 staff_space,
+ 1.0, 1.6 linethickness);
+ fill open_path;
+ open_path := open_path yscaled -1;
+ fill open_path;
+ currentpicture := currentpicture rotated 90;
+fet_endchar;
+
+
+fet_beginchar ("open", "open.1M1");
+ set_char_box (.5 staff_space#, .5 staff_space#,
+ 1.6 linethickness# / 2, 1.0 staff_space#);
+ set_arrow_paths (staff_space, 0.5 staff_space,
+ 1.0, 1.6 linethickness);
+ fill open_path;
+ open_path := open_path yscaled -1;
+ fill open_path;
+ currentpicture := currentpicture rotated 90;
+ currentpicture := currentpicture yscaled -1;
+fet_endchar;
+
+
+fet_beginchar ("close", "close.01");
+ set_char_box (staff_space#, 0, 0.5 staff_space#, 0.5 staff_space#);
+ set_arrow_paths (staff_space, 0.5 staff_space, 1.5, blot_diameter);
+ fill close_path;
+ close_path := close_path yscaled -1;
+ fill close_path;
+fet_endchar;
+
+
+fet_beginchar ("close", "close.0M1");
+ set_char_box (0, staff_space#, 0.5 staff_space#, 0.5 staff_space#);
+ set_arrow_paths (staff_space, 0.5 staff_space, 1.5, blot_diameter);
+ fill close_path;
+ close_path := close_path yscaled -1;
+ fill close_path;
+ currentpicture := currentpicture xscaled -1;
+fet_endchar;
+
+
+fet_beginchar ("close", "close.11");
+ set_char_box (.5 staff_space#, .5 staff_space#,
+ 1.0 staff_space#, 0.0 staff_space#);
+ set_arrow_paths (staff_space, 0.5 staff_space, 1.5, blot_diameter);
+ fill close_path;
+ close_path := close_path yscaled -1;
+ fill close_path;
+ currentpicture := currentpicture rotated 90;
+fet_endchar;
+
+
+fet_beginchar ("close", "close.1M1");
+ set_char_box (.5 staff_space#, .5 staff_space#,
+ 0.0 staff_space#, 1.0 staff_space#);
+ set_arrow_paths (staff_space, 0.5 staff_space, 1.5, blot_diameter);
+ fill close_path;
+ close_path := close_path yscaled -1;
+ fill close_path;
+ currentpicture := currentpicture rotated -90;
+fet_endchar;
+
+
+fet_endgroup ("arrowheads");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-autometric.mf b/muse2/share/scoreglyphs/feta-original/feta-autometric.mf
new file mode 100644
index 00000000..24a0e1b9
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-autometric.mf
@@ -0,0 +1,255 @@
+%
+% autometric.mf -- administrative MF routines
+%
+% source file of the Feta (not an acronym for Font-En-Tja)
+% pretty-but-neat music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+% Jan Nieuwenhuizen <janneke@gnu.org>
+%
+% These macros help create ascii logging output
+% to automate generation of the lily tables.
+% The output should be parsed by the mf-to-table script.
+
+
+message "******************************************************";
+message "Using feta Autometric macros.";
+message "order of messages: ";
+message " NAME/CODE/BP/WD/DP/HT/WX/WY";
+message "******************************************************";
+message "";
+
+
+% font or database?
+def fet_beginfont (expr name, size, encod) =
+ font_identifier := name & decimal size;
+ font_size size;
+ font_coding_scheme "asis";
+ message "@{font@:GNU@:LilyPond@:" & name
+ & "@:" & decimal size
+ & "@:" & encod
+ & "@}";
+ message "";
+enddef;
+
+
+def fet_endfont =
+ message "@{tnof@}";
+enddef;
+
+
+% group or table?
+def fet_begingroup (expr name) =
+begingroup;
+ save feta_group;
+ string feta_group;
+
+ feta_group := name;
+
+ message "@{group@:" & feta_group
+ & "@}";
+ message "";
+enddef;
+
+
+def fet_endgroup (expr name) =
+ message "@{puorg@:" & name
+ & "@}";
+ message "";
+endgroup;
+enddef;
+
+
+def autometric_parameter (expr name, value) =
+ message "@{parameter@:" & name
+ & "@:" & decimal value
+ & "@}";
+enddef;
+
+
+def autometric_output_char =
+ message "@{char@:" & charnamestr
+ & "@:" & decimal charcode
+ & "@:" & decimal charbp
+ & "@:" & decimal charwd
+ & "@:" & decimal chardp
+ & "@:" & decimal charht
+ & "@:" & decimal charwx
+ & "@:" & decimal charwy
+ & "@:" & idstr
+ & "@}";
+enddef;
+
+
+def hround_pixels (expr sharped) =
+ hround (sharped * hppp)
+enddef;
+
+
+def vround_pixels (expr sharped) =
+ vround (sharped * vppp)
+enddef;
+
+
+def tand (expr alpha) =
+ (sind alpha / cosd alpha)
+enddef;
+
+
+def to_bp (expr num) =
+ decimal (num * bp_per_pixel)
+enddef;
+
+
+% breapth, width, depth, height
+% breapth x-depth
+def set_char_box (expr b_sharp, w_sharp, d_sharp, h_sharp) =
+ save scharbp, scharht, scharwd, schardp;
+
+ % some paranoia if someone calls set_char_box (charwd, charbp, ...)
+ scharbp := b_sharp;
+ scharht := h_sharp;
+ schardp := d_sharp;
+ scharwd := w_sharp;
+
+ charbp := scharbp;
+ charht := scharht;
+ chardp := schardp;
+ charwd := scharwd;
+
+ w := hround (w_sharp * hppp);
+ b := hround (b_sharp * hppp);
+ h := vround (h_sharp * vppp);
+ d := vround (d_sharp * vppp);
+
+ charwx := charwd;
+ charwy := 0;
+
+ % additions for mf2pt1 (`bbox' is called `glyph_dimensions' starting
+ % with version 2.4.2)
+ if known bp_per_pixel:
+ special "% MF2PT1: bbox "
+ & to_bp (-b) & " "
+ & to_bp (-d) & " "
+ & to_bp (w) & " "
+ & to_bp (h);
+ special "% MF2PT1: glyph_dimensions "
+ & to_bp (-b) & " "
+ & to_bp (-d) & " "
+ & to_bp (w) & " "
+ & to_bp (h);
+ special "% MF2PT1: font_size " & decimal designsize;
+ special "% MF2PT1: font_slant " & decimal font_slant_;
+
+ for fvar = "font_identifier",
+ "font_coding_scheme",
+ "font_version",
+ "font_comment",
+ "font_family",
+ "font_weight",
+ "font_unique_id",
+ "font_name":
+ if known scantokens (fvar & "_"):
+ special "% MF2PT1: "
+ & fvar & " "
+ & scantokens (fvar & "_");
+ fi;
+ endfor;
+
+ for fvar = "font_underline_position",
+ "font_underline_thickness":
+ if known scantokens (fvar & "_"):
+ special "% MF2PT1: "
+ & fvar & " "
+ & scantokens ("decimal " & fvar & "_");
+ fi;
+ endfor;
+
+ special "% MF2PT1: font_fixed_pitch "
+ & (if font_fixed_pitch_: "1" else: "0" fi);
+
+ % this must come after the `font_size' special
+ special "% MF2PT1: charwd " & decimal charwd;
+ fi;
+enddef;
+
+
+def no_dimen_beginchar (expr c) =
+begingroup;
+ charcode := if known c: byte c else: 0; fi;
+ charic := 0;
+ clearxy;
+ clearit;
+ clearpen;
+ scantokens extra_beginchar;
+enddef;
+
+
+%
+% we leave the ctrl characters alone.
+%
+code := 32;
+
+
+% starts just as plain mf's beginchar:
+% charcode,
+% and then adds:
+% charname see below
+% id index in lily's table
+
+% The dimensions are uninitialised; you should use set_char_box manually.
+def fet_beginchar (expr name, id_lit) =
+ save idstr, charnamestr;
+ save charbp;
+ save w, b, h, d;
+ save charwx, charwy;
+
+ string idstr, charnamestr;
+ charnamestr := name;
+ idstr := id_lit;
+
+ % addition for mf2pt1
+ if known bp_per_pixel:
+ if known feta_group:
+ special "% MF2PT1: glyph_name "
+ & feta_group & "." & idstr;
+ else:
+ special "% MF2PT1: glyph_name " & idstr;
+ fi;
+ fi;
+
+ no_dimen_beginchar (incr code) name;
+enddef;
+
+
+def makebox_with_breapth (text r) =
+ for y = -d, 0, h:
+ r ((-b, y), (w, y));
+ endfor;
+
+ for x = -b, 0, w:
+ r ( (x, -d), (x, h));
+ endfor;
+enddef;
+
+
+%
+% override plain endchar. We want a different box.
+%
+def breapth_endchar =
+ scantokens extra_endchar;
+
+ if proofing > 0:
+ makebox_with_breapth (proofrule);
+ fi;
+
+ chardx := (w + b); % what the heck is chardx
+ shipit;
+endgroup;
+enddef;
+
+
+def fet_endchar =
+ autometric_output_char;
+ breapth_endchar;
+enddef;
diff --git a/muse2/share/scoreglyphs/feta-original/feta-banier.mf b/muse2/share/scoreglyphs/feta-original/feta-banier.mf
new file mode 100644
index 00000000..46b3b061
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-banier.mf
@@ -0,0 +1,550 @@
+%
+% feta-banier.mf -- draw flags
+%
+% source file of the GNU LilyPond music typesetter
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+fet_begingroup ("flags");
+
+save outer_path;
+path outer_path;
+
+%
+% Flags pointing down overlap with the notehead (in x-direction), so
+% the down-flag can be bigger.
+%
+
+upflag_width# = .65 black_notehead_width# + stemthickness# / 2;
+downflag_width# = .833 black_notehead_width# + stemthickness# / 2;
+
+right_upflag_space# = .0 upflag_width#;
+right_downflag_space# = .0 downflag_width#;
+
+%
+% Flags pointing down cannot overlap with the notehead in y-direction,
+% so they have less slant.
+%
+% Because of optical illusion, the utmost flag (bottom for
+% down-pointing, top for up-pointing) should be smaller than the other
+% flags. Adobe Sonata doesn't do this correctly. (Instead they have
+% an extension flag, which looks less elegant.)
+%
+
+save hip_thickness, foot_thickness;
+
+hip_thickness# = 1.0 linethickness# + 0.069 staff_space#;
+foot_thickness# = 1.2055 linethickness# + 0.06 staff_space#;
+
+define_pixels (hip_thickness, foot_thickness);
+
+%
+% Inspired by Adobe Sonata and [Wanske].
+% For example, see POSTSCRIPT Language -- program design,
+% page 119, and [Wanske], p 41, 42.
+%
+
+def draw_flag (expr center, flare, dims, hip_depth, foot_wid,
+ hip_thickness, foot_thickness, show_labels) =
+ save c;
+
+ clearxy;
+
+ c = 0.7;
+
+ penpos1 (flare, 90);
+ penpos2 (whatever, 0);
+
+ x2r - x2l = hround (hip_thickness);
+
+ penpos3 (foot_thickness, -20.0);
+
+ z1r = center;
+ z2r = center + (xpart (dims), -ypart (dims) * hip_depth);
+ z3r = center + (xpart (dims) * foot_wid, -ypart (dims));
+
+ x2r := hround x2r;
+ y2r := vround y2r;
+
+ outer_path := z3r{curl c}
+ .. z2r{up}
+ .. {up}z1r;
+
+ if show_labels = 1:
+ penlabels (1, 2, 3);
+ fi;
+
+ fill z1l{curl 0}
+ ..tension 1.1.. z2l{down}
+ .. {curl c}simple_serif (z3l, z3r, 80)
+ & outer_path
+ & z1r
+ -- cycle;
+enddef;
+
+%
+% TODO: calculate intersectpoint (see TeX book, p. 137)
+% TODO: calculate incision_depth
+%
+
+def add_flag (expr yoff, flare, hip_wid_multiplier, hip_dep_multiplier,
+ intersectpoint, hip_thickness, foot_thickness) =
+begingroup
+ save prev_center, prev_xextreme, prev_yextreme;
+ save rel_foot, ip, center, incision_depth;
+ save prev_hipwid, prev_footdep, prev_hipdep, wid, dep, hip_dep;
+ save hip_dep_ratio, foot_wid_ratio;
+ pair prev_center, center, foot, prev_xextreme, prev_yextreme;
+ pair ip, rel_foot;
+
+ incision_depth = 1.013;
+ prev_center = point 2 of outer_path;
+ prev_xextreme = point 1 of outer_path;
+ prev_yextreme = point 0 of outer_path;
+ prev_hipwid = xpart (prev_xextreme - prev_center);
+ prev_footdep = -ypart (prev_yextreme - prev_center);
+ prev_hipdep = -ypart (prev_xextreme - prev_center);
+ ip = point intersectpoint of outer_path;
+
+ wid = prev_hipwid * hip_wid_multiplier;
+ hip_dep = prev_hipdep * hip_dep_multiplier;
+
+ center = prev_center + (0, yoff);
+ rel_foot = incision_depth [(wid, hip_dep), ip - center];
+ dep = -ypart (rel_foot);
+ foot_wid_ratio = xpart (rel_foot) / wid;
+ hip_dep_ratio = hip_dep / dep;
+
+ draw_flag (center, flare, (wid, dep),
+ hip_dep_ratio, foot_wid_ratio,
+ hip_thickness, foot_thickness, 0);
+endgroup
+enddef;
+
+
+fet_beginchar ("8th Flag (up)", "u3");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+
+ flare = staff_space;
+ hip_depth_ratio = .72;
+ foot_width_ratio = .8;
+ hip_width# = upflag_width# - hip_thickness# / 2;
+ foot_depth# = 3 staff_space# - blot_diameter# / 2;
+ define_pixels (hip_width, foot_depth);
+
+ set_char_box (0,
+ hip_width# + stemthickness# / 2 + right_upflag_space#,
+ foot_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ draw_flag ((0,0), flare, (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 1);
+
+ draw_square_block ((-0.5 stemthickness_rounded, -staff_space_rounded),
+ (0, 0));
+fet_endchar;
+
+
+fet_beginchar ("16th Flag (up)", "u4");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ total_depth# = 3.5 staff_space# - blot_diameter# / 2;
+ flag_count = 2;
+ flare = .85 staff_space;
+ flagspace# = .85 staff_space#;
+ hip_depth_ratio = .72;
+ hip_width# = upflag_width# - hip_thickness# / 2;
+ flagspace# + foot_depth# = total_depth#;
+ foot_width_ratio = .8;
+ define_pixels (hip_width, foot_depth);
+ define_whole_vertical_pixels (flagspace);
+
+ set_char_box (0,
+ hip_width# + stemthickness# / 2 + right_upflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ draw_flag ((0, -flagspace), flare, (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 1);
+
+ add_flag (flagspace, flare, .97, 1.00, 1.25,
+ hip_thickness, foot_thickness);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -2 staff_space_rounded));
+fet_endchar;
+
+
+fet_beginchar ("32nd Flag (up)", "u5");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ flag_count = 3;
+ total_depth# = 4.25 staff_space#;
+ flare = .85 staff_space;
+ flagspace# = .87 staff_space#;
+ hip_depth_ratio = .72;
+ hip_width# = upflag_width# - hip_thickness# / 2;
+ foot_width_ratio = .8;
+
+ (flag_count - 1) * flagspace# + foot_depth# = total_depth#;
+
+ define_pixels (hip_width, foot_depth);
+ define_whole_vertical_pixels (flagspace);
+
+ set_char_box (0, hip_width# + right_upflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ draw_flag ((0, -2 flagspace), flare, (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 1);
+
+ add_flag (flagspace, flare, .97, 1.00, 1.25,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, .95, 1.05, 1.25,
+ hip_thickness, foot_thickness);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -3 staff_space_rounded));
+fet_endchar;
+
+
+fet_beginchar ("64th Flag (up)", "u6");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ flag_count = 4;
+ flare = .85 staff_space;
+ flagspace# = .9 staff_space#;
+ hip_depth_ratio = .72;
+ hip_width# = upflag_width# - hip_thickness# / 2;
+ total_depth# = 5.25 staff_space#;
+ foot_width_ratio = .8;
+
+ (flag_count - 1) * flagspace# + foot_depth# = total_depth#;
+
+ define_pixels (hip_width, foot_depth);
+ define_whole_vertical_pixels (flagspace);
+
+ set_char_box (0, hip_width# + right_upflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ draw_flag ((0, -(flag_count - 1) * flagspace), flare,
+ (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 1);
+
+ add_flag (flagspace, flare, .97, 1.00, 1.3,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, 1.00, 1.00, 1.25,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, .95, 1.05, 1.25,
+ hip_thickness, foot_thickness);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -4 staff_space_rounded));
+fet_endchar;
+
+
+fet_beginchar ("128th Flag (up)", "u7");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ flag_count = 5;
+ flare = .85 staff_space;
+ flagspace# = .93 staff_space#;
+ hip_depth_ratio = .72;
+ hip_width# = upflag_width# - hip_thickness# / 2;
+ total_depth# = 6.25 staff_space#;
+ foot_width_ratio = .8;
+
+ (flag_count - 1) * flagspace# + foot_depth# = total_depth#;
+
+ define_pixels (hip_width, foot_depth);
+ define_whole_vertical_pixels (flagspace);
+
+ set_char_box (0, hip_width# + right_upflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ draw_flag ((0, -(flag_count - 1) * flagspace), flare,
+ (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 1);
+
+ add_flag (flagspace, flare, .97, 1.00, 1.3,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, 1.00, 1.00, 1.25,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, 1.00, 1.00, 1.25,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, 0.95, 1.05, 1.25,
+ hip_thickness, foot_thickness);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -5 staff_space_rounded));
+fet_endchar;
+
+
+fet_beginchar ("8th (down)", "d3");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ flag_count = 1;
+ flare = staff_space;
+ flagspace# = .9 staff_space#;
+ hip_depth_ratio = .72;
+ hip_width# = downflag_width# - hip_thickness# / 2;
+ total_depth# = 2.85 staff_space#;
+ foot_width_ratio = .8;
+
+ (flag_count - 1) * flagspace# + foot_depth# = total_depth#;
+
+ define_pixels (hip_width, flagspace, foot_depth);
+
+ set_char_box (0, hip_width# + right_downflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2)
+
+ draw_flag ((0, -(flag_count - 1) * flagspace), flare,
+ (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 0);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -staff_space_rounded));
+
+ y_mirror_char;
+fet_endchar;
+
+
+%%%%%%%%
+%
+% Single Stroke for Short Appogiatura
+%
+
+fet_beginchar ("grace dash (up)", "ugrace");
+ save flare, hip_depth_ratio, hip_width, foot_depth;
+
+ hip_depth_ratio = .72;
+ flare# = staff_space#;
+ hip_width# = upflag_width# - hip_thickness# / 2;
+ foot_depth# = 3 staff_space#;
+
+ define_pixels (hip_width, foot_depth);
+
+ set_char_box (hip_width# * hip_depth_ratio,
+ hip_width# + right_upflag_space#,
+ foot_depth# * hip_depth_ratio, -flare#)
+
+ pickup pencircle scaled 1.5 stemthickness;
+
+ z1 = (-b, -d);
+ z2 = (w, h);
+
+ penpos1 (1.5 stemthickness, angle (z2 - z1) - 90);
+ penpos2 (1.5 stemthickness, angle (z2 - z1) - 90);
+
+ fill z1l
+ -- z2l
+ .. top z2
+ .. rt z2
+ .. z2r
+ -- z1r
+ .. bot z1
+ .. lft z1
+ .. cycle;
+
+ penlabels (1, 2);
+fet_endchar;
+
+
+fet_beginchar ("grace dash (down)", "dgrace");
+ save flare, hip_depth_ratio, hip_width, foot_depth;
+ save total_depth;
+
+ hip_depth_ratio = .72 ;
+ flare# = .99 staff_space#;
+ hip_width# = downflag_width# - hip_thickness# / 2;
+ total_depth# = 2.85 staff_space#;
+ foot_depth# = total_depth#;
+ foot_width_ratio = .8;
+
+ define_pixels (hip_width, foot_depth);
+
+ set_char_box (hip_width# * hip_depth_ratio,
+ hip_width# + right_downflag_space#,
+ foot_depth# * hip_depth_ratio, -flare#)
+
+ pickup pencircle scaled 1.5 stemthickness;
+
+ z1 = (-b, -d);
+ z2 = (w, h);
+
+ penpos1 (1.5 stemthickness, angle (z2 - z1) - 90);
+ penpos2 (1.5 stemthickness, angle (z2 - z1) - 90);
+
+ fill z1l
+ -- z2l
+ .. top z2
+ .. rt z2
+ .. z2r
+ -- z1r
+ .. bot z1
+ .. lft z1
+ .. cycle;
+
+ y_mirror_char;
+fet_endchar;
+
+
+fet_beginchar ("16th (down)", "d4");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ flag_count = 2;
+ flare = .8 staff_space;
+ flagspace# = .9 staff_space#;
+ hip_depth_ratio = .85;
+ hip_width# = downflag_width# - hip_thickness# / 2;
+ total_depth# = 3.0 staff_space# - blot_diameter# / 2;
+ foot_width_ratio = .95;
+
+ (flag_count - 1) * flagspace# + foot_depth# = total_depth#;
+
+ set_char_box (0, hip_width# + right_downflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ define_pixels (hip_width, foot_depth);
+ define_whole_vertical_pixels (flagspace);
+
+ draw_flag ((0, -(flag_count - 1) * flagspace), flare,
+ (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 0);
+
+ add_flag (flagspace, flare, .95, 1.00, 1.25,
+ hip_thickness, foot_thickness);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -2 staff_space_rounded));
+
+ y_mirror_char;
+fet_endchar;
+
+
+fet_beginchar ("32nd (down)", "d5");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ flag_count = 3;
+ flare = .84 staff_space;
+ flagspace# = .9 staff_space#;
+ hip_depth_ratio = .85;
+ hip_width# = downflag_width# - hip_thickness# / 2;
+ total_depth# = 3.85 staff_space#;
+ foot_width_ratio = .95;
+
+ (flag_count - 1) * flagspace# + foot_depth# = total_depth#;
+
+ define_pixels (hip_width, foot_depth);
+ define_whole_vertical_pixels (flagspace);
+
+ set_char_box (0, hip_width# + right_downflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ draw_flag ((0, -(flag_count - 1) * flagspace), flare,
+ (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 0);
+
+ add_flag (flagspace, flare, .97, 1.00, 1.25,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, .95, 1.05, 1.25,
+ hip_thickness, foot_thickness);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -3 staff_space_rounded));
+
+ y_mirror_char;
+fet_endchar;
+
+
+fet_beginchar ("64th (down)", "d6");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ flag_count = 4;
+ flare = .8 staff_space;
+ flagspace# = .9 staff_space#;
+ hip_depth_ratio = .85;
+ hip_width# = downflag_width# - hip_thickness# / 2;
+ total_depth# = 4.35 staff_space#;
+ foot_width_ratio = .98;
+
+ (flag_count - 1) * flagspace# + foot_depth# = total_depth#;
+
+ define_pixels (hip_width, foot_depth);
+ define_whole_vertical_pixels (flagspace);
+
+ set_char_box (0, hip_width# + right_downflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ draw_flag ((0, -(flag_count - 1) * flagspace), flare,
+ (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 0);
+
+ add_flag (flagspace, flare, .97, 1.20, 1.175,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, .97, 1.10, 1.175,
+ hip_thickness, foot_thickness);
+ add_flag (.98 flagspace, flare, .91, 1.05, 1.2,
+ hip_thickness, foot_thickness);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -4 staff_space_rounded));
+
+ y_mirror_char;
+fet_endchar;
+
+
+fet_beginchar ("128th (down)", "d7");
+ save flare, hip_depth_ratio, hip_width, foot_depth, foot_width_ratio;
+ save flagspace, total_depth, flag_count;
+
+ flag_count = 5;
+ flare = .8 staff_space;
+ flagspace# = .9 staff_space#;
+ hip_depth_ratio = .85;
+ hip_width# = downflag_width# - hip_thickness# / 2;
+ total_depth# = 5.25 staff_space#;
+ foot_width_ratio = .98;
+
+ (flag_count - 1) * flagspace# + foot_depth# = total_depth#;
+ define_pixels (hip_width, foot_depth);
+ define_whole_vertical_pixels (flagspace);
+
+ set_char_box (0, hip_width# + right_downflag_space#,
+ total_depth# + foot_thickness# / 2, stemthickness# / 2);
+
+ draw_flag ((0, -(flag_count - 1) * flagspace), flare,
+ (hip_width, foot_depth),
+ hip_depth_ratio, foot_width_ratio,
+ hip_thickness, foot_thickness, 0);
+
+ add_flag (flagspace, flare, .97, 1.20, 1.175,
+ hip_thickness, foot_thickness);
+ add_flag (flagspace, flare, .97, 1.10, 1.175,
+ hip_thickness, foot_thickness);
+ add_flag (.98 flagspace, flare, .91, 1.05, 1.2,
+ hip_thickness, foot_thickness);
+ add_flag (.98 flagspace, flare, .91, 1.05, 1.2,
+ hip_thickness, foot_thickness);
+
+ draw_square_block ((-0.5 stemthickness_rounded, 0),
+ (0, -5 staff_space_rounded));
+
+ y_mirror_char;
+fet_endchar;
+
+fet_endgroup ("flags");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-beugel.mf b/muse2/share/scoreglyphs/feta-original/feta-beugel.mf
new file mode 100644
index 00000000..c61f756d
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-beugel.mf
@@ -0,0 +1,147 @@
+%
+% feta-beugel.mf -- Staff braces
+%
+% source file of the Feta (not an acronym for Font-En-Tja)
+% pretty-but-neat music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+% Jan Nieuwenhuizen <janneke@gnu.org>
+
+
+% We have to reduce the pixel-per-point value to
+% support large brace glyphs in case we are using MetaPost
+% (which by default sets `hppp' to 49.80244, regardless of
+% the used `mag' value)
+
+if known miterlimit:
+ bpppix_ := 0.2; % ten times larger than original
+
+ numeric mm, pt, dd, bp, cm, pc, cc, in;
+
+ mm * bpppix_ = 2.83464;
+ pt * bpppix_ = 0.99626;
+ dd * bpppix_ = 1.06601;
+ bp * bpppix_ = 1;
+ cm * bpppix_ = 28.34645;
+ pc * bpppix_ = 11.95517;
+ cc * bpppix_ = 12.79213;
+ in * bpppix_ = 72;
+
+ hppp := pt;
+ vppp := pt;
+fi;
+
+
+input feta-autometric;
+input feta-macros;
+
+staffsize# := 20 pt#; %% arbitrary
+
+input feta-params;
+
+%
+% We must let the design increase for each font to make sure that mftrace
+% doesn't jack up the resolution too highly for the longer braces.
+%
+
+fet_beginfont ("feta-braces-" & char (97 + font_count),
+ (font_count + 1) * 20, "fetaBraces");
+
+mode_setup;
+
+
+save code, braces_per_font;
+code := 64;
+braces_per_font := 64;
+
+def draw_brace (expr height_sharp, width_sharp, slt_sharp, brace_number) =
+ save pendir, height, width, thin, thick, slt, pat;
+ save penangle;
+ pair pendir;
+ path pat;
+
+ height# := height_sharp;
+ width# := width_sharp;
+ slt# := slt_sharp;
+
+ fet_beginchar ("brace number " & decimal (brace_number),
+ "brace" & decimal (brace_number))
+ set_char_box (width#, 0, height# / 2, height# / 2);
+
+ define_pixels (height, width, slt);
+ thin = 2 slt;
+ thick = .5 width;
+
+ z2 = .5 [z1, z3];
+ y3l = y1 + height / 2;
+ x3 = x1 + width;
+ y1 = 0;
+ x1 = -b;
+ y0 = y1;
+ x0 = x1 - 2/6 thin;
+
+ pendir = unitvector (x3 - x1, y3l / 6 - y1);
+ penangle = angle pendir - 90;
+ penpos3 (thin, penangle);
+ penpos2 (thick, angle (z3 - z1) - 90);
+ penpos1 (2/3 thin, penangle);
+
+ penlabels (1, 2, 3);
+ labels (0);
+
+ pat := z2r
+ .. simple_serif (z3r, z3l, 90)
+ .. z2l
+ .. z1l{dir (angle (z1r - z1l) - 90)}
+ .. z0{down}
+ .. z1r{-dir (angle (z1l - z1r) + 90)}
+ .. cycle;
+ pat := subpath (0, 5) of pat
+ -- subpath (6, 7) of pat
+ .. cycle;
+
+ fill pat;
+ fill pat yscaled -1;
+ fet_endchar;
+enddef;
+
+
+save stafflinethickness;
+save increment;
+
+linethickness := 0.5 pt#;
+increment := 0.5 pt#;
+y := 10 pt#;
+
+for i := 0 step 1 until font_count:
+ save number;
+
+ number := braces_per_font * i;
+
+ for j := 0 step 1 until (braces_per_font - 1):
+ % message "l: "&decimal l;
+ % note: define_pixels (x) multiplies x by hppp,
+ % must never get bigger than infinity
+ y := y + increment;
+ if y > infinity / hppp:
+ message "Resolution and/or magnification is too high";
+ message "HPPP: "& decimal hppp &" Y: " & decimal y;
+ errmessage "please report to <bug-lilypond@gnu.org>";
+ fi;
+
+ % x should be about one staff space, taking brace to have
+ % default height of 3 staffs, this yields height / 3 / 4 = 12
+ % but 15 looks better
+ x := y / 15;
+
+ increment := x / 10;
+ linethickness := min (0.5 pt#, y / 150);
+ if i = font_count:
+ draw_brace (y, x, linethickness, number);
+ fi;
+
+ number := number + 1;
+ endfor;
+endfor;
+
+fet_endfont ("feta-braces");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-bolletjes.mf b/muse2/share/scoreglyphs/feta-original/feta-bolletjes.mf
new file mode 100644
index 00000000..fcda6009
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-bolletjes.mf
@@ -0,0 +1,1497 @@
+% -*-Fundamental-*-
+% feta-bolletjes.mf -- implement noteheads
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 1997--2009 Jan Nieuwenhuizen <janneke@gnu.org>
+% & Han-Wen Nienhuys <hanwen@xs4all.nl>
+% & Juergen Reuter <reuter@ipd.uka.de>
+%
+
+test_outlines := 0;
+
+
+save remember_pic;
+picture remember_pic;
+
+
+% Most beautiful noteheads are pronounced, not circular,
+% and not even symmetric.
+% These examples are inspired by [Wanske]; see literature list.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% NOTE HEAD VARIABLES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+save black_notehead_width, noteheight;
+save half_notehead_width, whole_notehead_width, slash_thick;
+save slash_slope, overdone_heads, solfa_noteheight;
+
+numeric noteheight;
+numeric slash_thick;
+numeric black_notehead_width;
+numeric whole_notehead_width;
+numeric half_notehead_width;
+
+
+fet_begingroup ("noteheads");
+
+
+% Slope of slash. From scm/grob-description.scm. How to auto-copy?
+slash_slope := 1.7;
+
+% Thickness of slash lines. Quarter notes get 1.5slt width.
+slash_thick# := 2/3 * 0.48 staff_space#;
+
+
+%
+% Hand-engraved music often has balls extending above and below
+% the lines. If you like that, modify overdone heads (unit:
+% stafflinethickness).
+%
+overdone_heads = 0.0;
+noteheight# := staff_space# + (1 + overdone_heads) * stafflinethickness#;
+
+
+%
+% solfa heads should not overlap on chords.
+%
+solfa_noteheight# := staff_space# - stafflinethickness#;
+
+define_pixels (slash_thick);
+define_whole_vertical_pixels (noteheight);
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% SLANT moves both extrema on the long axis (by SLANT * ELLIPTICITY,
+% so SLANT = -1, puts the extreme on the long axis next to the short
+% axis one).
+%
+
+def draw_outside_ellipse (expr ellipticity, tilt, superness, slant) =
+ save attachment_y;
+ save pat;
+ path pat;
+
+ pat := superellipse ((ellipticity, 0), (-slant * ellipticity, 1.0),
+ (-ellipticity, 0), (slant * ellipticity, -1.0),
+ superness);
+ pat := pat rotated tilt;
+
+ save top_point, right_point;
+ pair top_point, right_point;
+
+ top_point := directionpoint left of pat;
+ right_point := directionpoint up of pat;
+
+ save scaling, width;
+
+ scaling# = noteheight# / (2 ypart (top_point));
+ width# := 2 xpart (right_point) * scaling#;
+ define_pixels (scaling, width);
+
+ set_char_box (0, width#, noteheight# / 2, noteheight# / 2);
+
+ d := d - feta_space_shift;
+
+ % attachment Y
+ charwy := ypart (right_point) * scaling#;
+ charwx := width#;
+
+ pat := pat scaled scaling shifted (w / 2, .5 (h - d));
+
+ width := hround width;
+
+ if test_outlines = 1:
+ draw pat;
+ else:
+ fill pat;
+ fi;
+enddef;
+
+
+def undraw_inside_ellipse (expr ellipticity, tilt, superness, clearance) =
+begingroup
+ save pat;
+ path pat;
+
+ pat := superellipse ((ellipticity, 0), (0, 1.0),
+ (-ellipticity, 0), (0, -1.0),
+ superness);
+ pat := pat rotated tilt;
+
+ save top_point, right_point;
+ pair top_point, right_point;
+
+ top_point := directionpoint left of pat;
+ right_point := directionpoint up of pat;
+
+ save height, scaling;
+
+ height# = staff_space# + stafflinethickness# - clearance;
+ scaling# = height# / (2 ypart (top_point));
+ define_pixels (scaling);
+ pat := pat scaled scaling shifted (w / 2, .5 (h - d));
+
+ if test_outlines = 1:
+ draw pat;
+ else:
+ unfill pat;
+ fi
+endgroup;
+enddef;
+
+
+%
+% dimensions aren't entirely right.
+%
+def draw_longa (expr up) =
+ save stemthick, fudge;
+
+ stemthick# = 2 stafflinethickness#;
+ define_whole_blacker_pixels (stemthick);
+
+ fudge = hround (blot_diameter / 2);
+
+ draw_outside_ellipse (1.80, 0, 0.707, 0);
+ undraw_inside_ellipse (1.30, 125, 0.68, 2 stafflinethickness#);
+
+ pickup pencircle scaled stemthick;
+
+ if up:
+ bot y1 = -d;
+ top y2 = h;
+ rt x1 - fudge = 0;
+ x1 = x2;
+
+ fudge + lft x3 = w;
+ x4 = x3;
+ top y4 = h + 3.0 staff_space;
+ y3 = y1;
+ else:
+ bot y1 = -d - 3.0 staff_space;
+ top y2 = h;
+ rt x1 - fudge = 0;
+ x1 = x2;
+
+ fudge + lft x3 = w;
+ x4 = x3;
+ y4 = y2;
+ bot y3 = -d;
+ fi;
+
+ draw_gridline (z1, z2, stemthick);
+ draw_gridline (z3, z4, stemthick);
+
+ labels (1, 2, 3, 4);
+enddef;
+
+
+fet_beginchar ("Longa notehead", "uM2");
+ draw_longa (true);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+fet_beginchar ("Longa notehead", "dM2");
+ draw_longa (false);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Longa notehead", "uM2");
+ draw_longa (true);
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+
+ fet_beginchar ("Longa notehead", "dM2");
+ draw_longa (false);
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+%
+% dimensions aren't entirely right.
+%
+def draw_brevis =
+ save stemthick, fudge;
+
+ stemthick# = 2 stafflinethickness#;
+ define_whole_blacker_pixels (stemthick);
+
+ fudge = hround (blot_diameter / 2);
+
+ draw_outside_ellipse (1.80, 0, 0.707, 0);
+ undraw_inside_ellipse (1.30, 125, 0.68, 2 stafflinethickness#);
+
+ pickup pencircle scaled stemthick;
+
+ bot y1 = -d;
+ top y2 = h;
+ rt x1 - fudge = 0;
+ x1 = x2;
+
+ fudge + lft x3 = w;
+ x4 = x3;
+ y4 = y2;
+ y3 = y1;
+
+ draw_gridline (z1, z2, stemthick);
+ draw_gridline (z3, z4, stemthick);
+enddef;
+
+
+fet_beginchar ("Brevis notehead", "sM1");
+ draw_brevis;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Brevis notehead", "sM1");
+ draw_brevis;
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+fet_beginchar ("Whole notehead", "s0");
+ draw_outside_ellipse (1.80 - puff_up_factor / 3.0, 0, 0.707, 0);
+ undraw_inside_ellipse (1.30, 125 - puff_up_factor * 10,
+ 0.68, 2 stafflinethickness#);
+
+ whole_notehead_width# := charwd;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Whole notehead", "s0");
+ draw_outside_ellipse (1.80 - puff_up_factor / 3.0, 0,
+ 0.707, 0);
+ undraw_inside_ellipse (1.30, 125 - puff_up_factor * 10,
+ 0.68, 2 stafflinethickness#);
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+fet_beginchar ("Half notehead", "s1");
+ draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34, 0.66, 0.17);
+ undraw_inside_ellipse (3.25, 33, 0.81, 2.5 stafflinethickness#);
+
+ half_notehead_width# := charwd;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Half notehead", "s1");
+ draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34,
+ 0.66, 0.17);
+ undraw_inside_ellipse (3.25, 33, 0.81,
+ 2.5 stafflinethickness#);
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+fet_beginchar ("Quart notehead", "s2");
+ % used to have 32. With 31, they are slightly bolder.
+ draw_outside_ellipse (1.49 - puff_up_factor / 3.0, 31, 0.707, 0);
+ black_notehead_width# := charwd;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Quart notehead", "s2");
+ draw_outside_ellipse (1.49 - puff_up_factor / 3.0, 31,
+ 0.707, 0);
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+fet_beginchar ("Whole diamondhead", "s0diamond");
+ draw_outside_ellipse (1.80, 0, 0.495, 0);
+ undraw_inside_ellipse (1.30, 125, 0.6,
+ .4 staff_space# + stafflinethickness#);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Whole diamondhead", "s0diamond");
+ draw_outside_ellipse (1.80, 0, 0.495, 0);
+ undraw_inside_ellipse (1.30, 125, 0.6,
+ .4 staff_space# + stafflinethickness#);
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+fet_beginchar ("Half diamondhead", "s1diamond");
+ draw_outside_ellipse (1.50, 34, 0.49, 0.17);
+ undraw_inside_ellipse (3.5, 33, 0.80,
+ .3 staff_space# + 1.5 stafflinethickness#);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Half diamondhead", "s1diamond");
+ draw_outside_ellipse (1.50, 34, 0.49, 0.17);
+ undraw_inside_ellipse (3.5, 33, 0.80,
+ .3 staff_space#
+ + 1.5 stafflinethickness#);
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+fet_beginchar ("Quart diamondhead", "s2diamond");
+ draw_outside_ellipse (1.80, 35, 0.495, -0.25);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Quart diamondhead", "s2diamond");
+ draw_outside_ellipse (1.80, 35, 0.495, -0.25);
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+vardef penposx@# (expr d) =
+begingroup;
+ save pat;
+ path pat;
+
+ pat = top z@#
+ .. lft z@#
+ .. bot z@#
+ .. rt z@#
+ .. cycle;
+ z@#l = pat intersectionpoint (z@# -- infinity * dir (d + 180));
+ z@#r = pat intersectionpoint (z@# -- infinity * dir (d));
+endgroup
+enddef;
+
+
+%
+% UGH: xs not declared as argument.
+%
+def define_triangle_shape (expr stemdir) =
+ save triangle_a, triangle_b, triangle_c;
+ save triangle_out_a, triangle_out_b, triangle_out_c;
+ save triangle_in, triangle_out;
+ save width, depth, height;
+ save origin, left_up_dir;
+ save exact_left_point, exact_right_point, exact_down_point;
+
+ path triangle_a, triangle_b, triangle_c;
+ path triangle_out_a, triangle_out_b, triangle_out_c;
+ path triangle_in, triangle_out;
+ pair origin, left_up_dir;
+ pair exact_down_point, exact_left_point, exact_right_point;
+
+ save pen_thick;
+ pen_thick# = stafflinethickness# + .1 staff_space#;
+ define_pixels (llap);
+ define_blacker_pixels (pen_thick);
+
+ left_up_dir = llap# * dir (90 + tilt);
+
+ xpart (left_up_dir) * xs - (pen_thick# * xs) / 2 + xpart origin = 0;
+ ypart origin = 0;
+
+ exact_left_point := origin + (left_up_dir xscaled xs);
+ exact_down_point := origin + (left_up_dir rotated 120 xscaled xs);
+ exact_right_point := origin + (left_up_dir rotated 240 xscaled xs);
+
+ height# = ypart (exact_left_point + origin) + pen_thick# / 2;
+ depth# = -ypart (exact_down_point + origin) + pen_thick# / 2;
+ width# = xpart (exact_right_point - exact_left_point)
+ + pen_thick# * xs;
+
+ set_char_box (0, width#, depth#, height#);
+
+ % Formerly, the shape has simply been drawn with an elliptical pen
+ % (`scaled pen_thick xscaled xs'), but the envelope of such a curve
+ % is of 6th degree. For the sake of mf2pt1, we approximate it.
+
+ pickup pencircle scaled pen_thick xscaled xs;
+
+ z0 = (hround_pixels (xpart origin), 0);
+
+ z1 = z1' = z0 + llap * dir (90 + tilt) xscaled xs;
+ z2 = z2' = z0 + llap * dir (90 + tilt + 120) xscaled xs;
+ z3 = z3' = z0 + llap * dir (90 + tilt + 240) xscaled xs;
+
+ z12 = caveness [.5[z1, z2], z3];
+ z23 = caveness [.5[z2, z3], z1];
+ z31 = caveness [.5[z3, z1], z2];
+
+ triangle_a = z1 .. z12 .. z2;
+ triangle_b = z2 .. z23 .. z3;
+ triangle_c = z3 .. z31 .. z1;
+
+ penposx1 (angle (direction 0 of triangle_a) - 90);
+ penposx2 (angle (direction 0 of triangle_b) - 90);
+ penposx3 (angle (direction 0 of triangle_c) - 90);
+
+ penposx1' (angle (direction infinity of triangle_c) + 90);
+ penposx2' (angle (direction infinity of triangle_a) + 90);
+ penposx3' (angle (direction infinity of triangle_b) + 90);
+
+ penposx12 (angle (z12 - z0));
+ penposx23 (angle (z23 - z0));
+ penposx31 (angle (z31 - z0));
+
+ z10 = (z0 -- z1) intersectionpoint (z1l .. z12l .. z2'r);
+ z20 = (z0 -- z2) intersectionpoint (z2l .. z23l .. z3'r);
+ z30 = (z0 -- z3) intersectionpoint (z3l .. z31l .. z1'r);
+
+ triangle_in = z10
+ .. z12l
+ .. z20
+ & z20
+ .. z23l
+ .. z30
+ & z30
+ .. z31l
+ .. z10
+ & cycle;
+
+ triangle_out_a = z1r .. z12r .. z2'l;
+ triangle_out_b = z2r .. z23r .. z3'l;
+ triangle_out_c = z3r .. z31r .. z1'l;
+
+ triangle_out = top z1
+ .. lft z1
+ .. z1r{direction 0 of triangle_out_a}
+ & triangle_out_a
+ & {direction infinity of triangle_out_a}z2'l
+ .. lft z2
+ .. bot z2
+ .. z2r{direction 0 of triangle_out_b}
+ & triangle_out_b
+ & {direction infinity of triangle_out_b}z3'l
+ .. rt z3
+ .. top z3
+ .. z3r{direction 0 of triangle_out_c}
+ & triangle_out_c
+ & {direction infinity of triangle_out_c}z1'l
+ .. cycle;
+
+ labels (0, 10, 20, 30);
+ penlabels (1, 1', 2, 2', 3, 3', 12, 23, 31);
+
+ % attachment Y
+ if stemdir = 1:
+ charwy := ypart exact_right_point;
+ charwx := xpart exact_right_point + .5 pen_thick# * xs;
+ else:
+ charwy := -ypart exact_down_point;
+ charwx := width# - (xpart exact_down_point - .5 pen_thick# * xs);
+ fi
+enddef;
+
+
+def draw_whole_triangle_head =
+ save hei, xs;
+ save llap;
+ save tilt;
+
+ tilt = 40;
+ llap# = 3/4 noteheight#;
+
+ xs = 1.5;
+ caveness := 0.1;
+ define_triangle_shape (1);
+ fill triangle_out;
+ unfill triangle_in;
+enddef;
+
+
+fet_beginchar ("Whole trianglehead", "s0triangle");
+ draw_whole_triangle_head;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Whole trianglehead", "s0triangle");
+ draw_whole_triangle_head;
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+def draw_small_triangle_head (expr dir) =
+ save hei, xs;
+ save llap;
+ save tilt;
+
+ tilt = 40;
+ llap# = 2/3 noteheight#;
+ xs = 1.2;
+ caveness := 0.1;
+ define_triangle_shape (dir);
+
+ pickup feta_fillpen;
+
+ filldraw triangle_out;
+ unfilldraw triangle_in;
+enddef;
+
+
+fet_beginchar ("Half trianglehead (downstem)", "d1triangle");
+ draw_small_triangle_head (-1);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("Half trianglehead (upstem)", "u1triangle");
+ draw_small_triangle_head (1);
+
+ draw_staff (-2, 2, 0.5);
+fet_endchar;
+
+
+def draw_closed_triangle_head (expr dir) =
+ save hei, xs;
+ save llap;
+ save tilt;
+
+ tilt = 40;
+ llap# = 2/3 noteheight#;
+ xs = 1.0;
+ caveness := 0.1;
+ define_triangle_shape (dir);
+ fill triangle_out;
+enddef;
+
+
+fet_beginchar ("Quart trianglehead (upstem)", "u2triangle");
+ draw_closed_triangle_head (1);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("Quart trianglehead (downstem)", "d2triangle");
+ draw_closed_triangle_head (-1);
+
+ draw_staff (-2, 2, 0.5);
+fet_endchar;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Slash heads are for indicating improvisation. They are
+% twice as high as normal heads.
+%
+def draw_slash (expr hwid_hash) =
+ save exact_height;
+ save ne, nw_dist;
+ pair ne, nw_dist;
+ exact_height = staff_space# + stafflinethickness# / 2;
+
+ set_char_box (0, 2 exact_height / slash_slope + hwid_hash,
+ exact_height, exact_height);
+
+ charwx := charwd;
+ charwy := charht;
+
+ clearxy;
+
+ d := d - feta_shift;
+
+ pickup pencircle scaled blot_diameter;
+
+ bot y1 = -d;
+ top y2 = h;
+ lft x1 = 0;
+ lft x2 = 2 h / slash_slope;
+
+ rt x3 = w;
+ y3 = y2;
+ y4 = y1;
+ x3 - x2 = x4 - x1;
+
+ ne = unitvector (z3 - z4);
+ nw_dist = (ne rotated 90) * 0.5 blot_diameter;
+
+ fill bot z1{left}
+ .. (z1 + nw_dist){ne}
+ -- (z2 + nw_dist){ne}
+ .. top z2{right}
+ -- top z3{right}
+ .. (z3 - nw_dist){-ne}
+ -- (z4 - nw_dist){-ne}
+ .. bot z4{left}
+ -- cycle;
+
+ if hwid_hash > 2 slash_thick#:
+ save th;
+
+ th = slash_thick - blot_diameter;
+ y6 = y7;
+ y5 = y8;
+ y3 - y7 = th;
+ y5 - y1 = th;
+ z6 - z5 = whatever * ne;
+ z8 - z7 = whatever * ne;
+
+ z5 = z1 + whatever * ne + th * (ne rotated -90);
+ z8 = z4 + whatever * ne + th * (ne rotated 90);
+
+ unfill z5
+ -- z6
+ -- z7
+ -- z8
+ -- cycle;
+ fi
+ labels (range 1 thru 10);
+enddef;
+
+
+fet_beginchar ("Whole slashhead", "s0slash");
+ draw_slash (4 slash_thick# + 0.5 staff_space#);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("Half slashhead", "s1slash");
+ draw_slash (3.0 slash_thick# + 0.15 staff_space#);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("Quart slashhead", "s2slash");
+ draw_slash (1.5 slash_thick#);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% `thick' is the distance between the NE/SW parallel lines in the cross
+% (distance between centres of lines) in multiples of stafflinethickness
+%
+def draw_cross (expr thick) =
+ save ne, nw;
+ save ne_dist, nw_dist, rt_dist, up_dist;
+ save crz_in, crz_out;
+ save thickness;
+ pair ne, nw;
+ pair ne_dist, nw_dist, rt_dist, up_dist;
+ path crz_in, crz_out;
+
+ pen_thick# := 1.2 stafflinethickness#;
+ thickness# := thick * stafflinethickness#;
+ define_pixels (thickness);
+ define_blacker_pixels (pen_thick);
+
+ pickup pencircle scaled pen_thick;
+
+ h := h - feta_shift;
+
+ top y3 = h;
+ ne = unitvector ((1, (2 h - pen_thick) / (w - pen_thick)));
+ rt x4 = w / 2;
+ y5 = 0;
+ z4 - z5 = whatever * ne;
+ x6 = 0;
+ z6 - z3 = whatever * ne;
+ z3 - z4 = whatever * (ne yscaled -1);
+
+ z4 - z3 = whatever * (ne) + (ne rotated -90) * thickness;
+
+
+ x1 = charwd / 2 - .5 pen_thick#;
+ z1 = whatever * ne
+ + thick / 2 * stafflinethickness# * (ne rotated -90);
+
+ % labels (1, 2, 3, 4, 5, 6);
+
+ nw = unitvector (z3 - z4);
+
+ up_dist = up * 0.5 pen_thick / cosd (angle (ne));
+ rt_dist = right * 0.5 pen_thick / sind (angle (ne));
+ nw_dist = (ne rotated 90) * 0.5 pen_thick;
+ ne_dist = (nw rotated -90) * 0.5 pen_thick;
+
+ x4' := x4;
+ x5' := x5;
+ y6' := y6;
+
+ x4 := hround (x4' + .5 pen_thick) - .5 pen_thick;
+ x5 := hfloor (x5' + xpart rt_dist) - xpart rt_dist;
+ y6 := vfloor (y6' + ypart up_dist) - ypart up_dist;
+
+ crz_out = (z6 + up_dist)
+ -- (z3 + nw_dist){ne}
+ .. (top z3)
+ .. (z3 + ne_dist){-nw}
+ -- (z4 + ne_dist){-nw}
+ .. (rt z4)
+ .. (z4 - nw_dist){-ne}
+ -- (z5 + rt_dist);
+ crz_out := crz_out shifted (0, feta_shift)
+ -- reverse crz_out yscaled -1 shifted (0, -feta_eps);
+ fill crz_out
+ -- reverse crz_out xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+
+ if (thick > 1):
+ x4 := hround (x4' - xpart rt_dist) + xpart rt_dist;
+ x5 := hceiling (x5' - .5 pen_thick) + .5 pen_thick;
+ y6 := vfloor (y6' - .5 pen_thick) + .5 pen_thick;
+
+ crz_in = (bot z6){right}
+ .. (z6 - nw_dist){ne}
+ -- (z3 - up_dist)
+ -- (z4 - rt_dist)
+ -- (z5 + nw_dist){-ne}
+ .. {down}(lft z5);
+ crz_in := crz_in shifted (0, feta_shift)
+ -- reverse crz_in yscaled -1 shifted (0, -feta_eps);
+ unfill crz_in
+ -- reverse crz_in xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+ fi
+
+ % ugh
+ currentpicture := currentpicture shifted (hround (w / 2), 0);
+
+ charwx := charwd;
+ charwy := y1 + feta_shift;
+
+ z12 = (charwx * hppp, y1 * vppp);
+
+ labels (12);
+enddef;
+
+
+fet_beginchar ("Whole Crossed notehead", "s0cross");
+ save wid, hei;
+
+ wid# := black_notehead_width# + 4 stafflinethickness#;
+ hei# := noteheight# + stafflinethickness#;
+
+ set_char_box (0, wid#, hei# / 2, hei# / 2);
+
+ draw_cross (3.75);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Whole Crossed notehead", "s0cross");
+ save wid, hei;
+
+ wid# := black_notehead_width# + 4 stafflinethickness#;
+ hei# := noteheight# + stafflinethickness#;
+
+ set_char_box (0, wid#, hei# / 2, hei# / 2);
+
+ currentpicture := remember_pic;
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+fet_beginchar ("Half Crossed notehead", "s1cross");
+ save wid, hei;
+
+ wid# := black_notehead_width# + 2 stafflinethickness#;
+ hei# := noteheight# + stafflinethickness# / 2;
+
+ set_char_box (0, wid#, hei# / 2, hei# / 2);
+
+ draw_cross (3.0);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Half Crossed notehead", "s1cross");
+ save wid, hei;
+
+ wid# := black_notehead_width# + 2 stafflinethickness#;
+ hei# := noteheight# + stafflinethickness# / 2;
+
+ set_char_box (0, wid#, hei# / 2, hei# / 2);
+
+ currentpicture := remember_pic;
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+fet_beginchar ("Crossed notehead", "s2cross");
+ wid# := black_notehead_width#;
+ hei# := noteheight#;
+ set_char_box (0, wid#, hei# / 2, hei# / 2);
+
+ draw_cross (1.0);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("Crossed notehead", "s2cross");
+ wid# := black_notehead_width#;
+ hei# := noteheight#;
+ set_char_box (0, wid#, hei# / 2, hei# / 2);
+
+ currentpicture := remember_pic;
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+fet_beginchar ("X-Circled notehead", "s2xcircle");
+ save wid, hei;
+ save cthick, cxd, cyd, dy;
+
+ wid# := black_notehead_width# * sqrt (sqrt2);
+ hei# := noteheight# * sqrt (sqrt2);
+
+ set_char_box (0, wid#, hei# / 2, hei# / 2);
+
+ d := d - feta_space_shift;
+
+ cthick# := (1.2 + 1/4) * stafflinethickness#;
+ define_blacker_pixels (cthick);
+
+ cxd := w - cthick;
+ cyd := h + d - cthick / 2;
+
+ dy = .5 (h - d);
+
+ pickup pencircle scaled cthick;
+
+ fill fullcircle xscaled (cxd + cthick)
+ yscaled (cyd + cthick)
+ shifted (w / 2, dy);
+ unfill fullcircle xscaled (cxd - cthick)
+ yscaled (cyd - cthick)
+ shifted (w / 2, dy);
+
+ xpos := .5 cxd / sqrt2;
+ ypos := .5 cyd / sqrt2;
+
+ pickup penrazor scaled cthick rotated (angle (xpos, ypos) + 90);
+ draw (-xpos + w / 2, -ypos + dy) -- (xpos + w / 2, ypos + dy);
+
+ pickup penrazor scaled cthick rotated (angle (xpos, -ypos) + 90);
+ draw (-xpos + w / 2, ypos + dy) -- (xpos + w / 2, -ypos + dy);
+
+ charwx := charwd;
+ charwy := 0;
+
+ z12 = (charwx * hppp, charwy * vppp);
+ labels (12);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+if test > 0:
+ fet_beginchar ("X-Circled notehead", "s2xcircle");
+ save wid, hei;
+ save cthick, cxr, cyr;
+
+ wid# := black_notehead_width# * sqrt (sqrt2);
+ hei# := noteheight# * sqrt (sqrt2);
+
+ set_char_box (0, wid#, hei# / 2, hei# / 2);
+
+ currentpicture := remember_pic;
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+
+
+%%%%%%%%
+%
+% SOLFA SHAPED NOTES
+%
+
+save solfa_pen_thick;
+solfa_pen_thick# = 1.75 stafflinethickness#;
+define_blacker_pixels (solfa_pen_thick);
+
+
+save solfa_base_notewidth;
+solfa_base_notewidth# := black_notehead_width#;
+
+solfa_whole_width := whole_notehead_width# / black_notehead_width#;
+solfa_half_width := half_notehead_width# / black_notehead_width#;
+solfa_quarter_width := 1.0;
+
+def draw_do_head (expr width_factor, dir) =
+ save p_in, p_out;
+ save left_dist, right_dist;
+ path p_in, p_out;
+ pair left_dist, right_dist;
+
+ set_char_box (0, width_factor * solfa_base_notewidth#,
+ 0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
+
+ pickup pencircle scaled solfa_pen_thick;
+
+ bot y1 = -d;
+ y1 = y2;
+ lft x1 = 0;
+ rt x2 = w;
+ top y3 = h;
+ x3 =.5 [x1, x2];
+
+ left_dist = (unitvector (z3 - z1) rotated 90) * 0.5 solfa_pen_thick;
+ right_dist = (unitvector (z2 - z3) rotated 90) * 0.5 solfa_pen_thick;
+
+ p_in := (((z1 - left_dist) -- (z3 - left_dist)) intersectionpoint
+ (top z1 -- top z2))
+ -- ((top z1 -- top z2) intersectionpoint
+ ((z2 - right_dist) -- (z3 - right_dist)))
+ -- (((z2 - right_dist) -- (z3 - right_dist)) intersectionpoint
+ ((z1 - left_dist) -- (z3 - left_dist)))
+ -- cycle;
+
+ p_out := bot z1
+ -- bot z2{right}
+ .. rt z2{up}
+ .. (z2 + right_dist){z3 - z2}
+ -- (z3 + right_dist){z3 - z2}
+ .. top z3{left}
+ .. (z3 + left_dist){z1 - z3}
+ -- (z1 + left_dist){z1 - z3}
+ .. lft z1{down}
+ .. {right}cycle;
+
+
+ labels (1, 2, 3);
+
+ charwx := charwd;
+ charwy := -chardp + 0.5 stafflinethickness#;
+ if dir = -1:
+ charwy := -charwy;
+ fi;
+enddef;
+
+
+fet_beginchar ("Whole dohead", "s0do");
+ draw_do_head (solfa_whole_width, 1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Half dohead", "d1do");
+ draw_do_head (solfa_half_width, -1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Half dohead", "u1do");
+ draw_do_head (solfa_half_width, 1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Quart dohead", "d2do");
+ draw_do_head (solfa_quarter_width, -1);
+ fill p_out;
+fet_endchar;
+
+
+fet_beginchar ("Quart dohead", "u2do");
+ draw_do_head (solfa_quarter_width, 1);
+ fill p_out;
+fet_endchar;
+
+
+%
+% re - flat top, curved bottom:
+% (0,h/2) {dir -90} .. (w/2,-h/2) .. {dir 90} (w,h/2) -- cycle;
+% (broader along the base and with more vertical sides for half and
+% whole notes)
+% stem attachment: h/2
+%
+
+def draw_re_head (expr width_factor, dir) =
+ save p_in, p_out;
+ path p_in, p_out;
+
+ set_char_box (0, width_factor * solfa_base_notewidth#,
+ 0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
+
+ pickup pencircle scaled solfa_pen_thick;
+
+ save curve_start;
+ curve_start = 0.7;
+ lft x1 = 0;
+ y1 = y5;
+ x1 = x2;
+ y2 = curve_start [y3, y1];
+ bot y3 = -d;
+ x3 = .5 [x2, x4];
+ rt x4 = w;
+ y4 = y2;
+ top y5 = h;
+ x5 = x4;
+
+ labels (range 1 thru 5);
+
+ p_in := (z1 + 0.5 solfa_pen_thick * (1, -1))
+ -- rt z2{down}
+ .. top z3
+ .. lft z4{up}
+ -- (z5 + 0.5 solfa_pen_thick * (-1, -1))
+ -- cycle;
+
+ p_out := lft z1
+ -- lft z2{down}
+ .. bot z3
+ .. rt z4{up}
+ -- rt z5{up}
+ .. top z5{left}
+ -- top z1{left}
+ .. {down}cycle;
+
+ charwx := charwd;
+ charwy := curve_start [-chardp, charht];
+
+ if dir = -1:
+ charwy := -charwy;
+ fi;
+enddef;
+
+
+fet_beginchar ("Whole rehead", "s0re");
+ draw_re_head (solfa_whole_width, 1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Half up rehead", "u1re");
+ draw_re_head (solfa_half_width, 1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Half down rehead", "d1re");
+ draw_re_head (solfa_half_width, -1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Quart rehead", "u2re");
+ draw_re_head (solfa_quarter_width, 1);
+ fill p_out;
+fet_endchar;
+
+
+fet_beginchar ("Quart rehead", "d2re");
+ draw_re_head (solfa_quarter_width, -1);
+ fill p_out;
+fet_endchar;
+
+
+def draw_mi_head (expr width_factor) =
+ save path_out, path_in;
+ save ne_dist, se_dist, ne, se;
+ path path_out, path_in;
+ pair ne_dist, se_dist, ne, se;
+
+ set_char_box (0, width_factor * solfa_base_notewidth#,
+ 0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
+
+ pickup pencircle scaled solfa_pen_thick;
+
+ lft x1 = 0;
+ y1 = 0;
+ bot y2 = -d;
+ x2 = .5 [x1, x3];
+ rt x3 = w;
+ x4 = x2;
+ y3 = y1;
+ top y4 = h;
+
+ z6 - z5 = whatever * (z2 - z1);
+ z8 - z7 = whatever * (z2 - z1);
+ z8 - z5 = whatever * (z4 - z1);
+ z6 - z7 = whatever * (z4 - z1);
+
+ ne = unitvector (z4 - z1);
+ se = unitvector (z1 - z2);
+
+ ne_dist = (ne rotated 90) * 0.5 solfa_pen_thick;
+ se_dist = (se rotated 90) * 0.5 solfa_pen_thick;
+
+ z5 = whatever [z1, z4] - ne_dist;
+ z5 = whatever [z1, z2] - 1.5 se_dist;
+
+ z5 - z1 = -(z7 - z3);
+
+ labels (range 1 thru 8);
+
+ path_in := z5
+ -- z6
+ -- z7
+ -- z8
+ -- cycle;
+
+ path_out := lft z1
+ .. (z1 + se_dist){-se}
+ -- (z2 + se_dist){-se}
+ .. bot z2
+ .. (z2 - ne_dist){ne}
+ -- (z3 - ne_dist){ne}
+ .. rt z3
+ .. (z3 - se_dist){se}
+ -- (z4 - se_dist){se}
+ .. top z4
+ .. (z4 + ne_dist){-ne}
+ -- (z1 + ne_dist){-ne}
+ .. cycle;
+enddef;
+
+
+fet_beginchar ("Whole mihead", "s0mi");
+ draw_mi_head (solfa_whole_width);
+ fill path_out;
+ unfill path_in;
+fet_endchar;
+
+
+fet_beginchar ("Half mihead", "s1mi");
+ draw_mi_head (solfa_quarter_width);
+ fill path_out;
+ unfill path_in;
+fet_endchar;
+
+
+fet_beginchar ("Quart mihead", "s2mi");
+ draw_mi_head (solfa_quarter_width);
+ fill path_out;
+fet_endchar;
+
+
+def draw_fa_head (expr width_factor) =
+ set_char_box (0, width_factor * solfa_base_notewidth#,
+ 0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
+
+ save p_down_in, p_down_out, p_up_in, p_up_out, nw_dist, nw;
+ path p_down_in, p_down_out, p_up_in, p_up_out;
+ pair nw_dist, nw;
+
+ pickup pencircle scaled solfa_pen_thick;
+
+ lft x1 = 0;
+ top y1 = h;
+
+ rt x2 = w;
+ y2 = y1;
+ bot y3 = -d;
+ x3 = x2;
+
+ y4 = y3;
+ x4 = x1;
+
+ labels (1, 2, 3, 4);
+
+ nw = unitvector (z1 - z3);
+ nw_dist = (nw rotated 90) * 0.5 solfa_pen_thick;
+
+ p_up_in := (((z1 - nw_dist) -- (z3 - nw_dist)) intersectionpoint
+ (bot z1 -- bot z2))
+ -- (((z1 - nw_dist) -- (z3 - nw_dist)) intersectionpoint
+ (lft z3 -- lft z2))
+ -- (z2 + 0.5 solfa_pen_thick * (-1, -1))
+ -- cycle;
+
+ p_up_out := lft z1{down}
+ .. (z1 + nw_dist){-nw}
+ -- (z3 + nw_dist){-nw}
+ .. bot z3{right}
+ .. rt z3{up}
+ -- rt z2{up}
+ .. top z2{left}
+ -- top z1{left}
+ .. {down}cycle;
+
+ p_down_in := p_up_in rotated 180 shifted (w, 0);
+ p_down_out := p_up_out rotated 180 shifted (w, 0);
+
+ charwy := 0.0;
+ charwx := charwd;
+enddef;
+
+
+fet_beginchar ("Whole fa up head", "u0fa");
+ draw_fa_head (solfa_whole_width);
+ fill p_up_out;
+ unfill p_up_in;
+fet_endchar;
+
+
+fet_beginchar ("Whole fa down head", "d0fa");
+ draw_fa_head (solfa_whole_width);
+ fill p_down_out;
+ unfill p_down_in;
+fet_endchar;
+
+
+fet_beginchar ("half fa up head", "u1fa");
+ draw_fa_head (solfa_half_width);
+ fill p_up_out;
+ unfill p_up_in;
+fet_endchar;
+
+
+fet_beginchar ("Half fa down head", "d1fa");
+ draw_fa_head (solfa_half_width);
+ fill p_down_out;
+ unfill p_down_in;
+fet_endchar;
+
+
+fet_beginchar ("Quarter fa up head", "u2fa");
+ draw_fa_head (solfa_quarter_width);
+ fill p_up_out;
+fet_endchar;
+
+
+fet_beginchar ("Quarter fa down head", "d2fa");
+ draw_fa_head (solfa_quarter_width);
+ fill p_down_out;
+fet_endchar;
+
+
+def draw_la_head (expr width_factor) =
+ set_char_box (0, width_factor * solfa_base_notewidth#,
+ 0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
+ save p_in, p_out;
+ path p_in, p_out;
+
+ pickup pencircle scaled solfa_pen_thick;
+
+ lft x1 = 0;
+ top y1 = h;
+
+ rt x2 = w;
+ y2 = y1;
+ bot y3 = -d;
+ x3 = x2;
+
+ y4 = y3;
+ x4 = x1;
+
+ labels (range 1 thru 4);
+
+ p_in := (z1 + 0.5 solfa_pen_thick * (1, -1))
+ -- (z2 + 0.5 solfa_pen_thick * (-1, -1))
+ -- (z3 + 0.5 solfa_pen_thick * (-1, 1))
+ -- (z4 + 0.5 solfa_pen_thick * (1, 1))
+ -- cycle;
+
+ p_out := top z1
+ -- top z2{right}
+ .. rt z2{down}
+ -- rt z3{down}
+ .. bot z3{left}
+ -- bot z4{left}
+ .. lft z4{up}
+ -- lft z1{up}
+ .. cycle;
+enddef;
+
+
+fet_beginchar ("Whole lahead", "s0la");
+ draw_la_head (solfa_whole_width);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Half lahead", "s1la");
+ draw_la_head (solfa_half_width);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Quart lahead", "s2la");
+ draw_la_head (solfa_quarter_width);
+ fill p_out;
+fet_endchar;
+
+
+def draw_ti_head (expr width_factor, dir) =
+ set_char_box (0, width_factor * solfa_base_notewidth#,
+ 0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
+ save p_in, p_out, p_top;
+ save nw_dist, sw_dist, nw, sw;
+ path p_in, p_out, p_top;
+ pair nw_dist, sw_dist, nw, sw;
+ save cone_height;
+ cone_height = 0.64;
+
+ pickup pencircle scaled solfa_pen_thick;
+
+ x1 = .5 [x2, x4];
+ bot y1 = -d;
+ lft x2 = 0;
+ y2 = cone_height [y1, y3];
+ rt x4 = w;
+ y4 = y2;
+ x3 = x1;
+ top y3 = h;
+
+ labels (range 1 thru 4);
+
+ nw = unitvector (z2 - z1);
+ sw = unitvector (z1 - z4);
+
+ nw_dist = (nw rotated 90) * 0.5 solfa_pen_thick;
+ sw_dist = (sw rotated 90) * 0.5 solfa_pen_thick;
+
+ p_top := (z2 - sw_dist)
+ .. (top z3){right}
+ .. (z4 - nw_dist);
+
+ p_in := (((z1 - nw_dist) -- (z2 - nw_dist)) intersectionpoint
+ ((z1 - sw_dist) -- (z4 - sw_dist)))
+ -- (((z1 - nw_dist) -- (z2 - nw_dist)) intersectionpoint
+ ((z2 + sw_dist) .. {right}(bot z3)))
+ .. bot z3
+ .. (((bot z3){right} .. (z4 + nw_dist)) intersectionpoint
+ ((z1 - sw_dist) -- (z4 - sw_dist)))
+ -- cycle;
+
+ p_out := bot z1
+ .. (z1 + nw_dist)
+ -- (z2 + nw_dist)
+ .. lft z2
+ .. (z2 - sw_dist){direction 0 of p_top}
+ & p_top
+ & {direction infinity of p_top}(z4 - nw_dist)
+ .. rt z4
+ .. (z4 + sw_dist)
+ -- (z1 + sw_dist)
+ .. cycle;
+
+ charwx := charwd;
+ charwy := cone_height [-chardp, charht];
+ if dir = -1:
+ charwy := -charwy;
+ fi;
+enddef;
+
+
+fet_beginchar ("Whole up tihead", "s0ti");
+ draw_ti_head (solfa_whole_width, 1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Half up tihead", "u1ti");
+ draw_ti_head (solfa_half_width, 1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Half down tihead", "d1ti");
+ draw_ti_head (solfa_half_width, -1);
+ fill p_out;
+ unfill p_in;
+fet_endchar;
+
+
+fet_beginchar ("Quart up tihead", "u2ti");
+ draw_ti_head (solfa_quarter_width, 1);
+ fill p_out;
+fet_endchar;
+
+
+fet_beginchar ("Quart down tihead", "d2ti");
+ draw_ti_head (solfa_quarter_width, -1);
+ fill p_out;
+fet_endchar;
+
+
+fet_endgroup ("noteheads");
+
+
+%
+% we derive black_notehead_width# from the quarter head,
+% so we have to define black_notehead_width (pixel qty)
+% after the black_notehead_width# itself.
+%
+% Let's keep it outside the group as well.
+%
+
+define_pixels (black_notehead_width);
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-a.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-a.mf
new file mode 100644
index 00000000..9d8a9d83
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-a.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-a.mf -- 256 smallest braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 0;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-b.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-b.mf
new file mode 100644
index 00000000..e74606dc
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-b.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-b.mf -- next 256 braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 1;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-c.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-c.mf
new file mode 100644
index 00000000..06a273ed
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-c.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-c.mf -- next 256 braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 2;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-d.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-d.mf
new file mode 100644
index 00000000..d926a595
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-d.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-d.mf -- next 256 braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 3;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-e.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-e.mf
new file mode 100644
index 00000000..ed89fc5a
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-e.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-e.mf -- next 256 braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 4;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-f.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-f.mf
new file mode 100644
index 00000000..4a96744e
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-f.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-f.mf -- next 256 braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 5;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-g.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-g.mf
new file mode 100644
index 00000000..3a12239c
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-g.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-g.mf -- next 256 braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 6;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-h.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-h.mf
new file mode 100644
index 00000000..9d4988e7
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-h.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-h.mf -- next 256 braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 7;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-braces-i.mf b/muse2/share/scoreglyphs/feta-original/feta-braces-i.mf
new file mode 100644
index 00000000..7089e60c
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-braces-i.mf
@@ -0,0 +1,11 @@
+%
+% feta-braces-i.mf -- next 256 braces
+%
+% source file of the Feta (Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+font_count := 8;
+input feta-beugel;
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-din-code.mf b/muse2/share/scoreglyphs/feta-original/feta-din-code.mf
new file mode 100644
index 00000000..809227de
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-din-code.mf
@@ -0,0 +1,791 @@
+% feta-din-code.mf -- implement dynamic signs
+%
+% part of LilyPond's pretty-but-neat music font
+%
+% source file of the Feta (not the Font-En-Tja) music font
+%
+% (c) 1997--2009 Jan Nieuwenhuizen <janneke@gnu.org>
+
+
+ex# := (dynamic_design_size / 2.4) * pt#;
+descender# := 0.5 ex#;
+ascender# := 0.72 ex#;
+staffspace# := 1.75 / 2.0 * ex#;
+horizontal_space# := .66 ex#;
+
+font_x_height ex#;
+font_normal_space horizontal_space#;
+
+define_pixels (staffspace, linethickness, ex, descender, ascender);
+
+
+%
+% TODO: blot diameter should be fixed, not scalable.
+%
+
+save serif_thick, med_thick, bottom_blot;
+
+serif_thick# = 1.1 linethickness#;
+define_blacker_pixels (serif_thick);
+
+med_thick = round (1.5 linethickness);
+bottom_blot = 1.3 serif_thick;
+
+
+code := 32;
+
+fet_beginchar ("Space", "space");
+ set_char_box (0, horizontal_space#, 0, ex#);
+fet_endchar;
+
+
+%
+% Couldn't find many z examples. This one is losely inspired
+% by a sfz from Mueller Etuden fuer Horn (Edition Hofmeister).
+%
+
+code := 121;
+
+fet_beginchar ("dynamic z", "z");
+ save thin_thick, top_narrow, over_shoot;
+ save bot_thick;
+
+ set_char_box (0, .98 ex#, 0, 0.9 ex#);
+
+ thin_thick = serif_thick;
+ top_narrow = thin_thick;
+ top_overshoot = .8 serif_thick;
+ top_thick = .3 h;
+ bot_thick = .2 ex;
+ bot_overshoot = serif_thick;
+
+ x0 = top_narrow;
+ y0 = .9 [y1r, y1l];
+
+ penpos1 (top_thick, 80);
+ y1l = .72 h;
+ x1r = .34 ex;
+
+ x2 = .66 ex;
+ y2 = y1r - top_overshoot;
+
+ y3 = h - .7 thin_thick;
+ x3 = w - .6 top_narrow - .5 thin_thick;
+ y4 = .5 thin_thick;
+ x4 = .5 thin_thick;
+
+ penpos3 (thin_thick, angle (z3 - z4) + 90);
+ penpos4 (thin_thick, angle (z3 - z4) + 90);
+
+ penpos5 (bot_thick, 70);
+ x5l =.25 ex;
+ y5l = .4 bot_overshoot;
+
+ penpos6 (3/2 bot_thick, 70);
+ y6l = -bot_overshoot;
+ x6 = w - 3 top_narrow;
+
+ x7 = w;
+ y7 = .82 [y8r, y6r];
+
+ penpos8 (thin_thick, 20);
+ x8r = w - .35 top_narrow;
+ y8r = .45 h;
+
+ penlabels (range 0 thru 8);
+
+% pickup pencircle scaled 1;
+
+% draw
+ fill z0{down}
+ .. z1l{dir (10)}
+ .. simple_serif (z3l, z3r, 90)
+ .. z2{left}
+ .. z1r{left}
+ ..tension 1.2.. cycle;
+
+% draw
+ fill z3l
+ -- z3r
+ -- z4r
+ -- z4l
+ -- cycle;
+
+% draw
+ fill simple_serif (z4r, z4l, 90)
+ .. z5l{right}
+ .. z6l{right}
+ .. z7{up}
+ .. simple_serif (z8r, z8l, 90)
+ .. z6r{left}
+ .. z5r{left}
+ .. cycle;
+fet_endchar;
+
+
+% forte f, grabbed from Ed Breitkopf Mozart horn concerto 3.
+%
+% NOTES:
+%
+% * the bulbs are open
+%
+% * blotting around the serif
+%
+% TODO: insert blots around the serif
+%
+
+slant_angle = 20;
+code := 101;
+
+fet_beginchar ("dynamic f", "f");
+ save left_angle, right_angle;
+ save serif_length, serif_eccentricity;
+ save f_thick;
+ save bulb_thick, bulb_diam, fill_up;
+ save slant;
+ save p;
+ path p;
+
+ set_char_box (0, 1.1 ex#, descender#, ex# + ascender#);
+
+ bulb_diam = 7.5 / 40 ex;
+ bulb_thick = 8.5 / 40 ex;
+ fill_up = 1.5 serif_thick;
+ left_angle = slant_angle - 6;
+ right_angle = slant_angle - 3;
+ f_thick = 7/16 ex;
+ serif_length = 0.96 ex;
+ serif_eccentricity = 0.01 ex;
+
+ % z1 is the `base point'
+ z1 = (0.2 ex, -serif_thick);
+
+ penpos2 (f_thick, 0);
+ y2 = y1 + ex;
+ z2l = z1 + whatever * dir (90 - left_angle);
+
+ penpos3 (med_thick, -90);
+ y3l = y1 + ex + ascender;
+ x3l = x1 + ex;
+
+ penpos4 (bulb_thick, -20);
+ z3r = whatever [z4r, z4l];
+
+ x4l - x3l = 1/10 ex;
+
+ penpos5 (bulb_thick, -45);
+ x5r = 0.1 [x4l, x4r];
+ y5l = y4l - bulb_diam;
+
+ z6 = z2r + whatever * dir (90 - right_angle);
+ y6 = y1 + 3/8 ex;
+
+ penpos7 (med_thick, -90);
+ x7 = x1 - 1/4 ex;
+ y7r = y1 -descender;
+
+ penpos8 (bulb_thick, 160);
+ x8l = x7l - 1/10 ex;
+
+ z7l = whatever [z8r, z8l];
+
+ penpos9 (bulb_thick, 135);
+ x9r = 0.1 [x8l, x8r];
+ y9l = y8l + bulb_diam;
+
+ labels (1, 6, 9);
+ penlabels (2, 3, 4, 5, 7, 8, 9);
+
+% pickup pencircle scaled 1;
+
+% draw
+ fill z1
+ -- z2l{z2l - z1}
+ ..tension 1.1.. z3l{right}
+ .. z4r{down}
+ .. z5r{left}
+ .. z5l{up}
+ ..tension 0.8.. z4l{up}
+ .. z3r{left}
+ ..tension 1.1.. z2r{z6 - z2r}
+ -- z6{z6 - z2r}
+ ..tension 1.25.. z7r{left}
+ .. z8r{up}
+ .. z9r{right}
+ .. z9l{down}
+ ..tension 0.8.. z8l{down}
+ .. z7l{right}
+ .. {z2l - z1}cycle;
+
+ x13 - x14 = serif_length;
+ y13 = y14;
+ y14 = y2;
+ 0.5 [x13, x14] = x2 + serif_eccentricity;
+
+ draw_rounded_block (z14 - (0, 0.7 serif_thick),
+ z13 + (0, 0.7 serif_thick),
+ 1.4 serif_thick);
+
+ labels (13, 14);
+fet_endchar;
+
+
+%
+% Notes:
+%
+% - The `s' is trapezoidal (i.e., narrower at the top).
+%
+% - The white space is differently shaped at the top (the bulb's inner
+% curve is filled up).
+%
+% - Less heavy than the `f' and `p' signs.
+%
+
+code := 114;
+
+fet_beginchar ("dynamic s", "s");
+ save left_angle, right_angle;
+ save s_thick, s_thin;
+ save bulb_diam, bulb_len;
+ save over_shoot;
+ save base_point;
+ pair base_point;
+
+ set_char_box (0, 17/24 ex#, 0, ex#);
+
+ over_shoot = 0; % .2 serif_thick;
+ bulb_diam = 11/70 ex;
+ bulb_len = 1.0 bulb_diam;
+ left_angle = slant_angle - 2;
+ right_angle = slant_angle - 11;
+ s_thick = 16/70 ex;
+ s_thin = serif_thick;
+
+ base_point = (0, 0);
+
+ penpos1 (bulb_diam, -45);
+ z1 = 0.35 [z2l, z2r] + bulb_len * dir (45);
+
+ penpos2 (bulb_diam, -25);
+ y2l = 0.845 [y7r, y3r];
+ z2l = base_point + whatever * dir (90 - left_angle);
+
+ penpos3 (s_thin, 100);
+ x3l = 1/2 w;
+ y3l = ypart base_point - over_shoot;
+
+ penpos4 (s_thick, 25);
+ y4l = y1r;
+ z4r = base_point + (w, 0) + whatever * dir (90 - right_angle);
+
+ penpos5 (s_thick, 40);
+ z5 = z3l + whatever * dir (90 - right_angle);
+ y5 = 0.48 [y7r, y3r];
+
+ penpos6 (s_thick, 25);
+ z6l = base_point + whatever * dir (90 - left_angle);
+ y6r = y9l;
+
+ penpos7 (.9 s_thin, 110);
+ z7l = 0.45 [z6r, z8l] + whatever * dir (90 - left_angle);
+ y7r = h + over_shoot;
+
+ penpos8 (.9 bulb_diam, -25);
+ z8 = .6 [z4l, z4r] + whatever * dir (90 - right_angle);
+ y8r = 0.23 [y7r, y3r];
+
+ penpos9 (.9 bulb_diam, -45);
+ z9 = .4 [z8r, z8l] + .9 bulb_len * dir (-135);
+
+ penlabels (range 1 thru 9);
+
+% pickup pencircle scaled 1;
+
+% draw
+ fill z2l{down}
+ .. z3l{right}
+ .. z4r{up}
+ .. z5r
+ .. z6r{up}
+ .. z7l{right}
+ % .. z8l{down}
+ .. z9l{dir (-125)}
+ .. z9r{right}
+ .. z7r{left}
+ .. z6l{down}
+ .. z5l
+ .. z4l{down}
+ .. z3r{left}
+ .. z2r{up}
+ .. z1r{up}
+ .. z1l{left}
+ .. cycle;
+fet_endchar;
+
+
+% for `p' and `m'
+
+save slant;
+slant := ypart (dir (slant_angle));
+
+
+%
+% Piano `p', grabbed from Ed Breitkopf Mozart horn concerto 3.
+%
+% Notes:
+%
+% * There is no dishing in the serif (but we do it anyway).
+%
+% * The cheek is a little fatter than the stem.
+%
+% * The slant is extreme: 20 degrees.
+%
+% * The twiddle (what's-it-called) is a slightly darker than the serif.
+%
+% * The hole in the cheek has a straight right side.
+%
+% * Corners are filled up.
+%
+
+code := 111;
+
+fet_beginchar ("dynamic p", "p")
+ % TODO: w really is 13/12 ex
+ % but should do kerning
+
+ save twiddle_thick, stem_thick, cheek_thick, cheek_width;
+ save fill_up, straigh_len;
+ save serif, dishing_angle, p, tmp;
+ save cheek_medium, left_serif_protrude, right_serif_protrude;
+ save lower_overshoot;
+ save blot_t, corner_t;
+ path serif, p;
+ pair tmp, updir;
+
+ set_char_box (0, 15/12 ex#, descender#, 1.0 ex#);
+
+ twiddle_thick = med_thick;
+ cheek_medium = 1/6 ex;
+
+ dishing_angle = 5;
+ fill_up = 1.5 serif_thick;
+ straigh_len = 0.5 ex;
+ lower_overshoot = .3 serif_thick;
+
+ stem_thick = 2/6 ex;
+ cheek_thick = 13/32 ex;
+ cheek_width = 0.72 ex;
+ left_serif_protrude = 18/60 ex;
+ right_serif_protrude = 15/60 ex;
+
+ currenttransform := currenttransform slanted slant;
+
+ penpos1 (twiddle_thick, -slant - 5);
+ penpos2 (cheek_medium, 90 - slant);
+ penpos3 (cheek_medium, 90 - slant);
+
+ x4r - x4l = cheek_thick;
+
+ penpos4 (whatever, 0);
+ penpos5 (whatever, -38);
+ penpos6 (stem_thick, 0);
+ penpos17 (straigh_len, 90 - slant);
+
+ whatever [z17l, z17r] = z4l;
+ y17 = 7/16 ex;
+ x6l = 0;
+ y6l = -descender + serif_thick / 2;
+ z1l = z6l - whatever * dir (110);
+ y1r = 0.5 ex;
+ y2r = ex;
+ z7 = whatever * up + z6l;
+ y7 = 43/60 ex;
+ z2l = whatever * up + 0.3 [z7, z1r];
+ y8 = 0.9 [y7, y2l];
+ z8 = 2/3 [z6l, z6r] + whatever * up;
+ y3r = ex;
+ z3l = 0.58 [(stem_thick, -descender),
+ (stem_thick + cheek_width - cheek_thick, -descender)]
+ + whatever * up;
+ y4r = .38 ex;
+ z4r = whatever * up + (stem_thick + cheek_width, -descender);
+ z5l = whatever * up + z3l;
+ y5r = -lower_overshoot;
+ y5l = y5r + cheek_medium * ypart dir (55);
+ z9 = z6r + whatever * up;
+ y9 = .2 [y5l, y5r];
+
+ p := z2r{right}
+ .. {dir (-60)}z8{dir 60}
+ .. z3r{right}
+ .. z4r{down}
+ ..tension 1.1.. z5r{left}
+ .. {curl 1}z9
+ -- z6r
+ -- z6l
+ -- z7{up}
+ .. z2l{left}
+ ..tension 1.2.. simple_serif (z1r, z1l, -90)
+ .. cycle;
+
+ blot_t := 0.13;
+ corner_t := xpart (p intersectiontimes z9);
+
+% pickup pencircle scaled 1;
+
+% draw
+ fill subpath (0, corner_t - 2 blot_t) of p
+ .. subpath (corner_t + blot_t, length p) of p
+ .. cycle;
+
+ y12 = 0.5 ex;
+ z12 = z6r + whatever * up;
+
+ unfill z17l
+ ..tension 1.5.. z17r
+ .. z3l{left}
+ ..tension 1.05.. z12{down}
+ ..tension 1.05.. z5l{right}
+ .. cycle;
+
+ penlabels (1, 2, 3, 4, 5, 6, 17);
+ labels (7, 8, 9);
+
+ pickup pencircle scaled serif_thick;
+
+ lft x11 = -left_serif_protrude;
+ rt x10 = stem_thick + right_serif_protrude;
+ bot y10 = bot y11 = -descender;
+
+ z15 = z6l + up * fill_up;
+ z16 = z6r + up * 1.2 fill_up;
+
+ % Since pens are not affected by currenttransform we directly
+ % transform the necessary points, then simulating the pen with
+ % an outline while using the identity transformation.
+
+ forsuffixes $ = 7, 10, 11, 15, 16:
+ tmp := z$ transformed currenttransform;
+ x$ := xpart tmp;
+ y$ := ypart tmp;
+ endfor;
+
+ currenttransform := identity;
+
+ updir = z7 - z15;
+
+ serif := simple_serif (z10, z11, dishing_angle);
+
+ penpos10 (serif_thick, -dishing_angle - 90);
+ penpos11 (serif_thick, dishing_angle - 90);
+ penpos13 (serif_thick, angle (direction 0.05 of serif) + 90);
+ penpos14 (serif_thick, angle (direction 0.85 of serif) + 90);
+
+ z13 = point 0.05 of serif;
+ z14 = point 0.85 of serif;
+
+ penlabels (10, 11, 13, 14);
+ labels (15, 16);
+
+% draw
+ fill z15{-updir}
+ .. z14l{direction 0.85 of serif}
+ .. z11l{-dir (dishing_angle)}
+ .. z11r{dir (dishing_angle)}
+ .. z14r{-direction 0.85 of serif}
+ .. z13r{-direction 0.05 of serif}
+ .. z10r{dir (-dishing_angle)}
+ .. z10l{-dir (-dishing_angle)}
+ .. z13l{direction 0.05 of serif}
+ .. z16{updir}
+ -- cycle;
+fet_endchar;
+
+
+%
+% NOTES:
+%
+% * Right stem is fatter and more straight than the left two stems.
+%
+% * The twiddle at the left is similar to the `p' twiddle.
+%
+% * The bottoms of the stems are blotted.
+%
+%
+% This is cut & paste programming. Somehow three `i' shapes in two
+% characters (`p' and `m') -- doesn't seem worth the trouble of writing
+% a macro.
+%
+
+code := 108;
+
+fet_beginchar ("dynamic m", "m");
+ save i_thick, i_angle, i_twiddle_thick;
+ save i_twiddle_start_angle, i_twiddle_start_y;
+ save i_twiddle_end_angle, i_left_space;
+ save idir, center, right_ending;
+ save overshoot;
+ save p;
+ pair center, idir, right_ending;
+ path p;
+
+ set_char_box (0, 1.5 ex#, 0, 1.0 ex#);
+
+ % should share code with p for twiddle.
+
+ overshoot = .25 serif_thick;
+ i_thick := 21/80 ex;
+ i_twiddle_thick = 1.2 serif_thick;
+ i_twiddle_start_y = 8/16 ex;
+ i_twiddle_start_angle = 0;
+ i_twiddle_end_angle := 35;
+
+ center = (0, 0);
+
+ currenttransform := currenttransform slanted slant;
+
+ i_angle := 0;
+ idir := dir (90 - i_angle);
+ i_left_space = 16/80 ex;
+
+ penpos1 (i_twiddle_thick, -i_twiddle_start_angle);
+ y1 = i_twiddle_start_y;
+ z1r = center - (i_left_space, 0) + whatever * idir;
+
+ y2l = ex + overshoot;
+ z2l = .08 [z3l, z3r] + whatever * idir;
+ z2r = 5/8 [z1r, z3l] + whatever * idir;
+ y2r = y5l + 1/9 ex;
+ z2 = 1/2 [z2l, z2r];
+
+ penpos3 (i_thick, 0);
+ y3 = 0.5 bottom_blot + ypart center;
+ z3l = center + whatever * idir;
+
+ penpos4 (i_thick - bottom_blot, 0);
+ y4 = ypart center;
+ z4 - z3 = whatever * idir;
+
+ penpos5 (i_thick, 0);
+ z5 = z4 + whatever * idir;
+ y5 = 55/80 ex;
+
+ fill simple_serif (z1l, z1r, 90)
+ ..tension 1.2.. z2r{right}
+ .. z5l{z3 - z5}
+ -- z3l{z3 - z5}
+ .. z4l{right}
+ -- z4r{right}
+ .. z3r{z5 - z3}
+ -- z5r{z5 - z3}
+ ..tension 1.2.. z2l{left}
+ .. cycle;
+
+ right_ending := z5r;
+ penlabels (1, 2, 3, 4, 5);
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ clearxy;
+
+ i_angle := -3.2;
+ idir := dir (90 - i_angle);
+ i_left_space := 14/80 ex;
+
+ penpos1 (serif_thick, -i_twiddle_start_angle);
+ z1r = right_ending;
+
+ y2l = ex+ overshoot;
+ z2l = .08 [z3l, z3r] + whatever * idir;
+ z2r = 5/8 [z1r, z3l] + whatever * idir;
+ y2r = y5l + 1/9 ex;
+ z2 = 1/2 [z2l, z2r];
+
+ penpos3 (i_thick, 0);
+ y3 = 0.5 bottom_blot + ypart center;
+ z3l = z5l + whatever * idir;
+
+ penpos4 (i_thick - bottom_blot, 0);
+ y4 = ypart center;
+ z4 - z3 = whatever * idir;
+
+ penpos5 (i_thick, 0);
+ z5l = right_ending + (i_left_space, 0);
+
+ fill simple_serif (z1l, z1r, 90)
+ ..tension 1.05.. z2r{right}
+ .. z5l{z3 - z5}
+ -- z3l
+ .. z4l{right}
+ -- z4r{right}
+ .. z3r{z5 - z3}
+ -- z5r{z5 - z3}
+ ..tension 1.2.. z2l{left}
+ .. cycle;
+
+ right_ending := z5r;
+ penlabels (1, 2, 3, 4, 5);
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ clearxy;
+
+ i_thick := 23/80 ex;
+ i_angle := -6;
+ idir := dir (90 - i_angle);
+ i_left_space := 14/80 ex;
+
+ penpos1 (serif_thick, -i_twiddle_start_angle);
+ z1r = right_ending;
+
+ y2l = ex + overshoot;
+ z2l = .08 [z3l, z3r] + whatever * idir;
+ z2r = 5/8 [z1r, z3l] + whatever * idir;
+ y2r = y5l + 1/9 ex;
+ z2 = 1/2 [z2l, z2r];
+
+ penpos3 (whatever, 20);
+ y3l = 1/8 ex + ypart center;
+ z3l = z7l + whatever * idir;
+ z3r = z7r + whatever * idir;
+
+ penpos5 (whatever, 10);
+ z5l = right_ending + (i_left_space, 0);
+ z5r = z7r + whatever * idir;
+
+ penpos6 (serif_thick, -i_twiddle_end_angle);
+ y6l = 23/80 ex + ypart center;
+ z6l = 1.6 [z3l, z3r] + whatever * idir;
+
+ penpos7 (i_thick, 0);
+ y7 = 0;
+ z7l = z5l + whatever * idir;
+
+ z8 = z7 - (0, overshoot);
+
+ fill simple_serif (z1l, z1r, 90)
+ ..tension 1.05.. z2r{right}
+ .. z5l{z3 - z5}
+ -- z3l{z3 - z5}
+ .. z8{right}
+ .. simple_serif (z6r, z6l, 90)
+ ..tension 0.85.. z3r{z5 - z3}
+ -- z5r{z5 - z3}
+ ..tension 1.2.. z2l{left}
+ .. cycle;
+
+ penlabels (range 1 thru 8);
+fet_endchar;
+
+
+code := 113;
+
+fet_beginchar ("dynamic r", "r");
+ save base_point, stem_thick, bulb_diam;
+ save twiddle_thick, attach_len, overshoot, taille;
+ pair base_point;
+
+ set_char_box (0, .75 ex#, 0, ex#);
+
+ stem_thick =.26 ex;
+ bulb_diam = .30 ex;
+ twiddle_thick = 1.1 serif_thick;
+ overshoot = .5 serif_thick;
+ taille = -0.3 serif_thick;
+ attach_len + bulb_diam / 2 + stem_thick = w;
+
+
+ base_point = (0, 0);
+
+ currenttransform := identity slanted ypart (dir (15));
+
+ penpos1 (stem_thick, 0);
+ x1l = 0;
+ y1l = .5 bottom_blot;
+
+ penpos2 (stem_thick, 0);
+ x2l = x1l;
+ y2l - y1l = 36/47 ex;
+
+ penpos3 (twiddle_thick, -20);
+ x3r = x2l - .2 ex;
+ y3 = .77 ex;
+
+ x4l = -0.1 [x1l, x1r];
+ y4l = ex + overshoot;
+ x4r = 0.62 [x3r, x2l];
+ y4r = 0.5 [y4l, y2l];
+
+ penpos5 (whatever, -74);
+ y5l - y5r = bulb_diam;
+ y5l = ex + overshoot;
+ x5 = x2r + attach_len;
+
+ penpos6 (bulb_diam, 0);
+ z6 = z5;
+
+% z7 = z6l + taille * dir (180);
+ z7 = z6 + .4 * bulb_diam * dir (-125);
+
+ z8 = 9/10 [z1r, z2r];
+
+ x9 = 0.15 [x1r, x1l];
+ y9 = y4l - .12 ex;
+
+ penpos10 (stem_thick - bottom_blot, 0);
+ x10 = x1;
+ y10 = 0;
+
+% pickup pencircle scaled 1;
+
+% draw
+ fill z1r{down}
+ .. z10r{left}
+ -- z10l{left}
+ .. z1l{up}
+ -- z2l{up}
+ .. z4r{left}
+ ..tension 1.2.. {down}simple_serif (z3r, z3l,-90){up}
+ ..tension 0.95.. z4l
+ .. {curl 1}z9{curl 1}
+ .. z5l
+ .. z6r{dir (-80)}
+ .. z5r{left}
+ .. z7
+ .. z6l
+ ..tension 1.2.. z8{down}
+ -- cycle;
+
+ penlabels (range 1 thru 10);
+fet_endchar;
+
+
+%%% KERNING
+
+ligtable "m":
+ "p" kern 0.2 ex#,
+ "f" kern -0.1 ex#;
+
+ligtable "f":
+ "f" kern -0.13 ex#;
+
+ligtable "r":
+ "f" kern 0.1 ex#;
+
+
+%% notes from old dyn code.
+
+% `f' obviously has a _lot_ bigger slant than `p' (see Wanske p.239).
+% However; perhaps we need two f symbols:
+% - a super-slanted one used in `f', `mf', `sfz', `sf'
+% - a more normal-slanted in `ff', `fff', `fp', `fp' (see Wanske p.241)
+%
+% Looking at professionally typeset music reveals that typesetters
+% are somewhat unsure about slanting in `mf', `fp', `sfz'
+%
+% `f' and `p' (in any combination) are a lot (factor two) fatter than
+% `s', `m', and `z'. Sometimes the `m' and `z' are a bit fatter than
+% `s'.
+%
+% Chester, Breitkopf suggest smaller sizes of these other glyphs,
+% using the x-height as reference point.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-eindelijk.mf b/muse2/share/scoreglyphs/feta-original/feta-eindelijk.mf
new file mode 100644
index 00000000..de97f186
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-eindelijk.mf
@@ -0,0 +1,593 @@
+% feta-eindelijk.mf -- implement rest symbols -*-Fundamental-*-
+%
+% part of LilyPond's pretty-but-neat music font
+%
+% source file of the Feta (not the Font-En-Tja) music font
+%
+% (c) 1997--2009 Jan Nieuwenhuizen <janneke@gnu.org>
+
+fet_begingroup ("rests");
+
+save block_rest_y, block_rest_x;
+save breve_rest_y, breve_rest_x;
+
+breve_rest_y# = staff_space#;
+breve_rest_x# = 3/5 staff_space#;
+block_rest_y# = 5/8 staff_space#;
+block_rest_x# = 3/2 staff_space#;
+
+define_whole_pixels (block_rest_y, block_rest_x);
+define_whole_pixels (breve_rest_y, breve_rest_x);
+
+
+def block_rest =
+ draw_block ((0, 0), (block_rest_x, block_rest_y));
+enddef;
+
+
+fet_beginchar ("whole rest", "0");
+ set_char_box (0, block_rest_x#,
+ block_rest_y#, 0);
+
+ block_rest;
+ currentpicture := currentpicture
+ shifted (0, -block_rest_y + feta_space_shift);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("half rest", "1");
+ set_char_box (0, block_rest_x#, 0, block_rest_y#);
+
+ block_rest;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+%
+% should use ledgerline thickness?
+%
+fet_beginchar ("whole rest (outside staff)", "0o");
+ set_char_box (0, block_rest_x#,
+ block_rest_y#, ledgerlinethickness# / 2);
+
+ block_rest;
+ currentpicture := currentpicture shifted (0, -block_rest_y);
+
+ pickup pencircle scaled ledgerlinethickness;
+
+ y5 = y6 = 0;
+ lft x5 = -b - block_rest_y;
+ rt x6 = w + block_rest_y;
+ draw_gridline (z5, z6, ledgerlinethickness_rounded);
+
+ draw_staff (-2, 2, -3);
+fet_endchar;
+
+
+fet_beginchar ("half rest (outside staff)", "1o");
+ set_char_box (0, block_rest_x#,
+ ledgerlinethickness# / 2, block_rest_y#);
+
+ block_rest;
+
+ pickup pencircle scaled ledgerlinethickness;
+
+ y5 = y6 = 0;
+ lft x5 = -b - block_rest_y;
+ rt x6 = w + block_rest_y;
+
+ draw_gridline (z5, z6, ledgerlinethickness_rounded);
+
+ draw_staff (-2, 2, 3);
+fet_endchar;
+
+
+fet_beginchar ("maxima rest", "M3");
+ set_char_box (0, 3 breve_rest_x#, breve_rest_y#, breve_rest_y#);
+
+ draw_block ((0, -breve_rest_y + feta_shift),
+ (breve_rest_x, breve_rest_y));
+
+ addto currentpicture also currentpicture shifted (2 breve_rest_x, 0);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("longa rest", "M2");
+ set_char_box (0, breve_rest_x#, breve_rest_y#, breve_rest_y#);
+
+ draw_block ((0, -breve_rest_y + feta_shift),
+ (breve_rest_x, breve_rest_y));
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("breve rest", "M1");
+ set_char_box (0, breve_rest_x#, 0, breve_rest_y#);
+
+ draw_block ((0, 0), (breve_rest_x, breve_rest_y));
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("Quarter rest", "2");
+ save alpha, yshift, height;
+ save xcenter;
+
+ yshift# := -1.25 staff_space#;
+ height# := 2.8125 staff_space#;
+ define_pixels (yshift, height);
+
+ alpha := -50;
+ thick := 1/4 staff_space;
+ rthin := 1.25 linethickness;
+ xcenter := -0.1 staff_space;
+ rthick := 2 thick + rthin;
+
+ set_char_box (0, 0.95 staff_space#, -yshift#, yshift# + height#);
+
+ save ne, nw, se, sw;
+ pair ne, nw, se, sw;
+
+ se = dir alpha;
+ ne = dir (alpha + 90);
+ nw = dir (alpha + 180);
+ sw = dir (alpha + 270);
+
+ penpos1 (rthin, alpha + 90);
+ penpos2 (5/4 rthick, alpha);
+ penpos4 (5/4 rthick, alpha);
+ penpos5 (rthin, alpha + 90);
+ penpos3 (3/4 rthick, alpha);
+% penpos6 (5/8 rthick, alpha);
+ penpos6 (2/3 rthick, alpha);
+ penpos7 (1/2 rthin, alpha + 90);
+
+ z10 = z2l + 1/2 rthin * sw;
+% z11 = z4l + 1/2 rthin * sw;
+ z11 = z4l + 1/2 rthin * sw + 1/2 rthin * se;
+ z12 = z4r + 1/2 rthin * ne;
+% z13 = z2r + 1/2 rthin * ne;
+ z13 = z2r + 1/2 rthin * ne + 1/2 rthin * nw;
+
+ y1r = h;
+ x1l = xcenter + 1/3 staff_space;
+ z2r = z1 + staff_space * se;
+ z3 = 1/2 [z2, z4];
+ x4 = xcenter + 3/8 staff_space;
+ y4 = 0;
+ y4l := vround y4l;
+ z5 = round (z4l + 1.3 staff_space * se) + feta_offset;
+ x6l = x4l;
+ y6l = vround y4r;
+ x6r := hround x6r + xpart feta_offset;
+ y6r := vround y6r + ypart feta_offset;
+ x7 = hround (xcenter + 2/5 staff_space) + xpart feta_offset;
+ y7 = -d;
+
+ save before, after;
+ path before, after;
+ before = z11{se}
+ .. {se}z5l;
+ after = z5r{nw}
+ ..tension1.4.. z6l;
+ (u, v) = before intersectiontimes after;
+
+ fill z1l{se}
+ .. {se}z10
+ .. z3l
+ .. subpath (0, u) of before
+ .. subpath (v, infinity) of after
+ ..tension1.4.. {se}z7l
+ .. z7r{nw}
+ ..tension1.4.. z6r
+ ..tension1.4.. {se}z5l
+ .. z5r{nw}
+ .. {nw}z12
+ .. z3r
+ .. z13{nw}
+ .. {nw}z1r
+ .. cycle;
+
+ penlabels (1, 2, 3, 4, 5, 6, 7);
+ penlabels (10, 11, 12, 13);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+%
+% Notes about 8th rest:
+%
+% * 8th rest should be no wider than the black note head
+%
+% * The inside corner of the horizontal portion is usually a little blotted.
+%
+% * The top of the crook chops off the vertical brush
+%
+% * The crook widens a little
+%
+% * The bottom of the brush is slightly flat, as it has to align with
+% stafflines if it is inside the staff.
+%
+% * The top of the brush usually is a little lower than the top of bulb.
+%
+% * The bulb can vary. Sometimes it is open (like in the clefs). Sometimes
+% it is closed, or even a flare.
+%
+
+% from an email to Rune Zedeler:
+%
+%
+% For example, the 8th rest was vaguely based on a book with trumpet
+% studies by Duhem, and by Baerenreiters cello suites. I included my
+% findings in a comment in the mf file. One of the things that I tried
+% to do was make the rest a little lighter and narrower than the black
+% note head. I think this looks better in polyphonic music, when the
+% rest is below a head from a different voice.
+%
+
+save bulb_diam, thin, thick;
+
+bulb_diam# := 0.64 staff_space#;
+thin# := 1.4 linethickness# - 0.02 staff_space#;
+thick# := 2.2 linethickness#;
+
+crook_thin := 0.5 linethickness + 0.08 staff_space;
+lower_brush := 1.5 linethickness;
+
+define_pixels (bulb_diam);
+define_whole_blacker_pixels (thin, thick);
+
+
+%
+% PAT is a compact way to pass the brush shape to the routine.
+%
+
+def draw_rest_bulb (expr ycenter, ycut, pat, stretch, show_labels) =
+begingroup;
+ save x, y, pt, res;
+
+ z1l = point 0 of pat;
+ z2l = point 1 of pat;
+ z2r = point 3 of pat;
+ z1r = point 4 of pat;
+ z1 = 0.5 [z1l, z1r];
+ z2 = 0.5 [z2l, z2r];
+ y10 = ycenter;
+ z10 = whatever [z2, z1] + left * bulb_diam * stretch;
+
+ % this enforces similar bulb shapes for lower resolutions
+ x10 := hround x10;
+
+ z3 = z10 + bulb_diam / 2.15 * dir (-72);
+ y3 := hround y3;
+ z5 = z10 + up * bulb_diam / 2 + right * linethickness / 3;
+ y5 := hround y5;
+
+ z7 = 0.5 [z4, z5] + crook_thin * (0.45, 0.4) / 1.3;
+ x8 = hround (x10 - 0.4 bulb_diam);
+ y8 = y10 + 0.25 linethickness;
+
+ z6 = whatever [z1l, z2l];
+ z6 = z3 + whatever * dir (12);
+
+ z4 = z3 + whatever * (z6 - z3)
+ + 1.1 crook_thin * (unitvector (z6 - z3) rotated 90);
+ x4 = x10 + bulb_diam * .62;
+ y4 := vround y4;
+
+ (pt, whatever) = pat intersectiontimes ((0, ycut) -- (w, ycut));
+
+ path res;
+ res = point pt of pat {-direction pt of pat}
+ ..tension 2.. z4{left}
+ ..tension 0.9.. z7
+ .. z5{left}
+ .. z8
+ .. z3{right}
+ .. {curl 0.2}z6;
+
+ if show_labels = 1:
+ labels (3, 4, 5, 6, 7, 8, 10);
+ fi;
+
+res
+endgroup;
+enddef;
+
+
+def draw_eighth_rest (expr show_labels) =
+ save ycenter;
+ save pat, bulb;
+ path pat, bulb;
+
+ set_char_box (0, 1.0 staff_space#,
+ 1.0 staff_space# + 0.5 linethickness#,
+ 0.5 staff_space# + bulb_diam# / 2);
+
+ penpos1 (thick, 0);
+ penpos2 (thin, 10);
+
+ y1 = -staff_space_rounded;
+ y2 = h - vround lower_brush;
+ x2r = w;
+ z2 = z1 + whatever * dir (72);
+ z9 = z2 + 0.5 linethickness * dir (angle (z2 - z1) - 10);
+ y9 := vround y9;
+
+ x1l := hround x1l;
+ x1r := hround x1r;
+ x1 := .5 [x1l, x1r];
+
+ if show_labels = 1:
+ penlabels (1, 2);
+ labels (9);
+ fi;
+
+ pat = z1l
+ -- z2l
+ .. z9
+ .. z2r
+ -- z1r
+ .. cycle;
+ bulb = draw_rest_bulb (0.5 staff_space, y2r, pat, 1.0, show_labels);
+
+ fill simple_serif (z1l, z1r, 40)
+ -- z2r
+ .. z9
+ .. bulb
+ -- z1l
+ .. cycle;
+
+ draw_staff (-2, 2, 0);
+enddef;
+
+
+fet_beginchar ("Classical quarter rest", "2classical");
+ draw_eighth_rest (0);
+ currentpicture := currentpicture xscaled -1 shifted (w, 0);
+fet_endchar;
+
+
+fet_beginchar ("8th rest", "3");
+ draw_eighth_rest (1);
+fet_endchar;
+
+
+%
+% TODO: the X dimensions of the rests are fucked up:
+% they can collide with augmentation dots.
+%
+
+fet_beginchar ("16th rest", "4");
+ save ycenter;
+ save pat, bulb_a, bulb_b;
+ path pat, bulb_a, bulb_b;
+
+ set_char_box (0, 1.2 staff_space#,
+ 2.0 staff_space# + 0.5 linethickness#,
+ 0.5 staff_space# + bulb_diam# / 2);
+
+ penpos1 (thick, 0);
+ penpos2 (thin, 10);
+
+ y1 = -2 staff_space_rounded;
+ y2 = h - vround lower_brush;
+ x2r = w;
+ z2 = z1 + whatever * dir (74);
+ z9 = z2 + 0.5 linethickness * dir (angle (z2 - z1) - 10);
+ y9 := vround y9;
+
+ x1l := hround x1l;
+ x1r := hround x1r;
+ x1 := .5 [x1l, x1r];
+
+ pat = z1l
+ -- z2l
+ .. z9
+ .. z2r
+ -- z1r
+ .. cycle;
+ bulb_a = draw_rest_bulb (.5 staff_space,
+ y2r, pat, 0.98, 1);
+ bulb_b = draw_rest_bulb (.5 staff_space - staff_space_rounded,
+ hround ((-0.5 + 0.2) * staff_space),
+ pat, 1.02, 1);
+
+ fill simple_serif (z1l, z1r, 40)
+ -- z2r
+ .. z9
+ .. bulb_a
+ -- bulb_b
+ -- z1l
+ .. cycle;
+
+ penlabels (1, 2);
+ labels (9);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("32th rest", "5");
+ save ycenter;
+ save pat, bulb_a, bulb_b, bulb_c;
+ path pat, bulb_a, bulb_b, bulb_c;
+
+ set_char_box (0, 1.3 staff_space#,
+ 2.0 staff_space# + 0.5 linethickness#,
+ 1.5 staff_space# + bulb_diam# / 2);
+
+ penpos1 (thick, 0);
+ penpos2 (thin, 10);
+
+ y1 = -2 staff_space_rounded;
+ y2 = h - vround lower_brush;
+ x2r = w;
+ z2 = z1 + whatever * dir (76);
+ z9 = z2 + 0.5 linethickness * dir (angle (z2 - z1) - 10);
+ y9 := vround y9;
+
+ x1l := hround x1l;
+ x1r := hround x1r;
+ x1 := .5 [x1l, x1r];
+
+ pat = z1l
+ -- z2l
+ .. z9
+ .. z2r
+ -- z1r
+ .. cycle;
+ bulb_a = draw_rest_bulb (.5 staff_space + staff_space_rounded,
+ y2r, pat, 0.96, 1);
+ bulb_b = draw_rest_bulb (.5 staff_space,
+ hround ((0.5 + 0.2) * staff_space),
+ pat, 1.00, 1);
+ bulb_c = draw_rest_bulb (.5 staff_space - staff_space_rounded,
+ hround ((-0.5 + 0.21) * staff_space),
+ pat, 1.04, 1);
+
+ fill simple_serif (z1l, z1r, 40)
+ -- z2r
+ .. z9
+ .. bulb_a
+ -- bulb_b
+ -- bulb_c
+ -- z1l
+ .. cycle;
+
+ penlabels (1, 2);
+ labels (9);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("64th rest", "6");
+ save ycenter;
+ save pat, bulb_a, bulb_b, bulb_c, bulb_d;
+ path pat, bulb_a, bulb_b, bulb_c, bulb_d;
+
+ set_char_box (0, 1.4 staff_space#,
+ 3.0 staff_space# + 0.5 linethickness#,
+ 1.5 staff_space# + bulb_diam# / 2);
+
+ penpos1 (thick, 0);
+ penpos2 (thin, 10);
+
+ y1 = -3 staff_space_rounded;
+ y2 = h - vround lower_brush;
+ x2r = w;
+ z2 = z1 + whatever * dir (78);
+ z9 = z2 + 0.5 linethickness * dir (angle (z2 - z1) - 10);
+ y9 := vround y9;
+
+ x1l := hround x1l;
+ x1r := hround x1r;
+ x1 := .5 [x1l, x1r];
+
+ pat = z1l
+ -- z2l
+ .. z9
+ .. z2r
+ -- z1r
+ .. cycle;
+ bulb_a = draw_rest_bulb (.5 staff_space + staff_space_rounded,
+ y2r, pat, 0.94, 1);
+ bulb_b = draw_rest_bulb (.5 staff_space,
+ hround ((0.5 + 0.20) * staff_space),
+ pat, 0.98, 1);
+ bulb_c = draw_rest_bulb (.5 staff_space - staff_space_rounded,
+ hround ((-0.5 + 0.21) * staff_space),
+ pat, 1.02, 1);
+ bulb_d = draw_rest_bulb (.5 staff_space - 2 staff_space_rounded,
+ hround ((-1.5 + 0.22) * staff_space),
+ pat, 1.06, 1);
+
+ fill simple_serif (z1l, z1r, 40)
+ -- z2r
+ .. z9
+ .. bulb_a
+ -- bulb_b
+ -- bulb_c
+ -- bulb_d
+ -- z1l
+ .. cycle;
+
+ penlabels (1, 2);
+ labels (9);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("128th rest", "7");
+ save ycenter;
+ save pat, bulb_a, bulb_b, bulb_c, bulb_d, bulb_e;
+ path pat, bulb_a, bulb_b, bulb_c, bulb_d, bulb_e;
+
+ set_char_box (0, 1.5 staff_space#,
+ 3.0 staff_space# + 0.5 linethickness#,
+ 2.5 staff_space# + bulb_diam# / 2);
+
+ penpos1 (thick, 0);
+ penpos2 (thin, 10);
+
+ y1 = -3 staff_space_rounded;
+ y2 = h - vround lower_brush;
+ x2r = w;
+ z2 = z1 + whatever * dir (80);
+ z9 = z2 + 0.5 linethickness * dir (angle (z2 - z1)- 10);
+ y9 := vround y9;
+
+ x1l := hround x1l;
+ x1r := hround x1r;
+ x1 := .5 [x1l, x1r];
+
+ pat = z1l
+ -- z2l
+ .. z9
+ .. z2r
+ -- z1r
+ .. cycle;
+ bulb_a = draw_rest_bulb (.5 staff_space + 2 staff_space_rounded,
+ y2r, pat, 0.92, 1);
+ bulb_b = draw_rest_bulb (.5 staff_space + staff_space_rounded,
+ hround ((1.5 + 0.20) * staff_space),
+ pat, 0.96, 1);
+ bulb_c = draw_rest_bulb (.5 staff_space,
+ hround ((0.5 + 0.21) * staff_space),
+ pat, 1.0, 1);
+ bulb_d = draw_rest_bulb (.5 staff_space - staff_space_rounded,
+ hround ((-0.5 + 0.22) * staff_space),
+ pat, 1.04, 1);
+ bulb_e = draw_rest_bulb (.5 staff_space - 2 staff_space_rounded,
+ hround ((-1.5 + 0.23) * staff_space),
+ pat, 1.08, 1);
+
+ fill simple_serif (z1l, z1r, 40)
+ -- z2r
+ .. z9
+ .. bulb_a
+ -- bulb_b
+ -- bulb_c
+ -- bulb_d
+ -- bulb_e
+ -- z1l
+ .. cycle;
+
+ penlabels (1, 2);
+ labels (9);
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_endgroup ("rests");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-generic.mf b/muse2/share/scoreglyphs/feta-original/feta-generic.mf
new file mode 100644
index 00000000..f2c90cdf
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-generic.mf
@@ -0,0 +1,57 @@
+%
+% feta-generic.mf -- implement generic stuff: include lots of files, but don't
+% set dims.
+%
+% source file of the Feta (defintively not an abbreviation for Font-En-Tja)
+% music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+
+if test = -1:
+ mode := smoke;
+fi
+
+staffsize# := design_size * pt#;
+
+mode_setup;
+
+input feta-macros;
+
+input feta-params;
+
+font_x_height staff_space#;
+
+%% this is a fallback so we can run the font without including feta-bolletjes.
+black_notehead_width# := 1.0 staff_space#;
+
+
+fet_beginfont ("feta", design_size, "fetaMusic");
+
+if test = 0:
+ input feta-eindelijk;
+ input feta-toevallig;
+ input feta-arrow;
+ input feta-puntje;
+ input feta-bolletjes;
+ input feta-schrift;
+ input feta-banier;
+ input feta-klef;
+ input feta-timesig;
+ input feta-pendaal;
+ input feta-haak;
+ input feta-accordion;
+else:
+ input feta-test-generic.mf;
+fi
+
+autometric_parameter ("staffsize", staffsize#);
+autometric_parameter ("stafflinethickness", stafflinethickness#);
+autometric_parameter ("staff_space", staff_space#);
+autometric_parameter ("linethickness", linethickness#);
+autometric_parameter ("black_notehead_width", black_notehead_width#);
+autometric_parameter ("ledgerlinethickness", ledgerlinethickness#);
+autometric_parameter ("blot_diameter", blot_diameter#);
+
+fet_endfont;
diff --git a/muse2/share/scoreglyphs/feta-original/feta-haak.mf b/muse2/share/scoreglyphs/feta-original/feta-haak.mf
new file mode 100644
index 00000000..ddc01c08
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-haak.mf
@@ -0,0 +1,92 @@
+% feta-haak.mf -- implement bracket tips -*-Fundamental-*-
+%
+% part of LilyPond's pretty-but-neat music font
+%
+% source file of the Feta (not the Font-En-Tja) music font
+%
+% (c) 2005--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+fet_begingroup ("brackettips");
+
+def draw_bracket (expr thick_sharp, width_sharp, updown) =
+begingroup;
+ save p, thin, thick, flattening, width, hair, flare;
+ path p;
+ pair tipdir;
+
+ flattening = 0.72;
+ thick# = thick_sharp;
+ flare# = flattening * width#;
+ width# = width_sharp;
+
+ define_pixels (thick, width, flare);
+ if updown = 1:
+ set_char_box (0, width#,
+ .5 thick#, flare#);
+ else:
+ set_char_box (0, width#,
+ flare#, .5 thick#);
+ fi;
+
+ thin = 2 linethickness;
+ hair = 1.25 linethickness;
+
+ pickup pencircle scaled thin;
+ y7 = y1;
+ x7 = x2;
+ z2 = z4r + (thin, 0);
+
+ penpos3 (thin, 0);
+ penpos4 (thin, 90);
+
+ z3 = z4;
+
+ top y3 = 0.5 thick;
+ lft x3 = 0.0;
+ x1 = x3l;
+ y1 = -0.5 thick;
+
+ z8 = .5 [z2, z7];
+ top y5 = flare;
+ rt x5 = width;
+
+ p := z8{right}
+ ..tension 1.2.. z5{curl 0};
+ tipdir := direction 1 of p;
+
+ penpos5 (hair, angle tipdir);
+ penpos6 (hair, 90 + angle tipdir);
+
+ z5 = z6;
+
+ pickup pencircle scaled 1;
+
+ fill (z1
+ -- z3l{up}
+ .. z4r{right}
+ -- z2{right}
+ .. z6r{tipdir}
+ .. z5r
+ .. z6l{-tipdir}
+ ..tension 1.1.. z7{left}
+ & z7
+ -- z1
+ & cycle) yscaled updown;
+
+ if updown = 1:
+ penlabels (1, 2, 3, 4, 5, 6, 7, 8);
+ fi;
+endgroup;
+enddef;
+
+
+fet_beginchar ("bracket tip up", "up");
+ draw_bracket (0.45 staff_space#, 1.9 staff_space#, 1);
+fet_endchar;
+
+
+fet_beginchar ("bracket tip down", "down");
+ draw_bracket (0.45 staff_space#, 1.9 staff_space#, -1);
+fet_endchar;
+
+fet_endgroup ("brackettips");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-klef.mf b/muse2/share/scoreglyphs/feta-original/feta-klef.mf
new file mode 100644
index 00000000..15008d84
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-klef.mf
@@ -0,0 +1,698 @@
+% feta-klef.mf -- implement Clefs -*-Fundamental-*-
+%
+% part of LilyPond's pretty-but-neat music font
+%
+% source file of the Feta (not the Font-En-Tja) music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>,
+% Jan Nieuwenhuizen <janneke@gnu.org>,
+% Juergen Reuter <reuter@ipd.uka.de>
+
+
+fet_begingroup ("clefs");
+
+%
+% [Wanske] says the bulbs should be positioned about 1/4 right of the
+% `arrow'.
+%
+% TODO: The hair-curve at z6r looks a little awkward.
+%
+
+def draw_c_clef (expr reduction) =
+ save hair, norm, reduced_ss, right_edge;
+ save xoff;
+
+ reduced_ss# = staff_space# * reduction;
+ norm# := 2/3 reduced_ss#;
+ hair# := 0.06 reduced_ss# + 0.5 linethickness#;
+ right_edge# = 15/4 norm# + 2 hair#;
+ define_pixels (norm, reduced_ss, right_edge);
+ define_whole_vertical_blacker_pixels (hair);
+
+ set_char_box (0, right_edge#, 2 reduced_ss#, 2 reduced_ss#);
+
+ % make unreduced glyph fit exactly into five staff lines
+ if reduction = 1:
+ h := d := 2 staff_space_rounded;
+ fi;
+
+ % assure that the gap between the left and right stem
+ % has the same number of pixels as the thickness of the right
+ % stem
+ draw_block ((0, -d + feta_shift),
+ (3/4 norm + 1/2 hair, h));
+ draw_block ((3/4 norm + 1/2 hair + hround (3/2 hair), -d + feta_shift),
+ (3/4 norm + 1/2 hair + 2 hround (3/2 hair), h));
+
+ % assure symmetry
+ h := h - feta_shift;
+
+ pickup feta_fillpen;
+
+ xoff = 3/4 norm + 1/2 hair + 2 hround (3/2 hair);
+ z5l = (xoff - 3/4 hair, 0);
+ z5r = (x4, 0);
+
+ penpos1 (hair - pen_top - pen_bot, -90);
+ top z1l = (xoff + norm + hair, h);
+
+ penpos2 (hround (norm - 3/2 hair) - pen_lft - pen_rt, 180);
+ rt z2l = (w, h / 2);
+
+ penpos3 (hair - pen_top - pen_bot, 90);
+ bot z3l = ((right_edge - xoff) / 2 + xoff,
+ vround (.5 norm - 1.5 hair));
+
+ penpos4 (hair - pen_lft - pen_rt, 0);
+ top z4 = (xoff + 1/2 norm + 1/2 hair,
+ vfloor (reduced_ss - linethickness - .2 hair));
+
+ bot z6 = (xoff + 3/4 norm, vround (.5 norm - .5 hair));
+
+ save t;
+ t = 0.833;
+
+ save pat;
+ path pat;
+
+ pat = z5l{curl 1}
+ .. z4l{up}
+ .. z4r{down}
+ .. z3r{right}
+ ..tension t.. z2r{up}
+ ..tension t.. flare_path (top z1l, 180, 90,
+ hair, hfloor (norm - 1/2 hair), -1)
+ ..tension t.. z2l{down}
+ .. z3l{left}
+ .. z6
+ .. z5r{down};
+
+ filldraw pat shifted (0, feta_shift)
+ -- reverse pat yscaled -1 shifted (0, -feta_eps)
+ -- cycle;
+
+ penlabels (1, 2, 3, 4, 5, 6);
+
+ % ugh, should be bulb, not flare?
+
+ draw_staff (-2, 2, 0);
+enddef;
+
+
+fet_beginchar ("C clef", "C");
+ draw_c_clef (1.0);
+fet_endchar;
+
+
+fet_beginchar ("C clef", "C_change");
+ draw_c_clef (.8);
+fet_endchar;
+
+
+%
+% New bulb routine:
+%
+% Insert a brushed piece of the path, and draw the rest of the bulb
+% separately.
+%
+% The bulb has circular form. Neat merging of the bulb and brushed path
+% is done by playing with tension.
+%
+
+def new_bulb (expr start_point, start_angle,
+ outer_tangent_point,
+ end_point, end_angle,
+ big_radius, bulb_radius, flare,
+ direction, turning_dir) =
+begingroup;
+ save pat, before, after;
+ save center;
+ save u, v;
+ path pat, before, after;
+ pair center;
+
+ clearxy;
+
+ center = outer_tangent_point
+ + big_radius * dir (0);
+% + (big_radius - bulb_radius) * dir (-turning_dir * 90)
+
+ z1' = center + bulb_radius * dir (turning_dir * 180);
+ z2' = outer_tangent_point + flare * dir (0);
+ z3' = center + bulb_radius * dir (0);
+ z4' = center + bulb_radius * dir (turning_dir * 90);
+ z5' = center - 0.5 [big_radius, bulb_radius] * dir (turning_dir * 90);
+
+ labels (1', 2', 3', 4', 5');
+
+ before := z3'{dir (turning_dir * 90)}
+ .. z4'{-dir (0)}
+ ..tension 1.1.. z1'{-dir (turning_dir* 90)};
+ after := z2'{dir (turning_dir * 90)}
+ .. end_point{dir (end_angle)};
+ (u, v) = before intersectiontimes after;
+
+ pat := start_point{dir (start_angle)}
+ .. outer_tangent_point{dir (-turning_dir * 90)}
+ ..tension 1.02.. z5'{dir (0)}
+ .. subpath (0, u) of before
+ .. subpath (v, infinity) of after;
+
+ if direction = 0:
+ pat := reverse pat;
+ fi
+
+pat
+endgroup
+enddef;
+
+
+%
+% There is some variation in the shape of bass clefs.
+%
+% * In some clefs the size of the swoosh tip almost reaches the
+% bottom staff line; in some it crosses the 2nd line from the bottom
+% with a small overshoot.
+%
+% The most popular design is where the X part of the tip is aligned
+% with the left bulb boundary, and the Y part ends on the 2nd
+% staffline exactly. This is what we do.
+%
+% * The diameter of the bulb is the width of the open space.
+%
+% * The vertical center of the bulb can be on or slightly above the
+% staff line.
+%
+% * The vertical position of the dots can be symmetrical around the
+% staffline, centered in the staff space. The Baerenreiter SCS has
+% the bottom dot raised by approximately 0.1 staff space.
+%
+% * Uncarefully set music may have overshoots at the top. We have none.
+%
+% * It is not exactly clear where the vertical tangent at the right
+% of the swoosh should be.
+%
+
+def draw_bass_clef (expr exact_center, reduction) =
+ save reduced_ss, swoosh_width;
+ save right_thickness, right_offset, tip_protrude;
+ save dot_diam, bulb_y_offset, bulb_flare;
+ pair tip_protrude;
+
+ reduced_ss# = staff_space# * reduction;
+ 2.2 dot_diam# = reduction * (staff_space# - stafflinethickness#);
+ right_thickness# = 0.37 staff_space# + 1.2 linethickness#;
+ swoosh_width# = 2.1 reduced_ss#;
+ define_pixels (swoosh_width);
+ define_whole_pixels (reduced_ss);
+ define_whole_blacker_pixels (dot_diam, right_thickness);
+
+ right_offset = 0.05 staff_space;
+ bulb_y_offset := 0.075 staff_space;
+ bulb_flare := 2.5 linethickness;
+% tip_protrude := (-linethickness, -.2 staff_space);
+ tip_protrude := (0, 0);
+
+ set_char_box (-xpart exact_center,
+ xpart exact_center + swoosh_width# + 7/12 reduced_ss#,
+ -ypart exact_center + 2.5 reduced_ss#,
+ ypart exact_center + reduced_ss#);
+
+ y1 = bulb_y_offset;
+ x1 = 0;
+
+ x2 = .5 [x1, x3];
+ x2l = x2r = x2;
+
+ y2l := vround_pixels (reduced_ss# + 0.5 linethickness#);
+ y2l - y2r = linethickness;
+
+ x3l - x1 = swoosh_width;
+ x3l - x3r = right_thickness;
+
+ % optical correction: the top dot seems farther away if y3l = 0.
+ y3l = right_offset;
+
+ z4 = -(0, 2.0 reduced_ss) + tip_protrude;
+
+ penpos3 (whatever, 185);
+ penpos4 (linethickness, 135);
+
+ fill new_bulb (z2l, 180, z1, z2r, 0,
+ 0.45 reduced_ss, 0.4 reduced_ss,
+ bulb_flare, 1, 1)
+ .. z3r{down}
+ .. {curl 0}simple_serif (z4r, z4l, 90){curl 0}
+ .. z3l{up}
+ ..tension 0.9.. cycle;
+
+ pickup pencircle scaled dot_diam;
+
+ lft x5 = hround (x3l + 1/3 reduced_ss - dot_diam / 2);
+ bot y5 = vfloor (.5 reduced_ss - dot_diam / 2);
+ z6 = z5 yscaled -1;
+
+ % for symmetry
+ y5 := y5 + feta_shift;
+
+ drawdot z5;
+ drawdot z6;
+
+ penlabels (1, 2, 3, 4, 5, 6);
+
+ draw_staff (-3, 1, 0);
+enddef;
+
+
+fet_beginchar ("F clef ", "F");
+ draw_bass_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("F clef (reduced)", "F_change");
+ draw_bass_clef ((0, 0), 0.8);
+fet_endchar;
+
+
+
+%
+% Inspired by Baerenreiter
+%
+%
+% Beste lezers, kijk,
+%
+% Een bolletje hebben we bij toeval allemaal wel eens getekend, maar begint u
+% toch eenvoudig. Eerst een eenvoudig kruis of herstellingsteken
+% en via de dubbelslag naar een voorzichtig vlaggetje, en heb geduld!
+% Ikzelf heb bijvoorbeeld over mijn eerste gave G-sleutel
+% 35 kilobyte metafont, 12 patchlevels, 0 vriendinnen en 45 dagen gedaan
+%
+% -- vrij naar Van Kooten & De Bie
+%
+
+def debugfill = fill enddef;
+
+def draw_gclef (expr reduction) =
+ save reduced_ss, downstroke_dir, downstroke_angle, center;
+ save breapth_factor, inner_thick_end, thinness, thickness, thinnib;
+ save start_angle, inner_start_angle, thinness;
+ save upward_swoosh_angle, bot_angle;
+ save pat;
+ path pat;
+ pair downstroke_dir, center;
+
+ reduced_ss# = staff_space# * reduction;
+ define_pixels (reduced_ss);
+
+ thinness = 0.095 staff_space + 0.75 linethickness;
+ downstroke_dir = unitvector (14, -75);
+ downstroke_angle = angle downstroke_dir;
+ bot_angle = -180; % downstroke_angle - 87
+
+ upward_swoosh_angle = 132;
+ start_angle = -97;
+
+ breapth_factor = 21/14;
+ inner_thick_end = 45;
+ inner_start_angle = downstroke_angle - 43;
+ thickness = .32 reduced_ss + 1.1 linethickness;
+
+ thinnib = thinness;
+
+ set_char_box (0, 1.71 * breapth_factor * reduced_ss#,
+ 2.6 * reduced_ss#, 5 * reduced_ss#);
+
+ center := (breapth_factor * reduced_ss, 0);
+
+ z1 = center + whatever * dir (inner_start_angle);
+ x1 = xpart center - .28 reduced_ss;
+ penpos1 (thinnib, inner_start_angle);
+
+ x2r = xpart center;
+ y2r = vround_pixels (reduced_ss# + .5 stafflinethickness#);
+ penpos2 (thickness, 90);
+
+ z3 = (z4 - center) rotated inner_thick_end + center;
+ penpos3 (thinnib, -90 + inner_thick_end);
+
+ x4 = xpart center - .1 reduced_ss;
+ y4r = -y2r + feta_shift;
+ penpos4 (thinnib, -90);
+
+ x5r = -breapth_factor * reduced_ss + xpart center;
+ y5r = .37 reduced_ss + ypart center;
+ penpos5 (thickness, upward_swoosh_angle);
+
+ z6 = center + whatever * downstroke_dir;
+ y6 = ypart center + 2 reduced_ss;
+ % penpos6 is computed later
+
+ z7l - z6 = whatever * (z5 - z6) ;
+ y7l = 3.5 reduced_ss;
+ penpos7 (thickness, upward_swoosh_angle);
+
+ x9 = .7 [x10, x7r];
+ top y9l = 5 reduced_ss;
+ penpos9 (1.45 thickness, -70);
+
+ x11 - x13r = 1.5 reduced_ss + 0.5 thinnib;
+ y11 = ypart center - 47/28 reduced_ss;
+ y12 = ypart center - 71/28 reduced_ss;
+ y13 = .48 [y12, y4r];
+ x12r = xpart (.45 [z13r, z11] + .75 reduced_ss * downstroke_dir);
+
+% z10 = center + whatever * dir (downstroke_angle - 1.5);
+ x10 = x6 - 2 thinnib;
+ y10 = ypart center + 3.5 reduced_ss;
+ y10l - y10r = 1.0 thickness;
+ z10r - z10l = .7 thinnib * dir (downstroke_angle + 90)
+ + whatever * downstroke_dir;
+ z10 = .5 [z10l, z10r];
+ z11 = center + whatever * downstroke_dir + (-0.05 reduced_ss, 0);
+
+ penpos11 (thinnib, start_angle + 90);
+ penpos12 (thinnib, bot_angle + 90);
+ penpos13 (thinnib + 0.14 staff_space, 180);
+
+ % this auxiliary point ensures good contour overlapping
+ z8 = .5 [z9l, z9r] + .25 ((z9r - z9l) rotated -90);
+
+ z20 = z9l - (0, .25 blot_diameter);
+ penpos20 (blot_diameter, 0);
+
+ pat := z10{down}
+ .. z6
+ ..tension 1.1.. z11{dir (start_angle)};
+
+ penpos6 (thinnib, angle (direction 1 of pat) + 90);
+
+ % two auxiliary points to simulate `draw' with `penstroke'
+ z10' = point 0.3 of pat;
+ penpos10' (1.3 thinnib, angle (direction 0.3 of pat) + 50);
+
+ z11' = point 1.5 of pat;
+ penpos11' (thinnib, angle (direction 1.5 of pat) + 90);
+
+ z21l = z20l;
+ z21r = z9r;
+
+ pat := z21l
+ .. z10l{down}
+ .. z10'l;
+
+ fill z2l{right}
+ .. z3l
+ .. z4l{left}
+ ..tension 1.07.. z5l{up} % inside curve
+ .. z7l{up}
+ ..tension 1.2.. z20r{curl 1}
+ .. {direction 0 of pat}z20l
+ -- z8
+ -- z9r % {dir (downstroke_angle + 0)}
+ ..tension 0.8.. z7r{down}
+ .. z5r{down}
+ .. z4r{right}
+ .. z3r
+ .. z2r{left}
+ ..tension .95.. z1r
+ -- simple_serif (z1r, z1l, 80)
+ -- z1l
+ ..tension 0.85.. cycle;
+
+ penstroke z21e
+ .. z10e{down}
+ .. z10'e
+ .. z6e
+ .. z11'e
+ .. z11e{dir (-95)}
+ .. z12e{dir (bot_angle)};
+
+ fill new_bulb (z12r, bot_angle, z13r, z12l, bot_angle + 180,
+ 0.45 reduced_ss, 0.38 reduced_ss,
+ thinnib + .05 staff_space, 1, -1)
+ -- cycle;
+
+ penlabels (range 1 thru 21);
+ penlabels (10', 11');
+
+ draw_staff (-1, 3, 0);
+enddef;
+
+
+fet_beginchar ("G clef", "G");
+ draw_gclef (1.0);
+fet_endchar;
+
+
+fet_beginchar ("G clef", "G_change");
+ draw_gclef (0.8);
+fet_endchar;
+
+
+%%%%
+%
+% PERCUSSION
+%
+
+%
+% The percussion clef extent is not coincident with its bbox, since
+% the percussion clef needs more space in front than a normal clef.
+%
+
+def draw_percussion_clef (expr reduction) =
+ save reduced_ss, razt;
+
+ reduced_ss# = staff_space# * reduction;
+ define_pixels (reduced_ss);
+
+ set_char_box (-.67 reduced_ss#, 2.0 reduced_ss#,
+ reduced_ss#, reduced_ss#);
+
+ razt := hround (0.45 reduced_ss);
+
+ d := d - feta_shift;
+
+ draw_block ((-b, -d), (-b + razt, h));
+ draw_block ((w - razt, -d), (w, h));
+
+ draw_staff (-3, 1, 1);
+enddef;
+
+
+fet_beginchar ("percussion clef", "percussion");
+ draw_percussion_clef (1.0);
+fet_endchar;
+
+
+fet_beginchar ("percussion clef (reduced)", "percussion_change");
+ draw_percussion_clef (.8);
+fet_endchar;
+
+
+def draw_tab_T (expr pos, siz, slant) =
+begingroup;
+ save vx, vy;
+ pair vx, vy;
+
+ clearxy;
+
+ vx = (xpart siz) * dir 0;
+ vy = (ypart siz) * dir 90;
+
+ penpos1 (.75 penh, 100);
+ z1 = z2 + (1/6 * vx - .15 * vy);
+ penpos2 (hround (.9 penw), 0);
+ x2l = hround xpart (pos + .75 vy);
+ y2l = ypart (pos + .75 vy);
+ penpos3 (penh, -100);
+ z3l = pos + .4 vx + vy;
+ penpos4 (penh, -90);
+ z4 = -.1 vy + .5 [z3, z5];
+ penpos5 (.8 penh, -30);
+ x5r = xpart (pos + siz);
+ y5l = ypart (pos + siz);
+
+ penpos10 (penw, 170);
+ z10 = pos + .55 vx + .9 vy;
+ penpos11 (.75 [penh, penw], 170);
+ z11 = z10 - .5 vy + .025 vx;
+ penpos12 (penh, 100);
+ z12l = (xpart .5 [z13, z11], ypart (pos - .025 * siz));
+ penpos13 (.75 penh, 60);
+ z13 = pos + .2 vx + .15 vy;
+
+ % penlabels (range 1 thru 13);
+
+ soft_penstroke (z1e
+ ..tension 1.1.. z2e
+ .. z3e{right}
+ ..tension 1.5.. z4e
+ ..z5e)
+ slanted slant shifted (slant * -ypart pos, 0);
+
+ soft_end_penstroke (z10e
+ ..tension 1.5.. z11e
+ .. z12e
+ ..tension 1.1.. z13e{(z13r - z13l) rotated 90})
+ slanted slant shifted (slant * -ypart pos, 0);
+endgroup;
+enddef;
+
+
+def draw_tab_A (expr pos, siz, slant) =
+begingroup;
+ save vx, vy, pat;
+ pair vx, vy;
+ path pat;
+
+ clearxy;
+
+ vx = (xpart siz) * dir 0;
+ vy = (ypart siz) * dir 90;
+
+ penpos1 (.75 penh, -110);
+ z1r = pos + .07 vy;
+ penpos2 (penh, -75);
+ z2r = (.5 [x1, x3], ypart pos);
+ penpos3 (.25 [penh, penw], -30);
+ z3 = (.45 [x2, x4], .15 [y2, y4]);
+ penpos4 (1 [penh, penw], 0);
+ z4 = pos + .5 vx + .975 vy;
+
+ penpos5 (1 [penh, penw], -180);
+ z5 = z4;
+ penpos6 (.2 [penh, penw], -150);
+ z6l = (.8 [x5l, x7l], .9 [y5l, y7l]);
+ penpos7 (penh,-90);
+ z7r = (.5 [x6, x8], ypart pos);
+ penpos8 (.75 penh, -70);
+ z8r = (xpart (pos + siz), y7r + .075 ypart (siz));
+
+ pat := z2
+ .. z3
+ .. z4;
+
+ penpos10 (penh, angle (direction 1.2 of pat) - 180);
+ z10 = point 1.2 of pat;
+ penpos11 (.9 penh, -90);
+ z11 = .4 [z10, z6] - 0.05 vy;
+ penpos12 (.75 penh, -75);
+ z12 = .3 [z11, z6] + 0.02 vy;
+
+ % penlabels (range 1 thru 12);
+
+ soft_penstroke (z1e{(z1r - z1l) rotated 90}
+ .. z2e
+ .. z3e
+ .. z4e)
+ slanted slant shifted (slant * -ypart pos, 0);
+
+ soft_end_penstroke (z5e
+ .. z6e
+ .. z7e
+ .. z8e{(z8r - z8l) rotated 90})
+ slanted slant shifted (slant * -ypart pos, 0);
+
+ soft_end_penstroke (z10e
+ .. z11e
+ .. z12e)
+ slanted slant shifted (slant * -ypart pos, 0);
+endgroup;
+enddef;
+
+
+def draw_tab_B (expr pos, siz, slant) =
+begingroup;
+ save vx, vy;
+ pair vx, vy;
+
+ clearxy;
+
+ vx = (xpart siz) * dir 0;
+ vy = (ypart siz) * dir 90;
+
+ penpos1 (.75 penh, 100);
+ z1 = z2 + (.15 * vx - .1 * vy);
+ penpos2 (hround (.9 penw), 0);
+ x2l = hround xpart (pos + .75 vy);
+ y2l = ypart (pos + .75 vy);
+ penpos3 (penh, -100);
+ z3l = pos + .4 vx + 1.05 vy;
+ penpos4 (.8 [penh, penw], -180);
+ z4 = (xpart (pos + .75 siz), .5 [y3, y5]);
+ penpos5 (.8 penh, 90);
+ z5 = (.5 [x10, x4], ypart (pos + .55 siz));
+
+ penpos6 (.8 penh, 270);
+ z6 = z5;
+ penpos7 (penw, 180);
+ z7l = (xpart (pos + siz), .5 [y6, y8]);
+ penpos8 (.8 penh, 45);
+ z8 = .5 [z12l, z11l] + .15 vx - .05 vy;
+
+ penpos10 (.75 [penh, penw], 170);
+ z10 = pos + .375 vx + vy;
+ penpos11 (.8 [penh, penw], 150);
+ z11 = z10 - .5 vy + .04 vx;
+ penpos12 (penh, 100);
+ z12l = (xpart .5 [z13, z11], ypart pos);
+ penpos13 (.75 penh, 60);
+ z13 = pos + .1 vx + .15 vy;
+
+ % penlabels (range 1 thru 13);
+
+ soft_penstroke (z1e
+ ..tension 1.1.. z2e
+ .. z3e
+ .. z4e
+ ..z5e {left})
+ slanted slant shifted (slant * -ypart pos, 0);
+
+ soft_end_penstroke (z6e{right}
+ .. z7e
+ .. z8e{(z8r - z8l) rotated 90})
+ slanted slant shifted (slant * -ypart pos, 0);
+
+ soft_end_penstroke (z10e
+ ..tension 1.5.. z11e
+ .. z12e
+ ..tension 1.1.. z13e{(z13r - z13l) rotated 90})
+ slanted slant shifted (slant * -ypart pos, 0);
+endgroup;
+enddef;
+
+
+def draw_tab_clef (expr reduction) =
+ save reduced_ss, letterheight, penw, penh;
+
+ reduced_ss# = staff_space# * reduction;
+ letterheight# = 1.8 reduced_ss#;
+ define_pixels (reduced_ss, letterheight);
+
+ set_char_box (-.2 reduced_ss#, 2.8 reduced_ss#,
+ 1.6 letterheight#, 1.6 letterheight#);
+
+ penw = .45 reduced_ss;
+ penh = .2 reduced_ss;
+
+ draw_tab_T ((-b + .15 reduced_ss, h - letterheight),
+ (2.1 reduced_ss, letterheight), 0.2);
+ draw_tab_A ((-b - .05 reduced_ss, -.5 letterheight +.15 reduced_ss),
+ (2.2 reduced_ss, letterheight), 0.4);
+ draw_tab_B ((-b + .025 reduced_ss, -d),
+ (2.1 reduced_ss, letterheight), 0.25);
+
+ draw_staff (-3, 2, 0.5);
+enddef;
+
+
+fet_beginchar ("tab clef", "tab");
+ draw_tab_clef (1.0);
+fet_endchar;
+
+
+fet_beginchar ("tab clef (reduced)", "tab_change");
+ draw_tab_clef (.8);
+fet_endchar;
+
+fet_endgroup ("clefs");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-macros.mf b/muse2/share/scoreglyphs/feta-original/feta-macros.mf
new file mode 100644
index 00000000..19cc379a
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-macros.mf
@@ -0,0 +1,497 @@
+%
+% feta-macros.mf -- auxiliary macros for both feta and parmesan fonts
+%
+% source file of the GNU LilyPond music typesetter
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+
+%
+% debugging
+%
+
+def print_penpos (suffix $) =
+ message
+ "z" & str$ & "l = (" & decimal x.$.l & ", " &decimal y.$.l & ");"
+ & " z" & str$ & "r = (" & decimal x.$.r & ", " & decimal y.$.r & ");";
+enddef;
+
+
+def test_grid =
+ if test > 1:
+ proofrulethickness 1pt#;
+
+ makegrid
+ (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor)
+ (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor);
+
+ proofrulethickness .1pt#;
+
+ makegrid
+ (0pt, 0pt for i := -4.8pt step .2pt until 4.8pt: , i endfor)
+ (0pt, 0pt for i := -4.8pt step .2pt until 4.8pt: , i endfor);
+ fi;
+enddef;
+
+
+def treq =
+ tracingequations := tracingonline := 1;
+enddef;
+
+
+def draw_staff (expr first, last, offset) =
+ if test <> 0:
+ pickup pencircle scaled stafflinethickness;
+
+ for i := first step 1 until last:
+ draw (-staff_space,
+ (i + offset) * staff_space_rounded)
+ -- (4 staff_space,
+ (i + offset) * staff_space_rounded);
+ endfor;
+ fi;
+enddef;
+
+
+%
+% Draw the outline of the stafflines. For fine tuning.
+%
+
+def draw_staff_outline (expr first, last, offset) =
+ if test <> 0:
+ save p;
+ path p;
+
+ pickup pencircle scaled 2;
+
+ for i := first step 1 until last:
+ p := (-staff_space,
+ (i + offset) * staff_space_rounded)
+ -- (4 staff_space,
+ (i + offset) * staff_space_rounded);
+
+ draw p shifted (0, .5 stafflinethickness);
+ draw p shifted (0, -.5 stafflinethickness);
+ endfor;
+ fi;
+enddef;
+
+
+%
+% Transformations
+%
+
+def scaledabout (expr point, scale) =
+ shifted -point scaled scale shifted point
+enddef;
+
+
+%
+% make a local (restored after endgroup) copy of t_var
+%
+
+def local_copy (text type, t_var) =
+ save copy_temp;
+ type copy_temp;
+ copy_temp := t_var;
+ save t_var;
+ type t_var;
+ t_var := copy_temp;
+enddef;
+
+
+%
+% Urgh! Want to do parametric types
+%
+
+def del_picture_stack =
+ save save_picture_stack, picture_stack_idx;
+enddef;
+
+
+%
+% better versions of Taupin/Egler savepic cmds
+%
+
+def make_picture_stack =
+ % override previous stack
+ del_picture_stack;
+ picture save_picture_stack[];
+ numeric picture_stack_idx;
+ picture_stack_idx := 0;
+
+ def push_picture (expr p) =
+ save_picture_stack[picture_stack_idx] := p;
+ picture_stack_idx := picture_stack_idx + 1;
+ enddef;
+
+ def pop_picture = save_picture_stack[decr picture_stack_idx] enddef;
+ def top_picture = save_picture_stack[picture_stack_idx] enddef;
+enddef;
+
+
+%
+% save/restore pens
+% why can't I delete individual pens?
+%
+
+def make_pen_stack =
+ del_pen_stack;
+ pen save_pen_stack[];
+ numeric pen_stack_idx;
+ pen_stack_idx := 0;
+ def push_pen (expr p) =
+ save_pen_stack[pen_stack_idx] := p;
+ pen_stack_idx := pen_stack_idx + 1;
+ enddef;
+ def pop_pen = save_pen_stack[decr pen_stack_idx] enddef;
+ def top_pen = save_pen_stack[pen_stack_idx] enddef;
+enddef;
+
+
+def del_pen_stack =
+ save save_pen_stack, pen_stack_idx;
+enddef;
+
+
+%
+% drawing
+%
+
+def soft_penstroke text t =
+ forsuffixes e = l, r:
+ path_.e := t;
+ endfor;
+
+ if cycle path_.l:
+ cyclestroke_;
+ else:
+ fill path_.l
+ ..tension1.5.. reverse path_.r
+ ..tension1.5.. cycle;
+ fi;
+enddef;
+
+
+def soft_start_penstroke text t =
+ forsuffixes e = l, r:
+ path_.e := t;
+ endfor;
+
+ if cycle path_.l:
+ cyclestroke_;
+ else:
+ fill path_.l
+ -- reverse path_.r
+ ..tension1.5.. cycle;
+ fi;
+enddef;
+
+
+def soft_end_penstroke text t =
+ forsuffixes e = l, r:
+ path_.e := t;
+ endfor;
+
+ if cycle path_.l:
+ cyclestroke_;
+ else:
+ fill path_.l
+ ..tension1.5.. reverse path_.r
+ -- cycle;
+ fi;
+enddef;
+
+
+%
+% Make a round path segment going from P to Q. 2*A is the angle that the
+% path should take.
+%
+
+def simple_serif (expr p, q, a) =
+ p{dir (angle (q - p) - a)}
+ .. q{-dir (angle (p - q) + a)}
+enddef;
+
+
+%
+% Draw an axis aligned block making sure that edges are on pixels.
+%
+
+def draw_rounded_block (expr bottom_left, top_right, roundness) =
+begingroup;
+ save size;
+ save x, y;
+
+ % Originally, there was `floor' instead of `round', but this is
+ % not correct because pens use `round' also.
+ size = round min (roundness,
+ xpart (top_right - bottom_left),
+ ypart (top_right - bottom_left));
+
+ z2 + (size / 2, size / 2) = top_right;
+ z4 - (size / 2, size / 2) = bottom_left;
+ y3 = y2;
+ y4 = y1;
+ x2 = x1;
+ x4 = x3;
+
+ pickup pencircle scaled size;
+
+ fill bot z1{right}
+ .. rt z1{up}
+ -- rt z2{up}
+ .. top z2{left}
+ -- top z3{left}
+ .. lft z3{down}
+ -- lft z4{down}
+ .. bot z4{right}
+ -- cycle;
+endgroup;
+enddef;
+
+
+def draw_block (expr bottom_left, top_right) =
+ draw_rounded_block (bottom_left, top_right, blot_diameter);
+enddef;
+
+
+def draw_square_block (expr bottom_left, top_right) =
+ save x, y;
+
+ x1 = xpart bottom_left;
+ y1 = ypart bottom_left;
+ x2 = xpart top_right;
+ y2 = ypart top_right;
+
+ fill (x1, y1)
+ -- (x2, y1)
+ -- (x2, y2)
+ -- (x1, y2)
+ -- cycle;
+enddef;
+
+
+def draw_gridline (expr bottom_left, top_right, thickness) =
+ draw_rounded_block (bottom_left - (thickness / 2, thickness / 2),
+ top_right + (thickness / 2, thickness / 2),
+ thickness);
+enddef;
+
+
+def draw_brush (expr a, w, b, v) =
+ save x, y;
+
+ z1 = a;
+ z2 = b;
+ z3 = z4 = z1;
+ z5 = z6 = z2;
+
+ penpos3 (w, angle (z2 - z1) + 90);
+ penpos4 (w, angle (z2 - z1));
+ penpos5 (v, angle (z1 - z2) + 90);
+ penpos6 (v, angle (z1 - z2));
+
+ fill z3r{z3r - z5l}
+ .. z4l
+ .. {z5r - z3l}z3l
+ .. z5r{z5r - z3l}
+ .. z6l
+ .. {z3r - z5l}z5l
+ .. cycle;
+enddef;
+
+
+%
+% Make a superellipsoid segment going from FROM to TO, with SUPERNESS.
+% Take superness = sqrt(2)/2 to get a circle segment.
+%
+% See Knuth, p. 267 and p.126.
+
+def super_curvelet (expr from, to, superness, dir) =
+ if dir = 1:
+ (superness [xpart to, xpart from],
+ superness [ypart from, ypart to]){to - from}
+ else:
+ (superness [xpart from, xpart to],
+ superness [ypart to, ypart from]){to - from}
+ fi
+enddef;
+
+
+%
+% Bulb with smooth inside curve.
+%
+% alpha = start direction
+% beta = which side to turn to
+% flare = diameter of the bulb
+% line = diameter of line attachment
+% direction = is ink on left or right side (1 or -1)
+%
+% Note that `currentpen' must be set correctly -- only circular pens
+% are supported properly.
+
+def flare_path (expr pos, alpha, beta, line, flare, direction) =
+begingroup;
+ save thick;
+
+ thick = pen_top + pen_bot;
+
+ clearxy;
+
+ penpos1' (line - thick, 180 + beta + alpha);
+ top z1'r = pos;
+
+ penpos2' (flare - thick, 180 + beta + alpha);
+ z2' = z3';
+
+ penpos3' (flare - thick, 0 + alpha);
+ rt x3'l = hround (x1'r
+ + (1/2 + 0.43) * flare * xpart dir (alpha + beta));
+ bot y2'l = vround (y1'r
+ + (1 + 0.43) * flare * ypart dir (alpha + beta));
+
+ rt x4' = x2'r - line * xpart dir (alpha);
+ y4' = y2'r - line * ypart dir (alpha);
+
+ penlabels (1', 2', 3', 4');
+
+ save t, p;
+ t = 0.833;
+ path p;
+
+ p := z1'r{dir (alpha)}
+ .. z3'r{dir (180 + alpha - beta)}
+ .. z2'l{dir (alpha + 180)}
+ .. z3'l{dir (180 + alpha + beta)}
+ ..tension t.. z4'{dir (180 + alpha + beta)}
+ .. z1'l{dir (alpha + 180)};
+
+ if direction <> 1:
+ p := reverse p;
+ fi;
+
+p
+endgroup
+enddef;
+
+
+def brush (expr a, w, b, v) =
+begingroup;
+ draw_brush (a, w, b, v);
+ penlabels (3, 4, 5, 6);
+endgroup;
+enddef;
+
+
+%
+% Draw a (rest) crook, starting at thickness STEM in point A,
+% ending a ball W to the left, diameter BALLDIAM.
+% ypart of the center of the ball is BALLDIAM/4 lower than ypart A.
+%
+
+def balled_crook (expr a, w, balldiam, stem) =
+begingroup;
+ save x, y;
+
+ penpos1 (balldiam / 2, -90);
+ penpos2 (balldiam / 2, 0);
+ penpos3 (balldiam / 2, 90);
+ penpos4 (balldiam / 2, 180);
+
+ x4r = xpart a - w;
+ y3r = ypart a + balldiam / 4;
+ x1l = x2l = x3l = x4l;
+ y1l = y2l = y3l = y4l;
+
+ penpos5 (stem, 250);
+ x5 = x4r + 9/8 balldiam;
+ y5r = y1r;
+
+ penpos6 (stem, 260);
+ x6l = xpart a;
+ y6l = ypart a;
+
+ penstroke z1e
+ .. z2e
+ .. z3e
+ .. z4e
+ .. z1e
+ .. z5e{right}
+ .. z6e;
+
+ penlabels (1, 2, 3, 4, 5, 6);
+endgroup;
+enddef;
+
+
+def y_mirror_char =
+ currentpicture := currentpicture yscaled -1;
+
+ set_char_box (charbp, charwd, charht, chardp);
+enddef;
+
+
+def xy_mirror_char =
+ currentpicture := currentpicture scaled -1;
+
+ set_char_box (charwd, charbp, charht, chardp);
+enddef;
+
+
+%
+% center_factor: typically .5; the larger, the larger the radius of the bulb
+% radius factor: how much the bulb curves inward
+%
+
+def draw_bulb (expr turndir, zl, zr, bulb_rad, radius_factor)=
+begingroup;
+ save rad, ang, pat;
+ path pat;
+
+ clearxy;
+
+ ang = angle (zr - zl);
+
+ % don't get near infinity
+ % z0 = zr + bulb_rad * (zl - zr) / length (zr - zl);
+ z0' = zr + bulb_rad / length (zr - zl) * (zl - zr);
+
+ rad = bulb_rad;
+
+ z1' = z0' + radius_factor * rad * dir (ang + turndir * 100);
+ z2' = z0' + rad * dir (ang + turndir * 300);
+
+ labels (0', 1', 2');
+
+ pat = zr{dir (ang + turndir * 90)}
+ .. z1'
+ .. z2'
+ .. cycle;
+
+ % avoid grazing outlines
+ fill subpath (0, 2.5) of pat
+ -- cycle;
+endgroup
+enddef;
+
+
+pi := 3.14159;
+
+
+%
+% To get symmetry at low resolutions we need to shift some points and
+% paths, but not if mf2pt1 is used.
+%
+
+if known miterlimit:
+ vardef hfloor primary x = x enddef;
+ vardef vfloor primary y = y enddef;
+ vardef hceiling primary x = x enddef;
+ vardef vceiling primary y = y enddef;
+else:
+ vardef hfloor primary x = floor x enddef;
+ vardef vfloor primary y = (floor y.o_)_o_ enddef;
+ vardef hceiling primary x = ceiling x enddef;
+ vardef vceiling primary y = (ceiling y.o_)_o_ enddef;
+fi;
diff --git a/muse2/share/scoreglyphs/feta-original/feta-nummer-code.mf b/muse2/share/scoreglyphs/feta-original/feta-nummer-code.mf
new file mode 100644
index 00000000..ab8fe9f0
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-nummer-code.mf
@@ -0,0 +1,899 @@
+% feta-nummer-code.mf -- implement bold Orator numerals
+%
+% part of LilyPond's pretty-but-neat music font
+%
+% source file of the Feta (not the Font-En-Tja) music font
+%
+% (c) 1997--2009 Jan Nieuwenhuizen <janneke@gnu.org>
+
+
+height# := number_design_size;
+space# := number_design_size / 2;
+
+font_x_height height#;
+font_normal_space space#;
+
+
+%
+% DOCME!
+%
+% ugh. b and h are reused.
+%
+
+save b, h;
+4 h + b = 1.15;
+10 h + b = 1;
+fatten := number_design_size * h + b;
+
+save b, h;
+4 h + b = 1.05;
+10 h + b = 1;
+widen := number_design_size * h + b;
+
+tense = 0.85;
+thick# := 7/30 height# * fatten;
+thin# := thick# / 4 * fatten + max (.1 (height# / 10 - 1), 0);
+
+%% sqrt (.8 * blot_diameter# * thin#);
+hair# := thin# * .8;
+
+flare# := 9/8 thick# + .75 (height# / 10 - 1);
+
+save b, h;
+4h + b = 1/8;
+10h + b = 1/6;
+kuulleke# := thick# * number_design_size * h + b;
+foot_top# := thick#;
+foot_width# := 9/4 thick#;
+
+
+%
+% These numbers were taken from a part that that the EJE violas played
+% 1997 -- Probably Mendelssohn's ouverture `Heimkehr aus der Fremde'.
+%
+
+
+%
+% TODO all the invocation of flare_path are weird --
+% the horizontal tangents should be more at the center of the
+% glyph.
+%
+
+define_pixels (height, thick, thick, thin, hair, flare);
+define_pixels (foot_top, foot_width);
+define_pixels (kuulleke);
+
+
+%
+% Yet Another Bulb Routine with smooth inside curve.
+%
+% alpha = start direction.
+% beta = which side to turn to
+% flare = diameter of the bulb
+% line = diameter of line attachment
+% direction = is ink on left or right side (1 or -1)
+%
+%
+% move_away_to = amount left (for 2)
+% turn_to = amount down (for 2)
+%
+
+def number_flare_path (expr pos, alpha, beta, line, flare,
+ move_away_to, turn_to, taille, taille_ratio,
+ direction) =
+begingroup;
+ save res;
+ path res;
+
+ clearxy;
+
+% z5 = z2 + 0.43 * flare * dir (alpha - 1.5 beta);
+
+ z4 = (0.75 - taille) [z2r, z2l] + whatever * dir (alpha - beta);
+ z4 = (taille_ratio * taille) [z3l, z3r] + whatever * dir (alpha);
+
+ z1r = pos;
+ z2r = z1r + move_away_to * dir (alpha)
+ + (line + turn_to) * dir (alpha + beta);
+ z3r = 0.5 [z2l, z2r] + 0.5 * flare * dir (alpha + beta);
+
+ penpos1 (line, 180 + beta + alpha);
+ penpos2 (flare, alpha);
+ penpos3 (flare, alpha + beta);
+
+ penlabels (1, 2, 3, 4, 5);
+
+ res := z1r{dir (alpha)}
+ .. z2r{dir (180 + alpha - beta)}
+ .. z3r{dir (alpha + 180)}
+ .. z2l{dir (alpha - beta)}
+
+%%% Two versions of the curve: one with z4, the other with z5.
+% .. z5{dir (alpha - beta / 2)}
+
+ .. z4{dir (180 + alpha + beta)}
+ .. z1l{dir (alpha + 180)};
+
+% pickup pencircle;
+% draw res;
+
+ if direction <> 1:
+ res := reverse res;
+ fi;
+
+res
+endgroup
+enddef;
+
+
+def calc_kuulleke (expr w, alpha) =
+begingroup;
+ save beta, gamma;
+
+ beta = (alpha - 90) / 2;
+ gamma = (90 + alpha) / 2;
+
+ penpos1 (w / cosd (alpha), alpha);
+ penpos2 (hair, 90 + beta);
+ penpos3 (hair, gamma - 90);
+
+ z2 = z1l + (1/2 hair / tand ((alpha + 90) / 2)) * dir (beta);
+ z3 = z1r - (1/2 hair / tand ((90 - alpha) / 2)) * dir (gamma);
+ z4 = z1 + kuulleke * dir (alpha - 90);
+endgroup;
+enddef;
+
+
+% should make generic macro?
+%
+def draw_foot (expr xpos) =
+begingroup;
+ clearxy;
+
+ penpos1 (thick, 0);
+ penpos2 (foot_width, 0);
+ penpos3 (hair, -90);
+ penpos4 (hair, 90);
+
+ z1= (xpos, foot_top);
+ z2= (x1, 0);
+ z3r = z2r;
+ z4l = z2l;
+ z5 = (x1, kuulleke);
+
+ penlabels (1, 2, 3, 4);
+
+ fill z1
+ .. {right}z1r{down}
+ .. {right}z3l
+ .. z3r{left}
+ .. z5
+ .. {left}z4l
+ .. z4r{right}
+ .. {up}z1l{right}
+ .. z1
+ .. cycle;
+endgroup;
+enddef;
+
+
+def draw_six =
+ save outer_t, t;
+ save before, after, u, v;
+ path before, after;
+
+ set_char_box (0, .68 height# * widen, 0, height#);
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ penpos2 (hair, 90);
+ z2 = (w / 2, h / 2 + thin - hair / 2);
+
+ penpos3 (15/16 thick, 0);
+ x3r = w;
+ y3r = .5 [y4r, y2r];
+
+ penpos4 (hair, -90);
+ z4r = (x2, 0);
+
+ penpos6 (hair, 90);
+ x6r = .56 w;
+ y6r = h;
+
+ penpos7 (thick, 180);
+ x7r = 0;
+ y7r = .50 h;
+
+ penpos10 (thick, 180);
+ z10r = (0, y3);
+
+ penlabels (range 1 thru 10);
+
+ outer_t = 0.88;
+ t := tense;
+
+ before := z7{right}
+ .. z2r{right};
+ after := z7r{up}
+ .. number_flare_path (z6r, 0, -90, hair, flare,
+ w - x6r - hair / 2, .16 h,
+ 0.05, 2.5, 1)
+ .. z7l{down};
+ (u, v) = before intersectiontimes after;
+
+% draw
+ fill subpath (u, infinity) of before
+ ..tension outer_t.. z3r{down}
+ ..tension outer_t.. z4r{left}
+ .. subpath (0, v) of after
+ .. cycle;
+
+ unfill z2l{right}
+ ..tension t.. z3l{down}
+ ..tension t.. z4l{left}
+ ..tension t.. z10l{up}
+ ..tension t.. cycle;
+enddef;
+
+
+save dot_diam;
+dot_diam# = 7/8 flare#;
+define_pixels (dot_diam);
+
+
+code := 42; % , 43
+
+fet_beginchar ("Plus", "plus");
+ set_char_box (0, .5 height#, -0.25 height#, 0.75 height#);
+
+ save hthick, vthick, size, outer_hsize, outer_vsize;
+
+ hthick# = vthick# = 2 linethickness#;
+ size# = 1.1 staff_space#;
+ define_whole_blacker_pixels (vthick);
+ define_whole_vertical_blacker_pixels (hthick);
+
+ outer_hsize = hround ((b + w - vthick) / 2);
+ outer_vsize = vround ((h + d - hthick) / 2);
+
+ centerx := hround (w / 2);
+ centery := vround ((h - d) / 2);
+
+ z1 = (centerx - hthick / 2, -d);
+ z2 = (centerx + hthick / 2, h);
+
+ labels (1, 2);
+
+ draw_rounded_block (z1, z2, hthick);
+ draw_rounded_block ((0, centery - vthick / 2),
+ (w, (centery + vthick / 2)),
+ vthick);
+fet_endchar;
+
+
+code := 43; % , = 44
+
+fet_beginchar ("Numeral comma", "comma");
+ save pat, pos;
+ path pat;
+
+ set_char_box (0, dot_diam#, 3/2 dot_diam#, dot_diam#);
+
+ pat := (dot_diam / 2, 0)
+ .. (dot_diam, dot_diam / 2)
+ .. (dot_diam / 2, dot_diam)
+ .. (0, dot_diam / 2)
+ .. cycle;
+
+ pos = ypart (((w / 3, 0) -- (w / 3, dot_diam / 2))
+ intersectiontimes pat);
+ z0 = point pos of pat;
+
+ alpha = 65;
+ penpos1 (thin, alpha + 90);
+
+ z1l = (w / 2, -1.5 h + hair);
+ z2 = (w, h / 2);
+
+ pickup feta_fillpen;
+
+ % include z0 to assist removal of overlaps
+ fill subpath (0,3) of pat
+ .. z0
+ .. cycle;
+ filldraw z1l{dir (alpha)}
+ .. {up}z2
+ -- z0{direction pos of pat}
+ ..tension 0.95.. {dir (180 + alpha)}z1r
+ .. cycle;
+
+ labels (0, 2);
+ penlabels (1);
+fet_endchar;
+
+
+fet_beginchar ("Numeral dash", "hyphen");
+ set_char_box (0, height# / 3, 0, height#);
+
+ draw_rounded_block ((-b, h / 3 - thin / 2),
+ (w, h / 3 + thin / 2), thin);
+fet_endchar;
+
+
+fet_beginchar ("Numeral dot", "period");
+ set_char_box (0, dot_diam#, 0, dot_diam#);
+
+ pickup pencircle scaled dot_diam;
+
+ drawdot (dot_diam / 2, dot_diam / 2);
+fet_endchar;
+
+
+% skip slash
+
+code := 47; % 0 = 48
+
+fet_beginchar ("Numeral 0", "zero");
+ set_char_box (0, 11/15 height# * widen, 0, height#);
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ penpos1 (thin, 90);
+ penpos2 (thick, 180);
+ penpos3 (thin,- 90);
+ penpos4 (thick, 0);
+
+ z1r = (w / 2, h);
+ z2r = (0, h / 2);
+ z3r = (w / 2, 0);
+ z4r = (w, h / 2);
+
+ fill z1r
+ .. z2r
+ .. z3r
+ .. z4r
+ .. cycle;
+
+ save t;
+ t = 1 / tense;
+
+ penlabels (1, 2, 3, 4);
+
+ unfill z1l
+ ..tension t.. z2l
+ ..tension t.. z3l
+ ..tension t.. z4l
+ ..tension t.. cycle;
+fet_endchar;
+
+
+fet_beginchar ("Numeral 1", "one");
+ save alpha, beta, gamma;
+
+% set_char_box (0, 19/30 height# * widen, 0, height#);
+ set_char_box (0, 1/2 foot_width# + 3/2 thick# + 1/2 hair#,
+ 0, height#);
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ alpha = 0;
+ calc_kuulleke (thick, alpha);
+ z1 = (3/2 thick, height);
+
+ penpos5 (thick, 0);
+ z5 = (x1, foot_top);
+
+ z6 = (0, h / 2);
+ beta = angle (z1l - z6);
+
+ penpos7 (thin, beta - 90);
+ z7l = z6;
+
+ penpos8 (thin / cosd (beta), -90);
+ z8l = z1l;
+
+ penpos9 (thin, beta - 90);
+ z9r = z8r + (thin / cosd (beta)) * down;
+
+ penlabels (range 1 thru 9);
+
+ gamma = angle (length (z1r - z1), 2 kuulleke);
+
+ fill z2r{dir (alpha - gamma)}
+ .. z4
+ .. {dir (alpha + gamma)}z3l
+ .. z3r{down}
+ -- z5r
+ -- z5l
+ -- z2l{up}
+ .. cycle;
+
+ fill z7l
+ -- z1l{dir (beta)}
+ .. {dir (alpha - gamma)}z2r
+ -- z9r{up}
+ .. {dir (180 + beta)}z9l
+ -- z7r{dir (180 + beta)}
+ .. {dir (beta)}cycle;
+
+ draw_foot (x1);
+fet_endchar;
+
+
+fet_beginchar ("Numeral 2", "two");
+ save tolerance;
+ save alpha, beta, gamma, theta;
+ save flare_start_distance;
+ save t, pat, bow;
+ path pat, bow;
+
+ set_char_box (0, 22/30 height# * widen, 0, height#);
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ alpha = -45 * widen;
+ beta = 85;
+ gamma = beta - 10;
+ theta = 20 / widen;
+
+ flare_start = 0.25;
+
+ penpos1 (hair, 90 + beta);
+ z1 = (0, 0) + (1/2 sqrt (2) * hair) * dir (45);
+
+ penpos3 (hair,90 + gamma);
+ z3 = (w, thick) + (1/2 sqrt (2) * hair) * dir (-135);
+
+ penpos2 (thick, 90 + alpha - 15);
+ x2 - x1 = x3 - x2;
+ y2 = 10/16 thick / widen;
+
+ tolerance := epsilon;
+
+ % Find proper tension to exactly touch the x axis.
+ % Later on we directly use `bow'.
+ vardef f (expr t) =
+ bow := z3l{dir (180 + gamma)}
+ ..tension t.. {dir (180 + alpha -5)}z2l;
+ ypart (directionpoint left of bow) < 0
+ enddef;
+
+ % the return value of `solve' is stored in a dummy variable
+ t = solve f (0.8, 1.2);
+
+ fill z1r{dir (beta)}
+ ..tension 0.9.. {dir (alpha + 10)}z2r
+ .. {dir (gamma)}z3r
+ .. bow
+ .. {dir (180 + beta)}z1l
+ .. cycle;
+
+ penpos4 (thick, 0);
+ z4r = (w - thin / 2, .71 h);
+
+ penpos5 (hair, 90);
+ y5r = h;
+ x5r = 9/20 w;
+
+ penlabels (range 1 thru 6);
+
+ t := tense;
+
+ pat := z1l{dir (beta)}
+ ..tension t.. z4r{up}
+ .. number_flare_path (z5r, 180, 90, hair, 1.05 flare,
+ x5r - 1/2 hair, .21 h, 0.006, 0.4, 1)
+ .. z4l{down}
+ ..tension t.. {dir (180 + beta)}z1r
+ -- cycle;
+
+% pickup pencircle scaled 1;
+% draw pat;
+
+ fill pat;
+fet_endchar;
+
+
+%%
+% TODO: should widen a bit. The right edge of the 3 bumps into next glyph in
+% combinations
+%
+fet_beginchar ("Numeral 3", "three");
+ set_char_box (0, 2/3 height# * widen, 0, height#);
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ penpos1 (hair, -90);
+
+% flare_start = 0.25;
+
+ x1l = 36/80 w;
+ y1l = h;
+
+% z1l = (17/16 thick, h);
+
+ penpos2 (7/8 thick, 180);
+ x2l = w - thick / 8;
+ y2l = 3/4 h + thick * 3/32;
+
+ penpos3 (thin, 90);
+ z3 = (w / 2, h / 2 + 1/8 thick);
+
+ penpos4 (thin, 90);
+ z4 = (5/8 thick + 1/2 thin, y3);
+
+ penpos5 (thick, 0);
+ x5r = w;
+ y5r = 17/64 h + thick / 16;
+
+ penpos6 (hair, -90);
+ x6r = 37/80 w;
+ y6r = 0;
+
+ penpos7 (3/2 thin, 90);
+ x7 = .83 w;
+ y7 = y3;
+
+ penlabels (range 1 thru 7);
+
+ save alpha, t, outer_t;
+ alpha = 25;
+ t = tense;
+ outer_t := 0.93;
+
+% pickup pencircle scaled 1;
+% draw
+ fill number_flare_path (z1l, 180, 90, hair, 7/8 flare, x1l - .5 hair,
+ .16 h, 0.06, 1.5, -1)
+ ..tension outer_t.. z2l{down}
+ ..tension outer_t.. z7r{dir (180 + alpha)}
+ .. z7l{dir (-alpha)}
+ ..tension outer_t.. z5r{down}
+ ..tension outer_t.. number_flare_path (z6r, 180, -90, hair,
+ flare, x6l, .18 h, 0.06,
+ 1.5, 1)
+ .. z5l{up}
+ ..tension t.. z3l{left}
+ .. z4l{left}
+ .. z4r{right}
+ .. z3r{right}
+ ..tension t.. z2r{up}
+ ..tension t.. cycle;
+fet_endchar;
+
+
+fet_beginchar ("Numeral 4", "four");
+ save alpha, beta, gamma;
+
+ set_char_box (0, 4/5 height# * widen, 0, height#);
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ alpha = 0;
+ calc_kuulleke (3/2 thick, alpha);
+
+ z1r = (w - 3/4 thick, height);
+ z5 = (thin, 1/4 height + thin);
+
+ beta = angle (z3r - z5);
+
+ penpos6 (thin, -90);
+ z6l = z5;
+
+ penpos7 (thin, -90);
+ y7 = y6;
+ x7 = w - 1/2 thin;
+
+ penpos8 (thin, -alpha);
+ z8r = z5;
+
+ penlabels (range 1 thru 8);
+
+ gamma = angle (length (z1r - z1), 2 kuulleke);
+
+ fill z2r{dir (alpha - gamma)}
+ .. z4
+ .. {dir (alpha + gamma)}z3l
+ .. {dir (180 + beta)}z3r
+ -- z8r
+ -- z7l{right}
+ .. {left}z7r
+ -- z6r{left}
+ ..tension 0.8 and 2.. z8l{dir (beta)}
+ .. {up}z2l
+ .. cycle;
+
+ clearxy;
+
+ alpha := beta;
+ calc_kuulleke (thick, alpha);
+
+ z1r = (w - 3/4 thick, height - (3/2 thin) / cosd (alpha));
+
+ penpos5 (thick, 0);
+ z5 = (x1, foot_top);
+
+ gamma := angle (length (z1r - z1), 2 kuulleke);
+
+ fill z2r{dir (alpha - gamma)}
+ .. z4
+ .. {dir (alpha + gamma)}z3l
+ .. {down}z3r
+ -- z5r
+ -- z5l
+ -- z2l{up}
+ .. cycle;
+
+ penlabels (1, 2, 3, 4, 5);
+
+ draw_foot (x5);
+fet_endchar;
+
+
+fet_beginchar ("Numeral 5", "five");
+ save alpha, beta, gamma, delta;
+ save inner_t, outer_t;
+ save pat;
+ path pat;
+
+ set_char_box (0, 27/40 height# * widen, 0, height#);
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ alpha = 0;
+ calc_kuulleke (w - thin, alpha);
+
+ z1 = (w / 2 + 1/8 thick, h);
+
+ penpos5 (thin, 0);
+ z5l = (x1l, h - 15/16 thick);
+
+ penpos6 (hair, 90 - 45);
+ z6 = z5r + 1/2 hair * dir (-45);
+
+ penpos7 (thin, 0);
+ z7l = (x1l, h / 2 + thin - hair);
+
+ penlabels (range 1 thru 7);
+
+ gamma = angle (length (z1r - z1), 2 kuulleke);
+
+ pat := z2r{dir (alpha - gamma)}
+ .. z4
+ .. {dir (alpha + gamma)}z3l
+ .. z3r{dir (-135)}
+ .. {left}z6r
+ .. {down}z6l
+ -- z7r{down}
+ .. {up}z7l
+ -- z2l{up}
+ .. cycle;
+
+ beta = 45;
+ delta = 180 + beta + 10;
+ z8r = (x7r, y7r - 1/16 thick + thin);
+ z8l = directionpoint dir (delta) of
+ subpath (6, 7) of pat;
+
+ % include intersection point to improve overlap removal
+ fill subpath (0, 6) of pat
+ .. z8l
+ .. subpath (7, length (pat)) of pat
+ .. cycle;
+
+ penpos9 (thin, 90);
+ y9 = 10/16 [y5, y7];
+ x9 = .36 [x8r, x10r];
+
+ penpos10 (thick, 0);
+ x10r = w + hair / 2;
+ y10r = 1/2 [y9r, y11r];
+
+ penpos11 (hair, -90);
+ y11r = 0;
+ x11r = .7 [0, x10l];
+
+ penlabels (range 8 thru 12);
+
+ inner_t = 1.0;
+ outer_t = .85;
+
+ fill z8r {dir (beta)}
+ .. z9r{right}
+ ..tension outer_t.. z10r{down}
+ .. number_flare_path (z11r, 180, -90, hair, flare, x11l,
+ .18 h, 0.06, 1.5, 1)
+ .. z11l{right}
+ ..tension inner_t.. z10l{up}
+ ..tension inner_t.. z9l{left}
+ .. z8l{dir (delta)}
+ -- cycle;
+fet_endchar;
+
+
+fet_beginchar ("Numeral 6", "six");
+ draw_six;
+fet_endchar;
+
+
+fet_beginchar ("Numeral 7", "seven");
+ save tolerance;
+ save alpha, beta, gamma, delta;
+ save bow;
+ save x_overshoot;
+
+ path bow;
+
+ set_char_box (0, 11/15 height# * widen - thin#, 0, height#);
+ overshoot_x = .75 thin;
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ alpha = -180;
+
+ penpos1 (3/2 thick, 180 + alpha);
+ penpos2 (hair, 180 + alpha - 45);
+ penpos3 (hair, 180 + alpha + 45);
+
+ z2 = z1l + (1/4 sqrt (2) * hair) * dir (alpha - 135);
+ z3 = z1r + (1/4 sqrt (2) * hair) * dir (alpha - 45);
+ z4 = z1 + kuulleke * dir (alpha - 90);
+
+ z1l = (thin, 0);
+
+ beta = 55;
+ penpos5 (thin, 90 + beta);
+ z5 = (w, h) + (1/2 sqrt (2) * thin) * dir (-135) + (overshoot_x, 0);
+
+ gamma = angle (length (z1r - z1), 2 kuulleke);
+ delta = 12;
+
+ pickup pencircle;
+
+ fill z3l{dir (alpha - gamma)}
+ .. z4
+ .. {dir (alpha + gamma)}z2r
+ .. z2l{dir (beta + delta)}
+ .. {dir (beta)}z5r
+ .. z5l{dir (180 + beta)}
+ .. {dir (delta - 90)}z3r
+ .. cycle;
+
+ penlabels (1, 2, 3, 4, 5);
+
+ alpha := -45 * widen;
+
+ penpos11 (1/2 thick, 90);
+ z11 = (3/2 thin, h - (thick + thin) / 2);
+
+ penpos13 (thin, 90 + beta);
+ z13 = z5;
+
+ penpos12 (thick, 90 + alpha);
+ x12 = 1/2 [x11, x13] - 1/4 thick;
+ y12 = h - 15/16 thick + thin * widen;
+
+ penpos14 (thin, 0);
+ z14l = (0, h - thin / 2);
+
+ penpos15 (thin, 0);
+ z15l = (0, h / 2 + thin / 2);
+
+ penpos16 (9/8 thick, 90);
+ z16r = (thin, y11r + 2/16 thick);
+
+ tolerance := epsilon;
+
+ % Find proper tension to exactly touch the x axis.
+ % Later on we directly use `bow'.
+ vardef f (expr t) =
+ bow := z11r{dir (beta)}
+ ..tension t.. {dir (alpha)}z12r;
+ ypart (directionpoint right of bow) > h
+ enddef;
+
+ % the return value of `solve' is stored in a dummy variable
+ t = solve f (0.8, 1.2);
+
+ fill bow
+ .. {dir (beta)}z13r
+ -- z13l{dir (180 + beta)}
+ .. {dir (180 + alpha)}z12l
+ .. {dir (180 + beta)}z11l
+ .. {down}z16l
+ -- z15r{down}
+ .. {up}z15l
+ -- z14l{up}
+ .. {down}z14r
+ -- z16r{down}
+ ..tension 1.5.. {dir (beta)}cycle;
+
+ penlabels (range 11 thru 16);
+fet_endchar;
+
+
+fet_beginchar ("Numeral 8", "eight");
+ save alpha, beta;
+
+ set_char_box (0, 11/15 height# * widen, 0, height#);
+
+ message "w:" & decimal w;
+ message "h:" & decimal h;
+
+ alpha = 60;
+ beta = alpha - 15;
+
+ z1 = (w / 2, h / 2 + thick / 8);
+
+ penpos2 (14/8 thin, 0);
+ z2 = (w / 3, h / 2 + thin);
+
+ penpos3 (3/2 thin, 0);
+ z3l = (0, h / 4 + thin / 2);
+
+ penpos4 (hair, 90);
+ z4l = (x1, 0);
+
+ penpos5 (thick, 90 + 90 + alpha);
+ z5 = z1 + w / 4 * dir (alpha - 90);
+
+ penpos6 (thick, 90 + 90 + alpha);
+ z6 = z1 + (w / 4 - thin / 2) * dir (90 + alpha);
+
+ penpos7 (hair, 90);
+ z7r = (x1 + .02 w, h);
+
+ penpos8 (3/2 thin, 0);
+ z8r = (w - thin / 2, 3/4 h + thin / 2);
+
+ penpos9 (13/8 thin, 0);
+ z9 = (2/3 w, h / 2);
+
+ penlabels (range 1 thru 9);
+
+ save t;
+ t = tense;
+
+ fill z2r{dir (180 + beta)}
+ .. z3r{down}
+ .. z4r{right}
+ .. z5r{dir (90 + alpha)}
+ -- z6r{dir (90 + alpha)}
+ ..tension t.. z7r{right}
+ .. z8r{down}
+ .. {dir (180 + beta)}z9r
+ -- z9l{dir (beta)}
+ .. z8l{up}
+ .. z7l{left}
+ .. {dir (alpha - 90)}z6l
+ -- z5l{dir (alpha - 90)}
+ ..tension t.. z4l{left}
+ .. z3l{up}
+ .. {dir (beta)}z2l
+ -- cycle;
+fet_endchar;
+
+
+fet_beginchar ("Numeral 9", "nine");
+ draw_six;
+% xy_mirror_char;
+
+ currentpicture := currentpicture scaled -1;
+ currentpicture := currentpicture shifted (w, h);
+fet_endchar;
+
+
+ligtable "3":
+ "3" kern 0.1 space#,
+ "0" kern 0.1 space#;
+
+ligtable "2":
+ "7" kern 0.15 space#;
diff --git a/muse2/share/scoreglyphs/feta-original/feta-params.mf b/muse2/share/scoreglyphs/feta-original/feta-params.mf
new file mode 100644
index 00000000..96d98628
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-params.mf
@@ -0,0 +1,213 @@
+%
+% feta-params.mf -- global parameters for both feta and parmesan fonts
+%
+% source file of the GNU LilyPond music typesetter
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+stafflines := 5;
+
+%
+% The design size of a staff should really be the
+% staff_space, but we use staffsize for historical reasons.
+%
+
+staff_space# := staffsize# / (stafflines - 1);
+staff_space_rounded# := staff_space#;
+
+
+%
+% Measuring on pocket scores turns out: stafflinethickness is
+% largely independent on staff size, and generally about 0.5 pt.
+%
+% By request of WL, we tune down the blackness a little
+% for increased contrast with beams.
+%
+
+%% !! synchronize with paper.scm
+
+save fixed_line_thickness, variable_line_factor;
+fixed_line_thickness + variable_line_factor * 5 pt# = 0.50 pt#;
+fixed_line_thickness + variable_line_factor * 4.125 pt# = 0.47 pt#;
+
+stafflinethickness# := fixed_line_thickness
+ + variable_line_factor * staff_space#;
+stafflinethickness_rounded# := stafflinethickness#;
+
+%
+% The following tunes the general blackness of the glyphs.
+%
+
+linethickness# := stafflinethickness#; %% 0.5 pt#;
+linethickness_rounded# := linethickness#;
+
+%
+% bigger puff_up_factor, relatively thicker stafflines.
+%
+% 20 pt = puff_up_factor 0
+% 10 pt = puff_up_factor 1
+%
+
+puff_up_factor = (linethickness# - 0.1 staff_space#) / (0.1 staff_space#);
+
+
+stemthickness# := 1.3 stafflinethickness#;
+stemthickness_rounded# := stemthickness#;
+ledgerlinethickness# := 2 stafflinethickness#;
+ledgerlinethickness_rounded# := ledgerlinethickness#;
+
+define_pixels (staff_space, stemthickness, stafflinethickness,
+ ledgerlinethickness, linethickness);
+define_whole_pixels (staff_space_rounded);
+define_whole_blacker_pixels (stemthickness_rounded);
+define_whole_vertical_blacker_pixels (stafflinethickness_rounded,
+ ledgerlinethickness_rounded,
+ linethickness_rounded);
+
+if ledgerlinethickness_rounded > 2 stafflinethickness_rounded:
+ ledgerlinethickness_rounded := 2 stafflinethickness_rounded;
+fi;
+
+%
+% Because of the engraving/stamping process, no traditional
+% characters have sharp edges and corners.
+% The following variable controls the amount of `roundness'.
+%
+% This is not a meta variable: it is related to absolute sizes.
+%
+% FIXME: According to [Wanske], only outside corners should be round
+% I don't think we do this anywhere -- jcn
+%
+
+blot_diameter# = .40 pt#;
+if (blot_diameter# * hppp) < 1:
+ blot_diameter# := 1 / hppp;
+fi
+if (blot_diameter# * vppp) < 1:
+ blot_diameter# := 1 / vppp;
+fi
+
+define_pixels (blot_diameter);
+
+
+%
+% symmetry
+% --------
+%
+% Some glyphs have to be positioned exactly between stafflines (clefs,
+% note heads). This needs some care at lower resolutions.
+%
+% Most glyphs use the staffline thickness and the space between two
+% staff lines as the fundamental parameters. The latter is the distance
+% between the middle of one staff line to the middle of the next. To
+% say it differently, the value `staff_space' is the sum of one staff line
+% thickness and the whitespace between two adjacent staff lines.
+%
+% Normally, feta's vertical origin for glyphs is either the middle
+% between two staff lines or the middle of a staff line. For example, the
+% lower edge of the central staff line is at the vertical position
+% `-<staffline thickness> / 2', and the upper edge at
+% `<staffline thickness> / 2'. Here we need a value rounded to an integer
+% (the feta code uses `stafflinethickness_rounded' for that purpose).
+%
+% If we have an odd number of pixels as the staffline thickness, Metafont
+% rounds `-stafflinethickness_rounded / 2' towards zero and
+% `stafflinethickness_rounded / 2' towards infinity. Example: `round -1.5'
+% yields -1, `round 1.5' yields 2. The whitespace between staff lines is
+% handled similarly. If we assume that stafflinethickness_rounded is odd,
+% we have the following cases:
+%
+% o The glyph is centered between three stafflines or five stafflines
+% (clef, `c' meter). We have this:
+%
+% ___________ a
+% ___________ 1
+% ___________ a
+%
+% whitespace
+%
+% ___________ a
+% ...... ___________ 1 .................. x axis
+% ___________ a
+%
+% whitespace
+%
+% ___________ a
+% ___________ 1
+% ___________ a
+%
+% As can be seen, we get symmetry if we split staff lines into two
+% equal parts `a' and a pixel line with thickness 1. Consequently, we
+% use the following algorithm:
+%
+% . Decrease the height `h' by 1 temporarily.
+%
+% . Compute the path for the upper half of the glyph.
+%
+% . Mirror the path at the x axis.
+%
+% . Shift the upper half one pixel up and connect it with the lower path.
+%
+% . Restore height and decrease `d' by 1.
+%
+% o The glyph is centered between two or four staff lines, and the origin is
+% the middle of the whitespace. Assuming that the the whitespace consists
+% of an odd number of pixels, we have this:
+%
+% -----------
+% b
+% 1
+% b
+% ___________
+% b
+% .................. 1 ................. x axis
+% b
+% ___________
+% b
+% 1
+% b
+% ___________
+%
+% For symmetrical glyphs, this leads to a similar algorithm as above.
+% Glyphs which can't be constructed from an upper and lower part need
+% to be handled differently, namely to shift up the vertical center by
+% half a pixel:
+%
+% ___________
+% b
+%
+% 0.5
+% .................. 0.5 ................ x axis
+%
+% b
+% ___________
+%
+
+feta_eps := 0;
+feta_shift := 0;
+feta_space_shift := 0;
+
+% Use this for paths with a slant of 45 degrees to assure that
+% the middle point of a penpos gets covered.
+pair feta_offset;
+feta_offset := (0, 0);
+
+if known miterlimit:
+ pickup nullpen;
+else:
+ feta_eps := eps;
+
+ if odd stafflinethickness_rounded:
+ feta_shift := 1;
+ fi;
+
+ if odd (staff_space_rounded - stafflinethickness_rounded):
+ feta_space_shift := 1;
+ fi;
+
+ feta_offset := (0.5, 0.5);
+
+ pickup pencircle scaled 1;
+fi;
+
+feta_fillpen := savepen;
diff --git a/muse2/share/scoreglyphs/feta-original/feta-pendaal.mf b/muse2/share/scoreglyphs/feta-original/feta-pendaal.mf
new file mode 100644
index 00000000..fded9ecb
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-pendaal.mf
@@ -0,0 +1,348 @@
+% -*- Fundamental -*- (emacs-20 mf mode mucks
+% feta-pendaal.mf -- piano pedal markings
+%
+% part of LilyPond's pretty-but-neat music font
+%
+% source file of the Feta (not the Font-En-Tja) music font
+%
+% (c) 2000--2009 Jan Nieuwenhuizen <janneke@gnu.org>
+%
+% Voor Cup
+
+% Kerning
+%
+% Pe = -0.034 pedalh == -0.07 staff-space
+% ed = -0.27 pedalh == -0.53 staff-space
+
+
+fet_begingroup ("pedal");
+
+pedalpha = 40;
+pedbeta = 25;
+
+penh# = 0.7 linethickness#;
+penw# = 2 penh# + 0.14 staff_space#;
+define_pixels (penh, penw);
+
+pedalh# = 2 staff_space#;
+pedalbh# = 4/7 pedalh#;
+define_pixels (pedalh, pedalbh);
+
+
+fet_beginchar ("Pedal asterisk", "*");
+ save bulb, p, radius, thin, inner_r;
+ path pat;
+
+ set_char_box (0, 7/9 pedalh#, 0, pedalh#);
+
+ z0 = (1/2 w, h - 1/2 w);
+
+ thin = 0.8 linethickness;
+
+ bulb + 2 radius = w;
+ 0.9 thin + bulb = (radius * pi * 2) / 8;
+
+ pickup pencircle scaled penh;
+
+ penpos1 (bulb, 180);
+ penpos2 (bulb, 0);
+ penpos3 (thin, 0);
+
+ z1 = z0 + (0, radius);
+ z2 = z1;
+
+ inner_r = .45 radius;
+
+ z4l = z0 + inner_r * dir (90 + 360/16);
+ z4r = z0 + inner_r * dir (90 - 360/16);
+
+ z4 = .5 [z4l, z4r];
+ z3 = .75 [z1, z4];
+
+ penlabels (0, 1, 2, 3, 4);
+
+ pat := z3r{up}
+ .. z1l{up}
+ .. z2l{down}
+ .. z3l{down}
+ .. z4l{dir (180 + 360/16)};
+ for i = 1 upto 7:
+ pat := pat
+ .. ((z3r{up}
+ .. z1l{up}
+ .. z2l{down}
+ .. z3l{down}
+ .. z4l{dir (180 + 360/16)})
+ rotatedaround (z0, 360/8 i));
+ endfor;
+
+ pat := pat
+ .. cycle;
+ fill pat;
+
+ pickup pencircle scaled (7/8 inner_r);
+
+ undrawdot z0;
+fet_endchar;
+
+
+%% ugh. rounded corners!
+
+fet_beginchar ("Pedal dash", "M");
+ save dash_thickness;
+
+ dash_thickness# := penw#;
+ define_whole_vertical_blacker_pixels (dash_thickness);
+
+ set_char_box (0, 3 penw#, 0, pedalbh#);
+
+ penpos1 (dash_thickness, 60);
+ penpos2 (dash_thickness, 60);
+
+ z1l = (0, vround (2/3 h - 1/2 penw));
+ z2r = (w, vround (y1l + 1.2 penw));
+
+ penlabels (1, 2, 3);
+
+ penstroke z1e{dir 40}
+ ..tension 1.2.. z2e{dir 40};
+fet_endchar;
+
+
+fet_beginchar ("Pedal dot", ".");
+ set_char_box (0, penw#, 0, penw#);
+
+ pickup pencircle scaled penw;
+
+ drawdot (hround (1/2 penw), vround (1/2 penw));
+fet_endchar;
+
+
+def draw_pedal_P (expr show_labels) =
+begingroup;
+ clearxy;
+
+ penpos1 (hround penh, 0);
+ penpos2 (penw, 55);
+ penpos3 (penw, pedalpha);
+ penpos4 (1.2 penh, -pedalpha);
+ penpos5 (penh, -pedalpha);
+ penpos6 (penh, 180 - pedalpha);
+ penpos7 (penh, 180 - pedalpha);
+ penpos8 (penh, 90);
+ penpos9 (4/3 penw, 50);
+ penpos10 (1.4 penw, 50);
+ penpos11 (penh, 90 + pedalpha);
+
+ z1r = (hround 0.6 w, h);
+ x2l = hround (x1l - penw) + xpart feta_offset;
+ y2 = vround (0.7 h) + ypart feta_offset;
+ x3r = hround (x2l + 2 penw);
+ y3r = 0.4 h;
+ z4l = z5r + 1/4 (z3r - z5r);
+ x5 = 1/4 w;
+ y5r = 0;
+ z6 = z5;
+ z7l = z6r + 1/3 (z8r - z6r);
+ z8r = z5r + 3/5 (z3r - z5r);
+ x9l = x10l - penh;
+ y9l = 1/4 penh;
+ x10l = w - tand (90 - pedalpha) * y11l;
+ y10l = 1/4 penh;
+ x11l = w;
+ y11 = 1/5 h;
+
+ % don't stick out at the top
+ z1' = round (0.9 [z2, z1]) + (xpart feta_offset, 0);
+ penpos1' (penh, 0);
+
+ % shift start point of pen stroke to avoid overlapping contours
+ z8'l = z8l;
+ y8'r = y8r;
+ z8'r = z8l + whatever * (z3r - z8l);
+
+ penpos12 (hround penh, 0);
+ penpos13 (penw, -90 - pedbeta);
+ penpos14 (vround penh, 90);
+ penpos15 (penw, -90 + pedbeta);
+ penpos16 (penh, 180 + pedbeta);
+
+ z12r = (hround (5/9 x1 + 1/2 hround penh), y2);
+ z13l = (1/2 x12r, y15r);
+ z14r = z1r;
+ z15l = (1/2 [x16, w], y2l + 0.5 penw);
+ x16 = 1/4 [x1, w];
+ y16r = y2r;
+
+ % We now do a correction to `center' the stem horizontally. While
+ % this is not the most elegant solution, it is definitely the
+ % easiest...
+
+ save horz_corr;
+ horz_corr = 1/5 [x12, x16] - x2l;
+ x2 := x2 + horz_corr;
+ x2l := x2l + horz_corr;
+ x2r := x2r + horz_corr;
+
+ penstroke z1'e
+ ..tension 2.5.. z2e
+ ..tension 1.5.. z3e
+ ..tension 2.5.. {dir (225)}z4e;
+
+ soft_end_penstroke z8'e{right}
+ ..tension 1.5.. z9e{dir (-pedalpha)}
+ .. z10e
+ ..tension 2.5.. z11e;
+
+ fill z4r{dir (225)}
+ ..tension 1.5.. z5r{left}
+ .. z6r
+ ..tension 1.5.. z7r
+ ..tension 1.5.. z8r{right}
+ -- cycle;
+
+ soft_penstroke z12e{down}
+ ..tension 1.1.. z13e{dir (180 - pedbeta)}
+ ..tension 1.1.. z14e{right}
+ ..tension 1.1.. z15e{dir (180 + pedbeta)}
+ ..tension 1.1.. z16e{dir (90 + pedbeta)};
+
+ if show_labels = 1:
+ penlabels (range 1 thru 16);
+ penlabels (1', 8');
+ fi;
+endgroup;
+enddef;
+
+
+def draw_pedal_d (expr show_labels) =
+begingroup;
+ clearxy;
+
+ penpos1 (vround penh, -10 - 90);
+ penpos2 (hround penw, 190);
+ penpos3 (vround (2 penh), 90);
+ penpos4 (hround (3/4 penw), 0);
+ penpos5 (penh, -70);
+
+ x1r = 0;
+ y1l = h;
+ z2 = (w - 1/2 hround penw, 1/2 pedalbh + penh);
+ z4l = (hround (1/3 w), 1/2 pedalbh);
+ z5l = (2/3 w, pedalbh);
+ z3l = (hround x5l, 0);
+
+ if show_labels = 1:
+ penlabels (1, 2, 3, 4, 5);
+ fi;
+
+ soft_start_penstroke z1e{dir (-10)}
+ ..tension 1.1.. z2e{dir (-90 + 10)}
+ ..tension 1.1.. z3e{left}
+ ..tension 1.1.. z4e{up}
+ ..tension 1.1.. z5e{dir (-70 + 90)};
+endgroup;
+enddef;
+
+
+def draw_pedal_e (expr show_labels) =
+begingroup;
+ clearxy;
+
+ penpos1 (penh, pedalpha - 90);
+ penpos2 (penh, pedalpha - 90);
+ penpos3 (3/5 penw, pedalpha);
+ penpos4 (1.2 penh, 90 + pedalpha);
+ penpos5 (2/3 penw, 180);
+ penpos6 (penw, 180 + pedalpha);
+ penpos7 (2/3 penw, -90 - 20);
+ penpos8 (penh, pedalpha - 90);
+
+ z1l = (0, 1/5 pedalh);
+ % this helps to make the path go through z2 at low resolutions
+ z2 = round (z1 + dir pedalpha * penw) + feta_offset;
+ z3 = (3/5 w, 8/9 h);
+ z4 = (2/9 w, y3);
+ x4r := hround x4r;
+ x5r = 0;
+ y5 = y2;
+ x6 = 3/8 w;
+ y6r = 1/2 penh;
+ z7l = (x6l + penh, y6l);
+ x8r = w;
+ y8 = 1/5 pedalh;
+
+ soft_penstroke z1e
+ -- z2e{z2 - z1}
+ ..tension 1.1.. z3e
+ ..tension 1.05.. z4e
+ ..tension 1.1.. z5e
+ ..tension 1.5.. z6e{dir - pedalpha}
+ ..tension 1.1.. z7e
+ ..tension 2.5.. z8e;
+
+ if show_labels = 1:
+ penlabels (range 1 thru 8);
+ fi;
+endgroup;
+enddef;
+
+
+fet_beginchar ("Pedal P", "P");
+ set_char_box (0, 5/6 pedalh#, 0, pedalh#);
+
+ draw_pedal_P (1);
+fet_endchar;
+
+
+fet_beginchar ("Pedal d", "d");
+ set_char_box (0, 2/3 pedalh#, 0, 7/8 pedalh#);
+
+ draw_pedal_d (1);
+fet_endchar;
+
+
+fet_beginchar ("Pedal e", "e");
+ set_char_box (0, 2/5 pedalh#, 0, pedalbh#);
+
+ draw_pedal_e (1);
+fet_endchar;
+
+
+fet_beginchar ("Pedal Ped", "Ped");
+ P_width# = 5/6 pedalh#;
+ e_width# = 2/5 pedalh#;
+ d_width# = 2/3 pedalh#;
+ define_pixels (P_width, e_width, d_width);
+
+ e_height = pedalbh;
+ d_height = 7/8 pedalh;
+
+ % Pe = -0.034 pedalh == -0.07 staff-space
+ % ed = -0.27 pedalh == -0.53 staff-space
+ Pe_kern# = -0.034 pedalh#;
+ ed_kern# = -0.27 pedalh#;
+ define_pixels (Pe_kern, ed_kern);
+
+ w := hround d_width;
+ h := vround d_height;
+ draw_pedal_d (0);
+ currentpicture := currentpicture
+ shifted (hround (e_width + ed_kern), 0);
+
+ w := hround e_width;
+ h := vround e_height;
+ draw_pedal_e (0);
+ currentpicture := currentpicture
+ shifted (hround (P_width + Pe_kern), 0);
+
+ w := hround P_width;
+ h := vround pedalh;
+ draw_pedal_P (0);
+
+ set_char_box (0, P_width# + Pe_kern# + e_width# + ed_kern# + d_width#,
+ 0, pedalh#);
+fet_endchar;
+
+
+fet_endgroup ("pedal");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-puntje.mf b/muse2/share/scoreglyphs/feta-original/feta-puntje.mf
new file mode 100644
index 00000000..a24e3693
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-puntje.mf
@@ -0,0 +1,26 @@
+%
+% feta-puntje.mf -- a duration dot
+%
+% source file of the GNU LilyPond music typesetter
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+fet_begingroup ("dots");
+
+save dot_diam;
+
+2 dot_diam# = staff_space# - stafflinethickness#;
+define_whole_blacker_pixels (dot_diam);
+
+fet_beginchar ("duration dot", "dot");
+ pickup pencircle scaled dot_diam;
+
+ lft x0 = 0;
+ top y0 = vround (.5 dot_diam);
+
+ drawdot z0;
+
+ set_char_box (0, dot_diam#, .5 dot_diam#, .5 dot_diam#);
+fet_endchar;
+
+fet_endgroup ("dots");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-schrift.mf b/muse2/share/scoreglyphs/feta-original/feta-schrift.mf
new file mode 100644
index 00000000..5bb7c1ab
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-schrift.mf
@@ -0,0 +1,1560 @@
+% -*- Fundamental -*- (emacs-20 mf mode mucks
+% feta-schrift.mf -- implement scripts
+%
+% source file of the Feta (defintively not an abbreviation for Font-En-Tja)
+% music font
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+% Jan Nieuwenhuizen <janneke@gnu.org>
+%
+
+
+fet_begingroup ("scripts");
+
+def draw_fermata =
+ save alpha, radius, crook_thinness, crook_fatness, dot_size;
+ save pat;
+ path pat;
+
+ % [Wanske] and some Baerenreiter editions
+ % suggest about 80 degrees instead of a half-circle
+ alpha := 10;
+
+ radius# = 1.25 staff_space#;
+ crook_thinness# = 1.5 linethickness#;
+ crook_fatness# = 0.25 staff_space# + 1.5 linethickness#;
+
+ radius# + crook_fatness# / 2 = h#;
+ radius# + crook_thinness# / 2 = w#;
+
+ set_char_box (w#, w#, crook_thinness# / 2, h#);
+
+ define_pixels (radius, crook_thinness, crook_fatness);
+
+ dot_size# = 8/6 crook_fatness#;
+ define_whole_blacker_pixels (dot_size);
+
+ penpos1 (crook_thinness, 0);
+ penpos2 (crook_fatness, -90);
+ z1 = (-radius, 0);
+ z2 = (0, radius);
+
+ pat := z2l{left}
+ .. z1l{dir (-alpha - 90)}
+ .. {dir (90 - alpha)}z1r
+ .. {right}z2r;
+ pat := pat
+ -- reverse pat xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+ fill pat;
+
+ pickup pencircle scaled dot_size;
+ x4 = 0;
+ bot y4 = vround (-crook_thinness / 2);
+ drawdot z4;
+enddef;
+
+
+fet_beginchar ("fermata up", "ufermata");
+ draw_fermata;
+ penlabels (1, 2, 4);
+fet_endchar;
+
+
+fet_beginchar ("fermata down", "dfermata");
+ draw_fermata;
+ y_mirror_char;
+fet_endchar;
+
+
+def draw_short_fermata =
+ save fat_factor, thinness, dot_size;
+ save left_dist, right_dist, se, ne;
+ pair left_dist, right_dist, se, ne;
+
+ set_char_box (staff_space#, staff_space#, 0, 2.2 staff_space#);
+
+ dot_size# = 0.266 staff_space# + 2.666 linethickness#;
+ define_whole_blacker_pixels (dot_size);
+
+ fat_factor = .11;
+ thinness = 1.5 linethickness;
+
+ pickup pencircle scaled thinness;
+
+ rt x2 = w;
+ lft x5 = -b;
+ bot y5 = 0;
+ top y3 = h;
+ y1 = y2 = y5;
+
+ x3 = 0;
+ z1 - z4 = whatever * (charwd, -charht);
+ z4 = fat_factor [z3, z5];
+
+ ne = unitvector (z3 - z5);
+ se = unitvector (z2 - z3);
+
+ left_dist = (ne rotated 90) * 0.5 thinness;
+ right_dist = (se rotated 90) * 0.5 thinness;
+
+ fill bot z5{right}
+ .. (z5 - left_dist){ne}
+ -- (((z5 - left_dist) -- (z3 - left_dist)) intersectionpoint
+ ((z1 - right_dist) -- (z4 - right_dist)))
+ -- (z1 - right_dist){se}
+ .. bot z1{right}
+ -- bot z2{right}
+ .. (z2 + right_dist){-se}
+ -- (z3 + right_dist){-se}
+ .. top z3
+ .. (z3 + left_dist){-ne}
+ -- (z5 + left_dist){-ne}
+ .. cycle;
+
+ pickup pencircle scaled dot_size;
+
+ x1 - 2 x6 = x2;
+ x6 := vround (x6);
+ bot y6 = -d;
+
+ drawdot z6;
+enddef;
+
+fet_beginchar ("short fermata up", "ushortfermata");
+ draw_short_fermata;
+ labels (1, 2, 3, 4, 5, 6);
+fet_endchar;
+
+
+fet_beginchar ("short fermata down", "dshortfermata");
+ draw_short_fermata;
+ xy_mirror_char;
+fet_endchar;
+
+
+def draw_long_fermata =
+ save stemthick, beamheight, dot_size, wd;
+ save pat;
+ path pat;
+
+ wd# = 2.5 staff_space#;
+ stemthick = hround (1.5 linethickness);
+ beamheight = 0.3 staff_space + linethickness;
+ dot_size# = 0.266 staff_space# + 2.666 * linethickness#;
+ define_pixels (wd);
+ define_whole_blacker_pixels (dot_size);
+
+ set_char_box (wd# / 2, wd# / 2, 0, 3/2 staff_space#);
+
+ pickup pencircle scaled blot_diameter;
+
+ top y1 = h;
+ lft x1 = -b;
+
+ pat := top z1{left}
+ .. {down}lft z1;
+
+ pickup pencircle scaled stemthick;
+
+ x2 = -b + stemthick;
+ y2 = h - beamheight;
+ lft x3 = -b;
+ bot y3 = -d;
+
+ pat := pat
+ -- lft z3
+ .. bot z3
+ .. rt z3
+ -- z2;
+ pat := pat
+ -- reverse pat xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+
+ fill pat;
+
+ pickup pencircle scaled dot_size;
+
+ x4 = 0;
+ bot y4 = -d;
+
+ drawdot z4;
+enddef;
+
+
+fet_beginchar ("long fermata up", "ulongfermata");
+ draw_long_fermata;
+ labels (1, 2, 3, 4);
+fet_endchar;
+
+
+fet_beginchar ("long fermata down", "dlongfermata");
+ draw_long_fermata;
+ y_mirror_char;
+fet_endchar;
+
+
+def draw_very_long_fermata =
+ save ibeamheight, obeamheight;
+ save ihwd, ohwd, iht, oht; % inner/outer half_width/height
+ save stemthick, dot_size;
+ save opat, ipat;
+ path opat, ipat;
+
+ ihwd# = 1.0 staff_space#;
+ ohwd# = 1.5 staff_space#;
+ iht# = 0.9 staff_space#;
+ oht# = 1.6 staff_space#;
+ define_pixels (ihwd, ohwd, iht, oht)
+
+ stemthick = hround (1.5 linethickness);
+ ibeamheight# = 0.3 staff_space#;
+ obeamheight# = 0.5 staff_space#;
+ define_pixels (ibeamheight, obeamheight);
+
+ dot_size# = (iht# - ibeamheight#) * 8/10;
+ define_whole_blacker_pixels (dot_size);
+
+ set_char_box (ohwd#, ohwd#, 0, oht#);
+
+ pickup pencircle scaled blot_diameter;
+
+ top y1 = oht;
+ lft x1 = -ohwd;
+ top y11 = iht;
+ lft x11 = -ihwd;
+
+ opat := top z1{left}
+ .. {down}lft z1;
+ ipat := top z11{left}
+ .. {down}lft z11;
+
+ pickup pencircle scaled stemthick;
+
+ x2 = -ohwd + stemthick;
+ y2 = oht - obeamheight;
+ lft x3 = -ohwd;
+ bot y3 = 0;
+ x12 = -ihwd + stemthick;
+ y12 = iht - ibeamheight;
+ lft x13 = -ihwd;
+ bot y13 = 0;
+
+ opat := opat
+ -- lft z3
+ .. bot z3
+ .. rt z3
+ -- z2;
+ opat := opat
+ -- reverse opat xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+ ipat := ipat
+ -- lft z13
+ .. bot z13
+ .. rt z13
+ -- z12;
+ ipat := ipat
+ -- reverse ipat xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+
+ fill opat;
+ fill ipat;
+
+ pickup pencircle scaled dot_size;
+
+ x4 = 0;
+ bot y4 = -d;
+
+ drawdot z4;
+enddef;
+
+
+fet_beginchar ("very long fermata up", "uverylongfermata");
+ draw_very_long_fermata;
+ labels (1, 2, 3, 11, 12, 13, 4);
+fet_endchar;
+
+
+fet_beginchar ("very long fermata down", "dverylongfermata");
+ draw_very_long_fermata;
+ y_mirror_char;
+fet_endchar;
+
+
+%
+% Thumbs are used in cello music.
+% TODO : thumbs should look like the finger-font and should be placed in
+% the same way in the score.
+%
+
+fet_beginchar ("Thumb", "thumb");
+ save thin, height, width, thick, depth;
+ height# = 5/4 width#;
+ height# = staff_space#;
+ depth# = 1.6 (height# / 2);
+
+ set_char_box (width# / 2, width# / 2, depth#, height# / 2);
+
+ define_pixels (height, width);
+
+ thin = .6 linethickness + 0.06 staff_space;
+ 2 thick + 0.5 (height - 2 thin) = width;
+
+ penpos1 (thick, 0);
+ penpos2 (thin, 90);
+ penpos3 (thick, 180);
+ penpos4 (thin, 270);
+ z1r = (w, 0);
+ z2r = (0, h);
+ z3r = (-w, 0);
+ z4r = (0, -h);
+
+ penlabels (1, 2, 3, 4);
+
+ penstroke z1e{up}
+ .. z2e{left}
+ .. z3e{down}
+ .. z4e{right}
+ .. cycle;
+
+ save brush_thick;
+ y5 = -d + brush_thick / 2;
+ brush_thick = 0.9 thick;
+ x5 = 0;
+
+ labels (5);
+
+ draw_brush (z4r, 1.4 thin, z5, brush_thick);
+fet_endchar;
+
+
+%
+% `\accent' is TeX reserved.
+%
+
+def draw_accent (expr bottom_left, top_right, thickness, diminish) =
+ save thinning_start;
+ thinning_start = 0.4;
+ pickup pencircle scaled thickness;
+
+ lft x1 = xpart bottom_left;
+ top y1 = ypart top_right;
+ lft x6 = xpart bottom_left;
+ bot y6 = ypart bottom_left;
+
+ rt z4 = (xpart top_right, (ypart top_right + ypart bottom_left) / 2);
+ x5 = x3 = thinning_start [xpart top_right, xpart bottom_left]
+ - linethickness + 0.1 staff_space;
+ z3 = whatever [z1, z4];
+ z5 = whatever [z6, z4];
+
+ penpos1 (thickness, angle (z3 - z1) + 90);
+ penpos3 (thickness, angle (z3 - z1) + 90);
+ penpos4 (thickness, 90);
+ penpos5 (thickness, angle (z6 - z5) + 90);
+ penpos6 (thickness, angle (z6 - z5) + 90);
+
+ x4 - x7 = diminish * thickness;
+ y7 = y4;
+
+ fill z1l
+ -- z3l
+ -- z7
+ -- z5l
+ -- z6l
+ .. lft z6{down}
+ .. bot z6
+ .. z6r
+ -- z4l
+ ..tension 0.8.. rt z4
+ ..tension 0.8.. z4r
+ -- z1r
+ .. top z1
+ .. lft z1{down}
+ .. cycle;
+enddef;
+
+
+fet_beginchar ("> accent", "sforzato");
+ set_char_box (.9 staff_space#, .9 staff_space#,
+ .5 staff_space#, .5 staff_space#);
+
+ draw_accent ((-w, -d), (w, h),
+ 0.05 staff_space + linethickness, 0.7);
+ penlabels (1, 3, 4, 5, 6);
+ labels (7);
+fet_endchar;
+
+
+fet_beginchar ("espr", "espr");
+ set_char_box (1.9 staff_space#, 1.9 staff_space#,
+ .5 staff_space#, .5 staff_space#);
+
+ draw_accent ((w - 1.78 staff_space, -d), (w, h),
+ 0.05 staff_space + linethickness, 0.6);
+ addto currentpicture also currentpicture xscaled -1;
+fet_endchar;
+
+
+fet_beginchar ("staccato dot", "staccato");
+ save radius;
+ radius# = 0.20 * staff_space#;
+ define_whole_pixels (radius);
+
+ pickup pencircle scaled 2 radius;
+ drawdot (0, 0);
+
+ set_char_box (radius#, radius#, radius#, radius#);
+fet_endchar;
+
+
+def draw_staccatissimo =
+ save radius, height;
+ height# = .8 staff_space#;
+ radius# = linethickness# + .1 staff_space#;
+ define_whole_blacker_pixels (radius);
+ define_pixels (height);
+
+ draw_brush ((0, 0), linethickness, (0, height), 2 radius);
+
+ set_char_box (radius#, radius#,
+ blot_diameter# / 2, height# + radius#);
+enddef;
+
+
+fet_beginchar ("staccatissimo/martellato up", "ustaccatissimo");
+ draw_staccatissimo;
+fet_endchar;
+
+
+fet_beginchar ("staccatissimo/martellato down", "dstaccatissimo");
+ draw_staccatissimo;
+ y_mirror_char;
+fet_endchar;
+
+
+fet_beginchar ("portato/single tenuto", "tenuto");
+ save thick;
+ thick# = 1.6 linethickness#;
+ define_whole_blacker_pixels (thick);
+
+ set_char_box (.6 staff_space#, .6 staff_space#,
+ thick# / 2, thick# / 2);
+
+ draw_rounded_block ((-b, -thick / 2), (w, thick / 2), thick);
+fet_endchar;
+
+
+def draw_portato =
+ save thick, dot_size;
+ thick# = 1.4 linethickness#;
+ dot_size# = 2.4 linethickness# + 0.08 staff_space#;
+ define_whole_blacker_pixels (thick, dot_size);
+
+ set_char_box (.6 staff_space#, .6 staff_space#,
+ thick# / 2, .5 staff_space# + .5 dot_size#);
+
+ draw_rounded_block ((-b, -thick / 2), (w, thick / 2), thick);
+
+ pickup pencircle scaled dot_size;
+ drawdot (0, h);
+enddef;
+
+
+fet_beginchar ("portato/tenuto with staccato", "uportato");
+ draw_portato;
+fet_endchar;
+
+
+fet_beginchar ("portato/tenuto with staccato", "dportato");
+ draw_portato;
+ y_mirror_char
+fet_endchar;
+
+
+def draw_marcato =
+ save fat_factor, thinness;
+ save left_dist, right_dist, ne, se;
+ pair left_dist, right_dist, ne, se;
+
+ set_char_box (staff_space# / 2, staff_space# / 2,
+ 0, 1.1 staff_space#);
+
+ fat_factor = .3;
+ thinness = linethickness;
+
+ pickup pencircle scaled thinness;
+
+ rt x2 = w;
+ lft x5 = -b;
+ bot y5 = 0;
+ top y3 = h;
+ y1 = y2 = y5;
+
+ x3 =0;
+ z1 - z4 = whatever * (charwd, -charht);
+ z4 = fat_factor [z3, z5];
+
+ ne = unitvector (z3 - z5);
+ se = unitvector (z2 - z3);
+
+ left_dist = (ne rotated 90) * 0.5 thinness;
+ right_dist = (se rotated 90) * 0.5 thinness;
+
+ fill bot z5{right}
+ .. (z5 - left_dist){ne}
+ -- (((z5 - left_dist) -- (z3 - left_dist)) intersectionpoint
+ ((z1 - right_dist) -- (z4 - right_dist)))
+ -- (z1 - right_dist){se}
+ .. bot z1{right}
+ -- bot z2{right}
+ .. (z2 + right_dist){-se}
+ -- (z3 + right_dist){-se}
+ .. top z3
+ .. (z3 + left_dist){-ne}
+ -- (z5 + left_dist){-ne}
+ .. cycle;
+enddef;
+
+
+fet_beginchar ("marcato up", "umarcato");
+ draw_marcato;
+ labels (1, 2, 3, 4, 5);
+fet_endchar;
+
+
+%
+% The down marcato char (not very much used).
+% Contrary to what some MF/TeX `gurus' believe
+% it is *point*-symmetric with the "up" version
+%
+
+fet_beginchar ("marcato down", "dmarcato");
+ draw_marcato;
+ xy_mirror_char;
+fet_endchar;
+
+
+%
+% used in french horn music todo
+%
+% TODO: too light at 20pt
+%
+
+fet_beginchar ("open (unstopped)", "open");
+ save thin, height, width, thick;
+
+ height# = 5/4 width#;
+ height# = staff_space#;
+ thin = .6 linethickness + 0.06 staff_space;
+
+ set_char_box (width# / 2, width# / 2, height# / 2, height# / 2);
+
+ define_pixels (width, height);
+
+ 2 thick + 0.6 (height - 2 thin) = width;
+
+ penpos1 (thick, 0);
+ penpos2 (thin, 90);
+ penpos3 (thick, 180);
+ penpos4 (thin, 270);
+ z1r = (w, 0);
+ z2r = (0, h);
+ z3r = (-w, 0);
+ z4r = (0, -h);
+
+ penlabels (1, 2, 3, 4);
+
+ penstroke z1e{up}
+ .. z2e{left}
+ .. z3e{down}
+ .. z4e{right}
+ .. cycle;
+fet_endchar;
+
+
+fet_beginchar ("plus (stopped)", "stopped");
+ save hthick, vthick, size, outer_hsize, outer_vsize;
+
+ hthick# = vthick# = 2 linethickness#;
+ size# = 1.1 staff_space#;
+ define_whole_blacker_pixels (vthick);
+ define_whole_vertical_blacker_pixels (hthick);
+
+ set_char_box (size# / 2, size# / 2, size# / 2, size# / 2);
+
+ outer_hsize = hround ((b + w - vthick) / 2);
+ outer_vsize = vround ((h + d - hthick) / 2);
+ w := b := (2 outer_hsize + vthick) / 2;
+ h := d := (2 outer_vsize + hthick) / 2;
+
+ draw_rounded_block ((-b, -d + outer_vsize),
+ (w, -d + outer_vsize + hthick), hthick);
+ draw_rounded_block ((-b + outer_hsize, -d),
+ (-b + outer_hsize + vthick, h), vthick);
+fet_endchar;
+
+
+fet_beginchar ("Upbow", "upbow");
+ save ht, wd, thick;
+
+ thick = 1.4 linethickness;
+ wd# = 1.3 staff_space#;
+ ht# = 1.6 wd#;
+
+ set_char_box (wd# / 2, wd# / 2, 0, ht#);
+
+ draw_accent ((-h, -w), (0, w), thick, 0.9);
+ currentpicture := currentpicture rotated -90;
+fet_endchar;
+
+
+fet_beginchar ("Downbow", "downbow");
+ save stemthick, beamheight, wd;
+ save pat;
+ path pat;
+
+ wd# = 1.5 staff_space#;
+ define_pixels (wd);
+
+ stemthick = hround (1.2 linethickness);
+
+ set_char_box (wd# / 2, wd# / 2, 0, 4/3 staff_space#);
+
+ beamheight = 4/10 h;
+
+ pickup pencircle scaled blot_diameter;
+
+ top y1 = h;
+ lft x1 = -b;
+
+ pat := top z1{left}
+ .. {down}lft z1;
+
+ pickup pencircle scaled stemthick;
+
+ x2 = -b + stemthick;
+ y2 = h - beamheight;
+ lft x3 = -b;
+ bot y3 = -d;
+
+ pat := pat
+ -- lft z3
+ .. bot z3
+ .. rt z3
+ -- z2;
+ pat := pat
+ -- reverse pat xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+
+ fill pat;
+
+ labels (1, 2, 3);
+fet_endchar;
+
+%
+% Inspired by a computer-set version of Auf dem Strom by Baerenreiter.
+%
+
+def draw_turn =
+ save thin, thick, ball_diam, darkness;
+ save wd, ht, thick_nibangle, ball_nib_thick;
+ save turndir;
+ pair turndir;
+
+ wd# = 35/16 staff_space#;
+ ht# = 18/17 staff_space#;
+ darkness = 0.3 linethickness + 0.09 staff_space;
+
+ set_char_box (wd# / 2, wd# / 2, ht# / 2, ht# / 2);
+
+ thick_nibangle = 60;
+ thick = 3 darkness;
+ thin = darkness;
+ ball_nib_thick = 2.7 darkness;
+ ball_diam = ball_nib_thick + (h - ball_nib_thick) / 10;
+
+ x3l = w;
+ y3 = 0;
+ y4l = h;
+ x4 = x2;
+ x2l = w / 2;
+ y2l = -d;
+ z1 = (0,0);
+
+ penpos1 (1.1 thick, thick_nibangle);
+ penpos2 (thick, thick_nibangle);
+ penpos3 (thin, 180);
+ penpos4 (ball_nib_thick, -90);
+
+ path swoosh, ploop;
+ swoosh := z1l{curl 0}
+ .. z2l
+ .. z3l{up}
+ .. {left}z4l
+ -- z4r
+ .. z3r{down}
+ .. z2r{left};
+ fill swoosh
+ .. swoosh scaled -1 shifted (-feta_eps, -feta_eps)
+ .. cycle;
+
+ x5r = x4;
+ y5r = y4l - ball_diam / 2;
+ z6r = z5r;
+
+ penpos5 (1.6 ball_diam / 2, 10);
+ penpos6 (ball_diam / 2, 150);
+
+ ploop := z4l{left}
+ .. z5l
+ .. z6l
+ -- cycle;
+ fill ploop;
+ fill ploop scaled -1 shifted (-feta_eps, -feta_eps);
+enddef;
+
+
+fet_beginchar ("Reverse turn", "reverseturn");
+ draw_turn;
+ currentpicture := currentpicture yscaled -1;
+fet_endchar;
+
+
+fet_beginchar ("Turn", "turn");
+ draw_turn;
+ penlabels (1, 2, 3, 4, 5, 6, 7);
+fet_endchar;
+
+
+%
+% Inspired by a (by now) PD edition of Durand & C'ie edition of
+% Saint-Saens' Celloconcerto no. 1
+%
+% FIXME take out hardcoded vars.
+% FIXME the two loops on the `t' should be smoother (and the left one bigger).
+% FIXME generic macros for serifs: top of the t and bottom of r
+%
+
+fet_beginchar ("Trill (`tr')", "trill");
+ save start_nib_angle, ascender_extra, ex, hair_thick, fatness;
+ save slant, t_fatness, r_fatness, kerning, t_overshoot;
+ save uitschieter, bulb_size, krul_ang;
+ save u, v;
+
+ ascender_extra# = 1/2 ex#;
+ ascender# = ascender_extra# + ex#;
+ ex# = 1.4 staff_space#;
+ kerning# = 0.6 ex#;
+ start_nib_angle = 20;
+ bulb_size = 0.8;
+ define_pixels (ex, ascender_extra, ascender, kerning);
+
+ t_overshoot = 0.03 ex;
+ fatness = 12/40 ex;
+ t_fatness = 0.78 fatness;
+ t_width = 1.9 t_fatness;
+ r_fatness = 0.78 fatness;
+ uitschieter = 0.48 ex;
+ hair_thick = linethickness;
+ r_flare = .5 hair_thick + 0.25 r_fatness;
+ r_width = 2 r_fatness + 0.25 kerning;
+ slant = .2;
+
+ local_copy (transform)(currenttransform);
+ currenttransform := currenttransform slanted slant
+ shifted (-staff_space, 0);
+
+ set_char_box (.85 staff_space#, .85 staff_space#, 0, ascender#);
+
+ y1 = ascender;
+
+ % try to position in such a way that the center is the visual
+ % center
+
+ x1l = 0.2 staff_space;
+ x1r - x1l = t_fatness;
+ penpos1 (start_nib_wid, start_nib_angle);
+
+ z2 = (x1, 7/18 ex);
+ penpos2 (start_nib_wid, start_nib_angle);
+
+ z3l = (x2l + 0.5 t_width, - t_overshoot);
+
+ z4l = (x2l + t_width, 0.23 ex);
+ penpos4 (whatever, 180); % 200
+ x4l - x4r = hair_thick;
+
+ x3r = 0.5 [x4r, x2r];
+% 1.7 [x3l, x3r] = x4r;
+ y3r - y3l = 0.6 t_fatness;
+
+ save krul_p;
+ path krul_p;
+
+ krul_ang = 32;
+
+ pickup pencircle scaled hair_thick;
+
+ z5 = (x2l + t_fatness / 2, 2/3 ex);
+ lft x6 = x2l - uitschieter;
+ y6 = y5; % - 1/20 ex;
+ z7 = z5 + whatever * dir krul_ang;
+ up_angle = krul_ang; % = angle (z7-z5)
+ x7 = 5/10 kerning + x5;
+
+ krul_p := z4{up}
+ ..tension 0.98.. z5
+ .. z6
+ .. z5{z7 - z5}
+ -- z7;
+
+ z4' = point 0.85 of krul_p;
+ penpos4' (hair_thick, angle (direction 0.85 of krul_p) + 90);
+
+ % the body of the `t' and the bottom loop
+ fill z1r{dir (angle (z1l - z1r) + 30)}
+ .. z1l{-dir (angle (z1r - z1l) - 45)}
+ -- z2l{down}
+ ..tension (1 + .5 slant).. z3l{right}
+ .. z4l{up}
+ .. z4'l{direction 0.85 of krul_p}
+ -- z4'r{-direction 0.85 of krul_p}
+ .. z4r{down}
+ .. z3r{left}
+ ..tension (1.5 + .7 slant).. z2r{up}
+ -- cycle;
+
+ z5' = point 1.1 of krul_p;
+ penpos5' (hair_thick, angle (direction 1.1 of krul_p) + 90);
+ z5'' = point 1.5 of krul_p;
+ penpos5'' (hair_thick, angle (direction 1.5 of krul_p) + 90);
+ z5''' = point 1.8 of krul_p;
+ penpos5''' (hair_thick, angle (direction 1.8 of krul_p) + 90);
+ z6 = point 2 of krul_p;
+ penpos6 (hair_thick, angle (direction 2 of krul_p) + 90);
+ z6' = point 2.3 of krul_p;
+ penpos6' (hair_thick, angle (direction 2.3 of krul_p) + 90);
+ z6'' = point 2.6 of krul_p;
+ penpos6'' (hair_thick, angle (direction 2.6 of krul_p) + 90);
+ z6''' = point 2.9 of krul_p;
+ penpos6''' (hair_thick, angle (direction 2.9 of krul_p) + 90);
+ penpos7 (hair_thick, up_angle + 90);
+ z7' = point 3.2 of krul_p;
+ penpos7' (hair_thick, angle (direction 3.2 of krul_p) + 90);
+
+ % the left loop
+ penstroke z5'e{direction 1.1 of krul_p}
+ .. z5''e{direction 1.5 of krul_p}
+ .. z5'''e{direction 1.8 of krul_p}
+ .. z6e{direction 2 of krul_p}
+ .. z6'e{direction 2.3 of krul_p}
+ .. z6''e{direction 2.6 of krul_p}
+ .. {direction 2.9 of krul_p}z6'''e;
+
+ y9 = 3/4 ex;
+ x9 = x1 + kerning;
+ penpos9 (r_fatness, 0);
+
+ x10 = x9;
+ y10 = -0.3 linethickness;
+ penpos10 (r_fatness, 0);
+
+ penpos11 (hair_thick, -4);
+ z11r = z9r;
+
+ z13l = (x9l + r_width, y11 - linethickness);
+ penpos13 (r_flare, 180);
+
+ z15 = z13r - (bulb_size * r_fatness, 0);
+ z14 = 0.5 [z13l, z15] - (0, bulb_size * r_fatness);
+
+ save before, after;
+ path before, after;
+ before := z13l{up}
+ .. {down}z11l;
+ after := z9r{up}
+ .. z7r{z7' - z7}
+ -- z7'r;
+ (u, v) = before intersectiontimes after;
+
+ save before_bulb, after_bulb;
+ path before_bulb, after_bulb;
+ before_bulb := z9r{up}
+ ..tension 0.94.. z13r{down};
+ after_bulb := z13l{up}
+ ..tension 1.06.. z15{down};
+ (u_bulb, v_bulb) = before_bulb intersectiontimes after_bulb;
+
+ % the connection between `t' and `r', the body of the `r',
+ % and the bulb
+ fill z7'l
+ -- z7l{z7 - z7'}
+ .. z9l{down}
+ -- simple_serif (z10l, z10r, -30)
+ -- z9r{up}
+ .. subpath (0, u_bulb) of before_bulb
+ .. subpath (v_bulb, infinity) of after_bulb
+ .. z14
+ .. z13l{up}
+ .. subpath (0, u) of before
+ .. subpath (v, infinity) of after
+ -- cycle;
+
+ penlabels (range 1 thru 15);
+ penlabels (4', 5', 5'', 5''', 6', 6'', 6''', 7');
+fet_endchar;
+
+
+def draw_heel =
+ save radius, thickness;
+ save pat;
+ path pat;
+
+ radius# := .5 staff_space#;
+
+ set_char_box (radius#, radius#, radius#, 2/3 staff_space#);
+
+ thickness := hround (1.5 linethickness);
+
+ pickup pencircle scaled thickness;
+
+ rt x1 = b;
+ top y1 = h;
+
+ x2 =x1;
+ y2 = 0;
+
+ x3 = 0;
+ bot y3 = -d;
+
+ pat := top z3{right}
+ .. lft z2{up}
+ -- lft z1
+ .. top z1
+ .. rt z1
+ -- rt z2{down}
+ .. bot z3{left};
+ pat := pat
+ -- reverse pat xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+ fill pat;
+enddef;
+
+
+fet_beginchar ("left heel", "upedalheel");
+ draw_heel;
+ labels (1, 2, 3);
+fet_endchar;
+
+
+fet_beginchar ("right heel", "dpedalheel");
+ draw_heel;
+ y_mirror_char;
+fet_endchar;
+
+
+def draw_toe =
+ save ht, wd, thickness;
+
+ thickness := 1.5 linethickness;
+ ht# := 1.5 staff_space#;
+ wd# := 1/3 ht#;
+ define_pixels (ht, wd);
+
+ set_char_box (wd#, wd#, 0, ht#);
+ draw_accent ((-h, -w), (0, w), thickness, 0.9);
+ currentpicture := currentpicture rotated -90;
+enddef;
+
+
+fet_beginchar ("left toe", "upedaltoe");
+ draw_toe;
+fet_endchar;
+
+
+fet_beginchar ("right toe", "dpedaltoe");
+ draw_toe;
+ y_mirror_char;
+fet_endchar;
+
+
+fet_beginchar ("Flageolet", "flageolet");
+ save height, width, thickness, superness;
+
+ height# = 4/15 staffsize#;
+ width# = height#;
+ thickness# = blot_diameter#;
+ define_pixels (height, width);
+ define_whole_blacker_pixels (thickness);
+
+ set_char_box (width# / 2, width# / 2, height# / 2, height# / 2);
+
+ penpos1 (thickness, 90);
+ penpos2 (thickness, 180);
+ penpos3 (thickness, 270);
+ penpos4 (thickness, 0);
+
+ x1 = 0;
+ y1r = h;
+ x4r = w;
+ x2r = -x4r;
+ y2 = 0;
+ y4 = y2;
+ x3 = x1;
+ y3r = -y1r;
+
+ penlabels (1, 2, 3, 4);
+
+ % mf doesn't handle pixel dropouts in outline objects, so we use
+ % `draw' if not called by mpost
+ if known miterlimit:
+ penstroke z1e
+ .. z2e
+ .. z3e
+ .. z4e
+ .. cycle;
+ else:
+ pickup pencircle scaled thickness;
+ draw z1
+ .. z2
+ .. z3
+ .. z4
+ .. cycle;
+ fi;
+fet_endchar;
+
+
+%
+% TODO: ARGRGHGH code dup.
+%
+
+fet_beginchar ("Segno", "segno");
+ save thin, thick, ball_diam, darkness, pointheight;
+ save wd, ht, thick_nibangle, ball_nib_thick;
+ save turndir;
+ pair turndir;
+
+ ht# = 3 staff_space#;
+ wd# = 2 staff_space#;
+ darkness = .08 staff_space + 0.4 linethickness;
+
+ set_char_box (wd# / 2, wd# / 2, ht# / 2, ht# / 2);
+
+ thick_nibangle = 30;
+ thick = 3 darkness;
+ thin = darkness;
+ ball_nib_thick = 2.7 darkness;
+ ball_diam = ball_nib_thick + (w - ball_nib_thick) / 10;
+ pointheight = 2 linethickness;
+
+ y3l = h;
+ 2 x3 = x2 + x4;
+ x4 = 0;
+ y4 = y2;
+ y2l = .6 h;
+ x2l = -b;
+ z1 = (0, 0);
+
+ penpos1 (thick, 2 thick_nibangle);
+ penpos2 (thick, thick_nibangle);
+ penpos3 (thin, -90);
+ penpos4 (ball_nib_thick, 180 - thick_nibangle);
+
+ save swoosh, ploop;
+ path swoosh, ploop;
+
+ swoosh := z1l{curl 0}
+ .. z2l
+ .. z3l{right}
+ .. {down}z4l
+ -- z4r
+ .. z3r{left}
+ .. z2r{down};
+ fill swoosh
+ .. (swoosh scaled -1)
+ .. cycle;
+
+ y5r = y4;
+ x5r = x4l - ball_diam / 2;
+ z6r = z5r;
+
+ penpos5 (1.6 ball_diam / 2, 100);
+ penpos6 (ball_diam / 2, 240);
+
+ ploop := z4l{down}
+ .. z5l
+ .. z6l
+ -- cycle;
+ fill ploop;
+ fill ploop scaled -1;
+
+ penpos7 (2 thin, 0);
+ z7l = (-b, -d);
+ penpos8 (2 thin, 0);
+ z8r = (w, h);
+
+ penstroke z7e
+ -- z8e;
+
+ pickup pencircle scaled 2 thin;
+ drawdot (-x2r, pointheight);
+ drawdot (x2r, -pointheight);
+
+ penlabels (range 1 thru 8);
+fet_endchar;
+
+
+fet_beginchar ("Coda", "coda");
+ save stickout, thin, thick, codawidth, codaheight;
+
+ stickout# = 0.35 staff_space#;
+ codawidth# = 2/3 staff_space#;
+ codaheight# = staff_space#;
+ define_pixels (codawidth, codaheight);
+
+ set_char_box (codawidth# + stickout#, codawidth# + stickout#,
+ codaheight# + stickout#, codaheight# + stickout#);
+
+ thin = 1.2 linethickness;
+ 0.1 (codaheight - 2 thin) = (codawidth - 2 thick);
+
+ penpos1 (thick, 0);
+ penpos2 (thin, -90);
+ penpos3 (thick, -180);
+ penpos4 (thin, -270);
+
+ x1l = -codawidth;
+ y2l = codaheight;
+ y1 = 0;
+ x2 = 0;
+ z3 = -z1;
+ z4 = -z2;
+
+ penlabels (1, 2, 3, 4);
+
+ fill z1l{up}
+ .. z2l{right}
+ .. z3l{down}
+ .. z4l{left}
+ .. cycle;
+ unfill z1r{up}
+ .. z2r{right}
+ .. z3r{down}
+ .. z4r{left}
+ .. cycle;
+
+ draw_gridline ((0, -h), (0, h), thin);
+ draw_gridline ((-w, 0), (w, 0), thin);
+fet_endchar;
+
+
+fet_beginchar ("Varied Coda", "varcoda");
+ save thin, thick, codawidth, codaheight;
+ thin# = 1.2 linethickness#;
+ thick# = 1.0 linethickness# + 0.25 staff_space#;
+ codawidth# = 2/3 staff_space#;
+ codaheight# = staff_space#;
+ define_pixels (thin, thick, codawidth, codaheight);
+
+ set_char_box (codawidth# + thick#, codawidth# + thick#,
+ codaheight# + thick#, codaheight# + thick#);
+
+ x1 = -codawidth + thick - .5 blot_diameter;
+ y1 = y2 - thin;
+ x2 = codawidth - thick + .5 blot_diameter;
+ y2 = codaheight;
+ draw_square_block (z1, z2);
+
+ x3 = -codawidth;
+ y3 = -codaheight;
+ x4 = x3 + thick;
+ y4 = y2;
+ draw_block (z3, z4);
+
+ labels (1, 2, 3, 4);
+
+ addto currentpicture also currentpicture scaled -1;
+
+ draw_gridline ((0, -h), (0, h), thin);
+ draw_gridline ((-w, 0), (w, 0), thin);
+fet_endchar;
+
+
+def draw_comma =
+ save alpha, thick, thin, ht;
+
+ alpha := 35;
+ thin# = 1.2 linethickness#;
+ thick# = 3 linethickness#;
+ ht# = .6 staff_space#;
+ define_pixels (thin, thick, ht);
+
+ set_char_box (0, .5 staff_space#, ht#, ht#);
+
+ penpos1 (thick, alpha);
+ penpos2 (thick, alpha + 90);
+ penpos3 (thin, 180 - alpha);
+ penpos4 (thin, 90 - alpha);
+
+ x3r = 0;
+ x1l = x3l;
+ y2r = -y4l = h;
+ z1 = z2;
+ z3 = z4;
+
+ fill z1l{dir (alpha + 90)}
+ .. z2r{dir alpha}
+ .. z1r{dir (alpha - 90)}
+ .. z3l{dir (270 - alpha)}
+ .. z4l{dir (180 - alpha)}
+ .. z3r{dir (90-alpha)}
+ .. cycle;
+enddef;
+
+
+fet_beginchar ("Right Comma", "rcomma");
+ draw_comma;
+ penlabels (1, 2, 3, 4);
+fet_endchar;
+
+
+fet_beginchar ("Left Comma", "lcomma");
+ draw_comma;
+ xy_mirror_char;
+fet_endchar;
+
+
+def draw_varcomma =
+ save thick, thin, ht, wd, alpha;
+
+ alpha := 35;
+ thin# = 1.2 linethickness#;
+ thick# = 3 linethickness#;
+ ht# = .6 staff_space#;
+ wd# = .25 staff_space#;
+ define_pixels (thin, thick, ht, alpha);
+
+ set_char_box (wd#, wd#, ht#, ht#);
+
+ z1 = (-b, -d);
+ z2 = (w, h);
+
+ draw_brush (z1, thin, z2, thick);
+enddef;
+
+
+fet_beginchar ("Right Varied Comma", "rvarcomma");
+ draw_varcomma;
+ labels (1, 2);
+fet_endchar;
+
+
+fet_beginchar ("Left Varied Comma", "lvarcomma");
+ draw_varcomma;
+ xy_mirror_char;
+fet_endchar;
+
+
+thick# := 1/24 designsize;
+define_blacker_pixels (thick);
+
+rthin := 0.075 * staff_space + 0.5 linethickness;
+rthick := 2 thick + rthin;
+
+
+def draw_arpeggio =
+ save alpha;
+ save ne, nw, se, sw;
+ save x, y;
+ pair ne, nw, se, sw;
+
+ alpha := -40;
+
+ nw = dir (alpha + 180);
+ ne = dir (alpha + 90);
+ se = dir alpha;
+ sw = dir (alpha - 90);
+
+ penpos1 (rthin, alpha + 90);
+ penpos2 (5/4 rthick, alpha);
+ penpos3 (3/4 rthick, alpha);
+ penpos4 (5/4 rthick, alpha);
+ penpos5 (rthin, alpha + 90);
+
+ z1 = (width / 2, height) - overshoot * se;
+ z2 = 2 [z4, (width / 2, height / 2)];
+ z3 = 1/2 [z2, z4];
+ x4 = 2/8 staff_space;
+ y4 = rthin;
+
+ z5 = 2 [z1, (width / 2, height / 2)];
+ z6 = z2l + 1/2 rthin * sw;
+ z7 = z4l + 1/2 rthin * sw + 1/2 rthin * se;
+ z8 = 2 [z6, (width / 2, height / 2)];
+ z9 = 2 [z7, (width / 2, height / 2)];
+
+ fill z1l{se}
+ -- z6
+ .. z3l
+ .. z7{se}
+ -- z5l
+ .. z5r{nw}
+ -- z8
+ .. z3r
+ .. z9{nw}
+ -- z1r
+ .. cycle;
+enddef;
+
+
+fet_beginchar ("Arpeggio", "arpeggio");
+ save height, overshoot, width;
+ height# = staff_space#;
+ width# = 0.8 height#;
+ overshoot# = 0.25 staff_space#;
+ define_pixels (height, overshoot, width);
+
+ set_char_box (0, width#, 0, height#);
+ draw_arpeggio;
+ penlabels (range 1 thru 9);
+
+ draw_staff (-2, 2, 0.0);
+fet_endchar;
+
+
+%
+% Extendable Trill symbol.
+% Not yet used
+% Rename me to Trill, rename Trill to Tr?
+%
+
+fet_beginchar ("Trill_element", "trill_element");
+ save height, overshoot;
+ height# = staff_space#;
+ width# = 0.8 height#;
+ overshoot# = 0.25 staff_space#;
+ define_pixels (height, overshoot, width);
+
+ set_char_box (0, height#, 0, width#);
+ draw_arpeggio;
+
+ currentpicture := currentpicture shifted -(width / 2, height / 2);
+ currentpicture := currentpicture rotated 90;
+ currentpicture := currentpicture shifted (height / 2, width / 2);
+fet_endchar;
+
+
+%
+% Arpeggio arrow by Chris Jackson <chris@fluffhouse.org.uk>
+%
+
+def draw_arpeggio_arrow =
+ save thinness, height, width, overshoot;
+ save nw, ne, se, sw;
+ save alpha;
+ save before_left, before_right, after_left, after_right;
+ save u_left, v_left, u_right, v_right;
+ pair nw, ne, se, sw;
+ path before_left, before_right, after_left, after_right;
+
+ height# = staff_space#;
+ width# = 0.8 height#;
+ overshoot# = 0.25 staff_space#;
+ define_pixels (height, overshoot, width);
+
+ set_char_box (0, width#, 0, height#);
+
+ alpha := -40;
+ nw = dir (alpha + 180);
+ ne = dir (alpha + 90);
+ se = dir alpha;
+ sw = dir (alpha - 90);
+
+ penpos1 (rthin, alpha + 90);
+ penpos2 (5/4 rthick, alpha);
+ penpos3 (5/4 rthick, 0);
+
+ z1 = (width / 2, height) - overshoot * se; % numbering is consistent
+ % with the arpeggio symbol
+ z2 = 2 [z4, (width / 2, height / 2)];
+ z3 = (0.5 width, 0.5 height);
+ z4 = (0.25 staff_space, rthin);
+ z6 = z2l + 1/2 rthin * sw;
+ z9 = (width / 2, height) + overshoot * se;
+
+ pickup pencircle scaled vround (0.5 rthin);
+
+ bot z10 = (0.5 w, 0);
+ lft z11 = (0.5 w - hround (0.8 w), 0.8 h);
+ rt z12 = (0.5 w + hround (0.8 w), 0.8 h);
+
+ before_left := z1l
+ -- z6{z6 - z1l}
+ .. {down}z3l;
+ after_left := (z3 + (0, -0.25 rthin / cosd (angle (nw))))
+ -- (z11 + 0.25 rthin * ne);
+ (u_left, v_left) = before_left intersectiontimes after_left;
+
+ before_right := (z12 + 0.25 rthin * nw)
+ -- (z3 + (0, -0.25 rthin / cosd (angle (nw))));
+ after_right := z3r{up}
+ .. z9{z1r - z9}
+ -- z1r;
+ (u_right, v_right) = before_right intersectiontimes after_right;
+
+ fill subpath (0, u_left) of before_left
+ .. subpath (v_left, infinity) of after_left
+ .. top z11
+ .. lft z11
+ .. {dir -50}(z11 + 0.25 rthin * sw)
+ .. (z10 + 0.25 rthin * sw){dir -70}
+ .. bot z10
+ .. {dir 70}(z10 + 0.25 rthin * se)
+ .. (z12 + 0.25 rthin * se){dir 50}
+ .. rt z12
+ .. top z12
+ .. subpath (0, u_right) of before_right
+ .. subpath (v_right, infinity) of after_right
+ .. cycle;
+
+ % mf doesn't handle pixel dropouts in outline objects, so we use
+ % `draw' if not called by mpost
+ if not known miterlimit:
+ pickup pencircle scaled 0.7 rthin;
+ draw z1
+ -- (z9 + 0.5 rthin * dir (alpha - 90));
+ fi;
+enddef;
+
+
+fet_beginchar ("Arpeggio arrow down", "arpeggio.arrow.M1");
+ draw_arpeggio_arrow;
+ penlabels (range 1 thru 12);
+fet_endchar;
+
+
+fet_beginchar ("Arpeggio arrow up", "arpeggio.arrow.1");
+ draw_arpeggio_arrow;
+ currentpicture := currentpicture scaled -1
+ shifted (w - feta_eps, h - feta_eps);
+fet_endchar;
+
+
+% Hmm
+input feta-slag;
+
+
+%
+% Railroad tracks. We define two variants of these -- both as slightly
+% tapered, comma-shaped curves and as two straight parallel slashes.
+%
+
+fet_beginchar ("Curved caesura", "caesura.curved");
+ save slant, space_between, clearance;
+ save alpha, pat;
+ save botthick, topthick;
+ save krom;
+ path pat;
+
+ botthick = 1.5 linethickness;
+ topthick = 2.5 linethickness;
+
+ pickup pencircle scaled botthick;
+
+ slant = 3.5;
+ space_between# = 0.6 staff_space#;
+ clearance# = 0.2 staff_space#;
+ height# = 1.2 staff_space#;
+
+ set_char_box (0, 2.0 staff_space#,
+ staff_space# - clearance#, height#);
+ define_pixels (clearance, height);
+ define_whole_pixels (space_between);
+
+ bot y1 = -d;
+ top y2 = h;
+
+ lft x1 = 0;
+ x2 = (y2 - y1) / slant;
+
+ krom = 10;
+
+ alpha = angle (z2 - z1);
+ penpos1 (botthick, alpha - krom);
+ penpos3 (botthick, alpha - krom + 90);
+
+ penpos2 (topthick, alpha + krom);
+ penpos4 (topthick, alpha + krom + 90);
+
+ z3 = z1;
+ z4 = z2;
+
+ penlabels (1, 2, 3, 4);
+
+ pat := z3r{(z1r - z1l)}
+ .. z4r{z2r-z2l}
+ .. z2r{z4l-z4r}
+ .. z4l{z2l-z2r}
+ .. z3l{z1l-z1r}
+ .. z1l{z3r-z3l}
+ .. cycle;
+ fill pat;
+ fill pat shifted (space_between, 0);
+fet_endchar;
+
+
+fet_beginchar ("Straight caesura", "caesura.straight");
+ save slant, space_between, clearance;
+ save thick, ne, pat;
+ path pat;
+ pair ne;
+
+ slant = 2.0;
+ thick = 2.88 linethickness;
+
+ space_between# = 0.56 staff_space#;
+ clearance# = 0.2 staff_space#;
+
+ set_char_box (0, 2.0 staff_space#,
+ staff_space# - clearance#, 1.2 staff_space#);
+ define_whole_pixels (space_between);
+
+ x1 = 0;
+ x2 = x1 + thick;
+ y1 = y2 = -d;
+
+ x3 = x4 + thick;
+ x4 = x1 + (h + d) / slant;
+ y3 = y4 = h;
+
+ ne = unitvector (z4 - z1);
+
+ z1a = z1 + blot_diameter * ne;
+ z1b = z1 + blot_diameter * right;
+ z2a = z2 + blot_diameter * ne;
+ z2b = z2 + blot_diameter * left;
+
+ z3a = z3 - blot_diameter * ne;
+ z3b = z3 + blot_diameter * left;
+ z4a = z4 - blot_diameter * ne;
+ z4b = z4 + blot_diameter * right;
+
+ pat = z1a{-ne}
+ .. {right}z1b
+ -- z2b{right}
+ .. {ne}z2a
+ -- z3a{ne}
+ .. {left}z3b
+ -- z4b{left}
+ .. {-ne}z4a
+ -- cycle;
+
+ fill pat;
+ fill pat shifted (space_between, 0);
+
+ labels(range 1 thru 4);
+ labels(1a, 1b, 2a, 2b, 3a, 3b, 4a, 4b);
+fet_endchar;
+
+fet_endgroup ("scripts");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-slag.mf b/muse2/share/scoreglyphs/feta-original/feta-slag.mf
new file mode 100644
index 00000000..3b054103
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-slag.mf
@@ -0,0 +1,315 @@
+% -*- Fundamental -*- (emacs-20 mf mode sucks)
+% feta-slag.mf -- implement trill symbols
+%
+% source file of the Feta (definitely not an abbreviation for Font-En-Tja)
+% music font
+%
+% (c) 1998--2009 Jan Nieuwenhuizen <janneke@gnu.org>
+%
+
+% this file is included by feta-scripts.mf
+
+trill_thin# = 0.1 staff_space# + 0.6 stafflinethickness#;
+trill_stemwidth# = trill_thin#;
+define_pixels (trill_thin);
+define_whole_blacker_pixels (trill_stemwidth);
+
+trill_thick = 1/2 staff_space;
+trill_overlap = 1/6 staff_space;
+
+trill_width# = 5/6 staff_space#;
+trill_height# = 1/2 staff_space#;
+define_pixels (trill_height);
+define_whole_pixels (trill_width);
+
+pair trill_ne;
+trill_ne := unitvector ((2, 3));
+
+
+%
+% The trill element sticks out on both the left and right side
+% of the normal bbox, so you can glue them together easily.
+%
+% `ending' is either 0 for none, 1 for left, or 2 for right.
+%
+
+def draw_trillelement (expr offset, ending) =
+ clearxy;
+
+begingroup;
+ save nw, pat, nw_dist, ne_dist;
+ pair nw, nw_dist, ne_dist;
+ path pat;
+
+ pickup pencircle scaled trill_thin;
+
+ x1 = -.5 trill_width;
+ y1 = 0;
+ z3 = whatever * trill_ne + z1;
+ top y3 = vround trill_height;
+ z2 = z3 - (trill_thick - trill_thin) * trill_ne;
+
+ bot z3' = (top z3) scaled -1;
+
+ nw = unitvector (z2 - z3');
+ ne_dist = (nw rotated -90) * 0.5 trill_thin;
+ nw_dist = (trill_ne rotated 90) * 0.5 trill_thin;
+
+ z5 = whatever * trill_ne + (z1 - nw_dist);
+ z5 = whatever * nw + (z3' - ne_dist);
+
+ pat := z5
+ -- (z1 - nw_dist){-trill_ne}
+ -- (z1 + nw_dist){trill_ne}
+ -- (z3 + nw_dist){trill_ne}
+ .. top z3{right}
+ .. (z3 + ne_dist){-nw};
+ pat := pat
+ -- pat scaled -1 shifted (-feta_eps, -feta_eps)
+ -- cycle;
+ pat := pat shifted (offset, 0);
+ fill pat;
+
+ z4 = z1 - trill_ne * trill_overlap;
+ x4 := hround (x4 + 0.5 trill_thin) - 0.5 trill_thin;
+
+ pat := (z4 - nw_dist){-trill_ne}
+ .. bot z4{left}
+ .. lft z4{up}
+ .. (z4 + nw_dist){trill_ne}
+ -- (z1 + nw_dist){trill_ne}
+ -- (z1 - nw_dist){-trill_ne}
+ -- cycle;
+
+ if ending = 1:
+ fill pat shifted (offset, 0);
+ elseif ending = 2:
+ pat := pat scaled -1 shifted (-feta_eps, -feta_eps);
+ fill pat shifted (offset, 0);
+ fi;
+endgroup;
+enddef;
+
+
+fet_beginchar ("trilelement", "trilelement");
+ set_char_box (.5 trill_width#, .5 trill_width#,
+ trill_height#, trill_height#);
+
+ draw_trillelement (0, 0);
+ labels (1, 2, 3, 3', 4, 5, 5');
+fet_endchar;
+
+
+fet_beginchar ("prall", "prall");
+ set_char_box (trill_width#, trill_width#,
+ trill_height#, trill_height#);
+
+ draw_trillelement (-hround (.5 trill_width), 1);
+ draw_trillelement (-hround (.5 trill_width) + trill_width, 2);
+fet_endchar;
+
+
+fet_beginchar ("mordent", "mordent");
+ set_char_box (trill_width#, trill_width#,
+ 4/3 trill_height#, 4/3 trill_height#);
+
+ draw_trillelement (-hround (.5 trill_width), 1);
+ draw_trillelement (-hround (.5 trill_width) + trill_width, 2);
+
+ clearxy;
+
+ pickup pencircle scaled trill_stemwidth;
+
+ top y1 = h;
+ bot y2 = -d;
+ x1 = x2;
+ x2 = 0;
+
+ draw_gridline (z2, z1, trill_stemwidth);
+
+ labels (1, 2);
+fet_endchar;
+
+
+fet_beginchar ("prallprall", "prallprall");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ trill_height#, trill_height#);
+
+ draw_trillelement (-trill_width, 1);
+ draw_trillelement (0, 0);
+ draw_trillelement (trill_width, 2);
+fet_endchar;
+
+
+fet_beginchar ("prallmordent", "prallmordent");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ 4/3 trill_height#, 4/3 trill_height#);
+
+ draw_trillelement (-trill_width, 1);
+ draw_trillelement (0, 0);
+ draw_trillelement (trill_width, 2);
+
+ clearxy;
+
+ pickup pencircle scaled trill_stemwidth;
+
+ top y1 = h;
+ bot y2 = -d;
+ x1 = x2 ;
+ x2 = good.x (.5 trill_width);
+
+ draw_gridline (z2, z1, trill_stemwidth);
+
+ labels (1, 2);
+fet_endchar;
+
+
+save remember_pic;
+picture remember_pic;
+
+
+fet_beginchar ("upprall", "upprall");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ trill_height#, trill_height#);
+
+ draw_trillelement (-trill_width, 1);
+ draw_trillelement (0, 0);
+ draw_trillelement (trill_width, 2);
+
+ z11 = z4 shifted (-trill_width, 0);
+ z12 = z11 + (0, -2 trill_height);
+
+ penpos11 (trill_thin, angle (trill_ne) - 90);
+ penpos12 (trill_thin, angle (trill_ne yscaled -1) + 90);
+ penlabels (11, 12);
+
+ pickup pencircle scaled trill_stemwidth;
+
+ fill z11l{-trill_ne}
+ .. z12l{trill_ne yscaled -1}
+ .. bot z12
+ .. rt z12
+ .. z12r{-trill_ne yscaled -1}
+ .. z11r{trill_ne}
+ -- cycle;
+
+ remember_pic := currentpicture;
+fet_endchar;
+
+
+fet_beginchar ("upmordent", "upmordent");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ 4/3 trill_height#, 4/3 trill_height#);
+
+ currentpicture := remember_pic;
+
+ clearxy;
+
+ pickup pencircle scaled trill_stemwidth;
+
+ top y1 = h;
+ bot y2 = -d;
+ x1 = x2;
+ x2 = good.x (.5 trill_width);
+
+ draw_gridline (z2, z1, trill_stemwidth);
+
+ labels (1, 2);
+fet_endchar;
+
+
+fet_beginchar ("pralldown", "pralldown");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ trill_height#, trill_height#);
+
+ currentpicture := remember_pic xscaled -1;
+fet_endchar;
+
+
+fet_beginchar ("downprall", "downprall");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ trill_height#, trill_height#);
+
+ draw_trillelement (-trill_width, 1);
+ draw_trillelement (0, 0);
+ draw_trillelement (trill_width, 2);
+
+ z11 = z4 shifted (-trill_width, 0);
+ z12 = z11 + (0, 2 trill_height);
+
+ penpos11 (trill_thin, angle (trill_ne xscaled -1) - 90);
+ penpos12 (trill_thin, angle (trill_ne) - 90);
+ penlabels (11, 12);
+
+ pickup pencircle scaled trill_stemwidth;
+
+ fill z11l{trill_ne xscaled -1}
+ .. z12l{trill_ne}
+ .. top z12
+ .. rt z12
+ .. z12r{-trill_ne}
+ .. z11r{-trill_ne xscaled -1}
+ -- cycle;
+
+ remember_pic := currentpicture;
+fet_endchar;
+
+
+fet_beginchar ("downmordent", "downmordent");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ 4/3 trill_height#, 4/3 trill_height#);
+
+ currentpicture := remember_pic;
+
+ clearxy;
+
+ pickup pencircle scaled trill_stemwidth;
+
+ top y1 = h;
+ bot y2 = -d;
+ x1 = x2;
+ x2 = good.x (.5 trill_width);
+
+ draw_gridline (z2, z1, trill_stemwidth);
+
+ labels (1, 2);
+fet_endchar;
+
+
+fet_beginchar ("prallup", "prallup");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ trill_height#, trill_height#);
+
+ currentpicture := remember_pic xscaled -1;
+fet_endchar;
+
+
+fet_beginchar ("lineprall", "lineprall");
+ set_char_box (1.5 trill_width#, 1.5 trill_width#,
+ trill_height#, 4 trill_height#);
+
+ draw_trillelement (-trill_width, 1);
+
+ labels (1, 2, 3, 3', 4, 5, 5');
+
+ pickup pencircle scaled trill_stemwidth;
+
+ penpos10 (trill_stemwidth, 0);
+ penpos11 (trill_stemwidth, 0);
+
+ x10l = x4 - .5 trill_thin - trill_width;
+ y10 = y4;
+ z11 = z10 + (0, h);
+
+ penlabels (10, 11);
+
+ fill z11l
+ .. top z11
+ .. z11r
+ -- z10r
+ -- z10l
+ -- cycle;
+
+ draw_trillelement (0, 0);
+ draw_trillelement (trill_width, 2);
+fet_endchar;
diff --git a/muse2/share/scoreglyphs/feta-original/feta-test-generic.mf b/muse2/share/scoreglyphs/feta-original/feta-test-generic.mf
new file mode 100644
index 00000000..1ade03f2
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-test-generic.mf
@@ -0,0 +1,20 @@
+%
+% test stuff.
+% in a separate file to avoid tainting non-test font files for testing.
+%
+
+%input feta-eindelijk;
+input feta-toevallig;
+%input feta-puntje;
+%input feta-bolletjes;
+%input feta-arrow;
+%input feta-schrift;
+%input feta-schrift;
+%input feta-banier;
+% input feta-slag;
+%input feta-klef;
+%input feta-haak;
+% input feta-haak;
+%input feta-timesig;
+%input feta-pendaal;
+%input feta-accordion;
diff --git a/muse2/share/scoreglyphs/feta-original/feta-test11.mf b/muse2/share/scoreglyphs/feta-original/feta-test11.mf
new file mode 100644
index 00000000..ad21720a
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-test11.mf
@@ -0,0 +1,15 @@
+% feta-test11.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 11;
+test := 1;
+
+% smoked cheese
+% test := -1;
+
+input feta-generic;
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-test13.mf b/muse2/share/scoreglyphs/feta-original/feta-test13.mf
new file mode 100644
index 00000000..28abf42c
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-test13.mf
@@ -0,0 +1,16 @@
+% feta-test13.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 13;
+test := 1;
+
+% smoked cheese
+% test := -1;
+
+input feta-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-test16.mf b/muse2/share/scoreglyphs/feta-original/feta-test16.mf
new file mode 100644
index 00000000..eaa280aa
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-test16.mf
@@ -0,0 +1,16 @@
+% feta-test16.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 16;
+test := 1;
+
+% smoked cheese
+% test := -1;
+
+input feta-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-test20.mf b/muse2/share/scoreglyphs/feta-original/feta-test20.mf
new file mode 100644
index 00000000..5a58be3d
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-test20.mf
@@ -0,0 +1,16 @@
+% feta-test20.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 20;
+test := 1;
+
+% smoked cheese
+% test := -1;
+
+input feta-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-test23.mf b/muse2/share/scoreglyphs/feta-original/feta-test23.mf
new file mode 100644
index 00000000..5a25b469
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-test23.mf
@@ -0,0 +1,16 @@
+% feta-test23.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 23;
+test := 1;
+
+% smoked cheese
+% test := -1;
+
+input feta-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta-test26.mf b/muse2/share/scoreglyphs/feta-original/feta-test26.mf
new file mode 100644
index 00000000..e9e15218
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-test26.mf
@@ -0,0 +1,15 @@
+% feta-test26.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 26;
+test := 1;
+
+% smoked cheese
+% test := -1;
+
+input feta-generic;
+
+
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta-timesig.mf b/muse2/share/scoreglyphs/feta-original/feta-timesig.mf
new file mode 100644
index 00000000..ffaa1883
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-timesig.mf
@@ -0,0 +1,108 @@
+%
+% feta-timesig.mf -- implement Time Signatures
+%
+% source file of the Feta (not an abbreviation of Font-En-Tja) music font
+%
+% (c) 1998--2009 Mats Bengtsson <matsb@s3.kth.se>,
+% Christian Mondrup <scancm@biobase.dk>
+
+fet_begingroup ("timesig");
+
+
+%
+% Originally by Mats B. nuked by Han-Wen, inspired by
+% Baerenreiter BA320 (Bach Cello Suites, Suite III).
+%
+% Notes:
+%
+% * The inside curve of the C is rather straight.
+% * The outside curve of the C is rather round.
+% * Right tips of the C point slightly outward.
+% * Lower tip protrudes to the right very slightly.
+%
+
+def draw_C =
+ save hair, bulb_rad, left_fatness;
+ save left_width, right_width;
+ save width, lower_offset;
+
+ width# := 1.8 staff_space# - stafflinethickness#;
+
+ left_width := 1.0 staff_space;
+ right_width := 0.8 staff_space;
+
+ hair := stafflinethickness;
+
+ bulb_rad := 0.40 staff_space - .6 stafflinethickness;
+ left_fatness := 0.55 * staff_space;
+ lower_offset := 0.3 stafflinethickness;
+
+ set_char_box (0, width#, staff_space#, staff_space#);
+
+ d := d - feta_shift;
+
+ x1r = w;
+ x3r = 0;
+ y1r = .45 h;
+ y2r = h + vround (.5 stafflinethickness_rounded);
+ y4r = -d - vround (.5 stafflinethickness_rounded);
+ x2 = x4;
+ x2 = x3r + h;
+ y3r = .5 (h - d);
+
+ x5r = x1r + lower_offset;
+ y5r = -0.37 h;
+
+ penpos1 (hair, 10);
+ penpos2 (stafflinethickness_rounded, 90);
+ penpos3 (left_fatness, 180);
+ penpos4 (stafflinethickness_rounded, -90);
+ penpos5 (hair, -13);
+
+ draw_bulb (-1, z1l, z1r, bulb_rad, .8);
+
+ save s;
+ s := 0.735;
+
+ fill z1l{dir (100)}
+ .. z2l{left}
+ ..tension 0.8.. z3l{down}
+ ..tension 0.8.. z4l{right}
+ .. simple_serif (z5l, z5r, -90)
+ .. z4r{left}
+ .. super_curvelet (z4r, z3r, s, -1)
+ .. z3r{up}
+ .. super_curvelet (z3r, z2r, s, 1)
+ .. z2r{right}
+ .. {dir (-80)}z1r
+ -- cycle;
+
+ penlabels (1, 2, 3, 4, 5);
+
+ draw_staff (-2, 2, 0);
+enddef;
+
+
+fet_beginchar ("4/4 meter", "C44");
+ draw_C;
+fet_endchar;
+
+
+fet_beginchar ("2/2 meter", "C22");
+ save eccentricity, top_stemlen, bottom_stemlen, thick, left_pos;
+
+ draw_C;
+
+ eccentricity = -1.75 stafflinethickness - 0.025 staff_space;
+ top_stemlen# = bottom_stemlen# = 1.4 staff_space#;
+ thick# = stafflinethickness# + 0.05 staff_space#;
+ define_whole_pixels (top_stemlen, bottom_stemlen);
+ define_whole_blacker_pixels (thick);
+
+ bottom_stemlen := bottom_stemlen - feta_shift;
+
+ draw_block ((x2 + eccentricity, -bottom_stemlen),
+ (x2 + eccentricity + thick, top_stemlen));
+fet_endchar;
+
+fet_endgroup ("timesig");
diff --git a/muse2/share/scoreglyphs/feta-original/feta-toevallig.mf b/muse2/share/scoreglyphs/feta-original/feta-toevallig.mf
new file mode 100644
index 00000000..48061fcd
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta-toevallig.mf
@@ -0,0 +1,1308 @@
+%
+% feta-toevallig.mf -- implement Accidentals
+%
+% (c) 1997--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+
+
+%
+% also show in other configuration wrt staff lines.
+%
+def draw_shifted_too =
+if test > 0:
+ fet_beginchar ("shifted too", "");
+ set_char_box (0, 0, 0, 0);
+ currentpicture := remember_pic;
+
+ draw_staff (-2, 2, 0.5);
+ fet_endchar;
+fi;
+enddef;
+
+
+%
+% Accidentals from various sources, notably
+%
+% Baerenreiter edition of Schuberts `Auf dem Strom' (sharp, natural)
+% F Hofmeister edition of Muellers `Etueden fuer Horn' (double sharp, flat)
+%
+
+
+%
+% Naming for accidentals (including microtonal variants):
+%
+% SHARPBASE[.SLASHES.STEMS]
+% FLATBASE[.MODIFIER]
+%
+% Examples:
+%
+% sharp.slashslash.stem
+% mirroredflat.flat
+%
+%
+
+
+fet_begingroup ("accidentals");
+
+%
+% Draw an arrow
+%
+% * `stemslant' gives the direction of the stem's left boundary
+% (needed for brushed stems, equals "up" for straight stems)
+% * `extend' is used to make the stem longer or shorter (if negative);
+% different kinds of accidentals need different values here
+%
+def draw_arrow (expr attach, stemwidth, stemslant, extend, pointingdown) =
+begingroup;
+ save htip; % tip height
+ save wwing; % wing `radius'
+ save angle_wing_bot, angle_wing_top, angle_tip;
+ save upshift;
+ clearxy;
+
+ wwing := 0.26 stemwidth;
+ htip := staff_space * 0.85 + stafflinethickness - wwing;
+
+ % `flip' is used to reflect the arrow vertically
+ % if arrow points downward
+ transform flip;
+ if pointingdown:
+ flip = identity reflectedabout (origin, right);
+ else:
+ flip = identity;
+ fi;
+
+ z1 = attach shifted (-stemwidth / 2, 0);
+ upshift := max (0, wwing + 0.1 staff_space + extend);
+ z2 = z1 shifted (((unitvector stemslant)
+ scaled upshift) transformed flip);
+
+ z7 = attach shifted ((stemwidth/2),0);
+ z6 = z7 shifted (((unitvector (-xpart stemslant, ypart stemslant))
+ scaled upshift) transformed flip);
+ z2 - z3 = ( 0.38 staff_space, 0.05 htip) transformed flip;
+ z6 - z5 = (-0.38 staff_space, 0.05 htip) transformed flip;
+
+ z4 = attach shifted ((-0.2 stemwidth, upshift + htip)
+ transformed flip);
+ z4'= attach shifted (( 0.2 stemwidth, upshift + htip)
+ transformed flip);
+
+ % `angle_wing_bot' is the angle at which the arc
+ % from z2 to z3a enters z3a
+ % `angle_wing_top' is the angle at which the arc
+ % from z3b to z4 leaves z3b
+ % `angle_tip' is the angle at which the arc
+ % from z4 to z4' leaves z4
+ angle_wing_bot = 30;
+ angle_wing_top = 55;
+ angle_tip = 68;
+
+ z3a = z3 shifted ((((dir angle_wing_bot) rotated -90)
+ scaled wwing) transformed flip);
+ z3b = z3 shifted ((((dir angle_wing_top) rotated 90)
+ scaled wwing) transformed flip);
+
+ z5a = z5 shifted ((((dir (180 - angle_wing_bot)) rotated 90)
+ scaled wwing) transformed flip);
+ z5b = z5 shifted ((((dir (180 - angle_wing_top)) rotated -90)
+ scaled wwing) transformed flip);
+
+ % Draw the arrow
+ pickup pencircle scaled 1;
+ fill z1
+ -- z2{stemslant transformed flip}
+ .. {(-dir angle_wing_bot) transformed flip}z3a
+ .. z3b{(dir angle_wing_top) transformed flip}
+ .. z4{(dir angle_tip) transformed flip}
+ .. z4'{(dir (-angle_tip)) transformed flip}
+ .. {(dir (-angle_wing_top)) transformed flip}z5b
+ .. z5a{(-dir (-angle_wing_bot)) transformed flip}
+ .. z6{((-stemslant) reflectedabout (origin, up)) transformed flip}
+ -- z7
+ -- cycle;
+
+ labels (range 0 thru 7, 4', 3a, 3b, 5a, 5b);
+endgroup;
+enddef;
+
+save remember_pic;
+picture remember_pic;
+
+save sharp_beamheight;
+sharp_beamheight# := 0.3 staff_space# + stafflinethickness#;
+
+%
+% The beams of most sharps have horizontal endings (as if drawn with
+% a square pen). [Wanske] does not mention this, so we'll just ignore
+% this fact.
+%
+
+def draw_meta_sharp (expr width, offset) =
+ save beamwidth, beamslope;
+ save ne, nw_dist;
+ pair ne, nw_dist;
+
+ beamwidth := width;
+
+ define_whole_vertical_blacker_pixels (sharp_beamheight);
+
+ clearxy;
+
+ beamslope = sharp_beamheight / beamwidth;
+
+ pickup pencircle scaled 2 blot_diameter;
+
+ rt x2 - lft x1 = beamwidth;
+ z2 = z1 + whatever * (beamwidth, sharp_beamheight);
+ .5 [z1, z3] = (.5 w, offset);
+ x3 = x2;
+ top y2 - bot y3 = sharp_beamheight;
+ x4 = x1;
+ top y1 - bot y4 = sharp_beamheight;
+
+ ne = unitvector (z2 - z1);
+ nw_dist = (ne rotated 90) * blot_diameter;
+
+ fill lft z1{up}
+ ... (z1 + nw_dist){ne}
+ -- (z2 + nw_dist){ne}
+ ... rt z2{down}
+ -- rt z3{down}
+ ... (z3 - nw_dist){-ne}
+ -- (z4 - nw_dist){-ne}
+ ... lft z4{up}
+ -- cycle;
+
+ labels (1, 2, 3, 4);
+enddef;
+
+
+def draw_sharp(expr arrowup, arrowdown) =
+ save stem, stemx, stemwidth;
+ save outer_space, interbeam;
+ save stemlength, extendleft, extendright, height, depth;
+
+ stemwidth# := stafflinethickness# + .05 staff_space#;
+ define_whole_blacker_pixels (stemwidth);
+
+ interbeam := 1.05 staff_space_rounded;
+
+ stemlength# := 1.5 staff_space#;
+ define_pixels (stemlength);
+
+ height# = stemlength#;
+ depth# = stemlength#;
+ extendright# = 0;
+ extendleft# = 0;
+ if arrowup:
+ height# := height# + 1.2 staff_space#;
+ extendright# := extendright# + 1.5 stafflinethickness#;
+ fi;
+ if arrowdown:
+ depth# := depth# + 1.2 staff_space#;
+ extendleft# := extendleft# + 1.5 stafflinethickness#;
+ fi;
+ define_pixels (extendleft, extendright);
+ set_char_box (extendleft#, 1.1 staff_space#, depth#, height#);
+
+ stem := 7 / 16 * w;
+ stemx := hround stem;
+ outer_space := hround ((w - stemx - stemwidth) / 2);
+
+ w := 2 outer_space + stemx + stemwidth;
+ d := d - feta_space_shift;
+
+ draw_meta_sharp (w, -.5 interbeam);
+ draw_meta_sharp (w, -.5 interbeam + vround interbeam);
+
+ % expand the charbox so that it encloses the whole arrow;
+ % this must not happen earlier because some commands above
+ % still rely on the old width
+ w := w + extendright;
+
+ pickup pencircle scaled stemwidth;
+
+ lft x5 = lft x6 = outer_space;
+ lft x7 = lft x8 = outer_space + stemx;
+ bot y5 = -stemlength;
+ top y6 = vround (1.5 staff_space - stem * beamslope);
+ bot y7 = -top y6 + feta_space_shift;
+ top y8 = stemlength;
+
+ labels (5, 6, 7, 8);
+
+ draw_gridline (z5, z6, stemwidth);
+ draw_gridline (z7, z8, stemwidth);
+
+ if arrowup:
+ draw_arrow (z8, stemwidth, up,
+ stafflinethickness / 2 + stemwidth / 2, false);
+ fi;
+ if arrowdown:
+ draw_arrow (z5, stemwidth, up,
+ stafflinethickness / 2 + stemwidth / 2, true);
+ fi;
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+enddef;
+
+
+fet_beginchar ("Sharp", "sharp");
+ draw_sharp (false, false);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Sharp (arrow up)", "sharp.arrowup");
+ draw_sharp (true, false);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Sharp (arrow down)", "sharp.arrowdown");
+ draw_sharp (false, true);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Sharp (arrows up and down)", "sharp.arrowboth");
+ draw_sharp (true, true);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("1/2 Sharp", "sharp.slashslash.stem");
+ save stem, stemwidth;
+ save outer_space, interbeam;
+
+ stemwidth# := stafflinethickness# + .05 staff_space#;
+ define_whole_blacker_pixels (stemwidth);
+
+ interbeam := 1.05 staff_space_rounded;
+
+ set_char_box (0, 0.7 staff_space#,
+ 1.5 staff_space#, 1.5 staff_space#);
+
+ stem := 7 / 16 * w;
+ outer_space := hround ((w - stemwidth) / 2);
+
+ w := 2 outer_space + stemwidth;
+ d := d - feta_space_shift;
+
+ draw_meta_sharp (w, -.5 interbeam);
+ draw_meta_sharp (w, -.5 interbeam + vround interbeam);
+
+ pickup pencircle scaled stemwidth;
+
+ lft x5 = lft x6 = outer_space;
+ top y6 = vround (1.5 staff_space - .5 stem);
+ bot y5 = -top y6 + feta_space_shift;
+
+ labels (5, 6);
+
+ draw_gridline (z5, z6, stemwidth);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Sharp (3 beams)", "sharp.slashslashslash.stemstem");
+ save stem, stemx, stemwidth;
+ save outer_space, interbeam;
+ save sharp_beamheight;
+
+ sharp_beamheight# := 0.22 staff_space# + stafflinethickness#;
+
+ stemwidth# := stafflinethickness# + .05 staff_space#;
+ define_whole_blacker_pixels (stemwidth);
+
+ interbeam := 1.2 staff_space_rounded;
+
+ set_char_box (0, 1.1 staff_space#,
+ 1.5 staff_space#, 1.5 staff_space#);
+
+ stem := 7 / 16 * w;
+ stemx := hround stem;
+ outer_space := hround ((w - stemx - stemwidth) / 2);
+
+ w := 2 outer_space + stemx + stemwidth;
+ d := d - feta_space_shift;
+
+ draw_meta_sharp (.88 w, -.5 interbeam);
+ draw_meta_sharp (.88 w, -.5 interbeam + vround interbeam);
+ sharp_beamheight# := 1/.88 sharp_beamheight#;
+ draw_meta_sharp (w, 0);
+
+ pickup pencircle scaled stemwidth;
+
+ lft x5 = lft x6 = outer_space;
+ lft x7 = lft x8 = outer_space + stemx;
+ bot y5 = -d;
+ top y6 = vround (1.5 staff_space - stem * beamslope);
+ bot y7 = -top y6 + feta_space_shift;
+ top y8 = h;
+
+ labels (5, 6, 7, 8);
+
+ draw_gridline (z5, z6, stemwidth);
+ draw_gridline (z7, z8, stemwidth);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("1/2 Sharp (3 beams)", "sharp.slashslashslash.stem");
+ save stem, stemx, stemwidth;
+ save outer_space, interbeam;
+ save sharp_beamheight;
+
+ sharp_beamheight# := 0.22 staff_space# + stafflinethickness#;
+
+ stemwidth# := stafflinethickness# + .05 staff_space#;
+ define_whole_blacker_pixels (stemwidth);
+
+ interbeam := 1.2 staff_space_rounded;
+
+ set_char_box (0, 0.95 staff_space#,
+ 1.3 staff_space#, 1.3 staff_space#);
+
+ stem := 7 / 16 * w;
+ outer_space := hround ((w - stemwidth) / 2);
+
+ w := 2 outer_space + stemwidth;
+ d := d - feta_space_shift;
+
+ draw_meta_sharp (.8 w, -.5 interbeam);
+ draw_meta_sharp (.8 w, -.5 interbeam + vround interbeam);
+ sharp_beamheight# := 1/.8 sharp_beamheight#;
+ draw_meta_sharp (w, 0);
+
+ pickup pencircle scaled stemwidth;
+
+ lft x5 = lft x6 = outer_space;
+ top y6 = vround (1.5 staff_space - .5 stem);
+ bot y5 = -top y6 + feta_space_shift;
+ labels (5, 6);
+
+ draw_gridline (z5, z6, stemwidth);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("3/4 Sharp", "sharp.slashslash.stemstemstem");
+ save stem, stemx, stemwidth;
+ save outer_space, interbeam;
+
+ stemwidth# := stafflinethickness# + .05 staff_space#;
+ define_whole_blacker_pixels (stemwidth);
+
+ interbeam := 1.05 staff_space_rounded;
+
+ set_char_box (0, 1.6 staff_space#,
+ 1.5 staff_space#, 1.5 staff_space#);
+
+ stem := 9 / 32 * w;
+ stemx := hround stem;
+ outer_space := hround ((w - 2 stemx - stemwidth) / 2);
+
+ w := 2 outer_space + 2 stemx + stemwidth;
+ d := d - feta_space_shift;
+
+ draw_meta_sharp (w, -.5 interbeam);
+ draw_meta_sharp (w, -.5 interbeam + vround interbeam);
+
+ pickup pencircle scaled stemwidth;
+
+ lft x5 = lft x6 = outer_space;
+ lft x7 = lft x8 = outer_space + stemx;
+ lft x9 = lft x10 = outer_space + 2 stemx;
+ bot y5 = -d;
+ top y6 = vround (1.5 staff_space - 2 stem * beamslope);
+ bot y9 = -top y6 + feta_space_shift;
+ top y10 = h;
+ y7 = .5 [y5, y9];
+ y8 = .5 [y6, y10];
+
+ labels (5, 6, 7, 8, 9, 10);
+
+ draw_gridline (z5, z6, stemwidth);
+ draw_gridline (z7, z8, stemwidth);
+ draw_gridline (z9, z10, stemwidth);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+%
+% The stems of the natural are brushed (at least, in Barenreiter SCS)
+%
+
+def draw_natural (expr arrowup, arrowdown) =
+ save stemwidth, top_stem_thick;
+ save ne, pat_top, pat_bottom;
+ save depth, height, extendleft, extendright, stemlength;
+ save brush_scale_up, brush_scale_down;
+ pair ne;
+ path pat_top, pat_bottom;
+
+ top_stem_thick# = stafflinethickness# + .10 staff_space#;
+ stemwidth# = 0.09 staff_space# + .5 stafflinethickness#;
+ define_whole_blacker_pixels (top_stem_thick, stemwidth);
+
+ stemlength# = 1.5 staff_space#;
+ define_pixels (stemlength);
+
+ height# = stemlength#;
+ depth# = stemlength#;
+ extendleft# = 0;
+ extendright# = 0;
+ if arrowup:
+ extendleft# := 3 stafflinethickness#;
+ height# := height# + 1.2 staff_space#;
+ fi;
+ if arrowdown:
+ extendright# := 3.15 stafflinethickness#;
+ depth# := depth# + 1.2 staff_space#;
+ fi;
+ define_pixels (extendright);
+
+ set_char_box (extendleft#, 2/3 staff_space#, depth#, height#);
+
+ d := d - feta_space_shift;
+
+ pickup pencircle scaled stemwidth;
+
+ brush_scale_up := 1.0;
+ brush_scale_down := 1.0;
+ % to look nice, arrowed stems must be less brushed
+ if arrowup:
+ brush_scale_up := 0.85;
+ fi;
+ if arrowdown:
+ brush_scale_down := 0.85;
+ fi;
+
+ penpos1 (top_stem_thick, 0);
+ penpos3 (top_stem_thick, 0);
+ penpos2 (stemwidth, 0);
+ penpos4 (stemwidth, 0);
+ % z1' and z3' are needed for the arrowed accidentals
+ penpos1' (top_stem_thick * brush_scale_up, 0);
+ penpos3' (top_stem_thick * brush_scale_down, 0);
+
+ x2r = w;
+ x4l = 0;
+ x3 = x3' = x2;
+ x1 = x1' = x4;
+
+ y1 = y1' = stemlength;
+ y3 = y3' = -stemlength;
+ top y2 = vround (staff_space - 3/2 stafflinethickness);
+ y4 = -y2 + feta_space_shift;
+
+ pat_bottom := z4r{z4r - z1r}
+ .. bot z4
+ .. z4l{z1l - z4l};
+ fill simple_serif (z1'l, z1'r, -30)
+ -- pat_bottom
+ -- cycle;
+
+ pat_top := z2r{z2r - z3r}
+ .. top z2
+ .. z2l{z3l - z2l};
+ fill simple_serif (z3'l, z3'r, 30)
+ -- pat_top
+ -- cycle;
+
+ ne = (x2 - x4, stafflinethickness);
+
+ z11' = z3l + whatever * (z2l - z3l);
+ y11' = vround (.5 (staff_space - stafflinethickness));
+ z11 = z11' + whatever * ne;
+ x11 = x12;
+ z12 = directionpoint -ne of pat_top;
+ z13 = z12 + whatever * ne;
+ x13 = x1;
+ z14 = z11 + whatever * ne;
+ x14 = x1;
+
+ z21' = z4r + whatever * (z1r - z4r);
+ y21' = -y11' + feta_space_shift;
+ z21 = z21' + whatever * ne;
+ x21 = x22;
+ z22 = directionpoint -ne of pat_bottom;
+ z23 = z22 + whatever * ne;
+ x23 = x3;
+ z24 = z21 + whatever * ne;
+ x24 = x3;
+
+ fill z11
+ -- z12
+ -- z13
+ -- z14
+ -- cycle;
+ fill z21
+ -- z22
+ -- z23
+ -- z24
+ -- cycle;
+
+ penlabels (1, 1', 2, 3, 3', 4);
+ labels (11, 11', 12, 13, 14, 21, 21', 22, 23, 24);
+
+ if arrowup:
+ draw_arrow (z1, top_stem_thick * brush_scale_up,
+ z1'l - z4l, stafflinethickness / 2, false);
+ fi;
+ if arrowdown:
+ draw_arrow (z3, top_stem_thick * brush_scale_down,
+ z2r - z3'r, stafflinethickness / 2, true);
+ w := w + extendright;
+ fi;
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+enddef;
+
+
+fet_beginchar ("Natural", "natural");
+ draw_natural (false, false);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Natural (arrow up)", "natural.arrowup");
+ draw_natural (true, false);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Natural (arrow down)", "natural.arrowdown");
+ draw_natural (false, true);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Natural (arrows up and down)", "natural.arrowboth");
+ draw_natural (true, true);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+%
+% Dedicated to my mom. (3/10/97)
+%
+% Mamma, ik hou van je; kom je alsjeblieft terug?
+% -- HW
+%
+%
+% TODO: remove crook_fatness
+% TODO: document, simplify!
+%
+
+def draw_meta_flat (expr xcenter, w, crook_fatness, arrowup, arrowdown) =
+ save crook_thinness;
+ save bottom_overshoot, bot_crook_dir;
+ save top_stem_thick, top_stem_thick_orig;
+ save bottom_stem_thick, hair, smaller_hole;
+ save top_crook_thinness;
+ save zwiep;
+ save center;
+ pair center, bot_crook_dir;
+ save clearing, clearing_orig;
+
+ clearxy;
+
+ % the stem shouldn't reach the top staff line.
+ %% TODO: should take from height.
+ %
+ % TODO: parameterize this
+ %
+ if w >= 0.75 staff_space:
+ smaller_hole = 0.35 stafflinethickness;
+ else:
+ smaller_hole = 0;
+ fi;
+ crook_thinness = .7 stafflinethickness + .06 staff_space;
+ top_crook_thinness = 1 stafflinethickness + .065 staff_space;
+ clearing = 1.7 stafflinethickness;
+ clearing_orig = clearing;
+ if arrowup:
+ clearing := 0.5 staff_space;
+ fi;
+ bottom_overshoot = stafflinethickness;
+
+ bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#;
+ top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#;
+ top_stem_thick_orig# = top_stem_thick#;
+ if arrowup:
+ % to look nice, arrowed stems should be less brushed
+ top_stem_thick# := top_stem_thick# * 0.8;
+ fi;
+ define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick,
+ top_stem_thick_orig);
+
+ if odd (top_stem_thick - bottom_stem_thick):
+ top_stem_thick := top_stem_thick - 1;
+ fi;
+ if odd (top_stem_thick_orig - bottom_stem_thick):
+ top_stem_thick_orig := top_stem_thick_orig - 1;
+ fi;
+
+ center = (xcenter, 0);
+
+ x1l = hround (xcenter - .5 top_stem_thick);
+ y1 = vround (2 staff_space - clearing);
+ x2l = hround (xcenter - .5 bottom_stem_thick);
+ y2 = -.5 staff_space - .5 stafflinethickness;
+ % z16 and the `*_orig' variables are needed for arrowed accidentals
+ % because their inner part should be unchanged from plain ones but
+ % the points z3l, z3r, and z10 depend on values that are different
+ % for arrowed accidentals
+ x16l = hround (xcenter -.5 top_stem_thick_orig);
+ y16 = vround (2 staff_space - clearing_orig);
+
+ penpos1 (top_stem_thick, 0);
+ penpos16 (top_stem_thick_orig, 0);
+ penpos2 (bottom_stem_thick, 0);
+
+ y3l = vfloor ((staff_space - stafflinethickness) / 2);
+ z3l = whatever [z2r, z1r];
+ z3r = .3 [z2r,
+ (z16r shifted (0, clearing_orig - 1.7 stafflinethickness))]
+ + (smaller_hole, 0);
+ x3r := hceiling x3r;
+
+ % we insert z3l to get better conversion with mf2pt1
+ fill simple_serif (z1r, z1l, 30)
+ -- z2l
+ -- z2r
+ -- z3l
+ -- cycle;
+
+ z10 = whatever [z2r, z16r] + (smaller_hole, 0);
+ y10 = -1/10 staff_space;
+ x10 := hceiling x10;
+
+ x11 = xcenter + bottom_overshoot / 3;
+ y11 = -vround (.5 (staff_space + stafflinethickness)
+ + bottom_overshoot);
+
+ x2a = 0.2[x2r, x7];
+ y2a = 1.5[y2, y11];
+
+ penpos4 (whatever, 53);
+
+ y4l - y4r = top_crook_thinness;
+ y5r = .15 staff_space;
+ x5l = hround (w + xcenter);
+ y4 = staff_space / 2;
+ x4r = .45 [x5r, x3r];
+ y4l := vround y4l;
+
+ penpos5 (crook_fatness, -175);
+
+ bot_crook_dir = unitvector ((x5l, 0) - z11);
+ z8 = z11 + whatever * bot_crook_dir;
+ y8 = -staff_space / 2;
+
+ z7 = z8
+ + whatever * bot_crook_dir
+ + crook_thinness * (bot_crook_dir rotated 90);
+ x7 = .1 [x3r, x8];
+
+ unfill z3r{z3r - z10}
+ .. z4r{right}
+ .. z5r{down}
+ .. z7{-bot_crook_dir}
+ & z7
+ .. z10{z3r - z10}
+ -- cycle;
+
+ if arrowdown:
+ fill z2l{down}
+ .. z2a{up}
+ .. z8{bot_crook_dir}
+ .. z5l{up}
+ .. z4l{left}
+ .. z3l
+ -- cycle;
+ else:
+ fill z2l{down}
+ .. z11{right}
+ .. z8{bot_crook_dir}
+ .. z5l{up}
+ .. z4l{left}
+ .. z3l
+ -- cycle;
+ fi;
+
+ if arrowup:
+ draw_arrow (z1, top_stem_thick, z1l - z2l,
+ 0.5 stafflinethickness, false);
+ fi;
+ if arrowdown:
+ draw_arrow ((0.5 [x2l, x2a], y2), x2a - x2l, up,
+ staff_space / 2, true);
+ fi;
+enddef;
+
+
+def draw_arrowed_meta_flat (expr xcenter, width, crook_fatness,
+ arrowup, arrowdown) =
+ save depth, height, extendleft;
+
+ depth# = 0.6 staff_space#;
+ height# = 1.9 staff_space#;
+ extendleft# := 1.2 stafflinethickness#;
+ if arrowup:
+ extendleft# := 3.45 stafflinethickness#;
+ height# := height# + 0.8 staff_space#;
+ fi;
+ if arrowdown:
+ extendleft# := 3.45 stafflinethickness#;
+ depth# := depth# + 1.6 staff_space#;
+ fi;
+
+ set_char_box (extendleft#, width, depth#, height#);
+ draw_meta_flat(xcenter, w, crook_fatness, arrowup, arrowdown);
+enddef;
+
+%
+% unfortunately, 600dpi is not enough to show the brush of the stem.
+%
+
+fet_beginchar ("Flat", "flat");
+ draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
+ false, false);
+ penlabels (range 0 thru 11);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Flat (arrow up)", "flat.arrowup");
+ draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
+ true, false);
+ penlabels (range 0 thru 23);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Flat (arrow down)", "flat.arrowdown");
+ draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
+ false, true);
+ penlabels (range 0 thru 23);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Arrowed Flat (arrow up and down)", "flat.arrowboth");
+ draw_arrowed_meta_flat (0, 0.8 staff_space#, 0.31 staff_space,
+ true, true);
+ penlabels (range 0 thru 23);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Flat (slashed)", "flat.slash");
+ set_char_box (.4 staff_space#, .8 staff_space#,
+ 0.6 staff_space#, 1.9 staff_space#);
+
+ draw_meta_flat (0, w, 0.31 staff_space, false, false);
+
+ clearxy;
+
+ save slope, slash_width;
+ slope = 0.5;
+ slash_width = w;
+
+ z11 = (0, h / 2);
+ z12 = z11 - (slash_width, slash_width * slope) / 2;
+ z13 = z11 + (slash_width, slash_width * slope) / 2;
+ penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
+ penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
+
+ z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
+ z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
+
+ fill z13r
+ .. z15
+ .. z13l
+ -- z12l
+ .. z14
+ .. z12r
+ -- z13r
+ .. cycle;
+
+ penlabels (12, 13);
+ labels (14, 15);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("Flat (slashed twice)", "flat.slashslash");
+ set_char_box (.4 staff_space#, .8 staff_space#,
+ 0.6 staff_space#, 1.9 staff_space#);
+
+ draw_meta_flat (0, w, 0.31 staff_space, false, false);
+
+ clearxy;
+
+ save slope, slash_width;
+ slope = 0.5;
+ slash_width = w;
+
+ z11 = (0, 5/12 h);
+ z12 = z11 - (slash_width, slash_width * slope) / 2;
+ z13 = z11 + (slash_width, slash_width * slope) / 2;
+ penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
+ penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
+
+ z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
+ z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
+
+ fill z13r
+ .. z15
+ .. z13l
+ -- z12l
+ .. z14
+ .. z12r
+ -- z13r
+ .. cycle;
+
+ penlabels (12, 13);
+ labels (14, 15);
+
+ z21 = (0, 2/3 h);
+ z22 = z21 - (slash_width, slash_width * slope) / 2;
+ z23 = z21 + (slash_width, slash_width * slope) / 2;
+ penpos22 (1.5 stafflinethickness, angle (z23 - z22) - 90);
+ penpos23 (1.5 stafflinethickness, angle (z23 - z22) - 90);
+
+ z24 = z22 - .75 stafflinethickness * unitvector (z23 - z22);
+ z25 = z23 + .75 stafflinethickness * unitvector (z23 - z22);
+
+ fill z23r
+ .. z25
+ .. z23l
+ -- z22l
+ .. z24
+ .. z22r
+ -- z23r
+ .. cycle;
+
+ penlabels (22, 23);
+ labels (24, 25);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+fet_beginchar ("Flatflat (mirrored)", "mirroredflat.flat");
+ set_char_box (0, 1.6 staff_space#,
+ 0.6 staff_space#, 1.9 staff_space#);
+
+ % This is a modified version of `draw_meta_flat'.
+
+ save crook_thinness, crook_fatness;
+ save bottom_overshoot, bot_crook_dir;
+ save top_stem_thick, bottom_stem_thick, hair, smaller_hole;
+ save top_crook_thinness;
+ save zwiep;
+ save center;
+ pair center, bot_crook_dir;
+ save clearing, wid;
+ save pat;
+ path pat;
+
+ clearxy;
+
+ wid = w / 2;
+
+ % the stem shouldn't reach the top staff line.
+ %% TODO: should take from height.
+ %
+ % TODO: parameterize this
+ %
+ if wid >= 0.75 staff_space:
+ smaller_hole = 0.35 stafflinethickness;
+ else:
+ smaller_hole = 0;
+ fi;
+ clearing = 1.7 stafflinethickness;
+ crook_thinness = .7 stafflinethickness + .06 staff_space;
+ crook_fatness = 0.31 staff_space;
+ top_crook_thinness = 1 stafflinethickness + .065 staff_space;
+ bottom_overshoot = stafflinethickness;
+
+ bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#;
+ top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#;
+ define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick);
+
+ if odd (top_stem_thick - bottom_stem_thick):
+ top_stem_thick := top_stem_thick - 1;
+ fi;
+
+ center = (0, 0);
+
+ x1l = hround (-.5 top_stem_thick);
+ y1 = vround (2 staff_space - clearing);
+ x2l = hround (-.5 bottom_stem_thick);
+ y2 = -.5 staff_space - .5 stafflinethickness;
+
+ penpos1 (top_stem_thick, 0);
+ penpos2 (bottom_stem_thick, 0);
+
+ y3l = vfloor ((staff_space - stafflinethickness) / 2);
+ z3l = whatever [z2r, z1r];
+ z3r = .3 [z2r, z1r] + (smaller_hole, 0);
+ x3r := hceiling x3r;
+
+ z10 = whatever [z2r, z1r] + (smaller_hole, 0);
+ y10 = -1/10 staff_space;
+ x10 := hceiling x10;
+
+ x11 = bottom_overshoot / 3;
+ y11 = -vround (.5 (staff_space + stafflinethickness)
+ + bottom_overshoot);
+
+ penpos4 (whatever, 53);
+
+ y4l - y4r = top_crook_thinness;
+ y5r = .15 staff_space;
+ x5l = hround (wid);
+ y4 = staff_space / 2;
+ x4r = .45 [x5r, x3r];
+ y4l := vround y4l;
+
+ penpos5 (crook_fatness, -175);
+
+ bot_crook_dir = unitvector ((x5l, 0) - z11);
+ z8 = z11 + whatever * bot_crook_dir;
+ y8 = -staff_space / 2;
+
+ z7 = z8
+ + whatever * bot_crook_dir
+ + crook_thinness * (bot_crook_dir rotated 90);
+ x7 = .1 [x3r, x8];
+
+ pat := z3r{z3r - z10}
+ .. z4r{right}
+ .. z5r{down}
+ .. z7{-bot_crook_dir}
+ & z7
+ .. z10{z3r - z10}
+ -- cycle;
+ unfill pat;
+ unfill pat xscaled -1;
+
+ pat := z11{right}
+ .. z8{bot_crook_dir}
+ .. z5l{up}
+ .. z4l{left}
+ .. z3l;
+ fill pat
+ -- simple_serif (z1r, z1l, 30)
+ -- reverse pat xscaled -1 shifted (-feta_eps, 0)
+ -- cycle;
+
+ currentpicture := currentpicture shifted (w/2, 0);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Semi flat", "mirroredflat");
+ set_char_box (1.2 stafflinethickness#, .8 staff_space#,
+ 0.6 staff_space#, 1.9 staff_space#);
+
+ draw_meta_flat (0, w, 0.31 staff_space, false, false);
+ currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
+fet_endchar;
+
+
+fet_beginchar ("Semi flat", "mirroredflat.backslash");
+ set_char_box (.4 staff_space#, .8 staff_space#,
+ 0.6 staff_space#, 1.9 staff_space#);
+
+ draw_meta_flat (0, w, 0.31 staff_space, false, false);
+
+ clearxy;
+
+ save slope, slash_width;
+ slope = 0.5;
+ slash_width = w;
+
+ z11 = (0, h / 2);
+ z12 = z11 - (slash_width, slash_width * slope) / 2;
+ z13 = z11 + (slash_width, slash_width * slope) / 2;
+ penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90);
+ penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90);
+
+ z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12);
+ z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12);
+
+ fill z13r
+ .. z15
+ .. z13l
+ -- z12l
+ .. z14
+ .. z12r
+ -- z13r
+ .. cycle;
+
+ currentpicture := currentpicture xscaled -1 shifted (w - b, 0);
+
+ labels (1, 2, 3);
+fet_endchar;
+
+
+fet_beginchar ("Double Flat", "flatflat");
+ save left_wid, overlap, right_wid;
+
+ left_wid = .7;
+ right_wid = .8;
+ overlap = .05;
+
+ set_char_box (1.2 stafflinethickness#,
+ (left_wid + right_wid - overlap) * staff_space#,
+ .6 staff_space#, 1.9 staff_space#);
+ draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space,
+ false, false);
+ draw_meta_flat (hround ((left_wid - overlap) * staff_space),
+ right_wid * staff_space, 1/3 staff_space,
+ false, false);
+fet_endchar;
+
+
+fet_beginchar ("3/4 Flat", "flatflat.slash");
+ save left_wid, overlap, right_wid;
+
+ left_wid = .7;
+ right_wid = .8;
+ overlap = .05;
+
+ set_char_box (1.2 stafflinethickness#,
+ (left_wid + right_wid - overlap) * staff_space#,
+ .6 staff_space#, 1.9 staff_space#);
+ draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space,
+ false, false);
+ draw_meta_flat (hround ((left_wid - overlap) * staff_space),
+ right_wid * staff_space, 1/3 staff_space,
+ false, false);
+
+ %% maybe we should clip part of the stems?
+ %% or make the 1st flat smaller?
+ %% or reverse it?
+ pickup pencircle scaled 2 stafflinethickness;
+
+ z12 = round (-.25 w - b, .55 staff_space) + feta_offset;
+ z13 = round (.75 w, 1.45 staff_space) + feta_offset;
+ penpos12 (2 stafflinethickness, angle (z13 - z12) - 90);
+ penpos13 (2 stafflinethickness, angle (z13 - z12) - 90);
+
+ z14 = z12 - stafflinethickness * unitvector (z13 - z12);
+ z15 = z13 + stafflinethickness * unitvector (z13 - z12);
+
+ fill z13r
+ .. z15
+ .. z13l
+ -- z12l
+ .. z14
+ .. z12r
+ -- z13r
+ .. cycle;
+
+ penlabels (12, 13);
+ labels (14, 15);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Double Sharp", "doublesharp");
+ save klaverblad, klaversteel;
+ save pat;
+ path pat;
+
+ klaversteel = 1/15 staff_space;
+ klaverblad = .4 staff_space - .5 stafflinethickness;
+
+ set_char_box (0, staff_space#, .5 staff_space#, .5 staff_space#);
+
+ z1 = (klaversteel, 0);
+ z2 = (w / 2 - klaverblad / 10, h - klaverblad);
+ z3 = (w / 2, h);
+ z4 = z2 reflectedabout ((0, 0), (1, 1));
+ z5 = z1 reflectedabout ((0, 0), (1, 1));
+
+ labels (1, 2, 3, 4, 5);
+
+ pickup pencircle scaled blot_diameter;
+
+ x2 := hfloor (rt x2) - blot_diameter / 2;
+ x3 := hfloor (rt x3) - blot_diameter / 2;
+ y3 := vfloor (top y3) - blot_diameter / 2;
+ y4 := vfloor (top y4) - blot_diameter / 2;
+
+ pat = (rt z1){dir45}
+ .. {right}(bot z2)
+ .. rt z2
+ -- rt z3{z3 - z2}
+ .. top z3{z4 - z3}
+ -- top z4{z4 - z3}
+ .. (lft z4){down}
+ .. {dir 225}(top z5);
+ pat := pat
+ -- reverse pat xscaled -1 shifted (-feta_eps, 0);
+
+ % assure symmetry -- it's more important to center the glyph on the
+ % staff line than centering it between staff lines, so we use
+ % feta_shift, not feta_space_shift.
+ h := h + feta_shift;
+
+ fill pat shifted (0, feta_shift)
+ -- reverse pat yscaled -1 shifted (0, -feta_eps)
+ -- cycle;
+
+ % ugh
+ currentpicture := currentpicture shifted (hround (w / 2), 0);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+def draw_paren =
+ save leftindent;
+
+ leftindent := .2 staff_space;
+
+ set_char_box (0, .5 staff_space# + stafflinethickness#,
+ staff_space#, staff_space#);
+
+ d := d - feta_shift;
+
+ z1 = (leftindent, h);
+ z2 = (w - stafflinethickness, .5 (h - d));
+ z3 = (leftindent, -d);
+
+ penpos1 (stafflinethickness, 35);
+ penpos2 (.1 staff_space + stafflinethickness, 0);
+ penpos3 (stafflinethickness, -35);
+
+ fill z2l{down}
+ .. simple_serif (z3l, z3r, 90)
+ .. z2r{up}
+ .. simple_serif (z1r, z1l, 90)
+ .. z2l{down}
+ -- cycle;
+enddef;
+
+
+fet_beginchar ("Right Parenthesis", "rightparen");
+ draw_paren;
+ penlabels (1, 2, 3);
+
+ remember_pic := currentpicture;
+
+ draw_staff (-2, 2, 0);
+fet_endchar;
+
+
+draw_shifted_too;
+
+
+fet_beginchar ("Left Parenthesis", "leftparen");
+ draw_paren;
+
+ currentpicture := currentpicture xscaled -1;
+
+ set_char_box (charwd, charbp, chardp, charht);
+fet_endchar;
+
+fet_endgroup ("accidentals");
diff --git a/muse2/share/scoreglyphs/feta-original/feta11.mf b/muse2/share/scoreglyphs/feta-original/feta11.mf
new file mode 100644
index 00000000..be6a6a7e
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta11.mf
@@ -0,0 +1,13 @@
+% feta11.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 11.22;
+test := 0;
+
+
+input feta-generic;
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta13.mf b/muse2/share/scoreglyphs/feta-original/feta13.mf
new file mode 100644
index 00000000..5014c123
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta13.mf
@@ -0,0 +1,13 @@
+% feta13.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 12.60;
+test := 0;
+
+
+input feta-generic;
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta14.mf b/muse2/share/scoreglyphs/feta-original/feta14.mf
new file mode 100644
index 00000000..23ac8e4d
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta14.mf
@@ -0,0 +1,14 @@
+% feta14.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 14.14;
+test := 0;
+
+
+input feta-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta16.mf b/muse2/share/scoreglyphs/feta-original/feta16.mf
new file mode 100644
index 00000000..174460b7
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta16.mf
@@ -0,0 +1,13 @@
+% feta16.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 15.87;
+test := 0;
+
+
+input feta-generic;
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta18.mf b/muse2/share/scoreglyphs/feta-original/feta18.mf
new file mode 100644
index 00000000..b52f6a3e
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta18.mf
@@ -0,0 +1,14 @@
+% feta18.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+% todo change file name
+design_size := 17.82;
+test := 0;
+
+
+input feta-generic;
+
+
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta20.mf b/muse2/share/scoreglyphs/feta-original/feta20.mf
new file mode 100644
index 00000000..2b561b20
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta20.mf
@@ -0,0 +1,14 @@
+% feta20.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 20;
+
+input feta-autometric;
+
+
+% use feta-test for debugging.
+test := 0;
+input feta-generic;
+
+
+end.
diff --git a/muse2/share/scoreglyphs/feta-original/feta23.mf b/muse2/share/scoreglyphs/feta-original/feta23.mf
new file mode 100644
index 00000000..d2cf0025
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta23.mf
@@ -0,0 +1,15 @@
+% feta23.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+% todo change file name
+design_size := 22.45;
+test := 0;
+
+
+input feta-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/feta26.mf b/muse2/share/scoreglyphs/feta-original/feta26.mf
new file mode 100644
index 00000000..2bfa5366
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/feta26.mf
@@ -0,0 +1,15 @@
+% feta26.mf
+% part of LilyPond's pretty-but-neat music font
+
+input feta-autometric;
+
+design_size := 25.20;
+test := 0;
+
+
+input feta-generic;
+
+
+end.
+
+
diff --git a/muse2/share/scoreglyphs/feta-original/mf2pt1.mp b/muse2/share/scoreglyphs/feta-original/mf2pt1.mp
new file mode 100644
index 00000000..a8b45aad
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/mf2pt1.mp
@@ -0,0 +1,495 @@
+%%%%
+%%%% MF2PT1.MP, by Scott Pakin, scott+mf@pakin.org
+%%%%
+%%%% This file is used to dump a special version of MetaPost with:
+%%%% mpost -progname=mpost -ini mf2pt1 \\dump
+%%%%
+%%%% To pretty-print this file, you'll need LaTeX and the mftinc package
+%%%% (available from CTAN).
+%%%%
+
+%%%% ==================================================================== %%%%
+%%%% mf2pt1 %%%%
+%%%% Copyright (C) 2008 Scott Pakin %%%%
+%%%% %%%%
+%%%% This program may be distributed and/or modified under the conditions %%%%
+%%%% of the LaTeX Project Public License, either version 1.3c of this %%%%
+%%%% license or (at your option) any later version. %%%%
+%%%% %%%%
+%%%% The latest version of this license is in: %%%%
+%%%% %%%%
+%%%% http://www.latex-project.org/lppl.txt %%%%
+%%%% %%%%
+%%%% and version 1.3c or later is part of all distributions of LaTeX %%%%
+%%%% version 2006/05/20 or later. %%%%
+%%%% ==================================================================== %%%%
+
+input mfplain;
+
+%%% addto makepath makepen
+%%% length clockwise counterclockwise
+%%% scaled dashed withcolor
+
+%% \begin{explaincode}
+%% Enable a \MF\ file to determine if it's being built with
+%% \texttt{mf2pt1}.
+%% \end{explaincode}
+
+newinternal ps_output;
+ps_output := 1;
+
+
+%% \begin{explaincode}
+%% The following was taken right out of \texttt{mfplain.mp}. The \mfcomment
+% |def| and the |special|s at the end
+%% are the sole additions. Normally, MetaPost outputs a tight bounding
+%% box around the character in its PostScript output. The purpose of the
+%% first \mfcomment
+% |special|
+%% is to pass \texttt{mf2pt1} a bounding box that includes the proper
+%% surrounding whitespace. The purpose of the second special is to
+%% provide \texttt{mf2pt1} with a default PostScript font name.
+%% \end{explaincode}
+
+def beginchar(expr c,w_sharp,h_sharp,d_sharp) =
+ begingroup
+ charcode:=if known c: byte c else: 0 fi;
+ charwd:=w_sharp; charht:=h_sharp; chardp:=d_sharp;
+ w:=charwd*pt; h:=charht*pt; d:=chardp*pt;
+ charic:=0; clearxy; clearit; clearpen; scantokens extra_beginchar;
+
+ def to_bp (expr num) = decimal (ceiling (num*bp_per_pixel)) enddef;
+ special "% MF2PT1: glyph_dimensions 0 " & to_bp (-d) & " " & to_bp(w) & " " & to_bp(h);
+ special "% MF2PT1: font_size " & decimal designsize;
+ special "% MF2PT1: font_slant " & decimal font_slant_;
+ special "% MF2PT1: charwd " & decimal charwd; % Must come after the |font_size| |special|
+ for fvar = "font_identifier", "font_coding_scheme", "font_version",
+ "font_comment", "font_family", "font_weight", "font_unique_id",
+ "font_name":
+ if known scantokens (fvar & "_"):
+ special "% MF2PT1: " & fvar & " " & scantokens (fvar & "_");
+ fi;
+ endfor;
+ for fvar = "font_underline_position", "font_underline_thickness":
+ if known scantokens (fvar & "_"):
+ special "% MF2PT1: " & fvar & " " &
+ scantokens ("decimal " & fvar & "_");
+ fi;
+ endfor;
+ special "% MF2PT1: font_fixed_pitch " &
+ (if font_fixed_pitch_: "1" else: "0" fi);
+enddef;
+
+
+%% \begin{explaincode}
+%% Enable a character to specify explicitly the PostScript glyph
+%% name associated with it.
+%% \end{explaincode}
+def glyph_name expr name =
+ special "% MF2PT1: glyph_name " & name;
+enddef;
+
+
+%% \begin{explaincode}
+%% Store the value of \mfcomment
+% |font_slant_|, so we can recall it at each |beginchar|.
+%% \end{explaincode}
+
+font_slant_ := 0;
+
+def font_slant expr x =
+ font_slant_ := x;
+ fontdimen 1: x
+enddef;
+
+
+%% \begin{explaincode}
+%% Redefine \mfcomment
+% |bpppix_|, the number of ``big'' points per pixel. \mfcomment
+% This in turn redefines |mm|, |in|, |pt|, and other derived units.
+%% \end{explaincode}
+
+def bpppix expr x =
+ bpppix_ := x;
+ mm := 2.83464 / bpppix_;
+ pt := 0.99626 / bpppix_;
+ dd := 1.06601 / bpppix_;
+ bp := 1 / bpppix_;
+ cm := 28.34645 / bpppix_;
+ pc := 11.95517 / bpppix_;
+ cc := 12.79213 / bpppix_;
+ in := 72 / bpppix_;
+ hppp := pt;
+ vppp := pt;
+enddef;
+
+
+%% \begin{explaincode}
+%% Define a bunch of PostScript font parameters to be used by
+%% \texttt{mf2pt1.pl}. Default values are specified in
+%% \texttt{mf2pt1.pl}, not here.
+%% \end{explaincode}
+
+forsuffixes fvar = font_version, font_comment, font_family, font_weight,
+ font_name, font_unique_id:
+ scantokens ("string " & str fvar & "_;");
+ scantokens ("def " & str fvar & " expr x = " & str fvar & "_ := x enddef;");
+endfor;
+
+forsuffixes fvar = font_underline_position, font_underline_thickness:
+ scantokens ("numeric " & str fvar & "_;");
+ scantokens ("def " & str fvar & " expr x = " & str fvar & "_ := x enddef;");
+endfor;
+
+boolean font_fixed_pitch_;
+font_fixed_pitch_ := false;
+def font_fixed_pitch expr x = font_fixed_pitch_ := x enddef;
+
+
+%% \begin{explaincode}
+%% We'd like to be able to use calligraphic pens. Normally, MetaPost's
+%% output routine does all the work for us of converting these to filled
+%% PostScript paths. The only exception occurs for paths drawn using a
+%% pen that was transformed from \mfcomment
+% |pencircle|. MetaPost outputs these paths as stroked PostScript
+%% paths. The following code tricks MetaPost into using a filled path
+%% for \mfcomment
+% |pencircle| by replacing the primitive |pencircle| pen with a
+%% non-primitive approximation. Note that we use a 20-gon for our circle
+%% instead of a diamond, so we get better results from \mfcomment
+% |draw|.
+%% \end{explaincode}
+
+pen fakepencircle, mfplain_pencircle;
+mfplain_pencircle := pencircle;
+fakepencircle := makepen (for deg=0 step 360/20 until 359:
+ (0.5 cosd deg, 0.5 sind deg)--
+ endfor cycle);
+save pencircle;
+pen pencircle;
+pencircle := fakepencircle;
+
+
+%% \begin{explaincode}
+%% Return \mfcomment
+% |true| if a path is cyclic, |false| otherwise.
+%% \end{explaincode}
+
+def is_cyclic expr cpath =
+ (point 0 of cpath = point (length cpath) of cpath)
+enddef;
+
+
+%% \begin{explaincode}
+%% Determine the direction of a path which doesn't intersect
+%% itself. \mfcomment
+% Returns |true| if the curve is clockwise, |false| if
+%% counterclockwise. For non-cyclic paths the result is not
+%% predictable.
+%% \bigskip
+%%
+%% The \mfcomment
+% |crossproduct|, |makeline|, and |is_clockwise| functions were
+%% provided by Werner Lemberg.
+%% \bigskip
+%%
+%% The algorithm used is quite simple:
+%%
+%% \begin{itemize}
+%% \item Find a point~$P$ on the path which has a non-zero direction,
+%% and which is on a not-too-short path element.
+%%
+%% \item Construct a ray of ``infinite'' length, starting in the
+%% vicinity of~$P$ which intersects the path at this point.
+%%
+%% \item Use \mfcomment
+% |intersectiontimes| to find the intersection. If the direction of
+%% the path at this point is (near) zero, or if we have a grazing
+%% intersection or even a tangent, get a new ray.
+%%
+%% \item Shorten the ray so that it starts right after the
+%% intersection. Repeat the previous step until no intersection is
+%% found. Then go back to the last intersection and compare the path's
+%% direction with the direction of the ray. According to the
+%% \emph{nonzero winding number} rule we have found a clockwise
+%% oriented path if it crosses the ray from left to right.
+%% \end{itemize}
+%%
+%% This method completely avoids any problems with the geometry of
+%% B\'{e}zier curves. If problems arise, a different ray is tried.
+%% Since it isn't necessary to analyze the whole path it runs quite fast
+%% in spite of using \mfcomment
+% |intersectiontimes| which is a slow MetaPost command.
+%% \end{explaincode}
+
+vardef crossproduct (expr u, v) =
+ save u_, v_;
+ pair u_, v_;
+
+ u_ := unitvector u;
+ v_ := unitvector v;
+
+ abs (xpart u_ * ypart v_ - ypart u_ * xpart v_)
+enddef;
+
+vardef makeline primary p =
+ save start, bad_n, loop, distance, d, i, n;
+ pair start, d;
+
+ loop := 0;
+ bad_n := -1;
+ for i := 0 step 1 until length p - 1:
+ distance := length (point i of p - point (i + 1) of p);
+ if distance <> 0:
+ if distance < 1:
+ % In case we don't find something better.
+ bad_n := i;
+ else:
+ n := i;
+ loop := 1;
+ fi;
+ fi;
+ exitif loop = 1;
+ endfor;
+
+ if loop = 0:
+ if bad_n <> -1:
+ n := bad_n;
+ loop = 1;
+ fi;
+ fi;
+
+ % Add some randomness to get different lines for each function call.
+ n := n + uniformdeviate 0.8 + 0.1;
+ start := point n of p;
+
+ if loop = 0:
+ % Construct a line which misses the degenerated path.
+ start + (1, 0)
+ -- start + (1, 1)
+ else:
+ d := direction n of p;
+
+ % Again, some added randomness.
+ n := uniformdeviate 150 + 15;
+ d := unitvector (d rotated n);
+
+ % Construct a line which intersects the path at least once.
+ start - eps * d
+ -- infinity * d
+ fi
+enddef;
+
+vardef is_clockwise primary p =
+ save line, cut, cut_new, res, line_dir, tangent_dir;
+ path line;
+ pair cut, cut_new, line_dir, tangent_dir;
+
+ line := makeline p;
+ line_dir := direction 0 of line;
+
+ % Find the outermost intersection.
+ cut := (0, 0);
+ forever:
+ cut_new := line intersectiontimes p;
+ exitif cut_new = (-1, -1);
+
+ % Compute a new line if we have a strange intersection.
+ tangent_dir := direction (ypart cut_new) of p;
+ if abs tangent_dir < eps:
+ % The vector is zero or too small.
+ line := makeline p;
+ line_dir := direction 0 of line;
+
+ elseif abs (ypart cut_new - floor (ypart cut_new + 0.5)) < eps:
+ % Avoid possible tangent touching in a corner or cusp.
+ line := makeline p;
+ line_dir := direction 0 of line;
+
+ elseif crossproduct (tangent_dir, line_dir) < 0.2:
+ % Grazing intersection (arcsin 0.2 ~= 11.5 degrees).
+ line := makeline p;
+ line_dir := direction 0 of line;
+
+ else:
+ % Go ahead.
+ cut := cut_new;
+ line := subpath (xpart cut + eps, infinity) of line;
+ fi;
+ endfor;
+
+ tangent_dir := direction (ypart cut) of p;
+ if tangent_dir <> (0, 0):
+ res := (angle tangent_dir - angle line_dir + 180) mod 360 - 180;
+ res < 0
+ else:
+ false
+ fi
+enddef;
+
+
+%% \begin{explaincode}
+%% Make a given path run clockwise or counterclockwise. \mfcomment
+% (|counterclockwise| is defined by \texttt{mfplain} but we override
+%% it here.)
+%% \end{explaincode}
+
+vardef counterclockwise primary c =
+ (if is_clockwise c: (reverse c) else: c fi)
+enddef;
+
+vardef clockwise primary c =
+ (if is_clockwise c: c else: (reverse c) fi)
+enddef;
+
+
+%% \begin{explaincode}
+%% Redefine \mfcomment
+% |fill| and |unfill| to ensure that filled paths run
+%% counterclockwise and unfilled paths run clockwise, as is required
+%% by PostScript Type~1 fonts.
+%% \end{explaincode}
+
+def fill expr c =
+ addto currentpicture contour counterclockwise c t_ pc_
+enddef;
+
+def unfill expr c =
+ addto currentpicture contour clockwise c t_ pc_ withcolor background
+enddef;
+
+
+%% \begin{explaincode}
+%% Convert \mfcomment
+% |filldraw| and |unfilldraw| to |fill| and |unfill|.
+%% \end{explaincode}
+
+let mfplain_filldraw := filldraw;
+def filldraw expr c =
+ begingroup
+ message "! Warning: Replacing filldraw with fill.";
+ fill c
+ endgroup
+enddef;
+
+let mfplain_unfilldraw := unfilldraw;
+def unfilldraw expr c =
+ begingroup
+ message "! Warning: Replacing unfilldraw with unfill.";
+ unfill c
+ endgroup
+enddef;
+
+
+%% \begin{explaincode}
+%% Return \mfcomment
+% |true| if |currentpen| looks like a |pencircle|.
+%% \end{explaincode}
+
+def using_pencircle =
+ begingroup
+ path qpath, circlepath;
+ qpath = makepath currentpen;
+ numeric circlediv;
+ circlepath = makepath pencircle;
+ circlediv = xpart (lrcorner circlepath);
+
+ (length qpath = length circlepath) and (pen_rt <> 0) and (pen_top <> 0)
+ for pp = 0 upto (length qpath)-1:
+ and ((xpart (point pp of qpath) / pen_rt,
+ ypart (point pp of qpath) / pen_top) =
+ point pp of circlepath / circlediv)
+ endfor
+ endgroup
+enddef;
+
+
+%% \begin{explaincode}
+%% If the pen looks like a circular pen, draw a nice circle. Otherwise,
+%% draw the pen as is.
+%% \end{explaincode}
+
+def drawdot expr z =
+ if using_pencircle:
+ begingroup
+ path cpath;
+ numeric clength;
+ cpath = makepath currentpen;
+ clength = length cpath;
+ fill ((point 0 of cpath)
+ ..(point clength/4 of cpath)
+ ..(point clength/2 of cpath)
+ ..(point 3*clength/4 of cpath)
+ ..cycle) shifted z t_
+ endgroup
+ else:
+ addto currentpicture contour makepath currentpen shifted z
+ t_ pc_
+ fi
+enddef;
+
+
+%% \begin{explaincode}
+%% Do the same as the above, but unfill the current pen.
+%% \end{explaincode}
+
+def undrawdot expr z =
+ if using_pencircle:
+ begingroup
+ path cpath;
+ numeric clength;
+ cpath = makepath currentpen;
+ clength = length cpath;
+ unfill ((point 0 of cpath)
+ ..(point clength/4 of cpath)
+ ..(point clength/2 of cpath)
+ ..(point 3*clength/4 of cpath)
+ ..cycle) shifted z t_
+ endgroup
+ else:
+ unfill makepath currentpen shifted z t_
+ fi
+enddef;
+
+
+%% \begin{explaincode}
+%% MetaPost renders \mfcomment
+% |draw| with a filled curve.
+%% Hence, we need to ensure the orientation is correct (i.e.,
+%% counterclockwise). Unfortunately, we have no way to check for
+%% overlap, and it's fairly common for MetaPost to output
+%% self-overlapping curve outlines, even if the curve itself has no
+%% overlap.
+%% \end{explaincode}
+
+def draw expr p =
+ addto currentpicture
+ if picture p:
+ also p
+ elseif is_cyclic p:
+ doublepath counterclockwise p t_ withpen currentpen
+ else:
+ if is_clockwise (p--cycle):
+ doublepath (reverse p) t_ withpen currentpen
+ else:
+ doublepath p t_ withpen currentpen
+ fi
+ fi
+ pc_
+enddef;
+
+def undraw expr p =
+ addto currentpicture
+ if picture p:
+ also p
+ elseif is_cyclic p:
+ doublepath clockwise p t_ withpen currentpen
+ else:
+ if is_clockwise (p--cycle):
+ doublepath p t_ withpen currentpen
+ else:
+ doublepath (reverse p) t_ withpen currentpen
+ fi
+ fi
+ pc_ withcolor background
+enddef;
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-accidentals.mf b/muse2/share/scoreglyphs/feta-original/parmesan-accidentals.mf
new file mode 100644
index 00000000..b5fe6630
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-accidentals.mf
@@ -0,0 +1,385 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-accidentals.mf -- implement ancient accidentals
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2001--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+fet_begingroup ("accidentals");
+
+
+%%%%%%%%
+%
+%
+%
+% EDITIO MEDICAEA
+%
+%
+%
+fet_beginchar ("Ed. Med. Flat" , "medicaeaM1");
+ set_char_box (0.1 staff_space#, 0.6 staff_space#,
+ 0.6 staff_space#, 1.0 staff_space#);
+
+ save ellipse, pat, outline, T;
+ path ellipse, pat, outline;
+ transform T;
+
+ T := identity xscaled 0.50 linethickness
+ yscaled 0.22 staff_space;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ x1 = x2 = 0;
+ top y1 = h;
+ bot y2 = -d;
+
+ fill get_subpath (ellipse, up, down, z1)
+ -- get_subpath (ellipse, down, up, z2)
+ -- cycle;
+
+ T := identity xscaled 0.50 linethickness
+ yscaled 0.22 staff_space
+ rotated -63;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ z3 = (0.10 staff_space, -0.50 staff_space);
+ z4 = (0.40 staff_space, +0.40 staff_space);
+ z5 = (0.10 staff_space, +0.40 staff_space);
+
+ pat := z3{(1, 2)}
+ .. z4
+ .. z5{(-1, -1)};
+
+ % the original envelope curve created with `draw' contains
+ % cusps which we avoid
+ outline := get_subpath (ellipse, -direction 0 of pat,
+ direction 0 of pat, z3)
+ .. get_subpoint (ellipse, direction 1 of pat, z4)
+ .. get_subpath (ellipse, direction 2 of pat,
+ -direction 1.8 of pat, z5)
+ .. get_subpoint (ellipse, -direction 1 of pat, z4)
+ {-direction 1 of pat}
+ .. cycle;
+
+ save shift;
+ pair shift;
+
+ % make the outline touch the bounding box
+ shift = find_tangent_shift (((w, -d) -- (w, h)), outline,
+ (b, 0), (-b, 0));
+ outline := outline shifted shift;
+
+ fill outline;
+
+ labels (1, 2, 3, 4, 5);
+fet_endchar;
+
+
+%%%%%%%%
+%
+%
+%
+% EDITIO VATICANA
+%
+%
+%
+fet_beginchar ("Ed. Vat. Flat" , "vaticanaM1");
+ z1 = (0.00 staff_space, +0.80 staff_space);
+ z2 = (0.00 staff_space, -0.08 staff_space);
+ z3 = (0.25 staff_space, -0.23 staff_space);
+ z4 = (0.50 staff_space, -0.24 staff_space);
+ z5 = (0.50 staff_space, +0.03 staff_space);
+ z6 = (0.25 staff_space, +0.20 staff_space);
+ z7 = (0.15 staff_space, +0.26 staff_space);
+
+ save pat, ellipse, T;
+ path pat, ellipse;
+ transform T;
+
+ T := identity xscaled 0.50 linethickness
+ yscaled 0.22 staff_space;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ pat := z1
+ -- z2{down}
+ ... z3
+ ... {up}z4
+ -- z5{up}
+ .. z6
+ .. z7;
+
+ % the original envelope curve created with `draw' contains
+ % cusps which we avoid
+ fill get_subpath (ellipse, up, down, z1)
+ -- get_subpath (ellipse, down, direction 1.1 of pat, z2)
+ ... bot z3
+ ... get_subpath (ellipse, direction 2.9 of pat, up, z4)
+ -- get_subpath (ellipse, up, direction 4.1 of pat, z5)
+ .. top z6
+ .. get_subpath (ellipse,
+ direction 6 of pat, -direction 6 of pat, z7)
+ .. bot z6
+ .. {down}bot lft z5
+ -- top lft z4{down}
+ ... top z3
+ ... top rt z2{up}
+ -- cycle;
+
+ set_char_box (0.00 staff_space# + 0.25 linethickness#,
+ 0.50 staff_space# + 0.25 linethickness#,
+ 0.23 staff_space# + 0.11 staff_space#,
+ 0.80 staff_space# + 0.11 staff_space#);
+
+ labels (1, 2, 3, 4, 5, 6, 7);
+fet_endchar;
+
+
+fet_beginchar ("Ed. Vat. Natural" , "vaticana0");
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled 0.80 linethickness
+ yscaled 0.22 staff_space;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ z1 = (0.00 staff_space, +0.65 staff_space);
+ z2 = (0.00 staff_space, -0.35 staff_space);
+
+ fill get_subpath (ellipse, up, down, z1)
+ -- get_subpath (ellipse, down, up, z2)
+ -- cycle;
+
+ pickup penrazor scaled 0.22 staff_space
+ rotated 90;
+
+ z3 = (0.00 staff_space, -0.30 staff_space);
+ z4 = (0.40 staff_space, -0.08 staff_space);
+
+ draw z3
+ -- z4;
+
+ addto currentpicture also currentpicture
+ xscaled -1
+ yscaled -1
+ shifted (0.40 staff_space, 0.0 staff_space);
+
+ set_char_box (0.00 staff_space# + 0.40 linethickness#,
+ 0.40 staff_space# + 0.40 linethickness#,
+ 0.65 staff_space# + 0.11 staff_space#,
+ 0.65 staff_space# + 0.11 staff_space#);
+
+ labels (1, 2, 3, 4);
+fet_endchar;
+
+
+%%%%%%%%
+%
+%
+%
+% MENSURAL NOTATION
+%
+%
+%
+fet_beginchar ("Mensural Sharp" , "mensural1");
+ save stemthick;
+
+ define_pixels (stemthick);
+
+ stemthick# = linethickness#;
+
+ save circle, pat, T;
+ path circle, pat;
+ transform T;
+
+ T := identity scaled 0.8 stemthick;
+ pickup pencircle transformed T;
+ circle := fullcircle transformed T;
+
+ z1 = 0.4 staff_space * (0.8, 1);
+ z1 = -z2;
+
+ pat := get_subpath (circle, z1 - z2, z2 - z1, z1)
+ -- get_subpath (circle, z2 - z1, z1 - z2, z2)
+ -- cycle;
+
+ fill pat;
+ fill pat xscaled -1;
+ fill pat shifted (0.20 staff_space, 0);
+ fill pat xscaled -1 shifted (0.20 staff_space, 0);
+
+ set_char_box (0.8 * 0.4 staff_space# + 0.4 stemthick#,
+ (0.8 * 0.4 + 0.2) * staff_space# + 0.4 stemthick#,
+ 0.4 staff_space# + 0.4 stemthick#,
+ 0.4 staff_space# + 0.4 stemthick#);
+
+ labels (1, 2);
+fet_endchar;
+
+
+fet_beginchar ("Mensural Flat" , "mensuralM1");
+ save stemthick;
+
+ define_pixels (stemthick);
+
+ stemthick# = linethickness#;
+
+ save ellipse, pat, outline, T;
+ path ellipse, pat, outline;
+ transform T;
+
+ T := identity xscaled 1.4 stemthick
+ yscaled 0.6 stemthick
+ rotated 45;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ z1 = (0.00 staff_space, +1.80 staff_space);
+ z2 = (0.00 staff_space, -0.25 staff_space);
+ z3 = (0.35 staff_space, -0.25 staff_space);
+ z4 = (0.35 staff_space, +0.25 staff_space);
+ z5 = (0.00 staff_space, +0.25 staff_space);
+
+ pat := z2
+ .. z3
+ .. z4
+ .. z5;
+
+ save dirs, s;
+ pair dirs[];
+
+ s := 1/4;
+
+ % we approximate `draw pat'
+ for i = 2 step s until (length pat + 2):
+ dirs[i] := direction (i - 2) of pat;
+ endfor;
+
+ outline := get_subpath (ellipse, up, down, z1)
+ -- get_subpath (ellipse, down, dirs2, z2)
+ for i = (2 + s) step s until (length pat + 2 - s):
+ .. get_subpoint (ellipse, dirs[i],
+ point (i - 2) of pat)
+ endfor
+ .. top z5
+ -- bot z5
+ for i = (length pat + 2 - s) step -s until 2:
+ .. get_subpoint (ellipse, -dirs[i],
+ point (i - 2) of pat)
+ endfor
+ -- get_subpoint (ellipse, up, z2)
+ -- cycle;
+
+ fill outline;
+
+ set_char_box (0.00 staff_space# + 0.75 stemthick#,
+ 0.40 staff_space# + 0.75 stemthick#,
+ 0.25 staff_space# + 0.75 stemthick#,
+ 1.80 staff_space# + 0.75 stemthick#);
+
+ labels (1, 2, 3, 4, 5);
+fet_endchar;
+
+
+fet_beginchar ("Hufnagel Flat" , "hufnagelM1");
+ save stemthick;
+
+ define_pixels (stemthick);
+
+ stemthick# = linethickness#;
+
+ save ellipse, pat, T;
+ path ellipse, pat;
+ transform T;
+
+ T := identity xscaled 2.4 stemthick
+ yscaled 0.4 stemthick
+ rotated 45;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ z1 = (0.00 staff_space, +1.80 staff_space);
+ z2 = (0.00 staff_space, -0.15 staff_space);
+ z3 = (0.25 staff_space, -0.30 staff_space);
+ z4 = (0.50 staff_space, +0.00 staff_space);
+ z5 = (0.30 staff_space, +0.30 staff_space);
+ z6 = (0.00 staff_space, +0.15 staff_space);
+
+ pat := z3
+ .. z4
+ .. z5;
+
+ save t;
+ numeric t[];
+
+ % we have to find the envelope intersections (if any)
+ t1 = find_envelope_cusp (reverse ellipse, pat, 1/256) + 3;
+ if t1 < 3:
+ t1 := 3;
+ fi;
+ t2 = find_envelope_cusp (ellipse, reverse pat, 1/256);
+ if t2 < 0:
+ t2 := 3;
+ else:
+ t2 := length pat - t2 + 3;
+ fi;
+
+ save dirs, s;
+ pair dirs[];
+
+ s := 1/8;
+
+ % we approximate `draw pat'
+ for i = 3 step s until 5:
+ dirs[i] := direction (i - 3) of pat;
+ endfor;
+
+ fill get_subpath (ellipse, up, down, z1)
+ -- get_subpath (ellipse, down, z3 - z2, z2)
+ -- get_subpoint (ellipse, z3 - z2, z3)
+ for i = 3 step s until 5:
+ .. get_subpoint (ellipse, dirs[i],
+ point (i - 3) of pat)
+ endfor
+ .. get_subpoint (ellipse, z6 - z5, z5)
+ -- get_subpoint (ellipse, z6 - z5, z6)
+ -- get_subpoint (ellipse, z5 - z6, z6)
+ -- get_subpoint (ellipse, z5 - z6, z5)
+ -- get_subpoint (ellipse, -dirs[5], z5)
+ for i = (5 - s) step -s until t2:
+ .. get_subpoint (ellipse, -dirs[i],
+ point (i - 3) of pat)
+ endfor
+ .. get_subpoint (ellipse, -direction (t2 - 3) of pat,
+ point (t2 - 3) of pat)
+ -- get_subpoint (ellipse, -direction (t1 - 3) of pat,
+ point (t1 - 3) of pat)
+ for i = (floor ((t1 - 3) / s) * s + 3) step -s until (3 + s):
+ .. get_subpoint (ellipse, -dirs[i],
+ point (i - 3) of pat)
+ endfor
+ .. get_subpoint (ellipse, -dirs[3], z3)
+ -- get_subpoint (ellipse, z2 - z3, z3)
+ -- get_subpoint (ellipse, z2 - z3, z2)
+ -- get_subpoint (ellipse, up, z2)
+ -- cycle;
+
+% draw z1
+% -- z2
+% -- pat
+% -- z6;
+
+ set_char_box (0.00 staff_space# + 1.0 stemthick#,
+ 0.50 staff_space# + 1.0 stemthick#,
+ 0.30 staff_space# + 0.5 stemthick#,
+ 1.80 staff_space# + 0.5 stemthick#);
+
+ labels (1, 2, 3, 4, 5, 6);
+fet_endchar;
+
+
+fet_endgroup ("accidentals");
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-clefs.mf b/muse2/share/scoreglyphs/feta-original/parmesan-clefs.mf
new file mode 100644
index 00000000..afd5058e
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-clefs.mf
@@ -0,0 +1,1693 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-clefs.mf -- implement ancient clefs
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2001--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+fet_begingroup ("clefs");
+
+%
+% character aligment:
+%
+% Each clef is associated with a particular pitch: the treble clef
+% with the `g', the alto clef with the `c', the bass clef with the
+% `f', etc. The shape of each clef character defines a vertical
+% position that is assumed to represent this pitch. For the treble
+% clef, it is the vertical position of the center of the spiral
+% ending that represents the `g' pitch. For the bass clef, it is
+% the center between the two fat dots that define the vertical
+% position of the `f' pitch. For the alto clef, it is the vertical
+% center of the clef that is aligned with the `c' pitch. For each
+% clef character, this center should be vertically aligned with the
+% point (0, 0). The horizontal alignment of each clef character
+% should be such that the vertical line through the point (0, 0)
+% touches the left-most edge of the clef.
+%
+% TODO: document exact_center
+%
+% set_char_box() conventions:
+%
+% * breapth: Ignored (as far as I know). Should be set to 0.
+%
+% * width: Should match the clef's width.
+%
+% * depth: Should match the bottom edge of the clef. Affects vertical
+% collision handling.
+%
+% * height: Should match the top edge of the clef. Affects vertical
+% collision handling.
+%
+
+
+%%%%%%%%
+%
+%
+%
+% Editio Vaticana
+%
+%
+%
+def draw_vaticana_do_clef (expr exact_center, reduction) =
+ save reduced_il;
+
+ reduced_il# = staff_space# * reduction;
+
+ set_char_box (0 - xpart exact_center,
+ 0.5 reduced_il# + xpart exact_center,
+ 0.8 reduced_il# - ypart exact_center,
+ 0.8 reduced_il# + ypart exact_center);
+
+ define_pixels (reduced_il);
+
+ save pat, ellipse, clef, T;
+ path pat, ellipse, clef;
+ transform T;
+
+ T := identity xscaled 0.6 linethickness
+ yscaled 0.6 reduced_il;
+ pickup pencircle transformed T;
+ ellipse := reverse fullcircle transformed T;
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ rt z11 = (xoffs + 0.50 reduced_il, yoffs - .45 reduced_il);
+ z12 = (xoffs + 0.25 reduced_il, yoffs - .50 reduced_il);
+ lft z13 = (xoffs + 0.00 reduced_il, yoffs - .28 reduced_il);
+ lft z14 = (xoffs, yoffs);
+
+ pat := z11
+ .. z12
+ .. z13
+ -- z14;
+
+ save shift;
+ pair shift;
+
+ % adjust vertically to fit into bounding box
+ shift = find_tangent_shift (((0, -d + 0.3 reduced_il)
+ -- (w, -d + 0.3 reduced_il)), pat,
+ (0, -d / 2), (0, d / 2));
+ pat := pat shifted shift;
+
+ clef := rt z14{down}
+ .. top (point 1 of pat)
+ .. get_subpath (ellipse,
+ -direction 0 of pat, direction 0 of pat,
+ point 0 of pat)
+ .. bot (point 1 of pat)
+ .. get_subpath (ellipse,
+ direction 2 of pat, up,
+ point 2 of pat);
+
+ fill clef
+ -- reverse clef yscaled -1
+ -- cycle;
+
+ labels (11, 12, 13, 14);
+enddef;
+
+
+fet_beginchar ("Ed. Vat. do clef", "vaticana.do");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_vaticana_do_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("Ed. Vat. do clef", "vaticana.do_change");
+ draw_vaticana_do_clef ((0, 0), 1.0); % no reduction
+fet_endchar;
+
+
+def draw_vaticana_fa_clef (expr exact_center, reduction) =
+ save reduced_il, xoffs, yoffs;
+
+ reduced_il# = staff_space# * reduction;
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (reduced_il, xoffs, yoffs);
+
+ % left-handed punctum
+ save ellipse, pat, T;
+ path ellipse, pat;
+ transform T;
+
+ T := identity xscaled 0.6 linethickness
+ yscaled 0.5 reduced_il;
+ pickup pencircle transformed T;
+ ellipse := reverse fullcircle transformed T;
+
+ lft z21 = (xoffs + 0.00 reduced_il, yoffs + 0.00 reduced_il);
+ z22 = (xoffs + 0.25 reduced_il, yoffs + 0.05 reduced_il);
+ rt z23 = (xoffs + 0.50 reduced_il, yoffs - 0.05 reduced_il);
+
+ pat := z21
+ .. z22
+ .. z23;
+
+ fill get_subpath (ellipse,
+ -direction 0 of pat, direction 0 of pat, z21)
+ .. top z22
+ .. get_subpath (ellipse,
+ direction 2 of pat, -direction 2 of pat, z23)
+ .. bot z22
+ .. cycle;
+
+ % stem
+ pickup pencircle scaled 0.6 linethickness;
+
+ x23 = x24;
+ yoffs = bot y24 + 1.5 reduced_il;
+
+ draw_rounded_block (bot lft z24, top rt z23, 0.6 linethickness);
+
+ labels (21, 22, 23, 24);
+
+ % right-handed puncta as in do clef
+ draw_vaticana_do_clef (exact_center + (0.55 reduced_il#, 0),
+ reduction);
+
+ set_char_box (0 - xpart exact_center,
+ 1.05 reduced_il# + xpart exact_center,
+ 1.5 reduced_il# - ypart exact_center,
+ 0.8 reduced_il# + ypart exact_center);
+enddef;
+
+
+fet_beginchar ("Ed. Vat. fa clef", "vaticana.fa");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_vaticana_fa_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("Ed. Vat. fa clef", "vaticana.fa_change");
+ draw_vaticana_fa_clef ((0, 0), 1.0); % no reduction
+fet_endchar;
+
+
+%%%%%%%%
+%
+%
+%
+% Editio Medicaea
+%
+%
+%
+def draw_medicaea_do_clef (expr exact_center, reduction) =
+ save reduced_il, reduced_slt;
+
+ reduced_il# = staff_space# * reduction;
+ reduced_slt# = linethickness# * reduction;
+
+ define_pixels (reduced_il);
+ define_pixels (reduced_slt);
+
+ set_char_box (0 - xpart exact_center,
+ 1.0 reduced_il# + xpart exact_center,
+ 1.5 reduced_il# - ypart exact_center,
+ 1.5 reduced_il# + ypart exact_center);
+
+ save flag_height;
+
+ flag_height# = 0.5 reduced_il#;
+
+ define_pixels (flag_height);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ % flags
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled reduced_slt
+ yscaled flag_height;
+ pickup pencircle transformed T;
+ ellipse := reverse fullcircle transformed T;
+
+ xoffs = lft x1 = rt x2 - reduced_il;
+ y1 = yoffs + 0.5 (reduced_il - flag_height - staff_space);
+ y2 = y1 - reduced_il + flag_height;
+
+ fill top z1
+ -- get_subpath (ellipse, z2 - z1, z1 - z2, z2)
+ -- bot z1
+ -- cycle;
+
+ xoffs = lft x3 = rt x4 - reduced_il;
+ y3 = yoffs + 0.5 (reduced_il - flag_height + staff_space);
+ y4 = y3 - reduced_il + flag_height;
+
+ fill top z3
+ -- get_subpath (ellipse, z4 - z3, z3 - z4, z4)
+ -- bot z3
+ -- cycle;
+
+ % stem
+ pickup pencircle scaled reduced_slt;
+
+ lft x5 = lft x6 = xoffs;
+ yoffs = top y6 - 1.5 reduced_il = bot y5 + 1.5 reduced_il;
+
+ draw_rounded_block (bot lft z5, top rt z6, reduced_slt);
+
+ labels (1, 2, 3, 4, 5, 6);
+enddef;
+
+
+fet_beginchar ("Ed. Med. do clef", "medicaea.do");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_medicaea_do_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("Ed. Med. do clef", "medicaea.do_change");
+ draw_medicaea_do_clef ((0, 0), .8);
+fet_endchar;
+
+
+def draw_medicaea_fa_clef (expr exact_center, reduction) =
+ % inspired by Regensburger Edition of Medicaea (1885/86), in:
+ % MGG, volume 2, col. 1327 ("Choralreform"), fig. 2.
+
+ save reduced_il, reduced_slt;
+
+ reduced_il# = staff_space# * reduction;
+ reduced_slt# = linethickness# * reduction;
+
+ define_pixels (reduced_il);
+ define_pixels (reduced_slt);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ % stem
+ pickup pencircle scaled reduced_slt;
+
+ x11 = x12 = xoffs + 0.4 reduced_il;
+ y11 = yoffs = bot y12 + 1.5 reduced_il;
+
+ draw_rounded_block (bot lft z12, top rt z11, reduced_slt);
+
+ % left-handed punctum
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled reduced_slt
+ yscaled reduced_il;
+ pickup pencircle transformed T;
+ ellipse := reverse fullcircle transformed T;
+
+ lft z13 = (xoffs, yoffs);
+ rt z14 = z11 + (reduced_slt / 2, 0);
+
+ fill get_subpath (ellipse, left, right, z13)
+ -- get_subpath (ellipse, right, left, z14)
+ -- cycle;
+
+ labels (11, 12, 13, 14);
+
+ % right-handed puncta as in do clef
+ draw_medicaea_do_clef (exact_center + (0.7 reduced_il#, 0),
+ reduction);
+
+ set_char_box (0 - xpart exact_center,
+ 1.7 reduced_il# + xpart exact_center,
+ 1.5 reduced_il# - ypart exact_center,
+ 1.5 reduced_il# + ypart exact_center);
+enddef;
+
+
+fet_beginchar ("Ed. Med. fa clef", "medicaea.fa");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_medicaea_fa_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("Ed. Med. fa clef", "medicaea.fa_change");
+ draw_medicaea_fa_clef ((0, 0), .8);
+fet_endchar;
+
+
+%%%%%%%%
+%
+%
+%
+% Mensural Notation
+%
+%
+%
+
+%
+% width: interval from left end to right end
+% height: interval from bottom of lower beam to top of upper beam
+% exact_center: the coordinates of the vertical center point of the
+% left edge.
+%
+def draw_brevis (expr exact_center, bwidth, bheight, blinethickness) =
+ save brevis_width, brevis_height, linethickness;
+
+ brevis_width# = bwidth;
+ brevis_height# = bheight;
+ linethickness# = blinethickness;
+
+ save beam_width, beam_height;
+ save serif_size, serif_protrude, hole_height;
+
+ beam_width# = 1.4 linethickness#;
+ hole_height# = 3 linethickness#;
+ 2 beam_height# + hole_height# = brevis_height#;
+ serif_size# = (hole_height# - linethickness#) / 2;
+ serif_protrude# = 1.5 serif_size#;
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+ define_pixels (brevis_width, brevis_height, linethickness);
+ define_pixels (beam_width, beam_height, serif_size, serif_protrude);
+
+ z1l = (xoffs, yoffs - linethickness);
+ z2r = z1r + serif_size * (1, -1);
+ z3l = z2l + (-serif_size, -serif_protrude);
+
+ penpos1 (beam_width, 0);
+ penpos2 (beam_height, 90);
+ penpos3 (beam_width, 180);
+
+ save pat_in, pat_out;
+ path pat_in, pat_out;
+
+ pat_out := z3r{down}
+ .. z3l{up}
+ .. z2l{right};
+ pat_out := pat_out
+ -- reverse pat_out xscaled -1
+ shifted (2 xoffs + brevis_width, 0);
+ pat_out := pat_out
+ -- reverse pat_out yscaled -1
+ shifted (0, 2 yoffs)
+ -- cycle;
+
+ pat_in := z1r{down}
+ .. z2r{right};
+ pat_in := pat_in
+ -- reverse pat_in xscaled -1
+ shifted (2 xoffs + brevis_width, 0);
+ pat_in := pat_in
+ -- reverse pat_in yscaled -1
+ shifted (0, 2 yoffs)
+ -- cycle;
+
+ fill pat_out;
+ unfill pat_in;
+
+ penlabels (1, 2, 3);
+enddef;
+
+%
+% Draw two brevis notes; the second one shifted down by `shift'.
+% The other parameters are the same as with `draw_brevis'.
+%
+def draw_double_brevis (expr exact_center, bwidth, bheight,
+ blinethickness, shift) =
+ save brevis_width, brevis_height, linethickness;
+
+ brevis_width# = bwidth;
+ brevis_height# = bheight;
+ linethickness# = blinethickness;
+
+ save beam_width, beam_height;
+ save serif_size, serif_protrude, hole_height;
+
+ beam_width# = 1.4 linethickness#;
+ hole_height# = 3 linethickness#;
+ 2 beam_height# + hole_height# = brevis_height#;
+ serif_size# = (hole_height# - linethickness#) / 2;
+ serif_protrude# = 1.5 serif_size#;
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+ define_pixels (brevis_width, brevis_height, linethickness);
+ define_pixels (beam_width, beam_height, serif_size, serif_protrude);
+
+ z1l = (xoffs, yoffs - linethickness);
+ z2r = z1r + serif_size * (1, -1);
+ z3l = z2l + (-serif_size, -serif_protrude);
+
+ penpos1 (beam_width, 0);
+ penpos2 (beam_height, 90);
+ penpos3 (beam_width, 180);
+
+ z4 = z1 shifted (0, -shift);
+ z5 = z2 shifted (0, -shift);
+ z6 = z3 shifted (0, -shift);
+
+ penpos4 (beam_width, 0);
+ penpos5 (beam_height, 90);
+ penpos6 (beam_width, 180);
+
+ save pat_in, pat_out;
+ path pat_in, pat_out;
+
+ pat_out := z6r{down}
+ .. z6l{up}
+ .. z5l{right};
+ pat_out := pat_out
+ -- reverse pat_out xscaled -1
+ shifted (2 xoffs + brevis_width, 0);
+ pat_out := pat_out
+ -- reverse pat_out yscaled -1
+ shifted (0, shift - 2 yoffs)
+ -- cycle;
+
+ fill pat_out;
+
+ pat_in := z1r{down}
+ .. z2r{right};
+ pat_in := pat_in
+ -- reverse pat_in xscaled -1
+ shifted (2 xoffs + brevis_width, 0);
+ pat_in := pat_in
+ -- reverse pat_in yscaled -1
+ shifted (0, 2 yoffs)
+ -- cycle;
+
+ unfill pat_in;
+ unfill pat_in shifted (0, -shift);
+
+ penlabels (1, 2, 3, 4, 5, 6);
+enddef;
+
+
+%
+% Draw three brevis notes; the second one shifted down by `shift',
+% the third one by `2 shift'.
+% The other parameters are the same as with `draw_brevis'.
+%
+def draw_triple_brevis (expr exact_center, bwidth, bheight,
+ blinethickness, shift) =
+ save brevis_width, brevis_height, linethickness;
+
+ brevis_width# = bwidth;
+ brevis_height# = bheight;
+ linethickness# = blinethickness;
+
+ save beam_width, beam_height;
+ save serif_size, serif_protrude, hole_height;
+
+ beam_width# = 1.4 linethickness#;
+ hole_height# = 3 linethickness#;
+ 2 beam_height# + hole_height# = brevis_height#;
+ serif_size# = (hole_height# - linethickness#) / 2;
+ serif_protrude# = 1.5 serif_size#;
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+ define_pixels (brevis_width, brevis_height, linethickness);
+ define_pixels (beam_width, beam_height, serif_size, serif_protrude);
+
+ z1l = (xoffs, yoffs - linethickness);
+ z2r = z1r + serif_size * (1, -1);
+ z3l = z2l + (-serif_size, -serif_protrude);
+
+ penpos1 (beam_width, 0);
+ penpos2 (beam_height, 90);
+ penpos3 (beam_width, 180);
+
+ z7 = z1 shifted (0, -2 shift);
+ z8 = z2 shifted (0, -2 shift);
+ z9 = z3 shifted (0, -2 shift);
+
+ penpos7 (beam_width, 0);
+ penpos8 (beam_height, 90);
+ penpos9 (beam_width, 180);
+
+ save pat_in, pat_out;
+ path pat_in, pat_out;
+
+ pat_out := z9r{down}
+ .. z9l{up}
+ .. z8l{right};
+ pat_out := pat_out
+ -- reverse pat_out xscaled -1
+ shifted (2 xoffs + brevis_width, 0);
+ pat_out := pat_out
+ -- reverse pat_out yscaled -1
+ shifted (0, -2 yoffs)
+ -- cycle;
+
+ fill pat_out;
+
+ pat_in := z1r{down}
+ .. z2r{right};
+ pat_in := pat_in
+ -- reverse pat_in xscaled -1
+ shifted (2 xoffs + brevis_width, 0);
+ pat_in := pat_in
+ -- reverse pat_in yscaled -1
+ shifted (0, 2 yoffs)
+ -- cycle;
+
+ unfill pat_in;
+ unfill pat_in shifted (0, -shift);
+ unfill pat_in shifted (0, -2 shift);
+
+ penlabels (1, 2, 3, 7, 8, 9);
+enddef;
+
+
+def draw_neomensural_c_clef (expr exact_center, reduction) =
+ save reduced_il, reduced_slt, stem_width;
+
+ reduced_il# = staff_space# * reduction;
+ reduced_slt# = linethickness# * reduction;
+ stem_width# = 1.4 reduced_slt#;
+
+ define_pixels (reduced_il, reduced_slt, stem_width);
+
+ set_char_box (0 - xpart exact_center,
+ 2 reduced_il# + 6 reduced_slt# + xpart exact_center,
+ 2 reduced_il# - ypart exact_center,
+ 2 reduced_il# + ypart exact_center);
+
+ draw_brevis (exact_center + (3 reduced_slt#, 0),
+ 2 reduced_il#, reduced_il#, reduced_slt#);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ save ellipse, pat, T;
+ path ellipse, pat;
+ transform T;
+
+ T := identity xscaled stem_width
+ yscaled blot_diameter;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ lft x11 = lft x12 = xoffs;
+ top y12 - bot y11 = 4 reduced_il;
+ top y12 + bot y11 = 2 yoffs;
+ x13 = x3;
+ y13 = y11;
+ rt x14 = rt x15 = w;
+ y14 = y11;
+ y15 = y12;
+
+ pat := get_subpath (ellipse, down, up, z13)
+ -- z3l
+ -- z3r
+ -- cycle;
+
+ fill get_subpath (ellipse, down, up, z11)
+ -- get_subpath (ellipse, up, down, z12)
+ -- cycle;
+ fill get_subpath (ellipse, down, up, z14)
+ -- get_subpath (ellipse, up, down, z15)
+ -- cycle;
+
+ fill pat;
+ fill pat xscaled -1
+ shifted (w, 0);
+ fill pat yscaled -1
+ shifted (0, 2 yoffs);
+ fill pat scaled -1
+ shifted (w, 2 yoffs);
+
+ labels (11, 12, 13, 14, 15);
+enddef;
+
+
+fet_beginchar ("neo-mensural c clef", "neomensural.c");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_neomensural_c_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("neo-mensural c clef", "neomensural.c_change");
+ draw_neomensural_c_clef ((0, 0), .8);
+fet_endchar;
+
+
+def draw_petrucci_c_clef (expr exact_center, flare_align, reduction) =
+ % inspired by Josquin Desprez, "Stabat Mater", Libro tertio,
+ % 1519, printed by Petrucci, in: MGG, volume 7, Table 11.
+ % Also by Petrucci's Canti C, Venedig 1503. In: MGG, volume
+ % 9, p. 1681/1682.
+
+ save reduced_il, reduced_slt;
+
+ reduced_il# = staff_space# * reduction;
+ reduced_slt# = linethickness# * reduction;
+
+ define_pixels (reduced_il);
+
+ draw_double_brevis (exact_center + (0, 0.5 staff_space#),
+ reduced_il#, reduced_il#, reduced_slt#,
+ staff_space);
+
+ save half_reduced_il, left_depth, left_height;
+
+ half_reduced_il# = staff_space# * sqrt (reduction);
+ left_height# = half_reduced_il# * min (3.2, 3.2 + 0.2 + flare_align);
+ left_depth# = half_reduced_il# * min (3.2, 3.2 + 0.2 - flare_align);
+
+ define_pixels (half_reduced_il);
+ define_pixels (left_depth, left_height);
+
+ set_char_box (0 - xpart exact_center,
+ reduced_il# + xpart exact_center,
+ left_depth# - ypart exact_center,
+ left_height# + ypart exact_center);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled 1.4 linethickness
+ yscaled blot_diameter;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ lft x11 = lft x13 = xoffs;
+ top y11 = yoffs + left_height;
+ bot y13 = yoffs - left_depth;
+ rt x15 = rt x17 = xoffs + brevis_width;
+ y15 = min (y11 - 0.2 half_reduced_il, yoffs + 2.2 half_reduced_il);
+ y17 = max (y13 + 0.2 half_reduced_il, yoffs - 2.2 half_reduced_il);
+
+ z12 = z14 yscaled -1;
+ z14 = z6;
+ z16 = z18 yscaled -1;
+ rt z18 = lft z14 shifted (brevis_width, 0);
+
+ penpos12 (1.4 linethickness, 0);
+ penpos14 (1.4 linethickness, 0);
+ penpos16 (1.4 linethickness, 0);
+ penpos18 (1.4 linethickness, 0);
+
+ if top y11 > -y6 + 0.7 linethickness:
+ fill get_subpath (ellipse, up, down, z11)
+ -- z12l
+ -- z12r
+ -- cycle;
+ fi;
+ if bot y13 < y6 - 0.7 linethickness:
+ fill get_subpath (ellipse, down, up, z13)
+ -- z14r
+ -- z14l
+ -- cycle;
+ fi;
+ if top y15 > -y6 + 0.7 linethickness:
+ fill get_subpath (ellipse, up, down, z15)
+ -- z16l
+ -- z16r
+ -- cycle;
+ fi;
+ if bot y17 < y6 - 0.7 linethickness:
+ fill get_subpath (ellipse, down, up, z17)
+ -- z18r
+ -- z18l
+ -- cycle;
+ fi;
+
+ labels (11, 13, 15, 17);
+ penlabels (12, 14, 16, 18);
+enddef;
+
+
+fet_beginchar ("petrucci c1 clef", "petrucci.c1");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_petrucci_c_clef ((0, 0), +2, 1.0);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c1 clef", "petrucci.c1_change");
+ draw_petrucci_c_clef ((0, 0), +2, .8);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c2 clef", "petrucci.c2");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_petrucci_c_clef ((0, 0), +1, 1.0);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c2 clef", "petrucci.c2_change");
+ draw_petrucci_c_clef ((0, 0), +1, .8);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c3 clef", "petrucci.c3");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_petrucci_c_clef ((0, 0), 0, 1.0);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c3 clef", "petrucci.c3_change");
+ draw_petrucci_c_clef ((0, 0), 0, .8);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c4 clef", "petrucci.c4");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_petrucci_c_clef ((0, 0), -1, 1.0);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c4 clef", "petrucci.c4_change");
+ draw_petrucci_c_clef ((0, 0), -1, .8);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c5 clef", "petrucci.c5");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_petrucci_c_clef ((0, 0), -2, 1.0);
+fet_endchar;
+
+
+fet_beginchar ("petrucci c5 clef", "petrucci.c5_change");
+ draw_petrucci_c_clef ((0, 0), -2, .8);
+fet_endchar;
+
+
+def draw_mensural_c_clef (expr exact_center, reduction) =
+ % inspired by Ockeghem, "Missa Prolationum", in: MGG, volume
+ % 9, table 94.
+
+ save reduced_il;
+
+ reduced_il# = staff_space# * reduction;
+
+ define_pixels (reduced_il);
+
+ draw_triple_brevis (exact_center + (0, 0.5 staff_space#),
+ 2 reduced_il#, 0.8 staff_space#,
+ 0.8 linethickness#, staff_space);
+
+ save half_reduced_il;
+
+ half_reduced_il# = staff_space# * sqrt (reduction);
+
+ define_pixels (half_reduced_il);
+
+ set_char_box (0 - xpart exact_center,
+ 2 reduced_il# + xpart exact_center,
+ 2.2 half_reduced_il# + staff_space# -
+ 2 ypart exact_center,
+ 2.2 half_reduced_il# + 2 ypart exact_center);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled 1.4 linethickness
+ yscaled blot_diameter;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ lft x11 = lft x13 = xoffs;
+ top y11 = yoffs + 2.2 half_reduced_il;
+ bot y13 = yoffs - 2.2 half_reduced_il - staff_space;
+ rt x15 = rt x17 = xoffs + brevis_width;
+ y15 = yoffs + 1.4 half_reduced_il;
+ y17 = yoffs - 1.4 half_reduced_il - staff_space;
+
+ z12 = z14 yscaled -1 shifted (0, -staff_space);
+ z14 = z9;
+ z16 = z18 yscaled -1 shifted (0, -staff_space);
+ rt z18 = lft z14 shifted (brevis_width, 0);
+
+ penpos12 (1.4 linethickness, 0);
+ penpos14 (1.4 linethickness, 0);
+ penpos16 (1.4 linethickness, 0);
+ penpos18 (1.4 linethickness, 0);
+
+ fill get_subpath (ellipse, up, down, z11)
+ -- z12l
+ -- z12r
+ -- cycle;
+ fill get_subpath (ellipse, down, up, z13)
+ -- z14r
+ -- z14l
+ -- cycle;
+ fill get_subpath (ellipse, up, down, z15)
+ -- z16l
+ -- z16r
+ -- cycle;
+ fill get_subpath (ellipse, down, up, z17)
+ -- z18r
+ -- z18l
+ -- cycle;
+
+ labels (11, 13, 15, 17);
+ penlabels (12, 14, 16, 18);
+enddef;
+
+
+fet_beginchar ("mensural c clef", "mensural.c");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_mensural_c_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("mensural c clef", "mensural.c_change");
+ draw_mensural_c_clef ((0, 0), .8);
+fet_endchar;
+
+
+def draw_diamond (expr exact_center, reduction) =
+ save stem_width, reduced_nht, holeheight, beamheight;
+ save rh_height, rh_width;
+
+ stem_width# = 1.4 reduced_slt#;
+ reduced_nht# = noteheight# * reduction;
+ holeheight# = 3 reduced_slt#;
+ beamheight# = 0.4 (reduced_nht# - holeheight#);
+
+ rh_height# = 1.2 staff_space# * reduction;
+ rh_width# / rh_height# = tand (30);
+
+ define_pixels (beamheight, stem_width);
+ define_pixels (rh_height, rh_width);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled beamheight
+ yscaled stem_width
+ rotated 45;
+ pickup pencircle transformed T;
+ ellipse := reverse fullcircle transformed T;
+
+ x21 := xoffs - rh_width / 2;
+ y21 := yoffs;
+ x22 := xoffs;
+ y22 := yoffs + rh_height / 2;
+ x23 := xoffs + rh_width / 2;
+ y23 := yoffs;
+ x24 := xoffs;
+ y24 := yoffs - rh_height / 2;
+
+ fill get_subpath (ellipse, z21 - z24, z22 - z21, z21)
+ -- get_subpath (ellipse, z22 - z21, z23 - z22, z22)
+ -- get_subpath (ellipse, z23 - z22, z24 - z23, z23)
+ -- get_subpath (ellipse, z24 - z23, z21 - z24, z24)
+ -- cycle;
+
+ save l;
+ path l[];
+
+ l2122 := (directionpoint (z21 - z22) of ellipse) shifted z21
+ -- (directionpoint (z21 - z22) of ellipse) shifted z22;
+ l2223 := (directionpoint (z22 - z23) of ellipse) shifted z22
+ -- (directionpoint (z22 - z23) of ellipse) shifted z23;
+ l2324 := (directionpoint (z23 - z24) of ellipse) shifted z23
+ -- (directionpoint (z23 - z24) of ellipse) shifted z24;
+ l2421 := (directionpoint (z24 - z21) of ellipse) shifted z24
+ -- (directionpoint (z24 - z21) of ellipse) shifted z21;
+
+ unfill l2122 intersectionpoint l2223
+ -- l2223 intersectionpoint l2324
+ -- l2324 intersectionpoint l2421
+ -- l2421 intersectionpoint l2122
+ -- cycle;
+
+ labels (21, 22, 23, 24);
+enddef;
+
+
+def draw_petrucci_f_clef (expr exact_center, reduction) =
+ % inspired by L'homme arme super voces musicales in Misse
+ % Josquin, 1502, Petrucci, in: MGG, volume 7, col. 200; also
+ % inspired by Gaspar van Weerbeke, "Virgo Maria" (1502), in:
+ % MGG, volume 9, col. 653 ("Motette"), fig. 3.; also by Andr'e
+ % Campra, "Entr'ee des s'er'enades" (1710), in: MGG, volume 2,
+ % col. 1649 ("Contredanse"), fig. 2.
+
+ save interline, reduced_il, reduced_slt;
+
+ interline# = staff_space#;
+ reduced_il# = staff_space# * reduction;
+ reduced_slt# = linethickness# * reduction;
+
+ draw_brevis (exact_center, reduced_il#, reduced_il#, reduced_slt#);
+ draw_diamond (exact_center +
+ (1.6 interline# * reduction, interline# / 2),
+ reduction);
+ draw_diamond (exact_center +
+ (1.6 interline# * reduction, -interline# / 2),
+ reduction);
+
+ define_pixels (interline, reduced_il, reduced_slt);
+
+ save stem_width;
+
+ stem_width# = 1.4 reduced_slt#;
+
+ define_pixels (stem_width);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ % brevis stem
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled stem_width
+ yscaled blot_diameter;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ rt x8 = xoffs + reduced_il;
+ y8 = y3;
+ rt z9 = (xoffs + reduced_il, yoffs - 4 reduced_il);
+
+ penpos8 (stem_width, 0);
+
+ fill get_subpath (ellipse, down, up, z9)
+ -- z8r
+ -- z8l
+ -- cycle;
+
+ % upper diamond's stem
+ z10 = (xoffs + 1.6 interline * reduction + stem_width / 2,
+ yoffs + interline * reduction);
+ top z11 = z10 + (0, 1.5 interline * reduction);
+
+ penpos10 (stem_width, 0);
+
+ fill get_subpath (ellipse, up, down, z11)
+ -- z10l
+ -- z10r
+ -- cycle;
+
+ % lower diamond's stem
+ z12 = (xoffs + 1.6 interline * reduction - stem_width / 2,
+ yoffs - interline * reduction);
+ bot z13 = z12 + (0, -3.5 interline * reduction);
+
+ penpos12 (stem_width, 0);
+
+ fill get_subpath (ellipse, down, up, z13)
+ -- z12r
+ -- z12l
+ -- cycle;
+
+ save reduced_il, rh_height, rh_width;
+
+ reduced_il# = staff_space# * reduction;
+ rh_height# = 1.2 reduced_il#;
+ rh_width# / rh_height# = tand (30);
+
+ set_char_box (0 - xpart exact_center,
+ 1.6 interline# * reduction + 0.5 rh_width# +
+ xpart exact_center,
+ 4.5 interline# * reduction - ypart exact_center,
+ 2.5 interline# * reduction + ypart exact_center);
+
+ labels (9, 11, 13);
+ penlabels (8, 10, 12);
+enddef;
+
+
+fet_beginchar ("petrucci f clef", "petrucci.f");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_petrucci_f_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("petrucci f clef", "petrucci.f_change");
+ draw_petrucci_f_clef ((0, 0), .8);
+fet_endchar;
+
+
+def draw_mensural_f_clef (expr exact_center, reduction) =
+ % inspired by Philippe le Duc, "Dite Signori" (1590), in: MGG,
+ % volume 3, col. 848 ("Duc"); also by John Dowland, "The First
+ % Booke of Songes" (1597), in: MGG, volume 3, col. 721
+ % ("Dowland"), fig. 3.
+
+ save width, reduced_slt, stem_width, dot_diameter;
+
+ width# = 1.2 staff_space# * reduction;
+ reduced_slt# = linethickness# * reduction;
+ stem_width# = 1.4 reduced_slt#;
+ dot_diameter# = 0.1 reduction * staff_space#;
+
+ define_pixels (width, stem_width, staff_space, dot_diameter);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled 0.2 width
+ yscaled stem_width
+ rotated 45;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ % half circle
+ lft z10 = (0, 0);
+
+ save pat;
+ path pat;
+
+ pat := halfcircle scaled width
+ rotated -90
+ shifted (z10 - (xoffs, yoffs));
+
+ z5 = point 0 of pat;
+ z6 = point 1 of pat;
+ z7 = point 2 of pat;
+ z8 = point 3 of pat;
+ z9 = point 4 of pat;
+
+ save dirs;
+ pair dirs[];
+
+ dirs5 := direction 0 of pat;
+ dirs6 := direction 1 of pat;
+ dirs7 := direction 2 of pat;
+ dirs8 := direction 3 of pat;
+ dirs9 := direction 4 of pat;
+
+ % we approximate `draw pat'
+ fill get_subpath (ellipse, -dirs5, dirs5, z5)
+ .. get_subpoint (ellipse, dirs6, z6)
+ .. get_subpoint (ellipse, dirs7, z7)
+ .. get_subpoint (ellipse, dirs8, z8)
+ .. get_subpath (ellipse, dirs9, -dirs9, z9)
+ .. get_subpoint (ellipse, -dirs8, z8)
+ .. get_subpoint (ellipse, -dirs7, z7)
+ .. get_subpoint (ellipse, -dirs6, z6)
+ .. cycle;
+
+ % upper dot
+ rt x2 = xoffs + width;
+ top y1 = yoffs + 0.5 width;
+ z2 - z1 = (dot_diameter, -dot_diameter);
+
+ fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
+ -- get_subpath (ellipse, z2 - z1, z1 - z2, z2)
+ -- cycle;
+
+ % lower dot
+ x3 = x1;
+ top y1 - bot y4 = width;
+ z4 - z3 = (dot_diameter, -dot_diameter);
+
+ fill get_subpath (ellipse, z3 - z4, z4 - z3, z3)
+ -- get_subpath (ellipse, z4 - z3, z3 - z4, z4)
+ -- cycle;
+
+ set_char_box (0 - xpart exact_center,
+ width# + xpart exact_center,
+ 0.5 width# - ypart exact_center,
+ 0.5 width# + ypart exact_center);
+
+ labels (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+enddef;
+
+
+fet_beginchar ("mensural f clef", "mensural.f");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_mensural_f_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("mensural f clef", "mensural.f_change");
+ draw_mensural_f_clef ((0, 0), .8);
+fet_endchar;
+
+
+def draw_petrucci_g_clef (expr exact_center, reduction) =
+ % inspired by Josquin Desprez, "Stabat Mater", Libro tertio,
+ % 1519, printed by Petrucci, in: MGG, volume 7, Table 11.
+
+ save reduced_il, reduced_slt;
+
+ reduced_il# = staff_space# * reduction;
+ reduced_slt# = linethickness# * reduction;
+ define_pixels (reduced_il, reduced_slt);
+
+ set_char_box (0 - xpart exact_center,
+ 1.25 reduced_il# + xpart exact_center,
+ 0.65 reduced_il# - ypart exact_center,
+ 3.80 reduced_il# + ypart exact_center);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ save ellipse, paths, sub_path, outlines, sub_outlines, T;
+ path ellipse, paths[], sub_path, outlines[], sub_outlines[];
+ transform T;
+
+ T := identity xscaled 0.5 reduced_slt
+ yscaled 0.22 reduced_il
+ rotated -35;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ lft z1 = (xoffs + 0.80 reduced_il, yoffs + 0.00 reduced_il);
+ lft z2 = (xoffs + 1.00 reduced_il, yoffs + 1.20 reduced_il);
+ lft z3 = (xoffs + 0.70 reduced_il, yoffs + 2.00 reduced_il);
+ lft z4 = (xoffs + 0.30 reduced_il, yoffs + 3.00 reduced_il);
+ lft z5 = (xoffs + 0.80 reduced_il, yoffs + 3.70 reduced_il);
+ lft z6 = (xoffs + 1.00 reduced_il, yoffs + 3.00 reduced_il);
+ lft z7 = (xoffs + 0.60 reduced_il, yoffs + 2.00 reduced_il);
+ lft z8 = (xoffs + 0.30 reduced_il, yoffs + 1.70 reduced_il);
+ lft z9 = (xoffs + 0.00 reduced_il, yoffs + 0.75 reduced_il);
+ lft z10 = (xoffs + 0.20 reduced_il, yoffs + 0.60 reduced_il);
+
+ paths1 := z1{-1, 2}
+ .. z2
+ .. z3
+ .. z4
+ .. z5
+ .. z6
+ .. z7
+ .. z8
+ .. z9
+ .. z10;
+
+ save dirs, s;
+ pair dirs[];
+
+ s := 1/4;
+
+ % we approximate `draw paths1'
+ for i = 1 step s until (length paths1 + 1):
+ dirs[i] := direction (i - 1) of paths1;
+ endfor;
+
+ outlines1 := get_subpath (ellipse, -dirs1, dirs1, z1)
+ for i = (1 + s) step s until (length paths1 + 1 - s):
+ .. get_subpoint (ellipse, dirs[i],
+ point (i - 1) of paths1)
+ endfor
+ .. get_subpath (ellipse, dirs10, -dirs10, z10)
+ for i = (length paths1 + 1 - s) step -s until (1 + s):
+ .. get_subpoint (ellipse, -dirs[i],
+ point (i - 1) of paths1)
+ endfor
+ .. cycle;
+
+ save len;
+
+ len := length outlines1;
+
+ sub_outlines1 := subpath (0,
+ floor (1/4 len)) of outlines1;
+ sub_outlines2 := subpath (floor (1/4 len),
+ floor (2/4 len)) of outlines1;
+ sub_outlines3 := subpath (floor (2/4 len),
+ floor (3/4 len)) of outlines1;
+ sub_outlines4 := subpath (floor (3/4 len),
+ len) of outlines1;
+
+ save times;
+ numeric times[];
+
+ (times12, times21) = sub_outlines1 intersectiontimes sub_outlines2;
+ (times13, times31) = sub_outlines1 intersectiontimes sub_outlines3;
+ (times42, times24) = sub_outlines4 intersectiontimes sub_outlines2;
+ (times43, times34) = sub_outlines4 intersectiontimes sub_outlines3;
+
+ T := identity xscaled 0.75 reduced_slt
+ yscaled 0.33 reduced_il
+ rotated -35;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ lft z21 = (xoffs + 1.05 reduced_il, yoffs + 0.45 reduced_il);
+ lft z22 = (xoffs + 0.55 reduced_il, yoffs + 0.45 reduced_il);
+ lft z23 = (xoffs + 0.55 reduced_il, yoffs - 0.45 reduced_il);
+ lft z24 = (xoffs + 1.05 reduced_il, yoffs - 0.45 reduced_il);
+ lft z25 = (xoffs + 1.10 reduced_il, yoffs + 0.00 reduced_il);
+ lft z26 = (xoffs + 0.80 reduced_il, yoffs + 0.00 reduced_il);
+
+ paths2 := z21
+ .. z22
+ .. z23
+ .. z24
+ .. {up}z25
+ -- z26;
+
+ sub_path := subpath (0, 1) of paths2;
+
+ times1 = xpart (sub_outlines1 intersectiontimes sub_path);
+ times4 = xpart (sub_outlines4 intersectiontimes sub_path);
+
+ % we have to find the envelope intersections (if any)
+ save t;
+ numeric t[];
+
+ t1 = find_envelope_cusp (reverse ellipse,
+ subpath (1, 2) of paths2,
+ 1/256) + 1;
+ if t1 < 1:
+ t1 := 1;
+ t2 := 1;
+ else:
+ t2 = find_envelope_cusp (ellipse,
+ subpath (3, 4) of reverse paths2,
+ 1/256) + 3;
+ t2 := length paths2 - t2;
+ fi;
+
+ t3 = find_envelope_cusp (reverse ellipse,
+ subpath (2, 4 - epsilon) of paths2,
+ 1/256) + 2;
+ if t3 < 2:
+ t3 := 3;
+ t4 := 3;
+ else:
+ t4 = find_envelope_cusp (ellipse,
+ subpath (1 + epsilon, 3)
+ of reverse paths2,
+ 1/256) + 1;
+ t4 := length paths2 - t4;
+ fi;
+
+ fill subpath (times1 + s / 4, times13) of sub_outlines1
+ -- subpath (times31, infinity) of sub_outlines3
+ & subpath (0, times42) of sub_outlines4
+ -- subpath (times24, infinity) of sub_outlines2
+ & subpath (0, times34) of sub_outlines3
+ -- subpath (times43, times4 - s / 4) of sub_outlines4
+ -- cycle;
+ unfill subpath (times12, infinity) of sub_outlines1
+ & subpath (0, times21) of sub_outlines2
+ -- cycle;
+ fill subpath (times4 + s / 4, infinity) of sub_outlines4
+ & subpath (0, times1 - s / 4) of sub_outlines1
+ -- cycle;
+
+
+ % we approximate `draw paths2'
+ for i = 1 step s until (length paths2 - s):
+ dirs[i + 20] := direction (i - 1) of paths2;
+ endfor;
+
+ sub_outlines21 := get_subpath (ellipse, -dirs21, dirs21, z21)
+ for i = (1 + s) step s until (length paths2 - s):
+ .. get_subpoint (ellipse, dirs[i + 20],
+ point (i - 1) of paths2)
+ endfor
+ .. get_subpath (ellipse, up, z26 - z25, z25);
+ sub_outlines22 := get_subpath (ellipse, z26 - z25, z25 - z26, z26)
+ -- get_subpoint (ellipse, z25 - z26, z25);
+ sub_outlines23 := get_subpoint (ellipse, down, z25)
+ for i = (length paths2 - s) step -s until (t4 + 1):
+ .. get_subpoint (ellipse, -dirs[i + 20],
+ point (i - 1) of paths2)
+ endfor
+ .. get_subpoint (ellipse, -direction t4 of paths2,
+ point t4 of paths2);
+ sub_outlines24 := get_subpoint (ellipse, -direction t3 of paths2,
+ point t3 of paths2)
+ for i = (floor (t3 / s) * s + 1) step -s until (t2 + 1):
+ .. get_subpoint (ellipse, -dirs[i + 20],
+ point (i - 1) of paths2)
+ endfor
+ .. get_subpoint (ellipse, -direction t2 of paths2,
+ point t2 of paths2);
+ sub_outlines25 := get_subpoint (ellipse, -direction t1 of paths2,
+ point t1 of paths2)
+ for i = (floor (t1 / s) * s + 1) step -s until (1 + s):
+ .. get_subpoint (ellipse, -dirs[i + 20],
+ point (i - 1) of paths2)
+ endfor;
+
+ (times2223, times2322) = sub_outlines22 intersectiontimes sub_outlines23;
+ (times2324, times2423) = sub_outlines23 intersectiontimes sub_outlines24;
+ (times2425, times2524) = sub_outlines24 intersectiontimes sub_outlines25;
+
+ fill sub_outlines21
+ -- subpath (0, times2223) of sub_outlines22
+ -- subpath (times2322, times2324) of sub_outlines23
+ -- subpath (times2423, times2425) of sub_outlines24
+ -- subpath (times2524, infinity) of sub_outlines25
+ .. cycle;
+
+ labels (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ labels (21, 22, 23, 24, 25, 26);
+enddef;
+
+
+fet_beginchar ("petrucci g clef", "petrucci.g");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_petrucci_g_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("petrucci g clef", "petrucci.g_change");
+ draw_petrucci_g_clef ((0, 0), .8);
+fet_endchar;
+
+
+def draw_mensural_g_clef (expr exact_center, reduction) =
+ % TODO: Rewrite me. The former mensural g clef looked ugly, and the
+ % code was removed when it broke for small font sizes after some
+ % global changes in the font. Currently, the character is mapped to
+ % a copy of the petrucci g clef (which, after all, *is* a mensural g
+ % clef, but not the one that we have in mind here). -- jr
+ %
+ % Possible sources of inspiration for this clef include: Francisco
+ % Guerrero, "Lib. 1. Missarum" (1566), in: MGG, volume 3, col. 858
+ % ("Ducis"); Stefano Fabri, "Quam speciosa veteranis" (1611), in:
+ % MGG, volume 3, col. 1698 ("Fabri"); Philippus Dulichius,
+ % "Fasciculus novus ..." (1598), in: MGG, volume 3, col. 919
+ % ("Dulichius"), fig. 1; Noe Faignient, "Ic sal de Heer myn God
+ % gebenedye" (1568), in: MGG, volume 3, col. 1735 ("Faignient").
+enddef;
+
+
+%
+% FIXME: This clef is preliminarily mapped to the petrucci g clef
+% until the code for the mensural g clef will be rewritten.
+%
+fet_beginchar ("mensural g clef", "mensural.g");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_petrucci_g_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("mensural g clef", "mensural.g_change");
+ draw_petrucci_g_clef ((0, 0), .8);
+fet_endchar;
+
+
+
+%%%%%%%%
+%
+%
+%
+% Hufnagel
+%
+%
+%
+def draw_hufnagel_do_clef (expr exact_center, reduction) =
+ % inspired by Graduale of Friedrich Zollner (1442), in: MGG,
+ % volume 9, col. 1413 ("Neustift"), fig. 1.
+
+ save reduced_il;
+
+ reduced_il# = staff_space# * reduction;
+
+ define_pixels (reduced_il);
+
+ set_char_box (0 - xpart exact_center,
+ 1.10 reduced_il# + xpart exact_center,
+ 0.70 reduced_il# - ypart exact_center,
+ 0.75 reduced_il# + ypart exact_center);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ save ellipse, pat, T;
+ path ellipse, pat;
+ transform T;
+
+ T := identity xscaled 0.6 reduced_il
+ yscaled 0.1 reduced_il
+ rotated 40;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ z1 = (xoffs + 0.90 reduced_il, yoffs + .45 reduced_il);
+ z2 = (xoffs + 0.80 reduced_il, yoffs + .45 reduced_il);
+ z3 = (xoffs + 0.50 reduced_il, yoffs + .60 reduced_il);
+ z4 = (xoffs + 0.20 reduced_il, yoffs + .45 reduced_il);
+ z5 = (xoffs + 0.20 reduced_il, yoffs - .45 reduced_il);
+ z6 = (xoffs + 0.40 reduced_il, yoffs - .55 reduced_il);
+
+ pat := z1
+ .. z2
+ .. z3
+ -- z4
+ -- z5
+ -- z6;
+
+ fill get_subpath (ellipse,
+ -direction 0 of pat, direction 0 of pat, z1)
+ .. get_subpoint (ellipse, direction 1 of pat, z2)
+ .. get_subpath (ellipse,
+ direction (2 - epsilon) of pat, z4 - z3, z3)
+ -- get_subpath (ellipse,
+ z4 - z3, z5 - z4, z4)
+ -- get_subpath (ellipse,
+ z5 - z4, z6 - z5, z5)
+ -- get_subpath (ellipse,
+ z6 - z5, z5 - z6, z6)
+ -- get_subpoint (ellipse, z5 - z6, z5)
+ -- get_subpoint (ellipse, z4 - z5, z5)
+ -- get_subpoint (ellipse, z4 - z5, z4)
+ -- get_subpoint (ellipse, -direction (2 - epsilon) of pat, z3)
+ .. get_subpath (ellipse,
+ -direction 1 of pat, -direction 1 of pat, z2)
+ .. cycle;
+
+ labels (1, 2, 3, 4, 5, 6);
+enddef;
+
+
+fet_beginchar ("Hufnagel do clef", "hufnagel.do");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_hufnagel_do_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("Hufnagel do clef", "hufnagel.do_change");
+ draw_hufnagel_do_clef ((0, 0), .8);
+fet_endchar;
+
+
+def draw_hufnagel_fa_clef (expr exact_center, reduction) =
+ % inspired by Bamberger Manuscript (15th century), in:
+ % MGG, volume 2, table 59.
+
+ save reduced_il;
+
+ reduced_il# = staff_space# * reduction;
+
+ define_pixels (reduced_il);
+
+ set_char_box (0 - xpart exact_center,
+ 1.20 reduced_il# + xpart exact_center,
+ 1.15 reduced_il# - ypart exact_center,
+ 1.00 reduced_il# + ypart exact_center);
+
+ save xoffs, yoffs;
+
+ xoffs# = xpart exact_center;
+ yoffs# = ypart exact_center;
+
+ define_pixels (xoffs, yoffs);
+
+ save ellipse, pat, T;
+ path ellipse, pat;
+ transform T;
+
+ T := identity xscaled 0.6 reduced_il
+ yscaled 0.1 reduced_il
+ rotated 40;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ z11 = (xoffs + 0.90 reduced_il, yoffs + 0.70 reduced_il);
+ z12 = (xoffs + 0.80 reduced_il, yoffs + 0.70 reduced_il);
+ z13 = (xoffs + 0.50 reduced_il, yoffs + 0.85 reduced_il);
+ z14 = (xoffs + 0.20 reduced_il, yoffs + 0.70 reduced_il);
+ z15 = (xoffs + 0.20 reduced_il, yoffs - 1.10 reduced_il);
+
+ pat := z11
+ .. z12
+ .. z13
+ -- z14
+ -- z15;
+
+ fill get_subpath (ellipse,
+ -direction 0 of pat, direction 0 of pat, z11)
+ .. get_subpoint (ellipse, direction 1 of pat, z12)
+ .. get_subpath (ellipse,
+ direction (2 - epsilon) of pat, z14 - z13, z13)
+ -- get_subpath (ellipse,
+ z14 - z13, z15 - z14, z14)
+ -- get_subpath (ellipse,
+ z15 - z14, z14 - z15, z15)
+ -- get_subpoint (ellipse, z14 - z15, z14)
+ -- get_subpoint (ellipse, -direction (2 - epsilon) of pat, z13)
+ .. get_subpath (ellipse,
+ -direction 1 of pat, -direction 1 of pat, z12)
+ .. cycle;
+
+ z16 = (xoffs + 0.90 reduced_il, yoffs - 0.05 reduced_il);
+ z17 = (xoffs + 0.80 reduced_il, yoffs - 0.05 reduced_il);
+ z18 = (xoffs + 0.50 reduced_il, yoffs + 0.10 reduced_il);
+ z19 = (xoffs + 0.20 reduced_il, yoffs - 0.05 reduced_il);
+
+ pat := z16
+ .. z17
+ .. z18
+ -- z19;
+
+ fill get_subpath (ellipse,
+ -direction 0 of pat, direction 0 of pat, z16)
+ .. get_subpoint (ellipse, direction 1 of pat, z17)
+ .. get_subpath (ellipse,
+ direction (2 - epsilon) of pat, z19 - z18, z18)
+ -- get_subpoint (ellipse, z19 - z18, z19)
+ -- get_subpoint (ellipse, -direction (2 - epsilon) of pat, z18)
+ .. get_subpoint (ellipse, -direction 1 of pat, z17)
+ .. cycle;
+
+ labels (11, 12, 13, 14, 15, 16, 17, 18, 19);
+enddef;
+
+
+fet_beginchar ("Hufnagel fa clef", "hufnagel.fa");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_hufnagel_fa_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("Hufnagel fa clef", "hufnagel.fa_change");
+ draw_hufnagel_fa_clef ((0, 0), .8);
+fet_endchar;
+
+
+def draw_hufnagel_do_fa_clef (expr exact_center, reduction) =
+ draw_hufnagel_do_clef (exact_center, reduction);
+ draw_hufnagel_fa_clef (exact_center + (0, -2 staff_space#), reduction);
+
+ set_char_box (0 - xpart exact_center,
+ 1.20 reduced_il# + xpart exact_center,
+ 1.15 reduced_il# + 2 staff_space# - ypart exact_center,
+ 0.75 reduced_il# + ypart exact_center);
+enddef;
+
+
+fet_beginchar ("Hufnagel do/fa clef", "hufnagel.do.fa");
+ if test = 1:
+ draw_staff (-1, 3, 0.0);
+ fi;
+ draw_hufnagel_do_fa_clef ((0, 0), 1.0);
+fet_endchar;
+
+
+fet_beginchar ("Hufnagel do/fa clef", "hufnagel.do.fa_change");
+ draw_hufnagel_do_fa_clef ((0, 0), .8);
+fet_endchar;
+
+
+fet_endgroup ("clefs");
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-custodes.mf b/muse2/share/scoreglyphs/feta-original/parmesan-custodes.mf
new file mode 100644
index 00000000..d1a2d6c7
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-custodes.mf
@@ -0,0 +1,500 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-custodes.mf -- implement ancient custodes
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2000--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+save black_notehead_width;
+numeric black_notehead_width;
+
+fet_begingroup ("custodes");
+
+%
+% character aligment:
+%
+% The custos is assumed to be vertically centered around (0, 0).
+% The left-most edge of the custos should touch the vertical line
+% that goes though the point (0, 0).
+%
+% set_char_box() conventions:
+%
+% * breapth: Ignored (as far as I know). Should be set to 0.
+%
+% * width: Should cover the horizontal range of the custos that is to
+% be printed in the staff. If the custos has an appendage that is
+% supposed to reach beyond the right end of the staff, the width
+% should be set such that the appendage is outside of the char box.
+%
+% * depth: Should match the bottom edge of the custos. Affects
+% vertical collision handling.
+%
+% * height: Should match the top edge of the custos. Affects vertical
+% collision handling.
+%
+
+save between_staff_lines, on_staff_line, anywhere;
+
+between_staff_lines := 0;
+on_staff_line := 1;
+anywhere := 2;
+
+save dir_up, dir_down;
+
+dir_up := 1;
+dir_down := -1;
+
+
+%%%%%%%%
+%
+%
+% Hufnagel style
+%
+%
+
+% parameterized hufnagel custos
+def custos_hufnagel (expr verbose_name, internal_name,
+ direction, staffline_adjustment) =
+
+ fet_beginchar (verbose_name, internal_name);
+ save alpha, dalpha, ht, wd, stem_ht, pen_size;
+
+ ht# = noteheight#;
+ wd# / ht# = 0.6;
+ alpha = 35;
+ dalpha = direction * alpha;
+
+ if staffline_adjustment = between_staff_lines:
+ stem_ht# = 1.00 staff_space#;
+ elseif staffline_adjustment = on_staff_line:
+ stem_ht# = 1.50 staff_space#;
+ else: % staffline_adjustment = anywhere
+ stem_ht# = 1.25 staff_space#;
+ fi;
+
+ pen_size# = 0.5 (wd# ++ ht#);
+
+ define_pixels (ht, wd, pen_size, stem_ht);
+
+ save ellipse, pat, T;
+ path ellipse, pat;
+ transform T;
+
+ T := identity xscaled linethickness
+ yscaled pen_size
+ rotated -dalpha;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ if direction = dir_up:
+ top y1 = ht / 2;
+ bot y2 = -ht / 2;
+ else:
+ bot y1 = -ht / 2;
+ top y2 = ht / 2;
+ fi;
+
+ lft x1 = 0;
+ rt x2 = wd;
+ y3 - y2 = direction * stem_ht;
+ (y3 - y2) = (x3 - x2) * tand (90 - dalpha);
+
+ fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
+ if direction > 0:
+ -- get_subpath (ellipse, z2 - z1, z3 - z2, z2)
+ else:
+ -- get_subpoint (ellipse, z2 - z1, z2)
+ -- get_subpoint (ellipse, z3 - z2, z2)
+ fi
+ -- get_subpath (ellipse, z3 - z2, z2 - z3, z3)
+ if direction > 0:
+ -- get_subpoint (ellipse, z2 - z3, z2)
+ -- get_subpoint (ellipse, z1 - z2, z2)
+ else:
+ -- get_subpath (ellipse, z2 - z3, z1 - z2, z2)
+ fi
+ -- cycle;
+
+ % The stem is intentionally outside of the char box.
+ if direction > 0:
+ set_char_box (0, wd#, ht# / 2, stem_ht#);
+ else:
+ set_char_box (0, wd#, stem_ht#, ht# / 2);
+ fi;
+
+ labels (1, 2, 3);
+ fet_endchar;
+enddef;
+
+
+% custos hufnagel, stem up, between staff lines
+custos_hufnagel ("Custos Hufnagel", "hufnagel.u0",
+ dir_up, between_staff_lines);
+
+
+% custos hufnagel, stem up, on staff line
+custos_hufnagel ("Custos Hufnagel", "hufnagel.u1",
+ dir_up, on_staff_line);
+
+
+% custos hufnagel, stem up, anywhere
+custos_hufnagel ("Custos Hufnagel", "hufnagel.u2",
+ dir_up, anywhere);
+
+
+% custos hufnagel, stem down, between staff lines
+custos_hufnagel ("Reverse Custos Hufnagel", "hufnagel.d0",
+ dir_down, between_staff_lines);
+
+
+% custos hufnagel, stem down, on staff line
+custos_hufnagel ("Reverse Custos Hufnagel", "hufnagel.d1",
+ dir_down, on_staff_line);
+
+
+% custos hufnagel, stem down, anywhere
+custos_hufnagel ("Reverse Custos Hufnagel", "hufnagel.d2",
+ dir_down, anywhere);
+
+
+%%%%%%%%
+%
+%
+% Medicaea style
+%
+%
+
+def custos_medicaea (expr verbose_name, internal_name,
+ direction, staffline_adjustment) =
+ fet_beginchar (verbose_name, internal_name);
+ save ht, wd, stem_ht;
+
+ ht# = noteheight#;
+ wd# / ht# = 0.25;
+
+ if staffline_adjustment = between_staff_lines:
+ stem_ht# = 1.00 staff_space#;
+ elseif staffline_adjustment = on_staff_line:
+ stem_ht# = 1.50 staff_space#;
+ else: % staffline_adjustment = anywhere
+ stem_ht# = 1.25 staff_space#;
+ fi;
+
+ define_pixels (ht, wd, stem_ht);
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled 0.6 linethickness
+ yscaled ht;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ lft x1 = 0;
+ y1 = 0;
+ rt x2 = wd;
+ y2 = y1;
+
+ fill get_subpath (ellipse, left, right, z1)
+ -- get_subpath (ellipse, right, left, z2)
+ -- cycle;
+
+ pickup pencircle scaled 0.6 linethickness;
+
+ rt x3 = wd;
+ y3 = 0;
+ x4 = x3;
+ if direction > 0:
+ top y4 = stem_ht;
+ draw_rounded_block (bot lft z3, top rt z4,
+ 0.6 linethickness);
+ else:
+ bot y4 = -stem_ht;
+ draw_rounded_block (bot lft z4, top rt z3,
+ 0.6 linethickness);
+ fi;
+
+
+ if direction > 0:
+ set_char_box (0, wd#, ht# / 2, stem_ht#);
+ else:
+ set_char_box (0, wd#, stem_ht#, ht# / 2);
+ fi;
+
+ labels (1, 2, 3, 4);
+ fet_endchar;
+enddef;
+
+
+% custos medicaea, stem up, between staff lines
+custos_medicaea ("Custos Med.", "medicaea.u0",
+ dir_up, between_staff_lines);
+
+
+% custos medicaea, stem up, on staff line
+custos_medicaea ("Custos Med.", "medicaea.u1",
+ dir_up, on_staff_line);
+
+
+% custos medicaea, stem up, anywhere
+custos_medicaea ("Custos Med.", "medicaea.u2",
+ dir_up, anywhere);
+
+
+% custos medicaea, stem down, between staff lines
+custos_medicaea ("Reverse Custos Med.", "medicaea.d0",
+ dir_down, between_staff_lines);
+
+
+% custos medicaea, stem down, on staff line
+custos_medicaea ("Reverse Custos Med.", "medicaea.d1",
+ dir_down, on_staff_line);
+
+
+% custos medicaea, stem down, anywhere
+custos_medicaea ("Reverse Custos Med.", "medicaea.d2",
+ dir_down, anywhere);
+
+
+%%%%%%%%
+%
+%
+% Editio Vaticana style
+%
+%
+
+def custos_vaticana (expr verbose_name, internal_name,
+ direction, staffline_adjustment) =
+ fet_beginchar (verbose_name, internal_name);
+ save ht, wd, u_offs, l_offs, stem_size, stem_end;
+ save pen_ht, l_shift, curve_ht, bend_ht;
+
+ ht# = noteheight#;
+ wd# = 0.24 ht#;
+
+ if staffline_adjustment = between_staff_lines:
+ stem_size# = 1.00;
+ elseif staffline_adjustment = on_staff_line:
+ stem_size# = 1.50;
+ else: % staffline_adjustment = anywhere
+ stem_size# = 1.25;
+ fi;
+
+ curve_ht# = 0.6 ht#;
+ bend_ht# = 0.10 ht#;
+ l_shift# = 0.04 ht#;
+ u_offs# = +direction * 0.5 * (bend_ht# + l_shift#);
+ l_offs# = -direction * 0.5 * (bend_ht# - l_shift#);
+ stem_end# = direction * stem_size# * staff_space#;
+ pen_ht# = curve_ht# - l_shift#;
+
+ define_pixels (u_offs, l_offs, stem_end, ht, wd, pen_ht);
+
+ pickup pencircle scaled 0.6 linethickness;
+
+ z1 = (0, u_offs);
+ z2 = (0.7 wd, l_offs);
+ z3 = (wd, l_offs);
+
+ penpos1 (pen_ht, 90);
+ penpos2 (pen_ht, 90);
+ penpos3 (pen_ht, 90);
+
+ penstroke z1e{z2 - z1}
+ .. {right}z2e
+ .. z3e;
+
+ rt x4 = wd;
+ x5 = x4;
+
+ if direction > 0:
+ y4 = y3r;
+ top y5 = stem_end;
+ draw_rounded_block (bot lft z4, top rt z5,
+ 0.6 linethickness);
+ else:
+ y4 = y3l;
+ bot y5 = stem_end;
+ draw_rounded_block (bot lft z5, top rt z4,
+ 0.6 linethickness);
+ fi;
+
+ if direction > 0:
+ set_char_box (0, wd#,
+ -l_offs# + 0.5 pen_ht#, stem_end#);
+ else:
+ set_char_box (0, wd#,
+ -stem_end#, +l_offs# + 0.5 pen_ht#);
+ fi;
+
+ penlabels (1, 2, 3);
+ labels (4, 5);
+ fet_endchar;
+enddef;
+
+
+% custos vaticana, stem up, between staff lines
+custos_vaticana ("Custos Ed. Vat.", "vaticana.u0",
+ dir_up, between_staff_lines);
+
+
+% custos vaticana, stem up, on staff line
+custos_vaticana ("Custos Ed. Vat.", "vaticana.u1",
+ dir_up, on_staff_line);
+
+
+% custos vaticana, stem up, anywhere
+custos_vaticana ("Custos Ed. Vat.", "vaticana.u2",
+ dir_up, anywhere);
+
+
+% custos vaticana, stem down, between staff lines
+custos_vaticana ("Reverse Custos Ed. Vat.", "vaticana.d0",
+ dir_down, between_staff_lines);
+
+
+% custos vaticana, stem down, on_staff_line
+custos_vaticana ("Reverse Custos Ed. Vat.", "vaticana.d1",
+ dir_down, on_staff_line);
+
+
+% custos vaticana, stem down, anywhere
+custos_vaticana ("Reverse Custos Ed. Vat.", "vaticana.d2",
+ dir_down, anywhere);
+
+
+%%%%%%%%
+%
+%
+% Mensural style
+%
+%
+
+def custos_mensural (expr verbose_name, internal_name,
+ direction, staffline_adjustment) =
+ fet_beginchar (verbose_name, internal_name);
+ save alpha, dalpha, ht, wd, stem_ht;
+
+ ht# = noteheight#;
+ wd# / ht# = 1.2;
+ alpha = 35;
+ dalpha = direction * alpha;
+
+ if staffline_adjustment = between_staff_lines:
+ stem_ht# = 1.00 staff_space#;
+ elseif staffline_adjustment = on_staff_line:
+ stem_ht# = 1.50 staff_space#;
+ else: % staffline_adjustment = anywhere
+ stem_ht# = 1.25 staff_space#;
+ fi;
+
+ define_pixels (ht, wd, stem_ht);
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled linethickness
+ yscaled 0.4 ht
+ rotated -dalpha;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ if direction > 0:
+ bot y1 = bot y3 = bot y5 = -direction * 0.33 ht;
+ top y2 = top y4 = +direction * 0.33 ht;
+ else:
+ top y1 = top y3 = top y5 = -direction * 0.33 ht;
+ bot y2 = bot y4 = +direction * 0.33 ht;
+ fi;
+
+ lft x1 = 0.0 wd;
+ lft x2 = 0.2 wd;
+ lft x3 = 0.4 wd;
+ lft x4 = 0.6 wd;
+ lft x5 = 0.8 wd;
+
+ y6 - y5 = direction * stem_ht;
+ y6 - y5 = (x6 - x5) * tand (90 - dalpha);
+
+ if direction > 0:
+ fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
+ -- get_subpoint (ellipse, z2 - z1, z2)
+ -- get_subpoint (ellipse, z3 - z2, z2)
+ -- get_subpath (ellipse, z3 - z2, z4 - z3, z3)
+ -- get_subpoint (ellipse, z4 - z3, z4)
+ -- get_subpoint (ellipse, z5 - z4, z4)
+ -- get_subpath (ellipse, z5 - z4, z6 - z5, z5)
+ -- get_subpath (ellipse, z6 - z5, z5 - z6, z6)
+ -- get_subpoint (ellipse, z5 - z6, z5)
+ -- get_subpoint (ellipse, z4 - z5, z5)
+ -- get_subpath (ellipse, z4 - z5, z3 - z4, z4)
+ -- get_subpoint (ellipse, z3 - z4, z3)
+ -- get_subpoint (ellipse, z2 - z3, z3)
+ -- get_subpath (ellipse, z2 - z3, z1 - z2, z2)
+ -- cycle;
+ else:
+ fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
+ -- get_subpath (ellipse, z2 -z1, z3 - z2, z2)
+ -- get_subpoint (ellipse, z3 - z2, z3)
+ -- get_subpoint (ellipse, z4 - z3, z3)
+ -- get_subpath (ellipse, z4 -z3, z5 - z4, z4)
+ -- get_subpoint (ellipse, z5 - z4, z5)
+ -- get_subpoint (ellipse, z6 - z5, z5)
+ -- get_subpath (ellipse, z6 - z5, z5 - z6, z6)
+ -- get_subpath (ellipse, z5 - z6, z4 - z5, z5)
+ -- get_subpoint (ellipse, z4 - z5, z4)
+ -- get_subpoint (ellipse, z3 - z4, z4)
+ -- get_subpath (ellipse, z3 - z4, z2 - z3, z3)
+ -- get_subpoint (ellipse, z2 - z3, z2)
+ -- get_subpoint (ellipse, z1 - z2, z2)
+ -- cycle;
+ fi;
+
+ % The stem is intentionally outside of the char box.
+ if direction > 0:
+ set_char_box (0, wd#,
+ +direction * 0.33 ht#, stem_ht#);
+ else:
+ set_char_box (0, wd#,
+ stem_ht#, -direction * 0.33 ht#);
+ fi;
+
+ labels (1, 2, 3, 4, 5, 6);
+ fet_endchar;
+enddef;
+
+
+% custos mensural, stem up, between staff lines
+custos_mensural ("Custos Mensural", "mensural.u0",
+ dir_up, between_staff_lines);
+
+
+% custos mensural, stem up, on staff line
+custos_mensural ("Custos Mensural", "mensural.u1",
+ dir_up, on_staff_line);
+
+
+% custos mensural, stem up, anywhere
+custos_mensural ("Custos Mensural", "mensural.u2",
+ dir_up, anywhere);
+
+
+% custos mensural, stem down, between staff lines
+custos_mensural ("Reverse Custos Mensural", "mensural.d0",
+ dir_down, between_staff_lines);
+
+
+% custos mensural, stem down, on staff line
+custos_mensural ("Reverse Custos Mensural", "mensural.d1",
+ dir_down, on_staff_line);
+
+
+% custos mensural, stem down, anywhere
+custos_mensural ("Reverse Custos Mensural", "mensural.d2",
+ dir_down, anywhere);
+
+
+fet_endgroup ("custodes");
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-dots.mf b/muse2/share/scoreglyphs/feta-original/parmesan-dots.mf
new file mode 100644
index 00000000..826dabe2
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-dots.mf
@@ -0,0 +1,27 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-dots.mf -- dot vaticana
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2006--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+fet_begingroup ("dots");
+
+save dot_diam;
+
+3 dot_diam# = staff_space# - stafflinethickness#;
+define_whole_blacker_pixels (dot_diam);
+
+fet_beginchar ("duration dot", "dotvaticana");
+ pickup pencircle scaled dot_diam;
+
+ lft x0 = 0;
+ top y0 = vround (.5 dot_diam);
+
+ drawdot z0;
+
+ set_char_box (0, dot_diam#, .5 dot_diam#, .5 dot_diam#);
+fet_endchar;
+
+fet_endgroup ("dots");
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-flags.mf b/muse2/share/scoreglyphs/feta-original/parmesan-flags.mf
new file mode 100644
index 00000000..32a55df0
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-flags.mf
@@ -0,0 +1,326 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-flags.mf -- implement ancient flags
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2001--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+fet_begingroup ("flags");
+
+save between_staff_lines, on_staff_line, anywhere;
+
+between_staff_lines := 0;
+on_staff_line := 1;
+anywhere := 2;
+
+save dir_up, dir_down;
+
+dir_up := 1;
+dir_down := -1;
+
+
+%%%%%%%%
+%
+%
+%
+% Mensural Notation
+%
+%
+%
+
+def draw_mensural_outermost_flare (expr staffline_adjustment, d_) =
+ define_pixels (linethickness, staff_space);
+
+ save ellipse, pat, T;
+ path ellipse, pat;
+ transform T;
+
+ T := identity xscaled 1.00 linethickness
+ yscaled 0.22 staff_space
+ rotated -35;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ z11 = (+0.00 staff_space, -0.00 staff_space);
+ z12 = (+0.15 staff_space, -0.00 staff_space);
+
+ if staffline_adjustment = between_staff_lines:
+ z13 = (+0.45 staff_space, -0.35 staff_space);
+ z14 = (+0.45 staff_space, -0.85 staff_space);
+ z15 = (+0.00 staff_space, -2.00 staff_space);
+ elseif staffline_adjustment = on_staff_line:
+ z13 = (+0.20 staff_space, -0.05 staff_space);
+ z14 = (+0.20 staff_space, -1.15 staff_space);
+ z15 = (+0.00 staff_space, -1.40 staff_space);
+ else: % staffline_adjustment = anywhere
+ z13 = (+0.33 staff_space, -0.20 staff_space);
+ z14 = (+0.33 staff_space, -1.00 staff_space);
+ z15 = (+0.00 staff_space, -1.70 staff_space);
+ fi;
+
+ pat := z13{z13 - z12}
+ .. {z15 - z14}z14;
+
+ fill get_subpath (ellipse, z11 - z12, z12 - z11, z11)
+ -- get_subpoint (ellipse, z12 - z11, z12)
+ -- get_subpoint (ellipse, z13 - z12, z12)
+ -- get_subpoint (ellipse, direction 0 of pat, z13)
+ {direction 0 of pat}
+ .. {direction 1 of pat}
+ get_subpoint (ellipse, direction 1 of pat, z14)
+ -- get_subpath (ellipse, z15 - z14, z14 - z15, z15)
+ -- get_subpoint (ellipse, -direction 1 of pat, z14)
+ {-direction 1 of pat}
+ .. {-direction 0 of pat}
+ get_subpoint (ellipse, -direction 0 of pat, z13)
+ -- get_subpath (ellipse, z12 - z13, z11 - z12, z12)
+ -- cycle;
+
+ if d_ = dir_up:
+ labels (11, 12, 13, 14, 15);
+ fi;
+enddef;
+
+
+def draw_mensural_inner_flare (expr il_shift, idx, d_) =
+ define_pixels (linethickness, staff_space);
+
+ save ellipse, pat, T;
+ path ellipse, pat;
+ transform T;
+
+ T := identity xscaled 1.00 linethickness
+ yscaled 0.22 staff_space
+ rotated -35;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ save i;
+ numeric i[];
+
+ i0 := idx * 10;
+ i1 := idx * 10 + 1;
+ i2 := idx * 10 + 2;
+ i3 := idx * 10 + 3;
+ i4 := idx * 10 + 4;
+
+ z[i0] = (0, -il_shift * staff_space);
+ z[i1] = z[i0] + (+0.00 staff_space, -0.10 staff_space);
+ z[i2] = z[i0] + (+0.33 staff_space, -0.30 staff_space);
+ z[i3] = z[i0] + (+0.33 staff_space, -0.70 staff_space);
+ z[i4] = z[i0] + (+0.00 staff_space, -0.90 staff_space);
+
+ pat := z[i1]{2, 1}
+ .. z[i2]
+ .. z[i3]
+ .. {-2, -1}z[i4];
+
+ % we avoid cusps originally present in `draw pat'
+ fill get_subpath (ellipse,
+ -direction 0 of pat, direction 0 of pat, z[i1])
+ .. get_subpoint (ellipse, direction 1 of pat, z[i2])
+ {direction 1 of pat}
+ .. get_subpoint (ellipse, direction 2 of pat, z[i3])
+ {direction 2 of pat}
+ .. get_subpath (ellipse,
+ direction 3 of pat, -direction 3 of pat, z[i4])
+ .. get_subpoint (ellipse, -direction 2 of pat, z[i3])
+ {-direction 2 of pat}
+ .. get_subpoint (ellipse, -direction 1 of pat, z[i2])
+ {-direction 1 of pat}
+ .. cycle;
+
+ if d_ = dir_up:
+ labels ([i0], [i1], [i2], [i3], [i4]);
+ fi;
+enddef;
+
+
+def draw_mensural_flag (expr staffline_adjustment, flares, d_) =
+ save char_box_adjust, flare_shift;
+
+ if staffline_adjustment = between_staff_lines:
+ flare_shift := 0.5;
+ elseif staffline_adjustment = on_staff_line:
+ flare_shift := 0.0;
+ else: % staffline_adjustment = anywhere
+ flare_shift := 0.25;
+ fi;
+
+ char_box_adjust := flare_shift + 0.5;
+
+ if d_ = dir_up:
+ set_char_box (0,
+ 0.60 staff_space#,
+ (flares + char_box_adjust) * staff_space#,
+ 0.10 staff_space#);
+ else: % d_ = dir_down
+ set_char_box (0.60 staff_space#,
+ 0,
+ 0.10 staff_space#,
+ (flares + char_box_adjust) * staff_space#);
+ fi;
+
+ draw_mensural_outermost_flare (staffline_adjustment, d_);
+
+ for flare_count := 2 step 1 until 4:
+ if flares >= flare_count:
+ draw_mensural_inner_flare (flare_shift
+ + flare_count - 0.5,
+ flare_count, d_);
+ fi;
+ endfor;
+
+ if d_ = dir_down:
+ currentpicture := currentpicture xscaled -1
+ yscaled -1;
+ fi;
+enddef;
+
+
+% 8th mensural flag, upwards, between staff lines
+fet_beginchar ("8th Mensural Flag (up)", "mensuralu03");
+ draw_mensural_flag (between_staff_lines, 1, dir_up);
+fet_endchar;
+
+
+% 8th mensural flag, upwards, on staff line
+fet_beginchar ("8th Mensural Flag (up)", "mensuralu13");
+ draw_mensural_flag (on_staff_line, 1, dir_up);
+fet_endchar;
+
+
+% 8th mensural flag, upwards, anywhere
+fet_beginchar ("8th Mensural Flag (up)", "mensuralu23");
+ draw_mensural_flag (anywhere, 1, dir_up);
+fet_endchar;
+
+
+% 8th mensural flag, downwards, between staff lines
+fet_beginchar ("8th Mensural Flag (down)", "mensurald03");
+ draw_mensural_flag (between_staff_lines, 1, dir_down);
+fet_endchar;
+
+
+% 8th mensural flag, downwards, on staff line
+fet_beginchar ("8th Mensural Flag (down)", "mensurald13");
+ draw_mensural_flag (on_staff_line, 1, dir_down);
+fet_endchar;
+
+
+% 8th mensural flag, downwards, anywhere
+fet_beginchar ("8th Mensural Flag (down)", "mensurald23");
+ draw_mensural_flag (anywhere, 1, dir_down);
+fet_endchar;
+
+
+% 16th mensural flag, upwards, between staff lines
+fet_beginchar ("16th Mensural Flag (up)", "mensuralu04");
+ draw_mensural_flag (between_staff_lines, 2, dir_up);
+fet_endchar;
+
+
+% 16th mensural flag, upwards, on staff line
+fet_beginchar ("16th Mensural Flag (up)", "mensuralu14");
+ draw_mensural_flag (on_staff_line, 2, dir_up);
+fet_endchar;
+
+
+% 16th mensural flag, upwards, anywhere
+fet_beginchar ("16th Mensural Flag (up)", "mensuralu24");
+ draw_mensural_flag (anywhere, 2, dir_up);
+fet_endchar;
+
+
+% 16th mensural flag, downwards, between staff lines
+fet_beginchar ("16th Mensural Flag (down)", "mensurald04");
+ draw_mensural_flag (between_staff_lines, 2, dir_down);
+fet_endchar;
+
+
+% 16th mensural flag, downwards, on staff line
+fet_beginchar ("16th Mensural Flag (down)", "mensurald14");
+ draw_mensural_flag (on_staff_line, 2, dir_down);
+fet_endchar;
+
+
+% 16th mensural flag, downwards, anywhere
+fet_beginchar ("16th Mensural Flag (down)", "mensurald24");
+ draw_mensural_flag (anywhere, 2, dir_down);
+fet_endchar;
+
+
+% 32th mensural flag, upwards, between staff lines
+fet_beginchar ("32th Mensural Flag (up)", "mensuralu05");
+ draw_mensural_flag (between_staff_lines, 3, dir_up);
+fet_endchar;
+
+
+% 32th mensural flag, upwards, on staff line
+fet_beginchar ("32th Mensural Flag (up)", "mensuralu15");
+ draw_mensural_flag (on_staff_line, 3, dir_up);
+fet_endchar;
+
+
+% 32th mensural flag, upwards, anywhere
+fet_beginchar ("32th Mensural Flag (up)", "mensuralu25");
+ draw_mensural_flag (anywhere, 3, dir_up);
+fet_endchar;
+
+
+% 32th mensural flag, downwards, between staff lines
+fet_beginchar ("32th Mensural Flag (down)", "mensurald05");
+ draw_mensural_flag (between_staff_lines, 3, dir_down);
+fet_endchar;
+
+
+% 32th mensural flag, downwards, on staff line
+fet_beginchar ("32th Mensural Flag (down)", "mensurald15");
+ draw_mensural_flag (on_staff_line, 3, dir_down);
+fet_endchar;
+
+
+% 32th mensural flag, downwards, anywhere
+fet_beginchar ("32th Mensural Flag (down)", "mensurald25");
+ draw_mensural_flag (anywhere, 3, dir_down);
+fet_endchar;
+
+
+% 64th mensural flag, upwards, between staff lines
+fet_beginchar ("64th Mensural Flag (up)", "mensuralu06");
+ draw_mensural_flag (between_staff_lines, 4, dir_up);
+fet_endchar;
+
+
+% 64th mensural flag, upwards, on staff line
+fet_beginchar ("64th Mensural Flag (up)", "mensuralu16");
+ draw_mensural_flag (on_staff_line, 4, dir_up);
+fet_endchar;
+
+
+% 64th mensural flag, upwards, anywhere
+fet_beginchar ("64th Mensural Flag (up)", "mensuralu26");
+ draw_mensural_flag (anywhere, 4, dir_up);
+fet_endchar;
+
+
+% 64th mensural flag, downwards, between staff lines
+fet_beginchar ("64th Mensural Flag (down)", "mensurald06");
+ draw_mensural_flag (between_staff_lines, 4, dir_down);
+fet_endchar;
+
+
+% 64th mensural flag, downwards, on staff line
+fet_beginchar ("64th Mensural Flag (down)", "mensurald16");
+ draw_mensural_flag (on_staff_line, 4, dir_down);
+fet_endchar;
+
+
+% 64th mensural flag, downwards, anywhere
+fet_beginchar ("64th Mensural Flag (down)", "mensurald26");
+ draw_mensural_flag (anywhere, 4, dir_down);
+fet_endchar;
+
+
+fet_endgroup ("flags");
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-generic.mf b/muse2/share/scoreglyphs/feta-original/parmesan-generic.mf
new file mode 100644
index 00000000..6ffb53aa
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-generic.mf
@@ -0,0 +1,42 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-generic.mf -- implement generic stuff: include lots of files,
+% but don't set dimensions.
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2002--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+
+if test = -1:
+ mode := smoke;
+fi;
+
+mode_setup;
+
+staffsize# := design_size * pt#;
+
+input feta-macros;
+input feta-params;
+
+input parmesan-macros;
+
+
+font_x_height staff_space#;
+
+
+fet_beginfont ("parmesan", design_size, "parmesanMusic");
+ if test = 0:
+ input parmesan-rests;
+ input parmesan-heads;
+ input parmesan-clefs;
+ input parmesan-custodes
+ input parmesan-accidentals;
+ input parmesan-flags;
+ input parmesan-timesig;
+ input parmesan-scripts;
+ input parmesan-dots;
+ else:
+
+ fi;
+fet_endfont;
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-heads.mf b/muse2/share/scoreglyphs/feta-original/parmesan-heads.mf
new file mode 100644
index 00000000..b897554d
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-heads.mf
@@ -0,0 +1,1492 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-heads.mf -- implement ancient note heads
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2001--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+% Neo-mensural heads originally by
+% Christian Mondrup and Mats Bengtsson
+%
+
+save black_notehead_width;
+numeric black_notehead_width;
+
+fet_begingroup ("noteheads");
+
+%
+% character aligment:
+%
+% The head is assumed to be vertically centered around (0, 0).
+% The left-most edge of the head should touch the vertical line
+% that goes though the point (0, 0).
+%
+% set_char_box() conventions:
+%
+% * breapth: Ignored (as far as I know). Should be set to 0.
+%
+% * width: Should match the head's width.
+%
+% * depth: Should match the bottom edge of the head. Affects vertical
+% collision handling.
+%
+% * height: Should match the top edge of the head. Affects vertical
+% collision handling.
+%
+% TODO: should depth/height include appendages/stems?
+
+overdone_heads = 0;
+noteheight# := staff_space# + (1 + overdone_heads) * stafflinethickness#;
+define_pixels (noteheight);
+
+
+%%%%%%%%
+%
+%
+%
+% MENSURAL NOTATION
+%
+%
+%
+
+def draw_neomensural_brevis (expr brevwid) =
+ save beamheight, head_width;
+ save holeheight, stem_width;
+ save serif_size, serif_protrude;
+
+ head_width# = brevwid;
+ holeheight = 3 stafflinethickness;
+ stem_width = 1.4 stafflinethickness;
+
+ define_pixels (head_width);
+
+ set_char_box (0, head_width#,
+ noteheight# / 2, noteheight# / 2);
+
+ 2 beamheight + holeheight = noteheight;
+ serif_size = (holeheight - stafflinethickness) / 2;
+ serif_protrude = 1.5 serif_size;
+
+ z1l = (0, 0);
+ z2l = (0, -stafflinethickness / 2);
+ z3r = z2r + serif_size * (1, -1);
+ y4r = y3r;
+ x4r = head_width / 2;
+ z5l = z3l + (-serif_size, -serif_protrude);
+
+ penpos1 (stem_width, 0);
+ penpos2 (stem_width, 0);
+ penpos3 (beamheight, 90);
+ penpos4 (beamheight, 90);
+ penpos5 (stem_width, 180);
+
+ save pat_in, pat_out;
+ path pat_in, pat_out;
+
+ pat_out := z4l
+ -- z3l{left}
+ .. z5l{down}
+ .. z5r{up}
+ -- z1l;
+ pat_out := pat_out
+ -- reverse pat_out yscaled -1;
+ pat_out := pat_out
+ -- reverse pat_out shifted (-x4r, 0)
+ xscaled -1
+ shifted (x4l, 0)
+ -- cycle;
+ fill pat_out;
+
+ pat_in := z4r
+ -- z3r{left}
+ .. z2r{up}
+ -- z1r;
+ pat_in := pat_in
+ -- reverse pat_in yscaled -1;
+ pat_in := pat_in
+ -- reverse pat_in shifted (-x4r, 0)
+ xscaled -1
+ shifted (x4l, 0)
+ -- cycle;
+ unfill pat_in;
+
+ penlabels (1, 2, 3, 4, 5);
+enddef;
+
+
+%%% This head does not seem to be used anywhere. Junk me? -- jr
+def draw_neomensural_left_stemmed_head (expr wid) =
+ draw_neomensural_brevis (wid);
+
+ x6 = x7 = stem_width / 2;
+ y6 = y5;
+ y7 = y5 - 2.25 staff_space;
+
+ z17 = (x7, y7 - stem_width / 2);
+
+ penpos6 (stem_width, 0);
+ penpos7 (stem_width, 0);
+
+ fill z7l
+ -- z6l
+ -- z6r
+ -- z7r
+ .. z17
+ .. cycle;
+
+ penlabels (6, 7);
+ labels (17);
+enddef;
+
+
+%%% This head does not seem to be used anywhere. Junk me? -- jr
+fet_beginchar ("Left stemmed notehead", "slneomensural");
+ draw_neomensural_left_stemmed_head (2 staff_space#);
+fet_endchar;
+
+
+%
+% Some sources (eg. Musix/OpusTeX) think that the appendage should be on
+% the left, some say right. Right wins democratically.
+%
+def draw_neomensural_longa (expr wid) =
+ draw_neomensural_brevis (wid);
+
+ save theta;
+
+ x7r = head_width;
+ y7 = y5;
+ z6 - z7 = (stem_width / 2, -staff_space);
+ theta = angle (z6 - z7) + 90;
+
+ penpos7 (stem_width, 0);
+ penpos6 (1.2 stem_width, theta);
+
+ z7' = find_tangent (z6l, pat_out,
+ (x7l + 0.5 stem_width, y7l),
+ (x7l - 0.5 stem_width, y7l));
+
+ fill z7r
+ .. z6r{z6 - z7}
+ .. {z7 - z6}z6l
+ -- z7'
+ -- cycle;
+
+ penlabels (6, 7);
+ labels (7');
+enddef;
+
+
+%
+% En wij presenteren U: de opvolgster van Emily
+%
+% (ze is wel breed)
+%
+fet_beginchar ("Neo-mensural maxima notehead", "sM3neomensural");
+ draw_neomensural_longa (2.6 staff_space#);
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural longa notehead", "sM2neomensural");
+ draw_neomensural_longa (2 staff_space#);
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural brevis notehead", "sM1neomensural");
+ draw_neomensural_brevis (2 staff_space#);
+fet_endchar;
+
+
+def draw_neomensural_black_head (expr wid, height) =
+ save head_width;
+ save ne, nw, ne_dist, nw_dist;
+ pair ne, nw, ne_dist, nw_dist;
+
+ head_width# = wid;
+
+ set_char_box (0, head_width#,
+ height / 2, height / 2);
+
+ charwx := head_width# / 2;
+ charwy := height / 2;
+
+ y3 = y1 = 0;
+ x2 = x4 = (x1 + x3) / 2;
+
+ pickup pencircle scaled blot_diameter;
+
+ top y2 = h;
+ bot y4 = -d;
+ lft x1 = 0;
+ rt x3 = w;
+
+ ne := unitvector (z2 - z1);
+ nw_dist := (ne rotated 90) * 0.5 blot_diameter;
+ nw := unitvector (z2 - z3);
+ ne_dist := (nw rotated -90) * 0.5 blot_diameter;
+
+ fill lft z1{up}
+ .. (z1 + nw_dist){ne}
+ -- (z2 + nw_dist){ne}
+ .. top z2{right}
+ .. (z2 + ne_dist){-nw}
+ -- (z3 + ne_dist){-nw}
+ .. rt z3{down}
+ .. (z3 - nw_dist){-ne}
+ -- (z4 - nw_dist){-ne}
+ .. bot z4{left}
+ .. (z4 - ne_dist){nw}
+ -- (z1 - ne_dist){nw}
+ .. cycle;
+
+ labels (1, 2, 3, 4);
+enddef;
+
+
+def draw_neomensural_open_head (expr wid, height)=
+ draw_neomensural_black_head (wid, height);
+
+ save diamNW, diamSW;
+
+ diamNW = length (z2 - z1) + blot_diameter;
+ diamSW = length (z4 - z1) + blot_diameter;
+
+ save hole_widthNW, hole_widthSW;
+
+ hole_widthNW = 0.34 diamNW ;
+ hole_widthSW + 2.6 linethickness = diamSW;
+
+ (z7 + z5) / 2 = (w / 2, 0);
+ (z8 + z6) / 2 = (w / 2, 0);
+ z6 - z5 = hole_widthNW * unitvector (z2 - z1);
+ z7 - z6 = hole_widthSW * unitvector (z4 - z1);
+
+ unfill z5
+ -- z6
+ -- z7
+ -- z8
+ -- cycle;
+
+ labels (5, 6, 7, 8);
+enddef;
+
+
+%
+% WL says the thin lines should be thinner.
+%
+fet_beginchar ("Harmonic notehead (Neo-mensural open)", "s0harmonic");
+ draw_neomensural_open_head (1.3 staff_space#, 1.3 noteheight#);
+ charwx := head_width#;
+ charwy := 0;
+fet_endchar;
+
+
+fet_beginchar ("Harmonic notehead (Neo-mensural black)", "s2harmonic");
+ draw_neomensural_black_head (1.3 staff_space#, 1.3 noteheight#);
+ charwx := head_width#;
+ charwy := 0;
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural semibrevis head", "s0neomensural");
+ draw_neomensural_open_head (staff_space#, noteheight#);
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural minima head", "s1neomensural");
+ draw_neomensural_open_head (staff_space#, noteheight#);
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural semiminima head", "s2neomensural");
+ draw_neomensural_black_head (staff_space#, noteheight#);
+fet_endchar;
+
+
+def draw_mensural_brevis (expr wid) =
+ % TODO. For the moment, fall back to draw_neomensural_brevis.
+ draw_neomensural_brevis (wid);
+enddef;
+
+
+%%% This head does not seem to be used anywhere. Junk me? -- jr
+def draw_mensural_left_stemmed_head (expr wid) =
+ draw_mensural_brevis (wid);
+
+ x6 = x7 = stem_width / 2;
+ y6 = y5;
+ y7 = y5 - 2.25 staff_space;
+
+ z17 = (x7, y7 - stem_width / 2);
+
+ penpos6 (stem_width, 0);
+ penpos7 (stem_width, 0);
+
+ fill z7l
+ -- z6l
+ -- z6r
+ -- z7r
+ .. z17
+ .. cycle;
+
+ penlabels (6, 7);
+ labels (17);
+enddef;
+
+
+def draw_mensural_longa (expr wid) =
+ draw_mensural_brevis (wid);
+
+ x6 = x7 = head_width - stem_width / 2;
+ y6 = y5;
+ y7 = y5 - 2.25 staff_space;
+
+ z17 = (x7, y7 - stem_width / 2);
+
+ penpos6 (stem_width, 0);
+ penpos7 (stem_width, 0);
+
+ fill z7l
+ -- z6l
+ -- z6r
+ -- z7r
+ .. z17
+ .. cycle;
+
+ penlabels (6, 7);
+ labels (17);
+enddef;
+
+
+%%% This head does not seem to be used anywhere. Junk me? -- jr
+fet_beginchar ("Mensural left stemmed notehead", "slmensural");
+ draw_mensural_left_stemmed_head (staff_space#);
+fet_endchar;
+
+
+fet_beginchar ("Mensural maxima notehead", "sM3mensural");
+ draw_mensural_longa (2.0 staff_space#);
+fet_endchar;
+
+
+fet_beginchar ("Mensural longa notehead", "sM2mensural");
+ draw_mensural_longa (staff_space#);
+fet_endchar;
+
+
+fet_beginchar ("Mensural brevis notehead", "sM1mensural");
+ draw_mensural_brevis (staff_space#);
+fet_endchar;
+
+
+def draw_diamond_head (expr head_h, pen_w, pen_h, angle, open) =
+ save head_width, head_height;
+ save ellipse, ellipse_r;
+ path ellipse, ellipse_r, diamond_shape;
+
+ head_height# = head_h;
+ head_width# / head_height# = tand (angle);
+
+ set_char_box (0, head_width#,
+ head_height# / 2, head_height# / 2);
+
+ charwx := head_width# / 2;
+ charwy := head_height# / 2 - linethickness#;
+
+ define_pixels (head_width, head_height);
+
+ ellipse := reverse fullcircle
+ xscaled (max (blot_diameter, pen_w * head_width))
+ yscaled (max (blot_diameter, pen_h * head_width))
+ rotated -angle;
+
+ z1 = find_tangent_shift (((0, h) -- (0, -h)), ellipse,
+ (0, 0), (w / 2, 0));
+ z2 = find_tangent_shift (((0, h) -- (w, h)), ellipse,
+ (w / 2, h), (w / 2, 0));
+ z3 = find_tangent_shift (((w, h) -- (w, -h)), ellipse,
+ (w, 0), (w / 2, 0));
+ z4 = find_tangent_shift (((0, -h) -- (w, -h)), ellipse,
+ (w / 2, -h), (w / 2, 0));
+
+ diamond_shape := get_subpath (ellipse, z1 - z4, z2 - z1, z1)
+ -- get_subpath (ellipse, z2 - z1, z3 - z2, z2)
+ -- get_subpath (ellipse, z3 - z2, z4 - z3, z3)
+ -- get_subpath (ellipse, z4 - z3, z1 - z4, z4)
+ -- cycle;
+ fill diamond_shape;
+
+ if open:
+ save l;
+ path l[];
+
+ l12 := (directionpoint (z1 - z2) of ellipse) shifted z1
+ -- (directionpoint (z1 - z2) of ellipse) shifted z2;
+ l23 := (directionpoint (z2 - z3) of ellipse) shifted z2
+ -- (directionpoint (z2 - z3) of ellipse) shifted z3;
+ l34 := (directionpoint (z3 - z4) of ellipse) shifted z3
+ -- (directionpoint (z3 - z4) of ellipse) shifted z4;
+ l41 := (directionpoint (z4 - z1) of ellipse) shifted z4
+ -- (directionpoint (z4 - z1) of ellipse) shifted z1;
+
+ unfill l12 intersectionpoint l23
+ -- l23 intersectionpoint l34
+ -- l34 intersectionpoint l41
+ -- l41 intersectionpoint l12
+ -- cycle;
+ fi;
+
+ labels (1, 2, 3, 4);
+enddef;
+
+
+fet_beginchar ("Mensural semibrevis head", "s0mensural");
+ draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
+fet_endchar;
+
+
+fet_beginchar ("Mensural minima head", "s1mensural");
+ draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
+fet_endchar;
+
+
+fet_beginchar ("Mensural semiminima head", "s2mensural");
+ draw_diamond_head (staff_space#, 0.15, 0.30, 30, false);
+fet_endchar;
+
+
+fet_beginchar ("Petrucci semibrevis head", "s0petrucci");
+% draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
+ draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
+fet_endchar;
+
+
+fet_beginchar ("Petrucci minima head", "s1petrucci");
+% draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
+ draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
+fet_endchar;
+
+
+fet_beginchar ("Petrucci semiminima head", "s2petrucci");
+% draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, false);
+ draw_neomensural_black_head (staff_space#, 1.8 staff_space#);
+fet_endchar;
+
+
+%%%%%%%%
+%
+%
+%
+% EDITIO VATICANA (including solesmes extensions)
+%
+%
+%
+
+def vat_punctum_char (expr verbose_name, internal_name,
+ linea, cavum, straight, auctum,
+ d_up, up_shift, down_shift, mag) =
+ fet_beginchar (verbose_name, "s" & internal_name);
+ save a_b, b_h, a_w;
+
+ a_b := 1.54; % b_h * a_b / a_w = wd / ht
+ b_h := 0.85;
+ a_w := 1.09;
+
+ save a, beta, ht, wd;
+
+ ht# = noteheight# * mag;
+ 2 beta = ht# * b_h;
+ a = beta * a_b;
+ wd# = 2 a / a_w;
+ black_notehead_width# := wd#;
+
+ % direction
+ save d_, d_sign;
+ pair d_;
+
+ if d_up:
+ d_ := up;
+ d_sign := 1;
+ else:
+ d_ := down;
+ d_sign := -1;
+ fi;
+
+ % convexity and eccentricity
+ save u_convexity, u_eccentricity;
+
+ if straight:
+ u_convexity# := -0.01 ht#;
+ u_eccentricity# := 0.0 ht#; % dummy
+ elseif auctum:
+ u_convexity# := -0.03 ht#;
+ u_eccentricity# := +0.25 ht#;
+ else:
+ u_convexity# := -0.05 ht#;
+ u_eccentricity# := 0.0 ht#; % dummy
+ fi;
+
+ save convexity, eccentricity;
+
+ convexity# := d_sign * u_convexity#;
+ eccentricity# := d_sign * u_eccentricity#;
+
+ % y shift offset
+ save yoffs;
+
+ if up_shift:
+ yoffs# := 0.08 ht#;
+ elseif down_shift:
+ yoffs# := -0.11 ht#;
+ else:
+ yoffs# := 0.00 ht#;
+ fi;
+
+ define_pixels (convexity, eccentricity, yoffs, ht, wd);
+
+ pickup pencircle scaled linethickness;
+
+ save height, yoffs_bt, p, circle, circle_r;
+ path p, circle, circle_r;
+
+ height# = 0.47 ht#;
+ yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
+
+ define_pixels (height, yoffs_bt);
+
+ circle := fullcircle scaled linethickness;
+
+ x1 = x6;
+ x2 = x5;
+ x3 = x4;
+ y1 + height = y6;
+ y2 + height = y5;
+ y3 + height = y4;
+
+ save box_top, box_bt;
+
+ if auctum:
+ z1 = (0.00 wd + linethickness / 2, yoffs_bt);
+ z2 = (0.21 wd, yoffs_bt + convexity);
+ z3 = (0.42 wd - linethickness/ 2,
+ yoffs_bt + eccentricity);
+ box_top# = height# + yoffs_bt# +
+ max (0, convexity#, eccentricity#);
+ box_bt# = yoffs_bt# +
+ min (0, convexity#, eccentricity#);
+ p = z1
+ .. {right}z2
+ .. {d_}z3
+ -- z4{-d_}
+ .. z5{left}
+ .. z6
+ -- cycle;
+ else:
+ z1 = (0.00 wd + linethickness / 2, yoffs_bt);
+ z2 = (0.21 wd, yoffs_bt + convexity);
+ z3 = (0.42 wd - linethickness / 2, yoffs_bt);
+ box_top# = height# + yoffs_bt# + max (0, convexity#);
+ box_bt# = yoffs_bt# + min (0, convexity#);
+ p = z1
+ .. z2
+ .. z3
+ -- z4
+ .. z5
+ .. z6
+ -- cycle;
+ fi;
+
+ labels (1, 2, 3, 4, 5, 6);
+
+ save dirs;
+ pair dirs[];
+
+ dirs12 := direction (0 + epsilon) of p;
+ dirs2 := direction 1 of p;
+ dirs32 := direction (2 - epsilon) of p;
+ dirs45 := direction (3 + epsilon) of p;
+ dirs5 := direction 4 of p;
+ dirs65 := direction (5 - epsilon) of p;
+
+ fill get_subpath (circle, down, dirs12, z1)
+ .. (bot z2){dirs2}
+ .. get_subpath (circle, dirs32, up, z3)
+ -- get_subpath (circle, up, dirs45, z4)
+ .. (top z5){dirs5}
+ .. get_subpath (circle, dirs65, down, z6)
+ -- cycle;
+
+ if cavum:
+ save pat, t;
+ path pat[];
+ numeric t[];
+
+ pat123 := ((directionpoint -dirs12 of circle)
+ shifted z1){dirs12}
+ .. (top z2){dirs2}
+ .. {dirs32}((directionpoint -dirs32 of circle)
+ shifted z3);
+ pat34 := lft z3
+ -- lft z4;
+ pat456 := ((directionpoint -dirs45 of circle)
+ shifted z4){dirs45}
+ .. (bot z5){dirs5}
+ .. {dirs65}((directionpoint -dirs65 of circle)
+ shifted z6);
+ pat61 := rt z6
+ -- rt z1;
+
+ t61 := ypart (pat61 intersectiontimes pat123);
+ t12 := xpart (pat123 intersectiontimes pat34);
+ t34 := ypart (pat34 intersectiontimes pat456);
+ t45 := xpart (pat456 intersectiontimes pat61);
+
+ unfill subpath (t61, t12) of pat123
+ -- subpath (t34, t45) of pat456
+ -- cycle;
+ fi;
+
+ set_char_box (0.00 wd#, 0.42 wd#,
+ max (0, -box_bt#) + linethickness# / 2,
+ max (0, box_top#) + linethickness# / 2);
+
+ if linea:
+ save linea_width, linea_height;
+
+ linea_width# = 0.6 linethickness#;
+ linea_height# = 0.7 ht#;
+
+ define_pixels (linea_width, linea_height);
+
+ pickup pencircle scaled 0.6 linethickness;
+
+ draw_rounded_block ((-0.10 wd - linea_width / 2,
+ -linea_height / 2),
+ (-0.10 wd + linea_width / 2,
+ +linea_height / 2),
+ 0.6 linethickness);
+ draw_rounded_block ((+0.52 wd - linea_width / 2,
+ -linea_height / 2),
+ (+0.52 wd + linea_width / 2,
+ +linea_height / 2),
+ 0.6 linethickness);
+
+ set_char_box (0, 0.62 wd# + linea_width#,
+ linea_height# / 2,
+ linea_height# / 2);
+
+ currentpicture := currentpicture
+ shifted (0.10 wd + linea_width / 2, 0);
+ fi;
+ fet_endchar;
+enddef;
+
+
+def plica_char (expr verbose_name, internal_name,
+ d_up, mag) =
+ fet_beginchar (verbose_name, "s" & internal_name);
+ save a_b, b_h, a_w;
+
+ a_b := 1.54; % b_h * a_b / a_w = wd / ht
+ b_h := 0.85;
+ a_w := 1.09;
+
+ save a, beta, ht, wd;
+
+ ht# = noteheight# * mag;
+ 2 beta = ht# * b_h;
+ a = beta * a_b;
+ wd# = 2 a / a_w;
+ black_notehead_width# := wd#;
+
+ % direction
+ save d_, d_sign;
+ pair d_;
+
+ if d_up:
+ d_ := up;
+ d_sign := 1;
+ else:
+ d_ := down;
+ d_sign := -1;
+ fi;
+
+ % convexity and eccentricity
+ save convexity, eccentricity;
+
+ convexity# := d_sign * -0.10 ht#;
+ eccentricity# := d_sign * -0.12 ht#;
+
+ % y shift offset
+ save yoffs;
+
+ yoffs# := -0.11 ht#;
+
+ define_pixels (convexity, eccentricity, yoffs, ht, wd);
+
+ pickup pencircle scaled linethickness;
+
+ save height, yoffs_bt, p, circle, circle_r;
+ path p, circle, circle_r;
+
+ height# = 0.47 ht#;
+ yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
+
+ define_pixels (height, yoffs_bt);
+
+ circle := fullcircle scaled linethickness;
+
+ x1 = x6;
+ x2 = x5;
+ x3 = x4;
+ y1 + height = y6;
+ y2 + height = y5;
+ y3 + height = y4;
+
+ save box_top, box_bt;
+
+ z1 = (0.00 wd + linethickness / 2, yoffs_bt);
+ z2 = (0.21 wd, yoffs_bt + convexity);
+ z3 = (0.42 wd - linethickness/ 2, yoffs_bt + eccentricity);
+ box_top# = height# + yoffs_bt# +
+ max (0, convexity#, eccentricity#);
+ box_bt# = yoffs_bt# +
+ min (0, convexity#, eccentricity#);
+ p = z1
+ .. z2{right}
+ .. z3
+ -- z4
+ .. z5{left}
+ .. z6
+ -- cycle;
+
+ labels (1, 2, 3, 4, 5, 6);
+
+ save dirs;
+ pair dirs[];
+
+ dirs12 := direction (0 + epsilon) of p;
+ dirs2 := direction 1 of p;
+ dirs32 := direction (2 - epsilon) of p;
+ dirs45 := direction (3 + epsilon) of p;
+ dirs5 := direction 4 of p;
+ dirs65 := direction (5 - epsilon) of p;
+
+ fill get_subpath (circle, down, dirs12, z1)
+ .. (bot z2){dirs2}
+ .. get_subpath (circle, dirs32, up, z3)
+ -- get_subpath (circle, up, dirs45, z4)
+ .. (top z5){dirs5}
+ .. get_subpath (circle, dirs65, down, z6)
+ -- cycle;
+
+ pickup pencircle scaled 0.6 linethickness;
+
+ save stem_bt;
+
+ set_char_box (0.00 wd#, 0.42 wd#,
+ max (0, -box_bt#) + linethickness# / 2,
+ max (0, box_top#) + linethickness# / 2);
+
+ fet_endchar;
+enddef;
+
+
+def epiphonus_char (expr verbose_name, internal_name,
+ left_stem, d_up, down_shift, mag) =
+ fet_beginchar (verbose_name, "s" & internal_name);
+ save a_b, b_h, a_w;
+
+ a_b := 1.54; % b_h * a_b / a_w = wd / ht
+ b_h := 0.85;
+ a_w := 1.09;
+
+ save a, beta, ht, wd;
+
+ ht# = noteheight# * mag;
+ 2 beta = ht# * b_h;
+ a = beta * a_b;
+ wd# = 2 a / a_w;
+ black_notehead_width# := wd#;
+
+ % direction
+ save d_, d_sign;
+ pair d_;
+
+ if d_up:
+ d_ := up;
+ d_sign := 1;
+ else:
+ d_ := down;
+ d_sign := -1;
+ fi;
+
+ % convexity and eccentricity
+ save convexity;
+
+ convexity# := d_sign * -0.05ht#;
+
+ % y shift offset
+ save yoffs;
+
+ if down_shift:
+ yoffs# := -0.11 ht#;
+ else:
+ yoffs# := 0.00 ht#;
+ fi;
+
+ define_pixels (convexity, yoffs, ht, wd);
+
+ pickup pencircle scaled linethickness;
+
+ save height, yoffs_bt, p, circle, circle_r;
+ path p, circle, circle_r;
+
+ height# = 0.47 ht#;
+ yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
+
+ define_pixels (height, yoffs_bt);
+
+ circle := fullcircle scaled linethickness;
+
+ x1 = x6;
+ x2 = x5;
+ x3 = x4;
+ y1 + height = y6;
+ y2 + height = y5;
+ y3 + height = y4;
+
+ save box_top, box_bt;
+
+ z1 = (0.00 wd + linethickness / 2, yoffs_bt - 2.5 convexity);
+ z2 = (0.06 wd, yoffs_bt + 1.4 convexity);
+ z3 = (0.42 wd - linethickness / 2, yoffs_bt - 1.0 convexity);
+ box_top# = height# + yoffs_bt# +
+ max (-1.0 convexity#, 1.4 convexity#, 0);
+ box_bt# = yoffs_bt# +
+ min (-1.0 convexity#, 1.4 convexity#, 0);
+ p = z1{-d_}
+ .. {curl 1}z2{right}
+ .. z3
+ -- z4
+ .. {left}z5{curl 1}
+ .. {d_}z6
+ -- cycle;
+
+ labels (1, 2, 3, 4, 5, 6);
+
+ save dirs;
+ pair dirs[];
+
+ dirs12 := direction (0 + epsilon) of p;
+ dirs21 := direction (1 - epsilon) of p;
+ dirs23 := direction (1 + epsilon) of p;
+ dirs32 := direction (2 - epsilon) of p;
+ dirs45 := direction (3 + epsilon) of p;
+ dirs54 := direction (4 - epsilon) of p;
+ dirs56 := direction (4 + epsilon) of p;
+ dirs65 := direction (5 - epsilon) of p;
+
+ fill get_subpath (circle, down, dirs12, z1)
+ .. get_subpath (circle, dirs21, dirs23, z2)
+ .. get_subpath (circle, dirs32, up, z3)
+ -- get_subpath (circle, up, dirs45, z4)
+ .. get_subpath (circle, dirs54, dirs56, z5)
+ .. get_subpath (circle, dirs65, down, z6)
+ -- cycle;
+
+ save stem_bt;
+
+ if left_stem:
+ pickup pencircle scaled 0.6 linethickness;
+
+ lft x11 = x1 - linethickness / 2;
+ bot y11 = yoffs - 1.1 ht - linethickness / 2;
+ x12 = x11;
+ y12 = y1;
+
+ draw_rounded_block (bot lft z11, top rt z12,
+ 0.6 linethickness);
+ stem_bt# = yoffs# - 1.1 ht#;
+
+ labels (11, 12);
+ else:
+ stem_bt# = 0;
+ fi;
+
+ set_char_box (0.00 wd#, 0.42 wd#,
+ max (0, -box_bt#, -stem_bt#) + linethickness# / 2,
+ max (0, box_top#) + linethickness# / 2);
+ fet_endchar;
+enddef;
+
+
+def inclinatum_char (expr verbose_name, internal_name,
+ small, stropha, auctum) =
+ fet_beginchar (verbose_name, "s" & internal_name);
+ save ht, alpha;
+
+ alpha := 35;
+
+ if small:
+ ht# = 0.50 noteheight#;
+ else:
+ ht# = 0.80 noteheight#;
+ fi;
+
+ draw_diamond_head (ht#, 0, 0, alpha, false);
+
+ save off_angle;
+
+ off_angle := alpha + 15;
+
+ save stropha_ellipse, auctum_hook, circle;
+ path stropha_ellipse, auctum_hook, circle;
+
+ circle := reverse fullcircle scaled linethickness;
+
+ stropha_ellipse := fullcircle xscaled 0.25 head_height
+ yscaled 0.55 head_height
+ rotated alpha;
+
+ z11 = z12
+ + linethickness / 2 * dir (180 - off_angle)
+ - directionpoint dir (90 - off_angle)
+ of stropha_ellipse;
+ z12 = directionpoint -dir (90 - off_angle) of diamond_shape +
+ linethickness / 2 * dir (180 - off_angle);
+ z13 = (0, -0.5 head_height + linethickness);
+
+ auctum_hook := z12{-dir (90 - off_angle)}
+ .. {dir (90 + alpha)}z13;
+
+ labels (12);
+
+ if (stropha and not auctum):
+ clearit;
+
+ save t_in, t_out;
+
+ t_in := xpart ((stropha_ellipse shifted z11)
+ intersectiontimes
+ get_subpath (diamond_shape,
+ left, up,
+ (0, 0)));
+ t_out := xpart ((stropha_ellipse shifted z11)
+ intersectiontimes
+ get_subpath (diamond_shape,
+ up, right,
+ (0, 0)));
+
+ % the addition or subtraction of `1' is necessary
+ % so that we get the right starting point
+ fill get_subpath_i (diamond_shape,
+ dir (angle (z2 - z1) - 1),
+ dir (angle (z1 - z4) + 1),
+ (0, 0))
+ -- get_subpath (stropha_ellipse,
+ direction t_in of stropha_ellipse,
+ direction t_out of stropha_ellipse,
+ z11)
+ -- cycle;
+
+ labels (11);
+ fi;
+
+ if (auctum and not stropha):
+ clearit;
+
+ fill get_subpath (diamond_shape,
+ left,
+ -dir (90 - off_angle),
+ (0, 0))
+ .. get_subpath (circle,
+ dir (90 + alpha),
+ -dir (90 + alpha),
+ z13)
+ .. get_subpath (circle,
+ dir (90 - off_angle),
+ right,
+ z12)
+ -- cycle;
+
+ labels (13);
+ fi;
+
+ if (auctum and stropha):
+ clearit;
+
+ save t;
+
+ t := xpart ((stropha_ellipse shifted z11)
+ intersectiontimes
+ get_subpath (diamond_shape, up, right,
+ (0, 0)));
+
+ % the addition or subtraction of `1' is necessary
+ % so that we get the right starting point
+ fill get_subpath_i (diamond_shape,
+ dir (angle (z2 - z1) - 1),
+ -dir (90 - off_angle),
+ (0, 0))
+ .. get_subpath (circle,
+ dir (90 + alpha),
+ -dir (90 + alpha),
+ z13)
+ .. get_subpath (stropha_ellipse,
+ dir (90 - off_angle),
+ direction t of stropha_ellipse,
+ z11)
+ -- cycle;
+
+ labels (11, 13);
+ fi;
+ fet_endchar;
+enddef;
+
+
+% punctum
+vat_punctum_char ("Ed. Vat. punctum", "vaticana.punctum",
+ false, false, false, false,
+ false, false, false, 1.0);
+
+
+% punctum cavum (for OpusTeX compatibility)
+vat_punctum_char ("Ed. Vat. punctum cavum", "vaticana.punctum.cavum",
+ false, true, false, false,
+ false, false, false, 1.0);
+
+
+% linea punctum (for OpusTeX compatibility)
+vat_punctum_char ("Ed. Vat. linea punctum", "vaticana.linea.punctum",
+ true, false, false, false,
+ false, false, false, 1.0);
+
+
+% linea punctum cavum (for OpusTeX compatibility)
+vat_punctum_char ("Ed. Vat. linea punctum cavum", "vaticana.linea.punctum.cavum",
+ true, true, false, false,
+ false, false, false, 1.0);
+
+
+% punctum inclinatum
+inclinatum_char ("Ed. Vat. inclinatum", "vaticana.inclinatum",
+ false, false, false);
+
+
+% pes lower punctum
+vat_punctum_char ("Ed. Vat. pes lower punctum", "vaticana.lpes",
+ false, false, true, false,
+ true, false, false, 1.0);
+
+
+% pes lower punctum
+vat_punctum_char ("Ed. Vat. pes var lower punctum", "vaticana.vlpes",
+ false, false, true, false,
+ true, false, true, 1.0);
+
+
+% pes upper punctum
+vat_punctum_char ("Ed. Vat. pes upper punctum", "vaticana.upes",
+ false, false, true, false,
+ false, false, false, 1.0);
+
+
+% pes upper punctum (shifted variation)
+%
+% This note head is used instead of the regular pes upper punctum to
+% avoid collision with the lower punctum note of the pes when the upper
+% punctum sits directly on top of the lower punctum.
+%
+vat_punctum_char ("Ed. Vat. var pes upper punctum", "vaticana.vupes",
+ false, false, true, false,
+ false, true, false, 1.0);
+
+
+% small punctum as used in epiphonus
+vat_punctum_char ("Ed. Vat. plica", "vaticana.plica",
+ false, false, false, false,
+ false, false, false, 0.6);
+
+
+% small punctum as used in epiphonus
+plica_char ("Ed. Vat. var plica", "vaticana.vplica",
+ false, 0.6);
+
+
+% eccentric punctum as used in epiphonus
+epiphonus_char ("Ed. Vat. epiphonus", "vaticana.epiphonus",
+ false, true, false, 1.0);
+
+
+% eccentric punctum as used in epiphonus (shifted variation)
+%
+% This note head is used instead of the regular epiphonus punctum to
+% avoid collision with the plica head when the plica sits directly on
+% top of the lower head.
+%
+epiphonus_char ("Ed. Vat. var epiphonus", "vaticana.vepiphonus",
+ false, true, true, 1.0);
+
+
+% small punctum as used in cephalicus
+vat_punctum_char ("Ed. Vat. rev. plica", "vaticana.reverse.plica",
+ false, false, false, false,
+ true, false, false, 0.6);
+
+
+% small punctum as used in cephalicus
+plica_char ("Ed. Vat. rev. var plica", "vaticana.reverse.vplica",
+ true, 0.6);
+
+
+% eccentric punctum as used in cephalicus; without left stem
+epiphonus_char ("Ed. Vat. inner cephalicus", "vaticana.inner.cephalicus",
+ false, false, false, 1.0);
+
+
+% eccentric punctum as used in cephalicus; with left stem
+epiphonus_char ("Ed. Vat. cephalicus", "vaticana.cephalicus",
+ true, false, false, 1.0);
+
+
+% quilisma
+fet_beginchar ("Ed. Vat. quilisma", "svaticana.quilisma");
+ save a_b, b_h, a_w;
+
+ a_b := 1.54; % b_h * a_b / a_w = wd / ht
+ b_h := 0.85;
+ a_w := 1.09;
+
+ save a, beta, ht, wd;
+
+ ht# = noteheight#;
+ 2 beta = ht# * b_h;
+ a = beta * a_b;
+ wd# = 2 a / a_w;
+
+ set_char_box (0, 0.42 wd#, 0.28 ht#, 0.36 ht#);
+
+ black_notehead_width# := wd#;
+
+ define_pixels (ht, wd);
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled linethickness
+ yscaled 0.44 ht;
+ pickup pencircle transformed T;
+ ellipse := reverse fullcircle transformed T;
+
+ z1 = (rt 0.00 wd, top -0.28 ht);
+ z2 = (0.11 wd, -0.14 ht);
+ z3 = (0.12 wd, +0.03 ht);
+ z4 = (0.25 wd, -0.09 ht);
+ z5 = (0.25 wd, +0.08 ht);
+ z6 = (lft 0.42 wd, -0.04 ht);
+ z7 = (lft 0.40 wd, bot +0.36 ht);
+
+ fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
+ -- get_subpath (ellipse, z2 - z1, z1 - z2, z2)
+ -- cycle;
+ fill get_subpath (ellipse, z3 - z4, z4 - z3, z3)
+ -- get_subpath (ellipse, z4 - z3, z3 - z4, z4)
+ -- cycle;
+ fill get_subpath (ellipse, z5 - z6, z6 - z5, z5)
+ -- point 0 of get_subpath (ellipse, z6 - z5, z5 - z6, z6)
+ -- get_subpath (ellipse, z7 - z6, z6 - z7, z7)
+ -- get_subpath (ellipse, z6 - z7, z5 - z6, z6)
+ -- cycle;
+
+ labels (1, 2, 3, 4, 5, 6, 7);
+fet_endchar;
+
+
+% solesmes punctum inclinatum parvum
+inclinatum_char ("Solesmes punctum inclinatum parvum", "solesmes.incl.parvum",
+ true, false, false);
+
+
+% solesmes punctum auctum ascendens
+vat_punctum_char ("Solesmes punctum auctum ascendens", "solesmes.auct.asc",
+ false, false, false, true,
+ true, false, false, 1.0);
+
+
+% solesmes punctum auctum descendens
+vat_punctum_char ("Solesmes punctum auctum descendens", "solesmes.auct.desc",
+ false, false, false, true,
+ false, false, false, 1.0);
+
+
+% solesmes punctum inclinatum auctum
+inclinatum_char ("Solesmes punctum incl. auctum", "solesmes.incl.auctum",
+ false, false, true);
+
+
+% solesmes stropha
+inclinatum_char ("Solesmes stropha", "solesmes.stropha",
+ false, true, false);
+
+
+% solesmes stropha aucta
+inclinatum_char ("Solesmes stropha aucta", "solesmes.stropha.aucta",
+ false, true, true);
+
+
+% solesmes oriscus
+fet_beginchar ("Solesmes oriscus", "ssolesmes.oriscus");
+ save a_b, b_h, a_w;
+
+ a_b := 1.54; % b_h * a_b / a_w = wd / ht
+ b_h := 0.85;
+ a_w := 1.09;
+
+ save a, beta, ht, wd;
+
+ ht# = noteheight#;
+ 2 beta = ht# * b_h;
+ a = beta * a_b;
+ wd# = 2 a / a_w;
+ black_notehead_width# := wd#;
+
+ save convexity;
+
+ convexity# = +0.05 ht#;
+
+ define_pixels (ht, wd, convexity);
+
+ set_char_box (0.00 wd#, 0.50 wd#,
+ 0.25 ht# + convexity#, 0.25 ht# + convexity#);
+
+ z1 = (0.00 wd + blot_diameter / 2, -convexity);
+ z2 = (1/6 wd, +convexity);
+ z3 = (2/6 wd, -convexity);
+ z4 = (0.50 wd - blot_diameter / 2, +convexity);
+
+
+ save height;
+
+ height = 2 ypart (directionpoint right of (z1
+ .. z2
+ .. z3
+ .. z4));
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled blot_diameter
+ yscaled (h + d - height);
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ % Adjust vertical coordinates to touch bounding box.
+ y1 := top -d;
+ y4 := bot h;
+
+ save d_;
+ pair d_;
+
+ d_ := direction 0 of (z1
+ .. z2
+ .. z3
+ .. z4);
+
+ fill get_subpath (ellipse, -d_, d_, z1)
+ .. bot z2
+ .. bot z3
+ .. get_subpath (ellipse, d_, -d_, z4)
+ .. top z3
+ .. top z2
+ .. cycle;
+
+ labels (1, 2, 3, 4);
+fet_endchar;
+
+
+%%%%%%%%
+%
+%
+%
+% EDITIO MEDICAEA
+%
+%
+%
+
+% inclinatum
+fet_beginchar ("Ed. Med. inclinatum", "smedicaea.inclinatum");
+ draw_diamond_head (1.2 staff_space#, 0, 0, 35, false);
+fet_endchar;
+
+
+def med_punctum_char (expr verbose_name, internal_name,
+ left_up_stem, left_down_stem) =
+ fet_beginchar (verbose_name, "s" & internal_name);
+ save a, ht, wd;
+
+ ht# = 2 staff_space#;
+ wd# = ht#;
+ black_notehead_width# := wd#;
+
+ define_pixels (ht, wd);
+
+ save ellipse;
+ path ellipse;
+
+ ellipse := fullcircle xscaled blot_diameter
+ yscaled 0.50 ht;
+
+ z1 = (0.00 wd + blot_diameter / 2, 0);
+ z2 = (0.4 wd - blot_diameter / 2, 0);
+
+ labels (1, 2);
+
+ pickup pencircle scaled linethickness;
+
+ if left_down_stem:
+ z4 = (0.00 wd + linethickness / 2, -1.25 ht);
+
+ fill get_subpath (ellipse, left, down, z1)
+ -- top lft z4{down}
+ .. z4{right}
+ .. top rt z4{up}
+ -- (rt x4, -.5 ht / 2)
+ -- get_subpath (ellipse, right, left, z2)
+ -- cycle;
+
+ labels (4);
+
+ set_char_box (0.0, 0.4 wd#, 1.25 ht#, 0.25 ht#);
+ elseif left_up_stem:
+ z4 = (0.00 wd + linethickness / 2, +1.25 ht);
+
+ fill get_subpath (ellipse, down, right, z1)
+ -- get_subpath (ellipse, right, left, z2)
+ -- (rt x4, .5 ht / 2)
+ -- bot rt z4{up}
+ .. z4{left}
+ .. bot lft z4{down}
+ -- cycle;
+
+ labels (4);
+
+ set_char_box (0.0, 0.4 wd#, 0.25 ht#, 1.25 ht#);
+ else:
+ fill get_subpath (ellipse, left, right, z1)
+ -- get_subpath (ellipse, right, left, z2)
+ -- cycle;
+
+ set_char_box (0.0, 0.4 wd#, 0.25 ht#, 0.25 ht#);
+ fi;
+
+ fet_endchar;
+enddef;
+
+
+% punctum
+med_punctum_char ("Ed. Med. punctum", "medicaea.punctum",
+ false, false);
+
+
+% left up-stemmed punctum
+med_punctum_char ("Ed. Med. reverse virga", "medicaea.rvirga",
+ true, false);
+
+
+% virga (i.e. left down-stemmed punctum)
+med_punctum_char ("Ed. Med. virga", "medicaea.virga",
+ false, true);
+
+
+%%%%%%%%
+%
+%
+%
+% HUFNAGEL
+%
+%
+%
+
+def huf_punctum_char (expr verbose_name, internal_name,
+ down_stem) =
+ fet_beginchar (verbose_name, "s" & internal_name);
+ save alpha;
+
+ alpha = 55;
+
+ draw_diamond_head (staff_space#, 0, 0, alpha, false);
+
+ if down_stem:
+ set_char_box (0, head_width#,
+ 1.5 staff_space#, head_height# / 2);
+
+ save ellipse;
+ path ellipse;
+
+ ellipse := reverse fullcircle xscaled blot_diameter
+ yscaled 0.7 staff_space
+ rotated -alpha;
+
+ z11 = (head_width / 2, 0);
+ z12 = find_tangent_shift (((0, -d) -- (w, -d)), ellipse,
+ (w / 2, -d), (w / 2, 0));
+
+ fill get_subpath (ellipse, up, down, z11)
+ -- get_subpath (ellipse, down, up, z12)
+ -- cycle;
+
+ labels (11, 12);
+ fi;
+ fet_endchar;
+enddef;
+
+
+% punctum
+huf_punctum_char ("Hufnagel punctum", "hufnagel.punctum", false)
+
+
+% virga
+huf_punctum_char ("Hufnagel virga", "hufnagel.virga", true)
+
+
+% pes lower punctum
+fet_beginchar ("Hufnagel pes lower punctum", "shufnagel.lpes")
+ save width, height, alpha;
+
+ width# = 2 * staff_space#;
+ height# = 0.7 * staff_space#;
+ alpha = 35;
+
+ set_char_box (0, width#, height# / 2, height# / 2);
+
+ define_pixels (width, height);
+
+ save circle;
+ path circle;
+
+ circle := reverse fullcircle scaled linethickness;
+
+ pickup pencircle scaled linethickness;
+
+ rt x3 = -lft x1 = width / 2;
+ y2 = y3 = height / 2;
+ y1 = y4 = -height / 2;
+
+ tand (alpha) * (y2 - y1) = x2 - x1 = x3 - x4;
+
+ fill get_subpath (circle, left, z2 - z1, z1)
+ -- get_subpath (circle, z2 - z1, right, z2)
+ -- get_subpath (circle, right, z4 - z3, z3)
+ -- get_subpath (circle, z4 - z3, left, z4)
+ -- cycle;
+
+ currentpicture := currentpicture shifted (width/2, 0);
+
+% labels (1, 2, 3, 4);
+fet_endchar;
+
+
+fet_endgroup ("noteheads");
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-macros.mf b/muse2/share/scoreglyphs/feta-original/parmesan-macros.mf
new file mode 100644
index 00000000..94d728a3
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-macros.mf
@@ -0,0 +1,215 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-macros.mf -- macros for parmesan font
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2001--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+
+%
+% Find point on `curve' which gives the tangent between point `p'
+% and `curve'. To guide the search, two auxiliary points must be
+% specified, `p_in' and `p_out'. The line between `p' and `p_in'
+% must intersect `curve', while the line between `p' and `p_out'
+% must not.
+%
+def find_tangent (expr p, curve, p_in, p_out) =
+ begingroup;
+ save mid, t, t_good, in, out;
+ pair mid, in, out;
+
+ in := p_in;
+ out := p_out;
+
+ forever:
+ mid := 0.5 [in, out];
+ exitif abs (out - mid) <= eps;
+ t := xpart (curve intersectiontimes (p -- mid));
+ if t > 0:
+ in := mid;
+ t_good := t;
+ else:
+ out := mid;
+ fi;
+ endfor;
+
+ point t_good of curve
+ endgroup
+enddef;
+
+
+%
+% Shift `curve' along the line given by the auxiliary points `p_in'
+% and `p_out' until `line' is a tangent, and return the shift.
+% If `curve' is shifted to position `p_in', it must intersect
+% `line', while shifted to `p_out' it must not.
+%
+def find_tangent_shift (expr line, curve, p_in, p_out) =
+ begingroup;
+ save mid, t, in, out;
+ pair mid, in, out;
+
+ in := p_in;
+ out := p_out;
+
+ forever:
+ mid := 0.5 [in, out];
+ exitif abs (out - mid) <= eps;
+ t := xpart ((curve shifted mid) intersectiontimes line);
+ if t > 0:
+ in := mid;
+ else:
+ out := mid;
+ fi;
+ endfor;
+
+ mid
+ endgroup
+enddef;
+
+
+%
+% Get subpath specified by `dir_in' and `dir_out' of `curve'
+% which is then shifted by `offset'. Assure that result has
+% the same orientation as `curve'.
+%
+def get_subpath (expr curve, dir_in, dir_out, offset) =
+ begingroup;
+ save t_in, t_out;
+
+ t_in := directiontime dir_in of curve;
+ t_out := directiontime dir_out of curve;
+
+ if t_in > t_out:
+ t_out := t_out + length curve;
+ fi;
+
+ (subpath (t_in, t_out) of curve) shifted offset
+ endgroup
+enddef;
+
+
+%
+% Get point specified by `dir_' of `curve' which is then
+% shifted by `offset'.
+%
+def get_subpoint (expr curve, dir_, offset) =
+ (directionpoint dir_ of curve) shifted offset
+enddef;
+
+
+%
+% This is the same as `get_subpath', except that the time values
+% used to construct the resulting subpath are rounded to integers.
+%
+def get_subpath_i (expr curve, dir_in, dir_out, offset) =
+ begingroup;
+ save t_in, t_out;
+
+ t_in := directiontime dir_in of curve;
+ t_out := directiontime dir_out of curve;
+
+ if t_in > t_out:
+ t_out := t_out + length curve;
+ fi;
+
+ (subpath (floor (t_in + 0.5), floor (t_out + 0.5)) of curve)
+ shifted offset
+ endgroup
+enddef;
+
+
+%
+% Find envelope cusp created by `object' moved along `curve', using
+% step value `s' for initial intermediate points. `s' must be small
+% enough so that this macro finds at least one point on the envelope
+% between the `entrance' and `exit' points of the cusp which has
+% a significantly different direction vector.
+%
+% This function returns a time value on `curve'; if there is no
+% cusp, it returns -1.
+%
+def find_envelope_cusp (expr object, curve, s) =
+ begingroup;
+ save mid, p, t, t_good, delta, start, stop, do_exit;
+ pair p[];
+ boolean do_exit;
+
+ p0 := (directionpoint (direction 0 of curve) of object)
+ shifted (point 0 of curve);
+ p1 := (directionpoint (direction s of curve) of object)
+ shifted (point s of curve);
+
+ t := s;
+
+ forever:
+ t := t + s;
+ exitif t >= length curve;
+
+ p2 := (directionpoint (direction t of curve) of object)
+ shifted (point t of curve);
+ if p2 <> p1:
+ delta := angle (p2 - p1) - angle (p1 - p0);
+ if delta > 180:
+ delta := delta - 360;
+ fi;
+
+ % we check for a direction change by more than
+ % than 45 degrees
+ if abs (delta) >= 45:
+ do_exit := true;
+ else:
+ do_exit := false;
+ fi;
+
+ p0 := p1;
+ p1 := p2;
+ fi;
+
+ % having `exitif' within an if-clause doesn't work
+ exitif do_exit;
+ endfor;
+
+ if t >= length curve:
+ t_good := -1;
+ else:
+ % the wanted point lies between `t - s' and `t'
+ start := t - s;
+ stop := t;
+ t_good := start;
+
+ forever:
+ mid := 0.5 [start, stop];
+ exitif abs (stop - mid) <= eps;
+
+ p0 := (directionpoint (direction start of curve)
+ of object) shifted (point start of curve);
+ p1 := (directionpoint (direction mid of curve)
+ of object) shifted (point mid of curve);
+ p2 := (directionpoint (direction stop of curve)
+ of object) shifted (point stop of curve);
+
+ exitif (length (p1 - p0) = 0)
+ or (length (p2 - p1) = 0);
+
+ delta := angle (p2 - p1) - angle (p1 - p0);
+ if delta > 180:
+ delta := delta - 360;
+ fi;
+
+ if abs (delta) >= 45:
+ stop := mid;
+ t_good := mid;
+ else:
+ start := mid;
+ t_good := stop;
+ fi;
+ endfor;
+ fi;
+
+ t_good
+ endgroup
+enddef;
+
+% EOF
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-rests.mf b/muse2/share/scoreglyphs/feta-original/parmesan-rests.mf
new file mode 100644
index 00000000..060307db
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-rests.mf
@@ -0,0 +1,418 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-rests.mf -- implement ancient rests
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2001--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+% Neo-mensural rests originally by
+% Christian Mondrup and Mats Bengtsson.
+%
+
+fet_begingroup ("rests")
+
+
+%%%%%%%%
+%
+%
+%
+% NEO-MENSURAL NOTATION
+%
+%
+%
+
+% Neo-mensural longa and breve are identical with default longa and breve.
+
+neomens_block_rest_x# = 2/5 staff_space#;
+neomens_block_rest_y# = 1/1 staff_space#;
+neomens_half_block_rest_y# = 5/8 staff_space#;
+
+define_pixels (neomens_block_rest_x,
+ neomens_block_rest_y,
+ neomens_half_block_rest_y);
+
+
+def neomens_half_block_rest =
+ draw_block ((0, 0),
+ (neomens_block_rest_x, neomens_half_block_rest_y));
+enddef;
+
+
+fet_beginchar ("Neo-mensural maxima rest", "M3neomensural");
+ set_char_box (0, 3 neomens_block_rest_x#,
+ neomens_block_rest_y#, neomens_block_rest_y#);
+
+ draw_block ((0, -neomens_block_rest_y),
+ (neomens_block_rest_x, neomens_block_rest_y));
+ addto currentpicture also currentpicture
+ shifted (2 neomens_block_rest_x, 0);
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural longa rest", "M2neomensural");
+ set_char_box (0, neomens_block_rest_x#,
+ neomens_block_rest_y#, neomens_block_rest_y#);
+
+ draw_block ((0, -neomens_block_rest_y),
+ (neomens_block_rest_x, neomens_block_rest_y));
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural breve rest", "M1neomensural");
+ set_char_box (0, neomens_block_rest_x#,
+ 0, neomens_block_rest_y#);
+
+ draw_block ((0, 0),
+ (neomens_block_rest_x, neomens_block_rest_y));
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural whole rest", "0neomensural");
+ set_char_box (0, neomens_block_rest_x#,
+ neomens_half_block_rest_y#, 0);
+
+ neomens_half_block_rest;
+ currentpicture :=
+ currentpicture shifted (0, -neomens_half_block_rest_y);
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural half rest", "1neomensural");
+ set_char_box (0, neomens_block_rest_x#,
+ 0, neomens_half_block_rest_y#);
+
+ neomens_half_block_rest;
+fet_endchar;
+
+
+neomensrestsize# = 0.8 staff_space#;
+
+
+fet_beginchar ("Neo-mensural 4th rest", "2neomensural");
+ set_char_box (0, neomensrestsize#,
+ 0, neomensrestsize#);
+
+ pickup pencircle scaled 2 stafflinethickness;
+
+ lft x1 = 0;
+ bot y1 = 0;
+ lft x2 = lft x3 = 0;
+ top y2 = top y3 = h;
+ rt x4 = w;
+ bot y4 = h / 2;
+
+ z11 = z1 - stafflinethickness * unitvector (z2 - z1);
+ z14 = z4 + stafflinethickness * unitvector (z4 - z3);
+
+ penpos1 (2 stafflinethickness, 0);
+ penpos2 (2 stafflinethickness, 0);
+ penpos3 (2 stafflinethickness, angle (z4 - z3) - 90);
+ penpos4 (2 stafflinethickness, angle (z4 - z3) - 90);
+
+ fill z1l
+ -- z2l
+ -- z2r
+ -- z1r
+ .. z11
+ .. z1l
+ .. cycle;
+ fill z3l
+ -- z4l
+ .. z14
+ .. z4r
+ -- z3r
+ .. z2l{up}
+ .. z3l
+ .. cycle;
+
+ penlabels (1, 2, 3, 4);
+ labels (11, 14);
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural 8th rest", "3neomensural");
+ set_char_box (0, neomensrestsize#,
+ 0, neomensrestsize#);
+
+ pickup pencircle scaled 2 stafflinethickness;
+
+ rt x1 = w;
+ bot y1 = 0;
+ rt x2 = rt x3 = w;
+ top y2 = top y3 = h;
+ lft x4 = 0;
+ bot y4 = h / 2;
+
+ z11 = z1 - stafflinethickness * unitvector (z2 - z1);
+ z14 = z4 + stafflinethickness * unitvector (z4 - z3);
+
+ penpos1 (2 stafflinethickness, 0);
+ penpos2 (2 stafflinethickness, 0);
+ penpos3 (2 stafflinethickness, angle (z4 - z3) - 90);
+ penpos4 (2 stafflinethickness, angle (z4 - z3) - 90);
+
+ fill z1l
+ -- z2l
+ -- z2r
+ -- z1r
+ .. z11
+ .. z1l
+ .. cycle;
+ fill z3l
+ -- z4l
+ .. z14
+ .. z4r
+ -- z3r
+ .. z2r{down}
+ .. z3l
+ .. cycle;
+
+ penlabels (1, 2, 3, 4);
+ labels (11, 14);
+fet_endchar;
+
+
+fet_beginchar ("Neo-mensural 16th rest", "4neomensural");
+ set_char_box (0, neomensrestsize#,
+ 0, staff_space#);
+
+ pickup pencircle scaled 2 stafflinethickness;
+
+ rt x1 = w;
+ bot y1 = 0;
+ rt x2 = w;
+ top y2 = h;
+
+ rt x3 = w;
+ top y3 = h;
+ lft x4 = 0;
+ bot y4 = h / 2;
+ rt x5 = w;
+ top y5 = 5/8 h;
+ lft x6 = 0;
+ bot y6 = h / 8;
+
+ z11 = z1 - stafflinethickness * unitvector (z2 - z1);
+ z14 = z4 + stafflinethickness * unitvector (z4 - z3);
+ z16 = z6 + stafflinethickness * unitvector (z6 - z5);
+
+ penpos1 (2 stafflinethickness, 0);
+ penpos2 (2 stafflinethickness, 0);
+ penpos3 (2 stafflinethickness, angle (z4 - z3) - 90);
+ penpos4 (2 stafflinethickness, angle (z4 - z3) - 90);
+ penpos5 (2 stafflinethickness, angle (z6 - z5) - 90);
+ penpos6 (2 stafflinethickness, angle (z6 - z5) - 90);
+
+ fill z1l
+ -- z2l
+ -- z2r
+ -- z1r
+ .. z11
+ .. z1l
+ .. cycle;
+ fill z3l
+ -- z4l
+ .. z14
+ .. z4r
+ -- z3r
+ .. z2r{down}
+ .. z3l
+ .. cycle;
+ fill z5l
+ -- z6l
+ .. z16
+ .. z6r
+ -- z5r
+ -- z5l
+ -- cycle;
+
+ penlabels (1, 2, 3, 4, 5, 6);
+ labels (11, 14, 16);
+fet_endchar;
+
+
+%%%%%%%%
+%
+%
+%
+% MENSURAL NOTATION
+%
+%
+%
+
+pen_width# = 0.3 staff_space#;
+pen_height# = 0;
+pen_rotation = 30;
+slight_pen_rotation = 15;
+
+mens_block_rest_y# = 1/1 staff_space#;
+mens_half_block_rest_y# = 5/8 staff_space#;
+
+define_pixels (mens_block_rest_y, mens_half_block_rest_y,
+ pen_width, pen_height);
+
+
+fet_beginchar ("Mensural maxima rest", "M3mensural");
+ set_char_box (0, pen_width#,
+ mens_block_rest_y#, 2 mens_block_rest_y#);
+
+ pickup pencircle xscaled pen_width
+ yscaled pen_height
+ rotated slight_pen_rotation;
+
+ draw (w / 2, -mens_block_rest_y)
+ -- (w / 2, 2 mens_block_rest_y);
+fet_endchar;
+
+
+fet_beginchar ("Mensural longa rest", "M2mensural");
+ set_char_box (0, pen_width#,
+ mens_block_rest_y#, mens_block_rest_y#);
+
+ pickup pencircle xscaled pen_width
+ yscaled pen_height
+ rotated slight_pen_rotation;
+
+ draw (w / 2, -mens_block_rest_y)
+ -- (w / 2, mens_block_rest_y);
+fet_endchar;
+
+
+fet_beginchar ("Mensural breve rest", "M1mensural");
+ set_char_box (0, pen_width#,
+ 0, mens_block_rest_y#);
+
+ pickup pencircle xscaled pen_width
+ yscaled pen_height
+ rotated slight_pen_rotation;
+
+ draw (w / 2, 0)
+ -- (w / 2, mens_block_rest_y);
+fet_endchar;
+
+
+fet_beginchar ("Mensural whole rest", "0mensural");
+ set_char_box (0, pen_width#,
+ mens_half_block_rest_y#, 0);
+
+ pickup pencircle xscaled pen_width
+ yscaled pen_height
+ rotated slight_pen_rotation;
+
+ draw (w / 2, 0)
+ -- (w / 2, -mens_half_block_rest_y);
+fet_endchar;
+
+
+fet_beginchar ("Mensural half rest", "1mensural");
+ set_char_box (0, pen_width#,
+ 0, mens_half_block_rest_y#);
+
+ pickup pencircle xscaled pen_width
+ yscaled pen_height
+ rotated slight_pen_rotation;
+
+ draw (w / 2, 0)
+ -- (w / 2, mens_half_block_rest_y);
+fet_endchar;
+
+
+mensrestsize# = .8 staff_space#;
+
+
+fet_beginchar ("Mensural 4th rest", "2mensural");
+ set_char_box (0, mensrestsize#,
+ 0, mensrestsize#);
+
+ pickup pencircle xscaled pen_width
+ yscaled pen_height
+ rotated pen_rotation;
+
+ lft x1 = 0;
+ y1 = 0;
+ lft x2 = 0;
+ top y2 = 5/8 h;
+ rt x3 = 1/5 w;
+ bot y3 = 6/8 h;
+ rt x4 = w;
+ bot y4 = 4/8 h;
+
+ draw z1
+ -- z2
+ -- z3
+ -- z4;
+
+ labels (1, 2, 3, 4);
+fet_endchar;
+
+%
+% FIXME: The left sharp corner produces ugly results at lower resolutions.
+%
+fet_beginchar ("Mensural 8th rest", "3mensural");
+ set_char_box (0, mensrestsize#,
+ 0, mensrestsize#);
+
+ pickup pencircle xscaled pen_width
+ yscaled pen_height
+ rotated pen_rotation;
+
+ rt x1 = w;
+ y1 = 0;
+ rt x2 = w;
+ top y2 = 5/8 h;
+ lft x3 = 1/5 w;
+ bot y3 = 6/8 h;
+ lft x4 = 0;
+ bot y4 = 4/8 h;
+
+ draw z1
+ -- z2
+ -- z3
+ -- z4;
+
+ labels (1, 2, 3, 4);
+fet_endchar;
+
+%
+% FIXME: So far, I have never seen a semifusa rest printed. Hence,
+% the shape of this font character is currently pure invention. --jr
+%
+%
+% FIXME: The left sharp corner produces ugly results at lower resolutions.
+%
+fet_beginchar ("Mensural 16th rest", "4mensural");
+ set_char_box (0, mensrestsize#,
+ 0, staff_space#);
+
+ pickup pencircle xscaled pen_width
+ yscaled pen_height
+ rotated pen_rotation;
+
+ rt x1 = w;
+ y1 = 0;
+ rt x2 = w;
+ top y2 = 5.5/8 h;
+ lft x3 = 1/5 w;
+ bot y3 = 6.5/8 h;
+ lft x4 = 0;
+ bot y4 = 4.5/8 h;
+ rt x5 = w;
+ top y5 = 2.5/8 h;
+ lft x6 = 1/5 w;
+ bot y6 = 3.5/8 h;
+ lft x7 = 0;
+ bot y7 = 1.5/8 h;
+
+ draw z1
+ -- z2
+ -- z3
+ -- z4;
+ draw z5
+ -- z6
+ -- z7;
+
+ labels (1, 2, 3, 4, 5, 6, 7);
+fet_endchar;
+
+
+fet_endgroup ("rests")
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-scripts.mf b/muse2/share/scoreglyphs/feta-original/parmesan-scripts.mf
new file mode 100644
index 00000000..3a43a46a
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-scripts.mf
@@ -0,0 +1,231 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-scripts.mf -- implement ancient script symbols
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 2002--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+fet_begingroup ("scripts");
+
+fet_beginchar ("ictus", "ictus");
+ save ht, wd;
+ ht# = .35 staff_space#;
+ wd# = linethickness#;
+
+ define_pixels (wd, ht);
+
+ save ellipse, T;
+ path ellipse;
+ transform T;
+
+ T := identity xscaled wd
+ yscaled blot_diameter;
+ pickup pencircle transformed T;
+ ellipse := fullcircle transformed T;
+
+ set_char_box (wd# / 2, wd# / 2, ht# / 2, ht# / 2);
+
+ x1 = 0;
+ top y1 = ht / 2;
+ x2 = 0;
+ bot y2 = -ht / 2;
+
+ fill get_subpath (ellipse, up, down, z1)
+ -- get_subpath (ellipse, down, up, z2)
+ -- cycle;
+
+ labels (1, 2);
+fet_endchar;
+
+
+def draw_accentus =
+ save thick, thin, ht, wd;
+
+ thin# = 1 linethickness#;
+ thick# = 1.2 linethickness#;
+ ht# = .35 staff_space#;
+ wd# = .25 staff_space#;
+
+ define_pixels (wd, ht, thin, thick);
+
+ z1 = z2 = (-wd / 2 + thin / 2, -ht / 2 + thin / 2);
+ z3 = z4 = (wd / 2 - thick / 2, ht / 2 - thick / 2);
+
+ penpos1 (thin, angle (z1 - z3));
+ penpos2 (thin, angle (z1 - z3) + 90);
+ penpos3 (thick, angle (z3 - z1) + 90);
+ penpos4 (thick, angle (z3 - z1));
+
+ fill z1r
+ .. z2r
+ -- z3l
+ .. z4r
+ .. z3r
+ -- z2l
+ .. cycle;
+
+ set_char_box (wd#/2, wd#/2, ht#/2, ht#/2);
+enddef;
+
+
+fet_beginchar ("accentus up", "uaccentus");
+ draw_accentus;
+ penlabels (1, 2, 3, 4);
+fet_endchar;
+
+
+fet_beginchar ("accentus down", "daccentus");
+ draw_accentus;
+ y_mirror_char;
+fet_endchar;
+
+
+def draw_half_circle (expr diam) =
+ save diameter, thick;
+
+ diameter# = diam;
+
+ define_pixels (diameter);
+
+ thick = 0.6 linethickness;
+
+ penpos1 (thick, 0);
+ penpos2 (thick, -90);
+ penpos3 (thick, -180);
+
+ z1r = (diameter / 2, 0);
+ z2r = (0, -diameter / 2);
+ z3r = (-diameter / 2, 0);
+
+ penstroke z1e{down}
+ .. z2e{left}
+ .. z3e{up};
+enddef;
+
+
+fet_beginchar ("half circle", "usemicirculus");
+ draw_half_circle (5/16 staff_space#);
+
+ currentpicture := currentpicture yscaled -1;
+
+ set_char_box (diameter# / 2, diameter# / 2,
+ 0, diameter# / 2);
+fet_endchar;
+
+
+fet_beginchar ("half circle", "dsemicirculus");
+ draw_half_circle (5/16 staff_space#);
+
+ set_char_box (diameter# / 2, diameter# / 2,
+ diameter# / 2, 0);
+
+ penlabels (1, 2, 3);
+fet_endchar;
+
+
+fet_beginchar ("circle", "circulus");
+ save diameter, thick;
+
+ diameter# = 5/16 staff_space#;
+
+ define_pixels (diameter);
+
+ thick = 0.6 linethickness;
+
+ fill fullcircle scaled diameter;
+ unfill fullcircle scaled (diameter - 2 thick);
+
+ set_char_box (diameter# / 2, diameter# / 2,
+ diameter# / 2, diameter# / 2);
+fet_endchar;
+
+
+fet_beginchar ("augmentum", "augmentum");
+ save diameter;
+
+ diameter# = 0.25 staff_space#;
+
+ define_pixels (diameter);
+
+ pickup pencircle scaled diameter;
+
+ drawdot (0, 0);
+
+ set_char_box (diameter# / 2, diameter# / 2,
+ diameter# / 2, diameter# / 2);
+fet_endchar;
+
+
+def draw_signum_congruentiae =
+ set_char_box (0.50 staff_space# + 1.5 linethickness#,
+ 0.50 staff_space# + 1.5 linethickness#,
+ 2.5 linethickness#,
+ 2.00 staff_space# + 3.5 linethickness#);
+
+ save ellipse, pat;
+ path ellipse, pat;
+
+ ellipse := fullcircle xscaled 1.0 linethickness
+ yscaled 5.0 linethickness
+ rotated -35;
+
+ z1 = (+0.50 staff_space, +2.00 staff_space);
+ z2 = (+0.00 staff_space, +2.00 staff_space);
+ z3 = (-0.50 staff_space, +1.50 staff_space);
+ z4 = (-0.25 staff_space, +1.00 staff_space);
+ z5 = (+0.10 staff_space, +0.80 staff_space);
+ z6 = (+0.00 staff_space, +0.00 staff_space);
+
+ pat := z1{-1, +1}
+ .. z2
+ .. z3
+ .. z4
+ .. z5
+ .. z6;
+
+ % we avoid cusps originally present in `draw pat'
+ fill get_subpath (ellipse,
+ -direction 0 of pat, direction 0 of pat, z1)
+ .. get_subpoint (ellipse, direction 1 of pat, z2)
+ {direction 1 of pat}
+ .. get_subpoint (ellipse, direction 2 of pat, z3)
+ {direction 2 of pat}
+ .. get_subpoint (ellipse, direction 3 of pat, z4)
+ {direction 3 of pat}
+ .. get_subpoint (ellipse, direction 4 of pat, z5)
+ {direction 4 of pat}
+ .. get_subpath (ellipse,
+ direction 4.8 of pat, -direction 5 of pat, z6)
+ .. get_subpoint (ellipse, -direction 4 of pat, z5)
+ {-direction 4 of pat}
+ .. get_subpoint (ellipse, -direction 3 of pat, z4)
+ {-direction 3 of pat}
+ .. get_subpoint (ellipse, -direction 2.5 of pat, point 2.5 of pat)
+ .. get_subpoint (ellipse, -direction 1 of pat, z2)
+ {-direction 1 of pat}
+ .. cycle;
+
+ pickup pencircle scaled 3.0 linethickness;
+
+ z7 = (-0.5 staff_space, +0.0 staff_space);
+ z8 = (+0.5 staff_space, +0.0 staff_space);
+
+ drawdot z7;
+ drawdot z8;
+enddef;
+
+
+fet_beginchar ("signum congruentiae up", "usignumcongruentiae");
+ draw_signum_congruentiae;
+ labels (1, 2, 3, 4, 5, 6, 7, 8);
+fet_endchar;
+
+
+fet_beginchar ("signum congruentiae down", "dsignumcongruentiae");
+ draw_signum_congruentiae;
+ xy_mirror_char;
+fet_endchar;
+
+
+fet_endgroup ("scripts");
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan-timesig.mf b/muse2/share/scoreglyphs/feta-original/parmesan-timesig.mf
new file mode 100644
index 00000000..8d0ab9d4
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan-timesig.mf
@@ -0,0 +1,395 @@
+% -%-Fundamental-%- -*-Metafont-*-
+% parmesan-timesig.mf -- implement ancient time signatures
+%
+% source file of LilyPond's pretty-but-neat music font
+%
+% (c) 1998--2009 Mats Bengtsson <matsb@s3.kth.se>,
+% Christian Mondrup <scancm@biobase.dk>
+% (c) 2002--2009 Juergen Reuter <reuter@ipd.uka.de>
+%
+
+fet_begingroup ("timesig");
+
+
+path threequartercircle;
+
+threequartercircle := halfcircle & quartercircle rotated 180;
+
+save mensural_Cdiameter, mensural_Cthickness, mensural_Chairpin;
+
+mensural_Cdiameter# := 3/2 staff_space#;
+mensural_Cthickness# := 2 linethickness#;
+mensural_Chairpin# := 0.5 linethickness#;
+
+define_pixels (mensural_Cdiameter, mensural_Cthickness, mensural_Chairpin);
+
+
+%%%%%%%%
+%
+%
+%
+% MENSURAL NOTATION
+%
+%
+%
+
+def draw_nail (expr bottom_left, top_right) =
+ save round;
+
+ round = floor min (blot_diameter,
+ xpart (top_right-bottom_left),
+ ypart (top_right-bottom_left));
+
+ pickup pencircle scaled round;
+
+ z2 + (round / 2, round / 2) = top_right +
+ (mensural_Cthickness / 2, 0);
+ z4 - (round / 2,round / 2) = bottom_left;
+ y3 = y2;
+ y4 = y1;
+ x2 = x1 + mensural_Cthickness / 2;
+ x2 - x1 = x4 - x3;
+ x5 = x1;
+ x6 = x4;
+ y5 = y6 = y2 - 2 mensural_Cthickness;
+
+ fill bot z1{right}
+ .. rt z1{up}
+ -- rt z5{up}
+ .. rt z2
+ .. top z2{left}
+ -- top z3{left}
+ .. lft z3
+ .. lft z6{down}
+ -- lft z4{down}
+ .. bot z4{right}
+ -- cycle;
+
+% labels (1, 2, 3, 4, 5, 6);
+enddef;
+
+
+def mensural_timesig (expr verbose_name, internal_name,
+ full_circle, reverse_circle, slashed, dotted) =
+ fet_beginchar (verbose_name, internal_name);
+ if slashed:
+ set_char_box (
+ 0,
+ mensural_Cdiameter# + mensural_Cthickness#,
+ .75 (mensural_Cdiameter# + mensural_Cthickness#),
+ .75 (mensural_Cdiameter# + mensural_Cthickness#));
+
+ if (full_circle or dotted):
+ draw_nail ((-mensural_Cthickness / 2, -d),
+ (mensural_Cthickness / 2, h));
+ elseif reverse_circle:
+ draw_nail ((0, -d), (mensural_Cthickness, h));
+ else:
+ draw_nail ((-mensural_Cthickness, -d), (0, h));
+ fi;
+ else:
+ set_char_box (
+ 0,
+ mensural_Cdiameter# + mensural_Cthickness#,
+ .5 (mensural_Cdiameter# + mensural_Cthickness#),
+ .5 (mensural_Cdiameter# + mensural_Cthickness#));
+ fi;
+
+ save ellipse, pat;
+ path ellipse, pat;
+
+ ellipse := fullcircle xscaled mensural_Cthickness
+ yscaled mensural_Chairpin;
+
+ save rot;
+
+ if reverse_circle:
+ rot := 225;
+ else:
+ rot := 45;
+ fi;
+
+ if full_circle:
+ pat := fullcircle scaled mensural_Cdiameter;
+
+ fill get_subpoint (ellipse,
+ direction 0 of pat,
+ point 0 of pat)
+ for i = 1 step 1 until length pat:
+ .. get_subpoint (ellipse,
+ direction i of pat,
+ point i of pat)
+ endfor
+ .. cycle;
+ unfill get_subpoint (ellipse,
+ -direction 0 of pat,
+ point 0 of pat)
+ for i = 1 step 1 until length pat:
+ .. get_subpoint (ellipse,
+ -direction i of pat,
+ point i of pat)
+ endfor
+ .. cycle;
+ else:
+ pat := threequartercircle rotated rot
+ scaled mensural_Cdiameter;
+
+ fill get_subpath (ellipse,
+ -direction 0 of pat,
+ direction 0 of pat,
+ point 0 of pat)
+ for i = 1 step 1 until (length pat - 1):
+ .. get_subpoint (ellipse,
+ direction i of pat,
+ point i of pat)
+ endfor
+ .. get_subpath (ellipse,
+ direction infinity of pat,
+ -direction infinity of pat,
+ point infinity of pat)
+ for i = (length pat - 1) step -1 until 1:
+ .. get_subpoint (ellipse,
+ -direction i of pat,
+ point i of pat)
+ endfor
+ .. cycle;
+ fi;
+
+ if dotted:
+ pickup pencircle scaled 4 linethickness;
+ drawdot (0, 0);
+ fi;
+
+ currentpicture := currentpicture
+ shifted 0.5 (mensural_Cdiameter
+ + mensural_Cthickness, 0);
+ fet_endchar;
+enddef;
+
+
+%% tempus imperfectum cum prolatione imperfecta
+mensural_timesig ("Mensural 4/4 meter", "mensural44",
+ false, false, false, false);
+
+
+%% tempus imperfectum cum prolatione imperfecta proportio dupla
+mensural_timesig ("Mensural 2/2 meter", "mensural22",
+ false, false, true, false);
+
+
+%% tempus perfectum cum prolatione imperfecta
+mensural_timesig ("Mensural 3/2 meter", "mensural32",
+ true, false, false, false);
+
+
+%% tempus imperfectum cum prolatione perfecta
+mensural_timesig ("Mensural 6/4 meter", "mensural64",
+ false, false, false, true);
+
+
+%% tempus perfectum cum prolatione perfecta
+mensural_timesig ("Mensural 9/4 meter", "mensural94",
+ true, false, false, true);
+
+
+%% tempus perfectum cum prolatione imperfecta proportio dupla
+mensural_timesig ("Mensural 3/4 meter", "mensural34",
+ true, false, true, false);
+
+
+%% tempus imperfectum cum prolatione perfecta proportio dupla
+mensural_timesig ("Mensural 6/8 meter", "mensural68",
+ false, false, true, true);
+
+
+%% tempus perfectum cum prolatione perfecta proportio dupla
+mensural_timesig ("Mensural 9/8 meter", "mensural98",
+ true, false, true, true);
+
+
+%% tempus imperfectum cum prolatione imperfecta diminutio simplex
+mensural_timesig ("Mensural 4/8 meter", "mensural48",
+ false, true, false, false);
+
+
+%% tempus imperfectum cum prolatione perfecta diminutio simplex
+mensural_timesig ("Mensural 6/8 meter", "mensural68alt",
+ false, true, false, true);
+
+
+%% tempus imperfectum cum prolatione imperfecta diminutio duplex
+mensural_timesig ("Mensural 2/4 meter", "mensural24",
+ false, true, true, false);
+
+
+%%%%%%%%
+%
+%
+%
+% NEO-MENSURAL NOTATION
+%
+%
+%
+
+save neomensural_Cdiameter, neomensural_Cthickness;
+
+neomensural_Cdiameter# := 3/2 staff_space#;
+neomensural_Cthickness# := 2 linethickness#;
+
+define_pixels (neomensural_Cdiameter, neomensural_Cthickness);
+
+
+def neomensural_timesig (expr verbose_name, internal_name,
+ full_circle, reverse_circle, slashed, dotted) =
+ fet_beginchar (verbose_name, internal_name);
+ set_char_box (
+ 0,
+ neomensural_Cdiameter# + neomensural_Cthickness#,
+ .5 (neomensural_Cdiameter# + neomensural_Cthickness#),
+ .5 (neomensural_Cdiameter# + neomensural_Cthickness#));
+
+ if slashed:
+ pickup penrazor scaled neomensural_Cthickness;
+
+ save t;
+ t := neomensural_Cthickness / 2;
+
+ if (full_circle or dotted):
+ draw (0, -d + t)
+ -- (0, h - t);
+ elseif reverse_circle:
+ draw (t, -d + t)
+ -- (t, h - t);
+ else:
+ draw (-t, -d + t)
+ -- (-t, h - t);
+ fi;
+ fi;
+
+ save ellipse, pat;
+ path ellipse, pat;
+
+ ellipse := fullcircle scaled neomensural_Cthickness;
+
+ save rot;
+
+ if reverse_circle:
+ rot := 225;
+ else:
+ rot := 45;
+ fi;
+
+ if full_circle:
+ pat := fullcircle scaled neomensural_Cdiameter;
+
+ fill get_subpoint (ellipse,
+ direction 0 of pat,
+ point 0 of pat)
+ for i = 1 step 1 until length pat:
+ .. get_subpoint (ellipse,
+ direction i of pat,
+ point i of pat)
+ endfor
+ .. cycle;
+ unfill get_subpoint (ellipse,
+ -direction 0 of pat,
+ point 0 of pat)
+ for i = 1 step 1 until length pat:
+ .. get_subpoint (ellipse,
+ -direction i of pat,
+ point i of pat)
+ endfor
+ .. cycle;
+ else:
+ pat := threequartercircle rotated rot
+ scaled neomensural_Cdiameter;
+
+ fill get_subpath (ellipse,
+ -direction 0 of pat,
+ direction 0 of pat,
+ point 0 of pat)
+ for i = 1 step 1 until (length pat - 1):
+ .. get_subpoint (ellipse,
+ direction i of pat,
+ point i of pat)
+ endfor
+ .. get_subpath (ellipse,
+ direction infinity of pat,
+ -direction infinity of pat,
+ point infinity of pat)
+ for i = (length pat - 1) step -1 until 1:
+ .. get_subpoint (ellipse,
+ -direction i of pat,
+ point i of pat)
+ endfor
+ .. cycle;
+ fi;
+
+ if dotted:
+ pickup pencircle scaled 4 linethickness;
+ drawdot (0, 0);
+ fi;
+
+ currentpicture := currentpicture
+ shifted 0.5 (neomensural_Cdiameter
+ + neomensural_Cthickness, 0);
+ fet_endchar;
+enddef;
+
+
+%% tempus imperfectum cum prolatione imperfecta
+neomensural_timesig ("Mensural 4/4 meter", "neomensural44",
+ false, false, false, false);
+
+
+%% tempus imperfectum cum prolatione imperfecta proportio dupla
+neomensural_timesig ("Mensural 2/2 meter", "neomensural22",
+ false, false, true, false);
+
+
+%% tempus perfectum cum prolatione imperfecta
+neomensural_timesig ("Mensural 3/2 meter", "neomensural32",
+ true, false, false, false);
+
+
+%% tempus imperfectum cum prolatione perfecta
+neomensural_timesig ("Mensural 6/4 meter", "neomensural64",
+ false, false, false, true);
+
+
+%% tempus perfectum cum prolatione perfecta
+neomensural_timesig ("Mensural 9/4 meter", "neomensural94",
+ true, false, false, true);
+
+
+%% tempus perfectum cum prolatione imperfecta proportio dupla
+neomensural_timesig ("Mensural 3/4 meter", "neomensural34",
+ true, false, true, false);
+
+
+%% tempus imperfectum cum prolatione perfecta proportio dupla
+neomensural_timesig ("Mensural 6/8 meter", "neomensural68",
+ false, false, true, true);
+
+
+%% tempus perfectum cum prolatione perfecta proportio dupla
+neomensural_timesig ("Mensural 9/8 meter", "neomensural98",
+ true, false, true, true);
+
+
+%% tempus imperfectum cum prolatione imperfecta diminutio simplex
+neomensural_timesig ("Mensural 4/8 meter", "neomensural48",
+ false, true, false, false);
+
+
+%% tempus imperfectum cum prolatione perfecta diminutio simplex
+neomensural_timesig ("Mensural 6/8 meter", "neomensural68alt",
+ false, true, false, true);
+
+
+%% tempus imperfectum cum prolatione imperfecta diminutio duplex
+neomensural_timesig ("Mensural 2/4 meter", "neomensural24",
+ false, true, true, false);
+
+
+fet_endgroup ("timesig");
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan11.mf b/muse2/share/scoreglyphs/feta-original/parmesan11.mf
new file mode 100644
index 00000000..27ba3414
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan11.mf
@@ -0,0 +1,13 @@
+% parmesan11.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 11.22;
+
+input feta-autometric;
+
+test := 0;
+
+input parmesan-generic;
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan13.mf b/muse2/share/scoreglyphs/feta-original/parmesan13.mf
new file mode 100644
index 00000000..905da48d
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan13.mf
@@ -0,0 +1,14 @@
+% parmesan13.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 12.60;
+
+input feta-autometric;
+
+test := 0;
+
+input parmesan-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan14.mf b/muse2/share/scoreglyphs/feta-original/parmesan14.mf
new file mode 100644
index 00000000..6357337b
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan14.mf
@@ -0,0 +1,14 @@
+% parmesan14.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 14.14;
+
+input feta-autometric;
+
+test := 0;
+
+input parmesan-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan16.mf b/muse2/share/scoreglyphs/feta-original/parmesan16.mf
new file mode 100644
index 00000000..19b05167
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan16.mf
@@ -0,0 +1,14 @@
+% parmesan16.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 15.87;
+
+input feta-autometric;
+
+test := 0;
+
+input parmesan-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan18.mf b/muse2/share/scoreglyphs/feta-original/parmesan18.mf
new file mode 100644
index 00000000..8c285070
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan18.mf
@@ -0,0 +1,14 @@
+% parmesan18.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 17.82;
+
+input feta-autometric;
+
+test := 0;
+
+input parmesan-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan20.mf b/muse2/share/scoreglyphs/feta-original/parmesan20.mf
new file mode 100644
index 00000000..d14251ed
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan20.mf
@@ -0,0 +1,14 @@
+% parmesan20.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 20;
+
+input feta-autometric;
+
+test := 0;
+
+input parmesan-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan23.mf b/muse2/share/scoreglyphs/feta-original/parmesan23.mf
new file mode 100644
index 00000000..39b64373
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan23.mf
@@ -0,0 +1,14 @@
+% parmesan23.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 22.45;
+
+input feta-autometric;
+
+test := 0;
+
+input parmesan-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/feta-original/parmesan26.mf b/muse2/share/scoreglyphs/feta-original/parmesan26.mf
new file mode 100644
index 00000000..1be6fb51
--- /dev/null
+++ b/muse2/share/scoreglyphs/feta-original/parmesan26.mf
@@ -0,0 +1,14 @@
+% parmesan26.mf
+% part of LilyPond's pretty-but-neat music font
+
+design_size := 25.20;
+
+input feta-autometric;
+
+test := 0;
+
+input parmesan-generic;
+
+
+end.
+
diff --git a/muse2/share/scoreglyphs/flags16d.png b/muse2/share/scoreglyphs/flags16d.png
new file mode 100644
index 00000000..dbffcdee
--- /dev/null
+++ b/muse2/share/scoreglyphs/flags16d.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/flags16u.png b/muse2/share/scoreglyphs/flags16u.png
new file mode 100644
index 00000000..4278b260
--- /dev/null
+++ b/muse2/share/scoreglyphs/flags16u.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/flags32d.png b/muse2/share/scoreglyphs/flags32d.png
new file mode 100644
index 00000000..7aedf14b
--- /dev/null
+++ b/muse2/share/scoreglyphs/flags32d.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/flags32u.png b/muse2/share/scoreglyphs/flags32u.png
new file mode 100644
index 00000000..ddcee1c2
--- /dev/null
+++ b/muse2/share/scoreglyphs/flags32u.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/flags64d.png b/muse2/share/scoreglyphs/flags64d.png
new file mode 100644
index 00000000..30c622e0
--- /dev/null
+++ b/muse2/share/scoreglyphs/flags64d.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/flags64u.png b/muse2/share/scoreglyphs/flags64u.png
new file mode 100644
index 00000000..5e1a099f
--- /dev/null
+++ b/muse2/share/scoreglyphs/flags64u.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/flags8d.png b/muse2/share/scoreglyphs/flags8d.png
new file mode 100644
index 00000000..664ee6b5
--- /dev/null
+++ b/muse2/share/scoreglyphs/flags8d.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/flags8u.png b/muse2/share/scoreglyphs/flags8u.png
new file mode 100644
index 00000000..f80a9799
--- /dev/null
+++ b/muse2/share/scoreglyphs/flags8u.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/half.png b/muse2/share/scoreglyphs/half.png
new file mode 100644
index 00000000..50be5da9
--- /dev/null
+++ b/muse2/share/scoreglyphs/half.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/quarter.png b/muse2/share/scoreglyphs/quarter.png
new file mode 100644
index 00000000..f773f824
--- /dev/null
+++ b/muse2/share/scoreglyphs/quarter.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/rest1.png b/muse2/share/scoreglyphs/rest1.png
new file mode 100644
index 00000000..3f0df51b
--- /dev/null
+++ b/muse2/share/scoreglyphs/rest1.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/rest16.png b/muse2/share/scoreglyphs/rest16.png
new file mode 100644
index 00000000..42fc656d
--- /dev/null
+++ b/muse2/share/scoreglyphs/rest16.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/rest2.png b/muse2/share/scoreglyphs/rest2.png
new file mode 100644
index 00000000..0f4497f7
--- /dev/null
+++ b/muse2/share/scoreglyphs/rest2.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/rest4.png b/muse2/share/scoreglyphs/rest4.png
new file mode 100644
index 00000000..c229426d
--- /dev/null
+++ b/muse2/share/scoreglyphs/rest4.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/rest8.png b/muse2/share/scoreglyphs/rest8.png
new file mode 100644
index 00000000..b3289706
--- /dev/null
+++ b/muse2/share/scoreglyphs/rest8.png
Binary files differ
diff --git a/muse2/share/scoreglyphs/whole.png b/muse2/share/scoreglyphs/whole.png
new file mode 100644
index 00000000..eb8b4b7f
--- /dev/null
+++ b/muse2/share/scoreglyphs/whole.png
Binary files differ