Seperate the idea layout and pixel bounds.
This commit is contained in:
parent
e67a43ee7f
commit
2365004c9c
|
@ -482,7 +482,7 @@ proc measureText*(ctx: Context, text: string): TextMetrics {.raises: [PixieError
|
|||
## text (such as its width, for example).
|
||||
let
|
||||
font = newFont(ctx)
|
||||
bounds = typeset(font, text).computeBounds()
|
||||
bounds = typeset(font, text).layoutBounds()
|
||||
result.width = bounds.x
|
||||
|
||||
proc getLineDash*(ctx: Context): seq[float32] {.inline, raises: [].} =
|
||||
|
|
|
@ -467,7 +467,7 @@ proc typeset*(
|
|||
## wrap: enable/disable text wrapping
|
||||
typeset(@[newSpan(text, font)], bounds, hAlign, vAlign, wrap)
|
||||
|
||||
proc computeBounds*(arrangement: Arrangement): Vec2 {.raises: [].} =
|
||||
proc layoutBounds*(arrangement: Arrangement): Vec2 {.raises: [].} =
|
||||
## Computes the width and height of the arrangement in pixels.
|
||||
if arrangement.runes.len > 0:
|
||||
for i in 0 ..< arrangement.runes.len:
|
||||
|
@ -481,13 +481,13 @@ proc computeBounds*(arrangement: Arrangement): Vec2 {.raises: [].} =
|
|||
# If the text ends with a new line, we need add another line height.
|
||||
result.y += finalRect.h
|
||||
|
||||
proc computeBounds*(font: Font, text: string): Vec2 {.inline, raises: [].} =
|
||||
proc layoutBounds*(font: Font, text: string): Vec2 {.inline, raises: [].} =
|
||||
## Computes the width and height of the text in pixels.
|
||||
font.typeset(text).computeBounds()
|
||||
font.typeset(text).layoutBounds()
|
||||
|
||||
proc computeBounds*(spans: seq[Span]): Vec2 {.inline, raises: [].} =
|
||||
proc layoutBounds*(spans: seq[Span]): Vec2 {.inline, raises: [].} =
|
||||
## Computes the width and height of the spans in pixels.
|
||||
typeset(spans).computeBounds()
|
||||
typeset(spans).layoutBounds()
|
||||
|
||||
proc parseOtf*(buf: string): Typeface {.raises: [PixieError].} =
|
||||
result = Typeface()
|
||||
|
@ -583,6 +583,57 @@ proc textUber(
|
|||
else: # target is Mask
|
||||
target.fillPath(path, transform)
|
||||
|
||||
proc computeBounds*(
|
||||
arrangement: Arrangement,
|
||||
): Rect =
|
||||
var
|
||||
fullPath = newPath()
|
||||
line: int
|
||||
for spanIndex, (start, stop) in arrangement.spans:
|
||||
let
|
||||
font = arrangement.fonts[spanIndex]
|
||||
underlineThickness = font.typeface.underlineThickness * font.scale
|
||||
underlinePosition = font.typeface.underlinePosition * font.scale
|
||||
strikeoutThickness = font.typeface.strikeoutThickness * font.scale
|
||||
strikeoutPosition = font.typeface.strikeoutPosition * font.scale
|
||||
for runeIndex in start .. stop:
|
||||
let position = arrangement.positions[runeIndex]
|
||||
|
||||
let path = font.typeface.getGlyphPath(arrangement.runes[runeIndex])
|
||||
path.transform(
|
||||
translate(position) *
|
||||
scale(vec2(font.scale))
|
||||
)
|
||||
|
||||
var applyDecoration = true
|
||||
if runeIndex == arrangement.lines[line][1]:
|
||||
inc line
|
||||
if arrangement.runes[runeIndex] == SP:
|
||||
# Do not apply decoration to the space at end of lines
|
||||
applyDecoration = false
|
||||
|
||||
if applyDecoration:
|
||||
if font.underline:
|
||||
path.rect(
|
||||
arrangement.selectionRects[runeIndex].x,
|
||||
position.y - underlinePosition + underlineThickness / 2,
|
||||
arrangement.selectionRects[runeIndex].w,
|
||||
underlineThickness,
|
||||
font.typeface.isCCW()
|
||||
)
|
||||
if font.strikethrough:
|
||||
path.rect(
|
||||
arrangement.selectionRects[runeIndex].x,
|
||||
position.y - strikeoutPosition,
|
||||
arrangement.selectionRects[runeIndex].w,
|
||||
strikeoutThickness,
|
||||
font.typeface.isCCW()
|
||||
)
|
||||
|
||||
fullPath.addPath(path)
|
||||
|
||||
fullPath.computeBounds()
|
||||
|
||||
proc fillText*(
|
||||
target: Image | Mask,
|
||||
arrangement: Arrangement,
|
||||
|
|
BIN
tests/fonts/PinyonScript.ttf
Normal file
BIN
tests/fonts/PinyonScript.ttf
Normal file
Binary file not shown.
BIN
tests/fonts/diffs/spans7.png
Normal file
BIN
tests/fonts/diffs/spans7.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
tests/fonts/masters/spans7.png
Normal file
BIN
tests/fonts/masters/spans7.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
BIN
tests/fonts/rendered/spans7.png
Normal file
BIN
tests/fonts/rendered/spans7.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -16,14 +16,14 @@ block:
|
|||
var font = readFont("tests/fonts/Roboto-Regular_1.ttf")
|
||||
font.size = 24
|
||||
|
||||
let bounds = font.computeBounds("Word")
|
||||
let bounds = font.layoutBounds("Word")
|
||||
doAssert bounds == vec2(56, 28)
|
||||
|
||||
block:
|
||||
var font = readFont("tests/fonts/Roboto-Regular_1.ttf")
|
||||
font.size = 24
|
||||
|
||||
let bounds = font.computeBounds("Word\n")
|
||||
let bounds = font.layoutBounds("Word\n")
|
||||
doAssert bounds == vec2(56, 56)
|
||||
|
||||
block:
|
||||
|
@ -996,6 +996,48 @@ block:
|
|||
|
||||
doDiff(image, "spans6")
|
||||
|
||||
block:
|
||||
|
||||
let typeface1 = readTypeface("tests/fonts/PinyonScript.ttf")
|
||||
|
||||
var font1 = newFont(typeface1)
|
||||
font1.size = 82
|
||||
font1.lineHeight = 60
|
||||
font1.paint = "#000000"
|
||||
|
||||
let spans = @[
|
||||
newSpan("Fancy text", font1),
|
||||
]
|
||||
|
||||
let image = newImage(400, 400)
|
||||
image.fill(rgba(255, 255, 255, 255))
|
||||
let ctx = newContext(image)
|
||||
ctx.fillStyle = "#FFD6D6"
|
||||
ctx.fillRect(rect(40, 170, 320, 60))
|
||||
|
||||
let arrangement = typeset(spans, bounds = vec2(320, 60))
|
||||
|
||||
echo arrangement.layoutBounds()
|
||||
echo arrangement.computeBounds()
|
||||
echo arrangement.computeBounds().snapToPixels()
|
||||
|
||||
let snappedBounds = arrangement.computeBounds().snapToPixels()
|
||||
|
||||
let textImage = newImage(snappedBounds.w.int, snappedBounds.h.int)
|
||||
textImage.fillText(arrangement, translate(-snappedBounds.xy))
|
||||
|
||||
image.draw(textImage, translate(snappedBounds.xy + vec2(40, 170)))
|
||||
|
||||
# Enable this to show bounds
|
||||
# ctx.strokeStyle = "#FF0000"
|
||||
# ctx.translate(vec2(40, 170))
|
||||
# ctx.strokeRect(arrangement.computeBounds())
|
||||
|
||||
# Enable this to show how text is drawing directly
|
||||
# image.fillText(arrangement, translate(vec2(40, 170)))
|
||||
|
||||
doDiff(image, "spans7")
|
||||
|
||||
block:
|
||||
var font = readFont("tests/fonts/Roboto-Regular_1.ttf")
|
||||
font.size = 36
|
||||
|
|
Loading…
Reference in a new issue