def __call__(self, oeb, path): """ Write the book in the :class:`OEBBook` object :param:`oeb` to a folder at :param:`path`. """ version = int(self.version[0]) opfname = None if os.path.splitext(path)[1].lower() == '.opf': opfname = os.path.basename(path) path = os.path.dirname(path) if not os.path.isdir(path): os.mkdir(path) output = DirContainer(path, oeb.log) for item in oeb.manifest.values(): output.write(item.href, str(item)) if version == 1: metadata = oeb.to_opf1() elif version == 2: metadata = oeb.to_opf2(page_map=self.page_map) else: raise OEBError("Unrecognized OPF version %r" % self.version) pretty_print = self.pretty_print for mime, (href, data) in metadata.items(): if opfname and mime == OPF_MIME: href = opfname output.write(href, xml2str(data, pretty_print=pretty_print)) return
def __call__(self, oeb, path): """ Write the book in the :class:`OEBBook` object :param:`oeb` to a folder at :param:`path`. """ version = int(self.version[0]) opfname = None if os.path.splitext(path)[1].lower() == '.opf': opfname = os.path.basename(path) path = os.path.dirname(path) if not os.path.isdir(path): os.mkdir(path) output = DirContainer(path, oeb.log) for item in oeb.manifest.values(): output.write(item.href, item.bytes_representation) if version == 1: metadata = oeb.to_opf1() elif version == 2: metadata = oeb.to_opf2(page_map=self.page_map) else: raise OEBError("Unrecognized OPF version %r" % self.version) pretty_print = self.pretty_print for mime, (href, data) in metadata.items(): if opfname and mime == OPF_MIME: href = opfname output.write(href, xml2str(data, pretty_print=pretty_print)) return
def contenttypes(self): E = ElementMaker(namespace=namespaces['ct'], nsmap={None:namespaces['ct']}) types = E.Types() for partname, mt in { "/word/footnotes.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", "/word/document.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/numbering.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", "/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", "/word/endnotes.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml", "/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", "/word/theme/theme1.xml": "application/vnd.openxmlformats-officedocument.theme+xml", "/word/fontTable.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", "/word/webSettings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", "/docProps/core.xml": "application/vnd.openxmlformats-package.core-properties+xml", "/docProps/app.xml": "application/vnd.openxmlformats-officedocument.extended-properties+xml", }.iteritems(): types.append(E.Override(PartName=partname, ContentType=mt)) added = {'png', 'gif', 'jpeg', 'jpg', 'svg', 'xml'} for ext in added: types.append(E.Default(Extension=ext, ContentType=guess_type('a.'+ext)[0])) for ext, mt in { "rels": "application/vnd.openxmlformats-package.relationships+xml", "odttf": "application/vnd.openxmlformats-officedocument.obfuscatedFont", }.iteritems(): added.add(ext) types.append(E.Default(Extension=ext, ContentType=mt)) # TODO: Iterate over all resources and add mimetypes for any that are # not already added return xml2str(types, pretty_print=True)
def appproperties(self): E = ElementMaker(namespace=namespaces['ep'], nsmap={None:namespaces['ep']}) props = E.Properties( E.Application(__appname__), E.AppVersion('%02d.%04d' % numeric_version[:2]), E.DocSecurity('0'), E.HyperlinksChanged('false'), E.LinksUpToDate('true'), E.ScaleCrop('false'), E.SharedDoc('false'), ) return xml2str(props, pretty_print=True)
def appproperties(self): E = ElementMaker(namespace=namespaces['ep'], nsmap={None: namespaces['ep']}) props = E.Properties( E.Application(__appname__), E.AppVersion('%02d.%04d' % numeric_version[:2]), E.DocSecurity('0'), E.HyperlinksChanged('false'), E.LinksUpToDate('true'), E.ScaleCrop('false'), E.SharedDoc('false'), ) return xml2str(props, pretty_print=True)
def rasterize_svg(self, elem, width=0, height=0, format='PNG'): view_box = elem.get('viewBox', elem.get('viewbox', None)) sizes = None logger = self.oeb.logger if view_box is not None: try: box = [ float(x) for x in filter(None, re.split('[, ]', view_box)) ] sizes = [box[2] - box[0], box[3] - box[1]] except (TypeError, ValueError, IndexError): logger.warn( 'SVG image has invalid viewBox="%s", ignoring the viewBox' % view_box) else: for image in elem.xpath( 'descendant::*[local-name()="image" and ' '@height and contains(@height, "%")]'): logger.info( 'Found SVG image height in %, trying to convert...') try: h = float(image.get('height').replace('%', '')) / 100. image.set('height', str(h * sizes[1])) except: logger.exception( 'Failed to convert percentage height:', image.get('height')) data = QByteArray(xml2str(elem, with_tail=False)) svg = QSvgRenderer(data) size = svg.defaultSize() if size.width() == 100 and size.height() == 100 and sizes: size.setWidth(sizes[0]) size.setHeight(sizes[1]) if width or height: size.scale(int(width), int(height), Qt.AspectRatioMode.KeepAspectRatio) logger.info('Rasterizing %r to %dx%d' % (elem, size.width(), size.height())) image = QImage(size, QImage.Format.Format_ARGB32_Premultiplied) image.fill(QColor("white").rgb()) painter = QPainter(image) svg.render(painter) painter.end() array = QByteArray() buffer = QBuffer(array) buffer.open(QIODevice.OpenModeFlag.WriteOnly) image.save(buffer, format) return array.data()
def contenttypes(self): E = ElementMaker(namespace=namespaces['ct'], nsmap={None: namespaces['ct']}) types = E.Types() for partname, mt in { "/word/footnotes.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", "/word/document.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/numbering.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", "/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", "/word/endnotes.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml", "/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", "/word/theme/theme1.xml": "application/vnd.openxmlformats-officedocument.theme+xml", "/word/fontTable.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", "/word/webSettings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", "/docProps/core.xml": "application/vnd.openxmlformats-package.core-properties+xml", "/docProps/app.xml": "application/vnd.openxmlformats-officedocument.extended-properties+xml", }.iteritems(): types.append(E.Override(PartName=partname, ContentType=mt)) added = {'png', 'gif', 'jpeg', 'jpg', 'svg', 'xml'} for ext in added: types.append( E.Default(Extension=ext, ContentType=guess_type('a.' + ext)[0])) for ext, mt in { "rels": "application/vnd.openxmlformats-package.relationships+xml", "odttf": "application/vnd.openxmlformats-officedocument.obfuscatedFont", }.iteritems(): added.add(ext) types.append(E.Default(Extension=ext, ContentType=mt)) # TODO: Iterate over all resources and add mimetypes for any that are # not already added return xml2str(types, pretty_print=True)
def rasterize_svg(self, elem, width=0, height=0, format='PNG'): view_box = elem.get('viewBox', elem.get('viewbox', None)) sizes = None logger = self.oeb.logger if view_box is not None: try: box = [float(x) for x in filter(None, re.split('[, ]', view_box))] sizes = [box[2]-box[0], box[3] - box[1]] except (TypeError, ValueError, IndexError): logger.warn('SVG image has invalid viewBox="%s", ignoring the viewBox' % view_box) else: for image in elem.xpath('descendant::*[local-name()="image" and ' '@height and contains(@height, "%")]'): logger.info('Found SVG image height in %, trying to convert...') try: h = float(image.get('height').replace('%', ''))/100. image.set('height', str(h*sizes[1])) except: logger.exception('Failed to convert percentage height:', image.get('height')) data = QByteArray(xml2str(elem, with_tail=False)) svg = QSvgRenderer(data) size = svg.defaultSize() if size.width() == 100 and size.height() == 100 and sizes: size.setWidth(sizes[0]) size.setHeight(sizes[1]) if width or height: size.scale(width, height, Qt.KeepAspectRatio) logger.info('Rasterizing %r to %dx%d' % (elem, size.width(), size.height())) image = QImage(size, QImage.Format_ARGB32_Premultiplied) image.fill(QColor("white").rgb()) painter = QPainter(image) svg.render(painter) painter.end() array = QByteArray() buffer = QBuffer(array) buffer.open(QIODevice.WriteOnly) image.save(buffer, format) return str(array)
def convert(self, oeb_book, output_path, input_plugin, opts, log): from calibre.ebooks.oeb.base import OEB_IMAGES, xml2str from calibre.utils.zipfile import ZipFile with TemporaryDirectory('_txtz_output') as tdir: # TXT txt_name = 'index.txt' if opts.txt_output_formatting.lower() == 'textile': txt_name = 'index.text' with TemporaryFile(txt_name) as tf: TXTOutput.convert(self, oeb_book, tf, input_plugin, opts, log) shutil.copy(tf, os.path.join(tdir, txt_name)) # Images for item in oeb_book.manifest: if item.media_type in OEB_IMAGES: if hasattr(self.writer, 'images'): path = os.path.join(tdir, 'images') if item.href in self.writer.images: href = self.writer.images[item.href] else: continue else: path = os.path.join(tdir, os.path.dirname(item.href)) href = os.path.basename(item.href) if not os.path.exists(path): os.makedirs(path) with open(os.path.join(path, href), 'wb') as imgf: imgf.write(item.data) # Metadata with open(os.path.join(tdir, 'metadata.opf'), 'wb') as mdataf: root = oeb_book.metadata.to_opf1() elem = root.makeelement('text-formatting') elem.text = opts.txt_output_formatting root.append(elem) mdataf.write(xml2str(root, pretty_print=True)) txtz = ZipFile(output_path, 'w') txtz.add_dir(tdir)
def websettings(self): E = ElementMaker(namespace=namespaces['w'], nsmap={'w': namespaces['w']}) ws = E.webSettings(E.optimizeForBrowser, E.allowPNG, E.doNotSaveAsSingleFile) return xml2str(ws, pretty_print=True)
def websettings(self): E = ElementMaker(namespace=namespaces['w'], nsmap={'w':namespaces['w']}) ws = E.webSettings( E.optimizeForBrowser, E.allowPNG, E.doNotSaveAsSingleFile) return xml2str(ws, pretty_print=True)