# Drawing text with non Latin alphabet

**URL:** <https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105>\
**Category:** How to?\
**Created:** [May 9, 2020, 2:41pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105 "2020-05-09T14:41:15Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![sidec](https://avatars.discourse-cdn.com/v4/letter/s/9fc29f/32.png) [@sidec](https://openrndr.discourse.group/u/sidec)\
**Post date:** [May 9, 2020, 2:41pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/1 "2020-05-09T14:41:15Z")

</div>

Hi,  
Trying to do some typography work using Polish alphabet. All characters with diacritics, (like acute accent, overdot, stroke, etc) are missing from drawn text. I am using otf or ttf fonts that support all set of characters. Is this implemented in openrndr?  
thanks

---

<div class="post-metadata">

**Author:** ![edwin](https://avatars.discourse-cdn.com/v4/letter/e/73ab20/32.png) [@edwin](https://openrndr.discourse.group/u/edwin)\
**Post date:** [May 9, 2020, 7:07pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/2 "2020-05-09T19:07:35Z")

</div>

Hi and welcome sidec! Currently we support a pretty limited set of characters in OPENRNDR. I can add the missing entries for the Polish alphabet if desired. Our current approach for rendering text uses pre-rendered glyphs from a texture, which has pros but also cons (such as limited alphabest).

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [May 10, 2020, 8:08am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/3 "2020-05-10T08:08:51Z")

</div>

Would it be possible somehow to specify the character range by the user?

---

<div class="post-metadata">

**Author:** ![sidec](https://avatars.discourse-cdn.com/v4/letter/s/9fc29f/32.png) [@sidec](https://openrndr.discourse.group/u/sidec)\
**Post date:** [May 10, 2020, 10:48am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/4 "2020-05-10T10:48:54Z")

</div>

thanks @edwin! that would be very nice, if this is not too much work for you. does this go into [https://github.com/openrndr/openrndr/blob/master/openrndr-gl3/src/main/kotlin/org/openrndr/internal/gl3/FontImageMapManagerGL3.kt](https://github.com/openrndr/openrndr/blob/master/openrndr-gl3/src/main/kotlin/org/openrndr/internal/gl3/FontImageMapManagerGL3.kt) right? I can create pr if you don’t mind.

---

<div class="post-metadata">

**Author:** ![edwin](https://avatars.discourse-cdn.com/v4/letter/e/73ab20/32.png) [@edwin](https://openrndr.discourse.group/u/edwin)\
**Post date:** [May 10, 2020, 10:53am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/5 "2020-05-10T10:53:03Z")

</div>

Exactly! Would save me some time if you create a PR for it, which is much appreciated!

---

<div class="post-metadata">

**Author:** ![edwin](https://avatars.discourse-cdn.com/v4/letter/e/73ab20/32.png) [@edwin](https://openrndr.discourse.group/u/edwin)\
**Post date:** [May 10, 2020, 11:36am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/6 "2020-05-10T11:36:29Z")

</div>

I think that is a good stop-gap solution until a better text renderer is implemented

---

<div class="post-metadata">

**Author:** ![sidec](https://avatars.discourse-cdn.com/v4/letter/s/9fc29f/32.png) [@sidec](https://openrndr.discourse.group/u/sidec)\
**Post date:** [May 10, 2020, 11:39am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/7 "2020-05-10T11:39:13Z")

</div>

sure, I will prepare small p with adding all diacritics (~8) to standard, as this is extension to Latin.

---

<div class="post-metadata">

**Author:** ![shiwl](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/shiwl/32/39_2.png) [@shiwl](https://openrndr.discourse.group/u/shiwl)\
**Post date:** [May 17, 2020, 2:52am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/8 "2020-05-17T02:52:50Z")

</div>

@edwin would it be feasible for FontMapManager to display CJK characters (tens of thousands of different characters) if such an alphabet is provided, or for each font, specify a different alphabet?

---

<div class="post-metadata">

**Author:** ![sidec](https://avatars.discourse-cdn.com/v4/letter/s/9fc29f/32.png) [@sidec](https://openrndr.discourse.group/u/sidec)\
**Post date:** [May 23, 2020, 7:10pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/9 "2020-05-23T19:10:07Z")

</div>

I don’t think this won’t be feasible with current implementation, but I created some helper class that basically convert font glyph into OPENRNDR shape. I’m planning to wrap it into a small library, or think about how it might contribute to main codebase, but for now I can share kotlin file in this tread if you like

---

<div class="post-metadata">

**Author:** ![sidec](https://avatars.discourse-cdn.com/v4/letter/s/9fc29f/32.png) [@sidec](https://openrndr.discourse.group/u/sidec)\
**Post date:** [May 23, 2020, 7:20pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/10 "2020-05-23T19:20:30Z")

</div>

I can’t upload the file, but here the content. Should be self explanatory. I use it for poster type typography and it is not as performant as existing text implementation, but it handles any alphabet. I used it for Greek with no issues.

```
package font

import org.openrndr.math.Vector2
import org.openrndr.shape.Segment
import org.openrndr.shape.Shape
import org.openrndr.shape.ShapeContour
import org.slf4j.LoggerFactory
import java.awt.Font
import java.awt.font.FontRenderContext
import java.awt.font.TextLayout
import java.awt.geom.AffineTransform
import java.awt.geom.GeneralPath
import java.awt.geom.PathIterator
import java.io.File
import java.net.URL

typealias JShape = java.awt.Shape

object FontShape {
    val logger = LoggerFactory.getLogger(FontShape::class.java)

    fun String.getShape(fontName: String, from: Vector2, fontSize: Double = 128.0): Shape {
        val stream = try {
            fontName.asResource()?.openStream()
        } catch (e: NullPointerException) {
            File(fontName).inputStream()
        }
        val font = Font.createFont(Font.TRUETYPE_FONT, stream).deriveFont(fontSize.toFloat())

        val context = FontRenderContext(null, true, true)
        val shape = GeneralPath()
        val layout = TextLayout(this, font, context)
        val transform = AffineTransform.getTranslateInstance(from.x, from.y)
        val outline = layout.getOutline(transform)
        shape.append(outline, true)
        return getPoints(shape)
    }

    private fun getPoints(shape: JShape): Shape {
        val iterator: PathIterator = shape.getPathIterator(null)
        val coordinates = DoubleArray(6)
        var x = 0.0
        var y = 0.0
        var cursor = Vector2(x, y)
        val contours = mutableListOf<ShapeContour>()
        val segments = mutableListOf<Segment>()

        while (!iterator.isDone) {

            var segment: Segment? = null
            when (iterator.currentSegment(coordinates)) {
                PathIterator.SEG_CLOSE -> {
                    logger.info("SEG_CLOSE")
                    contours.add(ShapeContour(segments.toList(), true))
                    segments.clear()
                }
                PathIterator.SEG_QUADTO -> {
                    logger.info("SEG_QUADTO")
                    val x1 = coordinates[0]
                    val y1 = coordinates[1]
                    val x2 = coordinates[2]
                    val y2 = coordinates[3]
                    x = x2
                    y = y2
                    segment = Segment(start = cursor, c0 = Vector2(x1, y1), end = Vector2(x2, y2))
                }
                PathIterator.SEG_CUBICTO -> {
                    logger.info("SEG_CUBICTO")
                    val x1 = coordinates[0]
                    val y1 = coordinates[1]
                    val x2 = coordinates[2]
                    val y2 = coordinates[3]
                    val x3 = coordinates[4]
                    val y3 = coordinates[5]
                    x = x3
                    y = y3
                    segment = Segment(start = cursor, c0 = Vector2(x1, y1), c1 = Vector2(x2, y2), end = Vector2(x3, y3))
                }
                PathIterator.SEG_LINETO -> {
                    logger.info("SEG_LINETO")
                    val x1 = coordinates[0]
                    val y1 = coordinates[1]
                    x = x1
                    y = y1
                    segment = Segment(start = cursor, end = Vector2(x1, y1))
                }
                PathIterator.SEG_MOVETO -> {
                    logger.info("SEG_MOVETO")
                    val x1 = coordinates[0]
                    val y1 = coordinates[1]
                    x = x1
                    y = y1
                }
            }
            cursor = Vector2(x, y)
            if (segment != null) {
                segments.add(segment)
            }
            iterator.next()
        }
        return Shape(contours)
    }
}

fun String.asResource(): URL? {
    return object {}.javaClass.classLoader.getResource(this)
}
```

---

<div class="post-metadata">

**Author:** ![shiwl](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/shiwl/32/39_2.png) [@shiwl](https://openrndr.discourse.group/u/shiwl)\
**Post date:** [May 24, 2020, 2:10am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/11 "2020-05-24T02:10:17Z")

</div>

Thank you @sidec. This is so helpful! I’m able to display Chinese using your code with no effort.

---

<div class="post-metadata">

**Author:** ![andremichelle](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/andremichelle/32/145_2.png) [@andremichelle](https://openrndr.discourse.group/u/andremichelle)\
**Post date:** [July 2, 2020, 6:13pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/12 "2020-07-02T18:13:04Z")

</div>

For me the code never completes. But I also figured that  
Font(“Dialog”, Font.PLAIN, 14)  
will never return anything. Is there some configuration, I am not aware of?

---

<div class="post-metadata">

**Author:** ![andremichelle](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/andremichelle/32/145_2.png) [@andremichelle](https://openrndr.discourse.group/u/andremichelle)\
**Post date:** [July 2, 2020, 6:22pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/13 "2020-07-02T18:22:45Z")

</div>

Any call to any **awt** related classes will freeze the application.

Like GraphicsEnvironment.getLocalGraphicsEnvironment().allFonts or Canvas() etc…

---

<div class="post-metadata">

**Author:** ![sidec](https://avatars.discourse-cdn.com/v4/letter/s/9fc29f/32.png) [@sidec](https://openrndr.discourse.group/u/sidec)\
**Post date:** [July 2, 2020, 10:18pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/14 "2020-07-02T22:18:48Z")

</div>

@andremichelle what java/kotlin versions, OS?  
Also, how you used the snippet? something like  
`drawer.shape("some text".getShape("Dialog", Vector(width/4.0,height/2.0)))`?

---

<div class="post-metadata">

**Author:** ![andremichelle](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/andremichelle/32/145_2.png) [@andremichelle](https://openrndr.discourse.group/u/andremichelle)\
**Post date:** [July 3, 2020, 3:47am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/15 "2020-07-03T03:47:14Z")

</div>

Yes, I am using it like that. But the application freezes whenever anything tries to access the java.awt package. There is no other code in the program

`macOS Catalina 10.15.5`

`java version "1.8.0_172" Java(TM) SE Runtime Environment (build 1.8.0_172-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)`

`kotlinVersion = "1.3.72"`

---

<div class="post-metadata">

**Author:** ![edwin](https://avatars.discourse-cdn.com/v4/letter/e/73ab20/32.png) [@edwin](https://openrndr.discourse.group/u/edwin)\
**Post date:** [July 3, 2020, 9:07am UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/16 "2020-07-03T09:07:42Z")

</div>

Can you try enabling AWT’s headless mode?

This can be done by adding the following before using any AWT code  
`System.setProperty("java.awt.headless", "true")`

---

<div class="post-metadata">

**Author:** ![axel](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/axel/32/146_2.png) [@axel](https://openrndr.discourse.group/u/axel)\
**Post date:** [September 27, 2020, 2:27pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/17 "2020-09-27T14:27:08Z")

</div>

Update: seems solved with the above `System.setProperty("java.awt.headless", "true")` - as another awt call (getting the font list) was working earlier in the code, I thought this would not be my problem … but I guess that call doesn’t require a UI yet and therefore works, while the latter requires it and then fails… Thanks!

> Hi - I was trying this today - I got the part to get a shape working when using something like  
> ` val font = Font("Arial", Font.PLAIN, 128)`  
> inside the `String.getShape()` call, but then later when I try to draw that eg with `drawer.contours(shape.contours)` I get an error  
> ` could not compile vertex shader (Exception)`  
> Any idea?

---

<div class="post-metadata">

**Author:** ![axel](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/axel/32/146_2.png) [@axel](https://openrndr.discourse.group/u/axel)\
**Post date:** [September 27, 2020, 6:09pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/19 "2020-09-27T18:09:20Z")

</div>

Another question: could it be that in the CLOSE section something is missing like a

```auto
if ((anchor - cursor).length > 0.001) {
    segments.add(Segment(cursor, anchor))
}

```

? Without that, if I draw an “I” with fill, it looks like:

![image](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/ec48856f32050dffcea1ab55afe41c1827227730.png)

so there seems to be Segment missing.  
With that addition (having set the `anchor` in the `SEG_MOVETO`) it looks correct like

![image](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/3d359b7a9ec7092e25d7eb5264d65f978d73d981.png)

---

<div class="post-metadata">

**Author:** ![ricardo](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/ricardo/32/8_2.png) [@ricardo](https://openrndr.discourse.group/u/ricardo)\
**Post date:** [October 17, 2020, 1:07pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/20 "2020-10-17T13:07:14Z")

</div>

@axel Did you manage to figure out the segments issue? Do you have some code you can share as an example?

---

<div class="post-metadata">

**Author:** ![axel](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/axel/32/146_2.png) [@axel](https://openrndr.discourse.group/u/axel)\
**Post date:** [October 17, 2020, 5:02pm UTC](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105/21 "2020-10-17T17:02:40Z")

</div>

The code with the mentioned change (the addition to the CLOSE part) is working for me currently, but then, I did not yet try the latest OpenRNDR version. My question was meant to ask whether I should expect the code as given by @sidec originally to work, or whether my observation is a required fix.

[Next page](https://openrndr.discourse.group/t/drawing-text-with-non-latin-alphabet/105.md?page=2)
