Class: Pdfrb::Font::CFF::Subsetter

Inherits:
Object
  • Object
show all
Defined in:
lib/pdfrb/font/cff/subsetter.rb

Overview

Safe CFF subsetter (TN5176). Given the used glyph IDs, produces a smaller CFF with:

* a CharStrings INDEX holding only .notdef + the used
glyphs (original order, .notdef forced to gid 0);
* a format-0 charset remapping SIDs to the new gids —
unless the source charset was range-encoded or implicit,
in which case the original charset bytes are copied
verbatim (only safe when every glyph is kept);
* the Global Subr INDEX, Private DICT, and Local Subr INDEX
copied verbatim — subr references inside charstrings use
biased absolute indices, which stay valid unchanged;
* Name/String INDEXes and all other Top DICT data copied;
the CharStrings / charset / Private offsets are
re-encoded.

Constant Summary collapse

NOTDEF_GID =
0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cff, glyph_ids) ⇒ Subsetter

Returns a new instance of Subsetter.



26
27
28
29
# File 'lib/pdfrb/font/cff/subsetter.rb', line 26

def initialize(cff, glyph_ids)
  @cff = cff
  @glyph_ids = ([NOTDEF_GID] + glyph_ids).sort.uniq
end

Instance Attribute Details

#cffObject (readonly)

Returns the value of attribute cff.



24
25
26
# File 'lib/pdfrb/font/cff/subsetter.rb', line 24

def cff
  @cff
end

#glyph_idsObject (readonly)

Returns the value of attribute glyph_ids.



24
25
26
# File 'lib/pdfrb/font/cff/subsetter.rb', line 24

def glyph_ids
  @glyph_ids
end

Class Method Details

.subset_otf(otf_bytes, glyph_ids) ⇒ Object

Subset the 'CFF ' table of an OTF (sfnt) byte string and rebuild the container directory; other tables are copied verbatim. Returns the new OTF bytes (or the original when subsetting is not possible).



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/pdfrb/font/cff/subsetter.rb', line 133

def subset_otf(otf_bytes, glyph_ids)
  cff_table = table_bytes(otf_bytes, "CFF ")
  return otf_bytes unless cff_table

  subset = new(Pdfrb::Font::CFF::File.new(cff_table), glyph_ids).subset
  return otf_bytes if subset.bytesize >= cff_table.bytesize

  tables = directory(otf_bytes).map do |entry|
    data = entry[:tag] == "CFF " ? subset : otf_bytes.byteslice(entry[:offset], entry[:length])
    { tag: entry[:tag], data: data }
  end
  rebuild_sfnt(otf_bytes, tables)
end

Instance Method Details

#glyph_mapObject



35
36
37
# File 'lib/pdfrb/font/cff/subsetter.rb', line 35

def glyph_map
  @glyph_map ||= glyph_ids.each_with_index.to_h { |old, new| [old, new] }
end

#subsetObject



31
32
33
# File 'lib/pdfrb/font/cff/subsetter.rb', line 31

def subset
  @subset ||= build
end