diff --git a/Verovio.xcodeproj/project.pbxproj b/Verovio.xcodeproj/project.pbxproj index f5cdedb870..b3de24bcc6 100644 --- a/Verovio.xcodeproj/project.pbxproj +++ b/Verovio.xcodeproj/project.pbxproj @@ -182,6 +182,12 @@ 4D16945A1E3A44F300569BF4 /* dot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DC34BA719BC4A83006175CD /* dot.cpp */; }; 4D16946A1E3A455100569BF4 /* humlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40CA06581E351161009CFDD7 /* humlib.cpp */; }; 4D1694741E3A455200569BF4 /* humlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 40CA06581E351161009CFDD7 /* humlib.cpp */; }; + 4D1788C22CB8FD0100FE9043 /* fraction.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D1788C12CB8FD0100FE9043 /* fraction.h */; }; + 4D1788C32CB8FD0100FE9043 /* fraction.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D1788C12CB8FD0100FE9043 /* fraction.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4D1788C52CB8FD7300FE9043 /* fraction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1788C42CB8FD7300FE9043 /* fraction.cpp */; }; + 4D1788C62CB8FD7300FE9043 /* fraction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1788C42CB8FD7300FE9043 /* fraction.cpp */; }; + 4D1788C72CB8FD7300FE9043 /* fraction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1788C42CB8FD7300FE9043 /* fraction.cpp */; }; + 4D1788C82CB8FD7300FE9043 /* fraction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1788C42CB8FD7300FE9043 /* fraction.cpp */; }; 4D1AC9772B6A9BB200434023 /* filereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1AC9762B6A9BB200434023 /* filereader.cpp */; }; 4D1AC9782B6A9BB200434023 /* filereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1AC9762B6A9BB200434023 /* filereader.cpp */; }; 4D1AC9792B6A9BB200434023 /* filereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D1AC9762B6A9BB200434023 /* filereader.cpp */; }; @@ -1805,6 +1811,8 @@ 4D09D3EC1EA8AD8500A420E6 /* horizontalaligner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = horizontalaligner.cpp; path = src/horizontalaligner.cpp; sourceTree = ""; }; 4D14600F1EA8A913007DB90C /* horizontalaligner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = horizontalaligner.h; path = include/vrv/horizontalaligner.h; sourceTree = ""; }; 4D1694601E3A44F300569BF4 /* Verovio-Humdrum */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Verovio-Humdrum"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4D1788C12CB8FD0100FE9043 /* fraction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fraction.h; path = include/vrv/fraction.h; sourceTree = ""; }; + 4D1788C42CB8FD7300FE9043 /* fraction.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = fraction.cpp; path = src/fraction.cpp; sourceTree = ""; }; 4D1AC9762B6A9BB200434023 /* filereader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = filereader.cpp; path = src/filereader.cpp; sourceTree = ""; }; 4D1AC97B2B6A9BD000434023 /* filereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = filereader.h; path = include/vrv/filereader.h; sourceTree = ""; }; 4D1BD1B421908D6B000D35B2 /* halfmrpt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = halfmrpt.cpp; path = src/halfmrpt.cpp; sourceTree = ""; }; @@ -2836,6 +2844,8 @@ 4D1AC97B2B6A9BD000434023 /* filereader.h */, 4DF28A041A754DF000BA9F7D /* floatingobject.cpp */, 4D95D4F41D7185DE00B2B856 /* floatingobject.h */, + 4D1788C12CB8FD0100FE9043 /* fraction.h */, + 4D1788C42CB8FD7300FE9043 /* fraction.cpp */, 4D09D3EC1EA8AD8500A420E6 /* horizontalaligner.cpp */, 4D14600F1EA8A913007DB90C /* horizontalaligner.h */, 4DACC93F2990ED2600B55913 /* libmei.h */, @@ -3474,6 +3484,7 @@ 4DEBE6E12B36E78900B67DFB /* facsimilefunctor.h in Headers */, 4D94E0E22995411100F49F89 /* meibasic.h in Headers */, BD2E4D9B2875882200B04350 /* stem.h in Headers */, + 4D1788C22CB8FD0100FE9043 /* fraction.h in Headers */, 4DACC9EA2990F29A00B55913 /* attmodule.h in Headers */, 4DACC98E2990F29A00B55913 /* atts_externalsymbols.h in Headers */, 4D6413762035F57800BB630E /* pages.h in Headers */, @@ -3750,6 +3761,7 @@ 4DC3B9EB239E2B23007F185E /* transposition.h in Headers */, BB4C4BC122A932FC001F6AF0 /* MidiMessage.h in Headers */, BB4C4B9222A932DF001F6AF0 /* textelement.h in Headers */, + 4D1788C32CB8FD0100FE9043 /* fraction.h in Headers */, BB4C4B5C22A932D7001F6AF0 /* mensur.h in Headers */, 4D79641E26C152400026288B /* pageelement.h in Headers */, BB4C4AEC22A932BC001F6AF0 /* editorial.h in Headers */, @@ -4003,6 +4015,7 @@ E7F1C36929F03461007E12C1 /* savefunctor.cpp in Sources */, 4DF092A62497711800239195 /* phrase.cpp in Sources */, 4DB3D8D91F83D13C00B5FC2B /* turn.cpp in Sources */, + 4D1788C62CB8FD7300FE9043 /* fraction.cpp in Sources */, 4DA0EAC422BB779400A7EBEB /* surface.cpp in Sources */, 4D1694051E3A44F300569BF4 /* iodarms.cpp in Sources */, 4DEC4DAF21C81F0600D1D273 /* sic.cpp in Sources */, @@ -4483,6 +4496,7 @@ 4DACC9F82990F29A00B55913 /* atts_figtable.cpp in Sources */, 400FEDD3206FA743000D3233 /* gracegrp.cpp in Sources */, 4D4FCD0C1F5455FF0009C455 /* staffgrp.cpp in Sources */, + 4D1788C82CB8FD7300FE9043 /* fraction.cpp in Sources */, 4DEC4DBE21C828AC00D1D273 /* corr.cpp in Sources */, 4D1BD1B521908D6B000D35B2 /* halfmrpt.cpp in Sources */, 4D1EB6A12A2A40B400AF2F98 /* textlayoutelement.cpp in Sources */, @@ -4582,6 +4596,7 @@ E7F1C36729F0345D007E12C1 /* savefunctor.cpp in Sources */, 4DEC4D8021C804C500D1D273 /* add.cpp in Sources */, 8F3DD36518854B390051330C /* view_tuplet.cpp in Sources */, + 4D1788C72CB8FD7300FE9043 /* fraction.cpp in Sources */, 4DF092A72497711800239195 /* phrase.cpp in Sources */, 4D20741422A708C600E0765F /* view_tab.cpp in Sources */, 4D1BE7861C6A40A80086DC0E /* pugixml.cpp in Sources */, @@ -4872,6 +4887,7 @@ E7F1C36829F0345D007E12C1 /* savefunctor.cpp in Sources */, BB4C4AC122A932B6001F6AF0 /* layer.cpp in Sources */, BB4C4B0522A932C3001F6AF0 /* pgfoot.cpp in Sources */, + 4D1788C52CB8FD7300FE9043 /* fraction.cpp in Sources */, 4DF092A82497711800239195 /* phrase.cpp in Sources */, BB4C4ABF22A932B6001F6AF0 /* labelabbr.cpp in Sources */, 4DA0EAC622BB779400A7EBEB /* surface.cpp in Sources */, diff --git a/bindings/iOS/all.h b/bindings/iOS/all.h index acb38d8b1e..9b4e08bfd6 100644 --- a/bindings/iOS/all.h +++ b/bindings/iOS/all.h @@ -18,6 +18,7 @@ #import #import #import +#import #import #import #import @@ -28,6 +29,7 @@ #import #import #import +#import #import #import #import @@ -105,9 +107,11 @@ #import #import #import +#import #import #import #import +#import #import #import #import @@ -121,13 +125,14 @@ #import #import #import -#import #import +#import #import #import #import #import #import +#import #import #import #import @@ -167,6 +172,7 @@ #import #import #import +#import #import #import #import @@ -184,6 +190,7 @@ #import #import #import +#import #import #import #import diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index 2a101f46e8..d8e8714c12 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -12,7 +12,7 @@ #include "atts_gestural.h" #include "atts_mensural.h" #include "atts_shared.h" -#include "horizontalaligner.h" +#include "fraction.h" #include "interface.h" namespace vrv { diff --git a/include/vrv/fraction.h b/include/vrv/fraction.h new file mode 100644 index 0000000000..c65f19fb5d --- /dev/null +++ b/include/vrv/fraction.h @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: fraction.h +// Author: Laurent Pugin +// Created: 2024 +// Copyright (c) Authors and others. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +#ifndef __VRV_FRACTION_H__ +#define __VRV_FRACTION_H__ + +#include "vrv.h" + +namespace vrv { + +//---------------------------------------------------------------------------- +// Fraction +//---------------------------------------------------------------------------- + +class Fraction { + +public: + // Constructors - make them explicit to avoid type conversion + explicit Fraction(int num = 0, int denom = 1); + explicit Fraction(data_DURATION duration); + + // Enable implicit conversion constructor for `int` + template >> + Fraction(T num) : m_numerator(num), m_denominator(1) + { + } + + /** Addition operator */ + Fraction operator+(const Fraction &other) const; + /** Subtraction operator */ + Fraction operator-(const Fraction &other) const; + /** Multiplication operator */ + Fraction operator*(const Fraction &other) const; + /** Division operator */ + Fraction operator/(const Fraction &other) const; + + /** Equality operator */ + bool operator==(const Fraction &other) const; + /** Ordering operator */ + std::strong_ordering operator<=>(const Fraction &other) const; + + /** Getters */ + int GetNumerator() const { return m_numerator; } + int GetDenominator() const { return m_denominator; } + + /** Convert fraction to a double */ + double ToDouble() const; + + /** Convert fraction to a string */ + std::string ToString() const; + + /** Convert to data_DURATION and the remaining Fraction */ + std::pair ToDur() const; + + //----------------// + // Static methods // + //----------------// + + /** Reduce the fraction represented by the two numbers */ + static void Reduce(int &numerator, int &denominator); + +private: + /** Reduce the fraction */ + void Reduce(); + +public: + // +private: + int m_numerator; + int m_denominator; +}; + +} // namespace vrv + +#endif diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index fb5a0f005b..30f470c7b2 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -9,6 +9,7 @@ #define __VRV_HORIZONTAL_ALIGNER_H__ #include "atts_shared.h" +#include "fraction.h" #include "object.h" #include "vrv.h" @@ -60,69 +61,6 @@ enum AlignmentType { #define BARLINE_REFERENCES -1 #define TSTAMP_REFERENCES -2 -//---------------------------------------------------------------------------- -// Fraction -//---------------------------------------------------------------------------- - -class Fraction { - -public: - // Constructors - make them explicit to avoid type conversion - explicit Fraction(); - explicit Fraction(int num, int denom = 1); - explicit Fraction(data_DURATION duration); - - // Enable implicit conversion constructor for `int` - template >> - Fraction(T num) : m_numerator(num), m_denominator(1) - { - } - - /** Addition operator */ - Fraction operator+(const Fraction &other) const; - /** Subtraction operator */ - Fraction operator-(const Fraction &other) const; - /** Multiplication operator */ - Fraction operator*(const Fraction &other) const; - /** Division operator */ - Fraction operator/(const Fraction &other) const; - - /** Equality operator */ - bool operator==(const Fraction &other) const; - /** Ordering operator */ - std::strong_ordering operator<=>(const Fraction &other) const; - - /** Getters */ - int GetNumerator() const { return m_numerator; } - int GetDenominator() const { return m_denominator; } - - /** Convert fraction to a double */ - double ToDouble() const; - - /** Convert fraction to a string */ - std::string ToString() const; - - /** Convert to data_DURATION and the remaining Fraction */ - std::pair ToDur() const; - - //----------------// - // Static methods // - //----------------// - - /** Reduce the fraction represented by the two numbers */ - static void Reduce(int &numerator, int &denominator); - -private: - /** Reduce the fraction */ - void Reduce(); - -public: - // -private: - int m_numerator; - int m_denominator; -}; - //---------------------------------------------------------------------------- // Alignment //---------------------------------------------------------------------------- diff --git a/include/vrv/layerelement.h b/include/vrv/layerelement.h index 30f8e1323c..b4557c22f6 100644 --- a/include/vrv/layerelement.h +++ b/include/vrv/layerelement.h @@ -14,7 +14,7 @@ #include "atts_shared.h" #include "facsimileinterface.h" -#include "horizontalaligner.h" +#include "fraction.h" #include "linkinginterface.h" #include "object.h" diff --git a/src/fraction.cpp b/src/fraction.cpp new file mode 100644 index 0000000000..63c0e8de67 --- /dev/null +++ b/src/fraction.cpp @@ -0,0 +1,132 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: fraction.cpp +// Author: Laurent Pugin +// Created: 2024 +// Copyright (c) Authors and others. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +#include "fraction.h" + +//---------------------------------------------------------------------------- + +#include +#include +#include + +//---------------------------------------------------------------------------- + +namespace vrv { + +//---------------------------------------------------------------------------- +// Fraction +//---------------------------------------------------------------------------- + +Fraction::Fraction(int num, int denom) +{ + m_numerator = num; + if (denom == 0) { + LogDebug("Denominator cannot be zero."); + denom = 1; + } + m_denominator = denom; + Reduce(); +} + +Fraction::Fraction(data_DURATION duration) +{ + duration = vrv::DurationMin(duration, DURATION_2048); + duration = vrv::DurationMax(duration, DURATION_maxima); + int den = pow(2, (duration + 1)); + m_numerator = 8; + m_denominator = den; + Reduce(); +} + +Fraction Fraction::operator+(const Fraction &other) const +{ + int num = m_numerator * other.m_denominator + other.m_numerator * m_denominator; + int denom = m_denominator * other.m_denominator; + return Fraction(num, denom); +} + +Fraction Fraction::operator-(const Fraction &other) const +{ + int num = m_numerator * other.m_denominator - other.m_numerator * m_denominator; + int denom = m_denominator * other.m_denominator; + return Fraction(num, denom); +} + +Fraction Fraction::operator*(const Fraction &other) const +{ + int num = m_numerator * other.m_numerator; + int denom = m_denominator * other.m_denominator; + return Fraction(num, denom); +} + +Fraction Fraction::operator/(const Fraction &other) const +{ + if (other.m_numerator == 0) { + LogDebug("Cannot divide by zero."); + return *this; + } + int num = m_numerator * other.m_denominator; + int denom = m_denominator * other.m_numerator; + return Fraction(num, denom); +} + +bool Fraction::operator==(const Fraction &other) const +{ + return m_numerator * other.m_denominator == other.m_numerator * m_denominator; +} + +std::strong_ordering Fraction::operator<=>(const Fraction &other) const +{ + return m_numerator * other.m_denominator <=> other.m_numerator * m_denominator; +} + +double Fraction::ToDouble() const +{ + return static_cast(m_numerator) / m_denominator; +} + +std::string Fraction::ToString() const +{ + return StringFormat("%d/%d", m_numerator, m_denominator); +} + +void Fraction::Reduce() +{ + if (m_denominator < 0) { // Keep the denominator positive + m_numerator = -m_numerator; + m_denominator = -m_denominator; + } + int gcdVal = std::gcd(abs(m_numerator), abs(m_denominator)); + if (gcdVal != 1) { + m_numerator /= gcdVal; + m_denominator /= gcdVal; + } +} + +std::pair Fraction::ToDur() const +{ + if (m_numerator == 0) return { DURATION_NONE, 0 }; + + int value = ceil(log2((double)m_denominator / (double)m_numerator * 8)) - 1; + data_DURATION dur = static_cast(value); + dur = vrv::DurationMax(DURATION_maxima, dur); + dur = vrv::DurationMin(DURATION_2048, dur); + + Fraction remainder = *this - Fraction(dur); + // Making sure we would not be trigger an inifite loop when looping over the remainder + if ((remainder >= *this) || (remainder < 0)) remainder = 0; + return { dur, remainder }; +} + +void Fraction::Reduce(int &numerator, int &denominator) +{ + Fraction fraction(numerator, denominator); + numerator = fraction.GetNumerator(); + denominator = fraction.GetDenominator(); +} + +} // namespace vrv diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 198d529eb9..6c65684f83 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -34,122 +34,6 @@ namespace vrv { -//---------------------------------------------------------------------------- -// Fraction -//---------------------------------------------------------------------------- - -Fraction::Fraction() -{ - m_numerator = 0; - m_denominator = 1; -} - -Fraction::Fraction(int num, int denom) : m_numerator(num), m_denominator(denom) -{ - if (denom == 0) { - LogDebug("Denominator cannot be zero."); - denom = 1; - } - Reduce(); -} - -Fraction::Fraction(data_DURATION duration) -{ - duration = vrv::DurationMin(duration, DURATION_2048); - duration = vrv::DurationMax(duration, DURATION_maxima); - int den = pow(2, (duration + 1)); - m_numerator = 8; - m_denominator = den; - Reduce(); -} - -Fraction Fraction::operator+(const Fraction &other) const -{ - int num = m_numerator * other.m_denominator + other.m_numerator * m_denominator; - int denom = m_denominator * other.m_denominator; - return Fraction(num, denom); -} - -Fraction Fraction::operator-(const Fraction &other) const -{ - int num = m_numerator * other.m_denominator - other.m_numerator * m_denominator; - int denom = m_denominator * other.m_denominator; - return Fraction(num, denom); -} - -Fraction Fraction::operator*(const Fraction &other) const -{ - int num = m_numerator * other.m_numerator; - int denom = m_denominator * other.m_denominator; - return Fraction(num, denom); -} - -Fraction Fraction::operator/(const Fraction &other) const -{ - if (other.m_numerator == 0) { - LogDebug("Cannot divide by zero."); - return *this; - } - int num = m_numerator * other.m_denominator; - int denom = m_denominator * other.m_numerator; - return Fraction(num, denom); -} - -bool Fraction::operator==(const Fraction &other) const -{ - return m_numerator * other.m_denominator == other.m_numerator * m_denominator; -} - -std::strong_ordering Fraction::operator<=>(const Fraction &other) const -{ - return m_numerator * other.m_denominator <=> other.m_numerator * m_denominator; -} - -double Fraction::ToDouble() const -{ - return static_cast(m_numerator) / m_denominator; -} - -std::string Fraction::ToString() const -{ - return StringFormat("%d/%d", m_numerator, m_denominator); -} - -void Fraction::Reduce() -{ - if (m_denominator < 0) { // Keep the denominator positive - m_numerator = -m_numerator; - m_denominator = -m_denominator; - } - int gcdVal = std::gcd(abs(m_numerator), abs(m_denominator)); - if (gcdVal != 1) { - m_numerator /= gcdVal; - m_denominator /= gcdVal; - } -} - -std::pair Fraction::ToDur() const -{ - if (m_numerator == 0) return { DURATION_NONE, 0 }; - - int value = ceil(log2((double)m_denominator / (double)m_numerator * 8)) - 1; - data_DURATION dur = static_cast(value); - dur = vrv::DurationMax(DURATION_maxima, dur); - dur = vrv::DurationMin(DURATION_2048, dur); - - Fraction remainder = *this - Fraction(dur); - // Making sure we would not be trigger an inifite loop when looping over the remainder - if ((remainder >= *this) || (remainder < 0)) remainder = 0; - return { dur, remainder }; -} - -void Fraction::Reduce(int &numerator, int &denominator) -{ - Fraction fraction(numerator, denominator); - numerator = fraction.GetNumerator(); - denominator = fraction.GetDenominator(); -} - //---------------------------------------------------------------------------- // HorizontalAligner //---------------------------------------------------------------------------- diff --git a/src/layerelement.cpp b/src/layerelement.cpp index ceda043f43..2422f9b41e 100644 --- a/src/layerelement.cpp +++ b/src/layerelement.cpp @@ -32,6 +32,7 @@ #include "doc.h" #include "dot.h" #include "elementpart.h" +#include "fraction.h" #include "ftrem.h" #include "functor.h" #include "horizontalaligner.h"