Merge pull request #280 from treeform/fonts1

Fix strikethough and underline for CFF fonts with winding flag.
This commit is contained in:
treeform 2021-09-07 13:18:31 -07:00 committed by GitHub
commit 163a087366
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 35 additions and 2 deletions

View file

@ -192,6 +192,7 @@ exportRefObject Typeface:
descent descent
lineGap lineGap
lineHeight lineHeight
hasGlyph
getGlyphPath getGlyphPath
getAdvance getAdvance
getKerningAdjustment getKerningAdjustment

View file

@ -1070,6 +1070,9 @@ proc parseCFFCharstring(cff: CffTable, code: string, glyphIndex: int): Path =
x += stack.pop() x += stack.pop()
p.moveTo(x, y) p.moveTo(x, y)
of 23: # vstemhm
parseStems()
of 24: # rcurveline of 24: # rcurveline
while stack.len > 2: while stack.len > 2:
let let
@ -2084,6 +2087,9 @@ proc parsePostTable(buf: string, offset: int): PostTable =
proc getGlyphId(opentype: OpenType, rune: Rune): uint16 = proc getGlyphId(opentype: OpenType, rune: Rune): uint16 =
result = opentype.cmap.runeToGlyphId.getOrDefault(rune, 0) result = opentype.cmap.runeToGlyphId.getOrDefault(rune, 0)
proc hasGlyph*(opentype: OpenType, rune: Rune): bool =
rune in opentype.cmap.runeToGlyphId
proc parseGlyfGlyph(opentype: OpenType, glyphId: uint16): Path {.raises: [PixieError].} proc parseGlyfGlyph(opentype: OpenType, glyphId: uint16): Path {.raises: [PixieError].}
proc parseGlyphPath( proc parseGlyphPath(
@ -2415,6 +2421,12 @@ proc getKerningAdjustment*(
elif opentype.kern != nil: elif opentype.kern != nil:
result = opentype.kern.kerningPairs.getOrDefault(glyphPair, 0) result = opentype.kern.kerningPairs.getOrDefault(glyphPair, 0)
proc isCCW*(opentype: OpenType): bool {.inline.} =
## Returns the expected winding order of a font.
## Gyph - false - clockwise
## CFF - true - counterclockwise
opentype.cff == nil
proc parseOpenType*(buf: string): OpenType {.raises: [PixieError].} = proc parseOpenType*(buf: string): OpenType {.raises: [PixieError].} =
result = OpenType() result = OpenType()
result.buf = buf result.buf = buf

View file

@ -11,6 +11,9 @@ type SvgFont* = ref object
proc getGlyphPath*(svgFont: SvgFont, rune: Rune): Path {.raises: [].} = proc getGlyphPath*(svgFont: SvgFont, rune: Rune): Path {.raises: [].} =
svgFont.glyphPaths.getOrDefault(rune, svgFont.missingGlyphPath) svgFont.glyphPaths.getOrDefault(rune, svgFont.missingGlyphPath)
proc hasGlyph*(svgFont: SvgFont, rune: Rune): bool =
rune in svgFont.glyphPaths
proc getAdvance*(svgFont: SvgFont, rune: Rune): float32 {.raises: [].} = proc getAdvance*(svgFont: SvgFont, rune: Rune): float32 {.raises: [].} =
svgFont.advances.getOrDefault(rune, svgFont.missingGlyphAdvance) svgFont.advances.getOrDefault(rune, svgFont.missingGlyphAdvance)

View file

@ -92,6 +92,11 @@ proc strikeoutThickness(typeface: Typeface): float32 =
if typeface.opentype != nil: if typeface.opentype != nil:
result = typeface.opentype.os2.yStrikeoutSize.float32 result = typeface.opentype.os2.yStrikeoutSize.float32
proc isCCW(typeface: Typeface): bool {.inline.} =
## Returns the expected winding order of a font.
if typeface.opentype != nil:
return typeface.opentype.isCCW()
proc getGlyphPath*( proc getGlyphPath*(
typeface: Typeface, rune: Rune typeface: Typeface, rune: Rune
): Path {.inline, raises: [PixieError].} = ): Path {.inline, raises: [PixieError].} =
@ -103,6 +108,16 @@ proc getGlyphPath*(
else: else:
result.addPath(typeface.svgFont.getGlyphPath(rune)) result.addPath(typeface.svgFont.getGlyphPath(rune))
proc hasGlyph*(typeface: Typeface, rune: Rune): bool {.inline.} =
## Returns if there is a glyph for this rune.
if rune.uint32 > SP.uint32: # Empty paths for control runes (not tofu)
if typeface.opentype != nil:
typeface.opentype.hasGlyph(rune)
else:
typeface.svgFont.hasGlyph(rune)
else:
false
proc getAdvance*(typeface: Typeface, rune: Rune): float32 {.inline, raises: [].} = proc getAdvance*(typeface: Typeface, rune: Rune): float32 {.inline, raises: [].} =
## The advance for the rune in pixels. ## The advance for the rune in pixels.
if typeface.opentype != nil: if typeface.opentype != nil:
@ -478,14 +493,16 @@ proc textUber(
arrangement.selectionRects[runeIndex].x, arrangement.selectionRects[runeIndex].x,
position.y - underlinePosition + underlineThickness / 2, position.y - underlinePosition + underlineThickness / 2,
arrangement.selectionRects[runeIndex].w, arrangement.selectionRects[runeIndex].w,
underlineThickness underlineThickness,
font.typeface.isCCW()
) )
if font.strikethrough: if font.strikethrough:
path.rect( path.rect(
arrangement.selectionRects[runeIndex].x, arrangement.selectionRects[runeIndex].x,
position.y - strikeoutPosition, position.y - strikeoutPosition,
arrangement.selectionRects[runeIndex].w, arrangement.selectionRects[runeIndex].w,
strikeoutThickness strikeoutThickness,
font.typeface.isCCW()
) )
when stroke: when stroke:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB