mirror of
https://github.com/foliojs/pdfkit.git
synced 2025-12-08 20:15:54 +00:00
114 lines
3.1 KiB
CoffeeScript
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 |