diff --git a/src/calibre/ebooks/oeb/iterator/book.py b/src/calibre/ebooks/oeb/iterator/book.py index 1878e2c6fd..0832d4bafc 100644 --- a/src/calibre/ebooks/oeb/iterator/book.py +++ b/src/calibre/ebooks/oeb/iterator/book.py @@ -75,8 +75,7 @@ class EbookIterator(BookmarksMixin): return i def __enter__(self, processed=False, only_input_plugin=False, - run_char_count=True, read_anchor_map=True, view_kepub=False, - extract_embedded_fonts_for_qt=False): + run_char_count=True, read_anchor_map=True, view_kepub=False): ''' Convert an ebook file into an exploded OEB book suitable for display in viewers/preprocessing etc. ''' @@ -178,16 +177,6 @@ class EbookIterator(BookmarksMixin): self.read_bookmarks() - if extract_embedded_fonts_for_qt: - from calibre.ebooks.oeb.iterator.extract_fonts import extract_fonts - try: - extract_fonts(self.opf, self.log) - except: - ol = self.log.filter_level - self.log.filter_level = self.log.DEBUG - self.log.exception('Failed to extract fonts') - self.log.filter_level = ol - return self def __exit__(self, *args): diff --git a/src/calibre/ebooks/oeb/iterator/extract_fonts.py b/src/calibre/ebooks/oeb/iterator/extract_fonts.py deleted file mode 100644 index 132ccb6505..0000000000 --- a/src/calibre/ebooks/oeb/iterator/extract_fonts.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/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 ' -__docformat__ = 'restructuredtext en' - -import re, os, logging -from functools import partial -from future_builtins import map - -class FamilyMap(dict): - - def __init__(self, log): - dict.__init__(self) - self.replace_map = {} - self.added_fonts = set() - self.log = log - - def __call__(self, basedir, match): - self.read_font_fule(basedir, match.group()) - return b'' - - def finalize(self): - if self.replace_map: - self.pat = re.compile(br'(font-family.*?)(' + - b'|'.join([re.escape(x) for x in - self.replace_map.iterkeys()])+b')', re.I) - - def replace_font_families(self, raw): - if self.replace_map: - def sub(m): - k = m.group(2).lower() - for q, val in self.replace_map.iteritems(): - if q.lower() == k.lower(): - return m.group().replace(m.group(2), val) - return m.group() - - return self.pat.sub(sub, raw) - - def read_font_fule(self, basedir, css): - from PyQt5.Qt import QFontDatabase - import cssutils - cssutils.log.setLevel(logging.ERROR) - try: - sheet = cssutils.parseString(css, validate=False) - except: - return - for rule in sheet.cssRules: - try: - s = rule.style - src = s.getProperty('src').propertyValue[0].uri - font_family = s.getProperty('font-family').propertyValue[0].value - except: - continue - if not src or not font_family: - continue - font_file = os.path.normcase(os.path.abspath(os.path.join(basedir, - src))) - if font_file not in self.added_fonts: - self.added_fonts.add(font_file) - if not os.path.exists(font_file): - from calibre.ebooks.oeb.base import urlunquote - ff = urlunquote(font_file, error_handling='replace') - if os.path.exists(ff): - font_file = ff - if os.path.exists(font_file): - with open(font_file, 'rb') as f: - idx = QFontDatabase.addApplicationFontFromData(f.read()) - if idx > -1: - family = map(unicode, - QFontDatabase.applicationFontFamilies(idx)).next() - self.log('Extracted embedded font:', family, 'from', - os.path.basename(font_file)) - if (family and family != font_family and - family not in self.replace_map): - self.log('Replacing font family value:', - font_family, 'with', family) - self.replace_map[font_family.encode('utf-8')] = \ - family.encode('utf-8') - -def extract_fonts(opf, log): - ''' - Extract embedded fonts from the ebook and add them explicitly to the Qt - font database to workaround https://bugs.webkit.org/show_bug.cgi?id=29433 - - Only works if the font-face and font-family rules are all contained in the - CSS files (Also processing the HTML files would be too much of a - performance hit, to do robustly). - ''' - css_files = {} - font_family_map = FamilyMap(log) - pat = re.compile(br'^\s*@font-face\s*{[^}]+}', re.M) - - for item in opf.manifest: - if item.mime_type and item.mime_type.lower() in { - 'text/css', 'text/x-oeb1-css', 'text/x-oeb-css'}: - try: - with open(item.path, 'rb') as f: - raw = f.read() - except EnvironmentError: - continue - css_files[item.path] = pat.sub(partial(font_family_map, - os.path.dirname(item.path)), raw) - - font_family_map.finalize() - - if font_family_map.added_fonts: - for path, raw in css_files.iteritems(): - with open(path, 'wb') as f: - nraw = font_family_map.replace_font_families(raw) or raw - f.write(nraw) - diff --git a/src/calibre/gui2/tweak_book/boss.py b/src/calibre/gui2/tweak_book/boss.py index 3c88b8746b..ded63cb952 100644 --- a/src/calibre/gui2/tweak_book/boss.py +++ b/src/calibre/gui2/tweak_book/boss.py @@ -18,7 +18,7 @@ from calibre import prints, isbytestring from calibre.ptempfile import PersistentTemporaryDirectory, TemporaryDirectory from calibre.ebooks.oeb.base import urlnormalize from calibre.ebooks.oeb.polish.main import SUPPORTED, tweak_polish -from calibre.ebooks.oeb.polish.container import get_container as _gc, clone_container, guess_type, OEB_FONTS, OEB_DOCS, OEB_STYLES +from calibre.ebooks.oeb.polish.container import get_container as _gc, clone_container, guess_type, OEB_DOCS, OEB_STYLES from calibre.ebooks.oeb.polish.cover import mark_as_cover, mark_as_titlepage, set_cover from calibre.ebooks.oeb.polish.css import filter_css from calibre.ebooks.oeb.polish.pretty import fix_all_html, pretty_all @@ -34,7 +34,7 @@ from calibre.gui2.tweak_book import ( from calibre.gui2.tweak_book.undo import GlobalUndoHistory from calibre.gui2.tweak_book.file_list import NewFileDialog from calibre.gui2.tweak_book.save import SaveManager, save_container, find_first_existing_ancestor -from calibre.gui2.tweak_book.preview import parse_worker, font_cache +from calibre.gui2.tweak_book.preview import parse_worker from calibre.gui2.tweak_book.toc import TOCEditor from calibre.gui2.tweak_book.editor import editor_from_syntax, syntax_from_mime from calibre.gui2.tweak_book.editor.insert_resource import get_resource_data, NewBook @@ -50,14 +50,6 @@ _diff_dialogs = [] def get_container(*args, **kwargs): kwargs['tweak_mode'] = True container = _gc(*args, **kwargs) - # We preload the embedded fonts from this book, so that the preview panel - # works - font_cache.remove_fonts() - for name, mt in container.mime_map.iteritems(): - if mt in OEB_FONTS and container.exists(name): - with container.open(name, 'rb') as f: - raw = f.read() - font_cache.add_font(raw) return container def setup_cssutils_serialization(): diff --git a/src/calibre/gui2/tweak_book/preview.py b/src/calibre/gui2/tweak_book/preview.py index 457f98c3b1..d6999153e5 100644 --- a/src/calibre/gui2/tweak_book/preview.py +++ b/src/calibre/gui2/tweak_book/preview.py @@ -12,19 +12,17 @@ from base64 import b64encode from future_builtins import map from threading import Thread from Queue import Queue, Empty -from collections import namedtuple from functools import partial from urlparse import urlparse from PyQt5.Qt import ( QWidget, QVBoxLayout, QApplication, QSize, QNetworkAccessManager, QMenu, QIcon, QNetworkReply, QTimer, QNetworkRequest, QUrl, Qt, QNetworkDiskCache, QToolBar, - pyqtSlot, pyqtSignal, QFontDatabase) + pyqtSlot, pyqtSignal) from PyQt5.QtWebKitWidgets import QWebView, QWebInspector, QWebPage from calibre import prints from calibre.constants import iswindows -from calibre.ebooks.oeb.polish.container import OEB_FONTS from calibre.ebooks.oeb.polish.parsing import parse from calibre.ebooks.oeb.base import serialize, OEB_DOCS from calibre.ptempfile import PersistentTemporaryDirectory @@ -43,31 +41,6 @@ def get_data(name): return editors[name].get_raw_data() return current_container().raw_data(name) -class FontCache(object): - - def __init__(self): - self.cache = {} - self.entry = namedtuple('Entry', 'size hash families') - - def remove_fonts(self): - for font_id in self.cache: - QFontDatabase.removeApplicationFont(font_id) - self.cache.clear() - - def add_font(self, data): - existing = None - for font_id, entry in self.cache.iteritems(): - if entry.size == len(data) and entry.hash == hash(data): - existing = entry - break - if existing is None: - font_id = QFontDatabase.addApplicationFontFromData(data) - if font_id > -1: - families = frozenset(map(lambda x:icu_lower(unicode(x)), QFontDatabase.applicationFontFamilies(font_id))) - self.cache[font_id] = self.entry(len(data), hash(data), families) - -font_cache = FontCache() - # Parsing of html to add linenumbers {{{ def parse_html(raw): root = parse(raw, decoder=lambda x:x.decode('utf-8'), line_numbers=True, linenumber_attribute='data-lnum') @@ -182,12 +155,6 @@ class NetworkReply(QNetworkReply): self.setHeader(QNetworkRequest.ContentTypeHeader, mime_type) self.setHeader(QNetworkRequest.ContentLengthHeader, len(self.__data)) QTimer.singleShot(0, self.finalize_reply) - if mime_type in OEB_FONTS: - font_cache.add_font(data) - # We prevent the use of the embedded font because of the the - # bug in Qt WebKit, - # https://bugs.webkit.org/show_bug.cgi?id=29433 - self.__data = b'' def check_for_parse(self): if self._aborted: @@ -422,8 +389,8 @@ class WebView(QWebView):

Note that this is a quick preview only, it is not intended to simulate an actual ebook reader. Some - aspects of your ebook will not work, such as, page breaks, - page margins and embedded fonts that use font name aliasing. + aspects of your ebook will not work, such as, page breaks and + page margins. ''')) self.page().current_root = None diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index bd047f27a2..c2bad89aaf 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -774,8 +774,7 @@ class EbookViewer(MainWindow): self.iterator.__exit__() self.iterator = EbookIterator(pathtoebook) self.open_progress_indicator(_('Loading ebook...')) - worker = Worker(target=partial(self.iterator.__enter__, - extract_embedded_fonts_for_qt=True, view_kepub=True)) + worker = Worker(target=partial(self.iterator.__enter__, view_kpepub=True)) worker.start() while worker.isAlive(): worker.join(0.1)