@@ -753,8 +753,19 @@ bool isLikelySubtitleText(const String& text, const bool caseInsensitive = true)
753
753
std::regex::flag_type caseOption = caseInsensitive ? std::regex::icase : std::regex::ECMAScript;
754
754
return text.trimmed ().contains (std::wregex (L" ^[Ff]rom\\ s+(?!$)" , caseOption))
755
755
|| text.trimmed ().contains (std::wregex (L" ^Theme from\\ s+(?!$)" , caseOption))
756
- || text.trimmed ().contains (std::wregex (L" (Op\\ .?\\ s?\\ d+)\\ s?(No\\ .?\\ s?\\ d+)?" , caseOption))
757
- || text.trimmed ().contains (std::wregex (L" ^\\ (.*[Ff]rom\\ s.*\\ )$" , caseOption));
756
+ || text.trimmed ().contains (std::wregex (L" (((Op\\ .?\\ s?\\ d+)|(No\\ .?\\ s?\\ d+))\\ s?)+" , caseOption))
757
+ || text.trimmed ().contains (std::wregex (L" \\ (.*[Ff]rom\\ s.*\\ )" , caseOption));
758
+ }
759
+
760
+ // ---------------------------------------------------------
761
+ // isLikelyCreditText
762
+ // ---------------------------------------------------------
763
+
764
+ bool isLikelyCreditText (const String& text, const bool caseInsensitive = true )
765
+ {
766
+ std::regex::flag_type caseOption = caseInsensitive ? std::regex::icase : std::regex::ECMAScript;
767
+ return text.trimmed ().contains (std::wregex (L" ^((Words|Music|Lyrics|Composed),?(\\ sand|\\ s&|\\ s&)?\\ s)*[Bb]y\\ s+(?!$)" , caseOption))
768
+ || text.trimmed ().contains (std::wregex (L" ^(Traditional|Trad\\ .)" , caseOption));
758
769
}
759
770
760
771
// ---------------------------------------------------------
@@ -764,17 +775,31 @@ bool isLikelySubtitleText(const String& text, const bool caseInsensitive = true)
764
775
// Extracts a likely subtitle from the title string
765
776
// Returns the inferred subtitle
766
777
767
- static String inferSubTitleFromTitle ( const String& title)
778
+ static void inferFromTitle ( String& title, String& inferredSubtitle, String& inferredCredits )
768
779
{
769
- String inferredSubTitle;
770
- static const std::regex re (" \\ n" );
771
- for (const String& line : title.split (re)) {
780
+ StringList subtitleLines;
781
+ StringList creditLines;
782
+ StringList titleLines = title.split (std::regex (" \\ n" ));
783
+ for (int i = titleLines.size () - 1 ; i > 0 ; --i) {
784
+ String line = titleLines[i];
785
+ if (isLikelyCreditText (line, true )) {
786
+ for (int j = titleLines.size () - 1 ; j >= i; --j) {
787
+ creditLines.insert (0 , titleLines[j]);
788
+ titleLines.removeAt (j);
789
+ }
790
+ continue ;
791
+ }
772
792
if (isLikelySubtitleText (line, true )) {
773
- inferredSubTitle = line;
774
- break ;
793
+ for (int j = titleLines.size () - 1 ; j >= i; --j) {
794
+ subtitleLines.insert (0 , titleLines[j]);
795
+ titleLines.removeAt (j);
796
+ }
797
+ continue ;
775
798
}
776
799
}
777
- return inferredSubTitle;
800
+ title = titleLines.join (u" \n " );
801
+ inferredSubtitle = subtitleLines.join (u" \n " );
802
+ inferredCredits = creditLines.join (u" \n " );
778
803
}
779
804
780
805
// ---------------------------------------------------------
@@ -839,11 +864,12 @@ static VBox* addCreditWords(Score* score, const CreditWordsList& crWords,
839
864
// createMeasuresAndVboxes
840
865
// ---------------------------------------------------------
841
866
842
- static void createDefaultHeader (Score* score)
867
+ void MusicXMLParserPass1:: createDefaultHeader (Score* score)
843
868
{
844
869
String strTitle;
845
870
String strSubTitle;
846
871
String inferredStrSubTitle;
872
+ String inferredStrComposer;
847
873
String strComposer;
848
874
String strLyricist;
849
875
String strTranslator;
@@ -853,23 +879,28 @@ static void createDefaultHeader(Score* score)
853
879
if (strTitle.isEmpty ()) {
854
880
strTitle = score->metaTag (u" workTitle" );
855
881
}
856
- inferredStrSubTitle = inferSubTitleFromTitle (strTitle);
882
+ inferFromTitle (strTitle, inferredStrSubTitle, inferredStrComposer );
857
883
}
858
884
if (!(score->metaTag (u" movementNumber" ).isEmpty () && score->metaTag (u" workNumber" ).isEmpty ())) {
859
885
strSubTitle = score->metaTag (u" movementNumber" );
860
886
if (strSubTitle.isEmpty ()) {
861
887
strSubTitle = score->metaTag (u" workNumber" );
862
888
}
863
- } else if (!inferredStrSubTitle.isEmpty ()) {
889
+ }
890
+ if (!inferredStrSubTitle.isEmpty ()) {
864
891
strSubTitle = inferredStrSubTitle;
865
- strTitle. replace (inferredStrSubTitle, u" " ) ;
892
+ m_hasInferredHeaderText = true ;
866
893
}
867
894
String metaComposer = score->metaTag (u" composer" );
868
895
String metaLyricist = score->metaTag (u" lyricist" );
869
896
String metaTranslator = score->metaTag (u" translator" );
870
897
if (!metaComposer.isEmpty ()) {
871
898
strComposer = metaComposer;
872
899
}
900
+ if (!inferredStrComposer.isEmpty ()) {
901
+ strComposer = inferredStrComposer;
902
+ m_hasInferredHeaderText = true ;
903
+ }
873
904
if (metaLyricist.isEmpty ()) {
874
905
metaLyricist = score->metaTag (u" poet" );
875
906
}
@@ -897,13 +928,13 @@ static void createDefaultHeader(Score* score)
897
928
Create required measures with correct number, start tick and length for Score \a score.
898
929
*/
899
930
900
- static void createMeasuresAndVboxes (Score* score,
901
- const std::vector<Fraction>& ml,
902
- const std::vector<Fraction>& ms,
903
- const std::set<int >& systemStartMeasureNrs,
904
- const std::set<int >& pageStartMeasureNrs,
905
- const CreditWordsList& crWords,
906
- const Size& pageSize)
931
+ void MusicXMLParserPass1:: createMeasuresAndVboxes (Score* score,
932
+ const std::vector<Fraction>& ml,
933
+ const std::vector<Fraction>& ms,
934
+ const std::set<int >& systemStartMeasureNrs,
935
+ const std::set<int >& pageStartMeasureNrs,
936
+ const CreditWordsList& crWords,
937
+ const Size& pageSize)
907
938
{
908
939
if (crWords.empty ()) {
909
940
createDefaultHeader (score);
0 commit comments