Edit Book: Check Book: Add a test to check if the embedded fonts in the book have their embedding permissions enabled

This commit is contained in:
Kovid Goyal 2016-11-18 14:09:45 +05:30
parent fc5e3a8f47
commit 2974bb4d1e
2 changed files with 38 additions and 2 deletions

View File

@ -14,7 +14,7 @@ from calibre.ebooks.oeb.polish.check.base import BaseError, WARN
from calibre.ebooks.oeb.polish.container import OEB_FONTS from calibre.ebooks.oeb.polish.container import OEB_FONTS
from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style
from calibre.ebooks.oeb.polish.fonts import change_font_in_declaration from calibre.ebooks.oeb.polish.fonts import change_font_in_declaration
from calibre.utils.fonts.utils import get_all_font_names from calibre.utils.fonts.utils import get_all_font_names, is_font_embeddable, UnsupportedFont
from tinycss.fonts3 import parse_font_family from tinycss.fonts3 import parse_font_family
@ -32,6 +32,17 @@ def fix_sheet(sheet, css_name, font_name):
return changed return changed
class NotEmbeddable(BaseError):
level = WARN
def __init__(self, name, fs_type):
BaseError.__init__(self, _('The font {} is not allowed to be embedded').format(name), name)
self.HELP = _('The font has a flag in its metadata ({:09b}) set indicating that it is'
' not licensed for embedding. You can ignore this warning, if you are'
' sure you have permission to embed this font.').format(fs_type)
class FontAliasing(BaseError): class FontAliasing(BaseError):
level = WARN level = WARN
@ -83,6 +94,12 @@ def check_fonts(container):
errors.append(InvalidFont(_('Not a valid font: %s') % e, name)) errors.append(InvalidFont(_('Not a valid font: %s') % e, name))
continue continue
font_map[name] = name_map.get('family_name', None) or name_map.get('preferred_family_name', None) or name_map.get('wws_family_name', None) font_map[name] = name_map.get('family_name', None) or name_map.get('preferred_family_name', None) or name_map.get('wws_family_name', None)
try:
embeddable, fs_type = is_font_embeddable(raw)
except UnsupportedFont:
embeddable = True
if not embeddable:
errors.append(NotEmbeddable(name, fs_type))
sheets = [] sheets = []
for name, mt in container.mime_map.iteritems(): for name, mt in container.mime_map.iteritems():

View File

@ -328,6 +328,26 @@ def remove_embed_restriction(raw):
return raw return raw
def is_font_embeddable(raw):
# https://www.microsoft.com/typography/otspec/os2.htm#fst
ok, sig = is_truetype_font(raw)
if not ok:
raise UnsupportedFont('Not a supported font, sfnt_version: %r'%sig)
table, table_index, table_offset = get_table(raw, 'os/2')[:3]
if table is None:
raise UnsupportedFont('Not a supported font, has no OS/2 table')
fs_type_offset = struct.calcsize(b'>HhHH')
fs_type = struct.unpack_from(b'>H', table, fs_type_offset)[0]
if fs_type == 0 or fs_type & 0x8:
return True, fs_type
if fs_type & 1:
return False, fs_type
if fs_type & 0x200:
return False, fs_type
return True, fs_type
def read_bmp_prefix(table, bmp): def read_bmp_prefix(table, bmp):
length, language, segcount = struct.unpack_from(b'>3H', table, bmp+2) length, language, segcount = struct.unpack_from(b'>3H', table, bmp+2)
array_len = segcount //2 array_len = segcount //2
@ -479,4 +499,3 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()