kerning
This commit is contained in:
parent
9dc96f45ce
commit
4bdcc67baa
|
@ -15,6 +15,7 @@ type
|
|||
numTables*: uint16
|
||||
encodingRecords*: seq[EncodingRecord]
|
||||
runeToGlyphId*: Table[Rune, uint16]
|
||||
glyphIdToRune*: Table[uint16, Rune]
|
||||
|
||||
HeadTable* = ref object
|
||||
majorVersion*: uint16
|
||||
|
@ -295,6 +296,7 @@ proc parseCmapTable(buf: string, offset: int): CmapTable =
|
|||
|
||||
if c != 65535:
|
||||
result.runeToGlyphId[Rune(c)] = glyphId.uint16
|
||||
result.glyphIdToRune[glyphId.uint16] = Rune(c)
|
||||
else:
|
||||
# TODO implement other Windows encodingIDs
|
||||
discard
|
||||
|
@ -563,13 +565,13 @@ proc parseKernTable(buf: string, offset: int): KernTable =
|
|||
else:
|
||||
failUnsupported()
|
||||
|
||||
proc getGlyphId*(opentype: OpenType, rune: Rune): int =
|
||||
proc getGlyphId*(opentype: OpenType, rune: Rune): uint16 =
|
||||
if rune in opentype.cmap.runeToGlyphId:
|
||||
result = opentype.cmap.runeToGlyphId[rune].int
|
||||
result = opentype.cmap.runeToGlyphId[rune]
|
||||
else:
|
||||
discard # Index 0 is the "missing character" glyph
|
||||
|
||||
proc parseGlyph(opentype: OpenType, glyphId: int): Path
|
||||
proc parseGlyph(opentype: OpenType, glyphId: uint16): Path
|
||||
|
||||
proc parseGlyphPath(buf: string, offset, numberOfContours: int): Path =
|
||||
if numberOfContours < 0:
|
||||
|
@ -781,7 +783,7 @@ proc parseCompositeGlyph(opentype: OpenType, offset: int): Path =
|
|||
# elif (flags and 0b1000000000000) != 0: # UNSCALED_COMPONENT_OFFSET
|
||||
# discard
|
||||
|
||||
var subPath = opentype.parseGlyph(component.glyphId.int)
|
||||
var subPath = opentype.parseGlyph(component.glyphId)
|
||||
subPath.transform(mat3(
|
||||
component.xScale, component.scale10, 0.0,
|
||||
component.scale01, component.yScale, 0.0,
|
||||
|
@ -792,8 +794,8 @@ proc parseCompositeGlyph(opentype: OpenType, offset: int): Path =
|
|||
|
||||
moreComponents = (flags and 0b100000) != 0
|
||||
|
||||
proc parseGlyph(opentype: OpenType, glyphId: int): Path =
|
||||
if glyphId < 0 or glyphId >= opentype.glyf.offsets.len:
|
||||
proc parseGlyph(opentype: OpenType, glyphId: uint16): Path =
|
||||
if glyphId.int >= opentype.glyf.offsets.len:
|
||||
raise newException(PixieError, "Invalid glyph ID " & $glyphId)
|
||||
|
||||
let glyphOffset = opentype.glyf.offsets[glyphId]
|
||||
|
|
|
@ -6,6 +6,7 @@ type
|
|||
Font* = ref object
|
||||
opentype: OpenType
|
||||
glyphPaths: Table[Rune, Path]
|
||||
kerningPairs: Table[(Rune, Rune), float32]
|
||||
size*: float32 ## Font size in pixels.
|
||||
lineHeight*: float32 ## The line height in pixels or AutoLineHeight for the font's default line height.
|
||||
|
||||
|
@ -46,12 +47,17 @@ proc getGlyphPath*(font: Font, rune: Rune): Path =
|
|||
font.glyphPaths[rune]
|
||||
|
||||
proc getGlyphAdvance*(font: Font, rune: Rune): float32 =
|
||||
let glyphId = font.opentype.getGlyphId(rune)
|
||||
let glyphId = font.opentype.getGlyphId(rune).int
|
||||
if glyphId < font.opentype.hmtx.hMetrics.len:
|
||||
font.opentype.hmtx.hMetrics[glyphId].advanceWidth.float32
|
||||
else:
|
||||
font.opentype.hmtx.hMetrics[^1].advanceWidth.float32
|
||||
|
||||
proc getKerningAdjustment*(font: Font, left, right: Rune): float32 =
|
||||
let pair = (left, right)
|
||||
if pair in font.kerningPairs:
|
||||
result = font.kerningPairs[pair]
|
||||
|
||||
proc scale*(font: Font): float32 =
|
||||
## The scale factor to transform font units into pixels.
|
||||
font.size / font.opentype.head.unitsPerEm.float32
|
||||
|
@ -104,6 +110,9 @@ proc typeset*(
|
|||
if rune.canWrap():
|
||||
prevCanWrap = i
|
||||
|
||||
if i > 0:
|
||||
at.x += font.getKerningAdjustment(runes[i - 1], rune) * font.scale
|
||||
|
||||
let advance = font.getGlyphAdvance(rune) * font.scale
|
||||
if bounds.x > 0 and at.x + advance > bounds.x: # Wrap to new line
|
||||
at.x = 0
|
||||
|
@ -112,6 +121,8 @@ proc typeset*(
|
|||
# Go back and wrap glyphs after the wrap index down to the next line
|
||||
if prevCanWrap > 0 and prevCanWrap != i:
|
||||
for j in prevCanWrap + 1 ..< i:
|
||||
if j > 0:
|
||||
at.x += font.getKerningAdjustment(runes[j - 1], runes[j]) * font.scale
|
||||
positions[j] = at
|
||||
at.x += font.getGlyphAdvance(runes[j]) * font.scale
|
||||
|
||||
|
@ -129,5 +140,16 @@ proc parseOtf*(buf: string): Font =
|
|||
result.size = 12
|
||||
result.lineHeight = AutoLineHeight
|
||||
|
||||
if result.opentype.kern != nil:
|
||||
for table in result.opentype.kern.subTables:
|
||||
for pair in table.kernPairs:
|
||||
if pair.value != 0 and
|
||||
pair.left in result.opentype.cmap.glyphIdToRune and
|
||||
pair.right in result.opentype.cmap.glyphIdToRune:
|
||||
result.kerningPairs[(
|
||||
result.opentype.cmap.glyphIdToRune[pair.left],
|
||||
result.opentype.cmap.glyphIdToRune[pair.right]
|
||||
)] = pair.value.float32
|
||||
|
||||
proc parseTtf*(buf: string): Font =
|
||||
parseOtf(buf)
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.2 KiB |
Loading…
Reference in a new issue