%PDF- %PDF-
Direktori : /usr/lib/calibre/calibre/utils/fonts/sfnt/ |
Current File : //usr/lib/calibre/calibre/utils/fonts/sfnt/loca.py |
#!/usr/bin/env python3 __license__ = 'GPL v3' __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' __docformat__ = 'restructuredtext en' import array, sys from operator import itemgetter from itertools import repeat from calibre.utils.fonts.sfnt import UnknownTable from polyglot.builtins import iteritems def four_byte_type_code(): for c in 'IL': a = array.array(c) if a.itemsize == 4: return c def read_array(data, fmt='H'): ans = array.array(fmt, data) if sys.byteorder != 'big': ans.byteswap() return ans class LocaTable(UnknownTable): def load_offsets(self, head_table, maxp_table): fmt = 'H' if head_table.index_to_loc_format == 0 else four_byte_type_code() locs = read_array(self.raw, fmt) self.offset_map = locs.tolist() if fmt == 'H': self.offset_map = [2*i for i in self.offset_map] self.fmt = fmt def glyph_location(self, glyph_id): offset = self.offset_map[glyph_id] next_offset = self.offset_map[glyph_id+1] return offset, next_offset - offset def update(self, resolved_glyph_map): ''' Update this table to contain pointers only to the glyphs in resolved_glyph_map which must be a map of glyph_ids to (offset, sz) Note that the loca table is generated for all glyphs from 0 to the largest glyph that is either in resolved_glyph_map or was present originally. The pointers to glyphs that have no data will be set to zero. This preserves glyph ids. ''' current_max_glyph_id = len(self.offset_map) - 2 max_glyph_id = max(resolved_glyph_map or (0,)) max_glyph_id = max(max_glyph_id, current_max_glyph_id) self.offset_map = list(repeat(0, max_glyph_id + 2)) glyphs = [(glyph_id, x[0], x[1]) for glyph_id, x in iteritems(resolved_glyph_map)] glyphs.sort(key=itemgetter(1)) for glyph_id, offset, sz in glyphs: self.offset_map[glyph_id] = offset self.offset_map[glyph_id+1] = offset + sz # Fix all zero entries to be the same as the previous entry, which # means that if the ith entry is zero, the i-1 glyph is not present. for i in range(1, len(self.offset_map)): if self.offset_map[i] == 0: self.offset_map[i] = self.offset_map[i-1] vals = self.offset_map max_offset = max(vals) if vals else 0 if max_offset < 0x20000 and all(l % 2 == 0 for l in vals): self.fmt = 'H' vals = array.array(self.fmt, (i // 2 for i in vals)) else: self.fmt = four_byte_type_code() vals = array.array(self.fmt, vals) if sys.byteorder != "big": vals.byteswap() self.raw = vals.tobytes() subset = update def dump_glyphs(self, sfnt): if not hasattr(self, 'offset_map'): self.load_offsets(sfnt[b'head'], sfnt[b'maxp']) for i in range(len(self.offset_map)-1): off, noff = self.offset_map[i], self.offset_map[i+1] if noff != off: print('Glyph id:', i, 'size:', noff-off)