def rationalize_cover(self, opf, log): removed = None from lxml import etree guide_cover, guide_elem = None, None for guide_elem in opf.iterguide(): if guide_elem.get('type', '').lower() == 'cover': guide_cover = guide_elem.get('href', '').partition('#')[0] break if not guide_cover: return spine = list(opf.iterspine()) if not spine: return # Check if the cover specified in the guide is also # the first element in spine idref = spine[0].get('idref', '') manifest = list(opf.itermanifest()) if not manifest: return elem = [x for x in manifest if x.get('id', '') == idref] if not elem or elem[0].get('href', None) != guide_cover: return log('Found HTML cover', guide_cover) # Remove from spine as covers must be treated # specially if not self.for_viewer: spine[0].getparent().remove(spine[0]) removed = guide_cover else: # Ensure the cover is displayed as the first item in the book, some # epub files have it set with linear='no' which causes the cover to # display in the end spine[0].attrib.pop('linear', None) opf.spine[0].is_linear = True guide_elem.set('href', 'calibre_raster_cover.jpg') from calibre.ebooks.oeb.base import OPF t = etree.SubElement(elem[0].getparent(), OPF('item'), href=guide_elem.get('href'), id='calibre_raster_cover') t.set('media-type', 'image/jpeg') for elem in list(opf.iterguide()): if elem.get('type', '').lower() == 'titlepage': elem.getparent().remove(elem) t = etree.SubElement(guide_elem.getparent(), OPF('reference')) t.set('type', 'titlepage') t.set('href', guide_cover) t.set('title', 'Title Page') from calibre.ebooks import render_html_svg_workaround if os.path.exists(guide_cover): renderer = render_html_svg_workaround(guide_cover, log) if renderer is not None: open('calibre_raster_cover.jpg', 'wb').write(renderer) return removed
def rationalize_cover(self, opf, log): removed = None from lxml import etree guide_cover, guide_elem = None, None for guide_elem in opf.iterguide(): if guide_elem.get('type', '').lower() == 'cover': guide_cover = guide_elem.get('href', '').partition('#')[0] break if not guide_cover: return spine = list(opf.iterspine()) if not spine: return # Check if the cover specified in the guide is also # the first element in spine idref = spine[0].get('idref', '') manifest = list(opf.itermanifest()) if not manifest: return elem = [x for x in manifest if x.get('id', '') == idref] if not elem or elem[0].get('href', None) != guide_cover: return log('Found HTML cover', guide_cover) # Remove from spine as covers must be treated # specially if not self.for_viewer: spine[0].getparent().remove(spine[0]) removed = guide_cover else: # Ensure the cover is displayed as the first item in the book, some # epub files have it set with linear='no' which causes the cover to # display in the end spine[0].attrib.pop('linear', None) opf.spine[0].is_linear = True guide_elem.set('href', 'calibre_raster_cover.jpg') from calibre.ebooks.oeb.base import OPF t = etree.SubElement(elem[0].getparent(), OPF('item'), href=guide_elem.get('href'), id='calibre_raster_cover') t.set('media-type', 'image/jpeg') for elem in list(opf.iterguide()): if elem.get('type', '').lower() == 'titlepage': elem.getparent().remove(elem) t = etree.SubElement(guide_elem.getparent(), OPF('reference')) t.set('type', 'titlepage') t.set('href', guide_cover) t.set('title', 'Title Page') from calibre.ebooks import render_html_svg_workaround if os.path.exists(guide_cover): renderer = render_html_svg_workaround(guide_cover, log) if renderer is not None: open('calibre_raster_cover.jpg', 'wb').write( renderer) return removed
def _cover_from_html(self, hcover): from calibre.ebooks import render_html_svg_workaround with TemporaryDirectory('_html_cover') as tdir: writer = OEBWriter() writer(self.oeb, tdir) path = os.path.join(tdir, urlunquote(hcover.href)) data = render_html_svg_workaround(path, self.logger) if not data: data = '' id, href = self.oeb.manifest.generate('cover', 'cover.jpg') item = self.oeb.manifest.add(id, href, JPEG_MIME, data=data) return item
def render_cover(opf, opf_path, zf, reader=None): from calibre.ebooks import render_html_svg_workaround from calibre.utils.logging import default_log cpage = opf.first_spine_item() if not cpage: return if reader is not None and reader.encryption_meta.is_encrypted(cpage): return with TemporaryDirectory('_epub_meta') as tdir: with CurrentDir(tdir): zf.extractall() opf_path = opf_path.replace('/', os.sep) cpage = os.path.join(tdir, os.path.dirname(opf_path), cpage) if not os.path.exists(cpage): return if isosx: # On OS X trying to render a HTML cover which uses embedded # fonts more than once in the same process causes a crash in Qt # so be safe and remove the fonts as well as any @font-face # rules for f in walk('.'): if os.path.splitext(f)[1].lower() in ('.ttf', '.otf'): os.remove(f) ffpat = re.compile(br'@font-face.*?{.*?}', re.DOTALL | re.IGNORECASE) with open(cpage, 'r+b') as f: raw = f.read() f.truncate(0) f.seek(0) raw = ffpat.sub(b'', raw) f.write(raw) from calibre.ebooks.chardet import xml_to_unicode raw = xml_to_unicode(raw, strip_encoding_pats=True, resolve_entities=True)[0] from lxml import html for link in html.fromstring(raw).xpath('//link'): href = link.get('href', '') if href: path = os.path.join(os.path.dirname(cpage), href) if os.path.exists(path): with open(path, 'r+b') as f: raw = f.read() f.truncate(0) f.seek(0) raw = ffpat.sub(b'', raw) f.write(raw) return render_html_svg_workaround(cpage, default_log)
def render_cover(opf, opf_path, zf, reader=None): from calibre.ebooks import render_html_svg_workaround from calibre.utils.logging import default_log cpage = opf.first_spine_item() if not cpage: return if reader is not None and reader.encryption_meta.is_encrypted(cpage): return with TemporaryDirectory('_epub_meta') as tdir: with CurrentDir(tdir): zf.extractall() opf_path = opf_path.replace('/', os.sep) cpage = os.path.join(tdir, os.path.dirname(opf_path), cpage) if not os.path.exists(cpage): return if isosx: # On OS X trying to render a HTML cover which uses embedded # fonts more than once in the same process causes a crash in Qt # so be safe and remove the fonts as well as any @font-face # rules for f in walk('.'): if os.path.splitext(f)[1].lower() in ('.ttf', '.otf'): os.remove(f) ffpat = re.compile(br'@font-face.*?{.*?}', re.DOTALL|re.IGNORECASE) with open(cpage, 'r+b') as f: raw = f.read() f.truncate(0) f.seek(0) raw = ffpat.sub(b'', raw) f.write(raw) from calibre.ebooks.chardet import xml_to_unicode raw = xml_to_unicode(raw, strip_encoding_pats=True, resolve_entities=True)[0] from lxml import html for link in html.fromstring(raw).xpath('//link'): href = link.get('href', '') if href: path = os.path.join(os.path.dirname(cpage), href) if os.path.exists(path): with open(path, 'r+b') as f: raw = f.read() f.truncate(0) f.seek(0) raw = ffpat.sub(b'', raw) f.write(raw) return render_html_svg_workaround(cpage, default_log)
def rationalize_cover(self, opf, log): removed = None from lxml import etree guide_cover, guide_elem = None, None for guide_elem in opf.iterguide(): if guide_elem.get("type", "").lower() == "cover": guide_cover = guide_elem.get("href", "") break if not guide_cover: return spine = list(opf.iterspine()) if not spine: return # Check if the cover specified in the guide is also # the first element in spine idref = spine[0].get("idref", "") manifest = list(opf.itermanifest()) if not manifest: return elem = [x for x in manifest if x.get("id", "") == idref] if not elem or elem[0].get("href", None) != guide_cover: return log("Found HTML cover", guide_cover) # Remove from spine as covers must be treated # specially if not self.for_viewer: spine[0].getparent().remove(spine[0]) removed = guide_cover guide_elem.set("href", "calibre_raster_cover.jpg") from calibre.ebooks.oeb.base import OPF t = etree.SubElement(elem[0].getparent(), OPF("item"), href=guide_elem.get("href"), id="calibre_raster_cover") t.set("media-type", "image/jpeg") for elem in list(opf.iterguide()): if elem.get("type", "").lower() == "titlepage": elem.getparent().remove(elem) t = etree.SubElement(guide_elem.getparent(), OPF("reference")) t.set("type", "titlepage") t.set("href", guide_cover) t.set("title", "Title Page") from calibre.ebooks import render_html_svg_workaround if os.path.exists(guide_cover): renderer = render_html_svg_workaround(guide_cover, log) if renderer is not None: open("calibre_raster_cover.jpg", "wb").write(renderer) return removed
def render_cover(cpage, zf, reader=None): from calibre.ebooks import render_html_svg_workaround from calibre.utils.logging import default_log if not cpage: return if reader is not None and reader.encryption_meta.is_encrypted(cpage): return with TemporaryDirectory('_epub_meta') as tdir: with CurrentDir(tdir): zf.extractall() cpage = os.path.join(tdir, cpage) if not os.path.exists(cpage): return return render_html_svg_workaround(cpage, default_log)
def rationalize_cover2(self, opf, log): ''' Ensure that the cover information in the guide is correct. That means, at most one entry with type="cover" that points to a raster cover and at most one entry with type="titlepage" that points to an HTML titlepage. ''' from calibre.ebooks.oeb.base import OPF removed = None from lxml import etree guide_cover, guide_elem = None, None for guide_elem in opf.iterguide(): if guide_elem.get('type', '').lower() == 'cover': guide_cover = guide_elem.get('href', '').partition('#')[0] break if not guide_cover: raster_cover = opf.raster_cover if raster_cover: if guide_elem is None: g = opf.root.makeelement(OPF('guide')) opf.root.append(g) else: g = guide_elem.getparent() guide_cover = raster_cover guide_elem = g.makeelement(OPF('reference'), attrib={ 'href': raster_cover, 'type': 'cover' }) g.append(guide_elem) return spine = list(opf.iterspine()) if not spine: return # Check if the cover specified in the guide is also # the first element in spine idref = spine[0].get('idref', '') manifest = list(opf.itermanifest()) if not manifest: return elem = [x for x in manifest if x.get('id', '') == idref] if not elem or elem[0].get('href', None) != guide_cover: return log('Found HTML cover', guide_cover) # Remove from spine as covers must be treated # specially if not self.for_viewer: if len(spine) == 1: log.warn( 'There is only a single spine item and it is marked as the cover. Removing cover marking.' ) for guide_elem in tuple(opf.iterguide()): if guide_elem.get('type', '').lower() == 'cover': guide_elem.getparent().remove(guide_elem) return else: spine[0].getparent().remove(spine[0]) removed = guide_cover else: # Ensure the cover is displayed as the first item in the book, some # epub files have it set with linear='no' which causes the cover to # display in the end spine[0].attrib.pop('linear', None) opf.spine[0].is_linear = True # Ensure that the guide has a cover entry pointing to a raster cover # and a titlepage entry pointing to the html titlepage. The titlepage # entry will be used by the epub output plugin, the raster cover entry # by other output plugins. # Search for a raster cover identified in the OPF raster_cover = opf.raster_cover # Set the cover guide entry if raster_cover is not None: guide_elem.set('href', raster_cover) else: # Render the titlepage to create a raster cover from calibre.ebooks import render_html_svg_workaround guide_elem.set('href', 'calibre_raster_cover.jpg') t = etree.SubElement(elem[0].getparent(), OPF('item'), href=guide_elem.get('href'), id='calibre_raster_cover') t.set('media-type', 'image/jpeg') if os.path.exists(guide_cover): renderer = render_html_svg_workaround(guide_cover, log) if renderer is not None: open('calibre_raster_cover.jpg', 'wb').write(renderer) # Set the titlepage guide entry self.set_guide_type(opf, 'titlepage', guide_cover, 'Title Page') return removed
def rationalize_cover2(self, opf, log): ''' Ensure that the cover information in the guide is correct. That means, at most one entry with type="cover" that points to a raster cover and at most one entry with type="titlepage" that points to an HTML titlepage. ''' removed = None from lxml import etree guide_cover, guide_elem = None, None for guide_elem in opf.iterguide(): if guide_elem.get('type', '').lower() == 'cover': guide_cover = guide_elem.get('href', '').partition('#')[0] break if not guide_cover: return spine = list(opf.iterspine()) if not spine: return # Check if the cover specified in the guide is also # the first element in spine idref = spine[0].get('idref', '') manifest = list(opf.itermanifest()) if not manifest: return elem = [x for x in manifest if x.get('id', '') == idref] if not elem or elem[0].get('href', None) != guide_cover: return log('Found HTML cover', guide_cover) # Remove from spine as covers must be treated # specially if not self.for_viewer: if len(spine) == 1: log.warn('There is only a single spine item and it is marked as the cover. Removing cover marking.') for guide_elem in tuple(opf.iterguide()): if guide_elem.get('type', '').lower() == 'cover': guide_elem.getparent().remove(guide_elem) return else: spine[0].getparent().remove(spine[0]) removed = guide_cover else: # Ensure the cover is displayed as the first item in the book, some # epub files have it set with linear='no' which causes the cover to # display in the end spine[0].attrib.pop('linear', None) opf.spine[0].is_linear = True # Ensure that the guide has a cover entry pointing to a raster cover # and a titlepage entry pointing to the html titlepage. The titlepage # entry will be used by the epub output plugin, the raster cover entry # by other output plugins. from calibre.ebooks.oeb.base import OPF # Search for a raster cover identified in the OPF raster_cover = opf.raster_cover # Set the cover guide entry if raster_cover is not None: guide_elem.set('href', raster_cover) else: # Render the titlepage to create a raster cover from calibre.ebooks import render_html_svg_workaround guide_elem.set('href', 'calibre_raster_cover.jpg') t = etree.SubElement( elem[0].getparent(), OPF('item'), href=guide_elem.get('href'), id='calibre_raster_cover') t.set('media-type', 'image/jpeg') if os.path.exists(guide_cover): renderer = render_html_svg_workaround(guide_cover, log) if renderer is not None: open('calibre_raster_cover.jpg', 'wb').write( renderer) # Set the titlepage guide entry self.set_guide_type(opf, 'titlepage', guide_cover, 'Title Page') return removed