mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
KF8 Output: Handle links ot binary resources
This commit is contained in:
parent
ed118bbaa0
commit
d9b9961c77
@ -170,13 +170,13 @@ class MOBIOutput(OutputFormatPlugin):
|
|||||||
resources = Resources(oeb, opts, self.is_periodical,
|
resources = Resources(oeb, opts, self.is_periodical,
|
||||||
add_fonts=create_kf8)
|
add_fonts=create_kf8)
|
||||||
|
|
||||||
kf8 = self.create_kf8() if create_kf8 else None
|
kf8 = self.create_kf8(resources) if create_kf8 else None
|
||||||
|
|
||||||
self.write_mobi(input_plugin, output_path, kf8, resources)
|
self.write_mobi(input_plugin, output_path, kf8, resources)
|
||||||
|
|
||||||
def create_kf8(self):
|
def create_kf8(self, resources):
|
||||||
from calibre.ebooks.mobi.writer8.main import KF8Writer
|
from calibre.ebooks.mobi.writer8.main import KF8Writer
|
||||||
return KF8Writer(self.oeb, self.opts)
|
return KF8Writer(self.oeb, self.opts, resources)
|
||||||
|
|
||||||
def write_mobi(self, input_plugin, output_path, kf8, resources):
|
def write_mobi(self, input_plugin, output_path, kf8, resources):
|
||||||
from calibre.ebooks.mobi.mobiml import MobiMLizer
|
from calibre.ebooks.mobi.mobiml import MobiMLizer
|
||||||
|
@ -7,6 +7,8 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
import imghdr
|
||||||
|
|
||||||
from calibre.ebooks.mobi import MAX_THUMB_DIMEN, MAX_THUMB_SIZE
|
from calibre.ebooks.mobi import MAX_THUMB_DIMEN, MAX_THUMB_SIZE
|
||||||
from calibre.ebooks.mobi.utils import (rescale_image, mobify_image,
|
from calibre.ebooks.mobi.utils import (rescale_image, mobify_image,
|
||||||
write_font_record)
|
write_font_record)
|
||||||
@ -23,6 +25,7 @@ class Resources(object):
|
|||||||
|
|
||||||
self.item_map = {}
|
self.item_map = {}
|
||||||
self.records = []
|
self.records = []
|
||||||
|
self.mime_map = {}
|
||||||
self.masthead_offset = 0
|
self.masthead_offset = 0
|
||||||
self.used_image_indices = set()
|
self.used_image_indices = set()
|
||||||
self.image_indices = set()
|
self.image_indices = set()
|
||||||
@ -76,6 +79,7 @@ class Resources(object):
|
|||||||
self.image_indices.add(len(self.records))
|
self.image_indices.add(len(self.records))
|
||||||
self.records.append(data)
|
self.records.append(data)
|
||||||
self.item_map[item.href] = index
|
self.item_map[item.href] = index
|
||||||
|
self.mime_map[item.href] = 'image/%s'%imghdr.what(None, data)
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
if cover_href and item.href == cover_href:
|
if cover_href and item.href == cover_href:
|
||||||
|
@ -8,20 +8,25 @@ __copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
import cssutils
|
import cssutils
|
||||||
|
|
||||||
from calibre.ebooks.oeb.base import (OEB_DOCS, OEB_STYLES, SVG_MIME)
|
from calibre import isbytestring
|
||||||
|
from calibre.ebooks.oeb.base import (OEB_DOCS, OEB_STYLES, SVG_MIME, XPath)
|
||||||
|
|
||||||
XML_DOCS = OEB_DOCS | {SVG_MIME}
|
XML_DOCS = OEB_DOCS | {SVG_MIME}
|
||||||
|
|
||||||
class KF8Writer(object):
|
class KF8Writer(object):
|
||||||
|
|
||||||
def __init__(self, oeb, opts):
|
def __init__(self, oeb, opts, resources):
|
||||||
self.oeb, self.opts, self.log = oeb, opts, oeb.log
|
self.oeb, self.opts, self.log = oeb, opts, oeb.log
|
||||||
self.used_images = set()
|
self.used_images = set()
|
||||||
|
self.resources = resources
|
||||||
self.dup_data()
|
self.dup_data()
|
||||||
|
|
||||||
|
self.replace_resource_links()
|
||||||
|
|
||||||
self.create_pieces()
|
self.create_pieces()
|
||||||
|
|
||||||
def dup_data(self):
|
def dup_data(self):
|
||||||
@ -41,6 +46,51 @@ class KF8Writer(object):
|
|||||||
def data(self, item):
|
def data(self, item):
|
||||||
return self._data_cache.get(item.href, item.data)
|
return self._data_cache.get(item.href, item.data)
|
||||||
|
|
||||||
|
def replace_resource_links(self):
|
||||||
|
''' Replace links to resources (raster images/fonts) with pointers to
|
||||||
|
the MOBI record containing the resource. The pointers are of the form:
|
||||||
|
kindle:embed:XXXX?mime=image/* The ?mime= is apparently optional and
|
||||||
|
not used for fonts. '''
|
||||||
|
|
||||||
|
def pointer(item, oref):
|
||||||
|
ref = item.abshref(oref)
|
||||||
|
idx = self.resources.item_map.get(ref, None)
|
||||||
|
if idx is not None:
|
||||||
|
is_image = self.resources.records[idx-1][:4] not in {b'FONT'}
|
||||||
|
if is_image:
|
||||||
|
self.used_images.add(ref)
|
||||||
|
return 'kindle:embed:%04d?mime=%s'%(idx,
|
||||||
|
self.resources.mime_map[ref])
|
||||||
|
else:
|
||||||
|
return 'kindle:embed:%04d'%idx
|
||||||
|
return oref
|
||||||
|
|
||||||
|
for item in self.oeb.manifest:
|
||||||
|
|
||||||
|
if item.media_type in XML_DOCS:
|
||||||
|
root = self.data(item)
|
||||||
|
for tag in XPath('//h:img|//svg:image')(root):
|
||||||
|
for attr, ref in tag.attrib.iteritems():
|
||||||
|
if attr.split('}')[-1].lower() in {'src', 'href'}:
|
||||||
|
tag.attrib[attr] = pointer(item, ref)
|
||||||
|
|
||||||
|
for tag in XPath('//h:style')(root):
|
||||||
|
if tag.text:
|
||||||
|
sheet = cssutils.parseString(tag.text)
|
||||||
|
replacer = partial(pointer, item)
|
||||||
|
cssutils.replaceUrls(sheet, replacer,
|
||||||
|
ignoreImportRules=True)
|
||||||
|
repl = sheet.cssText
|
||||||
|
if isbytestring(repl):
|
||||||
|
repl = repl.decode('utf-8')
|
||||||
|
tag.text = '\n'+ repl + '\n'
|
||||||
|
|
||||||
|
elif item.media_type in OEB_STYLES:
|
||||||
|
sheet = self.data(item)
|
||||||
|
replacer = partial(pointer, item)
|
||||||
|
cssutils.replaceUrls(sheet, replacer, ignoreImportRules=True)
|
||||||
|
|
||||||
|
|
||||||
def create_pieces(self):
|
def create_pieces(self):
|
||||||
self.flows = [None] # First flow item is reserved for the text
|
self.flows = [None] # First flow item is reserved for the text
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user