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 lxml.builder import ElementMaker
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 @@ class DocumentRelationships(object):
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 @@ class DOCX(object):
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 lxml.builder import ElementMaker
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 @@ class Convert(object):
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 @@ class Convert(object):
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)