Crescendo et Diminuendo en symbole < ou >

This commit is contained in:
dotmg 2025-07-11 11:09:38 +02:00
parent 2cef5008cf
commit b9021a7e00
7 changed files with 110 additions and 18 deletions

View file

@ -2,7 +2,7 @@
"themeMode": "DARK", "themeMode": "DARK",
"fontSize": 18.5, "fontSize": 18.5,
"playlist": [ "playlist": [
"assets://ffpm-46.txt", "assets://ff-33.txt",
"assets://ews-456.txt", "assets://ews-456.txt",
"assets://ews-1.txt", "assets://ews-1.txt",
"assets://ews-2.txt", "assets://ews-2.txt",

View file

@ -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 herinny 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

View file

@ -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 fasanny olonao: Y3:He! Ny vo_avotrao di_a mi_andry,/Na izahay na ireo nodimandry;/Tompo, tsinjovy ny fasanny olonao:
Y4:Ary ny zavatra eto an-tany/Samy mi_ara-misento ihany,/Ka manantena ny mba hihavi_anao: 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: 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 ô!» Y6:«Tsy mba ho ela, fa faingana Aho,/Ary hanafaka ny mitalaho»./«Eny, avi_a, faingàna, ry Tompo ô!»
Y

View file

@ -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.

View file

@ -1,9 +1,6 @@
package mg.dot.feufaro.solfa package mg.dot.feufaro.solfa
class PTemplate (val template: String, val separatorAfter: String, private val markers: MutableList<String> = mutableListOf("")){ class PTemplate (val template: String, val separatorAfter: String, private val markers: MutableList<String> = mutableListOf("")){
fun addMarker(newMarker: String) {
markers.add(newMarker)
}
fun hasMarker(marker: String): Boolean { fun hasMarker(marker: String): Boolean {
return markers.contains(marker) return markers.contains(marker)
} }
@ -14,6 +11,7 @@ class PTemplate (val template: String, val separatorAfter: String, private val m
return markers.joinToString(separator = "") { return markers.joinToString(separator = "") {
it.replace(Regex("^\\$\\{([a-z]:)?(.*)\\}"), "$2") it.replace(Regex("^\\$\\{([a-z]:)?(.*)\\}"), "$2")
.replace("\$Q", "\uD834\uDD10") .replace("\$Q", "\uD834\uDD10")
.replace(Regex("^[<=>]$"), "")
} }
} }

View file

@ -369,9 +369,9 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
'h' => 'composer', 'h' => 'composer',
'i' => 'interline', 'i' => 'interline',
'l' => 'lyrics font size', 'l' => 'lyrics font size',
'm' => 'rhythm', 'm' => 'measure',
'n' => 'note font size', 'n' => 'note font size',
'r' => 'speed', 'r' => 'rhythm',
't' => 'title', 't' => 'title',
);*/ );*/
if (line.trim() == "") { if (line.trim() == "") {

View file

@ -20,11 +20,14 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.foundation.Canvas
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextLayoutResult import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle 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.rememberTextMeasurer
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnit
@ -48,6 +51,16 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) {
fun hasMarker(yes: Boolean) { fun hasMarker(yes: Boolean) {
_hasmarker = yes _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 { init {
nbBlock++ nbBlock++
@ -57,6 +70,18 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) {
nbStanzas = 0 nbStanzas = 0
annotated = false annotated = false
} }
fun hasHairPin(): Char? {
if (pTemplate.hasMarker($$"${<}")) {
return '<'
}
if (pTemplate.hasMarker($$"${>}")) {
return '>'
}
if (pTemplate.hasMarker($$"${=}")) {
return '='
}
return null
}
fun addLyrics(lyricsIn: POneStanzaLyrics) { fun addLyrics(lyricsIn: POneStanzaLyrics) {
lyrics.add(lyricsIn) lyrics.add(lyricsIn)
} }
@ -98,7 +123,7 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) {
markerBefore += newMarker markerBefore += newMarker
} }
fun addMarker(newMarker: Char) { fun addMarker(newMarker: Char) {
if (tuNotes.size == 0) { if (tuNotes.isEmpty()) {
markBefore(newMarker) markBefore(newMarker)
} }
tuNotes.forEach { tuNotes.forEach {
@ -157,7 +182,8 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) {
@Composable @Composable
fun TimeUnitComposable( fun TimeUnitComposable(
tuo: TimeUnitObject, tuo: TimeUnitObject,
stanzaNumber: Int stanzaNumber: Int,
gridColumnCount: Int
) { ) {
val col = if (tuo.getNum() % 2 == 0) Color(0xff, 0xfa, 0xf7) else Color(0xfb, 0xf3, 0xff) val col = if (tuo.getNum() % 2 == 0) Color(0xff, 0xfa, 0xf7) else Color(0xfb, 0xf3, 0xff)
Column( Column(
@ -170,13 +196,58 @@ fun TimeUnitComposable(
val lineHeightDp : Dp = with(density) { val lineHeightDp : Dp = with(density) {
lineHeight.toDp() 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( AutoResizingText(
text = tuo.pTemplate.markerToString(), text = text,
minFontSize = 8.sp, minFontSize = 8.sp,
maxFontSize = 18.sp, maxFontSize = 18.sp,
maxLines = 1, maxLines = 1,
fontStyle = fontStyle,
fontWeight = fontWeight,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
.height(lineHeightDp)) .height(lineHeightDp))
} }
Row (modifier = Modifier.height(IntrinsicSize.Min)){ Row (modifier = Modifier.height(IntrinsicSize.Min)){
if (tuo.sep0 == "/" || tuo.sep0 == "|") { if (tuo.sep0 == "/" || tuo.sep0 == "|") {
@ -227,7 +298,7 @@ fun TimeUnitComposable(
} }
//if (it.underlineSpec.size > 0) { //if (it.underlineSpec.size > 0) {
var colorUnderline = when (tuo.mutableNoteVersion) { var colorUnderline = when (tuo.mutableNoteVersion) {
0 -> Color.Red 0 -> Color.DarkGray
1 -> Color.Yellow 1 -> Color.Yellow
2 -> Color.Magenta 2 -> Color.Magenta
3 -> Color.Blue 3 -> Color.Blue
@ -293,6 +364,8 @@ fun AutoResizingText(
maxFontSize: TextUnit = 24.sp, // Taille de police maximale de référence maxFontSize: TextUnit = 24.sp, // Taille de police maximale de référence
minFontSize: TextUnit = 10.sp, // Taille de police minimale autorisée minFontSize: TextUnit = 10.sp, // Taille de police minimale autorisée
textStyle: TextStyle = LocalTextStyle.current, 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 maxLines: Int = 1 // Pour s'assurer que le texte ne déborde jamais sur deux lignes
) { ) {
var fontSize by remember { mutableStateOf(maxFontSize) } var fontSize by remember { mutableStateOf(maxFontSize) }
@ -325,6 +398,8 @@ fun AutoResizingText(
readyToDraw = true // La taille est stable ou min atteinte, on peut dessiner 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 // Le modificateur drawWithContent est utilisé pour retarder le dessin
// jusqu'à ce que la taille de police finale soit déterminée. // jusqu'à ce que la taille de police finale soit déterminée.
modifier = Modifier.fillMaxWidth() // Le modifier du Text interne peut être ajusté modifier = Modifier.fillMaxWidth() // Le modifier du Text interne peut être ajusté
@ -361,8 +436,8 @@ fun LazyVerticalGridTUO(
val itemMinBaseWidth = bestTUOWidth(tuoList) val itemMinBaseWidth = bestTUOWidth(tuoList)
val gridWidthDp = with(density) { gridWidthPx.toDp() } val gridWidthDp = with(density) { gridWidthPx.toDp() }
val actualColumns = remember(gridWidthDp, itemMinBaseWidth, columnGroup) { val (gridCells: GridCells, gridColumnCount: Int) = remember(gridWidthDp, itemMinBaseWidth, columnGroup) {
if (gridWidthDp == 0.dp) return@remember GridCells.Fixed(columnGroup) if (gridWidthDp == 0.dp) return@remember Pair(GridCells.Fixed(columnGroup), columnGroup)
var calculatedCols = var calculatedCols =
(gridWidthDp / (itemMinBaseWidth + horizontalArrangementSpacing)).toInt() (gridWidthDp / (itemMinBaseWidth + horizontalArrangementSpacing)).toInt()
if (calculatedCols == 0) calculatedCols = columnGroup if (calculatedCols == 0) calculatedCols = columnGroup
@ -370,13 +445,14 @@ fun LazyVerticalGridTUO(
calculatedCols = (calculatedCols / columnGroup) * columnGroup calculatedCols = (calculatedCols / columnGroup) * columnGroup
if (calculatedCols == 0) calculatedCols = 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 val currentStanza = viewModel.stanza
LazyVerticalGrid( LazyVerticalGrid(
columns = actualColumns, columns = gridCells,
modifier = Modifier.fillMaxWidth().heightIn(max = 800.dp), modifier = Modifier.fillMaxWidth().heightIn(max = 800.dp),
horizontalArrangement = Arrangement.spacedBy(horizontalArrangementSpacing), horizontalArrangement = Arrangement.spacedBy(horizontalArrangementSpacing),
@ -387,7 +463,8 @@ fun LazyVerticalGridTUO(
items(items = tuoList.drop(1), key = { it.numBlock }) { oneTUO -> items(items = tuoList.drop(1), key = { it.numBlock }) { oneTUO ->
TimeUnitComposable( TimeUnitComposable(
tuo = oneTUO, tuo = oneTUO,
currentStanza currentStanza,
gridColumnCount
) )
} }
} }