MuseScore/fonttools/genft.cpp
2018-12-18 14:55:54 +01:00

513 lines
20 KiB
C++

//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2009-2013 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
//
// q+d hack to create an font description file from
// lilipond tables embedded in mscore.ttf
//
//
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TRUETYPE_TABLES_H
#include <QMap>
#include <QString>
#include <QPointF>
#include <QRectF>
#include <QList>
#include <QJsonObject>
#include <QJsonValue>
#include <QFile>
#include <QStringList>
#include <QJsonDocument>
QMap<int, int> codemap;
QMap<QString, int> namemap;
//---------------------------------------------------------
// nmap
// mapping glyph names between emmentaler and smufl
//---------------------------------------------------------
QMap<QString, QString> nmap {
// { "space", "space" },
// { "plus", "plus" },
// { "comma", "comma" },
// { "hyphen", "hyphen" },
// { "period", "period" },
{ "zero", "timeSig0" },
{ "one", "timeSig1" },
{ "two", "timeSig2" },
{ "three", "timeSig3" },
{ "four", "timeSig4" },
{ "five", "timeSig5" },
{ "six", "timeSig6" },
{ "seven", "timeSig7" },
{ "eight", "timeSig8" },
{ "nine", "timeSig9" },
{ "f", "dynamicForte" },
{ "m", "dynamicMezzo" },
{ "p", "dynamicPiano" },
{ "r", "dynamicRinforzando" },
{ "s", "dynamicSubito" },
{ "z", "dynamicZ" },
{ "rests.0", "restWhole" },
{ "rests.1", "restHalf" },
// { "rests.0o", "rests.0o" }, // outside staff
// { "rests.1o", "rests.1o" },
// { "rests.M3", "rests.M3" }, // longer than longa
{ "rests.M2", "restLonga" },
{ "rests.M1", "restDoubleWhole" },
{ "rests.2", "restQuarter" },
{ "rests.2classical", "restQuarterOld" },
{ "rests.3", "rest8th" },
{ "rests.4", "rest16th" },
{ "rests.5", "rest32nd" },
{ "rests.6", "rest64th" },
{ "rests.7", "rest128th" },
{ "accidentals.sharp", "accidentalSharp" },
{ "accidentals.sharp.slashslash.stem", "accidentalQuarterSharp4" },
// { "accidentals.sharp.slashslashslash.stemstem", "accidentals.sharp.slashslashslash.stemstem" },
// { "accidentals.sharp.slashslashslash.stem", "accidentals.sharp.slashslashslash.stem" },
{ "accidentals.natural", "accidentalNatural" },
{ "accidentals.flat", "accidentalFlat" },
{ "accidentals.flatflat", "accidentalDoubleFlat" },
{ "accidentals.doublesharp", "accidentalDoubleSharp" },
// { "accidentals.sharp.slashslash.stemstemstem", "accidentals.sharp.slashslash.stemstemstem" },
// { "accidentals.flat.slash", "accidentals.flat.slash" },
// { "accidentals.flat.slashslash", "accidentals.flat.slashslash" },
// { "accidentals.mirroredflat.flat", "accidentals.mirroredflat.flat" },
// { "accidentals.mirroredflat", "accidentals.mirroredflat" },
// { "accidentals.mirroredflat.backslash", "accidentals.mirroredflat.backslash" },
// { "accidentals.flatflat.slash", "accidentals.flatflat.slash" },
// { "accidentals.rightparen", "accidentals.rightparen" },
// { "accidentals.leftparen", "accidentals.leftparen" },
// { "arrowheads.open.01", "arrowheads.open.01" },
// { "arrowheads.open.0M1", "arrowheads.open.0M1" },
// { "arrowheads.open.11", "arrowheads.open.11" },
// { "arrowheads.open.1M1", "arrowheads.open.1M1" },
// { "arrowheads.close.01", "arrowheads.close.01" },
// { "arrowheads.close.0M1", "arrowheads.close.0M1" },
// { "arrowheads.close.11", "arrowheads.close.11" },
// { "arrowheads.close.1M1", "arrowheads.close.1M1" },
{ "dots.dot", "augmentationDot" },
// { "noteheads.uM2", "noteheads.uM2" },
// { "noteheads.dM2", "noteheads.dM2" },
{ "noteheads.sM1", "noteheadDoubleWhole" },
{ "noteheads.s0", "noteheadWhole" },
{ "noteheads.s1", "noteheadHalf" },
{ "noteheads.s2", "noteheadBlack" },
{ "noteheads.s0diamond", "noteheadDiamondWhole" },
{ "noteheads.s1diamond", "noteheadDiamondHalf" },
{ "noteheads.s2diamond", "noteheadDiamondBlack" },
{ "noteheads.s0triangle", "noteheadTriangleUpWhole" },
{ "noteheads.d1triangle", "noteheadTriangleUpHalf" },
// { "noteheads.u1triangle", "" },
{ "noteheads.u2triangle", "noteheadTriangleUpBlack" },
// { "noteheads.d2triangle", "notehead" },
{ "noteheads.s0slash", "noteheadSlashWhite" },
{ "noteheads.s1slash", "noteheadSlashWhite" },
{ "noteheads.s2slash", "noteheadSlashHorizontalEnds" },
{ "noteheads.s0cross", "noteheadXWhole" },
{ "noteheads.s1cross", "noteheadXHalf" },
{ "noteheads.s2cross", "noteheadXBlack" },
{ "noteheads.s2xcircle", "noteheadCircleX" },
#if 0
{ "noteheads.s0do", "notehead" },
{ "noteheads.d1do", "notehead" },
{ "noteheads.u1do", "notehead" },
{ "noteheads.d2do", "notehead" },
{ "noteheads.u2do", "notehead" },
{ "noteheads.s0re", "notehead" },
{ "noteheads.u1re", "notehead" },
{ "noteheads.d1re", "notehead" },
{ "noteheads.u2re", "notehead" },
{ "noteheads.d2re", "notehead" },
{ "noteheads.s0mi", "notehead" },
{ "noteheads.s1mi", "notehead" },
{ "noteheads.s2mi", "notehead" },
{ "noteheads.u0fa", "notehead" },
{ "noteheads.d0fa", "notehead" },
{ "noteheads.u1fa", "notehead" },
{ "noteheads.d1fa", "notehead" },
{ "noteheads.u2fa", "notehead" },
{ "noteheads.d2fa", "notehead" },
{ "noteheads.s0la", "notehead" },
{ "noteheads.s1la", "notehead" },
{ "noteheads.s2la", "notehead" },
{ "noteheads.s0ti", "notehead" },
{ "noteheads.u1ti", "notehead" },
{ "noteheads.d1ti", "notehead" },
{ "noteheads.u2ti", "notehead" },
{ "noteheads.d2ti", "notehead" },
#endif
{ "scripts.ufermata", "fermataAbove" },
{ "scripts.dfermata", "fermataBelow" },
{ "scripts.ushortfermata", "fermataShortAbove" },
{ "scripts.dshortfermata", "fermataShortBelow" },
{ "scripts.ulongfermata", "fermataLongAbove" },
{ "scripts.dlongfermata", "fermataLongBelow" },
{ "scripts.uverylongfermata", "fermataVeryLongAbove" },
{ "scripts.dverylongfermata", "fermataVeryLongBelow" },
{ "scripts.thumb", "stringsThumbPosition" },
{ "scripts.sforzato", "articAccent" },
// { "scripts.espr", "scripts.espr" }, "<>" ?
{ "scripts.staccato", "articStaccato" },
{ "scripts.ustaccatissimo", "articStaccatissimoAbove" },
{ "scripts.dstaccatissimo", "articStaccatissimoBelow" },
{ "scripts.tenuto", "articTenuto" },
{ "scripts.uportato", "articTenuroSlurBelow" }, // spelling bug!
{ "scripts.dportato", "articTenutoSlurAbove" },
{ "scripts.umarcato", "articMarcatoAbove" },
{ "scripts.dmarcato", "articMarcatoBelow" },
{ "scripts.fadein", "guitarFadeIn" },
{ "scripts.fadeout", "guitarFadeOut" },
{ "scripts.wigglesawtooth", "volumeSwell" },
{ "scripts.wigglesawtoothwide", "wiggleSawtooth" },
{ "scripts.wigglevibratolargefaster", "wiggleSawtoothWide" },
{ "scripts.wigglevibratolargeslowest", "wiggleVibratoLargeFaster" },
{ "scripts.widelefthandvibrato", "wiggleVibratoLargeSlowest" },
{ "scripts.open", "brassMuteOpen" },
{ "scripts.stopped", "brassMuteClosed" },
{ "scripts.upbow", "stringsUpBow" },
{ "scripts.downbow", "stringsDownBow" },
{ "scripts.reverseturn", "ornamentTurnInverted" },
{ "scripts.turn", "ornamentTurn" },
{ "scripts.trill", "ornamentTrill" },
{ "scripts.upedalheel", "keyboardPedalHeel1" },
{ "scripts.dpedalheel", "keyboardPedalHeel2" },
{ "scripts.upedaltoe", "keyboardPedalToe1" },
{ "scripts.dpedaltoe", "keyboardPedalToe2" },
{ "scripts.flageolet", "stringsHarmonic" },
{ "scripts.segno", "segno" },
{ "scripts.coda", "coda" },
{ "scripts.varcoda", "codaSquare" },
{ "scripts.rcomma", "breathMark" },
// { "scripts.lcomma", "scripts.lcomma" },
// { "scripts.rvarcomma", "scripts.rvarcomma" },
// { "scripts.lvarcomma", "scripts.lvarcomma" },
{ "scripts.arpeggio", "wiggleArpeggiatoUp" },
{ "scripts.trill_element", "wiggleTrill" },
// { "scripts.arpeggio.arrow.M1", "scripts.arpeggio.arrow.M1" },
// { "scripts.arpeggio.arrow.1", "scripts.arpeggio.arrow.1" },
// { "scripts.trilelement", "scripts.trilelement" },
{ "scripts.prall", "ornamentMordent" },
{ "scripts.mordent", "ornamentMordentInverted" },
{ "scripts.prallprall", "ornamentTremblement" },
{ "scripts.prallmordent", "ornamentPrallMordent" },
{ "scripts.upprall", "ornamentUpPrall", }, // "ornamentPrecompSlideTrillAnglebert"
{ "scripts.upmordent", "ornamentUpMordent", }, // "ornamentPrecompSlideTrillBach"
{ "scripts.pralldown", "ornamentPrallDown" },
{ "scripts.downprall", "ornamentDownPrall" },
{ "scripts.downmordent", "ornamentDownMordent" },
{ "scripts.prallup", "ornamentPrallUp" },
{ "scripts.lineprall", "ornamentLinePrall" },
// { "scripts.caesura.curved", "scripts.caesura.curved" },
{ "scripts.caesura.straight", "caesura" },
{ "flags.u3", "flag8thUp" },
{ "flags.u4", "flag16thUp" },
{ "flags.u5", "flag32ndUp" },
{ "flags.u6", "flag64thUp" },
{ "flags.d3", "flag8thDown" },
// { "flags.ugrace", "flags.ugrace" },
// { "flags.dgrace", "flags.dgrace" },
{ "flags.d4", "flag16thDown" },
{ "flags.d5", "flag32ndDown" },
{ "flags.d6", "flag64thDown" },
{ "clefs.C", "cClef" },
// { "clefs.C_change", "clefs.C_change" },
{ "clefs.F", "fClef" },
// { "clefs.F_change", "clefs.F_change" },
{ "clefs.G", "gClef" },
// { "clefs.G_change", "clefs.G_change" },
{ "clefs.percussion", "unpitchedPercussionClef1" },
// { "clefs.percussion_change", "clefs.percussion_change" },
{ "clefs.tab", "6stringTabClefSerif" },
// { "clefs.tab_change", "clefs.tab_change" },
{ "timesig.C44", "timeSigCommon" },
{ "timesig.C22", "timeSigCutCommon" },
{ "pedal.*", "keyboardPedalUp" },
// { "pedal.M", "pedal.M" },
// { "pedal..", "pedal.." },
{ "pedal.P", "keyboardPedalP" },
// { "pedal.d", "pedal.d" },
// { "pedal.e", "pedal.e" },
{ "pedal.Ped", "keyboardPedalPed" },
{ "brackettips.uright", "bracketTop" },
{ "brackettips.dright", "bracketBottom" },
// { "accordion.accDiscant", "accordion.accDiscant" },
// { "accordion.accDot", "accordion.accDot" },
// { "accordion.accFreebase", "accordion.accFreebase" },
// { "accordion.accStdbase", "accordion.accStdbase" },
// { "accordion.accBayanbase", "accordion.accBayanbase" },
// { "accordion.accOldEE", "accordion.accOldEE" },
{ "brackettips.uleft", "reversedBracketTop" },
{ "brackettips.dleft", "reversedBracketBottom" },
{ "flags.d7", "flag128thDown" },
{ "flags.u7", "flag128thUp" },
{ "scripts.snappizzicato", "pluckedSnapPizzicatoAbove" },
#if 0
{ "noteheads.sM1double", "noteheads.sM1double" },
{ "accidentals.flat.arrowup", "accidentals.flat.arrowup" },
{ "accidentals.flat.arrowdown", "accidentals.flat.arrowdown" },
{ "accidentals.flat.arrowboth", "accidentals.flat.arrowboth" },
{ "accidentals.natural.arrowup", "accidentals.natural.arrowup" },
{ "accidentals.natural.arrowdown", "accidentals.natural.arrowdown" },
{ "accidentals.natural.arrowboth", "accidentals.natural.arrowboth" },
{ "accidentals.sharp.arrowup", "accidentals.sharp.arrowup" },
{ "accidentals.sharp.arrowdown", "accidentals.sharp.arrowdown" },
{ "accidentals.sharp.arrowboth", "accidentals.sharp.arrowboth" },
{ "noteheads.uM2alt", "noteheads.uM2alt" },
{ "noteheads.dM2alt", "noteheads.dM2alt" },
{ "noteheads.sM1alt", "noteheads.sM1alt" },
{ "timesig.Cdot", "timesig.Cdot" },
{ "timesig.O", "timesig.O" },
{ "timesig.Ocut", "timesig.Ocut" },
{ "timesig.Odot", "timesig.Odot" },
#endif
// { "uniE1CB", "uniE1CB" },
// { "uniE1CC", "uniE1CC" },
// { "uniE1CD", "uniE1CD" },
// { "uniE1CE", "uniE1CE" },
// { "uniE1CF", "uniE1CF" },
// { "uniE1D0", "uniE1D0" },
// { "uniE1D1", "uniE1D1" },
// { "uniE1D2", "uniE1D2" },
{ "uniE1D3", "ornamentPrecompSlide" },
{ "uniE1D6", "gClef15mb" }, // new glyphs for smufl compatibility
{ "uniE1D7", "gClef8vb" },
{ "uniE1D8", "gClef8va" },
{ "uniE1D9", "gClef15ma" },
{ "uniE1DA", "fClef15mb" },
{ "uniE1DB", "fClef8vb" },
{ "uniE1DC", "fClef8va" },
{ "uniE1DD", "fClef15ma" },
{ "accidentals.sori", "accidentalSori" },
{ "accidentals.koron", "accidentalKoron" }
};
//---------------------------------------------------------
// Glyph
//---------------------------------------------------------
struct Glyph {
QString name;
int code;
QPointF attach;
QRectF bbox;
};
QList<Glyph> glyphs;
#if 0
//---------------------------------------------------------
// getTable
//---------------------------------------------------------
static char* getTable(char* t, FT_Face face)
{
FT_ULong tag = FT_MAKE_TAG(t[0], t[1], t[2], t[3]);
FT_ULong length = 0;
int error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &length);
if (error) {
qDebug("genft: cannot load table LILC");
exit(-3);
}
FT_Byte* buffer = (FT_Byte*)malloc(length + 1);
error = FT_Load_Sfnt_Table(face, tag, 0, buffer, &length);
buffer[length] = 0;
if (error) {
qDebug("genft: cannot load font table LILC");
exit(4);
}
return (char*)buffer;
}
//---------------------------------------------------------
// parseLILC
// (rests.0 .
// ((bbox . (-0.000000 -3.125000 7.500000 0.000000))
// (subfont . "feta20")
// (subfont-index . 33)
// (attachment . (7.500000 . 0.000000))))
//---------------------------------------------------------
static void parseLILC(char* buffer)
{
QString s(buffer);
QStringList sl = s.split("\n");
QRegExp ra("\\(attachment\\s\\.\\s\\(([0-9\\+\\-\\.]{1,})\\s\\.\\s([0-9\\+\\-\\.]{1,})\\)\\)\\)\\)");
QRegExp rb("\\(\\(bbox\\s\\.\\s\\(([0-9\\+\\-\\.]{1,})\\s([0-9\\+\\-\\.]{1,})\\s([0-9\\+\\-\\.]{1,})\\s([0-9\\+\\-\\.]{1,})\\)\\)");
int n = sl.size();
for (int i = 0; (i+4) < n; i += 5) {
Glyph g;
QString s = sl[i];
int nn = s.size();
s = s.mid(1, nn - 3);
g.name = s;
int idx = 0;
if (namemap.contains(s))
idx = namemap[s];
else
qDebug("genft: <%s> not in map", qPrintable(s));
int code = 0;
if (codemap.contains(idx))
code = codemap[idx];
else
qDebug("codemap has no index %d", idx);
g.code = code;
s = sl[i+4];
int val = ra.indexIn(s);
if (val == -1 || ra.captureCount() != 2) {
qDebug("bad reg expr a");
exit(-5);
}
g.attach.rx() = ra.cap(1).toDouble();
g.attach.ry() = -ra.cap(2).toDouble();
s = sl[i+1];
val = rb.indexIn(s);
if (val == -1 || rb.captureCount() != 4) {
qDebug("bad reg expr b");
exit(-5);
}
double a = rb.cap(1).toDouble();
double b = rb.cap(2).toDouble();
double c = rb.cap(3).toDouble();
double d = rb.cap(4).toDouble();
g.bbox = QRectF(a, -d, c - a, d - b);
glyphs.append(g);
}
}
#endif
//---------------------------------------------------------
// genJson
//---------------------------------------------------------
static void genJson()
{
QJsonObject o;
QMapIterator<QString, int> i(namemap);
while (i.hasNext()) {
i.next();
if (!nmap.contains(i.key())) {
fprintf(stderr, "not found: <%s>\n", qPrintable(i.key()));
continue;
}
int code = codemap[i.value()];
QString smufl = nmap.value(i.key());
QJsonObject jg;
QString s = QString("U+%1").arg(code, 0, 16);
jg.insert("codepoint", s);
QJsonValue val(s);
o.insert(smufl, jg);
}
QJsonDocument d(o);
QByteArray ba = d.toJson();
QFile f("glyphnames.json");
f.open(QIODevice::WriteOnly);
f.write(ba);
f.close();
}
//---------------------------------------------------------
// main
//---------------------------------------------------------
int main(int, char* argv[])
{
FT_Library library;
if (FT_Init_FreeType(&library)) {
qDebug("init free type library failed");
exit(-1);
}
FT_Face face;
int error = FT_New_Face(library, argv[1], 0, &face);
if (error) {
qDebug("open font failed <%s>", argv[1]);
exit(-2);
}
FT_Select_Charmap(face, FT_ENCODING_UNICODE);
FT_ULong charcode;
FT_UInt gindex;
for (charcode = FT_Get_First_Char(face, &gindex); gindex;
charcode = FT_Get_Next_Char(face, charcode, &gindex)) {
char name[256];
FT_Get_Glyph_Name(face, gindex, name, 256);
codemap[gindex] = charcode;
namemap[name] = gindex;
}
// char* p = getTable((char*)"LILC", face);
// parseLILC(p);
// p = getTable("LILY", face); // global values, not used
// p = getTable("LILF", face); // subfont table, not used
genJson();
return 0;
}