DOCX: Add support for theme fonts

This commit is contained in:
Kovid Goyal 2013-06-13 10:12:57 +05:30
parent 19cb39873c
commit bd9bb1bad8
5 changed files with 55 additions and 7 deletions

View File

@ -117,8 +117,12 @@ def read_vert_align(parent, dest):
def read_font_family(parent, dest):
ans = inherit
for col in XPath('./w:rFonts[@w:ascii]')(parent):
val = get(col, 'w:ascii')
for col in XPath('./w:rFonts')(parent):
val = get(col, 'w:asciiTheme')
if val:
val = '|%s|' % val
else:
val = get(col, 'w:ascii')
if val:
ans = val
setattr(dest, 'font_family', ans)

View File

@ -22,6 +22,7 @@ IMAGES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships
LINKS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink'
FOOTNOTES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes'
ENDNOTES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes'
THEMES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
namespaces = {
'mo': 'http://schemas.microsoft.com/office/mac/office/2008/main',

View File

@ -142,8 +142,8 @@ class Styles(object):
def get(self, key, default=None):
return self.id_map.get(key, default)
def __call__(self, root, fonts):
self.fonts = fonts
def __call__(self, root, fonts, theme):
self.fonts, self.theme = fonts, theme
for s in XPath('//w:style')(root):
s = Style(s)
if s.style_id:
@ -304,7 +304,8 @@ class Styles(object):
setattr(ans, attr, self.run_val(parent_styles, direct_formatting, attr))
if ans.font_family is not inherit:
ans.font_family = self.fonts.family_for(ans.font_family, ans.b, ans.i)
ff = self.theme.resolve_font_family(ans.font_family)
ans.font_family = self.fonts.family_for(ff, ans.b, ans.i)
return ans

View File

@ -0,0 +1,31 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
from calibre.ebooks.docx.names import XPath
class Theme(object):
def __init__(self):
self.major_latin_font = 'Cambria'
self.minor_latin_font = 'Calibri'
def __call__(self, root):
for fs in XPath('//a:fontScheme')(root):
for mj in XPath('./a:majorFont')(fs):
for l in XPath('./a:latin[@typeface]')(mj):
self.major_latin_font = l.get('typeface')
for mj in XPath('./a:minorFont')(fs):
for l in XPath('./a:latin[@typeface]')(mj):
self.minor_latin_font = l.get('typeface')
def resolve_font_family(self, ff):
if ff.startswith('|'):
ff = ff[1:-1]
ff = self.major_latin_font if ff.startswith('major') else self.minor_latin_font
return ff

View File

@ -16,7 +16,7 @@ from lxml.html.builder import (
from calibre.ebooks.docx.container import DOCX, fromstring
from calibre.ebooks.docx.names import (
XPath, is_tag, XML, STYLES, NUMBERING, FONTS, get, generate_anchor,
descendants, FOOTNOTES, ENDNOTES, children)
descendants, FOOTNOTES, ENDNOTES, children, THEMES)
from calibre.ebooks.docx.styles import Styles, inherit, PageProperties
from calibre.ebooks.docx.numbering import Numbering
from calibre.ebooks.docx.fonts import Fonts
@ -24,6 +24,7 @@ from calibre.ebooks.docx.images import Images
from calibre.ebooks.docx.tables import Tables
from calibre.ebooks.docx.footnotes import Footnotes
from calibre.ebooks.docx.cleanup import cleanup_markup
from calibre.ebooks.docx.theme import Theme
from calibre.ebooks.metadata.opf2 import OPFCreator
from calibre.ebooks.metadata.toc import TOC
from calibre.ebooks.oeb.polish.toc import elem_to_toc_text
@ -49,6 +50,7 @@ class Convert(object):
self.dest_dir = dest_dir or os.getcwdu()
self.mi = self.docx.metadata
self.body = BODY()
self.theme = Theme()
self.tables = Tables()
self.styles = Styles(self.tables)
self.images = Images()
@ -203,6 +205,7 @@ class Convert(object):
nname = get_name(NUMBERING, 'numbering.xml')
sname = get_name(STYLES, 'styles.xml')
fname = get_name(FONTS, 'fontTable.xml')
tname = get_name(THEMES, 'theme1.xml')
foname = get_name(FOOTNOTES, 'footnotes.xml')
enname = get_name(ENDNOTES, 'endnotes.xml')
numbering = self.numbering = Numbering()
@ -231,13 +234,21 @@ class Convert(object):
else:
fonts(fromstring(raw), embed_relationships, self.docx, self.dest_dir)
if tname is not None:
try:
raw = self.docx.read(tname)
except KeyError:
self.log.warn('Styles %s do not exist' % sname)
else:
self.theme(fromstring(raw))
if sname is not None:
try:
raw = self.docx.read(sname)
except KeyError:
self.log.warn('Styles %s do not exist' % sname)
else:
self.styles(fromstring(raw), fonts)
self.styles(fromstring(raw), fonts, self.theme)
if nname is not None:
try: