Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pixie.nimble
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = "4.0.0"
version = "4.0.1"
author = "Andre von Houck and Ryan Oldenburg"
description = "Full-featured 2d graphics library for Nim."
license = "MIT"
Expand Down
39 changes: 22 additions & 17 deletions src/pixie/fonts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ proc lineGap*(typeface: Typeface): float32 {.raises: [].} =

proc lineHeight*(typeface: Typeface): float32 {.inline, raises: [].} =
## The default line height in font units.
# The descent is negative number, so this is really ascent + descent + lineGap.
typeface.ascent - typeface.descent + typeface.lineGap

proc underlinePosition(typeface: Typeface): float32 =
Expand Down Expand Up @@ -186,6 +187,18 @@ proc defaultLineHeight*(font: Font): float32 {.inline, raises: [].} =
font.typeface.ascent - font.typeface.descent + font.typeface.lineGap
round(fontUnits * font.scale)

proc lineGap(font: Font): float32 =
## The line gap in font units for the current font size and line-height.
let lineHeight =
if font.lineHeight >= 0:
font.lineHeight
else:
font.defaultLineHeight
if lineHeight == font.defaultLineHeight:
font.typeface.lineGap
else:
(lineHeight / font.scale) - font.typeface.ascent + font.typeface.descent

proc paint*(font: Font): Paint {.inline, raises: [].} =
font.paints[0]

Expand Down Expand Up @@ -356,20 +369,10 @@ proc typeset*(
for spanIndex, (start, stop) in result.spans:
let
font = result.fonts[spanIndex]
lineHeight =
if font.lineHeight >= 0:
font.lineHeight
else:
font.defaultLineHeight
var fontUnitInitialY = font.typeface.ascent + font.typeface.lineGap / 2
if lineHeight != font.defaultLineHeight:
fontUnitInitialY += (
(lineHeight / font.scale) - font.typeface.lineHeight
) / 2
fontUnitInitialY = font.typeface.ascent + font.lineGap / 2
maxInitialY = max(maxInitialY, round(fontUnitInitialY * font.scale))
for runeIndex in start .. stop:
if runeIndex == result.lines[0][1]:
break outer
if stop >= result.lines[0][1]:
break outer
maxInitialY

var lineHeights = newSeq[float32](result.lines.len)
Expand All @@ -385,6 +388,8 @@ proc typeset*(
font.defaultLineHeight
lineHeights[line] = max(lineHeights[line], fontLineHeight)
for runeIndex in start .. stop:
# This span could be many lines. This check can be made faster by
# hopping based on line endings instead of checking each index.
if line + 1 < result.lines.len and
runeIndex == result.lines[line + 1][0]:
inc line
Expand All @@ -401,8 +406,8 @@ proc typeset*(
let
font = result.fonts[spanIndex]
lineHeight =
if font.lineheight >= 0:
font.lineheight
if font.lineHeight >= 0:
font.lineHeight
else:
font.defaultLineHeight
for runeIndex in start .. stop:
Expand All @@ -411,8 +416,8 @@ proc typeset*(
inc line
baseline += lineHeights[line]
result.positions[runeIndex].y = baseline
result.selectionRects[runeIndex].y =
baseline - round(font.typeface.ascent * font.scale)
result.selectionRects[runeIndex].y = baseline -
round((font.typeface.ascent + font.lineGap / 2) * font.scale)
result.selectionRects[runeIndex].h = lineHeight

if vAlign != TopAlign:
Expand Down
Binary file added tests/fonts/Inter-Bold.ttf
Binary file not shown.
Binary file added tests/fonts/diffs/customlineheight.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/fonts/diffs/selection_rects1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/fonts/diffs/selection_rects2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/fonts/masters/customlineheight.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/fonts/rendered/customlineheight.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/fonts/rendered/selection_rects1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/fonts/rendered/selection_rects2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions tests/test_fonts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1101,3 +1101,61 @@ block:
image.fillText(font, "This[]Advance!")

doDiff(image, "tofu_advance")

block:
let image = newImage(200, 200)
image.fill(color(1, 1, 1, 1))

let paint = newPaint(SolidPaint)
paint.color = color(1, 0, 0, 1)

let ctx = newContext(image)
ctx.lineWidth = 1
ctx.strokeStyle = paint
ctx.strokeRect(0, 60, 200, 80)

let text = "AbCd\naBcD"

let font = pixie.read_font("tests/fonts/Inter-Bold.ttf")
font.size = 40
font.line_height = 27

let arrangement1 = font.typeset(
text,
vec2(200, 80),
CenterAlign,
TopAlign
)

# let p1 = newPath()
# p1.rect(arrangement1.selectionRects[0])
# image.fillpath(p1, rgba(196, 196, 196, 255), translate(vec2(0, 266)))

font.paint.color = color(1, 0, 0, 1)
image.fillText(arrangement1, translate(vec2(0, 60)))

let arrangement2 = font.typeset(
text,
vec2(200, 80),
CenterAlign,
MiddleAlign
)

# let p2 = newPath()
# p2.rect(arrangement2.selectionRects[0])
# image.fillpath(p2, rgba(196, 196, 196, 255), translate(vec2(0, 266)))

font.paint.color = color(0, 1, 0, 1)
image.fillText(arrangement2, translate(vec2(0, 60)))

font.paint.color = color(0, 0, 1, 1)
image.fillText(
font,
text,
bounds = vec2(200, 80),
hAlign = CenterAlign,
vAlign = BottomAlign,
transform = translate(vec2(0, 60))
)

doDiff(image, "customlineheight")
6 changes: 3 additions & 3 deletions tests/test_paints.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ block:
heartShape,
rgba(255, 0, 0, 255)
)
image.writeFile("tests/paths/SolidPaint.png")
image.writeFile("tests/paths/paintSolid.png")

block:
let paint = newPaint(ImagePaint)
Expand All @@ -23,7 +23,7 @@ block:

let image = newImage(100, 100)
image.fillPath(heartShape, paint)
image.writeFile("tests/paths/ImagePaint.png")
image.writeFile("tests/paths/paintImage.png")

block:
let paint = newPaint(ImagePaint)
Expand All @@ -42,7 +42,7 @@ block:

let image = newImage(100, 100)
image.fillPath(heartShape, paint)
image.writeFile("tests/paths/TiledImagePaint.png")
image.writeFile("tests/paths/paintImageTiled.png")

block:
let paint = newPaint(TiledImagePaint)
Expand Down