Those are interesting issues. I had no problems with missing segments, even using some crazy Polish diacritics or Greek @axel where exactly did you put anchor
variable? Also I haven’t tested with the latest OpenRNDR and I don’t have any more access to osx, so I can test it only on Linux machines or maybe on win 10
also my code is just refactoring of this https://stackoverflow.com/questions/26563073/get-font-outlines-programmatically, it might be easier for someone to refer to this answer in case of any issues. also OpenRNDR Api for text object now includes an option for set of custom glyphs. My solution was intended only as walk around. it doesn’t of course mean that can not be used for its own to render shapes from glyphs.
Sorry that I never came back on this - I have tried that today with OpenRNDR 0.3.44 - still the same.
Maybe I expressed myself wrongly - not sure whether ‘missing segment’ is the right word - the outline seems correct without any change, but for the area fill to be correct, I need that additional statement in CLOSE.
So compared to your getPoints
code above, mine reads:
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)
var anchor = 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")
// --- added next 3 lines as otherwise are does not see to be closed
if ((anchor - cursor).length > 0.001) {
segments.add(Segment(cursor, anchor))
}
// ---------------------
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]
anchor = Vector2(x1, y1)
x = x1
y = y1
}
}
cursor = Vector2(x, y)
if (segment != null) {
segments.add(segment)
}
iterator.next()
}
return Shape(contours)
}
The above given figures with the ‘I’ letter are produced by these lines:
drawer.clear(ColorRGBa.PINK)
val shape = "I".getShape("Arial", Vector2(width/4.0,height/2.0))
drawer.fill = ColorRGBa.BLUE
drawer.stroke = ColorRGBa.RED
drawer.shape(shape)
So, without the additional 3 lines marked above int the SEG_CLOSE
section, the fill is not complete, with them it looks fine.
In any case, thank you very much for the helpful code - for me things are fine this way.