hyphenate text fix for desktop
This commit is contained in:
parent
3fd6606077
commit
14c9863a83
@ -26,15 +26,22 @@ import androidx.compose.material3.Card
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.drawWithContent
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.StrokeCap
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.TextLayoutResult
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
@ -48,6 +55,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.text.style.TextDecoration
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
import androidx.compose.ui.text.withStyle
|
import androidx.compose.ui.text.withStyle
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.isSpecified
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import net.sergeych.toread.fb2.Fb2Block
|
import net.sergeych.toread.fb2.Fb2Block
|
||||||
import net.sergeych.toread.fb2.Fb2Book
|
import net.sergeych.toread.fb2.Fb2Book
|
||||||
@ -57,6 +65,9 @@ import net.sergeych.toread.fb2.Fb2Text
|
|||||||
import net.sergeych.toread.fb2.Fb2TextSpan
|
import net.sergeych.toread.fb2.Fb2TextSpan
|
||||||
import net.sergeych.toread.fb2.Fb2TextStyle
|
import net.sergeych.toread.fb2.Fb2TextStyle
|
||||||
import net.sergeych.toread.text.HyphenationRegistry
|
import net.sergeych.toread.text.HyphenationRegistry
|
||||||
|
import net.sergeych.toread.text.SoftHyphen
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun ContinuousBookReader(
|
internal fun ContinuousBookReader(
|
||||||
@ -343,11 +354,50 @@ private fun ReaderText(
|
|||||||
textAlign: TextAlign,
|
textAlign: TextAlign,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
val annotatedText = text.toAnnotatedString(language, hyphenation)
|
||||||
|
val needsSoftHyphenPaintWorkaround = isDesktopPlatform()
|
||||||
|
var textLayout by remember(annotatedText) { mutableStateOf<TextLayoutResult?>(null) }
|
||||||
|
val desktopHyphenColor = MaterialTheme.colorScheme.onSurface
|
||||||
|
val desktopHyphenGutter = 8.dp
|
||||||
|
val textModifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.then(
|
||||||
|
if (needsSoftHyphenPaintWorkaround) {
|
||||||
|
Modifier.drawWithContent {
|
||||||
|
drawContent()
|
||||||
|
|
||||||
|
val layout = textLayout ?: return@drawWithContent
|
||||||
|
val layoutText = layout.layoutInput.text.text
|
||||||
|
val fontSizePx = if (style.fontSize.isSpecified) style.fontSize.toPx() else 18.sp.toPx()
|
||||||
|
val hyphenLength = fontSizePx * 0.36f
|
||||||
|
val strokeWidth = max(1f, fontSizePx * 0.055f)
|
||||||
|
|
||||||
|
for (line in 0 until layout.lineCount) {
|
||||||
|
if (!layout.endsAtSoftHyphen(layoutText, line)) continue
|
||||||
|
|
||||||
|
val lineRight = layout.getLineRight(line)
|
||||||
|
val x = min(lineRight + hyphenLength * 0.12f, size.width - hyphenLength)
|
||||||
|
val y = layout.getLineBaseline(line) - fontSizePx * 0.32f
|
||||||
|
drawLine(
|
||||||
|
color = desktopHyphenColor,
|
||||||
|
start = Offset(x, y),
|
||||||
|
end = Offset(x + hyphenLength, y),
|
||||||
|
strokeWidth = strokeWidth,
|
||||||
|
cap = StrokeCap.Square,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.padding(end = desktopHyphenGutter)
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = text.toAnnotatedString(language, hyphenation),
|
text = annotatedText,
|
||||||
style = style,
|
style = style,
|
||||||
textAlign = textAlign,
|
textAlign = textAlign,
|
||||||
modifier = modifier.fillMaxWidth(),
|
modifier = textModifier,
|
||||||
|
onTextLayout = { textLayout = it },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,6 +414,14 @@ private fun readerParagraphTextStyle(language: String?): TextStyle =
|
|||||||
private fun isAndroidPlatform(): Boolean =
|
private fun isAndroidPlatform(): Boolean =
|
||||||
getPlatform().name.startsWith("Android")
|
getPlatform().name.startsWith("Android")
|
||||||
|
|
||||||
|
private fun isDesktopPlatform(): Boolean =
|
||||||
|
getPlatform().name.startsWith("Java")
|
||||||
|
|
||||||
|
private fun TextLayoutResult.endsAtSoftHyphen(text: String, line: Int): Boolean {
|
||||||
|
val end = getLineEnd(line, visibleEnd = false)
|
||||||
|
return text.getOrNull(end - 1) == SoftHyphen || text.getOrNull(end) == SoftHyphen
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BookImage(
|
private fun BookImage(
|
||||||
book: Fb2Book,
|
book: Fb2Book,
|
||||||
|
|||||||
@ -11,13 +11,13 @@ androidx-lifecycle = "2.10.0"
|
|||||||
androidx-testExt = "1.3.0"
|
androidx-testExt = "1.3.0"
|
||||||
composeHotReload = "1.1.0"
|
composeHotReload = "1.1.0"
|
||||||
composeMaterialIcons = "1.7.3"
|
composeMaterialIcons = "1.7.3"
|
||||||
composeMultiplatform = "1.10.3"
|
composeMultiplatform = "1.11.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
kotlin = "2.3.21"
|
kotlin = "2.3.21"
|
||||||
kotlinx-coroutines = "1.10.2"
|
kotlinx-coroutines = "1.10.2"
|
||||||
ktor = "3.4.3"
|
ktor = "3.4.3"
|
||||||
logback = "1.5.32"
|
logback = "1.5.32"
|
||||||
material3 = "1.10.0-alpha05"
|
material3 = "1.11.0-alpha07"
|
||||||
h2 = "2.4.240"
|
h2 = "2.4.240"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user