diff --git a/.github/workflows/ci_build.yml b/.github/workflows/ci_build.yml index 1b2a06a5f05..08437b037dc 100644 --- a/.github/workflows/ci_build.yml +++ b/.github/workflows/ci_build.yml @@ -112,7 +112,7 @@ jobs: steps: - name: Checkout main repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Installation step for Ubuntu - name: Configure Ubuntu with ${{ matrix.compiler }}-${{ matrix.version }} @@ -239,7 +239,7 @@ jobs: steps: - name: Checkout main repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create TEMP_DIR working-directory: ${{ github.workspace }} @@ -291,7 +291,7 @@ jobs: steps: - name: Checkout main repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create TEMP_DIR working-directory: ${{ github.workspace }} @@ -353,7 +353,7 @@ jobs: steps: - name: Checkout GH_PAGES_REPO into GH_PAGES_DIR - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # repository to check out repository: ${{ env.GH_PAGES_REPO }} @@ -435,7 +435,7 @@ jobs: steps: - name: Checkout main repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install doxygen run: | @@ -472,7 +472,7 @@ jobs: steps: - name: Checkout DOXYGEN_REPO into DOXYGEN_DIR - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # repository to check out repository: ${{ env.DOXYGEN_REPO }} diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml index 2bd967fee70..e00c94d00fa 100644 --- a/.github/workflows/clang-format-check.yml +++ b/.github/workflows/clang-format-check.yml @@ -16,7 +16,7 @@ jobs: name: Check for ${{ matrix.path['check'] }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run clang-format style check for C/C++ programs. uses: jidicula/clang-format-action@v4.9.0 with: diff --git a/.github/workflows/python-ci-wheel.yml b/.github/workflows/python-ci-wheel.yml index 4eba9e8bbda..219ed29ce00 100644 --- a/.github/workflows/python-ci-wheel.yml +++ b/.github/workflows/python-ci-wheel.yml @@ -24,7 +24,7 @@ jobs: # Build the wheels for Linux, Windows and macOS matrix: os: [macos-latest, windows-latest, ubuntu-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] architecture: [x86, x64] include: - os: macos-latest @@ -48,7 +48,7 @@ jobs: steps: #===============================================# # Set up - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -82,7 +82,7 @@ jobs: #===============================================# # wheels - name: Build wheels - uses: pypa/cibuildwheel@v2.11.1 + uses: pypa/cibuildwheel@v2.16.1 with: output-dir: wheelhouse env: @@ -147,7 +147,7 @@ jobs: steps: #===============================================# # Set up - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -224,7 +224,7 @@ jobs: steps: #===============================================# # Set up - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python 3.9 uses: actions/setup-python@v4 diff --git a/.github/workflows/tests_build.yml b/.github/workflows/tests_build.yml index 8080101ed21..042d65eaf72 100644 --- a/.github/workflows/tests_build.yml +++ b/.github/workflows/tests_build.yml @@ -45,7 +45,7 @@ jobs: echo "OUTPUT_DIR=${{ github.event.pull_request.number }}/${{ env.SHORT_SHA }}" >> $GITHUB_ENV - name: Checkout GH_PAGES_BRANCH into GH_PAGES_DIR - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ env.GH_PAGES_REPO }} ref: ${{ env.GH_PAGES_BRANCH }} @@ -67,7 +67,7 @@ jobs: python3 -m pip install diffimg jsondiff lxml xmldiff cairosvg - name: Checkout the dev branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: develop path: ${{ env.DEV_DIR }}/ @@ -88,7 +88,7 @@ jobs: python3 ../../doc/test-suite.py ${{ github.workspace }}/${{env.GH_PAGES_DIR}}/musicxmlTestSuite ${{ github.workspace }}/${{ env.TEMP_DIR }}/${{ env.DEV_DIR }}/ - name: Checkout the PR - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} path: ${{ env.PR_DIR }}/ diff --git a/.gitignore b/.gitignore index 1c2172a8b7b..a452c339bc1 100644 --- a/.gitignore +++ b/.gitignore @@ -99,3 +99,4 @@ Release/ # Intermediate font files fonts/**/tmp libmei/tools/__pycache__ +doc/.venv diff --git a/CHANGELOG.md b/CHANGELOG.md index 8906a50d062..6b095c12dbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,25 @@ ## [unreleased] +## [4.1.0] - 2023-12-15 +* Support for staves ordered by `scoreDef` +* Support for `rend@letterspacing` and `syl@letterspacing` in MEI vu +* Support for `nc@loc` +* Support for `note@head.color` +* Support for `note@head.fill` with `@headshape="diammond"` +* Support for `staffDef@oct.default` +* Improved metadata in the Humdrum importer (@gregchapman-dev) +* Improved layout with labels in verses +* Fix validity of the MEI header output in MEI Basic +* Fix for the Java binding and cocoaPods + +## [4.0.1] - 2023-09-05 +* Fix MEI version in output + +## [4.0.0] - 2023-09-05 +* Update schemas to MEI 5.0 and corresponding adjustments +* Support for `space` within `beam` + ## [3.16.0] - 2023-07-03 * Support for rectangular tone clusters (@eNote-GmbH) * Support for delayed turns on chords (@eNote-GmbH) diff --git a/Verovio.podspec b/Verovio.podspec index 769a2dc10b7..e401987e0fa 100644 --- a/Verovio.podspec +++ b/Verovio.podspec @@ -1,21 +1,21 @@ Pod::Spec.new do |s| s.name = 'Verovio' - s.version = '3.17.0-dev' - s.license = { :type => 'LGPL' } + s.version = '4.2.0-dev' + s.license = { :type => 'LGPL', :file => 'COPYING' } s.homepage = 'https://www.verovio.org/index.xhtml' s.authors = { 'Contributors List' => 'https://github.com/rism-digital/verovio/graphs/contributors' } s.summary = 'Verovio' s.source = { :git => 'https://github.com/rism-digital/verovio.git', :tag => 'version-' + s.version.to_s } - s.swift_versions = ['3.0', '4.0', '4.1', '4.2', '5.0','5.1'] + s.swift_versions = ['3.0', '4.0', '4.1', '4.2', '5.0', '5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '5.7'] s.source_files = 'src/**/*.{h,cpp,cc}', - 'include/{crc,hum,json,midi,pugi,utf8,vrv,zip}/*.{h,hpp}', - 'libmei/{dist,addons}/*.{h,cpp}' + 'include/{crc,hum,json,midi,pugi,utf8,vrv,zip}/*.{h,hpp}', + 'libmei/{dist,addons}/*.{h,cpp}' s.public_header_files = 'src/**/*.{h}', 'include/{crc,hum,json,midi,pugi,utf8,vrv,zip}/*.{h,hpp}', 'libmei/{dist,addons}/*.{h}' s.resources = 'data' - s.ios.deployment_target = '10.0' - s.osx.deployment_target = '10.13' + s.ios.deployment_target = '14.0' + s.osx.deployment_target = '10.15' s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", "CLANG_CXX_LIBRARY" => "libc++", @@ -29,7 +29,7 @@ Pod::Spec.new do |s| "MTL_FAST_MATH" => "YES", "SUPPORTS_UIKITFORMAC" => "NO", "MTL_ENABLE_DEBUG_INFO" => "NO", - "PRODUCT_BUNDLE_IDENTIFIER" => "com.rism.VerovioFramework" + "PRODUCT_BUNDLE_IDENTIFIER" => "digital.rism.VerovioFramework" } end diff --git a/Verovio.xcodeproj/project.pbxproj b/Verovio.xcodeproj/project.pbxproj index 71a61738a1e..b129cb6e9af 100644 --- a/Verovio.xcodeproj/project.pbxproj +++ b/Verovio.xcodeproj/project.pbxproj @@ -375,6 +375,12 @@ 4D796B5E1D78641900A15238 /* harm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D796B5D1D78641900A15238 /* harm.cpp */; }; 4D798CBD1B8AEDBA007281CA /* drawinginterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D798CBC1B8AEDBA007281CA /* drawinginterface.cpp */; }; 4D798CBE1B8AEDBA007281CA /* drawinginterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D798CBC1B8AEDBA007281CA /* drawinginterface.cpp */; }; + 4D7AFDC72A5554A100835ED1 /* divline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D7AFDC62A5554A100835ED1 /* divline.cpp */; }; + 4D7AFDC82A5554A100835ED1 /* divline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D7AFDC62A5554A100835ED1 /* divline.cpp */; }; + 4D7AFDC92A5554A100835ED1 /* divline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D7AFDC62A5554A100835ED1 /* divline.cpp */; }; + 4D7AFDCA2A5554A100835ED1 /* divline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D7AFDC62A5554A100835ED1 /* divline.cpp */; }; + 4D7AFDCC2A5554C100835ED1 /* divline.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D7AFDCB2A5554C100835ED1 /* divline.h */; }; + 4D7AFDCD2A5554C100835ED1 /* divline.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D7AFDCB2A5554C100835ED1 /* divline.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D81351B2322C2CC00F59C01 /* keyaccid.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D81351A2322C2CC00F59C01 /* keyaccid.h */; }; 4D81351C2322C2CC00F59C01 /* keyaccid.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D81351A2322C2CC00F59C01 /* keyaccid.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D81351E2322C41800F59C01 /* keyaccid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D81351D2322C41800F59C01 /* keyaccid.cpp */; }; @@ -1844,6 +1850,8 @@ 4D796B5D1D78641900A15238 /* harm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = harm.cpp; path = src/harm.cpp; sourceTree = ""; }; 4D797B041A67C55F007637BD /* devicecontextbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = devicecontextbase.h; path = include/vrv/devicecontextbase.h; sourceTree = ""; }; 4D798CBC1B8AEDBA007281CA /* drawinginterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = drawinginterface.cpp; path = src/drawinginterface.cpp; sourceTree = ""; }; + 4D7AFDC62A5554A100835ED1 /* divline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = divline.cpp; path = src/divline.cpp; sourceTree = ""; }; + 4D7AFDCB2A5554C100835ED1 /* divline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = divline.h; path = include/vrv/divline.h; sourceTree = ""; }; 4D81351A2322C2CC00F59C01 /* keyaccid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keyaccid.h; path = include/vrv/keyaccid.h; sourceTree = ""; }; 4D81351D2322C41800F59C01 /* keyaccid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = keyaccid.cpp; path = src/keyaccid.cpp; sourceTree = ""; }; 4D88AD07289673D50006D7DA /* symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = symbol.h; path = include/vrv/symbol.h; sourceTree = ""; }; @@ -2607,8 +2615,9 @@ 4DF2AF7D1A62F6A50016F869 /* drawinginterface.h */, 8F086EBE188539540037FD8E /* durationinterface.cpp */, 8F59291518854BF800FE51AD /* durationinterface.h */, - 4DA0EAD322BB77AF00A7EBEB /* facsimileinterface.h */, 4DA0EAE922BB77C300A7EBEB /* facsimileinterface.cpp */, + 4DA0EAD322BB77AF00A7EBEB /* facsimileinterface.h */, + 4DE0B9A02988070C00D4C939 /* interface.h */, 4D94721E20CA702C00C780C8 /* linkinginterface.cpp */, 4D94721C20CA701000C780C8 /* linkinginterface.h */, 8F086ECF188539540037FD8E /* pitchinterface.cpp */, @@ -2763,7 +2772,6 @@ 4D95D4F41D7185DE00B2B856 /* floatingobject.h */, 4D09D3EC1EA8AD8500A420E6 /* horizontalaligner.cpp */, 4D14600F1EA8A913007DB90C /* horizontalaligner.h */, - 4DE0B9A02988070C00D4C939 /* interface.h */, 4DACC93F2990ED2600B55913 /* libmei.h */, 8F086ECD188539540037FD8E /* object.cpp */, 8F59292418854BF800FE51AD /* object.h */, @@ -2907,6 +2915,8 @@ 8F59291218854BF800FE51AD /* clef.h */, 4DC34BA619BC4A83006175CD /* custos.cpp */, 4DC34BA019BC4A70006175CD /* custos.h */, + 4D7AFDC62A5554A100835ED1 /* divline.cpp */, + 4D7AFDCB2A5554C100835ED1 /* divline.h */, 4DC34BA719BC4A83006175CD /* dot.cpp */, 4DC34BA119BC4A70006175CD /* dot.h */, 4DEEDE631E617C930087E8BC /* elementpart.cpp */, @@ -3205,6 +3215,7 @@ 4DACCA112990F2E600B55913 /* attalternates.h in Headers */, 4DACC98C2990F29A00B55913 /* atts_usersymbols.h in Headers */, 8F59294418854BF800FE51AD /* layer.h in Headers */, + 4D7AFDCC2A5554C100835ED1 /* divline.h in Headers */, E7F1C36429F033FB007E12C1 /* savefunctor.h in Headers */, 4DACCA172990F2E600B55913 /* attdef.h in Headers */, 4DB3D8EC1F83D18300B5FC2B /* proport.h in Headers */, @@ -3491,6 +3502,7 @@ BB4C4B4C22A932D7001F6AF0 /* custos.h in Headers */, 4DACCA182990F2E600B55913 /* attdef.h in Headers */, BB4C4ADA22A932B6001F6AF0 /* system.h in Headers */, + 4D7AFDCD2A5554C100835ED1 /* divline.h in Headers */, 4DACC9CD2990F29A00B55913 /* attclasses.h in Headers */, E76A9D4829A74E180044682D /* adjustdotsfunctor.h in Headers */, 4DA0EAE422BB77AF00A7EBEB /* surface.h in Headers */, @@ -3845,6 +3857,7 @@ buildActionMask = 2147483647; files = ( 4D1693F51E3A44F300569BF4 /* verticalaligner.cpp in Sources */, + 4D7AFDC82A5554A100835ED1 /* divline.cpp in Sources */, 4D1693F61E3A44F300569BF4 /* barline.cpp in Sources */, E7901661298BCB2C008FDB4E /* calcalignmentxposfunctor.cpp in Sources */, 400FEDD6206FA74D000D3233 /* gracegrp.cpp in Sources */, @@ -4322,6 +4335,7 @@ 8F086F0A188539540037FD8E /* view_page.cpp in Sources */, E7876F2029C0A702002147DC /* adjusttupletsxfunctor.cpp in Sources */, E79C87C3269440570098FE85 /* lv.cpp in Sources */, + 4D7AFDC72A5554A100835ED1 /* divline.cpp in Sources */, 4DEC4DA621C81ED400D1D273 /* reg.cpp in Sources */, 8F086F0B188539540037FD8E /* view_tuplet.cpp in Sources */, 4D4C26ED1EF7E75400681770 /* label.cpp in Sources */, @@ -4406,6 +4420,7 @@ buildActionMask = 2147483647; files = ( 4DEF8A6621B7AAF90093A76B /* f.cpp in Sources */, + 4D7AFDC92A5554A100835ED1 /* divline.cpp in Sources */, 4DB3D8F01F83D1A700B5FC2B /* fig.cpp in Sources */, E790165F298BCB27008FDB4E /* calcalignmentxposfunctor.cpp in Sources */, 8F3DD36718854B410051330C /* verticalaligner.cpp in Sources */, @@ -4687,6 +4702,7 @@ buildActionMask = 2147483647; files = ( BB4C4AF522A932BC001F6AF0 /* ref.cpp in Sources */, + 4D7AFDCA2A5554A100835ED1 /* divline.cpp in Sources */, BB4C4B9322A932E5001F6AF0 /* areaposinterface.cpp in Sources */, E7901660298BCB27008FDB4E /* calcalignmentxposfunctor.cpp in Sources */, BB4C4AA122A9328F001F6AF0 /* verticalaligner.cpp in Sources */, diff --git a/bindings/iOS/all.h b/bindings/iOS/all.h index c884aa77465..9c77adf6e96 100644 --- a/bindings/iOS/all.h +++ b/bindings/iOS/all.h @@ -75,6 +75,7 @@ #import #import #import +#import #import #import #import @@ -139,6 +140,7 @@ #import #import #import +#import #import #import #import @@ -172,7 +174,6 @@ #import #import #import -#import #import #import #import diff --git a/bindings/java/pom.xml b/bindings/java/pom.xml index 4bf70a08e9a..33ef0597eb8 100644 --- a/bindings/java/pom.xml +++ b/bindings/java/pom.xml @@ -4,7 +4,7 @@ org.rism.verovio VerovioToolkit - 3.17.0-dev + 4.2.0-dev jar VerovioToolkit @@ -29,11 +29,11 @@ run - + - + diff --git a/bindings/python/.pypi-version b/bindings/python/.pypi-version index de1ab3a3da4..84066c019f4 100644 --- a/bindings/python/.pypi-version +++ b/bindings/python/.pypi-version @@ -1,3 +1,3 @@ # dummy file used by setup.py for counting revisions when publishing to test.pypi # counting can be reset by making a change to this file -3.17.0 +4.2.0 diff --git a/codemeta.json b/codemeta.json index 85627993ac9..390078a93ba 100644 --- a/codemeta.json +++ b/codemeta.json @@ -4,8 +4,8 @@ "identifier": "Verovio", "name": "Verovio", "description": "Verovio is a fast, portable and lightweight open-source library for engraving Music Encoding Initiative (MEI) music scores into SVG.", - "softwareVersion": "3.17.0-dev", - "datePublished": "2023-07-03", + "softwareVersion": "4.2.0-dev", + "datePublished": "2023-12-15", "license": "https://www.gnu.org/licenses/lgpl-3.0", "programmingLanguage": [{ "@type": "ComputerLanguage", diff --git a/data/Bravura.css b/data/Bravura.css index 4527236eee8..c4c899e374f 100644 --- a/data/Bravura.css +++ b/data/Bravura.css @@ -1,6 +1,6 @@ @font-face { font-family: 'Bravura'; - src: url(data:application/font-woff2;charset=utf-8;base64,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) format('woff2'); + src: url(data:application/font-woff2;charset=utf-8;base64,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) format('woff2'); font-weight: normal; font-style: normal; } \ No newline at end of file diff --git a/data/Bravura.xml b/data/Bravura.xml index 7ef71dbd76c..6c8403f057e 100644 --- a/data/Bravura.xml +++ b/data/Bravura.xml @@ -809,6 +809,7 @@ + diff --git a/data/Bravura/EBA6.xml b/data/Bravura/EBA6.xml new file mode 100644 index 00000000000..9ff55298b55 --- /dev/null +++ b/data/Bravura/EBA6.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/data/Leipzig.css b/data/Leipzig.css index 0409002b61b..1c5ceaffd16 100644 --- a/data/Leipzig.css +++ b/data/Leipzig.css @@ -1,6 +1,6 @@ @font-face { font-family: 'Leipzig'; - src: url(data:application/font-woff2;charset=utf-8;base64,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) format('woff2'); + src: url(data:application/font-woff2;charset=utf-8;base64,d09GMgABAAAAAKOsAA0AAAABvkwAAKNSAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP0ZGVE0cGh4GVgCTIBEICoaUcITcNAuJXAABNgIkA5MmBCAFgwAHsERbT1xxRLx9UCluB3bHtvNTRyJsJec1HxQdqMF5QCS03Lmz////05LKITZlaYFht+2/EIxgBCN4slyg5tyKuDiJ3V38HDKlZRlng7ZMsxOuQqkUzx/HMsCW7Nu1bjLFsSMX1CEjaQVbVf3RrNCokioZaFQLL8ILXzgVk/IKcek7eMa/cckV5Re9bExAaU/drUsLnkN1xu+9bWUeL6nluFlPDHUhTFhiISPYtDngRTbVdUMiD9TuOrfBfby/WmQ8+JGkJ/HYFvF3tGWA7TojRAYpm9cnVFQXRVb3nmS/KM7w/Nx6fx0sEzbYxojRazZ6RJVEKxaoKFZhBjaKeqJ3Z+SpZ+aZ53lGnXrGxP5egKGKpe466+puXQ/0h9yWykIa/QMnu7fByDIKfFRAnEmUJZ8qmWzn2gRhLMYYLD84b20ZBzhdrEXL5kJMXD23x8wGPoEvOnln5t3u5ZKfJAYVKGGlFS4AF6hif1Hvue8KE5sZR25V1gMFrVgDs4w4486p6YunGn2okYcfRZ9F92DcvIHTg/NyHnUI8TWd54E19zfapCFipRPKrDRCfYR+h0tTKwm/PqfVLTmZqt/OnGJpCD1LBJK+MwoM4Gmuu+xXe+u+2lagtoYMS5gsENjOEpi0bCvkP9VW40pV7iyt2Vc0h3UoJDhuLp/s3iT0Mt87taRkUbpjgZMsx4lTWkDOdUZTWE4P+BNw5nfmlyTLjgsGybLjNOjGTnip5a1t7bsvzu9KACra/e0EzAkFIA3Pb7OXv/n8TyuK8CfGMMHYGsTaLIxaWbG5Uuey++52Xbuo2EX+3ze1/t545kHVLld1SWpDQEC2A06MYe7qcqKBxJ73ZjkPaCY/rd0/6eyf0PawSZIdJ2yScSBsO+5WP4SvFwIREAN/b6rVhd3kYBbUOGh0hprZmpLOSmdskHA5s95F56ILst+vG+zu32iw0Q1QQIPUgE3ODIy0AzSoFQhIs0DDEGpCEuh0cmOMXeNASNylyDUaaI2WZzWz3kTGmuyMs+JG1EaaMy66cOuySzc65yNro0uiCdKLsrskMTZILkvW/2/5zt6bzZzzJn3zaW04J6UZT1MIiVH7Z/eX2RIyhAm1FQdOpUgcDmkhEIcp/kiXdOlRDQsIz7I71e1nvl/TL8DMIJYIAaM/Fkp79z3vIZvWQFNKnU4Mj9hd0ixjr8LLIZu2Fptb63jkDiIEIvD7YSzNMwVT2+a5ZV16a34ffEAlMY0PvgEF3cxZJjNK6ybosfE14yvNCGMWbfk8joSBqG7tvgpNZH5IUrFzAYW5//zB3WEPPwx6kI/EyTi83T4p3GqDQDwsAKnPPyQYm7ZeU0zKdXqYIdj4YqQDp49XtMzmVXs7SkH1ZN86xWdS9uX7tmzta9FdORJ1GsLOEaCVDRG2K45Rfiwg+NUg2WOUNoBALNKRh3oswGbswD7cw1dD80ymxCCJ0io9Gq1Felqv9FbfrCzCkm2UTbEVdspKHsoh2ZGzy7hyqVh72n7mQQXjuJKH2eeHt1f4Ot8R0lgRW+NC8GbyZvLNvpvfbxf/lcW2XgAsIwm5KEYzVr2eEMO4idfGzQUZEx8xS6GMV7MW6io9r9Ank3Usycqtx5bbTnuSO1n/etSSSkO5WPptr31Pk0ITZ3MnH/DB40mvbW8OfsyODfF74Cbd9G5WveoWzr764L7S6Q6dPkgjiNesmyJLuTOTtmrvO6QKxfToHzhWO2xJoZrTFdfQzNptdBG6gI2ts71S5duv6zLsEgZ9H85hCZsAgEfjAbgK1+AxeDKeidfi6/hD+H8IMYkhGWQYAIhOMo0sJHvJSfIM4l2kRpMAQJYSNQgoZQAoydo8cg/iJUpqwa7yoKNhYPKqTHkUVCxsHFw8AJhJNgVqqVSOXAXy5AdAzRQpDgB8oHy0gwELDjwEiPjx9dijxgOAIDAECsPh2wAOWQOSD7dS86PjS6OOipo3H1WqD1cmg/pq1LrhpltuB3TXkvfI++QD8iH5iHxMPiGfjv2sFBlSpUlP6+IPTbcpq6h2Suua266744a7brrnlvvR0DEwExLgkxKREZOQU1BSOeMPADjrnPP+dMFFl1x2xdVSpEqTLkOWTNnznV+58iyiM5gstlcFChWpUGk5l8cXCEVi4hKSUtIy8gqmgHS87dPS0JaVU1PXMQW66KJLLgdAV3kkSZQgPh09A39GAR546K/qAwDqWrJRGlqYmBaOwxMQKDQSg+1NpU5dRgcoy8nBxS1Gi1adOrRrM9oY3bJkypajy1jjjAcAwRAQFNafZ54XpUSxcmWqmFmU5pYcAFCFnnqSnoE/owCBggQzCREqTLgIkaKYWVjZ2Dk4RXOZjsFWVFFSVu1doybNAbAcM2qZodhiW/KVOMnvKt4UZ5+Orp6WvoGRXwxNHHbUMSccd9Ipe9Q1uhckmEmIUGHCRYhkPzKXtezlLHd5NVpQpo+WpvZpTM2NNa6X/vXKa+988917//vhJ73xNgh8CIBvPvnPZ198Va0GADqpM6KXyeZweXyBUFTf0MBoOYfBYnNILo+/k6LvnxN8mkyBhKSUtIysnLyCopJQWUVVrec+vyeKwBCGEyTFe5aKJ4tIj5vbu/sHC+h8iCmXygKoE+vfO7v/VPo86td5F1x0yWVX9pHeYDSZLVab3eF0uT1i9LJP3778GNL1/PhGkEim0pnsz51uLzAeLrenNy/vPpI+H/oGhkbGJqZm5haWIgCEYATFcIKkaIbleEEklkhl8n45eQVFKenNhIyUpCVTskmWZJcckpfklFyS27+IOru0JaUcmpaMgIgQx0/oPSPtvS/Ns3y7zp8l3ta77nlNm+JPUexTN7aiP4VUlDt/dLCRkY3YbJRYjDlBq4loBWZvMds0Nm4Cg2XzQ/hLueqYMI6LlXfFIgDMoA6ZOInYLJEAoEsHlU7EqsgWp6hxKEZZExt2WaNwkx1/PoYdI1YsevYhl9DFEmSq+rAIWEfZcYMToyY/DbnZDbCx6zeBsMbo6LGdQiXMeCAzluyEY/bCaEKKNra0+0wkrAmxMbFiubgXy7CdsOKkYMiwcjKJMmPH5GSLQ6GJWcfirFjExlPA6cIwCuwnuqxwtjD644mdErmbq1fBKzFvsmYLv+grM5LDEiO0/TEp6pP7adeRAyqrRIjNs0QNhy3CEqSAfXwTMRu9/J0r6TMcslngH0u2jfKpz9IK/xdgPrjKl+Sny5oWwDXJKv4YIECc0TSlbQaPXOBJAXB62WiZAXwHg6VSMOrtyHX2X77DTHPTNDsv826CySKHbSTsO5Lxc3snfnEW/k4Fwz/ZrIKpg7dhfarjhkYAkKYheEuREGiZ+OvDorQVQsRx9u+N9hxWlD39ds55QnB+a0WMyHKz/wH6ue+J/9mG/3jE/28qfPhef/ve7XW/LhvD7bsnyKKIemrXpIbDknLe7cWQKiQJjk+j6GjPW+iMOLZfFCHg92TQQh6QeFZSQIOIqpQrAER3CFAogUilCqOum8mAB34dxRBSWvJ8gRSXMmjng6lHHCEVq1qoHwKUjTHiPkPUEJlZnAVsFCpC4qXJxetIdinmHfO05IsHXxOOTne8Ef/mr/8I8VwhTFP/9iUfhVNAKIpYBPt+DA9IQhRB0yELIldxPTUlcBOQBNtttHbujlopQ/b6CXmqd/9rwcd60Vo3VfiWJVs8w8brJDew6vvI1NzDNq+OmK4fHeMzswrJ2IEVCBNtiArTVVCB6FjFigJqd+vq9tXOvcsffXJ9+tCZ83s27zgXbT9+dtvqhdWrO1u9B0eFIDoasRRnzFV6OwhQHqGXbOxFCvm5QcaEm+g0g9RtNHJLpq1TRSurq5DlP9sK13DMskQlyzQQ1Uhc5Abs1EBiW/E2oVAgJ8azifQejU+d/lgULZebN/PGEOnUa4qY70kCCPHEjKnrnmgYwBzOpOMzNUg5tdxBaRQv8CJjG88ArVtYqOuxbbEYCtBlNoETgZwbZZADVzhK0jbo8LqYT/OkRGiV4Om760huXQjr0wVeGzQ+eHVyAHaY2yS+YbHQHQl3YRjuFuHwLu9leShlVal7hhNGOJWXIR9XbGTL/XVsrffns1hXC7IJWeZIIdKWWVKVNKB6HQEdV2LD5pWRnDtmZJrWVptoi60CM8p2SM7A+fSi4Gx0oQsFLMDUsVOJO42xizBu3nOxuRdaZya9IlRNxp7Uiq6QAqfVTBMbqGR0xyBJVSPeppoURk436zU9Xda2NrVw12bVSfCxnB1sOu7ZwuAUOfTuqsGpusI16kyyTNTfg70R+rl7g7jUNoBNVB1N1bBOOs8CJnacKjVErbaQmrdtqZseIidBRIP6JCWZmq431pBYGEPdtdYWYoWov8wE3ye4AAZ9rafz0bOZe2NtYDr8WtqhtsOs29MPiWrmaZeVC5ex7DrDjbaXA7UeqPryiFVaYVUwwQJqawjC2yfva6IeMVIE80QXEK5MXWXO2h6wHjbZAwUCFiWCNoXsfOqQkTvUVI/cNBoEa95g4hmxSFQ/AzvIATUX38TM2Tdimb++F01w8jUZabozVRc6xMvEWU1qYyGi/xyvG6xH60QNg2WOK6Ep9SRV1GYiQWBVPdKL+57nbRtqyaO7Kl2UTJELb45q0YSnnyALj4lOw14kDsC1Xvrt8xWEql5yhMmcPZqZBMY5+/EKL1NbRWzYRjypx7IENXyHaFe1/GnOl6TFy84XYTkV6ndJ0pXEl4/Wybayh3s4aChGYmqipoeQ6F9hEmZQxBKhmkp4/PiXriLROaLz9SofYnzCHikQxaMxJXKPPcYcmMCXorYlkoBM712OXINxbJOLHp1c2U2oNWSsLCfdnFasUmtNcFg7sbeVNM5qMlrXhtxDdNQdThIdBpGYC2qDBmcc8GCGWgWh5aOSqADePV1e5KmQQpB5xGLI0e1p5ailtaw55FZIsIzb0rIoL+iiV9udXipcTR2X0xhXPQcyWmXcklK1g19DowajSc1tDRGNg+1LRLsGZofEXE3V7PbTR/ho2s7kXZVDvR4ehnlq+zdqM4IvvvAWgad3yhQD0/5smXEmpcega4RWYpifKLOIkGlZUGCYLqkQQXSaKMLVqcZtG4wA0iL6kCgWT3TlYnGaHwe9SIUSMkhI4Da5QzhezxtsSFX60Tyam3D7sBPgbGDSZ+jutHvTl3qHtib71NoHNW3PvskIkvNIDqHSMpKayGSgFJnOoBmiZ+r1xlonc+UbDRCdxJev3aYjiDwkD6AXoe2X6oI9G1KkyJN+snr9J8VYPYbV9xUjkVNsZKTU63bRg5sI0ec+KXB0PIKYwa15r9TymhSVULuayG2GtRk72WKsOksh174gbH0kwQ5ILkSaYfGuzhQ/Zu0yK3FFpbhaLSlutFCafCypG/k7ttFQvz4NG14SUwDQJd42HlYvw1kNBJbW0qpShS5uVIubQcpMqQFIWvn/k4vpqjWf+sePmvvYjPd2zLinS3Q2uobYk6rHckyObtvXu5GlWIg0hFy12FQSg+15TaprOUQ72hCRhb+K8EfwzKc7lEAfkWL8VtNcAO+CAgZNjUyzKPMAYCSQSCLyyPXcZwppFRfExAO5mCfVz4ffMYiCZDOAKGwBW3hrutbjd0REtSpCqDRL3LujXapxIWbiRWUyJoyuSUXKxLU9mhURGqRxWZAqQIKSMrqCEgtBzwj2VhVKCBpeB25A9+qqYcGYKDe1C/ZHqTs/Km1R04AznC8H6tKfOz/xShdq19peZhNM5lygX1yDEGgI6W1K6i3HmcLEMaopUPGO4ENXGXhbJlId2mLrIqKjPM7MBh1fjJduHpbg3N7YKBQy44yHm1BQ9N5liY/gnUblHTTXKrLkKp/9KgzZMbqQ14y3uSSsReZiZIxfLnK6fpqxF5tS95TLaDyvOtamP/WMlQIzhr9TZhOC2UXbcs4L2BJX3GTtgqPH5uC3htFCLgbdB+6mm3Y2HOeed8RoDdTe1FK2bXsy/7XmUwvJxTRKswhS2tWj6WNmo2DftdftVMlRtfu+f18mS3pmkLx4IX3ande+enexybKuZkpTFytVubi8r6ZeD09hTPL592UuhxFJ83WZjHaV8flx4nhZpB21mLPqIgQ3NwNe0lW6JOlAeOD1+H6tW4lWG8lmQHI1aWtE2VCH2mbrfSFK/9xFQgQXay3SN9uff070UAN4XV5NtXaY7p+qBzYMuhxLXOZAoMKbSCwRC8gbr10l5qJ6pKhFRKkasAoXZudRbns44/VnDzcl7XozOEnDloX3Cx5zS2qyay3a6KUm6XmzfmHDl/elCFyYCy17BceMt9k2c2NKV3laI/lw28uk6sic9oXExwS1g+gpUe0LPHmyMuLFWTDuF3Spu1bRXdfs/71h5OOnXHJZ+Zjf1hIdU3nhomlBBpkwhudz2F7oKDNcIx0hriq1I8K2+kaxUKpy9h9JPtwgVcsY+ZCVvP7BHeP2andnjxnbHxSMeXuncdR1W9stBjAXqlTUY3ywKX6fj1WMONGGl9YMZc7lc7qPooxdbscWf1mhdvZCkxmbif13xrKKiKtyYW9U+LxokyCu1DZ7nCwuXqiEkvm9Fzoat5dj22BBi5sBCbY8mUMAVbW1JkmQGj0YEFlzW+vqDjSYOJIJTJirjLWmCaUjQ0MJwKI6wNc95vYCfkTxcXCKExmfRcR1NadK2swyEFPiQCeUq8USjMkgXrXetjHRAcRmggVn0CJC/LzvcamnVRiYCHu2OT9K1rJQgigHsxxKrlEcM4fr0V1GrPVnjE2cP5Ix1uZcpd9prE3055LWh8xrMj2RAZWiCVWMlVAhVqjLwtwOd2qIZNDJWtkpw2dH+CPmjteW+tgXBCGtMi4M+jg93QTbhpnF/Y4jBUvNSaJG5rbkiYjQ+CCcQBA9vZj0YmqtJYyYSozf5if8+oJx0G4JaoOx3au7e5zIL0Jeoox3eQxPHQB8YOrguKTBwiiEfMCdwhuA8Y4RW/ARD/RK1bVROLeDaFKrEx0H+2EyetFky1TWD5UjE+KoKsxtQV+9H+8ILPj0BV/jwut75D333KmaslbZx4fOvIrjjXpcDJi2qIcKMMw7CIX91Oe6rsPJG56MbzPDJ3OoHY+fBeZlFvlbyTHJC5QhGnXppxJSiyCadB+otTPozyxSK93AJVpxc+MkpiL7EOMw4L67uN3lAkPKmgdA2hdVg8JITsoiEIVUhW6HESXc5/JxOdhmS/PKZNyyNIJXcBI5DaQ2rljgnLOxPDnJbZzRFmpaR25C/pwOpol7VBb6+cTEEuo6ysQnKyggwkxa0K1NqCSY0qTB3xU5a1VNoT6OCMsXSbXV3ekRFAP5g4EKZ3DmtSadcEnQ0D0Pop4PMZOIbfTijXAXDLeuqmUyqof7UOggwOJM9L4Ig3ncaJ7j90R+GnQkHnV1otE4ID5ZG3Xw+OCMaRRjubVFrSEJqc2pHr3KeDWE24n2LuVqiy4Sb8PM7xLsNz9YEqcBJvi4iKUt7ThGTp1Ix6GJ+gLYw4U2rKtBBC8hoooiIuYI9zTGb1RcyVGxTWpQWGxX6UtAsYpYVVu74yNrdLvgFRAFlfrGcJDq8V3l63wsjA1HbfQ1xhozay/McJb6wjhsahBeDVWifoP9scxwhhmekjFG7RktUH2kcgv3dImT7Kkx7jeuetpo+fLEtcMRM6CuIFrmthM9bCJZbbO2Z0Zbf5rKCzGBRdqolkfNkc5tu86LiEbrmgh4zLGEGGvdJ4n6fY8PmmERhDmU3iBQOyL78jY7wB3iogFnudoNi1KdISXywQqLamBWa8Fl2Tfzb1A/Z1UhTA9lQC2WNM3ILFeON4AUMKgMKx1NKXFWSZbNUPi4L1RywFU60Ub3j4qjUEIIZ67iYMCuNZFtPD4k8sKAPkD3g3nWMc5kdL+iLM0E3J5oZJa/Cr0oe0Ru3rZQ1lX29fEVFU2CFLRV70LJdYZcVcNlttJIKunIxESts8NoO46LvpX36Vat7tCWTdxeacRH5gmnfPHCntZNpuwe0a56yxzi6O7FK1SMPzKRMxOCpbr2nu5OUOOaBkVU6LKN/z7FKtlZEiSXC1a9PFsFcwEbqOb203nLG0dEqTTcCnFpVvfJURWnxcS/Cns7Q4olpPpkWQ5hOTM8GEqoGT2sk1H0QcP4++IETT3I4QSdANWZTsERTZ7tH67lBTzhaSiGE6OdedMgvnZgDnExJLxCv8s3mv97FCEX1+/snbJT5VtGvf62TINFhkbwIqkNzDt0x4KmUkzXkoRqQhf6hlcCcXPgQJ2skaxdvUKIoIYjDx9imuWBhNKxRB8H6Ajw/vh9iJkcW0Tc0d4FAy+rOhp0wgNcF4TeQyFpdTORvsRM4aXw1InjMYI39p1swPHGqfYxemLlTaNbotJp3g6IEdoU7GCIa+aYuTMawczqbpuN1n2j0tI5Vjp44BJGrHavaVVya6rY5Rj6C2LLrShVq+4jVmfjjWv6ZeEqn6GUgM98QA7eSI6iiIPsEdTs5qZmzMCNF7KOBLJXfPtHrFuTf2jZUgx58U05JxlMohMtNoWujkjfjs+HG21ZS6RXJcR4BcRTikr3S71jZNt9R4i6CFAyGQMXGPxMjKfiQ2GwHG01495Ja6ImzkemBMOJWZvfai7PbFH/+8Ihrhso4AwaeHU3H9yAeee2yq3Oh6O2LN0ucaHyl0cP61YYncTe2YjTJ5biGPWVCF19rdupi0pfXisBBQzSZLr23DnwCORllTog+Wg9FAotDVRcOH7Rty9vlVdjgMU32Ljg4eMuFsq4Y+4YJfrMMjokTJEsZwrucQXA2VhlUFfCDlpSiK1WqF/NP6oIlZwwO8ZRO4c1Jub9hZOh6Y9n54KeXsydIhclftVPEPOY3TfQm2BHwd3KMGmTB3zWC0haPqk5K1MwPLIQUiL9YHnmSXcWj1LjE4KbuyndIerPWqDgz3LWJt3oZcSDkKLSmYHdcRrJHhSC+chCUEIvVIttxjqxZfJPN/rx+jEarHfVD9SD1SAduyIQTOM/aTQvnvYvX+H7w2jvEOsUfKLihS6J2hSiTBp/N0ykjWQuxHYFsGlkmCUdOcwtQfZT1ERFL9yoXpAzgfLUeJ2LPCRcWbqoifTGNJ8Yj3oij+/B2aBtQlAVI2dCVENs0rdLeEr0SN1HWmXnWBhCTkXMOs9yyWfcvG30TrzjbI2ydEFENYL3ZZeZyFIWYmxKTZIZJKeSKlpLUAt8DbsTZBEhxpT4J+GDngbeERuOeEcEb8JueGu5PHZhinYA0wtiKiZyqmac9+WjG9G5aB5PbqKXBk2VaSiZeU1lXOADjDJ/y/ZHjHNzvxZv5ymF5G3uIzmRLDjsOqI9ETgslq/RdVDMjnA2+ECgnMRLxOm+6grCPanGxuh7ibll1/uz5yjc6ZvzSQzE1FV7wPKRHPAjHtiYsPwQ4IXxCRPLRLbY3PzkrhQM1RQyYbdsg4ZyJTv/JpDqumRKDBpvuZHsb56Bjt6NdkTqhKiw+UQykoX2NWrz+dgPXHc5szQbCsZJZgC8ItPcPgpWSvPMpOYYrmZYRHOaM3gbrqmmBMrrclFzudcQdd9l4y/vdkfbESsqJ/NFNmXQWcf8g4x4hrNCfIsccRdYiOEoxWdytSHRNy6j5QYc3+oDZrffW1J/+FPSjZWpEWphLzcFD73WiHVWaTOi08c9Bfj3mbDgW6hkJa2kvr3TXxFYgKa9yE4DNKYLVNNf399XWY1Z20dylcBt6WwXomJKh4eYKSfPmJ72p3Fcyi3BQaLws1vZR9mN+alWSTpCao3cBNbPNRn3GwxjZkpioW7tS2pKNvWzMMis/f4a1v6vuFkT/bOBa/9GS2tFKtzJhzJDUAs9A7rGo+kMOIL8dOeitIeH5b52WU6Ayhx1UnAhMYCCmMox3RtzWjJ9pHiPJxcF43Zay2nfa9z7yxvr3WCyKcC/gwojBdOFHlXVG+dNhcRPA3AcTfL4qJ8zlhxLTkYTnuLM3mfV6qzqNMmPEaT1dqDwXtftxJ5IICHJTToL1UJmjSGx2CQiQjX+iKBPVoP2PNFRfkwy1s66EBCIxZYaYkSNJTtaddZh2O8IN18Ea/P7qEo/4mzSdvIUMfBieY7SUjpfbZJ8R4ANutBCtIJZobK6i8gRnfcAIDn0Al5CzHB7C/9ouEJQP4ZYx95GMcRU6AftVAy7dJSwOeN0Q4XRGL+eFgfuQ7oyjagjY1k8lTPuVzHe9yEuZwacOaDNuN/8stxagxYYXoNoexEzXqb1z+B9WuzsyX/xa6bcigY2BTPgabPEHA1uIEZW0JtwfULAwN3Gsf3MPmaxaWzMGY0A/bcOJc9Ylu/xw9xfxmSd6yAlnz7RgLy7H7YywdDCb+BeuN9me1pJl3m2vjUTCUcSF79mVKiGIQpolruksfIDBTl2Pw39Gu8jFrogQooGbqdNDMdGyzNvyUjKBF8Ug0KkVI3o7lkFSGUyahqFPHJ4TGA0xXA8BGkQTnWIjAC/gwEUEBdoWRmLcKY0XyD3cLLbHoEnZW19Td+1hI+Uta2Yfk+ugImFUO0VXoE2ZBnl1V52RZOa7l00QXXniM6eYHTrtJwXrj+NYzX6qVyLdoypj5He9V36Xp09fktE2GKH75vjlaGE4kKAwxswKP0ezliiKTmecrzb1I4mO5gQIL6VOjKHEEJSJrAy8W76cBMwSU5Ed4ge8tUNhrUmyKCID2v0MPTYJ335W/COV2iKPj8PV3N6Th8+ofYoEqOqA9ha6zRJ/rfGeR4+XfomLWO4MsD+L/QIhb5vJS+J/2EW01cpQfWHQUy/4gqMk5VdSxHkMTLpFPk+fQ9TGlHPXgQdkQ97rw/C900U5A6b1y9KJjfTG9Z6qmZV04vJhZTv3F/8ZDqW9Gl+jMAocvmoG86PKO3XrAQFqPwdTTYgdOeDfPeo+l/WdGo2OZe+/v+IMEummuz62QfjjK8hGVJwQlx3lZVF0LkUiHqYYMtS/Deq2vtPc1dT1LI3u/OZn344NzMCY22f1M4vx/dB9JXXvB3KiD0QXT4SS/qiLejxw1vG6Gos4m0puZLjGDom/J6B4d9lp1TgCBkRjSwJWF+KBC6U0Q358BwWwmpGpB8fNjwlEvk65LfwBRJvOZZwea851F8Oc4gnyetIkuu29Opbbi6WgYj5YfliXGPQazEMJSC+8c8JR2mS0DtUaQozF2g+b6oHDoSa0DdVp5n0WpyVlnNuI3JdQ1rBgpgctIpFBpm1Xc3XSSnLXdnBtSG2kCFiEAo777ua+/W3+NtL95DYZTpOlOyHxc2NbAjtn7zxRrtzigM8HS6zswnsuKEkwoudQTE5OQxy7dqus9dpOjzt6YWbLqyLvvQO4EHFyXw9bUYdkXezw+xem7yPLJpB7LPLyK9mpFG8HZGPciQk//CyQvoUlcfPLuzQZ8xf8romJljttZmE2XXE9ngsnTdMFFrgrfXOGzdBbeXnnqGXOcFm5PX5XnaPWWjyjlcO4x/R56NRQCbmbjO9a+pjMoyxyS20jncHGexd6R7ue4QHBM/jY0ORYO0eE/z+sX//jq2903Zcoq5Z1TszcgSLk+cf6D0DC0hSRiyiTKA+FzkNythTziFVIPGGtTOdn4M2SiOyLPN10PXeYb+IDQ9BcMq+59tevIPSIIKGkPWJ3vx2IwslbZjlpli7/Rx3CU8C/d2wXvs8fTq9SW1/QJ5JrRNF1TepbaRjrH8a9+aOGSD1sTFPGqrLGyVqXdCA7gD8Mc2hgItqZcxtF2C9Wpw0iNba5DYSzRAqjBA65bkFxPOsvJAVw8GjJkj5QMbHT8xppkF42ZNaOFpESwMDl7iC7ZknyusbblGreqvILj0EbzKX8/k1gNI1vhAC24XQ5Tl5n2dTffRuuOEstQciuokLkjIfgmcYkfcdkH9aSEwrizW5AGqVmhQDZebecgWzTjRTyHhKURxC7J4WtZFqoK+X6OgJYiHY4SRKFBCnxQ06EM5wv8Sa5aTdZC319ykEp2TZKXe/M2GSs0O+Kg1rflANhX077ZIpmprnZTjy1FTQtPgjo3eSUyHdYvfPI8DBtB1EERZd8u4Tr5QdKOZlXT78+zZLLtUD/IJBN+1IQ6BYwNAcp2CumlmpuSynWD36xHxIaOA5/C/yHcoPrPsH5CyVUwNTI4NXxc5j2GFT2oKHI/+2iHIf7gNF71ReA1klDmgXX7mfiaeI/RBdkWbkAavMI/KlJ/0iOluLbXjO4q48ZW2kN5NvUjZloYTYQmzxEJlsLOcQbk2iXDDy2DpQdz+1fQknLUlqf1ORfkP4zxKRvhzuX1u2XO9hmfvRwNOM26Qr+54K+M/jSrl2beE8sur/BJWEE/bigcKRID2kWpDr2ojG/XPkIMsLlR9Lj2T5OuhJI/zRDZVghfYMB6oUWzMEgWA9soh7/pSiI5RTyFk/4S5FKnNC5tyl1gjUT6bzvYBlGLdJ+BEtkEMsLq7yZUFMdyncUanbtnNWbh6RESw0psMTMG28AmuoDVsQeqhwNYf1HzIcCxzipLyqqGCAK5sJMBucqwepyIkdqg8jU4Q6BjLMlJYDP/rkkUDF8fRESURhYTCVHFL+AD9lUlAGJ6uaTPJPQbUERYRQEPC6pPGQcdaegHlFE9oRusuKVY34N4iDSlx3PZBh5bDF3T7IEComG8Pq5hKlcByEIgkl8xiBVI5g6HeLLPcEwgpzu1LrZUKMQLUtPqQP9pkqLR8MyeHXYwYBx5xfjmoNJh7Emg3ophAkISuE3zSdQY+sKQaacMS6RRxXqnqyxqlyGye0Tgx1Yi2Er56KCRCkOvaHiH9mKPEUDM1yQBFS9Bon/tWUA7dJng5kv7ORJ5C1yieNb41H9ZmkTqgFosD/uNUqLiCia6YnqdUl8ee1Wzgja+ftyxzqvmrWYldTkZCHEm6ognx0BdN8OcO3bfZzFOaYPHnZGTMIeiEMhsMcPy95w7rzUGrisd5Yl5TgmqAtMRA8XyPEW0WYkUE8wvWgrdB1p4bhIcFDDHCR187AKGx7AD5MWp5WGEWU8wExGL2suOokbEUatN8c+mCD2Tgj7EEppxDtbm5pdW1VoEfrgu4F6Wy07rSjnlIsuPhR9i07PogsukHJf+P9k7hML4rKQNFfamEpWzEfx/VFsMhsTHprEKW/X40yUyaZjCcSZh8zonIMPl3EdqOWgbNKhONh4DRLu61NmLbJLKUbl7lNru82YxiQO7D/Tp0os04KNZvVLtaO+oo+/Scqe3OuHS7hBLWy1QBKbUJnPd5spSyjMrC2DKoN+c581UZstLBYkWTmtUy4zCJIGqaKRBYLWOs/IkTNeeinDiBOaiH1gt7Rjva0hvscUvYLRZlG0w26rqr5dMeUf4TDPTj9Lks9xopJGMR5XEDXEkyWEDF1pujNtgGmsosdlKg2aMwEIZUDJQmovuHGbzQZZciH4CPICUQYjlb3kT4b7W7Y1ANyAkLTR06gMsMDsN7G98qkt/qm6okB0UyqqsI454p1PyW99eSm0nA1AUOFCTqfTWPFht8rIBbgBGTF/DRSbeoQGKI32VNKbeo6grwAssXDTbpMAaAQxZta1MY7VqjndwiGOW6MFhUxW3oOlwxP+AcE+zPQpXXSixBBJLHr3Cqv2jN9JaCQFoY9rHMVAjz0pOEnoMiCP4CeqI2iXpHENfbRjIDQOfzQr5dwGJrK1VwB5c3ljIMZ7iOH3+4TDFRTamt5uNBRyIW35DXKCnOftl+GkdaLh0oxRXvuQZ9krUM7oaJEX3lJjKEsHUPx430WZllFAYUacSmlSpMDiCZJC6yKez8qlEnRj6tVRFnrq6qOuuomSprhd+IOUYqvwB7GGQj7jprhRhuF1Kxob+0w4jc0R1gIpuzQHuIaeu8AFdQQQj+qt9pN47FidoX5Qpa5l3oivkJo7b0tuwQjQntC5QVyE9+OGBED1OYU0QyF3O4mO5ATyihJLHQxXDQUveiKdZ2DBP9IwTYf8MN0//oej/wYh9mnvt6laxJpzPvKPdSV5rcHRN4Jol5A+23Wv5+iDXxROOrhCZ8vZ3D1SoKP9ZtkoCbdV+5ECY7OEE+UyJRpCHUmfwyLDmL7nqbSWSa/hztlrecu8VtPLQFkuJSZZMaggqRA7bhANACIGwXIOtrBmmfoklQYaXpPYhFHVgrZ1ZMiVZHe4kapGhEWi+bH1xmeS01bJkVdlOL0R85WfY9xq4pPl/dIal4uxZxmABhYkoZMLNcHRBtYkOU5DICKyCUELkdL8nTMst6EQJbKBcqOfDnRBVsHrzO/1Xp6RF8rcFmEOgPyrgKWF11hXQlGqHUr4fmnVY7oTeKT2tty0FQ21+1KwSWvcV5W0NSxaRqD5rzcfk8Wm/6ioEsXn3xFKRQG7uj87Y4nXn2pGMasOzA9JLh73e3h+czbOnsvdePe7OqBMJbMoBXQ1XQ0Pn4DlQyRcjfkGw39oOEJmylN+DM0iN7xXArZ+UmePqiPny2rEzdYZzTuwGxm8xOs4yNPCNSZKn93mBDhnPfcs5yBhGXgL7uXrvm6nqkTFFTBHZHQ4YY+tddhISNLu5PVTUFQVL8mywOPF/4QJDncXneodNoJsBrCGdQXxaUyuGy7Isun8clNTQANi7UQ9annXJLCm4PCtYVyObfmkOsdKYpZi6dqnM1L7/F7rdyiSlHoGvjzwoU+XUiZPKf0AEcVHgCAziOAG7zR9ieJPoj6plGIuuc2pRE8I4yCVHjkVauuXjWU2LrS7iQEbqrRk7p2yNBZoame6Rr709uNriPo8FgwMTNMEPMhGf856Pg6I9ps1UIt23Z4uc8ApF22Oc24slhn3uyBiwJQ3ExbbLRe03zqnBlYeUPuc7zw1PKVJ9+FNH8pGzSRJeeQc78z8nejMCnbEBkGWJc1JRG9EF4BlKozM1SW3KtJ6IJgfPzl072UGmpJPGqktdrXeMB+lGx6RhIpqIdA3uZdBTHP3VtIZH37kHlQf+aUf6GUSYIcHSr0HtGVRh0PplaFonXGl2wQuUat/T6d9Tqfn1rf+ZAlnwYGRnO8ovgbGhjgMQ1/m8NKvzmQwqHnuvL7Tnw2NcfCulCWp+Pqqq7WkOk1Dt2dJzpTIxgNmtih1GaUPQnZLDJr4Uq/CjrcI74r6UTYLBvMtF+2wVNVNKtHAF26M4N9psLF1MkU6PuuqzaVTc1zwFAC36me8cQ9XHcL3o6b+UIKjDxUzuXliSDIBX5qj9tQ0s91JOjPF0TB3Ppn4ZQ5i87aAWV2qizY17E2b9Oh1jpAPrpJ5dPmGNIzvqpyyUOzWqcPv/pKH9SwpE5uxqCytmHuVKIrkcpyu1Wq82R9XxofyLTReTP3sfIZmhWAZhJf7c1HV56jdDyTEZb7t0XrMHfMb7puauc5x7eQ1GpuU523P9wxUw1e31wN+HhYX1gn7rOWelB0W4Qsg7uuUj0vsF593wGME92UICjxitPc9waSGhAb2nGmaWAaPyK/BDkL3EcKgkWRUAE4ty+8QulIXgRTsUK0DQhO2ZaXOtHjrrUQhgQv2566hFtsP8kLHaGaiZ6LGPecNERDcVdfwhEpOCbV//gS2ZPS7Y/IatR1RNNEDyj/idoYzv27NXHhy4DRiE+EAZM1jPgyy0riC/85nfXdIVRH0RNhJnIO7OwZD2epuYBQaX+OQcF6fmAb8/UF1t8WcBG5RK27g9zK4Tv/6SndhQA5JVfhuNe9qdDtYhKGCx/e5MJGOGK8vgDnJ/ZsA0eaHIWY972XJx3JPYlw35Z9+GFaQ3oOuZq0r1KPWWrfSvQb3EhceuEjE4LHDZho45ibU7ST5bMLROMR/DvHv9yBG4pcRGI+LKNuxe5hovsG5oIs3IUubqrTvll5z24ba/I2zbJ3bnVwJrvV0ani9thTgcMDYOs6v92mJ+0NVS8Rt63pKotpYLtydPe6J8iktG1bWvcHywGQpJKQN95zMQ4oWD90uiYre96Tx1dXdxB1ecIDKE1rhJDUmOJzcKsj+NzsSzCsr07KUa26fT7bsiy/FkwqCTqHEyv79upfxH8F8By1LSu/lGSzH0frtl2VK5NFGZ4NnW6cZvcqDhsXRRuSSfH7Am3aFhc+oOQhMEGy7Ux5p06eAdPxpN9JiKaTxmf8ImIhoYtVyyTRSPYSr6wdX++zLiAEiVH5KTs2VhKNCvppVzy8ik/18TDdq2qdV0ekPucg7zi34M65NtvV7bDb+ocQdZ9vme8Jg0NKNTYKyZhTCLMA6Scu7WpFO6oXPold/hCWxVDqheFMIYEEln8z+QYosv+FplYHUlPNTSsNVRBQ4I1CMKM6BfNNBrNsskWbNyoe+d6+7x/84AcHb5F9dF/0vYPtM+2xw/U6z0brtSAcb8Y6xjPMyho3PQ4eJTsHFw8aKtPYXdEkFiJsr8ykVaL7TKq4KK/Va2TcWm7kDE+Q7qyvO+hsy4FjVJx4MUUBIwcnBwj5mLL4RmkVXhA66KwGdIlDUYYfmflSb5TE7bM4veBUR3SDSWRonXBUIkkD8Ty/AspwFEUlYFEJCBBFuT2tND5qWRo0NmUG1YDupHJ0zV2h6oJjKWCmUY0G7tZnG9caXjiKSH76UBxltLG548984ReZ6lBSPHcv2DV18NB9JRStCT2rbIhIMZ9kXxa/3inWMmTZ44qUFEcSHlNuScoouzSnDV8Ll/adw0NuQ7fvGZuCDeTnnvYi6DfQ2zPtk2E4M65v6EyBI7XbDSXZkw8M/yiEzJymcN+EqCuE0/q7631NV8VKUsMnVFi/Ra5JSaUpXKTyuxiUQ0XAMQAoMKxxCEUnqp4h8bTkHqihZCLXey3uLQDu6nUmcRrw+9RnSZi835CXTOOKMq9KJYFxTYwFUmQLbwKy4lwqsOInyhJIZLxXW6l9aRZAZnzlxq26B83YRnN1bd1gOQvvF1sgNt2GZC35wKgeK1ox3x13BIkFIBr+3J5sye4xxh2Je8GQ0Nffa0C+2bcnNC80bAhVo5NLpY4xwcPESOWyjcNnhOJxrS60P2Zce1JrRlYqJvl2dGZf6ql7FrGjAeX+h/aPv/397ypmCFxpef5mHW8UyPxc3c/Vop1YTaIiHGh5d/hTobQZw3Zab/2hnZXnu8i4vIhDbxWLtPboHRggapCCqjNTw6llwQegZzlINmPHkx75Z5FV83vwCYZO/MetxfLdMsgQSCEWjSSF8HE7SfJthuquzGB/k+8pV5RjB3+rg0ZI2/9w3vh55MRNLNOfkLA8fUrcWCgioyynn0es5BQZmkkxbWocDSUYHCrk6t14QlnqwmGFGl9RIdc7lFu0pAdxangyLfQTjvctRpR98DZ7FnMM+r0tU430inivywfAN0Yr+4ONCNuDbnNTfrWZw4sq7Ninn1QG85iqpdgQrPC9Us62owOfat2nREdzAznEpvuEWjY9Jtwu5kLZb6UQJkRS5VQBTx7tl7i3hvpdyx+YKI/7GNf0cZmGEt6ETFiVQYCeJzVeh5ERmfC3d5nynprI6cU5MySRN+15jXpngiY5kzEfUjMjNc0W3ujGQl4O1HBSl9LXiDP624iumauXL9nJYtnpSwYLbXLFua5oN+uPM7zKjTZ2BC8CHCcChMhHOjkB0TtBZmfi6SUjwvj0jqDrlSNDzezR1vQvs3xQSrl2bmkBHmUP4PKNfk9QLzirTr40IbWD1zGUoG5cJVqHmhXVU5oZax/JQrd/wqSilSm54tqG3N+pdZ7GkyaGXHjWZWq+2Rt7Z/F1ErzeEYmdy1RrlcSR4PHXCD1ca13Cy+10wZdEVdXi6dQRT6oJxHNVZdedxCi8vs7QzoRfyXENnzvq/9WwbH0Y6QJF8BTrxc92pgehtQ/LpHHKJB+9/3aS4JHgrw0j4s45cdR/bNi/I++aMIgciMkhMqH3p8VPDLuQYlB450xk3PSeljFP8cOaxxaCmo00YOIREzL2oeDHbbzBF1IeqHuHSpBxQkVDv9QAh3wh5B0FXtQ/JApmsR/TKXK6OW22Ofneu+/X7b5RNxaUD9LAHRDcwSuHcsu7/3LLHujrh7+UWzL8FcDdCQDcf6oXGHWS0xqxJCW/N5+GEriVZfmflFn/e8PY8rrvzJsSOy5dDbc6fsRm627xfZNSXD+J6ZXXslcix0nNwqoHuApo+cqinGSFaDaX/GDVpRa5UUabv2W7/8tjk3Hp3Lf7dWt2wNtyreTugXnDRaoHQ7Qo/KFCtIgMpmQsHkxu8PUCvOegxFl4AAXaco6gukqI69f2DUF8MweGdK9Url5bbhAK1AqM/5LWnG9MfXJyg29zNQhuU4ABIFCaRa/IIvnRLwO6xAjozIscD5Kff6hQGK/H07ztg2IQMFpFeOCam6SidT8tjQPiiPvsNk7EErR3y60Wh9hpGHDx7dCR6zNSkmH5S5ONXIhJA/w05LdHmIe+4nFEbpm77hh0R3xdrErIW4NWxhhDg+Y2fLDJp78zBJJJpCHk4Vd8ZP0ekfVb67eW1we4eeIIzL5709a9LLZHr0egrtPxqjS978IgDVn8Drd0dJ7GzEBNbfY6LbN9AslMOWJ9AKtbE1VePi1Pl3IYsA5Y/A3jm4ycPywkLr4RgtXP2ixNegNoCdKP2NsHjwpaW4YbyPJkKqNuN+c62lT906E9S+P1/pYWhOQGa9AogAYM5fdAfe4RbNlBtKbUEtoWi4uARrAnFIpJJjPd06ZID252fDGSYZxnxLT98YYhere5NiCm3SyUN6BKoHw/01qLfeOsKSTqPesOVhHIEi223s79lalBmLhbOU9zg3pKtKJhyymxu/Qh75N2CfayucJ/h5oIEi8QtbywOQtWcmcsByqReNJNR3WIb3YHtMusI3C9UA7v9Ewj1E81BdMDcMI9DpWw8yOTLF923GacPRvIEVbdZ5u1keD8XWgibwmqlFaWBikcGcEjuggU18w5osWM0tzsK2Sidh0SacnVNxvhmnFW2OBlmBFJaL0k55Ltdlp5fQ9aFe0roE0gAcbpDtkgUW1V1gTUm0O4UHxCHsfswyXQ1o8kBpe/HOZS9luaxwiMqO41d45DlR4ZE9A1b0CXucn1hXD3VLnNUZTdM3mgW2U/t7+ZrS0KVqIZvLXBG/c7CrheI6wyCRFf5ByMsw3AIP5UIwrDXaXCWiWWjAE2z6sLPaGnKwmEI/Y+C/Vw9n5dYBWvpTY0Z44bJmKqOwCp0jK1hVHxhzT/BjHyAv82fYcGWo/HdE+Jj8V1qx7NS66dTkxMnGRitUnVirV6DhlHyl8JCE5BBnQoarAw+6h0nbOxvsSrc/HHdHJ1K79kXHAAo1buDEGbfSO8B62ChgZ1P84C26IMFeZD5JJ5lqvzxvcDK95z+PrkPYPl9fLPvkB7hIjh4D2NSrM8JZUDOm+scyg4srmTlHZixGFBTV/lQs3bXIUpWkGQfD8ufuF1N/tr/c10di/372XpuOiyA4jisPIcy3hvnSxiwXmPGACm1IG9M6YY8pOmecAJtZrjfrIMEPvWd/6uImAZIvpSqIP4y6EHeGs3n1MrxIMYuWpQZ8OLZlftjIZ7exmtrZcwBL7ItWZQzFJhG2MXq44682NJYlcQtHjsRP10UX+wLUmlqbb4L0nK5kJygSCNNkSx+3NmeXj4jzYcBs8XmmSCnP9snetKfaZx4lFcWqA3GyuuuDnI7iyOnPm/exprEEpjLYty5Dhqovkj9l8gg60msvwa7Cfe4K3lIfc6uetRoTqzEYm7DjWYn0N5BS0sIYAx52bS9g1nLZCfvpTdWUHw85I1xQ4MdqwKleQctWcQp0rGPlB0UWWxI05zLz5oSRU0CsxP+UZzgrN2kwhPTUYa4bloy0khTwMX0QqHqaeT8Z45Xm3guZTI3CoxXeLaD68d9IlgLPk4KHl/ApP4NnEE1VkBZNvH5rULTWoHSYGQPBWWVRCgS52ytLx87iSzthSkAWRCeVxRJht0HaQHrkDOILxVggk3B3RzBqOqgwz8JTeygVGfJzH1H+Ulak0a6M5/yC8Qt5DMox/0OFiuOxWoNoBK0Vl2mnGuoLZjyODAravdg5qt9d64/ZzT2bY7hjxIAwjeAgQT7J3VM0xR6DTWzuJtUpnKUiG8AhjQZFlzfj61jcsbHplxZPDRI3eXN9JNj2PJ1bMDs3QnOBPQHFleib5Ke6GAabtNPJPezL203KDt01Hvk5wA0fpys+ZAG7RMc6OdX0Ge1nycgSM12zaMYU31pd6hNJodhop7/emhMrzRlThUXz5nnKq/n9qZpKWB2dQ01JJp9ZV1up5UWmrCmqSUal6BJpsuLcNw2y3wv1y5Ii9soOWRGwxEB4gHlbX9XOr4BGh+YUKFbsU63UIrxCyYSH51EbQPKroILU13TK15kLh12+8heslNuimMg859qYq87ylce4qPZxis9gN2fAQiNrrj1vLGhpNlolTnPHt6UsZffC/3pnwHH1I4G5cpMNAU+rwjT6+RK9k2OL1vLEk0j4P66aw7NQBzB9n+ghqN6m/rOnaUWu/zPhyys+WHwyJl8MhGjGW1SWKb0Y/lEhR4YUx9hvOlmhwdvTbJ/WiYtNQHPkUcRK8aEWj+kyBqas/UZGvliqBIhUiqTJTwoWLHZBsC81MVkWufEDpGn+BWsEqcZywGT587Iw6QcustYffJ2EHnviRR39dpbe6NZFRsKsLmS03x5WAnhrOlmKXd9K65R6s1AyrZ77/Ky3Bf5ux2fDRPf8Zdh4Jk6SU800uXPCOrbvI5KmNtvcedp+ZJbmrcrofj/p5VtWX1ovsp6KrcqW3Xr0JehuBikSDhdaE6YqCaK8beXYfQ4XGWDwTlpwMD6v6W1DrlIrZn3dpB4MYg55khcKbkPoW641y8mvTeXBo2TD3pdS+CMu2TyWqAUbl6a12OFakGtKwCvOy1S4jGam60d7b2JeIfsTVKxrMO6rwNVffalpay15hhIFjVeoq16otdDeBcGyAn980WFrvRK6kNG72EjPMt3+/IMtF6C8zsneIYKcHJqhgeGCCtRG89JUnNpIl1KveMVK8z9I73M8tRrKoK0wRLBaWYQPa/Pmperws8At73DrLRFBM2OJDiDWeT0Vq6D0Sek9DuaBO3rQC2PSMUI4YPD1FxL7ojJlWbiANzAhy2LaeKqHi58REJPskdopeg3tI7awd3fPkTDgtRT80bHE5jSi0EwdWsdxphW0xO1pR8rg086x0T3dxySdS6NZjcI5Ta7qhKvyMZTnW6OYD68ez5JfBJ9VGAR1GXoIeg3mrkRZWjtdoWBzS1e3ILXVSqQcdN7en/foHgupPLfa31VBUzM5cmdsXwWuJzD5E1KpXyElSTtJKzR5dNbt3BRHM9wnYc7jMhSHXk47/n6UVEXeGKauHQH4fKXMjcDhdTIb80L+I+nRCDON/RR68m7xX7MEOmcU9Svz9RYL79lFTLJ0asPH/8Pjv8HIzZwLSh/dNnOHaFmrh7zZsGlh2E5qkVokv257ewEdlfEw2wa7jNuf5cBb+4CPTH4cAEuPVjLK2D6gjn8IlPwDFIS33VC2DY06dN4AEyRZeu1CUodOz3e9JDcpOmhy6EHwB3ib5pNEVF6CUIjsj2EM+m33G+wQ6uBX+4sMxfaez0IgYooh6nRcc5RYqJXK2fDmgD8gLiwWJFbBB9+HQenLYG3ULEd4QjtIZbFMPgCXarECmBnJ15xnqSU7E2EE7p28jZVW5BYffIoA9748+xmKokqYqoErVvZiVo5680+O85GwImgfuzs6OhhbRZosMFXA3K0fADOHuEZ+Qlt8ytlEeJGrDhRvJt7DpgOe9hL1cGQw/3JX6C8Z9oApiZiQK4x9Ezx/lC6JcUwsOEkfpwHmxQoW/JRyTTCoWhCoiBT2qDJRNPlcN9MDTxlOi3kyGpDsknVk3jxkIVkjNld7ZYHOl45BMdEUltaGdSNbxPntHkwO6Bjw5nQPELUCClPk9lmBETn5vQBD5sUx4byyjFnf/RxNJXTsOUk0BTl2lBW5/WVJuiijKn/JbnO3DUxGEOauNhr8dB+RoD5eOpfIx9fHxDnkyt8NR9RdhDEeMHPxPqiag9JA/by50cLFcdxRz64tRXiC9rtRU/4/ZqudGF+16EpRqszHF/wZZ208tsrS/Fg7+wrKIFLmu6DS70SfevhsIl3nl/JdtLYSN6cso5fBuUN1YLLm4W5UL8gmDoR+/Sot/h4mJwERKnuCFU7XA7vl2MS96AVaLUisxVpj77KqRt0Sq+nm9renlljUQOlgJjaIVhBPUlciYu/Bh5XuNDFcYaUIUiQxoeLtTiqvrBv5FXuBvvxWWOP5ePxtRWOsO9LtntH87pmFXJDAob1ZTp/1FjnlybUggefwUfkib0j2pon5qV3ragtLx7/qavMlRAcWZzU69LUFmKM1wfRrNjcoDti1x+eI/8q2f81uof46fJd0nkYPR+2tgiua+ce31ihycuAWXU5GuNYlZGRFhaw/WzVdSQBAqPnJTWkJzKeoas65UmNQRkqxvgTEqtGudYLQtiROdzmZZruPNm8OcXd4VNX9nKeB8X4a97deGnT8mwPtE8WUuTJgkl3lwebjndbpcvkXVPk9u+BqvJMbHDzpnX2bwhHuuyOnhUOKDHRzhNM0lTT06KGfUgpdC9YU352K6HIaoQqSVE+kEunSPn/QFWKQKaxAimVrWHxlKojTOoQ07ExKUud0WWwz06N8PsseqVdwT8qUL0oMMynDXa3zsxwDcgDvCyRWN4XKVN4xNhFsUEFsqCksvou8MjEqxBzsZMuyklSJ1MixGJy+fyC+yCYKM53i5XQjZLdHYm+cwSogLyxnSr1hBX1eu9ZHyLYqki+6/Dk+bfbDm8ukEq1Hd+2NNMDIQwFRmFd/CxWfy21O12JMzPireowZGrccRg7ITwu4Ff1/swik7m8ntfcMRn2CEZLWPMPNUYDycsW6WIztSeNVjUoVVuF42tx0+49o1vsofJdGapsycZTKv28RXxI3XKOo5Abgm6Ez6fj186KUHDT739PtoPbptxPFIWUlSU7RstnsuzLOHXdQykuz12sQQc700Z7Yw0T7HnJBY7xjY6hgYY7dsy7ikNFUeVZm8qa8L4SeUq2E97954EqrBRDZn+7zXmydUphWD7R82p+Rtdue7Jds6aG7UaN4i3v17jI9Si8u8HIg/xexoK/OOLD1DPzhukSXJLctJB4t6997eG5mZIczNCt97fuzdRnF6UkyuhDfoJi+P9C4qWYw/R9PsuVILDZ81rO4jXuGtvrOHYJ7tzXRvnn9LgfnnZ9rINjBarDYQESTa2SubBxbtTolLgu1UEypX0cquODNz5YRjGK78Wtb1s83suHhYzngYlITD62Yvb9MDgy05dIo/OO6VEOKJUl/6ygFjvmBnP5/Yk+53SvNSc+gZ65j6fEcfzwYFYy1+XVCIhIuapeUcRl5hxCf0oNac4O0Ps2bO2Jf0DeMvaPR5xWl5uOu5HsRA3fEXaBtBGC5rB8L38EdyfotqkiqsU9MRrY/0NJ4wcN7WqhemTsbYnMihb72lOz91y02VLDC1Lc8gy+FXj/BM9QmWOuiguQVCcGJg8dKpZuOctIf3j4ujJGRXj40Sm9hWSfIn2ptTyGcuPRegNweMpQ5fKGHCujOp2Ea1eqbEHajgJPE4ZQngfz/2MIUUGvMwlBKeLkg0XeSE8tI7aEKIpVWbDpSOEl/wSf0GMFWLU+TGSFJiJsCzRLBhsKM5pA5LGmERlgtFkY6be8rnHgWk1wkxyXYLE4TIFOsMS4cHs9YsJ6Tl1irD1cr/oQyWKhgDsNDHZmxLLPsDfrJjoigqylcc35CWkuVoVmbhA3BdhY7QZ7P/A/KuhtqM6sYTLEjI0aZYIDGYbPYp7osiCZeuLIkuy5TLNmGmM/sqaqnlTBxRWItF55FsZK4NniwnDF1tR0ZslWMi98oQQ3BhEblGfFI6hoVT4prTstTqazPJr1hgao82BaKCzL+PkbqzliUS2rSI6OwFBd8vZRUnNbBJ2KY2Un0lQ835oVlI4PuImvWuiiGUIK6bNp+LrNYc/LosDM30e5EGhn72kF+AbZMI3Teusp3wD0h1Ro4q/WJqSqX2H+LsQOcu7Y621RnbukffYYS+ELnY2i2nrOtoHELTRmTJdqtphS05hcp/LfvehGIkvEvHK8x2mJlkRGaQ+d+UJK1CuTcGDfyvfJaSlrlBuVhLSGjq0fO7khozcrfdmVAeKPyD2F1X9bc9iFBnE402QUoKrnoLT3MAcylci1GkcRs5Rju1qsJifj5Bn0S78QcaOcK5GDO4nNVW0GqclKuIDTTbgmKWnPnkk1M9/Ofa0RFk2+IlbF/FgmkZ1ZL+fI+STtyufHjjnSsQwPXi6ra71N0XBFRIX1+oQLI/3mZeh3ywympHcqJdGj15u49ld/cu0FCgWHq33Q4/lNoUq8XwsZ1gwTpbLQDBS9Qw2Bqt5KYMDhG1NWLwIUkJg2SMIWSexfGwZQngez+WehiM5HGlWczLB4cTYti6iouqdKMRACLgfEbBxhfCsyZHBDRBiK42lrZaed+Pp+hLPHEkKERKsACiAFBISLR7q6TI1UbBPLH/D43zT8ZifAILR70E2dSmnUYSUrKOZhCltN0EbJWgM3Xc1kymaL2RcUXjgSP2/m0dbS4cdcMMkpE5Pm9yDMHkKbcS/yeicb8hyto51NxJdOyTDFJ523en8QK22zqde8ZA2WhGvqGVlxN89N2bZyIyb3GXO9vcvbx5P8EtYYW3kK2AI4oUqduObkJc7l7UowMJVL+Mx/vQWq5UtjD7ngim/bKauO5RzaP1IzsGl1IWxzKXUBVuzt23clrt1M3Vt7sZY5iZwkEf7bRqTST3Qae6k7OykAXpdtkowvSbEpDqM+C8joZfhqJbzjwzufyND6qDhVBNgVW26MCJc/LA4jN3KqMiffFK168NBp+y8pygKF/3Ia7wutSE2rsShOnPAOWHpAdOgDWNeRjIsi69UR0zQg8TXwTGusH7lrDBnbPC9pHv88gxfrjwYCpajN9zlrMLGpIzMe1RleXfZCK9lVZGw5gUeo32jwz8VYAAu8s4D/pVbX8esFoN/foq9Tz5aAUBlqJZlOtf6bFl1tnSTzsaxYZwuMbteEZ9Trh9f7hdokVmdGVa3FjyZg8P9iou31eHP/qctON4bP84sm/ihfsUOu8zitEvGgKFJt74KPKaYgopoZmMC8a4Fnqz/L7W4s3GcS5otTiVNE+hAOHseGJpEGzcGGkiFabKzQprtGtfZWJz6g6zDlrsJxCl5zIKKGJPA8xWMnHxQ225SMJaMnM6r6PXQXWJkXt6t30IcBvaRJ6jMRn8JeWGEjUvHcV+ptNTHO4y42C/kqBxdONexZkWsXejalxZWOWvgC0gZSmrnRbn76irGDZ485R2tiTE285KWBWfaPg2ZOpw+qpyDd9O8tVwXO3/U8lUa5VulZL2QF50ZdBlUyzLvwlUfzFCe1jJJ9O9Se7myiyKIGrWqOjzBypm5yZ2BP/Suo1BRF4F3TTh0eyNS+3xRUQbsA5ewICk81nijr5yz5uF7WkNBhgyMdiWu6dkfnMcerMZc/FDsFCvvLRE/RKw6Jq93c+XBuBRFPDepFvTW64KPEpLPWo6xI6Ubqwy7W99HjcAwNH5jmUSde7Ou+0DhHES/rpl7ZXWKGtsjo/B0pWG49WMUsAd6+S7zClplaqYKPra8NMrCD6Rq+Ow83c0grplN3jvj2TG8TfzQctz++KO46P0EuP7CS71d+q8m3QVu2d4yKn1RKpfsV/U0+Ax3VcQKPyl7eAtvNyDujjxeic943AOh1JfmbJyShGqqf3q0lO1mOq8ypLt9emU1pKxk4YlqHS/hr4+FU3m2G8dwic9HHpRqyLYirdGGeeCZxnaMjmuiHh4JPzDHh/Opy/9RGty/m2vcP4T3/BTx6zM32eo8maNnN4KuoFRkrB1/h1vAlP4mzGfukcqi78vr30XQkLu8exZ/2F2DK3+rmAbt8R9FJvbDjE45WQ4P3OG1nXAgX/434tgVg3XPDH3/t8vI0C5e3/AxwvpxF6MO7zbyzV7TDUODT3qW8MufXCEnvWo+PiVSeK1bN7zpcBzHF6x3SNcpsvLnOuTrVYk+jik1thDRFIOsmp9uEgATtR9vu3KFEV8Lzgel0pxMKr5ibyqZv/yyJ2iHM3igdjJYH6R7rPFtcojGjmHOGS4+UNxM/GRj+2rM36dLfxXgOp96gdWT8fksnwjn3f2tPuoseKwZb74xg67p14gEHNyPeNmXYJUj3x7mkY4Sq6LD/QhRyWyDguC1o888RTiOnT1+qtRzovSA6RcCmRSL/24CNplCvTXTVkMpUFLEiEEA1lUR9t51hZq6NJXy6IrnZK+99yJurNlapF9WYs9LqIEZ8xLjkJ7NIDXVSozJ6GPglg/ghgf7jyJsepTs2l0p1Wq9HoF32CJzxLBlkhkmNHIrUnClAZeshmdKnUu5cmxLhtS/dyIYcJj0OPOc7JTf95YThBn6eNWX5Z6ZkkyKMMvZgZa0AP8UEw0Xr18WkZLywY6PtQv8/hN75yyl0MTXXeBdUOTlwxon7N4CUakiEZ79UxrVnr0Hz517k4Kv/HflZqaig9GNZtQlzX5MzNgYoowengwGQPgnucXHRx76rXESWdm37vJKN0uqdWoD/ew6VWCmFD2odEJgugc9eECngsM8SpVQSGukRIOU+vMtFu0x0Tklo3uoPM3fZDDR4Yv3aWtWJAcmWdkWLNdiwvUFxDasrIt8cClo3ZiT0RSxU2KI8uRHyDeIbP501jE6wpBYZQGrN8iasPpfvuqF7wplD2kuXy7GB2CG5w4sEzeFh4dcRQShfnDBYy3dlM9cFiLgLGVDiMHG8uteLNjPfC7sJ6HguaQlynd5/vul/mwmtvpzFTVnuYzZyZQcrbw2SUhvA8yw8QuwgrkjF3ulJJeDzmnPndxS6LQlho1bcBpNc9rz2giMFsobwDLp7Xl9eJoNmGEdM+0pkkaUszNvv3BliB3OzCuPea6fdo8XXDXmNzx0qVD5jXiHnRjIduwXLgh/jW3YtigjcWAu8jYAgYFX5roNkjlbQWws9Dp4kuUuEDpw2ocAjLoAaTm4OkeW+wm4ChUUgK1zJG7D3CuBgJJOMVIpA4Nk+fQOKsUo66MMDlDJJ3dQyCd3iAcGQfaQHELr7aacy4OmO5o/Q5XO/olTjn5HqeJI5t1d6OEGAXrTgNupF2c3uE1cem33zZtEA6Mee3FfdSd8AqwoLo1aKq7kpY1RZMao5OFPxNzh/pYFOHn8GpYPSu7QumXTQRJS3URmh12l7yK+MLUcOjAHus8a22qUrubW/YhFHkwc10b4kB0eNRwdd5WoyjM7TkYNO+IuIvirdqWr9o6XyPL5mZ6fuVD9mSXIpGyybSzZMHfNauA1mnXry+632Ok7qN3TUabonBiql05SPXOpe+UKPinetYCaUhW8XGZqFAu2CZionkpVWwwqvox4673xq+atMogXLqHLvRgbTo4+Ia/XYuIJF0bz5jCY4PA2lgDnYTmT4+dvygmscNNhpMLpyJnXr8dX/JR58eEyynNT2im+IElMSRHgZ+bdhF/i3AnyoSuL6gTY2vyd7Gh/Yg8JK8efjGyby/iVjYt6YhVNESAkFW4/yhahYgfCmbewYGsT2WOStmca6c3D2BGcThelXNj5ZhV2+gy2IP2Q+NIaNQMTRC9T6UoiALMnBUZnGkirsiHJ8ufiAutYUtHQ/klkvHAm4ramLbcDFef7N4JXHG0qotxLuvbWSgu5YGAvBWH+ipoKIN5y4ROLtPdVmT0rxZ4wo5vhVSLk8vuX0bD1DU4O32v0GLqwsND5F5LV+hRKqdARmKVnSPrPYt/ztz9duGghib+9nIHk4qc2asQjZ/UQRfbKDZPG/jmTQ0to7WOh0weesgmEDnNgpMcUf8WsTPIz2CLTmAi+9Me8emyUYOr/R+OkiROZrGAvoXrRwIPvTC+9fCMX29eK5/taCS+/57WCG++pqRTi4pfI6Q7/ETf9HoObk3FW2QX79TrA5R4AkxgvvJhnabix2QOPXGzYCHTyjaHYUAN9kMG8wdYaYkE6dO9SH+VWQilJ3QvJnqMTZ483z7WRdb6FsrVr17H/OMVh3D3QQvu5XUzsmkXj5sPW4PxZ7W65iPaYSV9HFTjTc50MAadZbfT7ryUwMyKSHJLFnly8MmXWlWNE00rlRIFyAVXqFwxwSTkJfDZC7GtF8tuf3uCq8IwLS1ha97lvvKg6y8pV+kRAEZu3Bm3MiHB3OgrK/Bxzzil0Fq5605EoGrY0Y99MnHk23rfqtE9o+Tr33eACVsT43qNYp4vstfUvoBCi3+GKeNQFU0nS9TYKAfRW4989amukwTDhbnG2M+wEPvvv2raeu8rrx3je8qwBj2eUBLgZTp5IIAtfHq8kDw3RLxmwHQ04ybSU7OQL6n7mqOWsVongkt1dPphO+uudjH9WeNZPgfqTjHuJaJ2Gaxo3jobfBhGNC4WxxKAc5SI6QM1NSjKTveXG3GTx1LPec+5ssy8NNEY7A4S3hJQFVOGkCV6MPDat+8bKQ5P+VE+/Fy2J/6yJyJwnltdIKLup/MryziCsM4dsyBI7yao9j2YTO0lqkEINAOznZs6f1348/7/JRXXL3GU71yX6CCtPSC1qi2L3ooi6jmuPm4diZDFBk7xIpZvXioo45k1MBXdW7Dr2CdkJr87aILYNE81HP6NKPcbOCMqf0dx/LJWpcMRVgAMTLYq5Fnnv9bZgDsN47eP8rusLHF6wMoN/TbqPRTY7/CvqtR4FVxN8eW6XR8kPtEgzBSXvr8Tr4EVycV3LsuCM15BJS5+rSE3zO5+zEptx/xfMp/5a3bSHsIhmGbHsj6J8w2loyuQQ/hBTwa+SdisEgRZRGr+YEyBuOnVQg+AY465tP/9/xk9nuDk4tbGIZTwSljAK1O29xRNukbEG7VPaXy2a1aJbeBZPnJ0S8Xyn/8DoUdtw6urVe8H/b6seza16FDiaefYuhXn7NuJjqdcff/jfTETG3iiwhu1YUPpBov6kcCQVY3frhfWN9V9F+sH6tnpxf5tLrTIq5+8Aqu0UDUxdsyKzBi1ExhvO13O76qlp03E5A8+MaaibU0UVSxS8nBqcr13O/B+N9TmmUaK9T8zA+gefq9fXnJd4p5kjeB2UfBph1BuX0ILyftvuZ/THwum0nCxNiNJxcKQv1+XH7g0dLOHqGMlPkUxND04r8SyaTXcV1Dp84YGIE7sm83TediQzVjWJls72cmM/s7GnmjY3s3V063UUM0cJES6NU6bh8j7kt8vjZnfPCqP6fcynaSOBT7tgU9lDyA7V9GDx4YxVpuDzMo825u0anyURSRS82BpqPJ3o77Ee9Ye2ntORtxqXl3Fwv6HmV6oYO71RTM6aubycEgHTjXjjL7TgmHL5MaeJVKAkhiidomqn0eXHWsgTbm7m6GhzV3+yQ3v0ruL4g+to0cV1dl/QY6dpGZh8tvPKY4K/UzE3QfMdxYrXtEaxDROU0vEwP7SWKI7cpLCo+17c/5UWHa9OI1UN+PVFUFWkJF/O62eTU1Xs2NcALcMBo/uloVFFzTB4csAWvwezwF3tcrk4RaB/ML3O+0m7aeLsO5o/Zzd7GDX57pQ+FMnpD33iEkb8/P6JAteU7DmRFk5lcq4YV8u4gyqDl9lt2S2S/1P+TwMvv1ya5CTXbYLF9+Pux96X7+6+7pkYs+gjVlB8XBQz0XO9e7c8Fg3AG8kbAOzvFCXgcjdSu3Y3eALSlMYn+SIWFtGjWPzTXGpowWKz9YFAOKk3QHVkASnovDb1uhdyvmQbzyVca900Qa3BkOIbQdKu5HkoOKig5W6F4NJ5KWUcuNwaOI4iPX9JUHG3JTYU4r+qyPolAcF54iZsKt9HCB/PJsynljenXhPbSFvuqQJ6JwkFD8zWxQWhVO5pPiuKXrSQbyRFpDGQCzLv7pOC45Nqx9opniZqZnzZHLPUkhCNOVwT39polloT2lGopzo+bbVZarIZasbOgyllKRnx81F9WQlGBLOtJn5dUrk1wQj3a2WZcXYU7RtoBd2XA/+DpN/6Xmy7G71nLQW7t3fh0sekNbKnlY9OuMr+HRM+d3EdjPcgS6uyuTIfXiRl+ad+XPsils1/T/eqOtwYZCSxidF2Rq8Qq0omCdfYs/sYoEJzHEuiLOw+MGpyykD8gKAPA6CvJ1brZaQ2624wO4lh45N8j1R50d+z+Mu41LUfp1rNpJcfZrpsKm3WA5u4bvFYLuZh9l4uYVbrNHYP7dinSxe0rcAqh/ZE32276PtSCv0OwPTHOcCn2DO9eNO99MhT1Ng6k7NpvmS3osAfX/Le149u8O9EVELhdNS8fP148buzSy4suFHz7FvJr4Gznm0KrvKNMGXqeNRyU8KGZQvZ231X65mHTtdIECfcsaLEpNS88HOBcK/j3061j9vtNXutFBmWZyqJHdWrjhsX7CVbUUWy6fn1Xh1BSedaty+tAJjBueCgY3vOHEsah9Qv57w0zexrLrcQB9p/4v7F57UxW59Hr/zGRUeaqfFUfSCRVl9eTTPHRqxFEmM/hmsDXgBblIHWUVONlrrBj6jkazN2Nc0yn378arvQPXZZ86zvexKO1Z6sff5ROnwyT7Jakn4yXQqg56GzKok5waJnoUElmMjK9iYe/D24ia81IX4FE/wEjHJsLspGqSnvPAiq5QLkThPXF7UCvo3QFqidsBlokYnMLcMEBSawQTlQNoFAmdqR2iH1N+SE+kNOlI91MxHeP4ij3Vq6fz6oF2/2kzO7w6C3JokPfTTdRVOhbDzDxQ9dSwmYHjp98MPuWlWbS/78lOmY3/VaERCqOK4uvnCd05LxL2/ch2KnETN+P6XYCNM1wAM/uFngzamAdVhG4mqw4WwfWUYOZisnn/lmdi48QRRU3+B6MwHyuFj1ed/RPdKXQnTuWeMx8YTEYfVnDv6cAlyrFIaFbPqL9c9UkFMIzvTHbvoPEj+HgqhCa3rocA9Jx0yndECpbqnuQajSaSvfdFXcK7SU3xY2rdSPh+eGvvqGi3tRiNAyz9172jyQC+TsQpx3bvQi6rKnKWop9ZTC/YEnJPCIITcJguyoH7DFLwOHUy2c/VeY/8F24F5niFnW7f8VdbfwpboRk3JUPn/Q9oodoJqRF/wt+Pkzt67A/EXkveXJvka/EErs6ntJt29smBM+H1bXFR/RoqQIvFYvpM+M5m6xFE13hjYz4sHmMaGvHasrRL8HV3Ca60r5GOPpOCDagcxpLFF6SlJV91Bysvd50S5+FgZQmkX+/cOldE1lKr3l2XQn+WdE8HhIUX/sHWPgfqZMnNrWSfq7vypXq1VUDjLRLU+mEXX/Jm3a7q5g8pTJ/3zy0w4uEXLgOOqBj/zGf6EB+3+h8nKCmy4tYIvDbOzbB7hmVmydN+fd2zk+sbwVoEbNgJ9/2bbSRmclt0YaLyEqsT/I7dubT8jizd3ZZoMcIf6TQjN/ez6H7OfjdqccCUdO3QQPqxwjVW5V6dyJJtkHibcU9yMep/3TQie+SBOe20rnnePyKZn/KTJoCCteq5zCVwM4OFvVkYBX9WEzYBBiRDLvyunxAM3kcBUdVLoXI//nQ0TNbqfaGUIZU5pNNCiMZzAAKdj9t5lHdlVSMM9iTfHT+OnwMADFdKsI5jh2Pz8dhi3bAu78wmJs62fTEdaGUapcCWsqx1uKZBmGdfb48okcczs3B1bvTubGQ52GroCUcpIlDF+gf58XNyOUoG/JnS2QOIpM6ghEGCPlZayq74Z1NwRBcFtziKqd6Yybnz/w8G3B6711If/iIN7k0lE8GF0kCBsXnVHr3O9uapz0NtGKGDeDcv4afnyT4qyz7xBUrMDkv8rzDla3iELmNXyjz8WIo6/0PsvOzSEv+V4GK+d+oyQlwRmRpnipODZvAIEhKeXzj2KCaFBBkh1ua4+52CMhDZ1LoVL/CWbp4FHRjeh8gEQ4zMr1yeqZwFzOwRjNIwdQ6v9Pt0wNIzYHKfbN3RAN62YW3eR8vAbLDCmubmQi9WyYARChxPqZYd3CvCXcP/otJSHoevviRJmAwVp1prSCziYVJWxC2rIwYtyT2qW8U39fpBw6KMQzXFHzB5LvI4+Dypn4sHCyAYf8u3bd920aFu6Wn23oBU5+6f7QffK9+xFgoB+ywrh79dvrwZ6J4uWf9c5YVJ6Hi4sPJ+Q/iI3Wofe4vGdrVCxSfTje5yPYxFLZ3X/H1RkYkGfEh9eTrOJplqR+GUiXLEcn58V+dBHC49E6YEEJLIu0FDjvMdkF+OqRqg3Y7wPNMRhJC9xhAMDUfHX3g0xvZPTBIvlQkQq2joM0NMJKUyhFQ/KiNXJkPBZk8tR/KP+wbUvqvrOHfIvtoBbiAWN4SwaystqyfrSLpn1tji8/5EXBdK6T9kuyJeOSJvu+CARIYjrDGSAjZx0k0qFRBuFoxsLe5E2n/e/XzhV7lYySObX3QU9zb6FRPAoAcUSxPYEF/DDP8xAIIvt6gxeqphhJZhB94iHAJPmWqRYGtxrJGQB6XgPzB2CfgQY2Rf0ixVZO2+6ELgCAtIbhhsZpll13rVurfoUY/zQxcvxqERCfrkF8r167znV9mUYdgQuzIgHYBeWepZXbUl6oweGNfj+r0WwnmZuZ3unezEWWIyGLOcWzl9nJAG6RsHQe0pBlWUQNlPh0WV5/jDD2eqag+/IASHIk8tSImuRstuNN0BtJy4cWCeB6pntmeJQV/xkV8BS3nJK7AWBE3oDw9JH8UNGkyJF8oY02iqADxMeIyqfs18enk6PkF3v/JEWNWC+DdiVBDeEf2I8fHLujmKiTjgUHx/mRE/T2aybN4uzKl5tpxOqnsZsadQESb/rPKdQyicGMELcGCaYd7YeOW528X2pr1oMn/uV4PnoJOtBoP/kL9MiQPXUjkg9qaF0rOOgxsx0zvxHHzhlgEIJb8cSfKimjTlE7GSDRFc/DLk7LIBpOdD5eO5jsKSeyWhBLj504PASx+zV7sQVdpslw4nqnQdb6XRiHj8oTlNh9tAJfwfRpEUYnRx8RESkSgM9CgxSFPPgttwC2d9bVg0shKWvUA8GIb8UCWFV6LuhXXvBVbShFfEDkeE68yENfIvQQ0/H0zKcqKJQJ8XY9iC+4oUfosnusyrYOEKNiAg4GKLNBFpwrv06DyVXNDylI6n3u101vVRiJCbPsz4hZ6VrJtXT8Wu5gUtdMRA8eH6I9DH/xgiUjeV0R8L7G9WRrMxmZ5Jky99gWXuvhuldiH6WVHsqBIvFgJ+3Q2Q9RJCfhFt2fxoqgnupnpxUB6jrY72ujnQv4E4u4o+HmOyDMNRdl8ygB135bpTuWcbeZ177yTPEeSvsdF+dnba0fJb8aAnbVVTB6MxJ+IA6rTCE10wWqHw+bttAgHe334/7BI3zw7zymEcxGHpWqIber3gWqgPXw+suefWMCCcl3oRtXWH0BelYD5/7Ru2MdabUe9m+5pNMUDUJK9SmrdhZxabkaUT13LkzU+8eAY/5jOMW/wX/n2wNwYzSl00vWiQJ2pl+AuTv3edAqvnhzOPiU0Cqix2ev5FcbCA+Twl/ccQbZkOE+R83XXz9jjOmw7V6Lpiu1t23DOHb+giUbhMHF3zrNhh8vWL/BOLPHBeAWMkaR6zdpzoDfcrroAbZKA4F4KNAKFZysSquD+MTrvyNxf5g54PH733w6RS747/yhTaXWc/BAR1l8mh8T2FEztDXu+BOuMbQhs+LkS2+Yw+kXKAafEkhXNypCbbFgUQLWogpyDl47EtjssMiHtJO2zdebl3vTRGVaSgb3hTtjfSMsptm6264Z3DpbkWQDMDj61U6zLRsHzbSINFH2X4Yya3TYwlphOZzF8sSIGV4XYsoeVXf8vKabtjag52kNFUemJtGxTKlIZv1Bz1N/b8mcquQsxrAKQBcjk+aOxXmRg4eOcIrdFtDYkhrvfLOFJyPo3FN1oN4EZjkK+lFo8kTLfP+//fMGLEfnwPWrmylnfQu/xkFDoFeUVkGO0aeVRMPj3f6w471G3YYJdNT8DZ5hyxeDz92IA3/fY0knr90DAh9cbXbku9DsvZcmbNu9qD9XLF3+uCHDj0fkG6+k2FRcHFJcZCoqAWnyyZNjztsJqLrx7YuwTHOruywJ9qrHbZw5toxwXa7F1YqjLYxeOZlREkTHjdLB5m2PGZOpBNrrpO6InzTGyB16rER6c4RB+8lvJgcDLTuaxMssmUdLjJ+ZNtDHmX7ooU4kyGqYvfzdMn0zMw1sx32At9pxHzC+W+qxlBF1LCvWD6BfpiN5dlgSEEGEQeeJUSEIihm5ZROFZeGw/L34J5IvJ8N1OlLDoP2Y2c1DkYa/R3C5yjtmqPKJUbkCRhSL4ghAoDTD8TUw+J4wefd7qah4UGk9PcShla0LjGciNr7zg0tA1eOwzliNYaJSgZQmk8MEQ3G36JGRO8+PgjVsnU8OmtmP+lmk62b1bff8Dc1Q9XoiEjmVXcXqfG3Fa3SRYi2XWBFgc0Uxkd7qLia9xujNUntR5Lm5RYaAmOBrZO7p/fkeiGdyMMeTxAd6Eftnk89pKn7R/P8idMqTE6iSeLXSx2QPjc+KMXMT2VzCy0RXGAVNwU5OgL1aumveYFsb/bglfiemT98cIEvtTby7SL45FzV/xUGGvsUnnqJvbk1AdXav4p4m1D0SOQoep9/FgPHa8QGz1ujRHDMuuI/dUZ4SYsssmT69JNMWcmaWY8KiombGpLW1pcW4ku8rPQcKqjwaNWbF+IMfNB9ZKI97iopGFXdXr+KIp5UpYF0BO80/Is3DLaWFJhtDkF802KwlXi5bYq2N8qbMukTrgbthoPA6kA+CXijf3IUOTh4OKy1HroN9z/JRw1uQr5Zaj3q5NbCLa+dSrpeVRyQBHL2stNuPM5CScuHY8PGtF4HCOqa0bGaMfaNA75JtCQFcFJXzaMoRBn1QPaBe5sv44sGnmEGQSHb2mc5y6QsvDsTjYe1R3BIV42kTV0grbFtiNAmNyX6Vfc9Epa+ujYurRygjYLFcL08a613/W/1ik51HFBP6XJ0gtGCh8OvsiytKeJ8hB5aIocKoi/fPnm3Y1tCFNk2dL/rRUutl5PCWfNTWVuTKacG+eI/XkhXDJmHUKJot9d6KCcjfO3n8mTFV3VR/S1xyYNLZd8MXiZ6To0wmsTilf30MWDv9Mf+Emp8ZjE9AP22KZwjtaDwmNIZAKvjn9EblqVPfpWHh5YMGKGlHGuBeQWEM+UxlQpG4D8mGsXIyx8GJvOkiKbwCvh+z3RAyhqYmJhIsR4gSqQDcM0hTE0sChALE8ymQyYlcH4KegzjezEkZwQYYz0AzosGn47gkKgsWlnBg/TnO0iH7T5pooGJDXHmaiFFuREoG/lAjDHODACywrR0waJNpKN8nkCBgVfv0lNs+AJBi+XW8Pr6sFc0x/FcT+IKQGeB3OYeI/JCyHM+9jEQvIQWUgij2IkSfRrg7AEYVcLVBOmNpOVovQNa3ZgYE4iAAKQgDB9lmIhRAvIGjpIeDSGEYcInAQ9VddEWs73r7hscnfb8vQG6XosZ2s0L1HhQJ3aP9ReJFuxkKwfne8asoBjhG+3+ydHle8OUj7TucoHOaZEikMKQa1BK1ccR+e7USwyLiS506vH+gPEROHaQy8D0uvQb2MZz6VJR6C+z/F/IU7MknqAJBxbcgjJRmgAqlo4hFge/HicICXgbRv1EG7USD6c9OBvGFf+her9rxS6K/H2BzqCNExQcyjCWUEqMeadDiuD/t/r5rYJMV/2AAJqW9ovM+zJbo0u4y6XfbN5yApULlMhAbng+84rCpZaWj/LRfYWB8L4rR4Xu4+P+tAuHC/Qp9V7o30RusKdfhxgTQhOexD2x/HrZew1zj4/NoFY3xc4BAygEM/6r4UIRW+qFj8TRQqgmFPsKIAh4Cu4co8QncfE4DYB5cHig0c52GCawd3igIKiQlAgvjnR62namVrr4EAPoTWCIvksbvxZ6Iw1Lxw0FkvuR6CdFkacGjail9orJL46cg88cRn8egUsn8JXOtvwZV78SoYioROQRDaNAYYbHEQgvE1Wlw1AxxRBjc2n09g1spDKLu4sHnSGQ1msSBjiH5RtSxVO3baBfyehj8HnyRkMB+Isdy0SWY+Wqdwz0g/U9yIgN5SX0rndLHeXVByH8InqyHUy+OMqxvEbWQgYec0aHo0IiC8cwb0BtYazG+pTUQucTth+dkwhgsuLwaWaXPnzL8WUjakT0GX/FnMr9UEkzaUA2bj4bW8orFVlYwXCh1wq5DnI8tPX2HPax4wsc4fjmi6wAAxlC8kM4DCC6QcwyFXMUWhuDhAaSY4GG/VI3iNuH0aDLKnCDrUOlNBOYm5PMoDkmWLzuW6/yOwSJRIkochvU3qloM40Sj4SqhdhwX5v/QzalUhuA3mMJxw6tE5XILNZiWSEWgUbg/NfU8z+JXSgIpjcAKy4Dj/ihVWRmhqHIXAo2GKJlYur9k8GukwTCDH+bgwddH/kI8zZ87Z1sktCnFx9v4rBhlIFhM8ybXA0jv0kBln+cQ+oT45ilVNJtrtC6e/z4oL8IbHVwwEsKaH9hpduzFgq+PztkiQ4xzxjtAD9LzeFVgOlue6tR1YuFWGIC+9AlIfQDpxeOUstNqHbF6t8/TfV5ZZUwkZQxJ7GhCFu2m+0OkwdHv+lbmG3aaPbZx8ImI5uAEayhusLxyP5AfIaU5Hvtj/PK9QCPCdlDJpzrcO/GfL/n9om6JLTYll/MefCJCPYT+PYrZg8d7ivF+SnNI+a5ZAvsj2yd7AeoVU2N9UFSUF9I17d+KuZzYFJukW7T/9J+VPzAewlDWZhKlVx4P8UYoJCi1TCcn/ZUaUJZThaSDCRqbLNdk6Ju3i5g3Ju3DRTPGaeUrn31iwB6BMdWlEKVEKBICGQC0zOOcL/Wl/36Pw71PHrwAD0VNcL3eaBTw7eWTHnNhjZhSMYzujiwBEKVZ2JBBA5/2ImlUPhEysxlkgU3BBayQa0jIMNR7fRIMEmyf7GqcN4ATOOq9mh92DUAAyh943IxCJeD7MPJOP7RFSxOyflIEUER9ARuwNBgGAlUqJLKwodEMoMaonE5xRd/57hM8Y+dbSHD36au+6BlewS9PezuJ8Wgy2FODpBC+AjlTlsEjzHBDTieL//eRszI9HEPnrbOHAUQoGgIhROqXeHaDAVJl63sQIjYrQh92toJK3gYojrk4tZJKmrQPgHEPmmRIe/fRVxR4UtZkPspEqcHRwMVM5yhRCKVYws6mdlgEhxHESE+pRBqQmiXJYRVnhAbT6fIjr3v6JDARg+aHZJ+GV6wCGIIc7rEJPveWKy5KmHVe8qlT5KIMNonSOEooQKBjlwFEcCJL6YdxACKI0Tuk7ndfvYOA19sUklTPUKsJhlXtgoGPN1/Gqc/d23adD4aE7JlCPHZVpQ1ycFx66s71dcUsLytHemM6gMFfEUjizB1LI2my1JUTAGCU2thK/s2xAEIqAqiDJma8d9SPLips8dTNuGSPwD6yQLEUgAbYINYqwMnUPmMLjMCrIqVo2go5C2VmuUMDYIRSOAET110xFfYJQkhkzNlSDN6IaWMzXPxfqEsHJZ2kV0Di3iMU7JRDFGqLP+ad2wwkJM/BblUwGIl7YwjKjIdpcB0ifLRAOYGHDy+EoxIIe49SAYxSCAch0rf8CJyewokY44WIUuhLCuaQsIJYSbZyPMxiwzzQxVeX0BC6VRisSYd3YATar7f30SFsoxQBOxXnFvR0gA3BM9idDiGApE1v2fZSUX6lOwWeOTwoLqgQYqsgBoyTlIew2ADW9eTwMIA3U4pA3evyyeJHjwYpMIzq5qQ5LGF3RgZ2UeEE68YF5zUDGDa2rHSYDAtvoqEgItVxaxsEKWFyUmNKY60QImjIED99916nBcAocY4MyW76+2aanQZDDAQxJTgWQcNJHxgkWBpXnXT2VQ2ECZbHqD73qLCLfgRSNRll/RcZgGPUmGKz2cdislQYIZuy03m/gxwUNBI1p7JOQy69QTf0G/37DYxfyKWeOkclRA0odVShilx1lG9uaDDzN5CrYgvBAtYE7TVOmIQO4wvFtx/Uo4PTittK7GidRFJnVXZXGuC0j+GyniiEKCDriMYRryBF6AAhXB7fSXJNOr/5Nh7AGa3I4UqSIok23aeyTyxFac6+Sp8OKYJq+UnxDiCToFwHmq0IxnuwWQrDrkOtVgTRUPjRj6hJ9VKM1sIJFPyZInBYUd69jaW48v3NUhhxHmqxIlAW8/akwklFk4s8OyQnIil7/p0j2yt1h/YstSWgUG9HRKK3FKXVlU7O6V9fLLCkAN98fHQpRtcrbGDra2lVDWg9G8rHiT0nz9RttmYVPtNwoVqgCJoRn625562LMNqLfO6/XJvk+f7nw6Wp+IiUW23sB8nJ9i3MRlpiItvLYLhOzV4aI42JvYhPBnIGoz3OVWsLsuRvlv4bZWmzZXpadi5q0rjHss7I+01pPZIQFZFKS1MD/GpAwBmSIOBhrQvUKCCXL/3eGjyR+mzvzO8Ofy1+fHt6YpkYYxrxtCpkU7cWsqDRI2TSvBdaaSBwlq2REeKpKSRE+lFTIysNnSU6SxVRRk0uUm2+8l7+CVa5hAJnXysINnqbHYkuU7FSj9tBmfso09AuXYErzvnr+vzcAZx3x84W8IubYCwW4lKotp+nJZgI3VGbcxw1lA/1g72sVyeZcBm6Mz+lYNJooYesF2+JrROCMif42NG8T7r9eV5tfl0nASPW+WiTXiNK4b+64QPYIyBA2hRKpfuoP1syvmy0qVDIcNU2znz2j/TTaMikz0WKFbMvTcZNs7KT9qc5j6vChxNeCC29ubBcYVBfmR3zMKSMgrgnYpRbxVD0zBBzsldbyu+Jr3GWgK3giSg1vfFjBPyfWORRCxyvX73slwdh1rOE5dEGka3+alEkcisdPHrt1M4QWBbI/g6AA8zFbg7lYRG2suRkxMsx6RR0VxExPYoopQVEa0BSggk9Q+QMovr51bmj5eFmZTRfdh9mbEu/ezDDSYdRc1dCoKVzIo+OgAxyjUgstPSUTh3AYSWlFaX6NEad2BsadyUvrc+zHr6YlJ3CFbItsjomWuGSjBqULS2YenqvcN7oXx8YQk9/W1AmnownqYmvj+l0noaEe+Kzr895yV8l7H5k1DT+xv0AEV4f1C1bOL5xXsu07ViRho+l+l2WtW16+PIu1Xpsf/5J3SwJ/ZKuyurKyQGvPcr44RTyFg6L5gTAph67633C+tcFfr5GKcl52iTcYk2A1UhqxhbhlEcU6STUPEvielz0w75AUd9rrA8jX8pxlIcUYBkVvStwqq2vZRIPOzMyp6iBTumh2+BwfnrS2ti02qXqvE4xZcli6vuxekfU5klZBhuKqXQaKkLj49XeKcv2oghmzqodV6LuyA3TUyQ2n/NTMpYZkpFiE706T7uFexNy4AXnXiXs/mAULmuHnxZ7Ldi03SCgd/BAOoQwqQIRedERj73IXzgCRlWNnhUPL8PBJHdA2G6Fs6HRo8vo85BwINI1v+C0Q8Il/xksDUbIVOr0N5sc+ygICEGJmvfzm3ZQOPDUgIS9O6UJS8FP56RNmXEOlABbhsW9MYbv8lFXsYkFhELHPQHO3mk+I7NAxIjKNbfMtz8kQ1h2uxyQEdh53C3ca02AHwAZq4RjHhm5qQP8KguMKoUJC5WvYxZqbJBgiEUX9NbFiH6OYDcGqQL/vAw/bPPlJ7E1Y6UGfp0MpizIfSkJsajnCzcBSaPNX8Ce1A8vscWkwmWn2ml9KIWn5vsuEe6UpEVKhWe06Gi9hQy2VKMsSikosn848Avq7YdtYwLcM/AK5q713khDMBCxSfnA16uTLwbXwWqszdq3g4LmAy/uc1yBQ/j0gzcPduo/LP/yGg74E3v64kEMNwZMqxJvGpiKFH8KZeGjxf426oZp+9xUOQg+Rn4Kn/PxkKyJesD4e26GXIBAVqEFqvilkYCxSGgSraHnA+G5AhMTjaZ5y7IWly+8ge9NxsBOIMRMN02OIJvWMyFRobHiWK8g9rsI8MeHUGpVSILceMIQ66+Nm1cpiMO6NstRWdujtHicXSCbZoSvx+00rf6mVpMqWdFuihNVjM8gM9y0GvNf6YSfhHuaTw0FJicKSuLJKNudpcwRKoyecfyqDJkjrSwx1GWzRGjStBnJcAkznXH2oOyeyLUZPvDmo7BUGuKGDE4MdLpMDomWXOfIzITK0whr+DWsflaXIt4mVH/BWfKVrWmu1Gh0m64kqzzIFTVRwd88qI71T9Hh+WmTAxQly3R2gE4fYWMC8fJFqmhewPG0eD91fE80blzbpEF+xEHrXfXWESVRhIKUFEnhpCQafG5FlVbaO0kQ4vAobbwSt1wo4M5V5Ii2rTbzqtIFsZnFyREOsz1KnYJJEMU82xVrgTd2ObXR5HYERtoTNgD6637EcI+5uNxSyXl0jXs2L90ZRTz5o18PsGf6pWjxQt8ko6LkoNYpRKflWoGowHsDFAuVhGX9LjvPtnz06AuYUdTvE+k3z8uI91nuEJSrMfJrioLW32x104PpEcNX5gTm071dn0IcfvuPqDTTHkTUcT8NlvUe0r/lUI8nRBM5T3QXfY6Qw36pfKek6q8Us2BJCIg2y8nfb6lvTa/+q3/LEc6hd8k1GF1e8XEqh13o+cuztfGKnqp8B7Z/fDl9jiz004mi5sVzQHrJ6Z13lnpA42+x336D9ENXBFZdhcHb/hhZjnk0THNIrboz7qBJVLHczvQ8rBeyBU6+XYkfaon7PTf/7zus/iSKLdSmR48lUnaoZL+aVOkIVsrmqmM8CDQfxT62VY5x/Rk5ERnxJBc9OMTShEs3fp2t5plkxHJwdKvUP55epKMb+xfd0aGL3dpu729p/EICZbom7lw93gfFVwxsz/RBjeLysgOuXGP2HN6Qf8eYGImjoUWjcsQbJggOgukLZI29VoaJMdFIWm45EErKXJEjZe8mj1mCnPpmV75THZU059WIBwSB1YdjkmIcuGG6RR6OLsbJj3HqOJoe4rD+zgR3zOHVIAiM/JUUpXbmd11vQi4ZQ75kk+ZMDSYNuunVR/ItZJgY1t5GGeZVbYG2AHzr9jnnc9d4+K+//m+wswRi6aKLrBzua4VSPG7hP2GGnYnJlI9JBwJXvNSPDi0o2wCVbyayltaGYZt8fJzPfKqZiY6yQWzoRkZXtWFvmFntUpGgGwYAdX9gY+CSNeFr4J+wDNPNG68mrLtq009/57oad7X4yPXfLG5roMssSBN7wmJjo2SrWxa25C+MPDNvzTz1IZl8K8C9JPtPVsFWs71JzjpNQ1hAXZivqGCVfpZxluVa2HgtPjp5fW+wWuLDYiWUJUT5G72nlNSW8M7pz43NsknEZcd0LJee2brFGGg5MhmKWehELae7ZvSWv0evOd/I2Pb0JEvsKCKZ07QciPfnTNSlN8ZTe6PnrBrhpXzNOLr0RH0qa48PrqCA55d5I7FsEvVaalw8LPSW8EVhU0pYx+VEtmmYtuGpfWx8TtkRMSafOal28U8gj/fghNmjqG8onzBLBOFdnDBE4N/5hO+EndxvlDfU7DH444T3vk+OtNNNRB6iSUMbR42KgkHIITXHv7bCYZIAEnLlmCpqF68cg5LS8FH4oCJgAAKLH+Ax2lIZsCBtrIIF13vn7fTOm70o4MFOsffliuC/izGatTH7/sh7r/wEQPLF9be69eSE9MZX7cVpdQfAIb8FWx8cendOlciyhPl6/AF6l642aa6YosdlRnPr3fL+jYiX9UvuKZ1i8YMhTOdJdl7w/p41iUDXZcljDgdiX3Hzvbw2bg3K1YmCO5heF8TAuWgWa8FNoYm/1GCtZiR9RKM2pUZwI1JNzZL5Jr5oJHJExDfN93BBxUmstiI1tzyLPBdjQPk5dY+D9nP0NLQ0H+DuuesesGjRYu7iv3YRyNoVGVYiSpaGhjpeyRPCIkvfzvIKljZH5URwI6w6mYVrYfy0KJ//O7m3y4xS0IDTyoqTS2QMDAVplY9zd8CpQsHcuQChyDvGHs2oBAhezHMlsqIcK/IEVrdfrluGBiuBJLTAzjGP0yoh74Z9l/WPAAeGQTltpxLWwZ7MMFv4Mr9Y1aLxXBlWvpcu+Ttlv2NKsIuDvIHDUdc7GwF+lSRbJN7AS9IaXgIEaYW/aWETwPY2qCoaYXjD5i4K0tKEYvEh2JAYtgSa9NUo8HO42Y8BPZm95U5o/XgM3DsN0QOOZ2xur/VLHKjH1Ef0RfTm8WJ304Gye3h1P/psihibrjuc3ZZF+0xo0ku2Z/Oq6f7mTzqIQDCAIg3YR34O44NydiUsoFDRHYSiRag3V50kVUITmBWJRKaW0J1gEV3a5EH8rDfYYRsTsa0mAXj4oZmBXUEofo+3rj1NgCmBg9Cz6BOMrK6uQ1KWxoEOEWo1MNeBJh+b2z+6/h2m7zkM6IhJj0lb72YBhRzftDYxahXBpBd4DEBcaGD9KkIL5CtRrMpGjdvDA2gN/IP2b9N4K9sNbl/1YgEIQI/bYs4L4z6iU1CKIKSgnXtw4877733HIUChoiyOgKkBcUIHqQFXbYdXyQ0OR0Dc1AxwjVB9bnVTPFsMsv+RoVvW0qZWF0XYb+dss4cDaNdwVRkjQvqsKEJ4+aO5DJn2KgItyFS0G2mYnOEYx61fRgXEUekr0tL+SgxZhOztRc4OGy3Roc7mjtkLbJk1Zgxm2pB8aXpiELYuBinpaFdFsWpMlXdrww7yrDqpd2WF0hpeoi6tn+K/iJDplYHTnyAqG/hTiS7+Zoqxt4gl/8pgPVDj+qudF49cjGE7TKPvxP9B6edtzwEUvUZVtiG9LAwMtNYT8FLsCiW2Hn2Ryneg8RJgCILLeL4Va/IQtv/5HMtkqqDY5+xvD9/r6wDABEXw+r9H3DL3gZPS3yf8+0CMLGbkb/OmEyknZCdST6h396a0HXNu0KYsllUfOyjoPLgMPF89Y730PIK7yusQC8VT6jruZoELB/r70/r7wRpDrak287BkgmmC5Lmk09Qp8d59wsvPaWcB+FxR6DaElUXbwBfyH5gpx7VpgQq5ywcA4RcbCElhhpS34rb3Q5IrgudJu6kRnAI5ueIRSP5w3gEt8rT0mpVRglId18beWjH66tMUahQxXgTcEuFTn1sR5a7lcJDr618Dvu5cRPqlDu+Oa37wwkxa4OsrLn3Bi7tW9iQBsb7cFan/xcNphE3miWBA9kfDpFQFROlgOnq097Y6H3LH6SQUivPYef9g0AVm8YEhESEJnG+6STNL95Mwb+L4gnh8AeHFF9bAt6SeOszm/5DQRwDGbfwfKT6iAtTBEP5qcm5GCbNAnq77EuBP/hHIHLf5lFvBC8yYzdtIKUxwo7KdtvFudpgjiC132++KTUx8fbehy4V8R8FfcSN+CKNm9vwGUxybCt+hUODuFzt8bMBvGmcvpRBWdyp22Ho0nvOLh/ODI3uFcoUd7NZj4ZefsTDskUOMpUmFhPwt4UELwcoxkKpWrt6ekZsSOpGmzlYrOvKKGtvOfDqLCtJl9xhrkyllVlBBNZCwrCM4yS8pGLA+uY6bD6Ru8sjQTsD3hOLYmzqBCbnaOO/ndLCA12PeuWtd99myVvLwvof7iebIW3qYu3bJPIZXnlbPV+f/oj6gztCotCrLGIs66XfhLGpsvfjWMvM2r8ZgdfD4KHtmwjFYYvhoXlubesC2WDWj2bm3tkO9w7ZV3XcDmVKx7Pu6ULNWZ7Pp9FbLac/4dT+4ulPOtMoLxn1fhB+jH2O16XW2zuDjQzLKrrQJUPaYu41xXNeVeX3u+rnqa+cKLaxNr3okrGn3TJK/ShMkjNDDLBr3zMZGt2hrF9lOsOjcY4Z0wquNbInp1TSWpOfVJpalsLVCtWRa11YurXHjGd7KyjYBxj3GIhOegjmZDDy8MeuqgLXxVbOE3fXK4j2aKKExr53rMo2zmh24F2y/UfIuqL5+jkmTTHy1iSUxvepiS3pebWQJrnatjlllexiLzgLdHPD6rMfjg54jdzbf6Wy+M3Inquxbdc3PT2PKuPE/h/AZCUJK7MnwgHt7RJsbbFu1I3OJZ//5OXt2xs8h7D6wXfLxxdFkkD/Dw88TUsQy5ArY6wSpb+GMgNYZRtbmiJbNka2LAAczFTMDymp8QDmjy5c3tRGCBeHrJrZAY+tGauvmtGhsHnkbc1vXcVqB4ava+HXm3SRVMvA/iZlSA6cAlPRi5964ACAujdancH5U04q+6i9X4sGKA6mx7v+0tvVPuq6rhCr5Nl+sMMH9c/hA5cr9cyKGOUQlg2l7zH4EWQY1N2KDu9+XMoFEYkDTB/mHhYTWF09REcxCdkfXW9jG2t6aDADr8WpoPqQRnV8RGuvDqqYUpp/xip/rnXgd3FYqUXpouj0R7E9nXBlgJ9H/nBw9mXZ0MgMMnTxI3/uj7Me+b+KfW7fSN6ayttE3vCp9/cur8n8P0ofLD6SyD3xsNPB4789z5f4P3Z+uu/3yg1TorqsC1dfkASpm1hGupOi27wxvVvSZVKVJv/8Oj09ccm8wXgBoFfd5fHNvjVPTrbK3V6T4AnpKHiPfVZY/CT6fdepLC2ZhKbhGZtxDugI1HSWMvMK6qjrb172NX1H+lFHA3Y88ZFxPWJYNQ3oJGNc3pSNmJQ3BZ6biahCBm3y0jMqxWJQFD6pIONERfUricBvXPIvqqTby7TMgKWGJDe3DB4PkWX4U9vx+OQRu7UDYifmJyKqciuU3Oi46WV17UXJsgykjBr4CzjtuXWpc9hzOcG4cEXOYE5OzAgNT4GEDqivKtUdij9aveWr8KtkQiqLPIttf/G8qI7AMo6aKToUycYbq6jIIYgaWAMHucritZ52oqmyIlExW7lvygYpfhiOx6YnI6pyEcem9W7d3srr2ofXuxpAMt7gPmnc8daoxS0tDcm4UKY/2y7l2zzY0UQ5T0ROczr3uDQLkcxjxzGvoIUtIezCtHK0mKW9EoGEgathDhpDHyi07tHbJsuXMarAOVl3OHTVo4+DZbdGGuc+exw0Bklyc82bwgH0h6MZb6oMzPR5Rk9e05Ue5F7KV2tV4YzP5ZTsL1QbWe+Nw4VzWbBai4ztYWPMTEZW50OSnZo5sm5UK1vHQMYtLrAFypChNXL64o8JqRPAWo/K5lqJ5W4H3SR6zBcnVuREAGeorwBPtAg2Jeq3mQxKny3/NE9jbv4uTcUqqF2rcoUzCzh+XvfGwafq3G+Rsxtawl1Hbz/VAcDVSjVfuR9XkNJ1btOR+sFc7QMX4Ritm89Q/o+ErJiBkbdSBzoCLsJXZfX10i5fKHjLbyI4Y7kdW5ECT79ceormR61yqnhJ7AF9B1FQ7U7e8uy6F82ajmFhXKuMmVs7CkNQDdCScGOU4JXG6DGvugN5FqCG4iTgJDBmYyHEbO89seb2NmizCJDFH00XYJHJ4gAiXwBw5G5PJkYyrzv1XBd+PKme4IQIxEBw/EIZWv46oyms6eKtzKT29EzowFK3cj6rNzVUWdtnaZq7JCdzskD7JNO4fjDaQ1dH/VLCxS4eimBJZI9mxBNE2hiPTM8797oNBTOR6OyZmUYvVCIRATK9hiU6KFNjouGEEpIUzZ2Gomo4Fupy2A1KHde6aumrSPoHmJECdwU0pYqQ/F1PnVbV778ZUB1MxiczlWIo2dM5KJumdCDbhl9HopD9eAAJBXAe4ARkBFQHlAeCb3xtPcGCQO+gi7t1Eqdo7WfIvaPf7MTrEbu0MOY99d4w0KNRWfAlgSf+vMJXkrwi5589fJ01K3PxD6Vsw9vIESxM5O0FLzu22hE4kBxKzuXMsxm+CtBjjd0mqrV5otoaBZQXwDNO64VXoDdyHCxeyXhPSM7DMpUNN6LHJcAA+5hUJCAkxxhSePGvrodV/PHkm025ZqvI5OVxU2sZZ0Hs9mRd9XiCuIV2cWkwpn7Vxec7odaD2DlWuE3CvTjShCKZrpxaL+UIhh5868Lxx4d59CtWggM1YFjHt7i8afWpZtOjmfjw7SwAD2rFD4yjP2M+DpEGZ3pnzpWCwiP1caxVZOVKOTWTT9rjmDfFvuoF4YQPRMSJLaXPyC2QwP4AMEEE4YGY9ZkuV0Q/yO9HNYyY7/k7z53FDWydFcj5MYaJzcgiK1LE2g8hAkAxTX5TRLH0LKJN6nfn0s8w2z/alH9zlI10e8a97eYW/2aXuUj3FKriUROR8HrSjR59/RcJhU8uzMQ3DlkYi1KfqJAvqR5FcX4VBZ8F10VW9nzs1OifabA5KwtCODhqFKI4O68lgeI8cDNCFZvB8vE/U/TjtXlCKdsukYGR5y01ulE5JOXcSVqsNOIuLrvaBFnid3SYeCfAyFzupRloR2sA6uRG3KMlV1umR4xK5qK2lJjaJTL2v2oAzn2HuCN9+qWHRSVhehKZX5ocxhjhv2Ly39wLzFqxnyuQMvgD94SM+++F9MevfH14sRuCuwlpYnEO6d5+fd+tkgXDKv2+3m9Rixf5fdD7XrislrvtePmD+XJsSpheVDApFyvn00U/5+rVS92dkdrDq+fPtDDBwzHuB8pvkwMvoyZG9a4iJa2f5BF/+S7dYGQLgBqxWm3Ba8V4D1d6whd7ts/7V8CZ5WYhNXFkBy44MWCfVz9sMH+FQdwf2ZDiw1cvSMYgZakGyQlugga7Y9IzwvohNe3ZNJ2L/en8gaUyuqepW4Szi++SNVkPHEravUCdg76BU2K7r/FZ4sDhpJsHzAUtLJ5yFYu5fX8U3FeOnVRJGCN0FylhcVwEeFNqr8K3HTZvKN5g2FuLHfleIH7PNtLhicciiKnzLwIp/KwB+U5JkqmGx1Fcrf8N+L9f4SfsMfVI/X+VbNlX+id7z2d8V1L+y01n4lPw0f8e+UBJMiq+8G7X5CPID17hofdelimJ7oLHZDp5nSd3qwmA1at51kdKiKRmgYWcdXXFbO0bNcv6Sqgz2228L9mokLr63OU4AznRrNhphAy3Q5GE91Q6fWoWtrRxIVpKSytnz2KgK3Rh6RWaNw8IjX727SuniBZETK52FTxlrW1mydqEtEAUp+B5NiEu3J4bDjMgE4SYvjaHVgm40KptJ6jM7b0mjY4yXpJETKh0q3656c8PwsqV2py20IuO/5fpcbG4ODxXfE55tx9AtxDhvyZSKsdVy8EVNGl6b5sWkw5DEClzNKxEZy1HQCRcrqKoY9x6pw204Atf5rHbcDSM3ScdDlpAOhayUaxAFDAWX1IQgTuB5z1qnSRcoUGIWZFEkfMh0I7I6Dw7b9r0o/5CB3GtF2MGjvbCT93hcc2o/WjaxVTHRe41fL6LmLhOc3MB1Cyr2bomwPtX5KU/m8gyiAB3Kb3IwvSCIDiriA7B5J6eUjxT+juJya+hBpbXlDFlRqwuOSualT97SdYE5gwWPvMa4EVWTi1JQydSg/QMBndMuwu3bXIahtHiv54Pr5+H9Z6T1uk4D9kXzMBB55QCiX4/PKIqa3HDYemd46uFlZXa4Hbw6AMUmwmCc5+0IW8O0kBpd3KTyeJxiAgjqMrFwgTvSaLfxCAzl4/MW2gQxJ9cdyhROffOOo/VFALWv6FxgaUMgUidX1wZRjW2BKJNw6jDB8kRkdSGEt46Mt0tGHcWYr5Vq8uFo1N6MxUsC6nFs0+MRdQVwPPXOPxUV1qGA+yjaDG/+WvBsC6bJyY2r7kYrJtR0i/2WNNrtf+QLimdLgBzDiIST6jZ2/rHlNexCr9CHS5VrWHS5mkuXaFl0mYT0FJ+zLz8R0Tmwos6IlPXLxKBfJ0MKMd3YtWiz6G5qdIOe+YTJ3jzYfbLpjchabLF9Sw/RUQe+8WxRdXnVpr4w0hEguiAvbnbVHh+/dFZefPmLtKQ1Go6nvr9o2vnRD8B3X7Y60JoYCjMiZISwLhoBqSHOBM1hVSNEiOvi4LNv4ne8fVUmKK2t5Snahdap93+wXoR5Xd0mHFd6Top8VeuLkuKTEFL/ZMTOPF0Fuv4J7+FxQ1CbMsvqA5BkOdP1oY4VKUcbuVO0cjjSeD/qIlef/HX3Fgat9yE2uqElBuWDONPhyMLuSYgYg3A3N0fvw7ZBWWlLvvXnz7R3Hn69lyazplgDBBNj/t1HnNTjUKoGqFeaJp/6GjDUZ+mMs26nGXRQNI9zQCzRchZsjtcgY+PzwPRuNunwKhAzytf2B/lua+1qp0FaSniqwU6Z/tjvyfxylrMfK8zM5emswBDzb8TLiLvml3QQ0RIpXjWLJ7ndPbwZhPAmrBEKoagAZ/Oe7tsAPiYdsTrRhR2e/DuGoQyX6REj6ucB5HqGe1gXhc1PnB7iGFeIcHqCMQzwXwsx0BFG3PseVksa7dn2ws1EwE82alQSGvLuQ3gXMP1Gp8Dy5rhiCSINXMbKTP4Ob5LYWUqnUGdScVcVAHMeY+O+XLu2yTfK7DsAYli/eWhLaBzWeqLPDn6jLaUl7WQxBUbiUStYSEzQAW67RwS2Gh2wfU8E30W5WAemPHo1MH/fyn7PlQrNoSEqqPR0YV5rp+Fcp3fS2JVzy9e1JJWBT82jKieP7Bu7fc+Ryob8gBk7vMgLxwpBwt57+sTpKR1F679kxW/EWo/sYtKmL0ywtDOSvIO/5IlbQm1XGQ/mD+XPPz6YMYwCl94u3ZrOn/8mqRsPVavTnTLfGPYDp1zrlEWqkw9NCYs/NOZQyaRk72RvEJnE2OFMnzwlIglal1GxaBGI+jHZm003Xrvb4D/QVbgNbZq5e+/trnlsnir47igmLZmjqSkWa0eTqjNAFsp3ITyhJbbN4iNcqmQeLC/+l7M7EBGR2BX+/kqFj0VK8tcVb1dU/b/bmuaJstN8A7rQNOWJ20+vWH1FL5tEi9q14nxNLtfku5uhyI9XT3fszdbHHNSiWPJPbsfFnwGLubCcogQnLDwHVlz8Q+q6ucXxDpnt+KFWBZdPanyr8H8nl5yxvaLb9NOi2KN6XVadTOENI7P3Jyd2Dgz6k1v1D1xWF5+50byRyZ91HuRseVP+psAVbZlsVeaa/xfwzMogpw50moJ06FS8bQuSqTb50mOpUAqEIDkZUeKpf6VDr2p1JXoHuI3cXffyzo8n9su74aBp/k0fpJpDJMAaJSvdcp+tNufTsXP2gr5tC4KzAn9Si8CG69+xXqFKOVOv5TQ65Pifr+WRmEWDw2Utn8v8gtQ+HL6z8UBan8oCQj4QGPGxORJs6ynbWanrBTaisMAY6jI9OzWBJLS2pfuXU3FdIOi1oLKoVBmtoowtmdXpMAbNSjC4LZUZfSeW7mBDw5bF2LROtRDTOOGzQm3/vx3nyQ/zl9VPnpZ5hlcV5o46/MYByk1VC/oqdKtPYw3ntqamJaaaKQ7pZ7vx5nPw7MoSUsmzU27ffjUigK3SuLwfxQjmBvyZJDX0zENcfsUXlAErOtewlZKF/OstWINKKhI89XNYNx/GERhxas7z1NzjzACf4Ln67Mxh5BfXGFEf4sIlYZwb43iBv4ucgYvFPp1zewY9AgV/P5P4gECiesVNcrUHeTMyJQDxV0Chg9pHGBlPJjeqjrd/jbc5c1yuWTGd6hKtVJCBYfHN1S6MCU2Y83blZPSBASp4rylyL6hRmbJ1ZPeI0QfKFkeBlORXLmL4hrH/UMvSdOMEDMyN9Pkv0HoNnIpdnToI/d8G994JE4LuDhBGxpNg4EZ1yz+C2YvsBlheaUamai0Sd/Q/HC1jRa9U/vLCNisliQn3onFdb2e1omeBHpwFjzIFLXhc7B0oP7ZaSiTh0vNWg5cS/GeuDfO/1AZT0l8U34+AoS+oXxLMpxDVbWvhrvGEuvdw3akS1KrohOTA+G7TOGq0DimUalz+TZLwlhLjfGoeUj3ny0IVSKB5YZ4J4h7Znyan8Ahm3gYmvFkXAxJHYUJF/no3dvtP0Ki8+JFoHbK81qnwIsn/Y6rCsW4ZE52vB6A/rP1u8Rxfgjzi64ZtU/2lg7CypHi/EFdgaAUS7DesubZ0SK6KsAf0dvwJFnzto4NipIl8FHykX69wyN7PdD/moerzIcyGwfRCzG/EwLKo11DukLPUnfl4Xi9o7bMG3AkZZ+ZgNoBeG5nd8lLRapk+NNsZQp1VneSOJo4YGu9NNgd8DHY4ncA06B4F2wXYAwpq0ptkeaao/yIOPvtC8TuwPuUd1uvBnl/P8scRm1du8EAfR13HRCUhTBkWcNiC9dFf6TViASNoWrTxDhO1aUvAeOu3yR8bkLLljS8rx6mlVWRd/9MZNPmBs+Z6Gbn+cZkeHQ0Wy6HfWcmKJ5jGmeIIJCSeF49pVBb0QgA3hOF+5NGCa6SDAHmzCqvvK3cQlnuslGQDjfGRR4tPmmDJypxWrpJzZxmzxul8W7QOJ4r18jTzdxS3kxS+NKnjRj/A5onJ6XO+kIw8zStzYeT2JjtKeHyuKySuPn4mjkk5OIPEL/k6hT19+Z7jnQiJ7hgYbbejhMeiso+f/UXISjWcLFmD4h6AljDD7LKDChzxpfp3GNvK7Ug+Jj7m87AX4ywLJjQ/ubMgOpMRTQ4kiNCBV/e2UhVqizmXpQgqvJ4m8TIAAhNqXZ1634hgxB5SWPJoFVx7TKHLyTKwZ30J/LKRKf+ilLJkgXXFfXDRAKa+c1BskUmx6fVR9rS+RPvcxabwFV8lpXC1w56ZBNPtutgiz+Iii0dC4U1CBqaydiC1jE6UMTuo38WWkYEKj9ZLj7GNFMUHBqfrogIqA0Ki7NoAS5IFpP+uj4ov0BayVMLV9WITH70QQwBdY57GWzP/rpRkeuwaVlqwWWWIswT4uRL1GH0ODrWYQ7NzXIGWwB+D+YsXoqFxSGolDbeofUrqlGsngQq1UUGvLHK3Ffh/ktfTHWLURfWRU5kMP3o5QxecmBCojMn9DpbF6sb/U0NouObtaRCFW2GNf2R0vubFR8toY3PGUzr37e7GDzdki2K/RHzcMODZbmLFZl72ZMK8zrPUzGoQ9XGMO3JBmgDNRhQFpQcryBnJtQkWeD0yfMfFFZb0YvSWVbuKFUk0JKqeFXErdrRMRD67cQB6XOXiRA1UJSasLmzYIpghFUoyInNSeuTZO7LmQ6Ml04clATNzNvFNc7pBiJPfZvXool7+MYpkvu6d1MydH1nzHMpLOdIx/ouwOiNCkgTp7F9whLF8XNzUS1Hx7hDRYoqlgFXyZ6LV6uZlcaLMKsbELOTs20Pgi+xLtH6oY+VK54DLne8wOZPT9OxENwPRVkhyjvkPo7VX0uiWGKYqKt1oCk/RUr9cpY5aCLVnKme2ffi0J4jyoixRHHVoeowyRXkwSXgPr82K5QmP7E8rSQlIkWeHAOo+o19srDKe6t2ydbhdRMiJjD3oUGo4J3V75jwY+GcHWTD2z0mgKUZ1RkBXU9C5RfJfMu2uD5nlY6Gu1D9iueY2m1bkVcKk++UJOY8DFRVHib6ifNx24bP5MTqW/aiJ4kWMzotPVOtW9am3+U60ATQJe2RIQZs1RYdybOV7G7cM+Ou0Fp6qIkoIbzPbyVplq5WtNBkvIcSIcoUka4DJ2nHY5i0Pib02fQlMzkrmU3gUgr32au6Unxys/1Iz1rIQMWxkoewfuhhh3rVvbp7EHimInscu6p0LikXbaV7dLqw8NZ9L2nNCqEyWIAw9EXEqaawlQUyBIBgXk4Nkbguse9xNZkS9gLX76V2CpVBSqXMpKJ+///DGejlvq/UrBIOW4WyW1Mu7gIXxly5CxF5/c5cmtngLleULwaGZ+DlFNKh+Rl44rPmL2Wz88REt9FLrxm/txlYF48wgHK6dwjHfSvNlFBLetpD0iX/dvU5S/3rSTbY+y8AYZ3/zSs8b91ocuGyKh2S8JPa3nW1bRFu9KKU8K5Dt7RlAOKH6ASFnhOHsv0RijcjrjPePPusFB+eeymo+TQpX0ajrvl5JLHwq9p8/OqRvrz5HUgGH92DUcj4TaRqSEJ7Kd9ZX2aKLkiIQXW4FDW3JpxCfpJO27gpnhlswYYcbxbSefr1/ckCAdkAWj7PErpBawLgiYpYbKlVfKNA+ucGa8lqojjOH+hjMA9Qj5x/c9Y4oLw1zqJ3sebkTuMrf003HVlzmGZLTAmnhe8haTIcQ44nBGQk1rmTwhztTY1KJtk/rLt2YR1cGWLVR06lOXye7VZcx+SCT9Pv1K/hEFRNcw2YVxjlZNcFckvJTgDg2t8q5xG1jCP87cvwrFA6+G/kntFT6BH179cl5DFWgRYNP/yd16DCx1pCsSl8oDKSsJFUAfyuFyCrRhHevkw3vfOqn0rezOCn9guZArDkTnusq/xTBUMWbw7z15kHqr6EZxoiy0og8bXJ8RKncPzkjgBq+h+zm+uB7zE7w9Svpq/ssH0gfQDvpe1JD03dffoC5Qoew1dHHxaKkZAmFjs2opSP6B0MLAMmdUNGHerO5WN35+6CPVd80Skk3uPFw3KlefhUnezrlof//d9nOoAwaN+od8tE9KrRcHvrnxUFqS9wePNR+6iQLs56coifZY6R3eR8WvaYBIfi/b5W0s7lYceT9vytld7DfsVLmcWUh8ctCK+1Uyr72rJpoZvFfzOu1GW0/WhUu+L9/ywc/TiQH7/tQCT8n4n7mHCiOxIV/8szWAIyLay2u1TdUG1vBbKWY/p8CxL5B3uTw3xIe/vx2wz0i3P/T0ccfX3sjGJQwWXMcPF6YhPxos0svfJ22NmuAV+XAAuZ4jJJ4gMu4hTO4gQcvzG9Fm7VckBusCXc14X5u8k4PNDeG4wCLcVI0SqyE1gAa77A/FvWwssfqpaeqYoPLuabKFl8oFaT5ePBBMLOG5v1uuCDymgBO+Chc13wxMQI8wjZvjYGKPZr6l0yz7fkaLbgr9r8/9XAvdeQwq3/eyT5s9W4t0MhroTC+TeV/L/Wny5N5tuca3L/GZ7nOvJOxRk6gl/lMjhQ9uurtRKy+FjFQQKgSQOXDWbEP3l8GIonVarM8HyTp3ZyYn38mk0KvjJ267jxef407eVfSXdJMGOK9pNu6G2567wXzvG1T3L1Op+5lzok3rruwoVl9XndhSbNuPjd9B9wDbdM5Ad20/rI0tJrds23+WSHQowbddGmVZPlK9nC0R1HW8Hrf1zxeQda6FMyjEtU74XwzLQ7/AjW7VBK1qzrA99Ph/RF4vw9Ug6Xu7apu7ZqGdrmFq2Nwx2GWNUUHZv0KMTDKRtzPXZCHN6bvgOqUfet/kuN7hzWaAuJObVMP9T3Nh9svQxKP0ViAB1UqCxFujlSpdJdpYbC7pvkL3UE1344Ntnhg2wnlArcTXMOD3G37oZl5P03laI771OCyEO8UT4ByrEU8aNuZxYvkbR9Ps8q8ApkCtf/oXt6PFq6aNKAIP3960S9NAnqSRSvbtek94q56H42oLq4ufAz5gMvxAqEcnYTqG5frz8G1P+OKhOhGFpfv0OMf2Rx7CEtjHwBZrw0q5lNlJnYzOKsVExQ/PC1THmeH6nJr4MPLPdGW0/4eey/W398iuAbuO3JI0+1XWFsz0NHq4P7AK6sHVjA2s5XnqRVBVUCqwK3WRhuxTre5XsHdb/7wIocOmFIdVOllTOfdbrto25Af8zeHbjK3GqCROD9HsUvM/DDQVA432vYxenVwdkifcxKDV9bnO3q/tKQp/bdjGoxB/oDzg36hnoNiz3fhpDKFfqdrsg2er9L4phvd4XGt0N9P2Hj3dI4btYzevUwJWr2ihzGwR3jS40poZTKHA8zhb6QapciA76FEadoTNNurmMV9h/MSkfpmsNCyLZH7//XGbjjt7vvpPTUGEPgsNDQgCwfIfMLqLiBlCLkup4QQUg9iABVrfIPTQhyAgBCHyMJgaZzwgMQCa3QiAHtblxgvb4YwwghL2AnqICxbBjxQVG/bh6vB5XMmWgcmBjWN0zlpcpRglvXg1DYBohVbWPhXp5FGNGyWvrbHkGKq83ViGDujcnuERdy+jv+ixazSIU2NorqvTmol4CcT/771g1dcQuKJVtELBYKEi9unKZ5pq4PjY2a+T35/8OT9GO1++o/tKRqGbEXc32NZSn0+sAdrY8IOupevenhUAOtsSctRYUsV1OMyuRKJhabzjqChdEMGCuWQQ6rZ+bTaMBQCzwkXZp37KyuGPJakTIZgEGAPwbHzdQhRC4eQeNnuUHLokrjbunegQdfvgxVApVdVQ1fVs6ssrvTxcqs64B+1eBSAMkap16IHmlRsvlHMnx89fhdKzL4pmy8Y+Qq2sT/9QSOgikZ82BhNFWVi6acXh4r7qD/N6Bvs+9PG0sBFZB1fk2YJR/jFDM0icGNupvDTrynG+PyC191QrPNL+oWZ8mh03hwSRLZrAXOF5y0vI6egBAiGNbR8MYKFRvm9Kd1ixIoTL0GiJB7JoEBbpixgDkLcCkKDB/1lyg2A/irVcsG71Kk3yuzXrUUrk48xAWrG6Nb3GYMHe+IIJMr1B+7Bt1ACkUSmUGl0BpNF72Ple2dNSctw9uy2QQb010NTS9v5R4cfMv4wg8w57kQmpK+FJXgcV1x1zXUkIUIIIYQQQgwvsBAOv6Jv1cLjQwghhBBC6BJ8J3moNOTf6eTydH9AJLwWodMb/I32vgxmYB6svz8kNk3b9cM4zcu67cd53c/7ASAEIyiGEyRFMyzHC6IkK6qmG6ZlO67nB2EUiyeSqXQmm8sXiqVypVqrN5qtdqfb6w+GI4QJZVxIpY31/CCM4iTN8qKsagdN2/XDOM3Luu3Hed3P+/0W0PkQUy6VWFQtJsCgaCYbi52DFyeXuHkQJoqq6YZp2Y7r+UEYxUma5UVZ1U1LGRey64dxmpd124/zugFAEBgChcERSBQag8XhCUTEJKRk5BSUVNQ0tHT0DIxMzCysbOwcnFzz+zlN80FxSb2/CoAIE8q4yKyilNKxECCcUkaY0LBBRhAQxjEVUkUPGZiX3J/aAlyW6VceOSXjQkZ11EAIIYQQQhw1g4kdALIOGXWUCBBgEjpMIXSAGOXiRyPhRgSEybyEe+6P17qgIwUChVTRQy24U2sXY6NPckCa2I1waZ8RNBKQzBpd6AVcK5mxmWFsHr7wCxgXWiqTWwiEUyYkRMk/oQ/LqF9pUZvlq7aYUMb7NL8aIMKEMi6kWp7AVq6JPYZAhGHIkAlJEKZx1+T8ktQqp54RBIQyvjzS5G4HQIRJaocIIbYQCBMKUy6jr3Im9goRMzTvVb7U16S0cdvU6o0AiLA2hOcVAUSYpBYGZVL52NEHEGFCGReZVS6U1DFXEuviRw9AhAllXEilY/4D4KeNVbuS+bVtrOtE1IF20LChDRBhQhkXUmljXX4NQIQJZXyNlfk7vPUbueY6BCPYsOtMbQGBCBNGp8XbGYRxqnRO2eaV6hrL1NxleiI4CCTzEnot+PA0c44xCEQ4YuQxgE3SAxs3EoKrNRftQ34lQIRJaG+N7Kl6zJZxLq9hTgYe/zbJmiNiEjkUePbtS70conUsS/gJcaMiTCjjyyOsy3+/0DPXNieBZaVgE/Caw/Zp/mwFdPwYJLUciIAIUya5Vsb6vFoMGo1jXf4cu7T+Lod4JsLkzj+R2brXQ77BfQVEmHKpbX4dYho+VAEGda1TD4UJZVxIpY11+dsAMOg2A9wCyn547qVeABGmXGqbX42Yhn/MBF2JCBPKuMuuRoQJZVxIpY11+TUQOMRgldTvZV3e3iksfAwARJhQxoVU2liXXwgQYUIZF1JpY11+EUD0yls8CGU8YnQCRJhQxoVU2thvBwA=) format('woff2'); font-weight: normal; font-style: normal; } \ No newline at end of file diff --git a/data/Leipzig.xml b/data/Leipzig.xml index cd3ff7288fe..e9ec64193a3 100644 --- a/data/Leipzig.xml +++ b/data/Leipzig.xml @@ -572,6 +572,7 @@ + diff --git a/data/Leipzig/EBA6.xml b/data/Leipzig/EBA6.xml new file mode 100644 index 00000000000..0c45cc9dca9 --- /dev/null +++ b/data/Leipzig/EBA6.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/doc/diffTests.sh b/doc/diffTests.sh index 2e4513c57e4..1f49b58bb10 100755 --- a/doc/diffTests.sh +++ b/doc/diffTests.sh @@ -30,8 +30,10 @@ then echo "Emptying directories ..." rm $indir1/*/*.png rm $indir1/*/*.svg + rm $indir1/*/*.json rm $indir2/*/*.png rm $indir2/*/*.svg + rm $indir2/*/*.json rm $outdir/*/*.png rm $outdir/index.html fi diff --git a/emscripten/buildToolkit b/emscripten/buildToolkit index 649fb415fa5..b6f20e5a7ae 100755 --- a/emscripten/buildToolkit +++ b/emscripten/buildToolkit @@ -122,6 +122,7 @@ if ($wasmQ) { $LFLAGS .= " -s INITIAL_MEMORY=512MB"; $LFLAGS .= " -s STACK_SIZE=256MB"; $LFLAGS .= " -s SINGLE_FILE=1"; + $LFLAGS .= " -s INCOMING_MODULE_JS_API=onRuntimeInitialized"; $FLAGS_NAME = "-wasm"; } @@ -240,16 +241,17 @@ if ($makeQ) { print "*************\nBuilding makefile...\n"; my $cmakeCmd = "$EMCMAKE cmake ../cmake $cmake -DCMAKE_CXX_FLAGS=\"$FLAGS\""; +print "$cmakeCmd\n" if $CHATTY; system($cmakeCmd) == 0 or die "system $cmakeCmd failed: $?"; print "*************\nCompiling...\n"; my $makeCmd = "$EMMAKE make -j 8"; +print "$makeCmd\n" if $CHATTY; system($makeCmd); print "*************\nLinking...\n"; my $ccCmd = "$EMCC $CHATTY libverovio.a $LFLAGS $FLAGS $embed $exports $extra_exports $output $modularize"; print "$ccCmd\n" if $CHATTY; - system($ccCmd); if ($? == 0) { diff --git a/emscripten/npm/package.json b/emscripten/npm/package.json index 85b665e5169..68404c71027 100644 --- a/emscripten/npm/package.json +++ b/emscripten/npm/package.json @@ -1,6 +1,6 @@ { "name": "verovio", - "version": "3.17.0-alpha", + "version": "4.2.0-alpha", "description": "This is the stable version of the verovio package", "main": "dist/verovio-toolkit-wasm.js", "exports": { diff --git a/fonts/poetry.lock b/fonts/poetry.lock index e7f2ff99d5b..7c516f071b4 100644 --- a/fonts/poetry.lock +++ b/fonts/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "appnope" version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" -category = "dev" optional = false python-versions = "*" files = [ @@ -16,7 +15,6 @@ files = [ name = "astroid" version = "2.14.2" description = "An abstract syntax tree for Python with inference support." -category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -36,7 +34,6 @@ wrapt = [ name = "asttokens" version = "2.2.1" description = "Annotate AST trees with source code positions" -category = "dev" optional = false python-versions = "*" files = [ @@ -54,7 +51,6 @@ test = ["astroid", "pytest"] name = "backcall" version = "0.2.0" description = "Specifications for callback functions passed in to an API" -category = "dev" optional = false python-versions = "*" files = [ @@ -66,7 +62,6 @@ files = [ name = "black" version = "22.12.0" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -102,7 +97,6 @@ uvloop = ["uvloop (>=0.15.2)"] name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -117,7 +111,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -129,7 +122,6 @@ files = [ name = "decorator" version = "5.1.1" description = "Decorators for Humans" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -141,7 +133,6 @@ files = [ name = "dill" version = "0.3.6" description = "serialize all of python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -156,7 +147,6 @@ graph = ["objgraph (>=1.7.2)"] name = "executing" version = "1.2.0" description = "Get the currently executing AST node of a frame, and other information" -category = "dev" optional = false python-versions = "*" files = [ @@ -171,7 +161,6 @@ tests = ["asttokens", "littleutils", "pytest", "rich"] name = "ipython" version = "8.10.0" description = "IPython: Productive Interactive Computing" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -210,7 +199,6 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pa name = "isort" version = "5.12.0" description = "A Python utility / library to sort Python imports." -category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -228,7 +216,6 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "jedi" version = "0.18.2" description = "An autocompletion tool for Python that can be used for text editors." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -248,7 +235,6 @@ testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] name = "lazy-object-proxy" version = "1.9.0" description = "A fast and thorough lazy object proxy." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -294,7 +280,6 @@ files = [ name = "matplotlib-inline" version = "0.1.6" description = "Inline Matplotlib backend for Jupyter" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -309,7 +294,6 @@ traitlets = "*" name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -321,7 +305,6 @@ files = [ name = "mypy" version = "0.971" description = "Optional static typing for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -364,7 +347,6 @@ reports = ["lxml"] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -376,7 +358,6 @@ files = [ name = "numpy" version = "1.24.2" description = "Fundamental package for array computing in Python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -414,7 +395,6 @@ files = [ name = "parso" version = "0.8.3" description = "A Python Parser" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -430,7 +410,6 @@ testing = ["docopt", "pytest (<6.0.0)"] name = "pathspec" version = "0.11.0" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -442,7 +421,6 @@ files = [ name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." -category = "dev" optional = false python-versions = "*" files = [ @@ -457,7 +435,6 @@ ptyprocess = ">=0.5" name = "pickleshare" version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" -category = "dev" optional = false python-versions = "*" files = [ @@ -469,7 +446,6 @@ files = [ name = "platformdirs" version = "3.0.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -485,7 +461,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytes name = "prompt-toolkit" version = "3.0.36" description = "Library for building powerful interactive command lines in Python" -category = "dev" optional = false python-versions = ">=3.6.2" files = [ @@ -500,7 +475,6 @@ wcwidth = "*" name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -512,7 +486,6 @@ files = [ name = "pure-eval" version = "0.2.2" description = "Safely evaluate AST nodes without side effects" -category = "dev" optional = false python-versions = "*" files = [ @@ -525,14 +498,13 @@ tests = ["pytest"] [[package]] name = "pygments" -version = "2.14.0" +version = "2.15.0" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, - {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, + {file = "Pygments-2.15.0-py3-none-any.whl", hash = "sha256:77a3299119af881904cd5ecd1ac6a66214b6e9bed1f2db16993b54adede64094"}, + {file = "Pygments-2.15.0.tar.gz", hash = "sha256:f7e36cffc4c517fbc252861b9a6e4644ca0e5abadf9a113c72d1358ad09b9500"}, ] [package.extras] @@ -542,7 +514,6 @@ plugins = ["importlib-metadata"] name = "pylint" version = "2.16.2" description = "python code static checker" -category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -572,7 +543,6 @@ testutils = ["gitpython (>3)"] name = "scipy" version = "1.9.3" description = "Fundamental algorithms for scientific computing in Python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -611,7 +581,6 @@ test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "sciki name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -623,7 +592,6 @@ files = [ name = "stack-data" version = "0.6.2" description = "Extract data from python stack frames and tracebacks for informative displays" -category = "dev" optional = false python-versions = "*" files = [ @@ -643,7 +611,6 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] name = "svgpathtools" version = "1.6.0" description = "A collection of tools for manipulating and analyzing SVG Path objects and Bezier curves." -category = "main" optional = false python-versions = "*" files = [ @@ -660,7 +627,6 @@ svgwrite = "*" name = "svgwrite" version = "1.4.3" description = "A Python library to create SVG drawings." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -672,7 +638,6 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -684,7 +649,6 @@ files = [ name = "tomlkit" version = "0.11.6" description = "Style preserving TOML library" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -696,7 +660,6 @@ files = [ name = "traitlets" version = "5.9.0" description = "Traitlets Python configuration system" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -712,7 +675,6 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] name = "typing-extensions" version = "4.5.0" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -724,7 +686,6 @@ files = [ name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -736,7 +697,6 @@ files = [ name = "wrapt" version = "1.14.1" description = "Module for decorators, wrappers and monkey patching." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ diff --git a/fonts/supported.xml b/fonts/supported.xml index 859837641f5..ccd9a8d22d7 100644 --- a/fonts/supported.xml +++ b/fonts/supported.xml @@ -2834,7 +2834,7 @@ - + diff --git a/include/hum/.download b/include/hum/.download index ae3293fb191..f7d50d15a27 100755 --- a/include/hum/.download +++ b/include/hum/.download @@ -1,2 +1,2 @@ -wget https://raw.githubusercontent.com/craigsapp/humlib/master/include/humlib.h -O humlib.h +wget https://raw.githubusercontent.com/craigsapp/humlib/master/min/humlib.h -O humlib.h diff --git a/include/hum/humlib.h b/include/hum/humlib.h index 42fea3f0d8d..5223b1a9250 100644 --- a/include/hum/humlib.h +++ b/include/hum/humlib.h @@ -1,9 +1,9 @@ // // Programmer: Craig Stuart Sapp // Creation Date: Sat Aug 8 12:24:49 PDT 2015 -// Last Modified: Sat Apr 15 11:52:53 PDT 2023 -// Filename: humlib.h -// URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h +// Last Modified: Tue Dec 12 11:01:04 PST 2023 +// Filename: min/humlib.h +// URL: https://github.com/craigsapp/humlib/blob/master/min/humlib.h // Syntax: C++11 // vim: ts=3 // @@ -39,17 +39,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef _HUMLIB_H_INCLUDED #define _HUMLIB_H_INCLUDED -#include -#include - #include #include #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -1230,6 +1230,7 @@ class HumdrumLine : public std::string, public HumHash { bool isCommentGlobal (void) const; bool isCommentUniversal (void) const; bool isReference (void) const; + bool isReferenceRecord (void) const { return isReference(); } bool isGlobalReference (void) const; bool isUniversalReference (void) const; bool isSignifier (void) const; @@ -1544,9 +1545,12 @@ class HumdrumToken : public std::string, public HumHash { bool isModernMensurationSymbol (void); bool isOriginalMensuration (void) { return isOriginalMensurationSymbol(); } bool isModernMensuration (void) { return isModernMensurationSymbol(); } - bool isInstrumentDesignation (void); bool isInstrumentName (void); bool isInstrumentAbbreviation (void); + bool isInstrumentDesignation (void); + bool isInstrumentCode (void) { return isInstrumentDesignation(); } + bool isInstrumentClass (void); + bool isInstrumentGroup (void); bool isModernInstrumentName (void); bool isModernInstrumentAbbreviation(void); bool isOriginalInstrumentName (void); @@ -2313,6 +2317,26 @@ std::ostream& operator<<(std::ostream& out, HumdrumFileBase& infile); +////////////////////////////// +// +// HumdrumFileBase::initializeArray -- adjust the size of the input array +// to the same dimensions as the HumdrumFile, filling in each cell of the +// array with the given value as a default. +// + +template +void HumdrumFileBase::initializeArray(std::vector>& array, TYPE value) { + HumdrumFileBase& infile = *this; + array.clear(); + array.resize(infile.getLineCount()); + for (int i=0; i blank // columns 26 - 31: beam codes @@ -3400,7 +3424,7 @@ class MuseRecord : public MuseRecordBasic { int getFigureCount (void); // columns 3 -- 5 ---> blank - + // columns 6 -- 8: figure division pointer advancement (duration) std::string getFigurePointerField (void); int figurePointerQ (void); @@ -4091,6 +4115,9 @@ class Convert { static double coefficientOfVariationPopulation(const std::vector& x); static double nPvi (const std::vector& x); + // instrument related functions defined in Convert-instrument.cpp + static std::vector> getInstrumentList(void); + // Reference record functions defined in Convert-reference.cpp static std::string getReferenceKeyMeaning(HTp token); static std::string getReferenceKeyMeaning(const std::string& token); @@ -4275,6 +4302,9 @@ class MxmlPart { string cleanSpaces (const string& input); bool hasOrnaments (void) const; + vector> getVoiceMapping (void) { return m_voicemapping; }; + vector> getStaffVoiceHist (void) { return m_staffvoicehist; }; + private: void receiveStaffNumberFromChild (int staffnum, int voicenum); @@ -4820,6 +4850,7 @@ class MxmlEvent { void setVoiceNumber (int value); int getStaffNumber (void) const; int getStaffIndex (void) const; + int getCrossStaffOffset(void) const; int getVoiceIndex (int maxvoice = 4) const; void setStaffNumber (int value); measure_event_type getType (void) const; @@ -5243,27 +5274,25 @@ class HumTool : public Options { // #define BASIC_INTERFACE(CLASS) \ -using namespace std; \ -using namespace hum; \ int main(int argc, char** argv) { \ - CLASS interface; \ + hum::CLASS interface; \ if (!interface.process(argc, argv)) { \ - interface.getError(cerr); \ + interface.getError(std::cerr); \ return -1; \ } \ - HumdrumFile infile; \ + hum::HumdrumFile infile; \ if (interface.getArgCount() > 0) { \ infile.readNoRhythm(interface.getArgument(1)); \ } else { \ - infile.readNoRhythm(cin); \ + infile.readNoRhythm(std::cin); \ } \ - int status = interface.run(infile, cout); \ + int status = interface.run(infile, std::cout); \ if (interface.hasWarning()) { \ - interface.getWarning(cerr); \ + interface.getWarning(std::cerr); \ return 0; \ } \ if (interface.hasError()) { \ - interface.getError(cerr); \ + interface.getError(std::cerr); \ return -1; \ } \ interface.finally(); \ @@ -5278,39 +5307,37 @@ int main(int argc, char** argv) { \ // usage implementation). // -#define STREAM_INTERFACE(CLASS) \ -using namespace std; \ -using namespace hum; \ -int main(int argc, char** argv) { \ - CLASS interface; \ - if (!interface.process(argc, argv)) { \ - interface.getError(cerr); \ - return -1; \ - } \ - HumdrumFileStream instream(static_cast(interface)); \ - HumdrumFileSet infiles; \ - bool status = true; \ - while (instream.readSingleSegment(infiles)) { \ - status &= interface.run(infiles); \ - if (interface.hasWarning()) { \ - interface.getWarning(cerr); \ - } \ - if (interface.hasAnyText()) { \ - interface.getAllText(cout); \ - } \ - if (interface.hasError()) { \ - interface.getError(cerr); \ - return -1; \ - } \ - if (!interface.hasAnyText()) { \ - for (int i=0; i(interface)); \ + hum::HumdrumFileSet infiles; \ + bool status = true; \ + while (instream.readSingleSegment(infiles)) { \ + status &= interface.run(infiles); \ + if (interface.hasWarning()) { \ + interface.getWarning(std::cerr); \ + } \ + if (interface.hasAnyText()) { \ + interface.getAllText(std::cout); \ + } \ + if (interface.hasError()) { \ + interface.getError(std::cerr); \ + return -1; \ + } \ + if (!interface.hasAnyText()) { \ + for (int i=0; i(interface)); \ - bool status = interface.run(instream); \ - if (interface.hasWarning()) { \ - interface.getWarning(cerr); \ - } \ - if (interface.hasAnyText()) { \ - interface.getAllText(cout); \ - } \ - if (interface.hasError()) { \ - interface.getError(cerr); \ - return -1; \ - } \ - interface.finally(); \ - interface.clearOutput(); \ - return !status; \ +#define RAW_STREAM_INTERFACE(CLASS) \ +int main(int argc, char** argv) { \ + hum::CLASS interface; \ + if (!interface.process(argc, argv)) { \ + interface.getError(std::cerr); \ + return -1; \ + } \ + hum::HumdrumFileStream instream(static_cast(interface)); \ + bool status = interface.run(instream); \ + if (interface.hasWarning()) { \ + interface.getWarning(std::cerr); \ + } \ + if (interface.hasAnyText()) { \ + interface.getAllText(std::cout); \ + } \ + if (interface.hasError()) { \ + interface.getError(std::cerr); \ + return -1; \ + } \ + interface.finally(); \ + interface.clearOutput(); \ + return !status; \ } @@ -5356,37 +5381,35 @@ int main(int argc, char** argv) { \ // usage implementation). // -#define SET_INTERFACE(CLASS) \ -using namespace std; \ -using namespace hum; \ -int main(int argc, char** argv) { \ - CLASS interface; \ - if (!interface.process(argc, argv)) { \ - interface.getError(cerr); \ - return -1; \ - } \ - HumdrumFileStream instream(static_cast(interface)); \ - HumdrumFileSet infiles; \ - instream.read(infiles); \ - bool status = interface.run(infiles); \ - if (interface.hasWarning()) { \ - interface.getWarning(cerr); \ - } \ - if (interface.hasAnyText()) { \ - interface.getAllText(cout); \ - } \ - if (interface.hasError()) { \ - interface.getError(cerr); \ - return -1; \ - } \ - if (!interface.hasAnyText()) { \ - for (int i=0; i(interface)); \ + hum::HumdrumFileSet infiles; \ + instream.read(infiles); \ + bool status = interface.run(infiles); \ + if (interface.hasWarning()) { \ + interface.getWarning(std::cerr); \ + } \ + if (interface.hasAnyText()) { \ + interface.getAllText(std::cout); \ + } \ + if (interface.hasError()) { \ + interface.getError(std::cerr); \ + return -1; \ + } \ + if (!interface.hasAnyText()) { \ + for (int i=0; i> m_instrumentList; + bool m_fixQ = false; // used with -f option: fix incorrect instrument classes + + +}; + + class Tool_autoaccid : public HumTool { public: Tool_autoaccid (void); @@ -6094,7 +6146,7 @@ class Tool_cmr : public HumTool { void getPartNames (std::vector& partNames, HumdrumFile& infile); void checkForCmr (int index, int direction, HumdrumFile& infile); bool hasHigher (int pitch, int tolerance, - std::vector& midinums, + std::vector& midinums, std::vector>& notelist, int index1, int index2); bool hasGroupUp (void); @@ -6208,39 +6260,6 @@ class Tool_colorgroups : public HumTool { }; -class Tool_colorthirds : public HumTool { - public: - Tool_colorthirds (void); - ~Tool_colorthirds () {}; - - bool run (HumdrumFileSet& infiles); - bool run (HumdrumFile& infile); - bool run (const string& indata, ostream& out); - bool run (HumdrumFile& infile, ostream& out); - - protected: - void initialize (void); - void processFile (HumdrumFile& infile); - std::vector getMidiNotes(std::vector& kernNotes); - std::vector getChordPositions(std::vector& midiNotes); - void labelChordPositions(std::vector& kernNotes, std::vector& chordPositions); - - private: - std::string m_root_marker = "@"; - std::string m_third_marker = "N"; - std::string m_fifth_marker = "Z"; - - std::string m_root_color = "crimson"; - std::string m_third_color = "limegreen"; - std::string m_fifth_color = "royalblue"; - - bool m_colorThirds = true; - bool m_colorFifths = true; - bool m_colorTriads = true; - -}; - - class Tool_colortriads : public HumTool { public: Tool_colortriads (void); @@ -6454,10 +6473,11 @@ class Tool_composite : public HumTool { int m_groupAssignmentIndex = 0; int m_verseLabelIndex = 0; - int m_coincidenceEventCount = -1; - int m_fullCompositeEventCount = -1; - int m_groupAEventCount = -1; - int m_groupBEventCount = -1; + // analytic counts: + int m_coincidenceEventCount = -1; // number of events in coincidence + int m_fullCompositeEventCount = -1; // number of events in full composite rhythm + int m_groupAEventCount = -1; // number of events in group A composite rhythm + int m_groupBEventCount = -1; // number of events in group B composite rhythm double m_scoreSize = 100.0; double m_analysisSize = 100.0; @@ -6817,7 +6837,7 @@ class Tool_deg : public HumTool { // m_insertTracks: matches to m_degSpines first dimension. // It gives the track number for spines before which the corresponding // m_degSpine[x] spine should be inserted. A -1 value at the last - // position in m_insertTracks means append the **deg spine at the + // position in m_insertTracks means append the **deg spine at the // end of the line. std::vector m_insertTracks; @@ -7124,7 +7144,7 @@ class Tool_esac2hum : public HumTool { void getLyrics (vector& lyrics, const string& buffer); void cleanupLyrics (vector& lyrics); bool getFileContents (vector& array, const string& filename); - void chopExtraInfo (char* holdbuffer); + void chopExtraInfo (string& buffer); void printHumdrumHeaderInfo(ostream& out, vector& song); void printHumdrumFooterInfo(ostream& out, vector& song); @@ -7275,7 +7295,7 @@ class Tool_extract : public HumTool { class FiguredBassNumber { public: - FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack, bool intervallsatz); + FiguredBassNumber(int num, string accid, bool showAccid, int voiceIndex, int lineIndex, bool isAttack, bool intervallsatz, string intervalQuality, bool hint); std::string toString(bool nonCompoundIntervalsQ, bool noAccidentalsQ, bool hideThreeQ); int getNumberWithinOctave(void); @@ -7288,6 +7308,8 @@ class FiguredBassNumber { bool m_isAttack; bool m_convert2To9 = false; bool m_intervallsatz = false; + std::string m_intervalQuality; + bool m_hint = false; }; @@ -7300,7 +7322,7 @@ class FiguredBassAbbreviationMapping { // String to compare the numbers with // e.g. "6 4 3" // Sorted by size, larger numbers first - string m_str; + string m_str; // Figured bass number as int vector m_numbers; @@ -7334,6 +7356,7 @@ class Tool_fb : public HumTool { string getNumberString (vector numbers); string getKeySignature (HumdrumFile& infile, int lineIndex); int getLowestBase40Pitch (vector base40Pitches); + string getIntervalQuality (int basePitchBase40, int targetPitchBase40); private: @@ -7351,6 +7374,7 @@ class Tool_fb : public HumTool { bool m_showNegativeQ = false; bool m_aboveQ = false; string m_rateQ = ""; + bool m_hintQ = false; string m_spineTracks = ""; // used with -s option string m_kernTracks = ""; // used with -k option @@ -7800,7 +7824,7 @@ class Tool_humtr : public HumTool { public: Tool_humtr (void); ~Tool_humtr () {}; - + bool run (HumdrumFileSet& infiles); bool run (HumdrumFile& infile); bool run (const std::string& indata, ostream& out); @@ -7922,16 +7946,32 @@ class Tool_kern2mens : public HumTool { bool run (HumdrumFile& infile, ostream& out); protected: - void convertToMens (HumdrumFile& infile); - string convertKernTokenToMens (HTp token); - void printBarline (HumdrumFile& infile, int line); + void convertToMens (HumdrumFile& infile); + std::string convertKernTokenToMens(HTp token); + void printBarline (HumdrumFile& infile, int line); + std::string getClefConversion (HTp token); + void storeKernEditorialAccidental(HumdrumFile& infile); + void storeKernTerminalLong (HumdrumFile& infile); + void addVerovioStyling (HumdrumFile& infile); + void analyzeColoration (HumdrumFile& infile); + void analyzeColoration (HTp infile); private: - bool m_numbersQ = true; // used with -N option - bool m_measuresQ = true; // used with -M option - bool m_invisibleQ = true; // used with -I option - bool m_doublebarQ = true; // used with -D option - string m_clef; // used with -c option + bool m_numbersQ = true; // used with -N option + bool m_measuresQ = true; // used with -M option + bool m_invisibleQ = true; // used with -I option + bool m_doublebarQ = true; // used with -D option + bool m_noverovioQ = false; // used with -V option + bool m_evenNoteSpacingQ = false; // used with -e option + std::string m_clef; // used with -c option + + std::string m_kernEditorialAccidental; // used with !!!RDF**kern: + int m_kernEdAccLineIndex = -1; + std::string m_mensEdAccLine; + + std::string m_kernTerminalLong; // used with !!!RDF**kern: + int m_kernTerminalLongIndex = -1; + std::string m_mensTerminalLongLine; }; @@ -8352,6 +8392,7 @@ class Tool_mens2kern : public HumTool { int brevis_def, int semibrevis_def); void getMensuralInfo (HTp token, int& maximodus, int& modus, int& tempus, int& prolatio); + std::string getClefConversion(HTp token); private: bool m_debugQ; @@ -8360,6 +8401,62 @@ class Tool_mens2kern : public HumTool { }; +class Tool_meter : public HumTool { + + public: + Tool_meter (void); + ~Tool_meter () {}; + + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, std::ostream& out); + bool run (HumdrumFile& infile, std::ostream& out); + + + protected: + void initialize (void); + void processFile (HumdrumFile& infile); + void getMeterData (HumdrumFile& infile); + void processLine (HumdrumLine& line, + std::vector& curNum, + std::vector& curDen, + std::vector& curBeat, + std::vector& curBarTime); + void printMeterData (HumdrumFile& infile); + void printHumdrumLine (HumdrumLine& line, bool printLabels); + int printKernAndAnalysisSpine(HumdrumLine& line, int index, bool printLabels, bool forceInterpretation = false); + HumNum getHumNum (HTp token, const std::string& parameter); + std::string getHumNumString(HumNum input); + bool searchForLabels (HumdrumLine& line); + void printLabelLine (HumdrumLine& line); + void analyzePickupMeasures(HumdrumFile& infile); + void analyzePickupMeasures(HTp sstart); + HumNum getTimeSigDuration(HTp tsig); + void markPickupContent (HTp stok, HTp etok); + + private: + + bool m_commaQ = false; + bool m_debugQ = false; + bool m_denominatorQ = false; + bool m_eighthQ = false; + bool m_floatQ = false; + bool m_halfQ = false; + bool m_joinQ = false; + bool m_nobeatQ = false; + bool m_nolabelQ = false; + bool m_numeratorQ = false; + bool m_quarterQ = false; + bool m_restQ = false; + bool m_sixteenthQ = false; + bool m_tsigQ = false; + bool m_wholeQ = false; + bool m_zeroQ = false; + int m_digits = 0; + +}; + + class Tool_metlev : public HumTool { public: Tool_metlev (void); @@ -8545,7 +8642,7 @@ class SonorityNoteData { break; } } - + bool hasAccidental(void) { // Set only with setText() input. return m_accidentalQ; @@ -8942,6 +9039,7 @@ class Tool_musicxml2hum : public HumTool { std::vector& nowevents, HumNum nowtime, std::vector& partdata); + void handleFiguredBassWithoutNonZeroEvent (std::vector& nowevents, HumNum nowtime); void appendNonZeroEvents (GridMeasure* outdata, std::vector& nowevents, HumNum nowtime, @@ -9080,12 +9178,14 @@ class Tool_musicxml2hum : public HumTool { bool m_stemsQ = false; int m_slurabove = 0; int m_slurbelow = 0; + int m_staffabove = 0; + int m_staffbelow = 0; char m_hasEditorial = '\0'; bool m_hasOrnamentsQ = false; int m_maxstaff = 0; std::vector> m_last_ottava_direction; std::vector offsetHarmony; - std::vector offsetFiguredBass; + std::vector m_offsetFiguredBass; std::vector m_stop_char; // RDF indications in **kern data: @@ -9098,7 +9198,7 @@ class Tool_musicxml2hum : public HumTool { std::vector> m_current_brackets; std::map m_bracket_type_buffer; std::vector> m_used_hairpins; - std::vector m_current_figured_bass; + std::vector> m_current_figured_bass; std::vector> m_current_text; std::vector> m_current_tempo; @@ -9293,6 +9393,74 @@ class Tool_myank : public HumTool { }; +class Tool_nproof : public HumTool { + + public: + Tool_nproof (void); + ~Tool_nproof () {}; + + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, std::ostream& out); + bool run (HumdrumFile& infile, std::ostream& out); + + void checkForBlankLines(HumdrumFile& infile); + void checkInstrumentInformation(HumdrumFile& infile); + void checkKeyInformation(HumdrumFile& infile); + void checkSpineTerminations(HumdrumFile& infile); + void checkForValidInstrumentCode(HTp token, vector>& instrumentList); + void checkReferenceRecords(HumdrumFile& infile); + + protected: + void initialize (void); + void processFile (HumdrumFile& infile); + + private: + int m_errorCount = 0; + std::string m_errorList; + std::string m_errorHtml; + + bool m_noblankQ = false; + bool m_noinstrumentQ = false; + bool m_nokeyQ = false; + bool m_noreferenceQ = false; + bool m_noterminationQ = false; + + bool m_fileQ = false; + bool m_rawQ = false; + +}; + + +class Tool_ordergps : public HumTool { + public: + Tool_ordergps (void); + ~Tool_ordergps () {}; + + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, ostream& out); + bool run (HumdrumFile& infile, ostream& out); + + protected: + void initialize (void); + void processFile (HumdrumFile& infile); + void printStaffLine (HumdrumFile& infile); + void printFile (HumdrumFile& infile, int gindex, int pindex, int sindex); + void printFileTop (HumdrumFile& infile, int gindex, int pindex, int sindex); + + private: + bool m_emptyQ = false; + bool m_fileQ = false; + bool m_listQ = false; + bool m_problemQ = false; + bool m_reverseQ = false; + bool m_staffQ = false; + bool m_topQ = false; + +}; + + class Tool_pccount : public HumTool { public: @@ -9428,6 +9596,38 @@ class Tool_phrase : public HumTool { +class Tool_pline : public HumTool { + public: + Tool_pline (void); + ~Tool_pline () {}; + + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, ostream& out); + bool run (HumdrumFile& infile, ostream& out); + + + protected: + void initialize (void); + void processFile (HumdrumFile& infile); + void getPlineInterpretations(HumdrumFile& infile, vector& tokens); + void plineToColor (HumdrumFile& infile, vector& tokens); + void markRests (HumdrumFile& infile); + void markSpineRests (HTp spineStop); + void fillLineInfo (HumdrumFile& infile, std::vector>& lineInfo); + + private: + bool m_colorQ = false; // used with -c option + // bool m_overlapQ = false; // used with -o option + + std::vector m_colors; + std::vector m_ptokens; + std::vector> m_lineInfo; + + +}; + + class Tool_pnum : public HumTool { public: Tool_pnum (void); @@ -10084,6 +10284,58 @@ class Tool_tassoize : public HumTool { }; +class Tool_textdur : public HumTool { + public: + Tool_textdur (void); + ~Tool_textdur () {}; + + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, ostream& out); + bool run (HumdrumFile& infile, ostream& out); + + + protected: + void initialize (void); + void processFile (HumdrumFile& infile); + void printMelismas (HumdrumFile& infile); + void printDurations (HumdrumFile& infile); + void getTextSpineStarts(HumdrumFile& infile, vector& starts); + void processTextSpine (vector& starts, int index); + int getMelisma (HTp tok1, HTp tok2); + HumNum getDuration (HTp tok1, HTp tok2); + HTp getTandemKernToken(HTp token); + void printInterleaved (HumdrumFile& infile); + void printInterleavedLine(HumdrumLine& line, vector& textTrack); + void printTokenAnalysis(HTp token); + void printAnalysis (void); + void printDurationAverage(void); + void printMelismaAverage(void); + void printHtmlContent (void); + void printMelismaHtmlHistogram(void); + void printMelismaHtmlHistogram(int index, int maxVal); + void printDurationHtmlHistogram(void); + void fillInstrumentNameInfo(void); + std::string getColumnName (HTp token); + + private: + std::vector m_textStarts; + std::vector m_track2column; + std::vector m_columnName; + + std::vector> m_syllables; // List of syllables in **text/**sylba + std::vector> m_durations; // List of durations excluding trailing rests + std::vector> m_melismas; // List of note counts for syllable + + bool m_analysisQ = false; // used with -a option + bool m_melismaQ = false; // used with -m option + bool m_durationQ = true; // used with -m, -d option + bool m_interleaveQ = false; // used with -i option + HumNum m_RhythmFactor = 1; // uwed with -1, -2, -8, and later -f # + +}; + + class Tool_thru : public HumTool { public: Tool_thru (void); @@ -10344,6 +10596,105 @@ class Tool_trillspell : public HumTool { +class Tool_tspos : public HumTool { + public: + Tool_tspos (void); + ~Tool_tspos () {}; + + bool run (HumdrumFileSet& infiles); + bool run (HumdrumFile& infile); + bool run (const string& indata, ostream& out); + bool run (HumdrumFile& infile, ostream& out); + + protected: + void initialize (HumdrumFile& infile); + void processFile (HumdrumFile& infile); + std::vector getMidiNotes(std::vector& kernNotes); + std::vector getChordPositions(std::vector& midiNotes); + std::vector getNoteMods(std::vector& midiNotes); + std::vector getThirds(std::vector& midiNotes); + std::vector getFifths(std::vector& midiNotes); + void labelChordPositions(std::vector& kernNotes, std::vector& chordPositions); + void labelThirds(std::vector& kernNotes, std::vector& thirdPositions); + void labelFifths(std::vector& kernNotes, std::vector& fifthPositions); + void keepOnlyDoubles(std::vector& output); + void checkForTriadicSonority(std::vector& positions, int line); + std::string generateStatistics(HumdrumFile& infile); + std::vector getTrackNames(HumdrumFile& infile); + int getVectorSum(std::vector& input); + void analyzeVoiceCount(HumdrumFile& infile); + int countVoicesOnLine(HumdrumFile& infile, int line); + std::string generateTable(HumdrumFile& infile, std::vector& name); + bool hasFullTriadAttack(HumdrumLine& line); + void avoidRdfCollisions(HumdrumFile& infile); + void printUsedMarkers(void); + std::string makeOpacityColor(std::string& color, double value, double total); + int getToolCounter(HumdrumFile& infile); + std::string makePercentString(double value, double total, int digits); + + private: + std::string m_root_marker = "@"; + std::string m_third_marker = "N"; + std::string m_fifth_marker = "Z"; + std::string m_3rd_root_marker = "j"; + std::string m_3rd_third_marker = "l"; + std::string m_5th_root_marker = "V"; + std::string m_5th_fifth_marker = "|"; + + std::vector m_used_markers; + + std::string m_root_color = "#DC143C"; // crimson + std::string m_third_color = "#32CD32"; // limegreen + std::string m_fifth_color = "#4169E1"; // royalblue + std::string m_3rd_root_color = "#8B0000"; // darkred + std::string m_3rd_third_color = "#008000"; // green + std::string m_5th_root_color = "#8B0000"; // darkred + std::string m_5th_fifth_color = "#4682B4"; // steelblue + + bool m_colorThirds = true; // used with -3 option (to negate) + bool m_colorFifths = true; // used with -5 option (to negate) + bool m_colorTriads = true; // used with -T option (to negate) + bool m_doubleQ = false; // used with -d option + + bool m_topQ = false; // used with --top option + bool m_tableQ = false; // used with -t option + bool m_triadAttack = false; // used with -x option + + // Statistical data variables: + vector m_triadState; + + // m_partTriadPositions -- count the number of chordal positions by + // voice. The first dimention is the track number of the part, and + // the second dimension is the counts for 7 categories: + // 0 = count of root positions in full triadic chords + // 1 = count of third positions in full triadic chords + // 2 = count of fifth positions in full triadic chords + // 3 = count of root positions in partial triadic chords ("open thirds") + // 4 = count of third positions in partial triadic chords + // 5 = count of root positions in partial triadic chords ("open fifths") + // 6 = count of fifth positions in partial triadic chords + std::vector> m_partTriadPositions; + int m_positionCount = 7; // entries in 2nd dim. of m_partTriadPositions + + string m_toolName = "tspos"; + + std::vector m_voiceCount; + // m_voice: used with -v option to limit analysis to sonorities that + // have the given voice count. 0 means analyze any voice counts. + int m_voice = 0; + + bool m_compressedQ = false; + + bool m_minorQ = true; + bool m_majorQ = true; + + bool m_questionQ = true; + int m_toolCount = 0; + + std::vector m_fullNames; +}; + + } // end of namespace hum diff --git a/include/pugi/pugiconfig.hpp b/include/pugi/pugiconfig.hpp index 77496aefe7c..3dc839da6ec 100644 --- a/include/pugi/pugiconfig.hpp +++ b/include/pugi/pugiconfig.hpp @@ -1,77 +1,77 @@ -/** - * pugixml parser - version 1.13 - * -------------------------------------------------------- - * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at https://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef HEADER_PUGICONFIG_HPP -#define HEADER_PUGICONFIG_HPP - -// Uncomment this to enable wchar_t mode -// #define PUGIXML_WCHAR_MODE - -// Uncomment this to enable compact mode -// #define PUGIXML_COMPACT - -// Uncomment this to disable XPath -// #define PUGIXML_NO_XPATH - -// Uncomment this to disable STL -// #define PUGIXML_NO_STL - -// Uncomment this to disable exceptions -// #define PUGIXML_NO_EXCEPTIONS - -// Set this to control attributes for public classes/functions, i.e.: -// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL -// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL -// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall -// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead - -// Tune these constants to adjust memory-related behavior -// #define PUGIXML_MEMORY_PAGE_SIZE 32768 -// #define PUGIXML_MEMORY_OUTPUT_STACK 10240 -// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 - -// Tune this constant to adjust max nesting for XPath queries -// #define PUGIXML_XPATH_DEPTH_LIMIT 1024 - -// Uncomment this to switch to header-only version -// #define PUGIXML_HEADER_ONLY - -// Uncomment this to enable long long support -// #define PUGIXML_HAS_LONG_LONG - -#endif - -/** - * Copyright (c) 2006-2022 Arseny Kapoulkine - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ +/** + * pugixml parser - version 1.14 + * -------------------------------------------------------- + * Copyright (C) 2006-2023, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef HEADER_PUGICONFIG_HPP +#define HEADER_PUGICONFIG_HPP + +// Uncomment this to enable wchar_t mode +// #define PUGIXML_WCHAR_MODE + +// Uncomment this to enable compact mode +// #define PUGIXML_COMPACT + +// Uncomment this to disable XPath +// #define PUGIXML_NO_XPATH + +// Uncomment this to disable STL +// #define PUGIXML_NO_STL + +// Uncomment this to disable exceptions +// #define PUGIXML_NO_EXCEPTIONS + +// Set this to control attributes for public classes/functions, i.e.: +// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL +// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL +// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall +// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead + +// Tune these constants to adjust memory-related behavior +// #define PUGIXML_MEMORY_PAGE_SIZE 32768 +// #define PUGIXML_MEMORY_OUTPUT_STACK 10240 +// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 + +// Tune this constant to adjust max nesting for XPath queries +// #define PUGIXML_XPATH_DEPTH_LIMIT 1024 + +// Uncomment this to switch to header-only version +// #define PUGIXML_HEADER_ONLY + +// Uncomment this to enable long long support +// #define PUGIXML_HAS_LONG_LONG + +#endif + +/** + * Copyright (c) 2006-2023 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/include/pugi/pugixml.hpp b/include/pugi/pugixml.hpp index 59c0c58641e..d17a7e6930e 100644 --- a/include/pugi/pugixml.hpp +++ b/include/pugi/pugixml.hpp @@ -1,1506 +1,1516 @@ -/** - * pugixml parser - version 1.13 - * -------------------------------------------------------- - * Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at https://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons -// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits -#ifndef PUGIXML_VERSION -# define PUGIXML_VERSION 1130 // 1.13 -#endif - -// Include user configuration file (this can define various configuration macros) -#include "pugiconfig.hpp" - -#ifndef HEADER_PUGIXML_HPP -#define HEADER_PUGIXML_HPP - -// Include stddef.h for size_t and ptrdiff_t -#include - -// Include exception header for XPath -#if !defined(PUGIXML_NO_XPATH) && !defined(PUGIXML_NO_EXCEPTIONS) -# include -#endif - -// Include STL headers -#ifndef PUGIXML_NO_STL -# include -# include -# include -#endif - -// Macro for deprecated features -#ifndef PUGIXML_DEPRECATED -# if defined(__GNUC__) -# define PUGIXML_DEPRECATED __attribute__((deprecated)) -# elif defined(_MSC_VER) && _MSC_VER >= 1300 -# define PUGIXML_DEPRECATED __declspec(deprecated) -# else -# define PUGIXML_DEPRECATED -# endif -#endif - -// If no API is defined, assume default -#ifndef PUGIXML_API -# define PUGIXML_API -#endif - -// If no API for classes is defined, assume default -#ifndef PUGIXML_CLASS -# define PUGIXML_CLASS PUGIXML_API -#endif - -// If no API for functions is defined, assume default -#ifndef PUGIXML_FUNCTION -# define PUGIXML_FUNCTION PUGIXML_API -#endif - -// If the platform is known to have long long support, enable long long functions -#ifndef PUGIXML_HAS_LONG_LONG -# if __cplusplus >= 201103 -# define PUGIXML_HAS_LONG_LONG -# elif defined(_MSC_VER) && _MSC_VER >= 1400 -# define PUGIXML_HAS_LONG_LONG -# endif -#endif - -// If the platform is known to have move semantics support, compile move ctor/operator implementation -#ifndef PUGIXML_HAS_MOVE -# if __cplusplus >= 201103 -# define PUGIXML_HAS_MOVE -# elif defined(_MSC_VER) && _MSC_VER >= 1600 -# define PUGIXML_HAS_MOVE -# endif -#endif - -// If C++ is 2011 or higher, add 'noexcept' specifiers -#ifndef PUGIXML_NOEXCEPT -# if __cplusplus >= 201103 -# define PUGIXML_NOEXCEPT noexcept -# elif defined(_MSC_VER) && _MSC_VER >= 1900 -# define PUGIXML_NOEXCEPT noexcept -# else -# define PUGIXML_NOEXCEPT -# endif -#endif - -// Some functions can not be noexcept in compact mode -#ifdef PUGIXML_COMPACT -# define PUGIXML_NOEXCEPT_IF_NOT_COMPACT -#else -# define PUGIXML_NOEXCEPT_IF_NOT_COMPACT PUGIXML_NOEXCEPT -#endif - -// If C++ is 2011 or higher, add 'override' qualifiers -#ifndef PUGIXML_OVERRIDE -# if __cplusplus >= 201103 -# define PUGIXML_OVERRIDE override -# elif defined(_MSC_VER) && _MSC_VER >= 1700 -# define PUGIXML_OVERRIDE override -# else -# define PUGIXML_OVERRIDE -# endif -#endif - -// If C++ is 2011 or higher, use 'nullptr' -#ifndef PUGIXML_NULL -# if __cplusplus >= 201103 -# define PUGIXML_NULL nullptr -# elif defined(_MSC_VER) && _MSC_VER >= 1600 -# define PUGIXML_NULL nullptr -# else -# define PUGIXML_NULL 0 -# endif -#endif - -// Character interface macros -#ifdef PUGIXML_WCHAR_MODE -# define PUGIXML_TEXT(t) L ## t -# define PUGIXML_CHAR wchar_t -#else -# define PUGIXML_TEXT(t) t -# define PUGIXML_CHAR char -#endif - -namespace pugi -{ - // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE - typedef PUGIXML_CHAR char_t; - -#ifndef PUGIXML_NO_STL - // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE - typedef std::basic_string, std::allocator > string_t; -#endif -} - -// The PugiXML namespace -namespace pugi -{ - // Tree node types - enum xml_node_type - { - node_null, // Empty (null) node handle - node_document, // A document tree's absolute root - node_element, // Element tag, i.e. '' - node_pcdata, // Plain character data, i.e. 'text' - node_cdata, // Character data, i.e. '' - node_comment, // Comment tag, i.e. '' - node_pi, // Processing instruction, i.e. '' - node_declaration, // Document declaration, i.e. '' - node_doctype // Document type declaration, i.e. '' - }; - - // Parsing options - - // Minimal parsing mode (equivalent to turning all other flags off). - // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed. - const unsigned int parse_minimal = 0x0000; - - // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default. - const unsigned int parse_pi = 0x0001; - - // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default. - const unsigned int parse_comments = 0x0002; - - // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default. - const unsigned int parse_cdata = 0x0004; - - // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree. - // This flag is off by default; turning it on usually results in slower parsing and more memory consumption. - const unsigned int parse_ws_pcdata = 0x0008; - - // This flag determines if character and entity references are expanded during parsing. This flag is on by default. - const unsigned int parse_escapes = 0x0010; - - // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default. - const unsigned int parse_eol = 0x0020; - - // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default. - const unsigned int parse_wconv_attribute = 0x0040; - - // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default. - const unsigned int parse_wnorm_attribute = 0x0080; - - // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default. - const unsigned int parse_declaration = 0x0100; - - // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default. - const unsigned int parse_doctype = 0x0200; - - // This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only - // of whitespace is added to the DOM tree. - // This flag is off by default; turning it on may result in slower parsing and more memory consumption. - const unsigned int parse_ws_pcdata_single = 0x0400; - - // This flag determines if leading and trailing whitespace is to be removed from plain character data. This flag is off by default. - const unsigned int parse_trim_pcdata = 0x0800; - - // This flag determines if plain character data that does not have a parent node is added to the DOM tree, and if an empty document - // is a valid document. This flag is off by default. - const unsigned int parse_fragment = 0x1000; - - // This flag determines if plain character data is be stored in the parent element's value. This significantly changes the structure of - // the document; this flag is only recommended for parsing documents with many PCDATA nodes in memory-constrained environments. - // This flag is off by default. - const unsigned int parse_embed_pcdata = 0x2000; - - // The default parsing mode. - // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, - // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. - const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol; - - // The full parsing mode. - // Nodes of all types are added to the DOM tree, character/reference entities are expanded, - // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. - const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype; - - // These flags determine the encoding of input data for XML document - enum xml_encoding - { - encoding_auto, // Auto-detect input encoding using BOM or < / class xml_object_range - { - public: - typedef It const_iterator; - typedef It iterator; - - xml_object_range(It b, It e): _begin(b), _end(e) - { - } - - It begin() const { return _begin; } - It end() const { return _end; } - - bool empty() const { return _begin == _end; } - - private: - It _begin, _end; - }; - - // Writer interface for node printing (see xml_node::print) - class PUGIXML_CLASS xml_writer - { - public: - virtual ~xml_writer() {} - - // Write memory chunk into stream/file/whatever - virtual void write(const void* data, size_t size) = 0; - }; - - // xml_writer implementation for FILE* - class PUGIXML_CLASS xml_writer_file: public xml_writer - { - public: - // Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio - xml_writer_file(void* file); - - virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; - - private: - void* file; - }; - - #ifndef PUGIXML_NO_STL - // xml_writer implementation for streams - class PUGIXML_CLASS xml_writer_stream: public xml_writer - { - public: - // Construct writer from an output stream object - xml_writer_stream(std::basic_ostream >& stream); - xml_writer_stream(std::basic_ostream >& stream); - - virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; - - private: - std::basic_ostream >* narrow_stream; - std::basic_ostream >* wide_stream; - }; - #endif - - // A light-weight handle for manipulating attributes in DOM tree - class PUGIXML_CLASS xml_attribute - { - friend class xml_attribute_iterator; - friend class xml_node; - - private: - xml_attribute_struct* _attr; - - typedef void (*unspecified_bool_type)(xml_attribute***); - - public: - // Default constructor. Constructs an empty attribute. - xml_attribute(); - - // Constructs attribute from internal pointer - explicit xml_attribute(xml_attribute_struct* attr); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators (compares wrapped attribute pointers) - bool operator==(const xml_attribute& r) const; - bool operator!=(const xml_attribute& r) const; - bool operator<(const xml_attribute& r) const; - bool operator>(const xml_attribute& r) const; - bool operator<=(const xml_attribute& r) const; - bool operator>=(const xml_attribute& r) const; - - // Check if attribute is empty - bool empty() const; - - // Get attribute name/value, or "" if attribute is empty - const char_t* name() const; - const char_t* value() const; - - // Get attribute value, or the default value if attribute is empty - const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; - - // Get attribute value as a number, or the default value if conversion did not succeed or attribute is empty - int as_int(int def = 0) const; - unsigned int as_uint(unsigned int def = 0) const; - double as_double(double def = 0) const; - float as_float(float def = 0) const; - - #ifdef PUGIXML_HAS_LONG_LONG - long long as_llong(long long def = 0) const; - unsigned long long as_ullong(unsigned long long def = 0) const; - #endif - - // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty - bool as_bool(bool def = false) const; - - // Set attribute name/value (returns false if attribute is empty or there is not enough memory) - bool set_name(const char_t* rhs); - bool set_value(const char_t* rhs, size_t sz); - bool set_value(const char_t* rhs); - - // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") - bool set_value(int rhs); - bool set_value(unsigned int rhs); - bool set_value(long rhs); - bool set_value(unsigned long rhs); - bool set_value(double rhs); - bool set_value(double rhs, int precision); - bool set_value(float rhs); - bool set_value(float rhs, int precision); - bool set_value(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - bool set_value(long long rhs); - bool set_value(unsigned long long rhs); - #endif - - // Set attribute value (equivalent to set_value without error checking) - xml_attribute& operator=(const char_t* rhs); - xml_attribute& operator=(int rhs); - xml_attribute& operator=(unsigned int rhs); - xml_attribute& operator=(long rhs); - xml_attribute& operator=(unsigned long rhs); - xml_attribute& operator=(double rhs); - xml_attribute& operator=(float rhs); - xml_attribute& operator=(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - xml_attribute& operator=(long long rhs); - xml_attribute& operator=(unsigned long long rhs); - #endif - - // Get next/previous attribute in the attribute list of the parent node - xml_attribute next_attribute() const; - xml_attribute previous_attribute() const; - - // Get hash value (unique for handles to the same object) - size_t hash_value() const; - - // Get internal pointer - xml_attribute_struct* internal_object() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs); -#endif - - // A light-weight handle for manipulating nodes in DOM tree - class PUGIXML_CLASS xml_node - { - friend class xml_attribute_iterator; - friend class xml_node_iterator; - friend class xml_named_node_iterator; - - protected: - xml_node_struct* _root; - - typedef void (*unspecified_bool_type)(xml_node***); - - public: - // Default constructor. Constructs an empty node. - xml_node(); - - // Constructs node from internal pointer - explicit xml_node(xml_node_struct* p); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators (compares wrapped node pointers) - bool operator==(const xml_node& r) const; - bool operator!=(const xml_node& r) const; - bool operator<(const xml_node& r) const; - bool operator>(const xml_node& r) const; - bool operator<=(const xml_node& r) const; - bool operator>=(const xml_node& r) const; - - // Check if node is empty. - bool empty() const; - - // Get node type - xml_node_type type() const; - - // Get node name, or "" if node is empty or it has no name - const char_t* name() const; - - // Get node value, or "" if node is empty or it has no value - // Note: For text node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes. - const char_t* value() const; - - // Get attribute list - xml_attribute first_attribute() const; - xml_attribute last_attribute() const; - - // Get children list - xml_node first_child() const; - xml_node last_child() const; - - // Get next/previous sibling in the children list of the parent node - xml_node next_sibling() const; - xml_node previous_sibling() const; - - // Get parent node - xml_node parent() const; - - // Get root of DOM tree this node belongs to - xml_node root() const; - - // Get text object for the current node - xml_text text() const; - - // Get child, attribute or next/previous sibling with the specified name - xml_node child(const char_t* name) const; - xml_attribute attribute(const char_t* name) const; - xml_node next_sibling(const char_t* name) const; - xml_node previous_sibling(const char_t* name) const; - - // Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast) - xml_attribute attribute(const char_t* name, xml_attribute& hint) const; - - // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA - const char_t* child_value() const; - - // Get child value of child with specified name. Equivalent to child(name).child_value(). - const char_t* child_value(const char_t* name) const; - - // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) - bool set_name(const char_t* rhs); - bool set_value(const char_t* rhs, size_t sz); - bool set_value(const char_t* rhs); - - // Add attribute with specified name. Returns added attribute, or empty attribute on errors. - xml_attribute append_attribute(const char_t* name); - xml_attribute prepend_attribute(const char_t* name); - xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); - xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); - - // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. - xml_attribute append_copy(const xml_attribute& proto); - xml_attribute prepend_copy(const xml_attribute& proto); - xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr); - xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr); - - // Add child node with specified type. Returns added node, or empty node on errors. - xml_node append_child(xml_node_type type = node_element); - xml_node prepend_child(xml_node_type type = node_element); - xml_node insert_child_after(xml_node_type type, const xml_node& node); - xml_node insert_child_before(xml_node_type type, const xml_node& node); - - // Add child element with specified name. Returns added node, or empty node on errors. - xml_node append_child(const char_t* name); - xml_node prepend_child(const char_t* name); - xml_node insert_child_after(const char_t* name, const xml_node& node); - xml_node insert_child_before(const char_t* name, const xml_node& node); - - // Add a copy of the specified node as a child. Returns added node, or empty node on errors. - xml_node append_copy(const xml_node& proto); - xml_node prepend_copy(const xml_node& proto); - xml_node insert_copy_after(const xml_node& proto, const xml_node& node); - xml_node insert_copy_before(const xml_node& proto, const xml_node& node); - - // Move the specified node to become a child of this node. Returns moved node, or empty node on errors. - xml_node append_move(const xml_node& moved); - xml_node prepend_move(const xml_node& moved); - xml_node insert_move_after(const xml_node& moved, const xml_node& node); - xml_node insert_move_before(const xml_node& moved, const xml_node& node); - - // Remove specified attribute - bool remove_attribute(const xml_attribute& a); - bool remove_attribute(const char_t* name); - - // Remove all attributes - bool remove_attributes(); - - // Remove specified child - bool remove_child(const xml_node& n); - bool remove_child(const char_t* name); - - // Remove all children - bool remove_children(); - - // Parses buffer as an XML document fragment and appends all nodes as children of the current node. - // Copies/converts the buffer, so it may be deleted or changed after the function returns. - // Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory. - xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Find attribute using predicate. Returns first attribute for which predicate returned true. - template xml_attribute find_attribute(Predicate pred) const - { - if (!_root) return xml_attribute(); - - for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute()) - if (pred(attrib)) - return attrib; - - return xml_attribute(); - } - - // Find child node using predicate. Returns first child for which predicate returned true. - template xml_node find_child(Predicate pred) const - { - if (!_root) return xml_node(); - - for (xml_node node = first_child(); node; node = node.next_sibling()) - if (pred(node)) - return node; - - return xml_node(); - } - - // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true. - template xml_node find_node(Predicate pred) const - { - if (!_root) return xml_node(); - - xml_node cur = first_child(); - - while (cur._root && cur._root != _root) - { - if (pred(cur)) return cur; - - if (cur.first_child()) cur = cur.first_child(); - else if (cur.next_sibling()) cur = cur.next_sibling(); - else - { - while (!cur.next_sibling() && cur._root != _root) cur = cur.parent(); - - if (cur._root != _root) cur = cur.next_sibling(); - } - } - - return xml_node(); - } - - // Find child node by attribute name/value - xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const; - xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const; - - #ifndef PUGIXML_NO_STL - // Get the absolute node path from root as a text string. - string_t path(char_t delimiter = '/') const; - #endif - - // Search for a node by path consisting of node names and . or .. elements. - xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const; - - // Recursively traverse subtree with xml_tree_walker - bool traverse(xml_tree_walker& walker); - - #ifndef PUGIXML_NO_XPATH - // Select single node by evaluating XPath query. Returns first node from the resulting node set. - xpath_node select_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; - xpath_node select_node(const xpath_query& query) const; - - // Select node set by evaluating XPath query - xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; - xpath_node_set select_nodes(const xpath_query& query) const; - - // (deprecated: use select_node instead) Select single node by evaluating XPath query. - PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; - PUGIXML_DEPRECATED xpath_node select_single_node(const xpath_query& query) const; - - #endif - - // Print subtree using a writer object - void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - - #ifndef PUGIXML_NO_STL - // Print subtree to stream - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; - #endif - - // Child nodes iterators - typedef xml_node_iterator iterator; - - iterator begin() const; - iterator end() const; - - // Attribute iterators - typedef xml_attribute_iterator attribute_iterator; - - attribute_iterator attributes_begin() const; - attribute_iterator attributes_end() const; - - // Range-based for support - xml_object_range children() const; - xml_object_range children(const char_t* name) const; - xml_object_range attributes() const; - - // Get node offset in parsed file/string (in char_t units) for debugging purposes - ptrdiff_t offset_debug() const; - - // Get hash value (unique for handles to the same object) - size_t hash_value() const; - - // Get internal pointer - xml_node_struct* internal_object() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs); -#endif - - // A helper for working with text inside PCDATA nodes - class PUGIXML_CLASS xml_text - { - friend class xml_node; - - xml_node_struct* _root; - - typedef void (*unspecified_bool_type)(xml_text***); - - explicit xml_text(xml_node_struct* root); - - xml_node_struct* _data_new(); - xml_node_struct* _data() const; - - public: - // Default constructor. Constructs an empty object. - xml_text(); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Check if text object is empty - bool empty() const; - - // Get text, or "" if object is empty - const char_t* get() const; - - // Get text, or the default value if object is empty - const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; - - // Get text as a number, or the default value if conversion did not succeed or object is empty - int as_int(int def = 0) const; - unsigned int as_uint(unsigned int def = 0) const; - double as_double(double def = 0) const; - float as_float(float def = 0) const; - - #ifdef PUGIXML_HAS_LONG_LONG - long long as_llong(long long def = 0) const; - unsigned long long as_ullong(unsigned long long def = 0) const; - #endif - - // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty - bool as_bool(bool def = false) const; - - // Set text (returns false if object is empty or there is not enough memory) - bool set(const char_t* rhs, size_t sz); - bool set(const char_t* rhs); - - // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") - bool set(int rhs); - bool set(unsigned int rhs); - bool set(long rhs); - bool set(unsigned long rhs); - bool set(double rhs); - bool set(double rhs, int precision); - bool set(float rhs); - bool set(float rhs, int precision); - bool set(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - bool set(long long rhs); - bool set(unsigned long long rhs); - #endif - - // Set text (equivalent to set without error checking) - xml_text& operator=(const char_t* rhs); - xml_text& operator=(int rhs); - xml_text& operator=(unsigned int rhs); - xml_text& operator=(long rhs); - xml_text& operator=(unsigned long rhs); - xml_text& operator=(double rhs); - xml_text& operator=(float rhs); - xml_text& operator=(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - xml_text& operator=(long long rhs); - xml_text& operator=(unsigned long long rhs); - #endif - - // Get the data node (node_pcdata or node_cdata) for this object - xml_node data() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_text& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_text& lhs, bool rhs); -#endif - - // Child node iterator (a bidirectional iterator over a collection of xml_node) - class PUGIXML_CLASS xml_node_iterator - { - friend class xml_node; - - private: - mutable xml_node _wrap; - xml_node _parent; - - xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent); - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_node value_type; - typedef xml_node* pointer; - typedef xml_node& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_node_iterator(); - - // Construct an iterator which points to the specified node - xml_node_iterator(const xml_node& node); - - // Iterator operators - bool operator==(const xml_node_iterator& rhs) const; - bool operator!=(const xml_node_iterator& rhs) const; - - xml_node& operator*() const; - xml_node* operator->() const; - - xml_node_iterator& operator++(); - xml_node_iterator operator++(int); - - xml_node_iterator& operator--(); - xml_node_iterator operator--(int); - }; - - // Attribute iterator (a bidirectional iterator over a collection of xml_attribute) - class PUGIXML_CLASS xml_attribute_iterator - { - friend class xml_node; - - private: - mutable xml_attribute _wrap; - xml_node _parent; - - xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent); - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_attribute value_type; - typedef xml_attribute* pointer; - typedef xml_attribute& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_attribute_iterator(); - - // Construct an iterator which points to the specified attribute - xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent); - - // Iterator operators - bool operator==(const xml_attribute_iterator& rhs) const; - bool operator!=(const xml_attribute_iterator& rhs) const; - - xml_attribute& operator*() const; - xml_attribute* operator->() const; - - xml_attribute_iterator& operator++(); - xml_attribute_iterator operator++(int); - - xml_attribute_iterator& operator--(); - xml_attribute_iterator operator--(int); - }; - - // Named node range helper - class PUGIXML_CLASS xml_named_node_iterator - { - friend class xml_node; - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_node value_type; - typedef xml_node* pointer; - typedef xml_node& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_named_node_iterator(); - - // Construct an iterator which points to the specified node - xml_named_node_iterator(const xml_node& node, const char_t* name); - - // Iterator operators - bool operator==(const xml_named_node_iterator& rhs) const; - bool operator!=(const xml_named_node_iterator& rhs) const; - - xml_node& operator*() const; - xml_node* operator->() const; - - xml_named_node_iterator& operator++(); - xml_named_node_iterator operator++(int); - - xml_named_node_iterator& operator--(); - xml_named_node_iterator operator--(int); - - private: - mutable xml_node _wrap; - xml_node _parent; - const char_t* _name; - - xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name); - }; - - // Abstract tree walker class (see xml_node::traverse) - class PUGIXML_CLASS xml_tree_walker - { - friend class xml_node; - - private: - int _depth; - - protected: - // Get current traversal depth - int depth() const; - - public: - xml_tree_walker(); - virtual ~xml_tree_walker(); - - // Callback that is called when traversal begins - virtual bool begin(xml_node& node); - - // Callback that is called for each node traversed - virtual bool for_each(xml_node& node) = 0; - - // Callback that is called when traversal ends - virtual bool end(xml_node& node); - }; - - // Parsing status, returned as part of xml_parse_result object - enum xml_parse_status - { - status_ok = 0, // No error - - status_file_not_found, // File was not found during load_file() - status_io_error, // Error reading from file/stream - status_out_of_memory, // Could not allocate memory - status_internal_error, // Internal error occurred - - status_unrecognized_tag, // Parser could not determine tag type - - status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction - status_bad_comment, // Parsing error occurred while parsing comment - status_bad_cdata, // Parsing error occurred while parsing CDATA section - status_bad_doctype, // Parsing error occurred while parsing document type declaration - status_bad_pcdata, // Parsing error occurred while parsing PCDATA section - status_bad_start_element, // Parsing error occurred while parsing start element tag - status_bad_attribute, // Parsing error occurred while parsing element attribute - status_bad_end_element, // Parsing error occurred while parsing end element tag - status_end_element_mismatch,// There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag) - - status_append_invalid_root, // Unable to append nodes since root type is not node_element or node_document (exclusive to xml_node::append_buffer) - - status_no_document_element // Parsing resulted in a document without element nodes - }; - - // Parsing result - struct PUGIXML_CLASS xml_parse_result - { - // Parsing status (see xml_parse_status) - xml_parse_status status; - - // Last parsed offset (in char_t units from start of input data) - ptrdiff_t offset; - - // Source document encoding - xml_encoding encoding; - - // Default constructor, initializes object to failed state - xml_parse_result(); - - // Cast to bool operator - operator bool() const; - - // Get error description - const char* description() const; - }; - - // Document class (DOM tree root) - class PUGIXML_CLASS xml_document: public xml_node - { - private: - char_t* _buffer; - - char _memory[192]; - - // Non-copyable semantics - xml_document(const xml_document&); - xml_document& operator=(const xml_document&); - - void _create(); - void _destroy(); - void _move(xml_document& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; - - public: - // Default constructor, makes empty document - xml_document(); - - // Destructor, invalidates all node/attribute handles to this document - ~xml_document(); - - #ifdef PUGIXML_HAS_MOVE - // Move semantics support - xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; - xml_document& operator=(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; - #endif - - // Removes all nodes, leaving the empty document - void reset(); - - // Removes all nodes, then copies the entire contents of the specified document - void reset(const xml_document& proto); - - #ifndef PUGIXML_NO_STL - // Load document from stream. - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); - #endif - - // (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied. - PUGIXML_DEPRECATED xml_parse_result load(const char_t* contents, unsigned int options = parse_default); - - // Load document from zero-terminated string. No encoding conversions are applied. - xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default); - - // Load document from file - xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns. - xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). - // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed. - xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). - // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore). - xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details). - void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - - #ifndef PUGIXML_NO_STL - // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; - #endif - - // Save XML to file - bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - - // Get document element - xml_node document_element() const; - }; - -#ifndef PUGIXML_NO_XPATH - // XPath query return type - enum xpath_value_type - { - xpath_type_none, // Unknown type (query failed to compile) - xpath_type_node_set, // Node set (xpath_node_set) - xpath_type_number, // Number - xpath_type_string, // String - xpath_type_boolean // Boolean - }; - - // XPath parsing result - struct PUGIXML_CLASS xpath_parse_result - { - // Error message (0 if no error) - const char* error; - - // Last parsed offset (in char_t units from string start) - ptrdiff_t offset; - - // Default constructor, initializes object to failed state - xpath_parse_result(); - - // Cast to bool operator - operator bool() const; - - // Get error description - const char* description() const; - }; - - // A single XPath variable - class PUGIXML_CLASS xpath_variable - { - friend class xpath_variable_set; - - protected: - xpath_value_type _type; - xpath_variable* _next; - - xpath_variable(xpath_value_type type); - - // Non-copyable semantics - xpath_variable(const xpath_variable&); - xpath_variable& operator=(const xpath_variable&); - - public: - // Get variable name - const char_t* name() const; - - // Get variable type - xpath_value_type type() const; - - // Get variable value; no type conversion is performed, default value (false, NaN, empty string, empty node set) is returned on type mismatch error - bool get_boolean() const; - double get_number() const; - const char_t* get_string() const; - const xpath_node_set& get_node_set() const; - - // Set variable value; no type conversion is performed, false is returned on type mismatch error - bool set(bool value); - bool set(double value); - bool set(const char_t* value); - bool set(const xpath_node_set& value); - }; - - // A set of XPath variables - class PUGIXML_CLASS xpath_variable_set - { - private: - xpath_variable* _data[64]; - - void _assign(const xpath_variable_set& rhs); - void _swap(xpath_variable_set& rhs); - - xpath_variable* _find(const char_t* name) const; - - static bool _clone(xpath_variable* var, xpath_variable** out_result); - static void _destroy(xpath_variable* var); - - public: - // Default constructor/destructor - xpath_variable_set(); - ~xpath_variable_set(); - - // Copy constructor/assignment operator - xpath_variable_set(const xpath_variable_set& rhs); - xpath_variable_set& operator=(const xpath_variable_set& rhs); - - #ifdef PUGIXML_HAS_MOVE - // Move semantics support - xpath_variable_set(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT; - xpath_variable_set& operator=(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT; - #endif - - // Add a new variable or get the existing one, if the types match - xpath_variable* add(const char_t* name, xpath_value_type type); - - // Set value of an existing variable; no type conversion is performed, false is returned if there is no such variable or if types mismatch - bool set(const char_t* name, bool value); - bool set(const char_t* name, double value); - bool set(const char_t* name, const char_t* value); - bool set(const char_t* name, const xpath_node_set& value); - - // Get existing variable by name - xpath_variable* get(const char_t* name); - const xpath_variable* get(const char_t* name) const; - }; - - // A compiled XPath query object - class PUGIXML_CLASS xpath_query - { - private: - void* _impl; - xpath_parse_result _result; - - typedef void (*unspecified_bool_type)(xpath_query***); - - // Non-copyable semantics - xpath_query(const xpath_query&); - xpath_query& operator=(const xpath_query&); - - public: - // Construct a compiled object from XPath expression. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. - explicit xpath_query(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL); - - // Constructor - xpath_query(); - - // Destructor - ~xpath_query(); - - #ifdef PUGIXML_HAS_MOVE - // Move semantics support - xpath_query(xpath_query&& rhs) PUGIXML_NOEXCEPT; - xpath_query& operator=(xpath_query&& rhs) PUGIXML_NOEXCEPT; - #endif - - // Get query expression return type - xpath_value_type return_type() const; - - // Evaluate expression as boolean value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - bool evaluate_boolean(const xpath_node& n) const; - - // Evaluate expression as double value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - double evaluate_number(const xpath_node& n) const; - - #ifndef PUGIXML_NO_STL - // Evaluate expression as string value in the specified context; performs type conversion if necessary. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - string_t evaluate_string(const xpath_node& n) const; - #endif - - // Evaluate expression as string value in the specified context; performs type conversion if necessary. - // At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero). - // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. - // If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead. - size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const; - - // Evaluate expression as node set in the specified context. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. - // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node set instead. - xpath_node_set evaluate_node_set(const xpath_node& n) const; - - // Evaluate expression as node set in the specified context. - // Return first node in document order, or empty node if node set is empty. - // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. - // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node instead. - xpath_node evaluate_node(const xpath_node& n) const; - - // Get parsing result (used to get compilation errors in PUGIXML_NO_EXCEPTIONS mode) - const xpath_parse_result& result() const; - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - }; - - #ifndef PUGIXML_NO_EXCEPTIONS - #if defined(_MSC_VER) - // C4275 can be ignored in Visual C++ if you are deriving - // from a type in the Standard C++ Library - #pragma warning(push) - #pragma warning(disable: 4275) - #endif - // XPath exception class - class PUGIXML_CLASS xpath_exception: public std::exception - { - private: - xpath_parse_result _result; - - public: - // Construct exception from parse result - explicit xpath_exception(const xpath_parse_result& result); - - // Get error message - virtual const char* what() const throw() PUGIXML_OVERRIDE; - - // Get parse result - const xpath_parse_result& result() const; - }; - #if defined(_MSC_VER) - #pragma warning(pop) - #endif - #endif - - // XPath node class (either xml_node or xml_attribute) - class PUGIXML_CLASS xpath_node - { - private: - xml_node _node; - xml_attribute _attribute; - - typedef void (*unspecified_bool_type)(xpath_node***); - - public: - // Default constructor; constructs empty XPath node - xpath_node(); - - // Construct XPath node from XML node/attribute - xpath_node(const xml_node& node); - xpath_node(const xml_attribute& attribute, const xml_node& parent); - - // Get node/attribute, if any - xml_node node() const; - xml_attribute attribute() const; - - // Get parent of contained node/attribute - xml_node parent() const; - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators - bool operator==(const xpath_node& n) const; - bool operator!=(const xpath_node& n) const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xpath_node& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xpath_node& lhs, bool rhs); -#endif - - // A fixed-size collection of XPath nodes - class PUGIXML_CLASS xpath_node_set - { - public: - // Collection type - enum type_t - { - type_unsorted, // Not ordered - type_sorted, // Sorted by document order (ascending) - type_sorted_reverse // Sorted by document order (descending) - }; - - // Constant iterator type - typedef const xpath_node* const_iterator; - - // We define non-constant iterator to be the same as constant iterator so that various generic algorithms (i.e. boost foreach) work - typedef const xpath_node* iterator; - - // Default constructor. Constructs empty set. - xpath_node_set(); - - // Constructs a set from iterator range; data is not checked for duplicates and is not sorted according to provided type, so be careful - xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted); - - // Destructor - ~xpath_node_set(); - - // Copy constructor/assignment operator - xpath_node_set(const xpath_node_set& ns); - xpath_node_set& operator=(const xpath_node_set& ns); - - #ifdef PUGIXML_HAS_MOVE - // Move semantics support - xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT; - xpath_node_set& operator=(xpath_node_set&& rhs) PUGIXML_NOEXCEPT; - #endif - - // Get collection type - type_t type() const; - - // Get collection size - size_t size() const; - - // Indexing operator - const xpath_node& operator[](size_t index) const; - - // Collection iterators - const_iterator begin() const; - const_iterator end() const; - - // Sort the collection in ascending/descending order by document order - void sort(bool reverse = false); - - // Get first node in the collection by document order - xpath_node first() const; - - // Check if collection is empty - bool empty() const; - - private: - type_t _type; - - xpath_node _storage[1]; - - xpath_node* _begin; - xpath_node* _end; - - void _assign(const_iterator begin, const_iterator end, type_t type); - void _move(xpath_node_set& rhs) PUGIXML_NOEXCEPT; - }; -#endif - -#ifndef PUGIXML_NO_STL - // Convert wide string to UTF8 - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); - - // Convert UTF8 to wide string - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); -#endif - - // Memory allocation function interface; returns pointer to allocated memory or NULL on failure - typedef void* (*allocation_function)(size_t size); - - // Memory deallocation function interface - typedef void (*deallocation_function)(void* ptr); - - // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions. - void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate); - - // Get current memory management functions - allocation_function PUGIXML_FUNCTION get_memory_allocation_function(); - deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function(); -} - -#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) -namespace std -{ - // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&); -} -#endif - -#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) -namespace std -{ - // Workarounds for (non-standard) iterator category detection - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&); -} -#endif - -#endif - -// Make sure implementation is included in header-only mode -// Use macro expansion in #include to work around QMake (QTBUG-11923) -#if defined(PUGIXML_HEADER_ONLY) && !defined(PUGIXML_SOURCE) -# define PUGIXML_SOURCE "pugixml.cpp" -# include PUGIXML_SOURCE -#endif - -/** - * Copyright (c) 2006-2022 Arseny Kapoulkine - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ +/** + * pugixml parser - version 1.14 + * -------------------------------------------------------- + * Copyright (C) 2006-2023, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons +// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits +#ifndef PUGIXML_VERSION +# define PUGIXML_VERSION 1140 // 1.14 +#endif + +// Include user configuration file (this can define various configuration macros) +#include "pugiconfig.hpp" + +#ifndef HEADER_PUGIXML_HPP +#define HEADER_PUGIXML_HPP + +// Include stddef.h for size_t and ptrdiff_t +#include + +// Include exception header for XPath +#if !defined(PUGIXML_NO_XPATH) && !defined(PUGIXML_NO_EXCEPTIONS) +# include +#endif + +// Include STL headers +#ifndef PUGIXML_NO_STL +# include +# include +# include +#endif + +// Macro for deprecated features +#ifndef PUGIXML_DEPRECATED +# if defined(__GNUC__) +# define PUGIXML_DEPRECATED __attribute__((deprecated)) +# elif defined(_MSC_VER) && _MSC_VER >= 1300 +# define PUGIXML_DEPRECATED __declspec(deprecated) +# else +# define PUGIXML_DEPRECATED +# endif +#endif + +// If no API is defined, assume default +#ifndef PUGIXML_API +# define PUGIXML_API +#endif + +// If no API for classes is defined, assume default +#ifndef PUGIXML_CLASS +# define PUGIXML_CLASS PUGIXML_API +#endif + +// If no API for functions is defined, assume default +#ifndef PUGIXML_FUNCTION +# define PUGIXML_FUNCTION PUGIXML_API +#endif + +// If the platform is known to have long long support, enable long long functions +#ifndef PUGIXML_HAS_LONG_LONG +# if __cplusplus >= 201103 +# define PUGIXML_HAS_LONG_LONG +# elif defined(_MSC_VER) && _MSC_VER >= 1400 +# define PUGIXML_HAS_LONG_LONG +# endif +#endif + +// If the platform is known to have move semantics support, compile move ctor/operator implementation +#ifndef PUGIXML_HAS_MOVE +# if __cplusplus >= 201103 +# define PUGIXML_HAS_MOVE +# elif defined(_MSC_VER) && _MSC_VER >= 1600 +# define PUGIXML_HAS_MOVE +# endif +#endif + +// If C++ is 2011 or higher, add 'noexcept' specifiers +#ifndef PUGIXML_NOEXCEPT +# if __cplusplus >= 201103 +# define PUGIXML_NOEXCEPT noexcept +# elif defined(_MSC_VER) && _MSC_VER >= 1900 +# define PUGIXML_NOEXCEPT noexcept +# else +# define PUGIXML_NOEXCEPT +# endif +#endif + +// Some functions can not be noexcept in compact mode +#ifdef PUGIXML_COMPACT +# define PUGIXML_NOEXCEPT_IF_NOT_COMPACT +#else +# define PUGIXML_NOEXCEPT_IF_NOT_COMPACT PUGIXML_NOEXCEPT +#endif + +// If C++ is 2011 or higher, add 'override' qualifiers +#ifndef PUGIXML_OVERRIDE +# if __cplusplus >= 201103 +# define PUGIXML_OVERRIDE override +# elif defined(_MSC_VER) && _MSC_VER >= 1700 +# define PUGIXML_OVERRIDE override +# else +# define PUGIXML_OVERRIDE +# endif +#endif + +// If C++ is 2011 or higher, use 'nullptr' +#ifndef PUGIXML_NULL +# if __cplusplus >= 201103 +# define PUGIXML_NULL nullptr +# elif defined(_MSC_VER) && _MSC_VER >= 1600 +# define PUGIXML_NULL nullptr +# else +# define PUGIXML_NULL 0 +# endif +#endif + +// Character interface macros +#ifdef PUGIXML_WCHAR_MODE +# define PUGIXML_TEXT(t) L ## t +# define PUGIXML_CHAR wchar_t +#else +# define PUGIXML_TEXT(t) t +# define PUGIXML_CHAR char +#endif + +namespace pugi +{ + // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE + typedef PUGIXML_CHAR char_t; + +#ifndef PUGIXML_NO_STL + // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE + typedef std::basic_string, std::allocator > string_t; +#endif +} + +// The PugiXML namespace +namespace pugi +{ + // Tree node types + enum xml_node_type + { + node_null, // Empty (null) node handle + node_document, // A document tree's absolute root + node_element, // Element tag, i.e. '' + node_pcdata, // Plain character data, i.e. 'text' + node_cdata, // Character data, i.e. '' + node_comment, // Comment tag, i.e. '' + node_pi, // Processing instruction, i.e. '' + node_declaration, // Document declaration, i.e. '' + node_doctype // Document type declaration, i.e. '' + }; + + // Parsing options + + // Minimal parsing mode (equivalent to turning all other flags off). + // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed. + const unsigned int parse_minimal = 0x0000; + + // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default. + const unsigned int parse_pi = 0x0001; + + // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default. + const unsigned int parse_comments = 0x0002; + + // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default. + const unsigned int parse_cdata = 0x0004; + + // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree. + // This flag is off by default; turning it on usually results in slower parsing and more memory consumption. + const unsigned int parse_ws_pcdata = 0x0008; + + // This flag determines if character and entity references are expanded during parsing. This flag is on by default. + const unsigned int parse_escapes = 0x0010; + + // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default. + const unsigned int parse_eol = 0x0020; + + // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default. + const unsigned int parse_wconv_attribute = 0x0040; + + // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default. + const unsigned int parse_wnorm_attribute = 0x0080; + + // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default. + const unsigned int parse_declaration = 0x0100; + + // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default. + const unsigned int parse_doctype = 0x0200; + + // This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only + // of whitespace is added to the DOM tree. + // This flag is off by default; turning it on may result in slower parsing and more memory consumption. + const unsigned int parse_ws_pcdata_single = 0x0400; + + // This flag determines if leading and trailing whitespace is to be removed from plain character data. This flag is off by default. + const unsigned int parse_trim_pcdata = 0x0800; + + // This flag determines if plain character data that does not have a parent node is added to the DOM tree, and if an empty document + // is a valid document. This flag is off by default. + const unsigned int parse_fragment = 0x1000; + + // This flag determines if plain character data is be stored in the parent element's value. This significantly changes the structure of + // the document; this flag is only recommended for parsing documents with many PCDATA nodes in memory-constrained environments. + // This flag is off by default. + const unsigned int parse_embed_pcdata = 0x2000; + + // This flag determines whether determines whether the the two pcdata should be merged or not, if no intermediatory data are parsed in the document. + // This flag is off by default. + const unsigned int parse_merge_pcdata = 0x4000; + + // The default parsing mode. + // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, + // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. + const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol; + + // The full parsing mode. + // Nodes of all types are added to the DOM tree, character/reference entities are expanded, + // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. + const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype; + + // These flags determine the encoding of input data for XML document + enum xml_encoding + { + encoding_auto, // Auto-detect input encoding using BOM or < / class xml_object_range + { + public: + typedef It const_iterator; + typedef It iterator; + + xml_object_range(It b, It e): _begin(b), _end(e) + { + } + + It begin() const { return _begin; } + It end() const { return _end; } + + bool empty() const { return _begin == _end; } + + private: + It _begin, _end; + }; + + // Writer interface for node printing (see xml_node::print) + class PUGIXML_CLASS xml_writer + { + public: + virtual ~xml_writer(); + + // Write memory chunk into stream/file/whatever + virtual void write(const void* data, size_t size) = 0; + }; + + // xml_writer implementation for FILE* + class PUGIXML_CLASS xml_writer_file: public xml_writer + { + public: + // Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio + xml_writer_file(void* file); + + virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; + + private: + void* file; + }; + + #ifndef PUGIXML_NO_STL + // xml_writer implementation for streams + class PUGIXML_CLASS xml_writer_stream: public xml_writer + { + public: + // Construct writer from an output stream object + xml_writer_stream(std::basic_ostream >& stream); + xml_writer_stream(std::basic_ostream >& stream); + + virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; + + private: + std::basic_ostream >* narrow_stream; + std::basic_ostream >* wide_stream; + }; + #endif + + // A light-weight handle for manipulating attributes in DOM tree + class PUGIXML_CLASS xml_attribute + { + friend class xml_attribute_iterator; + friend class xml_node; + + private: + xml_attribute_struct* _attr; + + typedef void (*unspecified_bool_type)(xml_attribute***); + + public: + // Default constructor. Constructs an empty attribute. + xml_attribute(); + + // Constructs attribute from internal pointer + explicit xml_attribute(xml_attribute_struct* attr); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators (compares wrapped attribute pointers) + bool operator==(const xml_attribute& r) const; + bool operator!=(const xml_attribute& r) const; + bool operator<(const xml_attribute& r) const; + bool operator>(const xml_attribute& r) const; + bool operator<=(const xml_attribute& r) const; + bool operator>=(const xml_attribute& r) const; + + // Check if attribute is empty + bool empty() const; + + // Get attribute name/value, or "" if attribute is empty + const char_t* name() const; + const char_t* value() const; + + // Get attribute value, or the default value if attribute is empty + const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; + + // Get attribute value as a number, or the default value if conversion did not succeed or attribute is empty + int as_int(int def = 0) const; + unsigned int as_uint(unsigned int def = 0) const; + double as_double(double def = 0) const; + float as_float(float def = 0) const; + + #ifdef PUGIXML_HAS_LONG_LONG + long long as_llong(long long def = 0) const; + unsigned long long as_ullong(unsigned long long def = 0) const; + #endif + + // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty + bool as_bool(bool def = false) const; + + // Set attribute name/value (returns false if attribute is empty or there is not enough memory) + bool set_name(const char_t* rhs); + bool set_name(const char_t* rhs, size_t size); + bool set_value(const char_t* rhs); + bool set_value(const char_t* rhs, size_t size); + + // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") + bool set_value(int rhs); + bool set_value(unsigned int rhs); + bool set_value(long rhs); + bool set_value(unsigned long rhs); + bool set_value(double rhs); + bool set_value(double rhs, int precision); + bool set_value(float rhs); + bool set_value(float rhs, int precision); + bool set_value(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + bool set_value(long long rhs); + bool set_value(unsigned long long rhs); + #endif + + // Set attribute value (equivalent to set_value without error checking) + xml_attribute& operator=(const char_t* rhs); + xml_attribute& operator=(int rhs); + xml_attribute& operator=(unsigned int rhs); + xml_attribute& operator=(long rhs); + xml_attribute& operator=(unsigned long rhs); + xml_attribute& operator=(double rhs); + xml_attribute& operator=(float rhs); + xml_attribute& operator=(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + xml_attribute& operator=(long long rhs); + xml_attribute& operator=(unsigned long long rhs); + #endif + + // Get next/previous attribute in the attribute list of the parent node + xml_attribute next_attribute() const; + xml_attribute previous_attribute() const; + + // Get hash value (unique for handles to the same object) + size_t hash_value() const; + + // Get internal pointer + xml_attribute_struct* internal_object() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs); +#endif + + // A light-weight handle for manipulating nodes in DOM tree + class PUGIXML_CLASS xml_node + { + friend class xml_attribute_iterator; + friend class xml_node_iterator; + friend class xml_named_node_iterator; + + protected: + xml_node_struct* _root; + + typedef void (*unspecified_bool_type)(xml_node***); + + public: + // Default constructor. Constructs an empty node. + xml_node(); + + // Constructs node from internal pointer + explicit xml_node(xml_node_struct* p); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators (compares wrapped node pointers) + bool operator==(const xml_node& r) const; + bool operator!=(const xml_node& r) const; + bool operator<(const xml_node& r) const; + bool operator>(const xml_node& r) const; + bool operator<=(const xml_node& r) const; + bool operator>=(const xml_node& r) const; + + // Check if node is empty. + bool empty() const; + + // Get node type + xml_node_type type() const; + + // Get node name, or "" if node is empty or it has no name + const char_t* name() const; + + // Get node value, or "" if node is empty or it has no value + // Note: For text node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes. + const char_t* value() const; + + // Get attribute list + xml_attribute first_attribute() const; + xml_attribute last_attribute() const; + + // Get children list + xml_node first_child() const; + xml_node last_child() const; + + // Get next/previous sibling in the children list of the parent node + xml_node next_sibling() const; + xml_node previous_sibling() const; + + // Get parent node + xml_node parent() const; + + // Get root of DOM tree this node belongs to + xml_node root() const; + + // Get text object for the current node + xml_text text() const; + + // Get child, attribute or next/previous sibling with the specified name + xml_node child(const char_t* name) const; + xml_attribute attribute(const char_t* name) const; + xml_node next_sibling(const char_t* name) const; + xml_node previous_sibling(const char_t* name) const; + + // Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast) + xml_attribute attribute(const char_t* name, xml_attribute& hint) const; + + // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA + const char_t* child_value() const; + + // Get child value of child with specified name. Equivalent to child(name).child_value(). + const char_t* child_value(const char_t* name) const; + + // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) + bool set_name(const char_t* rhs); + bool set_name(const char_t* rhs, size_t size); + bool set_value(const char_t* rhs); + bool set_value(const char_t* rhs, size_t size); + + // Add attribute with specified name. Returns added attribute, or empty attribute on errors. + xml_attribute append_attribute(const char_t* name); + xml_attribute prepend_attribute(const char_t* name); + xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); + xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); + + // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. + xml_attribute append_copy(const xml_attribute& proto); + xml_attribute prepend_copy(const xml_attribute& proto); + xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr); + xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr); + + // Add child node with specified type. Returns added node, or empty node on errors. + xml_node append_child(xml_node_type type = node_element); + xml_node prepend_child(xml_node_type type = node_element); + xml_node insert_child_after(xml_node_type type, const xml_node& node); + xml_node insert_child_before(xml_node_type type, const xml_node& node); + + // Add child element with specified name. Returns added node, or empty node on errors. + xml_node append_child(const char_t* name); + xml_node prepend_child(const char_t* name); + xml_node insert_child_after(const char_t* name, const xml_node& node); + xml_node insert_child_before(const char_t* name, const xml_node& node); + + // Add a copy of the specified node as a child. Returns added node, or empty node on errors. + xml_node append_copy(const xml_node& proto); + xml_node prepend_copy(const xml_node& proto); + xml_node insert_copy_after(const xml_node& proto, const xml_node& node); + xml_node insert_copy_before(const xml_node& proto, const xml_node& node); + + // Move the specified node to become a child of this node. Returns moved node, or empty node on errors. + xml_node append_move(const xml_node& moved); + xml_node prepend_move(const xml_node& moved); + xml_node insert_move_after(const xml_node& moved, const xml_node& node); + xml_node insert_move_before(const xml_node& moved, const xml_node& node); + + // Remove specified attribute + bool remove_attribute(const xml_attribute& a); + bool remove_attribute(const char_t* name); + + // Remove all attributes + bool remove_attributes(); + + // Remove specified child + bool remove_child(const xml_node& n); + bool remove_child(const char_t* name); + + // Remove all children + bool remove_children(); + + // Parses buffer as an XML document fragment and appends all nodes as children of the current node. + // Copies/converts the buffer, so it may be deleted or changed after the function returns. + // Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory. + xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Find attribute using predicate. Returns first attribute for which predicate returned true. + template xml_attribute find_attribute(Predicate pred) const + { + if (!_root) return xml_attribute(); + + for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute()) + if (pred(attrib)) + return attrib; + + return xml_attribute(); + } + + // Find child node using predicate. Returns first child for which predicate returned true. + template xml_node find_child(Predicate pred) const + { + if (!_root) return xml_node(); + + for (xml_node node = first_child(); node; node = node.next_sibling()) + if (pred(node)) + return node; + + return xml_node(); + } + + // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true. + template xml_node find_node(Predicate pred) const + { + if (!_root) return xml_node(); + + xml_node cur = first_child(); + + while (cur._root && cur._root != _root) + { + if (pred(cur)) return cur; + + if (cur.first_child()) cur = cur.first_child(); + else if (cur.next_sibling()) cur = cur.next_sibling(); + else + { + while (!cur.next_sibling() && cur._root != _root) cur = cur.parent(); + + if (cur._root != _root) cur = cur.next_sibling(); + } + } + + return xml_node(); + } + + // Find child node by attribute name/value + xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const; + xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const; + + #ifndef PUGIXML_NO_STL + // Get the absolute node path from root as a text string. + string_t path(char_t delimiter = '/') const; + #endif + + // Search for a node by path consisting of node names and . or .. elements. + xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const; + + // Recursively traverse subtree with xml_tree_walker + bool traverse(xml_tree_walker& walker); + + #ifndef PUGIXML_NO_XPATH + // Select single node by evaluating XPath query. Returns first node from the resulting node set. + xpath_node select_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; + xpath_node select_node(const xpath_query& query) const; + + // Select node set by evaluating XPath query + xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; + xpath_node_set select_nodes(const xpath_query& query) const; + + // (deprecated: use select_node instead) Select single node by evaluating XPath query. + PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; + PUGIXML_DEPRECATED xpath_node select_single_node(const xpath_query& query) const; + + #endif + + // Print subtree using a writer object + void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + + #ifndef PUGIXML_NO_STL + // Print subtree to stream + void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; + #endif + + // Child nodes iterators + typedef xml_node_iterator iterator; + + iterator begin() const; + iterator end() const; + + // Attribute iterators + typedef xml_attribute_iterator attribute_iterator; + + attribute_iterator attributes_begin() const; + attribute_iterator attributes_end() const; + + // Range-based for support + xml_object_range children() const; + xml_object_range attributes() const; + + // Range-based for support for all children with the specified name + // Note: name pointer must have a longer lifetime than the returned object; be careful with passing temporaries! + xml_object_range children(const char_t* name) const; + + // Get node offset in parsed file/string (in char_t units) for debugging purposes + ptrdiff_t offset_debug() const; + + // Get hash value (unique for handles to the same object) + size_t hash_value() const; + + // Get internal pointer + xml_node_struct* internal_object() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs); +#endif + + // A helper for working with text inside PCDATA nodes + class PUGIXML_CLASS xml_text + { + friend class xml_node; + + xml_node_struct* _root; + + typedef void (*unspecified_bool_type)(xml_text***); + + explicit xml_text(xml_node_struct* root); + + xml_node_struct* _data_new(); + xml_node_struct* _data() const; + + public: + // Default constructor. Constructs an empty object. + xml_text(); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Check if text object is empty + bool empty() const; + + // Get text, or "" if object is empty + const char_t* get() const; + + // Get text, or the default value if object is empty + const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; + + // Get text as a number, or the default value if conversion did not succeed or object is empty + int as_int(int def = 0) const; + unsigned int as_uint(unsigned int def = 0) const; + double as_double(double def = 0) const; + float as_float(float def = 0) const; + + #ifdef PUGIXML_HAS_LONG_LONG + long long as_llong(long long def = 0) const; + unsigned long long as_ullong(unsigned long long def = 0) const; + #endif + + // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty + bool as_bool(bool def = false) const; + + // Set text (returns false if object is empty or there is not enough memory) + bool set(const char_t* rhs); + bool set(const char_t* rhs, size_t size); + + // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") + bool set(int rhs); + bool set(unsigned int rhs); + bool set(long rhs); + bool set(unsigned long rhs); + bool set(double rhs); + bool set(double rhs, int precision); + bool set(float rhs); + bool set(float rhs, int precision); + bool set(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + bool set(long long rhs); + bool set(unsigned long long rhs); + #endif + + // Set text (equivalent to set without error checking) + xml_text& operator=(const char_t* rhs); + xml_text& operator=(int rhs); + xml_text& operator=(unsigned int rhs); + xml_text& operator=(long rhs); + xml_text& operator=(unsigned long rhs); + xml_text& operator=(double rhs); + xml_text& operator=(float rhs); + xml_text& operator=(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + xml_text& operator=(long long rhs); + xml_text& operator=(unsigned long long rhs); + #endif + + // Get the data node (node_pcdata or node_cdata) for this object + xml_node data() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_text& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_text& lhs, bool rhs); +#endif + + // Child node iterator (a bidirectional iterator over a collection of xml_node) + class PUGIXML_CLASS xml_node_iterator + { + friend class xml_node; + + private: + mutable xml_node _wrap; + xml_node _parent; + + xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent); + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_node value_type; + typedef xml_node* pointer; + typedef xml_node& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_node_iterator(); + + // Construct an iterator which points to the specified node + xml_node_iterator(const xml_node& node); + + // Iterator operators + bool operator==(const xml_node_iterator& rhs) const; + bool operator!=(const xml_node_iterator& rhs) const; + + xml_node& operator*() const; + xml_node* operator->() const; + + xml_node_iterator& operator++(); + xml_node_iterator operator++(int); + + xml_node_iterator& operator--(); + xml_node_iterator operator--(int); + }; + + // Attribute iterator (a bidirectional iterator over a collection of xml_attribute) + class PUGIXML_CLASS xml_attribute_iterator + { + friend class xml_node; + + private: + mutable xml_attribute _wrap; + xml_node _parent; + + xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent); + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_attribute value_type; + typedef xml_attribute* pointer; + typedef xml_attribute& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_attribute_iterator(); + + // Construct an iterator which points to the specified attribute + xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent); + + // Iterator operators + bool operator==(const xml_attribute_iterator& rhs) const; + bool operator!=(const xml_attribute_iterator& rhs) const; + + xml_attribute& operator*() const; + xml_attribute* operator->() const; + + xml_attribute_iterator& operator++(); + xml_attribute_iterator operator++(int); + + xml_attribute_iterator& operator--(); + xml_attribute_iterator operator--(int); + }; + + // Named node range helper + class PUGIXML_CLASS xml_named_node_iterator + { + friend class xml_node; + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_node value_type; + typedef xml_node* pointer; + typedef xml_node& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_named_node_iterator(); + + // Construct an iterator which points to the specified node + // Note: name pointer is stored in the iterator and must have a longer lifetime than iterator itself + xml_named_node_iterator(const xml_node& node, const char_t* name); + + // Iterator operators + bool operator==(const xml_named_node_iterator& rhs) const; + bool operator!=(const xml_named_node_iterator& rhs) const; + + xml_node& operator*() const; + xml_node* operator->() const; + + xml_named_node_iterator& operator++(); + xml_named_node_iterator operator++(int); + + xml_named_node_iterator& operator--(); + xml_named_node_iterator operator--(int); + + private: + mutable xml_node _wrap; + xml_node _parent; + const char_t* _name; + + xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name); + }; + + // Abstract tree walker class (see xml_node::traverse) + class PUGIXML_CLASS xml_tree_walker + { + friend class xml_node; + + private: + int _depth; + + protected: + // Get current traversal depth + int depth() const; + + public: + xml_tree_walker(); + virtual ~xml_tree_walker(); + + // Callback that is called when traversal begins + virtual bool begin(xml_node& node); + + // Callback that is called for each node traversed + virtual bool for_each(xml_node& node) = 0; + + // Callback that is called when traversal ends + virtual bool end(xml_node& node); + }; + + // Parsing status, returned as part of xml_parse_result object + enum xml_parse_status + { + status_ok = 0, // No error + + status_file_not_found, // File was not found during load_file() + status_io_error, // Error reading from file/stream + status_out_of_memory, // Could not allocate memory + status_internal_error, // Internal error occurred + + status_unrecognized_tag, // Parser could not determine tag type + + status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction + status_bad_comment, // Parsing error occurred while parsing comment + status_bad_cdata, // Parsing error occurred while parsing CDATA section + status_bad_doctype, // Parsing error occurred while parsing document type declaration + status_bad_pcdata, // Parsing error occurred while parsing PCDATA section + status_bad_start_element, // Parsing error occurred while parsing start element tag + status_bad_attribute, // Parsing error occurred while parsing element attribute + status_bad_end_element, // Parsing error occurred while parsing end element tag + status_end_element_mismatch,// There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag) + + status_append_invalid_root, // Unable to append nodes since root type is not node_element or node_document (exclusive to xml_node::append_buffer) + + status_no_document_element // Parsing resulted in a document without element nodes + }; + + // Parsing result + struct PUGIXML_CLASS xml_parse_result + { + // Parsing status (see xml_parse_status) + xml_parse_status status; + + // Last parsed offset (in char_t units from start of input data) + ptrdiff_t offset; + + // Source document encoding + xml_encoding encoding; + + // Default constructor, initializes object to failed state + xml_parse_result(); + + // Cast to bool operator + operator bool() const; + + // Get error description + const char* description() const; + }; + + // Document class (DOM tree root) + class PUGIXML_CLASS xml_document: public xml_node + { + private: + char_t* _buffer; + + char _memory[192]; + + // Non-copyable semantics + xml_document(const xml_document&); + xml_document& operator=(const xml_document&); + + void _create(); + void _destroy(); + void _move(xml_document& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; + + public: + // Default constructor, makes empty document + xml_document(); + + // Destructor, invalidates all node/attribute handles to this document + ~xml_document(); + + #ifdef PUGIXML_HAS_MOVE + // Move semantics support + xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; + xml_document& operator=(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; + #endif + + // Removes all nodes, leaving the empty document + void reset(); + + // Removes all nodes, then copies the entire contents of the specified document + void reset(const xml_document& proto); + + #ifndef PUGIXML_NO_STL + // Load document from stream. + xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); + #endif + + // (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied. + PUGIXML_DEPRECATED xml_parse_result load(const char_t* contents, unsigned int options = parse_default); + + // Load document from zero-terminated string. No encoding conversions are applied. + xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default); + + // Load document from file + xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns. + xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). + // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed. + xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). + // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore). + xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details). + void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + + #ifndef PUGIXML_NO_STL + // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). + void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; + #endif + + // Save XML to file + bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + + // Get document element + xml_node document_element() const; + }; + +#ifndef PUGIXML_NO_XPATH + // XPath query return type + enum xpath_value_type + { + xpath_type_none, // Unknown type (query failed to compile) + xpath_type_node_set, // Node set (xpath_node_set) + xpath_type_number, // Number + xpath_type_string, // String + xpath_type_boolean // Boolean + }; + + // XPath parsing result + struct PUGIXML_CLASS xpath_parse_result + { + // Error message (0 if no error) + const char* error; + + // Last parsed offset (in char_t units from string start) + ptrdiff_t offset; + + // Default constructor, initializes object to failed state + xpath_parse_result(); + + // Cast to bool operator + operator bool() const; + + // Get error description + const char* description() const; + }; + + // A single XPath variable + class PUGIXML_CLASS xpath_variable + { + friend class xpath_variable_set; + + protected: + xpath_value_type _type; + xpath_variable* _next; + + xpath_variable(xpath_value_type type); + + // Non-copyable semantics + xpath_variable(const xpath_variable&); + xpath_variable& operator=(const xpath_variable&); + + public: + // Get variable name + const char_t* name() const; + + // Get variable type + xpath_value_type type() const; + + // Get variable value; no type conversion is performed, default value (false, NaN, empty string, empty node set) is returned on type mismatch error + bool get_boolean() const; + double get_number() const; + const char_t* get_string() const; + const xpath_node_set& get_node_set() const; + + // Set variable value; no type conversion is performed, false is returned on type mismatch error + bool set(bool value); + bool set(double value); + bool set(const char_t* value); + bool set(const xpath_node_set& value); + }; + + // A set of XPath variables + class PUGIXML_CLASS xpath_variable_set + { + private: + xpath_variable* _data[64]; + + void _assign(const xpath_variable_set& rhs); + void _swap(xpath_variable_set& rhs); + + xpath_variable* _find(const char_t* name) const; + + static bool _clone(xpath_variable* var, xpath_variable** out_result); + static void _destroy(xpath_variable* var); + + public: + // Default constructor/destructor + xpath_variable_set(); + ~xpath_variable_set(); + + // Copy constructor/assignment operator + xpath_variable_set(const xpath_variable_set& rhs); + xpath_variable_set& operator=(const xpath_variable_set& rhs); + + #ifdef PUGIXML_HAS_MOVE + // Move semantics support + xpath_variable_set(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT; + xpath_variable_set& operator=(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT; + #endif + + // Add a new variable or get the existing one, if the types match + xpath_variable* add(const char_t* name, xpath_value_type type); + + // Set value of an existing variable; no type conversion is performed, false is returned if there is no such variable or if types mismatch + bool set(const char_t* name, bool value); + bool set(const char_t* name, double value); + bool set(const char_t* name, const char_t* value); + bool set(const char_t* name, const xpath_node_set& value); + + // Get existing variable by name + xpath_variable* get(const char_t* name); + const xpath_variable* get(const char_t* name) const; + }; + + // A compiled XPath query object + class PUGIXML_CLASS xpath_query + { + private: + void* _impl; + xpath_parse_result _result; + + typedef void (*unspecified_bool_type)(xpath_query***); + + // Non-copyable semantics + xpath_query(const xpath_query&); + xpath_query& operator=(const xpath_query&); + + public: + // Construct a compiled object from XPath expression. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. + explicit xpath_query(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL); + + // Constructor + xpath_query(); + + // Destructor + ~xpath_query(); + + #ifdef PUGIXML_HAS_MOVE + // Move semantics support + xpath_query(xpath_query&& rhs) PUGIXML_NOEXCEPT; + xpath_query& operator=(xpath_query&& rhs) PUGIXML_NOEXCEPT; + #endif + + // Get query expression return type + xpath_value_type return_type() const; + + // Evaluate expression as boolean value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + bool evaluate_boolean(const xpath_node& n) const; + + // Evaluate expression as double value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + double evaluate_number(const xpath_node& n) const; + + #ifndef PUGIXML_NO_STL + // Evaluate expression as string value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + string_t evaluate_string(const xpath_node& n) const; + #endif + + // Evaluate expression as string value in the specified context; performs type conversion if necessary. + // At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero). + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead. + size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const; + + // Evaluate expression as node set in the specified context. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node set instead. + xpath_node_set evaluate_node_set(const xpath_node& n) const; + + // Evaluate expression as node set in the specified context. + // Return first node in document order, or empty node if node set is empty. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node instead. + xpath_node evaluate_node(const xpath_node& n) const; + + // Get parsing result (used to get compilation errors in PUGIXML_NO_EXCEPTIONS mode) + const xpath_parse_result& result() const; + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + }; + + #ifndef PUGIXML_NO_EXCEPTIONS + #if defined(_MSC_VER) + // C4275 can be ignored in Visual C++ if you are deriving + // from a type in the Standard C++ Library + #pragma warning(push) + #pragma warning(disable: 4275) + #endif + // XPath exception class + class PUGIXML_CLASS xpath_exception: public std::exception + { + private: + xpath_parse_result _result; + + public: + // Construct exception from parse result + explicit xpath_exception(const xpath_parse_result& result); + + // Get error message + virtual const char* what() const throw() PUGIXML_OVERRIDE; + + // Get parse result + const xpath_parse_result& result() const; + }; + #if defined(_MSC_VER) + #pragma warning(pop) + #endif + #endif + + // XPath node class (either xml_node or xml_attribute) + class PUGIXML_CLASS xpath_node + { + private: + xml_node _node; + xml_attribute _attribute; + + typedef void (*unspecified_bool_type)(xpath_node***); + + public: + // Default constructor; constructs empty XPath node + xpath_node(); + + // Construct XPath node from XML node/attribute + xpath_node(const xml_node& node); + xpath_node(const xml_attribute& attribute, const xml_node& parent); + + // Get node/attribute, if any + xml_node node() const; + xml_attribute attribute() const; + + // Get parent of contained node/attribute + xml_node parent() const; + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators + bool operator==(const xpath_node& n) const; + bool operator!=(const xpath_node& n) const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xpath_node& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xpath_node& lhs, bool rhs); +#endif + + // A fixed-size collection of XPath nodes + class PUGIXML_CLASS xpath_node_set + { + public: + // Collection type + enum type_t + { + type_unsorted, // Not ordered + type_sorted, // Sorted by document order (ascending) + type_sorted_reverse // Sorted by document order (descending) + }; + + // Constant iterator type + typedef const xpath_node* const_iterator; + + // We define non-constant iterator to be the same as constant iterator so that various generic algorithms (i.e. boost foreach) work + typedef const xpath_node* iterator; + + // Default constructor. Constructs empty set. + xpath_node_set(); + + // Constructs a set from iterator range; data is not checked for duplicates and is not sorted according to provided type, so be careful + xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted); + + // Destructor + ~xpath_node_set(); + + // Copy constructor/assignment operator + xpath_node_set(const xpath_node_set& ns); + xpath_node_set& operator=(const xpath_node_set& ns); + + #ifdef PUGIXML_HAS_MOVE + // Move semantics support + xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT; + xpath_node_set& operator=(xpath_node_set&& rhs) PUGIXML_NOEXCEPT; + #endif + + // Get collection type + type_t type() const; + + // Get collection size + size_t size() const; + + // Indexing operator + const xpath_node& operator[](size_t index) const; + + // Collection iterators + const_iterator begin() const; + const_iterator end() const; + + // Sort the collection in ascending/descending order by document order + void sort(bool reverse = false); + + // Get first node in the collection by document order + xpath_node first() const; + + // Check if collection is empty + bool empty() const; + + private: + type_t _type; + + xpath_node _storage[1]; + + xpath_node* _begin; + xpath_node* _end; + + void _assign(const_iterator begin, const_iterator end, type_t type); + void _move(xpath_node_set& rhs) PUGIXML_NOEXCEPT; + }; +#endif + +#ifndef PUGIXML_NO_STL + // Convert wide string to UTF8 + std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); + std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); + + // Convert UTF8 to wide string + std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); + std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); +#endif + + // Memory allocation function interface; returns pointer to allocated memory or NULL on failure + typedef void* (*allocation_function)(size_t size); + + // Memory deallocation function interface + typedef void (*deallocation_function)(void* ptr); + + // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions. + void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate); + + // Get current memory management functions + allocation_function PUGIXML_FUNCTION get_memory_allocation_function(); + deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function(); +} + +#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) +namespace std +{ + // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&); +} +#endif + +#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) +namespace std +{ + // Workarounds for (non-standard) iterator category detection + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&); +} +#endif + +#endif + +// Make sure implementation is included in header-only mode +// Use macro expansion in #include to work around QMake (QTBUG-11923) +#if defined(PUGIXML_HEADER_ONLY) && !defined(PUGIXML_SOURCE) +# define PUGIXML_SOURCE "pugixml.cpp" +# include PUGIXML_SOURCE +#endif + +/** + * Copyright (c) 2006-2023 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/include/vrv/adjustslursfunctor.h b/include/vrv/adjustslursfunctor.h index af32d918c71..cc4665938fc 100644 --- a/include/vrv/adjustslursfunctor.h +++ b/include/vrv/adjustslursfunctor.h @@ -9,9 +9,36 @@ #define __VRV_ADJUSTSLURSFUNCTOR_H__ #include "functor.h" +#include "slur.h" namespace vrv { +//---------------------------------------------------------------------------- +// ControlPointConstraint +//---------------------------------------------------------------------------- +/** + * This represents a constraint ax + by >= c where x and y are + * vertical control point adjustments + */ +struct ControlPointConstraint { + double a; + double b; + double c; +}; + +//---------------------------------------------------------------------------- +// ControlPointAdjustment +//---------------------------------------------------------------------------- +/** + * A vertical adjustment of bezier control points + */ +struct ControlPointAdjustment { + int leftShift; + int rightShift; + bool moveUpwards; + int requestedStaffSpace; +}; + //---------------------------------------------------------------------------- // AdjustSlursFunctor //---------------------------------------------------------------------------- @@ -39,6 +66,11 @@ class AdjustSlursFunctor : public DocFunctor { */ bool HasCrossStaffSlurs() const { return m_crossStaffSlurs; } + /* + * Reset the current slur and curve + */ + void ResetCurrent(); + /* * Functor interface */ @@ -50,12 +82,97 @@ class AdjustSlursFunctor : public DocFunctor { protected: // private: - // + /** + * High level helper functions + */ + ///@{ + void AdjustSlur(int unit) const; + + void AdjustOuterSlur(const ArrayOfFloatingCurvePositioners &innerCurves, int unit) const; + ///@} + + /** + * Intermediate level helper functions + */ + ///@{ + // Discard certain spanned elements + void FilterSpannedElements(const BezierCurve &bezierCurve, int margin) const; + + // Detect collisions near the endpoints + NearEndCollision DetectCollisionsNearEnd(const BezierCurve &bezierCurve, int margin) const; + + // Calculate the vertical shift of the slur end points + std::pair CalcEndPointShift(const BezierCurve &bezierCurve, double flexibility, int margin) const; + + // Apply the vertical shift of the slur end points + void ApplyEndPointShift(BezierCurve &bezierCurve, int endPointShiftLeft, int endPointShiftRight) const; + + // Calculate slur from bulge values + void AdjustSlurFromBulge(BezierCurve &bezierCurve, int unit) const; + + // Check whether control points should be adjusted horizontally + bool AllowControlOffsetAdjustment(const BezierCurve &bezierCurve, double symmetry, int unit) const; + + // Calculate the horizontal control point offset + std::tuple CalcControlPointOffset(const BezierCurve &bezierCurve, int margin) const; + + // Calculate the vertical control point shift + ControlPointAdjustment CalcControlPointVerticalShift( + const BezierCurve &bezierCurve, double symmetry, int margin) const; + + // Solve the constraints for vertical control point adjustment + std::pair SolveControlPointConstraints( + const std::list &constraints, double symmetry = 0.0) const; + + // Improve the slur shape by adjusting the control point heights + void AdjustSlurShape(BezierCurve &bezierCurve, curvature_CURVEDIR dir, int unit) const; + ///@} + + /** + * Intermediate level helper functions for adjustment w.r.t. inner slurs + */ + ///@{ + // Calculate the vertical control point shift + ControlPointAdjustment CalcControlPointShift(const BezierCurve &bezierCurve, + const ArrayOfFloatingCurvePositioners &innerCurves, double symmetry, int margin) const; + + // Calculate the vertical shift of the slur end points + std::pair CalcEndPointShift(const BezierCurve &bezierCurve, + const ArrayOfFloatingCurvePositioners &innerCurves, double flexibility, int margin) const; + ///@} + + /** + * Low level helper functions + */ + ///@{ + // Shift end points for collisions nearby + void ShiftEndPoints(int &shiftLeft, int &shiftRight, double ratio, int intersection, double flexibility, + bool isBelow, char spanningType) const; + + // Calculate the full and partial shift radii + std::pair CalcShiftRadii(bool forShiftLeft, double flexibility, char spanningType) const; + + // Determine a quadratic interpolation function between zero and one and evaluate it + double CalcQuadraticInterpolation(double zeroAt, double oneAt, double arg) const; + + // Rotate the slope by a given number of degrees, but choose smaller angles if already close to the vertical axis + // Choose doublingBound as the positive slope value where doubling has the same effect as rotating: + // tan(atan(doublingBound) + degrees * PI / 180.0) ≈ 2.0 * doublingBound + double RotateSlope(double slope, double degrees, double doublingBound, bool upwards) const; + + // Calculate the minimal angle <)C1P1P2 or <)P1P2C2 + float GetMinControlPointAngle(const BezierCurve &bezierCurve, float angle, int unit) const; + ///@} + public: // private: // Indicates that there is at least one cross-staff slur bool m_crossStaffSlurs; + // The current slur + Slur *m_currentSlur; + // The curve positioner + FloatingCurvePositioner *m_currentCurve; }; } // namespace vrv diff --git a/include/vrv/bboxdevicecontext.h b/include/vrv/bboxdevicecontext.h index e22c3408618..05b63b990ba 100644 --- a/include/vrv/bboxdevicecontext.h +++ b/include/vrv/bboxdevicecontext.h @@ -115,7 +115,7 @@ class BBoxDeviceContext : public DeviceContext { * @name Method for starting and ending a graphic */ ///@{ - void StartGraphic(Object *object, std::string gClass, std::string gId, GraphicID graphicID = PRIMARY, + void StartGraphic(Object *object, const std::string &gClass, const std::string &gId, GraphicID graphicID = PRIMARY, bool prepend = false) override; void EndGraphic(Object *object, View *view) override; ///@} diff --git a/include/vrv/boundingbox.h b/include/vrv/boundingbox.h index c4c7e1a3308..20a437657c5 100644 --- a/include/vrv/boundingbox.h +++ b/include/vrv/boundingbox.h @@ -182,7 +182,8 @@ class BoundingBox { * A segment of the beam that matches horizontal position of the bounding box is taken to find whether there is * intersection. */ - int Intersects(const BeamDrawingInterface *beamInterface, Accessor type, int margin = 0) const; + int Intersects(const BeamDrawingInterface *beamInterface, Accessor type, int margin = 0, + bool fromBeamContentSide = false) const; //----------------// // Static methods // diff --git a/include/vrv/btrem.h b/include/vrv/btrem.h index c7c11b804d0..9d64e26e046 100644 --- a/include/vrv/btrem.h +++ b/include/vrv/btrem.h @@ -21,9 +21,9 @@ namespace vrv { * This class models the MEI element. */ class BTrem : public LayerElement, - public AttBTremLog, public AttNumbered, public AttNumberPlacement, + public AttTremForm, public AttTremMeasured { public: /** diff --git a/include/vrv/calcalignmentpitchposfunctor.h b/include/vrv/calcalignmentpitchposfunctor.h index d7f4c3d2147..c6c2504f587 100644 --- a/include/vrv/calcalignmentpitchposfunctor.h +++ b/include/vrv/calcalignmentpitchposfunctor.h @@ -40,6 +40,9 @@ class CalcAlignmentPitchPosFunctor : public DocFunctor { */ ///@{ FunctorCode VisitLayerElement(LayerElement *layerElement) override; + FunctorCode VisitScore(Score *score) override; + FunctorCode VisitScoreDef(ScoreDef *scoreDef) override; + FunctorCode VisitStaffDef(StaffDef *staffDef) override; ///@} protected: @@ -49,7 +52,10 @@ class CalcAlignmentPitchPosFunctor : public DocFunctor { public: // private: - // + // The current scoreDef default octave + data_OCTAVE m_octDefault; + // The current staffDef default octaves + std::map m_octDefaultForStaffN; }; } // namespace vrv diff --git a/include/vrv/devicecontext.h b/include/vrv/devicecontext.h index f0255c0b125..e493d38b611 100644 --- a/include/vrv/devicecontext.h +++ b/include/vrv/devicecontext.h @@ -247,8 +247,8 @@ class DeviceContext { * For example, the method can be used for grouping shapes in in SVG */ ///@{ - virtual void StartGraphic( - Object *object, std::string gClass, std::string gId, GraphicID graphicID = PRIMARY, bool preprend = false) + virtual void StartGraphic(Object *object, const std::string &gClass, const std::string &gId, + GraphicID graphicID = PRIMARY, bool preprend = false) = 0; virtual void EndGraphic(Object *object, View *view) = 0; ///@} @@ -258,10 +258,15 @@ class DeviceContext { * For example, the method can be used for grouping shapes in in SVG */ ///@{ - virtual void StartCustomGraphic(std::string name, std::string gClass = "", std::string gId = ""){}; + virtual void StartCustomGraphic(const std::string &name, std::string gClass = "", std::string gId = ""){}; virtual void EndCustomGraphic(){}; ///@} + /** + * Method for changing the color of a custom graphic + */ + virtual void SetCustomGraphicColor(const std::string &color){}; + /** * @name Methods for re-starting and ending a graphic for objects drawn in separate steps * The methods can be used to the output together, for example for a Beam @@ -276,7 +281,7 @@ class DeviceContext { * For example, in SVG, a text graphic is a (and not a ) */ ///@{ - virtual void StartTextGraphic(Object *object, std::string gClass, std::string gId) + virtual void StartTextGraphic(Object *object, const std::string &gClass, const std::string &gId) { StartGraphic(object, gClass, gId); } diff --git a/include/vrv/devicecontextbase.h b/include/vrv/devicecontextbase.h index 3db45409c47..faa51c6d05d 100644 --- a/include/vrv/devicecontextbase.h +++ b/include/vrv/devicecontextbase.h @@ -133,6 +133,7 @@ class FontInfo { FontInfo() { m_pointSize = 0; + m_letterSpacing = 0.0; m_family = 0; // was wxFONTFAMILY_DEFAULT; m_style = FONTSTYLE_NONE; m_weight = FONTWEIGHT_NONE; @@ -147,6 +148,7 @@ class FontInfo { // accessors and modifiers for the font elements int GetPointSize() const { return m_pointSize; } + int GetLetterSpacing() const { return m_letterSpacing; } data_FONTSTYLE GetStyle() const { return m_style; } data_FONTWEIGHT GetWeight() const { return m_weight; } bool GetUnderlined() const { return m_underlined; } @@ -158,6 +160,7 @@ class FontInfo { SmuflTextFont GetSmuflFont() const { return m_smuflFont; } void SetPointSize(int pointSize) { m_pointSize = pointSize; } + void SetLetterSpacing(double letterSpacing) { m_letterSpacing = letterSpacing; } void SetStyle(data_FONTSTYLE style) { m_style = style; } void SetWeight(data_FONTWEIGHT weight) { m_weight = weight; } void SetUnderlined(bool underlined) { m_underlined = underlined; } @@ -171,6 +174,7 @@ class FontInfo { private: int m_pointSize; + int m_letterSpacing; int m_family; data_FONTSTYLE m_style; data_FONTWEIGHT m_weight; diff --git a/include/vrv/div.h b/include/vrv/div.h index 9ba84946929..8c488866910 100644 --- a/include/vrv/div.h +++ b/include/vrv/div.h @@ -18,7 +18,7 @@ namespace vrv { /** * This class represents an MEI Div. - * The current implementation accepts as child of
, which is not valid + * The current implementation accepts rend as child of div, which is not valid * See https://github.com/music-encoding/music-encoding/issues/1189 */ class Div : public TextLayoutElement { diff --git a/include/vrv/divline.h b/include/vrv/divline.h new file mode 100644 index 00000000000..98622e62d5f --- /dev/null +++ b/include/vrv/divline.h @@ -0,0 +1,104 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: divline.h +// Author: Yinan Zhou +// Created: 2021 +// Copyright (c) Authors and others. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +#ifndef __VRV_DIVLINE_H__ +#define __VRV_DIVLINE_H__ + +#include "atts_externalsymbols.h" +#include "atts_neumes.h" +#include "atts_shared.h" +#include "layerelement.h" + +namespace vrv { + +//---------------------------------------------------------------------------- +// DivLine +//---------------------------------------------------------------------------- + +/** + * This class models the MEI element. + */ +class DivLine : public LayerElement, + public AttColor, + public AttDivLineLog, + public AttExtSymAuth, + public AttExtSymNames, + public AttNNumberLike, + public AttVisibility { +public: + /** + * @name Constructors, destructors, and other standard methods + * Reset method resets all attribute classes. + */ + ///@{ + DivLine(); + virtual ~DivLine(); + virtual Object *Clone() const { return new DivLine(*this); } + virtual void Reset(); + virtual std::string GetClassName() const { return "DivLine"; } + ///@} + + /** Override the method since alignment is required */ + virtual bool HasToBeAligned() const { return true; } + + /** + * Use to set the alignment for the Measure BarLine members. + * This is as special case where we need to add to the measure aligner. + */ + bool SetAlignment(Alignment *alignment); + + /** + * Retrieve SMuFL string for the divLine. + */ + std::wstring GetSymbolStr() const; + + /** + * @name Method used for drawing divLine on ornaments + */ + static wchar_t GetDivLineGlyph(divLineLog_FORM); + +private: + // +public: + // +private: +}; + +//---------------------------------------------------------------------------- +// DivLineAttr +//---------------------------------------------------------------------------- + +/** + * This class models the divLine related attributes of a MEI measure. + */ +class DivLineAttr : public DivLine { +public: + /** + * @name Constructors, destructors, and other standard methods + * No Reset() method is required. + */ + ///@{ + DivLineAttr(); + virtual ~DivLineAttr(); + virtual Object *Clone() const { return new DivLineAttr(*this); } + virtual std::string GetClassName() const { return "DivLineAttr"; } + ///@} + + // void SetLeft() { m_isLeft = true; } + +private: + // +public: + // +private: + /** A flag for left barlines (right if false) */ + // bool m_isLeft; +}; + +} // namespace vrv + +#endif diff --git a/include/vrv/doc.h b/include/vrv/doc.h index d1cfdc7a7af..d32fd434a3b 100644 --- a/include/vrv/doc.h +++ b/include/vrv/doc.h @@ -90,12 +90,12 @@ class Doc : public Object { /** * Generate a document pgFoot if none is provided */ - bool GenerateFooter(); + void GenerateFooter(); /** * Generate a document pgHead from the MEI header if none is provided */ - bool GenerateHeader(); + void GenerateHeader(); /** * Generate measure numbers from measure attributes @@ -121,11 +121,6 @@ class Doc : public Object { */ bool HasPage(int pageIdx) const; - /** - * Get all the Score in the visible Mdiv. - */ - std::list GetScores(); - /** * Get the Pages in the visible Mdiv. * Will find it only when having read a pages-based MEI file, @@ -141,6 +136,31 @@ class Doc : public Object { */ int GetPageCount() const; + /** + * Get the first scoreDef + */ + ///@{ + ScoreDef *GetFirstScoreDef(); + const ScoreDef *GetFirstScoreDef() const; + ///@} + + /** + * Get all visible scores / the first visible score + * Lazily updates the visible scores, hence not const + */ + ///@{ + std::list GetVisibleScores(); + Score *GetFirstVisibleScore(); + ///@} + + /** + * Get the corresponding score for a node + */ + ///@{ + Score *GetCorrespondingScore(const Object *object); + const Score *GetCorrespondingScore(const Object *object) const; + ///@} + /** * Return true if the MIDI generation is already done */ @@ -225,7 +245,7 @@ class Doc : public Object { * Get the default distance from the staff for the object * The distance is given in x * MEI UNIT */ - data_MEASUREMENTSIGNED GetStaffDistance(const ClassId classId, int staffIndex, data_STAFFREL staffPosition); + data_MEASUREMENTSIGNED GetStaffDistance(const Object *object, int staffIndex, data_STAFFREL staffPosition) const; /** * Prepare the timemap for MIDI and timemap file export. @@ -418,19 +438,6 @@ class Doc : public Object { bool HasFacsimile() const { return m_facsimile != NULL; } ///@} - /** - * @name Setter and getter for the current Score/ScoreDef. - * If not set, then looks for the first Score in the Document and use that. - * The currentScoreDef is also changed by the Object::Process whenever as Score is reached. - * When processing backward, the ScoreDef is changed when reaching the corresponding PageMilestoneEnd - */ - ///@{ - Score *GetCurrentScore(); - ScoreDef *GetCurrentScoreDef(); - void SetCurrentScore(Score *score); - bool HasCurrentScore() const { return m_currentScore != NULL; } - ///@} - /** * Return true if the document has been cast off already. */ @@ -477,6 +484,11 @@ class Doc : public Object { */ void PrepareMeasureIndices(); + /** + * Determine all visible scores + */ + void CollectVisibleScores(); + public: Page *m_selectionPreceding; Page *m_selectionFollowing; @@ -498,6 +510,11 @@ class Doc : public Object { */ pugi::xml_document m_back; + /** + * The music@decls value + */ + std::string m_musicDecls; + /** The current page height */ int m_drawingPageHeight; /** The current page width */ @@ -546,12 +563,10 @@ class Doc : public Object { Resources m_resources; /** - * @name Holds a pointer to the current score/scoreDef. - * Set by Doc::GetCurrentScoreDef or explicitly through Doc::SetCurrentScoreDef + * The list of all visible scores + * Used in Doc::GetCorrespondingScore to quickly determine the score for an object */ - ///@{ - Score *m_currentScore; - ///@} + std::list m_visibleScores; /** * A flag indicating if the document has been cast off or not. diff --git a/include/vrv/drawinginterface.h b/include/vrv/drawinginterface.h index cd915eaa3c0..32d2e88e253 100644 --- a/include/vrv/drawinginterface.h +++ b/include/vrv/drawinginterface.h @@ -95,12 +95,10 @@ class BeamDrawingInterface : public ObjectListInterface { /** * Return information about the position in the beam. - * (no const since the cached list is updated) - * Object * is a pointer to the object implementing the interface (e.g., Beam, fTrem) */ ///@{ - bool IsFirstIn(const Object *object, const LayerElement *element) const; - bool IsLastIn(const Object *object, const LayerElement *element) const; + bool IsFirstIn(const LayerElement *element) const; + bool IsLastIn(const LayerElement *element) const; ///@} /** @@ -113,11 +111,17 @@ class BeamDrawingInterface : public ObjectListInterface { ///@} /** - * Initialize m_cueSize value based on the @cue attribute and presence of child elements with @cue/@grace + * Initialize m_cueSize value based on the @cue attribute and presence of child elements with @cue * attributes */ void InitCue(bool beamCue); + /** + * Initialize m_notesStemDir value based on the @graceGrp attribute and presence of child elements with @grace + * attributes + */ + void InitGraceStemDir(bool graceGrp); + bool IsHorizontal() const; bool IsRepeatedPattern() const; @@ -163,7 +167,7 @@ class BeamDrawingInterface : public ObjectListInterface { * Return the position of the element in the beam. * For notes, lookup the position of the parent chord. */ - int GetPosition(const Object *object, const LayerElement *element) const; + int GetPosition(const LayerElement *element) const; // private: diff --git a/include/vrv/editortoolkit_neume.h b/include/vrv/editortoolkit_neume.h index e265398335f..dfeb65043e5 100644 --- a/include/vrv/editortoolkit_neume.h +++ b/include/vrv/editortoolkit_neume.h @@ -17,6 +17,7 @@ #include "doc.h" #include "editortoolkit.h" #include "view.h" +#include "vrv.h" #include "zone.h" #include "jsonxx.h" @@ -38,36 +39,46 @@ class EditorToolkitNeume : public EditorToolkit { */ ///@{ bool Chain(jsonxx::Array actions); + bool DisplaceClefOctave(std::string elementId, std::string direction); bool Drag(std::string elementId, int x, int y); bool Insert(std::string elementType, std::string staffId, int ulx, int uly, int lrx, int lry, std::vector> attributes); + bool InsertToSyllable(std::string elementId); bool Merge(std::vector elementIds); + bool MoveOutsideSyllable(std::string elementId); bool Set(std::string elementId, std::string attrType, std::string attrValue); bool SetText(std::string elementId, const std::string &text); bool SetClef(std::string elementId, std::string shape); bool Split(std::string elementId, int x); + bool SplitNeume(std::string elementId, std::string ncId); bool Remove(std::string elementId); bool Resize(std::string elementId, int ulx, int uly, int lrx, int lry, float resize = NAN); bool Group(std::string groupType, std::vector elementIds); bool Ungroup(std::string groupType, std::vector elementIds); bool ChangeGroup(std::string elementId, std::string contour); - bool ToggleLigature(std::vector elementIds, std::string isLigature); + bool ToggleLigature(std::vector elementIds); bool ChangeStaff(std::string elementId); + bool ChangeStaffTo(std::string elementId, std::string staffId); + bool ClefMovementHandler(Clef *clef, int x, int y); ///@} protected: /** * Parse JSON instructions for experimental editor functions. */ ///@{ + bool ParseDisplaceClefAction(jsonxx::Object param, std::string *elementId, std::string *direction); bool ParseDragAction(jsonxx::Object param, std::string *elementId, int *x, int *y); bool ParseInsertAction(jsonxx::Object param, std::string *elementType, std::string *startId, std::string *endId); bool ParseInsertAction(jsonxx::Object param, std::string *elementType, std::string *staffId, int *ulx, int *uly, int *lrx, int *lry, std::vector> *attributes); + bool ParseInsertToSyllableAction(jsonxx::Object param, std::string *elementId); bool ParseMergeAction(jsonxx::Object param, std::vector *elementIds); + bool ParseMoveOutsideSyllableAction(jsonxx::Object param, std::string *elementId); bool ParseSetAction(jsonxx::Object param, std::string *elementId, std::string *attrType, std::string *attrValue); bool ParseSetTextAction(jsonxx::Object param, std::string *elementId, std::string *text); bool ParseSetClefAction(jsonxx::Object param, std::string *elementId, std::string *shape); bool ParseSplitAction(jsonxx::Object param, std::string *elementId, int *x); + bool ParseSplitNeumeAction(jsonxx::Object param, std::string *elementId, std::string *ncId); bool ParseRemoveAction(jsonxx::Object param, std::string *elementId); bool ParseResizeAction(jsonxx::Object param, std::string *elementId, int *ulx, int *uly, int *lrx, int *lry); bool ParseResizeRotateAction( @@ -75,8 +86,9 @@ class EditorToolkitNeume : public EditorToolkit { bool ParseGroupAction(jsonxx::Object param, std::string *groupType, std::vector *elementIds); bool ParseUngroupAction(jsonxx::Object param, std::string *groupType, std::vector *elementIds); bool ParseChangeGroupAction(jsonxx::Object param, std::string *elementId, std::string *contour); - bool ParseToggleLigatureAction(jsonxx::Object param, std::vector *elementIds, std::string *isLigature); + bool ParseToggleLigatureAction(jsonxx::Object param, std::vector *elementIds); bool ParseChangeStaffAction(jsonxx::Object param, std::string *elementId); + bool ParseChangeStaffToAction(jsonxx::Object param, std::string *elementId, std::string *staffId); ///@} /** @@ -104,8 +116,8 @@ struct ClosestBB { int distanceToBB(int ulx, int uly, int lrx, int lry, double rotate = 0) { int offset = (x - ulx) * tan(rotate * M_PI / 180.0); - uly = uly - offset; - lry = lry - offset; + uly = uly + offset; + lry = lry + offset; int xDiff = std::max((ulx > x ? ulx - x : 0), (x > lrx ? x - lrx : 0)); int yDiff = std::max((uly > y ? uly - y : 0), (y > lry ? y - lry : 0)); @@ -126,11 +138,45 @@ struct ClosestBB { } }; +// To be used with std::stable_sort to find the position to insert a new accid / divLine +struct ClosestNeume { + int x; + int y; + + bool operator()(Object *a, Object *b) + { + // check if neume has neume components + if (!a->GetFirst(NC)) { + LogError("Neume %s doesn't have neume components.", a->GetID().c_str()); + return true; + } + if (!b->GetFirst(NC)) { + LogError("Neume %s doesn't have neume components.", b->GetID().c_str()); + return true; + } + if (!a->GetFirst(NC)->GetFacsimileInterface()) { + LogError("Neume component %s doesn't have facsimile.", a->GetFirst(NC)->GetID().c_str()); + return true; + } + if (!b->GetFirst(NC)->GetFacsimileInterface()) { + LogError("Neume component %s doesn't have facsimile.", b->GetFirst(NC)->GetID().c_str()); + return true; + } + Zone *zoneA = a->GetFirst(NC)->GetFacsimileInterface()->GetZone(); + Zone *zoneB = b->GetFirst(NC)->GetFacsimileInterface()->GetZone(); + + int distA = std::abs(x - zoneA->GetUlx()); + int distB = std::abs(x - zoneB->GetUlx()); + + return (distA < distB); + } +}; + // To be used with std::stable_sort to find the position to insert a new staff struct StaffSort { // Sort staves left-to-right and top-to-bottom - // Sort by y if there is no intersection, by x if there is + // Sort by y if there is no intersection, by x if there is x intersection is smaller than half length of staff line bool operator()(Object *a, Object *b) { if (!a->GetFacsimileInterface() || !b->GetFacsimileInterface()) return true; @@ -156,8 +202,11 @@ struct StaffSort { : zoneB->GetUly() - (zoneB->GetLrx() - zoneB->GetUlx()) * tan(zoneB->GetRotate() * M_PI / 180.0); // Check for y intersection - if ((aLowest <= bLowest && aLowest >= bHighest) || (aHighest <= bLowest && aHighest >= bHighest) - || (bLowest <= aLowest && bLowest >= aHighest) || (bHighest <= aLowest && bHighest >= aHighest)) { + // if the x intersection part is smaller than half of length of staffA + // sort by x coordinate + if (((aLowest <= bLowest && aLowest >= bHighest) || (aHighest <= bLowest && aHighest >= bHighest) + || (bLowest <= aLowest && bLowest >= aHighest) || (bHighest <= aLowest && bHighest >= aHighest)) + && (zoneA->GetLrx() - zoneB->GetUlx() <= 0.5 * (zoneA->GetLrx() - zoneA->GetUlx()))) { // sort by x center return (zoneA->GetUlx() < zoneB->GetUlx()); } diff --git a/include/vrv/floatingobject.h b/include/vrv/floatingobject.h index aaa9d9edcf3..f6cd1f450a3 100644 --- a/include/vrv/floatingobject.h +++ b/include/vrv/floatingobject.h @@ -251,7 +251,7 @@ class FloatingPositioner : public BoundingBox { /** * Update the Y drawing relative position based on collision detection with the overlapping bounding box */ - void CalcDrawingYRel(Doc *doc, const StaffAlignment *staffAlignment, const BoundingBox *horizOverlappingBBox); + void CalcDrawingYRel(const Doc *doc, const StaffAlignment *staffAlignment, const BoundingBox *horizOverlappingBBox); /** * Align extender elements across systems diff --git a/include/vrv/functor.h b/include/vrv/functor.h index 54185b9ecb9..6a08fac2bea 100644 --- a/include/vrv/functor.h +++ b/include/vrv/functor.h @@ -8,8 +8,6 @@ #ifndef __VRV_FUNCTOR_H__ #define __VRV_FUNCTOR_H__ -#include - #include "comparison.h" #include "functorinterface.h" #include "vrvdef.h" @@ -31,7 +29,7 @@ class FunctorBase { * @name Constructors, destructors */ ///@{ - FunctorBase(){}; + FunctorBase() {} virtual ~FunctorBase() = default; ///@} @@ -45,16 +43,7 @@ class FunctorBase { ///@} /** - * Getters/Setters for the filters - */ - ///@{ - Filters *GetFilters() { return m_filters.empty() ? NULL : m_filters.top(); } - void PushFilters(Filters *filters) { m_filters.push(filters); } - void PopFilters() { m_filters.pop(); } - ///@} - - /** - * Getters/Setters for the visibility + * Getter/Setter for the visibility */ ///@{ bool VisibleOnly() const { return m_visibleOnly; } @@ -62,12 +51,24 @@ class FunctorBase { ///@} /** - * Getters/Setters for the direction + * Getters/Setters for the filters and direction + * Here setters return the previous value */ ///@{ - bool GetDirection() const { return m_direction.empty() ? FORWARD : m_direction.top(); } - void PushDirection(bool direction) { m_direction.push(direction); } - void PopDirection() { m_direction.pop(); } + Filters *GetFilters() const { return m_filters; } + Filters *SetFilters(Filters *filters) + { + Filters *previous = m_filters; + m_filters = filters; + return previous; + } + bool GetDirection() const { return m_direction; } + bool SetDirection(bool direction) + { + bool previous = m_direction; + m_direction = direction; + return previous; + } ///@} /** @@ -82,12 +83,12 @@ class FunctorBase { private: // The functor code FunctorCode m_code = FUNCTOR_CONTINUE; - // The filter stack - std::stack m_filters; + // The filters + Filters *m_filters = NULL; // Visible only flag bool m_visibleOnly = true; - // The direction stack - std::stack m_direction; + // Direction + bool m_direction = FORWARD; }; //---------------------------------------------------------------------------- @@ -103,7 +104,7 @@ class Functor : public FunctorBase, public FunctorInterface { * @name Constructors, destructors */ ///@{ - Functor(){}; + Functor() {} virtual ~Functor() = default; ///@} @@ -128,7 +129,7 @@ class ConstFunctor : public FunctorBase, public ConstFunctorInterface { * @name Constructors, destructors */ ///@{ - ConstFunctor(){}; + ConstFunctor() {} virtual ~ConstFunctor() = default; ///@} diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index 1e3ae47f246..9c8a8da8160 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -45,6 +45,7 @@ enum AlignmentType { ALIGNMENT_ACCID, ALIGNMENT_GRACENOTE, ALIGNMENT_BARLINE, + ALIGNMENT_DIVLINE, ALIGNMENT_DEFAULT, // Non-justifiable ALIGNMENT_MEASURE_RIGHT_BARLINE, diff --git a/include/vrv/iohumdrum.h b/include/vrv/iohumdrum.h index 9036fe2cfde..f5ac61083e2 100644 --- a/include/vrv/iohumdrum.h +++ b/include/vrv/iohumdrum.h @@ -22,6 +22,7 @@ #include "clef.h" #include "dir.h" #include "ending.h" +#include "fing.h" #include "ftrem.h" #include "harm.h" #include "io.h" @@ -365,12 +366,19 @@ class HumdrumSignifiers { bool empty = true; // boolean switches: - char nostem = '\0'; // !!!RDF**kern: N = no stem - char cuesize = '\0'; // !!!RDF**kern: @ = cue size - char terminallong = '\0'; // !!!RDF**kern: l = terminal long - char terminalbreve = '\0'; // !!!RDF**kern: l = terminal breve - std::vector editacc; // !!!RDF**kern: i = editorial accidental - std::vector edittype; // !!!RDF**kern: i = editoral accidental, brack[ets]/paren[theses] + std::string nostem; // !!!RDF**kern: N = no stem + std::string cuesize; // !!!RDF**kern: @ = cue size + + std::string kernTerminalLong; // !!!RDF**kern: l = terminal long + std::string kernTerminalBreve; // !!!RDF**kern: l = terminal breve + + std::string mensTerminalLong; // !!!RDF**mens: l = terminal long + std::string mensTerminalBreve; // !!!RDF**mens: l = terminal breve + + std::vector editaccKern; // !!!RDF**kern: i = editorial accidental + std::vector editaccMens; // !!!RDF**mens: z = editorial accidental + std::vector edittypeKern; // !!!RDF**kern: i = editoral accidental, brack[ets]/paren[theses] + std::vector edittypeMens; // !!!RDF**mens: z = editoral accidental, brack[ets]/paren[theses] // for **dynam: std::string cresctext; // !!!RDF**kern: > = "cresc." @@ -378,8 +386,8 @@ class HumdrumSignifiers { std::string decresctext; // !!!RDF**kern: > = "decresc." std::string decrescfontstyle; // !!!RDF**kern: < = "decresc." fontstyle="normal|italic|bold|bold-italic" - char below = '\0'; // !!!RDF**kern: < = below (previous signifier is "below") - char above = '\0'; // !!!RDF**kern: > = above (previous signifier is "above") + std::string below; // !!!RDF**kern: < = below (previous signifier is "below") + std::string above; // !!!RDF**kern: > = above (previous signifier is "above") std::string phrase_color; // for global stying of phrase markers std::string phrase_style; // for global stying of phrase markers @@ -397,30 +405,77 @@ class HumdrumSignifiers { // default is red if no color given: // !!!RDF**kern: i = matched note // !!!RDF**kern: i = marked note - std::vector mark; + std::vector mark; std::vector mcolor; std::vector markdir; // Coloring of **mens notes (not for coloration). // default color is hotpink, since red is used for // colored notes in black notation. - std::vector mens_mark; + std::vector mens_mark; std::vector mens_mcolor; std::vector mens_markdir; // Coloring of **text: - std::vector textmark; + std::vector textmark; std::vector textcolor; // Articulation signfiers - char hairpinAccent = '\0'; // For <> accent on a note. - char verticalStroke = '\0'; // For horizontal stroke ornament - char lhpizz = '\0'; // For left-hand pizzicato - char tremolo = '\0'; // For unmeasured tremolo slashes + std::string hairpinAccent; // For <> accent on a note. + std::string verticalStroke; // For horizontal stroke ornament + std::string lhpizz; // For left-hand pizzicato + std::string tremolo; // For unmeasured tremolo slashes }; #endif /* NO_HUMDRUM_SUPPORT */ +struct HumdrumReferenceItem { + std::string lineText; // the full text of the HumdrumLine containing this item, + // e.g. "!!!OTL2@FR:Le deuxième titre Français" + std::string key; // the interpreted key, with key, index, isTranslated, language stripped out + // e.g. "OTL" (if not parseable, we get everything between "!!!" and ":") + std::string value; // the value (everything after the ':') + // e.g. "Le deuxième titre Français" + bool isParseable = false; // true if we could parse out key, index, isTranslated, language + // e.g. true + bool isHumdrumKey = false; // true if isParseable and key is in the known list of Humdrum keys + // e.g. true + bool isTranslated = false; // true if single '@' (not '@@') is present + // e.g. true + std::string language; // the language, if present, lowercased + // e.g. "fr" + int index = -1; // the index (0 if not present) + // e.g. 2 +}; + +struct DateWithErrors { + bool valid = false; // if false, ignore everything here, the date was not parseable. + std::string dateError; // error of the entire date ("", "approximate", "uncertain") + int year; + std::string yearError; // error of the year ("", "approximate", "uncertain") + int month; + std::string monthError; // error of the month ("", "approximate", "uncertain") + int day; + std::string dayError; // error of the day ("", "approximate", "uncertain") + int hour; + std::string hourError; // error of the hour ("", "approximate", "uncertain") + int minute; + std::string minuteError; // error of the minute ("", "approximate", "uncertain") + int second; + std::string secondError; // error of the second ("", "approximate", "uncertain") +}; + +struct DateConstruct { + // constructType can be any of "" (invalid), "DateSingle" (one date), "DateRelative" + // (one date, qualifier="before" or "after"), "DateBetween" (two dates), "DateSelection" + // (N dates, qualifier="and" or "or"), or "DateConstructRange" (two DateConstructs). + std::string constructType; // if type is "", ignore everything here, the date construct was not parseable. + std::string dateConstructError; // error of the entire DateConstruct + std::string qualifier; + std::vector dates; // empty for "DateConstructRange" + std::vector dateConstructs; // only used for "DateConstructRange" (has two elements in that case) +}; + //---------------------------------------------------------------------------- // HumdrumInput //---------------------------------------------------------------------------- @@ -482,7 +537,7 @@ class HumdrumInput : public vrv::Input { void addFermata(hum::HTp token, vrv::Object *parent = NULL); void addBreath(hum::HTp token, vrv::Object *parent = NULL); void addTrill(vrv::Object *linked, hum::HTp token); - void addTurn(hum::HTp token, const string &tok, int noteIndex); + void addTurn(hum::HTp token, const std::string &tok, int noteIndex); void addMordent(vrv::Object *linked, hum::HTp token); void addOrnaments(vrv::Object *object, hum::HTp token); void addArpeggio(vrv::Object *object, hum::HTp token); @@ -596,7 +651,7 @@ class HumdrumInput : public vrv::Input { void embedQstampInClass(vrv::Space *irest, hum::HTp token, const std::string &tstring); void embedPitchInformationInClass(vrv::Note *note, const std::string &token); void embedTieInformation(Note *note, const std::string &token); - void splitSyllableBySpaces(vector &vtext, char spacer = ' '); + void splitSyllableBySpaces(std::vector &vtext, char spacer = ' '); void addDefaultTempo(ScoreDef *scoreDef); int getChordNoteCount(hum::HTp token); bool isLeftmostSystemArpeggio(hum::HTp token); @@ -657,7 +712,7 @@ class HumdrumInput : public vrv::Input { void removeInstrumentAbbreviation(StaffDef *sd); std::string getEndIdForOttava(hum::HTp token); void prepareInitialOttavas(hum::HTp measure); - void linkFingeringToNote(Dir *dir, hum::HTp token, int xstaffindex); + void linkFingeringToNote(Fing *fing, hum::HTp token, int xstaffindex); bool checkForTupletForcedBreak(const std::vector &duritems, int index); void extractSlurNoteAttachmentInformation(std::vector> &data, hum::HTp token, char slurtype); void extractPhraseNoteAttachmentInformation( @@ -723,7 +778,7 @@ class HumdrumInput : public vrv::Input { bool hasLayoutParameter(hum::HTp token, const std::string &category, const std::string ¶m); void assignTupletScalings(std::vector &tg); std::string getLayoutParameter(hum::HTp token, const std::string &category, const std::string &catkey, - const string &trueString, const string &falseString = ""); + const std::string &trueString, const std::string &falseString = ""); void analyzeClefNulls(hum::HumdrumFile &infile); void markAdjacentNullsWithClef(hum::HTp clef); void markOtherClefsAsChange(hum::HTp clef); @@ -744,12 +799,12 @@ class HumdrumInput : public vrv::Input { void addPlicaUp(Note *note); void addPlicaDown(Note *note); void setLayoutSlurDirection(Slur *slur, hum::HTp token); - void setFontStyle(Rend *rend, const string &fontstyle); + void setFontStyle(Rend *rend, const std::string &fontstyle); void setFontWeight(Rend *rend, const std::string &fontweight); void importVerovioOptions(Doc *doc); void adjustChordNoteDurations(Chord *chord, std::vector ¬es, std::vector &tstrings); void adjustChordNoteDuration(Note *note, hum::HumNum hdur, int dur, int dots, hum::HumNum chorddur, - const string &tstring, hum::HumNum factor); + const std::string &tstring, hum::HumNum factor); void setNoteMeiDur(Note *note, int meidur); void storeExpansionListsInChoice(Section *section, std::vector &expansions); double getMmTempo(hum::HTp token, bool checklast = false); @@ -766,7 +821,7 @@ class HumdrumInput : public vrv::Input { void addBarLineElement(hum::HTp bartok, std::vector &elements, std::vector &pointers); void prepareFingerings(hum::HumdrumFile &infile); void prepareFingerings(hum::HTp fstart); - std::string getLoColor(hum::HTp token, const string &category, int subtoken = 0); + std::string getLoColor(hum::HTp token, const std::string &category, int subtoken = 0); bool isTieAllowedToHang(hum::HTp token); void analyzeVerseColor(hum::HumdrumFile &infile); void analyzeVerseColor(hum::HTp &token); @@ -803,8 +858,8 @@ class HumdrumInput : public vrv::Input { void analyzeHarmInterpretations(hum::HTp starttok); void analyzeDegreeInterpretations(hum::HTp starttok); void analyzeTextInterpretation(hum::HTp starttok); - void addHarmLabel( - hum::HumNum timestamp, const std::string &label, const std::string &n, const std::string &place, int staffNum); + void addHarmLabel(hum::HumNum timestamp, const std::string &label, const std::string &labelStyle, + const std::string &n, const std::string &place, int staffNum); std::u32string getMoveableDoName(hum::HTp token, int degree, int semitones); void setFontsizeForHarm(Harm *harm, const std::string &fontsize); void setFontStyleForHarm(Harm *harm, const std::string &style); @@ -824,22 +879,53 @@ class HumdrumInput : public vrv::Input { void checkForLineContinuations(hum::HTp token); std::u32string convertNumberToWstring(int number); void appendTextToRend(Rend *rend, const std::string &content); - void parseMultiVerovioOptions(std::map ¶meters, const string &input); + void parseMultiVerovioOptions(std::map ¶meters, const std::string &input); void addSforzandoToNote(hum::HTp token, int staffindex); void addDynamicsMark(hum::HTp dyntok, hum::HTp token, hum::HLp line, const std::string &letters, int staffindex, int staffadj, int trackdiff); bool hasNoStaves(hum::HumdrumFile &infile); hum::HTp getVisualKeySignature(hum::HTp keysigtok); + bool isNotAtStartOfMeasure(std::vector &layerdata, int index); + void analyzeFingerings(hum::HumdrumFile &infile); + void analyzeFingerings(hum::HTp sstart); + void insertMidMeasureKeySignature( + int staffindex, std::vector &elements, std::vector &pointers, hum::HTp token); + int getKeySignatureNumber(const std::string &humkeysig); + int getStaffNumForSpine(hum::HTp token); + bool checkIfReversedSpineOrder(std::vector &staffstarts); // header related functions: /////////////////////////////////////////// void createHeader(); - void insertTitle(pugi::xml_node &titleStmt, const std::vector &references); - void insertExtMeta(std::vector &references); - void addPerson(std::vector> &respPeople, std::vector &references, - const std::string &key, const std::string &role); - void getRespPeople(std::vector> &respPeople, std::vector &references); - void insertRespStmt(pugi::xml_node &titleStmt, std::vector> &respPeople); - void insertPeople(pugi::xml_node &work, std::vector> &respPeople); + void createFileDesc(pugi::xml_node meiHead); + void createDigitalSource(pugi::xml_node sourceDesc); + void createPrintedSource(pugi::xml_node sourceDesc); + void createRecordedSource(pugi::xml_node sourceDesc); + void createUnpublishedSource(pugi::xml_node sourceDesc); + void createEncodingDesc(pugi::xml_node meiHead); + void createWorkList(pugi::xml_node meiHead); + void createHumdrumVerbatimExtMeta(pugi::xml_node meiHead); + void createBackMatter(); + void createSimpleTitleElement(); + void createSimpleComposerElements(); + void createTitleElements(pugi::xml_node element); + void createComposerElements(pugi::xml_node element); + void fillInIsoDate(pugi::xml_node element, const std::string &dateString); + std::map isoDateAttributesFromHumdrumDate( + const std::string &inHumdrumDate, bool edtf = false); + DateConstruct dateConstructFromHumdrumDate(const std::string &dateString); + std::map isoDateAttributesFromDateConstruct( + const DateConstruct &dateConstruct, bool edtf, bool isEdgeOfDateConstructRange = false); + std::string isoDateFromDateWithErrors(const DateWithErrors &dateWithErrors, bool edtf); + DateWithErrors dateWithErrorsFromHumdrumDate(const std::string &dateString); + bool sanityCheckDate(int year, int month, int day, int hour, int minute, int second); + std::string stripDateError(std::string &value); + std::string getTextListLanguage(const std::vector &textItems); + std::map> getAllReferenceItems(hum::HumdrumFile &infile); + std::vector getReferenceItems(const std::string &key); + bool anyReferenceItemsExist(const std::vector &keys); + int getBestItem(const std::vector &items, const std::string &requiredLanguage); + bool isStandardHumdrumKey(const std::string &key); + void appendText(pugi::xml_node element, std::string text); /// Templates /////////////////////////////////////////////////////////// template void verticalRest(ELEMENT rest, const std::string &token); @@ -897,8 +983,8 @@ class HumdrumInput : public vrv::Input { template void addDurRecip(ELEMENT element, const std::string &ttoken); template void addFermata(ELEMENT *rest, const std::string &tstring); template void storeExpansionList(ELEMENT *parent, hum::HTp etok); - template void setWrittenAccidentalUpper(ELEMENT element, const string &value); - template void setWrittenAccidentalLower(ELEMENT element, const string &value); + template void setWrittenAccidentalUpper(ELEMENT element, const std::string &value); + template void setWrittenAccidentalLower(ELEMENT element, const std::string &value); template void attachToToken(ELEMENT *element, hum::HTp token); template void setAttachmentType(ELEMENT *element, hum::HTp token); template @@ -913,7 +999,6 @@ class HumdrumInput : public vrv::Input { static int nextLowerPowerOfTwo(int x); static hum::HumNum nextHigherPowerOfTwo(hum::HumNum x); static std::string getDateString(); - static std::string getReferenceValue(const std::string &key, std::vector &references); static bool replace(std::string &str, const std::string &oldStr, const std::string &newStr); static bool replace(std::u32string &str, const std::u32string &oldStr, const std::u32string &newStr); @@ -1148,13 +1233,13 @@ class HumdrumInput : public vrv::Input { std::vector m_ftrem_slurs; // m_group_name == used to store group names, such as *I""trumpets - std::map m_group_name; + std::map m_group_name; // m_group_name_tok == used to store group names, such as *I""trumpets std::map m_group_name_tok; // m_group_abbr == used to store group abbreviations, such as *I""trps. - std::map m_group_abbr; + std::map m_group_abbr; // m_group_abbr_tok == used to store group abbreviations, such as *I""trps. std::map m_group_abbr_tok; @@ -1196,6 +1281,114 @@ class HumdrumInput : public vrv::Input { // (excluding augmentation dots). std::string m_textSmuflSpacer = "\xc2\xa0"; + // Some metadata elements that are computed once and used multiple times + std::vector m_humdrumLineReferences; + std::map> m_references; + pugi::xml_document m_simpleTitleDoc; + pugi::xml_node m_simpleTitle; + pugi::xml_document m_simpleComposersDoc; + pugi::xml_document m_madsDoc; + pugi::xml_node m_madsCollection; + + std::vector m_standardHumdrumKeys = { + "COM", // composer's name + "COA", // attributed composer + "COS", // suspected composer + "COL", // composer's abbreviated, alias, or stage name + "COC", // composer's corporate name + "CDT", // composer's birth and death dates (**zeit format) + "CBL", // composer's birth location + "CDL", // composer's death location + "CNT", // composer's nationality + "LYR", // lyricist's name + "LIB", // librettist's name + "LAR", // music arranger's name + "LOR", // orchestrator's name + "TXO", // original language of vocal/choral text + "TXL", // language of the encoded vocal/choral text + "TRN", // translator of the text + "RTL", // album title + "RMM", // manufacturer or sponsoring company + "RC#", // recording company's catalog number of album + "RRD", // release date (**date format) + "RLC", // place of recording + "RNP", // producer's name + "RDT", // date of recording (**date format) + "RT#", // track number + "MGN", // Humdrum encodes, say, a MIDI performance) + "MPN", // ensemble's name + "MPS", // performer's name + "MRD", // suspected performer + "MLC", // date of performance (**date format) + "MCN", // place of performance + "MPD", // conductor's name + "MDT", // date of first performance (**date format) + "OTL", // I've seen 'em (another way to say date of performance?) + "OTP", // title + "OTA", // popular title + "OPR", // alternative title + "OAC", // title of parent work + "OSC", // act number (e.g. '2' or 'Act 2') + "OMV", // scene number (e.g. '3' or 'Scene 3') + "OMD", // movement number (e.g. '4', or 'mov. 4', or...) + "OPS", // movement name + "ONM", // opus number (e.g. '23', or 'Opus 23') + "OVM", // number (e.g. number of song within ABC multi-song file) + "ODE", // volume number (e.g. '6' or 'Vol. 6') + "OCO", // dedicated to + "OCL", // commissioned by + "ONB", // collected/transcribed by + "ODT", // free form note related to title or identity of work + "OCY", // date or period of composition (**date or **zeit format) + "OPC", // country of composition + "GTL", // city, town, or village of composition + "GAW", // group title (e.g. 'The Seasons') + "GCO", // associated work, such as a play or film + "PUB", // publication status 'published'/'unpublished' + "PED", // publication editor + "PPR", // first publisher + "PDT", // date first published (**date format) + "PTL", // publication (volume) title + "PPP", // place first published + "PC#", // publisher's catalog number (NOT scholarly catalog) + "SCT", // scholarly catalog abbrev/number (e.g. 'BWV 551') + "SCA", // scholarly catalog (unabbreviated) (e.g. 'Koechel 117') + "SMS", // unpublished manuscript source name + "SML", // unpublished manuscript location + "SMA", // acknowledgment of manuscript access + "YEP", // publisher of electronic edition + "YEC", // date and owner of electronic copyright + "YER", // date electronic edition released + "YEM", // copyright message (e.g. 'All rights reserved') + "YEN", // country of copyright + "YOR", // original document from which encoded doc was prepared + "YOO", // original document owner + "YOY", // original copyright year + "YOE", // original editor + "EED", // electronic editor + "ENC", // electronic encoder (person) + "END", // encoding date + "EMD", // electronic document modification description (one/mod) + "EEV", // electronic edition version + "EFL", // file number e.g. '1/4' for one of four + "EST", // encoding status (usually deleted before distribution) + "VTS", // checksum (excluding the VTS line itself) + "ACO", // collection designation + "AFR", // form designation + "AGN", // genre designation + "AST", // style, period, or type of work designation + "AMD", // mode classification e.g. '5; Lydian' + "AMT", // metric classification, must be one of eight names, e.g. 'simple quadruple' + "AIN", // instrumentation, must be alphabetical list of *I abbrevs, space-delimited + "ARE", // geographical region of origin (list of 'narrowing down' names of regions) + "ARL", // geographical location of origin (lat/long) + "HAO", // aural history (lots of text, stories about the work) + "HTX", // freeform translation of vocal text + "RLN", // Extended ASCII language code + "RNB", // a note about the representation + "RWB" // a warning about the representation + }; + #endif /* NO_HUMDRUM_SUPPORT */ }; diff --git a/include/vrv/iomei.h b/include/vrv/iomei.h index 05d5c967dc5..6b0d7800119 100644 --- a/include/vrv/iomei.h +++ b/include/vrv/iomei.h @@ -52,6 +52,7 @@ class Del; class Dot; class Dir; class Div; +class DivLine; class DurationInterface; class Dynam; class Ending; @@ -305,7 +306,7 @@ class MEIOutput : public Output { * Scoredef manipulation */ ///@{ - void WriteCustomScoreDef(); + void WriteCustomScoreDef(ScoreDef *scoreDef); void AdjustStaffDef(StaffDef *staffDef, Measure *measure); bool AdjustLabel(Label *label); ///@} @@ -389,6 +390,7 @@ class MEIOutput : public Output { void WriteChord(pugi::xml_node currentNode, Chord *chord); void WriteClef(pugi::xml_node currentNode, Clef *clef); void WriteCustos(pugi::xml_node currentNode, Custos *custos); + void WriteDivLine(pugi::xml_node currentNode, DivLine *divLine); void WriteDot(pugi::xml_node currentNode, Dot *dot); void WriteFTrem(pugi::xml_node currentNode, FTrem *fTrem); void WriteGraceGrp(pugi::xml_node currentNode, GraceGrp *graceGrp); @@ -699,6 +701,7 @@ class MEIInput : public Input { bool ReadChord(Object *parent, pugi::xml_node chord); bool ReadClef(Object *parent, pugi::xml_node clef); bool ReadCustos(Object *parent, pugi::xml_node custos); + bool ReadDivLine(Object *parent, pugi::xml_node divLine); bool ReadDot(Object *parent, pugi::xml_node dot); bool ReadFTrem(Object *parent, pugi::xml_node fTrem); bool ReadGraceGrp(Object *parent, pugi::xml_node graceGrp); @@ -886,20 +889,20 @@ class MEIInput : public Input { */ ///@{ // to MEI 5.0.0 - void UpgradeKeySigTo_5_0_0(pugi::xml_node keySig); - void UpgradePageTo_5_0_0(Page *page); - void UpgradePgHeadFootTo_5_0_0(pugi::xml_node element); - void UpgradeMeasureTo_5_0_0(pugi::xml_node measure); - void UpgradeMeterSigTo_5_0_0(pugi::xml_node meterSig, MeterSig *vrvMeterSig); - void UpgradeScoreDefElementTo_5_0_0(pugi::xml_node scoreDefElement); - void UpgradeStaffTo_5_0_0(pugi::xml_node staff); - void UpgradeLayerElementTo_5_0_0(pugi::xml_node element); - void UpgradeRendTo_5_0_0(pugi::xml_node element); + void UpgradeKeySigTo_5_0(pugi::xml_node keySig); + void UpgradePageTo_5_0(Page *page); + void UpgradePgHeadFootTo_5_0(pugi::xml_node element); + void UpgradeMeasureTo_5_0(pugi::xml_node measure); + void UpgradeMeterSigTo_5_0(pugi::xml_node meterSig, MeterSig *vrvMeterSig); + void UpgradeScoreDefElementTo_5_0(pugi::xml_node scoreDefElement); + void UpgradeStaffTo_5_0(pugi::xml_node staff); + void UpgradeLayerElementTo_5_0(pugi::xml_node element); + void UpgradeRendTo_5_0(pugi::xml_node element); // to MEI 4.0.0 void UpgradeBeatRptTo_4_0_0(pugi::xml_node beatRpt, BeatRpt *vrvBeatRpt); void UpgradeDurGesTo_4_0_0(pugi::xml_node element, DurationInterface *interface); void UpgradeFTremTo_4_0_0(pugi::xml_node fTrem, FTrem *vrvFTrem); - void UpgradeMensurTo_5_0_0(pugi::xml_node mensur, Mensur *vrvMensur); + void UpgradeMensurTo_5_0(pugi::xml_node mensur, Mensur *vrvMensur); void UpgradeMordentTo_4_0_0(pugi::xml_node mordent, Mordent *vrvMordent); void UpgradeScoreDefElementTo_4_0_0(pugi::xml_node scoreDefElement, ScoreDefElement *vrvScoreDefElement); void UpgradeStaffDefTo_4_0_0(pugi::xml_node staffDef, StaffDef *vrvStaffDef); diff --git a/include/vrv/iomusxml.h b/include/vrv/iomusxml.h index 62ca7c1c802..2d6decc245c 100644 --- a/include/vrv/iomusxml.h +++ b/include/vrv/iomusxml.h @@ -197,7 +197,14 @@ class MusicXmlInput : public Input { MusicXmlInput(Doc *doc); virtual ~MusicXmlInput(); +private: + /* + * Objects that were not successfully added and should be destroyed at the end of the import + */ + ListOfObjects m_garbage; + #ifndef NO_MUSICXML_SUPPORT +public: bool Import(const std::string &musicxml) override; private: @@ -558,11 +565,6 @@ class MusicXmlInput : public Input { /* measure rests */ std::map m_multiRests; - /* - * Objects that were not successfully added and should be destroyed at the end of the import - */ - ListOfObjects m_garbage; - #endif // NO_MUSICXML_SUPPORT }; diff --git a/include/vrv/keysig.h b/include/vrv/keysig.h index 773aa23e323..edaf86d536a 100644 --- a/include/vrv/keysig.h +++ b/include/vrv/keysig.h @@ -45,10 +45,10 @@ class KeySig : public LayerElement, public ObjectListInterface, public AttAccidental, public AttColor, - public AttPitch, - public AttKeySigAnl, + public AttKeyMode, public AttKeySigLog, public AttKeySigVis, + public AttPitch, public AttVisibility { public: /** diff --git a/include/vrv/layerelement.h b/include/vrv/layerelement.h index f9eb21bddfe..af0917a61d7 100644 --- a/include/vrv/layerelement.h +++ b/include/vrv/layerelement.h @@ -24,6 +24,7 @@ class Beam; class BeamElementCoord; class FTrem; class Layer; +class Liquescent; class Mensur; class MeterSig; class Staff; diff --git a/include/vrv/nc.h b/include/vrv/nc.h index 83d1296332f..4f02ea5430b 100644 --- a/include/vrv/nc.h +++ b/include/vrv/nc.h @@ -15,6 +15,7 @@ #include "atts_analytical.h" #include "atts_neumes.h" #include "atts_shared.h" +#include "atts_visual.h" #include "durationinterface.h" #include "layerelement.h" #include "pitchinterface.h" @@ -35,6 +36,7 @@ class Nc : public LayerElement, public PitchInterface, public PositionInterface, public AttColor, + public AttCurvatureDirection, public AttIntervalMelodic, public AttNcForm { public: diff --git a/include/vrv/neume.h b/include/vrv/neume.h index 083aa39eede..9ca466cbe7d 100644 --- a/include/vrv/neume.h +++ b/include/vrv/neume.h @@ -77,6 +77,7 @@ class Neume : public LayerElement, public ObjectListInterface, public AttColor { */ bool IsSupportedChild(Object *object) override; + int GetLigatureCount(int position); bool IsLastInNeume(const LayerElement *element) const; bool GenerateChildMelodic(); diff --git a/include/vrv/object.h b/include/vrv/object.h index fce939c1569..1cb3f41ff41 100644 --- a/include/vrv/object.h +++ b/include/vrv/object.h @@ -692,7 +692,6 @@ class Object : public BoundingBox { * Helper methods for functor processing */ ///@{ - void UpdateDocumentScore(bool direction); bool SkipChildren(bool visibleOnly) const; bool FiltersApply(const Filters *filters, Object *object) const; ///@} @@ -809,6 +808,7 @@ class Object : public BoundingBox { * children LayerElement for processing. * The list is a flatten list of pointers to children elements. * It is not an abstract class but should not be instanciated directly. + * It is expected to be used as a base class of element classes derived from Object. */ class ObjectListInterface { public: @@ -816,7 +816,7 @@ class ObjectListInterface { ObjectListInterface(){}; virtual ~ObjectListInterface(){}; ObjectListInterface(const ObjectListInterface &listInterface); // copy constructor; - ObjectListInterface &operator=(const ObjectListInterface &listInterface); // copy assignement; + ObjectListInterface &operator=(const ObjectListInterface &listInterface); // copy assignment; /** * Look for the Object in the list and return its position (-1 if not found) @@ -853,29 +853,30 @@ class ObjectListInterface { * Return the list. * Before returning the list, it checks that the list is up-to-date with Object::IsModified * If not, it updates the list and also calls FilterList. - * Because this is an interface, we need to pass the object - not the best design. */ ///@{ - const ListOfConstObjects &GetList(const Object *node) const; - ListOfObjects GetList(const Object *node); + const ListOfConstObjects &GetList() const; + ListOfObjects GetList(); ///@} + /** + * Reset the list of children and call FilterList(). + */ + void ResetList() const; + /** * Convenience functions that check if the list is up-to-date * If not, the list is updated before returning the result */ ///@{ - bool HasEmptyList(const Object *node) const; - int GetListSize(const Object *node) const; - const Object *GetListFront(const Object *node) const; - Object *GetListFront(const Object *node); - const Object *GetListBack(const Object *node) const; - Object *GetListBack(const Object *node); + bool HasEmptyList() const; + int GetListSize() const; + const Object *GetListFront() const; + Object *GetListFront(); + const Object *GetListBack() const; + Object *GetListBack(); ///@} -private: - mutable ListOfConstObjects m_list; - protected: /** * Filter the list for a specific class. @@ -883,12 +884,19 @@ class ObjectListInterface { */ virtual void FilterList(ListOfConstObjects &childList) const {}; -public: +private: /** - * Reset the list of children and call FilterList(). - * As for GetList, we need to pass the object. + * Retrieve the owner object of the interface. */ - void ResetList(const Object *node) const; + const Object *GetInterfaceOwner() const; + +public: + // +private: + // The flat list of children + mutable ListOfConstObjects m_list; + // The owner object + mutable const Object *m_owner = NULL; }; //---------------------------------------------------------------------------- @@ -910,12 +918,12 @@ class TextListInterface : public ObjectListInterface { /** * Returns a contatenated version of all the text children */ - std::u32string GetText(const Object *node) const; + std::u32string GetText() const; /** * Fill an array of lines with concatenated content of each line */ - void GetTextLines(const Object *node, std::vector &lines) const; + void GetTextLines(std::vector &lines) const; protected: /** diff --git a/include/vrv/options.h b/include/vrv/options.h index 7e4a351d223..ad4c87eb7ae 100644 --- a/include/vrv/options.h +++ b/include/vrv/options.h @@ -86,7 +86,7 @@ enum option_SMUFLTEXTFONT { SMUFLTEXTFONT_embedded = 0, SMUFLTEXTFONT_linked, SM // Option //---------------------------------------------------------------------------- -enum class OptionsCategory { None, Base, General, Layout, Margins, Midi, Selectors, Full }; +enum class OptionsCategory { None, Base, General, Layout, Mensural, Margins, Midi, Selectors, Full }; /** * This class is a base class of each styling parameter @@ -626,8 +626,6 @@ class Options { OptionBool m_incip; OptionBool m_justifyVertically; OptionBool m_landscape; - OptionBool m_ligatureAsBracket; - OptionBool m_mensuralToMeasure; OptionDbl m_minLastJustification; OptionBool m_mmOutput; OptionBool m_moveScoreDefinitionToStaff; @@ -826,6 +824,14 @@ class Options { OptionBool m_midiNoCue; OptionDbl m_midiTempoAdjustment; + /** + * Mensural + */ + OptionGrp m_mensural; + + OptionBool m_ligatureAsBracket; + OptionBool m_mensuralToMeasure; + /** * Deprecated options */ diff --git a/include/vrv/ornam.h b/include/vrv/ornam.h index 88b1da5c8ed..25950ab63b3 100644 --- a/include/vrv/ornam.h +++ b/include/vrv/ornam.h @@ -29,8 +29,6 @@ class Ornam : public ControlElement, public TextDirInterface, public TimePointInterface, public AttColor, - public AttExtSymAuth, - public AttExtSymNames, public AttOrnamentAccid { public: /** @@ -64,11 +62,6 @@ class Ornam : public ControlElement, */ bool IsSupportedChild(Object *object) override; - /** - * Get the SMuFL glyph for the ornam based glyph.num - */ - char32_t GetOrnamGlyph() const; - //----------// // Functors // //----------// diff --git a/include/vrv/page.h b/include/vrv/page.h index 7bab10d7ec7..f1751100c99 100644 --- a/include/vrv/page.h +++ b/include/vrv/page.h @@ -48,11 +48,6 @@ class Page : public Object { bool IsSupportedChild(Object *object) override; ///@} - /** - * Return the number of system (children are System object only) - */ - int GetSystemCount() const { return (int)GetChildren().size(); } - /** * @name Get and set the pixel per unit factor. */ diff --git a/include/vrv/pitchinterface.h b/include/vrv/pitchinterface.h index ed9d397659a..72b0d42a029 100644 --- a/include/vrv/pitchinterface.h +++ b/include/vrv/pitchinterface.h @@ -25,7 +25,7 @@ class Layer; * This class is an interface for elements with pitch, such as notes and neumes. * It is not an abstract class but should not be instanciated directly. */ -class PitchInterface : public Interface, public AttNoteGes, public AttOctave, public AttPitch { +class PitchInterface : public Interface, public AttNoteGes, public AttOctave, public AttPitch, public AttPitchGes { public: /** * @name Constructors, destructors, reset methods @@ -38,6 +38,15 @@ class PitchInterface : public Interface, public AttNoteGes, public AttOctave, pu InterfaceId IsInterface() const override { return INTERFACE_PITCH; } ///@} + /** + * @name Set and get the default octave + */ + ///@{ + void SetOctDefault(data_OCTAVE oct) { m_octDefault = oct; } + data_OCTAVE GetOctDefault() const { return m_octDefault; } + bool HasOctDefault() const { return (m_octDefault != MEI_UNSET_OCT); } + ///@} + /** * Interface comparison operator. * Checks if the LayerElement has a PitchInterface and compares attributes @@ -90,7 +99,10 @@ class PitchInterface : public Interface, public AttNoteGes, public AttOctave, pu public: // private: - // + /** + * The default octave: extracted from scoreDef/staffDef and used when no octave attribute is given + */ + data_OCTAVE m_octDefault; }; } // namespace vrv diff --git a/include/vrv/preparedatafunctor.h b/include/vrv/preparedatafunctor.h index 505b7518820..412ef9f3918 100644 --- a/include/vrv/preparedatafunctor.h +++ b/include/vrv/preparedatafunctor.h @@ -558,6 +558,47 @@ class PrepareTimestampsFunctor : public Functor { ListOfObjectBeatPairs m_tstamps; }; +//---------------------------------------------------------------------------- +// PreparePedalsFunctor +//---------------------------------------------------------------------------- + +/** + * This class matches down and up pedal lines. + */ +class PreparePedalsFunctor : public DocFunctor { +public: + /** + * @name Constructors, destructors + */ + ///@{ + PreparePedalsFunctor(Doc *doc); + virtual ~PreparePedalsFunctor() = default; + ///@} + + /* + * Abstract base implementation + */ + bool ImplementsEndInterface() const override { return true; } + + /* + * Functor interface + */ + ///@{ + FunctorCode VisitMeasureEnd(Measure *measure) override; + FunctorCode VisitPedal(Pedal *pedal) override; + ///@} + +protected: + // +private: + // +public: + // +private: + // The current pedals to be linked / grouped + std::list m_pedalLines; +}; + //---------------------------------------------------------------------------- // PreparePointersByLayerFunctor //---------------------------------------------------------------------------- @@ -579,7 +620,7 @@ class PreparePointersByLayerFunctor : public Functor { /* * Abstract base implementation */ - bool ImplementsEndInterface() const override { return false; } + bool ImplementsEndInterface() const override { return true; } /* * Functor interface @@ -587,6 +628,7 @@ class PreparePointersByLayerFunctor : public Functor { ///@{ FunctorCode VisitDot(Dot *dot) override; FunctorCode VisitLayerElement(LayerElement *layerElement) override; + FunctorCode VisitMeasureEnd(Measure *measure) override; ///@} protected: @@ -687,7 +729,13 @@ class PrepareLayerElementPartsFunctor : public Functor { protected: // private: - // + // Create stem if it does not exist + Stem *EnsureStemExists(Stem *stem, Object *parent) const; + // Create dots if they should exist, otherwise remove them + Dots *ProcessDots(Dots *dots, Object *parent, bool shouldExist) const; + // Create flag if it should exist, otherwise remove it + Flag *ProcessFlag(Flag *flag, Object *parent, bool shouldExist) const; + public: // private: @@ -861,13 +909,13 @@ class PrepareMilestonesFunctor : public Functor { * This class groups FloatingObjects by drawingGrpId. * Also chains the Dynam and Hairpin. */ -class PrepareFloatingGrpsFunctor : public DocFunctor { +class PrepareFloatingGrpsFunctor : public Functor { public: /** * @name Constructors, destructors */ ///@{ - PrepareFloatingGrpsFunctor(Doc *doc); + PrepareFloatingGrpsFunctor(); virtual ~PrepareFloatingGrpsFunctor() = default; ///@} @@ -906,8 +954,6 @@ class PrepareFloatingGrpsFunctor : public DocFunctor { std::vector m_hairpins; // The map of existing harms (based on @n) std::map m_harms; - // The current pedals to be linked / grouped - std::list m_pedalLines; }; //---------------------------------------------------------------------------- diff --git a/include/vrv/score.h b/include/vrv/score.h index de496139af5..975909c70b9 100644 --- a/include/vrv/score.h +++ b/include/vrv/score.h @@ -56,12 +56,6 @@ class Score : public PageElement, public PageMilestoneInterface, public AttLabel const ScoreDef *GetScoreDef() const { return &m_scoreDef; } ///@} - /** - * Helper looking at the parent Doc and set its scoreDef as current one. - * Called from Object::Process - */ - void SetAsCurrent(); - /** * Calculate the height of the pgHead/pgHead2 and pgFoot/pgFoot2 (if any) * Requires the Doc to have an empty Pages object because it adds temporary pages diff --git a/include/vrv/scoredefinterface.h b/include/vrv/scoredefinterface.h index a9f4e7afbe2..2fd9dd6b59d 100644 --- a/include/vrv/scoredefinterface.h +++ b/include/vrv/scoredefinterface.h @@ -36,6 +36,7 @@ class ScoreDefInterface : public Interface, public AttMidiTempo, public AttMmTempo, public AttMultinumMeasures, + public AttOctaveDefault, public AttPianoPedals, public AttSpacing, public AttSystems { diff --git a/include/vrv/slur.h b/include/vrv/slur.h index a3cf6a0ec4b..15fb1174a3c 100644 --- a/include/vrv/slur.h +++ b/include/vrv/slur.h @@ -42,32 +42,6 @@ struct NearEndCollision { bool endPointsAdjusted; }; -//---------------------------------------------------------------------------- -// ControlPointConstraint -//---------------------------------------------------------------------------- -/** - * This represents a constraint ax + by >= c where x and y are - * vertical control point adjustments - */ -struct ControlPointConstraint { - double a; - double b; - double c; -}; - -//---------------------------------------------------------------------------- -// ControlPointAdjustment -//---------------------------------------------------------------------------- -/** - * A vertical adjustment of bezier control points - */ -struct ControlPointAdjustment { - int leftShift; - int rightShift; - bool moveUpwards; - int requestedStaffSpace; -}; - // Helper enum classes enum class SlurCurveDirection { None, Above, Below, AboveBelow, BelowAbove }; enum class PortatoSlurType { None, StemSide, Centered }; @@ -80,8 +54,8 @@ class Slur : public ControlElement, public TimeSpanningInterface, public AttColor, public AttCurvature, - public AttCurveRend, - public AttLayerIdent { + public AttLayerIdent, + public AttLineRendBase { public: /** * @name Constructors, destructors, reset and class name methods @@ -195,18 +169,6 @@ class Slur : public ControlElement, */ void InitBezierControlSides(BezierCurve &bezier, curvature_CURVEDIR curveDir) const; - /** - * Slur adjustment - */ - ///@{ - void AdjustSlur(const Doc *doc, FloatingCurvePositioner *curve, int unit); - - void AdjustOuterSlur( - const Doc *doc, FloatingCurvePositioner *curve, const ArrayOfFloatingCurvePositioners &innerCurves, int unit); - - float GetAdjustedSlurAngle(const Doc *doc, Point &p1, Point &p2, curvature_CURVEDIR curveDir) const; - ///@} - //----------// // Functors // //----------// @@ -258,83 +220,8 @@ class Slur : public ControlElement, bool StartsOnBeam() const { return this->HasBoundaryOnBeam(true); } bool EndsOnBeam() const { return this->HasBoundaryOnBeam(false); } bool HasBoundaryOnBeam(bool isStart) const; - ///@} - - /** - * Adjust slur position based on overlapping objects within its spanning elements - */ - ///@{ - // Discard certain spanned elements - void FilterSpannedElements(FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, int margin); - - // Detect collisions near the endpoints - NearEndCollision DetectCollisionsNearEnd( - FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, int margin); - - // Calculate the vertical shift of the slur end points - std::pair CalcEndPointShift( - FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, double flexibility, int margin); - - // Apply the vertical shift of the slur end points - void ApplyEndPointShift( - FloatingCurvePositioner *curve, BezierCurve &bezierCurve, int endPointShiftLeft, int endPointShiftRight); - - // Calculate slur from bulge values - void AdjustSlurFromBulge(FloatingCurvePositioner *curve, BezierCurve &bezierCurve, int unit); - - // Check whether control points should be adjusted horizontally - bool AllowControlOffsetAdjustment(const BezierCurve &bezierCurve, double symmetry, int unit) const; - - // Calculate the horizontal control point offset - std::tuple CalcControlPointOffset( - FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, int margin); - - // Calculate the vertical control point shift - ControlPointAdjustment CalcControlPointVerticalShift( - FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, double symmetry, int margin); - - // Solve the constraints for vertical control point adjustment - std::pair SolveControlPointConstraints( - const std::list &constraints, double symmetry = 0.0) const; - - // Improve the slur shape by adjusting the control point heights - void AdjustSlurShape(BezierCurve &bezierCurve, curvature_CURVEDIR dir, int unit); - ///@} - - /** - * Adjust slur position based on inner slurs - */ - ///@{ - // Calculate the vertical control point shift - ControlPointAdjustment CalcControlPointShift(FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, - const ArrayOfFloatingCurvePositioners &innerCurves, double symmetry, int margin); - - // Calculate the vertical shift of the slur end points - std::pair CalcEndPointShift(FloatingCurvePositioner *curve, const BezierCurve &bezierCurve, - const ArrayOfFloatingCurvePositioners &innerCurves, double flexibility, int margin); - ///@} - - /** - * Low level helper functions for slur adjustment - */ - ///@{ - // Shift end points for collisions nearby - void ShiftEndPoints(int &shiftLeft, int &shiftRight, double ratio, int intersection, double flexibility, - bool isBelow, char spanningType) const; - - // Calculate the full and partial shift radii - std::pair CalcShiftRadii(bool forShiftLeft, double flexibility, char spanningType) const; - - // Determine a quadratic interpolation function between zero and one and evaluate it - double CalcQuadraticInterpolation(double zeroAt, double oneAt, double arg) const; - - // Rotate the slope by a given number of degrees, but choose smaller angles if already close to the vertical axis - // Choose doublingBound as the positive slope value where doubling has the same effect as rotating: - // tan(atan(doublingBound) + degrees * PI / 180.0) ≈ 2.0 * doublingBound - double RotateSlope(double slope, double degrees, double doublingBound, bool upwards) const; - - // Calculate the minimal angle <)C1P1P2 or <)P1P2C2 - float GetMinControlPointAngle(const BezierCurve &bezierCurve, float angle, int unit) const; + // Angle adjustment + float GetAdjustedSlurAngle(const Doc *doc, Point &p1, Point &p2, curvature_CURVEDIR curveDir) const; ///@} public: diff --git a/include/vrv/smufl.h b/include/vrv/smufl.h index 867ebd0954b..5e70fa53c69 100644 --- a/include/vrv/smufl.h +++ b/include/vrv/smufl.h @@ -547,6 +547,7 @@ enum { SMUFL_EB9D_staffPosLower6 = 0xEB9D, SMUFL_EB9E_staffPosLower7 = 0xEB9E, SMUFL_EB9F_staffPosLower8 = 0xEB9F, + SMUFL_EBA6_luteDurationDoubleWhole = 0xEBA6, SMUFL_EBA7_luteDurationWhole = 0xEBA7, SMUFL_EBA8_luteDurationHalf = 0xEBA8, SMUFL_EBA9_luteDurationQuarter = 0xEBA9, @@ -643,7 +644,7 @@ enum { }; /** The number of glyphs for verification **/ -#define SMUFL_COUNT 618 +#define SMUFL_COUNT 619 } // namespace vrv diff --git a/include/vrv/surface.h b/include/vrv/surface.h index 5d155a3d876..f6cc1eb8eec 100644 --- a/include/vrv/surface.h +++ b/include/vrv/surface.h @@ -27,7 +27,7 @@ namespace vrv { * in MEI */ -class Surface : public Object, public AttTyped, public AttCoordinated { +class Surface : public Object, public AttTyped, public AttCoordinated, public AttCoordinatedUl { public: /** * @name Constructors, destructors, reset, and class name methods diff --git a/include/vrv/svgdevicecontext.h b/include/vrv/svgdevicecontext.h index 9eed0baa79a..0e7b43e4afd 100644 --- a/include/vrv/svgdevicecontext.h +++ b/include/vrv/svgdevicecontext.h @@ -117,7 +117,7 @@ class SvgDeviceContext : public DeviceContext { * @name Method for starting and ending a graphic */ ///@{ - void StartGraphic(Object *object, std::string gClass, std::string gId, GraphicID graphicID = PRIMARY, + void StartGraphic(Object *object, const std::string &gClass, const std::string &gId, GraphicID graphicID = PRIMARY, bool prepend = false) override; void EndGraphic(Object *object, View *view) override; ///@} @@ -126,10 +126,15 @@ class SvgDeviceContext : public DeviceContext { * @name Method for starting and ending a graphic custom graphic that do not correspond to an Object */ ///@{ - void StartCustomGraphic(std::string name, std::string gClass = "", std::string gId = "") override; + void StartCustomGraphic(const std::string &name, std::string gClass = "", std::string gId = "") override; void EndCustomGraphic() override; ///@} + /** + * Method for changing the color of a custom graphic + */ + virtual void SetCustomGraphicColor(const std::string &color) override; + /** * @name Methods for re-starting and ending a graphic for objects drawn in separate steps */ @@ -142,7 +147,7 @@ class SvgDeviceContext : public DeviceContext { * @name Method for starting and ending a text () text graphic */ ///@{ - void StartTextGraphic(Object *object, std::string gClass, std::string gId) override; + void StartTextGraphic(Object *object, const std::string &gClass, const std::string &gId) override; void EndTextGraphic(Object *object, View *view) override; ///@} @@ -171,8 +176,8 @@ class SvgDeviceContext : public DeviceContext { /** * Add id, data-id and class attributes */ - void AppendIdAndClass( - std::string gId, std::string baseClass, std::string addedClasses, GraphicID graphicID = PRIMARY); + void AppendIdAndClass(const std::string &gId, const std::string &baseClass, const std::string &addedClasses, + GraphicID graphicID = PRIMARY); /** * Append additional attributes, as given in m_svgAdditionalAttributes @@ -225,7 +230,7 @@ class SvgDeviceContext : public DeviceContext { /** * Setter for an additional CSS */ - void SetCss(std::string css) { m_css = css; } + void SetCss(const std::string &css) { m_css = css; } /** * Copies additional attributes of defined elements to the SVG, each string in the form "elementName@attribute" diff --git a/include/vrv/tie.h b/include/vrv/tie.h index 2784d10b767..ccd92e5e5e7 100644 --- a/include/vrv/tie.h +++ b/include/vrv/tie.h @@ -28,7 +28,7 @@ class Tie : public ControlElement, public TimeSpanningInterface, public AttColor, public AttCurvature, - public AttCurveRend { + public AttLineRendBase { public: /** * @name Constructors, destructors, and other standard methods diff --git a/include/vrv/toolkit.h b/include/vrv/toolkit.h index 3078f7e420c..268175e3217 100644 --- a/include/vrv/toolkit.h +++ b/include/vrv/toolkit.h @@ -500,9 +500,10 @@ class Toolkit { /** * Get the MEI as a string. * - * @param jsonOptions A stringified JSON object with the output options + * @param jsonOptions A stringified JSON object with the output options; * pageNo: integer; (1-based), all pages if none (or 0) specified; * scoreBased: true or false; true by default; + * basic: true or false; false by default; * removeIds: true or false; false by default - remove all \@xml:id not used in the data; */ std::string GetMEI(const std::string &jsonOptions = ""); diff --git a/include/vrv/tuning.h b/include/vrv/tuning.h index d5be1648c09..bdb78867b98 100644 --- a/include/vrv/tuning.h +++ b/include/vrv/tuning.h @@ -45,13 +45,13 @@ class Tuning : public Object, public AttCourseLog { int CalcPitchPos(int course, data_NOTATIONTYPE notationType, int lines) const; /** - * Calclate the MIDI pitch number for course/fret + * Calculate the MIDI note number for course/fret * - * @param[in] course - * @param[in] fret - * @param[in] notationType, used to default tuning if not otherwise specified + * @param[in] course The course number + * @param[in] fret The fret number + * @param[in] notationType The notationType used to default tuning if not otherwise specified * - * @return MIDI pitch + * @return MIDI note number */ int CalcPitchNumber(int course, int fret, data_NOTATIONTYPE notationType) const; diff --git a/include/vrv/verticalaligner.h b/include/vrv/verticalaligner.h index 5a209b611c7..d5ce55c8644 100644 --- a/include/vrv/verticalaligner.h +++ b/include/vrv/verticalaligner.h @@ -39,6 +39,11 @@ class SystemAligner : public Object { SystemAligner(); virtual ~SystemAligner(); + /** + * Override the method of adding AlignmentReference children + */ + bool IsSupportedChild(Object *object) override; + /** * Do not copy children for HorizontalAligner */ @@ -67,6 +72,13 @@ class SystemAligner : public Object { */ StaffAlignment *GetStaffAlignment(int idx, Staff *staff, const Doc *doc); + /** + * Reorder the staff alignment as given in the staffNs. + * Reordering will fail if the number of staffAlignment does not correspond, or + * if some staffAlignment pointers are missing for a corresponding staffN + */ + void ReorderBy(const std::vector &staffNs); + /** * Get the StaffAlignment for the staffN. * Return NULL if not found. diff --git a/include/vrv/view.h b/include/vrv/view.h index 830a5e617ec..2c5473db68d 100644 --- a/include/vrv/view.h +++ b/include/vrv/view.h @@ -31,6 +31,7 @@ class ControlElement; class DeviceContext; class Dir; class Div; +class DivLine; class Doc; class Dynam; class EditorialElement; @@ -49,6 +50,7 @@ class KeyAccid; class Layer; class LayerElement; class Lb; +class Liquescent; class Measure; class MNum; class Mordent; @@ -412,6 +414,7 @@ class View { * Defined in view_neume.cpp */ ///@{ + void DrawDivLine(DeviceContext *dc, LayerElement *element, Layer *layer, Staff *staff, Measure *measure); void DrawSyllable(DeviceContext *dc, LayerElement *element, Layer *layer, Staff *staff, Measure *measure); void DrawNc(DeviceContext *dc, LayerElement *element, Layer *layer, Staff *staff, Measure *measure); void DrawNeume(DeviceContext *dc, LayerElement *element, Layer *layer, Staff *staff, Measure *measure); diff --git a/include/vrv/vrvdef.h b/include/vrv/vrvdef.h index f2e47befc7d..86ead543896 100644 --- a/include/vrv/vrvdef.h +++ b/include/vrv/vrvdef.h @@ -38,8 +38,8 @@ namespace vrv { // Version //---------------------------------------------------------------------------- -#define VERSION_MAJOR 3 -#define VERSION_MINOR 17 +#define VERSION_MAJOR 4 +#define VERSION_MINOR 2 #define VERSION_REVISION 0 // Adds "-dev" in the version number - should be set to false for releases #define VERSION_DEV true @@ -218,6 +218,7 @@ enum ClassId : uint16_t { CHORD, CLEF, CUSTOS, + DIVLINE, DOT, DOTS, FLAG, @@ -311,6 +312,7 @@ class BeamElementCoord; class BoundingBox; class Comparison; class CurveSpannedElement; +class DivLine; class FloatingPositioner; class FloatingCurvePositioner; class GraceAligner; @@ -318,6 +320,7 @@ class InterfaceComparison; class LayerElement; class LedgerLine; class LinkingInterface; +class Liquescent; class Nc; class Note; class Neume; @@ -681,6 +684,13 @@ enum GraphicID { PRIMARY = 0, SPANNING, SYMBOLREF }; #define SUPER_SCRIPT_POSITION -0.20 // lowered down from the midline #define SUB_SCRIPT_POSITION -0.17 // lowered down from the baseline +//---------------------------------------------------------------------------- +// Neume notation note size to staff size ratio defines +//---------------------------------------------------------------------------- + +#define NOTE_HEIGHT_TO_STAFF_SIZE_RATIO 2 +#define NOTE_WIDTH_TO_STAFF_SIZE_RATIO 1.4 + } // namespace vrv #endif // __VRV_DEF_H__ diff --git a/include/vrv/zone.h b/include/vrv/zone.h index bbe0c1b90c4..c9e3e44ebc7 100644 --- a/include/vrv/zone.h +++ b/include/vrv/zone.h @@ -27,7 +27,7 @@ namespace vrv { * in MEI */ -class Zone : public Object, public AttTyped, public AttCoordinated { +class Zone : public Object, public AttTyped, public AttCoordinated, public AttCoordinatedUl { public: /** * @name Constructors, destructors, reset, and class name methods diff --git a/libmei/addons/attdef.h b/libmei/addons/attdef.h index b94f8eafbe4..fd991b11345 100644 --- a/libmei/addons/attdef.h +++ b/libmei/addons/attdef.h @@ -22,6 +22,7 @@ namespace vrv { #define MEI_UNSET -0x7FFFFFFF +#define MEI_UNSET_OCT -127 /** * MEI virtual unit; diff --git a/libmei/config.yml b/libmei/config.yml index fcb10ef424f..e2f1f42844d 100644 --- a/libmei/config.yml +++ b/libmei/config.yml @@ -5,4 +5,4 @@ addons_dir: "./addons" elements: false namespace: "vrv" datatypes: "./datatypes.yml" -basic_odd: "./mei/develop/mei-basic_compiled.odd" \ No newline at end of file +basic_odd: "./mei/mei-basic_compiled.odd" \ No newline at end of file diff --git a/libmei/datatypes.yml b/libmei/datatypes.yml index fe307d2a24b..165866c920e 100644 --- a/libmei/datatypes.yml +++ b/libmei/datatypes.yml @@ -168,7 +168,7 @@ defaults: data_MIDIVALUE_PAN: data_MIDIVALUE_PAN() data_OCTAVE: - -127 + MEI_UNSET_OCT data_SUMMAND_List: std::vector() xsdAnyURI_List: @@ -208,6 +208,11 @@ modules: type: double default: -1.0 + neumes: + att.divLine.log: + form: + type: divLineLog_FORM + shared: att.articulation: artic: @@ -253,3 +258,9 @@ modules: tab.fret: type: int default: -1 + + visual: + att.mensural.vis: + mensur.slash: + type: char + default: 0 diff --git a/libmei/dist/attclasses.h b/libmei/dist/attclasses.h index cd97543bc18..114d32e45ef 100644 --- a/libmei/dist/attclasses.h +++ b/libmei/dist/attclasses.h @@ -26,13 +26,11 @@ enum AttClassId { ATT_HARMONICFUNCTION, ATT_INTERVALHARMONIC, ATT_INTERVALMELODIC, - ATT_KEYSIGANL, ATT_KEYSIGDEFAULTANL, ATT_MELODICFUNCTION, ATT_PITCHCLASS, ATT_SOLFA, ATT_ARPEGLOG, - ATT_BTREMLOG, ATT_BEAMPRESENT, ATT_BEAMREND, ATT_BEAMSECONDARY, @@ -42,7 +40,6 @@ enum AttClassId { ATT_BRACKETSPANLOG, ATT_CUTOUT, ATT_EXPANDABLE, - ATT_FTREMLOG, ATT_GLISSPRESENT, ATT_GRACEGRPLOG, ATT_GRACED, @@ -57,10 +54,10 @@ enum AttClassId { ATT_PEDALLOG, ATT_PIANOPEDALS, ATT_REHEARSAL, - ATT_SCOREDEFVISCMN, ATT_SLURREND, ATT_STEMSCMN, ATT_TIEREND, + ATT_TREMFORM, ATT_TREMMEASURED, ATT_MORDENTLOG, ATT_ORNAMPRESENT, @@ -78,13 +75,12 @@ enum AttClassId { ATT_NOTEGESTAB, ATT_ACCIDENTALGES, ATT_ARTICULATIONGES, + ATT_ATTACKING, ATT_BENDGES, ATT_DURATIONGES, - ATT_MDIVGES, - ATT_NCGES, ATT_NOTEGES, ATT_ORNAMENTACCIDGES, - ATT_SECTIONGES, + ATT_PITCHGES, ATT_SOUNDLOCATION, ATT_TIMESTAMPGES, ATT_TIMESTAMP2GES, @@ -114,6 +110,7 @@ enum AttClassId { ATT_DIVLINELOG, ATT_NCLOG, ATT_NCFORM, + ATT_NEUMETYPE, ATT_MARGINS, ATT_ALIGNMENT, ATT_ACCIDLOG, @@ -139,9 +136,9 @@ enum AttClassId { ATT_COORDX2, ATT_COORDY1, ATT_COORDINATED, + ATT_COORDINATEDUL, ATT_CUE, ATT_CURVATURE, - ATT_CURVEREND, ATT_CUSTOSLOG, ATT_DATAPOINTING, ATT_DATABLE, @@ -165,6 +162,7 @@ enum AttClassId { ATT_HORIZONTALALIGN, ATT_INTERNETMEDIA, ATT_JOINED, + ATT_KEYMODE, ATT_KEYSIGLOG, ATT_KEYSIGDEFAULTLOG, ATT_LABELLED, @@ -181,6 +179,7 @@ enum AttClassId { ATT_MEDIABOUNDS, ATT_MEDIUM, ATT_MEIVERSION, + ATT_MENSURLOG, ATT_METADATAPOINTING, ATT_METERCONFORMANCE, ATT_METERCONFORMANCEBAR, @@ -271,10 +270,12 @@ enum AttClassId { ATT_BEATRPTVIS, ATT_CHORDVIS, ATT_CLEFFINGVIS, + ATT_CURVATUREDIRECTION, ATT_EPISEMAVIS, ATT_FTREMVIS, ATT_FERMATAVIS, ATT_FINGGRPVIS, + ATT_GUITARGRIDVIS, ATT_HAIRPINVIS, ATT_HARMVIS, ATT_HISPANTICKVIS, diff --git a/libmei/dist/attconverter.cpp b/libmei/dist/attconverter.cpp index 659e5ecef62..d97e5b5a880 100644 --- a/libmei/dist/attconverter.cpp +++ b/libmei/dist/attconverter.cpp @@ -43,6 +43,8 @@ std::string AttConverterBase::AccidentalGesturalToStr(data_ACCIDENTAL_GESTURAL d case ACCIDENTAL_GESTURAL_sd: value = "sd"; break; case ACCIDENTAL_GESTURAL_fu: value = "fu"; break; case ACCIDENTAL_GESTURAL_fd: value = "fd"; break; + case ACCIDENTAL_GESTURAL_xu: value = "xu"; break; + case ACCIDENTAL_GESTURAL_ffd: value = "ffd"; break; case ACCIDENTAL_GESTURAL_bms: value = "bms"; break; case ACCIDENTAL_GESTURAL_kms: value = "kms"; break; case ACCIDENTAL_GESTURAL_bs: value = "bs"; break; @@ -74,6 +76,8 @@ data_ACCIDENTAL_GESTURAL AttConverterBase::StrToAccidentalGestural(const std::st if (value == "sd") return ACCIDENTAL_GESTURAL_sd; if (value == "fu") return ACCIDENTAL_GESTURAL_fu; if (value == "fd") return ACCIDENTAL_GESTURAL_fd; + if (value == "xu") return ACCIDENTAL_GESTURAL_xu; + if (value == "ffd") return ACCIDENTAL_GESTURAL_ffd; if (value == "bms") return ACCIDENTAL_GESTURAL_bms; if (value == "kms") return ACCIDENTAL_GESTURAL_kms; if (value == "bs") return ACCIDENTAL_GESTURAL_bs; @@ -130,6 +134,8 @@ std::string AttConverterBase::AccidentalGesturalExtendedToStr(data_ACCIDENTAL_GE case ACCIDENTAL_GESTURAL_extended_sd: value = "sd"; break; case ACCIDENTAL_GESTURAL_extended_fu: value = "fu"; break; case ACCIDENTAL_GESTURAL_extended_fd: value = "fd"; break; + case ACCIDENTAL_GESTURAL_extended_xu: value = "xu"; break; + case ACCIDENTAL_GESTURAL_extended_ffd: value = "ffd"; break; default: LogWarning("Unknown value '%d' for data.ACCIDENTAL.GESTURAL.extended", data); value = ""; @@ -144,6 +150,8 @@ data_ACCIDENTAL_GESTURAL_extended AttConverterBase::StrToAccidentalGesturalExten if (value == "sd") return ACCIDENTAL_GESTURAL_extended_sd; if (value == "fu") return ACCIDENTAL_GESTURAL_extended_fu; if (value == "fd") return ACCIDENTAL_GESTURAL_extended_fd; + if (value == "xu") return ACCIDENTAL_GESTURAL_extended_xu; + if (value == "ffd") return ACCIDENTAL_GESTURAL_extended_ffd; if (logWarning && !value.empty()) LogWarning("Unsupported value '%s' for data.ACCIDENTAL.GESTURAL.extended", value.c_str()); return ACCIDENTAL_GESTURAL_extended_NONE; @@ -171,6 +179,10 @@ std::string AttConverterBase::AccidentalWrittenToStr(data_ACCIDENTAL_WRITTEN dat case ACCIDENTAL_WRITTEN_fd: value = "fd"; break; case ACCIDENTAL_WRITTEN_nu: value = "nu"; break; case ACCIDENTAL_WRITTEN_nd: value = "nd"; break; + case ACCIDENTAL_WRITTEN_xu: value = "xu"; break; + case ACCIDENTAL_WRITTEN_xd: value = "xd"; break; + case ACCIDENTAL_WRITTEN_ffu: value = "ffu"; break; + case ACCIDENTAL_WRITTEN_ffd: value = "ffd"; break; case ACCIDENTAL_WRITTEN_1qf: value = "1qf"; break; case ACCIDENTAL_WRITTEN_3qf: value = "3qf"; break; case ACCIDENTAL_WRITTEN_1qs: value = "1qs"; break; @@ -213,6 +225,10 @@ data_ACCIDENTAL_WRITTEN AttConverterBase::StrToAccidentalWritten(const std::stri if (value == "fd") return ACCIDENTAL_WRITTEN_fd; if (value == "nu") return ACCIDENTAL_WRITTEN_nu; if (value == "nd") return ACCIDENTAL_WRITTEN_nd; + if (value == "xu") return ACCIDENTAL_WRITTEN_xu; + if (value == "xd") return ACCIDENTAL_WRITTEN_xd; + if (value == "ffu") return ACCIDENTAL_WRITTEN_ffu; + if (value == "ffd") return ACCIDENTAL_WRITTEN_ffd; if (value == "1qf") return ACCIDENTAL_WRITTEN_1qf; if (value == "3qf") return ACCIDENTAL_WRITTEN_3qf; if (value == "1qs") return ACCIDENTAL_WRITTEN_1qs; @@ -285,6 +301,10 @@ std::string AttConverterBase::AccidentalWrittenExtendedToStr(data_ACCIDENTAL_WRI case ACCIDENTAL_WRITTEN_extended_fd: value = "fd"; break; case ACCIDENTAL_WRITTEN_extended_nu: value = "nu"; break; case ACCIDENTAL_WRITTEN_extended_nd: value = "nd"; break; + case ACCIDENTAL_WRITTEN_extended_xu: value = "xu"; break; + case ACCIDENTAL_WRITTEN_extended_xd: value = "xd"; break; + case ACCIDENTAL_WRITTEN_extended_ffu: value = "ffu"; break; + case ACCIDENTAL_WRITTEN_extended_ffd: value = "ffd"; break; case ACCIDENTAL_WRITTEN_extended_1qf: value = "1qf"; break; case ACCIDENTAL_WRITTEN_extended_3qf: value = "3qf"; break; case ACCIDENTAL_WRITTEN_extended_1qs: value = "1qs"; break; @@ -305,6 +325,10 @@ data_ACCIDENTAL_WRITTEN_extended AttConverterBase::StrToAccidentalWrittenExtende if (value == "fd") return ACCIDENTAL_WRITTEN_extended_fd; if (value == "nu") return ACCIDENTAL_WRITTEN_extended_nu; if (value == "nd") return ACCIDENTAL_WRITTEN_extended_nd; + if (value == "xu") return ACCIDENTAL_WRITTEN_extended_xu; + if (value == "xd") return ACCIDENTAL_WRITTEN_extended_xd; + if (value == "ffu") return ACCIDENTAL_WRITTEN_extended_ffu; + if (value == "ffd") return ACCIDENTAL_WRITTEN_extended_ffd; if (value == "1qf") return ACCIDENTAL_WRITTEN_extended_1qf; if (value == "3qf") return ACCIDENTAL_WRITTEN_extended_3qf; if (value == "1qs") return ACCIDENTAL_WRITTEN_extended_1qs; @@ -3911,29 +3935,6 @@ audience_AUDIENCE AttConverterBase::StrToAudienceAudience(const std::string &val return audience_AUDIENCE_NONE; } -std::string AttConverterBase::BTremLogFormToStr(bTremLog_FORM data) const -{ - std::string value; - switch (data) { - case bTremLog_FORM_meas: value = "meas"; break; - case bTremLog_FORM_unmeas: value = "unmeas"; break; - default: - LogWarning("Unknown value '%d' for att.bTrem.log@form", data); - value = ""; - break; - } - return value; -} - -bTremLog_FORM AttConverterBase::StrToBTremLogForm(const std::string &value, bool logWarning) const -{ - if (value == "meas") return bTremLog_FORM_meas; - if (value == "unmeas") return bTremLog_FORM_unmeas; - if (logWarning && !value.empty()) - LogWarning("Unsupported value '%s' for att.bTrem.log@form", value.c_str()); - return bTremLog_FORM_NONE; -} - std::string AttConverterBase::BeamRendFormToStr(beamRend_FORM data) const { std::string value; @@ -4036,6 +4037,29 @@ curvature_CURVEDIR AttConverterBase::StrToCurvatureCurvedir(const std::string &v return curvature_CURVEDIR_NONE; } +std::string AttConverterBase::CurvatureDirectionCurveToStr(curvatureDirection_CURVE data) const +{ + std::string value; + switch (data) { + case curvatureDirection_CURVE_a: value = "a"; break; + case curvatureDirection_CURVE_c: value = "c"; break; + default: + LogWarning("Unknown value '%d' for att.curvatureDirection@curve", data); + value = ""; + break; + } + return value; +} + +curvatureDirection_CURVE AttConverterBase::StrToCurvatureDirectionCurve(const std::string &value, bool logWarning) const +{ + if (value == "a") return curvatureDirection_CURVE_a; + if (value == "c") return curvatureDirection_CURVE_c; + if (logWarning && !value.empty()) + LogWarning("Unsupported value '%s' for att.curvatureDirection@curve", value.c_str()); + return curvatureDirection_CURVE_NONE; +} + std::string AttConverterBase::CurveLogFuncToStr(curveLog_FUNC data) const { std::string value; @@ -4226,29 +4250,6 @@ extSymAuth_GLYPHAUTH AttConverterBase::StrToExtSymAuthGlyphauth(const std::strin return extSymAuth_GLYPHAUTH_NONE; } -std::string AttConverterBase::FTremLogFormToStr(fTremLog_FORM data) const -{ - std::string value; - switch (data) { - case fTremLog_FORM_meas: value = "meas"; break; - case fTremLog_FORM_unmeas: value = "unmeas"; break; - default: - LogWarning("Unknown value '%d' for att.fTrem.log@form", data); - value = ""; - break; - } - return value; -} - -fTremLog_FORM AttConverterBase::StrToFTremLogForm(const std::string &value, bool logWarning) const -{ - if (value == "meas") return fTremLog_FORM_meas; - if (value == "unmeas") return fTremLog_FORM_unmeas; - if (logWarning && !value.empty()) - LogWarning("Unsupported value '%s' for att.fTrem.log@form", value.c_str()); - return fTremLog_FORM_NONE; -} - std::string AttConverterBase::FermataVisFormToStr(fermataVis_FORM data) const { std::string value; @@ -4641,29 +4642,6 @@ lineLog_FUNC AttConverterBase::StrToLineLogFunc(const std::string &value, bool l return lineLog_FUNC_NONE; } -std::string AttConverterBase::LiquescentVisCurveToStr(liquescentVis_CURVE data) const -{ - std::string value; - switch (data) { - case liquescentVis_CURVE_a: value = "a"; break; - case liquescentVis_CURVE_c: value = "c"; break; - default: - LogWarning("Unknown value '%d' for att.liquescent.vis@curve", data); - value = ""; - break; - } - return value; -} - -liquescentVis_CURVE AttConverterBase::StrToLiquescentVisCurve(const std::string &value, bool logWarning) const -{ - if (value == "a") return liquescentVis_CURVE_a; - if (value == "c") return liquescentVis_CURVE_c; - if (logWarning && !value.empty()) - LogWarning("Unsupported value '%s' for att.liquescent.vis@curve", value.c_str()); - return liquescentVis_CURVE_NONE; -} - std::string AttConverterBase::MeasurementUnitToStr(measurement_UNIT data) const { std::string value; @@ -4725,8 +4703,11 @@ std::string AttConverterBase::MeiVersionMeiversionToStr(meiVersion_MEIVERSION da case meiVersion_MEIVERSION_3_0_0: value = "3.0.0"; break; case meiVersion_MEIVERSION_4_0_0: value = "4.0.0"; break; case meiVersion_MEIVERSION_4_0_1: value = "4.0.1"; break; - case meiVersion_MEIVERSION_5_0_0_devplusbasic: value = "5.0.0-dev+basic"; break; - case meiVersion_MEIVERSION_5_0_0_dev: value = "5.0.0-dev"; break; + case meiVersion_MEIVERSION_5_0: value = "5.0"; break; + case meiVersion_MEIVERSION_5_0plusbasic: value = "5.0+basic"; break; + case meiVersion_MEIVERSION_5_0plusCMN: value = "5.0+CMN"; break; + case meiVersion_MEIVERSION_5_0plusMensural: value = "5.0+Mensural"; break; + case meiVersion_MEIVERSION_5_0plusNeumes: value = "5.0+Neumes"; break; default: LogWarning("Unknown value '%d' for att.meiVersion@meiversion", data); value = ""; @@ -4741,8 +4722,11 @@ meiVersion_MEIVERSION AttConverterBase::StrToMeiVersionMeiversion(const std::str if (value == "3.0.0") return meiVersion_MEIVERSION_3_0_0; if (value == "4.0.0") return meiVersion_MEIVERSION_4_0_0; if (value == "4.0.1") return meiVersion_MEIVERSION_4_0_1; - if (value == "5.0.0-dev+basic") return meiVersion_MEIVERSION_5_0_0_devplusbasic; - if (value == "5.0.0-dev") return meiVersion_MEIVERSION_5_0_0_dev; + if (value == "5.0") return meiVersion_MEIVERSION_5_0; + if (value == "5.0+basic") return meiVersion_MEIVERSION_5_0plusbasic; + if (value == "5.0+CMN") return meiVersion_MEIVERSION_5_0plusCMN; + if (value == "5.0+Mensural") return meiVersion_MEIVERSION_5_0plusMensural; + if (value == "5.0+Neumes") return meiVersion_MEIVERSION_5_0plusNeumes; if (logWarning && !value.empty()) LogWarning("Unsupported value '%s' for att.meiVersion@meiversion", value.c_str()); return meiVersion_MEIVERSION_NONE; @@ -4894,50 +4878,86 @@ ncForm_CON AttConverterBase::StrToNcFormCon(const std::string &value, bool logWa return ncForm_CON_NONE; } -std::string AttConverterBase::NcFormCurveToStr(ncForm_CURVE data) const +std::string AttConverterBase::NcFormRellenToStr(ncForm_RELLEN data) const { std::string value; switch (data) { - case ncForm_CURVE_a: value = "a"; break; - case ncForm_CURVE_c: value = "c"; break; + case ncForm_RELLEN_l: value = "l"; break; + case ncForm_RELLEN_s: value = "s"; break; default: - LogWarning("Unknown value '%d' for att.ncForm@curve", data); + LogWarning("Unknown value '%d' for att.ncForm@rellen", data); value = ""; break; } return value; } -ncForm_CURVE AttConverterBase::StrToNcFormCurve(const std::string &value, bool logWarning) const +ncForm_RELLEN AttConverterBase::StrToNcFormRellen(const std::string &value, bool logWarning) const { - if (value == "a") return ncForm_CURVE_a; - if (value == "c") return ncForm_CURVE_c; + if (value == "l") return ncForm_RELLEN_l; + if (value == "s") return ncForm_RELLEN_s; if (logWarning && !value.empty()) - LogWarning("Unsupported value '%s' for att.ncForm@curve", value.c_str()); - return ncForm_CURVE_NONE; + LogWarning("Unsupported value '%s' for att.ncForm@rellen", value.c_str()); + return ncForm_RELLEN_NONE; } -std::string AttConverterBase::NcFormRellenToStr(ncForm_RELLEN data) const +std::string AttConverterBase::NeumeTypeTypeToStr(neumeType_TYPE data) const { std::string value; switch (data) { - case ncForm_RELLEN_l: value = "l"; break; - case ncForm_RELLEN_s: value = "s"; break; + case neumeType_TYPE_apostropha: value = "apostropha"; break; + case neumeType_TYPE_bistropha: value = "bistropha"; break; + case neumeType_TYPE_climacus: value = "climacus"; break; + case neumeType_TYPE_clivis: value = "clivis"; break; + case neumeType_TYPE_oriscus: value = "oriscus"; break; + case neumeType_TYPE_pes: value = "pes"; break; + case neumeType_TYPE_pessubpunctis: value = "pessubpunctis"; break; + case neumeType_TYPE_porrectus: value = "porrectus"; break; + case neumeType_TYPE_porrectusflexus: value = "porrectusflexus"; break; + case neumeType_TYPE_pressusmaior: value = "pressusmaior"; break; + case neumeType_TYPE_pressusminor: value = "pressusminor"; break; + case neumeType_TYPE_punctum: value = "punctum"; break; + case neumeType_TYPE_quilisma: value = "quilisma"; break; + case neumeType_TYPE_scandicus: value = "scandicus"; break; + case neumeType_TYPE_strophicus: value = "strophicus"; break; + case neumeType_TYPE_torculus: value = "torculus"; break; + case neumeType_TYPE_torculusresupinus: value = "torculusresupinus"; break; + case neumeType_TYPE_tristropha: value = "tristropha"; break; + case neumeType_TYPE_virga: value = "virga"; break; + case neumeType_TYPE_virgastrata: value = "virgastrata"; break; default: - LogWarning("Unknown value '%d' for att.ncForm@rellen", data); + LogWarning("Unknown value '%d' for att.neumeType@type", data); value = ""; break; } return value; } -ncForm_RELLEN AttConverterBase::StrToNcFormRellen(const std::string &value, bool logWarning) const +neumeType_TYPE AttConverterBase::StrToNeumeTypeType(const std::string &value, bool logWarning) const { - if (value == "l") return ncForm_RELLEN_l; - if (value == "s") return ncForm_RELLEN_s; + if (value == "apostropha") return neumeType_TYPE_apostropha; + if (value == "bistropha") return neumeType_TYPE_bistropha; + if (value == "climacus") return neumeType_TYPE_climacus; + if (value == "clivis") return neumeType_TYPE_clivis; + if (value == "oriscus") return neumeType_TYPE_oriscus; + if (value == "pes") return neumeType_TYPE_pes; + if (value == "pessubpunctis") return neumeType_TYPE_pessubpunctis; + if (value == "porrectus") return neumeType_TYPE_porrectus; + if (value == "porrectusflexus") return neumeType_TYPE_porrectusflexus; + if (value == "pressusmaior") return neumeType_TYPE_pressusmaior; + if (value == "pressusminor") return neumeType_TYPE_pressusminor; + if (value == "punctum") return neumeType_TYPE_punctum; + if (value == "quilisma") return neumeType_TYPE_quilisma; + if (value == "scandicus") return neumeType_TYPE_scandicus; + if (value == "strophicus") return neumeType_TYPE_strophicus; + if (value == "torculus") return neumeType_TYPE_torculus; + if (value == "torculusresupinus") return neumeType_TYPE_torculusresupinus; + if (value == "tristropha") return neumeType_TYPE_tristropha; + if (value == "virga") return neumeType_TYPE_virga; + if (value == "virgastrata") return neumeType_TYPE_virgastrata; if (logWarning && !value.empty()) - LogWarning("Unsupported value '%s' for att.ncForm@rellen", value.c_str()); - return ncForm_RELLEN_NONE; + LogWarning("Unsupported value '%s' for att.neumeType@type", value.c_str()); + return neumeType_TYPE_NONE; } std::string AttConverterBase::NoteGesExtremisToStr(noteGes_EXTREMIS data) const @@ -5426,6 +5446,29 @@ tempoLog_FUNC AttConverterBase::StrToTempoLogFunc(const std::string &value, bool return tempoLog_FUNC_NONE; } +std::string AttConverterBase::TremFormFormToStr(tremForm_FORM data) const +{ + std::string value; + switch (data) { + case tremForm_FORM_meas: value = "meas"; break; + case tremForm_FORM_unmeas: value = "unmeas"; break; + default: + LogWarning("Unknown value '%d' for att.tremForm@form", data); + value = ""; + break; + } + return value; +} + +tremForm_FORM AttConverterBase::StrToTremFormForm(const std::string &value, bool logWarning) const +{ + if (value == "meas") return tremForm_FORM_meas; + if (value == "unmeas") return tremForm_FORM_unmeas; + if (logWarning && !value.empty()) + LogWarning("Unsupported value '%s' for att.tremForm@form", value.c_str()); + return tremForm_FORM_NONE; +} + std::string AttConverterBase::TupletVisNumformatToStr(tupletVis_NUMFORMAT data) const { std::string value; diff --git a/libmei/dist/attconverter.h b/libmei/dist/attconverter.h index cc7724b062a..5d158e75565 100644 --- a/libmei/dist/attconverter.h +++ b/libmei/dist/attconverter.h @@ -300,9 +300,6 @@ class AttConverterBase { std::string AudienceAudienceToStr(audience_AUDIENCE data) const; audience_AUDIENCE StrToAudienceAudience(const std::string &value, bool logWarning = true) const; - std::string BTremLogFormToStr(bTremLog_FORM data) const; - bTremLog_FORM StrToBTremLogForm(const std::string &value, bool logWarning = true) const; - std::string BeamRendFormToStr(beamRend_FORM data) const; beamRend_FORM StrToBeamRendForm(const std::string &value, bool logWarning = true) const; @@ -315,6 +312,9 @@ class AttConverterBase { std::string CurvatureCurvedirToStr(curvature_CURVEDIR data) const; curvature_CURVEDIR StrToCurvatureCurvedir(const std::string &value, bool logWarning = true) const; + std::string CurvatureDirectionCurveToStr(curvatureDirection_CURVE data) const; + curvatureDirection_CURVE StrToCurvatureDirectionCurve(const std::string &value, bool logWarning = true) const; + std::string CurveLogFuncToStr(curveLog_FUNC data) const; curveLog_FUNC StrToCurveLogFunc(const std::string &value, bool logWarning = true) const; @@ -339,9 +339,6 @@ class AttConverterBase { std::string ExtSymAuthGlyphauthToStr(extSymAuth_GLYPHAUTH data) const; extSymAuth_GLYPHAUTH StrToExtSymAuthGlyphauth(const std::string &value, bool logWarning = true) const; - std::string FTremLogFormToStr(fTremLog_FORM data) const; - fTremLog_FORM StrToFTremLogForm(const std::string &value, bool logWarning = true) const; - std::string FermataVisFormToStr(fermataVis_FORM data) const; fermataVis_FORM StrToFermataVisForm(const std::string &value, bool logWarning = true) const; @@ -390,9 +387,6 @@ class AttConverterBase { std::string LineLogFuncToStr(lineLog_FUNC data) const; lineLog_FUNC StrToLineLogFunc(const std::string &value, bool logWarning = true) const; - std::string LiquescentVisCurveToStr(liquescentVis_CURVE data) const; - liquescentVis_CURVE StrToLiquescentVisCurve(const std::string &value, bool logWarning = true) const; - std::string MeasurementUnitToStr(measurement_UNIT data) const; measurement_UNIT StrToMeasurementUnit(const std::string &value, bool logWarning = true) const; @@ -417,12 +411,12 @@ class AttConverterBase { std::string NcFormConToStr(ncForm_CON data) const; ncForm_CON StrToNcFormCon(const std::string &value, bool logWarning = true) const; - std::string NcFormCurveToStr(ncForm_CURVE data) const; - ncForm_CURVE StrToNcFormCurve(const std::string &value, bool logWarning = true) const; - std::string NcFormRellenToStr(ncForm_RELLEN data) const; ncForm_RELLEN StrToNcFormRellen(const std::string &value, bool logWarning = true) const; + std::string NeumeTypeTypeToStr(neumeType_TYPE data) const; + neumeType_TYPE StrToNeumeTypeType(const std::string &value, bool logWarning = true) const; + std::string NoteGesExtremisToStr(noteGes_EXTREMIS data) const; noteGes_EXTREMIS StrToNoteGesExtremis(const std::string &value, bool logWarning = true) const; @@ -477,6 +471,9 @@ class AttConverterBase { std::string TempoLogFuncToStr(tempoLog_FUNC data) const; tempoLog_FUNC StrToTempoLogFunc(const std::string &value, bool logWarning = true) const; + std::string TremFormFormToStr(tremForm_FORM data) const; + tremForm_FORM StrToTremFormForm(const std::string &value, bool logWarning = true) const; + std::string TupletVisNumformatToStr(tupletVis_NUMFORMAT data) const; tupletVis_NUMFORMAT StrToTupletVisNumformat(const std::string &value, bool logWarning = true) const; diff --git a/libmei/dist/attmodule.cpp b/libmei/dist/attmodule.cpp index cdff9d3b589..74f400b5c03 100644 --- a/libmei/dist/attmodule.cpp +++ b/libmei/dist/attmodule.cpp @@ -106,14 +106,6 @@ bool AttModule::SetAnalytical(Object *element, const std::string &attrType, cons return true; } } - if (element->HasAttClass(ATT_KEYSIGANL)) { - AttKeySigAnl *att = dynamic_cast(element); - assert(att); - if (attrType == "mode") { - att->SetMode(att->StrToMode(attrValue)); - return true; - } - } if (element->HasAttClass(ATT_KEYSIGDEFAULTANL)) { AttKeySigDefaultAnl *att = dynamic_cast(element); assert(att); @@ -188,13 +180,6 @@ void AttModule::GetAnalytical(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "intm", att->StrToStr(att->GetIntm()) }); } } - if (element->HasAttClass(ATT_KEYSIGANL)) { - const AttKeySigAnl *att = dynamic_cast(element); - assert(att); - if (att->HasMode()) { - attributes->push_back({ "mode", att->ModeToStr(att->GetMode()) }); - } - } if (element->HasAttClass(ATT_KEYSIGDEFAULTANL)) { const AttKeySigDefaultAnl *att = dynamic_cast(element); assert(att); @@ -251,14 +236,6 @@ bool AttModule::SetCmn(Object *element, const std::string &attrType, const std:: return true; } } - if (element->HasAttClass(ATT_BTREMLOG)) { - AttBTremLog *att = dynamic_cast(element); - assert(att); - if (attrType == "form") { - att->SetForm(att->StrToBTremLogForm(attrValue)); - return true; - } - } if (element->HasAttClass(ATT_BEAMPRESENT)) { AttBeamPresent *att = dynamic_cast(element); assert(att); @@ -347,14 +324,6 @@ bool AttModule::SetCmn(Object *element, const std::string &attrType, const std:: return true; } } - if (element->HasAttClass(ATT_FTREMLOG)) { - AttFTremLog *att = dynamic_cast(element); - assert(att); - if (attrType == "form") { - att->SetForm(att->StrToFTremLogForm(attrValue)); - return true; - } - } if (element->HasAttClass(ATT_GLISSPRESENT)) { AttGlissPresent *att = dynamic_cast(element); assert(att); @@ -511,14 +480,6 @@ bool AttModule::SetCmn(Object *element, const std::string &attrType, const std:: return true; } } - if (element->HasAttClass(ATT_SCOREDEFVISCMN)) { - AttScoreDefVisCmn *att = dynamic_cast(element); - assert(att); - if (attrType == "grid.show") { - att->SetGridShow(att->StrToBoolean(attrValue)); - return true; - } - } if (element->HasAttClass(ATT_SLURREND)) { AttSlurRend *att = dynamic_cast(element); assert(att); @@ -551,6 +512,14 @@ bool AttModule::SetCmn(Object *element, const std::string &attrType, const std:: return true; } } + if (element->HasAttClass(ATT_TREMFORM)) { + AttTremForm *att = dynamic_cast(element); + assert(att); + if (attrType == "form") { + att->SetForm(att->StrToTremFormForm(attrValue)); + return true; + } + } if (element->HasAttClass(ATT_TREMMEASURED)) { AttTremMeasured *att = dynamic_cast(element); assert(att); @@ -572,13 +541,6 @@ void AttModule::GetCmn(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "order", att->ArpegLogOrderToStr(att->GetOrder()) }); } } - if (element->HasAttClass(ATT_BTREMLOG)) { - const AttBTremLog *att = dynamic_cast(element); - assert(att); - if (att->HasForm()) { - attributes->push_back({ "form", att->BTremLogFormToStr(att->GetForm()) }); - } - } if (element->HasAttClass(ATT_BEAMPRESENT)) { const AttBeamPresent *att = dynamic_cast(element); assert(att); @@ -654,13 +616,6 @@ void AttModule::GetCmn(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "expand", att->BooleanToStr(att->GetExpand()) }); } } - if (element->HasAttClass(ATT_FTREMLOG)) { - const AttFTremLog *att = dynamic_cast(element); - assert(att); - if (att->HasForm()) { - attributes->push_back({ "form", att->FTremLogFormToStr(att->GetForm()) }); - } - } if (element->HasAttClass(ATT_GLISSPRESENT)) { const AttGlissPresent *att = dynamic_cast(element); assert(att); @@ -792,13 +747,6 @@ void AttModule::GetCmn(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "reh.enclose", att->RehearsalRehencloseToStr(att->GetRehEnclose()) }); } } - if (element->HasAttClass(ATT_SCOREDEFVISCMN)) { - const AttScoreDefVisCmn *att = dynamic_cast(element); - assert(att); - if (att->HasGridShow()) { - attributes->push_back({ "grid.show", att->BooleanToStr(att->GetGridShow()) }); - } - } if (element->HasAttClass(ATT_SLURREND)) { const AttSlurRend *att = dynamic_cast(element); assert(att); @@ -826,6 +774,13 @@ void AttModule::GetCmn(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "tie.lwidth", att->LinewidthToStr(att->GetTieLwidth()) }); } } + if (element->HasAttClass(ATT_TREMFORM)) { + const AttTremForm *att = dynamic_cast(element); + assert(att); + if (att->HasForm()) { + attributes->push_back({ "form", att->TremFormFormToStr(att->GetForm()) }); + } + } if (element->HasAttClass(ATT_TREMMEASURED)) { const AttTremMeasured *att = dynamic_cast(element); assert(att); @@ -1282,6 +1237,14 @@ bool AttModule::SetGestural(Object *element, const std::string &attrType, const return true; } } + if (element->HasAttClass(ATT_ATTACKING)) { + AttAttacking *att = dynamic_cast(element); + assert(att); + if (attrType == "attacca") { + att->SetAttacca(att->StrToBoolean(attrValue)); + return true; + } + } if (element->HasAttClass(ATT_BENDGES)) { AttBendGes *att = dynamic_cast(element); assert(att); @@ -1318,30 +1281,6 @@ bool AttModule::SetGestural(Object *element, const std::string &attrType, const return true; } } - if (element->HasAttClass(ATT_MDIVGES)) { - AttMdivGes *att = dynamic_cast(element); - assert(att); - if (attrType == "attacca") { - att->SetAttacca(att->StrToBoolean(attrValue)); - return true; - } - } - if (element->HasAttClass(ATT_NCGES)) { - AttNcGes *att = dynamic_cast(element); - assert(att); - if (attrType == "oct.ges") { - att->SetOctGes(att->StrToOctave(attrValue)); - return true; - } - if (attrType == "pname.ges") { - att->SetPnameGes(att->StrToPitchname(attrValue)); - return true; - } - if (attrType == "pnum") { - att->SetPnum(att->StrToInt(attrValue)); - return true; - } - } if (element->HasAttClass(ATT_NOTEGES)) { AttNoteGes *att = dynamic_cast(element); assert(att); @@ -1349,18 +1288,6 @@ bool AttModule::SetGestural(Object *element, const std::string &attrType, const att->SetExtremis(att->StrToNoteGesExtremis(attrValue)); return true; } - if (attrType == "oct.ges") { - att->SetOctGes(att->StrToOctave(attrValue)); - return true; - } - if (attrType == "pname.ges") { - att->SetPnameGes(att->StrToPitchname(attrValue)); - return true; - } - if (attrType == "pnum") { - att->SetPnum(att->StrToInt(attrValue)); - return true; - } } if (element->HasAttClass(ATT_ORNAMENTACCIDGES)) { AttOrnamentAccidGes *att = dynamic_cast(element); @@ -1374,11 +1301,19 @@ bool AttModule::SetGestural(Object *element, const std::string &attrType, const return true; } } - if (element->HasAttClass(ATT_SECTIONGES)) { - AttSectionGes *att = dynamic_cast(element); + if (element->HasAttClass(ATT_PITCHGES)) { + AttPitchGes *att = dynamic_cast(element); assert(att); - if (attrType == "attacca") { - att->SetAttacca(att->StrToBoolean(attrValue)); + if (attrType == "oct.ges") { + att->SetOctGes(att->StrToOctave(attrValue)); + return true; + } + if (attrType == "pname.ges") { + att->SetPnameGes(att->StrToPitchname(attrValue)); + return true; + } + if (attrType == "pnum") { + att->SetPnum(att->StrToInt(attrValue)); return true; } } @@ -1438,6 +1373,13 @@ void AttModule::GetGestural(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "artic.ges", att->ArticulationListToStr(att->GetArticGes()) }); } } + if (element->HasAttClass(ATT_ATTACKING)) { + const AttAttacking *att = dynamic_cast(element); + assert(att); + if (att->HasAttacca()) { + attributes->push_back({ "attacca", att->BooleanToStr(att->GetAttacca()) }); + } + } if (element->HasAttClass(ATT_BENDGES)) { const AttBendGes *att = dynamic_cast(element); assert(att); @@ -1467,41 +1409,12 @@ void AttModule::GetGestural(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "dur.recip", att->StrToStr(att->GetDurRecip()) }); } } - if (element->HasAttClass(ATT_MDIVGES)) { - const AttMdivGes *att = dynamic_cast(element); - assert(att); - if (att->HasAttacca()) { - attributes->push_back({ "attacca", att->BooleanToStr(att->GetAttacca()) }); - } - } - if (element->HasAttClass(ATT_NCGES)) { - const AttNcGes *att = dynamic_cast(element); - assert(att); - if (att->HasOctGes()) { - attributes->push_back({ "oct.ges", att->OctaveToStr(att->GetOctGes()) }); - } - if (att->HasPnameGes()) { - attributes->push_back({ "pname.ges", att->PitchnameToStr(att->GetPnameGes()) }); - } - if (att->HasPnum()) { - attributes->push_back({ "pnum", att->IntToStr(att->GetPnum()) }); - } - } if (element->HasAttClass(ATT_NOTEGES)) { const AttNoteGes *att = dynamic_cast(element); assert(att); if (att->HasExtremis()) { attributes->push_back({ "extremis", att->NoteGesExtremisToStr(att->GetExtremis()) }); } - if (att->HasOctGes()) { - attributes->push_back({ "oct.ges", att->OctaveToStr(att->GetOctGes()) }); - } - if (att->HasPnameGes()) { - attributes->push_back({ "pname.ges", att->PitchnameToStr(att->GetPnameGes()) }); - } - if (att->HasPnum()) { - attributes->push_back({ "pnum", att->IntToStr(att->GetPnum()) }); - } } if (element->HasAttClass(ATT_ORNAMENTACCIDGES)) { const AttOrnamentAccidGes *att = dynamic_cast(element); @@ -1513,11 +1426,17 @@ void AttModule::GetGestural(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "accidlower.ges", att->AccidentalGesturalToStr(att->GetAccidlowerGes()) }); } } - if (element->HasAttClass(ATT_SECTIONGES)) { - const AttSectionGes *att = dynamic_cast(element); + if (element->HasAttClass(ATT_PITCHGES)) { + const AttPitchGes *att = dynamic_cast(element); assert(att); - if (att->HasAttacca()) { - attributes->push_back({ "attacca", att->BooleanToStr(att->GetAttacca()) }); + if (att->HasOctGes()) { + attributes->push_back({ "oct.ges", att->OctaveToStr(att->GetOctGes()) }); + } + if (att->HasPnameGes()) { + attributes->push_back({ "pname.ges", att->PitchnameToStr(att->GetPnameGes()) }); + } + if (att->HasPnum()) { + attributes->push_back({ "pnum", att->IntToStr(att->GetPnum()) }); } } if (element->HasAttClass(ATT_SOUNDLOCATION)) { @@ -2119,7 +2038,7 @@ bool AttModule::SetNeumes(Object *element, const std::string &attrType, const st AttDivLineLog *att = dynamic_cast(element); assert(att); if (attrType == "form") { - att->SetForm(att->StrToStr(attrValue)); + att->SetForm(att->StrToDivLineLogForm(attrValue)); return true; } } @@ -2146,10 +2065,6 @@ bool AttModule::SetNeumes(Object *element, const std::string &attrType, const st att->SetCon(att->StrToNcFormCon(attrValue)); return true; } - if (attrType == "curve") { - att->SetCurve(att->StrToNcFormCurve(attrValue)); - return true; - } if (attrType == "hooked") { att->SetHooked(att->StrToBoolean(attrValue)); return true; @@ -2171,6 +2086,14 @@ bool AttModule::SetNeumes(Object *element, const std::string &attrType, const st return true; } } + if (element->HasAttClass(ATT_NEUMETYPE)) { + AttNeumeType *att = dynamic_cast(element); + assert(att); + if (attrType == "type") { + att->SetType(att->StrToStr(attrValue)); + return true; + } + } return false; } @@ -2181,7 +2104,7 @@ void AttModule::GetNeumes(const Object *element, ArrayOfStrAttr *attributes) const AttDivLineLog *att = dynamic_cast(element); assert(att); if (att->HasForm()) { - attributes->push_back({ "form", att->StrToStr(att->GetForm()) }); + attributes->push_back({ "form", att->DivLineLogFormToStr(att->GetForm()) }); } } if (element->HasAttClass(ATT_NCLOG)) { @@ -2203,9 +2126,6 @@ void AttModule::GetNeumes(const Object *element, ArrayOfStrAttr *attributes) if (att->HasCon()) { attributes->push_back({ "con", att->NcFormConToStr(att->GetCon()) }); } - if (att->HasCurve()) { - attributes->push_back({ "curve", att->NcFormCurveToStr(att->GetCurve()) }); - } if (att->HasHooked()) { attributes->push_back({ "hooked", att->BooleanToStr(att->GetHooked()) }); } @@ -2222,6 +2142,13 @@ void AttModule::GetNeumes(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "tilt", att->CompassdirectionToStr(att->GetTilt()) }); } } + if (element->HasAttClass(ATT_NEUMETYPE)) { + const AttNeumeType *att = dynamic_cast(element); + assert(att); + if (att->HasType()) { + attributes->push_back({ "type", att->StrToStr(att->GetType()) }); + } + } } } // namespace vrv @@ -2530,14 +2457,6 @@ bool AttModule::SetShared(Object *element, const std::string &attrType, const st if (element->HasAttClass(ATT_COORDINATED)) { AttCoordinated *att = dynamic_cast(element); assert(att); - if (attrType == "ulx") { - att->SetUlx(att->StrToInt(attrValue)); - return true; - } - if (attrType == "uly") { - att->SetUly(att->StrToInt(attrValue)); - return true; - } if (attrType == "lrx") { att->SetLrx(att->StrToInt(attrValue)); return true; @@ -2551,6 +2470,18 @@ bool AttModule::SetShared(Object *element, const std::string &attrType, const st return true; } } + if (element->HasAttClass(ATT_COORDINATEDUL)) { + AttCoordinatedUl *att = dynamic_cast(element); + assert(att); + if (attrType == "ulx") { + att->SetUlx(att->StrToInt(attrValue)); + return true; + } + if (attrType == "uly") { + att->SetUly(att->StrToInt(attrValue)); + return true; + } + } if (element->HasAttClass(ATT_CUE)) { AttCue *att = dynamic_cast(element); assert(att); @@ -2575,18 +2506,6 @@ bool AttModule::SetShared(Object *element, const std::string &attrType, const st return true; } } - if (element->HasAttClass(ATT_CURVEREND)) { - AttCurveRend *att = dynamic_cast(element); - assert(att); - if (attrType == "lform") { - att->SetLform(att->StrToLineform(attrValue)); - return true; - } - if (attrType == "lwidth") { - att->SetLwidth(att->StrToLinewidth(attrValue)); - return true; - } - } if (element->HasAttClass(ATT_CUSTOSLOG)) { AttCustosLog *att = dynamic_cast(element); assert(att); @@ -2819,6 +2738,14 @@ bool AttModule::SetShared(Object *element, const std::string &attrType, const st return true; } } + if (element->HasAttClass(ATT_KEYMODE)) { + AttKeyMode *att = dynamic_cast(element); + assert(att); + if (attrType == "mode") { + att->SetMode(att->StrToMode(attrValue)); + return true; + } + } if (element->HasAttClass(ATT_KEYSIGLOG)) { AttKeySigLog *att = dynamic_cast(element); assert(att); @@ -2906,14 +2833,14 @@ bool AttModule::SetShared(Object *element, const std::string &attrType, const st att->SetLform(att->StrToLineform(attrValue)); return true; } - if (attrType == "lsegs") { - att->SetLsegs(att->StrToInt(attrValue)); - return true; - } if (attrType == "lwidth") { att->SetLwidth(att->StrToLinewidth(attrValue)); return true; } + if (attrType == "lsegs") { + att->SetLsegs(att->StrToInt(attrValue)); + return true; + } } if (element->HasAttClass(ATT_LINKING)) { AttLinking *att = dynamic_cast(element); @@ -3027,6 +2954,14 @@ bool AttModule::SetShared(Object *element, const std::string &attrType, const st return true; } } + if (element->HasAttClass(ATT_MENSURLOG)) { + AttMensurLog *att = dynamic_cast(element); + assert(att); + if (attrType == "level") { + att->SetLevel(att->StrToDuration(attrValue)); + return true; + } + } if (element->HasAttClass(ATT_METADATAPOINTING)) { AttMetadataPointing *att = dynamic_cast(element); assert(att); @@ -4128,12 +4063,6 @@ void AttModule::GetShared(const Object *element, ArrayOfStrAttr *attributes) if (element->HasAttClass(ATT_COORDINATED)) { const AttCoordinated *att = dynamic_cast(element); assert(att); - if (att->HasUlx()) { - attributes->push_back({ "ulx", att->IntToStr(att->GetUlx()) }); - } - if (att->HasUly()) { - attributes->push_back({ "uly", att->IntToStr(att->GetUly()) }); - } if (att->HasLrx()) { attributes->push_back({ "lrx", att->IntToStr(att->GetLrx()) }); } @@ -4144,6 +4073,16 @@ void AttModule::GetShared(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "rotate", att->DblToStr(att->GetRotate()) }); } } + if (element->HasAttClass(ATT_COORDINATEDUL)) { + const AttCoordinatedUl *att = dynamic_cast(element); + assert(att); + if (att->HasUlx()) { + attributes->push_back({ "ulx", att->IntToStr(att->GetUlx()) }); + } + if (att->HasUly()) { + attributes->push_back({ "uly", att->IntToStr(att->GetUly()) }); + } + } if (element->HasAttClass(ATT_CUE)) { const AttCue *att = dynamic_cast(element); assert(att); @@ -4164,16 +4103,6 @@ void AttModule::GetShared(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "curvedir", att->CurvatureCurvedirToStr(att->GetCurvedir()) }); } } - if (element->HasAttClass(ATT_CURVEREND)) { - const AttCurveRend *att = dynamic_cast(element); - assert(att); - if (att->HasLform()) { - attributes->push_back({ "lform", att->LineformToStr(att->GetLform()) }); - } - if (att->HasLwidth()) { - attributes->push_back({ "lwidth", att->LinewidthToStr(att->GetLwidth()) }); - } - } if (element->HasAttClass(ATT_CUSTOSLOG)) { const AttCustosLog *att = dynamic_cast(element); assert(att); @@ -4371,6 +4300,13 @@ void AttModule::GetShared(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "join", att->StrToStr(att->GetJoin()) }); } } + if (element->HasAttClass(ATT_KEYMODE)) { + const AttKeyMode *att = dynamic_cast(element); + assert(att); + if (att->HasMode()) { + attributes->push_back({ "mode", att->ModeToStr(att->GetMode()) }); + } + } if (element->HasAttClass(ATT_KEYSIGLOG)) { const AttKeySigLog *att = dynamic_cast(element); assert(att); @@ -4445,12 +4381,12 @@ void AttModule::GetShared(const Object *element, ArrayOfStrAttr *attributes) if (att->HasLform()) { attributes->push_back({ "lform", att->LineformToStr(att->GetLform()) }); } - if (att->HasLsegs()) { - attributes->push_back({ "lsegs", att->IntToStr(att->GetLsegs()) }); - } if (att->HasLwidth()) { attributes->push_back({ "lwidth", att->LinewidthToStr(att->GetLwidth()) }); } + if (att->HasLsegs()) { + attributes->push_back({ "lsegs", att->IntToStr(att->GetLsegs()) }); + } } if (element->HasAttClass(ATT_LINKING)) { const AttLinking *att = dynamic_cast(element); @@ -4543,6 +4479,13 @@ void AttModule::GetShared(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "meiversion", att->MeiVersionMeiversionToStr(att->GetMeiversion()) }); } } + if (element->HasAttClass(ATT_MENSURLOG)) { + const AttMensurLog *att = dynamic_cast(element); + assert(att); + if (att->HasLevel()) { + attributes->push_back({ "level", att->DurationToStr(att->GetLevel()) }); + } + } if (element->HasAttClass(ATT_METADATAPOINTING)) { const AttMetadataPointing *att = dynamic_cast(element); assert(att); @@ -5437,14 +5380,6 @@ bool AttModule::SetVisual(Object *element, const std::string &attrType, const st att->SetArrowFillcolor(att->StrToStr(attrValue)); return true; } - if (attrType == "line.form") { - att->SetLineForm(att->StrToLineform(attrValue)); - return true; - } - if (attrType == "line.width") { - att->SetLineWidth(att->StrToLinewidth(attrValue)); - return true; - } } if (element->HasAttClass(ATT_BARLINEVIS)) { AttBarLineVis *att = dynamic_cast(element); @@ -5506,6 +5441,14 @@ bool AttModule::SetVisual(Object *element, const std::string &attrType, const st return true; } } + if (element->HasAttClass(ATT_CURVATUREDIRECTION)) { + AttCurvatureDirection *att = dynamic_cast(element); + assert(att); + if (attrType == "curve") { + att->SetCurve(att->StrToCurvatureDirectionCurve(attrValue)); + return true; + } + } if (element->HasAttClass(ATT_EPISEMAVIS)) { AttEpisemaVis *att = dynamic_cast(element); assert(att); @@ -5554,6 +5497,14 @@ bool AttModule::SetVisual(Object *element, const std::string &attrType, const st return true; } } + if (element->HasAttClass(ATT_GUITARGRIDVIS)) { + AttGuitarGridVis *att = dynamic_cast(element); + assert(att); + if (attrType == "grid.show") { + att->SetGridShow(att->StrToBoolean(attrValue)); + return true; + } + } if (element->HasAttClass(ATT_HAIRPINVIS)) { AttHairpinVis *att = dynamic_cast(element); assert(att); @@ -5653,10 +5604,6 @@ bool AttModule::SetVisual(Object *element, const std::string &attrType, const st if (element->HasAttClass(ATT_LIQUESCENTVIS)) { AttLiquescentVis *att = dynamic_cast(element); assert(att); - if (attrType == "curve") { - att->SetCurve(att->StrToLiquescentVisCurve(attrValue)); - return true; - } if (attrType == "looped") { att->SetLooped(att->StrToBoolean(attrValue)); return true; @@ -5829,10 +5776,6 @@ bool AttModule::SetVisual(Object *element, const std::string &attrType, const st if (element->HasAttClass(ATT_STAFFDEFVIS)) { AttStaffDefVis *att = dynamic_cast(element); assert(att); - if (attrType == "grid.show") { - att->SetGridShow(att->StrToBoolean(attrValue)); - return true; - } if (attrType == "layerscheme") { att->SetLayerscheme(att->StrToLayerscheme(attrValue)); return true; @@ -5937,12 +5880,6 @@ void AttModule::GetVisual(const Object *element, ArrayOfStrAttr *attributes) if (att->HasArrowFillcolor()) { attributes->push_back({ "arrow.fillcolor", att->StrToStr(att->GetArrowFillcolor()) }); } - if (att->HasLineForm()) { - attributes->push_back({ "line.form", att->LineformToStr(att->GetLineForm()) }); - } - if (att->HasLineWidth()) { - attributes->push_back({ "line.width", att->LinewidthToStr(att->GetLineWidth()) }); - } } if (element->HasAttClass(ATT_BARLINEVIS)) { const AttBarLineVis *att = dynamic_cast(element); @@ -5994,6 +5931,13 @@ void AttModule::GetVisual(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "clef.visible", att->BooleanToStr(att->GetClefVisible()) }); } } + if (element->HasAttClass(ATT_CURVATUREDIRECTION)) { + const AttCurvatureDirection *att = dynamic_cast(element); + assert(att); + if (att->HasCurve()) { + attributes->push_back({ "curve", att->CurvatureDirectionCurveToStr(att->GetCurve()) }); + } + } if (element->HasAttClass(ATT_EPISEMAVIS)) { const AttEpisemaVis *att = dynamic_cast(element); assert(att); @@ -6034,6 +5978,13 @@ void AttModule::GetVisual(const Object *element, ArrayOfStrAttr *attributes) attributes->push_back({ "orient", att->FingGrpVisOrientToStr(att->GetOrient()) }); } } + if (element->HasAttClass(ATT_GUITARGRIDVIS)) { + const AttGuitarGridVis *att = dynamic_cast(element); + assert(att); + if (att->HasGridShow()) { + attributes->push_back({ "grid.show", att->BooleanToStr(att->GetGridShow()) }); + } + } if (element->HasAttClass(ATT_HAIRPINVIS)) { const AttHairpinVis *att = dynamic_cast(element); assert(att); @@ -6116,9 +6067,6 @@ void AttModule::GetVisual(const Object *element, ArrayOfStrAttr *attributes) if (element->HasAttClass(ATT_LIQUESCENTVIS)) { const AttLiquescentVis *att = dynamic_cast(element); assert(att); - if (att->HasCurve()) { - attributes->push_back({ "curve", att->LiquescentVisCurveToStr(att->GetCurve()) }); - } if (att->HasLooped()) { attributes->push_back({ "looped", att->BooleanToStr(att->GetLooped()) }); } @@ -6263,9 +6211,6 @@ void AttModule::GetVisual(const Object *element, ArrayOfStrAttr *attributes) if (element->HasAttClass(ATT_STAFFDEFVIS)) { const AttStaffDefVis *att = dynamic_cast(element); assert(att); - if (att->HasGridShow()) { - attributes->push_back({ "grid.show", att->BooleanToStr(att->GetGridShow()) }); - } if (att->HasLayerscheme()) { attributes->push_back({ "layerscheme", att->LayerschemeToStr(att->GetLayerscheme()) }); } diff --git a/libmei/dist/atts_analytical.cpp b/libmei/dist/atts_analytical.cpp index 205f2acaa2f..e913cbb8e29 100644 --- a/libmei/dist/atts_analytical.cpp +++ b/libmei/dist/atts_analytical.cpp @@ -182,46 +182,6 @@ bool AttIntervalMelodic::HasIntm() const return (m_intm != ""); } -//---------------------------------------------------------------------------- -// AttKeySigAnl -//---------------------------------------------------------------------------- - -AttKeySigAnl::AttKeySigAnl() : Att() -{ - ResetKeySigAnl(); -} - -void AttKeySigAnl::ResetKeySigAnl() -{ - m_mode = MODE_NONE; -} - -bool AttKeySigAnl::ReadKeySigAnl(pugi::xml_node element, bool removeAttr) -{ - bool hasAttribute = false; - if (element.attribute("mode")) { - this->SetMode(StrToMode(element.attribute("mode").value())); - if (removeAttr) element.remove_attribute("mode"); - hasAttribute = true; - } - return hasAttribute; -} - -bool AttKeySigAnl::WriteKeySigAnl(pugi::xml_node element) -{ - bool wroteAttribute = false; - if (this->HasMode()) { - element.append_attribute("mode") = ModeToStr(this->GetMode()).c_str(); - wroteAttribute = true; - } - return wroteAttribute; -} - -bool AttKeySigAnl::HasMode() const -{ - return (m_mode != MODE_NONE); -} - //---------------------------------------------------------------------------- // AttKeySigDefaultAnl //---------------------------------------------------------------------------- diff --git a/libmei/dist/atts_analytical.h b/libmei/dist/atts_analytical.h index f214943cf8e..8381b948639 100644 --- a/libmei/dist/atts_analytical.h +++ b/libmei/dist/atts_analytical.h @@ -232,55 +232,6 @@ class InstIntervalMelodic : public AttIntervalMelodic { virtual ~InstIntervalMelodic() = default; }; -//---------------------------------------------------------------------------- -// AttKeySigAnl -//---------------------------------------------------------------------------- - -class AttKeySigAnl : public Att { -protected: - AttKeySigAnl(); - ~AttKeySigAnl() = default; - -public: - /** Reset the default values for the attribute class **/ - void ResetKeySigAnl(); - - /** Read the values for the attribute class **/ - bool ReadKeySigAnl(pugi::xml_node element, bool removeAttr = true); - - /** Write the values for the attribute class **/ - bool WriteKeySigAnl(pugi::xml_node element); - - /** - * @name Setters, getters and presence checker for class members. - * The checker returns true if the attribute class is set (e.g., not equal - * to the default value) - **/ - ///@{ - void SetMode(data_MODE mode_) { m_mode = mode_; } - data_MODE GetMode() const { return m_mode; } - bool HasMode() const; - ///@} - -private: - /** Indicates major, minor, or other tonality. **/ - data_MODE m_mode; -}; - -//---------------------------------------------------------------------------- -// InstKeySigAnl -//---------------------------------------------------------------------------- - -/** - * Instantiable version of AttKeySigAnl - */ - -class InstKeySigAnl : public AttKeySigAnl { -public: - InstKeySigAnl() = default; - virtual ~InstKeySigAnl() = default; -}; - //---------------------------------------------------------------------------- // AttKeySigDefaultAnl //---------------------------------------------------------------------------- diff --git a/libmei/dist/atts_cmn.cpp b/libmei/dist/atts_cmn.cpp index b36be4bd036..837e1dd4f66 100644 --- a/libmei/dist/atts_cmn.cpp +++ b/libmei/dist/atts_cmn.cpp @@ -62,46 +62,6 @@ bool AttArpegLog::HasOrder() const return (m_order != arpegLog_ORDER_NONE); } -//---------------------------------------------------------------------------- -// AttBTremLog -//---------------------------------------------------------------------------- - -AttBTremLog::AttBTremLog() : Att() -{ - ResetBTremLog(); -} - -void AttBTremLog::ResetBTremLog() -{ - m_form = bTremLog_FORM_NONE; -} - -bool AttBTremLog::ReadBTremLog(pugi::xml_node element, bool removeAttr) -{ - bool hasAttribute = false; - if (element.attribute("form")) { - this->SetForm(StrToBTremLogForm(element.attribute("form").value())); - if (removeAttr) element.remove_attribute("form"); - hasAttribute = true; - } - return hasAttribute; -} - -bool AttBTremLog::WriteBTremLog(pugi::xml_node element) -{ - bool wroteAttribute = false; - if (this->HasForm()) { - element.append_attribute("form") = BTremLogFormToStr(this->GetForm()).c_str(); - wroteAttribute = true; - } - return wroteAttribute; -} - -bool AttBTremLog::HasForm() const -{ - return (m_form != bTremLog_FORM_NONE); -} - //---------------------------------------------------------------------------- // AttBeamPresent //---------------------------------------------------------------------------- @@ -522,46 +482,6 @@ bool AttExpandable::HasExpand() const return (m_expand != BOOLEAN_NONE); } -//---------------------------------------------------------------------------- -// AttFTremLog -//---------------------------------------------------------------------------- - -AttFTremLog::AttFTremLog() : Att() -{ - ResetFTremLog(); -} - -void AttFTremLog::ResetFTremLog() -{ - m_form = fTremLog_FORM_NONE; -} - -bool AttFTremLog::ReadFTremLog(pugi::xml_node element, bool removeAttr) -{ - bool hasAttribute = false; - if (element.attribute("form")) { - this->SetForm(StrToFTremLogForm(element.attribute("form").value())); - if (removeAttr) element.remove_attribute("form"); - hasAttribute = true; - } - return hasAttribute; -} - -bool AttFTremLog::WriteFTremLog(pugi::xml_node element) -{ - bool wroteAttribute = false; - if (this->HasForm()) { - element.append_attribute("form") = FTremLogFormToStr(this->GetForm()).c_str(); - wroteAttribute = true; - } - return wroteAttribute; -} - -bool AttFTremLog::HasForm() const -{ - return (m_form != fTremLog_FORM_NONE); -} - //---------------------------------------------------------------------------- // AttGlissPresent //---------------------------------------------------------------------------- @@ -1287,46 +1207,6 @@ bool AttRehearsal::HasRehEnclose() const return (m_rehEnclose != rehearsal_REHENCLOSE_NONE); } -//---------------------------------------------------------------------------- -// AttScoreDefVisCmn -//---------------------------------------------------------------------------- - -AttScoreDefVisCmn::AttScoreDefVisCmn() : Att() -{ - ResetScoreDefVisCmn(); -} - -void AttScoreDefVisCmn::ResetScoreDefVisCmn() -{ - m_gridShow = BOOLEAN_NONE; -} - -bool AttScoreDefVisCmn::ReadScoreDefVisCmn(pugi::xml_node element, bool removeAttr) -{ - bool hasAttribute = false; - if (element.attribute("grid.show")) { - this->SetGridShow(StrToBoolean(element.attribute("grid.show").value())); - if (removeAttr) element.remove_attribute("grid.show"); - hasAttribute = true; - } - return hasAttribute; -} - -bool AttScoreDefVisCmn::WriteScoreDefVisCmn(pugi::xml_node element) -{ - bool wroteAttribute = false; - if (this->HasGridShow()) { - element.append_attribute("grid.show") = BooleanToStr(this->GetGridShow()).c_str(); - wroteAttribute = true; - } - return wroteAttribute; -} - -bool AttScoreDefVisCmn::HasGridShow() const -{ - return (m_gridShow != BOOLEAN_NONE); -} - //---------------------------------------------------------------------------- // AttSlurRend //---------------------------------------------------------------------------- @@ -1477,6 +1357,46 @@ bool AttTieRend::HasTieLwidth() const return (m_tieLwidth.HasValue()); } +//---------------------------------------------------------------------------- +// AttTremForm +//---------------------------------------------------------------------------- + +AttTremForm::AttTremForm() : Att() +{ + ResetTremForm(); +} + +void AttTremForm::ResetTremForm() +{ + m_form = tremForm_FORM_NONE; +} + +bool AttTremForm::ReadTremForm(pugi::xml_node element, bool removeAttr) +{ + bool hasAttribute = false; + if (element.attribute("form")) { + this->SetForm(StrToTremFormForm(element.attribute("form").value())); + if (removeAttr) element.remove_attribute("form"); + hasAttribute = true; + } + return hasAttribute; +} + +bool AttTremForm::WriteTremForm(pugi::xml_node element) +{ + bool wroteAttribute = false; + if (this->HasForm()) { + element.append_attribute("form") = TremFormFormToStr(this->GetForm()).c_str(); + wroteAttribute = true; + } + return wroteAttribute; +} + +bool AttTremForm::HasForm() const +{ + return (m_form != tremForm_FORM_NONE); +} + //---------------------------------------------------------------------------- // AttTremMeasured //---------------------------------------------------------------------------- diff --git a/libmei/dist/atts_cmn.h b/libmei/dist/atts_cmn.h index 747223483ae..83f97531ef0 100644 --- a/libmei/dist/atts_cmn.h +++ b/libmei/dist/atts_cmn.h @@ -74,55 +74,6 @@ class InstArpegLog : public AttArpegLog { virtual ~InstArpegLog() = default; }; -//---------------------------------------------------------------------------- -// AttBTremLog -//---------------------------------------------------------------------------- - -class AttBTremLog : public Att { -protected: - AttBTremLog(); - ~AttBTremLog() = default; - -public: - /** Reset the default values for the attribute class **/ - void ResetBTremLog(); - - /** Read the values for the attribute class **/ - bool ReadBTremLog(pugi::xml_node element, bool removeAttr = true); - - /** Write the values for the attribute class **/ - bool WriteBTremLog(pugi::xml_node element); - - /** - * @name Setters, getters and presence checker for class members. - * The checker returns true if the attribute class is set (e.g., not equal - * to the default value) - **/ - ///@{ - void SetForm(bTremLog_FORM form_) { m_form = form_; } - bTremLog_FORM GetForm() const { return m_form; } - bool HasForm() const; - ///@} - -private: - /** Indicates to what degree the harmonic label is supported by the notation. **/ - bTremLog_FORM m_form; -}; - -//---------------------------------------------------------------------------- -// InstBTremLog -//---------------------------------------------------------------------------- - -/** - * Instantiable version of AttBTremLog - */ - -class InstBTremLog : public AttBTremLog { -public: - InstBTremLog() = default; - virtual ~InstBTremLog() = default; -}; - //---------------------------------------------------------------------------- // AttBeamPresent //---------------------------------------------------------------------------- @@ -611,55 +562,6 @@ class InstExpandable : public AttExpandable { virtual ~InstExpandable() = default; }; -//---------------------------------------------------------------------------- -// AttFTremLog -//---------------------------------------------------------------------------- - -class AttFTremLog : public Att { -protected: - AttFTremLog(); - ~AttFTremLog() = default; - -public: - /** Reset the default values for the attribute class **/ - void ResetFTremLog(); - - /** Read the values for the attribute class **/ - bool ReadFTremLog(pugi::xml_node element, bool removeAttr = true); - - /** Write the values for the attribute class **/ - bool WriteFTremLog(pugi::xml_node element); - - /** - * @name Setters, getters and presence checker for class members. - * The checker returns true if the attribute class is set (e.g., not equal - * to the default value) - **/ - ///@{ - void SetForm(fTremLog_FORM form_) { m_form = form_; } - fTremLog_FORM GetForm() const { return m_form; } - bool HasForm() const; - ///@} - -private: - /** Indicates to what degree the harmonic label is supported by the notation. **/ - fTremLog_FORM m_form; -}; - -//---------------------------------------------------------------------------- -// InstFTremLog -//---------------------------------------------------------------------------- - -/** - * Instantiable version of AttFTremLog - */ - -class InstFTremLog : public AttFTremLog { -public: - InstFTremLog() = default; - virtual ~InstFTremLog() = default; -}; - //---------------------------------------------------------------------------- // AttGlissPresent //---------------------------------------------------------------------------- @@ -1440,55 +1342,6 @@ class InstRehearsal : public AttRehearsal { virtual ~InstRehearsal() = default; }; -//---------------------------------------------------------------------------- -// AttScoreDefVisCmn -//---------------------------------------------------------------------------- - -class AttScoreDefVisCmn : public Att { -protected: - AttScoreDefVisCmn(); - ~AttScoreDefVisCmn() = default; - -public: - /** Reset the default values for the attribute class **/ - void ResetScoreDefVisCmn(); - - /** Read the values for the attribute class **/ - bool ReadScoreDefVisCmn(pugi::xml_node element, bool removeAttr = true); - - /** Write the values for the attribute class **/ - bool WriteScoreDefVisCmn(pugi::xml_node element); - - /** - * @name Setters, getters and presence checker for class members. - * The checker returns true if the attribute class is set (e.g., not equal - * to the default value) - **/ - ///@{ - void SetGridShow(data_BOOLEAN gridShow_) { m_gridShow = gridShow_; } - data_BOOLEAN GetGridShow() const { return m_gridShow; } - bool HasGridShow() const; - ///@} - -private: - /** Determines whether to display guitar chord grids. **/ - data_BOOLEAN m_gridShow; -}; - -//---------------------------------------------------------------------------- -// InstScoreDefVisCmn -//---------------------------------------------------------------------------- - -/** - * Instantiable version of AttScoreDefVisCmn - */ - -class InstScoreDefVisCmn : public AttScoreDefVisCmn { -public: - InstScoreDefVisCmn() = default; - virtual ~InstScoreDefVisCmn() = default; -}; - //---------------------------------------------------------------------------- // AttSlurRend //---------------------------------------------------------------------------- @@ -1656,6 +1509,55 @@ class InstTieRend : public AttTieRend { virtual ~InstTieRend() = default; }; +//---------------------------------------------------------------------------- +// AttTremForm +//---------------------------------------------------------------------------- + +class AttTremForm : public Att { +protected: + AttTremForm(); + ~AttTremForm() = default; + +public: + /** Reset the default values for the attribute class **/ + void ResetTremForm(); + + /** Read the values for the attribute class **/ + bool ReadTremForm(pugi::xml_node element, bool removeAttr = true); + + /** Write the values for the attribute class **/ + bool WriteTremForm(pugi::xml_node element); + + /** + * @name Setters, getters and presence checker for class members. + * The checker returns true if the attribute class is set (e.g., not equal + * to the default value) + **/ + ///@{ + void SetForm(tremForm_FORM form_) { m_form = form_; } + tremForm_FORM GetForm() const { return m_form; } + bool HasForm() const; + ///@} + +private: + /** Indicates to what degree the harmonic label is supported by the notation. **/ + tremForm_FORM m_form; +}; + +//---------------------------------------------------------------------------- +// InstTremForm +//---------------------------------------------------------------------------- + +/** + * Instantiable version of AttTremForm + */ + +class InstTremForm : public AttTremForm { +public: + InstTremForm() = default; + virtual ~InstTremForm() = default; +}; + //---------------------------------------------------------------------------- // AttTremMeasured //---------------------------------------------------------------------------- diff --git a/libmei/dist/atts_gestural.cpp b/libmei/dist/atts_gestural.cpp index b448bd659a6..28917cfcbf6 100644 --- a/libmei/dist/atts_gestural.cpp +++ b/libmei/dist/atts_gestural.cpp @@ -102,6 +102,46 @@ bool AttArticulationGes::HasArticGes() const return (m_articGes != std::vector()); } +//---------------------------------------------------------------------------- +// AttAttacking +//---------------------------------------------------------------------------- + +AttAttacking::AttAttacking() : Att() +{ + ResetAttacking(); +} + +void AttAttacking::ResetAttacking() +{ + m_attacca = BOOLEAN_NONE; +} + +bool AttAttacking::ReadAttacking(pugi::xml_node element, bool removeAttr) +{ + bool hasAttribute = false; + if (element.attribute("attacca")) { + this->SetAttacca(StrToBoolean(element.attribute("attacca").value())); + if (removeAttr) element.remove_attribute("attacca"); + hasAttribute = true; + } + return hasAttribute; +} + +bool AttAttacking::WriteAttacking(pugi::xml_node element) +{ + bool wroteAttribute = false; + if (this->HasAttacca()) { + element.append_attribute("attacca") = BooleanToStr(this->GetAttacca()).c_str(); + wroteAttribute = true; + } + return wroteAttribute; +} + +bool AttAttacking::HasAttacca() const +{ + return (m_attacca != BOOLEAN_NONE); +} + //---------------------------------------------------------------------------- // AttBendGes //---------------------------------------------------------------------------- @@ -257,116 +297,6 @@ bool AttDurationGes::HasDurRecip() const return (m_durRecip != ""); } -//---------------------------------------------------------------------------- -// AttMdivGes -//---------------------------------------------------------------------------- - -AttMdivGes::AttMdivGes() : Att() -{ - ResetMdivGes(); -} - -void AttMdivGes::ResetMdivGes() -{ - m_attacca = BOOLEAN_NONE; -} - -bool AttMdivGes::ReadMdivGes(pugi::xml_node element, bool removeAttr) -{ - bool hasAttribute = false; - if (element.attribute("attacca")) { - this->SetAttacca(StrToBoolean(element.attribute("attacca").value())); - if (removeAttr) element.remove_attribute("attacca"); - hasAttribute = true; - } - return hasAttribute; -} - -bool AttMdivGes::WriteMdivGes(pugi::xml_node element) -{ - bool wroteAttribute = false; - if (this->HasAttacca()) { - element.append_attribute("attacca") = BooleanToStr(this->GetAttacca()).c_str(); - wroteAttribute = true; - } - return wroteAttribute; -} - -bool AttMdivGes::HasAttacca() const -{ - return (m_attacca != BOOLEAN_NONE); -} - -//---------------------------------------------------------------------------- -// AttNcGes -//---------------------------------------------------------------------------- - -AttNcGes::AttNcGes() : Att() -{ - ResetNcGes(); -} - -void AttNcGes::ResetNcGes() -{ - m_octGes = -127; - m_pnameGes = PITCHNAME_NONE; - m_pnum = MEI_UNSET; -} - -bool AttNcGes::ReadNcGes(pugi::xml_node element, bool removeAttr) -{ - bool hasAttribute = false; - if (element.attribute("oct.ges")) { - this->SetOctGes(StrToOctave(element.attribute("oct.ges").value())); - if (removeAttr) element.remove_attribute("oct.ges"); - hasAttribute = true; - } - if (element.attribute("pname.ges")) { - this->SetPnameGes(StrToPitchname(element.attribute("pname.ges").value())); - if (removeAttr) element.remove_attribute("pname.ges"); - hasAttribute = true; - } - if (element.attribute("pnum")) { - this->SetPnum(StrToInt(element.attribute("pnum").value())); - if (removeAttr) element.remove_attribute("pnum"); - hasAttribute = true; - } - return hasAttribute; -} - -bool AttNcGes::WriteNcGes(pugi::xml_node element) -{ - bool wroteAttribute = false; - if (this->HasOctGes()) { - element.append_attribute("oct.ges") = OctaveToStr(this->GetOctGes()).c_str(); - wroteAttribute = true; - } - if (this->HasPnameGes()) { - element.append_attribute("pname.ges") = PitchnameToStr(this->GetPnameGes()).c_str(); - wroteAttribute = true; - } - if (this->HasPnum()) { - element.append_attribute("pnum") = IntToStr(this->GetPnum()).c_str(); - wroteAttribute = true; - } - return wroteAttribute; -} - -bool AttNcGes::HasOctGes() const -{ - return (m_octGes != -127); -} - -bool AttNcGes::HasPnameGes() const -{ - return (m_pnameGes != PITCHNAME_NONE); -} - -bool AttNcGes::HasPnum() const -{ - return (m_pnum != MEI_UNSET); -} - //---------------------------------------------------------------------------- // AttNoteGes //---------------------------------------------------------------------------- @@ -379,9 +309,6 @@ AttNoteGes::AttNoteGes() : Att() void AttNoteGes::ResetNoteGes() { m_extremis = noteGes_EXTREMIS_NONE; - m_octGes = -127; - m_pnameGes = PITCHNAME_NONE; - m_pnum = MEI_UNSET; } bool AttNoteGes::ReadNoteGes(pugi::xml_node element, bool removeAttr) @@ -392,21 +319,6 @@ bool AttNoteGes::ReadNoteGes(pugi::xml_node element, bool removeAttr) if (removeAttr) element.remove_attribute("extremis"); hasAttribute = true; } - if (element.attribute("oct.ges")) { - this->SetOctGes(StrToOctave(element.attribute("oct.ges").value())); - if (removeAttr) element.remove_attribute("oct.ges"); - hasAttribute = true; - } - if (element.attribute("pname.ges")) { - this->SetPnameGes(StrToPitchname(element.attribute("pname.ges").value())); - if (removeAttr) element.remove_attribute("pname.ges"); - hasAttribute = true; - } - if (element.attribute("pnum")) { - this->SetPnum(StrToInt(element.attribute("pnum").value())); - if (removeAttr) element.remove_attribute("pnum"); - hasAttribute = true; - } return hasAttribute; } @@ -417,18 +329,6 @@ bool AttNoteGes::WriteNoteGes(pugi::xml_node element) element.append_attribute("extremis") = NoteGesExtremisToStr(this->GetExtremis()).c_str(); wroteAttribute = true; } - if (this->HasOctGes()) { - element.append_attribute("oct.ges") = OctaveToStr(this->GetOctGes()).c_str(); - wroteAttribute = true; - } - if (this->HasPnameGes()) { - element.append_attribute("pname.ges") = PitchnameToStr(this->GetPnameGes()).c_str(); - wroteAttribute = true; - } - if (this->HasPnum()) { - element.append_attribute("pnum") = IntToStr(this->GetPnum()).c_str(); - wroteAttribute = true; - } return wroteAttribute; } @@ -437,21 +337,6 @@ bool AttNoteGes::HasExtremis() const return (m_extremis != noteGes_EXTREMIS_NONE); } -bool AttNoteGes::HasOctGes() const -{ - return (m_octGes != -127); -} - -bool AttNoteGes::HasPnameGes() const -{ - return (m_pnameGes != PITCHNAME_NONE); -} - -bool AttNoteGes::HasPnum() const -{ - return (m_pnum != MEI_UNSET); -} - //---------------------------------------------------------------------------- // AttOrnamentAccidGes //---------------------------------------------------------------------------- @@ -508,43 +393,73 @@ bool AttOrnamentAccidGes::HasAccidlowerGes() const } //---------------------------------------------------------------------------- -// AttSectionGes +// AttPitchGes //---------------------------------------------------------------------------- -AttSectionGes::AttSectionGes() : Att() +AttPitchGes::AttPitchGes() : Att() { - ResetSectionGes(); + ResetPitchGes(); } -void AttSectionGes::ResetSectionGes() +void AttPitchGes::ResetPitchGes() { - m_attacca = BOOLEAN_NONE; + m_octGes = MEI_UNSET_OCT; + m_pnameGes = PITCHNAME_NONE; + m_pnum = MEI_UNSET; } -bool AttSectionGes::ReadSectionGes(pugi::xml_node element, bool removeAttr) +bool AttPitchGes::ReadPitchGes(pugi::xml_node element, bool removeAttr) { bool hasAttribute = false; - if (element.attribute("attacca")) { - this->SetAttacca(StrToBoolean(element.attribute("attacca").value())); - if (removeAttr) element.remove_attribute("attacca"); + if (element.attribute("oct.ges")) { + this->SetOctGes(StrToOctave(element.attribute("oct.ges").value())); + if (removeAttr) element.remove_attribute("oct.ges"); + hasAttribute = true; + } + if (element.attribute("pname.ges")) { + this->SetPnameGes(StrToPitchname(element.attribute("pname.ges").value())); + if (removeAttr) element.remove_attribute("pname.ges"); + hasAttribute = true; + } + if (element.attribute("pnum")) { + this->SetPnum(StrToInt(element.attribute("pnum").value())); + if (removeAttr) element.remove_attribute("pnum"); hasAttribute = true; } return hasAttribute; } -bool AttSectionGes::WriteSectionGes(pugi::xml_node element) +bool AttPitchGes::WritePitchGes(pugi::xml_node element) { bool wroteAttribute = false; - if (this->HasAttacca()) { - element.append_attribute("attacca") = BooleanToStr(this->GetAttacca()).c_str(); + if (this->HasOctGes()) { + element.append_attribute("oct.ges") = OctaveToStr(this->GetOctGes()).c_str(); + wroteAttribute = true; + } + if (this->HasPnameGes()) { + element.append_attribute("pname.ges") = PitchnameToStr(this->GetPnameGes()).c_str(); + wroteAttribute = true; + } + if (this->HasPnum()) { + element.append_attribute("pnum") = IntToStr(this->GetPnum()).c_str(); wroteAttribute = true; } return wroteAttribute; } -bool AttSectionGes::HasAttacca() const +bool AttPitchGes::HasOctGes() const { - return (m_attacca != BOOLEAN_NONE); + return (m_octGes != MEI_UNSET_OCT); +} + +bool AttPitchGes::HasPnameGes() const +{ + return (m_pnameGes != PITCHNAME_NONE); +} + +bool AttPitchGes::HasPnum() const +{ + return (m_pnum != MEI_UNSET); } //---------------------------------------------------------------------------- diff --git a/libmei/dist/atts_gestural.h b/libmei/dist/atts_gestural.h index e49d7a8052d..9400a9d9bf1 100644 --- a/libmei/dist/atts_gestural.h +++ b/libmei/dist/atts_gestural.h @@ -123,6 +123,58 @@ class InstArticulationGes : public AttArticulationGes { virtual ~InstArticulationGes() = default; }; +//---------------------------------------------------------------------------- +// AttAttacking +//---------------------------------------------------------------------------- + +class AttAttacking : public Att { +protected: + AttAttacking(); + ~AttAttacking() = default; + +public: + /** Reset the default values for the attribute class **/ + void ResetAttacking(); + + /** Read the values for the attribute class **/ + bool ReadAttacking(pugi::xml_node element, bool removeAttr = true); + + /** Write the values for the attribute class **/ + bool WriteAttacking(pugi::xml_node element); + + /** + * @name Setters, getters and presence checker for class members. + * The checker returns true if the attribute class is set (e.g., not equal + * to the default value) + **/ + ///@{ + void SetAttacca(data_BOOLEAN attacca_) { m_attacca = attacca_; } + data_BOOLEAN GetAttacca() const { return m_attacca; } + bool HasAttacca() const; + ///@} + +private: + /** + * Indicates that the performance of the next musical division should begin + * immediately following this one. + **/ + data_BOOLEAN m_attacca; +}; + +//---------------------------------------------------------------------------- +// InstAttacking +//---------------------------------------------------------------------------- + +/** + * Instantiable version of AttAttacking + */ + +class InstAttacking : public AttAttacking { +public: + InstAttacking() = default; + virtual ~InstAttacking() = default; +}; + //---------------------------------------------------------------------------- // AttBendGes //---------------------------------------------------------------------------- @@ -261,119 +313,6 @@ class InstDurationGes : public AttDurationGes { virtual ~InstDurationGes() = default; }; -//---------------------------------------------------------------------------- -// AttMdivGes -//---------------------------------------------------------------------------- - -class AttMdivGes : public Att { -protected: - AttMdivGes(); - ~AttMdivGes() = default; - -public: - /** Reset the default values for the attribute class **/ - void ResetMdivGes(); - - /** Read the values for the attribute class **/ - bool ReadMdivGes(pugi::xml_node element, bool removeAttr = true); - - /** Write the values for the attribute class **/ - bool WriteMdivGes(pugi::xml_node element); - - /** - * @name Setters, getters and presence checker for class members. - * The checker returns true if the attribute class is set (e.g., not equal - * to the default value) - **/ - ///@{ - void SetAttacca(data_BOOLEAN attacca_) { m_attacca = attacca_; } - data_BOOLEAN GetAttacca() const { return m_attacca; } - bool HasAttacca() const; - ///@} - -private: - /** - * Indicates that the performance of the next musical division should begin - * immediately following this one. - **/ - data_BOOLEAN m_attacca; -}; - -//---------------------------------------------------------------------------- -// InstMdivGes -//---------------------------------------------------------------------------- - -/** - * Instantiable version of AttMdivGes - */ - -class InstMdivGes : public AttMdivGes { -public: - InstMdivGes() = default; - virtual ~InstMdivGes() = default; -}; - -//---------------------------------------------------------------------------- -// AttNcGes -//---------------------------------------------------------------------------- - -class AttNcGes : public Att { -protected: - AttNcGes(); - ~AttNcGes() = default; - -public: - /** Reset the default values for the attribute class **/ - void ResetNcGes(); - - /** Read the values for the attribute class **/ - bool ReadNcGes(pugi::xml_node element, bool removeAttr = true); - - /** Write the values for the attribute class **/ - bool WriteNcGes(pugi::xml_node element); - - /** - * @name Setters, getters and presence checker for class members. - * The checker returns true if the attribute class is set (e.g., not equal - * to the default value) - **/ - ///@{ - void SetOctGes(data_OCTAVE octGes_) { m_octGes = octGes_; } - data_OCTAVE GetOctGes() const { return m_octGes; } - bool HasOctGes() const; - // - void SetPnameGes(data_PITCHNAME pnameGes_) { m_pnameGes = pnameGes_; } - data_PITCHNAME GetPnameGes() const { return m_pnameGes; } - bool HasPnameGes() const; - // - void SetPnum(int pnum_) { m_pnum = pnum_; } - int GetPnum() const { return m_pnum; } - bool HasPnum() const; - ///@} - -private: - /** Records performed octave information that differs from the written value. **/ - data_OCTAVE m_octGes; - /** Contains a performed pitch name that differs from the written value. **/ - data_PITCHNAME m_pnameGes; - /** Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. **/ - int m_pnum; -}; - -//---------------------------------------------------------------------------- -// InstNcGes -//---------------------------------------------------------------------------- - -/** - * Instantiable version of AttNcGes - */ - -class InstNcGes : public AttNcGes { -public: - InstNcGes() = default; - virtual ~InstNcGes() = default; -}; - //---------------------------------------------------------------------------- // AttNoteGes //---------------------------------------------------------------------------- @@ -402,29 +341,11 @@ class AttNoteGes : public Att { void SetExtremis(noteGes_EXTREMIS extremis_) { m_extremis = extremis_; } noteGes_EXTREMIS GetExtremis() const { return m_extremis; } bool HasExtremis() const; - // - void SetOctGes(data_OCTAVE octGes_) { m_octGes = octGes_; } - data_OCTAVE GetOctGes() const { return m_octGes; } - bool HasOctGes() const; - // - void SetPnameGes(data_PITCHNAME pnameGes_) { m_pnameGes = pnameGes_; } - data_PITCHNAME GetPnameGes() const { return m_pnameGes; } - bool HasPnameGes() const; - // - void SetPnum(int pnum_) { m_pnum = pnum_; } - int GetPnum() const { return m_pnum; } - bool HasPnum() const; ///@} private: /** Indicates an extreme, indefinite performed pitch. **/ noteGes_EXTREMIS m_extremis; - /** Records performed octave information that differs from the written value. **/ - data_OCTAVE m_octGes; - /** Contains a performed pitch name that differs from the written value. **/ - data_PITCHNAME m_pnameGes; - /** Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. **/ - int m_pnum; }; //---------------------------------------------------------------------------- @@ -497,23 +418,23 @@ class InstOrnamentAccidGes : public AttOrnamentAccidGes { }; //---------------------------------------------------------------------------- -// AttSectionGes +// AttPitchGes //---------------------------------------------------------------------------- -class AttSectionGes : public Att { +class AttPitchGes : public Att { protected: - AttSectionGes(); - ~AttSectionGes() = default; + AttPitchGes(); + ~AttPitchGes() = default; public: /** Reset the default values for the attribute class **/ - void ResetSectionGes(); + void ResetPitchGes(); /** Read the values for the attribute class **/ - bool ReadSectionGes(pugi::xml_node element, bool removeAttr = true); + bool ReadPitchGes(pugi::xml_node element, bool removeAttr = true); /** Write the values for the attribute class **/ - bool WriteSectionGes(pugi::xml_node element); + bool WritePitchGes(pugi::xml_node element); /** * @name Setters, getters and presence checker for class members. @@ -521,31 +442,40 @@ class AttSectionGes : public Att { * to the default value) **/ ///@{ - void SetAttacca(data_BOOLEAN attacca_) { m_attacca = attacca_; } - data_BOOLEAN GetAttacca() const { return m_attacca; } - bool HasAttacca() const; + void SetOctGes(data_OCTAVE octGes_) { m_octGes = octGes_; } + data_OCTAVE GetOctGes() const { return m_octGes; } + bool HasOctGes() const; + // + void SetPnameGes(data_PITCHNAME pnameGes_) { m_pnameGes = pnameGes_; } + data_PITCHNAME GetPnameGes() const { return m_pnameGes; } + bool HasPnameGes() const; + // + void SetPnum(int pnum_) { m_pnum = pnum_; } + int GetPnum() const { return m_pnum; } + bool HasPnum() const; ///@} private: - /** - * Indicates that the performance of the next musical division should begin - * immediately following this one. - **/ - data_BOOLEAN m_attacca; + /** Records performed octave information that differs from the written value. **/ + data_OCTAVE m_octGes; + /** Contains a performed pitch name that differs from the written value. **/ + data_PITCHNAME m_pnameGes; + /** Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. **/ + int m_pnum; }; //---------------------------------------------------------------------------- -// InstSectionGes +// InstPitchGes //---------------------------------------------------------------------------- /** - * Instantiable version of AttSectionGes + * Instantiable version of AttPitchGes */ -class InstSectionGes : public AttSectionGes { +class InstPitchGes : public AttPitchGes { public: - InstSectionGes() = default; - virtual ~InstSectionGes() = default; + InstPitchGes() = default; + virtual ~InstPitchGes() = default; }; //---------------------------------------------------------------------------- diff --git a/libmei/dist/atts_neumes.cpp b/libmei/dist/atts_neumes.cpp index cbb89b100a1..f9c9eb06fb1 100644 --- a/libmei/dist/atts_neumes.cpp +++ b/libmei/dist/atts_neumes.cpp @@ -33,14 +33,14 @@ AttDivLineLog::AttDivLineLog() : Att() void AttDivLineLog::ResetDivLineLog() { - m_form = ""; + m_form = divLineLog_FORM_NONE; } bool AttDivLineLog::ReadDivLineLog(pugi::xml_node element, bool removeAttr) { bool hasAttribute = false; if (element.attribute("form")) { - this->SetForm(StrToStr(element.attribute("form").value())); + this->SetForm(StrToDivLineLogForm(element.attribute("form").value())); if (removeAttr) element.remove_attribute("form"); hasAttribute = true; } @@ -51,7 +51,7 @@ bool AttDivLineLog::WriteDivLineLog(pugi::xml_node element) { bool wroteAttribute = false; if (this->HasForm()) { - element.append_attribute("form") = StrToStr(this->GetForm()).c_str(); + element.append_attribute("form") = DivLineLogFormToStr(this->GetForm()).c_str(); wroteAttribute = true; } return wroteAttribute; @@ -59,7 +59,7 @@ bool AttDivLineLog::WriteDivLineLog(pugi::xml_node element) bool AttDivLineLog::HasForm() const { - return (m_form != ""); + return (m_form != divLineLog_FORM_NONE); } //---------------------------------------------------------------------------- @@ -130,7 +130,6 @@ void AttNcForm::ResetNcForm() { m_angled = BOOLEAN_NONE; m_con = ncForm_CON_NONE; - m_curve = ncForm_CURVE_NONE; m_hooked = BOOLEAN_NONE; m_ligated = BOOLEAN_NONE; m_rellen = ncForm_RELLEN_NONE; @@ -151,11 +150,6 @@ bool AttNcForm::ReadNcForm(pugi::xml_node element, bool removeAttr) if (removeAttr) element.remove_attribute("con"); hasAttribute = true; } - if (element.attribute("curve")) { - this->SetCurve(StrToNcFormCurve(element.attribute("curve").value())); - if (removeAttr) element.remove_attribute("curve"); - hasAttribute = true; - } if (element.attribute("hooked")) { this->SetHooked(StrToBoolean(element.attribute("hooked").value())); if (removeAttr) element.remove_attribute("hooked"); @@ -195,10 +189,6 @@ bool AttNcForm::WriteNcForm(pugi::xml_node element) element.append_attribute("con") = NcFormConToStr(this->GetCon()).c_str(); wroteAttribute = true; } - if (this->HasCurve()) { - element.append_attribute("curve") = NcFormCurveToStr(this->GetCurve()).c_str(); - wroteAttribute = true; - } if (this->HasHooked()) { element.append_attribute("hooked") = BooleanToStr(this->GetHooked()).c_str(); wroteAttribute = true; @@ -232,11 +222,6 @@ bool AttNcForm::HasCon() const return (m_con != ncForm_CON_NONE); } -bool AttNcForm::HasCurve() const -{ - return (m_curve != ncForm_CURVE_NONE); -} - bool AttNcForm::HasHooked() const { return (m_hooked != BOOLEAN_NONE); @@ -262,4 +247,44 @@ bool AttNcForm::HasTilt() const return (m_tilt != data_COMPASSDIRECTION()); } +//---------------------------------------------------------------------------- +// AttNeumeType +//---------------------------------------------------------------------------- + +AttNeumeType::AttNeumeType() : Att() +{ + ResetNeumeType(); +} + +void AttNeumeType::ResetNeumeType() +{ + m_type = ""; +} + +bool AttNeumeType::ReadNeumeType(pugi::xml_node element, bool removeAttr) +{ + bool hasAttribute = false; + if (element.attribute("type")) { + this->SetType(StrToStr(element.attribute("type").value())); + if (removeAttr) element.remove_attribute("type"); + hasAttribute = true; + } + return hasAttribute; +} + +bool AttNeumeType::WriteNeumeType(pugi::xml_node element) +{ + bool wroteAttribute = false; + if (this->HasType()) { + element.append_attribute("type") = StrToStr(this->GetType()).c_str(); + wroteAttribute = true; + } + return wroteAttribute; +} + +bool AttNeumeType::HasType() const +{ + return (m_type != ""); +} + } // namespace vrv diff --git a/libmei/dist/atts_neumes.h b/libmei/dist/atts_neumes.h index cce5271c4ce..77f76e4d717 100644 --- a/libmei/dist/atts_neumes.h +++ b/libmei/dist/atts_neumes.h @@ -50,14 +50,14 @@ class AttDivLineLog : public Att { * to the default value) **/ ///@{ - void SetForm(std::string form_) { m_form = form_; } - std::string GetForm() const { return m_form; } + void SetForm(divLineLog_FORM form_) { m_form = form_; } + divLineLog_FORM GetForm() const { return m_form; } bool HasForm() const; ///@} private: /** Indicates to what degree the harmonic label is supported by the notation. **/ - std::string m_form; + divLineLog_FORM m_form; }; //---------------------------------------------------------------------------- @@ -162,10 +162,6 @@ class AttNcForm : public Att { ncForm_CON GetCon() const { return m_con; } bool HasCon() const; // - void SetCurve(ncForm_CURVE curve_) { m_curve = curve_; } - ncForm_CURVE GetCurve() const { return m_curve; } - bool HasCurve() const; - // void SetHooked(data_BOOLEAN hooked_) { m_hooked = hooked_; } data_BOOLEAN GetHooked() const { return m_hooked; } bool HasHooked() const; @@ -195,8 +191,6 @@ class AttNcForm : public Att { * should not be used for the first component of a neume. **/ ncForm_CON m_con; - /** Records direction of curvature. **/ - ncForm_CURVE m_curve; /** Pen stroke has an extension; specific to Hispanic notation. **/ data_BOOLEAN m_hooked; /** Indicates participation in a ligature. **/ @@ -226,6 +220,58 @@ class InstNcForm : public AttNcForm { virtual ~InstNcForm() = default; }; +//---------------------------------------------------------------------------- +// AttNeumeType +//---------------------------------------------------------------------------- + +class AttNeumeType : public Att { +protected: + AttNeumeType(); + ~AttNeumeType() = default; + +public: + /** Reset the default values for the attribute class **/ + void ResetNeumeType(); + + /** Read the values for the attribute class **/ + bool ReadNeumeType(pugi::xml_node element, bool removeAttr = true); + + /** Write the values for the attribute class **/ + bool WriteNeumeType(pugi::xml_node element); + + /** + * @name Setters, getters and presence checker for class members. + * The checker returns true if the attribute class is set (e.g., not equal + * to the default value) + **/ + ///@{ + void SetType(std::string type_) { m_type = type_; } + std::string GetType() const { return m_type; } + bool HasType() const; + ///@} + +private: + /** + * Provides a description of the relationship between the current and the target + * categories. + **/ + std::string m_type; +}; + +//---------------------------------------------------------------------------- +// InstNeumeType +//---------------------------------------------------------------------------- + +/** + * Instantiable version of AttNeumeType + */ + +class InstNeumeType : public AttNeumeType { +public: + InstNeumeType() = default; + virtual ~InstNeumeType() = default; +}; + } // namespace vrv #endif // __LIBMEI_ATTS_NEUMES_H__ diff --git a/libmei/dist/atts_shared.cpp b/libmei/dist/atts_shared.cpp index 355de5cc18e..d65dd28bf23 100644 --- a/libmei/dist/atts_shared.cpp +++ b/libmei/dist/atts_shared.cpp @@ -1003,8 +1003,6 @@ AttCoordinated::AttCoordinated() : Att() void AttCoordinated::ResetCoordinated() { - m_ulx = MEI_UNSET; - m_uly = MEI_UNSET; m_lrx = MEI_UNSET; m_lry = MEI_UNSET; m_rotate = 0.0; @@ -1013,16 +1011,6 @@ void AttCoordinated::ResetCoordinated() bool AttCoordinated::ReadCoordinated(pugi::xml_node element, bool removeAttr) { bool hasAttribute = false; - if (element.attribute("ulx")) { - this->SetUlx(StrToInt(element.attribute("ulx").value())); - if (removeAttr) element.remove_attribute("ulx"); - hasAttribute = true; - } - if (element.attribute("uly")) { - this->SetUly(StrToInt(element.attribute("uly").value())); - if (removeAttr) element.remove_attribute("uly"); - hasAttribute = true; - } if (element.attribute("lrx")) { this->SetLrx(StrToInt(element.attribute("lrx").value())); if (removeAttr) element.remove_attribute("lrx"); @@ -1044,14 +1032,6 @@ bool AttCoordinated::ReadCoordinated(pugi::xml_node element, bool removeAttr) bool AttCoordinated::WriteCoordinated(pugi::xml_node element) { bool wroteAttribute = false; - if (this->HasUlx()) { - element.append_attribute("ulx") = IntToStr(this->GetUlx()).c_str(); - wroteAttribute = true; - } - if (this->HasUly()) { - element.append_attribute("uly") = IntToStr(this->GetUly()).c_str(); - wroteAttribute = true; - } if (this->HasLrx()) { element.append_attribute("lrx") = IntToStr(this->GetLrx()).c_str(); wroteAttribute = true; @@ -1067,16 +1047,6 @@ bool AttCoordinated::WriteCoordinated(pugi::xml_node element) return wroteAttribute; } -bool AttCoordinated::HasUlx() const -{ - return (m_ulx != MEI_UNSET); -} - -bool AttCoordinated::HasUly() const -{ - return (m_uly != MEI_UNSET); -} - bool AttCoordinated::HasLrx() const { return (m_lrx != MEI_UNSET); @@ -1092,6 +1062,61 @@ bool AttCoordinated::HasRotate() const return (m_rotate != 0.0); } +//---------------------------------------------------------------------------- +// AttCoordinatedUl +//---------------------------------------------------------------------------- + +AttCoordinatedUl::AttCoordinatedUl() : Att() +{ + ResetCoordinatedUl(); +} + +void AttCoordinatedUl::ResetCoordinatedUl() +{ + m_ulx = MEI_UNSET; + m_uly = MEI_UNSET; +} + +bool AttCoordinatedUl::ReadCoordinatedUl(pugi::xml_node element, bool removeAttr) +{ + bool hasAttribute = false; + if (element.attribute("ulx")) { + this->SetUlx(StrToInt(element.attribute("ulx").value())); + if (removeAttr) element.remove_attribute("ulx"); + hasAttribute = true; + } + if (element.attribute("uly")) { + this->SetUly(StrToInt(element.attribute("uly").value())); + if (removeAttr) element.remove_attribute("uly"); + hasAttribute = true; + } + return hasAttribute; +} + +bool AttCoordinatedUl::WriteCoordinatedUl(pugi::xml_node element) +{ + bool wroteAttribute = false; + if (this->HasUlx()) { + element.append_attribute("ulx") = IntToStr(this->GetUlx()).c_str(); + wroteAttribute = true; + } + if (this->HasUly()) { + element.append_attribute("uly") = IntToStr(this->GetUly()).c_str(); + wroteAttribute = true; + } + return wroteAttribute; +} + +bool AttCoordinatedUl::HasUlx() const +{ + return (m_ulx != MEI_UNSET); +} + +bool AttCoordinatedUl::HasUly() const +{ + return (m_uly != MEI_UNSET); +} + //---------------------------------------------------------------------------- // AttCue //---------------------------------------------------------------------------- @@ -1202,61 +1227,6 @@ bool AttCurvature::HasCurvedir() const return (m_curvedir != curvature_CURVEDIR_NONE); } -//---------------------------------------------------------------------------- -// AttCurveRend -//---------------------------------------------------------------------------- - -AttCurveRend::AttCurveRend() : Att() -{ - ResetCurveRend(); -} - -void AttCurveRend::ResetCurveRend() -{ - m_lform = LINEFORM_NONE; - m_lwidth = data_LINEWIDTH(); -} - -bool AttCurveRend::ReadCurveRend(pugi::xml_node element, bool removeAttr) -{ - bool hasAttribute = false; - if (element.attribute("lform")) { - this->SetLform(StrToLineform(element.attribute("lform").value())); - if (removeAttr) element.remove_attribute("lform"); - hasAttribute = true; - } - if (element.attribute("lwidth")) { - this->SetLwidth(StrToLinewidth(element.attribute("lwidth").value())); - if (removeAttr) element.remove_attribute("lwidth"); - hasAttribute = true; - } - return hasAttribute; -} - -bool AttCurveRend::WriteCurveRend(pugi::xml_node element) -{ - bool wroteAttribute = false; - if (this->HasLform()) { - element.append_attribute("lform") = LineformToStr(this->GetLform()).c_str(); - wroteAttribute = true; - } - if (this->HasLwidth()) { - element.append_attribute("lwidth") = LinewidthToStr(this->GetLwidth()).c_str(); - wroteAttribute = true; - } - return wroteAttribute; -} - -bool AttCurveRend::HasLform() const -{ - return (m_lform != LINEFORM_NONE); -} - -bool AttCurveRend::HasLwidth() const -{ - return (m_lwidth.HasValue()); -} - //---------------------------------------------------------------------------- // AttCustosLog //---------------------------------------------------------------------------- @@ -2357,6 +2327,46 @@ bool AttJoined::HasJoin() const return (m_join != ""); } +//---------------------------------------------------------------------------- +// AttKeyMode +//---------------------------------------------------------------------------- + +AttKeyMode::AttKeyMode() : Att() +{ + ResetKeyMode(); +} + +void AttKeyMode::ResetKeyMode() +{ + m_mode = MODE_NONE; +} + +bool AttKeyMode::ReadKeyMode(pugi::xml_node element, bool removeAttr) +{ + bool hasAttribute = false; + if (element.attribute("mode")) { + this->SetMode(StrToMode(element.attribute("mode").value())); + if (removeAttr) element.remove_attribute("mode"); + hasAttribute = true; + } + return hasAttribute; +} + +bool AttKeyMode::WriteKeyMode(pugi::xml_node element) +{ + bool wroteAttribute = false; + if (this->HasMode()) { + element.append_attribute("mode") = ModeToStr(this->GetMode()).c_str(); + wroteAttribute = true; + } + return wroteAttribute; +} + +bool AttKeyMode::HasMode() const +{ + return (m_mode != MODE_NONE); +} + //---------------------------------------------------------------------------- // AttKeySigLog //---------------------------------------------------------------------------- @@ -2749,8 +2759,8 @@ AttLineRendBase::AttLineRendBase() : Att() void AttLineRendBase::ResetLineRendBase() { m_lform = LINEFORM_NONE; - m_lsegs = MEI_UNSET; m_lwidth = data_LINEWIDTH(); + m_lsegs = MEI_UNSET; } bool AttLineRendBase::ReadLineRendBase(pugi::xml_node element, bool removeAttr) @@ -2761,16 +2771,16 @@ bool AttLineRendBase::ReadLineRendBase(pugi::xml_node element, bool removeAttr) if (removeAttr) element.remove_attribute("lform"); hasAttribute = true; } - if (element.attribute("lsegs")) { - this->SetLsegs(StrToInt(element.attribute("lsegs").value())); - if (removeAttr) element.remove_attribute("lsegs"); - hasAttribute = true; - } if (element.attribute("lwidth")) { this->SetLwidth(StrToLinewidth(element.attribute("lwidth").value())); if (removeAttr) element.remove_attribute("lwidth"); hasAttribute = true; } + if (element.attribute("lsegs")) { + this->SetLsegs(StrToInt(element.attribute("lsegs").value())); + if (removeAttr) element.remove_attribute("lsegs"); + hasAttribute = true; + } return hasAttribute; } @@ -2781,14 +2791,14 @@ bool AttLineRendBase::WriteLineRendBase(pugi::xml_node element) element.append_attribute("lform") = LineformToStr(this->GetLform()).c_str(); wroteAttribute = true; } - if (this->HasLsegs()) { - element.append_attribute("lsegs") = IntToStr(this->GetLsegs()).c_str(); - wroteAttribute = true; - } if (this->HasLwidth()) { element.append_attribute("lwidth") = LinewidthToStr(this->GetLwidth()).c_str(); wroteAttribute = true; } + if (this->HasLsegs()) { + element.append_attribute("lsegs") = IntToStr(this->GetLsegs()).c_str(); + wroteAttribute = true; + } return wroteAttribute; } @@ -2797,14 +2807,14 @@ bool AttLineRendBase::HasLform() const return (m_lform != LINEFORM_NONE); } -bool AttLineRendBase::HasLsegs() const +bool AttLineRendBase::HasLwidth() const { - return (m_lsegs != MEI_UNSET); + return (m_lwidth.HasValue()); } -bool AttLineRendBase::HasLwidth() const +bool AttLineRendBase::HasLsegs() const { - return (m_lwidth.HasValue()); + return (m_lsegs != MEI_UNSET); } //---------------------------------------------------------------------------- @@ -3297,6 +3307,46 @@ bool AttMeiVersion::HasMeiversion() const return (m_meiversion != meiVersion_MEIVERSION_NONE); } +//---------------------------------------------------------------------------- +// AttMensurLog +//---------------------------------------------------------------------------- + +AttMensurLog::AttMensurLog() : Att() +{ + ResetMensurLog(); +} + +void AttMensurLog::ResetMensurLog() +{ + m_level = DURATION_NONE; +} + +bool AttMensurLog::ReadMensurLog(pugi::xml_node element, bool removeAttr) +{ + bool hasAttribute = false; + if (element.attribute("level")) { + this->SetLevel(StrToDuration(element.attribute("level").value())); + if (removeAttr) element.remove_attribute("level"); + hasAttribute = true; + } + return hasAttribute; +} + +bool AttMensurLog::WriteMensurLog(pugi::xml_node element) +{ + bool wroteAttribute = false; + if (this->HasLevel()) { + element.append_attribute("level") = DurationToStr(this->GetLevel()).c_str(); + wroteAttribute = true; + } + return wroteAttribute; +} + +bool AttMensurLog::HasLevel() const +{ + return (m_level != DURATION_NONE); +} + //---------------------------------------------------------------------------- // AttMetadataPointing //---------------------------------------------------------------------------- @@ -4043,7 +4093,7 @@ AttOctave::AttOctave() : Att() void AttOctave::ResetOctave() { - m_oct = -127; + m_oct = MEI_UNSET_OCT; } bool AttOctave::ReadOctave(pugi::xml_node element, bool removeAttr) @@ -4069,7 +4119,7 @@ bool AttOctave::WriteOctave(pugi::xml_node element) bool AttOctave::HasOct() const { - return (m_oct != -127); + return (m_oct != MEI_UNSET_OCT); } //---------------------------------------------------------------------------- @@ -4083,7 +4133,7 @@ AttOctaveDefault::AttOctaveDefault() : Att() void AttOctaveDefault::ResetOctaveDefault() { - m_octDefault = -127; + m_octDefault = MEI_UNSET_OCT; } bool AttOctaveDefault::ReadOctaveDefault(pugi::xml_node element, bool removeAttr) @@ -4109,7 +4159,7 @@ bool AttOctaveDefault::WriteOctaveDefault(pugi::xml_node element) bool AttOctaveDefault::HasOctDefault() const { - return (m_octDefault != -127); + return (m_octDefault != MEI_UNSET_OCT); } //---------------------------------------------------------------------------- @@ -5764,7 +5814,7 @@ AttStaffLocPitched::AttStaffLocPitched() : Att() void AttStaffLocPitched::ResetStaffLocPitched() { m_ploc = PITCHNAME_NONE; - m_oloc = -127; + m_oloc = MEI_UNSET_OCT; } bool AttStaffLocPitched::ReadStaffLocPitched(pugi::xml_node element, bool removeAttr) @@ -5804,7 +5854,7 @@ bool AttStaffLocPitched::HasPloc() const bool AttStaffLocPitched::HasOloc() const { - return (m_oloc != -127); + return (m_oloc != MEI_UNSET_OCT); } //---------------------------------------------------------------------------- diff --git a/libmei/dist/atts_shared.h b/libmei/dist/atts_shared.h index e6d444e1ac4..b86e2877bab 100644 --- a/libmei/dist/atts_shared.h +++ b/libmei/dist/atts_shared.h @@ -1215,14 +1215,6 @@ class AttCoordinated : public Att { * to the default value) **/ ///@{ - void SetUlx(int ulx_) { m_ulx = ulx_; } - int GetUlx() const { return m_ulx; } - bool HasUlx() const; - // - void SetUly(int uly_) { m_uly = uly_; } - int GetUly() const { return m_uly; } - bool HasUly() const; - // void SetLrx(int lrx_) { m_lrx = lrx_; } int GetLrx() const { return m_lrx; } bool HasLrx() const; @@ -1237,10 +1229,6 @@ class AttCoordinated : public Att { ///@} private: - /** Indicates the upper-left corner x coordinate. **/ - int m_ulx; - /** Indicates the upper-left corner y coordinate. **/ - int m_uly; /** Indicates the lower-right corner x coordinate. **/ int m_lrx; /** Indicates the lower-left corner x coordinate. **/ @@ -1268,6 +1256,61 @@ class InstCoordinated : public AttCoordinated { virtual ~InstCoordinated() = default; }; +//---------------------------------------------------------------------------- +// AttCoordinatedUl +//---------------------------------------------------------------------------- + +class AttCoordinatedUl : public Att { +protected: + AttCoordinatedUl(); + ~AttCoordinatedUl() = default; + +public: + /** Reset the default values for the attribute class **/ + void ResetCoordinatedUl(); + + /** Read the values for the attribute class **/ + bool ReadCoordinatedUl(pugi::xml_node element, bool removeAttr = true); + + /** Write the values for the attribute class **/ + bool WriteCoordinatedUl(pugi::xml_node element); + + /** + * @name Setters, getters and presence checker for class members. + * The checker returns true if the attribute class is set (e.g., not equal + * to the default value) + **/ + ///@{ + void SetUlx(int ulx_) { m_ulx = ulx_; } + int GetUlx() const { return m_ulx; } + bool HasUlx() const; + // + void SetUly(int uly_) { m_uly = uly_; } + int GetUly() const { return m_uly; } + bool HasUly() const; + ///@} + +private: + /** Indicates the upper-left corner x coordinate. **/ + int m_ulx; + /** Indicates the upper-left corner y coordinate. **/ + int m_uly; +}; + +//---------------------------------------------------------------------------- +// InstCoordinatedUl +//---------------------------------------------------------------------------- + +/** + * Instantiable version of AttCoordinatedUl + */ + +class InstCoordinatedUl : public AttCoordinatedUl { +public: + InstCoordinatedUl() = default; + virtual ~InstCoordinatedUl() = default; +}; + //---------------------------------------------------------------------------- // AttCue //---------------------------------------------------------------------------- @@ -1390,63 +1433,6 @@ class InstCurvature : public AttCurvature { virtual ~InstCurvature() = default; }; -//---------------------------------------------------------------------------- -// AttCurveRend -//---------------------------------------------------------------------------- - -class AttCurveRend : public Att { -protected: - AttCurveRend(); - ~AttCurveRend() = default; - -public: - /** Reset the default values for the attribute class **/ - void ResetCurveRend(); - - /** Read the values for the attribute class **/ - bool ReadCurveRend(pugi::xml_node element, bool removeAttr = true); - - /** Write the values for the attribute class **/ - bool WriteCurveRend(pugi::xml_node element); - - /** - * @name Setters, getters and presence checker for class members. - * The checker returns true if the attribute class is set (e.g., not equal - * to the default value) - **/ - ///@{ - void SetLform(data_LINEFORM lform_) { m_lform = lform_; } - data_LINEFORM GetLform() const { return m_lform; } - bool HasLform() const; - // - void SetLwidth(data_LINEWIDTH lwidth_) { m_lwidth = lwidth_; } - data_LINEWIDTH GetLwidth() const { return m_lwidth; } - bool HasLwidth() const; - /** Getter for reference (for alternate type only) */ - data_LINEWIDTH *GetLwidthAlternate() { return &m_lwidth; } - ///@} - -private: - /** Describes the line style of a curve. **/ - data_LINEFORM m_lform; - /** Width of a curved line. **/ - data_LINEWIDTH m_lwidth; -}; - -//---------------------------------------------------------------------------- -// InstCurveRend -//---------------------------------------------------------------------------- - -/** - * Instantiable version of AttCurveRend - */ - -class InstCurveRend : public AttCurveRend { -public: - InstCurveRend() = default; - virtual ~InstCurveRend() = default; -}; - //---------------------------------------------------------------------------- // AttCustosLog //---------------------------------------------------------------------------- @@ -2701,6 +2687,55 @@ class InstJoined : public AttJoined { virtual ~InstJoined() = default; }; +//---------------------------------------------------------------------------- +// AttKeyMode +//---------------------------------------------------------------------------- + +class AttKeyMode : public Att { +protected: + AttKeyMode(); + ~AttKeyMode() = default; + +public: + /** Reset the default values for the attribute class **/ + void ResetKeyMode(); + + /** Read the values for the attribute class **/ + bool ReadKeyMode(pugi::xml_node element, bool removeAttr = true); + + /** Write the values for the attribute class **/ + bool WriteKeyMode(pugi::xml_node element); + + /** + * @name Setters, getters and presence checker for class members. + * The checker returns true if the attribute class is set (e.g., not equal + * to the default value) + **/ + ///@{ + void SetMode(data_MODE mode_) { m_mode = mode_; } + data_MODE GetMode() const { return m_mode; } + bool HasMode() const; + ///@} + +private: + /** Indicates major, minor, or other tonality. **/ + data_MODE m_mode; +}; + +//---------------------------------------------------------------------------- +// InstKeyMode +//---------------------------------------------------------------------------- + +/** + * Instantiable version of AttKeyMode + */ + +class InstKeyMode : public AttKeyMode { +public: + InstKeyMode() = default; + virtual ~InstKeyMode() = default; +}; + //---------------------------------------------------------------------------- // AttKeySigLog //---------------------------------------------------------------------------- @@ -3154,20 +3189,22 @@ class AttLineRendBase : public Att { data_LINEFORM GetLform() const { return m_lform; } bool HasLform() const; // - void SetLsegs(int lsegs_) { m_lsegs = lsegs_; } - int GetLsegs() const { return m_lsegs; } - bool HasLsegs() const; - // void SetLwidth(data_LINEWIDTH lwidth_) { m_lwidth = lwidth_; } data_LINEWIDTH GetLwidth() const { return m_lwidth; } bool HasLwidth() const; /** Getter for reference (for alternate type only) */ data_LINEWIDTH *GetLwidthAlternate() { return &m_lwidth; } + // + void SetLsegs(int lsegs_) { m_lsegs = lsegs_; } + int GetLsegs() const { return m_lsegs; } + bool HasLsegs() const; ///@} private: - /** Describes the line style of a curve. **/ + /** Describes the style of a line. **/ data_LINEFORM m_lform; + /** Width of a line. **/ + data_LINEWIDTH m_lwidth; /** * Describes the number of segments into which a dashed or dotted line may be * divided, or the number of "peaks" of a wavy line; a pair of space-separated @@ -3176,8 +3213,6 @@ class AttLineRendBase : public Att { * amount of space; that is, the minimum and maximum values are equal. **/ int m_lsegs; - /** Width of a curved line. **/ - data_LINEWIDTH m_lwidth; }; //---------------------------------------------------------------------------- @@ -3648,6 +3683,55 @@ class InstMeiVersion : public AttMeiVersion { virtual ~InstMeiVersion() = default; }; +//---------------------------------------------------------------------------- +// AttMensurLog +//---------------------------------------------------------------------------- + +class AttMensurLog : public Att { +protected: + AttMensurLog(); + ~AttMensurLog() = default; + +public: + /** Reset the default values for the attribute class **/ + void ResetMensurLog(); + + /** Read the values for the attribute class **/ + bool ReadMensurLog(pugi::xml_node element, bool removeAttr = true); + + /** Write the values for the attribute class **/ + bool WriteMensurLog(pugi::xml_node element); + + /** + * @name Setters, getters and presence checker for class members. + * The checker returns true if the attribute class is set (e.g., not equal + * to the default value) + **/ + ///@{ + void SetLevel(data_DURATION level_) { m_level = level_; } + data_DURATION GetLevel() const { return m_level; } + bool HasLevel() const; + ///@} + +private: + /** Indicates the nesting level of staff grouping symbols. **/ + data_DURATION m_level; +}; + +//---------------------------------------------------------------------------- +// InstMensurLog +//---------------------------------------------------------------------------- + +/** + * Instantiable version of AttMensurLog + */ + +class InstMensurLog : public AttMensurLog { +public: + InstMensurLog() = default; + virtual ~InstMensurLog() = default; +}; + //---------------------------------------------------------------------------- // AttMetadataPointing //---------------------------------------------------------------------------- diff --git a/libmei/dist/atts_visual.cpp b/libmei/dist/atts_visual.cpp index 832314ecc8d..6106237605c 100644 --- a/libmei/dist/atts_visual.cpp +++ b/libmei/dist/atts_visual.cpp @@ -78,8 +78,6 @@ void AttArpegVis::ResetArpegVis() m_arrowSize = MEI_UNSET; m_arrowColor = ""; m_arrowFillcolor = ""; - m_lineForm = LINEFORM_NONE; - m_lineWidth = data_LINEWIDTH(); } bool AttArpegVis::ReadArpegVis(pugi::xml_node element, bool removeAttr) @@ -110,16 +108,6 @@ bool AttArpegVis::ReadArpegVis(pugi::xml_node element, bool removeAttr) if (removeAttr) element.remove_attribute("arrow.fillcolor"); hasAttribute = true; } - if (element.attribute("line.form")) { - this->SetLineForm(StrToLineform(element.attribute("line.form").value())); - if (removeAttr) element.remove_attribute("line.form"); - hasAttribute = true; - } - if (element.attribute("line.width")) { - this->SetLineWidth(StrToLinewidth(element.attribute("line.width").value())); - if (removeAttr) element.remove_attribute("line.width"); - hasAttribute = true; - } return hasAttribute; } @@ -146,14 +134,6 @@ bool AttArpegVis::WriteArpegVis(pugi::xml_node element) element.append_attribute("arrow.fillcolor") = StrToStr(this->GetArrowFillcolor()).c_str(); wroteAttribute = true; } - if (this->HasLineForm()) { - element.append_attribute("line.form") = LineformToStr(this->GetLineForm()).c_str(); - wroteAttribute = true; - } - if (this->HasLineWidth()) { - element.append_attribute("line.width") = LinewidthToStr(this->GetLineWidth()).c_str(); - wroteAttribute = true; - } return wroteAttribute; } @@ -182,16 +162,6 @@ bool AttArpegVis::HasArrowFillcolor() const return (m_arrowFillcolor != ""); } -bool AttArpegVis::HasLineForm() const -{ - return (m_lineForm != LINEFORM_NONE); -} - -bool AttArpegVis::HasLineWidth() const -{ - return (m_lineWidth.HasValue()); -} - //---------------------------------------------------------------------------- // AttBarLineVis //---------------------------------------------------------------------------- @@ -467,6 +437,46 @@ bool AttCleffingVis::HasClefVisible() const return (m_clefVisible != BOOLEAN_NONE); } +//---------------------------------------------------------------------------- +// AttCurvatureDirection +//---------------------------------------------------------------------------- + +AttCurvatureDirection::AttCurvatureDirection() : Att() +{ + ResetCurvatureDirection(); +} + +void AttCurvatureDirection::ResetCurvatureDirection() +{ + m_curve = curvatureDirection_CURVE_NONE; +} + +bool AttCurvatureDirection::ReadCurvatureDirection(pugi::xml_node element, bool removeAttr) +{ + bool hasAttribute = false; + if (element.attribute("curve")) { + this->SetCurve(StrToCurvatureDirectionCurve(element.attribute("curve").value())); + if (removeAttr) element.remove_attribute("curve"); + hasAttribute = true; + } + return hasAttribute; +} + +bool AttCurvatureDirection::WriteCurvatureDirection(pugi::xml_node element) +{ + bool wroteAttribute = false; + if (this->HasCurve()) { + element.append_attribute("curve") = CurvatureDirectionCurveToStr(this->GetCurve()).c_str(); + wroteAttribute = true; + } + return wroteAttribute; +} + +bool AttCurvatureDirection::HasCurve() const +{ + return (m_curve != curvatureDirection_CURVE_NONE); +} + //---------------------------------------------------------------------------- // AttEpisemaVis //---------------------------------------------------------------------------- @@ -687,6 +697,46 @@ bool AttFingGrpVis::HasOrient() const return (m_orient != fingGrpVis_ORIENT_NONE); } +//---------------------------------------------------------------------------- +// AttGuitarGridVis +//---------------------------------------------------------------------------- + +AttGuitarGridVis::AttGuitarGridVis() : Att() +{ + ResetGuitarGridVis(); +} + +void AttGuitarGridVis::ResetGuitarGridVis() +{ + m_gridShow = BOOLEAN_NONE; +} + +bool AttGuitarGridVis::ReadGuitarGridVis(pugi::xml_node element, bool removeAttr) +{ + bool hasAttribute = false; + if (element.attribute("grid.show")) { + this->SetGridShow(StrToBoolean(element.attribute("grid.show").value())); + if (removeAttr) element.remove_attribute("grid.show"); + hasAttribute = true; + } + return hasAttribute; +} + +bool AttGuitarGridVis::WriteGuitarGridVis(pugi::xml_node element) +{ + bool wroteAttribute = false; + if (this->HasGridShow()) { + element.append_attribute("grid.show") = BooleanToStr(this->GetGridShow()).c_str(); + wroteAttribute = true; + } + return wroteAttribute; +} + +bool AttGuitarGridVis::HasGridShow() const +{ + return (m_gridShow != BOOLEAN_NONE); +} + //---------------------------------------------------------------------------- // AttHairpinVis //---------------------------------------------------------------------------- @@ -1128,18 +1178,12 @@ AttLiquescentVis::AttLiquescentVis() : Att() void AttLiquescentVis::ResetLiquescentVis() { - m_curve = liquescentVis_CURVE_NONE; m_looped = BOOLEAN_NONE; } bool AttLiquescentVis::ReadLiquescentVis(pugi::xml_node element, bool removeAttr) { bool hasAttribute = false; - if (element.attribute("curve")) { - this->SetCurve(StrToLiquescentVisCurve(element.attribute("curve").value())); - if (removeAttr) element.remove_attribute("curve"); - hasAttribute = true; - } if (element.attribute("looped")) { this->SetLooped(StrToBoolean(element.attribute("looped").value())); if (removeAttr) element.remove_attribute("looped"); @@ -1151,10 +1195,6 @@ bool AttLiquescentVis::ReadLiquescentVis(pugi::xml_node element, bool removeAttr bool AttLiquescentVis::WriteLiquescentVis(pugi::xml_node element) { bool wroteAttribute = false; - if (this->HasCurve()) { - element.append_attribute("curve") = LiquescentVisCurveToStr(this->GetCurve()).c_str(); - wroteAttribute = true; - } if (this->HasLooped()) { element.append_attribute("looped") = BooleanToStr(this->GetLooped()).c_str(); wroteAttribute = true; @@ -1162,11 +1202,6 @@ bool AttLiquescentVis::WriteLiquescentVis(pugi::xml_node element) return wroteAttribute; } -bool AttLiquescentVis::HasCurve() const -{ - return (m_curve != liquescentVis_CURVE_NONE); -} - bool AttLiquescentVis::HasLooped() const { return (m_looped != BOOLEAN_NONE); @@ -1275,7 +1310,7 @@ void AttMensuralVis::ResetMensuralVis() m_mensurOrient = ORIENTATION_NONE; m_mensurSign = MENSURATIONSIGN_NONE; m_mensurSize = data_FONTSIZE(); - m_mensurSlash = MEI_UNSET; + m_mensurSlash = 0; } bool AttMensuralVis::ReadMensuralVis(pugi::xml_node element, bool removeAttr) @@ -1399,7 +1434,7 @@ bool AttMensuralVis::HasMensurSize() const bool AttMensuralVis::HasMensurSlash() const { - return (m_mensurSlash != MEI_UNSET); + return (m_mensurSlash != 0); } //---------------------------------------------------------------------------- @@ -1938,7 +1973,6 @@ AttStaffDefVis::AttStaffDefVis() : Att() void AttStaffDefVis::ResetStaffDefVis() { - m_gridShow = BOOLEAN_NONE; m_layerscheme = LAYERSCHEME_NONE; m_linesColor = ""; m_linesVisible = BOOLEAN_NONE; @@ -1948,11 +1982,6 @@ void AttStaffDefVis::ResetStaffDefVis() bool AttStaffDefVis::ReadStaffDefVis(pugi::xml_node element, bool removeAttr) { bool hasAttribute = false; - if (element.attribute("grid.show")) { - this->SetGridShow(StrToBoolean(element.attribute("grid.show").value())); - if (removeAttr) element.remove_attribute("grid.show"); - hasAttribute = true; - } if (element.attribute("layerscheme")) { this->SetLayerscheme(StrToLayerscheme(element.attribute("layerscheme").value())); if (removeAttr) element.remove_attribute("layerscheme"); @@ -1979,10 +2008,6 @@ bool AttStaffDefVis::ReadStaffDefVis(pugi::xml_node element, bool removeAttr) bool AttStaffDefVis::WriteStaffDefVis(pugi::xml_node element) { bool wroteAttribute = false; - if (this->HasGridShow()) { - element.append_attribute("grid.show") = BooleanToStr(this->GetGridShow()).c_str(); - wroteAttribute = true; - } if (this->HasLayerscheme()) { element.append_attribute("layerscheme") = LayerschemeToStr(this->GetLayerscheme()).c_str(); wroteAttribute = true; @@ -2002,11 +2027,6 @@ bool AttStaffDefVis::WriteStaffDefVis(pugi::xml_node element) return wroteAttribute; } -bool AttStaffDefVis::HasGridShow() const -{ - return (m_gridShow != BOOLEAN_NONE); -} - bool AttStaffDefVis::HasLayerscheme() const { return (m_layerscheme != LAYERSCHEME_NONE); diff --git a/libmei/dist/atts_visual.h b/libmei/dist/atts_visual.h index 0e8ad069431..29586bee1fe 100644 --- a/libmei/dist/atts_visual.h +++ b/libmei/dist/atts_visual.h @@ -120,16 +120,6 @@ class AttArpegVis : public Att { void SetArrowFillcolor(std::string arrowFillcolor_) { m_arrowFillcolor = arrowFillcolor_; } std::string GetArrowFillcolor() const { return m_arrowFillcolor; } bool HasArrowFillcolor() const; - // - void SetLineForm(data_LINEFORM lineForm_) { m_lineForm = lineForm_; } - data_LINEFORM GetLineForm() const { return m_lineForm; } - bool HasLineForm() const; - // - void SetLineWidth(data_LINEWIDTH lineWidth_) { m_lineWidth = lineWidth_; } - data_LINEWIDTH GetLineWidth() const { return m_lineWidth; } - bool HasLineWidth() const; - /** Getter for reference (for alternate type only) */ - data_LINEWIDTH *GetLineWidthAlternate() { return &m_lineWidth; } ///@} private: @@ -143,10 +133,6 @@ class AttArpegVis : public Att { std::string m_arrowColor; /** Captures the fill color of the arrow if different from the line color. **/ std::string m_arrowFillcolor; - /** Visual form of the line. **/ - data_LINEFORM m_lineForm; - /** Width of the line. **/ - data_LINEWIDTH m_lineWidth; }; //---------------------------------------------------------------------------- @@ -447,6 +433,55 @@ class InstCleffingVis : public AttCleffingVis { virtual ~InstCleffingVis() = default; }; +//---------------------------------------------------------------------------- +// AttCurvatureDirection +//---------------------------------------------------------------------------- + +class AttCurvatureDirection : public Att { +protected: + AttCurvatureDirection(); + ~AttCurvatureDirection() = default; + +public: + /** Reset the default values for the attribute class **/ + void ResetCurvatureDirection(); + + /** Read the values for the attribute class **/ + bool ReadCurvatureDirection(pugi::xml_node element, bool removeAttr = true); + + /** Write the values for the attribute class **/ + bool WriteCurvatureDirection(pugi::xml_node element); + + /** + * @name Setters, getters and presence checker for class members. + * The checker returns true if the attribute class is set (e.g., not equal + * to the default value) + **/ + ///@{ + void SetCurve(curvatureDirection_CURVE curve_) { m_curve = curve_; } + curvatureDirection_CURVE GetCurve() const { return m_curve; } + bool HasCurve() const; + ///@} + +private: + /** Records direction of curvature. **/ + curvatureDirection_CURVE m_curve; +}; + +//---------------------------------------------------------------------------- +// InstCurvatureDirection +//---------------------------------------------------------------------------- + +/** + * Instantiable version of AttCurvatureDirection + */ + +class InstCurvatureDirection : public AttCurvatureDirection { +public: + InstCurvatureDirection() = default; + virtual ~InstCurvatureDirection() = default; +}; + //---------------------------------------------------------------------------- // AttEpisemaVis //---------------------------------------------------------------------------- @@ -667,6 +702,55 @@ class InstFingGrpVis : public AttFingGrpVis { virtual ~InstFingGrpVis() = default; }; +//---------------------------------------------------------------------------- +// AttGuitarGridVis +//---------------------------------------------------------------------------- + +class AttGuitarGridVis : public Att { +protected: + AttGuitarGridVis(); + ~AttGuitarGridVis() = default; + +public: + /** Reset the default values for the attribute class **/ + void ResetGuitarGridVis(); + + /** Read the values for the attribute class **/ + bool ReadGuitarGridVis(pugi::xml_node element, bool removeAttr = true); + + /** Write the values for the attribute class **/ + bool WriteGuitarGridVis(pugi::xml_node element); + + /** + * @name Setters, getters and presence checker for class members. + * The checker returns true if the attribute class is set (e.g., not equal + * to the default value) + **/ + ///@{ + void SetGridShow(data_BOOLEAN gridShow_) { m_gridShow = gridShow_; } + data_BOOLEAN GetGridShow() const { return m_gridShow; } + bool HasGridShow() const; + ///@} + +private: + /** Determines whether to display guitar chord grids. **/ + data_BOOLEAN m_gridShow; +}; + +//---------------------------------------------------------------------------- +// InstGuitarGridVis +//---------------------------------------------------------------------------- + +/** + * Instantiable version of AttGuitarGridVis + */ + +class InstGuitarGridVis : public AttGuitarGridVis { +public: + InstGuitarGridVis() = default; + virtual ~InstGuitarGridVis() = default; +}; + //---------------------------------------------------------------------------- // AttHairpinVis //---------------------------------------------------------------------------- @@ -1111,18 +1195,12 @@ class AttLiquescentVis : public Att { * to the default value) **/ ///@{ - void SetCurve(liquescentVis_CURVE curve_) { m_curve = curve_; } - liquescentVis_CURVE GetCurve() const { return m_curve; } - bool HasCurve() const; - // void SetLooped(data_BOOLEAN looped_) { m_looped = looped_; } data_BOOLEAN GetLooped() const { return m_looped; } bool HasLooped() const; ///@} private: - /** Records direction of curvature. **/ - liquescentVis_CURVE m_curve; /** Indicates whether curve is closed. **/ data_BOOLEAN m_looped; }; @@ -1263,8 +1341,8 @@ class AttMensuralVis : public Att { /** Getter for reference (for alternate type only) */ data_FONTSIZE *GetMensurSizeAlternate() { return &m_mensurSize; } // - void SetMensurSlash(int mensurSlash_) { m_mensurSlash = mensurSlash_; } - int GetMensurSlash() const { return m_mensurSlash; } + void SetMensurSlash(char mensurSlash_) { m_mensurSlash = mensurSlash_; } + char GetMensurSlash() const { return m_mensurSlash; } bool HasMensurSlash() const; ///@} @@ -1290,7 +1368,7 @@ class AttMensuralVis : public Att { * Indicates the number lines added to the mensuration sign. * For example, one slash is added for what we now call 'alla breve'. **/ - int m_mensurSlash; + char m_mensurSlash; }; //---------------------------------------------------------------------------- @@ -1959,10 +2037,6 @@ class AttStaffDefVis : public Att { * to the default value) **/ ///@{ - void SetGridShow(data_BOOLEAN gridShow_) { m_gridShow = gridShow_; } - data_BOOLEAN GetGridShow() const { return m_gridShow; } - bool HasGridShow() const; - // void SetLayerscheme(data_LAYERSCHEME layerscheme_) { m_layerscheme = layerscheme_; } data_LAYERSCHEME GetLayerscheme() const { return m_layerscheme; } bool HasLayerscheme() const; @@ -1981,8 +2055,6 @@ class AttStaffDefVis : public Att { ///@} private: - /** Determines whether to display guitar chord grids. **/ - data_BOOLEAN m_gridShow; /** Indicates the number of layers and their stem directions. **/ data_LAYERSCHEME m_layerscheme; /** Captures the colors of the staff lines. **/ diff --git a/libmei/dist/atttypes.h b/libmei/dist/atttypes.h index 2c5568c3c29..7d15953404c 100644 --- a/libmei/dist/atttypes.h +++ b/libmei/dist/atttypes.h @@ -37,6 +37,8 @@ enum data_ACCIDENTAL_GESTURAL : int8_t { ACCIDENTAL_GESTURAL_sd, ACCIDENTAL_GESTURAL_fu, ACCIDENTAL_GESTURAL_fd, + ACCIDENTAL_GESTURAL_xu, + ACCIDENTAL_GESTURAL_ffd, ACCIDENTAL_GESTURAL_bms, ACCIDENTAL_GESTURAL_kms, ACCIDENTAL_GESTURAL_bs, @@ -74,6 +76,8 @@ enum data_ACCIDENTAL_GESTURAL_extended : int8_t { ACCIDENTAL_GESTURAL_extended_sd, ACCIDENTAL_GESTURAL_extended_fu, ACCIDENTAL_GESTURAL_extended_fd, + ACCIDENTAL_GESTURAL_extended_xu, + ACCIDENTAL_GESTURAL_extended_ffd, ACCIDENTAL_GESTURAL_extended_MAX }; @@ -100,6 +104,10 @@ enum data_ACCIDENTAL_WRITTEN : int8_t { ACCIDENTAL_WRITTEN_fd, ACCIDENTAL_WRITTEN_nu, ACCIDENTAL_WRITTEN_nd, + ACCIDENTAL_WRITTEN_xu, + ACCIDENTAL_WRITTEN_xd, + ACCIDENTAL_WRITTEN_ffu, + ACCIDENTAL_WRITTEN_ffd, ACCIDENTAL_WRITTEN_1qf, ACCIDENTAL_WRITTEN_3qf, ACCIDENTAL_WRITTEN_1qs, @@ -148,6 +156,10 @@ enum data_ACCIDENTAL_WRITTEN_extended : int8_t { ACCIDENTAL_WRITTEN_extended_fd, ACCIDENTAL_WRITTEN_extended_nu, ACCIDENTAL_WRITTEN_extended_nd, + ACCIDENTAL_WRITTEN_extended_xu, + ACCIDENTAL_WRITTEN_extended_xd, + ACCIDENTAL_WRITTEN_extended_ffu, + ACCIDENTAL_WRITTEN_extended_ffd, ACCIDENTAL_WRITTEN_extended_1qf, ACCIDENTAL_WRITTEN_extended_3qf, ACCIDENTAL_WRITTEN_extended_1qs, @@ -1790,7 +1802,7 @@ enum data_VERTICALALIGNMENT : int8_t { }; /** - * MEI att.accid.log@func + * MEI att.accid.log\@func */ enum accidLog_FUNC : int8_t { accidLog_FUNC_NONE = 0, @@ -1800,7 +1812,7 @@ enum accidLog_FUNC : int8_t { }; /** - * MEI att.anchoredText.log@func + * MEI att.anchoredText.log\@func */ enum anchoredTextLog_FUNC : int8_t { anchoredTextLog_FUNC_NONE = 0, @@ -1809,7 +1821,7 @@ enum anchoredTextLog_FUNC : int8_t { }; /** - * MEI att.arpeg.log@order + * MEI att.arpeg.log\@order */ enum arpegLog_ORDER : int8_t { arpegLog_ORDER_NONE = 0, @@ -1820,7 +1832,7 @@ enum arpegLog_ORDER : int8_t { }; /** - * MEI att.audience@audience + * MEI att.audience\@audience */ enum audience_AUDIENCE : int8_t { audience_AUDIENCE_NONE = 0, @@ -1830,17 +1842,7 @@ enum audience_AUDIENCE : int8_t { }; /** - * MEI att.bTrem.log@form - */ -enum bTremLog_FORM : int8_t { - bTremLog_FORM_NONE = 0, - bTremLog_FORM_meas, - bTremLog_FORM_unmeas, - bTremLog_FORM_MAX -}; - -/** - * MEI att.beamRend@form + * MEI att.beamRend\@form */ enum beamRend_FORM : int8_t { beamRend_FORM_NONE = 0, @@ -1852,7 +1854,7 @@ enum beamRend_FORM : int8_t { }; /** - * MEI att.beaming.vis@beam.rend + * MEI att.beaming.vis\@beam.rend */ enum beamingVis_BEAMREND : int8_t { beamingVis_BEAMREND_NONE = 0, @@ -1863,7 +1865,7 @@ enum beamingVis_BEAMREND : int8_t { }; /** - * MEI att.bracketSpan.log@func + * MEI att.bracketSpan.log\@func */ enum bracketSpanLog_FUNC : int8_t { bracketSpanLog_FUNC_NONE = 0, @@ -1874,7 +1876,7 @@ enum bracketSpanLog_FUNC : int8_t { }; /** - * MEI att.curvature@curvedir + * MEI att.curvature\@curvedir */ enum curvature_CURVEDIR : int8_t { curvature_CURVEDIR_NONE = 0, @@ -1885,7 +1887,17 @@ enum curvature_CURVEDIR : int8_t { }; /** - * MEI att.curve.log@func + * MEI att.curvatureDirection\@curve + */ +enum curvatureDirection_CURVE : int8_t { + curvatureDirection_CURVE_NONE = 0, + curvatureDirection_CURVE_a, + curvatureDirection_CURVE_c, + curvatureDirection_CURVE_MAX +}; + +/** + * MEI att.curve.log\@func */ enum curveLog_FUNC : int8_t { curveLog_FUNC_NONE = 0, @@ -1894,7 +1906,7 @@ enum curveLog_FUNC : int8_t { }; /** - * MEI att.cutout@cutout + * MEI att.cutout\@cutout */ enum cutout_CUTOUT : int8_t { cutout_CUTOUT_NONE = 0, @@ -1903,7 +1915,7 @@ enum cutout_CUTOUT : int8_t { }; /** - * MEI att.divLine.log@form + * MEI att.divLine.log\@form */ enum divLineLog_FORM : int8_t { divLineLog_FORM_NONE = 0, @@ -1917,7 +1929,7 @@ enum divLineLog_FORM : int8_t { }; /** - * MEI att.dot.log@form + * MEI att.dot.log\@form */ enum dotLog_FORM : int8_t { dotLog_FORM_NONE = 0, @@ -1927,7 +1939,7 @@ enum dotLog_FORM : int8_t { }; /** - * MEI att.endings@ending.rend + * MEI att.endings\@ending.rend */ enum endings_ENDINGREND : int8_t { endings_ENDINGREND_NONE = 0, @@ -1938,7 +1950,7 @@ enum endings_ENDINGREND : int8_t { }; /** - * MEI att.episema.vis@form + * MEI att.episema.vis\@form */ enum episemaVis_FORM : int8_t { episemaVis_FORM_NONE = 0, @@ -1948,7 +1960,7 @@ enum episemaVis_FORM : int8_t { }; /** - * MEI att.evidence@evidence + * MEI att.evidence\@evidence */ enum evidence_EVIDENCE : int8_t { evidence_EVIDENCE_NONE = 0, @@ -1959,7 +1971,7 @@ enum evidence_EVIDENCE : int8_t { }; /** - * MEI att.extSym.auth@glyph.auth + * MEI att.extSym.auth\@glyph.auth */ enum extSymAuth_GLYPHAUTH : int8_t { extSymAuth_GLYPHAUTH_NONE = 0, @@ -1968,17 +1980,7 @@ enum extSymAuth_GLYPHAUTH : int8_t { }; /** - * MEI att.fTrem.log@form - */ -enum fTremLog_FORM : int8_t { - fTremLog_FORM_NONE = 0, - fTremLog_FORM_meas, - fTremLog_FORM_unmeas, - fTremLog_FORM_MAX -}; - -/** - * MEI att.fermata.vis@form + * MEI att.fermata.vis\@form */ enum fermataVis_FORM : int8_t { fermataVis_FORM_NONE = 0, @@ -1988,7 +1990,7 @@ enum fermataVis_FORM : int8_t { }; /** - * MEI att.fermata.vis@shape + * MEI att.fermata.vis\@shape */ enum fermataVis_SHAPE : int8_t { fermataVis_SHAPE_NONE = 0, @@ -1999,7 +2001,7 @@ enum fermataVis_SHAPE : int8_t { }; /** - * MEI att.fingGrp.log@form + * MEI att.fingGrp.log\@form */ enum fingGrpLog_FORM : int8_t { fingGrpLog_FORM_NONE = 0, @@ -2010,7 +2012,7 @@ enum fingGrpLog_FORM : int8_t { }; /** - * MEI att.fingGrp.vis@orient + * MEI att.fingGrp.vis\@orient */ enum fingGrpVis_ORIENT : int8_t { fingGrpVis_ORIENT_NONE = 0, @@ -2020,7 +2022,7 @@ enum fingGrpVis_ORIENT : int8_t { }; /** - * MEI att.graceGrp.log@attach + * MEI att.graceGrp.log\@attach */ enum graceGrpLog_ATTACH : int8_t { graceGrpLog_ATTACH_NONE = 0, @@ -2031,7 +2033,7 @@ enum graceGrpLog_ATTACH : int8_t { }; /** - * MEI att.hairpin.log@form + * MEI att.hairpin.log\@form */ enum hairpinLog_FORM : int8_t { hairpinLog_FORM_NONE = 0, @@ -2041,7 +2043,7 @@ enum hairpinLog_FORM : int8_t { }; /** - * MEI att.harm.anl@form + * MEI att.harm.anl\@form */ enum harmAnl_FORM : int8_t { harmAnl_FORM_NONE = 0, @@ -2051,7 +2053,7 @@ enum harmAnl_FORM : int8_t { }; /** - * MEI att.harm.vis@rendgrid + * MEI att.harm.vis\@rendgrid */ enum harmVis_RENDGRID : int8_t { harmVis_RENDGRID_NONE = 0, @@ -2062,7 +2064,7 @@ enum harmVis_RENDGRID : int8_t { }; /** - * MEI att.harpPedal.log@a + * MEI att.harpPedal.log\@a */ enum harpPedalLog_A : int8_t { harpPedalLog_A_NONE = 0, @@ -2073,7 +2075,7 @@ enum harpPedalLog_A : int8_t { }; /** - * MEI att.harpPedal.log@b + * MEI att.harpPedal.log\@b */ enum harpPedalLog_B : int8_t { harpPedalLog_B_NONE = 0, @@ -2084,7 +2086,7 @@ enum harpPedalLog_B : int8_t { }; /** - * MEI att.harpPedal.log@c + * MEI att.harpPedal.log\@c */ enum harpPedalLog_C : int8_t { harpPedalLog_C_NONE = 0, @@ -2095,7 +2097,7 @@ enum harpPedalLog_C : int8_t { }; /** - * MEI att.harpPedal.log@d + * MEI att.harpPedal.log\@d */ enum harpPedalLog_D : int8_t { harpPedalLog_D_NONE = 0, @@ -2106,7 +2108,7 @@ enum harpPedalLog_D : int8_t { }; /** - * MEI att.harpPedal.log@e + * MEI att.harpPedal.log\@e */ enum harpPedalLog_E : int8_t { harpPedalLog_E_NONE = 0, @@ -2117,7 +2119,7 @@ enum harpPedalLog_E : int8_t { }; /** - * MEI att.harpPedal.log@f + * MEI att.harpPedal.log\@f */ enum harpPedalLog_F : int8_t { harpPedalLog_F_NONE = 0, @@ -2128,7 +2130,7 @@ enum harpPedalLog_F : int8_t { }; /** - * MEI att.harpPedal.log@g + * MEI att.harpPedal.log\@g */ enum harpPedalLog_G : int8_t { harpPedalLog_G_NONE = 0, @@ -2139,7 +2141,7 @@ enum harpPedalLog_G : int8_t { }; /** - * MEI att.line.log@func + * MEI att.line.log\@func */ enum lineLog_FUNC : int8_t { lineLog_FUNC_NONE = 0, @@ -2150,17 +2152,7 @@ enum lineLog_FUNC : int8_t { }; /** - * MEI att.liquescent.vis@curve - */ -enum liquescentVis_CURVE : int8_t { - liquescentVis_CURVE_NONE = 0, - liquescentVis_CURVE_a, - liquescentVis_CURVE_c, - liquescentVis_CURVE_MAX -}; - -/** - * MEI att.measurement@unit + * MEI att.measurement\@unit */ enum measurement_UNIT : int8_t { measurement_UNIT_NONE = 0, @@ -2185,7 +2177,7 @@ enum measurement_UNIT : int8_t { }; /** - * MEI att.meiVersion@meiversion + * MEI att.meiVersion\@meiversion */ enum meiVersion_MEIVERSION : int8_t { meiVersion_MEIVERSION_NONE = 0, @@ -2193,13 +2185,16 @@ enum meiVersion_MEIVERSION : int8_t { meiVersion_MEIVERSION_3_0_0, meiVersion_MEIVERSION_4_0_0, meiVersion_MEIVERSION_4_0_1, - meiVersion_MEIVERSION_5_0_0_devplusbasic, - meiVersion_MEIVERSION_5_0_0_dev, + meiVersion_MEIVERSION_5_0, + meiVersion_MEIVERSION_5_0plusbasic, + meiVersion_MEIVERSION_5_0plusCMN, + meiVersion_MEIVERSION_5_0plusMensural, + meiVersion_MEIVERSION_5_0plusNeumes, meiVersion_MEIVERSION_MAX }; /** - * MEI att.mensur.vis@form + * MEI att.mensur.vis\@form */ enum mensurVis_FORM : int8_t { mensurVis_FORM_NONE = 0, @@ -2209,7 +2204,7 @@ enum mensurVis_FORM : int8_t { }; /** - * MEI att.mensural.vis@mensur.form + * MEI att.mensural.vis\@mensur.form */ enum mensuralVis_MENSURFORM : int8_t { mensuralVis_MENSURFORM_NONE = 0, @@ -2219,7 +2214,7 @@ enum mensuralVis_MENSURFORM : int8_t { }; /** - * MEI att.meterConformance@metcon + * MEI att.meterConformance\@metcon */ enum meterConformance_METCON : int8_t { meterConformance_METCON_NONE = 0, @@ -2230,7 +2225,7 @@ enum meterConformance_METCON : int8_t { }; /** - * MEI att.meterSigGrp.log@func + * MEI att.meterSigGrp.log\@func */ enum meterSigGrpLog_FUNC : int8_t { meterSigGrpLog_FUNC_NONE = 0, @@ -2242,7 +2237,7 @@ enum meterSigGrpLog_FUNC : int8_t { }; /** - * MEI att.mordent.log@form + * MEI att.mordent.log\@form */ enum mordentLog_FORM : int8_t { mordentLog_FORM_NONE = 0, @@ -2252,7 +2247,7 @@ enum mordentLog_FORM : int8_t { }; /** - * MEI att.ncForm@con + * MEI att.ncForm\@con */ enum ncForm_CON : int8_t { ncForm_CON_NONE = 0, @@ -2263,17 +2258,7 @@ enum ncForm_CON : int8_t { }; /** - * MEI att.ncForm@curve - */ -enum ncForm_CURVE : int8_t { - ncForm_CURVE_NONE = 0, - ncForm_CURVE_a, - ncForm_CURVE_c, - ncForm_CURVE_MAX -}; - -/** - * MEI att.ncForm@rellen + * MEI att.ncForm\@rellen */ enum ncForm_RELLEN : int8_t { ncForm_RELLEN_NONE = 0, @@ -2283,7 +2268,35 @@ enum ncForm_RELLEN : int8_t { }; /** - * MEI att.note.ges@extremis + * MEI att.neumeType\@type + */ +enum neumeType_TYPE : int8_t { + neumeType_TYPE_NONE = 0, + neumeType_TYPE_apostropha, + neumeType_TYPE_bistropha, + neumeType_TYPE_climacus, + neumeType_TYPE_clivis, + neumeType_TYPE_oriscus, + neumeType_TYPE_pes, + neumeType_TYPE_pessubpunctis, + neumeType_TYPE_porrectus, + neumeType_TYPE_porrectusflexus, + neumeType_TYPE_pressusmaior, + neumeType_TYPE_pressusminor, + neumeType_TYPE_punctum, + neumeType_TYPE_quilisma, + neumeType_TYPE_scandicus, + neumeType_TYPE_strophicus, + neumeType_TYPE_torculus, + neumeType_TYPE_torculusresupinus, + neumeType_TYPE_tristropha, + neumeType_TYPE_virga, + neumeType_TYPE_virgastrata, + neumeType_TYPE_MAX +}; + +/** + * MEI att.note.ges\@extremis */ enum noteGes_EXTREMIS : int8_t { noteGes_EXTREMIS_NONE = 0, @@ -2293,7 +2306,7 @@ enum noteGes_EXTREMIS : int8_t { }; /** - * MEI att.noteHeads@head.auth + * MEI att.noteHeads\@head.auth */ enum noteHeads_HEADAUTH : int8_t { noteHeads_HEADAUTH_NONE = 0, @@ -2302,7 +2315,7 @@ enum noteHeads_HEADAUTH : int8_t { }; /** - * MEI att.octave.log@coll + * MEI att.octave.log\@coll */ enum octaveLog_COLL : int8_t { octaveLog_COLL_NONE = 0, @@ -2311,7 +2324,7 @@ enum octaveLog_COLL : int8_t { }; /** - * MEI att.pb.vis@folium + * MEI att.pb.vis\@folium */ enum pbVis_FOLIUM : int8_t { pbVis_FOLIUM_NONE = 0, @@ -2321,7 +2334,7 @@ enum pbVis_FOLIUM : int8_t { }; /** - * MEI att.pedal.log@dir + * MEI att.pedal.log\@dir */ enum pedalLog_DIR : int8_t { pedalLog_DIR_NONE = 0, @@ -2333,7 +2346,7 @@ enum pedalLog_DIR : int8_t { }; /** - * MEI att.pedal.log@func + * MEI att.pedal.log\@func */ enum pedalLog_FUNC : int8_t { pedalLog_FUNC_NONE = 0, @@ -2345,7 +2358,7 @@ enum pedalLog_FUNC : int8_t { }; /** - * MEI att.pointing@xlink:actuate + * MEI att.pointing\@xlink:actuate */ enum pointing_XLINKACTUATE : int8_t { pointing_XLINKACTUATE_NONE = 0, @@ -2357,7 +2370,7 @@ enum pointing_XLINKACTUATE : int8_t { }; /** - * MEI att.pointing@xlink:show + * MEI att.pointing\@xlink:show */ enum pointing_XLINKSHOW : int8_t { pointing_XLINKSHOW_NONE = 0, @@ -2370,7 +2383,7 @@ enum pointing_XLINKSHOW : int8_t { }; /** - * MEI att.recordType@recordtype + * MEI att.recordType\@recordtype */ enum recordType_RECORDTYPE : int8_t { recordType_RECORDTYPE_NONE = 0, @@ -2392,7 +2405,7 @@ enum recordType_RECORDTYPE : int8_t { }; /** - * MEI att.regularMethod@method + * MEI att.regularMethod\@method */ enum regularMethod_METHOD : int8_t { regularMethod_METHOD_NONE = 0, @@ -2402,7 +2415,7 @@ enum regularMethod_METHOD : int8_t { }; /** - * MEI att.rehearsal@reh.enclose + * MEI att.rehearsal\@reh.enclose */ enum rehearsal_REHENCLOSE : int8_t { rehearsal_REHENCLOSE_NONE = 0, @@ -2413,7 +2426,7 @@ enum rehearsal_REHENCLOSE : int8_t { }; /** - * MEI att.repeatMark.log@func + * MEI att.repeatMark.log\@func */ enum repeatMarkLog_FUNC : int8_t { repeatMarkLog_FUNC_NONE = 0, @@ -2426,7 +2439,7 @@ enum repeatMarkLog_FUNC : int8_t { }; /** - * MEI att.sb.vis@form + * MEI att.sb.vis\@form */ enum sbVis_FORM : int8_t { sbVis_FORM_NONE = 0, @@ -2435,7 +2448,7 @@ enum sbVis_FORM : int8_t { }; /** - * MEI att.staffGroupingSym@symbol + * MEI att.staffGroupingSym\@symbol */ enum staffGroupingSym_SYMBOL : int8_t { staffGroupingSym_SYMBOL_NONE = 0, @@ -2448,7 +2461,7 @@ enum staffGroupingSym_SYMBOL : int8_t { }; /** - * MEI att.syl.log@con + * MEI att.syl.log\@con */ enum sylLog_CON : int8_t { sylLog_CON_NONE = 0, @@ -2464,7 +2477,7 @@ enum sylLog_CON : int8_t { }; /** - * MEI att.syl.log@wordpos + * MEI att.syl.log\@wordpos */ enum sylLog_WORDPOS : int8_t { sylLog_WORDPOS_NONE = 0, @@ -2476,7 +2489,7 @@ enum sylLog_WORDPOS : int8_t { }; /** - * MEI att.targetEval@evaluate + * MEI att.targetEval\@evaluate */ enum targetEval_EVALUATE : int8_t { targetEval_EVALUATE_NONE = 0, @@ -2487,7 +2500,7 @@ enum targetEval_EVALUATE : int8_t { }; /** - * MEI att.tempo.log@func + * MEI att.tempo.log\@func */ enum tempoLog_FUNC : int8_t { tempoLog_FUNC_NONE = 0, @@ -2499,7 +2512,17 @@ enum tempoLog_FUNC : int8_t { }; /** - * MEI att.tuplet.vis@num.format + * MEI att.tremForm\@form + */ +enum tremForm_FORM : int8_t { + tremForm_FORM_NONE = 0, + tremForm_FORM_meas, + tremForm_FORM_unmeas, + tremForm_FORM_MAX +}; + +/** + * MEI att.tuplet.vis\@num.format */ enum tupletVis_NUMFORMAT : int8_t { tupletVis_NUMFORMAT_NONE = 0, @@ -2509,7 +2532,7 @@ enum tupletVis_NUMFORMAT : int8_t { }; /** - * MEI att.turn.log@form + * MEI att.turn.log\@form */ enum turnLog_FORM : int8_t { turnLog_FORM_NONE = 0, @@ -2519,7 +2542,7 @@ enum turnLog_FORM : int8_t { }; /** - * MEI att.voltaGroupingSym@voltasym + * MEI att.voltaGroupingSym\@voltasym */ enum voltaGroupingSym_VOLTASYM : int8_t { voltaGroupingSym_VOLTASYM_NONE = 0, @@ -2532,7 +2555,7 @@ enum voltaGroupingSym_VOLTASYM : int8_t { }; /** - * MEI att.whitespace@xml:space + * MEI att.whitespace\@xml:space */ enum whitespace_XMLSPACE : int8_t { whitespace_XMLSPACE_NONE = 0, diff --git a/libmei/dist/meibasic.h b/libmei/dist/meibasic.h index f057bffa1b3..ef66762c8aa 100644 --- a/libmei/dist/meibasic.h +++ b/libmei/dist/meibasic.h @@ -12,66 +12,66 @@ class MEIBasic { // clang-format off inline static std::map> map = { - {"arpeg", {"label", "type", "order", "layer", "plist", "staff", "tstamp", "startid", "arrow", "arrow.shape", "arrow.size", "arrow.color", "arrow.fillcolor", "line.form", "line.width", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"beam", {"label", "type", "layer", "staff", "cue"}}, - {"beatRpt", {"label", "type", "beatdef", "layer", "staff", "slash", "expand", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "plist"}}, - {"breath", {"label", "type", "layer", "staff", "startid", "tstamp", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "ho", "vo"}}, - {"bTrem", {"label", "type", "form", "layer", "staff", "dots", "dur", "num", "num.place", "num.visible", "unitdur"}}, - {"fermata", {"label", "type", "layer", "plist", "staff", "tstamp", "endid", "startid", "form", "shape", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "ho", "vo"}}, - {"fTrem", {"label", "type", "form", "layer", "staff", "dots", "dur", "unitdur"}}, - {"gliss", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo", "startho", "endho", "startvo", "endvo", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth"}}, - {"graceGrp", {"label", "type", "attach", "layer", "staff", "grace", "grace.time"}}, - {"hairpin", {"label", "type", "form", "niente", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "opening", "closed", "opening.vertical", "angle.optimize", "lform", "lsegs", "lwidth", "place", "ho", "vo", "startho", "endho", "startvo", "endvo", "val", "val2"}}, - {"halfmRpt", {"label", "type", "layer", "staff", "dur", "expand", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"harpPedal", {"label", "type", "c", "d", "e", "f", "g", "a", "b", "layer", "plist", "staff", "tstamp", "endid", "startid", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"lv", {"label", "type", "layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "ho", "vo", "startho", "endho", "startvo", "endvo", "curvedir"}}, + {"arpeg", {"label", "type", "order", "layer", "plist", "staff", "tstamp", "startid", "arrow", "arrow.shape", "arrow.size", "arrow.color", "arrow.fillcolor", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "lform", "lwidth", "lsegs", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"beam", {"label", "type", "layer", "staff", "color", "cue"}}, + {"beatRpt", {"label", "type", "beatdef", "layer", "staff", "slash", "color", "expand", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "plist"}}, + {"breath", {"label", "type", "layer", "staff", "startid", "tstamp", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "ho", "vo"}}, + {"bTrem", {"label", "type", "layer", "staff", "dots", "dur", "num", "form", "num.place", "num.visible", "unitdur"}}, + {"fermata", {"label", "type", "layer", "plist", "staff", "tstamp", "endid", "startid", "form", "shape", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "ho", "vo"}}, + {"fTrem", {"label", "type", "layer", "staff", "dots", "dur", "form", "unitdur"}}, + {"gliss", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo", "startho", "endho", "startvo", "endvo", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs"}}, + {"graceGrp", {"label", "type", "attach", "layer", "staff", "grace", "grace.time", "color"}}, + {"hairpin", {"label", "type", "form", "niente", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "opening", "closed", "opening.vertical", "angle.optimize", "color", "lform", "lwidth", "lsegs", "place", "ho", "vo", "startho", "endho", "startvo", "endvo", "val", "val2"}}, + {"halfmRpt", {"label", "type", "layer", "staff", "dur", "color", "expand", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"harpPedal", {"label", "type", "c", "d", "e", "f", "g", "a", "b", "layer", "plist", "staff", "tstamp", "endid", "startid", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"lv", {"label", "type", "layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "color", "curvedir", "lform", "lwidth", "lsegs", "ho", "vo", "startho", "endho", "startvo", "endvo"}}, {"measure", {"label", "type", "left", "right", "metcon", "n"}}, - {"mNum", {"label", "type", "xml:lang", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"mRest", {"label", "type", "cue", "dur", "layer", "staff", "cutout", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"mRpt", {"label", "type", "layer", "staff", "num", "expand", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "num.place", "num.visible", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}}, - {"multiRest", {"label", "type", "layer", "staff", "num", "block", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "num.place", "num.visible", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "width"}}, - {"multiRpt", {"label", "type", "layer", "staff", "num", "expand", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}}, - {"octave", {"label", "type", "coll", "layer", "plist", "staff", "tstamp", "dur", "dis", "dis.place", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "ho", "vo", "startho", "endho"}}, - {"pedal", {"label", "type", "dir", "func", "layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "form", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"reh", {"label", "type", "xml:lang", "staff", "startid", "tstamp", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"repeatMark", {"label", "type", "xml:lang", "func", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "ho", "vo", "startho", "endho"}}, - {"slur", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "ho", "vo", "startho", "endho", "startvo", "endvo", "curvedir"}}, - {"tie", {"label", "type", "layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "ho", "vo", "startho", "endho", "startvo", "endvo", "curvedir"}}, - {"tuplet", {"label", "type", "dur", "num", "numbase", "layer", "staff", "endid", "startid", "bracket.place", "bracket.visible", "dur.visible", "num.format", "num.place", "num.visible"}}, - {"mordent", {"label", "type", "form", "long", "layer", "plist", "staff", "tstamp", "endid", "startid", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"trill", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "place", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo", "startho", "endho"}}, - {"turn", {"label", "type", "delayed", "form", "layer", "plist", "staff", "tstamp", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "startid", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, - {"fing", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "place", "ho", "vo"}}, + {"mNum", {"label", "type", "xml:lang", "color", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"mRest", {"label", "type", "cue", "dur", "layer", "staff", "color", "cutout", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"mRpt", {"label", "type", "layer", "staff", "num", "color", "expand", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "num.place", "num.visible", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}}, + {"multiRest", {"label", "type", "layer", "staff", "num", "block", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "num.place", "num.visible", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "width"}}, + {"multiRpt", {"label", "type", "layer", "staff", "num", "color", "expand", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}}, + {"octave", {"label", "type", "coll", "layer", "plist", "staff", "tstamp", "dur", "dis", "dis.place", "endid", "startid", "tstamp2", "color", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "ho", "vo", "startho", "endho"}}, + {"pedal", {"label", "type", "dir", "func", "layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "form", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"reh", {"label", "type", "xml:lang", "staff", "startid", "tstamp", "color", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"repeatMark", {"label", "type", "xml:lang", "func", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "ho", "vo", "startho", "endho"}}, + {"slur", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "color", "curvedir", "lform", "lwidth", "lsegs", "ho", "vo", "startho", "endho", "startvo", "endvo"}}, + {"tie", {"label", "type", "layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "color", "curvedir", "lform", "lwidth", "lsegs", "ho", "vo", "startho", "endho", "startvo", "endvo"}}, + {"tuplet", {"label", "type", "dur", "num", "numbase", "layer", "staff", "endid", "startid", "bracket.place", "bracket.visible", "dur.visible", "num.format", "color", "num.place", "num.visible"}}, + {"mordent", {"label", "type", "form", "long", "layer", "plist", "staff", "tstamp", "endid", "startid", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"trill", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "endid", "startid", "tstamp2", "color", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "place", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo", "startho", "endho"}}, + {"turn", {"label", "type", "delayed", "form", "layer", "plist", "staff", "tstamp", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "startid", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"fing", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "place", "ho", "vo"}}, {"fingGrp", {"label", "type", "form", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2"}}, {"chordDef", {"label", "type", "tab.pos", "tab.strings"}}, {"chordMember", {"label", "type", "accid.ges", "pname", "oct", "tab.fing", "tab.fret", "tab.string"}}, {"chordTable", {"label", "type"}}, - {"f", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "place", "ho", "vo"}}, + {"f", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "place", "ho", "vo"}}, {"fb", {"label", "type"}}, - {"harm", {"label", "type", "chordref", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2"}}, + {"harm", {"label", "type", "chordref", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "rendgrid", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "place", "ho", "vo", "startho", "endho"}}, {"availability", {"label", "type", "data"}}, {"fileDesc", {"label", "type", "corresp"}}, {"meiHead", {"label", "xml:lang", "type"}}, {"pubStmt", {"label", "type"}}, {"titleStmt", {"label", "type"}}, - {"refrain", {"label", "type", "xml:lang", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "vo", "voltasym"}}, - {"verse", {"label", "type", "xml:lang", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "vo", "voltasym"}}, - {"volta", {"label", "type", "xml:lang", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "vo"}}, + {"refrain", {"label", "type", "xml:lang", "color", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "vo", "voltasym"}}, + {"verse", {"label", "type", "color", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "vo", "voltasym", "n"}}, + {"volta", {"label", "type", "xml:lang", "color", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "vo"}}, {"instrDef", {"label", "n", "type", "midi.channel", "midi.duty", "midi.port", "midi.track", "midi.instrnum", "midi.instrname", "midi.pan", "midi.patchname", "midi.patchnum", "midi.volume", "azimuth", "elevation"}}, {"persName", {"label", "type", "xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}}, - {"accid", {"label", "type", "func", "accid", "layer", "plist", "staff", "tstamp", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "ho", "vo", "accid.ges"}}, + {"accid", {"label", "type", "func", "accid", "layer", "plist", "staff", "tstamp", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "ho", "vo", "accid.ges"}}, {"arranger", {"label", "type", "xml:lang"}}, - {"artic", {"label", "type", "artic", "layer", "plist", "staff", "tstamp", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "ho", "vo"}}, + {"artic", {"label", "type", "artic", "layer", "plist", "staff", "tstamp", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "place", "ho", "vo"}}, {"body", {"label", "type"}}, - {"caesura", {"label", "type", "layer", "staff", "startid", "tstamp", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "ho", "vo"}}, - {"chord", {"label", "type", "dots", "grace", "grace.time", "cue", "dur", "layer", "staff", "cluster", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "stem.dir", "stem.len", "stem.mod", "ho", "breaksec", "instr", "stem.dir", "stem.len", "stem.mod"}}, - {"clef", {"label", "type", "layer", "staff", "cautionary", "shape", "line", "oct", "dis", "dis.place", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, + {"caesura", {"label", "type", "layer", "staff", "startid", "tstamp", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "ho", "vo"}}, + {"chord", {"label", "type", "dots", "grace", "grace.time", "cue", "dur", "layer", "staff", "cluster", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "stem.dir", "stem.len", "stem.mod", "ho", "breaksec", "instr"}}, + {"clef", {"label", "type", "layer", "staff", "cautionary", "shape", "line", "oct", "dis", "dis.place", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo"}}, {"clefGrp", {"label", "type", "layer", "staff"}}, {"composer", {"label", "type", "xml:lang"}}, {"date", {"label", "type", "calendar", "enddate", "isodate", "notafter", "notbefore", "startdate", "xml:lang"}}, - {"dir", {"label", "type", "xml:lang", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "place", "ho", "vo", "startho", "endho"}}, - {"dynam", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "place", "ho", "vo", "startho", "endho", "xml:lang"}}, - {"ending", {"label", "type", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth"}}, + {"dir", {"label", "type", "xml:lang", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "place", "ho", "vo", "startho", "endho"}}, + {"dynam", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "place", "ho", "vo", "startho", "endho", "xml:lang"}}, + {"ending", {"label", "type", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs"}}, {"label", {"label", "type", "xml:lang"}}, {"labelAbbr", {"label", "type", "xml:lang"}}, {"layer", {"label", "n", "type"}}, @@ -80,15 +80,15 @@ class MEIBasic { {"mdiv", {"label", "type", "attacca", "n"}}, {"mei", {"meiversion"}}, {"music", {"label", "type"}}, - {"note", {"label", "type", "dots", "cue", "dur", "layer", "staff", "grace", "grace.time", "pname", "oct", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "stem.dir", "stem.len", "stem.mod", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "breaksec", "oct.ges", "pname.ges", "instr", "vel", "tab.fing", "tab.fret", "tab.string"}}, - {"ornam", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "endid", "startid", "tstamp2", "place", "ho", "vo", "startho", "endho"}}, + {"note", {"label", "type", "dots", "cue", "dur", "layer", "staff", "grace", "grace.time", "pname", "oct", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "stem.dir", "stem.len", "stem.mod", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "breaksec", "oct.ges", "pname.ges", "instr", "vel", "tab.fing", "tab.fret", "tab.string"}}, + {"ornam", {"label", "type", "layer", "plist", "staff", "tstamp", "dur", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "endid", "startid", "tstamp2", "color", "place", "ho", "vo", "startho", "endho"}}, {"pb", {"label", "type", "folium"}}, - {"pgFoot", {"label", "type", "xml:lang", "halign", "func"}}, - {"pgHead", {"label", "type", "xml:lang", "halign", "func"}}, + {"pgFoot", {"label", "type", "func", "halign", "xml:lang"}}, + {"pgHead", {"label", "type", "func", "halign", "xml:lang"}}, {"pubPlace", {"label", "type", "xml:lang"}}, - {"rend", {"label", "type", "glyph.auth", "glyph.uri", "halign", "xml:lang", "altrend", "rend", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "valign", "xml:space", "rotation"}}, + {"rend", {"color", "label", "type", "glyph.auth", "glyph.uri", "halign", "xml:lang", "altrend", "rend", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "valign", "xml:space", "rotation"}}, {"respStmt", {"label", "type"}}, - {"rest", {"label", "type", "dots", "cue", "dur", "layer", "staff", "breaksec", "ho", "vo", "instr"}}, + {"rest", {"label", "type", "dots", "cue", "dur", "layer", "staff", "color", "breaksec", "ho", "vo", "instr"}}, {"sb", {"label", "type", "form", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}}, {"score", {"label", "type"}}, {"scoreDef", {"label", "type", "keysig", "meter.count", "meter.unit", "meter.sym"}}, @@ -98,8 +98,8 @@ class MEIBasic { {"staffDef", {"label", "n", "type", "lines", "clef.shape", "clef.line", "clef.dis", "clef.dis.place", "keysig", "meter.count", "meter.unit", "meter.sym", "trans.diat", "trans.semi", "instr", "tab.strings", "ppq", "tune.Hz", "tune.pname", "tune.temper"}}, {"staffGrp", {"label", "type", "bar.thru", "symbol", "instr"}}, {"syl", {"label", "type", "xml:lang", "con", "wordpos", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "ho", "vo", "halign"}}, - {"symbol", {"label", "type", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "scale", "ho", "vo"}}, - {"tempo", {"label", "type", "xml:lang", "func", "layer", "plist", "staff", "tstamp", "mm", "mm.unit", "mm.dots", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "place", "ho", "vo", "startho", "endho", "midi.bpm", "midi.mspb"}}, + {"symbol", {"label", "type", "color", "glyph.auth", "glyph.uri", "glyph.name", "glyph.num", "scale", "ho", "vo"}}, + {"tempo", {"label", "type", "xml:lang", "func", "layer", "plist", "staff", "tstamp", "mm", "mm.unit", "mm.dots", "endid", "startid", "tstamp2", "extender", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lwidth", "lsegs", "place", "ho", "vo", "startho", "endho", "midi.bpm", "midi.mspb"}}, {"title", {"label", "xml:lang", "n", "level", "type"}}, {"barre", {"label", "type", "endid", "startid", "fret"}}, }; diff --git a/libmei/mei/develop/mei-all_compiled.odd b/libmei/mei/mei-all_compiled.odd similarity index 93% rename from libmei/mei/develop/mei-all_compiled.odd rename to libmei/mei/mei-all_compiled.odd index 8be4d4eb9c5..9e03cdf81a3 100644 --- a/libmei/mei/develop/mei-all_compiled.odd +++ b/libmei/mei/mei-all_compiled.odd @@ -1,16 +1,18 @@ - + - Music Encoding Initiative Guidelines: <title type="sub">All - Customization + Music Encoding Initiative Guidelines: <title type="sub">All Customization Authored by Perry Roland -

+ Music Encoding Initiative (MEI) Board + + Licensed under the Educational Community License version 2.0 +

@@ -29,7 +31,7 @@ - + Written accidental values. @@ -104,6 +106,18 @@ Natural note lowered by quarter tone (natural modified by arrow). + + Double sharp note raised by quarter tone (double sharp modified by arrow). + + + Double sharp note lowered by quarter tone (double sharp modified by arrow). + + + Double flat note raised by quarter tone (double flat modified by arrow). + + + Double flat note lowered by quarter tone (double flat modified by arrow). + 1/4-tone flat accidental. @@ -214,6 +228,12 @@ Three quarter-tones flat. + + Five quarter-tones sharp. + + + Five quarter-tones flat. + @@ -249,6 +269,12 @@ Spiccato. + + Stress (Unicode 00B4). + + + Unstress (Unicode 02D8). + Main note followed by short slide to higher, indeterminate pitch (Unicode 1D185). @@ -337,7 +363,7 @@ - + "" contains a deprecated value. @@ -382,7 +408,7 @@ Dotted line (SMuFL E037). - Double barline (SMuFL E031 and Unicode 1D101). + Double bar line (SMuFL E031 and Unicode 1D101). Double dashed line. @@ -391,16 +417,16 @@ Double dotted line. - Heavy double barline (SMuFL E035). + Heavy double bar line (SMuFL E035). Segno serpent with vertical lines (SMuFL E04B). - End barline (SMuFL E032 and Unicode 1D102). + End bar line (SMuFL E032 and Unicode 1D102). - Heavy barline (SMuFL E034). + Heavy bar line (SMuFL E034). Bar line not rendered. @@ -418,7 +444,7 @@ Segno serpent. - Single barline (SMuFL E030 and Unicode 1D100). + Single bar line (SMuFL E030 and Unicode 1D100). @@ -487,6 +513,24 @@ + + Indicates where cancellation accidentals are shown in a key signature. + + + + Do not show cancellation accidentals. + + + Show cancellation accidentals before the new key accidentals. + + + Show cancellation accidentals after the new key accidentals ("Old style" or "French") + + + Show cancellation accidentals before the barline (also known as "Russian"). + + + Values for certainty attribute. Certainty may be expressed by one of the predefined symbolic values high, medium, or low. The value unknown should be used in cases where the encoder @@ -522,7 +566,7 @@ G clef (Unicode 1D11E). - Double G clef. + Double G clef. Sounds one octave lower than G clef. (See remarks on usage below.) F clef (Unicode 1D122). @@ -538,6 +582,14 @@ + +

Double-G clefs sound one octave lower, so do not combine with dis/ + dis.place/clef.dis/clef.dis.place. In some cases + the double G clef may be used to indicate that two voices share one staff and + does not sound one octave lower. In this case the oct attribute may be + used to clarify the sounding octave of the instruments for the clef. +

+ Tone-cluster rendition. @@ -1126,7 +1178,7 @@ - + Performed duration attribute values. @@ -1677,12 +1729,12 @@ A count of measures plus a beat location, i.e., [0-9]+m *\+ *[0-9]+(\.?[0-9]*)?. The - measure count is the number of barlines crossed by the event, while the beat location is a + measure count is the number of bar lines crossed by the event, while the beat location is a timestamp expressed as a beat with an optional fractional part. For example, "1m+3.5" indicates a point in the next measure on the second half of beat 3. The measure number must be in the range of 0 to the number of remaining measures, while the beat number must be in the range from 0 to the numerator of the time signature plus 1. For example, in 6/8 the beat - number must be within the range from 0 (the left barline) to 7 (the right barline). A value + number must be within the range from 0 (the left bar line) to 7 (the right bar line). A value with a measure number of "0", such as "0m+2", indicates a point within the current measure. @@ -1692,14 +1744,14 @@ A count of measures plus a beat location, i.e., (\+|-)?[0-9]+m\+[0-9]+(\.?[0-9]*)?. The - measure count is the number of barlines crossed by the event, while the beat location is a + measure count is the number of bar lines crossed by the event, while the beat location is a timestamp expressed as a beat with an optional fractional part. The measure number must be in the range of preceding measures to the number of remaining measures. A value with a positive measure number, such as "1m+3", indicates a point in the following measure, while a value with a negative measure number, such as "-1m+3", marks a point in the preceding measure. The beat number must be in the range from 0 to the numerator of the time signature plus 1. For example, - in 6/8 the beat number must be within the range from 0 (the left barline) to 7 (the right - barline). A value with a measure number of "0", such as "0m+2", indicates a point within the + in 6/8 the beat number must be within the range from 0 (the left bar line) to 7 (the right + bar line). A value with a measure number of "0", such as "0m+2", indicates a point within the current measure. @@ -1910,8 +1962,8 @@ Meter signature rendered using traditional numeric values. - - Meter signature not rendered. + + Meter signature rendered using both the symbol and the traditional numeric values. @@ -2761,7 +2813,7 @@ Enclosing circle. - + Enclosing "fences". @@ -2776,8 +2828,7 @@ - Oct attribute values. The default values conform to Acoustical Society of America - representation. Read, p. 44. + Octave number. The default values conform to the Scientific Pitch Notation (SPN). 9 @@ -2842,26 +2893,50 @@ - Positive decimal number plus '%', i.e., [0-9]+(\.?[0-9]*)?\%. + Positive decimal number plus '%', i.e., [0-9]+(\.[0-9]*)?%. - [0-9]+(\.?[0-9]*)?% + [0-9]+(\.[0-9]*)?% - Positive decimal number between 0 and 100, followed by a percent sign "%". + Decimal number between 0 and 100, followed by a percent sign "%". - (([0-9]|[1-9][0-9])(\.[0-9]+)?|100(\.0+)?)% + (([0-9]|[1-9][0-9])(\.[0-9]*)?|100(\.0*)?)% - Positive decimal number between -100 and 100, followed by a percent sign "%". + Decimal number between -100 and 100, followed by a percent sign "%". - (\+|-)?(([0-9]|[1-9][0-9])(\.[0-9]+)?|100(\.0+)?)% + (\+|-)?(([0-9]|[1-9][0-9])(\.[0-9]*)?|100(\.0*)?)% + + Page header and footer function; a value that defines the function (i.e., the placement) of the header or the footer. + + + + Header or footer for all pages, including the first and the last page, unless a page header or footer for the first or the last page is provided. + + + Header or footer for the first page only. + + + Header or footer for the last page only. + + + The first of an alternating pattern of headers or footers. + + + The second of an alternating pattern of headers or footers. + + + + +

An alternating pattern with "alt1" and "alt2" starts from the first page. However, if header or footer with a func="first" is also defined, it will shift the pattern by one page. A header or footer with func="last" will interupt the pattern.

+
Page scale factor; a percentage of the values in page.height and page.width. @@ -2882,7 +2957,7 @@ [a-g] - + Gestural pitch names need an additional value for when the notated pitch is not to be sounded. @@ -2900,7 +2975,7 @@ - + Other values not permitted when 'above', 'below', 'between' or 'within' is @@ -3027,7 +3102,7 @@ - Staff location. The value '0' indicates the bottom line of the current staff; positive + Staff location. The value 0 indicates the bottom line of the current staff; positive values are used for positions above the bottom line and negative values for the positions below. For example, in treble clef, 1 = F4, 2 = G4, 3 = A4, etc. and -1 = D4, -2 = C4, and so on. @@ -3039,7 +3114,7 @@ - + The @staff @@ -3377,7 +3452,7 @@ - + An element with a notationsubtype attribute must have @@ -3389,8 +3464,15 @@ Analytical domain attributes. + + Analytical domain attributes. + + + Analytical domain attributes. + + Analytical domain attributes. Analytical domain attributes. @@ -3490,10 +3572,13 @@ + + Analytical domain attributes. Attributes describing the harmonic function of a single pitch. + degree Captures scale degree information using Humdrum **deg syntax -- an optional indicator of melodic approach (^ = ascending approach, v = descending approach), a scale degree value (1 = tonic ... 7 = leading tone), and an optional indication of chromatic @@ -3514,6 +3599,7 @@ Attributes that describe harmonic intervals. + interval harmonic Encodes the harmonic interval between pitches occurring at the same time. @@ -3524,6 +3610,7 @@ Attributes that provide for description of intervallic content. + interval melodic Encodes the melodic interval from the previous pitch. The value may be a general directional indication (u, d, s, etc.), an indication of diatonic interval direction, quality, and size, or a precise numeric value in half steps. @@ -3538,16 +3625,9 @@ Analytical domain attributes. + - - - Indicates major, minor, or other tonality. - - - - - Used by staffDef and scoreDef to provide default values for attributes in the analytical domain that are related to key signatures. @@ -3584,6 +3664,8 @@ Analytical domain attributes. Analytical domain attributes. + + Analytical domain attributes. Analytical domain attributes. @@ -3601,12 +3683,16 @@ Analytical domain attributes. + + Analytical domain attributes. Analytical domain attributes. Analytical domain attributes. Analytical domain attributes. + + Analytical domain attributes. Analytical domain attributes. @@ -3634,6 +3720,7 @@ + @@ -3641,6 +3728,9 @@ Analytical domain attributes. Analytical domain attributes. + + + Analytical domain attributes. @@ -3682,12 +3772,15 @@ Attributes that describe pitch class. + pitch class Holds pitch class information. + + Analytical domain attributes that describe the properties of a plica in the mensural repertoire. Analytical domain attributes. @@ -3698,6 +3791,8 @@ Analytical domain attributes. Analytical domain attributes. + + Analytical domain attributes. Analytical domain attributes. @@ -3725,6 +3820,7 @@ Attributes that specify pitch using sol-fa. + pitch sol-fa Contains sol-fa designation, e.g., do, re, mi, etc., in either a fixed or movable Do system. @@ -3750,6 +3846,8 @@ Analytical domain attributes. Analytical domain attributes. + + Analytical domain attributes that describe the properties of a stem in the mensural repertoire. Analytical domain attributes. @@ -4007,7 +4105,7 @@ - + Stem direction must be specified for all notes and chords under the @@ -4052,7 +4150,7 @@ - + Logical domain attributes. @@ -4076,7 +4174,7 @@ - + Logical domain attributes. @@ -4084,10 +4182,11 @@ - + + function Describes the function of the bracketed event sequence. @@ -4113,29 +4212,17 @@ - + Logical domain attributes. - + + - - - Indicates whether the tremolo is measured or unmeasured. - - - Measured tremolo. - - - Unmeasured tremolo. - - - - Analytical domain attributes in the CMN repertoire. @@ -4175,21 +4262,8 @@ - - Analytical domain attributes. - - Gestural domain attributes. Logical domain attributes. - - Visual domain attributes. - - - - - - - Attributes that indicate whether to render a repeat symbol or the source material to which it refers. @@ -4214,25 +4288,14 @@ - + + - - - Describes the style of the tremolo. - - - Measured tremolo. - - - Unmeasured tremolo. - - - - Attributes that indicate whether an event participates in a glissando. + glissando Indicates that this element participates in a glissando. If visual information about the glissando needs to be recorded, then a gliss element should be employed instead. @@ -4247,7 +4310,7 @@ - + Attributes that mark a note or chord as a "grace", how it should "steal" time, and how @@ -4267,10 +4330,6 @@ - - Analytical domain attributes. - - Gestural domain attributes. Logical domain attributes. @@ -4294,18 +4353,13 @@ - - Visual domain attributes. - - - Logical domain attributes. - + @@ -4332,7 +4386,7 @@ Logical domain attributes. - + Logical domain attributes. The pedal setting, i.e., flat, natural, or sharp, for each @@ -4458,7 +4512,7 @@ - + Attributes that indicate the presence of an l.v. (laissez vibrer) marking attached to a @@ -4504,6 +4558,7 @@ Logical domain attributes. + function Function of the meter signature group. @@ -4516,6 +4571,9 @@ Meter signatures with different unit values are used to express a complex metrical pattern that is not expressible using traditional means, such as 2/4+1/8. + + Meter signatures in a relationship not covered by the values alternating, interchanging or mixed. + @@ -4581,6 +4639,7 @@ Attributes that record numbers to be displayed with a feature. + number Records a number or count accompanying a notational feature. @@ -4592,6 +4651,7 @@ tremolo or tuplet. + number placement States where the tuplet number will be placed in relation to the note heads. @@ -4611,7 +4671,7 @@ - + @@ -4633,10 +4693,11 @@ - + + direction Records the position of the piano damper pedal. @@ -4654,6 +4715,7 @@ + function Indicates the function of the depressed pedal, but not necessarily the text associated with its use. Use the dir element for such text. @@ -4687,7 +4749,7 @@ Visual domain attributes. - + Used by scoreDef and staffDef to provide default description of piano pedal @@ -4707,8 +4769,8 @@ - - + + Attributes used by scoreDef and staffDef to provide default information about rehearsal @@ -4752,26 +4814,19 @@ Visual domain attributes. + - - - Determines whether to display guitar chord grids. - - - - - Logical domain attributes. - + Attributes that describe the rendition of slurs. @@ -4794,6 +4849,8 @@ + + Logical domain attributes in the CMN repertoire. Logical domain attributes for staffDef in the CMN repertoire. @@ -4826,7 +4883,7 @@ - + Attributes that describe the rendition of ties. @@ -4842,6 +4899,21 @@ + + Attributes describing the form of a tremolo. + + + Describes the style of the tremolo. + + + Measured tremolo. + + + Unmeasured tremolo. + + + + Attributes that describe measured tremolandi. @@ -4869,7 +4941,7 @@ - + Groups control events that appear in CMN. @@ -4946,7 +5018,7 @@ - + Must have one of the @@ -4972,10 +5044,10 @@ - + - - A beam without a copyof attribute must have at least 2 note, rest, chord, or space + + A beam that contains neither a copyof nor sameas attribute must have at least 2 note, rest, chord, or space descendants. @@ -4996,7 +5068,7 @@ - + Must have one of the @@ -5039,7 +5111,7 @@ - + Must have one of the @@ -5058,7 +5130,7 @@ - + Must have one of the @@ -5085,7 +5157,7 @@ - + Must have one of the @@ -5125,7 +5197,7 @@ - + Must have one of the @@ -5162,7 +5234,7 @@ - + Must have one of the @@ -5181,7 +5253,7 @@ tstamp.real attribute, while the ending point may be recorded by either a dur, dur.ges, endid, or tstamp2 attribute. It is a semantic error not to specify one starting and one ending type of attribute.

- A container for a sequence of grace notes. + grace groupA container for a sequence of grace notes. @@ -5191,14 +5263,14 @@ - + A graceGrp without a copyof attribute must have at least 1 note, rest, chord, or space descendants. - + The grace attribute is not allowed on @@ -5216,7 +5288,7 @@ - + Must have one of the @@ -5255,7 +5327,7 @@ - + Must have one of the @@ -5276,14 +5348,14 @@ - + Must have one of the attributes: startid, tstamp, tstamp.ges or tstamp.real. - + The visual attributes of the lv element (@bezier, @bulge, @curvedir, @@ -5326,7 +5398,7 @@ - meter signature groupUsed to capture alternating, interchanging, and mixed meter signatures. + meter signature groupUsed to capture alternating, interchanging, mixed or other non-standard meter signatures. @@ -5336,7 +5408,7 @@ - + meterSigGrp must have at least 2 child @@ -5444,7 +5516,7 @@ - + Must have one of the @@ -5489,7 +5561,7 @@ - + @@ -5535,7 +5607,7 @@ - + Must have one of the @@ -5562,6 +5634,37 @@

It may also be called a "rehearsal figure", or when numbers are used instead of letters, a "rehearsal number". See Read, p. 443. reh uses a subset of model.textPhraseLike.limited.

+
repetition mark + An instruction expressed as a combination of text and symbols – segno and coda – typically above, + below, or between staves, but not on the staff. + + + + + + + + + + + + + + Must have one of the + attributes: startid, tstamp, tstamp.ges or tstamp.real. + + + + + + When @glyph.name or @glyph.num is present, repeatMark must not have content. + + + +

When only func is provided to describe the function of the repeat mark (i.e., without glyph information and no textual content), then a renderer + can rely on it to display the appropriate symbol. When textual content is provided, it will take precedence over the symbol implied by the function. Generic repeat marks where + no function can be determined, then generic dir elements should be used. +

Indication of 1) a "unified melodic idea" or 2) performance technique. @@ -5572,7 +5675,7 @@ - + Must have one of the @@ -5581,7 +5684,7 @@ dur, dur.ges, endid, or tstamp2. - + The visual attributes of the slur (@bezier, @bulge, @curvedir, @lform, @@ -5616,7 +5719,7 @@ - + Must have one of the @@ -5625,7 +5728,7 @@ dur, dur.ges, endid, or tstamp2. - + The visual attributes of the tie (@bezier, @bulge, @curvedir, @lform, @@ -5672,7 +5775,7 @@ - + Must have one of the @@ -5755,6 +5858,7 @@ Attributes for marking the presence of an ornament. + ornament Indicates that this element has an attached ornament. If visual information about the ornament is needed, then one of the elements that represents an ornament (mordent, trill, or turn) should be employed. @@ -5770,7 +5874,7 @@ - +
Logical domain attributes. @@ -5817,7 +5921,7 @@ - + Must have one of the @@ -5839,7 +5943,7 @@ - + Must have one of the @@ -5866,7 +5970,7 @@ - + Must have one of the @@ -5885,8 +5989,7 @@ -

This element is modelled on the teiCorpus element in the Text Encoding Initiative (TEI) - standard. The MEI instances making up the corpus may be related in a number of ways, for +

The model of this element is based on the teiCorpus element of the Text Encoding Initiative (TEI). The MEI instances making up the corpus may be related in a number of ways, for example, by composer, by similar instrumentation, by holding institution, etc. This element’s name should not be changed in order to assure an absolute minimum level of MEI compliance.

@@ -5922,7 +6025,7 @@ -
(apparatus) – Contains one or more alternative encodings. + apparatusContains one or more alternative encodings. @@ -5937,8 +6040,8 @@ unclear), or the nature of the variation or the principles required to understand it (e.g., lectio difficilior, usus auctoris, etc.).

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

-
(lemma) – Contains the lemma, or base text, of a textual variation. +

The model of this element is based on the app element of the Text Encoding Initiative (TEI).

+
lemmaContains the lemma, or base text, of a textual variation. @@ -5962,8 +6065,8 @@ example, when used as a descendent of verse, lem should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

-
(reading) – Contains a single reading within a textual variation. +

The model of this element is based on the lem element of the Text Encoding Initiative (TEI).

+
readingContains a single reading within a textual variation. @@ -5985,20 +6088,20 @@ example, when used as a descendent of verse, rdg should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the rdg element of the Text Encoding Initiative (TEI).

Logical domain attributes. - + Logical domain attributes. - + Groups elements containing stage directions in performance texts. @@ -6020,14 +6123,14 @@ - + Must have one of the attributes: startid, tstamp, tstamp.ges or tstamp.real. - + Must not have any of the attributes: startid, endid, tstamp, tstamp2, tstamp.ges, @@ -6040,7 +6143,7 @@ not a descendant of sp. In a textual content sp must NOT have any musical attributes.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the sp element of the Text Encoding Initiative (TEI).

stage directionContains any kind of stage direction within a dramatic text or fragment. @@ -6053,14 +6156,14 @@ - + Must have one of the attributes: startid, tstamp, tstamp.ges or tstamp.real. - + Must not have any of the attributes: startid, endid, tstamp, tstamp2, tstamp.ges, @@ -6072,7 +6175,7 @@

In a musical context stageDir must have a start-type attribute when it’s not a descendant of sp. In a textual content stageDir must NOT have any musical attributes.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the stage element of the Text Encoding Initiative (TEI).

Attributes for the identification of a causative agent. @@ -6088,13 +6191,13 @@ Logical domain attributes. - + - + Attributes describing the nature of an encoded scholarly intervention or @@ -6103,27 +6206,15 @@ - - Analytical domain attributes. - - Gestural domain attributes. - - - Logical domain attributes. - + - - Visual domain attributes. - - - Attributes that identify the reason why an editorial feature is used. @@ -6192,8 +6283,8 @@ permitted to occur within the parent of its own app ancestor. For example, when used as a descendent of verse, abbr should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the abbr element of the Text Encoding Initiative (TEI) and the abbr element of the Encoded + Archival Description (EAD).

additionMarks an addition to the text. @@ -6223,7 +6314,7 @@ example, when used as a descendent of verse, add should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the add element of the Text Encoding Initiative (TEI).

Groups a number of alternative encodings for the same point in a text. @@ -6236,7 +6327,7 @@ encodings to be considered as parallel. Note also that choice elements may be recursively nested.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the choice element of the Text Encoding Initiative (TEI).

correctionContains the correct form of an apparent erroneous passage. @@ -6258,7 +6349,7 @@ permitted to occur within the parent of its own app ancestor. For example, when used as a descendent of verse, corr should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the corr element of the Text Encoding Initiative (TEI).

copy/colla parte markA verbal or graphical indication to copy musical material written elsewhere. @@ -6270,7 +6361,7 @@ - + Must have one of the @@ -6328,7 +6419,7 @@ permitted to occur within the parent of its own app ancestor. For example, when used as a descendent of verse, damage should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the damage element of the Text Encoding Initiative (TEI).

deletionContains information deleted, marked as deleted, or otherwise indicated as superfluous or spurious in the copy text by an author, scribe, annotator, or corrector. @@ -6353,8 +6444,7 @@ example, when used as a descendent of verse, del should only contain those elements allowed within verse.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the del element of the Text Encoding Initiative (TEI).

expansionContains the expansion of an abbreviation. @@ -6366,6 +6456,7 @@ + abbreviation Captures the abbreviated form of the text. @@ -6375,8 +6466,8 @@ permitted to occur within the parent of its own app ancestor. For example, when used as a descendent of verse, expan should only contain those elements allowed within verse.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the expan element of the Text Encoding Initiative (TEI) and the expan element of the Encoded + Archival Description (EAD).

Indicates a point where material has been omitted in a transcription, whether as part of sampling practice or for editorial reasons described in the MEI header. @@ -6403,7 +6494,7 @@ deletion by an identifiable hand. The cert attribute signifies the degree of certainty ascribed to the identification of the extent of the missing material.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the gap element of the Text Encoding Initiative (TEI).

Marks the beginning of a passage written in a new hand, or of a change in the scribe, writing style, ink or character of the document hand. @@ -6424,7 +6515,7 @@ - + @new attribute should @@ -6440,7 +6531,7 @@ - + @old attribute should @@ -6461,10 +6552,10 @@ attribute signifies the degree of certainty ascribed to the identification of the new hand.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the handShift element of the Text Encoding Initiative (TEI).

A graphical or textual statement with additional / explanatory information about the musical text. The textual consequences of this intervention are encoded independently via - other means; that is, with elements such as <add>, <del>, etc. + other means; that is, with elements such as add, del, etc.
@@ -6545,7 +6636,7 @@ permitted to occur within the parent of its own app ancestor. For example, when used as a descendent of verse, orig should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the orig element of the Text Encoding Initiative (TEI).

regularizationContains material which has been regularized or normalized in some sense. @@ -6569,7 +6660,7 @@ example, when used as a descendent of verse, reg should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the reg element of the Text Encoding Initiative (TEI).

Indicates restoration of material to an earlier state by cancellation of an editorial or authorial marking or instruction. @@ -6582,6 +6673,7 @@ + description Provides a description of the means of restoration, stet or strike-down, for example. @@ -6592,7 +6684,7 @@ be permitted to occur within the parent of its own app ancestor. For example, when used as a descendent of verse, restore should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the restore element of the Text Encoding Initiative (TEI).

Contains apparently incorrect or inaccurate material. @@ -6610,7 +6702,7 @@ example, when used as a descendent of verse, sic should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the sic element of the Text Encoding Initiative (TEI).

substitutionGroups transcriptional elements when the combination is to be regarded as a single intervention in the text. @@ -6621,7 +6713,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the subst element of the Text Encoding Initiative (TEI).

Contains material supplied by the transcriber or editor for any reason. @@ -6649,7 +6741,7 @@ be permitted to occur within the parent of its own app ancestor. For example, when used as a descendent of verse, supplied should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the supplied element of the Text Encoding Initiative (TEI).

Contains material that cannot be transcribed with certainty because it is illegible or inaudible in the source. @@ -6679,14 +6771,13 @@ be permitted to occur within the parent of its own app ancestor. For example, when used as a descendent of verse, unclear should only contain those elements allowed within verse.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

-
- Attributes used to associate MEI features with corresponding glyphs in an - externally-defined standard such as SMuFL. +

The model of this element is based on the unclear element of the Text Encoding Initiative (TEI).

+ + Attributes that point to an external symbol authority. A name or label associated with the controlled vocabulary from which the value of - glyph.name or glyph.num is taken. + glyph.name or glyph.num is taken, or the textual content of the element. @@ -6696,12 +6787,23 @@ + + The web-accessible location of the controlled vocabulary from which the value of + glyph.name or glyph.num is taken, or the textual content of the element. + + + + + + + Attributes that specify names or values taken from an external symbol authority. + Glyph name. - + @glyph.name attribute @@ -6716,7 +6818,7 @@ - + SMuFL version 1.18 uses the range U+E000 - U+ECBF. @@ -6724,24 +6826,24 @@ - - The web-accessible location of the controlled vocabulary from which the value of - glyph.name or glyph.num is taken. - - - - + + Attributes used to associate MEI features with corresponding glyphs in an + externally-defined standard such as SMuFL. + + + + Attributes that associate a feature corresponding with all or part of an image. - Permits the current element to reference a facsimile surface or image zone which - corresponds to it. - + facsimile + Points to one or more images, portions of an image, or surfaces which correspond to the current element. + - + @facs attribute should @@ -6770,7 +6872,7 @@

The decls attribute may be used to link the collection of images with a particular source described in the header.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the facsimile element of the Text Encoding Initiative (TEI).

Defines a writing surface in terms of a rectangular coordinate space, optionally grouping one or more graphic representations of that space, and rectangular zones of interest within it. @@ -6789,8 +6891,8 @@

The startid attribute may be used to hold a reference to the first feature occurring on this surface.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

-
Defines an area of interest within a surface or graphic file. +

The model of this element is based on the surface element of the Text Encoding Initiative (TEI).

+
Defines an area of interest within a surface or graphic file. @@ -6800,7 +6902,7 @@

Scalable Vector Graphics (SVG) markup may be used when allowed by the graphicLike model.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the zone element of the Text Encoding Initiative (TEI).

Attributes shared by table cells. @@ -6846,8 +6948,7 @@
-

This element is modelled on the figure element in the Text Encoding Initiative (TEI) - standard.

+

The model of this element is based on the figure element of the Text Encoding Initiative (TEI).

figure descriptionContains a brief prose description of the appearance or content of a graphic figure, for use when documenting an image without displaying it. @@ -6860,9 +6961,10 @@ confuse this entity with a figure caption. A caption is text primarily intended for display with an illustration. It may or may not function as a description of the illustration.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the figDesc element of the Text Encoding Initiative (TEI).

Indicates the location of an inline graphic. + @@ -6873,7 +6975,7 @@ - + Graphic child of zone should not have @@ -6890,18 +6992,8 @@ attributes. - - Indicates the upper-left corner x coordinate. - - - - - Indicates the upper-left corner y coordinate. - - - - -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+
+

The model of this element is based on the graphic element of the Text Encoding Initiative (TEI).

Contains text displayed in tabular form. @@ -6913,8 +7005,8 @@ -

This element is modelled on elements in the Encoded Archival Description (EAD), Text - Encoding Initiative (TEI), and HTML standards.

+

The model of this element is based on the table element of the Encoded Archival Description (EAD), the table element of the Text + Encoding Initiative (TEI), and the table element of HTML.

table dataDesignates a table cell that contains data as opposed to a cell that contains column or row heading information. @@ -6928,7 +7020,7 @@

The colspan and rowspan attributes record tabular display rendering information.

-

This element is modelled on an element in the HTML standard.

+

The model of this element is based on the td element of HTML.

table headerDesignates a table cell containing column or row heading information as opposed to one containing data. @@ -6942,7 +7034,7 @@

The colspan and rowspan attributes record tabular display rendering information.

-

This element is modelled on an element in the HTML standard.

+

The model of this element is based on the th element of HTML.

table rowA formatting element that contains one or more cells (intersection of a row and a column) in a table. @@ -6954,14 +7046,14 @@

More precise rendition of the table and its cells can be specified in a style sheet.

-

This element is modelled on an element in the HTML standard.

+

The model of this element is based on the tr element of HTML.

Logical domain attributes. - + Logical domain attributes. @@ -6969,7 +7061,7 @@ - + @@ -6992,7 +7084,7 @@ - finger – An individual finger in a fingering indication. + fingerAn individual finger in a fingering indication. @@ -7002,14 +7094,14 @@ - + Must have one of the attributes: startid, tstamp, tstamp.ges or tstamp.real. - + @@ -7017,7 +7109,7 @@ descendant of fing. - (finger group)– A group of individual fingers in a fingering indication. + finger groupA group of individual fingers in a fingering indication. @@ -7027,14 +7119,14 @@ - + At least 2 fing or fingGrp elements are required. - + @@ -7280,10 +7372,19 @@ equals "true". + + + + Availability is only permitted when @singleton equals "true". + + + Indicates the manifestation is a unique physical object. +

This attribute is inspired by the FRBRoo concept of manifestation singleton.

+

Manifestation singleton encompasses: manuscripts, preperatory sketches, and final clean drafts.

A container for the descriptions of physical embodiments of an expression of a work. @@ -7317,7 +7418,7 @@ - (genetic description) - Bundles information about the textual development of a + genetic descriptionBundles information about the textual development of a work. @@ -7360,9 +7461,9 @@ Gestural domain attributes. - + - + Attributes for capturing momentary pitch inflection in the gestural domain. @@ -7370,7 +7471,7 @@ - + The value of @accid.ges should @@ -7380,23 +7481,27 @@ + + Gestural domain attributes. Gestural domain attributes. + + Gestural domain attributes. Gestural domain attributes. - - - + + + Gestural domain attributes. Gestural domain attributes. - + - + Attributes describing the method of performance. @@ -7409,8 +7514,19 @@ Gestural domain attributes. - + + + Attributes whether an element is performed "attacca". + + + Indicates that the performance of the next musical division should begin immediately + following this one. + + + + + Gestural domain attributes. @@ -7418,15 +7534,15 @@ Gestural domain attributes. - - + + Gestural domain attributes. Gestural domain attributes. - + @@ -7440,13 +7556,13 @@ Gestural domain attributes. - - + + Gestural domain attributes. - + Gestural domain attributes. @@ -7456,14 +7572,14 @@ Gestural domain attributes. - - + + Gestural domain attributes. - - + + @@ -7472,7 +7588,7 @@ Gestural domain attributes. - + Gestural domain attributes. @@ -7481,8 +7597,8 @@ Gestural domain attributes. - - + + Gestural domain attributes. @@ -7490,31 +7606,25 @@ Gestural domain attributes. Gestural domain attributes. - - - Indicates that the performance of the next musical division should begin immediately - following this one. - - - - - + + + Gestural domain attributes. - - + + Gestural domain attributes. - + Attributes that record performed duration that differs from a feature’s written duration. Records performed duration information that differs from the written duration. - + @@ -7559,40 +7669,40 @@ Gestural domain attributes. - + - + Gestural domain attributes. Gestural domain attributes. - + Gestural domain attributes. - - + + Gestural domain attributes. - + Gestural domain attributes. - - + + Gestural domain attributes. - - + + Gestural domain attributes. @@ -7602,34 +7712,36 @@ Gestural domain attributes. - - + + + + Gestural domain attributes. Gestural domain attributes. Gestural domain attributes. - + - + Gestural domain attributes. - + Gestural domain attributes. - - + + Gestural domain attributes. - + Gestural domain attributes. @@ -7657,15 +7769,15 @@ Attributes for describing the performed components of a line. - - + + Gestural domain attributes. Gestural domain attributes. - + Gestural domain attributes. @@ -7674,22 +7786,30 @@ time of the measure. In reality, this is usually the same as the onset time of the first event in the measure. - + Gestural domain attributes. + + Gestural domain attributes. + + + + Gestural domain attributes. Gestural domain attributes. Gestural domain attributes. + + Gestural domain attributes. Gestural domain attributes. Gestural domain attributes. - + Gestural domain attributes. @@ -7698,12 +7818,12 @@ Gestural domain attributes. - + Gestural domain attributes. - + Gestural domain attributes. @@ -7711,54 +7831,36 @@ Gestural domain attributes. - - - + + + + - - - Records performed octave information that differs from the written value. - - - - - - Contains a performed pitch name that differs from the written value. - - - - - - Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. - - - - - Gestural domain attributes. - + Gestural domain attributes. - + Gestural domain attributes. - - - + + + + - + When the @extremis attribute is used, @@ -7785,38 +7887,20 @@ necessary to record the written pitch and octave of the symbol for this note.

- - Records performed octave information that differs from the written value. - - - - - - Contains a performed pitch name that differs from the written value. - - - - - - Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. - - - -
Gestural domain attributes. - - + + Gestural domain attributes. Gestural domain attributes. - - + + Gestural accidentals associated with ornaments. @@ -7847,29 +7931,60 @@ Gestural domain attributes. - + Gestural domain attributes. - - + + - - Gestural domain attributes. - - Gestural domain attributes. - - Gestural domain attributes. - - Gestural domain attributes. - - Gestural domain attributes. - - Gestural domain attributes. - - - + + Gestural attributes about pitch. + + + Records performed octave information that differs from the written value. + + + + + + Contains a performed pitch name that differs from the written value. + + + + + + pitch number + Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. + + + + + + + Gestural domain attributes that describe the properties of a plica in the mensural repertoire. + + Gestural domain attributes. + + Gestural domain attributes. + + Gestural domain attributes. + + Gestural domain attributes. + + Gestural domain attributes. + + Gestural domain attributes. + + + + + + Gestural domain attributes. + + + Gestural domain attributes. @@ -7892,22 +8007,16 @@
Gestural domain attributes. - - - Indicates that the performance of the next section should begin immediately following - this one. - - - - - + + + Gestural domain attributes. Gestural domain attributes. - - + + Attributes that locate a sound source within 3-D space. @@ -7936,12 +8045,12 @@ Gestural domain attributes. - + Gestural domain attributes. - + Gestural domain attributes. @@ -7961,8 +8070,10 @@ Gestural domain attributes. - + + + Gestural domain attributes that describe the properties of a stem in the mensural repertoire. Gestural domain attributes. @@ -7979,9 +8090,9 @@ Gestural domain attributes. - + - + Attributes that record a performed (as opposed to notated) time stamp. @@ -7998,7 +8109,7 @@ - + Attributes that record a performed (as opposed to notated) time stamp for the end of an event. @@ -8019,18 +8130,18 @@ Gestural domain attributes. - - + + Gestural domain attributes. - + Gestural domain attributes. - + @@ -8057,7 +8168,7 @@ - +
Logical domain attributes. @@ -8065,16 +8176,17 @@ - + + chord reference Contains a reference to a chordDef element elsewhere in the document. - + @chordref attribute @@ -8168,7 +8280,7 @@ - + Must have one of the @@ -8187,6 +8299,7 @@ + @@ -8242,6 +8355,60 @@ + + Attributes that define the characteristics and components of the performance resource. + + + + + + + Use this attribute to identify the performance resource as a soloist especially in an accompanied work, such as a concerto or vocal solo. + + + + + + + Attributes that define the characteristics and components of the performance resource or a performance resource list. + + + + + + Indicates the number of performers. + + + + + + + Attributes that describe a performance resource as ad libitum (optional). + + + Marks a performance resource as ad libitum (optional). + + + + + + +

The technical term “ad libitum” has several meanings depending on the context in which it occurs:

+

+ + Meanings of ad libitum + + indicates an optional performance resource (instrumental or vocal part or group), + + marks a passage to be played freely or free in time, + + requests or invites to improvise a passage of music, + + indicates that the number repetitions can be set individually or spontaneously. + +

+

Currently only the use within a performance resource (case 1) is supported.

+
Attributes that define the characteristics and components of the bibliographic description. @@ -8415,8 +8582,7 @@ information about limitations on the use of material, such as those afforded by copyright.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the accessrestrict element of the Encoded Archival Description (EAD).

Records information concerning the process by which an item was acquired by the holding institution. @@ -8424,9 +8590,9 @@ - + -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the acquisition element of the Text Encoding Initiative (TEI).

alternative identifierMay contain a bibliographic identifier that does not fit within the meiHead element’s id attribute, for example because the identifier does not fit the definition of an XML id or because multiple identifiers are needed. @@ -8435,7 +8601,7 @@ -

One or the other of altId or the id attribute on mei is required when applicable.

+

One or the other of altId or the xml:id attribute on mei is required when applicable.

application informationGroups information about applications which have acted upon the MEI file. @@ -8444,7 +8610,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the appInfo element of the Text Encoding Initiative (TEI).

Provides information about an application which has acted upon the current document. @@ -8459,13 +8625,13 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the application element of the Text Encoding Initiative (TEI).

Documents the usage of a specific attribute of the element. - + @context attribute should @@ -8478,7 +8644,7 @@ - Circumstances in which the element appears, an XPath expression. + Circumstances in which the attribute appears, an XPath expression. @@ -8497,14 +8663,13 @@ - +

When used within the fileDesc element, availability indicates access to the MEI-encoded document itself.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the availability element of the Text Encoding Initiative (TEI).

Describes a folded sheet of paper. @@ -8555,7 +8720,7 @@ - + To be addressable, the category element must @@ -8600,7 +8765,7 @@ - + The date of the change must be recorded in an @@ -8619,8 +8784,7 @@ to designate an MEI encoding that has been so substantively changed that it constitutes a new version that supersedes earlier versions.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the respective element of the Encoded Archival Description (EAD).

change descriptionDescription of a revision of the MEI file. @@ -8657,14 +8821,14 @@ - + Only child elements of the same name as the parent of the componentList are allowed. - + When any child @@ -8692,8 +8856,7 @@ -

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the respective element of the Encoded Archival Description (EAD).

Contains a single entry within a content description element. @@ -8708,7 +8871,7 @@ - + When labels @@ -8718,7 +8881,7 @@ -

A suitable tone ; Left hand colouring ; Rhythm and accent ; Tempo ; +

A suitable tone ; Left hand coloring ; Rhythm and accent ; Tempo ; Flexibility ; Ornaments

@@ -8780,7 +8943,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the correction element of the Text Encoding Initiative (TEI).

A cutout is a section of a document sheet that has been removed and is now missing. @@ -8876,8 +9039,8 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the editionStmt element of the Text Encoding Initiative (TEI) and the editionstmt Encoded + Archival Description (EAD).

editorial declarationUsed to provide details of editorial principles and practices applied during the encoding of musical text. @@ -8889,7 +9052,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the editorialDecl element of the Text Encoding Initiative (TEI).

encoding descriptionDocuments the relationship between an electronic file and the source or sources from which it was derived as well as applications used in the encoding/editing process. @@ -8906,7 +9069,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the encodingDesc element of the Text Encoding Initiative (TEI).

exhibition historyA record of public exhibitions, including dates, venues, etc. @@ -8916,8 +9079,7 @@ -

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the MARC 585 field.

extended metadataProvides a container element for non-MEI metadata formats. @@ -8947,8 +9109,8 @@

Extent in this context represents file size.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the fileDesc element of the Text Encoding Initiative (TEI) and the filedesc element of the Encoded + Archival Description (EAD).

Describes the order of folia and bifolia making up the text block of a manuscript or print. @@ -8993,7 +9155,7 @@ thick, etc. may be described within the content of the hand element.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the handNote element of the Text Encoding Initiative (TEI).

Container for one or more hand elements. @@ -9001,7 +9163,7 @@ - + When labels are used, @@ -9009,7 +9171,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the handNotes element of the Text Encoding Initiative (TEI).

Provides a container for information about the history of a resource other than the circumstances of its creation. @@ -9018,7 +9180,7 @@ - + The elements acquisition, provenance, exhibHist, treatHist and treatSched are not permitted at the work or expression level and are only permitted at the manifestation level, if the manifestation is a manifestation singleton. @@ -9036,7 +9198,7 @@ - + incipCode must have a form or mimetype @@ -9053,7 +9215,7 @@ Plaine & Easie Code. - Humdrum Kern format. + **kern representation of the Humdrum format. Parsons code. @@ -9084,24 +9246,20 @@ - + -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the interpretation element of the Text Encoding Initiative (TEI).

Key captures information about tonal center and mode. + - - Indicates major, minor, or other tonality. - - - - +

This element is used exclusively within bibliographic descriptions. Do not confuse this element with keySig, which is used within the body of an MEI file to record this data.

@@ -9119,8 +9277,8 @@ of the authorizing list may be encoded in the auth attribute and the auth.uri attribute, respectively.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the language element of the Text Encoding Initiative (TEI) and the language element of the Encoded + Archival Description (EAD).

language usageGroups elements describing the languages, sub-languages, dialects, etc., represented within the encoded resource. @@ -9130,7 +9288,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the langUsage element of the Text Encoding Initiative (TEI).

MEI headerSupplies the descriptive and declarative metadata prefixed to every MEI-conformant text. @@ -9226,7 +9384,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the namespace element of the Text Encoding Initiative (TEI).

Indicates the extent of normalization or regularization of the original source carried out in converting it to electronic form. @@ -9239,8 +9397,8 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

-
(notes statement)– Collects any notes providing information about a text additional to +

The model of this element is based on the normalization element of the Text Encoding Initiative (TEI).

+
notes statementCollects any notes providing information about a text additional to that recorded in other parts of the bibliographic description. @@ -9248,7 +9406,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the notesStmt element of the Text Encoding Initiative (TEI).

other distinguishing characteristicAny characteristic that serves to differentiate a work or expression from another. @@ -9360,34 +9518,24 @@ + - - Indicates the number of performers. - - - - - Marks this instrument or vocal part as a soloist. Do not use this attribute for a solo - instrument which is not accompanied. - - - - Several instrumental or vocal resources treated as a group. + +

In the context of a performance resource the attribute adlib marks a resource as optional.

+
+

To indicate the tuning of an instrument, the attribute trans.diat can be used.

+
performance resources listSeveral instrumental or vocal resources treated as a group. + - - Indicates the number of performers. - - - - +

The function of instrumentalists or vocalists is represented by the choice of perfRes and perfResList child elements. Arrangements are coded for the medium of the work being described, not for the original medium.

physical descriptionContainer for information about the appearance, construction, or @@ -9404,8 +9552,7 @@ transcribed as part of the front or back matter; i.e., when they are considered to be meta-data rather than a transcription.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the physdesc element of the Encoded Archival Description (EAD).

physical mediumRecords the physical materials used in the source, such as ink and paper. @@ -9419,9 +9566,8 @@

All materials may be described in a single physMedium element or multiple elements may be used, one for each medium.

-

This element is modelled on elements in the Encoded Archival Description (EAD) standard. It - has the same function as the material element in the Text Encoding Initiative (TEI) - standard.

+

The model of this element is based on respective elements of the Encoded Archival Description (EAD). It + has the same function as the material element of the Text Encoding Initiative (TEI).

plate numberDesignation assigned to a resource by a music publisher, usually printed at the bottom of each page, and sometimes appearing also on the title page. @@ -9480,7 +9626,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the projectDesc element of the Text Encoding Initiative (TEI).

The record of ownership or custodianship of an item. @@ -9489,8 +9635,8 @@ -

This element is modelled on elements in the Encoded Archival Description (EAD) and Text - Encoding Initiative (TEI) standards.

+

The model of this element is based on the respective element of the Encoded Archival Description (EAD) and the provenance element of the Text + Encoding Initiative (TEI).

publication statementContainer for information regarding the publication or distribution of a bibliographic item, including the publisher’s name and address, the date of publication, and other relevant details. @@ -9502,7 +9648,7 @@

When an item is unpublished, use only the unpub sub-element.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the publicationStmt element of the Text Encoding Initiative (TEI).

revision descriptionContainer for information about alterations that have been made to an MEI file. @@ -9514,7 +9660,7 @@

It is recommended that changes be recorded in reverse chronological order, with the most recent alteration first.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the revisionDesc element of the Text Encoding Initiative (TEI).

sampling declarationContains a prose description of the rationale and methods used in sampling texts in the creation of a corpus or collection. @@ -9526,7 +9672,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the samplingDecl element of the Text Encoding Initiative (TEI).

Describes the type of score used to represent a musical composition (e.g., short score, full score, condensed score, close score, etc.). @@ -9547,7 +9693,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the segmentation element of the Text Encoding Initiative (TEI).

series statementGroups information about the series, if any, to which a publication belongs. @@ -9562,7 +9708,7 @@ series, but not describe each component. The seriesStmt element is provided within seriesStmt for the description of a sub-series.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the seriesStmt element of the Text Encoding Initiative (TEI).

sound channelsReflects the number of apparent sound channels in the playback of a recording (monaural, stereophonic, quadraphonic, etc.). @@ -9613,8 +9759,8 @@

The data attribute may be used to reference one or more musical features found in the content of this particular source.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the source element of the Text Encoding Initiative (TEI) and the source element of the Encoded + Archival Description (EAD).

source descriptionA container for the descriptions of the source(s) used in the creation of the electronic file. @@ -9644,7 +9790,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the stdVals element of the Text Encoding Initiative (TEI).

system requirementsSystem requirements for using the electronic item. @@ -9661,14 +9807,14 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the tagsDecl element of the Text Encoding Initiative (TEI).

Documents the usage of a specific element within the document. - + @context attribute should @@ -9697,7 +9843,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the tagUsage element of the Text Encoding Initiative (TEI).

Defines a typology either implicitly, by means of a bibliographic citation, or explicitly by a structured taxonomy. @@ -9714,7 +9860,7 @@ - + When labels are used, @@ -9732,7 +9878,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the titleStmt element of the Text Encoding Initiative (TEI).

track configurationNumber of physical/input tracks on a sound medium (e.g., eight track, twelve track). @@ -9766,8 +9912,7 @@

Treatment history may also comprise details of the treatment process (e.g., chemical solutions used, techniques applied, etc.), the date the treatment was applied, etc.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the respective element of the Encoded Archival Description (EAD).

treatment scheduledScheduled treatment, e.g., de-acidification, restoration, etc., for an item. @@ -9777,13 +9922,13 @@ -

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the respective element of the Encoded Archival Description (EAD).

unpublishedUsed to explicitly indicate that a bibliographic resource is unpublished. + @@ -9806,8 +9951,7 @@ the accessRestrict element, which holds information about conditions affecting the availability of the material.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the userestrict element of the Encoded Archival Description (EAD).

Contains a description of a watermark or similar device. @@ -9821,7 +9965,7 @@

The facs attribute may be used to record the location of the watermark in a facsimile image.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the watermark element of the Text Encoding Initiative (TEI).

Provides a detailed description of a work — a distinct intellectual or artistic creation — specifically its history, language use, and high-level musical attributes (e.g., key, tempo, meter, medium of performance, and intended duration). @@ -10087,7 +10231,7 @@
Attribute that expresses duration for a given mensural note symbol. - + @@ -10096,7 +10240,7 @@ - + @@ -10145,7 +10289,7 @@ Shared attributes in the mensural repertoire. - + @@ -10205,28 +10349,8 @@ - - Analytical domain attributes that describe the properties of a plica in the mensural repertoire. - - Gestural domain attributes that describe the properties of a plica in the mensural repertoire. Logical domain attributes that describe the properties of a plica in the mensural repertoire. - - Visual domain attributes that describe the properties of a plica stem in the mensural repertoire. - - - Describes the direction of a stem. - - - - - - Encodes the stem length. - - - - - Logical domain attributes. These attributes describe augmentation or diminution of the normal value of the notes in mensural notation as a ratio. @@ -10270,58 +10394,8 @@ - - Analytical domain attributes that describe the properties of a stem in the mensural repertoire. - - Gestural domain attributes that describe the properties of a stem in the mensural repertoire. Logical domain attributes that describe the properties of a stem in the mensural repertoire. - - Visual domain attributes that describe the properties of a stem in the mensural repertoire. - - - - - - - - - Records the position of the stem in relation to the note head(s). - - - - - - Encodes the stem length. - - - - - - Encodes the form of the stem using the values provided by the data.STEMFORM.mensural datatype. - - - - - - Describes the direction of a stem. - - - - - - Records the position of the flag using the values provided by the data.FLAGPOS.mensural datatype. - - - - - - Encodes the form of the flag using the values provided by the data.FLAGFORM.mensural datatype. - - - - - Attributes that describe the properties of stemmed features specific to mensural repertoires. @@ -10343,11 +10417,6 @@ - - Groups elements that may appear as part of a section in the mensural repertoire. - - - Groups elements that may appear in the declaration of staff features. @@ -10398,7 +10467,7 @@ - + Only one plica is allowed. @@ -10429,7 +10498,7 @@ - + A note with nested stem elements must not have @stem.* attributes. @@ -10480,7 +10549,7 @@ - + @instr attribute @@ -10498,8 +10567,8 @@ - - + + Logical domain attributes. @@ -10510,7 +10579,7 @@ Attributes that record MIDI instrument information. - + Only one of @midi.instrname and @midi.instrnum @@ -10518,7 +10587,7 @@ - + Only one of @midi.patchname and @midi.patchnum @@ -10571,6 +10640,7 @@ Attributes that record MIDI numbers. + number MIDI number in the range set by data.MIDIVALUE. @@ -10689,7 +10759,13 @@

The element’s content must be wrapped in a CDATA section to avoid parsing errors.

instrument definitionMIDI instrument declaration. - + + + + + + + @@ -10790,7 +10866,7 @@ Attributes that express the relationship between a component and its host. - + @@ -10814,6 +10890,18 @@ +
+ Attributes that describe foliation schemes. + + + Identifies the foliation scheme in terms of which the location is being specified by + pointing to some foliation element defining it, or to some other equivalent + resource. + + + + + Groups elements that may appear inline when the msdesc module is active. @@ -10828,7 +10916,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the accMat element of the Text Encoding Initiative (TEI).

addition descriptionProvides a description of significant additions found within an item, such as marginalia or other annotations. @@ -10838,22 +10926,19 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the additions element of the Text Encoding Initiative (TEI).

bindingContains a description of one binding, i.e., type of covering, boards, etc. applied to an item. + - - - - - -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+ +

The model of this element is based on the binding element of the Text Encoding Initiative (TEI).

binding descriptionDescribes the present and former bindings of an item. @@ -10863,7 +10948,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the bindingDesc element of the Text Encoding Initiative (TEI).

Describes the system used to ensure correct ordering of the quires making up an item, typically by means of annotations at the foot of the page. @@ -10873,8 +10958,15 @@ - -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+ + + + The catchwords element may only appear as a + descendant of the physDesc element. + + + +

The model of this element is based on the catchwords element of the Text Encoding Initiative (TEI).

Records a description of how the leaves or bifolia of an item are physically arranged. @@ -10883,7 +10975,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the collation element of the Text Encoding Initiative (TEI).

Contains a statement providing information regarding the date, place, agency, or reason for production of the item. @@ -10894,7 +10986,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the colophon element of the Text Encoding Initiative (TEI).

decoration descriptionContains a description of the decoration of an item. @@ -10903,7 +10995,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the decoDesc element of the Text Encoding Initiative (TEI).

decoration noteContains a description of one or more decorative features of an item. @@ -10912,7 +11004,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the decoNote element of the Text Encoding Initiative (TEI).

Contains the explicit of a manuscript item; that is, the closing words of the text proper, exclusive of any rubric or colophon which might follow it. @@ -10923,7 +11015,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the explicit element of the Text Encoding Initiative (TEI).

Describes the numbering system or systems used to count the leaves or pages in a codex. @@ -10932,7 +11024,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the foliation element of the Text Encoding Initiative (TEI).

Contains a heraldic formula or phrase, typically found as part of a blazon, coat of arms, etc. @@ -10944,7 +11036,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the heraldry element of the Text Encoding Initiative (TEI).

Describes how text is laid out on the page, including information about any ruling, pricking, or other evidence of page-preparation techniques. @@ -11002,7 +11094,7 @@ supplied.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the layout element of the Text Encoding Initiative (TEI).

layout descriptionCollects layout descriptions. @@ -11011,23 +11103,17 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the layoutDesc element of the Text Encoding Initiative (TEI).

Defines a location within a manuscript or manuscript component, usually as a (possibly discontinuous) sequence of folio references. + - - Identifies the foliation scheme in terms of which the location is being specified by - pointing to some foliation element defining it, or to some other equivalent - resource. - - - - + Specifies the starting point of the location in a normalized form. @@ -11038,24 +11124,26 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the locus element of the Text Encoding Initiative (TEI).

locus groupGroups locations which together form a distinct but discontinuous item within a manuscript or manuscript part, according to a specific foliation. + - - Identifies the foliation scheme in terms of which the location is being specified by - pointing to some foliation element defining it, or to some other equivalent - resource. - - - - -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+ + + + The locusGrp element may only appear as a descendant of a physDesc element, a + contentItem element, or a source element that is a component of another source or + work. + + + +

The model of this element is based on the locusGrp element of the Text Encoding Initiative (TEI).

Contains a string of words through which a manuscript signals the beginning or end of a text division, often with an assertion as to its author and title, which is in some way set off from the text itself, usually in red ink, or by use of different size or type of script, @@ -11073,11 +11161,11 @@ Signals beginning of a text division. - Makrs the end of a text division. + Marks the end of a text division. -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the rubric element of the Text Encoding Initiative (TEI).

script descriptionContains a description of the letters or characters used in an autographic item. @@ -11087,7 +11175,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the scriptDesc element of the Text Encoding Initiative (TEI).

script noteDescribes a particular script distinguished within the description of an autographic item. @@ -11096,20 +11184,17 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the scriptNote element of the Text Encoding Initiative (TEI).

A single seal or similar attachment. + - - - - - -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+ +

The model of this element is based on the seal element of the Text Encoding Initiative (TEI).

seal descriptionDescribes the seals or similar external attachments applied to an item. @@ -11119,7 +11204,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the sealDesc element of the Text Encoding Initiative (TEI).

second folioMarks the word or words taken from a fixed point in a codex (typically the beginning of the second leaf) in order to provide a unique identifier for the item. @@ -11130,8 +11215,15 @@ - -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+ + + + The secFolio element may only appear as a + descendant of the physDesc element. + + + +

The model of this element is based on the secFol element of the Text Encoding Initiative (TEI).

Provides a description of the leaf or quire signatures found within a codex. @@ -11140,8 +11232,15 @@ - -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+ + + + The signatures element may only appear as a + descendant of the physDesc element. + + + +

The model of this element is based on the signatures element of the Text Encoding Initiative (TEI).

Contains a word or phrase describing an official mark indicating ownership, genuineness, validity, etc. @@ -11154,7 +11253,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the stamp element of the Text Encoding Initiative (TEI).

Provides a description of the physical support material of a written item. @@ -11163,7 +11262,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the support element of the Text Encoding Initiative (TEI).

support descriptionGroups elements describing the physical support material of an item. @@ -11190,7 +11289,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the supportDesc element of the Text Encoding Initiative (TEI).

type descriptionContains a description of the typefaces or other aspects of the printing of a printed source. @@ -11200,7 +11299,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the typeDesc element of the Text Encoding Initiative (TEI).

type noteDescribes a particular font or other significant typographic feature of a printed resource. @@ -11209,7 +11308,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the typeNote element in the Text Encoding Initiative (TEI).

Groups elements used as part of a physical address. @@ -11256,7 +11355,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the addName element of the Text Encoding Initiative (TEI).

Contains the name of a geopolitical unit consisting of two or more nation states or countries. @@ -11269,7 +11368,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the bloc element of the Text Encoding Initiative (TEI).

corporate nameIdentifies an organization or group of people that acts as a single entity. @@ -11289,8 +11388,7 @@ sub-elements. The name of the list from which a controlled value is taken may be recorded using the auth attribute.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the corpname element of the Encoded Archival Description (EAD).

Contains the name of a geopolitical unit, such as a nation, country, colony, or commonwealth, larger than or administratively superior to a region and smaller than a bloc. @@ -11304,7 +11402,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the country element of the Text Encoding Initiative (TEI).

Contains the name of any kind of subdivision of a settlement, such as a parish, ward, or other administrative or geographic unit. @@ -11317,7 +11415,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the district element of the Text Encoding Initiative (TEI).

family nameContains a family (inherited) name, as opposed to a given, baptismal, or nick name. @@ -11340,7 +11438,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the forename element of the Text Encoding Initiative (TEI).

generational name componentContains a name component used to distinguish otherwise similar names on the basis of the relative ages or generations of the persons named. @@ -11353,7 +11451,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the genName element of the Text Encoding Initiative (TEI).

geographical feature nameContains a common noun identifying a geographical feature. @@ -11366,7 +11464,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the geogFeat element of the Text Encoding Initiative (TEI).

geographic nameThe proper noun designation for a place, natural feature, or political jurisdiction. @@ -11387,8 +11485,7 @@ Thesaurus of Geographic Names (TGN), may be recorded using the auth attribute.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the geogname element of the Encoded Archival Description (EAD).

name linkContains a connecting phrase or link used within a name but not regarded as part of it, such as "van der" or "of", "from", etc. @@ -11401,7 +11498,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the nameLink element of the Text Encoding Initiative (TEI).

period nameA label that describes a period of time, such as 'Baroque' or '3rd Style period'. @@ -11433,9 +11530,8 @@ nameLink, and roleName elements. The name of the list from which a controlled value for persName is taken may be recorded using the auth attribute.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

-
(postal box or post office box) contains a number or other identifier for some postal +

The model of this element is based on the persname element of the Encoded Archival Description (EAD).

+
postal box or post office boxContains a number or other identifier for some postal delivery point other than a street address. @@ -11444,8 +11540,8 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

-
(postal code) contains a numerical or alphanumeric code used as part of a postal address +

The model of this element is based on the postBox element of the Text Encoding Initiative (TEI).

+
postal codeContains a numerical or alphanumeric code used as part of a postal address to simplify sorting or delivery of mail. @@ -11454,7 +11550,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the postCode element of the Text Encoding Initiative (TEI).

Contains the name of an administrative unit such as a state, province, or county, larger than a settlement, but smaller than a country. @@ -11467,7 +11563,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the region element of the Text Encoding Initiative (TEI).

role nameContains a name component which indicates that the referent has a particular role or position in society, such as an official title or rank. @@ -11480,7 +11576,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the roleName element of the Text Encoding Initiative (TEI).

Contains the name of a settlement such as a city, town, or village identified as a single geopolitical or administrative unit. @@ -11493,7 +11589,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the settlement element of the Text Encoding Initiative (TEI).

full street address including any name or number identifying a building as well as the name of the street or route on which it is located. @@ -11503,7 +11599,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the street element of the Text Encoding Initiative (TEI).

style nameA label for a characteristic style of writing or performance, such as 'bebop' or 'rock-n-roll'. @@ -11521,7 +11617,25 @@ attribute.

Items in the Neume repertoire that may be printed near a staff. - + + Logical domain attributes. + + + Identifies the different kinds of division. + + + + + + + + + + + + + + Logical domain attributes. @@ -11566,6 +11680,7 @@ + pitch name Contains a written pitch name. @@ -11576,6 +11691,9 @@ Attributes that record visual details of neume notation. + + + @@ -11598,17 +11716,6 @@ - - Records direction of curvature. - - - Anti-clockwise curvature. - - - Clockwise curvature. - - - Pen stroke has an extension; specific to Hispanic notation. @@ -11666,6 +11773,39 @@ + + Attributes that specify the type of neumes. + + + Designation which characterizes the element in some sense, using any convenient + classification scheme or typology that employs single-token labels. + + + + + + + + + + + + + + + + + + + + + + + + + + + Logical domain attributes. @@ -11705,16 +11845,6 @@ Groups elements that modify neume-like features. Groups elements that may occur within a neume. - - Groups elements that may appear as part of a section in the neume repertoire. - - - - - Groups elements that are components of a staff in the neume repertoire. - - - Groups elements that accommodate neumed text. @@ -11764,37 +11894,7 @@ - - Designation which characterizes the element in some sense, using any convenient - classification scheme or typology that employs single-token labels. - - - - - - - - - - - - - - - - - - - - - - - - - - - - Collection of one or more neume components. + neume component groupCollection of one or more neume components. @@ -11819,37 +11919,7 @@ - - Designation which characterizes the element in some sense, using any convenient - classification scheme or typology that employs single-token labels. - - - - - - - - - - - - - - - - - - - - - - - - - - - - Oriscus. + Oriscus. @@ -11899,6 +11969,7 @@ + @@ -11910,22 +11981,9 @@ - - Identifies the different kinds of division. - - - - - - - - - - - - + Temporal alignment attributes. - + @when attribute should @@ -11954,7 +12012,7 @@ - + An avFile child of clip cannot have @@ -11974,7 +12032,7 @@ - + When @begin or @end @@ -12004,7 +12062,7 @@ - + When @begin or @end is used, @betype should be @@ -12019,8 +12077,8 @@ - - + + @since must be present when @interval is used. @@ -12036,7 +12094,7 @@ be 'time'. - + When @absolute is @@ -12080,7 +12138,7 @@ - + @since attribute @@ -12094,7 +12152,7 @@

The data attribute may be used to reference one or more features that occur at this point in time.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the when element of the Text Encoding Initiative (TEI).

Groups elements used for purposes of location and reference. @@ -12114,8 +12172,8 @@

Unlike the ref element, ptr cannot contain text or sub-elements to describe the referenced object.

-

This element is modelled on elements in the Encoded Archival Description (EAD) and Text - Encoding Initiative (TEI) standards.

+

The model of this element is based on the ptr element of the Encoded Archival Description (EAD) and the ptr element of the Text + Encoding Initiative (TEI).

referenceDefines a traversible reference to another location. May contain text and sub-elements that describe the destination. @@ -12131,8 +12189,8 @@

Unlike the ptr element, ref may contain text and sub-elements to describe the destination.

-

This element is modelled on elements in the Encoded Archival Description (EAD) and TEI - standards.

+

The model of this element is based on the ref element of the Encoded Archival Description (EAD) and the ref element of the Text + Encoding Initiative (TEI).

Permits any XML elements except those from the MEI or SVG namespace. @@ -12247,35 +12305,16 @@ -
- Analytical domain attributes. - - - - - Gestural domain attributes. Logical domain attributes. - - Visual domain attributes. Logical domain attributes. - + - - Analytical domain attributes. - - Gestural domain attributes. - - Visual domain attributes. - - - - Logical domain attributes for annot. Values for the type attribute can be taken from any convenient typology of annotation suitable to the work in hand; e.g., annotation, gloss, @@ -12288,8 +12327,8 @@ - - + + Logical domain attributes. @@ -12315,7 +12354,7 @@ - + @@ -12323,7 +12362,7 @@ - + @target attribute @@ -12358,7 +12397,7 @@ - + An element with a dots attribute must also have a dur @@ -12414,7 +12453,7 @@ Attributes that capture the placement of bar lines. - States the length of barlines in virtual units. The value must be greater than 0 and + States the length of bar lines in virtual units. The value must be greater than 0 and is typically equal to 2 times (the number of staff lines - 1); e.g., a value of 8 for a 5-line staff. @@ -12431,7 +12470,7 @@ - + "mensur" not allowed in this @@ -12495,7 +12534,7 @@ - + Attributes that indicate the calendar system of a date or other datable element. @@ -12533,7 +12572,7 @@ - + @@ -12546,7 +12585,7 @@ - + The value in @class must either correspond to the @xml:id attribute of a category @@ -12576,7 +12615,7 @@ Used by staffDef and scoreDef to provide default values for attributes in the logical domain related to clefs. - + An 'F', 'C', or 'G' clef requires that its position be @@ -12620,7 +12659,7 @@ Logical domain attributes. Attributes that record the shape of a clef. - + When @shape is present, @line must also be @@ -12671,6 +12710,15 @@ + + Attributes specifying whether a feature is contemporary or historical. + + + + + + + Attributes shared by events which rely on other events for their existence. For example, a slur/phrase marking must be drawn between or over a group of notes. The slur is therefore a @@ -12682,25 +12730,16 @@ - - + + This attribute class records the position of a feature within a two-dimensional coordinate system. + + + - - Indicates the upper-left corner x coordinate. - - - - - - Indicates the upper-left corner y coordinate. - - - - Indicates the lower-right corner x coordinate. @@ -12728,6 +12767,23 @@ + + This attribute class records the upper left position of a feature within a two-dimensional coordinate + system. + + + Indicates the upper-left corner x coordinate. + + + + + + Indicates the upper-left corner y coordinate. + + + + + Attributes that describe "cue-ness". @@ -12774,22 +12830,6 @@ - - Attributes that record the visual rendition of curves. - - - Describes the line style of a curve. - - - - - - Width of a curved line. - - - - - Logical domain attributes. @@ -12803,7 +12843,7 @@ - + @target attribute @@ -12857,7 +12897,7 @@ - + @data attribute should @@ -12885,7 +12925,7 @@ - + @decls attribute @@ -12911,11 +12951,17 @@ - + Attributes that describe distance from the staff. + + Records the default distance from the staff for directives. + + + + Records the default distance from the staff for dynamic marks. @@ -12929,8 +12975,14 @@ - - Determines how far from the staff to render text elements. + + Records the default distance from the staff for rehearsal marks. + + + + + + Records the default distance from the staff for tempo marks. @@ -12958,6 +13010,7 @@ Attributes that permit total duration to be represented by multiple values. + duration When a duration cannot be represented as a single power-of-two value, multiple space-separated values that add up to the total duration may be used. @@ -12990,10 +13043,11 @@ - + Attributes that express duration in musical terms. + duration Records the duration of a feature using the relative durational values provided by the data.DURATION datatype. @@ -13005,6 +13059,7 @@ Attributes that describe duration as a ratio. + number Along with numbase, describes duration as a ratio. num is the first value in the ratio, while numbase is the second. @@ -13025,7 +13080,7 @@ - + Attributes that capture characters used to enclose symbols having a cautionary or @@ -13069,8 +13124,8 @@ - - + + Attributes describing the support for and the certainty of an assertion. @@ -13128,7 +13183,7 @@ - + The @unit attribute is @@ -13165,6 +13220,16 @@ + + Attributes that record the function (i.e., placement) of forme work elements. + + + Records the function (i.e., placement) of a page header or footer. + + + + + Logical domain attributes. @@ -13187,7 +13252,7 @@ - + @hand attribute should @@ -13256,7 +13321,7 @@ - + @join attribute should @@ -13275,6 +13340,16 @@ + + Attributes for describing key mode. + + + Indicates major, minor, or other tonality. + + + + + Logical domain attributes. @@ -13294,7 +13369,7 @@ Used by staffDef and scoreDef to provide default values for attributes in the logical domain that are related to key signatures. - + Written key signature. @@ -13365,7 +13440,7 @@ - + @def attribute should @@ -13415,6 +13490,7 @@ + line end symbol Symbol rendered at end of line. @@ -13427,6 +13503,7 @@ + line start symbol Symbol rendered at start of line. @@ -13440,16 +13517,22 @@ - Attributes that record the basic visual rendition of lines. - - - Describes the line style of a line. - - - - + Attributes that record the basic visual rendition of lines. + - + + Describes the style of a line. + + + + + + Width of a line. + + + + + Describes the number of segments into which a dashed or dotted line may be divided, or the number of "peaks" of a wavy line; a pair of space-separated values (minimum and maximum, respectively) provides a range between which a rendering system-supplied value @@ -13460,7 +13543,7 @@ 2 - + @lform attribute @@ -13469,12 +13552,6 @@ - - Width of a line. - - - - @@ -13779,30 +13856,28 @@ - - Attributes that record the version of MEI in use. - - - Specifies a generic MEI version label. - 5.0.0-dev - - - Development version of MEI 5.0.0 - - - - - + Attributes that record the version of MEI in use.Specifies a generic MEI version label.5.0 + MEI 5.0 + Logical domain attributes. + + + Level of duration at which the proportion given by the @num and @numbase ratio applies. + + + + + Attributes that provide information about a structure’s conformance to the prevailing meter. + meter conformance Indicates the relationship between the content of a staff or layer and the prevailing meter. @@ -13823,6 +13898,7 @@ meter. + meter conformance Indicates the relationship between the content of a measure and the prevailing meter. @@ -13833,7 +13909,7 @@ Indicates whether or not a bar line is "controlling"; that is, if it indicates a point of alignment across all the parts. Bar lines within a score are usually controlling; that is, they "line up". Bar lines within parts may or may not be controlling. When applied to - measure, this attribute indicates the nature of the right barline + measure, this attribute indicates the nature of the right bar line but not the left. @@ -13854,6 +13930,7 @@ + symbol Indicates the use of a meter symbol instead of a numeric meter signature, that is, 'C' for common time or 'C' with a slash for cut time. @@ -13949,7 +14026,7 @@ - + @nymref attribute @@ -14017,7 +14094,7 @@ - + @@ -14033,7 +14110,7 @@ - + @head.altsym attribute @@ -14050,7 +14127,7 @@ - + When @@ -14102,7 +14179,7 @@ - + SMuFL version 1.18 uses the range U+E000 - U+ECBF. @@ -14122,6 +14199,7 @@ Attributes that record written octave. + octave Captures written octave information. @@ -14216,7 +14294,7 @@ - + Attributes that identify a musical range in terms of musical time. @@ -14233,7 +14311,7 @@ - + When @origin.tstamp2 is used @origin.tstamp must @@ -14250,7 +14328,7 @@ - + Logical domain attributes. @@ -14276,24 +14354,28 @@ + page top margin Indicates the amount of whitespace at the top of a page. + page bottom margin Indicates the amount of whitespace at the bottom of a page. + page left margin Indicates the amount of whitespace at the left side of a page. + page right margin Indicates the amount of whitespace at the right side of a page. @@ -14365,12 +14447,13 @@ - + Attributes that record written pitch name. + pitch name Contains a written pitch name. @@ -14426,7 +14509,7 @@ - + @plist attribute @@ -14560,7 +14643,7 @@ - + The attributes @min and @max are required when @@ -14570,6 +14653,36 @@ + + Logical domain attributes. + + + + + + + + + Indicates the function of the mark, usually implying a corresponding form. + + + Coda (SMuFL E048 or Unicode 1D10C). + + + Segno (SMuFL E047 or Unicode 1D10B). + + + Dal segno (SMuFL E045 or Unicode 1D109). + + + Da capo (SMuFL E046 or Unicode 1D10A). + + + Fine. (text) + + + + Attributes capturing information regarding responsibility for some aspect of the text's creation, transcription, editing, or encoding. @@ -14581,7 +14694,7 @@ - + @resp attribute should @@ -14598,11 +14711,11 @@ - + - + Attributes that express duration of rests in musical terms. @@ -14707,8 +14820,9 @@ Logical domain attributes. - + + Attributes that capture notation spacing information. @@ -14754,7 +14868,7 @@ - + @def attribute should @@ -14888,7 +15002,7 @@ - + @endid attribute @@ -14910,7 +15024,7 @@ - + @startid attribute @@ -14963,7 +15077,7 @@ - + @@ -15130,7 +15244,7 @@ - + @@ -15167,6 +15281,7 @@ + rendition Captures the appearance of the element’s contents using MEI-defined descriptors. @@ -15224,11 +15339,12 @@ - + Attributes that record a time stamp in terms of musical time, i.e., beats[.fractional beat part]. + time stamp Encodes the onset time in terms of musical time, i.e., beats[.fractional beat part], as expressed in the written time signature. @@ -15236,7 +15352,7 @@ - + Attributes that record a time stamp for the end of an event in terms of musical time. @@ -15252,6 +15368,7 @@ Attributes that describe transposition. + transposition (diatonic) Records the amount of diatonic pitch shift, e.g., C to C♯ = 0, C to D♭ = 1, necessary to calculate the sounded pitch from the written one. @@ -15259,6 +15376,7 @@ + transposition (semitones) Records the amount of pitch shift in semitones, e.g., C to C♯ = 1, C to D♭ = 1, necessary to calculate the sounded pitch from the written one. @@ -15546,7 +15664,7 @@ Allows one to signal to an application whether an element’s white space is "significant". The behavior of xml:space cascades to all descendant elements, but it can - be turned off locally by setting the xml:space attribute to the value "default". + be turned off locally by setting the xml:space attribute to the value default. Allows the application to handle white space as necessary. Not including an @@ -15571,7 +15689,7 @@

The width attribute may be used to capture measure width data for interchange with music - printing systems that utilize this information for printing. On <barLine> the width + printing systems that utilize this information for printing. On barLine the width attribute captures the width of the preceding measure.

@@ -15765,8 +15883,7 @@ Groups elements that modify note-like features. - - + Groups elements that denote a number or a quantity. @@ -15831,12 +15948,6 @@ Groups elements that represent a score. Groups elements that may appear as part of a score. - - Groups elements that may appear as part of a score in the mensural and neumes - repertoires. - - - Groups elements that represent a segment of music notation. @@ -15916,6 +16027,7 @@ + @@ -15933,7 +16045,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the actor element of the Text Encoding Initiative (TEI).

Contains a postal address, for example of a publisher, an organization, or an individual. @@ -15943,8 +16055,8 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the address element of the Text Encoding Initiative (TEI) and the address element of the Encoded + Archival Description (EAD).

address lineSingle line of a postal address. @@ -15955,8 +16067,8 @@

addrLine may be repeated as many times as necessary to enter all lines of an address.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the addrLine element of the Text Encoding Initiative (TEI) and the addressline element of the Encoded + Archival Description (EAD).

Range of a voice, instrument or piece. @@ -16008,7 +16120,7 @@ - + The @data attribute may only occur on an @@ -16066,8 +16178,8 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the author element of the Text Encoding Initiative (TEI) and the author element of the Encoded + Archival Description (EAD).

Vertical line drawn through one or more staves that divides musical notation into metrical units. @@ -16085,7 +16197,7 @@

This element is provided for repertoires, such as mensural notation, that lack measures. Because the barLine element’s attributes, from which the logical and visual characteristics of the bar line can be discerned, largely duplicate those of measure, - the use of barLine is not necessary within measure elements in + the use of barLine is not necessary within measure elements in CMN.

bibliographic referenceProvides a loosely-structured bibliographic citation in which the sub-components may or may not be explicitly marked. @@ -16103,8 +16215,8 @@ and corpName. This element may also function as a hypertext reference to an external electronic resource. Do not confuse this element with ref, which does not provide special bibliographic sub-elements.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the bibl element of the Text Encoding Initiative (TEI) and the bibref element of the Encoded + Archival Description (EAD).

List of bibliographic references. @@ -16114,7 +16226,7 @@ - + When labels are used, @@ -16122,7 +16234,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the listBibl element of the Text Encoding Initiative (TEI).

scope of citationDefines the scope of a bibliographic reference, for example as a list of page numbers, or a named subdivision of a larger work. @@ -16144,7 +16256,7 @@

Use the from and to attributes to regularize the beginning and ending values provided in the element content.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the biblScope element of the Text Encoding Initiative (TEI).

structured bibliographic citationContains a bibliographic citation in which bibliographic sub-elements must appear in a specified order. @@ -16182,7 +16294,7 @@ - + Must have one of the @@ -16217,7 +16329,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the castGroup element of the Text Encoding Initiative (TEI).

Contains a single entry within a cast list, describing either a single role or a list of non-speaking roles. @@ -16227,7 +16339,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the castItem element of the Text Encoding Initiative (TEI).

Contains a single cast list or dramatis personae. @@ -16238,7 +16350,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the castList element of the Text Encoding Initiative (TEI).

column beginningAn empty formatting element that forces text to begin in a new column. @@ -16257,7 +16369,7 @@ - + @@ -16270,7 +16382,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the cb element of the Text Encoding Initiative (TEI).

A simultaneous sounding of two or more notes in the same layer *with the same duration*. @@ -16296,7 +16408,7 @@ - + @@ -16304,7 +16416,7 @@ staff.
-
+ @@ -16363,7 +16475,7 @@ - + The value of @role must not contain the name of another element available in this @@ -16392,7 +16504,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI).

+

The model of this element is based on the creation element of the Text Encoding Initiative (TEI).

Symbol placed at the end of a line of music to indicate the first note of the next line. Sometimes called a "direct". @@ -16421,8 +16533,8 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the date element of the Text Encoding Initiative (TEI) and the date element of the Encoded + Archival Description (EAD).

Entity to whom a creative work is formally offered. @@ -16431,7 +16543,7 @@ - + The dedicatee element may not be @@ -16457,7 +16569,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the desc element of the Text Encoding Initiative (TEI).

dimensionAny single dimensional specification. @@ -16525,7 +16637,7 @@ - + The depth element may only appear @@ -16541,12 +16653,11 @@ capture of the individual dimensions of an object. Do not confuse this element with the extent element, which is used to indicate the quantity of described materials.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

-
directiveAn instruction expressed as a combination of text and symbols — such as - segno and coda symbols, fermatas over a bar line, etc., typically above, below, or between - staves, but not on the staff — that is not encoded elsewhere in more specific elements, like - tempo or dynam. +

The model of this element is based on the dimensions element of the Text Encoding Initiative (TEI) and the dimensions element of the Encoded + Archival Description (EAD).

+
directiveAn instruction expressed as a combination of text and symbols, typically above, + below, or between staves, but not on the staff — that is not encoded elsewhere in more specific + elements, like tempo, dynam or repeatMark. @@ -16557,7 +16668,7 @@ - + Must have one of the @@ -16583,7 +16694,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the distributor element of the Text Encoding Initiative (TEI).

divisionMajor structural division of text, such as a preface, chapter or section. @@ -16654,8 +16765,8 @@ -

Often, the head sub-element identifies the div’s purpose. This element is modelled on an element in the Text Encoding Initiative - (TEI) standard.

+

Often, the head sub-element identifies the div’s purpose. The model of this element is based on the div element of the Text Encoding Initiative + (TEI).

Dot of augmentation or division. @@ -16682,14 +16793,14 @@ - + Must have one of the attributes: startid, tstamp, tstamp.ges or tstamp.real. - + When @val2 is present, either @@ -16718,8 +16829,8 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the edition element of the Text Encoding Initiative (TEI) and the edition element of the Encoded + Archival Description (EAD).

The name of the individual(s), institution(s) or organization(s) acting in an editorial capacity. @@ -16731,7 +16842,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the editor element of the Text Encoding Initiative (TEI).

Alternative ending for a repeated passage of music; i.e., prima volta, seconda volta, etc. @@ -16812,8 +16923,19 @@

Use the dimensions element when it is necessary to specify the physical size of materials being described, for example, height and width.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the extent element of the Text Encoding Initiative (TEI).

+
extended dataProvides a container element for non-MEI data formats. + + + + + + + + + + +

Container for holding non-MEI data formats, similar to extMeta but available in when rather than in meiHead. The content of this element, by virtue of being inside a when element, is associated with a particular point in time in a media file and this point in time may be linked to symbolic data, such as notes, chords, rests, etc., recorded elsewhere. When the data in extData contains left angle bracket (less-than) or ampersand characters, or when it contains white space that should be preserved (such as line breaks), then the data should be enclosed in a CDATA section (e.g., for JSON formatted data).

Names of individuals, institutions, or organizations responsible for funding. Funders provide financial support for a project; they are distinct from sponsors, who provide intellectual support and authority. @@ -16826,7 +16948,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the funder element of the Text Encoding Initiative (TEI).

Term or terms that designate a category characterizing a particular style, form, or content. @@ -16850,7 +16972,7 @@

Because its model contains the music element, each of the subordinate MEI documents can have its own front and back matter.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the group element of the Text Encoding Initiative (TEI).

group symbolA brace or bracket used to group two or more staves of a score or part. @@ -16861,14 +16983,14 @@ - + In scoreDef, grpSym must have startid, endid, and level attributes. - + In staffGrp, grpSym must not have @@ -16892,8 +17014,8 @@

One or more head elements usually identify the parent element and/or its purpose.

-

This element is modelled on elements in Encoded Archival Description (EAD), Text Encoding - Initiative (TEI), and HTML standards.

+

The model of this element is based on the head element of the Encoded Archival Description (EAD), the head element of the Text Encoding + Initiative (TEI), and the head element of HTML.

Description of the vertical size of an object. @@ -16924,8 +17046,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the imprint element of the Text Encoding Initiative (TEI).

incipitThe opening music and/or words of a musical or textual work. @@ -16956,7 +17077,7 @@ - + One of the following is required: @x and @@ -16988,7 +17109,7 @@ - + If the @oct attribute @@ -16996,7 +17117,7 @@ elements. - + Only keyAccid elements are allowed @@ -17013,7 +17134,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the label element of the Text Encoding Initiative (TEI).

Don't confuse this element, which is used to capture labelling text appearing in the document, with the label attribute, which records text to be used to generate a designation for the element to which it’s attached, a "tool tip" or prefatory text, for @@ -17041,7 +17162,7 @@ - +

The term 'layer' is used instead of 'voice' in order to avoid confusion between 'voice' and 'voice leading' and 'voicing'. The def attribute may be used to create a @@ -17082,13 +17203,14 @@ attribute. Do not confuse this element with the sb element, which performs a similar function for musical notation.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the lb element of the Text Encoding Initiative (TEI).

line groupMay be used for any section of text that is organized as a group of lines; however, it is most often used for a group of verse lines functioning as a formal unit, e.g., a stanza, refrain, verse paragraph, etc. + @@ -17100,7 +17222,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the lg element of the Text Encoding Initiative (TEI).

Person or organization who is a writer of the text of an opera, oratorio, etc. @@ -17149,7 +17271,7 @@ - + The values in @staff must correspond to @n attribute of a staffDef @@ -17195,7 +17317,7 @@ - + Recommended practice is to use name elements to capture sub-parts of a generic @@ -17246,8 +17368,7 @@ its electronically-available location may be recorded using the auth and auth.uri attributes.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the name element of the Encoded Archival Description (EAD).

A single pitched event. @@ -17298,7 +17419,7 @@ - + Must have one of the @@ -17324,8 +17445,8 @@

A paragraph is usually typographically distinct: The text usually begins on a new line and the first letter of the content is often indented, enlarged, or both.

-

This element is modelled on elements in the Encoded Archival Description, Text Encoding - Initiative (TEI), and HTML standards.

+

The model of this element is based on the p element of the Encoded Archival Description, the p element of the Text Encoding + Initiative (TEI), and the p element of HTML.

paddingAn indication of extra visual space between notational elements. @@ -17384,7 +17505,7 @@ calculated by counting previous pb ancestor elements. When used in a score context, a page beginning implies an accompanying system beginning.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the pb element of the Text Encoding Initiative (TEI).

page descriptionContains a brief prose description of the appearance or description of the content of a physical page. @@ -17396,77 +17517,34 @@

Best practice suggests the use of controlled vocabulary. Don't confuse this element with a figure caption. A caption is text primarily intended for display with an illustration. It may or may not function as a description of the illustration.

-
page footerA running footer on the first page. Also, used to temporarily override a - running footer on individual pages. + page footerA running footer. + + - - Records horizontal alignment of the page footer. - - - - -

This element is used to capture the textual data that often appears on the first page of + +

This element is used to capture the textual data that often appears in printed music. It may also be used for similarly formatted material in manuscripts. When used within pb, it records a temporary suspension of the pattern of page footers established by the use of pgFoot within a previous scoreDef. Auto-generated page numbers may be indicated with a processing - instruction. The pgHead, pgHead2, pgFoot, and pgFoot2 elements should *not* be used to encode textual notes/annotations.

-
page footer 2A running footer on the pages following the first. - - - - - - - Records horizontal alignment of the page footer. Use multiple values to capture an - alternating pattern. - - - - -

This element is used to capture the textual data that often appears on the second and - succeeding pages of printed music. It may also be used for similarly formatted material in - manuscripts. Auto-generated page numbers may be indicated with a processing instruction. The - pgHead, pgHead2, pgFoot, and pgFoot2 elements should *not* be used to - encode textual notes/annotations.

-
page headerA running header on the first page. Also, used to temporarily override a - running header on individual pages. + instruction. The pgHead and pgFoot elements should *not* be used to encode textual notes/annotations.

+
page headerA running header. + + - - Records horizontal alignment of the page header. - - - - -

This element is used to capture the textual data that often appears on the first page of + +

This element is used to capture the textual data that often appears in printed music. It may also be used for similarly formatted material in manuscripts. When used within pb, it records a temporary suspension of the pattern of page headers established by the use of pgHead within a previous scoreDef. Auto-generated page numbers may be indicated with a processing - instruction. The pgHead, pgHead2, pgFoot, and pgFoot2 elements should *not* be used to encode textual notes/annotations.

-
page header 2A running header on the pages following the first. - - - - - - - Records horizontal alignment of the page header. Use multiple values to capture an - alternating pattern. - - - - -

This element is used to capture the textual data that often appears at the top of the - second and succeeding pages of printed music. It may also be used for similarly formatted - material in manuscripts. Auto-generated page numbers may be indicated with a processing - instruction. The pgHead, pgHead2, pgFoot, and pgFoot2 elements should not be used to encode textual notes/annotations.

+ instruction. The pgHead and pgFoot elements should *not* be used to encode textual notes/annotations.

Indication of 1) a "unified melodic idea" or 2) performance technique. @@ -17477,7 +17555,7 @@ - + Must have one of the @@ -17486,7 +17564,7 @@ dur, dur.ges, endid, or tstamp2. - + The visual attributes of the phrase (@bezier, @bulge, @curvedir, @lform, @@ -17522,8 +17600,7 @@ -

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the physloc element of the Encoded Archival Description (EAD).

Name of the organization responsible for the publication of a bibliographic item. @@ -17534,7 +17611,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the publisher element of the Text Encoding Initiative (TEI).

publication placeName of the place where a bibliographic item was published. @@ -17545,7 +17622,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the pubPlace element of the Text Encoding Initiative (TEI).

The name of the individual(s), institution(s) or organization(s) receiving correspondence. @@ -17583,7 +17660,7 @@ - + @@ -17625,6 +17702,7 @@ italicized, of a text word or phrase. + @@ -17642,7 +17720,9 @@

When an entire element should be rendered in a special way, a style sheet function should - be used instead of the rend element.

+ be used instead of the rend element. The glyph.auth and glyph.uri + attributes may be used to specify an external authority, e.g., SMuFL, to be used for + displaying code points in the textual content of the element.

Institution, agency, or individual which holds a bibliographic item. @@ -17657,8 +17737,7 @@ sub-elements. The name of the list from which a controlled value is taken may be recorded using the auth attribute.

-

This element is modelled on an element in the Encoded Archival Description (EAD) - standard.

+

The model of this element is based on the repository element of the Encoded Archival Description (EAD).

responsibilityA phrase describing the nature of intellectual responsibility. @@ -17672,7 +17751,7 @@

The name of the list from which a controlled value is taken may be recorded using the auth attribute.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the resp element of the Text Encoding Initiative (TEI).

responsibility statementTranscription of text that names one or more individuals, groups, or in rare cases, mechanical processes, responsible for creation, realization, production, funding, or distribution of the intellectual or artistic content. @@ -17684,7 +17763,7 @@ - + At least one element pair (a resp element and a name-like element) is @@ -17693,7 +17772,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the respStmt element of the Text Encoding Initiative (TEI).

A non-sounding event found in the source being transcribed. @@ -17704,7 +17783,7 @@ - + @@ -17722,7 +17801,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the role element of the Text Encoding Initiative (TEI).

role descriptionDescribes a character’s role in a drama. @@ -17730,7 +17809,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the roleDesc element of the Text Encoding Initiative (TEI).

system beginningAn empty formatting element that forces musical notation to begin on a new line. @@ -17773,10 +17852,8 @@ - - - - + + @@ -17795,7 +17872,7 @@ - + A @@ -17818,7 +17895,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the series element of the Text Encoding Initiative (TEI).

A placeholder used to fill an incomplete measure, layer, etc. most often so that the combined duration of the events equals the number of beats in the measure. @@ -17839,7 +17916,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the speaker element of the Text Encoding Initiative (TEI).

Names of sponsoring individuals, organizations or institutions. Sponsors give their intellectual authority to a project; they are to be distinguished from funders, who provide the funding but do not necessarily take intellectual responsibility. @@ -17852,8 +17929,8 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the sponsor element of the Text Encoding Initiative (TEI) and the sponsor element of the Encoded + Archival Description (EAD).

stacked textAn inline table with a single column. @@ -17902,7 +17979,7 @@ - + @@ -17933,7 +18010,7 @@ - + @@ -17945,7 +18022,7 @@ permitted.
-
+ @@ -17953,7 +18030,7 @@ current staff.
-
+ @@ -17962,14 +18039,14 @@ exist.
-
+ The clef position must be less than or equal to the number of lines on the staff. - + @@ -17978,7 +18055,7 @@ less than or equal to the number of lines on the staff.
-
+ @@ -17986,7 +18063,7 @@ number of values as there are staff lines.
-
+ @@ -17996,7 +18073,7 @@ lines. - + @@ -18013,7 +18090,7 @@ - + @@ -18024,7 +18101,7 @@ - + @@ -18050,7 +18127,7 @@ - + @@ -18087,7 +18164,7 @@ - + In the symbolDef context, symbol must have @@ -18119,7 +18196,7 @@ - + Only analog, class, label, mm, mm.dots, mm.unit, n, translit, type, xml:base, xml:id, @@ -18127,7 +18204,7 @@ part. - + Must have one of the @@ -18142,7 +18219,7 @@ - + The @data attribute may only occur on a @@ -18158,7 +18235,7 @@ taxonomy, class must contain an absolute URI, which may include the fragment identifier of the element containing the category label.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the term element of the Text Encoding Initiative (TEI).

text languageIdentifies the languages and writing systems within the work described by a bibliographic description, not the language of the description. @@ -18270,7 +18347,7 @@ as those constituting an article or preposition) that should not be used for sorting a title or name may be indicated in the nonfiling attribute.

-

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the title element of the Text Encoding Initiative (TEI).

Contains a transcription of the title page of a text. @@ -18285,7 +18362,7 @@

This element may be used within the physDesc element when no other transcription is provided.

-

This element is modelled on an element in Encoded Archival Description (EAD) standard.

+

The model of this element is based on the titlePage element of the Text Encoding Initiative (TEI).

Contains a subsection or division of the title of a bibliographic entity. @@ -18356,7 +18433,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the titlePart element of the Text Encoding Initiative (TEI).

Description of the horizontal size of an object. @@ -18479,7 +18556,7 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the argument element of the Text Encoding Initiative (TEI).

back matterContains any appendixes, advertisements, indexes, etc. following the main body of a musical text. @@ -18490,8 +18567,7 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the back element of the Text Encoding Initiative (TEI).

Contains a quotation, anonymous or attributed, appearing on a title page. @@ -18501,7 +18577,7 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the epigraph element of the Text Encoding Initiative (TEI).

front matterBundles prefatory text found before the start of the musical text. @@ -18516,8 +18592,7 @@ as textual divisions; that is, as div elements, with an optional head sub-element describing the nature of the division. The pb element is allowed here in order to accommodate page images, e.g., cover, endpapers, etc. before and after the actual textual matter.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) and Encoded - Archival Description (EAD) standards.

+

The model of this element is based on the front element of the Text Encoding Initiative (TEI).

Contains a formal statement authorizing the publication of a work, sometimes required to appear on a title page or its verso. @@ -18528,7 +18603,7 @@ -

This element is modelled on elements in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the imprimatur element of the Text Encoding Initiative (TEI).

line of textContains a single line of text within a line group. @@ -18546,7 +18621,7 @@

Do not confuse this element with the line element, which is used for graphical lines that occur in music notation.

-

This element is modelled on elements in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the l element of the Text Encoding Initiative (TEI).

list itemSingle item in a list. @@ -18554,8 +18629,8 @@ -

This element is modelled on elements in the Encoded Archival Description (EAD), Text - Encoding Initiative (TEI), and HTML standards.

+

The model of this element is based on the item elements of the Encoded Archival Description (EAD), the item element of the Text + Encoding Initiative (TEI), and the li element of HTML.

A formatting element that contains a series of items separated from one another and arranged in a linear, often vertical, sequence. @@ -18571,7 +18646,7 @@ - + In a list of type "gloss" all items @@ -18627,8 +18702,8 @@ label.

-

This element is modelled on elements in Encoded Archival Description (EAD), Text Encoding - Initiative (TEI), and HTML standards.

+

The model of this element is based on the list element of the Encoded Archival Description (EAD), the list element of the Text Encoding + Initiative (TEI), and the respective elements of HTML.

quotedContains material which is distinguished from the surrounding phrase-level text using quotation marks or a similar method. Use quote for block-level quotations. @@ -18681,7 +18756,7 @@ and passages that are mentioned but not used.

Do not confuse this element, used to capture phrase-level quotations, and quote, intended for block quotations.

-

This element is modelled on elements found in HTML, TEI, and EAD standards.

+

The model of this element is based on the q element of HTML and the q element of the Text Encoding Initiative (TEI).

quoted materialContains a paragraph-like block of text attributed to an external source, normally set off from the surrounding text by spacing or other typographic distinction. @@ -18696,9 +18771,8 @@

The source for the quote may be included in a bibl sub-element.

Do not confuse this element, used to capture block-level quotations, and q, intended for inline quotations.

-

This element is modelled on elements found in HTML, TEI, and EAD standards.

-
(arbitrary segment) represents any segmentation of text below the "text component" - level. +

The model of this element is based on the quote element of the Text Encoding Initiative (TEI) and the quote element of the Encoded Archival Description (EAD).

+
arbitrary segmentrepresents any segmentation of text below the "text component" level. @@ -18706,7 +18780,7 @@ -

This element is modelled on an element in the Text Encoding Initiative (TEI) standard.

+

The model of this element is based on the seg element of the Text Encoding Initiative (TEI).

Attributes supplying pointers to user-defined symbols. @@ -18716,7 +18790,7 @@ - + @altsym attribute @@ -18773,7 +18847,7 @@ - + @@ -18832,7 +18906,7 @@ - + In the symbolDef context, curve must have @@ -18866,7 +18940,7 @@ - + When used in the symbolDef context, must have @@ -18968,6 +19042,8 @@ + + Visual domain attributes. Visual domain attributes. @@ -18978,6 +19054,12 @@ + + Visual domain attributes. + + + + Visual domain attributes. @@ -18995,6 +19077,7 @@ + @@ -19030,18 +19113,6 @@ - - Visual form of the line. - - - - - - Width of the line. - - - - Visual domain attributes. @@ -19050,7 +19121,7 @@ - + @@ -19080,7 +19151,8 @@ - States the length of barlines in virtual units. The value must be greater than 0 and + length + States the length of bar lines in virtual units. The value must be greater than 0 and is typically equal to 2 times (the number of staff lines - 1); e.g., a value of 8 for a 5-line staff. @@ -19188,12 +19260,12 @@ attributes. + + - - Visual domain attributes. @@ -19313,12 +19385,27 @@ + + Attributes describing the direction of curvature. + + + Records direction of curvature. + + + Anti-clockwise curvature. + + + Clockwise curvature. + + + + Visual domain attributes. - + @@ -19487,6 +19574,7 @@ + orientation Combination expressed horizontally, as for brass instruments. @@ -19514,7 +19602,7 @@ - + The number of floating beams must be less @@ -19543,6 +19631,21 @@ + + Visual domain attributes. + + + + + Visual domain attributes + + + Determines whether to display guitar chord grids. + + + + + Visual domain attributes. @@ -19694,10 +19797,10 @@ - - Determines whether cautionary accidentals should be displayed at a key change. + + Determines where cautionary accidentals should be displayed at a key change. - + @@ -19705,14 +19808,14 @@ Used by staffDef and scoreDef to provide default values for attributes in the visual domain related to key signatures. - - Indicates whether the key signature should be displayed. + + Determines where cautionary accidentals should be displayed at a key change. - + - - Determines whether cautionary accidentals should be displayed at a key change. + + Determines whether the key signature is to be displayed. @@ -19800,6 +19903,7 @@ + @@ -19809,17 +19913,6 @@ - - Records direction of curvature. - - - Anti-clockwise curvature. - - - Clockwise curvature. - - - Indicates whether curve is closed. @@ -19836,12 +19929,12 @@ beats. + + - - Visual domain attributes. @@ -19957,6 +20050,11 @@ + + Visual domain attributes. + + + Visual domain attributes. @@ -19965,6 +20063,7 @@ + @@ -19991,9 +20090,24 @@ + + Determines whether the meter signature is to be displayed. + + + + Visual domain attributes. + + Visual domain attributes. + + + + + + + Visual domain attributes. @@ -20016,7 +20130,6 @@ - @@ -20055,6 +20168,7 @@ + @@ -20221,6 +20335,24 @@ + + Visual domain attributes that describe the properties of a plica stem in the mensural repertoire. + + + direction + Describes the direction of a stem. + + + + + + length + Encodes the stem length. + + + + + Visual domain attributes. @@ -20276,6 +20408,18 @@ + + Visual domain attributes. + + + + + + + + + + Visual domain attributes. @@ -20384,12 +20528,12 @@ normal position) of the entire rendered slur/phrase mark. + + - - Visual domain attributes. @@ -20425,6 +20569,7 @@ + @@ -20439,12 +20584,6 @@ - - Determines whether to display guitar chord grids. - - - - Indicates the number of layers and their stem directions. @@ -20457,7 +20596,7 @@ -

The value is structured; that is, it should contain a single color value or have +

The value is structured; that is, it should contain a single color value or have the same number of space-separated values as the number of lines indicated by the lines attribute. The first value then applies to the lowest line of the staff.

All values from data.COLOR are allowed.

@@ -20487,6 +20626,7 @@ + bar lines through Indicates whether bar lines go across the space between staves (true) or are only drawn across the lines of each staff (false). @@ -20507,6 +20647,55 @@ +
+ Visual domain attributes that describe the properties of a stem in the mensural repertoire. + + + + + + + + + position + Records the position of the stem in relation to the note head(s). + + + + + + length + Encodes the stem length. + + + + + + Encodes the form of the stem using the values provided by the data.STEMFORM.mensural datatype. + + + + + + direction + Describes the direction of a stem. + + + + + + Records the position of the flag using the values provided by the data.FLAGPOS.mensural datatype. + + + + + + Encodes the form of the flag using the values provided by the data.FLAGFORM.mensural datatype. + + + + + Visual domain attributes. @@ -20547,6 +20736,7 @@ Visual domain attributes. + @@ -20563,12 +20753,12 @@ beats. + + - - Visual domain attributes. @@ -20660,7 +20850,7 @@ - +
diff --git a/libmei/mei/develop/mei-basic_compiled.odd b/libmei/mei/mei-basic_compiled.odd similarity index 97% rename from libmei/mei/develop/mei-basic_compiled.odd rename to libmei/mei/mei-basic_compiled.odd index c311db8a660..b1b8931f0d0 100644 --- a/libmei/mei/develop/mei-basic_compiled.odd +++ b/libmei/mei/mei-basic_compiled.odd @@ -1,4 +1,4 @@ - + @@ -11,13 +11,20 @@ Revisions Laurent Pugin + + Revisions + Klaus Rettinghaus + In collaboration with The MEI Community -

+ Music Encoding Initiative (MEI) Board + + Licensed under the Educational Community License version 2.0 +

@@ -33,11 +40,14 @@ Revisions at the MEI Developers Conference, Charlottesville. + + Fixing color attribute and cleanup attribute class references. + - + Written accidental values. @@ -112,6 +122,18 @@ Natural note lowered by quarter tone (natural modified by arrow). + + Double sharp note raised by quarter tone (double sharp modified by arrow). + + + Double sharp note lowered by quarter tone (double sharp modified by arrow). + + + Double flat note raised by quarter tone (double flat modified by arrow). + + + Double flat note lowered by quarter tone (double flat modified by arrow). + 1/4-tone flat accidental. @@ -222,6 +244,12 @@ Three quarter-tones flat. + + Five quarter-tones sharp. + + + Five quarter-tones flat. + @@ -2668,7 +2696,7 @@ - Staff location. The value '0' indicates the bottom line of the current staff; positive + Staff location. The value 0 indicates the bottom line of the current staff; positive values are used for positions above the bottom line and negative values for the positions below. For example, in treble clef, 1 = F4, 2 = G4, 3 = A4, etc. and -1 = D4, -2 = C4, and so on. @@ -3166,20 +3194,8 @@ + - - - Indicates whether the tremolo is measured or unmeasured. - - - Measured tremolo. - - - Unmeasured tremolo. - - - - Logical domain attributes in the CMN repertoire. @@ -3231,20 +3247,8 @@ + - - - Describes the style of the tremolo. - - - Measured tremolo. - - - Unmeasured tremolo. - - - - Logical domain attributes. @@ -3657,6 +3661,21 @@ + + Attributes describing the form of a tremolo. + + + Describes the style of the tremolo. + + + Measured tremolo. + + + Unmeasured tremolo. + + + + Attributes that describe measured tremolandi. @@ -3883,7 +3902,7 @@ tstamp.real attribute, while the ending point may be recorded by either a dur, dur.ges, endid, or tstamp2 attribute. It is a semantic error not to specify one starting and one ending type of attribute.

- A container for a sequence of grace notes. + grace groupA container for a sequence of grace notes. @@ -4543,7 +4562,7 @@ -
finger – An individual finger in a fingering indication. +
fingerAn individual finger in a fingering indication. @@ -4568,7 +4587,7 @@ descendant of fing. - (finger group)– A group of individual fingers in a fingering indication. + finger groupA group of individual fingers in a fingering indication. @@ -4627,6 +4646,17 @@ +
+ Attributes whether an element is performed "attacca". + + + Indicates that the performance of the next musical division should begin immediately + following this one. + + + + + Gestural domain attributes. @@ -4658,15 +4688,9 @@ Gestural domain attributes. - - - Indicates that the performance of the next musical division should begin immediately - following this one. - - - - - + + + Gestural domain attributes. @@ -4807,15 +4831,9 @@ Gestural domain attributes. Gestural domain attributes. - - - Indicates that the performance of the next section should begin immediately following - this one. - - - - - + + + Gestural domain attributes. @@ -5007,7 +5025,7 @@ - + @@ -5125,23 +5143,7 @@

The lb element is allowed here in order to facilitate karaoke applications. The func attribute on lb may be used to distinguish true line endings from those of line groups for these applications.

- Division of a poem or song lyrics, sometimes having a fixed length, meter or rhyme scheme; - a stanza. - - - - - - - - - - - - - - - + Division of a poem or song lyrics, sometimes having a fixed length, meter or rhyme scheme; a stanza.

The lb element is allowed here in order to facilitate karaoke applications. The func attribute on lb may be used to distinguish true line endings from those of line groups for these applications.

@@ -5657,6 +5659,17 @@
+
+ Visual color attributes. + + + Used to indicate visual appearance. Do not confuse this with the musical term 'color' + as used in pre-CMN notation. + + + + + Attributes common to many elements. Attributes shared by events which rely on other events for their existence. For example, a slur/phrase marking must be drawn between or over a group of notes. The slur is therefore a @@ -5830,6 +5843,16 @@ + + Attributes that record the function (i.e., placement) of forme work elements. + + + Records the function (i.e., placement) of a page header or footer. + + + + + Attributes that record horizontal alignment. @@ -5966,15 +5989,20 @@ Attributes that record the basic visual rendition of lines. - - line form - Describes the line style of a line. - - - - - + + Describes the style of a line. + + + + + + Width of a line. + + + + + Describes the number of segments into which a dashed or dotted line may be divided, or the number of "peaks" of a wavy line; a pair of space-separated values (minimum and maximum, respectively) provides a range between which a rendering system-supplied value @@ -5994,27 +6022,13 @@ - - Width of a line. - - - - - - Attributes that record the version of MEI in use. - - - Specifies a generic MEI version label. - - - This version of MEI. - - - - - + Attributes that record the version of MEI in use.Specifies a generic MEI version label.5.0 + MEI 5.0 + + MEI 5.0+basic + Attributes that provide information about a measure's conformance to the prevailing meter. @@ -6817,7 +6831,7 @@ Allows one to signal to an application whether an element’s white space is "significant". The behavior of xml:space cascades to all descendant elements, but it can - be turned off locally by setting the xml:space attribute to the value "default". + be turned off locally by setting the xml:space attribute to the value default. Allows the application to handle white space as necessary. Not including an @@ -7173,8 +7187,18 @@ attributes, a caesura will be rendered as a pair of slanted lines through the top line of the staff.

- A simultaneous sounding of two or more notes in the same layer *with the same - duration*.Indication of the exact location of a particular note on the staff and, therefore, the + A simultaneous sounding of two or more notes in the same layer *with the same + duration*. + + + + + + + + + + Indication of the exact location of a particular note on the staff and, therefore, the other notes as well. @@ -7494,20 +7518,12 @@ page footerA running footer. + + - - Records horizontal alignment of the page footer. - - - - - Records the function (i.e., placement) of the page footer. - - - - +

This element is used to capture the textual data that often appears in printed music. It may also be used for similarly formatted material in manuscripts. When used within pb, it records a temporary suspension of the pattern of @@ -7516,20 +7532,12 @@ page headerA running header. + + - - Records horizontal alignment of the page header. - - - - - Records the function (i.e., placement) of the page header. - - - - +

This element is used to capture the textual data that often appears in printed music. It may also be used for similarly formatted material in manuscripts. When used within pb, it records a temporary suspension of the pattern of @@ -7548,7 +7556,7 @@

The model of this element is based on the pubPlace element of the Text Encoding Initiative (TEI).

renderA formatting element indicating special visual rendering, e.g., bold or italicized, of a text word or phrase. - + @@ -8084,13 +8092,14 @@

The startid and endid attributes are used to indicate the chordMember elements on which the barre starts and finishes respectively. The fret at which the barre should be created is recorded by the fret attribute.

-
Visual domain attributes. + Visual domain attributes. Visual domain attributes. - + + @@ -8126,28 +8135,16 @@
- - Visual form of the line. - - - - - - Width of the line. - - - -
-
Visual domain attributes. + Visual domain attributes. Visual domain attributes. - + - Visual domain attributes. + Visual domain attributes. Indicates the number of slashes required to render the appropriate beat repeat symbol. When a single beat consisting of a single note or chord is repeated, the repetition symbol is a single thick, slanting slash; therefore, the value 1 should be used. When the beat @@ -8157,15 +8154,15 @@ - Visual domain attributes. + Visual domain attributes. Visual domain attributes. - Visual domain attributes.Visual domain attributes for chord. The slur, slur.dir, slur.rend, tie, tie.dir, and tie.rend + Visual domain attributes.Visual domain attributes for chord. The slur, slur.dir, slur.rend, tie, tie.dir, and tie.rend attributes here are syntactic sugar for these attributes on each of the chord's individual notes. The values here apply to all the notes in the chord. If some notes are slurred or tied - while others aren't, then the individual note attributes must be used. + while others aren't, then the individual note attributes must be used. Indicates a single, alternative note head should be displayed instead of individual note heads. The highest and lowest notes of the chord usually indicate the upper and lower boundaries of the cluster note head. @@ -8176,7 +8173,7 @@ Visual domain attributes. - + @@ -8223,7 +8220,7 @@

If tstamp2 is not provided, then the extender should be drawn based on the value of tstamp2 on the harm ancestor.

-
Visual domain attributes. + Visual domain attributes. Describes the visual appearance of the fermata; that is, whether it occurs as upright or inverted. @@ -8265,7 +8262,7 @@ Visual domain attributes. - + @@ -8277,7 +8274,7 @@ Visual domain attributes. - + Visual domain attributes. The startho and startvo attributes record the horizontal and @@ -8289,7 +8286,7 @@ the startho, endho, startvo, and endvo attributes, while the placement of the entire rendered mark may be controlled by use of the ho and vo attributes. - + @@ -8329,17 +8326,30 @@ Visual domain attributes. - + - + Visual domain attributes. + Describes how the harmonic indication should be rendered. + + + Chord tablature grid. + + + Chord tablature grid and the element’s textual content. + + + Textual content of the element. + + + Visual domain attributes. - + @@ -8359,18 +8369,18 @@ lines. Startto and endto describe the start and end points in terms of time; that is, beats. - + + + - - Visual domain attributes. - + @@ -8380,7 +8390,7 @@ Visual domain attributes. - + @@ -8391,7 +8401,7 @@ Visual domain attributes. - + @@ -8399,13 +8409,12 @@ - Visual domain attributes. - + @@ -8415,12 +8424,13 @@ Visual domain attributes. - + + @@ -8436,7 +8446,7 @@ Visual domain attributes. - + @@ -8445,7 +8455,7 @@ Visual domain attributes. - + @@ -8462,7 +8472,7 @@ Visual domain attributes. - + @@ -8473,7 +8483,7 @@ Visual domain attributes. - + @@ -8503,7 +8513,7 @@ allows the full range of values. - + @@ -8523,7 +8533,7 @@ Visual domain attributes. - + @@ -8534,7 +8544,7 @@ Visual domain attributes. - + @@ -8552,7 +8562,7 @@ - Visual domain attributes. + Visual domain attributes. Visual domain attributes. @@ -8584,13 +8594,13 @@ Visual domain attributes for slur. The vo attribute is the vertical offset (from its normal position) of the entire rendered slur/phrase mark. - + + + - - Visual domain attributes. @@ -8643,7 +8653,7 @@ - Visual domain attributes. + Visual domain attributes. Visual domain attributes. @@ -8662,19 +8672,19 @@ lines. Startto and endto describe the start and end points in terms of time; that is, beats. - + + + - - Visual domain attributes. - + @@ -8688,7 +8698,7 @@ Visual domain attributes. - + @@ -8727,7 +8737,7 @@ Visual domain attributes. - + @@ -8738,7 +8748,7 @@ Visual domain attributes. - + @@ -8749,7 +8759,7 @@ Visual domain attributes. - + diff --git a/libmei/mei/develop/mei-verovio.xml b/libmei/mei/mei-verovio.xml similarity index 97% rename from libmei/mei/develop/mei-verovio.xml rename to libmei/mei/mei-verovio.xml index 4c9a796df64..3d2a80d1fee 100644 --- a/libmei/mei/develop/mei-verovio.xml +++ b/libmei/mei/mei-verovio.xml @@ -91,7 +91,7 @@ Specifies a generic MEI version label. - 5.0.0-dev + 5.0 MEI 2013 @@ -105,11 +105,20 @@ MEI 4.0.1 - - MEI basic + + MEI 5.0 - - Development version of MEI 5.0.0 + + MEI 5.0+basic + + + MEI 5.0+CMN + + + MEI 5.0+Mensural + + + MEI 5.0+Neumes @@ -243,7 +252,7 @@ - + @@ -259,7 +268,7 @@ - + @@ -296,7 +305,7 @@ - +

This element is necessary to allow round-tripping between page-based and score-based (regular) MEI.

diff --git a/libmei/mei/develop/mei-verovio_compiled.odd b/libmei/mei/mei-verovio_compiled.odd similarity index 99% rename from libmei/mei/develop/mei-verovio_compiled.odd rename to libmei/mei/mei-verovio_compiled.odd index 6f7ff7c7885..a3ca3632df4 100644 --- a/libmei/mei/develop/mei-verovio_compiled.odd +++ b/libmei/mei/mei-verovio_compiled.odd @@ -1,4 +1,4 @@ - + @@ -50,7 +50,7 @@ - + Written accidental values. @@ -125,6 +125,18 @@ Natural note lowered by quarter tone (natural modified by arrow). + + Double sharp note raised by quarter tone (double sharp modified by arrow). + + + Double sharp note lowered by quarter tone (double sharp modified by arrow). + + + Double flat note raised by quarter tone (double flat modified by arrow). + + + Double flat note lowered by quarter tone (double flat modified by arrow). + 1/4-tone flat accidental. @@ -235,6 +247,12 @@ Three quarter-tones flat. + + Five quarter-tones sharp. + + + Five quarter-tones flat. + @@ -3103,7 +3121,7 @@ - Staff location. The value '0' indicates the bottom line of the current staff; positive + Staff location. The value 0 indicates the bottom line of the current staff; positive values are used for positions above the bottom line and negative values for the positions below. For example, in treble clef, 1 = F4, 2 = G4, 3 = A4, etc. and -1 = D4, -2 = C4, and so on. @@ -3621,16 +3639,9 @@ Analytical domain attributes. + - - - Indicates major, minor, or other tonality. - - - - -
Used by staffDef and scoreDef to provide default values for attributes in the analytical domain that are related to key signatures. @@ -3723,6 +3734,7 @@ + @@ -3730,6 +3742,9 @@ Analytical domain attributes. Analytical domain attributes. + + + Analytical domain attributes. @@ -4220,20 +4235,8 @@ + - - - Indicates whether the tremolo is measured or unmeasured. - - - Measured tremolo. - - - Unmeasured tremolo. - - - - Analytical domain attributes in the CMN repertoire. @@ -4300,20 +4303,8 @@ + - - - Describes the style of the tremolo. - - - Measured tremolo. - - - Unmeasured tremolo. - - - - Attributes that indicate whether an event participates in a glissando. @@ -4772,7 +4763,7 @@ Visual domain attributes. - + Used by scoreDef and staffDef to provide default description of piano pedal @@ -4837,19 +4828,12 @@ Visual domain attributes. + - - - Determines whether to display guitar chord grids. - - - - - Logical domain attributes. @@ -4929,6 +4913,21 @@ + + Attributes describing the form of a tremolo. + + + Describes the style of the tremolo. + + + Measured tremolo. + + + Unmeasured tremolo. + + + + Attributes that describe measured tremolandi. @@ -6965,6 +6964,7 @@

The model of this element is based on the figDesc element of the Text Encoding Initiative (TEI).

Indicates the location of an inline graphic. + @@ -6992,17 +6992,7 @@ attributes. - - Indicates the upper-left corner x coordinate. - - - - - Indicates the upper-left corner y coordinate. - - - - +

The model of this element is based on the graphic element of the Text Encoding Initiative (TEI).

Contains text displayed in tabular form. @@ -7459,6 +7449,17 @@ +
+ Attributes whether an element is performed "attacca". + + + Indicates that the performance of the next musical division should begin immediately + following this one. + + + + + Gestural domain attributes. @@ -7538,15 +7539,9 @@ Gestural domain attributes. Gestural domain attributes. - - - Indicates that the performance of the next musical division should begin immediately - following this one. - - - - - + + + Gestural domain attributes. @@ -7774,28 +7769,8 @@ + - - - Records performed octave information that differs from the written value. - - - - - - Contains a performed pitch name that differs from the written value. - - - - - - pitch number - Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. - - - - - Gestural domain attributes. @@ -7815,6 +7790,7 @@ + @@ -7844,25 +7820,6 @@ necessary to record the written pitch and octave of the symbol for this note.

- - Records performed octave information that differs from the written value. - - - - - - Contains a performed pitch name that differs from the written value. - - - - - - pitch number - Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. - - - -
Gestural domain attributes. @@ -7915,6 +7872,29 @@ + + Gestural attributes about pitch. + + + Records performed octave information that differs from the written value. + + + + + + Contains a performed pitch name that differs from the written value. + + + + + + pitch number + Holds a pitch-to-number mapping, a base-40 or MIDI note number, for example. + + + + + Gestural domain attributes that describe the properties of a plica in the mensural repertoire. @@ -7960,15 +7940,9 @@ Gestural domain attributes. - - - Indicates that the performance of the next section should begin immediately following - this one. - - - - - + + + Gestural domain attributes. @@ -8603,7 +8577,7 @@ - Circumstances in which the element appears, an XPath expression. + Circumstances in which the attribute appears, an XPath expression. @@ -9213,16 +9187,12 @@ + - - Indicates major, minor, or other tonality. - - - - +

This element is used exclusively within bibliographic descriptions. Do not confuse this element with keySig, which is used within the body of an MEI file to record this data.

@@ -9924,14 +9894,7 @@ - - - - The watermark element may only appear as a - descendant of the physDesc element. - - - +

The facs attribute may be used to record the location of the watermark in a facsimile image.

@@ -11214,6 +11177,9 @@
Attributes that record visual details of neume notation. + + + @@ -11236,17 +11202,6 @@ - - Records direction of curvature. - - - Anti-clockwise curvature. - - - Clockwise curvature. - - - Pen stroke has an extension; specific to Hispanic notation. @@ -11304,6 +11259,39 @@ + + Attributes that specify the type of neumes. + + + Designation which characterizes the element in some sense, using any convenient + classification scheme or typology that employs single-token labels. + + + + + + + + + + + + + + + + + + + + + + + + + + + Logical domain attributes. @@ -11392,37 +11380,7 @@ - - Designation which characterizes the element in some sense, using any convenient - classification scheme or typology that employs single-token labels. - - - - - - - - - - - - - - - - - - - - - - - - - - - - neume component groupCollection of one or more neume components. + neume component groupCollection of one or more neume components. @@ -11447,37 +11405,7 @@ - - Designation which characterizes the element in some sense, using any convenient - classification scheme or typology that employs single-token labels. - - - - - - - - - - - - - - - - - - - - - - - - - - - - Oriscus. + Oriscus. @@ -12285,19 +12213,10 @@ This attribute class records the position of a feature within a two-dimensional coordinate system. + + + - - Indicates the upper-left corner x coordinate. - - - - - - Indicates the upper-left corner y coordinate. - - - - Indicates the lower-right corner x coordinate. @@ -12325,6 +12244,23 @@ + + This attribute class records the upper left position of a feature within a two-dimensional coordinate + system. + + + Indicates the upper-left corner x coordinate. + + + + + + Indicates the upper-left corner y coordinate. + + + + + Attributes that describe "cue-ness". @@ -12371,22 +12307,6 @@ - - Attributes that record the visual rendition of curves. - - - Describes the line style of a curve. - - - - - - Width of a curved line. - - - - - Logical domain attributes. @@ -12897,6 +12817,16 @@ + + Attributes for describing key mode. + + + Indicates major, minor, or other tonality. + + + + + Logical domain attributes. @@ -13066,15 +12996,20 @@ Attributes that record the basic visual rendition of lines. - - line form - Describes the line style of a line. - - - - - + + Describes the style of a line. + + + + + + Width of a line. + + + + + Describes the number of segments into which a dashed or dotted line may be divided, or the number of "peaks" of a wavy line; a pair of space-separated values (minimum and maximum, respectively) provides a range between which a rendering system-supplied value @@ -13094,12 +13029,6 @@ - - Width of a line. - - - - @@ -13409,7 +13338,7 @@ Specifies a generic MEI version label. - 5.0.0-dev + 5.0 MEI 2013 @@ -13423,11 +13352,20 @@ MEI 4.0.1 - - MEI basic + + MEI 5.0 + + + MEI 5.0+basic + + + MEI 5.0+CMN + + + MEI 5.0+Mensural - - Development version of MEI 5.0.0 + + MEI 5.0+Neumes @@ -13438,6 +13376,14 @@ + + + Level of duration at which the proportion given by the @num and @numbase ratio applies. + + + + + Attributes that provide information about a structure’s conformance to the prevailing meter. @@ -15230,7 +15176,7 @@ Allows one to signal to an application whether an element’s white space is "significant". The behavior of xml:space cascades to all descendant elements, but it can - be turned off locally by setting the xml:space attribute to the value "default". + be turned off locally by setting the xml:space attribute to the value default. Allows the application to handle white space as necessary. Not including an @@ -17075,15 +17021,11 @@ + - - Records horizontal alignment of the page footer. - - - - +

This element is used to capture the textual data that often appears in printed music. It may also be used for similarly formatted material in manuscripts. When used within pb, it records a temporary suspension of the pattern of @@ -17093,15 +17035,11 @@ + - - Records horizontal alignment of the page header. - - - - +

This element is used to capture the textual data that often appears in printed music. It may also be used for similarly formatted material in manuscripts. When used within pb, it records a temporary suspension of the pattern of @@ -17414,8 +17352,8 @@ - - + + @@ -18556,6 +18494,7 @@ + @@ -18591,18 +18530,6 @@ - - Visual form of the line. - - - - - - Width of the line. - - - - Visual domain attributes. @@ -18750,12 +18677,12 @@ attributes. + + - - Visual domain attributes. @@ -18875,12 +18802,27 @@ + + Attributes describing the direction of curvature. + + + Records direction of curvature. + + + Anti-clockwise curvature. + + + Clockwise curvature. + + + + Visual domain attributes. - + @@ -19111,6 +19053,16 @@ + + Visual domain attributes + + + Determines whether to display guitar chord grids. + + + + + Visual domain attributes. @@ -19368,6 +19320,7 @@ + @@ -19377,17 +19330,6 @@ - - Records direction of curvature. - - - Anti-clockwise curvature. - - - Clockwise curvature. - - - Indicates whether curve is closed. @@ -19404,12 +19346,12 @@ beats. + + - - Visual domain attributes. @@ -20003,12 +19945,12 @@ normal position) of the entire rendered slur/phrase mark. + + - - Visual domain attributes. @@ -20044,6 +19986,7 @@ + @@ -20058,12 +20001,6 @@ - - Determines whether to display guitar chord grids. - - - - Indicates the number of layers and their stem directions. @@ -20233,12 +20170,12 @@ beats. + + - - Visual domain attributes. @@ -20366,14 +20303,14 @@ - + Collects mdivbLike (mdiv beginning) elements. mdiv beginningA milestone element indicating the start of a new mdiv in page-based MEI. - + score beginningA milestone element indicating the start of a new score in page-based MEI. @@ -20385,7 +20322,7 @@ - +

This element is necessary to allow round-tripping between page-based and score-based (regular) MEI.

part beginningA milestone element indicating the start of a new part in page-based MEI. diff --git a/libmei/tools/cpp.py b/libmei/tools/cpp.py index d6f593416d6..aa4ff7b1fca 100644 --- a/libmei/tools/cpp.py +++ b/libmei/tools/cpp.py @@ -926,7 +926,7 @@ def create_att_datatypes(cpp_ns: str, schema, outdir: Path): val_prefix = vrv_getformattedvallist(list_type.rsplit('@')[0], list_type.rsplit('@')[1]) type_start_fmt = { - "meitype": list_type, + "meitype": list_type.replace("@", "\@"), "vrvtype": val_prefix, "enumtype": " : int8_t" if len(values) < 64 else "", "val_prefix": val_prefix diff --git a/setup.py b/setup.py index 8366bbc0ef5..fc1f38b2709 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ def get_commit(): """Call tools/get_git_commit.sh on any platform.""" if os.path.exists('./tools'): print('running tools/get_git_commit.sh') - os.system('bash -c "cd tools; ./get_git_commit.sh"') + os.system('sh -c "cd tools; ./get_git_commit.sh"') else: print('tools directory is missing') diff --git a/src/adjustaccidxfunctor.cpp b/src/adjustaccidxfunctor.cpp index ece6761c994..7bc8b01512d 100644 --- a/src/adjustaccidxfunctor.cpp +++ b/src/adjustaccidxfunctor.cpp @@ -10,6 +10,7 @@ //---------------------------------------------------------------------------- #include "doc.h" +#include "score.h" //---------------------------------------------------------------------------- @@ -41,7 +42,8 @@ FunctorCode AdjustAccidXFunctor::VisitAlignmentReference(AlignmentReference *ali if (accids.empty()) return FUNCTOR_SIBLINGS; assert(m_doc); - StaffDef *staffDef = m_doc->GetCurrentScoreDef()->GetStaffDef(alignmentReference->GetN()); + ScoreDef *scoreDef = m_doc->GetCorrespondingScore(alignmentReference)->GetScoreDef(); + StaffDef *staffDef = scoreDef->GetStaffDef(alignmentReference->GetN()); int staffSize = (staffDef && staffDef->HasScale()) ? staffDef->GetScale() : 100; std::sort(accids.begin(), accids.end(), AccidSpaceSort()); diff --git a/src/adjustarpegfunctor.cpp b/src/adjustarpegfunctor.cpp index 83e56f4cfab..6051efd924b 100644 --- a/src/adjustarpegfunctor.cpp +++ b/src/adjustarpegfunctor.cpp @@ -172,10 +172,10 @@ FunctorCode AdjustArpegFunctor::VisitMeasureEnd(Measure *measure) { if (!m_alignmentArpegTuples.empty()) { m_measureAligner = &measure->m_measureAligner; - // Process backwards on measure aligner - this->PushDirection(BACKWARD); + // Process backwards on measure aligner, then reset to previous direction + const bool previousDirection = this->SetDirection(BACKWARD); m_measureAligner->Process(*this); - this->PopDirection(); + this->SetDirection(previousDirection); m_alignmentArpegTuples.clear(); } diff --git a/src/adjustbeamsfunctor.cpp b/src/adjustbeamsfunctor.cpp index f0f130b9552..c887831d837 100644 --- a/src/adjustbeamsfunctor.cpp +++ b/src/adjustbeamsfunctor.cpp @@ -298,21 +298,12 @@ FunctorCode AdjustBeamsFunctor::VisitRest(Rest *rest) if (!m_outerBeam) return FUNCTOR_SIBLINGS; // Calculate possible overlap for the rest with beams - int leftMargin = 0, rightMargin = 0; const int beams = m_outerBeam->GetBeamPartDuration(rest, false) - DUR_4; const int beamWidth = m_outerBeam->m_beamWidth; - if (m_directionBias > 0) { - leftMargin = m_y1 - beams * beamWidth - rest->GetSelfTop(); - rightMargin = m_y2 - beams * beamWidth - rest->GetSelfTop(); - } - else { - leftMargin = rest->GetSelfBottom() - m_y1 - beams * beamWidth; - rightMargin = rest->GetSelfBottom() - m_y2 - beams * beamWidth; - } + const int overlapMargin = rest->Intersects(m_outerBeam, SELF, beams * beamWidth, true) * m_directionBias; // Adjust drawing location for the rest based on the overlap with beams. // Adjustment should be an even number, so that the rest is positioned properly - const int overlapMargin = std::min(leftMargin, rightMargin); if (overlapMargin >= 0) return FUNCTOR_CONTINUE; Staff *staff = rest->GetAncestorStaff(); @@ -344,11 +335,9 @@ FunctorCode AdjustBeamsFunctor::VisitRest(Rest *rest) } const int unit = m_doc->GetDrawingUnit(staff->m_drawingStaffSize); - const int unitChangeNumber = ((std::abs(overlapMargin) + unit / 6) / unit); - if (unitChangeNumber > 0) { - const int adjust = unitChangeNumber * unit * m_directionBias; - if (std::abs(adjust) > std::abs(m_overlapMargin)) m_overlapMargin = adjust; - } + const int unitChangeNumber = std::abs(overlapMargin) / unit + 1; + const int adjust = unitChangeNumber * unit * m_directionBias; + if (std::abs(adjust) > std::abs(m_overlapMargin)) m_overlapMargin = adjust; return FUNCTOR_CONTINUE; } diff --git a/src/adjustdotsfunctor.cpp b/src/adjustdotsfunctor.cpp index 749adcd8910..1f930da9a88 100644 --- a/src/adjustdotsfunctor.cpp +++ b/src/adjustdotsfunctor.cpp @@ -11,6 +11,7 @@ #include "doc.h" #include "elementpart.h" +#include "score.h" #include "staff.h" //---------------------------------------------------------------------------- @@ -101,7 +102,7 @@ FunctorCode AdjustDotsFunctor::VisitMeasure(Measure *measure) if (!measure->HasAlignmentRefWithMultipleLayers()) return FUNCTOR_SIBLINGS; Filters filters; - this->PushFilters(&filters); + Filters *previousFilters = this->SetFilters(&filters); std::vector::iterator iter; for (iter = m_staffNs.begin(); iter != m_staffNs.end(); ++iter) { @@ -118,14 +119,14 @@ FunctorCode AdjustDotsFunctor::VisitMeasure(Measure *measure) measure->m_measureAligner.Process(*this); } - this->PopFilters(); + this->SetFilters(previousFilters); return FUNCTOR_SIBLINGS; } FunctorCode AdjustDotsFunctor::VisitScore(Score *score) { - m_staffNs = m_doc->GetCurrentScoreDef()->GetStaffNs(); + m_staffNs = score->GetScoreDef()->GetStaffNs(); return FUNCTOR_CONTINUE; } diff --git a/src/adjustgracexposfunctor.cpp b/src/adjustgracexposfunctor.cpp index eda19401a21..85e4876cbb5 100644 --- a/src/adjustgracexposfunctor.cpp +++ b/src/adjustgracexposfunctor.cpp @@ -10,6 +10,7 @@ //---------------------------------------------------------------------------- #include "doc.h" +#include "score.h" //---------------------------------------------------------------------------- @@ -48,9 +49,9 @@ FunctorCode AdjustGraceXPosFunctor::VisitAlignment(Alignment *alignment) MeasureAligner *measureAligner = vrv_cast(alignment->GetFirstAncestor(MEASURE_ALIGNER)); assert(measureAligner); - this->PushDirection(BACKWARD); + const bool previousDirection = this->SetDirection(BACKWARD); Filters filters; - this->PushFilters(&filters); + Filters *previousFilters = this->SetFilters(&filters); std::vector::iterator iter; for (iter = m_staffNs.begin(); iter != m_staffNs.end(); ++iter) { @@ -108,8 +109,8 @@ FunctorCode AdjustGraceXPosFunctor::VisitAlignment(Alignment *alignment) } } - this->PopDirection(); - this->PopFilters(); + this->SetDirection(previousDirection); + this->SetFilters(previousFilters); // Change the flag back m_isGraceAlignment = false; @@ -141,15 +142,15 @@ FunctorCode AdjustGraceXPosFunctor::VisitAlignmentReference(AlignmentReference * // Because we are processing grace notes alignment backward (see VisitAlignment) we need // to process the children (LayerElement) "by hand" in FORWARD manner // (filters can be NULL because filtering was already applied in the parent) - this->PushDirection(FORWARD); - this->PushFilters(NULL); + const bool previousDirection = this->SetDirection(FORWARD); + Filters *previousFilters = this->SetFilters(NULL); for (auto child : alignmentReference->GetChildren()) { child->Process(*this); } - this->PopDirection(); - this->PopFilters(); + this->SetDirection(previousDirection); + this->SetFilters(previousFilters); return FUNCTOR_SIBLINGS; } @@ -205,7 +206,7 @@ FunctorCode AdjustGraceXPosFunctor::VisitMeasure(Measure *measure) m_rightDefaultAlignment = NULL; // We process it backward because we want to get the rightDefaultAlignment - this->PushDirection(BACKWARD); + const bool previousDirection = this->SetDirection(BACKWARD); measure->m_measureAligner.Process(*this); // We need to process the staves in the reverse order @@ -220,7 +221,7 @@ FunctorCode AdjustGraceXPosFunctor::VisitMeasure(Measure *measure) m_staffNs = staffNsReversed; m_measureTieEndpoints = measure->GetInternalTieEndpoints(); measure->m_measureAligner.Process(*this); - this->PopDirection(); + this->SetDirection(previousDirection); // Put params back m_staffNs = staffNs; @@ -230,7 +231,7 @@ FunctorCode AdjustGraceXPosFunctor::VisitMeasure(Measure *measure) FunctorCode AdjustGraceXPosFunctor::VisitScore(Score *score) { - m_staffNs = m_doc->GetCurrentScoreDef()->GetStaffNs(); + m_staffNs = score->GetScoreDef()->GetStaffNs(); return FUNCTOR_CONTINUE; } diff --git a/src/adjustlayersfunctor.cpp b/src/adjustlayersfunctor.cpp index 80d0c344b7f..058120c970c 100644 --- a/src/adjustlayersfunctor.cpp +++ b/src/adjustlayersfunctor.cpp @@ -10,6 +10,7 @@ //---------------------------------------------------------------------------- #include "doc.h" +#include "score.h" #include "staff.h" //---------------------------------------------------------------------------- @@ -124,7 +125,7 @@ FunctorCode AdjustLayersFunctor::VisitMeasure(Measure *measure) if (!measure->HasAlignmentRefWithMultipleLayers()) return FUNCTOR_SIBLINGS; Filters filters; - this->PushFilters(&filters); + Filters *previousFilters = this->SetFilters(&filters); std::vector::iterator iter; for (iter = m_staffNs.begin(); iter != m_staffNs.end(); ++iter) { @@ -141,14 +142,14 @@ FunctorCode AdjustLayersFunctor::VisitMeasure(Measure *measure) measure->m_measureAligner.Process(*this); } - this->PopFilters(); + this->SetFilters(previousFilters); return FUNCTOR_SIBLINGS; } FunctorCode AdjustLayersFunctor::VisitScore(Score *score) { - m_staffNs = m_doc->GetCurrentScoreDef()->GetStaffNs(); + m_staffNs = score->GetScoreDef()->GetStaffNs(); return FUNCTOR_CONTINUE; } diff --git a/src/adjustslursfunctor.cpp b/src/adjustslursfunctor.cpp index 2eac8fdb01e..34d5bb61c6b 100644 --- a/src/adjustslursfunctor.cpp +++ b/src/adjustslursfunctor.cpp @@ -27,6 +27,13 @@ namespace vrv { AdjustSlursFunctor::AdjustSlursFunctor(Doc *doc) : DocFunctor(doc) { m_crossStaffSlurs = false; + this->ResetCurrent(); +} + +void AdjustSlursFunctor::ResetCurrent() +{ + m_currentCurve = NULL; + m_currentSlur = NULL; } FunctorCode AdjustSlursFunctor::VisitStaffAlignment(StaffAlignment *staffAlignment) @@ -42,22 +49,26 @@ FunctorCode AdjustSlursFunctor::VisitStaffAlignment(StaffAlignment *staffAlignme if (!positioner->GetObject()->Is({ PHRASE, SLUR })) continue; Slur *slur = vrv_cast(positioner->GetObject()); assert(slur); + m_currentSlur = slur; assert(positioner->Is(FLOATING_CURVE_POSITIONER)); FloatingCurvePositioner *curve = vrv_cast(positioner); assert(curve); + m_currentCurve = curve; // Skip if no content bounding box is available if (!curve->HasContentBB()) continue; positioners.push_back(curve); - slur->AdjustSlur(m_doc, curve, unit); + this->AdjustSlur(unit); if (curve->IsCrossStaff()) { m_crossStaffSlurs = true; } } + this->ResetCurrent(); + // Detection of inner slurs std::map innerCurveMap; for (int i = 0; i < (int)positioners.size(); ++i) { @@ -104,9 +115,14 @@ FunctorCode AdjustSlursFunctor::VisitStaffAlignment(StaffAlignment *staffAlignme for (const auto &mapEntry : innerCurveMap) { Slur *slur = vrv_cast(mapEntry.first->GetObject()); assert(slur); - slur->AdjustOuterSlur(m_doc, mapEntry.first, mapEntry.second, unit); + m_currentCurve = mapEntry.first; + m_currentSlur = slur; + + this->AdjustOuterSlur(mapEntry.second, unit); } + this->ResetCurrent(); + return FUNCTOR_SIBLINGS; } @@ -117,4 +133,834 @@ FunctorCode AdjustSlursFunctor::VisitSystem(System *system) return FUNCTOR_SIBLINGS; } +void AdjustSlursFunctor::AdjustSlur(int unit) const +{ + assert(m_currentCurve); + assert(m_currentSlur); + + Point points[4]; + m_currentCurve->GetPoints(points); + BezierCurve bezier(points[0], points[1], points[2], points[3]); + m_currentSlur->InitBezierControlSides(bezier, m_currentCurve->GetDir()); + bezier.UpdateControlPointParams(); + + const int margin = m_doc->GetOptions()->m_slurMargin.GetValue() * unit; + const double flexibility = m_doc->GetOptions()->m_slurEndpointFlexibility.GetValue(); + const double symmetry = m_doc->GetOptions()->m_slurSymmetry.GetValue(); + + // STEP 1: Filter spanned elements and discard certain bounding boxes even though they collide + this->FilterSpannedElements(bezier, margin); + + // STEP 2: Detect collisions near the endpoints and switch to secondary endpoints if necessary + NearEndCollision nearEndCollision = this->DetectCollisionsNearEnd(bezier, margin); + m_currentSlur->CalcInitialCurve(m_doc, m_currentCurve, &nearEndCollision); + if (nearEndCollision.endPointsAdjusted) { + m_currentCurve->GetPoints(points); + bezier.p1 = points[0]; + bezier.c1 = points[1]; + bezier.c2 = points[2]; + bezier.p2 = points[3]; + bezier.UpdateControlPointParams(); + m_currentSlur->CalcSpannedElements(m_currentCurve); + this->FilterSpannedElements(bezier, margin); + } + else { + m_currentCurve->UpdatePoints(bezier); + } + + // STEP 3: Calculate the vertical adjustment of endpoints. This shifts the slur vertically. + // Only collisions near the endpoints are taken into account. + int endPointShiftLeft = 0; + int endPointShiftRight = 0; + std::tie(endPointShiftLeft, endPointShiftRight) = this->CalcEndPointShift(bezier, flexibility, margin); + this->ApplyEndPointShift(bezier, endPointShiftLeft, endPointShiftRight); + + // Special handling if bulge is prescribed from here on + if (m_currentSlur->HasBulge()) { + this->AdjustSlurFromBulge(bezier, unit); + return; + } + + // STEP 4: Calculate the horizontal offset of the control points. + // The idea is to shift control points to the outside if there is an obstacle in the vicinity of the corresponding + // endpoint. For C1 we consider the largest angle <)BP1P2 where B is a colliding left bounding box corner and choose + // C1 in this direction. Similar for C2. + if (this->AllowControlOffsetAdjustment(bezier, symmetry, unit)) { + bool ok = false; + int controlPointOffsetLeft = 0; + int controlPointOffsetRight = 0; + std::tie(ok, controlPointOffsetLeft, controlPointOffsetRight) = this->CalcControlPointOffset(bezier, margin); + if (ok) { + bezier.SetLeftControlOffset(controlPointOffsetLeft); + bezier.SetRightControlOffset(controlPointOffsetRight); + bezier.UpdateControlPoints(); + m_currentCurve->UpdatePoints(bezier); + } + } + + // STEP 5: Calculate the vertical shift of the control points. + // For each colliding bounding box we formulate a constraint ax + by >= c + // where x, y denote the vertical adjustments of the control points and c is the size of the collision. + // The coefficients a, b are calculated from the Bezier curve equation. + // After collecting all constraints we calculate a solution. + const ControlPointAdjustment adjustment = this->CalcControlPointVerticalShift(bezier, symmetry, margin); + const int leftSign = (bezier.IsLeftControlAbove() == adjustment.moveUpwards) ? 1 : -1; + bezier.SetLeftControlHeight(bezier.GetLeftControlHeight() + leftSign * adjustment.leftShift); + const int rightSign = (bezier.IsRightControlAbove() == adjustment.moveUpwards) ? 1 : -1; + bezier.SetRightControlHeight(bezier.GetRightControlHeight() + rightSign * adjustment.rightShift); + bezier.UpdateControlPoints(); + m_currentCurve->UpdatePoints(bezier); + m_currentCurve->SetRequestedStaffSpace(adjustment.requestedStaffSpace); + + // STEP 6: Adjust the slur shape + // Through the control point adjustments in step 4 and 5 it can happen that the slur looses its desired shape. + // We correct the shape if the slur is too flat or not convex. + if (m_currentCurve->GetDir() != curvature_CURVEDIR_mixed) { + this->AdjustSlurShape(bezier, m_currentCurve->GetDir(), unit); + m_currentCurve->UpdatePoints(bezier); + } + + // Since we are going to redraw it, reset its bounding box + m_currentCurve->ResetBoundingBox(); +} + +void AdjustSlursFunctor::AdjustOuterSlur(const ArrayOfFloatingCurvePositioners &innerCurves, int unit) const +{ + assert(m_currentCurve); + assert(m_currentSlur); + + Point points[4]; + m_currentCurve->GetPoints(points); + BezierCurve bezier(points[0], points[1], points[2], points[3]); + m_currentSlur->InitBezierControlSides(bezier, m_currentCurve->GetDir()); + bezier.UpdateControlPointParams(); + + const int margin = m_doc->GetOptions()->m_slurMargin.GetValue() * unit; + const double flexibility = m_doc->GetOptions()->m_slurEndpointFlexibility.GetValue(); + const double symmetry = m_doc->GetOptions()->m_slurSymmetry.GetValue(); + + // STEP 1: Calculate the vertical adjustment of endpoints. This shifts the slur vertically. + // Only collisions near the endpoints are taken into account. + int endPointShiftLeft = 0; + int endPointShiftRight = 0; + std::tie(endPointShiftLeft, endPointShiftRight) = this->CalcEndPointShift(bezier, innerCurves, flexibility, margin); + this->ApplyEndPointShift(bezier, endPointShiftLeft, endPointShiftRight); + + // STEP 2: Calculate the vertical shift of the control points. + // For each inner slur we formulate some constraints ax + by >= c + // where x, y denote the vertical adjustments of the control points and c is the size of the collision. + // The coefficients a, b are calculated from the Bezier curve equation. + // After collecting all constraints we calculate a solution. + const ControlPointAdjustment adjustment = this->CalcControlPointShift(bezier, innerCurves, symmetry, margin); + bezier.SetLeftControlHeight(bezier.GetLeftControlHeight() + adjustment.leftShift); + bezier.SetRightControlHeight(bezier.GetRightControlHeight() + adjustment.rightShift); + bezier.UpdateControlPoints(); + m_currentCurve->UpdatePoints(bezier); + + // STEP 3: Adjust the slur shape + // We correct the shape if the slur is too flat or not convex. + if (m_currentCurve->GetDir() != curvature_CURVEDIR_mixed) { + this->AdjustSlurShape(bezier, m_currentCurve->GetDir(), unit); + m_currentCurve->UpdatePoints(bezier); + } + + // Since we are going to redraw it, reset its bounding box + m_currentCurve->ResetBoundingBox(); +} + +void AdjustSlursFunctor::FilterSpannedElements(const BezierCurve &bezierCurve, int margin) const +{ + if (bezierCurve.p1.x >= bezierCurve.p2.x) return; + + const int dist = bezierCurve.p2.x - bezierCurve.p1.x; + + const ArrayOfCurveSpannedElements *spannedElements = m_currentCurve->GetSpannedElements(); + + for (CurveSpannedElement *spannedElement : *spannedElements) { + + if (spannedElement->m_discarded) { + continue; + } + + bool discard = false; + const int intersection = m_currentCurve->CalcDirectionalAdjustment( + spannedElement->m_boundingBox, spannedElement->m_isBelow, discard, margin); + const int xMiddle + = (spannedElement->m_boundingBox->GetSelfLeft() + spannedElement->m_boundingBox->GetSelfRight()) / 2.0; + const float distanceRatio = float(xMiddle - bezierCurve.p1.x) / float(dist); + + // Check if obstacles completely lie on the other side of the slur + const int elementHeight + = std::abs(spannedElement->m_boundingBox->GetSelfTop() - spannedElement->m_boundingBox->GetSelfBottom()); + if (intersection > elementHeight + 4 * margin) { + // Ignore elements in a different layer near the endpoints + const LayerElement *layerElement = dynamic_cast(spannedElement->m_boundingBox); + if (distanceRatio < 0.05) { + spannedElement->m_discarded = layerElement + ? (layerElement->GetOriginalLayerN() != m_currentSlur->GetStart()->GetOriginalLayerN()) + : true; + } + else if (distanceRatio > 0.95) { + spannedElement->m_discarded = layerElement + ? (layerElement->GetOriginalLayerN() != m_currentSlur->GetEnd()->GetOriginalLayerN()) + : true; + } + // Ignore tuplet numbers + if (layerElement && layerElement->Is(TUPLET_NUM)) { + spannedElement->m_discarded = true; + } + } + } +} + +NearEndCollision AdjustSlursFunctor::DetectCollisionsNearEnd(const BezierCurve &bezierCurve, int margin) const +{ + NearEndCollision nearEndCollision({ 0.0, 0.0, false }); + if (bezierCurve.p1.x >= bezierCurve.p2.x) return nearEndCollision; + + const ArrayOfCurveSpannedElements *spannedElements = m_currentCurve->GetSpannedElements(); + for (CurveSpannedElement *spannedElement : *spannedElements) { + if (spannedElement->m_discarded) { + continue; + } + + bool discard = false; + int intersectionLeft, intersectionRight; + std::tie(intersectionLeft, intersectionRight) = m_currentCurve->CalcDirectionalLeftRightAdjustment( + spannedElement->m_boundingBox, spannedElement->m_isBelow, discard, margin); + + if ((intersectionLeft > 0) || (intersectionRight > 0)) { + Point points[4]; + points[0] = bezierCurve.p1; + points[1] = bezierCurve.c1; + points[2] = bezierCurve.c2; + points[3] = bezierCurve.p2; + + // Adjust the collision metrics + const int xLeft = std::max(bezierCurve.p1.x, spannedElement->m_boundingBox->GetSelfLeft()); + Point pLeft(xLeft, BoundingBox::CalcBezierAtPosition(points, xLeft)); + double distStart = std::max(BoundingBox::CalcDistance(bezierCurve.p1, pLeft), 1.0); + double distEnd = std::max(BoundingBox::CalcDistance(bezierCurve.p2, pLeft), 1.0); + nearEndCollision.metricAtStart = std::max(intersectionLeft / distStart, nearEndCollision.metricAtStart); + nearEndCollision.metricAtEnd = std::max(intersectionLeft / distEnd, nearEndCollision.metricAtEnd); + + const int xRight = std::min(bezierCurve.p2.x, spannedElement->m_boundingBox->GetSelfRight()); + Point pRight(xRight, BoundingBox::CalcBezierAtPosition(points, xRight)); + distStart = std::max(BoundingBox::CalcDistance(bezierCurve.p1, pRight), 1.0); + distEnd = std::max(BoundingBox::CalcDistance(bezierCurve.p2, pRight), 1.0); + nearEndCollision.metricAtStart = std::max(intersectionRight / distStart, nearEndCollision.metricAtStart); + nearEndCollision.metricAtEnd = std::max(intersectionRight / distEnd, nearEndCollision.metricAtEnd); + } + } + + return nearEndCollision; +} + +std::pair AdjustSlursFunctor::CalcEndPointShift( + const BezierCurve &bezierCurve, double flexibility, int margin) const +{ + if (bezierCurve.p1.x >= bezierCurve.p2.x) return { 0, 0 }; + + int shiftLeft = 0; + int shiftRight = 0; + + const int dist = bezierCurve.p2.x - bezierCurve.p1.x; + + const ArrayOfCurveSpannedElements *spannedElements = m_currentCurve->GetSpannedElements(); + for (CurveSpannedElement *spannedElement : *spannedElements) { + + if (spannedElement->m_discarded) { + continue; + } + + bool discard = false; + int intersectionLeft, intersectionRight; + std::tie(intersectionLeft, intersectionRight) = m_currentCurve->CalcDirectionalLeftRightAdjustment( + spannedElement->m_boundingBox, spannedElement->m_isBelow, discard, margin); + + if (discard) { + spannedElement->m_discarded = true; + continue; + } + + if ((intersectionLeft > 0) || (intersectionRight > 0)) { + // Now apply the intersections on the left and right hand side of the bounding box + const int xLeft = std::max(bezierCurve.p1.x, spannedElement->m_boundingBox->GetSelfLeft()); + const float distanceRatioLeft = float(xLeft - bezierCurve.p1.x) / float(dist); + this->ShiftEndPoints(shiftLeft, shiftRight, distanceRatioLeft, intersectionLeft, flexibility, + spannedElement->m_isBelow, m_currentCurve->m_spanningType); + + const int xRight = std::min(bezierCurve.p2.x, spannedElement->m_boundingBox->GetSelfRight()); + const float distanceRatioRight = float(xRight - bezierCurve.p1.x) / float(dist); + this->ShiftEndPoints(shiftLeft, shiftRight, distanceRatioRight, intersectionRight, flexibility, + spannedElement->m_isBelow, m_currentCurve->m_spanningType); + } + } + + return { shiftLeft, shiftRight }; +} + +void AdjustSlursFunctor::ApplyEndPointShift( + BezierCurve &bezierCurve, int endPointShiftLeft, int endPointShiftRight) const +{ + if ((endPointShiftLeft != 0) || (endPointShiftRight != 0)) { + const int signLeft = bezierCurve.IsLeftControlAbove() ? 1 : -1; + const int signRight = bezierCurve.IsRightControlAbove() ? 1 : -1; + bezierCurve.p1.y += signLeft * endPointShiftLeft; + bezierCurve.p2.y += signRight * endPointShiftRight; + if (bezierCurve.p1.x != bezierCurve.p2.x) { + double lambda1, lambda2; + std::tie(lambda1, lambda2) = bezierCurve.EstimateCurveParamForControlPoints(); + bezierCurve.c1.y + += signLeft * (1.0 - lambda1) * endPointShiftLeft + signRight * lambda1 * endPointShiftRight; + bezierCurve.c2.y + += signLeft * (1.0 - lambda2) * endPointShiftLeft + signRight * lambda2 * endPointShiftRight; + } + bezierCurve.UpdateControlPointParams(); + m_currentCurve->UpdatePoints(bezierCurve); + } +} + +void AdjustSlursFunctor::AdjustSlurFromBulge(BezierCurve &bezierCurve, int unit) const +{ + if (bezierCurve.p1.x >= bezierCurve.p2.x) return; + + data_BULGE bulge = m_currentSlur->GetBulge(); + + // Filter admissible values + bulge.erase(std::remove_if(bulge.begin(), bulge.end(), + [](const data_BULGE::value_type &entry) { + return ((entry.first <= 0.0) || (entry.second <= 0.0) || (entry.second >= 100.0)); + }), + bulge.end()); + + // Get the minimal and maximal lambda + double lambdaMin = 0.66; + double lambdaMax = 0.33; + for (const data_BULGE::value_type &bulgeEntry : bulge) { + const double lambda = bulgeEntry.second / 100.0; + lambdaMin = std::min(lambda, lambdaMin); + lambdaMax = std::max(lambda, lambdaMax); + } + + // Horizontal control point adjustment + lambdaMin /= 2.0; + lambdaMax = 1.0 - (1.0 - lambdaMax) / 2.0; + const double xMin = (1.0 - lambdaMin) * bezierCurve.p1.x + lambdaMin * bezierCurve.p2.x; + const double xMax = (1.0 - lambdaMax) * bezierCurve.p1.x + lambdaMax * bezierCurve.p2.x; + bezierCurve.SetLeftControlOffset(xMin - bezierCurve.p1.x); + bezierCurve.SetRightControlOffset(bezierCurve.p2.x - xMax); + bezierCurve.UpdateControlPoints(); + m_currentCurve->UpdatePoints(bezierCurve); + + // Generate a control point constraint for each bulge entry + std::list constraints; + Point points[4]; + points[0] = bezierCurve.p1; + points[1] = bezierCurve.c1; + points[2] = bezierCurve.c2; + points[3] = bezierCurve.p2; + + for (const data_BULGE::value_type &bulgeEntry : bulge) { + const double lambda = bulgeEntry.second / 100.0; + const double x = (1.0 - lambda) * bezierCurve.p1.x + lambda * bezierCurve.p2.x; + const double t = BoundingBox::CalcBezierParamAtPosition(points, x); + constraints.push_back({ 3.0 * pow(1.0 - t, 2.0) * t, 3.0 * (1.0 - t) * pow(t, 2.0), bulgeEntry.first * unit }); + } + + // Solve these constraints and calculate the vertical control point adjustment + int leftShift = 0; + int rightShift = 0; + std::tie(leftShift, rightShift) = this->SolveControlPointConstraints(constraints); + bezierCurve.SetLeftControlHeight(bezierCurve.GetLeftControlHeight() + leftShift); + bezierCurve.SetRightControlHeight(bezierCurve.GetRightControlHeight() + rightShift); + bezierCurve.UpdateControlPoints(); + m_currentCurve->UpdatePoints(bezierCurve); + + // Prevent awkward slur shapes + this->AdjustSlurShape(bezierCurve, m_currentCurve->GetDir(), unit); + m_currentCurve->UpdatePoints(bezierCurve); + + // Since we are going to redraw it, reset its bounding box + m_currentCurve->ResetBoundingBox(); +} + +bool AdjustSlursFunctor::AllowControlOffsetAdjustment(const BezierCurve &bezierCurve, double symmetry, int unit) const +{ + const double distance = BoundingBox::CalcDistance(bezierCurve.p1, bezierCurve.p2); + + return (distance > symmetry * 40 * unit); +} + +std::tuple AdjustSlursFunctor::CalcControlPointOffset(const BezierCurve &bezierCurve, int margin) const +{ + if (bezierCurve.p1.x >= bezierCurve.p2.x) return { false, 0, 0 }; + + // Initially we start with the slopes of the lines P1-C1 and P2-C2 + double leftSlopeMax = std::abs(BoundingBox::CalcSlope(bezierCurve.p1, bezierCurve.c1)); + double rightSlopeMax = std::abs(BoundingBox::CalcSlope(bezierCurve.p2, bezierCurve.c2)); + const ArrayOfCurveSpannedElements *spannedElements = m_currentCurve->GetSpannedElements(); + for (CurveSpannedElement *spannedElement : *spannedElements) { + + if (spannedElement->m_discarded) { + continue; + } + + const int bbY = spannedElement->m_isBelow ? spannedElement->m_boundingBox->GetSelfTop() + : spannedElement->m_boundingBox->GetSelfBottom(); + const Point pLeft = { spannedElement->m_boundingBox->GetSelfLeft(), bbY }; + const Point pRight = { spannedElement->m_boundingBox->GetSelfRight(), bbY }; + + // Prefer the (increased) slope of P1-B1, if larger + // B1 is the upper left bounding box corner of a colliding obstacle + if ((pLeft.x > bezierCurve.p1.x + margin) && (bezierCurve.IsLeftControlAbove() == spannedElement->m_isBelow)) { + const double slope = BoundingBox::CalcSlope(bezierCurve.p1, pLeft); + if ((slope > 0.0) && bezierCurve.IsLeftControlAbove()) { + const double adjustedSlope = this->RotateSlope(slope, 10.0, 2.5, true); + leftSlopeMax = std::max(leftSlopeMax, adjustedSlope); + } + if ((slope < 0.0) && !bezierCurve.IsLeftControlAbove()) { + const double adjustedSlope = this->RotateSlope(-slope, 10.0, 2.5, true); + leftSlopeMax = std::max(leftSlopeMax, adjustedSlope); + } + } + + // Prefer the (increased) slope of P2-B2, if larger + // B2 is the upper right bounding box corner of a colliding obstacle + if ((pRight.x < bezierCurve.p2.x - margin) + && (bezierCurve.IsRightControlAbove() == spannedElement->m_isBelow)) { + const double slope = BoundingBox::CalcSlope(bezierCurve.p2, pRight); + if ((slope < 0.0) && bezierCurve.IsRightControlAbove()) { + const double adjustedSlope = this->RotateSlope(-slope, 10.0, 2.5, true); + rightSlopeMax = std::max(rightSlopeMax, adjustedSlope); + } + if ((slope > 0.0) && !bezierCurve.IsRightControlAbove()) { + const double adjustedSlope = this->RotateSlope(slope, 10.0, 2.5, true); + rightSlopeMax = std::max(rightSlopeMax, adjustedSlope); + } + } + } + + if ((leftSlopeMax == 0.0) || (rightSlopeMax == 0.0)) return { false, 0, 0 }; + + // Calculate offset from extremal slope, but use 1/20 of horizontal distance as minimum + const int minOffset = (bezierCurve.p2.x - bezierCurve.p1.x) / 20; + int leftOffset = minOffset; + if (bezierCurve.GetLeftControlOffset() > 0) { + leftOffset = std::max(leftOffset, std::abs(bezierCurve.GetLeftControlHeight()) / leftSlopeMax); + } + int rightOffset = minOffset; + if (bezierCurve.GetRightControlOffset() > 0) { + rightOffset = std::max(rightOffset, std::abs(bezierCurve.GetRightControlHeight()) / rightSlopeMax); + } + + return { true, leftOffset, rightOffset }; +} + +ControlPointAdjustment AdjustSlursFunctor::CalcControlPointVerticalShift( + const BezierCurve &bezierCurve, double symmetry, int margin) const +{ + ControlPointAdjustment adjustment{ 0, 0, false, 0 }; + if (bezierCurve.p1.x >= bezierCurve.p2.x) return adjustment; + + std::list aboveConstraints; + std::list belowConstraints; + int maxIntersectionAbove = 0; + int maxIntersectionBelow = 0; + + const int dist = bezierCurve.p2.x - bezierCurve.p1.x; + + const ArrayOfCurveSpannedElements *spannedElements = m_currentCurve->GetSpannedElements(); + + for (CurveSpannedElement *spannedElement : *spannedElements) { + + if (spannedElement->m_discarded) { + continue; + } + + bool discard = false; + int intersectionLeft, intersectionRight; + std::tie(intersectionLeft, intersectionRight) = m_currentCurve->CalcDirectionalLeftRightAdjustment( + spannedElement->m_boundingBox, spannedElement->m_isBelow, discard, margin); + + if (discard) { + spannedElement->m_discarded = true; + continue; + } + + std::list &constraints + = spannedElement->m_isBelow ? belowConstraints : aboveConstraints; + int &maxIntersection = spannedElement->m_isBelow ? maxIntersectionBelow : maxIntersectionAbove; + + if ((intersectionLeft > 0) || (intersectionRight > 0)) { + Point points[4]; + points[0] = bezierCurve.p1; + points[1] = bezierCurve.c1; + points[2] = bezierCurve.c2; + points[3] = bezierCurve.p2; + + // Add constraint for the left boundary of the colliding bounding box + const int xLeft = std::max(bezierCurve.p1.x, spannedElement->m_boundingBox->GetSelfLeft()); + float distanceRatio = float(xLeft - bezierCurve.p1.x) / float(dist); + // Ignore obstacles close to the endpoints, because this would result in very large shifts + if ((std::abs(0.5 - distanceRatio) < 0.45) && (intersectionLeft > 0)) { + const double t = BoundingBox::CalcBezierParamAtPosition(points, xLeft); + constraints.push_back( + { 3.0 * pow(1.0 - t, 2.0) * t, 3.0 * (1.0 - t) * pow(t, 2.0), double(intersectionLeft) }); + maxIntersection = std::max(maxIntersection, intersectionLeft); + } + + // Add constraint for the right boundary of the colliding bounding box + const int xRight = std::min(bezierCurve.p2.x, spannedElement->m_boundingBox->GetSelfRight()); + distanceRatio = float(xRight - bezierCurve.p1.x) / float(dist); + // Ignore obstacles close to the endpoints, because this would result in very large shifts + if ((std::abs(0.5 - distanceRatio) < 0.45) && (intersectionRight > 0)) { + const double t = BoundingBox::CalcBezierParamAtPosition(points, xRight); + constraints.push_back( + { 3.0 * pow(1.0 - t, 2.0) * t, 3.0 * (1.0 - t) * pow(t, 2.0), double(intersectionRight) }); + maxIntersection = std::max(maxIntersection, intersectionRight); + } + } + } + + // Solve the constraints and calculate the adjustment + if (maxIntersectionAbove > maxIntersectionBelow) { + std::tie(adjustment.leftShift, adjustment.rightShift) + = this->SolveControlPointConstraints(aboveConstraints, symmetry); + adjustment.moveUpwards = false; + } + else { + std::tie(adjustment.leftShift, adjustment.rightShift) + = this->SolveControlPointConstraints(belowConstraints, symmetry); + adjustment.moveUpwards = true; + } + + // Determine the requested staff space + if (bezierCurve.IsLeftControlAbove() && !bezierCurve.IsRightControlAbove()) { + adjustment.requestedStaffSpace = std::max(bezierCurve.p1.y - bezierCurve.p2.y + 6 * margin, 0); + } + else if (!bezierCurve.IsLeftControlAbove() && bezierCurve.IsRightControlAbove()) { + adjustment.requestedStaffSpace = std::max(bezierCurve.p2.y - bezierCurve.p1.y + 6 * margin, 0); + } + if ((maxIntersectionAbove > 0) && (maxIntersectionBelow > 0)) { + adjustment.requestedStaffSpace + = std::max(adjustment.requestedStaffSpace, maxIntersectionAbove + maxIntersectionBelow); + } + + return adjustment; +} + +std::pair AdjustSlursFunctor::SolveControlPointConstraints( + const std::list &constraints, double symmetry) const +{ + if (constraints.empty()) return { 0, 0 }; + + // Each constraint corresponds to a halfplane in the upper right quadrant. + // We consider the line through the origin orthogonal to the halfplane's boundary + // and average the slopes of these orthogonal lines. + double weightSum = 0.0; + double weightedAngleSum = 0.0; + for (const ControlPointConstraint &constraint : constraints) { + // Use the distance of the halfplane's boundary to the origin as weight + const double weight = constraint.c / std::hypot(constraint.a, constraint.b); + weightedAngleSum += weight * atan(constraint.b / constraint.a); + weightSum += weight; + } + // Depending on symmetry we want the angle to be near PI/4 + double angle = weightedAngleSum / weightSum; + angle = std::max(symmetry * M_PI / 4.0, angle); + angle = std::min((2.0 - symmetry) * M_PI / 4.0, angle); + const double slope = tan(angle); + + // Now follow the line with the averaged slope until we have hit all halfplanes. + // For each constraint we must solve: slope * x = c/b - a/b * x + double xMax = 0.0; + for (const ControlPointConstraint &constraint : constraints) { + const double x = constraint.c / (constraint.a + slope * constraint.b); + xMax = std::max(xMax, x); + } + + // The point which hits the last halfplane is the desired solution. + return { xMax, slope * xMax }; +} + +void AdjustSlursFunctor::AdjustSlurShape(BezierCurve &bezierCurve, curvature_CURVEDIR dir, int unit) const +{ + if (bezierCurve.p1.x >= bezierCurve.p2.x) return; + + // Normalize the slur via rotation (such that p1-p2 is horizontal) + const float angle = atan2(bezierCurve.p2.y - bezierCurve.p1.y, bezierCurve.p2.x - bezierCurve.p1.x); + bezierCurve.Rotate(-angle, bezierCurve.p1); + bezierCurve.UpdateControlPointParams(); + + // *** STEP 1: Ensure MINIMAL HEIGHT *** + // <)C1P1P2 should be at least 30 degrees, but allow smaller angles if the midpoint would be lifted more than 6 MEI + // units + // Similar for <)P1P2C2 + const int sign = (dir == curvature_CURVEDIR_above) ? 1 : -1; + const Point shiftedMidpoint( + (bezierCurve.p1.x + bezierCurve.p2.x) / 2, (bezierCurve.p1.y + bezierCurve.p2.y) / 2 + sign * 6 * unit); + const float minAngle = this->GetMinControlPointAngle(bezierCurve, angle / M_PI * 180.0, unit); + const bool ignoreLeft = (bezierCurve.c1.x <= bezierCurve.p1.x); + const bool ignoreRight = (bezierCurve.c2.x >= bezierCurve.p2.x); + double slopeLeft = BoundingBox::CalcSlope(bezierCurve.p1, bezierCurve.c1); + double slopeRight = BoundingBox::CalcSlope(bezierCurve.p2, bezierCurve.c2); + const double slopeBase = BoundingBox::CalcSlope(bezierCurve.p1, bezierCurve.p2); + + if (dir == curvature_CURVEDIR_above) { + double minSlopeLeft = this->RotateSlope(slopeBase, minAngle, 1.0, true); + minSlopeLeft = std::min(minSlopeLeft, BoundingBox::CalcSlope(bezierCurve.p1, shiftedMidpoint)); + slopeLeft = std::max(slopeLeft, minSlopeLeft); + double minSlopeRight = this->RotateSlope(slopeBase, minAngle, 1.0, false); + minSlopeRight = std::max(minSlopeRight, BoundingBox::CalcSlope(bezierCurve.p2, shiftedMidpoint)); + slopeRight = std::min(slopeRight, minSlopeRight); + } + else if (dir == curvature_CURVEDIR_below) { + double minSlopeLeft = this->RotateSlope(slopeBase, minAngle, 1.0, false); + minSlopeLeft = std::max(minSlopeLeft, BoundingBox::CalcSlope(bezierCurve.p1, shiftedMidpoint)); + slopeLeft = std::min(slopeLeft, minSlopeLeft); + double minSlopeRight = this->RotateSlope(slopeBase, minAngle, 1.0, true); + minSlopeRight = std::min(minSlopeRight, BoundingBox::CalcSlope(bezierCurve.p2, shiftedMidpoint)); + slopeRight = std::max(slopeRight, minSlopeRight); + } + + // Update control points + if (!ignoreLeft) bezierCurve.SetLeftControlHeight(slopeLeft * sign * bezierCurve.GetLeftControlOffset()); + if (!ignoreRight) bezierCurve.SetRightControlHeight(slopeRight * -sign * bezierCurve.GetRightControlOffset()); + bezierCurve.UpdateControlPoints(); + + // *** STEP 2: Ensure CONVEXITY *** + // <)C1P1C2 and <)C1P2C2 should be at least 3 degrees + if (dir == curvature_CURVEDIR_above) { + const double minSlopeLeft + = this->RotateSlope(BoundingBox::CalcSlope(bezierCurve.p1, bezierCurve.c2), 3.0, 10.0, true); + slopeLeft = std::max(slopeLeft, minSlopeLeft); + const double minSlopeRight + = this->RotateSlope(BoundingBox::CalcSlope(bezierCurve.p2, bezierCurve.c1), 3.0, 10.0, false); + slopeRight = std::min(slopeRight, minSlopeRight); + } + else if (dir == curvature_CURVEDIR_below) { + const double minSlopeLeft + = this->RotateSlope(BoundingBox::CalcSlope(bezierCurve.p1, bezierCurve.c2), 3.0, 10.0, false); + slopeLeft = std::min(slopeLeft, minSlopeLeft); + const double minSlopeRight + = this->RotateSlope(BoundingBox::CalcSlope(bezierCurve.p2, bezierCurve.c1), 3.0, 10.0, true); + slopeRight = std::max(slopeRight, minSlopeRight); + } + + // Update control points + if (!ignoreLeft) bezierCurve.SetLeftControlHeight(slopeLeft * sign * bezierCurve.GetLeftControlOffset()); + if (!ignoreRight) bezierCurve.SetRightControlHeight(slopeRight * -sign * bezierCurve.GetRightControlOffset()); + bezierCurve.UpdateControlPoints(); + + // Rotate back + bezierCurve.Rotate(angle, bezierCurve.p1); + + // Enforce p1.x <= c1.x <= c2.x <= p2.x + bezierCurve.c1.x = std::max(bezierCurve.p1.x, bezierCurve.c1.x); + bezierCurve.c2.x = std::max(bezierCurve.c1.x, bezierCurve.c2.x); + bezierCurve.c2.x = std::min(bezierCurve.p2.x, bezierCurve.c2.x); + bezierCurve.c1.x = std::min(bezierCurve.c2.x, bezierCurve.c1.x); + + bezierCurve.UpdateControlPointParams(); +} + +ControlPointAdjustment AdjustSlursFunctor::CalcControlPointShift(const BezierCurve &bezierCurve, + const ArrayOfFloatingCurvePositioners &innerCurves, double symmetry, int margin) const +{ + ControlPointAdjustment adjustment{ 0, 0, false, 0 }; + if (bezierCurve.p1.x >= bezierCurve.p2.x) return adjustment; + + const int dist = bezierCurve.p2.x - bezierCurve.p1.x; + const bool isBelow = (m_currentCurve->GetDir() == curvature_CURVEDIR_above); + const int sign = isBelow ? 1 : -1; + Point points[4]; + points[0] = bezierCurve.p1; + points[1] = bezierCurve.c1; + points[2] = bezierCurve.c2; + points[3] = bezierCurve.p2; + + std::list constraints; + for (FloatingCurvePositioner *innerCurve : innerCurves) { + Point innerPoints[4]; + innerCurve->GetPoints(innerPoints); + + // Create five constraints for each inner slur + for (int step = 0; step <= 4; ++step) { + const Point innerPoint = BoundingBox::CalcPointAtBezier(innerPoints, 0.25 * step); + if ((bezierCurve.p1.x <= innerPoint.x) && (innerPoint.x <= bezierCurve.p2.x)) { + const int y = BoundingBox::CalcBezierAtPosition(points, innerPoint.x); + const int intersection = (innerPoint.y - y) * sign + margin; + const float distanceRatio = float(innerPoint.x - bezierCurve.p1.x) / float(dist); + + // Ignore obstacles close to the endpoints, because this would result in very large shifts + if ((std::abs(0.5 - distanceRatio) < 0.45) && (intersection > 0)) { + const double t = BoundingBox::CalcBezierParamAtPosition(points, innerPoint.x); + constraints.push_back( + { 3.0 * pow(1.0 - t, 2.0) * t, 3.0 * (1.0 - t) * pow(t, 2.0), double(intersection) }); + } + } + } + } + + // Solve the constraints and calculate the adjustment + std::tie(adjustment.leftShift, adjustment.rightShift) = this->SolveControlPointConstraints(constraints, symmetry); + + return adjustment; +} + +std::pair AdjustSlursFunctor::CalcEndPointShift(const BezierCurve &bezierCurve, + const ArrayOfFloatingCurvePositioners &innerCurves, double flexibility, int margin) const +{ + if (bezierCurve.p1.x >= bezierCurve.p2.x) return { 0, 0 }; + + int shiftLeft = 0; + int shiftRight = 0; + + const int dist = bezierCurve.p2.x - bezierCurve.p1.x; + const bool isBelow = (m_currentCurve->GetDir() == curvature_CURVEDIR_above); + const int sign = isBelow ? 1 : -1; + Point points[4]; + points[0] = bezierCurve.p1; + points[1] = bezierCurve.c1; + points[2] = bezierCurve.c2; + points[3] = bezierCurve.p2; + + for (FloatingCurvePositioner *innerCurve : innerCurves) { + Point innerPoints[4]; + innerCurve->GetPoints(innerPoints); + + // Adjustment for start point of inner slur + const int xInnerStart = innerPoints[0].x; + if ((bezierCurve.p1.x <= xInnerStart) && (xInnerStart <= bezierCurve.p2.x)) { + const int yStart = BoundingBox::CalcBezierAtPosition(points, xInnerStart); + const int intersectionStart = (innerPoints[0].y - yStart) * sign + 1.5 * margin; + if (intersectionStart > 0) { + const float distanceRatioStart = float(xInnerStart - bezierCurve.p1.x) / float(dist); + this->ShiftEndPoints(shiftLeft, shiftRight, distanceRatioStart, intersectionStart, flexibility, isBelow, + m_currentCurve->m_spanningType); + } + } + + // Adjustment for midpoint of inner slur + const Point innerMidPoint = BoundingBox::CalcPointAtBezier(innerPoints, 0.5); + if ((bezierCurve.p1.x <= innerMidPoint.x) && (innerMidPoint.x <= bezierCurve.p2.x)) { + const int yMid = BoundingBox::CalcBezierAtPosition(points, innerMidPoint.x); + const int intersectionMid = (innerMidPoint.y - yMid) * sign + 1.5 * margin; + if (intersectionMid > 0) { + const float distanceRatioMid = float(innerMidPoint.x - bezierCurve.p1.x) / float(dist); + this->ShiftEndPoints(shiftLeft, shiftRight, distanceRatioMid, intersectionMid, flexibility, isBelow, + m_currentCurve->m_spanningType); + } + } + + // Adjustment for end point of inner slur + const int xInnerEnd = innerPoints[3].x; + if ((bezierCurve.p1.x <= xInnerEnd) && (xInnerEnd <= bezierCurve.p2.x)) { + const int yEnd = BoundingBox::CalcBezierAtPosition(points, xInnerEnd); + const int intersectionEnd = (innerPoints[3].y - yEnd) * sign + 1.5 * margin; + if (intersectionEnd > 0) { + const float distanceRatioEnd = float(xInnerEnd - bezierCurve.p1.x) / float(dist); + this->ShiftEndPoints(shiftLeft, shiftRight, distanceRatioEnd, intersectionEnd, flexibility, isBelow, + m_currentCurve->m_spanningType); + } + } + } + + return { shiftLeft, shiftRight }; +} + +void AdjustSlursFunctor::ShiftEndPoints(int &shiftLeft, int &shiftRight, double ratio, int intersection, + double flexibility, bool isBelow, char spanningType) const +{ + // Filter collisions near the endpoints + // Collisions with ratio beyond the partialShiftRadius do not contribute to shifts + // They are compensated later by shifting the control points + double fullShiftRadius = 0.0; + double partialShiftRadius = 0.0; + std::tie(fullShiftRadius, partialShiftRadius) = this->CalcShiftRadii(true, flexibility, spanningType); + + if ((ratio < partialShiftRadius) && (m_currentSlur->HasEndpointAboveStart() == isBelow)) { + if (ratio > fullShiftRadius) { + // Collisions here only partially contribute to shifts + // We multiply with a function that interpolates between 1 and 0 + intersection *= this->CalcQuadraticInterpolation(partialShiftRadius, fullShiftRadius, ratio); + } + shiftLeft = std::max(shiftLeft, intersection); + } + + std::tie(fullShiftRadius, partialShiftRadius) = this->CalcShiftRadii(false, flexibility, spanningType); + + if ((ratio > 1.0 - partialShiftRadius) && (m_currentSlur->HasEndpointAboveEnd() == isBelow)) { + if (ratio < 1.0 - fullShiftRadius) { + // Collisions here only partially contribute to shifts + // We multiply with a function that interpolates between 0 and 1 + intersection *= this->CalcQuadraticInterpolation(1.0 - partialShiftRadius, 1.0 - fullShiftRadius, ratio); + } + shiftRight = std::max(shiftRight, intersection); + } +} + +std::pair AdjustSlursFunctor::CalcShiftRadii( + bool forShiftLeft, double flexibility, char spanningType) const +{ + // Use full flexibility for broken slur endpoints + if (forShiftLeft) { + if ((spanningType == SPANNING_MIDDLE) || (spanningType == SPANNING_END)) { + flexibility = 1.0; + } + } + else { + if ((spanningType == SPANNING_START) || (spanningType == SPANNING_MIDDLE)) { + flexibility = 1.0; + } + } + + const double fullShiftRadius = 0.05 + flexibility * 0.15; + const double partialShiftRadius = fullShiftRadius * 3.0; + + return { fullShiftRadius, partialShiftRadius }; +} + +double AdjustSlursFunctor::CalcQuadraticInterpolation(double zeroAt, double oneAt, double arg) const +{ + assert(zeroAt != oneAt); + const double a = 1.0 / (oneAt - zeroAt); + const double b = zeroAt / (zeroAt - oneAt); + return pow(a * arg + b, 2.0); +} + +double AdjustSlursFunctor::RotateSlope(double slope, double degrees, double doublingBound, bool upwards) const +{ + assert(degrees >= 0.0); + assert(doublingBound >= 0.0); + + if (upwards && (slope >= doublingBound)) return slope * 2.0; + if (!upwards && (slope <= -doublingBound)) return slope * 2.0; + const int sign = upwards ? 1 : -1; + return tan(atan(slope) + sign * M_PI * degrees / 180.0); +} + +float AdjustSlursFunctor::GetMinControlPointAngle(const BezierCurve &bezierCurve, float angle, int unit) const +{ + angle = abs(angle); + const double distance = double(bezierCurve.p2.x - bezierCurve.p1.x) / unit; + + // Increase min angle for short and angled slurs + double angleIncrement = std::min(angle / 4.0, 15.0); // values in [0.0, 15.0] + double factor = 1.0 - (distance - 8.0) / 8.0; + factor = std::min(factor, 1.0); + factor = std::max(factor, 0.0); // values in [0.0, 1.0] + + // not if control points are horizontally in a degenerated position + if ((bezierCurve.c1.x < bezierCurve.p1.x) || (2.0 * bezierCurve.c1.x > bezierCurve.p1.x + bezierCurve.p2.x)) { + angleIncrement = 0.0; + } + if ((bezierCurve.c2.x > bezierCurve.p2.x) || (2.0 * bezierCurve.c2.x < bezierCurve.p1.x + bezierCurve.p2.x)) { + angleIncrement = 0.0; + } + + return 30.0 + angleIncrement * factor; +} + } // namespace vrv diff --git a/src/adjustsylspacingfunctor.cpp b/src/adjustsylspacingfunctor.cpp index e95d258b1cd..b9d1f65d5b9 100644 --- a/src/adjustsylspacingfunctor.cpp +++ b/src/adjustsylspacingfunctor.cpp @@ -10,6 +10,7 @@ //---------------------------------------------------------------------------- #include "doc.h" +#include "label.h" #include "labelabbr.h" #include "staff.h" #include "syl.h" @@ -168,6 +169,12 @@ FunctorCode AdjustSylSpacingFunctor::VisitVerse(Verse *verse) int overlap = m_lastSyl->GetContentRight() - (firstSyl->GetContentLeft() + xShift); overlap += m_lastSyl->CalcConnectorSpacing(m_doc, m_staffSize); + // Check that we also include the space for the label if the verse has a new label + Label *label = vrv_cast