ps-python-pptx 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pptx/__init__.py +84 -0
- pptx/action.py +270 -0
- pptx/api.py +49 -0
- pptx/chart/__init__.py +0 -0
- pptx/chart/axis.py +523 -0
- pptx/chart/category.py +200 -0
- pptx/chart/chart.py +280 -0
- pptx/chart/data.py +864 -0
- pptx/chart/datalabel.py +288 -0
- pptx/chart/legend.py +79 -0
- pptx/chart/marker.py +70 -0
- pptx/chart/plot.py +412 -0
- pptx/chart/point.py +101 -0
- pptx/chart/series.py +258 -0
- pptx/chart/xlsx.py +272 -0
- pptx/chart/xmlwriter.py +1840 -0
- pptx/dml/__init__.py +0 -0
- pptx/dml/chtfmt.py +40 -0
- pptx/dml/color.py +301 -0
- pptx/dml/effect.py +41 -0
- pptx/dml/fill.py +468 -0
- pptx/dml/line.py +100 -0
- pptx/enum/__init__.py +0 -0
- pptx/enum/action.py +71 -0
- pptx/enum/base.py +175 -0
- pptx/enum/chart.py +492 -0
- pptx/enum/dml.py +405 -0
- pptx/enum/lang.py +685 -0
- pptx/enum/shapes.py +1029 -0
- pptx/enum/text.py +371 -0
- pptx/exc.py +23 -0
- pptx/media.py +197 -0
- pptx/opc/__init__.py +0 -0
- pptx/opc/constants.py +331 -0
- pptx/opc/oxml.py +188 -0
- pptx/opc/package.py +762 -0
- pptx/opc/packuri.py +109 -0
- pptx/opc/serialized.py +296 -0
- pptx/opc/shared.py +20 -0
- pptx/opc/spec.py +44 -0
- pptx/oxml/__init__.py +492 -0
- pptx/oxml/action.py +53 -0
- pptx/oxml/chart/__init__.py +0 -0
- pptx/oxml/chart/axis.py +297 -0
- pptx/oxml/chart/chart.py +282 -0
- pptx/oxml/chart/datalabel.py +252 -0
- pptx/oxml/chart/legend.py +72 -0
- pptx/oxml/chart/marker.py +61 -0
- pptx/oxml/chart/plot.py +345 -0
- pptx/oxml/chart/series.py +254 -0
- pptx/oxml/chart/shared.py +219 -0
- pptx/oxml/coreprops.py +288 -0
- pptx/oxml/dml/__init__.py +0 -0
- pptx/oxml/dml/color.py +111 -0
- pptx/oxml/dml/fill.py +197 -0
- pptx/oxml/dml/line.py +12 -0
- pptx/oxml/ns.py +129 -0
- pptx/oxml/presentation.py +130 -0
- pptx/oxml/shapes/__init__.py +19 -0
- pptx/oxml/shapes/autoshape.py +455 -0
- pptx/oxml/shapes/connector.py +107 -0
- pptx/oxml/shapes/graphfrm.py +342 -0
- pptx/oxml/shapes/groupshape.py +280 -0
- pptx/oxml/shapes/picture.py +270 -0
- pptx/oxml/shapes/shared.py +523 -0
- pptx/oxml/simpletypes.py +740 -0
- pptx/oxml/slide.py +347 -0
- pptx/oxml/table.py +588 -0
- pptx/oxml/text.py +748 -0
- pptx/oxml/theme.py +29 -0
- pptx/oxml/xmlchemy.py +717 -0
- pptx/package.py +222 -0
- pptx/parts/__init__.py +0 -0
- pptx/parts/chart.py +95 -0
- pptx/parts/coreprops.py +167 -0
- pptx/parts/embeddedpackage.py +93 -0
- pptx/parts/image.py +275 -0
- pptx/parts/media.py +37 -0
- pptx/parts/presentation.py +126 -0
- pptx/parts/slide.py +297 -0
- pptx/parts/theme.py +13 -0
- pptx/presentation.py +113 -0
- pptx/py.typed +0 -0
- pptx/shapes/__init__.py +26 -0
- pptx/shapes/autoshape.py +355 -0
- pptx/shapes/base.py +293 -0
- pptx/shapes/connector.py +297 -0
- pptx/shapes/freeform.py +337 -0
- pptx/shapes/graphfrm.py +166 -0
- pptx/shapes/group.py +69 -0
- pptx/shapes/picture.py +203 -0
- pptx/shapes/placeholder.py +407 -0
- pptx/shapes/shapetree.py +1190 -0
- pptx/shared.py +82 -0
- pptx/slide.py +577 -0
- pptx/spec.py +632 -0
- pptx/table.py +520 -0
- pptx/templates/default.pptx +0 -0
- pptx/templates/docx-icon.emf +0 -0
- pptx/templates/generic-icon.emf +0 -0
- pptx/templates/notes.xml +23 -0
- pptx/templates/notesMaster.xml +352 -0
- pptx/templates/pptx-icon.emf +0 -0
- pptx/templates/theme.xml +321 -0
- pptx/templates/xlsx-icon.emf +0 -0
- pptx/text/__init__.py +0 -0
- pptx/text/fonts.py +399 -0
- pptx/text/layout.py +325 -0
- pptx/text/text.py +770 -0
- pptx/theme.py +135 -0
- pptx/types.py +36 -0
- pptx/util.py +284 -0
- ps_python_pptx-1.1.0.dist-info/METADATA +75 -0
- ps_python_pptx-1.1.0.dist-info/RECORD +117 -0
- ps_python_pptx-1.1.0.dist-info/WHEEL +5 -0
- ps_python_pptx-1.1.0.dist-info/licenses/LICENSE +20 -0
- ps_python_pptx-1.1.0.dist-info/top_level.txt +1 -0
pptx/dml/fill.py
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
"""DrawingML objects related to fill."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
from collections.abc import Sequence
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from pptx.dml.color import ColorFormat, RGBColor
|
|
10
|
+
from pptx.enum.dml import MSO_FILL, MSO_THEME_COLOR
|
|
11
|
+
from pptx.oxml.dml.fill import (
|
|
12
|
+
CT_BlipFillProperties,
|
|
13
|
+
CT_GradientFillProperties,
|
|
14
|
+
CT_GroupFillProperties,
|
|
15
|
+
CT_NoFillProperties,
|
|
16
|
+
CT_PatternFillProperties,
|
|
17
|
+
CT_SolidColorFillProperties,
|
|
18
|
+
)
|
|
19
|
+
from pptx.oxml.xmlchemy import BaseOxmlElement, OxmlElement
|
|
20
|
+
from pptx.shared import ElementProxy
|
|
21
|
+
from pptx.util import lazyproperty
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from pptx.enum.dml import MSO_FILL_TYPE
|
|
25
|
+
from pptx.oxml.xmlchemy import BaseOxmlElement
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FillFormat(object):
|
|
29
|
+
"""Provides access to the current fill properties.
|
|
30
|
+
|
|
31
|
+
Also provides methods to change the fill type.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, eg_fill_properties_parent: BaseOxmlElement, fill_obj: _Fill):
|
|
35
|
+
super(FillFormat, self).__init__()
|
|
36
|
+
self._xPr = eg_fill_properties_parent
|
|
37
|
+
self._fill = fill_obj
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def from_fill_parent(cls, eg_fillProperties_parent: BaseOxmlElement) -> FillFormat:
|
|
41
|
+
"""
|
|
42
|
+
Return a |FillFormat| instance initialized to the settings contained
|
|
43
|
+
in *eg_fillProperties_parent*, which must be an element having
|
|
44
|
+
EG_FillProperties in its child element sequence in the XML schema.
|
|
45
|
+
"""
|
|
46
|
+
fill_elm = eg_fillProperties_parent.eg_fillProperties
|
|
47
|
+
fill = _Fill(fill_elm)
|
|
48
|
+
fill_format = cls(eg_fillProperties_parent, fill)
|
|
49
|
+
return fill_format
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def back_color(self):
|
|
53
|
+
"""Return a |ColorFormat| object representing background color.
|
|
54
|
+
|
|
55
|
+
This property is only applicable to pattern fills and lines.
|
|
56
|
+
"""
|
|
57
|
+
return self._fill.back_color
|
|
58
|
+
|
|
59
|
+
def background(self):
|
|
60
|
+
"""
|
|
61
|
+
Sets the fill type to noFill, i.e. transparent.
|
|
62
|
+
"""
|
|
63
|
+
noFill = self._xPr.get_or_change_to_noFill()
|
|
64
|
+
self._fill = _NoFill(noFill)
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def fore_color(self):
|
|
68
|
+
"""
|
|
69
|
+
Return a |ColorFormat| instance representing the foreground color of
|
|
70
|
+
this fill.
|
|
71
|
+
"""
|
|
72
|
+
return self._fill.fore_color
|
|
73
|
+
|
|
74
|
+
def set_gradient(self, stops, *, angle=0.0, radial=False, center=(0.5, 0.5)):
|
|
75
|
+
"""Replace the fill with an explicit linear or circular radial gradient.
|
|
76
|
+
|
|
77
|
+
Stops are (position, color) pairs with ascending positions from 0 to 1.
|
|
78
|
+
Colors are RGBColor or MSO_THEME_COLOR values. At least two are required.
|
|
79
|
+
Angle is in counter-clockwise degrees. For radial gradients, center is
|
|
80
|
+
an (x, y) pair of fractions measured from the upper-left corner.
|
|
81
|
+
Invalid arguments leave the existing fill unchanged.
|
|
82
|
+
"""
|
|
83
|
+
values = list(stops)
|
|
84
|
+
if len(values) < 2:
|
|
85
|
+
raise ValueError("a gradient requires at least two stops")
|
|
86
|
+
if not isinstance(radial, bool):
|
|
87
|
+
raise TypeError("radial must be bool")
|
|
88
|
+
if not math.isfinite(angle):
|
|
89
|
+
raise ValueError("gradient angle must be finite")
|
|
90
|
+
if len(center) != 2 or any(not math.isfinite(v) or not 0 <= v <= 1 for v in center):
|
|
91
|
+
raise ValueError("center must contain two fractions between 0 and 1")
|
|
92
|
+
gradient = OxmlElement("a:gradFill")
|
|
93
|
+
gradient.set("rotWithShape", "1")
|
|
94
|
+
stop_list = OxmlElement("a:gsLst")
|
|
95
|
+
previous = -1.0
|
|
96
|
+
for position, color in values:
|
|
97
|
+
if not math.isfinite(position) or not previous <= position <= 1 or position < 0:
|
|
98
|
+
raise ValueError("gradient positions must be ascending fractions from 0 to 1")
|
|
99
|
+
previous = position
|
|
100
|
+
stop = OxmlElement("a:gs")
|
|
101
|
+
stop.pos = position
|
|
102
|
+
if isinstance(color, RGBColor):
|
|
103
|
+
color_element = OxmlElement("a:srgbClr")
|
|
104
|
+
color_element.set("val", str(color))
|
|
105
|
+
elif isinstance(color, MSO_THEME_COLOR):
|
|
106
|
+
color_element = OxmlElement("a:schemeClr")
|
|
107
|
+
color_element.set("val", MSO_THEME_COLOR.to_xml(color))
|
|
108
|
+
else:
|
|
109
|
+
raise TypeError("gradient colors must be RGBColor or MSO_THEME_COLOR")
|
|
110
|
+
stop.append(color_element)
|
|
111
|
+
stop_list.append(stop)
|
|
112
|
+
gradient.append(stop_list)
|
|
113
|
+
if radial:
|
|
114
|
+
path = OxmlElement("a:path")
|
|
115
|
+
path.set("path", "circle")
|
|
116
|
+
rect = OxmlElement("a:fillToRect")
|
|
117
|
+
x, y = center
|
|
118
|
+
for name, value in zip(("l", "t", "r", "b"), (x, y, 1 - x, 1 - y)):
|
|
119
|
+
rect.set(name, str(round(value * 100000)))
|
|
120
|
+
path.append(rect)
|
|
121
|
+
gradient.append(path)
|
|
122
|
+
else:
|
|
123
|
+
linear = OxmlElement("a:lin")
|
|
124
|
+
linear.set("ang", str(round(((360.0 - angle) % 360.0) * 60000) % 21600000))
|
|
125
|
+
linear.set("scaled", "0")
|
|
126
|
+
gradient.append(linear)
|
|
127
|
+
old = self._xPr.get_or_change_to_gradFill()
|
|
128
|
+
old.getparent().replace(old, gradient)
|
|
129
|
+
self._fill = _GradFill(gradient)
|
|
130
|
+
|
|
131
|
+
def _set_picture(self, relationship_id):
|
|
132
|
+
"""Set a stretched picture fill using a relationship owned by the containing part."""
|
|
133
|
+
fill = self._xPr.get_or_change_to_blipFill()
|
|
134
|
+
fill[:] = []
|
|
135
|
+
blip = OxmlElement("a:blip")
|
|
136
|
+
blip.rEmbed = relationship_id
|
|
137
|
+
fill.append(blip)
|
|
138
|
+
stretch = OxmlElement("a:stretch")
|
|
139
|
+
stretch.append(OxmlElement("a:fillRect"))
|
|
140
|
+
fill.append(stretch)
|
|
141
|
+
self._fill = _BlipFill(fill)
|
|
142
|
+
|
|
143
|
+
def gradient(self):
|
|
144
|
+
"""Sets the fill type to gradient.
|
|
145
|
+
|
|
146
|
+
If the fill is not already a gradient, a default gradient is added.
|
|
147
|
+
The default gradient corresponds to the default in the built-in
|
|
148
|
+
PowerPoint "White" template. This gradient is linear at angle
|
|
149
|
+
90-degrees (upward), with two stops. The first stop is Accent-1 with
|
|
150
|
+
tint 100%, shade 100%, and satMod 130%. The second stop is Accent-1
|
|
151
|
+
with tint 50%, shade 100%, and satMod 350%.
|
|
152
|
+
"""
|
|
153
|
+
gradFill = self._xPr.get_or_change_to_gradFill()
|
|
154
|
+
self._fill = _GradFill(gradFill)
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def gradient_angle(self):
|
|
158
|
+
"""Angle in float degrees of line of a linear gradient.
|
|
159
|
+
|
|
160
|
+
Read/Write. May be |None|, indicating the angle should be inherited
|
|
161
|
+
from the style hierarchy. An angle of 0.0 corresponds to
|
|
162
|
+
a left-to-right gradient. Increasing angles represent
|
|
163
|
+
counter-clockwise rotation of the line, for example 90.0 represents
|
|
164
|
+
a bottom-to-top gradient. Raises |TypeError| when the fill type is
|
|
165
|
+
not MSO_FILL_TYPE.GRADIENT. Raises |ValueError| for a non-linear
|
|
166
|
+
gradient (e.g. a radial gradient).
|
|
167
|
+
"""
|
|
168
|
+
if self.type != MSO_FILL.GRADIENT:
|
|
169
|
+
raise TypeError("Fill is not of type MSO_FILL_TYPE.GRADIENT")
|
|
170
|
+
return self._fill.gradient_angle
|
|
171
|
+
|
|
172
|
+
@gradient_angle.setter
|
|
173
|
+
def gradient_angle(self, value):
|
|
174
|
+
if self.type != MSO_FILL.GRADIENT:
|
|
175
|
+
raise TypeError("Fill is not of type MSO_FILL_TYPE.GRADIENT")
|
|
176
|
+
self._fill.gradient_angle = value
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def gradient_stops(self):
|
|
180
|
+
"""|GradientStops| object providing access to stops of this gradient.
|
|
181
|
+
|
|
182
|
+
Raises |TypeError| when fill is not gradient (call `fill.gradient()`
|
|
183
|
+
first). Each stop represents a color between which the gradient
|
|
184
|
+
smoothly transitions.
|
|
185
|
+
"""
|
|
186
|
+
if self.type != MSO_FILL.GRADIENT:
|
|
187
|
+
raise TypeError("Fill is not of type MSO_FILL_TYPE.GRADIENT")
|
|
188
|
+
return self._fill.gradient_stops
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def pattern(self):
|
|
192
|
+
"""Return member of :ref:`MsoPatternType` indicating fill pattern.
|
|
193
|
+
|
|
194
|
+
Raises |TypeError| when fill is not patterned (call
|
|
195
|
+
`fill.patterned()` first). Returns |None| if no pattern has been set;
|
|
196
|
+
PowerPoint may display the default `PERCENT_5` pattern in this case.
|
|
197
|
+
Assigning |None| will remove any explicit pattern setting, although
|
|
198
|
+
relying on the default behavior is discouraged and may produce
|
|
199
|
+
rendering differences across client applications.
|
|
200
|
+
"""
|
|
201
|
+
return self._fill.pattern
|
|
202
|
+
|
|
203
|
+
@pattern.setter
|
|
204
|
+
def pattern(self, pattern_type):
|
|
205
|
+
self._fill.pattern = pattern_type
|
|
206
|
+
|
|
207
|
+
def patterned(self):
|
|
208
|
+
"""Selects the pattern fill type.
|
|
209
|
+
|
|
210
|
+
Note that calling this method does not by itself set a foreground or
|
|
211
|
+
background color of the pattern. Rather it enables subsequent
|
|
212
|
+
assignments to properties like fore_color to set the pattern and
|
|
213
|
+
colors.
|
|
214
|
+
"""
|
|
215
|
+
pattFill = self._xPr.get_or_change_to_pattFill()
|
|
216
|
+
self._fill = _PattFill(pattFill)
|
|
217
|
+
|
|
218
|
+
def solid(self):
|
|
219
|
+
"""
|
|
220
|
+
Sets the fill type to solid, i.e. a solid color. Note that calling
|
|
221
|
+
this method does not set a color or by itself cause the shape to
|
|
222
|
+
appear with a solid color fill; rather it enables subsequent
|
|
223
|
+
assignments to properties like fore_color to set the color.
|
|
224
|
+
"""
|
|
225
|
+
solidFill = self._xPr.get_or_change_to_solidFill()
|
|
226
|
+
self._fill = _SolidFill(solidFill)
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def type(self) -> MSO_FILL_TYPE:
|
|
230
|
+
"""The type of this fill, e.g. `MSO_FILL_TYPE.SOLID`."""
|
|
231
|
+
return self._fill.type
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class _Fill(object):
|
|
235
|
+
"""
|
|
236
|
+
Object factory for fill object of class matching fill element, such as
|
|
237
|
+
_SolidFill for ``<a:solidFill>``; also serves as the base class for all
|
|
238
|
+
fill classes
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
def __new__(cls, xFill):
|
|
242
|
+
if xFill is None:
|
|
243
|
+
fill_cls = _NoneFill
|
|
244
|
+
elif isinstance(xFill, CT_BlipFillProperties):
|
|
245
|
+
fill_cls = _BlipFill
|
|
246
|
+
elif isinstance(xFill, CT_GradientFillProperties):
|
|
247
|
+
fill_cls = _GradFill
|
|
248
|
+
elif isinstance(xFill, CT_GroupFillProperties):
|
|
249
|
+
fill_cls = _GrpFill
|
|
250
|
+
elif isinstance(xFill, CT_NoFillProperties):
|
|
251
|
+
fill_cls = _NoFill
|
|
252
|
+
elif isinstance(xFill, CT_PatternFillProperties):
|
|
253
|
+
fill_cls = _PattFill
|
|
254
|
+
elif isinstance(xFill, CT_SolidColorFillProperties):
|
|
255
|
+
fill_cls = _SolidFill
|
|
256
|
+
else:
|
|
257
|
+
fill_cls = _Fill
|
|
258
|
+
return super(_Fill, cls).__new__(fill_cls)
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def back_color(self):
|
|
262
|
+
"""Raise TypeError for types that do not override this property."""
|
|
263
|
+
tmpl = "fill type %s has no background color, call .patterned() first"
|
|
264
|
+
raise TypeError(tmpl % self.__class__.__name__)
|
|
265
|
+
|
|
266
|
+
@property
|
|
267
|
+
def fore_color(self):
|
|
268
|
+
"""Raise TypeError for types that do not override this property."""
|
|
269
|
+
tmpl = "fill type %s has no foreground color, call .solid() or .patterned() first"
|
|
270
|
+
raise TypeError(tmpl % self.__class__.__name__)
|
|
271
|
+
|
|
272
|
+
@property
|
|
273
|
+
def pattern(self):
|
|
274
|
+
"""Raise TypeError for fills that do not override this property."""
|
|
275
|
+
tmpl = "fill type %s has no pattern, call .patterned() first"
|
|
276
|
+
raise TypeError(tmpl % self.__class__.__name__)
|
|
277
|
+
|
|
278
|
+
@property
|
|
279
|
+
def type(self) -> MSO_FILL_TYPE: # pragma: no cover
|
|
280
|
+
raise NotImplementedError(
|
|
281
|
+
f".type property must be implemented on {self.__class__.__name__}"
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class _BlipFill(_Fill):
|
|
286
|
+
@property
|
|
287
|
+
def type(self):
|
|
288
|
+
return MSO_FILL.PICTURE
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class _GradFill(_Fill):
|
|
292
|
+
"""Proxies an `a:gradFill` element."""
|
|
293
|
+
|
|
294
|
+
def __init__(self, gradFill):
|
|
295
|
+
self._element = self._gradFill = gradFill
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def gradient_angle(self):
|
|
299
|
+
"""Angle in float degrees of line of a linear gradient.
|
|
300
|
+
|
|
301
|
+
Read/Write. May be |None|, indicating the angle is inherited from the
|
|
302
|
+
style hierarchy. An angle of 0.0 corresponds to a left-to-right
|
|
303
|
+
gradient. Increasing angles represent clockwise rotation of the line,
|
|
304
|
+
for example 90.0 represents a top-to-bottom gradient. Raises
|
|
305
|
+
|TypeError| when the fill type is not MSO_FILL_TYPE.GRADIENT. Raises
|
|
306
|
+
|ValueError| for a non-linear gradient (e.g. a radial gradient).
|
|
307
|
+
"""
|
|
308
|
+
# ---case 1: gradient path is explicit, but not linear---
|
|
309
|
+
path = self._gradFill.path
|
|
310
|
+
if path is not None:
|
|
311
|
+
raise ValueError("not a linear gradient")
|
|
312
|
+
|
|
313
|
+
# ---case 2: gradient path is inherited (no a:lin OR a:path)---
|
|
314
|
+
lin = self._gradFill.lin
|
|
315
|
+
if lin is None:
|
|
316
|
+
return None
|
|
317
|
+
|
|
318
|
+
# ---case 3: gradient path is explicitly linear---
|
|
319
|
+
# angle is stored in XML as a clockwise angle, whereas the UI
|
|
320
|
+
# reports it as counter-clockwise from horizontal-pointing-right.
|
|
321
|
+
# Since the UI is consistent with trigonometry conventions, we
|
|
322
|
+
# respect that in the API.
|
|
323
|
+
clockwise_angle = lin.ang
|
|
324
|
+
counter_clockwise_angle = 0.0 if clockwise_angle == 0.0 else (360.0 - clockwise_angle)
|
|
325
|
+
return counter_clockwise_angle
|
|
326
|
+
|
|
327
|
+
@gradient_angle.setter
|
|
328
|
+
def gradient_angle(self, value):
|
|
329
|
+
lin = self._gradFill.lin
|
|
330
|
+
if lin is None:
|
|
331
|
+
raise ValueError("not a linear gradient")
|
|
332
|
+
lin.ang = 360.0 - value
|
|
333
|
+
|
|
334
|
+
@lazyproperty
|
|
335
|
+
def gradient_stops(self):
|
|
336
|
+
"""|_GradientStops| object providing access to gradient colors.
|
|
337
|
+
|
|
338
|
+
Each stop represents a color between which the gradient smoothly
|
|
339
|
+
transitions.
|
|
340
|
+
"""
|
|
341
|
+
return _GradientStops(self._gradFill.get_or_add_gsLst())
|
|
342
|
+
|
|
343
|
+
@property
|
|
344
|
+
def type(self):
|
|
345
|
+
return MSO_FILL.GRADIENT
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
class _GrpFill(_Fill):
|
|
349
|
+
@property
|
|
350
|
+
def type(self):
|
|
351
|
+
return MSO_FILL.GROUP
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
class _NoFill(_Fill):
|
|
355
|
+
@property
|
|
356
|
+
def type(self):
|
|
357
|
+
return MSO_FILL.BACKGROUND
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class _NoneFill(_Fill):
|
|
361
|
+
@property
|
|
362
|
+
def type(self):
|
|
363
|
+
return None
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
class _PattFill(_Fill):
|
|
367
|
+
"""Provides access to patterned fill properties."""
|
|
368
|
+
|
|
369
|
+
def __init__(self, pattFill):
|
|
370
|
+
super(_PattFill, self).__init__()
|
|
371
|
+
self._element = self._pattFill = pattFill
|
|
372
|
+
|
|
373
|
+
@lazyproperty
|
|
374
|
+
def back_color(self):
|
|
375
|
+
"""Return |ColorFormat| object that controls background color."""
|
|
376
|
+
bgClr = self._pattFill.get_or_add_bgClr()
|
|
377
|
+
return ColorFormat.from_colorchoice_parent(bgClr)
|
|
378
|
+
|
|
379
|
+
@lazyproperty
|
|
380
|
+
def fore_color(self):
|
|
381
|
+
"""Return |ColorFormat| object that controls foreground color."""
|
|
382
|
+
fgClr = self._pattFill.get_or_add_fgClr()
|
|
383
|
+
return ColorFormat.from_colorchoice_parent(fgClr)
|
|
384
|
+
|
|
385
|
+
@property
|
|
386
|
+
def pattern(self):
|
|
387
|
+
"""Return member of :ref:`MsoPatternType` indicating fill pattern.
|
|
388
|
+
|
|
389
|
+
Returns |None| if no pattern has been set; PowerPoint may display the
|
|
390
|
+
default `PERCENT_5` pattern in this case. Assigning |None| will
|
|
391
|
+
remove any explicit pattern setting.
|
|
392
|
+
"""
|
|
393
|
+
return self._pattFill.prst
|
|
394
|
+
|
|
395
|
+
@pattern.setter
|
|
396
|
+
def pattern(self, pattern_type):
|
|
397
|
+
self._pattFill.prst = pattern_type
|
|
398
|
+
|
|
399
|
+
@property
|
|
400
|
+
def type(self):
|
|
401
|
+
return MSO_FILL.PATTERNED
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
class _SolidFill(_Fill):
|
|
405
|
+
"""Provides access to fill properties such as color for solid fills."""
|
|
406
|
+
|
|
407
|
+
def __init__(self, solidFill):
|
|
408
|
+
super(_SolidFill, self).__init__()
|
|
409
|
+
self._solidFill = solidFill
|
|
410
|
+
|
|
411
|
+
@lazyproperty
|
|
412
|
+
def fore_color(self):
|
|
413
|
+
"""Return |ColorFormat| object controlling fill color."""
|
|
414
|
+
return ColorFormat.from_colorchoice_parent(self._solidFill)
|
|
415
|
+
|
|
416
|
+
@property
|
|
417
|
+
def type(self):
|
|
418
|
+
return MSO_FILL.SOLID
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class _GradientStops(Sequence):
|
|
422
|
+
"""Collection of |GradientStop| objects defining gradient colors.
|
|
423
|
+
|
|
424
|
+
A gradient must have a minimum of two stops, but can have as many more
|
|
425
|
+
than that as required to achieve the desired effect (three is perhaps
|
|
426
|
+
most common). Stops are sequenced in the order they are transitioned
|
|
427
|
+
through.
|
|
428
|
+
"""
|
|
429
|
+
|
|
430
|
+
def __init__(self, gsLst):
|
|
431
|
+
self._gsLst = gsLst
|
|
432
|
+
|
|
433
|
+
def __getitem__(self, idx):
|
|
434
|
+
return _GradientStop(self._gsLst[idx])
|
|
435
|
+
|
|
436
|
+
def __len__(self):
|
|
437
|
+
return len(self._gsLst)
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
class _GradientStop(ElementProxy):
|
|
441
|
+
"""A single gradient stop.
|
|
442
|
+
|
|
443
|
+
A gradient stop defines a color and a position.
|
|
444
|
+
"""
|
|
445
|
+
|
|
446
|
+
def __init__(self, gs):
|
|
447
|
+
super(_GradientStop, self).__init__(gs)
|
|
448
|
+
self._gs = gs
|
|
449
|
+
|
|
450
|
+
@lazyproperty
|
|
451
|
+
def color(self):
|
|
452
|
+
"""Return |ColorFormat| object controlling stop color."""
|
|
453
|
+
return ColorFormat.from_colorchoice_parent(self._gs)
|
|
454
|
+
|
|
455
|
+
@property
|
|
456
|
+
def position(self):
|
|
457
|
+
"""Location of stop in gradient path as float between 0.0 and 1.0.
|
|
458
|
+
|
|
459
|
+
The value represents a percentage, where 0.0 (0%) represents the
|
|
460
|
+
start of the path and 1.0 (100%) represents the end of the path. For
|
|
461
|
+
a linear gradient, these would represent opposing extents of the
|
|
462
|
+
filled area.
|
|
463
|
+
"""
|
|
464
|
+
return self._gs.pos
|
|
465
|
+
|
|
466
|
+
@position.setter
|
|
467
|
+
def position(self, value):
|
|
468
|
+
self._gs.pos = float(value)
|
pptx/dml/line.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""DrawingML objects related to line formatting."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pptx.dml.fill import FillFormat
|
|
6
|
+
from pptx.enum.dml import MSO_FILL
|
|
7
|
+
from pptx.util import Emu, lazyproperty
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LineFormat(object):
|
|
11
|
+
"""Provides access to line properties such as color, style, and width.
|
|
12
|
+
|
|
13
|
+
A LineFormat object is typically accessed via the ``.line`` property of
|
|
14
|
+
a shape such as |Shape| or |Picture|.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, parent):
|
|
18
|
+
super(LineFormat, self).__init__()
|
|
19
|
+
self._parent = parent
|
|
20
|
+
|
|
21
|
+
@lazyproperty
|
|
22
|
+
def color(self):
|
|
23
|
+
"""
|
|
24
|
+
The |ColorFormat| instance that provides access to the color settings
|
|
25
|
+
for this line. Essentially a shortcut for ``line.fill.fore_color``.
|
|
26
|
+
As a side-effect, accessing this property causes the line fill type
|
|
27
|
+
to be set to ``MSO_FILL.SOLID``. If this sounds risky for your use
|
|
28
|
+
case, use ``line.fill.type`` to non-destructively discover the
|
|
29
|
+
existing fill type.
|
|
30
|
+
"""
|
|
31
|
+
if self.fill.type != MSO_FILL.SOLID:
|
|
32
|
+
self.fill.solid()
|
|
33
|
+
return self.fill.fore_color
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def dash_style(self):
|
|
37
|
+
"""Return value indicating line style.
|
|
38
|
+
|
|
39
|
+
Returns a member of :ref:`MsoLineDashStyle` indicating line style, or
|
|
40
|
+
|None| if no explicit value has been set. When no explicit value has
|
|
41
|
+
been set, the line dash style is inherited from the style hierarchy.
|
|
42
|
+
|
|
43
|
+
Assigning |None| removes any existing explicitly-defined dash style.
|
|
44
|
+
"""
|
|
45
|
+
ln = self._ln
|
|
46
|
+
if ln is None:
|
|
47
|
+
return None
|
|
48
|
+
return ln.prstDash_val
|
|
49
|
+
|
|
50
|
+
@dash_style.setter
|
|
51
|
+
def dash_style(self, dash_style):
|
|
52
|
+
if dash_style is None:
|
|
53
|
+
ln = self._ln
|
|
54
|
+
if ln is None:
|
|
55
|
+
return
|
|
56
|
+
ln._remove_prstDash()
|
|
57
|
+
ln._remove_custDash()
|
|
58
|
+
return
|
|
59
|
+
ln = self._get_or_add_ln()
|
|
60
|
+
ln.prstDash_val = dash_style
|
|
61
|
+
|
|
62
|
+
@lazyproperty
|
|
63
|
+
def fill(self):
|
|
64
|
+
"""
|
|
65
|
+
|FillFormat| instance for this line, providing access to fill
|
|
66
|
+
properties such as foreground color.
|
|
67
|
+
"""
|
|
68
|
+
ln = self._get_or_add_ln()
|
|
69
|
+
return FillFormat.from_fill_parent(ln)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def width(self):
|
|
73
|
+
"""
|
|
74
|
+
The width of the line expressed as an integer number of :ref:`English
|
|
75
|
+
Metric Units <EMU>`. The returned value is an instance of |Length|,
|
|
76
|
+
a value class having properties such as `.inches`, `.cm`, and `.pt`
|
|
77
|
+
for converting the value into convenient units.
|
|
78
|
+
"""
|
|
79
|
+
ln = self._ln
|
|
80
|
+
if ln is None:
|
|
81
|
+
return Emu(0)
|
|
82
|
+
return ln.w
|
|
83
|
+
|
|
84
|
+
@width.setter
|
|
85
|
+
def width(self, emu):
|
|
86
|
+
if emu is None:
|
|
87
|
+
emu = 0
|
|
88
|
+
ln = self._get_or_add_ln()
|
|
89
|
+
ln.w = emu
|
|
90
|
+
|
|
91
|
+
def _get_or_add_ln(self):
|
|
92
|
+
"""
|
|
93
|
+
Return the ``<a:ln>`` element containing the line format properties
|
|
94
|
+
in the XML.
|
|
95
|
+
"""
|
|
96
|
+
return self._parent.get_or_add_ln()
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def _ln(self):
|
|
100
|
+
return self._parent.ln
|
pptx/enum/__init__.py
ADDED
|
File without changes
|
pptx/enum/action.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Enumerations that describe click-action settings."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pptx.enum.base import BaseEnum
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PP_ACTION_TYPE(BaseEnum):
|
|
9
|
+
"""
|
|
10
|
+
Specifies the type of a mouse action (click or hover action).
|
|
11
|
+
|
|
12
|
+
Alias: ``PP_ACTION``
|
|
13
|
+
|
|
14
|
+
Example::
|
|
15
|
+
|
|
16
|
+
from pptx.enum.action import PP_ACTION
|
|
17
|
+
|
|
18
|
+
assert shape.click_action.action == PP_ACTION.HYPERLINK
|
|
19
|
+
|
|
20
|
+
MS API name: `PpActionType`
|
|
21
|
+
|
|
22
|
+
https://msdn.microsoft.com/EN-US/library/office/ff744895.aspx
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
END_SHOW = (6, "Slide show ends.")
|
|
26
|
+
"""Slide show ends."""
|
|
27
|
+
|
|
28
|
+
FIRST_SLIDE = (3, "Returns to the first slide.")
|
|
29
|
+
"""Returns to the first slide."""
|
|
30
|
+
|
|
31
|
+
HYPERLINK = (7, "Hyperlink.")
|
|
32
|
+
"""Hyperlink."""
|
|
33
|
+
|
|
34
|
+
LAST_SLIDE = (4, "Moves to the last slide.")
|
|
35
|
+
"""Moves to the last slide."""
|
|
36
|
+
|
|
37
|
+
LAST_SLIDE_VIEWED = (5, "Moves to the last slide viewed.")
|
|
38
|
+
"""Moves to the last slide viewed."""
|
|
39
|
+
|
|
40
|
+
NAMED_SLIDE = (101, "Moves to slide specified by slide number.")
|
|
41
|
+
"""Moves to slide specified by slide number."""
|
|
42
|
+
|
|
43
|
+
NAMED_SLIDE_SHOW = (10, "Runs the slideshow.")
|
|
44
|
+
"""Runs the slideshow."""
|
|
45
|
+
|
|
46
|
+
NEXT_SLIDE = (1, "Moves to the next slide.")
|
|
47
|
+
"""Moves to the next slide."""
|
|
48
|
+
|
|
49
|
+
NONE = (0, "No action is performed.")
|
|
50
|
+
"""No action is performed."""
|
|
51
|
+
|
|
52
|
+
OPEN_FILE = (102, "Opens the specified file.")
|
|
53
|
+
"""Opens the specified file."""
|
|
54
|
+
|
|
55
|
+
OLE_VERB = (11, "OLE Verb.")
|
|
56
|
+
"""OLE Verb."""
|
|
57
|
+
|
|
58
|
+
PLAY = (12, "Begins the slideshow.")
|
|
59
|
+
"""Begins the slideshow."""
|
|
60
|
+
|
|
61
|
+
PREVIOUS_SLIDE = (2, "Moves to the previous slide.")
|
|
62
|
+
"""Moves to the previous slide."""
|
|
63
|
+
|
|
64
|
+
RUN_MACRO = (8, "Runs a macro.")
|
|
65
|
+
"""Runs a macro."""
|
|
66
|
+
|
|
67
|
+
RUN_PROGRAM = (9, "Runs a program.")
|
|
68
|
+
"""Runs a program."""
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
PP_ACTION = PP_ACTION_TYPE
|