Fix embedded fonts not working in preview panel

Add the embedded fonts to Qt and prevent web kit from loading them to
workaround the bug in qt webkit.
This commit is contained in:
Kovid Goyal 2013-11-26 19:13:23 +05:30
parent 1828f46a3b
commit 7a7878f21c
2 changed files with 36 additions and 2 deletions

View File

@ -28,7 +28,7 @@ from calibre.gui2.tweak_book import set_current_container, current_container, tp
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
from calibre.gui2.tweak_book.preview import parse_worker
from calibre.gui2.tweak_book.preview import parse_worker, font_cache
from calibre.gui2.tweak_book.toc import TOCEditor
from calibre.gui2.tweak_book.editor import editor_from_syntax, syntax_from_mime
@ -114,6 +114,7 @@ class Boss(QObject):
parse_worker.clear()
container = job.result
set_current_container(container)
font_cache.remove_fonts()
self.current_metadata = self.gui.current_metadata = container.mi
self.global_undo.open_book(container)
self.gui.update_window_title()

View File

@ -12,15 +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 PyQt4.Qt import (
QWidget, QVBoxLayout, QApplication, QSize, QNetworkAccessManager, QMenu, QIcon,
QNetworkReply, QTimer, QNetworkRequest, QUrl, Qt, QNetworkDiskCache, QToolBar,
pyqtSlot, pyqtSignal)
pyqtSlot, pyqtSignal, QFontDatabase)
from PyQt4.QtWebKit 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
@ -38,6 +40,31 @@ 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')
@ -149,6 +176,12 @@ 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: