pdfkit/lib/font/subset.coffee
2014-03-23 12:25:09 -07:00

114 lines
3.1 KiB
CoffeeScript

CmapTable = require './tables/cmap'
utils = require './utils'
class Subset
constructor: (@font) ->
@subset = {}
@unicodes = {}
@next = 33 # PDFs don't like character codes between 0 and 32
use: (character) ->
# if given a string, add each character
if typeof character is 'string'
for i in [0...character.length]
@use character.charCodeAt(i)
return
if not @unicodes[character]
@subset[@next] = character
@unicodes[character] = @next++
encodeText: (text) ->
# encodes UTF-8 text for this subset. Returned
# text may not look correct, but it is.
string = ''
for i in [0...text.length]
char = @unicodes[text.charCodeAt(i)]
string += String.fromCharCode(char)
return string
cmap: ->
# generate the cmap table for this subset
unicodeCmap = @font.cmap.tables[0].codeMap
mapping = {}
for roman, unicode of @subset
mapping[roman] = unicodeCmap[unicode]
return mapping
glyphIDs: ->
# collect glyph ids for this subset
unicodeCmap = @font.cmap.tables[0].codeMap
ret = [0]
for roman, unicode of @subset
val = unicodeCmap[unicode]
ret.push val if val? and val not in ret
return ret.sort()
glyphsFor: (glyphIDs) ->
# collect the actual glyph data for this subset
glyphs = {}
for id in glyphIDs
glyphs[id] = @font.glyf.glyphFor(id)
# collect additional glyphs referenced from compound glyphs
additionalIDs = []
for id, glyph of glyphs when glyph?.compound
additionalIDs.push glyph.glyphIDs...
if additionalIDs.length > 0
for id, glyph of @glyphsFor(additionalIDs)
glyphs[id] = glyph
return glyphs
encode: ->
# generate the Cmap for this subset
cmap = CmapTable.encode @cmap(), 'unicode'
glyphs = @glyphsFor @glyphIDs()
# compute old2new and new2old mapping tables
old2new = { 0: 0 }
for code, ids of cmap.charMap
old2new[ids.old] = ids.new
nextGlyphID = cmap.maxGlyphID
for oldID of glyphs when oldID not of old2new
old2new[oldID] = nextGlyphID++
new2old = utils.invert(old2new)
newIDs = Object.keys(new2old).sort (a, b) -> a - b
oldIDs = (new2old[id] for id in newIDs)
# encode the font tables
glyf = @font.glyf.encode(glyphs, oldIDs, old2new)
loca = @font.loca.encode(glyf.offsets)
name = @font.name.encode()
# store for use later
@postscriptName = name.postscriptName
@cmap = {}
for code, ids of cmap.charMap
@cmap[code] = ids.old
tables =
cmap: cmap.table
glyf: glyf.table
loca: loca.table
hmtx: @font.hmtx.encode(oldIDs)
hhea: @font.hhea.encode(oldIDs)
maxp: @font.maxp.encode(oldIDs)
post: @font.post.encode(oldIDs)
name: name.table
head: @font.head.encode(loca)
# just copy over the OS/2 table if it exists
tables['OS/2'] = @font.os2.raw() if @font.os2.exists
# encode the font directory
@font.directory.encode(tables)
module.exports = Subset