I want to draw Text inside a canvas to display a label for a chart.
On Android, I can use the library: https://github.com/tehras/charts (For Compose: 1-alpha03) but on Desktop I can't.
Thus I tried to rewrite the broken parts. But I can't get the labels to display.
Original Code, which I try to change to work with Desktop Source:
private val textPaint = android.graphics.Paint().apply {
isAntiAlias = true
color = labelTextColor.toLegacyInt()
}
private val textBounds = android.graphics.Rect()
override fun drawAxisLabels(
drawScope: DrawScope,
canvas: Canvas,
drawableArea: Rect,
minValue: Float,
maxValue: Float
) = with(drawScope) {
val labelPaint = textPaint.apply {
textSize = labelTextSize.toPx()
textAlign = android.graphics.Paint.Align.RIGHT
}
val minLabelHeight = (labelTextSize.toPx() * labelRatio.toFloat())
val totalHeight = drawableArea.height
val labelCount = max((drawableArea.height / minLabelHeight).roundToInt(), 2)
for (i in 0..labelCount) {
val value = minValue + (i * ((maxValue - minValue) / labelCount))
val label = labelValueFormatter(value)
val x = drawableArea.right - axisLineThickness.toPx() - (labelTextSize.toPx() / 2f)
labelPaint.getTextBounds(label, 0, label.length, textBounds)
val y = drawableArea.bottom - (i * (totalHeight / labelCount)) + (textBounds.height() / 2f)
canvas.nativeCanvas.drawText(label, x, y, labelPaint)
}
}
For me, the function at the end NativeCanvas::drawText
does not exist on Compose Desktop. I tried to replace all the logic with a TextPainter but nothing was painted.
What could I try to make it work ? or
Are there dependencies I could import from Android to just make it work?
COMPOSE_DESKTOP_VERSION: "0.3.0-build138"
KOTLIN_VERSION: "1.4.21"
The Desktop Compose native canvas should have a couple of methods related to drawing text. Instead of canvas.nativeCanvas.drawText
, you could try calling canvas.nativeCanvas.drawString(label, x, y, org.jetbrains.skija.Font(), labelPaint)
.
I got this using version 0.4.0-build177
of Desktop Compose, so YMMV on different versions.
This also comes with a few caveats:
Font
instance. The empty constructor seems to use some system defaults. I'm still learning the API myself, so I would suggest reading through the documentation (which at the moment is just the code, I think).Paint
since (at least on the version I was using) doesn't support textSize
on the Paint
- I had to specify this as part of the Font
creation.TextLine
with the canvas.nativeCanvas.drawTextLine()
function:val textLine = TextLine.make(yourTextString, yourFont)
val xOffset = when (yourTextAlign) {
// There are probably better ways to handle Start, End, and Justify...
TextAlign.Left, TextAlign.Start -> 0f
TextAlign.Right, TextAlign.End -> textLine.width
TextAlign.Center, TextAlign.Justify -> textLine.width / 2f
}
val actualX = x - xOffset
canvas.nativeCanvas.drawTextLine(textLine, actualX, y, yourPaint)