mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Subsetting of the kern table
This commit is contained in:
parent
508ca6bc5a
commit
1d9398e009
@ -21,6 +21,7 @@ from calibre.utils.fonts.sfnt.maxp import MaxpTable
|
|||||||
from calibre.utils.fonts.sfnt.loca import LocaTable
|
from calibre.utils.fonts.sfnt.loca import LocaTable
|
||||||
from calibre.utils.fonts.sfnt.glyf import GlyfTable
|
from calibre.utils.fonts.sfnt.glyf import GlyfTable
|
||||||
from calibre.utils.fonts.sfnt.cmap import CmapTable
|
from calibre.utils.fonts.sfnt.cmap import CmapTable
|
||||||
|
from calibre.utils.fonts.sfnt.kern import KernTable
|
||||||
from calibre.utils.fonts.sfnt.cff.table import CFFTable
|
from calibre.utils.fonts.sfnt.cff.table import CFFTable
|
||||||
|
|
||||||
# OpenType spec: http://www.microsoft.com/typography/otspec/otff.htm
|
# OpenType spec: http://www.microsoft.com/typography/otspec/otff.htm
|
||||||
@ -44,6 +45,7 @@ class Sfnt(object):
|
|||||||
b'glyf' : GlyfTable,
|
b'glyf' : GlyfTable,
|
||||||
b'cmap' : CmapTable,
|
b'cmap' : CmapTable,
|
||||||
b'CFF ' : CFFTable,
|
b'CFF ' : CFFTable,
|
||||||
|
b'kern' : KernTable,
|
||||||
}.get(table_tag, UnknownTable)(table)
|
}.get(table_tag, UnknownTable)(table)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
|
89
src/calibre/utils/fonts/sfnt/kern.py
Normal file
89
src/calibre/utils/fonts/sfnt/kern.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
|
||||||
|
from __future__ import (unicode_literals, division, absolute_import,
|
||||||
|
print_function)
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
from struct import unpack_from, calcsize, pack, error as struct_error
|
||||||
|
|
||||||
|
from calibre.utils.fonts.sfnt import (UnknownTable, FixedProperty,
|
||||||
|
max_power_of_two)
|
||||||
|
from calibre.utils.fonts.sfnt.errors import UnsupportedFont
|
||||||
|
|
||||||
|
class KernTable(UnknownTable):
|
||||||
|
|
||||||
|
version = FixedProperty('_version')
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(KernTable, self).__init__(*args, **kwargs)
|
||||||
|
self._version, self.num_tables = unpack_from(b'>HH', self.raw)
|
||||||
|
if self._version == 1 and len(self.raw) >= 8:
|
||||||
|
self._version, self.num_tables = unpack_from(b'>LL', self.raw)
|
||||||
|
self.headerfmt = b'>HH' if self._version == 0 else b'>LL'
|
||||||
|
|
||||||
|
def restrict_to_glyphs(self, glyph_ids):
|
||||||
|
if self._version not in {0, 0x10000}:
|
||||||
|
raise UnsupportedFont('kern table has version: %x'%self._version)
|
||||||
|
offset = 4 if (self._version == 0) else 8
|
||||||
|
tables = []
|
||||||
|
for i in xrange(self.num_tables):
|
||||||
|
if self._version == 0:
|
||||||
|
version, length, coverage = unpack_from(b'>3H', self.raw, offset)
|
||||||
|
table_format = version
|
||||||
|
else:
|
||||||
|
length, coverage = unpack_from(b'>LH', self.raw, offset)
|
||||||
|
table_format = coverage & 0xff
|
||||||
|
raw = self.raw[offset:offset+length]
|
||||||
|
if table_format == 0:
|
||||||
|
raw = self.restrict_format_0(raw, glyph_ids)
|
||||||
|
if not raw:
|
||||||
|
continue
|
||||||
|
tables.append(raw)
|
||||||
|
offset += length
|
||||||
|
self.raw = pack(self.headerfmt, self._version, len(tables)) + b''.join(tables)
|
||||||
|
|
||||||
|
def restrict_format_0(self, raw, glyph_ids):
|
||||||
|
if self._version == 0:
|
||||||
|
version, length, coverage, npairs = unpack_from(b'>4H', raw)
|
||||||
|
headerfmt = b'>3H'
|
||||||
|
else:
|
||||||
|
length, coverage, tuple_index, npairs = unpack_from(b'>L3H', raw)
|
||||||
|
headerfmt = b'>L2H'
|
||||||
|
|
||||||
|
offset = calcsize(headerfmt + b'4H')
|
||||||
|
entries = []
|
||||||
|
entrysz = calcsize(b'>2Hh')
|
||||||
|
for i in xrange(npairs):
|
||||||
|
try:
|
||||||
|
left, right, value = unpack_from(b'>2Hh', raw, offset)
|
||||||
|
except struct_error:
|
||||||
|
offset = len(raw)
|
||||||
|
break # Buggy kern table
|
||||||
|
if left in glyph_ids and right in glyph_ids:
|
||||||
|
entries.append(pack(b'>2Hh', left, right, value))
|
||||||
|
offset += entrysz
|
||||||
|
|
||||||
|
if offset != len(raw):
|
||||||
|
raise UnsupportedFont('This font has extra data at the end of'
|
||||||
|
' a Format 0 kern subtable')
|
||||||
|
|
||||||
|
npairs = len(entries)
|
||||||
|
if npairs == 0:
|
||||||
|
return b''
|
||||||
|
|
||||||
|
entry_selector = max_power_of_two(npairs)
|
||||||
|
search_range = (2 ** entry_selector) * 6
|
||||||
|
range_shift = (npairs - (2 ** entry_selector)) * 6
|
||||||
|
|
||||||
|
entries = b''.join(entries)
|
||||||
|
length = calcsize(headerfmt + b'4H') + len(entries)
|
||||||
|
if self._version == 0:
|
||||||
|
header = pack(headerfmt, version, length, coverage)
|
||||||
|
else:
|
||||||
|
header = pack(headerfmt, length, coverage, tuple_index)
|
||||||
|
return header + pack(b'>4H', npairs, search_range, entry_selector,
|
||||||
|
range_shift) + entries
|
||||||
|
|
@ -104,6 +104,16 @@ def subset(raw, individual_chars, ranges=()):
|
|||||||
# Restrict the cmap table to only contain entries for the resolved glyphs
|
# Restrict the cmap table to only contain entries for the resolved glyphs
|
||||||
cmap.set_character_map(character_map)
|
cmap.set_character_map(character_map)
|
||||||
|
|
||||||
|
if b'kern' in sfnt:
|
||||||
|
try:
|
||||||
|
sfnt[b'kern'].restrict_to_glyphs(frozenset(character_map.itervalues()))
|
||||||
|
except UnsupportedFont as e:
|
||||||
|
print ('Subsetting of kern table failed, ignoring: %s'%e)
|
||||||
|
except Exception as e:
|
||||||
|
print ('Subsetting of kern table failed, ignoring')
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
raw, new_sizes = sfnt()
|
raw, new_sizes = sfnt()
|
||||||
return raw, old_sizes, new_sizes
|
return raw, old_sizes, new_sizes
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user