mirror of
git://github.com/kovidgoyal/calibre.git
synced 2025-12-22 19:35:14 +01:00
Add support for embedded fonts and entity declarations to ebook-viewer
This commit is contained in:
parent
0b6f8761d3
commit
483ece52ce
20 changed files with 8364 additions and 4698 deletions
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import re, os, math, copy
|
||||
|
||||
from PyQt4.Qt import QFontDatabase
|
||||
|
||||
from calibre.ebooks.epub.from_any import MAP
|
||||
from calibre.ebooks.epub.from_html import TITLEPAGE
|
||||
from calibre.ebooks.epub import config
|
||||
|
|
@ -77,6 +79,25 @@ def search(self, text, index):
|
|||
if text in open(path, 'rb').read().decode(path.encoding).lower():
|
||||
return i
|
||||
|
||||
def find_embedded_fonts(self):
|
||||
for item in self.opf.manifest:
|
||||
if item.mime_type and 'css' in item.mime_type.lower():
|
||||
css = open(item.path, 'rb').read().decode('utf-8')
|
||||
for match in re.compile(r'@font-face\s*{([^}]+)}').finditer(css):
|
||||
block = match.group(1)
|
||||
family = re.compile(r'font-family\s*:\s*([^;]+)').search(block)
|
||||
url = re.compile(r'url\s*\((.+?)\)', re.DOTALL).search(block)
|
||||
if url:
|
||||
path = url.group(1).split('/')
|
||||
path = os.path.join(os.path.dirname(item.path), *path)
|
||||
id = QFontDatabase.addApplicationFont(path)
|
||||
if id != -1:
|
||||
families = [unicode(f) for f in QFontDatabase.applicationFontFamilies(id)]
|
||||
if family:
|
||||
family = family.group(1).strip().replace('"', '')
|
||||
if family not in families:
|
||||
print 'WARNING: Family aliasing not supported:', block
|
||||
|
||||
def __enter__(self):
|
||||
self._tdir = TemporaryDirectory('_ebook_iter')
|
||||
self.base = self._tdir.__enter__()
|
||||
|
|
@ -104,7 +125,7 @@ def __enter__(self):
|
|||
s.max_page = s.start_page + s.pages - 1
|
||||
self.toc = self.opf.toc
|
||||
|
||||
|
||||
self.find_embedded_fonts()
|
||||
|
||||
return self
|
||||
|
||||
|
|
|
|||
|
|
@ -118,11 +118,10 @@ def __init__(self, url, size, loop):
|
|||
self.page.mainFrame().load(url)
|
||||
|
||||
def render_html(self, ok):
|
||||
from calibre.utils.PythonMagickWand import ImageMagick, NewMagickWand, MagickGetImageBlob, \
|
||||
MagickReadImageBlob, MagickTrimImage, MagickSetFormat
|
||||
|
||||
self.rendered = True
|
||||
try:
|
||||
from calibre.utils.PythonMagickWand import ImageMagick, NewMagickWand, MagickGetImageBlob, \
|
||||
MagickReadImageBlob, MagickTrimImage, MagickSetFormat
|
||||
if not ok:
|
||||
return
|
||||
self.page.setViewportSize(QSize(1280, 1024))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
'''
|
||||
'''
|
||||
import os, math
|
||||
import os, math, re
|
||||
from PyQt4.Qt import QWidget, QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, \
|
||||
QPainter, QPalette, QBrush, QFontDatabase, QDialog, \
|
||||
QByteArray, QColor, QWheelEvent, QPoint, QImage, QRegion, QFont
|
||||
|
|
@ -215,6 +215,18 @@ def fget(self):
|
|||
return self.mainFrame().contentsSize().width() # offsetWidth gives inaccurate results
|
||||
return property(fget=fget)
|
||||
|
||||
class EntityDeclarationProcessor(object):
|
||||
|
||||
def __init__(self, html):
|
||||
self.declared_entities = {}
|
||||
for match in re.finditer(r'<!\s*ENTITY\s+([^>]+)>', html):
|
||||
tokens = match.group(1).split()
|
||||
if len(tokens) > 1:
|
||||
self.declared_entities[tokens[0].strip()] = tokens[1].strip().replace('"', '')
|
||||
self.processed_html = html
|
||||
for key, val in self.declared_entities.iteritems():
|
||||
self.processed_html = self.processed_html.replace('&%s;'%key, val)
|
||||
|
||||
class DocumentView(QWebView):
|
||||
|
||||
DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern)
|
||||
|
|
@ -290,6 +302,7 @@ def path(self):
|
|||
def load_path(self, path, pos=0.0):
|
||||
self.initial_pos = pos
|
||||
html = open(path, 'rb').read().decode(path.encoding)
|
||||
html = EntityDeclarationProcessor(html).processed_html
|
||||
self.setHtml(html, QUrl.fromLocalFile(path))
|
||||
|
||||
def load_started(self):
|
||||
|
|
|
|||
|
|
@ -363,7 +363,9 @@ def load_path(self, path, pos=0.0):
|
|||
self.view.load_path(path, pos=pos)
|
||||
|
||||
def viewport_resized(self, frac):
|
||||
self.set_page_number(frac)
|
||||
pos = self.pos.value()
|
||||
self.view.scroll_to(pos, notify=False)
|
||||
#self.set_page_number(frac)
|
||||
|
||||
def close_progress_indicator(self):
|
||||
self.pi.stop()
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue