DOCX Output: Plumbing for font embedding

This commit is contained in:
Kovid Goyal 2015-03-26 15:19:13 +05:30
parent b5ca830fc2
commit e07bd9b022
3 changed files with 36 additions and 1 deletions

View file

@ -14,7 +14,7 @@
from calibre import guess_type
from calibre.constants import numeric_version, __appname__
from calibre.ebooks.docx.names import namespaces, STYLES, WEB_SETTINGS, IMAGES
from calibre.ebooks.docx.names import namespaces, STYLES, WEB_SETTINGS, IMAGES, FONTS
from calibre.ebooks.metadata import authors_to_string
from calibre.ebooks.metadata.opf2 import OPF as ReadOPF
from calibre.ebooks.oeb.base import OPF, OPF2_NS
@ -54,6 +54,7 @@ def __init__(self):
for typ, target in {
STYLES: 'styles.xml',
WEB_SETTINGS: 'webSettings.xml',
FONTS: 'fontTable.xml',
}.iteritems():
self.add_relationship(target, typ)
@ -85,6 +86,9 @@ class DOCX(object):
def __init__(self, opts, log):
self.opts, self.log = opts, log
self.document_relationships = DocumentRelationships()
self.font_table = etree.Element('{%s}fonts' % namespaces['w'], nsmap={k:namespaces[k] for k in 'wr'})
E = ElementMaker(namespace=namespaces['pr'], nsmap={None:namespaces['pr']})
self.embedded_fonts = E.Relationships()
# Boilerplate {{{
@property
@ -181,7 +185,9 @@ def write(self, path_or_stream, oeb):
zf.writestr('word/webSettings.xml', self.websettings)
zf.writestr('word/document.xml', xml2str(self.document))
zf.writestr('word/styles.xml', xml2str(self.styles))
zf.writestr('word/fontTable.xml', xml2str(self.font_table))
zf.writestr('word/_rels/document.xml.rels', self.document_relationships.serialize())
zf.writestr('word/_rels/fontTable.xml.rels', xml2str(self.embedded_fonts))
for fname, data_getter in self.images.iteritems():
zf.writestr(fname, data_getter())

View file

@ -0,0 +1,26 @@
#!/usr/bin/env python2
# vim:fileencoding=utf-8
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
from calibre.ebooks.docx.names import makeelement
class FontsManager(object):
def __init__(self, oeb):
self.oeb, self.log = oeb, oeb.log
def serialize(self, text_styles, fonts, embed_relationships):
font_families, seen = set(), set()
for ts in text_styles:
if ts.font_family:
lf = ts.font_family.lower()
if lf not in seen:
seen.add(lf)
font_families.add(ts.font_family)
for family in sorted(font_families):
makeelement(fonts, 'w:font', w_name=family)

View file

@ -14,6 +14,7 @@
from calibre.ebooks.docx.names import namespaces
from calibre.ebooks.docx.writer.styles import w, StylesManager
from calibre.ebooks.docx.writer.images import ImagesManager
from calibre.ebooks.docx.writer.fonts import FontsManager
from calibre.ebooks.oeb.stylizer import Stylizer as Sz, Style as St
from calibre.ebooks.oeb.base import XPath, barename
from calibre.ebooks.pdf.render.common import PAPER_SIZES
@ -170,6 +171,7 @@ def __call__(self):
self.styles_manager = StylesManager()
self.images_manager = ImagesManager(self.oeb, self.docx.document_relationships)
self.fonts_manager = FontsManager(self.oeb)
for item in self.oeb.spine:
self.process_item(item)
@ -296,3 +298,4 @@ def margin(which):
self.docx.images = {}
self.styles_manager.serialize(self.docx.styles)
self.images_manager.serialize(self.docx.images)
self.fonts_manager.serialize(self.styles_manager.text_styles, self.docx.font_table, self.docx.embedded_fonts)