Merge pull request #386 from guzba/master
4.0.1 fix for custom line-height on font
|
@ -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"
|
||||
|
|
|
@ -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 =
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
|
BIN
tests/fonts/Inter-Bold.ttf
Normal file
BIN
tests/fonts/diffs/customlineheight.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
BIN
tests/fonts/masters/customlineheight.png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
tests/fonts/rendered/customlineheight.png
Normal file
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
|