api changes, encoding fixed.
This commit is contained in:
parent
655099a64e
commit
a46a9ebf12
3 changed files with 86 additions and 14 deletions
|
@ -430,16 +430,21 @@ proc readVersion16Dot16(buf: string, offset: int): float32 =
|
||||||
failUnsupported("invalid version format")
|
failUnsupported("invalid version format")
|
||||||
majorDigit.float32 + minorDigit.float32 / 10
|
majorDigit.float32 + minorDigit.float32 / 10
|
||||||
|
|
||||||
proc convertUTF16(input: string): string =
|
func maybeSwap(u: uint16, swap: bool): uint16 =
|
||||||
|
if swap:
|
||||||
|
((u and 0xFF) shl 8) or ((u and 0xFF00) shr 8)
|
||||||
|
else:
|
||||||
|
u
|
||||||
|
|
||||||
|
proc fromUTF16Inner(input: string, i: var int, swap: bool): string =
|
||||||
## Converts UTF16 Big Endian to UTF8 string.
|
## Converts UTF16 Big Endian to UTF8 string.
|
||||||
var i = 0
|
while i + 1 < input.len:
|
||||||
while i < input.len:
|
var u1 = input.readUInt16(i).maybeSwap(swap)
|
||||||
var u1 = input.readUInt16(i)
|
|
||||||
i += 2
|
i += 2
|
||||||
if u1 - 0xd800 >= 0x800:
|
if u1 - 0xd800 >= 0x800:
|
||||||
result.add Rune(u1.int)
|
result.add Rune(u1.int)
|
||||||
else:
|
else:
|
||||||
var u2 = input.readUInt16(i)
|
var u2 = input.readUInt16(i).maybeSwap(swap)
|
||||||
i += 2
|
i += 2
|
||||||
if ((u1 and 0xfc00) == 0xd800) and ((u2 and 0xfc00) == 0xdc00):
|
if ((u1 and 0xfc00) == 0xd800) and ((u2 and 0xfc00) == 0xdc00):
|
||||||
result.add Rune((u1.uint32 shl 10) + u2.uint32 - 0x35fdc00)
|
result.add Rune((u1.uint32 shl 10) + u2.uint32 - 0x35fdc00)
|
||||||
|
@ -447,6 +452,11 @@ proc convertUTF16(input: string): string =
|
||||||
# Error, produce tofu character.
|
# Error, produce tofu character.
|
||||||
result.add "□"
|
result.add "□"
|
||||||
|
|
||||||
|
proc fromUTF16BE*(input: string): string =
|
||||||
|
## Converts UTF16 Big Endian to UTF8 string.
|
||||||
|
var i = 0
|
||||||
|
input.fromUTF16Inner(i, true)
|
||||||
|
|
||||||
proc parseCmapTable(buf: string, offset: int): CmapTable =
|
proc parseCmapTable(buf: string, offset: int): CmapTable =
|
||||||
var i = offset
|
var i = offset
|
||||||
buf.eofCheck(i + 4)
|
buf.eofCheck(i + 4)
|
||||||
|
@ -677,8 +687,11 @@ proc parseNameTable(buf: string, offset: int): NameTable =
|
||||||
(offset + result.stringOffset.int + record.offset.int) ..<
|
(offset + result.stringOffset.int + record.offset.int) ..<
|
||||||
(offset + result.stringOffset.int + record.offset.int + record.length.int)
|
(offset + result.stringOffset.int + record.offset.int + record.length.int)
|
||||||
]
|
]
|
||||||
if record.encodingID in {1, 3}:
|
if record.platformID == 3 and
|
||||||
record.text = convertUTF16(record.text)
|
record.encodingID == 1 and
|
||||||
|
record.languageID == 1033:
|
||||||
|
record.text = fromUTF16BE(record.text)
|
||||||
|
|
||||||
record.text = record.text
|
record.text = record.text
|
||||||
result.nameRecords.add(record)
|
result.nameRecords.add(record)
|
||||||
i += 12
|
i += 12
|
||||||
|
@ -2500,7 +2513,7 @@ proc fullName*(opentype: OpenType): string =
|
||||||
if opentype.cff != nil:
|
if opentype.cff != nil:
|
||||||
return opentype.cff.topDict.fullName
|
return opentype.cff.topDict.fullName
|
||||||
for record in opentype.name.nameRecords:
|
for record in opentype.name.nameRecords:
|
||||||
if record.nameID == 1:
|
if record.nameID == 6 and record.languageID == 1033:
|
||||||
return record.text
|
return record.text
|
||||||
|
|
||||||
proc parseOpenType*(buf: string, startLoc = 0): OpenType {.raises: [PixieError].} =
|
proc parseOpenType*(buf: string, startLoc = 0): OpenType {.raises: [PixieError].} =
|
||||||
|
|
|
@ -496,10 +496,6 @@ proc parseOtf*(buf: string): Typeface {.raises: [PixieError].} =
|
||||||
proc parseTtf*(buf: string): Typeface {.raises: [PixieError].} =
|
proc parseTtf*(buf: string): Typeface {.raises: [PixieError].} =
|
||||||
parseOtf(buf)
|
parseOtf(buf)
|
||||||
|
|
||||||
proc parseTtc*(buf: string): Typeface {.raises: [PixieError].} =
|
|
||||||
result = Typeface()
|
|
||||||
result.opentype = parseOpenTypeCollection(buf)[0]
|
|
||||||
|
|
||||||
proc parseSvgFont*(buf: string): Typeface {.raises: [PixieError].} =
|
proc parseSvgFont*(buf: string): Typeface {.raises: [PixieError].} =
|
||||||
result = Typeface()
|
result = Typeface()
|
||||||
result.svgFont = svgfont.parseSvgFont(buf)
|
result.svgFont = svgfont.parseSvgFont(buf)
|
||||||
|
@ -701,8 +697,6 @@ proc readTypeface*(filePath: string): Typeface {.raises: [PixieError].} =
|
||||||
parseTtf(readFile(filePath))
|
parseTtf(readFile(filePath))
|
||||||
of ".otf":
|
of ".otf":
|
||||||
parseOtf(readFile(filePath))
|
parseOtf(readFile(filePath))
|
||||||
of ".ttc":
|
|
||||||
parseTtc(readFile(filePath))
|
|
||||||
of ".svg":
|
of ".svg":
|
||||||
parseSvgFont(readFile(filePath))
|
parseSvgFont(readFile(filePath))
|
||||||
else:
|
else:
|
||||||
|
@ -712,6 +706,21 @@ proc readTypeface*(filePath: string): Typeface {.raises: [PixieError].} =
|
||||||
|
|
||||||
result.filePath = filePath
|
result.filePath = filePath
|
||||||
|
|
||||||
|
proc readTypefaces*(filePath: string): seq[Typeface] {.raises: [PixieError].} =
|
||||||
|
## Loads a OpenType Collection (.ttc).
|
||||||
|
try:
|
||||||
|
for opentype in parseOpenTypeCollection(readFile(filePath)):
|
||||||
|
let typeface = Typeface()
|
||||||
|
typeface.opentype = opentype
|
||||||
|
result.add(typeface)
|
||||||
|
except IOError as e:
|
||||||
|
raise newException(PixieError, e.msg, e)
|
||||||
|
|
||||||
|
proc name*(typeface: Typeface): string =
|
||||||
|
## Returns the name of the font.
|
||||||
|
if typeface.opentype != nil:
|
||||||
|
return typeface.opentype.fullName
|
||||||
|
|
||||||
proc readFont*(filePath: string): Font {.raises: [PixieError].} =
|
proc readFont*(filePath: string): Font {.raises: [PixieError].} =
|
||||||
## Loads a font from a file.
|
## Loads a font from a file.
|
||||||
newFont(readTypeface(filePath))
|
newFont(readTypeface(filePath))
|
||||||
|
|
|
@ -1196,3 +1196,53 @@ block:
|
||||||
)
|
)
|
||||||
|
|
||||||
doDiff(image, "customlineheight")
|
doDiff(image, "customlineheight")
|
||||||
|
|
||||||
|
block:
|
||||||
|
var font = readTypefaces("tests/fonts/PTSans.ttc")[0].newFont
|
||||||
|
font.size = 72
|
||||||
|
let image = newImage(200, 100)
|
||||||
|
image.fill(rgba(255, 255, 255, 255))
|
||||||
|
image.fillText(font, "AbCd")
|
||||||
|
|
||||||
|
block:
|
||||||
|
var typefaces = readTypefaces("tests/fonts/PTSans.ttc")
|
||||||
|
for i, typeface in typefaces:
|
||||||
|
echo i, ": ", typeface.name
|
||||||
|
|
||||||
|
when defined(windows):
|
||||||
|
block:
|
||||||
|
let files = @[
|
||||||
|
"/Windows/Fonts/batang.ttc",
|
||||||
|
"/Windows/Fonts/BIZ-UDGothicB.ttc",
|
||||||
|
"/Windows/Fonts/BIZ-UDGothicR.ttc",
|
||||||
|
"/Windows/Fonts/BIZ-UDMinchoM.ttc",
|
||||||
|
"/Windows/Fonts/cambria.ttc",
|
||||||
|
"/Windows/Fonts/gulim.ttc",
|
||||||
|
"/Windows/Fonts/meiryo.ttc",
|
||||||
|
"/Windows/Fonts/meiryob.ttc",
|
||||||
|
"/Windows/Fonts/mingliub.ttc",
|
||||||
|
"/Windows/Fonts/msgothic.ttc",
|
||||||
|
"/Windows/Fonts/msjh.ttc",
|
||||||
|
"/Windows/Fonts/msjhbd.ttc",
|
||||||
|
"/Windows/Fonts/msjhl.ttc",
|
||||||
|
"/Windows/Fonts/msmincho.ttc",
|
||||||
|
"/Windows/Fonts/msyh.ttc",
|
||||||
|
"/Windows/Fonts/msyhbd.ttc",
|
||||||
|
"/Windows/Fonts/msyhl.ttc",
|
||||||
|
"/Windows/Fonts/simsun.ttc",
|
||||||
|
"/Windows/Fonts/Sitka.ttc",
|
||||||
|
"/Windows/Fonts/SitkaB.ttc",
|
||||||
|
"/Windows/Fonts/SitkaI.ttc",
|
||||||
|
"/Windows/Fonts/SitkaZ.ttc",
|
||||||
|
"/Windows/Fonts/UDDigiKyokashoN-B.ttc",
|
||||||
|
"/Windows/Fonts/UDDigiKyokashoN-R.ttc",
|
||||||
|
"/Windows/Fonts/YuGothB.ttc",
|
||||||
|
"/Windows/Fonts/YuGothL.ttc",
|
||||||
|
"/Windows/Fonts/YuGothM.ttc",
|
||||||
|
"/Windows/Fonts/YuGothR.ttc",
|
||||||
|
]
|
||||||
|
for file in files:
|
||||||
|
echo file
|
||||||
|
var typefaces = readTypefaces(file)
|
||||||
|
for i, typeface in typefaces:
|
||||||
|
echo i, ": ", typeface.name
|
||||||
|
|
Loading…
Reference in a new issue