Better fallback
This commit is contained in:
parent
8a88cd29fa
commit
a8e1943556
2 changed files with 67 additions and 30 deletions
|
@ -112,51 +112,65 @@ proc hasGlyph*(typeface: Typeface, rune: Rune): bool {.inline.} =
|
|||
else:
|
||||
typeface.svgFont.hasGlyph(rune)
|
||||
|
||||
proc fallbackTypeface*(typeface: Typeface, rune: Rune): Typeface =
|
||||
## Looks through fallback typefaces to find one that has the glyph.
|
||||
if typeface.hasGlyph(rune):
|
||||
return typeface
|
||||
for fallback in typeface.fallbacks:
|
||||
let typeface = fallback.fallbackTypeface(rune)
|
||||
if typeface != nil:
|
||||
return typeface
|
||||
|
||||
proc getGlyphPath*(
|
||||
typeface: Typeface, rune: Rune
|
||||
): Path {.inline, raises: [PixieError].} =
|
||||
## The glyph path for the rune.
|
||||
result = newPath()
|
||||
if typeface.hasGlyph(rune):
|
||||
if typeface.opentype != nil:
|
||||
result.addPath(typeface.opentype.getGlyphPath(rune))
|
||||
else:
|
||||
result.addPath(typeface.svgFont.getGlyphPath(rune))
|
||||
|
||||
let typeface2 = typeface.fallbackTypeface(rune)
|
||||
if typeface2 == nil:
|
||||
return
|
||||
|
||||
if typeface2.opentype != nil:
|
||||
result.addPath(typeface2.opentype.getGlyphPath(rune))
|
||||
else:
|
||||
for fallback in typeface.fallbacks:
|
||||
if fallback.hasGlyph(rune):
|
||||
result = fallback.getGlyphPath(rune)
|
||||
let ratio = typeface.scale / fallback.scale
|
||||
result.transform(scale(vec2(ratio, ratio)))
|
||||
result.addPath(typeface2.svgFont.getGlyphPath(rune))
|
||||
|
||||
# Apply typeface ratio.
|
||||
let ratio = typeface.scale / typeface2.scale
|
||||
if ratio != 1.0:
|
||||
result.transform(scale(vec2(ratio, ratio)))
|
||||
|
||||
proc getAdvance*(typeface: Typeface, rune: Rune): float32 {.inline, raises: [].} =
|
||||
## The advance for the rune in pixels.
|
||||
if typeface.hasGlyph(rune):
|
||||
if typeface.opentype != nil:
|
||||
return typeface.opentype.getAdvance(rune)
|
||||
else:
|
||||
return typeface.svgFont.getAdvance(rune)
|
||||
else:
|
||||
for fallback in typeface.fallbacks:
|
||||
if fallback.hasGlyph(rune):
|
||||
result = fallback.getAdvance(rune)
|
||||
let ratio = typeface.scale / fallback.scale
|
||||
result *= ratio
|
||||
return
|
||||
let typeface2 = typeface.fallbackTypeface(rune)
|
||||
if typeface2 == nil:
|
||||
return
|
||||
|
||||
if typeface.opentype != nil:
|
||||
return typeface.opentype.getAdvance(rune)
|
||||
else:
|
||||
return typeface.svgFont.getAdvance(rune)
|
||||
if typeface2.opentype != nil:
|
||||
result = typeface2.opentype.getAdvance(rune)
|
||||
else:
|
||||
result = typeface2.svgFont.getAdvance(rune)
|
||||
|
||||
# Apply typeface ratio.
|
||||
result *= typeface.scale / typeface2.scale
|
||||
|
||||
proc getKerningAdjustment*(
|
||||
typeface: Typeface, left, right: Rune
|
||||
): float32 {.inline, raises: [].} =
|
||||
## The kerning adjustment for the rune pair, in pixels.
|
||||
if typeface.opentype != nil:
|
||||
typeface.opentype.getKerningAdjustment(left, right)
|
||||
else:
|
||||
typeface.svgfont.getKerningAdjustment(left, right)
|
||||
let
|
||||
typefaceRight = typeface.fallbackTypeface(right)
|
||||
typefaceLeft = typeface.fallbackTypeface(left)
|
||||
# Only do kerning if both typefaces are the same.
|
||||
if typefaceRight == typefaceLeft:
|
||||
if typefaceRight.opentype != nil:
|
||||
result = typefaceRight.opentype.getKerningAdjustment(left, right)
|
||||
else:
|
||||
result = typefaceRight.svgfont.getKerningAdjustment(left, right)
|
||||
|
||||
# Apply typeface ratio.
|
||||
result *= typeface.scale / typefaceRight.scale
|
||||
|
||||
proc scale*(font: Font): float32 {.inline, raises: [].} =
|
||||
## The scale factor to transform font units into pixels.
|
||||
|
|
|
@ -1068,3 +1068,26 @@ block:
|
|||
image.fillText(font, "Grumpy ウィザード make 有毒な醸造 for the 悪い女王 and Jack.")
|
||||
|
||||
doDiff(image, "fallback")
|
||||
|
||||
block:
|
||||
let
|
||||
font = readFont("tests/fonts/Inter-Regular.ttf")
|
||||
typeface1 = readTypeface("tests/fonts/Aclonica-Regular_1.ttf")
|
||||
typeface2 = readTypeface("tests/fonts/Ubuntu-Regular_1.ttf")
|
||||
typeface3 = readTypeface("tests/fonts/NotoSansJP-Regular.ttf")
|
||||
|
||||
# font
|
||||
# |.... typeface1
|
||||
# |.... typeface2
|
||||
# |.... typeface3 (with JP)
|
||||
|
||||
font.typeface.fallbacks.add(typeface1)
|
||||
typeface1.fallbacks.add(typeface2)
|
||||
typeface1.fallbacks.add(typeface3)
|
||||
|
||||
font.size = 26
|
||||
let image = newImage(800, 100)
|
||||
image.fill(rgba(255, 255, 255, 255))
|
||||
image.fillText(font, "Grumpy ウィザード make 有毒な醸造 for the 悪い女王 and Jack.")
|
||||
|
||||
doDiff(image, "fallback2")
|
||||
|
|
Loading…
Reference in a new issue