I've made this proc for making this feature for me, it behaves like the Microsoft Word.
import
pixie,
unicode
const
LF = Rune(10)
NR = Rune(0)
proc justifyArrangement*(arrangement: Arrangement, maxWidth: float32) {.raises: [].} =
proc right(rect: Rect): float32 = rect.x + rect.w
let
runes: ptr = arrangement.runes.addr
positions: ptr = arrangement.positions.addr
rects: ptr = arrangement.selectionRects.addr
lastLineId: int = arrangement.lines.len-1
var
rune, lastRune: Rune
lastWordRuneId: int
spacesIdx: seq[int]
incWidth, spaceWidth, lineWidth, xOffset: float32
for lineId, (start, stop) in arrangement.lines:
lastRune = runes[stop]
# This line must not be justified, if it's the last or if the last rune is a breakline char.
if lineId == lastLineId or lastRune == LF:
continue
echo runes[start..stop]
# Get the spaces indexes of this line to increase their width, and get the line width.
# Spaces in the end will be pushed away the maxWidth like the Microsoft Word.
spacesIdx = @[]
lastRune = NR
for rId in start..stop:
rune = runes[rId]
if not rune.isWhiteSpace():
if lastRune.isWhiteSpace():
spacesIdx.add(rId-1)
lastWordRuneId = rId
lastRune = rune
lineWidth = rects[lastWordRuneId].right
echo "Line spaces: ", spacesIdx.len
if spacesIdx.len > 0:
# Get the amount of pixels/units to increase each space width in the middle of the line.
incWidth = (maxWidth - lineWidth) / spacesIdx.len.float32
if incWidth > 0:
spaceWidth = rects[spacesIdx[0]].w + incWidth
# Adjust the runes X position
xOffset = 0
for rId in spacesIdx[0]..stop:
positions[rId].x += xOffset
rects[rId].x += xOffset
if rId in spacesIdx:
rects[rId].w = spaceWidth
xOffset += incWidth
Would be nice if add this alignment style.
I've made this proc for making this feature for me, it behaves like the Microsoft Word.