Aligning text in drawer.writer

Hi! I took a first attempt at doing this. The idea is to pass uv coordinates to drawer.text() as a third argument. For instance Vector2(0.5, 0.5) would be used for aligning a text to the center. The TextAlign class contains some frequent locations (the typical 9 grid points).

tests.TextAlign-2023-04-18-16.16.40

import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.Drawer
import org.openrndr.draw.Writer
import org.openrndr.draw.isolated
import org.openrndr.draw.loadFont
import org.openrndr.math.Vector2

fun main() = application {
    program {
        val word = "H|j"
        val font = loadFont("data/fonts/default.otf", 100.0, word.toSet())

        fun pos(u: Double, v: Double) = drawer.bounds.position(u, v)

        extend {
            drawer.clear(ColorRGBa.WHITE)
            drawer.fill = ColorRGBa.BLACK
            drawer.fontMap = font
            drawer.text(word, pos(1.0, 0.0), TextAlign.TOP_RIGHT)
            drawer.text(word, pos(0.0, 1.0), TextAlign.BOTTOM_LEFT)
            drawer.text(word, pos(1.0, 1.0), TextAlign.BOTTOM_RIGHT)
            drawer.text(word, pos(0.0, 0.0), TextAlign.TOP_LEFT)

            drawer.text(word, pos(0.5, 0.0), TextAlign.TOP)
            drawer.text(word, pos(0.5, 1.0), TextAlign.BOTTOM)
            drawer.text(word, pos(1.0, 0.5), TextAlign.RIGHT)
            drawer.text(word, pos(0.0, 0.5), TextAlign.LEFT)

            drawer.text(word, pos(0.5, 0.5), TextAlign.CENTER)

            drawer.stroke = ColorRGBa.BLACK.opacify(0.3)
            drawer.lineSegment(pos(0.5, 0.0), pos(0.5, 1.0))
            drawer.lineSegment(pos(0.0, 0.5), pos(1.0, 0.5))
        }
    }
}

/**
 * Text alignment presets
 */
class TextAlign {
    companion object {
        val CENTER = Vector2(0.5, 0.5)
        val LEFT = Vector2(0.0, 0.5)
        val RIGHT = Vector2(1.0, 0.5)
        val TOP = Vector2(0.5, 0.0)
        val BOTTOM = Vector2(0.5, 1.0)
        val TOP_LEFT = Vector2(0.0, 0.0)
        val TOP_RIGHT = Vector2(1.0, 0.0)
        val BOTTOM_LEFT = Vector2(0.0, 1.0)
        val BOTTOM_RIGHT = Vector2(1.0, 1.0)
    }
}

/**
 * A version of `Drawer.text()` accepting an [align] argument.
 */
private fun Drawer.text(txt: String, pos: Vector2, align: Vector2) {
    fontMap?.let { fm ->
        val writer = Writer(this)
        val off = Vector2(
            -writer.textWidth(txt) * align.x,
            fm.height * (1 - align.y)
        )
        text(txt, pos + off)
    }
}

I will think more about it. Also about multiline text.

3 Likes