Complete contentDescription for all icons - verse selection on print settings
This commit is contained in:
parent
f5eb92a374
commit
9b783200df
19 changed files with 312 additions and 104 deletions
|
|
@ -3,8 +3,9 @@ package mg.dot.feufaro.pdf
|
|||
import com.tom_roush.pdfbox.pdmodel.PDDocument
|
||||
import com.tom_roush.pdfbox.pdmodel.PDPage
|
||||
import com.tom_roush.pdfbox.pdmodel.PDPageContentStream
|
||||
import com.tom_roush.pdfbox.pdmodel.common.PDRectangle
|
||||
import com.tom_roush.pdfbox.pdmodel.font.PDType0Font
|
||||
import com.tom_roush.pdfbox.pdmodel.graphics.image.PDImageXObject
|
||||
import com.tom_roush.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState
|
||||
import com.tom_roush.pdfbox.util.Matrix
|
||||
import feufaro.composeapp.generated.resources.Res
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -249,26 +250,49 @@ private fun drawNoteWithModulation(
|
|||
|
||||
// ── drawNoteWithSubscript ─────────────────────────────────────────────────────
|
||||
private fun drawNoteWithSubscript(
|
||||
cs: PDPageContentStream, font: PDType0Font, fontSize: Float,
|
||||
cs: PDPageContentStream, font: PDType0Font,
|
||||
boldFont: PDType0Font?,
|
||||
fontSize: Float,
|
||||
text: String, x: Float, y: Float
|
||||
) {
|
||||
var curX = x
|
||||
val superscriptOffset = fontSize * 0.35f
|
||||
val subscriptOffset = fontSize * 0.2f
|
||||
|
||||
for (char in text) {
|
||||
val str = char.toString().sanitize()
|
||||
val isSuperscript = char in setOf('¹', '²', '³')
|
||||
val isSubscript = char in setOf('₁', '₂', '₃')
|
||||
val isSuperscript = char in setOf('¹', '²', '³', '⁴', '⁵')
|
||||
val isSubscript = char in setOf('₁', '₂', '₃', '₄', '₅')
|
||||
val isSpecialSymbol = char == '•' || char == ','
|
||||
val isPunctuation = char in setOf('•', ',')
|
||||
|
||||
val activeFont = if (isSpecialSymbol && boldFont != null) boldFont else font
|
||||
|
||||
val currentSize = if (isSuperscript || isSubscript) fontSize * 0.6f else fontSize
|
||||
val currentY = if (isSuperscript) y + superscriptOffset else y
|
||||
val currentY = when {
|
||||
isSuperscript -> y + superscriptOffset
|
||||
isSubscript -> y - subscriptOffset
|
||||
else -> y
|
||||
}
|
||||
|
||||
cs.beginText()
|
||||
cs.setFont(font, currentSize)
|
||||
cs.setFont(activeFont, currentSize)
|
||||
|
||||
if (isSuperscript || isSubscript) {
|
||||
cs.newLineAtOffset(curX - (currentSize * 0.2f), currentY)
|
||||
} else {
|
||||
cs.newLineAtOffset(curX, currentY)
|
||||
}
|
||||
|
||||
cs.showText(str)
|
||||
cs.endText()
|
||||
curX += font.getStringWidth(str) / 1000f * currentSize + 0.5f
|
||||
|
||||
val charWidth = font.getStringWidth(str) / 1000f * currentSize
|
||||
curX += when {
|
||||
isSuperscript || isSubscript -> charWidth * 0.3f
|
||||
isPunctuation -> charWidth
|
||||
else -> charWidth + 0.5f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -384,6 +408,33 @@ private fun drawHeader(
|
|||
cs.stroke()
|
||||
}
|
||||
|
||||
private fun drawFooterLogo(
|
||||
doc: PDDocument,
|
||||
cs: PDPageContentStream,
|
||||
logoBytes: ByteArray,
|
||||
pageWidth: Float
|
||||
) {
|
||||
try {
|
||||
val pdImage = PDImageXObject.createFromByteArray(doc, logoBytes, "logo_footer")
|
||||
val imgWidth = 100f
|
||||
val imgHeight = 100f * (pdImage.height.toFloat() / pdImage.width.toFloat())
|
||||
|
||||
val x = (pageWidth - imgWidth) / 2f
|
||||
val y = 40f
|
||||
cs.saveGraphicsState()
|
||||
|
||||
val graphicsState = PDExtendedGraphicsState()
|
||||
graphicsState.nonStrokingAlphaConstant = 0.15f
|
||||
cs.setGraphicsStateParameters(graphicsState)
|
||||
|
||||
cs.drawImage(pdImage, x, y, imgWidth, imgHeight)
|
||||
|
||||
cs.restoreGraphicsState()
|
||||
} catch (e: Exception) {
|
||||
println("⚠️ Erreur lors du dessin du logo en bas de page : ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
// ── actual fun ────────────────────────────────────────────────────────────────
|
||||
actual fun rememberPdfExportAction(
|
||||
scope: CoroutineScope,
|
||||
|
|
@ -452,11 +503,12 @@ private suspend fun generatePdfToBytes(
|
|||
val customNbGrid = settings.nbGridOnMeasure
|
||||
|
||||
// ── Polices ────────────────────────────────────────────────────────────────
|
||||
val noteFontBytes = Res.readBytes("font/PTSerif-Regular.ttf")
|
||||
val noteFontBytes = Res.readBytes("font/Lucida-Sans-Unicode.ttf")
|
||||
val lyricFontBytes = Res.readBytes("font/LinLibertine_R.ttf")
|
||||
val markerItalicBoldFontBytes = Res.readBytes("font/PT_Serif_Bold_Italic.ttf")
|
||||
val markerBoldFontBytes = Res.readBytes("font/PTSerif_Bold.ttf")
|
||||
val emmentalerFontBytes = Res.readBytes("font/Emmentaler.ttf")
|
||||
val logoBytes = Res.readBytes("drawable/icon.png")
|
||||
|
||||
PDDocument().use { doc ->
|
||||
|
||||
|
|
@ -479,11 +531,34 @@ private suspend fun generatePdfToBytes(
|
|||
(1..nbStanza).maxOfOrNull { sz -> tuo.getSingleSyllable(sz).size } ?: 1
|
||||
} ?: 1
|
||||
|
||||
|
||||
val hasOverrideLyrics = maxSylsSize >= 2
|
||||
val allStanzas = (1..nbStanza).toList()
|
||||
val selectedInSettings = settings.selectedStanzasInScore.filter { it in allStanzas }
|
||||
|
||||
val (stanzasRemaining, stanzasToShow) = when {
|
||||
selectedInSettings.isNotEmpty() -> {
|
||||
val bottom = if (!hasOverrideLyrics) {
|
||||
selectedInSettings
|
||||
} else {
|
||||
listOf(selectedInSettings.first())
|
||||
}
|
||||
val score = allStanzas.filter { it !in bottom }
|
||||
score to bottom
|
||||
}
|
||||
else -> {
|
||||
emptyList<Int>() to emptyList<Int>()
|
||||
}
|
||||
}
|
||||
|
||||
// ── Fonctions de dessin locales ────────────────────────────────────────
|
||||
fun newPage(): PDPageContentStream {
|
||||
val page = PDPage(settings.pdRectangle)
|
||||
doc.addPage(page)
|
||||
return PDPageContentStream(doc, page)
|
||||
val cs = PDPageContentStream(doc, page)
|
||||
drawFooterLogo(doc, cs, logoBytes, pageWidth)
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
fun drawCurlyBrace(cs: PDPageContentStream, x: Float, top: Float, bottom: Float) {
|
||||
|
|
@ -837,7 +912,7 @@ private suspend fun generatePdfToBytes(
|
|||
val currentY = notesStartY - (vLi * noteLineH)
|
||||
if (line.isNotBlank()) {
|
||||
if (line.contains(">")) drawNoteWithModulation(cs, customFont, noteFontSize, line, noteX, currentY)
|
||||
else drawNoteWithSubscript(cs, customFont, noteFontSize, line, noteX, currentY)
|
||||
else drawNoteWithSubscript(cs, customFont, markerBoldFont, noteFontSize, line, noteX, currentY)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -850,7 +925,7 @@ private suspend fun generatePdfToBytes(
|
|||
val totalAreaSlots = lastVirtualIndex + customSpacings[lastVoiceIndex]
|
||||
val finalBraceBottom = notesStartY - (totalAreaSlots * noteLineH)
|
||||
|
||||
val stanzasToShow = if (maxSylsSize >= 2) listOf(1) else if (nbStanza >= 2) listOf(1, 2) else listOf(1)
|
||||
//val stanzasToShow = if (maxSylsSize >= 2) listOf(1) else if (nbStanza >= 2) listOf(1, 2) else listOf(1)
|
||||
var lowestYOfThisRow = finalBraceBottom
|
||||
|
||||
stanzasToShow.forEachIndexed { stanzaIdx, currentStanza ->
|
||||
|
|
@ -1022,10 +1097,6 @@ private suspend fun generatePdfToBytes(
|
|||
y = lowestYOfThisRow - interRowGap
|
||||
}
|
||||
|
||||
// ── Stanzas restantes en texte ─────────────────────────────────────────
|
||||
val stanzasDisplayed = if (maxSylsSize >= 2) listOf(1) else if (nbStanza >= 2) listOf(1, 2) else listOf(1)
|
||||
val stanzasRemaining = (1..nbStanza).filter { it !in stanzasDisplayed }
|
||||
|
||||
if (stanzasRemaining.isNotEmpty()) {
|
||||
val textFont = lyricFont
|
||||
val textSize = lyricFontSize
|
||||
|
|
@ -1059,7 +1130,7 @@ private suspend fun generatePdfToBytes(
|
|||
val normal = syls.getOrNull(0)?.trim() ?: ""
|
||||
val dcPart = syls.drop(1).joinToString(" ") { it.trim() }
|
||||
if (normal.isNotEmpty()) result.append(normal).append(" ")
|
||||
if (dcPart.isNotEmpty()) result.append("[$dcPart] ")
|
||||
/*if (dcPart.isNotEmpty()) result.append("[$dcPart] ")*/
|
||||
val marker = tuo.pTemplate.markerToString()
|
||||
if (marker.contains("DC") && !inDcBlock && allDcLyrics.isNotEmpty()) {
|
||||
result.append("(")
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ actual data class PrintSettings actual constructor(
|
|||
actual val marginX : Float,
|
||||
actual val marginY : Float,
|
||||
actual val headerH : Float,
|
||||
actual val nbGridOnMeasure: Int
|
||||
actual val nbGridOnMeasure: Int,
|
||||
actual val selectedStanzasInScore: List<Int>
|
||||
) {
|
||||
val pdRectangle: PDRectangle
|
||||
get() {
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -25,7 +25,8 @@ expect class PrintSettings(
|
|||
marginX : Float,
|
||||
marginY : Float,
|
||||
headerH : Float,
|
||||
nbGridOnMeasure : Int
|
||||
nbGridOnMeasure : Int,
|
||||
selectedStanzasInScore: List<Int> = listOf(1, 2)
|
||||
) {
|
||||
val pageSize : PageSize
|
||||
val orientation : PageOrientation
|
||||
|
|
@ -43,6 +44,7 @@ expect class PrintSettings(
|
|||
val nbGridOnMeasure : Int
|
||||
val pageWidth : Float
|
||||
val pageHeight : Float
|
||||
val selectedStanzasInScore: List<Int>
|
||||
}
|
||||
|
||||
expect fun defaultPrintSettings(): PrintSettings
|
||||
|
|
@ -30,7 +30,7 @@ fun GridActionMenu(
|
|||
Icon(
|
||||
modifier = Modifier.width(50.dp),
|
||||
imageVector = Icons.Default.Add,
|
||||
contentDescription = null
|
||||
contentDescription = "Ajoute une grille"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ fun GridActionMenu(
|
|||
Icon(
|
||||
modifier = Modifier.width(50.dp),
|
||||
imageVector = Icons.Default.Delete,
|
||||
contentDescription = null
|
||||
contentDescription = "Enlèver une grille"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ private fun ExpandableGroup(
|
|||
Icons.Default.RemoveCircleOutline
|
||||
else
|
||||
Icons.Default.AddCircleOutline,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn marker ${group.title}",
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ fun TUODetailDialog(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.KeyboardDoubleArrowLeft,
|
||||
contentDescription = "Diminuer",
|
||||
contentDescription = "Diminuer z time",
|
||||
tint = if (silentDurationOrder.indexOf(editState.silentDuration) > 0) Color.LightGray else Color.DarkGray
|
||||
)
|
||||
}
|
||||
|
|
@ -297,7 +297,7 @@ fun TUODetailDialog(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.KeyboardDoubleArrowRight,
|
||||
contentDescription = "Augmenter",
|
||||
contentDescription = "Augmenter z time",
|
||||
tint = if (silentDurationOrder.indexOf(editState.silentDuration) < silentDurationOrder.lastIndex) Color.LightGray else Color.DarkGray
|
||||
)
|
||||
}
|
||||
|
|
@ -313,7 +313,7 @@ fun TUODetailDialog(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = "Précédent",
|
||||
contentDescription = "Précédent grid",
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
|
@ -335,7 +335,7 @@ fun TUODetailDialog(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowForward,
|
||||
contentDescription = "Suivant",
|
||||
contentDescription = "Suivant grid",
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
|
@ -418,7 +418,7 @@ fun TUODetailDialog(
|
|||
Icon(
|
||||
imageVector = Icons.Default.Add,
|
||||
tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
|
||||
contentDescription = null
|
||||
contentDescription = "btn add barre mesure"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -479,7 +479,7 @@ fun TUODetailDialog(
|
|||
Icon(
|
||||
imageVector = Icons.Sharp.Delete,
|
||||
tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
|
||||
contentDescription = "Enlever"
|
||||
contentDescription = "Enlever marker"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -512,7 +512,7 @@ fun TUODetailDialog(
|
|||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
|
||||
contentDescription = null
|
||||
contentDescription = "Complete marker"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -541,7 +541,7 @@ fun TUODetailDialog(
|
|||
Icon(
|
||||
imageVector = Icons.Default.Edit,
|
||||
tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
|
||||
contentDescription = null
|
||||
contentDescription = "Btn add marker"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -748,7 +748,7 @@ fun TUODetailDialog(
|
|||
tint = if (index == 0) MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f) else MaterialTheme.colorScheme.tertiary.copy(
|
||||
alpha = 1.5f
|
||||
),
|
||||
contentDescription = null
|
||||
contentDescription = "Ajouter enlever ligne lyrics"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -766,7 +766,7 @@ fun TUODetailDialog(
|
|||
IconButton(onClick = onDismiss, modifier = Modifier.size(20.dp)) {
|
||||
Icon(
|
||||
Icons.Default.Clear,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn cancel edit",
|
||||
tint = Color.LightGray
|
||||
)
|
||||
}
|
||||
|
|
@ -795,7 +795,7 @@ fun TUODetailDialog(
|
|||
) {
|
||||
Icon(
|
||||
Icons.Default.Build,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn save edit",
|
||||
tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1501,7 +1501,7 @@ fun EditSourceCompose(
|
|||
Modifier.fillMaxWidth().background(Color(0xFFF5F5F5)).padding(2.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(Icons.Default.Description, contentDescription = null, modifier = Modifier.size(16.dp))
|
||||
Icon(Icons.Default.Description, contentDescription = "new partition", modifier = Modifier.size(16.dp))
|
||||
Text(
|
||||
text = sourceTitle.ifEmpty { "nouveau_feufaro.txt" },
|
||||
modifier = Modifier.padding(start = 8.dp).widthIn(max = 160.dp),
|
||||
|
|
|
|||
|
|
@ -233,14 +233,14 @@ fun AboutDialog(onDismiss: () -> Unit) {
|
|||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Code,
|
||||
contentDescription = null,
|
||||
contentDescription = "Developpers",
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.OpenInNew,
|
||||
contentDescription = null,
|
||||
contentDescription = "Open in tab",
|
||||
modifier = Modifier.size(14.dp),
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ fun MainScreenWithDrawer(
|
|||
if (showPrintSettings) {
|
||||
PrintSettingsDialog(
|
||||
initialSettings = defaultPrintSettings(),
|
||||
// nbStanza = nbStanzas,
|
||||
totalStanzas = nbStanzas,
|
||||
onDismiss = { showPrintSettings = false },
|
||||
onConfirm = { settings ->
|
||||
showPrintSettings = false
|
||||
|
|
@ -389,7 +389,7 @@ fun MainScreenWithDrawer(
|
|||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Search,
|
||||
contentDescription = null,
|
||||
contentDescription = "Icon search on leading",
|
||||
tint = Color.White.copy(alpha = 0.8f),
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
|
|
@ -408,7 +408,7 @@ fun MainScreenWithDrawer(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = if (isNumericKeyboard) Icons.Default.Abc else Icons.Filled._123,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn to switch abc 123",
|
||||
tint = MaterialTheme.colorScheme.tertiary,
|
||||
modifier = Modifier.size(22.dp)
|
||||
)
|
||||
|
|
@ -424,7 +424,7 @@ fun MainScreenWithDrawer(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Clear,
|
||||
contentDescription = null,
|
||||
contentDescription = "Annuler recherche",
|
||||
tint = Color.White.copy(alpha = 0.8f),
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
|
|
@ -483,7 +483,7 @@ fun MainScreenWithDrawer(
|
|||
IconButton(onClick = {
|
||||
scope.launch { drawerState.open() }
|
||||
}) {
|
||||
Icon(Icons.Filled.Menu, contentDescription = "Ouvrir Menu")
|
||||
Icon(Icons.Filled.Menu, contentDescription = "Ouvrir Menu Latéral")
|
||||
}
|
||||
}
|
||||
}, actions = {
|
||||
|
|
@ -566,7 +566,7 @@ fun MainScreenWithDrawer(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowLeft,
|
||||
contentDescription = null,
|
||||
contentDescription = "Transposer de moins",
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
|
@ -609,7 +609,7 @@ fun MainScreenWithDrawer(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = centralIcon,
|
||||
contentDescription = null,
|
||||
contentDescription = "Valider transpose",
|
||||
tint = centralTint
|
||||
)
|
||||
}
|
||||
|
|
@ -633,7 +633,7 @@ fun MainScreenWithDrawer(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
||||
contentDescription = null,
|
||||
contentDescription = "Transposer de plus",
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
|
@ -1024,7 +1024,7 @@ fun MainScreenWithDrawer(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = if (isSearchActive) Icons.Default.Close else Icons.Default.Search,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn search",
|
||||
tint = MaterialTheme.colorScheme.onTertiary
|
||||
)
|
||||
}
|
||||
|
|
@ -1098,7 +1098,7 @@ fun MainScreenWithDrawer(
|
|||
leadingContent = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.SearchOff,
|
||||
contentDescription = null,
|
||||
contentDescription = "Not result search",
|
||||
tint = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
|
|
@ -1142,7 +1142,7 @@ fun MainScreenWithDrawer(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = if (isFavorite) Icons.Default.FavoriteBorder else Icons.Default.Favorite,
|
||||
contentDescription = null,
|
||||
contentDescription = "Favorite btn",
|
||||
modifier = Modifier.scale(scale),
|
||||
tint = MaterialTheme.colorScheme.onSecondary
|
||||
)
|
||||
|
|
@ -1153,7 +1153,7 @@ fun MainScreenWithDrawer(
|
|||
leadingContent = {
|
||||
Icon(
|
||||
imageVector = if (item.path.startsWith("assets://")) Icons.Default.ArrowDropDownCircle else Icons.Default.Folder,
|
||||
contentDescription = null,
|
||||
contentDescription = "Part interne ou personnel",
|
||||
modifier = Modifier.size(30.dp)
|
||||
)
|
||||
},
|
||||
|
|
@ -1166,7 +1166,7 @@ fun MainScreenWithDrawer(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.PlaylistAdd,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn add playlist",
|
||||
tint = if (!onPlaylist) Color.LightGray else Color(
|
||||
0xFFFFD700
|
||||
)
|
||||
|
|
@ -1295,7 +1295,7 @@ private fun getIntervalToC(key: String): Int {
|
|||
@Composable
|
||||
private fun MyFAB(
|
||||
onClick: () -> Unit,
|
||||
size: Dp ?= 55.dp,
|
||||
size: Dp = 55.dp,
|
||||
icon: ImageVector
|
||||
) {
|
||||
FloatingActionButton(
|
||||
|
|
@ -1306,7 +1306,7 @@ private fun MyFAB(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
contentDescription = "FAB ${icon.name}",
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ fun MidiControlPanel(
|
|||
|
||||
Icon(
|
||||
imageVector = Icons.Default.Loop,
|
||||
contentDescription = null,
|
||||
contentDescription = "AB Looping",
|
||||
tint = if (isLooping) Color.White else Color.Black,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ fun ModernVolumeSlider(
|
|||
volume < 0.5f -> Icons.AutoMirrored.Filled.VolumeDown
|
||||
else -> Icons.AutoMirrored.Filled.VolumeUp
|
||||
},
|
||||
contentDescription = null,
|
||||
contentDescription = "Volume slider",
|
||||
tint = if (volume > 0) MaterialTheme.colorScheme.onSecondary else Color.Gray,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ fun NewPartition(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.MusicNote,
|
||||
contentDescription = null,
|
||||
contentDescription = "music note title",
|
||||
tint = AccentBlue
|
||||
)
|
||||
}
|
||||
|
|
@ -373,7 +373,7 @@ fun NewPartition(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Add,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn create part",
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
Spacer(Modifier.width(6.dp))
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import kotlin.math.roundToInt
|
|||
@Composable
|
||||
fun PrintSettingsDialog(
|
||||
initialSettings: PrintSettings = defaultPrintSettings(),
|
||||
totalStanzas: Int = 4,
|
||||
onDismiss: () -> Unit,
|
||||
onConfirm: (PrintSettings) -> Unit
|
||||
) {
|
||||
|
|
@ -51,6 +52,7 @@ fun PrintSettingsDialog(
|
|||
var marginY by remember { mutableStateOf(initialSettings.marginY) }
|
||||
var headerH by remember { mutableStateOf(initialSettings.headerH) }
|
||||
var nbGridOnMeasure by remember { mutableStateOf(initialSettings.nbGridOnMeasure) }
|
||||
var selectedStanzasInScore by remember { mutableStateOf(initialSettings.selectedStanzasInScore) }
|
||||
|
||||
Dialog(
|
||||
properties = DialogProperties(
|
||||
|
|
@ -134,8 +136,6 @@ fun PrintSettingsDialog(
|
|||
}
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(4.dp))
|
||||
|
||||
// Taille papier
|
||||
LabelRow("Taille du papier")
|
||||
SegmentedRow(
|
||||
|
|
@ -144,17 +144,76 @@ fun PrintSettingsDialog(
|
|||
onSelect = { pageSize = PageSize.entries[it] }
|
||||
)
|
||||
|
||||
Spacer(Modifier.height(4.dp))
|
||||
|
||||
// Orientation
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
LabelRow("Orientation")
|
||||
Spacer(Modifier.height(4.dp))
|
||||
SegmentedRow(
|
||||
options = PageOrientation.entries.map { it.label },
|
||||
selected = orientation.ordinal,
|
||||
onSelect = { orientation = PageOrientation.entries[it] }
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Column(
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
LabelRow("Versets sous les notes")
|
||||
Spacer(Modifier.height(12.dp))
|
||||
Row(
|
||||
modifier = Modifier.horizontalScroll(rememberScrollState()),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
(1..totalStanzas).forEach { stanza ->
|
||||
val isSelected = stanza in selectedStanzasInScore
|
||||
|
||||
val backgroundColor = if (isSelected) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
Color.DarkGray
|
||||
}
|
||||
val contentColor = if (isSelected) {
|
||||
MaterialTheme.colorScheme.onPrimary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.6f)
|
||||
}
|
||||
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.size(22.dp)
|
||||
.clip(RoundedCornerShape(4.dp))
|
||||
.background(backgroundColor)
|
||||
.clickable {
|
||||
selectedStanzasInScore = if (isSelected) {
|
||||
selectedStanzasInScore - stanza
|
||||
} else {
|
||||
if (selectedStanzasInScore.size >= 2) {
|
||||
(selectedStanzasInScore.drop(1) + stanza).sorted()
|
||||
} else {
|
||||
(selectedStanzasInScore + stanza).sorted()
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = "$stanza",
|
||||
color = contentColor,
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Preview miniature de la page ──────────────────────
|
||||
SectionTitle("Aperçu")
|
||||
|
|
@ -306,10 +365,11 @@ fun PrintSettingsDialog(
|
|||
marginX = def.marginX
|
||||
marginY = def.marginY
|
||||
headerH = def.headerH
|
||||
selectedStanzasInScore = def.selectedStanzasInScore
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.RestartAlt,
|
||||
contentDescription = null,
|
||||
contentDescription = "Réinitialiser paramètre impression",
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
|
|
@ -319,7 +379,7 @@ fun PrintSettingsDialog(
|
|||
OutlinedButton(onClick = onDismiss) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = null,
|
||||
contentDescription = "Fermer paramètre impression",
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
|
|
@ -340,13 +400,14 @@ fun PrintSettingsDialog(
|
|||
marginX = marginX,
|
||||
marginY = marginY,
|
||||
headerH = headerH,
|
||||
nbGridOnMeasure = nbGridOnMeasure
|
||||
nbGridOnMeasure = nbGridOnMeasure,
|
||||
selectedStanzasInScore = selectedStanzasInScore
|
||||
)
|
||||
)
|
||||
}) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PictureAsPdf,
|
||||
contentDescription = null,
|
||||
contentDescription = "Enregistrer en pdf",
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ fun Settings(
|
|||
thumbContent = {
|
||||
Icon(
|
||||
imageVector = if (tempDarkMode) Icons.Default.DarkMode else Icons.Default.LightMode,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn dark mode",
|
||||
tint = MaterialTheme.colorScheme.onSecondary
|
||||
)
|
||||
},
|
||||
|
|
@ -411,7 +411,7 @@ fun Settings(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.Undo,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn reset dynamic volumes",
|
||||
tint = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
|
|
@ -661,7 +661,7 @@ fun Settings(
|
|||
if (isSelected) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null,
|
||||
contentDescription = "Selected instru",
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
|
|
@ -809,7 +809,7 @@ fun SettingsAccordion(
|
|||
|
||||
Icon(
|
||||
imageVector = Icons.Default.KeyboardArrowDown,
|
||||
contentDescription = null,
|
||||
contentDescription = "Setting $title",
|
||||
tint = if (isExpanded) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.rotate(arrowRotationDegree)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ fun SimpleDrawerContent(
|
|||
)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.NoteAdd, contentDescription = null, tint = MaterialTheme.colorScheme.error
|
||||
imageVector = Icons.AutoMirrored.Default.NoteAdd, contentDescription = "Btn create partition", tint = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ fun SimpleDrawerContent(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PlaylistAddCircle,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn add playlist drawer intern",
|
||||
tint = if (!onPlaylist) Color.LightGray else Color(0xFFFFD700),
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
|
|
@ -225,7 +225,7 @@ fun SimpleDrawerContent(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PlaylistAddCircle,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn add playlist drawer perso",
|
||||
tint = if (!onPlaylist) Color.LightGray else Color(0xFFFFD700),
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
|
|
@ -279,7 +279,7 @@ fun SimpleDrawerContent(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.VerticalAlignTop,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn align playlist drawer",
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = MaterialTheme.colorScheme.onSecondary
|
||||
)
|
||||
|
|
@ -291,7 +291,7 @@ fun SimpleDrawerContent(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.PlaylistRemove,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn remove playlist drawer",
|
||||
tint = if (isSelected) Color.LightGray else Color(0xFFFFD700)
|
||||
)
|
||||
}
|
||||
|
|
@ -343,7 +343,7 @@ fun SimpleDrawerContent(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.StarRate,
|
||||
contentDescription = null,
|
||||
contentDescription = "Btn add favorite",
|
||||
tint = if (isSelected) MaterialTheme.colorScheme.background else MaterialTheme.colorScheme.tertiary
|
||||
)
|
||||
}
|
||||
|
|
@ -383,7 +383,7 @@ fun SimpleDrawerContent(
|
|||
) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.icon),
|
||||
contentDescription = null,
|
||||
contentDescription = "Icon feufarooo",
|
||||
modifier = Modifier.size(45.dp)
|
||||
)
|
||||
}
|
||||
|
|
@ -397,7 +397,7 @@ fun SimpleDrawerContent(
|
|||
solfaScreenModel.loadCustomFile()
|
||||
scope.launch { drawerState.close() }
|
||||
}) {
|
||||
Icon(Icons.Default.FolderOpen, contentDescription = null, tint = MaterialTheme.colorScheme.onSecondary)
|
||||
Icon(Icons.Default.FolderOpen, contentDescription = "Btn to load custom file", tint = MaterialTheme.colorScheme.onSecondary)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ fun SimpleDrawerContent(
|
|||
onSettingsCheck()
|
||||
scope.launch { drawerState.close() }
|
||||
}) {
|
||||
Icon(Icons.Default.Settings, contentDescription = null, tint = MaterialTheme.colorScheme.onSecondary)
|
||||
Icon(Icons.Default.Settings, contentDescription = "Btn to settings", tint = MaterialTheme.colorScheme.onSecondary)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -423,7 +423,7 @@ fun SimpleDrawerContent(
|
|||
onAboutCheck()
|
||||
scope.launch { drawerState.close() }
|
||||
}) {
|
||||
Icon(Icons.Default.Info, contentDescription = null, tint = MaterialTheme.colorScheme.onSecondary)
|
||||
Icon(Icons.Default.Info, contentDescription = "Btn to about", tint = MaterialTheme.colorScheme.onSecondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -449,7 +449,7 @@ fun DrawerHeaderSticky(
|
|||
modifier = Modifier.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(icon, contentDescription = null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(20.dp))
|
||||
Icon(icon, contentDescription = "Title $title", tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(20.dp))
|
||||
Spacer(Modifier.width(12.dp))
|
||||
Text(
|
||||
text = title.uppercase(),
|
||||
|
|
@ -470,7 +470,7 @@ fun DrawerHeaderSticky(
|
|||
}
|
||||
Icon(
|
||||
imageVector = Icons.Default.KeyboardArrowDown,
|
||||
contentDescription = null,
|
||||
contentDescription = "Title $title arrow",
|
||||
modifier = Modifier.rotate(rotation)
|
||||
)
|
||||
}
|
||||
|
|
@ -526,7 +526,7 @@ fun CustomSwitchItem(
|
|||
thumbContent = {
|
||||
Icon(
|
||||
imageVector = if (checked) thumbIcon else Icons.Default.Visibility,
|
||||
contentDescription = null,
|
||||
contentDescription = "Toggle $label",
|
||||
modifier = Modifier.size(SwitchDefaults.IconSize)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ fun SolfaKeyboard(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.KeyboardTab,
|
||||
contentDescription = null,
|
||||
contentDescription = "Solfakey tab",
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
Spacer(Modifier.width(2.dp))
|
||||
|
|
@ -181,7 +181,7 @@ fun SolfaKeyboard(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = null,
|
||||
contentDescription = "Solfakey close",
|
||||
tint = MaterialTheme.colorScheme.onErrorContainer
|
||||
)
|
||||
}
|
||||
|
|
@ -197,7 +197,7 @@ fun SolfaKeyboard(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.KeyboardBackspace,
|
||||
contentDescription = null,
|
||||
contentDescription = "Solfakey backspace",
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
|
@ -213,7 +213,7 @@ fun SolfaKeyboard(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Save,
|
||||
contentDescription = null,
|
||||
contentDescription = "Solfakey save",
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import org.apache.pdfbox.pdmodel.PDDocument
|
|||
import org.apache.pdfbox.pdmodel.PDPage
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream
|
||||
import org.apache.pdfbox.pdmodel.font.PDType0Font
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject
|
||||
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState
|
||||
import org.apache.pdfbox.util.Matrix
|
||||
import java.awt.Color
|
||||
import java.awt.geom.GeneralPath
|
||||
|
|
@ -441,6 +443,7 @@ private fun drawNoteWithModulation(
|
|||
private fun drawNoteWithSubscript(
|
||||
cs: PDPageContentStream,
|
||||
font: PDType0Font,
|
||||
boldFont: PDType0Font?,
|
||||
fontSize: Float,
|
||||
text: String,
|
||||
x: Float,
|
||||
|
|
@ -448,21 +451,41 @@ private fun drawNoteWithSubscript(
|
|||
) {
|
||||
var curX = x
|
||||
val superscriptOffset = fontSize * 0.35f
|
||||
val subscriptOffset = fontSize * 0.2f
|
||||
|
||||
for (char in text) {
|
||||
val str = char.toString().sanitize()
|
||||
val isSuperscript = char in setOf('¹', '²', '³')
|
||||
val isSubscript = char in setOf('₁', '₂', '₃')
|
||||
val isSuperscript = char in setOf('¹', '²', '³', '⁴', '⁵')
|
||||
val isSubscript = char in setOf('₁', '₂', '₃', '₄', '₅')
|
||||
val isSpecialSymbol = char == '•' || char == ','
|
||||
val isPunctuation = char in setOf('•', ',')
|
||||
val activeFont = if (isSpecialSymbol && boldFont != null) boldFont else font
|
||||
|
||||
val currentSize = if (isSuperscript || isSubscript) fontSize * 0.6f else fontSize
|
||||
val currentY = if (isSuperscript) y + superscriptOffset else y
|
||||
val currentY = when {
|
||||
isSuperscript -> y + superscriptOffset
|
||||
isSubscript -> y - subscriptOffset
|
||||
else -> y
|
||||
}
|
||||
|
||||
cs.beginText()
|
||||
cs.setFont(font, currentSize)
|
||||
cs.setFont(activeFont, currentSize)
|
||||
|
||||
if (isSuperscript || isSubscript) {
|
||||
cs.newLineAtOffset(curX - (currentSize * 0.2f), currentY)
|
||||
} else {
|
||||
cs.newLineAtOffset(curX, currentY)
|
||||
}
|
||||
|
||||
cs.showText(str)
|
||||
cs.endText()
|
||||
curX += font.getStringWidth(str) / 1000f * currentSize + 0.5f
|
||||
|
||||
val charWidth = font.getStringWidth(str) / 1000f * currentSize
|
||||
curX += when {
|
||||
isSuperscript || isSubscript -> charWidth * 0.3f
|
||||
isPunctuation -> charWidth
|
||||
else -> charWidth + 0.5f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -578,6 +601,34 @@ private fun drawHeader(
|
|||
cs.stroke()
|
||||
}
|
||||
|
||||
fun drawWatermark(
|
||||
doc: PDDocument,
|
||||
cs: PDPageContentStream,
|
||||
logoBytes: ByteArray,
|
||||
pageWidth: Float,
|
||||
pageHeight: Float
|
||||
) {
|
||||
try {
|
||||
val pdImage = PDImageXObject.createFromByteArray(doc, logoBytes, "logo_footer")
|
||||
val imgWidth = 100f
|
||||
val imgHeight = 100f * (pdImage.height.toFloat() / pdImage.width.toFloat())
|
||||
|
||||
val x = (pageWidth - imgWidth) / 2f
|
||||
val y = 40f
|
||||
|
||||
cs.saveGraphicsState()
|
||||
|
||||
val graphicsState = PDExtendedGraphicsState()
|
||||
graphicsState.nonStrokingAlphaConstant = 0.15f
|
||||
cs.setGraphicsStateParameters(graphicsState)
|
||||
|
||||
cs.drawImage(pdImage, x, y, imgWidth, imgHeight)
|
||||
|
||||
cs.restoreGraphicsState()
|
||||
} catch (e: Exception) {
|
||||
println("⚠️ Erreur lors du chargement du logo du bas de page : ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
actual fun rememberPdfExportAction(
|
||||
scope: CoroutineScope,
|
||||
|
|
@ -650,11 +701,13 @@ private suspend fun generatePdfToBytes(
|
|||
val customNbGrid = settings.nbGridOnMeasure
|
||||
|
||||
// ── Polices ────────────────────────────────────────────────────
|
||||
val noteFontBytes = Res.readBytes("font/PTSerif-Regular.ttf")
|
||||
val noteFontBytes = Res.readBytes("font/Lucida-Sans-Unicode.ttf")
|
||||
val lyricFontBytes = Res.readBytes("font/LinLibertine_R.ttf")
|
||||
val markerItalicBoldFontBytes = Res.readBytes("font/PT_Serif_Bold_Italic.ttf")
|
||||
val markerBoldFontBytes = Res.readBytes("font/PTSerif_Bold.ttf")
|
||||
val emmentalerFontBytes = Res.readBytes("font/Emmentaler.ttf")
|
||||
val logoBytes = Res.readBytes("drawable/icon.png")
|
||||
|
||||
|
||||
PDDocument().use { doc ->
|
||||
|
||||
|
|
@ -692,12 +745,33 @@ private suspend fun generatePdfToBytes(
|
|||
} ?: 1
|
||||
} ?: 1
|
||||
|
||||
val hasOverrideLyrics = maxSylsSize >= 2
|
||||
val allStanzas = (1..nbStanza).toList()
|
||||
val selectedInSettings = settings.selectedStanzasInScore.filter { it in allStanzas }
|
||||
|
||||
val (stanzasRemaining, stanzasToShow) = when {
|
||||
selectedInSettings.isNotEmpty() -> {
|
||||
val bottom = if (!hasOverrideLyrics) {
|
||||
selectedInSettings
|
||||
} else {
|
||||
listOf(selectedInSettings.first())
|
||||
}
|
||||
val score = allStanzas.filter { it !in bottom }
|
||||
score to bottom
|
||||
}
|
||||
else -> {
|
||||
emptyList<Int>() to emptyList<Int>()
|
||||
}
|
||||
}
|
||||
|
||||
// ── Fonctions de dessin ────────────────────────────────────
|
||||
fun newPage(): PDPageContentStream {
|
||||
val page = PDPage(settings.pdRectangle)
|
||||
doc.addPage(page)
|
||||
val cs = PDPageContentStream(doc, page)
|
||||
|
||||
drawWatermark(doc, cs, logoBytes, pageWidth, pageHeight)
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
|
|
@ -1225,7 +1299,7 @@ private suspend fun generatePdfToBytes(
|
|||
if (line.contains(">")) {
|
||||
drawNoteWithModulation(cs, customFont, noteFontSize, line, noteX, currentY)
|
||||
} else {
|
||||
drawNoteWithSubscript(cs, customFont, noteFontSize, line, noteX, currentY)
|
||||
drawNoteWithSubscript(cs, customFont, markerBoldFont, noteFontSize, line, noteX, currentY)
|
||||
}
|
||||
}
|
||||
// Pour écrire dans l'espace vide JUSTE en dessous de cette voix :
|
||||
|
|
@ -1262,7 +1336,7 @@ private suspend fun generatePdfToBytes(
|
|||
// La position Y réelle du bas de l'accolade
|
||||
val finalBraceBottom = notesStartY - (totalAreaSlots * noteLineH)
|
||||
|
||||
val stanzasToShow = if (maxSylsSize >= 2) listOf(1) else if (nbStanza >= 2) listOf(1, 2) else listOf(1)
|
||||
//val stanzasToShow = if (maxSylsSize >= 2) listOf(1) else if (nbStanza >= 2) listOf(1, 2) else listOf(1)
|
||||
|
||||
val verticalMargin = 25f // Espace de sécurité entre l'accolade et les paroles
|
||||
// val finalBraceBottom = braceBottom // On l'a calculé plus haut
|
||||
|
|
@ -1527,8 +1601,6 @@ private suspend fun generatePdfToBytes(
|
|||
} else {
|
||||
if (nbStanza >= 2) listOf(1, 2) else listOf(1)
|
||||
}
|
||||
val stanzasRemaining = (1..nbStanza).filter { it !in stanzasDisplayed }
|
||||
|
||||
if (stanzasRemaining.isNotEmpty()) {
|
||||
val textFont = if (lyricFont is PDType0Font) lyricFont else customFont
|
||||
val textSize = lyricFontSize
|
||||
|
|
@ -1588,7 +1660,7 @@ private suspend fun generatePdfToBytes(
|
|||
// CROCHET DC (TOUJOURS, même si normal vide)
|
||||
if (dcPart.isNotEmpty()) {
|
||||
// dcPart
|
||||
result.append("[${cleanSyllable(dcPart)}] ")
|
||||
//result.append("[${cleanSyllable(dcPart)}] ")
|
||||
}
|
||||
|
||||
// 3. DC MARQUEUR (parenthèses)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ actual data class PrintSettings actual constructor(
|
|||
actual val marginX : Float,
|
||||
actual val marginY : Float,
|
||||
actual val headerH : Float,
|
||||
actual val nbGridOnMeasure: Int
|
||||
actual val nbGridOnMeasure: Int,
|
||||
actual val selectedStanzasInScore: List<Int>
|
||||
) {
|
||||
val pdRectangle: PDRectangle
|
||||
get() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue