Skip to content

Commit 3b65ca5

Browse files
authored
Merge pull request #552 from Nimaoth/master
added support for open type format 12
2 parents 2ce0404 + f192718 commit 3b65ca5

File tree

5 files changed

+56
-2
lines changed

5 files changed

+56
-2
lines changed

pixie.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version = "5.0.6"
1+
version = "5.0.7"
22
author = "Andre von Houck and Ryan Oldenburg"
33
description = "Full-featured 2d graphics library for Nim."
44
license = "MIT"

src/pixie/fontformats/opentype.nim

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ proc parseCmapTable(buf: string, offset: int): CmapTable =
455455

456456
let format = buf.readUint16(i + 0).swap()
457457
if format == 4:
458+
# https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#format-4-segment-mapping-to-delta-values
458459
type Format4 = object
459460
format: uint16
460461
length: uint16
@@ -518,8 +519,46 @@ proc parseCmapTable(buf: string, offset: int): CmapTable =
518519
if c != 65535:
519520
result.runeToGlyphId[Rune(c)] = glyphId.uint16
520521
result.glyphIdToRune[glyphId.uint16] = Rune(c)
522+
523+
elif format == 12:
524+
# https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#format-12-segmented-coverage
525+
type Format12 = object
526+
format: uint16
527+
reserved: uint16
528+
length: uint32
529+
language: uint32
530+
numGroups: uint32
531+
532+
buf.eofCheck(i + 16)
533+
534+
var subTable: Format12
535+
subTable.format = format
536+
subTable.reserved = buf.readUint16(i + 2).swap()
537+
subTable.length = buf.readUint32(i + 4).swap()
538+
subTable.language = buf.readUint32(i + 8).swap()
539+
subTable.numGroups = buf.readUint32(i + 12).swap()
540+
i += 16
541+
542+
buf.eofCheck(i + subTable.numGroups.int * 12)
543+
544+
for k in 0 ..< subTable.numGroups:
545+
let startCharCode = buf.readUint32(i + 0).swap()
546+
let endCharCode = buf.readUint32(i + 4).swap()
547+
let startGlyphId = buf.readUint32(i + 8).swap()
548+
549+
for c in startCharCode .. endCharCode:
550+
let glyphId = startGlyphId + (c - startCharCode)
551+
if glyphId > uint16.high:
552+
# TODO: currently only 16 bit glyph ids are supported
553+
raise newException(PixieError, "Found glyph outside of uint16 range: " & $glyphId)
554+
555+
result.runeToGlyphId[Rune(c)] = uint16(glyphId)
556+
result.glyphIdToRune[uint16(glyphId)] = Rune(c)
557+
558+
i += 12
559+
521560
else:
522-
# TODO implement other Windows encodingIDs
561+
# TODO implement other windows formats
523562
discard
524563
else:
525564
# TODO implement other cmap platformIDs

tests/fonts/NotoEmoji.otf

2.17 MB
Binary file not shown.

tests/fonts/masters/emoji.png

101 KB
Loading

tests/test_fonts.nim

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ proc wh(image: Image): Vec2 =
44
## Return with and height as a size vector.
55
vec2(image.width.float32, image.height.float32)
66

7+
block:
8+
var font = readFont("tests/fonts/NotoEmoji.otf")
9+
font.size = 26
10+
let image = newImage(800, 300)
11+
image.fill(rgba(255, 255, 255, 255))
12+
image.fillText(font, """
13+
🚑🐑👭🔉🚷🦣💆🔁💺🚵🕦🔦🗓🦟😶🦄⌛🍙😄🇽
14+
🐠💓🦗🎭🏛🔴🫕🧶🍖🦁🏋🌗🛬🕐💡👉🎯🕔🚏🚲
15+
🐵🎍💳🥬🟦🪘📠📊🎧🎦🎁🌌🪲🦩🤢☎🚺🚾👺🚃
16+
🐨🌆🥉💭🗳🦵🟪📆🥮⏯🩴💷🦲➗🌶🧜🖖⏰🛗🔻
17+
📁🧞😃🌴🚶󾠫🦙🔎⏲🔵🖐☦😪🌯🙆🇺😂🍅🇿🚟🤜
18+
📼👰🍁📽☪🔄🤝🔧🦸🏰🏳🔜🎥🚋🇫🦨🏜🆖🏤🪖⏏""")
19+
20+
image.xray("tests/fonts/masters/emoji.png")
21+
722
block:
823
var font = readFont("tests/fonts/Roboto-Regular_1.ttf")
924
font.size = 24

0 commit comments

Comments
 (0)