Skip to content

Commit

Permalink
text overflow
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusandra committed Apr 23, 2024
1 parent 3d51e7a commit 3dcc31d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 26 deletions.
84 changes: 58 additions & 26 deletions frameos/src/apps/text/app.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import pixie, options
import pixie, options, json, strformat

import frameos/types
import frameos/utils/font
Expand All @@ -14,6 +14,7 @@ type
fontSize*: float
borderColor*: Color
borderWidth*: int
overflow*: string

RenderData* = object
text*: string
Expand Down Expand Up @@ -57,30 +58,61 @@ proc `==`(obj1, obj2: RenderData): bool =
obj1.fontSize == obj2.fontSize and obj1.borderColor ==
obj2.borderColor and obj1.borderWidth == obj2.borderWidth

proc generateTypeset(typeface: Typeface, renderData: RenderData,
proc generateTypeset(self: App, typeface: Typeface, renderData: RenderData,
border: bool): Arrangement =

let font = if border:
newFont(typeface, renderData.fontSize, renderData.borderColor)
else:
newFont(typeface, renderData.fontSize, renderData.fontColor)

let hAlign = case renderData.position:
of "top-right", "center-right", "bottom-right": RightAlign
of "top-left", "center-left", "bottom-left": LeftAlign
else: CenterAlign
let vAlign = case renderData.position:
of "top-left", "top-center", "top-right": TopAlign
of "bottom-left", "bottom-center", "bottom-right": BottomAlign
else: MiddleAlign

result = typeset(
spans = [newSpan(renderData.text, font)],
bounds = vec2(renderData.width.toFloat() - 2 * renderData.padding,
renderData.height.toFloat() - 2 * renderData.padding),
hAlign = hAlign,
vAlign = vAlign,
)
let
hAlign = case renderData.position:
of "top-right", "center-right", "bottom-right": RightAlign
of "top-left", "center-left", "bottom-left": LeftAlign
else: CenterAlign
vAlign = case renderData.position:
of "top-left", "top-center", "top-right": TopAlign
of "bottom-left", "bottom-center", "bottom-right": BottomAlign
else: MiddleAlign
color = if border: renderData.borderColor else: renderData.fontColor
width = renderData.width.toFloat() - 2 * renderData.padding
height = renderData.height.toFloat() - 2 * renderData.padding
bounds = vec2(width, height)
font = newFont(typeface, renderData.fontSize, color)

if self.appConfig.overflow == "visible":
return typeset([newSpan(renderData.text, font)], bounds, hAlign, vAlign)

else: # "fit-bounds"
var tooBigFontSize = 0.0
var tooSmallFontSize = 0.0
var loopIndex = 0
while loopIndex < 100:
loopIndex += 1
result = typeset([newSpan(renderData.text, font)], bounds, hAlign, vAlign)
let bounds = layoutBounds(result)

# if the text is too big, shrink the font size
if bounds.y > height:
if font.size < 2:
break

# try to get closer based on the ratio
tooBigFontSize = font.size
if tooSmallFontSize > 0.0:
font.size = (tooBigFontSize + tooSmallFontSize) / 2
else:
font.size = tooBigFontSize / 2
continue

# we're in bounds, and on the first run (text was never too big), so return
elif tooBigFontSize == 0.0:
break

# the text is too small, and was once too big
else:
if height - bounds.y < 1:
break
tooSmallFontSize = font.size
if tooBigFontSize - tooSmallFontSize < 0.5:
break
font.size = (tooBigFontSize + tooSmallFontSize) / 2
continue

proc run*(self: App, context: ExecutionContext) =
let renderData = RenderData(
Expand All @@ -97,11 +129,11 @@ proc run*(self: App, context: ExecutionContext) =

let cacheMatch = self.cachedRender.isSome and self.cachedRender.get().renderData == renderData
let textTypeset = if cacheMatch: self.cachedRender.get().typeset
else: generateTypeset(self.typeface, renderData, false)
else: self.generateTypeset(self.typeface, renderData, false)
let borderTypeset = if renderData.borderWidth > 0:
if cacheMatch:
self.cachedRender.get().borderTypeset
else: some(generateTypeset(self.typeface, renderData, true))
else: some(self.generateTypeset(self.typeface, renderData, true))
else: none(Arrangement)

if not cacheMatch:
Expand Down
10 changes: 10 additions & 0 deletions frameos/src/apps/text/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@
"required": true,
"label": "Border width",
"placeholder": "1"
},
{
"name": "overflow",
"type": "select",
"options": [
"fit-bounds",
"visible"
],
"value": "fit-bounds",
"label": "Overflow"
}
]
}

0 comments on commit 3dcc31d

Please sign in to comment.