%PDF- %PDF-
Direktori : /usr/lib/calibre/calibre/utils/fonts/sfnt/ |
Current File : //usr/lib/calibre/calibre/utils/fonts/sfnt/metrics.py |
#!/usr/bin/env python3 __license__ = 'GPL v3' __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' __docformat__ = 'restructuredtext en' from calibre.utils.fonts.utils import get_all_font_names from calibre.utils.fonts.sfnt.container import UnsupportedFont class FontMetrics: ''' Get various metrics for the specified sfnt. All the metrics are returned in units of pixels. To calculate a metric you have to specify the font size (in pixels) and the horizontal stretch factor (between 0.0 and 1.0). ''' def __init__(self, sfnt): for table in (b'head', b'hhea', b'hmtx', b'cmap', b'OS/2', b'post', b'name', b'maxp'): if table not in sfnt: raise UnsupportedFont('This font has no %s table'%table) self.sfnt = sfnt self.head = self.sfnt[b'head'] hhea = self.sfnt[b'hhea'] hhea.read_data(self.sfnt[b'hmtx'], self.sfnt[b'maxp'].num_glyphs) self.ascent = hhea.ascender self.descent = hhea.descender self.bbox = (self.head.x_min, self.head.y_min, self.head.x_max, self.head.y_max) self._advance_widths = hhea.advance_widths self.cmap = self.sfnt[b'cmap'] self.units_per_em = self.head.units_per_em self.os2 = self.sfnt[b'OS/2'] self.os2.read_data() self.post = self.sfnt[b'post'] self.post.read_data() self.names = get_all_font_names(self.sfnt[b'name'].raw, raw_is_table=True) self.is_otf = 'CFF ' in self.sfnt.tables self._sig = hash(self.sfnt[b'name'].raw) # Metrics for embedding in PDF pdf_scale = self.pdf_scale = lambda x:int(round(x*1000./self.units_per_em)) self.pdf_ascent, self.pdf_descent = map(pdf_scale, (self.os2.typo_ascender, self.os2.typo_descender)) self.pdf_bbox = tuple(map(pdf_scale, self.bbox)) self.pdf_capheight = pdf_scale(getattr(self.os2, 'cap_height', self.os2.typo_ascender)) self.pdf_avg_width = pdf_scale(self.os2.average_char_width) self.pdf_stemv = 50 + int((self.os2.weight_class / 65.0) ** 2) def __hash__(self): return self._sig @property def postscript_name(self): if 'postscript_name' in self.names: return self.names['postscript_name'].replace(' ', '-') try: return self.names['full_name'].replace(' ', '-') except KeyError: return self.names['family_name'].replace(' ', '-') def underline_thickness(self, pixel_size=12.0): 'Thickness for lines (in pixels) at the specified size' yscale = pixel_size / self.units_per_em return self.post.underline_thickness * yscale def underline_position(self, pixel_size=12.0): yscale = pixel_size / self.units_per_em return self.post.underline_position * yscale def overline_position(self, pixel_size=12.0): yscale = pixel_size / self.units_per_em return (self.ascent + 2) * yscale def strikeout_size(self, pixel_size=12.0): 'The width of the strikeout line, in pixels' yscale = pixel_size / self.units_per_em return yscale * self.os2.strikeout_size def strikeout_position(self, pixel_size=12.0): 'The displacement from the baseline to top of the strikeout line, in pixels' yscale = pixel_size / self.units_per_em return yscale * self.os2.strikeout_position def advance_widths(self, string, pixel_size=12.0, stretch=1.0): ''' Return the advance widths (in pixels) for all glyphs corresponding to the characters in string at the specified pixel_size and stretch factor. ''' if not isinstance(string, str): raise ValueError('Must supply a unicode object') chars = tuple(map(ord, string)) cmap = self.cmap.get_character_map(chars) glyph_ids = (cmap[c] for c in chars) pixel_size_x = stretch * pixel_size xscale = pixel_size_x / self.units_per_em return tuple(i*xscale for i in self.glyph_widths(glyph_ids)) def glyph_widths(self, glyph_ids): last = len(self._advance_widths) return tuple(self._advance_widths[i if i < last else -1] for i in glyph_ids) def width(self, string, pixel_size=12.0, stretch=1.0): 'The width of the string at the specified pixel size and stretch, in pixels' return sum(self.advance_widths(string, pixel_size, stretch)) if __name__ == '__main__': import sys from calibre.utils.fonts.sfnt.container import Sfnt with open(sys.argv[-1], 'rb') as f: raw = f.read() sfnt = Sfnt(raw) m = FontMetrics(sfnt) print('Ascent:', m.pdf_ascent) print('Descent:', m.pdf_descent) print('PDF BBox:', m.pdf_bbox) print('CapHeight:', m.pdf_capheight) print('AvgWidth:', m.pdf_avg_width) print('ItalicAngle', m.post.italic_angle) print('StemV', m.pdf_stemv)