mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-31 14:33:54 -04:00
Also use the new font fallback code for embedding fonts in the conversion pipeline
This commit is contained in:
parent
57476aa5cb
commit
8f6f6fe4a0
@ -19,9 +19,18 @@ from calibre.utils.filenames import ascii_filename
|
|||||||
from calibre.utils.fonts.scanner import font_scanner, NoFonts
|
from calibre.utils.fonts.scanner import font_scanner, NoFonts
|
||||||
|
|
||||||
|
|
||||||
def used_font(style, embedded_fonts):
|
def font_families_from_style(style):
|
||||||
ff = [unicode(f) for f in style.get('font-family', []) if unicode(f).lower() not in {
|
return [unicode(f) for f in style.get('font-family', []) if unicode(f).lower() not in {
|
||||||
'serif', 'sansserif', 'sans-serif', 'fantasy', 'cursive', 'monospace'}]
|
'serif', 'sansserif', 'sans-serif', 'fantasy', 'cursive', 'monospace'}]
|
||||||
|
|
||||||
|
|
||||||
|
def font_already_embedded(style, newly_embedded_fonts):
|
||||||
|
ff = font_families_from_style(style)
|
||||||
|
return not ff or ff[0] in newly_embedded_fonts
|
||||||
|
|
||||||
|
|
||||||
|
def used_font(style, embedded_fonts):
|
||||||
|
ff = font_families_from_style(style)
|
||||||
if not ff:
|
if not ff:
|
||||||
return False, None
|
return False, None
|
||||||
lnames = {unicode(x).lower() for x in ff}
|
lnames = {unicode(x).lower() for x in ff}
|
||||||
@ -85,7 +94,7 @@ class EmbedFonts(object):
|
|||||||
self.parser = cssutils.CSSParser(loglevel=logging.CRITICAL, log=logging.getLogger('calibre.css'))
|
self.parser = cssutils.CSSParser(loglevel=logging.CRITICAL, log=logging.getLogger('calibre.css'))
|
||||||
self.warned = set()
|
self.warned = set()
|
||||||
self.warned2 = set()
|
self.warned2 = set()
|
||||||
self.warned3 = set()
|
self.newly_embedded_fonts = set()
|
||||||
|
|
||||||
for item in oeb.spine:
|
for item in oeb.spine:
|
||||||
if not hasattr(item.data, 'xpath'):
|
if not hasattr(item.data, 'xpath'):
|
||||||
@ -171,7 +180,7 @@ class EmbedFonts(object):
|
|||||||
for child in elem:
|
for child in elem:
|
||||||
self.find_usage_in(child, style, ff_rules)
|
self.find_usage_in(child, style, ff_rules)
|
||||||
has_font, existing = used_font(style, ff_rules)
|
has_font, existing = used_font(style, ff_rules)
|
||||||
if not has_font:
|
if not has_font or font_already_embedded(style, self.newly_embedded_fonts):
|
||||||
return
|
return
|
||||||
if existing is None:
|
if existing is None:
|
||||||
in_book = used_font(style, self.embedded_fonts)[1]
|
in_book = used_font(style, self.embedded_fonts)[1]
|
||||||
@ -194,8 +203,8 @@ class EmbedFonts(object):
|
|||||||
page_sheet.data.insertRule(rule, len(page_sheet.data.cssRules))
|
page_sheet.data.insertRule(rule, len(page_sheet.data.cssRules))
|
||||||
|
|
||||||
def embed_font(self, style):
|
def embed_font(self, style):
|
||||||
ff = [unicode(f) for f in style.get('font-family', []) if unicode(f).lower() not in {
|
from calibre.ebooks.oeb.polish.embed import find_matching_font, weight_as_number
|
||||||
'serif', 'sansserif', 'sans-serif', 'fantasy', 'cursive', 'monospace'}]
|
ff = font_families_from_style(style)
|
||||||
if not ff:
|
if not ff:
|
||||||
return
|
return
|
||||||
ff = ff[0]
|
ff = ff[0]
|
||||||
@ -204,39 +213,41 @@ class EmbedFonts(object):
|
|||||||
try:
|
try:
|
||||||
fonts = font_scanner.fonts_for_family(ff)
|
fonts = font_scanner.fonts_for_family(ff)
|
||||||
except NoFonts:
|
except NoFonts:
|
||||||
self.log.warn('Failed to find fonts for family:', ff, 'not embedding')
|
try:
|
||||||
self.warned.add(ff)
|
fonts = font_scanner.alt_fonts_for_family(ff)
|
||||||
return
|
except NoFonts:
|
||||||
try:
|
self.log.warn('Failed to find fonts for family:', ff, 'not embedding')
|
||||||
weight = int(style.get('font-weight', '400'))
|
self.warned.add(ff)
|
||||||
except (ValueError, TypeError, AttributeError):
|
return
|
||||||
w = style['font-weight']
|
weight = weight_as_number(style.get('font-weight', '400'))
|
||||||
if w not in self.warned2:
|
|
||||||
self.log.warn('Invalid weight in font style: %r' % w)
|
def do_embed(f):
|
||||||
self.warned2.add(w)
|
data = font_scanner.get_font_data(f)
|
||||||
return
|
name = f['full_name']
|
||||||
|
ext = 'otf' if f['is_otf'] else 'ttf'
|
||||||
|
name = ascii_filename(name).replace(' ', '-').replace('(', '').replace(')', '')
|
||||||
|
fid, href = self.oeb.manifest.generate(id=u'font', href=u'fonts/%s.%s'%(name, ext))
|
||||||
|
item = self.oeb.manifest.add(fid, href, guess_type('dummy.'+ext)[0], data=data)
|
||||||
|
item.unload_data_from_memory()
|
||||||
|
page_sheet = self.get_page_sheet()
|
||||||
|
href = page_sheet.relhref(item.href)
|
||||||
|
css = '''@font-face { font-family: "%s"; font-weight: %s; font-style: %s; font-stretch: %s; src: url(%s) }''' % (
|
||||||
|
f['font-family'], f['font-weight'], f['font-style'], f['font-stretch'], href)
|
||||||
|
sheet = self.parser.parseString(css, validate=False)
|
||||||
|
page_sheet.data.insertRule(sheet.cssRules[0], len(page_sheet.data.cssRules))
|
||||||
|
self.newly_embedded_fonts.add(ff)
|
||||||
|
return find_font_face_rules(sheet, self.oeb)[0]
|
||||||
|
|
||||||
for f in fonts:
|
for f in fonts:
|
||||||
if f['weight'] == weight and f['font-style'] == style.get('font-style', 'normal') and f['font-stretch'] == style.get('font-stretch', 'normal'):
|
if f['weight'] == weight and f['font-style'] == style.get('font-style', 'normal') and f['font-stretch'] == style.get('font-stretch', 'normal'):
|
||||||
self.log('Embedding font %s from %s' % (f['full_name'], f['path']))
|
self.log('Embedding font %s from %s' % (f['full_name'], f['path']))
|
||||||
data = font_scanner.get_font_data(f)
|
return do_embed(f)
|
||||||
name = f['full_name']
|
try:
|
||||||
ext = 'otf' if f['is_otf'] else 'ttf'
|
f = find_matching_font(fonts, style.get('font-weight', 'normal'), style.get('font-style', 'normal'), style.get('font-stretch', 'normal'))
|
||||||
name = ascii_filename(name).replace(' ', '-').replace('(', '').replace(')', '')
|
except Exception:
|
||||||
fid, href = self.oeb.manifest.generate(id=u'font', href=u'fonts/%s.%s'%(name, ext))
|
if ff not in self.warned2:
|
||||||
item = self.oeb.manifest.add(fid, href, guess_type('dummy.'+ext)[0], data=data)
|
self.log.exception('Failed to find a matching font for family', ff, 'not embedding')
|
||||||
item.unload_data_from_memory()
|
self.warned2.add(ff)
|
||||||
page_sheet = self.get_page_sheet()
|
return
|
||||||
href = page_sheet.relhref(item.href)
|
self.log('Embedding font %s from %s' % (f['full_name'], f['path']))
|
||||||
css = '''@font-face { font-family: "%s"; font-weight: %s; font-style: %s; font-stretch: %s; src: url(%s) }''' % (
|
return do_embed(f)
|
||||||
f['font-family'], f['font-weight'], f['font-style'], f['font-stretch'], href)
|
|
||||||
sheet = self.parser.parseString(css, validate=False)
|
|
||||||
page_sheet.data.insertRule(sheet.cssRules[0], len(page_sheet.data.cssRules))
|
|
||||||
return find_font_face_rules(sheet, self.oeb)[0]
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
w = int(f['weight'])
|
|
||||||
except Exception:
|
|
||||||
w = 200
|
|
||||||
if w % 100 and ((ff, w) not in self.warned3):
|
|
||||||
self.warned3.add((ff, w))
|
|
||||||
self.log.warn('The font %s has a non-standard weight: %s, it will not be embedded' % (ff, w))
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user