Fix canvas text rendering at density times its intended size

b453bb1 · Gabriel Morell · 2026-09-16 03:25

11 files +16 -4
Message
{commit_body(@commit)}

Files changed

modified android/app/src/main/java/org/neiam/diogramos/app/canvas/Renderer.kt
+16 −4
@@ -17,7 +17,7 @@ import androidx.compose.ui.text.font.FontStyle
17 17 import androidx.compose.ui.text.font.FontWeight
18 18 import androidx.compose.ui.text.style.TextAlign
19 19 import androidx.compose.ui.unit.Constraints
20 −import androidx.compose.ui.unit.sp
20 +
21 21 import org.neiam.diogramos.app.ui.theme.AppTheme
22 22 import org.neiam.diogramos.app.ui.theme.B612
23 23 import kotlin.math.atan2
@@ -180,11 +180,23 @@ class Renderer(
180 180 val isText = element.type == ElementType.TEXT
181 181 val style = element.style
182 182
183 − val fontSize = when {
183 + // Document units scaled by the zoom, so this is device pixels.
184 + val fontSizePx = when {
184 185 isText -> (style.fontSize ?: 16.0) * viewport.scale
185 186 else -> labelSizePx(style.labelSize) * viewport.scale
186 187 }
187 − if (fontSize < 4f) return // Below this it is noise, not text.
188 + if (fontSizePx < 4f) return // Below this it is noise, not text.
189 +
190 + // px -> sp, deliberately. `sp` is scaled by both display density
191 + // and the reader's font-size setting, so handing it a pixel count
192 + // renders the text density-times too large -- and since the wrap
193 + // width below is in real pixels, every word then overflows its box
194 + // and the label wraps after each character.
195 + //
196 + // This is also why canvas text must not follow the system font
197 + // scale: a diagram's text has to fit the box it was drawn in, the
198 + // same way `font_size` is in user units on the web.
199 + val fontSize = with(scope) { fontSizePx.toFloat().toSp() }
188 200
189 201 val color = when {
190 202 isText -> style.fill?.let { theme.token(it) } ?: theme.baseContent
@@ -195,7 +207,7 @@ class Renderer(
195 207 text = element.label,
196 208 style = TextStyle(
197 209 color = color,
198 − fontSize = fontSize.sp,
210 + fontSize = fontSize,
199 211 fontFamily = fontFamily(if (isText) style.fontFamily else style.labelFontFamily),
200 212 fontWeight = if (if (isText) style.fontBold else style.labelBold) {
201 213 FontWeight.Bold

Parents: b018a0f