mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
ebook-polish: Initial subsetting code
This commit is contained in:
parent
09429e3c1c
commit
6b35f84cab
74
src/calibre/ebooks/oeb/polish/subset.py
Normal file
74
src/calibre/ebooks/oeb/polish/subset.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#!/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__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from calibre.ebooks.oeb.base import OEB_STYLES, OEB_DOCS, XPath
|
||||||
|
from calibre.ebooks.oeb.polish import OEB_FONTS
|
||||||
|
from calibre.utils.fonts.sfnt.subset import subset
|
||||||
|
|
||||||
|
def remove_font_face_rules(container, sheet, remove_names):
|
||||||
|
changed = False
|
||||||
|
for rule in tuple(sheet.cssRules):
|
||||||
|
if rule.type != rule.FONT_FACE_RULE:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
uri = rule.style.getProperty('src').propertyValue[0].uri
|
||||||
|
except (IndexError, KeyError, AttributeError, TypeError, ValueError):
|
||||||
|
continue
|
||||||
|
name = container.href_to_name(uri)
|
||||||
|
if name in remove_names:
|
||||||
|
sheet.deleteRule(rule)
|
||||||
|
changed = True
|
||||||
|
return changed
|
||||||
|
|
||||||
|
def subset_all_fonts(container, font_stats, report):
|
||||||
|
remove = set()
|
||||||
|
total_old = total_new = 0
|
||||||
|
for name, mt in container.mime_map.iteritems():
|
||||||
|
if mt in OEB_FONTS or name.rpartition('.')[-1].lower() in {'otf', 'ttf'}:
|
||||||
|
chars = font_stats.get(name, set())
|
||||||
|
path = container.name_path_map[name]
|
||||||
|
total_old += os.path.getsize(path)
|
||||||
|
if not chars:
|
||||||
|
remove.add(name)
|
||||||
|
report('Removed unused font: %s'%name)
|
||||||
|
continue
|
||||||
|
with open(path, 'r+b') as f:
|
||||||
|
raw = f.read()
|
||||||
|
warnings = []
|
||||||
|
container.log('Subsetting font: %s'%name)
|
||||||
|
nraw, old_sizes, new_sizes = subset(raw, chars,
|
||||||
|
warnings=warnings)
|
||||||
|
for w in warnings:
|
||||||
|
container.log.warn(w)
|
||||||
|
olen = sum(old_sizes.itervalues())
|
||||||
|
nlen = sum(new_sizes.itervalues())
|
||||||
|
total_new += len(nraw)
|
||||||
|
report('Decreased the font %s to %.1f%% of its original size'%
|
||||||
|
(name, nlen/olen * 100))
|
||||||
|
f.seek(0), f.truncate(), f.write(nraw)
|
||||||
|
|
||||||
|
for name in remove:
|
||||||
|
container.remove_item(name)
|
||||||
|
|
||||||
|
if remove:
|
||||||
|
for name, mt in container.mime_map.iteritems():
|
||||||
|
if mt in OEB_STYLES:
|
||||||
|
sheet = container.parsed(name)
|
||||||
|
if remove_font_face_rules(container, sheet, remove):
|
||||||
|
container.dirty(name)
|
||||||
|
elif mt in OEB_DOCS:
|
||||||
|
for style in XPath('//h:style')(container.parsed(name)):
|
||||||
|
if style.get('type', 'text/css') == 'text/css' and style.text:
|
||||||
|
sheet = container.parse_css(style.text, name)
|
||||||
|
if remove_font_face_rules(container, sheet, remove):
|
||||||
|
style.text = sheet.cssText
|
||||||
|
container.dirty(name)
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user