From b9021a7e00b512ca1df2471f088b9ecc6c4c6eef Mon Sep 17 00:00:00 2001 From: dotmg Date: Fri, 11 Jul 2025 11:09:38 +0200 Subject: [PATCH] Crescendo et Diminuendo en symbole < ou > --- .../composeResources/files/config.json | 2 +- .../composeResources/files/ff-33.txt | 9 ++ .../composeResources/files/ffpm-46.txt | 3 +- .../composeResources/files/ffpm-546.txt | 9 ++ .../kotlin/mg/dot/feufaro/solfa/PTemplate.kt | 4 +- .../kotlin/mg/dot/feufaro/solfa/Solfa.kt | 4 +- .../mg/dot/feufaro/solfa/TimeUnitObject.kt | 97 +++++++++++++++++-- 7 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 composeApp/src/commonMain/composeResources/files/ff-33.txt create mode 100644 composeApp/src/commonMain/composeResources/files/ffpm-546.txt diff --git a/composeApp/src/commonMain/composeResources/files/config.json b/composeApp/src/commonMain/composeResources/files/config.json index 3a72ef6..67bef1f 100644 --- a/composeApp/src/commonMain/composeResources/files/config.json +++ b/composeApp/src/commonMain/composeResources/files/config.json @@ -2,7 +2,7 @@ "themeMode": "DARK", "fontSize": 18.5, "playlist": [ - "assets://ffpm-46.txt", + "assets://ff-33.txt", "assets://ews-456.txt", "assets://ews-1.txt", "assets://ews-2.txt", diff --git a/composeApp/src/commonMain/composeResources/files/ff-33.txt b/composeApp/src/commonMain/composeResources/files/ff-33.txt new file mode 100644 index 0000000..c553892 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/files/ff-33.txt @@ -0,0 +1,9 @@ +M0:|c:Eb|m:2/4|t:FFPM 546 Haleloia, Haleloia, Jeso No Mpamonjiko|a:H. Rabeony 1860 eo ho eo - 1956|h:H. Rabeony 1860 eo ho eo - 1956|r:8.7.8.7.D. +U0:z4:z224y62yy62yy62yy624t4yyy624t4yyy624t4yyy44t(111)18ty62yy(22)yyy6z2zG +N1:s,#l,ssfmdtdrtddfffslmmmrdr#rsttlsdsssslsssttlsdsmmmrdrs,sssfmd,d,fldlsmmfslsfmrffslts#t,sdrmfs-ldtdmrd +N2:#s,smmrdssstssTllldddddllttr4mddt4ddt4dmd5tsmmmrddTldffmdD4-D-drrmffmsstddTddlssdts +N3:#rsdtlsmrmfrmmfffmffF4frf4smmrrrfmmrfffmssF4ssddtlssmffltdsl4Tlsssr'r'dsmfsls-drrmsfm +N4:#f,sd4ls4ddffld#s,ffrrrrss6dds4dds#l,sssd'ddllrr#f,ssd7f4ddD4-D-rs5dfmrdlm,-frs4d +Y1:Inty aho Jesoa !/Miantso ahy Hianao/Na dia tsy mendrika e/Manolo-tena izao/Hianao no nifidy/Tsy haiko ny handà/‘Ty antso sarobidy/Ry Tompo, mamelà/Ny heloko rehetra/Diovy aho, havaozy/Ho olom-baovao/Hanao ny sitrakao/Ho mendrika tokoa/Ny antsonao Jesoa. +Y2:Inty aho Jeso miantso ahy Hianao/Ny fahalemeko anie/Ry Tompo fantatrao/Hianao no nifidy/Sy maniraka ahy/Avy Aminao Jesoa/Ny herin’ny fanahy/Ho entiko manao/Ny asa atolotrao/Fa sarotra e ny dia/Ry Tompo manampia/Ho mendrika tokoa/Ny antsonao Jesoa +Y3:Inty aho Jesoa/Miantso ahy Hianao/Mba ho fahazavan’/Izao tontolo izao/Hianao no nifidy ahy/Ho fanasina/Hanefa ny adidy/Lehibe sy masina/Koa hamasino, Tompo/Fa vonona aho hanompo/Hombay ny herinao/Hitondra aim-baovao/Ho mendrika tokoa/Ny antsonao Jesoa diff --git a/composeApp/src/commonMain/composeResources/files/ffpm-46.txt b/composeApp/src/commonMain/composeResources/files/ffpm-46.txt index 2db986b..09b6695 100644 --- a/composeApp/src/commonMain/composeResources/files/ffpm-46.txt +++ b/composeApp/src/commonMain/composeResources/files/ffpm-46.txt @@ -9,5 +9,4 @@ Y2:He! Izahay, fa vahiny mandalo/Indro manenjika ny fahavalo;/Ko_a henoy re ny s Y3:He! Ny vo_avotrao di_a mi_andry,/Na izahay na ireo nodimandry;/Tompo, tsinjovy ny fasan’ny olonao: Y4:Ary ny zavatra eto an-tany/Samy mi_ara-misento ihany,/Ka manantena ny mba hihavi_anao: Y5:Mbola ho ela va I\lay antenaina?/Tsia, fa akaiky izao ny maraina;/Ko\a andrandrao sy antso_y ny Tompo hoe: -Y6:«Tsy mba ho ela, fa faingana Aho,/Ary hanafaka ny mitalaho»./«Eny, avi_a, faingàna, ry Tompo ô!» -Y +Y6:«Tsy mba ho ela, fa faingana Aho,/Ary hanafaka ny mitalaho»./«Eny, avi_a, faingàna, ry Tompo ô!» \ No newline at end of file diff --git a/composeApp/src/commonMain/composeResources/files/ffpm-546.txt b/composeApp/src/commonMain/composeResources/files/ffpm-546.txt new file mode 100644 index 0000000..e06921c --- /dev/null +++ b/composeApp/src/commonMain/composeResources/files/ffpm-546.txt @@ -0,0 +1,9 @@ +M0:|c:G|m:4/4|t:FFPM 546 Haleloia, Haleloia, Jeso No Mpamonjiko|a:H. Rabeony 1860 eo ho eo - 1956|h:H. Rabeony 1860 eo ho eo - 1956|r:8.7.8.7.D. +U0:zC:2z11482z1148/2z116244C/2z11482z1148/2z114444C/2z11482z1148/2z114444C/2z11482z1148/2z11444(22)C +N1:#s,ssdds'fmd/dddddfm/mmrrmtrd/dtlrrmr/ssdds'fmd/dtltdrm/#dmfssfmll/llsmrs-d +N2:#f,ssssdtdd/sslllSs/ssssSSSl/lsFFFFs/ssssdtdd/ssfsllS/dtddtddd/d5t-s +N3:#t,m4s3m/mmffffm/mmrrmmmm/mmrrrdt/rrmmsssm/mmddfrt/s6ff/ffmsfsfm +N4:#t,ddddmrdd/d7/ddtt#r,tmml/llrrrrs/#f,ttddmrdd/ddffffm,/mrdmrdff/ffssss-d +Y1:Halelo_ia, halelo_ia!/Jeso no Mpamonjiko,/Halelo_ia, halelo_ia!/Afaka ny heloko./Sambatra\ aho tretrika\ aho/Ahy re ny lanitra,/Halelo_ia, halelo_ia!/Jeso no Mpanavotra. +Y2:Halelo_ia, halelo_ia!/Ravoravo re ny fo./Halelo_ia, halelo_ia!/Jeso re no soloko./Afaka\ aho, afaka\ aho,/Levona ny otako;/Halelo_ia, halelo_ia!/Lanitra no lovako. +Y3:Halelo_ia, halelo_ia!/Matoki_a hi_anao./Halelo_ia, halelo_ia!/Maty mba ho solonao/Jeso Tompo mahatoky,/Ry mpanota very ô./Halelo_ia, halelo_ia!/Raiso ny famindram-po. diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/PTemplate.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/PTemplate.kt index 0edfd7e..34c28bb 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/PTemplate.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/PTemplate.kt @@ -1,9 +1,6 @@ package mg.dot.feufaro.solfa class PTemplate (val template: String, val separatorAfter: String, private val markers: MutableList = mutableListOf("")){ - fun addMarker(newMarker: String) { - markers.add(newMarker) - } fun hasMarker(marker: String): Boolean { return markers.contains(marker) } @@ -14,6 +11,7 @@ class PTemplate (val template: String, val separatorAfter: String, private val m return markers.joinToString(separator = "") { it.replace(Regex("^\\$\\{([a-z]:)?(.*)\\}"), "$2") .replace("\$Q", "\uD834\uDD10") + .replace(Regex("^[<=>]$"), "") } } diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Solfa.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Solfa.kt index b20eb4b..40f3300 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Solfa.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Solfa.kt @@ -369,9 +369,9 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository 'h' => 'composer', 'i' => 'interline', 'l' => 'lyrics font size', - 'm' => 'rhythm', + 'm' => 'measure', 'n' => 'note font size', - 'r' => 'speed', + 'r' => 'rhythm', 't' => 'title', );*/ if (line.trim() == "") { diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt index e09f92a..7d15f9f 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt @@ -20,11 +20,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.geometry.Offset +import androidx.compose.foundation.Canvas import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextLayoutResult import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.TextUnit @@ -48,6 +51,16 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) { fun hasMarker(yes: Boolean) { _hasmarker = yes } + var lastHairPinStart: Int = -1 + var lastHairPinSymbol: Char? = null + fun startHairPin(hairPinSymbol: Char, hairPinBlock: Int) { + lastHairPinSymbol = hairPinSymbol + lastHairPinStart = hairPinBlock + } + fun endHairPin() { + lastHairPinStart = -1 + lastHairPinSymbol = null + } } init { nbBlock++ @@ -57,6 +70,18 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) { nbStanzas = 0 annotated = false } + fun hasHairPin(): Char? { + if (pTemplate.hasMarker($$"${<}")) { + return '<' + } + if (pTemplate.hasMarker($$"${>}")) { + return '>' + } + if (pTemplate.hasMarker($$"${=}")) { + return '=' + } + return null + } fun addLyrics(lyricsIn: POneStanzaLyrics) { lyrics.add(lyricsIn) } @@ -98,7 +123,7 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) { markerBefore += newMarker } fun addMarker(newMarker: Char) { - if (tuNotes.size == 0) { + if (tuNotes.isEmpty()) { markBefore(newMarker) } tuNotes.forEach { @@ -157,7 +182,8 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) { @Composable fun TimeUnitComposable( tuo: TimeUnitObject, - stanzaNumber: Int + stanzaNumber: Int, + gridColumnCount: Int ) { val col = if (tuo.getNum() % 2 == 0) Color(0xff, 0xfa, 0xf7) else Color(0xfb, 0xf3, 0xff) Column( @@ -170,13 +196,58 @@ fun TimeUnitComposable( val lineHeightDp : Dp = with(density) { lineHeight.toDp() } + var fontStyle = FontStyle.Normal + var fontWeight = FontWeight.Normal + val text = tuo.pTemplate.markerToString() + if (text.contains(Regex("^([mfp]+|[rR]it.*)$"))) { + fontStyle = FontStyle.Italic + } + if (text.contains("p")) { + fontWeight = FontWeight.Bold + } + val hairPinSymbol = tuo.hasHairPin() + if ((hairPinSymbol == '=') && (TimeUnitObject.lastHairPinSymbol != null)) { + println("LastHairpin: ${TimeUnitObject.lastHairPinSymbol} ${TimeUnitObject.lastHairPinStart}") + val hairPinStart = TimeUnitObject.lastHairPinStart + val lastHairPinSymbol = TimeUnitObject.lastHairPinSymbol + val hairPinStartLine: Int = (hairPinStart - 1) / gridColumnCount + val hairPinEndLine: Int = (tuo.numBlock - 1) / gridColumnCount + if (hairPinStartLine == hairPinEndLine) { + Canvas( + modifier = Modifier.fillMaxSize() + ) { + val xStart = if (lastHairPinSymbol == '>') -size.width * (tuo.numBlock - hairPinStart) else size.width/2 + val xEnd = if (lastHairPinSymbol == '>') size.width/2 else -size.width * (tuo.numBlock - hairPinStart) + val yHeight = with(density) { lineHeightDp.toPx()} + drawLine( + Color.DarkGray, + start = Offset(x=xStart, y=0f), + end = Offset(xEnd, yHeight/2) + ) + drawLine( + Color.DarkGray, + start = Offset(xStart, yHeight), + end = Offset(xEnd, yHeight/2) + ) + } + TimeUnitObject.endHairPin() + } + + } + if (hairPinSymbol != null && hairPinSymbol != '=') { + TimeUnitObject.startHairPin(hairPinSymbol, tuo.numBlock) + } AutoResizingText( - text = tuo.pTemplate.markerToString(), + text = text, minFontSize = 8.sp, maxFontSize = 18.sp, maxLines = 1, + fontStyle = fontStyle, + fontWeight = fontWeight, modifier = Modifier.fillMaxWidth() .height(lineHeightDp)) + + } Row (modifier = Modifier.height(IntrinsicSize.Min)){ if (tuo.sep0 == "/" || tuo.sep0 == "|") { @@ -227,7 +298,7 @@ fun TimeUnitComposable( } //if (it.underlineSpec.size > 0) { var colorUnderline = when (tuo.mutableNoteVersion) { - 0 -> Color.Red + 0 -> Color.DarkGray 1 -> Color.Yellow 2 -> Color.Magenta 3 -> Color.Blue @@ -293,6 +364,8 @@ fun AutoResizingText( maxFontSize: TextUnit = 24.sp, // Taille de police maximale de référence minFontSize: TextUnit = 10.sp, // Taille de police minimale autorisée textStyle: TextStyle = LocalTextStyle.current, + fontStyle: FontStyle? = null, + fontWeight: FontWeight? = null, maxLines: Int = 1 // Pour s'assurer que le texte ne déborde jamais sur deux lignes ) { var fontSize by remember { mutableStateOf(maxFontSize) } @@ -325,6 +398,8 @@ fun AutoResizingText( readyToDraw = true // La taille est stable ou min atteinte, on peut dessiner } }, + fontStyle = fontStyle, + fontWeight = fontWeight, // Le modificateur drawWithContent est utilisé pour retarder le dessin // jusqu'à ce que la taille de police finale soit déterminée. modifier = Modifier.fillMaxWidth() // Le modifier du Text interne peut être ajusté @@ -361,8 +436,8 @@ fun LazyVerticalGridTUO( val itemMinBaseWidth = bestTUOWidth(tuoList) val gridWidthDp = with(density) { gridWidthPx.toDp() } - val actualColumns = remember(gridWidthDp, itemMinBaseWidth, columnGroup) { - if (gridWidthDp == 0.dp) return@remember GridCells.Fixed(columnGroup) + val (gridCells: GridCells, gridColumnCount: Int) = remember(gridWidthDp, itemMinBaseWidth, columnGroup) { + if (gridWidthDp == 0.dp) return@remember Pair(GridCells.Fixed(columnGroup), columnGroup) var calculatedCols = (gridWidthDp / (itemMinBaseWidth + horizontalArrangementSpacing)).toInt() if (calculatedCols == 0) calculatedCols = columnGroup @@ -370,13 +445,14 @@ fun LazyVerticalGridTUO( calculatedCols = (calculatedCols / columnGroup) * columnGroup if (calculatedCols == 0) calculatedCols = columnGroup } - GridCells.Fixed(calculatedCols.coerceAtLeast(columnGroup)) - + val actualColumnCount: Int = calculatedCols.coerceAtLeast(columnGroup) + Pair(GridCells.Fixed(actualColumnCount), actualColumnCount) } + val currentStanza = viewModel.stanza LazyVerticalGrid( - columns = actualColumns, + columns = gridCells, modifier = Modifier.fillMaxWidth().heightIn(max = 800.dp), horizontalArrangement = Arrangement.spacedBy(horizontalArrangementSpacing), @@ -387,7 +463,8 @@ fun LazyVerticalGridTUO( items(items = tuoList.drop(1), key = { it.numBlock }) { oneTUO -> TimeUnitComposable( tuo = oneTUO, - currentStanza + currentStanza, + gridColumnCount ) } }