diff --git a/orx-shapes/build.gradle.kts b/orx-shapes/build.gradle.kts index 9f45200ab..cdbeb29d8 100644 --- a/orx-shapes/build.gradle.kts +++ b/orx-shapes/build.gradle.kts @@ -53,4 +53,5 @@ kotlin { } } } -} \ No newline at end of file +} + diff --git a/orx-shapes/src/commonMain/kotlin/text/TextShapes.kt b/orx-shapes/src/commonMain/kotlin/text/TextShapes.kt new file mode 100644 index 000000000..25aa77eaa --- /dev/null +++ b/orx-shapes/src/commonMain/kotlin/text/TextShapes.kt @@ -0,0 +1,29 @@ +package org.openrndr.extra.shapes.text + +import org.openrndr.draw.font.Face +import org.openrndr.math.Vector2 +import org.openrndr.math.transforms.buildTransform +import org.openrndr.shape.Shape + +fun shapesFromText(face: Face, text: String, size: Double, position: Vector2 = Vector2.ZERO): List { + var cursor = position + return text.windowed(2, 1, partialWindows = true) { + + if (it[0] == '\n') { + cursor = Vector2(position.x, cursor.y + face.lineSpace(size)) + Shape.EMPTY + } else { + + val glyph = face.glyphForCharacter(it.first()) + val shape = glyph.shape(size).transform(buildTransform { + translate(cursor) + }) + if (it.length == 2) { + cursor += Vector2(face.kernAdvance(size, it[0], it[1]), 0.0) + } + cursor += Vector2(glyph.advanceWidth(size), 0.0) + shape + } + }.filter { !it.empty } +} + diff --git a/orx-shapes/src/jvmDemo/kotlin/DemoText01.kt b/orx-shapes/src/jvmDemo/kotlin/DemoText01.kt new file mode 100644 index 000000000..ec4407450 --- /dev/null +++ b/orx-shapes/src/jvmDemo/kotlin/DemoText01.kt @@ -0,0 +1,31 @@ +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.draw.font.loadFace +import org.openrndr.extra.shapes.bounds.bounds +import org.openrndr.extra.shapes.text.shapesFromText +import org.openrndr.math.Vector2 +import java.io.File + +fun main() { + application { + + configure { + width = 720 + height = 720 + } + program { + + val face = + loadFace("https://github.com/IBM/plex/raw/master/IBM-Plex-Mono/fonts/complete/otf/IBMPlexMono-Bold.otf") + val shapes = shapesFromText(face, "SUCH\nVECTOR\nSUCH\nTEXT", 150.0) + + val bounds = shapes.bounds + extend { + drawer.clear(ColorRGBa.PINK) + drawer.translate(-bounds.corner) + drawer.translate((width - bounds.width) / 2.0, (height - bounds.height) / 2.0) + drawer.shapes(shapes) + } + } + } +} \ No newline at end of file