diff --git a/src/calibre/ebooks/conversion/plugins/pdf_output.py b/src/calibre/ebooks/conversion/plugins/pdf_output.py index 4db9c07c48..be48afc8dd 100644 --- a/src/calibre/ebooks/conversion/plugins/pdf_output.py +++ b/src/calibre/ebooks/conversion/plugins/pdf_output.py @@ -285,5 +285,49 @@ class PDFOutput(OutputFormatPlugin): if close: out_stream.close() + def specialize_css_for_output(self, log, opts, item, stylizer): + ''' Qt WebKit (4.8.x) cannot handle font-variant: small-caps. It tries to fake the small caps, + which is ok, but the faking continues on to subsequent text that should not be in small-caps. + So we workaround the problem by faking small caps ourselves. A minimal example that Qt chokes on: +
+Some Small-caps Text
+Some non small-caps text with enough text for at least one + full line and justification enabled. Both of these are needed for the example to work.
+ ''' + from calibre.ebooks.oeb.base import XHTML + import itertools, string + if not hasattr(item.data, 'xpath'): + return + ws = unicode(string.whitespace) + def fake_small_caps(elem): + spans = [] + for lowercase, textiter in itertools.groupby(elem.text, lambda x:x not in ws and icu_lower(x)==x): + text = ''.join(textiter) + if lowercase: + text = icu_upper(text) + span = elem.makeelement(XHTML('span')) + span.text = text + style = stylizer.style(span) + if lowercase: + style.set('font-size', '0.65em') + spans.append(span) + elem.text = None + elem[0:] = spans + + def process_elem(elem, parent_fv=None): + children = tuple(elem) + style = stylizer.style(elem) + fv = style.drop('font-variant') + if not fv or fv.lower() == 'inherit': + fv = parent_fv + if fv and fv.lower() in {'smallcaps', 'small-caps'}: + if elem.text: + fake_small_caps(elem) + for child in children: + if hasattr(getattr(child, 'tag', None), 'lower'): + process_elem(child, parent_fv=fv) + + for body in item.data.xpath('//*[local-name()="body"]'): + process_elem(body) diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index fbb8fb1f49..a19a36de8c 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -569,8 +569,8 @@ class Style(object): def set(self, prop, val): self._style[prop] = val - def drop(self, prop): - self._style.pop(prop, None) + def drop(self, prop, default=None): + return self._style.pop(prop, default) def _update_cssdict(self, cssdict): self._style.update(cssdict)