f
This commit is contained in:
parent
f92e6d49d1
commit
6539002e5e
1 changed files with 191 additions and 59 deletions
|
@ -316,9 +316,6 @@ type
|
||||||
size: uint8
|
size: uint8
|
||||||
offsetSize: uint8
|
offsetSize: uint8
|
||||||
|
|
||||||
CFFIndex = ref object
|
|
||||||
objects: seq[string]
|
|
||||||
|
|
||||||
CFFTopDict = ref object
|
CFFTopDict = ref object
|
||||||
charStrings: int
|
charStrings: int
|
||||||
charset: int
|
charset: int
|
||||||
|
@ -330,8 +327,12 @@ type
|
||||||
copyright: string
|
copyright: string
|
||||||
encoding: int
|
encoding: int
|
||||||
familyName: string
|
familyName: string
|
||||||
fdArray: pointer
|
|
||||||
fdSelect: pointer
|
fdArray: int
|
||||||
|
fdSelect: int
|
||||||
|
fdArraySeq: seq[CFFTopDict]
|
||||||
|
fdSelectSeq: seq[int]
|
||||||
|
|
||||||
fontBBox: array[4, float32]
|
fontBBox: array[4, float32]
|
||||||
fontMatrix: array[6, float32]
|
fontMatrix: array[6, float32]
|
||||||
fontName: string
|
fontName: string
|
||||||
|
@ -342,9 +343,11 @@ type
|
||||||
paintType: int
|
paintType: int
|
||||||
private: array[2, float32]
|
private: array[2, float32]
|
||||||
subrs: int
|
subrs: int
|
||||||
|
subrsBias: int
|
||||||
|
subrIndex: seq[string]
|
||||||
defaultWidthX: int
|
defaultWidthX: int
|
||||||
nominalWidthX: int
|
nominalWidthX: int
|
||||||
ros: array[3, float32]
|
ros: array[3, string]
|
||||||
strokeWidth: int
|
strokeWidth: int
|
||||||
uidBase: pointer
|
uidBase: pointer
|
||||||
underlinePosition: int
|
underlinePosition: int
|
||||||
|
@ -356,18 +359,16 @@ type
|
||||||
CFFTable = ref object
|
CFFTable = ref object
|
||||||
## Contains the glyph outlines in PostScript format.
|
## Contains the glyph outlines in PostScript format.
|
||||||
header: CFFHeader
|
header: CFFHeader
|
||||||
nameIndex: CFFIndex
|
nameIndex: seq[string]
|
||||||
topDictIndex: CFFIndex
|
topDictIndex: seq[string]
|
||||||
stringIndex: CFFIndex
|
stringIndex: seq[string]
|
||||||
globalSubrIndex: CFFIndex
|
globalSubrIndex: seq[string]
|
||||||
topDict: CFFTopDict
|
topDict: CFFTopDict
|
||||||
subrsBias: int
|
charIndex: seq[string]
|
||||||
subrIndex: CFFIndex
|
|
||||||
charIndex: CFFIndex
|
|
||||||
#charsets*: CFF..
|
#charsets*: CFF..
|
||||||
#charStringsIndex*: CFF..
|
#charStringsIndex*: CFF..
|
||||||
#privateDict*: CFF..
|
#privateDict*: CFF..
|
||||||
|
isCID: bool
|
||||||
|
|
||||||
OpenType* = ref object
|
OpenType* = ref object
|
||||||
buf*: string
|
buf*: string
|
||||||
|
@ -810,7 +811,7 @@ proc parseKernTable(buf: string, offset: int): KernTable =
|
||||||
else:
|
else:
|
||||||
failUnsupported("Kern version")
|
failUnsupported("Kern version")
|
||||||
|
|
||||||
proc parseCFFIndex(buf: string, start: var int, stripZero = false): CFFIndex =
|
proc parseCFFIndex(buf: string, start: var int, stripZero = false): seq[string] =
|
||||||
|
|
||||||
proc getOffset(buf: string, offset, offSize: int): int =
|
proc getOffset(buf: string, offset, offSize: int): int =
|
||||||
var v = 0
|
var v = 0
|
||||||
|
@ -821,7 +822,6 @@ proc parseCFFIndex(buf: string, start: var int, stripZero = false): CFFIndex =
|
||||||
|
|
||||||
# Compute all of the offsets first.
|
# Compute all of the offsets first.
|
||||||
var offsets: seq[int]
|
var offsets: seq[int]
|
||||||
result = CFFIndex()
|
|
||||||
let count = buf.readUint16(start).swap().int
|
let count = buf.readUint16(start).swap().int
|
||||||
var endOffset = 0
|
var endOffset = 0
|
||||||
var objectOffset = 0
|
var objectOffset = 0
|
||||||
|
@ -844,7 +844,7 @@ proc parseCFFIndex(buf: string, start: var int, stripZero = false): CFFIndex =
|
||||||
var value = buf[objectOffset + offsets[i] ..< objectOffset + offsets[i + 1]]
|
var value = buf[objectOffset + offsets[i] ..< objectOffset + offsets[i + 1]]
|
||||||
if stripZero:
|
if stripZero:
|
||||||
value = value[0..^1] # ignore 0 at the end
|
value = value[0..^1] # ignore 0 at the end
|
||||||
result.objects.add(value)
|
result.add(value)
|
||||||
start = endOffset
|
start = endOffset
|
||||||
|
|
||||||
const cffStandardStrings = [
|
const cffStandardStrings = [
|
||||||
|
@ -935,24 +935,58 @@ proc shift[T](s: var seq[T]): T =
|
||||||
## Pops from the front.
|
## Pops from the front.
|
||||||
result = s[0]
|
result = s[0]
|
||||||
s.delete(0)
|
s.delete(0)
|
||||||
|
import print
|
||||||
|
|
||||||
proc parseCFFCharstring(cff: CffTable, code: string): Path =
|
proc calcCFFSubroutineBias(subrs: seq[string]): int =
|
||||||
|
if subrs.len < 1240:
|
||||||
|
107
|
||||||
|
elif subrs.len < 33900:
|
||||||
|
1131
|
||||||
|
else:
|
||||||
|
32768
|
||||||
|
|
||||||
|
proc parseCFFCharstring(cff: CffTable, code: string, glyphIndex: int): Path =
|
||||||
|
|
||||||
var p = newPath()
|
var p = newPath()
|
||||||
var stack: seq[float32]
|
var stack: seq[float32]
|
||||||
# var nStems = 0
|
var nStems = 0
|
||||||
var haveWidth = false
|
var haveWidth = false
|
||||||
var x = 0f
|
var x = 0f
|
||||||
var y = 0f
|
var y = 0f
|
||||||
|
|
||||||
let
|
var
|
||||||
subrs = cff.topDict.subrs
|
subrs: seq[string]
|
||||||
subrsBias = cff.subrsBias
|
subrsBias: int
|
||||||
|
defaultWidthX: int
|
||||||
|
nominalWidthX: int
|
||||||
|
|
||||||
|
if cff.isCID:
|
||||||
|
print cff.isCID
|
||||||
|
let fdIndex = cff.topDict.fdSelectSeq[glyphIndex]
|
||||||
|
print fdIndex
|
||||||
|
let fdDict = cff.topDict.fdArraySeq[fdIndex]
|
||||||
|
subrs = fdDict.subrIndex
|
||||||
|
subrsBias = calcCFFSubroutineBias(subrs)
|
||||||
|
defaultWidthX = fdDict.defaultWidthX
|
||||||
|
nominalWidthX = fdDict.nominalWidthX
|
||||||
|
else:
|
||||||
|
subrs = cff.topDict.subrIndex
|
||||||
|
subrsBias = cff.topDict.subrsBias
|
||||||
defaultWidthX = cff.topDict.defaultWidthX
|
defaultWidthX = cff.topDict.defaultWidthX
|
||||||
nominalWidthX = cff.topDict.nominalWidthX
|
nominalWidthX = cff.topDict.nominalWidthX
|
||||||
|
|
||||||
var width = defaultWidthX.float32
|
var width = defaultWidthX.float32
|
||||||
|
|
||||||
|
proc parseStems() =
|
||||||
|
# The number of stem operators on the stack is always even.
|
||||||
|
# If the value is uneven, that means a width is specified.
|
||||||
|
print "parseStems", stack
|
||||||
|
if stack.len mod 2 != 0 and not haveWidth:
|
||||||
|
width = stack.shift() + nominalWidthX.float32
|
||||||
|
nStems += stack.len shr 1
|
||||||
|
stack.setLen(0)
|
||||||
|
haveWidth = true
|
||||||
|
|
||||||
proc parse(code: string) =
|
proc parse(code: string) =
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
|
@ -961,6 +995,9 @@ proc parseCFFCharstring(cff: CffTable, code: string): Path =
|
||||||
inc i
|
inc i
|
||||||
case v:
|
case v:
|
||||||
|
|
||||||
|
of 1, 3: # hstem vstem
|
||||||
|
parseStems()
|
||||||
|
|
||||||
of 4: # vmoveto
|
of 4: # vmoveto
|
||||||
if stack.len > 1 and not haveWidth:
|
if stack.len > 1 and not haveWidth:
|
||||||
width = stack.shift() + nominalWidthX.float32
|
width = stack.shift() + nominalWidthX.float32
|
||||||
|
@ -1005,7 +1042,8 @@ proc parseCFFCharstring(cff: CffTable, code: string): Path =
|
||||||
|
|
||||||
of 10: # callsubr
|
of 10: # callsubr
|
||||||
let codeIndex = stack.pop().int + subrsBias
|
let codeIndex = stack.pop().int + subrsBias
|
||||||
let subrCode = cff.subrIndex.objects[codeIndex]
|
#print codeIndex, cff.subrIndex
|
||||||
|
let subrCode = subrs[codeIndex]
|
||||||
if subrCode.len > 0:
|
if subrCode.len > 0:
|
||||||
parse(subrCode)
|
parse(subrCode)
|
||||||
|
|
||||||
|
@ -1018,6 +1056,13 @@ proc parseCFFCharstring(cff: CffTable, code: string): Path =
|
||||||
haveWidth = true
|
haveWidth = true
|
||||||
p.closePath()
|
p.closePath()
|
||||||
|
|
||||||
|
of 18: # hstemhm
|
||||||
|
parseStems()
|
||||||
|
|
||||||
|
of 19, 20: # hintmask, cntrmask
|
||||||
|
parseStems()
|
||||||
|
i += (nStems + 7) shr 3
|
||||||
|
|
||||||
of 21: # rmoveto
|
of 21: # rmoveto
|
||||||
if stack.len > 2 and not haveWidth:
|
if stack.len > 2 and not haveWidth:
|
||||||
width = stack.shift() + nominalWidthX.float32
|
width = stack.shift() + nominalWidthX.float32
|
||||||
|
@ -1093,8 +1138,8 @@ proc parseCFFCharstring(cff: CffTable, code: string): Path =
|
||||||
i += 2
|
i += 2
|
||||||
|
|
||||||
of 29: # callgsubr
|
of 29: # callgsubr
|
||||||
let codeIndex = stack.pop().int + subrsBias
|
let codeIndex = stack.pop().int + calcCFFSubroutineBias(cff.globalSubrIndex)
|
||||||
let subrCode = cff.globalSubrIndex.objects[codeIndex]
|
let subrCode = cff.globalSubrIndex[codeIndex]
|
||||||
if subrCode.len > 0:
|
if subrCode.len > 0:
|
||||||
parse(subrCode)
|
parse(subrCode)
|
||||||
|
|
||||||
|
@ -1158,7 +1203,7 @@ proc parseCFFCharstring(cff: CffTable, code: string): Path =
|
||||||
i += 1
|
i += 1
|
||||||
stack.add(float32(-(v - 251) * 256 - b1 - 108))
|
stack.add(float32(-(v - 251) * 256 - b1 - 108))
|
||||||
else:
|
else:
|
||||||
failUnsupported("test me")
|
#failUnsupported("test me")
|
||||||
let
|
let
|
||||||
b1 = code.readUint8(i + 0).int
|
b1 = code.readUint8(i + 0).int
|
||||||
b2 = code.readUint8(i + 1).int
|
b2 = code.readUint8(i + 1).int
|
||||||
|
@ -1169,9 +1214,10 @@ proc parseCFFCharstring(cff: CffTable, code: string): Path =
|
||||||
((b1 shl 24) or (b2 shl 16) or (b3 shl 8) or b4).float32 / 65536f)
|
((b1 shl 24) or (b2 shl 16) or (b3 shl 8) or b4).float32 / 65536f)
|
||||||
|
|
||||||
parse(code)
|
parse(code)
|
||||||
|
print $p
|
||||||
return p
|
return p
|
||||||
|
|
||||||
proc parseCFFTable(buf: string, offset: int): CFFTable =
|
proc parseCFFTable(buf: string, offset: int, maxp: MaxpTable): CFFTable =
|
||||||
buf.eofCheck(offset + 32)
|
buf.eofCheck(offset + 32)
|
||||||
|
|
||||||
result = CFFTable()
|
result = CFFTable()
|
||||||
|
@ -1190,16 +1236,6 @@ proc parseCFFTable(buf: string, offset: int): CFFTable =
|
||||||
# contains binary glyphs
|
# contains binary glyphs
|
||||||
result.globalSubrIndex = buf.parseCFFIndex(indexOffset)
|
result.globalSubrIndex = buf.parseCFFIndex(indexOffset)
|
||||||
|
|
||||||
# Subroutines are encoded using the negative half of the number space.
|
|
||||||
# See type 2 chapter 4.7 "Subroutine operators".
|
|
||||||
result.subrsBias =
|
|
||||||
if result.globalSubrIndex.objects.len < 1240:
|
|
||||||
107
|
|
||||||
elif result.globalSubrIndex.objects.len < 33900:
|
|
||||||
1131
|
|
||||||
else:
|
|
||||||
32768
|
|
||||||
|
|
||||||
# Parse a `CFF` DICT object.
|
# Parse a `CFF` DICT object.
|
||||||
# A dictionary contains key-value pairs in a compact tokenized format.
|
# A dictionary contains key-value pairs in a compact tokenized format.
|
||||||
proc parseCFFDict(data: string, start, stop: int): seq[(int, seq[float64])] =
|
proc parseCFFDict(data: string, start, stop: int): seq[(int, seq[float64])] =
|
||||||
|
@ -1335,12 +1371,12 @@ proc parseCFFTable(buf: string, offset: int): CFFTable =
|
||||||
# "Top DICT"s found using an INDEX list.
|
# "Top DICT"s found using an INDEX list.
|
||||||
proc gatherCFFTopDicts(
|
proc gatherCFFTopDicts(
|
||||||
cff: CFFTable,
|
cff: CFFTable,
|
||||||
|
maxp: MaxpTable,
|
||||||
data: string,
|
data: string,
|
||||||
start: int,
|
start: int,
|
||||||
cffIndex,
|
cffIndex,
|
||||||
strings: seq[string]
|
strings: seq[string]
|
||||||
): seq[CFFTopDict] =
|
): seq[CFFTopDict] =
|
||||||
|
|
||||||
for iTopDict in 0 ..< cffIndex.len:
|
for iTopDict in 0 ..< cffIndex.len:
|
||||||
let
|
let
|
||||||
cffTopDict = CFFTopDict()
|
cffTopDict = CFFTopDict()
|
||||||
|
@ -1378,6 +1414,20 @@ proc parseCFFTable(buf: string, offset: int): CFFTable =
|
||||||
result[i] = topDict[key][i].float32
|
result[i] = topDict[key][i].float32
|
||||||
else:
|
else:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
proc getArrStr[N: int](
|
||||||
|
topDict: Table[string, seq[float64]],
|
||||||
|
key: string,
|
||||||
|
default: array[N, string],
|
||||||
|
strings: seq[string]
|
||||||
|
): array[N, string] =
|
||||||
|
if key in topDict:
|
||||||
|
for i in 0 ..< result.len:
|
||||||
|
let index = topDict[key][i].int
|
||||||
|
result[i] = getCFFString(strings, index)
|
||||||
|
else:
|
||||||
|
return default
|
||||||
|
|
||||||
cffTopDict.charStrings = topDict.getInt("charStrings", 0)
|
cffTopDict.charStrings = topDict.getInt("charStrings", 0)
|
||||||
cffTopDict.charset = topDict.getInt("charset", 0)
|
cffTopDict.charset = topDict.getInt("charset", 0)
|
||||||
cffTopDict.charstringType = topDict.getInt("charstringType", 2)
|
cffTopDict.charstringType = topDict.getInt("charstringType", 2)
|
||||||
|
@ -1388,8 +1438,8 @@ proc parseCFFTable(buf: string, offset: int): CFFTable =
|
||||||
cffTopDict.copyright = topDict.getStr("copyright", "")
|
cffTopDict.copyright = topDict.getStr("copyright", "")
|
||||||
cffTopDict.encoding = topDict.getInt("encoding", 0)
|
cffTopDict.encoding = topDict.getInt("encoding", 0)
|
||||||
cffTopDict.familyName = topDict.getStr("familyName", "")
|
cffTopDict.familyName = topDict.getStr("familyName", "")
|
||||||
# cffTopDict.fdArray: pointer
|
cffTopDict.fdArray = topDict.getInt("fdArray", 0)
|
||||||
# cffTopDict.fdSelect: pointer
|
cffTopDict.fdSelect = topDict.getInt("fdSelect", 0)
|
||||||
cffTopDict.fontBBox = topDict.getArr("fontBBox", [0f, 0f, 0f, 0f])
|
cffTopDict.fontBBox = topDict.getArr("fontBBox", [0f, 0f, 0f, 0f])
|
||||||
cffTopDict.fontMatrix = topDict.getArr("fontMatrix",
|
cffTopDict.fontMatrix = topDict.getArr("fontMatrix",
|
||||||
[0.001f, 0f, 0f, 0.001f, 0f, 0f])
|
[0.001f, 0f, 0f, 0.001f, 0f, 0f])
|
||||||
|
@ -1402,14 +1452,20 @@ proc parseCFFTable(buf: string, offset: int): CFFTable =
|
||||||
cffTopDict.private = topDict.getArr("private", [0f, 0f])
|
cffTopDict.private = topDict.getArr("private", [0f, 0f])
|
||||||
var privateSize = cffTopDict.private[0].int
|
var privateSize = cffTopDict.private[0].int
|
||||||
var privateOffset = cffTopDict.private[1].int
|
var privateOffset = cffTopDict.private[1].int
|
||||||
var privateDict = parseCFFPrivateDict(
|
if privateOffset != 0:
|
||||||
buf[privateOffset + start ..< privateOffset + start + privateSize],
|
var privateDict = parseCFFPrivateDict(
|
||||||
strings
|
buf[privateOffset + start ..< privateOffset + start + privateSize],
|
||||||
)
|
strings
|
||||||
cffTopDict.defaultWidthX = privateDict.getInt("defaultWidthX", 0)
|
)
|
||||||
cffTopDict.nominalWidthX = privateDict.getInt("nominalWidthX", 0)
|
cffTopDict.defaultWidthX = privateDict.getInt("defaultWidthX", 0)
|
||||||
cffTopDict.subrs = privateDict.getInt("subrs", 0)
|
cffTopDict.nominalWidthX = privateDict.getInt("nominalWidthX", 0)
|
||||||
# cffTopDict.ros: array[3, float32]
|
cffTopDict.subrs = privateDict.getInt("subrs", 0)
|
||||||
|
if cffTopDict.subrs > 0:
|
||||||
|
var subrOffset = cffTopDict.private[1].int + cffTopDict.subrs
|
||||||
|
var subrOffset2 = subrOffset + offset
|
||||||
|
cffTopDict.subrIndex = buf.parseCFFIndex(subrOffset2)
|
||||||
|
|
||||||
|
cffTopDict.ros = topDict.getArrStr("ros", ["", "", ""], strings)
|
||||||
cffTopDict.strokeWidth = topDict.getInt("strokeWidth", 0)
|
cffTopDict.strokeWidth = topDict.getInt("strokeWidth", 0)
|
||||||
# cffTopDict.uidBase: pointer
|
# cffTopDict.uidBase: pointer
|
||||||
cffTopDict.underlinePosition = topDict.getInt("underlinePosition", -100)
|
cffTopDict.underlinePosition = topDict.getInt("underlinePosition", -100)
|
||||||
|
@ -1419,20 +1475,95 @@ proc parseCFFTable(buf: string, offset: int): CFFTable =
|
||||||
cffTopDict.weight = topDict.getStr("weight", "")
|
cffTopDict.weight = topDict.getStr("weight", "")
|
||||||
result.add(cffTopDict)
|
result.add(cffTopDict)
|
||||||
|
|
||||||
let topDicts = result.gatherCFFTopDicts(
|
let topDicts = result.gatherCFFTopDicts(maxp,
|
||||||
buf, offset, result.topDictIndex.objects, result.stringIndex.objects)
|
buf, offset, result.topDictIndex, result.stringIndex)
|
||||||
if topDicts.len == 0:
|
if topDicts.len == 0:
|
||||||
failUnsupported("CFF no topDict")
|
failUnsupported("CFF no topDict")
|
||||||
if topDicts.len > 1:
|
if topDicts.len > 1:
|
||||||
failUnsupported("CFF multiple topDict")
|
failUnsupported("CFF multiple topDict")
|
||||||
result.topDict = topDicts[0]
|
result.topDict = topDicts[0]
|
||||||
|
|
||||||
# TODO: isCIDFont?
|
# Subroutines are encoded using the negative half of the number space.
|
||||||
|
# See type 2 chapter 4.7 "Subroutine operators".
|
||||||
|
result.topDict.subrsBias =
|
||||||
|
if result.globalSubrIndex.len < 1240:
|
||||||
|
107
|
||||||
|
elif result.globalSubrIndex.len < 33900:
|
||||||
|
1131
|
||||||
|
else:
|
||||||
|
32768
|
||||||
|
|
||||||
|
if result.topDict.ros[0] != "" and result.topDict.ros[1] != "":
|
||||||
|
result.isCID = true
|
||||||
|
|
||||||
|
var fdArrayOffset = result.topDict.fdArray + offset
|
||||||
|
var fdSelectOffset = result.topDict.fdSelect + offset
|
||||||
|
if fdArrayOffset == 0 or fdSelectOffset == 0:
|
||||||
|
failUnsupported("CFF CID tables are missing")
|
||||||
|
|
||||||
|
var fdArrayIndex = parseCFFIndex(buf, fdArrayOffset)
|
||||||
|
result.topDict.fdArraySeq = result.gatherCFFTopDicts(maxp, buf, offset, fdArrayIndex, result.stringIndex)
|
||||||
|
|
||||||
|
proc parseCFFFDSelect(buf: string, start, nGlyphs, fdArrayCount: int): seq[int] =
|
||||||
|
print "here", buf.len, start, nGlyphs, fdArrayCount
|
||||||
|
|
||||||
|
var at = start
|
||||||
|
var format = buf.readUint8(at)
|
||||||
|
inc at
|
||||||
|
print format
|
||||||
|
|
||||||
|
# if (format === 0) {
|
||||||
|
# // Simple list of nGlyphs elements
|
||||||
|
# for (var iGid = 0; iGid < nGlyphs; iGid++) {
|
||||||
|
# fdIndex = parser.parseCard8();
|
||||||
|
# if (fdIndex >= fdArrayCount) {
|
||||||
|
# throw new Error('CFF table CID Font FDSelect has bad FD index value ' + fdIndex + ' (FD count ' + fdArrayCount + ')');
|
||||||
|
# }
|
||||||
|
# fdSelect.push(fdIndex);
|
||||||
|
# }
|
||||||
|
if format == 3:
|
||||||
|
# Ranges
|
||||||
|
var nRanges = buf.readUint16(at).swap().int
|
||||||
|
at += 2
|
||||||
|
var first = buf.readUint16(at).swap().int
|
||||||
|
at += 2
|
||||||
|
print nRanges, first
|
||||||
|
if first != 0:
|
||||||
|
failUnsupported("CFF Table CID Font FDSelect format 3 range has bad initial GID")
|
||||||
|
|
||||||
|
var next = 0
|
||||||
|
for iRange in 0 ..< nRanges:
|
||||||
|
var fdIndex = buf.readUint8(at).int
|
||||||
|
inc at
|
||||||
|
next = buf.readUint16(at).swap().int
|
||||||
|
at += 2
|
||||||
|
if fdIndex >= fdArrayCount:
|
||||||
|
failUnsupported("CFF table CID Font FDSelect has bad FD index value")
|
||||||
|
if next > nGlyphs:
|
||||||
|
failUnsupported("CFF Table CID Font FDSelect format 3 range has bad GID")
|
||||||
|
|
||||||
|
while first < next:
|
||||||
|
result.add(fdIndex)
|
||||||
|
inc first
|
||||||
|
|
||||||
|
first = next
|
||||||
|
|
||||||
|
if next != nGlyphs:
|
||||||
|
failUnsupported("CFF Table CID Font FDSelect format 3 range has bad final GID")
|
||||||
|
|
||||||
|
else:
|
||||||
|
failUnsupported("CFF Table CID Font FDSelect format")
|
||||||
|
|
||||||
|
result.topDict.fdSelectSeq = parseCFFFDSelect(buf, fdSelectOffset, maxp.numGlyphs.int, result.topDict.fdArraySeq.len)
|
||||||
|
print result.topDict.fdSelectSeq.len
|
||||||
|
|
||||||
|
|
||||||
|
print result.topDict.subrs
|
||||||
if result.topDict.subrs != 0:
|
if result.topDict.subrs != 0:
|
||||||
var subrOffset =
|
var subrOffset =
|
||||||
offset + result.topDict.private[1].int + result.topDict.subrs
|
offset + result.topDict.private[1].int + result.topDict.subrs
|
||||||
result.subrIndex = buf.parseCFFIndex(subrOffset)
|
result.topDict.subrIndex = buf.parseCFFIndex(subrOffset)
|
||||||
|
result.topDict.subrsBias = calcCFFSubroutineBias(result.topDict.subrIndex)
|
||||||
|
|
||||||
proc parseCFFIndexLowMemory(buf: string, offset: int): seq[int] =
|
proc parseCFFIndexLowMemory(buf: string, offset: int): seq[int] =
|
||||||
proc getOffset(dataView: string, offset, offSize: int): int =
|
proc getOffset(dataView: string, offset, offSize: int): int =
|
||||||
|
@ -1482,11 +1613,11 @@ proc parseCFFTable(buf: string, offset: int): CFFTable =
|
||||||
break
|
break
|
||||||
sid += 1
|
sid += 1
|
||||||
else:
|
else:
|
||||||
failUnsupported("CFF charset format")
|
failUnsupported("CFF charset format: " & $format)
|
||||||
|
|
||||||
# Why do we need this anyways?
|
# Why do we need this anyways?
|
||||||
var charset = parseCFFCharset(
|
#var charset = parseCFFCharset(
|
||||||
buf, offset + result.topDict.charset, nGlyphs, result.stringIndex.objects)
|
# buf, offset + result.topDict.charset, nGlyphs, result.stringIndex.objects)
|
||||||
var start = offset + result.topDict.charStrings
|
var start = offset + result.topDict.charStrings
|
||||||
result.charIndex = buf.parseCFFIndex(start)
|
result.charIndex = buf.parseCFFIndex(start)
|
||||||
|
|
||||||
|
@ -2251,11 +2382,12 @@ proc parseGlyfGlyph(opentype: OpenType, glyphId: uint16): Path =
|
||||||
else:
|
else:
|
||||||
parseGlyphPath(opentype.buf, i, numberOfContours)
|
parseGlyphPath(opentype.buf, i, numberOfContours)
|
||||||
|
|
||||||
|
import print
|
||||||
proc parseCffGlyph(opentype: OpenType, glyphId: uint16): Path =
|
proc parseCffGlyph(opentype: OpenType, glyphId: uint16): Path =
|
||||||
let cff = opentype.cff
|
let cff = opentype.cff
|
||||||
let charstring = cff.charIndex.objects[glyphId]
|
let charstring = cff.charIndex[glyphId]
|
||||||
return cff.parseCFFCharstring(charstring)
|
print glyphId
|
||||||
|
return cff.parseCFFCharstring(charstring, glyphId.int)
|
||||||
|
|
||||||
proc parseGlyph(opentype: OpenType, rune: Rune): Path {.inline.} =
|
proc parseGlyph(opentype: OpenType, rune: Rune): Path {.inline.} =
|
||||||
if opentype.glyf != nil:
|
if opentype.glyf != nil:
|
||||||
|
@ -2371,7 +2503,7 @@ proc parseOpenType*(buf: string): OpenType {.raises: [PixieError].} =
|
||||||
result.glyf =
|
result.glyf =
|
||||||
parseGlyfTable(buf, result.tableRecords["glyf"].offset.int, result.loca)
|
parseGlyfTable(buf, result.tableRecords["glyf"].offset.int, result.loca)
|
||||||
elif "CFF " in result.tableRecords:
|
elif "CFF " in result.tableRecords:
|
||||||
result.cff = parseCFFTable(buf, result.tableRecords["CFF "].offset.int)
|
result.cff = parseCFFTable(buf, result.tableRecords["CFF "].offset.int, result.maxp)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
failUnsupported("glyph outlines")
|
failUnsupported("glyph outlines")
|
||||||
|
|
Loading…
Reference in a new issue