Skip to content

Commit 83cf975

Browse files
author
Steve Canny
committed
reorg: extract docx.oxml.text.font
1 parent f54ccd7 commit 83cf975

File tree

3 files changed

+293
-284
lines changed

3 files changed

+293
-284
lines changed

docx/oxml/__init__.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -144,25 +144,11 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
144144
register_element_cls('w:tr', CT_Row)
145145
register_element_cls('w:vMerge', CT_VMerge)
146146

147-
from .text.paragraph import CT_Ind, CT_Jc, CT_P, CT_PPr, CT_Spacing
148-
register_element_cls('w:ind', CT_Ind)
149-
register_element_cls('w:jc', CT_Jc)
150-
register_element_cls('w:keepLines', CT_OnOff)
151-
register_element_cls('w:keepNext', CT_OnOff)
152-
register_element_cls('w:p', CT_P)
153-
register_element_cls('w:pageBreakBefore', CT_OnOff)
154-
register_element_cls('w:pPr', CT_PPr)
155-
register_element_cls('w:pStyle', CT_String)
156-
register_element_cls('w:spacing', CT_Spacing)
157-
register_element_cls('w:widowControl', CT_OnOff)
158-
159-
from .text.run import (
160-
CT_Br, CT_Fonts, CT_HpsMeasure, CT_R, CT_RPr, CT_Text, CT_Underline,
161-
CT_VerticalAlignRun
147+
from .text.font import (
148+
CT_Fonts, CT_HpsMeasure, CT_RPr, CT_Underline, CT_VerticalAlignRun
162149
)
163150
register_element_cls('w:b', CT_OnOff)
164151
register_element_cls('w:bCs', CT_OnOff)
165-
register_element_cls('w:br', CT_Br)
166152
register_element_cls('w:caps', CT_OnOff)
167153
register_element_cls('w:cs', CT_OnOff)
168154
register_element_cls('w:dstrike', CT_OnOff)
@@ -173,7 +159,6 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
173159
register_element_cls('w:noProof', CT_OnOff)
174160
register_element_cls('w:oMath', CT_OnOff)
175161
register_element_cls('w:outline', CT_OnOff)
176-
register_element_cls('w:r', CT_R)
177162
register_element_cls('w:rFonts', CT_Fonts)
178163
register_element_cls('w:rPr', CT_RPr)
179164
register_element_cls('w:rStyle', CT_String)
@@ -184,8 +169,24 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
184169
register_element_cls('w:specVanish', CT_OnOff)
185170
register_element_cls('w:strike', CT_OnOff)
186171
register_element_cls('w:sz', CT_HpsMeasure)
187-
register_element_cls('w:t', CT_Text)
188172
register_element_cls('w:u', CT_Underline)
189173
register_element_cls('w:vanish', CT_OnOff)
190174
register_element_cls('w:vertAlign', CT_VerticalAlignRun)
191175
register_element_cls('w:webHidden', CT_OnOff)
176+
177+
from .text.paragraph import CT_Ind, CT_Jc, CT_P, CT_PPr, CT_Spacing
178+
register_element_cls('w:ind', CT_Ind)
179+
register_element_cls('w:jc', CT_Jc)
180+
register_element_cls('w:keepLines', CT_OnOff)
181+
register_element_cls('w:keepNext', CT_OnOff)
182+
register_element_cls('w:p', CT_P)
183+
register_element_cls('w:pageBreakBefore', CT_OnOff)
184+
register_element_cls('w:pPr', CT_PPr)
185+
register_element_cls('w:pStyle', CT_String)
186+
register_element_cls('w:spacing', CT_Spacing)
187+
register_element_cls('w:widowControl', CT_OnOff)
188+
189+
from .text.run import CT_Br, CT_R, CT_Text
190+
register_element_cls('w:br', CT_Br)
191+
register_element_cls('w:r', CT_R)
192+
register_element_cls('w:t', CT_Text)

docx/oxml/text/font.py

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Custom element classes related to run properties (font).
5+
"""
6+
7+
from ...enum.text import WD_UNDERLINE
8+
from ..ns import qn
9+
from ..simpletypes import ST_HpsMeasure, ST_String, ST_VerticalAlignRun
10+
from ..xmlchemy import (
11+
BaseOxmlElement, OptionalAttribute, RequiredAttribute, ZeroOrOne
12+
)
13+
14+
15+
class CT_Fonts(BaseOxmlElement):
16+
"""
17+
``<w:rFonts>`` element, specifying typeface name for the various language
18+
types.
19+
"""
20+
ascii = OptionalAttribute('w:ascii', ST_String)
21+
hAnsi = OptionalAttribute('w:hAnsi', ST_String)
22+
23+
24+
class CT_HpsMeasure(BaseOxmlElement):
25+
"""
26+
Used for ``<w:sz>`` element and others, specifying font size in
27+
half-points.
28+
"""
29+
val = RequiredAttribute('w:val', ST_HpsMeasure)
30+
31+
32+
class CT_RPr(BaseOxmlElement):
33+
"""
34+
``<w:rPr>`` element, containing the properties for a run.
35+
"""
36+
_tag_seq = (
37+
'w:rStyle', 'w:rFonts', 'w:b', 'w:bCs', 'w:i', 'w:iCs', 'w:caps',
38+
'w:smallCaps', 'w:strike', 'w:dstrike', 'w:outline', 'w:shadow',
39+
'w:emboss', 'w:imprint', 'w:noProof', 'w:snapToGrid', 'w:vanish',
40+
'w:webHidden', 'w:color', 'w:spacing', 'w:w', 'w:kern', 'w:position',
41+
'w:sz', 'w:szCs', 'w:highlight', 'w:u', 'w:effect', 'w:bdr', 'w:shd',
42+
'w:fitText', 'w:vertAlign', 'w:rtl', 'w:cs', 'w:em', 'w:lang',
43+
'w:eastAsianLayout', 'w:specVanish', 'w:oMath'
44+
)
45+
rStyle = ZeroOrOne('w:rStyle', successors=_tag_seq[1:])
46+
rFonts = ZeroOrOne('w:rFonts', successors=_tag_seq[2:])
47+
b = ZeroOrOne('w:b', successors=_tag_seq[3:])
48+
bCs = ZeroOrOne('w:bCs', successors=_tag_seq[4:])
49+
i = ZeroOrOne('w:i', successors=_tag_seq[5:])
50+
iCs = ZeroOrOne('w:iCs', successors=_tag_seq[6:])
51+
caps = ZeroOrOne('w:caps', successors=_tag_seq[7:])
52+
smallCaps = ZeroOrOne('w:smallCaps', successors=_tag_seq[8:])
53+
strike = ZeroOrOne('w:strike', successors=_tag_seq[9:])
54+
dstrike = ZeroOrOne('w:dstrike', successors=_tag_seq[10:])
55+
outline = ZeroOrOne('w:outline', successors=_tag_seq[11:])
56+
shadow = ZeroOrOne('w:shadow', successors=_tag_seq[12:])
57+
emboss = ZeroOrOne('w:emboss', successors=_tag_seq[13:])
58+
imprint = ZeroOrOne('w:imprint', successors=_tag_seq[14:])
59+
noProof = ZeroOrOne('w:noProof', successors=_tag_seq[15:])
60+
snapToGrid = ZeroOrOne('w:snapToGrid', successors=_tag_seq[16:])
61+
vanish = ZeroOrOne('w:vanish', successors=_tag_seq[17:])
62+
webHidden = ZeroOrOne('w:webHidden', successors=_tag_seq[18:])
63+
sz = ZeroOrOne('w:sz', successors=_tag_seq[24:])
64+
u = ZeroOrOne('w:u', successors=_tag_seq[27:])
65+
vertAlign = ZeroOrOne('w:vertAlign', successors=_tag_seq[32:])
66+
rtl = ZeroOrOne('w:rtl', successors=_tag_seq[33:])
67+
cs = ZeroOrOne('w:cs', successors=_tag_seq[34:])
68+
specVanish = ZeroOrOne('w:specVanish', successors=_tag_seq[38:])
69+
oMath = ZeroOrOne('w:oMath', successors=_tag_seq[39:])
70+
del _tag_seq
71+
72+
@property
73+
def rFonts_ascii(self):
74+
"""
75+
The value of `w:rFonts/@w:ascii` or |None| if not present. Represents
76+
the assigned typeface name. The rFonts element also specifies other
77+
special-case typeface names; this method handles the case where just
78+
the common name is required.
79+
"""
80+
rFonts = self.rFonts
81+
if rFonts is None:
82+
return None
83+
return rFonts.ascii
84+
85+
@rFonts_ascii.setter
86+
def rFonts_ascii(self, value):
87+
if value is None:
88+
self._remove_rFonts()
89+
return
90+
rFonts = self.get_or_add_rFonts()
91+
rFonts.ascii = value
92+
93+
@property
94+
def rFonts_hAnsi(self):
95+
"""
96+
The value of `w:rFonts/@w:hAnsi` or |None| if not present.
97+
"""
98+
rFonts = self.rFonts
99+
if rFonts is None:
100+
return None
101+
return rFonts.hAnsi
102+
103+
@rFonts_hAnsi.setter
104+
def rFonts_hAnsi(self, value):
105+
if value is None and self.rFonts is None:
106+
return
107+
rFonts = self.get_or_add_rFonts()
108+
rFonts.hAnsi = value
109+
110+
@property
111+
def style(self):
112+
"""
113+
String contained in <w:rStyle> child, or None if that element is not
114+
present.
115+
"""
116+
rStyle = self.rStyle
117+
if rStyle is None:
118+
return None
119+
return rStyle.val
120+
121+
@style.setter
122+
def style(self, style):
123+
"""
124+
Set val attribute of <w:rStyle> child element to *style*, adding a
125+
new element if necessary. If *style* is |None|, remove the <w:rStyle>
126+
element if present.
127+
"""
128+
if style is None:
129+
self._remove_rStyle()
130+
elif self.rStyle is None:
131+
self._add_rStyle(val=style)
132+
else:
133+
self.rStyle.val = style
134+
135+
@property
136+
def subscript(self):
137+
"""
138+
|True| if `w:vertAlign/@w:val` is 'subscript'. |False| if
139+
`w:vertAlign/@w:val` contains any other value. |None| if
140+
`w:vertAlign` is not present.
141+
"""
142+
vertAlign = self.vertAlign
143+
if vertAlign is None:
144+
return None
145+
if vertAlign.val == ST_VerticalAlignRun.SUBSCRIPT:
146+
return True
147+
return False
148+
149+
@subscript.setter
150+
def subscript(self, value):
151+
if value is None:
152+
self._remove_vertAlign()
153+
elif bool(value) is True:
154+
self.get_or_add_vertAlign().val = ST_VerticalAlignRun.SUBSCRIPT
155+
elif self.vertAlign is None:
156+
return
157+
elif self.vertAlign.val == ST_VerticalAlignRun.SUBSCRIPT:
158+
self._remove_vertAlign()
159+
160+
@property
161+
def superscript(self):
162+
"""
163+
|True| if `w:vertAlign/@w:val` is 'superscript'. |False| if
164+
`w:vertAlign/@w:val` contains any other value. |None| if
165+
`w:vertAlign` is not present.
166+
"""
167+
vertAlign = self.vertAlign
168+
if vertAlign is None:
169+
return None
170+
if vertAlign.val == ST_VerticalAlignRun.SUPERSCRIPT:
171+
return True
172+
return False
173+
174+
@superscript.setter
175+
def superscript(self, value):
176+
if value is None:
177+
self._remove_vertAlign()
178+
elif bool(value) is True:
179+
self.get_or_add_vertAlign().val = ST_VerticalAlignRun.SUPERSCRIPT
180+
elif self.vertAlign is None:
181+
return
182+
elif self.vertAlign.val == ST_VerticalAlignRun.SUPERSCRIPT:
183+
self._remove_vertAlign()
184+
185+
@property
186+
def sz_val(self):
187+
"""
188+
The value of `w:sz/@w:val` or |None| if not present.
189+
"""
190+
sz = self.sz
191+
if sz is None:
192+
return None
193+
return sz.val
194+
195+
@sz_val.setter
196+
def sz_val(self, value):
197+
if value is None:
198+
self._remove_sz()
199+
return
200+
sz = self.get_or_add_sz()
201+
sz.val = value
202+
203+
@property
204+
def u_val(self):
205+
"""
206+
Value of `w:u/@val`, or None if not present.
207+
"""
208+
u = self.u
209+
if u is None:
210+
return None
211+
return u.val
212+
213+
@u_val.setter
214+
def u_val(self, value):
215+
self._remove_u()
216+
if value is not None:
217+
self._add_u().val = value
218+
219+
def _get_bool_val(self, name):
220+
"""
221+
Return the value of the boolean child element having *name*, e.g.
222+
'b', 'i', and 'smallCaps'.
223+
"""
224+
element = getattr(self, name)
225+
if element is None:
226+
return None
227+
return element.val
228+
229+
def _set_bool_val(self, name, value):
230+
if value is None:
231+
getattr(self, '_remove_%s' % name)()
232+
return
233+
element = getattr(self, 'get_or_add_%s' % name)()
234+
element.val = value
235+
236+
237+
class CT_Underline(BaseOxmlElement):
238+
"""
239+
``<w:u>`` element, specifying the underlining style for a run.
240+
"""
241+
@property
242+
def val(self):
243+
"""
244+
The underline type corresponding to the ``w:val`` attribute value.
245+
"""
246+
val = self.get(qn('w:val'))
247+
underline = WD_UNDERLINE.from_xml(val)
248+
if underline == WD_UNDERLINE.SINGLE:
249+
return True
250+
if underline == WD_UNDERLINE.NONE:
251+
return False
252+
return underline
253+
254+
@val.setter
255+
def val(self, value):
256+
# works fine without these two mappings, but only because True == 1
257+
# and False == 0, which happen to match the mapping for WD_UNDERLINE
258+
# .SINGLE and .NONE respectively.
259+
if value is True:
260+
value = WD_UNDERLINE.SINGLE
261+
elif value is False:
262+
value = WD_UNDERLINE.NONE
263+
264+
val = WD_UNDERLINE.to_xml(value)
265+
self.set(qn('w:val'), val)
266+
267+
268+
class CT_VerticalAlignRun(BaseOxmlElement):
269+
"""
270+
``<w:vertAlign>`` element, specifying subscript or superscript.
271+
"""
272+
val = RequiredAttribute('w:val', ST_VerticalAlignRun)

0 commit comments

Comments
 (0)