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 import guess_type
from calibre.constants import numeric_version, __appname__ 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 import authors_to_string
from calibre.ebooks.metadata.opf2 import OPF as ReadOPF from calibre.ebooks.metadata.opf2 import OPF as ReadOPF
from calibre.ebooks.oeb.base import OPF, OPF2_NS from calibre.ebooks.oeb.base import OPF, OPF2_NS
@ -54,6 +54,7 @@ class DocumentRelationships(object):
for typ, target in { for typ, target in {
STYLES: 'styles.xml', STYLES: 'styles.xml',
WEB_SETTINGS: 'webSettings.xml', WEB_SETTINGS: 'webSettings.xml',
FONTS: 'fontTable.xml',
}.iteritems(): }.iteritems():
self.add_relationship(target, typ) self.add_relationship(target, typ)
@ -85,6 +86,9 @@ class DOCX(object):
def __init__(self, opts, log): def __init__(self, opts, log):
self.opts, self.log = opts, log self.opts, self.log = opts, log
self.document_relationships = DocumentRelationships() 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 {{{ # Boilerplate {{{
@property @property
@ -181,7 +185,9 @@ class DOCX(object):
zf.writestr('word/webSettings.xml', self.websettings) zf.writestr('word/webSettings.xml', self.websettings)
zf.writestr('word/document.xml', xml2str(self.document)) zf.writestr('word/document.xml', xml2str(self.document))
zf.writestr('word/styles.xml', xml2str(self.styles)) 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/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(): for fname, data_getter in self.images.iteritems():
zf.writestr(fname, data_getter()) 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.names import namespaces
from calibre.ebooks.docx.writer.styles import w, StylesManager from calibre.ebooks.docx.writer.styles import w, StylesManager
from calibre.ebooks.docx.writer.images import ImagesManager 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.stylizer import Stylizer as Sz, Style as St
from calibre.ebooks.oeb.base import XPath, barename from calibre.ebooks.oeb.base import XPath, barename
from calibre.ebooks.pdf.render.common import PAPER_SIZES from calibre.ebooks.pdf.render.common import PAPER_SIZES
@ -170,6 +171,7 @@ class Convert(object):
self.styles_manager = StylesManager() self.styles_manager = StylesManager()
self.images_manager = ImagesManager(self.oeb, self.docx.document_relationships) self.images_manager = ImagesManager(self.oeb, self.docx.document_relationships)
self.fonts_manager = FontsManager(self.oeb)
for item in self.oeb.spine: for item in self.oeb.spine:
self.process_item(item) self.process_item(item)
@ -296,3 +298,4 @@ class Convert(object):
self.docx.images = {} self.docx.images = {}
self.styles_manager.serialize(self.docx.styles) self.styles_manager.serialize(self.docx.styles)
self.images_manager.serialize(self.docx.images) self.images_manager.serialize(self.docx.images)
self.fonts_manager.serialize(self.styles_manager.text_styles, self.docx.font_table, self.docx.embedded_fonts)