mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
DOCX Output: Fix handling of border properties for character styles
This commit is contained in:
parent
142c1e84cf
commit
0a3b9f678f
@ -21,6 +21,7 @@ css_parser = CSS21Parser()
|
|||||||
|
|
||||||
border_edges = ('left', 'top', 'right', 'bottom')
|
border_edges = ('left', 'top', 'right', 'bottom')
|
||||||
border_props = ('padding_%s', 'border_%s_width', 'border_%s_style', 'border_%s_color')
|
border_props = ('padding_%s', 'border_%s_width', 'border_%s_style', 'border_%s_color')
|
||||||
|
ignore = object()
|
||||||
|
|
||||||
def parse_css_font_family(raw):
|
def parse_css_font_family(raw):
|
||||||
decl, errs = css_parser.parse_style_attr('font-family:' + raw)
|
decl, errs = css_parser.parse_style_attr('font-family:' + raw)
|
||||||
@ -73,24 +74,6 @@ class DOCXStyle(object):
|
|||||||
return etree.tostring(self.serialize(etree.Element(self.__class__.__name__, nsmap={'w':namespaces['w']})), pretty_print=True)
|
return etree.tostring(self.serialize(etree.Element(self.__class__.__name__, nsmap={'w':namespaces['w']})), pretty_print=True)
|
||||||
__str__ = __repr__
|
__str__ = __repr__
|
||||||
|
|
||||||
def serialize_borders(self, bdr, normal_style):
|
|
||||||
for edge in border_edges:
|
|
||||||
e = bdr.makeelement(w(edge))
|
|
||||||
padding = getattr(self, 'padding_' + edge)
|
|
||||||
if (self is normal_style and padding > 0) or (padding != getattr(normal_style, 'padding_' + edge)):
|
|
||||||
e.set(w('space'), str(padding))
|
|
||||||
width = getattr(self, 'border_%s_width' % edge)
|
|
||||||
bstyle = getattr(self, 'border_%s_style' % edge)
|
|
||||||
if (self is normal_style and width > 0 and bstyle != 'none'
|
|
||||||
) or width != getattr(normal_style, 'border_%s_width' % edge
|
|
||||||
) or bstyle != getattr(normal_style, 'border_%s_style' % edge):
|
|
||||||
e.set(w('val'), bstyle)
|
|
||||||
e.set(w('sz'), str(width))
|
|
||||||
e.set(w('color'), getattr(self, 'border_%s_color' % edge))
|
|
||||||
if e.attrib:
|
|
||||||
bdr.append(e)
|
|
||||||
return bdr
|
|
||||||
|
|
||||||
def serialize(self, styles, normal_style):
|
def serialize(self, styles, normal_style):
|
||||||
style = makeelement(styles, 'style', styleId=self.id, type=self.TYPE)
|
style = makeelement(styles, 'style', styleId=self.id, type=self.TYPE)
|
||||||
style.append(makeelement(style, 'name', val=self.name))
|
style.append(makeelement(style, 'name', val=self.name))
|
||||||
@ -119,8 +102,8 @@ class TextStyle(DOCXStyle):
|
|||||||
|
|
||||||
ALL_PROPS = ('font_family', 'font_size', 'bold', 'italic', 'color',
|
ALL_PROPS = ('font_family', 'font_size', 'bold', 'italic', 'color',
|
||||||
'background_color', 'underline', 'strike', 'dstrike', 'caps',
|
'background_color', 'underline', 'strike', 'dstrike', 'caps',
|
||||||
'shadow', 'small_caps', 'spacing', 'vertical_align') + tuple(
|
'shadow', 'small_caps', 'spacing', 'vertical_align', 'padding',
|
||||||
x%edge for edge in border_edges for x in border_props)
|
'border_style', 'border_width', 'border_color')
|
||||||
TYPE = 'character'
|
TYPE = 'character'
|
||||||
|
|
||||||
def __init__(self, css, is_parent_style=False):
|
def __init__(self, css, is_parent_style=False):
|
||||||
@ -148,22 +131,45 @@ class TextStyle(DOCXStyle):
|
|||||||
except (ValueError, TypeError, AttributeError):
|
except (ValueError, TypeError, AttributeError):
|
||||||
self.spacing = None
|
self.spacing = None
|
||||||
self.vertical_align = css['vertical-align']
|
self.vertical_align = css['vertical-align']
|
||||||
for edge in border_edges:
|
self.padding = self.border_color = self.border_width = self.border_style = None
|
||||||
if is_parent_style:
|
if not is_parent_style:
|
||||||
setattr(self, 'padding_' + edge, 0)
|
# DOCX does not support individual borders/padding for inline content
|
||||||
setattr(self, 'border_%s_width' % edge, 0)
|
for edge in border_edges:
|
||||||
setattr(self, 'border_%s_color' % edge, None)
|
|
||||||
setattr(self, 'border_%s_style' % edge, 'none')
|
|
||||||
else:
|
|
||||||
# In DOCX padding can only be a positive integer
|
# In DOCX padding can only be a positive integer
|
||||||
setattr(self, 'padding_' + edge, max(0, int(css['padding-' + edge])))
|
padding = max(0, int(css['padding-' + edge]))
|
||||||
val = min(96, max(2, int({'thin':0.2, 'medium':1, 'thick':2}.get(css['border-%s-width' % edge], 0) * 8)))
|
if self.padding is None:
|
||||||
setattr(self, 'border_%s_width' % edge, val)
|
self.padding = padding
|
||||||
setattr(self, 'border_%s_color' % edge, convert_color(css['border-%s-color' % edge]))
|
elif self.padding != padding:
|
||||||
setattr(self, 'border_%s_style' % edge, LINE_STYLES.get(css['border-%s-style' % edge].lower(), 'none'))
|
self.padding = ignore
|
||||||
|
width = min(96, max(2, int({'thin':0.2, 'medium':1, 'thick':2}.get(css['border-%s-width' % edge], 0) * 8)))
|
||||||
|
if self.border_width is None:
|
||||||
|
self.border_width = width
|
||||||
|
elif self.border_width != width:
|
||||||
|
self.border_width = ignore
|
||||||
|
color = convert_color(css['border-%s-color' % edge])
|
||||||
|
if self.border_color is None:
|
||||||
|
self.border_color = color
|
||||||
|
elif self.border_color != color:
|
||||||
|
self.border_color = ignore
|
||||||
|
style = LINE_STYLES.get(css['border-%s-style' % edge].lower(), 'none')
|
||||||
|
if self.border_style is None:
|
||||||
|
self.border_style = style
|
||||||
|
elif self.border_style != style:
|
||||||
|
self.border_style = ignore
|
||||||
|
|
||||||
DOCXStyle.__init__(self)
|
DOCXStyle.__init__(self)
|
||||||
|
|
||||||
|
def serialize_borders(self, bdr, normal_style):
|
||||||
|
if (self.padding not in (None, ignore, 0) and self is normal_style) or self.padding != normal_style.padding:
|
||||||
|
bdr.set(w('space'), str(0 if self.padding in (None, ignore) else self.padding))
|
||||||
|
if (self.border_width not in (None, ignore, 0) and self is normal_style) or self.border_width != normal_style.border_width:
|
||||||
|
bdr.set(w('sz'), str(0 if self.border_width in (None, ignore) else self.border_width))
|
||||||
|
if (self.border_style not in (None, ignore, 'none') and self is normal_style) or self.border_style != normal_style.border_style:
|
||||||
|
bdr.set(w('val'), 'none' if self.border_style in (None, ignore) else self.border_style)
|
||||||
|
if (self.border_color not in (None, ignore, 'auto') and self is normal_style) or self.border_color != normal_style.border_color:
|
||||||
|
bdr.set(w('color'), 'auto' if self.border_color in (None, ignore) else self.border_color)
|
||||||
|
return bdr
|
||||||
|
|
||||||
def serialize(self, styles, normal_style):
|
def serialize(self, styles, normal_style):
|
||||||
style_root = DOCXStyle.serialize(self, styles, normal_style)
|
style_root = DOCXStyle.serialize(self, styles, normal_style)
|
||||||
style = makeelement(style_root, 'rPr')
|
style = makeelement(style_root, 'rPr')
|
||||||
@ -210,7 +216,7 @@ class TextStyle(DOCXStyle):
|
|||||||
style.append(makeelement(style, 'vertAlign', val=val))
|
style.append(makeelement(style, 'vertAlign', val=val))
|
||||||
|
|
||||||
bdr = self.serialize_borders(makeelement(style, 'bdr'), normal_style)
|
bdr = self.serialize_borders(makeelement(style, 'bdr'), normal_style)
|
||||||
if len(bdr):
|
if bdr.attrib:
|
||||||
style.append(bdr)
|
style.append(bdr)
|
||||||
|
|
||||||
if len(style) > 0:
|
if len(style) > 0:
|
||||||
@ -250,6 +256,24 @@ class BlockStyle(DOCXStyle):
|
|||||||
|
|
||||||
DOCXStyle.__init__(self)
|
DOCXStyle.__init__(self)
|
||||||
|
|
||||||
|
def serialize_borders(self, bdr, normal_style):
|
||||||
|
for edge in border_edges:
|
||||||
|
e = bdr.makeelement(w(edge))
|
||||||
|
padding = getattr(self, 'padding_' + edge)
|
||||||
|
if (self is normal_style and padding > 0) or (padding != getattr(normal_style, 'padding_' + edge)):
|
||||||
|
e.set(w('space'), str(padding))
|
||||||
|
width = getattr(self, 'border_%s_width' % edge)
|
||||||
|
bstyle = getattr(self, 'border_%s_style' % edge)
|
||||||
|
if (self is normal_style and width > 0 and bstyle != 'none'
|
||||||
|
) or width != getattr(normal_style, 'border_%s_width' % edge
|
||||||
|
) or bstyle != getattr(normal_style, 'border_%s_style' % edge):
|
||||||
|
e.set(w('val'), bstyle)
|
||||||
|
e.set(w('sz'), str(width))
|
||||||
|
e.set(w('color'), getattr(self, 'border_%s_color' % edge))
|
||||||
|
if e.attrib:
|
||||||
|
bdr.append(e)
|
||||||
|
return bdr
|
||||||
|
|
||||||
def serialize(self, styles, normal_style):
|
def serialize(self, styles, normal_style):
|
||||||
style_root = DOCXStyle.serialize(self, styles, normal_style)
|
style_root = DOCXStyle.serialize(self, styles, normal_style)
|
||||||
style = makeelement(style_root, 'pPr')
|
style = makeelement(style_root, 'pPr')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user